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