Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
materialComposition.C
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file materialComposition.C
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2021 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
9 #include <cmath>
10 #include <iostream>
11 #include <map>
12 #include <string>
13 #include <tuple>
14 
15 #include <TCanvas.h>
16 #include <TDirectory.h>
17 #include <TFile.h>
18 #include <TH1F.h>
19 #include <TProfile.h>
20 #include <TTree.h>
21 
23  TProfile* x0_vs_eta = nullptr;
24  TProfile* l0_vs_eta = nullptr;
25 
26  TProfile* x0_vs_phi = nullptr;
27  TProfile* l0_vs_phi = nullptr;
28 
29  float s_x0 = 0.;
30  float s_l0 = 0.;
31 
32  MaterialHistograms() = default;
33 
37  MaterialHistograms(const std::string& name, unsigned int iA,
38  unsigned int bins, float eta) {
39  std::string x0NameEta =
40  (iA == 0) ? name + std::string("_x0_vs_eta_all")
41  : name + std::string("_x0_vs_eta_A") + std::to_string(iA);
42  std::string l0NameEta =
43  (iA == 0) ? name + std::string("_l0_vs_eta_all")
44  : name + std::string("_l0_vs_eta_A") + std::to_string(iA);
45 
46  x0_vs_eta = new TProfile(x0NameEta.c_str(), "X_{0} vs. #eta", bins, -eta,
47  eta);
48  l0_vs_eta = new TProfile(l0NameEta.c_str(), "L_{0} vs. #eta", bins, -eta,
49  eta);
50 
51  std::string x0NamePhi =
52  (iA == 0) ? name + std::string("_x0_vs_phi_all")
53  : name + std::string("_x0_vs_phi_A") + std::to_string(iA);
54  std::string l0NamePhi =
55  (iA == 0) ? name + std::string("_l0_vs_phi_all")
56  : name + std::string("_l0_vs_phi_A") + std::to_string(iA);
57 
58  x0_vs_phi = new TProfile(x0NamePhi.c_str(), "X_{0} vs. #phi", bins, -M_PI,
59  M_PI);
60  l0_vs_phi = new TProfile(l0NamePhi.c_str(), "L_{0} vs. #phi", bins, -M_PI,
61  M_PI);
62  }
63 
70  void fillAndClear(float eta, float phi) {
71  x0_vs_eta->Fill(eta, s_x0);
72  l0_vs_eta->Fill(eta, s_l0);
73 
74  x0_vs_phi->Fill(phi, s_x0);
75  l0_vs_phi->Fill(phi, s_l0);
76 
77  s_x0 = 0.;
78  s_l0 = 0.;
79  }
80 
86  void write() {
87  if (x0_vs_eta->GetMaximum() > 0.) {
88  x0_vs_eta->Write();
89  l0_vs_eta->Write();
90 
91  x0_vs_phi->Write();
92  l0_vs_phi->Write();
93  }
94  }
95 };
96 
97 struct Region {
99  std::vector<std::tuple<float, float, float, float>> boxes;
100 
101  bool inside(float r, float z) const {
102  for (const auto& [minR, maxR, minZ, maxZ] : boxes) {
103  if (minR <= r && r < maxR && minZ <= z && z < maxZ) {
104  return true;
105  }
106  }
107  return false;
108  }
109 };
110 
118 void materialComposition(const std::string& inFile, const std::string& treeName,
119  const std::string& outFile, unsigned int bins,
120  float eta, const std::vector<Region>& regions) {
121  // Open the input file & get the tree
122  auto inputFile = TFile::Open(inFile.c_str());
123  auto inputTree = dynamic_cast<TTree*>(inputFile->Get(treeName.c_str()));
124  if (inputTree == nullptr) {
125  return;
126  }
127 
128  // Get the different atomic numbers
129  TCanvas* materialCanvas =
130  new TCanvas("materialCanvas", "Materials", 100, 100, 620, 400);
131  materialCanvas->cd();
132  // Draw all the atomic elements & get the histogram
133  inputTree->Draw("mat_A>>hA(200,0.5,200.5)");
134  TH1F* histA = dynamic_cast<TH1F*>(gDirectory->Get("hA"));
135  histA->Draw();
136 
137  auto outputFile = TFile::Open(outFile.c_str(), "recreate");
138 
139  float v_eta = 0;
140  float v_phi = 0;
141  std::vector<float>* stepLength = new std::vector<float>;
142  std::vector<float>* stepX0 = new std::vector<float>;
143  std::vector<float>* stepL0 = new std::vector<float>;
144  std::vector<float>* stepA = new std::vector<float>;
145 
146  std::vector<float>* stepX = new std::vector<float>;
147  std::vector<float>* stepY = new std::vector<float>;
148  std::vector<float>* stepZ = new std::vector<float>;
149 
150  inputTree->SetBranchAddress("v_eta", &v_eta);
151  inputTree->SetBranchAddress("v_phi", &v_phi);
152  inputTree->SetBranchAddress("mat_step_length", &stepLength);
153 
154  inputTree->SetBranchAddress("mat_X0", &stepX0);
155  inputTree->SetBranchAddress("mat_L0", &stepL0);
156  inputTree->SetBranchAddress("mat_A", &stepA);
157 
158  inputTree->SetBranchAddress("mat_x", &stepX);
159  inputTree->SetBranchAddress("mat_y", &stepY);
160  inputTree->SetBranchAddress("mat_z", &stepZ);
161 
162  // Loop over all entries ---------------
163  unsigned int entries = inputTree->GetEntries();
164 
165 #ifdef BOOST_AVAILABLE
166  std::cout << "*** Event Loop: " << std::endl;
167  progress_display event_loop_progress(entries * regions.size());
168 #endif
169 
170  // Loop of the regions
171  for (auto& region : regions) {
172  const auto rName = region.name;
173 
174  // The material histograms ordered by atomic mass
175  std::map<unsigned int, MaterialHistograms> mCache;
176 
177  // The material histograms for all
178  mCache[0] = MaterialHistograms(rName, 0, bins, eta);
179  for (unsigned int ib = 1; ib <= 200; ++ib) {
180  if (histA->GetBinContent(ib) > 0.) {
181  mCache[ib] = MaterialHistograms(rName, ib, bins, eta);
182  }
183  }
184 
185  for (unsigned int ie = 0; ie < entries; ++ie) {
186  // Get the entry
187  inputTree->GetEntry(ie);
188 
189 #ifdef BOOST_AVAILABLE
190  ++event_loop_progress;
191 #endif
192 
193  // Accumulate the material per track
194  size_t steps = stepLength->size();
195  for (unsigned int is = 0; is < steps; ++is) {
196  float x = stepX->at(is);
197  float y = stepY->at(is);
198  float z = stepZ->at(is);
199  float r = std::hypot(x, y);
200 
201  if (!region.inside(r, z)) {
202  continue;
203  }
204 
205  float step = stepLength->at(is);
206  float X0 = stepX0->at(is);
207  float L0 = stepL0->at(is);
208 
209  // The integral one
210  auto& all = mCache[0];
211  all.s_x0 += step / X0;
212  all.s_l0 += step / L0;
213 
214  unsigned int sA = histA->FindBin(stepA->at(is));
215  // The current one
216  auto currentIt = mCache.find(sA);
217  if (currentIt == mCache.end()) {
218  throw std::runtime_error{"Unknown atomic number " +
219  std::to_string(sA)};
220  }
221  auto& current = currentIt->second;
222  current.s_x0 += step / X0;
223  current.s_l0 += step / L0;
224  }
225  // Fill the profiles and clear the cache
226  for (auto& [key, cache] : mCache) {
227  cache.fillAndClear(v_eta, v_phi);
228  }
229  }
230  // -----------------------------------
231 
232  for (auto [key, cache] : mCache) {
233  cache.write();
234  }
235  }
236 
237  outputFile->Close();
238 
239  delete stepLength;
240  delete stepX0;
241  delete stepL0;
242  delete stepA;
243 
244  delete stepX;
245  delete stepY;
246  delete stepZ;
247 
248  delete materialCanvas;
249 }