CMS 3D CMS Logo

CSCGasCollisions Class Reference

Class to handle CSC gas ionization simulation during digitization. More...

#include <SimMuon/CSCDigitizer/src/CSCGasCollisions.h>

List of all members.

Public Member Functions

 CSCGasCollisions ()
void setParticleDataTable (const ParticleDataTable *pdt)
void setRandomEngine (CLHEP::HepRandomEngine &engine)
void simulate (const PSimHit &, const CSCLayer *layer, std::vector< LocalPoint > &clusters, std::vector< int > &electrons)
virtual ~CSCGasCollisions ()

Static Public Attributes

static const int MAX_STEPS = 400
static const int N_ENERGY = 63
static const int N_ENTRIES = N_GAMMA*N_ENERGY
static const int N_GAMMA = 21

Private Member Functions

void fillCollisionsForThisGamma (float, std::vector< float > &) const
float generateEnergyLoss (double avCollisions, double anmin, double anmax, const std::vector< float > &collisions) const
double generateStep (double avCollisions) const
void ionize (double energyTransferred, LocalPoint startHere) const
float lnEnergyLoss (float, const std::vector< float > &) const
void readCollisionTable ()
void writeSummary (int n_steps, double sum_steps, float dedx) const

Private Attributes

double clusterExtent
double deCut
double eion
double ework
double gasDensity
const std::string me
bool saveGasCollisions
std::vector< float > theCollisionTable
CSCCrossGaptheCrossGap
std::vector< float > theEnergyBins
std::vector< float > theGammaBins
const ParticleDataTabletheParticleDataTable
CLHEP::RandExponential * theRandExponential
CLHEP::RandFlat * theRandFlat


Detailed Description

Class to handle CSC gas ionization simulation during digitization.

Author:
Tim Cox
This class contains the port of the old CMSIM/ORCA Fortran routine mc_clus.F, and the GEANT3 code it relied on. Of course the version here is much improved :)

Definition at line 25 of file CSCGasCollisions.h.


Constructor & Destructor Documentation

CSCGasCollisions::CSCGasCollisions (  ) 

Definition at line 39 of file CSCGasCollisions.cc.

References clusterExtent, deCut, eion, ework, gasDensity, me, readCollisionTable(), and saveGasCollisions.

00039                                    : me("CSCGasCollisions"),
00040   gasDensity( 2.1416e-03 ), 
00041   deCut( 1.e05 ), eion( 10.4 ), ework( 70.0 ), clusterExtent( 0.001 ),
00042   theGammaBins(N_GAMMA, 0.), theEnergyBins(N_ENERGY, 0.), 
00043   theCollisionTable(N_ENTRIES, 0.), theCrossGap( 0 ),
00044   theParticleDataTable(0),
00045   theRandFlat(0),
00046   theRandExponential(0),
00047   saveGasCollisions ( false )
00048 {
00049 
00050   edm::LogInfo(me) << "Constructing a " << me << ":"; 
00051   edm::LogInfo(me) << "gas density = " << gasDensity << " g/cm3";
00052   edm::LogInfo(me) << "max eloss per collision allowed = " << deCut/1000. 
00053        << " keV (for higher elosses, hits should have been simulated.)";
00054   edm::LogInfo(me) << "ionization threshold = " << eion << " eV";
00055   edm::LogInfo(me) << "effective work function = " << ework << " eV";
00056   edm::LogInfo(me) << "cluster extent = " << clusterExtent*1.e04 << " micrometres";
00057   edm::LogInfo(me) << "Save gas collision info to files when using debugV? " << saveGasCollisions;
00058 
00059   readCollisionTable();
00060 }

CSCGasCollisions::~CSCGasCollisions (  )  [virtual]

Definition at line 62 of file CSCGasCollisions.cc.

References me, theCrossGap, theRandExponential, and theRandFlat.

00062                                     {
00063   edm::LogInfo(me) << "Destructing a " << me;
00064   delete theCrossGap;
00065   delete theRandFlat;
00066   delete theRandExponential;
00067 }


Member Function Documentation

void CSCGasCollisions::fillCollisionsForThisGamma ( float  logGamma,
std::vector< float > &  collisions 
) const [private]

Definition at line 513 of file CSCGasCollisions.cc.

