Mantid
Loading...
Searching...
No Matches
DetectorDiagnostic.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
19
20#include <boost/iterator/counting_iterator.hpp>
21
22#include <algorithm>
23#include <cfloat>
24
25namespace Mantid::Algorithms {
26// Register the class into the algorithm factory
27DECLARE_ALGORITHM(DetectorDiagnostic)
28
32using std::string;
33using namespace Mantid::DataObjects;
34using namespace Mantid::API;
35using namespace Mantid::Kernel;
36
37//--------------------------------------------------------------------------
38// Functions to make this a proper workflow algorithm
39//--------------------------------------------------------------------------
40const std::string DetectorDiagnostic::category() const { return "Diagnostics;Workflow\\Diagnostics"; }
41
42const std::string DetectorDiagnostic::name() const { return "DetectorDiagnostic"; }
43
44int DetectorDiagnostic::version() const { return 1; }
45
47 this->declareProperty(std::make_unique<WorkspaceProperty<>>("InputWorkspace", "", Direction::Input),
48 "Name of the integrated detector vanadium (white beam) workspace.");
49 this->declareProperty(
50 std::make_unique<WorkspaceProperty<>>("HardMaskWorkspace", "", Direction::Input, PropertyMode::Optional),
51 "A hard mask to apply to the inputworkspace");
52 this->declareProperty(std::make_unique<WorkspaceProperty<>>("OutputWorkspace", "", Direction::Output),
53 "A MaskWorkspace containing the masked spectra as zeroes and ones.");
54 auto mustBePosInt = std::make_shared<BoundedValidator<int>>();
55 mustBePosInt->setLower(0);
56 this->declareProperty("StartWorkspaceIndex", 0, mustBePosInt,
57 "The index number of the first spectrum to include in the calculation\n"
58 "(default 0)");
59 this->declareProperty("EndWorkspaceIndex", EMPTY_INT(), mustBePosInt,
60 "The index number of the last spectrum to include in the calculation\n"
61 "(default the last histogram)");
62 this->declareProperty("RangeLower", EMPTY_DBL(),
63 "No bin with a boundary at an x value less than this will be used\n"
64 "in the summation that decides if a detector is 'bad' (default: the\n"
65 "start of each histogram)");
66 this->declareProperty("RangeUpper", EMPTY_DBL(),
67 "No bin with a boundary at an x value higher than this value will\n"
68 "be used in the summation that decides if a detector is 'bad'\n"
69 "(default: the end of each histogram)");
70
71 string findDetOutLimGrp("Find Detectors Outside Limits");
72 this->declareProperty("LowThreshold", 0.0,
73 "Spectra whose total number of counts are equal to or below this value\n"
74 "will be marked bad (default 0)");
75 this->setPropertyGroup("LowThreshold", findDetOutLimGrp);
76 this->declareProperty("HighThreshold", EMPTY_DBL(),
77 "Spectra whose total number of counts are equal to or above this value\n"
78 "will be marked bad (default off)");
79 this->setPropertyGroup("HighThreshold", findDetOutLimGrp);
80
81 string medianDetTestGrp("Median Detector Test");
82 auto mustBePositiveDbl = std::make_shared<BoundedValidator<double>>();
83 mustBePositiveDbl->setLower(0);
84 this->declareProperty("LevelsUp", 0, mustBePosInt,
85 "Levels above pixel that will be used to compute the median.\n"
86 "If no level is specified, or 0, the median is over the whole "
87 "instrument.");
88 this->setPropertyGroup("LevelsUp", medianDetTestGrp);
89 this->declareProperty("SignificanceTest", 0.0, mustBePositiveDbl,
90 "Error criterion as a multiple of error bar i.e. to "
91 "fail the test, the magnitude of the\n"
92 "difference with respect to the median value must also "
93 "exceed this number of error bars");
94 this->setPropertyGroup("SignificanceTest", medianDetTestGrp);
95 this->declareProperty("LowThresholdFraction", 0.1, "Lower acceptable bound as fraction of median value");
96 this->setPropertyGroup("LowThresholdFraction", medianDetTestGrp);
97 this->declareProperty("HighThresholdFraction", 1.5, "Upper acceptable bound as fraction of median value");
98 this->setPropertyGroup("HighThresholdFraction", medianDetTestGrp);
99 this->declareProperty("LowOutlier", 0.01, "Lower bound defining outliers as fraction of median value");
100 this->setPropertyGroup("LowOutlier", medianDetTestGrp);
101 this->declareProperty("HighOutlier", 100., "Upper bound defining outliers as fraction of median value");
102 this->setPropertyGroup("HighOutlier", medianDetTestGrp);
103 this->declareProperty("CorrectForSolidAngle", false, "Flag to correct for solid angle efficiency. False by default.");
104 this->setPropertyGroup("CorrectForSolidAngle", medianDetTestGrp);
105 this->declareProperty("ExcludeZeroesFromMedian", false,
106 "If false (default) zeroes will be included in "
107 "the median calculation, otherwise they will not be "
108 "included but they will be left unmasked");
109 this->setPropertyGroup("ExcludeZeroesFromMedian", medianDetTestGrp);
110
111 string detEffVarGrp("Detector Efficiency Variation");
112 this->declareProperty(
113 std::make_unique<WorkspaceProperty<>>("DetVanCompare", "", Direction::Input, PropertyMode::Optional),
114 "Name of a matching second detector vanadium run from the same\n"
115 "instrument. It must be treated in the same manner as the input detector "
116 "vanadium.");
117 this->setPropertyGroup("DetVanCompare", detEffVarGrp);
118 this->declareProperty("DetVanRatioVariation", 1.1, mustBePositiveDbl,
119 "Identify spectra whose total number of counts has changed by more\n"
120 "than this factor of the median change between the two input workspaces");
121 this->setPropertyGroup("DetVanRatioVariation", detEffVarGrp);
122 this->setPropertySettings("DetVanRatioVariation",
123 std::make_unique<EnabledWhenProperty>("DetVanCompare", IS_NOT_DEFAULT));
124
125 string countsCheck("Check Sample Counts");
126 this->declareProperty(
127 std::make_unique<WorkspaceProperty<>>("SampleTotalCountsWorkspace", "", Direction::Input, PropertyMode::Optional),
128 "A sample workspace integrated over the full axis range.");
129 this->setPropertyGroup("SampleTotalCountsWorkspace", countsCheck);
130
131 string backgroundCheck("Check Sample Background");
132 this->declareProperty(
133 std::make_unique<WorkspaceProperty<>>("SampleBackgroundWorkspace", "", Direction::Input, PropertyMode::Optional),
134 "A sample workspace integrated over the background region.");
135 this->setPropertyGroup("SampleBackgroundWorkspace", backgroundCheck);
136 this->declareProperty("SampleBkgLowAcceptanceFactor", 0.0, mustBePositiveDbl,
137 "Low threshold for the background check MedianDetectorTest.");
138 this->setPropertyGroup("SampleBkgLowAcceptanceFactor", backgroundCheck);
139 this->declareProperty("SampleBkgHighAcceptanceFactor", 5.0, mustBePositiveDbl,
140 "High threshold for the background check MedianDetectorTest.");
141 this->setPropertyGroup("SampleBkgHighAcceptanceFactor", backgroundCheck);
142 this->declareProperty("SampleBkgSignificanceTest", 3.3, mustBePositiveDbl,
143 "Error criterion as a multiple of error bar i.e. to "
144 "fail the test, the magnitude of the\n"
145 "difference with respect to the median value must also "
146 "exceed this number of error bars");
147 this->setPropertyGroup("SampleBkgSignificanceTest", backgroundCheck);
148 this->declareProperty("SampleCorrectForSolidAngle", false,
149 "Flag to correct for solid angle efficiency for "
150 "background check MedianDetectorTest. False by "
151 "default.");
152 this->setPropertyGroup("SampleCorrectForSolidAngle", backgroundCheck);
153
154 string psdBleedMaskGrp("Create PSD Bleed Mask");
155 this->declareProperty(
156 std::make_unique<WorkspaceProperty<>>("SampleWorkspace", "", Direction::Input, PropertyMode::Optional),
157 "A sample workspace. This is used in the PSD Bleed calculation.");
158 this->setPropertyGroup("SampleWorkspace", psdBleedMaskGrp);
159 this->declareProperty("MaxTubeFramerate", 0.0, mustBePositiveDbl,
160 "The maximum rate allowed for a tube in counts/us/frame.");
161 this->setPropertyGroup("MaxTubeFramerate", psdBleedMaskGrp);
162 this->declareProperty("NIgnoredCentralPixels", 80, mustBePosInt, "The number of pixels about the centre to ignore.");
163 this->setPropertyGroup("NIgnoredCentralPixels", psdBleedMaskGrp);
164 this->setPropertySettings("NIgnoredCentralPixels",
165 std::make_unique<EnabledWhenProperty>("MaxTubeFramerate", IS_NOT_DEFAULT));
166
167 this->declareProperty("NumberOfFailures", 0, Direction::Output);
168}
169
171 // get the generic information that everybody uses
172 MatrixWorkspace_sptr inputWS = this->getProperty("InputWorkspace");
173 m_minIndex = this->getProperty("StartWorkspaceIndex");
174 m_maxIndex = this->getProperty("EndWorkspaceIndex");
175 m_rangeLower = this->getProperty("RangeLower");
176 m_rangeUpper = this->getProperty("RangeUpper");
177
178 // integrate the data once to pass to ChildAlgorithms
179 m_fracDone = 0.;
180
181 // Get the other workspaces
182 MatrixWorkspace_sptr input2WS = this->getProperty("DetVanCompare");
183 MatrixWorkspace_sptr totalCountsWS = this->getProperty("SampleTotalCountsWorkspace");
184 MatrixWorkspace_sptr bkgWS = this->getProperty("SampleBackgroundWorkspace");
185 MatrixWorkspace_sptr sampleWS = this->getProperty("SampleWorkspace");
186
187 // calculate the number of tests for progress bar
188 m_progStepWidth = 0;
189 {
190 int numTests(1); // if detector vanadium present, do it!
191 if (input2WS)
192 numTests += 1;
193 if (totalCountsWS)
194 numTests += 1;
195 if (bkgWS)
196 numTests += 1;
197 if (sampleWS)
198 numTests += 1;
199 g_log.information() << "Number of tests requested: " << numTests << '\n';
200 m_progStepWidth = (1. - m_fracDone) / static_cast<double>(numTests);
201 }
202
203 int numFailed(0);
205
206 // Apply hard mask if present
207 MatrixWorkspace_sptr hardMaskWS = this->getProperty("HardMaskWorkspace");
208 if (hardMaskWS) {
209 auto md = createChildAlgorithm("MaskDetectors");
210 md->setProperty("Workspace", inputWS);
211 md->setProperty("MaskedWorkspace", hardMaskWS);
212 md->executeAsChildAlg();
213 }
214
215 // Perform FindDetectorsOutsideLimits and MedianDetectorTest on the
216 // detector vanadium
217 maskWS = this->doDetVanTest(inputWS, numFailed);
218
219 // DetectorEfficiencyVariation (only if two workspaces are specified)
220 if (input2WS) {
221 // apply mask to what we are going to input
222 this->applyMask(input2WS, maskWS);
223
224 maskWS = this->doDetVanTest(input2WS, numFailed);
225
226 // get the relevant inputs
227 double variation = this->getProperty("DetVanRatioVariation");
228
229 // run the ChildAlgorithm
230 auto alg = createChildAlgorithm("DetectorEfficiencyVariation", m_fracDone, m_fracDone + m_progStepWidth);
232 alg->setProperty("WhiteBeamBase", inputWS);
233 alg->setProperty("WhiteBeamCompare", input2WS);
234 alg->setProperty("StartWorkspaceIndex", m_minIndex);
235 alg->setProperty("EndWorkspaceIndex", m_maxIndex);
236 alg->setProperty("RangeLower", m_rangeLower);
237 alg->setProperty("RangeUpper", m_rangeUpper);
238 alg->setProperty("Variation", variation);
239 alg->executeAsChildAlg();
240 MatrixWorkspace_sptr localMaskWS = alg->getProperty("OutputWorkspace");
241 applyMask(inputWS, localMaskWS);
242 applyMask(input2WS, localMaskWS);
243 int localFails = alg->getProperty("NumberOfFailures");
244 numFailed += localFails;
245 }
246
247 // Zero total counts check for sample counts
248 if (totalCountsWS) {
249 // apply mask to what we are going to input
250 applyMask(totalCountsWS, maskWS);
251
252 auto zeroChk = createChildAlgorithm("FindDetectorsOutsideLimits", m_fracDone, m_fracDone + m_progStepWidth);
254 zeroChk->setProperty("InputWorkspace", totalCountsWS);
255 zeroChk->setProperty("StartWorkspaceIndex", m_minIndex);
256 zeroChk->setProperty("EndWorkspaceIndex", m_maxIndex);
257 zeroChk->setProperty("LowThreshold", 1.0e-10);
258 zeroChk->setProperty("HighThreshold", 1.0e100);
259 zeroChk->executeAsChildAlg();
260 MatrixWorkspace_sptr localMaskWS = zeroChk->getProperty("OutputWorkspace");
261 applyMask(inputWS, localMaskWS);
262 int localFails = zeroChk->getProperty("NumberOfFailures");
263 numFailed += localFails;
264 }
265
266 // Background check
267 if (bkgWS) {
268 // apply mask to what we are going to input
269 this->applyMask(bkgWS, maskWS);
270
271 double significanceTest = this->getProperty("SampleBkgSignificanceTest");
272 double lowThreshold = this->getProperty("SampleBkgLowAcceptanceFactor");
273 double highThreshold = this->getProperty("SampleBkgHighAcceptanceFactor");
274 bool correctSA = this->getProperty("SampleCorrectForSolidAngle");
275
276 // run the ChildAlgorithm
277 auto alg = createChildAlgorithm("MedianDetectorTest", m_fracDone, m_fracDone + m_progStepWidth);
279 alg->setProperty("InputWorkspace", bkgWS);
280 alg->setProperty("StartWorkspaceIndex", m_minIndex);
281 alg->setProperty("EndWorkspaceIndex", m_maxIndex);
282 alg->setProperty("SignificanceTest", significanceTest);
283 alg->setProperty("LowThreshold", lowThreshold);
284 alg->setProperty("HighThreshold", highThreshold);
285 alg->setProperty("LowOutlier", 0.0);
286 alg->setProperty("HighOutlier", 1.0e100);
287 alg->setProperty("ExcludeZeroesFromMedian", true);
288 alg->setProperty("CorrectForSolidAngle", correctSA);
289 alg->executeAsChildAlg();
290 MatrixWorkspace_sptr localMaskWS = alg->getProperty("OutputWorkspace");
291 applyMask(inputWS, localMaskWS);
292 int localFails = alg->getProperty("NumberOfFailures");
293 numFailed += localFails;
294 }
295
296 // CreatePSDBleedMask (if selected)
297 if (sampleWS) {
298 // get the relevant inputs
299 double maxTubeFrameRate = this->getProperty("MaxTubeFramerate");
300 int numIgnore = this->getProperty("NIgnoredCentralPixels");
301
302 // run the ChildAlgorithm
303 auto alg = createChildAlgorithm("CreatePSDBleedMask", m_fracDone, m_fracDone + m_progStepWidth);
305 alg->setProperty("InputWorkspace", sampleWS);
306 alg->setProperty("MaxTubeFramerate", maxTubeFrameRate);
307 alg->setProperty("NIgnoredCentralPixels", numIgnore);
308 alg->executeAsChildAlg();
309 MatrixWorkspace_sptr localMaskWS = alg->getProperty("OutputWorkspace");
310 applyMask(inputWS, localMaskWS);
311 int localFails = alg->getProperty("NumberOfFailures");
312 numFailed += localFails;
313 }
314
315 g_log.information() << numFailed << " spectra are being masked\n";
316 setProperty("NumberOfFailures", numFailed);
317
318 // Extract the mask from the vanadium workspace
319 std::vector<int> detList;
320 auto extract = createChildAlgorithm("ExtractMask");
321 extract->setProperty("InputWorkspace", inputWS);
322 extract->setProperty("OutputWorkspace", "final_mask");
323 extract->setProperty("DetectorList", detList);
324 extract->executeAsChildAlg();
325 maskWS = extract->getProperty("OutputWorkspace");
326
327 this->setProperty("OutputWorkspace", maskWS);
328}
329
336 auto maskAlg = createChildAlgorithm("MaskDetectors"); // should set progress bar
337 maskAlg->setProperty("Workspace", inputWS);
338 maskAlg->setProperty("MaskedWorkspace", maskWS);
339 maskAlg->setProperty("StartWorkspaceIndex", m_minIndex);
340 maskAlg->setProperty("EndWorkspaceIndex", m_maxIndex);
341 maskAlg->executeAsChildAlg();
342}
343
351 MatrixWorkspace_sptr localMask;
352
353 // FindDetectorsOutsideLimits
354 // get the relevant inputs
355 double lowThreshold = this->getProperty("LowThreshold");
356 double highThreshold = this->getProperty("HighThreshold");
357 // run the ChildAlgorithm
358 auto fdol = createChildAlgorithm("FindDetectorsOutsideLimits", m_fracDone, m_fracDone + m_progStepWidth);
360 fdol->setProperty("InputWorkspace", inputWS);
361 fdol->setProperty("OutputWorkspace", localMask);
362 fdol->setProperty("StartWorkspaceIndex", m_minIndex);
363 fdol->setProperty("EndWorkspaceIndex", m_maxIndex);
364 fdol->setProperty("RangeLower", m_rangeLower);
365 fdol->setProperty("RangeUpper", m_rangeUpper);
366 fdol->setProperty("LowThreshold", lowThreshold);
367 fdol->setProperty("HighThreshold", highThreshold);
368 fdol->executeAsChildAlg();
369 localMask = fdol->getProperty("OutputWorkspace");
370 int localFails = fdol->getProperty("NumberOfFailures");
371 nFails += localFails;
372
373 // get the relevant inputs for the MedianDetectorTests
374 int parents = this->getProperty("LevelsUp");
375 double significanceTest = this->getProperty("SignificanceTest");
376 double lowThresholdFrac = this->getProperty("LowThresholdFraction");
377 double highThresholdFrac = this->getProperty("HighThresholdFraction");
378 double lowOutlier = this->getProperty("LowOutlier");
379 double highOutlier = this->getProperty("HighOutlier");
380 bool excludeZeroes = this->getProperty("ExcludeZeroesFromMedian");
381 bool correctforSA = this->getProperty("CorrectForSolidAngle");
382
383 // MedianDetectorTest
384 // apply mask to what we are going to input
385 this->applyMask(inputWS, localMask);
386
387 // run the ChildAlgorithm
388 auto mdt = createChildAlgorithm("MedianDetectorTest", m_fracDone, m_fracDone + m_progStepWidth);
390 mdt->setProperty("InputWorkspace", inputWS);
391 mdt->setProperty("StartWorkspaceIndex", m_minIndex);
392 mdt->setProperty("EndWorkspaceIndex", m_maxIndex);
393 mdt->setProperty("RangeLower", m_rangeLower);
394 mdt->setProperty("RangeUpper", m_rangeUpper);
395 mdt->setProperty("LevelsUp", parents);
396 mdt->setProperty("SignificanceTest", significanceTest);
397 mdt->setProperty("LowThreshold", lowThresholdFrac);
398 mdt->setProperty("HighThreshold", highThresholdFrac);
399 mdt->setProperty("LowOutlier", lowOutlier);
400 mdt->setProperty("HighOutlier", highOutlier);
401 mdt->setProperty("ExcludeZeroesFromMedian", excludeZeroes);
402 mdt->setProperty("CorrectForSolidAngle", correctforSA);
403 mdt->executeAsChildAlg();
404 localMask = mdt->getProperty("OutputWorkspace");
405 localFails = mdt->getProperty("NumberOfFailures");
406 nFails += localFails;
407
408 this->applyMask(inputWS, localMask);
409 return localMask;
410}
411
412//--------------------------------------------------------------------------
413// Public member functions
414//--------------------------------------------------------------------------
416 : API::Algorithm(), m_fracDone(0.0), m_TotalTime(RTTotal), m_parents(0), m_progStepWidth(0.0), m_minIndex(0),
417 m_maxIndex(EMPTY_INT()), m_rangeLower(EMPTY_DBL()), m_rangeUpper(EMPTY_DBL()) {}
418
419//--------------------------------------------------------------------------
420// Protected member functions
421//--------------------------------------------------------------------------
422
435 const int indexMax, const double lower, const double upper,
436 const bool outputWorkspace2D) {
437 g_log.debug() << "Integrating input spectra.\n";
438 // If the input spectra only has one bin, assume it has been integrated
439 // already
440 // but we need to pass it to the algorithm so that a copy of the input
441 // workspace is
442 // actually created to use for further calculations
443 // get percentage completed estimates for now, t0 and when we've finished t1
445 auto childAlg = createChildAlgorithm("Integration", t0, t1);
446 childAlg->setProperty("InputWorkspace", inputWS);
447 childAlg->setProperty("StartWorkspaceIndex", indexMin);
448 childAlg->setProperty("EndWorkspaceIndex", indexMax);
449 // pass inputed values straight to this integration trusting the checking done
450 // there
451 childAlg->setProperty("RangeLower", lower);
452 childAlg->setProperty("RangeUpper", upper);
453 childAlg->setPropertyValue("IncludePartialBins", "1");
454 childAlg->executeAsChildAlg();
455
456 // Convert to 2D if desired, and if the input was an EventWorkspace.
457 MatrixWorkspace_sptr outputW = childAlg->getProperty("OutputWorkspace");
458 MatrixWorkspace_sptr finalOutputW = outputW;
459 if (outputWorkspace2D && std::dynamic_pointer_cast<EventWorkspace>(outputW)) {
460 g_log.debug() << "Converting output Event Workspace into a Workspace2D.\n";
461 childAlg = createChildAlgorithm("ConvertToMatrixWorkspace", t0, t1);
462 childAlg->setProperty("InputWorkspace", outputW);
463 childAlg->executeAsChildAlg();
464 finalOutputW = childAlg->getProperty("OutputWorkspace");
465 }
466
467 return finalOutputW;
468}
469
477 // Create a new workspace for the results, copy from the input to ensure that
478 // we copy over the instrument and current masking
479 auto maskWS = create<DataObjects::MaskWorkspace>(*inputWS, HistogramData::Points(1));
480 maskWS->setTitle(inputWS->getTitle());
481
482 return maskWS;
483}
484
485std::vector<std::vector<size_t>> DetectorDiagnostic::makeInstrumentMap(const API::MatrixWorkspace &countsWS) {
486 return {{boost::counting_iterator<std::size_t>(0),
487 boost::counting_iterator<std::size_t>(countsWS.getNumberHistograms())}};
488}
493std::vector<std::vector<size_t>> DetectorDiagnostic::makeMap(const API::MatrixWorkspace_sptr &countsWS) {
494 std::multimap<size_t, size_t> mymap;
495
496 if (m_parents == 0) {
497 return makeInstrumentMap(*countsWS);
498 }
499
500 // check if not grouped. If grouped, it will throw
501 if (countsWS->hasGroupedDetectors()) {
502 throw std::runtime_error("Median detector test: not able to create "
503 "detector to spectra map. Try with LevelUp=0.");
504 }
505
506 const SpectrumInfo &spectrumInfo = countsWS->spectrumInfo();
507 const auto &componentInfo = countsWS->componentInfo();
508
509 for (size_t i = 0; i < countsWS->getNumberHistograms(); ++i) {
510 if (!spectrumInfo.hasDetectors(i))
511 throw Kernel::Exception::NotFoundError("SpectrumInfo: No detectors for this workspace index.", std::to_string(i));
512 auto ancestor = spectrumInfo.spectrumDefinition(i)[0].first;
513 for (int level = 0; level < m_parents; ++level) {
514 if (!componentInfo.hasParent(ancestor)) {
515 g_log.warning("Too many levels up. Will ignore LevelsUp");
516 m_parents = 0;
517 return makeInstrumentMap(*countsWS);
518 }
519 ancestor = componentInfo.parent(ancestor);
520 }
521 mymap.emplace(ancestor, i);
522 }
523
524 std::vector<std::vector<size_t>> speclist;
525
526 std::multimap<size_t, size_t>::iterator m_it, s_it;
527 for (m_it = mymap.begin(); m_it != mymap.end(); m_it = s_it) {
528 auto const theKey = m_it->first;
529 auto keyRange = mymap.equal_range(theKey);
530 // Iterate over all map elements with key == theKey
531 std::vector<size_t> speclistsingle;
532 for (s_it = keyRange.first; s_it != keyRange.second; ++s_it) {
533 speclistsingle.emplace_back(s_it->second);
534 }
535 speclist.emplace_back(std::move(speclistsingle));
536 }
537
538 return speclist;
539}
554std::vector<double> DetectorDiagnostic::calculateMedian(const API::MatrixWorkspace &input, bool excludeZeroes,
555 const std::vector<std::vector<size_t>> &indexmap) {
556 std::vector<double> medianvec;
557 g_log.debug("Calculating the median count rate of the spectra");
558
559 bool checkForMask = false;
561 if (instrument != nullptr) {
562 checkForMask = ((instrument->getSource() != nullptr) && (instrument->getSample() != nullptr));
563 }
564 const auto &spectrumInfo = input.spectrumInfo();
565
566 for (const auto &hists : indexmap) {
567 std::vector<double> medianInput;
568 const auto nhists = static_cast<int>(hists.size());
569 // The maximum possible length is that of workspace length
570 medianInput.reserve(nhists);
571
573 for (int i = 0; i < nhists; ++i) { // NOLINT
575
576 if (checkForMask && spectrumInfo.hasDetectors(hists[i])) {
577 if (spectrumInfo.isMasked(hists[i]) || spectrumInfo.isMonitor(hists[i]))
578 continue;
579 }
580
581 const double yValue = input.y(hists[i])[0];
582 if (yValue < 0.0) {
583 throw std::out_of_range("Negative number of counts found, could be "
584 "corrupted raw counts or solid angle data");
585 }
586 if (!std::isfinite(yValue) || (excludeZeroes && yValue < DBL_EPSILON)) // NaNs/Infs
587 {
588 continue;
589 }
590 // Now we have a good value
591 PARALLEL_CRITICAL(DetectorDiagnostic_median_d) { medianInput.emplace_back(yValue); }
592
594 }
596
597 if (medianInput.empty()) {
598 g_log.information("some group has no valid histograms. Will use 0 for median.");
599 medianInput.emplace_back(0.);
600 }
601
603 double median = stats.median;
604
605 if (median < 0 || median > DBL_MAX / 10.0) {
606 throw std::out_of_range("The calculated value for the median was either "
607 "negative or unreliably large");
608 }
609 medianvec.emplace_back(median);
610 }
611 return medianvec;
612}
613
620 if (workspace->isDistribution()) {
621 g_log.information() << "Workspace already contains a count rate, nothing to do.\n";
622 return workspace;
623 }
624
625 g_log.information("Calculating time averaged count rates");
626 // get percentage completed estimates for now, t0 and when we've finished t1
627 double t0 = m_fracDone, t1 = advanceProgress(RTGetRate);
628 auto childAlg = createChildAlgorithm("ConvertToDistribution", t0, t1);
629 childAlg->setProperty<MatrixWorkspace_sptr>("Workspace", workspace);
630 // Now execute the Child Algorithm but allow any exception to bubble up
631 childAlg->execute();
632 return childAlg->getProperty("Workspace");
633}
634
643 m_fracDone += toAdd / m_TotalTime;
644 // it could go negative as sometimes the percentage is re-estimated backwards,
645 // this is worrying about if a small negative value will cause a problem some
646 // where
647 m_fracDone = std::abs(m_fracDone);
649 return m_fracDone;
650}
651
660 advanceProgress(-aborted);
661 m_TotalTime -= aborted;
662}
663} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:547
IPeaksWorkspace_sptr workspace
#define PARALLEL_START_INTERRUPT_REGION
Begins a block to skip processing is the algorithm has been interupted Note the end of the block if n...
#define PARALLEL_CRITICAL(name)
#define PARALLEL_END_INTERRUPT_REGION
Ends a block to skip processing is the algorithm has been interupted Note the start of the block if n...
#define PARALLEL_FOR_IF(condition)
Empty definitions - to enable set your complier to enable openMP.
#define PARALLEL_CHECK_INTERRUPT_REGION
Adds a check after a Parallel region to see if it was interupted.
double lower
lower and upper bounds on the multiplier, if known
double upper
Base class from which all concrete algorithm classes should be derived.
Definition Algorithm.h:76
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.
Kernel::Logger & g_log
Definition Algorithm.h:426
void interruption_point()
This is called during long-running operations, and check if the algorithm has requested that it be ca...
const SpectrumInfo & spectrumInfo() const
Return a reference to the SpectrumInfo object.
Geometry::Instrument_const_sptr getInstrument() const
Returns the parameterized instrument.
Base MatrixWorkspace Abstract Class.
virtual std::size_t getNumberHistograms() const =0
Returns the number of histograms in the workspace.
const HistogramData::HistogramY & y(const size_t index) const
API::SpectrumInfo is an intermediate step towards a SpectrumInfo that is part of Instrument-2....
bool hasDetectors(const size_t index) const
Returns true if the spectrum is associated with detectors in the instrument.
const SpectrumDefinition & spectrumDefinition(const size_t index) const
Returns a const reference to the SpectrumDefinition of the spectrum.
A property class for workspaces.
const std::string name() const override
Algorithm's name for identification overriding a virtual method.
int version() const override
Algorithm's version for identification overriding a virtual method.
void init() override
Virtual method - must be overridden by concrete algorithm.
double m_rangeUpper
Ending x-axis value for integrations.
std::vector< double > calculateMedian(const API::MatrixWorkspace &input, bool excludeZeroes, const std::vector< std::vector< size_t > > &indexmap)
Calculate the median of the given workspace.
int m_TotalTime
An estimate total number of additions or equilivent required to compute a spectrum.
std::vector< std::vector< size_t > > makeMap(const API::MatrixWorkspace_sptr &countsWS)
method to check which spectra should be grouped when calculating the median
std::vector< std::vector< size_t > > makeInstrumentMap(const API::MatrixWorkspace &countsWS)
method to create the map with all spectra
double m_fracDone
An estimate of the percentage of the algorithm runtimes that has been completed.
RunTime
For the progress bar, estimates of how many additions, or equivalent, member functions will do for ea...
@ RTGetTotalCounts
Estimate of the work required from Integrate for each spectrum.
@ RTGetRate
Work required by the ConvertToDistribution algorithm.
int m_maxIndex
Ending workspace index to run tests on.
API::MatrixWorkspace_sptr integrateSpectra(const API::MatrixWorkspace_sptr &inputWS, const int indexMin, const int indexMax, const double lower, const double upper, const bool outputWorkspace2D=false)
Get the total counts for each spectra.
API::MatrixWorkspace_sptr convertToRate(API::MatrixWorkspace_sptr workspace)
Convert to a distribution.
double m_progStepWidth
The number of tests to be run.
DataObjects::MaskWorkspace_sptr generateEmptyMask(const API::MatrixWorkspace_const_sptr &inputWS)
Create a masking workspace to return.
void applyMask(const API::MatrixWorkspace_sptr &inputWS, const API::MatrixWorkspace_sptr &maskWS)
Apply a given mask.
void exec() override
Virtual method - must be overridden by concrete algorithm.
API::MatrixWorkspace_sptr doDetVanTest(const API::MatrixWorkspace_sptr &inputWS, int &nFails)
Perform checks on detector vanadium.
double m_rangeLower
Starting x-axis value for integrations.
int m_minIndex
Starting workspace index to run tests on.
double advanceProgress(double toAdd)
Update the fraction complete estimate assuming that the algorithm has completed a task with estimated...
int m_parents
number of parents up, 0 go to instrument
void failProgress(RunTime aborted)
Update the fraction complete estimate assuming that the algorithm aborted a task with estimated RunTi...
const std::string category() const override
Algorithm's category for identification.
Exception for when an item is not found in a collection.
Definition Exception.h:145
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 const > settings)
Add a PropertySettings instance to the chain of settings for a given property.
void setPropertyGroup(const std::string &name, const std::string &group)
Set the group for a given property.
void debug(const std::string &msg)
Logs at debug level.
Definition Logger.cpp:145
void warning(const std::string &msg)
Logs at warning level.
Definition Logger.cpp:117
void information(const std::string &msg)
Logs at information level.
Definition Logger.cpp:136
std::shared_ptr< IAlgorithm > IAlgorithm_sptr
shared pointer to Mantid::API::IAlgorithm
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::shared_ptr< MaskWorkspace > MaskWorkspace_sptr
shared pointer to the MaskWorkspace class
std::shared_ptr< const Mantid::Geometry::IDetector > IDetector_const_sptr
Shared pointer to IDetector (const version)
Definition IDetector.h:96
std::shared_ptr< const Instrument > Instrument_const_sptr
Shared pointer to an const instrument object.
Statistics getStatistics(const std::vector< TYPE > &data, const unsigned int flags=StatOptions::AllStats)
Return a statistics object for the given data set.
std::enable_if< std::is_pointer< Arg >::value, bool >::type threadSafe(Arg workspace)
Thread-safety check Checks the workspace to ensure it is suitable for multithreaded access.
constexpr int EMPTY_INT() noexcept
Returns what we consider an "empty" integer within a property.
Definition EmptyValues.h:24
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
Definition EmptyValues.h:42
std::string to_string(const wide_integer< Bits, Signed > &n)
@ Input
An input workspace.
Definition Property.h:54
@ Output
An output workspace.
Definition Property.h:55
Simple struct to store statistics.
Definition Statistics.h:36
double median
Median value.
Definition Statistics.h:44