CMS 3D CMS Logo

EMShower.cc
Go to the documentation of this file.
1 //FAMOS Headers
6 
9 
10 #include <cmath>
11 
12 //#include "FastSimulation/Utilities/interface/Histos.h"
13 
14 using std::vector;
15 
18  EMECALShowerParametrization* const myParam,
19  vector<const RawParticle*>* const myPart,
20  EcalHitMaker* const myGrid,
21  PreshowerHitMaker* const myPresh,
22  bool bFixedLength)
23 
24  : theParam(myParam),
25  thePart(myPart),
26  theGrid(myGrid),
27  thePreshower(myPresh),
28  random(engine),
29  myGammaGenerator(gamma),
30  bFixedLength_(bFixedLength) {
31  // Get the Famos Histos pointer
32  // myHistos = Histos::instance();
33  // myGammaGenerator = GammaFunctionGenerator::instance();
34  stepsCalculated = false;
35  hasPreshower = myPresh != nullptr;
36  theECAL = myParam->ecalProperties();
37  theHCAL = myParam->hcalProperties();
38  theLayer1 = myParam->layer1Properties();
39  theLayer2 = myParam->layer2Properties();
40 
42 
43  nPart = thePart->size();
44  totalEnergy = 0.;
45  globalMaximum = 0.;
46  //double meanDepth = 0.;
47  // Initialize the shower parameters for each particle
48 
49  for (unsigned int i = 0; i < nPart; ++i) {
50  // std::cout << " AAA " << *(*thePart)[i] << std::endl;
51  // The particle and the shower energy
52  Etot.push_back(0.);
53  E.push_back(((*thePart)[i])->e());
54  totalEnergy += E[i];
55 
56  double lny = std::log(E[i] / theECAL->criticalEnergy());
57 
58  // Average and Sigma for T and alpha
59  double theMeanT = myParam->meanT(lny);
60  double theMeanAlpha = myParam->meanAlpha(lny);
61  double theMeanLnT = myParam->meanLnT(lny);
62  double theMeanLnAlpha = myParam->meanLnAlpha(lny);
63  double theSigmaLnT = myParam->sigmaLnT(lny);
64  double theSigmaLnAlpha = myParam->sigmaLnAlpha(lny);
65 
66  // The correlation matrix
67  double theCorrelation = myParam->correlationAlphaT(lny);
68  double rhop = std::sqrt((1. + theCorrelation) / 2.);
69  double rhom = std::sqrt((1. - theCorrelation) / 2.);
70 
71  // The number of spots in ECAL / HCAL
72  theNumberOfSpots.push_back(myParam->nSpots(E[i]));
73  // theNumberOfSpots.push_back(myParam->nSpots(E[i])*spotFraction);
74  //theNumberOfSpots = random->poissonShoot(myParam->nSpots(myPart->e()));
75 
76  // Photo-statistics
77  photos.push_back(E[i] * fotos);
78 
79  // The longitudinal shower development parameters
80  // Fluctuations of alpha, T and beta
81  double z1 = 0.;
82  double z2 = 0.;
83  double aa = 0.;
84 
85  // Protect against too large fluctuations (a < 1) for small energies
86  while (aa <= 1.) {
87  z1 = random->gaussShoot(0., 1.);
88  z2 = random->gaussShoot(0., 1.);
89  aa = std::exp(theMeanLnAlpha + theSigmaLnAlpha * (z1 * rhop - z2 * rhom));
90  }
91 
92  a.push_back(aa);
93  T.push_back(std::exp(theMeanLnT + theSigmaLnT * (z1 * rhop + z2 * rhom)));
94  b.push_back((a[i] - 1.) / T[i]);
95  maximumOfShower.push_back((a[i] - 1.) / b[i]);
97  //meanDepth += a[i] / b[i] * E[i];
98  // std::cout << " Adding max " << maximumOfShower[i] << " " << E[i] << " " <<maximumOfShower[i]*E[i] << std::endl;
99  // std::cout << std::setw(8) << std::setprecision(5) << " a /b " << a[i] << " " << b[i] << std::endl;
100  Ti.push_back(a[i] / b[i] * (std::exp(theMeanLnAlpha) - 1.) / std::exp(theMeanLnAlpha));
101 
102  // The parameters for the number of energy spots
103  TSpot.push_back(theParam->meanTSpot(theMeanT));
104  aSpot.push_back(theParam->meanAlphaSpot(theMeanAlpha));
105  bSpot.push_back((aSpot[i] - 1.) / TSpot[i]);
106  // myHistos->fill("h7000",a[i]);
107  // myHistos->fill("h7002",E[i],a[i]);
108  }
109  // std::cout << " PS1 : " << myGrid->ps1TotalX0()
110  // << " PS2 : " << myGrid->ps2TotalX0()
111  // << " ECAL : " << myGrid->ecalTotalX0()
112  // << " HCAL : " << myGrid->hcalTotalX0()
113  // << " Offset : " << myGrid->x0DepthOffset()
114  // << std::endl;
115 
117  //meanDepth /= totalEnergy;
118  // std::cout << " Total Energy " << totalEnergy << " Global max " << globalMaximum << std::endl;
119 }
120 
122  // TimeMe theT("EMShower::compute");
123 
124  // Determine the longitudinal intervals
125  // std::cout << " EMShower compute" << std::endl;
126  double dt;
127  double radlen;
128  int stps;
129  int first_Ecal_step = 0;
130  int last_Ecal_step = 0;
131 
132  // The maximum is in principe 8 (with 5X0 steps in the ECAL)
133  steps.reserve(24);
134 
135  /*
136  std::cout << " PS1 : " << theGrid->ps1TotalX0()
137  << " PS2 : " << theGrid->ps2TotalX0()
138  << " PS2 and ECAL : " << theGrid->ps2eeTotalX0()
139  << " ECAL : " << theGrid->ecalTotalX0()
140  << " HCAL : " << theGrid->hcalTotalX0()
141  << " Offset : " << theGrid->x0DepthOffset()
142  << std::endl;
143  */
144 
145  radlen = -theGrid->x0DepthOffset();
146 
147  // Preshower Layer 1
148  radlen += theGrid->ps1TotalX0();
149  if (radlen > 0.) {
150  steps.push_back(Step(0, radlen));
151  radlen = 0.;
152  }
153 
154  // Preshower Layer 2
155  radlen += theGrid->ps2TotalX0();
156  if (radlen > 0.) {
157  steps.push_back(Step(1, radlen));
158  radlen = 0.;
159  }
160 
161  // add a step between preshower and ee
162  radlen += theGrid->ps2eeTotalX0();
163  if (radlen > 0.) {
164  steps.push_back(Step(5, radlen));
165  radlen = 0.;
166  }
167 
168  // ECAL
169  radlen += theGrid->ecalTotalX0();
170 
171  // std::cout << "theGrid->ecalTotalX0() = " << theGrid->ecalTotalX0() << std::endl;
172 
173  if (radlen > 0.) {
174  if (!bFixedLength_) {
175  stps = (int)((radlen + 2.5) / 5.);
176  // stps=(int)((radlen+.5)/1.);
177  if (stps == 0)
178  stps = 1;
179  dt = radlen / (double)stps;
180  Step step(2, dt);
181  first_Ecal_step = steps.size();
182  for (int ist = 0; ist < stps; ++ist)
183  steps.push_back(step);
184  last_Ecal_step = steps.size() - 1;
185  radlen = 0.;
186  } else {
187  dt = 1.0;
188  stps = static_cast<int>(radlen);
189  if (stps == 0)
190  stps = 1;
191  Step step(2, dt);
192  first_Ecal_step = steps.size();
193  for (int ist = 0; ist < stps; ++ist)
194  steps.push_back(step);
195  dt = radlen - stps;
196  if (dt > 0) {
197  Step stepLast(2, dt);
198  steps.push_back(stepLast);
199  }
200  last_Ecal_step = steps.size() - 1;
201  // std::cout << "radlen = " << radlen << " stps = " << stps << " dt = " << dt << std::endl;
202  radlen = 0.;
203  }
204  }
205 
206  // I should had a gap here !
207 
208  // HCAL
209  radlen += theGrid->hcalTotalX0();
210  if (radlen > 0.) {
211  double dtFrontHcal = theGrid->totalX0() - theGrid->hcalTotalX0();
212  // One single step for the full HCAL
213  if (dtFrontHcal < 30.) {
214  dt = 30. - dtFrontHcal;
215  Step step(3, dt);
216  steps.push_back(step);
217  }
218  }
219 
220  nSteps = steps.size();
221  if (nSteps == 0)
222  return;
223  double ESliceTot = 0.;
224  double MeanDepth = 0.;
225  depositedEnergy.resize(nSteps);
226  meanDepth.resize(nSteps);
227  double t = 0.;
228 
229  int offset = 0;
230  for (unsigned iStep = 0; iStep < nSteps; ++iStep) {
231  ESliceTot = 0.;
232  MeanDepth = 0.;
233  double realTotalEnergy = 0;
234  dt = steps[iStep].second;
235  t += dt;
236  for (unsigned int i = 0; i < nPart; ++i) {
237  depositedEnergy[iStep].push_back(deposit(t, a[i], b[i], dt));
238  ESliceTot += depositedEnergy[iStep][i];
239  MeanDepth += deposit(t, a[i] + 1., b[i], dt) / b[i] * a[i];
240  realTotalEnergy += depositedEnergy[iStep][i] * E[i];
241  }
242 
243  if (ESliceTot > 0.) // can happen for the shower tails; this depth will be skipped anyway
244  MeanDepth /= ESliceTot;
245  else
246  MeanDepth = t - dt;
247 
248  meanDepth[iStep] = MeanDepth;
249  if (realTotalEnergy < 0.001) {
250  offset -= 1;
251  }
252  }
253 
254  innerDepth = meanDepth[first_Ecal_step];
255  if (last_Ecal_step + offset >= 0)
256  outerDepth = meanDepth[last_Ecal_step + offset];
257  else
259 
260  stepsCalculated = true;
261 }
262 
264  double t = 0.;
265  double dt = 0.;
266  if (!stepsCalculated)
267  prepareSteps();
268 
269  // Prepare the grids in EcalHitMaker
270  // theGrid->setInnerAndOuterDepth(innerDepth,outerDepth);
271  //float pstot = 0.;
272  //float ps2tot = 0.;
273  //float ps1tot = 0.;
274  bool status = false;
275  // double E1 = 0.; // Energy layer 1
276  // double E2 = 0.; // Energy layer 2
277  // double n1 = 0.; // #mips layer 1
278  // double n2 = 0.; // #mips layer 2
279  // double E9 = 0.; // Energy ECAL
280 
281  // Loop over all segments for the longitudinal development
282  //double totECalc = 0;
283 
284  for (unsigned iStep = 0; iStep < nSteps; ++iStep) {
285  // The length of the shower in this segment
286  dt = steps[iStep].second;
287 
288  // std::cout << " Detector " << steps[iStep].first << " t " << t << " " << dt << std::endl;
289 
290  // The elapsed length
291  t += dt;
292 
293  // In what detector are we ?
294  unsigned detector = steps[iStep].first;
295 
296  bool presh1 = detector == 0;
297  bool presh2 = detector == 1;
298  bool ecal = detector == 2;
299  bool hcal = detector == 3;
300  bool vfcal = detector == 4;
301  bool gap = detector == 5;
302 
303  // Temporary. Will be removed
304  if (theHCAL == nullptr)
305  hcal = false;
306 
307  // Keep only ECAL for now
308  if (vfcal)
309  continue;
310 
311  // Nothing to do in the gap
312  if (gap)
313  continue;
314 
315  // cout << " t = " << t << endl;
316  // Build the grid of crystals at this ECAL depth
317  // Actually, it might be useful to check if this grid is empty or not.
318  // If it is empty (because no crystal at this depth), it is of no use
319  // (and time consuming) to generate the spots
320 
321  // middle of the step
322  double tt = t - 0.5 * dt;
323 
324  double realTotalEnergy = 0.;
325  for (unsigned int i = 0; i < nPart; ++i) {
326  realTotalEnergy += depositedEnergy[iStep][i] * E[i];
327  }
328 
329  // std::cout << " Step " << tt << std::endl;
330  // std::cout << "ecal " << ecal << " hcal " << hcal <<std::endl;
331 
332  // If the amount of energy is greater than 1 MeV, make a new grid
333  // otherwise put in the previous one.
334  bool usePreviousGrid = (realTotalEnergy < 0.001);
335 
336  // If the amount of energy is greater than 1 MeV, make a new grid
337  // otherwise put in the previous one.
338 
339  // If less than 1 kEV. Just skip
340  if (iStep > 2 && realTotalEnergy < 0.000001)
341  continue;
342 
343  if (ecal && !usePreviousGrid) {
344  status = theGrid->getPads(meanDepth[iStep]);
345  }
346  if (hcal) {
348  }
349  if ((ecal || hcal) && !status)
350  continue;
351 
352  bool detailedShowerTail = false;
353  // check if a detailed treatment of the rear leakage should be applied
354  if (ecal && !usePreviousGrid) {
355  detailedShowerTail = (t - dt > theGrid->getX0back());
356  }
357 
358  // The particles of the shower are processed in parallel
359  for (unsigned int i = 0; i < nPart; ++i) {
360  // double Edepo=deposit(t,a[i],b[i],dt);
361 
362  // integration of the shower profile between t-dt and t
363  double dE = (!hcal) ? depositedEnergy[iStep][i] : 1. - deposit(a[i], b[i], t - dt);
364 
365  // no need to do the full machinery if there is ~nothing to distribute)
366  if (dE * E[i] < 0.000001)
367  continue;
368 
369  if (ecal && !theECAL->isHom()) {
370  double mean = dE * E[i];
371  double sigma = theECAL->resE() * sqrt(mean);
372 
373  /*
374  double meanLn = log(mean);
375  double kLn = sigma/mean+1;
376  double sigmaLn = log(kLn);
377  */
378 
379  double dE0 = dE;
380 
381  // std::cout << "dE before shoot = " << dE << std::endl;
382  dE = random->gaussShoot(mean, sigma) / E[i];
383 
384  // myGammaGenerator->setParameters(aSam,bSam,0);
385  // dE = myGammaGenerator->shoot()/E[i];
386  // std::cout << "dE shooted = " << dE << " E[i] = " << E[i] << std::endl;
387  if (dE * E[i] < 0.000001)
388  continue;
389  photos[i] = photos[i] * dE / dE0;
390  }
391 
392  /*
393  if (ecal && !theParam->ecalProperties()->isHom()){
394 
395  double cSquare = TMath::Power(theParam->ecalProperties()->resE(),2);
396  double aSam = dE/cSquare;
397  double bSam = 1./cSquare;
398 
399  // dE = dE*gam(bSam*dE, aSam)/tgamma(aSam);
400  }
401  */
402 
403  //totECalc += dE;
404 
405  // The number of energy spots (or mips)
406  double nS = 0;
407 
408  // ECAL case : Account for photostatistics and long'al non-uniformity
409  if (ecal) {
410  // double aSam = E[i]*dE*one_over_resoSquare;
411  // double bSam = one_over_resoSquare;
412 
413  dE = random->poissonShoot(dE * photos[i]) / photos[i];
414  double z0 = random->gaussShoot(0., 1.);
415  dE *= 1. + z0 * theECAL->lightCollectionUniformity();
416 
417  // Expected spot number
418  nS = (theNumberOfSpots[i] * gam(bSpot[i] * tt, aSpot[i]) * bSpot[i] * dt / tgamma(aSpot[i]));
419 
420  // Preshower : Expected number of mips + fluctuation
421  } else if (hcal) {
422  nS = (theNumberOfSpots[i] * gam(bSpot[i] * tt, aSpot[i]) * bSpot[i] * dt / tgamma(aSpot[i])) *
424  double nSo = nS;
425  nS = random->poissonShoot(nS);
426  // 'Quick and dirty' fix (but this line should be better removed):
427  if (nSo > 0. && nS / nSo < 10.)
428  dE *= nS / nSo;
429 
430  // if(true)
431  // {
432  // std::cout << " theHCAL->spotFraction = " <<theHCAL->spotFraction() <<std::endl;
433  // std::cout << " nSpot Ecal : " << nSo/theHCAL->spotFraction() << " Final " << nS << std::endl;
434  // }
435  } else if (presh1) {
436  nS = random->poissonShoot(dE * E[i] * theLayer1->mipsPerGeV());
437  // std::cout << " dE *E[i] (1)" << dE*E[i] << " " << dE*E[i]*theLayer1->mipsPerGeV() << " "<< nS << std::endl;
438  //pstot += dE * E[i];
439  //ps1tot += dE * E[i];
440  dE = nS / (E[i] * theLayer1->mipsPerGeV());
441 
442  // E1 += dE*E[i];
443  // n1 += nS;
444  // if (presh2) { E2 += SpotEnergy; ++n2; }
445 
446  } else if (presh2) {
447  nS = random->poissonShoot(dE * E[i] * theLayer2->mipsPerGeV());
448  // std::cout << " dE *E[i] (2) " << dE*E[i] << " " << dE*E[i]*theLayer2->mipsPerGeV() << " "<< nS << std::endl;
449  //pstot += dE * E[i];
450  //ps2tot += dE * E[i];
451  dE = nS / (E[i] * theLayer2->mipsPerGeV());
452 
453  // E2 += dE*E[i];
454  // n2 += nS;
455  }
456 
457  if (detailedShowerTail)
458  myGammaGenerator->setParameters(floor(a[i] + 0.5), b[i], t - dt);
459 
460  // myHistos->fill("h100",t,dE);
461 
462  // The lateral development parameters
463 
464  // Energy of the spots
465  double eSpot = (nS > 0.) ? dE / nS : 0.;
466  double SpotEnergy = eSpot * E[i];
467 
468  if (hasPreshower && (presh1 || presh2))
469  thePreshower->setSpotEnergy(0.00009);
470  if (hcal) {
471  SpotEnergy *= theHCAL->hOverPi();
472  theHcalHitMaker->setSpotEnergy(SpotEnergy);
473  }
474  // Poissonian fluctuations for the number of spots
475  // int nSpot = random->poissonShoot(nS);
476  int nSpot = (int)(nS + 0.5);
477 
478  // Fig. 11 (right) *** Does not match.
479  // myHistos->fill("h101",t,(double)nSpot/theNumberOfSpots);
480 
481  //double taui = t/T;
482  double taui = tt / Ti[i];
483  double proba = theParam->p(taui, E[i]);
484  double theRC = theParam->rC(taui, E[i]);
485  double theRT = theParam->rT(taui, E[i]);
486 
487  // Fig. 10
488  // myHistos->fill("h300",taui,theRC);
489  // myHistos->fill("h301",taui,theRT);
490  // myHistos->fill("h302",taui,proba);
491 
492  double dSpotsCore = random->gaussShoot(proba * nSpot, std::sqrt(proba * (1. - proba) * nSpot));
493 
494  if (dSpotsCore < 0)
495  dSpotsCore = 0;
496 
497  unsigned nSpots_core = (unsigned)(dSpotsCore + 0.5);
498  unsigned nSpots_tail = ((unsigned)nSpot > nSpots_core) ? nSpot - nSpots_core : 0;
499 
500  for (unsigned icomp = 0; icomp < 2; ++icomp) {
501  double theR = (icomp == 0) ? theRC : theRT;
502  unsigned ncompspots = (icomp == 0) ? nSpots_core : nSpots_tail;
503 
504  RadialInterval radInterval(theR, ncompspots, SpotEnergy, random);
505  if (ecal) {
506  if (icomp == 0) {
507  setIntervals(icomp, radInterval);
508  } else {
509  setIntervals(icomp, radInterval);
510  }
511  } else {
512  radInterval.addInterval(100., 1.); // 100% of the spots
513  }
514 
515  radInterval.compute();
516  // irad = 0 : central circle; irad=1 : outside
517 
518  unsigned nrad = radInterval.nIntervals();
519 
520  for (unsigned irad = 0; irad < nrad; ++irad) {
521  double spote = radInterval.getSpotEnergy(irad);
522  if (ecal)
523  theGrid->setSpotEnergy(spote);
524  if (hcal)
526  unsigned nradspots = radInterval.getNumberOfSpots(irad);
527  double umin = radInterval.getUmin(irad);
528  double umax = radInterval.getUmax(irad);
529  // Go for the lateral development
530  // std::cout << "Couche " << iStep << " irad = " << irad << " Ene = " << E[i] << " eSpot = " << eSpot << " spote = " << spote << " nSpot = " << nS << std::endl;
531 
532  for (unsigned ispot = 0; ispot < nradspots; ++ispot) {
533  double z3 = random->flatShoot(umin, umax);
534  double ri = theR * std::sqrt(z3 / (1. - z3));
535 
536  // Generate phi
537  double phi = 2. * M_PI * random->flatShoot();
538 
539  // Add the hit in the crystal
540  // if( ecal ) theGrid->addHit(ri*theECAL->moliereRadius(),phi);
541  // Now the *moliereRadius is done in EcalHitMaker
542  if (ecal) {
543  if (detailedShowerTail) {
544  // std::cout << "About to call addHitDepth " << std::endl;
545  double depth;
546  do {
548  } while (depth > t);
549  theGrid->addHitDepth(ri, phi, depth);
550  // std::cout << " Done " << std::endl;
551  } else
552  theGrid->addHit(ri, phi);
553  } else if (hasPreshower && presh1)
554  thePreshower->addHit(ri, phi, 1);
555  else if (hasPreshower && presh2)
556  thePreshower->addHit(ri, phi, 2);
557  else if (hcal) {
558  // std::cout << " About to add a spot in the HCAL" << status << std::endl;
559  theHcalHitMaker->addHit(ri, phi);
560  // std::cout << " Added a spot in the HCAL" << status << std::endl;
561  }
562  // if (ecal) E9 += SpotEnergy;
563  // if (presh1) { E1 += SpotEnergy; ++n1; }
564  // if (presh2) { E2 += SpotEnergy; ++n2; }
565 
566  Etot[i] += spote;
567  }
568  }
569  }
570  // std::cout << " Done with the step " << std::endl;
571  // The shower!
572  //myHistos->fill("h500",theSpot.z(),theSpot.perp());
573  }
574  // std::cout << " nPart " << nPart << std::endl;
575  }
576  // std::cout << " Finshed the step loop " << std::endl;
577  // myHistos->fill("h500",E1+0.7*E2,E9);
578  // myHistos->fill("h501",n1+0.7*n2,E9);
579  // myHistos->fill("h400",n1);
580  // myHistos->fill("h401",n2);
581  // myHistos->fill("h402",E9+E1+0.7*E2);
582  // if(!standalone)theGrid->printGrid();
583  /*
584  double Etotal = 0.;
585  for (unsigned i = 0; i < nPart; ++i) {
586  // myHistos->fill("h10",Etot[i]);
587  Etotal += Etot[i];
588  }
589  */
590 
591  // std::cout << "Etotal = " << Etotal << " nPart = "<< nPart << std::endl;
592  // std::cout << "totECalc = " << totECalc << std::endl;
593 
594  // myHistos->fill("h20",Etotal);
595  // if(thePreshower)
596  // std::cout << " PS " << thePreshower->layer1Calibrated() << " " << thePreshower->layer2Calibrated() << " " << thePreshower->totalCalibrated() << " " << ps1tot << " " <<ps2tot << " " << pstot << std::endl;
597 }
598 
599 double EMShower::gam(double x, double a) const {
600  // A stupid gamma function
601  return std::pow(x, a - 1.) * std::exp(-x);
602 }
603 
604 //double
605 //EMShower::deposit(double t, double a, double b, double dt) {
606 //
607 // // The number of integration steps (about 1 / X0)
608 // int numberOfSteps = (int)dt+1;
609 //
610 // // The size if the integration step
611 // double integrationstep = dt/(double)numberOfSteps;
612 //
613 // // Half this size
614 // double halfis = 0.5*integrationstep;
615 //
616 // double dE = 0.;
617 //
618 // for(double tt=t-dt+halfis;tt<t;tt+=integrationstep) {
619 //
620 // // Simpson integration over each of these steps
621 // dE += gam(b*(tt-halfis),a)
622 // + 4.*gam(b* tt ,a)
623 // + gam(b*(tt+halfis),a);
624 //
625 // }
626 //
627 // // Normalization
628 // dE *= b*integrationstep/tgamma(a)/6.;
629 //
630 // // There we go.
631 // return dE;
632 //}
633 
634 double EMShower::deposit(double t, double a, double b, double dt) {
635  myIncompleteGamma.a().setValue(a);
636  double b1 = b * (t - dt);
637  double b2 = b * t;
638  double result = 0.;
639  double rb1 = (b1 != 0.) ? myIncompleteGamma(b1) : 0.;
640  double rb2 = (b2 != 0.) ? myIncompleteGamma(b2) : 0.;
641  result = (rb2 - rb1);
642  return result;
643 }
644 
645 void EMShower::setIntervals(unsigned icomp, RadialInterval& rad) {
646  // std::cout << " Got the pointer " << std::endl;
647  const std::vector<double>& myValues((icomp) ? theParam->getTailIntervals() : theParam->getCoreIntervals());
648  // std::cout << " Got the vector " << myValues.size () << std::endl;
649  unsigned nvals = myValues.size() / 2;
650  for (unsigned iv = 0; iv < nvals; ++iv) {
651  // std::cout << myValues[2*iv] << " " << myValues[2*iv+1] <<std::endl;
652  rad.addInterval(myValues[2 * iv], myValues[2 * iv + 1]);
653  }
654 }
655 
657  if (myPresh != nullptr) {
658  thePreshower = myPresh;
659  hasPreshower = true;
660  }
661 }
662 
663 void EMShower::setHcal(HcalHitMaker* const myHcal) { theHcalHitMaker = myHcal; }
664 
665 double EMShower::deposit(double a, double b, double t) {
666  // std::cout << " Deposit " << std::endl;
667  myIncompleteGamma.a().setValue(a);
668  double b2 = b * t;
669  double result = 0.;
670  if (fabs(b2) < 1.e-9)
671  b2 = 1.e-9;
673  // std::cout << " deposit t = " << t << " " << result <<std::endl;
674  return result;
675 }
float dt
Definition: AMPTWrapper.h:136
weight_default_t b1[25]
Definition: b1.h:9
bool addHit(double r, double phi, unsigned layer=0) override
std::vector< const RawParticle * > *const thePart
Definition: EMShower.h:89
double getUmin(unsigned i) const
Lower limit of the argument in the radius generator.
std::vector< double > theNumberOfSpots
Definition: EMShower.h:93
bool isHom() const
a rough estimate of ECAL resolution sigma/E = resE/sqrt(E)
double meanLnAlpha(double lny) const
void prepareSteps()
Computes the steps before the real compute.
Definition: EMShower.cc:121
std::vector< double > maximumOfShower
Definition: EMShower.h:108
double totalX0() const
Definition: EcalHitMaker.h:49
int32_t *__restrict__ iv
double criticalEnergy() const override
Critical energy in GeV (2.66E-3*(x0*Z/A)^1.1): 8.74E-3 for Standard ECAL.
std::vector< double > aSpot
Definition: EMShower.h:102
const HCALProperties * hcalProperties() const
EMShower(RandomEngineAndDistribution const *engine, GammaFunctionGenerator *gamma, EMECALShowerParametrization *const myParam, std::vector< const RawParticle *> *const myPart, EcalHitMaker *const myGrid=nullptr, PreshowerHitMaker *const myPreshower=nullptr, bool bFixedLength=false)
Definition: EMShower.cc:16
double deposit(double t, double a, double b, double dt)
Definition: EMShower.cc:634
double ps1TotalX0() const
Definition: EcalHitMaker.h:58
const RandomEngineAndDistribution * random
Definition: EMShower.h:139
const std::vector< double > & getCoreIntervals() const
const HCALProperties * theHCAL
Definition: EMShower.h:84
double rC(double tau, double E) const
void setPreshower(PreshowerHitMaker *const myPresh)
set the preshower address
Definition: EMShower.cc:656
const PreshowerLayer2Properties * layer2Properties() const
double x0DepthOffset() const
get the offset (e.g the number of X0 after which the shower starts)
Definition: EcalHitMaker.h:55
const ECALProperties * theECAL
Definition: EMShower.h:83
void setIntervals(unsigned icomp, RadialInterval &rad)
Definition: EMShower.cc:645
void compute()
Compute the shower longitudinal and lateral development.
Definition: EMShower.cc:263
std::vector< double > Etot
Definition: EMShower.h:94
double hOverPi() const
double mipsPerGeV() const override
Number of Mips/GeV [Default : 41.7 Mips/GeV or 24 MeV/Mips].
unsigned nIntervals() const
Number of intervals.
double hcalTotalX0() const
in the HCAL
Definition: EcalHitMaker.h:73
bool stepsCalculated
Definition: EMShower.h:120
bool addHit(double r, double phi, unsigned layer=0) override
add the hit in the HCAL in local coordinates
Definition: HcalHitMaker.cc:30
PreshowerHitMaker * thePreshower
Definition: EMShower.h:126
std::vector< std::vector< double > > depositedEnergy
Definition: EMShower.h:109
Definition: TTTypes.h:54
Steps steps
Definition: EMShower.h:118
bool addHitDepth(double r, double phi, double depth=-1)
T sqrt(T t)
Definition: SSEVec.h:19
double getSpotEnergy(unsigned i) const
Spot energy in a given interval.
double ecalTotalX0() const
in the ECAL
Definition: EcalHitMaker.h:67
bool addHit(double r, double phi, unsigned layer=0) override
double innerDepth
Definition: EMShower.h:111
double p(double tau, double E) const
HcalHitMaker * theHcalHitMaker
Definition: EMShower.h:129
double getX0back() const
Definition: EcalHitMaker.h:104
double gam(double x, double a) const
Definition: EMShower.cc:599
unsigned int nPart
Definition: EMShower.h:90
const PreshowerLayer1Properties * layer1Properties() const
std::vector< double > meanDepth
Definition: EMShower.h:110
weight_default_t b2[10]
Definition: b2.h:9
void setSpotEnergy(double e) override
Set the spot energy.
Definition: HcalHitMaker.h:26
double spotFraction() const
Spot fraction wrt ECAL.
double sigmaLnAlpha(double lny) const
double rT(double tau, double E) const
void setParameters(double a, double b, double xm)
The parameters must be set before shooting.
bool bFixedLength_
Definition: EMShower.h:144
std::vector< double > photos
Definition: EMShower.h:96
double gaussShoot(double mean=0.0, double sigma=1.0) const
const std::vector< double > & getTailIntervals() const
#define M_PI
const ECALProperties * ecalProperties() const
double ps2eeTotalX0() const
Definition: EcalHitMaker.h:64
bool hasPreshower
Definition: EMShower.h:132
double mipsPerGeV() const override
Number of Mips/GeV [Default : 59.5 Mips/GeV or 0.7*24 MeV/Mips].
double globalMaximum
Definition: EMShower.h:113
double resE() const
a rough estimate of ECAL resolution sigma/E = resE/sqrt(E)
double b
Definition: hdecay.h:118
double meanAlphaSpot(double alpha) const
const PreshowerLayer2Properties * theLayer2
Definition: EMShower.h:86
bool getPads(double depth, bool inCm=false)
unsigned int poissonShoot(double mean) const
virtual double lightCollectionEfficiency() const =0
Light Collection efficiency.
const PreshowerLayer1Properties * theLayer1
Definition: EMShower.h:85
std::vector< double > a
Definition: EMShower.h:98
double shoot(RandomEngineAndDistribution const *) const
double ps2TotalX0() const
total number of X0 in the PS (Layer2).
Definition: EcalHitMaker.h:61
double a
Definition: hdecay.h:119
double outerDepth
Definition: EMShower.h:111
virtual double lightCollectionUniformity() const =0
Light Collection uniformity.
float x
EMECALShowerParametrization *const theParam
Definition: EMShower.h:80
unsigned getNumberOfSpots(unsigned i) const
Number of spots in a given interval.
EcalHitMaker * theGrid
Definition: EMShower.h:123
GammaFunctionGenerator * myGammaGenerator
Definition: EMShower.h:142
std::vector< double > Ti
Definition: EMShower.h:100
step
Definition: StallMonitor.cc:98
double correlationAlphaT(double lny) const
std::vector< double > TSpot
Definition: EMShower.h:101
double flatShoot(double xmin=0.0, double xmax=1.0) const
unsigned nSteps
Definition: EMShower.h:119
Genfun::IncompleteGamma myIncompleteGamma
Definition: EMShower.h:136
std::vector< double > b
Definition: EMShower.h:99
double totalEnergy
Definition: EMShower.h:115
std::vector< double > E
Definition: EMShower.h:95
long double T
virtual double photoStatistics() const =0
Photostatistics (photons/GeV) in the homegeneous material.
double getUmax(unsigned i) const
Upper limit of the argument in the radius generator.
std::pair< unsigned int, double > Step
Definition: EMShower.h:30
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:29
bool setDepth(double, bool inCm=false)
set the depth in X0 or Lambda0 units depending on showerType
void setSpotEnergy(double e) override
Definition: EcalHitMaker.h:112
void addInterval(double, double)
void setHcal(HcalHitMaker *const myHcal)
set the HCAL address
Definition: EMShower.cc:663
void setSpotEnergy(double e) override
std::vector< double > bSpot
Definition: EMShower.h:103