References i, LogTrace, me, N_ENERGY, N_GAMMA, theCollisionTable, and theGammaBins.

Referenced by simulate().

00515 {
00516   std::vector<float>::const_iterator bigger = find_if(theGammaBins.begin(),
00517     theGammaBins.end(), bind2nd(greater<float>(), logGamma));
00518 
00519   if ( bigger == theGammaBins.end() ) {
00520     // use highest bin
00521     LogTrace(me) << ": using highest gamma bin" 
00522                       << " for logGamma = " << logGamma;
00523     for (int i=0; i<N_ENERGY; ++i)
00524       collisions[i] = theCollisionTable[i*N_GAMMA];
00525   }
00526   else {
00527     // use bigger and its lower neighbour
00528     std::vector<float>::difference_type ihi = bigger - theGammaBins.begin();
00529     if ( ihi > 0 ) {
00530       double dlg2 = *bigger--; // and decrement after deref
00531       //LogTrace(me) << ": using gamma bins " 
00532       //                   << ihi-1 << " and " << ihi;
00533       double dlg1 = *bigger;   // now the preceding element
00534       double dlg = (logGamma-dlg1)/(dlg2-dlg1);
00535       double omdlg = 1. - dlg;
00536       for (int i=0; i<N_ENERGY; ++i)
00537         collisions[i] = theCollisionTable[i*N_GAMMA+ihi-1]*omdlg +
00538           theCollisionTable[i*N_GAMMA+ihi]*dlg;
00539     }
00540     else {
00541       // bigger has no lower neighbour
00542        LogTrace(me) << ": using lowest gamma bin" 
00543                          << " for logGamma = " << logGamma;
00544 
00545       for (int i=0; i<N_ENERGY; ++i)
00546         collisions[i] = theCollisionTable[i*N_GAMMA];
00547     }
00548   }
00549 }

float CSCGasCollisions::generateEnergyLoss ( double  avCollisions,
double  anmin,
double  anmax,
const std::vector< float > &  collisions 
) const [private]

Definition at line 289 of file CSCGasCollisions.cc.

References CSCCrossGap::beta2(), funct::exp(), CSCCrossGap::gamma(), lnEnergyLoss(), funct::log(), LogTrace, me, theCrossGap, and theRandFlat.

Referenced by simulate().

00291 {
00292 // Generate a no. of collisions between collisions[0] and [N_ENERGY-1]
00293     float lnColl = log(theRandFlat->fire(anmin, anmax));
00294 
00295 // Without using CLHEP: approx random between anmin and anmax
00296 //    double ra = double(rand())/double(RAND_MAX)*avCollisions;
00297 //    cout << "ra = " << ra << std::endl;
00298 //    float lnColl = static_cast<float>( log( ra ) );
00299 
00300     // Find energy loss for that number
00301     float lnE    = lnEnergyLoss( lnColl, collisions );
00302     float eloss  = exp(lnE);
00303     // Compensate if gamma was actually below 1.1
00304     if ( theCrossGap->gamma() < 1.1 ) eloss = eloss * 0.173554/theCrossGap->beta2();
00305     LogTrace(me) << "eloss = " << eloss;
00306     // TODO
00307 //    theCrossGap->addEloss( eloss );
00308     return eloss;
00309 }

double CSCGasCollisions::generateStep ( double  avCollisions  )  const [private]

Definition at line 274 of file CSCGasCollisions.cc.

References LogTrace, me, cmsRelvalreportInput::step, and theRandExponential.

Referenced by simulate().

00275 {
00276 // Generate a m.f.p.  (1/avCollisions = cm/collision)
00277   double step = (theRandExponential->fire())/avCollisions;
00278 
00279 // Without using CLHEP: approx random exponential by...
00280 //    double da = double(rand())/double(RAND_MAX);
00281 //    double step = -log(1.-da)/avCollisions;
00282 
00283     LogTrace(me)  << " step = " << step;
00284     // TODO CAn this possibly be right?
00285     //if ( debugV ) theCrossGap->addStep( step );
00286     return step;
00287 }

void CSCGasCollisions::ionize ( double  energyTransferred,
LocalPoint  startHere 
) const [private]

Definition at line 311 of file CSCGasCollisions.cc.

