8#pragma warning(disable : 4250)
15#pragma warning(default : 4250)
25#include <Poco/ActiveResult.h>
26#include <Poco/Thread.h>
28#include <boost/python/arg_from_python.hpp>
29#include <boost/python/bases.hpp>
30#include <boost/python/class.hpp>
31#include <boost/python/object.hpp>
32#include <boost/python/operators.hpp>
33#include <boost/python/register_ptr_to_python.hpp>
35#include <unordered_map>
54using ToPyString = to_python_value<const std::string &>;
57using ThreadIDObjectMap = std::unordered_map<long, object>;
59ThreadIDObjectMap &threadIDMap() {
60 static ThreadIDObjectMap threadIDs;
70void _trackAlgorithm(
long threadID,
const object &alg) { threadIDMap()[threadID] = alg; }
76void _forgetAlgorithm(
long threadID) { threadIDMap().erase(threadID); }
83object _algorithmInThread(
long threadID) {
84 auto &threadMap = threadIDMap();
85 auto it = threadMap.find(threadID);
86 if (it != threadMap.end()) {
87 auto value = it->second;
97struct MandatoryFirst {
108using PropertyVector = std::vector<Property *>;
117PropertyVector apiOrderedProperties(
const IAlgorithm &propMgr) {
119 std::stable_sort(properties.begin(), properties.end(), MandatoryFirst());
131list getInputPropertiesWithMandatoryFirst(
const IAlgorithm &self) {
132 PropertyVector properties(apiOrderedProperties(self));
137 for (
const auto &prop : properties) {
139 names.append(handle<>(toPyStr(prop->name())));
152list getAlgorithmPropertiesOrdered(
const IAlgorithm &self) {
153 PropertyVector properties(apiOrderedProperties(self));
158 for (
const auto &prop : properties) {
159 names.append(handle<>(toPyStr(prop->name())));
169list getOutputProperties(
const IAlgorithm &self) {
175 for (
const auto &p : properties) {
177 names.append(handle<>(toPyStr(p->name())));
188list getInOutProperties(
const IAlgorithm &self) {
194 for (
const auto &p : properties) {
196 names.append(handle<>(toPyStr(p->name())));
207std::string createDocString(
const IAlgorithm &self) {
208 const std::string EOL =
"\n";
211 std::stringstream buffer;
212 std::string temp = self.
summary();
214 buffer << temp << EOL << EOL;
217 PropertyVector properties(apiOrderedProperties(self));
219 const size_t numProps(properties.size());
221 buffer <<
"Property descriptions: " << EOL << EOL;
223 for (
size_t i = 0; i < numProps; ++i) {
228 buffer <<
") *" << prop->
type() <<
"* ";
232 if (!allowed.empty()) {
237 if (i < numProps - 1)
251struct AllowCThreads {
252 explicit AllowCThreads(
const object &algm)
253 : m_tracefunc(nullptr), m_tracearg(nullptr), m_saved(nullptr), m_tracking(false) {
254 PyThreadState *curThreadState = PyThreadState_GET();
255 m_tracefunc = curThreadState->c_tracefunc;
256 m_tracearg = curThreadState->c_traceobj;
257 Py_XINCREF(m_tracearg);
258 PyEval_SetTrace(
nullptr,
nullptr);
260 _trackAlgorithm(curThreadState->thread_id, algm);
263 m_saved = PyEval_SaveThread();
266 PyEval_RestoreThread(m_saved);
268 _forgetAlgorithm(m_saved->thread_id);
270 PyEval_SetTrace(m_tracefunc, m_tracearg);
271 Py_XDECREF(m_tracearg);
275 Py_tracefunc m_tracefunc;
276 PyObject *m_tracearg;
277 PyThreadState *m_saved;
285bool executeProxy(
object &self) {
295 auto &calg = extract<IAlgorithm &>(self)();
296 AllowCThreads threadStateHolder((!calg.isChild()) ? self :
object());
297 return calg.execute();
304void executeAsync(
const object &self) {
305 auto &calg = extract<IAlgorithm &>(self)();
314PyObject *getAlgorithmID(
const IAlgorithm &self) {
329std::string getOptionalMessage(
const IAlgorithm &self) {
330 PyErr_Warn(PyExc_DeprecationWarning,
".getOptionalMessage() is deprecated. Use .summary() instead.");
338std::string getWikiSummary(
const IAlgorithm &self) {
339 PyErr_Warn(PyExc_DeprecationWarning,
".getWikiSummary() is deprecated. Use .summary() instead.");
347boost::python::dict validateInputs(
IAlgorithm &self) {
350 return MapToPyDictionary(map)();
361 class_<AlgorithmIDProxy>(
"AlgorithmID", no_init).def(self == self);
363 register_ptr_to_python<std::shared_ptr<IAlgorithm>>();
364 register_ptr_to_python<std::shared_ptr<const IAlgorithm>>();
366 class_<IAlgorithm, bases<IPropertyManager>, boost::noncopyable>(
"IAlgorithm",
"Interface for all algorithms", no_init)
367 .def(
"name", &
IAlgorithm::name, arg(
"self"),
"Returns the name of the algorithm")
368 .def(
"alias", &
IAlgorithm::alias, arg(
"self"),
"Return the aliases for the algorithm")
370 "Deprecation date (in ISO8601 format) for the algorithm aliases. "
371 "Returns empty string if no deprecation date")
372 .def(
"version", &
IAlgorithm::version, arg(
"self"),
"Returns the version number of the algorithm")
373 .def(
"cancel", &
IAlgorithm::cancel, arg(
"self"),
"Request that the algorithm stop running")
374 .def(
"category", &
IAlgorithm::category, arg(
"self"),
"Returns the category containing the algorithm")
376 "Returns the list of categories this algorithm belongs to")
378 "Returns the list of similar algorithms")
379 .def(
"summary", &
IAlgorithm::summary, arg(
"self"),
"Returns a summary message describing the algorithm")
380 .def(
"helpURL", &
IAlgorithm::helpURL, arg(
"self"),
"Returns optional URL for algorithm documentation")
382 "Returns a name that will be used when attached as a workspace "
383 "method. Empty string indicates do not attach")
385 return_value_policy<VectorToNumpy>(),
386 "Returns a set of class names that will have the method attached. "
387 "Empty list indicates all types")
389 "Returns the name of the input workspace property used by the "
391 .def(
"getAlgorithmID", &getAlgorithmID, arg(
"self"),
"Returns a unique identifier for this algorithm object")
392 .def(
"docString", &createDocString, arg(
"self"),
"Returns a doc string for the algorithm")
393 .def(
"mandatoryProperties", &getInputPropertiesWithMandatoryFirst, arg(
"self"),
394 "Returns a list of input and in/out property names that is ordered "
395 "such that the mandatory properties are first followed by the "
397 .def(
"orderedProperties", &getAlgorithmPropertiesOrdered, arg(
"self"),
398 "Return a list of input, in/out and output properties "
399 "such that the mandatory properties are first followed by the "
401 .def(
"outputProperties", &getOutputProperties, arg(
"self"),
402 "Returns a list of the output properties on the algorithm")
403 .def(
"inoutProperties", &getInOutProperties, arg(
"self"),
404 "Returns a list of the inout properties on the algorithm")
406 "Returns True if the algorithm is initialized, False otherwise")
408 "Returns True if the algorithm has been executed successfully, "
411 "Returns True if the "
412 "algorithm's logger is turned "
413 "on, False otherwise")
415 "Returns True if the algorithm "
416 "is considered to be running, "
419 "If true this algorithm is run as a child algorithm. There will be "
420 "no logging and nothing is stored in the Analysis Data Service")
422 "If true then history will be recorded regardless of the child "
425 "If true then allow logging of start and end messages")
427 "Returns true if logging of start and end messages")
429 "If true then even child algorithms will have their workspaces "
430 "stored in the ADS.")
432 "Returns True if the algorithm has been marked to run as a child. "
433 "If True then Output workspaces "
434 "are NOT stored in the Analysis Data Service but must be retrieved "
435 "from the property.")
438 "To query whether an algorithm "
439 "should rethrow exceptions when "
441 .def(
"initialize", &initializeProxy, arg(
"self"),
"Initializes the algorithm")
442 .def(
"validateInputs", &validateInputs, arg(
"self"),
443 "Cross-check all inputs and return any errors as a dictionary")
444 .def(
"execute", &executeProxy, arg(
"self"),
"Runs the algorithm and returns whether it has been successful")
445 .def(
"executeAsync", &executeAsync, arg(
"self"),
446 "Starts the algorithm in a separate thread and returns immediately")
448 .def(
"_algorithmInThread", &_algorithmInThread, arg(
"thread_id"))
449 .staticmethod(
"_algorithmInThread")
454 .def(
"getOptionalMessage", &getOptionalMessage, arg(
"self"),
455 "Returns the optional user message attached to the algorithm")
456 .def(
"getWikiSummary", &getWikiSummary, arg(
"self"),
"Returns the summary found on the wiki page");
double value
The value of the point.
#define GET_POINTER_SPECIALIZATION(TYPE)
IAlgorithm is the interface implemented by the Algorithm base class.
virtual const std::string workspaceMethodInputProperty() const =0
Returns the name of the input workspace property used by the calling object.
virtual std::string toString() const =0
Serialize an algorithm.
virtual bool isExecuted() const =0
Check whether the algorithm has been executed sucessfully.
virtual bool isInitialized() const =0
Check whether the algorithm is initialized properly.
virtual const std::string alias() const =0
function to return any aliases of the algorithm.
virtual bool isChild() const =0
To query whether algorithm is a child. Default to false.
virtual int version() const =0
function to return a version of the algorithm, must be overridden in all algorithms
virtual const std::string aliasDeprecated() const =0
Expiration date (in ISO8601 format) for the algorithm aliases. Empty if no expiration date.
virtual const std::string helpURL() const =0
function to return an optional URL for documentation.
virtual const std::vector< std::string > categories() const =0
Function to return all of the categories that contain this algorithm.
virtual bool isLogging() const =0
returns the status of logging, True = enabled
virtual const std::vector< std::string > seeAlso() const =0
Function to return all of the seeAlso algorithms related to this algorithm.
virtual bool isRunning() const =0
True if the algorithm is running.
virtual const std::string category() const =0
function to return a category of the algorithm.
virtual void setChild(const bool isChild)=0
To set whether algorithm is a child.
virtual const std::string workspaceMethodName() const =0
virtual const std::vector< std::string > workspaceMethodOn() const =0
Returns a set of class names that will have the method attached.
virtual bool getAlgStartupLogging() const =0
get the state of Logging of start and end messages
virtual const std::string summary() const =0
function returns a summary message that will be displayed in the default GUI, and in the help.
virtual void enableHistoryRecordingForChild(const bool on)=0
If true history will be recorded for a child.
virtual void setLogging(const bool value)=0
Logging can be disabled by passing a value of false.
virtual void cancel()=0
Raises the cancel flag.
virtual void setAlwaysStoreInADS(const bool doStore)=0
Set whether we always store the output in the analysis data service.
virtual void setRethrows(const bool rethrow)=0
To query whether an algorithm should rethrow exceptions when executing.
virtual void setAlgStartupLogging(const bool enabled)=0
disable Logging of start and end messages
virtual const std::string name() const =0
function to return a name of the algorithm, must be overridden in all algorithms
virtual std::map< std::string, std::string > validateInputs()=0
Method checking errors on ALL the inputs, before execution.
virtual AlgorithmID getAlgorithmID() const =0
Algorithm ID.
virtual void initialize()=0
Initialization method invoked by the framework.
Interface to PropertyManager.
virtual const std::vector< Property * > & getProperties() const =0
Get the list of managed properties.
Base class for properties.
unsigned int direction() const
returns the direction of the property
const std::string & documentation() const
Get the property's documentation string.
virtual std::string isValid() const
Overridden function that checks whether the property, if not overriden returns "".
const std::string & name() const
Get the property's name.
virtual std::vector< std::string > allowedValues() const
Returns the set of valid values for this property, if such a set exists.
const std::string type() const
Returns the type of the property as a string.
Defines a structure for acquiring/releasing the Python GIL using the RAII pattern.
Defines a structure for releasing the Python GIL using the RAII pattern.
std::shared_ptr< IAlgorithm > IAlgorithm_sptr
shared pointer to Mantid::API::IAlgorithm
void * AlgorithmID
As we have multiple interfaces to the same logical algorithm we need a way of uniquely identifying ma...
DLLExport std::string join(ITERATOR_TYPE begin, ITERATOR_TYPE end, const std::string &separator, typename std::enable_if<!(std::is_same< typename std::iterator_traits< ITERATOR_TYPE >::iterator_category, std::random_access_iterator_tag >::value)>::type *=nullptr)
Join a set or vector of (something that turns into a string) together into one string,...
bool isNone(PyObject *ptr)
Describes the direction (within an algorithm) of a Property.
@ InOut
Both an input & output workspace.
@ Output
An output workspace.
static const std::string asText(const unsigned int &direction)
Returns a text representation of the input Direction enum.
Provides a concrete type to wrap & return AlgorithmIDs that are actually just typedefs for void*.
Implements a return value policy that returns a numpy array from a function returning a std::vector b...