Mantid
Loading...
Searching...
No Matches
AnalysisDataService.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 +
9#include <iterator>
10#include <sstream>
11
12namespace Mantid::API {
13
14//-------------------------------------------------------------------------
15// Nested class methods
16//-------------------------------------------------------------------------
22 : DataServiceNotification(name, AnalysisDataService::Instance().retrieve(name)) {}
26std::shared_ptr<const WorkspaceGroup> AnalysisDataServiceImpl::GroupUpdatedNotification::getWorkspaceGroup() const {
27 return std::dynamic_pointer_cast<const WorkspaceGroup>(this->object());
28}
29
30//-------------------------------------------------------------------------
31// Public methods
32//-------------------------------------------------------------------------
40const std::string AnalysisDataServiceImpl::isValid(const std::string &name) const {
41 std::string error;
42 const std::string &illegal = illegalCharacters();
43 if (illegal.empty())
44 return error; // Quick route out.
45 const size_t length = name.size();
46 for (size_t i = 0; i < length; ++i) {
47 if (illegal.find_first_of(name[i]) != std::string::npos) {
48 std::ostringstream strm;
49 strm << "Invalid object name '" << name << "'. Names cannot contain any of the following characters: " << illegal;
50 error = strm.str();
51 break;
52 }
53 }
54 return error;
55}
56
66void AnalysisDataServiceImpl::add(const std::string &name, const std::shared_ptr<API::Workspace> &workspace) {
67 auto group = std::dynamic_pointer_cast<WorkspaceGroup>(workspace);
68 verifyName(name, group);
69
70 // Attach the name to the workspace
71 if (workspace)
72 workspace->setName(name);
74
75 // if a group is added add its members as well
76 if (!group)
77 return;
78
79 group->observeADSNotifications(true);
80 for (size_t i = 0; i < group->size(); ++i) {
81 auto ws = group->getItem(i);
82 std::string wsName = ws->getName();
83 // if anonymous make up a name and add
84 if (wsName.empty()) {
85 wsName = name + "_" + std::to_string(i + 1);
86 } else if (doesExist(wsName)) { // if ws is already there do nothing
87 wsName.clear();
88 }
89 // add member workspace if needed
90 if (!wsName.empty()) {
91 add(wsName, ws);
92 }
93 }
94}
95
104void AnalysisDataServiceImpl::addOrReplace(const std::string &name, const std::shared_ptr<API::Workspace> &workspace) {
105 auto group = std::dynamic_pointer_cast<WorkspaceGroup>(workspace);
106 verifyName(name, group);
107
108 // Attach the name to the workspace
109 if (workspace)
110 workspace->setName(name);
112
113 if (!group)
114 return;
115 group->observeADSNotifications(true);
116 for (size_t i = 0; i < group->size(); ++i) {
117 auto ws = group->getItem(i);
118 std::string wsName = ws->getName();
119 // make up a name for an anonymous workspace
120 if (wsName.empty()) {
121 wsName = name + "_" + std::to_string(i + 1);
122 } else if (doesExist(wsName)) { // if ws is already there do nothing
123 wsName.clear();
124 }
125 // add member workspace if needed
126 if (!wsName.empty()) {
127 addOrReplace(wsName, ws);
128 }
129 }
130}
131
138void AnalysisDataServiceImpl::rename(const std::string &oldName, const std::string &newName) {
139
140 auto oldWorkspace = retrieve(oldName);
141 auto group = std::dynamic_pointer_cast<WorkspaceGroup>(oldWorkspace);
142 if (group && group->containsInChildren(newName)) {
143 throw std::invalid_argument("Unable to rename group as the new name matches its members");
144 }
145
147 // Attach the new name to the workspace
148 auto ws = retrieve(newName);
149 ws->setName(newName);
150}
151
157void AnalysisDataServiceImpl::remove(const std::string &name) {
159 try {
160 ws = retrieve(name);
161 } catch (const Kernel::Exception::NotFoundError &) {
162 // do nothing - remove will do what's needed
163 }
165 if (ws) {
166 ws->setName("");
167 }
168}
169
180std::vector<Workspace_sptr> AnalysisDataServiceImpl::retrieveWorkspaces(const std::vector<std::string> &names,
181 bool unrollGroups) const {
182 using WorkspacesVector = std::vector<Workspace_sptr>;
183 WorkspacesVector workspaces;
184 workspaces.reserve(names.size());
185 std::transform(std::begin(names), std::end(names), std::back_inserter(workspaces),
186 [this](const std::string &name) { return this->retrieve(name); });
187 assert(names.size() == workspaces.size());
188 if (unrollGroups) {
189 using IteratorDifference = std::iterator_traits<WorkspacesVector::iterator>::difference_type;
190
191 bool done{workspaces.size() == 0};
192 size_t i{0};
193 while (!done) {
194 if (auto group = std::dynamic_pointer_cast<WorkspaceGroup>(workspaces.at(i))) {
195 const auto groupLength(group->size());
196 workspaces.erase(std::next(std::begin(workspaces), static_cast<IteratorDifference>(i)));
197 for (size_t j = 0; j < groupLength; ++j) {
198 workspaces.insert(std::next(std::begin(workspaces), static_cast<IteratorDifference>(i + j)),
199 group->getItem(j));
200 }
201 i += groupLength;
202 } else {
203 ++i;
204 }
205
206 if (i == workspaces.size()) {
207 done = true;
208 }
209 }
210 }
211 return workspaces;
212}
213
218void AnalysisDataServiceImpl::sortGroupByName(const std::string &groupName) {
219 WorkspaceGroup_sptr group = retrieveWS<WorkspaceGroup>(groupName);
220 if (!group) {
221 throw std::runtime_error("Workspace " + groupName + " is not a workspace group.");
222 }
223 group->sortMembersByName();
224 notificationCenter.postNotification(new GroupUpdatedNotification(groupName));
225}
226
232void AnalysisDataServiceImpl::addToGroup(const std::string &groupName, const std::string &wsName) {
233 WorkspaceGroup_sptr group = retrieveWS<WorkspaceGroup>(groupName);
234 if (!group) {
235 throw std::runtime_error("Workspace " + groupName + " is not a workspace group.");
236 }
237
238 if (groupName == wsName) {
239 throw std::runtime_error("The group name and workspace name are the same");
240 }
241
242 auto ws = retrieve(wsName);
243 group->addWorkspace(ws);
244 notificationCenter.postNotification(new GroupUpdatedNotification(groupName));
245}
246
251void AnalysisDataServiceImpl::deepRemoveGroup(const std::string &name) {
252 WorkspaceGroup_sptr group = retrieveWS<WorkspaceGroup>(name);
253 if (!group) {
254 throw std::runtime_error("Workspace " + name + " is not a workspace group.");
255 }
256 group->observeADSNotifications(false);
257 for (size_t i = 0; i < group->size(); ++i) {
258 auto ws = group->getItem(i);
259 WorkspaceGroup_sptr gws = std::dynamic_pointer_cast<WorkspaceGroup>(ws);
260 if (gws) {
261 // if a member is a group remove its items as well
262 deepRemoveGroup(gws->getName());
263 } else {
264 remove(ws->getName());
265 }
266 }
267 remove(name);
268}
269
276void AnalysisDataServiceImpl::removeFromGroup(const std::string &groupName, const std::string &wsName) {
277 WorkspaceGroup_sptr group = retrieveWS<WorkspaceGroup>(groupName);
278 if (!group) {
279 throw std::runtime_error("Workspace " + groupName + " is not a workspace group.");
280 }
281 if (!group->contains(wsName)) {
282 throw std::runtime_error("WorkspaceGroup " + groupName + " does not containt workspace " + wsName);
283 }
284 group->removeByADS(wsName);
285 notificationCenter.postNotification(new GroupUpdatedNotification(groupName));
286}
287
293std::map<std::string, Workspace_sptr> AnalysisDataServiceImpl::topLevelItems() const {
294 std::map<std::string, Workspace_sptr> topLevel;
295 auto topLevelNames = this->getObjectNames();
296 std::set<Workspace_sptr> groupMembers;
297
298 for (const auto &topLevelName : topLevelNames) {
299 try {
300 const std::string &name = topLevelName;
301 auto ws = this->retrieve(topLevelName);
302 topLevel.emplace(name, ws);
303 if (auto group = std::dynamic_pointer_cast<WorkspaceGroup>(ws)) {
304 group->reportMembers(groupMembers);
305 }
306 } catch (const std::exception &) {
307 }
308 }
309
310 // Prune members
311 for (auto it = topLevel.begin(); it != topLevel.end();) {
312 const Workspace_sptr &item = it->second;
313 if (groupMembers.count(item) == 1) {
314 topLevel.erase(it++);
315 } else {
316 ++it;
317 }
318 }
319
320 return topLevel;
321}
322
324
325//-------------------------------------------------------------------------
326// Private methods
327//-------------------------------------------------------------------------
328
333 : Mantid::Kernel::DataService<Mantid::API::Workspace>("AnalysisDataService"), m_illegalChars() {}
334
335// The following is commented using /// rather than /** to stop the compiler
336// complaining
337// about the special characters in the comment fields.
342const std::string &AnalysisDataServiceImpl::illegalCharacters() const { return m_illegalChars; }
343
350void AnalysisDataServiceImpl::setIllegalCharacterList(const std::string &illegalChars) {
351 m_illegalChars = illegalChars;
352}
353
363void AnalysisDataServiceImpl::verifyName(const std::string &name, const std::shared_ptr<API::WorkspaceGroup> &group) {
364 const std::string error = isValid(name);
365 if (!error.empty()) {
366 throw std::invalid_argument(error);
367 }
368
369 if (group && group->containsInChildren(name)) {
370 throw std::invalid_argument("Unable to add group as name matches its members");
371 }
372}
373
374} // namespace Mantid::API
double error
Definition: IndexPeaks.cpp:133
IPeaksWorkspace_sptr workspace
Definition: IndexPeaks.cpp:114
GroupWorkspaces notification is send when a group is updated by adding or removing members.
std::shared_ptr< const WorkspaceGroup > getWorkspaceGroup() const
Returns the workspace pointer cast to WorkspaceGroup.
const std::string isValid(const std::string &name) const
Is the given name a valid name for an object in the ADS.
void setIllegalCharacterList(const std::string &)
Set the list of illegal characters.
std::string m_illegalChars
The string of illegal characters.
const std::string & illegalCharacters() const
Return the list of illegal characters as one string.
virtual void rename(const std::string &oldName, const std::string &newName)
Overridden rename member to attach the new name to the workspace when a workspace object is renamed.
void add(const std::string &name, const std::shared_ptr< API::Workspace > &workspace) override
Overridden add member to attach the name to the workspace when a workspace object is added to the ser...
std::map< std::string, Workspace_sptr > topLevelItems() const
Return a lookup of the top level items.
void shutdown() override
Prepare for shutdown.
void sortGroupByName(const std::string &groupName)
Sort members by Workspace name.
void deepRemoveGroup(const std::string &name)
Remove a workspace group and all its members from the ADS.
virtual void remove(const std::string &name)
Overridden remove member to delete its name held by the workspace itself.
void addOrReplace(const std::string &name, const std::shared_ptr< API::Workspace > &workspace) override
Overridden addOrReplace member to attach the name to the workspace when a workspace object is added t...
void addToGroup(const std::string &groupName, const std::string &wsName)
Add a workspace to a group.
void verifyName(const std::string &name, const std::shared_ptr< API::WorkspaceGroup > &workspace)
Checks the name is valid, throwing if not.
std::vector< Workspace_sptr > retrieveWorkspaces(const std::vector< std::string > &names, bool unrollGroups=false) const
Given a list of names retrieve the corresponding workspace handles.
void removeFromGroup(const std::string &groupName, const std::string &wsName)
Remove a workspace from a group but not from the ADS.
Base Workspace Abstract Class.
Definition: Workspace.h:30
DataService stores instances of a given type.
Definition: DataService.h:58
virtual void add(const std::string &name, const std::shared_ptr< T > &Tobject)
Add an object to the service.
Definition: DataService.h:190
bool doesExist(const std::string &name) const
Check to see if a data object exists in the store.
Definition: DataService.h:370
void rename(const std::string &oldName, const std::string &newName)
Rename an object within the service.
Definition: DataService.h:281
std::vector< std::string > getObjectNames(DataServiceSort sortState=DataServiceSort::Unsorted, DataServiceHidden hiddenState=DataServiceHidden::Auto, const std::string &contain="") const
Returns a vector of strings containing all object names in the ADS.
Definition: DataService.h:398
std::shared_ptr< API::Workspace > retrieve(const std::string &name) const
Get a shared pointer to a stored data object.
Definition: DataService.h:350
virtual void addOrReplace(const std::string &name, const std::shared_ptr< T > &Tobject)
Add or replace an object to the service.
Definition: DataService.h:222
Poco::NotificationCenter notificationCenter
Sends notifications to observers.
Definition: DataService.h:484
void remove(const std::string &name)
Remove an object from the service.
Definition: DataService.h:251
Exception for when an item is not found in a collection.
Definition: Exception.h:145
Manage the lifetime of a class intended to be a singleton.
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
Helper class which provides the Collimation Length for SANS instruments.
std::string to_string(const wide_integer< Bits, Signed > &n)