-
Notifications
You must be signed in to change notification settings - Fork 122
/
GroupWorkspaces.cpp
161 lines (138 loc) · 5.96 KB
/
GroupWorkspaces.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
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
130
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
// 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 "MantidAlgorithms/GroupWorkspaces.h"
#include "MantidAPI/ADSValidator.h"
#include "MantidAPI/AnalysisDataService.h"
#include "MantidAPI/WorkspaceGroup.h"
#include "MantidKernel/ArrayProperty.h"
#include "MantidParallel/Communicator.h"
#include "Poco/Glob.h"
namespace Mantid::Algorithms {
DECLARE_ALGORITHM(GroupWorkspaces)
using namespace API;
using namespace Kernel;
/// Initialisation method
void GroupWorkspaces::init() {
declareProperty(
std::make_unique<ArrayProperty<std::string>>("InputWorkspaces", std::make_shared<ADSValidator>(true, true)),
"Names of the Input Workspaces to Group");
declareProperty(std::make_unique<PropertyWithValue<std::string>>("GlobExpression", ""),
"Add all Workspaces that match Glob expression to Group");
declareProperty(std::make_unique<WorkspaceProperty<WorkspaceGroup>>("OutputWorkspace", "", Direction::Output),
"Name of the workspace to be created as the output of grouping ");
}
/** Executes the algorithm
* @throw std::runtime_error If the selected workspaces are not of same types
*/
void GroupWorkspaces::exec() {
const std::vector<std::string> inputWorkspaces = getProperty("InputWorkspaces");
const std::string globExpression = getProperty("GlobExpression");
// Clear WorkspaceGroup in case algorithm instance is reused.
m_group = nullptr;
if (!inputWorkspaces.empty())
addToGroup(inputWorkspaces);
if (!globExpression.empty())
addToGroup(globExpression);
if ((m_group == nullptr) || m_group->isEmpty())
throw std::invalid_argument("Glob pattern " + globExpression + " does not match any workspace names in the ADS.");
setProperty("OutputWorkspace", m_group);
auto ¬ifier = API::AnalysisDataService::Instance().notificationCenter;
notifier.postNotification(new WorkspacesGroupedNotification(inputWorkspaces));
}
std::map<std::string, std::string> GroupWorkspaces::validateInputs() {
std::map<std::string, std::string> results;
const std::vector<std::string> inputWorkspaces = getProperty("InputWorkspaces");
std::string globExpression = getProperty("GlobExpression");
std::string outputWorkspace = getProperty("OutputWorkspace");
// Peform a check that inputworkspaces cannot contain a workspace with the
// same name as the group/output workspace
for (const auto &ws : inputWorkspaces) {
if (ws == outputWorkspace) {
if (!AnalysisDataService::Instance().retrieve(ws)->isGroup())
results["OutputWorkspace"] = "The output workspace has the same name as "
"one of the input workspaces";
}
}
for (auto it = globExpression.begin(); it < globExpression.end(); ++it) {
if (*it == '\\') {
it = globExpression.erase(it, it + 1);
}
}
if (inputWorkspaces.empty() && globExpression.empty()) {
results["InputWorkspaces"] = "No InputWorkspace names specified. Rerun with a list of workspaces "
"names or a glob expression";
return results;
}
// ADSValidator already checks names in inputWorkspaces
if (!globExpression.empty()) {
// This is only a sanity check. If may fail to detect subtle errors in
// complex expressions.
if (globExpression.find_first_of("*?[]") == std::string::npos) {
results["GlobExpression"] = "Expression is expected to contain one or "
"more of the following characters: *?[";
return results;
}
if (std::count(globExpression.cbegin(), globExpression.cend(), '[') !=
std::count(globExpression.cbegin(), globExpression.cend(), ']')) {
results["GlobExpression"] = "Expression has a mismatched number of []";
return results;
}
}
return results;
}
/**
* Add a list of names to the new group
* @param globExpression glob pattern for selecting names from the ADS
*/
void GroupWorkspaces::addToGroup(const std::string &globExpression) {
Poco::Glob glob(globExpression);
const AnalysisDataServiceImpl &ads = AnalysisDataService::Instance();
const auto names = ads.topLevelItems();
for (const auto &name : names) {
if (glob.match(name.first)) {
addToGroup(name.second);
}
}
}
/**
* Add a list of names to the new group
* @param names The list of names to add from the ADS
*/
void GroupWorkspaces::addToGroup(const std::vector<std::string> &names) {
const AnalysisDataServiceImpl &ads = AnalysisDataService::Instance();
for (const auto &name : names) {
auto workspace = ads.retrieve(name);
addToGroup(workspace);
}
}
/**
* If it is a group it is unrolled and each member added
* @param workspace A pointer to the workspace to add
*/
void GroupWorkspaces::addToGroup(const API::Workspace_sptr &workspace) {
auto localGroup = std::dynamic_pointer_cast<WorkspaceGroup>(workspace);
if (localGroup) {
addToGroup(localGroup->getNames());
// Remove the group from the ADS
AnalysisDataService::Instance().remove(workspace->getName());
} else {
if (!m_group)
m_group = std::make_shared<WorkspaceGroup>(workspace->storageMode());
else if (communicator().size() != 1 && m_group->storageMode() != workspace->storageMode()) {
throw std::runtime_error("WorkspaceGroup with mixed Parallel::Storage mode is not supported.");
}
m_group->addWorkspace(workspace);
}
}
Parallel::ExecutionMode
GroupWorkspaces::getParallelExecutionMode(const std::map<std::string, Parallel::StorageMode> &storageModes) const {
static_cast<void>(storageModes);
const std::vector<std::string> names = getProperty("InputWorkspaces");
const auto ws = AnalysisDataService::Instance().retrieve(names.front());
return Parallel::getCorrespondingExecutionMode(ws->storageMode());
}
} // namespace Mantid::Algorithms