CMS 3D CMS Logo

CSCGasCollisions.cc

Go to the documentation of this file.
00001 // This implements the CSC gas ionization simulation.
00002 // It requires the GEANT3-generated tables in the input file 
00003 // (default) MuonData/EndcapData/collisions.dat
00004 
00005 // Outstanding problems to fix 15-Oct-2003
00006 // - ework must be re-tuned once eion or ework are removed before delta e range estimation.
00007 // - logic of long-range delta e's must be revisited.
00008 // - The code here needs to have diagnostic output removed, or reduced. PARTICULARLY filling of std::vectors!
00009 // - 'gap' is a misnomer, when simhit entry and exit don't coincide with gap edges
00010 //  so the CSCCrossGap might better be named as a simhit-related thing. 
00011 // 22-Jan-2004 Corrected position of trap for 'infinite' loop while
00012 //    generating steps. Output files (debugV-flagged only) require SC flag.
00013 //    Increase deCut from 10 keV to 100 keV to accomodate protons!
00014 
00015 #include "FWCore/Utilities/interface/Exception.h"
00016 #include "DataFormats/GeometryVector/interface/LocalVector.h"
00017 #include "SimMuon/CSCDigitizer/src/CSCGasCollisions.h"
00018 #include "Utilities/General/interface/FileInPath.h"
00019 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00020 #include <iostream>
00021 #include <fstream>
00022 
00023 // stdlib math functions
00024 // for 'abs':
00025 #include <cstdlib>
00026 // for usual math functions:
00027 #include <cmath>
00028 
00029 // stdlib container trickery
00030 // for 'for_each':
00031 #include <algorithm>
00032 // for 'greater' and 'less':
00033 #include <functional>
00034 // for 'accumulate':
00035 #include <numeric>
00036 
00037 using namespace std;
00038 
00039 CSCGasCollisions::CSCGasCollisions() : 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 }
00061 
00062 CSCGasCollisions::~CSCGasCollisions() {
00063   edm::LogInfo(me) << "Destructing a " << me;
00064   delete theCrossGap;
00065   delete theRandFlat;
00066   delete theRandExponential;
00067 }
00068 
00069 void CSCGasCollisions::readCollisionTable() {
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 }
00136 
00137 
00138 void CSCGasCollisions::setParticleDataTable(const ParticleDataTable * pdt)
00139 {
00140   theParticleDataTable = pdt;
00141 }
00142 
00143 
00144 void CSCGasCollisions::setRandomEngine(CLHEP::HepRandomEngine & engine)
00145 {
00146   theRandFlat = new CLHEP::RandFlat(engine);
00147   theRandExponential = new CLHEP::RandExponential(engine);
00148 }
00149 
00150 
00151 void CSCGasCollisions::simulate( const PSimHit& simHit, const CSCLayer * layer,
00152   std::vector<LocalPoint>& positions, std::vector<int>& electrons ) {
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 }
00273 
00274 double CSCGasCollisions::generateStep( double avCollisions ) const
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 }
00288 
00289 float CSCGasCollisions::generateEnergyLoss( double avCollisions,
00290    double anmin, double anmax, const std::vector<float>& collisions ) const
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 }
00310 
00311 void  CSCGasCollisions::ionize( double energyAvailable, LocalPoint startHere ) const
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 }
00384 
00385 void CSCGasCollisions::writeSummary( int n_steps, double sum_steps, float dedx ) const
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 }
00472 
00473 float CSCGasCollisions::lnEnergyLoss( float lnCollisions, 
00474    const std::vector<float>& collisions ) const {
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 }
00512 
00513 void CSCGasCollisions::fillCollisionsForThisGamma( float logGamma,
00514    std::vector<float>& collisions ) const
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 }

Generated on Tue Jun 9 17:47:31 2009 for CMSSW by  doxygen 1.5.4