26 #include <G4VTouchable.hh>
27 #include <G4LogicalVolume.hh>
28 #include <G4VPhysicalVolume.hh>
39 #ifdef VOLMGR_HAVE_DEBUG_INFO
45 class Geant4GeometryInfo::DebugInfo {
47 typedef std::vector<const G4VPhysicalVolume*> Geant4PlacementPath;
48 std::map<Geant4PlacementPath, Placement>
g4Paths;
58 using VolIDDescriptor = std::pair<VolumeID,std::vector<std::pair<const BitFieldElement*, VolumeID> > >;
70 typedef std::vector<const TGeoNode*> Chain;
72 typedef std::set<VolumeID> Registries;
81 bool m_debug {
false };
85 : m_detDesc(description), m_geo(g), m_debug(dbg)
87 #ifdef VOLMGR_HAVE_DEBUG_INFO
89 g.
g4DebugInfo =
new Geant4GeometryInfo::DebugInfo();
95 #ifdef VOLMGR_HAVE_DEBUG_INFO
108 for(
const auto& i : children ) {
117 scanPhysicalVolume(pv.
ptr(), std::move(ids), sd, chain);
120 printout(WARNING,
"Geant4VolumeManager",
121 "++ Detector element %s of type %s has no placement.",
126 if( pv.second->IsParameterised() )
128 if( pv.second->IsReplicated() )
140 chain.emplace_back(node);
141 ids.PlacedVolume::VolIDs::Base::insert(ids.end(), pv_ids.begin(), pv_ids.end());
145 add_entry(sd, node, ids, chain);
148 printout(WARNING,
"Geant4VolumeManager",
149 "populate: Strange constellation volume %s is sensitive, but has no readout! sd:%p", pv.
volume().
name(),
153 for( Int_t idau = 0, ndau = node->GetNdaughters(); idau < ndau; ++idau ) {
154 TGeoNode* daughter = node->GetDaughter(idau);
156 if( placement.
data() ) {
157 scanPhysicalVolume(daughter, ids, sd, chain);
169 PrintLevel print_level = m_debug ? ALWAYS : m_geo.
printLevel;
170 PrintLevel print_action = print_level;
171 PrintLevel print_chain = print_level;
172 PrintLevel print_res = print_level;
173 bool print_nodes =
false;
175 Registries::const_iterator i = m_entries.find(code);
177 printout(print_action,
"Geant4VolumeManager",
"+++ Add path:%s vid:%016X",
180 if( i == m_entries.end() ) {
181 path.reserve(nodes.size());
182 for( Chain::const_reverse_iterator k = nodes.rbegin(), kend=nodes.rend(); k != kend; ++k ) {
183 const TGeoNode* node = *(k);
186 G4VPhysicalVolume* phys = g4pit->second;
187 if( phys->IsParameterised() ) {
194 path.emplace_back(phys);
195 printout(print_chain,
"Geant4VolumeManager",
196 "+++ Chain: Node OK: %s [%s]", node->GetName(), phys->GetName().c_str());
199 control.insert(control.begin(),node);
200 vol =
Volume(node->GetVolume());
203 for(
const auto& imp : iVolImp->second ) {
204 const auto& c = imp.first;
205 if ( c.size() <= control.size() && control == c ) {
206 path.emplace_back(imp.second);
207 printout(print_chain,
"Geant4VolumeManager",
"+++ Chain: Node OK: %s %s -> %s",
209 imp.second->GetName().c_str());
216 if ( control.empty() ) {
217 printout(print_res,
"Geant4VolumeManager",
"+++ Volume IDs:%s",
219 path.erase(path.begin()+path.size()-1);
220 printout(print_res,
"Geant4VolumeManager",
"+++ Map %016X to Geant4 Path:%s",
222 auto hash = detail::hash64(&path[0], path.size()*
sizeof(path[0]));
224 #ifdef VOLMGR_HAVE_DEBUG_INFO
227 if ( missing_real_path != missing_hash_path ) {
230 if ( !nodes.empty() )
234 if ( missing_real_path ) {
242 if ( missing_hash_path ) {
247 m_entries.emplace(code);
251 if ( !path.empty() && (path.front()->IsParameterised() || path.front()->IsReplicated()) ) {
254 printout(ERROR,
"Geant4VolumeManager",
"populate: Severe error: Duplicated Geant4 path!!!! %s %s",
258 printout(INFO,
"Geant4VolumeManager",
"Control block has still %d entries:%s",
265 if ( !path.empty() && (path.front()->IsParameterised() || path.front()->IsReplicated()) ) {
269 printout(ERROR,
"Geant4VolumeManager",
"populate: Severe error: Duplicated Volume entry: 0x%X"
270 " [THIS SHOULD NEVER HAPPEN]", code);
273 if ( i != m_entries.end() )
277 if ( !nodes.empty() ) {
280 std::string node_path;
281 for( std::size_t in=0; in<nodes.size(); ++in ) {
284 node_path += pv.
name();
285 printout( ALWAYS,
"Geant4VolumeManager",
" TGeo Node[%ld]: %s [%p] Volids: '%s'",
286 in, node_path.c_str(), (
void*)nodes[in], pv.
volIDs().
str().c_str() );
291 throw std::runtime_error(
"Failed to populate Geant4 volume manager!");
300 if( !
info->has_volmgr ) {
302 p.populate(description.
world());
303 info->has_volmgr =
true;
307 except(
"Geant4VolumeManager",
"Attempt populate from invalid Geant4 geometry info [Invalid-Info]");
311 std::vector<const G4VPhysicalVolume*>
320 except(
"Geant4VolumeManager",
"Attempt to use invalid Geant4 volume manager [Invalid-Handle]");
323 except(
"Geant4VolumeManager",
"Attempt to use invalid Geant4 geometry info [Invalid-Info]");
331 auto* p = mgr->
ptr();
333 ::snprintf(text,
sizeof(text),
"==> #path entries: %ld valid: %s has_volmgr: %s",
334 p->g4Paths.size(), yes_no(p->valid), yes_no(p->has_volmgr));
337 return {
"Invalid handle to Geant4GeometryInfo" };
344 std::vector<const G4VPhysicalVolume*> path = handler.
placementPath();
346 printout(INFO,
"Geant4VolumeManager",
"+++ INVALID Geant4VolumeManager handle.");
350 printout(INFO,
"Geant4VolumeManager",
"+++ INVALID Geant4VolumeManager [Not initialized]");
353 else if( path.empty() ) {
354 printout(INFO,
"Geant4VolumeManager",
"+++ EMPTY volume Geant4 Path: %s",
359 uint64_t
hash = detail::hash64(&path[0],
sizeof(path[0])*path.size());
360 auto i =
ptr()->g4Paths.find(
hash);
361 if( i !=
ptr()->g4Paths.end() ) {
362 const auto& e = (*i).second;
368 const auto& paramterised =
ptr()->g4Parameterised;
369 const auto& replicated =
ptr()->g4Replicated;
371 for( std::size_t j=0; j < path.size(); ++j ) {
372 const auto* phys = path[j];
373 if( phys->IsParameterised() ) {
374 int copy_no = touchable->GetCopyNumber(j);
375 const auto it = paramterised.find(phys);
376 if( it != paramterised.end() ) {
379 const auto* field = (*it).second.data()->params->field;
383 except(
"Geant4VolumeManager",
384 "Error Geant4VolumeManager::volumeID(const G4VTouchable* touchable)");
386 else if( phys->IsReplicated() ) {
387 int copy_no = touchable->GetCopyNumber(j);
388 const auto it = replicated.find(phys);
389 if( it != replicated.end() ) {
390 const auto* field = (*it).second.data()->params->field;
394 except(
"Geant4VolumeManager",
395 "Error Geant4VolumeManager::volumeID(const G4VTouchable* touchable)");
401 printout(INFO,
"Geant4VolumeManager",
"+++ Bad Geant4 volume path: \'%s\' [invalid path] %s",
405 else if( !path[0]->GetLogicalVolume()->GetSensitiveDetector() ) {
406 printout(DEBUG,
"Geant4VolumeManager",
"+++ Bad Geant4 volume path: \'%s\' [insensitive] %s",
410 printout(INFO,
"Geant4VolumeManager",
411 "+++ Bad Geant4 volume path: \'%s\' [missing entry] %s",
415 printout(INFO,
"Geant4VolumeManager",
"+++ Bad Geant4 volume path: \'%s\' %s",
424 vol_desc.second.clear();
427 auto hash = detail::hash64(&path[0],
sizeof(path[0])*path.size());
428 auto i =
ptr()->g4Paths.find(
hash);
429 if( i !=
ptr()->g4Paths.end() ) {
430 VolumeID vid = (*i).second.volumeID;
431 G4LogicalVolume* lvol = path[0]->GetLogicalVolume();
432 if( lvol->GetSensitiveDetector() ) {
433 const auto* node = path[0];
434 const auto& pm =
ptr()->g4Placements;
435 for(
const auto& ipm : pm ) {
436 if ( ipm.second == node ) {
440 vol_desc.first = vid;
451 else if( !path[0]->GetLogicalVolume()->GetSensitiveDetector() )