Mantid
Loading...
Searching...
No Matches
WorkspaceProperty.hxx
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 +
14
15#include <boost/algorithm/string/trim.hpp>
16
17#include <json/value.h>
18
19namespace Mantid {
20namespace API {
21
33template <typename TYPE>
34WorkspaceProperty<TYPE>::WorkspaceProperty(const std::string &name, const std::string &wsName,
35 const unsigned int direction, const Kernel::IValidator_sptr &validator)
36 : Kernel::PropertyWithValue<std::shared_ptr<TYPE>>(name, std::shared_ptr<TYPE>(), validator, direction),
37 m_workspaceName(wsName), m_initialWSName(wsName), m_optional(PropertyMode::Mandatory), m_locking(LockMode::Lock) {
38}
39
52template <typename TYPE>
53WorkspaceProperty<TYPE>::WorkspaceProperty(const std::string &name, const std::string &wsName,
54 const unsigned int direction, const PropertyMode::Type optional,
55 const Kernel::IValidator_sptr &validator)
56 : Kernel::PropertyWithValue<std::shared_ptr<TYPE>>(name, std::shared_ptr<TYPE>(), validator, direction),
57 m_workspaceName(wsName), m_initialWSName(wsName), m_optional(optional), m_locking(LockMode::Lock) {}
58
75template <typename TYPE>
76WorkspaceProperty<TYPE>::WorkspaceProperty(const std::string &name, const std::string &wsName,
77 const unsigned int direction, const PropertyMode::Type optional,
78 const LockMode::Type locking, const Kernel::IValidator_sptr &validator)
79 : Kernel::PropertyWithValue<std::shared_ptr<TYPE>>(name, std::shared_ptr<TYPE>(), validator, direction),
80 m_workspaceName(wsName), m_initialWSName(wsName), m_optional(optional), m_locking(locking) {}
81
84template <typename TYPE>
86 : Kernel::PropertyWithValue<std::shared_ptr<TYPE>>(right), m_workspaceName(right.m_workspaceName),
87 m_initialWSName(right.m_initialWSName), m_optional(right.m_optional), m_locking(right.m_locking) {}
88
92 if (&right == this)
93 return *this;
95 return *this;
96}
97
103template <typename TYPE>
105 std::string wsName = value->getName();
106 if (this->direction() == Kernel::Direction::Input && !wsName.empty()) {
107 m_workspaceName = wsName;
108 }
110 return *this;
111}
112
113//--------------------------------------------------------------------------------------
116 throw Kernel::Exception::NotImplementedError("+= operator is not implemented for WorkspaceProperty.");
117}
118
121 return new WorkspaceProperty<TYPE>(*this);
122}
123
127template <typename TYPE> std::string WorkspaceProperty<TYPE>::value() const { return m_workspaceName; }
128
132template <typename TYPE> Json::Value WorkspaceProperty<TYPE>::valueAsJson() const { return Json::Value(value()); }
133
137template <typename TYPE> bool WorkspaceProperty<TYPE>::isValueSerializable() const {
138 return !m_workspaceName.empty() || !this->m_value;
139}
140
144template <typename TYPE> std::string WorkspaceProperty<TYPE>::getDefault() const { return m_initialWSName; }
145
152template <typename TYPE> std::string WorkspaceProperty<TYPE>::setValue(const std::string &value) {
153 m_workspaceName = value;
154 if (Kernel::PropertyWithValue<std::shared_ptr<TYPE>>::autoTrim()) {
155 boost::trim(m_workspaceName);
156 }
157 retrieveWorkspaceFromADS();
158 return isValid();
159}
160
168template <typename TYPE> std::string WorkspaceProperty<TYPE>::setValueFromJson(const Json::Value &value) {
169 try {
170 return setValue(value.asString());
171 } catch (std::exception &exc) {
172 return exc.what();
173 }
174}
175
181template <typename TYPE>
182std::string WorkspaceProperty<TYPE>::setDataItem(const std::shared_ptr<Kernel::DataItem> &value) {
183 std::shared_ptr<TYPE> typed = std::dynamic_pointer_cast<TYPE>(value);
184 if (typed) {
185 if (typed->getName().empty() && this->direction() == Kernel::Direction::Output) {
186 typed->setPythonVariableName(m_workspaceName);
187 }
188 if (this->direction() == Kernel::Direction::Input) {
189 m_workspaceName = typed->getName();
190 }
192 } else {
193 this->clear();
194 }
195 return isValid();
196}
197
201template <typename TYPE> void WorkspaceProperty<TYPE>::setPropertyMode(const PropertyMode::Type &optional) {
202 m_optional = optional;
203}
204
212template <typename TYPE> std::string WorkspaceProperty<TYPE>::isValid() const {
213
214 // If an output workspace it must have a name, although it might not exist
215 // in the ADS yet
216 if (this->direction() == Kernel::Direction::Output) {
217 return isValidOutputWs();
218 }
219
220 // If an input (or inout) workspace, must point to something, although it
221 // doesn't have to have a name
222 // unless it's optional
223 if (this->direction() == Kernel::Direction::Input || this->direction() == Kernel::Direction::InOut) {
224 // Workspace groups will not have a value since they are not of type TYPE
225 if (!Kernel::PropertyWithValue<std::shared_ptr<TYPE>>::m_value) {
227 // if the workspace name is empty then there is no point asking the ADS
228 if (m_workspaceName.empty()) {
229 return isOptionalWs();
230 }
231
232 try {
233 wksp = AnalysisDataService::Instance().retrieve(m_workspaceName);
235 return isOptionalWs();
236 }
237
238 // At this point we have a valid pointer to a Workspace so we need to
239 // test whether it is a group
240 if (std::dynamic_pointer_cast<Mantid::API::WorkspaceGroup>(wksp)) {
241 return isValidGroup(std::dynamic_pointer_cast<Mantid::API::WorkspaceGroup>(wksp));
242 }
243
244 std::string error = "Workspace " + this->value() + " is not of the correct type";
245 return error;
246 }
247 }
248 // Call superclass method to access any attached validators (which do their
249 // own logging)
251}
252
257template <typename TYPE> bool WorkspaceProperty<TYPE>::isDefault() const {
258 if (m_initialWSName.empty()) {
259 return m_workspaceName.empty() && !this->m_value;
260 }
261 return m_initialWSName == m_workspaceName;
262}
263
266template <typename TYPE> bool WorkspaceProperty<TYPE>::isOptional() const {
267 return (m_optional == PropertyMode::Optional);
268}
271template <typename TYPE> bool WorkspaceProperty<TYPE>::isLocking() const { return (m_locking == LockMode::Lock); }
272
278template <typename TYPE> std::vector<std::string> WorkspaceProperty<TYPE>::allowedValues() const {
279 if (this->direction() == Kernel::Direction::Input || this->direction() == Kernel::Direction::InOut) {
280 // If an input workspace, get the list of workspaces currently in the ADS
281 auto vals = AnalysisDataService::Instance().getObjectNames(Mantid::Kernel::DataServiceSort::Sorted);
282 if (isOptional()) // Insert an empty option
283 {
284 vals.emplace_back("");
285 }
286 // Copy-construct a temporary workspace property to test the validity of
287 // each workspace
288 WorkspaceProperty<TYPE> tester(*this);
289
290 // Remove any workspace that's not valid for this algorithm
291 auto eraseIter = remove_if(vals.begin(), vals.end(),
292 [&tester](const std::string &wsName) { return !tester.setValue(wsName).empty(); });
293 // Erase everything past returned iterator afterwards for readability
294 vals.erase(eraseIter, vals.end());
295 return vals;
296 } else {
297 // For output workspaces, just return an empty set
298 return std::vector<std::string>();
299 }
300}
301
305 std::string wsName = m_workspaceName;
306 bool isdefault = this->isDefault();
307 bool pythonVariable = false;
308
309 if ((wsName.empty() || this->hasTemporaryValue()) && this->operator()()) {
310 const auto pvName = Kernel::PropertyWithValue<std::shared_ptr<TYPE>>::m_value->getPythonVariableName();
311 pythonVariable = !pvName.empty();
312 if (pythonVariable) {
313 wsName = pvName;
314 } else {
315 // give the property a temporary name in the history
316 std::ostringstream os;
317 os << "__TMP" << this->operator()().get();
318 wsName = os.str();
319 }
320 isdefault = false;
321 }
322 return Kernel::PropertyHistory(this->name(), wsName, this->type(), isdefault, this->direction(), pythonVariable);
323}
324
329template <typename TYPE> bool WorkspaceProperty<TYPE>::store() {
330 bool result = false;
331 if (!this->operator()() && isOptional())
332 return result;
333 if (this->direction()) // Output or InOut
334 {
335 // Check that workspace exists
336 if (this->operator()()) {
337 // Note use of addOrReplace rather than add
338 API::AnalysisDataService::Instance().addOrReplace(m_workspaceName, this->operator()());
339 } else {
340 throw std::runtime_error("WorkspaceProperty doesn't point to a workspace");
341 }
342 result = true;
343 }
344 // always clear the internal pointer after storing
345 clear();
346
347 return result;
348}
349
350template <typename TYPE> Workspace_sptr WorkspaceProperty<TYPE>::getWorkspace() const { return this->operator()(); }
351
357template <typename TYPE>
358std::string WorkspaceProperty<TYPE>::isValidGroup(const std::shared_ptr<WorkspaceGroup> &wsGroup) const {
359 g_log.debug() << " Input WorkspaceGroup found \n";
360
361 std::vector<std::string> wsGroupNames = wsGroup->getNames();
362 std::string error;
363
364 // Cycle through each workspace in the group ...
365 for (const auto &memberWsName : wsGroupNames) {
366 std::shared_ptr<Workspace> memberWs = AnalysisDataService::Instance().retrieve(memberWsName);
367
368 // Table Workspaces are ignored
369 if ("TableWorkspace" == memberWs->id()) {
370 error = "Workspace " + memberWsName +
371 " is of type TableWorkspace and "
372 "will therefore be ignored as "
373 "part of the GroupedWorkspace.";
374
375 g_log.debug() << error << '\n';
376 } else {
377 // ... and if it is a workspace of incorrect type, exclude the group by
378 // returning an error.
379 if (!std::dynamic_pointer_cast<TYPE>(memberWs)) {
380 error = "Workspace " + memberWsName + " is not of type " +
382
383 g_log.debug() << error << '\n';
384
385 return error;
386 }
387 // If it is of the correct type, it may still be invalid. Check.
388 else {
389 Mantid::API::WorkspaceProperty<TYPE> memberWsProperty(*this);
390 std::string memberError = memberWsProperty.setValue(memberWsName);
391 if (!memberError.empty())
392 return memberError; // Since if this member is invalid, then the
393 // whole group is invalid.
394 }
395 }
396 }
397
398 return ""; // Since all members of the group are valid.
399}
400
406template <typename TYPE> std::string WorkspaceProperty<TYPE>::isValidOutputWs() const {
407 std::string error;
408 const std::string workspaceName = this->value();
409 if (!workspaceName.empty()) {
410 // Will the ADS accept it
411 error = AnalysisDataService::Instance().isValid(workspaceName);
412 } else {
413 if (isOptional())
414 error = ""; // Optional ones don't need a name
415 else
416 error = "Enter a name for the Output workspace";
417 }
418 return error;
419}
420
426template <typename TYPE> std::string WorkspaceProperty<TYPE>::isOptionalWs() const {
427 std::string error;
428
429 if (m_workspaceName.empty()) {
430 if (isOptional()) {
431 error = "";
432 } else {
433 error = "Enter a name for the Input/InOut workspace";
434 }
435 } else {
436 error = "Workspace \"" + this->value() + "\" was not found in the Analysis Data Service";
437 }
438
439 return error;
440}
441
443template <typename TYPE> void WorkspaceProperty<TYPE>::clear() {
445}
446
451 // Try and get the workspace from the ADS, but don't worry if we can't
452 try {
454 AnalysisDataService::Instance().retrieveWS<TYPE>(m_workspaceName);
456 // Set to null property if not found
457 this->clear();
458 }
459}
460
461} // namespace API
462} // namespace Mantid
const std::string & m_value
Definition Algorithm.cpp:71
std::string name
Definition Run.cpp:60
double value
The value of the point.
Definition FitMW.cpp:51
double error
double right
A property class for workspaces.
std::string value() const override
Get the name of the workspace.
std::string setDataItem(const std::shared_ptr< Kernel::DataItem > &value) override
Set a value from a data item.
void setPropertyMode(const PropertyMode::Type &optional) override
Set the property mode of the property e.g.
std::string isOptionalWs() const
Checks whether the entered workspace (that by this point we've found is not in the ADS) is actually a...
std::string setValue(const std::string &value) override
Set the name of the workspace.
bool isLocking() const override
Does the workspace need to be locked before starting an algorithm?
std::string isValidGroup(const std::shared_ptr< WorkspaceGroup > &wsGroup) const
Checks whether the entered workspace group is valid.
WorkspaceProperty< TYPE > * clone() const override
'Virtual copy constructor'
Workspace_sptr getWorkspace() const override
Get a pointer to the workspace.
WorkspaceProperty & operator+=(Kernel::Property const *) override
Add the value of another property.
Json::Value valueAsJson() const override
std::string isValidOutputWs() const
Checks whether the entered output workspace is valid.
void retrieveWorkspaceFromADS()
Attempts to retreive the data from the ADS if the data is not foung the internal pointer is set to nu...
std::string setValueFromJson(const Json::Value &value) override
Set the name of the workspace from a Json::Value object Also tries to retrieve it from the AnalysisDa...
bool isOptional() const override
Is the workspace property optional.
std::string getDefault() const override
Get the value the property was initialised with -its default value.
std::string isValid() const override
Checks whether the entered workspace is valid.
bool isValueSerializable() const override
Returns true if the workspace is in the ADS or there is none.
const Kernel::PropertyHistory createHistory() const override
Create a history record.
void clear() override
Reset the pointer to the workspace.
WorkspaceProperty(const std::string &name, const std::string &wsName, const unsigned int direction, const Kernel::IValidator_sptr &validator=Kernel::IValidator_sptr(new Kernel::NullValidator))
Constructor.
bool isDefault() const override
Indicates if the object is still pointing to the same workspace.
std::vector< std::string > allowedValues() const override
Returns the current contents of the AnalysisDataService for input workspaces.
WorkspaceProperty & operator=(const WorkspaceProperty &right)
Copy assignment operator.
bool store() override
If this is an output workspace, store it into the AnalysisDataService.
Exception for when an item is not found in a collection.
Definition Exception.h:145
Marks code as not implemented yet.
Definition Exception.h:138
void debug(const std::string &msg)
Logs at debug level.
Definition Logger.cpp:145
This class stores information about the parameters used by an algorithm.
The concrete, templated class for properties.
Base class for properties.
Definition Property.h:94
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
Kernel::Logger g_log("ExperimentInfo")
static logger object
std::shared_ptr< IValidator > IValidator_sptr
A shared_ptr to an IValidator.
Definition IValidator.h:26
Helper class which provides the Collimation Length for SANS instruments.
STL namespace.
Enumeration for locking behaviour.
Enumeration for a mandatory/optional property.
@ InOut
Both an input & output workspace.
Definition Property.h:55
@ Input
An input workspace.
Definition Property.h:53
@ Output
An output workspace.
Definition Property.h:54