Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-10 10:18:05

0001 #pragma once
0002 
0003 #include <map>
0004 
0005 class G4LogicalVolume;
0006 class G4RadiatorMaterial;
0007 class G4OpticalSurface;
0008 
0009 class CherenkovMirror;
0010 class CherenkovPhotonDetector;
0011 
0012 #include "BitMask.h"
0013 #include "CherenkovDetector.h"
0014 
0015 #define _STORE_ORPHAN_PHOTONS_    (0x00000001)
0016 #define _STORE_REFLECTION_POINTS_ (0x00000002)
0017 #define _STORE_REFRACTION_POINTS_ (0x00000003)
0018 
0019 namespace IRT2 {
0020 
0021 class CherenkovDetectorCollection: public BitMask {
0022  public:
0023   CherenkovDetectorCollection() {};
0024   // FIXME: populate the dtor, for completeness;
0025   ~CherenkovDetectorCollection() {};
0026 
0027   CherenkovDetector *AddNewDetector(const char *name) {
0028     auto det = new CherenkovDetector(name);
0029     m_Detectors[det->GetName()] = det;
0030 
0031     return det;
0032   };
0033   //void AddNewDetector(CherenkovDetector *det) {
0034   //m_Detectors[det->GetName()] = det;
0035   //};
0036 
0037   CherenkovRadiator *FindOrAddRadiator(CherenkovDetector *det, const char *name, const G4LogicalVolume *volume, 
0038                  const G4RadiatorMaterial *material) {
0039     auto radiator = FindRadiator(volume);
0040     // FIXME: check consistency;
0041     if (!radiator) {
0042       radiator = new CherenkovRadiator(volume, material);
0043       det->AddRadiator(name, radiator);
0044 
0045       m_RadiatorLookup[volume] = radiator;
0046     } //if
0047 
0048     return radiator;
0049   };
0050   CherenkovRadiator *AddFlatRadiator(CherenkovDetector *det, const char *name, CherenkovDetector::ud where, unsigned path, 
0051                      const G4LogicalVolume *volume, 
0052                      const G4RadiatorMaterial *material, const FlatSurface *surface, 
0053                      double thickness) {
0054     auto radiator = FindOrAddRadiator(det, name, volume, material);
0055 
0056     // Make a pair of local copies; they are stored in their respective class instances, 
0057     // therefore need two separate ones;
0058     {
0059       auto boundary = surface->_Clone(0.0, TVector3(0,0,1));
0060       boundary->Shift(( thickness/2)*surface->GetNormal());
0061       det->AddOpticalBoundary(where, path, new OpticalBoundary(radiator,                  boundary, true));
0062       radiator->m_Borders[path].first = boundary;
0063 
0064       // FIXME (?): in case of dRICH (and FRICH) this boundary is assigned by hand (a spherical
0065       // mirror surface), so it should kind of work;
0066       if (where == CherenkovDetector::Downstream && !det->GetContainerVolume()->GetRearSide(path))
0067     det->GetContainerVolume()->m_Borders[path].second = boundary;
0068     }
0069     {
0070       auto boundary = surface->_Clone(0.0, TVector3(0,0,1));
0071       boundary->Shift((-thickness/2)*surface->GetNormal());
0072       det->AddOpticalBoundary(where, path, new OpticalBoundary(det->GetContainerVolume(), boundary, true));
0073       radiator->m_Borders[path].second = boundary;
0074 
0075       // This will most likely be a temporary assignment; only "upstream" boundaries are of interest 
0076       // here since the "downstream" ones are essentially a sensor-side description;
0077       if (where == CherenkovDetector::Upstream) det->GetContainerVolume()->m_Borders[path].first = boundary;
0078     }    
0079 
0080     return radiator;
0081   };
0082   void AddRadiatorLogicalVolume(CherenkovRadiator *radiator, const G4LogicalVolume *lv) {
0083     radiator->AddLogicalVolume(lv);
0084     m_RadiatorLookup[lv] = radiator;
0085   };
0086 
0087   //inline void AddOrphanPhoton(OpticalPhoton *photon) { m_OrphanPhotons.push_back(photon); };
0088 
0089   void AddPhotonDetector(CherenkovDetector *det, const G4LogicalVolume *lv, 
0090              CherenkovPhotonDetector *pd) {
0091     // FIXME: a consistency check!;
0092     if (FindPhotonDetector(lv)) return;
0093 
0094     det->AddPhotonDetector(pd);
0095 
0096     m_PhotonDetectorLookup[lv] = pd;
0097   };
0098 
0099   //inline unsigned GetDetectorCount( void ) const { return m_Detectors.size(); };
0100 
0101   inline CherenkovRadiator *FindRadiator(const G4LogicalVolume *lv) {
0102     return (m_RadiatorLookup.find(lv) == m_RadiatorLookup.end() ? 0 : m_RadiatorLookup[lv]);
0103   };
0104   inline CherenkovMirror *FindMirror(const G4LogicalVolume *lv) {
0105     return (m_MirrorLookup.find(lv) == m_MirrorLookup.end() ? 0 : m_MirrorLookup[lv]);
0106   };
0107   inline void AddMirrorLookupEntry(const G4LogicalVolume *lv, CherenkovMirror *mirror) {
0108     m_MirrorLookup[lv] = mirror;
0109   };
0110   inline void AddPhotonDetectorLookupEntry(const G4LogicalVolume *lv, CherenkovPhotonDetector *pd) {
0111     m_PhotonDetectorLookup[lv] = pd;
0112   };
0113   inline CherenkovPhotonDetector *FindPhotonDetector(const G4LogicalVolume *lv) {
0114     return (m_PhotonDetectorLookup.find(lv) == m_PhotonDetectorLookup.end() ? 0 : m_PhotonDetectorLookup[lv]);
0115   };
0116 
0117   CherenkovRadiator *SetContainerVolume(CherenkovDetector *det, const char *name, unsigned path, 
0118                     const G4LogicalVolume *lv, 
0119                     const G4RadiatorMaterial *material, 
0120                     /*const*/ ParametricSurface *surface) { 
0121     auto radiator = FindOrAddRadiator(det, name, lv, material);
0122     // This is most likely a temporary assignment;
0123     radiator->m_Borders[path].first = surface;
0124 
0125     det->AddOpticalBoundary(CherenkovDetector::Upstream, path, new OpticalBoundary(FindRadiator(lv), surface, true));
0126     //det->SetContainerVolume(lv);
0127     det->SetContainerVolume(radiator);
0128 
0129     return radiator;
0130   };
0131 
0132   // FIXME: do it more efficient later;
0133   CherenkovDetector *GetDetectorByRadiator(const CherenkovRadiator *radiator) {
0134     for(auto detector: m_Detectors)
0135       for(auto ptr: detector.second->Radiators())
0136     if (ptr.second == radiator)
0137       return detector.second;
0138       
0139     return 0;
0140   };
0141   CherenkovDetector *GetDetector(const char *name) {
0142     if (m_Detectors.find(name) == m_Detectors.end()) return 0;
0143 
0144     return m_Detectors[name];
0145   };
0146   const std::map<TString, CherenkovDetector*> &GetDetectors( void ) const {
0147     return m_Detectors;
0148   }; 
0149 
0150   // The lookup tables are global of course since the same particle can hit radiators
0151   // in more than one detector;
0152  private:
0153   std::map<const G4LogicalVolume*, CherenkovRadiator*>       m_RadiatorLookup;         //!
0154   std::map<const G4LogicalVolume*, CherenkovMirror*>         m_MirrorLookup;           //!
0155   std::map<const G4LogicalVolume*, CherenkovPhotonDetector*> m_PhotonDetectorLookup;   //!
0156 
0157   std::map<TString, CherenkovDetector*> m_Detectors;
0158   
0159   //std::vector<OpticalPhoton*> m_OrphanPhotons; 
0160 
0161 #ifndef DISABLE_ROOT_IO
0162   ClassDef(CherenkovDetectorCollection, 3);
0163 #endif
0164 };
0165 
0166 } // namespace IRT2