EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RootMaterialWriter.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file RootMaterialWriter.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2017-2018 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 
10 
13 
14 #include <ios>
15 #include <iostream>
16 #include <stdexcept>
17 
18 #include <TFile.h>
19 #include <TH2F.h>
20 
23  : m_cfg(cfg) {
24  // Validate the configuration
25  if (m_cfg.folderNameBase.empty()) {
26  throw std::invalid_argument("Missing folder name base");
27  } else if (m_cfg.fileName.empty()) {
28  throw std::invalid_argument("Missing file name");
29  } else if (!m_cfg.logger) {
30  throw std::invalid_argument("Missing logger");
31  } else if (m_cfg.name.empty()) {
32  throw std::invalid_argument("Missing service name");
33  }
34 }
35 
37  const Acts::DetectorMaterialMaps& detMaterial) {
38  // Setup ROOT I/O
39  TFile* outputFile = TFile::Open(m_cfg.fileName.c_str(), "recreate");
40  if (!outputFile) {
41  throw std::ios_base::failure("Could not open '" + m_cfg.fileName);
42  }
43 
44  // Change to the output file
45  outputFile->cd();
46 
47  auto& surfaceMaps = detMaterial.first;
48  for (auto& [key, value] : surfaceMaps) {
49  // Get the Surface material
50  const Acts::ISurfaceMaterial* sMaterial = value.get();
51 
52  // get the geometry ID
53  Acts::GeometryIdentifier geoID = key;
54  // decode the geometryID
55  const auto gvolID = geoID.volume();
56  const auto gbouID = geoID.boundary();
57  const auto glayID = geoID.layer();
58  const auto gappID = geoID.approach();
59  const auto gsenID = geoID.sensitive();
60  // create the directory
61  std::string tdName = m_cfg.folderNameBase.c_str();
62  tdName += m_cfg.voltag + std::to_string(gvolID);
63  tdName += m_cfg.boutag + std::to_string(gbouID);
64  tdName += m_cfg.laytag + std::to_string(glayID);
65  tdName += m_cfg.apptag + std::to_string(gappID);
66  tdName += m_cfg.sentag + std::to_string(gsenID);
67  // create a new directory
68  outputFile->mkdir(tdName.c_str());
69  outputFile->cd(tdName.c_str());
70 
71  ACTS_VERBOSE("Writing out map at " << tdName);
72 
73  size_t bins0 = 1, bins1 = 1;
74  // understand what sort of material you have in mind
75  const Acts::BinnedSurfaceMaterial* bsm =
76  dynamic_cast<const Acts::BinnedSurfaceMaterial*>(sMaterial);
77  if (bsm) {
78  // overwrite the bin numbers
79  bins0 = bsm->binUtility().bins(0);
80  bins1 = bsm->binUtility().bins(1);
81 
82  // Get the binning data
83  auto& binningData = bsm->binUtility().binningData();
84  // 1-D or 2-D maps
85  size_t binningBins = binningData.size();
86 
87  // The bin number information
88  TH1F* n = new TH1F(m_cfg.ntag.c_str(), "bins; bin", binningBins, -0.5,
89  binningBins - 0.5);
90 
91  // The binning value information
92  TH1F* v = new TH1F(m_cfg.vtag.c_str(), "binning values; bin", binningBins,
93  -0.5, binningBins - 0.5);
94 
95  // The binning option information
96  TH1F* o = new TH1F(m_cfg.otag.c_str(), "binning options; bin",
97  binningBins, -0.5, binningBins - 0.5);
98 
99  // The binning option information
100  TH1F* min = new TH1F(m_cfg.mintag.c_str(), "min; bin", binningBins, -0.5,
101  binningBins - 0.5);
102 
103  // The binning option information
104  TH1F* max = new TH1F(m_cfg.maxtag.c_str(), "max; bin", binningBins, -0.5,
105  binningBins - 0.5);
106 
107  // Now fill the histogram content
108  size_t b = 1;
109  for (auto bData : binningData) {
110  // Fill: nbins, value, option, min, max
111  n->SetBinContent(b, int(binningData[b - 1].bins()));
112  v->SetBinContent(b, int(binningData[b - 1].binvalue));
113  o->SetBinContent(b, int(binningData[b - 1].option));
114  min->SetBinContent(b, binningData[b - 1].min);
115  max->SetBinContent(b, binningData[b - 1].max);
116  ++b;
117  }
118  n->Write();
119  v->Write();
120  o->Write();
121  min->Write();
122  max->Write();
123  }
124 
125  TH2F* t = new TH2F(m_cfg.ttag.c_str(), "thickness [mm] ;b0 ;b1", bins0,
126  -0.5, bins0 - 0.5, bins1, -0.5, bins1 - 0.5);
127  TH2F* x0 = new TH2F(m_cfg.x0tag.c_str(), "X_{0} [mm] ;b0 ;b1", bins0, -0.5,
128  bins0 - 0.5, bins1, -0.5, bins1 - 0.5);
129  TH2F* l0 = new TH2F(m_cfg.l0tag.c_str(), "#Lambda_{0} [mm] ;b0 ;b1", bins0,
130  -0.5, bins0 - 0.5, bins1, -0.5, bins1 - 0.5);
131  TH2F* A = new TH2F(m_cfg.atag.c_str(), "X_{0} [mm] ;b0 ;b1", bins0, -0.5,
132  bins0 - 0.5, bins1, -0.5, bins1 - 0.5);
133  TH2F* Z = new TH2F(m_cfg.ztag.c_str(), "#Lambda_{0} [mm] ;b0 ;b1", bins0,
134  -0.5, bins0 - 0.5, bins1, -0.5, bins1 - 0.5);
135  TH2F* rho = new TH2F(m_cfg.rhotag.c_str(), "#rho [g/mm^3] ;b0 ;b1", bins0,
136  -0.5, bins0 - 0.5, bins1, -0.5, bins1 - 0.5);
137 
138  // loop over the material and fill
139  for (size_t b0 = 0; b0 < bins0; ++b0) {
140  for (size_t b1 = 0; b1 < bins1; ++b1) {
141  // get the material for the bin
142  auto& mat = sMaterial->materialSlab(b0, b1);
143  if (mat) {
144  t->SetBinContent(b0 + 1, b1 + 1, mat.thickness());
145  x0->SetBinContent(b0 + 1, b1 + 1, mat.material().X0());
146  l0->SetBinContent(b0 + 1, b1 + 1, mat.material().L0());
147  A->SetBinContent(b0 + 1, b1 + 1, mat.material().Ar());
148  Z->SetBinContent(b0 + 1, b1 + 1, mat.material().Z());
149  rho->SetBinContent(b0 + 1, b1 + 1, mat.material().massDensity());
150  }
151  }
152  }
153  t->Write();
154  x0->Write();
155  l0->Write();
156  A->Write();
157  Z->Write();
158  rho->Write();
159  }
160 
161  outputFile->Close();
162 }
163 
166  // Create a detector material map and loop recursively through it
167  Acts::DetectorMaterialMaps detMatMap;
168  auto hVolume = tGeometry.highestTrackingVolume();
169  if (hVolume != nullptr) {
170  collectMaterial(*hVolume, detMatMap);
171  }
172  // Write the resulting map to the file
173  write(detMatMap);
174 }
175 
177  const Acts::TrackingVolume& tVolume,
178  Acts::DetectorMaterialMaps& detMatMap) {
179  // If the volume has volume material, write that
180  if (tVolume.volumeMaterialSharedPtr() != nullptr and m_cfg.processVolumes) {
181  detMatMap.second[tVolume.geometryId()] = tVolume.volumeMaterialSharedPtr();
182  }
183 
184  // If confined layers exist, loop over them and collect the layer material
185  if (tVolume.confinedLayers() != nullptr) {
186  for (auto& lay : tVolume.confinedLayers()->arrayObjects()) {
187  collectMaterial(*lay, detMatMap);
188  }
189  }
190 
191  // If any of the boundary surfaces has material collect that
192  if (m_cfg.processBoundaries) {
193  for (auto& bou : tVolume.boundarySurfaces()) {
194  const auto& bSurface = bou->surfaceRepresentation();
195  if (bSurface.surfaceMaterialSharedPtr() != nullptr) {
196  detMatMap.first[bSurface.geometryId()] =
197  bSurface.surfaceMaterialSharedPtr();
198  }
199  }
200  }
201 
202  // If the volume has sub volumes, step down
203  if (tVolume.confinedVolumes() != nullptr) {
204  for (auto& tvol : tVolume.confinedVolumes()->arrayObjects()) {
205  collectMaterial(*tvol, detMatMap);
206  }
207  }
208 }
209 
211  const Acts::Layer& tLayer, Acts::DetectorMaterialMaps& detMatMap) {
212  // If the representing surface has material, collect it
213  const auto& rSurface = tLayer.surfaceRepresentation();
214  if (rSurface.surfaceMaterialSharedPtr() != nullptr and
215  m_cfg.processRepresenting) {
216  detMatMap.first[rSurface.geometryId()] =
217  rSurface.surfaceMaterialSharedPtr();
218  }
219 
220  // Check the approach surfaces
221  if (tLayer.approachDescriptor() != nullptr and m_cfg.processApproaches) {
222  for (auto& aSurface : tLayer.approachDescriptor()->containedSurfaces()) {
223  if (aSurface->surfaceMaterialSharedPtr() != nullptr) {
224  detMatMap.first[aSurface->geometryId()] =
225  aSurface->surfaceMaterialSharedPtr();
226  }
227  }
228  }
229 
230  // Check the sensitive surfaces
231  if (tLayer.surfaceArray() != nullptr and m_cfg.processSensitives) {
232  // sensitive surface loop
233  for (auto& sSurface : tLayer.surfaceArray()->surfaces()) {
234  if (sSurface->surfaceMaterialSharedPtr() != nullptr) {
235  detMatMap.first[sSurface->geometryId()] =
236  sSurface->surfaceMaterialSharedPtr();
237  }
238  }
239  }
240 }