CMS 3D CMS Logo

HFCherenkov.cc
Go to the documentation of this file.
1 // File: HFCherenkov.cc
3 // Description: Generate Cherenkov photons for HF
5 
7 
8 #include "G4Poisson.hh"
9 #include "G4ParticleDefinition.hh"
10 #include "G4NavigationHistory.hh"
11 #include "TMath.h"
12 
13 #include "Randomize.hh"
14 #include "G4SystemOfUnits.hh"
15 
16 //#define EDM_ML_DEBUG
17 
19  ref_index = m_HF.getParameter<double>("RefIndex");
20  lambda1 = ((m_HF.getParameter<double>("Lambda1")) / pow(double(10), 7)) * cm;
21  lambda2 = ((m_HF.getParameter<double>("Lambda2")) / pow(double(10), 7)) * cm;
22  aperture = cos(asin(m_HF.getParameter<double>("Aperture")));
23  apertureTrap = cos(asin(m_HF.getParameter<double>("ApertureTrapped")));
24  aperturetrapped = m_HF.getParameter<double>("CosApertureTrapped");
25  gain = m_HF.getParameter<double>("Gain");
26  checkSurvive = m_HF.getParameter<bool>("CheckSurvive");
27  UseNewPMT = m_HF.getParameter<bool>("UseR7600UPMT");
28  sinPsimax = m_HF.getUntrackedParameter<double>("SinPsiMax", 0.5);
29  fibreR = m_HF.getUntrackedParameter<double>("FibreR", 0.3) * mm;
30 
31  edm::LogVerbatim("HFShower") << "HFCherenkov:: initialised with ref_index " << ref_index << " lambda1/lambda2 (cm) "
32  << lambda1 / cm << "|" << lambda2 / cm << " aperture(total/trapped) " << aperture << "|"
33  << apertureTrap << "|" << aperturetrapped << " Check photon survival in HF "
34  << checkSurvive << " Gain " << gain << " useNewPMT " << UseNewPMT << " FibreR "
35  << fibreR;
36 
37  clearVectors();
38 }
39 
41 
43  double pBeta, double u, double v, double w, double step_length, double zFiber, double dose, int npe_Dose) {
44  if (pBeta < (1 / ref_index) || step_length < 0.0001) {
45  return 0;
46  }
47 
48  double uv = sqrt(u * u + v * v);
49  int nbOfPhotons = computeNbOfPhotons(pBeta, step_length);
50 
51  if (nbOfPhotons < 0) {
52  return 0;
53  } else if (nbOfPhotons > 0) {
54  double w_ph = 0;
55  for (int i = 0; i < nbOfPhotons; i++) {
56  double rand = G4UniformRand();
57  double theta_C = acos(1. / (pBeta * ref_index));
58  double phi_C = 2 * M_PI * rand;
59  double sinTheta = sin(theta_C);
60  double cosTheta = cos(theta_C);
61  double cosPhi = cos(phi_C);
62  //photon momentum
63  if (uv < 0.001) { // aligned with z-axis
64  w_ph = cosTheta;
65  } else { // general case
66  w_ph = w * cosTheta - sinTheta * cosPhi * uv;
67  }
68  if (w_ph > apertureTrap) { // phton trapped inside fiber
69  npe_Dose += 1;
70  }
71  }
72  }
73  int n_photons = npe_Dose;
74  return n_photons;
75 }
76 
77 int HFCherenkov::computeNPE(const G4Step* aStep,
78  const G4ParticleDefinition* pDef,
79  double pBeta,
80  double u,
81  double v,
82  double w,
83  double step_length,
84  double zFiber,
85  double dose,
86  int npe_Dose) {
87  clearVectors();
88  if (!isApplicable(pDef)) {
89  return 0;
90  }
91  if (pBeta < (1 / ref_index) || step_length < 0.0001) {
92 #ifdef EDM_ML_DEBUG
93  edm::LogVerbatim("HFShower") << "HFCherenkov::computeNPE: pBeta " << pBeta << " 1/mu " << (1 / ref_index)
94  << " step_length " << step_length;
95 #endif
96  return 0;
97  }
98 
99  double uv = sqrt(u * u + v * v);
100  int nbOfPhotons = computeNbOfPhotons(pBeta, step_length) * aStep->GetTrack()->GetWeight();
101 #ifdef EDM_ML_DEBUG
102  edm::LogVerbatim("HFShower") << "HFCherenkov::computeNPE: pBeta " << pBeta << " u/v/w " << u << "/" << v << "/" << w
103  << " step_length " << step_length << " zFib " << zFiber << " nbOfPhotons "
104  << nbOfPhotons;
105 #endif
106  if (nbOfPhotons < 0) {
107  return 0;
108  } else if (nbOfPhotons > 0) {
109  G4StepPoint* preStepPoint = aStep->GetPreStepPoint();
110  const G4TouchableHandle& theTouchable = preStepPoint->GetTouchableHandle();
111  G4ThreeVector localprepos =
112  theTouchable->GetHistory()->GetTopTransform().TransformPoint(aStep->GetPreStepPoint()->GetPosition());
113  G4ThreeVector localpostpos =
114  theTouchable->GetHistory()->GetTopTransform().TransformPoint(aStep->GetPostStepPoint()->GetPosition());
115 
116  double length = sqrt((localpostpos.x() - localprepos.x()) * (localpostpos.x() - localprepos.x()) +
117  (localpostpos.y() - localprepos.y()) * (localpostpos.y() - localprepos.y()));
118  double yemit = std::sqrt(fibreR * fibreR - length * length / 4.);
119 
120  double u_ph = 0, v_ph = 0, w_ph = 0;
121  for (int i = 0; i < nbOfPhotons; i++) {
122  double rand = G4UniformRand();
123  double theta_C = acos(1. / (pBeta * ref_index));
124  double phi_C = 2 * M_PI * rand;
125  double sinTheta = sin(theta_C);
126  double cosTheta = cos(theta_C);
127  double cosPhi = cos(phi_C);
128  double sinPhi = sin(phi_C);
129  //photon momentum
130  if (uv < 0.001) { // aligned with z-axis
131  u_ph = sinTheta * cosPhi;
132  v_ph = sinTheta * sinPhi;
133  w_ph = cosTheta;
134  } else { // general case
135  u_ph = uv * cosTheta + sinTheta * cosPhi * w;
136  v_ph = sinTheta * sinPhi;
137  w_ph = w * cosTheta - sinTheta * cosPhi * uv;
138  }
139  double r_lambda = G4UniformRand();
140  double lambda0 = (lambda1 * lambda2) / (lambda2 - r_lambda * (lambda2 - lambda1));
141  double lambda = (lambda0 / cm) * pow(double(10), 7); // lambda is in nm
142  wlini.push_back(lambda);
143 #ifdef EDM_ML_DEBUG
144  edm::LogVerbatim("HFShower") << "HFCherenkov::computeNPE: " << i << " lambda " << lambda << " w_ph " << w_ph
145  << " aperture " << aperture;
146 #endif
147  // --------------
148  double xemit = length * (G4UniformRand() - 0.5);
149  double gam = atan2(yemit, xemit);
150  double eps = atan2(v_ph, u_ph);
151  double sinBeta = sin(gam - eps);
152  double rho = sqrt(xemit * xemit + yemit * yemit);
153  double sinEta = rho / fibreR * sinBeta;
154  double cosEta = sqrt(1. - sinEta * sinEta);
155  double sinPsi = sqrt(1. - w_ph * w_ph);
156  double cosKsi = cosEta * sinPsi;
157 #ifdef EDM_ML_DEBUG
158  if (cosKsi < aperturetrapped && w_ph > 0.) {
159  edm::LogVerbatim("HFShower") << "HFCherenkov::Trapped photon : " << u_ph << " " << v_ph << " " << w_ph << " "
160  << xemit << " " << gam << " " << eps << " " << sinBeta << " " << rho << " "
161  << sinEta << " " << cosEta << " "
162  << " " << sinPsi << " " << cosKsi;
163  } else {
164  edm::LogVerbatim("HFShower") << "HFCherenkov::Rejected photon : " << u_ph << " " << v_ph << " " << w_ph << " "
165  << xemit << " " << gam << " " << eps << " " << sinBeta << " " << rho << " "
166  << sinEta << " " << cosEta << " "
167  << " " << sinPsi << " " << cosKsi;
168  }
169 #endif
170  if (cosKsi < aperturetrapped // photon trapped inside fiber
171  && w_ph > 0. // and moves to PMT
172  && sinPsi < sinPsimax) { // and is not reflected at fiber end
173  wltrap.push_back(lambda);
174  double prob_HF = 1.0; //photon survived in HF
175  double a0_inv = 0.1234; //meter^-1
176  double prob_MX = exp(-0.5 * a0_inv); //light mixer
177  if (checkSurvive) {
178  double a_inv = a0_inv + 0.14 * pow(dose, 0.30);
179  double z_meters = zFiber;
180  prob_HF = exp(-z_meters * a_inv); //photon survived in HF
181  }
182  rand = G4UniformRand();
183 #ifdef EDM_ML_DEBUG
184  edm::LogVerbatim("HFShower") << "HFCherenkov::computeNPE: probHF " << prob_HF << " prob_MX " << prob_MX
185  << " Random " << rand << " Survive? " << (rand < (prob_HF * prob_MX));
186 #endif
187  if (rand < (prob_HF * prob_MX)) { // survived and sent to light mixer
188  wlatten.push_back(lambda);
189  rand = G4UniformRand();
190  double effHEM = computeHEMEff(lambda);
191 #ifdef EDM_ML_DEBUG
192  edm::LogVerbatim("HFShower") << "HFCherenkov::computeNPE: w_ph " << w_ph << " effHEM " << effHEM << " Random "
193  << rand << " Survive? " << (w_ph > 0.997 || (rand < effHEM));
194 #endif
195  if (w_ph > 0.997 || (rand < effHEM)) { // survived HEM
196  wlhem.push_back(lambda);
197  double qEffic = computeQEff(lambda);
198  rand = G4UniformRand();
199 #ifdef EDM_ML_DEBUG
200  edm::LogVerbatim("HFShower") << "HFCherenkov::computeNPE: qEffic " << qEffic << " Random " << rand
201  << " Survive? " << (rand < qEffic);
202 #endif
203  if (rand < qEffic) { // made photoelectron
204  npe_Dose += 1;
205  momZ.push_back(w_ph);
206  wl.push_back(lambda);
207  wlqeff.push_back(lambda);
208  } // made pe
209  } // passed HEM
210  } // passed fiber
211  } // end of if(w_ph < w_aperture), trapped inside fiber
212  } // end of ++NbOfPhotons
213  } // end of if(NbOfPhotons)}
214  int npe = npe_Dose; // Nb of photoelectrons
215 #ifdef EDM_ML_DEBUG
216  edm::LogVerbatim("HFShower") << "HFCherenkov::computeNPE: npe " << npe;
217 #endif
218  return npe;
219 }
220 
222  const G4ParticleDefinition* pDef, double pBeta, double u, double v, double w, double step_length) {
223  clearVectors();
224  int npe_ = 0;
225  if (!isApplicable(pDef)) {
226  return 0;
227  }
228  if (pBeta < (1 / ref_index) || step_length < 0.0001) {
229 #ifdef EDM_ML_DEBUG
230  edm::LogVerbatim("HFShower") << "HFCherenkov::computeNPEinPMT: pBeta " << pBeta << " 1/mu " << (1 / ref_index)
231  << " step_length " << step_length;
232 #endif
233  return 0;
234  }
235 
236  double uv = sqrt(u * u + v * v);
237  int nbOfPhotons = computeNbOfPhotons(pBeta, step_length);
238 #ifdef EDM_ML_DEBUG
239  edm::LogVerbatim("HFShower") << "HFCherenkov::computeNPEinPMT: pBeta " << pBeta << " u/v/w " << u << "/" << v << "/"
240  << w << " step_length " << step_length << " nbOfPhotons " << nbOfPhotons;
241 #endif
242  if (nbOfPhotons < 0) {
243  return 0;
244  } else if (nbOfPhotons > 0) {
245  double w_ph = 0;
246  for (int i = 0; i < nbOfPhotons; i++) {
247  double rand = G4UniformRand();
248  double theta_C = acos(1. / (pBeta * ref_index));
249  double phi_C = 2 * M_PI * rand;
250  double sinTheta = sin(theta_C);
251  double cosTheta = cos(theta_C);
252  double cosPhi = cos(phi_C);
253  //photon momentum
254  if (uv < 0.001) { // aligned with z-axis
255  w_ph = cosTheta;
256  } else { // general case
257  w_ph = w * cosTheta - sinTheta * cosPhi * uv;
258  }
259  double r_lambda = G4UniformRand();
260  double lambda0 = (lambda1 * lambda2) / (lambda2 - r_lambda * (lambda2 - lambda1));
261  double lambda = (lambda0 / cm) * pow(double(10), 7); // lambda is in nm
262  wlini.push_back(lambda);
263 #ifdef EDM_ML_DEBUG
264  edm::LogVerbatim("HFShower") << "HFCherenkov::computeNPEinPMT: " << i << " lambda " << lambda << " w_ph " << w_ph
265  << " aperture " << aperture;
266 #endif
267  if (w_ph > aperture) { // phton trapped inside PMT glass
268  wltrap.push_back(lambda);
269  rand = G4UniformRand();
270 #ifdef EDM_ML_DEBUG
271  edm::LogVerbatim("HFShower") << "HFCherenkov::computeNPEinPMT: Random " << rand << " Survive? " << (rand < 1.);
272 #endif
273  if (rand < 1.0) { // survived all the times and sent to photo-cathode
274  wlatten.push_back(lambda);
275  double qEffic = computeQEff(lambda); //Quantum efficiency of the PMT
276  rand = G4UniformRand();
277 #ifdef EDM_ML_DEBUG
278  edm::LogVerbatim("HFShower") << "HFCherenkov::computeNPEinPMT: qEffic " << qEffic << " Random " << rand
279  << " Survive? " << (rand < qEffic);
280 #endif
281  if (rand < qEffic) { // made photoelectron
282  npe_ += 1;
283  momZ.push_back(w_ph);
284  wl.push_back(lambda);
285  wlqeff.push_back(lambda);
286  } // made pe
287  } // accepted all Cherenkov photons
288  } // end of if(w_ph < w_aperture), trapped inside glass
289  } // end of ++NbOfPhotons
290  } // end of if(NbOfPhotons)}
291 #ifdef EDM_ML_DEBUG
292  edm::LogVerbatim("HFShower") << "HFCherenkov::computeNPEinPMT: npe " << npe_;
293 #endif
294  return npe_;
295 }
296 
297 std::vector<double> HFCherenkov::getWLIni() {
298  std::vector<double> v = wlini;
299  return v;
300 }
301 
302 std::vector<double> HFCherenkov::getWLTrap() {
303  std::vector<double> v = wltrap;
304  return v;
305 }
306 
307 std::vector<double> HFCherenkov::getWLAtten() {
308  std::vector<double> v = wlatten;
309  return v;
310 }
311 
312 std::vector<double> HFCherenkov::getWLHEM() {
313  std::vector<double> v = wlhem;
314  return v;
315 }
316 
317 std::vector<double> HFCherenkov::getWLQEff() {
318  std::vector<double> v = wlqeff;
319  return v;
320 }
321 
322 std::vector<double> HFCherenkov::getWL() {
323  std::vector<double> v = wl;
324  return v;
325 }
326 
327 std::vector<double> HFCherenkov::getMom() {
328  std::vector<double> v = momZ;
329  return v;
330 }
331 
332 int HFCherenkov::computeNbOfPhotons(double beta, G4double stepL) {
333  double pBeta = beta;
334  double alpha = 0.0073;
335  double step_length = stepL;
336  double theta_C = acos(1. / (pBeta * ref_index));
337  double lambdaDiff = (1. / lambda1 - 1. / lambda2);
338  double cherenPhPerLength = 2 * M_PI * alpha * lambdaDiff * cm;
339  double d_NOfPhotons = cherenPhPerLength * sin(theta_C) * sin(theta_C) * (step_length / cm);
340  int nbOfPhotons = int(d_NOfPhotons);
341 #ifdef EDM_ML_DEBUG
342  edm::LogVerbatim("HFShower") << "HFCherenkov::computeNbOfPhotons: StepLength " << step_length << " theta_C "
343  << theta_C << " lambdaDiff " << lambdaDiff << " cherenPhPerLength " << cherenPhPerLength
344  << " Photons " << d_NOfPhotons << " " << nbOfPhotons;
345 #endif
346  return nbOfPhotons;
347 }
348 
349 double HFCherenkov::computeQEff(double wavelength) {
350  double qeff(0.);
351  if (UseNewPMT) {
352  if (wavelength <= 350) {
353  qeff = 2.45867 * (TMath::Landau(wavelength, 353.820, 59.1324));
354  } else if (wavelength > 350 && wavelength < 500) {
355  qeff = 0.441989 * exp(-pow((wavelength - 358.371), 2) / (2 * pow((138.277), 2)));
356  } else if (wavelength >= 500 && wavelength < 550) {
357  qeff = 0.271862 * exp(-pow((wavelength - 491.505), 2) / (2 * pow((47.0418), 2)));
358  } else if (wavelength >= 550) {
359  qeff = 0.137297 * exp(-pow((wavelength - 520.260), 2) / (2 * pow((75.5023), 2)));
360  }
361 #ifdef EDM_ML_DEBUG
362  edm::LogVerbatim("HFShower") << "HFCherenkov:: for new PMT : wavelength === " << wavelength << "\tqeff ===\t"
363  << qeff;
364 #endif
365  } else {
366  double y = (wavelength - 275.) / 180.;
367  double func = 1. / (1. + 250. * pow((y / 5.), 4));
368  double qE_R7525 = 0.77 * y * exp(-y) * func;
369  qeff = qE_R7525;
370 #ifdef EDM_ML_DEBUG
371  edm::LogVerbatim("HFShower") << "HFCherenkov::computeQEff: wavelength " << wavelength << " y/func " << y << "/"
372  << func << " qeff " << qeff;
373  edm::LogVerbatim("HFShower") << "HFCherenkov:: for old PMT : wavelength === " << wavelength << "; qeff = " << qeff;
374 #endif
375  }
376  return qeff;
377 }
378 
379 double HFCherenkov::computeHEMEff(double wavelength) {
380  double hEMEff = 0;
381  if (wavelength < 400.) {
382  hEMEff = 0.;
383  } else if (wavelength >= 400. && wavelength < 410.) {
384  //hEMEff = .99 * (wavelength - 400.) / 10.;
385  hEMEff = (-1322.453 / wavelength) + 4.2056;
386  } else if (wavelength >= 410.) {
387  hEMEff = 0.99;
388  if (wavelength > 415. && wavelength < 445.) {
389  //abs(wavelength - 430.) < 15.
390  //hEMEff = 0.95;
391  hEMEff = 0.97;
392  } else if (wavelength > 550. && wavelength < 600.) {
393  // abs(wavelength - 575.) < 25.)
394  //hEMEff = 0.96;
395  hEMEff = 0.98;
396  } else if (wavelength > 565. && wavelength <= 635.) { // added later
397  // abs(wavelength - 600.) < 35.)
398  hEMEff = (701.7268 / wavelength) - 0.186;
399  }
400  }
401 #ifdef EDM_ML_DEBUG
402  edm::LogVerbatim("HFShower") << "HFCherenkov::computeHEMEff: wavelength " << wavelength << " hEMEff " << hEMEff;
403 #endif
404  return hEMEff;
405 }
406 
407 double HFCherenkov::smearNPE(int npe) {
408  double pe = 0.;
409  if (npe > 0) {
410  for (int i = 0; i < npe; ++i) {
411  double val = G4Poisson(gain);
412  pe += (val / gain) + 0.001 * G4UniformRand();
413  }
414  }
415 #ifdef EDM_ML_DEBUG
416  edm::LogVerbatim("HFShower") << "HFCherenkov::smearNPE: npe " << npe << " pe " << pe;
417 #endif
418  return pe;
419 }
420 
422  wl.clear();
423  wlini.clear();
424  wltrap.clear();
425  wlatten.clear();
426  wlhem.clear();
427  wlqeff.clear();
428  momZ.clear();
429 }
430 
431 bool HFCherenkov::isApplicable(const G4ParticleDefinition* aParticleType) {
432  bool tmp = (aParticleType->GetPDGCharge() != 0);
433 #ifdef EDM_ML_DEBUG
434  edm::LogVerbatim("HFShower") << "HFCherenkov::isApplicable: aParticleType " << aParticleType->GetParticleName()
435  << " PDGCharge " << aParticleType->GetPDGCharge() << " Result " << tmp;
436 #endif
437  return tmp;
438 }
T getParameter(std::string const &) const
T getUntrackedParameter(std::string const &, T const &) const
double computeQEff(double wavelength)
Definition: HFCherenkov.cc:349
float alpha
Definition: AMPTWrapper.h:95
virtual ~HFCherenkov()
Definition: HFCherenkov.cc:40
double fibreR
Definition: HFCherenkov.h:61
const double w
Definition: UKUtility.cc:23
double aperturetrapped
Definition: HFCherenkov.h:60
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
HFCherenkov(edm::ParameterSet const &p)
Definition: HFCherenkov.cc:18
std::vector< double > wlqeff
Definition: HFCherenkov.h:72
void clearVectors()
Definition: HFCherenkov.cc:421
bool UseNewPMT
Definition: HFCherenkov.h:63
std::vector< double > wlini
Definition: HFCherenkov.h:68
double computeHEMEff(double wavelength)
Definition: HFCherenkov.cc:379
double smearNPE(G4int Npe)
Definition: HFCherenkov.cc:407
double sinPsimax
Definition: HFCherenkov.h:61
std::vector< double > getWL()
Definition: HFCherenkov.cc:322
std::vector< double > getWLQEff()
Definition: HFCherenkov.cc:317
T sqrt(T t)
Definition: SSEVec.h:18
std::vector< double > wltrap
Definition: HFCherenkov.h:69
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
double aperture
Definition: HFCherenkov.h:60
std::vector< double > wlhem
Definition: HFCherenkov.h:71
double apertureTrap
Definition: HFCherenkov.h:60
std::vector< double > getMom()
Definition: HFCherenkov.cc:327
#define M_PI
std::vector< double > getWLIni()
Definition: HFCherenkov.cc:297
std::vector< std::vector< double > > tmp
Definition: MVATrainer.cc:100
int computeNbOfPhotons(double pBeta, double step_length)
Definition: HFCherenkov.cc:332
std::vector< double > getWLTrap()
Definition: HFCherenkov.cc:302
Signal rand(Signal arg)
Definition: vlib.cc:442
std::vector< double > getWLAtten()
Definition: HFCherenkov.cc:307
bool isApplicable(const G4ParticleDefinition *aParticleType)
Definition: HFCherenkov.cc:431
std::vector< double > wlatten
Definition: HFCherenkov.h:70
double gain
Definition: HFCherenkov.h:61
double lambda1
Definition: HFCherenkov.h:59
int computeNPE(const G4Step *step, const G4ParticleDefinition *pDef, double pBeta, double u, double v, double w, double step_length, double zFiber, double Dose, int Npe_Dose)
Definition: HFCherenkov.cc:77
double lambda2
Definition: HFCherenkov.h:59
bool checkSurvive
Definition: HFCherenkov.h:62
std::vector< double > momZ
Definition: HFCherenkov.h:67
int computeNPhTrapped(double pBeta, double u, double v, double w, double step_length, double zFiber, double Dose, int Npe_Dose)
Definition: HFCherenkov.cc:42
int computeNPEinPMT(const G4ParticleDefinition *pDef, double pBeta, double u, double v, double w, double step_length)
Definition: HFCherenkov.cc:221
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:40
double ref_index
Definition: HFCherenkov.h:58
std::vector< double > getWLHEM()
Definition: HFCherenkov.cc:312
std::vector< double > wl
Definition: HFCherenkov.h:66