Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:12:10

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