References CSCCrossGap::addCluster(), CSCCrossGap::addElectrons(), CSCCrossGap::addElectronToBack(), clusterExtent, eion, ework, gasDensity, LogTrace, me, CSCCrossGap::noOfClusters(), CSCCrossGap::noOfElectrons(), funct::pow(), range, theCrossGap, and CSCCrossGap::unitVector().

Referenced by simulate().

00312 {
00313   while ( energyAvailable > eion ) {
00314     LogTrace(me) << "     NEW CLUSTER " << theCrossGap->noOfClusters() + 1 <<
00315                " AT " << startHere;
00316     LocalPoint newCluster( startHere );
00317     theCrossGap->addCluster(newCluster);
00318 
00319   //@@ I consider NOT subtracting eion before calculating range to be a bug.
00320   //@@ But this changes tuning of the algorithm so leave it until after the big rush to 7_5_0
00321   //@@  energyAvailable -= eion; 
00322 
00323   // Sauli CERN 77-09: delta e range with E in MeV (Sauli references Kobetich & Katz 1968,
00324   // but I cannot find this expression in that set of papers.)
00325   // Take HALF that range. //@@ Why? Why not...
00326     double range = 0.5 * (0.71/gasDensity)*pow( energyAvailable*1.E-6, 1.72);
00327     LogTrace(me) << " range = " << range;
00328     if ( range < clusterExtent ) {
00329 
00330       // short-range delta e
00331           // How many electrons can we make? Now use *average* energy for ionization (not *minimum*)
00332       int nelec = static_cast<int>(energyAvailable/ework);
00333       LogTrace(me) << "s-r delta energy in = " << energyAvailable;
00334       energyAvailable -= nelec*(energyAvailable/ework);
00335             // If still above eion (minimum, not average) add one more e
00336       if ( energyAvailable > eion ) {
00337         ++nelec;
00338         energyAvailable -= eion;
00339       }
00340       LogTrace(me) << "s-r delta energy out = " << energyAvailable << ", nelec = " << nelec;
00341       theCrossGap->addElectrons( nelec );
00342       break;
00343 
00344      }
00345      else {
00346       // long-range delta e
00347          LogTrace(me) << "l-r delta \n"
00348              << "no. of electrons in cluster now = " << theCrossGap->noOfElectrons();
00349          theCrossGap->addElectrons( 1 ); // Position is at startHere still
00350 
00351           bool new_range = false;
00352           while ( !new_range && (energyAvailable>ework) ) {
00353             energyAvailable -= ework;
00354             while ( energyAvailable > eion ) {
00355               double range2 = 0.5 * 0.71/gasDensity*pow( 1.E-6*energyAvailable, 1.72);
00356               double drange = range - range2;
00357               LogTrace(me) << "  energy left = " << energyAvailable << 
00358                         ", range2 = " << range2 << ", drange = " << drange;
00359               if ( drange < clusterExtent ) {
00360                 theCrossGap->addElectronToBack(); // increment last element
00361               }
00362               else {
00363                 startHere += drange*theCrossGap->unitVector(); // update delta e start position
00364                 range = range2;                       // update range
00365                 new_range = true;                     // Test range again
00366                 LogTrace(me) << "reset range to range2 and iterate";
00367               }
00368               break; // out of inner while energyAvailable>eion
00369 
00370             } // inner while energyAvailable>eion
00371 
00372           } // while !new_range && energyAvailable>ework
00373 
00374           // energyAvailable now less than ework, but still may be over eion...add an e
00375           if ( energyAvailable > eion ) {
00376             energyAvailable -= ework; // yes, it may go negative
00377             theCrossGap->addElectronToBack(); // add one more e
00378           }
00379 
00380         } // if range
00381 
00382       } // outer while energyAvailable>eion
00383 }

float CSCGasCollisions::lnEnergyLoss ( float  lnCollisions,
const std::vector< float > &  collisions 
) const [private]

Definition at line 473 of file CSCGasCollisions.cc.

References find(), it, LogTrace, me, and theEnergyBins.

Referenced by generateEnergyLoss().

