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
134 if (fileBackEnd && filename.empty()) {
135 result["Filename"] = "Filename must be given if FileBackEnd is required.";
136 }
137
138 if (treeBuilderType.find("Indexed") != std::string::npos) {
139 if (fileBackEnd)
140 result["ConverterType"] += "No file back end implemented "
141 "for indexed version of algorithm. ";
142
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 return result;
183}
184
185//----------------------------------------------------------------------------------------------
186/* Execute the algorithm. */
188 // initiate class which would deal with any dimension workspaces requested by
189 // algorithm parameters
190 if (!m_OutWSWrapper)
191 m_OutWSWrapper = std::make_shared<MDEventWSWrapper>();
192
193 // -------- get Input workspace
194 m_InWS2D = getProperty("InputWorkspace");
195
196 const std::string out_filename = this->getProperty("Filename");
197 const bool fileBackEnd = this->getProperty("FileBackEnd");
198
199 // get the output workspace
200 API::IMDEventWorkspace_sptr spws = getProperty("OutputWorkspace");
201
202 // Collect and Analyze the requests to the job, specified by the input
203 // parameters:
204 // a) Q selector:
205 std::string QModReq = getProperty("QDimensions");
206 // b) the energy exchange mode
207 std::string dEModReq = getProperty("dEAnalysisMode");
208 // c) other dim property;
209 std::vector<std::string> otherDimNames = getProperty("OtherDimensions");
210 // d) The output dimensions in the Q3D mode, processed together with
211 // QConversionScales
212 std::string QFrame = getProperty("Q3DFrames");
213 // e) part of the procedure, specifying the target dimensions units. Currently
214 // only Q3D target units can be converted to different flavors of hkl
215 std::string convertTo_ = getProperty("QConversionScales");
216
217 // get the min and max values for the dimensions from the input properties
218 std::vector<double> dimMin = getProperty("MinValues");
219 std::vector<double> dimMax = getProperty("MaxValues");
220
221 // Sanity check some options
222 if (QModReq != MDTransfQ3D().transfID()) {
223 MDWSTransform transform;
224 const std::string autoSelect = transform.getTargetFrames()[CnvrtToMD::AutoSelect];
225 if (QFrame != autoSelect) {
226 g_log.warning("Q3DFrames value ignored with QDimensions != " + MDTransfQ3D().transfID());
227 QFrame = autoSelect;
228 }
229 const std::string noScaling = transform.getQScalings()[CnvrtToMD::NoScaling];
230 if (convertTo_ != noScaling) {
231 g_log.warning("QConversionScales value ignored with QDimensions != " + MDTransfQ3D().transfID());
232 convertTo_ = noScaling;
233 }
234 }
235
236 // Build the target ws description as function of the input & output ws and
237 // the parameters, supplied to the algorithm
238 MDWSDescription targWSDescr;
239 // get workspace parameters and build target workspace description, report if
240 // there is need to build new target MD workspace
241 bool createNewTargetWs =
242 buildTargetWSDescription(spws, QModReq, dEModReq, otherDimNames, dimMin, dimMax, QFrame, convertTo_, targWSDescr);
243
244 // create and initiate new workspace or set up existing workspace as a target.
245 if (createNewTargetWs) // create new
246 spws = this->createNewMDWorkspace(targWSDescr, fileBackEnd, out_filename);
247 else // setup existing MD workspace as workspace target.
248 m_OutWSWrapper->setMDWS(spws);
249
250 // pre-process detectors;
251 targWSDescr.m_PreprDetTable = this->preprocessDetectorsPositions(m_InWS2D, dEModReq, getProperty("UpdateMasks"),
252 std::string(getProperty("PreprocDetectorsWS")));
253
257 addExperimentInfo(spws, targWSDescr);
258 // get pointer to appropriate ConverttToMD plugin from the CovertToMD plugins
259 // factory, (will throw if logic is wrong and ChildAlgorithm is not found
260 // among existing)
263 ConvToMDSelector AlgoSelector(convType);
264 this->m_Convertor = AlgoSelector.convSelector(m_InWS2D, this->m_Convertor);
265
266 bool ignoreZeros = getProperty("IgnoreZeroSignals");
267 // initiate conversion and estimate amount of job to do
268 size_t n_steps = this->m_Convertor->initialize(targWSDescr, m_OutWSWrapper, ignoreZeros);
269
270 // copy the metadata, necessary for resolution corrections
271 copyMetaData(spws);
272
273 // progress reporter
274 m_Progress.reset(new API::Progress(this, 0.0, 1.0, n_steps));
275
276 g_log.information() << " conversion started\n";
277 // DO THE JOB:
278 this->m_Convertor->runConversion(m_Progress.get());
279
280 // Set the normalization of the event workspace
281 m_Convertor->setDisplayNormalization(spws, m_InWS2D);
282
283 if (fileBackEnd) {
284 auto savemd = this->createChildAlgorithm("SaveMD");
285 savemd->setProperty("InputWorkspace", spws);
286 savemd->setPropertyValue("Filename", out_filename);
287 savemd->setProperty("UpdateFileBackEnd", true);
288 savemd->setProperty("MakeFileBacked", false);
289 savemd->executeAsChildAlg();
290 }
291
292 // JOB COMPLETED:
293 setProperty("OutputWorkspace", std::dynamic_pointer_cast<IMDEventWorkspace>(spws));
294 // free the algorithm from the responsibility for the target workspace to
295 // allow it to be deleted if necessary
296 m_OutWSWrapper->releaseWorkspace();
297 // free up the sp to the input workspace, which would be deleted if nobody
298 // needs it any more;
299 m_InWS2D.reset();
300}
312 // Copy ExperimentInfo (instrument, run, sample) to the output WS
313 API::ExperimentInfo_sptr ei(m_InWS2D->cloneExperimentInfo());
314
315 ei->mutableRun().addProperty("RUBW_MATRIX", targWSDescr.m_Wtransf.getVector(), true);
316 ei->mutableRun().addProperty("W_MATRIX", targWSDescr.getPropertyValueAsType<std::vector<double>>("W_MATRIX"), true);
317
318 // associated experiment-info index as the number of experiment into merged within this run. It is
319 // possible to interpret it differently
320 // and should never expect it to start with 0 (for first experiment info)
321 uint16_t expInfoIndex = mdEventWS->addExperimentInfo(ei);
322
323 // add run-index to the target workspace description for further usage as the
324 // identifier for the events, which come from this run.
325 targWSDescr.addProperty("EXP_INFO_INDEX", expInfoIndex, true);
326}
327
336
337 // found detector which is not a monitor to get proper bin boundaries.
338 size_t spectra_index(0);
339 bool detector_found(false);
340 const auto &spectrumInfo = m_InWS2D->spectrumInfo();
341 for (size_t i = 0; i < m_InWS2D->getNumberHistograms(); ++i) {
342 if (spectrumInfo.hasDetectors(i) && !spectrumInfo.isMonitor(i)) {
343 spectra_index = i;
344 detector_found = true;
345 g_log.debug() << "Using spectra N " << i
346 << " as the source of the bin "
347 "boundaries for the resolution corrections \n";
348 break;
349 }
350 }
351 if (!detector_found) {
352 g_log.information() << "No spectra in the workspace have detectors associated "
353 "with them. Storing bin boundaries from first spectrum for"
354 "resolution calculation\n";
355 }
356
357 // retrieve representative bin boundaries
358 auto binBoundaries = m_InWS2D->x(spectra_index);
359
360 // check if the boundaries transformation is necessary
361 if (m_Convertor->getUnitConversionHelper().isUnitConverted()) {
362
363 if (!dynamic_cast<DataObjects::EventWorkspace *>(m_InWS2D.get())) {
364 g_log.information() << " ConvertToMD converts input workspace units, but "
365 "the bin boundaries are copied from the first "
366 "workspace spectra. The resolution estimates can "
367 "be incorrect if unit conversion depends on "
368 "spectra number.\n";
369
370 UnitsConversionHelper &unitConv = m_Convertor->getUnitConversionHelper();
371 unitConv.updateConversion(spectra_index);
372 std::transform(binBoundaries.cbegin(), binBoundaries.cend(), binBoundaries.begin(),
373 [&unitConv](const auto &binBoundary) { return unitConv.convertUnits(binBoundary); });
374 }
375 // sort bin boundaries in case if unit transformation have swapped them.
376 if (binBoundaries[0] > binBoundaries.back()) {
377 g_log.information() << "Bin boundaries are not arranged monotonously. "
378 "Sorting performed\n";
379 std::sort(binBoundaries.begin(), binBoundaries.end());
380 }
381 }
382
383 // The last experiment info should always be the one that refers
384 // to latest converting workspace. All others should have had this
385 // information set already
386 uint16_t nexpts = mdEventWS->getNumExperimentInfo();
387 if (nexpts > 0) {
388 ExperimentInfo_sptr expt = mdEventWS->getExperimentInfo(static_cast<uint16_t>(nexpts - 1));
389 expt->mutableRun().storeHistogramBinBoundaries(binBoundaries.rawData());
390 }
391}
392
412bool ConvertToMD::buildTargetWSDescription(const API::IMDEventWorkspace_sptr &spws, const std::string &QModReq,
413 const std::string &dEModReq, const std::vector<std::string> &otherDimNames,
414 std::vector<double> &dimMin, std::vector<double> &dimMax,
415 const std::string &QFrame, const std::string &convertTo_,
416 MDAlgorithms::MDWSDescription &targWSDescr) {
417 // ------- Is there need to create new output workspace?
418 bool createNewTargetWs = doWeNeedNewTargetWorkspace(spws);
419 std::vector<int> split_into;
420
421 if (createNewTargetWs) {
422 targWSDescr.m_buildingNewWorkspace = true;
423 // find min-max dimensions values -- either take them from input parameters
424 // or identify the defaults if input parameters are not defined
425 this->findMinMax(m_InWS2D, QModReq, dEModReq, QFrame, convertTo_, otherDimNames, dimMin, dimMax);
426 // set number of bins each dimension split into.
427 split_into = this->getProperty("SplitInto");
428 } else // get min/max from existing MD workspace ignoring input min/max values
429 {
430 targWSDescr.m_buildingNewWorkspace = false;
431 size_t NDims = spws->getNumDims();
432 dimMin.resize(NDims);
433 dimMax.resize(NDims);
434 split_into.resize(NDims);
435 for (size_t i = 0; i < NDims; i++) {
436 const Geometry::IMDDimension *pDim = spws->getDimension(i).get();
437 dimMin[i] = pDim->getMinimum();
438 dimMax[i] = pDim->getMaximum();
439 // number of dimension
440 split_into[i] = static_cast<int>(pDim->getNBins());
441 }
442 }
443
444 // verify that the number min/max values is equivalent to the number of
445 // dimensions defined by properties and min is less max
446 targWSDescr.setMinMax(dimMin, dimMax);
447 targWSDescr.buildFromMatrixWS(m_InWS2D, QModReq, dEModReq, otherDimNames);
448 targWSDescr.setNumBins(split_into);
449
450 bool LorentzCorrections = getProperty("LorentzCorrection");
451 targWSDescr.setLorentsCorr(LorentzCorrections);
452
453 double m_AbsMin = getProperty("AbsMinQ");
454 targWSDescr.setAbsMin(m_AbsMin);
455
456 // Set optional projections for Q3D mode
458 if (QModReq == MDTransfQ3D().transfID()) {
459 try {
460 // otherwise input uv are ignored -> later it can be modified to set ub
461 // matrix if no given, but this may over-complicate things.
462 MsliceProj.setUVvectors(getProperty("UProj"), getProperty("VProj"), getProperty("WProj"));
463 } catch (std::invalid_argument &) {
464 g_log.warning() << "The projections are coplanar. Will use defaults "
465 "[1,0,0],[0,1,0] and [0,0,1]\n";
466 }
467 } else {
468 auto warnIfSet = [this](const std::string &propName) {
469 Property *prop = this->getProperty(propName);
470 if (!prop->isDefault()) {
471 g_log.warning(propName + " value ignored with QDimensions != " + MDTransfQ3D().transfID());
472 }
473 };
474 for (const auto &name : {"UProj", "VProj", "WProj"}) {
475 warnIfSet(name);
476 }
477 }
478
479 if (createNewTargetWs) {
480
481 // check if we are working in powder mode
482 // set up target coordinate system and identify/set the (multi) dimension's
483 // names to use
484 targWSDescr.m_RotMatrix = MsliceProj.getTransfMatrix(targWSDescr, QFrame, convertTo_);
485 } else // user input is mainly ignored and everything is in old MD workspace
486 {
487 // dimensions are already build, so build MDWS description from existing
488 // workspace
490 oldWSDescr.buildFromMDWS(spws);
491
492 // some conversion parameters can not be defined by the target workspace.
493 // They have to be retrieved from the input workspace
494 // and derived from input parameters.
495 oldWSDescr.setUpMissingParameters(targWSDescr);
496 // set up target coordinate system and the dimension names/units
497 oldWSDescr.m_RotMatrix = MsliceProj.getTransfMatrix(oldWSDescr, QFrame, convertTo_);
498
499 // check inconsistencies, if the existing workspace can be used as target
500 // workspace.
501 oldWSDescr.checkWSCorresponsMDWorkspace(targWSDescr);
502 // reset new ws description name
503 targWSDescr = oldWSDescr;
504 }
505 return createNewTargetWs;
506}
507
517 const bool filebackend, const std::string &filename) {
518 // create new md workspace and set internal shared pointer of m_OutWSWrapper
519 // to this workspace
520 API::IMDEventWorkspace_sptr spws = m_OutWSWrapper->createEmptyMDWS(targWSDescr);
521 if (!spws) {
522 g_log.error() << "can not create target event workspace with :" << targWSDescr.nDimensions() << " dimensions\n";
523 throw(std::invalid_argument("can not create target workspace"));
524 }
525 // Build up the box controller
526 Mantid::API::BoxController_sptr bc = m_OutWSWrapper->pWorkspace()->getBoxController();
527 // Build up the box controller, using the properties in
528 // BoxControllerSettingsAlgorithm
529 this->setBoxController(bc, m_InWS2D->getInstrument());
530 if (filebackend) {
531 setupFileBackend(filename, m_OutWSWrapper->pWorkspace());
532 }
533
534 // Check if the user want sto force a top level split or not
535 bool topLevelSplittingChecked = this->getProperty("TopLevelSplitting");
536
537 if (topLevelSplittingChecked) {
538 // Perform initial split with the forced settings
540 }
541
542 // split boxes;
543 spws->splitBox();
544
545 // Do we split more due to MinRecursionDepth?
546 int minDepth = this->getProperty("MinRecursionDepth");
547 int maxDepth = this->getProperty("MaxRecursionDepth");
548 if (minDepth > maxDepth)
549 throw std::invalid_argument("MinRecursionDepth must be >= MaxRecursionDepth ");
550 spws->setMinRecursionDepth(size_t(minDepth));
551
552 return spws;
553}
554
561 const size_t topLevelSplitSetting = 50;
562 const size_t dimCutoff = 4;
563
564 // Set the Top level splitting
565 for (size_t dim = 0; dim < bc->getNDims(); dim++) {
566 if (dim < dimCutoff) {
567 bc->setSplitTopInto(dim, topLevelSplitSetting);
568 } else {
569 bc->setSplitTopInto(dim, bc->getSplitInto(dim));
570 }
571 }
572}
573
582
583 bool createNewWs(false);
584 if (!spws) {
585 createNewWs = true;
586 } else {
587 bool shouldOverwrite = getProperty("OverwriteExisting");
588 createNewWs = shouldOverwrite;
589 }
590 return createNewWs;
591}
592
610void ConvertToMD::findMinMax(const Mantid::API::MatrixWorkspace_sptr &inWS, const std::string &QMode,
611 const std::string &dEMode, const std::string &QFrame, const std::string &ConvertTo,
612 const std::vector<std::string> &otherDim, std::vector<double> &minVal,
613 std::vector<double> &maxVal) {
614
615 // get raw pointer to Q-transformation (do not delete this pointer, it hold by
616 // MDTransfFatctory!)
617 MDTransfInterface *pQtransf = MDTransfFactory::Instance().create(QMode).get();
618 // get number of dimensions this Q transformation generates from the
619 // workspace.
620 auto iEmode = Kernel::DeltaEMode::fromString(dEMode);
621 // get total number of dimensions the workspace would have.
622 unsigned int nMatrixDim = pQtransf->getNMatrixDimensions(iEmode, inWS);
623 // total number of dimensions
624 size_t nDim = nMatrixDim + otherDim.size();
625
626 // probably already have well defined min-max values, so no point of
627 // pre-calculating them
628 bool wellDefined(true);
629 if ((nDim == minVal.size()) && (minVal.size() == maxVal.size())) {
630 // are they indeed well defined?
631 for (size_t i = 0; i < minVal.size(); i++) {
632 if (minVal[i] >= maxVal[i]) // no it is ill defined
633 {
634 g_log.information() << " Min Value: " << minVal[i] << " for dimension N: " << i
635 << " equal or exceeds max value:" << maxVal[i] << '\n';
636 wellDefined = false;
637 break;
638 }
639 }
640 if (wellDefined)
641 return;
642 }
643
644 // we need to identify min-max values by themselves
645
646 Mantid::API::Algorithm_sptr childAlg = createChildAlgorithm("ConvertToMDMinMaxLocal");
647 if (!childAlg)
648 throw(std::runtime_error("Can not create child ChildAlgorithm to found min/max values"));
649
650 childAlg->setProperty("InputWorkspace", inWS);
651 childAlg->setProperty("QDimensions", QMode);
652 childAlg->setProperty("dEAnalysisMode", dEMode);
653 childAlg->setProperty("Q3DFrames", QFrame);
654 childAlg->setProperty("OtherDimensions", otherDim);
655 childAlg->setProperty("QConversionScales", ConvertTo);
656 childAlg->setProperty("PreprocDetectorsWS", std::string(getProperty("PreprocDetectorsWS")));
657 childAlg->execute();
658 if (!childAlg->isExecuted())
659 throw(std::runtime_error("Can not properly execute child algorithm to find "
660 "min/max workspace values"));
661
662 minVal = childAlg->getProperty("MinValues");
663 maxVal = childAlg->getProperty("MaxValues");
664
665 // if some min-max values for dimensions produce ws with 0 width in this
666 // direction, change it to have some width;
667 for (unsigned int i = 0; i < nDim; i++) {
668 if (minVal[i] >= maxVal[i]) {
669 g_log.debug() << "identified min-max values for dimension N: " << i
670 << " are equal. Modifying min-max value to produce "
671 "dimension with 0.2*dimValue width\n";
672 if (minVal[i] > 0) {
673 minVal[i] *= 0.9;
674 maxVal[i] *= 1.1;
675 } else if (minVal[i] == 0) {
676 minVal[i] = -0.1;
677 maxVal[i] = 0.1;
678 } else {
679 minVal[i] *= 1.1;
680 maxVal[i] *= 0.9;
681 }
682 } else {
683 MDHistoDimensionBuilder::resizeToFitMDBox(minVal[i], maxVal[i]);
684 }
685 }
686
687 if (!wellDefined)
688 return;
689
690 // if only min or only max limits are defined and are well defined workspace,
691 // the algorithm will use these limits
692 std::vector<double> minAlgValues = this->getProperty("MinValues");
693 std::vector<double> maxAlgValues = this->getProperty("MaxValues");
694 bool allMinDefined = (minAlgValues.size() == nDim);
695 bool allMaxDefined = (maxAlgValues.size() == nDim);
696 if (allMinDefined || allMaxDefined) {
697 for (size_t i = 0; i < nDim; i++) {
698 if (allMinDefined)
699 minVal[i] = minAlgValues[i];
700 if (allMaxDefined)
701 maxVal[i] = maxAlgValues[i];
702 }
703 }
704}
705
712void ConvertToMD::setupFileBackend(const std::string &filebackPath,
713 const Mantid::API::IMDEventWorkspace_sptr &outputWS) {
715 auto savemd = this->createChildAlgorithm("SaveMD", 0.01, 0.05, true);
716 savemd->setProperty("InputWorkspace", outputWS);
717 savemd->setPropertyValue("Filename", filebackPath);
718 savemd->setProperty("UpdateFileBackEnd", false);
719 savemd->setProperty("MakeFileBacked", false);
720 savemd->executeAsChildAlg();
721
722 // create file-backed box controller
723 auto boxControllerMem = outputWS->getBoxController();
724 auto boxControllerIO = std::make_shared<BoxControllerNeXusIO>(boxControllerMem.get());
725 boxControllerMem->setFileBacked(boxControllerIO, filebackPath);
726 outputWS->setFileBacked();
727 boxControllerMem->getFileIO()->setWriteBufferSize(1000000);
728}
729
730} // namespace Mantid::MDAlgorithms
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
Definition: Algorithm.cpp:2026
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
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.
Definition: Algorithm.cpp:842
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
Definition: FileProperty.h:50
void addProperty(Kernel::Property *prop, bool overwrite=false)
Add data to the object in the form of a property.
Definition: LogManager.h:79
HeldType getPropertyValueAsType(const std::string &name) const
Get the value of a property as the given TYPE.
Definition: LogManager.cpp:332
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...
Definition: IMDDimension.h:39
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.
Definition: ArrayProperty.h:28
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:114
void error(const std::string &msg)
Logs at error level.
Definition: Logger.cpp:77
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
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 T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
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:36
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:67
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:60
std::shared_ptr< MDAlgorithms::MDEventWSWrapper > m_OutWSWrapper
Definition: ConvertToMD.h:70
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:31
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
Definition: MDWSTransform.h:84
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
Definition: MDWSTransform.h:80
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< BoxController > BoxController_sptr
Shared ptr to BoxController.
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
static Type fromString(const std::string &modeStr)
Returns the emode from the given string.
Definition: DeltaEMode.cpp:69
@ Input
An input workspace.
Definition: Property.h:53
@ Output
An output workspace.
Definition: Property.h:54