diff --git a/Cards/legacy/lpair.card b/Cards/legacy/lpair.card index 5c832a2..df55cef 100644 --- a/Cards/legacy/lpair.card +++ b/Cards/legacy/lpair.card @@ -1,22 +1,24 @@ PROC lpair MODE 1 IEND 3 NCVG 100000 ITVG 10 INPP 6500. PMOD 11 INPE 6500. #EMOD 2 PAIR 13 MCUT 2 PTCT 15. ECUT 0. NGEN 100000 ETMN -2.5 ETMX 2.5 MXMX 1000.0 #THMN 0. #THMX 180. XIMN 0.02 XIMX 0.15 +#OUTP lhef +OUTP text diff --git a/Cards/lpair_cfg.py b/Cards/lpair_cfg.py index 92304ef..02c6246 100644 --- a/Cards/lpair_cfg.py +++ b/Cards/lpair_cfg.py @@ -1,38 +1,40 @@ import Config.Core as cepgen from Config.Integration.vegas_cff import integrator #from Config.Hadronisation.pythia6_cff import pythia6 as hadroniser #from Config.Hadronisation.pythia8_cff import pythia8 as hadroniser from Config.PDG_cfi import PDG process = cepgen.Module('lpair', processParameters = cepgen.Parameters( mode = cepgen.ProcessMode.InelasticElastic, pair = PDG.muon, ), inKinematics = cepgen.Parameters( pz = (6500., 6500.), structureFunctions = cepgen.StructureFunctions.SuriYennie, #structureFunctions = cepgen.StructureFunctions.FioreBrasse, #structureFunctions = cepgen.StructureFunctions.LUXlike, ), outKinematics = cepgen.Parameters( pt = (25.,), energy = (0.,), eta = (-2.5, 2.5), mx = (1.07, 1000.), ), #tamingFunctions = cepgen.Parameters( # # example of a complex taming function # cepgen.Parameters(variable = "m_ll", expression = "(m_ll>80.) ? exp(-(m_ll-80)/10) : 1.0"), #), ) -output = cepgen.Module('text', variables = ['m(4)', 'pt(4)', 'xi(ob1)']) +#--- example of an output module parameterisation +#output = cepgen.Module('text', variables = ['m(4)']) +#output = cepgen.Module('lhef', output = 'test.lhe') #--- let the user specify the run conditions from Config.generator_cff import generator generator = generator.clone( numEvents = 100000, printEvery = 10000, ) diff --git a/CepGen/Cards/LpairHandler.cpp b/CepGen/Cards/LpairHandler.cpp index 4e72012..d9378ab 100644 --- a/CepGen/Cards/LpairHandler.cpp +++ b/CepGen/Cards/LpairHandler.cpp @@ -1,238 +1,249 @@ #include "CepGen/Cards/LpairHandler.h" #include "CepGen/Core/Exception.h" #include "CepGen/Core/ParametersList.h" #include "CepGen/Core/Integrator.h" #include "CepGen/Processes/ProcessesHandler.h" #include "CepGen/Hadronisers/HadronisersHandler.h" +#include "CepGen/IO/ExportHandler.h" #include "CepGen/StructureFunctions/StructureFunctions.h" #include "CepGen/Physics/GluonGrid.h" #include "CepGen/Physics/PDG.h" #include #include namespace cepgen { namespace card { const int LpairHandler::kInvalid = 99999; //----- specialization for LPAIR input cards LpairHandler::LpairHandler( const char* file ) : proc_params_( new ParametersList ), str_fun_( 11 ), sr_type_( 1 ), xi_min_( 0. ), xi_max_( 1. ), hi_1_( { 0, 0 } ), hi_2_( { 0, 0 } ) { std::ifstream f( file, std::fstream::in ); if ( !f.is_open() ) throw CG_FATAL( "LpairHandler" ) << "Failed to parse file \"" << file << "%s\"."; init(); //--- parse all fields std::unordered_map m_params; std::string key, value; std::ostringstream os; while ( f >> key >> value ) { if ( key[0] == '#' ) // FIXME need to ensure there is no extra space before! continue; setParameter( key, value ); m_params.insert( { key, value } ); if ( getDescription( key ) != "null" ) os << "\n>> " << key << " = " << std::setw( 15 ) << getParameter( key ) << " (" << getDescription( key ) << ")"; } f.close(); //--- parse the process name params_.setProcess( proc::ProcessesHandler::get().build( proc_name_, *proc_params_ ) ); const Limits lim_xi{ xi_min_, xi_max_ }; if ( lim_xi.valid() ) params_.kinematics.cuts.remnants.energy_single = ( lim_xi+(-1.) )*( -params_.kinematics.incoming_beams.first.pz ); //--- parse the structure functions code auto sf_params = ParametersList() .set( "id", str_fun_ ) .set( "sigmaRatio", ParametersList() .set( "id", sr_type_ ) ); const unsigned long kLHAPDFCodeDec = 10000000, kLHAPDFPartDec = 1000000; if ( str_fun_ / kLHAPDFCodeDec == 1 ) { // SF from parton const unsigned long icode = str_fun_ % kLHAPDFCodeDec; sf_params .set( "id", (int)strfun::Type::Partonic ) .set( "pdfId", icode % kLHAPDFPartDec ) .set( "mode", icode / kLHAPDFPartDec ); // 0, 1, 2 } else if ( str_fun_ == (int)strfun::Type::MSTWgrid ) sf_params .set( "gridPath", mstw_grid_path_ ); params_.kinematics.structure_functions = strfun::StructureFunctionsHandler::get().build( sf_params ); //--- parse the integration algorithm name if ( integr_type_ == "plain" ) params_.integration().type = IntegratorType::plain; else if ( integr_type_ == "Vegas" ) params_.integration().type = IntegratorType::Vegas; else if ( integr_type_ == "MISER" ) params_.integration().type = IntegratorType::MISER; else if ( integr_type_ != "" ) throw CG_FATAL( "LpairHandler" ) << "Unrecognized integrator type: " << integr_type_ << "!"; //--- parse the hadronisation algorithm name if ( !hadr_name_.empty() ) { params_.setHadroniser( cepgen::hadr::HadronisersHandler::get().build( hadr_name_, ParametersList() ) ); params_.hadroniser()->setParameters( params_ ); } + //--- parse the output module name + if ( !out_mod_name_.empty() ) { + ParametersList outm; + if ( !out_file_name_.empty() ) + outm.set( "filename", out_file_name_ ); + params_.setOutputModule( cepgen::io::ExportHandler::get().build( out_mod_name_, outm ) ); + } + if ( m_params.count( "IEND" ) ) setValue( "IEND", ( std::stoi( m_params["IEND"] ) > 1 ) ); if ( m_params.count( "KMRG" ) && !kmr_grid_path_.empty() ) kmr::GluonGrid::get( kmr_grid_path_.c_str() ); //--- check if we are dealing with heavy ions for incoming states HeavyIon hi1{ hi_1_.first, (Element)hi_1_.second }, hi2{ hi_2_.first, (Element)hi_2_.second }; if ( hi1 ) params_.kinematics.incoming_beams.first.pdg = hi1; if ( hi2 ) params_.kinematics.incoming_beams.second.pdg = hi2; CG_INFO( "LpairHandler" ) << "File '" << file << "' succesfully opened!\n\t" << "The following parameters are set:" << os.str(); } void LpairHandler::init() { //------------------------------------------------------------------------------------------- // Process/integration/hadronisation parameters //------------------------------------------------------------------------------------------- registerParameter( "PROC", "Process name to simulate", &proc_name_ ); registerParameter( "ITYP", "Integration algorithm", &integr_type_ ); registerParameter( "HADR", "Hadronisation algorithm", &hadr_name_ ); + registerParameter( "OUTP", "Output module", &out_mod_name_ ); + registerParameter( "OUTF", "Output file name", &out_file_name_ ); registerParameter( "KMRG", "KMR grid interpolation path", &kmr_grid_path_ ); //------------------------------------------------------------------------------------------- // General parameters //------------------------------------------------------------------------------------------- registerParameter( "IEND", "Generation type", ¶ms_.generation().enabled ); registerParameter( "NTRT", "Smoothen the integrand", ¶ms_.generation().treat ); registerParameter( "DEBG", "Debugging verbosity", (int*)&utils::Logger::get().level ); registerParameter( "NCVG", "Number of function calls", (int*)¶ms_.integration().ncvg ); registerParameter( "ITVG", "Number of integration iterations", (int*)¶ms_.integration().vegas.iterations ); registerParameter( "SEED", "Random generator seed", (int*)¶ms_.integration().rng_seed ); registerParameter( "NTHR", "Number of threads to use for events generation", (int*)¶ms_.generation().num_threads ); registerParameter( "MODE", "Subprocess' mode", (int*)¶ms_.kinematics.mode ); registerParameter( "NCSG", "Number of points to probe", (int*)¶ms_.generation().num_points ); registerParameter( "NGEN", "Number of events to generate", (int*)¶ms_.generation().maxgen ); registerParameter( "NPRN", "Number of events before printout", (int*)¶ms_.generation().gen_print_every ); //------------------------------------------------------------------------------------------- // Process-specific parameters //------------------------------------------------------------------------------------------- registerParameter( "METH", "Computation method (kT-factorisation)", &proc_params_->operator[]( "method" ) ); registerParameter( "IPOL", "Polarisation states to consider", &proc_params_->operator[]( "polarisationStates" ) ); //------------------------------------------------------------------------------------------- // Process kinematics parameters //------------------------------------------------------------------------------------------- registerParameter( "MGRD", "MSTW grid interpolation path", &mstw_grid_path_ ); registerParameter( "PMOD", "Outgoing primary particles' mode", &str_fun_ ); registerParameter( "EMOD", "Outgoing primary particles' mode", &str_fun_ ); registerParameter( "RTYP", "R-ratio computation type", &sr_type_ ); registerParameter( "PAIR", "Outgoing particles' PDG id", (int*)&proc_params_->operator[]( "pair" ) ); registerParameter( "INA1", "Heavy ion atomic weight (1st incoming beam)", (int*)&hi_1_.first ); registerParameter( "INZ1", "Heavy ion atomic number (1st incoming beam)", (int*)&hi_1_.second ); registerParameter( "INA2", "Heavy ion atomic weight (1st incoming beam)", (int*)&hi_2_.first ); registerParameter( "INZ2", "Heavy ion atomic number (1st incoming beam)", (int*)&hi_2_.second ); registerParameter( "INP1", "Momentum (1st primary particle)", ¶ms_.kinematics.incoming_beams.first.pz ); registerParameter( "INP2", "Momentum (2nd primary particle)", ¶ms_.kinematics.incoming_beams.second.pz ); registerParameter( "INPP", "Momentum (1st primary particle)", ¶ms_.kinematics.incoming_beams.first.pz ); registerParameter( "INPE", "Momentum (2nd primary particle)", ¶ms_.kinematics.incoming_beams.second.pz ); registerParameter( "PTCT", "Minimal transverse momentum (single central outgoing particle)", ¶ms_.kinematics.cuts.central.pt_single.min() ); registerParameter( "MSCT", "Minimal central system mass", ¶ms_.kinematics.cuts.central.mass_sum.min() ); registerParameter( "ECUT", "Minimal energy (single central outgoing particle)", ¶ms_.kinematics.cuts.central.energy_single.min() ); registerParameter( "ETMN", "Minimal pseudo-rapidity (central outgoing particles)", ¶ms_.kinematics.cuts.central.eta_single.min() ); registerParameter( "ETMX", "Maximal pseudo-rapidity (central outgoing particles)", ¶ms_.kinematics.cuts.central.eta_single.max() ); registerParameter( "YMIN", "Minimal rapidity (central outgoing particles)", ¶ms_.kinematics.cuts.central.rapidity_single.min() ); registerParameter( "YMAX", "Maximal rapidity (central outgoing particles)", ¶ms_.kinematics.cuts.central.rapidity_single.max() ); registerParameter( "Q2MN", "Minimal Q² = -q² (exchanged parton)", ¶ms_.kinematics.cuts.initial.q2.min() ); registerParameter( "Q2MX", "Maximal Q² = -q² (exchanged parton)", ¶ms_.kinematics.cuts.initial.q2.max() ); registerParameter( "MXMN", "Minimal invariant mass of proton remnants", ¶ms_.kinematics.cuts.remnants.mass_single.min() ); registerParameter( "MXMX", "Maximal invariant mass of proton remnants", ¶ms_.kinematics.cuts.remnants.mass_single.max() ); registerParameter( "XIMN", "Minimal fractional momentum loss of outgoing proton (ξ)", &xi_min_ ); registerParameter( "XIMX", "Maximal fractional momentum loss of outgoing proton (ξ)", &xi_max_ ); } void LpairHandler::store( const char* file ) { std::ofstream f( file, std::fstream::out | std::fstream::trunc ); if ( !f.is_open() ) throw CG_ERROR( "LpairHandler" ) << "Failed to open file \"" << file << "%s\" for writing."; for ( const auto& it : p_strings_ ) if ( it.second.value ) f << it.first << " = " << *it.second.value << "\n"; for ( const auto& it : p_ints_ ) if ( it.second.value ) f << it.first << " = " << *it.second.value << "\n"; for ( const auto& it : p_doubles_ ) if ( it.second.value ) f << it.first << " = " << *it.second.value << "\n"; for ( const auto& it : p_bools_ ) if ( it.second.value ) f << it.first << " = " << *it.second.value << "\n"; f.close(); } void LpairHandler::setParameter( const std::string& key, const std::string& value ) { try { setValue( key.c_str(), std::stod( value ) ); } catch ( const std::invalid_argument& ) {} try { setValue( key.c_str(), std::stoi( value ) ); } catch ( const std::invalid_argument& ) {} try { setValue( key.c_str(), value ); } catch ( const std::invalid_argument& ) { throw CG_FATAL( "LpairHandler:setParameter" ) << "Failed to add the parameter \"" << key << "\" → \"" << value << "\"!"; } } std::string LpairHandler::getParameter( std::string key ) const { double dd = getValue( key.c_str() ); if ( dd != -999. ) return std::to_string( dd ); int ui = getValue( key.c_str() ); if ( ui != 999 ) return std::to_string( ui ); //if ( out = getValue( key.c_str() ) ); return getValue( key.c_str() ); } std::string LpairHandler::getDescription( std::string key ) const { if ( p_strings_.count( key ) ) return p_strings_.find( key )->second.description; if ( p_ints_.count( key ) ) return p_ints_.find( key )->second.description; if ( p_doubles_.count( key ) ) return p_doubles_.find( key )->second.description; if ( p_bools_.count( key ) ) return p_bools_.find( key )->second.description; return "null"; } } } diff --git a/CepGen/Cards/LpairHandler.h b/CepGen/Cards/LpairHandler.h index 0064dd0..fef13af 100644 --- a/CepGen/Cards/LpairHandler.h +++ b/CepGen/Cards/LpairHandler.h @@ -1,118 +1,121 @@ #ifndef CepGen_Cards_LpairReader_h #define CepGen_Cards_LpairReader_h #include "CepGen/Cards/Handler.h" #include using std::string; namespace cepgen { class ParametersList; namespace card { /// LPAIR-like steering cards parser and writer class LpairHandler : public Handler { public: /// Read a LPAIR steering card explicit LpairHandler( const char* file ); /// Store a configuration into a LPAIR steering card void store( const char* file ); private: /// Single parameter handler /// \tparam T Parameter type template struct Parameter { Parameter( const char* key, const char* descr, T* value ) : key( key ), description( descr ), value( value ) {} std::string key, description; T* value; }; /// Register a parameter to be steered to a configuration variable template void registerParameter( const char* key, const char* description, T* def ) {} /// Set a parameter value template void setValue( const char* key, const T& value ) {} /// Retrieve a parameter value template T getValue( const char* key ) const {} void setParameter( const std::string& key, const std::string& value ); std::string getParameter( std::string key ) const; std::string getDescription( std::string key ) const; static const int kInvalid; std::unordered_map > p_strings_; std::unordered_map > p_doubles_; std::unordered_map > p_ints_; std::unordered_map > p_bools_; void init(); std::shared_ptr proc_params_; int str_fun_, sr_type_; double xi_min_, xi_max_; - std::string proc_name_, hadr_name_, integr_type_, kmr_grid_path_, mstw_grid_path_; + std::string proc_name_, hadr_name_, out_mod_name_; + std::string out_file_name_; + std::string integr_type_; + std::string kmr_grid_path_, mstw_grid_path_; std::pair hi_1_, hi_2_; }; //----- specialised registerers /// Register a string parameter template<> inline void LpairHandler::registerParameter( const char* key, const char* description, std::string* def ) { p_strings_.insert( std::make_pair( key, Parameter( key, description, def ) ) ); } /// Register a double floating point parameter template<> inline void LpairHandler::registerParameter( const char* key, const char* description, double* def ) { p_doubles_.insert( std::make_pair( key, Parameter( key, description, def ) ) ); } /// Register an integer parameter template<> inline void LpairHandler::registerParameter( const char* key, const char* description, int* def ) { p_ints_.insert( std::make_pair( key, Parameter( key, description, def ) ) ); } /// Register a boolean parameter template<> inline void LpairHandler::registerParameter( const char* key, const char* description, bool* def ) { p_bools_.insert( std::make_pair( key, Parameter( key, description, def ) ) ); } //----- specialised setters template<> inline void LpairHandler::setValue( const char* key, const std::string& value ) { auto it = p_strings_.find( key ); if ( it != p_strings_.end() ) *it->second.value = value; } template<> inline void LpairHandler::setValue( const char* key, const double& value ) { auto it = p_doubles_.find( key ); if ( it != p_doubles_.end() ) *it->second.value = value; } template<> inline void LpairHandler::setValue( const char* key, const int& value ) { auto it = p_ints_.find( key ); if ( it != p_ints_.end() ) *it->second.value = value; } template<> inline void LpairHandler::setValue( const char* key, const bool& value ) { auto it = p_bools_.find( key ); if ( it != p_bools_.end() ) *it->second.value = value; } //----- specialised getters /// Retrieve a string parameter value template<> inline std::string LpairHandler::getValue( const char* key ) const { const auto& it = p_strings_.find( key ); if ( it != p_strings_.end() ) return *it->second.value; return "null"; } /// Retrieve a floating point parameter value template<> inline double LpairHandler::getValue( const char* key ) const { const auto& it = p_doubles_.find( key ); if ( it != p_doubles_.end() ) return *it->second.value; return -999.; } /// Retrieve an integer parameter value template<> inline int LpairHandler::getValue( const char* key ) const { const auto& it = p_ints_.find( key ); if ( it != p_ints_.end() ) return *it->second.value; return 999; } /// Retrieve a boolean parameter value template<> inline bool LpairHandler::getValue( const char* key ) const { const auto& it = p_bools_.find( key ); if ( it != p_bools_.end() ) return *it->second.value; return true; } } } #endif diff --git a/CepGen/Core/Version.cpp b/CepGen/Core/Version.cpp index 868096f..432ea30 100644 --- a/CepGen/Core/Version.cpp +++ b/CepGen/Core/Version.cpp @@ -1,12 +1,12 @@ #include "CepGen/Version.h" #include "CepGen/Core/utils.h" namespace cepgen { const std::string version() { - return Form( "%02u.%02u.%02u", ( cepgen_version >> 16 ) & 0xff, - ( cepgen_version >> 8 ) & 0xff, - cepgen_version & 0xff ); + return Form( "%u.%u.%u", ( cepgen_version >> 16 ) & 0xff, + ( cepgen_version >> 8 ) & 0xff, + cepgen_version & 0xff ); } } diff --git a/CepGen/IO/GenericExportHandler.cpp b/CepGen/IO/GenericExportHandler.cpp index 62ae8d9..5c5cd6b 100644 --- a/CepGen/IO/GenericExportHandler.cpp +++ b/CepGen/IO/GenericExportHandler.cpp @@ -1,72 +1,72 @@ #include "CepGen/IO/GenericExportHandler.h" #include "CepGen/StructureFunctions/StructureFunctions.h" #include "CepGen/Physics/Constants.h" #include "CepGen/Parameters.h" #include "CepGen/Version.h" #include namespace cepgen { namespace io { GenericExportHandler::GenericExportHandler( const std::string& name ) : name_( name ), event_num_( 0. ) {} GenericExportHandler::~GenericExportHandler() {} std::string - GenericExportHandler::banner( const Parameters& params ) + GenericExportHandler::banner( const Parameters& params, const std::string& prep ) { std::ostringstream os; os - << " ***** Sample generated with CepGen v" << version() << " *****\n" - << " * process: " << params.processName() << " (" << params.kinematics.mode << ")\n"; + << prep << " ***** Sample generated with CepGen v" << version() << " *****\n" + << prep << " * process: " << params.processName() << " (" << params.kinematics.mode << ")\n"; if ( params.kinematics.mode != KinematicsMode::ElasticElastic ) { - os << " * structure functions: " << params.kinematics.structure_functions->description() << "\n"; + os << prep << " * structure functions: " << params.kinematics.structure_functions->description() << "\n"; if ( !params.hadroniserName().empty() ) - os << " * hadroniser: " << params.hadroniserName() << "\n"; + os << prep << " * hadroniser: " << params.hadroniserName() << "\n"; } os - << " *--- incoming state\n"; + << prep << " *--- incoming state\n"; if ( params.kinematics.cuts.initial.q2.valid() ) os - << " * Q2 range (GeV2): " + << prep << " * Q2 range (GeV2): " << params.kinematics.cuts.initial.q2 << "\n"; if ( params.kinematics.mode != KinematicsMode::ElasticElastic && params.kinematics.cuts.remnants.mass_single.valid() ) os - << " * remnants mass range (GeV/c2): " + << prep << " * remnants mass range (GeV/c2): " << params.kinematics.cuts.remnants.mass_single << "\n"; - os << " *--- central system\n"; + os << prep << " *--- central system\n"; if ( params.kinematics.cuts.central.pt_single.valid() ) os - << " * single particle pt (GeV/c): " + << prep << " * single particle pt (GeV/c): " << params.kinematics.cuts.central.pt_single << "\n"; if ( params.kinematics.cuts.central.energy_single.valid() ) os - << " * single particle energy (GeV): " + << prep << " * single particle energy (GeV): " << params.kinematics.cuts.central.energy_single << "\n"; if ( params.kinematics.cuts.central.eta_single.valid() ) os - << " * single particle eta: " + << prep << " * single particle eta: " << params.kinematics.cuts.central.eta_single << "\n"; if ( params.kinematics.cuts.central.pt_sum.valid() ) os - << " * total pt (GeV/c): " + << prep << " * total pt (GeV/c): " << params.kinematics.cuts.central.mass_sum << "\n"; if ( params.kinematics.cuts.central.mass_sum.valid() ) os - << " * total invariant mass (GeV/c2): " + << prep << " * total invariant mass (GeV/c2): " << params.kinematics.cuts.central.mass_sum << "\n"; os - << " **************************************************"; + << prep << " **************************************************"; return os.str(); } } } diff --git a/CepGen/IO/GenericExportHandler.h b/CepGen/IO/GenericExportHandler.h index cf998e6..775ce03 100644 --- a/CepGen/IO/GenericExportHandler.h +++ b/CepGen/IO/GenericExportHandler.h @@ -1,46 +1,46 @@ #ifndef CepGen_IO_GenericExportHandler_h #define CepGen_IO_GenericExportHandler_h #include #include namespace cepgen { class Event; class Parameters; /// Location for all output generators namespace io { /** * \brief Output format handler for events export * \author Laurent Forthomme * \date Sep 2016 */ class GenericExportHandler { public: /// Class constructor explicit GenericExportHandler( const std::string& ); virtual ~GenericExportHandler(); const std::string& name() const { return name_; } /// Initialise the handler and its inner parameterisation virtual void initialise( const Parameters& ) = 0; /// Set the process cross section and its associated error virtual void setCrossSection( double /*xsec*/, double /*err_xsec*/ ) {} /// Set the event number void setEventNumber( const unsigned int& ev_id ) { event_num_ = ev_id; } /// Writer operator virtual void operator<<( const Event& ) = 0; protected: - static std::string banner( const Parameters& ); + static std::string banner( const Parameters&, const std::string& prep = "" ); /// Module unique name const std::string name_; /// Event index unsigned int event_num_; }; } } #endif diff --git a/CepGen/IO/TextHandler.cpp b/CepGen/IO/TextHandler.cpp index d16a508..96ffdb5 100644 --- a/CepGen/IO/TextHandler.cpp +++ b/CepGen/IO/TextHandler.cpp @@ -1,187 +1,195 @@ #include "CepGen/IO/ExportHandler.h" #include "CepGen/Core/Exception.h" #include "CepGen/Core/ParametersList.h" #include "CepGen/Event/Event.h" #include "CepGen/Parameters.h" +#include "CepGen/Version.h" #include #include namespace cepgen { namespace io { /** * \brief Handler for the generic text file output * \author Laurent Forthomme * \date Jul 2019 */ class TextHandler : public GenericExportHandler { public: explicit TextHandler( const ParametersList& ); ~TextHandler(); void initialise( const Parameters& ) override; void operator<<( const Event& ) override; private: /// Retrieve a named variable from a particle double variable( const Particle&, const std::string& ) const; /// Retrieve a named variable from the whole event double variable( const Event&, const std::string& ) const; static const std::regex rgx_select_id_, rgx_select_role_; static constexpr double INVALID_OUTPUT = -999.; std::ofstream file_; - std::vector variables_; + const std::vector variables_; + const bool print_banner_; //--- variables definition typedef std::pair IndexedVariable; std::unordered_map > variables_per_id_; std::unordered_map > variables_per_role_; std::vector variables_for_event_; unsigned short num_vars_; + std::ostringstream oss_vars_; //--- auxiliary helper maps const std::unordered_map role_str_ = { { "ib1", Particle::Role::IncomingBeam1 }, { "ib2", Particle::Role::IncomingBeam2 }, { "ob1", Particle::Role::OutgoingBeam1 }, { "ob2", Particle::Role::OutgoingBeam2 }, { "pa1", Particle::Role::Parton1 }, { "pa2", Particle::Role::Parton2 }, { "cs", Particle::Role::CentralSystem }, { "int", Particle::Role::Intermediate } }; typedef double( Particle::Momentum::*pMethod )(void) const; /// Mapping of string variables to momentum getter methods const std::unordered_map m_mom_str_ = { { "px", &Particle::Momentum::px }, { "py", &Particle::Momentum::py }, { "pz", &Particle::Momentum::pz }, { "pt", &Particle::Momentum::pt }, { "eta", &Particle::Momentum::eta }, { "phi", &Particle::Momentum::phi }, { "m", &Particle::Momentum::mass }, { "e", &Particle::Momentum::energy }, { "p", &Particle::Momentum::p }, { "pt2", &Particle::Momentum::pt2 }, { "th", &Particle::Momentum::theta }, { "y", &Particle::Momentum::rapidity } }; //--- kinematic variables double sqrts_; }; const std::regex TextHandler::rgx_select_id_( "(\\w+)\\((\\d+)\\)" ); const std::regex TextHandler::rgx_select_role_( "(\\w+)\\(([a-z]+\\d?)\\)" ); TextHandler::TextHandler( const ParametersList& params ) : GenericExportHandler( "text" ), - file_( params.get( "filename", "output.txt" ) ), - variables_( params.get >( "variables" ) ), + file_ ( params.get( "filename", "output.txt" ) ), + variables_ ( params.get >( "variables" ) ), + print_banner_( params.get( "saveBanner", true ) ), num_vars_( 0 ) { std::smatch sm; + oss_vars_.clear(); std::string sep; - file_ << "# "; + oss_vars_ << "# "; for ( const auto& var : variables_ ) { if ( std::regex_match( var, sm, rgx_select_id_ ) ) variables_per_id_[stod( sm[2].str() )].emplace_back( std::make_pair( num_vars_, sm[1].str() ) ); else if ( std::regex_match( var, sm, rgx_select_role_ ) ) { const auto& str_role = sm[2].str(); if ( role_str_.count( str_role ) == 0 ) { CG_WARNING( "TextHandler" ) << "Invalid particle role retrieved from configuration: \"" << str_role << "\".\n\t" << "Skipping the variable \"" << var << "\" in the output module."; continue; } variables_per_role_[role_str_.at( str_role )].emplace_back( std::make_pair( num_vars_, sm[1].str() ) ); } else // event-level variables variables_for_event_.emplace_back( std::make_pair( num_vars_, var ) ); - file_ << sep << var, sep = "\t"; + oss_vars_ << sep << var, sep = "\t"; ++num_vars_; } - file_ << "\n"; + oss_vars_ << "\n"; } TextHandler::~TextHandler() { file_.close(); } void TextHandler::initialise( const Parameters& params ) { sqrts_ = params.kinematics.sqrtS(); + if ( print_banner_ ) + file_ << banner( params, "#" ) << "\n"; + file_ << oss_vars_.str(); } void TextHandler::operator<<( const Event& ev ) { std::vector vars( num_vars_ ); //--- extract and order the variables to be retrieved //--- particle-level variables (indexed by integer id) for ( const auto& id_vars : variables_per_id_ ) { const auto& part = ev[id_vars.first]; //--- loop over the list of variables for this particle for ( const auto& var : id_vars.second ) vars[var.first] = variable( part, var.second ); } //--- particle-level variables (indexed by role) for ( const auto& role_vars : variables_per_role_ ) { const auto& part = ev[role_vars.first][0]; //--- loop over the list of variables for this particle for ( const auto& var : role_vars.second ) vars[var.first] = variable( part, var.second ); } //--- event-level variables for ( const auto& var : variables_for_event_ ) vars[var.first] = variable( ev, var.second ); //--- write down the variables list in the file std::string separator; for ( const auto& var : vars ) file_ << separator << var, separator = "\t"; file_ << "\n"; } double TextHandler::variable( const Particle& part, const std::string& var ) const { if ( m_mom_str_.count( var ) ) { auto meth = m_mom_str_.at( var ); return ( part.momentum().*meth )(); } else if ( var == "xi" ) return 1.-part.energy()*2./sqrts_; else if ( var == "pdg" ) return (double)part.integerPdgId(); else if ( var == "charge" ) return part.charge(); else if ( var == "status" ) return (double)part.status(); CG_WARNING( "TextHandler" ) << "Failed to retrieve variable \"" << var << "\"."; return INVALID_OUTPUT; } double TextHandler::variable( const Event& ev, const std::string& var ) const { if ( var == "nob1" || var == "nob2" ) { unsigned short out = 0.; for ( const auto& part : ev[ var == "nob1" ? Particle::Role::OutgoingBeam1 : Particle::Role::OutgoingBeam2 ] ) if ( (int)part.status() > 0 ) out++; return (double)out; } CG_WARNING( "TextHandler" ) << "Failed to retrieve the event-level variable \"" << var << "\"."; return INVALID_OUTPUT; } } } REGISTER_IO_MODULE( text, TextHandler )