Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-06-01 07:07:32

0001 
0002 #include <vector>
0003 #include <map>
0004 
0005 #include <TRef.h>
0006 #include <TString.h>
0007 
0008 #ifndef _CHERENKOV_DETECTOR_
0009 #define _CHERENKOV_DETECTOR_
0010 
0011 #include "CherenkovPhotonDetector.h"
0012 class CherenkovMirrorGroup;
0013 class OpticalBoundary;
0014 class G4LogicalVolume;
0015 
0016 class CherenkovDetector: public TObject {
0017  public:
0018  CherenkovDetector(const char *name = 0): /*m_ContainerVolume(0),*/ m_Name(name ? name : ""), 
0019     m_ReadoutCellMask(0x0)/*, m_SectorBoundaryOffset(0.0)*/ {};
0020   ~CherenkovDetector() {};
0021 
0022   void AddOpticalBoundary(unsigned sector, OpticalBoundary *boundary) {
0023     _m_OpticalBoundaries[sector].push_back(boundary);
0024   };
0025 
0026   void AddRadiator(const char *name, CherenkovRadiator *radiator) { 
0027     _m_Radiators[name] = radiator; 
0028   };
0029   //+void AddMirrorGroup(CherenkovMirrorGroup *mgroup) { m_MirrorGroups.push_back(mgroup); };
0030 
0031   // FIXME: "sector" is in fact *some* index rather than an azimuthal segmentation index;
0032   void AddPhotonDetector(CherenkovPhotonDetector *pd) { 
0033     m_PhotonDetectors.push_back(pd); 
0034   };
0035   void CreatePhotonDetectorInstance(unsigned sector, CherenkovPhotonDetector *pd, 
0036                     uint64_t icopy, ParametricSurface *surface) {
0037     auto irt = pd->AllocateIRT(sector, icopy);
0038 
0039     if (_m_OpticalBoundaries.find(sector) != _m_OpticalBoundaries.end())
0040       for(auto boundary: _m_OpticalBoundaries[sector])
0041     irt->AddOpticalBoundary(boundary);
0042  
0043     pd->AddItselfToOpticalBoundaries(irt, surface);
0044   };
0045 
0046   //unsigned GetRadiatorCount( void ) const { return m_Radiators.size(); };
0047   // FIXME: this kind of denies 'private' access;
0048   std::map<TString, CherenkovRadiator*> &Radiators( void ) { return _m_Radiators; };
0049 
0050   //std::vector<std::pair<unsigned, OpticalBoundary*>> _m_OpticalBoundaries;
0051   std::map<unsigned, std::vector<OpticalBoundary*>> _m_OpticalBoundaries;
0052   std::vector<CherenkovPhotonDetector*> m_PhotonDetectors; 
0053 
0054   //void SetContainerVolume(const G4LogicalVolume *lv) { m_ContainerVolume = lv; };
0055   //const G4LogicalVolume *m_ContainerVolume; //!
0056   void SetContainerVolume(CherenkovRadiator *radiator) { m_ContainerVolume = radiator; };
0057   CherenkovRadiator *GetContainerVolume( void ) const { 
0058     return dynamic_cast<CherenkovRadiator*>(m_ContainerVolume.GetObject()); };
0059   TRef m_ContainerVolume; 
0060 
0061   const char *GetName( void ) const { return m_Name.Data(); };
0062 
0063   CherenkovRadiator *GetRadiator(const char *name) {
0064     if (_m_Radiators.find(name) == _m_Radiators.end()) return 0;
0065 
0066     return _m_Radiators[name];
0067   };
0068 
0069   void SetReadoutCellMask(uint64_t mask) { m_ReadoutCellMask = mask; };
0070   inline uint64_t GetReadoutCellMask( void ) const { return m_ReadoutCellMask; };
0071 
0072   // FIXME: not at all clean (uses implicit phase assumptions); 
0073   unsigned GetSector(const TVector3 &pt) {
0074     // FIXME: may require tuning for a dual-mirror setup;
0075     unsigned nSectors = _m_OpticalBoundaries.size();
0076 
0077     // Either a single "sector" or sector structure not define yet -> return 0;
0078     if (nSectors <= 1) return 0;
0079 
0080     // FIXME: this offset is only defined by the way Chris positions sector #0; 
0081     double bin = 2*M_PI/nSectors, offset = -bin/2;
0082     
0083     return (unsigned)floor((pt.Phi() + 4*M_PI - offset)/bin) % nSectors;
0084     //return 0;
0085   };
0086 
0087   // FIXME: get rid of the second argument here;
0088   CherenkovRadiator *GuessRadiator(const TVector3 &x0, const TVector3 &n0) {
0089     // FIXME: may want to do a better check;
0090     if (_m_OpticalBoundaries.empty()) return 0;
0091 
0092     // Determine sector (in EIC DRICH terminology);
0093     unsigned isec = GetSector(x0);
0094 
0095     // Now loop through all radiators, and check boundaries in this sector;
0096     for(auto rptr: _m_Radiators) {
0097       const auto radiator = rptr.second;
0098  
0099       // Front and rear surfaces for this particular sector;
0100       auto s1 = radiator->GetFrontSide(isec);
0101       auto s2 = radiator->GetRearSide (isec);
0102 
0103       //printf("Here-A! %f %f %f\n", x0[0], x0[1], x0[2]);
0104       TVector3 from, to;
0105       // Go backwards and ignore surface orientation mismatch;
0106       bool b1 = s1->GetCrossing(x0, -1*n0, &from, false);
0107       bool b2 = s2->GetCrossing(x0,    n0, &to);
0108       //printf("Here-B %d %d\n", b1, b2);
0109       if (!b1 || !b2) continue;
0110 
0111       if ((x0 - from).Dot(to - x0) > 0.0) return radiator;
0112     } //for radiator
0113    
0114     // Seemingly this 3D point does not belong to any radiator;
0115     return 0;
0116   };
0117 
0118   // readout ID -> pixel position converter (for external usage)
0119   std::function<TVector3(long long int)> m_ReadoutIDToPosition; //!
0120 
0121  private:  
0122   TString m_Name;
0123   // This is needed for dd4hep cell index decoding;
0124   uint64_t m_ReadoutCellMask;
0125 
0126   //+double m_SectorBoundaryOffset;
0127 
0128   std::map<TString, CherenkovRadiator*> _m_Radiators;
0129   //+std::vector<CherenkovMirrorGroup*> m_MirrorGroups;
0130 
0131 #ifndef DISABLE_ROOT_IO
0132   ClassDef(CherenkovDetector, 5);
0133 #endif
0134 };
0135 
0136 #endif