DD4hep  1.31.0
Detector Description Toolkit for High Energy Physics
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
DetectorTools.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 // Framework include files
15 #define DETECTORTOOLS_CPP
17 #include <DD4hep/Printout.h>
18 #include <DD4hep/Detector.h>
20 
21 // C/C++ include files
22 #include <stdexcept>
23 #include <sstream>
24 #include <string>
25 
26 // ROOT include files
27 #include <TGeoMatrix.h>
28 
30 namespace dd4hep {
31 
33 
37  namespace detail { namespace tools {
39  std::string elementPath(const PlacementPath& nodes, bool reverse);
43  void elementPath(DetElement elt, PlacementPath& nodes);
45  void elementPath(DetElement parent, DetElement element, PlacementPath& nodes);
47  bool findChild(PlacedVolume parent, PlacedVolume child, PlacementPath& path);
48 
49 
50  // Internal helper
51  static void makePlacementPath(PlacementPath det_nodes, PlacementPath& all_nodes);
52  }}
53 }
54 
55 using namespace dd4hep;
56 
59  if ( parent.isValid() && child.isValid() ) {
60  if ( parent.ptr() == child.ptr() ) return true;
61  for(DetElement par=child; par.isValid(); par=par.parent()) {
62  if ( par.ptr() == parent.ptr() ) return true;
63  }
64  }
65  throw std::runtime_error("Search for parent detector element with invalid handles not allowed.");
66 }
67 
70  if ( parent.isValid() && child.isValid() ) {
71  // Check self
72  if ( parent.ptr() == child.ptr() ) {
73  path.emplace_back(child);
74  return true;
75  }
76  TIter next(parent->GetVolume()->GetNodes());
77  // Now check next layer children
78  for (TGeoNode *daughter = (TGeoNode*) next(); daughter; daughter = (TGeoNode*) next()) {
79  if ( daughter == child.ptr() ) {
80  path.emplace_back(daughter);
81  return true;
82  }
83  }
84  next.Reset();
85  // Finally crawl down the tree
86  for (TGeoNode *daughter = (TGeoNode*) next(); daughter; daughter = (TGeoNode*) next()) {
87  PlacementPath sub_path;
88  bool res = findChild(daughter, child, sub_path);
89  if (res) {
90  path.insert(path.end(), sub_path.begin(), sub_path.end());
91  path.emplace_back(daughter);
92  return res;
93  }
94  }
95  }
96  return false;
97 }
98 
100 static bool findChildByName(PlacedVolume parent, PlacedVolume child, detail::tools::PlacementPath& path) {
101  if ( parent.isValid() && child.isValid() ) {
102  // Check self
103  if ( 0 == ::strcmp(parent.ptr()->GetName(),child.ptr()->GetName()) ) {
104  path.emplace_back(child);
105  return true;
106  }
107  TIter next(parent->GetVolume()->GetNodes());
108  // Now check next layer children
109  for (TGeoNode *daughter = (TGeoNode*) next(); daughter; daughter = (TGeoNode*) next()) {
110  if ( 0 == ::strcmp(daughter->GetName(),child.ptr()->GetName()) ) {
111  path.emplace_back(daughter);
112  return true;
113  }
114  }
115  next.Reset();
116  // Finally crawl down the tree
117  for (TGeoNode *daughter = (TGeoNode*) next(); daughter; daughter = (TGeoNode*) next()) {
119  bool res = findChildByName(daughter, child, sub_path);
120  if (res) {
121  path.insert(path.end(), sub_path.begin(), sub_path.end());
122  path.emplace_back(daughter);
123  return res;
124  }
125  }
126  }
127  return false;
128 }
129 
132  for(DetElement par = element; par.isValid(); par = par.parent())
133  detectors.emplace_back(par);
134 }
135 
138  detectors.clear();
139  if ( parent.isValid() && child.isValid() ) {
140  if ( parent.ptr() == child.ptr() ) {
141  detectors.emplace_back(child);
142  return;
143  }
144  ElementPath elements;
145  for(DetElement par = child; par.isValid(); par = par.parent()) {
146  elements.emplace_back(par);
147  if ( par.ptr() == parent.ptr() ) {
148  detectors = elements;
149  return;
150  }
151  }
152  throw std::runtime_error(std::string("The detector element ")+parent.name()+std::string(" is no parent of ")+child.name());
153  }
154  throw std::runtime_error("Search for parent detector element with invalid handles not allowed.");
155 }
156 
159  for(DetElement par = element; par.isValid(); par = par.parent()) {
160  PlacedVolume pv = par.placement();
161  if ( pv.isValid() ) {
162  det_nodes.emplace_back(pv);
163  }
164  if ( par.ptr() == parent.ptr() ) return;
165  }
166  throw std::runtime_error(std::string("The detector element ")+parent.name()+std::string(" is no parent of ")+element.name());
167 }
168 
171  for(DetElement par = element; par.isValid(); par = par.parent()) {
172  PlacedVolume pv = par.placement();
173  if ( pv.isValid() ) {
174  det_nodes.emplace_back(pv);
175  }
176  }
177 }
178 
180 std::string detail::tools::elementPath(const PlacementPath& nodes, bool reverse) {
181  std::string path = "";
182  if ( reverse ) {
183  for(auto i=nodes.rbegin(); i != nodes.rend(); ++i)
184  path += "/" + std::string((*i).name());
185  }
186  else {
187  for(auto i=begin(nodes); i != end(nodes); ++i)
188  path += "/" + std::string((*i)->GetName());
189  }
190  return path;
191 }
192 
194 std::string detail::tools::elementPath(const ElementPath& nodes, bool reverse) {
195  std::string path = "";
196  if ( reverse ) {
197  for(ElementPath::const_reverse_iterator i=nodes.rbegin();i!=nodes.rend();++i)
198  path += "/" + std::string((*i)->GetName());
199  }
200  else {
201  for(ElementPath::const_iterator i=nodes.begin();i!=nodes.end();++i)
202  path += "/" + std::string((*i)->GetName());
203  }
204  return path;
205 }
206 
209  ElementPath nodes;
210  elementPath(element,nodes);
211  return elementPath(nodes);
212 }
213 
215 DetElement detail::tools::findElement(const Detector& description, const std::string& path) {
216  return findDaughterElement(description.world(),path);
217 }
218 
220 DetElement detail::tools::findDaughterElement(DetElement parent, const std::string& subpath) {
221  if ( parent.isValid() ) {
222  size_t idx = subpath.find('/',1);
223  if ( subpath[0] == '/' ) {
224  DetElement top = topElement(parent);
225  if ( idx == std::string::npos ) return top;
226  return findDaughterElement(top,subpath.substr(idx+1));
227  }
228  if ( idx == std::string::npos )
229  return parent.child(subpath);
230  std::string name = subpath.substr(0,idx);
231  DetElement node = parent.child(name);
232  if ( node.isValid() ) {
233  return findDaughterElement(node,subpath.substr(idx+1));
234  }
235  throw std::runtime_error("dd4hep: DetElement "+parent.path()+" has no child named:"+name+" [No such child]");
236  }
237  throw std::runtime_error("dd4hep: Cannot determine child with path "+subpath+" from invalid parent [invalid handle]");
238 }
239 
242  if ( child.isValid() ) {
243  if ( child.parent().isValid() )
244  return topElement(child.parent());
245  return child;
246  }
247  throw std::runtime_error("dd4hep: DetElement cannot determine top parent (world) [invalid handle]");
248 }
249 
250 static void detail::tools::makePlacementPath(PlacementPath det_nodes, PlacementPath& all_nodes) {
251  for (size_t i = 0, n = det_nodes.size(); n > 0 && i < n-1; ++i) {
252  if (!findChildByName(det_nodes[i + 1], det_nodes[i], all_nodes)) {
253  throw std::runtime_error("dd4hep: DetElement cannot determine placement path of "
254  + std::string(det_nodes[i].name()) + " [internal error]");
255  }
256  }
257  if ( det_nodes.size() > 0 ) {
258  all_nodes.emplace_back(det_nodes.back());
259  }
260 }
261 
264  PlacementPath det_nodes;
265  elementPath(element,det_nodes);
266  makePlacementPath(std::move(det_nodes), all_nodes);
267 }
268 
271  PlacementPath det_nodes;
272  elementPath(parent,element,det_nodes);
273  makePlacementPath(std::move(det_nodes), all_nodes);
274 }
275 
278  PlacementPath path;
279  placementPath(element,path);
280  return placementPath(std::move(path));
281 }
282 
284 std::string detail::tools::placementPath(const PlacementPath& nodes, bool reverse) {
285  std::string path = "";
286  if ( reverse ) {
287  for(PlacementPath::const_reverse_iterator i=nodes.rbegin();i!=nodes.rend();++i)
288  path += "/" + std::string((*i)->GetName());
289  }
290  else {
291  for(PlacementPath::const_iterator i=nodes.begin();i!=nodes.end();++i)
292  path += "/" + std::string((*i)->GetName());
293  }
294  return path;
295 }
296 
298 std::string detail::tools::placementPath(const std::vector<const TGeoNode*>& nodes, bool reverse) {
299  std::string path = "";
300  if ( reverse ) {
301  for(std::vector<const TGeoNode*>::const_reverse_iterator i=nodes.rbegin();i!=nodes.rend();++i)
302  path += "/" + std::string((*i)->GetName());
303  return path;
304  }
305  for( const auto* n : nodes )
306  path += "/" + std::string(n->GetName());
307  return path;
308 }
309 
311 void detail::tools::placementTrafo(const PlacementPath& nodes, bool inverse, TGeoHMatrix*& mat) {
312  if ( !mat ) mat = new TGeoHMatrix(*gGeoIdentity);
313  placementTrafo(nodes,inverse,*mat);
314 }
315 
317 void detail::tools::placementTrafo(const PlacementPath& nodes, bool inverse, TGeoHMatrix& mat) {
318  mat = *gGeoIdentity;
319  if (nodes.size() > 0) {
320  for (size_t i = 0, n=nodes.size(); n>0 && i < n-1; ++i) {
321  const PlacedVolume& p = nodes[i];
322  mat.MultiplyLeft(p->GetMatrix());
323  }
324  if ( inverse ) mat = mat.Inverse();
325  }
326 }
327 
329 PlacedVolume detail::tools::findNode(PlacedVolume top_place, const std::string& place) {
330  TGeoNode* top = top_place.ptr();
331  const char* path = place.c_str();
332  // Check if a geometry path is valid without changing the state of the navigator.
333  Int_t length = strlen(path);
334  if (!length) return 0;
335  TString spath = path;
336  TGeoVolume *vol;
337  // Check first occurance of a '/'
338  Int_t ind1 = spath.Index("/");
339  if (ind1<0) {
340  // No '/' so we check directly the path against the name of the top
341  if ( strcmp(path,top->GetName()) ) return 0;
342  return top;
343  }
344  Int_t ind2 = ind1;
345  Bool_t end = kFALSE;
346  if (ind1>0) ind1 = -1; // no trailing '/'
347  else ind2 = spath.Index("/", ind1+1);
348 
349  if (ind2<0) ind2 = length;
350  TString name(spath(ind1+1, ind2-ind1-1));
351  if ( name == top->GetName() ) {
352  if (ind2>=length-1) return top;
353  ind1 = ind2;
354  }
355  else {
356  return 0;
357  }
358  TGeoNode *node = top;
359  // Deeper than just top level
360  while (!end) {
361  ind2 = spath.Index("/", ind1+1);
362  if (ind2<0) {
363  ind2 = length;
364  end = kTRUE;
365  }
366  vol = node->GetVolume();
367  name = spath(ind1+1, ind2-ind1-1);
368  node = vol->GetNode(name.Data());
369  if (!node)
370  return 0;
371  else if (ind2>=length-1)
372  return node;
373  ind1 = ind2;
374  }
375  return node;
376 }
377 
380  std::stringstream log;
381  for( const auto& v : ids )
382  log << v.first << "=" << v.second << "; ";
383  return log.str();
384 }
385 
387 std::string detail::tools::toString(const IDDescriptor& dsc, const PlacedVolume::VolIDs& ids, VolumeID code) {
388  std::stringstream log;
389  for( const auto& id : ids ) {
390  const BitFieldElement* f = dsc.field(id.first);
391  VolumeID value = f->value(code);
392  log << id.first << "=" << id.second << "," << value << " [" << f->offset() << "," << f->width() << "] ";
393  }
394  return log.str();
395 }
396 
398 std::vector<std::string> detail::tools::pathElements(const std::string& path) {
399  std::vector<std::string> result;
400  if ( !path.empty() ) {
401  std::string tmp = path[0]=='/' ? path.substr(1) : path;
402  for(size_t idx=tmp.find('/'); idx != std::string::npos; idx=tmp.find('/')) {
403  std::string val = tmp.substr(0,idx);
404  result.emplace_back(val);
405  tmp = tmp.length()>idx ? tmp.substr(idx+1) : std::string();
406  }
407  if ( !tmp.empty() ) {
408  result.emplace_back(tmp);
409  }
410  }
411  return result;
412 }
dd4hep::DetElement::path
const std::string & path() const
Path of the detector element (not necessarily identical to placement path!)
Definition: DetElement.cpp:158
dd4hep::DDSegmentation::BitFieldElement::offset
unsigned offset() const
Definition: BitFieldCoder.h:63
dd4hep::Detector::world
virtual DetElement world() const =0
Return reference to the top-most (world) detector element.
dd4hep::DDSegmentation::BitFieldElement
Helper class for BitFieldCoder that corresponds to one field value.
Definition: BitFieldCoder.h:31
dd4hep::detail::tools::ElementPath
std::vector< DetElement > ElementPath
Definition: DetectorTools.h:38
v
View * v
Definition: MultiView.cpp:28
dd4hep::DetElement::parent
DetElement parent() const
Access to the detector elements's parent.
Definition: DetElement.cpp:239
Detector.h
dd4hep::IDDescriptor::field
const BitFieldElement * field(const std::string &field_name) const
Get the field descriptor of one field by name.
Definition: IDDescriptor.cpp:96
dd4hep::PlacedVolume
Handle class holding a placed volume (also called physical volume)
Definition: Volumes.h:164
dd4hep::detail::tools::placementPath
std::string placementPath(DetElement element)
Assemble the placement path from a given detector element to the world volume.
Definition: DetectorTools.cpp:277
dd4hep::IDDescriptor
Class implementing the ID encoding of the detector response.
Definition: IDDescriptor.h:36
dd4hep::DDSegmentation::BitFieldElement::value
FieldID value(CellID bitfield) const
calculate this field's value given an external 64 bit bitmap
Definition: BitFieldCoder.cpp:56
dd4hep::Handle::isValid
bool isValid() const
Check the validity of the object held by the handle.
Definition: Handle.h:126
DetectorInterna.h
dd4hep::Handle::name
const char * name() const
Access the object name (or "" if not supported by the object)
dd4hep::detail::tools::findDaughterElement
DetElement findDaughterElement(DetElement parent, const std::string &subpath)
Find DetElement as child of a parent by its relative or absolute path.
Definition: DetectorTools.cpp:220
dd4hep::detail::tools::findElement
DetElement findElement(const Detector &description, const std::string &path)
Find DetElement as child of the top level volume by its absolute path.
Definition: DetectorTools.cpp:215
dd4hep::detail::tools::placementTrafo
void placementTrafo(const PlacementPath &nodes, bool inverse, TGeoHMatrix *&mat)
Update cached matrix to transform to positions to an upper level Placement.
Definition: DetectorTools.cpp:311
dd4hep::DetElement
Handle class describing a detector element.
Definition: DetElement.h:187
dd4hep::PlacedVolumeExtension::VolIDs
Volume ID container.
Definition: Volumes.h:89
dd4hep::detail::tools::findChild
bool findChild(PlacedVolume parent, PlacedVolume child, PlacementPath &path)
Find Child of PlacedVolume and assemble on the fly the path of PlacedVolumes.
Definition: DetectorTools.cpp:69
DetectorTools.h
dd4hep::DDSegmentation::BitFieldElement::width
unsigned width() const
Definition: BitFieldCoder.h:66
dd4hep::detail::tools::elementPath
void elementPath(DetElement parent, DetElement element, PlacementPath &nodes)
Collect detector elements placements to the parent detector element [no holes!].
Definition: DetectorTools.cpp:158
ElementPath
detail::tools::ElementPath ElementPath
Definition: DetectorInterna.cpp:30
dd4hep::detail::tools::isParentElement
bool isParentElement(DetElement parent, DetElement child)
Find path between the child element and the parent element.
Definition: DetectorTools.cpp:58
detectors
DetectorMap detectors
Definition: AlignmentsCalculator.cpp:79
dd4hep::detail::tools::findNode
PlacedVolume findNode(PlacedVolume top_place, const std::string &place)
Find a given node in the hierarchy starting from the top node (absolute placement!...
Definition: DetectorTools.cpp:329
dd4hep::detail::tools::pathElements
std::vector< std::string > pathElements(const std::string &path)
Extract all the path elements from a path.
Definition: DetectorTools.cpp:398
VolumeID
dd4hep::DDSegmentation::VolumeID VolumeID
Definition: SegmentationDictionary.h:50
dd4hep::detail::tools::elementPath
std::string elementPath(DetElement element)
Assemble the path of a particular detector element.
Definition: DetectorTools.cpp:208
dd4hep::Handle::ptr
T * ptr() const
Access to the held object.
Definition: Handle.h:151
dd4hep::detail::tools::topElement
DetElement topElement(DetElement child)
Determine top level element (=world) for any element walking up the detector element tree.
Definition: DetectorTools.cpp:241
dd4hep
Namespace for the AIDA detector description toolkit.
Definition: AlignmentsCalib.h:28
dd4hep::DetElement::child
DetElement child(const std::string &name) const
Access to individual children by name.
Definition: DetElement.cpp:212
dd4hep::detail::tools::toString
std::string toString(const PlacedVolume::VolIDs &ids)
Convert VolumeID to string.
Definition: DetectorTools.cpp:379
dd4hep::detail::tools::PlacementPath
std::vector< PlacedVolume > PlacementPath
Definition: DetectorTools.h:39
dd4hep::Detector
The main interface to the dd4hep detector description package.
Definition: Detector.h:90
PlacementPath
detail::tools::PlacementPath PlacementPath
Definition: DetectorInterna.cpp:29
Printout.h