Mantid
Loading...
Searching...
No Matches
RebinToWorkspace.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 +
13#include "MantidHistogramData/Rebin.h"
14
15namespace Mantid::Algorithms {
16
17using namespace API;
18using DataObjects::EventWorkspace;
20using HistogramData::Counts;
21using HistogramData::CountStandardDeviations;
22
23// Register the algorithm into the AlgorithmFactory
24DECLARE_ALGORITHM(RebinToWorkspace)
25
26//---------------------------
27// Private Methods
28//---------------------------
32void RebinToWorkspace::init() {
33 // using namespace Mantid::DataObjects;
34 declareProperty(std::make_unique<WorkspaceProperty<>>("WorkspaceToRebin", "", Kernel::Direction::Input,
35 std::make_unique<API::HistogramValidator>()),
36 "The workspace on which to perform the algorithm "
37 "This must be a Histogram workspace, not Point data. "
38 "If this is a problem try ConvertToHistogram.");
39 declareProperty(std::make_unique<WorkspaceProperty<>>("WorkspaceToMatch", "", Kernel::Direction::Input,
40 std::make_unique<API::HistogramValidator>()),
41 "The workspace to match the bin boundaries against. "
42 "This must be a Histogram workspace, not Point data. "
43 "If this is a problem try ConvertToHistogram.");
44 declareProperty(std::make_unique<WorkspaceProperty<>>("OutputWorkspace", "", Kernel::Direction::Output),
45 "The name of the workspace to be created as the output of the algorithm");
46 declareProperty("PreserveEvents", true,
47 "Keep the output workspace as an EventWorkspace, if the "
48 "input has events (default). "
49 "If the input and output EventWorkspace names are the same, "
50 "only the X bins are set, which is very quick. "
51 "If false, then the workspace gets converted to a "
52 "Workspace2D histogram.");
53}
54
56 // converting from EventWorkspace to Workspace2D is a rebin
58 return true;
59
60 // if pointers match they are the same object
61 if (left == rght)
62 return false;
63
64 // see if there is the same number of histograms
65 const size_t numHist = left->getNumberHistograms();
66 if (numHist != rght->getNumberHistograms())
67 return true;
68
69 // look for first non-equal x-axis between the workspaces
70 for (size_t i = 0; i < numHist; ++i) {
71 if (left->getSpectrum(i).x() != rght->getSpectrum(i).x()) {
72 return true;
73 }
74 }
75 // everything must be the same
76 return false;
77}
78
83 // The input workspaces ...
84 MatrixWorkspace_sptr toRebin = getProperty("WorkspaceToRebin");
85 MatrixWorkspace_sptr toMatch = getProperty("WorkspaceToMatch");
86 m_preserveEvents = getProperty("PreserveEvents");
87 m_isEvents = bool(std::dynamic_pointer_cast<const EventWorkspace>(toRebin));
88
89 if (needToRebin(toRebin, toMatch)) {
90 g_log.information("Rebinning");
91 if (m_isEvents && (!m_preserveEvents)) {
92 this->histogram(toRebin, toMatch);
93 } else {
94 this->rebin(toRebin, toMatch);
95 }
96 } else { // don't need to rebin
97 g_log.information("WorkspaceToRebin and WorkspaceToMatch already have matched binning");
98
99 MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace");
100 const bool inPlace = (toRebin == outputWS);
101 if (!inPlace) {
102 outputWS = toRebin->clone();
103 }
104 this->setProperty("OutputWorkspace", outputWS);
105 }
106}
107
108// this follows closely what Rebin does except each x-axis is different
110 // create the output workspace
111 MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace");
112 const bool inPlace = (toRebin == outputWS);
113 if (!inPlace) {
114 outputWS = toRebin->clone();
115 }
116 auto outputWSEvents = std::dynamic_pointer_cast<EventWorkspace>(outputWS);
117
118 const auto numHist = static_cast<int>(toRebin->getNumberHistograms());
119 Progress prog(this, 0.5, 1.0, numHist);
120
121 // everything gets the same bin boundaries as the first spectrum
122 const bool matchingX = (toRebin->getNumberHistograms() != toMatch->getNumberHistograms());
123
124 // rebin
125 PARALLEL_FOR_IF(Kernel::threadSafe(*toMatch, *outputWS))
126 for (int i = 0; i < numHist; ++i) {
128 const auto &edges = matchingX ? toMatch->histogram(0).binEdges() : toMatch->histogram(i).binEdges();
129 if (m_isEvents) {
130 outputWSEvents->getSpectrum(i).setHistogram(edges);
131 } else {
132 outputWS->setHistogram(i, HistogramData::rebin(toRebin->histogram(i), edges));
133 }
134 prog.report();
136 }
138
139 setProperty("OutputWorkspace", outputWS);
140}
141
142// handles the special case when binning from EventWorkspace to Workspace2D most
143// efficiently by histogramming the events to the correct binning directly
145 const auto &inputWS = std::dynamic_pointer_cast<const EventWorkspace>(toRebin);
146 const auto numHist = static_cast<int>(toRebin->getNumberHistograms());
147 // everything gets the same bin boundaries as the first spectrum
148 const bool matchingX = (toRebin->getNumberHistograms() != toMatch->getNumberHistograms());
149
150 auto outputWS = DataObjects::create<API::HistoWorkspace>(*toRebin);
151 Progress prog(this, 0.25, 1.0, numHist);
152
153 // histogram
154 PARALLEL_FOR_IF(Kernel::threadSafe(*toMatch, *outputWS))
155 for (int i = 0; i < numHist; ++i) {
157 const auto &edges = matchingX ? toMatch->histogram(0).binEdges() : toMatch->histogram(i).binEdges();
158
159 // TODO this should be in HistogramData/Rebin
160 const auto &eventlist = inputWS->getSpectrum(i);
161 MantidVec y_data(edges.size() - 1), e_data(edges.size() - 1);
162 eventlist.generateHistogram(edges.rawData(), y_data, e_data);
163
164 outputWS->setHistogram(i, edges, Counts(std::move(y_data)), CountStandardDeviations(std::move(e_data)));
165 prog.report();
167 }
169
170 setProperty("OutputWorkspace", std::move(outputWS));
171}
172
173Parallel::ExecutionMode
174RebinToWorkspace::getParallelExecutionMode(const std::map<std::string, Parallel::StorageMode> &storageModes) const {
175 // Probably we can relax these restrictions based on particular combination
176 // with storage mode of WorkspaceToRebin, but this is simple and sufficient
177 // for now.
178 if (storageModes.at("WorkspaceToMatch") != Parallel::StorageMode::Cloned)
179 throw std::runtime_error("WorkspaceToMatch must have " + Parallel::toString(Parallel::StorageMode::Cloned));
180 return Parallel::getCorrespondingExecutionMode(storageModes.at("WorkspaceToRebin"));
181}
182
183} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
double left
Definition: LineProfile.cpp:80
#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...
Definition: MultiThreaded.h:94
#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.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
Kernel::Logger & g_log
Definition: Algorithm.h:451
Helper class for reporting progress from algorithms.
Definition: Progress.h:25
A property class for workspaces.
Rebins a workspace so that the binning, for all its spectra, match that of the first spectrum of a se...
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.
void exec() override
Execution code.
void histogram(API::MatrixWorkspace_sptr &toRebin, API::MatrixWorkspace_sptr &toMatch)
void rebin(API::MatrixWorkspace_sptr &toRebin, API::MatrixWorkspace_sptr &toMatch)
bool needToRebin(const API::MatrixWorkspace_sptr &left, const API::MatrixWorkspace_sptr &rght)
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void information(const std::string &msg)
Logs at information level.
Definition: Logger.cpp:105
void report()
Increments the loop counter by 1, then sends the progress notification on behalf of its algorithm.
Definition: ProgressBase.h:51
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::shared_ptr< const EventWorkspace > EventWorkspace_const_sptr
shared pointer to a const Workspace2D
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.
Definition: MultiThreaded.h:22
std::vector< double > MantidVec
typedef for the data storage used in Mantid matrix workspaces
Definition: cow_ptr.h:172
@ Input
An input workspace.
Definition: Property.h:53
@ Output
An output workspace.
Definition: Property.h:54