17#include "MantidIndexing/Extract.h"
18#include "MantidIndexing/IndexInfo.h"
26#include <boost/algorithm/string.hpp>
27#include <boost/format.hpp>
39 :
Algorithm(), m_FilterWithDerivative(true),
41 m_min_Eresolution(0.08),
43 m_max_Eresolution(0.5e-3), m_peakEnergyRatio2reject(0.1), m_phase(0), m_chopper(), m_pFilterLog(
nullptr) {}
50 "The input workspace containing the monitor's spectra "
51 "measured after the last chopper");
52 auto nonNegative = std::make_shared<Kernel::BoundedValidator<int>>();
53 nonNegative->setLower(0);
56 "The workspace index (ID) of the spectra, containing first monitor's"
57 " signal to analyze.");
59 "The workspace index (ID) of the spectra, containing second monitor's"
60 " signal to analyze.");
63 "Name of the instrument log, "
64 "containing chopper angular velocity. If 'Defined in IDF' "
65 "option is specified, "
66 "the log name is obtained from the IDF");
68 "Name of the instrument log, "
69 "containing chopper delay time or chopper phase v.r.t. the pulse time. "
70 "If 'Defined in IDF' option is specified, "
71 "the log name is obtained from IDF");
73 "Name of the instrument log, "
74 "with positive values indicating that instrument is running\n "
75 "and 0 or negative that it is not.\n"
76 "The log is used to identify time interval to evaluate"
77 " chopper speed and chopper delay which matter.\n"
78 "If such log is not present, average log values are calculated "
79 "within experiment start&end time range.");
81 "Use derivative of 'FilterBaseLog' "
82 "rather then log values itself to filter invalid time intervals.\n"
83 "Invalid values are then the "
84 "values where the derivative of the log turns zero.\n"
85 "E.g. the 'proton_chage' log grows for each frame "
86 "when instrument is counting and is constant otherwise.");
88 std::make_unique<Kernel::EnabledWhenProperty>(
91 auto maxInRange = std::make_shared<Kernel::BoundedValidator<double>>();
92 maxInRange->setLower(1.e-6);
93 maxInRange->setUpper(0.1);
96 "The maximal energy resolution possible for an "
97 "instrument at working energies (full width at half "
98 "maximum). \nPeaks, sharper then "
99 "this width are rejected. Accepted limits are: 1e^(-6)-0.1");
101 auto minInRange = std::make_shared<Kernel::BoundedValidator<double>>();
102 minInRange->setLower(0.001);
103 minInRange->setUpper(0.5);
105 "The minimal energy resolution possible for an "
106 "instrument at working energies (full width at half maximum).\n"
107 "Peaks broader then this width are rejected. Accepted limits are: "
110 auto peakInRange = std::make_shared<Kernel::BoundedValidator<double>>();
111 peakInRange->setLower(0.0);
112 minInRange->setUpper(1.);
114 "Ratio of a peak energy to the maximal energy among all peaks. "
115 "If the ratio is lower then the value specified here, "
116 "peak is treated as insignificant and rejected.\n"
117 "Accepted limits are:0.0 (All accepted) to 1 -- only one peak \n"
118 "(or peaks with max and equal intensity) are accepted.");
120 "Usually peaks are analyzed and accepted "
121 "only if identified on both monitors. If this property is set to true, "
122 "only first monitor peaks are analyzed.\n"
123 "This is debugging option as getEi has to use both monitors.");
127 "Name of the output matrix workspace, containing single spectra with"
128 " monitor peaks energies\n"
129 "together with total intensity within each peak.");
141template <
class T>
void removeInvalidValues(
const std::vector<bool> &guessValid, std::vector<T> &guess) {
142 std::vector<T> new_guess;
143 new_guess.reserve(guess.size());
145 for (
size_t i = 0; i < guessValid.size(); i++) {
147 new_guess.emplace_back(guess[i]);
150 new_guess.swap(guess);
159 peakKeeper(
double pos,
double heigh,
double sig) :
position(pos),
height(heigh),
sigma(sig) {
160 this->energy = std::sqrt(2 * M_PI) *
height *
sigma;
163 bool operator<(
const peakKeeper &str)
const {
return (energy > str.energy); }
177 auto pInstrument = inputWS->getInstrument();
182 m_chopper = pInstrument->getComponentByName(
"chopper-position");
184 throw std::runtime_error(
"Instrument " + pInstrument->getName() +
" does not have 'chopper-position' component");
186 auto phase =
m_chopper->getNumberParameter(
"initial_phase");
189 throw std::runtime_error(
"Can not find initial_phase parameter"
190 " attached to the chopper-position component");
192 if (phase.size() > 1) {
193 throw std::runtime_error(
"Can not deal with multiple phases for initial_phase"
194 " parameter attached to the chopper-position component");
202 double chopSpeed, chopDelay;
204 g_log.
debug() << boost::str(boost::format(
"*Identified avrg ChopSpeed: %8.2f and Delay: %8.2f\n") % chopSpeed %
207 auto moderator = pInstrument->getSource();
208 double chopDistance =
m_chopper->getDistance(*moderator);
209 double velocity = chopDistance / chopDelay;
216 const auto &detector1 = inputWS->spectrumInfo().detector(det1WSIndex);
217 double mon1Distance = detector1.getDistance(*moderator);
218 double TOF0 = mon1Distance / velocity;
230 auto &baseSpectrum = inputWS->getSpectrum(det1WSIndex);
231 std::pair<double, double> TOF_range = baseSpectrum.getXDataRange();
233 double Period = (0.5 * 1.e+6) / chopSpeed;
236 auto destUnit = Kernel::UnitFactory::Instance().create(
"Energy");
238 std::vector<double> guess_opening;
241 if (guess_opening.empty()) {
242 throw std::runtime_error(
243 "Can not find any chopper opening time within TOF range: " + boost::lexical_cast<std::string>(TOF_range.first) +
244 ':' + boost::lexical_cast<std::string>(TOF_range.second));
249 std::pair<double, double> Mon1_Erange = monitorWS->getSpectrum(0).getXDataRange();
250 std::pair<double, double> Mon2_Erange = monitorWS->getSpectrum(1).getXDataRange();
251 double eMin = std::max(Mon1_Erange.first, Mon2_Erange.first);
252 double eMax = std::min(Mon1_Erange.second, Mon2_Erange.second);
253 g_log.
debug() << boost::str(boost::format(
"Monitors record data in energy range Emin=%8.2f; Emax=%8.2f\n") % eMin %
257 std::vector<double> guess_ei;
258 guess_ei.reserve(guess_opening.size());
260 for (
double time : guess_opening) {
261 double eGuess = destUnit->singleFromTOF(time);
262 if (eGuess > eMin && eGuess < eMax) {
263 guess_ei.emplace_back(eGuess);
267 " fell within both monitor's recording energy range\n";
269 for (
double ei : guess_ei) {
270 g_log.
debug() << boost::str(boost::format(
" %8.2f; ") % ei);
274 std::sort(guess_ei.begin(), guess_ei.end());
276 std::vector<size_t> irange_min, irange_max;
277 std::vector<bool> guessValid;
279 g_log.
debug() <<
"*Looking for real energy peaks on first monitor\n";
280 findBinRanges(monitorWS->x(0), monitorWS->y(0), guess_ei, this->m_min_Eresolution / (2. * std::sqrt(2. * M_LN2)),
281 irange_min, irange_max, guessValid);
284 removeInvalidValues<double>(guessValid, guess_ei);
287 std::vector<size_t> irange1_min, irange1_max;
289 g_log.
debug() <<
"*Looking for real energy peaks on second monitor\n";
290 findBinRanges(monitorWS->x(1), monitorWS->y(1), guess_ei, this->m_min_Eresolution / (2. * std::sqrt(2. * M_LN2)),
291 irange1_min, irange1_max, guessValid);
292 removeInvalidValues<double>(guessValid, guess_ei);
293 removeInvalidValues<size_t>(guessValid, irange_min);
294 removeInvalidValues<size_t>(guessValid, irange_max);
298 irange1_min.assign(irange_min.begin(), irange_min.end());
299 irange1_max.assign(irange_max.begin(), irange_max.end());
302 " peaks with sufficient signal around guess chopper opening\n";
304 std::vector<peakKeeper> peaks;
306 double maxPeakEnergy(0);
307 std::vector<size_t> monsRangeMin(2), monsRangeMax(2);
308 for (
size_t i = 0; i < guess_ei.size(); i++) {
309 monsRangeMin[0] = irange_min[i];
310 monsRangeMax[0] = irange_max[i];
311 monsRangeMin[1] = irange1_min[i];
312 monsRangeMax[1] = irange1_max[i];
318 if (peaks.back().energy > maxPeakEnergy)
319 maxPeakEnergy = peaks.back().energy;
324 size_t nPeaks = peaks.size();
326 throw std::runtime_error(
"Can not identify any energy peaks");
329 guessValid.resize(nPeaks);
330 bool needsRemoval(
false);
331 for (
size_t i = 0; i < nPeaks; i++) {
332 peaks[i].energy /= maxPeakEnergy;
334 guessValid[i] =
false;
335 g_log.
debug() <<
"*Rejecting peak at Ei=" + boost::lexical_cast<std::string>(peaks[i].
position) +
336 " as its total energy lower then the threshold\n";
339 guessValid[i] =
true;
343 removeInvalidValues<peakKeeper>(guessValid, peaks);
344 nPeaks = peaks.size();
346 std::sort(peaks.begin(), peaks.end());
349 auto result_ws = create<Workspace2D>(1, Points(nPeaks));
351 HistogramX peaks_positions(peaks.size());
352 std::transform(peaks.cbegin(), peaks.cend(), peaks_positions.begin(),
353 [](
const peakKeeper &peak) { return peak.position; });
354 auto &Signal = result_ws->mutableY(0);
355 std::transform(peaks.cbegin(), peaks.cend(), Signal.begin(), [](
const peakKeeper &peak) { return peak.height; });
357 auto &Error = result_ws->mutableE(0);
358 std::transform(peaks.cbegin(), peaks.cend(), Error.begin(), [](
const peakKeeper &peak) { return peak.sigma; });
360 result_ws->setPoints(0, peaks_positions);
362 setProperty(
"OutputWorkspace", std::move(result_ws));
374 std::shared_ptr<Kernel::Unit> &destUnit) {
376 g_log.
debug() <<
"*Found : " << guess_opening.size()
377 <<
" chopper prospective opening within time frame: " << TOF_range.first <<
" to: " << TOF_range.second
380 for (
double time : guess_opening) {
381 g_log.
debug() << boost::str(boost::format(
" %8.2f; ") % time);
384 g_log.
debug() <<
" Corresponding to energies:\n";
385 for (
double time : guess_opening) {
386 double ei = destUnit->singleFromTOF(time);
387 g_log.
debug() << boost::str(boost::format(
" %8.2f; ") % ei);
402 std::string filerLogName;
403 std::string filterBase =
getProperty(
"FilterBaseLog");
404 if (boost::iequals(filterBase,
"Defined in IDF")) {
405 filerLogName =
m_chopper->getStringParameter(
"FilterBaseLog")[0];
408 filerLogName = filterBase;
413 }
catch (std::runtime_error &) {
414 g_log.
warning() <<
" Can not retrieve (double) filtering log: " + filerLogName +
415 " from current workspace\n"
416 " Using total experiment range to "
417 "find logs averages for chopper parameters\n";
437 const std::vector<size_t> &monsRangeMin,
const std::vector<size_t> &monsRangeMax,
438 double &peakPos,
double &peakHeight,
double &peakTwoSigma) {
443 double sMin(std::numeric_limits<double>::max());
445 double xOfMax(0), dXmax(0);
448 const auto &
X = inputWS->x(
index);
449 const auto &S = inputWS->y(
index);
450 size_t ind_min = monsRangeMin[
index];
451 size_t ind_max = monsRangeMax[
index];
453 if (std::fabs(
double(ind_max - ind_min)) < 5)
460 for (
size_t i = ind_min; i < ind_max; i++) {
461 double dX =
X[i + 1] -
X[i];
462 double signal = S[i] / dX;
474 if (sMax * dXmax <= 2)
479 double SmoothRange = 2 * maxSigma;
481 std::vector<double> SAvrg, binsAvrg;
484 double realPeakPos(xOfMax);
486 bool foundRealPeakPos(
false);
487 std::vector<double> der1Avrg, der2Avrg, peaks, hillsPos, SAvrg1, binsAvrg1;
491 foundRealPeakPos =
true;
492 realPeakPos = peaks[0];
495 size_t ic(0), stay_still_count(0);
496 bool iterations_fail(
false);
497 while ((nPeaks > 1 || nHills > 2) && (!iterations_fail)) {
499 const auto nPrevHills = nHills;
504 binsAvrg.swap(binsAvrg1);
505 if (nPeaks == 1 && !foundRealPeakPos) {
506 foundRealPeakPos =
true;
507 realPeakPos = peaks[0];
510 if (nPrevHills <= nHills) {
513 stay_still_count = 0;
515 if (ic > 50 || stay_still_count > 3)
516 iterations_fail =
true;
518 if (iterations_fail) {
520 " smoothing iterations at still_count: " +
std::to_string(stay_still_count) +
521 " Wrong energy or noisy peak at Ei=" + boost::lexical_cast<std::string>(Ei)
525 " at energy: " + boost::lexical_cast<std::string>(Ei) +
528 g_log.
debug() <<
"*Peak rejected as n-peaks !=1 after averaging\n";
535 peakTwoSigma = hillsPos[peakIndex + 1] - hillsPos[peakIndex];
537 if (hillsPos.size() == 2) {
538 peakTwoSigma = hillsPos[1] - hillsPos[0];
548 peakHeight = Intensity / (0.5 * std::sqrt(2. * M_PI) * peakTwoSigma) - sMin;
549 peakPos = realPeakPos;
567 const std::vector<size_t> &monsRangeMin,
const std::vector<size_t> &monsRangeMax,
573 double peak1Pos, peak1TwoSigma, peak1Height;
574 if (!
peakGuess(inputWS, 0, Ei, monsRangeMin, monsRangeMax, peak1Pos, peak1Height, peak1TwoSigma))
576 if (0.25 * peak1TwoSigma > maxSigma || peak1TwoSigma < minSigma) {
577 g_log.
debug() <<
"*Rejecting due to width: Peak at mon1 Ei=" + boost::lexical_cast<std::string>(peak1Pos) +
578 " with Height:" + boost::lexical_cast<std::string>(peak1Height) +
579 " and 2*Sigma: " + boost::lexical_cast<std::string>(peak1TwoSigma)
585 double peak2Pos, peak2TwoSigma, peak2Height;
586 if (!
peakGuess(inputWS, 1, Ei, monsRangeMin, monsRangeMax, peak2Pos, peak2Height, peak2TwoSigma))
595 if (std::fabs(peak1Pos - peak2Pos) > 0.25 * (peak1TwoSigma + peak2TwoSigma)) {
596 g_log.
debug() <<
"*Rejecting due to displacement between Peak at mon1: Ei=" +
597 boost::lexical_cast<std::string>(peak1Pos) +
598 " with Height:" + boost::lexical_cast<std::string>(peak1Height) +
599 " and 2*Sigma: " + boost::lexical_cast<std::string>(peak1TwoSigma) +
600 "\n and Peak at mon2: Ei= " + boost::lexical_cast<std::string>(peak2Pos) +
601 "and height: " + boost::lexical_cast<std::string>(peak1Height)
609 twoSigma = peak1TwoSigma;
620bool signChanged(
double val,
int &prevSign) {
621 int curSign = (val >= 0 ? 1 : -1);
622 bool changed = curSign != prevSign;
641 std::vector<double> &deriv, std::vector<double> &zeros) {
642 size_t nPoints = signal.size();
643 deriv.resize(nPoints);
646 std::list<double> funVal;
647 double bin0 = bins[1] - bins[0];
648 double f0 = signal[0] / bin0;
649 double bin1 = bins[2] - bins[1];
650 double f1 = signal[1] / bin1;
654 funVal.push_front(f1);
655 deriv[0] = 2 * (f1 - f0) / (bin0 + bin1);
656 int prevSign = (deriv[0] >= 0 ? 1 : -1);
658 for (
size_t i = 1; i < nPoints - 1; i++) {
659 bin1 = (bins[i + 2] - bins[i + 1]);
660 f1 = signal[i + 1] / bin1;
661 deriv[i] = (f1 - f0) / (bins[i + 2] - bins[i]);
664 funVal.push_front(f1);
666 if (signChanged(deriv[i], prevSign)) {
668 zeros.emplace_back(0.5 * (bins[i - 1] + bins[i]));
671 deriv[nPoints - 1] = 2 * (f1 - f0) / (bin1 + bin0);
672 if (signChanged(deriv[nPoints - 1], prevSign)) {
673 zeros.emplace_back(bins[nPoints - 1]);
681void getBinRange(
const HistogramData::HistogramX &eBins,
double eMin,
double eMax,
size_t &index_min,
684 const auto &bins = eBins.rawData();
685 const size_t nBins = bins.size();
686 if (eMin <= bins[0]) {
692 if (eMax >= eBins[nBins - 1]) {
693 index_max = nBins - 1;
696 if (index_max >= nBins)
697 index_max = nBins - 1;
702bool refineEGuess(
const HistogramX &eBins,
const HistogramY &signal,
double &eGuess,
size_t index_min,
705 size_t ind_Emax = index_min;
707 for (
size_t i = index_min; i < index_max; i++) {
708 double dX = eBins[i + 1] - eBins[i];
709 double sig = signal[i] /
dX;
715 if (ind_Emax == index_min || ind_Emax == index_max) {
718 eGuess = 0.5 * (eBins[ind_Emax] + eBins[ind_Emax + 1]);
743 double eResolution, std::vector<size_t> &irangeMin, std::vector<size_t> &irangeMax,
744 std::vector<bool> &guessValid) {
747 guessValid.resize(guess_energy.size());
750 size_t ind_min, ind_max;
755 std::vector<peakKeeper2> guess_peak(guess_energy.size());
756 for (
size_t nGuess = 0; nGuess < guess_energy.size(); nGuess++) {
757 double eGuess = guess_energy[nGuess];
758 getBinRange(eBins, eGuess * (1 - 4 * eResolution), eGuess * (1 + 4 * eResolution), ind_min, ind_max);
759 guess_peak[nGuess] = peakKeeper2(eBins[ind_min], eBins[ind_max]);
762 for (
size_t i = 1; i < guess_energy.size(); i++) {
764 double mid_pnt = 0.5 * (guess_peak[i - 1].right_rng + guess_peak[i].left_rng);
765 guess_peak[i - 1].right_rng = mid_pnt;
766 guess_peak[i].left_rng = mid_pnt;
770 for (
size_t nGuess = 0; nGuess < guess_energy.size(); nGuess++) {
772 double eGuess = guess_energy[nGuess];
773 getBinRange(eBins, guess_peak[nGuess].
left_rng, guess_peak[nGuess].
right_rng, ind_min, ind_max);
775 if (refineEGuess(eBins, signal, eGuess, ind_min, ind_max)) {
776 getBinRange(eBins, std::max(guess_peak[nGuess].
left_rng, eGuess * (1 - 3 * eResolution)),
777 std::max(guess_peak[nGuess].
right_rng, eGuess * (1 + 3 * eResolution)), ind_min, ind_max);
778 irangeMin.emplace_back(ind_min);
779 irangeMax.emplace_back(ind_max);
780 guessValid[nGuess] =
true;
782 guessValid[nGuess] =
false;
783 g_log.
debug() <<
"*Incorrect guess energy: " << boost::lexical_cast<std::string>(eGuess)
784 <<
" no energy peak found in 4*Sigma range\n";
789 if (!irangeMax.empty()) {
790 if (irangeMax[0] < irangeMin[0]) {
791 irangeMax.swap(irangeMin);
809 wsIndex0 = inputWS->getIndexFromSpectrumNumber(specNum1);
811 size_t wsIndex1 = inputWS->getIndexFromSpectrumNumber(specNum2);
814 std::shared_ptr<API::HistoWorkspace> working_ws = DataObjects::create<API::HistoWorkspace>(
815 *inputWS, Indexing::extract(inputWS->indexInfo(), std::vector<size_t>{wsIndex0, wsIndex1}),
816 inputWS->histogram(wsIndex0));
819 working_ws->setSharedY(0, inputWS->sharedY(wsIndex0));
821 working_ws->setSharedY(1, inputWS->sharedY(wsIndex1));
823 working_ws->setSharedE(0, inputWS->sharedE(wsIndex0));
825 working_ws->setSharedE(1, inputWS->sharedE(wsIndex1));
827 if (inputWS->getAxis(0)->unit()->caption() !=
"Energy") {
830 conv->setProperty(
"InputWorkspace", working_ws);
831 conv->setProperty(
"OutputWorkspace", working_ws);
832 conv->setPropertyValue(
"Target",
"Energy");
833 conv->setPropertyValue(
"EMode",
"Elastic");
852 std::vector<double> &guess_opening_times) {
854 if (ChopDelay >= TOF_range.second) {
855 std::string chop = boost::str(boost::format(
"%.2g") % ChopDelay);
856 std::string t_min = boost::str(boost::format(
"%.2g") % TOF_range.first);
857 std::string t_max = boost::str(boost::format(
"%.2g") % TOF_range.second);
858 throw std::runtime_error(
"Logical error: Chopper opening time: " + chop +
" is outside of time interval: " + t_min +
859 ":" + t_max +
" of the signal, measured on monitors.");
863 size_t n_openings =
static_cast<size_t>((TOF_range.second - ChopDelay) / Period) + 1;
866 if (ChopDelay < TOF_range.first) {
867 n_start =
static_cast<size_t>((TOF_range.first - ChopDelay) / Period) + 1;
868 n_openings -= n_start;
871 guess_opening_times.resize(n_openings);
872 for (
size_t i = n_start; i < n_openings + n_start; i++) {
873 guess_opening_times[i - n_start] = ChopDelay +
static_cast<double>(i) * Period;
884 const std::string &propertyName) {
886 std::string LogName = this->
getProperty(propertyName);
887 if (boost::iequals(LogName,
"Defined in IDF")) {
888 auto AllNames =
m_chopper->getStringParameter(propertyName);
889 if (AllNames.size() != 1)
891 LogName = AllNames[0];
893 auto pIProperty = (inputWS->run().getProperty(LogName));
915 throw std::runtime_error(
"Could not retrieve a time series property for the property name " + propertyName);
920 const auto timeStart = inputWS->run().startTime();
921 const auto timeStop = inputWS->run().endTime();
922 if (timeStart < timeStop) {
924 value = pTimeSeries->getStatistics(&localROI).mean;
927 value = pTimeSeries->getStatistics().mean;
930 value = pTimeSeries->getStatistics(&timeroi).mean;
933 if (std::isnan(
value)) {
934 throw std::runtime_error(
"Can not find average value for log defined by property" + propertyName +
935 " As no valid log values are found.");
956bool SelectInterval(
const Types::Core::DateAndTime &t_beg,
const Types::Core::DateAndTime &t_end,
double value,
957 bool &inSelection, Types::Core::DateAndTime &startTime, Types::Core::DateAndTime &endTime) {
967 if (endTime > startTime)
986 std::unique_ptr<Kernel::TimeSeriesProperty<double>> pDerivative;
989 bool inSelection(
false);
991 Types::Core::DateAndTime startTime, endTime;
995 auto it = dateAndTimes.begin();
998 std::map<Types::Core::DateAndTime, double> derivMap;
1002 derivMap = pDerivative->valueAsCorrectMap();
1003 itder = derivMap.begin();
1007 if (dateAndTimes.size() <= 1) {
1008 SelectInterval(it->first, it->first, itder->second, inSelection, startTime, endTime);
1010 startTime = inputWS->run().startTime();
1011 endTime = inputWS->run().endTime();
1012 timeroi.
addROI(startTime, endTime);
1014 throw std::runtime_error(
"filtered all data points. Nothing to do");
1017 SelectInterval(it->first, next->first, itder->second, inSelection, startTime, endTime);
1023 for (; next != dateAndTimes.end(); ++next, ++itder) {
1024 if (SelectInterval(it->first, next->first, itder->second, inSelection, startTime, endTime)) {
1025 timeroi.
addROI(startTime, endTime);
1030 if (inSelection && (endTime > startTime)) {
1031 timeroi.
addROI(startTime, endTime);
1035 chop_speed = this->
getAvrgLogValue(inputWS,
"ChopperSpeedLog", timeroi);
1036 chop_speed = std::fabs(chop_speed);
1037 if (chop_speed < 1.e-7) {
1038 throw std::runtime_error(
"Chopper speed can not be zero ");
1040 chop_delay = std::fabs(this->
getAvrgLogValue(inputWS,
"ChopperDelayLog", timeroi));
1045 throw std::runtime_error(
"ChopperDelayLog has been removed from workspace "
1046 "during the algorithm execution");
1047 std::string units = pProperty->units();
1049 if (units ==
"deg" || units.c_str()[0] == -80) {
1050 chop_delay *= 1.e+6 / (360. * chop_speed);
1052 chop_delay +=
m_phase / chop_speed;
1074 const std::shared_ptr<const Geometry::IComponent> &chopper,
1075 const std::string &prop_name,
const std::string &err_presence,
1076 const std::string &err_type,
bool fail, std::map<std::string, std::string> &result) {
1078 std::string LogName = algo->
getProperty(prop_name);
1079 if (boost::iequals(LogName,
"Defined in IDF")) {
1081 auto theLogs = chopper->getStringParameter(prop_name);
1082 if (theLogs.empty()) {
1084 result[prop_name] =
"Can not retrieve parameter " + prop_name +
" from the instrument definition file.";
1087 LogName = theLogs[0];
1089 result[prop_name] =
"Can not retrieve parameter " + prop_name +
" from the instrument definition file.";
1098 result[prop_name] =
"Workspace contains " + err_type + LogName +
" But its type is not a timeSeries property";
1101 }
catch (std::runtime_error &) {
1103 result[prop_name] =
"Workspace has to contain " + err_presence + LogName;
1117 std::map<std::string, std::string> result;
1121 result[
"Workspace"] =
"Input workspace can not be identified";
1124 if (!inputWS->isHistogramData()) {
1125 result[
"Workspace"] =
"Only histogram workspaces are currently supported. "
1126 "Rebin input workspace first.";
1131 inputWS->getIndexFromSpectrumNumber(specNum1);
1132 }
catch (std::runtime_error &) {
1133 result[
"Monitor1SpecID"] =
"Input workspace does not contain spectra with ID: " +
std::to_string(specNum1);
1137 inputWS->getIndexFromSpectrumNumber(specNum2);
1138 }
catch (std::runtime_error &) {
1139 result[
"Monitor2SpecID"] =
"Input workspace does not contain spectra with ID: " +
std::to_string(specNum2);
1142 m_chopper = inputWS->getInstrument()->getComponentByName(
"chopper-position");
1144 result[
"Workspace_chopper"] =
" For this algorithm to work workspace has"
1145 " to contain well defined 'chopper-position' component";
1149 check_time_series_property(
this, inputWS,
m_chopper,
"ChopperSpeedLog",
1150 "chopper speed log with name: ",
"chopper speed log ",
true, result);
1151 check_time_series_property(
this, inputWS,
m_chopper,
"ChopperDelayLog",
1152 "property related to chopper delay log with name: ",
"chopper delay log ",
true, result);
1153 bool failed = check_time_series_property(
this, inputWS,
m_chopper,
"FilterBaseLog",
1154 "filter base log named: ",
"filter base log: ",
false, result);
1156 g_log.
warning() <<
" Can not find a log to identify good DAE operations.\n"
1157 " Assuming that good operations start from experiment time=0";
#define DECLARE_ALGORITHM(classname)
double value
The value of the point.
std::map< DeltaEMode::Type, std::string > index
Base class from which all concrete algorithm classes should be derived.
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
virtual std::shared_ptr< Algorithm > createChildAlgorithm(const std::string &name, const double startProgress=-1., const double endProgress=-1., const bool enableLogging=true, const int &version=-1)
Create a Child Algorithm.
A property class for workspaces.
Estimate all incident energies, used by chopper instrument.
Kernel::TimeSeriesProperty< double > * m_pFilterLog
void findGuessOpeningTimes(const std::pair< double, double > &TOF_range, double ChopDelay, double Period, std::vector< double > &guess_opening_times)
function calculates list of provisional chopper opening times.
bool findMonitorPeak(const API::MatrixWorkspace_sptr &inputWS, double Ei, const std::vector< size_t > &monsRangeMin, const std::vector< size_t > &monsRangeMax, double &position, double &height, double &twoSigma)
Get energy of monitor peak if one is present.
double getAvrgLogValue(const API::MatrixWorkspace_sptr &inputWS, const std::string &propertyName, const Kernel::TimeROI &timeroi)
Return average time series log value for the appropriately filtered log.
Kernel::Property * getPLogForProperty(const API::MatrixWorkspace_sptr &inputWS, const std::string &propertyName)
Finds pointer to log value for the property with the name provided.
std::shared_ptr< const Geometry::IComponent > m_chopper
API::MatrixWorkspace_sptr buildWorkspaceToFit(const API::MatrixWorkspace_sptr &inputWS, size_t &wsIndex0)
Build 2-spectra workspace in units of energy, used as source to identify actual monitors spectra.
void exec() override
Executes the algorithm – found all existing monitor peaks.
void findChopSpeedAndDelay(const API::MatrixWorkspace_sptr &inputWS, double &chop_speed, double &chop_delay)
process logs and retrieve chopper speed and chopper delay
std::map< std::string, std::string > validateInputs() override
Cross-check properties with each other.
bool peakGuess(const API::MatrixWorkspace_sptr &inputWS, size_t index, double Ei, const std::vector< size_t > &monsRangeMin, const std::vector< size_t > &monsRangeMax, double &peakPos, double &peakHeight, double &peakTwoSigma)
Former lambda to identify guess values for a peak at given index and set up these parameters as input...
void findBinRanges(const HistogramData::HistogramX &eBins, const HistogramData::HistogramY &signal, const std::vector< double > &guess_energy, double eResolution, std::vector< size_t > &irangeMin, std::vector< size_t > &irangeMax, std::vector< bool > &guessValid)
Find indexes of each expected peak intervals.
size_t calcDerivativeAndCountZeros(const std::vector< double > &bins, const std::vector< double > &signal, std::vector< double > &deriv, std::vector< double > &zeros)
Bare-bone function to calculate numerical derivative, and estimate number of zeros this derivative ha...
bool m_FilterWithDerivative
if true, take derivate of the filter log to identify interval when instrument is running.
void printDebugModeInfo(const std::vector< double > &guess_opening, const std::pair< double, double > &TOF_range, std::shared_ptr< Kernel::Unit > &destUnit)
Auxiliary method to print guess chopper energies in debug mode.
void init() override
Initialization method.
void setFilterLog(const API::MatrixWorkspace_sptr &inputWS)
The internal procedure to set filter log from properties, defining it.
double m_min_Eresolution
maximal relative peak width to consider acceptable.
double m_peakEnergyRatio2reject
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void setPropertySettings(const std::string &name, std::unique_ptr< IPropertySettings > settings)
void debug(const std::string &msg)
Logs at debug level.
void warning(const std::string &msg)
Logs at warning level.
void information(const std::string &msg)
Logs at information level.
Base class for properties.
TimeROI : Object that holds information about when the time measurement was active.
void addROI(const std::string &startTime, const std::string &stopTime)
bool useAll() const
TimeROI selects all time to be used.
A specialised Property class for holding a series of time-value pairs.
std::map< Types::Core::DateAndTime, TYPE > valueAsCorrectMap() const
Return the time series as a correct C++ map<DateAndTime, TYPE>.
std::unique_ptr< TimeSeriesProperty< double > > getDerivative() const
Return time series property, containing time derivative of current property.
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
MANTID_KERNEL_DLL void smoothInRange(const std::vector< double > &input, std::vector< double > &output, double avrgInterval, std::vector< double > const *const binBndrs=nullptr, size_t startIndex=0, size_t endIndex=0, std::vector< double > *const outBins=nullptr)
Basic running average of input vector within specified range, considering variable bin-boundaries if ...
MANTID_KERNEL_DLL int getBinIndex(const std::vector< double > &bins, const double value)
Return the index into a vector of bin boundaries for a particular X value.
constexpr int EMPTY_INT() noexcept
Returns what we consider an "empty" integer within a property.
int32_t specnum_t
Typedef for a spectrum Number.
std::string to_string(const wide_integer< Bits, Signed > &n)
constexpr bool operator<(const wide_integer< Bits, Signed > &lhs, const wide_integer< Bits2, Signed2 > &rhs)
@ Input
An input workspace.
@ Output
An output workspace.