Mantid
Loading...
Searching...
No Matches
CreateUserDefinedBackground.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 +
8#include "MantidAPI/Axis.h"
11#include "MantidAPI/TableRow.h"
14#include "MantidKernel/Unit.h"
15
16#include <algorithm>
17
18namespace Mantid::Algorithms {
19
20// Key for the "normalize data to bin width" plot option
21const std::string CreateUserDefinedBackground::AUTODISTRIBUTIONKEY = "graph1d.autodistribution";
22
24using Mantid::HistogramData::Frequencies;
25using Mantid::HistogramData::FrequencyStandardDeviations;
26using Mantid::HistogramData::Histogram;
28
29// Register the algorithm into the AlgorithmFactory
30DECLARE_ALGORITHM(CreateUserDefinedBackground)
31
32//----------------------------------------------------------------------------------------------
33
34
35const std::string CreateUserDefinedBackground::name() const { return "CreateUserDefinedBackground"; }
36
38int CreateUserDefinedBackground::version() const { return 1; }
39
41const std::string CreateUserDefinedBackground::category() const { return "CorrectionFunctions\\BackgroundCorrections"; }
42
44const std::string CreateUserDefinedBackground::summary() const {
45 return "Creates a workspace of background data from a user-supplied set of "
46 "points. This workspace can then be subtracted from the original "
47 "data.";
48}
49
50//----------------------------------------------------------------------------------------------
55 declareProperty(std::make_unique<WorkspaceProperty<API::MatrixWorkspace>>("InputWorkspace", "", Direction::Input),
56 "Input workspace containing data and background");
57 declareProperty(std::make_unique<WorkspaceProperty<API::ITableWorkspace>>("BackgroundPoints", "", Direction::Input),
58 "Table containing user-defined background points");
60 std::make_unique<WorkspaceProperty<API::MatrixWorkspace>>("OutputBackgroundWorkspace", "", Direction::Output),
61 "Workspace containing background to be subtracted");
62}
63
64//----------------------------------------------------------------------------------------------
69 const API::MatrixWorkspace_const_sptr inputWS = getProperty("InputWorkspace");
70 API::ITableWorkspace_sptr pointsTable = getProperty("BackgroundPoints");
71
72 // Clean up input points table and extend to range of data
73 cleanUpTable(pointsTable);
74 extendBackgroundToData(pointsTable, inputWS);
75
76 // Generate output workspace with background data
77 const auto outputWS = createBackgroundWorkspace(pointsTable, inputWS);
78
79 setProperty("OutputBackgroundWorkspace", API::MatrixWorkspace_sptr(outputWS));
80}
81
89 // Delete blank (zero) rows at the end of the table
90 std::vector<size_t> blankRows;
91 const auto isZero = [](const double n) { return !(fabs(n) > std::numeric_limits<double>::epsilon()); };
92 for (size_t i = table->rowCount() - 1; i > 0; i--) {
93 double x, y;
94 API::TableRow row = table->getRow(i);
95 row >> x >> y;
96 if (!isZero(x)) {
97 break;
98 } else if (isZero(y)) {
99 blankRows.emplace_back(i);
100 }
101 }
102 for (const auto &row : blankRows) {
103 table->removeRow(row);
104 }
105
106 // Sort the table
107 std::vector<std::pair<std::string, bool>> sortArgs;
108 sortArgs.emplace_back(table->getColumn(0)->name(), true);
109 table->sort(sortArgs);
110}
111
119 const API::MatrixWorkspace_const_sptr &data) const {
120 const auto &xPoints = data->points(0);
121
122 // If first point > data minimum, insert a new first point
123 if (background->Double(0, 0) > xPoints[0]) {
124 background->insertRow(0);
125 API::TableRow firstRow = background->getFirstRow();
126 firstRow << xPoints.front() << background->Double(0, 1);
127 }
128 // If last point < data maximum, append a new last point
129 const size_t endIndex = background->rowCount() - 1;
130 if (background->Double(endIndex, 0) < xPoints.back()) {
131 API::TableRow lastRow = background->appendRow();
132 lastRow << xPoints.back() << background->Double(endIndex, 1);
133 }
134}
135
146 const API::MatrixWorkspace_const_sptr &data) const {
147 auto outputWS = data->clone();
148
149 const auto &xPoints = outputWS->points(0);
150 const auto &xBinEdges = outputWS->binEdges(0);
151 std::vector<double> yBackground;
152 std::vector<double> eBackground(xPoints.size(), 0);
153
154 // Interpolate Y data in the table to get y for each point
155 const auto &lerp = getInterpolator(background, data);
156 for (const auto &x : xPoints) {
157 const double y = lerp.value(x);
158 yBackground.emplace_back(y);
159 }
160
161 auto histogram = outputWS->histogram(0);
162 if (histogram.yMode() == Histogram::YMode::Frequencies) {
163 histogram.setFrequencies(yBackground);
164 histogram.setFrequencyStandardDeviations(eBackground);
165 } else {
166 if (data->isHistogramData() &&
167 Kernel::ConfigService::Instance().getValue<bool>(AUTODISTRIBUTIONKEY).value_or(false)) {
168 // Background data is actually frequencies, we put it into temporary to
169 // benefit from automatic conversion in setCounts(), etc.
170 histogram.setCounts(Frequencies(yBackground), xBinEdges);
171 histogram.setCountStandardDeviations(FrequencyStandardDeviations(eBackground), xBinEdges);
172 } else {
173 histogram.setCounts(yBackground);
174 histogram.setCountStandardDeviations(eBackground);
175 }
176 }
177
178 // Apply Y and E data to all spectra in the workspace
179 for (size_t spec = 0; spec < outputWS->getNumberHistograms(); spec++) {
180 // Setting same histogram for all spectra, data is shared, saving memory
181 outputWS->setHistogram(spec, histogram);
182 }
183
184 return API::MatrixWorkspace_sptr(std::move(outputWS));
185}
186
197 lerp.setMethod("linear");
198 lerp.setXUnit(workspace->getAxis(0)->unit()->unitID());
199 lerp.setYUnit(workspace->getAxis(1)->unit()->unitID());
200
201 // Set up data from table
202 const auto xColumn = background->getColumn(0);
203 const auto yColumn = background->getColumn(1);
204 for (size_t i = 0; i < background->rowCount(); i++) {
205 double x = xColumn->cell<double>(i);
206 double y = yColumn->cell<double>(i);
207 lerp.addPoint(x, y);
208 }
209 return lerp;
210}
211
220std::map<std::string, std::string> CreateUserDefinedBackground::validateInputs() {
221 std::map<std::string, std::string> errors;
222
223 const static std::string pointsProp = "BackgroundPoints", inputProp = "InputWorkspace";
224 const API::ITableWorkspace_const_sptr pointsTable = getProperty(pointsProp);
225 if (pointsTable) {
226 if (pointsTable->columnCount() != 2) {
227 errors[pointsProp] = "Table of points must have two columns (X, Y)";
228 }
229 for (size_t col = 0; col < pointsTable->columnCount(); col++) {
230 const std::string colType = pointsTable->getColumn(col)->type();
231 if (colType != "double" && colType != "int") {
232 errors[pointsProp] = "Table of points must have numeric columns";
233 }
234 }
235 if (pointsTable->rowCount() < 2) {
236 errors[pointsProp] = "Table of points must contain at least two points";
237 }
238 }
239
240 const API::MatrixWorkspace_const_sptr inputWS = getProperty(inputProp);
241 if (inputWS) {
242 if (inputWS->getNumberHistograms() == 0 || inputWS->blocksize() < 2) {
243 errors[inputProp] = "Input workspace must contain some data";
244 }
245 if (!inputWS->isCommonBins()) {
246 errors[inputProp] = "Input workspace must have common bins";
247 }
248 }
249
250 return errors;
251}
252
253} // namespace Mantid::Algorithms
std::string name
Definition Run.cpp:60
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:547
double background
IPeaksWorkspace_sptr workspace
#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.
TableRow represents a row in a TableWorkspace.
Definition TableRow.h:39
double & Double(size_t col)
Returns a reference to the element in position col if its type is double.
Definition TableRow.h:137
A property class for workspaces.
CreateUserDefinedBackground : Given an input workspace containing data with a background and a table ...
void init() override
Declare properties and initialise algorithm.
API::MatrixWorkspace_sptr createBackgroundWorkspace(const API::ITableWorkspace_const_sptr &background, const API::MatrixWorkspace_const_sptr &data) const
Create new background workspace with data interpolated from table.
const std::string category() const override
Category algorithm belongs to.
static const std::string AUTODISTRIBUTIONKEY
Key name for "normalize histogram to bin width" option on plots.
void cleanUpTable(API::ITableWorkspace_sptr &table) const
Sort table and remove blank rows.
void extendBackgroundToData(API::ITableWorkspace_sptr &background, const API::MatrixWorkspace_const_sptr &data) const
Extend background to cover range of data.
std::map< std::string, std::string > validateInputs() override
Verify input properties and return errors.
const std::string summary() const override
Description of algorithm.
Kernel::Interpolation getInterpolator(const API::ITableWorkspace_const_sptr &background, const API::MatrixWorkspace_const_sptr &workspace) const
Set up and return an interpolator object ready for use.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
Provide interpolation over a series of points.
void setMethod(const std::string &method)
set interpolation method
void setXUnit(const std::string &unit)
set x-axis unit
void setYUnit(const std::string &unit)
set y-axis unit
void addPoint(const double &xx, const double &yy)
add data point
std::shared_ptr< ITableWorkspace > ITableWorkspace_sptr
shared pointer to Mantid::API::ITableWorkspace
std::shared_ptr< const ITableWorkspace > ITableWorkspace_const_sptr
shared pointer to Mantid::API::ITableWorkspace (const version)
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
STL namespace.
Describes the direction (within an algorithm) of a Property.
Definition Property.h:51
@ Input
An input workspace.
Definition Property.h:54
@ Output
An output workspace.
Definition Property.h:55