00474                                               {
00475 
00476   float lnE = -1.;
00477 
00478    // Find collision[] bin in which lnCollisions falls
00479     std::vector<float>::const_iterator it = find(collisions.begin(),
00480       collisions.end(), lnCollisions );
00481 
00482     if ( it != collisions.end() ) {
00483       // found the value
00484       std::vector<float>::difference_type ihi = it - collisions.begin();
00485       LogTrace(me) << ": using one energy bin " << ihi << " = " 
00486                          << theEnergyBins[ihi]
00487                          << " for lnCollisions = " << lnCollisions;
00488       lnE = theEnergyBins[ihi];
00489     }
00490     else {
00491       // interpolate the value
00492       std::vector<float>::const_iterator loside = find_if(collisions.begin(),
00493         collisions.end(), bind2nd(less<float>(), lnCollisions));
00494       std::vector<float>::difference_type ilo = loside - collisions.begin();
00495       if ( ilo > 0 ) {
00496         LogTrace(me) << ": using energy bin " 
00497                            << ilo-1 << " and " << ilo;
00498         lnE = theEnergyBins[ilo-1] + (lnCollisions-collisions[ilo-1])*
00499           (theEnergyBins[ilo]-theEnergyBins[ilo-1]) /
00500              (collisions[ilo]-collisions[ilo-1]);
00501       }
00502       else {
00503         LogTrace(me) << ": using one energy bin 0 = " 
00504                            << theEnergyBins[0]
00505                            << " for lnCollisions = " << lnCollisions;
00506         lnE = theEnergyBins[0]; //@@ WHAT ELSE TO DO?
00507       }
00508     }
00509 
00510     return lnE;
00511 }

void CSCGasCollisions::readCollisionTable (  )  [private]

Definition at line 69 of file CSCGasCollisions.cc.

References Exception, f1, i, j, LogTrace, me, N_ENERGY, N_ENTRIES, N_GAMMA, FileInPath::name(), path(), theCollisionTable, theEnergyBins, and theGammaBins.

Referenced by CSCGasCollisions().

00069                                           {
00070 
00071   // I'd prefer to allow comments in the data file which means
00072   // complications of reading line-by-line and then item-by-item.
00073 
00074   // Is float OK? Or do I need double?
00075 
00076   // Do I need any sort of error trapping?
00077 
00078   // We use the default CMSSW data file path
00079   // We use the default file name 'collisions.dat'
00080    
00081   // This can be reset in .orcarc by SimpleConfigurable
00082   //    Muon:Endcap:CollisionsFile
00083 
00084   string path( getenv( "CMSSW_SEARCH_PATH" ) );
00085   // TODO make configurable
00086   string colliFile = "SimMuon/CSCDigitizer/data/collisions.dat";
00087   FileInPath f1( path, colliFile );
00088   if (f1() == 0 ) {
00089     string errorMessage = "Input file " + colliFile + "not found";
00090     edm::LogError("CSCGasCollisions") << errorMessage << " in path " << path
00091           << "\nSet Muon:Endcap:CollisionsFile in .orcarc to the "
00092          " location of the file relative to ORCA_DATA_PATH." ;
00093     throw cms::Exception( " Endcap Muon gas collisions data file not found.");
00094   }
00095   else {
00096     edm::LogInfo(me) << ": reading " << f1.name();
00097   }
00098 
00099   ifstream & fin = *f1();
00100 
00101   if (fin == 0) {
00102     string errorMessage = "Cannot open input file " + path + colliFile;
00103     edm::LogError("CSCGasCollisions") << errorMessage;
00104     throw cms::Exception(errorMessage);
00105   }
00106 
00107   fin.clear( );                  // Clear eof read status
00108   fin.seekg( 0, ios::beg );      // Position at start of file
00109 
00110   // @@ We had better have the right sizes everywhere or all
00111   // hell will break loose. There's no trapping.
00112   LogTrace(me) << "Reading gamma bins";
00113   int j = 0;
00114   for(int i = 0; i<N_GAMMA; ++i) {
00115     fin >> theGammaBins[i];
00116     LogTrace(me) << ++j << "   " << theGammaBins[i];
00117   }
00118 
00119   j = 0;
00120   LogTrace(me) << "Reading energy bins \n";
00121   for(int i = 0; i<N_ENERGY; ++i) {
00122      fin >> theEnergyBins[i];
00123      LogTrace(me) << ++j << "   " << theEnergyBins[i];
00124   }
00125 
00126   j = 0;
00127   LogTrace(me) << "Reading collisions table \n";
00128 
00129   for(int i = 0; i<N_ENTRIES; ++i) {
00130      fin >> theCollisionTable[i];
00131      LogTrace(me) << ++j << "   " << theCollisionTable[i];
00132   }
00133 
00134   fin.close();
00135 }

