DD4hep - The AIDA detector description toolkit for high energy physics experiments
DD4hep  Rev:Unversioneddirectory
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DetectorTools.cpp
Go to the documentation of this file.
1 //==========================================================================
2 // AIDA Detector description implementation for LCD
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
16 #include "DD4hep/DetectorTools.h"
17 #include "DD4hep/Printout.h"
18 #include "DD4hep/LCDD.h"
20 
21 // C/C++ include files
22 #include <stdexcept>
23 #include <memory>
24 
25 // ROOT include files
26 #include "TGeoMatrix.h"
27 
29 namespace DD4hep {
30 
32  namespace Geometry {
33 
35 
39  namespace DetectorTools {
41  std::string elementPath(const PlacementPath& nodes, bool reverse);
43  void elementPath(DetElement parent, DetElement elt, ElementPath& detectors);
45  void elementPath(DetElement elt, PlacementPath& nodes);
47  void elementPath(DetElement parent, DetElement element, PlacementPath& nodes);
49  bool findChild(PlacedVolume parent, PlacedVolume child, PlacementPath& path);
50 
51 
52  // Internal helper
53  static void makePlacementPath(PlacementPath det_nodes, PlacementPath& all_nodes);
54  }
55  }
56 }
57 
58 using namespace std;
59 using namespace DD4hep;
60 using namespace DD4hep::Geometry;
61 
64  if ( parent.isValid() && child.isValid() ) {
65  if ( parent.ptr() == child.ptr() ) return true;
66  for(DetElement par=child; par.isValid(); par=par.parent()) {
67  if ( par.ptr() == parent.ptr() ) return true;
68  }
69  }
70  throw runtime_error("Search for parent detector element with invalid handles not allowed.");
71 }
72 
75  if ( parent.isValid() && child.isValid() ) {
76  // Check self
77  if ( parent.ptr() == child.ptr() ) {
78  path.push_back(child);
79  return true;
80  }
81  TIter next(parent->GetVolume()->GetNodes());
82  // Now check next layer children
83  for (TGeoNode *daughter = (TGeoNode*) next(); daughter; daughter = (TGeoNode*) next()) {
84  if ( daughter == child.ptr() ) {
85  path.push_back(daughter);
86  return true;
87  }
88  }
89  next.Reset();
90  // Finally crawl down the tree
91  for (TGeoNode *daughter = (TGeoNode*) next(); daughter; daughter = (TGeoNode*) next()) {
92  PlacementPath sub_path;
93  bool res = findChild(daughter, child, sub_path);
94  if (res) {
95  path.insert(path.end(), sub_path.begin(), sub_path.end());
96  path.push_back(daughter);
97  return res;
98  }
99  }
100  }
101  return false;
102 }
103 
106  if ( parent.isValid() && child.isValid() ) {
107  // Check self
108  if ( 0 == ::strcmp(parent.ptr()->GetName(),child.ptr()->GetName()) ) {
109  path.push_back(child);
110  return true;
111  }
112  TIter next(parent->GetVolume()->GetNodes());
113  // Now check next layer children
114  for (TGeoNode *daughter = (TGeoNode*) next(); daughter; daughter = (TGeoNode*) next()) {
115  if ( 0 == ::strcmp(daughter->GetName(),child.ptr()->GetName()) ) {
116  path.push_back(daughter);
117  return true;
118  }
119  }
120  next.Reset();
121  // Finally crawl down the tree
122  for (TGeoNode *daughter = (TGeoNode*) next(); daughter; daughter = (TGeoNode*) next()) {
124  bool res = findChildByName(daughter, child, sub_path);
125  if (res) {
126  path.insert(path.end(), sub_path.begin(), sub_path.end());
127  path.push_back(daughter);
128  return res;
129  }
130  }
131  }
132  return false;
133 }
134 
137  for(DetElement par = element; par.isValid(); par = par.parent())
138  detectors.push_back(par);
139 }
140 
143  detectors.clear();
144  if ( parent.isValid() && child.isValid() ) {
145  if ( parent.ptr() == child.ptr() ) {
146  detectors.push_back(child);
147  return;
148  }
149  ElementPath elements;
150  for(DetElement par = child; par.isValid(); par = par.parent()) {
151  elements.push_back(par);
152  if ( par.ptr() == parent.ptr() ) {
153  detectors = elements;
154  return;
155  }
156  }
157  throw runtime_error(string("The detector element ")+parent.name()+string(" is no parent of ")+child.name());
158  }
159  throw runtime_error("Search for parent detector element with invalid handles not allowed.");
160 }
161 
164  for(DetElement par = element; par.isValid(); par = par.parent()) {
165  PlacedVolume pv = par.placement();
166  if ( pv.isValid() ) {
167  det_nodes.push_back(pv);
168  }
169  if ( par.ptr() == parent.ptr() ) return;
170  }
171  throw runtime_error(string("The detector element ")+parent.name()+string(" is no parent of ")+element.name());
172 }
173 
176  for(DetElement par = element; par.isValid(); par = par.parent()) {
177  PlacedVolume pv = par.placement();
178  if ( pv.isValid() ) {
179  det_nodes.push_back(pv);
180  }
181  }
182 }
183 
185 std::string DetectorTools::elementPath(const PlacementPath& nodes, bool reverse) {
186  string s = "";
187  if ( reverse ) {
188  for(PlacementPath::const_reverse_iterator i=nodes.rbegin();i!=nodes.rend();++i)
189  s += "/" + string((*i).name());
190  }
191  else {
192  for(PlacementPath::const_iterator i=nodes.begin();i!=nodes.end();++i)
193  s += "/" + string((*i)->GetName());
194  }
195  return s;
196 }
197 
199 std::string DetectorTools::elementPath(const ElementPath& nodes, bool reverse) {
200  string s = "";
201  if ( reverse ) {
202  for(ElementPath::const_reverse_iterator i=nodes.rbegin();i!=nodes.rend();++i)
203  s += "/" + string((*i)->GetName());
204  }
205  else {
206  for(ElementPath::const_iterator i=nodes.begin();i!=nodes.end();++i)
207  s += "/" + string((*i)->GetName());
208  }
209  return s;
210 }
211 
214  ElementPath nodes;
215  elementPath(element,nodes);
216  return elementPath(nodes);
217 }
218 
220 DetElement DetectorTools::findElement(LCDD& lcdd, const std::string& path) {
221  return findDaughterElement(lcdd.world(),path);
222 }
223 
225 DetElement DetectorTools::findDaughterElement(DetElement parent, const std::string& subpath) {
226  if ( parent.isValid() ) {
227  size_t idx = subpath.find('/',1);
228  if ( subpath[0] == '/' ) {
229  DetElement top = topElement(parent);
230  if ( idx == string::npos ) return top;
231  return findDaughterElement(top,subpath.substr(idx+1));
232  }
233  if ( idx == string::npos )
234  return parent.child(subpath);
235  string name = subpath.substr(0,idx);
236  DetElement node = parent.child(name);
237  if ( node.isValid() ) {
238  return findDaughterElement(node,subpath.substr(idx+1));
239  }
240  throw runtime_error("DD4hep: DetElement "+parent.path()+" has no child named:"+name+" [No such child]");
241  }
242  throw runtime_error("DD4hep: Cannot determine child with path "+subpath+" from invalid parent [invalid handle]");
243 }
244 
247  if ( child.isValid() ) {
248  if ( child.parent().isValid() )
249  return topElement(child.parent());
250  return child;
251  }
252  throw runtime_error("DD4hep: DetElement cannot determine top parent (world) [invalid handle]");
253 }
254 
256  for (size_t i = 0, n = det_nodes.size(); i < n-1; ++i) {
257  if (!findChildByName(det_nodes[i + 1], det_nodes[i], all_nodes)) {
258  throw runtime_error("DD4hep: DetElement cannot determine placement path of "
259  + string(det_nodes[i].name()) + " [internal error]");
260  }
261  }
262  if ( det_nodes.size() > 0 ) {
263  all_nodes.push_back(det_nodes.back());
264  }
265 }
266 
269  PlacementPath det_nodes;
270  elementPath(element,det_nodes);
271  makePlacementPath(det_nodes, all_nodes);
272 }
273 
276  PlacementPath det_nodes;
277  elementPath(parent,element,det_nodes);
278  makePlacementPath(det_nodes, all_nodes);
279 }
280 
283  PlacementPath path;
284  placementPath(element,path);
285  return placementPath(path);
286 }
287 
289 std::string DetectorTools::placementPath(const PlacementPath& nodes, bool reverse) {
290  string s="";
291  if ( reverse ) {
292  for(PlacementPath::const_reverse_iterator i=nodes.rbegin();i!=nodes.rend();++i)
293  s += "/" + string((*i)->GetName());
294  }
295  else {
296  for(PlacementPath::const_iterator i=nodes.begin();i!=nodes.end();++i)
297  s += "/" + string((*i)->GetName());
298  }
299  return s;
300 }
301 
303 std::string DetectorTools::placementPath(const std::vector<const TGeoNode*>& nodes, bool reverse) {
304  string s="";
305  if ( reverse ) {
306  for(std::vector<const TGeoNode*>::const_reverse_iterator i=nodes.rbegin();i!=nodes.rend();++i)
307  s += "/" + string((*i)->GetName());
308  }
309  else {
310  for(std::vector<const TGeoNode*>::const_iterator i=nodes.begin();i!=nodes.end();++i)
311  s += "/" + string((*i)->GetName());
312  }
313  return s;
314 }
315 
317 void DetectorTools::placementTrafo(const PlacementPath& nodes, bool inverse, TGeoHMatrix*& mat) {
318  if ( !mat ) mat = new TGeoHMatrix(*gGeoIdentity);
319  placementTrafo(nodes,inverse,*mat);
320 }
321 
323 void DetectorTools::placementTrafo(const PlacementPath& nodes, bool inverse, TGeoHMatrix& mat) {
324  mat = *gGeoIdentity;
325  if (nodes.size() > 0) {
326  for (size_t i = 0, n=nodes.size(); n>0 && i < n-1; ++i) {
327  const PlacedVolume& p = nodes[i];
328  mat.MultiplyLeft(p->GetMatrix());
329  }
330  if ( inverse ) mat = mat.Inverse();
331  }
332 }
333 
335 PlacedVolume DetectorTools::findNode(PlacedVolume top_place, const std::string& place) {
336  TGeoNode* top = top_place.ptr();
337  const char* path = place.c_str();
338  // Check if a geometry path is valid without changing the state of the navigator.
339  Int_t length = strlen(path);
340  if (!length) return 0;
341  TString spath = path;
342  TGeoVolume *vol;
343  // Check first occurance of a '/'
344  Int_t ind1 = spath.Index("/");
345  if (ind1<0) {
346  // No '/' so we check directly the path against the name of the top
347  if ( strcmp(path,top->GetName()) ) return 0;
348  return top;
349  }
350  Int_t ind2 = ind1;
351  Bool_t end = kFALSE;
352  if (ind1>0) ind1 = -1; // no trailing '/'
353  else ind2 = spath.Index("/", ind1+1);
354 
355  if (ind2<0) ind2 = length;
356  TString name(spath(ind1+1, ind2-ind1-1));
357  if ( name == top->GetName() ) {
358  if (ind2>=length-1) return top;
359  ind1 = ind2;
360  }
361  else {
362  return 0;
363  }
364  TGeoNode *node = top;
365  // Deeper than just top level
366  while (!end) {
367  ind2 = spath.Index("/", ind1+1);
368  if (ind2<0) {
369  ind2 = length;
370  end = kTRUE;
371  }
372  vol = node->GetVolume();
373  name = spath(ind1+1, ind2-ind1-1);
374  node = vol->GetNode(name.Data());
375  if (!node)
376  return 0;
377  else if (ind2>=length-1)
378  return node;
379  ind1 = ind2;
380  }
381  return node;
382 }
383 
386  stringstream log;
387  for (PlacedVolume::VolIDs::const_iterator vit = ids.begin(); vit != ids.end(); ++vit)
388  log << (*vit).first << "=" << (*vit).second << "; ";
389  return log.str();
390 }
391 
393 std::string DetectorTools::toString(const IDDescriptor& dsc, const PlacedVolume::VolIDs& ids, VolumeID code) {
394  stringstream log;
395  for (PlacedVolume::VolIDs::const_iterator idIt = ids.begin(); idIt != ids.end(); ++idIt) {
396  const PlacedVolume::VolID& id = (*idIt);
397  IDDescriptor::Field f = dsc.field(id.first);
398  VolumeID value = f->value(code);
399  log << id.first << "=" << id.second << "," << value << " [" << f->offset() << "," << f->width() << "] ";
400  }
401  return log.str();
402 }
403 
404 
Handle class holding a placed volume (also called physical volume)
Definition: Volumes.h:135
virtual DetElement world() const =0
Return reference to the top-most (world) detector element.
const char * name() const
Access the object name (or "" if not supported by the object)
Definition: Handle.inl:36
bool isValid() const
Check the validity of the object held by the handle.
Definition: Handle.h:124
void placementTrafo(const PlacementPath &nodes, bool inverse, TGeoHMatrix *&mat)
Update cached matrix to transform to positions to an upper level Placement.
std::vector< DetElement > ElementPath
Definition: DetectorTools.h:40
bool isParentElement(DetElement parent, DetElement child)
Find path between the child element and the parent element.
TGeoShape * s
Definition: Volumes.cpp:294
static void makePlacementPath(PlacementPath det_nodes, PlacementPath &all_nodes)
T * ptr() const
Access to the held object.
Definition: Handle.h:149
std::vector< PlacedVolume > PlacementPath
Definition: DetectorTools.h:41
DetElement child(const std::string &name) const
Access to individual children by name.
Definition: Detector.cpp:212
std::string placementPath(DetElement element)
Assemble the placement path from a given detector element to the world volume.
DetElement findDaughterElement(DetElement parent, const std::string &subpath)
Find DetElement as child of a parent by it's relative or absolute path.
bool findChild(PlacedVolume parent, PlacedVolume child, PlacementPath &path)
Find Child of PlacedVolume and assemble on the fly the path of PlacedVolumes.
Field field(const std::string &field_name) const
Get the field descriptor of one field by name.
DetElement findElement(LCDD &lcdd, const std::string &path)
Find DetElement as child of the top level volume by it's absolute path.
PlacedVolume findNode(PlacedVolume top_place, const std::string &place)
Find a given node in the hierarchy starting from the top node (absolute placement!) ...
const std::string & path() const
Path of the detector element (not necessarily identical to placement path!)
Definition: Detector.cpp:160
DetElement parent() const
Access to the detector elements's parent.
Definition: Detector.cpp:222
Handle class describing a detector element.
Definition: Detector.h:172
std::string elementPath(const PlacementPath &nodes, bool reverse)
Assemble the path of the PlacedVolume selection.
static bool findChildByName(PlacedVolume parent, PlacedVolume child, DetectorTools::PlacementPath &path)
Find Child of PlacedVolume and assemble on the fly the path of PlacedVolumes.
long long int VolumeID
Definition: Primitives.h:35
The main interface to the DD4hep detector description package.
Definition: LCDD.h:82
void elementPath(DetElement parent, DetElement element, PlacementPath &nodes)
Collect detector elements placements to the parent detector element [no holes!].
DetElement topElement(DetElement child)
Determine top level element (=world) for any element walking up the detector element tree...
Class implementing the ID encoding of detector response.
Definition: IDDescriptor.h:40
std::string toString(const PlacedVolume::VolIDs &ids)
Convert VolumeID to string.