16#include "MantidHistogramData/HistogramBuilder.h"
17#include "MantidIndexing/GlobalSpectrumIndex.h"
18#include "MantidIndexing/IndexInfo.h"
19#include "MantidIndexing/SpectrumIndexSet.h"
29using namespace Kernel;
31using namespace DataObjects;
32using namespace HistogramData;
33using namespace Indexing;
41 unitOptions.emplace_back(
"SpectraNumber");
42 unitOptions.emplace_back(
"Text");
45 "Name to be given to the created workspace.");
47 auto required = std::make_shared<MandatoryValidator<std::vector<double>>>();
48 declareProperty(std::make_unique<
ArrayProperty<double>>(
"DataX", required),
"X-axis data values for workspace.");
50 "Y-axis data values for workspace (measures).");
52 declareProperty(std::make_unique<
PropertyWithValue<int>>(
"NSpec", 1),
"Number of spectra to divide data into.");
53 declareProperty(
"UnitX",
"",
"The unit to assign to the XAxis");
55 declareProperty(
"VerticalAxisUnit",
"SpectraNumber", std::make_shared<StringListValidator>(unitOptions),
56 "The unit to assign to the second Axis (leave blank for "
57 "default Spectra number)");
61 "Whether OutputWorkspace should be marked as a distribution.");
62 declareProperty(
"YUnitLabel",
"",
"Label for Y Axis");
64 declareProperty(
"WorkspaceTitle",
"",
"Title for Workspace");
68 "Name of a parent workspace.");
69 declareProperty(std::make_unique<
ArrayProperty<double>>(
"Dx"),
"X error values for workspace (optional).");
70 std::vector<std::string> propOptions{Parallel::toString(Parallel::StorageMode::Cloned),
71 Parallel::toString(Parallel::StorageMode::Distributed),
72 Parallel::toString(Parallel::StorageMode::MasterOnly)};
73 declareProperty(
"ParallelStorageMode", Parallel::toString(Parallel::StorageMode::Cloned),
74 std::make_shared<StringListValidator>(propOptions),
75 "The parallel storage mode of the output workspace for MPI builds");
76 setPropertySettings(
"ParallelStorageMode", std::make_unique<InvisibleProperty>());
81 std::map<std::string, std::string> issues;
83 const std::string vUnit =
getProperty(
"VerticalAxisUnit");
84 const std::vector<std::string> vAxis =
getProperty(
"VerticalAxisValues");
86 if (vUnit ==
"SpectraNumber" && !vAxis.empty())
87 issues[
"VerticalAxisValues"] =
"Axis values cannot be provided when using a spectra axis";
102 throw std::invalid_argument(
"DataX cannot be casted to a double vector");
103 const std::vector<double> &dataX = *xCheck;
107 throw std::invalid_argument(
"DataY cannot be casted to a double vector");
108 const std::vector<double> &dataY = *yCheck;
112 throw std::invalid_argument(
"DataE cannot be casted to a double vector");
113 const std::vector<double> &dataE = *eCheck;
117 throw std::invalid_argument(
"Dx cannot be casted to a double vector");
118 const std::vector<double> &dX = *dxCheck;
122 const std::string vUnit =
getProperty(
"VerticalAxisUnit");
123 const std::vector<std::string> vAxis =
getProperty(
"VerticalAxisValues");
126 const auto vAxisSize =
static_cast<int>(vAxis.size());
127 if (vUnit !=
"SpectraNumber") {
130 if ((vUnit ==
"Text" && vAxisSize != nSpec) || (vAxisSize != nSpec && vAxisSize != nSpec + 1)) {
131 throw std::invalid_argument(
"The number of vertical axis values doesn't "
132 "match the number of histograms.");
137 if ((dataY.size() % nSpec) != 0) {
138 throw std::invalid_argument(
"Length of DataY must be divisible by NSpec");
140 const std::size_t ySize = dataY.size() / nSpec;
144 const bool commonX(dataX.size() == ySize || dataX.size() == ySize + 1);
146 std::size_t xSize{dataX.size()};
147 HistogramBuilder histogramBuilder;
149 histogramBuilder.setX(dataX);
151 if (xSize % nSpec != 0) {
152 throw std::invalid_argument(
"Length of DataX must be divisible by NSpec");
155 histogramBuilder.setX(xSize);
157 histogramBuilder.setY(ySize);
160 if (dX.size() != dataY.size())
161 throw std::runtime_error(
"Dx must have the same size as DataY");
162 histogramBuilder.setDx(ySize);
165 histogramBuilder.setDistribution(
getProperty(
"Distribution"));
166 auto histogram = histogramBuilder.build();
168 const bool dataE_provided = !dataE.empty();
169 if (dataE_provided && dataY.size() != dataE.size()) {
170 throw std::runtime_error(
"DataE (if provided) must be the same size as DataY");
177 outputWS = create<HistoWorkspace>(*parentWS, nSpec, histogram);
179 auto storageMode = Parallel::fromString(
getProperty(
"ParallelStorageMode"));
180 IndexInfo indexInfo(nSpec, storageMode,
communicator());
181 outputWS = create<Workspace2D>(indexInfo, histogram);
185 const auto &indexInfo = outputWS->indexInfo();
188 for (
int i = 0; i < nSpec; i++) {
193 const auto localIndices = indexInfo.makeIndexSet({
static_cast<GlobalSpectrumIndex
>(i)});
194 if (localIndices.empty())
197 const std::vector<double>::difference_type xStart = i * xSize;
198 const std::vector<double>::difference_type xEnd = xStart + xSize;
199 const std::vector<double>::difference_type yStart = i * ySize;
200 const std::vector<double>::difference_type yEnd = yStart + ySize;
201 auto local_i = localIndices[0];
206 outputWS->mutableX(local_i).assign(dataX.begin() + xStart, dataX.begin() + xEnd);
208 outputWS->mutableY(local_i).assign(dataY.begin() + yStart, dataY.begin() + yEnd);
211 outputWS->mutableE(local_i).assign(dataE.begin() + yStart, dataE.begin() + yEnd);
214 outputWS->mutableDx(local_i).assign(dX.begin() + yStart, dX.begin() + yEnd);
226 Unit_sptr unit = outputWS->getAxis(0)->unit();
227 std::shared_ptr<Units::Label> label = std::dynamic_pointer_cast<Units::Label>(unit);
228 label->setLabel(xUnit, xUnit);
233 if (vUnit !=
"SpectraNumber") {
234 if (vUnit ==
"Text") {
235 auto newAxis = std::make_unique<TextAxis>(vAxis.size());
236 auto newAxisRaw = newAxis.get();
237 outputWS->replaceAxis(1, std::move(newAxis));
238 for (
size_t i = 0; i < vAxis.size(); i++) {
239 newAxisRaw->setLabel(i, vAxis[i]);
242 std::unique_ptr<NumericAxis> newAxis(
nullptr);
243 if (vAxisSize == nSpec)
244 newAxis = std::make_unique<NumericAxis>(vAxisSize);
245 else if (vAxisSize == nSpec + 1)
246 newAxis = std::make_unique<BinEdgeAxis>(vAxisSize);
248 throw std::range_error(
"Invalid vertical axis length. It must be the "
249 "same length as NSpec or 1 longer.");
250 auto newAxisRaw = newAxis.get();
252 outputWS->replaceAxis(1, std::move(newAxis));
253 for (
size_t i = 0; i < vAxis.size(); i++) {
255 newAxisRaw->setValue(i, boost::lexical_cast<double, std::string>(vAxis[i]));
256 }
catch (boost::bad_lexical_cast &) {
257 throw std::invalid_argument(
"CreateWorkspace - YAxisValues property "
258 "could not be converted to a double.");
266 outputWS->setYUnitLabel(
getProperty(
"YUnitLabel"));
278Parallel::ExecutionMode
280 const auto storageMode = Parallel::fromString(
getProperty(
"ParallelStorageMode"));
281 if (!storageModes.empty())
282 if (storageModes.begin()->second != storageMode)
283 throw std::invalid_argument(
"Input workspace storage mode differs from "
284 "requested output workspace storage mode.");
285 return Parallel::getCorrespondingExecutionMode(storageMode);
#define DECLARE_ALGORITHM(classname)
#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.
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.
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
const Parallel::Communicator & communicator() const
Returns a const reference to the (MPI) communicator of the algorithm.
Helper class for reporting progress from algorithms.
A property class for workspaces.
CreateWorkspace Algorithm.
std::map< std::string, std::string > validateInputs() override
Input validation.
void exec() override
Execute the Algorithm.
Parallel::ExecutionMode getParallelExecutionMode(const std::map< std::string, Parallel::StorageMode > &storageModes) const override
Get correct execution mode based on input storage modes for an MPI run.
Support for a property that holds an array of values.
Exception for when an item is not found in a collection.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
The concrete, templated class for properties.
Base class for properties.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::shared_ptr< Unit > Unit_sptr
Shared pointer to the Unit base class.
std::enable_if< std::is_pointer< Arg >::value, bool >::type threadSafe(Arg workspace)
Thread-safety check Checks the workspace to ensure it is suitable for multithreaded access.
@ Input
An input workspace.
@ Output
An output workspace.