00001
00002
00003
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
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
00065 if (uv < 0.001) {
00066 w_ph = cosTheta;
00067 } else {
00068 w_ph = w * cosTheta - sinTheta * cosPhi * uv;
00069 }
00070 if (w_ph > apertureTrap) {
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
00128 if (uv < 0.001) {
00129 u_ph = sinTheta * cosPhi ;
00130 v_ph = sinTheta * sinPhi;
00131 w_ph = cosTheta;
00132 } else {
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);
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
00173 && w_ph>0.
00174 && sinPsi < sinPsimax) {
00175 wltrap.push_back(lambda);
00176 double prob_HF = 1.0;
00177 double a0_inv = 0.1234;
00178 double prob_MX = exp( - 0.5 * a0_inv );
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 );
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)) {
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)) {
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) {
00209 npe_Dose += 1;
00210 momZ.push_back(w_ph);
00211 wl.push_back(lambda);
00212 wlqeff.push_back(lambda);
00213 }
00214 }
00215 }
00216 }
00217 }
00218 }
00219 int npe = npe_Dose;
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
00261 if (uv < 0.001) {
00262 w_ph = cosTheta;
00263 } else {
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);
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) {
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) {
00284 wlatten.push_back(lambda);
00285 rand = G4UniformRand();
00286 double qEffic = computeQEff(lambda);
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) {
00294 npe_ += 1;
00295 momZ.push_back(w_ph);
00296 wl.push_back(lambda);
00297 wlqeff.push_back(lambda);
00298 }
00299 }
00300 }
00301 }
00302 }
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
00406 hEMEff = (-1322.453 / wavelength) + 4.2056;
00407 } else if (wavelength >= 410.) {
00408 hEMEff = 0.99;
00409 if (wavelength > 415. && wavelength < 445.) {
00410
00411
00412 hEMEff = 0.97;
00413 } else if (wavelength > 550. && wavelength < 600.) {
00414
00415
00416 hEMEff = 0.98;
00417 } else if (wavelength > 565. && wavelength <= 635.) {
00418
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 }