CMS 3D CMS Logo

MaterialEffects.cc

Go to the documentation of this file.
00001 //Framework Headers
00002 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00003 
00004 //TrackingTools Headers
00005 
00006 // Famos Headers
00007 #include "FastSimulation/Event/interface/FSimEvent.h"
00008 #include "FastSimulation/ParticlePropagator/interface/ParticlePropagator.h"
00009 #include "FastSimulation/TrackerSetup/interface/TrackerLayer.h"
00010 #include "FastSimulation/MaterialEffects/interface/MaterialEffects.h"
00011 
00012 #include "FastSimulation/MaterialEffects/interface/PairProductionSimulator.h"
00013 #include "FastSimulation/MaterialEffects/interface/MultipleScatteringSimulator.h"
00014 #include "FastSimulation/MaterialEffects/interface/BremsstrahlungSimulator.h"
00015 #include "FastSimulation/MaterialEffects/interface/EnergyLossSimulator.h"
00016 #include "FastSimulation/MaterialEffects/interface/NuclearInteractionSimulator.h"
00017 
00018 #include <list>
00019 #include <map>
00020 #include <string>
00021 
00022 MaterialEffects::MaterialEffects(const edm::ParameterSet& matEff,
00023                                  const RandomEngine* engine)
00024   : PairProduction(0), Bremsstrahlung(0), 
00025     MultipleScattering(0), EnergyLoss(0), 
00026     NuclearInteraction(0),
00027     pTmin(999.), random(engine)
00028 {
00029   // Set the minimal photon energy for a Brem from e+/-
00030 
00031   bool doPairProduction     = matEff.getParameter<bool>("PairProduction");
00032   bool doBremsstrahlung     = matEff.getParameter<bool>("Bremsstrahlung");
00033   bool doEnergyLoss         = matEff.getParameter<bool>("EnergyLoss");
00034   bool doMultipleScattering = matEff.getParameter<bool>("MultipleScattering");
00035   bool doNuclearInteraction = matEff.getParameter<bool>("NuclearInteraction");
00036 
00037   double A = matEff.getParameter<double>("A");
00038   double Z = matEff.getParameter<double>("Z");
00039   double density = matEff.getParameter<double>("Density");
00040   double radLen = matEff.getParameter<double>("RadiationLength");
00041   
00042   // Set the minimal pT before giving up the dE/dx treatment
00043 
00044   if ( doPairProduction ) { 
00045 
00046     double photonEnergy = matEff.getParameter<double>("photonEnergy");
00047     PairProduction = new PairProductionSimulator(photonEnergy,
00048                                                  random);
00049 
00050   }
00051 
00052   if ( doBremsstrahlung ) { 
00053 
00054     double bremEnergy = matEff.getParameter<double>("bremEnergy");
00055     double bremEnergyFraction = matEff.getParameter<double>("bremEnergyFraction");
00056     Bremsstrahlung = new BremsstrahlungSimulator(bremEnergy,
00057                                                  bremEnergyFraction,
00058                                                  random);
00059 
00060   }
00061 
00062   if ( doEnergyLoss ) { 
00063 
00064     pTmin = matEff.getParameter<double>("pTmin");
00065     EnergyLoss = new EnergyLossSimulator(random,A,Z,density,radLen);
00066 
00067   }
00068 
00069   if ( doMultipleScattering ) { 
00070     
00071     MultipleScattering = new MultipleScatteringSimulator(random,A,Z,density,radLen);
00072 
00073   }
00074 
00075   if ( doNuclearInteraction ) { 
00076 
00077     // The energies simulated
00078     std::vector<double> pionEnergies 
00079       = matEff.getUntrackedParameter<std::vector<double> >("pionEnergies");
00080 
00081     // The particle types simulated
00082     std::vector<int> pionTypes 
00083       = matEff.getUntrackedParameter<std::vector<int> >("pionTypes");
00084 
00085     // The corresponding particle names
00086     std::vector<std::string> pionNames 
00087       = matEff.getUntrackedParameter<std::vector<std::string> >("pionNames");
00088 
00089     // The corresponding particle masses
00090     std::vector<double> pionMasses 
00091       = matEff.getUntrackedParameter<std::vector<double> >("pionMasses");
00092 
00093     // The smallest momentum for inelastic interactions
00094     std::vector<double> pionPMin 
00095       = matEff.getUntrackedParameter<std::vector<double> >("pionMinP");
00096 
00097     // The interaction length / radiation length ratio for each particle type
00098     std::vector<double> lengthRatio 
00099       = matEff.getParameter<std::vector<double> >("lengthRatio");
00100     //    std::map<int,double> lengthRatio;
00101     //    for ( unsigned i=0; i<theLengthRatio.size(); ++i )
00102     //      lengthRatio[ pionTypes[i] ] = theLengthRatio[i];
00103 
00104     // A global fudge factor for TEC layers (which apparently do not react to 
00105     // hadrons the same way as all other layers...
00106     theTECFudgeFactor = matEff.getParameter<double>("fudgeFactor");
00107 
00108     // The evolution of the interaction lengths with energy
00109     std::vector<double> theRatios  
00110       = matEff.getUntrackedParameter<std::vector<double> >("ratios");
00111     //std::map<int,std::vector<double> > ratios;
00112     //for ( unsigned i=0; i<pionTypes.size(); ++i ) { 
00113     //  for ( unsigned j=0; j<pionEnergies.size(); ++j ) { 
00114     //  ratios[ pionTypes[i] ].push_back(theRatios[ i*pionEnergies.size() + j ]);
00115     //  }
00116     //}
00117     std::vector< std::vector<double> > ratios;
00118     ratios.resize(pionTypes.size());
00119     for ( unsigned i=0; i<pionTypes.size(); ++i ) { 
00120       for ( unsigned j=0; j<pionEnergies.size(); ++j ) { 
00121         ratios[i].push_back(theRatios[ i*pionEnergies.size() + j ]);
00122       }
00123     }
00124 
00125     // The smallest momentum for elastic interactions
00126     double pionEnergy 
00127       = matEff.getParameter<double>("pionEnergy");
00128 
00129     // The algorithm to compute the distance between primary and secondaries
00130     // when a nuclear interaction occurs
00131     unsigned distAlgo 
00132       = matEff.getParameter<unsigned>("distAlgo");
00133     double distCut 
00134       = matEff.getParameter<double>("distCut");
00135 
00136     // The file to read the starting interaction in each files
00137     // (random reproducibility in case of a crash)
00138     std::string inputFile 
00139       = matEff.getUntrackedParameter<std::string>("inputFile");
00140 
00141     // Build the ID map (i.e., what is to be considered as a proton, etc...)
00142     std::map<int,int> idMap;
00143     // Protons
00144     std::vector<int> idProtons 
00145       = matEff.getUntrackedParameter<std::vector<int> >("protons");
00146     for ( unsigned i=0; i<idProtons.size(); ++i ) 
00147       idMap[idProtons[i]] = 2212;
00148     // Anti-Protons
00149     std::vector<int> idAntiProtons 
00150       = matEff.getUntrackedParameter<std::vector<int> >("antiprotons");
00151     for ( unsigned i=0; i<idAntiProtons.size(); ++i ) 
00152       idMap[idAntiProtons[i]] = -2212;
00153     // Neutrons
00154     std::vector<int> idNeutrons 
00155       = matEff.getUntrackedParameter<std::vector<int> >("neutrons");
00156     for ( unsigned i=0; i<idNeutrons.size(); ++i ) 
00157       idMap[idNeutrons[i]] = 2112;
00158     // Anti-Neutrons
00159     std::vector<int> idAntiNeutrons 
00160       = matEff.getUntrackedParameter<std::vector<int> >("antineutrons");
00161     for ( unsigned i=0; i<idAntiNeutrons.size(); ++i ) 
00162       idMap[idAntiNeutrons[i]] = -2112;
00163     // K0L's
00164     std::vector<int> idK0Ls 
00165       = matEff.getUntrackedParameter<std::vector<int> >("K0Ls");
00166     for ( unsigned i=0; i<idK0Ls.size(); ++i ) 
00167       idMap[idK0Ls[i]] = 130;
00168     // K+'s
00169     std::vector<int> idKplusses 
00170       = matEff.getUntrackedParameter<std::vector<int> >("Kplusses");
00171     for ( unsigned i=0; i<idKplusses.size(); ++i ) 
00172       idMap[idKplusses[i]] = 321;
00173     // K-'s
00174     std::vector<int> idKminusses 
00175       = matEff.getUntrackedParameter<std::vector<int> >("Kminusses");
00176     for ( unsigned i=0; i<idKminusses.size(); ++i ) 
00177       idMap[idKminusses[i]] = -321;
00178     // pi+'s
00179     std::vector<int> idPiplusses 
00180       = matEff.getUntrackedParameter<std::vector<int> >("Piplusses");
00181     for ( unsigned i=0; i<idPiplusses.size(); ++i ) 
00182       idMap[idPiplusses[i]] = 211;
00183     // pi-'s
00184     std::vector<int> idPiminusses 
00185       = matEff.getUntrackedParameter<std::vector<int> >("Piminusses");
00186     for ( unsigned i=0; i<idPiminusses.size(); ++i ) 
00187       idMap[idPiminusses[i]] = -211;
00188 
00189     // Construction
00190     NuclearInteraction = 
00191       new NuclearInteractionSimulator(pionEnergies, pionTypes, pionNames, 
00192                                       pionMasses, pionPMin, pionEnergy, 
00193                                       lengthRatio, ratios, idMap, 
00194                                       inputFile, distAlgo, distCut, random);
00195   }
00196 
00197 }
00198 
00199 
00200 MaterialEffects::~MaterialEffects() {
00201 
00202   if ( PairProduction ) delete PairProduction;
00203   if ( Bremsstrahlung ) delete Bremsstrahlung;
00204   if ( EnergyLoss ) delete EnergyLoss;
00205   if ( MultipleScattering ) delete MultipleScattering;
00206   if ( NuclearInteraction ) delete NuclearInteraction;
00207 
00208 }
00209 
00210 void MaterialEffects::interact(FSimEvent& mySimEvent, 
00211                                const TrackerLayer& layer,
00212                                ParticlePropagator& myTrack,
00213                                unsigned itrack) {
00214 
00215   MaterialEffectsSimulator::RHEP_const_iter DaughterIter;
00216   double radlen;
00217   theEnergyLoss = 0;
00218   theNormalVector = normalVector(layer,myTrack);
00219   radlen = radLengths(layer,myTrack);
00220 
00221 //-------------------
00222 //  Photon Conversion
00223 //-------------------
00224 
00225   if ( PairProduction && myTrack.pid()==22 ) {
00226     
00227     //
00228     PairProduction->updateState(myTrack,radlen);
00229 
00230     if ( PairProduction->nDaughters() ) {       
00231       //add a vertex to the mother particle
00232       int ivertex = mySimEvent.addSimVertex(myTrack.vertex(),itrack);
00233       
00234       // This was a photon that converted
00235       for ( DaughterIter = PairProduction->beginDaughters();
00236             DaughterIter != PairProduction->endDaughters(); 
00237             ++DaughterIter) {
00238 
00239         mySimEvent.addSimTrack(&(*DaughterIter), ivertex);
00240 
00241       }
00242       // The photon converted. Return.
00243       return;
00244     }
00245   }
00246 
00247   if ( myTrack.pid() == 22 ) return;
00248 
00249 //------------------------
00250 //   Nuclear interactions
00251 //------------------------ 
00252 
00253   if ( NuclearInteraction && abs(myTrack.pid()) > 100 
00254                           && abs(myTrack.pid()) < 1000000) { 
00255 
00256     // Simulate a nuclear interaction
00257     double factor = 1.0;
00258     if (layer.layerNumber() >= 19 && layer.layerNumber() <= 27 ) 
00259       factor = theTECFudgeFactor;
00260     NuclearInteraction->updateState(myTrack,radlen*factor);
00261 
00262     if ( NuclearInteraction->nDaughters() ) { 
00263 
00264       //add a end vertex to the mother particle
00265       int ivertex = mySimEvent.addSimVertex(myTrack.vertex(),itrack);
00266       
00267       // This was a hadron that interacted inelastically
00268       int idaugh = 0;
00269       for ( DaughterIter = NuclearInteraction->beginDaughters();
00270             DaughterIter != NuclearInteraction->endDaughters(); 
00271             ++DaughterIter) {
00272 
00273         // The daughter in the event
00274         int daughId = mySimEvent.addSimTrack(&(*DaughterIter), ivertex);
00275         
00276         // Store the closest daughter in the mother info (for later tracking purposes)
00277         if ( NuclearInteraction->closestDaughterId() == idaugh++ ) {
00278           if ( mySimEvent.track(itrack).vertex().position().Pt() < 4.0 ) 
00279             mySimEvent.track(itrack).setClosestDaughterId(daughId);
00280         }
00281 
00282       }
00283       // The hadron is destroyed. Return.
00284       return;
00285     }
00286     
00287   }
00288 
00289   if ( myTrack.charge() == 0 ) return;
00290 
00291   if ( !Bremsstrahlung && !EnergyLoss && !MultipleScattering ) return;
00292 
00293 //----------------
00294 //  Bremsstrahlung
00295 //----------------
00296 
00297   if ( Bremsstrahlung && abs(myTrack.pid())==11 ) {
00298         
00299     Bremsstrahlung->updateState(myTrack,radlen);
00300 
00301     if ( Bremsstrahlung->nDaughters() ) {
00302       
00303       // Add a vertex, but do not attach it to the electron, because it 
00304       // continues its way...
00305       int ivertex = mySimEvent.addSimVertex(myTrack.vertex(),itrack);
00306 
00307       for ( DaughterIter = Bremsstrahlung->beginDaughters();
00308             DaughterIter != Bremsstrahlung->endDaughters(); 
00309             ++DaughterIter) {
00310         mySimEvent.addSimTrack(&(*DaughterIter), ivertex);
00311 
00312       }
00313       
00314     }
00315     
00316   } 
00317 
00318 
00322 
00323   if ( EnergyLoss )
00324   {
00325     theEnergyLoss = myTrack.E();
00326     EnergyLoss->updateState(myTrack,radlen);
00327     theEnergyLoss -= myTrack.E();
00328   }
00329   
00330 
00334 
00335   if ( MultipleScattering && myTrack.Pt() > pTmin ) {
00336     //    MultipleScattering->setNormalVector(normalVector(layer,myTrack));
00337     MultipleScattering->setNormalVector(theNormalVector);
00338     MultipleScattering->updateState(myTrack,radlen);
00339   }
00340     
00341 }
00342 
00343 double
00344 MaterialEffects::radLengths(const TrackerLayer& layer,
00345                             ParticlePropagator& myTrack) {
00346 
00347   // Thickness of layer
00348   theThickness = layer.surface().mediumProperties()->radLen();
00349 
00350   GlobalVector P(myTrack.Px(),myTrack.Py(),myTrack.Pz());
00351   
00352   // Effective length of track inside layer (considering crossing angle)
00353   //  double radlen = theThickness / fabs(P.dot(theNormalVector)/(P.mag()*theNormalVector.mag()));
00354   double radlen = theThickness / fabs(P.dot(theNormalVector)) * P.mag();
00355 
00356   // This is a series of fudge factors (from the geometry description), 
00357   // to describe the layer inhomogeneities (services, cables, supports...)
00358   double rad = myTrack.R();
00359   double zed = fabs(myTrack.Z());
00360 
00361   double factor = 1;
00362 
00363   // Are there fudge factors for this layer
00364   if ( layer.fudgeNumber() ) 
00365 
00366     // If yes, loop on them
00367     for ( unsigned int iLayer=0; iLayer < layer.fudgeNumber(); ++iLayer ) { 
00368 
00369       // Apply to R if forward layer, to Z if barrel layer
00370       if ( (  layer.forward() && layer.fudgeMin(iLayer) < rad && rad < layer.fudgeMax(iLayer) )  ||
00371            ( !layer.forward() && layer.fudgeMin(iLayer) < zed && zed < layer.fudgeMax(iLayer) ) ) {
00372         factor = layer.fudgeFactor(iLayer);
00373         break;
00374       }
00375     
00376   }
00377 
00378   theThickness *= factor;
00379 
00380   return radlen * factor;
00381 
00382 }
00383 
00384 GlobalVector
00385 MaterialEffects::normalVector(const TrackerLayer& layer,
00386                               ParticlePropagator& myTrack ) const {
00387   return layer.forward() ?  
00388     layer.disk()->normalVector() :
00389     GlobalVector(myTrack.X(),myTrack.Y(),0.)/myTrack.R();
00390 }
00391 
00392 void 
00393 MaterialEffects::save() { 
00394 
00395   // Save current nuclear interactions in the event libraries.
00396   if ( NuclearInteraction ) NuclearInteraction->save();
00397 
00398 }

Generated on Tue Jun 9 17:35:09 2009 for CMSSW by  doxygen 1.5.4