Newer
Older
Peterson, Peter
committed
#ifndef MANTID_API_ALGORITHM_H_
#define MANTID_API_ALGORITHM_H_
/* Used to register classes into the factory. creates a global object in an
Russell Taylor
committed
* anonymous namespace. The object itself does nothing, but the comma operator
* is used in the call to its constructor to effect a call to the factory's
* subscribe method.
*/
Peterson, Peter
committed
#define DECLARE_ALGORITHM(classname) \
Russell Taylor
committed
namespace { \
Mantid::Kernel::RegistrationHelper register_alg_##classname( \
((Mantid::API::AlgorithmFactory::Instance().subscribe<classname>()) \
, 0)); \
}
Peterson, Peter
committed
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidKernel/System.h"
#include "MantidAPI/AlgorithmFactory.h"
#include "MantidAPI/FrameworkManager.h"
Peterson, Peter
committed
#include "MantidAPI/IAlgorithm.h"
#include "MantidKernel/PropertyManagerOwner.h"
#include "MantidKernel/Property.h"
#include "MantidKernel/BoundedValidator.h"
#include "MantidKernel/FileValidator.h"
#include "MantidKernel/ListValidator.h"
#include "MantidKernel/MandatoryValidator.h"
#include "MantidKernel/Logger.h"
#include "MantidKernel/Exception.h"
#include "MantidKernel/MultiThreaded.h"
#include "MantidAPI/WorkspaceGroup.h"
Peterson, Peter
committed
#include "MantidAPI/Progress.h"
#include "MantidAPI/WorkspaceProperty.h"
#include "MantidAPI/WorkspaceOpOverloads.h"
#include "MantidAPI/WorkspaceFactory.h"
#include <boost/shared_ptr.hpp>
#include <Poco/ActiveMethod.h>
#include <Poco/NotificationCenter.h>
#include <Poco/Notification.h>
Roman Tolchenov
committed
#include <Poco/NObserver.h>
Gigg, Martyn Anthony
committed
#include <Poco/Void.h>
Peterson, Peter
committed
#include <string>
#include <vector>
#include <map>
#include <cmath>
Peterson, Peter
committed
#ifndef PACKAGE_VERSION
#define PACKAGE_VERSION "unknown"
#endif
namespace Mantid
{
Russell Taylor
committed
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
namespace API
{
//----------------------------------------------------------------------
// Forward Declaration
//----------------------------------------------------------------------
class AlgorithmProxy;
/**
Base class from which all concrete algorithm classes should be derived.
In order for a concrete algorithm class to do anything
useful the methods init() & exec() should be overridden.
Further text from Gaudi file.......
The base class provides utility methods for accessing
standard services (event data service etc.); for declaring
properties which may be configured by the job options
service; and for creating sub algorithms.
The only base class functionality which may be used in the
constructor of a concrete algorithm is the declaration of
member variables as properties. All other functionality,
i.e. the use of services and the creation of sub-algorithms,
may be used only in initialise() and afterwards (see the
Gaudi user guide).
@author Russell Taylor, Tessella Support Services plc
@author Based on the Gaudi class of the same name (see http://proj-gaudi.web.cern.ch/proj-gaudi/)
@date 12/09/2007
Copyright © 2007-10 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory
This file is part of Mantid.
Mantid is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
Mantid is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
File change history is stored at: <https://svn.mantidproject.org/mantid/trunk/Code/Mantid>.
Code Documentation is available at: <http://doxygen.mantidproject.org>
*/
class DLLExport Algorithm : public IAlgorithm, public Kernel::PropertyManagerOwner
{
public:
/// Base class for algorithm notifications
class AlgorithmNotification: public Poco::Notification
{
public:
AlgorithmNotification(const Algorithm* const alg):Poco::Notification(),m_algorithm(alg){}///< Constructor
const IAlgorithm* algorithm() const {return m_algorithm;} ///< The algorithm
private:
const IAlgorithm* const m_algorithm;///< The algorithm
};
/// StartedNotification is sent when the algorithm begins execution.
class StartedNotification: public AlgorithmNotification
{
public:
StartedNotification(const Algorithm* const alg):AlgorithmNotification(alg){}///< Constructor
virtual std::string name() const{return "StartedNotification";}///< class name
};
/// FinishedNotification is sent after the algorithm finishes its execution
class FinishedNotification: public AlgorithmNotification
{
public:
FinishedNotification(const Algorithm* const alg, bool res):AlgorithmNotification(alg),success(res){}///< Constructor
virtual std::string name() const{return "FinishedNotification";}///< class name
bool success;///< true if the finished algorithm was successful or false if it failed.
};
/// An algorithm can report its progress by sending ProgressNotification. Use
/// Algorithm::progress(double) function to send a preogress notification.
class ProgressNotification: public AlgorithmNotification
{
public:
ProgressNotification(const Algorithm* const alg, double p,const std::string& msg):AlgorithmNotification(alg),progress(p),message(msg){}///< Constructor
virtual std::string name() const{return "ProgressNotification";}///< class name
double progress;///< Current progress. Value must be between 0 and 1.
std::string message;///< Message sent with notification
};
/// ErrorNotification is sent when an exception is caught during execution of the algorithm.
class ErrorNotification: public AlgorithmNotification
{
public:
/// Constructor
ErrorNotification(const Algorithm* const alg, const std::string& str):AlgorithmNotification(alg),what(str){}
virtual std::string name() const{return "ErrorNotification";}///< class name
std::string what;///< message string
};
/// CancelException is thrown to cancel execution of the algorithm. Use Algorithm::cancel() to
/// terminate an algorithm. The execution will only be stopped if Algorithm::exec() method calls
/// periodically Algorithm::interuption_point() which checks if Algorithm::cancel() has been called
/// and throws CancelException if needed.
class CancelException : public std::exception
{
public:
CancelException():outMessage("Algorithm terminated"){}
CancelException(const CancelException& A):outMessage(A.outMessage){}///< Copy constructor
/// Assignment operator
CancelException& operator=(const CancelException& A);
/// Destructor
~CancelException() throw() {}
/// Returns the message string.
const char* what() const throw()
{
return outMessage.c_str();
}
private:
/// The message returned by what()
std::string outMessage;
};
Algorithm();
virtual ~Algorithm();
/// function to return a name of the algorithm, must be overridden in all algorithms
virtual const std::string name() const = 0;
/// function to return a version of the algorithm, must be overridden in all algorithms
virtual int version() const = 0;
/// function to return a category of the algorithm. A default implementation is provided
virtual const std::string category() const {return "Misc";}
/// Algorithm ID. Unmanaged algorithms return 0 (or NULL?) values. Managed ones have non-zero.
AlgorithmID getAlgorithmID()const{return m_algorithmID;}
// IAlgorithm methods
void initialize();
bool execute();
virtual bool isInitialized() const;
virtual bool isExecuted() const;
// End of IAlgorithm methods
using Kernel::PropertyManagerOwner::getProperty;
/// To query whether algorithm is a child. Default to false
bool isChild() const;
void setChild(const bool isChild);
void setRethrows(const bool rethrow);
/// Asynchronous execution.
Poco::ActiveResult<bool> executeAsync();
/// Add an observer for a notification
void addObserver(const Poco::AbstractObserver& observer)const;
/// Remove an observer
void removeObserver(const Poco::AbstractObserver& observer)const;
/// Raises the cancel flag. interuption_point() method if called inside exec() checks this flag
/// and if true terminates the algorithm.
void cancel()const;
/// True if the algorithm is running asynchronously.
bool isRunningAsync(){return m_runningAsync;}
/// True if the algorithm is running.
bool isRunning(){return m_running;}
///Logging can be disabled by passing a value of false
void setLogging(const bool value){g_log.setEnabled(value);}
///returns the status of logging, True = enabled
bool isLogging() const {return g_log.getEnabled();}
Janik Zikovsky
committed
/// function returns an optional message that will be displayed in the default GUI, at the top.
const std::string getOptionalMessage() const { return m_OptionalMessage;}
/// Set an optional message that will be displayed in the default GUI, at the top.
void setOptionalMessage(const std::string optionalMessage) { m_OptionalMessage = optionalMessage;}
protected:
Russell Taylor
committed
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
// Equivalents of Gaudi's initialize & execute methods
/// Virtual method - must be overridden by concrete algorithm
virtual void init() = 0;
/// Virtual method - must be overridden by concrete algorithm
virtual void exec() = 0;
friend class AlgorithmProxy;
/// Initialize with properties from an algorithm proxy
void initializeFromProxy(const AlgorithmProxy&);
//creates a sub algorithm for use in this algorithm
IAlgorithm_sptr createSubAlgorithm(const std::string& name, const double startProgress = -1.,
const double endProgress = -1., const bool enableLogging=true, const int& version = -1);
void setInitialized();
void setExecuted(bool state);
// Make PropertyManager's declareProperty methods protected in Algorithm
using Kernel::PropertyManagerOwner::declareProperty;
/// Sends notifications to observers. Observers can subscribe to notificationCenter
/// using Poco::NotificationCenter::addObserver(...);
mutable Poco::NotificationCenter m_notificationCenter;
friend class Progress;
/// Sends ProgressNotification. p must be between 0 (just started) and 1 (finished)
void progress(double p, const std::string& msg = "");
/// Interrupts algorithm execution if Algorithm::cancel() has been called.
/// Does nothing otherwise.
void interruption_point();
///Observation slot for child algorithm progress notification messages, these are scaled and then signalled for this algorithm.
void handleChildProgressNotification(const Poco::AutoPtr<ProgressNotification>& pNf);
///Child algorithm progress observer
Poco::NObserver<Algorithm, ProgressNotification> m_progressObserver;
///checks that the value was not set by users, uses the value in EMPTY_DBL()
static bool isEmpty(double toCheck) { return std::abs( (toCheck - EMPTY_DBL())/(EMPTY_DBL()) ) < 1e-8 ;}
///checks that the value was not set by users, uses the value in EMPTY_INT()
static bool isEmpty(int toCheck) { return toCheck == EMPTY_INT(); }
///checks the property is a workspace property
bool isWorkspaceProperty(const Kernel::Property* const prop) const;
/// checks the property is input workspace property
bool isInputWorkspaceProperty(const Kernel::Property* const prop) const;
/// checks the property is output workspace property
bool isOutputWorkspaceProperty(const Kernel::Property* const prop) const;
Sofia Antony
committed
/// This method checks the members workspaces are of similar names (example group_1,group_2) and returns true if they are.
bool isGroupWorkspacesofSimilarNames(const std::string&,const std::vector<std::string>& grpmembersNames);
Russell Taylor
committed
/// process workspace groups
Sofia Antony
committed
virtual bool processGroups(WorkspaceGroup_sptr ingrpws_sptr,const std::vector<Mantid::Kernel::Property*>&props);
Russell Taylor
committed
/// virtual method to set non workspace properties for an algorithm,it's useful for checking the period number when a member in a group workspace is executed
virtual void setOtherProperties(IAlgorithm* alg,const std::string & propertyName,const std::string &propertyValue,int perioidNum);
mutable bool m_cancel; ///< set to true to stop execution
bool m_parallelException; ///< Set if an exception is thrown, and not caught, within a parallel region
Kernel::Logger& g_log; ///< reference to the logger class
private:
Russell Taylor
committed
/// Private Copy constructor: NO COPY ALLOWED
Algorithm(const Algorithm&);
/// Private assignment operator: NO ASSIGNMENT ALLOWED
Algorithm& operator=(const Algorithm&);
Janik Zikovsky
committed
void store();
Janik Zikovsky
committed
void fillHistory(Mantid::Kernel::DateAndTime, double,unsigned int);
Janik Zikovsky
committed
void findWorkspaceProperties(std::vector<Workspace_sptr>& inputWorkspaces,
std::vector<Workspace_sptr>& outputWorkspaces) const;
void algorithm_info() const;
/// setting the input properties for an algorithm - to handle workspace groups
bool setInputWSProperties(IAlgorithm* pAlg,Mantid::Kernel::Property* prop,const std::string& inMemberWSName );
/// setting the output properties for an algorithm -to handle workspace groups
bool setOutputWSProperties(IAlgorithm* pAlg,Mantid::Kernel::Property* prop,const int nPeriod,
const std::string& inmemberwsName,WorkspaceGroup_sptr& outwsgrp_sptr,bool bSimilarNames,bool bequal);
/// This method gets the input workspace name
void getInputGroupWorkspaceName(const std::vector<Mantid::Kernel::Property*>& props,std::string& ingroupwsName);
/// This method returns true if the input and output workspaces are same
bool isInputequaltoOutPut(const std::vector<Mantid::Kernel::Property*>&props);
Sofia Antony
committed
Russell Taylor
committed
/// Poco::ActiveMethod used to implement asynchronous execution.
Poco::ActiveMethod<bool, Poco::Void, Algorithm> m_executeAsync;
/** executeAsync() implementation.
@param i Unused argument
Russell Taylor
committed
*/
bool executeAsyncImpl(const Poco::Void & i);
bool m_isInitialized; ///< Algorithm has been initialized flag
bool m_isExecuted; ///< Algorithm is executed flag
Peterson, Peter
committed
Russell Taylor
committed
bool m_isChildAlgorithm; ///< Algorithm is a child algorithm
Peterson, Peter
committed
Russell Taylor
committed
bool m_runningAsync; ///< Algorithm is running asynchronously
bool m_running; ///< Algorithm is running
bool m_rethrow; ///< Algorithm should rethrow exceptions while executing
Peterson, Peter
committed
Russell Taylor
committed
double m_startChildProgress; ///< Keeps value for algorithm's progress at start of an sub-algorithm
double m_endChildProgress; ///< Keeps value for algorithm's progress at sub-algorithm's finish
Peterson, Peter
committed
Russell Taylor
committed
AlgorithmID m_algorithmID; ///< Algorithm ID for managed algorithms
Peterson, Peter
committed
Russell Taylor
committed
static unsigned int g_execCount; ///< Counter to keep track of algorithm execution order
Janik Zikovsky
committed
std::string m_OptionalMessage; ///< An optional message string to be displayed in the GUI.
Russell Taylor
committed
};
Peterson, Peter
committed
Russell Taylor
committed
///Typedef for a shared pointer to an Algorithm
typedef boost::shared_ptr<Algorithm> Algorithm_sptr;
Peterson, Peter
committed
Russell Taylor
committed
} // namespace API
Peterson, Peter
committed
} // namespace Mantid
#endif /*MANTID_API_ALGORITHM_H_*/