diff --git a/CepGen/Core/ModuleFactory.h b/CepGen/Core/ModuleFactory.h index 5582d78..e9f4204 100644 --- a/CepGen/Core/ModuleFactory.h +++ b/CepGen/Core/ModuleFactory.h @@ -1,96 +1,101 @@ #ifndef CepGen_Core_ModuleFactory_h #define CepGen_Core_ModuleFactory_h #include "CepGen/Core/ParametersList.h" #include #include #include #include #define BUILDERNM( obj ) obj ## Builder #define STRINGIFY( name ) #name namespace cepgen { /// A generic factory to build modules /// \tparam T Base class to build /// \tparam I Indexing variable type template class ModuleFactory { public: /// Retrieve a unique instance of this factory static ModuleFactory& get() { static ModuleFactory instance; return instance; } /// Default destructor ~ModuleFactory() = default; /// Register a named module in the database /// \tparam U Class to register (inherited from T base class) template void registerModule( const I& name, const ParametersList& def_params = ParametersList() ) { static_assert( std::is_base_of::value, "\n\n *** Failed to register an object with improper inheritance into the factory. ***\n" ); + if ( map_.count( name ) > 0 || params_map_.count( name ) > 0 ) { + std::ostringstream oss; + oss << __PRETTY_FUNCTION__ << "\n\n *** Duplicate module registration detected for index/name \"" << name << "\"! ***\n"; + throw std::invalid_argument( oss.str() ); + } map_[name] = &build; params_map_[name] = def_params; } /// Build one instance of a named module /// \param[in] name Module name to retrieve /// \param[in] params List of parameters to be invoked by the constructor std::unique_ptr build( const I& name, ParametersList params = ParametersList() ) const { if ( name == I() || map_.count( name ) == 0 ) { std::ostringstream oss; oss << __PRETTY_FUNCTION__ << "\n\n *** Failed to build a module with index/name \"" << name << "\" from factory! ***\n"; throw std::invalid_argument( oss.str() ); } if ( params_map_.count( name ) > 0 ) params += params_map_.at( name ); return map_.at( name )( params ); } /// Build one instance of a named module /// \param[in] params List of parameters to be invoked by the constructor std::unique_ptr build( ParametersList params = ParametersList() ) const { if ( params.has( KEY ) ) { const I& idx = params.get( KEY ); if ( map_.count( idx ) == 0 ) throw std::invalid_argument( std::string( __PRETTY_FUNCTION__ )+"\n\n *** Failed to build a module with index/name \""+std::to_string( idx )+"\" from factory! ***\n" ); if ( params_map_.count( idx ) > 0 ) params += params_map_.at( idx ); return map_.at( idx )( params ); } else throw std::invalid_argument( std::string( __PRETTY_FUNCTION__ )+"\n\n *** Failed to retrieve an indexing key from parameters to build from factory! ***\n" ); } /// List of modules registred in the database std::vector modules() const { std::vector out; for ( const auto& p : map_ ) out.emplace_back( p.first ); return out; } static constexpr const char* KEY = "id"; private: explicit ModuleFactory() = default; /// Construct a module with its parameters set template static std::unique_ptr build( const ParametersList& params ) { return std::unique_ptr( new U( params ) ); } protected: /// Constructor type for a module typedef std::unique_ptr (*ModCreate)( const ParametersList& ); /// Database of modules handled by this instance std::unordered_map map_; /// Database of default parameters associated to modules std::unordered_map params_map_; public: ModuleFactory( const ModuleFactory& ) = delete; void operator=( const ModuleFactory& ) = delete; }; } #endif diff --git a/CepGen/IO/ROOTTreeHandler.cpp b/CepGen/IO/ROOTTreeHandler.cpp index 2b4d51f..7565eb9 100644 --- a/CepGen/IO/ROOTTreeHandler.cpp +++ b/CepGen/IO/ROOTTreeHandler.cpp @@ -1,103 +1,103 @@ #include "CepGen/IO/ExportHandler.h" #include "CepGen/IO/ROOTTreeInfo.h" #include "CepGen/Core/Exception.h" #include "CepGen/Core/ParametersList.h" #include "CepGen/Event/Event.h" #include "CepGen/Parameters.h" // ROOT includes #include "TFile.h" #include namespace cepgen { namespace io { /** * Handler for the storage of events in a ROOT format * \author Laurent Forthomme * \date 27 Jan 2014 */ class ROOTTreeHandler : public GenericExportHandler { public: /// Class constructor explicit ROOTTreeHandler( const ParametersList& ); ~ROOTTreeHandler(); void initialise( const Parameters& ) override; /// Writer operator void operator<<( const Event& ) override; void setCrossSection( double, double ) override; private: std::unique_ptr file_; std::unique_ptr run_tree_; std::unique_ptr evt_tree_; }; ROOTTreeHandler::ROOTTreeHandler( const ParametersList& params ) : GenericExportHandler( "root" ), file_( TFile::Open( params.get( "filename", "output.root" ).c_str(), "recreate" ) ), run_tree_( new ROOT::CepGenRun ), evt_tree_( new ROOT::CepGenEvent ) { if ( !file_->IsOpen() ) throw CG_FATAL( "ROOTTreeHandler" ) << "Failed to create the output file!"; run_tree_->create(); evt_tree_->create(); } ROOTTreeHandler::~ROOTTreeHandler() { run_tree_->fill(); file_->Write(); } void ROOTTreeHandler::initialise( const Parameters& params ) { run_tree_->litigious_events = 0; run_tree_->sqrt_s = params.kinematics.sqrtS(); } void ROOTTreeHandler::operator<<( const Event& ev ) { evt_tree_->gen_time = ev.time_generation; evt_tree_->tot_time = ev.time_total; evt_tree_->np = 0; for ( const auto& p : ev.particles() ) { const cepgen::Particle::Momentum m = p.momentum(); evt_tree_->rapidity[evt_tree_->np] = m.rapidity(); evt_tree_->pt[evt_tree_->np] = m.pt(); evt_tree_->eta[evt_tree_->np] = m.eta(); evt_tree_->phi[evt_tree_->np] = m.phi(); evt_tree_->E[evt_tree_->np] = p.energy(); evt_tree_->m[evt_tree_->np] = p.mass(); evt_tree_->pdg_id[evt_tree_->np] = p.integerPdgId(); evt_tree_->parent1[evt_tree_->np] = ( p.mothers().size() > 0 ) ? *p.mothers().begin() : -1; evt_tree_->parent2[evt_tree_->np] = ( p.mothers().size() > 1 ) ? *p.mothers().rbegin() : -1; evt_tree_->status[evt_tree_->np] = (int)p.status(); evt_tree_->stable[evt_tree_->np] = ( (short)p.status() > 0 ); evt_tree_->charge[evt_tree_->np] = p.charge(); evt_tree_->role[evt_tree_->np] = p.role(); evt_tree_->np++; } run_tree_->num_events += 1; evt_tree_->fill(); } void ROOTTreeHandler::setCrossSection( double xsect, double xsect_err ) { run_tree_->xsect = xsect; run_tree_->errxsect = xsect_err; } } } -REGISTER_IO_MODULE( root, ROOTTreeHandler ) +REGISTER_IO_MODULE( root_tree, ROOTTreeHandler )