Mantid
Loading...
Searching...
No Matches
ScriptBuilder.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 +
7//----------------------------------------------------------------------
8// Includes
9//----------------------------------------------------------------------
17#include "MantidKernel/Logger.h"
20
21#include <boost/algorithm/string/classification.hpp>
22#include <boost/range/algorithm/remove_if.hpp>
23#include <boost/utility.hpp>
24#include <set>
25#include <utility>
26
27namespace Mantid::API {
28
31
32namespace {
33Mantid::Kernel::Logger g_log("ScriptBuilder");
34}
35
36const std::string COMMENT_ALG = "Comment";
37
38ScriptBuilder::ScriptBuilder(const std::shared_ptr<HistoryView> &view, std::string versionSpecificity,
39 bool appendTimestamp, std::vector<std::string> ignoreTheseAlgs,
40 std::vector<std::vector<std::string>> ignoreTheseAlgProperties, bool appendExecCount)
41 : m_historyItems(view->getAlgorithmsList()), m_output(), m_versionSpecificity(std::move(versionSpecificity)),
42 m_timestampCommands(appendTimestamp), m_algsToIgnore(std::move(ignoreTheseAlgs)),
43 m_propertiesToIgnore(std::move(ignoreTheseAlgProperties)), m_execCount(appendExecCount) {}
44
50const std::string ScriptBuilder::build() {
51 std::ostringstream os;
52 os << "from mantid.simpleapi import *\n\n";
53 auto iter = m_historyItems.begin();
54 for (; iter != m_historyItems.end(); ++iter) {
55 writeHistoryToStream(os, iter);
56 }
57 return os.str();
58}
59
71void ScriptBuilder::writeHistoryToStream(std::ostringstream &os, std::vector<HistoryItem>::const_iterator &iter,
72 int depth) {
73 auto algHistory = iter->getAlgorithmHistory();
74 if (iter->isUnrolled()) {
75 os << "\n";
76 os << std::string(depth, '#');
77 os << " Child algorithms of " << algHistory->name() << "\n";
78
79 // don't create a line for the algorithm, just output its children
80 buildChildren(os, iter, depth + 1);
81
82 os << std::string(depth, '#');
83 os << " End of child algorithms of " << algHistory->name() << "\n";
84
85 if (boost::next(iter) == m_historyItems.end() || !boost::next(iter)->isUnrolled()) {
86
88 os << " # " << algHistory->executionDate().toISO8601String();
89 }
90
91 os << "\n";
92 }
93 } else {
94 // create the string for this algorithm if not found to be in the ignore
95 // list
96 if (!(std::find(m_algsToIgnore.begin(), m_algsToIgnore.end(), algHistory->name()) != m_algsToIgnore.end())) {
97 createStringForAlg(os, algHistory);
98 }
99 }
100}
101
102void ScriptBuilder::createStringForAlg(std::ostringstream &os,
103 std::shared_ptr<const Mantid::API::AlgorithmHistory> &algHistory) {
104 os << buildAlgorithmString(*algHistory);
106 os << " # " << algHistory->executionDate().toISO8601String();
107 }
108
109 if (m_execCount) {
111 os << " execCount: " << algHistory->execCount();
112 } else {
113 os << " # execCount: " << algHistory->execCount();
114 }
115 }
116
117 os << "\n";
118}
119
132void ScriptBuilder::buildChildren(std::ostringstream &os, std::vector<HistoryItem>::const_iterator &iter, int depth) {
133 size_t numChildren = iter->numberOfChildren();
134 ++iter; // move to first child
135 for (size_t i = 0; i < numChildren && iter != m_historyItems.end(); ++i, ++iter) {
136 writeHistoryToStream(os, iter, depth);
137 }
138 --iter;
139}
140
147const std::string ScriptBuilder::buildCommentString(const AlgorithmHistory &algHistory) {
148 std::ostringstream comment;
149 const std::string name = algHistory.name();
150 if (name == COMMENT_ALG) {
151 auto props = algHistory.getProperties();
152 for (auto &prop : props) {
153 if (prop->name() == "Text") {
154 comment << "# " << prop->value();
155 }
156 }
157 }
158 return comment.str();
159}
160
167const std::string ScriptBuilder::buildAlgorithmString(const AlgorithmHistory &algHistory) {
168 std::ostringstream properties;
169 const std::string name = algHistory.name();
170 std::string prop;
171
172 if (name == COMMENT_ALG)
173 return buildCommentString(algHistory);
174
175 auto props = algHistory.getProperties();
176
177 try {
179 // create a fresh version of the algorithm - unmanaged
180 if (name == "Load") {
181 int version = std::stoi(algHistory.getPropertyValue("LoaderVersion"));
182 algFresh = AlgorithmManager::Instance().createUnmanaged(algHistory.getPropertyValue("LoaderName"), version);
183 } else {
184 algFresh = AlgorithmManager::Instance().createUnmanaged(name, algHistory.version());
185 }
186 algFresh->initialize();
187
188 const auto &propsFresh = algFresh->getProperties();
189 // just get the names out of the fresh alg properties
190 std::set<std::string> freshPropNames;
191 for (const auto &propFresh : propsFresh) {
192 freshPropNames.insert(propFresh->name());
193 }
194
195 // remove output properties that are not present on a fresh algorithm
196 // i.e. remove dynamically added properties
197 for (auto prop_iter = props.begin(); prop_iter != props.end();) {
198 if (freshPropNames.find((*prop_iter)->name()) == freshPropNames.end() &&
199 (*prop_iter)->direction() == Kernel::Direction::Output) {
200 prop_iter = props.erase(prop_iter);
201 } else {
202 ++prop_iter;
203 }
204 }
205
206 } catch (std::exception &) {
207 g_log.error() << "Could not create a fresh version of " << name << " version " << algHistory.version() << "\n";
208 }
209
210 for (auto &propIter : props) {
211 prop = buildPropertyString(*propIter, name);
212 if (prop.length() > 0) {
213 properties << prop << ", ";
214 }
215 }
216
217 // Three cases, we can either specify the version of every algorithm...
218 if (m_versionSpecificity == "all") {
219 properties << "Version=" << algHistory.version() << ", ";
220 } else if (m_versionSpecificity == "old") {
221 //...or only specify algorithm versions when they're not the newest version
222 const auto &algName = algHistory.name();
223 auto &algFactory = API::AlgorithmFactory::Instance();
224 int latestVersion = 0;
225
226 if (algFactory.exists(algName)) { // Check the alg still exists in Mantid
227 latestVersion = AlgorithmFactory::Instance().highestVersion(algName);
228 }
229 // If a newer version of this algorithm exists, then this must be an old
230 // version.
231 if (latestVersion > algHistory.version()) {
232 properties << "Version=" << algHistory.version() << ", ";
233 }
234 }
235 // Third case is we never specify the version, so do nothing.
236
237 std::string propStr = properties.str();
238 if (propStr.length() > 0) {
239 // remove trailing comma & space
240 propStr.erase(propStr.size() - 1);
241 propStr.erase(propStr.size() - 1);
242 }
243
244 std::string historyEntry = name + "(" + propStr + ")";
245 historyEntry.erase(boost::remove_if(historyEntry, boost::is_any_of("\n\r")), historyEntry.end());
246 return historyEntry;
247}
248
257 const std::string &algName) {
259
260 // If the property is to be ignored then return with an empty string
261 if (std::find_if(m_propertiesToIgnore.begin(), m_propertiesToIgnore.end(),
262 [&propHistory, algName](std::vector<std::string> &c) -> bool {
263 return algName == c[0] && propHistory.name() == c[1];
264 }) != m_propertiesToIgnore.end()) {
265 return "";
266 }
267
268 // Create a vector of all non workspace property type names
269 std::vector<std::string> nonWorkspaceTypes{"number", "boolean", "string"};
270
271 std::string prop;
272 // No need to specify value for default properties
273 if (!propHistory.isDefault()) {
274 // Do not give values to output properties other than workspace properties
275 if (find(nonWorkspaceTypes.begin(), nonWorkspaceTypes.end(), propHistory.type()) != nonWorkspaceTypes.end() &&
276 propHistory.direction() == Direction::Output) {
277 // If algs are to be ignored (Common use case is project recovery) ignore
278 if (m_algsToIgnore.size() == 0) {
279 g_log.debug() << "Ignoring property " << propHistory.name() << " of type " << propHistory.type() << '\n';
280 }
281 // Handle numerical properties
282 } else if (propHistory.type() == "number") {
283 prop = propHistory.name() + "=" + propHistory.value();
284 // Handle boolean properties
285 } else if (propHistory.type() == "boolean") {
286 std::string value = (propHistory.value() == "1" ? "True" : "False");
287 prop = propHistory.name() + "=" + value;
288 // Handle all other property types
289 } else {
290 std::string opener = "='";
291 if (propHistory.value().find('\\') != std::string::npos) {
292 opener = "=r'";
293 }
294
295 prop = propHistory.name() + opener + propHistory.value() + "'";
296 }
297 }
298
299 return prop;
300}
301
302} // namespace Mantid::API
double value
The value of the point.
Definition: FitMW.cpp:51
This class stores information about the Command History used by algorithms on a workspace.
const std::string & getPropertyValue(const std::string &name) const
get the string representation of a specified property
const std::string & name() const
get name of algorithm in history const
const int & version() const
get version number of algorithm in history const
const Mantid::Kernel::PropertyHistories & getProperties() const
get parameter list of algorithm in history const
void createStringForAlg(std::ostringstream &os, std::shared_ptr< const Mantid::API::AlgorithmHistory > &algHistory)
const std::string buildCommentString(const AlgorithmHistory &algHistory)
Build the script output for a single comment.
std::vector< std::vector< std::string > > m_propertiesToIgnore
Definition: ScriptBuilder.h:53
void writeHistoryToStream(std::ostringstream &os, std::vector< HistoryItem >::const_iterator &iter, int depth=1)
Write out an algorithm to the script.
std::vector< std::string > m_algsToIgnore
Definition: ScriptBuilder.h:52
const std::vector< HistoryItem > m_historyItems
Definition: ScriptBuilder.h:48
ScriptBuilder(const std::shared_ptr< HistoryView > &view, std::string versionSpecificity="old", bool appendTimestamp=false, std::vector< std::string > ignoreTheseAlgs={}, std::vector< std::vector< std::string > > ignoreTheseAlgProperties={}, bool appendExecCount=false)
void buildChildren(std::ostringstream &os, std::vector< HistoryItem >::const_iterator &iter, int depth=1)
Iterate over each of the items children and output them to the script.
const std::string buildAlgorithmString(const AlgorithmHistory &algHistory)
Build the script output for a single algorithm.
const std::string buildPropertyString(const Mantid::Kernel::PropertyHistory &propHistory, const std::string &algName)
Build the script output for a single property.
std::string m_versionSpecificity
Definition: ScriptBuilder.h:50
const std::string build()
build a python script from the history view
The Logger class is in charge of the publishing messages from the framework through various channels.
Definition: Logger.h:52
void debug(const std::string &msg)
Logs at debug level.
Definition: Logger.cpp:114
void error(const std::string &msg)
Logs at error level.
Definition: Logger.cpp:77
This class stores information about the parameters used by an algorithm.
unsigned int direction() const
get direction flag of algorithm parameter const
const std::string & name() const
get name of algorithm parameter const
const std::string & value() const
get value of algorithm parameter const
bool isDefault() const
get isdefault flag of algorithm parameter const
const std::string & type() const
get type of algorithm parameter const
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
Kernel::Logger g_log("ExperimentInfo")
static logger object
const std::string COMMENT_ALG
std::shared_ptr< Algorithm > Algorithm_sptr
Typedef for a shared pointer to an Algorithm.
Definition: Algorithm.h:61
std::shared_ptr< const PropertyHistory > PropertyHistory_const_sptr
std::shared_ptr< PropertyHistory > PropertyHistory_sptr
STL namespace.
Describes the direction (within an algorithm) of a Property.
Definition: Property.h:50
@ Output
An output workspace.
Definition: Property.h:54