26 #include "CLHEP/Random/RandExponential.h" 27 #include "CLHEP/Random/RandFlat.h" 59 : me(
"CSCGasCollisions"),
60 gasDensity(2.1416
e-03),
65 theGammaBins(N_GAMMA, 0.),
66 theEnergyBins(N_ENERGY, 0.),
67 theCollisionTable(N_ENTRIES, 0.),
70 saveGasCollisions_(
false),
71 dumpGasCollisions_(
false) {
77 <<
" keV (for higher elosses, hits should have been simulated.)";
107 string colliFile =
"SimMuon/CSCDigitizer/data/collisions.dat";
111 ifstream
fin{
f1.fullPath()};
114 string errorMessage =
"Cannot open input file " +
f1.fullPath();
120 fin.seekg(0, ios::beg);
139 LogTrace(
me) <<
"Reading collisions table \n";
143 LogTrace(
me) << ++j <<
" " << theCollisionTable[
i];
152 std::vector<LocalPoint> &positions,
154 CLHEP::HepRandomEngine *engine) {
155 const float epsilonL = 0.01;
163 double mom = simhit.
pabs();
168 double mass = 0.105658;
169 if (particle ==
nullptr) {
172 mass = particle->mass();
180 if (gapSize <= epsilonL) {
181 edm::LogVerbatim(
"CSCDigitizer") <<
"[CSCGasCollisions] WARNING! simhit entry and exit are too close - " 185 <<
" : momentum = " << simhit.
pabs()
186 <<
" GeV/c : energy loss = " << simhit.
energyLoss() * 1.E06 <<
" keV" 187 <<
", gapSize = " << gapSize <<
" cm (< epsilonL = " << epsilonL <<
" cm)";
193 std::vector<float> collisions(
N_ENERGY);
198 double anmax =
exp(collisions[0]);
199 double amu = anmax - anmin;
201 LogTrace(
me) <<
"collisions extremes = " << collisions[
N_ENERGY - 1] <<
", " << collisions[0] <<
"\n" 202 <<
"anmin = " << anmin <<
", anmax = " << anmax <<
"\n" 203 <<
"amu = " << amu <<
"\n";
206 double sum_steps = 0.;
214 while (sum_steps < gapSize) {
218 edm::LogVerbatim(
"CSCDigitizer") <<
"[CSCGasCollisions] WARNING! n_try = " << n_try
219 <<
" is > MAX_STEPS = " << maxst <<
" - skipping simhit:" 222 <<
" : momentum = " << simhit.
pabs()
223 <<
" GeV/c : energy loss = " << simhit.
energyLoss() * 1.E06 <<
" keV" 224 <<
"\n gapSize = " << gapSize <<
" cm, last step = " << step
225 <<
" cm, sum_steps = " << sum_steps <<
" cm, n_steps = " << n_steps;
229 if (sum_steps + step > gapSize)
236 edm::LogVerbatim(
"CSCDigitizer") <<
"[CSCGasCollisions] WARNING! eloss = " << eloss <<
" eV is too large (> " 237 <<
deCut <<
" eV) - trying another collision";
246 edm::LogVerbatim(
"CSCDigitizer") <<
"[CSCGasCollisions] WARNING! " << n_steps
247 <<
" is too many steps - skipping simhit:" 250 <<
" : momentum = " << simhit.
pabs()
251 <<
" GeV/c : energy loss = " << simhit.
energyLoss() * 1.E06 <<
" keV" 252 <<
"\ngapSize=" << gapSize <<
" cm, last step=" << step
253 <<
" cm, sum_steps=" << sum_steps <<
" cm";
256 LogTrace(
me) <<
"sum_steps = " << sum_steps <<
" cm , dedx = " << dedx <<
" eV";
262 ionize(eloss, layerLocalPoint);
264 LogTrace(
me) <<
"Energy available = " << eloss <<
" eV is too low for ionization (< eion = " <<
eion <<
" eV)";
280 double step = (CLHEP::RandExponential::shoot(engine)) / avCollisions;
297 const std::vector<float> &collisions,
298 CLHEP::HepRandomEngine *engine)
const {
300 float lnColl =
log(CLHEP::RandFlat::shoot(engine, anmin, anmax));
309 float eloss =
exp(lnE);
321 while (energyAvailable >
eion) {
339 double range = 0.5 * (0.71 /
gasDensity) *
pow(energyAvailable * 1.E-6, 1.72);
340 LogTrace(
me) <<
" range = " << range <<
" cm";
345 int nelec =
static_cast<int>(energyAvailable /
ework);
346 LogTrace(
me) <<
"short-range delta energy in = " << energyAvailable <<
" eV";
348 energyAvailable -= nelec *
ework;
350 if (energyAvailable >
eion) {
352 energyAvailable -=
eion;
354 LogTrace(
me) <<
"short-range delta energy out = " << energyAvailable <<
" eV, nelec = " << nelec;
364 bool new_range =
false;
365 while (!new_range && (energyAvailable >
ework)) {
366 energyAvailable -=
ework;
367 while (energyAvailable >
eion) {
368 double range2 = 0.5 * 0.71 /
gasDensity *
pow(1.E-6 * energyAvailable, 1.72);
369 double drange = range - range2;
370 LogTrace(
me) <<
" energy left = " << energyAvailable <<
" eV, range2 = " << range2
371 <<
" cm, drange = " << drange <<
" cm";
378 LogTrace(
me) <<
"reset range to range2 = " << range <<
" from startHere = " << startHere <<
" and iterate";
388 if (energyAvailable >
eion) {
389 energyAvailable -=
ework;
407 <<
"\nAFTER CROSSING GAP";
426 size_t nsteps = n_steps;
427 size_t mstep = steps.size() - 1;
429 if ((nsteps !=
MAX_STEPS) && (nsteps != mstep)) {
430 edm::LogVerbatim(
"CSCDigitizer") <<
"[CSCGasCollisions] WARNING! no. of steps = " << nsteps
431 <<
" .ne. steps.size()-1 = " << mstep;
433 size_t meloss = elosses.size();
435 if (nsteps != meloss) {
436 edm::LogVerbatim(
"CSCDigitizer") <<
"[CSCGasCollisions] WARNING! no. of steps = " << nsteps
437 <<
" .ne. no. of elosses = " << meloss;
439 edm::LogVerbatim(
"CSCDigitizer") <<
"[CSCGasCollisions] # / length of step / energy loss per collision:";
440 for (
size_t i = 0;
i != nsteps; ++
i) {
441 edm::LogVerbatim(
"CSCDigitizer") <<
i + 1 <<
" / S: " << steps[
i] <<
" / E: " << elosses[
i];
445 size_t mclus = ion_clusters.size();
446 size_t melec = electrons.size();
448 if (mclus != melec) {
449 edm::LogVerbatim(
"CSCDigitizer") <<
"[CSCGasCollisions] WARNING! size of cluster vector = " << mclus
450 <<
" .ne. size of electrons vector = " << melec;
453 "cluster / electrons per cluster: ";
454 for (
size_t i = 0;
i != mclus; ++
i) {
455 edm::LogVerbatim(
"CSCDigitizer") <<
i + 1 <<
" / I: " << ion_clusters[
i] <<
" / E: " << electrons[
i];
459 int n_ic = count_if(elosses.begin(), elosses.end(), [&](
auto c) {
return c > this->
eion; });
461 edm::LogVerbatim(
"CSCDigitizer") <<
"[CSCGasCollisions] total no. of collision steps = " << n_steps;
462 edm::LogVerbatim(
"CSCDigitizer") <<
"[CSCGasCollisions] total sum of steps = " << sum_steps <<
" cm";
464 edm::LogVerbatim(
"CSCDigitizer") <<
"[CSCGasCollisions] average step length = " << sum_steps /
float(nsteps)
466 edm::LogVerbatim(
"CSCDigitizer") <<
"[CSCGasCollisions] total energy loss across gap = " << dedx
467 <<
" eV = " << dedx / 1000. <<
" keV";
468 edm::LogVerbatim(
"CSCDigitizer") <<
"[CSCGasCollisions] no. of primary ionizing collisions across gap = " 469 "no. with eloss > eion = " 470 <<
eion <<
" eV = " << n_ic;
472 edm::LogVerbatim(
"CSCDigitizer") <<
"[CSCGasCollisions] average energy loss/collision = " << dedx /
float(nsteps)
475 std::vector<int>::const_iterator bigger =
find(electrons.begin(), electrons.end(), 0);
476 if (bigger != electrons.end()) {
477 edm::LogVerbatim(
"CSCDigitizer") <<
"[CSCGasCollisions] TROUBLE! There is a cluster with 0 electrons.";
480 int n_e = accumulate(electrons.begin(), electrons.end(), 0);
485 <<
" : momentum = " << simhit.
pabs()
486 <<
" GeV/c : energy loss = " << simhit.
energyLoss() * 1.E06 <<
" keV";
489 edm::LogVerbatim(
"CSCDigitizer") <<
"[CSCGasCollisions] SUMMARY: ionization" 490 <<
" : steps= " << nsteps <<
" : sum(steps)= " << sum_steps
491 <<
" cm : <step>= " << sum_steps /
float(nsteps) <<
" cm" 492 <<
" : ionizing= " << n_ic <<
" : ionclus= " << mclus <<
" : total e= " << n_e
493 <<
" : <dedx/step>= " << dedx /
float(nsteps)
494 <<
" eV : <e/ionclus>= " <<
float(n_e) /
float(mclus)
495 <<
" : dedx= " << dedx / 1000. <<
" keV";
497 edm::LogVerbatim(
"CSCDigitizer") <<
"[CSCGasCollisons] ERROR? no collision steps!";
524 std::vector<float>::const_iterator it =
find(collisions.begin(), collisions.end(), lnCollisions);
526 if (it != collisions.end()) {
528 std::vector<float>::difference_type ihi = it - collisions.begin();
530 <<
" for lnCollisions = " << lnCollisions;
534 std::vector<float>::const_iterator loside =
535 find_if(collisions.begin(), collisions.end(), [&lnCollisions](
auto c) {
return c < lnCollisions; });
536 std::vector<float>::difference_type ilo = loside - collisions.begin();
538 LogTrace(
me) <<
": using energy bin " << ilo - 1 <<
" and " << ilo;
539 lnE =
theEnergyBins[ilo - 1] + (lnCollisions - collisions[ilo - 1]) *
541 (collisions[ilo] - collisions[ilo - 1]);
552 std::vector<float>::const_iterator bigger =
558 <<
" for logGamma = " << logGamma;
563 std::vector<float>::difference_type ihi = bigger -
theGammaBins.begin();
565 double dlg2 = *bigger--;
568 double dlg1 = *bigger;
569 double dlg = (logGamma - dlg1) / (dlg2 - dlg1);
570 double omdlg = 1. - dlg;
576 <<
" for logGamma = " << logGamma;
T getUntrackedParameter(std::string const &, T const &) const
std::vector< int > electrons() const
HepPDT::ParticleDataTable ParticleDataTable
bool saveGasCollisions(void) const
void addEloss(float eloss)
static const int N_ENERGY
std::vector< LocalPoint > ionClusters() const
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
CSCGasCollisions(const edm::ParameterSet &pset)
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.
bool dumpGasCollisions(void) const
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 writeSummary(int n_try, int n_steps, double sum_steps, float dedx, const PSimHit &simhit) const
double logGamma(double mass, float momentum)
void readCollisionTable()
std::vector< float > theCollisionTable
double generateStep(double avCollisions, CLHEP::HepRandomEngine *) const
std::vector< float > theEnergyBins
float energyLoss() const
The energy deposit in the PSimHit, in ???.
float generateEnergyLoss(double avCollisions, double anmin, double anmax, const std::vector< float > &collisions, CLHEP::HepRandomEngine *) const
void addStep(double step)
void fillCollisionsForThisGamma(float, std::vector< float > &) const
CSCCrossGap * theCrossGap
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)