Mantid
Loading...
Searching...
No Matches
TransformMD.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 +
15
16using namespace Mantid::Kernel;
17using namespace Mantid::API;
18using namespace Mantid::DataObjects;
20
21namespace Mantid::MDAlgorithms {
22
23// Register the algorithm into the AlgorithmFactory
24DECLARE_ALGORITHM(TransformMD)
25
26//----------------------------------------------------------------------------------------------
28const std::string TransformMD::name() const { return "TransformMD"; }
29
31int TransformMD::version() const { return 1; }
32
34const std::string TransformMD::category() const { return "MDAlgorithms\\Transforms"; }
35
36//----------------------------------------------------------------------------------------------
37
38//----------------------------------------------------------------------------------------------
42 declareProperty(std::make_unique<WorkspaceProperty<IMDWorkspace>>("InputWorkspace", "", Direction::Input),
43 "Any input MDWorkspace.");
44
45 std::vector<double> defaultScaling(1, 1.0);
46 declareProperty(std::make_unique<ArrayProperty<double>>("Scaling", std::move(defaultScaling)),
47 "Scaling value multiplying each coordinate. Default "
48 "1.\nEither a single value or a list for each dimension.");
49
50 std::vector<double> defaultOffset(1, 0.0);
51 declareProperty(std::make_unique<ArrayProperty<double>>("Offset", std::move(defaultOffset)),
52 "Offset value to add to each coordinate. Default 0.\nEither "
53 "a single value or a list for each dimension.");
54
55 declareProperty(std::make_unique<WorkspaceProperty<IMDWorkspace>>("OutputWorkspace", "", Direction::Output),
56 "Name of the output MDWorkspace.");
57}
58
59//----------------------------------------------------------------------------------------------
64template <typename MDE, size_t nd>
66 std::vector<API::IMDNode *> boxes;
67 // Get ALL the boxes, including MDGridBoxes.
68 ws->getBox()->getBoxes(boxes, 1000, false);
69
70 // If file backed, sort them first.
71 if (ws->isFileBacked())
73
75 for (int i = 0; i < static_cast<int>(boxes.size()); i++) { // NOLINT
77 auto *box = dynamic_cast<MDBoxBase<MDE, nd> *>(boxes[i]);
78 if (box) {
80 }
82 }
84}
85
86//----------------------------------------------------------------------------------------------
92void TransformMD::reverse(signal_t *array, size_t arrayLength) {
93 for (size_t i = 0; i < (arrayLength / 2); i++) {
94 signal_t temp = array[i];
95 array[i] = array[(arrayLength - 1) - i];
96 array[(arrayLength - 1) - i] = temp;
97 }
98}
99
100//----------------------------------------------------------------------------------------------
106
107 inWS = getProperty("InputWorkspace");
108 outWS = getProperty("OutputWorkspace");
109 std::string outName = getPropertyValue("OutputWorkspace");
110
111 if (std::dynamic_pointer_cast<MatrixWorkspace>(inWS))
112 throw std::runtime_error("TransformMD can only transform a "
113 "MDHistoWorkspace or a MDEventWorkspace.");
114
115 if (outWS != inWS) {
116 // NOT in-place. So first we clone inWS into outWS
117 auto clone = createChildAlgorithm("CloneMDWorkspace", 0.0, 0.5, true);
118 clone->setProperty("InputWorkspace", inWS);
119 clone->executeAsChildAlg();
120 outWS = clone->getProperty("OutputWorkspace");
121 }
122
123 if (!outWS)
124 throw std::runtime_error("Invalid output workspace.");
125
126 size_t nd = outWS->getNumDims();
127 m_scaling = getProperty("Scaling");
128 m_offset = getProperty("Offset");
129
130 // Replicate single values
131 if (m_scaling.size() == 1)
132 m_scaling = std::vector<double>(nd, m_scaling[0]);
133 if (m_offset.size() == 1)
134 m_offset = std::vector<double>(nd, m_offset[0]);
135
136 // Check the size
137 if (m_scaling.size() != nd)
138 throw std::invalid_argument("Scaling argument must be either length 1 or "
139 "match the number of dimensions.");
140 if (m_offset.size() != nd)
141 throw std::invalid_argument("Offset argument must be either length 1 or "
142 "match the number of dimensions.");
143
144 // Transform the dimensions
145 outWS->transformDimensions(m_scaling, m_offset);
146
147 MDHistoWorkspace_sptr histo = std::dynamic_pointer_cast<MDHistoWorkspace>(outWS);
148 IMDEventWorkspace_sptr event = std::dynamic_pointer_cast<IMDEventWorkspace>(outWS);
149
150 if (histo) {
151 // Recalculate all the values since the dimensions changed.
152 histo->cacheValues();
153 // Expect first 3 dimensions to be -1 for changing conventions
154 for (int i = 0; i < static_cast<int>(m_scaling.size()); i++)
155 if (m_scaling[i] < 0) {
156 std::vector<int> axes(m_scaling.size()); // vector with ints.
157 std::iota(std::begin(axes), std::end(axes), 0); // Fill with 0, 1, ...
158 axes[0] = i;
159 axes[i] = 0;
160 if (i > 0)
161 histo = transposeMD(histo, axes);
162 signal_t *signals = histo->mutableSignalArray();
163 signal_t *errorsSq = histo->mutableErrorSquaredArray();
164 signal_t *numEvents = histo->mutableNumEventsArray();
165
166 // Find the extents
167 size_t nPoints = static_cast<size_t>(histo->getDimension(0)->getNBins());
168 size_t mPoints = 1;
169 for (size_t k = 1; k < histo->getNumDims(); k++) {
170 mPoints *= static_cast<size_t>(histo->getDimension(k)->getNBins());
171 }
172 // other dimensions
173 for (size_t j = 0; j < mPoints; j++) {
174 this->reverse(signals + j * nPoints, nPoints);
175 this->reverse(errorsSq + j * nPoints, nPoints);
176 this->reverse(numEvents + j * nPoints, nPoints);
177 }
178
179 histo = transposeMD(histo, axes);
180 }
181
182 // Pass on the display normalization from the input workspace
183 histo->setDisplayNormalization(inWS->displayNormalizationHisto());
184
185 this->setProperty("OutputWorkspace", histo);
186 } else if (event) {
187 // Call the method for this type of MDEventWorkspace.
189 Progress *prog2 = nullptr;
191 ThreadPool tp(ts, 0, prog2);
192 event->splitAllIfNeeded(ts);
193 // prog2->resetNumSteps( ts->size(), 0.4, 0.6);
194 tp.joinAll();
195 event->refreshCache();
196 // Set the special coordinate system.
197 IMDEventWorkspace_sptr inEvent = std::dynamic_pointer_cast<IMDEventWorkspace>(inWS);
198 event->setCoordinateSystem(inEvent->getSpecialCoordinateSystem());
199
200 if (m_scaling[0] < 0) {
201 // Only need these 2 algorithms for transforming with negative number
202 std::vector<double> extents;
203 std::vector<std::string> names, units;
204 for (size_t d = 0; d < nd; d++) {
205 Geometry::IMDDimension_const_sptr dim = event->getDimension(d);
206 // Find the extents
207 extents.emplace_back(dim->getMinimum());
208 extents.emplace_back(dim->getMaximum());
209 names.emplace_back(std::string(dim->getName()));
210 units.emplace_back(dim->getUnits());
211 }
212 Algorithm_sptr create_alg = createChildAlgorithm("CreateMDWorkspace");
213 create_alg->setProperty("Dimensions", static_cast<int>(nd));
214 create_alg->setProperty("EventType", event->getEventTypeName());
215 create_alg->setProperty("Extents", extents);
216 create_alg->setProperty("Names", names);
217 create_alg->setProperty("Units", units);
218 create_alg->setPropertyValue("OutputWorkspace", "__none");
219 create_alg->executeAsChildAlg();
220 Workspace_sptr none = create_alg->getProperty("OutputWorkspace");
221
222 AnalysisDataService::Instance().addOrReplace(outName, event);
223 AnalysisDataService::Instance().addOrReplace("__none", none);
224 Mantid::API::BoxController_sptr boxController = event->getBoxController();
225 std::vector<int> splits;
226 for (size_t d = 0; d < nd; d++) {
227 splits.emplace_back(static_cast<int>(boxController->getSplitInto(d)));
228 }
229 Algorithm_sptr merge_alg = createChildAlgorithm("MergeMD");
230 merge_alg->setPropertyValue("InputWorkspaces", outName + ",__none");
231 merge_alg->setProperty("SplitInto", splits);
232 merge_alg->setProperty("SplitThreshold", static_cast<int>(boxController->getSplitThreshold()));
233 merge_alg->setProperty("MaxRecursionDepth", 13);
234 merge_alg->executeAsChildAlg();
235 event = merge_alg->getProperty("OutputWorkspace");
236 AnalysisDataService::Instance().remove("__none");
237 }
238 this->setProperty("OutputWorkspace", event);
239 }
240}
247MDHistoWorkspace_sptr TransformMD::transposeMD(MDHistoWorkspace_sptr &toTranspose, const std::vector<int> &axes) {
248
249 auto transposeMD = this->createChildAlgorithm("TransposeMD", 0.0, 0.5);
250 transposeMD->setProperty("InputWorkspace", toTranspose);
251 transposeMD->setProperty("Axes", axes);
252 transposeMD->execute();
253 IMDHistoWorkspace_sptr outputWS = transposeMD->getProperty("OutputWorkspace");
254 return std::dynamic_pointer_cast<MDHistoWorkspace>(outputWS);
255}
256
257} // namespace Mantid::MDAlgorithms
std::string name
Definition Run.cpp:60
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:538
static std::unique_ptr< QThreadPool > tp
#define CALL_MDEVENT_FUNCTION(funcname, workspace)
Macro that makes it possible to call a templated method for a MDEventWorkspace using a IMDEventWorksp...
#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 PARALLEL_FOR_IF(condition)
Empty definitions - to enable set your complier to enable openMP.
#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.
static void sortObjByID(std::vector< IMDNode * > &boxes)
Static method for sorting a list of MDBoxBase pointers by their file position, ascending.
Definition IMDNode.h:292
Helper class for reporting progress from algorithms.
Definition Progress.h:25
A property class for workspaces.
Templated super-class of a multi-dimensional event "box".
Definition MDBoxBase.h:50
void transformDimensions(std::vector< double > &scaling, std::vector< double > &offset) override
Transform the dimensions contained in this box x' = x*scaling + offset.
Definition MDBoxBase.hxx:78
std::shared_ptr< MDEventWorkspace< MDE, nd > > sptr
Typedef for a shared pointer of this kind of event workspace.
Support for a property that holds an array of values.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
A Thread Pool implementation that keeps a certain number of threads running (normally,...
Definition ThreadPool.h:36
A First-In-First-Out Thread Scheduler.
The ThreadScheduler object defines how tasks are allocated to threads and in what order.
Scale and/or offset the coordinates of a MDWorkspace.
Definition TransformMD.h:20
const std::string category() const override
Algorithm's category for identification.
std::vector< double > m_offset
Definition TransformMD.h:39
void reverse(signal_t *array, size_t arrayLength)
Swap the array elements.
Mantid::DataObjects::MDHistoWorkspace_sptr transposeMD(Mantid::DataObjects::MDHistoWorkspace_sptr &toTranspose, const std::vector< int > &axes)
Transpose the input data workspace according to the axis provided.
void doTransform(typename Mantid::DataObjects::MDEventWorkspace< MDE, nd >::sptr ws)
Perform the transform on a MDEventWorkspace.
std::vector< double > m_scaling
Definition TransformMD.h:38
int version() const override
Algorithm's version for identification.
void init() override
Initialize the algorithm's properties.
void exec() override
Execute the algorithm.
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< IMDHistoWorkspace > IMDHistoWorkspace_sptr
shared pointer to Mantid::API::IMDHistoWorkspace
std::shared_ptr< IMDWorkspace > IMDWorkspace_sptr
Shared pointer to the IMDWorkspace base class.
std::shared_ptr< BoxController > BoxController_sptr
Shared ptr to BoxController.
std::shared_ptr< Algorithm > Algorithm_sptr
Typedef for a shared pointer to an Algorithm.
Definition Algorithm.h:52
std::size_t numEvents(Nexus::File &file, bool &hasTotalCounts, bool &oldNeXusFileNames, const std::string &prefix, const Nexus::NexusDescriptor &descriptor)
Get the number of events in the currently opened group.
std::shared_ptr< MDHistoWorkspace > MDHistoWorkspace_sptr
A shared pointer to a MDHistoWorkspace.
std::shared_ptr< const IMDDimension > IMDDimension_const_sptr
Shared Pointer to const IMDDimension.
double signal_t
Typedef for the signal recorded in a MDBox, etc.
Definition MDTypes.h:36
STL namespace.
@ Input
An input workspace.
Definition Property.h:53
@ Output
An output workspace.
Definition Property.h:54