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