Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:14:58

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 #include <cmath>
0010 #include <iostream>
0011 #include <map>
0012 #include <numbers>
0013 #include <string>
0014 #include <tuple>
0015 
0016 #include <TCanvas.h>
0017 #include <TDirectory.h>
0018 #include <TFile.h>
0019 #include <TH1F.h>
0020 #include <TProfile.h>
0021 #include <TTree.h>
0022 
0023 struct MaterialHistograms {
0024   TProfile* x0_vs_eta = nullptr;
0025   TProfile* l0_vs_eta = nullptr;
0026 
0027   TProfile* x0_vs_phi = nullptr;
0028   TProfile* l0_vs_phi = nullptr;
0029 
0030   float s_x0 = 0.;
0031   float s_l0 = 0.;
0032 
0033   MaterialHistograms() = default;
0034 
0035   /// Material histogram constructor
0036   ///
0037   /// @param iA the atomic number
0038   MaterialHistograms(const std::string& name, unsigned int iA,
0039                      unsigned int bins, float eta) {
0040     std::string x0NameEta =
0041         (iA == 0) ? name + std::string("_x0_vs_eta_all")
0042                   : name + std::string("_x0_vs_eta_A") + std::to_string(iA);
0043     std::string l0NameEta =
0044         (iA == 0) ? name + std::string("_l0_vs_eta_all")
0045                   : name + std::string("_l0_vs_eta_A") + std::to_string(iA);
0046 
0047     x0_vs_eta =
0048         new TProfile(x0NameEta.c_str(), "X_{0} vs. #eta", bins, -eta, eta);
0049     l0_vs_eta =
0050         new TProfile(l0NameEta.c_str(), "L_{0} vs. #eta", bins, -eta, eta);
0051 
0052     std::string x0NamePhi =
0053         (iA == 0) ? name + std::string("_x0_vs_phi_all")
0054                   : name + std::string("_x0_vs_phi_A") + std::to_string(iA);
0055     std::string l0NamePhi =
0056         (iA == 0) ? name + std::string("_l0_vs_phi_all")
0057                   : name + std::string("_l0_vs_phi_A") + std::to_string(iA);
0058 
0059     x0_vs_phi =
0060         new TProfile(x0NamePhi.c_str(), "X_{0} vs. #phi", bins, -std::numbers::pi, std::numbers::pi);
0061     l0_vs_phi =
0062         new TProfile(l0NamePhi.c_str(), "L_{0} vs. #phi", bins, -std::numbers::pi, std::numbers::pi);
0063   }
0064 
0065   /// This fills the event into the histograms
0066   /// and clears the cache accordingly
0067   ///
0068   /// @param eta the pseudorapidity value
0069   /// @param phi the phi value
0070   ///
0071   void fillAndClear(float eta, float phi) {
0072     x0_vs_eta->Fill(eta, s_x0);
0073     l0_vs_eta->Fill(eta, s_l0);
0074 
0075     x0_vs_phi->Fill(phi, s_x0);
0076     l0_vs_phi->Fill(phi, s_l0);
0077 
0078     s_x0 = 0.;
0079     s_l0 = 0.;
0080   }
0081 
0082   /// Write out the histograms, the TDirectory needs
0083   /// to be set before
0084   ///
0085   /// Histograms with no contribution will not be
0086   /// written to file.
0087   void write() {
0088     if (x0_vs_eta->GetMaximum() > 0.) {
0089       x0_vs_eta->Write();
0090       l0_vs_eta->Write();
0091 
0092       x0_vs_phi->Write();
0093       l0_vs_phi->Write();
0094     }
0095   }
0096 };
0097 
0098 struct Region {
0099   std::string name;
0100   std::vector<std::tuple<float, float, float, float>> boxes;
0101 
0102   bool inside(float r, float z) const {
0103     for (const auto& [minR, maxR, minZ, maxZ] : boxes) {
0104       if (minR <= r && r < maxR && minZ <= z && z < maxZ) {
0105         return true;
0106       }
0107     }
0108     return false;
0109   }
0110 };
0111 
0112 /// Plot the material composition
0113 ///
0114 /// @param inFile the input root file
0115 /// @param treeNAme the input tree name (default: 'trackstates)
0116 /// @param outFile the output root file
0117 /// @param bins the number of bins
0118 /// @param eta the eta range
0119 void materialComposition(const std::string& inFile, const std::string& treeName,
0120                          const std::string& outFile, unsigned int bins,
0121                          float eta, const std::vector<Region>& regions) {
0122   // Open the input file & get the tree
0123   auto inputFile = TFile::Open(inFile.c_str());
0124   auto inputTree = dynamic_cast<TTree*>(inputFile->Get(treeName.c_str()));
0125   if (inputTree == nullptr) {
0126     return;
0127   }
0128 
0129   // Get the different atomic numbers
0130   TCanvas* materialCanvas =
0131       new TCanvas("materialCanvas", "Materials", 100, 100, 620, 400);
0132   materialCanvas->cd();
0133   // Draw all the atomic elements & get the histogram
0134   inputTree->Draw("mat_A>>hA(200,0.5,200.5)");
0135   TH1F* histA = dynamic_cast<TH1F*>(gDirectory->Get("hA"));
0136   if (histA == nullptr) {
0137     throw std::runtime_error{"Could not get the histogram"};
0138   }
0139 
0140   histA->Draw();
0141 
0142   auto outputFile = TFile::Open(outFile.c_str(), "recreate");
0143 
0144   float v_eta = 0;
0145   float v_phi = 0;
0146   std::vector<float>* stepLength = new std::vector<float>;
0147   std::vector<float>* stepX0 = new std::vector<float>;
0148   std::vector<float>* stepL0 = new std::vector<float>;
0149   std::vector<float>* stepA = new std::vector<float>;
0150 
0151   std::vector<float>* stepX = new std::vector<float>;
0152   std::vector<float>* stepY = new std::vector<float>;
0153   std::vector<float>* stepZ = new std::vector<float>;
0154 
0155   inputTree->SetBranchAddress("v_eta", &v_eta);
0156   inputTree->SetBranchAddress("v_phi", &v_phi);
0157   inputTree->SetBranchAddress("mat_step_length", &stepLength);
0158 
0159   inputTree->SetBranchAddress("mat_X0", &stepX0);
0160   inputTree->SetBranchAddress("mat_L0", &stepL0);
0161   inputTree->SetBranchAddress("mat_A", &stepA);
0162 
0163   inputTree->SetBranchAddress("mat_x", &stepX);
0164   inputTree->SetBranchAddress("mat_y", &stepY);
0165   inputTree->SetBranchAddress("mat_z", &stepZ);
0166 
0167   // Loop over all entries ---------------
0168   unsigned int entries = inputTree->GetEntries();
0169 
0170 #ifdef BOOST_AVAILABLE
0171   std::cout << "*** Event Loop: " << std::endl;
0172   progress_display event_loop_progress(entries * regions.size());
0173 #endif
0174 
0175   // Loop of the regions
0176   for (auto& region : regions) {
0177     const auto rName = region.name;
0178 
0179     // The material histograms ordered by atomic mass
0180     std::map<unsigned int, MaterialHistograms> mCache;
0181 
0182     // The material histograms for all
0183     mCache[0] = MaterialHistograms(rName, 0, bins, eta);
0184     for (unsigned int ib = 1; ib <= 200; ++ib) {
0185       if (histA->GetBinContent(ib) > 0.) {
0186         mCache[ib] = MaterialHistograms(rName, ib, bins, eta);
0187       }
0188     }
0189 
0190     for (unsigned int ie = 0; ie < entries; ++ie) {
0191       // Get the entry
0192       inputTree->GetEntry(ie);
0193 
0194 #ifdef BOOST_AVAILABLE
0195       ++event_loop_progress;
0196 #endif
0197 
0198       // Accumulate the material per track
0199       std::size_t steps = stepLength->size();
0200       for (unsigned int is = 0; is < steps; ++is) {
0201         float x = stepX->at(is);
0202         float y = stepY->at(is);
0203         float z = stepZ->at(is);
0204         float r = std::hypot(x, y);
0205 
0206         if (!region.inside(r, z)) {
0207           continue;
0208         }
0209 
0210         float step = stepLength->at(is);
0211         float X0 = stepX0->at(is);
0212         float L0 = stepL0->at(is);
0213 
0214         // The integral one
0215         auto& all = mCache[0];
0216         all.s_x0 += step / X0;
0217         all.s_l0 += step / L0;
0218 
0219         unsigned int sA = histA->FindBin(stepA->at(is));
0220         // The current one
0221         auto currentIt = mCache.find(sA);
0222         if (currentIt == mCache.end()) {
0223           throw std::runtime_error{"Unknown atomic number " +
0224                                    std::to_string(sA)};
0225         }
0226         auto& current = currentIt->second;
0227         current.s_x0 += step / X0;
0228         current.s_l0 += step / L0;
0229       }
0230       // Fill the profiles and clear the cache
0231       for (auto& [key, cache] : mCache) {
0232         cache.fillAndClear(v_eta, v_phi);
0233       }
0234     }
0235     // -----------------------------------
0236 
0237     for (auto [key, cache] : mCache) {
0238       cache.write();
0239     }
0240   }
0241 
0242   outputFile->Close();
0243 
0244   delete stepLength;
0245   delete stepX0;
0246   delete stepL0;
0247   delete stepA;
0248 
0249   delete stepX;
0250   delete stepY;
0251   delete stepZ;
0252 
0253   delete materialCanvas;
0254 }