Mantid
Loading...
Searching...
No Matches
AlignAndFocusPowder.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 +
9#include "MantidAPI/Axis.h"
29
31using namespace Mantid::Kernel;
32using namespace Mantid::API;
33using namespace Mantid::DataObjects;
34
36using namespace Kernel;
41
42namespace { // anonymous namespace
43namespace PropertyNames {
44const std::string INPUT_WKSP("InputWorkspace");
45const std::string OUTPUT_WKSP("OutputWorkspace");
46const std::string UNFOCUS_WKSP("UnfocussedWorkspace");
47const std::string CAL_FILE("CalFileName");
48const std::string GROUP_FILE("GroupFilename");
49const std::string GROUP_WKSP("GroupingWorkspace");
50const std::string CAL_WKSP("CalibrationWorkspace");
51const std::string OFFSET_WKSP("OffsetsWorkspace");
52const std::string MASK_WKSP("MaskWorkspace");
53const std::string MASK_TABLE("MaskBinTable");
54const std::string BINNING("Params");
55const std::string RESAMPLEX("ResampleX");
56const std::string BIN_IN_D("Dspacing");
57const std::string D_MINS("DMin");
58const std::string D_MAXS("DMax");
59const std::string RAGGED_DELTA("DeltaRagged");
60const std::string TOF_MIN("TMin");
61const std::string TOF_MAX("TMax");
62const std::string WL_MIN("CropWavelengthMin");
63const std::string WL_MAX("CropWavelengthMax");
64const std::string PRESERVE_EVENTS("PreserveEvents");
65const std::string REMOVE_PROMPT_PULSE("RemovePromptPulseWidth");
66const std::string RESONANCE_UNITS("ResonanceFilterUnits");
67const std::string RESONANCE_LOWER_LIMITS("ResonanceFilterLowerLimits");
68const std::string RESONANCE_UPPER_LIMITS("ResonanceFilterUpperLimits");
69const std::string COMPRESS_TOF_TOL("CompressTolerance");
70const std::string COMPRESS_WALL_TOL("CompressWallClockTolerance");
71const std::string COMPRESS_WALL_START("CompressStartTime");
72const std::string COMPRESS_MODE("CompressBinningMode");
73const std::string L1("PrimaryFlightPath");
74const std::string SPEC_IDS("SpectrumIDs");
75const std::string L2("L2");
76const std::string POLAR("Polar");
77const std::string AZIMUTHAL("Azimuthal");
78const std::string PM_NAME("ReductionProperties");
79const std::string LORENTZ("LorentzCorrection");
80} // namespace PropertyNames
81
82void getTofRange(const MatrixWorkspace_const_sptr &wksp, double &tmin, double &tmax) {
83 if (const auto eventWksp = std::dynamic_pointer_cast<const EventWorkspace>(wksp)) {
84 eventWksp->getEventXMinMax(tmin, tmax);
85 } else {
86 wksp->getXMinMax(tmin, tmax);
87 }
88}
89
90const std::vector<std::string> binningModeNames{"Default", "Linear", "Logarithmic"};
91enum class BinningMode { DEFAULT, LINEAR, LOGARITHMIC, enum_count };
93
94} // anonymous namespace
95
96// Register the class into the algorithm factory
97DECLARE_ALGORITHM(AlignAndFocusPowder)
98
99//----------------------------------------------------------------------------------------------
104 "The input workspace");
105 declareProperty(
107 "The result of diffraction focussing of InputWorkspace");
108 declareProperty(std::make_unique<WorkspaceProperty<MatrixWorkspace>>(PropertyNames::UNFOCUS_WKSP, "",
110 "Treated data in d-spacing before focussing (optional). This will likely "
111 "need rebinning.");
112 // declareProperty(
113 // new WorkspaceProperty<MatrixWorkspace>("LowResTOFWorkspace", "",
114 // Direction::Output, PropertyMode::Optional),
115 // "The name of the workspace containing the filtered low resolution TOF
116 // data.");
117 declareProperty(std::make_unique<FileProperty>(PropertyNames::CAL_FILE, "", FileProperty::OptionalLoad,
118 std::vector<std::string>{".h5", ".hd5", ".hdf", ".cal"}),
119 "The name of the calibration file with offset, masking, and "
120 "grouping data");
121 declareProperty(std::make_unique<FileProperty>(PropertyNames::GROUP_FILE, "", FileProperty::OptionalLoad,
122 std::vector<std::string>{".xml", ".cal"}),
123 "Overrides grouping from CalFileName");
124 declareProperty(std::make_unique<WorkspaceProperty<GroupingWorkspace>>(PropertyNames::GROUP_WKSP, "",
126 "Optional: A GroupingWorkspace giving the grouping info.");
127
128 declareProperty(std::make_unique<WorkspaceProperty<ITableWorkspace>>(PropertyNames::CAL_WKSP, "", Direction::InOut,
130 "Optional: A Workspace containing the calibration information. Either "
131 "this or CalibrationFile needs to be specified.");
132 declareProperty(std::make_unique<WorkspaceProperty<OffsetsWorkspace>>(PropertyNames::OFFSET_WKSP, "",
134 "Optional: An OffsetsWorkspace giving the detector calibration values.");
135 declareProperty(std::make_unique<WorkspaceProperty<MaskWorkspace>>(PropertyNames::MASK_WKSP, "", Direction::InOut,
137 "Optional: A workspace giving which detectors are masked.");
138 declareProperty(
139 std::make_unique<WorkspaceProperty<TableWorkspace>>("MaskBinTable", "", Direction::Input, PropertyMode::Optional),
140 "Optional: A workspace giving pixels and bins to mask.");
141 declareProperty( // intentionally not using the RebinParamsValidator
142 std::make_unique<ArrayProperty<double>>(PropertyNames::BINNING),
143 "A comma separated list of first bin boundary, width, last bin boundary. "
144 "Optionally\n"
145 "this can be followed by a comma and more widths and last boundary "
146 "pairs.\n"
147 "Negative width values indicate logarithmic binning.");
148 declareProperty(PropertyNames::RESAMPLEX, 0,
149 "Number of bins in x-axis. Non-zero value "
150 "overrides \"Params\" property. Negative "
151 "value means logarithmic binning.");
152 setPropertySettings(PropertyNames::BINNING,
153 std::make_unique<EnabledWhenProperty>(PropertyNames::RESAMPLEX, IS_DEFAULT));
154 declareProperty(PropertyNames::BIN_IN_D, true, "Bin in Dspace. (True is Dspace; False is TOF)");
155 declareProperty(std::make_unique<ArrayProperty<double>>(PropertyNames::D_MINS),
156 "Minimum for Dspace axis. (Default 0.) ");
157 mapPropertyName(PropertyNames::D_MINS, "d_min");
158 declareProperty(std::make_unique<ArrayProperty<double>>(PropertyNames::D_MAXS),
159 "Maximum for Dspace axis. (Default 0.) ");
160 mapPropertyName(PropertyNames::D_MAXS, "d_max");
161 declareProperty(std::make_unique<ArrayProperty<double>>(PropertyNames::RAGGED_DELTA), "Step parameter for rebin");
162 mapPropertyName(PropertyNames::RAGGED_DELTA, "delta");
163 declareProperty(PropertyNames::TOF_MIN, EMPTY_DBL(), "Minimum for TOF axis. Defaults to 0. ");
164 mapPropertyName(PropertyNames::TOF_MIN, "tof_min");
165 declareProperty(PropertyNames::TOF_MAX, EMPTY_DBL(), "Maximum for TOF or dspace axis. Defaults to 0. ");
166 mapPropertyName(PropertyNames::TOF_MAX, "tof_max");
167 declareProperty(PropertyNames::PRESERVE_EVENTS, true,
168 "If the InputWorkspace is an "
169 "EventWorkspace, this will preserve "
170 "the full event list (warning: this "
171 "will use much more memory!).");
172 declareProperty(PropertyNames::REMOVE_PROMPT_PULSE, 0.,
173 "Width of events (in "
174 "microseconds) near the prompt "
175 "pulse to remove. 0 disables");
176 auto mustBePositive = std::make_shared<BoundedValidator<double>>();
177 mustBePositive->setLower(0.0);
178
179 std::vector<std::string> allowedResonanceUnits({"Energy", "Wavelength"});
180 declareProperty(PropertyNames::RESONANCE_UNITS, allowedResonanceUnits.back(),
181 std::make_shared<StringListValidator>(allowedResonanceUnits),
182 "Units for resonances to be filtered in. "
183 "The data will be converted to these units temporarily to filter.");
184 declareProperty(std::make_unique<ArrayProperty<double>>(PropertyNames::RESONANCE_LOWER_LIMITS),
185 "Minimum values to filter absorption resonance. This must have same number of values as "
186 "ResonanceFilterUpperLimits. Default behavior is to not filter.");
187 declareProperty(std::make_unique<ArrayProperty<double>>(PropertyNames::RESONANCE_UPPER_LIMITS),
188 "Maximum values to filter absorption resonance. This must have same number of values as "
189 "ResonanceFilterLowerLimits. Default behavior is to not filter.");
190
191 declareProperty(std::make_unique<PropertyWithValue<double>>(PropertyNames::COMPRESS_TOF_TOL, 1e-5, Direction::Input),
192 "Compress events (in microseconds) within this tolerance. (Default 1e-5). If negative then do "
193 "logorithmic compression.");
194 declareProperty(std::make_unique<PropertyWithValue<double>>(PropertyNames::COMPRESS_WALL_TOL, EMPTY_DBL(),
195 mustBePositive, Direction::Input),
196 "The tolerance (in seconds) on the wall-clock time for comparison. Unset "
197 "means compressing all wall-clock times together disabling pulsetime "
198 "resolution.");
199 auto dateValidator = std::make_shared<DateTimeValidator>();
200 dateValidator->allowEmpty(true);
201 declareProperty(PropertyNames::COMPRESS_WALL_START, "", dateValidator,
202 "An ISO formatted date/time string specifying the timestamp for "
203 "starting filtering. Ignored if WallClockTolerance is not specified. "
204 "Default is start of run",
206 declareProperty(PropertyNames::COMPRESS_MODE, binningModeNames[size_t(BinningMode::DEFAULT)],
207 std::make_shared<Mantid::Kernel::StringListValidator>(binningModeNames),
208 "Optional. Binning behavior can be specified in the usual way through sign of tolerance "
209 "('Default'); or can be set to one of the allowed binning modes. ");
210 declareProperty(PropertyNames::LORENTZ, false,
211 "Multiply each spectrum by "
212 "sin(theta) where theta is "
213 "half of the Bragg angle");
214 declareProperty("CropWavelengthMin", 0., "Crop the data at this minimum wavelength.");
215 mapPropertyName(PropertyNames::WL_MIN, "wavelength_min");
216 declareProperty("CropWavelengthMax", EMPTY_DBL(),
217 "Crop the data at this maximum wavelength. Forces use of "
218 "CropWavelengthMin.");
219 mapPropertyName(PropertyNames::WL_MAX, "wavelength_max");
220 declareProperty(PropertyNames::L1, -1.0, "If positive, focus positions are changed. (Default -1) ");
221 declareProperty(std::make_unique<ArrayProperty<int32_t>>(PropertyNames::SPEC_IDS),
222 "Optional: Spectrum Nos (note that it is not detector ID or "
223 "workspace indices).");
224 declareProperty(std::make_unique<ArrayProperty<double>>(PropertyNames::L2),
225 "Optional: Secondary flight (L2) paths for each detector");
226 declareProperty(std::make_unique<ArrayProperty<double>>(PropertyNames::POLAR),
227 "Optional: Polar angles (two thetas) for detectors");
228 declareProperty(std::make_unique<ArrayProperty<double>>(PropertyNames::AZIMUTHAL),
229 "Azimuthal angles (out-of-plain) for detectors");
230
231 declareProperty(PropertyNames::PM_NAME, "__powdereduction", Direction::Input);
232}
233
234std::map<std::string, std::string> AlignAndFocusPowder::validateInputs() {
235 std::map<std::string, std::string> result;
236
237 if (!isDefault(PropertyNames::UNFOCUS_WKSP)) {
238 if (getPropertyValue(PropertyNames::OUTPUT_WKSP) == getPropertyValue(PropertyNames::UNFOCUS_WKSP)) {
239 result[PropertyNames::OUTPUT_WKSP] = "Cannot be the same as UnfocussedWorkspace";
240 result[PropertyNames::UNFOCUS_WKSP] = "Cannot be the same as OutputWorkspace";
241 }
242 }
243
244 if ((!isDefault(PropertyNames::RAGGED_DELTA)) && (!isDefault(PropertyNames::RESAMPLEX))) {
245 result[PropertyNames::RAGGED_DELTA] = "Cannot specify with " + PropertyNames::RESAMPLEX;
246 result[PropertyNames::RESAMPLEX] = "Cannot specify with " + PropertyNames::RAGGED_DELTA;
247 }
248
250 auto inputEW = std::dynamic_pointer_cast<EventWorkspace>(m_inputW);
251 if (inputEW && inputEW->getNumberEvents() <= 0)
252 result[PropertyNames::INPUT_WKSP] = "Empty workspace encounter, possibly due to beam down."
253 "Please plot the pCharge-time to identify suitable range for "
254 "re-time-slicing";
255
256 m_resonanceLower = getProperty(PropertyNames::RESONANCE_LOWER_LIMITS);
257 m_resonanceUpper = getProperty(PropertyNames::RESONANCE_UPPER_LIMITS);
258 // verify that they are the same length
259 if (m_resonanceLower.size() == m_resonanceUpper.size()) {
260 // verify that the lowers are less than the uppers
261 const size_t NUM_WINDOWS = m_resonanceLower.size();
262 bool ok = true;
263 for (size_t i = 0; i < NUM_WINDOWS; ++i) {
265 ok = false;
266 }
267 if (!ok) {
268 const std::string msg = "Lower limits must be less than upper limits";
269 result[PropertyNames::RESONANCE_LOWER_LIMITS] = msg;
270 result[PropertyNames::RESONANCE_UPPER_LIMITS] = msg;
271 }
272 } else {
273 result[PropertyNames::RESONANCE_LOWER_LIMITS] =
274 "Must have same number of values as " + PropertyNames::RESONANCE_UPPER_LIMITS;
275 result[PropertyNames::RESONANCE_UPPER_LIMITS] =
276 "Must have same number of values as " + PropertyNames::RESONANCE_LOWER_LIMITS;
277 }
278
279 return result;
280}
281
282//----------------------------------------------------------------------------------------------
293double AlignAndFocusPowder::getVecPropertyFromPmOrSelf(const std::string &name, std::vector<double> &avec) {
294 avec = getProperty(name);
295 if (!avec.empty()) {
296 return avec[0];
297 }
298 // No overrides provided.
299 return 0.0;
300}
301
302//----------------------------------------------------------------------------------------------
310 // retrieve the properties
312 m_instName = m_inputW->getInstrument()->getName();
313 try {
314 m_instName = Kernel::ConfigService::Instance().getInstrument(m_instName).shortName();
315 } catch (Exception::NotFoundError &) {
316 ; // not noteworthy
317 }
318 std::string calFilename = getPropertyValue(PropertyNames::CAL_FILE);
319 std::string groupFilename = getPropertyValue(PropertyNames::GROUP_FILE);
320 m_calibrationWS = getProperty(PropertyNames::CAL_WKSP);
321 m_maskWS = getProperty(PropertyNames::MASK_WKSP);
322 m_groupWS = getProperty(PropertyNames::GROUP_WKSP);
323 DataObjects::TableWorkspace_sptr maskBinTableWS = getProperty(PropertyNames::MASK_TABLE);
324 m_l1 = getProperty(PropertyNames::L1);
325 specids = getProperty(PropertyNames::SPEC_IDS);
326 l2s = getProperty(PropertyNames::L2);
327 tths = getProperty(PropertyNames::POLAR);
328 phis = getProperty(PropertyNames::AZIMUTHAL);
329 m_params = getProperty(PropertyNames::BINNING);
330 binInDspace = getProperty(PropertyNames::BIN_IN_D);
331 auto dmin = getVecPropertyFromPmOrSelf(PropertyNames::D_MINS, m_dmins);
332 auto dmax = getVecPropertyFromPmOrSelf(PropertyNames::D_MAXS, m_dmaxs);
333 this->getVecPropertyFromPmOrSelf(PropertyNames::RAGGED_DELTA, m_delta_ragged);
334 const bool applyLorentz = getProperty(PropertyNames::LORENTZ);
335 minwl = getProperty(PropertyNames::WL_MIN);
336 maxwl = getProperty(PropertyNames::WL_MAX);
337 if (maxwl == 0.)
338 maxwl = EMPTY_DBL(); // python can only specify 0 for unused
339 tmin = getProperty(PropertyNames::TOF_MIN);
340 tmax = getProperty(PropertyNames::TOF_MAX);
341 m_preserveEvents = getProperty(PropertyNames::PRESERVE_EVENTS);
342 m_resampleX = getProperty(PropertyNames::RESAMPLEX);
343 double compressEventsTolerance = getProperty(PropertyNames::COMPRESS_TOF_TOL);
344 const double wallClockTolerance = getProperty(PropertyNames::COMPRESS_WALL_TOL);
345 const BINMODE mode = getPropertyValue(PropertyNames::COMPRESS_MODE);
346 if (mode == BinningMode::LINEAR)
347 compressEventsTolerance = std::fabs(compressEventsTolerance);
348 else if (mode == BinningMode::LOGARITHMIC)
349 compressEventsTolerance = -1. * std::fabs(compressEventsTolerance);
350
351 // determine some bits about d-space and binning
352 if (m_resampleX != 0) {
353 // ignore the normal rebin parameters
354 m_params.clear();
355 } else if (m_params.size() == 1 && m_delta_ragged.empty()) {
356 // if there is 1 binning parameter and not in ragged rebinning mode
357 // ignore what people asked for
358 binInDspace = bool(dmax > 0.);
359 }
360 if (binInDspace) {
361 if (m_params.size() == 1 && (!isEmpty(dmin)) && (!isEmpty(dmax))) {
362 if (dmin > 0. && dmax > dmin) {
363 double step = m_params[0];
364 m_params.clear();
365 m_params.emplace_back(dmin);
366 m_params.emplace_back(step);
367 m_params.emplace_back(dmax);
368 g_log.information() << "d-Spacing binning updated: " << m_params[0] << " " << m_params[1] << " "
369 << m_params[2] << "\n";
370 } else {
371 g_log.warning() << "something is wrong with dmin (" << dmin << ") and dmax (" << dmax
372 << "). They are being ignored.\n";
373 }
374 }
375 } else {
376 if (m_params.size() == 1 && (!isEmpty(tmin)) && (!isEmpty(tmax))) {
377 if (tmin > 0. && tmax > tmin) {
378 double step = m_params[0];
379 m_params[0] = tmin;
380 m_params.emplace_back(step);
381 m_params.emplace_back(tmax);
382 g_log.information() << "TOF binning updated: " << m_params[0] << " " << m_params[1] << " " << m_params[2]
383 << "\n";
384 } else {
385 g_log.warning() << "something is wrong with tmin (" << tmin << ") and tmax (" << tmax
386 << "). They are being ignored.\n";
387 }
388 }
389 }
390 xmin = 0.;
391 xmax = 0.;
392 if (tmin > 0.) {
393 xmin = tmin;
394 }
395 if (tmax > 0.) {
396 xmax = tmax;
397 }
398 if (!binInDspace && m_params.size() == 3) {
399 xmin = m_params[0];
400 xmax = m_params[2];
401 }
402
403 loadCalFile(calFilename, groupFilename);
404
405 // Now setup the output workspace
407 if (auto inputEW = std::dynamic_pointer_cast<EventWorkspace>(m_inputW)) {
408 // event workspace
409 if (m_outputW != m_inputW) {
410 // out-of-place: clone the input EventWorkspace
411 EventWorkspace_sptr outputEW = inputEW->clone();
412 m_outputW = std::dynamic_pointer_cast<MatrixWorkspace>(outputEW);
413 } // in-place doesn't require anything
414 } else {
415 // workspace2D
416 if (m_outputW != m_inputW) {
417 m_outputW = m_inputW->clone();
418 }
419 }
420
421 // set up a progress bar with the "correct" number of steps
422 m_progress = std::make_unique<Progress>(this, 0., 1., 21);
423
424 if (m_maskWS) {
425 g_log.information() << "running MaskDetectors started at " << Types::Core::DateAndTime::getCurrentTime() << "\n";
426
427 API::IAlgorithm_sptr maskDetAlg = createChildAlgorithm("MaskDetectors");
428 // cast to Workspace for MaksDetectors alg
429 Workspace_sptr outputw = std::dynamic_pointer_cast<Workspace>(m_outputW);
430 maskDetAlg->setProperty("Workspace", outputw);
431 MatrixWorkspace_sptr mksws = std::dynamic_pointer_cast<MatrixWorkspace>(m_maskWS);
432 maskDetAlg->setProperty("MaskedWorkspace", mksws);
433 maskDetAlg->executeAsChildAlg();
434 outputw = maskDetAlg->getProperty("Workspace");
435 // casting
436 m_outputW = std::dynamic_pointer_cast<MatrixWorkspace>(outputw);
437 }
438 m_progress->report();
439
440 // hold onto over tof range for CropWorkspace(tof) and RemovePromptPulse
441 double tofmin = EMPTY_DBL();
442 double tofmax = EMPTY_DBL();
443
444 // crop the workspace in time-of-flight
445 if (((!isEmpty(xmin)) && (xmin >= 0.)) || ((!isEmpty(xmax)) && (xmax > 0.))) {
446 getTofRange(m_outputW, tofmin, tofmax);
447
448 API::IAlgorithm_sptr cropAlg = createChildAlgorithm("CropWorkspace");
449 cropAlg->setProperty("InputWorkspace", m_outputW);
450 cropAlg->setProperty("OutputWorkspace", m_outputW);
451 bool setxmin = false;
452 if ((xmin >= 0.) && (xmin > tofmin)) {
453 cropAlg->setProperty("Xmin", xmin);
454 tofmin = xmin; // increase value
455 setxmin = true;
456 }
457 bool setxmax = false;
458 if ((xmax > 0.) && (xmax < tofmax)) {
459 cropAlg->setProperty("Xmax", xmax);
460 tofmax = xmax;
461 setxmax = true;
462 }
463 // only run if either xmin or xmax was set
464 if (setxmin || setxmax) {
465 g_log.information() << "running CropWorkspace(TOFmin=" << xmin << ", TOFmax=" << xmax << ") started at "
466 << Types::Core::DateAndTime::getCurrentTime() << "\n";
467 cropAlg->executeAsChildAlg();
468 m_outputW = cropAlg->getProperty("OutputWorkspace");
469 }
470 }
471 m_progress->report();
472
473 // filter the input events if appropriate
474 const double removePromptPulseWidth = getProperty(PropertyNames::REMOVE_PROMPT_PULSE);
475 if (removePromptPulseWidth > 0.) {
476 bool removePromptPulse(false);
477 if (auto outputEW = std::dynamic_pointer_cast<EventWorkspace>(m_outputW)) {
478 removePromptPulse = (outputEW->getNumberEvents() > 0);
479 }
480 if (removePromptPulse) {
481 g_log.information() << "running RemovePromptPulse(Width=" << removePromptPulseWidth << ") started at "
482 << Types::Core::DateAndTime::getCurrentTime() << "\n";
483 API::IAlgorithm_sptr filterPAlg = createChildAlgorithm("RemovePromptPulse");
484 filterPAlg->setProperty("InputWorkspace", m_outputW);
485 filterPAlg->setProperty("OutputWorkspace", m_outputW);
486 filterPAlg->setProperty("Width", removePromptPulseWidth);
487
488 // if some of the range was known in CropWorkspace-TOF, use it again here
489 // they default to EMPTY_DBL which the alg interprets as unset
490 filterPAlg->setProperty("TMin", tofmin);
491 filterPAlg->setProperty("TMax", tofmax);
492
493 filterPAlg->executeAsChildAlg();
494 m_outputW = filterPAlg->getProperty("OutputWorkspace");
495 } else {
496 g_log.information("skipping RemovePromptPulse on empty EventWorkspace");
497 }
498 }
499 m_progress->report();
500
501 if (maskBinTableWS) {
502 g_log.information() << "running MaskBinsFromTable started at " << Types::Core::DateAndTime::getCurrentTime()
503 << "\n";
504 API::IAlgorithm_sptr alg = createChildAlgorithm("MaskBinsFromTable");
505 alg->setProperty("InputWorkspace", m_outputW);
506 alg->setProperty("OutputWorkspace", m_outputW);
507 alg->setProperty("MaskingInformation", maskBinTableWS);
508 alg->executeAsChildAlg();
509 m_outputW = alg->getProperty("OutputWorkspace");
510 }
511 m_progress->report();
512
513 // do a calculation to determine if compressing the un-focussed data will reduce data size
514 if (shouldCompressUnfocused(compressEventsTolerance, tofmin, tofmax, !isEmpty(wallClockTolerance))) {
515 compressEventsOutputWS(compressEventsTolerance, wallClockTolerance);
516 }
517
518 if (!binInDspace)
520 m_progress->report();
521
522 if (m_calibrationWS) {
523 // ApplyDiffCal and update m_outputW
524 g_log.information() << "apply calibration workspace to input workspace at "
525 << Types::Core::DateAndTime::getCurrentTime() << "\n";
526 Workspace_sptr outputw = std::dynamic_pointer_cast<Workspace>(m_outputW);
527 API::IAlgorithm_sptr applyDiffCalAlg = createChildAlgorithm("ApplyDiffCal");
528 applyDiffCalAlg->setProperty("InstrumentWorkspace", outputw);
529 applyDiffCalAlg->setProperty("CalibrationWorkspace", m_calibrationWS);
530 applyDiffCalAlg->executeAsChildAlg();
531 // grab and cast
532 outputw = applyDiffCalAlg->getProperty("InstrumentWorkspace");
533 m_outputW = std::dynamic_pointer_cast<MatrixWorkspace>(outputw);
534 }
535
536 m_progress->report();
537
538 m_outputW = convertUnits(m_outputW, "dSpacing");
539 m_progress->report();
540
541 if (m_calibrationWS) {
542 // NOTE:
543 // The conventional workflow for AlignAndFocusPowder allows users to modify the instrument so that the averaged
544 // pixel position can be used when converting back to TOF.
545 // With the recent changes in Unit.h, Mantid is using the averaged DIFC attached to workspace to convert from
546 // d-spacing to TOF by default, which unfortunately breaks the intended workflow here.
547 // To bypass this issue, we are going to remove the attached paramter map so taht Unit.h cannot perform the default
548 // conversion, which will effectively forcing Mantid to revert back to the original intended method.
549 Workspace_sptr outputw = std::dynamic_pointer_cast<Workspace>(m_outputW);
550 API::IAlgorithm_sptr applyDiffCalAlg = createChildAlgorithm("ApplyDiffCal");
551 applyDiffCalAlg->setProperty("InstrumentWorkspace", outputw);
552 applyDiffCalAlg->setProperty("ClearCalibration", true);
553 applyDiffCalAlg->executeAsChildAlg();
554 // grab and cast
555 outputw = applyDiffCalAlg->getProperty("InstrumentWorkspace");
556 m_outputW = std::dynamic_pointer_cast<MatrixWorkspace>(outputw);
557 }
558
559 // filter out absorption resonances
560 if (!m_resonanceLower.empty()) {
562 }
563 m_progress->report(); // the step wil be really fast if the option isn't selected
564
565 // ----------------- WACKY LORENTZ THING HERE
566 // TODO should call LorentzCorrection as a sub-algorithm
567 if (applyLorentz) {
568 g_log.information() << "Applying Lorentz correction started at " << Types::Core::DateAndTime::getCurrentTime()
569 << "\n";
570
571 API::IAlgorithm_sptr alg = createChildAlgorithm("LorentzCorrection");
572 alg->setProperty("InputWorkspace", m_outputW);
573 alg->setProperty("OutputWorkspace", m_outputW);
574 alg->setPropertyValue("Type", "PowderTOF");
575 alg->executeAsChildAlg();
576 m_outputW = alg->getProperty("OutputWorkspace");
577 }
578
579 m_progress->report();
580
581 // crop the workspace in wavelength if requested
582 if (minwl > 0. || (!isEmpty(maxwl))) { // just crop the workspace
583 if (const auto ews = std::dynamic_pointer_cast<EventWorkspace>(m_outputW))
584 g_log.information() << "Number of events = " << ews->getNumberEvents() << ".\n";
585
586 m_outputW = convertUnits(m_outputW, "Wavelength");
587
588 g_log.information() << "running CropWorkspace(WavelengthMin=" << minwl;
589 if (!isEmpty(maxwl))
590 g_log.information() << ", WavelengthMax=" << maxwl;
591 g_log.information() << ") started at " << Types::Core::DateAndTime::getCurrentTime() << "\n";
592
593 API::IAlgorithm_sptr removeAlg = createChildAlgorithm("CropWorkspace");
594 removeAlg->setProperty("InputWorkspace", m_outputW);
595 removeAlg->setProperty("OutputWorkspace", m_outputW);
596 removeAlg->setProperty("XMin", minwl);
597 removeAlg->setProperty("XMax", maxwl);
598 removeAlg->executeAsChildAlg();
599 m_outputW = removeAlg->getProperty("OutputWorkspace");
600 if (const auto ews = std::dynamic_pointer_cast<EventWorkspace>(m_outputW))
601 g_log.information() << "Number of events = " << ews->getNumberEvents() << ".\n";
602 }
603 m_progress->report();
604
605 // Convert units
606 if (minwl > 0. || (!isEmpty(maxwl))) {
607 m_outputW = convertUnits(m_outputW, "dSpacing");
608 }
609 m_progress->report();
610
611 if (binInDspace) {
613 }
614 m_progress->report();
615
616 // copy the output workspace just before `DiffractionFocusing`
617 // this probably should be binned by callers before inspecting
618 if (!isDefault("UnfocussedWorkspace")) {
619 auto wkspCopy = m_outputW->clone();
620 setProperty("UnfocussedWorkspace", std::move(wkspCopy));
621 }
622
623 if (binInDspace && m_resampleX == 0 && !m_delta_ragged.empty() && !m_dmins.empty() && !m_dmaxs.empty()) {
624 // Special case where we can do ragged rebin within diffraction focus
626 m_progress->report();
627 } else {
628 // Diffraction focus
630 m_progress->report();
631
632 // this next call should probably be in for rebin as well
633 // but it changes the system tests
634 if (binInDspace) {
635 if (m_resampleX != 0.) {
637 } else if (!m_delta_ragged.empty()) {
639 }
640 }
641 }
642 m_progress->report();
643
644 // edit the instrument geometry
645 if (m_groupWS && (m_l1 > 0 || !tths.empty() || !l2s.empty() || !phis.empty())) {
646 try {
648 } catch (std::runtime_error &e) {
649 g_log.warning("Not editing instrument geometry:");
650 g_log.warning(e.what());
651 }
652 }
653 m_progress->report();
654
655 // Convert units to TOF
657 m_progress->report();
658
659 // compress again if appropriate
660 compressEventsOutputWS(compressEventsTolerance, wallClockTolerance);
661 m_progress->report();
662
663 if (!binInDspace && !m_delta_ragged.empty()) {
665 }
666
667 // return the output workspace
668 setProperty("OutputWorkspace", m_outputW);
669}
670
671//----------------------------------------------------------------------------------------------
675 const std::vector<double> &polars,
676 const std::vector<specnum_t> &specids,
677 const std::vector<double> &l2s,
678 const std::vector<double> &phis) {
679 g_log.information() << "running EditInstrumentGeometry started at " << Types::Core::DateAndTime::getCurrentTime()
680 << "\n";
681
682 API::IAlgorithm_sptr editAlg = createChildAlgorithm("EditInstrumentGeometry");
683 editAlg->setProperty("Workspace", ws);
684 if (m_l1 > 0.)
685 editAlg->setProperty("PrimaryFlightPath", m_l1);
686 if (!polars.empty())
687 editAlg->setProperty("Polar", polars);
688 if (!specids.empty())
689 editAlg->setProperty("SpectrumIDs", specids);
690 if (!l2s.empty())
691 editAlg->setProperty("L2", l2s);
692 if (!phis.empty())
693 editAlg->setProperty("Azimuthal", phis);
694 editAlg->executeAsChildAlg();
695
696 ws = editAlg->getProperty("Workspace");
697
698 return ws;
699}
700
701//----------------------------------------------------------------------------------------------
705 if (!m_groupWS) {
706 g_log.information() << "not focussing data\n";
707 return ws;
708 }
709
710 // cannot convert to histogram if running with ragged bins
711 // otherwise the data is a histogram *before* the correct binning is set
712 const bool preserveEvents = m_delta_ragged.empty() ? m_preserveEvents : true;
713
714 g_log.information() << "running DiffractionFocussing(PreserveEvents=" << preserveEvents << ") started at "
715 << Types::Core::DateAndTime::getCurrentTime() << "\n";
716
717 API::IAlgorithm_sptr focusAlg = createChildAlgorithm("DiffractionFocussing");
718 focusAlg->setProperty("InputWorkspace", ws);
719 focusAlg->setProperty("OutputWorkspace", ws);
720 focusAlg->setProperty("GroupingWorkspace", m_groupWS);
721 focusAlg->setProperty("PreserveEvents", preserveEvents);
722 focusAlg->executeAsChildAlg();
723 ws = focusAlg->getProperty("OutputWorkspace");
724
725 return ws;
726}
727
728//----------------------------------------------------------------------------------------------
732 if (!m_groupWS) {
733 g_log.information() << "not focussing data\n";
734 return ws;
735 }
736
737 API::IAlgorithm_sptr focusAlg = createChildAlgorithm("DiffractionFocussing");
738 focusAlg->setProperty("InputWorkspace", ws);
739 focusAlg->setProperty("OutputWorkspace", ws);
740 focusAlg->setProperty("GroupingWorkspace", m_groupWS);
741 focusAlg->setProperty("PreserveEvents", m_preserveEvents);
742 focusAlg->setProperty("DMin", m_dmins);
743 focusAlg->setProperty("DMax", m_dmaxs);
744 focusAlg->setProperty("Delta", m_delta_ragged);
745
746 g_log.information() << "running DiffractionFocussing(PreserveEvents=" << m_preserveEvents;
747 g_log.information() << " XMin=" << focusAlg->getPropertyValue("DMin");
748 g_log.information() << " XMax=" << focusAlg->getPropertyValue("DMax");
749 g_log.information() << " Delta=" << focusAlg->getPropertyValue("Delta");
750 g_log.information() << ") started at " << Types::Core::DateAndTime::getCurrentTime() << "\n";
751
752 focusAlg->executeAsChildAlg();
753 ws = focusAlg->getProperty("OutputWorkspace");
754
755 return ws;
756}
757//----------------------------------------------------------------------------------------------
761 const std::string &target) {
762 g_log.information() << "running ConvertUnits(Target=" << target << ") started at "
763 << Types::Core::DateAndTime::getCurrentTime() << "\n";
764
765 API::IAlgorithm_sptr convert2Alg = createChildAlgorithm("ConvertUnits");
766 convert2Alg->setProperty("InputWorkspace", matrixws);
767 convert2Alg->setProperty("OutputWorkspace", matrixws);
768 convert2Alg->setProperty("Target", target);
769 convert2Alg->executeAsChildAlg();
770
771 matrixws = convert2Alg->getProperty("OutputWorkspace");
772
773 return matrixws;
774}
775
777 // determine the previous units
778 const std::string PREVIOUS_UNITS(matrixws->getAxis(0)->unit()->unitID());
779 // number of resonance windows to be removed
780 const size_t NUM_WINDOWS = m_resonanceLower.size();
781
782 // convert to the units requested
783 matrixws = convertUnits(matrixws, getPropertyValue(PropertyNames::RESONANCE_UNITS));
784
785 // filter out the requested area
786 API::IAlgorithm_sptr maskBinsAlg = createChildAlgorithm("MaskBins");
787 for (size_t i = 0; i < NUM_WINDOWS; ++i) {
788 g_log.information() << "running MaskBins(XMin=" << m_resonanceLower[i] << ", XMax=" << m_resonanceUpper[i]
789 << ") started at " << Types::Core::DateAndTime::getCurrentTime() << "\n";
790 maskBinsAlg->setProperty("InputWorkspace", matrixws);
791 maskBinsAlg->setProperty("OutputWorkspace", matrixws); // operate in-place
792 maskBinsAlg->setProperty("XMin", m_resonanceLower[i]);
793 maskBinsAlg->setProperty("XMax", m_resonanceUpper[i]);
794 maskBinsAlg->executeAsChildAlg();
795
796 matrixws = maskBinsAlg->getProperty("OutputWorkspace"); // update workspace pointer
797 }
798
799 // convert back to the original units
800 matrixws = convertUnits(matrixws, PREVIOUS_UNITS);
801
802 return matrixws;
803}
804
805//----------------------------------------------------------------------------------------------
809 if (!m_delta_ragged.empty()) {
810 return matrixws;
811 } else if (m_resampleX != 0) {
812 // ResampleX
813 g_log.information() << "running ResampleX(NumberBins=" << abs(m_resampleX) << ", LogBinning=" << (m_resampleX < 0)
814 << ", dMin(" << m_dmins.size() << "), dmax(" << m_dmaxs.size() << ")) started at "
815 << Types::Core::DateAndTime::getCurrentTime() << "\n";
817 alg->setProperty("InputWorkspace", matrixws);
818 alg->setProperty("OutputWorkspace", matrixws);
819 if ((!m_dmins.empty()) && (!m_dmaxs.empty())) {
820 size_t numHist = m_outputW->getNumberHistograms();
821 if ((numHist == m_dmins.size()) && (numHist == m_dmaxs.size())) {
822 alg->setProperty("XMin", m_dmins);
823 alg->setProperty("XMax", m_dmaxs);
824 } else {
825 g_log.information() << "Number of dmin and dmax values don't match the "
826 << "number of workspace indices. Ignoring the parameters.\n";
827 }
828 }
829 alg->setProperty("NumberBins", abs(m_resampleX));
830 alg->setProperty("LogBinning", (m_resampleX < 0));
831 alg->executeAsChildAlg();
832 matrixws = alg->getProperty("OutputWorkspace");
833 return matrixws;
834 } else {
835 g_log.information() << "running Rebin( ";
836 for (double param : m_params)
837 g_log.information() << param << " ";
838 g_log.information() << ") started at " << Types::Core::DateAndTime::getCurrentTime() << "\n";
839 for (double param : m_params)
840 if (isEmpty(param))
841 g_log.warning("encountered empty binning parameter");
842
843 API::IAlgorithm_sptr rebin3Alg = createChildAlgorithm("Rebin");
844 rebin3Alg->setProperty("InputWorkspace", matrixws);
845 rebin3Alg->setProperty("OutputWorkspace", matrixws);
846 rebin3Alg->setProperty("Params", m_params);
847 rebin3Alg->executeAsChildAlg();
848 matrixws = rebin3Alg->getProperty("OutputWorkspace");
849 return matrixws;
850 }
851}
852
853//----------------------------------------------------------------------------------------------
857 // local variables to control whether or not to log individual values
858 bool print_xmin = false;
859 bool print_xmax = false;
860
861 // configure RebinRagged
862 API::IAlgorithm_sptr alg = createChildAlgorithm("RebinRagged");
863 if (inDspace) {
864 if (!m_dmins.empty()) {
865 print_xmin = true;
866 alg->setProperty("XMin", m_dmins);
867 }
868 if (!m_dmaxs.empty()) {
869 print_xmax = true;
870 alg->setProperty("XMax", m_dmaxs);
871 }
872 } else { // assume time-of-flight
873 if (tmin > 0.) {
874 print_xmin = true;
875 // wacky syntax to set a single value to an ArrayProperty
876 alg->setProperty("XMin", std::vector<double>(1, tmin));
877 }
878 if (tmax > 0. && tmax > tmin) {
879 print_xmax = true;
880 // wacky syntax to set a single value to an ArrayProperty
881 alg->setProperty("XMax", std::vector<double>(1, tmax));
882 }
883 }
884 alg->setProperty("Delta", m_delta_ragged);
885 alg->setProperty("InputWorkspace", matrixws);
886 alg->setProperty("OutputWorkspace", matrixws);
887 alg->setProperty("PreserveEvents", m_preserveEvents);
888
889 // log the parameters used
890 g_log.information() << "running RebinRagged(";
891 if (print_xmin)
892 g_log.information() << " XMin=" << alg->getPropertyValue("XMin");
893 if (print_xmax)
894 g_log.information() << " XMax=" << alg->getPropertyValue("XMax");
895 g_log.information() << " Delta=" << alg->getPropertyValue("Delta");
896 g_log.information() << " ) started at " << Types::Core::DateAndTime::getCurrentTime() << "\n";
897
898 // run the algorithm and get the result back
899 alg->executeAsChildAlg();
900 matrixws = alg->getProperty("OutputWorkspace");
901 return matrixws;
902}
903
905 if (!offsetsWS)
906 return;
907
908 IAlgorithm_sptr alg = createChildAlgorithm("ConvertDiffCal");
909 alg->setProperty("OffsetsWorkspace", offsetsWS);
910 alg->setPropertyValue("OutputWorkspace", m_instName + "_cal");
911 alg->executeAsChildAlg();
912
913 m_calibrationWS = alg->getProperty("OutputWorkspace");
914 AnalysisDataService::Instance().addOrReplace(m_instName + "_cal", m_calibrationWS);
915}
916
917//----------------------------------------------------------------------------------------------
921void AlignAndFocusPowder::loadCalFile(const std::string &calFilename, const std::string &groupFilename) {
922
923 // check if the workspaces exist with their canonical names so they are not
924 // reloaded for chunks
925 if ((!m_groupWS) && (!calFilename.empty()) && (!groupFilename.empty())) {
926 if (AnalysisDataService::Instance().doesExist(m_instName + "_group"))
927 m_groupWS = AnalysisDataService::Instance().retrieveWS<GroupingWorkspace>(m_instName + "_group");
928 }
929 if ((!m_calibrationWS) && (!calFilename.empty())) {
930 OffsetsWorkspace_sptr offsetsWS = getProperty(PropertyNames::OFFSET_WKSP);
931 if (offsetsWS) {
932 convertOffsetsToCal(offsetsWS);
933 } else {
934 if (AnalysisDataService::Instance().doesExist(m_instName + "_cal"))
935 m_calibrationWS = AnalysisDataService::Instance().retrieveWS<ITableWorkspace>(m_instName + "_cal");
936 if (!m_calibrationWS) {
937 if (AnalysisDataService::Instance().doesExist(m_instName + "_offsets")) {
938 offsetsWS = AnalysisDataService::Instance().retrieveWS<OffsetsWorkspace>(m_instName + "_offsets");
939 convertOffsetsToCal(offsetsWS);
940 }
941 }
942 }
943 }
944 if ((!m_maskWS) && (!calFilename.empty())) {
945 if (AnalysisDataService::Instance().doesExist(m_instName + "_mask"))
946 m_maskWS = AnalysisDataService::Instance().retrieveWS<MaskWorkspace>(m_instName + "_mask");
947 }
948
949 // see if everything exists to exit early
951 return;
952
953 // see if the calfile or grouping file is specified
954 if (calFilename.empty() && groupFilename.empty())
955 return;
956
957 // bunch of booleans to keep track of things
958 const bool loadMask = !m_maskWS;
959 const bool loadGrouping = !m_groupWS;
960 const bool loadCalibration = !m_calibrationWS;
961
962 if (calFilename.empty()) { // only load the grouping file
963 g_log.information() << "Loading Grouping file \"" << groupFilename << "\"\n";
964
965 IAlgorithm_sptr alg = createChildAlgorithm("LoadDetectorsGroupingFile");
966 alg->setProperty("InputFile", groupFilename);
967 alg->setProperty("InputWorkspace", m_inputW);
968 alg->executeAsChildAlg();
969
970 m_groupWS = alg->getProperty("OutputWorkspace");
971 const std::string groupname = m_instName + "_group";
972 AnalysisDataService::Instance().addOrReplace(groupname, m_groupWS);
973 this->setPropertyValue(PropertyNames::GROUP_WKSP, groupname);
974 } else { // let LoadDiffCal sort out everything
975 g_log.information() << "Loading Calibration file \"" << calFilename << "\"";
976 if (!groupFilename.empty())
977 g_log.information() << "with grouping from \"" << groupFilename << "\"";
978 g_log.information("");
979
980 IAlgorithm_sptr alg = createChildAlgorithm("LoadDiffCal");
981 alg->setProperty("InputWorkspace", m_inputW);
982 alg->setPropertyValue("Filename", calFilename);
983 alg->setPropertyValue("GroupFilename", groupFilename);
984 alg->setProperty<bool>("MakeCalWorkspace", loadCalibration);
985 alg->setProperty<bool>("MakeGroupingWorkspace", loadGrouping);
986 alg->setProperty<bool>("MakeMaskWorkspace", loadMask);
987 alg->setProperty<double>("TofMin", getProperty("TMin"));
988 alg->setProperty<double>("TofMax", getProperty("TMax"));
989 alg->setPropertyValue("WorkspaceName", m_instName);
990 alg->executeAsChildAlg();
991
992 // replace workspaces as appropriate
993 if (loadGrouping) {
994 m_groupWS = alg->getProperty("OutputGroupingWorkspace");
995
996 const std::string groupname = m_instName + "_group";
997 AnalysisDataService::Instance().addOrReplace(groupname, m_groupWS);
998 this->setPropertyValue(PropertyNames::GROUP_WKSP, groupname);
999 }
1000 if (loadCalibration) {
1001 m_calibrationWS = alg->getProperty("OutputCalWorkspace");
1002
1003 const std::string calname = m_instName + "_cal";
1004 AnalysisDataService::Instance().addOrReplace(calname, m_calibrationWS);
1005 this->setPropertyValue(PropertyNames::CAL_WKSP, calname);
1006 }
1007 if (loadMask) {
1008 m_maskWS = alg->getProperty("OutputMaskWorkspace");
1009
1010 const std::string maskname = m_instName + "_mask";
1011 AnalysisDataService::Instance().addOrReplace(maskname, m_maskWS);
1012 this->setPropertyValue(PropertyNames::MASK_WKSP, maskname);
1013 }
1014 }
1015}
1016
1017void AlignAndFocusPowder::compressEventsOutputWS(const double compressEventsTolerance,
1018 const double wallClockTolerance) {
1019 if (compressEventsTolerance == 0.)
1020 return; // no compression is required
1021
1022 if (auto outputEW = std::dynamic_pointer_cast<EventWorkspace>(m_outputW)) {
1023 g_log.information() << "running CompressEvents(Tolerance=" << compressEventsTolerance;
1024 if (!isEmpty(wallClockTolerance))
1025 g_log.information() << " and WallClockTolerance=" << wallClockTolerance;
1026 g_log.information() << ") started at " << Types::Core::DateAndTime::getCurrentTime() << "\n";
1027 API::IAlgorithm_sptr compressAlg = createChildAlgorithm("CompressEvents");
1028 compressAlg->setProperty("InputWorkspace", outputEW);
1029 compressAlg->setProperty("OutputWorkspace", outputEW);
1030 compressAlg->setProperty("Tolerance", compressEventsTolerance);
1031 if (!isEmpty(wallClockTolerance)) {
1032 compressAlg->setProperty("WallClockTolerance", wallClockTolerance);
1033 compressAlg->setPropertyValue("StartTime", getPropertyValue(PropertyNames::COMPRESS_WALL_START));
1034 }
1035 compressAlg->executeAsChildAlg();
1036 outputEW = compressAlg->getProperty("OutputWorkspace");
1037 m_outputW = std::dynamic_pointer_cast<MatrixWorkspace>(outputEW);
1038 }
1039}
1040
1046bool AlignAndFocusPowder::shouldCompressUnfocused(const double compressTolerance, const double tofmin,
1047 const double tofmax, const bool hasWallClockTolerance) {
1048 // compressing to WEIGHTED (w/ time) is harder to predict
1049 if (hasWallClockTolerance)
1050 return false;
1051 // compressing isn't an option
1052 if (compressTolerance == 0.)
1053 return false;
1054
1055 if (const auto eventWS = std::dynamic_pointer_cast<const EventWorkspace>(m_outputW)) {
1056 // estimate the time-of-flight range for the data
1057 // if the parameters aren't supplied, get them from the workspace
1058 double tofmin_wksp = tofmin;
1059 double tofmax_wksp = tofmax;
1060 if (isEmpty(tofmin) || isEmpty(tofmax))
1061 getTofRange(m_outputW, tofmin_wksp, tofmax_wksp);
1062 const double tofRange = std::fabs(tofmax_wksp - tofmin_wksp);
1063
1064 // constants estimating size difference of various events
1065 constexpr double TOF_EVENT_BYTE_SIZE{static_cast<double>(sizeof(Types::Event::TofEvent))};
1066 constexpr double WEIGHTED_EVENT_BYTE_SIZE{static_cast<double>(sizeof(WeightedEvent))};
1067 constexpr double WEIGHTED_NOTIME_EVENT_BYTE_SIZE{static_cast<double>(sizeof(WeightedEventNoTime))};
1068
1069 // assume one frame although this is generically wrong
1070 // there are 3 fields in weighted events no time
1071 double sizeWeightedEventsEstimate;
1072 if (compressTolerance > 0) // linear
1073 sizeWeightedEventsEstimate = WEIGHTED_NOTIME_EVENT_BYTE_SIZE * tofRange / compressTolerance;
1074 else { // log
1075 if (tofmin_wksp < 0)
1076 return false; // log compression cannot have negative TOF values
1077
1078 if (tofmin_wksp == 0)
1079 tofmin_wksp = compressTolerance;
1080
1081 sizeWeightedEventsEstimate =
1082 WEIGHTED_NOTIME_EVENT_BYTE_SIZE * log(tofmax_wksp / tofmin_wksp) / log1p(abs(compressTolerance));
1083 }
1084
1085 double numEvents = static_cast<double>(eventWS->getNumberEvents());
1086 const auto eventType = eventWS->getEventType();
1087 if (eventType == API::EventType::TOF) {
1088 // there are two fields in tof
1089 numEvents *= TOF_EVENT_BYTE_SIZE;
1090 } else if (eventType == API::EventType::WEIGHTED) {
1091 // there are four fields in weighted w/ time
1092 numEvents *= WEIGHTED_EVENT_BYTE_SIZE;
1093 } else if (eventType == API::EventType::WEIGHTED_NOTIME) {
1094 // it looks like things are already compressed
1095 return false;
1096 } else {
1097 return false; // not coded for something else
1098 }
1099
1100 // there is an error as this doesn't account for the number of spectra, but this is meant to be
1101 // a rough calculation
1102 g_log.information() << "Calculation for compressing events early with size of events currently " << numEvents
1103 << " and comparing to " << sizeWeightedEventsEstimate << "\n";
1104 return sizeWeightedEventsEstimate < numEvents;
1105 } else {
1106 // fall-through is to not compress
1107 return false;
1108 }
1109}
1110
1111} // namespace Mantid::WorkflowAlgorithms
std::string name
Definition Run.cpp:60
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:542
A specialized class for dealing with file properties.
@ OptionalLoad
to specify a file to read but the file doesn't have to exist
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) override
Create a Child Algorithm.
Kernel::IPropertyManager::TypedValue getProperty(const std::string &name) const override
Get the property held by this object.
std::string getPropertyValue(const std::string &name) const override
Get the property held by this object.
ITableWorkspace is an implementation of Workspace in which the data are organised in columns of same ...
Base MatrixWorkspace Abstract Class.
A property class for workspaces.
A GroupingWorkspace is a subclass of Workspace2D where each spectrum has a single number entry,...
An OffsetsWorkspace is a specialized Workspace2D where the Y value at each pixel is the offset to be ...
Info about a single neutron detection event, including a weight and error value, but excluding the pu...
Definition Events.h:91
Info about a single neutron detection event, including a weight and error value:
Definition Events.h:39
Support for a property that holds an array of values.
Exception for when an item is not found in a collection.
Definition Exception.h: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
The concrete, templated class for properties.
This is a parent algorithm that uses several different child algorithms to perform it's task.
void exec() override
Executes the algorithm.
void loadCalFile(const std::string &calFilename, const std::string &groupFilename)
Loads the .cal file if necessary.
const std::string name() const override
Algorithm's name for identification overriding a virtual method.
API::MatrixWorkspace_sptr diffractionFocusRaggedRebinInDspace(API::MatrixWorkspace_sptr ws)
Call diffraction focus to a matrix workspace with ragged rebin parameters.
DataObjects::GroupingWorkspace_sptr m_groupWS
bool shouldCompressUnfocused(const double compressTolerance, const double tofmin, const double tofmax, const bool hasWallClockTolerance)
Return true if a rough estimate suggests that the size of the events will be smaller after compressin...
void convertOffsetsToCal(DataObjects::OffsetsWorkspace_sptr &offsetsWS)
API::MatrixWorkspace_sptr editInstrument(API::MatrixWorkspace_sptr ws, const std::vector< double > &polars, const std::vector< specnum_t > &specids, const std::vector< double > &l2s, const std::vector< double > &phis)
Call edit instrument geometry.
API::MatrixWorkspace_sptr diffractionFocus(API::MatrixWorkspace_sptr ws)
Call diffraction focus to a matrix workspace.
std::unique_ptr< API::Progress > m_progress
Progress reporting.
API::MatrixWorkspace_sptr filterResonances(API::MatrixWorkspace_sptr matrixws)
Filter out absorption resonances.
API::MatrixWorkspace_sptr rebinRagged(API::MatrixWorkspace_sptr matrixws, const bool inDspace)
RebinRagged this should only be done on the final focussed workspace.
double getVecPropertyFromPmOrSelf(const std::string &name, std::vector< double > &avec)
Function to get a vector property either from a PropertyManager or the algorithm properties.
API::MatrixWorkspace_sptr convertUnits(API::MatrixWorkspace_sptr matrixws, const std::string &target)
Convert units.
API::MatrixWorkspace_sptr rebin(API::MatrixWorkspace_sptr matrixws)
Rebin.
void compressEventsOutputWS(const double compressEventsTolerance, const double wallClockTolerance)
std::map< std::string, std::string > validateInputs() override
std::shared_ptr< IAlgorithm > IAlgorithm_sptr
shared pointer to Mantid::API::IAlgorithm
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
Kernel::Logger g_log("ExperimentInfo")
static logger object
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::size_t numEvents(Nexus::File &file, bool &hasTotalCounts, bool &oldNeXusFileNames, const std::string &prefix)
Get the number of events in the currently opened group.
std::shared_ptr< TableWorkspace > TableWorkspace_sptr
shared pointer to Mantid::DataObjects::TableWorkspace
std::shared_ptr< OffsetsWorkspace > OffsetsWorkspace_sptr
shared pointer to the OffsetsWorkspace class
std::shared_ptr< EventWorkspace > EventWorkspace_sptr
shared pointer to the EventWorkspace class
std::shared_ptr< const Instrument > Instrument_const_sptr
Shared pointer to an const instrument object.
const std::string BINMODE("BinningMode")
const std::string OUTPUT_WKSP("OutputWorkspace")
const std::string INPUT_WKSP("InputWorkspace")
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
Definition EmptyValues.h:42
@ InOut
Both an input & output workspace.
Definition Property.h:55
@ Input
An input workspace.
Definition Property.h:53
@ Output
An output workspace.
Definition Property.h:54