void CSCGasCollisions::setParticleDataTable ( const ParticleDataTable pdt  ) 

Definition at line 138 of file CSCGasCollisions.cc.

References theParticleDataTable.

Referenced by CSCWireHitSim::setParticleDataTable().

00139 {
00140   theParticleDataTable = pdt;
00141 }

void CSCGasCollisions::setRandomEngine ( CLHEP::HepRandomEngine &  engine  ) 

Definition at line 144 of file CSCGasCollisions.cc.

References theRandExponential, and theRandFlat.

Referenced by CSCWireHitSim::setRandomEngine().

00145 {
00146   theRandFlat = new CLHEP::RandFlat(engine);
00147   theRandExponential = new CLHEP::RandExponential(engine);
00148 }

void CSCGasCollisions::simulate ( const PSimHit simHit,
const CSCLayer layer,
std::vector< LocalPoint > &  clusters,
std::vector< int > &  electrons 
)

Definition at line 151 of file CSCGasCollisions.cc.

References deCut, eion, CSCCrossGap::electrons(), PSimHit::entryPoint(), PSimHit::exitPoint(), funct::exp(), fillCollisionsForThisGamma(), generateEnergyLoss(), generateStep(), CSCCrossGap::ionClusters(), ionize(), CSCCrossGap::length(), CSCCrossGap::logGamma(), LogTrace, MAX_STEPS, me, N_ENERGY, PSimHit::pabs(), PSimHit::particleType(), cmsRelvalreportInput::step, theCrossGap, theParticleDataTable, and CSCCrossGap::unitVector().

Referenced by CSCWireHitSim::getIonizationClusters().

