Newer
Older
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
// NScD Oak Ridge National Laboratory, European Spallation Source,
// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
// SPDX - License - Identifier: GPL - 3.0 +
#include "MantidAPI/AlgorithmManager.h"
#include "MantidAPI/FileProperty.h"
#include "MantidAPI/FrameworkManager.h"
Gigg, Martyn Anthony
committed
#include "MantidAPI/IEventWorkspace.h"
#include "MantidAPI/IMDEventWorkspace.h"
#include "MantidAPI/ITableWorkspace.h"
Gigg, Martyn Anthony
committed
#include "MantidAPI/IWorkspaceProperty.h"
#include "MantidAPI/MultipleFileProperty.h"
#include "MantidAPI/NexusFileLoader.h"
#include "MantidAPI/WorkspaceGroup.h"
Gigg, Martyn Anthony
committed
#include "MantidKernel/FacilityInfo.h"
#include <Poco/Path.h>
#include <functional>
#include <numeric>
#include <set>
namespace {
/**
* Convenience function that returns true if the passed vector of vector of
*strings
* contains a single string, false if contains more than that (or zero).
*
* @param fileNames :: a vector of vectors of file name strings.
*
* @returns true if there is exactly one string, else false.
*/
bool isSingleFile(const std::vector<std::vector<std::string>> &fileNames) {
if (fileNames.size() == 1) {
Hahn, Steven
committed
auto first = fileNames.cbegin();
if (first->size() == 1)
return true;
}
return false;
}
/**
* Helper function that takes a vector of filenames, and generates a suggested
*workspace name.
*
* @param filenames :: a vector of filenames.
*
* @returns a string containing a suggested ws name based on the given file
*names.
*/
std::string
generateWsNameFromFileNames(const std::vector<std::string> &filenames) {
for (auto &filename : filenames) {
if (!wsName.empty())
wsName += "_";
Poco::Path path(filename);
/**
* Helper function that takes a vector of vectors of items and flattens it into
* a single vector of items.
*/
std::vector<std::string>
flattenVecOfVec(std::vector<std::vector<std::string>> vecOfVec) {
std::vector<std::string> flattenedVec;
std::vector<std::vector<std::string>>::const_iterator it = vecOfVec.begin();
for (; it != vecOfVec.end(); ++it) {
flattenedVec.insert(flattenedVec.end(), it->begin(), it->end());
namespace Mantid {
namespace DataHandling {
// Register the algorithm into the algorithm factory
std::recursive_mutex Load::m_mutex;
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
using namespace Kernel;
using namespace API;
//--------------------------------------------------------------------------
// Public methods
//--------------------------------------------------------------------------
/** Override setPropertyValue to catch if filename is being set, as this may
* mean
* a change of concrete loader. If it's any other property, just forward the
* call.
* @param name The name of the property
* @param value The value of the property as a string
*/
void Load::setPropertyValue(const std::string &name, const std::string &value) {
// Call base class method in all cases.
// For a filename property is deals with resolving the full path.
Algorithm::setPropertyValue(name, value);
std::string NAME(name);
std::transform(name.begin(), name.end(), NAME.begin(), toupper);
if (NAME == "FILENAME") {
// Get back full path before passing to getFileLoader method, and also
// find out whether this is a multi file load.
std::vector<std::string> fileNames =
flattenVecOfVec(getProperty("Filename"));
// If it's a single file load, then it's fine to change loader.
if (fileNames.size() == 1) {
IAlgorithm_sptr loader = getFileLoader(getPropertyValue(name));
assert(loader); // (getFileLoader should throw if no loader is found.)
declareLoaderProperties(loader);
Gigg, Martyn Anthony
committed
}
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
// Else we've got multiple files, and must enforce the rule that only one
// type of loader is allowed.
// Allowing more than one would mean that "extra" properties defined by the
// class user (for example
// "LoadLogFiles") are potentially ambiguous.
else if (fileNames.size() > 1) {
IAlgorithm_sptr loader = getFileLoader(fileNames[0]);
// If the first file has a loader ...
if (loader) {
// ... store it's name and version and check that all other files have
// loaders with the same name and version.
std::string name = loader->name();
int version = loader->version();
// std::string ext =
// fileNames[0].substr(fileNames[0].find_last_of("."));
auto ifl =
boost::dynamic_pointer_cast<IFileLoader<Kernel::FileDescriptor>>(
loader);
auto iflNexus =
boost::dynamic_pointer_cast<IFileLoader<Kernel::NexusDescriptor>>(
loader);
for (size_t i = 1; i < fileNames.size(); ++i) {
// If it's loading into a single file, perform a cursory check on file
// extensions only.
if ((ifl && ifl->loadMutipleAsOne()) ||
(iflNexus && iflNexus->loadMutipleAsOne())) {
// Currently disabled for ticket
// http://trac.mantidproject.org/mantid/ticket/10397 : should be put
// back in when completing 10231
/* if( fileNames[i].substr(fileNames[i].find_last_of(".")) != ext)
throw std::runtime_error("Cannot load multiple files when more
than one Loader is needed.");
}*/
} else {
loader = getFileLoader(fileNames[i]);
if (name != loader->name() || version != loader->version())
throw std::runtime_error("Cannot load multiple files when more "
"than one Loader is needed.");
Gigg, Martyn Anthony
committed
}
assert(loader); // (getFileLoader should throw if no loader is found.)
declareLoaderProperties(loader);
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
//--------------------------------------------------------------------------
// Private methods
//--------------------------------------------------------------------------
/**
* Get a shared pointer to the load algorithm with highest preference for
* loading
* @param filePath :: path of the file
* @returns A shared pointer to the unmanaged algorithm
*/
API::IAlgorithm_sptr Load::getFileLoader(const std::string &filePath) {
API::IAlgorithm_sptr winningLoader;
try {
winningLoader = API::FileLoaderRegistry::Instance().chooseLoader(filePath);
} catch (Exception::NotFoundError &) {
// Clear what may have been here previously
setPropertyValue("LoaderName", "");
setProperty("LoaderVersion", -1);
throw std::runtime_error(
"Cannot find an algorithm that is able to load \"" + filePath +
"\".\n"
"Check that the file is a supported type.");
}
winningLoader->initialize();
setUpLoader(winningLoader, 0, 1);
findFilenameProperty(winningLoader);
setPropertyValue("LoaderName", winningLoader->name());
setProperty("LoaderVersion", winningLoader->version());
return winningLoader;
}
void Load::findFilenameProperty(const API::IAlgorithm_sptr &loader) {
const auto nxsLoader = boost::dynamic_pointer_cast<NexusFileLoader>(loader);
if (nxsLoader) {
// NexusFileLoader has a method for giving back the name directly
m_filenamePropName = nxsLoader->getFilenamePropertyName();
} else {
// Use the first file property as the main Filename
const auto &props = loader->getProperties();
for (auto prop : props) {
auto *multiprop = dynamic_cast<API::MultipleFileProperty *>(prop);
auto *singleprop = dynamic_cast<API::FileProperty *>(prop);
if (multiprop) {
m_filenamePropName = multiprop->name();
break;
}
if (singleprop) {
m_filenamePropName = singleprop->name();
break;
}
// throw an exception if somehting nothing was found
if (m_filenamePropName.empty()) {
// unset member variables
setPropertyValue("LoaderName", "");
setProperty("LoaderVersion", -1);
std::stringstream msg;
msg << "Cannot find FileProperty on \"" << loader->name() << "\" v"
<< loader->version() << " algorithm.";
throw std::runtime_error(msg.str());
}
* Declare any additional properties of the concrete loader here
* @param loader A pointer to the concrete loader
*/
void Load::declareLoaderProperties(const API::IAlgorithm_sptr &loader) {
// If we have switch loaders then the concrete loader will have different
// properties
// so take care of ensuring Load has the correct ones
// THIS IS A COPY as the properties are mutated as we move through them
const std::vector<Property *> existingProps = this->getProperties();
for (auto existingProp : existingProps) {
const std::string &name = existingProp->name();
// Wipe all properties except the Load native ones
if (m_baseProps.find(name) == m_baseProps.end()) {
this->removeProperty(name);
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
const std::vector<Property *> &loaderProps = loader->getProperties();
size_t numProps(loaderProps.size());
for (size_t i = 0; i < numProps; ++i) {
Property *loadProp = loaderProps[i];
if (loadProp->name() == m_filenamePropName)
continue;
try {
auto propClone = std::unique_ptr<Property>(loadProp->clone());
propClone->clearSettings(); // Get rid of special settings because it
declareProperty(std::move(propClone), loadProp->documentation());
} catch (Exception::ExistsError &) {
// Already exists as a static property
continue;
}
}
}
Gigg, Martyn Anthony
committed
/// Initialisation method.
void Load::init() {
// Take extensions first from Facility object
const FacilityInfo &defaultFacility =
Mantid::Kernel::ConfigService::Instance().getFacility();
std::vector<std::string> exts = defaultFacility.extensions();
// Add in some other known extensions
exts.emplace_back(".xml");
exts.emplace_back(".dat");
exts.emplace_back(".txt");
exts.emplace_back(".csv");
exts.emplace_back(".spe");
exts.emplace_back(".grp");
exts.emplace_back(".nxspe");
exts.emplace_back(".h5");
exts.emplace_back(".hd5");
exts.emplace_back(".sqw");
exts.emplace_back(".fits");
exts.emplace_back(".bin");
std::make_unique<MultipleFileProperty>("Filename", exts),
"The name of the file(s) to read, including the full or relative "
"path. (N.B. case sensitive if running on Linux). Multiple runs "
"can be loaded and added together, e.g. INST10,11+12,13.ext");
declareProperty(
std::make_unique<WorkspaceProperty<Workspace>>("OutputWorkspace", "",
"The name of the workspace that will be created, filled with the "
"read-in data and stored in the Analysis Data Service. Some algorithms "
"can created additional OutputWorkspace properties on the fly, e.g. "
"multi-period data.");
declareProperty("LoaderName", std::string(""),
"When an algorithm has been found that will load the given "
"file, its name is set here.",
Direction::Output);
declareProperty("LoaderVersion", -1,
"When an algorithm has been found that "
"will load the given file, its version "
"is set here.",
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
Direction::Output);
// Save for later what the base Load properties are
const std::vector<Property *> &props = this->getProperties();
for (size_t i = 0; i < this->propertyCount(); ++i) {
m_baseProps.insert(props[i]->name());
}
}
/**
* Executes the algorithm.
*/
void Load::exec() {
std::vector<std::vector<std::string>> fileNames = getProperty("Filename");
// Test for loading as a single file
IAlgorithm_sptr loader = getFileLoader(fileNames[0][0]);
auto ifl =
boost::dynamic_pointer_cast<IFileLoader<Kernel::FileDescriptor>>(loader);
auto iflNexus =
boost::dynamic_pointer_cast<IFileLoader<Kernel::NexusDescriptor>>(loader);
if (isSingleFile(fileNames) || (ifl && ifl->loadMutipleAsOne()) ||
(iflNexus && iflNexus->loadMutipleAsOne())) {
// This is essentially just the same code that was called before multiple
// files were supported.
loadSingleFile();
} else {
// Code that supports multiple file loading.
loadMultipleFiles();
}
}
void Load::loadSingleFile() {
std::string loaderName = getPropertyValue("LoaderName");
if (loaderName.empty()) {
m_loader = getFileLoader(getPropertyValue("Filename"));
loaderName = m_loader->name();
} else {
m_loader = createLoader(0, 1);
findFilenameProperty(m_loader);
}
g_log.information() << "Using " << loaderName << " version "
<< m_loader->version() << ".\n";
/// get the list properties for the concrete loader load algorithm
const std::vector<Kernel::Property *> &loader_props =
m_loader->getProperties();
// Loop through and set the properties on the Child Algorithm
std::vector<Kernel::Property *>::const_iterator itr;
for (itr = loader_props.begin(); itr != loader_props.end(); ++itr) {
const std::string propName = (*itr)->name();
if (this->existsProperty(propName)) {
m_loader->setPropertyValue(propName, getPropertyValue(propName));
} else if (propName == m_filenamePropName) {
m_loader->setPropertyValue(propName, getPropertyValue("Filename"));
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
// Execute the concrete loader
m_loader->execute();
// Set the workspace. Deals with possible multiple periods
setOutputWorkspace(m_loader);
}
Gigg, Martyn Anthony
committed
void Load::loadMultipleFiles() {
// allFilenames contains "rows" of filenames. If the row has more than 1 file
// in it
// then that row is to be summed across each file in the row
const std::vector<std::vector<std::string>> allFilenames =
getProperty("Filename");
std::string outputWsName = getProperty("OutputWorkspace");
std::vector<std::string> wsNames(allFilenames.size());
std::transform(allFilenames.begin(), allFilenames.end(), wsNames.begin(),
generateWsNameFromFileNames);
Hahn, Steven
committed
auto wsName = wsNames.cbegin();
assert(allFilenames.size() == wsNames.size());
std::vector<API::Workspace_sptr> loadedWsList;
loadedWsList.reserve(allFilenames.size());
Workspace_sptr tempWs;
// Cycle through the filenames and wsNames.
Hahn, Steven
committed
for (auto filenames = allFilenames.cbegin(); filenames != allFilenames.cend();
++filenames, ++wsName) {
auto filename = filenames->cbegin();
Workspace_sptr sumWS = loadFileToWs(*filename, *wsName);
++filename;
Hahn, Steven
committed
for (; filename != filenames->cend(); ++filename) {
tempWs = loadFileToWs(*filename, "__@loadsum_temp@");
sumWS = plusWs(sumWS, tempWs);
Gigg, Martyn Anthony
committed
}
API::WorkspaceGroup_sptr group =
boost::dynamic_pointer_cast<WorkspaceGroup>(sumWS);
if (group) {
std::vector<std::string> childWsNames = group->getNames();
auto childWsName = childWsNames.begin();
size_t count = 1;
for (; childWsName != childWsNames.end(); ++childWsName, ++count) {
Workspace_sptr childWs = group->getItem(*childWsName);
const std::string childName =
group->getName() + "_" + std::to_string(count);
API::AnalysisDataService::Instance().addOrReplace(childName, childWs);
// childWs->setName(group->getName() + "_" +
// boost::lexical_cast<std::string>(count));
// Add the sum to the list of loaded workspace names.
loadedWsList.emplace_back(sumWS);
// If we only have one loaded ws, set it as the output.
if (loadedWsList.size() == 1) {
setProperty("OutputWorkspace", loadedWsList[0]);
AnalysisDataService::Instance().rename(loadedWsList[0]->getName(),
outputWsName);
}
// Else we have multiple loaded workspaces - group them and set the group as
// output.
else {
API::WorkspaceGroup_sptr group = groupWsList(loadedWsList);
setProperty("OutputWorkspace", group);
std::vector<std::string> childWsNames = group->getNames();
size_t count = 1;
for (auto &childWsName : childWsNames) {
if (childWsName == outputWsName) {
Mantid::API::Workspace_sptr child = group->getItem(childWsName);
// child->setName(child->getName() + "_" +
// boost::lexical_cast<std::string>(count));
const std::string childName =
child->getName() + "_" + std::to_string(count);
API::AnalysisDataService::Instance().addOrReplace(childName, child);
count++;
Gigg, Martyn Anthony
committed
}
}
childWsNames = group->getNames();
count = 1;
for (auto &childWsName : childWsNames) {
Workspace_sptr childWs = group->getItem(childWsName);
std::string outWsPropName = "OutputWorkspace_" + std::to_string(count);
declareProperty(std::make_unique<WorkspaceProperty<Workspace>>(
outWsPropName, childWsName, Direction::Output));
setProperty(outWsPropName, childWs);
}
}
// Clean up.
if (tempWs) {
Algorithm_sptr alg =
AlgorithmManager::Instance().createUnmanaged("DeleteWorkspace");
alg->initialize();
alg->setChild(true);
alg->setProperty("Workspace", tempWs);
alg->execute();
}
}
* Create the concrete instance use for the actual loading.
* @param startProgress :: The percentage progress value of the overall
* algorithm where this child algorithm starts
* @param endProgress :: The percentage progress value of the overall
* algorithm where this child algorithm ends
* @param logging :: Set to false to disable logging from the child algorithm
*/
API::IAlgorithm_sptr Load::createLoader(const double startProgress,
const double endProgress,
const bool logging) const {
std::string name = getPropertyValue("LoaderName");
int version = getProperty("LoaderVersion");
API::IAlgorithm_sptr loader =
API::AlgorithmManager::Instance().createUnmanaged(name, version);
loader->initialize();
if (!loader) {
throw std::runtime_error("Cannot create loader for \"" +
getPropertyValue("Filename") + "\"");
}
setUpLoader(loader, startProgress, endProgress, logging);
return loader;
}
/**
* Set the loader option for use as a Child Algorithm.
* @param loader :: Concrete loader
* @param startProgress :: The start progress fraction
* @param endProgress :: The end progress fraction
* @param logging:: If true, enable logging
*/
void Load::setUpLoader(API::IAlgorithm_sptr &loader, const double startProgress,
const double endProgress, const bool logging) const {
// Set as a child so that we are in control of output storage
loader->setChild(true);
loader->setLogging(logging);
// If output workspaces are nameless, give them a temporary name to satisfy
// validator
const std::vector<Property *> &props = loader->getProperties();
for (auto prop : props) {
auto wsProp = dynamic_cast<IWorkspaceProperty *>(prop);
if (wsProp && !wsProp->isOptional() &&
prop->direction() == Direction::Output) {
if (prop->value().empty())
prop->setValue("LoadChildWorkspace");
}
}
if (startProgress >= 0. && endProgress > startProgress && endProgress <= 1.) {
loader->addObserver(this->progressObserver());
setChildStartProgress(startProgress);
setChildEndProgress(endProgress);
}
}
* Set the output workspace(s) if the load's return workspace has type
* API::Workspace
* @param loader :: Shared pointer to load algorithm
*/
void Load::setOutputWorkspace(const API::IAlgorithm_sptr &loader) {
// Go through each OutputWorkspace property and check whether we need to make
// a counterpart here
const std::vector<Property *> &loaderProps = loader->getProperties();
const size_t count = loader->propertyCount();
for (size_t i = 0; i < count; ++i) {
Property *prop = loaderProps[i];
if (dynamic_cast<IWorkspaceProperty *>(prop) &&
prop->direction() == Direction::Output) {
const std::string &name = prop->name();
if (!this->existsProperty(name)) {
declareProperty(std::make_unique<WorkspaceProperty<Workspace>>(
name, loader->getPropertyValue(name), Direction::Output));
}
Workspace_sptr wkspace = getOutputWorkspace(name, loader);
setProperty(name, wkspace);
}
}
}
* Return an output workspace property dealing with the lack of connection
* between of
* WorkspaceProperty types
* @param propName :: The name of the property
* @param loader :: The loader algorithm
* @returns A pointer to the OutputWorkspace property of the Child Algorithm
*/
API::Workspace_sptr
Load::getOutputWorkspace(const std::string &propName,
const API::IAlgorithm_sptr &loader) const {
// @todo Need to try and find a better way using the getValue methods
try {
return loader->getProperty(propName);
} catch (std::runtime_error &) {
}
// Try a MatrixWorkspace
try {
MatrixWorkspace_sptr childWS = loader->getProperty(propName);
return childWS;
} catch (std::runtime_error &) {
}
// EventWorkspace
try {
IEventWorkspace_sptr childWS = loader->getProperty(propName);
return childWS;
} catch (std::runtime_error &) {
}
// IMDEventWorkspace
try {
IMDEventWorkspace_sptr childWS = loader->getProperty(propName);
return childWS;
} catch (std::runtime_error &) {
}
Gigg, Martyn Anthony
committed
// General IMDWorkspace
try {
IMDWorkspace_sptr childWS = loader->getProperty(propName);
return childWS;
} catch (std::runtime_error &) {
}
Gigg, Martyn Anthony
committed
// ITableWorkspace?
try {
ITableWorkspace_sptr childWS = loader->getProperty(propName);
return childWS;
} catch (std::runtime_error &) {
}
Gigg, Martyn Anthony
committed
// Just workspace?
try {
Workspace_sptr childWS = loader->getProperty(propName);
return childWS;
} catch (std::runtime_error &) {
}
g_log.debug() << "Workspace property " << propName
<< " did not return to MatrixWorkspace, EventWorkspace, "
"IMDEventWorkspace, IMDWorkspace\n";
Janik Zikovsky
committed
* Overrides the default cancel() method. Calls cancel() on the actual loader.
*/
void Load::cancel() {
if (m_loader) {
m_loader->cancel();
}
}
/**
* Loads a file into a *hidden* workspace.
*
* @param fileName :: file name to load.
* @param wsName :: workspace name, which will be prefixed by a "__"
*
* @returns a pointer to the loaded workspace
*/
API::Workspace_sptr Load::loadFileToWs(const std::string &fileName,
const std::string &wsName) {
Mantid::API::IAlgorithm_sptr loadAlg = createChildAlgorithm("Load", 1);
// Get the list properties for the concrete loader load algorithm
const std::vector<Kernel::Property *> &props = getProperties();
// Loop through and set the properties on the Child Algorithm
for (auto prop : props) {
const std::string &propName = prop->name();
if (this->existsProperty(propName)) {
if (propName == "Filename") {
loadAlg->setPropertyValue("Filename", fileName);
} else if (propName == "OutputWorkspace") {
loadAlg->setPropertyValue("OutputWorkspace", wsName);
} else {
loadAlg->setPropertyValue(propName, getPropertyValue(propName));
Roman Tolchenov
committed
}
}
Roman Tolchenov
committed
Workspace_sptr ws = loadAlg->getProperty("OutputWorkspace");
// ws->setName(wsName);
AnalysisDataService::Instance().addOrReplace(wsName, ws);
return ws;
}
/**
* Plus two workspaces together, "in place".
*
* @param ws1 :: The first workspace.
* @param ws2 :: The second workspace.
*
* @returns a pointer to the result (the first workspace).
*/
API::Workspace_sptr Load::plusWs(Workspace_sptr ws1,
const Workspace_sptr &ws2) {
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
WorkspaceGroup_sptr group1 = boost::dynamic_pointer_cast<WorkspaceGroup>(ws1);
WorkspaceGroup_sptr group2 = boost::dynamic_pointer_cast<WorkspaceGroup>(ws2);
if (group1 && group2) {
// If we're dealing with groups, then the child workspaces must be added
// separately - setProperty
// wont work otherwise.
std::vector<std::string> group1ChildWsNames = group1->getNames();
std::vector<std::string> group2ChildWsNames = group2->getNames();
if (group1ChildWsNames.size() != group2ChildWsNames.size())
throw std::runtime_error("Unable to add group workspaces with different "
"number of child workspaces.");
auto group1ChildWsName = group1ChildWsNames.begin();
auto group2ChildWsName = group2ChildWsNames.begin();
for (; group1ChildWsName != group1ChildWsNames.end();
++group1ChildWsName, ++group2ChildWsName) {
Workspace_sptr group1ChildWs = group1->getItem(*group1ChildWsName);
Workspace_sptr group2ChildWs = group2->getItem(*group2ChildWsName);
Mantid::API::IAlgorithm_sptr plusAlg = createChildAlgorithm("Plus", 1);
plusAlg->setProperty<Workspace_sptr>("LHSWorkspace", group1ChildWs);
plusAlg->setProperty<Workspace_sptr>("RHSWorkspace", group2ChildWs);
plusAlg->setProperty<Workspace_sptr>("OutputWorkspace", group1ChildWs);
plusAlg->executeAsChildAlg();
} else if (!group1 && !group2) {
Mantid::API::IAlgorithm_sptr plusAlg = createChildAlgorithm("Plus", 1);
plusAlg->setProperty<Workspace_sptr>("LHSWorkspace", ws1);
plusAlg->setProperty<Workspace_sptr>("RHSWorkspace", ws2);
plusAlg->setProperty<Workspace_sptr>("OutputWorkspace", ws1);
plusAlg->executeAsChildAlg();
} else {
throw std::runtime_error(
"Unable to add a group workspace to a non-group workspace");
}
/**
* Groups together a vector of workspaces. This is done "manually", since the
* workspaces being passed will be outside of the ADS and so the GroupWorkspaces
* alg is not an option here.
*
* @param wsList :: the list of workspaces to group
*/
API::WorkspaceGroup_sptr
Load::groupWsList(const std::vector<API::Workspace_sptr> &wsList) {
auto group = boost::make_shared<WorkspaceGroup>();
for (const auto &ws : wsList) {
boost::dynamic_pointer_cast<WorkspaceGroup>(ws);
// If the ws to add is already a group, then add its children individually.
if (isGroup) {
std::vector<std::string> childrenNames = isGroup->getNames();
size_t count = 1;
for (auto childName = childrenNames.begin();
childName != childrenNames.end(); ++childName, ++count) {
Workspace_sptr childWs = isGroup->getItem(*childName);
isGroup->remove(*childName);
// childWs->setName(isGroup->getName() + "_" +
// boost::lexical_cast<std::string>(count));
group->addWorkspace(childWs);
}
// Remove the old group from the ADS
AnalysisDataService::Instance().remove(isGroup->getName());
} else {
group->addWorkspace(ws);
Parallel::ExecutionMode Load::getParallelExecutionMode(
const std::map<std::string, Parallel::StorageMode> &storageModes) const {
static_cast<void>(storageModes);
// The actually relevant execution mode is that of the underlying loader. Here
// we simply default to ExecutionMode::Distributed to guarantee that the
// normal exec() is being run on all ranks.
return Parallel::ExecutionMode::Distributed;
}