Mantid
Loading...
Searching...
No Matches
QueryMDWorkspace.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 +
8
12#include "MantidAPI/TableRow.h"
19
20using namespace Mantid::API;
21using namespace Mantid::DataObjects;
22using namespace Mantid::Kernel;
23
24namespace Mantid::MDAlgorithms {
25
26// Register the class into the algorithm factory
27DECLARE_ALGORITHM(QueryMDWorkspace)
28
29
33std::string noNormalisationOption() { return "none"; }
34
39std::string volumeNormalisationOption() { return "volume"; }
40
45std::string numberOfEventsNormalisationOption() { return "number of events"; }
46
52Mantid::API::MDNormalization whichNormalisation(const std::string &strNormalisation) {
53 Mantid::API::MDNormalization requestedNormalisation;
54 if (strNormalisation == noNormalisationOption()) {
55 requestedNormalisation = Mantid::API::NoNormalization;
56 ;
57 } else if (strNormalisation == volumeNormalisationOption()) {
58 requestedNormalisation = Mantid::API::VolumeNormalization;
59 } else {
60 requestedNormalisation = Mantid::API::NumEventsNormalization;
61 }
62 return requestedNormalisation;
63}
64
67 declareProperty(std::make_unique<WorkspaceProperty<IMDWorkspace>>("InputWorkspace", "", Direction::Input),
68 "An input MDWorkspace.");
69
70 declareProperty(std::make_unique<WorkspaceProperty<ITableWorkspace>>("OutputWorkspace", "", Direction::Output),
71 "The output Tableworkspace "
72 "with columns containing key summary information about the MDWorkspace.");
73
74 declareProperty("LimitRows", true, "Limit the report output to a maximum number of rows");
75
76 declareProperty(std::make_unique<PropertyWithValue<int>>("MaximumRows", 100000,
77 std::make_shared<BoundedValidator<int>>(), Direction::Input),
78 "The number of neighbours to utilise. Defaults to 100000.");
79 setPropertySettings("MaximumRows", std::make_unique<EnabledWhenProperty>("LimitRows", IS_DEFAULT));
80
81 std::vector<std::string> propOptions;
82 propOptions.emplace_back(noNormalisationOption());
83 propOptions.emplace_back(volumeNormalisationOption());
84 propOptions.emplace_back(numberOfEventsNormalisationOption());
85
86 declareProperty("Normalisation", "none", std::make_shared<StringListValidator>(propOptions),
87 "What normalisation do you wish to apply"
88 " none: No normalisation.\n"
89 " volume: Normalise by the volume.\n"
90 " number of events: Normalise by the number of events.");
91
92 declareProperty("TransformCoordsToOriginal", true,
93 "Output box coordinates in terms of original workspace coordinates");
94
95 declareProperty(std::make_unique<WorkspaceProperty<ITableWorkspace>>("BoxDataTable", "", Direction::Output,
97 "Optional output data table with MDEventWorkspace-specific box data.");
98}
99
100//----------------------------------------------------------------------------------------------
104template <typename MDE, size_t nd>
106 if (this->getPropertyValue("BoxDataTable").empty())
107 return;
108
109 ITableWorkspace_sptr output = WorkspaceFactory::Instance().createTable();
110 output->addColumn("int", "RecursionDepth");
111 output->addColumn("int", "NumBoxes");
112 output->addColumn("int", "NumWithEvents");
113 output->addColumn("double", "PctWithEvents");
114 output->addColumn("int", "TotalEvents");
115 output->addColumn("double", "AvgEventsPer");
116 output->addColumn("double", "TotalWeight");
117 output->addColumn("double", "TotalSignal");
118 output->addColumn("double", "TotalErrorSquared");
119 for (size_t d = 0; d < nd; d++)
120 output->addColumn("double", "Dim" + Strings::toString(d));
121
122 size_t depth = ws->getBoxController()->getMaxDepth() + 1;
123 std::vector<int> NumBoxes(depth, 0);
124 std::vector<int> NumWithEvents(depth, 0);
125 std::vector<int> TotalEvents(depth, 0);
126 std::vector<double> TotalWeight(depth, 0);
127 std::vector<double> TotalSignal(depth, 0);
128 std::vector<double> TotalErrorSquared(depth, 0);
129 std::vector<std::vector<double>> Dims(depth, std::vector<double>(nd, 0.0));
130
131 std::vector<API::IMDNode *> boxes;
132 ws->getBox()->getBoxes(boxes, depth, true);
133 for (auto &boxe : boxes) {
134 auto *box = dynamic_cast<MDBoxBase<MDE, nd> *>(boxe);
135 if (!box)
136 throw(std::runtime_error("Can not cast IMDNode to any type of boxes"));
137 size_t d = box->getDepth();
138 NumBoxes[d] += 1;
139 if (box->getNPoints() > 0)
140 NumWithEvents[d] += 1;
141 TotalEvents[d] += static_cast<int>(box->getNPoints());
142 TotalWeight[d] += box->getTotalWeight();
143 TotalSignal[d] += box->getSignal();
144 TotalErrorSquared[d] += box->getErrorSquared();
145 for (size_t dim = 0; dim < nd; dim++)
146 Dims[d][dim] = double(box->getExtents(dim).getSize());
147 }
148
149 int rowCounter = 0;
150 for (size_t d = 0; d < depth; d++) {
151 int col = 0;
152 output->appendRow();
153 output->cell<int>(rowCounter, col++) = int(d);
154 output->cell<int>(rowCounter, col++) = NumBoxes[d];
155 output->cell<int>(rowCounter, col++) = NumWithEvents[d];
156 output->cell<double>(rowCounter, col++) = 100.0 * double(NumWithEvents[d]) / double(NumBoxes[d]);
157 output->cell<int>(rowCounter, col++) = TotalEvents[d];
158 output->cell<double>(rowCounter, col++) = double(TotalEvents[d]) / double(NumBoxes[d]);
159 output->cell<double>(rowCounter, col++) = TotalWeight[d];
160 output->cell<double>(rowCounter, col++) = TotalSignal[d];
161 output->cell<double>(rowCounter, col++) = TotalErrorSquared[d];
162 for (size_t dim = 0; dim < nd; dim++)
163 output->cell<double>(rowCounter, col++) = Dims[d][dim];
164 rowCounter++;
165 }
166
167 setProperty("BoxDataTable", output);
168}
169
170//----------------------------------------------------------------------------------------------
173 // Extract the required normalisation.
174 std::string strNormalisation = getPropertyValue("Normalisation");
175 MDNormalization requestedNormalisation = whichNormalisation(strNormalisation);
176
177 IMDWorkspace_sptr input = getProperty("InputWorkspace");
178
179 const bool transformCoordsToOriginal = getProperty("TransformCoordsToOriginal");
180
181 // Define a table workspace with a specific column schema.
182 ITableWorkspace_sptr output = WorkspaceFactory::Instance().createTable();
183 const std::string signalColumnName = "Signal/" + strNormalisation;
184 const std::string errorColumnName = "Error/" + strNormalisation;
185 output->addColumn("double", signalColumnName);
186 output->addColumn("double", errorColumnName);
187 output->addColumn("int", "Number of Events");
188
189 const size_t ndims = input->getNumDims();
190 for (size_t index = 0; index < ndims; ++index) {
191 Mantid::Geometry::IMDDimension_const_sptr dim = input->getDimension(index);
192 std::string dimInUnit = dim->getName() + "/" + dim->getUnits().ascii();
193 output->addColumn("double", dimInUnit);
194 // Magic numbers required to configure the X axis.
195 output->getColumn(dimInUnit)->setPlotType(1);
196 }
197
198 // Magic numbers required to configure the Y axis.
199 output->getColumn(signalColumnName)->setPlotType(2);
200 output->getColumn(errorColumnName)->setPlotType(5);
201
202 auto it = input->createIterator();
203 it->setNormalization(requestedNormalisation);
204
205 bool bLimitRows = getProperty("LimitRows");
206 int maxRows = 0;
207 if (bLimitRows) {
208 maxRows = getProperty("MaximumRows");
209 }
210
211 // Use the iterator to loop through each MDBoxBase and create a row for each
212 // entry.
213 int rowCounter = 0;
214
215 Progress progress(this, 0.0, 1.0, int64_t(input->getNPoints()));
216 while (true) {
217 size_t cellIndex = 0;
218 output->appendRow();
219 output->cell<double>(rowCounter, cellIndex++) = it->getNormalizedSignal();
220 output->cell<double>(rowCounter, cellIndex++) = it->getNormalizedError();
221 output->cell<int>(rowCounter, cellIndex++) = int(it->getNumEvents());
222 VMD center = it->getCenter();
223 const size_t numberOriginal = input->getNumberTransformsToOriginal();
224 if (transformCoordsToOriginal && numberOriginal > 0) {
225 const size_t index = numberOriginal - 1;
226 CoordTransform const *transform = input->getTransformToOriginal(index);
227 VMD temp = transform->applyVMD(center);
228 center = temp;
229 }
230
231 for (size_t index = 0; index < ndims; ++index) {
232 output->cell<double>(rowCounter, cellIndex++) = center[index];
233 }
234
235 progress.report();
236 if (!it->next() || (bLimitRows && ((rowCounter + 1) >= maxRows))) {
237 break;
238 }
239 rowCounter++;
240 }
241 setProperty("OutputWorkspace", output);
242
243 //
245 CALL_MDEVENT_FUNCTION(this->getBoxData, input);
246}
247
248} // namespace Mantid::MDAlgorithms
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
#define CALL_MDEVENT_FUNCTION(funcname, workspace)
Macro that makes it possible to call a templated method for a MDEventWorkspace using a IMDEventWorksp...
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
Definition: Algorithm.cpp:1913
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
Definition: Algorithm.cpp:2026
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
Definition: Algorithm.cpp:231
Unique SingleValueParameter Declaration for InputNDimensions.
Mantid::Kernel::VMD applyVMD(const Mantid::Kernel::VMD &inputVector) const
Wrapper for VMD.
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
std::shared_ptr< MDEventWorkspace< MDE, nd > > sptr
Typedef for a shared pointer of this kind of event workspace.
Mantid::API::BoxController_sptr getBoxController() override
Returns the BoxController used in this workspace.
BoundedValidator is a validator that requires the values to be between upper or lower bounds,...
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)
The concrete, templated class for properties.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
void exec() override
Run the algorithm.
void init() override
Initialise the properties.
void getBoxData(typename DataObjects::MDEventWorkspace< MDE, nd >::sptr ws)
Make a table of box data.
std::shared_ptr< IMDEventWorkspace > IMDEventWorkspace_sptr
Shared pointer to Mantid::API::IMDEventWorkspace.
std::shared_ptr< ITableWorkspace > ITableWorkspace_sptr
shared pointer to Mantid::API::ITableWorkspace
std::shared_ptr< IMDWorkspace > IMDWorkspace_sptr
Shared pointer to the IMDWorkspace base class.
Definition: IMDWorkspace.h:146
MDNormalization
Enum describing different ways to normalize the signal in a MDWorkspace.
Definition: IMDIterator.h:25
@ VolumeNormalization
Divide the signal by the volume of the box/bin.
Definition: IMDIterator.h:29
@ NumEventsNormalization
Divide the signal by the number of events that contributed to it.
Definition: IMDIterator.h:31
@ NoNormalization
Don't normalize = return raw counts.
Definition: IMDIterator.h:27
std::shared_ptr< const IMDDimension > IMDDimension_const_sptr
Shared Pointer to const IMDDimension.
Definition: IMDDimension.h:101
std::string toString(const T &value)
Convert a number to a string.
Definition: Strings.cpp:703
std::string numberOfEventsNormalisationOption()
Non-member defining the number of events normalisation option.
Mantid::API::MDNormalization whichNormalisation(const std::string &strNormalisation)
Non-member method to interpret an normalisation option.
std::string noNormalisationOption()
Non-member defining the no normalisation option.
std::string volumeNormalisationOption()
Non-member defining the volume normalisation option.
STL namespace.
@ Input
An input workspace.
Definition: Property.h:53
@ Output
An output workspace.
Definition: Property.h:54