DD4hep  1.37.0
Detector Description Toolkit for High Energy Physics
VolumeManager.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 #include <DD4hep/Detector.h>
16 #include <DD4hep/Printout.h>
17 #include <DD4hep/MatrixHelpers.h>
18 #include <DD4hep/detail/Handle.inl>
22 
23 // C/C++ includes
24 #include <set>
25 #include <cmath>
26 #include <sstream>
27 #include <iomanip>
28 #include <unordered_map>
29 
30 using namespace dd4hep;
31 using namespace dd4hep::detail;
32 
34 
36 namespace dd4hep {
37 
39  namespace detail {
40 
42 
47  typedef std::vector<TGeoNode*> Chain;
49  typedef std::pair<VolumeID, VolumeID> Encoding;
55  std::set<VolumeID> m_entries;
57  std::unordered_map<TGeoVolume*, bool> m_has_sensitive;
59  bool m_debug = false;
61  std::size_t m_numNodes = 0;
62 
63  public:
66  : m_detDesc(description), m_volManager(vm)
67  {
68  m_debug = (0 != ::getenv("DD4HEP_VOLMGR_DEBUG"));
69  }
70 
72  size_t numNodes() const { return m_numNodes; }
73 
75  bool hasSensitiveContent(TGeoVolume* vol) {
76  auto [it, inserted] = m_has_sensitive.emplace(vol, false);
77  if ( !inserted ) return it->second;
78  if ( Volume(vol).isSensitive() ) return it->second = true;
79  for ( Int_t i = 0, n = vol->GetNdaughters(); i < n; ++i ) {
80  TGeoNode* dau = vol->GetNode(i);
81  if ( PlacedVolume(dau).data() && hasSensitiveContent(dau->GetVolume()) )
82  return it->second = true;
83  }
84  return false;
85  }
86 
88  void populate(DetElement e) {
89  //const char* typ = 0;//::getenv("VOLMGR_NEW");
90  SensitiveDetector parent_sd;
92  parent_sd = m_detDesc.sensitiveDetector(e.name());
93  }
94  //printout(INFO, "VolumeManager", "++ Executing %s plugin manager version",typ ? "***NEW***" : "***OLD***");
95  for (const auto& i : e.children() ) {
96  DetElement de = i.second;
97  PlacedVolume pv = de.placement();
98  if (pv.isValid()) {
99  Chain chain;
100  Encoding coding(0, 0);
101  SensitiveDetector sd = parent_sd;
102  m_entries.clear();
103  scanPhysicalVolume(de, de, pv, coding, sd, chain);
104  continue;
105  }
106  printout(WARNING, "VolumeManager", "++ Detector element %s of type %s has no placement.",
107  de.name(), de.type().c_str());
108  }
109  }
112  Encoding parent_encoding,
113  SensitiveDetector& sd, Chain& chain)
114  {
115  TGeoNode* node = pv.ptr();
116  size_t count = 0;
117  if (node) {
118  Volume vol = pv.volume();
119  const VolIDs& pv_ids = pv.volIDs();
120  Encoding vol_encoding = parent_encoding;
121  bool is_sensitive = vol.isSensitive();
122  bool have_encoding = pv_ids.empty();
123  bool compound = e.type() == "compound";
124 
125  if ( compound ) {
126  sd = SensitiveDetector(0);
127  vol_encoding = Encoding();
128  }
129  else if ( !sd.isValid() ) {
130  if ( is_sensitive )
131  sd = vol.sensitiveDetector();
132  else if ( (parent->flag&DetElement::Object::HAVE_SENSITIVE_DETECTOR) )
133  sd = m_detDesc.sensitiveDetector(parent.name());
134  else if ( (e->flag&DetElement::Object::HAVE_SENSITIVE_DETECTOR) )
135  sd = m_detDesc.sensitiveDetector(e.name());
136  }
137  chain.emplace_back(node);
138  if ( sd.isValid() && !pv_ids.empty() ) {
139  Readout ro = sd.readout();
140  if ( ro.isValid() ) {
141  vol_encoding = update_encoding(ro.idSpec(), pv_ids, parent_encoding);
142  have_encoding = true;
143  }
144  else {
145  printout(WARNING, "VolumeManager",
146  "%s: Strange constellation volume %s is sensitive, but has no readout! sd:%p",
147  parent.name(), pv.volume().name(), sd.ptr());
148  }
149  }
150  for (int idau = 0, ndau = node->GetNdaughters(); idau < ndau; ++idau) {
151  TGeoNode* daughter = node->GetDaughter(idau);
152  PlacedVolume placement(daughter);
153  if ( placement.data() ) {
154  if ( hasSensitiveContent(daughter->GetVolume()) ) {
155  PlacedVolume pv_dau(daughter);
156  DetElement de_dau;
160  for( const auto& de : e.children() ) {
161  if ( de.second.placement().ptr() == daughter ) {
162  de_dau = de.second;
163  break;
164  }
165  }
166  if ( de_dau.isValid() ) {
167  Chain dau_chain;
168  count += scanPhysicalVolume(parent, de_dau, pv_dau, vol_encoding, sd, dau_chain);
169  }
170  else {
171  count += scanPhysicalVolume(parent, e, pv_dau, vol_encoding, sd, chain);
172  }
173  }
174  }
175  else {
176  except("VolumeManager",
177  "Invalid not instrumented placement:"+std::string(daughter->GetName())+
178  " [Internal error -- bad detector constructor]");
179  }
180  if ( compound ) {
181  sd = SensitiveDetector(0);
182  }
183  }
184  if ( sd.isValid() ) {
185  if ( !have_encoding && !compound ) {
186  printout(ERROR, "VolumeManager","Element %s: Missing SD encoding. Volume manager won't work!",
187  e.path().c_str());
188  }
189  if ( is_sensitive || count > 0 ) {
192  if ( node == e.placement().ptr() ) {
193  // These here are placement nodes, which at the same time are DetElement placements
194  // 1) We recuperate volumes from lower levels by reusing the subdetector
195  // This only works if there is exactly one sensitive detector per subdetector!
196  // 2) DetElements in the upper hierarchy of the sensitive also get al volume id,
197  // and the volume is registered. (to be discussed)
198  //
199  // I hate this, but I could not talk Frank out of this! M.F.
200  //
201  e.object<DetElement::Object>().volumeID = vol_encoding.first;
202  }
203  else {
204  // These here are placement nodes, which are no DetElement placement
205  // used e.g. to model a very fine grained sensitive volume structure
206  // without always having DetElements.
207  }
208  add_entry(sd, parent, e, node, vol_encoding, chain);
209  ++count;
210  if ( m_debug ) {
211  IDDescriptor id(sd.readout().idSpec());
212  printout(INFO,"VolumeManager","Parent: %-44s id:%016llx Encoding: %s",
213  parent.path().c_str(), parent.volumeID(), id.str(parent_encoding.first,parent_encoding.second).c_str());
214  printout(INFO,"VolumeManager","Element:%-44s id:%016llx Encoding: %s",
215  e.path().c_str(), e.volumeID(), id.str(vol_encoding.first,vol_encoding.second).c_str());
216  printout(INFO, "VolumeManager", "%s SD:%s VolIDs:%s id:%016llx mask:%016llx",
217  node == e.placement().ptr() ? "DETELEMENT PLACEMENT" : "VOLUME PLACEMENT ",
218  sd.name(), pv_ids.str().c_str(), vol_encoding.first, vol_encoding.second);
219  }
220  }
221  }
222  chain.pop_back();
223  }
224  return count;
225  }
226 
228  static Encoding update_encoding(const IDDescriptor iddesc, const VolIDs& ids, const Encoding& initial) {
229  VolumeID volume_id = initial.first, mask = initial.second;
230  for (VolIDs::const_iterator i = ids.begin(); i != ids.end(); ++i) {
231  const auto& id = (*i);
232  const BitFieldElement* f = iddesc.field(id.first);
233  VolumeID msk = f->mask();
234  int off = f->offset();
235  VolumeID val = id.second; // Necessary to extend volume IDs > 32 bit
236  volume_id |= ((f->value(val << off) << off)&msk);
237  mask |= msk;
238  }
239  return std::make_pair(volume_id, mask);
240  }
242  static Encoding encoding(const IDDescriptor iddesc, const VolIDs& ids) {
243  VolumeID volume_id = 0, mask = 0;
244  for (VolIDs::const_iterator i = ids.begin(); i != ids.end(); ++i) {
245  const auto& id = (*i);
246  const BitFieldElement* f = iddesc.field(id.first);
247  VolumeID msk = f->mask();
248  int off = f->offset();
249  VolumeID val = id.second; // Necessary to extend volume IDs > 32 bit
250  volume_id |= ((f->value(val << off) << off)&msk);
251  mask |= msk;
252  }
253  return std::make_pair(volume_id, mask);
254  }
255 
257  const TGeoNode* n, const Encoding& code, Chain& nodes)
258  {
259  if ( sd.isValid() ) {
260  if (m_entries.find(code.first) == m_entries.end()) {
261  Readout ro = sd.readout();
262  std::string sd_name = sd.name();
263  DetElement sub_detector = m_detDesc.detector(sd_name);
264  VolumeManager section = m_volManager.addSubdetector(sub_detector, ro);
265 
266  //m_debug = true;
267  // This is the block, we effectively have to save for each physical volume with a VolID
268  VolumeManagerContext* context = nodes.empty()
271  context->identifier = code.first;
272  context->mask = code.second;
273  context->element = e;
274  context->flag = nodes.empty() ? 0 : 1;
275  if ( context->flag ) {
277  ext->placement = PlacedVolume(n);
278  for (std::size_t i = nodes.size(); i > 1; --i) { // Omit the placement of the parent DetElement
279  TGeoMatrix* m = nodes[i-1]->GetMatrix();
280  ext->toElement.MultiplyLeft(m);
281  }
282  }
283  if ( !section.adoptPlacement(context) || m_debug ) {
284  print_node(sd, parent, e, n, code, nodes);
285  }
286  m_entries.insert(code.first);
287  ++m_numNodes;
288  //if ( (m_numNodes%1000) == 0 ) {
289  // printout(INFO, "VolumeManager","++ Added %ld volume entries.",m_numNodes);
290  //}
291  }
292  }
293  }
294 
296  const TGeoNode* n, const Encoding& code, const Chain& nodes) const
297  {
298  PlacedVolume pv = n;
299  Readout ro = sd.readout();
300  bool sensitive = pv.volume().isSensitive();
301 
302  //if ( !sensitive ) return;
303  std::stringstream log;
304  log << m_entries.size() << ": Detector: " << e.path()
305  << " id:" << volumeID(code.first)
306  << " Nodes(" << int(nodes.size()) << "):" << ro.idSpec().str(code.first,code.second);
307  printout(m_debug ? INFO : DEBUG,"VolumeManager",log.str().c_str());
308  //for(const auto& i : nodes )
309  // log << i->GetName() << "/";
310 
311  log.str("");
312  log << m_entries.size() << ": " << parent.name()
313  << " ro:" << ro.name() << " pv:" << n->GetName()
314  << " Sensitive:" << yes_no(sensitive);
315  printout(m_debug ? INFO : DEBUG, "VolumeManager", log.str().c_str());
316  }
317  };
318  } /* End namespace detail */
319 } /* End namespace dd4hep */
320 
323  if ( 0 == flag ) return;
324 }
325 
328  return element.placement();
329 }
330 
333  if ( 0 == flag )
334  return element.placement();
336  return ext->placement;
337 }
338 
340 const TGeoHMatrix& VolumeManagerContext::toElement() const {
341  static TGeoHMatrix identity;
342  if ( 0 == flag ) return identity;
344  return ext->toElement;
345 }
346 
348 Position VolumeManagerContext::localToElement(const double local[3]) const {
349  double elt[3];
350  toElement().LocalToMaster(local, elt);
351  return { elt[0], elt[1], elt[2] };
352 }
353 
356  double loc[3];
357  local.GetCoordinates(loc);
358  return localToElement(loc);
359 }
360 
362 Position VolumeManagerContext::localToWorld(const double local[3]) const {
363  double elt[3];
364  toElement().LocalToMaster(local, elt);
365  return element.nominal().localToWorld(elt);
366 }
367 
370  double l[3];
371  local.GetCoordinates(l);
372  return localToWorld(l);
373 }
374 
376 Position VolumeManagerContext::worldToElement(const double world[3]) const {
377  return element.nominal().worldToLocal(world);
378 }
379 
382  return element.nominal().worldToLocal(world);
383 }
384 
386 void VolumeManagerContext::worldToElement(const double world[3], double elt[3]) const {
387  element.nominal().worldToLocal(world, elt);
388 }
389 
391 Position VolumeManagerContext::worldToLocal(const double world[3]) const {
392  double elt[3], local[3];
393  worldToElement(world, elt);
394  toElement().MasterToLocal(elt, local);
395  return { local[0], local[1], local[2] };
396 }
397 
400  double global[3];
401  world.GetCoordinates(global);
402  return worldToLocal(global);
403 }
404 
406 void VolumeManagerContext::worldToLocal(const double world[3], double local[3]) const {
407  double elt[3];
408  worldToElement(world, elt);
409  toElement().MasterToLocal(elt, local);
410 }
411 
413 VolumeManager::VolumeManager(const Detector& description, const std::string& nam, DetElement elt, Readout ro, int flags) {
414  printout(INFO, "VolumeManager", " - populating volume ids - be patient ..." );
415  std::size_t node_count = 0;
416  Object* obj_ptr = new Object();
417  assign(obj_ptr, nam, "VolumeManager");
418  if (elt.isValid()) {
419  detail::VolumeManager_Populator p(description, *this);
420  obj_ptr->detector = elt;
421  obj_ptr->id = ro.isValid() ? ro.idSpec() : IDDescriptor();
422  obj_ptr->top = obj_ptr;
423  obj_ptr->flags = flags;
424  p.populate(elt);
425  node_count = p.numNodes();
426  }
427  printout(INFO, "VolumeManager", " - populating volume ids - done. %ld nodes.",node_count);
428 }
429 
432  Object* obj_ptr = new Object();
433  obj_ptr->detector = sub_detector;
434  obj_ptr->id = ro.isValid() ? ro.idSpec() : IDDescriptor();
435  assign(obj_ptr, sub_detector.name(), "VolumeManager");
436 }
437 
439  if( not description.volumeManager().isValid() ) {
440  description.apply("DD4hepVolumeManager", 0, 0);
441  }
442  return description.volumeManager();
443 }
444 
447  if (isValid()) {
448  Object& o = _data();
449  if (!det.isValid()) {
450  throw std::runtime_error("dd4hep: VolumeManager::addSubdetector: Only valid subdetectors "
451  "are allowed. [Invalid DetElement]");
452  }
453  auto i = o.subdetectors.find(det);
454  if (i == o.subdetectors.end()) {
455  std::string det_name = det.name();
456  // First check all pre-conditions
457  if (!ro.isValid()) {
458  throw std::runtime_error("dd4hep: VolumeManager::addSubdetector: Only subdetectors with a "
459  "valid readout descriptor are allowed. [Invalid DetElement:" + det_name + "]");
460  }
461  PlacedVolume pv = det.placement();
462  if (!pv.isValid()) {
463  throw std::runtime_error("dd4hep: VolumeManager::addSubdetector: Only subdetectors with a "
464  "valid placement are allowed. [Invalid DetElement:" + det_name + "]");
465  }
466  auto vit = pv.volIDs().find("system");
467  if (vit == pv.volIDs().end()) {
468  throw std::runtime_error("dd4hep: VolumeManager::addSubdetector: Only subdetectors with "
469  "valid placement VolIDs are allowed. [Invalid DetElement:" + det_name + "]");
470  }
471 
472  i = o.subdetectors.emplace(det, VolumeManager(det,ro)).first;
473  const auto& id = (*vit);
474  VolumeManager mgr = (*i).second;
475  const BitFieldElement* field = ro.idSpec().field(id.first);
476  if (!field) {
477  throw std::runtime_error("dd4hep: VolumeManager::addSubdetector: IdDescriptor of " +
478  std::string(det.name()) + " has no field " + id.first);
479  }
480  Object& mo = mgr._data();
481  mo.top = o.top;
482  mo.flags = o.flags;
483  mo.system = field;
484  mo.sysID = id.second;
485  mo.detMask = mo.sysID;
486  o.managers[mo.sysID] = mgr;
488  &mo,&Object::update);
489  }
490  return (*i).second;
491  }
492  throw std::runtime_error("dd4hep: VolumeManager::addSubdetector: "
493  "Failed to add subdetector section. [Invalid Manager Handle]");
494 }
495 
498  if (isValid()) {
499  const Object& o = _data();
501  for (const auto& j : o.subdetectors ) {
502  const Object& mo = j.second._data();
503  VolumeID sys_id = mo.system->value(id << mo.system->offset());
504  if ( sys_id == mo.sysID )
505  return j.second;
506  }
507  throw std::runtime_error("dd4hep: VolumeManager::subdetector(VolID): "
508  "Attempt to access unknown subdetector section.");
509  }
510  throw std::runtime_error("dd4hep: VolumeManager::subdetector(VolID): "
511  "Cannot assign ID descriptor [Invalid Manager Handle]");
512 }
513 
516  if (isValid()) {
517  return _data().detector;
518  }
519  throw std::runtime_error("dd4hep: VolumeManager::detector: Cannot access DetElement [Invalid Handle]");
520 }
521 
524  return _data().id;
525 }
526 
529  std::stringstream err;
530  Object& o = _data();
531  VolumeID vid = context->identifier;
532  VolumeID mask = context->mask;
533  PlacedVolume pv = context->elementPlacement();
534  auto i = o.volumes.find(vid);
535 
536  if ( (vid&mask) != vid ) {
537  err << "Bad context mask:" << (void*)mask
538  << " id:" << (void*)vid
539  << " pv:" << pv.name()
540  << " Sensitive:" << yes_no(pv.volume().isSensitive())
541  << std::endl;
542  goto Fail;
543  }
544 
545  if ( i == o.volumes.end()) {
546  o.volumes[vid] = context;
547  o.detMask |= mask;
548  err << "Inserted new volume:" << std::setw(6) << std::left << o.volumes.size()
549  << " Ptr:" << (void*) pv.ptr()
550  << " [" << pv.name() << "]"
551  << " id:" << std::setw(16) << std::hex << std::right << std::setfill('0') << vid << std::dec << std::setfill(' ')
552  << " mask:" << std::setw(16) << std::hex << std::right << std::setfill('0') << mask << std::dec << std::setfill(' ')
553  << " Det:" << std::setw(4) << std::hex << std::right << std::setfill('0') << context->element.volumeID()
554  << " / " << std::setw(4) << sys_id << std::dec << std::setfill(' ') << ": " << context->element.path();
555  printout(VERBOSE, "VolumeManager", err.str().c_str());
556  //printout(ALWAYS, "VolumeManager", err.str().c_str());
557  return true;
558  }
559  err << "+++ Attempt to register duplicate"
560  << " id:" << std::setw(16) << std::hex << std::right << std::setfill('0') << vid << std::dec << std::setfill(' ')
561  << " mask:" << std::setw(16) << std::hex << std::right << std::setfill('0') << mask << std::dec << std::setfill(' ')
562  << " to detector " << o.detector.name()
563  << " ptr:" << (void*) pv.ptr()
564  << " Name:" << pv.name()
565  << " Sensitive:" << yes_no(pv.volume().isSensitive())
566  << std::endl;
567  printout(ERROR, "VolumeManager", "%s", err.str().c_str());
568  err.str("");
569  context = (*i).second;
570  //pv = context->placement;
571  err << " !!!!! +++ Clashing"
572  << " id:" << std::setw(16) << std::hex << std::right << std::setfill('0') << vid << std::dec << std::setfill(' ')
573  << " mask:" << std::setw(16) << std::hex << std::right << std::setfill('0') << mask << std::dec << std::setfill(' ')
574  << " to detector " << o.detector.name()
575  << " ptr:" << (void*) pv.ptr()
576  << " Name:" << pv.name()
577  << " Sensitive:" << yes_no(pv.volume().isSensitive())
578  << std::endl;
579  Fail:
580  printout(ERROR, "VolumeManager", "%s", err.str().c_str());
581  // throw std::runtime_error(err.str());
582  return false;
583 }
584 
587  std::stringstream err;
588  if ( isValid() ) {
589  Object& o = _data();
590  if ( context ) {
591  if ( (o.flags & ONE) == ONE ) {
592  VolumeManager top(o.top);
593  return top.adoptPlacement(context);
594  }
595  if ( (o.flags & TREE) == TREE ) {
596  bool isTop = ptr() == o.top;
597  if ( !isTop ) {
598  VolumeID sys_id = o.system->value(context->identifier);
599  if ( sys_id == o.sysID ) {
600  return adoptPlacement(sys_id, context);
601  }
602  VolumeManager top(o.top);
603  return top.adoptPlacement(context);
604  }
605  for( auto& j : o.managers ) {
606  Object& mgr = j.second._data();
607  VolumeID sid = mgr.system->value(context->identifier);
608  if ( j.first == sid ) {
609  return j.second.adoptPlacement(sid, context);
610  }
611  }
612  }
613  return false;
614  }
615  except("VolumeManager","dd4hep: Failed to add new physical volume to detector: %s "
616  "[Invalid Context]", o.detector.name());
617  }
618  except("VolumeManager","dd4hep: Failed to add new physical volume [Invalid Manager Handle]");
619  return false;
620 }
621 
624  if (isValid()) {
625  VolumeManagerContext* c = 0;
626  const Object& o = _data();
627  bool is_top = o.top == ptr();
628  bool one_tree = (o.flags & ONE) == ONE;
629  if ( !is_top && one_tree ) {
630  return VolumeManager(o.top).lookupContext(volume_id);
631  }
632  VolumeID id = volume_id;
634  c = o.search(id);
635  if (c)
636  return c;
638  if (!one_tree) {
639  for (const auto& j : o.subdetectors ) {
640  if ((c = j.second._data().search(id)) != 0)
641  return c;
642  }
643  }
644  except("VolumeManager","lookupContext: Failed to search Volume context %016llX [Unknown identifier]", (void*)volume_id);
645  }
646  except("VolumeManager","lookupContext: Failed to search Volume context [Invalid Manager Handle]");
647  return 0;
648 }
649 
652  VolumeManagerContext* c = lookupContext(volume_id); // Throws exception if not found!
653  return c->elementPlacement();
654 }
655 
658  VolumeManagerContext* c = lookupContext(volume_id); // Throws exception if not found!
659  return c->volumePlacement();
660 }
661 
664  if (isValid()) {
665  const Object& o = _data();
666  VolumeID sys_id = 0;
667  if ( o.system ) {
668  sys_id = o.system->value(volume_id);
669  }
670  else {
671  for (const auto& j : o.subdetectors ) {
672  if ( j.second->system ) {
673  VolumeID vid = volume_id&j.second->system->mask();
674  if ( (volume_id&j.second->sysID) == vid ) {
675  sys_id = j.second->sysID;
676  break;
677  }
678  }
679  }
680  }
681  VolumeID det_id = (volume_id&sys_id);
682  VolumeManagerContext* c = lookupContext(det_id); // Throws exception if not found!
683  return c->element;
684  }
685  except("VolumeManager","lookupContext: Failed to search Volume context [Invalid Manager Handle]");
686  return DetElement();
687 }
688 
691  VolumeManagerContext* c = lookupContext(volume_id); // Throws exception if not found!
692  return c->element;
693 }
694 
696 const TGeoMatrix&
698  VolumeID volume_id) const
699 {
700  VolumeManagerContext* c = lookupContext(volume_id); // Throws exception if not found!
702  return a.worldTransformation();
703 }
704 
706 std::ostream& dd4hep::operator<<(std::ostream& os, const VolumeManager& mgr) {
708  VolumeManager::Object* top = dynamic_cast<VolumeManager::Object*>(o.top);
709  bool isTop = top == &o;
710  //bool hasTop = (o.flags & VolumeManager::ONE) == VolumeManager::ONE;
711  //bool isSdet = (o.flags & VolumeManager::TREE) == VolumeManager::TREE && top != &o;
712  std::string prefix(isTop ? "" : "++ ");
713  os << prefix << (isTop ? "TOP Level " : "Secondary ") << "Volume manager:"
714  << &o << " " << o.detector.name() << " IDD:"
715  << o.id.toString() << " SysID:" << (void*) o.sysID << " "
716  << o.managers.size() << " subsections " << o.volumes.size()
717  << " placements ";
718  if (!(o.managers.empty() && o.volumes.empty()))
719  os << std::endl;
720  for ( const auto& i : o.volumes ) {
721  const VolumeManagerContext* c = i.second;
722  os << prefix
723  << "Element:" << std::setw(32) << std::left << c->element.path()
724  //<< " pv:" << std::setw(32) << std::left << c->placement().name()
725  << " id:" << std::setw(18) << std::left << (void*) c->identifier
726  << " mask:" << std::setw(18) << std::left << (void*) c->mask
727  << std::endl;
728  }
729  for( const auto& i : o.managers )
730  os << prefix << i.second << std::endl;
731  return os;
732 }
733 
737  destroyObjects(volumes);
740  managers.clear();
741  subdetectors.clear();
742 }
743 
745 void VolumeManagerObject::update(unsigned long tags, DetElement& det, void* param) {
747  printout(DEBUG,"VolumeManager","+++ Conditions update %s param:%p",det.path().c_str(),param);
749  printout(DEBUG,"VolumeManager","+++ Alignment update %s param:%p",det.path().c_str(),param);
750 
751  for(const auto& i : volumes )
752  printout(DEBUG,"VolumeManager","+++ Alignment update %s",i.second->elementPlacement().name());
753 }
754 
757  auto i = volumes.find(vol_id&detMask);
758  return (i == volumes.end()) ? 0 : (*i).second;
759 }
760 
dd4hep::DetElement::children
const Children & children() const
Access to the list of children.
Definition: DetElement.cpp:207
dd4hep::VolumeManagerContext::worldToElement
Position worldToElement(const Position &world) const
Transform world coordinates to the DetElement coordinates.
Definition: VolumeManager.cpp:381
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::detail::VolumeManagerContextExtension::placement
PlacedVolume placement
The placement of the (sensitive) volume.
Definition: VolumeManagerInterna.h:49
DD4HEP_INSTANTIATE_HANDLE_NAMED
DD4HEP_INSTANTIATE_HANDLE_NAMED(VolumeManagerObject)
dd4hep::VolumeManager::lookupDetElement
DetElement lookupDetElement(VolumeID volume_id) const
Convenience routine: Lookup the closest subdetector detector element in the hierarchy according to a ...
Definition: VolumeManager.cpp:690
dd4hep::detail::VolumeManagerObject::flags
int flags
Population flags.
Definition: VolumeManagerInterna.h:86
dd4hep::DDSegmentation::BitFieldElement
Helper class for BitFieldCoder that corresponds to one field value.
Definition: BitFieldCoder.h:31
dd4hep::VolumeManager::lookupContext
VolumeManagerContext * lookupContext(VolumeID volume_id) const
Lookup the context, which belongs to a registered physical volume.
Definition: VolumeManager.cpp:623
dd4hep::Detector::detector
virtual DetElement detector(const std::string &name) const =0
Retrieve a subdetector element by its name from the detector description.
dd4hep::detail::VolumeManagerObject::managers
std::map< VolumeID, VolumeManager > managers
The volume managers for the individual subdetector elements.
Definition: VolumeManagerInterna.h:70
dd4hep::SensitiveDetector
Handle class to hold the information of a sensitive detector.
Definition: DetElement.h:43
MatrixHelpers.h
Detector.h
dd4hep::VolumeManager::adoptPlacement
bool adoptPlacement(VolumeManagerContext *context)
Register physical volume with the manager (normally: section manager)
Definition: VolumeManager.cpp:586
dd4hep::detail::VolumeManagerObject::system
const BitFieldElement * system
The system field descriptor.
Definition: VolumeManagerInterna.h:80
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::detail::VolumeManager_Populator::hasSensitiveContent
bool hasSensitiveContent(TGeoVolume *vol)
Returns true if vol or any descendant is a sensitive volume (result is cached).
Definition: VolumeManager.cpp:75
dd4hep::DetElement::type
std::string type() const
Access detector type (structure, tracker, calorimeter, etc.).
Definition: DetElement.cpp:97
dd4hep::PlacedVolume
Handle class holding a placed volume (also called physical volume)
Definition: Volumes.h:164
dd4hep::Handle::object
Q & object() const
Access to an unrelated object type.
Definition: Handle.h:163
dd4hep::detail::VolumeManager_Populator::m_has_sensitive
std::unordered_map< TGeoVolume *, bool > m_has_sensitive
Cache: does a TGeoVolume subtree contain any sensitive volume?
Definition: VolumeManager.cpp:57
dd4hep::detail::VolumeManager_Populator::encoding
static Encoding encoding(const IDDescriptor iddesc, const VolIDs &ids)
Compute the encoding for a set of VolIDs within a readout descriptor.
Definition: VolumeManager.cpp:242
dd4hep::DetElement::placement
PlacedVolume placement() const
Access to the physical volume of this detector element.
Definition: DetElement.cpp:321
VolumeManagerInterna.h
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::VolumeManagerContext::element
DetElement element
Handle to the closest Detector element.
Definition: VolumeManager.h:53
dd4hep::VolumeManager::worldTransformation
const TGeoMatrix & worldTransformation(const ConditionsMap &map, VolumeID volume_id) const
Convenience routine: Access the transformation of a physical volume to the world coordinate system.
Definition: VolumeManager.cpp:697
dd4hep::Handle::isValid
bool isValid() const
Check the validity of the object held by the handle.
Definition: Handle.h:126
dd4hep::detail::VolumeManager_Populator::update_encoding
static Encoding update_encoding(const IDDescriptor iddesc, const VolIDs &ids, const Encoding &initial)
Compute the encoding for a set of VolIDs within a readout descriptor.
Definition: VolumeManager.cpp:228
DetectorInterna.h
dd4hep::detail::VolumeManager_Populator::print_node
void print_node(SensitiveDetector sd, DetElement parent, DetElement e, const TGeoNode *n, const Encoding &code, const Chain &nodes) const
Definition: VolumeManager.cpp:295
dd4hep::detail::VolumeManagerObject::detector
DetElement detector
The Detector element handle managed by this instance.
Definition: VolumeManagerInterna.h:74
dd4hep::DetElement::CONDITIONS_CHANGED
@ CONDITIONS_CHANGED
Definition: DetElement.h:217
dd4hep::detail::VolumeManager_Populator::Encoding
std::pair< VolumeID, VolumeID > Encoding
Definition: VolumeManager.cpp:49
dd4hep::Volume::isSensitive
bool isSensitive() const
Accessor if volume is sensitive (ie. is attached to a sensitive detector)
Definition: Volumes.cpp:1322
dd4hep::VolumeManager::detector
DetElement detector() const
Access the top level detector element.
Definition: VolumeManager.cpp:515
dd4hep::DetElement::volumeID
VolumeID volumeID() const
The cached VolumeID of this subdetector element.
Definition: DetElement.cpp:344
dd4hep::VolumeManagerContext::volumePlacement
PlacedVolume volumePlacement() const
Acces the sensitive volume placement.
Definition: VolumeManager.cpp:332
dd4hep::Handle::name
const char * name() const
Access the object name (or "" if not supported by the object)
dd4hep::detail::VolumeManagerObject::search
VolumeManagerContext * search(const VolumeID &id) const
Search the locally cached volumes for a matching ID.
Definition: VolumeManager.cpp:756
dd4hep::detail::VolumeManagerContextExtension
Extended context. Needs to be public for persistency reasons.
Definition: VolumeManagerInterna.h:46
dd4hep::detail::VolumeManagerObject
This structure describes the internal data of the volume manager object.
Definition: VolumeManagerInterna.h:65
dd4hep::Detector::volumeManager
virtual VolumeManager volumeManager() const =0
Return handle to the VolumeManager.
dd4hep::DetElementObject
Data class with properties of a detector element.
Definition: DetectorInterna.h:81
dd4hep::operator<<
std::ostream & operator<<(std::ostream &os, const DetType &t)
Definition: DetType.h:101
dd4hep::detail::VolumeManager_Populator::VolumeManager_Populator
VolumeManager_Populator(const Detector &description, VolumeManager vm)
Default constructor.
Definition: VolumeManager.cpp:65
dd4hep::Handle::clear
Handle< T > & clear()
Release the object held by the handle.
Definition: Handle.h:134
dd4hep::VolumeManager::VolumeManager
VolumeManager()=default
Default constructor.
dd4hep::detail::VolumeManager_Populator::numNodes
size_t numNodes() const
Access node count.
Definition: VolumeManager.cpp:72
dd4hep::detail::VolumeManager_Populator::Chain
std::vector< TGeoNode * > Chain
Definition: VolumeManager.cpp:47
dd4hep::VolumeManagerContext::mask
VolumeID mask
Ignore mask of the placement identifier.
Definition: VolumeManager.h:57
dd4hep::VolumeManagerContext::~VolumeManagerContext
virtual ~VolumeManagerContext()
Default destructor.
Definition: VolumeManager.cpp:322
dd4hep::detail::VolumeManager_Populator::scanPhysicalVolume
size_t scanPhysicalVolume(DetElement &parent, DetElement e, PlacedVolume pv, Encoding parent_encoding, SensitiveDetector &sd, Chain &chain)
Scan a single physical volume and look for sensitive elements below.
Definition: VolumeManager.cpp:111
dd4hep::detail::VolumeManager_Populator::m_detDesc
const Detector & m_detDesc
Reference to the Detector instance.
Definition: VolumeManager.cpp:51
dd4hep::VolumeManager::lookupVolumePlacement
PlacedVolume lookupVolumePlacement(VolumeID volume_id) const
Lookup a physical (placed) volume identified by its 64 bit hit ID.
Definition: VolumeManager.cpp:657
dd4hep::DetElement
Handle class describing a detector element.
Definition: DetElement.h:187
dd4hep::PlacedVolumeExtension::VolIDs
Volume ID container.
Definition: Volumes.h:89
dd4hep::Volume
Handle class holding a placed volume (also called physical volume)
Definition: Volumes.h:371
dd4hep::VolumeManager
Class to support the retrieval of detector elements and volumes given a valid identifier.
Definition: VolumeManager.h:135
dd4hep::detail
DD4hep internal namespace.
Definition: Alignments.h:32
dd4hep::detail::VolumeManagerObject::subdetectors
std::map< DetElement, VolumeManager > subdetectors
The container of subdetector elements.
Definition: VolumeManagerInterna.h:68
dd4hep::VolumeManager::lookupDetector
DetElement lookupDetector(VolumeID volume_id) const
Convenience routine: Lookup a top level subdetector detector element according to a contained 64 bit ...
Definition: VolumeManager.cpp:663
dd4hep::Detector::apply
virtual long apply(const char *factory, int argc, char **argv) const =0
Manipulate geometry using factory converter.
dd4hep::detail::VolumeManagerContextExtension::toElement
TGeoHMatrix toElement
The transformation of space-points to the coordinate system of the closests detector element.
Definition: VolumeManagerInterna.h:51
dd4hep::align::Keys::alignmentKey
static const Condition::itemkey_type alignmentKey
Key value of an alignment condition object "alignment".
Definition: Alignments.h:56
dd4hep::Handle::data
Q * data() const
Access to an unrelated object type.
Definition: Handle.h:159
dd4hep::VolumeManager::getVolumeManager
static VolumeManager getVolumeManager(const Detector &description)
static accessor calling DD4hepVolumeManagerPlugin if necessary
Definition: VolumeManager.cpp:438
dd4hep::VolumeManager::subdetector
VolumeManager subdetector(VolumeID id) const
Access the volume manager by cell id.
Definition: VolumeManager.cpp:497
dd4hep::Alignment::worldTransformation
const TGeoHMatrix & worldTransformation() const
Create cached matrix to transform to world coordinates.
Definition: Alignments.cpp:68
dd4hep::Detector::sensitiveDetector
virtual SensitiveDetector sensitiveDetector(const std::string &name) const =0
Retrieve a sensitive detector by its name from the detector description.
dd4hep::detail::VolumeManager_Populator::add_entry
void add_entry(SensitiveDetector sd, DetElement parent, DetElement e, const TGeoNode *n, const Encoding &code, Chain &nodes)
Definition: VolumeManager.cpp:256
dd4hep::ConditionsMap::get
virtual Condition get(DetElement detector, Condition::itemkey_type key) const =0
Interface to access conditions by hash value. The detector element key and the item key make a unique...
dd4hep::detail::destroyHandles
void destroyHandles(M &arg)
Functional created of map destruction functors.
Definition: Handle.h:212
dd4hep::detail::VolumeManagerObject::id
IDDescriptor id
The ID descriptor object.
Definition: VolumeManagerInterna.h:76
dd4hep::IDDescriptor::str
std::string str(VolumeID vid) const
Decode volume IDs and return string reprensentation for debugging purposes.
Definition: IDDescriptor.cpp:174
dd4hep::detail::VolumeManager_Populator::m_entries
std::set< VolumeID > m_entries
Set of already added entries.
Definition: VolumeManager.cpp:55
dd4hep::Alignment
Main handle class to hold an alignment object.
Definition: Alignments.h:115
dd4hep::DDSegmentation::BitFieldElement::mask
CellID mask() const
Definition: BitFieldCoder.h:72
dd4hep::detail::VolumeManager_Populator::populate
void populate(DetElement e)
Populate the Volume manager.
Definition: VolumeManager.cpp:88
dd4hep::VolumeManagerContext::localToElement
Position localToElement(const double local[3]) const
Transform local coordinates to the DetElement coordinates.
Definition: VolumeManager.cpp:348
dd4hep::detail::VolumeManager_Populator::VolIDs
PlacedVolume::VolIDs VolIDs
Definition: VolumeManager.cpp:48
dd4hep::VolumeManagerContext::toElement
const TGeoHMatrix & toElement() const
Access the transformation to the closest detector element.
Definition: VolumeManager.cpp:340
dd4hep::VolumeManager::addSubdetector
VolumeManager addSubdetector(DetElement detector, Readout ro)
Add a new Volume manager section according to a new subdetector.
Definition: VolumeManager.cpp:446
dd4hep::VolumeManager::lookupDetElementPlacement
PlacedVolume lookupDetElementPlacement(VolumeID volume_id) const
Lookup a physical (placed) volume of the detector element containing a volume identified by its 64 bi...
Definition: VolumeManager.cpp:651
dd4hep::sim::IDDescriptor
IDDescriptor IDDescriptor
Definition: LCIOConversions.cpp:69
dd4hep::VolumeManagerContext::flag
long flag
Flag to indicate optional information.
Definition: VolumeManager.h:59
dd4hep::Position
ROOT::Math::XYZVector Position
Definition: Objects.h:80
dd4hep::detail::VolumeManagerObject::~VolumeManagerObject
virtual ~VolumeManagerObject()
Default destructor.
Definition: VolumeManager.cpp:735
VolumeID
dd4hep::DDSegmentation::VolumeID VolumeID
Definition: SegmentationDictionary.h:50
dd4hep::detail::VolumeManagerObject::top
VolumeManagerObject * top
The reference to the TOP level VolumeManager.
Definition: VolumeManagerInterna.h:78
dd4hep::VolumeManager::idSpec
IDDescriptor idSpec() const
Access IDDescription structure.
Definition: VolumeManager.cpp:523
dd4hep::detail::VolumeManager_Populator::m_volManager
VolumeManager m_volManager
Reference to the volume manager to be populated.
Definition: VolumeManager.cpp:53
dd4hep::Handle::ptr
T * ptr() const
Access to the held object.
Definition: Handle.h:151
ObjectsInterna.h
mapping
ConditionsMap & mapping
Definition: AlignmentsCalculator.cpp:82
dd4hep
Namespace for the AIDA detector description toolkit.
Definition: AlignmentsCalib.h:28
dd4hep::PlacedVolumeExtension::VolIDs::str
std::string str() const
String representation for debugging.
Definition: Volumes.cpp:436
dd4hep::VolumeManagerContext::identifier
VolumeID identifier
Placement identifier.
Definition: VolumeManager.h:55
dd4hep::detail::VolumeManagerObject::detMask
VolumeID detMask
Sub-detector mask.
Definition: VolumeManagerInterna.h:84
dd4hep::detail::VolumeManagerObject::sysID
VolumeID sysID
System identifier.
Definition: VolumeManagerInterna.h:82
det
DetElement::Object * det
Definition: AlignmentsCalculator.cpp:66
dd4hep::detail::VolumeManagerObject::volumes
std::map< VolumeID, VolumeManagerContext * > volumes
The container of placements managed by this instance.
Definition: VolumeManagerInterna.h:72
dd4hep::SensitiveDetector::readout
Readout readout() const
Access readout structure of the sensitive detector.
Definition: DetElement.cpp:420
dd4hep::PlacedVolume::volume
Volume volume() const
Logical volume of this placement.
Definition: Volumes.cpp:468
dd4hep::VolumeManager::_data
Object & _data() const
Additional data accessor.
Definition: VolumeManager.h:148
dd4hep::PlacedVolume::data
Object * data() const
Check if placement is properly instrumented.
Definition: Volumes.cpp:447
dd4hep::VolumeManagerContext
This structure describes the cached data for one placement held by the volume manager.
Definition: VolumeManager.h:50
dd4hep::Detector
The main interface to the dd4hep detector description package.
Definition: Detector.h:89
dd4hep::Readout
Handle to the implementation of the readout structure of a subdetector.
Definition: Readout.h:38
dd4hep::VolumeManagerContext::worldToLocal
Position worldToLocal(const Position &world) const
Transform world coordinates to the local coordinates.
Definition: VolumeManager.cpp:399
Encoding
DetElementVolumeIDs::Encoding Encoding
Definition: DetElementVolumeIDs.cpp:136
dd4hep::Readout::idSpec
IDDescriptor idSpec() const
Access IDDescription structure.
Definition: Readout.cpp:112
dd4hep::PlacedVolume::volIDs
const PlacedVolumeExtension::VolIDs & volIDs() const
Access to the volume IDs.
Definition: Volumes.cpp:496
dd4hep::DetElementObject::HAVE_SENSITIVE_DETECTOR
@ HAVE_SENSITIVE_DETECTOR
Definition: DetectorInterna.h:92
dd4hep::detail::VolumeManagerObject::update
void update(unsigned long tags, DetElement &det, void *param)
Update callback when alignment has changed (called only for subdetectors....)
Definition: VolumeManager.cpp:745
dd4hep::VolumeManagerContext::localToWorld
Position localToWorld(const double local[3]) const
Transform local coordinates to the world coordinates.
Definition: VolumeManager.cpp:362
Printout.h
dd4hep::IDDescriptor::toString
std::string toString() const
Access string representation.
Definition: IDDescriptor.cpp:60
dd4hep::PlacedVolumeExtension::VolIDs::find
std::vector< VolID >::const_iterator find(const std::string &name) const
Find entry.
Definition: Volumes.cpp:413
dd4hep::ConditionsMap
ConditionsMap class.
Definition: ConditionsMap.h:59
dd4hep::detail::VolumeManager_Populator
Helper class to populate the volume manager.
Definition: VolumeManager.cpp:46
dd4hep::DetElement::PLACEMENT_CHANGED
@ PLACEMENT_CHANGED
Definition: DetElement.h:218
dd4hep::DetElement::PLACEMENT_DETECTOR
@ PLACEMENT_DETECTOR
Definition: DetElement.h:222
dd4hep::VolumeManagerContext::elementPlacement
PlacedVolume elementPlacement() const
Acces the detector element volume placement.
Definition: VolumeManager.cpp:327
dd4hep::Volume::sensitiveDetector
Handle< NamedObject > sensitiveDetector() const
Access to the handle to the sensitive detector.
Definition: Volumes.cpp:1316