DD4hep  01.18
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups
MaterialScan.cpp
Go to the documentation of this file.
1 //==========================================================================
2 // AIDA Detector description implementation
3 //--------------------------------------------------------------------------
4 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
5 // All rights reserved.
6 //
7 // For the licensing terms see $DD4hepINSTALL/LICENSE.
8 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
9 //
10 // Author : M.Frank
11 //
12 //==========================================================================
13 //
14 // Simple program to print all the materials in a detector on
15 // a straight line between two given points
16 //
17 // Author : M.Frank, CERN
18 //
19 //==========================================================================
20 // Framework include files
21 #include "DDRec/MaterialScan.h"
22 #include "DD4hep/Detector.h"
23 #include "DD4hep/Printout.h"
24 
25 #include <cstdio>
26 
27 using namespace dd4hep;
28 using namespace dd4hep::rec;
29 
31 MaterialScan::MaterialScan()
32  : m_detector(Detector::getInstance())
33 {
34  m_materialMgr.reset(new MaterialManager(m_detector.world().volume()));
35 }
36 
39  : m_detector(description)
40 {
41  m_materialMgr.reset(new MaterialManager(m_detector.world().volume()));
42 }
43 
46 }
47 
48 
50 void MaterialScan::setRegion(const char* region) {
51  Region reg;
52  if ( region ) {
53  reg = m_detector.region(region);
54  }
55  setRegion(reg);
56 }
57 
59 void MaterialScan::setRegion(Region region) {
60  struct PvCollector {
61  Region rg;
63  PvCollector(Region r, std::set<const TGeoNode*>& c) : rg(r), cont(c) {}
64  void collect(TGeoNode* pv) {
65  cont.insert(pv);
66  for (Int_t idau = 0, ndau = pv->GetNdaughters(); idau < ndau; ++idau)
67  collect(pv->GetDaughter(idau));
68  }
69  void operator()(TGeoNode* pv) {
70  Volume v = pv->GetVolume();
71  Region r = v.region();
72  if ( r.isValid() ) {
73  collect(pv);
74  return;
75  }
76  for (Int_t idau = 0, ndau = pv->GetNdaughters(); idau < ndau; ++idau)
77  (*this)(pv->GetDaughter(idau));
78  }
79  };
81  if ( region.isValid() ) {
82  PvCollector coll(region, m_placements);
83  coll(m_detector.world().placement().ptr());
84  printout(ALWAYS,"MaterialScan","+++ Set new scanning region to: %s [%ld placements]",
85  region.name(), m_placements.size());
86  }
87  else {
88  printout(ALWAYS,"MaterialScan","+++ No region restrictions set. Back to full scanning mode.");
89  }
90 }
91 
93 void MaterialScan::setDetector(const char* detector) {
95  if ( detector ) {
96  det = m_detector.detector(detector);
97  }
98  setDetector(det);
99 }
100 
103  struct PvCollector {
105  PvCollector(std::set<const TGeoNode*>& c) : cont(c) {}
106  void operator()(TGeoNode* pv) {
107  cont.insert(pv);
108  for (Int_t idau = 0, ndau = pv->GetNdaughters(); idau < ndau; ++idau) {
109  TGeoNode* daughter = pv->GetDaughter(idau);
110  (*this)(daughter);
111  }
112  }
113  };
114  if ( detector.isValid() ) {
115  PlacedVolume pv = detector.placement();
117  if ( pv.isValid() ) {
118  PvCollector coll(m_placements);
119  coll(pv.ptr());
120  }
121  printout(ALWAYS,"MaterialScan","+++ Set new scanning volume to: %s [%ld placements]",
122  detector.path().c_str(), m_placements.size());
123  }
124  else {
125  printout(ALWAYS,"MaterialScan","+++ No subdetector restrictions set. Back to full scanning mode.");
127  }
128 }
129 
131 void MaterialScan::setMaterial(const char* material) {
132  Material mat;
133  if ( material ) {
134  mat = m_detector.material(material);
135  }
136  setMaterial(mat);
137 }
138 
140 void MaterialScan::setMaterial(Material material) {
141  struct PvCollector {
142  Material material;
144  PvCollector(Material mat, std::set<const TGeoNode*>& c) : material(mat), cont(c) {}
145  void operator()(TGeoNode* pv) {
146  Volume vol = pv->GetVolume();
147  Material mat = vol.material();
148  if ( mat.ptr() == material.ptr() ) {
149  cont.insert(pv);
150  }
151  for (Int_t idau = 0, ndau = pv->GetNdaughters(); idau < ndau; ++idau)
152  (*this)(pv->GetDaughter(idau));
153  }
154  };
156  if ( material.isValid() ) {
157  PvCollector coll(material, m_placements);
158  coll(m_detector.world().placement().ptr());
159  printout(ALWAYS,"MaterialScan","+++ Set new scanning material to: %s [%ld placements]",
160  material.name(), m_placements.size());
161  }
162  else {
163  printout(ALWAYS,"MaterialScan","+++ No material restrictions set. Back to full scanning mode.");
164  }
165 }
166 
168 const MaterialVec& MaterialScan::scan(double x0, double y0, double z0, double x1, double y1, double z1, double epsilon) const {
169  Vector3D p0(x0, y0, z0), p1(x1, y1, z1);
170  return m_materialMgr->materialsBetween(p0, p1, epsilon);
171 }
172 
174 void MaterialScan::print(const Vector3D& p0, const Vector3D& p1, double epsilon) const {
175  const auto& placements = m_materialMgr->placementsBetween(p0, p1, epsilon);
176  auto& matMgr = *m_materialMgr;
177  Vector3D end, direction;
178  double sum_x0 = 0;
179  double sum_lambda = 0;
180  double path_length = 0, total_length = 0;
181  const char* fmt1 = " | %5d %-20s %3.0f %8.3f %8.4f %11.4f %11.4f %10.3f %8.2f %11.6f %11.6f (%7.2f,%7.2f,%7.2f)\n";
182  const char* fmt2 = " | %5d %-20s %3.0f %8.3f %8.4f %11.6g %11.6g %10.3f %8.2f %11.6f %11.6f (%7.2f,%7.2f,%7.2f)\n";
183  const char* line = " +--------------------------------------------------------------------------------------------------------------------------------------------------\n";
184 
185  direction = (p1-p0).unit();
186 
187  ::printf("%s + Material scan between: x_0 = (%7.2f,%7.2f,%7.2f) [cm] and x_1 = (%7.2f,%7.2f,%7.2f) [cm] : \n%s",
188  line,p0[0],p0[1],p0[2],p1[0],p1[1],p1[2],line);
189  ::printf(" | \\ %-11s Atomic Radiation Interaction Path Integrated Integrated Material\n","Material");
190  ::printf(" | Num. \\ %-11s Number/Z Mass/A Density Length Length Thickness Length X0 Lambda Endpoint \n","Name");
191  ::printf(" | Layer \\ %-11s [g/mole] [g/cm3] [cm] [cm] [cm] [cm] [cm] [cm] ( cm, cm, cm)\n","");
192  ::printf("%s",line);
193  MaterialVec materials;
194  for( unsigned i=0,n=placements.size(); i<n; ++i){
195  TGeoNode* pv = placements[i].first.ptr();
196  double length = placements[i].second;
197  total_length += length;
198  end = p0 + total_length * direction;
199  if ( !m_placements.empty() && m_placements.find(pv) == m_placements.end() ) {
200 #if 0
201  ::printf("%p %s %s %s\n",
202  placements[i].first.ptr(),
203  placements[i].first->GetName(),
204  placements[i].first->GetVolume()->GetName(),
205  placements[i].first->GetMedium()->GetName());
206 #endif
207  continue;
208  }
209  TGeoMaterial* mat = placements[i].first->GetMedium()->GetMaterial();
210  double nx0 = length / mat->GetRadLen();
211  double nLambda = length / mat->GetIntLen();
212 
213  sum_x0 += nx0;
214  sum_lambda += nLambda;
215  path_length += length;
216  materials.emplace_back(placements[i].first->GetMedium(),length);
217  const char* fmt = mat->GetRadLen() >= 1e5 ? fmt2 : fmt1;
218  ::printf(fmt, i+1, mat->GetName(), mat->GetZ(), mat->GetA(),
219  mat->GetDensity(), mat->GetRadLen(), mat->GetIntLen(),
220  length, path_length, sum_x0, sum_lambda, end[0], end[1], end[2]);
221  //mat->Print();
222  }
223  printf("%s",line);
224  const MaterialData& avg = matMgr.createAveragedMaterial(materials);
225  const char* fmt = avg.radiationLength() >= 1e5 ? fmt2 : fmt1;
226  ::printf(fmt,0,"Average Material",avg.Z(),avg.A(),avg.density(),
227  avg.radiationLength(), avg.interactionLength(),
228  path_length, path_length,
229  path_length/avg.radiationLength(),
230  path_length/avg.interactionLength(),
231  end[0], end[1], end[2]);
232  printf("%s",line);
233 }
234 
236 void MaterialScan::print(double x0, double y0, double z0, double x1, double y1, double z1, double epsilon) const {
237  Vector3D p0(x0, y0, z0), p1(x1, y1, z1);
238  print(p0, p1, epsilon);
239 }
T empty(T...args)
virtual double radiationLength() const
radiation length - tgeo units
Definition: Material.h:170
virtual double interactionLength() const
interaction length - tgeo units
Definition: Material.h:173
void setRegion(const char *region)
Set a specific region to limit the scan (resets other selection criteria)
virtual ~MaterialScan()
Default destructor.
T end(T...args)
Simple three dimensional vector providing the components for cartesian, cylindrical and spherical coo...
Definition: Vector3D.h:32
MaterialScan()
Default constructor.
void setMaterial(const char *material)
Set a specific volume material to limit the scan (resets other selection criteria) ...
std::unique_ptr< MaterialManager > m_materialMgr
Material manager.
Definition: MaterialScan.h:58
std::set< const TGeoNode * > m_placements
Local cache: subdetector placements.
Definition: MaterialScan.h:60
T clear(T...args)
virtual double density() const
density
Definition: Material.h:167
T find(T...args)
T size(T...args)
void print(const Vector3D &start, const Vector3D &end, double epsilon=1e-4) const
Scan along a line and print the materials traversed.
Detector & m_detector
Reference to detector setup.
Definition: MaterialScan.h:56
virtual double A() const
averaged atomic number
Definition: Material.h:164
Simple data class that implements the IMaterial interface and is used in the Surface implementation...
Definition: Material.h:33
const MaterialVec & scan(double x0, double y0, double z0, double x1, double y1, double z1, double epsilon=1e-4) const
Scan along a line and store the matrials internally.
virtual double Z() const
averaged proton number
Definition: Material.h:161
void setDetector(DetElement detector)
Set a specific detector volume to limit the scan (resets other selection criteria) ...
T emplace_back(T...args)
Material manager provides access to the material properties of the detector.