CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
GflashEMShowerProfile.cc
Go to the documentation of this file.
1 //
2 // $Id: GflashEMShowerProfile.cc,v 1.4 2010/04/30 19:09:28 dwjang Exp $
3 // initial setup : Soon Jun & Dongwook Jang
4 // Translated from Fortran code.
5 //
7 
15 
16 #include <CLHEP/GenericFunctions/IncompleteGamma.hh>
17 #include <CLHEP/Units/PhysicalConstants.h>
18 #include <CLHEP/Random/Randomize.h>
19 #include <CLHEP/Random/RandGaussQ.h>
20 
22 {
23  theBField = parSet.getParameter<double>("bField");
24  theEnergyScaleEB = parSet.getParameter<double>("energyScaleEB");
25  theEnergyScaleEE = parSet.getParameter<double>("energyScaleEE");
26 
28 
29  theShowino = new GflashShowino();
30 
32 
33 }
34 
35 
37 {
38  if(theShowino) delete theShowino;
39 }
40 
41 void GflashEMShowerProfile::initialize(int showerType, double energy, double globalTime, double charge,
43 {
44  theShowino->initialize(showerType, energy, globalTime, charge,
45  position, momentum, theBField);
46 }
47 
49 {
50  // This part of code is copied from the original GFlash Fortran code.
51  // reference : hep-ex/0001020v1
52  // The units used in Geant4 internally are in mm, MeV.
53  // For simplicity, the units here are in cm, GeV.
54 
55  const double energyCutoff = 0.01;
56  const int maxNumberOfSpots = 100000;
57 
58  double incomingEnergy = theShowino->getEnergy();
59  Gflash3Vector showerStartingPosition = theShowino->getPositionAtShower();
60 
61  //find the calorimeter at the shower starting point
62  jCalorimeter = Gflash::getCalorimeterNumber(showerStartingPosition);
63 
64  double logEinc = std::log(incomingEnergy);
65  double y = incomingEnergy / Gflash::criticalEnergy; // y = E/Ec, criticalEnergy is in GeV
66  double logY = std::log(y);
67 
68  // Total number of spots are not yet optimized.
69  double nSpots = 93.0 * std::log(Gflash::Z[jCalorimeter]) * std::pow(incomingEnergy,0.876);
70 
71  //path Length from the origin to the shower starting point in cm
72  double pathLength0 = theShowino->getPathLengthAtShower();
73  double pathLength = pathLength0; // this will grow along the shower development
74 
75  //--- 2.2 Fix intrinsic properties of em. showers.
76 
77  double fluctuatedTmax = std::log(logY - 0.7157);
78  double fluctuatedAlpha = std::log(0.7996 +(0.4581 + 1.8628/Gflash::Z[jCalorimeter])*logY);
79 
80  double sigmaTmax = 1.0/( -1.4 + 1.26 * logY);
81  double sigmaAlpha = 1.0/( -0.58 + 0.86 * logY);
82  double rho = 0.705 - 0.023 * logY;
83  double sqrtPL = std::sqrt((1.0+rho)/2.0);
84  double sqrtLE = std::sqrt((1.0-rho)/2.0);
85 
86  double norm1 = CLHEP::RandGaussQ::shoot();
87  double norm2 = CLHEP::RandGaussQ::shoot();
88  double tempTmax = fluctuatedTmax + sigmaTmax*(sqrtPL*norm1 + sqrtLE*norm2);
89  double tempAlpha = fluctuatedAlpha + sigmaAlpha*(sqrtPL*norm1 - sqrtLE*norm2);
90 
91  // tmax, alpha, beta : parameters of gamma distribution
92  double tmax = std::exp(tempTmax);
93  double alpha = std::exp(tempAlpha);
94  double beta = std::max(0.0,(alpha - 1.0)/tmax);
95 
96  // spot fluctuations are added to tmax, alpha, beta
97  double averageTmax = logY-0.858;
98  double averageAlpha = 0.21+(0.492+2.38/Gflash::Z[jCalorimeter])*logY;
99  double spotTmax = averageTmax * (0.698 + .00212*Gflash::Z[jCalorimeter]);
100  double spotAlpha = averageAlpha * (0.639 + .00334*Gflash::Z[jCalorimeter]);
101  double spotBeta = std::max(0.0,(spotAlpha-1.0)/spotTmax);
102 
103  if(theHisto->getStoreFlag()) {
104  theHisto->em_incE->Fill(incomingEnergy);
105  theHisto->em_ssp_rho->Fill(showerStartingPosition.rho());
106  theHisto->em_ssp_z->Fill(showerStartingPosition.z());
107  }
108 
109  // parameters for lateral distribution and fluctuation
110  double z1=0.0251+0.00319*logEinc;
111  double z2=0.1162-0.000381*Gflash::Z[jCalorimeter];
112 
113  double k1=0.659 - 0.00309 * Gflash::Z[jCalorimeter];
114  double k2=0.645;
115  double k3=-2.59;
116  double k4=0.3585+ 0.0421*logEinc;
117 
118  double p1=2.623 -0.00094*Gflash::Z[jCalorimeter];
119  double p2=0.401 +0.00187*Gflash::Z[jCalorimeter];
120  double p3=1.313 -0.0686*logEinc;
121 
122  // @@@ dwjang, intial tuning by comparing 20-150GeV TB data : e25Scale = 1.006 for EB with ecalNotContainment = 1.0.
123  // Now e25Scale is a configurable parameter with default ecalNotContainment which is 0.97 for EB and 0.975 for EE.
124  // So if ecalNotContainment constants are to be changed in the future, e25Scale should be changed accordingly.
125  double e25Scale = 1.0;
126  if(jCalorimeter == Gflash::kESPM) e25Scale = theEnergyScaleEB;
127  else if(jCalorimeter == Gflash::kENCA) e25Scale = theEnergyScaleEE;
128 
129  // @@@ dwjang, intial tuning by comparing 20-150GeV TB data : p1 *= 0.965
130  p1 *= 0.965;
131 
132  // preparation of longitudinal integration
133  double stepLengthLeft = getDistanceToOut(jCalorimeter);
134 
135  int nSpots_sd = 0; // count total number of spots in SD
136  double zInX0 = 0.0; // shower depth in X0 unit
137  double deltaZInX0 = 0.0; // segment of depth in X0 unit
138  double deltaZ = 0.0; // segment of depth in cm
139  double stepLengthLeftInX0 = 0.0; // step length left in X0 unit
140 
141  const double divisionStepInX0 = 0.1; //step size in X0 unit
142  double energy = incomingEnergy; // energy left in GeV
143 
144  Genfun::IncompleteGamma gammaDist;
145 
146  double energyInGamma = 0.0; // energy in a specific depth(z) according to Gamma distribution
147  double preEnergyInGamma = 0.0; // energy calculated in a previous depth
148  double sigmaInGamma = 0.; // sigma of energy in a specific depth(z) according to Gamma distribution
149  double preSigmaInGamma = 0.0; // sigma of energy in a previous depth
150 
151  //energy segment in Gamma distribution of shower in each step
152  double deltaEnergy =0.0 ; // energy in deltaZ
153  int spotCounter = 0; // keep track of number of spots generated
154 
155  //step increment along the shower direction
156  double deltaStep = 0.0;
157 
158  theGflashHitList.clear();
159 
160  // loop for longitudinal integration
161  while(energy > 0.0 && stepLengthLeft > 0.0) {
162 
163  stepLengthLeftInX0 = stepLengthLeft / Gflash::radLength[jCalorimeter];
164 
165  if ( stepLengthLeftInX0 < divisionStepInX0 ) {
166  deltaZInX0 = stepLengthLeftInX0;
167  deltaZ = deltaZInX0 * Gflash::radLength[jCalorimeter];
168  stepLengthLeft = 0.0;
169  }
170  else {
171  deltaZInX0 = divisionStepInX0;
172  deltaZ = deltaZInX0 * Gflash::radLength[jCalorimeter];
173  stepLengthLeft -= deltaZ;
174  }
175 
176  zInX0 += deltaZInX0;
177 
178  int nSpotsInStep = 0;
179 
180  if ( energy > energyCutoff ) {
181  preEnergyInGamma = energyInGamma;
182  gammaDist.a().setValue(alpha); //alpha
183  energyInGamma = gammaDist(beta*zInX0); //beta
184  double energyInDeltaZ = energyInGamma - preEnergyInGamma;
185  deltaEnergy = std::min(energy,incomingEnergy*energyInDeltaZ);
186 
187  preSigmaInGamma = sigmaInGamma;
188  gammaDist.a().setValue(spotAlpha); //alpha spot
189  sigmaInGamma = gammaDist(spotBeta*zInX0); //beta spot
190  nSpotsInStep = std::max(1,int(nSpots * (sigmaInGamma - preSigmaInGamma)));
191  }
192  else {
193  deltaEnergy = energy;
194  preSigmaInGamma = sigmaInGamma;
195  nSpotsInStep = std::max(1,int(nSpots * (1.0 - preSigmaInGamma)));
196  }
197 
198  if ( deltaEnergy > energy || (energy-deltaEnergy) < energyCutoff ) deltaEnergy = energy;
199 
200  energy -= deltaEnergy;
201 
202  if ( spotCounter+nSpotsInStep > maxNumberOfSpots ) {
203  nSpotsInStep = maxNumberOfSpots - spotCounter;
204  if ( nSpotsInStep < 1 ) { // @@ check
205  edm::LogInfo("SimGeneralGFlash") << "GflashEMShowerProfile: Too Many Spots ";
206  edm::LogInfo("SimGeneralGFlash") << " - break to regenerate nSpotsInStep ";
207  break;
208  }
209  }
210 
211  // It begins with 0.5 of deltaZ and then icreases by 1 deltaZ
212  deltaStep += 0.5*deltaZ;
213  pathLength += deltaStep;
214  deltaStep = 0.5*deltaZ;
215 
216  // lateral shape and fluctuations for homogenous calo.
217  double tScale = tmax *alpha/(alpha-1.0) * (std::exp(fluctuatedAlpha)-1.0)/std::exp(fluctuatedAlpha);
218  double tau = std::min(10.0,(zInX0 - 0.5*deltaZInX0)/tScale);
219  double rCore = z1 + z2 * tau;
220  double rTail = k1 *( std::exp(k3*(tau-k2)) + std::exp(k4*(tau-k2))); // @@ check RT3 sign
221  double p23 = (p2 - tau)/p3;
222  double probabilityWeight = p1 * std::exp( p23 - std::exp(p23) );
223 
224  // Deposition of spots according to lateral distr.
225  // Apply absolute energy scale
226  // Convert into MeV unit
227  double hitEnergy = deltaEnergy / nSpotsInStep * e25Scale * CLHEP::GeV;
228  double hitTime = theShowino->getGlobalTime()*CLHEP::nanosecond + (pathLength - pathLength0)/30.0;
229 
230  GflashHit aHit;
231 
232  for (int ispot = 0 ; ispot < nSpotsInStep ; ispot++) {
233  spotCounter++;
234 
235  // Compute global position of generated spots with taking into account magnetic field
236  // Divide deltaZ into nSpotsInStep and give a spot a global position
237  double incrementPath = (deltaZ/nSpotsInStep)*(ispot+0.5 - 0.5*nSpotsInStep);
238 
239  // trajectoryPoint give a spot an imaginary point along the shower development
240  GflashTrajectoryPoint trajectoryPoint;
241  theShowino->getHelix()->getGflashTrajectoryPoint(trajectoryPoint,pathLength+incrementPath);
242 
243  double rShower = 0.0;
244  Gflash3Vector hitPosition = locateHitPosition(trajectoryPoint,rCore,rTail,probabilityWeight,rShower);
245 
246  // Convert into mm unit
247  hitPosition *= CLHEP::cm;
248 
249  if( std::fabs(hitPosition.getZ()/CLHEP::cm) > Gflash::Zmax[Gflash::kHE]) continue;
250 
251  // put energy and position to a Hit
252  aHit.setTime(hitTime);
253  aHit.setEnergy(hitEnergy);
254  aHit.setPosition(hitPosition);
255  theGflashHitList.push_back(aHit);
256 
257  double zInX0_spot = std::abs(pathLength+incrementPath - pathLength0)/Gflash::radLength[jCalorimeter];
258 
259  nSpots_sd++;
260 
261  // for histogramming
262  if(theHisto->getStoreFlag()) {
263  theHisto->em_long->Fill(zInX0_spot,hitEnergy/CLHEP::GeV);
264  theHisto->em_lateral->Fill(zInX0_spot,rShower/Gflash::rMoliere[jCalorimeter],hitEnergy/CLHEP::GeV);
265  theHisto->em_long_sd->Fill(zInX0_spot,hitEnergy/CLHEP::GeV);
266  theHisto->em_lateral_sd->Fill(zInX0_spot,rShower/Gflash::rMoliere[jCalorimeter],hitEnergy/CLHEP::GeV);
267  }
268 
269  } // end of for spot iteration
270 
271  } // end of while for longitudinal integration
272 
273  if(theHisto->getStoreFlag()) {
274  theHisto->em_nSpots_sd->Fill(nSpots_sd);
275  }
276 
277  // delete theGflashNavigator;
278 
279 }
280 
282 
283  double stepLengthLeft = 0.0;
284  if(kCalor == Gflash::kESPM ) {
287  }
288  else if (kCalor == Gflash::kENCA) {
289  double zsign = (theShowino->getPosition()).getEta() > 0 ? 1.0 : -1.0;
290  stepLengthLeft = theShowino->getHelix()->getPathLengthAtZ(zsign*Gflash::Zmax[Gflash::kENCA])
292  }
293  return stepLengthLeft;
294 
295 }
296 
298  double rCore, double rTail, double probability,double &rShower)
299 {
300  double u1 = CLHEP::HepUniformRand();
301  double u2 = CLHEP::HepUniformRand();
302  double rInRM = 0.0;
303 
304  if (u1 < probability ) {
305  rInRM = rCore* std::sqrt( u2/(1.0-u2) );
306  }
307  else {
308  rInRM = rTail * std::sqrt( u2/(1.0-u2) );
309  }
310 
311  rShower = rInRM * Gflash::rMoliere[jCalorimeter];
312 
313  // Uniform & random rotation of spot along the azimuthal angle
314  double azimuthalAngle = CLHEP::twopi*CLHEP::HepUniformRand();
315 
316  // actual spot position by adding a radial vector to a trajectoryPoint
318  rShower*std::cos(azimuthalAngle)*point.getOrthogonalUnitVector() +
319  rShower*std::sin(azimuthalAngle)*point.getCrossUnitVector();
320 
321  return position;
322 }
const double Z[kNumberCalorimeter]
const double beta
T getParameter(std::string const &) const
static GflashHistogram * instance()
float alpha
Definition: AMPTWrapper.h:95
double getPathLengthAtZ(double z) const
const double Zmax[kNumberCalorimeter]
Gflash3Vector getCrossUnitVector()
Gflash3Vector & getPosition()
Definition: GflashShowino.h:34
GflashTrajectory * getHelix()
Definition: GflashShowino.h:30
double getEnergy()
Definition: GflashShowino.h:24
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
Definition: DDAxes.h:10
#define abs(x)
Definition: mlp_lapack.h:159
#define min(a, b)
Definition: mlp_lapack.h:161
double getDistanceToOut(Gflash::CalorimeterNumber kCalor)
GflashHistogram * theHisto
Exp< T >::type exp(const T &t)
Definition: Exp.h:22
std::vector< GflashHit > theGflashHitList
double charge(const std::vector< uint8_t > &Ampls)
static int position[TOTALCHAMBERS][3]
Definition: ReadPGInfo.cc:509
Gflash::CalorimeterNumber jCalorimeter
const double rMoliere[kNumberCalorimeter]
const T & max(const T &a, const T &b)
double getPathLengthAtShower()
Definition: GflashShowino.h:26
T sqrt(T t)
Definition: SSEVec.h:28
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
void initialize(int showerType, double energy, double globalTime, double charge, Gflash3Vector &position, Gflash3Vector &momentum)
const double criticalEnergy
Gflash3Vector & getPositionAtShower()
Definition: GflashShowino.h:27
double p2[4]
Definition: TauolaWrapper.h:90
Gflash3Vector getOrthogonalUnitVector()
void getGflashTrajectoryPoint(GflashTrajectoryPoint &point, double s) const
Gflash3Vector locateHitPosition(GflashTrajectoryPoint &point, double rCore, double rTail, double probability, double &rShower)
static const double tmax[3]
const double radLength[kNumberCalorimeter]
Log< T >::type log(const T &t)
Definition: Log.h:22
CLHEP::Hep3Vector Gflash3Vector
Definition: Gflash3Vector.h:6
double getGlobalTime()
Definition: GflashShowino.h:32
CalorimeterNumber getCalorimeterNumber(const Gflash3Vector position)
Gflash3Vector & getPosition()
double p1[4]
Definition: TauolaWrapper.h:89
const double Rmax[kNumberCalorimeter]
GflashEMShowerProfile(edm::ParameterSet parSet)
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:40
*vegas h *****************************************************used in the default bin number in original ***version of VEGAS is ***a higher bin number might help to derive a more precise ***grade subtle point
Definition: invegas.h:5
double getPathLengthAtRhoEquals(double rho) const
double p3[4]
Definition: TauolaWrapper.h:91
void initialize(int showerType, double energy, double globalTime, double charge, Gflash3Vector &position, Gflash3Vector &momentum, double magneticField)