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