00152                                                                 {
00153 
00154   const float epsilonL = 0.01;                     // Shortness of simhit 'length'
00155   //  const float max_gap_z = 1.5;                     // Gas gaps are 0.5 or 1.0 cm
00156 
00157   // Note that what I call the 'gap' may in fact be the 'length' of a PSimHit which
00158   // does not start and end on the gap edges. This confuses the nomenclature at least.
00159 
00160   double mom    = simHit.pabs();
00161   int iam       = simHit.particleType();           // PDG type
00162   delete theCrossGap;                              // before building new one
00163   assert(theParticleDataTable != 0);
00164   ParticleData const * particle = theParticleDataTable->particle( simHit.particleType() );
00165   double mass = 0.105658; // assume a muon
00166   if(particle == 0)
00167   {
00168      edm::LogError("CSCGasCollisions") << "Cannot find particle of type " << simHit.particleType()
00169                                        << " in the PDT";
00170   }
00171   else 
00172   {
00173     mass = particle->mass();
00174   }
00175 
00176   theCrossGap   = new CSCCrossGap( mass, mom, simHit.exitPoint() - simHit.entryPoint() );
00177   float gapSize = theCrossGap->length();
00178 
00179   // Test the simhit 'length' (beware of angular effects)
00180   //  if ( gapSize <= epsilonL || gapSize > max_gap_z ) {
00181   if ( gapSize <= epsilonL ) {
00182     LogTrace(me) << ": WARNING! simhit entry and exit are very close: \n"
00183       << "\n entry = " << simHit.entryPoint()
00184       << "\n exit  = " << simHit.exitPoint()
00185       << "\n particle type = " << iam << ", momentum = " << mom 
00186       << ", gap length = " << gapSize;
00187     return; //@@ Just skip this PSimHit
00188   }
00189 
00190   // Interpolate the table for current gamma value
00191   // Extract collisions binned by energy loss values, for this gamma
00192   std::vector<float> collisions(N_ENERGY);
00193   double loggam = theCrossGap->logGamma(); 
00194   fillCollisionsForThisGamma( static_cast<float>(loggam), collisions );
00195 
00196   double anmin = exp(collisions[N_ENERGY-1]);
00197   double anmax = exp(collisions[0]);
00198   double amu   = anmax - anmin;
00199 
00200   LogTrace(me) << "collisions extremes = " << collisions[N_ENERGY-1]
00201      << ", " << collisions[0] << "\n"
00202      << "anmin = " << anmin << ", anmax = " << anmax << "\n"
00203      << "amu = " << amu << "\n";
00204 
00205   float dedx       = 0.; // total energy loss
00206   double sum_steps = 0.; // total distance across gap (along simhit direction)
00207   int n_steps      = 0;  // no. of steps/primary collisions
00208   int n_try        = 0;  // no. of tries to generate steps
00209   double step      = -1.; // Sentinel for start
00210 
00211   //LocalPoint chamberLocalPoint( simHit.entryPoint() );
00212   // translate to layer local coordinates
00213   //GlobalPoint globalPoint( layer->chamber()->toGlobal(chamberLocalPoint) );
00214   //LocalPoint layerLocalPoint( layer->toLocal(globalPoint) );
00215   LocalPoint layerLocalPoint( simHit.entryPoint() );
00216 
00217   //std::cout << "DEBUG " << chamberLocalPoint << " " << layerLocalPoint << std::endl;
00218   // step/primary collision loop
00219   while ( sum_steps < gapSize) {
00220     ++n_try;
00221     if ( n_try > MAX_STEPS ) {
00222           LogTrace(me) << ": n_try=" << n_try << " is too large. Skip simhit."
00223            << "\n particle type=" << iam << ", momentum= " << mom
00224            << "\n gapSize=" << gapSize << ", last step=" << step 
00225            << ", sum_steps=" << sum_steps << ", n_steps=" << n_steps;
00226         break;
00227     }
00228     step = generateStep( amu );
00229     if ( sum_steps + step > gapSize ) break;
00230 
00231     float eloss = generateEnergyLoss( amu, anmin, anmax, collisions );
00232 
00233     // Is the eloss too large? (then GEANT should have produced hits!)
00234     if ( eloss > deCut ) {
00235       LogTrace(me) << "eloss > " << deCut << " = " << eloss;
00236       continue; // to generate another collision/step
00237     }
00238 
00239     dedx      += eloss; // the energy lost from the ionizing particle
00240     sum_steps += step;  // the position of the ionizing particle
00241     ++n_steps;          // the number of primary collisions
00242     
00243     if (n_steps > MAX_STEPS ) { // Extra-careful trap for bizarreness
00244         edm::LogInfo(me) << ": n_steps=" << n_steps << " is too large. Skip simhit.";
00245         edm::LogInfo(me) << "particle type=" << iam << ", momentum= " << mom;
00246         edm::LogInfo(me) << "gapSize=" << gapSize << ", last step=" << step 
00247              << ", sum_steps=" << sum_steps;
00248         break;
00249     }
00250     LogTrace(me) << "sum_steps = " << sum_steps << ", dedx = " << dedx;
00251     
00252     // Generate ionization. 
00253     // eion is the minimum energy at which ionization can occur in the gas
00254     if ( eloss > eion  ) {
00255       layerLocalPoint += step * theCrossGap->unitVector(); // local point where the collision occurs
00256       ionize( eloss, layerLocalPoint );
00257     }
00258     else {
00259       LogTrace(me) << "Energy available = " << eloss <<
00260         ", too low for ionization.";
00261     }
00262 
00263   } // step/collision loop
00264 
00265   //TODO port this
00266   //if ( debugV ) writeSummary( n_steps, sum_steps, dedx );
00267 
00268   // Return values in two container arguments
00269   positions = theCrossGap->ionClusters();
00270   electrons = theCrossGap->electrons();
00271   return;
00272 }

void CSCGasCollisions::writeSummary ( int  n_steps,
double  sum_steps,
float  dedx 
) const [private]

Definition at line 385 of file CSCGasCollisions.cc.

References edmNew::copy(), GenMuonPlsPt100GeV_cfg::cout, eion, CSCCrossGap::electrons(), CSCCrossGap::eLossPerStep(), lat::endl(), find(), CSCCrossGap::ionClusters(), CSCCrossGap::noOfSteps(), saveGasCollisions, CSCCrossGap::stepLengths(), steps, and theCrossGap.

