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