Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-12 08:21:35

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #pragma once
0010 
0011 #include <functional>
0012 #include <limits>
0013 
0014 #include <TColor.h>
0015 #include <TDirectory.h>
0016 #include <TH1F.h>
0017 #include <TString.h>
0018 
0019 /// Helper function:
0020 /// function to set up the histogram style
0021 ///
0022 /// @tparam hist_t the histogram type
0023 ///
0024 /// @param hist the histogram
0025 /// @param color the color
0026 template <typename hist_t>
0027 void setHistStyle(hist_t* hist, short color = 1) {
0028   if (hist == nullptr) {
0029     return;
0030   }
0031   hist->GetXaxis()->SetTitleSize(0.04);
0032   hist->GetYaxis()->SetTitleSize(0.04);
0033   hist->GetXaxis()->SetLabelSize(0.04);
0034   hist->GetYaxis()->SetLabelSize(0.04);
0035   hist->GetXaxis()->SetTitleOffset(1.0);
0036   hist->GetYaxis()->SetTitleOffset(1.0);
0037   hist->GetXaxis()->SetNdivisions(505);
0038   hist->SetMarkerStyle(20);
0039   hist->SetMarkerSize(0.8);
0040   hist->SetLineWidth(2);
0041   hist->SetTitle("");
0042   hist->SetLineColor(color);
0043   hist->SetMarkerColor(color);
0044 }
0045 
0046 /// Helper function:
0047 /// function to set up the efficiency histogram style
0048 ///
0049 /// @tparam eff_t the efficiency histogram type
0050 ///
0051 /// @param eff the efficiency histogram
0052 /// @param color the color to be set
0053 template <typename eff_t>
0054 void setEffStyle(eff_t* eff, short color = 1) {
0055   eff->SetMarkerStyle(20);
0056   eff->SetMarkerSize(0.8);
0057   eff->SetLineWidth(2);
0058   eff->SetLineColor(color);
0059   eff->SetMarkerColor(color);
0060 }
0061 
0062 /// Helper function: set color palette
0063 ///
0064 /// @tparam type of the histogram
0065 ///
0066 /// @param h the histogram in question
0067 /// @param rmin the range min value
0068 /// @param rmax the range max value
0069 /// @param rgood the good value of the mistogram
0070 /// @param rwindow the window around the good value to be declared good
0071 /// @param n the number of divisions
0072 template <typename hist_t>
0073 void adaptColorPalette(hist_t* h, float rmin, float rmax, float rgood,
0074                        float rwindow, int n) {
0075   // min - max is the range of the axis
0076   float rel_good = (rgood - rmin) / (rmax - rmin);
0077   float rel_window = rwindow / (rmax - rmin);
0078 
0079   // Stops are
0080   const int number = 5;
0081   double red[number] = {0., 0., 0., 1., 1.};
0082   double green[number] = {0., 1., 1., 1., 0.};
0083   double blue[number] = {1., 1., 0., 0., 0.};
0084   double stops[number] = {0., rel_good - rel_window, rel_good,
0085                           rel_good + rel_window, 1.};
0086   h->SetContour(n);
0087 
0088   TColor::CreateGradientColorTable(number, stops, red, green, blue, n);
0089 }
0090 
0091 /// Helper function:
0092 /// increase eff range by a scale factor. Note that it assumes the eff has
0093 /// already been drawn
0094 ///
0095 /// @tparam eff_t the efficiency histogram type
0096 ///
0097 /// @param eff the efficiency histogram
0098 /// @param minScale the minimum of the scale
0099 /// @param maxScale the maximum of the scale
0100 template <typename eff_t>
0101 void adaptEffRange(eff_t* eff, float minScale = 1, float maxScale = 1.1) {
0102   gPad->Update();
0103   auto ymin = gPad->GetUymin();
0104   auto ymax = gPad->GetUymax();
0105   auto graph = eff->GetPaintedGraph();
0106   graph->SetMinimum(ymin * minScale);
0107   graph->SetMaximum(ymax * maxScale);
0108   gPad->Modified();
0109   gPad->Update();
0110 }
0111 
0112 /// A Parameter handle struct to deal with
0113 /// residuals and pulls.
0114 ///
0115 /// This struct allows to define accessors and
0116 /// cuts for residual and pull analysis in order
0117 /// to be able to access them in an ROOT event loop
0118 struct ResidualPullHandle {
0119   /// A tag name
0120   std::string tag = "";
0121 
0122   /// Title and names: residual
0123   std::string residualStr = "";
0124   std::string residualUnit = "";
0125 
0126   /// Title and names: error
0127   std::string errorStr = "";
0128 
0129   /// The rangeDrawStr draw string
0130   std::string rangeDrawStr = "";
0131   std::string rangeMaxStr = "";
0132   std::string rangeCutStr = "";
0133 
0134   /// The range array
0135   std::array<float, 2> range = {0., 0.};
0136 
0137   /// Value function that allows to create
0138   /// combined parameters
0139   std::function<float(ULong64_t)> value;
0140 
0141   /// The associated error accessor
0142   std::function<float(ULong64_t)> error;
0143 
0144   /// The acceptance
0145   std::function<bool(ULong64_t)> accept;
0146 
0147   TH1F* rangeHist = nullptr;
0148 
0149   TH1F* residualHist = nullptr;
0150 
0151   TH1F* pullHist = nullptr;
0152 
0153   ULong64_t accepted = 0;
0154 
0155   /// Fill the entry
0156   ///
0157   /// @param entry is the current TTree entry to be processed
0158   void fill(unsigned int entry) {
0159     if (accept(entry)) {
0160       // Access the value, error
0161       float v = value(entry);
0162       residualHist->Fill(v);
0163       pullHist->Fill(v / error(entry));
0164       // Count the accessor
0165       ++accepted;
0166     }
0167   };
0168 };
0169 
0170 /// This is a s
0171 struct SingleHandle {
0172   /// A tag name
0173   std::string tag = "";
0174 
0175   /// A label name
0176   std::string label = "";
0177 
0178   // Range draw string
0179   std::string rangeDrawStr = "";
0180 
0181   /// The number of bins for the booking
0182   unsigned int bins = 1;
0183 
0184   /// The range array
0185   std::array<float, 2> range = {0., 0.};
0186 
0187   /// Value function that allows to create
0188   /// combined parameters
0189   std::function<float(ULong64_t)> value;
0190 
0191   /// The acceptance
0192   std::function<bool(ULong64_t)> accept;
0193 
0194   TH1F* hist = nullptr;
0195 
0196   /// Fill the entry
0197   ///
0198   /// @param entry is the current TTree entry to be processed
0199   void fill(unsigned int entry) {
0200     if (accept(entry)) {
0201       // Access the value, error
0202       float v = value(entry);
0203       hist->Fill(v);
0204     }
0205   }
0206 };
0207 
0208 /// This is a combined accept struct
0209 ///
0210 /// It allows to define muleiple accept struct in a chained way
0211 struct AcceptCombination {
0212   std::function<bool(ULong64_t)> one;
0213 
0214   std::function<bool(ULong64_t)> two;
0215 
0216   /// returns true if value is within range
0217   /// @param entry the entry in the tree
0218   bool operator()(ULong64_t entry) { return (one(entry) && two(entry)); }
0219 };
0220 
0221 /// This Struct is to accept all values - a placeholder
0222 struct AcceptAll {
0223   // Call operator always returns true
0224   bool operator()(ULong64_t /*event*/) { return true; }
0225 };
0226 
0227 /// This Struct is to accept a certain range from a
0228 /// TTree accessible value
0229 struct AcceptRange {
0230   std::vector<float>* value = nullptr;
0231 
0232   std::array<float, 2> range = {0., 0.};
0233 
0234   /// returns true if value is within range
0235   /// @param entry the entry in the tree
0236   bool operator()(ULong64_t entry) {
0237     if (value != nullptr) {
0238       float v = value->at(entry);
0239       return (range[0] <= v && range[1] > v);
0240     }
0241     return false;
0242   }
0243 };
0244 
0245 /// This is a direct type accessor
0246 ///
0247 /// It simply forwards access to the underlying vector
0248 ///
0249 template <typename primitive_t>
0250 struct DirectAccessor {
0251   std::vector<primitive_t>* value = nullptr;
0252 
0253   /// Gives direct access to the underlying parameter
0254   ///
0255   /// @param entry the entry in the tree
0256   primitive_t operator()(ULong64_t entry) {
0257     if (value) {
0258       primitive_t v = value->at(entry);
0259       return v;
0260     }
0261     return std::numeric_limits<primitive_t>::max();
0262   }
0263 };
0264 
0265 // Division accessor
0266 template <typename primitive_one_t, typename primitive_two_t>
0267 struct DivisionAccessor {
0268   std::vector<primitive_one_t>* one = nullptr;
0269 
0270   std::vector<primitive_two_t>* two = nullptr;
0271 
0272   /// Gives direct access to the underlying parameter
0273   ///
0274   /// @param entry the entry in the tree
0275   primitive_one_t operator()(ULong64_t entry) {
0276     if (one && two) {
0277       primitive_one_t vo = one->at(entry);
0278       primitive_two_t vt = two->at(entry);
0279       return vo / vt;
0280     }
0281     return std::numeric_limits<primitive_one_t>::max();
0282   }
0283 };
0284 
0285 // This is a residual type accessor
0286 struct ResidualAccessor {
0287   std::vector<float>* value = nullptr;
0288 
0289   std::vector<float>* reference = nullptr;
0290 
0291   /// @return the calculated Residual
0292   ///
0293   /// @param entry the entry in the tree
0294   float operator()(ULong64_t entry) {
0295     if (value != nullptr && reference != nullptr) {
0296       float v = value->at(entry);
0297       float r = reference->at(entry);
0298       return (v - r);
0299     }
0300     return std::numeric_limits<float>::infinity();
0301   }
0302 };
0303 
0304 // This is a  dedicated qop residual accessor
0305 struct QopResidualAccessor {
0306   std::vector<float>* qop_value = nullptr;
0307 
0308   std::vector<int>* reference_charge = nullptr;
0309 
0310   std::vector<float>* reference_p = nullptr;
0311 
0312   /// @return the calculated Residual for q/p
0313   ///
0314   /// @param entry the entry in the tree
0315   float operator()(ULong64_t entry) {
0316     if (qop_value != nullptr && reference_charge != nullptr &&
0317         reference_p != nullptr) {
0318       float v = qop_value->at(entry);
0319       float q_true = reference_charge->at(entry);
0320       float p_true = reference_p->at(entry);
0321       return (v - q_true / p_true);
0322     }
0323     return std::numeric_limits<float>::infinity();
0324   }
0325 };
0326 
0327 /// This the dedicted pT residual accessor
0328 struct PtResidualAccessor {
0329   std::vector<float>* qop_value = nullptr;
0330 
0331   std::vector<float>* theta_value = nullptr;
0332 
0333   std::vector<float>* reference_pt = nullptr;
0334 
0335   /// @return the calculated Residual
0336   ///
0337   /// @param entry the entry in the tree
0338   float operator()(ULong64_t entry) {
0339     if (qop_value != nullptr && theta_value != nullptr &&
0340         reference_pt != nullptr) {
0341       float p = 1. / std::abs(qop_value->at(entry));
0342       float theta = theta_value->at(entry);
0343       float pt_true = reference_pt->at(entry);
0344       return (p * std::sin(theta) - pt_true);
0345     }
0346     return std::numeric_limits<float>::infinity();
0347   }
0348 };
0349 
0350 // This is a dedicated pT error accessor
0351 struct PtErrorAccessor {
0352   std::vector<float>* qop_value = nullptr;
0353   std::vector<float>* qop_error = nullptr;
0354 
0355   std::vector<float>* theta_value = nullptr;
0356   std::vector<float>* theta_error = nullptr;
0357 
0358   /// @return the calculated error on pT
0359   ///
0360   /// @param entry the entry in the tree
0361   float operator()(ULong64_t entry) {
0362     if (qop_value != nullptr && qop_error != nullptr &&
0363         theta_value != nullptr && theta_error != nullptr) {
0364       float qop_v = qop_value->at(entry);
0365       float qop_e = qop_error->at(entry);
0366       float theta_v = theta_value->at(entry);
0367       float theta_e = theta_error->at(entry);
0368       return std::cos(theta_v) / qop_v * theta_e -
0369              std::sin(theta_v) / (qop_v * qop_v) * qop_e;
0370     }
0371     return std::numeric_limits<float>::infinity();
0372   }
0373 };
0374 
0375 /// Range estimation for residuals
0376 ///
0377 /// @tparam dir_t the type of the directory to change into for writing
0378 /// @tparam tree_t the type of the tree to Draw from
0379 ///
0380 /// @param handle the residual/pull handle to be processed
0381 /// @param directory the writable directory
0382 /// @param tree the tree from which is drawn
0383 /// @param peakEntries the number of entries for the range peak
0384 /// @param hBarcode a temporary unique ROOT barcode for memory managements
0385 template <typename dir_t, typename tree_t>
0386 void estimateResiudalRange(ResidualPullHandle& handle, dir_t& directory,
0387                            tree_t& tree, unsigned long peakEntries,
0388                            unsigned int hBarcode) {
0389   // Change into the Directory
0390   directory.cd();
0391   TString rangeHist = handle.rangeDrawStr;
0392   rangeHist += ">>";
0393   // Hist name snipped
0394   TString rangeHN = "hrg_";
0395   rangeHN += hBarcode;
0396   // Full histogram
0397   rangeHist += rangeHN;
0398   rangeHist += handle.rangeMaxStr;
0399 
0400   // Do the drawing
0401   tree.Draw(rangeHist.Data(), handle.rangeCutStr.c_str(), "", peakEntries);
0402   handle.rangeHist = dynamic_cast<TH1F*>(gDirectory->Get(rangeHN.Data()));
0403   if (handle.rangeHist != nullptr) {
0404     float rms = handle.rangeHist->GetRMS();
0405     handle.range = {-rms, rms};
0406   }
0407 }
0408 
0409 /// Range estimation for integer values
0410 ///
0411 /// @tparam dir_t the type of the directory to change into for writing
0412 /// @tparam tree_t the type of the tree to Draw from
0413 ///
0414 /// @param handle the residual/pull handle to be processed
0415 /// @param directory the writable directory
0416 /// @param tree the tree from which is drawn
0417 /// @param peakEntries the number of entries for the range peak
0418 /// @param hBarcode a temporary unique ROOT barcode for memory managements
0419 template <typename dir_t, typename tree_t>
0420 void estimateIntegerRange(SingleHandle& handle, dir_t& directory, tree_t& tree,
0421                           unsigned long peakEntries, unsigned int startBins,
0422                           unsigned int addBins, unsigned int hBarcode) {
0423   // Change into the Directory
0424   directory.cd();
0425   TString rangeHist = handle.rangeDrawStr;
0426   rangeHist += ">>";
0427   // Hist name snipped
0428   TString rangeHN = "hrg_";
0429   rangeHN += hBarcode;
0430   // Full histogram
0431   rangeHist += rangeHN;
0432   rangeHist += "(";
0433   rangeHist += startBins;
0434   rangeHist += ",-0.5,";
0435   rangeHist += static_cast<float>(startBins - 0.5);
0436   rangeHist += ")";
0437 
0438   unsigned int nBins = startBins;
0439   // Do the drawing
0440   tree.Draw(rangeHist.Data(), "", "", peakEntries);
0441   auto rhist = dynamic_cast<TH1F*>(gDirectory->Get(rangeHN.Data()));
0442   if (rhist != nullptr) {
0443     for (unsigned int ib = 1; ib <= startBins; ++ib) {
0444       if (rhist->GetBinContent(ib) > 0.) {
0445         nBins = ib;
0446       }
0447     }
0448     handle.bins = (nBins + addBins);
0449     handle.range = {-0.5, static_cast<float>(handle.bins - 0.5)};
0450     return;
0451   }
0452   handle.bins = (startBins);
0453   handle.range = {-0.5, static_cast<float>(handle.bins - 0.5)};
0454 }
0455 
0456 /// Helper method to book residual and pull histograms
0457 ///
0458 /// @param handle the residual/pull handle
0459 /// @param pullRange the symmetric pull range for plotting
0460 /// @param hBins the number of histograms bins
0461 /// @param hBarcoode a temporary unique barcode for ROOT memory management
0462 void bookHistograms(ResidualPullHandle& handle, float pullRange,
0463                     unsigned int hBins, unsigned int hBarcode) {
0464   // Residual histogram
0465   TString rName = std::string("res_") + handle.tag;
0466   rName += hBarcode;
0467   handle.residualHist =
0468       new TH1F(rName.Data(), handle.tag.c_str(), hBins,
0469                pullRange * handle.range[0], pullRange * handle.range[1]);
0470   std::string xAxisTitle =
0471       handle.residualStr + std::string(" ") + handle.residualUnit;
0472   handle.residualHist->GetXaxis()->SetTitle(xAxisTitle.c_str());
0473   handle.residualHist->GetYaxis()->SetTitle("Entries");
0474 
0475   // Pull histogram
0476   TString pName = std::string("pull_") + handle.tag;
0477   pName += hBarcode;
0478   handle.pullHist =
0479       new TH1F(pName.Data(), (std::string("pull ") + handle.tag).c_str(), hBins,
0480                -pullRange, pullRange);
0481   xAxisTitle = std::string("(") + handle.residualStr + std::string(")/") +
0482                handle.errorStr;
0483   handle.pullHist->GetXaxis()->SetTitle(xAxisTitle.c_str());
0484   handle.pullHist->GetYaxis()->SetTitle("Entries");
0485 }
0486 
0487 /// Helper method to get and opentially overwrite the entries to be processed
0488 ///
0489 /// @tparam tree_t the type of the tree
0490 ///
0491 /// @param tree is the TTree/TChain in question
0492 /// @param configuredEntries is a configuration parameter
0493 ///
0494 /// @return the number of entries
0495 template <typename tree_t>
0496 unsigned long estimateEntries(const tree_t& tree,
0497                               unsigned long configuredEntries) {
0498   unsigned long entries = static_cast<unsigned long>(tree.GetEntries());
0499   if (configuredEntries > 0 && configuredEntries < entries) {
0500     entries = configuredEntries;
0501   }
0502   return entries;
0503 }