34#include <boost/lexical_cast.hpp>
46bool compareMomentum(
const std::array<double, 4> &v1,
const std::array<double, 4> &v2) {
return (v1[3] < v2[3]); }
53static bool abs_compare(
double a,
double b) {
return (std::fabs(a) < std::fabs(b)); }
64 : m_normWS(), m_inputWS(), m_isRLU(false), m_UB(3, 3, true), m_W(3, 3, true), m_transformation(), m_hX(), m_kX(),
65 m_lX(), m_eX(), m_hIdx(-1), m_kIdx(-1), m_lIdx(-1), m_eIdx(-1), m_numExptInfos(0), m_Ei(0.0), m_diffraction(true),
66 m_accumulate(false), m_dEIntegrated(true), m_samplePos(), m_beamDir(), convention("") {}
79 return "Bins multidimensional data and calculate the normalization on the "
89 "An input MDEventWorkspace. Must be in Q_sample frame.");
93 "An (optional) input MDEventWorkspace for background. Must be in Q_lab frame.");
96 declareProperty(
"RLU",
true,
"Use reciprocal lattice units. If false, use Q_sample");
99 auto mustBe3D = std::make_shared<Kernel::ArrayLengthValidator<double>>(3);
100 std::vector<double> Q0(3, 0.), Q1(3, 0), Q2(3, 0);
106 "The first Q projection axis - Default is (1,0,0)");
111 "The second Q projection axis - Default is (0,1,0)");
116 "The thirdtCalculateCover Q projection axis - Default is (0,0,1)");
121 auto fluxValidator = std::make_shared<CompositeValidator>();
124 auto solidAngleValidator = fluxValidator->
clone();
127 "An input workspace containing integrated vanadium "
128 "(a measure of the solid angle).\n"
129 "Mandatory for diffraction, optional for direct geometry inelastic");
132 "An input workspace containing momentum dependent flux.\n"
133 "Mandatory for diffraction. No effect on direct geometry inelastic");
138 for (std::size_t i = 0; i < 6; i++) {
141 std::string defaultName =
"";
147 auto atMost3 = std::make_shared<ArrayLengthValidator<double>>(0, 3);
148 std::vector<double> temp;
151 "- Leave blank for complete integration\n" +
152 "- One value is interpreted as step\n"
153 "- Two values are interpreted integration interval\n" +
154 "- Three values are interpreted as min, step, max");
161 "If specified the symmetry will be applied, "
162 "can be space group name, point group name, or list "
163 "individual symmetries.");
168 "An (optional) input MDHistoWorkspace used to accumulate data from "
169 "multiple MDEventWorkspaces. If unspecified a blank "
170 "MDHistoWorkspace will be created.");
173 "An (optional) input MDHistoWorkspace used to accumulate normalization "
174 "from multiple MDEventWorkspaces. If unspecified a blank "
175 "MDHistoWorkspace will be created.");
180 "An (optional) input MDHistoWorkspace used to accumulate background from "
181 "multiple background MDEventWorkspaces. If unspecified but "
182 "BackgroundWorkspace is specified, a blank "
183 "MDHistoWorkspace will be created.");
186 "An (optional) input MDHistoWorkspace used to accumulate background normalization "
187 "from multiple background MDEventWorkspaces. If unspecified but "
188 "BackgroundWorkspace is specified, a blank "
189 "MDHistoWorkspace will be created.");
192 setPropertyGroup(
"TemporaryNormalizationWorkspace",
"Temporary workspaces");
193 setPropertyGroup(
"TemporaryBackgroundDataWorkspace",
"Temporary workspaces");
194 setPropertyGroup(
"TemporaryBackgroundNormalizationWorkspace",
"Temporary workspaces");
197 "A name for the normalized output MDHistoWorkspace.");
200 "A name for the output data MDHistoWorkspace.");
202 "A name for the output normalization MDHistoWorkspace.");
205 "A name for the optional output background data MDHistoWorkspace.");
208 "A name for the optional output background normalization MDHistoWorkspace.");
214 std::map<std::string, std::string> errorMessage;
218 if (inputWS->getNumDims() < 3) {
219 errorMessage.emplace(
"InputWorkspace",
"The input workspace must be at least 3D");
221 for (
size_t i = 0; i < 3; i++) {
223 errorMessage.emplace(
"InputWorkspace",
"The input workspace must be in Q_sample");
231 if (bkgdWS->getNumDims() < 3) {
233 errorMessage.emplace(
"BackgroundWorkspace",
"The input background workspace must be at least 3D");
236 for (
size_t i = 0; i < 3; i++) {
238 errorMessage.emplace(
"BackgroundWorkspace",
"The input backgound workspace must be in Q_lab");
243 if (inputWS->getNumDims() > 3) {
244 if (bkgdWS->getNumDims() <= 3) {
245 errorMessage.emplace(
"BackgroundWorkspace",
"The input background workspace must have at 4 dimensions when "
246 "input workspace has more than 4 dimensions (inelastic case).");
247 }
else if (bkgdWS->getDimension(3)->getName() != inputWS->getDimension(3)->getName()) {
248 errorMessage.emplace(
"BackgroundWorkspace",
"The input background workspace 4th dimension must be DeltaE "
249 "for inelastic case.");
256 bool diffraction =
true;
257 if ((inputWS->getNumDims() > 3) && (inputWS->getDimension(3)->getName() ==
"DeltaE")) {
263 if (solidAngleWS ==
nullptr) {
264 errorMessage.emplace(
"SolidAngleWorkspace",
"SolidAngleWorkspace is required for diffraction");
266 if (fluxWS ==
nullptr) {
267 errorMessage.emplace(
"FluxWorkspace",
"FluxWorkspace is required for diffraction");
271 size_t nExperimentInfos = inputWS->getNumExperimentInfo();
272 if (nExperimentInfos == 0) {
273 errorMessage.emplace(
"InputWorkspace",
"There must be at least one experiment info");
275 for (
size_t iExpInfo = 0; iExpInfo < nExperimentInfos; iExpInfo++) {
276 auto ¤tExptInfo = *(inputWS->getExperimentInfo(
static_cast<uint16_t
>(iExpInfo)));
277 if (!currentExptInfo.run().hasProperty(
"MDNorm_low")) {
278 errorMessage.emplace(
"InputWorkspace",
"Missing MDNorm_low log. Please "
279 "use CropWorkspaceForMDNorm "
280 "before converting to MD");
282 if (!currentExptInfo.run().hasProperty(
"MDNorm_high")) {
283 errorMessage.emplace(
"InputWorkspace",
"Missing MDNorm_high log. Please use "
284 "CropWorkspaceForMDNorm before converting to MD");
291 std::vector<double> Q0Basis =
getProperty(
"QDimension0");
292 std::vector<double> Q1Basis =
getProperty(
"QDimension1");
293 std::vector<double> Q2Basis =
getProperty(
"QDimension2");
298 errorMessage.emplace(
"QDimension0",
"The projection dimensions are coplanar or zero");
299 errorMessage.emplace(
"QDimension1",
"The projection dimensions are coplanar or zero");
300 errorMessage.emplace(
"QDimension2",
"The projection dimensions are coplanar or zero");
302 if (!inputWS->getExperimentInfo(0)->sample().hasOrientedLattice()) {
303 errorMessage.emplace(
"InputWorkspace",
"There is no oriented lattice "
304 "associated with the input workspace. "
305 "Use SetUB algorithm");
309 std::vector<std::string> originalDimensionNames;
310 for (
size_t i = 3; i < inputWS->getNumDims(); i++) {
311 originalDimensionNames.emplace_back(inputWS->getDimension(i)->getName());
313 originalDimensionNames.emplace_back(
"QDimension0");
314 originalDimensionNames.emplace_back(
"QDimension1");
315 originalDimensionNames.emplace_back(
"QDimension2");
316 std::vector<std::string> selectedDimensions;
317 for (std::size_t i = 0; i < 6; i++) {
321 std::vector<double> binning =
getProperty(binningName);
322 if (!dimName.empty()) {
323 auto it = std::find(originalDimensionNames.begin(), originalDimensionNames.end(), dimName);
324 if (it == originalDimensionNames.end()) {
325 errorMessage.emplace(propName,
"Name '" + dimName +
326 "' is not one of the "
327 "original workspace names or a directional dimension");
330 auto itSel = std::find(selectedDimensions.begin(), selectedDimensions.end(), dimName);
331 if (itSel == selectedDimensions.end()) {
332 selectedDimensions.emplace_back(dimName);
334 errorMessage.emplace(propName,
"Name '" + dimName +
"' was already selected");
338 if (!binning.empty()) {
339 errorMessage.emplace(binningName,
"There should be no binning if the dimension name is empty");
344 if ((std::find(selectedDimensions.begin(), selectedDimensions.end(),
"QDimension0") == selectedDimensions.end()) ||
345 (std::find(selectedDimensions.begin(), selectedDimensions.end(),
"QDimension1") == selectedDimensions.end()) ||
346 (std::find(selectedDimensions.begin(), selectedDimensions.end(),
"QDimension2") == selectedDimensions.end())) {
347 for (std::size_t i = 0; i < 6; i++) {
349 errorMessage.emplace(propName,
"All of QDimension0, QDimension1, QDimension2 must be present");
353 std::string symOps = this->
getProperty(
"SymmetryOperations");
354 if (!symOps.empty()) {
357 if (!isSpaceGroup && !isPointGroup) {
361 errorMessage.emplace(
"SymmetryOperations",
"The input is not a space group, a point group, "
362 "or a list of symmetry operations");
367 std::shared_ptr<IMDHistoWorkspace> tempNormWS = this->
getProperty(
"TemporaryNormalizationWorkspace");
371 if ((tempNormWS && !tempDataWS) || (!tempNormWS && tempDataWS)) {
372 errorMessage.emplace(
"TemporaryDataWorkspace",
"Must provide either no accumulation workspaces or,"
373 "both TemporaryNormalizationWorkspaces and TemporaryDataWorkspace");
376 if (tempNormWS && tempDataWS) {
377 size_t numNormDims = tempNormWS->getNumDims();
378 size_t numDataDims = tempDataWS->getNumDims();
379 if (numNormDims == numDataDims) {
380 for (
size_t i = 0; i < numNormDims; i++) {
381 const auto dim1 = tempNormWS->getDimension(i);
382 const auto dim2 = tempDataWS->getDimension(i);
383 if ((dim1->getMinimum() != dim2->getMinimum()) || (dim1->getMaximum() != dim2->getMaximum()) ||
384 (dim1->getNBins() != dim2->getNBins()) || (dim1->getName() != dim2->getName())) {
385 errorMessage.emplace(
"TemporaryDataWorkspace",
"Binning for TemporaryNormalizationWorkspaces "
386 "and TemporaryDataWorkspace must be the same.");
391 errorMessage.emplace(
"TemporaryDataWorkspace",
"TemporaryNormalizationWorkspace and TemporaryDataWorkspace "
392 "do not have the same number of dimensions");
401 if (tempBkgdDataWS && (!bkgdWS || !tempDataWS || !tempBkgdNormWS)) {
402 errorMessage.emplace(
"TemporaryBackgroundDataWorkspace",
"TemporaryBackgroundDataWorkspace is specified but at "
403 "least one of these is not.");
404 }
else if (tempBkgdNormWS && (!bkgdWS || !tempNormWS || !tempBkgdDataWS)) {
405 errorMessage.emplace(
"TemporaryBackgroundNormalizationWorkspace",
"TemporaryBackgroundNormalizationWorkspace is "
406 "specified but at least one of these is not.");
407 }
else if (bkgdWS && tempDataWS && !tempBkgdDataWS) {
408 errorMessage.emplace(
"TemporaryDataWorkspace",
409 "With Background is specifed and TemporaryDataWorkspace is specifed, "
410 "TemporaryBackgroundDataWorkspace must be specified.");
411 }
else if (tempBkgdDataWS && tempNormWS) {
413 size_t numBkgdDataDims = tempBkgdDataWS->getNumDims();
414 size_t numBkgdNormDims = tempBkgdNormWS->getNumDims();
415 size_t numDataDims = tempDataWS->getNumDims();
416 if (numBkgdDataDims == numBkgdNormDims && numBkgdDataDims == numDataDims) {
418 for (
size_t idim = 0; idim < numBkgdDataDims; ++idim) {
419 const auto dimB = tempBkgdDataWS->getDimension(idim);
420 const auto dimN = tempBkgdNormWS->getDimension(idim);
421 const auto dimD = tempDataWS->getDimension(idim);
422 if ((dimB->getMinimum() != dimN->getMinimum()) || (dimB->getMinimum() != dimD->getMinimum()) ||
423 (dimB->getMaximum() != dimN->getMaximum()) || (dimB->getMaximum() != dimD->getMaximum()) ||
424 (dimB->getNBins() != dimN->getNBins()) || (dimB->getNBins() != dimD->getNBins()) ||
425 (dimB->getName() != dimN->getName()) || (dimB->getName() != dimD->getName())) {
426 errorMessage.emplace(
"TemporaryBackgroundDataWorkspace",
427 "TemporaryBackgroundDataWorkspace, "
428 "TemporaryBackgroundNormalizationWorkspace and "
429 "TemporaryDataWorkspace "
430 "must have same minimum, maximum, number of bins and name.");
435 errorMessage.emplace(
"TemporaryBackgroundDataWorkspace",
"TemporaryBackgroundDataWorkspace, "
436 "TemporaryBackgroundNormalizationWorkspace and "
437 "TemporaryDataWorkspace must have same dimensions");
450 std::string symOps = this->
getProperty(
"SymmetryOperations");
451 std::vector<Geometry::SymmetryOperation> symmetryOps;
452 if (symOps.empty()) {
457 auto pointGroup = spaceGroup->getPointGroup();
458 symmetryOps = pointGroup->getSymmetryOperations();
461 symmetryOps = pointGroup->getSymmetryOperations();
466 for (
auto so : symmetryOps) {
474 const auto &exptInfoZero = *(
m_inputWS->getExperimentInfo(0));
475 auto source = exptInfoZero.getInstrument()->getSource();
476 auto sample = exptInfoZero.getInstrument()->getSample();
477 if (source ==
nullptr || sample ==
nullptr) {
479 "Instrument not sufficiently defined: failed to get source and/or "
484 if ((
m_inputWS->getNumDims() > 3) && (
m_inputWS->getDimension(3)->getName() ==
"DeltaE")) {
487 if (exptInfoZero.run().hasProperty(
"Ei")) {
489 m_Ei = boost::lexical_cast<double>(eiprop->
value());
491 throw std::invalid_argument(
"Ei stored in the workspace is not positive");
494 throw std::invalid_argument(
"Could not find Ei value in the workspace.");
503 this->
setProperty(
"OutputDataWorkspace", outputDataWS);
513 this->
setProperty(
"OutputBackgroundDataWorkspace", outputBackgroundDataWS);
518 for (uint16_t expInfoIndex = 0; expInfoIndex <
m_numExptInfos; expInfoIndex++) {
521 bool skipNormalization =
false;
526 if (!skipNormalization) {
527 size_t symmOpsIndex = 0;
528 for (
const auto &so : symmetryOps) {
534 g_log.
warning(
"Binning limits are outside the limits of the MDWorkspace. "
535 "Not applying normalization.");
548 const std::string normedBkgdWSName(
"_normedBkgd");
554 minusMD->setProperty(
"LHSWorkspace", out);
555 minusMD->setProperty(
"RHSWorkspace", outbkgd);
556 minusMD->setPropertyValue(
"OutputWorkspace",
getPropertyValue(
"OutputWorkspace"));
558 minusMD->executeAsChildAlg();
559 out = minusMD->getProperty(
"OutputWorkspace");
572 const double &startProgress,
const double &endProgress) {
574 divideMD->setProperty(
"LHSWorkspace", lhs);
576 divideMD->setPropertyValue(
"OutputWorkspace", outputwsname);
591 return std::string(
"Q_sample_x");
593 return std::string(
"Q_sample_y");
595 return std::string(
"Q_sample_z");
597 throw std::invalid_argument(
"Index must be 0, 1, or 2 for QDimensionNameQSample");
606 std::vector<double>::iterator result;
607 result = std::max_element(projection.begin(), projection.end(), abs_compare);
608 std::vector<char> symbol{
'H',
'K',
'L'};
609 char character = symbol[std::distance(projection.begin(), result)];
610 std::stringstream
name;
612 for (
size_t i = 0; i < 3; i++) {
613 if (projection[i] == 0) {
615 }
else if (projection[i] == 1) {
617 }
else if (projection[i] == -1) {
618 name <<
"-" << character;
620 name << std::defaultfloat << std::setprecision(3) << projection[i] << character;
635 std::map<std::string, std::string> parameters;
636 std::stringstream extents;
637 std::stringstream bins;
638 std::vector<std::string> originalDimensionNames;
639 originalDimensionNames.emplace_back(
"QDimension0");
640 originalDimensionNames.emplace_back(
"QDimension1");
641 originalDimensionNames.emplace_back(
"QDimension2");
642 for (
size_t i = 3; i <
m_inputWS->getNumDims(); i++) {
643 originalDimensionNames.emplace_back(
m_inputWS->getDimension(i)->getName());
650 m_UB =
m_inputWS->getExperimentInfo(0)->sample().getOrientedLattice().getUB() * 2 * M_PI;
660 auto &exptInfo0 = *(
m_inputWS->getExperimentInfo(
static_cast<uint16_t
>(0)));
661 auto upperLimitsVector =
665 maxQ = 2. * (*std::max_element(upperLimitsVector.begin(), upperLimitsVector.end()));
668 double maxDE = *std::max_element(upperLimitsVector.begin(), upperLimitsVector.end());
669 auto loweLimitsVector =
671 double minDE = *std::min_element(loweLimitsVector.begin(), loweLimitsVector.end());
672 if (exptInfo0.run().hasProperty(
"Ei")) {
674 Ei = boost::lexical_cast<double>(eiprop->
value());
676 throw std::invalid_argument(
"Ei stored in the workspace is not positive");
679 throw std::invalid_argument(
"Could not find Ei value in the workspace.");
683 double ki = std::sqrt(energyToK * Ei);
684 double kfmin = std::sqrt(energyToK * (Ei - minDE));
685 double kfmax = std::sqrt(energyToK * (Ei - maxDE));
687 maxQ = ki + std::max(kfmin, kfmax);
689 size_t basisVectorIndex = 0;
690 std::vector<coord_t> transformation;
691 for (std::size_t i = 0; i < 6; i++) {
695 std::vector<double> binning =
getProperty(binningName);
696 std::string bv =
"BasisVector";
697 if (!dimName.empty()) {
699 std::stringstream propertyValue;
700 propertyValue << dimName;
702 auto dimIndex = std::distance(originalDimensionNames.begin(),
703 std::find(originalDimensionNames.begin(), originalDimensionNames.end(), dimName));
704 auto dimension =
m_inputWS->getDimension(dimIndex);
705 propertyValue <<
"," << dimension->getMDUnits().getUnitLabel().ascii();
706 for (
size_t j = 0; j < originalDimensionNames.size(); j++) {
707 if (j ==
static_cast<size_t>(dimIndex)) {
708 propertyValue <<
",1";
709 transformation.emplace_back(1.f);
711 propertyValue <<
",0";
712 transformation.emplace_back(0.f);
715 parameters.emplace(property, propertyValue.str());
717 coord_t dimMax = dimension->getMaximum();
718 coord_t dimMin = dimension->getMinimum();
723 dimMax =
static_cast<coord_t>(ol.
a() * maxQ);
725 }
else if (dimIndex == 1) {
726 dimMax =
static_cast<coord_t>(ol.
b() * maxQ);
728 }
else if (dimIndex == 2) {
729 dimMax =
static_cast<coord_t>(ol.
c() * maxQ);
733 if (binning.size() == 0) {
735 extents << dimMin <<
"," << dimMax <<
",";
737 }
else if (binning.size() == 2) {
739 extents << binning[0] <<
"," << binning[1] <<
",";
741 }
else if (binning.size() == 1) {
742 auto step = binning[0];
743 double nsteps = (dimMax - dimMin) / step;
744 if (nsteps + 1 - std::ceil(nsteps) >= 1e-4) {
745 nsteps = std::ceil(nsteps);
747 nsteps = std::floor(nsteps);
749 bins << static_cast<int>(nsteps) <<
",";
750 extents << dimMin <<
"," << dimMin + nsteps * step <<
",";
751 }
else if (binning.size() == 3) {
752 dimMin =
static_cast<coord_t>(binning[0]);
753 auto step = binning[1];
754 dimMax =
static_cast<coord_t>(binning[2]);
755 double nsteps = (dimMax - dimMin) / step;
756 if (nsteps + 1 - std::ceil(nsteps) >= 1e-4) {
757 nsteps = std::ceil(nsteps);
759 nsteps = std::floor(nsteps);
761 bins << static_cast<int>(nsteps) <<
",";
762 extents << dimMin <<
"," << dimMin + nsteps * step <<
",";
767 parameters.emplace(
"OutputExtents", extents.str());
768 parameters.emplace(
"OutputBins", bins.str());
770 transformation,
static_cast<size_t>((transformation.size()) /
m_inputWS->getNumDims()),
m_inputWS->getNumDims());
780 std::shared_ptr<IMDHistoWorkspace>
tmp = this->
getProperty(
"TemporaryNormalizationWorkspace");
781 m_normWS = std::dynamic_pointer_cast<MDHistoWorkspace>(
tmp);
799 std::shared_ptr<IMDHistoWorkspace>
tmp = this->
getProperty(
"TemporaryBackgroundNormalizationWorkspace");
819 const std::string numBinsStr = parameters.at(
"OutputBins");
820 const std::string extentsStr = parameters.at(
"OutputExtents");
825 size_t numDimsTemp = tempDataWS->getNumDims();
826 if ((numBins.size() != numDimsTemp) || (extents.size() != numDimsTemp * 2)) {
827 std::stringstream errorMessage;
828 errorMessage <<
"The number of dimensions in the output and ";
829 errorMessage <<
"TemporaryDataWorkspace are not the same.";
830 throw(std::invalid_argument(errorMessage.str()));
834 for (
size_t i = 0; i < numDimsTemp; i++) {
835 auto ax = tempDataWS->getDimension(i);
836 if (numBins[i] != ax->getNBins()) {
837 std::stringstream errorMessage;
838 errorMessage <<
"The number of bins output and number of bins in ";
839 errorMessage <<
"TemporaryDataWorkspace are not the same along ";
840 errorMessage <<
"dimension " << i;
841 throw(std::invalid_argument(errorMessage.str()));
843 if (std::abs(extents[2 * i] - ax->getMinimum()) > 1.e-5) {
844 std::stringstream errorMessage;
845 errorMessage <<
"The minimum binning value for the output and ";
846 errorMessage <<
"TemporaryDataWorkspace are not the same along ";
847 errorMessage <<
"dimension " << i;
848 throw(std::invalid_argument(errorMessage.str()));
850 if (std::abs(extents[2 * i + 1] - ax->getMaximum()) > 1.e-5) {
851 std::stringstream errorMessage;
852 errorMessage <<
"The maximum binning value for the output and ";
853 errorMessage <<
"TemporaryDataWorkspace are not the same along ";
854 errorMessage <<
"dimension " << i;
855 throw(std::invalid_argument(errorMessage.str()));
860 size_t parametersIndex = 0;
861 std::vector<size_t> dimensionIndex(numDimsTemp + 1, 3);
862 for (
auto const &p : parameters) {
864 auto value = p.second;
867 if (
value.find(
"QDimension0") != std::string::npos) {
868 dimensionIndex[0] = parametersIndex;
869 const std::string dimXName = tempDataWS->getDimension(parametersIndex)->getName();
872 std::stringstream errorMessage;
873 std::stringstream debugMessage;
874 errorMessage <<
"TemporaryDataWorkspace does not have the ";
875 errorMessage <<
"correct name for dimension " << parametersIndex;
877 debugMessage <<
" TemporaryDataWorkspace: " << dimXName;
879 throw(std::invalid_argument(errorMessage.str()));
883 std::stringstream errorMessage;
884 std::stringstream debugMessage;
885 errorMessage <<
"TemporaryDataWorkspace does not have the ";
886 errorMessage <<
"correct name for dimension " << parametersIndex;
888 debugMessage <<
" TemporaryDataWorkspace: " << dimXName;
890 throw(std::invalid_argument(errorMessage.str()));
893 }
else if (
value.find(
"QDimension1") != std::string::npos) {
894 dimensionIndex[1] = parametersIndex;
895 const std::string dimYName = tempDataWS->getDimension(parametersIndex)->getName();
898 std::stringstream errorMessage;
899 std::stringstream debugMessage;
900 errorMessage <<
"TemporaryDataWorkspace does not have the ";
901 errorMessage <<
"correct name for dimension " << parametersIndex;
903 debugMessage <<
" TemporaryDataWorkspace: " << dimYName;
905 throw(std::invalid_argument(errorMessage.str()));
909 std::stringstream errorMessage;
910 std::stringstream debugMessage;
911 errorMessage <<
"TemporaryDataWorkspace does not have the ";
912 errorMessage <<
"correct name for dimension " << parametersIndex;
914 debugMessage <<
" TemporaryDataWorkspace: " << dimYName;
916 throw(std::invalid_argument(errorMessage.str()));
919 }
else if (
value.find(
"QDimension2") != std::string::npos) {
920 dimensionIndex[2] = parametersIndex;
921 const std::string dimZName = tempDataWS->getDimension(parametersIndex)->getName();
924 std::stringstream errorMessage;
925 std::stringstream debugMessage;
926 errorMessage <<
"TemporaryDataWorkspace does not have the ";
927 errorMessage <<
"correct name for dimension " << parametersIndex;
929 debugMessage <<
" TemporaryDataWorkspace: " << dimZName;
931 throw(std::invalid_argument(errorMessage.str()));
935 std::stringstream errorMessage;
936 std::stringstream debugMessage;
937 errorMessage <<
"TemporaryDataWorkspace does not have the ";
938 errorMessage <<
"correct name for dimension " << parametersIndex;
940 debugMessage <<
" TemporaryDataWorkspace: " << dimZName;
942 throw(std::invalid_argument(errorMessage.str()));
946 }
else if ((key !=
"OutputBins") && (key !=
"OutputExtents")) {
948 const std::string nameData = tempDataWS->getDimension(parametersIndex)->getName();
949 if (
value.find(nameData) != 0) {
951 <<
" from the temporary workspace"
952 " is not one of the binning dimensions, "
953 " or dimensions are in the wrong order."
955 throw(std::invalid_argument(
"Beside the Q dimensions, "
956 "TemporaryDataWorkspace does not have the "
957 "same dimension names as OutputWorkspace."));
962 const auto it = std::find_if(dimensionIndex.cbegin(), dimensionIndex.cend(),
963 [numDimsTemp](
const auto &idx) { return idx > numDimsTemp; });
964 if (it != dimensionIndex.cend())
965 throw(std::invalid_argument(
"Cannot find at least one of QDimension0, "
966 "QDimension1, or QDimension2"));
1001 std::stringstream &basisVector, std::vector<size_t> &qDimensionIndices) {
1002 if (
value.find(
"QDimension0") != std::string::npos) {
1008 qDimensionIndices.emplace_back(qindex);
1009 projection[0] = Qtransform[0][0];
1010 projection[1] = Qtransform[1][0];
1011 projection[2] = Qtransform[2][0];
1014 }
else if (
value.find(
"QDimension1") != std::string::npos) {
1020 qDimensionIndices.emplace_back(qindex);
1021 projection[0] = Qtransform[0][1];
1022 projection[1] = Qtransform[1][1];
1023 projection[2] = Qtransform[2][1];
1026 }
else if (
value.find(
"QDimension2") != std::string::npos) {
1032 qDimensionIndices.emplace_back(qindex);
1033 projection[0] = Qtransform[0][2];
1034 projection[1] = Qtransform[1][2];
1035 projection[2] = Qtransform[2][2];
1038 }
else if (
value.find(
"DeltaE") != std::string::npos) {
1054 for (
size_t i : qDimensionIndices) {
1055 auto mdHistoDimension = std::const_pointer_cast<Mantid::Geometry::MDHistoDimension>(
1056 std::dynamic_pointer_cast<const Mantid::Geometry::MDHistoDimension>(outputMDHWS->getDimension(i)));
1057 mdHistoDimension->setMDFrame(*hklFrame);
1060 auto ei = outputMDHWS->getExperimentInfo(0);
1061 ei->mutableRun().addProperty(
"W_MATRIX",
m_W.
getVector(),
true);
1079 if (tempBkgdDataWS) {
1084 std::vector<size_t> qDimensionIndices;
1085 uint16_t numexpinfo =
static_cast<uint16_t
>(
m_inputWS->getNumExperimentInfo());
1087 throw std::runtime_error(
"Symmetry operation number m_umSymops is wrong!");
1089 for (uint16_t i_expinfo = 0; i_expinfo < numexpinfo; ++i_expinfo) {
1091 auto rotMatrix =
m_inputWS->getExperimentInfo(i_expinfo)->run().getGoniometerMatrix();
1096 for (
auto so : symmetryOps) {
1103 Qtransform = rotMatrix *
m_UB * soMatrix *
m_W;
1105 Qtransform = rotMatrix * soMatrix *
m_W;
1109 double progress_fraction = 1. /
static_cast<double>(symmetryOps.size() * numexpinfo);
1111 createChildAlgorithm(
"BinMD", soIndex * 0.3 * progress_fraction, (soIndex + 1) * 0.3 * progress_fraction);
1113 binMD->setPropertyValue(
"AxisAligned",
"0");
1115 binMD->setProperty(
"TemporaryDataWorkspace", tempBkgdDataWS);
1116 binMD->setPropertyValue(
"NormalizeBasisVectors",
"0");
1119 binMD->setPropertyValue(
"OutputWorkspace",
getPropertyValue(
"OutputBackgroundDataWorkspace"));
1122 for (
auto const &p : parameters) {
1124 auto value = p.second;
1125 std::stringstream basisVector;
1126 std::vector<double> projection(
m_inputWS->getNumDims(), 0.);
1131 if (!basisVector.str().empty()) {
1133 for (
auto proji : projection) {
1134 proji = std::abs(proji) > 1e-10 ? proji : 0.0;
1135 basisVector <<
"," << proji;
1137 value = basisVector.str();
1140 binMD->setPropertyValue(key,
value);
1144 binMD->executeAsChildAlg();
1149 outputWS = binMD->getProperty(
"OutputWorkspace");
1150 tempBkgdDataWS = std::dynamic_pointer_cast<MDHistoWorkspace>(outputWS);
1151 tempBkgdDataWS->clearOriginalWorkspaces();
1152 tempBkgdDataWS->clearTransforms();
1155 auto outputMDHWS = std::dynamic_pointer_cast<MDHistoWorkspace>(outputWS);
1158 setQUnit(qDimensionIndices, outputMDHWS);
1180 std::vector<size_t> qDimensionIndices;
1181 for (
auto so : symmetryOps) {
1187 Qtransform =
m_UB * soMatrix *
m_W;
1189 Qtransform = soMatrix *
m_W;
1193 double fraction = 1. /
static_cast<double>(symmetryOps.size());
1194 auto binMD =
createChildAlgorithm(
"BinMD", soIndex * 0.3 * fraction, (soIndex + 1) * 0.3 * fraction);
1195 binMD->setPropertyValue(
"AxisAligned",
"0");
1196 binMD->setProperty(
"InputWorkspace",
m_inputWS);
1197 binMD->setProperty(
"TemporaryDataWorkspace", tempDataWS);
1198 binMD->setPropertyValue(
"NormalizeBasisVectors",
"0");
1199 binMD->setPropertyValue(
"OutputWorkspace",
getPropertyValue(
"OutputDataWorkspace"));
1202 for (
auto const &p : parameters) {
1204 auto value = p.second;
1205 std::stringstream basisVector;
1206 std::vector<double> projection(
m_inputWS->getNumDims(), 0.);
1211 if (!basisVector.str().empty()) {
1213 for (
auto proji : projection) {
1214 proji = std::abs(proji) > 1e-10 ? proji : 0.0;
1215 basisVector <<
"," << proji;
1217 value = basisVector.str();
1220 binMD->setPropertyValue(key,
value);
1224 binMD->executeAsChildAlg();
1225 outputWS = binMD->getProperty(
"OutputWorkspace");
1229 tempDataWS = std::dynamic_pointer_cast<MDHistoWorkspace>(outputWS);
1230 tempDataWS->clearOriginalWorkspaces();
1231 tempDataWS->clearTransforms();
1235 auto outputMDHWS = std::dynamic_pointer_cast<MDHistoWorkspace>(outputWS);
1238 setQUnit(qDimensionIndices, outputMDHWS);
1254 const auto ¤tRun =
m_inputWS->getExperimentInfo(expInfoIndex)->run();
1256 std::vector<coord_t> otherDimValues;
1257 for (
size_t i = 3; i <
m_inputWS->getNumDims(); i++) {
1258 const auto dimension =
m_inputWS->getDimension(i);
1259 auto inputDimMin =
static_cast<float>(dimension->getMinimum());
1260 auto inputDimMax =
static_cast<float>(dimension->getMaximum());
1261 coord_t outputDimMin(0), outputDimMax(0);
1262 bool isIntegrated =
true;
1266 isIntegrated =
false;
1267 outputDimMin =
m_normWS->getDimension(j)->getMinimum();
1268 outputDimMax =
m_normWS->getDimension(j)->getMaximum();
1271 if (dimension->getName() ==
"DeltaE") {
1272 if ((inputDimMax < outputDimMin) || (inputDimMin > outputDimMax)) {
1273 skipNormalization =
true;
1278 otherDimValues.emplace_back(
value);
1279 if (value < inputDimMin || value > inputDimMax) {
1280 skipNormalization =
true;
1282 if ((!isIntegrated) && (value < outputDimMin || value > outputDimMax)) {
1283 skipNormalization =
true;
1287 return otherDimValues;
1296 m_hX.resize(hDim.getNBoundaries());
1297 for (
size_t i = 0; i <
m_hX.size(); ++i) {
1298 m_hX[i] = hDim.getX(i);
1301 m_kX.resize(kDim.getNBoundaries());
1302 for (
size_t i = 0; i <
m_kX.size(); ++i) {
1303 m_kX[i] = kDim.getX(i);
1307 m_lX.resize(lDim.getNBoundaries());
1308 for (
size_t i = 0; i <
m_lX.size(); ++i) {
1309 m_lX[i] = lDim.getX(i);
1315 m_eX.resize(eDim.getNBoundaries());
1316 for (
size_t i = 0; i <
m_eX.size(); ++i) {
1317 double temp =
m_Ei - eDim.getX(i);
1318 temp = std::max(temp, 0.);
1319 m_eX[i] = std::sqrt(energyToK * temp);
1358 std::vector<double> &xValues, std::vector<double> &yValues,
1362 auto intersectionsBegin = intersections.begin();
1364 xValues.resize(intersections.size());
1365 yValues.resize(intersections.size());
1366 auto x = xValues.begin();
1367 for (
auto it = intersectionsBegin; it != intersections.end(); ++it, ++
x) {
1390 std::vector<double> &yValues,
const size_t &vmdDims,
1391 std::vector<coord_t> &pos, std::vector<coord_t> &posNew,
1392 std::vector<std::atomic<signal_t>> &signalArray,
const double &solidBkgd,
1393 std::vector<std::atomic<signal_t>> &bkgdSignalArray) {
1395 auto intersectionsBegin = intersections.begin();
1396 for (
auto it = intersectionsBegin + 1; it != intersections.end(); ++it) {
1398 const auto &curIntSec = *it;
1399 const auto &prevIntSec = *(it - 1);
1407 delta = curIntSec[3] - prevIntSec[3];
1411 delta = (curIntSec[3] * curIntSec[3] - prevIntSec[3] * prevIntSec[3]) / energyToK;
1419 std::transform(curIntSec.data(), curIntSec.data() + vmdDims, prevIntSec.data(), pos.begin(),
1420 [](
const double rhs,
const double lhs) { return static_cast<coord_t>(0.5 * (rhs + lhs)); });
1426 auto k =
static_cast<size_t>(std::distance(intersectionsBegin, it));
1428 signal = (yValues[k] - yValues[k - 1]) * solid;
1430 bkgdSignal = (yValues[k] - yValues[k - 1]) * solidBkgd;
1435 pos[3] =
static_cast<coord_t>(
m_Ei - pos[3] * pos[3] / energyToK);
1438 signal = solid *
delta;
1440 bkgdSignal = solidBkgd *
delta;
1446 size_t linIndex =
m_normWS->getLinearIndexAtCoord(posNew.data());
1447 if (linIndex ==
size_t(-1))
1469 uint16_t expInfoIndex,
size_t soIndex) {
1470 const auto ¤tExptInfo = *(
m_inputWS->getExperimentInfo(expInfoIndex));
1471 std::vector<double> lowValues, highValues;
1472 auto *lowValuesLog =
dynamic_cast<VectorDoubleProperty *
>(currentExptInfo.getLog(
"MDNorm_low"));
1473 lowValues = (*lowValuesLog)();
1474 auto *highValuesLog =
dynamic_cast<VectorDoubleProperty *
>(currentExptInfo.getLog(
"MDNorm_high"));
1475 highValues = (*highValuesLog)();
1482 const double protonCharge = currentExptInfo.run().getProtonCharge();
1484 const double protonChargeBkgd =
1487 const auto &spectrumInfo = currentExptInfo.spectrumInfo();
1490 const auto ndets =
static_cast<int64_t
>(spectrumInfo.size());
1491 bool haveSA =
false;
1493 if (solidAngleWS !=
nullptr) {
1498 (haveSA) ? solidAngleWS->getDetectorIDToWorkspaceIndexMap() :
detid2index_map();
1504 std::vector<std::atomic<signal_t>> signalArray(
m_normWS->getNPoints());
1508 throw std::runtime_error(
"N points are different");
1510 std::vector<std::atomic<signal_t>> bkgdSignalArray(numNPoints);
1512 std::vector<std::array<double, 4>> intersections;
1513 std::vector<double> xValues, yValues;
1514 std::vector<coord_t> pos, posNew;
1518 auto progIndex =
static_cast<double>(soIndex + expInfoIndex *
m_numSymmOps);
1520 std::make_unique<API::Progress>(
this, 0.3 + progStep * progIndex, 0.3 + progStep * (1. + progIndex), ndets);
1524PRAGMA_OMP(parallel
for private(intersections, xValues, yValues, pos, posNew)
if (safe))
1525for (int64_t i = 0; i < ndets; i++) {
1529 if (!spectrumInfo.hasDetectors(i) || spectrumInfo.isMonitor(i) || spectrumInfo.isMasked(i)) {
1533 const auto &detector = spectrumInfo.detector(i);
1535 double phi = detector.getPhi();
1537 const auto detID = detector.getID();
1542 auto index = fluxDetToIdx.find(detID);
1543 if (
index != fluxDetToIdx.end()) {
1544 wsIdx =
index->second;
1554 if (intersections.empty())
1558 double solid = protonCharge;
1560 double bkgdSolid = protonChargeBkgd;
1562 double solid_angle_factor = solidAngleWS->y(solidAngDetToIdx.find(detID)->second)[0];
1564 solid = solid_angle_factor * protonCharge;
1566 bkgdSolid = solid_angle_factor * protonChargeBkgd;
1576 pos.resize(vmdDims + otherValues.size());
1577 std::copy(otherValues.begin(), otherValues.end(), pos.begin() + vmdDims);
1588 std::transform(signalArray.cbegin(), signalArray.cend(),
m_normWS->getSignalArray(),
m_normWS->mutableSignalArray(),
1589 [](
const std::atomic<signal_t> &a,
const signal_t &b) { return a + b; });
1592 std::transform(bkgdSignalArray.cbegin(), bkgdSignalArray.cend(),
m_bkgdNormWS->getSignalArray(),
1594 [](
const std::atomic<signal_t> &a,
const signal_t &b) { return a + b; });
1598 std::copy(signalArray.cbegin(), signalArray.cend(),
m_normWS->mutableSignalArray());
1601 std::copy(bkgdSignalArray.cbegin(), bkgdSignalArray.cend(),
m_bkgdNormWS->mutableSignalArray());
1619 V3D qout(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta)), qin(0., 0., 1);
1621 qout = transform * qout;
1622 qin = transform * qin;
1627 double kfmin, kfmax, kimin, kimax;
1634 kimin = std::sqrt(energyToK *
m_Ei);
1636 kfmin = std::sqrt(energyToK * (
m_Ei - highvalue));
1637 kfmax = std::sqrt(energyToK * (
m_Ei - lowvalue));
1640 double hStart = qin.
X() * kimin - qout.X() * kfmin, hEnd = qin.
X() * kimax - qout.X() * kfmax;
1641 double kStart = qin.
Y() * kimin - qout.Y() * kfmin, kEnd = qin.
Y() * kimax - qout.Y() * kfmax;
1642 double lStart = qin.
Z() * kimin - qout.Z() * kfmin, lEnd = qin.
Z() * kimax - qout.Z() * kfmax;
1645 auto hNBins =
m_hX.size();
1646 auto kNBins =
m_kX.size();
1647 auto lNBins =
m_lX.size();
1648 auto eNBins =
m_eX.size();
1649 intersections.clear();
1650 intersections.reserve(hNBins + kNBins + lNBins + eNBins + 2);
1653 if (
fabs(hStart - hEnd) > eps) {
1654 double fmom = (kfmax - kfmin) / (hEnd - hStart);
1655 double fk = (kEnd - kStart) / (hEnd - hStart);
1656 double fl = (lEnd - lStart) / (hEnd - hStart);
1657 for (
size_t i = 0; i < hNBins; i++) {
1658 double hi =
m_hX[i];
1659 if (((hStart - hi) * (hEnd - hi) < 0)) {
1663 double ki = fk * (hi - hStart) + kStart;
1664 double li = fl * (hi - hStart) + lStart;
1665 if ((ki >=
m_kX[0]) && (ki <=
m_kX[kNBins - 1]) && (li >=
m_lX[0]) && (li <=
m_lX[lNBins - 1])) {
1666 double momi = fmom * (hi - hStart) + kfmin;
1667 intersections.push_back({{hi, ki, li, momi}});
1673 if (
fabs(kStart - kEnd) > eps) {
1674 double fmom = (kfmax - kfmin) / (kEnd - kStart);
1675 double fh = (hEnd - hStart) / (kEnd - kStart);
1676 double fl = (lEnd - lStart) / (kEnd - kStart);
1677 for (
size_t i = 0; i < kNBins; i++) {
1678 double ki =
m_kX[i];
1679 if (((kStart - ki) * (kEnd - ki) < 0)) {
1683 double hi = fh * (ki - kStart) + hStart;
1684 double li = fl * (ki - kStart) + lStart;
1685 if ((hi >=
m_hX[0]) && (hi <=
m_hX[hNBins - 1]) && (li >=
m_lX[0]) && (li <=
m_lX[lNBins - 1])) {
1686 double momi = fmom * (ki - kStart) + kfmin;
1687 intersections.push_back({{hi, ki, li, momi}});
1694 if (
fabs(lStart - lEnd) > eps) {
1695 double fmom = (kfmax - kfmin) / (lEnd - lStart);
1696 double fh = (hEnd - hStart) / (lEnd - lStart);
1697 double fk = (kEnd - kStart) / (lEnd - lStart);
1699 for (
size_t i = 0; i < lNBins; i++) {
1700 double li =
m_lX[i];
1701 if (((lStart - li) * (lEnd - li) < 0)) {
1702 double hi = fh * (li - lStart) + hStart;
1703 double ki = fk * (li - lStart) + kStart;
1704 if ((hi >=
m_hX[0]) && (hi <=
m_hX[hNBins - 1]) && (ki >=
m_kX[0]) && (ki <=
m_kX[kNBins - 1])) {
1705 double momi = fmom * (li - lStart) + kfmin;
1706 intersections.push_back({{hi, ki, li, momi}});
1713 for (
size_t i = 0; i < eNBins; i++) {
1714 double kfi =
m_eX[i];
1715 if ((kfi - kfmin) * (kfi - kfmax) <= 0) {
1716 double h = qin.
X() * kimin - qout.X() * kfi;
1717 double k = qin.
Y() * kimin - qout.Y() * kfi;
1718 double l = qin.
Z() * kimin - qout.Z() * kfi;
1719 if ((h >=
m_hX[0]) && (h <=
m_hX[hNBins - 1]) && (k >=
m_kX[0]) && (k <=
m_kX[kNBins - 1]) && (l >=
m_lX[0]) &&
1720 (l <=
m_lX[lNBins - 1])) {
1721 intersections.push_back({{h, k, l, kfi}});
1728 if ((hStart >=
m_hX[0]) && (hStart <=
m_hX[hNBins - 1]) && (kStart >=
m_kX[0]) && (kStart <=
m_kX[kNBins - 1]) &&
1729 (lStart >=
m_lX[0]) && (lStart <=
m_lX[lNBins - 1])) {
1730 intersections.push_back({{hStart, kStart, lStart, kfmin}});
1732 if ((hEnd >=
m_hX[0]) && (hEnd <=
m_hX[hNBins - 1]) && (kEnd >=
m_kX[0]) && (kEnd <=
m_kX[kNBins - 1]) &&
1733 (lEnd >=
m_lX[0]) && (lEnd <=
m_lX[lNBins - 1])) {
1734 intersections.push_back({{hEnd, kEnd, lEnd, kfmax}});
1738 std::stable_sort(intersections.begin(), intersections.end(), compareMomentum);
1750 size_t sp, std::vector<double> &yValues) {
1751 assert(xValues.size() == yValues.size());
1754 const auto &xData = integrFlux.
x(sp);
1755 const double xStart = xData.front();
1756 const double xEnd = xData.back();
1761 const auto &yData = integrFlux.
y(sp);
1762 size_t spSize = yData.size();
1764 const double yMin = 0.0;
1765 const double yMax = yData.back();
1767 size_t nData = xValues.size();
1769 if (xValues[nData - 1] < xStart) {
1770 std::fill(yValues.begin(), yValues.end(), yMin);
1775 if (xValues[0] > xEnd) {
1776 std::fill(yValues.begin(), yValues.end(), yMax);
1782 while (i < nData - 1 && xValues[i] < xStart) {
1787 for (; i < nData; i++) {
1789 if (j >= spSize - 1) {
1792 double xi = xValues[i];
1793 while (j < spSize - 1 && xi > xData[j])
1796 if (xi == xData[j]) {
1797 yValues[i] = yData[j];
1798 }
else if (j == spSize - 1) {
1803 double x0 = xData[j - 1];
1804 double x1 = xData[j];
1805 double y0 = yData[j - 1];
1806 double y1 = yData[j];
1807 yValues[i] = y0 + (y1 - y0) * (xi - x0) / (x1 - x0);
#define DECLARE_ALGORITHM(classname)
const std::vector< double > & rhs
double value
The value of the point.
std::map< DeltaEMode::Type, std::string > index
#define PARALLEL_START_INTERRUPT_REGION
Begins a block to skip processing is the algorithm has been interupted Note the end of the block if n...
#define PARALLEL_END_INTERRUPT_REGION
Ends a block to skip processing is the algorithm has been interupted Note the start of the block if n...
#define PRAGMA_OMP(expression)
#define PARALLEL_CHECK_INTERRUPT_REGION
Adds a check after a Parallel region to see if it was interupted.
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.
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.
This class is shared by a few Workspace types and holds information related to a particular experimen...
const Run & run() const
Run details object access.
A validator which checks that a workspace has a valid instrument.
Base MatrixWorkspace Abstract Class.
const HistogramData::HistogramX & x(const size_t index) const
const HistogramData::HistogramY & y(const size_t index) const
const Kernel::Matrix< double > & getGoniometerMatrix() const
Retrieve the first goniometer rotation matrix.
A property class for workspaces.
std::unique_ptr< MDHistoWorkspace > clone() const
Returns a clone of the workspace.
static const std::string HKLName
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
static const std::string QSampleName
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)
double c() const
Get lattice parameter.
double b() const
Get lattice parameter.
Support for a property that holds an array of values.
Exception for errors associated with the instrument definition.
Records the filename, the description of failure and the line on which it happened.
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 > settings)
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.
void error(const std::string &msg)
Logs at error level.
void warning(const std::string &msg)
Logs at warning level.
T determinant() const
Calculate the determinant.
T Invert()
LU inversion routine.
void multiplyPoint(const std::vector< T > &in, std::vector< T > &out) const
Multiply M*Vec.
std::vector< T > getVector() const
size_t numRows() const
Return the number of rows in the matrix.
void setColumn(const size_t nCol, const std::vector< T > &newCol)
Matrix< T > & Transpose()
Transpose the matrix.
The concrete, templated class for properties.
Base class for properties.
virtual std::string value() const =0
Returns the value of the property as a string.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
static const UnitLabel RLU
Reciprocal lattice units.
constexpr double X() const noexcept
Get x.
constexpr double Y() const noexcept
Get y.
constexpr double Z() const noexcept
Get z.
MDNormalization : Bin single crystal diffraction or direct geometry inelastic data and calculate the ...
size_t m_numSymmOps
number of symmetry operations
Mantid::Kernel::DblMatrix m_W
W matrix.
void calcSingleDetectorNorm(const std::vector< std::array< double, 4 > > &intersections, const double &solid, std::vector< double > &yValues, const size_t &vmdDims, std::vector< coord_t > &pos, std::vector< coord_t > &posNew, std::vector< std::atomic< signal_t > > &signalArray, const double &solidBkgd, std::vector< std::atomic< signal_t > > &bkgdSignalArray)
Calculate the normalization among intersections on a single detector in 1 specific SpectrumInfo/Exper...
Mantid::Kernel::Matrix< coord_t > m_transformation
matrix for transforming from intersections to positions in the normalization workspace
bool m_dEIntegrated
Flag to indicate that the energy dimension is integrated.
DataObjects::MDHistoWorkspace_sptr binBackgroundWS(const std::vector< Geometry::SymmetryOperation > &symmetryOps)
Bin(MD) input Background workspace.
std::string QDimensionName(std::vector< double > projection)
Get the dimension name when using reciprocal lattice units.
bool m_diffraction
Flag indicating if the input workspace is from diffraction.
void createNormalizationWS(const DataObjects::MDHistoWorkspace &dataWS)
Create & cached the normalization workspace.
void exec() override
Execute the algorithm.
bool m_accumulate
Flag to accumulate normalization.
void calcIntegralsForIntersections(const std::vector< double > &xValues, const API::MatrixWorkspace &integrFlux, size_t sp, std::vector< double > &yValues)
Linearly interpolate between the points in integrFlux at xValues and save the results in yValues.
std::vector< double > m_Q0Basis
The projection vectors.
DataObjects::MDHistoWorkspace_sptr m_normWS
Normalization workspace.
const std::string summary() const override
Algorithm's summary for use in the GUI and help.
std::map< std::string, std::string > getBinParameters()
Calculate binning parameters.
API::IMDWorkspace_sptr divideMD(const API::IMDHistoWorkspace_sptr &lhs, const API::IMDHistoWorkspace_sptr &rhs, const std::string &outputwsname, const double &startProgress, const double &endProgress)
const std::string category() const override
Algorithm's category for identification.
std::vector< double > m_lX
std::vector< double > m_kX
std::vector< coord_t > getValuesFromOtherDimensions(bool &skipNormalization, uint16_t expInfoIndex=0) const
Retrieve logged values from non-HKL dimensions.
void setQUnit(const std::vector< size_t > &qDimensionIndices, const Mantid::DataObjects::MDHistoWorkspace_sptr &outputMDHWS)
Set the output Frame to HKL.
DataObjects::MDHistoWorkspace_sptr m_bkgdNormWS
void calculateIntersections(std::vector< std::array< double, 4 > > &intersections, const double theta, const double phi, const Kernel::DblMatrix &transform, double lowvalue, double highvalue)
Calculate the points of intersection for the given detector with cuboid surrounding the detector posi...
API::IMDEventWorkspace_sptr m_inputWS
Input workspace.
double m_Ei
Cached value of incident energy dor direct geometry.
size_t m_hIdx
index of h,k,l, dE dimensions in the output workspaces
Mantid::Kernel::DblMatrix m_UB
UB matrix.
std::vector< double > m_Q1Basis
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.
Mantid::Kernel::DblMatrix buildSymmetryMatrix(const Geometry::SymmetryOperation &so)
build symmetry matrix
Kernel::V3D m_beamDir
Beam direction.
size_t m_numExptInfos
number of experimentInfo objects
void calcDiffractionIntersectionIntegral(std::vector< std::array< double, 4 > > &intersections, std::vector< double > &xValues, std::vector< double > &yValues, const API::MatrixWorkspace &integrFlux, const size_t &wsIdx)
Calculate the diffraction MDE's intersection integral of a certain detector/spectru.
std::string QDimensionNameQSample(int i)
Get the dimension name when not using reciprocal lattice units.
void cacheDimensionXValues()
Stores the X values from each H,K,L, and optionally DeltaE dimension as member variables.
std::vector< double > m_hX
cached X values along dimensions h,k,l. dE
const std::string name() const override
Algorithms name for identification.
std::vector< double > m_Q2Basis
bool m_isRLU
flag for reciprocal lattice units
DataObjects::MDHistoWorkspace_sptr binInputWS(const std::vector< Geometry::SymmetryOperation > &symmetryOps)
Bin(MD) input MDE workspace.
void calculateNormalization(const std::vector< coord_t > &otherValues, const Geometry::SymmetryOperation &so, uint16_t expInfoIndex, size_t soIndex)
Computed the normalization for the input workspace.
std::string convention
ki-kf for Inelastic convention; kf-ki for Crystallography convention
Mantid::Kernel::DblMatrix calQTransform(const Mantid::API::ExperimentInfo ¤tExpInfo, const Geometry::SymmetryOperation &so)
Calculate QTransform = (R * UB * SymmetryOperation * m_W)^-1.
std::map< std::string, std::string > validateInputs() override final
Validate the input workspace.
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.
int version() const override
Algorithm's version for identification.
void init() override
Initialize the algorithm's properties.
API::IMDEventWorkspace_sptr m_backgroundWS
Input background workspace.
std::vector< double > m_eX
void createBackgroundNormalizationWS(const DataObjects::MDHistoWorkspace &dataWS)
Kernel::V3D m_samplePos
Sample position.
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.
std::shared_ptr< MDHistoWorkspace > MDHistoWorkspace_sptr
A shared pointer to a MDHistoWorkspace.
std::unique_ptr< MDFrame > MDFrame_uptr
MDFrameFactory_uptr MANTID_GEOMETRY_DLL makeMDFrameFactoryChain()
Make a complete factory chain.
std::string toString(const T &value)
Convert a number to a string.
template DLLExport std::vector< double > splitStringIntoVector< double >(std::string listString)
template DLLExport std::vector< size_t > splitStringIntoVector< size_t >(std::string listString)
std::enable_if< std::is_pointer< Arg >::value, bool >::type threadSafe(Arg workspace)
Thread-safety check Checks the workspace to ensure it is suitable for multithreaded access.
MANTID_KERNEL_DLL V3D normalize(V3D v)
Normalizes a V3D.
void AtomicOp(std::atomic< T > &f, T d, BinaryOp op)
Uses std::compare_exchange_weak to update the atomic value f = op(f, d) Used to improve parallel scal...
Mantid::Kernel::Matrix< double > DblMatrix
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,...
std::unordered_map< detid_t, size_t > detid2index_map
Map with key = detector ID, value = workspace index.
double signal_t
Typedef for the signal recorded in a MDBox, etc.
@ Input
An input workspace.
@ Output
An output workspace.