Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-27 09:14:57

0001 // lAger: General Purpose l/A-event Generator
0002 // Copyright (C) 2016-2021 Sylvester Joosten <sjoosten@anl.gov>
0003 // 
0004 // This file is part of lAger.
0005 // 
0006 // lAger is free software: you can redistribute it and/or modify
0007 // it under the terms of the GNU General Public License as published by
0008 // the Free Shoftware Foundation, either version 3 of the License, or
0009 // (at your option) any later version.
0010 // 
0011 // lAger is distributed in the hope that it will be useful,
0012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
0013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0014 // GNU General Public License for more details.
0015 // 
0016 // You should have received a copy of the GNU General Public License
0017 // along with lAger.  If not, see <https://www.gnu.org/licenses/>.
0018 // 
0019 
0020 #ifndef LAGER_CORE_HISTOGRAMMER_LOADED
0021 #define LAGER_CORE_HISTOGRAMMER_LOADED
0022 
0023 // an easy to define 1D and 2D histo that will automatically get its own
0024 // variables from Data using a custom getter (f(Data...){return Double_t;})
0025 
0026 #include <functional>
0027 #include <memory>
0028 #include <vector>
0029 
0030 #include <TFile.h>
0031 #include <TH1D.h>
0032 #include <TH2D.h>
0033 
0034 #include <lager/core/configuration.hh>
0035 #include <lager/core/interval.hh>
0036 
0037 // =============================================================================
0038 // helper class for more elegant histogram constructors
0039 //
0040 // members:
0041 //  * name: this variable name
0042 //  * getter: function that takes computes the variable value from (Data...)
0043 //  * n_bins: number of histogram bins
0044 //  * range: the [min, max] range of the histogram
0045 // =============================================================================
0046 namespace lager {
0047 template <class... Data> struct histogram_variable {
0048   using getter_type = std::function<Double_t(Data...)>;
0049 
0050   const std::string name;
0051   const getter_type getter;
0052   const Int_t n_bins;
0053   const interval<Double_t> range;
0054 
0055   histogram_variable(const std::string& name, const getter_type& getter,
0056                      const Int_t n_bins, const interval<Double_t> range)
0057       : name{name}, getter{getter}, n_bins{n_bins}, range{range} {}
0058 };
0059 } // ns lager
0060 
0061 // =============================================================================
0062 // Histogrammer class to auto-generate 1D and 2D histos from data
0063 //
0064 // members:
0065 //  * add_histo(shared_ptr<TFile>, name, var_x[, var_y])
0066 //  * add_histo(shared_ptr<TFile>, name, title, var_x[, var_y])
0067 //        ==> add 1D and 2D histos to the histogrammer
0068 //  * fill(Data..., weight)
0069 //        ==> fill all histograms using Data... as input
0070 // =============================================================================
0071 namespace lager {
0072 namespace histogrammer_impl {
0073 // utility classes needed by histogrammer
0074 template <class... Data> class histo1D;
0075 template <class... Data> class histo2D;
0076 } // ns histogrammer_impl
0077 
0078 template <class... Data> class histogrammer {
0079 public:
0080   using histo1D_type = histogrammer_impl::histo1D<Data...>;
0081   using histo2D_type = histogrammer_impl::histo2D<Data...>;
0082   using histo_var_type = histogram_variable<Data...>;
0083 
0084   histogrammer(const string_path& path, std::string name, std::string title)
0085       : path_{path.str()}, name_{std::move(name)}, title_{std::move(title)} {}
0086   histogrammer(const std::string& name) : histogrammer("", name, name) {}
0087   histogrammer(const histogrammer&) = delete;
0088   histogrammer& operator=(const histogrammer&) = delete;
0089 
0090   // add 1D histos
0091   void add_histo(std::shared_ptr<TFile> file, const std::string& name,
0092                  const std::string& title, const histo_var_type& var) {
0093     histos_1D_.push_back(
0094         std::move(histo1D_type{std::move(file), path_, format_name(name_, name),
0095                                format_title(title_, title), var}));
0096   }
0097   void add_histo(std::shared_ptr<TFile> file, const std::string& name,
0098                  const histo_var_type& var) {
0099     add_histo(std::move(file), name, name, var);
0100   }
0101   // add 2D histos
0102   void add_histo(std::shared_ptr<TFile> file, const std::string& name,
0103                  const std::string& title, const histo_var_type& var_x,
0104                  const histo_var_type& var_y) {
0105     histos_2D_.push_back(
0106         std::move(histo2D_type{std::move(file), path_, format_name(name_, name),
0107                                format_title(title_, title), var_x, var_y}));
0108   }
0109   void add_histo(std::shared_ptr<TFile> file, const std::string& name,
0110                  const histo_var_type& var_x, const histo_var_type& var_y) {
0111     add_histo(std::move(file), name, name, var_x, var_y);
0112   }
0113 
0114   // fill the histos
0115   void fill(Data... d, Double_t weight = 1.) {
0116     for (auto& h : histos_1D_) {
0117       h.fill(d..., weight);
0118     }
0119     for (auto& h : histos_2D_) {
0120       h.fill(d..., weight);
0121     }
0122   }
0123 
0124 private:
0125   const std::string path_;
0126   const std::string name_;
0127   const std::string title_;
0128   std::vector<histo1D_type> histos_1D_;
0129   std::vector<histo2D_type> histos_2D_;
0130 };
0131 
0132 } // ns lager
0133 
0134 // =============================================================================
0135 // Implementation: histo1D and histo2D
0136 // =============================================================================
0137 namespace lager {
0138 namespace histogrammer_impl {
0139 template <class... Data> class histo1D
0140 {
0141 public:
0142   using var_type = histogram_variable<Data...>;
0143   using getter_type = typename var_type::getter_type;
0144 
0145   histo1D(std::shared_ptr<TFile> file, const std::string& path,
0146           const std::string& name, const std::string& title,
0147           const var_type& var)
0148       : file_{std::move(file)}
0149       , path_{path}
0150       , getter_{var.getter}
0151       , histo_{nullptr} {
0152     if (file_) {
0153       file_->cd();
0154       if (path.size() && !file_->GetDirectory(path.c_str())) {
0155         file_->mkdir(path.c_str());
0156       }
0157       file_->cd(path.c_str());
0158       histo_ = new TH1D{name.c_str(), title.c_str(), var.n_bins, var.range.min,
0159                         var.range.max};
0160       histo_->GetXaxis()->SetTitle(var.name.c_str());
0161       histo_->GetYaxis()->SetTitle("#");
0162       file_->cd();
0163     }
0164   }
0165   histo1D(std::shared_ptr<TFile> file, const std::string& name,
0166           const var_type& var)
0167       : histo1D(std::move(file), "", name, name, var) {}
0168   // don't allow regular copying/assigment to avoid unexpected destructor
0169   // actions
0170   histo1D(const histo1D&) = delete;
0171   histo1D& operator=(const histo1D&) = delete;
0172   // move constructor to allow for handling histo rvalues without spurious
0173   // destructor invocations
0174   histo1D(histo1D&& rhs)
0175       : file_{std::move(rhs.file_)}
0176       , path_{rhs.path_}
0177       , getter_{rhs.getter_}
0178       , histo_{rhs.histo_} {
0179     rhs.file_.reset();
0180     rhs.histo_ = nullptr;
0181   }
0182 
0183   ~histo1D() {
0184     if (file_ && histo_) {
0185       if (path_.size()) {
0186         file_->cd(path_.c_str());
0187       }
0188       histo_->Write();
0189       file_->cd();
0190     }
0191   }
0192 
0193   Int_t fill(Data... d, Double_t weight = 1.) {
0194     if (file_ && histo_) {
0195       return histo_->Fill(getter_(d...), weight);
0196     }
0197     return -1;
0198   }
0199 
0200   TH1D* histo() { return histo_; }
0201 
0202 private:
0203   std::shared_ptr<TFile> file_;
0204   const std::string path_;
0205   const getter_type getter_;
0206   TH1D* histo_; // resource managed by file_
0207 };
0208 // 2D histo that uses a two custom 'getter's to extract the values from a Reader
0209 template <class... Data> class histo2D {
0210 public:
0211   using var_type = histogram_variable<Data...>;
0212   using getter_type = typename var_type::getter_type;
0213 
0214   histo2D(std::shared_ptr<TFile> file, const std::string& path,
0215           const std::string& name, const std::string& title,
0216           const var_type& var_x, const var_type& var_y)
0217       : file_{std::move(file)}
0218       , path_{path}
0219       , getter_x_{var_x.getter}
0220       , getter_y_{var_y.getter}
0221       , histo_{nullptr} {
0222     if (file_) {
0223       file_->cd();
0224       if (path.size() && !file_->GetDirectory(path.c_str())) {
0225         file_->mkdir(path.c_str());
0226       }
0227       file_->cd(path.c_str());
0228       histo_ = new TH2D{name.c_str(),    title.c_str(),   var_x.n_bins,
0229                         var_x.range.min, var_x.range.max, var_y.n_bins,
0230                         var_y.range.min, var_y.range.max};
0231       // set the hist to use the nicer colz drawing option
0232       histo_->SetOption("colz");
0233       histo_->GetXaxis()->SetTitle(var_x.name.c_str());
0234       histo_->GetYaxis()->SetTitle(var_y.name.c_str());
0235     }
0236   }
0237   histo2D(std::shared_ptr<TFile> file, const std::string& name,
0238           const var_type& var_x, const var_type& var_y)
0239       : histo2D(std::move(file), "", name, name, var_x, var_y) {}
0240   // don't allow regular copying/assigment to avoid unexpected destructor
0241   // actions
0242   histo2D(const histo2D&) = delete;
0243   histo2D& operator=(const histo2D&) = delete;
0244   // move constructor to allow for handling histo rvalues without spurious
0245   // destructor invocations
0246   histo2D(histo2D&& rhs)
0247       : file_{std::move(rhs.file_)}
0248       , path_{rhs.path_}
0249       , getter_x_{rhs.getter_x_}
0250       , getter_y_{rhs.getter_y_}
0251       , histo_{rhs.histo_} {
0252     rhs.file_.reset();
0253     rhs.histo_ = nullptr;
0254   }
0255 
0256   ~histo2D() {
0257     if (file_ && histo_) {
0258       if (path_.size()) {
0259         file_->cd(path_.c_str());
0260       }
0261       histo_->Write();
0262       file_->cd();
0263     }
0264   }
0265 
0266   Int_t fill(Data... d, Double_t weight = 1.) {
0267     if (file_ && histo_) {
0268       return histo_->Fill(getter_x_(d...), getter_y_(d...), weight);
0269     }
0270     return -1;
0271   }
0272 
0273   TH2D* histo() { return histo_; }
0274 
0275 private:
0276   std::shared_ptr<TFile> file_;
0277   const std::string& path_;
0278   const getter_type getter_x_;
0279   const getter_type getter_y_;
0280   TH2D* histo_; // resource managed by file_
0281 };
0282 } // ns histogrammer_impl
0283 } // ns lager
0284 
0285 #endif