File indexing completed on 2025-01-30 09:17:05
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <DD4hep/Detector.h>
0016 #include <DD4hep/Printout.h>
0017 #include <DD4hep/MatrixHelpers.h>
0018 #include <DD4hep/detail/Handle.inl>
0019 #include <DD4hep/detail/ObjectsInterna.h>
0020 #include <DD4hep/detail/DetectorInterna.h>
0021 #include <DD4hep/detail/VolumeManagerInterna.h>
0022
0023
0024 #include <set>
0025 #include <cmath>
0026 #include <sstream>
0027 #include <iomanip>
0028
0029 using namespace dd4hep;
0030 using namespace dd4hep::detail;
0031
0032 DD4HEP_INSTANTIATE_HANDLE_NAMED(VolumeManagerObject);
0033
0034
0035 namespace dd4hep {
0036
0037
0038 namespace detail {
0039
0040
0041
0042
0043
0044
0045 class VolumeManager_Populator {
0046 typedef std::vector<TGeoNode*> Chain;
0047 typedef PlacedVolume::VolIDs VolIDs;
0048 typedef std::pair<VolumeID, VolumeID> Encoding;
0049
0050 const Detector& m_detDesc;
0051
0052 VolumeManager m_volManager;
0053
0054 std::set<VolumeID> m_entries;
0055
0056 bool m_debug = false;
0057
0058 std::size_t m_numNodes = 0;
0059
0060 public:
0061
0062 VolumeManager_Populator(const Detector& description, VolumeManager vm)
0063 : m_detDesc(description), m_volManager(vm)
0064 {
0065 m_debug = (0 != ::getenv("DD4HEP_VOLMGR_DEBUG"));
0066 }
0067
0068
0069 size_t numNodes() const { return m_numNodes; }
0070
0071
0072 void populate(DetElement e) {
0073
0074 SensitiveDetector parent_sd;
0075 if ( e->flag&DetElement::Object::HAVE_SENSITIVE_DETECTOR ) {
0076 parent_sd = m_detDesc.sensitiveDetector(e.name());
0077 }
0078
0079 for (const auto& i : e.children() ) {
0080 DetElement de = i.second;
0081 PlacedVolume pv = de.placement();
0082 if (pv.isValid()) {
0083 Chain chain;
0084 Encoding coding(0, 0);
0085 SensitiveDetector sd = parent_sd;
0086 m_entries.clear();
0087 scanPhysicalVolume(de, de, pv, coding, sd, chain);
0088 continue;
0089 }
0090 printout(WARNING, "VolumeManager", "++ Detector element %s of type %s has no placement.",
0091 de.name(), de.type().c_str());
0092 }
0093 }
0094
0095 size_t scanPhysicalVolume(DetElement& parent, DetElement e, PlacedVolume pv,
0096 Encoding parent_encoding,
0097 SensitiveDetector& sd, Chain& chain)
0098 {
0099 TGeoNode* node = pv.ptr();
0100 size_t count = 0;
0101 if (node) {
0102 Volume vol = pv.volume();
0103 const VolIDs& pv_ids = pv.volIDs();
0104 Encoding vol_encoding = parent_encoding;
0105 bool is_sensitive = vol.isSensitive();
0106 bool have_encoding = pv_ids.empty();
0107 bool compound = e.type() == "compound";
0108
0109 if ( compound ) {
0110 sd = SensitiveDetector(0);
0111 vol_encoding = Encoding();
0112 }
0113 else if ( !sd.isValid() ) {
0114 if ( is_sensitive )
0115 sd = vol.sensitiveDetector();
0116 else if ( (parent->flag&DetElement::Object::HAVE_SENSITIVE_DETECTOR) )
0117 sd = m_detDesc.sensitiveDetector(parent.name());
0118 else if ( (e->flag&DetElement::Object::HAVE_SENSITIVE_DETECTOR) )
0119 sd = m_detDesc.sensitiveDetector(e.name());
0120 }
0121 chain.emplace_back(node);
0122 if ( sd.isValid() && !pv_ids.empty() ) {
0123 Readout ro = sd.readout();
0124 if ( ro.isValid() ) {
0125 vol_encoding = update_encoding(ro.idSpec(), pv_ids, parent_encoding);
0126 have_encoding = true;
0127 }
0128 else {
0129 printout(WARNING, "VolumeManager",
0130 "%s: Strange constellation volume %s is sensitive, but has no readout! sd:%p",
0131 parent.name(), pv.volume().name(), sd.ptr());
0132 }
0133 }
0134 for (int idau = 0, ndau = node->GetNdaughters(); idau < ndau; ++idau) {
0135 TGeoNode* daughter = node->GetDaughter(idau);
0136 PlacedVolume placement(daughter);
0137 if ( placement.data() ) {
0138 PlacedVolume pv_dau(daughter);
0139 DetElement de_dau;
0140
0141
0142
0143 for( const auto& de : e.children() ) {
0144 if ( de.second.placement().ptr() == daughter ) {
0145 de_dau = de.second;
0146 break;
0147 }
0148 }
0149 if ( de_dau.isValid() ) {
0150 Chain dau_chain;
0151 count += scanPhysicalVolume(parent, de_dau, pv_dau, vol_encoding, sd, dau_chain);
0152 }
0153 else {
0154 count += scanPhysicalVolume(parent, e, pv_dau, vol_encoding, sd, chain);
0155 }
0156 }
0157 else {
0158 except("VolumeManager",
0159 "Invalid not instrumented placement:"+std::string(daughter->GetName())+
0160 " [Internal error -- bad detector constructor]");
0161 }
0162 if ( compound ) {
0163 sd = SensitiveDetector(0);
0164 }
0165 }
0166 if ( sd.isValid() ) {
0167 if ( !have_encoding && !compound ) {
0168 printout(ERROR, "VolumeManager","Element %s: Missing SD encoding. Volume manager won't work!",
0169 e.path().c_str());
0170 }
0171 if ( is_sensitive || count > 0 ) {
0172
0173
0174 if ( node == e.placement().ptr() ) {
0175
0176
0177
0178
0179
0180
0181
0182
0183 e.object<DetElement::Object>().volumeID = vol_encoding.first;
0184 }
0185 else {
0186
0187
0188
0189 }
0190 add_entry(sd, parent, e, node, vol_encoding, chain);
0191 ++count;
0192 if ( m_debug ) {
0193 IDDescriptor id(sd.readout().idSpec());
0194 printout(INFO,"VolumeManager","Parent: %-44s id:%016llx Encoding: %s",
0195 parent.path().c_str(), parent.volumeID(), id.str(parent_encoding.first,parent_encoding.second).c_str());
0196 printout(INFO,"VolumeManager","Element:%-44s id:%016llx Encoding: %s",
0197 e.path().c_str(), e.volumeID(), id.str(vol_encoding.first,vol_encoding.second).c_str());
0198 printout(INFO, "VolumeManager", "%s SD:%s VolIDs:%s id:%016llx mask:%016llx",
0199 node == e.placement().ptr() ? "DETELEMENT PLACEMENT" : "VOLUME PLACEMENT ",
0200 sd.name(), pv_ids.str().c_str(), vol_encoding.first, vol_encoding.second);
0201 }
0202 }
0203 }
0204 chain.pop_back();
0205 }
0206 return count;
0207 }
0208
0209
0210 static Encoding update_encoding(const IDDescriptor iddesc, const VolIDs& ids, const Encoding& initial) {
0211 VolumeID volume_id = initial.first, mask = initial.second;
0212 for (VolIDs::const_iterator i = ids.begin(); i != ids.end(); ++i) {
0213 const auto& id = (*i);
0214 const BitFieldElement* f = iddesc.field(id.first);
0215 VolumeID msk = f->mask();
0216 int off = f->offset();
0217 VolumeID val = id.second;
0218 volume_id |= ((f->value(val << off) << off)&msk);
0219 mask |= msk;
0220 }
0221 return std::make_pair(volume_id, mask);
0222 }
0223
0224 static Encoding encoding(const IDDescriptor iddesc, const VolIDs& ids) {
0225 VolumeID volume_id = 0, mask = 0;
0226 for (VolIDs::const_iterator i = ids.begin(); i != ids.end(); ++i) {
0227 const auto& id = (*i);
0228 const BitFieldElement* f = iddesc.field(id.first);
0229 VolumeID msk = f->mask();
0230 int off = f->offset();
0231 VolumeID val = id.second;
0232 volume_id |= ((f->value(val << off) << off)&msk);
0233 mask |= msk;
0234 }
0235 return std::make_pair(volume_id, mask);
0236 }
0237
0238 void add_entry(SensitiveDetector sd, DetElement parent, DetElement e,
0239 const TGeoNode* n, const Encoding& code, Chain& nodes)
0240 {
0241 if ( sd.isValid() ) {
0242 if (m_entries.find(code.first) == m_entries.end()) {
0243 Readout ro = sd.readout();
0244 std::string sd_name = sd.name();
0245 DetElement sub_detector = m_detDesc.detector(sd_name);
0246 VolumeManager section = m_volManager.addSubdetector(sub_detector, ro);
0247
0248
0249
0250 VolumeManagerContext* context = nodes.empty()
0251 ? new VolumeManagerContext
0252 : new detail::VolumeManagerContextExtension;
0253 context->identifier = code.first;
0254 context->mask = code.second;
0255 context->element = e;
0256 context->flag = nodes.empty() ? 0 : 1;
0257 if ( context->flag ) {
0258 detail::VolumeManagerContextExtension* ext = (detail::VolumeManagerContextExtension*)context;
0259 ext->placement = PlacedVolume(n);
0260 for (std::size_t i = nodes.size(); i > 1; --i) {
0261 TGeoMatrix* m = nodes[i-1]->GetMatrix();
0262 ext->toElement.MultiplyLeft(m);
0263 }
0264 }
0265 if ( !section.adoptPlacement(context) || m_debug ) {
0266 print_node(sd, parent, e, n, code, nodes);
0267 }
0268 m_entries.insert(code.first);
0269 ++m_numNodes;
0270
0271
0272
0273 }
0274 }
0275 }
0276
0277 void print_node(SensitiveDetector sd, DetElement parent, DetElement e,
0278 const TGeoNode* n, const Encoding& code, const Chain& nodes) const
0279 {
0280 PlacedVolume pv = n;
0281 Readout ro = sd.readout();
0282 bool sensitive = pv.volume().isSensitive();
0283
0284
0285 std::stringstream log;
0286 log << m_entries.size() << ": Detector: " << e.path()
0287 << " id:" << volumeID(code.first)
0288 << " Nodes(" << int(nodes.size()) << "):" << ro.idSpec().str(code.first,code.second);
0289 printout(m_debug ? INFO : DEBUG,"VolumeManager",log.str().c_str());
0290
0291
0292
0293 log.str("");
0294 log << m_entries.size() << ": " << parent.name()
0295 << " ro:" << ro.name() << " pv:" << n->GetName()
0296 << " Sensitive:" << yes_no(sensitive);
0297 printout(m_debug ? INFO : DEBUG, "VolumeManager", log.str().c_str());
0298 }
0299 };
0300 }
0301 }
0302
0303
0304 VolumeManagerContext::~VolumeManagerContext() {
0305 if ( 0 == flag ) return;
0306 }
0307
0308
0309 PlacedVolume VolumeManagerContext::elementPlacement() const {
0310 return element.placement();
0311 }
0312
0313
0314 PlacedVolume VolumeManagerContext::volumePlacement() const {
0315 if ( 0 == flag )
0316 return element.placement();
0317 const detail::VolumeManagerContextExtension* ext = (const detail::VolumeManagerContextExtension*)this;
0318 return ext->placement;
0319 }
0320
0321
0322 const TGeoHMatrix& VolumeManagerContext::toElement() const {
0323 static TGeoHMatrix identity;
0324 if ( 0 == flag ) return identity;
0325 const detail::VolumeManagerContextExtension* ext = (const detail::VolumeManagerContextExtension*)this;
0326 return ext->toElement;
0327 }
0328
0329
0330 Position VolumeManagerContext::localToElement(const double local[3]) const {
0331 double elt[3];
0332 toElement().LocalToMaster(local, elt);
0333 return { elt[0], elt[1], elt[2] };
0334 }
0335
0336
0337 Position VolumeManagerContext::localToElement(const Position& local) const {
0338 double loc[3];
0339 local.GetCoordinates(loc);
0340 return localToElement(loc);
0341 }
0342
0343
0344 Position VolumeManagerContext::localToWorld(const double local[3]) const {
0345 double elt[3];
0346 toElement().LocalToMaster(local, elt);
0347 return element.nominal().localToWorld(elt);
0348 }
0349
0350
0351 Position VolumeManagerContext::localToWorld(const Position& local) const {
0352 double l[3];
0353 local.GetCoordinates(l);
0354 return localToWorld(l);
0355 }
0356
0357
0358 Position VolumeManagerContext::worldToElement(const double world[3]) const {
0359 return element.nominal().worldToLocal(world);
0360 }
0361
0362
0363 Position VolumeManagerContext::worldToElement(const Position& world) const {
0364 return element.nominal().worldToLocal(world);
0365 }
0366
0367
0368 void VolumeManagerContext::worldToElement(const double world[3], double elt[3]) const {
0369 element.nominal().worldToLocal(world, elt);
0370 }
0371
0372
0373 Position VolumeManagerContext::worldToLocal(const double world[3]) const {
0374 double elt[3], local[3];
0375 worldToElement(world, elt);
0376 toElement().MasterToLocal(elt, local);
0377 return { local[0], local[1], local[2] };
0378 }
0379
0380
0381 Position VolumeManagerContext::worldToLocal(const Position& world) const {
0382 double global[3];
0383 world.GetCoordinates(global);
0384 return worldToLocal(global);
0385 }
0386
0387
0388 void VolumeManagerContext::worldToLocal(const double world[3], double local[3]) const {
0389 double elt[3];
0390 worldToElement(world, elt);
0391 toElement().MasterToLocal(elt, local);
0392 }
0393
0394
0395 VolumeManager::VolumeManager(const Detector& description, const std::string& nam, DetElement elt, Readout ro, int flags) {
0396 printout(INFO, "VolumeManager", " - populating volume ids - be patient ..." );
0397 std::size_t node_count = 0;
0398 Object* obj_ptr = new Object();
0399 assign(obj_ptr, nam, "VolumeManager");
0400 if (elt.isValid()) {
0401 detail::VolumeManager_Populator p(description, *this);
0402 obj_ptr->detector = elt;
0403 obj_ptr->id = ro.isValid() ? ro.idSpec() : IDDescriptor();
0404 obj_ptr->top = obj_ptr;
0405 obj_ptr->flags = flags;
0406 p.populate(elt);
0407 node_count = p.numNodes();
0408 }
0409 printout(INFO, "VolumeManager", " - populating volume ids - done. %ld nodes.",node_count);
0410 }
0411
0412
0413 VolumeManager::VolumeManager(DetElement sub_detector, Readout ro) {
0414 Object* obj_ptr = new Object();
0415 obj_ptr->detector = sub_detector;
0416 obj_ptr->id = ro.isValid() ? ro.idSpec() : IDDescriptor();
0417 assign(obj_ptr, sub_detector.name(), "VolumeManager");
0418 }
0419
0420 VolumeManager VolumeManager::getVolumeManager(const Detector& description) {
0421 if( not description.volumeManager().isValid() ) {
0422 description.apply("DD4hepVolumeManager", 0, 0);
0423 }
0424 return description.volumeManager();
0425 }
0426
0427
0428 VolumeManager VolumeManager::addSubdetector(DetElement det, Readout ro) {
0429 if (isValid()) {
0430 Object& o = _data();
0431 if (!det.isValid()) {
0432 throw std::runtime_error("dd4hep: VolumeManager::addSubdetector: Only valid subdetectors "
0433 "are allowed. [Invalid DetElement]");
0434 }
0435 auto i = o.subdetectors.find(det);
0436 if (i == o.subdetectors.end()) {
0437 std::string det_name = det.name();
0438
0439 if (!ro.isValid()) {
0440 throw std::runtime_error("dd4hep: VolumeManager::addSubdetector: Only subdetectors with a "
0441 "valid readout descriptor are allowed. [Invalid DetElement:" + det_name + "]");
0442 }
0443 PlacedVolume pv = det.placement();
0444 if (!pv.isValid()) {
0445 throw std::runtime_error("dd4hep: VolumeManager::addSubdetector: Only subdetectors with a "
0446 "valid placement are allowed. [Invalid DetElement:" + det_name + "]");
0447 }
0448 auto vit = pv.volIDs().find("system");
0449 if (vit == pv.volIDs().end()) {
0450 throw std::runtime_error("dd4hep: VolumeManager::addSubdetector: Only subdetectors with "
0451 "valid placement VolIDs are allowed. [Invalid DetElement:" + det_name + "]");
0452 }
0453
0454 i = o.subdetectors.emplace(det, VolumeManager(det,ro)).first;
0455 const auto& id = (*vit);
0456 VolumeManager mgr = (*i).second;
0457 const BitFieldElement* field = ro.idSpec().field(id.first);
0458 if (!field) {
0459 throw std::runtime_error("dd4hep: VolumeManager::addSubdetector: IdDescriptor of " +
0460 std::string(det.name()) + " has no field " + id.first);
0461 }
0462 Object& mo = mgr._data();
0463 mo.top = o.top;
0464 mo.flags = o.flags;
0465 mo.system = field;
0466 mo.sysID = id.second;
0467 mo.detMask = mo.sysID;
0468 o.managers[mo.sysID] = mgr;
0469 det.callAtUpdate(DetElement::PLACEMENT_CHANGED|DetElement::PLACEMENT_DETECTOR,
0470 &mo,&Object::update);
0471 }
0472 return (*i).second;
0473 }
0474 throw std::runtime_error("dd4hep: VolumeManager::addSubdetector: "
0475 "Failed to add subdetector section. [Invalid Manager Handle]");
0476 }
0477
0478
0479 VolumeManager VolumeManager::subdetector(VolumeID id) const {
0480 if (isValid()) {
0481 const Object& o = _data();
0482
0483 for (const auto& j : o.subdetectors ) {
0484 const Object& mo = j.second._data();
0485 VolumeID sys_id = mo.system->value(id << mo.system->offset());
0486 if ( sys_id == mo.sysID )
0487 return j.second;
0488 }
0489 throw std::runtime_error("dd4hep: VolumeManager::subdetector(VolID): "
0490 "Attempt to access unknown subdetector section.");
0491 }
0492 throw std::runtime_error("dd4hep: VolumeManager::subdetector(VolID): "
0493 "Cannot assign ID descriptor [Invalid Manager Handle]");
0494 }
0495
0496
0497 DetElement VolumeManager::detector() const {
0498 if (isValid()) {
0499 return _data().detector;
0500 }
0501 throw std::runtime_error("dd4hep: VolumeManager::detector: Cannot access DetElement [Invalid Handle]");
0502 }
0503
0504
0505 IDDescriptor VolumeManager::idSpec() const {
0506 return _data().id;
0507 }
0508
0509
0510 bool VolumeManager::adoptPlacement(VolumeID sys_id, VolumeManagerContext* context) {
0511 std::stringstream err;
0512 Object& o = _data();
0513 VolumeID vid = context->identifier;
0514 VolumeID mask = context->mask;
0515 PlacedVolume pv = context->elementPlacement();
0516 auto i = o.volumes.find(vid);
0517
0518 if ( (vid&mask) != vid ) {
0519 err << "Bad context mask:" << (void*)mask
0520 << " id:" << (void*)vid
0521 << " pv:" << pv.name()
0522 << " Sensitive:" << yes_no(pv.volume().isSensitive())
0523 << std::endl;
0524 goto Fail;
0525 }
0526
0527 if ( i == o.volumes.end()) {
0528 o.volumes[vid] = context;
0529 o.detMask |= mask;
0530 err << "Inserted new volume:" << std::setw(6) << std::left << o.volumes.size()
0531 << " Ptr:" << (void*) pv.ptr()
0532 << " [" << pv.name() << "]"
0533 << " id:" << std::setw(16) << std::hex << std::right << std::setfill('0') << vid << std::dec << std::setfill(' ')
0534 << " mask:" << std::setw(16) << std::hex << std::right << std::setfill('0') << mask << std::dec << std::setfill(' ')
0535 << " Det:" << std::setw(4) << std::hex << std::right << std::setfill('0') << context->element.volumeID()
0536 << " / " << std::setw(4) << sys_id << std::dec << std::setfill(' ') << ": " << context->element.path();
0537 printout(VERBOSE, "VolumeManager", err.str().c_str());
0538
0539 return true;
0540 }
0541 err << "+++ Attempt to register duplicate"
0542 << " id:" << std::setw(16) << std::hex << std::right << std::setfill('0') << vid << std::dec << std::setfill(' ')
0543 << " mask:" << std::setw(16) << std::hex << std::right << std::setfill('0') << mask << std::dec << std::setfill(' ')
0544 << " to detector " << o.detector.name()
0545 << " ptr:" << (void*) pv.ptr()
0546 << " Name:" << pv.name()
0547 << " Sensitive:" << yes_no(pv.volume().isSensitive())
0548 << std::endl;
0549 printout(ERROR, "VolumeManager", "%s", err.str().c_str());
0550 err.str("");
0551 context = (*i).second;
0552
0553 err << " !!!!! +++ Clashing"
0554 << " id:" << std::setw(16) << std::hex << std::right << std::setfill('0') << vid << std::dec << std::setfill(' ')
0555 << " mask:" << std::setw(16) << std::hex << std::right << std::setfill('0') << mask << std::dec << std::setfill(' ')
0556 << " to detector " << o.detector.name()
0557 << " ptr:" << (void*) pv.ptr()
0558 << " Name:" << pv.name()
0559 << " Sensitive:" << yes_no(pv.volume().isSensitive())
0560 << std::endl;
0561 Fail:
0562 printout(ERROR, "VolumeManager", "%s", err.str().c_str());
0563
0564 return false;
0565 }
0566
0567
0568 bool VolumeManager::adoptPlacement(VolumeManagerContext* context) {
0569 std::stringstream err;
0570 if ( isValid() ) {
0571 Object& o = _data();
0572 if ( context ) {
0573 if ( (o.flags & ONE) == ONE ) {
0574 VolumeManager top(o.top);
0575 return top.adoptPlacement(context);
0576 }
0577 if ( (o.flags & TREE) == TREE ) {
0578 bool isTop = ptr() == o.top;
0579 if ( !isTop ) {
0580 VolumeID sys_id = o.system->value(context->identifier);
0581 if ( sys_id == o.sysID ) {
0582 return adoptPlacement(sys_id, context);
0583 }
0584 VolumeManager top(o.top);
0585 return top.adoptPlacement(context);
0586 }
0587 for( auto& j : o.managers ) {
0588 Object& mgr = j.second._data();
0589 VolumeID sid = mgr.system->value(context->identifier);
0590 if ( j.first == sid ) {
0591 return j.second.adoptPlacement(sid, context);
0592 }
0593 }
0594 }
0595 return false;
0596 }
0597 except("VolumeManager","dd4hep: Failed to add new physical volume to detector: %s "
0598 "[Invalid Context]", o.detector.name());
0599 }
0600 except("VolumeManager","dd4hep: Failed to add new physical volume [Invalid Manager Handle]");
0601 return false;
0602 }
0603
0604
0605 VolumeManagerContext* VolumeManager::lookupContext(VolumeID volume_id) const {
0606 if (isValid()) {
0607 VolumeManagerContext* c = 0;
0608 const Object& o = _data();
0609 bool is_top = o.top == ptr();
0610 bool one_tree = (o.flags & ONE) == ONE;
0611 if ( !is_top && one_tree ) {
0612 return VolumeManager(o.top).lookupContext(volume_id);
0613 }
0614 VolumeID id = volume_id;
0615
0616 c = o.search(id);
0617 if (c)
0618 return c;
0619
0620 if (!one_tree) {
0621 for (const auto& j : o.subdetectors ) {
0622 if ((c = j.second._data().search(id)) != 0)
0623 return c;
0624 }
0625 }
0626 except("VolumeManager","lookupContext: Failed to search Volume context %016llX [Unknown identifier]", (void*)volume_id);
0627 }
0628 except("VolumeManager","lookupContext: Failed to search Volume context [Invalid Manager Handle]");
0629 return 0;
0630 }
0631
0632
0633 PlacedVolume VolumeManager::lookupDetElementPlacement(VolumeID volume_id) const {
0634 VolumeManagerContext* c = lookupContext(volume_id);
0635 return c->elementPlacement();
0636 }
0637
0638
0639 PlacedVolume VolumeManager::lookupVolumePlacement(VolumeID volume_id) const {
0640 VolumeManagerContext* c = lookupContext(volume_id);
0641 return c->volumePlacement();
0642 }
0643
0644
0645 DetElement VolumeManager::lookupDetector(VolumeID volume_id) const {
0646 if (isValid()) {
0647 const Object& o = _data();
0648 VolumeID sys_id = 0;
0649 if ( o.system ) {
0650 sys_id = o.system->value(volume_id);
0651 }
0652 else {
0653 for (const auto& j : o.subdetectors ) {
0654 if ( j.second->system ) {
0655 VolumeID vid = volume_id&j.second->system->mask();
0656 if ( (volume_id&j.second->sysID) == vid ) {
0657 sys_id = j.second->sysID;
0658 break;
0659 }
0660 }
0661 }
0662 }
0663 VolumeID det_id = (volume_id&sys_id);
0664 VolumeManagerContext* c = lookupContext(det_id);
0665 return c->element;
0666 }
0667 except("VolumeManager","lookupContext: Failed to search Volume context [Invalid Manager Handle]");
0668 return DetElement();
0669 }
0670
0671
0672 DetElement VolumeManager::lookupDetElement(VolumeID volume_id) const {
0673 VolumeManagerContext* c = lookupContext(volume_id);
0674 return c->element;
0675 }
0676
0677
0678 const TGeoMatrix&
0679 VolumeManager::worldTransformation(const ConditionsMap& mapping,
0680 VolumeID volume_id) const
0681 {
0682 VolumeManagerContext* c = lookupContext(volume_id);
0683 Alignment a = mapping.get(c->element,align::Keys::alignmentKey);
0684 return a.worldTransformation();
0685 }
0686
0687
0688 std::ostream& dd4hep::operator<<(std::ostream& os, const VolumeManager& mgr) {
0689 const VolumeManager::Object& o = *mgr.data<VolumeManager::Object>();
0690 VolumeManager::Object* top = dynamic_cast<VolumeManager::Object*>(o.top);
0691 bool isTop = top == &o;
0692
0693
0694 std::string prefix(isTop ? "" : "++ ");
0695 os << prefix << (isTop ? "TOP Level " : "Secondary ") << "Volume manager:"
0696 << &o << " " << o.detector.name() << " IDD:"
0697 << o.id.toString() << " SysID:" << (void*) o.sysID << " "
0698 << o.managers.size() << " subsections " << o.volumes.size()
0699 << " placements ";
0700 if (!(o.managers.empty() && o.volumes.empty()))
0701 os << std::endl;
0702 for ( const auto& i : o.volumes ) {
0703 const VolumeManagerContext* c = i.second;
0704 os << prefix
0705 << "Element:" << std::setw(32) << std::left << c->element.path()
0706
0707 << " id:" << std::setw(18) << std::left << (void*) c->identifier
0708 << " mask:" << std::setw(18) << std::left << (void*) c->mask
0709 << std::endl;
0710 }
0711 for( const auto& i : o.managers )
0712 os << prefix << i.second << std::endl;
0713 return os;
0714 }
0715
0716
0717 VolumeManagerObject::~VolumeManagerObject() {
0718
0719 destroyObjects(volumes);
0720
0721 destroyHandles(managers);
0722 managers.clear();
0723 subdetectors.clear();
0724 }
0725
0726
0727 void VolumeManagerObject::update(unsigned long tags, DetElement& det, void* param) {
0728 if ( DetElement::CONDITIONS_CHANGED == (tags&DetElement::CONDITIONS_CHANGED) )
0729 printout(DEBUG,"VolumeManager","+++ Conditions update %s param:%p",det.path().c_str(),param);
0730 if ( DetElement::PLACEMENT_CHANGED == (tags&DetElement::PLACEMENT_CHANGED) )
0731 printout(DEBUG,"VolumeManager","+++ Alignment update %s param:%p",det.path().c_str(),param);
0732
0733 for(const auto& i : volumes )
0734 printout(DEBUG,"VolumeManager","+++ Alignment update %s",i.second->elementPlacement().name());
0735 }
0736
0737
0738 VolumeManagerContext* VolumeManagerObject::search(const VolumeID& vol_id) const {
0739 auto i = volumes.find(vol_id&detMask);
0740 return (i == volumes.end()) ? 0 : (*i).second;
0741 }
0742