Mantid
Loading...
Searching...
No Matches
PerformIndexOperations.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 +
11#include <boost/algorithm/string.hpp>
12#include <boost/regex.hpp>
13#include <utility>
14
15using namespace Mantid::Kernel;
16using namespace Mantid::API;
17
18namespace {
23class Command {
24public:
25 virtual bool isValid() const { return true; }
26
27 virtual MatrixWorkspace_sptr execute(MatrixWorkspace_sptr input) const = 0;
28
29 virtual MatrixWorkspace_sptr executeAndAppend(MatrixWorkspace_sptr inputWS, MatrixWorkspace_sptr toAppend) const {
30 if (!this->isValid()) {
31 return toAppend;
32 } else {
33 MatrixWorkspace_sptr current = this->execute(std::move(inputWS));
35 auto conjoinWorkspaceAlg = factory.create("ConjoinWorkspaces");
36 conjoinWorkspaceAlg->setChild(true);
37 conjoinWorkspaceAlg->initialize();
38 conjoinWorkspaceAlg->setProperty("InputWorkspace1", toAppend);
39 conjoinWorkspaceAlg->setProperty("InputWorkspace2", current);
40 conjoinWorkspaceAlg->execute();
41 MatrixWorkspace_sptr outWS = conjoinWorkspaceAlg->getProperty("InputWorkspace1");
42 return outWS;
43 }
44 }
45
46 virtual ~Command() = default;
47};
48
50using VecCommands = std::vector<std::shared_ptr<Command>>;
51
55class NullCommand : public Command {
56 bool isValid() const override { return false; }
57 MatrixWorkspace_sptr execute(MatrixWorkspace_sptr /*input*/) const override {
58 throw std::runtime_error("Should not be attempting ::execute on a NullCommand");
59 }
60};
61
65class AdditionCommand : public Command {
66private:
67 std::vector<int> m_indexes;
68
69public:
70 explicit AdditionCommand(std::vector<int> indexes) : m_indexes(std::move(indexes)) {}
71
72 MatrixWorkspace_sptr execute(MatrixWorkspace_sptr inputWS) const override {
74 if (!m_indexes.empty()) {
76 auto sumSpectraAlg = factory.create("SumSpectra");
77 sumSpectraAlg->setChild(true);
78 sumSpectraAlg->initialize();
79 sumSpectraAlg->setProperty("InputWorkspace", inputWS);
80 sumSpectraAlg->setProperty("ListOfWorkspaceIndices", m_indexes);
81 sumSpectraAlg->setPropertyValue("OutputWorkspace", "outWS");
82 sumSpectraAlg->execute();
83 outWS = sumSpectraAlg->getProperty("OutputWorkspace");
84 }
85 return outWS;
86 }
87};
88
92class CropCommand : public Command {
93private:
94 std::vector<int> m_indexes;
95
96public:
97 explicit CropCommand(std::vector<int> indexes) : m_indexes(std::move(indexes)) {}
98
99 MatrixWorkspace_sptr execute(MatrixWorkspace_sptr inputWS) const override {
100
102 for (size_t i = 0; i < m_indexes.size(); ++i) {
104 auto cropWorkspaceAlg = factory.create("CropWorkspace");
105 cropWorkspaceAlg->setChild(true);
106 cropWorkspaceAlg->initialize();
107 cropWorkspaceAlg->setProperty("InputWorkspace", inputWS);
108 cropWorkspaceAlg->setProperty("StartWorkspaceIndex", m_indexes[i]);
109 cropWorkspaceAlg->setProperty("EndWorkspaceIndex", m_indexes[i]);
110 cropWorkspaceAlg->setPropertyValue("OutputWorkspace", "outWS");
111 cropWorkspaceAlg->execute();
112 MatrixWorkspace_sptr subRange = cropWorkspaceAlg->getProperty("OutputWorkspace");
113 if (i == 0) {
114 outWS = subRange;
115 } else {
116 auto conjoinWorkspaceAlg = factory.create("ConjoinWorkspaces");
117 conjoinWorkspaceAlg->setChild(true);
118 conjoinWorkspaceAlg->initialize();
119 conjoinWorkspaceAlg->setProperty("InputWorkspace1", outWS);
120 conjoinWorkspaceAlg->setProperty("InputWorkspace2", subRange);
121 conjoinWorkspaceAlg->execute();
122 outWS = conjoinWorkspaceAlg->getProperty("InputWorkspace1");
123 }
124 }
125 return outWS;
126 }
127};
128
132class CommandParser {
133public:
134 virtual Command *interpret(const std::string &instruction) const = 0;
135
136 virtual ~CommandParser() = default;
137};
138
140using VecCommandParsers = std::vector<std::shared_ptr<CommandParser>>;
141
145template <typename ProductType> class CommandParserBase : public CommandParser {
146public:
147 Command *interpret(const std::string &instruction) const override {
148 Command *command = nullptr;
149 boost::regex ex = getRegex();
150 if (boost::regex_match(instruction, ex)) {
151 auto indexes = Mantid::Kernel::Strings::parseRange(instruction, ",", getSeparator());
152 command = new ProductType(indexes);
153 } else {
154 command = new NullCommand;
155 }
156 return command;
157 }
158
159private:
160 virtual std::string getSeparator() const = 0;
161 virtual boost::regex getRegex() const = 0;
162};
163
167class AdditionParserRange : public CommandParserBase<AdditionCommand> {
168public:
169private:
170 boost::regex getRegex() const override {
171 static const boost::regex r(R"(^\s*[0-9]+\s*\-\s*[0-9]+\s*$)");
172 return r;
173 }
174 std::string getSeparator() const override { return "-"; }
175};
176
180class AdditionParser : public CommandParser {
181public:
182 Command *interpret(const std::string &instruction) const override {
183 Command *command = nullptr;
184 static const boost::regex ex(R"(^\s*[0-9]+\s*\+\s*[0-9]+\s*$)");
185 if (boost::regex_match(instruction, ex)) {
186 std::vector<std::string> arguments;
187 boost::split(arguments, instruction, boost::is_any_of("+"));
188 int minIndex = -1;
189 int maxIndex = -1;
190 Mantid::Kernel::Strings::convert<int>(arguments.front(), minIndex);
191 Mantid::Kernel::Strings::convert<int>(arguments.back(), maxIndex);
192 std::vector<int> indexes;
193 indexes.emplace_back(minIndex);
194 indexes.emplace_back(maxIndex);
195 command = new AdditionCommand(indexes);
196 } else {
197 command = new NullCommand;
198 }
199 return command;
200 }
201};
202
206class CropParserRange : public CommandParserBase<CropCommand> {
207public:
208private:
209 boost::regex getRegex() const override {
210 static const boost::regex r(R"(^\s*[0-9]+\s*:\s*[0-9]+\s*$)");
211 return r;
212 }
213 std::string getSeparator() const override { return ":"; }
214};
215
219class CropParserIndex : public CommandParser {
220public:
221 Command *interpret(const std::string &instruction) const override {
222 Command *command = nullptr;
223 static const boost::regex ex("^\\s*[0-9]+\\s*$");
224 if (boost::regex_match(instruction, ex)) {
225 int index = -1;
226 Mantid::Kernel::Strings::convert<int>(instruction, index);
227 std::vector<int> indexes(1, index);
228 command = new CropCommand(indexes);
229 } else {
230 command = new NullCommand;
231 }
232 return command;
233 }
234};
235} // namespace
236
237namespace Mantid::Algorithms {
238
239// Register the algorithm into the AlgorithmFactory
240DECLARE_ALGORITHM(PerformIndexOperations)
241
242//------------------------------------------------------------------------------
244const std::string PerformIndexOperations::name() const { return "PerformIndexOperations"; }
245
247int PerformIndexOperations::version() const { return 1; }
248
250const std::string PerformIndexOperations::category() const { return "Transforms\\Grouping"; }
251
252//------------------------------------------------------------------------------
253
254//------------------------------------------------------------------------------
258 declareProperty(std::make_unique<WorkspaceProperty<MatrixWorkspace>>("InputWorkspace", "", Direction::Input),
259 "Input to processes workspace.");
260 declareProperty(std::make_unique<PropertyWithValue<std::string>>("ProcessingInstructions", "", Direction::Input),
261 "Processing instructions. See full instruction list.");
262 declareProperty(std::make_unique<WorkspaceProperty<MatrixWorkspace>>("OutputWorkspace", "", Direction::Output),
263 "Output processed workspace");
264}
265
274VecCommands interpret(const std::string &processingInstructions) {
275 std::vector<std::string> processingInstructionsSplit;
276 boost::split(processingInstructionsSplit, processingInstructions, boost::is_any_of(","));
277
278 VecCommandParsers commandParsers{std::make_shared<AdditionParserRange>(), std::make_shared<CropParserRange>(),
279 std::make_shared<CropParserIndex>(), std::make_shared<AdditionParser>()};
280
281 VecCommands commands;
282 for (const auto &candidate : processingInstructionsSplit) {
283 bool parserFound = false;
284 for (const auto &commandParser : commandParsers) {
285 Command *command = commandParser->interpret(candidate);
286 std::shared_ptr<Command> commandSptr(command);
287 if (commandSptr->isValid()) // Do not record invalid commands.
288 {
289 parserFound = true;
290 commands.emplace_back(commandSptr);
291 }
292 }
293 if (!parserFound) {
294 throw std::invalid_argument("Cannot interpret " + candidate);
295 }
296 }
297 return commands;
298}
299
300//------------------------------------------------------------------------------
304 MatrixWorkspace_sptr inputWorkspace = this->getProperty("InputWorkspace");
305 const std::string processingInstructions = this->getProperty("ProcessingInstructions");
306
307 boost::regex re(R"(^\s*[0-9]+\s*$|^(\s*,*[0-9]+(\s*(,|:|\+|\-)\s*)*[0-9]*)*$)");
308 if (!boost::regex_match(processingInstructions, re)) {
309 throw std::invalid_argument("ProcessingInstructions are not well formed: " + processingInstructions);
310 }
311
312 if (processingInstructions.empty()) {
313 auto cloneWS = this->createChildAlgorithm("CloneWorkspace");
314 cloneWS->initialize();
315 cloneWS->setProperty("InputWorkspace", inputWorkspace);
316 cloneWS->execute();
317 Workspace_sptr tmp = cloneWS->getProperty("OutputWorkspace");
318 MatrixWorkspace_sptr outWS = std::dynamic_pointer_cast<MatrixWorkspace>(tmp);
319 this->setProperty("OutputWorkspace", outWS);
320 } else {
321 // Interpret the instructions.
322 VecCommands commands = interpret(processingInstructions);
323
324 // Execute the commands.
325 auto command = commands[0];
326 MatrixWorkspace_sptr outWS = command->execute(inputWorkspace);
327 for (size_t j = 1; j < commands.size(); ++j) {
328 outWS = commands[j]->executeAndAppend(inputWorkspace, outWS);
329 }
330
331 this->setProperty("OutputWorkspace", outWS);
332 }
333}
334
335} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
gsl_vector * tmp
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
The AlgorithmManagerImpl class is responsible for controlling algorithm instances.
IAlgorithm_sptr create(const std::string &algName, const int &version=-1)
Creates a managed algorithm with the option of choosing a version.
std::shared_ptr< Algorithm > createChildAlgorithm(const std::string &name, const double startProgress=-1., const double endProgress=-1., const bool enableLogging=true, const int &version=-1) override
Create a Child Algorithm.
Kernel::IPropertyManager::TypedValue getProperty(const std::string &name) const override
Get the property held by this object.
A property class for workspaces.
PerformIndexOperations : Crop and sum a workspace according to the parsed workspace index operations ...
void init() override
Initialize the algorithm's properties.
int version() const override
Algorithm's version for identification.
void exec() override
Execute the algorithm.
const std::string category() const override
Algorithm's category for identification.
The concrete, templated class for properties.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
Definition: Workspace_fwd.h:20
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
VecCommands interpret(const std::string &processingInstructions)
Interpret the instructions as an ordered list of commands that can be executed later.
MANTID_KERNEL_DLL std::vector< int > parseRange(const std::string &str, const std::string &elemSep=",", const std::string &rangeSep="-")
Parses a number range, e.g.
Definition: Strings.cpp:1071
STL namespace.
@ Input
An input workspace.
Definition: Property.h:53
@ Output
An output workspace.
Definition: Property.h:54