Mantid
Loading...
Searching...
No Matches
Regroup.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 +
7//----------------------------------------------------------------------
8// Includes
9//----------------------------------------------------------------------
11#include "MantidAPI/Axis.h"
18
19#include <algorithm>
20#include <cmath>
21#include <functional>
22#include <numeric>
23
24namespace Mantid {
25using HistogramData::HistogramE;
26using HistogramData::HistogramX;
27using HistogramData::HistogramY;
28namespace Algorithms {
29
30// Register the class into the algorithm factory
31DECLARE_ALGORITHM(Regroup)
32
33using namespace Kernel;
34using API::MatrixWorkspace;
37using API::WorkspaceProperty;
38
41 auto wsVal = std::make_shared<CompositeValidator>();
42 wsVal->add<API::HistogramValidator>();
43 wsVal->add<API::CommonBinsValidator>();
44 declareProperty(std::make_unique<WorkspaceProperty<MatrixWorkspace>>("InputWorkspace", "", Direction::Input, wsVal),
45 "The input workspace.");
46 declareProperty(std::make_unique<WorkspaceProperty<MatrixWorkspace>>("OutputWorkspace", "", Direction::Output),
47 "The result of regrouping.");
48
49 declareProperty(std::make_unique<ArrayProperty<double>>("Params", std::make_shared<RebinParamsValidator>()),
50 "The new approximate bin boundaries in the form: x1,dx1,x2,dx2,...,xn");
51}
52
56 // retrieve the properties
57 std::vector<double> rb_params = getProperty("Params");
58
59 // Get the input workspace
60 MatrixWorkspace_const_sptr inputW = getProperty("InputWorkspace");
61
62 const bool dist = inputW->isDistribution();
63
64 const auto histnumber = static_cast<int>(inputW->getNumberHistograms());
65 HistogramData::BinEdges XValues_new(0);
66 auto &XValues_old = inputW->x(0);
67 std::vector<int> xoldIndex; // indeces of new x in XValues_old
68 // create new output X axis
69 int ntcnew = newAxis(rb_params, XValues_old.rawData(), XValues_new.mutableRawData(), xoldIndex);
70
71 // make output Workspace the same type is the input, but with new length of
72 // signal array
73 API::MatrixWorkspace_sptr outputW = API::WorkspaceFactory::Instance().create(inputW, histnumber, ntcnew, ntcnew - 1);
74
75 int progress_step = histnumber / 100;
76 if (progress_step == 0)
77 progress_step = 1;
78 for (int hist = 0; hist < histnumber; hist++) {
79 // get const references to input Workspace arrays (no copying)
80 auto &XValues = inputW->x(hist);
81 auto &YValues = inputW->y(hist);
82 auto &YErrors = inputW->e(hist);
83
84 // get references to output workspace data (no copying)
85 auto &YValues_new = outputW->mutableY(hist);
86 auto &YErrors_new = outputW->mutableE(hist);
87
88 // output data arrays are implicitly filled by function
89 rebin(XValues, YValues, YErrors, xoldIndex, YValues_new, YErrors_new, dist);
90
91 outputW->setBinEdges(hist, XValues_new);
92
93 if (hist % progress_step == 0) {
94 progress(double(hist) / histnumber);
96 }
97 }
98
99 outputW->setDistribution(dist);
100
101 // Copy units
102 if (outputW->getAxis(0)->unit().get())
103 outputW->getAxis(0)->unit() = inputW->getAxis(0)->unit();
104 try {
105 if (inputW->getAxis(1)->unit().get())
106 outputW->getAxis(1)->unit() = inputW->getAxis(1)->unit();
107 } catch (Exception::IndexError &) {
108 // OK, so this isn't a Workspace2D
109 }
110
111 // Assign it to the output workspace property
112 setProperty("OutputWorkspace", outputW);
113}
114
127void Regroup::rebin(const HistogramX &xold, const HistogramY &yold, const HistogramE &eold,
128 const std::vector<int> &xoldIndex, HistogramY &ynew, HistogramE &enew, bool distribution) {
129
130 for (int i = 0; i < int(xoldIndex.size() - 1); i++) {
131
132 int n = xoldIndex[i]; // start the group
133 int m = xoldIndex[i + 1]; // end the group
134 double width = xold[m] - xold[n]; // width of the group
135
136 if (width == 0.) {
137 g_log.error("Zero bin width");
138 throw std::runtime_error("Zero bin width");
139 }
140 /*
141 * yold contains counts/unit time, ynew contains counts
142 * enew contains counts**2
143 */
144 if (distribution) {
145 ynew[i] = 0.;
146 enew[i] = 0.;
147 for (int j = n; j < m; j++) {
148 double wdt = xold[j + 1] - xold[j]; // old bin width
149 ynew[i] += yold[j] * wdt;
150 enew[i] += eold[j] * eold[j] * wdt * wdt;
151 }
152 ynew[i] /= width;
153 enew[i] = sqrt(enew[i]) / width;
154 } else // yold,eold data is not distribution but counts
155 {
156 ynew[i] = 0.;
157 enew[i] = 0.;
158 for (int j = n; j < m; j++) {
159 ynew[i] += yold[j];
160 enew[i] += eold[j] * eold[j];
161 }
162 enew[i] = sqrt(enew[i]);
163 }
164 }
165}
166
176int Regroup::newAxis(const std::vector<double> &params, const std::vector<double> &xold, std::vector<double> &xnew,
177 std::vector<int> &xoldIndex) {
178 double xcurr, xs;
179 int ibound(2), istep(1), inew(0);
180 auto ibounds = static_cast<int>(params.size()); // highest index in params array containing a bin boundary
181 int isteps = ibounds - 1; // highest index in params array containing a step
182
183 xcurr = params[0];
184 using std::placeholders::_1;
185 auto iup = std::find_if(xold.cbegin(), xold.cend(), std::bind(std::greater_equal<double>(), _1, xcurr));
186 if (iup != xold.end()) {
187 xcurr = *iup;
188 xnew.emplace_back(xcurr);
189 xoldIndex.emplace_back(inew);
190 inew++;
191 } else
192 return 0;
193
194 while ((ibound <= ibounds) && (istep <= isteps)) {
195 // if step is negative then it is logarithmic step
196 if (params[istep] >= 0.0)
197 xs = params[istep];
198 else
199 xs = xcurr * fabs(params[istep]);
200
201 // xcurr += xs;
202
203 // find nearest x_i that is >= xcurr
204 iup = std::find_if(xold.begin(), xold.end(), std::bind(std::greater_equal<double>(), _1, xcurr + xs));
205 if (iup != xold.end()) {
206 if (*iup <= params[ibound]) {
207 xcurr = *iup;
208 xnew.emplace_back(xcurr);
209 xoldIndex.emplace_back(inew);
210 inew++;
211 } else {
212 ibound += 2;
213 istep += 2;
214 }
215 } else
216 return inew;
217 }
218 // returns length of new x array or -1 if failure
219 return inew;
220 // return( (ibound == ibounds) && (istep == isteps) ? inew : -1 );
221}
222
223} // namespace Algorithms
224} // namespace Mantid
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
#define fabs(x)
Definition: Matrix.cpp:22
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
Definition: Algorithm.cpp:1913
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
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
Definition: Algorithm.cpp:231
void interruption_point()
This is called during long-running operations, and check if the algorithm has requested that it be ca...
Definition: Algorithm.cpp:1687
A validator which provides a TENTATIVE check that a workspace contains common bins in each spectrum.
A validator which checks that a workspace contains histogram data (the default) or point data as requ...
A property class for workspaces.
void rebin(const HistogramData::HistogramX &xold, const HistogramData::HistogramY &yold, const HistogramData::HistogramE &eold, const std::vector< int > &xoldIndex, HistogramData::HistogramY &ynew, HistogramData::HistogramE &enew, bool distribution)
Regroup the data according to new output X array.
Definition: Regroup.cpp:127
void exec() override
Executes the regroup algorithm.
Definition: Regroup.cpp:55
void init() override
Initialisation method. Declares properties to be used in algorithm.
Definition: Regroup.cpp:40
int newAxis(const std::vector< double > &params, const std::vector< double > &xold, std::vector< double > &xnew, std::vector< int > &xoldIndex)
Creates a new output X array according to specific boundary defnitions.
Definition: Regroup.cpp:176
Support for a property that holds an array of values.
Definition: ArrayProperty.h:28
Exception for index errors.
Definition: Exception.h:284
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void error(const std::string &msg)
Logs at error level.
Definition: Logger.cpp:77
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
Helper class which provides the Collimation Length for SANS instruments.
@ Input
An input workspace.
Definition: Property.h:53
@ Output
An output workspace.
Definition: Property.h:54