CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/src/SimG4Core/Generators/src/Generator.cc

Go to the documentation of this file.
00001 
00002 #include "SimG4Core/Generators/interface/Generator.h"
00003 #include "SimG4Core/Generators/interface/HepMCParticle.h"
00004 
00005 // #include "FWCore/Utilities/interface/Exception.h"
00006 #include "SimG4Core/Notification/interface/SimG4Exception.h"
00007 
00008 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00009 
00010 #include "G4Event.hh"
00011 #include "G4EventManager.hh"
00012 #include "G4HEPEvtParticle.hh"
00013 #include "G4ParticleDefinition.hh"
00014 #include "G4UnitsTable.hh"
00015 
00016 using namespace edm;
00017 using std::cout;
00018 using std::endl;
00019 using std::string;
00020 
00021 
00022 Generator::Generator(const ParameterSet & p) : 
00023   fPCuts(p.getParameter<bool>("ApplyPCuts")),
00024   fEtaCuts(p.getParameter<bool>("ApplyEtaCuts")), 
00025   fPhiCuts(p.getParameter<bool>("ApplyPhiCuts")),
00026   theMinPhiCut(p.getParameter<double>("MinPhiCut")),   // now operates in radians (CMS standard)
00027   theMaxPhiCut(p.getParameter<double>("MaxPhiCut")),
00028   theMinEtaCut(p.getParameter<double>("MinEtaCut")),
00029   theMaxEtaCut(p.getParameter<double>("MaxEtaCut")),
00030   theMinPCut(p.getParameter<double>("MinPCut")),    // now operates in GeV (CMS standard)
00031   theMaxPCut(p.getParameter<double>("MaxPCut")),   
00032   theRDecLenCut(p.getParameter<double>("RDecLenCut")*cm),
00033   theEtaCutForHector(p.getParameter<double>("EtaCutForHector")),
00034   verbose(p.getUntrackedParameter<int>("Verbosity",0)),
00035   evt_(0),
00036   vtx_(0),
00037   weight_(0),
00038   Z_lmin(0),
00039   Z_lmax(0),
00040   Z_hector(0),
00041   pdgFilterSel(false) 
00042 {
00043 
00044   pdgFilter.resize(0);
00045   if ( p.exists("PDGselection") ) {
00046 
00047     pdgFilterSel = (p.getParameter<edm::ParameterSet>("PDGselection")).getParameter<bool>("PDGfilterSel");
00048     pdgFilter = (p.getParameter<edm::ParameterSet>("PDGselection")).getParameter<std::vector< int > >("PDGfilter");
00049     for ( unsigned int ii = 0; ii < pdgFilter.size() ; ii++ ) {
00050       if (pdgFilterSel) {
00051         edm::LogWarning("SimG4CoreGenerator") << " *** Selecting only PDG ID = " << pdgFilter[ii];
00052       } else {
00053         edm::LogWarning("SimG4CoreGenerator") << " *** Filtering out PDG ID = " << pdgFilter[ii];
00054       }
00055     }
00056   
00057   }
00058 
00059   if(fEtaCuts){
00060     Z_lmax = theRDecLenCut*( ( 1 - exp(-2*theMaxEtaCut) ) / ( 2*exp(-theMaxEtaCut) ) );
00061     Z_lmin = theRDecLenCut*( ( 1 - exp(-2*theMinEtaCut) ) / ( 2*exp(-theMinEtaCut) ) );
00062   }
00063 
00064   Z_hector = theRDecLenCut*( ( 1 - exp(-2*theEtaCutForHector) ) / ( 2*exp(-theEtaCutForHector) ) );
00065 
00066   if ( verbose > 0 ) LogDebug("SimG4CoreGenerator") << "Z_min = " << Z_lmin << " Z_max = " << Z_lmax << " Z_hector = " << Z_hector;
00067 
00068 }
00069 
00070 Generator::~Generator() 
00071 { 
00072 }
00073 
00074 void Generator::HepMC2G4(const HepMC::GenEvent * evt_orig, G4Event * g4evt)
00075 {
00076 
00077   if ( *(evt_orig->vertices_begin()) == 0 )
00078     {
00079       throw SimG4Exception( "SimG4CoreGenerator: Corrupted Event - GenEvent with no vertex" ) ;
00080     }
00081   
00082   
00083   HepMC::GenEvent* evt = new HepMC::GenEvent(*evt_orig) ;
00084   
00085   if ( evt->weights().size() > 0 )
00086     {
00087       weight_ = evt->weights()[0] ;
00088       for ( unsigned int iw=1; iw<evt->weights().size(); iw++ )
00089         {
00090           // terminate if the versot of weights contains a zero-weight
00091           if ( evt->weights()[iw] <= 0 ) break;
00092           weight_ *= evt->weights()[iw] ;
00093         }     
00094     }
00095   
00096   if (vtx_ != 0) delete vtx_;
00097   vtx_ = new math::XYZTLorentzVector((*(evt->vertices_begin()))->position().x(),
00098                                      (*(evt->vertices_begin()))->position().y(),
00099                                      (*(evt->vertices_begin()))->position().z(),
00100                                      (*(evt->vertices_begin()))->position().t());
00101   
00102   if(verbose >0){
00103     evt->print();
00104     LogDebug("SimG4CoreGenerator") << "Primary Vertex = (" << vtx_->x() << "," 
00105                                    << vtx_->y() << ","
00106                                    << vtx_->z() << ")";
00107   }
00108   
00109   //  double x0 = vtx_->x();
00110   //  double y0 = vtx_->y();
00111   
00112   unsigned int ng4vtx = 0;
00113 
00114   for(HepMC::GenEvent::vertex_const_iterator vitr= evt->vertices_begin();
00115       vitr != evt->vertices_end(); ++vitr ) { 
00116     // loop for vertex ...
00117     // real vertex?
00118     G4bool qvtx=false;
00119     
00120     for (HepMC::GenVertex::particle_iterator pitr= (*vitr)->particles_begin(HepMC::children);
00121          pitr != (*vitr)->particles_end(HepMC::children); ++pitr) {
00122       // Admit also status=1 && end_vertex for long vertex special decay treatment 
00123       if ((*pitr)->status()==1) {
00124         qvtx=true;
00125         if ( verbose > 2 ) LogDebug("SimG4CoreGenerator") << "GenVertex barcode = " << (*vitr)->barcode() 
00126                                                           << " selected for GenParticle barcode = " << (*pitr)->barcode() << std::endl;
00127         break;
00128       }  
00129       // The selection is made considering if the partcile with status = 2 have the end_vertex
00130       // with a radius (R) greater then the theRDecLenCut that means: the end_vertex is outside
00131       // the beampipe cilinder (no requirement on the Z of the vertex is applyed).
00132       else if ( (*pitr)->status()== 2 ) {
00133         if ( (*pitr)->end_vertex() != 0  ) { 
00134           //double xx = x0-(*pitr)->end_vertex()->position().x();
00135           //double yy = y0-(*pitr)->end_vertex()->position().y();
00136           double xx = (*pitr)->end_vertex()->position().x();
00137           double yy = (*pitr)->end_vertex()->position().y();
00138           double r_dd=std::sqrt(xx*xx+yy*yy);
00139           if (r_dd>theRDecLenCut){
00140             qvtx=true;
00141             if ( verbose > 2 ) LogDebug("SimG4CoreGenerator") << "GenVertex barcode = " << (*vitr)->barcode() 
00142                                          << " selected for GenParticle barcode = " << (*pitr)->barcode() << " radius = " << r_dd << std::endl;
00143             break;
00144           }
00145         }
00146       }
00147     }
00148 
00149 
00150     if (!qvtx) {
00151       continue;
00152     }
00153     
00154     double x1 = (*vitr)->position().x();
00155     double y1 = (*vitr)->position().y();
00156     double z1 = (*vitr)->position().z();
00157     double t1 = (*vitr)->position().t();        
00158     G4PrimaryVertex* g4vtx= 
00159       new G4PrimaryVertex(x1*mm, y1*mm, z1*mm, t1*mm/c_light);
00160     
00161     for (HepMC::GenVertex::particle_iterator vpitr= (*vitr)->particles_begin(HepMC::children);
00162          vpitr != (*vitr)->particles_end(HepMC::children); ++vpitr){
00163 
00164       // Special cases:
00165       // 1) import in Geant4 a full decay chain (e.g. also particles with status == 2) 
00166       //    from the generator in case the decay radius is larger than theRDecLenCut
00167       //    In this case no cuts will be applied to select the particles hat has to be 
00168       //    processed by geant
00169       // 2) import in Geant4 particles with status == 1 but a final end vertex. 
00170       //    The time of the vertex is used as the time of flight to be forced for the particle 
00171       
00172       double r_decay_length=-1;
00173       double decay_length=-1;
00174 
00175       if ( (*vpitr)->status() == 1 || (*vpitr)->status() == 2 ) {
00176         // this particle has decayed
00177         if ( (*vpitr)->end_vertex() != 0 ) { 
00178           // needed some particles have status 2 and no end_vertex 
00179           // Which are the particles with status 2 and not end_vertex, what are suppose to di such kind of particles
00180           // when propagated to geant?
00181           
00182           double x2 = (*vpitr)->end_vertex()->position().x();
00183           double y2 = (*vpitr)->end_vertex()->position().y();
00184           double z2 = (*vpitr)->end_vertex()->position().z();
00185           r_decay_length=std::sqrt(x2*x2+y2*y2);
00186           decay_length=std::sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2));
00187 
00188         }
00189       } 
00190       // end modification
00191 
00192       bool toBeAdded = false;
00193       math::XYZTLorentzVector p((*vpitr)->momentum().px(),
00194                                 (*vpitr)->momentum().py(),
00195                                 (*vpitr)->momentum().pz(),
00196                                 (*vpitr)->momentum().e());
00197 
00198       // protection against numerical problems for extremely low momenta
00199       const double minTan = 1.e-20;
00200       double zimpact = Z_hector+1.;
00201       if ( fabs(z1) < Z_hector && fabs(p.pt()/p.pz()) >= minTan ) { 
00202         // write tan(p.Theta()) as p.Pt()/p.Pz()
00203         zimpact = (theRDecLenCut-sqrt(x1*x1+y1*y1))*(p.pz()/p.pt())+z1;
00204       }
00205       
00206       if ( verbose > 2 ) LogDebug("SimG4CoreGenerator") << "Processing GenParticle barcode = " << (*vpitr)->barcode() 
00207                                                         << " status = " << (*vpitr)->status() 
00208                                                         << " zimpact = " << zimpact;
00209       
00210       // Filter on allowed particle species if required
00211       
00212       if ( pdgFilter.size() > 0 ) {
00213         std::vector<int>::iterator it = find(pdgFilter.begin(),pdgFilter.end(),(*vpitr)->pdg_id()); 
00214         if ( (it != pdgFilter.end() && !pdgFilterSel) || ( it == pdgFilter.end() && pdgFilterSel ) ) {
00215           toBeAdded = false;         
00216           if ( verbose > 2 ) LogDebug("SimG4CoreGenerator") << "Skip GenParticle barcode = " << (*vpitr)->barcode() 
00217                                                             << " PDG Id = " << (*vpitr)->pdg_id() << std::endl;
00218           continue;
00219         }
00220       }
00221       
00222       
00223       // Standard case: particles not decayed by the generator
00224       if( (*vpitr)->status() == 1 && fabs(zimpact) < Z_hector ) {
00225         if ( !particlePassesPrimaryCuts( p, zimpact ) ) {
00226           continue ;
00227         }
00228         toBeAdded = true;
00229         if ( verbose > 2 ) LogDebug("SimG4CoreGenerator") << "GenParticle barcode = " << (*vpitr)->barcode() << " passed case 1" << std::endl;
00230       }
00231       
00232       // Decay chain entering exiting the fiducial cylinder defined by theRDecLenCut
00233       else if((*vpitr)->status() == 2 && r_decay_length > theRDecLenCut  && 
00234          fabs(zimpact) < Z_hector ) {
00235         toBeAdded=true;
00236         if ( verbose > 2 ) LogDebug("SimG4CoreGenerator") << "GenParticle barcode = " << (*vpitr)->barcode() << " passed case 2" << std::endl;
00237       }
00238       
00239       // Particles trasnported along the beam pipe for forward detectors (HECTOR)
00240       // Always pass to Geant4 without cuts (to be checked)
00241       else if( (*vpitr)->status() == 1 && fabs(zimpact) >= Z_hector && fabs(z1) >= Z_hector) {
00242         toBeAdded = true;
00243         if ( verbose > 2 ) LogDebug("SimG4CoreGenerator") << "GenParticle barcode = " << (*vpitr)->barcode() << " passed case 3" << std::endl;
00244       }
00245 
00246       if(toBeAdded){
00247         
00248         G4int pdgcode= (*vpitr)-> pdg_id();
00249         G4PrimaryParticle* g4prim= 
00250           new G4PrimaryParticle(pdgcode, p.Px()*GeV, p.Py()*GeV, p.Pz()*GeV);
00251         
00252         if ( g4prim->GetG4code() != 0 ){ 
00253           g4prim->SetMass( g4prim->GetG4code()->GetPDGMass() ) ;
00254           g4prim->SetCharge( g4prim->GetG4code()->GetPDGCharge() ) ;  
00255         }
00256 
00257         // V.I. do not use SetWeight but the same code
00258         // value of the code compute inside TrackWithHistory        
00259         //g4prim->SetWeight( 10000*(*vpitr)->barcode() ) ;
00260         setGenId( g4prim, (*vpitr)->barcode() ) ;
00261 
00262         if ( (*vpitr)->status() == 2 ) 
00263           particleAssignDaughters(g4prim,(HepMC::GenParticle *) *vpitr, decay_length);
00264         if ( verbose > 1 ) g4prim->Print();
00265         g4vtx->SetPrimary(g4prim);
00266         // impose also proper time for status=1 and available end_vertex
00267         if ( (*vpitr)->status()==1 && (*vpitr)->end_vertex()!=0) {
00268           double proper_time=decay_length/(p.Beta()*p.Gamma()*c_light);
00269           if ( verbose > 1 ) LogDebug("SimG4CoreGenerator") <<"Setting proper time for beta="<<p.Beta()<<" gamma="<<p.Gamma()<<" Proper time=" <<proper_time<<" ns" ;
00270           g4prim->SetProperTime(proper_time*ns);
00271         }
00272       }
00273     }
00274 
00275     if (verbose > 1 ) g4vtx->Print();
00276     g4evt->AddPrimaryVertex(g4vtx);
00277     ng4vtx++;
00278   }
00279   
00280   // Add a protection for completely empty events (produced by LHCTransport): add a dummy vertex with no particle attached to it
00281   if ( ng4vtx == 0 ) {
00282     double x1 = 0.;
00283     double y1 = 0.;
00284     double z1 = 0.;
00285     double t1 = 0.;
00286     G4PrimaryVertex* g4vtx= 
00287       new G4PrimaryVertex(x1*mm, y1*mm, z1*mm, t1*mm/c_light);
00288     if (verbose > 1 ) g4vtx->Print();
00289     g4evt->AddPrimaryVertex(g4vtx);
00290   }
00291   
00292   delete evt ;  
00293   
00294   return ;
00295 }
00296 
00297 void Generator::particleAssignDaughters( G4PrimaryParticle* g4p, HepMC::GenParticle* vp, double decaylength)
00298 {
00299  
00300   if ( !(vp->end_vertex())  ) return ;
00301    
00302   if ( verbose > 1 ) 
00303     LogDebug("SimG4CoreGenerator") << "Special case of long decay length \n" 
00304                                    << "Assign daughters with to mother with decaylength=" << decaylength << "mm";
00305   math::XYZTLorentzVector p(vp->momentum().px(), vp->momentum().py(), vp->momentum().pz(), vp->momentum().e());
00306   double proper_time=decaylength/(p.Beta()*p.Gamma()*c_light);
00307   if ( verbose > 2 ) {
00308     LogDebug("SimG4CoreGenerator") <<" px="<<vp->momentum().px()
00309                                    <<" py="<<vp->momentum().py()
00310                                    <<" pz="<<vp->momentum().pz()
00311                                    <<" e="<<vp->momentum().e()
00312                                    <<" beta="<<p.Beta()
00313                                    <<" gamma="<<p.Gamma()
00314                                    <<" Proper time=" <<proper_time<<" ns" ;
00315   }
00316   g4p->SetProperTime(proper_time*ns); // the particle will decay after the same length if it has not interacted before
00317   double x1 = vp->end_vertex()->position().x();
00318   double y1 = vp->end_vertex()->position().y();
00319   double z1 = vp->end_vertex()->position().z();
00320   for (HepMC::GenVertex::particle_iterator 
00321          vpdec= vp->end_vertex()->particles_begin(HepMC::children);
00322        vpdec != vp->end_vertex()->particles_end(HepMC::children); ++vpdec) {
00323     
00324     //transform decay products such that in the rest frame of mother
00325     math::XYZTLorentzVector pdec((*vpdec)->momentum().px(),
00326                                  (*vpdec)->momentum().py(),
00327                                  (*vpdec)->momentum().pz(),
00328                                  (*vpdec)->momentum().e());
00329     // children should only be taken into account once
00330     G4PrimaryParticle * g4daught= 
00331       new G4PrimaryParticle((*vpdec)->pdg_id(), pdec.x()*GeV, pdec.y()*GeV, pdec.z()*GeV);
00332     if ( g4daught->GetG4code() != 0 )
00333       { 
00334         g4daught->SetMass( g4daught->GetG4code()->GetPDGMass() ) ;
00335         g4daught->SetCharge( g4daught->GetG4code()->GetPDGCharge() ) ;  
00336       }
00337     // V.I. do not use SetWeight but the same code
00338     // value of the code compute inside TrackWithHistory        
00339     //g4daught->SetWeight( 10000*(*vpdec)->barcode() ) ;
00340     setGenId( g4daught, (*vpdec)->barcode() ) ;
00341     if ( verbose > 1 ) LogDebug("SimG4CoreGenerator") <<"Assigning a "<<(*vpdec)->pdg_id()
00342                                                       <<" as daughter of a " <<vp->pdg_id() ;
00343     if ( (*vpdec)->status() == 2 && (*vpdec)->end_vertex() != 0 ) 
00344       {
00345         double x2 = (*vpdec)->end_vertex()->position().x();
00346         double y2 = (*vpdec)->end_vertex()->position().y();
00347         double z2 = (*vpdec)->end_vertex()->position().z();
00348         double dd = std::sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2));
00349         particleAssignDaughters(g4daught,*vpdec,dd);
00350       }
00351     (*vpdec)->set_status(1000+(*vpdec)->status()); 
00352     g4p->SetDaughter(g4daught);
00353   }
00354   return;
00355 }
00356 
00357 bool Generator::particlePassesPrimaryCuts( const math::XYZTLorentzVector& mom, const double zimp ) const 
00358 {
00359   
00360   double phi = mom.Phi() ;   
00361   double nrg  = mom.P() ;
00362   bool   flag = true;
00363 
00364   if ( (fEtaCuts) && (zimp < Z_lmin       || zimp > Z_lmax)      ) {
00365     flag = false;
00366   } else if ( (fPCuts)  && (nrg   < theMinPCut   || nrg  > theMaxPCut) ) {
00367     flag = false;
00368   } else if ( (fPhiCuts) && (phi  < theMinPhiCut || phi  > theMaxPhiCut) ) {
00369     flag = false;
00370   }
00371 
00372   if ( verbose > 2 ) LogDebug("SimG4CoreGenerator") << "Generator p = " << nrg << " z_imp = " << zimp << " phi = " << mom.Phi() << " Flag = " << flag;
00373   
00374   return flag;
00375 }
00376 
00377 bool Generator::particlePassesPrimaryCuts(const G4PrimaryParticle * p) const 
00378 {
00379 
00380   G4ThreeVector mom = p->GetMomentum();
00381   double        phi = mom.phi() ;
00382   double        nrg  = sqrt(p->GetPx()*p->GetPx() + p->GetPy()*p->GetPy() + p->GetPz()*p->GetPz());
00383   nrg /= GeV ;  // need to convert, since Geant4 operates in MeV
00384   double        eta = -log(tan(mom.theta()/2));
00385   bool   flag = true;
00386 
00387   if ( (fEtaCuts) && (eta < theMinEtaCut || eta > theMaxEtaCut) ) {
00388     flag = false;
00389   } else if ( (fPCuts)  &&  (nrg  < theMinPCut  || nrg > theMaxPCut)   ) {
00390     flag = false;
00391   } else if ( (fPhiCuts) && (phi < theMinPhiCut || phi > theMaxPhiCut) ) {
00392     flag = false;
00393   }
00394   
00395   if ( verbose > 2 ) LogDebug("SimG4CoreGenerator") << "Generator p = " << nrg  << " eta = " << eta << " theta = " << mom.theta() << " phi = " << phi << " Flag = " << flag;
00396 
00397   return flag;
00398 
00399 }
00400 
00401 void Generator::nonBeamEvent2G4(const HepMC::GenEvent * evt, G4Event * g4evt) 
00402 {
00403   int i = 0; 
00404   for(HepMC::GenEvent::particle_const_iterator it = evt->particles_begin(); 
00405       it != evt->particles_end(); ++it ) 
00406     {
00407       i++;
00408       HepMC::GenParticle * g = (*it);   
00409       int g_status = g->status();
00410       // storing only particle with status == 1         
00411       if (g_status == 1) 
00412         {
00413           int g_id = g->pdg_id();           
00414           G4PrimaryParticle * g4p = 
00415             new G4PrimaryParticle(g_id,g->momentum().px()*GeV,g->momentum().py()*GeV,g->momentum().pz()*GeV);
00416           if (g4p->GetG4code() != 0) 
00417             { 
00418               g4p->SetMass(g4p->GetG4code()->GetPDGMass());
00419               g4p->SetCharge(g4p->GetG4code()->GetPDGCharge()) ;
00420             }
00421           // V.I. do not use SetWeight but the same code
00422           // value of the code compute inside TrackWithHistory        
00423           //g4p->SetWeight(i*10000);
00424           setGenId(g4p,i);
00425           if (particlePassesPrimaryCuts(g4p)) 
00426             {
00427               G4PrimaryVertex * v = new 
00428                 G4PrimaryVertex(g->production_vertex()->position().x()*mm,
00429                                 g->production_vertex()->position().y()*mm,
00430                                 g->production_vertex()->position().z()*mm,
00431                                 g->production_vertex()->position().t()*mm/c_light);
00432               v->SetPrimary(g4p);
00433               g4evt->AddPrimaryVertex(v);
00434               if(verbose >0) {
00435                 v->Print();
00436               }
00437             }
00438         }
00439     } // end loop on HepMC particles
00440 }