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),
47 theRandExponential(0),
48 saveGasCollisions (
false )
54 <<
" keV (for higher elosses, hits should have been simulated.)";
85 string path( getenv(
"CMSSW_SEARCH_PATH" ) );
87 string colliFile =
"SimMuon/CSCDigitizer/data/collisions.dat";
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.");
100 ifstream & fin = *
f1();
103 string errorMessage =
"Cannot open input file " + path + colliFile;
109 fin.seekg( 0, ios::beg );
128 LogTrace(
me) <<
"Reading collisions table \n";
132 LogTrace(
me) << ++j <<
" " << theCollisionTable[
i];
153 std::vector<LocalPoint>& positions, std::vector<int>& electrons ) {
155 const float epsilonL = 0.01;
161 double mom = simHit.
pabs();
166 double mass = 0.105658;
174 mass = particle->mass();
182 if ( gapSize <= epsilonL ) {
183 LogTrace(
me) <<
": WARNING! simhit entry and exit are very close: \n"
186 <<
"\n particle type = " << iam <<
", momentum = " << mom
187 <<
", gap length = " << gapSize;
193 std::vector<float> collisions(
N_ENERGY);
198 double anmax =
exp(collisions[0]);
199 double amu = anmax - anmin;
202 <<
", " << collisions[0] <<
"\n"
203 <<
"anmin = " << anmin <<
", anmax = " << anmax <<
"\n"
204 <<
"amu = " << amu <<
"\n";
207 double sum_steps = 0.;
220 while ( sum_steps < gapSize) {
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;
230 if ( sum_steps + step > gapSize )
break;
235 if ( eloss >
deCut ) {
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;
251 LogTrace(
me) <<
"sum_steps = " << sum_steps <<
", dedx = " << dedx;
255 if ( eloss >
eion ) {
257 ionize( eloss, layerLocalPoint );
260 LogTrace(
me) <<
"Energy available = " << eloss <<
261 ", too low for ionization.";
291 double anmin,
double anmax,
const std::vector<float>& collisions )
const
303 float eloss =
exp(lnE);
314 while ( energyAvailable >
eion ) {
327 double range = 0.5 * (0.71/
gasDensity)*
pow( energyAvailable*1.E-6, 1.72);
333 int nelec =
static_cast<int>(energyAvailable/
ework);
334 LogTrace(
me) <<
"s-r delta energy in = " << energyAvailable;
335 energyAvailable -= nelec*(energyAvailable/
ework);
337 if ( energyAvailable >
eion ) {
339 energyAvailable -=
eion;
341 LogTrace(
me) <<
"s-r delta energy out = " << energyAvailable <<
", nelec = " << nelec;
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;
367 LogTrace(
me) <<
"reset range to range2 and iterate";
376 if ( energyAvailable >
eion ) {
377 energyAvailable -=
ework;
393 cout <<
"------------------" << std::endl;
394 cout <<
"AFTER CROSSING GAP" << std::endl;
395 cout <<
"No. of steps = " << n_steps << std::endl;
398 cout <<
"Lengths of steps: " << std::endl;
399 std::copy( steps.begin(), steps.end(), std::ostream_iterator<float>(
cout,
"\n"));
403 ofstream of0(
"osteplen.dat",ios::app);
404 std::copy( steps.begin(), steps.end(), std::ostream_iterator<float>(of0,
"\n"));
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;
412 cout <<
"Energy loss per collision:" << std::endl;
413 std::copy( elosses.begin(), elosses.end(), std::ostream_iterator<float>(
cout,
"\n"));
417 ofstream of1(
"olperc.dat",ios::app);
418 std::copy( elosses.begin(), elosses.end(), std::ostream_iterator<float>(of1,
"\n"));
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;
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"));
437 ofstream of2(
"oclpos.dat",ios::app);
438 std::copy( ion_clusters.begin(), ion_clusters.end(),
439 std::ostream_iterator<LocalPoint>(of2,
"\n"));
442 cout <<
"No. of electrons per cluster:" << std::endl;
443 std::copy( electrons.begin(), electrons.end(), std::ostream_iterator<int>(
cout,
"\n"));
447 ofstream of3(
"oepercl.dat",ios::app);
448 std::copy( electrons.begin(), electrons.end(), std::ostream_iterator<int>(of3,
"\n"));
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;
457 int n_e = accumulate(electrons.begin(), electrons.end(), 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;
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;
475 const std::vector<float>& collisions )
const {
480 std::vector<float>::const_iterator it =
find(collisions.begin(),
481 collisions.end(), lnCollisions );
483 if ( it != collisions.end() ) {
485 std::vector<float>::difference_type ihi = it - collisions.begin();
486 LogTrace(
me) <<
": using one energy bin " << ihi <<
" = "
488 <<
" for lnCollisions = " << lnCollisions;
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();
498 << ilo-1 <<
" and " << ilo;
499 lnE =
theEnergyBins[ilo-1] + (lnCollisions-collisions[ilo-1])*
501 (collisions[ilo]-collisions[ilo-1]);
506 <<
" for lnCollisions = " << lnCollisions;
515 std::vector<float>& collisions )
const
517 std::vector<float>::const_iterator bigger = find_if(
theGammaBins.begin(),
518 theGammaBins.end(), bind2nd(greater<float>(), logGamma));
523 <<
" for logGamma = " << logGamma;
529 std::vector<float>::difference_type ihi = bigger -
theGammaBins.begin();
531 double dlg2 = *bigger--;
534 double dlg1 = *bigger;
535 double dlg = (logGamma-dlg1)/(dlg2-dlg1);
536 double omdlg = 1. - dlg;
544 <<
" for logGamma = " << logGamma;
std::vector< int > electrons() const
HepPDT::ParticleDataTable ParticleDataTable
static const int N_ENERGY
Exp< T >::type exp(const T &t)
std::vector< LocalPoint > ionClusters() const
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
std::vector< float > eLossPerStep() const
std::vector< double > stepLengths() const
std::vector< float > theGammaBins
float lnEnergyLoss(float, const std::vector< float > &) const
Local3DPoint exitPoint() const
Exit point in the local Det frame.
const ParticleDataTable * theParticleDataTable
LocalVector unitVector() const
int noOfElectrons() const
static const int MAX_STEPS
float pabs() const
fast and more accurate access to momentumAtEntry().mag()
HepPDT::ParticleData ParticleData
void setParticleDataTable(const ParticleDataTable *pdt)
void ionize(double energyTransferred, LocalPoint startHere) const
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)
void readCollisionTable()
std::vector< float > theCollisionTable
Log< T >::type log(const T &t)
double generateStep(double avCollisions) const
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
void fillCollisionsForThisGamma(float, std::vector< float > &) const
CSCCrossGap * theCrossGap
void addCluster(LocalPoint here)
virtual ~CSCGasCollisions()
void writeSummary(int n_steps, double sum_steps, float dedx) const
Local3DPoint entryPoint() const
Entry point in the local Det frame.
CLHEP::RandFlat * theRandFlat
Power< A, B >::type pow(const A &a, const B &b)
void setRandomEngine(CLHEP::HepRandomEngine &engine)
void addElectrons(int nelec=1)