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