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 auto &XValues_old = inputW->x(0);
66 std::vector<int> xoldIndex; // indeces of new x in XValues_old
67 // create new output X axis
68 std::vector<double> xAxisTmp;
69 int ntcnew = newAxis(rb_params, XValues_old.rawData(), xAxisTmp, xoldIndex);
70 HistogramData::BinEdges XValues_new(std::move(xAxisTmp));
71
72 // make output Workspace the same type is the input, but with new length of
73 // signal array
74 API::MatrixWorkspace_sptr outputW = API::WorkspaceFactory::Instance().create(inputW, histnumber, ntcnew, ntcnew - 1);
75
76 int progress_step = histnumber / 100;
77 if (progress_step == 0)
78 progress_step = 1;
79 for (int hist = 0; hist < histnumber; hist++) {
80 // get const references to input Workspace arrays (no copying)
81 auto &XValues = inputW->x(hist);
82 auto &YValues = inputW->y(hist);
83 auto &YErrors = inputW->e(hist);
84
85 // get references to output workspace data (no copying)
86 auto &YValues_new = outputW->mutableY(hist);
87 auto &YErrors_new = outputW->mutableE(hist);
88
89 // output data arrays are implicitly filled by function
90 rebin(XValues, YValues, YErrors, xoldIndex, YValues_new, YErrors_new, dist);
91
92 outputW->setBinEdges(hist, XValues_new);
93
94 if (hist % progress_step == 0) {
95 progress(double(hist) / histnumber);
97 }
98 }
99
100 outputW->setDistribution(dist);
101
102 // Copy units
103 if (outputW->getAxis(0)->unit().get())
104 outputW->getAxis(0)->unit() = inputW->getAxis(0)->unit();
105 try {
106 if (inputW->getAxis(1)->unit().get())
107 outputW->getAxis(1)->unit() = inputW->getAxis(1)->unit();
108 } catch (Exception::IndexError &) {
109 // OK, so this isn't a Workspace2D
110 }
111
112 // Assign it to the output workspace property
113 setProperty("OutputWorkspace", outputW);
114}
115
128void Regroup::rebin(const HistogramX &xold, const HistogramY &yold, const HistogramE &eold,
129 const std::vector<int> &xoldIndex, HistogramY &ynew, HistogramE &enew, bool distribution) {
130
131 for (int i = 0; i < int(xoldIndex.size() - 1); i++) {
132
133 int n = xoldIndex[i]; // start the group
134 int m = xoldIndex[i + 1]; // end the group
135 double width = xold[m] - xold[n]; // width of the group
136
137 if (width == 0.) {
138 g_log.error("Zero bin width");
139 throw std::runtime_error("Zero bin width");
140 }
141 /*
142 * yold contains counts/unit time, ynew contains counts
143 * enew contains counts**2
144 */
145 if (distribution) {
146 ynew[i] = 0.;
147 enew[i] = 0.;
148 for (int j = n; j < m; j++) {
149 double wdt = xold[j + 1] - xold[j]; // old bin width
150 ynew[i] += yold[j] * wdt;
151 enew[i] += eold[j] * eold[j] * wdt * wdt;
152 }
153 ynew[i] /= width;
154 enew[i] = sqrt(enew[i]) / width;
155 } else // yold,eold data is not distribution but counts
156 {
157 ynew[i] = 0.;
158 enew[i] = 0.;
159 for (int j = n; j < m; j++) {
160 ynew[i] += yold[j];
161 enew[i] += eold[j] * eold[j];
162 }
163 enew[i] = sqrt(enew[i]);
164 }
165 }
166}
167
177int Regroup::newAxis(const std::vector<double> &params, const std::vector<double> &xold, std::vector<double> &xnew,
178 std::vector<int> &xoldIndex) {
179 double xcurr, xs;
180 int ibound(2), istep(1), inew(0);
181 auto ibounds = static_cast<int>(params.size()); // highest index in params array containing a bin boundary
182 int isteps = ibounds - 1; // highest index in params array containing a step
183
184 xcurr = params[0];
185 using std::placeholders::_1;
186 auto iup = std::find_if(xold.cbegin(), xold.cend(), std::bind(std::greater_equal<double>(), _1, xcurr));
187 if (iup != xold.end()) {
188 xcurr = *iup;
189 xnew.emplace_back(xcurr);
190 xoldIndex.emplace_back(inew);
191 inew++;
192 } else
193 return 0;
194
195 while ((ibound <= ibounds) && (istep <= isteps)) {
196 // if step is negative then it is logarithmic step
197 if (params[istep] >= 0.0)
198 xs = params[istep];
199 else
200 xs = xcurr * fabs(params[istep]);
201
202 // xcurr += xs;
203
204 // find nearest x_i that is >= xcurr
205 iup = std::find_if(xold.begin(), xold.end(), std::bind(std::greater_equal<double>(), _1, xcurr + xs));
206 if (iup != xold.end()) {
207 if (*iup <= params[ibound]) {
208 xcurr = *iup;
209 xnew.emplace_back(xcurr);
210 xoldIndex.emplace_back(inew);
211 inew++;
212 } else {
213 ibound += 2;
214 istep += 2;
215 }
216 } else
217 return inew;
218 }
219 // returns length of new x array or -1 if failure
220 return inew;
221 // return( (ibound == ibounds) && (istep == isteps) ? inew : -1 );
222}
223
224} // namespace Algorithms
225} // namespace Mantid
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:538
#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.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Kernel::Logger & g_log
Definition Algorithm.h:422
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
void interruption_point()
This is called during long-running operations, and check if the algorithm has requested that it be ca...
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:128
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:177
Support for a property that holds an array of values.
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:108
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