CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_4_5_patch3/src/FastSimulation/Event/src/FBaseSimEvent.cc

Go to the documentation of this file.
00001 //HepMC Headers
00002 #include "HepMC/GenEvent.h"
00003 #include "HepMC/GenVertex.h"
00004 #include "HepMC/GenParticle.h"
00005 
00006 //Framework Headers
00007 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00008 
00009 //CMSSW Data Formats
00010 #include "DataFormats/HepMCCandidate/interface/GenParticle.h"
00011 #include "DataFormats/Candidate/interface/Candidate.h"
00012 
00013 //FAMOS Headers
00014 #include "FastSimulation/Event/interface/FBaseSimEvent.h"
00015 #include "FastSimulation/Event/interface/FSimTrack.h"
00016 #include "FastSimulation/Event/interface/FSimVertex.h"
00017 #include "FastSimulation/Event/interface/KineParticleFilter.h"
00018 #include "FastSimulation/BaseParticlePropagator/interface/BaseParticlePropagator.h"
00019 #include "FastSimulation/Event/interface/BetaFuncPrimaryVertexGenerator.h"
00020 #include "FastSimulation/Event/interface/GaussianPrimaryVertexGenerator.h"
00021 #include "FastSimulation/Event/interface/FlatPrimaryVertexGenerator.h"
00022 #include "FastSimulation/Event/interface/NoPrimaryVertexGenerator.h"
00023 
00024 #include "FastSimDataFormats/NuclearInteractions/interface/FSimVertexType.h"
00025 
00026 using namespace HepPDT;
00027 
00028 // system include
00029 #include <iostream>
00030 #include <iomanip>
00031 #include <map>
00032 #include <string>
00033 
00034 FBaseSimEvent::FBaseSimEvent(const edm::ParameterSet& kine) 
00035   :
00036   nSimTracks(0),
00037   nSimVertices(0),
00038   nGenParticles(0),
00039   nChargedParticleTracks(0),
00040   initialSize(5000),
00041   random(0)
00042 {
00043 
00044   theVertexGenerator = new NoPrimaryVertexGenerator();
00045   theBeamSpot = math::XYZPoint(0.0,0.0,0.0);
00046 
00047   // Initialize the vectors of particles and vertices
00048   theGenParticles = new std::vector<HepMC::GenParticle*>(); 
00049   theSimTracks = new std::vector<FSimTrack>;
00050   theSimVertices = new std::vector<FSimVertex>;
00051   theChargedTracks = new std::vector<unsigned>();
00052   theFSimVerticesType = new FSimVertexTypeCollection();
00053 
00054   // Reserve some size to avoid mutiple copies
00055   /* */
00056   theSimTracks->resize(initialSize);
00057   theSimVertices->resize(initialSize);
00058   theGenParticles->resize(initialSize);
00059   theChargedTracks->resize(initialSize);
00060   theFSimVerticesType->resize(initialSize);
00061   theTrackSize = initialSize;
00062   theVertexSize = initialSize;
00063   theGenSize = initialSize;
00064   theChargedSize = initialSize;
00065   /* */
00066 
00067   // Initialize the Particle filter
00068   myFilter = new KineParticleFilter(kine);
00069 
00070 }
00071 
00072 FBaseSimEvent::FBaseSimEvent(const edm::ParameterSet& vtx,
00073                              const edm::ParameterSet& kine,
00074                              const RandomEngine* engine) 
00075   :
00076   nSimTracks(0),
00077   nSimVertices(0),
00078   nGenParticles(0),
00079   nChargedParticleTracks(0), 
00080   initialSize(5000),
00081   theVertexGenerator(0), 
00082   random(engine)
00083 {
00084 
00085   // Initialize the vertex generator
00086   std::string vtxType = vtx.getParameter<std::string>("type");
00087   if ( vtxType == "Gaussian" ) 
00088     theVertexGenerator = new GaussianPrimaryVertexGenerator(vtx,random);
00089   else if ( vtxType == "Flat" ) 
00090     theVertexGenerator = new FlatPrimaryVertexGenerator(vtx,random);
00091   else if ( vtxType == "BetaFunc" )
00092     theVertexGenerator = new BetaFuncPrimaryVertexGenerator(vtx,random);
00093   else
00094     theVertexGenerator = new NoPrimaryVertexGenerator();
00095   // Initialize the beam spot, if not read from the DataBase
00096   theBeamSpot = math::XYZPoint(0.0,0.0,0.0);
00097 
00098   // Initialize the distance from (0,0,0) after which *generated* particles are 
00099   // no longer considered - because the mother could have interacted before.
00100   // unit : cm x cm
00101   lateVertexPosition = 2.5*2.5;
00102 
00103   // Initialize the vectors of particles and vertices
00104   theGenParticles = new std::vector<HepMC::GenParticle*>(); 
00105   theSimTracks = new std::vector<FSimTrack>;
00106   theSimVertices = new std::vector<FSimVertex>;
00107   theChargedTracks = new std::vector<unsigned>();
00108   theFSimVerticesType = new FSimVertexTypeCollection();
00109 
00110   // Reserve some size to avoid mutiple copies
00111   /* */
00112   theSimTracks->resize(initialSize);
00113   theSimVertices->resize(initialSize);
00114   theGenParticles->resize(initialSize);
00115   theChargedTracks->resize(initialSize);
00116   theFSimVerticesType->resize(initialSize);
00117   theTrackSize = initialSize;
00118   theVertexSize = initialSize;
00119   theGenSize = initialSize;
00120   theChargedSize = initialSize;
00121   /* */
00122 
00123   // Initialize the Particle filter
00124   myFilter = new KineParticleFilter(kine);
00125 
00126 }
00127  
00128 FBaseSimEvent::~FBaseSimEvent(){
00129 
00130   // Clear the vectors
00131   theGenParticles->clear();
00132   theSimTracks->clear();
00133   theSimVertices->clear();
00134   theChargedTracks->clear();
00135   theFSimVerticesType->clear();
00136 
00137   // Delete 
00138   delete theGenParticles;
00139   delete theSimTracks;
00140   delete theSimVertices;
00141   delete theChargedTracks;
00142   delete theFSimVerticesType;
00143   delete myFilter;
00144 
00145 }
00146 
00147 void 
00148 FBaseSimEvent::initializePdt(const HepPDT::ParticleDataTable* aPdt) { 
00149 
00150   pdt = aPdt; 
00151 
00152 }
00153 
00154 /*
00155 const HepPDT::ParticleDataTable*
00156 FBaseSimEvent::theTable() const {
00157   return pdt;
00158 }
00159 */
00160 
00161 void
00162 FBaseSimEvent::fill(const HepMC::GenEvent& myGenEvent) {
00163   
00164   // Clear old vectors
00165   clear();
00166 
00167   // Add the particles in the FSimEvent
00168   addParticles(myGenEvent);
00169 
00170   /*
00171   std::cout << "The MC truth! " << std::endl;
00172   printMCTruth(myGenEvent);
00173 
00174   std::cout << std::endl  << "The FAMOS event! " << std::endl;
00175   print();
00176   */
00177 
00178 }
00179 
00180 void
00181 FBaseSimEvent::fill(const reco::GenParticleCollection& myGenParticles) {
00182   
00183   // Clear old vectors
00184   clear();
00185 
00186   // Add the particles in the FSimEvent
00187   addParticles(myGenParticles);
00188 
00189 }
00190 
00191 void
00192 FBaseSimEvent::fill(const std::vector<SimTrack>& simTracks, 
00193                     const std::vector<SimVertex>& simVertices) {
00194 
00195   // Watch out there ! A SimVertex is in mm (stupid), 
00196   //            while a FSimVertex is in cm (clever).
00197   
00198   clear();
00199 
00200   unsigned nVtx = simVertices.size();
00201   unsigned nTks = simTracks.size();
00202 
00203   // Empty event, do nothin'
00204   if ( nVtx == 0 ) return;
00205 
00206   // Two arrays for internal use.
00207   std::vector<int> myVertices(nVtx,-1);
00208   std::vector<int> myTracks(nTks,-1);
00209 
00210   // create a map associating geant particle id and position in the 
00211   // event SimTrack vector
00212   
00213   std::map<unsigned, unsigned> geantToIndex;
00214   for( unsigned it=0; it<simTracks.size(); ++it ) {
00215     geantToIndex[ simTracks[it].trackId() ] = it;
00216   }  
00217 
00218   // Create also a map associating a SimTrack with its endVertex
00219   /*
00220   std::map<unsigned, unsigned> endVertex;
00221   for ( unsigned iv=0; iv<simVertices.size(); ++iv ) { 
00222     endVertex[ simVertices[iv].parentIndex() ] = iv;
00223   }
00224   */
00225 
00226   // Set the main vertex for the kine particle filter
00227   // SimVertices were in mm until 110_pre2
00228   //  HepLorentzVector primaryVertex = simVertices[0].position()/10.;
00229   // SImVertices are now in cm
00230   // Also : position is copied until SimVertex switches to Mathcore.
00231   //  XYZTLorentzVector primaryVertex = simVertices[0].position();
00232   // The next 5 lines to be then replaced by the previous line
00233   XYZTLorentzVector primaryVertex(simVertices[0].position().x(),
00234                                   simVertices[0].position().y(),
00235                                   simVertices[0].position().z(),
00236                                   simVertices[0].position().t());
00237   //
00238   myFilter->setMainVertex(primaryVertex);
00239   // Add the main vertex to the list.
00240   addSimVertex(myFilter->vertex(), -1, FSimVertexType::PRIMARY_VERTEX);
00241   myVertices[0] = 0;
00242 
00243   for( unsigned trackId=0; trackId<nTks; ++trackId ) {
00244 
00245     // The track
00246     const SimTrack& track = simTracks[trackId];
00247     //    std::cout << std::endl << "SimTrack " << trackId << " " << track << std::endl;
00248 
00249     // The origin vertex
00250     int vertexId = track.vertIndex();
00251     const SimVertex& vertex = simVertices[vertexId];
00252     //std::cout << "Origin vertex " << vertexId << " " << vertex << std::endl;
00253 
00254     // The mother track 
00255     int motherId = -1;
00256     if( !vertex.noParent() ) { // there is a parent to this vertex
00257       // geant id of the mother
00258       unsigned motherGeantId =   vertex.parentIndex(); 
00259       std::map<unsigned, unsigned >::iterator association  
00260         = geantToIndex.find( motherGeantId );
00261       if(association != geantToIndex.end() )
00262         motherId = association->second;
00263     }
00264     int originId = motherId == - 1 ? -1 : myTracks[motherId];
00265     //std::cout << "Origin id " << originId << std::endl;
00266 
00267     /*
00268     if ( endVertex.find(trackId) != endVertex.end() ) 
00269       std::cout << "End vertex id = " << endVertex[trackId] << std::endl;
00270     else
00271       std::cout << "No endVertex !!! " << std::endl;
00272     std::cout << "Tracker surface position " << track.trackerSurfacePosition() << std::endl;
00273     */
00274 
00275     // Add the vertex (if it does not already exist!)
00276     XYZTLorentzVector position(vertex.position().px(),vertex.position().py(),
00277                                vertex.position().pz(),vertex.position().e());
00278     if ( myVertices[vertexId] == -1 ) 
00279       // Momentum and position are copied until SimTrack and SimVertex
00280       // switch to Mathcore.
00281       //      myVertices[vertexId] = addSimVertex(vertex.position(),originId); 
00282       // The next line to be then replaced by the previous line
00283       myVertices[vertexId] = addSimVertex(position,originId); 
00284 
00285     // Add the track (with protection for brem'ing electrons and muons)
00286     int motherType = motherId == -1 ? 0 : simTracks[motherId].type();
00287 
00288     bool notBremInDetector =
00289       (abs(motherType) != 11 && abs(motherType) != 13) ||
00290       motherType != track.type() ||
00291       position.Perp2() < lateVertexPosition ;
00292 
00293     if ( notBremInDetector ) {
00294       // Momentum and position are copied until SimTrack and SimVertex
00295       // switch to Mathcore.
00296       //      RawParticle part(track.momentum(), vertex.position());
00297       // The next 3 lines to be then replaced by the previous line
00298       XYZTLorentzVector momentum(track.momentum().px(),track.momentum().py(),
00299                                  track.momentum().pz(),track.momentum().e());
00300       RawParticle part(momentum,position);
00301       //
00302       part.setID(track.type()); 
00303       //std::cout << "Ctau  = " << part.PDGcTau() << std::endl;
00304       // Don't save tracks that have decayed immediately but for which no daughters
00305       // were saved (probably due to cuts on E, pT and eta)
00306       //  if ( part.PDGcTau() > 0.1 || endVertex.find(trackId) != endVertex.end() ) 
00307       myTracks[trackId] = addSimTrack(&part,myVertices[vertexId],track.genpartIndex());
00308       if ( myTracks[trackId] >= 0 ) { 
00309         (*theSimTracks)[ myTracks[trackId] ].setTkPosition(track.trackerSurfacePosition());
00310         (*theSimTracks)[ myTracks[trackId] ].setTkMomentum(track.trackerSurfaceMomentum());
00311       }
00312     } else {
00313 
00314       myTracks[trackId] = myTracks[motherId];
00315       if ( myTracks[trackId] >= 0 ) { 
00316         (*theSimTracks)[ myTracks[trackId] ].setTkPosition(track.trackerSurfacePosition());
00317         (*theSimTracks)[ myTracks[trackId] ].setTkMomentum(track.trackerSurfaceMomentum());
00318       }
00319     }
00320     
00321   }
00322 
00323   // Now loop over the remaining end vertices !
00324   for( unsigned vertexId=0; vertexId<nVtx; ++vertexId ) {
00325 
00326     // if the vertex is already saved, just ignore.
00327     if ( myVertices[vertexId] != -1 ) continue;
00328 
00329     // The yet unused vertex
00330     const SimVertex& vertex = simVertices[vertexId];
00331 
00332     // The mother track 
00333     int motherId = -1;
00334     if( !vertex.noParent() ) { // there is a parent to this vertex
00335 
00336       // geant id of the mother
00337       unsigned motherGeantId =   vertex.parentIndex(); 
00338       std::map<unsigned, unsigned >::iterator association  
00339         = geantToIndex.find( motherGeantId );
00340       if(association != geantToIndex.end() )
00341         motherId = association->second;
00342     }
00343     int originId = motherId == - 1 ? -1 : myTracks[motherId];
00344 
00345     // Add the vertex
00346     // Momentum and position are copied until SimTrack and SimVertex
00347     // switch to Mathcore.
00348     //    myVertices[vertexId] = addSimVertex(vertex.position(),originId);
00349     // The next 3 lines to be then replaced by the previous line
00350     XYZTLorentzVector position(vertex.position().px(),vertex.position().py(),
00351                                vertex.position().pz(),vertex.position().e());
00352     myVertices[vertexId] = addSimVertex(position,originId); 
00353   }
00354 
00355   // Finally, propagate all particles to the calorimeters
00356   BaseParticlePropagator myPart;
00357   XYZTLorentzVector mom;
00358   XYZTLorentzVector pos;
00359 
00360   // Loop over the tracks
00361   for( int fsimi=0; fsimi < (int)nTracks() ; ++fsimi) {
00362 
00363     
00364     FSimTrack& myTrack = track(fsimi);
00365     double trackerSurfaceTime = myTrack.vertex().position().t() 
00366                               + myTrack.momentum().e()/myTrack.momentum().pz()
00367                               * ( myTrack.trackerSurfacePosition().z()
00368                                 - myTrack.vertex().position().z() );
00369     pos = XYZTLorentzVector(myTrack.trackerSurfacePosition().x(),
00370                             myTrack.trackerSurfacePosition().y(),
00371                             myTrack.trackerSurfacePosition().z(),
00372                                     trackerSurfaceTime);
00373     mom = XYZTLorentzVector(myTrack.trackerSurfaceMomentum().x(),
00374                             myTrack.trackerSurfaceMomentum().y(),
00375                             myTrack.trackerSurfaceMomentum().z(),
00376                             myTrack.trackerSurfaceMomentum().t());
00377 
00378     if ( mom.T() >  0. ) {  
00379       // The particle to be propagated
00380       myPart = BaseParticlePropagator(RawParticle(mom,pos),0.,0.,4.);
00381       myPart.setCharge(myTrack.charge());
00382       
00383       // Propagate to Preshower layer 1
00384       myPart.propagateToPreshowerLayer1(false);
00385       if ( myTrack.notYetToEndVertex(myPart.vertex()) && myPart.getSuccess()>0 )
00386         myTrack.setLayer1(myPart,myPart.getSuccess());
00387       
00388       // Propagate to Preshower Layer 2 
00389       myPart.propagateToPreshowerLayer2(false);
00390       if ( myTrack.notYetToEndVertex(myPart.vertex()) && myPart.getSuccess()>0 )
00391         myTrack.setLayer2(myPart,myPart.getSuccess());
00392       
00393       // Propagate to Ecal Endcap
00394       myPart.propagateToEcalEntrance(false);
00395       if ( myTrack.notYetToEndVertex(myPart.vertex()) )
00396         myTrack.setEcal(myPart,myPart.getSuccess());
00397       
00398       // Propagate to HCAL entrance
00399       myPart.propagateToHcalEntrance(false);
00400       if ( myTrack.notYetToEndVertex(myPart.vertex()) )
00401         myTrack.setHcal(myPart,myPart.getSuccess());
00402       
00403       // Propagate to VFCAL entrance
00404       myPart.propagateToVFcalEntrance(false);
00405       if ( myTrack.notYetToEndVertex(myPart.vertex()) )
00406         myTrack.setVFcal(myPart,myPart.getSuccess());
00407     }
00408  
00409   }
00410 
00411 }
00412 
00413 
00414 void
00415 FBaseSimEvent::addParticles(const HepMC::GenEvent& myGenEvent) {
00416 
00418   int genEventSize = myGenEvent.particles_size();
00419   std::vector<int> myGenVertices(genEventSize, static_cast<int>(0));
00420 
00421   // If no particles, no work to be done !
00422   if ( myGenEvent.particles_empty() ) return;
00423 
00424   // Are there particles in the FSimEvent already ? 
00425   int offset = nGenParts();
00426 
00427   // Primary vertex (already smeared by the SmearedVtx module)
00428   HepMC::GenVertex* primaryVertex = *(myGenEvent.vertices_begin());
00429 
00430   // Beginning of workaround a bug in pythia particle gun
00431   unsigned primaryMother = primaryVertex->particles_in_size();
00432   if ( primaryMother ) {
00433     unsigned partId = (*(primaryVertex->particles_in_const_begin()))->pdg_id();
00434     if ( abs(partId) == 2212 ) primaryMother = 0;
00435   }
00436   // End of workaround a bug in pythia particle gun
00437 
00438   XYZTLorentzVector primaryVertexPosition(primaryVertex->position().x()/10.,
00439                                           primaryVertex->position().y()/10.,
00440                                           primaryVertex->position().z()/10.,
00441                                           primaryVertex->position().t()/10.);
00442   // Actually this is the true end of the workaround
00443   primaryVertexPosition *= (1-primaryMother);
00444   // THE END.
00445 
00446   // Smear the main vertex if needed
00447   // Now takes the origin from the database
00448   XYZTLorentzVector smearedVertex; 
00449   if ( primaryVertexPosition.Vect().Mag2() < 1E-16 ) {
00450     theVertexGenerator->generate();
00451     smearedVertex = XYZTLorentzVector(
00452       theVertexGenerator->X()-theVertexGenerator->beamSpot().X()+theBeamSpot.X(),
00453       theVertexGenerator->Y()-theVertexGenerator->beamSpot().Y()+theBeamSpot.Y(),
00454       theVertexGenerator->Z()-theVertexGenerator->beamSpot().Z()+theBeamSpot.Z(),
00455       0.);
00456   }
00457 
00458   // Set the main vertex
00459   myFilter->setMainVertex(primaryVertexPosition+smearedVertex);
00460 
00461   // This is the smeared main vertex
00462   int mainVertex = addSimVertex(myFilter->vertex(), -1, FSimVertexType::PRIMARY_VERTEX);
00463 
00464   HepMC::GenEvent::particle_const_iterator piter;
00465   HepMC::GenEvent::particle_const_iterator pbegin = myGenEvent.particles_begin();
00466   HepMC::GenEvent::particle_const_iterator pend = myGenEvent.particles_end();
00467 
00468   int initialBarcode = 0; 
00469   if ( pbegin != pend ) initialBarcode = (*pbegin)->barcode();
00470   // Loop on the particles of the generated event
00471   for ( piter = pbegin; piter != pend; ++piter ) {
00472 
00473     // This is the generated particle pointer - for the signal event only
00474     HepMC::GenParticle* p = *piter;
00475 
00476     if  ( !offset ) {
00477       (*theGenParticles)[nGenParticles++] = p;
00478       if ( nGenParticles/theGenSize*theGenSize == nGenParticles ) { 
00479         theGenSize *= 2;
00480         theGenParticles->resize(theGenSize);
00481       }
00482 
00483     }
00484 
00485     // Reject particles with late origin vertex (i.e., coming from late decays)
00486     // This should not happen, but one never knows what users may be up to!
00487     // For example exotic particles might decay late - keep the decay products in the case.
00488     XYZTLorentzVector productionVertexPosition(0.,0.,0.,0.);
00489     HepMC::GenVertex* productionVertex = p->production_vertex();
00490     if ( productionVertex ) { 
00491       unsigned productionMother = productionVertex->particles_in_size();
00492       if ( productionMother ) {
00493         unsigned motherId = (*(productionVertex->particles_in_const_begin()))->pdg_id();
00494         if ( abs(motherId) < 1000000 ) 
00495           productionVertexPosition = 
00496             XYZTLorentzVector(productionVertex->position().x()/10.,
00497                               productionVertex->position().y()/10.,
00498                               productionVertex->position().z()/10.,
00499                               productionVertex->position().t()/10.) + smearedVertex;
00500       }
00501     }
00502     if ( !myFilter->accept(productionVertexPosition) ) continue;
00503 
00504     int abspdgId = abs(p->pdg_id());
00505     HepMC::GenVertex* endVertex = p->end_vertex();
00506 
00507     // Keep only: 
00508     // 1) Stable particles (watch out! New status code = 1001!)
00509     bool testStable = p->status()%1000==1;
00510     // Declare stable standard particles that decay after a macroscopic path length
00511     // (except if exotic)
00512     if ( p->status() == 2 && abspdgId < 1000000) {
00513       if ( endVertex ) { 
00514         XYZTLorentzVector decayPosition = 
00515           XYZTLorentzVector(endVertex->position().x()/10.,
00516                             endVertex->position().y()/10.,
00517                             endVertex->position().z()/10.,
00518                             endVertex->position().t()/10.) + smearedVertex;
00519         // If the particle flew enough to be beyond the beam pipe enveloppe, just declare it stable
00520         if ( decayPosition.Perp2() > lateVertexPosition ) testStable = true;
00521       }
00522     }      
00523 
00524     // 2) or particles with stable daughters (watch out! New status code = 1001!)
00525     bool testDaugh = false;
00526     if ( !testStable && 
00527          p->status() == 2 &&
00528          endVertex && 
00529          endVertex->particles_out_size() ) { 
00530       HepMC::GenVertex::particles_out_const_iterator firstDaughterIt = 
00531         endVertex->particles_out_const_begin();
00532       HepMC::GenVertex::particles_out_const_iterator lastDaughterIt = 
00533         endVertex->particles_out_const_end();
00534       for ( ; firstDaughterIt != lastDaughterIt ; ++firstDaughterIt ) {
00535         HepMC::GenParticle* daugh = *firstDaughterIt;
00536         if ( daugh->status()%1000==1 ) {
00537           // Check that it is not a "prompt electron or muon brem":
00538           if (abspdgId == 11 || abspdgId == 13) {
00539             if ( endVertex ) { 
00540               XYZTLorentzVector endVertexPosition = XYZTLorentzVector(endVertex->position().x()/10.,
00541                                                                       endVertex->position().y()/10.,
00542                                                                       endVertex->position().z()/10.,
00543                                                                       endVertex->position().t()/10.);
00544               // If the particle flew enough to be beyond the beam pipe enveloppe, just declare it stable
00545               if ( endVertexPosition.Perp2() < lateVertexPosition ) {
00546                 break;
00547               }
00548             }
00549           }
00550           testDaugh=true;
00551           break;
00552         }
00553       }
00554     }
00555 
00556     // 3) or particles that fly more than one micron.
00557     double dist = 0.;
00558     if ( !testStable && !testDaugh && p->production_vertex() ) {
00559       XYZTLorentzVector 
00560         productionVertexPosition(p->production_vertex()->position().x()/10.,
00561                                  p->production_vertex()->position().y()/10.,
00562                                  p->production_vertex()->position().z()/10.,
00563                                  p->production_vertex()->position().t()/10.);
00564       dist = (primaryVertexPosition-productionVertexPosition).Vect().Mag2();
00565     }
00566     bool testDecay = ( dist > 1e-8 ) ? true : false; 
00567 
00568     // Save the corresponding particle and vertices
00569     if ( testStable || testDaugh || testDecay ) {
00570       
00571       /*
00572       const HepMC::GenParticle* mother = p->production_vertex() ?
00573         *(p->production_vertex()->particles_in_const_begin()) : 0;
00574       */
00575 
00576       int motherBarcode = p->production_vertex() && 
00577         p->production_vertex()->particles_in_const_begin() !=
00578         p->production_vertex()->particles_in_const_end() ?
00579         (*(p->production_vertex()->particles_in_const_begin()))->barcode() : 0;
00580 
00581       int originVertex = 
00582         motherBarcode && myGenVertices[motherBarcode-initialBarcode] ?
00583         myGenVertices[motherBarcode-initialBarcode] : mainVertex;
00584 
00585       XYZTLorentzVector momentum(p->momentum().px(),
00586                                  p->momentum().py(),
00587                                  p->momentum().pz(),
00588                                  p->momentum().e());
00589       RawParticle part(momentum, vertex(originVertex).position());
00590       part.setID(p->pdg_id());
00591 
00592       // Add the particle to the event and to the various lists
00593       
00594       int theTrack = testStable && p->end_vertex() ? 
00595         // The particle is scheduled to decay
00596         addSimTrack(&part,originVertex, nGenParts()-offset,p->end_vertex()) :
00597         // The particle is not scheduled to decay 
00598         addSimTrack(&part,originVertex, nGenParts()-offset);
00599 
00600       if ( 
00601           // This one deals with particles with no end vertex
00602           !p->end_vertex() ||
00603           // This one deals with particles that have a pre-defined
00604           // decay proper time, but have not decayed yet
00605           ( testStable && p->end_vertex() &&  !p->end_vertex()->particles_out_size() ) 
00606           // In both case, just don't add a end vertex in the FSimEvent 
00607           ) continue; 
00608       
00609       // Add the vertex to the event and to the various lists
00610       XYZTLorentzVector decayVertex = 
00611         XYZTLorentzVector(p->end_vertex()->position().x()/10.,
00612                           p->end_vertex()->position().y()/10.,
00613                           p->end_vertex()->position().z()/10.,
00614                           p->end_vertex()->position().t()/10.) +
00615         smearedVertex;
00616       //        vertex(mainVertex).position();
00617       int theVertex = addSimVertex(decayVertex,theTrack, FSimVertexType::DECAY_VERTEX);
00618 
00619       if ( theVertex != -1 ) myGenVertices[p->barcode()-initialBarcode] = theVertex;
00620 
00621       // There we are !
00622     }
00623   }
00624 
00625 }
00626 
00627 void
00628 FBaseSimEvent::addParticles(const reco::GenParticleCollection& myGenParticles) {
00629 
00630   // If no particles, no work to be done !
00631   unsigned int nParticles = myGenParticles.size();
00632   nGenParticles = nParticles;
00633 
00634   if ( !nParticles ) return;
00635 
00637   std::map<const reco::Candidate*,int> myGenVertices;
00638 
00639   // Are there particles in the FSimEvent already ? 
00640   int offset = nTracks();
00641 
00642   // Skip the incoming protons
00643   nGenParticles = 0;
00644   unsigned int ip = 0;
00645   if ( nParticles > 1 && 
00646        myGenParticles[0].pdgId() == 2212 &&
00647        myGenParticles[1].pdgId() == 2212 ) { 
00648     ip = 2;
00649     nGenParticles = 2;
00650   }
00651 
00652   // Primary vertex (already smeared by the SmearedVtx module)
00653   XYZTLorentzVector primaryVertex (myGenParticles[ip].vx(),
00654                                    myGenParticles[ip].vy(),
00655                                    myGenParticles[ip].vz(),
00656                                    0.);
00657 
00658   // Smear the main vertex if needed
00659   XYZTLorentzVector smearedVertex;
00660   if ( primaryVertex.mag() < 1E-8 ) {
00661     theVertexGenerator->generate();
00662     smearedVertex = XYZTLorentzVector(
00663       theVertexGenerator->X()-theVertexGenerator->beamSpot().X()+theBeamSpot.X(),
00664       theVertexGenerator->Y()-theVertexGenerator->beamSpot().Y()+theBeamSpot.Y(),
00665       theVertexGenerator->Z()-theVertexGenerator->beamSpot().Z()+theBeamSpot.Z(),
00666       0.);
00667   }
00668 
00669   // Set the main vertex
00670   myFilter->setMainVertex(primaryVertex+smearedVertex);
00671 
00672   // This is the smeared main vertex
00673   int mainVertex = addSimVertex(myFilter->vertex(), -1, FSimVertexType::PRIMARY_VERTEX);
00674 
00675   // Loop on the particles of the generated event
00676   for ( ; ip<nParticles; ++ip ) { 
00677     
00678     // nGenParticles = ip;
00679     
00680     nGenParticles++;
00681     const reco::GenParticle& p = myGenParticles[ip];
00682 
00683     // Reject particles with late origin vertex (i.e., coming from late decays)
00684     // This should not happen, but one never knows what users may be up to!
00685     // For example exotic particles might decay late - keep the decay products in the case.
00686     XYZTLorentzVector productionVertexPosition(0.,0.,0.,0.);
00687     const reco::Candidate* productionMother = p.numberOfMothers() ? p.mother(0) : 0;
00688     if ( productionMother ) {
00689       unsigned motherId = productionMother->pdgId();
00690       if ( abs(motherId) < 1000000 )
00691         productionVertexPosition = XYZTLorentzVector(p.vx(), p.vy(), p.vz(), 0.) + smearedVertex;
00692     }
00693     if ( !myFilter->accept(productionVertexPosition) ) continue;
00694 
00695     // Keep only: 
00696     // 1) Stable particles
00697     bool testStable = p.status()%1000==1;
00698     // Declare stable standard particles that decay after a macroscopic path length 
00699     // (except if exotic particle)
00700     if ( p.status() == 2 && abs(p.pdgId()) < 1000000 ) {
00701       unsigned int nDaughters = p.numberOfDaughters();
00702       if ( nDaughters ) { 
00703         const reco::Candidate* daughter = p.daughter(0);
00704         XYZTLorentzVector decayPosition = 
00705           XYZTLorentzVector(daughter->vx(), daughter->vy(), daughter->vz(), 0.) + smearedVertex;
00706         // If the particle flew enough to be beyond the beam pipe enveloppe, just declare it stable
00707         if ( decayPosition.Perp2() > lateVertexPosition ) testStable = true;
00708       }
00709     }
00710 
00711     // 2) or particles with stable daughters
00712     bool testDaugh = false;
00713     unsigned int nDaughters = p.numberOfDaughters();
00714     if ( !testStable  && 
00715          //      p.status() == 2 && 
00716          nDaughters ) {  
00717       for ( unsigned iDaughter=0; iDaughter<nDaughters; ++iDaughter ) {
00718         const reco::Candidate* daughter = p.daughter(iDaughter);
00719         if ( daughter->status()%1000==1 ) {
00720           testDaugh=true;
00721           break;
00722         }
00723       }
00724     }
00725 
00726     // 3) or particles that fly more than one micron.
00727     double dist = 0.;
00728     if ( !testStable && !testDaugh ) {
00729       XYZTLorentzVector productionVertex(p.vx(),p.vy(),p.vz(),0.);
00730       dist = (primaryVertex-productionVertex).Vect().Mag2();
00731     }
00732     bool testDecay = ( dist > 1e-8 ) ? true : false; 
00733 
00734     // Save the corresponding particle and vertices
00735     if ( testStable || testDaugh || testDecay ) {
00736       
00737       const reco::Candidate* mother = p.numberOfMothers() ? p.mother(0) : 0;
00738 
00739       int originVertex = 
00740         mother &&  
00741         myGenVertices.find(mother) != myGenVertices.end() ? 
00742         myGenVertices[mother] : mainVertex;
00743       
00744       XYZTLorentzVector momentum(p.px(),p.py(),p.pz(),p.energy());
00745       RawParticle part(momentum, vertex(originVertex).position());
00746       part.setID(p.pdgId());
00747 
00748       // Add the particle to the event and to the various lists
00749       int theTrack = addSimTrack(&part,originVertex, nGenParts()-offset);
00750 
00751       // It there an end vertex ?
00752       if ( !nDaughters ) continue; 
00753       const reco::Candidate* daughter = p.daughter(0);
00754 
00755       // Add the vertex to the event and to the various lists
00756       XYZTLorentzVector decayVertex = 
00757         XYZTLorentzVector(daughter->vx(), daughter->vy(),
00758                           daughter->vz(), 0.) + smearedVertex;
00759       int theVertex = addSimVertex(decayVertex,theTrack, FSimVertexType::DECAY_VERTEX);
00760 
00761       if ( theVertex != -1 ) myGenVertices[&p] = theVertex;
00762 
00763       // There we are !
00764     }
00765   }
00766 
00767   // There is no GenParticle's in that case...
00768   // nGenParticles=0;
00769 
00770 }
00771 
00772 int 
00773 FBaseSimEvent::addSimTrack(const RawParticle* p, int iv, int ig, 
00774                            const HepMC::GenVertex* ev) { 
00775   
00776   // Check that the particle is in the Famos "acceptance"
00777   // Keep all primaries of pile-up events, though
00778   if ( !myFilter->accept(p) && ig >= -1 ) return -1;
00779 
00780   // The new track index
00781   int trackId = nSimTracks++;
00782   if ( nSimTracks/theTrackSize*theTrackSize == nSimTracks ) {
00783     theTrackSize *= 2;
00784     theSimTracks->resize(theTrackSize);
00785   }
00786 
00787   // Attach the particle to the origin vertex, and to the mother
00788   vertex(iv).addDaughter(trackId);
00789   if ( !vertex(iv).noParent() ) {
00790     track(vertex(iv).parent().id()).addDaughter(trackId);
00791 
00792     if ( ig == -1 ) {
00793       int motherId = track(vertex(iv).parent().id()).genpartIndex();
00794       if ( motherId < -1 ) ig = motherId;
00795     }
00796   }
00797     
00798   // Some transient information for FAMOS internal use
00799   (*theSimTracks)[trackId] = ev ? 
00800     // A proper decay time is scheduled
00801     FSimTrack(p,iv,ig,trackId,this,
00802               ev->position().t()/10.
00803               * p->PDGmass()
00804               / std::sqrt(p->momentum().Vect().Mag2())) : 
00805     // No proper decay time is scheduled
00806     FSimTrack(p,iv,ig,trackId,this);
00807 
00808   return trackId;
00809 
00810 }
00811 
00812 int
00813 FBaseSimEvent::addSimVertex(const XYZTLorentzVector& v, int im, FSimVertexType::VertexType type) {
00814   
00815   // Check that the vertex is in the Famos "acceptance"
00816   if ( !myFilter->accept(v) ) return -1;
00817 
00818   // The number of vertices
00819   int vertexId = nSimVertices++;
00820   if ( nSimVertices/theVertexSize*theVertexSize == nSimVertices ) {
00821     theVertexSize *= 2;
00822     theSimVertices->resize(theVertexSize);
00823     theFSimVerticesType->resize(theVertexSize);
00824   }
00825 
00826   // Attach the end vertex to the particle (if accepted)
00827   if ( im !=-1 ) track(im).setEndVertex(vertexId);
00828 
00829   // Some transient information for FAMOS internal use
00830   (*theSimVertices)[vertexId] = FSimVertex(v,im,vertexId,this);
00831 
00832   (*theFSimVerticesType)[vertexId] = FSimVertexType(type);
00833 
00834   return vertexId;
00835 
00836 }
00837 
00838 void
00839 FBaseSimEvent::printMCTruth(const HepMC::GenEvent& myGenEvent) {
00840   
00841   std::cout << "Id  Gen Name       eta    phi     pT     E    Vtx1   " 
00842             << " x      y      z   " 
00843             << "Moth  Vtx2  eta   phi     R      Z   Da1  Da2 Ecal?" << std::endl;
00844 
00845   for ( HepMC::GenEvent::particle_const_iterator 
00846           piter  = myGenEvent.particles_begin();
00847           piter != myGenEvent.particles_end(); 
00848         ++piter ) {
00849     
00850     HepMC::GenParticle* p = *piter;
00851      /* */
00852     int partId = p->pdg_id();
00853     std::string name;
00854 
00855     if ( pdt->particle(ParticleID(partId)) !=0 ) {
00856       name = (pdt->particle(ParticleID(partId)))->name();
00857     } else {
00858       name = "none";
00859     }
00860   
00861     XYZTLorentzVector momentum1(p->momentum().px(),
00862                                 p->momentum().py(),
00863                                 p->momentum().pz(),
00864                                 p->momentum().e());
00865 
00866     int vertexId1 = 0;
00867 
00868     if ( !p->production_vertex() ) continue;
00869 
00870     XYZVector vertex1 (p->production_vertex()->position().x()/10.,
00871                        p->production_vertex()->position().y()/10.,
00872                        p->production_vertex()->position().z()/10.);
00873     vertexId1 = p->production_vertex()->barcode();
00874     
00875     std::cout.setf(std::ios::fixed, std::ios::floatfield);
00876     std::cout.setf(std::ios::right, std::ios::adjustfield);
00877     
00878     std::cout << std::setw(4) << p->barcode() << " " 
00879          << name;
00880     
00881     for(unsigned int k=0;k<11-name.length() && k<12; k++) std::cout << " ";  
00882     
00883     double eta = momentum1.eta();
00884     if ( eta > +10. ) eta = +10.;
00885     if ( eta < -10. ) eta = -10.;
00886     std::cout << std::setw(6) << std::setprecision(2) << eta << " " 
00887               << std::setw(6) << std::setprecision(2) << momentum1.phi() << " " 
00888               << std::setw(7) << std::setprecision(2) << momentum1.pt() << " " 
00889               << std::setw(7) << std::setprecision(2) << momentum1.e() << " " 
00890               << std::setw(4) << vertexId1 << " " 
00891               << std::setw(6) << std::setprecision(1) << vertex1.x() << " " 
00892               << std::setw(6) << std::setprecision(1) << vertex1.y() << " " 
00893               << std::setw(6) << std::setprecision(1) << vertex1.z() << " ";
00894 
00895     const HepMC::GenParticle* mother = 
00896       *(p->production_vertex()->particles_in_const_begin());
00897 
00898     if ( mother )
00899       std::cout << std::setw(4) << mother->barcode() << " ";
00900     else 
00901       std::cout << "     " ;
00902     
00903     if ( p->end_vertex() ) {  
00904       XYZTLorentzVector vertex2(p->end_vertex()->position().x()/10.,
00905                                 p->end_vertex()->position().y()/10.,
00906                                 p->end_vertex()->position().z()/10.,
00907                                 p->end_vertex()->position().t()/10.);
00908       int vertexId2 = p->end_vertex()->barcode();
00909 
00910       std::vector<const HepMC::GenParticle*> children;
00911       HepMC::GenVertex::particles_out_const_iterator firstDaughterIt = 
00912         p->end_vertex()->particles_out_const_begin();
00913       HepMC::GenVertex::particles_out_const_iterator lastDaughterIt = 
00914         p->end_vertex()->particles_out_const_end();
00915       for ( ; firstDaughterIt != lastDaughterIt ; ++firstDaughterIt ) {
00916         children.push_back(*firstDaughterIt);
00917       }      
00918 
00919       std::cout << std::setw(4) << vertexId2 << " "
00920                 << std::setw(6) << std::setprecision(2) << vertex2.eta() << " " 
00921                 << std::setw(6) << std::setprecision(2) << vertex2.phi() << " " 
00922                 << std::setw(5) << std::setprecision(1) << vertex2.pt() << " " 
00923                 << std::setw(6) << std::setprecision(1) << vertex2.z() << " ";
00924       for ( unsigned id=0; id<children.size(); ++id )
00925         std::cout << std::setw(4) << children[id]->barcode() << " ";
00926     }
00927     std::cout << std::endl;
00928 
00929   }
00930 
00931 }
00932 
00933 void
00934 FBaseSimEvent::print() const {
00935 
00936   std::cout << "  Id  Gen Name       eta    phi     pT     E    Vtx1   " 
00937             << " x      y      z   " 
00938             << "Moth  Vtx2  eta   phi     R      Z   Daughters Ecal?" << std::endl;
00939 
00940   for( int i=0; i<(int)nTracks(); i++ ) 
00941     std::cout << track(i) << std::endl;
00942 
00943   for( int i=0; i<(int)nVertices(); i++ ) 
00944     std::cout << "i = " << i << "  " << vertexType(i) << std::endl;
00945 
00946   
00947 
00948 }
00949 
00950 void 
00951 FBaseSimEvent::clear() {
00952 
00953   nSimTracks = 0;
00954   nSimVertices = 0;
00955   nGenParticles = 0;
00956   nChargedParticleTracks = 0;
00957 
00958 }
00959 
00960 void 
00961 FBaseSimEvent::addChargedTrack(int id) { 
00962   (*theChargedTracks)[nChargedParticleTracks++] = id;
00963   if ( nChargedParticleTracks/theChargedSize*theChargedSize 
00964        == nChargedParticleTracks ) {
00965     theChargedSize *= 2;
00966     theChargedTracks->resize(theChargedSize);
00967   }
00968 }
00969 
00970 int
00971 FBaseSimEvent::chargedTrack(int id) const {
00972   if (id>=0 && id<(int)nChargedParticleTracks) 
00973     return (*theChargedTracks)[id]; 
00974   else 
00975     return -1;
00976 }
00977 
00978 /* 
00979 const SimTrack & 
00980 FBaseSimEvent::embdTrack(int i) const {  
00981   return (*theSimTracks)[i].simTrack();
00982 }
00983 
00984 const SimVertex & 
00985 FBaseSimEvent::embdVertex(int i) const { 
00986   return (*theSimVertices)[i].simVertex();
00987 }
00988 */
00989 
00990 const HepMC::GenParticle* 
00991 FBaseSimEvent::embdGenpart(int i) const {
00992   return (*theGenParticles)[i]; 
00993 }
00994 
00995 /*
00996 FSimTrack&  
00997 FBaseSimEvent::track(int id) const { 
00998   return (*theSimTracks)[id];
00999 }
01000 
01001 
01002 FSimVertex&  
01003 FBaseSimEvent::vertex(int id) const { 
01004   return (*theSimVertices)[id];
01005 }
01006 */