Newer
Older
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "Algorithm.h"
#include "AnalysisDataService.h"
Russell Taylor
committed
namespace Mantid
Russell Taylor
committed
{
namespace Kernel
Russell Taylor
committed
{
// Get a reference to the logger
Logger& Algorithm::g_log = Logger::get("Algorithm");
/// Constructor
Algorithm::Algorithm() :
m_inputWorkspace(0),
m_outputWorkspace(0),
m_name("unknown"),
m_version("unknown"),
m_isInitialized(false),
m_isExecuted(false),
m_isFinalized(false)
Russell Taylor
committed
/// Virtual destructor
Russell Taylor
committed
Algorithm::~Algorithm()
{
}
/** The identifying name of the algorithm object. This is the name of a
* particular instantiation of an algorithm object as opposed to the name
* of the algorithm itself, e.g. "LinearTrackFit" may be the name of a
* concrete algorithm class, whereas "ApproxTrackFit" and
* "BestTrackFit" may be two instantiations of the class configured
* to find tracks with different fit criteria.
*
* @return Name of Instance
*/
const std::string& Algorithm::name() const
Russell Taylor
committed
{
return m_name;
}
/** The version of the algorithm
*
* @return Version string
*/
const std::string& Algorithm::version() const
Russell Taylor
committed
{
return m_version;
}
/** Initialization method invoked by the framework. This method is responsible
* for any bookkeeping of initialization required by the framework itself.
* It will in turn invoke the init() method of the derived algorithm,
* and of any sub-algorithms which it creates.
*
* @return A StatusCode object indicating whether the operation was successful
*/
StatusCode Algorithm::initialize()
Russell Taylor
committed
{
// Bypass the initialization if the algorithm
// has already been initialized.
if ( m_isInitialized ) return StatusCode::SUCCESS;
Russell Taylor
committed
Russell Taylor
committed
// Invoke initialize() method of the derived class inside a try/catch clause
try
{
// Invoke the initialize() method of the derived class
StatusCode status = init();
if( status.isFailure() ) return StatusCode::FAILURE;
Russell Taylor
committed
// Now initialize any sub-algorithms
std::vector<Algorithm*>::iterator it;
for (it = m_subAlgms.begin(); it != m_subAlgms.end(); it++)
{
status = (*it)->initialize();
if( status.isFailure() )
{
g_log.error("Error initializing one or several sub-algorithms");
return status;
Russell Taylor
committed
}
Russell Taylor
committed
// Indicate that this Algorithm has been initialized to prevent duplicate attempts.
setInitialized();
return StatusCode::SUCCESS;
}
// Unpleasant catch-all! Along with this, Gaudi version catches GaudiException & std::exception
// but doesn't really do anything except (print fatal) messages.
catch (...)
Russell Taylor
committed
{
// Gaudi: A call to the auditor service is here
// (1) perform the printout
g_log.fatal("UNKNOWN Exception is caught ");
Russell Taylor
committed
// Gaudi:
}
// Only gets to here if an exception is encountered
return StatusCode::FAILURE;
}
/** The actions to be performed by the algorithm on a dataset. This method is
* invoked for top level algorithms by the application manager.
* This method invokes exec() method.
* For sub-algorithms either the execute() method or exec() method
* must be EXPLICITLY invoked by the parent algorithm.
*
* @return A StatusCode object indicating whether the operation was successful
*/
Russell Taylor
committed
StatusCode Algorithm::execute()
{
// Return a failure if the algorithm hasn't been initialized
if ( !isInitialized() ) return StatusCode::FAILURE;
Russell Taylor
committed
// Set the input and output workspaces
std::string inputWorkspaceName;
m_outputWorkspace = 0;
m_inputWorkspace = 0;
m_outputWorkspaceName = "";
AnalysisDataService* ADS = AnalysisDataService::Instance();
StatusCode status = getProperty("InputWorkspace", inputWorkspaceName);
if ( status.isFailure() )
{
g_log.information("Algorthm:: Input workspace property not set ");
}
else
{
status = ADS->retrieve(inputWorkspaceName, m_inputWorkspace);
if (status.isFailure() )
{
g_log.error("Input workspace doesn't exist");
Russell Taylor
committed
// Invoke exec() method of derived class and catch all uncaught exceptions
try
{
// Call the concrete algorithm's exec method
StatusCode status = exec();
// Register the output workspace with the analysis data service
if ( m_outputWorkspace )
{
// Output Workspace:
status = getProperty("OutputWorkspace", m_outputWorkspaceName);
if ( status.isFailure() ) g_log.information("Output workspace property not set");
status = ADS->add(m_outputWorkspaceName, m_outputWorkspace);
if ( status.isFailure() ) g_log.error("Algorithm: Unable to register output workspace");
}
Russell Taylor
committed
setExecuted(true);
// NOTE THAT THERE IS NO EXECUTION OF SUB-ALGORITHMS HERE.
Russell Taylor
committed
// THIS HAS TO BE EXPLICITLY DONE BY THE PARENT ALGORITHM'S exec() METHOD.
Russell Taylor
committed
return status;
}
// Gaudi also specifically catches GaudiException & std:exception.
catch (...)
{
// Gaudi sets the executed flag to true here despite the exception.
// This allows it to move to the next command or it just loops indefinately.
Russell Taylor
committed
setExecuted(true);
g_log.error("UNKNOWN Exception is caught ");
Russell Taylor
committed
// Gaudi calls exception service 'handle' method here
}
// Gaudi has some stuff here where it tests for failure, increments the error counter
// and then converts to success if less than the maximum. This is clearly related to
// having an event loop, and thus we shouldn't want it. This is the only place it's used.
// Only gets to here if an exception is encountered
return StatusCode::FAILURE;
}
/** System finalization. This method invokes the finalize() method of a
* concrete algorithm and the finalize() methods of all of that algorithm's
* sub algorithms.
*
* @return A StatusCode object indicating whether the operation was successful
*/
StatusCode Algorithm::finalize()
Russell Taylor
committed
{
// Bypass the finalization if the algorithm hasn't been initialized or
// has already been finalized.
if ( !isInitialized() || isFinalized() ) return StatusCode::FAILURE;
Russell Taylor
committed
// Invoke final() method of the derived class inside a try/catch clause
try
{
StatusCode status(StatusCode::SUCCESS,true);
Russell Taylor
committed
// Finalize first any sub-algoithms (it can be done more than once)
// Gaudi at some point had a bug if this wasn't done first.
std::vector<Algorithm *>::iterator it;
for (it = m_subAlgms.begin(); it != m_subAlgms.end(); it++)
{
status = (*it)->finalize();
if( status.isFailure() )
{
g_log.error(" Error finalizing one or several sub-algorithms:"+(*it)->name());
break;
}
}
Russell Taylor
committed
// Invoke the final() method of the derived class
if( Fstatus.isFailure() ) status=Fstatus;
Russell Taylor
committed
// Release all sub-algorithms (uses IInterface release method in Gaudi instead of direct delete)
{
delete (*it);
}
m_subAlgms.clear();
Russell Taylor
committed
// Indicate that this Algorithm has been finalized to prevent duplicate attempts
setFinalized( );
return status;
}
// Unpleasant catch-all! Along with this, Gaudi version catches GaudiException & std::exception
// but doesn't really do anything except (print fatal) messages.
catch (...)
{
// (1) perform the printout
std::vector<Algorithm *>::iterator it;
for (it = m_subAlgms.begin(); it != m_subAlgms.end(); it++)
{
delete (*it);
}
m_subAlgms.clear();
Russell Taylor
committed
}
// Only gets to here if an exception is encountered
return StatusCode::FAILURE;
}
/// Has the Algorithm already been initialized
bool Algorithm::isInitialized( ) const
Russell Taylor
committed
{
return m_isInitialized;
}
/// Has the Algorithm already been executed
bool Algorithm::isExecuted() const
Russell Taylor
committed
{
return m_isExecuted;
}
bool Algorithm::isFinalized( ) const
Russell Taylor
committed
{
return m_isFinalized;
}
/** Create a sub algorithm. A call to this method creates a child algorithm object.
* Note that the returned pointer is to Algorithm (as opposed to IAlgorithm), and
* thus the methods of IProperty are also available for the direct setting of the
* sub-algorithm's properties. Using this mechanism instead of creating daughter
* algorithms directly via the new operator is prefered since then
* the framework can take care of all of the necessary book-keeping.
*
* @param type The concrete algorithm class of the sub algorithm
* @param name The name to be given to the sub algorithm
* @param pSubAlg Set to point to the newly created algorithm object
*
* @return Success since nothing ever happens.
*/
StatusCode Algorithm::createSubAlgorithm( const std::string& type, const std::string& name,
Algorithm*& pSubAlg )
{
/// @todo This method needs implementing now that we have an algorithm factory
return StatusCode::SUCCESS;
}
// Empty for now - requires Property manager
// StatusCode Algorithm::setProperty(const Property& p) {
// return m_propertyMgr->setProperty(p);
// }
StatusCode Algorithm::setProperty(const std::string& s)
{
if (s.empty()) return StatusCode::FAILURE;
m_properties[s] = "";
return StatusCode::SUCCESS;
StatusCode Algorithm::setProperty(const std::string& n, const std::string& v)
{
if (n.empty()) return StatusCode::FAILURE;
m_properties[n] = v;
return StatusCode::SUCCESS;
}
// StatusCode Algorithm::getProperty(Property* p) const {
// return m_propertyMgr->getProperty(p);
// }
// const Property& Algorithm::getProperty( const std::string& name) const{
// return m_propertyMgr->getProperty(name);
// }
StatusCode Algorithm::getProperty(const std::string& n, std::string& v ) const
// Check if key is in map & if not return with failure
if (m_properties.find(n) == m_properties.end()) return StatusCode::FAILURE;
// Retrieve the value corresponding to the key
v = m_properties.find(n)->second;
return StatusCode::SUCCESS;
}
// const std::vector<Property*>& Algorithm::getProperties( ) const {
// return m_propertyMgr->getProperties();
// }
//----------------------------------------------------------------------
// Protected Member Functions
//----------------------------------------------------------------------
Russell Taylor
committed
/// Set the Algorithm initialized state
Russell Taylor
committed
void Algorithm::setInitialized( )
{
m_isInitialized = true;
}
/// Set the executed flag to the specified state
// Public in Gaudi - don't know why and will leave here unless we find a reason otherwise
// Also don't know reason for different return type and argument.
Russell Taylor
committed
void Algorithm::setExecuted( bool state )
{
m_isExecuted = state;
}
/// Set the Algorithm finalized state
Russell Taylor
committed
void Algorithm::setFinalized( )
{
m_isFinalized = true;
}
Russell Taylor
committed
} // namespace Kernel
} // namespace Mantid