diff --git a/CepGen/Core/utils.h b/CepGen/Core/utils.h index 13f287d..6482326 100644 --- a/CepGen/Core/utils.h +++ b/CepGen/Core/utils.h @@ -1,61 +1,63 @@ #ifndef CepGen_Core_utils_h #define CepGen_Core_utils_h #include #include #include namespace cepgen { /// Format a string using a printf style format descriptor. std::string Form( const std::string fmt, ... ); /// Human-readable boolean printout inline const char* yesno( const bool& test ) { return ( test ) ? "\033[32;1myes\033[0m" : "\033[31;1mno\033[0m"; } //inline const char* boldify( const char* str ) { const std::string out = std::string( "\033[33;1m" ) + std::string( str ) + std::string( "\033[0m" ); return out.c_str(); } /// Boldify a string for TTY-type output streams inline std::string boldify( const std::string& str ) { return Form( "\033[1m%s\033[0m", str.c_str() ); } /// Boldify a string for TTY-type output streams inline std::string boldify( const char* str ) { return boldify( std::string( str ) ); } /// Boldify a double floating point number for TTY-type output streams inline std::string boldify( const double& dbl ) { return boldify( Form("%.2f", dbl ) ); } /// Boldify an integer for TTY-type output streams inline std::string boldify( const int& i ) { return boldify( Form("% d", i ) ); } /// Boldify an unsigned integer for TTY-type output streams inline std::string boldify( const unsigned int& ui ) { return boldify( Form("%d", ui ) ); } /// Boldify an unsigned long integer for TTY-type output streams inline std::string boldify( const unsigned long& ui ) { return boldify( Form("%lu", ui ) ); } /// TTY-type enumeration of colours enum class Colour { gray = 30, red = 31, green = 32, yellow = 33, blue = 34, purple = 35 }; /// Colourise a string for TTY-type output streams inline std::string colourise( const std::string& str, const Colour& col ) { return Form( "\033[%d%s\033[0m", (int)col, str.c_str() ); } /// Replace all occurences of a text by another size_t replace_all( std::string& str, const std::string& from, const std::string& to ); namespace utils { /// Add a trailing "s" when needed - inline const char* s( unsigned short num ) { return ( num > 1 ) ? "s" : ""; } + inline const char* s( size_t num ) { return ( num > 1 ) ? "s" : ""; } + /// Add a trailing "s" when needed + inline std::string s( const std::string& word, size_t num ) { return Form( "%i %s%s", num, word.c_str(), ( num > 1 ) ? "s" : "" ); } /// Helper to print a vector template std::string repr( const std::vector& vec, const std::string& sep = "," ) { return std::accumulate( std::next( vec.begin() ), vec.end(), std::to_string( *vec.begin() ), [&sep]( std::string str, T xv ) { return std::move( str )+sep+std::to_string( xv ); } ); } class ProgressBar { public: ProgressBar( size_t tot, size_t freq = 10 ); void update( size_t iter ) const; private: static constexpr size_t BAR_LENGTH = 50; const std::string bar_pattern_; size_t total_, frequency_; }; } } /// Provide a random number generated along a uniform distribution between 0 and 1 #define drand() (double)rand()/RAND_MAX #endif diff --git a/CepGen/IO/TextHandler.cpp b/CepGen/IO/TextHandler.cpp index 7601a03..0183a13 100644 --- a/CepGen/IO/TextHandler.cpp +++ b/CepGen/IO/TextHandler.cpp @@ -1,186 +1,193 @@ #include "CepGen/IO/ExportHandler.h" #include "CepGen/Core/Exception.h" #include "CepGen/Core/ParametersList.h" #include "CepGen/Core/utils.h" #include "CepGen/Event/Event.h" #include "CepGen/Event/EventBrowser.h" #include "CepGen/Parameters.h" #include "CepGen/Version.h" #include #include #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 setCrossSection( double xsec, double ) override { xsec_ = xsec; } void operator<<( const Event& ) override; private: std::string textHistogram( const std::string&, const gsl_histogram* ) const; static constexpr size_t PLOT_WIDTH = 50; static constexpr char PLOT_CHAR = '#'; std::ofstream file_, hist_file_; + std::string hist_filename_; //--- variables definition const std::vector variables_; const bool save_banner_, save_variables_; const bool show_hists_, save_hists_; const std::string separator_; const utils::EventBrowser browser_; std::ostringstream oss_vars_; double xsec_; //--- kinematic variables double sqrts_; unsigned long num_evts_; struct gsl_histogram_deleter { void operator()( gsl_histogram* h ) { gsl_histogram_free( h ); } }; - std::unordered_map > hists_; + std::vector > > hists_; }; TextHandler::TextHandler( const ParametersList& params ) : GenericExportHandler( "text" ), file_ ( params.get( "filename", "output.txt" ) ), + hist_filename_ ( params.get( "histFilename", "output.hists.txt" ) ), variables_ ( params.get >( "variables" ) ), save_banner_ ( params.get( "saveBanner", true ) ), save_variables_( params.get( "saveVariables", true ) ), show_hists_ ( params.get( "showHistograms", true ) ), save_hists_ ( params.get( "saveHistograms", false ) ), separator_ ( params.get( "separator", "\t" ) ), xsec_( 1. ) { //--- first extract list of variables to store in output file oss_vars_.clear(); std::string sep; for ( const auto& var : variables_ ) oss_vars_ << sep << var, sep = separator_; //--- then extract list of variables to be plotted in histogram const auto& hist_vars = params.get( "histVariables" ); for ( const auto& var : hist_vars.keys() ) { const auto& hvar = hist_vars.get( var ); const int nbins = hvar.get( "nbins", 10 ); const double min = hvar.get( "low", 0. ), max = hvar.get( "high", 1. ); - hists_[var].reset( gsl_histogram_alloc( nbins ) ); - gsl_histogram_set_ranges_uniform( hists_[var].get(), min, max ); + auto hist = gsl_histogram_alloc( nbins ); + gsl_histogram_set_ranges_uniform( hist, min, max ); + hists_.emplace_back( std::make_pair( var, hist ) ); CG_INFO( "TextHandler" ) << "Booking a histogram with " << nbins << " bin" << utils::s( nbins ) << " between " << min << " and " << max << " for \"" << var << "\"."; } if ( save_hists_ && !hists_.empty() ) - hist_file_.open( "lastrun.hists.txt" ); + hist_file_.open( hist_filename_ ); } TextHandler::~TextHandler() { //--- finalisation of the output file file_.close(); //--- histograms printout if ( !show_hists_ && !save_hists_ ) return; for ( const auto& h_var : hists_ ) { const auto& hist = h_var.second.get(); gsl_histogram_scale( hist, xsec_/( num_evts_+1 ) ); const auto& h_out = textHistogram( h_var.first, hist ); if ( show_hists_ ) CG_INFO( "TextHandler" ) << h_out; if ( save_hists_ ) hist_file_ << "\n" << h_out << "\n"; } + if ( save_hists_ ) + CG_INFO( "TextHandler" ) + << "Saved " << utils::s( "histogram", hists_.size() ) + << " into \"" << hist_filename_ << "\"."; } void TextHandler::initialise( const Parameters& params ) { sqrts_ = params.kinematics.sqrtS(); num_evts_ = 0ul; if ( save_banner_ ) file_ << banner( params, "#" ) << "\n"; if ( save_variables_ ) file_ << "# " << oss_vars_.str() << "\n"; if ( save_hists_ && !hists_.empty() ) hist_file_ << banner( params, "#" ) << "\n"; } void TextHandler::operator<<( const Event& ev ) { //--- write down the variables list in the file std::string sep; for ( const auto& var : variables_ ) file_ << sep << browser_.get( ev, var ), sep = separator_; file_ << "\n"; //--- increment the corresponding histograms for ( const auto& h_var : hists_ ) gsl_histogram_increment( h_var.second.get(), browser_.get( ev, h_var.first ) ); ++num_evts_; } std::string TextHandler::textHistogram( const std::string& var, const gsl_histogram* hist ) const { std::ostringstream os; const size_t nbins = gsl_histogram_bins( hist ); const double max_bin = gsl_histogram_max_val( hist ); const double inv_max_bin = max_bin > 0. ? 1./max_bin : 0.; const std::string sep( 17, ' ' ); os << "plot of \"" << var << "\"\n" << sep << std::string( PLOT_WIDTH-15-var.size(), ' ' ) << "d(sig)/d" << var << " (pb/bin)\n" << sep << Form( "%-5.2f", gsl_histogram_min_val( hist ) ) << std::string( PLOT_WIDTH-8, ' ' ) << Form( "%5.2f", gsl_histogram_max_val( hist ) ) << "\n" << sep << std::string( PLOT_WIDTH+2, '.' ); // abscissa axis for ( size_t i = 0; i < nbins; ++i ) { double min, max; gsl_histogram_get_range( hist, i, &min, &max ); const double value = gsl_histogram_get( hist, i ); const int val = value*PLOT_WIDTH*inv_max_bin; os << "\n" << Form( "[%7.2f,%7.2f):", min, max ) << std::string( val, PLOT_CHAR ) << std::string( PLOT_WIDTH-val, ' ' ) << ": " << Form( "%6.2f", value ); } const double bin_width = ( gsl_histogram_max( hist )-gsl_histogram_min( hist ) )/nbins; os << "\n" << Form( "%15s", var.c_str() ) << ":" << std::string( PLOT_WIDTH, '.' ) << ":\n" // 2nd abscissa axis << "\t(" << "bin width=" << bin_width << " unit" << utils::s( (int)bin_width ) << ", " << "mean=" << gsl_histogram_mean( hist ) << ", " << "st.dev.=" << gsl_histogram_sigma( hist ) << ")"; return os.str(); } } } REGISTER_IO_MODULE( text, TextHandler )