|
DD4hep
1.30.0
Detector Description Toolkit for High Energy Physics
|
Go to the documentation of this file.
18 #include <DD4hep/detail/Handle.inl>
46 typedef std::vector<TGeoNode*>
Chain;
48 typedef std::pair<VolumeID, VolumeID>
Encoding;
58 std::size_t m_numNodes = 0;
63 : m_detDesc(description), m_volManager(vm)
65 m_debug = (0 != ::getenv(
"DD4HEP_VOLMGR_DEBUG"));
79 for (
const auto& i : e.
children() ) {
87 scanPhysicalVolume(de, de, pv, coding, sd, chain);
90 printout(WARNING,
"VolumeManager",
"++ Detector element %s of type %s has no placement.",
99 TGeoNode* node = pv.
ptr();
104 Encoding vol_encoding = parent_encoding;
106 bool have_encoding = pv_ids.empty();
107 bool compound = e.
type() ==
"compound";
121 chain.emplace_back(node);
122 if ( sd.
isValid() && !pv_ids.empty() ) {
125 vol_encoding = update_encoding(ro.
idSpec(), pv_ids, parent_encoding);
126 have_encoding =
true;
129 printout(WARNING,
"VolumeManager",
130 "%s: Strange constellation volume %s is sensitive, but has no readout! sd:%p",
134 for (
int idau = 0, ndau = node->GetNdaughters(); idau < ndau; ++idau) {
135 TGeoNode* daughter = node->GetDaughter(idau);
137 if ( placement.
data() ) {
143 for(
const auto& de : e.
children() ) {
144 if ( de.second.placement().ptr() == daughter ) {
151 count += scanPhysicalVolume(parent, de_dau, pv_dau, vol_encoding, sd, dau_chain);
154 count += scanPhysicalVolume(parent, e, pv_dau, vol_encoding, sd, chain);
158 except(
"VolumeManager",
159 "Invalid not instrumented placement:"+std::string(daughter->GetName())+
160 " [Internal error -- bad detector constructor]");
167 if ( !have_encoding && !compound ) {
168 printout(ERROR,
"VolumeManager",
"Element %s: Missing SD encoding. Volume manager won't work!",
171 if ( is_sensitive || count > 0 ) {
190 add_entry(sd, parent, e, node, vol_encoding, chain);
194 printout(INFO,
"VolumeManager",
"Parent: %-44s id:%016llx Encoding: %s",
195 parent.
path().c_str(), parent.
volumeID(),
id.str(parent_encoding.first,parent_encoding.second).c_str());
196 printout(INFO,
"VolumeManager",
"Element:%-44s id:%016llx Encoding: %s",
197 e.
path().c_str(), e.
volumeID(),
id.str(vol_encoding.first,vol_encoding.second).c_str());
198 printout(INFO,
"VolumeManager",
"%s SD:%s VolIDs:%s id:%016llx mask:%016llx",
199 node == e.
placement().
ptr() ?
"DETELEMENT PLACEMENT" :
"VOLUME PLACEMENT ",
200 sd.
name(), pv_ids.
str().c_str(), vol_encoding.first, vol_encoding.second);
211 VolumeID volume_id = initial.first, mask = initial.second;
212 for (VolIDs::const_iterator i = ids.begin(); i != ids.end(); ++i) {
213 const auto&
id = (*i);
218 volume_id |= ((f->
value(val << off) << off)&msk);
221 return std::make_pair(volume_id, mask);
226 for (VolIDs::const_iterator i = ids.begin(); i != ids.end(); ++i) {
227 const auto&
id = (*i);
232 volume_id |= ((f->
value(val << off) << off)&msk);
235 return std::make_pair(volume_id, mask);
242 if (m_entries.find(code.first) == m_entries.end()) {
244 std::string sd_name = sd.
name();
254 context->
mask = code.second;
256 context->
flag = nodes.empty() ? 0 : 1;
257 if ( context->
flag ) {
260 for (std::size_t i = nodes.size(); i > 1; --i) {
261 TGeoMatrix* m = nodes[i-1]->GetMatrix();
266 print_node(sd, parent, e, n, code, nodes);
268 m_entries.insert(code.first);
278 const TGeoNode* n,
const Encoding& code,
const Chain& nodes)
const
285 std::stringstream log;
286 log << m_entries.size() <<
": Detector: " << e.
path()
287 <<
" id:" << volumeID(code.first)
288 <<
" Nodes(" << int(nodes.size()) <<
"):" << ro.
idSpec().
str(code.first,code.second);
289 printout(m_debug ? INFO : DEBUG,
"VolumeManager",log.str().c_str());
294 log << m_entries.size() <<
": " << parent.
name()
295 <<
" ro:" << ro.
name() <<
" pv:" << n->GetName()
296 <<
" Sensitive:" << yes_no(sensitive);
297 printout(m_debug ? INFO : DEBUG,
"VolumeManager", log.str().c_str());
305 if ( 0 == flag )
return;
310 return element.placement();
316 return element.placement();
323 static TGeoHMatrix identity;
324 if ( 0 == flag )
return identity;
332 toElement().LocalToMaster(local, elt);
333 return { elt[0], elt[1], elt[2] };
339 local.GetCoordinates(loc);
340 return localToElement(loc);
346 toElement().LocalToMaster(local, elt);
347 return element.nominal().localToWorld(elt);
353 local.GetCoordinates(l);
354 return localToWorld(l);
359 return element.nominal().worldToLocal(world);
364 return element.nominal().worldToLocal(world);
369 element.nominal().worldToLocal(world, elt);
374 double elt[3], local[3];
375 worldToElement(world, elt);
376 toElement().MasterToLocal(elt, local);
377 return { local[0], local[1], local[2] };
383 world.GetCoordinates(global);
384 return worldToLocal(global);
390 worldToElement(world, elt);
391 toElement().MasterToLocal(elt, local);
396 printout(INFO,
"VolumeManager",
" - populating volume ids - be patient ..." );
397 std::size_t node_count = 0;
399 assign(obj_ptr, nam,
"VolumeManager");
404 obj_ptr->
top = obj_ptr;
405 obj_ptr->
flags = flags;
409 printout(INFO,
"VolumeManager",
" - populating volume ids - done. %ld nodes.",node_count);
417 assign(obj_ptr, sub_detector.
name(),
"VolumeManager");
422 description.
apply(
"DD4hepVolumeManager", 0, 0);
431 if (!
det.isValid()) {
432 throw std::runtime_error(
"dd4hep: VolumeManager::addSubdetector: Only valid subdetectors "
433 "are allowed. [Invalid DetElement]");
437 std::string det_name =
det.name();
440 throw std::runtime_error(
"dd4hep: VolumeManager::addSubdetector: Only subdetectors with a "
441 "valid readout descriptor are allowed. [Invalid DetElement:" + det_name +
"]");
445 throw std::runtime_error(
"dd4hep: VolumeManager::addSubdetector: Only subdetectors with a "
446 "valid placement are allowed. [Invalid DetElement:" + det_name +
"]");
449 if (vit == pv.
volIDs().end()) {
450 throw std::runtime_error(
"dd4hep: VolumeManager::addSubdetector: Only subdetectors with "
451 "valid placement VolIDs are allowed. [Invalid DetElement:" + det_name +
"]");
455 const auto&
id = (*vit);
459 throw std::runtime_error(
"dd4hep: VolumeManager::addSubdetector: IdDescriptor of " +
460 std::string(
det.name()) +
" has no field " +
id.first);
466 mo.
sysID =
id.second;
470 &mo,&Object::update);
474 throw std::runtime_error(
"dd4hep: VolumeManager::addSubdetector: "
475 "Failed to add subdetector section. [Invalid Manager Handle]");
481 const Object& o = _data();
484 const Object& mo = j.second._data();
486 if ( sys_id == mo.
sysID )
489 throw std::runtime_error(
"dd4hep: VolumeManager::subdetector(VolID): "
490 "Attempt to access unknown subdetector section.");
492 throw std::runtime_error(
"dd4hep: VolumeManager::subdetector(VolID): "
493 "Cannot assign ID descriptor [Invalid Manager Handle]");
499 return _data().detector;
501 throw std::runtime_error(
"dd4hep: VolumeManager::detector: Cannot access DetElement [Invalid Handle]");
511 std::stringstream err;
518 if ( (vid&mask) != vid ) {
519 err <<
"Bad context mask:" << (
void*)mask
520 <<
" id:" << (
void*)vid
521 <<
" pv:" << pv.
name()
530 err <<
"Inserted new volume:" << std::setw(6) << std::left << o.
volumes.size()
531 <<
" Ptr:" << (
void*) pv.
ptr()
532 <<
" [" << pv.
name() <<
"]"
533 <<
" id:" << std::setw(16) << std::hex << std::right << std::setfill(
'0') << vid << std::dec << std::setfill(
' ')
534 <<
" mask:" << std::setw(16) << std::hex << std::right << std::setfill(
'0') << mask << std::dec << std::setfill(
' ')
535 <<
" Det:" << std::setw(4) << std::hex << std::right << std::setfill(
'0') << context->
element.
volumeID()
536 <<
" / " << std::setw(4) << sys_id << std::dec << std::setfill(
' ') <<
": " << context->
element.
path();
537 printout(VERBOSE,
"VolumeManager", err.str().c_str());
541 err <<
"+++ Attempt to register duplicate"
542 <<
" id:" << std::setw(16) << std::hex << std::right << std::setfill(
'0') << vid << std::dec << std::setfill(
' ')
543 <<
" mask:" << std::setw(16) << std::hex << std::right << std::setfill(
'0') << mask << std::dec << std::setfill(
' ')
545 <<
" ptr:" << (
void*) pv.
ptr()
546 <<
" Name:" << pv.
name()
549 printout(ERROR,
"VolumeManager",
"%s", err.str().c_str());
551 context = (*i).second;
553 err <<
" !!!!! +++ Clashing"
554 <<
" id:" << std::setw(16) << std::hex << std::right << std::setfill(
'0') << vid << std::dec << std::setfill(
' ')
555 <<
" mask:" << std::setw(16) << std::hex << std::right << std::setfill(
'0') << mask << std::dec << std::setfill(
' ')
557 <<
" ptr:" << (
void*) pv.
ptr()
558 <<
" Name:" << pv.
name()
562 printout(ERROR,
"VolumeManager",
"%s", err.str().c_str());
569 std::stringstream err;
573 if ( (o.
flags & ONE) == ONE ) {
577 if ( (o.
flags & TREE) == TREE ) {
578 bool isTop = ptr() == o.
top;
581 if ( sys_id == o.
sysID ) {
582 return adoptPlacement(sys_id, context);
588 Object& mgr = j.second._data();
590 if ( j.first == sid ) {
591 return j.second.adoptPlacement(sid, context);
597 except(
"VolumeManager",
"dd4hep: Failed to add new physical volume to detector: %s "
600 except(
"VolumeManager",
"dd4hep: Failed to add new physical volume [Invalid Manager Handle]");
608 const Object& o = _data();
609 bool is_top = o.
top == ptr();
610 bool one_tree = (o.
flags & ONE) == ONE;
611 if ( !is_top && one_tree ) {
622 if ((c = j.second._data().search(
id)) != 0)
626 except(
"VolumeManager",
"lookupContext: Failed to search Volume context %016llX [Unknown identifier]", (
void*)volume_id);
628 except(
"VolumeManager",
"lookupContext: Failed to search Volume context [Invalid Manager Handle]");
647 const Object& o = _data();
654 if ( j.second->system ) {
655 VolumeID vid = volume_id&j.second->system->mask();
656 if ( (volume_id&j.second->sysID) == vid ) {
657 sys_id = j.second->sysID;
663 VolumeID det_id = (volume_id&sys_id);
667 except(
"VolumeManager",
"lookupContext: Failed to search Volume context [Invalid Manager Handle]");
691 bool isTop = top == &o;
694 std::string prefix(isTop ?
"" :
"++ ");
695 os << prefix << (isTop ?
"TOP Level " :
"Secondary ") <<
"Volume manager:"
702 for (
const auto& i : o.
volumes ) {
705 <<
"Element:" << std::setw(32) << std::left << c->
element.
path()
707 <<
" id:" << std::setw(18) << std::left << (
void*) c->
identifier
708 <<
" mask:" << std::setw(18) << std::left << (
void*) c->
mask
712 os << prefix << i.second << std::endl;
729 printout(DEBUG,
"VolumeManager",
"+++ Conditions update %s param:%p",
det.path().c_str(),param);
731 printout(DEBUG,
"VolumeManager",
"+++ Alignment update %s param:%p",
det.path().c_str(),param);
734 printout(DEBUG,
"VolumeManager",
"+++ Alignment update %s",i.second->elementPlacement().name());
740 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.
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.
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.