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 {
00042
00043 if(fEtaCuts){
00044 Z_lmax = theRDecLenCut*( ( 1 - exp(-2*theMaxEtaCut) ) / ( 2*exp(-theMaxEtaCut) ) );
00045 Z_lmin = theRDecLenCut*( ( 1 - exp(-2*theMinEtaCut) ) / ( 2*exp(-theMinEtaCut) ) );
00046 }
00047
00048 Z_hector = theRDecLenCut*( ( 1 - exp(-2*theEtaCutForHector) ) / ( 2*exp(-theEtaCutForHector) ) );
00049
00050 if ( verbose > 0 ) LogDebug("SimG4CoreGenerator") << "Z_min = " << Z_lmin << " Z_max = " << Z_lmax << " Z_hector = " << Z_hector;
00051
00052 }
00053
00054 Generator::~Generator()
00055 {
00056 }
00057
00058 void Generator::HepMC2G4(const HepMC::GenEvent * evt_orig, G4Event * g4evt)
00059 {
00060
00061 if ( *(evt_orig->vertices_begin()) == 0 )
00062 {
00063 throw SimG4Exception( "SimG4CoreGenerator: Corrupted Event - GenEvent with no vertex" ) ;
00064 }
00065
00066
00067 HepMC::GenEvent* evt = new HepMC::GenEvent(*evt_orig) ;
00068
00069 if ( evt->weights().size() > 0 )
00070 {
00071 weight_ = evt->weights()[0] ;
00072 for ( unsigned int iw=1; iw<evt->weights().size(); iw++ )
00073 {
00074
00075 if ( evt->weights()[iw] <= 0 ) break;
00076 weight_ *= evt->weights()[iw] ;
00077 }
00078 }
00079
00080 if (vtx_ != 0) delete vtx_;
00081 vtx_ = new math::XYZTLorentzVector((*(evt->vertices_begin()))->position().x(),
00082 (*(evt->vertices_begin()))->position().y(),
00083 (*(evt->vertices_begin()))->position().z(),
00084 (*(evt->vertices_begin()))->position().t());
00085
00086 if(verbose >0){
00087 evt->print();
00088 LogDebug("SimG4CoreGenerator") << "Primary Vertex = (" << vtx_->x() << ","
00089 << vtx_->y() << ","
00090 << vtx_->z() << ")";
00091 }
00092
00093
00094
00095
00096 unsigned int ng4vtx = 0;
00097
00098 for(HepMC::GenEvent::vertex_const_iterator vitr= evt->vertices_begin();
00099 vitr != evt->vertices_end(); ++vitr ) {
00100
00101
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
00107 if ((*pitr)->status()==1) {
00108 qvtx=true;
00109 if ( verbose > 2 ) LogDebug("SimG4CoreGenerator") << "GenVertex barcode = " << (*vitr)->barcode()
00110 << " selected for GenParticle barcode = " << (*pitr)->barcode() << std::endl;
00111 break;
00112 }
00113
00114
00115
00116 else if ( (*pitr)->status()== 2 ) {
00117 if ( (*pitr)->end_vertex() != 0 ) {
00118
00119
00120 double xx = (*pitr)->end_vertex()->position().x();
00121 double yy = (*pitr)->end_vertex()->position().y();
00122 double r_dd=std::sqrt(xx*xx+yy*yy);
00123 if (r_dd>theRDecLenCut){
00124 qvtx=true;
00125 if ( verbose > 2 ) LogDebug("SimG4CoreGenerator") << "GenVertex barcode = " << (*vitr)->barcode()
00126 << " selected for GenParticle barcode = " << (*pitr)->barcode() << " radius = " << r_dd << std::endl;
00127 break;
00128 }
00129 }
00130 }
00131 }
00132
00133
00134 if (!qvtx) {
00135 continue;
00136 }
00137
00138 double x1 = (*vitr)->position().x();
00139 double y1 = (*vitr)->position().y();
00140 double z1 = (*vitr)->position().z();
00141 double t1 = (*vitr)->position().t();
00142 G4PrimaryVertex* g4vtx=
00143 new G4PrimaryVertex(x1*mm, y1*mm, z1*mm, t1*mm/c_light);
00144
00145 for (HepMC::GenVertex::particle_iterator vpitr= (*vitr)->particles_begin(HepMC::children);
00146 vpitr != (*vitr)->particles_end(HepMC::children); ++vpitr){
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156 double r_decay_length=-1;
00157 double decay_length=-1;
00158
00159 if ( (*vpitr)->status() == 1 || (*vpitr)->status() == 2 ) {
00160
00161 if ( (*vpitr)->end_vertex() != 0 ) {
00162
00163
00164
00165
00166 double x2 = (*vpitr)->end_vertex()->position().x();
00167 double y2 = (*vpitr)->end_vertex()->position().y();
00168 double z2 = (*vpitr)->end_vertex()->position().z();
00169 r_decay_length=std::sqrt(x2*x2+y2*y2);
00170 decay_length=std::sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2));
00171
00172 }
00173 }
00174
00175
00176 bool toBeAdded = false;
00177 math::XYZTLorentzVector p((*vpitr)->momentum().px(),
00178 (*vpitr)->momentum().py(),
00179 (*vpitr)->momentum().pz(),
00180 (*vpitr)->momentum().e());
00181
00182
00183 const double minTan = 1.e-20;
00184 double zimpact = Z_hector+1.;
00185 if ( fabs(z1) < Z_hector && fabs(p.pt()/p.pz()) >= minTan ) {
00186
00187 zimpact = (theRDecLenCut-sqrt(x1*x1+y1*y1))*(p.pz()/p.pt())+z1;
00188 }
00189
00190 if ( verbose > 2 ) LogDebug("SimG4CoreGenerator") << "Processing GenParticle barcode = " << (*vpitr)->barcode()
00191 << " status = " << (*vpitr)->status()
00192 << " zimpact = " << zimpact;
00193
00194
00195 if( (*vpitr)->status() == 1 && fabs(zimpact) < Z_hector ) {
00196 if ( !particlePassesPrimaryCuts( p, zimpact ) ) {
00197 continue ;
00198 }
00199 toBeAdded = true;
00200 if ( verbose > 2 ) LogDebug("SimG4CoreGenerator") << "GenParticle barcode = " << (*vpitr)->barcode() << " passed case 1" << std::endl;
00201 }
00202
00203
00204 else if((*vpitr)->status() == 2 && r_decay_length > theRDecLenCut &&
00205 fabs(zimpact) < Z_hector ) {
00206 toBeAdded=true;
00207 if ( verbose > 2 ) LogDebug("SimG4CoreGenerator") << "GenParticle barcode = " << (*vpitr)->barcode() << " passed case 2" << std::endl;
00208 }
00209
00210
00211
00212 else if( (*vpitr)->status() == 1 && fabs(zimpact) >= Z_hector && fabs(z1) >= Z_hector) {
00213 toBeAdded = true;
00214 if ( verbose > 2 ) LogDebug("SimG4CoreGenerator") << "GenParticle barcode = " << (*vpitr)->barcode() << " passed case 3" << std::endl;
00215 }
00216
00217 if(toBeAdded){
00218
00219 G4int pdgcode= (*vpitr)-> pdg_id();
00220 G4PrimaryParticle* g4prim=
00221 new G4PrimaryParticle(pdgcode, p.Px()*GeV, p.Py()*GeV, p.Pz()*GeV);
00222
00223 if ( g4prim->GetG4code() != 0 ){
00224 g4prim->SetMass( g4prim->GetG4code()->GetPDGMass() ) ;
00225 g4prim->SetCharge( g4prim->GetG4code()->GetPDGCharge() ) ;
00226 }
00227
00228 g4prim->SetWeight( 10000*(*vpitr)->barcode() ) ;
00229 setGenId( g4prim, (*vpitr)->barcode() ) ;
00230
00231 if ( (*vpitr)->status() == 2 )
00232 particleAssignDaughters(g4prim,(HepMC::GenParticle *) *vpitr, decay_length);
00233 if ( verbose > 1 ) g4prim->Print();
00234 g4vtx->SetPrimary(g4prim);
00235
00236 if ( (*vpitr)->status()==1 && (*vpitr)->end_vertex()!=0) {
00237 double proper_time=decay_length/(p.Beta()*p.Gamma()*c_light);
00238 if ( verbose > 1 ) LogDebug("SimG4CoreGenerator") <<"Setting proper time for beta="<<p.Beta()<<" gamma="<<p.Gamma()<<" Proper time=" <<proper_time<<" ns" ;
00239 g4prim->SetProperTime(proper_time*ns);
00240 }
00241 }
00242 }
00243
00244 if (verbose > 1 ) g4vtx->Print();
00245 g4evt->AddPrimaryVertex(g4vtx);
00246 ng4vtx++;
00247 }
00248
00249
00250 if ( ng4vtx == 0 ) {
00251 double x1 = 0.;
00252 double y1 = 0.;
00253 double z1 = 0.;
00254 double t1 = 0.;
00255 G4PrimaryVertex* g4vtx=
00256 new G4PrimaryVertex(x1*mm, y1*mm, z1*mm, t1*mm/c_light);
00257 if (verbose > 1 ) g4vtx->Print();
00258 g4evt->AddPrimaryVertex(g4vtx);
00259 }
00260
00261 delete evt ;
00262
00263 return ;
00264 }
00265
00266 void Generator::particleAssignDaughters( G4PrimaryParticle* g4p, HepMC::GenParticle* vp, double decaylength)
00267 {
00268
00269 if ( !(vp->end_vertex()) ) return ;
00270
00271 if ( verbose > 1 )
00272 LogDebug("SimG4CoreGenerator") << "Special case of long decay length \n"
00273 << "Assign daughters with to mother with decaylength=" << decaylength << "mm";
00274 math::XYZTLorentzVector p(vp->momentum().px(), vp->momentum().py(), vp->momentum().pz(), vp->momentum().e());
00275 double proper_time=decaylength/(p.Beta()*p.Gamma()*c_light);
00276 if ( verbose > 2 ) {
00277 LogDebug("SimG4CoreGenerator") <<" px="<<vp->momentum().px()
00278 <<" py="<<vp->momentum().py()
00279 <<" pz="<<vp->momentum().pz()
00280 <<" e="<<vp->momentum().e()
00281 <<" beta="<<p.Beta()
00282 <<" gamma="<<p.Gamma()
00283 <<" Proper time=" <<proper_time<<" ns" ;
00284 }
00285 g4p->SetProperTime(proper_time*ns);
00286 double x1 = vp->end_vertex()->position().x();
00287 double y1 = vp->end_vertex()->position().y();
00288 double z1 = vp->end_vertex()->position().z();
00289 for (HepMC::GenVertex::particle_iterator
00290 vpdec= vp->end_vertex()->particles_begin(HepMC::children);
00291 vpdec != vp->end_vertex()->particles_end(HepMC::children); ++vpdec) {
00292
00293
00294 math::XYZTLorentzVector pdec((*vpdec)->momentum().px(),
00295 (*vpdec)->momentum().py(),
00296 (*vpdec)->momentum().pz(),
00297 (*vpdec)->momentum().e());
00298
00299 G4PrimaryParticle * g4daught=
00300 new G4PrimaryParticle((*vpdec)->pdg_id(), pdec.x()*GeV, pdec.y()*GeV, pdec.z()*GeV);
00301 if ( g4daught->GetG4code() != 0 )
00302 {
00303 g4daught->SetMass( g4daught->GetG4code()->GetPDGMass() ) ;
00304 g4daught->SetCharge( g4daught->GetG4code()->GetPDGCharge() ) ;
00305 }
00306 g4daught->SetWeight( 10000*(*vpdec)->barcode() ) ;
00307 setGenId( g4daught, (*vpdec)->barcode() ) ;
00308 if ( verbose > 1 ) LogDebug("SimG4CoreGenerator") <<"Assigning a "<<(*vpdec)->pdg_id()
00309 <<" as daughter of a " <<vp->pdg_id() ;
00310 if ( (*vpdec)->status() == 2 && (*vpdec)->end_vertex() != 0 )
00311 {
00312 double x2 = (*vpdec)->end_vertex()->position().x();
00313 double y2 = (*vpdec)->end_vertex()->position().y();
00314 double z2 = (*vpdec)->end_vertex()->position().z();
00315 double dd = std::sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2));
00316 particleAssignDaughters(g4daught,*vpdec,dd);
00317 }
00318 (*vpdec)->set_status(1000+(*vpdec)->status());
00319 g4p->SetDaughter(g4daught);
00320 }
00321 return;
00322 }
00323
00324 bool Generator::particlePassesPrimaryCuts( const math::XYZTLorentzVector& mom, const double zimp ) const
00325 {
00326
00327 double phi = mom.Phi() ;
00328 double nrg = mom.P() ;
00329 bool flag = true;
00330
00331 if ( (fEtaCuts) && (zimp < Z_lmin || zimp > Z_lmax) ) {
00332 flag = false;
00333 } else if ( (fPCuts) && (nrg < theMinPCut || nrg > theMaxPCut) ) {
00334 flag = false;
00335 } else if ( (fPhiCuts) && (phi < theMinPhiCut || phi > theMaxPhiCut) ) {
00336 flag = false;
00337 }
00338
00339 if ( verbose > 2 ) LogDebug("SimG4CoreGenerator") << "Generator p = " << nrg << " z_imp = " << zimp << " phi = " << mom.Phi() << " Flag = " << flag;
00340
00341 return flag;
00342 }
00343
00344 bool Generator::particlePassesPrimaryCuts(const G4PrimaryParticle * p) const
00345 {
00346
00347 G4ThreeVector mom = p->GetMomentum();
00348 double phi = mom.phi() ;
00349 double nrg = sqrt(p->GetPx()*p->GetPx() + p->GetPy()*p->GetPy() + p->GetPz()*p->GetPz());
00350 nrg /= GeV ;
00351 double eta = -log(tan(mom.theta()/2));
00352 bool flag = true;
00353
00354 if ( (fEtaCuts) && (eta < theMinEtaCut || eta > theMaxEtaCut) ) {
00355 flag = false;
00356 } else if ( (fPCuts) && (nrg < theMinPCut || nrg > theMaxPCut) ) {
00357 flag = false;
00358 } else if ( (fPhiCuts) && (phi < theMinPhiCut || phi > theMaxPhiCut) ) {
00359 flag = false;
00360 }
00361
00362 if ( verbose > 2 ) LogDebug("SimG4CoreGenerator") << "Generator p = " << nrg << " eta = " << eta << " theta = " << mom.theta() << " phi = " << phi << " Flag = " << flag;
00363
00364 return flag;
00365
00366 }
00367
00368 void Generator::nonBeamEvent2G4(const HepMC::GenEvent * evt, G4Event * g4evt)
00369 {
00370 int i = 0;
00371 for(HepMC::GenEvent::particle_const_iterator it = evt->particles_begin();
00372 it != evt->particles_end(); ++it )
00373 {
00374 i++;
00375 HepMC::GenParticle * g = (*it);
00376 int g_status = g->status();
00377
00378 if (g_status == 1)
00379 {
00380 int g_id = g->pdg_id();
00381 G4PrimaryParticle * g4p =
00382 new G4PrimaryParticle(g_id,g->momentum().px()*GeV,g->momentum().py()*GeV,g->momentum().pz()*GeV);
00383 if (g4p->GetG4code() != 0)
00384 {
00385 g4p->SetMass(g4p->GetG4code()->GetPDGMass());
00386 g4p->SetCharge(g4p->GetG4code()->GetPDGCharge()) ;
00387 }
00388 g4p->SetWeight(i*10000);
00389 setGenId(g4p,i);
00390 if (particlePassesPrimaryCuts(g4p))
00391 {
00392 G4PrimaryVertex * v = new
00393 G4PrimaryVertex(g->production_vertex()->position().x()*mm,
00394 g->production_vertex()->position().y()*mm,
00395 g->production_vertex()->position().z()*mm,
00396 g->production_vertex()->position().t()*mm/c_light);
00397 v->SetPrimary(g4p);
00398 g4evt->AddPrimaryVertex(v);
00399 if(verbose >0) {
00400 v->Print();
00401 }
00402 }
00403 }
00404 }
00405 }