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 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
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
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
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 break;
00110 }
00111
00112
00113
00114 else if ( (*pitr)->status()== 2 ) {
00115 if ( (*pitr)->end_vertex() != 0 ) {
00116
00117
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
00145
00146
00147
00148
00149
00150
00151
00152 double r_decay_length=-1;
00153 double decay_length=-1;
00154
00155 if ( (*vpitr)->status() == 1 || (*vpitr)->status() == 2 ) {
00156
00157 if ( (*vpitr)->end_vertex() != 0 ) {
00158
00159
00160
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
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
00181 if( (*vpitr)->status() == 1 && fabs(zimpact) < Z_hector ) {
00182 if ( !particlePassesPrimaryCuts( p, zimpact ) ) {
00183 continue ;
00184 }
00185 toBeAdded = true;
00186 }
00187
00188
00189 else if((*vpitr)->status() == 2 && r_decay_length > theRDecLenCut &&
00190 fabs(zimpact) < Z_hector ) {
00191 toBeAdded=true;
00192 }
00193
00194
00195
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
00219 if ( (*vpitr)->status()==1 && (*vpitr)->end_vertex()!=0) {
00220 double proper_time=decay_length/(p.Beta()*p.Gamma()*c_light);
00221
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);
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
00260 math::XYZTLorentzVector pdec((*vpdec)->momentum().px(),
00261 (*vpdec)->momentum().py(),
00262 (*vpdec)->momentum().pz(),
00263 (*vpdec)->momentum().e());
00264
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
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 ;
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
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 }
00356 }