00386 {
00387   std::vector<LocalPoint> ion_clusters = theCrossGap->ionClusters();
00388   std::vector<int> electrons             = theCrossGap->electrons();
00389   std::vector<float> elosses             = theCrossGap->eLossPerStep();
00390   std::vector<double> steps              = theCrossGap->stepLengths();
00391 
00392     cout << "------------------" << std::endl;
00393     cout << "AFTER CROSSING GAP" << std::endl;
00394     cout << "No. of steps = " << n_steps << std::endl;
00395     cout << "Check:  stored steps = " << theCrossGap->noOfSteps() << std::endl;
00396 
00397     cout << "Lengths of steps: " << std::endl;
00398     std::copy( steps.begin(), steps.end(), std::ostream_iterator<float>(cout,"\n"));
00399     cout << std::endl;
00400 
00401     if ( saveGasCollisions ) {
00402       ofstream of0("osteplen.dat",ios::app);
00403       std::copy( steps.begin(), steps.end(), std::ostream_iterator<float>(of0,"\n"));
00404     }
00405 
00406     cout << "Total sum of steps = " << sum_steps << std::endl;
00407     if ( n_steps > 0 ) cout << "Average step length = " << 
00408        sum_steps/float(n_steps) << std::endl;
00409     cout << std::endl;
00410     
00411     cout << "Energy loss per collision:" << std::endl;
00412     std::copy( elosses.begin(), elosses.end(), std::ostream_iterator<float>(cout,"\n"));
00413     cout << std::endl;
00414 
00415     if ( saveGasCollisions ) {
00416       ofstream of1("olperc.dat",ios::app);
00417       std::copy( elosses.begin(), elosses.end(), std::ostream_iterator<float>(of1,"\n"));
00418     }
00419 
00420     cout << "Total energy loss across gap = " << dedx << " eV = " <<
00421        dedx/1000. << " keV" << std::endl;
00422     int n_ic = count_if( elosses.begin(), elosses.end(),
00423                      bind2nd(greater<float>(), eion) );
00424     cout << "No. of primary ionizing collisions across gap = " << n_ic << std::endl;
00425     if ( n_steps > 0 ) cout << "Average energy loss/collision = " << 
00426        dedx/float(n_steps) << " eV" << std::endl;
00427     cout << std::endl;
00428 
00429     cout << "No. of ion clusters = " << ion_clusters.size() << std::endl;
00430     cout << "Positions of clusters:" << std::endl;
00431     std::copy( ion_clusters.begin(), ion_clusters.end(), 
00432          std::ostream_iterator<LocalPoint>(cout,"\n"));
00433     cout << std::endl;
00434 
00435     if ( saveGasCollisions ) {
00436       ofstream of2("oclpos.dat",ios::app);
00437       std::copy( ion_clusters.begin(), ion_clusters.end(), 
00438          std::ostream_iterator<LocalPoint>(of2,"\n"));
00439     }
00440 
00441     cout << "No. of electrons per cluster:" << std::endl;
00442     std::copy( electrons.begin(), electrons.end(), std::ostream_iterator<int>(cout,"\n"));
00443     cout << std::endl;
00444 
00445     if ( saveGasCollisions ) {
00446       ofstream of3("oepercl.dat",ios::app);
00447       std::copy( electrons.begin(), electrons.end(), std::ostream_iterator<int>(of3,"\n"));
00448     }
00449 
00450     // Check for zero-e clusters
00451     std::vector<int>::const_iterator bigger = find(electrons.begin(),
00452            electrons.end(), 0 );
00453     if ( bigger != electrons.end() ) {
00454        cout << "Error! There is a cluster with 0 electrons." << std::endl;
00455     }
00456     int n_e = accumulate(electrons.begin(), electrons.end(), 0 );
00457     if ( n_steps > 0 ) {
00458       cout << "Total no. of electrons = " << n_e << ", energy loss/e = " <<
00459             dedx/float(n_e) << " eV " << std::endl;
00460             cout << "Average no. of electrons per cluster = " <<
00461             float(n_e)/float(ion_clusters.size()) << std::endl;
00462       cout << "------------------" << std::endl;
00463 
00464       cout << "#steps  path   av_step  n_i_cl  E/gap   n_i_col  E/step  n_e   E/e     e/i_c" << std::endl;
00465       cout << "#        cm       cm             keV               eV          eV       eV" << std::endl;
00466       cout << " " << n_steps << "  " << sum_steps << " " << sum_steps/float(n_steps) << "    " <<
00467          ion_clusters.size() << "    " <<
00468          dedx/1000. << "    " << n_ic << "    " << dedx/float(n_steps) << "  " << n_e << "  " <<
00469          dedx/float(n_e) << " " << float(n_e)/float(ion_clusters.size()) << std::endl;
00470     }
00471 }


