27 using namespace DD4hep;
28 using namespace DD4hep::Geometry;
34 typedef vector<TGeoNode*> Chain;
35 typedef pair<VolumeID, VolumeID> Encoding;
41 set<VolumeID> m_entries;
44 : m_lcdd(lcdd), m_volManager(vm) {
52 if ( e->flag&DetElement::Object::HAVE_SENSITIVE_DETECTOR ) {
53 parent_sd = m_lcdd.sensitiveDetector(e.
name());
56 for (DetElement::Children::const_iterator i = c.begin(); i != c.end(); ++i) {
65 Encoding coding(0, 0);
66 scanPhysicalVolume(de, de, pv, coding, sd, chain);
70 scanPhysicalVolume(de, de, pv, ids, sd, chain);
72 Encoding coding(0, 0);
73 scanPhysicalVolume(de, de, pv, coding, sd, chain);
77 printout(
WARNING,
"VolumeManager",
"++ Detector element %s of type %s has no placement.",
86 for (DetElement::Children::const_iterator i = c.begin(); i != c.end(); ++i) {
91 for (DetElement::Children::const_iterator i = c.begin(); i != c.end(); ++i) {
100 Encoding parent_encoding,
103 TGeoNode* node = pv.
ptr();
107 const VolIDs& pv_ids = pv.
volIDs();
108 Encoding vol_encoding = parent_encoding;
110 bool have_encoding = pv_ids.empty();
111 bool compound = e.
type() ==
"compound";
115 vol_encoding = Encoding();
120 else if ( (parent->flag&DetElement::Object::HAVE_SENSITIVE_DETECTOR) )
121 sd = m_lcdd.sensitiveDetector(parent.
name());
122 else if ( (e->flag&DetElement::Object::HAVE_SENSITIVE_DETECTOR) )
123 sd = m_lcdd.sensitiveDetector(e.
name());
125 chain.push_back(node);
126 if ( sd.
isValid() && !pv_ids.empty() ) {
129 vol_encoding = update_encoding(ro.
idSpec(), pv_ids, parent_encoding);
130 have_encoding =
true;
134 "%s: Strange constellation volume %s is sensitive, but has no readout! sd:%p",
138 for (Int_t idau = 0, ndau = node->GetNdaughters(); idau < ndau; ++idau) {
139 TGeoNode* daughter = node->GetDaughter(idau);
141 if ( placement.data() ) {
146 count += scanPhysicalVolume(parent, de_dau, pv_dau, vol_encoding, sd, dau_chain);
149 count += scanPhysicalVolume(parent, e, pv_dau, vol_encoding, sd, chain);
154 "Invalid not instrumented placement:"+
string(daughter->GetName())+
155 " [Internal error -- bad detector constructor]");
161 if ( e.
path().find(
"/world/EcalBarrel") == 0 ) {
165 if ( !have_encoding ) {
166 printout(
ERROR,
"VolumeManager",
"%s: Missing SD encoding. Volume manager won't work!",
169 bool add_det_vol_id = (is_sensitive || count > 0) && node == e.
placement().
ptr();
170 if ( add_det_vol_id ) {
179 have_encoding ?
"RECUPERATED" :
"REGULAR", sd.
name(),
180 (
void*)vol_encoding.first, (
void*)vol_encoding.second);
183 if ( is_sensitive || add_det_vol_id ) {
184 add_entry(sd, parent, e, node, vol_encoding, chain);
196 TGeoNode* node = pv.
ptr();
200 chain.push_back(node);
201 VolIDs pv_ids = pv.
volIDs();
202 ids.VolIDs::Base::insert(ids.end(), pv_ids.begin(), pv_ids.end());
203 bool got_readout =
false;
209 add_entry(sd, parent, e, node, ids, chain);
214 "%s: Strange constellation volume %s is sensitive, but has no readout! sd:%p",
218 for (Int_t idau = 0, ndau = node->GetNdaughters(); idau < ndau; ++idau) {
219 TGeoNode* daughter = node->GetDaughter(idau);
221 if ( placement.data() ) {
227 cnt = scanPhysicalVolume(parent, de_dau, pv_dau, ids, sd, dau_chain);
230 cnt = scanPhysicalVolume(parent, e, pv_dau, ids, sd, chain);
233 if ( count == 0 && cnt > 0 && sd.
isValid() && !pv_ids.empty()) {
234 add_entry(sd, parent, e, node, ids, chain);
239 throw runtime_error(
"Invalid not instrumented placement:"+
string(daughter->GetName())+
240 " [Internal error -- bad detector constructor]");
246 else if ( count > 0 && sd.
isValid() ) {
253 Encoding det_encoding = encoding(iddesc,ids);
255 got_readout ?
"RECUPERATED" :
"REGULAR", sd.
name(),
256 (
void*)det_encoding.first, (
void*)det_encoding.second);
266 static Encoding update_encoding(
const IDDescriptor iddesc,
const VolIDs& ids,
const Encoding& initial) {
267 VolumeID volume_id = initial.first, mask = initial.second;
268 for (VolIDs::const_iterator i = ids.begin(); i != ids.end(); ++i) {
272 int offset = f->offset();
273 volume_id |= ((f->value(
id.
second << offset) << offset)&msk);
276 return make_pair(volume_id, mask);
279 static Encoding encoding(
const IDDescriptor iddesc,
const VolIDs& ids) {
281 for (VolIDs::const_iterator i = ids.begin(); i != ids.end(); ++i) {
285 int off = f->offset();
286 volume_id |= ((f->value(
id.
second<<off)<<off)&msk);
289 return make_pair(volume_id, mask);
293 const TGeoNode* n,
const Encoding& code, Chain& nodes)
296 if (m_entries.find(code.first) == m_entries.end()) {
298 string sd_name = sd.
name();
299 DetElement sub_detector = m_lcdd.detector(sd_name);
304 context->
mask = code.second;
309 context->
path = nodes;
310 for (
size_t i = nodes.size(); i > 1; --i) {
311 TGeoMatrix*
m = nodes[i - 1]->GetMatrix();
312 context->
toWorld.MultiplyLeft(m);
315 context->
toDetector.MultiplyLeft(nodes[0]->GetMatrix());
318 print_node(sd, parent, e, n, code, nodes);
320 m_entries.insert(code.first);
326 const TGeoNode* n,
const VolIDs& ids, Chain& nodes)
331 Encoding code = encoding(iddesc, ids);
333 if (m_entries.find(code.first) == m_entries.end()) {
334 string sd_name = sd.
name();
335 DetElement sub_detector = m_lcdd.detector(sd_name);
340 context->
mask = code.second;
344 context->
volID = ids;
345 context->
path = nodes;
346 for (
size_t i = nodes.size(); i > 1; --i) {
347 TGeoMatrix* m = nodes[i - 1]->GetMatrix();
348 context->
toWorld.MultiplyLeft(m);
351 context->
toDetector.MultiplyLeft(nodes[0]->GetMatrix());
354 print_node(sd, parent, e, n, ids, nodes);
356 m_entries.insert(code.first);
362 const TGeoNode* n,
const VolIDs& ids,
const Chain& )
const
364 static int s_count = 0;
369 Encoding code = encoding(en, ids);
375 log << s_count <<
": " << parent.
name() <<
": " << e.
name()
376 <<
" ro:" << ro.
ptr() <<
" pv:" << n->GetName() <<
" id:"
377 << (
void*) volume_id <<
" : ";
378 for (VolIDs::const_iterator i = ids.begin(); i != ids.end(); ++i) {
381 VolumeID value = f->value(volume_id);
382 log <<
id.first <<
"=" <<
id.second <<
"," << value
383 <<
" [" << f->offset() <<
"," << f->width() <<
"] ";
385 log <<
" Sensitive:" <<
yes_no(sensitive);
389 log << s_count <<
": " << e.
name() <<
" Detector GeoNodes:";
390 for(vector<const TGeoNode*>::const_iterator j=nodes.begin(); j!=nodes.end();++j)
391 log << (
void*)(*j) <<
" ";
396 const TGeoNode* n,
const Encoding& code,
const Chain& )
const
398 static int s_count = 0;
407 log << s_count <<
": " << parent.
name() <<
": " << e.
name()
408 <<
" ro:" << ro.
ptr() <<
" pv:" << n->GetName() <<
" id:"
409 << (
void*) volume_id <<
" Sensitive:" <<
yes_no(sensitive);
413 log << s_count <<
": " << e.
name() <<
" Detector GeoNodes:";
414 for(vector<const TGeoNode*>::const_iterator j=nodes.begin(); j!=nodes.end();++j)
415 log << (
void*)(*j) <<
" ";
424 printout(
INFO,
"VolumeManager",
" - populating volume ids - be patient ..." );
426 assign(obj_ptr, nam,
"VolumeManager");
428 Populator p(lcdd, *
this);
431 obj_ptr->
top = obj_ptr;
432 obj_ptr->
flags = flags;
435 printout(
INFO,
"VolumeManager",
" - populating volume ids - done" );
443 assign(obj_ptr, sub_detector.
name(),
"VolumeManager");
451 throw runtime_error(
"DD4hep: VolumeManager::addSubdetector: Only valid subdetectors "
452 "are allowed. [Invalid DetElement]");
456 string det_name = det.
name();
459 throw runtime_error(
"DD4hep: VolumeManager::addSubdetector: Only subdetectors with a "
460 "valid readout descriptor are allowed. [Invalid DetElement:" + det_name +
"]");
464 throw runtime_error(
"DD4hep: VolumeManager::addSubdetector: Only subdetectors with a "
465 "valid placement are allowed. [Invalid DetElement:" + det_name +
"]");
467 VolIDs::Base::const_iterator vit = pv.
volIDs().
find(
"system");
468 if (vit == pv.
volIDs().end()) {
469 throw runtime_error(
"DD4hep: VolumeManager::addSubdetector: Only subdetectors with "
470 "valid placement VolIDs are allowed. [Invalid DetElement:" + det_name +
"]");
478 throw runtime_error(
"DD4hep: VolumeManager::addSubdetector: IdDescriptor of " +
479 string(det.
name()) +
" has no field " +
id.first);
485 mo.
sysID =
id.second;
488 det.
callAtUpdate(DetElement::PLACEMENT_CHANGED|DetElement::PLACEMENT_DETECTOR,
489 &mo,&Object::update);
493 throw runtime_error(
"DD4hep: VolumeManager::addSubdetector: "
494 "Failed to add subdetector section. [Invalid Manager Handle]");
503 const Object& mo = (*j).second._data();
506 if (sys_id == mo.
sysID)
509 throw runtime_error(
"DD4hep: VolumeManager::subdetector(VolID): "
510 "Attempt to access unknown subdetector section.");
512 throw runtime_error(
"DD4hep: VolumeManager::subdetector(VolID): "
513 "Cannot assign ID descriptor [Invalid Manager Handle]");
519 return _data().detector;
521 throw runtime_error(
"DD4hep: VolumeManager::detector: Cannot access DetElement [Invalid Handle]");
535 Volumes::iterator i = o.
volumes.find(vid);
538 err <<
"Bad context mask:" << (
void*)context->
mask <<
" id:" << (
void*)context->
identifier
539 <<
" pv:" << pv.
name() <<
" Sensitive:"
547 err <<
"Inserted new volume:" << setw(6) << left << o.
volumes.size() <<
" Ptr:" << (
void*) pv.
ptr() <<
" ["
548 << pv.
name() <<
"]" <<
" ID:" << (
void*) context->
identifier <<
" Mask:" << (
void*) context->
mask;
552 err <<
"+++ Attempt to register duplicate volID " << (
void*) context->
identifier
553 <<
" Mask:" << (
void*) context->
mask
555 <<
" ptr:" << (
void*) pv.
ptr()
556 <<
" Name:" << pv.
name()
560 err <<
" !!!!! ++++ VolIDS ";
562 for (VolIDs::Base::const_iterator vit = id_vector.begin(); vit != id_vector.end(); ++vit)
563 err << (*vit).first <<
"=" << (*vit).second <<
"; ";
566 context = (*i).second;
568 err <<
" !!!!! +++ Clashing volID " << (
void*) context->
identifier
569 <<
" Mask:" << (
void*) context->
mask
571 <<
" ptr:" << (
void*) pv.
ptr()
572 <<
" Name:" << pv.
name()
579 err <<
" !!!!! ++++ VolIDS ";
581 for (VolIDs::Base::const_iterator vit = ids.begin(); vit != ids.end(); ++vit)
582 err << (*vit).first <<
"=" << (*vit).second <<
"; ";
590 bool VolumeManager::adoptPlacement(
Context* context) {
595 if ((o.
flags & ONE) == ONE) {
599 if ((o.
flags & TREE) == TREE) {
600 bool isTop = ptr() == o.
top;
603 if (sys_id == o.
sysID) {
604 return adoptPlacement(sys_id, context);
609 for (Managers::iterator j = o.
managers.begin(); j != o.
managers.end(); ++j) {
610 Object& m = (*j).second._data();
612 if ((*j).first == sid) {
613 return (*j).second.adoptPlacement(sid, context);
619 err <<
"Failed to add new physical volume to detector:" << o.
detector.
name() <<
" [Invalid Context]";
622 err <<
"Failed to add new physical volume [Invalid Manager Handle]";
624 Fail:
throw runtime_error(
"DD4hep: " + err.str());
633 bool is_top = o.
top == ptr();
634 bool one_tree = (o.
flags & ONE) == ONE;
635 if (!is_top && one_tree) {
646 if ((c = (*j).second._data().search(
id)) != 0)
651 err <<
"VolumeManager::lookupContext: Failed to search Volume context [Unknown identifier]"
652 << (
void*) volume_id;
653 throw runtime_error(
"DD4hep: " + err.str());
655 throw runtime_error(
"DD4hep: VolumeManager::lookupContext: "
656 "Failed to search Volume context [Invalid Manager Handle]");
661 Context* c = lookupContext(volume_id);
667 Context* c = lookupContext(volume_id);
673 Context* c = lookupContext(volume_id);
678 const TGeoMatrix& VolumeManager::worldTransformation(
VolumeID volume_id)
const {
679 Context* c = lookupContext(volume_id);
687 bool isTop = top == &o;
690 string prefix(isTop ?
"" :
"++ ");
691 os << prefix << (isTop ?
"TOP Level " :
"Secondary ") <<
"Volume manager:"
698 for (VolumeManager::Volumes::const_iterator i = o.
volumes.begin(); i != o.
volumes.end(); ++i) {
701 os << prefix <<
"PV:" << setw(32) << left << pv.
name()
702 <<
" id:" << setw(18) << left << (
void*) c->
identifier <<
" mask:"
703 << setw(18) << left << (
void*) c->
mask << endl;
705 for (VolumeManager::Managers::const_iterator i = o.
managers.begin(); i != o.
managers.end(); ++i)
706 os << prefix << (*i).second << endl;
Handle class to hold the information of a sensitive detector.
Ref_t sensitiveDetector() const
Access to the handle to the sensitive detector.
VolumeManager addSubdetector(DetElement detector, Readout ro)
Add a new Volume manager section according to a new subdetector.
bool adoptPlacement(Context *context)
Register physical volume with the manager (normally: section manager)
VolIDs volID
Volume IDS corresponding to this element.
Handle class holding a placed volume (also called physical volume)
Volume volume() const
Logical volume of this placement.
Detectors subdetectors
The container of subdetector elements.
const VolIDs & volIDs() const
Access to the volume IDs.
TGeoHMatrix toDetector
The transformation of space-points to the corrdinate system of the closests detector element...
DetElement element
Handle to the closest Detector element.
const char * name() const
Access the object name (or "" if not supported by the object)
bool isValid() const
Check the validity of the object held by the handle.
Volumes volumes
The container of placements managed by this instance.
Handle< T > & clear()
Release the object held by the handle.
VolumeID sysID
System identifier.
std::string toString() const
Access string representation.
Q * data() const
Access to an unrelated object type.
VolumeManagerObject * top
The reference to the TOP level VolumeManager.
PlacedVolume placement
The placement.
const char * yes_no(bool value)
Helper function to print booleans in format YES/NO.
Object & _data() const
Additional data accessor.
TGeoHMatrix toWorld
The transformation of space-points to the world corrdinate system.
VolumeID mask
Ignore mask of the placement identifier.
void callAtUpdate(unsigned int typ, Q *pointer, void(T::*pmf)(unsigned long typ, DetElement &det, void *opt_par)) const
Extend the detector element with an arbitrary callback.
This structure describes the cached data for one placement held by the volume manager.
const Children & children() const
Access to the list of children.
std::string type() const
Access detector type (structure, tracker, calorimeter, etc.).
DetElement detector
The Detector element handle managed by this instance.
int except(const std::string &src, const std::string &fmt,...)
Calls the display action with ERROR and throws an std::runtime_error exception.
Handle to the implementation of the readout structure of a subdetector.
T * ptr() const
Access to the held object.
std::ostream & operator<<(std::ostream &os, const VolumeManager &m)
Enable printouts for debugging.
DD4hep::Geometry::DetElement DetElement
Field system
The system field descriptor.
Context * search(const VolumeID &id) const
Search the locally cached volumes for a matching ID.
Handle class holding a placed volume (also called physical volume)
Volume::Object * _data(const Volume &v, bool throw_exception=true)
Accessor to the data part of the Volume.
VolumeID detMask
Sub-detector mask.
This structure describes the internal data of the volume manager object.
Field field(const std::string &field_name) const
Get the field descriptor of one field by name.
VolumeID identifier
Placement identifier.
IDDescriptor idSpec() const
Access IDDescription structure.
Q & object() const
Access to an unrelated object type.
DD4hep::Geometry::SensitiveDetector SensitiveDetector
const std::string & path() const
Path of the detector element (not necessarily identical to placement path!)
PlacedVolume placement() const
Access to the physical volume of this detector element.
Handle< NamedObject > Ref_t
Default Ref_t definition describing named objects.
Context * lookupContext(VolumeID volume_id) const
Lookup the context, which belongs to a registered physical volume.
Handle class describing a detector element.
Class to support the retrieval of detector elements and volumes given a valid identifier.
std::vector< VolID > Base
std::vector< VolID >::const_iterator find(const std::string &name) const
Find entry.
Path path
Path of placements to this sensitive volume.
Readout readout() const
Access readout structure of the sensitive detector.
DetElement detector
Handle to the subdetector element handle.
DD4hep::VolumeID VolumeID
The main interface to the DD4hep detector description package.
static const double second
std::map< std::string, DetElement > Children
Data class with properties of a detector element.
int printout(PrintLevel severity, const char *src, const char *fmt,...)
Calls the display action with a given severity level.
Managers managers
The volume managers for the individual subdetector elements.
IDDescriptor id
The ID descriptor object.
int flags
Population flags.
Class implementing the ID encoding of detector response.
const TGeoHMatrix & worldTransformation() const
Set detector element for reference transformations. Will delete existing reference trafo...
Geometry::IDDescriptor IDDescriptor
bool isSensitive() const
Accessor if volume is sensitive (ie. is attached to a sensitive detector)