Newer
Older
#include "MantidMDAlgorithms/ImportMDHistoWorkspaceBase.h"
#include "MantidDataObjects/MDHistoWorkspace.h"
#include "MantidKernel/ArrayProperty.h"
#include "MantidKernel/BoundedValidator.h"
#include "MantidKernel/CompositeValidator.h"
#include "MantidKernel/MandatoryValidator.h"
#include "MantidGeometry/MDGeometry/QSample.h"
#include "MantidGeometry/MDGeometry/QLab.h"
#include "MantidGeometry/MDGeometry/HKL.h"
#include "MantidGeometry/MDGeometry/GeneralFrame.h"
#include "MantidGeometry/MDGeometry/MDFrameFactory.h"
#include <algorithm>
using namespace Mantid::API;
using namespace Mantid::DataObjects;
using namespace Mantid::Geometry;
using namespace Mantid::Kernel;
namespace MDAlgorithms {
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
/**
Functor to compute the product of the set.
*/
struct Product : public std::unary_function<size_t, void> {
Product() : result(1) {}
size_t result;
void operator()(size_t x) { result *= x; }
};
//----------------------------------------------------------------------------------------------
/** Constructor
*/
ImportMDHistoWorkspaceBase::ImportMDHistoWorkspaceBase() : m_bin_product(0) {}
//----------------------------------------------------------------------------------------------
/** Destructor
*/
ImportMDHistoWorkspaceBase::~ImportMDHistoWorkspaceBase() {}
//----------------------------------------------------------------------------------------------
/** Initalise generic importing properties.
*/
void ImportMDHistoWorkspaceBase::initGenericImportProps() {
auto validator = boost::make_shared<CompositeValidator>();
validator->add(boost::make_shared<BoundedValidator<int>>(1, 9));
validator->add(boost::make_shared<MandatoryValidator<int>>());
declareProperty(new PropertyWithValue<int>("Dimensionality", -1, validator,
Direction::Input),
"Dimensionality of the data in the file.");
declareProperty(new ArrayProperty<double>("Extents"),
"A comma separated list of min, max for each dimension,\n"
"specifying the extents of each dimension.");
declareProperty(new ArrayProperty<int>("NumberOfBins"),
"Number of bin in each dimension.");
declareProperty(new ArrayProperty<std::string>("Names"),
"A comma separated list of the name of each dimension.");
declareProperty(new ArrayProperty<std::string>("Units"),
"A comma separated list of the units of each dimension.");
declareProperty(new WorkspaceProperty<IMDHistoWorkspace>(
"OutputWorkspace", "", Direction::Output),
"MDHistoWorkspace reflecting the input text file.");
declareProperty(
new ArrayProperty<std::string>("Frames"),
" A comma separated list of the frames of each dimension. "
" The frames can be"
" **General Frame**: Any frame which is not a Q-based frame."
" **QLab**: Wave-vector converted into the lab frame."
" **QSample**: Wave-vector converted into the frame of the sample."
" **HKL**: Wave-vector converted into the crystal's HKL indices."
" Note if nothing is specified then the **General Frame** is being "
"selected. Also note that if you select a frame then this might override "
"your unit selection if it is not compatible with the frame.");
}
//----------------------------------------------------------------------------------------------
/** Create an empty output workspace from the generic properies. This gives a
new workspace with dimensions provided, but signal and
error arrays will not yet be set.
*/
MDHistoWorkspace_sptr ImportMDHistoWorkspaceBase::createEmptyOutputWorkspace() {
// Fetch input properties
size_t ndims;
int ndims_int = getProperty("Dimensionality");
ndims = ndims_int;
std::vector<double> extents = getProperty("Extents");
std::vector<int> nbins = getProperty("NumberOfBins");
std::vector<std::string> names = getProperty("Names");
std::vector<std::string> units = getProperty("Units");
std::vector<std::string> frames = getProperty("Frames");
// Perform all validation on inputs
if (extents.size() != ndims * 2)
throw std::invalid_argument("You must specify twice as many extents "
"(min,max) as there are dimensions.");
if (nbins.size() != ndims)
throw std::invalid_argument(
"You must specify as number of bins as there are dimensions.");
if (names.size() != ndims)
throw std::invalid_argument(
"You must specify as many names as there are dimensions.");
if (units.size() != ndims)
throw std::invalid_argument(
"You must specify as many units as there are dimensions.");
// If no frames are specified we want to default to the General Frame,
// to ensure backward compatibility. But if they are only partly specified,
// then we want to throw an error. It should be either used correctly or not
// at all
if (!frames.empty() && frames.size() != ndims) {
throw std::invalid_argument(
"You must specify as many frames as there are dimensions.");
}
if (frames.empty()) {
frames.resize(ndims);
std::fill(frames.begin(), frames.end(), GeneralFrame::GeneralFrameName);
}
// Fabricate new dimensions from inputs
std::vector<MDHistoDimension_sptr> dimensions;
for (size_t k = 0; k < ndims; ++k) {
auto frame = createMDFrame(frames[k], units[k]);
dimensions.push_back(MDHistoDimension_sptr(new MDHistoDimension(
names[k], names[k], *frame, static_cast<coord_t>(extents[k * 2]),
static_cast<coord_t>(extents[(k * 2) + 1]), nbins[k])));
// Calculate the total number of bins by multiplying across each dimension.
Product answer = std::for_each(nbins.begin(), nbins.end(), Product());
m_bin_product = answer.result;
MDHistoWorkspace_sptr ws(new MDHistoWorkspace(dimensions));
return ws;
}
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
/**
* Create an MDFrame
* @param frame: the selected frame
* @param unit: the selected unit
* @returns a unique pointer to an MDFrame
*/
MDFrame_uptr ImportMDHistoWorkspaceBase::createMDFrame(std::string frame,
std::string unit) {
auto frameFactory = makeMDFrameFactoryChain();
MDFrameArgument frameArg(frame, unit);
return frameFactory->create(frameArg);
}
std::map<std::string, std::string>
ImportMDHistoWorkspaceBase::validateInputs() {
// Check Frame names
std::map<std::string, std::string> errors;
std::string framePropertyName = "Frames";
std::vector<std::string> frames = getProperty(framePropertyName);
int ndims_prop = getProperty("Dimensionality");
auto ndims = static_cast<size_t>(ndims_prop);
std::vector<std::string> targetFrames;
targetFrames.push_back(Mantid::Geometry::GeneralFrame::GeneralFrameName);
targetFrames.push_back(Mantid::Geometry::HKL::HKLName);
targetFrames.push_back(Mantid::Geometry::QLab::QLabName);
targetFrames.push_back(Mantid::Geometry::QSample::QSampleName);
auto isValidFrame = true;
for (auto it = frames.begin(); it != frames.end(); ++it) {
auto result = checkIfFrameValid(*it, targetFrames);
if (!result) {
isValidFrame = result;
}
}
if (!frames.empty() && frames.size() != ndims) {
isValidFrame = false;
}
if (!isValidFrame) {
std::string message = "The selected frames can be 'HKL', 'QSample', 'QLab' "
"or 'General Frame'. You must specify as many frames "
"as there are dimensions.";
errors.insert(std::make_pair(framePropertyName, message));
}
return errors;
}
/**
* Check if the specified frame matches a target frame
* @param frame: the frame name under investigation
* @param targetFrames: the allowed frame names
* @returns true if the frame name is valid else false
*/
bool ImportMDHistoWorkspaceBase::checkIfFrameValid(
const std::string &frame, const std::vector<std::string> &targetFrames) {
for (auto targetFrame = targetFrames.begin();
targetFrame != targetFrames.end(); ++targetFrame) {
if (*targetFrame == frame) {
return true;
}
}
return false;
}
} // namespace Mantid
} // namespace MDAlgorithms