CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
CSCGasCollisions.cc
Go to the documentation of this file.
1 // This implements the CSC gas ionization simulation.
2 // It requires the GEANT3-generated tables in the input file
3 // (default) MuonData/EndcapData/collisions.dat
4 
5 // Outstanding problems to fix 15-Oct-2003
6 // - ework must be re-tuned once eion or ework are removed before delta e range estimation.
7 // - logic of long-range delta e's must be revisited.
8 // - The code here needs to have diagnostic output removed, or reduced. PARTICULARLY filling of std::vectors!
9 // - 'gap' is a misnomer, when simhit entry and exit don't coincide with gap edges
10 // so the CSCCrossGap might better be named as a simhit-related thing.
11 // 22-Jan-2004 Corrected position of trap for 'infinite' loop while
12 // generating steps. Output files (debugV-flagged only) require SC flag.
13 // Increase deCut from 10 keV to 100 keV to accomodate protons!
14 
20 #include <iostream>
21 #include <fstream>
22 
23 // stdlib math functions
24 // for 'abs':
25 #include <cstdlib>
26 // for usual math functions:
27 #include <cmath>
28 
29 // stdlib container trickery
30 // for 'for_each':
31 #include <algorithm>
32 // for 'greater' and 'less':
33 #include <functional>
34 // for 'accumulate':
35 #include <numeric>
36 #include <iterator>
37 
38 using namespace std;
39 
40 CSCGasCollisions::CSCGasCollisions() : me("CSCGasCollisions"),
41  gasDensity( 2.1416e-03 ),
42  deCut( 1.e05 ), eion( 10.4 ), ework( 70.0 ), clusterExtent( 0.001 ),
43  theGammaBins(N_GAMMA, 0.), theEnergyBins(N_ENERGY, 0.),
44  theCollisionTable(N_ENTRIES, 0.), theCrossGap( 0 ),
45  theParticleDataTable(0),
46  theRandFlat(0),
47  theRandExponential(0),
48  saveGasCollisions ( false )
49 {
50 
51  edm::LogInfo(me) << "Constructing a " << me << ":";
52  edm::LogInfo(me) << "gas density = " << gasDensity << " g/cm3";
53  edm::LogInfo(me) << "max eloss per collision allowed = " << deCut/1000.
54  << " keV (for higher elosses, hits should have been simulated.)";
55  edm::LogInfo(me) << "ionization threshold = " << eion << " eV";
56  edm::LogInfo(me) << "effective work function = " << ework << " eV";
57  edm::LogInfo(me) << "cluster extent = " << clusterExtent*1.e04 << " micrometres";
58  edm::LogInfo(me) << "Save gas collision info to files when using debugV? " << saveGasCollisions;
59 
61 }
62 
64  edm::LogInfo(me) << "Destructing a " << me;
65  delete theCrossGap;
66  delete theRandFlat;
67  delete theRandExponential;
68 }
69 
71 
72  // I'd prefer to allow comments in the data file which means
73  // complications of reading line-by-line and then item-by-item.
74 
75  // Is float OK? Or do I need double?
76 
77  // Do I need any sort of error trapping?
78 
79  // We use the default CMSSW data file path
80  // We use the default file name 'collisions.dat'
81 
82  // This can be reset in .orcarc by SimpleConfigurable
83  // Muon:Endcap:CollisionsFile
84 
85  string path( getenv( "CMSSW_SEARCH_PATH" ) );
86  // TODO make configurable
87  string colliFile = "SimMuon/CSCDigitizer/data/collisions.dat";
88  FileInPath f1( path, colliFile );
89  if (f1() == 0 ) {
90  string errorMessage = "Input file " + colliFile + "not found";
91  edm::LogError("CSCGasCollisions") << errorMessage << " in path " << path
92  << "\nSet Muon:Endcap:CollisionsFile in .orcarc to the "
93  " location of the file relative to ORCA_DATA_PATH." ;
94  throw cms::Exception( " Endcap Muon gas collisions data file not found.");
95  }
96  else {
97  edm::LogInfo(me) << ": reading " << f1.name();
98  }
99 
100  ifstream & fin = *f1();
101 
102  if (fin == 0) {
103  string errorMessage = "Cannot open input file " + path + colliFile;
104  edm::LogError("CSCGasCollisions") << errorMessage;
105  throw cms::Exception(errorMessage);
106  }
107 
108  fin.clear( ); // Clear eof read status
109  fin.seekg( 0, ios::beg ); // Position at start of file
110 
111  // @@ We had better have the right sizes everywhere or all
112  // hell will break loose. There's no trapping.
113  LogTrace(me) << "Reading gamma bins";
114  int j = 0;
115  for(int i = 0; i<N_GAMMA; ++i) {
116  fin >> theGammaBins[i];
117  LogTrace(me) << ++j << " " << theGammaBins[i];
118  }
119 
120  j = 0;
121  LogTrace(me) << "Reading energy bins \n";
122  for(int i = 0; i<N_ENERGY; ++i) {
123  fin >> theEnergyBins[i];
124  LogTrace(me) << ++j << " " << theEnergyBins[i];
125  }
126 
127  j = 0;
128  LogTrace(me) << "Reading collisions table \n";
129 
130  for(int i = 0; i<N_ENTRIES; ++i) {
131  fin >> theCollisionTable[i];
132  LogTrace(me) << ++j << " " << theCollisionTable[i];
133  }
134 
135  fin.close();
136 }
137 
138 
140 {
141  theParticleDataTable = pdt;
142 }
143 
144 
145 void CSCGasCollisions::setRandomEngine(CLHEP::HepRandomEngine & engine)
146 {
147  theRandFlat = new CLHEP::RandFlat(engine);
148  theRandExponential = new CLHEP::RandExponential(engine);
149 }
150 
151 
152 void CSCGasCollisions::simulate( const PSimHit& simHit, const CSCLayer * layer,
153  std::vector<LocalPoint>& positions, std::vector<int>& electrons ) {
154 
155  const float epsilonL = 0.01; // Shortness of simhit 'length'
156  // const float max_gap_z = 1.5; // Gas gaps are 0.5 or 1.0 cm
157 
158  // Note that what I call the 'gap' may in fact be the 'length' of a PSimHit which
159  // does not start and end on the gap edges. This confuses the nomenclature at least.
160 
161  double mom = simHit.pabs();
162  int iam = simHit.particleType(); // PDG type
163  delete theCrossGap; // before building new one
164  assert(theParticleDataTable != 0);
165  ParticleData const * particle = theParticleDataTable->particle( simHit.particleType() );
166  double mass = 0.105658; // assume a muon
167  if(particle == 0)
168  {
169  edm::LogError("CSCGasCollisions") << "Cannot find particle of type " << simHit.particleType()
170  << " in the PDT";
171  }
172  else
173  {
174  mass = particle->mass();
175  }
176 
177  theCrossGap = new CSCCrossGap( mass, mom, simHit.exitPoint() - simHit.entryPoint() );
178  float gapSize = theCrossGap->length();
179 
180  // Test the simhit 'length' (beware of angular effects)
181  // if ( gapSize <= epsilonL || gapSize > max_gap_z ) {
182  if ( gapSize <= epsilonL ) {
183  LogTrace(me) << ": WARNING! simhit entry and exit are very close: \n"
184  << "\n entry = " << simHit.entryPoint()
185  << "\n exit = " << simHit.exitPoint()
186  << "\n particle type = " << iam << ", momentum = " << mom
187  << ", gap length = " << gapSize;
188  return; //@@ Just skip this PSimHit
189  }
190 
191  // Interpolate the table for current gamma value
192  // Extract collisions binned by energy loss values, for this gamma
193  std::vector<float> collisions(N_ENERGY);
194  double loggam = theCrossGap->logGamma();
195  fillCollisionsForThisGamma( static_cast<float>(loggam), collisions );
196 
197  double anmin = exp(collisions[N_ENERGY-1]);
198  double anmax = exp(collisions[0]);
199  double amu = anmax - anmin;
200 
201  LogTrace(me) << "collisions extremes = " << collisions[N_ENERGY-1]
202  << ", " << collisions[0] << "\n"
203  << "anmin = " << anmin << ", anmax = " << anmax << "\n"
204  << "amu = " << amu << "\n";
205 
206  float dedx = 0.; // total energy loss
207  double sum_steps = 0.; // total distance across gap (along simhit direction)
208  int n_steps = 0; // no. of steps/primary collisions
209  int n_try = 0; // no. of tries to generate steps
210  double step = -1.; // Sentinel for start
211 
212  //LocalPoint chamberLocalPoint( simHit.entryPoint() );
213  // translate to layer local coordinates
214  //GlobalPoint globalPoint( layer->chamber()->toGlobal(chamberLocalPoint) );
215  //LocalPoint layerLocalPoint( layer->toLocal(globalPoint) );
216  LocalPoint layerLocalPoint( simHit.entryPoint() );
217 
218  //std::cout << "DEBUG " << chamberLocalPoint << " " << layerLocalPoint << std::endl;
219  // step/primary collision loop
220  while ( sum_steps < gapSize) {
221  ++n_try;
222  if ( n_try > MAX_STEPS ) {
223  LogTrace(me) << ": n_try=" << n_try << " is too large. Skip simhit."
224  << "\n particle type=" << iam << ", momentum= " << mom
225  << "\n gapSize=" << gapSize << ", last step=" << step
226  << ", sum_steps=" << sum_steps << ", n_steps=" << n_steps;
227  break;
228  }
229  step = generateStep( amu );
230  if ( sum_steps + step > gapSize ) break;
231 
232  float eloss = generateEnergyLoss( amu, anmin, anmax, collisions );
233 
234  // Is the eloss too large? (then GEANT should have produced hits!)
235  if ( eloss > deCut ) {
236  LogTrace(me) << "eloss > " << deCut << " = " << eloss;
237  continue; // to generate another collision/step
238  }
239 
240  dedx += eloss; // the energy lost from the ionizing particle
241  sum_steps += step; // the position of the ionizing particle
242  ++n_steps; // the number of primary collisions
243 
244  if (n_steps > MAX_STEPS ) { // Extra-careful trap for bizarreness
245  edm::LogInfo(me) << ": n_steps=" << n_steps << " is too large. Skip simhit.";
246  edm::LogInfo(me) << "particle type=" << iam << ", momentum= " << mom;
247  edm::LogInfo(me) << "gapSize=" << gapSize << ", last step=" << step
248  << ", sum_steps=" << sum_steps;
249  break;
250  }
251  LogTrace(me) << "sum_steps = " << sum_steps << ", dedx = " << dedx;
252 
253  // Generate ionization.
254  // eion is the minimum energy at which ionization can occur in the gas
255  if ( eloss > eion ) {
256  layerLocalPoint += step * theCrossGap->unitVector(); // local point where the collision occurs
257  ionize( eloss, layerLocalPoint );
258  }
259  else {
260  LogTrace(me) << "Energy available = " << eloss <<
261  ", too low for ionization.";
262  }
263 
264  } // step/collision loop
265 
266  //TODO port this
267  //if ( debugV ) writeSummary( n_steps, sum_steps, dedx );
268 
269  // Return values in two container arguments
270  positions = theCrossGap->ionClusters();
271  electrons = theCrossGap->electrons();
272  return;
273 }
274 
275 double CSCGasCollisions::generateStep( double avCollisions ) const
276 {
277 // Generate a m.f.p. (1/avCollisions = cm/collision)
278  double step = (theRandExponential->fire())/avCollisions;
279 
280 // Without using CLHEP: approx random exponential by...
281 // double da = double(rand())/double(RAND_MAX);
282 // double step = -log(1.-da)/avCollisions;
283 
284  LogTrace(me) << " step = " << step;
285  // Next line only used to fill a container of 'step's for later diagnostic dumps
286  //if ( debugV ) theCrossGap->addStep( step );
287  return step;
288 }
289 
290 float CSCGasCollisions::generateEnergyLoss( double avCollisions,
291  double anmin, double anmax, const std::vector<float>& collisions ) const
292 {
293 // Generate a no. of collisions between collisions[0] and [N_ENERGY-1]
294  float lnColl = log(theRandFlat->fire(anmin, anmax));
295 
296 // Without using CLHEP: approx random between anmin and anmax
297 // double ra = double(rand())/double(RAND_MAX)*avCollisions;
298 // cout << "ra = " << ra << std::endl;
299 // float lnColl = static_cast<float>( log( ra ) );
300 
301  // Find energy loss for that number
302  float lnE = lnEnergyLoss( lnColl, collisions );
303  float eloss = exp(lnE);
304  // Compensate if gamma was actually below 1.1
305  if ( theCrossGap->gamma() < 1.1 ) eloss = eloss * 0.173554/theCrossGap->beta2();
306  LogTrace(me) << "eloss = " << eloss;
307  // Next line only used to fill container of eloss's for later diagnostic dumps
308  // if ( debugV ) theCrossGap->addEloss( eloss );
309  return eloss;
310 }
311 
312 void CSCGasCollisions::ionize( double energyAvailable, LocalPoint startHere ) const
313 {
314  while ( energyAvailable > eion ) {
315  LogTrace(me) << " NEW CLUSTER " << theCrossGap->noOfClusters() + 1 <<
316  " AT " << startHere;
317  LocalPoint newCluster( startHere );
318  theCrossGap->addCluster(newCluster);
319 
320  //@@ I consider NOT subtracting eion before calculating range to be a bug.
321  //@@ But this changes tuning of the algorithm so leave it until after the big rush to 7_5_0
322  //@@ energyAvailable -= eion;
323 
324  // Sauli CERN 77-09: delta e range with E in MeV (Sauli references Kobetich & Katz 1968,
325  // but I cannot find this expression in that set of papers.)
326  // Take HALF that range. //@@ Why? Why not...
327  double range = 0.5 * (0.71/gasDensity)*pow( energyAvailable*1.E-6, 1.72);
328  LogTrace(me) << " range = " << range;
329  if ( range < clusterExtent ) {
330 
331  // short-range delta e
332  // How many electrons can we make? Now use *average* energy for ionization (not *minimum*)
333  int nelec = static_cast<int>(energyAvailable/ework);
334  LogTrace(me) << "s-r delta energy in = " << energyAvailable;
335  energyAvailable -= nelec*(energyAvailable/ework);
336  // If still above eion (minimum, not average) add one more e
337  if ( energyAvailable > eion ) {
338  ++nelec;
339  energyAvailable -= eion;
340  }
341  LogTrace(me) << "s-r delta energy out = " << energyAvailable << ", nelec = " << nelec;
342  theCrossGap->addElectrons( nelec );
343  break;
344 
345  }
346  else {
347  // long-range delta e
348  LogTrace(me) << "l-r delta \n"
349  << "no. of electrons in cluster now = " << theCrossGap->noOfElectrons();
350  theCrossGap->addElectrons( 1 ); // Position is at startHere still
351 
352  bool new_range = false;
353  while ( !new_range && (energyAvailable>ework) ) {
354  energyAvailable -= ework;
355  while ( energyAvailable > eion ) {
356  double range2 = 0.5 * 0.71/gasDensity*pow( 1.E-6*energyAvailable, 1.72);
357  double drange = range - range2;
358  LogTrace(me) << " energy left = " << energyAvailable <<
359  ", range2 = " << range2 << ", drange = " << drange;
360  if ( drange < clusterExtent ) {
361  theCrossGap->addElectronToBack(); // increment last element
362  }
363  else {
364  startHere += drange*theCrossGap->unitVector(); // update delta e start position
365  range = range2; // update range
366  new_range = true; // Test range again
367  LogTrace(me) << "reset range to range2 and iterate";
368  }
369  break; // out of inner while energyAvailable>eion
370 
371  } // inner while energyAvailable>eion
372 
373  } // while !new_range && energyAvailable>ework
374 
375  // energyAvailable now less than ework, but still may be over eion...add an e
376  if ( energyAvailable > eion ) {
377  energyAvailable -= ework; // yes, it may go negative
378  theCrossGap->addElectronToBack(); // add one more e
379  }
380 
381  } // if range
382 
383  } // outer while energyAvailable>eion
384 }
385 
386 void CSCGasCollisions::writeSummary( int n_steps, double sum_steps, float dedx ) const
387 {
388  std::vector<LocalPoint> ion_clusters = theCrossGap->ionClusters();
389  std::vector<int> electrons = theCrossGap->electrons();
390  std::vector<float> elosses = theCrossGap->eLossPerStep();
391  std::vector<double> steps = theCrossGap->stepLengths();
392 
393  cout << "------------------" << std::endl;
394  cout << "AFTER CROSSING GAP" << std::endl;
395  cout << "No. of steps = " << n_steps << std::endl;
396  cout << "Check: stored steps = " << theCrossGap->noOfSteps() << std::endl;
397 
398  cout << "Lengths of steps: " << std::endl;
399  std::copy( steps.begin(), steps.end(), std::ostream_iterator<float>(cout,"\n"));
400  cout << std::endl;
401 
402  if ( saveGasCollisions ) {
403  ofstream of0("osteplen.dat",ios::app);
404  std::copy( steps.begin(), steps.end(), std::ostream_iterator<float>(of0,"\n"));
405  }
406 
407  cout << "Total sum of steps = " << sum_steps << std::endl;
408  if ( n_steps > 0 ) cout << "Average step length = " <<
409  sum_steps/float(n_steps) << std::endl;
410  cout << std::endl;
411 
412  cout << "Energy loss per collision:" << std::endl;
413  std::copy( elosses.begin(), elosses.end(), std::ostream_iterator<float>(cout,"\n"));
414  cout << std::endl;
415 
416  if ( saveGasCollisions ) {
417  ofstream of1("olperc.dat",ios::app);
418  std::copy( elosses.begin(), elosses.end(), std::ostream_iterator<float>(of1,"\n"));
419  }
420 
421  cout << "Total energy loss across gap = " << dedx << " eV = " <<
422  dedx/1000. << " keV" << std::endl;
423  int n_ic = count_if( elosses.begin(), elosses.end(),
424  bind2nd(greater<float>(), eion) );
425  cout << "No. of primary ionizing collisions across gap = " << n_ic << std::endl;
426  if ( n_steps > 0 ) cout << "Average energy loss/collision = " <<
427  dedx/float(n_steps) << " eV" << std::endl;
428  cout << std::endl;
429 
430  cout << "No. of ion clusters = " << ion_clusters.size() << std::endl;
431  cout << "Positions of clusters:" << std::endl;
432  std::copy( ion_clusters.begin(), ion_clusters.end(),
433  std::ostream_iterator<LocalPoint>(cout,"\n"));
434  cout << std::endl;
435 
436  if ( saveGasCollisions ) {
437  ofstream of2("oclpos.dat",ios::app);
438  std::copy( ion_clusters.begin(), ion_clusters.end(),
439  std::ostream_iterator<LocalPoint>(of2,"\n"));
440  }
441 
442  cout << "No. of electrons per cluster:" << std::endl;
443  std::copy( electrons.begin(), electrons.end(), std::ostream_iterator<int>(cout,"\n"));
444  cout << std::endl;
445 
446  if ( saveGasCollisions ) {
447  ofstream of3("oepercl.dat",ios::app);
448  std::copy( electrons.begin(), electrons.end(), std::ostream_iterator<int>(of3,"\n"));
449  }
450 
451  // Check for zero-e clusters
452  std::vector<int>::const_iterator bigger = find(electrons.begin(),
453  electrons.end(), 0 );
454  if ( bigger != electrons.end() ) {
455  cout << "Error! There is a cluster with 0 electrons." << std::endl;
456  }
457  int n_e = accumulate(electrons.begin(), electrons.end(), 0 );
458  if ( n_steps > 0 ) {
459  cout << "Total no. of electrons = " << n_e << ", energy loss/e = " <<
460  dedx/float(n_e) << " eV " << std::endl;
461  cout << "Average no. of electrons per cluster = " <<
462  float(n_e)/float(ion_clusters.size()) << std::endl;
463  cout << "------------------" << std::endl;
464 
465  cout << "#steps path av_step n_i_cl E/gap n_i_col E/step n_e E/e e/i_c" << std::endl;
466  cout << "# cm cm keV eV eV eV" << std::endl;
467  cout << " " << n_steps << " " << sum_steps << " " << sum_steps/float(n_steps) << " " <<
468  ion_clusters.size() << " " <<
469  dedx/1000. << " " << n_ic << " " << dedx/float(n_steps) << " " << n_e << " " <<
470  dedx/float(n_e) << " " << float(n_e)/float(ion_clusters.size()) << std::endl;
471  }
472 }
473 
474 float CSCGasCollisions::lnEnergyLoss( float lnCollisions,
475  const std::vector<float>& collisions ) const {
476 
477  float lnE = -1.;
478 
479  // Find collision[] bin in which lnCollisions falls
480  std::vector<float>::const_iterator it = find(collisions.begin(),
481  collisions.end(), lnCollisions );
482 
483  if ( it != collisions.end() ) {
484  // found the value
485  std::vector<float>::difference_type ihi = it - collisions.begin();
486  LogTrace(me) << ": using one energy bin " << ihi << " = "
487  << theEnergyBins[ihi]
488  << " for lnCollisions = " << lnCollisions;
489  lnE = theEnergyBins[ihi];
490  }
491  else {
492  // interpolate the value
493  std::vector<float>::const_iterator loside = find_if(collisions.begin(),
494  collisions.end(), bind2nd(less<float>(), lnCollisions));
495  std::vector<float>::difference_type ilo = loside - collisions.begin();
496  if ( ilo > 0 ) {
497  LogTrace(me) << ": using energy bin "
498  << ilo-1 << " and " << ilo;
499  lnE = theEnergyBins[ilo-1] + (lnCollisions-collisions[ilo-1])*
500  (theEnergyBins[ilo]-theEnergyBins[ilo-1]) /
501  (collisions[ilo]-collisions[ilo-1]);
502  }
503  else {
504  LogTrace(me) << ": using one energy bin 0 = "
505  << theEnergyBins[0]
506  << " for lnCollisions = " << lnCollisions;
507  lnE = theEnergyBins[0]; //@@ WHAT ELSE TO DO?
508  }
509  }
510 
511  return lnE;
512 }
513 
515  std::vector<float>& collisions ) const
516 {
517  std::vector<float>::const_iterator bigger = find_if(theGammaBins.begin(),
518  theGammaBins.end(), bind2nd(greater<float>(), logGamma));
519 
520  if ( bigger == theGammaBins.end() ) {
521  // use highest bin
522  LogTrace(me) << ": using highest gamma bin"
523  << " for logGamma = " << logGamma;
524  for (int i=0; i<N_ENERGY; ++i)
525  collisions[i] = theCollisionTable[i*N_GAMMA];
526  }
527  else {
528  // use bigger and its lower neighbour
529  std::vector<float>::difference_type ihi = bigger - theGammaBins.begin();
530  if ( ihi > 0 ) {
531  double dlg2 = *bigger--; // and decrement after deref
532  //LogTrace(me) << ": using gamma bins "
533  // << ihi-1 << " and " << ihi;
534  double dlg1 = *bigger; // now the preceding element
535  double dlg = (logGamma-dlg1)/(dlg2-dlg1);
536  double omdlg = 1. - dlg;
537  for (int i=0; i<N_ENERGY; ++i)
538  collisions[i] = theCollisionTable[i*N_GAMMA+ihi-1]*omdlg +
539  theCollisionTable[i*N_GAMMA+ihi]*dlg;
540  }
541  else {
542  // bigger has no lower neighbour
543  LogTrace(me) << ": using lowest gamma bin"
544  << " for logGamma = " << logGamma;
545 
546  for (int i=0; i<N_ENERGY; ++i)
547  collisions[i] = theCollisionTable[i*N_GAMMA];
548  }
549  }
550 }
int i
Definition: DBlmapReader.cc:9
list step
Definition: launcher.py:15
std::vector< int > electrons() const
Definition: CSCCrossGap.h:35
HepPDT::ParticleDataTable ParticleDataTable
int noOfClusters() const
Definition: CSCCrossGap.h:34
static const int N_ENERGY
Exp< T >::type exp(const T &t)
Definition: Exp.h:22
std::vector< LocalPoint > ionClusters() const
Definition: CSCCrossGap.h:33
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:7
void addElectronToBack()
Definition: CSCCrossGap.h:44
std::vector< float > eLossPerStep() const
Definition: CSCCrossGap.h:39
std::vector< double > stepLengths() const
Definition: CSCCrossGap.h:37
std::vector< float > theGammaBins
const std::string me
int path() const
Definition: HLTadd.h:3
float lnEnergyLoss(float, const std::vector< float > &) const
Local3DPoint exitPoint() const
Exit point in the local Det frame.
Definition: PSimHit.h:38
const ParticleDataTable * theParticleDataTable
double gamma() const
Definition: CSCCrossGap.h:52
LocalVector unitVector() const
Definition: CSCCrossGap.h:54
int noOfElectrons() const
Definition: CSCCrossGap.h:36
int j
Definition: DBlmapReader.cc:9
static const int N_GAMMA
static const int MAX_STEPS
float pabs() const
fast and more accurate access to momentumAtEntry().mag()
Definition: PSimHit.h:63
HepPDT::ParticleData ParticleData
void setParticleDataTable(const ParticleDataTable *pdt)
void ionize(double energyTransferred, LocalPoint startHere) const
#define LogTrace(id)
static const int N_ENTRIES
void simulate(const PSimHit &, const CSCLayer *layer, std::vector< LocalPoint > &clusters, std::vector< int > &electrons)
CLHEP::RandExponential * theRandExponential
double logGamma(double mass, float momentum)
Definition: CSCCrossGap.cc:23
std::vector< float > theCollisionTable
Log< T >::type log(const T &t)
Definition: Log.h:22
int noOfSteps() const
Definition: CSCCrossGap.h:38
double generateStep(double avCollisions) const
double beta2() const
Definition: CSCCrossGap.h:51
float generateEnergyLoss(double avCollisions, double anmin, double anmax, const std::vector< float > &collisions) const
std::vector< float > theEnergyBins
const String & name() const
return full name
Definition: FileInPath.h:34
int particleType() const
Definition: PSimHit.h:85
float length() const
Definition: CSCCrossGap.h:55
void fillCollisionsForThisGamma(float, std::vector< float > &) const
CSCCrossGap * theCrossGap
tuple cout
Definition: gather_cfg.py:41
void addCluster(LocalPoint here)
Definition: CSCCrossGap.h:42
virtual ~CSCGasCollisions()
void writeSummary(int n_steps, double sum_steps, float dedx) const
Local3DPoint entryPoint() const
Entry point in the local Det frame.
Definition: PSimHit.h:35
CLHEP::RandFlat * theRandFlat
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:40
void setRandomEngine(CLHEP::HepRandomEngine &engine)
void addElectrons(int nelec=1)
Definition: CSCCrossGap.h:43