00001
00002 #include "SimG4Core/Generators/interface/Generator.h"
00003 #include "SimG4Core/Generators/interface/HepMCParticle.h"
00004
00005
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")),
00027 theMaxPhiCut(p.getParameter<double>("MaxPhiCut")),
00028 theMinEtaCut(p.getParameter<double>("MinEtaCut")),
00029 theMaxEtaCut(p.getParameter<double>("MaxEtaCut")),
00030 theMinPCut(p.getParameter<double>("MinPCut")),
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
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
00110
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
00117
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
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
00130
00131
00132 else if ( (*pitr)->status()== 2 ) {
00133 if ( (*pitr)->end_vertex() != 0 ) {
00134
00135
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
00165
00166
00167
00168
00169
00170
00171
00172 double r_decay_length=-1;
00173 double decay_length=-1;
00174
00175 if ( (*vpitr)->status() == 1 || (*vpitr)->status() == 2 ) {
00176
00177 if ( (*vpitr)->end_vertex() != 0 ) {
00178
00179
00180
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
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
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
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
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
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
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
00240
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
00258
00259
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
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
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);
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
00325 math::XYZTLorentzVector pdec((*vpdec)->momentum().px(),
00326 (*vpdec)->momentum().py(),
00327 (*vpdec)->momentum().pz(),
00328 (*vpdec)->momentum().e());
00329
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
00338
00339
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 ;
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
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
00422
00423
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 }
00440 }