 |
DD4hep
1.37.0
Detector Description Toolkit for High Energy Physics
|
Go to the documentation of this file.
18 #include <DD4hep/detail/Handle.inl>
28 #include <unordered_map>
47 typedef std::vector<TGeoNode*>
Chain;
49 typedef std::pair<VolumeID, VolumeID>
Encoding;
61 std::size_t m_numNodes = 0;
66 : m_detDesc(description), m_volManager(vm)
68 m_debug = (0 != ::getenv(
"DD4HEP_VOLMGR_DEBUG"));
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;
95 for (
const auto& i : e.
children() ) {
103 scanPhysicalVolume(de, de, pv, coding, sd, chain);
106 printout(WARNING,
"VolumeManager",
"++ Detector element %s of type %s has no placement.",
115 TGeoNode* node = pv.
ptr();
120 Encoding vol_encoding = parent_encoding;
122 bool have_encoding = pv_ids.empty();
123 bool compound = e.
type() ==
"compound";
137 chain.emplace_back(node);
138 if ( sd.
isValid() && !pv_ids.empty() ) {
141 vol_encoding = update_encoding(ro.
idSpec(), pv_ids, parent_encoding);
142 have_encoding =
true;
145 printout(WARNING,
"VolumeManager",
146 "%s: Strange constellation volume %s is sensitive, but has no readout! sd:%p",
150 for (
int idau = 0, ndau = node->GetNdaughters(); idau < ndau; ++idau) {
151 TGeoNode* daughter = node->GetDaughter(idau);
153 if ( placement.
data() ) {
154 if ( hasSensitiveContent(daughter->GetVolume()) ) {
160 for(
const auto& de : e.
children() ) {
161 if ( de.second.placement().ptr() == daughter ) {
168 count += scanPhysicalVolume(parent, de_dau, pv_dau, vol_encoding, sd, dau_chain);
171 count += scanPhysicalVolume(parent, e, pv_dau, vol_encoding, sd, chain);
176 except(
"VolumeManager",
177 "Invalid not instrumented placement:"+std::string(daughter->GetName())+
178 " [Internal error -- bad detector constructor]");
185 if ( !have_encoding && !compound ) {
186 printout(ERROR,
"VolumeManager",
"Element %s: Missing SD encoding. Volume manager won't work!",
189 if ( is_sensitive || count > 0 ) {
208 add_entry(sd, parent, e, node, vol_encoding, chain);
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);
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);
236 volume_id |= ((f->
value(val << off) << off)&msk);
239 return std::make_pair(volume_id, mask);
244 for (VolIDs::const_iterator i = ids.begin(); i != ids.end(); ++i) {
245 const auto&
id = (*i);
250 volume_id |= ((f->
value(val << off) << off)&msk);
253 return std::make_pair(volume_id, mask);
260 if (m_entries.find(code.first) == m_entries.end()) {
262 std::string sd_name = sd.
name();
272 context->
mask = code.second;
274 context->
flag = nodes.empty() ? 0 : 1;
275 if ( context->
flag ) {
278 for (std::size_t i = nodes.size(); i > 1; --i) {
279 TGeoMatrix* m = nodes[i-1]->GetMatrix();
284 print_node(sd, parent, e, n, code, nodes);
286 m_entries.insert(code.first);
296 const TGeoNode* n,
const Encoding& code,
const Chain& nodes)
const
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());
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());
323 if ( 0 == flag )
return;
328 return element.placement();
334 return element.placement();
341 static TGeoHMatrix identity;
342 if ( 0 == flag )
return identity;
350 toElement().LocalToMaster(local, elt);
351 return { elt[0], elt[1], elt[2] };
357 local.GetCoordinates(loc);
358 return localToElement(loc);
364 toElement().LocalToMaster(local, elt);
365 return element.nominal().localToWorld(elt);
371 local.GetCoordinates(l);
372 return localToWorld(l);
377 return element.nominal().worldToLocal(world);
382 return element.nominal().worldToLocal(world);
387 element.nominal().worldToLocal(world, elt);
392 double elt[3], local[3];
393 worldToElement(world, elt);
394 toElement().MasterToLocal(elt, local);
395 return { local[0], local[1], local[2] };
401 world.GetCoordinates(global);
402 return worldToLocal(global);
408 worldToElement(world, elt);
409 toElement().MasterToLocal(elt, local);
414 printout(INFO,
"VolumeManager",
" - populating volume ids - be patient ..." );
415 std::size_t node_count = 0;
417 assign(obj_ptr, nam,
"VolumeManager");
422 obj_ptr->
top = obj_ptr;
423 obj_ptr->
flags = flags;
427 printout(INFO,
"VolumeManager",
" - populating volume ids - done. %ld nodes.",node_count);
435 assign(obj_ptr, sub_detector.
name(),
"VolumeManager");
440 description.
apply(
"DD4hepVolumeManager", 0, 0);
449 if (!
det.isValid()) {
450 throw std::runtime_error(
"dd4hep: VolumeManager::addSubdetector: Only valid subdetectors "
451 "are allowed. [Invalid DetElement]");
455 std::string det_name =
det.name();
458 throw std::runtime_error(
"dd4hep: VolumeManager::addSubdetector: Only subdetectors with a "
459 "valid readout descriptor are allowed. [Invalid DetElement:" + det_name +
"]");
463 throw std::runtime_error(
"dd4hep: VolumeManager::addSubdetector: Only subdetectors with a "
464 "valid placement are allowed. [Invalid DetElement:" + det_name +
"]");
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 +
"]");
473 const auto&
id = (*vit);
477 throw std::runtime_error(
"dd4hep: VolumeManager::addSubdetector: IdDescriptor of " +
478 std::string(
det.name()) +
" has no field " +
id.first);
484 mo.
sysID =
id.second;
488 &mo,&Object::update);
492 throw std::runtime_error(
"dd4hep: VolumeManager::addSubdetector: "
493 "Failed to add subdetector section. [Invalid Manager Handle]");
499 const Object& o = _data();
502 const Object& mo = j.second._data();
504 if ( sys_id == mo.
sysID )
507 throw std::runtime_error(
"dd4hep: VolumeManager::subdetector(VolID): "
508 "Attempt to access unknown subdetector section.");
510 throw std::runtime_error(
"dd4hep: VolumeManager::subdetector(VolID): "
511 "Cannot assign ID descriptor [Invalid Manager Handle]");
517 return _data().detector;
519 throw std::runtime_error(
"dd4hep: VolumeManager::detector: Cannot access DetElement [Invalid Handle]");
529 std::stringstream err;
536 if ( (vid&mask) != vid ) {
537 err <<
"Bad context mask:" << (
void*)mask
538 <<
" id:" << (
void*)vid
539 <<
" pv:" << pv.
name()
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());
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(
' ')
563 <<
" ptr:" << (
void*) pv.
ptr()
564 <<
" Name:" << pv.
name()
567 printout(ERROR,
"VolumeManager",
"%s", err.str().c_str());
569 context = (*i).second;
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(
' ')
575 <<
" ptr:" << (
void*) pv.
ptr()
576 <<
" Name:" << pv.
name()
580 printout(ERROR,
"VolumeManager",
"%s", err.str().c_str());
587 std::stringstream err;
591 if ( (o.
flags & ONE) == ONE ) {
595 if ( (o.
flags & TREE) == TREE ) {
596 bool isTop = ptr() == o.
top;
599 if ( sys_id == o.
sysID ) {
600 return adoptPlacement(sys_id, context);
606 Object& mgr = j.second._data();
608 if ( j.first == sid ) {
609 return j.second.adoptPlacement(sid, context);
615 except(
"VolumeManager",
"dd4hep: Failed to add new physical volume to detector: %s "
618 except(
"VolumeManager",
"dd4hep: Failed to add new physical volume [Invalid Manager Handle]");
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 ) {
640 if ((c = j.second._data().search(
id)) != 0)
644 except(
"VolumeManager",
"lookupContext: Failed to search Volume context %016llX [Unknown identifier]", (
void*)volume_id);
646 except(
"VolumeManager",
"lookupContext: Failed to search Volume context [Invalid Manager Handle]");
665 const Object& o = _data();
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;
681 VolumeID det_id = (volume_id&sys_id);
685 except(
"VolumeManager",
"lookupContext: Failed to search Volume context [Invalid Manager Handle]");
709 bool isTop = top == &o;
712 std::string prefix(isTop ?
"" :
"++ ");
713 os << prefix << (isTop ?
"TOP Level " :
"Secondary ") <<
"Volume manager:"
720 for (
const auto& i : o.
volumes ) {
723 <<
"Element:" << std::setw(32) << std::left << c->
element.
path()
725 <<
" id:" << std::setw(18) << std::left << (
void*) c->
identifier
726 <<
" mask:" << std::setw(18) << std::left << (
void*) c->
mask
730 os << prefix << i.second << std::endl;
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);
752 printout(DEBUG,
"VolumeManager",
"+++ Alignment update %s",i.second->elementPlacement().name());
758 return (i ==
volumes.end()) ? 0 : (*i).second;
const Children & children() const
Access to the list of children.
Position worldToElement(const Position &world) const
Transform world coordinates to the DetElement coordinates.
const std::string & path() const
Path of the detector element (not necessarily identical to placement path!)
PlacedVolume placement
The placement of the (sensitive) volume.
DD4HEP_INSTANTIATE_HANDLE_NAMED(VolumeManagerObject)
DetElement lookupDetElement(VolumeID volume_id) const
Convenience routine: Lookup the closest subdetector detector element in the hierarchy according to a ...
int flags
Population flags.
Helper class for BitFieldCoder that corresponds to one field value.
VolumeManagerContext * lookupContext(VolumeID volume_id) const
Lookup the context, which belongs to a registered physical volume.
virtual DetElement detector(const std::string &name) const =0
Retrieve a subdetector element by its name from the detector description.
std::map< VolumeID, VolumeManager > managers
The volume managers for the individual subdetector elements.
Handle class to hold the information of a sensitive detector.
bool adoptPlacement(VolumeManagerContext *context)
Register physical volume with the manager (normally: section manager)
const BitFieldElement * system
The system field descriptor.
const BitFieldElement * field(const std::string &field_name) const
Get the field descriptor of one field by name.
bool hasSensitiveContent(TGeoVolume *vol)
Returns true if vol or any descendant is a sensitive volume (result is cached).
std::string type() const
Access detector type (structure, tracker, calorimeter, etc.).
Handle class holding a placed volume (also called physical volume)
Q & object() const
Access to an unrelated object type.
std::unordered_map< TGeoVolume *, bool > m_has_sensitive
Cache: does a TGeoVolume subtree contain any sensitive volume?
static Encoding encoding(const IDDescriptor iddesc, const VolIDs &ids)
Compute the encoding for a set of VolIDs within a readout descriptor.
PlacedVolume placement() const
Access to the physical volume of this detector element.
Class implementing the ID encoding of the detector response.
FieldID value(CellID bitfield) const
calculate this field's value given an external 64 bit bitmap
DetElement element
Handle to the closest Detector element.
const TGeoMatrix & worldTransformation(const ConditionsMap &map, VolumeID volume_id) const
Convenience routine: Access the transformation of a physical volume to the world coordinate system.
bool isValid() const
Check the validity of the object held by the handle.
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.
void print_node(SensitiveDetector sd, DetElement parent, DetElement e, const TGeoNode *n, const Encoding &code, const Chain &nodes) const
DetElement detector
The Detector element handle managed by this instance.
std::pair< VolumeID, VolumeID > Encoding
bool isSensitive() const
Accessor if volume is sensitive (ie. is attached to a sensitive detector)
DetElement detector() const
Access the top level detector element.
VolumeID volumeID() const
The cached VolumeID of this subdetector element.
PlacedVolume volumePlacement() const
Acces the sensitive volume placement.
const char * name() const
Access the object name (or "" if not supported by the object)
VolumeManagerContext * search(const VolumeID &id) const
Search the locally cached volumes for a matching ID.
Extended context. Needs to be public for persistency reasons.
This structure describes the internal data of the volume manager object.
virtual VolumeManager volumeManager() const =0
Return handle to the VolumeManager.
Data class with properties of a detector element.
std::ostream & operator<<(std::ostream &os, const DetType &t)
VolumeManager_Populator(const Detector &description, VolumeManager vm)
Default constructor.
Handle< T > & clear()
Release the object held by the handle.
VolumeManager()=default
Default constructor.
size_t numNodes() const
Access node count.
std::vector< TGeoNode * > Chain
VolumeID mask
Ignore mask of the placement identifier.
virtual ~VolumeManagerContext()
Default destructor.
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.
const Detector & m_detDesc
Reference to the Detector instance.
PlacedVolume lookupVolumePlacement(VolumeID volume_id) const
Lookup a physical (placed) volume identified by its 64 bit hit ID.
Handle class describing a detector element.
Handle class holding a placed volume (also called physical volume)
Class to support the retrieval of detector elements and volumes given a valid identifier.
DD4hep internal namespace.
std::map< DetElement, VolumeManager > subdetectors
The container of subdetector elements.
DetElement lookupDetector(VolumeID volume_id) const
Convenience routine: Lookup a top level subdetector detector element according to a contained 64 bit ...
virtual long apply(const char *factory, int argc, char **argv) const =0
Manipulate geometry using factory converter.
TGeoHMatrix toElement
The transformation of space-points to the coordinate system of the closests detector element.
static const Condition::itemkey_type alignmentKey
Key value of an alignment condition object "alignment".
Q * data() const
Access to an unrelated object type.
static VolumeManager getVolumeManager(const Detector &description)
static accessor calling DD4hepVolumeManagerPlugin if necessary
VolumeManager subdetector(VolumeID id) const
Access the volume manager by cell id.
const TGeoHMatrix & worldTransformation() const
Create cached matrix to transform to world coordinates.
virtual SensitiveDetector sensitiveDetector(const std::string &name) const =0
Retrieve a sensitive detector by its name from the detector description.
void add_entry(SensitiveDetector sd, DetElement parent, DetElement e, const TGeoNode *n, const Encoding &code, Chain &nodes)
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...
void destroyHandles(M &arg)
Functional created of map destruction functors.
IDDescriptor id
The ID descriptor object.
std::string str(VolumeID vid) const
Decode volume IDs and return string reprensentation for debugging purposes.
std::set< VolumeID > m_entries
Set of already added entries.
Main handle class to hold an alignment object.
void populate(DetElement e)
Populate the Volume manager.
Position localToElement(const double local[3]) const
Transform local coordinates to the DetElement coordinates.
PlacedVolume::VolIDs VolIDs
const TGeoHMatrix & toElement() const
Access the transformation to the closest detector element.
VolumeManager addSubdetector(DetElement detector, Readout ro)
Add a new Volume manager section according to a new subdetector.
PlacedVolume lookupDetElementPlacement(VolumeID volume_id) const
Lookup a physical (placed) volume of the detector element containing a volume identified by its 64 bi...
IDDescriptor IDDescriptor
long flag
Flag to indicate optional information.
ROOT::Math::XYZVector Position
virtual ~VolumeManagerObject()
Default destructor.
dd4hep::DDSegmentation::VolumeID VolumeID
VolumeManagerObject * top
The reference to the TOP level VolumeManager.
IDDescriptor idSpec() const
Access IDDescription structure.
VolumeManager m_volManager
Reference to the volume manager to be populated.
T * ptr() const
Access to the held object.
Namespace for the AIDA detector description toolkit.
std::string str() const
String representation for debugging.
VolumeID identifier
Placement identifier.
VolumeID detMask
Sub-detector mask.
VolumeID sysID
System identifier.
std::map< VolumeID, VolumeManagerContext * > volumes
The container of placements managed by this instance.
Readout readout() const
Access readout structure of the sensitive detector.
Volume volume() const
Logical volume of this placement.
Object & _data() const
Additional data accessor.
Object * data() const
Check if placement is properly instrumented.
This structure describes the cached data for one placement held by the volume manager.
The main interface to the dd4hep detector description package.
Handle to the implementation of the readout structure of a subdetector.
Position worldToLocal(const Position &world) const
Transform world coordinates to the local coordinates.
DetElementVolumeIDs::Encoding Encoding
IDDescriptor idSpec() const
Access IDDescription structure.
const PlacedVolumeExtension::VolIDs & volIDs() const
Access to the volume IDs.
@ HAVE_SENSITIVE_DETECTOR
void update(unsigned long tags, DetElement &det, void *param)
Update callback when alignment has changed (called only for subdetectors....)
Position localToWorld(const double local[3]) const
Transform local coordinates to the world coordinates.
std::string toString() const
Access string representation.
std::vector< VolID >::const_iterator find(const std::string &name) const
Find entry.
Helper class to populate the volume manager.
PlacedVolume elementPlacement() const
Acces the detector element volume placement.
Handle< NamedObject > sensitiveDetector() const
Access to the handle to the sensitive detector.