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