CMS 3D CMS Logo

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 {
00042   edm::LogInfo("SimG4CoreGenerator") << " Generator constructed " ;
00043 
00044   if(fEtaCuts){
00045     Z_lmax = theRDecLenCut*( ( 1 - exp(-2*theMaxEtaCut) ) / ( 2*exp(-theMaxEtaCut) ) );
00046     Z_lmin = theRDecLenCut*( ( 1 - exp(-2*theMinEtaCut) ) / ( 2*exp(-theMinEtaCut) ) );
00047   }
00048 
00049   Z_hector = theRDecLenCut*( ( 1 - exp(-2*theEtaCutForHector) ) / ( 2*exp(-theEtaCutForHector) ) );
00050 
00051   //  std::cout << "Z_min = " << Z_lmin << " Z_max = " << Z_lmax << " Z_hector = " << Z_hector << std::endl;
00052 
00053 }
00054 
00055 Generator::~Generator() 
00056 { 
00057 }
00058 
00059 void Generator::HepMC2G4(const HepMC::GenEvent * evt_orig, G4Event * g4evt)
00060 {
00061 
00062   if ( *(evt_orig->vertices_begin()) == 0 )
00063     {
00064       throw SimG4Exception( "SimG4CoreGenerator: Corrupted Event - GenEvent with no vertex" ) ;
00065     }
00066   
00067   
00068   HepMC::GenEvent* evt = new HepMC::GenEvent(*evt_orig) ;
00069   
00070   if ( evt->weights().size() > 0 )
00071     {
00072       weight_ = evt->weights()[0] ;
00073       for ( int iw=1; iw<evt->weights().size(); iw++ )
00074         {
00075           // terminate if the versot of weights contains a zero-weight
00076           if ( evt->weights()[iw] <= 0 ) break;
00077           weight_ *= evt->weights()[iw] ;
00078         }     
00079     }
00080   
00081   if (vtx_ != 0) delete vtx_;
00082   vtx_ = new math::XYZTLorentzVector((*(evt->vertices_begin()))->position().x(),
00083                                      (*(evt->vertices_begin()))->position().y(),
00084                                      (*(evt->vertices_begin()))->position().z(),
00085                                      (*(evt->vertices_begin()))->position().t());
00086   
00087   if(verbose >0){
00088     evt->print();
00089     cout << " " << endl;
00090     cout << " Prim.Vtx : " << vtx_->x() << " " 
00091          << vtx_->y() << " "
00092          << vtx_->z() << endl;
00093   }
00094   
00095   double x0 = vtx_->x();
00096   double y0 = vtx_->y();
00097   
00098   for(HepMC::GenEvent::vertex_const_iterator vitr= evt->vertices_begin();
00099       vitr != evt->vertices_end(); ++vitr ) { 
00100     // loop for vertex ...
00101     // real vertex?
00102     G4bool qvtx=false;
00103     
00104     for (HepMC::GenVertex::particle_iterator pitr= (*vitr)->particles_begin(HepMC::children);
00105          pitr != (*vitr)->particles_end(HepMC::children); ++pitr) {
00106       // Admit also status=1 && end_vertex for long vertex special decay treatment 
00107       if ((*pitr)->status()==1) {
00108         qvtx=true;
00109         break;
00110       }  
00111       // The selection is made considering if the partcile with status = 2 have the end_vertex
00112       // with a radius (R) greater then the theRDecLenCut that means: the end_vertex is outside
00113       // the beampipe cilinder (no requirement on the Z of the vertex is applyed).
00114       else if ( (*pitr)->status()== 2 ) {
00115         if ( (*pitr)->end_vertex() != 0  ) { 
00116           //double xx = x0-(*pitr)->end_vertex()->position().x();
00117           //double yy = y0-(*pitr)->end_vertex()->position().y();
00118           double xx = (*pitr)->end_vertex()->position().x();
00119           double yy = (*pitr)->end_vertex()->position().y();
00120           double r_dd=std::sqrt(xx*xx+yy*yy);
00121           if (r_dd>theRDecLenCut){
00122             qvtx=true;
00123             break;
00124           }
00125         }
00126       }
00127     }
00128 
00129 
00130     if (!qvtx) {
00131       continue;
00132     }
00133     
00134     double x1 = (*vitr)->position().x();
00135     double y1 = (*vitr)->position().y();
00136     double z1 = (*vitr)->position().z();
00137     double t1 = (*vitr)->position().t();        
00138     G4PrimaryVertex* g4vtx= 
00139       new G4PrimaryVertex(x1*mm, y1*mm, z1*mm, t1*mm/c_light);
00140     
00141     for (HepMC::GenVertex::particle_iterator vpitr= (*vitr)->particles_begin(HepMC::children);
00142          vpitr != (*vitr)->particles_end(HepMC::children); ++vpitr){
00143 
00144       // Special cases:
00145       // 1) import in Geant4 a full decay chain (e.g. also particles with status == 2) 
00146       //    from the generator in case the decay radius is larger than theRDecLenCut
00147       //    In this case no cuts will be applied to select the particles hat has to be 
00148       //    processed by geant
00149       // 2) import in Geant4 particles with status == 1 but a final end vertex. 
00150       //    The time of the vertex is used as the time of flight to be forced for the particle 
00151       
00152       double r_decay_length=-1;
00153       double decay_length=-1;
00154 
00155       if ( (*vpitr)->status() == 1 || (*vpitr)->status() == 2 ) {
00156         // this particle has decayed
00157         if ( (*vpitr)->end_vertex() != 0 ) { 
00158           // needed some particles have status 2 and no end_vertex 
00159           // Which are the particles with status 2 and not end_vertex, what are suppose to di such kind of particles
00160           // when propagated to geant?
00161           
00162           double x2 = (*vpitr)->end_vertex()->position().x();
00163           double y2 = (*vpitr)->end_vertex()->position().y();
00164           double z2 = (*vpitr)->end_vertex()->position().z();
00165           r_decay_length=std::sqrt(x2*x2+y2*y2);
00166           decay_length=std::sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2));
00167 
00168         }
00169       } 
00170       // end modification
00171 
00172       bool toBeAdded = false;
00173       math::XYZTLorentzVector p((*vpitr)->momentum().px(),
00174                                 (*vpitr)->momentum().py(),
00175                                 (*vpitr)->momentum().pz(),
00176                                 (*vpitr)->momentum().e());
00177 
00178       double zimpact = (theRDecLenCut-sqrt(x1*x1+y1*y1))*(1/tan(p.Theta()))+z1;
00179 
00180       // Standard case: particles not decayed by the generator
00181       if( (*vpitr)->status() == 1 && fabs(zimpact) < Z_hector ) {
00182         if ( !particlePassesPrimaryCuts( p, zimpact ) ) {
00183           continue ;
00184         }
00185         toBeAdded = true;
00186       }
00187       
00188       // Decay chain entering exiting the fiducial cylinder defined by theRDecLenCut
00189       else if((*vpitr)->status() == 2 && r_decay_length > theRDecLenCut  && 
00190          fabs(zimpact) < Z_hector ) {
00191         toBeAdded=true;
00192       }
00193       
00194       // Particles trasnported along the beam pipe for forward detectors (HECTOR)
00195       // Always pass to Geant4 without cuts (to be checked)
00196       else if( (*vpitr)->status() == 1 && fabs(zimpact) >= Z_hector && fabs(z1) >= Z_hector) {
00197         toBeAdded = true;
00198       }
00199 
00200       if(toBeAdded){
00201         
00202         G4int pdgcode= (*vpitr)-> pdg_id();
00203         G4PrimaryParticle* g4prim= 
00204           new G4PrimaryParticle(pdgcode, p.Px()*GeV, p.Py()*GeV, p.Pz()*GeV);
00205         
00206         if ( g4prim->GetG4code() != 0 ){ 
00207           g4prim->SetMass( g4prim->GetG4code()->GetPDGMass() ) ;
00208           g4prim->SetCharge( g4prim->GetG4code()->GetPDGCharge() ) ;  
00209         }
00210         
00211         g4prim->SetWeight( 10000*(*vpitr)->barcode() ) ;
00212         setGenId( g4prim, (*vpitr)->barcode() ) ;
00213 
00214         if ( (*vpitr)->status() == 2 ) 
00215           particleAssignDaughters(g4prim,(HepMC::GenParticle *) *vpitr, decay_length);
00216         if ( verbose > 1 ) g4prim->Print();
00217         g4vtx->SetPrimary(g4prim);
00218         // impose also proper time for status=1 and available end_vertex
00219         if ( (*vpitr)->status()==1 && (*vpitr)->end_vertex()!=0) {
00220           double proper_time=decay_length/(p.Beta()*p.Gamma()*c_light);
00221           //LogDebug("SimG4CoreGenerator") <<" beta="<<p.beta()<<" gamma="<<p.gamma()<<" Proper time=" <<proper_time<<" ns" ;
00222           g4prim->SetProperTime(proper_time*ns);
00223         }
00224       }
00225     }
00226 
00227     if (verbose > 1 ) g4vtx->Print();
00228     g4evt->AddPrimaryVertex(g4vtx);
00229 
00230   }
00231   
00232   delete evt ;  
00233   
00234   return ;
00235 }
00236 
00237 void Generator::particleAssignDaughters( G4PrimaryParticle* g4p, HepMC::GenParticle* vp, double decaylength)
00238 {
00239  
00240   if ( !(vp->end_vertex())  ) return ;
00241    
00242   edm::LogInfo("SimG4CoreGenerator") << "Special case of long decay length" ;
00243   edm::LogInfo("SimG4CoreGenerator") << "Assign daughters with to mother with decaylength=" << decaylength << "mm";
00244   math::XYZTLorentzVector p(vp->momentum().px(), vp->momentum().py(), vp->momentum().pz(), vp->momentum().e());
00245   LogDebug("SimG4CoreGenerator") <<" px="<<vp->momentum().px()<<" py="<<vp->momentum().py()<<" pz="<<vp->momentum().pz()<<" e="<<vp->momentum().e();
00246   LogDebug("SimG4CoreGenerator") <<" p.mag2="<<p.mag2()<<" (p.ee)**2="<<p.e()*p.e()<<" ratio:"<<p.mag2()/p.e()/p.e();
00247   LogDebug("SimG4CoreGenerator") <<" mass="<<vp->generatedMass()<<" rho="<<p.P()<<" mag="<<p.mag();
00248   double proper_time=decaylength/(p.Beta()*p.Gamma()*c_light);
00249   LogDebug("SimG4CoreGenerator") <<" beta="<<p.Beta()<<" gamma="<<p.Gamma()<<" Proper time="
00250                                  <<proper_time<<" ns" ;
00251   g4p->SetProperTime(proper_time*ns); // the particle will decay after the same length if it has not interacted before
00252   double x1 = vp->end_vertex()->position().x();
00253   double y1 = vp->end_vertex()->position().y();
00254   double z1 = vp->end_vertex()->position().z();
00255   for (HepMC::GenVertex::particle_iterator 
00256          vpdec= vp->end_vertex()->particles_begin(HepMC::children);
00257        vpdec != vp->end_vertex()->particles_end(HepMC::children); ++vpdec) {
00258     
00259     //transform decay products such that in the rest frame of mother
00260     math::XYZTLorentzVector pdec((*vpdec)->momentum().px(),
00261                                  (*vpdec)->momentum().py(),
00262                                  (*vpdec)->momentum().pz(),
00263                                  (*vpdec)->momentum().e());
00264     // children should only be taken into account once
00265     G4PrimaryParticle * g4daught= 
00266       new G4PrimaryParticle((*vpdec)->pdg_id(), pdec.x()*GeV, pdec.y()*GeV, pdec.z()*GeV);
00267     if ( g4daught->GetG4code() != 0 )
00268       { 
00269         g4daught->SetMass( g4daught->GetG4code()->GetPDGMass() ) ;
00270         g4daught->SetCharge( g4daught->GetG4code()->GetPDGCharge() ) ;  
00271       }
00272     g4daught->SetWeight( 10000*(*vpdec)->barcode() ) ;
00273     setGenId( g4daught, (*vpdec)->barcode() ) ;
00274     edm::LogInfo("SimG4CoreGenerator") <<" Assigning a "<<(*vpdec)->pdg_id()<<" as daughter of a "
00275                                        <<vp->pdg_id() ;
00276     if ( (*vpdec)->status() == 2 && (*vpdec)->end_vertex() != 0 ) 
00277       {
00278         double x2 = (*vpdec)->end_vertex()->position().x();
00279         double y2 = (*vpdec)->end_vertex()->position().y();
00280         double z2 = (*vpdec)->end_vertex()->position().z();
00281         double dd = std::sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2));
00282         particleAssignDaughters(g4daught,*vpdec,dd);
00283       }
00284     (*vpdec)->set_status(1000+(*vpdec)->status()); 
00285     g4p->SetDaughter(g4daught);
00286   }
00287   return;
00288 }
00289 
00290 bool Generator::particlePassesPrimaryCuts( const math::XYZTLorentzVector& mom, const double zimp ) const 
00291 {
00292   
00293   double phi = mom.Phi() ;   
00294   double nrg  = mom.P() ;
00295 
00296   if ( (fEtaCuts) && (zimp < Z_lmin       || zimp > Z_lmax)       ) return false ;
00297   if ( (fPCuts)  && (nrg   < theMinPCut   || nrg  > theMaxPCut)   ) return false ;
00298   if ( (fPhiCuts) && (phi  < theMinPhiCut || phi  > theMaxPhiCut) ) return false ;
00299 
00300   //  std::cout << "Passed p=" << mom.P() << " p_t=" << mom.Pt() << " z_imp=" << zimp << " eta=" << mom.Eta() << " theta=" << mom.Theta() << std::endl;
00301   
00302   return true;   
00303 }
00304 
00305 bool Generator::particlePassesPrimaryCuts(const G4PrimaryParticle * p) const
00306 {
00307 
00308   G4ThreeVector mom = p->GetMomentum();
00309   double        phi = mom.phi() ;
00310   double        nrg  = sqrt(p->GetPx()*p->GetPx() + p->GetPy()*p->GetPy() + p->GetPz()*p->GetPz());
00311   nrg /= GeV ;  // need to convert, since Geant4 operates in MeV
00312   double        eta = -log(tan(mom.theta()/2));
00313 
00314   if ( (fEtaCuts) && (eta < theMinEtaCut || eta > theMaxEtaCut) ) return false ;
00315   if ( (fPCuts)  &&  (nrg  < theMinPCut  || nrg > theMaxPCut)   ) return false ;
00316   if ( (fPhiCuts) && (phi < theMinPhiCut || phi > theMaxPhiCut) ) return false ;
00317 
00318   return true;
00319 
00320 }
00321 
00322 void Generator::nonBeamEvent2G4(const HepMC::GenEvent * evt, G4Event * g4evt)
00323 {
00324   int i = 0; 
00325   for(HepMC::GenEvent::particle_const_iterator it = evt->particles_begin(); 
00326       it != evt->particles_end(); ++it )
00327     {
00328       i++;
00329       HepMC::GenParticle * g = (*it);   
00330       int g_status = g->status();
00331       // storing only particle with status == 1         
00332       if (g_status == 1)
00333         {
00334           int g_id = g->pdg_id();           
00335           G4PrimaryParticle * g4p = 
00336             new G4PrimaryParticle(g_id,g->momentum().px()*GeV,g->momentum().py()*GeV,g->momentum().pz()*GeV);
00337           if (g4p->GetG4code() != 0)
00338             { 
00339               g4p->SetMass(g4p->GetG4code()->GetPDGMass());
00340               g4p->SetCharge(g4p->GetG4code()->GetPDGCharge()) ;
00341             }
00342           g4p->SetWeight(i*10000);
00343           setGenId(g4p,i);
00344           if (particlePassesPrimaryCuts(g4p))
00345             {
00346               G4PrimaryVertex * v = new 
00347                 G4PrimaryVertex(g->production_vertex()->position().x()*mm,           
00348                                 g->production_vertex()->position().y()*mm,           
00349                                 g->production_vertex()->position().z()*mm,           
00350                                 g->production_vertex()->position().t()*mm/c_light);
00351               v->SetPrimary(g4p);
00352               g4evt->AddPrimaryVertex(v);
00353             }
00354         }
00355     } // end loop on HepMC particles
00356 }

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