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"
10#include "MantidAPI/Run.h"
13#include "MantidHistogramData/LinearGenerator.h"
17
18#include <algorithm>
19#include <sstream>
20
22
23namespace Mantid::DataObjects {
24using std::size_t;
25
26DECLARE_WORKSPACE(Workspace2D)
27
28
30
31Workspace2D::Workspace2D(const Workspace2D &other) : HistoWorkspace(other), m_monitorList(other.m_monitorList) {
32 data.resize(other.data.size());
33 for (size_t i = 0; i < data.size(); ++i) {
34 data[i] = std::make_unique<Histogram1D>(*(other.data[i]));
35 }
36}
37
40
53void Workspace2D::init(const std::size_t &NVectors, const std::size_t &XLength, const std::size_t &YLength) {
54 data.resize(NVectors);
55
56 auto x = Kernel::make_cow<HistogramData::HistogramX>(XLength, HistogramData::LinearGenerator(1.0, 1.0));
57 HistogramData::Counts y(YLength);
58 HistogramData::CountStandardDeviations e(YLength);
59 Histogram1D spec(HistogramData::getHistogramXMode(XLength, YLength), HistogramData::Histogram::YMode::Counts);
60 spec.setX(x);
61 spec.setCounts(y);
63 for (size_t i = 0; i < data.size(); i++) {
64 data[i] = std::make_unique<Histogram1D>(spec);
65 // Default spectrum number = starts at 1, for workspace index 0.
66 data[i]->setSpectrumNo(specnum_t(i + 1));
67 }
68
69 // Add axes that reference the data
70 m_axes.resize(2);
71 m_axes[0] = std::make_unique<API::RefAxis>(this);
72 m_axes[1] = std::make_unique<API::SpectraAxis>(this);
73}
74
75void Workspace2D::init(const HistogramData::Histogram &histogram) {
77
78 HistogramData::Histogram initializedHistogram(histogram);
79 if (!histogram.sharedY()) {
80 if (histogram.yMode() == HistogramData::Histogram::YMode::Frequencies) {
81 initializedHistogram.setFrequencies(histogram.size(), 0.0);
82 initializedHistogram.setFrequencyStandardDeviations(histogram.size(), 0.0);
83 } else { // YMode::Counts or YMode::Uninitialized -> default to Counts
84 initializedHistogram.setCounts(histogram.size(), 0.0);
85 initializedHistogram.setCountStandardDeviations(histogram.size(), 0.0);
86 }
87 }
88
89 Histogram1D spec(initializedHistogram.xMode(), initializedHistogram.yMode());
90 spec.setHistogram(initializedHistogram);
91 std::transform(data.begin(), data.end(), data.begin(),
92 [&spec](const auto &) { return std::make_unique<Histogram1D>(spec); });
93
94 // Add axes that reference the data
95 m_axes.resize(2);
96 m_axes[0] = std::make_unique<API::RefAxis>(this);
97 m_axes[1] = std::make_unique<API::SpectraAxis>(this);
98}
99
103 if (data.empty()) {
104 throw std::runtime_error("There is no data in the Workspace2D, "
105 "therefore cannot determine if it is ragged.");
106 } else {
107 const auto numberOfBins = data[0]->size();
108 return std::any_of(data.cbegin(), data.cend(),
109 [&numberOfBins](const auto &histogram) { return numberOfBins != histogram->size(); });
110 }
111}
112
117
119size_t Workspace2D::size() const {
120 return std::accumulate(
121 data.begin(), data.end(), static_cast<size_t>(0),
122 [](const size_t value, const std::unique_ptr<Histogram1D> &histo) { return value + histo->size(); });
123}
124
127 if (data.empty()) {
128 return 0;
129 } else {
130 size_t numBins = data[0]->size();
131 const auto it =
132 std::find_if_not(data.cbegin(), data.cend(), [numBins](const auto &iter) { return numBins == iter->size(); });
133 if (it != data.cend())
134 throw std::length_error("blocksize undefined because size of histograms is not equal");
135 return numBins;
136 }
137}
138
143std::size_t Workspace2D::getNumberBins(const std::size_t &index) const {
144 if (index < data.size())
145 return data[index]->size();
146
147 throw std::invalid_argument("Could not find number of bins in a histogram at index " + std::to_string(index) +
148 ": index is too large.");
149}
150
154std::size_t Workspace2D::getMaxNumberBins() const {
155 if (data.empty()) {
156 return 0;
157 } else {
158 auto maxNumberOfBins = data[0]->size();
159 for (const auto &iter : data) {
160 const auto numberOfBins = iter->size();
161 if (numberOfBins > maxNumberOfBins)
162 maxNumberOfBins = numberOfBins;
163 }
164 return maxNumberOfBins;
165 }
166}
167
174void Workspace2D::setImageY(const MantidImage &image, size_t start, bool parallelExecution) {
176 setImageYAndE(image, m, start, parallelExecution);
177}
178
185void Workspace2D::setImageE(const MantidImage &image, size_t start, bool parallelExecution) {
187 setImageYAndE(m, image, start, parallelExecution);
188}
189
206void Workspace2D::setImageYAndE(const API::MantidImage &imageY, const API::MantidImage &imageE, size_t start,
207 bool loadAsRectImg, double scale_1, [[maybe_unused]] bool parallelExecution) {
208 if (imageY.empty() && imageE.empty())
209 return;
210 if (imageY.empty() && imageE[0].empty())
211 return;
212 if (imageE.empty() && imageY[0].empty())
213 return;
214
215 const size_t numBins = blocksize();
216 if (!loadAsRectImg && numBins != 1) {
217 throw std::runtime_error("Cannot set image in workspace: a single bin workspace is "
218 "required when initializing a workspace from an "
219 "image using a histogram per pixel.");
220 }
221
222 size_t height;
223 size_t width;
224 if (!imageY.empty()) {
225 height = imageY.size();
226 width = imageY.front().size();
227 } else {
228 height = imageE.size();
229 width = imageE.front().size();
230 }
231 size_t dataSize = width * height;
232
233 if (start + dataSize > getNumberHistograms() * numBins) {
234 throw std::runtime_error("Cannot set image: image is bigger than workspace.");
235 }
236
237 if (!loadAsRectImg) {
238 // 1 pixel - one spectrum
239 PARALLEL_FOR_IF(parallelExecution)
240 for (int i = 0; i < static_cast<int>(height); ++i) {
241
242 const auto &rowY = imageY[i];
243 const auto &rowE = imageE[i];
244 size_t spec = start + static_cast<size_t>(i) * width;
245 auto pE = rowE.begin();
246 for (auto pY = rowY.begin(); pY != rowY.end() && pE != rowE.end(); ++pY, ++pE, ++spec) {
247 data[spec]->dataY()[0] = *pY;
248 data[spec]->dataE()[0] = *pE;
249 }
250 }
251 } else {
252
253 if (height != (getNumberHistograms()))
254 throw std::runtime_error(std::string("To load an image into a workspace with one spectrum per "
255 "row, then number of spectra (") +
257 ") needs to be equal to the height (rows) of the image (" + std::to_string(height) +
258 ")");
259
260 if (width != numBins)
261 throw std::runtime_error(std::string("To load an image into a workspace with one spectrum per "
262 "row, then number of bins (") +
263 std::to_string(numBins) + ") needs to be equal to the width (columns) of the image (" +
264 std::to_string(width) + ")");
265
266 // one spectrum - one row
267 PARALLEL_FOR_IF(parallelExecution)
268 for (int i = 0; i < static_cast<int>(height); ++i) {
269
270 const auto &rowY = imageY[i];
271 const auto &rowE = imageE[i];
272 data[i]->dataY() = rowY;
273 data[i]->dataE() = rowE;
274 }
275 // X values. Set first spectrum and copy/propagate that one to all the other
276 // spectra
277 PARALLEL_FOR_IF(parallelExecution)
278 for (int i = 0; i < static_cast<int>(width) + 1; ++i) {
279 data[0]->dataX()[i] = i * scale_1;
280 }
281 PARALLEL_FOR_IF(parallelExecution)
282 for (int i = 1; i < static_cast<int>(height); ++i) {
283 data[i]->setX(data[0]->ptrX());
284 }
285 }
286}
287
290 auto &spec = const_cast<Histogram1D &>(static_cast<const Workspace2D &>(*this).getSpectrum(index));
291 spec.setMatrixWorkspace(this, index);
292 return spec;
293}
294
296const Histogram1D &Workspace2D::getSpectrum(const size_t index) const {
297 if (index >= data.size()) {
298 std::ostringstream ss;
299 ss << "Workspace2D::getSpectrum, histogram number " << index << " out of range " << data.size();
300 throw std::range_error(ss.str());
301 }
302 return *data[index];
303}
304
305//--------------------------------------------------------------------------------------------
313size_t Workspace2D::getHistogramNumberHelper() const { return data.size(); }
314
315//---------------------------------------------------------------------------
326 bool skipError) const {
327 UNUSED_ARG(skipError);
328 if (index >= data.size())
329 throw std::range_error("Workspace2D::generateHistogram, histogram number out of range");
330 // output data arrays are implicitly filled by function
331 const auto &spec = this->getSpectrum(index);
332 const MantidVec &currentX = spec.readX();
333 const MantidVec &currentY = spec.readY();
334 const MantidVec &currentE = spec.readE();
335 if (X.size() <= 1)
336 throw std::runtime_error("Workspace2D::generateHistogram(): X vector must be at least length 2");
337 Y.resize(X.size() - 1, 0);
338 E.resize(X.size() - 1, 0);
339
340 // Perform the rebin from the current bins to the new ones
341 if (currentX.size() == currentY.size()) // First, convert to bin boundaries if needed. The
342 { // VectorHelper::rebin, assumes bin boundaries, even if
343 std::vector<double> histX; // it is a distribution!
344 histX.resize(currentX.size() + 1);
346 Mantid::Kernel::VectorHelper::rebin(histX, currentY, currentE, X, Y, E, true);
347 } else // assume x_size = y_size + 1
348 {
349 Mantid::Kernel::VectorHelper::rebin(currentX, currentY, currentE, X, Y, E, this->isDistribution());
350 }
351}
352
353Workspace2D *Workspace2D::doClone() const { return new Workspace2D(*this); }
355} // namespace Mantid::DataObjects
356
357namespace Mantid::Kernel {
358template <>
360IPropertyManager::getValue<Mantid::DataObjects::Workspace2D_sptr>(const std::string &name) const {
361 auto *prop = dynamic_cast<PropertyWithValue<Mantid::DataObjects::Workspace2D_sptr> *>(getPointerToProperty(name));
362 if (prop) {
363 return *prop;
364 } else {
365 std::string message =
366 "Attempt to assign property " + name + " to incorrect type. Expected shared_ptr<Workspace2D>.";
367 throw std::runtime_error(message);
368 }
369}
370
371template <>
373IPropertyManager::getValue<Mantid::DataObjects::Workspace2D_const_sptr>(const std::string &name) const {
374 const auto *prop =
375 dynamic_cast<PropertyWithValue<Mantid::DataObjects::Workspace2D_sptr> *>(getPointerToProperty(name));
376 if (prop) {
377 return prop->operator()();
378 } else {
379 std::string message =
380 "Attempt to assign property " + name + " to incorrect type. Expected const shared_ptr<Workspace2D>.";
381 throw std::runtime_error(message);
382 }
383}
384} // namespace Mantid::Kernel
std::string name
Definition Run.cpp:60
double value
The value of the point.
Definition FitMW.cpp:51
double height
Definition GetAllEi.cpp:155
std::map< DeltaEMode::Type, std::string > index
#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:37
#define UNUSED_ARG(x)
Function arguments are sometimes unused in certain implmentations but are required for documentation ...
Definition System.h:48
#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:96
void setMatrixWorkspace(MatrixWorkspace *matrixWorkspace, const size_t index)
Sets the MatrixWorkspace pointer (pointer to the owning workspace).
void setCountStandardDeviations(T &&...data) &
Definition ISpectrum.h:155
void setCounts(T &&...data) &
Definition ISpectrum.h:146
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.
1D histogram implementation.
Definition Histogram1D.h:18
virtual std::size_t size() const
get pseudo size
Definition Histogram1D.h:59
void setX(const Kernel::cow_ptr< HistogramData::HistogramX > &X) override
Deprecated, use setSharedX() instead.
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:98
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()
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.
Histogram1D & getSpectrum(const size_t index) override
Return the underlying ISpectrum ptr at the given workspace index.
Definition Workspace2D.h:63
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:14
std::string to_string(const wide_integer< Bits, Signed > &n)