/
ConvertToDiffractionMDWorkspace3.cpp
134 lines (114 loc) · 5.38 KB
/
ConvertToDiffractionMDWorkspace3.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
// NScD Oak Ridge National Laboratory, European Spallation Source,
// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
// SPDX - License - Identifier: GPL - 3.0 +
#include "MantidMDAlgorithms/ConvertToDiffractionMDWorkspace3.h"
#include "MantidAPI/IMDEventWorkspace.h"
#include "MantidDataObjects/EventWorkspace.h"
#include "MantidDataObjects/MDEventWorkspace.h"
#include "MantidDataObjects/Workspace2D.h"
#include "MantidKernel/ArrayProperty.h"
#include "MantidKernel/EnabledWhenProperty.h"
#include "MantidKernel/ListValidator.h"
#include "MantidMDAlgorithms/ConvertToMDMinMaxLocal.h"
#include "MantidMDAlgorithms/MDTransfFactory.h"
#include "MantidMDAlgorithms/MDWSTransform.h"
#include <boost/math/special_functions/sign.hpp>
#include <algorithm>
#include <limits>
using namespace Mantid::API;
using namespace Mantid::Kernel;
using namespace Mantid::DataObjects;
using namespace Mantid::Geometry;
namespace Mantid::MDAlgorithms {
// Register the algorithm into the AlgorithmFactory
DECLARE_ALGORITHM(ConvertToDiffractionMDWorkspace3)
//----------------------------------------------------------------------------------------------
/** Initialize the algorithm's properties.
*/
void ConvertToDiffractionMDWorkspace3::init() {
// initilise common properties between versions
BaseConvertToDiffractionMDWorkspace::init();
std::vector<double> extents;
declareProperty(std::make_unique<ArrayProperty<double>>("Extents", std::move(extents)),
"A comma separated list of min, max for each dimension,\n"
"specifying the extents of each dimension. Optional, default "
"will use ConvertToMDMinMaxLocal to calculate extents for each "
"dimension.");
setPropertyGroup("Extents", getBoxSettingsGroupName());
}
/** Splits extents accepted by convertToDiffreactionMD workspace in the form
*min1,max1 or min1,max1,min2,max2,min3,max3
* into tso vectors min(3),max(3) accepted by convertToMD
* @param Extents -- the vector of extents consititing of 2 or 6 elements
* @param minVal -- 3-vector of minimal values for 3 processed dimensions
* @param maxVal -- 3-vector of maximal values for 3 processed dimensions
*
* @return minVal and maxVal -- two vectors with minimal and maximal values of
*the momentums in the target workspace.
*/
void ConvertToDiffractionMDWorkspace3::convertExtents(const std::vector<double> &Extents, std::vector<double> &minVal,
std::vector<double> &maxVal) {
minVal.resize(3);
maxVal.resize(3);
if (Extents.size() == 2) {
for (size_t d = 0; d < 3; d++) {
minVal[d] = Extents[0];
maxVal[d] = Extents[1];
}
} else if (Extents.size() == 6) {
for (size_t d = 0; d < 3; d++) {
minVal[d] = Extents[2 * d + 0];
maxVal[d] = Extents[2 * d + 1];
}
} else if (Extents.empty()) {
calculateExtentsFromData(minVal, maxVal);
} else
throw std::invalid_argument("You must specify either 2 or 6 extents (min,max).");
}
/** Calculate the extents to use for the conversion from the input workspace.
*
* @param minVal :: the minimum bounds of the MD space.
* @param maxVal :: the maximum bounds of the MD space.
*/
void ConvertToDiffractionMDWorkspace3::calculateExtentsFromData(std::vector<double> &minVal,
std::vector<double> &maxVal) {
auto alg = createChildAlgorithm("ConvertToMDMinMaxLocal");
alg->initialize();
alg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", getProperty("InputWorkspace"));
alg->setPropertyValue("QDimensions", "Q3D");
std::vector<std::string> dE_modes = Kernel::DeltaEMode::availableTypes();
alg->setPropertyValue("dEAnalysisMode", dE_modes[Kernel::DeltaEMode::Elastic]);
std::string TargetFrame, Scaling;
convertFramePropertyNames(getPropertyValue("OutputDimensions"), TargetFrame, Scaling);
alg->setProperty("Q3DFrames", TargetFrame);
alg->setProperty("QConversionScales", Scaling);
alg->execute();
minVal = alg->getProperty("MinValues");
maxVal = alg->getProperty("MaxValues");
// If the calculation produced +/- infinity as one of the extents
// replace this with a more reasonable value.
const auto INF = std::numeric_limits<double>::infinity();
const auto MAX_DBL = std::numeric_limits<double>::max();
const auto DEFAULT_BOUND = 50.0;
std::replace(minVal.begin(), minVal.end(), -INF, -DEFAULT_BOUND);
std::replace(maxVal.begin(), maxVal.end(), INF, DEFAULT_BOUND);
std::replace(minVal.begin(), minVal.end(), MAX_DBL, -DEFAULT_BOUND);
std::replace(maxVal.begin(), maxVal.end(), -MAX_DBL, DEFAULT_BOUND);
// Increases bounds by a small margin and ensures they aren't too close to
// zero. This is to prevent events from being incorrectly discarded as out
// of bounds by calcMatrixCoord functions (or, if fixed there, later causing
// further issues in MDGridBox::calculateChildIndex due to events sitting
// on maximum boundaries)
for (size_t i = 0; i < maxVal.size(); ++i) {
minVal[i] *= (1 - 1.e-5 * boost::math::sign(minVal[i]));
if (fabs(minVal[i]) < 1.e-5)
minVal[i] = -1.e-5;
maxVal[i] *= (1 + 1.e-5 * boost::math::sign(maxVal[i]));
if (fabs(maxVal[i]) < 1.e-5)
maxVal[i] = 1.e-5;
}
}
} // namespace Mantid::MDAlgorithms