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#include "MantidKernel/System.h"
30
32using namespace Mantid::Kernel;
33using namespace Mantid::API;
34using namespace Mantid::DataObjects;
35
37using namespace Kernel;
42
43namespace {
44namespace PropertyNames {
45const std::string INPUT_WKSP("InputWorkspace");
46const std::string OUTPUT_WKSP("OutputWorkspace");
47const std::string UNFOCUS_WKSP("UnfocussedWorkspace");
48const std::string CAL_FILE("CalFileName");
49const std::string GROUP_FILE("GroupFilename");
50const std::string GROUP_WKSP("GroupingWorkspace");
51const std::string CAL_WKSP("CalibrationWorkspace");
52const std::string OFFSET_WKSP("OffsetsWorkspace");
53const std::string MASK_WKSP("MaskWorkspace");
54const std::string MASK_TABLE("MaskBinTable");
55const std::string BINNING("Params");
56const std::string RESAMPLEX("ResampleX");
57const std::string BIN_IN_D("Dspacing");
58const std::string D_MINS("DMin");
59const std::string D_MAXS("DMax");
60const std::string RAGGED_DELTA("DeltaRagged");
61const std::string TOF_MIN("TMin");
62const std::string TOF_MAX("TMax");
63const std::string WL_MIN("CropWavelengthMin");
64const std::string WL_MAX("CropWavelengthMax");
65const std::string PRESERVE_EVENTS("PreserveEvents");
66const std::string REMOVE_PROMPT_PULSE("RemovePromptPulseWidth");
67const std::string RESONANCE_UNITS("ResonanceFilterUnits");
68const std::string RESONANCE_LOWER_LIMITS("ResonanceFilterLowerLimits");
69const std::string RESONANCE_UPPER_LIMITS("ResonanceFilterUpperLimits");
70const std::string COMPRESS_TOF_TOL("CompressTolerance");
71const std::string COMPRESS_WALL_TOL("CompressWallClockTolerance");
72const std::string COMPRESS_WALL_START("CompressStartTime");
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");
80const std::string UNWRAP_REF("UnwrapRef");
81const std::string LOWRES_REF("LowResRef");
82const std::string LOWRES_SPEC_OFF("LowResSpectrumOffset");
83} // namespace PropertyNames
84} // namespace
85
86// Register the class into the algorithm factory
87DECLARE_ALGORITHM(AlignAndFocusPowder)
88
89//----------------------------------------------------------------------------------------------
92void AlignAndFocusPowder::init() {
93 declareProperty(std::make_unique<WorkspaceProperty<MatrixWorkspace>>(PropertyNames::INPUT_WKSP, "", Direction::Input),
94 "The input workspace");
95 declareProperty(
96 std::make_unique<WorkspaceProperty<MatrixWorkspace>>(PropertyNames::OUTPUT_WKSP, "", Direction::Output),
97 "The result of diffraction focussing of InputWorkspace");
98 declareProperty(std::make_unique<WorkspaceProperty<MatrixWorkspace>>(PropertyNames::UNFOCUS_WKSP, "",
100 "Treated data in d-spacing before focussing (optional). This will likely "
101 "need rebinning.");
102 // declareProperty(
103 // new WorkspaceProperty<MatrixWorkspace>("LowResTOFWorkspace", "",
104 // Direction::Output, PropertyMode::Optional),
105 // "The name of the workspace containing the filtered low resolution TOF
106 // data.");
107 declareProperty(std::make_unique<FileProperty>(PropertyNames::CAL_FILE, "", FileProperty::OptionalLoad,
108 std::vector<std::string>{".h5", ".hd5", ".hdf", ".cal"}),
109 "The name of the calibration file with offset, masking, and "
110 "grouping data");
111 declareProperty(std::make_unique<FileProperty>(PropertyNames::GROUP_FILE, "", FileProperty::OptionalLoad,
112 std::vector<std::string>{".xml", ".cal"}),
113 "Overrides grouping from CalFileName");
114 declareProperty(std::make_unique<WorkspaceProperty<GroupingWorkspace>>(PropertyNames::GROUP_WKSP, "",
116 "Optional: A GroupingWorkspace giving the grouping info.");
117
118 declareProperty(std::make_unique<WorkspaceProperty<ITableWorkspace>>(PropertyNames::CAL_WKSP, "", Direction::InOut,
120 "Optional: A Workspace containing the calibration information. Either "
121 "this or CalibrationFile needs to be specified.");
122 declareProperty(std::make_unique<WorkspaceProperty<OffsetsWorkspace>>(PropertyNames::OFFSET_WKSP, "",
124 "Optional: An OffsetsWorkspace giving the detector calibration values.");
125 declareProperty(std::make_unique<WorkspaceProperty<MaskWorkspace>>(PropertyNames::MASK_WKSP, "", Direction::InOut,
127 "Optional: A workspace giving which detectors are masked.");
128 declareProperty(
129 std::make_unique<WorkspaceProperty<TableWorkspace>>("MaskBinTable", "", Direction::Input, PropertyMode::Optional),
130 "Optional: A workspace giving pixels and bins to mask.");
131 declareProperty( // intentionally not using the RebinParamsValidator
132 std::make_unique<ArrayProperty<double>>(PropertyNames::BINNING),
133 "A comma separated list of first bin boundary, width, last bin boundary. "
134 "Optionally\n"
135 "this can be followed by a comma and more widths and last boundary "
136 "pairs.\n"
137 "Negative width values indicate logarithmic binning.");
138 declareProperty(PropertyNames::RESAMPLEX, 0,
139 "Number of bins in x-axis. Non-zero value "
140 "overrides \"Params\" property. Negative "
141 "value means logarithmic binning.");
142 setPropertySettings(PropertyNames::BINNING,
143 std::make_unique<EnabledWhenProperty>(PropertyNames::RESAMPLEX, IS_DEFAULT));
144 declareProperty(PropertyNames::BIN_IN_D, true, "Bin in Dspace. (True is Dspace; False is TOF)");
145 declareProperty(std::make_unique<ArrayProperty<double>>(PropertyNames::D_MINS),
146 "Minimum for Dspace axis. (Default 0.) ");
147 mapPropertyName(PropertyNames::D_MINS, "d_min");
148 declareProperty(std::make_unique<ArrayProperty<double>>(PropertyNames::D_MAXS),
149 "Maximum for Dspace axis. (Default 0.) ");
150 mapPropertyName(PropertyNames::D_MAXS, "d_max");
151 declareProperty(std::make_unique<ArrayProperty<double>>(PropertyNames::RAGGED_DELTA), "Step parameter for rebin");
152 mapPropertyName(PropertyNames::RAGGED_DELTA, "delta");
153 declareProperty(PropertyNames::TOF_MIN, EMPTY_DBL(), "Minimum for TOF axis. Defaults to 0. ");
154 mapPropertyName(PropertyNames::TOF_MIN, "tof_min");
155 declareProperty(PropertyNames::TOF_MAX, EMPTY_DBL(), "Maximum for TOF or dspace axis. Defaults to 0. ");
156 mapPropertyName(PropertyNames::TOF_MAX, "tof_max");
157 declareProperty(PropertyNames::PRESERVE_EVENTS, true,
158 "If the InputWorkspace is an "
159 "EventWorkspace, this will preserve "
160 "the full event list (warning: this "
161 "will use much more memory!).");
162 declareProperty(PropertyNames::REMOVE_PROMPT_PULSE, 0.,
163 "Width of events (in "
164 "microseconds) near the prompt "
165 "pulse to remove. 0 disables");
166 auto mustBePositive = std::make_shared<BoundedValidator<double>>();
167 mustBePositive->setLower(0.0);
168
169 std::vector<std::string> allowedResonanceUnits({"Energy", "Wavelength"});
170 declareProperty(PropertyNames::RESONANCE_UNITS, allowedResonanceUnits.back(),
171 std::make_shared<StringListValidator>(allowedResonanceUnits),
172 "Units for resonances to be filtered in. "
173 "The data will be converted to these units temporarily to filter.");
174 declareProperty(std::make_unique<ArrayProperty<double>>(PropertyNames::RESONANCE_LOWER_LIMITS),
175 "Minimum values to filter absorption resonance. This must have same number of values as "
176 "ResonanceFilterUpperLimits. Default behavior is to not filter.");
177 declareProperty(std::make_unique<ArrayProperty<double>>(PropertyNames::RESONANCE_UPPER_LIMITS),
178 "Maximum values to filter absorption resonance. This must have same number of values as "
179 "ResonanceFilterLowerLimits. Default behavior is to not filter.");
180
181 declareProperty(std::make_unique<PropertyWithValue<double>>(PropertyNames::COMPRESS_TOF_TOL, 1e-5, mustBePositive,
183 "Compress events (in "
184 "microseconds) within this "
185 "tolerance. (Default 1e-5)");
186 declareProperty(std::make_unique<PropertyWithValue<double>>(PropertyNames::COMPRESS_WALL_TOL, EMPTY_DBL(),
187 mustBePositive, Direction::Input),
188 "The tolerance (in seconds) on the wall-clock time for comparison. Unset "
189 "means compressing all wall-clock times together disabling pulsetime "
190 "resolution.");
191
192 auto dateValidator = std::make_shared<DateTimeValidator>();
193 dateValidator->allowEmpty(true);
194 declareProperty(PropertyNames::COMPRESS_WALL_START, "", dateValidator,
195 "An ISO formatted date/time string specifying the timestamp for "
196 "starting filtering. Ignored if WallClockTolerance is not specified. "
197 "Default is start of run",
199 declareProperty(PropertyNames::LORENTZ, false,
200 "Multiply each spectrum by "
201 "sin(theta) where theta is "
202 "half of the Bragg angle");
203 declareProperty(PropertyNames::UNWRAP_REF, 0.,
204 "Reference total flight path for frame "
205 "unwrapping. Zero skips the correction");
206 declareProperty(PropertyNames::LOWRES_REF, 0., "Reference DIFC for resolution removal. Zero skips the correction");
207 declareProperty("CropWavelengthMin", 0., "Crop the data at this minimum wavelength. Overrides LowResRef.");
208 mapPropertyName(PropertyNames::WL_MIN, "wavelength_min");
209 declareProperty("CropWavelengthMax", EMPTY_DBL(),
210 "Crop the data at this maximum wavelength. Forces use of "
211 "CropWavelengthMin.");
212 mapPropertyName(PropertyNames::WL_MAX, "wavelength_max");
213 declareProperty(PropertyNames::L1, -1.0, "If positive, focus positions are changed. (Default -1) ");
214 declareProperty(std::make_unique<ArrayProperty<int32_t>>(PropertyNames::SPEC_IDS),
215 "Optional: Spectrum Nos (note that it is not detector ID or "
216 "workspace indices).");
217 declareProperty(std::make_unique<ArrayProperty<double>>(PropertyNames::L2),
218 "Optional: Secondary flight (L2) paths for each detector");
219 declareProperty(std::make_unique<ArrayProperty<double>>(PropertyNames::POLAR),
220 "Optional: Polar angles (two thetas) for detectors");
221 declareProperty(std::make_unique<ArrayProperty<double>>(PropertyNames::AZIMUTHAL),
222 "Azimuthal angles (out-of-plain) for detectors");
223
224 declareProperty(PropertyNames::LOWRES_SPEC_OFF, -1,
225 "Offset on spectrum No of low resolution spectra from high "
226 "resolution one. "
227 "If negative, then all the low resolution TOF will not be "
228 "processed. Otherwise, low resolution TOF "
229 "will be stored in an additional set of spectra. "
230 "If offset is equal to 0, then the low resolution will have "
231 "same spectrum Nos as the normal ones. "
232 "Otherwise, the low resolution spectra will have spectrum "
233 "IDs offset from normal ones. ");
234 declareProperty(PropertyNames::PM_NAME, "__powdereduction", Direction::Input);
235}
236
237std::map<std::string, std::string> AlignAndFocusPowder::validateInputs() {
238 std::map<std::string, std::string> result;
239
240 if (!isDefault(PropertyNames::UNFOCUS_WKSP)) {
241 if (getPropertyValue(PropertyNames::OUTPUT_WKSP) == getPropertyValue(PropertyNames::UNFOCUS_WKSP)) {
242 result[PropertyNames::OUTPUT_WKSP] = "Cannot be the same as UnfocussedWorkspace";
243 result[PropertyNames::UNFOCUS_WKSP] = "Cannot be the same as OutputWorkspace";
244 }
245 }
246
247 if ((!isDefault(PropertyNames::RAGGED_DELTA)) && (!isDefault(PropertyNames::RESAMPLEX))) {
248 result[PropertyNames::RAGGED_DELTA] = "Cannot specify with " + PropertyNames::RESAMPLEX;
249 result[PropertyNames::RESAMPLEX] = "Cannot specify with " + PropertyNames::RAGGED_DELTA;
250 }
251
252 m_inputW = getProperty(PropertyNames::INPUT_WKSP);
253 m_inputEW = std::dynamic_pointer_cast<EventWorkspace>(m_inputW);
254 if (m_inputEW && m_inputEW->getNumberEvents() <= 0)
255 result[PropertyNames::INPUT_WKSP] = "Empty workspace encounter, possibly due to beam down."
256 "Please plot the pCharge-time to identify suitable range for "
257 "re-time-slicing";
258
259 m_resonanceLower = getProperty(PropertyNames::RESONANCE_LOWER_LIMITS);
260 m_resonanceUpper = getProperty(PropertyNames::RESONANCE_UPPER_LIMITS);
261 // verify that they are the same length
262 if (m_resonanceLower.size() == m_resonanceUpper.size()) {
263 // verify that the lowers are less than the uppers
264 const size_t NUM_WINDOWS = m_resonanceLower.size();
265 bool ok = true;
266 for (size_t i = 0; i < NUM_WINDOWS; ++i) {
268 ok = false;
269 }
270 if (!ok) {
271 const std::string msg = "Lower limits must be less than upper limits";
272 result[PropertyNames::RESONANCE_LOWER_LIMITS] = msg;
273 result[PropertyNames::RESONANCE_UPPER_LIMITS] = msg;
274 }
275 } else {
276 result[PropertyNames::RESONANCE_LOWER_LIMITS] =
277 "Must have same number of values as " + PropertyNames::RESONANCE_UPPER_LIMITS;
278 result[PropertyNames::RESONANCE_UPPER_LIMITS] =
279 "Must have same number of values as " + PropertyNames::RESONANCE_LOWER_LIMITS;
280 }
281
282 return result;
283}
284
285template <typename NumT> struct RegLowVectorPair {
286 std::vector<NumT> reg;
287 std::vector<NumT> low;
288};
289
290template <typename NumT>
291RegLowVectorPair<NumT> splitVectors(const std::vector<NumT> &orig, const size_t numVal, const std::string &label) {
293
294 // check that there is work to do
295 if (!orig.empty()) {
296 // do the spliting
297 if (orig.size() == numVal) {
298 out.reg.assign(orig.begin(), orig.end());
299 out.low.assign(orig.begin(), orig.end());
300 } else if (orig.size() == 2 * numVal) {
301 out.reg.assign(orig.begin(), orig.begin() + numVal);
302 out.low.assign(orig.begin() + numVal, orig.begin());
303 } else {
304 std::stringstream msg;
305 msg << "Input number of " << label << " ids is not equal to "
306 << "the number of histograms or empty (" << orig.size() << " != 0 or " << numVal << " or " << (2 * numVal)
307 << ")";
308 throw std::runtime_error(msg.str());
309 }
310 }
311 return out;
312}
313
314//----------------------------------------------------------------------------------------------
325double AlignAndFocusPowder::getVecPropertyFromPmOrSelf(const std::string &name, std::vector<double> &avec) {
326 avec = getProperty(name);
327 if (!avec.empty()) {
328 return avec[0];
329 }
330 // No overrides provided.
331 return 0.0;
332}
333
334//----------------------------------------------------------------------------------------------
342 // retrieve the properties
343 m_inputW = getProperty(PropertyNames::INPUT_WKSP);
344 m_inputEW = std::dynamic_pointer_cast<EventWorkspace>(m_inputW);
345 m_instName = m_inputW->getInstrument()->getName();
346 try {
347 m_instName = Kernel::ConfigService::Instance().getInstrument(m_instName).shortName();
348 } catch (Exception::NotFoundError &) {
349 ; // not noteworthy
350 }
351 std::string calFilename = getPropertyValue(PropertyNames::CAL_FILE);
352 std::string groupFilename = getPropertyValue(PropertyNames::GROUP_FILE);
353 m_calibrationWS = getProperty(PropertyNames::CAL_WKSP);
354 m_maskWS = getProperty(PropertyNames::MASK_WKSP);
355 m_groupWS = getProperty(PropertyNames::GROUP_WKSP);
356 DataObjects::TableWorkspace_sptr maskBinTableWS = getProperty(PropertyNames::MASK_TABLE);
357 m_l1 = getProperty(PropertyNames::L1);
358 specids = getProperty(PropertyNames::SPEC_IDS);
359 l2s = getProperty(PropertyNames::L2);
360 tths = getProperty(PropertyNames::POLAR);
361 phis = getProperty(PropertyNames::AZIMUTHAL);
362 m_params = getProperty(PropertyNames::BINNING);
363 dspace = getProperty(PropertyNames::BIN_IN_D);
364 auto dmin = getVecPropertyFromPmOrSelf(PropertyNames::D_MINS, m_dmins);
365 auto dmax = getVecPropertyFromPmOrSelf(PropertyNames::D_MAXS, m_dmaxs);
366 this->getVecPropertyFromPmOrSelf(PropertyNames::RAGGED_DELTA, m_delta_ragged);
367 LRef = getProperty(PropertyNames::UNWRAP_REF);
368 DIFCref = getProperty(PropertyNames::LOWRES_REF);
369 const bool applyLorentz = getProperty(PropertyNames::LORENTZ);
370 minwl = getProperty(PropertyNames::WL_MIN);
371 maxwl = getProperty(PropertyNames::WL_MAX);
372 if (maxwl == 0.)
373 maxwl = EMPTY_DBL(); // python can only specify 0 for unused
374 tmin = getProperty(PropertyNames::TOF_MIN);
375 tmax = getProperty(PropertyNames::TOF_MAX);
376 m_preserveEvents = getProperty(PropertyNames::PRESERVE_EVENTS);
377 m_resampleX = getProperty(PropertyNames::RESAMPLEX);
378 const double compressEventsTolerance = getProperty(PropertyNames::COMPRESS_TOF_TOL);
379 const double wallClockTolerance = getProperty(PropertyNames::COMPRESS_WALL_TOL);
380 // determine some bits about d-space and binning
381 if (m_resampleX != 0) {
382 // ignore the normal rebin parameters
383 m_params.clear();
384 } else if (m_params.size() == 1 && m_delta_ragged.empty()) {
385 // if there is 1 binning parameter and not in ragged rebinning mode
386 // ignore what people asked for
387 dspace = bool(dmax > 0.);
388 }
389 if (dspace) {
390 if (m_params.size() == 1 && (!isEmpty(dmin)) && (!isEmpty(dmax))) {
391 if (dmin > 0. && dmax > dmin) {
392 double step = m_params[0];
393 m_params.clear();
394 m_params.emplace_back(dmin);
395 m_params.emplace_back(step);
396 m_params.emplace_back(dmax);
397 g_log.information() << "d-Spacing binning updated: " << m_params[0] << " " << m_params[1] << " "
398 << m_params[2] << "\n";
399 } else {
400 g_log.warning() << "something is wrong with dmin (" << dmin << ") and dmax (" << dmax
401 << "). They are being ignored.\n";
402 }
403 }
404 } else {
405 if (m_params.size() == 1 && (!isEmpty(tmin)) && (!isEmpty(tmax))) {
406 if (tmin > 0. && tmax > tmin) {
407 double step = m_params[0];
408 m_params[0] = tmin;
409 m_params.emplace_back(step);
410 m_params.emplace_back(tmax);
411 g_log.information() << "TOF binning updated: " << m_params[0] << " " << m_params[1] << " " << m_params[2]
412 << "\n";
413 } else {
414 g_log.warning() << "something is wrong with tmin (" << tmin << ") and tmax (" << tmax
415 << "). They are being ignored.\n";
416 }
417 }
418 }
419 xmin = 0.;
420 xmax = 0.;
421 if (tmin > 0.) {
422 xmin = tmin;
423 }
424 if (tmax > 0.) {
425 xmax = tmax;
426 }
427 if (!dspace && m_params.size() == 3) {
428 xmin = m_params[0];
429 xmax = m_params[2];
430 }
431
432 // Low resolution
433 int lowresoffset = getProperty(PropertyNames::LOWRES_SPEC_OFF);
434 if (lowresoffset < 0) {
435 m_processLowResTOF = false;
436 } else {
437 m_processLowResTOF = true;
438 m_lowResSpecOffset = static_cast<size_t>(lowresoffset);
439 }
440
441 loadCalFile(calFilename, groupFilename);
442
443 // Now setup the output workspace
444 m_outputW = getProperty(PropertyNames::OUTPUT_WKSP);
445 if (m_inputEW) {
446 // event workspace
447 if (m_outputW != m_inputW) {
448 // out-of-place: clone the input EventWorkspace
449 m_outputEW = m_inputEW->clone();
450 m_outputW = std::dynamic_pointer_cast<MatrixWorkspace>(m_outputEW);
451 } else {
452 // in-place
453 m_outputEW = std::dynamic_pointer_cast<EventWorkspace>(m_outputW);
454 }
455 } else {
456 // workspace2D
457 if (m_outputW != m_inputW) {
458 m_outputW = m_inputW->clone();
459 }
460 }
461
462 if (m_processLowResTOF) {
463 if (!m_inputEW) {
464 throw std::runtime_error("Input workspace is not EventWorkspace. It is not supported now.");
465 } else {
466 // Make a brand new EventWorkspace
467 m_lowResEW = std::dynamic_pointer_cast<EventWorkspace>(
468 WorkspaceFactory::Instance().create("EventWorkspace", m_inputEW->getNumberHistograms(), 2, 1));
469
470 // Cast to the matrixOutputWS and save it
471 m_lowResW = std::dynamic_pointer_cast<MatrixWorkspace>(m_lowResEW);
472 // m_lowResW->setName(lowreswsname);
473 }
474 }
475
476 // set up a progress bar with the "correct" number of steps
477 m_progress = std::make_unique<Progress>(this, 0., 1., 22);
478
479 if (m_inputEW) {
480 if (compressEventsTolerance > 0.) {
481 g_log.information() << "running CompressEvents(Tolerance=" << compressEventsTolerance;
482 if (!isEmpty(wallClockTolerance))
483 g_log.information() << " and WallClockTolerance=" << wallClockTolerance;
484 g_log.information() << ") started at " << Types::Core::DateAndTime::getCurrentTime() << "\n";
485 API::IAlgorithm_sptr compressAlg = createChildAlgorithm("CompressEvents");
486 compressAlg->setProperty("InputWorkspace", m_outputEW);
487 compressAlg->setProperty("OutputWorkspace", m_outputEW);
488 compressAlg->setProperty("OutputWorkspace", m_outputEW);
489 compressAlg->setProperty("Tolerance", compressEventsTolerance);
490 if (!isEmpty(wallClockTolerance)) {
491 compressAlg->setProperty("WallClockTolerance", wallClockTolerance);
492 compressAlg->setPropertyValue("StartTime", getPropertyValue(PropertyNames::COMPRESS_WALL_START));
493 }
494 compressAlg->executeAsChildAlg();
495 m_outputEW = compressAlg->getProperty("OutputWorkspace");
496 m_outputW = std::dynamic_pointer_cast<MatrixWorkspace>(m_outputEW);
497 } else {
498 g_log.information() << "Not compressing event list\n";
499 doSortEvents(m_outputW); // still sort to help some thing out
500 }
501 }
502 m_progress->report();
503
504 // crop the workspace in time-of-flight
505 if (xmin >= 0. || xmax > 0.) {
506 double tempmin;
507 double tempmax;
508 m_outputW->getXMinMax(tempmin, tempmax);
509
510 g_log.information() << "running CropWorkspace(TOFmin=" << xmin << ", TOFmax=" << xmax << ") started at "
511 << Types::Core::DateAndTime::getCurrentTime() << "\n";
512 API::IAlgorithm_sptr cropAlg = createChildAlgorithm("CropWorkspace");
513 cropAlg->setProperty("InputWorkspace", m_outputW);
514 cropAlg->setProperty("OutputWorkspace", m_outputW);
515 if ((xmin >= 0.) && (xmin > tempmin))
516 cropAlg->setProperty("Xmin", xmin);
517 if ((xmax > 0.) && (xmax < tempmax))
518 cropAlg->setProperty("Xmax", xmax);
519 cropAlg->executeAsChildAlg();
520 m_outputW = cropAlg->getProperty("OutputWorkspace");
521 m_outputEW = std::dynamic_pointer_cast<EventWorkspace>(m_outputW);
522 }
523 m_progress->report();
524
525 // filter the input events if appropriate
526 double removePromptPulseWidth = getProperty(PropertyNames::REMOVE_PROMPT_PULSE);
527 if (removePromptPulseWidth > 0.) {
528 m_outputEW = std::dynamic_pointer_cast<EventWorkspace>(m_outputW);
529 if (m_outputEW->getNumberEvents() > 0) {
530 g_log.information() << "running RemovePromptPulse(Width=" << removePromptPulseWidth << ") started at "
531 << Types::Core::DateAndTime::getCurrentTime() << "\n";
532 API::IAlgorithm_sptr filterPAlg = createChildAlgorithm("RemovePromptPulse");
533 filterPAlg->setProperty("InputWorkspace", m_outputW);
534 filterPAlg->setProperty("OutputWorkspace", m_outputW);
535 filterPAlg->setProperty("Width", removePromptPulseWidth);
536 filterPAlg->executeAsChildAlg();
537 m_outputW = filterPAlg->getProperty("OutputWorkspace");
538 m_outputEW = std::dynamic_pointer_cast<EventWorkspace>(m_outputW);
539 } else {
540 g_log.information("skipping RemovePromptPulse on empty EventWorkspace");
541 }
542 }
543 m_progress->report();
544
545 if (maskBinTableWS) {
546 g_log.information() << "running MaskBinsFromTable started at " << Types::Core::DateAndTime::getCurrentTime()
547 << "\n";
548 API::IAlgorithm_sptr alg = createChildAlgorithm("MaskBinsFromTable");
549 alg->setProperty("InputWorkspace", m_outputW);
550 alg->setProperty("OutputWorkspace", m_outputW);
551 alg->setProperty("MaskingInformation", maskBinTableWS);
552 alg->executeAsChildAlg();
553 m_outputW = alg->getProperty("OutputWorkspace");
554 m_outputEW = std::dynamic_pointer_cast<EventWorkspace>(m_outputW);
555 }
556 m_progress->report();
557
558 if (m_maskWS) {
559 g_log.information() << "running MaskDetectors started at " << Types::Core::DateAndTime::getCurrentTime() << "\n";
560
561 API::IAlgorithm_sptr maskDetAlg = createChildAlgorithm("MaskDetectors");
562 // cast to Workspace for MaksDetectors alg
563 Workspace_sptr outputw = std::dynamic_pointer_cast<Workspace>(m_outputW);
564 maskDetAlg->setProperty("Workspace", outputw);
565 MatrixWorkspace_sptr mksws = std::dynamic_pointer_cast<MatrixWorkspace>(m_maskWS);
566 maskDetAlg->setProperty("MaskedWorkspace", mksws);
567 maskDetAlg->executeAsChildAlg();
568 outputw = maskDetAlg->getProperty("Workspace");
569 // casting
570 m_outputW = std::dynamic_pointer_cast<MatrixWorkspace>(outputw);
571 m_outputEW = std::dynamic_pointer_cast<EventWorkspace>(m_outputW);
572 }
573 m_progress->report();
574
575 if (!dspace)
577 m_progress->report();
578
579 if (m_calibrationWS) {
580 // ApplyDiffCal and update m_outputW
581 g_log.information() << "apply calibration workspace to input workspace at "
582 << Types::Core::DateAndTime::getCurrentTime() << "\n";
583 Workspace_sptr outputw = std::dynamic_pointer_cast<Workspace>(m_outputW);
584 API::IAlgorithm_sptr applyDiffCalAlg = createChildAlgorithm("ApplyDiffCal");
585 applyDiffCalAlg->setProperty("InstrumentWorkspace", outputw);
586 applyDiffCalAlg->setProperty("CalibrationWorkspace", m_calibrationWS);
587 applyDiffCalAlg->executeAsChildAlg();
588 // grab and cast
589 outputw = applyDiffCalAlg->getProperty("InstrumentWorkspace");
590 m_outputW = std::dynamic_pointer_cast<MatrixWorkspace>(outputw);
591 }
592
593 m_outputW = convertUnits(m_outputW, "dSpacing");
594 // update the other pointer that people use
595 m_outputEW = std::dynamic_pointer_cast<EventWorkspace>(m_outputW);
596 m_progress->report();
597
598 if (m_calibrationWS) {
599 // NOTE:
600 // The conventional workflow for AlignAndFocusPowder allows users to modify the instrument so that the averaged
601 // pixel position can be used when converting back to TOF.
602 // With the recent changes in Unit.h, Mantid is using the averaged DIFC attached to workspace to convert from
603 // d-spacing to TOF by default, which unfortunately breaks the intended workflow here.
604 // To bypass this issue, we are going to remove the attached paramter map so taht Unit.h cannot perform the default
605 // conversion, which will effectively forcing Mantid to revert back to the original intended method.
606 Workspace_sptr outputw = std::dynamic_pointer_cast<Workspace>(m_outputW);
607 API::IAlgorithm_sptr applyDiffCalAlg = createChildAlgorithm("ApplyDiffCal");
608 applyDiffCalAlg->setProperty("InstrumentWorkspace", outputw);
609 applyDiffCalAlg->setProperty("ClearCalibration", true);
610 applyDiffCalAlg->executeAsChildAlg();
611 // grab and cast
612 outputw = applyDiffCalAlg->getProperty("InstrumentWorkspace");
613 m_outputW = std::dynamic_pointer_cast<MatrixWorkspace>(outputw);
614 }
615
616 // filter out absorption resonances
617 if (!m_resonanceLower.empty()) {
619 }
620 m_progress->report(); // the step wil be really fast if the option isn't selected
621
622 // ----------------- WACKY LORENTZ THING HERE
623 // TODO should call LorentzCorrection as a sub-algorithm
624 if (applyLorentz) {
625 g_log.information() << "Applying Lorentz correction started at " << Types::Core::DateAndTime::getCurrentTime()
626 << "\n";
627
628 API::IAlgorithm_sptr alg = createChildAlgorithm("LorentzCorrection");
629 alg->setProperty("InputWorkspace", m_outputW);
630 alg->setProperty("OutputWorkspace", m_outputW);
631 alg->setPropertyValue("Type", "PowderTOF");
632 alg->executeAsChildAlg();
633 m_outputW = alg->getProperty("OutputWorkspace");
634 m_outputEW = std::dynamic_pointer_cast<EventWorkspace>(m_outputW);
635 }
636
637 if (LRef > 0. || minwl > 0. || DIFCref > 0. || (!isEmpty(maxwl))) {
639 }
640 m_progress->report();
641
642 // Beyond this point, low resolution TOF workspace is considered.
643 if (LRef > 0.) {
644 g_log.information() << "running UnwrapSNS(LRef=" << LRef << ",Tmin=" << tmin << ",Tmax=" << tmax << ") started at "
645 << Types::Core::DateAndTime::getCurrentTime() << "\n";
646 API::IAlgorithm_sptr removeAlg = createChildAlgorithm("UnwrapSNS");
647 removeAlg->setProperty("InputWorkspace", m_outputW);
648 removeAlg->setProperty("OutputWorkspace", m_outputW);
649 removeAlg->setProperty("LRef", LRef);
650 if (tmin > 0.)
651 removeAlg->setProperty("Tmin", tmin);
652 if (tmax > tmin)
653 removeAlg->setProperty("Tmax", tmax);
654 removeAlg->executeAsChildAlg();
655 m_outputW = removeAlg->getProperty("OutputWorkspace");
656 }
657 m_progress->report();
658
659 if (minwl > 0. || (!isEmpty(maxwl))) { // just crop the worksapce
660 // turn off the low res stuff
661 m_processLowResTOF = false;
662
663 EventWorkspace_sptr ews = std::dynamic_pointer_cast<EventWorkspace>(m_outputW);
664 if (ews)
665 g_log.information() << "Number of events = " << ews->getNumberEvents() << ". ";
666 g_log.information("\n");
667
668 m_outputW = convertUnits(m_outputW, "Wavelength");
669
670 g_log.information() << "running CropWorkspace(WavelengthMin=" << minwl;
671 if (!isEmpty(maxwl))
672 g_log.information() << ", WavelengthMax=" << maxwl;
673 g_log.information() << ") started at " << Types::Core::DateAndTime::getCurrentTime() << "\n";
674
675 API::IAlgorithm_sptr removeAlg = createChildAlgorithm("CropWorkspace");
676 removeAlg->setProperty("InputWorkspace", m_outputW);
677 removeAlg->setProperty("OutputWorkspace", m_outputW);
678 removeAlg->setProperty("XMin", minwl);
679 removeAlg->setProperty("XMax", maxwl);
680 removeAlg->executeAsChildAlg();
681 m_outputW = removeAlg->getProperty("OutputWorkspace");
682 if (ews)
683 g_log.information() << "Number of events = " << ews->getNumberEvents() << ".\n";
684 } else if (DIFCref > 0.) {
685 g_log.information() << "running RemoveLowResTof(RefDIFC=" << DIFCref << ",K=3.22) started at "
686 << Types::Core::DateAndTime::getCurrentTime() << "\n";
687 EventWorkspace_sptr ews = std::dynamic_pointer_cast<EventWorkspace>(m_outputW);
688 if (ews)
689 g_log.information() << "Number of events = " << ews->getNumberEvents() << ". ";
690 g_log.information("\n");
691
692 API::IAlgorithm_sptr removeAlg = createChildAlgorithm("RemoveLowResTOF");
693 removeAlg->setProperty("InputWorkspace", m_outputW);
694 removeAlg->setProperty("OutputWorkspace", m_outputW);
695 removeAlg->setProperty("ReferenceDIFC", DIFCref);
696 removeAlg->setProperty("K", 3.22);
697 if (tmin > 0.)
698 removeAlg->setProperty("Tmin", tmin);
700 removeAlg->setProperty("LowResTOFWorkspace", m_lowResW);
701
702 removeAlg->executeAsChildAlg();
703 m_outputW = removeAlg->getProperty("OutputWorkspace");
705 m_lowResW = removeAlg->getProperty("LowResTOFWorkspace");
706 }
707 m_progress->report();
708
709 EventWorkspace_sptr ews = std::dynamic_pointer_cast<EventWorkspace>(m_outputW);
710 if (ews) {
711 size_t numhighevents = ews->getNumberEvents();
712 if (m_processLowResTOF) {
713 EventWorkspace_sptr lowes = std::dynamic_pointer_cast<EventWorkspace>(m_lowResW);
714 size_t numlowevents = lowes->getNumberEvents();
715 g_log.information() << "Number of high TOF events = " << numhighevents << "; "
716 << "Number of low TOF events = " << numlowevents << ".\n";
717 }
718 }
719 m_progress->report();
720
721 // Convert units
722 if (LRef > 0. || minwl > 0. || DIFCref > 0. || (!isEmpty(maxwl))) {
723 m_outputW = convertUnits(m_outputW, "dSpacing");
725 m_lowResW = convertUnits(m_lowResW, "dSpacing");
726 }
727 m_progress->report();
728
729 if (dspace) {
733 }
734 m_progress->report();
735
739 m_progress->report();
740
741 // copy the output workspace just before `DiffractionFocusing`
742 // this probably should be binned by callers before inspecting
743 if (!isDefault("UnfocussedWorkspace")) {
744 auto wkspCopy = m_outputW->clone();
745 setProperty("UnfocussedWorkspace", std::move(wkspCopy));
746 }
747
748 // Diffraction focus
752 m_progress->report();
753
757 m_progress->report();
758
759 // this next call should probably be in for rebin as well
760 // but it changes the system tests
761 if (dspace) {
762 if (m_resampleX != 0.) {
766 } else if (!m_delta_ragged.empty()) {
770 }
771 }
772 m_progress->report();
773
774 // edit the instrument geometry
775 if (m_groupWS && (m_l1 > 0 || !tths.empty() || !l2s.empty() || !phis.empty())) {
776 size_t numreg = m_outputW->getNumberHistograms();
777
778 try {
779 // set up the vectors for doing everything
780 auto specidsSplit = splitVectors(specids, numreg, "specids");
781 auto tthsSplit = splitVectors(tths, numreg, "two-theta");
782 auto l2sSplit = splitVectors(l2s, numreg, "L2");
783 auto phisSplit = splitVectors(phis, numreg, "phi");
784
785 // Edit instrument
786 m_outputW = editInstrument(m_outputW, tthsSplit.reg, specidsSplit.reg, l2sSplit.reg, phisSplit.reg);
787
788 if (m_processLowResTOF) {
789 m_lowResW = editInstrument(m_lowResW, tthsSplit.low, specidsSplit.low, l2sSplit.low, phisSplit.low);
790 }
791 } catch (std::runtime_error &e) {
792 g_log.warning("Not editing instrument geometry:");
793 g_log.warning(e.what());
794 }
795 }
796 m_progress->report();
797
798 // Conjoin 2 workspaces if there is low resolution
799 if (m_processLowResTOF) {
801 }
802 m_progress->report();
803
804 // Convert units to TOF
806 m_progress->report();
807
808 // compress again if appropriate
809 m_outputEW = std::dynamic_pointer_cast<EventWorkspace>(m_outputW);
810 if ((m_outputEW) && (compressEventsTolerance > 0.)) {
811 g_log.information() << "running CompressEvents(Tolerance=" << compressEventsTolerance;
812 if (!isEmpty(wallClockTolerance))
813 g_log.information() << " and WallClockTolerance=" << wallClockTolerance;
814 g_log.information() << ") started at " << Types::Core::DateAndTime::getCurrentTime() << "\n";
815 API::IAlgorithm_sptr compressAlg = createChildAlgorithm("CompressEvents");
816 compressAlg->setProperty("InputWorkspace", m_outputEW);
817 compressAlg->setProperty("OutputWorkspace", m_outputEW);
818 compressAlg->setProperty("Tolerance", compressEventsTolerance);
819 if (!isEmpty(wallClockTolerance)) {
820 compressAlg->setProperty("WallClockTolerance", wallClockTolerance);
821 compressAlg->setPropertyValue("StartTime", getPropertyValue("CompressStartTime"));
822 }
823 compressAlg->executeAsChildAlg();
824 m_outputEW = compressAlg->getProperty("OutputWorkspace");
825 m_outputW = std::dynamic_pointer_cast<MatrixWorkspace>(m_outputEW);
826 }
827 m_progress->report();
828
829 if (!dspace && !m_delta_ragged.empty()) {
831 }
832
833 // return the output workspace
834 setProperty("OutputWorkspace", m_outputW);
835}
836
837//----------------------------------------------------------------------------------------------
841 const std::vector<double> &polars,
842 const std::vector<specnum_t> &specids,
843 const std::vector<double> &l2s,
844 const std::vector<double> &phis) {
845 g_log.information() << "running EditInstrumentGeometry started at " << Types::Core::DateAndTime::getCurrentTime()
846 << "\n";
847
848 API::IAlgorithm_sptr editAlg = createChildAlgorithm("EditInstrumentGeometry");
849 editAlg->setProperty("Workspace", ws);
850 if (m_l1 > 0.)
851 editAlg->setProperty("PrimaryFlightPath", m_l1);
852 if (!polars.empty())
853 editAlg->setProperty("Polar", polars);
854 if (!specids.empty())
855 editAlg->setProperty("SpectrumIDs", specids);
856 if (!l2s.empty())
857 editAlg->setProperty("L2", l2s);
858 if (!phis.empty())
859 editAlg->setProperty("Azimuthal", phis);
860 editAlg->executeAsChildAlg();
861
862 ws = editAlg->getProperty("Workspace");
863
864 return ws;
865}
866
867//----------------------------------------------------------------------------------------------
871 if (!m_groupWS) {
872 g_log.information() << "not focussing data\n";
873 return ws;
874 }
875
876 if (m_maskWS) {
877 API::IAlgorithm_sptr maskAlg = createChildAlgorithm("MaskDetectors");
878 maskAlg->setProperty("Workspace", m_groupWS);
879 maskAlg->setProperty("MaskedWorkspace", m_maskWS);
880 maskAlg->executeAsChildAlg();
881 }
882
883 g_log.information() << "running DiffractionFocussing started at " << Types::Core::DateAndTime::getCurrentTime()
884 << "\n";
885
886 API::IAlgorithm_sptr focusAlg = createChildAlgorithm("DiffractionFocussing");
887 focusAlg->setProperty("InputWorkspace", ws);
888 focusAlg->setProperty("OutputWorkspace", ws);
889 focusAlg->setProperty("GroupingWorkspace", m_groupWS);
890 focusAlg->setProperty("PreserveEvents", m_preserveEvents);
891 focusAlg->executeAsChildAlg();
892 ws = focusAlg->getProperty("OutputWorkspace");
893
894 return ws;
895}
896
897//----------------------------------------------------------------------------------------------
901 const std::string &target) {
902 g_log.information() << "running ConvertUnits(Target=" << target << ") started at "
903 << Types::Core::DateAndTime::getCurrentTime() << "\n";
904
905 API::IAlgorithm_sptr convert2Alg = createChildAlgorithm("ConvertUnits");
906 convert2Alg->setProperty("InputWorkspace", matrixws);
907 convert2Alg->setProperty("OutputWorkspace", matrixws);
908 convert2Alg->setProperty("Target", target);
909 convert2Alg->executeAsChildAlg();
910
911 matrixws = convert2Alg->getProperty("OutputWorkspace");
912
913 return matrixws;
914}
915
917 // determine the previous units
918 const std::string PREVIOUS_UNITS(matrixws->getAxis(0)->unit()->unitID());
919 // number of resonance windows to be removed
920 const size_t NUM_WINDOWS = m_resonanceLower.size();
921
922 // convert to the units requested
923 matrixws = convertUnits(matrixws, getPropertyValue(PropertyNames::RESONANCE_UNITS));
924
925 // filter out the requested area
926 API::IAlgorithm_sptr maskBinsAlg = createChildAlgorithm("MaskBins");
927 for (size_t i = 0; i < NUM_WINDOWS; ++i) {
928 g_log.information() << "running MaskBins(XMin=" << m_resonanceLower[i] << ", XMax=" << m_resonanceUpper[i]
929 << ") started at " << Types::Core::DateAndTime::getCurrentTime() << "\n";
930 maskBinsAlg->setProperty("InputWorkspace", matrixws);
931 maskBinsAlg->setProperty("OutputWorkspace", matrixws); // operate in-place
932 maskBinsAlg->setProperty("XMin", m_resonanceLower[i]);
933 maskBinsAlg->setProperty("XMax", m_resonanceUpper[i]);
934 maskBinsAlg->executeAsChildAlg();
935
936 matrixws = maskBinsAlg->getProperty("OutputWorkspace"); // update workspace pointer
937 }
938
939 // convert back to the original units
940 matrixws = convertUnits(matrixws, PREVIOUS_UNITS);
941
942 return matrixws;
943}
944
945//----------------------------------------------------------------------------------------------
949 if (!m_delta_ragged.empty()) {
950 return matrixws;
951 } else if (m_resampleX != 0) {
952 // ResampleX
953 g_log.information() << "running ResampleX(NumberBins=" << abs(m_resampleX) << ", LogBinning=" << (m_resampleX < 0)
954 << ", dMin(" << m_dmins.size() << "), dmax(" << m_dmaxs.size() << ")) started at "
955 << Types::Core::DateAndTime::getCurrentTime() << "\n";
957 alg->setProperty("InputWorkspace", matrixws);
958 alg->setProperty("OutputWorkspace", matrixws);
959 if ((!m_dmins.empty()) && (!m_dmaxs.empty())) {
960 size_t numHist = m_outputW->getNumberHistograms();
961 if ((numHist == m_dmins.size()) && (numHist == m_dmaxs.size())) {
962 alg->setProperty("XMin", m_dmins);
963 alg->setProperty("XMax", m_dmaxs);
964 } else {
965 g_log.information() << "Number of dmin and dmax values don't match the "
966 << "number of workspace indices. Ignoring the parameters.\n";
967 }
968 }
969 alg->setProperty("NumberBins", abs(m_resampleX));
970 alg->setProperty("LogBinning", (m_resampleX < 0));
971 alg->executeAsChildAlg();
972 matrixws = alg->getProperty("OutputWorkspace");
973 return matrixws;
974 } else {
975 g_log.information() << "running Rebin( ";
976 for (double param : m_params)
977 g_log.information() << param << " ";
978 g_log.information() << ") started at " << Types::Core::DateAndTime::getCurrentTime() << "\n";
979 for (double param : m_params)
980 if (isEmpty(param))
981 g_log.warning("encountered empty binning parameter");
982
983 API::IAlgorithm_sptr rebin3Alg = createChildAlgorithm("Rebin");
984 rebin3Alg->setProperty("InputWorkspace", matrixws);
985 rebin3Alg->setProperty("OutputWorkspace", matrixws);
986 rebin3Alg->setProperty("Params", m_params);
987 rebin3Alg->executeAsChildAlg();
988 matrixws = rebin3Alg->getProperty("OutputWorkspace");
989 return matrixws;
990 }
991}
992
993//----------------------------------------------------------------------------------------------
997 // local variables to control whether or not to log individual values
998 bool print_xmin = false;
999 bool print_xmax = false;
1000
1001 // configure RebinRagged
1002 API::IAlgorithm_sptr alg = createChildAlgorithm("RebinRagged");
1003 if (inDspace) {
1004 if (!m_dmins.empty()) {
1005 print_xmin = true;
1006 alg->setProperty("XMin", m_dmins);
1007 }
1008 if (!m_dmaxs.empty()) {
1009 print_xmax = true;
1010 alg->setProperty("XMax", m_dmaxs);
1011 }
1012 } else { // assume time-of-flight
1013 if (tmin > 0.) {
1014 print_xmin = true;
1015 // wacky syntax to set a single value to an ArrayProperty
1016 alg->setProperty("XMin", std::vector<double>(1, tmin));
1017 }
1018 if (tmax > 0. && tmax > tmin) {
1019 print_xmax = true;
1020 // wacky syntax to set a single value to an ArrayProperty
1021 alg->setProperty("XMax", std::vector<double>(1, tmax));
1022 }
1023 }
1024 alg->setProperty("Delta", m_delta_ragged);
1025 alg->setProperty("InputWorkspace", matrixws);
1026 alg->setProperty("OutputWorkspace", matrixws);
1027
1028 // log the parameters used
1029 g_log.information() << "running RebinRagged(";
1030 if (print_xmin)
1031 g_log.information() << " XMin=" << alg->getPropertyValue("XMin");
1032 if (print_xmax)
1033 g_log.information() << " XMax=" << alg->getPropertyValue("XMax");
1034 g_log.information() << " Delta=" << alg->getPropertyValue("Delta");
1035 g_log.information() << " ) started at " << Types::Core::DateAndTime::getCurrentTime() << "\n";
1036
1037 // run the algorithm and get the result back
1038 alg->executeAsChildAlg();
1039 matrixws = alg->getProperty("OutputWorkspace");
1040 return matrixws;
1041}
1042
1043//----------------------------------------------------------------------------------------------
1047 const API::MatrixWorkspace_sptr &ws2, size_t offset) {
1048 // Get information from ws1: maximum spectrum number, and store original
1049 // spectrum Nos
1050 size_t nspec1 = ws1->getNumberHistograms();
1051 specnum_t maxspecNo1 = 0;
1052 std::vector<specnum_t> origspecNos;
1053 for (size_t i = 0; i < nspec1; ++i) {
1054 specnum_t tmpspecNo = ws1->getSpectrum(i).getSpectrumNo();
1055 origspecNos.emplace_back(tmpspecNo);
1056 if (tmpspecNo > maxspecNo1)
1057 maxspecNo1 = tmpspecNo;
1058 }
1059
1060 g_log.information() << "[DBx536] Max spectrum number of ws1 = " << maxspecNo1 << ", Offset = " << offset << ".\n";
1061
1062 size_t nspec2 = ws2->getNumberHistograms();
1063
1064 // Conjoin 2 workspaces
1065 Algorithm_sptr alg = this->createChildAlgorithm("AppendSpectra");
1066 alg->initialize();
1067 ;
1068
1069 alg->setProperty("InputWorkspace1", ws1);
1070 alg->setProperty("InputWorkspace2", ws2);
1071 alg->setProperty("OutputWorkspace", ws1);
1072 alg->setProperty("ValidateInputs", false);
1073
1074 alg->executeAsChildAlg();
1075
1076 API::MatrixWorkspace_sptr outws = alg->getProperty("OutputWorkspace");
1077
1078 // FIXED : Restore the original spectrum Nos to spectra from ws1
1079 for (size_t i = 0; i < nspec1; ++i) {
1080 specnum_t tmpspecNo = outws->getSpectrum(i).getSpectrumNo();
1081 outws->getSpectrum(i).setSpectrumNo(origspecNos[i]);
1082
1083 g_log.information() << "[DBx540] Conjoined spectrum " << i << ": restore spectrum number to "
1084 << outws->getSpectrum(i).getSpectrumNo() << " from spectrum number = " << tmpspecNo << ".\n";
1085 }
1086
1087 // Rename spectrum number
1088 if (offset >= 1) {
1089 for (size_t i = 0; i < nspec2; ++i) {
1090 specnum_t newspecid = maxspecNo1 + static_cast<specnum_t>((i) + offset);
1091 outws->getSpectrum(nspec1 + i).setSpectrumNo(newspecid);
1092 // ISpectrum* spec = outws->getSpectrum(nspec1+i);
1093 // if (spec)
1094 // spec->setSpectrumNo(3);
1095 }
1096 }
1097
1098 return outws;
1099}
1100
1102 if (!offsetsWS)
1103 return;
1104
1105 IAlgorithm_sptr alg = createChildAlgorithm("ConvertDiffCal");
1106 alg->setProperty("OffsetsWorkspace", offsetsWS);
1107 alg->setPropertyValue("OutputWorkspace", m_instName + "_cal");
1108 alg->executeAsChildAlg();
1109
1110 m_calibrationWS = alg->getProperty("OutputWorkspace");
1112}
1113
1114//----------------------------------------------------------------------------------------------
1118void AlignAndFocusPowder::loadCalFile(const std::string &calFilename, const std::string &groupFilename) {
1119
1120 // check if the workspaces exist with their canonical names so they are not
1121 // reloaded for chunks
1122 if ((!m_groupWS) && (!calFilename.empty()) && (!groupFilename.empty())) {
1123 if (AnalysisDataService::Instance().doesExist(m_instName + "_group"))
1125 }
1126 if ((!m_calibrationWS) && (!calFilename.empty())) {
1127 OffsetsWorkspace_sptr offsetsWS = getProperty(PropertyNames::OFFSET_WKSP);
1128 if (offsetsWS) {
1129 convertOffsetsToCal(offsetsWS);
1130 } else {
1131 if (AnalysisDataService::Instance().doesExist(m_instName + "_cal"))
1133 if (!m_calibrationWS) {
1134 if (AnalysisDataService::Instance().doesExist(m_instName + "_offsets")) {
1135 offsetsWS = AnalysisDataService::Instance().retrieveWS<OffsetsWorkspace>(m_instName + "_offsets");
1136 convertOffsetsToCal(offsetsWS);
1137 }
1138 }
1139 }
1140 }
1141 if ((!m_maskWS) && (!calFilename.empty())) {
1142 if (AnalysisDataService::Instance().doesExist(m_instName + "_mask"))
1144 }
1145
1146 // see if everything exists to exit early
1148 return;
1149
1150 // see if the calfile or grouping file is specified
1151 if (calFilename.empty() && groupFilename.empty())
1152 return;
1153
1154 // bunch of booleans to keep track of things
1155 const bool loadMask = !m_maskWS;
1156 const bool loadGrouping = !m_groupWS;
1157 const bool loadCalibration = !m_calibrationWS;
1158
1159 if (calFilename.empty()) { // only load the grouping file
1160 g_log.information() << "Loading Grouping file \"" << groupFilename << "\"\n";
1161
1162 IAlgorithm_sptr alg = createChildAlgorithm("LoadDetectorsGroupingFile");
1163 alg->setProperty("InputFile", groupFilename);
1164 alg->setProperty("InputWorkspace", m_inputW);
1165 alg->executeAsChildAlg();
1166
1167 m_groupWS = alg->getProperty("OutputWorkspace");
1168 const std::string name = m_instName + "_group";
1170 this->setPropertyValue(PropertyNames::GROUP_WKSP, name);
1171 } else { // let LoadDiffCal sort out everything
1172 g_log.information() << "Loading Calibration file \"" << calFilename << "\"";
1173 if (!groupFilename.empty())
1174 g_log.information() << "with grouping from \"" << groupFilename << "\"";
1175 g_log.information("");
1176
1177 IAlgorithm_sptr alg = createChildAlgorithm("LoadDiffCal");
1178 alg->setProperty("InputWorkspace", m_inputW);
1179 alg->setPropertyValue("Filename", calFilename);
1180 alg->setPropertyValue("GroupFilename", groupFilename);
1181 alg->setProperty<bool>("MakeCalWorkspace", loadCalibration);
1182 alg->setProperty<bool>("MakeGroupingWorkspace", loadGrouping);
1183 alg->setProperty<bool>("MakeMaskWorkspace", loadMask);
1184 alg->setProperty<double>("TofMin", getProperty("TMin"));
1185 alg->setProperty<double>("TofMax", getProperty("TMax"));
1186 alg->setPropertyValue("WorkspaceName", m_instName);
1187 alg->executeAsChildAlg();
1188
1189 // replace workspaces as appropriate
1190 if (loadGrouping) {
1191 m_groupWS = alg->getProperty("OutputGroupingWorkspace");
1192
1193 const std::string name = m_instName + "_group";
1195 this->setPropertyValue(PropertyNames::GROUP_WKSP, name);
1196 }
1197 if (loadCalibration) {
1198 m_calibrationWS = alg->getProperty("OutputCalWorkspace");
1199
1200 const std::string name = m_instName + "_cal";
1202 this->setPropertyValue(PropertyNames::CAL_WKSP, name);
1203 }
1204 if (loadMask) {
1205 m_maskWS = alg->getProperty("OutputMaskWorkspace");
1206
1207 const std::string name = m_instName + "_mask";
1209 this->setPropertyValue(PropertyNames::MASK_WKSP, name);
1210 }
1211 }
1212}
1213
1214//----------------------------------------------------------------------------------------------
1221 EventWorkspace_sptr eventWS = std::dynamic_pointer_cast<EventWorkspace>(ws);
1222 if (!eventWS)
1223 return;
1224 Algorithm_sptr alg = this->createChildAlgorithm("SortEvents");
1225 alg->setProperty("InputWorkspace", eventWS);
1226 alg->setPropertyValue("SortBy", "X Value");
1227 alg->executeAsChildAlg();
1228}
1229
1230} // namespace Mantid::WorkflowAlgorithms
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
A specialized class for dealing with file properties.
Definition: FileProperty.h:42
@ OptionalLoad
to specify a file to read but the file doesn't have to exist
Definition: FileProperty.h:53
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 ...
Support for a property that holds an array of values.
Definition: ArrayProperty.h:28
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:86
void information(const std::string &msg)
Logs at information level.
Definition: Logger.cpp:105
The concrete, templated class for properties.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
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.
void doSortEvents(const Mantid::API::Workspace_sptr &ws)
Perform SortEvents on the output workspaces but only if they are EventWorkspaces.
const std::string name() const override
Algorithm's name for identification overriding a virtual method.
DataObjects::GroupingWorkspace_sptr m_groupWS
API::MatrixWorkspace_sptr m_lowResW
Low resolution TOF matrix workspace.
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.
size_t m_lowResSpecOffset
Offset to low resolution TOF spectra.
API::MatrixWorkspace_sptr diffractionFocus(API::MatrixWorkspace_sptr ws)
Call diffraction focus to a matrix workspace.
std::unique_ptr< API::Progress > m_progress
Progress reporting.
DataObjects::EventWorkspace_sptr m_lowResEW
Low resolution TOF event workspace.
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.
bool m_processLowResTOF
Flag to process low resolution workspace.
API::MatrixWorkspace_sptr rebin(API::MatrixWorkspace_sptr matrixws)
Rebin.
API::MatrixWorkspace_sptr conjoinWorkspaces(const API::MatrixWorkspace_sptr &ws1, const API::MatrixWorkspace_sptr &ws2, size_t offset)
Add workspace2 to workspace1 by adding spectrum.
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
Definition: Workspace_fwd.h:20
Kernel::Logger g_log("ExperimentInfo")
static logger object
std::shared_ptr< Algorithm > Algorithm_sptr
Typedef for a shared pointer to an Algorithm.
Definition: Algorithm.h:61
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
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::unique_ptr< T > create(const P &parent, const IndexArg &indexArg, const HistArg &histArg)
This is the create() method that all the other create() methods call.
std::shared_ptr< const Instrument > Instrument_const_sptr
Shared pointer to an const instrument object.
RegLowVectorPair< NumT > splitVectors(const std::vector< NumT > &orig, const size_t numVal, const std::string &label)
int32_t specnum_t
Typedef for a spectrum Number.
Definition: IDTypes.h:16
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
Definition: EmptyValues.h:43
@ 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