Member Data Documentation

double CSCGasCollisions::clusterExtent [private]

Definition at line 65 of file CSCGasCollisions.h.

Referenced by CSCGasCollisions(), and ionize().

double CSCGasCollisions::deCut [private]

Definition at line 62 of file CSCGasCollisions.h.

Referenced by CSCGasCollisions(), and simulate().

double CSCGasCollisions::eion [private]

Definition at line 63 of file CSCGasCollisions.h.

Referenced by CSCGasCollisions(), ionize(), simulate(), and writeSummary().

double CSCGasCollisions::ework [private]

Definition at line 64 of file CSCGasCollisions.h.

Referenced by CSCGasCollisions(), and ionize().

double CSCGasCollisions::gasDensity [private]

Definition at line 56 of file CSCGasCollisions.h.

Referenced by CSCGasCollisions(), and ionize().

const int CSCGasCollisions::MAX_STEPS = 400 [static]

Definition at line 41 of file CSCGasCollisions.h.

Referenced by simulate().

const std::string CSCGasCollisions::me [private]

Definition at line 55 of file CSCGasCollisions.h.

Referenced by CSCGasCollisions(), fillCollisionsForThisGamma(), generateEnergyLoss(), generateStep(), ionize(), lnEnergyLoss(), readCollisionTable(), simulate(), and ~CSCGasCollisions().

const int CSCGasCollisions::N_ENERGY = 63 [static]

Definition at line 39 of file CSCGasCollisions.h.

Referenced by fillCollisionsForThisGamma(), readCollisionTable(), and simulate().

const int CSCGasCollisions::N_ENTRIES = N_GAMMA*N_ENERGY [static]

Definition at line 40 of file CSCGasCollisions.h.

Referenced by readCollisionTable().

const int CSCGasCollisions::N_GAMMA = 21 [static]

Definition at line 38 of file CSCGasCollisions.h.

Referenced by fillCollisionsForThisGamma(), and readCollisionTable().

bool CSCGasCollisions::saveGasCollisions [private]

Definition at line 75 of file CSCGasCollisions.h.

Referenced by CSCGasCollisions(), and writeSummary().

std::vector<float> CSCGasCollisions::theCollisionTable [private]

Definition at line 69 of file CSCGasCollisions.h.

Referenced by fillCollisionsForThisGamma(), and readCollisionTable().

CSCCrossGap* CSCGasCollisions::theCrossGap [private]

Definition at line 71 of file CSCGasCollisions.h.

Referenced by generateEnergyLoss(), ionize(), simulate(), writeSummary(), and ~CSCGasCollisions().

std::vector<float> CSCGasCollisions::theEnergyBins [private]

Definition at line 68 of file CSCGasCollisions.h.

Referenced by lnEnergyLoss(), and readCollisionTable().

std::vector<float> CSCGasCollisions::theGammaBins [private]

Definition at line 67 of file CSCGasCollisions.h.

Referenced by fillCollisionsForThisGamma(), and readCollisionTable().

const ParticleDataTable* CSCGasCollisions::theParticleDataTable [private]

Definition at line 72 of file CSCGasCollisions.h.

Referenced by setParticleDataTable(), and simulate().

CLHEP::RandExponential* CSCGasCollisions::theRandExponential [private]

Definition at line 74 of file CSCGasCollisions.h.

Referenced by generateStep(), setRandomEngine(), and ~CSCGasCollisions().

CLHEP::RandFlat* CSCGasCollisions::theRandFlat [private]

Definition at line 73 of file CSCGasCollisions.h.

Referenced by generateEnergyLoss(), setRandomEngine(), and ~CSCGasCollisions().


The documentation for this class was generated from the following files:
Generated on Tue Jun 9 18:17:19 2009 for CMSSW by  doxygen 1.5.4