DD4hep  1.30.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 #include <DD4hep/Shapes.h>
26 
28 #include <cstdio>
29 
30 using namespace dd4hep;
31 using namespace dd4hep::rec;
32 
35  : m_detector(Detector::getInstance())
36 {
38 }
39 
42  : m_detector(description)
43 {
45 }
46 
49 }
50 
51 
53 void MaterialScan::setRegion(const char* region) {
54  Region reg;
55  if ( region ) {
56  reg = m_detector.region(region);
57  }
58  setRegion(reg);
59 }
60 
63  struct PvCollector {
64  Region rg;
65  std::set<const TGeoNode*>& cont;
66  PvCollector(Region r, std::set<const TGeoNode*>& c) : rg(r), cont(c) {}
67  void collect(TGeoNode* pv) {
68  cont.insert(pv);
69  for (Int_t idau = 0, ndau = pv->GetNdaughters(); idau < ndau; ++idau)
70  collect(pv->GetDaughter(idau));
71  }
72  void operator()(TGeoNode* pv) {
73  Volume v = pv->GetVolume();
74  Region r = v.region();
75  if ( r.isValid() ) {
76  collect(pv);
77  return;
78  }
79  for (Int_t idau = 0, ndau = pv->GetNdaughters(); idau < ndau; ++idau)
80  (*this)(pv->GetDaughter(idau));
81  }
82  };
83  m_placements.clear();
84  if ( region.isValid() ) {
85  PvCollector coll(region, m_placements);
86  coll(m_detector.world().placement().ptr());
87  printout(ALWAYS,"MaterialScan","+++ Set new scanning region to: %s [%ld placements]",
88  region.name(), m_placements.size());
89  }
90  else {
91  printout(ALWAYS,"MaterialScan","+++ No region restrictions set. Back to full scanning mode.");
92  }
93 }
94 
96 void MaterialScan::setDetector(const char* detector) {
98  if ( detector ) {
99  det = m_detector.detector(detector);
100  }
101  setDetector(det);
102 }
103 
106  struct PvCollector {
107  std::set<const TGeoNode*>& cont;
108  PvCollector(std::set<const TGeoNode*>& c) : cont(c) {}
109  void operator()(TGeoNode* pv) {
110  cont.insert(pv);
111  for (Int_t idau = 0, ndau = pv->GetNdaughters(); idau < ndau; ++idau) {
112  TGeoNode* daughter = pv->GetDaughter(idau);
113  (*this)(daughter);
114  }
115  }
116  };
117  if ( detector.isValid() ) {
118  PlacedVolume pv = detector.placement();
119  m_placements.clear();
120  if ( pv.isValid() ) {
121  PvCollector coll(m_placements);
122  coll(pv.ptr());
123  }
124  printout(ALWAYS,"MaterialScan","+++ Set new scanning volume to: %s [%ld placements]",
125  detector.path().c_str(), m_placements.size());
126  }
127  else {
128  printout(ALWAYS,"MaterialScan","+++ No subdetector restrictions set. Back to full scanning mode.");
129  m_placements.clear();
130  }
131 }
132 
134 void MaterialScan::setMaterial(const char* material) {
135  Material mat;
136  if ( material ) {
137  mat = m_detector.material(material);
138  }
139  setMaterial(mat);
140 }
141 
144  struct PvCollector {
145  Material material;
146  std::set<const TGeoNode*>& cont;
147  PvCollector(Material mat, std::set<const TGeoNode*>& c) : material(mat), cont(c) {}
148  void operator()(TGeoNode* pv) {
149  Volume vol = pv->GetVolume();
150  Material mat = vol.material();
151  if ( mat.ptr() == material.ptr() ) {
152  cont.insert(pv);
153  }
154  for (Int_t idau = 0, ndau = pv->GetNdaughters(); idau < ndau; ++idau)
155  (*this)(pv->GetDaughter(idau));
156  }
157  };
158  m_placements.clear();
159  if ( material.isValid() ) {
160  PvCollector coll(material, m_placements);
161  coll(m_detector.world().placement().ptr());
162  printout(ALWAYS,"MaterialScan","+++ Set new scanning material to: %s [%ld placements]",
163  material.name(), m_placements.size());
164  }
165  else {
166  printout(ALWAYS,"MaterialScan","+++ No material restrictions set. Back to full scanning mode.");
167  }
168 }
169 
171 const MaterialVec& MaterialScan::scan(double x0, double y0, double z0, double x1, double y1, double z1, double epsilon) const {
172  Vector3D p0(x0, y0, z0), p1(x1, y1, z1);
173  return m_materialMgr->materialsBetween(p0, p1, epsilon);
174 }
175 
177 void MaterialScan::print(const Vector3D& p0, const Vector3D& p1, double epsilon) const {
178  const auto& placements = m_materialMgr->placementsBetween(p0, p1, epsilon);
179  auto& matMgr = *m_materialMgr;
180  Vector3D end, direction;
181  double sum_x0 = 0;
182  double sum_lambda = 0;
183  double path_length = 0, total_length = 0;
184  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";
185  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";
186  const char* line = " +--------------------------------------------------------------------------------------------------------------------------------------------------\n";
187 
188  direction = (p1-p0).unit();
189 
190  ::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",
191  line,p0[0],p0[1],p0[2],p1[0],p1[1],p1[2],line);
192  ::printf(" | \\ %-16s Atomic Radiation Interaction Path Integrated Integrated Material\n","Material");
193  ::printf(" | Num. \\ %-16s Number/Z Mass/A Density Length Length Thickness Length X0 Lambda Endpoint/Startpoint\n","Name");
194  ::printf(" | Layer \\ %-16s [g/mole] [g/cm3] [cm] [cm] [cm] [cm] [cm] [cm] ( cm, cm, cm)\n","");
195  ::printf("%s",line);
196  MaterialVec materials;
197  std::set<Solid> tessellated_solids;
198  for( unsigned i=0, n=placements.size(); i<n; ++i){
199  TGeoNode* pv = placements[i].first.ptr();
200  double length = placements[i].second;
201  total_length += length;
202  end = p0 + total_length * direction;
203  if ( !m_placements.empty() && m_placements.find(pv) == m_placements.end() ) {
204 #if 0
205  ::printf("%p %s %s %s\n",
206  placements[i].first.ptr(),
207  placements[i].first->GetName(),
208  placements[i].first->GetVolume()->GetName(),
209  placements[i].first->GetMedium()->GetName());
210 #endif
211  continue;
212  }
213  TGeoMaterial* curr_mat = placements[i].first->GetMedium()->GetMaterial();
214  TGeoMaterial* next_mat = (i+1)<n ? placements[i+1].first->GetMedium()->GetMaterial() : nullptr;
215  double nx0 = length / curr_mat->GetRadLen();
216  double nLambda = length / curr_mat->GetIntLen();
217 
218  sum_x0 += nx0;
219  sum_lambda += nLambda;
220  path_length += length;
221  materials.emplace_back(placements[i].first->GetMedium(),length);
222  const char* fmt = curr_mat->GetRadLen() >= 1e5 ? fmt2 : fmt1;
223  std::string mname = curr_mat->GetName();
224  if ( next_mat && (i+1)<n ) {
225  mname += " -> ";
226  mname += next_mat->GetName();
227  }
228  Volume vol(placements[i].first->GetVolume());
229  Solid shape(vol.solid());
230  if ( shape->IsA() == TGeoTessellated::Class() ) {
231  tessellated_solids.insert(shape);
232  }
233  if ( 0 == i ) {
234  ::printf(fmt, "(start)" , 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  // No else here!
240  if ( (n-1) == i ) {
241  ::printf(fmt, "(end)", curr_mat->GetName(), curr_mat->GetZ(), curr_mat->GetA(),
242  curr_mat->GetDensity(), curr_mat->GetRadLen()/dd4hep::cm, curr_mat->GetIntLen()/dd4hep::cm,
243  0e0, 0e0, 0e0, 0e0,
244  p0[0]/dd4hep::cm, p0[1]/dd4hep::cm, p0[2]/dd4hep::cm);
245  }
246  else {
247  ::printf(fmt, std::to_string(i+1).c_str(), mname.c_str(), next_mat->GetZ(), next_mat->GetA(),
248  next_mat->GetDensity(), next_mat->GetRadLen()/dd4hep::cm, next_mat->GetIntLen()/dd4hep::cm,
249  length/dd4hep::cm, path_length/dd4hep::cm, sum_x0, sum_lambda,
250  end[0]/dd4hep::cm, end[1]/dd4hep::cm, end[2]/dd4hep::cm);
251  }
252  }
253  ::printf("%s",line);
254  const MaterialData& avg = matMgr.createAveragedMaterial(materials);
255  const char* fmt = avg.radiationLength() >= 1e5 ? fmt2 : fmt1;
256  ::printf(fmt,"","Average Material",avg.Z(),avg.A(),avg.density(),
257  avg.radiationLength()/dd4hep::cm, avg.interactionLength()/dd4hep::cm,
258  path_length/dd4hep::cm, path_length/dd4hep::cm,
259  path_length/avg.radiationLength(),
260  path_length/avg.interactionLength(),
261  end[0]/dd4hep::cm, end[1]/dd4hep::cm, end[2]/dd4hep::cm);
262  ::printf("%s",line);
263 
264  if ( !tessellated_solids.empty() ) {
265  ::printf(" | WARNING: %ld tessellated shape were encountered during the volume traversal:\n",
266  tessellated_solids.size());
267  for(auto shape : tessellated_solids )
268  ::printf(" | \t\t %s\n", shape.name());
269  ::printf(" | WARNING: The results of this material scan are unreliable!\n");
270  ::printf("%s",line);
271  }
272 }
273 
275 void MaterialScan::print(double x0, double y0, double z0, double x1, double y1, double z1, double epsilon) const {
276  Vector3D p0(x0, y0, z0), p1(x1, y1, z1);
277  this->print(p0, p1, epsilon);
278 }
dd4hep::DetElement::path
const std::string & path() const
Path of the detector element (not necessarily identical to placement path!)
Definition: DetElement.cpp:158
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:105
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:53
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:171
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:321
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::Volume::solid
Solid solid() const
Access to Solid (Shape)
Definition: Volumes.cpp:1223
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:34
dd4hep::Solid_type< TGeoShape >
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:48
epsilon
const double epsilon
Definition: test_cellid_position_converter.cpp:41
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:352
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:134
dd4hep::rec::MaterialManager
Definition: MaterialManager.h:41
dd4hep::Region
Handle class describing a region as used in simulation.
Definition: Objects.h:462
Shapes.h
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:177
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