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 #ifdef DebugLog
00098 LogDebug("HFShower") << "HFCherenkov::computeNPE: pBeta " << pBeta
00099 << " u/v/w " << u << "/" << v << "/" << w
00100 << " step_length " << step_length << " zFib " << zFiber
00101 << " nbOfPhotons " << nbOfPhotons;
00102 #endif
00103 if (nbOfPhotons < 0) {
00104 return 0;
00105 } else if (nbOfPhotons > 0) {
00106 G4StepPoint * preStepPoint = aStep->GetPreStepPoint();
00107 G4TouchableHandle theTouchable = preStepPoint->GetTouchableHandle();
00108 G4ThreeVector localprepos = theTouchable->GetHistory()->
00109 GetTopTransform().TransformPoint(aStep->GetPreStepPoint()->GetPosition());
00110 G4ThreeVector localpostpos = theTouchable->GetHistory()->
00111 GetTopTransform().TransformPoint(aStep->GetPostStepPoint()->GetPosition());
00112
00113 double length=sqrt((localpostpos.x()-localprepos.x())*(localpostpos.x()-localprepos.x())
00114 +(localpostpos.y()-localprepos.y())*(localpostpos.y()-localprepos.y()));
00115 double yemit = std::sqrt(fibreR*fibreR-length*length/4.);
00116
00117 double u_ph=0,v_ph=0, w_ph=0;
00118 for (int i = 0; i < nbOfPhotons; i++) {
00119 double rand = G4UniformRand();
00120 double theta_C = acos(1./(pBeta*ref_index));
00121 double phi_C = 2*M_PI*rand;
00122 double sinTheta = sin(theta_C);
00123 double cosTheta = cos(theta_C);
00124 double cosPhi = cos(phi_C);
00125 double sinPhi = sin(phi_C);
00126
00127 if (uv < 0.001) {
00128 u_ph = sinTheta * cosPhi ;
00129 v_ph = sinTheta * sinPhi;
00130 w_ph = cosTheta;
00131 } else {
00132 u_ph = uv * cosTheta + sinTheta * cosPhi * w;
00133 v_ph = sinTheta * sinPhi;
00134 w_ph = w * cosTheta - sinTheta * cosPhi * uv;
00135 }
00136 double r_lambda = G4UniformRand();
00137 double lambda0 = (lambda1 * lambda2) / (lambda2 - r_lambda *
00138 (lambda2 - lambda1));
00139 double lambda = (lambda0/cm) * pow(double(10),7);
00140 wlini.push_back(lambda);
00141 #ifdef DebugLog
00142 LogDebug("HFShower") << "HFCherenkov::computeNPE: " << i << " lambda "
00143 << lambda << " w_ph " << w_ph << " aperture "
00144 << aperture;
00145 #endif
00146
00147 double xemit=length*(G4UniformRand()-0.5);
00148 double gam=atan2(yemit,xemit);
00149 double eps=atan2(v_ph,u_ph);
00150 double sinBeta=sin(gam-eps);
00151 double rho=sqrt(xemit*xemit+yemit*yemit);
00152 double sinEta=rho/fibreR*sinBeta;
00153 double cosEta=sqrt(1.-sinEta*sinEta);
00154 double sinPsi=sqrt(1.-w_ph*w_ph);
00155 double cosKsi=cosEta*sinPsi;
00156 #ifdef DebugLog
00157 if (cosKsi < aperturetrapped && w_ph>0.) {
00158 LogDebug("HFShower") << "HFCherenkov::Trapped photon : " << u_ph << " "
00159 << v_ph << " " << w_ph << " " << xemit << " "
00160 << gam << " " << eps << " " << sinBeta << " "
00161 << rho << " " << sinEta << " " << cosEta << " "
00162 << " " << sinPsi << " " << cosKsi;
00163 } else {
00164 LogDebug("HFShower") << "HFCherenkov::Rejected photon : " << u_ph <<" "
00165 << v_ph << " " << w_ph << " " << xemit << " "
00166 << gam << " " << eps << " " << sinBeta << " "
00167 << rho << " " << sinEta << " " << cosEta << " "
00168 << " " << sinPsi << " " << cosKsi;
00169 }
00170 #endif
00171 if (cosKsi < aperturetrapped
00172 && w_ph>0.
00173 && sinPsi < sinPsimax) {
00174 wltrap.push_back(lambda);
00175 double prob_HF = 1.0;
00176 double a0_inv = 0.1234;
00177 double prob_MX = exp( - 0.5 * a0_inv );
00178 if (checkSurvive) {
00179 double a_inv = a0_inv + 0.14 * pow(dose,0.30);
00180 double z_meters = zFiber;
00181 prob_HF = exp(-z_meters * a_inv );
00182 }
00183 rand = G4UniformRand();
00184 #ifdef DebugLog
00185 LogDebug("HFShower") << "HFCherenkov::computeNPE: probHF " << prob_HF
00186 << " prob_MX " << prob_MX << " Random " << rand
00187 << " Survive? " << (rand < (prob_HF * prob_MX));
00188 #endif
00189 if (rand < (prob_HF * prob_MX)) {
00190 wlatten.push_back(lambda);
00191 rand = G4UniformRand();
00192 double effHEM = computeHEMEff(lambda);
00193 #ifdef DebugLog
00194 LogDebug("HFShower") << "HFCherenkov::computeNPE: w_ph " << w_ph
00195 << " effHEM " << effHEM << " Random " << rand
00196 << " Survive? " << (w_ph>0.997||(rand<effHEM));
00197 #endif
00198 if (w_ph>0.997 || (rand<effHEM)) {
00199 wlhem.push_back(lambda);
00200 double qEffic = computeQEff(lambda);
00201 rand = G4UniformRand();
00202 #ifdef DebugLog
00203 LogDebug("HFShower") << "HFCherenkov::computeNPE: qEffic "
00204 << qEffic << " Random " << rand
00205 << " Survive? " <<(rand < qEffic);
00206 #endif
00207 if (rand < qEffic) {
00208 npe_Dose += 1;
00209 momZ.push_back(w_ph);
00210 wl.push_back(lambda);
00211 wlqeff.push_back(lambda);
00212 }
00213 }
00214 }
00215 }
00216 }
00217 }
00218 int npe = npe_Dose;
00219 #ifdef DebugLog
00220 LogDebug("HFShower") << "HFCherenkov::computeNPE: npe " << npe;
00221 #endif
00222 return npe;
00223 }
00224
00225 int HFCherenkov::computeNPEinPMT(G4ParticleDefinition* pDef, double pBeta,
00226 double u, double v, double w,
00227 double step_length){
00228 clearVectors();
00229 int npe_ = 0;
00230 if (!isApplicable(pDef)) {return 0;}
00231 if (pBeta < (1/ref_index) || step_length < 0.0001) {
00232 #ifdef DebugLog
00233 LogDebug("HFShower") << "HFCherenkov::computeNPEinPMT: pBeta " << pBeta
00234 << " 1/mu " << (1/ref_index) << " step_length "
00235 << step_length;
00236 #endif
00237 return 0;
00238 }
00239
00240 double uv = sqrt(u*u + v*v);
00241 int nbOfPhotons = computeNbOfPhotons(pBeta, step_length);
00242 #ifdef DebugLog
00243 LogDebug("HFShower") << "HFCherenkov::computeNPEinPMT: pBeta " << pBeta
00244 << " u/v/w " << u << "/" << v << "/" << w
00245 << " step_length " << step_length
00246 << " nbOfPhotons " << nbOfPhotons;
00247 #endif
00248 if (nbOfPhotons < 0) {
00249 return 0;
00250 } else if (nbOfPhotons > 0) {
00251 double w_ph=0;
00252 for (int i = 0; i < nbOfPhotons; i++) {
00253 double rand = G4UniformRand();
00254 double theta_C = acos(1./(pBeta*ref_index));
00255 double phi_C = 2*M_PI*rand;
00256 double sinTheta = sin(theta_C);
00257 double cosTheta = cos(theta_C);
00258 double cosPhi = cos(phi_C);
00259
00260 if (uv < 0.001) {
00261 w_ph = cosTheta;
00262 } else {
00263 w_ph = w * cosTheta - sinTheta * cosPhi * uv;
00264 }
00265 double r_lambda = G4UniformRand();
00266 double lambda0 = (lambda1 * lambda2) / (lambda2 - r_lambda *
00267 (lambda2 - lambda1));
00268 double lambda = (lambda0/cm) * pow(double(10),7);
00269 wlini.push_back(lambda);
00270 #ifdef DebugLog
00271 LogDebug("HFShower") << "HFCherenkov::computeNPEinPMT: " <<i <<" lambda "
00272 << lambda << " w_ph " << w_ph << " aperture "
00273 << aperture;
00274 #endif
00275 if (w_ph > aperture) {
00276 wltrap.push_back(lambda);
00277 rand = G4UniformRand();
00278 #ifdef DebugLog
00279 LogDebug("HFShower") << "HFCherenkov::computeNPEinPMT: Random " << rand
00280 << " Survive? " << (rand < 1.);
00281 #endif
00282 if (rand < 1.0) {
00283 wlatten.push_back(lambda);
00284 rand = G4UniformRand();
00285 double qEffic = computeQEff(lambda);
00286 rand = G4UniformRand();
00287 #ifdef DebugLog
00288 LogDebug("HFShower") << "HFCherenkov::computeNPEinPMT: qEffic "
00289 << qEffic << " Random " << rand
00290 << " Survive? " <<(rand < qEffic);
00291 #endif
00292 if (rand < qEffic) {
00293 npe_ += 1;
00294 momZ.push_back(w_ph);
00295 wl.push_back(lambda);
00296 wlqeff.push_back(lambda);
00297 }
00298 }
00299 }
00300 }
00301 }
00302 #ifdef DebugLog
00303 LogDebug("HFShower") << "HFCherenkov::computeNPEinPMT: npe " << npe_;
00304 #endif
00305 return npe_;
00306 }
00307
00308 std::vector<double> HFCherenkov::getWLIni() {
00309 std::vector<double> v = wlini;
00310 return v;
00311 }
00312
00313 std::vector<double> HFCherenkov::getWLTrap() {
00314 std::vector<double> v = wltrap;
00315 return v;
00316 }
00317
00318 std::vector<double> HFCherenkov::getWLAtten() {
00319 std::vector<double> v = wlatten;
00320 return v;
00321 }
00322
00323 std::vector<double> HFCherenkov::getWLHEM() {
00324 std::vector<double> v = wlhem;
00325 return v;
00326 }
00327
00328 std::vector<double> HFCherenkov::getWLQEff() {
00329 std::vector<double> v = wlqeff;
00330 return v;
00331 }
00332
00333 std::vector<double> HFCherenkov::getWL() {
00334 std::vector<double> v = wl;
00335 return v;
00336 }
00337
00338 std::vector<double> HFCherenkov::getMom() {
00339 std::vector<double> v = momZ;
00340 return v;
00341 }
00342
00343 int HFCherenkov::computeNbOfPhotons(double beta, G4double stepL) {
00344
00345 double pBeta = beta;
00346 double alpha = 0.0073;
00347 double step_length = stepL;
00348 double theta_C = acos(1./(pBeta*ref_index));
00349 double lambdaDiff = (1./lambda1 - 1./lambda2);
00350 double cherenPhPerLength = 2 * M_PI * alpha * lambdaDiff*cm;
00351 double d_NOfPhotons = cherenPhPerLength * sin(theta_C)*sin(theta_C) * (step_length/cm);
00352 int nbOfPhotons = int(d_NOfPhotons);
00353 #ifdef DebugLog
00354 LogDebug("HFShower") << "HFCherenkov::computeNbOfPhotons: StepLength "
00355 << step_length << " theta_C " << theta_C
00356 << " lambdaDiff " << lambdaDiff
00357 << " cherenPhPerLength " << cherenPhPerLength
00358 << " Photons " << d_NOfPhotons << " " << nbOfPhotons;
00359 #endif
00360 return nbOfPhotons;
00361 }
00362
00363 double HFCherenkov::computeQEff(double wavelength) {
00364
00365 double qeff(0.);
00366 if (UseNewPMT) {
00367 if (wavelength<=350) {
00368 qeff=2.45867*(TMath::Landau(wavelength,353.820,59.1324));
00369 } else if (wavelength>350 && wavelength<500) {
00370 qeff= 0.441989*exp(-pow((wavelength-358.371),2)/(2*pow((138.277),2)));
00371 } else if (wavelength>=500 && wavelength<550) {
00372 qeff= 0.271862*exp(-pow((wavelength-491.505),2)/(2*pow((47.0418),2)));
00373 } else if (wavelength>=550) {
00374 qeff= 0.137297*exp(-pow((wavelength-520.260),2)/(2*pow((75.5023),2)));
00375 }
00376 #ifdef DebugLog
00377 LogDebug("HFShower") << "HFCherenkov:: for new PMT : wavelength === "
00378 << wavelength << "\tqeff ===\t" << qeff;
00379 #endif
00380 } else {
00381 double y = (wavelength - 275.) /180.;
00382 double func = 1. / (1. + 250.*pow((y/5.),4));
00383 double qE_R7525 = 0.77 * y * exp(-y) * func ;
00384 qeff = qE_R7525;
00385 #ifdef DebugLog
00386 LogDebug("HFShower") << "HFCherenkov:: for old PMT : wavelength === "
00387 << wavelength << "; qeff = " << qeff;
00388 #endif
00389 }
00390
00391 #ifdef DebugLog
00392 LogDebug("HFShower") << "HFCherenkov::computeQEff: wavelength " << wavelength
00393 << " y/func " << y << "/" << func << " qeff " << qeff;
00394 #endif
00395 return qeff;
00396 }
00397
00398 double HFCherenkov::computeHEMEff(double wavelength) {
00399
00400 double hEMEff = 0;
00401 if (wavelength < 400.) {
00402 hEMEff = 0.;
00403 } else if (wavelength >= 400. && wavelength < 410.) {
00404
00405 hEMEff = (-1322.453 / wavelength) + 4.2056;
00406 } else if (wavelength >= 410.) {
00407 hEMEff = 0.99;
00408 if (wavelength > 415. && wavelength < 445.) {
00409
00410
00411 hEMEff = 0.97;
00412 } else if (wavelength > 550. && wavelength < 600.) {
00413
00414
00415 hEMEff = 0.98;
00416 } else if (wavelength > 565. && wavelength <= 635.) {
00417
00418 hEMEff = (701.7268 / wavelength) - 0.186;
00419 }
00420 }
00421 #ifdef DebugLog
00422 LogDebug("HFShower") << "HFCherenkov::computeHEMEff: wavelength "
00423 << wavelength << " hEMEff " << hEMEff;
00424 #endif
00425 return hEMEff;
00426 }
00427
00428 double HFCherenkov::smearNPE(int npe) {
00429
00430 double pe = 0.;
00431 if (npe > 0) {
00432 for (int i = 0; i < npe; ++i) {
00433 double val = G4Poisson(gain);
00434 pe += (val/gain) + 0.001*G4UniformRand();
00435 }
00436 }
00437 #ifdef DebugLog
00438 LogDebug("HFShower") << "HFCherenkov::smearNPE: npe " << npe << " pe " << pe;
00439 #endif
00440 return pe;
00441 }
00442
00443 void HFCherenkov::clearVectors() {
00444
00445 wl.clear();
00446 wlini.clear();
00447 wltrap.clear();
00448 wlatten.clear();
00449 wlhem.clear();
00450 wlqeff.clear();
00451 momZ.clear();
00452 }
00453
00454 bool HFCherenkov::isApplicable(const G4ParticleDefinition* aParticleType) {
00455 bool tmp = (aParticleType->GetPDGCharge() != 0);
00456 #ifdef DebugLog
00457 LogDebug("HFShower") << "HFCherenkov::isApplicable: aParticleType "
00458 << aParticleType->GetParticleName() << " PDGCharge "
00459 << aParticleType->GetPDGCharge() << " Result " << tmp;
00460 #endif
00461 return tmp;
00462 }