CMS 3D CMS Logo

HFGflash.cc
Go to the documentation of this file.
2 
3 #include "G4VPhysicalVolume.hh"
4 #include "G4Step.hh"
5 #include "G4Track.hh"
6 #include "G4Navigator.hh"
7 #include "G4NavigationHistory.hh"
8 #include <CLHEP/Units/PhysicalConstants.h>
9 #include <CLHEP/Units/SystemOfUnits.h>
10 
11 #include "Randomize.hh"
12 #include "G4TransportationManager.hh"
13 #include "G4VPhysicalVolume.hh"
14 #include "G4LogicalVolume.hh"
15 #include "G4VSensitiveDetector.hh"
16 #include "G4EventManager.hh"
17 #include "G4SteppingManager.hh"
18 #include "G4FastTrack.hh"
19 #include "G4ParticleTable.hh"
20 
21 #include "CLHEP/GenericFunctions/IncompleteGamma.hh"
22 
26 
29 
30 #include <cmath>
31 
32 using CLHEP::cm;
33 using CLHEP::degree;
34 using CLHEP::GeV;
35 using CLHEP::nanosecond;
36 using CLHEP::twopi;
37 
38 //#define EDM_ML_DEBUG
39 
41  edm::ParameterSet m_HF = p.getParameter<edm::ParameterSet>("HFGflash");
42  theBField = m_HF.getUntrackedParameter<double>("BField", 3.8);
43  theWatcherOn = m_HF.getUntrackedParameter<bool>("WatcherOn", true);
44  theFillHisto = m_HF.getUntrackedParameter<bool>("FillHisto", true);
45  edm::LogVerbatim("HFShower") << "HFGFlash:: Set B-Field to " << theBField << ", WatcherOn to " << theWatcherOn
46  << " and FillHisto to " << theFillHisto;
47 
48  theHelix = std::make_unique<GflashTrajectory>();
49  theGflashStep = std::make_unique<G4Step>();
50  theGflashNavigator = std::make_unique<G4Navigator>();
51  theGflashTouchableHandle = std::make_unique<G4TouchableHistory>();
52 
53 #ifdef EDM_ML_DEBUG
54  if (theFillHisto) {
56  if (tfile.isAvailable()) {
57  TFileDirectory showerDir = tfile->mkdir("GflashEMShowerProfile");
58 
59  em_incE = showerDir.make<TH1F>("em_incE", "Incoming energy (GeV)", 500, 0, 500.);
60  em_ssp_rho =
61  showerDir.make<TH1F>("em_ssp_rho", "Shower starting position;#rho (cm);Number of Events", 100, 100.0, 200.0);
62  em_ssp_z =
63  showerDir.make<TH1F>("em_ssp_z", "Shower starting position;z (cm);Number of Events", 2000, 0.0, 2000.0);
64  em_long =
65  showerDir.make<TH1F>("em_long", "Longitudinal Profile;Radiation Length;Number of Spots", 800, 800.0, 1600.0);
66  em_lateral = showerDir.make<TH1F>("em_lateral", "Lateral Profile;Radiation Length;Moliere Radius", 100, 0.0, 5.0);
67  em_2d = showerDir.make<TH2F>("em_2d",
68  "Lateral Profile vs. Shower Depth;Radiation Length;Moliere Radius",
69  800,
70  800.0,
71  1600.0,
72  100,
73  0.0,
74  5.0);
75  em_long_sd = showerDir.make<TH1F>("em_long_sd",
76  "Longitudinal Profile in Sensitive Detector;Radiation Length;Number of Spots",
77  800,
78  800.0,
79  1600.0);
81  showerDir.make<TH1F>("em_lateral_sd",
82  "Lateral Profile vs. Shower Depth in Sensitive Detector;Radiation Length;Moliere Radius",
83  100,
84  0.0,
85  5.0);
86  em_2d_sd =
87  showerDir.make<TH2F>("em_2d_sd",
88  "Lateral Profile vs. Shower Depth in Sensitive Detector;Radiation Length;Moliere Radius",
89  800,
90  800.0,
91  1600.0,
92  100,
93  0.0,
94  5.0);
95  em_ze = showerDir.make<TH2F>(
96  "em_ze", "Profile vs. Energy;Radiation Length;Moliere Radius", 800, 800.0, 1600.0, 1000, 0.0, 1.0);
97  em_ratio = showerDir.make<TH2F>(
98  "em_ratio", "Profile vs. Energy;Radiation Length;Moliere Radius", 800, 800.0, 1600.0, 1000, 0.0, 100.0);
99  em_ratio_selected = showerDir.make<TH2F>("em_ratio_selected",
100  "Profile vs. Energy;Radiation Length;Moliere Radius",
101  800,
102  800.0,
103  1600.0,
104  1000,
105  0.0,
106  100.0);
107  em_nSpots_sd =
108  showerDir.make<TH1F>("em_nSpots_sd",
109  "Number of Gflash Spots in Sensitive Detector;Number of Spots;Number of Events",
110  100,
111  0.0,
112  100);
113  em_ze_ratio = showerDir.make<TH1F>("em_ze_ratio", "Ratio of Energy and Z Position", 1000, 0.0, 0.001);
114  } else {
115  theFillHisto = false;
116  edm::LogVerbatim("HFShower") << "HFGFlash::No file is available for saving"
117  << " histos so the flag is set to false";
118  }
119  }
120 #endif
122 }
123 
125 
126 std::vector<HFGflash::Hit> HFGflash::gfParameterization(const G4Step* aStep, bool onlyLong) {
127  double tempZCalo = 26; // Gflash::Z[jCalorimeter]
128  double hfcriticalEnergy = 0.021; // Gflash::criticalEnergy
129 
130  std::vector<HFGflash::Hit> hit;
131  HFGflash::Hit oneHit;
132 
133  auto const preStepPoint = aStep->GetPreStepPoint();
134  auto const track = aStep->GetTrack();
135 
136  // This part of code is copied from the original GFlash Fortran code.
137  // reference : hep-ex/0001020v1
138 
139  const G4double energyCutoff = 1;
140  const G4int maxNumberOfSpots = 10000000;
141 
142  G4ThreeVector showerStartingPosition = track->GetPosition() / cm;
143  G4ThreeVector showerMomentum = preStepPoint->GetMomentum() / GeV;
145 
146  const G4double invgev = 1.0 / CLHEP::GeV;
147  G4double energy = preStepPoint->GetTotalEnergy() * invgev; // energy left in GeV
148  G4double logEinc = std::log(energy);
149 
150  G4double y = energy / hfcriticalEnergy; // y = E/Ec, criticalEnergy is in GeV
151  G4double logY = std::log(y);
152 
153  G4double nSpots = 93.0 * std::log(tempZCalo) * energy; // total number of spot due linearization
154  if (energy < 1.6)
155  nSpots = 140.4 * std::log(tempZCalo) * std::pow(energy, 0.876);
156 
157  // // implementing magnetic field effects
158  double charge = track->GetStep()->GetPreStepPoint()->GetCharge();
159  theHelix->initializeTrajectory(showerMomentum, showerStartingPosition, charge, theBField);
160 
161  G4double pathLength0 = theHelix->getPathLengthAtZ(showerStartingPosition.getZ());
162  G4double pathLength = pathLength0; // this will grow along the shower development
163 
164  //--- 2.2 Fix intrinsic properties of em. showers.
165 
166  G4double fluctuatedTmax = std::log(logY - 0.7157);
167  G4double fluctuatedAlpha = std::log(0.7996 + (0.4581 + 1.8628 / tempZCalo) * logY);
168 
169  G4double sigmaTmax = 1.0 / (-1.4 + 1.26 * logY);
170  G4double sigmaAlpha = 1.0 / (-0.58 + 0.86 * logY);
171  G4double rho = 0.705 - 0.023 * logY;
172  G4double sqrtPL = std::sqrt((1.0 + rho) / 2.0);
173  G4double sqrtLE = std::sqrt((1.0 - rho) / 2.0);
174 
175  G4double norm1 = G4RandGauss::shoot();
176  G4double norm2 = G4RandGauss::shoot();
177  G4double tempTmax = fluctuatedTmax + sigmaTmax * (sqrtPL * norm1 + sqrtLE * norm2);
178  G4double tempAlpha = fluctuatedAlpha + sigmaAlpha * (sqrtPL * norm1 - sqrtLE * norm2);
179 
180  // tmax, alpha, beta : parameters of gamma distribution
181  G4double tmax = std::exp(tempTmax);
182  G4double alpha = std::exp(tempAlpha);
183  G4double beta = (alpha - 1.0) / tmax;
184 
185  if (!alpha)
186  return hit;
187  if (!beta)
188  return hit;
189  if (alpha < 0.00001)
190  return hit;
191  if (beta < 0.00001)
192  return hit;
193 
194  // spot fluctuations are added to tmax, alpha, beta
195  G4double averageTmax = logY - 0.858;
196  G4double averageAlpha = 0.21 + (0.492 + 2.38 / tempZCalo) * logY;
197  G4double spotTmax = averageTmax * (0.698 + .00212 * tempZCalo);
198  G4double spotAlpha = averageAlpha * (0.639 + .00334 * tempZCalo);
199  G4double spotBeta = (spotAlpha - 1.0) / spotTmax;
200 
201  if (!spotAlpha)
202  return hit;
203  if (!spotBeta)
204  return hit;
205  if (spotAlpha < 0.00001)
206  return hit;
207  if (spotBeta < 0.00001)
208  return hit;
209 
210 #ifdef EDM_ML_DEBUG
211  edm::LogVerbatim("HFShower") << "HFGflash: Incoming energy = " << energy << " Position (rho,z) = ("
212  << showerStartingPosition.rho() << ", " << showerStartingPosition.z() << ")";
213 
214  if (theFillHisto) {
215  em_incE->Fill(energy);
216  em_ssp_rho->Fill(showerStartingPosition.rho());
217  em_ssp_z->Fill(std::abs(showerStartingPosition.z()));
218  }
219 #endif
220  // parameters for lateral distribution and fluctuation
221  G4double z1 = 0.0251 + 0.00319 * logEinc;
222  G4double z2 = 0.1162 - 0.000381 * tempZCalo;
223 
224  G4double k1 = 0.659 - 0.00309 * tempZCalo;
225  G4double k2 = 0.645;
226  G4double k3 = -2.59;
227  G4double k4 = 0.3585 + 0.0421 * logEinc;
228 
229  G4double p1 = 2.623 - 0.00094 * tempZCalo;
230  G4double p2 = 0.401 + 0.00187 * tempZCalo;
231  G4double p3 = 1.313 - 0.0686 * logEinc;
232 
233  // // @@@ dwjang, intial tuning by comparing 20-150GeV TB data
234  // // the width of energy response is not yet tuned.
235  const G4double e25Scale = 1.03551;
236  z1 *= 9.76972e-01 - 3.85026e-01 * std::tanh(1.82790e+00 * std::log(energy) - 3.66237e+00);
237  p1 *= 0.96;
238 
239 #ifdef EDM_ML_DEBUG
240  G4int nSpots_sd = 0; // count total number of spots in SD
241 #endif
242 
243  G4double stepLengthLeft = 10000;
244  G4double zInX0 = 0.0; // shower depth in X0 unit
245  G4double deltaZInX0 = 0.0; // segment of depth in X0 unit
246  G4double deltaZ = 0.0; // segment of depth in cm
247  G4double stepLengthLeftInX0 = 0.0; // step length left in X0 unit
248 
249  const G4double divisionStepInX0 = 0.1; //step size in X0 unit
250 
251  Genfun::IncompleteGamma gammaDist;
252 
253  G4double energyInGamma = 0.0; // energy in a specific depth(z) according to Gamma distribution
254  G4double preEnergyInGamma = 0.0; // energy calculated in a previous depth
255  G4double sigmaInGamma = 0.; // sigma of energy in a specific depth(z) according to Gamma distribution
256  G4double preSigmaInGamma = 0.0; // sigma of energy in a previous depth
257 
258  //energy segment in Gamma distribution of shower in each step
259  G4double deltaEnergy = 0.0; // energy in deltaZ
260  G4int spotCounter = 0; // keep track of number of spots generated
261 
262  //step increment along the shower direction
263  G4double deltaStep = 0.0;
264 
265  // Uniqueness of G4Step is important otherwise hits won't be created.
266  G4double timeGlobal = preStepPoint->GetGlobalTime();
267 
268  theGflashNavigator->SetWorldVolume(
269  G4TransportationManager::GetTransportationManager()->GetNavigatorForTracking()->GetWorldVolume());
270 
271  // // loop for longitudinal integration
272 
273 #ifdef EDM_ML_DEBUG
274  edm::LogVerbatim("HFShower") << "HFGflash: Energy = " << energy << " Step Length Left = " << stepLengthLeft;
275 #endif
276  while (energy > 0.0 && stepLengthLeft > 0.0) {
277  stepLengthLeftInX0 = stepLengthLeft / Gflash::radLength[jCalorimeter];
278 
279  if (stepLengthLeftInX0 < divisionStepInX0) {
280  deltaZInX0 = stepLengthLeftInX0;
281  deltaZ = deltaZInX0 * Gflash::radLength[jCalorimeter];
282  stepLengthLeft = 0.0;
283  } else {
284  deltaZInX0 = divisionStepInX0;
285  deltaZ = deltaZInX0 * Gflash::radLength[jCalorimeter];
286  stepLengthLeft -= deltaZ;
287  }
288 
289  zInX0 += deltaZInX0;
290 
291 #ifdef EDM_ML_DEBUG
292  edm::LogVerbatim("HFShower") << "HFGflash: zInX0 = " << zInX0 << " spotBeta*zInX0 = " << spotBeta * zInX0;
293 #endif
294  if ((!zInX0) || (!(spotBeta * zInX0 != 0)) || (zInX0 < 0.01) || (spotBeta * zInX0 < 0.00001) ||
295  (!(zInX0 * beta != 0)) || (zInX0 * beta < 0.00001))
296  return hit;
297 
298  G4int nSpotsInStep = 0;
299 
300 #ifdef EDM_ML_DEBUG
301  edm::LogVerbatim("HFShower") << "HFGflash: Energy - Energy Cut off = " << energy - energyCutoff;
302 #endif
303 
304  if (energy > energyCutoff) {
305  preEnergyInGamma = energyInGamma;
306  gammaDist.a().setValue(alpha); //alpha
307 
308  energyInGamma = gammaDist(beta * zInX0); //beta
309  G4double energyInDeltaZ = energyInGamma - preEnergyInGamma;
310  deltaEnergy = std::min(energy, energy * energyInDeltaZ);
311 
312  preSigmaInGamma = sigmaInGamma;
313  gammaDist.a().setValue(spotAlpha); //alpha spot
314  sigmaInGamma = gammaDist(spotBeta * zInX0); //beta spot
315  nSpotsInStep = std::max(1, int(nSpots * (sigmaInGamma - preSigmaInGamma)));
316  } else {
317  deltaEnergy = energy;
318  preSigmaInGamma = sigmaInGamma;
319  nSpotsInStep = std::max(1, int(nSpots * (1.0 - preSigmaInGamma)));
320  }
321 
322  if (deltaEnergy > energy || (energy - deltaEnergy) < energyCutoff)
323  deltaEnergy = energy;
324 
325  energy -= deltaEnergy;
326 
327  if (spotCounter + nSpotsInStep > maxNumberOfSpots) {
328  nSpotsInStep = maxNumberOfSpots - spotCounter;
329  if (nSpotsInStep < 1)
330  nSpotsInStep = 1;
331  }
332 
333  // // It begins with 0.5 of deltaZ and then icreases by 1 deltaZ
334  deltaStep += 0.5 * deltaZ;
335  pathLength += deltaStep;
336  deltaStep = 0.5 * deltaZ;
337 
338  //lateral shape and fluctuations for homogenous calo.
339  G4double tScale = tmax * alpha / (alpha - 1.0) * (1.0 - std::exp(-fluctuatedAlpha));
340  G4double tau = std::min(10.0, (zInX0 - 0.5 * deltaZInX0) / tScale);
341  G4double rCore = z1 + z2 * tau;
342  G4double rTail = k1 * (std::exp(k3 * (tau - k2)) + std::exp(k4 * (tau - k2))); // @@ check RT3 sign
343  G4double p23 = (p2 - tau) / p3;
344  G4double probabilityWeight = p1 * std::exp(p23 - std::exp(p23));
345 
346  // Deposition of spots according to lateral distr.
347  // Apply absolute energy scale
348  // Convert into MeV unit
349  G4double emSpotEnergy = deltaEnergy / (nSpotsInStep * e25Scale * GeV);
350 
351 #ifdef EDM_ML_DEBUG
352  edm::LogVerbatim("HFShower") << "HFGflash: nSpotsInStep = " << nSpotsInStep;
353 #endif
354 
355  for (G4int ispot = 0; ispot < nSpotsInStep; ispot++) {
356  spotCounter++;
357  G4double u1 = G4UniformRand();
358  G4double u2 = G4UniformRand();
359  G4double rInRM = 0.0;
360 
361  if (u1 < probabilityWeight) {
362  rInRM = rCore * std::sqrt(u2 / (1.0 - u2));
363  } else {
364  rInRM = rTail * std::sqrt(u2 / (1.0 - u2));
365  }
366 
367  G4double rShower = rInRM * Gflash::rMoliere[jCalorimeter];
368 
369  //Uniform & random rotation of spot along the azimuthal angle
370  G4double azimuthalAngle = twopi * G4UniformRand();
371 
372  //Compute global position of generated spots with taking into account magnetic field
373  //Divide deltaZ into nSpotsInStep and give a spot a global position
374  G4double incrementPath = (deltaZ / nSpotsInStep) * (ispot + 0.5 - 0.5 * nSpotsInStep);
375 
376  // trajectoryPoint give a spot an imaginary point along the shower development
377  GflashTrajectoryPoint trajectoryPoint;
378  theHelix->getGflashTrajectoryPoint(trajectoryPoint, pathLength + incrementPath);
379 
380  G4ThreeVector SpotPosition0 = trajectoryPoint.getPosition() +
381  rShower * std::cos(azimuthalAngle) * trajectoryPoint.getOrthogonalUnitVector() +
382  rShower * std::sin(azimuthalAngle) * trajectoryPoint.getCrossUnitVector();
383 
385  // Convert into mm unit
386  SpotPosition0 *= cm;
387 
388  //---------------------------------------------------
389  // fill a fake step to send it to hit maker
390  //---------------------------------------------------
391 
392  // to make a different time for each fake step. (0.03 nsec is corresponding to 1cm step size)
393  timeGlobal += 0.0001 * nanosecond;
394 
395  //fill equivalent changes to a (fake) step associated with a spot
396 
397  G4double zInX0_spot = std::abs(pathLength + incrementPath - pathLength0) / Gflash::radLength[jCalorimeter];
398 
399 #ifdef EDM_ML_DEBUG
400  edm::LogVerbatim("HFShower") << "HFGflash: zInX0_spot,emSpotEnergy/GeV =" << zInX0_spot << " , "
401  << emSpotEnergy / GeV << "emSpotEnergy/GeV =" << emSpotEnergy / GeV;
402 #endif
403 
404  if (zInX0_spot <= 0)
405  continue;
406  if (emSpotEnergy <= 0)
407  continue;
408  if (rShower / Gflash::rMoliere[jCalorimeter] <= 0)
409  continue;
410 
411  oneHit.depth = 1;
412 
413 #ifdef EDM_ML_DEBUG
414  if (theFillHisto) {
415  em_long->Fill(SpotPosition0.z() / cm, emSpotEnergy * invgev);
416  em_lateral->Fill(rShower / Gflash::rMoliere[jCalorimeter], emSpotEnergy * invgev);
417  em_2d->Fill(SpotPosition0.z() / cm, rShower / Gflash::rMoliere[jCalorimeter], emSpotEnergy * invgev);
418  }
419 #endif
420 
422  //if(SpotPosition0 == 0) continue;
423 
424  double energyratio = emSpotEnergy / (preStepPoint->GetTotalEnergy() / (nSpots * e25Scale));
425 
426  if (emSpotEnergy / GeV < 0.0001)
427  continue;
428  if (energyratio > 80)
429  continue;
430 
431  double zshift = 0;
432  if (SpotPosition0.z() > 0)
433  zshift = 18;
434  if (SpotPosition0.z() < 0)
435  zshift = -18;
436 
437  G4ThreeVector gfshift(0, 0, zshift * (pow(100, 0.1) / pow(energy, 0.1)));
438 
439  G4ThreeVector SpotPosition = gfshift + SpotPosition0;
440 
441  double LengthWeight = std::fabs(std::pow(SpotPosition0.z() / 11370, 1));
442  if (G4UniformRand() > 0.0021 * energyratio * LengthWeight)
443  continue;
444 
445  oneHit.position = SpotPosition;
446  oneHit.time = timeGlobal;
447  oneHit.edep = emSpotEnergy * invgev;
448  hit.push_back(oneHit);
449 #ifdef EDM_ML_DEBUG
450  nSpots_sd++;
451 #endif
452 
453  } // end of for spot iteration
454 
455  } // end of while for longitudinal integration
456 #ifdef EDM_ML_DEBUG
457  if (theFillHisto) {
458  em_nSpots_sd->Fill(nSpots_sd);
459  }
460 #endif
461  return hit;
462 }
Log< level::Info, true > LogVerbatim
virtual ~HFGflash()
Definition: HFGflash.cc:124
TH2F * em_ze
Definition: HFGflash.h:67
std::vector< Hit > gfParameterization(const G4Step *aStep, bool onlyLong=false)
Definition: HFGflash.cc:126
void tanh(data_T data[CONFIG_T::n_in], res_T res[CONFIG_T::n_in])
Gflash3Vector getCrossUnitVector()
TH1F * em_ssp_z
Definition: HFGflash.h:65
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
Gflash::CalorimeterNumber jCalorimeter
Definition: HFGflash.h:52
G4double theBField
Definition: HFGflash.h:56
T getUntrackedParameter(std::string const &, T const &) const
bool theFillHisto
Definition: HFGflash.h:55
T * make(const Args &...args) const
make new ROOT object
const double rMoliere[kNumberCalorimeter]
static const float invgev
Definition: TimingSD.cc:32
std::unique_ptr< GflashTrajectory > theHelix
Definition: HFGflash.h:47
T sqrt(T t)
Definition: SSEVec.h:23
Definition: tfile.py:1
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
TH2F * em_ratio_selected
Definition: HFGflash.h:67
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double edep
Definition: HFGflash.h:40
bool theWatcherOn
Definition: HFGflash.h:54
TH2F * em_ratio
Definition: HFGflash.h:67
TH1F * em_ze_ratio
Definition: HFGflash.h:66
HFGflash(edm::ParameterSet const &p)
Definition: HFGflash.cc:40
Gflash3Vector getOrthogonalUnitVector()
static const double tmax[3]
TH1F * em_ssp_rho
Definition: HFGflash.h:65
const double radLength[kNumberCalorimeter]
double time
Definition: HFGflash.h:39
TH1F * em_lateral_sd
Definition: HFGflash.h:66
TH1F * em_nSpots_sd
Definition: HFGflash.h:66
TH1F * em_lateral
Definition: HFGflash.h:65
TH1F * em_long
Definition: HFGflash.h:65
Gflash3Vector & getPosition()
G4ThreeVector position
Definition: HFGflash.h:37
std::unique_ptr< G4Navigator > theGflashNavigator
Definition: HFGflash.h:49
TH1F * em_incE
Definition: HFGflash.h:65
std::unique_ptr< G4TouchableHistory > theGflashTouchableHandle
Definition: HFGflash.h:50
TH1F * em_long_sd
Definition: HFGflash.h:66
TH2F * em_2d
Definition: HFGflash.h:67
std::unique_ptr< G4Step > theGflashStep
Definition: HFGflash.h:48
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:29
TH2F * em_2d_sd
Definition: HFGflash.h:67