21 #include "CLHEP/Random/RandExponential.h"
22 #include "CLHEP/Random/RandFlat.h"
52 gasDensity( 2.1416
e-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 )
63 <<
" 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];
153 std::vector<LocalPoint>& positions, std::vector<int>&
electrons,
154 CLHEP::HepRandomEngine* engine ) {
156 const float epsilonL = 0.01;
162 double mom = simHit.
pabs();
167 double mass = 0.105658;
175 mass = particle->mass();
183 if ( gapSize <= epsilonL ) {
184 LogTrace(
me) <<
": WARNING! simhit entry and exit are very close: \n"
187 <<
"\n particle type = " << iam <<
", momentum = " << mom
188 <<
", gap length = " << gapSize;
194 std::vector<float> collisions(
N_ENERGY);
199 double anmax =
exp(collisions[0]);
200 double amu = anmax - anmin;
203 <<
", " << collisions[0] <<
"\n"
204 <<
"anmin = " << anmin <<
", anmax = " << anmax <<
"\n"
205 <<
"amu = " << amu <<
"\n";
208 double sum_steps = 0.;
216 while ( sum_steps < gapSize) {
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;
226 if ( sum_steps + step > gapSize )
break;
231 if ( eloss >
deCut ) {
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;
247 LogTrace(
me) <<
"sum_steps = " << sum_steps <<
", dedx = " << dedx;
251 if ( eloss >
eion ) {
253 ionize( eloss, layerLocalPoint );
256 LogTrace(
me) <<
"Energy available = " << eloss <<
257 ", too low for ionization.";
274 double step = (CLHEP::RandExponential::shoot(engine))/avCollisions;
287 double anmin,
double anmax,
const std::vector<float>& collisions,
288 CLHEP::HepRandomEngine* engine )
const
291 float lnColl =
log(CLHEP::RandFlat::shoot(engine, anmin, anmax));
300 float eloss =
exp(lnE);
311 while ( energyAvailable >
eion ) {
324 double range = 0.5 * (0.71/
gasDensity)*
pow( energyAvailable*1.E-6, 1.72);
330 int nelec =
static_cast<int>(energyAvailable/
ework);
331 LogTrace(
me) <<
"s-r delta energy in = " << energyAvailable;
333 energyAvailable -= nelec*
ework;
335 if ( energyAvailable >
eion ) {
337 energyAvailable -=
eion;
339 LogTrace(
me) <<
"s-r delta energy out = " << energyAvailable <<
", nelec = " << nelec;
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;
365 LogTrace(
me) <<
"reset range to range2 and iterate";
374 if ( energyAvailable >
eion ) {
375 energyAvailable -=
ework;
391 cout <<
"------------------" << std::endl;
392 cout <<
"AFTER CROSSING GAP" << std::endl;
393 cout <<
"No. of steps = " << n_steps << std::endl;
396 cout <<
"Lengths of steps: " << std::endl;
397 std::copy( steps.begin(), steps.end(), std::ostream_iterator<float>(
cout,
"\n"));
401 ofstream of0(
"osteplen.dat",ios::app);
402 std::copy( steps.begin(), steps.end(), std::ostream_iterator<float>(of0,
"\n"));
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;
410 cout <<
"Energy loss per collision:" << std::endl;
411 std::copy( elosses.begin(), elosses.end(), std::ostream_iterator<float>(
cout,
"\n"));
415 ofstream of1(
"olperc.dat",ios::app);
416 std::copy( elosses.begin(), elosses.end(), std::ostream_iterator<float>(of1,
"\n"));
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;
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"));
435 ofstream of2(
"oclpos.dat",ios::app);
436 std::copy( ion_clusters.begin(), ion_clusters.end(),
437 std::ostream_iterator<LocalPoint>(of2,
"\n"));
440 cout <<
"No. of electrons per cluster:" << std::endl;
441 std::copy( electrons.begin(), electrons.end(), std::ostream_iterator<int>(
cout,
"\n"));
445 ofstream of3(
"oepercl.dat",ios::app);
446 std::copy( electrons.begin(), electrons.end(), std::ostream_iterator<int>(of3,
"\n"));
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;
455 int n_e = accumulate(electrons.begin(), electrons.end(), 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;
466 const std::vector<float>& collisions )
const {
471 std::vector<float>::const_iterator it =
find(collisions.begin(),
472 collisions.end(), lnCollisions );
474 if ( it != collisions.end() ) {
476 std::vector<float>::difference_type ihi = it - collisions.begin();
477 LogTrace(
me) <<
": using one energy bin " << ihi <<
" = "
479 <<
" for lnCollisions = " << lnCollisions;
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();
489 << ilo-1 <<
" and " << ilo;
490 lnE =
theEnergyBins[ilo-1] + (lnCollisions-collisions[ilo-1])*
492 (collisions[ilo]-collisions[ilo-1]);
497 <<
" for lnCollisions = " << lnCollisions;
506 std::vector<float>& collisions )
const
508 std::vector<float>::const_iterator bigger = find_if(
theGammaBins.begin(),
509 theGammaBins.end(), bind2nd(greater<float>(), logGamma));
514 <<
" for logGamma = " << logGamma;
520 std::vector<float>::difference_type ihi = bigger -
theGammaBins.begin();
522 double dlg2 = *bigger--;
525 double dlg1 = *bigger;
526 double dlg = (logGamma-dlg1)/(dlg2-dlg1);
527 double omdlg = 1. - dlg;
535 <<
" for logGamma = " << logGamma;
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
tuple path
else: Piece not in the list, fine.
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
double logGamma(double mass, float momentum)
void readCollisionTable()
std::vector< float > theCollisionTable
double generateStep(double avCollisions, CLHEP::HepRandomEngine *) const
std::vector< float > theEnergyBins
const String & name() const
return full name
float generateEnergyLoss(double avCollisions, double anmin, double anmax, const std::vector< float > &collisions, CLHEP::HepRandomEngine *) const
void fillCollisionsForThisGamma(float, std::vector< float > &) const
CSCCrossGap * theCrossGap
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)
virtual ~CSCGasCollisions()
Local3DPoint entryPoint() const
Entry point in the local Det frame.
Power< A, B >::type pow(const A &a, const B &b)
void addElectrons(int nelec=1)