48 gasDensity( 2.1416
e-03 ),
49 deCut( 1.e05 ), eion( 14.95 ), ework( 34.0 ), clusterExtent( 0.001 ),
50 theGammaBins(N_GAMMA, 0.), theEnergyBins(N_ENERGY, 0.),
51 theCollisionTable(N_ENTRIES, 0.), theCrossGap( 0 ),
52 theParticleDataTable(0),
54 theRandExponential(0),
55 saveGasCollisions (
false )
61 <<
" keV (for higher elosses, hits should have been simulated.)";
92 string path( getenv(
"CMSSW_SEARCH_PATH" ) );
94 string colliFile =
"SimMuon/CSCDigitizer/data/collisions.dat";
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.");
107 ifstream &
fin = *
f1();
110 string errorMessage =
"Cannot open input file " + path + colliFile;
116 fin.seekg( 0, ios::beg );
135 LogTrace(
me) <<
"Reading collisions table \n";
139 LogTrace(
me) << ++j <<
" " << theCollisionTable[
i];
160 std::vector<LocalPoint>& positions, std::vector<int>&
electrons ) {
162 const float epsilonL = 0.01;
168 double mom = simHit.
pabs();
173 double mass = 0.105658;
181 mass = particle->mass();
189 if ( gapSize <= epsilonL ) {
190 LogTrace(
me) <<
": WARNING! simhit entry and exit are very close: \n"
193 <<
"\n particle type = " << iam <<
", momentum = " << mom
194 <<
", gap length = " << gapSize;
200 std::vector<float> collisions(
N_ENERGY);
205 double anmax =
exp(collisions[0]);
206 double amu = anmax - anmin;
209 <<
", " << collisions[0] <<
"\n"
210 <<
"anmin = " << anmin <<
", anmax = " << anmax <<
"\n"
211 <<
"amu = " << amu <<
"\n";
214 double sum_steps = 0.;
222 while ( sum_steps < gapSize) {
225 LogTrace(
me) <<
": n_try=" << n_try <<
" is too large. Skip simhit."
226 <<
"\n particle type=" << iam <<
", momentum= " << mom
227 <<
"\n gapSize=" << gapSize <<
", last step=" << step
228 <<
", sum_steps=" << sum_steps <<
", n_steps=" << n_steps;
232 if ( sum_steps + step > gapSize )
break;
237 if ( eloss >
deCut ) {
247 edm::LogInfo(
me) <<
": n_steps=" << n_steps <<
" is too large. Skip simhit.";
248 edm::LogInfo(
me) <<
"particle type=" << iam <<
", momentum= " << mom;
249 edm::LogInfo(
me) <<
"gapSize=" << gapSize <<
", last step=" << step
250 <<
", sum_steps=" << sum_steps;
253 LogTrace(
me) <<
"sum_steps = " << sum_steps <<
", dedx = " << dedx;
257 if ( eloss >
eion ) {
259 ionize( eloss, layerLocalPoint );
262 LogTrace(
me) <<
"Energy available = " << eloss <<
263 ", too low for ionization.";
293 double anmin,
double anmax,
const std::vector<float>& collisions )
const
305 float eloss =
exp(lnE);
316 while ( energyAvailable >
eion ) {
329 double range = 0.5 * (0.71/
gasDensity)*
pow( energyAvailable*1.E-6, 1.72);
335 int nelec =
static_cast<int>(energyAvailable/
ework);
336 LogTrace(
me) <<
"s-r delta energy in = " << energyAvailable;
338 energyAvailable -= nelec*
ework;
340 if ( energyAvailable >
eion ) {
342 energyAvailable -=
eion;
344 LogTrace(
me) <<
"s-r delta energy out = " << energyAvailable <<
", nelec = " << nelec;
355 bool new_range =
false;
356 while ( !new_range && (energyAvailable>
ework) ) {
357 energyAvailable -=
ework;
358 while ( energyAvailable >
eion ) {
359 double range2 = 0.5 * 0.71/
gasDensity*
pow( 1.E-6*energyAvailable, 1.72);
360 double drange = range - range2;
361 LogTrace(
me) <<
" energy left = " << energyAvailable <<
362 ", range2 = " << range2 <<
", drange = " << drange;
370 LogTrace(
me) <<
"reset range to range2 and iterate";
379 if ( energyAvailable >
eion ) {
380 energyAvailable -=
ework;
396 cout <<
"------------------" << std::endl;
397 cout <<
"AFTER CROSSING GAP" << std::endl;
398 cout <<
"No. of steps = " << n_steps << std::endl;
401 cout <<
"Lengths of steps: " << std::endl;
402 std::copy( steps.begin(), steps.end(), std::ostream_iterator<float>(
cout,
"\n"));
406 ofstream of0(
"osteplen.dat",ios::app);
407 std::copy( steps.begin(), steps.end(), std::ostream_iterator<float>(of0,
"\n"));
410 cout <<
"Total sum of steps = " << sum_steps << std::endl;
411 if ( n_steps > 0 ) cout <<
"Average step length = " <<
412 sum_steps/float(n_steps) << std::endl;
415 cout <<
"Energy loss per collision:" << std::endl;
416 std::copy( elosses.begin(), elosses.end(), std::ostream_iterator<float>(
cout,
"\n"));
420 ofstream of1(
"olperc.dat",ios::app);
421 std::copy( elosses.begin(), elosses.end(), std::ostream_iterator<float>(of1,
"\n"));
424 cout <<
"Total energy loss across gap = " << dedx <<
" eV = " <<
425 dedx/1000. <<
" keV" << std::endl;
426 int n_ic = count_if( elosses.begin(), elosses.end(),
427 bind2nd(greater<float>(),
eion) );
428 cout <<
"No. of primary ionizing collisions across gap = " << n_ic << std::endl;
429 if ( n_steps > 0 ) cout <<
"Average energy loss/collision = " <<
430 dedx/float(n_steps) <<
" eV" << std::endl;
433 cout <<
"No. of ion clusters = " << ion_clusters.size() << std::endl;
434 cout <<
"Positions of clusters:" << std::endl;
435 std::copy( ion_clusters.begin(), ion_clusters.end(),
436 std::ostream_iterator<LocalPoint>(
cout,
"\n"));
440 ofstream of2(
"oclpos.dat",ios::app);
441 std::copy( ion_clusters.begin(), ion_clusters.end(),
442 std::ostream_iterator<LocalPoint>(of2,
"\n"));
445 cout <<
"No. of electrons per cluster:" << std::endl;
446 std::copy( electrons.begin(), electrons.end(), std::ostream_iterator<int>(
cout,
"\n"));
450 ofstream of3(
"oepercl.dat",ios::app);
451 std::copy( electrons.begin(), electrons.end(), std::ostream_iterator<int>(of3,
"\n"));
455 std::vector<int>::const_iterator bigger =
find(electrons.begin(),
456 electrons.end(), 0 );
457 if ( bigger != electrons.end() ) {
458 cout <<
"Error! There is a cluster with 0 electrons." << std::endl;
460 int n_e = accumulate(electrons.begin(), electrons.end(), 0 );
462 cout <<
"# cm cm keV eV eV eV keV" << std::endl;
463 cout <<
" " << n_steps <<
" " << sum_steps <<
" " << sum_steps/float(n_steps) <<
" " <<
464 ion_clusters.size() <<
" " <<
465 dedx/1000. <<
" " << n_ic <<
" " << dedx/float(n_steps) <<
" " << n_e <<
" " <<
466 dedx/float(n_e) <<
" " << float(n_e)/float(ion_clusters.size()) <<
" " << simHiteloss*1.E6 << std::endl;
471 const std::vector<float>& collisions )
const {
476 std::vector<float>::const_iterator it =
find(collisions.begin(),
477 collisions.end(), lnCollisions );
479 if ( it != collisions.end() ) {
481 std::vector<float>::difference_type ihi = it - collisions.begin();
482 LogTrace(
me) <<
": using one energy bin " << ihi <<
" = "
484 <<
" for lnCollisions = " << lnCollisions;
489 std::vector<float>::const_iterator loside = find_if(collisions.begin(),
490 collisions.end(), bind2nd(less<float>(), lnCollisions));
491 std::vector<float>::difference_type ilo = loside - collisions.begin();
494 << ilo-1 <<
" and " << ilo;
495 lnE =
theEnergyBins[ilo-1] + (lnCollisions-collisions[ilo-1])*
497 (collisions[ilo]-collisions[ilo-1]);
502 <<
" for lnCollisions = " << lnCollisions;
511 std::vector<float>& collisions )
const
513 std::vector<float>::const_iterator bigger = find_if(
theGammaBins.begin(),
514 theGammaBins.end(), bind2nd(greater<float>(), logGamma));
519 <<
" for logGamma = " << logGamma;
525 std::vector<float>::difference_type ihi = bigger -
theGammaBins.begin();
527 double dlg2 = *bigger--;
530 double dlg1 = *bigger;
531 double dlg = (logGamma-dlg1)/(dlg2-dlg1);
532 double omdlg = 1. - dlg;
540 <<
" for logGamma = " << logGamma;
void simulate(const PSimHit &, std::vector< LocalPoint > &clusters, std::vector< int > &electrons)
std::vector< int > electrons() const
HepPDT::ParticleDataTable ParticleDataTable
static const int N_ENERGY
void writeSummary(int n_steps, double sum_steps, float dedx, float simHiteloss) const
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
CLHEP::RandExponential * theRandExponential
double logGamma(double mass, float momentum)
void readCollisionTable()
std::vector< float > theCollisionTable
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()
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)