25 #include "G4VTouchable.hh"
26 #include "G4LogicalVolume.hh"
27 #include "G4VPhysicalVolume.hh"
32 using namespace DD4hep::Simulation;
33 using namespace DD4hep::Simulation::Geant4GeometryMaps;
34 using namespace DD4hep::Geometry;
35 using namespace DD4hep;
44 typedef vector<const TGeoNode*> Chain;
48 typedef map<VolumeID,Geant4PlacementPath> Registries;
58 : m_lcdd(lcdd), m_geo(g) {
64 for (DetElement::Children::const_iterator i = c.begin(); i != c.end(); ++i) {
72 chain.push_back(m_lcdd.world().placement().ptr());
73 scanPhysicalVolume(pv.
ptr(), ids, sd, chain);
76 printout(
WARNING,
"Geant4VolumeManager",
"++ Detector element %s of type %s has no placement.", de.
name(), de.
type().c_str());
86 chain.push_back(node);
87 ids.PlacedVolume::VolIDs::Base::insert(ids.end(), pv_ids.begin(), pv_ids.end());
91 add_entry(sd, node, ids, chain);
95 "populate: Strange constellation volume %s is sensitive, but has no readout! sd:%p", pv.
volume().
name(),
99 for (Int_t idau = 0, ndau = node->GetNdaughters(); idau < ndau; ++idau) {
100 TGeoNode* daughter = node->GetDaughter(idau);
102 if ( placement.data() ) {
103 scanPhysicalVolume(daughter, ids, sd, chain);
111 const TGeoNode* node;
117 Registries::const_iterator i = m_entries.find(code);
122 printout(print_action,
"Geant4VolumeManager",
"+++ Add path:%s vid:%016X",
125 if (i == m_entries.end()) {
126 path.reserve(nodes.size());
127 for (Chain::const_reverse_iterator k = nodes.rbegin(), kend=nodes.rend(); k != kend; ++k) {
129 PlacementMap::const_iterator g4pit = m_geo.g4Placements.find(node);
130 if (g4pit != m_geo.g4Placements.end()) {
131 path.push_back((*g4pit).second);
132 printout(print_chain,
"Geant4VolumeManager",
"+++ Chain: Node OK: %s [%s]",
133 node->GetName(), (*g4pit).second->GetName().c_str());
136 control.insert(control.begin(),node);
137 vol =
Volume(node->GetVolume());
138 VolumeImprintMap::const_iterator iVolImp = m_geo.g4VolumeImprints.find(vol);
139 if ( iVolImp != m_geo.g4VolumeImprints.end() ) {
140 const Imprints& imprints = (*iVolImp).second;
142 for(Imprints::const_iterator iImp=imprints.begin(); iImp != imprints.end(); ++iImp) {
144 if ( c.size() <= control.size() && control == c ) {
145 path.push_back((*iImp).second);
146 printout(print_chain,
"Geant4VolumeManager",
"+++ Chain: Node OK: %s %s -> %s",
148 (*iImp).second->GetName().c_str());
155 if ( control.empty() ) {
156 printout(print_res,
"Geant4VolumeManager",
"+++ Volume IDs:%s",
158 path.erase(path.begin()+path.size()-1);
159 printout(print_res,
"Geant4VolumeManager",
"+++ Map %016X to Geant4 Path:%s",
161 if (m_geo.g4Paths.find(path) == m_geo.g4Paths.end()) {
162 m_geo.g4Paths[path] = code;
163 m_entries.insert(make_pair(code,path));
166 printout(
ERROR,
"Geant4VolumeManager",
"populate: Severe error: Duplicated Geant4 path!!!! %s %s",
170 printout(
INFO,
"Geant4VolumeManager",
"Control block has still %d entries:%s",
174 printout(
ERROR,
"Geant4VolumeManager",
"populate: Severe error: Duplicated Volume entry: %X"
175 " [THIS SHOULD NEVER HAPPEN]", code);
178 if ( i != m_entries.end() )
182 if ( !nodes.empty() )
185 throw runtime_error(
"Failed to populate Geant4 volume manager!");
192 :
Base(info), m_isValid(false) {
194 Populator p(lcdd, *info);
195 p.populate(lcdd.
world());
198 throw runtime_error(
format(
"Geant4VolumeManager",
"Attempt populate from invalid Geant4 geometry info [Invalid-Info]"));
213 throw runtime_error(
format(
"Geant4VolumeManager",
"Attempt to use invalid Geant4 volume manager [Invalid-Handle]"));
215 else if (!
ptr()->valid) {
216 throw runtime_error(
format(
"Geant4VolumeManager",
"Attempt to use invalid Geant4 geometry info [Invalid-Info]"));
226 Geant4PathMap::const_iterator i = m.find(path);
231 else if (!path[0]->GetLogicalVolume()->GetSensitiveDetector())
234 printout(
INFO,
"Geant4VolumeManager",
"+++ Bad volume Geant4 Path: %s",
247 vol_desc.second.clear();
251 Geant4PathMap::const_iterator i = m.find(path);
254 G4LogicalVolume* lvol = path[0]->GetLogicalVolume();
255 if (lvol->GetSensitiveDetector()) {
256 const G4VPhysicalVolume* node = path[0];
258 for (PlacementMap::const_iterator ipm = pm.begin(); ipm != pm.end(); ++ipm) {
259 if ((*ipm).second == node) {
263 vol_desc.first = vid;
274 else if (!path[0]->GetLogicalVolume()->GetSensitiveDetector())
Handle class to hold the information of a sensitive detector.
static const VolumeID Insensitive
Ref_t sensitiveDetector() const
Access to the handle to the sensitive detector.
bool checkValidity() const
Check the validity of the information before accessing it.
std::vector< const TGeoNode * > VolumeChain
Handle class holding a placed volume (also called physical volume)
virtual DetElement world() const =0
Return reference to the top-most (world) detector element.
Volume volume() const
Logical volume of this placement.
const VolIDs & volIDs() const
Access to the volume IDs.
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.
VolumeID volumeID(const PlacementPath &path) const
Access CELLID by placement path.
std::map< Geant4PlacementPath, VolumeID > Geant4PathMap
bool m_isValid
Optimization flag to shortcut object checks.
std::vector< const G4VPhysicalVolume * > Geant4PlacementPath
std::vector< ImprintEntry > Imprints
const Children & children() const
Access to the list of children.
std::string type() const
Access detector type (structure, tracker, calorimeter, etc.).
void volumeDescriptor(const PlacementPath &path, VolIDDescriptor &volume_desc) const
Accessfully decoded volume fields by placement path.
Handle to the implementation of the readout structure of a subdetector.
T * ptr() const
Access to the held object.
DD4hep::Geometry::DetElement DetElement
Geant4GeometryMaps::Geant4PlacementPath PlacementPath
Handle class holding a placed volume (also called physical volume)
std::map< PlacedVolume, G4VPhysicalVolume * > PlacementMap
std::string format(const std::string &src, const std::string &fmt,...)
Build formatted string.
VolumeID encode(const std::vector< VolID > &ids) const
Encode a set of volume identifiers (corresponding to this description of course!) to a volumeID...
Helper class to ease the extraction of information from a G4Touchable object.
IDDescriptor idSpec() const
Access IDDescription structure.
static const VolumeID InvalidPath
std::pair< VolumeID, VolIDFields > VolIDDescriptor
PlacedVolume placement() const
Access to the physical volume of this detector element.
Geant4PlacementPath placementPath(bool exception=false) const
Helper: Generate placement path from touchable object.
Handle< NamedObject > Ref_t
Default Ref_t definition describing named objects.
Handle class describing a detector element.
Readout readout() const
Access readout structure of the sensitive detector.
Handle: a templated class like a shared pointer, which allows specialized access to tgeometry objects...
Geant4VolumeManager()
Default constructor.
The main interface to the DD4hep detector description package.
Concreate class holding the relation information between geant4 objects and dd4hep objects...
PlacementPath placementPath(const G4VTouchable *touchable, bool exception=true) const
Helper: Generate placement path from touchable object.
static const VolumeID NonExisting
std::map< std::string, DetElement > Children
void decodeFields(VolumeID vid, VolIDFields &fields)
Decode volume IDs and return filled descriptor with all fields.
int printout(PrintLevel severity, const char *src, const char *fmt,...)
Calls the display action with a given severity level.
Geant4GeometryMaps::Geant4PathMap g4Paths
Class implementing the ID encoding of detector response.
std::string placementPath(const Geant4PlacementPath &path, bool reverse=true)
Assemble Geant4 volume path.
bool isSensitive() const
Accessor if volume is sensitive (ie. is attached to a sensitive detector)