#include "PndRichGeo.h" #include "FairGeoNode.h" #include "TRandom.h" ClassImp(PndRichGeo) // ----- Default constructor ------------------------------------------- PndRichGeo::PndRichGeo() : FairGeoSet() { // Constructor // fName has to be the name used in the geometry for all volumes. // If there is a mismatch the geometry cannot be build. fName="rich"; maxSectors=0; maxModules=10; fRichOffset = TVector3( 0, 0, 700-35-10/*+50*/ ); //-70 fAlBoxSize = TVector3( 600, 600, 100 ); fAlBoxWallThickness = 0.05; fAerogelSize = TVector3( 0*590+1*290, 0*590+1*120, 4 ); fAerogelOffset = TVector3( 0, 0, 1 ); fnOpt = std::vector(1,1.05); fAerogelLayers = std::vector(1,1); fAngleExtansionInner = 1.0; fAngleExtansionOuter = 1.0; fMirrorCurvature = 20; fAngleOfMirrorPosition = 50; fMirrorThickness = 0.1; fMirrorLength = 290; fPhDetLength = 290; fPhDetThickness = 3; fBeamPipeHoleX = 10; fBeamPipeHoleY = 10; fMirrorType = 0; fFlatMirrorZ = std::vector(2); fFlatMirrorY = std::vector(2); fFlatMirrorZGlob = std::vector(2); fFlatMirrorYGlob = std::vector(2); fPhDetZ = std::vector(2); fPhDetY = std::vector(2); fSenseLevel = 4; fSensorsPerDevice = 1<<(fSenseLevel-1); // number of sensores per device in one direction // Quantum efficiency fPhDetDev = 0; // pde_dpc3200_22.dat fPhDetDev = 1; // pde_h12700.dat std::string workdir(getenv( "VMCWORKDIR" )); std::string effFileName = workdir; Double_t keff; if (fPhDetDev==0) { effFileName += "/rich/pde_dpc3200_22.dat"; fPhDetSizeX = 3.26; fPhDetSizeY = 3.26; fPhDetGapX = 0.01; fPhDetGapY = 0.01; keff = 1.7; // measured difference MC-EXP } if (fPhDetDev==1) { effFileName += "/rich/pde_h12700.dat"; fPhDetSizeX = 5.2; fPhDetSizeY = 5.2; fPhDetGapX = 0.01; fPhDetGapY = 0.01; keff = 1; } std::ifstream from( effFileName.c_str() ); Double_t wli, pdei; from >> wli >> pdei; while( !from.eof() ) { fWlPhoton.push_back(wli); // nm fPDE.push_back(pdei/100.0/keff); // %/100 from >> wli >> pdei; }; fPhDetEff = new TGraph(fWlPhoton.size(),fWlPhoton.data(),fPDE.data()); } void PndRichGeo::init(size_t ver0) { size_t nRefInd = (ver0%100000)/1000; size_t nlayers = (ver0%1000)/100; size_t ver = ver0%100; nlayers = nlayers ? nlayers : 3; double ka1 = angleExtansionInner(); double ka2 = angleExtansionOuter(); double beta = mirrorCurvature(); double alpha = angleOfMirrorPosition(); // Mirror double za = richOffset().Z() /*+ alBoxWallThickness()*/ + aerogelOffset().Z(); double ya = aerogelSize().Y()/2; double wa = aerogelSize().Z(); double yp1 = ya + wa; double zp1 = wa; alpha = alpha < 45 - beta ? alpha : 45 -beta; alpha *= M_PI/180; beta *= M_PI/180; double thetaCh = acos(1/nOpt()[0]); double theta = atan(ya/za); double alpha1 = 2*(alpha+beta) - ka1*thetaCh; double alpha2 = 2*(alpha-beta) + ka2*thetaCh + theta; double alpham = (alpha1+alpha2)/2; double zm1 = zp1 + yp1/tan(alpha1); double ym1 = 0; double zm2 = (zm1+ya*tan(alpha))/(1-tan(theta+ka2*thetaCh)*tan(alpha)); double ym2 = (zm2-zm1)/tan(alpha); double zp2 = ((ym2-yp1+zm2*tan(alpha2))*tan(alpham)+zp1)/(1+tan(alpha2)*tan(alpham)); double yp2 = yp1 + (zp2-zp1)/tan(alpham); if (yp2= fWlPhoton.front() )&&( wl <= fWlPhoton.back() )) ? fPhDetEff->Eval(wl) : 0 ; } TVector3 PndRichGeo::PhDetPositionLocal(TVector3 pos) { //photodetector: cell size if (pos.Y()>=0) { TVector3 dP = pos - fPhDetP0U; return TVector3(dP*fPhDetNxU,dP*fPhDetNyU,dP*fPhDetNzU); } else { TVector3 dP = pos - fPhDetP0D; return TVector3(dP*fPhDetNxD,dP*fPhDetNyD,dP*fPhDetNzD); } } TVector3 PndRichGeo::PhDetPositionGlobal(TVector3 pos) { if (pos.Y()>=0) return fPhDetP0U + pos.X()*fPhDetNxU + pos.Y()*fPhDetNyU + pos.Z()*fPhDetNzU; else return fPhDetP0D + pos.X()*fPhDetNxD + pos.Y()*fPhDetNyD + pos.Z()*fPhDetNzD; } TVector3 PndRichGeo::PositionDiscretization(TVector3 pos, bool cell) { // full variant TVector3 posl = PhDetPositionLocal(pos); Double_t xl = posl.X(); Double_t yl = posl.Y(); // to local coordinate system of the device Double_t wx = fPhDetSizeX + fPhDetGapX; UInt_t Ix = xl/wx + fPhDetNumX/2; Double_t xlc = wx*(Ix + 0.5 - fPhDetNumX/2); Double_t wy = fPhDetSizeY + fPhDetGapY; UInt_t Iy = yl/wy + fPhDetNumY/2; Double_t ylc = wy*(Iy + 0.5 - fPhDetNumY/2); xl -= xlc; yl -= ylc; // Double_t xc[4]; Double_t yc[4]; Double_t dxc[4]; Double_t dyc[4]; Double_t xcl3[2]; Double_t ycl3[2]; Double_t xcl2; Double_t ycl2; Double_t dx; Double_t dy; bool gep; // dpc3200-22 // http://www.digitalphotoncounting.com/wp-content/uploads/PDPC_leaflet_A4_2015_10.pdf if (fPhDetDev==0) { // pixel center x,y, pixel half widths wx,wy xc[0] = 0.23; yc[0] = 0.195; dxc[0] = 0.16; dyc[0] = 0.19; xc[1] = 0.56; yc[1] = 0.585; dxc[1] = 0.16; dyc[1] = 0.19; xc[2] = 1.02; yc[2] = 0.975; dxc[2] = 0.16; dyc[2] = 0.19; xc[3] = 1.35; yc[3] = 1.365; dxc[3] = 0.16; dyc[3] = 0.19; // die center x,y xcl3[0] = 0.395; ycl3[0] = 0.39; // {(xc[0]+xc[1])/2,(xc[2]+xc[3])/2} xcl3[1] = 1.185; ycl3[1] = 1.17; // {(yc[0]+yc[1])/2,(yc[2]+yc[3])/2} // quarter center x,y xcl2 = 0.79; // (xc[1]+xc[2])/2 ycl2 = 0.78; // (yc[1]+yc[2])/2 // dx = 0.395; dy = 0.39; // geometrical efficiency of pixel (cell filling) gep = gRandom->Uniform()<=(cell?0.74:1); } // h12700 // https://www.hamamatsu.com/resources/pdf/etd/H12700_TPMH1348E.pdf if (fPhDetDev==1) { // pixel center x,y, pixel half widths wx,wy xc[0] = 0.3; yc[0] = 0.3; dxc[0] = 0.3; dyc[0] = 0.3; xc[1] = 0.9; yc[1] = 0.9; dxc[1] = 0.3; dyc[1] = 0.3; xc[2] = 1.5; yc[2] = 1.5; dxc[2] = 0.3; dyc[2] = 0.3; xc[3] = 2.1125; yc[3] = 2.1125; dxc[3] = 0.3125; dyc[3] = 0.3125; // die center x,y xcl3[0] = 0.6; ycl3[0] = 0.6; // {(xc[0]+xc[1])/2,(xc[2]+xc[3])/2} xcl3[1] = 1.8125; ycl3[1] = 1.8125; // {(yc[0]+yc[1])/2,(yc[2]+yc[3])/2} // quarter center x,y xcl2 = 1.2125; // ~(xc[1]+xc[2])/2 ycl2 = 1.2125; // ~(yc[1]+yc[2])/2 // dx = 0.6; dy = 0.6; // geometrical efficiency of pixel (cell filling) gep = true; } Int_t sx = xl>0?1:-1; Int_t sy = yl>0?1:-1; UInt_t ix = (sx*xl)/dx; UInt_t iy = (sy*yl)/dy; ix = ix>3?3:ix; iy = iy>3?3:iy; //pixel level = 4 Double_t hx = sx*xc[ix]; Double_t hy = sy*yc[iy]; if ((std::fabs(xl-hx)0 ? dX : fdX; Double_t dY_ = dY>0 ? dY : fdY; Double_t dZ_ = dZ>0 ? dZ : fdZ; Double_t x = pos.X(); Double_t y = pos.Y(); Double_t z = pos.Z(); if (x&&dX) x = ((int)(x/dX_) + x/std::fabs(x)/2)*dX_; if (y&&dY) y = ((int)(y/dY_) + y/std::fabs(y)/2)*dY_; if (z&&dZ) z = ((int)(z/dZ_) + z/std::fabs(z)/2)*dZ_; return TVector3(x,y,z); } UInt_t PndRichGeo::IndexX(TVector3 pos) { if (pos!=fSensorPosition) PositionDiscretization(pos,false); return fSensorIndexX; //return (int)((pos.X()+fdX*fiXmax/2)/fdX); } UInt_t PndRichGeo::IndexY(TVector3 pos) { if (pos!=fSensorPosition) PositionDiscretization(pos,false); return fSensorIndexY; //return (int)((pos.Y()+fdY*fiXmax/2)/fdY); } TVector3 PndRichGeo::PixelPositionLocal(UInt_t ix, UInt_t iy) { Double_t x = ix*fdX-fiXmax*fdX/2+0.5*fdX; Double_t y = iy*fdY-fiYmax*fdY/2+0.5*fdY; return TVector3(x,y,0); } TVector3 PndRichGeo::PixelPositionGlobal(UInt_t ix, UInt_t iy) { return PhDetPositionGlobal(PixelPositionLocal(ix,iy)); } // ------------------------------------------------------------------------- const char* PndRichGeo::getModuleName(Int_t m) { /** Returns the module name of PndRich number m Setting PndRich here means that all modules names in the ASCII file should start with PndRich otherwise they will not be constructed */ sprintf(modName,"rich0%i",m+1); return modName; } const char* PndRichGeo::getEleName(Int_t m) { /** Returns the element name of Det number m */ sprintf(eleName,"rich0%i",m+1); return eleName; }