From b4f263c2e73fed78dfbf91d9686101b97cd18e0a Mon Sep 17 00:00:00 2001 From: Markus Frank <Markus.Frank@cern.ch> Date: Wed, 3 Jul 2024 17:09:06 +0200 Subject: [PATCH] Cosmetic changes only --- .../include/DDG4/Geant4DetectorConstruction.h | 5 +- DDG4/include/DDG4/Geant4Kernel.h | 19 ++- .../Geant4DetectorGeometryConstruction.cpp | 6 +- .../Geant4DetectorSensitivesConstruction.cpp | 38 ++---- DDG4/plugins/Geant4SDActions.cpp | 28 +++-- DDG4/python/DDG4.py | 6 + DDG4/src/Geant4Converter.cpp | 10 +- DDG4/src/Geant4DetectorConstruction.cpp | 66 +++++++---- DDG4/src/Geant4Kernel.cpp | 22 +++- DDG4/src/Geant4VolumeManager.cpp | 108 +++++++++--------- .../DDG4_MySensDet/src/MyTrackerSDAction.cpp | 32 ++++-- 11 files changed, 198 insertions(+), 142 deletions(-) diff --git a/DDG4/include/DDG4/Geant4DetectorConstruction.h b/DDG4/include/DDG4/Geant4DetectorConstruction.h index f63b7f937..9a227977a 100644 --- a/DDG4/include/DDG4/Geant4DetectorConstruction.h +++ b/DDG4/include/DDG4/Geant4DetectorConstruction.h @@ -73,7 +73,7 @@ namespace dd4hep { /// G4 User detector initializer G4VUserDetectorConstruction* detector { nullptr }; /// Initializing Constructor - Geant4DetectorConstructionContext(Detector& l,G4VUserDetectorConstruction* d) + Geant4DetectorConstructionContext(Detector& l, G4VUserDetectorConstruction* d) : description(l), world(0), geometry(0), detector(d) { } /// Default destructor ~Geant4DetectorConstructionContext() { } @@ -111,6 +111,9 @@ namespace dd4hep { virtual void constructField(Geant4DetectorConstructionContext* ctxt); /// Sensitive detector construction callback. Called at "ConstructSDandField()" virtual void constructSensitives(Geant4DetectorConstructionContext* ctxt); + /// Create Geant4 sensitive detector object using the factory mechanism + virtual G4VSensitiveDetector* createSensitiveDetector(const std::string& type, + const std::string& name); }; /// Concrete basic implementation of the Geant4 detector construction sequencer. diff --git a/DDG4/include/DDG4/Geant4Kernel.h b/DDG4/include/DDG4/Geant4Kernel.h index 5a055c4d0..03bfeed8d 100644 --- a/DDG4/include/DDG4/Geant4Kernel.h +++ b/DDG4/include/DDG4/Geant4Kernel.h @@ -88,20 +88,20 @@ namespace dd4hep { /// Property: Name of the UI action. Must be member of the global actions std::string m_uiName { }; /// Property: Name of the G4 run manager factory to be used. Default: Geant4RunManager - std::string m_runManagerType; + std::string m_runManagerType; /// Property: Name of the default factory to create G4VSensitiveDetector instances - std::string m_dfltSensitiveDetectorType; + std::string m_dfltSensitiveDetectorType; /// Property: Names with specialized factories to create G4VSensitiveDetector instances std::map<std::string, std::string> m_sensitiveDetectorTypes; /// Property: Number of events to be executed in batch mode - long m_numEvent = 10; + long m_numEvent = 10; /// Property: Output level - int m_outputLevel = 0; + int m_outputLevel = 0; /// Master property: Number of execution threads in multi threaded mode. - int m_numThreads = 0; + int m_numThreads = 0; /// Master property: Instantiate the Geant4 scoring manager object - int m_haveScoringMgr = false; + int m_haveScoringMgr = false; /// Registered action callbacks on configure UserCallbacks m_actionConfigure { }; @@ -205,6 +205,13 @@ namespace dd4hep { const std::map<std::string, std::string>& sensitiveDetectorTypes() const { return m_sensitiveDetectorTypes; } + /// Add new sensitive type to factory list + /** This is present mainly for debugging purposes and tests. + * Never necessary in real life! + * For all practical purpose the default type Geant4SensDet is sufficient. + * + */ + void defineSensitiveDetectorType(const std::string& type, const std::string& factory); /// Access to geometry world G4VPhysicalVolume* world() const; /// Set the geometry world diff --git a/DDG4/plugins/Geant4DetectorGeometryConstruction.cpp b/DDG4/plugins/Geant4DetectorGeometryConstruction.cpp index 8d79de9e5..2b9f37b5a 100644 --- a/DDG4/plugins/Geant4DetectorGeometryConstruction.cpp +++ b/DDG4/plugins/Geant4DetectorGeometryConstruction.cpp @@ -194,7 +194,7 @@ void Geant4DetectorGeometryConstruction::constructGeo(Geant4DetectorConstruction std::pair<std::string, dd4hep::PlacedVolume> Geant4DetectorGeometryConstruction::resolve_path(const char* vol_path) const { - std::string p = vol_path; + std::string p = vol_path; Detector& det = context()->kernel().detectorDescription(); PlacedVolume top = det.world().placement(); PlacedVolume pv = detail::tools::findNode(top, p); @@ -437,7 +437,7 @@ int Geant4DetectorGeometryConstruction::writeGDML(const char* output) { void Geant4DetectorGeometryConstruction::printG4(const std::string& prefix, const G4VPhysicalVolume* g4pv) const { std::string path = prefix + "/"; - printP2( "+++ GEANT4 volume: %s", prefix.c_str()); + printP2("+++ GEANT4 volume: %s", prefix.c_str()); auto* g4v = g4pv->GetLogicalVolume(); for(size_t i=0, n=g4v->GetNoDaughters(); i<n; ++i) { auto* dau = g4v->GetDaughter(i); @@ -480,5 +480,3 @@ void Geant4DetectorGeometryConstruction::installCommandMessenger() { m_control->addCall("printMaterial", "Print Geant4 material properties [uses argument]", Callback(this).make(&Geant4DetectorGeometryConstruction::printMaterial),1); } - - diff --git a/DDG4/plugins/Geant4DetectorSensitivesConstruction.cpp b/DDG4/plugins/Geant4DetectorSensitivesConstruction.cpp index f23dc4611..73d55c2aa 100644 --- a/DDG4/plugins/Geant4DetectorSensitivesConstruction.cpp +++ b/DDG4/plugins/Geant4DetectorSensitivesConstruction.cpp @@ -86,36 +86,18 @@ void Geant4DetectorSensitivesConstruction::constructSensitives(Geant4DetectorCon const std::string& dflt = kernel.defaultSensitiveDetectorType(); for( const auto& iv : p->sensitives ) { SensitiveDetector sd = iv.first; - std::string nam = sd.name(); - auto iter = types.find(nam); - std::string typ = (iter != types.end()) ? (*iter).second : dflt; - G4VSensitiveDetector* g4sd = - PluginService::Create<G4VSensitiveDetector*>(typ, nam, &ctxt->description); - if (g4sd) { - print("Geant4SDConstruction", "+++ Subdetector: %-32s type: %-16s factory: %s.", - nam.c_str(), sd.type().c_str(), typ.c_str()); - } - else { - PluginDebug dbg; - g4sd = PluginService::Create<G4VSensitiveDetector*>(typ, nam, &ctxt->description); - if ( !g4sd ) { - throw std::runtime_error("ConstructSDandField: FATAL Failed to " - "create Geant4 sensitive detector " + nam + - " (" + sd.type() + ") of type " + typ + "."); - } - print("Geant4SDConstruction", "+++ Subdetector: %-32s type: %-16s factory: %s.", - nam.c_str(), sd.type().c_str(), typ.c_str()); - } - g4sd->Activate(true); - G4SDManager::GetSDMpointer()->AddNewDetector(g4sd); - for(const TGeoVolume* vol : iv.second ) { + std::string nam = sd.name(); + auto iter = types.find(nam); + std::string typ = (iter != types.end()) ? (*iter).second : dflt; + G4VSensitiveDetector* g4sd = this->createSensitiveDetector(typ, nam); + for( const TGeoVolume* vol : iv.second ) { G4LogicalVolume* g4v = p->g4Volumes[vol]; - if ( !g4v ) { - throw std::runtime_error("ConstructSDandField: Failed to access G4LogicalVolume for SD "+ - nam + " of type " + typ + "."); + if( !g4v ) { + except("ConstructSDandField: Failed to access G4LogicalVolume for SD %s of type %s.", + nam.c_str(), typ.c_str()); } - ctxt->setSensitiveDetector(g4v,g4sd); + ctxt->setSensitiveDetector(g4v, g4sd); } } - print("Geant4SDConstruction", "+++ Handled %ld sensitive detectors.",p->sensitives.size()); + print("+++ Handled %ld sensitive detectors.",p->sensitives.size()); } diff --git a/DDG4/plugins/Geant4SDActions.cpp b/DDG4/plugins/Geant4SDActions.cpp index de9aba8e5..c3b734e55 100644 --- a/DDG4/plugins/Geant4SDActions.cpp +++ b/DDG4/plugins/Geant4SDActions.cpp @@ -296,7 +296,7 @@ namespace dd4hep { } Hit* hit = coll->findByKey<Hit>(cell); if ( !hit ) { - Geant4TouchableHandler handler(h.touchable()); + Geant4TouchableHandler handler(h.touchable()); DDSegmentation::Vector3D pos = m_segmentation.position(cell); Position global = h.localToGlobal(pos); hit = new Hit(global); @@ -507,7 +507,7 @@ namespace dd4hep { } Hit* hit = coll->findByKey<Hit>(cell); if ( !hit ) { - Geant4TouchableHandler handler(h.touchable()); + Geant4TouchableHandler handler(h.touchable()); DDSegmentation::Vector3D pos = m_segmentation.position(cell); Position global = h.localToGlobal(pos); hit = new Hit(global); @@ -577,13 +577,13 @@ namespace dd4hep { } void start(const G4Step* step, const G4StepPoint* point) { pre.storePoint(step,point); - start_collecting(step->GetTrack()); - firstSpotVolume = step->GetPreStepPoint()->GetTouchableHandle()->GetVolume(); + start_collecting(step->GetTrack()); + firstSpotVolume = step->GetPreStepPoint()->GetTouchableHandle()->GetVolume(); } void start(const Geant4FastSimSpot* spot) { pre.storePoint(spot); - start_collecting(spot->primary); - firstSpotVolume = spot->volume(); + start_collecting(spot->primary); + firstSpotVolume = spot->volume(); } /// Update energy and track information during hit info accumulation @@ -604,11 +604,11 @@ namespace dd4hep { } void update(const Geant4StepHandler& h) { post.storePoint(h.step, h.post); - update_collected_hit(h.preTouchable(), h.avgPositionG4()); // Compute cellID + update_collected_hit(h.preTouchable(), h.avgPositionG4()); // Compute cellID } void update(const Geant4FastSimHandler& h) { post.storePoint(h.spot); - update_collected_hit(h.touchable(), h.avgPositionG4()); // Compute cellID + update_collected_hit(h.touchable(), h.avgPositionG4()); // Compute cellID } /// Clear collected information and restart for new hit @@ -620,7 +620,7 @@ namespace dd4hep { current = -1; combined = 0; cell = 0; - firstSpotVolume = nullptr; + firstSpotVolume = nullptr; } /// Helper function to decide if the hit has to be extracted and saved in the collection @@ -653,10 +653,8 @@ namespace dd4hep { /// Method for generating hit(s) using the information of G4Step object. G4bool process(const G4Step* step, G4TouchableHistory* ) { Geant4StepHandler h(step); - - // std::cout << " process called - pre pos: " << h.prePos() << " post pos " << h.postPos() - // << " edep: " << h.deposit() << std::endl ; - + // std::cout << " process called - pre pos: " << h.prePos() << " post pos " << h.postPos() + // << " edep: " << h.deposit() << std::endl ; void *prePV = h.volume(h.pre), *postPV = h.volume(h.post); Geant4HitCollection* coll = sensitive->collection(0); @@ -689,7 +687,7 @@ namespace dd4hep { /// Method for generating hit(s) using the information of fast simulation spot object. G4bool process(const Geant4FastSimSpot* spot, G4TouchableHistory* ) { - Geant4FastSimHandler h(spot); + Geant4FastSimHandler h(spot); G4VPhysicalVolume* prePV = firstSpotVolume, *postPV = h.volume(); Geant4HitCollection* coll = sensitive->collection(0); /// If we are handling a new track, then store the content of the previous one. @@ -716,7 +714,7 @@ namespace dd4hep { else if ( h.track->GetTrackStatus() == fStopAndKill ) { extractHit(coll); } - return true; + return true; } /// Post-event action callback diff --git a/DDG4/python/DDG4.py b/DDG4/python/DDG4.py index 41007834e..b85a3711d 100644 --- a/DDG4/python/DDG4.py +++ b/DDG4/python/DDG4.py @@ -680,7 +680,10 @@ class Geant4: self.description.sensitiveDetector(str(name)) # sd.setType('calorimeter') if typ is None: + type = 'calorimeter' typ = self.sensitive_types['calorimeter'] + elif typ is not None and self.sensitive_types.get(typ): + typ = self.sensitive_types[typ] return self.setupDetector(name, typ, collections) def setupTracker(self, name, type=None, collections=None): # noqa: A002 @@ -693,7 +696,10 @@ class Geant4: self.description.sensitiveDetector(str(name)) # sd.setType('tracker') if typ is None: + type = 'tracker' typ = self.sensitive_types['tracker'] + elif typ is not None and self.sensitive_types.get(typ): + typ = self.sensitive_types[typ] return self.setupDetector(name, typ, collections) def _private_setupField(self, field, stepper, equation, prt): diff --git a/DDG4/src/Geant4Converter.cpp b/DDG4/src/Geant4Converter.cpp index 8bfc8921b..3b8a6d5e5 100644 --- a/DDG4/src/Geant4Converter.cpp +++ b/DDG4/src/Geant4Converter.cpp @@ -34,6 +34,7 @@ // ROOT includes #include <TClass.h> +#include <TTimeStamp.h> #include <TGeoBoolNode.h> // Geant4 include files @@ -1648,7 +1649,8 @@ void* Geant4Converter::printPlacement(const std::string& name, const TGeoNode* n printout(outputLevel, "G4Placement", str.str().c_str()); printout(outputLevel, "G4Placement", printSolid(sol).c_str()); str.str(""); - str << " |" << " Ndau:" << vol->GetNoDaughters() << " physvols." << " Mat:" << vol->GetMaterial()->GetName() + str << " |" << " Ndau:" << vol->GetNoDaughters() + << " physvols." << " Mat:" << vol->GetMaterial()->GetName() << " Mother:" << (char*) (mot ? mot->GetName().c_str() : "---"); printout(outputLevel, "G4Placement", str.str().c_str()); str.str(""); @@ -1660,6 +1662,7 @@ void* Geant4Converter::printPlacement(const std::string& name, const TGeoNode* n /// Create geometry conversion Geant4Converter& Geant4Converter::create(DetElement top) { typedef std::map<const TGeoNode*, std::vector<TGeoNode*> > _DAU; + TTimeStamp start; _DAU daughters; Geant4GeometryInfo& geo = this->init(); World wrld = top.world(); @@ -1710,6 +1713,9 @@ Geant4Converter& Geant4Converter::create(DetElement top) { m_daughters = nullptr; geo.setWorld(top.placement().ptr()); geo.valid = true; - printout(INFO, "Geant4Converter", "+++ Successfully converted geometry to Geant4."); + TTimeStamp stop; + printout(INFO, "Geant4Converter", + "+++ Successfully converted geometry to Geant4. [%7.3f seconds]", + stop.AsDouble()-start.AsDouble() ); return *this; } diff --git a/DDG4/src/Geant4DetectorConstruction.cpp b/DDG4/src/Geant4DetectorConstruction.cpp index 2b0efa9ef..561c4a08e 100644 --- a/DDG4/src/Geant4DetectorConstruction.cpp +++ b/DDG4/src/Geant4DetectorConstruction.cpp @@ -12,6 +12,7 @@ //========================================================================== // Framework include files +#include <DD4hep/Plugins.h> #include <DD4hep/InstanceCount.h> #include <DDG4/Geant4Mapping.h> #include <DDG4/Geant4GeometryInfo.h> @@ -23,7 +24,7 @@ using namespace dd4hep::sim; /// Helper: Assign sensitive detector to logical volume -void Geant4DetectorConstructionContext::setSensitiveDetector(G4LogicalVolume* vol, G4VSensitiveDetector* sd) { +void Geant4DetectorConstructionContext::setSensitiveDetector(G4LogicalVolume* vol, G4VSensitiveDetector* sd) { //detector->SetSensitiveDetector(vol,sd); G4SDManager::GetSDMpointer()->AddNewDetector(sd); vol->SetSensitiveDetector(sd); @@ -39,19 +40,44 @@ Geant4DetectorConstruction::Geant4DetectorConstruction(Geant4Context* ctxt, cons Geant4DetectorConstruction::~Geant4DetectorConstruction() { } +/// Create Geant4 sensitive detector object using the factory mechanism +G4VSensitiveDetector* +Geant4DetectorConstruction::createSensitiveDetector(const std::string& typ, + const std::string& nam) { + Detector& dsc = context()->detectorDescription(); + G4VSensitiveDetector* g4sd = PluginService::Create<G4VSensitiveDetector*>(typ, nam, &dsc); + if( g4sd ) { + print("+++ Subdetector: %-32s type: %s.", nam.c_str(), typ.c_str()); + } + else { + PluginDebug dbg; + g4sd = PluginService::Create<G4VSensitiveDetector*>(typ, nam, &dsc); + if ( !g4sd ) { + except("createSensitiveDetector: FATAL Failed to " + "create Geant4 sensitive detector %s of type %s.", + nam.c_str(), typ.c_str()); + } + print("+++ Subdetector: %-32s type: %s.", nam.c_str(), typ.c_str()); + } + if ( g4sd ) { + g4sd->Activate(true); + G4SDManager::GetSDMpointer()->AddNewDetector(g4sd); + } + return g4sd; +} + /// Geometry construction callback. Called at "Construct()" -void Geant4DetectorConstruction::constructGeo(Geant4DetectorConstructionContext* ) { +void Geant4DetectorConstruction::constructGeo(Geant4DetectorConstructionContext* ) { } /// Electromagnetic field construction callback. Called at "ConstructSDandField()" -void Geant4DetectorConstruction::constructField(Geant4DetectorConstructionContext* ) { +void Geant4DetectorConstruction::constructField(Geant4DetectorConstructionContext* ) { } /// Sensitive detector construction callback. Called at "ConstructSDandField()" -void Geant4DetectorConstruction::constructSensitives(Geant4DetectorConstructionContext* ) { +void Geant4DetectorConstruction::constructSensitives(Geant4DetectorConstructionContext* ) { } - /// Standard Constructor Geant4DetectorConstructionSequence::Geant4DetectorConstructionSequence(Geant4Context* ctxt, const std::string& nam) : Geant4Action(ctxt,nam) @@ -61,19 +87,19 @@ Geant4DetectorConstructionSequence::Geant4DetectorConstructionSequence(Geant4Con } /// Default destructor -Geant4DetectorConstructionSequence::~Geant4DetectorConstructionSequence() { +Geant4DetectorConstructionSequence::~Geant4DetectorConstructionSequence() { m_actors(&Geant4DetectorConstruction::release); InstanceCount::decrement(this); } /// Set or update client context -void Geant4DetectorConstructionSequence::updateContext(Geant4Context* ctxt) { +void Geant4DetectorConstructionSequence::updateContext(Geant4Context* ctxt) { m_context = ctxt; m_actors(&Geant4DetectorConstruction::updateContext,ctxt); } /// Add an actor responding to all callbacks. Sequence takes ownership. -void Geant4DetectorConstructionSequence::adopt(Geant4DetectorConstruction* action) { +void Geant4DetectorConstructionSequence::adopt(Geant4DetectorConstruction* action) { if (action) { action->addRef(); m_actors.add(action); @@ -83,7 +109,7 @@ void Geant4DetectorConstructionSequence::adopt(Geant4DetectorConstruction* actio } /// Access an actor by name -Geant4DetectorConstruction* Geant4DetectorConstructionSequence::get(const std::string& nam) const { +Geant4DetectorConstruction* Geant4DetectorConstructionSequence::get(const std::string& nam) const { for(auto* i : m_actors) { if ( i->name() == nam ) { return i; @@ -94,23 +120,23 @@ Geant4DetectorConstruction* Geant4DetectorConstructionSequence::get(const std::s } /// Geometry construction callback. Called at "Construct()" -void Geant4DetectorConstructionSequence::constructGeo(Geant4DetectorConstructionContext* ctxt) { +void Geant4DetectorConstructionSequence::constructGeo(Geant4DetectorConstructionContext* ctxt) { m_actors(&Geant4DetectorConstruction::constructGeo, ctxt); } /// Electromagnetic field construction callback. Called at "ConstructSDandField()" -void Geant4DetectorConstructionSequence::constructField(Geant4DetectorConstructionContext* ctxt) { +void Geant4DetectorConstructionSequence::constructField(Geant4DetectorConstructionContext* ctxt) { m_actors(&Geant4DetectorConstruction::constructField, ctxt); } /// Sensitive detector construction callback. Called at "ConstructSDandField()" -void Geant4DetectorConstructionSequence::constructSensitives(Geant4DetectorConstructionContext* ctxt) { +void Geant4DetectorConstructionSequence::constructSensitives(Geant4DetectorConstructionContext* ctxt) { m_actors(&Geant4DetectorConstruction::constructSensitives, ctxt); } /// Access to the converted regions const std::map<dd4hep::Region, G4Region*>& -Geant4DetectorConstructionSequence::regions() const { +Geant4DetectorConstructionSequence::regions() const { Geant4GeometryInfo* p = Geant4Mapping::instance().ptr(); if ( p ) return p->g4Regions; throw std::runtime_error("+++ Geant4DetectorConstructionSequence::regions: Access not possible. Geometry is not yet converted!"); @@ -118,14 +144,14 @@ Geant4DetectorConstructionSequence::regions() const { /// Access to the converted volumes const std::map<dd4hep::Volume, G4LogicalVolume*>& -Geant4DetectorConstructionSequence::volumes() const { +Geant4DetectorConstructionSequence::volumes() const { Geant4GeometryInfo* p = Geant4Mapping::instance().ptr(); if ( p ) return p->g4Volumes; throw std::runtime_error("+++ Geant4DetectorConstructionSequence::volumes: Access not possible. Geometry is not yet converted!"); } /// Access to the converted shapes -const std::map<const TGeoShape*, G4VSolid*>& Geant4DetectorConstructionSequence::shapes() const { +const std::map<const TGeoShape*, G4VSolid*>& Geant4DetectorConstructionSequence::shapes() const { Geant4GeometryInfo* p = Geant4Mapping::instance().ptr(); if ( p ) return p->g4Solids; throw std::runtime_error("+++ Geant4DetectorConstructionSequence::shapes: Access not possible. Geometry is not yet converted!"); @@ -133,7 +159,7 @@ const std::map<const TGeoShape*, G4VSolid*>& Geant4DetectorConstructionSequence: /// Access to the converted limit sets const std::map<dd4hep::LimitSet, G4UserLimits*>& -Geant4DetectorConstructionSequence::limits() const { +Geant4DetectorConstructionSequence::limits() const { Geant4GeometryInfo* p = Geant4Mapping::instance().ptr(); if ( p ) return p->g4Limits; throw std::runtime_error("+++ Geant4DetectorConstructionSequence::limits: Access not possible. Geometry is not yet converted!"); @@ -141,7 +167,7 @@ Geant4DetectorConstructionSequence::limits() const { /// Access to the converted assemblies const std::map<dd4hep::PlacedVolume, Geant4AssemblyVolume*>& -Geant4DetectorConstructionSequence::assemblies() const { +Geant4DetectorConstructionSequence::assemblies() const { Geant4GeometryInfo* p = Geant4Mapping::instance().ptr(); if ( p ) return p->g4AssemblyVolumes; throw std::runtime_error("+++ Geant4DetectorConstructionSequence::assemblies: Access not possible. Geometry is not yet converted!"); @@ -149,21 +175,21 @@ Geant4DetectorConstructionSequence::assemblies() const { /// Access to the converted placements const std::map<dd4hep::PlacedVolume, G4VPhysicalVolume*>& -Geant4DetectorConstructionSequence::placements() const { +Geant4DetectorConstructionSequence::placements() const { Geant4GeometryInfo* p = Geant4Mapping::instance().ptr(); if ( p ) return p->g4Placements; throw std::runtime_error("+++ Geant4DetectorConstructionSequence::placements: Access not possible. Geometry is not yet converted!"); } /// Access to the converted materials -const Geant4GeometryMaps::MaterialMap& Geant4DetectorConstructionSequence::materials() const { +const Geant4GeometryMaps::MaterialMap& Geant4DetectorConstructionSequence::materials() const { Geant4GeometryInfo* p = Geant4Mapping::instance().ptr(); if ( p ) return p->g4Materials; throw std::runtime_error("+++ Geant4DetectorConstructionSequence::materials: Access not possible. Geometry is not yet converted!"); } /// Access to the converted elements -const Geant4GeometryMaps::ElementMap& Geant4DetectorConstructionSequence::elements() const { +const Geant4GeometryMaps::ElementMap& Geant4DetectorConstructionSequence::elements() const { Geant4GeometryInfo* p = Geant4Mapping::instance().ptr(); if ( p ) return p->g4Elements; throw std::runtime_error("+++ Geant4DetectorConstructionSequence::elements: Access not possible. Geometry is not yet converted!"); diff --git a/DDG4/src/Geant4Kernel.cpp b/DDG4/src/Geant4Kernel.cpp index 00b004af8..dc85386dc 100644 --- a/DDG4/src/Geant4Kernel.cpp +++ b/DDG4/src/Geant4Kernel.cpp @@ -202,7 +202,7 @@ Geant4Kernel& Geant4Kernel::worker(unsigned long identifier, bool create_if) return *this; } } - else if ( create_if ) { + else if( create_if ) { return createWorker(); } except("Geant4Kernel", "DDG4: The Kernel object 0x%p does not exists!",(void*)identifier); @@ -216,16 +216,32 @@ int Geant4Kernel::numWorkers() const { /// Access to geometry world G4VPhysicalVolume* Geant4Kernel::world() const { - if ( this != m_master ) return m_master->world(); + if( this != m_master ) return m_master->world(); return m_world; } /// Set the geometry world void Geant4Kernel::setWorld(G4VPhysicalVolume* volume) { - if ( this == m_master ) m_world = volume; + if( this == m_master ) m_world = volume; else m_master->setWorld(volume); } +/// Add new sensitive type to factory list +void Geant4Kernel::defineSensitiveDetectorType(const std::string& type, const std::string& factory) { + auto iter = m_sensitiveDetectorTypes.find(type); + if( iter == m_sensitiveDetectorTypes.end() ) { + printout(INFO,"Geant4Kernel","+++ Define sensitive type: %s -> %s", type.c_str(), factory.c_str()); + m_sensitiveDetectorTypes.emplace(type, factory); + return; + } + else if( iter->first == type && iter->second == factory ) { + return; + } + except("Geant4Kernel", + "+++ The sensitive type %s is already defined and used %s. Cannot overwrite with %s", + type.c_str(), iter->second.c_str(), factory.c_str()); +} + void Geant4Kernel::printProperties() const { printout(ALWAYS,"Geant4Kernel","OutputLevel: %d", m_outputLevel); printout(ALWAYS,"Geant4Kernel","UI: %s", m_uiName.c_str()); diff --git a/DDG4/src/Geant4VolumeManager.cpp b/DDG4/src/Geant4VolumeManager.cpp index a2e1d2cb1..a24ee1e5e 100644 --- a/DDG4/src/Geant4VolumeManager.cpp +++ b/DDG4/src/Geant4VolumeManager.cpp @@ -28,22 +28,24 @@ // C/C++ include files #include <sstream> -using namespace dd4hep::sim::Geant4GeometryMaps; using namespace dd4hep::sim; using namespace dd4hep; #include <DDG4/Geant4AssemblyVolume.h> -typedef std::pair<VolumeID,std::vector<std::pair<const BitFieldElement*, VolumeID> > > VolIDDescriptor; -namespace { +using VolIDDescriptor = std::pair<VolumeID,std::vector<std::pair<const BitFieldElement*, VolumeID> > >; + +namespace { /// Helper class to populate the Geant4 volume manager struct Populator { + typedef std::vector<const TGeoNode*> Chain; typedef std::map<VolumeID,Geant4GeometryInfo::Geant4PlacementPath> Registries; + /// Reference to the Detector instance - const Detector& m_detDesc; + const Detector& m_detDesc; /// Set of already added entries - Registries m_entries; + Registries m_entries; /// Reference to Geant4 translation information Geant4GeometryInfo& m_geo; @@ -71,7 +73,7 @@ namespace { "++ Detector element %s of type %s has no placement.", de.name(), de.type().c_str()); } /// Needed to compute the cellID of parameterized volumes - for( const auto& pv : m_geo.g4Placements ) { + for( const auto& pv : m_geo.g4Placements ) { if ( pv.second->IsParameterised() ) m_geo.g4Parameterised[pv.second] = pv.first; if ( pv.second->IsReplicated() ) @@ -110,12 +112,12 @@ namespace { void add_entry(SensitiveDetector sd, const TGeoNode* n, const PlacedVolume::VolIDs& ids, const Chain& nodes) { Chain control; - const TGeoNode* node; - Volume vol; - Geant4GeometryInfo::Geant4PlacementPath path; - Readout ro = sd.readout(); + Volume vol; + const TGeoNode* node = nullptr; + Readout ro = sd.readout(); IDDescriptor iddesc = ro.idSpec(); - VolumeID code = iddesc.encode(ids); + VolumeID code = iddesc.encode(ids); + Geant4GeometryInfo::Geant4PlacementPath path; Registries::const_iterator i = m_entries.find(code); PrintLevel print_level = m_geo.printLevel; PrintLevel print_action = print_level; @@ -125,17 +127,17 @@ namespace { printout(print_action,"Geant4VolumeManager","+++ Add path:%s vid:%016X", detail::tools::placementPath(nodes,false).c_str(),code); - if (i == m_entries.end()) { + if( i == m_entries.end() ) { path.reserve(nodes.size()); - for (Chain::const_reverse_iterator k = nodes.rbegin(), kend=nodes.rend(); k != kend; ++k) { + for( Chain::const_reverse_iterator k = nodes.rbegin(), kend=nodes.rend(); k != kend; ++k ) { node = *(k); - PlacementMap::const_iterator g4pit = m_geo.g4Placements.find(node); - if (g4pit != m_geo.g4Placements.end()) { - G4VPhysicalVolume* phys = (*g4pit).second; - if ( phys->IsParameterised() ) { + auto g4pit = m_geo.g4Placements.find(node); + if( g4pit != m_geo.g4Placements.end() ) { + G4VPhysicalVolume* phys = g4pit->second; + if( phys->IsParameterised() ) { PlacedVolume pv(n); PlacedVolumeExtension* ext = pv.data(); - if ( nullptr == ext->params->field ) { + if( nullptr == ext->params->field ) { ext->params->field = iddesc.field(ext->volIDs.at(0).first); } } @@ -146,12 +148,11 @@ namespace { } control.insert(control.begin(),node); vol = Volume(node->GetVolume()); - VolumeImprintMap::const_iterator iVolImp = m_geo.g4VolumeImprints.find(vol); - if ( iVolImp != m_geo.g4VolumeImprints.end() ) { - const Imprints& imprints = (*iVolImp).second; - for(const auto& imp : imprints ) { - const VolumeChain& c = imp.first; - if ( c.size() <= control.size() && control == c ) { + auto iVolImp = m_geo.g4VolumeImprints.find(vol); + if ( iVolImp != m_geo.g4VolumeImprints.end() ) { + for(const auto& imp : iVolImp->second ) { + const auto& c = imp.first; + if ( c.size() <= control.size() && control == c ) { path.emplace_back(imp.second); printout(print_chain, "Geant4VolumeManager", "+++ Chain: Node OK: %s %s -> %s", node->GetName(), detail::tools::placementPath(c,false).c_str(), @@ -162,7 +163,7 @@ namespace { } } } - if ( control.empty() ) { + if ( control.empty() ) { printout(print_res, "Geant4VolumeManager", "+++ Volume IDs:%s", detail::tools::toString(ro.idSpec(),ids,code).c_str()); path.erase(path.begin()+path.size()-1); @@ -170,7 +171,7 @@ namespace { (void*)code, Geant4GeometryInfo::placementPath(path).c_str()); if ( m_geo.g4Paths.find(path) == m_geo.g4Paths.end() ) { Geant4GeometryInfo::PlacementFlags opt; - for(const auto* phys : path) { + for(const auto* phys : path) { opt.flags.path_has_parametrised = phys->IsParameterised() ? 1 : 0; opt.flags.path_has_replicated = phys->IsReplicated() ? 1 : 0; } @@ -181,7 +182,7 @@ namespace { return; } /// This is a normal case for parametrized volumes and no error - if ( !path.empty() && (path.front()->IsParameterised() || path.front()->IsReplicated()) ) { + if ( !path.empty() && (path.front()->IsParameterised() || path.front()->IsReplicated()) ) { return; } printout(ERROR, "Geant4VolumeManager", "populate: Severe error: Duplicated Geant4 path!!!! %s %s", @@ -194,7 +195,7 @@ namespace { } else { /// This is a normal case for parametrized volumes and no error - if ( !path.empty() && (path.front()->IsParameterised() || path.front()->IsReplicated()) ) { + if ( !path.empty() && (path.front()->IsParameterised() || path.front()->IsReplicated()) ) { return; } } @@ -216,7 +217,7 @@ namespace { /// Initializing constructor. The tree will automatically be built if possible Geant4VolumeManager::Geant4VolumeManager(const Detector& description, Geant4GeometryInfo* info) - : Handle<Geant4GeometryInfo>(info) { + : Handle<Geant4GeometryInfo>(info) { if (info && info->valid && info->g4Paths.empty()) { Populator p(description, *info); p.populate(description.world()); @@ -249,7 +250,7 @@ VolumeID Geant4VolumeManager::volumeID(const std::vector<const G4VPhysicalVolume if (!path.empty() && checkValidity()) { const auto& mapping = ptr()->g4Paths; auto i = mapping.find(path); - if ( i != mapping.end() ) { + if ( i != mapping.end() ) { return (*i).second.first; } if (!path[0]) @@ -267,25 +268,25 @@ VolumeID Geant4VolumeManager::volumeID(const std::vector<const G4VPhysicalVolume VolumeID Geant4VolumeManager::volumeID(const G4VTouchable* touchable) const { Geant4TouchableHandler handler(touchable); std::vector<const G4VPhysicalVolume*> path = handler.placementPath(); - if (!path.empty() && checkValidity()) { + if( !path.empty() && checkValidity() ) { const auto& mapping = ptr()->g4Paths; auto i = mapping.find(path); - if ( i != mapping.end() ) { + if( i != mapping.end() ) { const auto& e = (*i).second; /// No parametrization or replication. - if ( e.flags == 0 ) { + if( e.flags == 0 ) { return e.volumeID; } VolumeID volid = e.volumeID; const auto& paramterised = ptr()->g4Parameterised; const auto& replicated = ptr()->g4Replicated; /// This is incredibly slow .... but what can I do ? Need a better idea. - for ( std::size_t j=0; j < path.size(); ++j ) { + for( std::size_t j=0; j < path.size(); ++j ) { const auto* phys = path[j]; - if ( phys->IsParameterised() ) { + if( phys->IsParameterised() ) { int copy_no = touchable->GetCopyNumber(j); const auto it = paramterised.find(phys); - if ( it != paramterised.end() ) { + if( it != paramterised.end() ) { //printout(INFO,"Geant4VolumeManager", // "Copy number: %ld <--> %ld", copy_no, long(phys->GetCopyNo())); const auto* field = (*it).second.data()->params->field; @@ -294,10 +295,10 @@ VolumeID Geant4VolumeManager::volumeID(const G4VTouchable* touchable) const { } except("Geant4VolumeManager","Error Geant4VolumeManager::volumeID(const G4VTouchable* touchable)"); } - else if ( phys->IsReplicated() ) { + else if( phys->IsReplicated() ) { int copy_no = touchable->GetCopyNumber(j); const auto it = replicated.find(phys); - if ( it != replicated.end() ) { + if( it != replicated.end() ) { const auto* field = (*it).second.data()->params->field; volid |= IDDescriptor::encode(field, copy_no); continue; @@ -307,9 +308,9 @@ VolumeID Geant4VolumeManager::volumeID(const G4VTouchable* touchable) const { } return volid; } - if (!path[0]) + if( !path[0] ) return InvalidPath; - else if (!path[0]->GetLogicalVolume()->GetSensitiveDetector()) + else if( !path[0]->GetLogicalVolume()->GetSensitiveDetector() ) return Insensitive; } printout(INFO, "Geant4VolumeManager","+++ Bad volume Geant4 Path: %s", @@ -323,20 +324,20 @@ void Geant4VolumeManager::volumeDescriptor(const std::vector<const G4VPhysicalVo { vol_desc.second.clear(); vol_desc.first = NonExisting; - if ( !path.empty() && checkValidity() ) { + if( !path.empty() && checkValidity() ) { const auto& mapping = ptr()->g4Paths; auto i = mapping.find(path); - if (i != mapping.end()) { + if( i != mapping.end() ) { VolumeID vid = (*i).second.volumeID; G4LogicalVolume* lvol = path[0]->GetLogicalVolume(); - if ( lvol->GetSensitiveDetector() ) { - const G4VPhysicalVolume* node = path[0]; - const PlacementMap& pm = ptr()->g4Placements; - for (PlacementMap::const_iterator ipm = pm.begin(); ipm != pm.end(); ++ipm) { - if ( (*ipm).second == node ) { - PlacedVolume pv = (*ipm).first; - SensitiveDetector sd = pv.volume().sensitiveDetector(); - IDDescriptor dsc = sd.readout().idSpec(); + if( lvol->GetSensitiveDetector() ) { + const auto* node = path[0]; + const auto& pm = ptr()->g4Placements; + for( const auto& ipm : pm ) { + if ( ipm.second == node ) { + PlacedVolume pv = ipm.first; + SensitiveDetector sd = pv.volume().sensitiveDetector(); + IDDescriptor dsc = sd.readout().idSpec(); vol_desc.first = vid; dsc.decodeFields(vid, vol_desc.second); return; @@ -346,9 +347,9 @@ void Geant4VolumeManager::volumeDescriptor(const std::vector<const G4VPhysicalVo vol_desc.first = Insensitive; return; } - if ( !path[0] ) + if( !path[0] ) vol_desc.first = InvalidPath; - else if ( !path[0]->GetLogicalVolume()->GetSensitiveDetector() ) + else if( !path[0]->GetLogicalVolume()->GetSensitiveDetector() ) vol_desc.first = Insensitive; else vol_desc.first = NonExisting; @@ -357,7 +358,6 @@ void Geant4VolumeManager::volumeDescriptor(const std::vector<const G4VPhysicalVo /// Access fully decoded volume fields by Geant4 touchable object void Geant4VolumeManager::volumeDescriptor(const G4VTouchable* touchable, - VolIDDescriptor& vol_desc) const { + VolIDDescriptor& vol_desc) const { volumeDescriptor(placementPath(touchable), vol_desc); } - diff --git a/examples/DDG4_MySensDet/src/MyTrackerSDAction.cpp b/examples/DDG4_MySensDet/src/MyTrackerSDAction.cpp index 1d98b8edc..476244e46 100644 --- a/examples/DDG4_MySensDet/src/MyTrackerSDAction.cpp +++ b/examples/DDG4_MySensDet/src/MyTrackerSDAction.cpp @@ -24,7 +24,8 @@ namespace SomeExperiment { public: typedef MyTrackerHit Hit; // If we need special data to personalize the action, be put it here - int mumDeposits = 0; + bool haveCellID = true; + int mumDeposits = 0; double integratedDeposit = 0; }; } @@ -48,7 +49,20 @@ namespace dd4hep { * * @} */ - + template <> + Geant4SensitiveAction<MyTrackerSD>::Geant4SensitiveAction(Geant4Context* ctxt, + const std::string& nam, + DetElement det, + Detector& description_ref) + : Geant4Sensitive(ctxt,nam,det,description_ref), m_collectionName(), m_collectionID(0) + { + declareProperty("HaveCellID", m_userData.haveCellID = true); + declareProperty("ReadoutName", m_readoutName); + declareProperty("CollectionName", m_collectionName); + initialize(); + InstanceCount::increment(this); + } + /// Define collections created by this sensitivie action object template <> void Geant4SensitiveAction<MyTrackerSD>::defineCollections() { m_collectionID = declareReadoutFilteredCollection<MyTrackerSD::Hit>(); @@ -67,20 +81,20 @@ namespace dd4hep { double tim = h.track->GetGlobalTime(); // Somehow extract here the physics you want MyTrackerSD::Hit* hit = - new MyTrackerSD::Hit(h.trkID(), h.trkPdgID(), depo, tim, hit_len, pos, mom); + new MyTrackerSD::Hit(h.trkID(), h.trkPdgID(), depo, tim, hit_len, pos, mom); Geant4HitData::MonteCarloContrib contrib = Geant4HitData::extractContribution(step); - hit->cellID = cellID(step); + hit->cellID = this->m_userData.haveCellID ? cellID(step) : 0; hit->step_length = hit_len; hit->prePos = prePos; hit->postPos = postPos; collection(m_collectionID)->add(hit); mark(h.track); - if ( 0 == hit->cellID ) { + if ( this->m_userData.haveCellID && 0 == hit->cellID ) { hit->cellID = volumeID(step); except("+++ Invalid CELL ID for hit!"); } printP1("Hit with deposit:%f Pos:%f %f %f ID=%016X", - depo, pos.X(), pos.Y(), pos.Z(), (void*)hit->cellID); + depo, pos.X(), pos.Y(), pos.Z(), (void*)hit->cellID); Geant4TouchableHandler handler(step); print(" Geant4 path:%s", handler.path().c_str()); @@ -91,9 +105,9 @@ namespace dd4hep { /// Let's play with the Geant4TrackInformation /// See issue https://github.com/AIDASoft/DD4hep/issues/1073 if ( nullptr == h.track->GetUserInformation() ) { - auto data = std::make_unique<ParticleUserData>(); - data->absolute_momentum = h.track->GetMomentum().mag(); - h.track->SetUserInformation(new Geant4ParticleInformation(std::move(data))); + auto data = std::make_unique<ParticleUserData>(); + data->absolute_momentum = h.track->GetMomentum().mag(); + h.track->SetUserInformation(new Geant4ParticleInformation(std::move(data))); } return true; } -- GitLab