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;
70 using VolIDDescriptor = std::pair<VolumeID,std::vector<std::pair<const BitFieldElement*, VolumeID> > >;
82 typedef std::vector<const TGeoNode*> Chain;
84 typedef std::set<VolumeID> Registries;
97 : m_detDesc(description), m_geo(g), m_debug(dbg)
99 #ifdef VOLMGR_HAVE_DEBUG_INFO
101 g.
g4DebugInfo =
new Geant4GeometryInfo::DebugInfo();
107 #ifdef VOLMGR_HAVE_DEBUG_INFO
120 for(
const auto& i : children ) {
129 scanPhysicalVolume(pv.
ptr(), std::move(ids), sd, chain);
132 printout(WARNING,
"Geant4VolumeManager",
133 "++ Detector element %s of type %s has no placement.",
138 if( pv.second->IsParameterised() )
140 if( pv.second->IsReplicated() )
152 chain.emplace_back(node);
153 ids.PlacedVolume::VolIDs::Base::insert(ids.end(), pv_ids.begin(), pv_ids.end());
157 add_entry(sd, node, ids, chain);
160 printout(WARNING,
"Geant4VolumeManager",
161 "populate: Strange constellation volume %s is sensitive, but has no readout! sd:%p", pv.
volume().
name(),
165 for( Int_t idau = 0, ndau = node->GetNdaughters(); idau < ndau; ++idau ) {
166 TGeoNode* daughter = node->GetDaughter(idau);
168 if( placement.
data() ) {
169 scanPhysicalVolume(daughter, ids, sd, chain);
186 Registries::const_iterator i = m_entries.find(code);
188 printout(print_action,
"Geant4VolumeManager",
"+++ Add path:%s vid:%016X",
191 if( i == m_entries.end() ) {
192 path.reserve(nodes.size());
193 for( Chain::const_reverse_iterator k = nodes.rbegin(), kend=nodes.rend(); k != kend; ++k ) {
194 const TGeoNode* node = *(k);
197 G4VPhysicalVolume* phys = g4pit->second;
198 if( phys->IsParameterised() ) {
205 path.emplace_back(phys);
206 printout(print_chain,
"Geant4VolumeManager",
207 "+++ Chain: Node OK: %s [%s]", node->GetName(), phys->GetName().c_str());
210 control.insert(control.begin(),node);
211 vol =
Volume(node->GetVolume());
214 for(
const auto& imp : iVolImp->second ) {
215 const auto& c = imp.first;
216 if ( c.size() <= control.size() && control == c ) {
217 path.emplace_back(imp.second);
218 printout(print_chain,
"Geant4VolumeManager",
"+++ Chain: Node OK: %s %s -> %s",
220 imp.second->GetName().c_str());
227 if ( control.empty() ) {
228 printout(print_res,
"Geant4VolumeManager",
"+++ Encoded Volume IDs:%s",
230 path.erase(path.begin()+path.size()-1);
231 printout(print_res,
"Geant4VolumeManager",
"+++ Map %016X to Geant4 Path:%s",
233 auto hash = detail::hash64(&path[0], path.size()*
sizeof(path[0]));
235 #ifdef VOLMGR_HAVE_DEBUG_INFO
238 if ( missing_real_path != missing_hash_path ) {
241 if ( !nodes.empty() )
245 if ( missing_real_path ) {
253 if ( missing_hash_path ) {
259 std::string idstr = iddesc.
str(code);
260 printout(ALWAYS,
"Geant4VolumeManager",
261 "+++ Decoded Volume IDs: %016llX -> %s", code, idstr.c_str());
263 m_entries.emplace(code);
267 if ( !path.empty() && (path.front()->IsParameterised() || path.front()->IsReplicated()) ) {
270 printout(ERROR,
"Geant4VolumeManager",
"populate: Severe error: Duplicated Geant4 path!!!! %s %s",
274 printout(INFO,
"Geant4VolumeManager",
"Control block has still %d entries:%s",
281 if ( !path.empty() && (path.front()->IsParameterised() || path.front()->IsReplicated()) ) {
285 printout(ERROR,
"Geant4VolumeManager",
"populate: Severe error: Duplicated Volume entry: 0x%X"
286 " [THIS SHOULD NEVER HAPPEN]", code);
289 if ( i != m_entries.end() )
293 if ( !nodes.empty() ) {
296 std::string node_path;
297 for( std::size_t in=0; in<nodes.size(); ++in ) {
300 node_path += pv.
name();
301 printout( ALWAYS,
"Geant4VolumeManager",
" TGeo Node[%ld]: %s [%p] Volids: '%s'",
302 in, node_path.c_str(), (
void*)nodes[in], pv.
volIDs().
str().c_str() );
306 printout( ERROR,
"Geant4VolumeManager",
" Offend.VolIDs: %s",
detail::tools::toString(iddesc,ids,code).c_str() );
307 throw std::runtime_error(
"Failed to populate Geant4 volume manager!");
316 if( !
info->has_volmgr ) {
318 printout( ALWAYS,
"Geant4VolumeManager",
"+++ Populating Geant4 volume manager.");
319 p.populate(description.
world());
320 printout( ALWAYS,
"Geant4VolumeManager",
321 "+++ Geant4 volume manager populated with %ld sensitive path entries.",
322 info->g4Paths.size() );
326 for(
auto it=
info->g4Paths.begin(); it !=
info->g4Paths.end(); ++it, ++count ) {
327 VolumeID volid = it->second.volumeID;
333 std::string idstr = sens.
idSpec().
str(volid);
334 printout( ALWAYS,
"Geant4VolumeManager",
"%8d: %016X %s -> %s",
335 count, volid, path.c_str(), plac.
name());
336 printout(ALWAYS,
"Geant4VolumeManager",
"%8s %16s %s",
"",
"", idstr.c_str());
339 printout( ERROR,
"Geant4VolumeManager",
340 "Missing volume manager entry: volume ID %016X", volid);
344 info->has_volmgr =
true;
348 except(
"Geant4VolumeManager",
"Attempt populate from invalid Geant4 geometry info [Invalid-Info]");
352 std::vector<const G4VPhysicalVolume*>
361 except(
"Geant4VolumeManager",
"Attempt to use invalid Geant4 volume manager [Invalid-Handle]");
364 except(
"Geant4VolumeManager",
"Attempt to use invalid Geant4 geometry info [Invalid-Info]");
372 auto* p = mgr->
ptr();
374 ::snprintf(text,
sizeof(text),
"==> #path entries: %ld valid: %s has_volmgr: %s",
375 p->g4Paths.size(), yes_no(p->valid), yes_no(p->has_volmgr));
378 return {
"Invalid handle to Geant4GeometryInfo" };
385 std::vector<const G4VPhysicalVolume*> path = handler.
placementPath();
387 printout(INFO,
"Geant4VolumeManager",
"+++ INVALID Geant4VolumeManager handle.");
391 printout(INFO,
"Geant4VolumeManager",
"+++ INVALID Geant4VolumeManager [Not initialized]");
394 else if( path.empty() ) {
395 printout(INFO,
"Geant4VolumeManager",
"+++ EMPTY volume Geant4 Path: %s",
400 uint64_t
hash = detail::hash64(&path[0],
sizeof(path[0])*path.size());
401 auto i =
ptr()->g4Paths.find(
hash);
402 if( i !=
ptr()->g4Paths.end() ) {
403 const auto& e = (*i).second;
409 const auto& paramterised =
ptr()->g4Parameterised;
410 const auto& replicated =
ptr()->g4Replicated;
412 for( std::size_t j=0; j < path.size(); ++j ) {
413 const auto* phys = path[j];
414 if( phys->IsParameterised() ) {
415 int copy_no = touchable->GetCopyNumber(j);
416 const auto it = paramterised.find(phys);
417 if( it != paramterised.end() ) {
420 const auto* field = (*it).second.data()->params->field;
424 except(
"Geant4VolumeManager",
425 "Error Geant4VolumeManager::volumeID(const G4VTouchable* touchable)");
427 else if( phys->IsReplicated() ) {
428 int copy_no = touchable->GetCopyNumber(j);
429 const auto it = replicated.find(phys);
430 if( it != replicated.end() ) {
431 const auto* field = (*it).second.data()->params->field;
435 except(
"Geant4VolumeManager",
436 "Error Geant4VolumeManager::volumeID(const G4VTouchable* touchable)");
442 printout(INFO,
"Geant4VolumeManager",
"+++ Bad Geant4 volume path: \'%s\' [invalid path] %s",
446 else if( !path[0]->GetLogicalVolume()->GetSensitiveDetector() ) {
447 printout(DEBUG,
"Geant4VolumeManager",
"+++ Bad Geant4 volume path: \'%s\' [insensitive] %s",
451 printout(INFO,
"Geant4VolumeManager",
452 "+++ Bad Geant4 volume path: \'%s\' [missing entry] %s",
456 printout(INFO,
"Geant4VolumeManager",
"+++ Bad Geant4 volume path: \'%s\' %s",
465 vol_desc.second.clear();
468 auto hash = detail::hash64(&path[0],
sizeof(path[0])*path.size());
469 auto i =
ptr()->g4Paths.find(
hash);
470 if( i !=
ptr()->g4Paths.end() ) {
471 VolumeID vid = (*i).second.volumeID;
472 G4LogicalVolume* lvol = path[0]->GetLogicalVolume();
473 if( lvol->GetSensitiveDetector() ) {
474 const auto* node = path[0];
475 const auto& pm =
ptr()->g4Placements;
476 for(
const auto& ipm : pm ) {
477 if ( ipm.second == node ) {
481 vol_desc.first = vid;
492 else if( !path[0]->GetLogicalVolume()->GetSensitiveDetector() )