Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:55:23

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 #ifndef DDG4_GEANT4HITCOLLECTION_H
0014 #define DDG4_GEANT4HITCOLLECTION_H
0015 
0016 // Framework include files
0017 #include <DD4hep/Handle.h>
0018 #include <DDG4/ComponentUtils.h>
0019 #include <G4VHitsCollection.hh>
0020 #include <G4VHit.hh>
0021 
0022 // C/C++ include files
0023 #include <vector>
0024 #include <string>
0025 #include <climits>
0026 #include <typeinfo>
0027 #include <stdexcept>
0028 
0029 /// Namespace for the AIDA detector description toolkit
0030 namespace dd4hep {
0031 
0032   /// Namespace for the Geant4 based simulation part of the AIDA detector description toolkit
0033   namespace sim {
0034 
0035     // Forward declarations
0036     class Geant4Sensitive;
0037     class Geant4HitCollection;
0038     class Geant4HitWrapper;
0039 
0040     /// Generic wrapper class for hit structures created in Geant4 sensitive detectors
0041     /**
0042      *  Default base class for all geant 4 created hits.
0043      *  The hit is stored in an opaque way and can be accessed by the
0044      *  collection.
0045      *
0046      *  \author  M.Frank
0047      *  \version 1.0
0048      *  \ingroup DD4HEP_SIMULATION
0049      */
0050     class Geant4HitWrapper: public G4VHit {
0051     private:
0052     public:
0053       /// Helper class to indicate invalid hit wrappers or containers.
0054       class InvalidHit {
0055       public:
0056         virtual ~InvalidHit();
0057       };
0058 
0059       /// Generic type manipulation class for generic hit structures created in Geant4 sensitive detectors
0060       /**
0061        *  \author  M.Frank
0062        *  \version 1.0
0063        *  \ingroup DD4HEP_SIMULATION
0064        */
0065       class HitManipulator {
0066       public:
0067         typedef std::pair<void*, HitManipulator*> Wrapper;
0068 #ifdef __CINT__
0069         const ComponentCast* cast;
0070         const ComponentCast* vec_type;
0071 #else
0072         const ComponentCast& cast;
0073         const ComponentCast& vec_type;
0074 #endif
0075         /// Initializing Constructor
0076         HitManipulator(const ComponentCast& c, const ComponentCast& v);
0077         /// Default destructor
0078         ~HitManipulator();
0079         /// Check pointer to be of proper type
0080         template <typename TYPE> Wrapper castHit(TYPE* obj) {
0081           if (obj) {
0082             ComponentCast& me = ComponentCast::instance<TYPE>();
0083             Wrapper wrap(obj, this);
0084             if (&cast == &me) {
0085               return wrap;
0086             }
0087             // Need to ensure that the container types are the same!
0088             wrap.first = me.apply_dynCast(cast, obj);
0089             return wrap;
0090           }
0091           throw std::runtime_error("Invalid hit pointer passed to collection!");
0092         }
0093         /// Static function to delete contained hits
0094         template <typename TYPE> static void deleteHit(Wrapper& obj) {
0095           TYPE* p = (TYPE*) obj.first;
0096           if (p)
0097             delete p;
0098           obj.first = 0;
0099         }
0100         template <typename TYPE> static HitManipulator* instance() {
0101           static HitManipulator hm(ComponentCast::instance<TYPE>(), ComponentCast::instance<std::vector<TYPE*> >());
0102           return &hm;
0103         }
0104       };
0105 
0106       typedef HitManipulator::Wrapper Wrapper;
0107     protected:
0108       /// Wrapper data
0109       mutable Wrapper m_data;
0110 
0111     public:
0112 
0113       /// Default constructor
0114       Geant4HitWrapper() : G4VHit() {
0115         m_data.second = manipulator<InvalidHit>();
0116         m_data.first = 0;
0117       }
0118       /// Copy constructor
0119       Geant4HitWrapper(const Geant4HitWrapper& v) : G4VHit() {
0120         m_data = v.m_data;
0121         v.m_data.first = 0;
0122         //v.release();
0123       }
0124       /// Copy constructor
0125       Geant4HitWrapper(const Wrapper& v) : G4VHit()  {
0126         m_data = v;
0127       }
0128       /// Default destructor
0129       virtual ~Geant4HitWrapper();
0130       /// Geant4 required object allocator
0131       void *operator new(size_t);
0132       /// Geant4 required object destroyer
0133       void operator delete(void *ptr);
0134       /// Pointer/Object release
0135       void* release();
0136       /// Release data for copy
0137       Wrapper releaseData();
0138       /// Access to cast grammar
0139       HitManipulator* manip() const {
0140         return m_data.second;
0141       }
0142       /// Pointer/Object access
0143       void* data() {
0144         return m_data.first;
0145       }
0146       /// Pointer/Object access (CONST)
0147       void* data() const {
0148         return m_data.first;
0149       }
0150       /// Generate manipulator object
0151       template <typename TYPE> static HitManipulator* manipulator() {
0152         return HitManipulator::instance<TYPE>();
0153       }
0154       /// Assignment transfers the pointer ownership
0155       Geant4HitWrapper& operator=(const Geant4HitWrapper& v) {
0156         if ( this != & v )  {
0157           m_data = v.m_data;
0158           v.m_data.first = 0;
0159           //v.release();
0160         }
0161         return *this;
0162       }
0163       /// Automatic conversion to the desired type
0164       template <typename TYPE> operator TYPE*() const {
0165         return (TYPE*) m_data.second->
0166           cast.apply_dynCast(ComponentCast::instance<TYPE>(),m_data.first);
0167         //cast.apply_downCast(ComponentCast::instance<TYPE>(),m_data.first);
0168       }
0169     };
0170 
0171     /// Generic hit container class using Geant4HitWrapper objects
0172     /**
0173      * Opaque hit collection.
0174      * This hit collection is for good reasons homomorph,
0175      * Polymorphism without an explicit type would only
0176      * confuse most users.
0177      *
0178      * Note:
0179      * This hit collection is optimized to search repeatedly the same cell using 
0180      *
0181      *  template <typename TYPE> TYPE* find(const Compare& cmp) const;
0182      *
0183      * by remembering the last search index.
0184      * The collection uses this optimization if the corresponding flag
0185      * OPTIMIZE_REPEATEDLOOKUP is set:
0186      *
0187      *   setOptimize(OPTIMIZE_REPEATEDLOOKUP);
0188      *
0189      * The last search index is automatically set to last object insertion,
0190      * if one happened between 2 search calls. For the typical use case,
0191      * there always contributions to the same hit are added, this should
0192      * reduce the lookup speed from O(n) to O(1).
0193      * This obviously only helps, if contributions to the same cell come in
0194      * sequence ie. from the same G4Track.
0195      *
0196      *
0197      *  \author  M.Frank
0198      *  \version 1.0
0199      *  \ingroup DD4HEP_SIMULATION
0200      */
0201     class Geant4HitCollection : public G4VHitsCollection {
0202     public:
0203       /** Local type declarations  */
0204       /// Hit wrapper
0205       typedef std::vector<Geant4HitWrapper>    WrappedHits;
0206       /// Hit manipulator
0207       typedef Geant4HitWrapper::HitManipulator Manip;
0208       /// Hit key map for fast random lookup
0209       typedef std::map<VolumeID, size_t>  Keys;
0210 
0211       /// Generic class template to compare/select hits in Geant4HitCollection objects
0212       /**
0213        *
0214        *  Base class for hit comparisons.
0215        *
0216        * \author  M.Frank
0217        * \version 1.0
0218        *  \ingroup DD4HEP_SIMULATION
0219        */
0220       class Compare {
0221       public:
0222         /// Default destructor
0223         virtual ~Compare();
0224         /// Comparison function
0225         virtual void* operator()(const Geant4HitWrapper& w) const = 0;
0226       };
0227 
0228       /// Union defining the hit collection flags for processing
0229       union CollectionFlags  {
0230         /// Full value
0231         unsigned long        value;
0232         /// Individual hit collection bits
0233         struct BitItems  {
0234           unsigned           repeatedLookup:1;
0235           unsigned           mappedLookup:1;
0236         }                    bits;
0237       };
0238 
0239     protected:
0240       /// The collection of hit pointers in the wrapped format
0241       WrappedHits                      m_hits;
0242       /// Handle to the sensitive detector
0243       Geant4Sensitive*                 m_detector;
0244       /// The type of the objects in this collection. Set by the constructor
0245       Manip*                           m_manipulator;
0246       /// Memorize for speedup the last searched hit
0247       size_t                           m_lastHit;
0248       /// Hit key map for fast random lookup
0249       Keys                             m_keys;
0250       /// Optimization flags
0251       CollectionFlags                  m_flags;
0252       
0253     protected:
0254       /// Notification to increase the instance counter
0255       void newInstance();
0256       /// Find hit in a collection by comparison of attributes
0257       void* findHit(const Compare& cmp);
0258       /// Find hit in a collection by comparison of the key
0259       Geant4HitWrapper* findHitByKey(VolumeID key);
0260       /// Release all hits from the Geant4 container and pass ownership to the caller
0261       void releaseData(const ComponentCast& cast, std::vector<void*>* result);
0262       /// Release all hits from the Geant4 container. Ownership stays with the container
0263       void getData(const ComponentCast& cast, std::vector<void*>* result);
0264 
0265     public:
0266       /// Enumeration for collection optimization types
0267       enum OptimizationFlags  {
0268         OPTIMIZE_NONE = 0,
0269         OPTIMIZE_REPEATEDLOOKUP = 1<<0,
0270         OPTIMIZE_MAPPEDLOOKUP   = 1<<1,
0271         OPTIMIZE_LAST
0272       };
0273 
0274       /// Initializing constructor (C++ version)
0275       template <typename TYPE>
0276       Geant4HitCollection(const std::string& det, const std::string& coll, Geant4Sensitive* sd)
0277         : G4VHitsCollection(det, coll), m_detector(sd),
0278           m_manipulator(Geant4HitWrapper::manipulator<TYPE>()),
0279           m_lastHit(ULONG_MAX)
0280       {
0281         newInstance();
0282         m_hits.reserve(200);
0283         m_flags.value = OPTIMIZE_REPEATEDLOOKUP;
0284       }
0285       /// Initializing constructor
0286       template <typename TYPE>
0287       Geant4HitCollection(const std::string& det, const std::string& coll, Geant4Sensitive* sd, const TYPE*)
0288         : G4VHitsCollection(det, coll), m_detector(sd),
0289           m_manipulator(Geant4HitWrapper::manipulator<TYPE>()),
0290           m_lastHit(ULONG_MAX)
0291       {
0292         newInstance();
0293         m_hits.reserve(200);
0294         m_flags.value = OPTIMIZE_NONE;
0295       }
0296       /// Default destructor
0297       virtual ~Geant4HitCollection();
0298       /// Type information of the object stored
0299       const ComponentCast& type() const;
0300       /// Type information of the vector type for extracting data
0301       const ComponentCast& vector_type() const;
0302       /// Clear the collection (Deletes all valid references to real hits)
0303       virtual void clear();
0304       /// Set optimization flags
0305       void setOptimize(int flag)  {
0306         m_flags.value |= flag;
0307       }
0308       /// Set the sensitive detector
0309       void setSensitive(Geant4Sensitive* detector)   {
0310         m_detector = detector;
0311       }
0312       /// Access the sensitive detector
0313       Geant4Sensitive* sensitive() const   {
0314         return m_detector;
0315       }
0316       /// Access individual hits
0317       virtual G4VHit* GetHit(size_t which) const {
0318         return (G4VHit*) &m_hits.at(which);
0319       }
0320       /// Access the collection size
0321       virtual size_t GetSize() const {
0322         return m_hits.size();
0323       }
0324       /// Access the hit wrapper
0325       Geant4HitWrapper& hit(size_t which) {
0326         return m_hits.at(which);
0327       }
0328       /// Access the hit wrapper (CONST)
0329       const Geant4HitWrapper& hit(size_t which) const {
0330         return m_hits.at(which);
0331       }
0332       /// Add a new hit with a check, that the hit is of the same type
0333       template <typename TYPE> void add(TYPE* hit_pointer) {
0334         Geant4HitWrapper w(m_manipulator->castHit(hit_pointer));
0335         m_lastHit = m_hits.size();
0336         m_hits.emplace_back(w);
0337       }
0338       /// Add a new hit with a check, that the hit is of the same type
0339       template <typename TYPE> void add(VolumeID key, TYPE* hit_pointer) {
0340         m_lastHit = m_hits.size();
0341         std::pair<Keys::iterator,bool> ret = m_keys.emplace(key,m_lastHit);
0342         if ( ret.second )  {
0343           Geant4HitWrapper w(m_manipulator->castHit(hit_pointer));
0344           m_hits.emplace_back(w);
0345           return;
0346         }
0347         throw std::runtime_error("Attempt to insert hit with same key to G4 hit-collection "+GetName());
0348       }
0349       /// Find hits in a collection by comparison of attributes
0350       template <typename TYPE> TYPE* find(const Compare& cmp) {
0351         return (TYPE*) findHit(cmp);
0352       }
0353       /// Find hits in a collection by comparison of key value
0354       template <typename TYPE> TYPE* findByKey(VolumeID key) {
0355         Keys::const_iterator i=m_keys.find(key);
0356         if ( i == m_keys.end() ) return 0;
0357         m_lastHit = (*i).second;
0358         TYPE* obj = m_hits.at(m_lastHit);
0359         return obj;
0360       }
0361       /// Release all hits from the Geant4 container and pass ownership to the caller
0362       template <typename TYPE> std::vector<TYPE*> releaseHits() {
0363         std::vector<TYPE*> vec;
0364         if (m_hits.size() != 0) {
0365           releaseData(ComponentCast::instance<TYPE>(), (std::vector<void*>*) &vec);
0366         }
0367         m_lastHit = ULONG_MAX;
0368         m_keys.clear();
0369         return vec;
0370       }
0371       /// Release all hits from the Geant4 container and pass ownership to the caller
0372       void releaseHitsUnchecked(std::vector<void*>& result);
0373 
0374       /// Release all hits from the Geant4 container. Ownership stays with the container
0375       template <typename TYPE> std::vector<TYPE*> getHits() {
0376         std::vector<TYPE*> vec;
0377         if (m_hits.size() != 0) {
0378           getData(ComponentCast::instance<TYPE>(), (std::vector<void*>*) &vec);
0379         }
0380         return vec;
0381       }
0382       /// Release all hits from the Geant4 container. Ownership stays with the container
0383       void getHitsUnchecked(std::vector<void*>& result);
0384     };
0385 
0386 
0387     /// Specialized hit selector based on the hit's position.
0388     /**
0389      *  Class for hit matching using the hit position.
0390      *
0391      *  \author  M.Frank
0392      *  \version 1.0
0393      *  \ingroup DD4HEP_SIMULATION
0394      */
0395     template<typename TYPE, typename POS> class PositionCompare : public Geant4HitCollection::Compare {
0396     public:
0397       const POS& pos;
0398       /// Constructor
0399       PositionCompare(const POS& p) : pos(p)  {      }
0400       /// Comparison function
0401       virtual void* operator()(const Geant4HitWrapper& w) const;
0402     };
0403 
0404     template <typename TYPE, typename POS>
0405     void* PositionCompare<TYPE,POS>::operator()(const Geant4HitWrapper& w) const {
0406       TYPE* h = w;
0407       return pos == h->position ? h : 0;
0408     }
0409 
0410     /// Specialized hit selector based on the hit's cell identifier.
0411     /**
0412      *  Class for hit matching using the hit's cell identifier.
0413      *
0414      *  \author  M.Frank
0415      *  \version 1.0
0416      *  \ingroup DD4HEP_SIMULATION
0417      */
0418     template<typename TYPE> class CellIDCompare : public Geant4HitCollection::Compare {
0419     public:
0420       long long int id;
0421       /// Constructor
0422       CellIDCompare(long long int i) : id(i) {      }
0423       /// Comparison function.
0424       virtual void* operator()(const Geant4HitWrapper& w) const;
0425     };
0426 
0427     template <typename TYPE>
0428     void* CellIDCompare<TYPE>::operator()(const Geant4HitWrapper& w) const {
0429       TYPE* h = w;
0430       if ( id == h->cellID )
0431         return h;
0432       return 0;
0433     }
0434 
0435   }    // End namespace sim
0436 }      // End namespace dd4hep
0437 
0438 #endif // DDG4_GEANT4HITCOLLECTION_H