Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-10-05 08:17:11

0001 //==========================================================================
0002 //  AIDA Detector description implementation 
0003 //--------------------------------------------------------------------------
0004 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
0005 // All rights reserved.
0006 //
0007 // For the licensing terms see $DD4hepINSTALL/LICENSE.
0008 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
0009 //
0010 // Author     : M.Frank
0011 //
0012 //==========================================================================
0013 
0014 // Framework include files
0015 #include <DD4hep/Printout.h>
0016 #include <DD4hep/Primitives.h>
0017 #include <DD4hep/InstanceCount.h>
0018 
0019 #include <DDG4/Geant4Kernel.h>
0020 #include <DDG4/Geant4Mapping.h>
0021 #include <DDG4/Geant4StepHandler.h>
0022 #include <DDG4/Geant4SensDetAction.h>
0023 #include <DDG4/Geant4VolumeManager.h>
0024 #include <DDG4/Geant4MonteCarloTruth.h>
0025 
0026 // Geant4 include files
0027 #include <G4Step.hh>
0028 #include <G4SDManager.hh>
0029 #include <G4VSensitiveDetector.hh>
0030 
0031 // C/C++ include files
0032 #include <stdexcept>
0033 
0034 #include "G4OpticalParameters.hh"
0035 #include "G4OpticalPhoton.hh"
0036 
0037 #ifdef DD4HEP_USE_GEANT4_UNITS
0038 #define MM_2_CM 1.0
0039 #else
0040 #define MM_2_CM 0.1
0041 #endif
0042 
0043 namespace dd4hep  {
0044   namespace sim  {
0045     /// Print volume ID
0046     void _print_volumeid(const std::string& tag, const IDDescriptor& id, DDSegmentation::VolumeID volID)  {
0047       if( id.isValid() )  {
0048         std::string value = id.str(volID);
0049         printout(ALWAYS, tag, "Volume ID: %016llX -> %s", volID, value.c_str());
0050         return;
0051       }
0052       printout(ALWAYS, tag, "Volume ID: %016llX [no ID descriptor]", volID);
0053     }
0054 
0055     /// Print volume ID
0056     void _print_volumeid(const Geant4Sensitive* action, const char* tag, DDSegmentation::VolumeID volID, double ene=-1e0)  {
0057       SensitiveDetector sensitive = action->sensitiveDetector();
0058       char text[64];
0059       text[0] = 0;
0060       if( ene > 0e0 )  {
0061         ::snprintf(text, sizeof(text), "Deposit: %12.3e GeV", ene/1e9);
0062       }
0063       if( sensitive.isValid() )  {
0064         Readout readout = sensitive.readout();
0065         if( readout.isValid() )  {
0066           IDDescriptor id = readout.idSpec();
0067           if( id.isValid() )  {
0068             std::string value = id.str(volID);
0069             action->always("%-16s %016llX -> %s %s", tag, volID, value.c_str(), text);
0070             return;
0071           }
0072           action->always("%-16s %016llX -> Readout: %s [no ID descriptor] %s", tag, volID, readout.name(), text);
0073           return;
0074         }
0075         action->always("%-16s %016llX -> Sensitive: %s [no readout] %s", volID, sensitive.name(), text);
0076         return;
0077       }
0078       action->always("%-16s %016llX [internal error: no sensitive detectector] %s", volID, text);
0079     }
0080   }
0081 }
0082 
0083 using namespace dd4hep::sim;
0084 
0085 namespace {
0086 
0087 #if 0
0088   Geant4ActionSD* _getSensitiveDetector(const std::string& name) {
0089     G4SDManager* mgr = G4SDManager::GetSDMpointer();
0090     G4VSensitiveDetector* sd = mgr->FindSensitiveDetector(name);
0091     if (0 == sd) {
0092       dd4hep::except("Geant4Sensitive", "DDG4: You requested to configure actions "
0093                      "for the sensitive detector %s,\nDDG4: which is not known to Geant4. "
0094                      "Are you sure you already converted the geometry?", name.c_str());
0095     }
0096     Geant4ActionSD* action_sd = dynamic_cast<Geant4ActionSD*>(sd);
0097     if (0 == action_sd) {
0098       throw dd4hep::except("Geant4Sensitive", "DDG4: You may only configure actions "
0099                            "for sensitive detectors of type Geant4ActionSD.\n"
0100                            "DDG4: The sensitive detector of %s is of type %s, which is incompatible.", name.c_str(),
0101                            typeName(typeid(*sd)).c_str());
0102     }
0103     return action_sd;
0104   }
0105 #endif
0106 }
0107 
0108 /// Standard action constructor
0109 Geant4ActionSD::Geant4ActionSD(const std::string& nam)
0110   : Geant4Action(0, nam) {
0111   InstanceCount::increment(this);
0112 }
0113 
0114 /// Default destructor
0115 Geant4ActionSD::~Geant4ActionSD() {
0116   InstanceCount::decrement(this);
0117 }
0118 
0119 /// Standard constructor
0120 Geant4Filter::Geant4Filter(Geant4Context* ctxt, const std::string& nam)
0121   : Geant4Action(ctxt, nam) {
0122   InstanceCount::increment(this);
0123 }
0124 
0125 /// Standard destructor
0126 Geant4Filter::~Geant4Filter() {
0127   InstanceCount::decrement(this);
0128 }
0129 
0130 /// Filter action. Return true if hits should be processed
0131 bool Geant4Filter::operator()(const G4Step*) const {
0132   return true;
0133 }
0134 
0135 /// Filter action. Return true if hits should be processed
0136 bool Geant4Filter::operator()(const Geant4FastSimSpot*) const {
0137   except("The filter action %s does not support the GFLASH/FastSim interface for Geant4.", c_name());
0138   return false;
0139 }
0140 
0141 /// Constructor. The detector element is identified by the name
0142 Geant4Sensitive::Geant4Sensitive(Geant4Context* ctxt, const std::string& nam, DetElement det, Detector& det_ref)
0143   : Geant4Action(ctxt, nam), m_detDesc(det_ref), m_detector(det)
0144 {
0145   InstanceCount::increment(this);
0146   if (!det.isValid()) {
0147     except("DDG4: Detector element for %s is invalid.", nam.c_str());
0148   }
0149   declareProperty("UseVolumeManager", m_useVolumeManager = true);
0150   declareProperty("HitCreationMode",  m_hitCreationMode = SIMPLE_MODE);
0151   declareProperty("DebugVolumeID",    m_debugVolumeID = false);
0152   m_sequence     = context()->kernel().sensitiveAction(m_detector.name());
0153   m_sensitive    = m_detDesc.sensitiveDetector(det.name());
0154   m_readout      = m_sensitive.readout();
0155   m_segmentation = m_readout.segmentation();
0156 }
0157 
0158 /// Standard destructor
0159 Geant4Sensitive::~Geant4Sensitive() {
0160   m_filters(&Geant4Filter::release);
0161   m_filters.clear();
0162   InstanceCount::decrement(this);
0163 }
0164 
0165 /// Get the detector identifier (DetElement::id())
0166 int Geant4Sensitive::id()  const  {
0167   return this->m_detector.id();
0168 }
0169 
0170 /// Add an actor responding to all callbacks. Sequence takes ownership.
0171 void Geant4Sensitive::adoptFilter(Geant4Action* action)   {
0172   Geant4Filter* filter = dynamic_cast<Geant4Filter*>(action);
0173   adopt(filter);
0174 }
0175 
0176 /// Add an actor responding to all callbacks. Sequence takes ownership.
0177 void Geant4Sensitive::adopt(Geant4Filter* filter) {
0178   if (filter) {
0179     filter->addRef();
0180     m_filters.add(filter);
0181     return;
0182   }
0183   except("Attempt to add invalid sensitive filter!");
0184 }
0185 
0186 /// Add an actor responding to all callbacks. Sequence takes ownership.
0187 void Geant4Sensitive::adoptFilter_front(Geant4Action* action)   {
0188   Geant4Filter* filter = dynamic_cast<Geant4Filter*>(action);
0189   adopt_front(filter);
0190 }
0191 
0192 /// Add an actor responding to all callbacks. Sequence takes ownership.
0193 void Geant4Sensitive::adopt_front(Geant4Filter* filter) {
0194   if (filter) {
0195     filter->addRef();
0196     m_filters.add_front(filter);
0197     return;
0198   }
0199   except("Attempt to add invalid sensitive filter!");
0200 }
0201 
0202 /// Callback before hit processing starts. Invoke all filters.
0203 bool Geant4Sensitive::accept(const G4Step* step) const {
0204   bool (Geant4Filter::*filter)(const G4Step*) const = &Geant4Filter::operator();
0205   bool result = m_filters.filter(filter, step);
0206   return result;
0207 }
0208 
0209 /// GFLASH/FastSim interface: Callback before hit processing starts. Invoke all filters.
0210 bool Geant4Sensitive::accept(const Geant4FastSimSpot* spot) const {
0211   bool (Geant4Filter::*filter)(const Geant4FastSimSpot*) const = &Geant4Filter::operator();
0212   bool result = m_filters.filter(filter, spot);
0213   return result;
0214 }
0215 
0216 /// Access to the sensitive detector object
0217 void Geant4Sensitive::setDetector(Geant4ActionSD* sens_det) {
0218   m_sensitiveDetector = sens_det;
0219 }
0220 
0221 /// Access to the sensitive detector object
0222 Geant4ActionSD& Geant4Sensitive::detector() const {
0223   if (m_sensitiveDetector)
0224     return *m_sensitiveDetector;
0225   //m_sensitiveDetector = _getSensitiveDetector(m_detector.name());
0226   //if (  m_sensitiveDetector ) return *m_sensitiveDetector;
0227   except("DDG4: The sensitive detector for action %s was not properly configured.", name().c_str());
0228   throw std::runtime_error("Geant4Sensitive::detector");
0229 }
0230 
0231 /// Access to the hosting sequence
0232 Geant4SensDetActionSequence& Geant4Sensitive::sequence() const {
0233   return *m_sequence;
0234 }
0235 
0236 /// Access the detector description object
0237 dd4hep::Detector& Geant4Sensitive::detectorDescription() const {
0238   return m_detDesc;
0239 }
0240 
0241 /// Access HitCollection container names
0242 const std::string& Geant4Sensitive::hitCollectionName(std::size_t which) const {
0243   return sequence().hitCollectionName(which);
0244 }
0245 
0246 /// Retrieve the hits collection associated with this detector by its serial number
0247 Geant4HitCollection* Geant4Sensitive::collection(std::size_t which) {
0248   return sequence().collection(which);
0249 }
0250 
0251 /// Retrieve the hits collection associated with this detector by its collection identifier
0252 Geant4HitCollection* Geant4Sensitive::collectionByID(std::size_t id) {
0253   return sequence().collectionByID(id);
0254 }
0255 
0256 /// Define collections created by this sensitivie action object
0257 void Geant4Sensitive::defineCollections() {
0258 }
0259 
0260 /// Method invoked at the beginning of each event.
0261 void Geant4Sensitive::begin(G4HCofThisEvent* /* HCE */) {
0262 }
0263 
0264 /// Method invoked at the end of each event.
0265 void Geant4Sensitive::end(G4HCofThisEvent* /* HCE */) {
0266 }
0267 
0268 /// G4VSensitiveDetector interface: Method for generating hit(s) using the information of G4Step object.
0269 bool Geant4Sensitive::process(const G4Step* /* step */, G4TouchableHistory* /* history */) {
0270   return false;
0271 }
0272 
0273 /// GFLASH/FastSim interface: Method for generating hit(s) using the information of the Geant4FastSimSpot object.
0274 bool Geant4Sensitive::processFastSim(const Geant4FastSimSpot* /* spot */, G4TouchableHistory* /* history */) {
0275   except("The sensitive action %s does not support the GFLASH/FastSim interface for Geant4.", c_name());
0276   return false;
0277 }
0278 
0279 /// Method is invoked if the event abortion is occured.
0280 void Geant4Sensitive::clear(G4HCofThisEvent* /* HCE */) {
0281 }
0282 
0283 /// Mark the track to be kept for MC truth propagation during hit processing
0284 void Geant4Sensitive::mark(const G4Track* track) const  {
0285   Geant4MonteCarloTruth* truth = context()->event().extension<Geant4MonteCarloTruth>(false);
0286   if ( truth ) truth->mark(track);
0287 }
0288 
0289 /// Mark the track of this step to be kept for MC truth propagation during hit processing
0290 void Geant4Sensitive::mark(const G4Step* step) const  {
0291   Geant4MonteCarloTruth* truth = context()->event().extension<Geant4MonteCarloTruth>(false);
0292   if ( truth ) truth->mark(step);
0293 }
0294 
0295 /// Returns the volumeID of the sensitive volume corresponding to the step
0296 long long int Geant4Sensitive::volumeID(const G4Step* step) {
0297   VolumeID volID = m_detector.id();
0298   if( this->useVolumeManager() )  {
0299     Geant4StepHandler   stepH(step);
0300     Geant4VolumeManager volMgr = Geant4Mapping::instance().volumeManager();
0301     volID = volMgr.volumeID(stepH.preTouchable());
0302     if( this->m_debugVolumeID )  {
0303       _print_volumeid(this, "Volume ID", volID, step->GetTotalEnergyDeposit());
0304     }
0305   }
0306   return volID;
0307 }
0308 
0309 /// Returns the volumeID of the sensitive volume corresponding to the touchable history
0310 long long int Geant4Sensitive::volumeID(const G4VTouchable* touchable) {
0311   VolumeID volID = m_detector.id();
0312   if( this->useVolumeManager() )  {
0313     Geant4VolumeManager volMgr = Geant4Mapping::instance().volumeManager();
0314     volID= volMgr.volumeID(touchable);
0315     if( this->m_debugVolumeID )  {
0316       _print_volumeid(this, "Volume ID", volID);
0317     }
0318   }
0319   return volID;
0320 }
0321 
0322 /// Returns the cellID(volumeID+local coordinate encoding) of the sensitive volume corresponding to the step
0323 long long int Geant4Sensitive::cellID(const G4Step* step)  {
0324   VolumeID volID = m_detector.id();
0325   if( this->useVolumeManager() )  {
0326     Geant4StepHandler h(step);
0327     Geant4VolumeManager volMgr = Geant4Mapping::instance().volumeManager();
0328     bool UsePostStepOnly = G4OpticalParameters::Instance() &&
0329       G4OpticalParameters::Instance()->GetBoundaryInvokeSD() &&
0330       (step->GetTrack()->GetDefinition() == G4OpticalPhoton::Definition());
0331 
0332     volID = volMgr.volumeID(UsePostStepOnly? h.postTouchable() : h.preTouchable());
0333     if ( m_segmentation.isValid() )  {
0334       std::exception_ptr eptr;
0335       G4ThreeVector global = UsePostStepOnly? h.postPosG4() : 0.5 * (h.prePosG4()+h.postPosG4());
0336       G4ThreeVector local  = UsePostStepOnly? h.postTouchable()->GetHistory()->GetTopTransform().TransformPoint(global) :
0337         h.preTouchable()->GetHistory()->GetTopTransform().TransformPoint(global);
0338       Position loc(local.x()*MM_2_CM, local.y()*MM_2_CM, local.z()*MM_2_CM);
0339       Position glob(global.x()*MM_2_CM, global.y()*MM_2_CM, global.z()*MM_2_CM);
0340       try  {
0341         VolumeID cID = m_segmentation.cellID(loc, glob, volID);
0342         if( this->m_debugVolumeID )  {
0343           _print_volumeid(this, "Cell ID", cID, step->GetTotalEnergyDeposit());
0344         }
0345         return cID;
0346       }
0347       catch(const std::exception& e)   {
0348         eptr = std::current_exception();
0349         error("cellID: failed to access segmentation for VolumeID: %016lX [%ld]  [%s]", volID, volID, e.what());
0350         error("....... G4-local:   (%f, %f, %f) G4-global:   (%f, %f, %f)",
0351               local.x(), local.y(), local.z(), global.x(), global.y(), global.z());
0352         error("....... TGeo-local: (%f, %f, %f) TGeo-global: (%f, %f, %f)",
0353               loc.x(), loc.y(), loc.z(), glob.x(), glob.y(), glob.z());
0354         error("....... Pre-step:  %s  SD: %s", h.volName(h.pre), h.sdName(h.pre).c_str());
0355         if ( h.post )
0356           error("....... Post-step: %s  SD: %s", h.volName(h.post), h.sdName(h.post).c_str());
0357         std::rethrow_exception(std::move(eptr));
0358       }
0359     }
0360     else if( this->m_debugVolumeID )  {
0361       _print_volumeid(this, "Volume ID", volID, step->GetTotalEnergyDeposit());
0362     }
0363   }
0364   return volID;
0365 }
0366 
0367 /// Returns the cellID(volumeID+local coordinate encoding) of the sensitive volume corresponding to the touchable history
0368 long long int Geant4Sensitive::cellID(const G4VTouchable* touchable, const G4ThreeVector& global) {
0369   VolumeID volID = m_detector.id();
0370   if( this->useVolumeManager() )  {
0371     Geant4VolumeManager volMgr = Geant4Mapping::instance().volumeManager();
0372 
0373     volID = volMgr.volumeID(touchable);
0374     if ( m_segmentation.isValid() )  {
0375       std::exception_ptr eptr;
0376       G4ThreeVector local  = touchable->GetHistory()->GetTopTransform().TransformPoint(global);
0377       Position loc (local.x()*MM_2_CM, local.y()*MM_2_CM, local.z()*MM_2_CM);
0378       Position glob(global.x()*MM_2_CM, global.y()*MM_2_CM, global.z()*MM_2_CM);
0379       try  {
0380         VolumeID cID = m_segmentation.cellID(loc, glob, volID);
0381         if( this->m_debugVolumeID )  {
0382           _print_volumeid(this, "Cell ID", cID);
0383         }
0384         return cID;
0385       }
0386       catch(const std::exception& e)   {
0387         auto* pvol = touchable->GetVolume();
0388         auto* vol = pvol->GetLogicalVolume();
0389         auto* sd = vol->GetSensitiveDetector();
0390         eptr = std::current_exception();
0391         error("cellID: failed to access segmentation for VolumeID: %016lX [%ld]  [%s]", volID, volID, e.what());
0392         error("....... G4-local:   (%f, %f, %f) G4-global:   (%f, %f, %f)",
0393               local.x(), local.y(), local.z(), global.x(), global.y(), global.z());
0394         error("....... TGeo-local: (%f, %f, %f) TGeo-global: (%f, %f, %f)",
0395               loc.x(), loc.y(), loc.z(), glob.x(), glob.y(), glob.z());
0396         error("....... Touchable:  %s  SD: %s", vol->GetName().c_str(), sd ? sd->GetName().c_str() : "???");
0397         std::rethrow_exception(std::move(eptr));
0398       }
0399     }
0400     else if( this->m_debugVolumeID )  {
0401       _print_volumeid(this, "Volume ID", volID);
0402     }
0403   }
0404   return volID;
0405 }
0406 
0407 /// Standard constructor
0408 Geant4SensDetActionSequence::Geant4SensDetActionSequence(Geant4Context* ctxt, const std::string& nam)
0409   : Geant4Action(ctxt, nam), m_hce(0), m_detector(0)
0410 {
0411   m_needsControl = true;
0412   context()->sensitiveActions().insert(name(), this);
0413   /// Update the sensitive detector type, so that the proper instance is created
0414   m_sensitive = context()->detectorDescription().sensitiveDetector(nam);
0415   m_sensitiveType = m_sensitive.type();
0416   declareProperty("SensitiveType", m_sensitiveType);
0417   InstanceCount::increment(this);
0418 }
0419 
0420 /// Default destructor
0421 Geant4SensDetActionSequence::~Geant4SensDetActionSequence() {
0422   m_filters(&Geant4Filter::release);
0423   m_actors(&Geant4Sensitive::release);
0424   m_filters.clear();
0425   m_actors.clear();
0426   InstanceCount::decrement(this);
0427 }
0428 
0429 /// Set or update client context
0430 void Geant4SensDetActionSequence::updateContext(Geant4Context* ctxt)    {
0431   m_context = ctxt;
0432   m_actors.updateContext(ctxt);
0433   m_filters.updateContext(ctxt);
0434 }
0435 
0436 /// Add an actor responding to all callbacks. Sequence takes ownership.
0437 void Geant4SensDetActionSequence::adoptFilter(Geant4Action* action)   {
0438   Geant4Filter* filter = dynamic_cast<Geant4Filter*>(action);
0439   adopt(filter);
0440 }
0441 
0442 /// Add an actor responding to all callbacks
0443 void Geant4SensDetActionSequence::adopt(Geant4Sensitive* sensitive) {
0444   if (sensitive) {
0445     sensitive->addRef();
0446     m_actors.add(sensitive);
0447     return;
0448   }
0449   except("Attempt to add invalid sensitive actor!");
0450 }
0451 
0452 /// Add an actor responding to all callbacks. Sequence takes ownership.
0453 void Geant4SensDetActionSequence::adopt(Geant4Filter* filter) {
0454   if (filter) {
0455     filter->addRef();
0456     m_filters.add(filter);
0457     return;
0458   }
0459   except("Attempt to add invalid sensitive filter!");
0460 }
0461 
0462 /// Initialize the usage of a hit collection. Returns the collection identifier
0463 std::size_t Geant4SensDetActionSequence::defineCollection(Geant4Sensitive* owner, const std::string& collection_name, create_t func) {
0464   m_collections.emplace_back(collection_name, make_pair(owner,func));
0465   return m_collections.size() - 1;
0466 }
0467 
0468 /// Called at construction time of the sensitive detector to declare all hit collections
0469 std::size_t Geant4SensDetActionSequence::Geant4SensDetActionSequence::defineCollections(Geant4ActionSD* sens_det) {
0470   std::size_t count = 0;
0471   m_detector = sens_det;
0472   m_actors(&Geant4Sensitive::setDetector, sens_det);
0473   m_actors(&Geant4Sensitive::defineCollections);
0474   for (HitCollections::const_iterator i = m_collections.begin(); i != m_collections.end(); ++i) {
0475     sens_det->defineCollection((*i).first);
0476     ++count;
0477   }
0478   return count;
0479 }
0480 
0481 /// Access HitCollection container names
0482 const std::string& Geant4SensDetActionSequence::hitCollectionName(std::size_t which) const {
0483   if (which < m_collections.size()) {
0484     return m_collections[which].first;
0485   }
0486   static std::string blank = "";
0487   except("The collection name index for subdetector %s is out of range!", c_name());
0488   return blank;
0489 }
0490 
0491 /// Retrieve the hits collection associated with this detector by its serial number
0492 Geant4HitCollection* Geant4SensDetActionSequence::collection(std::size_t which) const {
0493   if (which < m_collections.size()) {
0494     int hc_id = m_detector->GetCollectionID(which);
0495     Geant4HitCollection* c = (Geant4HitCollection*) m_hce->GetHC(hc_id);
0496     if (c)
0497       return c;
0498     except("The collection index for subdetector %s is wrong!", c_name());
0499   }
0500   except("The collection name index for subdetector %s is out of range!", c_name());
0501   return 0;
0502 }
0503 
0504 /// Retrieve the hits collection associated with this detector by its collection identifier
0505 Geant4HitCollection* Geant4SensDetActionSequence::collectionByID(std::size_t id) const {
0506   Geant4HitCollection* c = (Geant4HitCollection*) m_hce->GetHC(id);
0507   if (c)
0508     return c;
0509   except("The collection index for subdetector %s is wrong!", c_name());
0510   return 0;
0511 }
0512 
0513 /// Callback before hit processing starts. Invoke all filters.
0514 bool Geant4SensDetActionSequence::accept(const G4Step* step) const {
0515   bool (Geant4Filter::*filter)(const G4Step*) const = &Geant4Filter::operator();
0516   bool result = m_filters.filter(filter, step);
0517   return result;
0518 }
0519 
0520 /// Callback before hit processing starts. Invoke all filters.
0521 bool Geant4SensDetActionSequence::accept(const Geant4FastSimSpot* spot) const {
0522   bool (Geant4Filter::*filter)(const Geant4FastSimSpot*) const = &Geant4Filter::operator();
0523   bool result = m_filters.filter(filter, spot);
0524   return result;
0525 }
0526 
0527 /// G4VSensitiveDetector interface: Method for generating hit(s) using the information of G4Step object.
0528 bool Geant4SensDetActionSequence::process(const G4Step* step, G4TouchableHistory* history) {
0529   bool result = false;
0530   for (Geant4Sensitive* sensitive : m_actors)  {
0531     if ( sensitive->accept(step) )
0532       result |= sensitive->process(step, history);
0533   }
0534   m_process(step, history);
0535   return result;
0536 }
0537 
0538 /// GFLASH/FastSim interface: Method for generating hit(s) using the information of the Geant4FastSimSpot object.
0539 bool Geant4SensDetActionSequence::processFastSim(const Geant4FastSimSpot* spot, G4TouchableHistory* history)  {
0540   bool result = false;
0541   for (Geant4Sensitive* sensitive : m_actors)  {
0542     if ( sensitive->accept(spot) )
0543       result |= sensitive->processFastSim(spot, history);
0544   }
0545   m_process(spot, history);
0546   return result;
0547 }
0548 
0549 /** G4VSensitiveDetector interface: Method invoked at the beginning of each event.
0550  *  The hits collection(s) created by this sensitive detector must
0551  *  be set to the G4HCofThisEvent object at one of these two methods.
0552  */
0553 void Geant4SensDetActionSequence::begin(G4HCofThisEvent* hce) {
0554   m_hce = hce;
0555   for (std::size_t count = 0; count < m_collections.size(); ++count) {
0556     const HitCollection& cr = m_collections[count];
0557     Geant4HitCollection* col = (*cr.second.second)(name(), cr.first, cr.second.first);
0558     int id = m_detector->GetCollectionID(count);
0559     m_hce->AddHitsCollection(id, col);
0560   }
0561   m_actors(&Geant4Sensitive::begin, m_hce);
0562   m_begin (m_hce);
0563 }
0564 
0565 /// G4VSensitiveDetector interface: Method invoked at the end of each event.
0566 void Geant4SensDetActionSequence::end(G4HCofThisEvent* hce) {
0567   m_end(hce);
0568   m_actors(&Geant4Sensitive::end, hce);
0569   // G4HCofThisEvent must be available until end-event. m_hce = 0;
0570 }
0571 
0572 /// G4VSensitiveDetector interface: Method invoked if the event was aborted.
0573 /** Hits collections created but not being set to G4HCofThisEvent
0574  *  at the event should be deleted.
0575  *  Collection(s) which have already set to G4HCofThisEvent
0576  *  will be deleted automatically.
0577  */
0578 void Geant4SensDetActionSequence::clear() {
0579   m_clear (m_hce);
0580   m_actors(&Geant4Sensitive::clear, m_hce);
0581 }
0582 
0583 /// Default destructor
0584 Geant4SensDetSequences::~Geant4SensDetSequences() {
0585   detail::releaseObjects(m_sequences);
0586   m_sequences.clear();
0587 }
0588 
0589 /// Access sequence member by name
0590 Geant4SensDetActionSequence* Geant4SensDetSequences::operator[](const std::string& nam) const {
0591   std::string n = "SD_Seq_" + nam;
0592   Members::const_iterator i = m_sequences.find(n);
0593   if (i != m_sequences.end())
0594     return (*i).second;
0595   except("Attempt to access undefined SensDetActionSequence: %s ", nam.c_str());
0596   return nullptr;
0597 }
0598 
0599 /// Access sequence member by name
0600 Geant4SensDetActionSequence* Geant4SensDetSequences::find(const std::string& name) const {
0601   std::string nam = "SD_Seq_" + name;
0602   Members::const_iterator i = m_sequences.find(nam);
0603   if (i != m_sequences.end())
0604     return (*i).second;
0605   return 0;
0606 }
0607 
0608 /// Insert sequence member
0609 void Geant4SensDetSequences::insert(const std::string& name, Geant4SensDetActionSequence* seq) {
0610   if (seq) {
0611     std::string nam = "SD_Seq_" + name;
0612     seq->addRef();
0613     m_sequences[nam] = seq;
0614     return;
0615   }
0616   except("Attempt to add invalid sensitive sequence with name:%s", name.c_str());
0617 }
0618 
0619 /// Clear the sequence list
0620 void Geant4SensDetSequences::clear()   {
0621   m_sequences.clear();
0622 }