Mantid
Loading...
Searching...
No Matches
ConvertToMD.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 +
8
9#include <algorithm>
10
13#include "MantidAPI/Run.h"
16
25
30
32
37
38using namespace Mantid::API;
39using namespace Mantid::Kernel;
40using namespace Mantid::DataObjects;
42
43namespace Mantid::MDAlgorithms {
44
45//
46// Register the algorithm into the AlgorithmFactory
47DECLARE_ALGORITHM(ConvertToMD)
48
49void ConvertToMD::init() {
51 declareProperty(std::make_unique<WorkspaceProperty<IMDEventWorkspace>>("OutputWorkspace", "", Direction::Output),
52 "Name of the output *MDEventWorkspace*.");
53
54 declareProperty(std::make_unique<PropertyWithValue<bool>>("OverwriteExisting", true, Direction::Input),
55 "By default (\"1\"), existing Output Workspace will be replaced. Select "
56 "false (\"0\") if you want to add new events to the workspace, which "
57 "already exist. "
58 "\nChoosing \"0\" can be very inefficient for file-based workspaces");
59
60 declareProperty(std::make_unique<ArrayProperty<double>>("MinValues"),
61 "It has to be N comma separated values, where N is the "
62 "number of dimensions of the target workspace. Values "
63 "smaller then specified here will not be added to "
64 "workspace.\n Number N is defined by properties 4,6 and 7 "
65 "and "
66 "described on *MD Transformation factory* page. See also "
67 ":ref:`algm-ConvertToMDMinMaxLocal`");
68
69 // TODO: " If a minimal target workspace range is higher then the one
70 // specified here, the target workspace range will be used instead " );
71
72 declareProperty(std::make_unique<ArrayProperty<double>>("MaxValues"),
73 "A list of the same size and the same units as MinValues "
74 "list. Values higher or equal to the specified by "
75 "this list will be ignored");
76 // TODO: "If a maximal target workspace range is lower, then one of
77 // specified here, the target workspace range will be used instead" );
78
79 // Box controller properties. These are the defaults
80 this->initBoxControllerProps("5" /*SplitInto*/, 1000 /*SplitThreshold*/, 20 /*MaxRecursionDepth*/);
81 // additional box controller settings property.
82 auto mustBeMoreThan1 = std::make_shared<BoundedValidator<int>>();
83 mustBeMoreThan1->setLower(1);
84
85 declareProperty(std::make_unique<PropertyWithValue<int>>("MinRecursionDepth", 1, mustBeMoreThan1),
86 "Optional. If specified, then all the boxes will be split to this "
87 "minimum recursion depth. 0 = no splitting, "
88 "1 = one level of splitting, etc. \n Be careful using this since it can "
89 "quickly create a huge number of :math:`boxes = "
90 "SplitInto^{MinRercursionDepth \\times NumDimensions}`. \n But setting "
91 "this property equal to MaxRecursionDepth "
92 "is necessary if one wants to generate multiple file based "
93 "workspaces in order to merge them later.");
94 setPropertyGroup("MinRecursionDepth", getBoxSettingsGroupName());
95
96 declareProperty(std::make_unique<PropertyWithValue<bool>>("TopLevelSplitting", false, Direction::Input),
97 "This option causes a split of the top level, i.e. level0, of 50 for the "
98 "first four dimensions.");
99
100 declareProperty(std::make_unique<FileProperty>("Filename", "", FileProperty::OptionalSave, ".nxs"),
101 "The name of the Nexus file to write, as a full or relative path.\n"
102 "Only used if FileBackEnd is true.");
103 setPropertySettings("Filename", std::make_unique<EnabledWhenProperty>("FileBackEnd", IS_EQUAL_TO, "1"));
104
105 declareProperty("FileBackEnd", false,
106 "If true, Filename must also be specified. The algorithm "
107 "will create the specified file in addition to an output "
108 "workspace. The workspace will load data from the file on "
109 "demand in order to reduce memory use.");
110
111 std::vector<std::string> converterType{"Default", "Indexed"};
112
113 auto loadTypeValidator = std::make_shared<StringListValidator>(converterType);
114 declareProperty("ConverterType", "Default", loadTypeValidator,
115 "[Default, Indexed], indexed is the experimental type that "
116 "can speedup the conversion process"
117 "for the big files using the indexing.");
118}
119//----------------------------------------------------------------------------------------------
120
121const std::string ConvertToMD::name() const { return "ConvertToMD"; }
122
123int ConvertToMD::version() const { return 1; }
124
125std::map<std::string, std::string> ConvertToMD::validateInputs() {
126 std::map<std::string, std::string> result;
127
128 const std::string treeBuilderType = this->getProperty("ConverterType");
129 const bool topLevelSplittingChecked = this->getProperty("TopLevelSplitting");
130 std::vector<int> split_into = this->getProperty("SplitInto");
131 const std::string filename = this->getProperty("Filename");
132 const bool fileBackEnd = this->getProperty("FileBackEnd");
133 const bool useLogTimes = this->getProperty("UseLogTimes");
134
135 if (fileBackEnd && filename.empty()) {
136 result["Filename"] = "Filename must be given if FileBackEnd is required.";
137 }
138
139 if (treeBuilderType.find("Indexed") != std::string::npos) {
140 if (fileBackEnd)
141 result["ConverterType"] += "No file back end implemented "
142 "for indexed version of algorithm. ";
143 if (topLevelSplittingChecked)
144 result["ConverterType"] += "The usage of top level splitting is "
145 "not possible for indexed version of algorithm. ";
146
147 bool validSplitInfo = ConvToMDEventsWSIndexing::isSplitValid(split_into);
148 if (!validSplitInfo)
149 result["ConverterType"] += "The split parameter should be the same for"
150 " all dimensions and be equal the power of 2"
151 " (2 ,4, 8, 16,..) for indexed version of algorithm. ";
152 }
153
154 std::vector<double> minVals = this->getProperty("MinValues");
155 std::vector<double> maxVals = this->getProperty("MaxValues");
156
157 if (minVals.size() != maxVals.size()) {
158 std::stringstream msg;
159 msg << "Rank of MinValues != MaxValues (" << minVals.size() << "!=" << maxVals.size() << ")";
160 result["MinValues"] = msg.str();
161 result["MaxValues"] = msg.str();
162 } else {
163 std::stringstream msg;
164
165 size_t rank = minVals.size();
166 for (size_t i = 0; i < rank; ++i) {
167 if (minVals[i] >= maxVals[i]) {
168 if (msg.str().empty())
169 msg << "max not bigger than min ";
170 else
171 msg << ", ";
172 msg << "at index=" << (i + 1) << " (" << minVals[i] << ">=" << maxVals[i] << ")";
173 }
174 }
175
176 if (!msg.str().empty()) {
177 result["MinValues"] = msg.str();
178 result["MaxValues"] = msg.str();
179 }
180 }
181
182 if (useLogTimes) {
183 API::MatrixWorkspace_const_sptr inWS = this->getProperty("InputWorkspace");
184 const auto evWs = std::dynamic_pointer_cast<const DataObjects::EventWorkspace>(inWS);
185 if (!evWs) {
186 result["UseLogTimes"] = "UseLogTimes requires the input to be an EventWorkspace.";
187 }
188 }
189
190 return result;
191}
192
193//----------------------------------------------------------------------------------------------
194/* Execute the algorithm. */
196 // initiate class which would deal with any dimension workspaces requested by
197 // algorithm parameters
198 if (!m_OutWSWrapper)
199 m_OutWSWrapper = std::make_shared<MDEventWSWrapper>();
200
201 // -------- get Input workspace
202 m_InWS2D = getProperty("InputWorkspace");
203
204 const std::string out_filename = this->getProperty("Filename");
205 const bool fileBackEnd = this->getProperty("FileBackEnd");
206
207 // get the output workspace
208 API::IMDEventWorkspace_sptr spws = getProperty("OutputWorkspace");
209
210 // Collect and Analyze the requests to the job, specified by the input
211 // parameters:
212 // a) Q selector:
213 std::string QModReq = getProperty("QDimensions");
214 // b) the energy exchange mode
215 std::string dEModReq = getProperty("dEAnalysisMode");
216 // c) other dim property;
217 std::vector<std::string> otherDimNames = getProperty("OtherDimensions");
218 // d) The output dimensions in the Q3D mode, processed together with
219 // QConversionScales
220 std::string QFrame = getProperty("Q3DFrames");
221 // e) part of the procedure, specifying the target dimensions units. Currently
222 // only Q3D target units can be converted to different flavors of hkl
223 std::string convertTo_ = getProperty("QConversionScales");
224
225 // get the min and max values for the dimensions from the input properties
226 std::vector<double> dimMin = getProperty("MinValues");
227 std::vector<double> dimMax = getProperty("MaxValues");
228
229 // Sanity check some options
230 if (QModReq != MDTransfQ3D().transfID()) {
231 MDWSTransform transform;
232 const std::string autoSelect = transform.getTargetFrames()[CnvrtToMD::AutoSelect];
233 if (QFrame != autoSelect) {
234 g_log.warning("Q3DFrames value ignored with QDimensions != " + MDTransfQ3D().transfID());
235 QFrame = autoSelect;
236 }
237 const std::string noScaling = transform.getQScalings()[CnvrtToMD::NoScaling];
238 if (convertTo_ != noScaling) {
239 g_log.warning("QConversionScales value ignored with QDimensions != " + MDTransfQ3D().transfID());
240 convertTo_ = noScaling;
241 }
242 }
243
244 // Build the target ws description as function of the input & output ws and
245 // the parameters, supplied to the algorithm
246 MDWSDescription targWSDescr;
247 // get workspace parameters and build target workspace description, report if
248 // there is need to build new target MD workspace
249 bool createNewTargetWs =
250 buildTargetWSDescription(spws, QModReq, dEModReq, otherDimNames, dimMin, dimMax, QFrame, convertTo_, targWSDescr);
251
252 // create and initiate new workspace or set up existing workspace as a target.
253 if (createNewTargetWs) // create new
254 spws = this->createNewMDWorkspace(targWSDescr, fileBackEnd, out_filename);
255 else // setup existing MD workspace as workspace target.
256 m_OutWSWrapper->setMDWS(spws);
257
258 // pre-process detectors;
259 targWSDescr.m_PreprDetTable = this->preprocessDetectorsPositions(m_InWS2D, dEModReq, getProperty("UpdateMasks"),
260 std::string(getProperty("PreprocDetectorsWS")));
261
265 addExperimentInfo(spws, targWSDescr);
266 // get pointer to appropriate ConverttToMD plugin from the CovertToMD plugins
267 // factory, (will throw if logic is wrong and ChildAlgorithm is not found
268 // among existing)
271 ConvToMDSelector AlgoSelector(convType);
272 this->m_Convertor = AlgoSelector.convSelector(m_InWS2D, this->m_Convertor);
273
274 bool ignoreZeros = getProperty("IgnoreZeroSignals");
275 bool useLogTimes = getProperty("UseLogTimes");
276 // initiate conversion and estimate amount of job to do
277 size_t n_steps = this->m_Convertor->initialize(targWSDescr, m_OutWSWrapper, ignoreZeros, useLogTimes);
278
279 // copy the metadata, necessary for resolution corrections
280 copyMetaData(spws);
281
282 // progress reporter
283 m_Progress.reset(new API::Progress(this, 0.0, 1.0, n_steps));
284
285 g_log.information() << " conversion started\n";
286 // DO THE JOB:
287 this->m_Convertor->runConversion(m_Progress.get());
288
289 // Set the normalization of the event workspace
290 m_Convertor->setDisplayNormalization(spws, m_InWS2D);
291
292 if (fileBackEnd) {
293 auto savemd = this->createChildAlgorithm("SaveMD");
294 savemd->setProperty("InputWorkspace", spws);
295 savemd->setPropertyValue("Filename", out_filename);
296 savemd->setProperty("UpdateFileBackEnd", true);
297 savemd->setProperty("MakeFileBacked", false);
298 savemd->executeAsChildAlg();
299 }
300
301 // JOB COMPLETED:
302 setProperty("OutputWorkspace", std::dynamic_pointer_cast<IMDEventWorkspace>(spws));
303 // free the algorithm from the responsibility for the target workspace to
304 // allow it to be deleted if necessary
305 m_OutWSWrapper->releaseWorkspace();
306 // free up the sp to the input workspace, which would be deleted if nobody
307 // needs it any more;
308 m_InWS2D.reset();
309}
318 // Copy ExperimentInfo (instrument, run, sample) to the output WS
319 API::ExperimentInfo_sptr ei(m_InWS2D->cloneExperimentInfo());
320
321 ei->mutableRun().addProperty("RUBW_MATRIX", targWSDescr.m_Wtransf.getVector(), true);
322 ei->mutableRun().addProperty("W_MATRIX", targWSDescr.getPropertyValueAsType<std::vector<double>>("W_MATRIX"), true);
323
324 // associated experiment-info index as the number of experiment into merged within this run. It is
325 // possible to interpret it differently
326 // and should never expect it to start with 0 (for first experiment info)
327 uint16_t expInfoIndex = mdEventWS->addExperimentInfo(ei);
328
329 // add run-index to the target workspace description for further usage as the
330 // identifier for the events, which come from this run.
331 targWSDescr.addProperty("EXP_INFO_INDEX", expInfoIndex, true);
332}
333
342
343 // found detector which is not a monitor to get proper bin boundaries.
344 size_t spectra_index(0);
345 bool detector_found(false);
346 const auto &spectrumInfo = m_InWS2D->spectrumInfo();
347 for (size_t i = 0; i < m_InWS2D->getNumberHistograms(); ++i) {
348 if (spectrumInfo.hasDetectors(i) && !spectrumInfo.isMonitor(i)) {
349 spectra_index = i;
350 detector_found = true;
351 g_log.debug() << "Using spectra N " << i
352 << " as the source of the bin "
353 "boundaries for the resolution corrections \n";
354 break;
355 }
356 }
357 if (!detector_found) {
358 g_log.information() << "No spectra in the workspace have detectors associated "
359 "with them. Storing bin boundaries from first spectrum for"
360 "resolution calculation\n";
361 }
362
363 // retrieve representative bin boundaries
364 auto binBoundaries = m_InWS2D->x(spectra_index);
365
366 // check if the boundaries transformation is necessary
367 if (m_Convertor->getUnitConversionHelper().isUnitConverted()) {
368
369 if (!dynamic_cast<DataObjects::EventWorkspace *>(m_InWS2D.get())) {
370 g_log.information() << " ConvertToMD converts input workspace units, but "
371 "the bin boundaries are copied from the first "
372 "workspace spectra. The resolution estimates can "
373 "be incorrect if unit conversion depends on "
374 "spectra number.\n";
375
376 UnitsConversionHelper &unitConv = m_Convertor->getUnitConversionHelper();
377 unitConv.updateConversion(spectra_index);
378 std::transform(binBoundaries.cbegin(), binBoundaries.cend(), binBoundaries.begin(),
379 [&unitConv](const auto &binBoundary) { return unitConv.convertUnits(binBoundary); });
380 }
381 // sort bin boundaries in case if unit transformation have swapped them.
382 if (binBoundaries[0] > binBoundaries.back()) {
383 g_log.information() << "Bin boundaries are not arranged monotonously. "
384 "Sorting performed\n";
385 std::sort(binBoundaries.begin(), binBoundaries.end());
386 }
387 }
388
389 // The last experiment info should always be the one that refers
390 // to latest converting workspace. All others should have had this
391 // information set already
392 uint16_t nexpts = mdEventWS->getNumExperimentInfo();
393 if (nexpts > 0) {
394 ExperimentInfo_sptr expt = mdEventWS->getExperimentInfo(static_cast<uint16_t>(nexpts - 1));
395 expt->mutableRun().storeHistogramBinBoundaries(binBoundaries.rawData());
396 }
397}
398
418bool ConvertToMD::buildTargetWSDescription(const API::IMDEventWorkspace_sptr &spws, const std::string &QModReq,
419 const std::string &dEModReq, const std::vector<std::string> &otherDimNames,
420 std::vector<double> &dimMin, std::vector<double> &dimMax,
421 const std::string &QFrame, const std::string &convertTo_,
422 MDAlgorithms::MDWSDescription &targWSDescr) {
423 // ------- Is there need to create new output workspace?
424 bool createNewTargetWs = doWeNeedNewTargetWorkspace(spws);
425 std::vector<int> split_into;
426
427 if (createNewTargetWs) {
428 targWSDescr.m_buildingNewWorkspace = true;
429 // find min-max dimensions values -- either take them from input parameters
430 // or identify the defaults if input parameters are not defined
431 this->findMinMax(m_InWS2D, QModReq, dEModReq, QFrame, convertTo_, otherDimNames, dimMin, dimMax);
432 // set number of bins each dimension split into.
433 split_into = this->getProperty("SplitInto");
434 } else // get min/max from existing MD workspace ignoring input min/max values
435 {
436 targWSDescr.m_buildingNewWorkspace = false;
437 size_t NDims = spws->getNumDims();
438 dimMin.resize(NDims);
439 dimMax.resize(NDims);
440 split_into.resize(NDims);
441 for (size_t i = 0; i < NDims; i++) {
442 const Geometry::IMDDimension *pDim = spws->getDimension(i).get();
443 dimMin[i] = pDim->getMinimum();
444 dimMax[i] = pDim->getMaximum();
445 // number of dimension
446 split_into[i] = static_cast<int>(pDim->getNBins());
447 }
448 }
449
450 // verify that the number min/max values is equivalent to the number of
451 // dimensions defined by properties and min is less max
452 targWSDescr.setMinMax(dimMin, dimMax);
453 targWSDescr.buildFromMatrixWS(m_InWS2D, QModReq, dEModReq, otherDimNames);
454 targWSDescr.setNumBins(split_into);
455
456 bool LorentzCorrections = getProperty("LorentzCorrection");
457 targWSDescr.setLorentsCorr(LorentzCorrections);
458
459 double m_AbsMin = getProperty("AbsMinQ");
460 targWSDescr.setAbsMin(m_AbsMin);
461
462 // Set optional projections for Q3D mode
464 if (QModReq == MDTransfQ3D().transfID()) {
465 try {
466 // otherwise input uv are ignored -> later it can be modified to set ub
467 // matrix if no given, but this may over-complicate things.
468 MsliceProj.setUVvectors(getProperty("UProj"), getProperty("VProj"), getProperty("WProj"));
469 } catch (std::invalid_argument &) {
470 g_log.warning() << "The projections are coplanar. Will use defaults "
471 "[1,0,0],[0,1,0] and [0,0,1]\n";
472 }
473 } else {
474 auto warnIfSet = [this](const std::string &propName) {
475 Property *prop = this->getProperty(propName);
476 if (!prop->isDefault()) {
477 g_log.warning(propName + " value ignored with QDimensions != " + MDTransfQ3D().transfID());
478 }
479 };
480 for (const auto &name : {"UProj", "VProj", "WProj"}) {
481 warnIfSet(name);
482 }
483 }
484
485 if (createNewTargetWs) {
486
487 // check if we are working in powder mode
488 // set up target coordinate system and identify/set the (multi) dimension's
489 // names to use
490 targWSDescr.m_RotMatrix = MsliceProj.getTransfMatrix(targWSDescr, QFrame, convertTo_);
491 } else // user input is mainly ignored and everything is in old MD workspace
492 {
493 // dimensions are already build, so build MDWS description from existing
494 // workspace
496 oldWSDescr.buildFromMDWS(spws);
497
498 // some conversion parameters can not be defined by the target workspace.
499 // They have to be retrieved from the input workspace
500 // and derived from input parameters.
501 oldWSDescr.setUpMissingParameters(targWSDescr);
502 // set up target coordinate system and the dimension names/units
503 oldWSDescr.m_RotMatrix = MsliceProj.getTransfMatrix(oldWSDescr, QFrame, convertTo_);
504
505 // check inconsistencies, if the existing workspace can be used as target
506 // workspace.
507 oldWSDescr.checkWSCorresponsMDWorkspace(targWSDescr);
508 // reset new ws description name
509 targWSDescr = oldWSDescr;
510 }
511 return createNewTargetWs;
512}
513
523 const bool filebackend, const std::string &filename) {
524 // create new md workspace and set internal shared pointer of m_OutWSWrapper
525 // to this workspace
526 API::IMDEventWorkspace_sptr spws = m_OutWSWrapper->createEmptyMDWS(targWSDescr);
527 if (!spws) {
528 g_log.error() << "can not create target event workspace with :" << targWSDescr.nDimensions() << " dimensions\n";
529 throw(std::invalid_argument("can not create target workspace"));
530 }
531 // Build up the box controller
532 Mantid::API::BoxController_sptr bc = m_OutWSWrapper->pWorkspace()->getBoxController();
533 // Build up the box controller, using the properties in
534 // BoxControllerSettingsAlgorithm
535 this->setBoxController(bc, m_InWS2D->getInstrument());
536 if (filebackend) {
537 setupFileBackend(filename, m_OutWSWrapper->pWorkspace());
538 }
539
540 // Check if the user want sto force a top level split or not
541 bool topLevelSplittingChecked = this->getProperty("TopLevelSplitting");
542
543 if (topLevelSplittingChecked) {
544 // Perform initial split with the forced settings
546 }
547
548 // split boxes;
549 spws->splitBox();
550
551 // Do we split more due to MinRecursionDepth?
552 int minDepth = this->getProperty("MinRecursionDepth");
553 int maxDepth = this->getProperty("MaxRecursionDepth");
554 if (minDepth > maxDepth)
555 throw std::invalid_argument("MinRecursionDepth must be >= MaxRecursionDepth ");
556 spws->setMinRecursionDepth(size_t(minDepth));
557
558 return spws;
559}
560
567 const size_t topLevelSplitSetting = 50;
568 const size_t dimCutoff = 4;
569
570 // Set the Top level splitting
571 for (size_t dim = 0; dim < bc->getNDims(); dim++) {
572 if (dim < dimCutoff) {
573 bc->setSplitTopInto(dim, topLevelSplitSetting);
574 } else {
575 bc->setSplitTopInto(dim, bc->getSplitInto(dim));
576 }
577 }
578}
579
588
589 bool createNewWs(false);
590 if (!spws) {
591 createNewWs = true;
592 } else {
593 bool shouldOverwrite = getProperty("OverwriteExisting");
594 createNewWs = shouldOverwrite;
595 }
596 return createNewWs;
597}
598
616void ConvertToMD::findMinMax(const Mantid::API::MatrixWorkspace_sptr &inWS, const std::string &QMode,
617 const std::string &dEMode, const std::string &QFrame, const std::string &ConvertTo,
618 const std::vector<std::string> &otherDim, std::vector<double> &minVal,
619 std::vector<double> &maxVal) {
620
621 // get raw pointer to Q-transformation (do not delete this pointer, it hold by
622 // MDTransfFatctory!)
623 MDTransfInterface *pQtransf = MDTransfFactory::Instance().create(QMode).get();
624 // get number of dimensions this Q transformation generates from the
625 // workspace.
626 auto iEmode = Kernel::DeltaEMode::fromString(dEMode);
627 // get total number of dimensions the workspace would have.
628 unsigned int nMatrixDim = pQtransf->getNMatrixDimensions(iEmode, inWS);
629 // total number of dimensions
630 size_t nDim = nMatrixDim + otherDim.size();
631
632 // probably already have well defined min-max values, so no point of
633 // pre-calculating them
634 bool wellDefined(true);
635 if ((nDim == minVal.size()) && (minVal.size() == maxVal.size())) {
636 // are they indeed well defined?
637 for (size_t i = 0; i < minVal.size(); i++) {
638 if (minVal[i] >= maxVal[i]) // no it is ill defined
639 {
640 g_log.information() << " Min Value: " << minVal[i] << " for dimension N: " << i
641 << " equal or exceeds max value:" << maxVal[i] << '\n';
642 wellDefined = false;
643 break;
644 }
645 }
646 if (wellDefined)
647 return;
648 }
649
650 // we need to identify min-max values by themselves
651
652 Mantid::API::Algorithm_sptr childAlg = createChildAlgorithm("ConvertToMDMinMaxLocal");
653 if (!childAlg)
654 throw(std::runtime_error("Can not create child ChildAlgorithm to found min/max values"));
655
656 childAlg->setProperty("InputWorkspace", inWS);
657 childAlg->setProperty("QDimensions", QMode);
658 childAlg->setProperty("dEAnalysisMode", dEMode);
659 childAlg->setProperty("Q3DFrames", QFrame);
660 childAlg->setProperty("OtherDimensions", otherDim);
661 childAlg->setProperty("QConversionScales", ConvertTo);
662 childAlg->setProperty("PreprocDetectorsWS", std::string(getProperty("PreprocDetectorsWS")));
663 childAlg->execute();
664 if (!childAlg->isExecuted())
665 throw(std::runtime_error("Can not properly execute child algorithm to find "
666 "min/max workspace values"));
667
668 minVal = childAlg->getProperty("MinValues");
669 maxVal = childAlg->getProperty("MaxValues");
670
671 // if some min-max values for dimensions produce ws with 0 width in this
672 // direction, change it to have some width;
673 for (unsigned int i = 0; i < nDim; i++) {
674 if (minVal[i] >= maxVal[i]) {
675 g_log.debug() << "identified min-max values for dimension N: " << i
676 << " are equal. Modifying min-max value to produce "
677 "dimension with 0.2*dimValue width\n";
678 if (minVal[i] > 0) {
679 minVal[i] *= 0.9;
680 maxVal[i] *= 1.1;
681 } else if (minVal[i] == 0) {
682 minVal[i] = -0.1;
683 maxVal[i] = 0.1;
684 } else {
685 minVal[i] *= 1.1;
686 maxVal[i] *= 0.9;
687 }
688 } else {
689 MDHistoDimensionBuilder::resizeToFitMDBox(minVal[i], maxVal[i]);
690 }
691 }
692
693 if (!wellDefined)
694 return;
695
696 // if only min or only max limits are defined and are well defined workspace,
697 // the algorithm will use these limits
698 std::vector<double> minAlgValues = this->getProperty("MinValues");
699 std::vector<double> maxAlgValues = this->getProperty("MaxValues");
700 bool allMinDefined = (minAlgValues.size() == nDim);
701 bool allMaxDefined = (maxAlgValues.size() == nDim);
702 if (allMinDefined || allMaxDefined) {
703 for (size_t i = 0; i < nDim; i++) {
704 if (allMinDefined)
705 minVal[i] = minAlgValues[i];
706 if (allMaxDefined)
707 maxVal[i] = maxAlgValues[i];
708 }
709 }
710}
711
718void ConvertToMD::setupFileBackend(const std::string &filebackPath,
719 const Mantid::API::IMDEventWorkspace_sptr &outputWS) {
721 auto savemd = this->createChildAlgorithm("SaveMD", 0.01, 0.05, true);
722 savemd->setProperty("InputWorkspace", outputWS);
723 savemd->setPropertyValue("Filename", filebackPath);
724 savemd->setProperty("UpdateFileBackEnd", false);
725 savemd->setProperty("MakeFileBacked", false);
726 savemd->executeAsChildAlg();
727
728 // create file-backed box controller
729 auto boxControllerMem = outputWS->getBoxController();
730 auto boxControllerIO = std::make_shared<BoxControllerNeXusIO>(boxControllerMem.get());
731 boxControllerMem->setFileBacked(boxControllerIO, filebackPath);
732 outputWS->setFileBacked();
733 boxControllerMem->getFileIO()->setWriteBufferSize(1000000);
734}
735
736} // namespace Mantid::MDAlgorithms
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:542
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
virtual std::shared_ptr< Algorithm > createChildAlgorithm(const std::string &name, const double startProgress=-1., const double endProgress=-1., const bool enableLogging=true, const int &version=-1)
Create a Child Algorithm.
void setBoxController(const Mantid::API::BoxController_sptr &bc, const Mantid::Geometry::Instrument_const_sptr &instrument)
Set the settings in the given box controller.
@ OptionalSave
to specify a file to write to but an empty string is
void addProperty(Kernel::Property *prop, bool overwrite=false)
Add data to the object in the form of a property.
Definition LogManager.h:90
HeldType getPropertyValueAsType(const std::string &name) const
Get the value of a property as the given TYPE.
Helper class for reporting progress from algorithms.
Definition Progress.h:25
A property class for workspaces.
The class responsible for saving events into nexus file using generic box controller interface Expect...
This class is intended to fulfill the design specified in <https://github.com/mantidproject/documents...
The class describes one dimension of multidimensional dataset representing an orthogonal dimension an...
virtual coord_t getMaximum() const =0
virtual coord_t getMinimum() const =0
virtual size_t getNBins() const =0
static void resizeToFitMDBox(CoordT &min, CoordT &max)
Push the min/max values out by a defined amount.
Support for a property that holds an array of values.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void debug(const std::string &msg)
Logs at debug level.
Definition Logger.cpp:145
void error(const std::string &msg)
Logs at error level.
Definition Logger.cpp:108
void warning(const std::string &msg)
Logs at warning level.
Definition Logger.cpp:117
void information(const std::string &msg)
Logs at information level.
Definition Logger.cpp:136
std::vector< T > getVector() const
Definition Matrix.cpp:77
The concrete, templated class for properties.
Base class for properties.
Definition Property.h:94
virtual bool isDefault() const =0
Overriden function that returns if property has the same value that it was initialised with,...
static bool isSplitValid(const std::vector< T > &split_into)
small class to select proper solver as function of the workspace kind and (possibly,...
std::shared_ptr< ConvToMDBase > convSelector(const API::MatrixWorkspace_sptr &inputWS, std::shared_ptr< ConvToMDBase > &currentSolver) const
function which selects the convertor depending on workspace type and (possibly, in a future) some wor...
std::shared_ptr< MDAlgorithms::ConvToMDBase > m_Convertor
pointer to the class, which does the particular conversion
DataObjects::TableWorkspace_const_sptr preprocessDetectorsPositions(const Mantid::API::MatrixWorkspace_const_sptr &InWS2D, const std::string &dEModeRequested, bool updateMasks, const std::string &OutWSName)
The method responsible for analyzing input workspace parameters and preprocessing detectors positions...
void init() override
Initialize the algorithm's properties.
ConvertToMD : Transform a workspace into MD workspace with components defined by user.
Definition ConvertToMD.h:32
int version() const override
Algorithm's version for identification.
void findMinMax(const Mantid::API::MatrixWorkspace_sptr &inWS, const std::string &QMode, const std::string &dEMode, const std::string &QFrame, const std::string &ConvertTo, const std::vector< std::string > &otherDim, std::vector< double > &minVal, std::vector< double > &maxVal)
Method takes min-max values from algorithm parameters if they are present or calculates default min-m...
bool doWeNeedNewTargetWorkspace(const API::IMDEventWorkspace_sptr &spws)
Check if target workspace new or existing one and we need to create new workspace.
Mantid::API::MatrixWorkspace_sptr m_InWS2D
pointer to the input workspace;
Definition ConvertToMD.h:63
void setupFileBackend(const std::string &filebackPath, const API::IMDEventWorkspace_sptr &outputWS)
Setup the filebackend for the output workspace.
void addExperimentInfo(API::IMDEventWorkspace_sptr &mdEventWS, MDAlgorithms::MDWSDescription &targWSDescr) const
par of store metadata routine which generate metadata necessary for initializing ConvertToMD plugin
const std::string name() const override
Algorithm's name for identification.
boost::scoped_ptr< API::Progress > m_Progress
progress reporter
Definition ConvertToMD.h:56
std::shared_ptr< MDAlgorithms::MDEventWSWrapper > m_OutWSWrapper
Definition ConvertToMD.h:66
void copyMetaData(API::IMDEventWorkspace_sptr &mdEventWS) const
Store metadata and set some metadata, needed for plugin to run on the target workspace description.
void exec() override
Virtual method - must be overridden by concrete algorithm.
void setupTopLevelSplitting(const Mantid::API::BoxController_sptr &bc)
Sets up the top level splitting, i.e. of level 0, for the box controller.
API::IMDEventWorkspace_sptr createNewMDWorkspace(const MDAlgorithms::MDWSDescription &targWSDescr, const bool filebackend, const std::string &filename)
Create new MD workspace using existing parameters for algorithm.
std::map< std::string, std::string > validateInputs() override
Perform validation of ALL the input properties of the algorithm.
bool buildTargetWSDescription(const API::IMDEventWorkspace_sptr &spws, const std::string &QModReq, const std::string &dEModReq, const std::vector< std::string > &otherDimNames, std::vector< double > &dimMin, std::vector< double > &dimMax, const std::string &QFrame, const std::string &convertTo_, MDAlgorithms::MDWSDescription &targWSDescr)
handle the input parameters and build target workspace description as function of input parameters
Interface to set of sub-classes used by ConvertToMD algorithm and responsible for conversion of input...
virtual unsigned int getNMatrixDimensions(Kernel::DeltaEMode::Type mode, API::MatrixWorkspace_const_sptr inWS) const =0
return the number of dimensions, calculated by the transformation from the workspace.
Class responsible for conversion of input workspace data into proper number of output dimensions for ...
Definition MDTransfQ3D.h:28
helper class describes the properties of target MD workspace, which should be obtained as the result ...
void setMinMax(const std::vector< double > &minVal, const std::vector< double > &maxVal)
function sets up min-max values to the dimensions, described by the class
void setUpMissingParameters(const MDWSDescription &SourceMatrWS)
copy some parameters from the input workspace, as target md WS do not have all information about the ...
void setNumBins(const std::vector< int > &nBins_toSplit)
sets number of bins each dimension is split
void buildFromMDWS(const API::IMDEventWorkspace_const_sptr &pWS)
method builds MD Event description from existing MD event workspace
void buildFromMatrixWS(const API::MatrixWorkspace_sptr &pWS, const std::string &QMode, const std::string &dEMode, const std::vector< std::string > &dimPropertyNames=std::vector< std::string >())
method builds MD Event ws description from a matrix workspace and the transformations,...
DataObjects::TableWorkspace_const_sptr m_PreprDetTable
void setLorentsCorr(bool On=false)
do we need to perform Lorentz corrections
void checkWSCorresponsMDWorkspace(const MDWSDescription &NewMDWorkspaceD)
compare two descriptions and select the complimentary result.
std::vector< std::string > getTargetFrames() const
returns the list of possible target frames to convert to
std::vector< double > getTransfMatrix(MDAlgorithms::MDWSDescription &TargWSDescription, const std::string &FrameRequested, const std::string &QScaleRequested) const
method to build the Q-coordinates transformation.
std::vector< std::string > getQScalings() const
return the list of possible scalings for momentums
void setUVvectors(const std::vector< double > &ut, const std::vector< double > &vt, const std::vector< double > &wt)
helper function which verifies if projection vectors are specified and if their values are correct wh...
void updateConversion(size_t i)
Method updates unit conversion given the index of detector parameters in the array of detectors.
std::shared_ptr< IMDEventWorkspace > IMDEventWorkspace_sptr
Shared pointer to Mantid::API::IMDEventWorkspace.
Kernel::Logger g_log("ExperimentInfo")
static logger object
std::shared_ptr< ExperimentInfo > ExperimentInfo_sptr
Shared pointer to ExperimentInfo.
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
std::shared_ptr< BoxController > BoxController_sptr
Shared ptr to BoxController.
std::shared_ptr< Algorithm > Algorithm_sptr
Typedef for a shared pointer to an Algorithm.
Definition Algorithm.h:52
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
static Type fromString(const std::string &modeStr)
Returns the emode from the given string.
@ Input
An input workspace.
Definition Property.h:53
@ Output
An output workspace.
Definition Property.h:54