26 #include <G4VTouchable.hh>
27 #include <G4LogicalVolume.hh>
28 #include <G4VPhysicalVolume.hh>
35 #ifdef VOLMGR_HAVE_DEBUG_INFO
41 class Geant4GeometryInfo::DebugInfo {
43 typedef std::vector<const G4VPhysicalVolume*> Geant4PlacementPath;
44 std::map<Geant4PlacementPath, Placement>
g4Paths;
54 using VolIDDescriptor = std::pair<VolumeID,std::vector<std::pair<const BitFieldElement*, VolumeID> > >;
66 typedef std::vector<const TGeoNode*> Chain;
68 typedef std::set<VolumeID> Registries;
79 : m_detDesc(description), m_geo(g)
81 #ifdef VOLMGR_HAVE_DEBUG_INFO
83 g.
g4DebugInfo =
new Geant4GeometryInfo::DebugInfo();
89 #ifdef VOLMGR_HAVE_DEBUG_INFO
97 typedef std::pair<VolumeID, VolumeID>
Encoding;
101 for(
const auto&
id : ids ) {
106 volume_id |= ((f->
value(val << off) << off)&msk);
109 return std::make_pair(volume_id, mask);
116 for(
const auto& i : c ) {
125 scanPhysicalVolume(pv.
ptr(), std::move(ids), sd, chain);
128 printout(WARNING,
"Geant4VolumeManager",
129 "++ Detector element %s of type %s has no placement.",
134 if( pv.second->IsParameterised() )
136 if( pv.second->IsReplicated() )
148 chain.emplace_back(node);
149 ids.PlacedVolume::VolIDs::Base::insert(ids.end(), pv_ids.begin(), pv_ids.end());
153 add_entry(sd, node, ids, chain);
156 printout(WARNING,
"Geant4VolumeManager",
157 "populate: Strange constellation volume %s is sensitive, but has no readout! sd:%p", pv.
volume().
name(),
161 for( Int_t idau = 0, ndau = node->GetNdaughters(); idau < ndau; ++idau ) {
162 TGeoNode* daughter = node->GetDaughter(idau);
164 if( placement.
data() ) {
165 scanPhysicalVolume(daughter, ids, sd, chain);
178 PrintLevel print_action = print_level;
179 PrintLevel print_chain = print_level;
180 PrintLevel print_res = print_level;
182 Registries::const_iterator i = m_entries.find(code);
184 printout(print_action,
"Geant4VolumeManager",
"+++ Add path:%s vid:%016X",
187 if( i == m_entries.end() ) {
188 path.reserve(nodes.size());
189 for( Chain::const_reverse_iterator k = nodes.rbegin(), kend=nodes.rend(); k != kend; ++k ) {
190 const TGeoNode* node = *(k);
193 G4VPhysicalVolume* phys = g4pit->second;
194 if( phys->IsParameterised() ) {
201 path.emplace_back(phys);
202 printout(print_chain,
"Geant4VolumeManager",
203 "+++ Chain: Node OK: %s [%s]", node->GetName(), phys->GetName().c_str());
206 control.insert(control.begin(),node);
207 vol =
Volume(node->GetVolume());
210 for(
const auto& imp : iVolImp->second ) {
211 const auto& c = imp.first;
212 if ( c.size() <= control.size() && control == c ) {
213 path.emplace_back(imp.second);
214 printout(print_chain,
"Geant4VolumeManager",
"+++ Chain: Node OK: %s %s -> %s",
216 imp.second->GetName().c_str());
223 if ( control.empty() ) {
224 printout(print_res,
"Geant4VolumeManager",
"+++ Volume IDs:%s",
226 path.erase(path.begin()+path.size()-1);
227 printout(print_res,
"Geant4VolumeManager",
"+++ Map %016X to Geant4 Path:%s",
229 auto hash = detail::hash64(&path[0], path.size()*
sizeof(path[0]));
231 #ifdef VOLMGR_HAVE_DEBUG_INFO
234 if ( missing_real_path != missing_hash_path ) {
237 if ( !nodes.empty() )
241 if ( missing_real_path ) {
249 if ( missing_hash_path ) {
254 m_entries.emplace(code);
258 if ( !path.empty() && (path.front()->IsParameterised() || path.front()->IsReplicated()) ) {
261 printout(ERROR,
"Geant4VolumeManager",
"populate: Severe error: Duplicated Geant4 path!!!! %s %s",
265 printout(INFO,
"Geant4VolumeManager",
"Control block has still %d entries:%s",
271 if ( !path.empty() && (path.front()->IsParameterised() || path.front()->IsReplicated()) ) {
275 printout(ERROR,
"Geant4VolumeManager",
"populate: Severe error: Duplicated Volume entry: 0x%X"
276 " [THIS SHOULD NEVER HAPPEN]", code);
279 if ( i != m_entries.end() )
283 if ( !nodes.empty() )
286 throw std::runtime_error(
"Failed to populate Geant4 volume manager!");
295 if( !
info->has_volmgr ) {
296 Populator p(description, *
info);
297 p.populate(description.
world());
298 info->has_volmgr =
true;
302 except(
"Geant4VolumeManager",
"Attempt populate from invalid Geant4 geometry info [Invalid-Info]");
306 std::vector<const G4VPhysicalVolume*>
315 except(
"Geant4VolumeManager",
"Attempt to use invalid Geant4 volume manager [Invalid-Handle]");
318 except(
"Geant4VolumeManager",
"Attempt to use invalid Geant4 geometry info [Invalid-Info]");
326 auto* p = mgr->
ptr();
328 ::snprintf(text,
sizeof(text),
"==> #path entries: %ld valid: %s has_volmgr: %s",
329 p->g4Paths.size(), yes_no(p->valid), yes_no(p->has_volmgr));
332 return {
"Invalid handle to Geant4GeometryInfo" };
339 std::vector<const G4VPhysicalVolume*> path = handler.
placementPath();
341 printout(INFO,
"Geant4VolumeManager",
"+++ INVALID Geant4VolumeManager handle.");
345 printout(INFO,
"Geant4VolumeManager",
"+++ INVALID Geant4VolumeManager [Not initialized]");
348 else if( path.empty() ) {
349 printout(INFO,
"Geant4VolumeManager",
"+++ EMPTY volume Geant4 Path: %s",
354 uint64_t
hash = detail::hash64(&path[0],
sizeof(path[0])*path.size());
355 auto i =
ptr()->g4Paths.find(
hash);
356 if( i !=
ptr()->g4Paths.end() ) {
357 const auto& e = (*i).second;
363 const auto& paramterised =
ptr()->g4Parameterised;
364 const auto& replicated =
ptr()->g4Replicated;
366 for( std::size_t j=0; j < path.size(); ++j ) {
367 const auto* phys = path[j];
368 if( phys->IsParameterised() ) {
369 int copy_no = touchable->GetCopyNumber(j);
370 const auto it = paramterised.find(phys);
371 if( it != paramterised.end() ) {
374 const auto* field = (*it).second.data()->params->field;
378 except(
"Geant4VolumeManager",
379 "Error Geant4VolumeManager::volumeID(const G4VTouchable* touchable)");
381 else if( phys->IsReplicated() ) {
382 int copy_no = touchable->GetCopyNumber(j);
383 const auto it = replicated.find(phys);
384 if( it != replicated.end() ) {
385 const auto* field = (*it).second.data()->params->field;
389 except(
"Geant4VolumeManager",
390 "Error Geant4VolumeManager::volumeID(const G4VTouchable* touchable)");
396 printout(INFO,
"Geant4VolumeManager",
"+++ Bad Geant4 volume path: \'%s\' [invalid path] %s",
400 else if( !path[0]->GetLogicalVolume()->GetSensitiveDetector() ) {
401 printout(INFO,
"Geant4VolumeManager",
"+++ Bad Geant4 volume path: \'%s\' [insensitive] %s",
405 printout(INFO,
"Geant4VolumeManager",
406 "+++ Bad Geant4 volume path: \'%s\' [missing entry] %s",
410 printout(INFO,
"Geant4VolumeManager",
"+++ Bad Geant4 volume path: \'%s\' %s",
419 vol_desc.second.clear();
422 auto hash = detail::hash64(&path[0],
sizeof(path[0])*path.size());
423 auto i =
ptr()->g4Paths.find(
hash);
424 if( i !=
ptr()->g4Paths.end() ) {
425 VolumeID vid = (*i).second.volumeID;
426 G4LogicalVolume* lvol = path[0]->GetLogicalVolume();
427 if( lvol->GetSensitiveDetector() ) {
428 const auto* node = path[0];
429 const auto& pm =
ptr()->g4Placements;
430 for(
const auto& ipm : pm ) {
431 if ( ipm.second == node ) {
435 vol_desc.first = vid;
446 else if( !path[0]->GetLogicalVolume()->GetSensitiveDetector() )