Mantid
Loading...
Searching...
No Matches
MDNorm.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 +
11#include "MantidAPI/Run.h"
12#include "MantidAPI/Sample.h"
32
33#include <algorithm>
34#include <boost/lexical_cast.hpp>
35
36namespace Mantid::MDAlgorithms {
37
38using namespace Mantid::Kernel;
39using namespace Mantid::API;
40using namespace Mantid::Geometry;
41using namespace Mantid::DataObjects;
42
43namespace {
45
46// k=sqrt(energyToK * E)
47constexpr double energyToK = 8.0 * M_PI * M_PI * PhysicalConstants::NeutronMass * PhysicalConstants::meV * 1e-20 /
49
50// compare absolute values of doubles
51static bool abs_compare(double a, double b) { return (std::fabs(a) < std::fabs(b)); }
52
54bool isMonochromaticSCDInstrument(const IMDEventWorkspace &workspace) {
55 if (workspace.getNumExperimentInfo() == 0)
56 return false;
57 const std::string instrument = workspace.getExperimentInfo(0)->getInstrumentName();
58 return instrument == "WAND" || instrument == "HB2C" || instrument == "HB3A" || instrument == "DEMAND";
59}
60} // namespace
61
62// Register the algorithm into the AlgorithmFactory
64
65//----------------------------------------------------------------------------------------------
69MDNorm::MDNorm() : m_isRLU(false), m_monochromatic(false) {}
70
72const std::string MDNorm::name() const { return "MDNorm"; }
73
75int MDNorm::version() const { return 1; }
76
78const std::string MDNorm::category() const { return "MDAlgorithms\\Normalisation"; }
79
81const std::string MDNorm::summary() const {
82 return "Bins multidimensional data and calculate the normalization on the "
83 "same grid";
84}
85
86//----------------------------------------------------------------------------------------------
91 std::make_unique<WorkspaceProperty<API::IMDEventWorkspace>>("InputWorkspace", "", Kernel::Direction::Input),
92 "An input MDEventWorkspace. Must be in Q_sample frame.");
93
95 "BackgroundWorkspace", "", Kernel::Direction::Input, PropertyMode::Optional),
96 "An (optional) input MDEventWorkspace for background. Must be in Q_lab frame.");
97
98 // RLU and settings
99 declareProperty("RLU", true, "Use reciprocal lattice units. If false, use Q_sample");
100 setPropertyGroup("RLU", "Q projections RLU");
101
102 auto mustBe3D = std::make_shared<Kernel::ArrayLengthValidator<double>>(3);
103 std::vector<double> Q0(3, 0.), Q1(3, 0), Q2(3, 0);
104 Q0[0] = 1.;
105 Q1[1] = 1.;
106 Q2[2] = 1.;
107
108 declareProperty(std::make_unique<ArrayProperty<double>>("QDimension0", Q0, mustBe3D),
109 "The first Q projection axis - Default is (1,0,0)");
110 setPropertySettings("QDimension0", std::make_unique<Kernel::VisibleWhenProperty>("RLU", IS_EQUAL_TO, "1"));
111 setPropertyGroup("QDimension0", "Q projections RLU");
112
113 declareProperty(std::make_unique<ArrayProperty<double>>("QDimension1", Q1, mustBe3D),
114 "The second Q projection axis - Default is (0,1,0)");
115 setPropertySettings("QDimension1", std::make_unique<Kernel::VisibleWhenProperty>("RLU", IS_EQUAL_TO, "1"));
116 setPropertyGroup("QDimension1", "Q projections RLU");
117
118 declareProperty(std::make_unique<ArrayProperty<double>>("QDimension2", Q2, mustBe3D),
119 "The thirdtCalculateCover Q projection axis - Default is (0,0,1)");
120 setPropertySettings("QDimension2", std::make_unique<Kernel::VisibleWhenProperty>("RLU", IS_EQUAL_TO, "1"));
121 setPropertyGroup("QDimension2", "Q projections RLU");
122
123 // vanadium
124 auto fluxValidator = std::make_shared<CompositeValidator>();
125 fluxValidator->add<InstrumentValidator>();
126 fluxValidator->add<CommonBinsValidator>();
127 auto solidAngleValidator = fluxValidator->clone();
128 declareProperty(std::make_unique<WorkspaceProperty<>>("SolidAngleWorkspace", "", Direction::Input,
129 API::PropertyMode::Optional, solidAngleValidator),
130 "An input workspace containing integrated vanadium "
131 "(a measure of the solid angle).\n"
132 "Mandatory for diffraction, optional for direct geometry inelastic");
133 declareProperty(std::make_unique<WorkspaceProperty<>>("FluxWorkspace", "", Direction::Input,
134 API::PropertyMode::Optional, fluxValidator),
135 "An input workspace containing momentum dependent flux.\n"
136 "Mandatory for diffraction. No effect on direct geometry inelastic");
137 setPropertyGroup("SolidAngleWorkspace", "Vanadium normalization");
138 setPropertyGroup("FluxWorkspace", "Vanadium normalization");
139
140 // monochromatic single crystal diffraction (WAND, DEMAND)
141 declareProperty(std::make_unique<WorkspaceProperty<API::IMDEventWorkspace>>("MonoSCDNormalizationWorkspace", "",
143 "An (optional) input MDEventWorkspace containing a pre-computed normalization "
144 "for monochromatic single crystal diffraction (e.g. produced by "
145 "ConvertHFIRSCDtoMDE). Must be in Q_sample frame with the same number of "
146 "dimensions as InputWorkspace. Cannot be used together with "
147 "SolidAngleWorkspace/FluxWorkspace or BackgroundWorkspace.");
148 setPropertyGroup("MonoSCDNormalizationWorkspace", "monochromatic-SCD");
149
150 // Define slicing
151 for (std::size_t i = 0; i < 6; i++) {
152 std::string propName = "Dimension" + Strings::toString(i) + "Name";
153 std::string propBinning = "Dimension" + Strings::toString(i) + "Binning";
154 std::string defaultName = "";
155 if (i < 3) {
156 defaultName = "QDimension" + Strings::toString(i);
157 }
158 declareProperty(std::make_unique<PropertyWithValue<std::string>>(propName, defaultName, Direction::Input),
159 "Name for the " + Strings::toString(i) + "th dimension. Leave blank for NONE.");
160 auto atMost3 = std::make_shared<ArrayLengthValidator<double>>(0, 3);
161 std::vector<double> temp;
162 declareProperty(std::make_unique<ArrayProperty<double>>(propBinning, temp, atMost3),
163 "Binning for the " + Strings::toString(i) + "th dimension.\n" +
164 "- Leave blank for complete integration\n" +
165 "- One value is interpreted as step\n"
166 "- Two values are interpreted integration interval\n" +
167 "- Three values are interpreted as min, step, max");
168 setPropertyGroup(propName, "Binning");
169 setPropertyGroup(propBinning, "Binning");
170 }
171
172 // symmetry operations
173 declareProperty(std::make_unique<PropertyWithValue<std::string>>("SymmetryOperations", "", Direction::Input),
174 "If specified the symmetry will be applied, "
175 "can be space group name, point group name, or list "
176 "individual symmetries.");
177
178 // temporary workspaces
179 declareProperty(std::make_unique<WorkspaceProperty<IMDHistoWorkspace>>("TemporaryDataWorkspace", "", Direction::Input,
181 "An (optional) input MDHistoWorkspace used to accumulate data from "
182 "multiple MDEventWorkspaces. If unspecified a blank "
183 "MDHistoWorkspace will be created.");
184 declareProperty(std::make_unique<WorkspaceProperty<IMDHistoWorkspace>>("TemporaryNormalizationWorkspace", "",
186 "An (optional) input MDHistoWorkspace used to accumulate normalization "
187 "from multiple MDEventWorkspaces. If unspecified a blank "
188 "MDHistoWorkspace will be created.");
189
190 // temporary background workspace
191 declareProperty(std::make_unique<WorkspaceProperty<IMDHistoWorkspace>>("TemporaryBackgroundDataWorkspace", "",
193 "An (optional) input MDHistoWorkspace used to accumulate background from "
194 "multiple background MDEventWorkspaces. If unspecified but "
195 "BackgroundWorkspace is specified, a blank "
196 "MDHistoWorkspace will be created.");
197 declareProperty(std::make_unique<WorkspaceProperty<IMDHistoWorkspace>>("TemporaryBackgroundNormalizationWorkspace",
199 "An (optional) input MDHistoWorkspace used to accumulate background normalization "
200 "from multiple background MDEventWorkspaces. If unspecified but "
201 "BackgroundWorkspace is specified, a blank "
202 "MDHistoWorkspace will be created.");
203
204 setPropertyGroup("TemporaryDataWorkspace", "Temporary workspaces");
205 setPropertyGroup("TemporaryNormalizationWorkspace", "Temporary workspaces");
206 setPropertyGroup("TemporaryBackgroundDataWorkspace", "Temporary workspaces");
207 setPropertyGroup("TemporaryBackgroundNormalizationWorkspace", "Temporary workspaces");
208
209 declareProperty(std::make_unique<WorkspaceProperty<API::Workspace>>("OutputWorkspace", "", Kernel::Direction::Output),
210 "A name for the normalized output MDHistoWorkspace.");
212 std::make_unique<WorkspaceProperty<API::Workspace>>("OutputDataWorkspace", "", Kernel::Direction::Output),
213 "A name for the output data MDHistoWorkspace.");
214 declareProperty(std::make_unique<WorkspaceProperty<Workspace>>("OutputNormalizationWorkspace", "", Direction::Output),
215 "A name for the output normalization MDHistoWorkspace.");
217 "OutputBackgroundDataWorkspace", "", Kernel::Direction::Output, PropertyMode::Optional),
218 "A name for the optional output background data MDHistoWorkspace.");
219 declareProperty(std::make_unique<WorkspaceProperty<Workspace>>("OutputBackgroundNormalizationWorkspace", "",
221 "A name for the optional output background normalization MDHistoWorkspace.");
222
223 m_progress = std::make_unique<API::Progress>(this, 0, 1, 1);
224}
225
226//----------------------------------------------------------------------------------------------
228std::map<std::string, std::string> MDNorm::validateInputs() {
229 std::map<std::string, std::string> errorMessage;
230
231 // Check for input workspace frame
232 Mantid::API::IMDEventWorkspace_sptr inputWS = this->getProperty("InputWorkspace");
233 if (inputWS->getNumDims() < 3) {
234 errorMessage.emplace("InputWorkspace", "The input workspace must be at least 3D");
235 } else {
236 for (size_t i = 0; i < 3; i++) {
237 if (inputWS->getDimension(i)->getMDFrame().name() != Mantid::Geometry::QSample::QSampleName) {
238 errorMessage.emplace("InputWorkspace", "The input workspace must be in Q_sample");
239 }
240 }
241 }
242
243 // Optional background input IMDE
244 Mantid::API::IMDEventWorkspace_sptr bkgdWS = this->getProperty("BackgroundWorkspace");
245 if (bkgdWS) {
246 if (bkgdWS->getNumDims() < 3) {
247 // must have at least 3 dimensions
248 errorMessage.emplace("BackgroundWorkspace", "The input background workspace must be at least 3D");
249 } else {
250 // Check first 3 dimension for Q lab,
251 for (size_t i = 0; i < 3; i++) {
252 if (bkgdWS->getDimension(i)->getMDFrame().name() != Mantid::Geometry::QLab::QLabName) {
253 errorMessage.emplace("BackgroundWorkspace", "The input backgound workspace must be in Q_lab");
254 }
255 }
256
257 // Check 4th dimension if input workspace is elastic
258 if (inputWS->getNumDims() > 3) {
259 if (bkgdWS->getNumDims() <= 3) {
260 errorMessage.emplace("BackgroundWorkspace", "The input background workspace must have at 4 dimensions when "
261 "input workspace has more than 4 dimensions (inelastic case).");
262 } else if (bkgdWS->getDimension(3)->getName() != inputWS->getDimension(3)->getName()) {
263 errorMessage.emplace("BackgroundWorkspace", "The input background workspace 4th dimension must be DeltaE "
264 "for inelastic case.");
265 }
266 }
267 }
268 }
269
270 // Check if the vanadium is available for diffraction
271 bool diffraction = true;
272 if ((inputWS->getNumDims() > 3) && (inputWS->getDimension(3)->getName() == "DeltaE")) {
273 diffraction = false;
274 }
275
276 // Optional pre-computed normalization workspace for monochromatic single crystal diffraction
277 // (e.g. WAND, DEMAND). This is an alternative to SolidAngleWorkspace/FluxWorkspace.
278 Mantid::API::IMDEventWorkspace_sptr monoNormWS = this->getProperty("MonoSCDNormalizationWorkspace");
279 bool monochromatic = bool(monoNormWS);
280 API::MatrixWorkspace_const_sptr solidAngleWS = getProperty("SolidAngleWorkspace");
281 API::MatrixWorkspace_const_sptr fluxWS = getProperty("FluxWorkspace");
282
283 // No background for monochromatic single crystal diffraction: it is subtracted in detector space instead. This
284 // message replaces any other problem found with BackgroundWorkspace, since the property is not to be used at all.
285 if (bkgdWS && (monochromatic || isMonochromaticSCDInstrument(*inputWS))) {
286 errorMessage["BackgroundWorkspace"] = "MDNorm does not support a background for monochromatic single crystal "
287 "diffraction. Subtract the background in detector space with "
288 "HFIRSCDSubtractBackground before ConvertHFIRSCDtoMDE.";
289 }
290
291 if (monochromatic) {
292 if (!diffraction) {
293 errorMessage.emplace("MonoSCDNormalizationWorkspace", "MonoSCDNormalizationWorkspace can only be used for "
294 "diffraction (InputWorkspace must not have a DeltaE "
295 "dimension)");
296 }
297 if (solidAngleWS || fluxWS) {
298 errorMessage.emplace("MonoSCDNormalizationWorkspace", "MonoSCDNormalizationWorkspace cannot be used together "
299 "with SolidAngleWorkspace/FluxWorkspace");
300 }
301 if (monoNormWS->getNumDims() < 3) {
302 errorMessage.emplace("MonoSCDNormalizationWorkspace", "MonoSCDNormalizationWorkspace must be at least 3D");
303 } else {
304 if (monoNormWS->getNumDims() != inputWS->getNumDims()) {
305 errorMessage.emplace("MonoSCDNormalizationWorkspace", "MonoSCDNormalizationWorkspace must have the same "
306 "number of dimensions as InputWorkspace");
307 }
308 for (size_t i = 0; i < 3; i++) {
309 if (monoNormWS->getDimension(i)->getMDFrame().name() != Mantid::Geometry::QSample::QSampleName) {
310 errorMessage.emplace("MonoSCDNormalizationWorkspace", "MonoSCDNormalizationWorkspace must be in Q_sample");
311 }
312 }
313 }
314 } else if (diffraction) {
315 if (solidAngleWS == nullptr) {
316 errorMessage.emplace("SolidAngleWorkspace", "SolidAngleWorkspace is required for diffraction");
317 }
318 if (fluxWS == nullptr) {
319 errorMessage.emplace("FluxWorkspace", "FluxWorkspace is required for diffraction");
320 }
321 }
322 // Check for property MDNorm_low and MDNorm_high (TOF only), or, for monochromatic
323 // input, that a wavelength log is present (set by e.g. ConvertHFIRSCDtoMDE)
324 size_t nExperimentInfos = inputWS->getNumExperimentInfo();
325 if (nExperimentInfos == 0) {
326 errorMessage.emplace("InputWorkspace", "There must be at least one experiment info");
327 } else {
328 for (size_t iExpInfo = 0; iExpInfo < nExperimentInfos; iExpInfo++) {
329 auto &currentExptInfo = *(inputWS->getExperimentInfo(static_cast<uint16_t>(iExpInfo)));
330 if (monochromatic) {
331 if (!currentExptInfo.run().hasProperty("wavelength")) {
332 errorMessage.emplace("InputWorkspace", "Missing wavelength log. InputWorkspace does not look like it was "
333 "produced by ConvertHFIRSCDtoMDE, as expected when "
334 "MonoSCDNormalizationWorkspace is provided");
335 }
336 } else {
337 if (!currentExptInfo.run().hasProperty("MDNorm_low")) {
338 errorMessage.emplace("InputWorkspace", "Missing MDNorm_low log. Please "
339 "use CropWorkspaceForMDNorm "
340 "before converting to MD");
341 }
342 if (!currentExptInfo.run().hasProperty("MDNorm_high")) {
343 errorMessage.emplace("InputWorkspace", "Missing MDNorm_high log. Please use "
344 "CropWorkspaceForMDNorm before converting to MD");
345 }
346 }
347 }
348 }
349 // check projections and UB
350 if (getProperty("RLU")) {
351 DblMatrix W = DblMatrix(3, 3);
352 std::vector<double> Q0Basis = getProperty("QDimension0");
353 std::vector<double> Q1Basis = getProperty("QDimension1");
354 std::vector<double> Q2Basis = getProperty("QDimension2");
355 W.setColumn(0, Q0Basis);
356 W.setColumn(1, Q1Basis);
357 W.setColumn(2, Q2Basis);
358 if (fabs(W.determinant()) < 1e-5) {
359 errorMessage.emplace("QDimension0", "The projection dimensions are coplanar or zero");
360 errorMessage.emplace("QDimension1", "The projection dimensions are coplanar or zero");
361 errorMessage.emplace("QDimension2", "The projection dimensions are coplanar or zero");
362 }
363 if (!inputWS->getExperimentInfo(0)->sample().hasOrientedLattice()) {
364 errorMessage.emplace("InputWorkspace", "There is no oriented lattice "
365 "associated with the input workspace. "
366 "Use SetUB algorithm");
367 }
368 }
369 // check dimension names
370 std::vector<std::string> originalDimensionNames;
371 for (size_t i = 3; i < inputWS->getNumDims(); i++) {
372 originalDimensionNames.emplace_back(inputWS->getDimension(i)->getName());
373 }
374 originalDimensionNames.emplace_back("QDimension0");
375 originalDimensionNames.emplace_back("QDimension1");
376 originalDimensionNames.emplace_back("QDimension2");
377 std::vector<std::string> selectedDimensions;
378 for (std::size_t i = 0; i < 6; i++) {
379 std::string propName = "Dimension" + Strings::toString(i) + "Name";
380 std::string dimName = getProperty(propName);
381 std::string binningName = "Dimension" + Strings::toString(i) + "Binning";
382 std::vector<double> binning = getProperty(binningName);
383 if (!dimName.empty()) {
384 auto it = std::find(originalDimensionNames.begin(), originalDimensionNames.end(), dimName);
385 if (it == originalDimensionNames.end()) {
386 errorMessage.emplace(propName, "Name '" + dimName +
387 "' is not one of the "
388 "original workspace names or a directional dimension");
389 } else {
390 // make sure dimension is unique
391 auto itSel = std::find(selectedDimensions.begin(), selectedDimensions.end(), dimName);
392 if (itSel == selectedDimensions.end()) {
393 selectedDimensions.emplace_back(dimName);
394 } else {
395 errorMessage.emplace(propName, "Name '" + dimName + "' was already selected");
396 }
397 }
398 } else {
399 if (!binning.empty()) {
400 errorMessage.emplace(binningName, "There should be no binning if the dimension name is empty");
401 }
402 }
403 }
404 // since Q dimensions can be non - orthogonal, all must be present
405 if ((std::find(selectedDimensions.begin(), selectedDimensions.end(), "QDimension0") == selectedDimensions.end()) ||
406 (std::find(selectedDimensions.begin(), selectedDimensions.end(), "QDimension1") == selectedDimensions.end()) ||
407 (std::find(selectedDimensions.begin(), selectedDimensions.end(), "QDimension2") == selectedDimensions.end())) {
408 for (std::size_t i = 0; i < 6; i++) {
409 std::string propName = "Dimension" + Strings::toString(i) + "Name";
410 errorMessage.emplace(propName, "All of QDimension0, QDimension1, QDimension2 must be present");
411 }
412 }
413 // symmetry operations
414 std::string symOps = this->getProperty("SymmetryOperations");
415 if (!symOps.empty()) {
416 bool isSpaceGroup = Geometry::SpaceGroupFactory::Instance().isSubscribed(symOps);
417 bool isPointGroup = Geometry::PointGroupFactory::Instance().isSubscribed(symOps);
418 if (!isSpaceGroup && !isPointGroup) {
419 try {
420 Geometry::SymmetryOperationFactory::Instance().createSymOps(symOps);
421 } catch (const Mantid::Kernel::Exception::ParseError &) {
422 errorMessage.emplace("SymmetryOperations", "The input is not a space group, a point group, "
423 "or a list of symmetry operations");
424 }
425 }
426 }
427 // validate accumulation workspaces, if provided
428 std::shared_ptr<IMDHistoWorkspace> tempNormWS = this->getProperty("TemporaryNormalizationWorkspace");
429 Mantid::API::IMDHistoWorkspace_sptr tempDataWS = this->getProperty("TemporaryDataWorkspace");
430
431 // check that either both or neuther accumulation workspaces are provied
432 if ((tempNormWS && !tempDataWS) || (!tempNormWS && tempDataWS)) {
433 errorMessage.emplace("TemporaryDataWorkspace", "Must provide either no accumulation workspaces or,"
434 "both TemporaryNormalizationWorkspaces and TemporaryDataWorkspace");
435 }
436 // check that both accumulation workspaces are on the same grid
437 if (tempNormWS && tempDataWS) {
438 size_t numNormDims = tempNormWS->getNumDims();
439 size_t numDataDims = tempDataWS->getNumDims();
440 if (numNormDims == numDataDims) {
441 for (size_t i = 0; i < numNormDims; i++) {
442 const auto dim1 = tempNormWS->getDimension(i);
443 const auto dim2 = tempDataWS->getDimension(i);
444 if ((dim1->getMinimum() != dim2->getMinimum()) || (dim1->getMaximum() != dim2->getMaximum()) ||
445 (dim1->getNBins() != dim2->getNBins()) || (dim1->getName() != dim2->getName())) {
446 errorMessage.emplace("TemporaryDataWorkspace", "Binning for TemporaryNormalizationWorkspaces "
447 "and TemporaryDataWorkspace must be the same.");
448 break;
449 }
450 }
451 } else { // accumulation workspaces have different number of dimensions
452 errorMessage.emplace("TemporaryDataWorkspace", "TemporaryNormalizationWorkspace and TemporaryDataWorkspace "
453 "do not have the same number of dimensions");
454 }
455 }
456
457 // validate accumulated background workspaces
458 Mantid::API::IMDHistoWorkspace_sptr tempBkgdDataWS = this->getProperty("TemporaryBackgroundDataWorkspace");
459 Mantid::API::IMDHistoWorkspace_sptr tempBkgdNormWS = this->getProperty("TemporaryBackgroundNormalizationWorkspace");
460 // check existing criteria: Background, TempBackgroundData and
461 // TempBackgroundNormalization must be specified
462 if (tempBkgdDataWS && (!bkgdWS || !tempDataWS || !tempBkgdNormWS)) {
463 errorMessage.emplace("TemporaryBackgroundDataWorkspace", "TemporaryBackgroundDataWorkspace is specified but at "
464 "least one of these is not.");
465 } else if (tempBkgdNormWS && (!bkgdWS || !tempNormWS || !tempBkgdDataWS)) {
466 errorMessage.emplace("TemporaryBackgroundNormalizationWorkspace", "TemporaryBackgroundNormalizationWorkspace is "
467 "specified but at least one of these is not.");
468 } else if (bkgdWS && tempDataWS && !tempBkgdDataWS) {
469 errorMessage.emplace("TemporaryDataWorkspace",
470 "With Background is specifed and TemporaryDataWorkspace is specifed, "
471 "TemporaryBackgroundDataWorkspace must be specified.");
472 } else if (tempBkgdDataWS && tempNormWS) {
473 // check when they both exist
474 size_t numBkgdDataDims = tempBkgdDataWS->getNumDims();
475 size_t numBkgdNormDims = tempBkgdNormWS->getNumDims();
476 size_t numDataDims = tempDataWS->getNumDims();
477 if (numBkgdDataDims == numBkgdNormDims && numBkgdDataDims == numDataDims) {
478 // On each dimension, compare min, max, NBins and name
479 for (size_t idim = 0; idim < numBkgdDataDims; ++idim) {
480 const auto dimB = tempBkgdDataWS->getDimension(idim);
481 const auto dimN = tempBkgdNormWS->getDimension(idim);
482 const auto dimD = tempDataWS->getDimension(idim);
483 if ((dimB->getMinimum() != dimN->getMinimum()) || (dimB->getMinimum() != dimD->getMinimum()) ||
484 (dimB->getMaximum() != dimN->getMaximum()) || (dimB->getMaximum() != dimD->getMaximum()) ||
485 (dimB->getNBins() != dimN->getNBins()) || (dimB->getNBins() != dimD->getNBins()) ||
486 (dimB->getName() != dimN->getName()) || (dimB->getName() != dimD->getName())) {
487 errorMessage.emplace("TemporaryBackgroundDataWorkspace",
488 "TemporaryBackgroundDataWorkspace, "
489 "TemporaryBackgroundNormalizationWorkspace and "
490 "TemporaryDataWorkspace "
491 "must have same minimum, maximum, number of bins and name.");
492 break;
493 }
494 }
495 } else {
496 errorMessage.emplace("TemporaryBackgroundDataWorkspace", "TemporaryBackgroundDataWorkspace, "
497 "TemporaryBackgroundNormalizationWorkspace and "
498 "TemporaryDataWorkspace must have same dimensions");
499 }
500 }
501
502 return errorMessage;
503}
504
505//----------------------------------------------------------------------------------------------
509 m_convention = Kernel::ConfigService::Instance().getString("Q.convention");
511 // symmetry operations
512 std::string symOps = this->getProperty("SymmetryOperations");
513 std::vector<Geometry::SymmetryOperation> symmetryOps;
514 if (symOps.empty()) {
515 symOps = "x,y,z";
516 }
517 if (Geometry::SpaceGroupFactory::Instance().isSubscribed(symOps)) {
518 auto spaceGroup = Geometry::SpaceGroupFactory::Instance().createSpaceGroup(symOps);
519 auto pointGroup = spaceGroup->getPointGroup();
520 symmetryOps = pointGroup->getSymmetryOperations();
521 } else if (Geometry::PointGroupFactory::Instance().isSubscribed(symOps)) {
522 auto pointGroup = Geometry::PointGroupFactory::Instance().createPointGroup(symOps);
523 symmetryOps = pointGroup->getSymmetryOperations();
524 } else {
525 symmetryOps = Geometry::SymmetryOperationFactory::Instance().createSymOps(symOps);
526 }
527 g_log.debug() << "Symmetry operations\n";
528 for (const auto &so : symmetryOps) {
529 g_log.debug() << so.identifier() << "\n";
530 }
531 m_numSymmOps = symmetryOps.size();
532
533 m_isRLU = getProperty("RLU");
534 // get the workspaces
535 m_inputWS = this->getProperty("InputWorkspace");
536 Mantid::API::IMDEventWorkspace_sptr monoNormInputWS = this->getProperty("MonoSCDNormalizationWorkspace");
537 m_monochromatic = bool(monoNormInputWS);
538 const auto &exptInfoZero = *(m_inputWS->getExperimentInfo(0));
539 auto source = exptInfoZero.getInstrument()->getSource();
540 auto sample = exptInfoZero.getInstrument()->getSample();
541 if (source == nullptr || sample == nullptr) {
543 "Instrument not sufficiently defined: failed to get source and/or "
544 "sample");
545 }
546 m_samplePos = sample->getPos();
547 m_beamDir = normalize(m_samplePos - source->getPos());
548 if ((m_inputWS->getNumDims() > 3) && (m_inputWS->getDimension(3)->getName() == "DeltaE")) {
549 // DeltaE in input MDE: it cannot be diffraction!
550 m_diffraction = false;
551 if (exptInfoZero.run().hasProperty("Ei")) {
552 Kernel::Property *eiprop = exptInfoZero.run().getProperty("Ei");
553 m_Ei = boost::lexical_cast<double>(eiprop->value());
554 if (m_Ei <= 0) {
555 throw std::invalid_argument("Ei stored in the workspace is not positive");
556 }
557 } else {
558 throw std::invalid_argument("Could not find Ei value in the workspace.");
559 }
560 }
561
562 // Calculate (BinMD) input sample MDE to MDH and create noramlization MDH from
563 // it
564 auto outputDataWS = binInputWS(symmetryOps);
565 if (m_monochromatic) {
566 // Monochromatic single crystal diffraction (WAND, DEMAND): the normalization is a
567 // pre-computed MDEventWorkspace, binned identically to the data instead of being
568 // calculated from solid angle/flux trajectories.
569 m_normWS = binMonoSCDNormalizationWS(symmetryOps);
570 } else {
571 createNormalizationWS(*outputDataWS);
572 }
573 this->setProperty("OutputNormalizationWorkspace", m_normWS);
574 this->setProperty("OutputDataWorkspace", outputDataWS);
575
576 // Background
577 m_backgroundWS = this->getProperty("BackgroundWorkspace");
578 DataObjects::MDHistoWorkspace_sptr outputBackgroundDataWS(nullptr);
579 // Outputs for background related
580 if (m_backgroundWS) {
581 outputBackgroundDataWS = binBackgroundWS(symmetryOps);
582 createBackgroundNormalizationWS(*outputBackgroundDataWS);
583 this->setProperty("OutputBackgroundNormalizationWorkspace", m_bkgdNormWS);
584 this->setProperty("OutputBackgroundDataWorkspace", outputBackgroundDataWS);
585 }
586
587 m_numExptInfos = outputDataWS->getNumExperimentInfo();
588 if (!m_monochromatic) {
589 m_signalArray = std::vector<std::atomic<signal_t>>(m_normWS->getNPoints());
590 if (m_backgroundWS)
591 m_bkgdSignalArray = std::vector<std::atomic<signal_t>>(m_bkgdNormWS->getNPoints());
592 // loop over all experiment infos, computing the normalization from solid angle/flux
593 // trajectories (TOF only; for monochromatic input, m_normWS was already binned above)
594 m_progress->resetNumSteps(m_numExptInfos * m_numSymmOps, 0.3, 0.9);
595 for (uint16_t expInfoIndex = 0; expInfoIndex < m_numExptInfos; expInfoIndex++) {
596 const auto &currentExptInfo = *(m_inputWS->getExperimentInfo(expInfoIndex));
597 // Check for other dimensions if we could measure anything in the original
598 // data
599 bool skipNormalization = false;
600 const std::vector<coord_t> otherValues = getValuesFromOtherDimensions(skipNormalization, expInfoIndex);
601
603
604 if (!skipNormalization) {
605 for (const auto &so : symmetryOps) {
606 if (currentExptInfo.run().hasProperty("useLogTimes")) {
607 calculateNormContinuous(otherValues, expInfoIndex, &so);
608 } else {
609 calculateNormalization(otherValues, so, expInfoIndex);
610 }
611 m_progress->report();
612 }
613 } else {
614 g_log.warning("Binning limits are outside the limits of the MDWorkspace. "
615 "Not applying normalization.");
616 }
617 }
618 if (m_accumulate) {
619 std::transform(m_signalArray.cbegin(), m_signalArray.cend(), m_normWS->getSignalArray(),
620 m_normWS->mutableSignalArray(),
621 [](const std::atomic<signal_t> &a, const signal_t &b) { return a + b; });
622 if (m_backgroundWS)
623 std::transform(m_bkgdSignalArray.cbegin(), m_bkgdSignalArray.cend(), m_bkgdNormWS->getSignalArray(),
624 m_bkgdNormWS->mutableSignalArray(),
625 [](const std::atomic<signal_t> &a, const signal_t &b) { return a + b; });
626 } else {
627 std::copy(m_signalArray.cbegin(), m_signalArray.cend(), m_normWS->mutableSignalArray());
628 if (m_backgroundWS)
629 std::copy(m_bkgdSignalArray.cbegin(), m_bkgdSignalArray.cend(), m_bkgdNormWS->mutableSignalArray());
630 }
631 }
632
633 API::IMDWorkspace_sptr out(nullptr);
634
635 if (m_backgroundWS) {
636 // Normalize binned (BinMD) sample workspace with background
637 out = divideMD(outputDataWS, m_normWS, getPropertyValue("OutputWorkspace"), 0.97, 0.98);
638
639 // Normalize background
640 const std::string normedBkgdWSName("_normedBkgd");
641 API::IMDWorkspace_sptr outbkgd = divideMD(outputBackgroundDataWS, m_bkgdNormWS, normedBkgdWSName, 0.98, 0.99);
642
643 // Clean workspace
644 auto minusMD = createChildAlgorithm("MinusMD", 0.99, 1.00);
645 // set up
646 minusMD->setProperty("LHSWorkspace", out);
647 minusMD->setProperty("RHSWorkspace", outbkgd);
648 minusMD->setPropertyValue("OutputWorkspace", getPropertyValue("OutputWorkspace"));
649 // run and return
650 minusMD->executeAsChildAlg();
651 out = minusMD->getProperty("OutputWorkspace");
652
653 } else {
654 // Normalize binned (BinMD) sample workspace without background
655 out = divideMD(outputDataWS, m_normWS, getPropertyValue("OutputWorkspace"), 0.97, 1.);
656 }
657
658 // Set output workspace
659 this->setProperty("OutputWorkspace", out);
660}
661
663 const API::IMDHistoWorkspace_sptr &rhs, const std::string &outputwsname,
664 const double &startProgress, const double &endProgress) {
665 auto divideMD = createChildAlgorithm("DivideMD", startProgress, endProgress);
666 divideMD->setProperty("LHSWorkspace", lhs);
667 divideMD->setProperty("RHSWorkspace", rhs);
668 divideMD->setPropertyValue("OutputWorkspace", outputwsname);
669 divideMD->executeAsChildAlg();
670 // API::IMDWorkspace_sptr
671 API::IMDWorkspace_sptr out = divideMD->getProperty("OutputWorkspace");
672
673 return out;
674}
675
682 if (i == 0)
683 return std::string("Q_sample_x");
684 else if (i == 1)
685 return std::string("Q_sample_y");
686 else if (i == 2)
687 return std::string("Q_sample_z");
688 else
689 throw std::invalid_argument("Index must be 0, 1, or 2 for QDimensionNameQSample");
690}
697std::string MDNorm::QDimensionName(std::vector<double> projection) {
698 std::vector<double>::iterator result;
699 result = std::max_element(projection.begin(), projection.end(), abs_compare);
700 std::vector<char> symbol{'H', 'K', 'L'};
701 char character = symbol[std::distance(projection.begin(), result)];
702 std::stringstream name;
703 name << "[";
704 for (size_t i = 0; i < 3; i++) {
705 if (projection[i] == 0) {
706 name << "0";
707 } else if (projection[i] == 1) {
708 name << character;
709 } else if (projection[i] == -1) {
710 name << "-" << character;
711 } else {
712 name << std::defaultfloat << std::setprecision(3) << projection[i] << character;
713 }
714 if (i != 2) {
715 name << ",";
716 }
717 }
718 name << "]";
719 return name.str();
720}
721
726std::map<std::string, std::string> MDNorm::getBinParameters() {
727 std::map<std::string, std::string> parameters;
728 std::stringstream extents;
729 std::stringstream bins;
730 std::vector<std::string> originalDimensionNames;
731 originalDimensionNames.emplace_back("QDimension0");
732 originalDimensionNames.emplace_back("QDimension1");
733 originalDimensionNames.emplace_back("QDimension2");
734 for (size_t i = 3; i < m_inputWS->getNumDims(); i++) {
735 originalDimensionNames.emplace_back(m_inputWS->getDimension(i)->getName());
736 }
737
738 if (m_isRLU) {
739 m_Q0Basis = getProperty("QDimension0");
740 m_Q1Basis = getProperty("QDimension1");
741 m_Q2Basis = getProperty("QDimension2");
742 m_UB = m_inputWS->getExperimentInfo(0)->sample().getOrientedLattice().getUB() * 2 * M_PI;
743 }
744
745 std::vector<double> W(m_Q0Basis);
746 W.insert(W.end(), m_Q1Basis.begin(), m_Q1Basis.end());
747 W.insert(W.end(), m_Q2Basis.begin(), m_Q2Basis.end());
748 m_W = DblMatrix(W);
749 m_W.Transpose();
750
751 // Find maximum Q, an isotropic bound used below to set the default HKL bin extents
752 // (only consumed when a Q dimension's binning is left automatic/step-only, see the
753 // m_isRLU branch below). For TOF input this comes from the physical wavelength/TOF
754 // window each detector reaches (MDNorm_low/MDNorm_high logs, set by
755 // CropWorkspaceForMDNorm). Monochromatic input has no such trajectory -- each event
756 // is a single measured Q_sample point -- so maxQ is instead estimated from the
757 // workspace's own data-occupied extents: the box-tree's tight bounding box (not the
758 // nominal/arbitrary MinValues/MaxValues used at MD-conversion time), converted to an
759 // isotropic bound by taking the modulus of its farthest corner from the origin.
760 double maxQ = 0.;
761 if (!m_monochromatic) {
762 auto &exptInfo0 = *(m_inputWS->getExperimentInfo(static_cast<uint16_t>(0)));
763 auto upperLimitsVector =
764 (*(dynamic_cast<Kernel::PropertyWithValue<std::vector<double>> *>(exptInfo0.getLog("MDNorm_high"))))();
765 if (m_diffraction) {
766 maxQ = 2. * (*std::max_element(upperLimitsVector.begin(), upperLimitsVector.end()));
767 } else {
768 double Ei;
769 double maxDE = *std::max_element(upperLimitsVector.begin(), upperLimitsVector.end());
770 auto loweLimitsVector =
771 (*(dynamic_cast<Kernel::PropertyWithValue<std::vector<double>> *>(exptInfo0.getLog("MDNorm_low"))))();
772 double minDE = *std::min_element(loweLimitsVector.begin(), loweLimitsVector.end());
773 if (exptInfo0.run().hasProperty("Ei")) {
774 Kernel::Property *eiprop = exptInfo0.run().getProperty("Ei");
775 Ei = boost::lexical_cast<double>(eiprop->value());
776 if (Ei <= 0) {
777 throw std::invalid_argument("Ei stored in the workspace is not positive");
778 }
779 } else {
780 throw std::invalid_argument("Could not find Ei value in the workspace.");
781 }
782 double ki = std::sqrt(energyToK * Ei);
783 double kfmin = std::sqrt(energyToK * (Ei - minDE));
784 double kfmax = std::sqrt(energyToK * (Ei - maxDE));
785
786 maxQ = ki + std::max(kfmin, kfmax);
787 }
788 } else {
789 // getMinimumExtents() walks the box tree to the given depth and unions the extents of
790 // populated boxes found there; its default depth of 2 can be much looser than the box
791 // tree's actual depth for sparser inputs (measured up to ~3.7x tighter per-axis bounds by
792 // depth 4 on real WAND/DEMAND data), while costing at most tens of milliseconds even for
793 // O(1e7)-event workspaces, so a fixed depth of 4 is used here instead of the default.
794 auto dataExtents = m_inputWS->getMinimumExtents(4);
795 double qx = std::max(std::fabs(dataExtents[0].getMin()), std::fabs(dataExtents[0].getMax()));
796 double qy = std::max(std::fabs(dataExtents[1].getMin()), std::fabs(dataExtents[1].getMax()));
797 double qz = std::max(std::fabs(dataExtents[2].getMin()), std::fabs(dataExtents[2].getMax()));
798 maxQ = std::sqrt(qx * qx + qy * qy + qz * qz);
799 }
800 size_t basisVectorIndex = 0;
801 std::vector<coord_t> transformation;
802 for (std::size_t i = 0; i < 6; i++) {
803 std::string propName = "Dimension" + Strings::toString(i) + "Name";
804 std::string binningName = "Dimension" + Strings::toString(i) + "Binning";
805 std::string dimName = getProperty(propName);
806 std::vector<double> binning = getProperty(binningName);
807 std::string bv = "BasisVector";
808 if (!dimName.empty()) {
809 std::string property = bv + Strings::toString(basisVectorIndex);
810 std::stringstream propertyValue;
811 propertyValue << dimName;
812 // get the index in the original workspace
813 auto dimIndex = std::distance(originalDimensionNames.begin(),
814 std::find(originalDimensionNames.begin(), originalDimensionNames.end(), dimName));
815 auto dimension = m_inputWS->getDimension(dimIndex);
816 propertyValue << "," << dimension->getMDUnits().getUnitLabel().ascii();
817 for (size_t j = 0; j < originalDimensionNames.size(); j++) {
818 if (j == static_cast<size_t>(dimIndex)) {
819 propertyValue << ",1";
820 transformation.emplace_back(1.f);
821 } else {
822 propertyValue << ",0";
823 transformation.emplace_back(0.f);
824 }
825 }
826 parameters.emplace(property, propertyValue.str());
827 // get the extents an number of bins
828 coord_t dimMax = dimension->getMaximum();
829 coord_t dimMin = dimension->getMinimum();
830 if (m_isRLU) {
832 ol.setUB(m_UB * m_W); // note that this is already multiplied by 2Pi
833 if (dimIndex == 0) {
834 dimMax = static_cast<coord_t>(ol.a() * maxQ);
835 dimMin = -dimMax;
836 } else if (dimIndex == 1) {
837 dimMax = static_cast<coord_t>(ol.b() * maxQ);
838 dimMin = -dimMax;
839 } else if (dimIndex == 2) {
840 dimMax = static_cast<coord_t>(ol.c() * maxQ);
841 dimMin = -dimMax;
842 }
843 }
844 if (binning.size() == 0) {
845 // only one bin, integrating from min to max
846 extents << dimMin << "," << dimMax << ",";
847 bins << 1 << ",";
848 } else if (binning.size() == 2) {
849 // only one bin, integrating from min to max
850 extents << binning[0] << "," << binning[1] << ",";
851 bins << 1 << ",";
852 } else if (binning.size() == 1) {
853 auto step = binning[0];
854 double nsteps = (dimMax - dimMin) / step;
855 if (nsteps + 1 - std::ceil(nsteps) >= 1e-4) {
856 nsteps = std::ceil(nsteps);
857 } else {
858 nsteps = std::floor(nsteps);
859 }
860 bins << static_cast<int>(nsteps) << ",";
861 extents << dimMin << "," << dimMin + nsteps * step << ",";
862 } else if (binning.size() == 3) {
863 dimMin = static_cast<coord_t>(binning[0]);
864 auto step = binning[1];
865 dimMax = static_cast<coord_t>(binning[2]);
866 double nsteps = (dimMax - dimMin) / step;
867 if (nsteps + 1 - std::ceil(nsteps) >= 1e-4) {
868 nsteps = std::ceil(nsteps);
869 } else {
870 nsteps = std::floor(nsteps);
871 }
872 bins << static_cast<int>(nsteps) << ",";
873 extents << dimMin << "," << dimMin + nsteps * step << ",";
874 }
875 basisVectorIndex++;
876 }
877 }
878 parameters.emplace("OutputExtents", extents.str());
879 parameters.emplace("OutputBins", bins.str());
881 transformation, static_cast<size_t>((transformation.size()) / m_inputWS->getNumDims()), m_inputWS->getNumDims());
882 return parameters;
883}
884
886
887 // requiring background workspace is specified
888 if (!m_backgroundWS) {
889 return;
890 }
891
892 // Copy the MDHisto workspace, and change signals and errors to 0.
893 std::shared_ptr<IMDHistoWorkspace> tmp = this->getProperty("TemporaryBackgroundNormalizationWorkspace");
894 m_bkgdNormWS = std::dynamic_pointer_cast<MDHistoWorkspace>(tmp);
895 if (!m_bkgdNormWS) {
896 m_bkgdNormWS = bkgdDataWS.clone();
897 m_bkgdNormWS->setTo(0., 0., 0.);
898 }
899}
900
907void MDNorm::validateBinningForTemporaryDataWorkspace(const std::map<std::string, std::string> &parameters,
908 const Mantid::API::IMDHistoWorkspace_sptr &tempDataWS) {
909
910 // parse the paramters map and get extents from tempDataWS
911 const std::string numBinsStr = parameters.at("OutputBins");
912 const std::string extentsStr = parameters.at("OutputExtents");
913 const std::vector<size_t> numBins = VectorHelper::splitStringIntoVector<size_t>(numBinsStr);
914 const std::vector<double> extents = VectorHelper::splitStringIntoVector<double>(extentsStr);
915
916 // make sure the number of dimensions is the same for both workspaces
917 size_t numDimsTemp = tempDataWS->getNumDims();
918 if ((numBins.size() != numDimsTemp) || (extents.size() != numDimsTemp * 2)) {
919 std::stringstream errorMessage;
920 errorMessage << "The number of dimensions in the output and ";
921 errorMessage << "TemporaryDataWorkspace are not the same.";
922 throw(std::invalid_argument(errorMessage.str()));
923 }
924
925 // compare the extents and number of bins
926 for (size_t i = 0; i < numDimsTemp; i++) {
927 auto ax = tempDataWS->getDimension(i);
928 if (numBins[i] != ax->getNBins()) {
929 std::stringstream errorMessage;
930 errorMessage << "The number of bins output and number of bins in ";
931 errorMessage << "TemporaryDataWorkspace are not the same along ";
932 errorMessage << "dimension " << i;
933 throw(std::invalid_argument(errorMessage.str()));
934 }
935 if (std::abs(extents[2 * i] - ax->getMinimum()) > 1.e-5) {
936 std::stringstream errorMessage;
937 errorMessage << "The minimum binning value for the output and ";
938 errorMessage << "TemporaryDataWorkspace are not the same along ";
939 errorMessage << "dimension " << i;
940 throw(std::invalid_argument(errorMessage.str()));
941 }
942 if (std::abs(extents[2 * i + 1] - ax->getMaximum()) > 1.e-5) {
943 std::stringstream errorMessage;
944 errorMessage << "The maximum binning value for the output and ";
945 errorMessage << "TemporaryDataWorkspace are not the same along ";
946 errorMessage << "dimension " << i;
947 throw(std::invalid_argument(errorMessage.str()));
948 }
949 }
950
951 // sort out which axes are dimensional and check names
952 size_t parametersIndex = 0;
953 std::vector<size_t> dimensionIndex(numDimsTemp + 1, 3); // stores h, k, l or Qx, Qy, Qz dimensions
954 for (const auto &p : parameters) {
955 auto key = p.first;
956 auto value = p.second;
957 // value starts with QDimension0, then other stuff
958 // do not use ==
959 if (value.find("QDimension0") != std::string::npos) {
960 dimensionIndex[0] = parametersIndex;
961 const std::string dimXName = tempDataWS->getDimension(parametersIndex)->getName();
962 if (m_isRLU) { // hkl
963 if (dimXName != QDimensionName(m_Q0Basis)) {
964 std::stringstream errorMessage;
965 std::stringstream debugMessage;
966 errorMessage << "TemporaryDataWorkspace does not have the ";
967 errorMessage << "correct name for dimension " << parametersIndex;
968 debugMessage << "QDimension0 Names: Output will be: " << QDimensionName(m_Q0Basis);
969 debugMessage << " TemporaryDataWorkspace: " << dimXName;
970 g_log.warning(debugMessage.str());
971 throw(std::invalid_argument(errorMessage.str()));
972 }
973 } else {
974 if (dimXName != QDimensionNameQSample(0)) {
975 std::stringstream errorMessage;
976 std::stringstream debugMessage;
977 errorMessage << "TemporaryDataWorkspace does not have the ";
978 errorMessage << "correct name for dimension " << parametersIndex;
979 debugMessage << "QDimension0 Names: Output will be: " << QDimensionNameQSample(0);
980 debugMessage << " TemporaryDataWorkspace: " << dimXName;
981 g_log.warning(debugMessage.str());
982 throw(std::invalid_argument(errorMessage.str()));
983 }
984 }
985 } else if (value.find("QDimension1") != std::string::npos) {
986 dimensionIndex[1] = parametersIndex;
987 const std::string dimYName = tempDataWS->getDimension(parametersIndex)->getName();
988 if (m_isRLU) { // hkl
989 if (dimYName != QDimensionName(m_Q1Basis)) {
990 std::stringstream errorMessage;
991 std::stringstream debugMessage;
992 errorMessage << "TemporaryDataWorkspace does not have the ";
993 errorMessage << "correct name for dimension " << parametersIndex;
994 debugMessage << "QDimension1 Names: Output will be: " << QDimensionName(m_Q1Basis);
995 debugMessage << " TemporaryDataWorkspace: " << dimYName;
996 g_log.warning(debugMessage.str());
997 throw(std::invalid_argument(errorMessage.str()));
998 }
999 } else {
1000 if (dimYName != QDimensionNameQSample(1)) {
1001 std::stringstream errorMessage;
1002 std::stringstream debugMessage;
1003 errorMessage << "TemporaryDataWorkspace does not have the ";
1004 errorMessage << "correct name for dimension " << parametersIndex;
1005 debugMessage << "QDimension1 Names: Output will be: " << QDimensionNameQSample(1);
1006 debugMessage << " TemporaryDataWorkspace: " << dimYName;
1007 g_log.warning(debugMessage.str());
1008 throw(std::invalid_argument(errorMessage.str()));
1009 }
1010 }
1011 } else if (value.find("QDimension2") != std::string::npos) {
1012 dimensionIndex[2] = parametersIndex;
1013 const std::string dimZName = tempDataWS->getDimension(parametersIndex)->getName();
1014 if (m_isRLU) { // hkl
1015 if (dimZName != QDimensionName(m_Q2Basis)) {
1016 std::stringstream errorMessage;
1017 std::stringstream debugMessage;
1018 errorMessage << "TemporaryDataWorkspace does not have the ";
1019 errorMessage << "correct name for dimension " << parametersIndex;
1020 debugMessage << "QDimension2 Names: Output will be: " << QDimensionName(m_Q2Basis);
1021 debugMessage << " TemporaryDataWorkspace: " << dimZName;
1022 g_log.warning(debugMessage.str());
1023 throw(std::invalid_argument(errorMessage.str()));
1024 }
1025 } else {
1026 if (dimZName != QDimensionNameQSample(2)) {
1027 std::stringstream errorMessage;
1028 std::stringstream debugMessage;
1029 errorMessage << "TemporaryDataWorkspace does not have the ";
1030 errorMessage << "correct name for dimension " << parametersIndex;
1031 debugMessage << "QDimension2 Names: Output will be: " << QDimensionNameQSample(2);
1032 debugMessage << " TemporaryDataWorkspace: " << dimZName;
1033 g_log.warning(debugMessage.str());
1034 throw(std::invalid_argument(errorMessage.str()));
1035 }
1036 }
1037
1038 } else if ((key != "OutputBins") && (key != "OutputExtents")) {
1039 // make sure the names of non-directional dimensions are the same
1040 const std::string nameData = tempDataWS->getDimension(parametersIndex)->getName();
1041 if (value.find(nameData) != 0) {
1042 g_log.error() << "Dimension " << nameData
1043 << " from the temporary workspace"
1044 " is not one of the binning dimensions, "
1045 " or dimensions are in the wrong order."
1046 << std::endl;
1047 throw(std::invalid_argument("Beside the Q dimensions, "
1048 "TemporaryDataWorkspace does not have the "
1049 "same dimension names as OutputWorkspace."));
1050 }
1051 }
1052 parametersIndex++;
1053 }
1054 const auto it = std::find_if(dimensionIndex.cbegin(), dimensionIndex.cend(),
1055 [numDimsTemp](const auto &idx) { return idx > numDimsTemp; });
1056 if (it != dimensionIndex.cend())
1057 throw(std::invalid_argument("Cannot find at least one of QDimension0, "
1058 "QDimension1, or QDimension2"));
1059}
1060
1067 // calculate dimensions for binning
1068 DblMatrix soMatrix(3, 3);
1069 auto v = so.transformHKL(V3D(1, 0, 0));
1070 soMatrix.setColumn(0, v);
1071 v = so.transformHKL(V3D(0, 1, 0));
1072 soMatrix.setColumn(1, v);
1073 v = so.transformHKL(V3D(0, 0, 1));
1074 soMatrix.setColumn(2, v);
1075 soMatrix.Invert();
1076
1077 return soMatrix;
1078}
1079
1080// projection: input/output
1081// requiring: m_hIdx, m_kIndex, m_lIdx, meidx, m_dEintegrated, m_Q0Basis,
1082// mQ1Basis,
1092inline void MDNorm::determineBasisVector(const size_t &qindex, const std::string &value,
1093 const Mantid::Kernel::DblMatrix &Qtransform, std::vector<double> &projection,
1094 std::stringstream &basisVector, std::vector<size_t> &qDimensionIndices) {
1095 if (value.find("QDimension0") != std::string::npos) {
1096 m_hIdx = qindex;
1097 if (!m_isRLU) {
1098 projection[0] = 1.;
1099 basisVector << QDimensionNameQSample(0) << ",A^{-1}";
1100 } else {
1101 qDimensionIndices.emplace_back(qindex);
1102 projection[0] = Qtransform[0][0];
1103 projection[1] = Qtransform[1][0];
1104 projection[2] = Qtransform[2][0];
1105 basisVector << QDimensionName(m_Q0Basis) << ", r.l.u.";
1106 }
1107 } else if (value.find("QDimension1") != std::string::npos) {
1108 m_kIdx = qindex;
1109 if (!m_isRLU) {
1110 projection[1] = 1.;
1111 basisVector << QDimensionNameQSample(1) << ",A^{-1}";
1112 } else {
1113 qDimensionIndices.emplace_back(qindex);
1114 projection[0] = Qtransform[0][1];
1115 projection[1] = Qtransform[1][1];
1116 projection[2] = Qtransform[2][1];
1117 basisVector << QDimensionName(m_Q1Basis) << ", r.l.u.";
1118 }
1119 } else if (value.find("QDimension2") != std::string::npos) {
1120 m_lIdx = qindex;
1121 if (!m_isRLU) {
1122 projection[2] = 1.;
1123 basisVector << QDimensionNameQSample(2) << ",A^{-1}";
1124 } else {
1125 qDimensionIndices.emplace_back(qindex);
1126 projection[0] = Qtransform[0][2];
1127 projection[1] = Qtransform[1][2];
1128 projection[2] = Qtransform[2][2];
1129 basisVector << QDimensionName(m_Q2Basis) << ", r.l.u.";
1130 }
1131 } else if (value.find("DeltaE") != std::string::npos) {
1132 m_eIdx = qindex;
1133 m_dEIntegrated = false;
1134 }
1135}
1136
1142inline void MDNorm::setQUnit(const std::vector<size_t> &qDimensionIndices,
1143 const Mantid::DataObjects::MDHistoWorkspace_sptr &outputMDHWS) {
1145 auto mdFrameFactory = Mantid::Geometry::makeMDFrameFactoryChain();
1146 Mantid::Geometry::MDFrame_uptr hklFrame = mdFrameFactory->create(argument);
1147 for (size_t i : qDimensionIndices) {
1148 auto mdHistoDimension = std::const_pointer_cast<Mantid::Geometry::MDHistoDimension>(
1149 std::dynamic_pointer_cast<const Mantid::Geometry::MDHistoDimension>(outputMDHWS->getDimension(i)));
1150 mdHistoDimension->setMDFrame(*hklFrame);
1151 }
1152 // add W_matrix
1153 auto ei = outputMDHWS->getExperimentInfo(0);
1154 ei->mutableRun().addProperty("W_MATRIX", m_W.getVector(), true);
1155}
1156
1163MDNorm::binBackgroundWS(const std::vector<Geometry::SymmetryOperation> &symmetryOps) {
1164 // Create output background data histogram MD workspace
1165 // Either from TemporaryBackgroundDataWorkspace
1166 // Or from scratch
1167 Mantid::API::IMDHistoWorkspace_sptr tempBkgdDataWS = this->getProperty("TemporaryBackgroundDataWorkspace");
1169
1170 // check that our input matches the temporary workspaces
1171 std::map<std::string, std::string> parameters = getBinParameters();
1172 if (tempBkgdDataWS) {
1173 validateBinningForTemporaryDataWorkspace(parameters, tempBkgdDataWS);
1174 }
1175
1176 // For each symmetry operation, do binning MD once
1177 std::vector<size_t> qDimensionIndices;
1178 uint16_t numexpinfo = static_cast<uint16_t>(m_inputWS->getNumExperimentInfo());
1179 if (m_numSymmOps != symmetryOps.size())
1180 throw std::runtime_error("Symmetry operation number m_umSymops is wrong!");
1181
1182 for (uint16_t i_expinfo = 0; i_expinfo < numexpinfo; ++i_expinfo) {
1183
1184 auto rotMatrix = m_inputWS->getExperimentInfo(i_expinfo)->run().getGoniometerMatrix();
1185
1186 // Reset symmetry operation index
1187 double soIndex = 0;
1188
1189 for (const auto &so : symmetryOps) {
1190 // Q transformation matrix: From Q_lab to HKL or Q_sample
1191 // Building symmetric operation matrix
1192 DblMatrix soMatrix = buildSymmetryMatrix(so);
1193 // Calculate Q transform matrix
1194 DblMatrix Qtransform;
1195 if (m_isRLU) {
1196 Qtransform = rotMatrix * m_UB * soMatrix * m_W;
1197 } else {
1198 Qtransform = rotMatrix * soMatrix * m_W;
1199 }
1200
1201 // Set up BinMD for this symmetry opeation
1202 double progress_fraction = 1. / static_cast<double>(symmetryOps.size() * numexpinfo);
1203 auto binMD =
1204 createChildAlgorithm("BinMD", soIndex * 0.3 * progress_fraction, (soIndex + 1) * 0.3 * progress_fraction);
1205
1206 binMD->setPropertyValue("AxisAligned", "0");
1207 binMD->setProperty("InputWorkspace", m_backgroundWS);
1208 binMD->setProperty("TemporaryDataWorkspace", tempBkgdDataWS);
1209 binMD->setPropertyValue("NormalizeBasisVectors", "0");
1210 // Set the output Workspace directly to Algorithm's
1211 // OutputBackgroundDataWorkspace
1212 binMD->setPropertyValue("OutputWorkspace", getPropertyValue("OutputBackgroundDataWorkspace"));
1213 // set binning properties
1214 size_t qindex = 0;
1215 for (const auto &p : parameters) {
1216 auto key = p.first;
1217 auto value = p.second;
1218 std::stringstream basisVector;
1219 std::vector<double> projection(m_inputWS->getNumDims(), 0.);
1220 // value is a string that can start with QDimension0, etc, but contain
1221 // other stuff. Do not use ==
1222 determineBasisVector(qindex, value, Qtransform, projection, basisVector, qDimensionIndices);
1223
1224 if (!basisVector.str().empty()) {
1225 // reconstruct from calculated basis vector
1226 for (auto proji : projection) {
1227 proji = std::abs(proji) > 1e-10 ? proji : 0.0;
1228 basisVector << "," << proji;
1229 }
1230 value = basisVector.str();
1231 }
1232
1233 binMD->setPropertyValue(key, value);
1234 qindex++;
1235 }
1236 // execute algorithm
1237 binMD->executeAsChildAlg();
1238
1239 // set the temporary workspace to be the output workspace, so it keeps
1240 // adding different symmetries AND
1241 // FIXME in future another ExpInfo
1242 outputWS = binMD->getProperty("OutputWorkspace");
1243 tempBkgdDataWS = std::dynamic_pointer_cast<MDHistoWorkspace>(outputWS);
1244 tempBkgdDataWS->clearOriginalWorkspaces();
1245 tempBkgdDataWS->clearTransforms();
1246 }
1247 }
1248 auto outputMDHWS = std::dynamic_pointer_cast<MDHistoWorkspace>(outputWS);
1249 // set MDUnits for Q dimensions
1250 if (m_isRLU) {
1251 setQUnit(qDimensionIndices, outputMDHWS);
1252 }
1253
1254 outputMDHWS->setDisplayNormalization(Mantid::API::NoNormalization);
1255 return outputMDHWS;
1256}
1257
1263DataObjects::MDHistoWorkspace_sptr MDNorm::binInputWS(const std::vector<Geometry::SymmetryOperation> &symmetryOps) {
1264 std::map<std::string, std::string> parameters = getBinParameters();
1265 return binMDEventWorkspace(m_inputWS, "TemporaryDataWorkspace", "OutputDataWorkspace", symmetryOps, parameters);
1266}
1267
1276MDNorm::binMonoSCDNormalizationWS(const std::vector<Geometry::SymmetryOperation> &symmetryOps) {
1277 std::map<std::string, std::string> parameters = getBinParameters();
1278 Mantid::API::IMDEventWorkspace_sptr monoNormInputWS = this->getProperty("MonoSCDNormalizationWorkspace");
1279 return binMDEventWorkspace(monoNormInputWS, "TemporaryNormalizationWorkspace", "OutputNormalizationWorkspace",
1280 symmetryOps, parameters);
1281}
1282
1298MDNorm::binMDEventWorkspace(const API::IMDEventWorkspace_sptr &ws, const std::string &temporaryWSPropertyName,
1299 const std::string &outputWSPropertyName,
1300 const std::vector<Geometry::SymmetryOperation> &symmetryOps,
1301 const std::map<std::string, std::string> &parameters) {
1302 Mantid::API::IMDHistoWorkspace_sptr tempWS = this->getProperty(temporaryWSPropertyName);
1304
1305 // check that our input matches the temporary workspace
1306 if (tempWS)
1307 validateBinningForTemporaryDataWorkspace(parameters, tempWS);
1308
1309 double soIndex = 0;
1310 std::vector<size_t> qDimensionIndices;
1311 for (const auto &so : symmetryOps) {
1312 // calculate dimensions for binning
1313 DblMatrix soMatrix = buildSymmetryMatrix(so);
1314 DblMatrix Qtransform;
1315
1316 if (m_isRLU) {
1317 Qtransform = m_UB * soMatrix * m_W;
1318 } else {
1319 Qtransform = soMatrix * m_W;
1320 }
1321
1322 // bin the data
1323 double fraction = 1. / static_cast<double>(symmetryOps.size());
1324 auto binMD = createChildAlgorithm("BinMD", soIndex * 0.3 * fraction, (soIndex + 1) * 0.3 * fraction);
1325 binMD->setPropertyValue("AxisAligned", "0");
1326 binMD->setProperty("InputWorkspace", ws);
1327 binMD->setProperty("TemporaryDataWorkspace", tempWS);
1328 binMD->setPropertyValue("NormalizeBasisVectors", "0");
1329 binMD->setPropertyValue("OutputWorkspace", getPropertyValue(outputWSPropertyName));
1330 // set binning properties
1331 size_t qindex = 0;
1332 for (const auto &p : parameters) {
1333 auto value = p.second;
1334 std::stringstream basisVector;
1335 std::vector<double> projection(ws->getNumDims(), 0.);
1336 // value is a string that can start with QDimension0, etc, but contain
1337 // other stuff. Do not use ==
1338 determineBasisVector(qindex, value, Qtransform, projection, basisVector, qDimensionIndices);
1339
1340 if (!basisVector.str().empty()) {
1341 // reconstruct from calculated basis vector
1342 for (auto proji : projection) {
1343 proji = std::abs(proji) > 1e-10 ? proji : 0.0;
1344 basisVector << "," << proji;
1345 }
1346 value = basisVector.str();
1347 }
1348
1349 binMD->setPropertyValue(p.first, value);
1350 qindex++;
1351 }
1352 // execute algorithm
1353 binMD->executeAsChildAlg();
1354 outputWS = binMD->getProperty("OutputWorkspace");
1355
1356 // set the temporary workspace to be the output workspace, so it keeps
1357 // adding different symmetries
1358 tempWS = std::dynamic_pointer_cast<MDHistoWorkspace>(outputWS);
1359 tempWS->clearOriginalWorkspaces();
1360 tempWS->clearTransforms();
1361 soIndex += 1;
1362 }
1363
1364 auto outputMDHWS = std::dynamic_pointer_cast<MDHistoWorkspace>(outputWS);
1365 // set MDUnits for Q dimensions
1366 if (m_isRLU) {
1367 setQUnit(qDimensionIndices, outputMDHWS);
1368 }
1369
1370 outputMDHWS->setDisplayNormalization(Mantid::API::NoNormalization);
1371 return outputMDHWS;
1372}
1373
1382std::vector<coord_t> MDNorm::getValuesFromOtherDimensions(bool &skipNormalization, uint16_t expInfoIndex) const {
1383 const auto &currentRun = m_inputWS->getExperimentInfo(expInfoIndex)->run();
1384
1385 std::vector<coord_t> otherDimValues;
1386 for (size_t i = 3; i < m_inputWS->getNumDims(); i++) {
1387 const auto dimension = m_inputWS->getDimension(i);
1388 auto inputDimMin = static_cast<float>(dimension->getMinimum());
1389 auto inputDimMax = static_cast<float>(dimension->getMaximum());
1390 coord_t outputDimMin(0), outputDimMax(0);
1391 bool isIntegrated = true;
1392
1393 for (size_t j = 0; j < m_transformation.numRows(); j++) {
1394 if (m_transformation[j][i] == 1) {
1395 isIntegrated = false;
1396 outputDimMin = m_normWS->getDimension(j)->getMinimum();
1397 outputDimMax = m_normWS->getDimension(j)->getMaximum();
1398 }
1399 }
1400 if (dimension->getName() == "DeltaE") {
1401 if ((inputDimMax < outputDimMin) || (inputDimMin > outputDimMax)) {
1402 skipNormalization = true;
1403 }
1404 } else {
1405 coord_t value = static_cast<coord_t>(
1406 currentRun.getLogAsSingleValue(dimension->getName(), Mantid::Kernel::Math::TimeAveragedMean));
1407 otherDimValues.emplace_back(value);
1408 if (value < inputDimMin || value > inputDimMax) {
1409 skipNormalization = true;
1410 }
1411 if ((!isIntegrated) && (value < outputDimMin || value > outputDimMax)) {
1412 skipNormalization = true;
1413 }
1414 }
1415 }
1416 return otherDimValues;
1417}
1418
1419} // namespace Mantid::MDAlgorithms
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:547
gsl_vector * tmp
const std::vector< double > & rhs
double value
The value of the point.
Definition FitMW.cpp:51
IPeaksWorkspace_sptr workspace
#define fabs(x)
Definition Matrix.cpp:22
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
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.
Kernel::Logger & g_log
Definition Algorithm.h:426
A validator which provides a TENTATIVE check that a workspace contains common bins in each spectrum.
Kernel::IValidator_sptr clone() const override
Clone the current state.
Abstract base class for multi-dimension event workspaces (MDEventWorkspace).
A validator which checks that a workspace has a valid instrument.
A property class for workspaces.
std::unique_ptr< MDHistoWorkspace > clone() const
Returns a clone of the workspace.
static const std::string HKLName
Definition HKL.h:26
Input argument type for MDFrameFactory chainable factory.
Class to implement UB matrix.
void setUB(const Kernel::DblMatrix &newUB)
Sets the UB matrix and recalculates lattice parameters.
static const std::string QLabName
Definition QLab.h:34
static const std::string QSampleName
Definition QSample.h:22
Crystallographic symmetry operations are composed of a rotational component, which is represented by ...
Kernel::V3D transformHKL(const Kernel::V3D &hkl) const
Transforms an index triplet hkl.
double a(int nd) const
Get lattice parameter a1-a3 as function of index (0-2)
Definition UnitCell.cpp:94
double c() const
Get lattice parameter.
Definition UnitCell.cpp:128
double b() const
Get lattice parameter.
Definition UnitCell.cpp:123
Support for a property that holds an array of values.
Exception for errors associated with the instrument definition.
Definition Exception.h:220
Records the filename, the description of failure and the line on which it happened.
Definition Exception.h:115
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void setPropertySettings(const std::string &name, std::unique_ptr< IPropertySettings const > settings)
Add a PropertySettings instance to the chain of settings for a given property.
void setPropertyGroup(const std::string &name, const std::string &group)
Set the group for a given property.
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
T determinant() const
Calculate the determinant.
Definition Matrix.cpp:1048
T Invert()
LU inversion routine.
Definition Matrix.cpp:924
std::vector< T > getVector() const
Definition Matrix.cpp:77
size_t numRows() const
Return the number of rows in the matrix.
Definition Matrix.h:143
void setColumn(const size_t nCol, const std::vector< T > &newCol)
Definition Matrix.cpp:675
Matrix< T > & Transpose()
Transpose the matrix.
Definition Matrix.cpp:793
The concrete, templated class for properties.
Base class for properties.
Definition Property.h:95
virtual std::string value() const =0
Returns the value of the property as a string.
static const UnitLabel RLU
Reciprocal lattice units.
Class for 3D vectors.
Definition V3D.h:35
std::vector< std::atomic< signal_t > > m_bkgdSignalArray
Definition MDNormBase.h:107
API::IMDEventWorkspace_sptr m_inputWS
Input workspace.
Definition MDNormBase.h:69
bool m_hIntegrated
flag for integrated h,k,l, dE dimensions
Definition MDNormBase.h:80
void createNormalizationWS(const DataObjects::MDHistoWorkspace &dataWS)
Create & cached the normalization workspace.
bool m_diffraction
Flag indicating if the input workspace is from diffraction.
Definition MDNormBase.h:100
API::IMDEventWorkspace_sptr m_backgroundWS
Input background workspace.
Definition MDNormBase.h:74
void cacheDimensionXValues()
Stores the X values from each H,K,L,E dimension as member variables Energy dimension is transformed t...
Mantid::Kernel::DblMatrix m_W
W matrix.
Definition MDNormBase.h:84
void calculateNormalization(const std::vector< coord_t > &otherValues, uint16_t expInfoIndex)
Computed the normalization for the input workspace (for MDNormSCD/MDNormDirectSC).
DataObjects::MDHistoWorkspace_sptr m_normWS
Normalization workspace.
Definition MDNormBase.h:71
Kernel::V3D m_samplePos
Sample position.
Definition MDNormBase.h:92
std::vector< std::atomic< signal_t > > m_signalArray
internal array to accumulate signals to avoid copying (serial) each loop
Definition MDNormBase.h:106
bool m_accumulate
Flag to accumulate normalization.
Definition MDNormBase.h:102
DataObjects::MDHistoWorkspace_sptr binInputWS()
Runs the BinMD algorithm on the input to provide the output workspace All slicing algorithm propertie...
uint16_t m_numExptInfos
number of experiment infos
Definition MDNormBase.h:98
DataObjects::MDHistoWorkspace_sptr m_bkgdNormWS
Definition MDNormBase.h:72
Mantid::Kernel::Matrix< coord_t > m_transformation
matrix for transforming from intersections to positions in the normalization workspace
Definition MDNormBase.h:86
Kernel::V3D m_beamDir
Beam direction.
Definition MDNormBase.h:94
Mantid::Kernel::DblMatrix m_UB
UB matrix.
Definition MDNormBase.h:82
size_t m_hIdx
index of h,k,l, dE dimensions in the output workspaces
Definition MDNormBase.h:88
std::unique_ptr< API::Progress > m_progress
Progress bar.
Definition MDNormBase.h:104
void calculateNormContinuous(const std::vector< coord_t > &otherValues, uint16_t expInfoIndex, const Geometry::SymmetryOperation *so=nullptr)
Computes the normalization for the input workspace for the case of a continous rotation.
std::string m_convention
ki-kf for Inelastic convention; kf-ki for Crystallography convention
Definition MDNormBase.h:96
double m_Ei
cached values for incident energy and momentum, final momentum min/max
Definition MDNormBase.h:78
MDNormalization : Bin single crystal diffraction or direct geometry inelastic data and calculate the ...
Definition MDNorm.h:20
size_t m_numSymmOps
number of symmetry operations
Definition MDNorm.h:81
bool m_monochromatic
Flag indicating a pre-computed MonoSCDNormalizationWorkspace was provided (monochromatic single cryst...
Definition MDNorm.h:84
DataObjects::MDHistoWorkspace_sptr binBackgroundWS(const std::vector< Geometry::SymmetryOperation > &symmetryOps)
Bin(MD) input Background workspace.
Definition MDNorm.cpp:1163
std::string QDimensionName(std::vector< double > projection)
Get the dimension name when using reciprocal lattice units.
Definition MDNorm.cpp:697
void exec() override
Execute the algorithm.
Definition MDNorm.cpp:508
std::vector< double > m_Q0Basis
The projection vectors.
Definition MDNorm.h:79
const std::string summary() const override
Algorithm's summary for use in the GUI and help.
Definition MDNorm.cpp:81
std::map< std::string, std::string > getBinParameters()
Calculate binning parameters.
Definition MDNorm.cpp:726
API::IMDWorkspace_sptr divideMD(const API::IMDHistoWorkspace_sptr &lhs, const API::IMDHistoWorkspace_sptr &rhs, const std::string &outputwsname, const double &startProgress, const double &endProgress)
Definition MDNorm.cpp:662
const std::string category() const override
Algorithm's category for identification.
Definition MDNorm.cpp:78
std::vector< coord_t > getValuesFromOtherDimensions(bool &skipNormalization, uint16_t expInfoIndex=0) const
Retrieve logged values from non-HKL dimensions.
Definition MDNorm.cpp:1382
void setQUnit(const std::vector< size_t > &qDimensionIndices, const Mantid::DataObjects::MDHistoWorkspace_sptr &outputMDHWS)
Set the output Frame to HKL.
Definition MDNorm.cpp:1142
std::vector< double > m_Q1Basis
Definition MDNorm.h:79
void validateBinningForTemporaryDataWorkspace(const std::map< std::string, std::string > &, const Mantid::API::IMDHistoWorkspace_sptr &)
Validates the TemporaryDataWorkspace has the same binning as the input binning parameters.
Definition MDNorm.cpp:907
Mantid::Kernel::DblMatrix buildSymmetryMatrix(const Geometry::SymmetryOperation &so)
build symmetry matrix
Definition MDNorm.cpp:1066
DataObjects::MDHistoWorkspace_sptr binMonoSCDNormalizationWS(const std::vector< Geometry::SymmetryOperation > &symmetryOps)
Bin(MD) MonoSCDNormalizationWorkspace (monochromatic single crystal diffraction)
Definition MDNorm.cpp:1276
std::string QDimensionNameQSample(int i)
Get the dimension name when not using reciprocal lattice units.
Definition MDNorm.cpp:681
const std::string name() const override
Algorithms name for identification.
Definition MDNorm.cpp:72
std::vector< double > m_Q2Basis
Definition MDNorm.h:79
bool m_isRLU
flag for reciprocal lattice units
Definition MDNorm.h:77
DataObjects::MDHistoWorkspace_sptr binMDEventWorkspace(const API::IMDEventWorkspace_sptr &ws, const std::string &temporaryWSPropertyName, const std::string &outputWSPropertyName, const std::vector< Geometry::SymmetryOperation > &symmetryOps, const std::map< std::string, std::string > &parameters)
Bin(MD), per symmetry operation, an MDEventWorkspace using pre-computed bin parameters.
Definition MDNorm.cpp:1298
std::map< std::string, std::string > validateInputs() override final
Validate the input workspace.
Definition MDNorm.cpp:228
void determineBasisVector(const size_t &qindex, const std::string &value, const Kernel::DblMatrix &Qtransform, std::vector< double > &projection, std::stringstream &basisVector, std::vector< size_t > &qDimensionIndices)
MDNorm::determineBasisVector.
Definition MDNorm.cpp:1092
int version() const override
Algorithm's version for identification.
Definition MDNorm.cpp:75
void init() override
Initialize the algorithm's properties.
Definition MDNorm.cpp:89
void createBackgroundNormalizationWS(const DataObjects::MDHistoWorkspace &dataWS)
Definition MDNorm.cpp:885
std::shared_ptr< IMDEventWorkspace > IMDEventWorkspace_sptr
Shared pointer to Mantid::API::IMDEventWorkspace.
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
std::shared_ptr< IMDHistoWorkspace > IMDHistoWorkspace_sptr
shared pointer to Mantid::API::IMDHistoWorkspace
std::shared_ptr< IMDWorkspace > IMDWorkspace_sptr
Shared pointer to the IMDWorkspace base class.
@ NoNormalization
Don't normalize = return raw counts.
Definition IMDIterator.h:27
std::shared_ptr< MDHistoWorkspace > MDHistoWorkspace_sptr
A shared pointer to a MDHistoWorkspace.
std::unique_ptr< MDFrame > MDFrame_uptr
Definition MDFrame.h:36
MDFrameFactory_uptr MANTID_GEOMETRY_DLL makeMDFrameFactoryChain()
Make a complete factory chain.
std::string toString(const T &value)
Convert a number to a string.
Definition Strings.cpp:735
template MANTID_KERNEL_DLL std::vector< double > splitStringIntoVector< double >(std::string listString, const std::string &separator)
template MANTID_KERNEL_DLL std::vector< size_t > splitStringIntoVector< size_t >(std::string listString, const std::string &separator)
MANTID_KERNEL_DLL V3D normalize(V3D v)
Normalizes a V3D.
Definition V3D.h:353
Mantid::Kernel::Matrix< double > DblMatrix
Definition Matrix.h:205
Kernel::PropertyWithValue< std::vector< double > > VectorDoubleProperty
static constexpr double NeutronMass
Mass of the neutron in kg.
static constexpr double h
Planck constant in J*s.
static constexpr double meV
1 meV in Joules.
float coord_t
Typedef for the data type to use for coordinate axes in MD objects such as MDBox, MDEventWorkspace,...
Definition MDTypes.h:27
double signal_t
Typedef for the signal recorded in a MDBox, etc.
Definition MDTypes.h:36
@ Input
An input workspace.
Definition Property.h:54
@ Output
An output workspace.
Definition Property.h:55