DD4hep  1.28.0
Detector Description Toolkit for High Energy Physics
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/DD4hepUnits.h>
23 #include <DD4hep/Detector.h>
24 #include <DD4hep/Printout.h>
25 
27 #include <cstdio>
28 
29 using namespace dd4hep;
30 using namespace dd4hep::rec;
31 
34  : m_detector(Detector::getInstance())
35 {
37 }
38 
41  : m_detector(description)
42 {
44 }
45 
48 }
49 
50 
52 void MaterialScan::setRegion(const char* region) {
53  Region reg;
54  if ( region ) {
55  reg = m_detector.region(region);
56  }
57  setRegion(reg);
58 }
59 
62  struct PvCollector {
63  Region rg;
64  std::set<const TGeoNode*>& cont;
65  PvCollector(Region r, std::set<const TGeoNode*>& c) : rg(r), cont(c) {}
66  void collect(TGeoNode* pv) {
67  cont.insert(pv);
68  for (Int_t idau = 0, ndau = pv->GetNdaughters(); idau < ndau; ++idau)
69  collect(pv->GetDaughter(idau));
70  }
71  void operator()(TGeoNode* pv) {
72  Volume v = pv->GetVolume();
73  Region r = v.region();
74  if ( r.isValid() ) {
75  collect(pv);
76  return;
77  }
78  for (Int_t idau = 0, ndau = pv->GetNdaughters(); idau < ndau; ++idau)
79  (*this)(pv->GetDaughter(idau));
80  }
81  };
82  m_placements.clear();
83  if ( region.isValid() ) {
84  PvCollector coll(region, m_placements);
85  coll(m_detector.world().placement().ptr());
86  printout(ALWAYS,"MaterialScan","+++ Set new scanning region to: %s [%ld placements]",
87  region.name(), m_placements.size());
88  }
89  else {
90  printout(ALWAYS,"MaterialScan","+++ No region restrictions set. Back to full scanning mode.");
91  }
92 }
93 
95 void MaterialScan::setDetector(const char* detector) {
97  if ( detector ) {
98  det = m_detector.detector(detector);
99  }
100  setDetector(det);
101 }
102 
105  struct PvCollector {
106  std::set<const TGeoNode*>& cont;
107  PvCollector(std::set<const TGeoNode*>& c) : cont(c) {}
108  void operator()(TGeoNode* pv) {
109  cont.insert(pv);
110  for (Int_t idau = 0, ndau = pv->GetNdaughters(); idau < ndau; ++idau) {
111  TGeoNode* daughter = pv->GetDaughter(idau);
112  (*this)(daughter);
113  }
114  }
115  };
116  if ( detector.isValid() ) {
117  PlacedVolume pv = detector.placement();
118  m_placements.clear();
119  if ( pv.isValid() ) {
120  PvCollector coll(m_placements);
121  coll(pv.ptr());
122  }
123  printout(ALWAYS,"MaterialScan","+++ Set new scanning volume to: %s [%ld placements]",
124  detector.path().c_str(), m_placements.size());
125  }
126  else {
127  printout(ALWAYS,"MaterialScan","+++ No subdetector restrictions set. Back to full scanning mode.");
128  m_placements.clear();
129  }
130 }
131 
133 void MaterialScan::setMaterial(const char* material) {
134  Material mat;
135  if ( material ) {
136  mat = m_detector.material(material);
137  }
138  setMaterial(mat);
139 }
140 
143  struct PvCollector {
144  Material material;
145  std::set<const TGeoNode*>& cont;
146  PvCollector(Material mat, std::set<const TGeoNode*>& c) : material(mat), cont(c) {}
147  void operator()(TGeoNode* pv) {
148  Volume vol = pv->GetVolume();
149  Material mat = vol.material();
150  if ( mat.ptr() == material.ptr() ) {
151  cont.insert(pv);
152  }
153  for (Int_t idau = 0, ndau = pv->GetNdaughters(); idau < ndau; ++idau)
154  (*this)(pv->GetDaughter(idau));
155  }
156  };
157  m_placements.clear();
158  if ( material.isValid() ) {
159  PvCollector coll(material, m_placements);
160  coll(m_detector.world().placement().ptr());
161  printout(ALWAYS,"MaterialScan","+++ Set new scanning material to: %s [%ld placements]",
162  material.name(), m_placements.size());
163  }
164  else {
165  printout(ALWAYS,"MaterialScan","+++ No material restrictions set. Back to full scanning mode.");
166  }
167 }
168 
170 const MaterialVec& MaterialScan::scan(double x0, double y0, double z0, double x1, double y1, double z1, double epsilon) const {
171  Vector3D p0(x0, y0, z0), p1(x1, y1, z1);
172  return m_materialMgr->materialsBetween(p0, p1, epsilon);
173 }
174 
176 void MaterialScan::print(const Vector3D& p0, const Vector3D& p1, double epsilon) const {
177  const auto& placements = m_materialMgr->placementsBetween(p0, p1, epsilon);
178  auto& matMgr = *m_materialMgr;
179  Vector3D end, direction;
180  double sum_x0 = 0;
181  double sum_lambda = 0;
182  double path_length = 0, total_length = 0;
183  const char* fmt1 = " | %7s %-25s %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";
184  const char* fmt2 = " | %7s %-25s %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";
185  const char* line = " +--------------------------------------------------------------------------------------------------------------------------------------------------\n";
186 
187  direction = (p1-p0).unit();
188 
189  ::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",
190  line,p0[0],p0[1],p0[2],p1[0],p1[1],p1[2],line);
191  ::printf(" | \\ %-16s Atomic Radiation Interaction Path Integrated Integrated Material\n","Material");
192  ::printf(" | Num. \\ %-16s Number/Z Mass/A Density Length Length Thickness Length X0 Lambda Endpoint/Startpoint\n","Name");
193  ::printf(" | Layer \\ %-16s [g/mole] [g/cm3] [cm] [cm] [cm] [cm] [cm] [cm] ( cm, cm, cm)\n","");
194  ::printf("%s",line);
195  MaterialVec materials;
196  for( unsigned i=0, n=placements.size(); i<n; ++i){
197  TGeoNode* pv = placements[i].first.ptr();
198  double length = placements[i].second;
199  total_length += length;
200  end = p0 + total_length * direction;
201  if ( !m_placements.empty() && m_placements.find(pv) == m_placements.end() ) {
202 #if 0
203  ::printf("%p %s %s %s\n",
204  placements[i].first.ptr(),
205  placements[i].first->GetName(),
206  placements[i].first->GetVolume()->GetName(),
207  placements[i].first->GetMedium()->GetName());
208 #endif
209  continue;
210  }
211  TGeoMaterial* curr_mat = placements[i].first->GetMedium()->GetMaterial();
212  TGeoMaterial* next_mat = (i+1)<n ? placements[i+1].first->GetMedium()->GetMaterial() : nullptr;
213  double nx0 = length / curr_mat->GetRadLen();
214  double nLambda = length / curr_mat->GetIntLen();
215 
216  sum_x0 += nx0;
217  sum_lambda += nLambda;
218  path_length += length;
219  materials.emplace_back(placements[i].first->GetMedium(),length);
220  const char* fmt = curr_mat->GetRadLen() >= 1e5 ? fmt2 : fmt1;
221  std::string mname = curr_mat->GetName();
222  if ( next_mat && (i+1)<n ) {
223  mname += " -> ";
224  mname += next_mat->GetName();
225  }
226  if ( 0 == i ) {
227  ::printf(fmt, "(start)" , curr_mat->GetName(), curr_mat->GetZ(), curr_mat->GetA(),
228  curr_mat->GetDensity(), curr_mat->GetRadLen()/dd4hep::cm, curr_mat->GetIntLen()/dd4hep::cm,
229  0e0, 0e0, 0e0, 0e0,
230  p0[0]/dd4hep::cm, p0[1]/dd4hep::cm, p0[2]/dd4hep::cm);
231  }
232  // No else here!
233  if ( (n-1) == i ) {
234  ::printf(fmt, "(end)", curr_mat->GetName(), curr_mat->GetZ(), curr_mat->GetA(),
235  curr_mat->GetDensity(), curr_mat->GetRadLen()/dd4hep::cm, curr_mat->GetIntLen()/dd4hep::cm,
236  0e0, 0e0, 0e0, 0e0,
237  p0[0]/dd4hep::cm, p0[1]/dd4hep::cm, p0[2]/dd4hep::cm);
238  }
239  else {
240  ::printf(fmt, std::to_string(i+1).c_str(), mname.c_str(), next_mat->GetZ(), next_mat->GetA(),
241  next_mat->GetDensity(), next_mat->GetRadLen()/dd4hep::cm, next_mat->GetIntLen()/dd4hep::cm,
242  length/dd4hep::cm, path_length/dd4hep::cm, sum_x0, sum_lambda,
243  end[0]/dd4hep::cm, end[1]/dd4hep::cm, end[2]/dd4hep::cm);
244  }
245  }
246  printf("%s",line);
247  const MaterialData& avg = matMgr.createAveragedMaterial(materials);
248  const char* fmt = avg.radiationLength() >= 1e5 ? fmt2 : fmt1;
249  ::printf(fmt,"","Average Material",avg.Z(),avg.A(),avg.density(),
250  avg.radiationLength()/dd4hep::cm, avg.interactionLength()/dd4hep::cm,
251  path_length/dd4hep::cm, path_length/dd4hep::cm,
252  path_length/avg.radiationLength(),
253  path_length/avg.interactionLength(),
254  end[0]/dd4hep::cm, end[1]/dd4hep::cm, end[2]/dd4hep::cm);
255  printf("%s",line);
256 }
257 
259 void MaterialScan::print(double x0, double y0, double z0, double x1, double y1, double z1, double epsilon) const {
260  Vector3D p0(x0, y0, z0), p1(x1, y1, z1);
261  this->print(p0, p1, epsilon);
262 }
dd4hep::DetElement::path
const std::string & path() const
Path of the detector element (not necessarily identical to placement path!)
Definition: DetElement.cpp:157
dd4hep::Detector::world
virtual DetElement world() const =0
Return reference to the top-most (world) detector element.
dd4hep::rec::MaterialScan::setDetector
void setDetector(DetElement detector)
Set a specific detector volume to limit the scan (resets other selection criteria)
Definition: MaterialScan.cpp:104
dd4hep::rec
Namespace for the reconstruction part of the AIDA detector description toolkit.
Definition: SurfaceInstaller.h:28
dd4hep::Detector::detector
virtual DetElement detector(const std::string &name) const =0
Retrieve a subdetector element by its name from the detector description.
dd4hep::rec::MaterialScan::setRegion
void setRegion(const char *region)
Set a specific region to limit the scan (resets other selection criteria)
Definition: MaterialScan.cpp:52
dd4hep::rec::MaterialScan::scan
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.
Definition: MaterialScan.cpp:170
dd4hep::rec::MaterialData::radiationLength
virtual double radiationLength() const
radiation length - tgeo units
Definition: Material.h:170
dd4hep::rec::MaterialData::density
virtual double density() const
density
Definition: Material.h:167
v
View * v
Definition: MultiView.cpp:28
dd4hep::rec::Vector3D
Definition: Vector3D.h:32
Detector.h
dd4hep::PlacedVolume
Handle class holding a placed volume (also called physical volume)
Definition: Volumes.h:173
dd4hep::DetElement::placement
PlacedVolume placement() const
Access to the physical volume of this detector element.
Definition: DetElement.cpp:320
dd4hep::rec::MaterialData::interactionLength
virtual double interactionLength() const
interaction length - tgeo units
Definition: Material.h:173
dd4hep::rec::MaterialVec
std::vector< std::pair< Material, double > > MaterialVec
Definition: MaterialManager.h:30
dd4hep::Handle::isValid
bool isValid() const
Check the validity of the object held by the handle.
Definition: Handle.h:128
dd4hep::Detector::region
virtual Region region(const std::string &name) const =0
Retrieve a region object by its name from the detector description.
dd4hep::rec::MaterialScan::MaterialScan
MaterialScan()
Default constructor.
Definition: MaterialScan.cpp:33
dd4hep::Handle::name
const char * name() const
Access the object name (or "" if not supported by the object)
dd4hep::rec::MaterialScan::~MaterialScan
virtual ~MaterialScan()
Default destructor.
Definition: MaterialScan.cpp:47
epsilon
const double epsilon
Definition: test_cellid_position_converter.cpp:42
dd4hep::Volume::material
Material material() const
Access to the Volume material.
Definition: Volumes.cpp:1122
dd4hep::Material
Handle class describing a material.
Definition: Objects.h:272
dd4hep::rec::MaterialScan::m_placements
std::set< const TGeoNode * > m_placements
Local cache: subdetector placements.
Definition: MaterialScan.h:60
dd4hep::Detector::material
virtual Material material(const std::string &name) const =0
Retrieve a matrial by its name from the detector description.
dd4hep::DetElement
Handle class describing a detector element.
Definition: DetElement.h:188
dd4hep::Volume
Handle class holding a placed volume (also called physical volume)
Definition: Volumes.h:378
dd4hep::DetElement::volume
Volume volume() const
Access to the logical volume of the detector element's placement.
Definition: DetElement.cpp:351
dd4hep::rec::MaterialScan::m_materialMgr
std::unique_ptr< MaterialManager > m_materialMgr
Material manager.
Definition: MaterialScan.h:58
dd4hep::rec::MaterialScan::setMaterial
void setMaterial(const char *material)
Set a specific volume material to limit the scan (resets other selection criteria)
Definition: MaterialScan.cpp:133
dd4hep::rec::MaterialManager
Definition: MaterialManager.h:41
dd4hep::Region
Handle class describing a region as used in simulation.
Definition: Objects.h:462
dd4hep::rec::MaterialScan::print
void print(const Vector3D &start, const Vector3D &end, double epsilon=1e-4) const
Scan along a line and print the materials traversed.
Definition: MaterialScan.cpp:176
dd4hep::rec::MaterialData::A
virtual double A() const
averaged atomic number
Definition: Material.h:164
dd4hep::rec::MaterialData
Definition: Material.h:33
dd4hep::rec::MaterialData::Z
virtual double Z() const
averaged proton number
Definition: Material.h:161
MaterialScan.h
dd4hep::Handle::ptr
T * ptr() const
Access to the held object.
Definition: Handle.h:153
dd4hep
Namespace for the AIDA detector description toolkit.
Definition: AlignmentsCalib.h:28
det
DetElement::Object * det
Definition: AlignmentsCalculator.cpp:66
dd4hep::Detector
The main interface to the dd4hep detector description package.
Definition: Detector.h:90
dd4hep::rec::MaterialScan::m_detector
Detector & m_detector
Reference to detector setup.
Definition: MaterialScan.h:56
DD4hepUnits.h
Printout.h