Mantid
Loading...
Searching...
No Matches
MultiPeriodGroupWorker.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 +
7#include <utility>
8
13#include "MantidAPI/Run.h"
18
19using namespace Mantid::Kernel;
20
21namespace Mantid::API {
22
28MultiPeriodGroupWorker::MultiPeriodGroupWorker(std::string workspacePropertyName)
29 : m_workspacePropertyName(std::move(workspacePropertyName)) {}
30
39 const Workspace_sptr &ws, MultiPeriodGroupWorker::VecWSGroupType &vecMultiPeriodWorkspaceGroups,
40 MultiPeriodGroupWorker::VecWSGroupType &vecWorkspaceGroups) const {
41 WorkspaceGroup_sptr inputGroup = std::dynamic_pointer_cast<WorkspaceGroup>(ws);
42 if (inputGroup) {
43 if (inputGroup->isMultiperiod()) {
44 vecMultiPeriodWorkspaceGroups.emplace_back(inputGroup);
45 } else {
46 vecWorkspaceGroups.emplace_back(inputGroup);
47 }
48 }
49}
50
53 if (!sourceAlg->isInitialized()) {
54 throw std::invalid_argument("Algorithm must be initialized");
55 }
56 VecWSGroupType vecMultiPeriodWorkspaceGroups;
57 VecWSGroupType vecWorkspaceGroups;
58
59 // Handles the case in which the algorithm is providing a non-workspace
60 // property as an input.
61 // This is currenly the case for algorithms that take an array of strings as
62 // an input where each entry is the name of a workspace.
63 if (this->useCustomWorkspaceProperty()) {
64 using WorkspaceNameType = std::vector<std::string>;
65
66 // Perform a check that the input property is the correct type.
67 Property *inputProperty = sourceAlg->getProperty(this->m_workspacePropertyName);
68
69 if (!dynamic_cast<ArrayProperty<std::string> *>(inputProperty)) {
70 throw std::runtime_error("Support for custom input workspaces that are "
71 "not string Arrays are not currently "
72 "supported.");
73 /*Note that we could extend this algorithm to cover other input property
74 * types if required, but we don't need that funtionality now.*/
75 }
76
77 WorkspaceNameType workspaces = sourceAlg->getProperty(this->m_workspacePropertyName);
78
79 // Inspect all the input workspaces in the ArrayProperty input.
80 for (auto &workspace : workspaces) {
82 if (!ws) {
84 }
85 tryAddInputWorkspaceToInputGroups(ws, vecMultiPeriodWorkspaceGroups, vecWorkspaceGroups);
86 }
87 } else {
88 using WorkspaceVector = std::vector<std::shared_ptr<Workspace>>;
89 WorkspaceVector inWorkspaces;
90 sourceAlg->findWorkspaces(inWorkspaces, Direction::Input);
91 for (auto &inWorkspace : inWorkspaces) {
92 tryAddInputWorkspaceToInputGroups(inWorkspace, vecMultiPeriodWorkspaceGroups, vecWorkspaceGroups);
93 }
94 }
95
96 if (!vecMultiPeriodWorkspaceGroups.empty() && !vecWorkspaceGroups.empty()) {
97 throw std::invalid_argument("The input contains a mix of multi-period and other workspaces.");
98 }
99
100 validateMultiPeriodGroupInputs(vecMultiPeriodWorkspaceGroups);
101
102 return vecMultiPeriodWorkspaceGroups;
103}
104
106
128 const VecWSGroupType &vecWorkspaceGroups) const {
129 std::string prefix;
130 std::string inputWorkspaces;
131 for (const auto &vecWorkspaceGroup : vecWorkspaceGroups) {
132 inputWorkspaces += prefix + vecWorkspaceGroup->getItem(periodIndex)->getName();
133 prefix = ",";
134 }
135 return inputWorkspaces;
136}
137
152 const int &periodNumber) const {
153 std::vector<Property *> props = sourceAlg->getProperties();
154 for (auto prop : props) {
155 if (prop) {
156 if (prop->direction() == Direction::Input) {
157 if (const IWorkspaceProperty *wsProp = dynamic_cast<IWorkspaceProperty *>(prop)) {
158 if (WorkspaceGroup_sptr inputws = std::dynamic_pointer_cast<WorkspaceGroup>(wsProp->getWorkspace())) {
159 if (inputws->isMultiperiod()) {
160 targetAlg->setProperty(prop->name(), inputws->getItem(periodNumber - 1));
161 }
162 }
163 }
164 }
165 }
166 }
167}
168
169//--------------------------------------------------------------------------------------------
186 const VecWSGroupType &vecMultiPeriodGroups) const {
187 // If we are not processing multiperiod groups, use the base behaviour.
188 if (vecMultiPeriodGroups.empty()) {
189 return false; // Indicates that this is not a multiperiod group workspace.
190 }
191 Property *outputWorkspaceProperty = sourceAlg->getProperty("OutputWorkspace");
192 const std::string outName = outputWorkspaceProperty->value();
193
194 const size_t nPeriods = vecMultiPeriodGroups[0]->size();
195 WorkspaceGroup_sptr outputWS = std::make_shared<WorkspaceGroup>();
196 AnalysisDataService::Instance().addOrReplace(outName, outputWS);
197
198 double progress_proportion = 1.0 / static_cast<double>(nPeriods);
199 // Loop through all the periods. Create spawned algorithms of the same type as
200 // this to process pairs from the input groups.
201 for (size_t i = 0; i < nPeriods; ++i) {
202 const auto periodNumber = static_cast<int>(i + 1);
203 // use create Child Algorithm that look like this one
204 Algorithm_sptr alg = sourceAlg->createChildAlgorithm(sourceAlg->name(), progress_proportion * periodNumber,
205 progress_proportion * (1 + periodNumber),
206 sourceAlg->isLogging(), sourceAlg->version());
207 if (!alg) {
208 throw std::runtime_error("Algorithm creation failed.");
209 }
210 // Don't make the new algorithm a child so that it's workspaces are stored
211 // correctly
212 alg->setChild(false);
213 alg->setRethrows(true);
214 alg->initialize();
215 // Copy properties that aren't workspaces properties.
216 sourceAlg->copyNonWorkspaceProperties(alg.get(), periodNumber);
217
218 if (this->useCustomWorkspaceProperty()) {
219 const std::string inputWorkspaces = createFormattedInputWorkspaceNames(i, vecMultiPeriodGroups);
220 // Set the input workspace property.
221 alg->setPropertyValue(this->m_workspacePropertyName, inputWorkspaces);
222 } else {
223 // Configure input properties that are group workspaces.
224 copyInputWorkspaceProperties(alg.get(), sourceAlg, periodNumber);
225 }
226 const std::string outName_i = outName + "_" + Strings::toString(i + 1);
227 alg->setPropertyValue("OutputWorkspace", outName_i);
228 // Run the spawned algorithm.
229 if (!alg->execute()) {
230 throw std::runtime_error("Execution of " + sourceAlg->name() + " for group entry " + Strings::toString(i + 1) +
231 " failed.");
232 }
233 // Add the output workpace from the spawned algorithm to the group.
234 outputWS->add(outName_i);
235 }
236
237 sourceAlg->setProperty("OutputWorkspace", outputWS);
238
239 return true;
240}
241
248 const size_t multiPeriodGroupsSize = vecMultiPeriodGroups.size();
249
250 if (multiPeriodGroupsSize > 0) {
251 const size_t benchMarkGroupSize = vecMultiPeriodGroups[0]->size();
252 for (size_t i = 0; i < multiPeriodGroupsSize; ++i) {
253 WorkspaceGroup_sptr currentGroup = vecMultiPeriodGroups[i];
254 if (currentGroup->size() != benchMarkGroupSize) {
255 throw std::runtime_error("Not all the input Multi-period-group input "
256 "workspaces are the same size.");
257 }
258 for (size_t j = 0; j < currentGroup->size(); ++j) {
259 MatrixWorkspace_const_sptr currentNestedWS =
260 std::dynamic_pointer_cast<const MatrixWorkspace>(currentGroup->getItem(j));
261 Property *nPeriodsProperty = currentNestedWS->run().getLogData("nperiods");
262 size_t nPeriods = std::stoul(nPeriodsProperty->value());
263 if (nPeriods != benchMarkGroupSize) {
264 throw std::runtime_error("Missmatch between nperiods log and the "
265 "number of workspaces in the input group: " +
266 vecMultiPeriodGroups[i]->getName());
267 }
268 Property *currentPeriodProperty = currentNestedWS->run().getLogData("current_period");
269 size_t currentPeriod = std::stoul(currentPeriodProperty->value());
270 if (currentPeriod != (j + 1)) {
271 throw std::runtime_error("Multiperiod group workspaces must be "
272 "ordered by current_period. Correct: " +
273 currentNestedWS->getName());
274 }
275 }
276 }
277 }
278}
279
280} // namespace Mantid::API
IPeaksWorkspace_sptr workspace
Definition: IndexPeaks.cpp:114
std::string getName(const IMDDimension &self)
Base class from which all concrete algorithm classes should be derived.
Definition: Algorithm.h:85
void copyNonWorkspaceProperties(IAlgorithm *alg, int periodNum)
Copy all the non-workspace properties from this to alg.
Definition: Algorithm.cpp:1523
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
virtual 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)
Create a Child Algorithm.
Definition: Algorithm.cpp:842
bool isInitialized() const override
Has the Algorithm already been initialized.
Definition: Algorithm.cpp:148
bool isLogging() const override
returns the status of logging, True = enabled
Definition: Algorithm.cpp:1664
int version() const override=0
function to return a version of the algorithm, must be overridden in all algorithms
void findWorkspaces(WorkspaceVector &workspaces, unsigned int direction, bool checkADS=false) const
Populate lists of the workspace properties for a given direction (InOut workspaces are included in bo...
Definition: Algorithm.cpp:1073
const std::string name() const override=0
function to return a name of the algorithm, must be overridden in all algorithms
IAlgorithm is the interface implemented by the Algorithm base class.
Definition: IAlgorithm.h:45
An interface that is implemented by WorkspaceProperty.
MultiPeriodGroupWorker()=default
Constructor.
void validateMultiPeriodGroupInputs(const VecWSGroupType &vecMultiPeriodGroups) const
Validate the input group workspace.
VecWSGroupType findMultiPeriodGroups(Algorithm const *const sourceAlg) const
Check groups.
bool useCustomWorkspaceProperty() const
Flag to indicate use of a custom workspace property.
std::vector< WorkspaceGroup_sptr > VecWSGroupType
Convenience typdef for workspace names.
void copyInputWorkspaceProperties(IAlgorithm *targetAlg, IAlgorithm *sourceAlg, const int &periodNumber) const
Copy input workspace properties to spawned algorithm.
void tryAddInputWorkspaceToInputGroups(const Workspace_sptr &ws, VecWSGroupType &vecMultiPeriodWorkspaceGroups, VecWSGroupType &vecWorkspaceGroups) const
Try ot add a workspace to the group of input workspaces.
std::string createFormattedInputWorkspaceNames(const size_t &periodIndex, const VecWSGroupType &vecWorkspaceGroups) const
Create an input workspace string from the workspace groups.
std::string m_workspacePropertyName
Workspace property name.
bool processGroups(Algorithm *const sourceAlg, const VecWSGroupType &vecMultiPeriodGroups) const
Process groups.
Support for a property that holds an array of values.
Definition: ArrayProperty.h:28
Exception for when an item is not found in a collection.
Definition: Exception.h:145
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
virtual const std::vector< Property * > & getProperties() const =0
Get the list of managed properties.
Base class for properties.
Definition: Property.h:94
virtual std::string value() const =0
Returns the value of the property as a string.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
std::shared_ptr< WorkspaceGroup > WorkspaceGroup_sptr
shared pointer to Mantid::API::WorkspaceGroup
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
Definition: Workspace_fwd.h:20
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
std::shared_ptr< Algorithm > Algorithm_sptr
Typedef for a shared pointer to an Algorithm.
Definition: Algorithm.h:61
std::string toString(const T &value)
Convert a number to a string.
Definition: Strings.cpp:703
STL namespace.
@ Input
An input workspace.
Definition: Property.h:53