Newer
Older
#include "MantidMDAlgorithms/CreateMDHistoWorkspace.h"
#include "MantidKernel/ArrayProperty.h"
#include "MantidKernel/MandatoryValidator.h"
#include "MantidKernel/CompositeValidator.h"
#include "MantidKernel/BoundedValidator.h"
#include <algorithm>
using namespace Mantid::Kernel;
using namespace Mantid::API;
using namespace Mantid::DataObjects;
namespace Mantid {
namespace MDAlgorithms {
/**
Helper type to compute the square in-place.
*/
struct Square : public std::unary_function<double, void> {
void operator()(double &i) { i *= i; }
};
// Register the algorithm into the AlgorithmFactory
DECLARE_ALGORITHM(CreateMDHistoWorkspace)
//----------------------------------------------------------------------------------------------
/** Constructor
*/
CreateMDHistoWorkspace::CreateMDHistoWorkspace() {}
//----------------------------------------------------------------------------------------------
/** Destructor
*/
CreateMDHistoWorkspace::~CreateMDHistoWorkspace() {}
//----------------------------------------------------------------------------------------------
/// Algorithm's name for identification. @see Algorithm::name
const std::string CreateMDHistoWorkspace::name() const {
return "CreateMDHistoWorkspace";
/// Algorithm's version for identification. @see Algorithm::version
int CreateMDHistoWorkspace::version() const { return 1; }
/// Algorithm's category for identification. @see Algorithm::category
const std::string CreateMDHistoWorkspace::category() const {
return "MDAlgorithms";
}
//----------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------
/** Initialize the algorithm's properties.
*/
void CreateMDHistoWorkspace::init() {
auto validator = boost::make_shared<CompositeValidator>();
validator->add(boost::make_shared<BoundedValidator<int>>(1, 9));
validator->add(boost::make_shared<MandatoryValidator<int>>());
auto mandatoryIntArrayValidator =
boost::make_shared<MandatoryValidator<std::vector<int>>>();
auto mandatoryDoubleArrayValidator =
boost::make_shared<MandatoryValidator<std::vector<double>>>();
auto mandatoryStrArrayValidator =
boost::make_shared<MandatoryValidator<std::vector<std::string>>>();
declareProperty(
new ArrayProperty<double>("SignalInput", mandatoryDoubleArrayValidator),
"Signal array for n-dimensional workspace");
declareProperty(
new ArrayProperty<double>("ErrorInput", mandatoryDoubleArrayValidator),
"Error array for n-dimensional workspace");
declareProperty(
new ArrayProperty<double>("NumberOfEvents", std::vector<double>(0)),
"Number of pixels array for n-dimensional workspace. Optional, defaults "
"to 1 per bin.");
declareProperty(new PropertyWithValue<int>("Dimensionality", -1, validator,
Direction::Input),
"Dimensionality of the data in the file.");
declareProperty(
new ArrayProperty<double>("Extents", mandatoryDoubleArrayValidator),
"A comma separated list of min, max for each dimension,\n"
"specifying the extents of each dimension.");
declareProperty(
new ArrayProperty<int>("NumberOfBins", mandatoryIntArrayValidator),
"Number of bin in each dimension.");
declareProperty(
new ArrayProperty<std::string>("Names", mandatoryStrArrayValidator),
"A comma separated list of the name of each dimension.");
declareProperty(
new ArrayProperty<std::string>("Units", mandatoryStrArrayValidator),
"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.");
}
//----------------------------------------------------------------------------------------------
/** Execute the algorithm.
*/
void CreateMDHistoWorkspace::exec() {
MDHistoWorkspace_sptr ws = this->createEmptyOutputWorkspace();
Mantid::signal_t *signals = ws->getSignalArray();
Mantid::signal_t *errors = ws->getErrorSquaredArray();
Mantid::signal_t *nEvents = ws->getNumEventsArray();
std::vector<double> signalValues = getProperty("SignalInput");
std::vector<double> errorValues = getProperty("ErrorInput");
std::vector<double> numberOfEvents = getProperty("NumberOfEvents");
size_t binProduct = this->getBinProduct();
std::stringstream stream;
stream << binProduct;
if (binProduct != signalValues.size()) {
throw std::invalid_argument("Expected size of the SignalInput is: " +
stream.str());
if (binProduct != errorValues.size()) {
throw std::invalid_argument("Expected size of the ErrorInput is: " +
stream.str());
if (!numberOfEvents.empty() && binProduct != numberOfEvents.size()) {
throw std::invalid_argument("Expected size of the NumberOfEvents is: " +
stream.str() +
". Leave empty to auto fill with 1.0");
numberOfEvents = std::vector<double>(binProduct, 1.0);
}
// Copy from property
std::copy(signalValues.begin(), signalValues.end(), signals);
std::vector<double> empty;
// Clean up.
signalValues.swap(empty);
// Copy from property
std::for_each(errorValues.begin(), errorValues.end(), Square());
std::copy(errorValues.begin(), errorValues.end(), errors);
// Clean up
errorValues.swap(empty);
// Copy from property
std::copy(numberOfEvents.begin(), numberOfEvents.end(), nEvents);
// Clean up
numberOfEvents.swap(empty);
setProperty("OutputWorkspace", ws);
}
} // namespace Mantid
} // namespace DataObjects