Mantid
Loading...
Searching...
No Matches
ProcessIndirectFitParameters.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
12#include "MantidAPI/TableRow.h"
13#include "MantidAPI/TextAxis.h"
14
20
21#include <boost/algorithm/string/predicate.hpp>
22#include <utility>
23
24namespace {
25using namespace Mantid::API;
26
27template <typename T, typename... Ts> std::vector<T, Ts...> repeat(std::vector<T, Ts...> const &vec, std::size_t n) {
28 std::vector<T, Ts...> result;
29 result.reserve(vec.size() * n);
30 for (; n > 0; --n)
31 result.insert(result.end(), vec.begin(), vec.end());
32 return result;
33}
34
35template <typename T> std::vector<T> getIncrementingSequence(const T &from, std::size_t length) {
36 std::vector<T> sequence(length);
37 std::iota(sequence.begin(), sequence.end(), from);
38 return sequence;
39}
40
41std::vector<std::string> appendSuffix(std::vector<std::string> const &vec, std::string const &suffix) {
42 std::vector<std::string> appended;
43 appended.reserve(vec.size());
44 std::transform(vec.cbegin(), vec.cend(), std::back_inserter(appended),
45 [&suffix](auto &&str) { return str + suffix; });
46 return appended;
47}
48
49MatrixWorkspace_sptr createWorkspace(std::vector<double> const &x, std::vector<double> const &y,
50 std::vector<double> const &e, int numberOfSpectra,
51 std::vector<std::string> const &verticalAxisNames, std::string const &unitX) {
52 auto createWorkspaceAlgorithm = AlgorithmManager::Instance().createUnmanaged("CreateWorkspace");
53 createWorkspaceAlgorithm->initialize();
54 createWorkspaceAlgorithm->setChild(true);
55 createWorkspaceAlgorithm->setLogging(false);
56 createWorkspaceAlgorithm->setProperty("DataX", x);
57 createWorkspaceAlgorithm->setProperty("DataY", y);
58 createWorkspaceAlgorithm->setProperty("DataE", e);
59 createWorkspaceAlgorithm->setProperty("NSpec", numberOfSpectra);
60 createWorkspaceAlgorithm->setProperty("VerticalAxisUnit", "Text");
61 createWorkspaceAlgorithm->setProperty("VerticalAxisValues", verticalAxisNames);
62 createWorkspaceAlgorithm->setProperty("UnitX", unitX);
63 createWorkspaceAlgorithm->setProperty("OutputWorkspace", "__created");
64 createWorkspaceAlgorithm->execute();
65 return createWorkspaceAlgorithm->getProperty("OutputWorkspace");
66}
67
68template <typename T, typename OutputIterator>
69void extractColumnValues(Column const &column, std::size_t startRow, std::size_t endRow, OutputIterator outputIt) {
70 for (auto i = startRow; i <= endRow; ++i)
71 *outputIt++ = column.cell<T>(i);
72}
73
74template <typename T, typename OutputIterator>
75void extractValuesFromColumns(std::size_t startRow, std::size_t endRow, const std::vector<Column_const_sptr> &columns,
76 OutputIterator outputIt) {
77 for (auto &&column : columns)
78 extractColumnValues<T>(*column, startRow, endRow, outputIt);
79}
80
81template <typename T> std::vector<T> getColumnValues(Column const &column, std::size_t startRow, std::size_t endRow) {
82 std::vector<T> values;
83 values.reserve(1 + (endRow - startRow));
84 extractColumnValues<T>(column, startRow, endRow, std::back_inserter(values));
85 return values;
86}
87
88std::vector<double> getNumericColumnValuesOrIndices(Column const &column, std::size_t startRow, std::size_t endRow) {
89 auto const length = startRow > endRow ? 0 : 1 + endRow - startRow;
90 if (column.isNumber())
91 return getColumnValues<double>(column, startRow, endRow);
92 return getIncrementingSequence(0.0, length);
93}
94
95std::string getColumnName(const Column_const_sptr &column) { return column->name(); }
96
97std::vector<std::string> extractColumnNames(std::vector<Column_const_sptr> const &columns) {
98 std::vector<std::string> names;
99 names.reserve(columns.size());
100 std::transform(columns.begin(), columns.end(), std::back_inserter(names), getColumnName);
101 return names;
102}
103
104template <typename ColumnFilter>
105std::vector<Column_const_sptr> extractColumns(ITableWorkspace const *table, ColumnFilter const &filter) {
106 std::vector<Column_const_sptr> columns;
107 for (auto i = 0u; i < table->columnCount(); ++i) {
108 auto const column = table->getColumn(i);
109 if (filter(*column))
110 columns.emplace_back(column);
111 }
112 return columns;
113}
114
115struct TableToMatrixWorkspaceConverter {
116 template <typename YFilter, typename EFilter>
117 TableToMatrixWorkspaceConverter(ITableWorkspace const *table, std::vector<double> x, YFilter const &yFilter,
118 EFilter const &eFilter)
119 : m_x(std::move(x)), m_yColumns(extractColumns(table, yFilter)), m_eColumns(extractColumns(table, eFilter)),
120 m_yAxis(extractColumnNames(m_yColumns)) {}
121
122 MatrixWorkspace_sptr operator()(std::size_t startRow, std::size_t endRow, std::string const &unitX,
123 bool includeChiSquared) const {
124 auto const x = repeat(m_x, m_yColumns.size());
125
126 std::vector<double> y;
127 std::vector<double> e;
128 y.reserve(x.size());
129 e.reserve(x.size());
130 extractValuesFromColumns<double>(startRow, endRow, m_yColumns, std::back_inserter(y));
131 extractValuesFromColumns<double>(startRow, endRow, m_eColumns, std::back_inserter(e));
132
133 if (includeChiSquared)
134 std::fill_n(std::back_inserter(e), y.size() - e.size(), 0.0);
135
136 return createWorkspace(x, y, e, static_cast<int>(m_yColumns.size()), m_yAxis, unitX);
137 }
138
139private:
140 std::vector<double> const m_x;
141 std::vector<Column_const_sptr> const m_yColumns;
142 std::vector<Column_const_sptr> const m_eColumns;
143 std::vector<std::string> const m_yAxis;
144};
145
146struct EndsWithOneOf {
147 explicit EndsWithOneOf(std::vector<std::string> &&strings) : m_strings(std::move(strings)) {}
148
149 bool operator()(std::string const &value) const {
150 for (auto &&str : m_strings) {
151 if (boost::algorithm::ends_with(value, str))
152 return true;
153 }
154 return false;
155 }
156
157private:
158 std::vector<std::string> const m_strings;
159};
160
161template <typename StringFilter> struct ColumnNameFilter {
162public:
163 explicit ColumnNameFilter(StringFilter &&filter) : m_filter(std::forward<StringFilter>(filter)) {}
164
165 bool operator()(Column const &column) const { return m_filter(column.name()); }
166
167private:
168 StringFilter const m_filter;
169};
170
171template <typename StringFilter> ColumnNameFilter<StringFilter> makeColumnNameFilter(StringFilter &&filter) {
172 return ColumnNameFilter<StringFilter>(std::forward<StringFilter>(filter));
173}
174} // namespace
175
176namespace Mantid::Algorithms {
177
178using namespace API;
179using namespace Kernel;
180
181// Register the algorithm into the AlgorithmFactory
182DECLARE_ALGORITHM(ProcessIndirectFitParameters)
183
184//----------------------------------------------------------------------------------------------
185
186
187const std::string ProcessIndirectFitParameters::name() const { return "ProcessIndirectFitParameters"; }
188
191
193const std::string ProcessIndirectFitParameters::category() const { return "Workflow\\MIDAS"; }
194
196const std::string ProcessIndirectFitParameters::summary() const {
197 return "Convert a parameter table output by PlotPeakByLogValue to a "
198 "MatrixWorkspace.";
199}
200
201//----------------------------------------------------------------------------------------------
205
206 std::vector<std::string> unitOptions = UnitFactory::Instance().getKeys();
207 unitOptions.emplace_back("");
208
209 declareProperty(std::make_unique<WorkspaceProperty<ITableWorkspace>>("InputWorkspace", "", Direction::Input),
210 "The table workspace to convert to a MatrixWorkspace.");
211
212 declareProperty("ColumnX", "", std::make_shared<MandatoryValidator<std::string>>(),
213 "The column in the table to use for the x values.", Direction::Input);
214
216 "ParameterNames", std::make_shared<MandatoryValidator<std::vector<std::string>>>()),
217 "List of the parameter names to add to the workspace.");
218
219 declareProperty("IncludeChiSquared", false, "Add Chi-squared to the output workspace.");
220
221 declareProperty("XAxisUnit", "", std::make_shared<StringListValidator>(unitOptions),
222 "The unit to assign to the X Axis");
223
224 auto positiveInt = std::make_shared<Kernel::BoundedValidator<int>>();
225 positiveInt->setLower(0);
226 declareProperty("StartRowIndex", EMPTY_INT(), positiveInt,
227 "The start row index to include in the output matrix workspace.");
228 declareProperty("EndRowIndex", EMPTY_INT(), positiveInt,
229 "The end row index to include in the output matrix workspace.");
230
231 declareProperty(std::make_unique<WorkspaceProperty<MatrixWorkspace>>("OutputWorkspace", "", Direction::Output),
232 "The name to give the output workspace");
233}
234
235//----------------------------------------------------------------------------------------------
239 ITableWorkspace_sptr const inputWs = getProperty("InputWorkspace");
240 std::string xColumn = getProperty("ColumnX");
241 std::string const xUnit = getProperty("XAxisUnit");
242 bool const includeChiSquared = getProperty("IncludeChiSquared");
243 std::vector<std::string> parameterNames = getProperty("ParameterNames");
244 std::vector<std::string> errorNames = appendSuffix(parameterNames, "_Err");
245 auto const startRow = getStartRow();
246 auto const endRow = getEndRow(inputWs->rowCount() - 1);
247
248 if (includeChiSquared)
249 parameterNames.emplace_back("Chi_squared");
250
251 auto const x = getNumericColumnValuesOrIndices(*inputWs->getColumn(xColumn), startRow, endRow);
252 auto const yFilter = makeColumnNameFilter(EndsWithOneOf(std::move(parameterNames)));
253 auto const eFilter = makeColumnNameFilter(EndsWithOneOf(std::move(errorNames)));
254
255 TableToMatrixWorkspaceConverter converter(inputWs.get(), x, yFilter, eFilter);
256 auto const output = converter(startRow, endRow, xUnit, includeChiSquared);
257 setProperty("OutputWorkspace", output);
258}
259
261 int startRow = getProperty("StartRowIndex");
262 return startRow == EMPTY_INT() ? 0 : static_cast<std::size_t>(startRow);
263}
264
265std::size_t ProcessIndirectFitParameters::getEndRow(std::size_t maximum) const {
266 int endRow = getProperty("EndRowIndex");
267 return endRow == EMPTY_INT() ? maximum : static_cast<std::size_t>(endRow);
268}
269
270} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
double value
The value of the point.
Definition: FitMW.cpp:51
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
Column is the base class for columns of TableWorkspace.
Definition: Column.h:35
T & cell(size_t index)
Templated method for returning a value. No type checks are done.
Definition: Column.h:127
virtual bool isNumber() const =0
Are elements of the column interpretable as a number?
const std::string & name() const
Name (caption) of the column.
Definition: Column.h:43
ITableWorkspace is an implementation of Workspace in which the data are organised in columns of same ...
virtual Column_sptr getColumn(const std::string &name)=0
Gets the shared pointer to a column by name.
virtual size_t columnCount() const =0
Number of columns in the workspace.
A property class for workspaces.
ProcessIndirectFitParameters : Convert a parameter table output by PlotPeakByLogValue to a MatrixWork...
void init() override
Initialize the algorithm's properties.
const std::string summary() const override
Algorithm's summary for use in the GUI and help.
const std::string category() const override
Algorithm's category for identification.
int version() const override
Algorithm's version for identification.
Support for a property that holds an array of values.
Definition: ArrayProperty.h:28
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
Validator to check that a property is not left empty.
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< T > createWorkspace(InitArgs... args)
std::shared_ptr< const Column > Column_const_sptr
Definition: Column.h:229
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
constexpr int EMPTY_INT() noexcept
Returns what we consider an "empty" integer within a property.
Definition: EmptyValues.h:25
STL namespace.
@ Input
An input workspace.
Definition: Property.h:53
@ Output
An output workspace.
Definition: Property.h:54