CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/SimG4CMS/Calo/src/HFCherenkov.cc

Go to the documentation of this file.
00001 
00002 // File:  HFCherenkov.cc
00003 // Description: Generate Cherenkov photons for HF
00005 
00006 #include "SimG4CMS/Calo/interface/HFCherenkov.h"
00007 
00008 #include "G4Poisson.hh"
00009 #include "G4ParticleDefinition.hh"
00010 #include "G4NavigationHistory.hh"
00011 #include "TMath.h"
00012 
00013 //#define DebugLog
00014 
00015 HFCherenkov::HFCherenkov(edm::ParameterSet const & m_HF) {
00016 
00017   ref_index       = m_HF.getParameter<double>("RefIndex");
00018   lambda1         = ((m_HF.getParameter<double>("Lambda1"))/pow(double(10),7))*cm;
00019   lambda2         = ((m_HF.getParameter<double>("Lambda2"))/pow(double(10),7))*cm;
00020   aperture        = cos(asin(m_HF.getParameter<double>("Aperture")));
00021   apertureTrap    = cos(asin(m_HF.getParameter<double>("ApertureTrapped")));
00022   aperturetrapped = m_HF.getParameter<double>("CosApertureTrapped");
00023   gain            = m_HF.getParameter<double>("Gain");
00024   checkSurvive    = m_HF.getParameter<bool>("CheckSurvive");
00025   UseNewPMT       = m_HF.getParameter<bool>("UseR7600UPMT");
00026   sinPsimax       = m_HF.getUntrackedParameter<double>("SinPsiMax",0.5);
00027   fibreR          = m_HF.getUntrackedParameter<double>("FibreR",0.3)*mm;
00028 
00029   edm::LogInfo("HFShower") << "HFCherenkov:: initialised with ref_index " 
00030                            << ref_index << " lambda1/lambda2 (cm) " 
00031                            << lambda1/cm << "|" << lambda2/cm
00032                            << " aperture(total/trapped) " << aperture << "|"
00033                            << apertureTrap << "|" << aperturetrapped
00034                            << " Check photon survival in HF " << checkSurvive 
00035                            << " Gain " << gain << " useNewPMT " << UseNewPMT
00036                            << " FibreR " << fibreR;
00037 
00038   clearVectors();
00039 }
00040 
00041 HFCherenkov::~HFCherenkov() {}
00042 
00043 int HFCherenkov::computeNPhTrapped(double pBeta, 
00044                                    double u, double v, double w, 
00045                                    double step_length, double zFiber,
00046                                    double dose, int npe_Dose) {
00047 
00048   if (pBeta < (1/ref_index) || step_length < 0.0001) {return 0;}
00049 
00050   double uv = sqrt(u*u + v*v);
00051   int nbOfPhotons = computeNbOfPhotons(pBeta, step_length);
00052 
00053   if (nbOfPhotons < 0) {
00054     return 0;
00055   } else if (nbOfPhotons > 0) {
00056     double w_ph=0;
00057     for (int i = 0; i < nbOfPhotons; i++) {
00058       double rand     = G4UniformRand();
00059       double theta_C  = acos(1./(pBeta*ref_index));
00060       double phi_C    = 2*M_PI*rand;
00061       double sinTheta = sin(theta_C);
00062       double cosTheta = cos(theta_C);
00063       double cosPhi   = cos(phi_C);
00064       //photon momentum
00065       if (uv < 0.001) { // aligned with z-axis
00066         w_ph = cosTheta;
00067       } else { // general case
00068         w_ph = w * cosTheta  - sinTheta * cosPhi * uv;
00069       }
00070       if (w_ph > apertureTrap) { // phton trapped inside fiber
00071         npe_Dose += 1; 
00072       }
00073     }
00074   }
00075   int n_photons = npe_Dose;
00076   return n_photons;
00077 }
00078 
00079 int HFCherenkov::computeNPE(G4Step * aStep, G4ParticleDefinition* pDef,
00080                             double pBeta, double u, double v, double w,
00081                             double step_length, double zFiber,
00082                             double dose, int npe_Dose) {
00083 
00084   clearVectors();
00085   if (!isApplicable(pDef)) {return 0;}
00086   if (pBeta < (1/ref_index) || step_length < 0.0001) {
00087 #ifdef DebugLog
00088     LogDebug("HFShower") << "HFCherenkov::computeNPE: pBeta " << pBeta 
00089                          << " 1/mu " << (1/ref_index) << " step_length " 
00090                          << step_length;
00091 #endif
00092     return 0;
00093   }
00094    
00095   double uv = sqrt(u*u + v*v);
00096   int nbOfPhotons = computeNbOfPhotons(pBeta, step_length)
00097     *aStep->GetTrack()->GetWeight();
00098 #ifdef DebugLog
00099   LogDebug("HFShower") << "HFCherenkov::computeNPE: pBeta " << pBeta 
00100                        << " u/v/w " << u << "/" << v << "/" << w 
00101                        << " step_length " << step_length << " zFib " << zFiber 
00102                        << " nbOfPhotons " << nbOfPhotons;
00103 #endif
00104   if (nbOfPhotons < 0) {
00105     return 0;
00106   } else if (nbOfPhotons > 0) {
00107     G4StepPoint * preStepPoint = aStep->GetPreStepPoint();
00108     G4TouchableHandle theTouchable = preStepPoint->GetTouchableHandle();
00109     G4ThreeVector localprepos = theTouchable->GetHistory()->
00110       GetTopTransform().TransformPoint(aStep->GetPreStepPoint()->GetPosition());
00111     G4ThreeVector localpostpos = theTouchable->GetHistory()->
00112       GetTopTransform().TransformPoint(aStep->GetPostStepPoint()->GetPosition());
00113   
00114     double length=sqrt((localpostpos.x()-localprepos.x())*(localpostpos.x()-localprepos.x())
00115                        +(localpostpos.y()-localprepos.y())*(localpostpos.y()-localprepos.y()));
00116     double yemit = std::sqrt(fibreR*fibreR-length*length/4.);
00117 
00118     double u_ph=0,v_ph=0, w_ph=0;
00119     for (int i = 0; i < nbOfPhotons; i++) {
00120       double rand     = G4UniformRand();
00121       double theta_C  = acos(1./(pBeta*ref_index));
00122       double phi_C    = 2*M_PI*rand;
00123       double sinTheta = sin(theta_C);
00124       double cosTheta = cos(theta_C);
00125       double cosPhi   = cos(phi_C);
00126       double sinPhi   = sin(phi_C);
00127       //photon momentum
00128       if (uv < 0.001) { // aligned with z-axis
00129         u_ph = sinTheta * cosPhi ;
00130         v_ph = sinTheta * sinPhi;
00131         w_ph = cosTheta;
00132       } else { // general case
00133         u_ph = uv * cosTheta + sinTheta * cosPhi * w;
00134         v_ph = sinTheta * sinPhi;
00135         w_ph =  w * cosTheta - sinTheta * cosPhi * uv;
00136       }
00137       double r_lambda = G4UniformRand();
00138       double lambda0 = (lambda1 * lambda2) / (lambda2 - r_lambda *
00139                                               (lambda2 - lambda1));
00140       double lambda  = (lambda0/cm) * pow(double(10),7); // lambda is in nm
00141       wlini.push_back(lambda);
00142 #ifdef DebugLog
00143       LogDebug("HFShower") << "HFCherenkov::computeNPE: " << i << " lambda "
00144                            << lambda << " w_ph " << w_ph << " aperture "
00145                            << aperture;
00146 #endif
00147 // --------------
00148       double xemit=length*(G4UniformRand()-0.5);
00149       double gam=atan2(yemit,xemit);
00150       double eps=atan2(v_ph,u_ph);
00151       double sinBeta=sin(gam-eps);
00152       double rho=sqrt(xemit*xemit+yemit*yemit);
00153       double sinEta=rho/fibreR*sinBeta;
00154       double cosEta=sqrt(1.-sinEta*sinEta);
00155       double sinPsi=sqrt(1.-w_ph*w_ph);
00156       double cosKsi=cosEta*sinPsi;
00157 #ifdef DebugLog
00158       if (cosKsi < aperturetrapped && w_ph>0.) {
00159         LogDebug("HFShower") << "HFCherenkov::Trapped photon : " << u_ph << " "
00160                              << v_ph << " " << w_ph << " " << xemit << " "
00161                              << gam << " " << eps << " " << sinBeta << " "
00162                              << rho << " " << sinEta << " " << cosEta << " "
00163                              << " " << sinPsi << " " << cosKsi;
00164       } else {
00165         LogDebug("HFShower") << "HFCherenkov::Rejected photon : " << u_ph <<" "
00166                              << v_ph << " " << w_ph << " " << xemit << " "
00167                              << gam << " " << eps << " " << sinBeta << " "
00168                              << rho << " " << sinEta << " " << cosEta << " "
00169                              << " " << sinPsi << " " << cosKsi;
00170       }
00171 #endif
00172       if (cosKsi < aperturetrapped // photon trapped inside fiber
00173           && w_ph>0.               // and moves to PMT
00174           && sinPsi < sinPsimax) { // and is not reflected at fiber end
00175         wltrap.push_back(lambda);
00176         double prob_HF  = 1.0; //photon survived in HF
00177         double a0_inv   = 0.1234;  //meter^-1
00178         double prob_MX  = exp( - 0.5 * a0_inv ); //light mixer
00179         if (checkSurvive) {
00180           double a_inv = a0_inv + 0.14 * pow(dose,0.30);
00181           double z_meters = zFiber;
00182           prob_HF  = exp(-z_meters * a_inv ); //photon survived in HF
00183         }
00184         rand = G4UniformRand();
00185 #ifdef DebugLog
00186         LogDebug("HFShower") << "HFCherenkov::computeNPE: probHF " << prob_HF
00187                              << " prob_MX " << prob_MX << " Random " << rand 
00188                              << " Survive? " << (rand < (prob_HF * prob_MX));
00189 #endif
00190         if (rand < (prob_HF * prob_MX)) { // survived and sent to light mixer
00191           wlatten.push_back(lambda);
00192           rand = G4UniformRand();
00193           double effHEM = computeHEMEff(lambda);
00194 #ifdef DebugLog
00195           LogDebug("HFShower") << "HFCherenkov::computeNPE: w_ph " << w_ph 
00196                                << " effHEM " << effHEM << " Random " << rand 
00197                                << " Survive? " << (w_ph>0.997||(rand<effHEM));
00198 #endif
00199           if (w_ph>0.997 || (rand<effHEM)) { // survived HEM
00200             wlhem.push_back(lambda);
00201             double qEffic = computeQEff(lambda);
00202             rand = G4UniformRand();
00203 #ifdef DebugLog
00204             LogDebug("HFShower") << "HFCherenkov::computeNPE: qEffic "
00205                                  << qEffic << " Random " << rand
00206                                  << " Survive? " <<(rand < qEffic);
00207 #endif
00208             if (rand < qEffic) { // made photoelectron
00209               npe_Dose += 1;
00210               momZ.push_back(w_ph);
00211               wl.push_back(lambda);
00212               wlqeff.push_back(lambda);
00213             } // made pe
00214           } // passed HEM
00215         } // passed fiber
00216       } // end of  if(w_ph < w_aperture), trapped inside fiber
00217     }// end of ++NbOfPhotons
00218   } // end of if(NbOfPhotons)}
00219   int npe =  npe_Dose; // Nb of photoelectrons
00220 #ifdef DebugLog
00221   LogDebug("HFShower") << "HFCherenkov::computeNPE: npe " << npe;
00222 #endif
00223   return npe;
00224 }
00225 
00226 int HFCherenkov::computeNPEinPMT(G4ParticleDefinition* pDef, double pBeta, 
00227                                  double u, double v, double w, 
00228                                  double step_length){
00229   clearVectors();
00230   int npe_ = 0;
00231   if (!isApplicable(pDef)) {return 0;}
00232   if (pBeta < (1/ref_index) || step_length < 0.0001) {
00233 #ifdef DebugLog
00234     LogDebug("HFShower") << "HFCherenkov::computeNPEinPMT: pBeta " << pBeta 
00235                          << " 1/mu " << (1/ref_index) << " step_length " 
00236                          << step_length;
00237 #endif
00238     return 0;
00239   }
00240    
00241   double uv = sqrt(u*u + v*v);
00242   int nbOfPhotons = computeNbOfPhotons(pBeta, step_length);
00243 #ifdef DebugLog
00244   LogDebug("HFShower") << "HFCherenkov::computeNPEinPMT: pBeta " << pBeta 
00245                        << " u/v/w " << u << "/" << v << "/" << w 
00246                        << " step_length " << step_length  
00247                        << " nbOfPhotons " << nbOfPhotons;
00248 #endif   
00249   if (nbOfPhotons < 0) {
00250     return 0;
00251   } else if (nbOfPhotons > 0) {
00252     double w_ph=0;
00253     for (int i = 0; i < nbOfPhotons; i++) {
00254       double rand     = G4UniformRand();
00255       double theta_C  = acos(1./(pBeta*ref_index));
00256       double phi_C    = 2*M_PI*rand;
00257       double sinTheta = sin(theta_C);
00258       double cosTheta = cos(theta_C);
00259       double cosPhi   = cos(phi_C); 
00260       //photon momentum
00261       if (uv < 0.001) { // aligned with z-axis
00262         w_ph = cosTheta;
00263       } else { // general case
00264         w_ph = w * cosTheta - sinTheta * cosPhi * uv;
00265       }
00266       double r_lambda = G4UniformRand();
00267       double lambda0 = (lambda1 * lambda2) / (lambda2 - r_lambda *
00268                                               (lambda2 - lambda1));
00269       double lambda  = (lambda0/cm) * pow(double(10),7); // lambda is in nm
00270       wlini.push_back(lambda);
00271 #ifdef DebugLog
00272       LogDebug("HFShower") << "HFCherenkov::computeNPEinPMT: " <<i <<" lambda "
00273                            << lambda << " w_ph " << w_ph << " aperture " 
00274                            << aperture;
00275 #endif
00276       if (w_ph > aperture) { // phton trapped inside PMT glass
00277         wltrap.push_back(lambda);
00278         rand = G4UniformRand();
00279 #ifdef DebugLog
00280         LogDebug("HFShower") << "HFCherenkov::computeNPEinPMT: Random " << rand
00281                              << " Survive? " << (rand < 1.);
00282 #endif
00283         if (rand < 1.0) { // survived all the times and sent to photo-cathode
00284           wlatten.push_back(lambda);
00285           rand = G4UniformRand();
00286           double qEffic = computeQEff(lambda);//Quantum efficiency of the PMT
00287           rand = G4UniformRand();
00288 #ifdef DebugLog
00289           LogDebug("HFShower") << "HFCherenkov::computeNPEinPMT: qEffic " 
00290                                << qEffic << " Random " << rand 
00291                                << " Survive? " <<(rand < qEffic);
00292 #endif
00293           if (rand < qEffic) { // made photoelectron
00294             npe_ += 1;
00295             momZ.push_back(w_ph);
00296             wl.push_back(lambda);
00297             wlqeff.push_back(lambda);
00298           } // made pe
00299         } // accepted all Cherenkov photons
00300       } // end of  if(w_ph < w_aperture), trapped inside glass
00301     }// end of ++NbOfPhotons
00302   } // end of if(NbOfPhotons)}
00303 #ifdef DebugLog
00304   LogDebug("HFShower") << "HFCherenkov::computeNPEinPMT: npe " << npe_;
00305 #endif
00306   return npe_;
00307 }
00308 
00309 std::vector<double>  HFCherenkov::getWLIni() {
00310   std::vector<double> v = wlini;
00311   return v;
00312 }
00313 
00314 std::vector<double>  HFCherenkov::getWLTrap() {
00315   std::vector<double> v = wltrap;
00316   return v;
00317 }
00318 
00319 std::vector<double>  HFCherenkov::getWLAtten() {
00320   std::vector<double> v = wlatten;
00321   return v;
00322 }
00323 
00324 std::vector<double>  HFCherenkov::getWLHEM() {
00325   std::vector<double> v  = wlhem;
00326   return v;
00327 }
00328 
00329 std::vector<double>  HFCherenkov::getWLQEff() {
00330   std::vector<double> v = wlqeff;
00331   return v;
00332 }
00333 
00334 std::vector<double>  HFCherenkov::getWL() {
00335   std::vector<double> v = wl;
00336   return v;
00337 }
00338 
00339 std::vector<double>  HFCherenkov::getMom() {
00340   std::vector<double> v = momZ;
00341   return v;
00342 }
00343 
00344 int HFCherenkov::computeNbOfPhotons(double beta, G4double stepL) {
00345 
00346   double pBeta = beta;
00347   double alpha = 0.0073;
00348   double step_length = stepL;
00349   double theta_C = acos(1./(pBeta*ref_index));
00350   double lambdaDiff = (1./lambda1 - 1./lambda2);
00351   double cherenPhPerLength = 2 * M_PI * alpha * lambdaDiff*cm;
00352   double d_NOfPhotons = cherenPhPerLength * sin(theta_C)*sin(theta_C) *  (step_length/cm);
00353   int nbOfPhotons = int(d_NOfPhotons);
00354 #ifdef DebugLog
00355   LogDebug("HFShower") << "HFCherenkov::computeNbOfPhotons: StepLength " 
00356                        << step_length << " theta_C " << theta_C 
00357                        << " lambdaDiff " << lambdaDiff
00358                        << " cherenPhPerLength " << cherenPhPerLength 
00359                        << " Photons " << d_NOfPhotons << " " << nbOfPhotons;
00360 #endif
00361   return nbOfPhotons;
00362 }
00363 
00364 double HFCherenkov::computeQEff(double wavelength) {
00365 
00366   double qeff(0.);
00367   if (UseNewPMT) {
00368     if (wavelength<=350) {
00369       qeff=2.45867*(TMath::Landau(wavelength,353.820,59.1324));
00370     } else if (wavelength>350 && wavelength<500) {
00371       qeff= 0.441989*exp(-pow((wavelength-358.371),2)/(2*pow((138.277),2)));
00372     } else if (wavelength>=500 && wavelength<550) {
00373       qeff= 0.271862*exp(-pow((wavelength-491.505),2)/(2*pow((47.0418),2)));
00374     } else if (wavelength>=550) {
00375       qeff= 0.137297*exp(-pow((wavelength-520.260),2)/(2*pow((75.5023),2)));
00376     }
00377 #ifdef DebugLog
00378     LogDebug("HFShower") << "HFCherenkov:: for new PMT : wavelength === "
00379                          << wavelength << "\tqeff  ===\t" << qeff;
00380 #endif
00381   } else {
00382     double y        = (wavelength - 275.) /180.;
00383     double func     = 1. / (1. + 250.*pow((y/5.),4));
00384     double qE_R7525 = 0.77 * y * exp(-y) * func ;
00385     qeff            = qE_R7525;
00386 #ifdef DebugLog
00387     LogDebug("HFShower") << "HFCherenkov:: for old PMT : wavelength === "
00388                          << wavelength << "; qeff = " << qeff;
00389 #endif
00390   }
00391 
00392 #ifdef DebugLog
00393   LogDebug("HFShower") << "HFCherenkov::computeQEff: wavelength " << wavelength
00394                        << " y/func " << y << "/" << func << " qeff " << qeff;
00395 #endif
00396   return qeff;
00397 }
00398 
00399 double HFCherenkov::computeHEMEff(double wavelength) {
00400 
00401   double hEMEff = 0;
00402   if (wavelength < 400.) {
00403     hEMEff = 0.;
00404   } else if (wavelength >= 400. && wavelength < 410.) {
00405     //hEMEff = .99 * (wavelength - 400.) / 10.;
00406     hEMEff = (-1322.453 / wavelength) + 4.2056;
00407   } else if (wavelength >= 410.) {
00408     hEMEff = 0.99;
00409     if (wavelength > 415. && wavelength < 445.) {
00410       //abs(wavelength - 430.) < 15.
00411       //hEMEff = 0.95;
00412       hEMEff = 0.97;
00413     } else if (wavelength > 550. && wavelength < 600.) {
00414       // abs(wavelength - 575.) < 25.)
00415       //hEMEff = 0.96;
00416       hEMEff = 0.98;
00417     } else if (wavelength > 565. && wavelength <= 635.) { // added later
00418       // abs(wavelength - 600.) < 35.)
00419       hEMEff = (701.7268 / wavelength) - 0.186;
00420     }
00421   }
00422 #ifdef DebugLog
00423   LogDebug("HFShower") << "HFCherenkov::computeHEMEff: wavelength "
00424                        << wavelength << " hEMEff " << hEMEff;
00425 #endif
00426   return hEMEff;
00427 }
00428 
00429 double HFCherenkov::smearNPE(int npe) {
00430 
00431   double pe = 0.;
00432   if (npe > 0) {
00433     for (int i = 0; i < npe; ++i) {
00434       double val =  G4Poisson(gain);
00435       pe += (val/gain) + 0.001*G4UniformRand();
00436     }
00437   }
00438 #ifdef DebugLog
00439   LogDebug("HFShower") << "HFCherenkov::smearNPE: npe " << npe << " pe " << pe;
00440 #endif
00441   return pe;
00442 }
00443 
00444 void HFCherenkov::clearVectors() {
00445 
00446   wl.clear();
00447   wlini.clear();
00448   wltrap.clear();
00449   wlatten.clear();
00450   wlhem.clear();
00451   wlqeff.clear();
00452   momZ.clear();
00453 }
00454 
00455 bool HFCherenkov::isApplicable(const G4ParticleDefinition* aParticleType) {
00456   bool tmp = (aParticleType->GetPDGCharge() != 0);
00457 #ifdef DebugLog
00458   LogDebug("HFShower") << "HFCherenkov::isApplicable: aParticleType " 
00459                        << aParticleType->GetParticleName() << " PDGCharge " 
00460                        << aParticleType->GetPDGCharge() << " Result " << tmp;
00461 #endif
00462   return tmp;
00463 }