#ifndef HISTOGRAM_HH_INCLUDED #define HISTOGRAM_HH_INCLUDED #include "Computable.hh" using stringutil::print; using stringutil::exec; using stringutil::strip_comments; /*! a generic wrapper around the root 1d, 2d, and 3d histogram classes */ struct Histogram { string name; string analysis_name; // something that ends up in the name. string flavor; string vars; // e.g. Enu:cos_theta (refer to Observable names) vector< Observable* > _obs_ptrs; // the quantities on the axes int dim; // dimesion TH1* H; // The actual root histogram string selectionname; string weightname; string variantname; vector options; // for post-processing etc Variant* variant; //! Selection* selection; //! Weight* weight; //! string draw_option; /*! colon separated list of all observable names */ string observables() const { return join(":", _obs_ptrs, [] (Observable * p) { return p->name ; } ); } string key() const { auto vars = observables(); return analysis_name + "_" + flavor + "_" + vars + variantname + selectionname + weightname; } string title() { key(); return analysis_name + " " + flavor + " " + variantname + " " + selectionname + " " + weightname; } Histogram(): H(0) { } // initializing pointers to zero is super-important for ROOT io (prevent horrible segfaults) virtual ~Histogram() { // print("Histrogram dtor", key() ); } Histogram( string analysis_name_, string flavor_, const vector& observables, Variant& variant_, Selection& selection_, Weight& weight_ ) { analysis_name = analysis_name_; flavor = flavor_; selection = &selection_; weight = &weight_; variant = &variant_; selectionname = selection->name; weightname = weight->name; variantname = variant->name; _obs_ptrs = observables; dim = _obs_ptrs.size(); vars = join(":", observables, [] (Observable * p) { return p->name ; } ); name = "H_" + analysis_name + "_" + flavor + "_" + join( "_v_", _obs_ptrs, [](Observable * ptr) { return ptr->name; } ) + "_" + variant->name + "_" + selection->name + "_" + weight->name; string title = ""; if ( dim == 1 ) { H = new TH1D( name.c_str(), title.c_str(), _obs_ptrs[0]->nbins , _obs_ptrs[0]->minval , _obs_ptrs[0]->maxval ); draw_option = "hist"; H->SetXTitle( observables[0]->axis_label().c_str() ); } if ( dim == 2 ) { H = new TH2D( name.c_str(), title.c_str(), _obs_ptrs[0]->nbins , _obs_ptrs[0]->minval , _obs_ptrs[0]->maxval , _obs_ptrs[1]->nbins , _obs_ptrs[1]->minval , _obs_ptrs[1]->maxval ); draw_option = "colz"; H->SetXTitle( observables[0]->axis_label().c_str() ); H->SetYTitle( observables[1]->axis_label().c_str() ); } if ( dim == 3 ) { H = new TH3D( name.c_str(), title.c_str(), _obs_ptrs[0]->nbins , _obs_ptrs[0]->minval , _obs_ptrs[0]->maxval , _obs_ptrs[1]->nbins , _obs_ptrs[1]->minval , _obs_ptrs[1]->maxval , _obs_ptrs[2]->nbins , _obs_ptrs[2]->minval , _obs_ptrs[2]->maxval ); draw_option = "BOX"; H->SetXTitle( observables[0]->axis_label().c_str() ); H->SetYTitle( observables[1]->axis_label().c_str() ); H->SetZTitle( observables[2]->axis_label().c_str() ); } } /*! Fill the histogram if selection is true, and using weight */ void fill ( Evt& evt ) { if ( selection->eval( evt ) == 0 ) return; double w = weight->eval(evt); slurp( evt, w ); } void slurp( Evt& evt, double weight = 1 ) { if ( dim == 1 ) H->Fill ( _obs_ptrs[0] -> eval(evt), weight ); if ( dim == 2 ) ( (TH2D*) H) ->Fill ( _obs_ptrs[0] -> eval(evt), _obs_ptrs[1] -> eval(evt), weight ); if ( dim == 3 ) ( (TH3D*) H ) ->Fill ( _obs_ptrs[0] -> eval(evt), _obs_ptrs[1] -> eval(evt), _obs_ptrs[2] -> eval(evt), weight ); } void slurp( Evt& evt, double weight , int chache_id ) { if ( dim == 1 ) H->Fill ( _obs_ptrs[0] -> eval(evt, chache_id), weight ); if ( dim == 2 ) ( (TH2D*) H) ->Fill ( _obs_ptrs[0] -> eval(evt, chache_id), _obs_ptrs[1] -> eval(evt, chache_id), weight ); if ( dim == 3 ) ( (TH3D*) H ) ->Fill ( _obs_ptrs[0] -> eval(evt, chache_id), _obs_ptrs[1] -> eval(evt, chache_id), _obs_ptrs[2] -> eval(evt, chache_id), weight ); } string info() { ostringstream s; auto write = stringutil::coolprinter::printer(s); write("histogram : ", H -> GetName() ); write("title : ", H -> GetTitle() ); write("analysis_name : ", analysis_name ); write("flavor : ", flavor ); write("variant : ", variant->info() ); write("selection : ", selection->info() ); write("weight : ", weight->info() ); write("draw_option : ", draw_option ); for ( auto o : _obs_ptrs ) { write( "observable: ", o->info() ); } return s.str(); } // why oh why is this not just in root (or: why can't I find it ;-) void set_style( TH1& donor ) { H->TAttFill::operator=( donor ); H->TAttLine::operator=( donor ); H->TAttMarker::operator=( donor ); } }; inline Table tabulate( const vector& histograms ) { Table T( split("histogram-name key type flavor selection weight entries integral mean over under dir ")) ; T.title = "Histogram Table"; for ( auto& o : histograms ) { string n = o.H->GetDirectory()? o.H->GetDirectory()->GetName() : "null"; T << o.H->GetName() << o.key() << o.H->IsA()->GetName() << o.flavor << o.selectionname << o.weightname << o.H->GetEntries() << o.H->Integral() << o.H->GetMean() << o.H->GetBinContent(0) << o.H->GetBinContent( o.H->GetNbinsX() + 1 ) << n ; } return T; } #endif