Skip to content

Commit 28243b0

Browse files
Merge pull request #37839 from mantidproject/33252_storeInADS_preserved_in_alg_history
storeInADS preserved in algorithm history and recreated correctly by script builder
2 parents bfc3d0f + 41ccc1c commit 28243b0

File tree

14 files changed

+135
-34
lines changed

14 files changed

+135
-34
lines changed

Framework/API/inc/MantidAPI/AlgorithmHistory.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ class MANTID_API_DLL AlgorithmHistory {
8080
const AlgorithmHistories &getChildHistories() const { return m_childHistories; }
8181
/// Retrieve a child algorithm history by index
8282
AlgorithmHistory_sptr getChildAlgorithmHistory(const size_t index) const;
83+
/// get storeInADS
84+
const bool &getStoreInADS() const { return m_storeInADS; }
8385
/// Add operator[] access
8486
AlgorithmHistory_sptr operator[](const size_t index) const;
8587
/// Retrieve the number of child algorithms
@@ -128,6 +130,8 @@ class MANTID_API_DLL AlgorithmHistory {
128130
AlgorithmHistories m_childHistories;
129131
/// UUID for this algorithm history
130132
std::string m_uuid;
133+
/// If algorithm was set to store workspaces in the ADS
134+
bool m_storeInADS{true};
131135
};
132136

133137
MANTID_API_DLL std::ostream &operator<<(std::ostream &, const AlgorithmHistory &);

Framework/API/inc/MantidAPI/Workspace.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,11 @@ class MANTID_API_DLL Workspace : public Kernel::DataItem {
6767

6868
void virtual setTitle(const std::string &);
6969
void setComment(const std::string &);
70+
void setPythonVariableName(const std::string &);
7071
virtual const std::string getTitle() const;
7172
const std::string &getComment() const;
7273
const std::string &getName() const override;
74+
const std::string &getPythonVariableName() const;
7375
bool isDirty(const int n = 1) const;
7476
virtual bool isGroup() const { return false; }
7577
/// Get the footprint in memory in bytes.
@@ -95,6 +97,8 @@ class MANTID_API_DLL Workspace : public Kernel::DataItem {
9597
/// The name associated with the object within the ADS (This is required for
9698
/// workspace algebra
9799
std::string m_name;
100+
/// The name of the variable holding the workspace, if not stored in the ADS
101+
std::string m_pythonVariableName;
98102
/// The history of the workspace, algorithm and environment
99103
std::unique_ptr<WorkspaceHistory> m_history;
100104

Framework/API/inc/MantidAPI/WorkspaceProperty.tcc

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,9 @@ template <typename TYPE>
180180
std::string WorkspaceProperty<TYPE>::setDataItem(const std::shared_ptr<Kernel::DataItem> &value) {
181181
std::shared_ptr<TYPE> typed = std::dynamic_pointer_cast<TYPE>(value);
182182
if (typed) {
183+
if (typed->getName().empty() && this->direction() == Kernel::Direction::Output) {
184+
typed->setPythonVariableName(m_workspaceName);
185+
}
183186
if (this->direction() == Kernel::Direction::Input) {
184187
m_workspaceName = typed->getName();
185188
}
@@ -299,15 +302,22 @@ template <typename TYPE> std::vector<std::string> WorkspaceProperty<TYPE>::allow
299302
template <typename TYPE> const Kernel::PropertyHistory WorkspaceProperty<TYPE>::createHistory() const {
300303
std::string wsName = m_workspaceName;
301304
bool isdefault = this->isDefault();
305+
bool pythonVariable = false;
302306

303307
if ((wsName.empty() || this->hasTemporaryValue()) && this->operator()()) {
304-
// give the property a temporary name in the history
305-
std::ostringstream os;
306-
os << "__TMP" << this->operator()().get();
307-
wsName = os.str();
308+
const auto pvName = Kernel::PropertyWithValue<std::shared_ptr<TYPE>>::m_value->getPythonVariableName();
309+
pythonVariable = !pvName.empty();
310+
if (pythonVariable) {
311+
wsName = pvName;
312+
} else {
313+
// give the property a temporary name in the history
314+
std::ostringstream os;
315+
os << "__TMP" << this->operator()().get();
316+
wsName = os.str();
317+
}
308318
isdefault = false;
309319
}
310-
return Kernel::PropertyHistory(this->name(), wsName, this->type(), isdefault, this->direction());
320+
return Kernel::PropertyHistory(this->name(), wsName, this->type(), isdefault, this->direction(), pythonVariable);
311321
}
312322

313323
/** If this is an output workspace, store it into the AnalysisDataService

Framework/API/src/AlgorithmHistory.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ static boost::uuids::random_generator uuidGen;
5151
AlgorithmHistory::AlgorithmHistory(const Algorithm *const alg, const Types::Core::DateAndTime &start,
5252
const double &duration, std::size_t uexeccount)
5353
: m_name(alg->name()), m_version(alg->version()), m_executionDate(start), m_executionDuration(duration),
54-
m_execCount(uexeccount), m_childHistories() {
54+
m_execCount(uexeccount), m_childHistories(), m_storeInADS(alg->getAlwaysStoreInADS()) {
5555
// Now go through the algorithm's properties and create the PropertyHistory
5656
// objects.
5757
setProperties(alg);
@@ -109,6 +109,7 @@ void AlgorithmHistory::fillAlgorithmHistory(const Algorithm *const alg, const Ty
109109
m_executionDate = start;
110110
m_executionDuration = duration;
111111
m_execCount = uexeccount;
112+
m_storeInADS = alg->getAlwaysStoreInADS();
112113
setProperties(alg);
113114
}
114115

@@ -234,11 +235,13 @@ AlgorithmHistory &AlgorithmHistory::operator=(const AlgorithmHistory &A) {
234235
m_executionDate = A.m_executionDate;
235236
m_executionDuration = A.m_executionDuration;
236237
m_properties = A.m_properties;
238+
m_storeInADS = A.m_storeInADS;
237239
// required to prevent destruction of descendant if assigning a descendant
238240
// to an ancestor
239241
auto temp = A.m_childHistories;
240242
m_childHistories = temp;
241243
m_uuid = A.m_uuid;
244+
m_execCount = A.m_execCount;
242245
}
243246
return *this;
244247
}
@@ -271,7 +274,7 @@ void AlgorithmHistory::saveNexus(::NeXus::File *file, int &algCount) const {
271274
file->writeData("data", algData.str());
272275

273276
// child algorithms
274-
for (auto &history : m_childHistories) {
277+
for (const auto &history : m_childHistories) {
275278
history->saveNexus(file, algCount);
276279
}
277280
file->closeGroup();

Framework/API/src/ScriptBuilder.cpp

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,12 @@ const std::string ScriptBuilder::buildAlgorithmString(const AlgorithmHistory &al
206206
g_log.error() << "Could not create a fresh version of " << name << " version " << algHistory.version() << "\n";
207207
}
208208

209-
for (auto &propIter : props) {
209+
const bool storeInADS = algHistory.getStoreInADS();
210+
211+
for (const auto &propIter : props) {
212+
if (!storeInADS && propIter->name() == "OutputWorkspace") {
213+
continue;
214+
}
210215
std::string prop = buildPropertyString(*propIter, name);
211216
if (prop.length() > 0) {
212217
properties << prop << ", ";
@@ -233,14 +238,24 @@ const std::string ScriptBuilder::buildAlgorithmString(const AlgorithmHistory &al
233238
}
234239
// Third case is we never specify the version, so do nothing.
235240

241+
std::string assignmentStatement("");
242+
if (!storeInADS) {
243+
properties << "StoreInADS=False, ";
244+
const auto it =
245+
std::find_if(props.cbegin(), props.cend(), [](const auto &prop) { return prop->name() == "OutputWorkspace"; });
246+
if (it != props.cend()) {
247+
assignmentStatement = (*it)->value() + " = ";
248+
}
249+
}
250+
236251
std::string propStr = properties.str();
237252
if (propStr.length() > 0) {
238253
// remove trailing comma & space
239254
propStr.erase(propStr.size() - 1);
240255
propStr.erase(propStr.size() - 1);
241256
}
242257

243-
std::string historyEntry = name + "(" + propStr + ")";
258+
std::string historyEntry = assignmentStatement + name + "(" + propStr + ")";
244259
historyEntry.erase(boost::remove_if(historyEntry, boost::is_any_of("\n\r")), historyEntry.end());
245260
return historyEntry;
246261
}
@@ -286,11 +301,15 @@ const std::string ScriptBuilder::buildPropertyString(const Mantid::Kernel::Prope
286301
// Handle all other property types
287302
} else {
288303
std::string opener = "='";
304+
std::string closer = "'";
289305
if (propHistory.value().find('\\') != std::string::npos) {
290306
opener = "=r'";
307+
} else if (propHistory.pythonVariable()) {
308+
opener = "=";
309+
closer = "";
291310
}
292311

293-
prop = propHistory.name() + opener + propHistory.value() + "'";
312+
prop = propHistory.name() + opener + propHistory.value() + closer;
294313
}
295314
}
296315

Framework/API/src/Workspace.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ void Workspace::setComment(const std::string &c) { m_comment = c; }
3838
*/
3939
void Workspace::setName(const std::string &name) { m_name = name; }
4040

41+
void Workspace::setPythonVariableName(const std::string &name) { m_pythonVariableName = name; }
42+
4143
/** Get the workspace title
4244
*
4345
* @return The title
@@ -56,6 +58,8 @@ const std::string &Workspace::getComment() const { return m_comment; }
5658
*/
5759
const std::string &Workspace::getName() const { return m_name; }
5860

61+
const std::string &Workspace::getPythonVariableName() const { return m_pythonVariableName; }
62+
5963
/**
6064
* Check whether other algorithms have been applied to the
6165
* workspace by checking the history length.
@@ -96,7 +100,7 @@ IPropertyManager::getValue<Mantid::API::Workspace_sptr>(const std::string &name)
96100
template <>
97101
MANTID_API_DLL Mantid::API::Workspace_const_sptr
98102
IPropertyManager::getValue<Mantid::API::Workspace_const_sptr>(const std::string &name) const {
99-
auto *prop = dynamic_cast<PropertyWithValue<Mantid::API::Workspace_sptr> *>(getPointerToProperty(name));
103+
const auto *prop = dynamic_cast<PropertyWithValue<Mantid::API::Workspace_sptr> *>(getPointerToProperty(name));
100104
if (prop) {
101105
return prop->operator()();
102106
} else {

Framework/API/test/ScriptBuilderTest.h

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -372,13 +372,13 @@ class ScriptBuilderTest : public CxxTest::TestSuite {
372372
"# Child algorithms of TopLevelAlgorithm",
373373
"",
374374
"## Child algorithms of NestedAlgorithm",
375-
"BasicAlgorithm(PropertyA='FirstOne')",
376-
"BasicAlgorithm(PropertyA='SecondOne')",
375+
"BasicAlgorithm(PropertyA='FirstOne', StoreInADS=False)",
376+
"BasicAlgorithm(PropertyA='SecondOne', StoreInADS=False)",
377377
"## End of child algorithms of NestedAlgorithm",
378378
"",
379379
"## Child algorithms of NestedAlgorithm",
380-
"BasicAlgorithm(PropertyA='FirstOne')",
381-
"BasicAlgorithm(PropertyA='SecondOne')",
380+
"BasicAlgorithm(PropertyA='FirstOne', StoreInADS=False)",
381+
"BasicAlgorithm(PropertyA='SecondOne', StoreInADS=False)",
382382
"## End of child algorithms of NestedAlgorithm",
383383
"",
384384
"# End of child algorithms of TopLevelAlgorithm",
@@ -419,16 +419,16 @@ class ScriptBuilderTest : public CxxTest::TestSuite {
419419
"# Child algorithms of TopLevelAlgorithm",
420420
"",
421421
"## Child algorithms of NestedAlgorithm",
422-
"BasicAlgorithm(PropertyA='FirstOne')",
423-
"BasicAlgorithm(PropertyA='SecondOne')",
422+
"BasicAlgorithm(PropertyA='FirstOne', StoreInADS=False)",
423+
"BasicAlgorithm(PropertyA='SecondOne', StoreInADS=False)",
424424
"## End of child algorithms of NestedAlgorithm",
425425
"",
426-
"NestedAlgorithm()",
426+
"NestedAlgorithm(StoreInADS=False)",
427427
"# End of child algorithms of TopLevelAlgorithm",
428428
"",
429429
"# Child algorithms of TopLevelAlgorithm",
430-
"NestedAlgorithm()",
431-
"NestedAlgorithm()",
430+
"NestedAlgorithm(StoreInADS=False)",
431+
"NestedAlgorithm(StoreInADS=False)",
432432
"# End of child algorithms of TopLevelAlgorithm",
433433
"",
434434
"",
@@ -604,6 +604,41 @@ class ScriptBuilderTest : public CxxTest::TestSuite {
604604
m_ads.remove("IRS21360");
605605
}
606606

607+
void test_ScriptBuilderWithOutputWorkspaceOutsideOfADS() {
608+
std::vector<double> xData = {1, 2, 3};
609+
std::vector<double> yData = {1, 2, 3};
610+
611+
auto createWorkspaceAlg = m_algFactory.create("CreateWorkspace", 1);
612+
createWorkspaceAlg->initialize();
613+
createWorkspaceAlg->setProperty("DataX", xData);
614+
createWorkspaceAlg->setProperty("DataY", yData);
615+
createWorkspaceAlg->setProperty("OutputWorkspace", "ws");
616+
createWorkspaceAlg->setAlwaysStoreInADS(false);
617+
createWorkspaceAlg->execute();
618+
619+
MatrixWorkspace_sptr ws = createWorkspaceAlg->getProperty("OutputWorkspace");
620+
std::vector<double> params = {1, 3, 10};
621+
auto rebinAlg = m_algFactory.create("Rebin", 1);
622+
rebinAlg->initialize();
623+
rebinAlg->setProperty("InputWorkspace", ws);
624+
rebinAlg->setProperty("Params", params);
625+
rebinAlg->setProperty("Power", 0.5);
626+
rebinAlg->setProperty("OutputWorkspace", "result");
627+
rebinAlg->execute();
628+
629+
auto resultWs = m_ads.retrieveWS<MatrixWorkspace>("result");
630+
auto wsHist = resultWs->getHistory();
631+
632+
ScriptBuilder builder(wsHist.createView());
633+
const std::string scriptText = builder.build();
634+
const std::string expectedCreateWorkspaceLine =
635+
"ws = CreateWorkspace(DataX='1,2,3', DataY='1,2,3', StoreInADS=False)";
636+
const std::string expectedRebinLine =
637+
"Rebin(InputWorkspace=ws, OutputWorkspace='result', Params='1,3,10', Power=0.5)";
638+
TS_ASSERT(scriptText.find(expectedCreateWorkspaceLine) != std::string::npos);
639+
TS_ASSERT(scriptText.find(expectedRebinLine) != std::string::npos);
640+
}
641+
607642
private:
608643
AlgorithmFactoryImpl &m_algFactory;
609644
AnalysisDataServiceImpl &m_ads;

Framework/Kernel/inc/MantidKernel/PropertyHistory.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class Property;
3434
class MANTID_KERNEL_DLL PropertyHistory {
3535
public:
3636
PropertyHistory(std::string name, std::string value, std::string type, const bool isdefault,
37-
const unsigned int direction = 99);
37+
const unsigned int direction = 99, const bool pythonVariable = false);
3838

3939
/// construct a property history from a property object
4040
PropertyHistory(Property const *const prop);
@@ -57,6 +57,7 @@ class MANTID_KERNEL_DLL PropertyHistory {
5757
/// get whether algorithm parameter was left as default EMPTY_INT,LONG,DBL
5858
/// const
5959
bool isEmptyDefault() const;
60+
bool pythonVariable() const { return m_pythonVariable; };
6061

6162
/// this is required for boost.python
6263
bool operator==(const PropertyHistory &other) const {
@@ -75,6 +76,8 @@ class MANTID_KERNEL_DLL PropertyHistory {
7576
bool m_isDefault;
7677
/// direction of parameter
7778
unsigned int m_direction;
79+
/// Whether the property should be treated as a python variable instead of string when building a script from history
80+
bool m_pythonVariable;
7881
};
7982

8083
// typedefs for property history pointers

Framework/Kernel/src/PropertyHistory.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@ namespace Mantid::Kernel {
2222

2323
/// Constructor
2424
PropertyHistory::PropertyHistory(std::string name, std::string value, std::string type, const bool isdefault,
25-
const unsigned int direction)
25+
const unsigned int direction, const bool pythonVariable)
2626
: m_name(std::move(name)), m_value(std::move(value)), m_type(std::move(type)), m_isDefault(isdefault),
27-
m_direction(direction) {}
27+
m_direction(direction), m_pythonVariable(pythonVariable) {}
2828

2929
PropertyHistory::PropertyHistory(Property const *const prop)
3030
: m_name(prop->name()), m_value(prop->valueAsPrettyStr(0, true)), m_type(prop->type()),
31-
m_isDefault(prop->isDefault()), m_direction(prop->direction()) {}
31+
m_isDefault(prop->isDefault()), m_direction(prop->direction()), m_pythonVariable(false) {}
3232

3333
/** Prints a text representation of itself
3434
* @param os :: The output stream to write to

Framework/PythonInterface/mantid/api/src/Exports/AlgorithmHistory.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@ void export_AlgorithmHistory() {
8787

8888
.def("getChildAlgorithm", &AlgorithmHistory::getChildAlgorithm, (arg("self"), arg("index")),
8989
"Returns the algorithm at the given index in the history")
90+
91+
.def("getStoreInADS", &AlgorithmHistory::getStoreInADS, arg("self"), return_value_policy<copy_const_reference>(),
92+
"Return storeInADS property")
9093
// ----------------- Operators --------------------------------------
9194
.def(self_ns::str(self));
9295
}

0 commit comments

Comments
 (0)