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;
83 : m_detDesc(description), m_geo(g)
85 #ifdef VOLMGR_HAVE_DEBUG_INFO
87 g.
g4DebugInfo =
new Geant4GeometryInfo::DebugInfo();
93 #ifdef VOLMGR_HAVE_DEBUG_INFO
106 for(
const auto& i : c ) {
115 scanPhysicalVolume(pv.
ptr(), std::move(ids), sd, chain);
118 printout(WARNING,
"Geant4VolumeManager",
119 "++ Detector element %s of type %s has no placement.",
124 if( pv.second->IsParameterised() )
126 if( pv.second->IsReplicated() )
138 chain.emplace_back(node);
139 ids.PlacedVolume::VolIDs::Base::insert(ids.end(), pv_ids.begin(), pv_ids.end());
143 add_entry(sd, node, ids, chain);
146 printout(WARNING,
"Geant4VolumeManager",
147 "populate: Strange constellation volume %s is sensitive, but has no readout! sd:%p", pv.
volume().
name(),
151 for( Int_t idau = 0, ndau = node->GetNdaughters(); idau < ndau; ++idau ) {
152 TGeoNode* daughter = node->GetDaughter(idau);
154 if( placement.
data() ) {
155 scanPhysicalVolume(daughter, ids, sd, chain);
168 PrintLevel print_action = print_level;
169 PrintLevel print_chain = print_level;
170 PrintLevel print_res = print_level;
172 Registries::const_iterator i = m_entries.find(code);
174 printout(print_action,
"Geant4VolumeManager",
"+++ Add path:%s vid:%016X",
177 if( i == m_entries.end() ) {
178 path.reserve(nodes.size());
179 for( Chain::const_reverse_iterator k = nodes.rbegin(), kend=nodes.rend(); k != kend; ++k ) {
180 const TGeoNode* node = *(k);
183 G4VPhysicalVolume* phys = g4pit->second;
184 if( phys->IsParameterised() ) {
191 path.emplace_back(phys);
192 printout(print_chain,
"Geant4VolumeManager",
193 "+++ Chain: Node OK: %s [%s]", node->GetName(), phys->GetName().c_str());
196 control.insert(control.begin(),node);
197 vol =
Volume(node->GetVolume());
200 for(
const auto& imp : iVolImp->second ) {
201 const auto& c = imp.first;
202 if ( c.size() <= control.size() && control == c ) {
203 path.emplace_back(imp.second);
204 printout(print_chain,
"Geant4VolumeManager",
"+++ Chain: Node OK: %s %s -> %s",
206 imp.second->GetName().c_str());
213 if ( control.empty() ) {
214 printout(print_res,
"Geant4VolumeManager",
"+++ Volume IDs:%s",
216 path.erase(path.begin()+path.size()-1);
217 printout(print_res,
"Geant4VolumeManager",
"+++ Map %016X to Geant4 Path:%s",
219 auto hash = detail::hash64(&path[0], path.size()*
sizeof(path[0]));
221 #ifdef VOLMGR_HAVE_DEBUG_INFO
224 if ( missing_real_path != missing_hash_path ) {
227 if ( !nodes.empty() )
231 if ( missing_real_path ) {
239 if ( missing_hash_path ) {
244 m_entries.emplace(code);
248 if ( !path.empty() && (path.front()->IsParameterised() || path.front()->IsReplicated()) ) {
251 printout(ERROR,
"Geant4VolumeManager",
"populate: Severe error: Duplicated Geant4 path!!!! %s %s",
255 printout(INFO,
"Geant4VolumeManager",
"Control block has still %d entries:%s",
261 if ( !path.empty() && (path.front()->IsParameterised() || path.front()->IsReplicated()) ) {
265 printout(ERROR,
"Geant4VolumeManager",
"populate: Severe error: Duplicated Volume entry: 0x%X"
266 " [THIS SHOULD NEVER HAPPEN]", code);
269 if ( i != m_entries.end() )
273 if ( !nodes.empty() )
276 throw std::runtime_error(
"Failed to populate Geant4 volume manager!");
285 if( !
info->has_volmgr ) {
286 Populator p(description, *
info);
287 p.populate(description.
world());
288 info->has_volmgr =
true;
292 except(
"Geant4VolumeManager",
"Attempt populate from invalid Geant4 geometry info [Invalid-Info]");
296 std::vector<const G4VPhysicalVolume*>
305 except(
"Geant4VolumeManager",
"Attempt to use invalid Geant4 volume manager [Invalid-Handle]");
308 except(
"Geant4VolumeManager",
"Attempt to use invalid Geant4 geometry info [Invalid-Info]");
316 auto* p = mgr->
ptr();
318 ::snprintf(text,
sizeof(text),
"==> #path entries: %ld valid: %s has_volmgr: %s",
319 p->g4Paths.size(), yes_no(p->valid), yes_no(p->has_volmgr));
322 return {
"Invalid handle to Geant4GeometryInfo" };
329 std::vector<const G4VPhysicalVolume*> path = handler.
placementPath();
331 printout(INFO,
"Geant4VolumeManager",
"+++ INVALID Geant4VolumeManager handle.");
335 printout(INFO,
"Geant4VolumeManager",
"+++ INVALID Geant4VolumeManager [Not initialized]");
338 else if( path.empty() ) {
339 printout(INFO,
"Geant4VolumeManager",
"+++ EMPTY volume Geant4 Path: %s",
344 uint64_t
hash = detail::hash64(&path[0],
sizeof(path[0])*path.size());
345 auto i =
ptr()->g4Paths.find(
hash);
346 if( i !=
ptr()->g4Paths.end() ) {
347 const auto& e = (*i).second;
353 const auto& paramterised =
ptr()->g4Parameterised;
354 const auto& replicated =
ptr()->g4Replicated;
356 for( std::size_t j=0; j < path.size(); ++j ) {
357 const auto* phys = path[j];
358 if( phys->IsParameterised() ) {
359 int copy_no = touchable->GetCopyNumber(j);
360 const auto it = paramterised.find(phys);
361 if( it != paramterised.end() ) {
364 const auto* field = (*it).second.data()->params->field;
368 except(
"Geant4VolumeManager",
369 "Error Geant4VolumeManager::volumeID(const G4VTouchable* touchable)");
371 else if( phys->IsReplicated() ) {
372 int copy_no = touchable->GetCopyNumber(j);
373 const auto it = replicated.find(phys);
374 if( it != replicated.end() ) {
375 const auto* field = (*it).second.data()->params->field;
379 except(
"Geant4VolumeManager",
380 "Error Geant4VolumeManager::volumeID(const G4VTouchable* touchable)");
386 printout(INFO,
"Geant4VolumeManager",
"+++ Bad Geant4 volume path: \'%s\' [invalid path] %s",
390 else if( !path[0]->GetLogicalVolume()->GetSensitiveDetector() ) {
391 printout(INFO,
"Geant4VolumeManager",
"+++ Bad Geant4 volume path: \'%s\' [insensitive] %s",
395 printout(INFO,
"Geant4VolumeManager",
396 "+++ Bad Geant4 volume path: \'%s\' [missing entry] %s",
400 printout(INFO,
"Geant4VolumeManager",
"+++ Bad Geant4 volume path: \'%s\' %s",
409 vol_desc.second.clear();
412 auto hash = detail::hash64(&path[0],
sizeof(path[0])*path.size());
413 auto i =
ptr()->g4Paths.find(
hash);
414 if( i !=
ptr()->g4Paths.end() ) {
415 VolumeID vid = (*i).second.volumeID;
416 G4LogicalVolume* lvol = path[0]->GetLogicalVolume();
417 if( lvol->GetSensitiveDetector() ) {
418 const auto* node = path[0];
419 const auto& pm =
ptr()->g4Placements;
420 for(
const auto& ipm : pm ) {
421 if ( ipm.second == node ) {
425 vol_desc.first = vid;
436 else if( !path[0]->GetLogicalVolume()->GetSensitiveDetector() )