11#include <boost/algorithm/string.hpp>
12#include <boost/regex.hpp>
25 virtual bool isValid()
const {
return true; }
30 if (!this->isValid()) {
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->setProperty(
"CheckMatchingBins",
false);
41 conjoinWorkspaceAlg->execute();
47 virtual ~Command() =
default;
51using VecCommands = std::vector<std::shared_ptr<Command>>;
56class NullCommand :
public Command {
57 bool isValid()
const override {
return false; }
59 throw std::runtime_error(
"Should not be attempting ::execute on a NullCommand");
66class AdditionCommand :
public Command {
68 std::vector<int> m_indexes;
71 explicit AdditionCommand(std::vector<int> indexes) : m_indexes(
std::move(indexes)) {}
75 if (!m_indexes.empty()) {
77 auto sumSpectraAlg = factory.
create(
"SumSpectra");
78 sumSpectraAlg->setChild(
true);
79 sumSpectraAlg->initialize();
80 sumSpectraAlg->setProperty(
"InputWorkspace", inputWS);
81 sumSpectraAlg->setProperty(
"ListOfWorkspaceIndices", m_indexes);
82 sumSpectraAlg->setPropertyValue(
"OutputWorkspace",
"outWS");
83 sumSpectraAlg->execute();
84 outWS = sumSpectraAlg->getProperty(
"OutputWorkspace");
93class CropCommand :
public Command {
95 std::vector<int> m_indexes;
98 explicit CropCommand(std::vector<int> indexes) : m_indexes(
std::move(indexes)) {}
103 for (
size_t i = 0; i < m_indexes.size(); ++i) {
105 auto cropWorkspaceAlg = factory.
create(
"CropWorkspace");
106 cropWorkspaceAlg->setChild(
true);
107 cropWorkspaceAlg->initialize();
108 cropWorkspaceAlg->setProperty(
"InputWorkspace", inputWS);
109 cropWorkspaceAlg->setProperty(
"StartWorkspaceIndex", m_indexes[i]);
110 cropWorkspaceAlg->setProperty(
"EndWorkspaceIndex", m_indexes[i]);
111 cropWorkspaceAlg->setPropertyValue(
"OutputWorkspace",
"outWS");
112 cropWorkspaceAlg->execute();
117 auto conjoinWorkspaceAlg = factory.
create(
"ConjoinWorkspaces");
118 conjoinWorkspaceAlg->setChild(
true);
119 conjoinWorkspaceAlg->initialize();
120 conjoinWorkspaceAlg->setProperty(
"InputWorkspace1", outWS);
121 conjoinWorkspaceAlg->setProperty(
"InputWorkspace2", subRange);
122 conjoinWorkspaceAlg->setProperty(
"CheckMatchingBins",
false);
123 conjoinWorkspaceAlg->execute();
124 outWS = conjoinWorkspaceAlg->getProperty(
"InputWorkspace1");
136 virtual Command *
interpret(
const std::string &instruction)
const = 0;
138 virtual ~CommandParser() =
default;
142using VecCommandParsers = std::vector<std::shared_ptr<CommandParser>>;
147template <
typename ProductType>
class CommandParserBase :
public CommandParser {
149 Command *
interpret(
const std::string &instruction)
const override {
150 Command *command =
nullptr;
151 boost::regex ex = getRegex();
152 if (boost::regex_match(instruction, ex)) {
154 command =
new ProductType(indexes);
156 command =
new NullCommand;
162 virtual std::string getSeparator()
const = 0;
163 virtual boost::regex getRegex()
const = 0;
169class AdditionParserRange :
public CommandParserBase<AdditionCommand> {
172 boost::regex getRegex()
const override {
173 static const boost::regex r(R
"(^\s*[0-9]+\s*\-\s*[0-9]+\s*$)");
176 std::string getSeparator()
const override {
return "-"; }
182class AdditionParser :
public CommandParser {
184 Command *
interpret(
const std::string &instruction)
const override {
185 Command *command =
nullptr;
186 static const boost::regex ex(R
"(^\s*[0-9]+\s*\+\s*[0-9]+\s*$)");
187 if (boost::regex_match(instruction, ex)) {
188 std::vector<std::string> arguments;
189 boost::split(arguments, instruction, boost::is_any_of(
"+"));
192 Mantid::Kernel::Strings::convert<int>(arguments.front(), minIndex);
193 Mantid::Kernel::Strings::convert<int>(arguments.back(), maxIndex);
194 std::vector<int> indexes;
195 indexes.emplace_back(minIndex);
196 indexes.emplace_back(maxIndex);
197 command =
new AdditionCommand(indexes);
199 command =
new NullCommand;
208class CropParserRange :
public CommandParserBase<CropCommand> {
211 boost::regex getRegex()
const override {
212 static const boost::regex r(R
"(^\s*[0-9]+\s*:\s*[0-9]+\s*$)");
215 std::string getSeparator()
const override {
return ":"; }
221class CropParserIndex :
public CommandParser {
223 Command *
interpret(
const std::string &instruction)
const override {
224 Command *command =
nullptr;
225 static const boost::regex ex(
"^\\s*[0-9]+\\s*$");
226 if (boost::regex_match(instruction, ex)) {
228 Mantid::Kernel::Strings::convert<int>(instruction,
index);
229 std::vector<int> indexes(1,
index);
230 command =
new CropCommand(indexes);
232 command =
new NullCommand;
261 "Input to processes workspace.");
263 "Processing instructions. See full instruction list.");
265 "Output processed workspace");
276VecCommands
interpret(
const std::string &processingInstructions) {
277 std::vector<std::string> processingInstructionsSplit;
278 boost::split(processingInstructionsSplit, processingInstructions, boost::is_any_of(
","));
280 VecCommandParsers commandParsers{std::make_shared<AdditionParserRange>(), std::make_shared<CropParserRange>(),
281 std::make_shared<CropParserIndex>(), std::make_shared<AdditionParser>()};
283 VecCommands commands;
284 for (
const auto &candidate : processingInstructionsSplit) {
285 bool parserFound =
false;
286 for (
const auto &commandParser : commandParsers) {
287 Command *command = commandParser->interpret(candidate);
288 std::shared_ptr<Command> commandSptr(command);
289 if (commandSptr->isValid())
292 commands.emplace_back(commandSptr);
296 throw std::invalid_argument(
"Cannot interpret " + candidate);
307 const std::string processingInstructions = this->
getProperty(
"ProcessingInstructions");
309 boost::regex re(R
"(^\s*[0-9]+\s*$|^(\s*,*[0-9]+(\s*(,|:|\+|\-)\s*)*[0-9]*)*$)");
310 if (!boost::regex_match(processingInstructions, re)) {
311 throw std::invalid_argument(
"ProcessingInstructions are not well formed: " + processingInstructions);
314 if (processingInstructions.empty()) {
316 cloneWS->initialize();
317 cloneWS->setProperty(
"InputWorkspace", inputWorkspace);
321 this->setProperty(
"OutputWorkspace", outWS);
324 VecCommands commands =
interpret(processingInstructions);
327 auto command = commands[0];
329 for (
size_t j = 1; j < commands.size(); ++j) {
330 outWS = commands[j]->executeAndAppend(inputWorkspace, outWS);
333 this->setProperty(
"OutputWorkspace", outWS);
#define DECLARE_ALGORITHM(classname)
std::map< DeltaEMode::Type, std::string > index
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.
The concrete, templated class for properties.
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
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.
@ Input
An input workspace.
@ Output
An output workspace.