Mantid
Loading...
Searching...
No Matches
Workspace2D.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 +
9#include "MantidAPI/RefAxis.h"
12#include "MantidHistogramData/LinearGenerator.h"
16
17#include <algorithm>
18#include <sstream>
19
21
22namespace Mantid::DataObjects {
23using std::size_t;
24
25DECLARE_WORKSPACE(Workspace2D)
26
27
28Workspace2D::Workspace2D(const Parallel::StorageMode storageMode) : HistoWorkspace(storageMode) {}
29
30Workspace2D::Workspace2D(const Workspace2D &other) : HistoWorkspace(other), m_monitorList(other.m_monitorList) {
31 data.resize(other.data.size());
32 for (size_t i = 0; i < data.size(); ++i) {
33 data[i] = std::make_unique<Histogram1D>(*(other.data[i]));
34 }
35}
36
39
52void Workspace2D::init(const std::size_t &NVectors, const std::size_t &XLength, const std::size_t &YLength) {
53 data.resize(NVectors);
54
55 auto x = Kernel::make_cow<HistogramData::HistogramX>(XLength, HistogramData::LinearGenerator(1.0, 1.0));
56 HistogramData::Counts y(YLength);
57 HistogramData::CountStandardDeviations e(YLength);
58 Histogram1D spec(HistogramData::getHistogramXMode(XLength, YLength), HistogramData::Histogram::YMode::Counts);
59 spec.setX(x);
60 spec.setCounts(y);
62 for (size_t i = 0; i < data.size(); i++) {
63 data[i] = std::make_unique<Histogram1D>(spec);
64 // Default spectrum number = starts at 1, for workspace index 0.
65 data[i]->setSpectrumNo(specnum_t(i + 1));
66 }
67
68 // Add axes that reference the data
69 m_axes.resize(2);
70 m_axes[0] = std::make_unique<API::RefAxis>(this);
71 m_axes[1] = std::make_unique<API::SpectraAxis>(this);
72}
73
74void Workspace2D::init(const HistogramData::Histogram &histogram) {
76
77 HistogramData::Histogram initializedHistogram(histogram);
78 if (!histogram.sharedY()) {
79 if (histogram.yMode() == HistogramData::Histogram::YMode::Frequencies) {
80 initializedHistogram.setFrequencies(histogram.size(), 0.0);
81 initializedHistogram.setFrequencyStandardDeviations(histogram.size(), 0.0);
82 } else { // YMode::Counts or YMode::Uninitialized -> default to Counts
83 initializedHistogram.setCounts(histogram.size(), 0.0);
84 initializedHistogram.setCountStandardDeviations(histogram.size(), 0.0);
85 }
86 }
87
88 Histogram1D spec(initializedHistogram.xMode(), initializedHistogram.yMode());
89 spec.setHistogram(initializedHistogram);
90 std::transform(data.begin(), data.end(), data.begin(),
91 [&spec](const auto &) { return std::move(std::make_unique<Histogram1D>(spec)); });
92
93 // Add axes that reference the data
94 m_axes.resize(2);
95 m_axes[0] = std::make_unique<API::RefAxis>(this);
96 m_axes[1] = std::make_unique<API::SpectraAxis>(this);
97}
98
102 if (data.empty()) {
103 throw std::runtime_error("There is no data in the Workspace2D, "
104 "therefore cannot determine if it is ragged.");
105 } else {
106 const auto numberOfBins = data[0]->size();
107 return std::any_of(data.cbegin(), data.cend(),
108 [&numberOfBins](const auto &histogram) { return numberOfBins != histogram->size(); });
109 }
110}
111
116
118size_t Workspace2D::size() const {
119 return std::accumulate(
120 data.begin(), data.end(), static_cast<size_t>(0),
121 [](const size_t value, const std::unique_ptr<Histogram1D> &histo) { return value + histo->size(); });
122}
123
126 if (data.empty()) {
127 return 0;
128 } else {
129 size_t numBins = data[0]->size();
130 const auto it =
131 std::find_if_not(data.cbegin(), data.cend(), [numBins](const auto &iter) { return numBins == iter->size(); });
132 if (it != data.cend())
133 throw std::length_error("blocksize undefined because size of histograms is not equal");
134 return numBins;
135 }
136}
137
142std::size_t Workspace2D::getNumberBins(const std::size_t &index) const {
143 if (index < data.size())
144 return data[index]->size();
145
146 throw std::invalid_argument("Could not find number of bins in a histogram at index " + std::to_string(index) +
147 ": index is too large.");
148}
149
153std::size_t Workspace2D::getMaxNumberBins() const {
154 if (data.empty()) {
155 return 0;
156 } else {
157 auto maxNumberOfBins = data[0]->size();
158 for (const auto &iter : data) {
159 const auto numberOfBins = iter->size();
160 if (numberOfBins > maxNumberOfBins)
161 maxNumberOfBins = numberOfBins;
162 }
163 return maxNumberOfBins;
164 }
165}
166
173void Workspace2D::setImageY(const MantidImage &image, size_t start, bool parallelExecution) {
175 setImageYAndE(image, m, start, parallelExecution);
176}
177
184void Workspace2D::setImageE(const MantidImage &image, size_t start, bool parallelExecution) {
186 setImageYAndE(m, image, start, parallelExecution);
187}
188
205void Workspace2D::setImageYAndE(const API::MantidImage &imageY, const API::MantidImage &imageE, size_t start,
206 bool loadAsRectImg, double scale_1, [[maybe_unused]] bool parallelExecution) {
207 if (imageY.empty() && imageE.empty())
208 return;
209 if (imageY.empty() && imageE[0].empty())
210 return;
211 if (imageE.empty() && imageY[0].empty())
212 return;
213
214 const size_t numBins = blocksize();
215 if (!loadAsRectImg && numBins != 1) {
216 throw std::runtime_error("Cannot set image in workspace: a single bin workspace is "
217 "required when initializing a workspace from an "
218 "image using a histogram per pixel.");
219 }
220
221 size_t height;
222 size_t width;
223 if (!imageY.empty()) {
224 height = imageY.size();
225 width = imageY.front().size();
226 } else {
227 height = imageE.size();
228 width = imageE.front().size();
229 }
230 size_t dataSize = width * height;
231
232 if (start + dataSize > getNumberHistograms() * numBins) {
233 throw std::runtime_error("Cannot set image: image is bigger than workspace.");
234 }
235
236 if (!loadAsRectImg) {
237 // 1 pixel - one spectrum
238 PARALLEL_FOR_IF(parallelExecution)
239 for (int i = 0; i < static_cast<int>(height); ++i) {
240
241 const auto &rowY = imageY[i];
242 const auto &rowE = imageE[i];
243 size_t spec = start + static_cast<size_t>(i) * width;
244 auto pE = rowE.begin();
245 for (auto pY = rowY.begin(); pY != rowY.end() && pE != rowE.end(); ++pY, ++pE, ++spec) {
246 data[spec]->dataY()[0] = *pY;
247 data[spec]->dataE()[0] = *pE;
248 }
249 }
250 } else {
251
252 if (height != (getNumberHistograms()))
253 throw std::runtime_error(std::string("To load an image into a workspace with one spectrum per "
254 "row, then number of spectra (") +
256 ") needs to be equal to the height (rows) of the image (" + std::to_string(height) +
257 ")");
258
259 if (width != numBins)
260 throw std::runtime_error(std::string("To load an image into a workspace with one spectrum per "
261 "row, then number of bins (") +
262 std::to_string(numBins) + ") needs to be equal to the width (columns) of the image (" +
263 std::to_string(width) + ")");
264
265 // one spectrum - one row
266 PARALLEL_FOR_IF(parallelExecution)
267 for (int i = 0; i < static_cast<int>(height); ++i) {
268
269 const auto &rowY = imageY[i];
270 const auto &rowE = imageE[i];
271 data[i]->dataY() = rowY;
272 data[i]->dataE() = rowE;
273 }
274 // X values. Set first spectrum and copy/propagate that one to all the other
275 // spectra
276 PARALLEL_FOR_IF(parallelExecution)
277 for (int i = 0; i < static_cast<int>(width) + 1; ++i) {
278 data[0]->dataX()[i] = i * scale_1;
279 }
280 PARALLEL_FOR_IF(parallelExecution)
281 for (int i = 1; i < static_cast<int>(height); ++i) {
282 data[i]->setX(data[0]->ptrX());
283 }
284 }
285}
286
289 auto &spec = const_cast<Histogram1D &>(static_cast<const Workspace2D &>(*this).getSpectrum(index));
290 spec.setMatrixWorkspace(this, index);
291 return spec;
292}
293
295const Histogram1D &Workspace2D::getSpectrum(const size_t index) const {
296 if (index >= data.size()) {
297 std::ostringstream ss;
298 ss << "Workspace2D::getSpectrum, histogram number " << index << " out of range " << data.size();
299 throw std::range_error(ss.str());
300 }
301 return *data[index];
302}
303
304//--------------------------------------------------------------------------------------------
312size_t Workspace2D::getHistogramNumberHelper() const { return data.size(); }
313
314//---------------------------------------------------------------------------
325 bool skipError) const {
326 UNUSED_ARG(skipError);
327 if (index >= data.size())
328 throw std::range_error("Workspace2D::generateHistogram, histogram number out of range");
329 // output data arrays are implicitly filled by function
330 const auto &spec = this->getSpectrum(index);
331 const MantidVec &currentX = spec.readX();
332 const MantidVec &currentY = spec.readY();
333 const MantidVec &currentE = spec.readE();
334 if (X.size() <= 1)
335 throw std::runtime_error("Workspace2D::generateHistogram(): X vector must be at least length 2");
336 Y.resize(X.size() - 1, 0);
337 E.resize(X.size() - 1, 0);
338
339 // Perform the rebin from the current bins to the new ones
340 if (currentX.size() == currentY.size()) // First, convert to bin boundaries if needed. The
341 { // VectorHelper::rebin, assumes bin boundaries, even if
342 std::vector<double> histX; // it is a distribution!
343 histX.resize(currentX.size() + 1);
345 Mantid::Kernel::VectorHelper::rebin(histX, currentY, currentE, X, Y, E, true);
346 } else // assume x_size = y_size + 1
347 {
348 Mantid::Kernel::VectorHelper::rebin(currentX, currentY, currentE, X, Y, E, this->isDistribution());
349 }
350}
351
352Workspace2D *Workspace2D::doClone() const { return new Workspace2D(*this); }
354} // namespace Mantid::DataObjects
355
356namespace Mantid::Kernel {
357template <>
359IPropertyManager::getValue<Mantid::DataObjects::Workspace2D_sptr>(const std::string &name) const {
360 auto *prop = dynamic_cast<PropertyWithValue<Mantid::DataObjects::Workspace2D_sptr> *>(getPointerToProperty(name));
361 if (prop) {
362 return *prop;
363 } else {
364 std::string message =
365 "Attempt to assign property " + name + " to incorrect type. Expected shared_ptr<Workspace2D>.";
366 throw std::runtime_error(message);
367 }
368}
369
370template <>
372IPropertyManager::getValue<Mantid::DataObjects::Workspace2D_const_sptr>(const std::string &name) const {
373 auto *prop = dynamic_cast<PropertyWithValue<Mantid::DataObjects::Workspace2D_sptr> *>(getPointerToProperty(name));
374 if (prop) {
375 return prop->operator()();
376 } else {
377 std::string message =
378 "Attempt to assign property " + name + " to incorrect type. Expected const shared_ptr<Workspace2D>.";
379 throw std::runtime_error(message);
380 }
381}
382} // namespace Mantid::Kernel
383
double value
The value of the point.
Definition: FitMW.cpp:51
double height
Definition: GetAllEi.cpp:155
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
#define PARALLEL_FOR_IF(condition)
Empty definitions - to enable set your complier to enable openMP.
#define DLLExport
Definitions of the DLLImport compiler directives for MSVC.
Definition: System.h:53
#define UNUSED_ARG(x)
Function arguments are sometimes unused in certain implmentations but are required for documentation ...
Definition: System.h:64
#define DECLARE_WORKSPACE(classname)
size_t numberOfDetectorGroups() const
Returns the number of detector groups.
HistoWorkspace is an abstract base class for MatrixWorkspace types that are NOT event workspaces.
void setHistogram(T &&...data)
Sets the Histogram associated with this spectrum.
Definition: ISpectrum.h:97
void setMatrixWorkspace(MatrixWorkspace *matrixWorkspace, const size_t index)
Sets the MatrixWorkspace pointer (pointer to the owning workspace).
Definition: ISpectrum.cpp:183
void setCountStandardDeviations(T &&...data) &
Definition: ISpectrum.h:156
void setCounts(T &&...data) &
Definition: ISpectrum.h:147
std::vector< std::unique_ptr< Axis > > m_axes
A vector of pointers to the axes for this workspace.
const HistogramData::HistogramE & e(const size_t index) const
bool isDistribution() const
Are the Y-values dimensioned?
HistogramData::Histogram histogram(const size_t index) const
Returns the Histogram at the given workspace index.
Parallel::StorageMode storageMode() const
Returns the storage mode (used for MPI runs)
Definition: Workspace.cpp:82
1D histogram implementation.
Definition: Histogram1D.h:18
void setX(const Kernel::cow_ptr< HistogramData::HistogramX > &X) override
Deprecated, use setSharedX() instead.
Definition: Histogram1D.cpp:51
Concrete workspace implementation.
Definition: Workspace2D.h:29
std::size_t getNumberHistograms() const override
Returns the histogram number.
std::size_t size() const override
get pseudo size
bool isRaggedWorkspace() const override
Returns true if the workspace is ragged (has differently sized spectra).
std::vector< std::unique_ptr< Histogram1D > > data
A vector that holds the 1D histograms.
Definition: Workspace2D.h:97
std::size_t getMaxNumberBins() const override
Returns the maximum number of bins in a workspace (works on ragged data).
void setImageYAndE(const API::MantidImage &imageY, const API::MantidImage &imageE, size_t start=0, bool loadAsRectImg=false, double scale_1=1.0, bool parallelExecution=true)
Copy the data from an image to this workspace's (Y's) and errors.
void init(const std::size_t &NVectors, const std::size_t &XLength, const std::size_t &YLength) override
Called by initialize()
Definition: Workspace2D.cpp:52
Workspace2D * doClone() const override
Virtual clone method. Not implemented to force implementation in children.
void generateHistogram(const std::size_t index, const MantidVec &X, MantidVec &Y, MantidVec &E, bool skipError=false) const override
Generate a new histogram by rebinning the existing histogram.
~Workspace2D() override
Destructor.
virtual std::size_t getHistogramNumberHelper() const
Returns the number of histograms.
Histogram1D & getSpectrumWithoutInvalidation(const size_t index) override
Return reference to Histogram1D at the given workspace index.
std::size_t getNumberBins(const std::size_t &index) const override
Returns the number of bins for a given histogram index.
void setImageY(const API::MantidImage &image, size_t start=0, bool parallelExecution=true) override
Copy the data (Y's) from an image to this workspace.
void setImageE(const API::MantidImage &image, size_t start=0, bool parallelExecution=true) override
Copy the data from an image to this workspace's errors.
Workspace2D(const Parallel::StorageMode storageMode=Parallel::StorageMode::Cloned)
Constructor.
Definition: Workspace2D.cpp:28
Histogram1D & getSpectrum(const size_t index) override
Return the underlying ISpectrum ptr at the given workspace index.
Definition: Workspace2D.h:62
std::size_t blocksize() const override
get the size of each vector
Workspace2D * doCloneEmpty() const override
Virtual cloneEmpty method.
The concrete, templated class for properties.
std::vector< std::vector< double > > MantidImage
typedef for the image type
std::shared_ptr< Workspace2D > Workspace2D_sptr
shared pointer to Mantid::DataObjects::Workspace2D
std::shared_ptr< const Workspace2D > Workspace2D_const_sptr
shared pointer to Mantid::DataObjects::Workspace2D (const version)
void MANTID_KERNEL_DLL rebin(const std::vector< double > &xold, const std::vector< double > &yold, const std::vector< double > &eold, const std::vector< double > &xnew, std::vector< double > &ynew, std::vector< double > &enew, bool distribution, bool addition=false)
Rebins data according to a new output X array.
void MANTID_KERNEL_DLL convertToBinBoundary(const std::vector< double > &bin_centers, std::vector< double > &bin_edges)
Convert an array of bin centers to bin boundary values.
std::vector< double > MantidVec
typedef for the data storage used in Mantid matrix workspaces
Definition: cow_ptr.h:172
int32_t specnum_t
Typedef for a spectrum Number.
Definition: IDTypes.h:16
std::string to_string(const wide_integer< Bits, Signed > &n)