Skip to content
Snippets Groups Projects
Algorithm.cpp 11.8 KiB
Newer Older
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "Algorithm.h"
#include "AnalysisDataService.h"

  // Get a reference to the logger
  Logger& Algorithm::g_log = Logger::get("Algorithm");

Matt Clarke's avatar
Matt Clarke committed
  Algorithm::Algorithm() :
    m_inputWorkspace(0),
    m_outputWorkspace(0),
    m_name("unknown"),
    m_version("unknown"),
    m_isInitialized(false),
    m_isExecuted(false),
    m_isFinalized(false)
  /** 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 
  /** The version of the algorithm
   * 
   *  @return Version string
   */ 
  const std::string& Algorithm::version() const 
  /** 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() 
  {
    // Bypass the initialization if the algorithm
    // has already been initialized.
    if ( m_isInitialized ) return StatusCode::SUCCESS;
    // 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;
Matt Clarke's avatar
Matt Clarke committed
      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;        
      
      // 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.
    {
      // Gaudi: A call to the auditor service is here
      // (1) perform the printout
      g_log.fatal("UNKNOWN Exception is caught ");
      // 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
    */
    // Return a failure if the algorithm hasn't been initialized
    if ( !isInitialized() ) return StatusCode::FAILURE;

    // Set the input and output workspaces
    std::string inputWorkspaceName;
Matt Clarke's avatar
Matt Clarke committed
   
    m_outputWorkspace = 0;
    m_inputWorkspace = 0;
    m_outputWorkspaceName = "";
    AnalysisDataService* ADS = AnalysisDataService::Instance();
Matt Clarke's avatar
Matt Clarke committed
    
    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");
Matt Clarke's avatar
Matt Clarke committed
		    return status;
    // 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");
      }
Matt Clarke's avatar
Matt Clarke committed
   
      setExecuted(true);
      
      // NOTE THAT THERE IS NO EXECUTION OF SUB-ALGORITHMS HERE.
      // THIS HAS TO BE EXPLICITLY DONE BY THE PARENT ALGORITHM'S exec() METHOD.
      
      return status;
    }
    // Gaudi also specifically catches GaudiException & std:exception.
    catch (...)
    {
Matt Clarke's avatar
Matt Clarke committed
      // 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.
      g_log.error("UNKNOWN Exception is caught ");
  
      // 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() 
    // Bypass the finalization if the algorithm hasn't been initialized or
    // has already been finalized.
    if ( !isInitialized() || isFinalized() ) return StatusCode::FAILURE;
  
    // Invoke final() method of the derived class inside a try/catch clause
    try
    {
      StatusCode status(StatusCode::SUCCESS,true);
Matt Clarke's avatar
Matt Clarke 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.
Matt Clarke's avatar
Matt Clarke committed
    
      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;
        }
      }		
  
      // Invoke the final() method of the derived class
Matt Clarke's avatar
Matt Clarke committed
      StatusCode Fstatus= final();
      if( Fstatus.isFailure() ) status=Fstatus;
  
      // Release all sub-algorithms (uses IInterface release method in Gaudi instead of direct delete)
Matt Clarke's avatar
Matt Clarke committed
      for (it = m_subAlgms.begin(); it != m_subAlgms.end(); it++) 
      
      // 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
Matt Clarke's avatar
Matt Clarke committed
      g_log.error("UNKNOWN Exception is caught ");   
Matt Clarke's avatar
Matt Clarke committed
      std::vector<Algorithm *>::iterator it;	    
      for (it = m_subAlgms.begin(); it != m_subAlgms.end(); it++) 
    }
    
    // Only gets to here if an exception is encountered
    return StatusCode::FAILURE;
  }
  
  /// Has the Algorithm already been initialized
  bool Algorithm::isInitialized( ) const 
  /// Has the Algorithm already been executed
  bool Algorithm::isExecuted() const 
Matt Clarke's avatar
Matt Clarke committed
  /// Has the Algorithm already been finalized?
  bool Algorithm::isFinalized( ) const
  /** 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, 
    /// @todo This method needs implementing now that we have an algorithm factory
  // IProperty implementation
  // Empty for now - requires Property manager
Matt Clarke's avatar
Matt Clarke committed
  //  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;
Matt Clarke's avatar
Matt Clarke committed
  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 
Matt Clarke's avatar
Matt Clarke committed
  {
    // 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
  //----------------------------------------------------------------------
  /// Set the Algorithm initialized state
  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.
  void Algorithm::setExecuted( bool state ) 
  {
    m_isExecuted = state;
  }
  
  /// Set the Algorithm finalized state
  void Algorithm::setFinalized( )
  {
    m_isFinalized = true;
  }