CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
Generator.cc
Go to the documentation of this file.
3 
5 
7 
8 #include "G4Event.hh"
9 
10 #include "G4HEPEvtParticle.hh"
11 #include "G4ParticleDefinition.hh"
12 #include "G4UnitsTable.hh"
13 #include "G4SystemOfUnits.hh"
14 #include "G4PhysicalConstants.hh"
15 
16 using namespace edm;
17 using std::cout;
18 using std::endl;
19 //using std::string;
20 
21 
23  fPCuts(p.getParameter<bool>("ApplyPCuts")),
24  fEtaCuts(p.getParameter<bool>("ApplyEtaCuts")),
25  fPhiCuts(p.getParameter<bool>("ApplyPhiCuts")),
26  theMinPhiCut(p.getParameter<double>("MinPhiCut")), // now operates in radians (CMS standard)
27  theMaxPhiCut(p.getParameter<double>("MaxPhiCut")),
28  theMinEtaCut(p.getParameter<double>("MinEtaCut")),
29  theMaxEtaCut(p.getParameter<double>("MaxEtaCut")),
30  theMinPCut(p.getParameter<double>("MinPCut")), // now operates in GeV (CMS standard)
31  theMaxPCut(p.getParameter<double>("MaxPCut")),
32  theRDecLenCut(p.getParameter<double>("RDecLenCut")*cm),
33  theEtaCutForHector(p.getParameter<double>("EtaCutForHector")),
34  verbose(p.getUntrackedParameter<int>("Verbosity",0)),
35  evt_(0),
36  vtx_(0),
37  weight_(0),
38  Z_lmin(0),
39  Z_lmax(0),
40  Z_hector(0),
41  pdgFilterSel(false)
42 {
43 
44  pdgFilter.resize(0);
45  if ( p.exists("PDGselection") ) {
46 
47  pdgFilterSel =
48  (p.getParameter<edm::ParameterSet>("PDGselection")).getParameter<bool>("PDGfilterSel");
49  pdgFilter =
50  (p.getParameter<edm::ParameterSet>("PDGselection")).getParameter<std::vector< int > >("PDGfilter");
51  for ( unsigned int ii = 0; ii < pdgFilter.size() ; ii++ ) {
52  if (pdgFilterSel) {
53  edm::LogWarning("SimG4CoreGenerator") << " *** Selecting only PDG ID = " << pdgFilter[ii];
54  } else {
55  edm::LogWarning("SimG4CoreGenerator") << " *** Filtering out PDG ID = " << pdgFilter[ii];
56  }
57  }
58 
59  }
60 
61  if(fEtaCuts){
62  Z_lmax = theRDecLenCut*( ( 1 - exp(-2*theMaxEtaCut) ) / ( 2*exp(-theMaxEtaCut) ) );
63  Z_lmin = theRDecLenCut*( ( 1 - exp(-2*theMinEtaCut) ) / ( 2*exp(-theMinEtaCut) ) );
64  }
65 
67 
68  if ( verbose > 0 ) LogDebug("SimG4CoreGenerator")
69  << "Z_min = " << Z_lmin << " Z_max = " << Z_lmax << " Z_hector = " << Z_hector
70  << std::endl;
71 
72 }
73 
75 {
76 }
77 
78 void Generator::HepMC2G4(const HepMC::GenEvent * evt_orig, G4Event * g4evt)
79 {
80 
81  if ( *(evt_orig->vertices_begin()) == 0 )
82  {
83  throw SimG4Exception( "SimG4CoreGenerator: Corrupted Event - GenEvent with no vertex" ) ;
84  }
85 
86 
87  HepMC::GenEvent* evt = new HepMC::GenEvent(*evt_orig) ;
88 
89  if ( evt->weights().size() > 0 )
90  {
91  weight_ = evt->weights()[0] ;
92  for ( unsigned int iw=1; iw<evt->weights().size(); iw++ )
93  {
94  // terminate if the versot of weights contains a zero-weight
95  if ( evt->weights()[iw] <= 0 ) break;
96  weight_ *= evt->weights()[iw] ;
97  }
98  }
99 
100  if (vtx_ != 0) delete vtx_;
101  vtx_ = new math::XYZTLorentzVector((*(evt->vertices_begin()))->position().x(),
102  (*(evt->vertices_begin()))->position().y(),
103  (*(evt->vertices_begin()))->position().z(),
104  (*(evt->vertices_begin()))->position().t());
105 
106  if(verbose >0){
107  evt->print();
108  LogDebug("SimG4CoreGenerator") << "Primary Vertex = (" << vtx_->x() << ","
109  << vtx_->y() << ","
110  << vtx_->z() << ")";
111  }
112 
113  // double x0 = vtx_->x();
114  // double y0 = vtx_->y();
115 
116  unsigned int ng4vtx = 0;
117 
118  for(HepMC::GenEvent::vertex_const_iterator vitr= evt->vertices_begin();
119  vitr != evt->vertices_end(); ++vitr ) {
120  // loop for vertex ...
121  // real vertex?
122  G4bool qvtx=false;
123 
124  for (HepMC::GenVertex::particle_iterator pitr= (*vitr)->particles_begin(HepMC::children);
125  pitr != (*vitr)->particles_end(HepMC::children); ++pitr) {
126  // Admit also status=1 && end_vertex for long vertex special decay treatment
127  if ((*pitr)->status()==1) {
128  qvtx=true;
129  if ( verbose > 2 ) LogDebug("SimG4CoreGenerator")
130  << "GenVertex barcode = " << (*vitr)->barcode()
131  << " selected for GenParticle barcode = " << (*pitr)->barcode()
132  << std::endl;
133  break;
134  }
135  // The selection is made considering if the partcile with status = 2 have the end_vertex
136  // with a radius (R) greater then the theRDecLenCut that means: the end_vertex is outside
137  // the beampipe cilinder (no requirement on the Z of the vertex is applyed).
138  else if ( (*pitr)->status()== 2 ) {
139  if ( (*pitr)->end_vertex() != 0 ) {
140  //double xx = x0-(*pitr)->end_vertex()->position().x();
141  //double yy = y0-(*pitr)->end_vertex()->position().y();
142  double xx = (*pitr)->end_vertex()->position().x();
143  double yy = (*pitr)->end_vertex()->position().y();
144  double r_dd=std::sqrt(xx*xx+yy*yy);
145  if (r_dd>theRDecLenCut){
146  qvtx=true;
147  if ( verbose > 2 ) LogDebug("SimG4CoreGenerator")
148  << "GenVertex barcode = " << (*vitr)->barcode()
149  << " selected for GenParticle barcode = "
150  << (*pitr)->barcode() << " radius = " << r_dd << std::endl;
151  break;
152  }
153  }
154  }
155  }
156 
157 
158  if (!qvtx) {
159  continue;
160  }
161 
162  double x1 = (*vitr)->position().x();
163  double y1 = (*vitr)->position().y();
164  double z1 = (*vitr)->position().z();
165  double t1 = (*vitr)->position().t();
166  G4PrimaryVertex* g4vtx=
167  new G4PrimaryVertex(x1*mm, y1*mm, z1*mm, t1*mm/c_light);
168 
169  for (HepMC::GenVertex::particle_iterator vpitr= (*vitr)->particles_begin(HepMC::children);
170  vpitr != (*vitr)->particles_end(HepMC::children); ++vpitr){
171 
172  // Special cases:
173  // 1) import in Geant4 a full decay chain (e.g. also particles with status == 2)
174  // from the generator in case the decay radius is larger than theRDecLenCut
175  // In this case no cuts will be applied to select the particles hat has to be
176  // processed by geant
177  // 2) import in Geant4 particles with status == 1 but a final end vertex.
178  // The time of the vertex is used as the time of flight to be forced for the particle
179 
180  double r_decay_length=-1;
181  double decay_length=-1;
182 
183  if ( (*vpitr)->status() == 1 || (*vpitr)->status() == 2 ) {
184  // this particle has decayed
185  if ( (*vpitr)->end_vertex() != 0 ) {
186  // needed some particles have status 2 and no end_vertex
187  // Which are the particles with status 2 and not end_vertex, what are suppose to di such kind of particles
188  // when propagated to geant?
189 
190  double x2 = (*vpitr)->end_vertex()->position().x();
191  double y2 = (*vpitr)->end_vertex()->position().y();
192  double z2 = (*vpitr)->end_vertex()->position().z();
193  r_decay_length=std::sqrt(x2*x2+y2*y2);
194  decay_length=std::sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2));
195 
196  }
197  }
198  // end modification
199 
200  bool toBeAdded = false;
201  math::XYZTLorentzVector p((*vpitr)->momentum().px(),
202  (*vpitr)->momentum().py(),
203  (*vpitr)->momentum().pz(),
204  (*vpitr)->momentum().e());
205 
206  // protection against numerical problems for extremely low momenta
207  const double minTan = 1.e-20;
208  double zimpact = Z_hector+1.;
209  if ( fabs(z1) < Z_hector && fabs(p.pt()/p.pz()) >= minTan ) {
210  // write tan(p.Theta()) as p.Pt()/p.Pz()
211  zimpact = (theRDecLenCut-sqrt(x1*x1+y1*y1))*(p.pz()/p.pt())+z1;
212  }
213 
214  if ( verbose > 2 ) LogDebug("SimG4CoreGenerator")
215  << "Processing GenParticle barcode = " << (*vpitr)->barcode()
216  << " status = " << (*vpitr)->status()
217  << " zimpact = " << zimpact;
218 
219  // Filter on allowed particle species if required
220 
221  if ( pdgFilter.size() > 0 ) {
222  std::vector<int>::iterator it = find(pdgFilter.begin(),pdgFilter.end(),(*vpitr)->pdg_id());
223  if ( (it != pdgFilter.end() && !pdgFilterSel) || ( it == pdgFilter.end() && pdgFilterSel ) ) {
224  toBeAdded = false;
225  if ( verbose > 2 ) LogDebug("SimG4CoreGenerator")
226  << "Skip GenParticle barcode = " << (*vpitr)->barcode()
227  << " PDG Id = " << (*vpitr)->pdg_id() << std::endl;
228  continue;
229  }
230  }
231 
232 
233  // Standard case: particles not decayed by the generator
234  if( (*vpitr)->status() == 1 && fabs(zimpact) < Z_hector ) {
235  if ( !particlePassesPrimaryCuts( p, zimpact ) ) {
236  continue ;
237  }
238  toBeAdded = true;
239  if ( verbose > 2 ) LogDebug("SimG4CoreGenerator")
240  << "GenParticle barcode = " << (*vpitr)->barcode()
241  << " passed case 1" << std::endl;
242  }
243 
244  // Decay chain entering exiting the fiducial cylinder defined by theRDecLenCut
245  else if((*vpitr)->status() == 2 && r_decay_length > theRDecLenCut &&
246  fabs(zimpact) < Z_hector ) {
247  toBeAdded=true;
248  if ( verbose > 2 ) LogDebug("SimG4CoreGenerator")
249  << "GenParticle barcode = " << (*vpitr)->barcode()
250  << " passed case 2" << std::endl;
251  }
252 
253  // Particles trasnported along the beam pipe for forward detectors (HECTOR)
254  // Always pass to Geant4 without cuts (to be checked)
255  else if( (*vpitr)->status() == 1 && fabs(zimpact) >= Z_hector && fabs(z1) >= Z_hector) {
256  toBeAdded = true;
257  if ( verbose > 2 ) LogDebug("SimG4CoreGenerator")
258  << "GenParticle barcode = " << (*vpitr)->barcode()
259  << " passed case 3" << std::endl;
260  }
261 
262  if(toBeAdded){
263 
264  G4int pdgcode= (*vpitr)-> pdg_id();
265  G4PrimaryParticle* g4prim=
266  new G4PrimaryParticle(pdgcode, p.Px()*GeV, p.Py()*GeV, p.Pz()*GeV);
267 
268  if ( g4prim->GetG4code() != 0 ){
269  g4prim->SetMass( g4prim->GetG4code()->GetPDGMass() ) ;
270  g4prim->SetCharge( g4prim->GetG4code()->GetPDGCharge() ) ;
271  }
272 
273  // V.I. do not use SetWeight but the same code
274  // value of the code compute inside TrackWithHistory
275  //g4prim->SetWeight( 10000*(*vpitr)->barcode() ) ;
276  setGenId( g4prim, (*vpitr)->barcode() ) ;
277 
278  if ( (*vpitr)->status() == 2 ) {
280  (HepMC::GenParticle *) *vpitr, decay_length);
281  }
282  if ( verbose > 1 ) g4prim->Print();
283  g4vtx->SetPrimary(g4prim);
284  // impose also proper time for status=1 and available end_vertex
285  if ( (*vpitr)->status()==1 && (*vpitr)->end_vertex()!=0) {
286  double proper_time=decay_length/(p.Beta()*p.Gamma()*c_light);
287  if ( verbose > 1 ) LogDebug("SimG4CoreGenerator")
288  <<"Setting proper time for beta="<<p.Beta()<<" gamma="
289  <<p.Gamma()<<" Proper time=" <<proper_time/ns<<" ns" ;
290  g4prim->SetProperTime(proper_time);
291  }
292  }
293  }
294 
295  if (verbose > 1 ) g4vtx->Print();
296  g4evt->AddPrimaryVertex(g4vtx);
297  ng4vtx++;
298  }
299 
300  // Add a protection for completely empty events (produced by LHCTransport): add a dummy vertex with no particle attached to it
301  if ( ng4vtx == 0 ) {
302  double x1 = 0.;
303  double y1 = 0.;
304  double z1 = 0.;
305  double t1 = 0.;
306  G4PrimaryVertex* g4vtx=
307  new G4PrimaryVertex(x1*mm, y1*mm, z1*mm, t1*mm/c_light);
308  if (verbose > 1 ) g4vtx->Print();
309  g4evt->AddPrimaryVertex(g4vtx);
310  }
311 
312  delete evt ;
313 
314  return ;
315 }
316 
317 void Generator::particleAssignDaughters( G4PrimaryParticle* g4p, HepMC::GenParticle* vp, double decaylength)
318 {
319 
320  if ( !(vp->end_vertex()) ) return ;
321 
322  if ( verbose > 1 )
323  LogDebug("SimG4CoreGenerator") << "Special case of long decay length \n"
324  << "Assign daughters with to mother with decaylength=" << decaylength << "mm";
325  math::XYZTLorentzVector p(vp->momentum().px(), vp->momentum().py(), vp->momentum().pz(), vp->momentum().e());
326  double proper_time=decaylength/(p.Beta()*p.Gamma()*c_light);
327  if ( verbose > 2 ) {
328  LogDebug("SimG4CoreGenerator") <<" px="<<vp->momentum().px()
329  <<" py="<<vp->momentum().py()
330  <<" pz="<<vp->momentum().pz()
331  <<" e="<<vp->momentum().e()
332  <<" beta="<<p.Beta()
333  <<" gamma="<<p.Gamma()
334  <<" Proper time=" <<proper_time<<" ns" ;
335  }
336  g4p->SetProperTime(proper_time*ns); // the particle will decay after the same length if it has not interacted before
337  double x1 = vp->end_vertex()->position().x();
338  double y1 = vp->end_vertex()->position().y();
339  double z1 = vp->end_vertex()->position().z();
340  for (HepMC::GenVertex::particle_iterator
341  vpdec= vp->end_vertex()->particles_begin(HepMC::children);
342  vpdec != vp->end_vertex()->particles_end(HepMC::children); ++vpdec) {
343 
344  //transform decay products such that in the rest frame of mother
345  math::XYZTLorentzVector pdec((*vpdec)->momentum().px(),
346  (*vpdec)->momentum().py(),
347  (*vpdec)->momentum().pz(),
348  (*vpdec)->momentum().e());
349  // children should only be taken into account once
350  G4PrimaryParticle * g4daught=
351  new G4PrimaryParticle((*vpdec)->pdg_id(), pdec.x()*GeV, pdec.y()*GeV, pdec.z()*GeV);
352  if ( g4daught->GetG4code() != 0 )
353  {
354  g4daught->SetMass( g4daught->GetG4code()->GetPDGMass() ) ;
355  g4daught->SetCharge( g4daught->GetG4code()->GetPDGCharge() ) ;
356  }
357  // V.I. do not use SetWeight but the same code
358  // value of the code compute inside TrackWithHistory
359  //g4daught->SetWeight( 10000*(*vpdec)->barcode() ) ;
360  setGenId( g4daught, (*vpdec)->barcode() ) ;
361  if ( verbose > 1 ) LogDebug("SimG4CoreGenerator") <<"Assigning a "<<(*vpdec)->pdg_id()
362  <<" as daughter of a " <<vp->pdg_id() ;
363  if ( (*vpdec)->status() == 2 && (*vpdec)->end_vertex() != 0 )
364  {
365  double x2 = (*vpdec)->end_vertex()->position().x();
366  double y2 = (*vpdec)->end_vertex()->position().y();
367  double z2 = (*vpdec)->end_vertex()->position().z();
368  double dd = std::sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2));
369  particleAssignDaughters(g4daught,*vpdec,dd);
370  }
371  (*vpdec)->set_status(1000+(*vpdec)->status());
372  g4p->SetDaughter(g4daught);
373  }
374  return;
375 }
376 
377 bool Generator::particlePassesPrimaryCuts( const math::XYZTLorentzVector& mom, const double zimp ) const
378 {
379 
380  double phi = mom.Phi() ;
381  double nrg = mom.P() ;
382  bool flag = true;
383 
384  if ( (fEtaCuts) && (zimp < Z_lmin || zimp > Z_lmax) ) {
385  flag = false;
386  } else if ( (fPCuts) && (nrg < theMinPCut || nrg > theMaxPCut) ) {
387  flag = false;
388  } else if ( (fPhiCuts) && (phi < theMinPhiCut || phi > theMaxPhiCut) ) {
389  flag = false;
390  }
391 
392  if ( verbose > 2 ) LogDebug("SimG4CoreGenerator") << "Generator p = " << nrg << " z_imp = " << zimp << " phi = " << mom.Phi() << " Flag = " << flag;
393 
394  return flag;
395 }
396 
397 bool Generator::particlePassesPrimaryCuts(const G4PrimaryParticle * p) const
398 {
399 
400  G4ThreeVector mom = p->GetMomentum();
401  double phi = mom.phi() ;
402  double nrg = sqrt(p->GetPx()*p->GetPx() + p->GetPy()*p->GetPy() + p->GetPz()*p->GetPz());
403  nrg /= GeV ; // need to convert, since Geant4 operates in MeV
404  double eta = -log(tan(mom.theta()/2));
405  bool flag = true;
406 
407  if ( (fEtaCuts) && (eta < theMinEtaCut || eta > theMaxEtaCut) ) {
408  flag = false;
409  } else if ( (fPCuts) && (nrg < theMinPCut || nrg > theMaxPCut) ) {
410  flag = false;
411  } else if ( (fPhiCuts) && (phi < theMinPhiCut || phi > theMaxPhiCut) ) {
412  flag = false;
413  }
414 
415  if ( verbose > 2 ) LogDebug("SimG4CoreGenerator") << "Generator p = " << nrg << " eta = " << eta << " theta = " << mom.theta() << " phi = " << phi << " Flag = " << flag;
416 
417  return flag;
418 
419 }
420 
421 void Generator::nonBeamEvent2G4(const HepMC::GenEvent * evt, G4Event * g4evt)
422 {
423  int i = 0;
424  for(HepMC::GenEvent::particle_const_iterator it = evt->particles_begin();
425  it != evt->particles_end(); ++it )
426  {
427  i++;
428  HepMC::GenParticle * g = (*it);
429  int g_status = g->status();
430  // storing only particle with status == 1
431  if (g_status == 1)
432  {
433  int g_id = g->pdg_id();
434  G4PrimaryParticle * g4p =
435  new G4PrimaryParticle(g_id,g->momentum().px()*GeV,g->momentum().py()*GeV,g->momentum().pz()*GeV);
436  if (g4p->GetG4code() != 0)
437  {
438  g4p->SetMass(g4p->GetG4code()->GetPDGMass());
439  g4p->SetCharge(g4p->GetG4code()->GetPDGCharge()) ;
440  }
441  // V.I. do not use SetWeight but the same code
442  // value of the code compute inside TrackWithHistory
443  //g4p->SetWeight(i*10000);
444  setGenId(g4p,i);
445  if (particlePassesPrimaryCuts(g4p))
446  {
447  G4PrimaryVertex * v = new
448  G4PrimaryVertex(g->production_vertex()->position().x()*mm,
449  g->production_vertex()->position().y()*mm,
450  g->production_vertex()->position().z()*mm,
451  g->production_vertex()->position().t()*mm/c_light);
452  v->SetPrimary(g4p);
453  g4evt->AddPrimaryVertex(v);
454  if(verbose >0) {
455  v->Print();
456  }
457  }
458  }
459  } // end loop on HepMC particles
460 }
#define LogDebug(id)
bool fPhiCuts
Definition: Generator.h:45
T getParameter(std::string const &) const
int i
Definition: DBlmapReader.cc:9
void setGenId(G4PrimaryParticle *p, int id) const
Definition: Generator.h:39
double theEtaCutForHector
Definition: Generator.h:53
double Z_lmax
Definition: Generator.h:58
void HepMC2G4(const HepMC::GenEvent *g, G4Event *e)
Definition: Generator.cc:78
double theMaxPhiCut
Definition: Generator.h:47
Generator(const edm::ParameterSet &p)
Definition: Generator.cc:22
bool exists(std::string const &parameterName) const
checks if a parameter exists
double theMinEtaCut
Definition: Generator.h:48
T eta() const
bool pdgFilterSel
Definition: Generator.h:60
int ii
Definition: cuy.py:588
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:7
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e g
Definition: Activities.doc:4
void particleAssignDaughters(G4PrimaryParticle *p, HepMC::GenParticle *hp, double length)
Definition: Generator.cc:317
XYZTLorentzVectorD XYZTLorentzVector
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:29
T sqrt(T t)
Definition: SSEVec.h:48
Tan< T >::type tan(const T &t)
Definition: Tan.h:22
double weight_
Definition: Generator.h:57
double theMaxEtaCut
Definition: Generator.h:49
double theRDecLenCut
Definition: Generator.h:52
double theMaxPCut
Definition: Generator.h:51
math::XYZTLorentzVector * vtx_
Definition: Generator.h:56
void nonBeamEvent2G4(const HepMC::GenEvent *g, G4Event *e)
Definition: Generator.cc:421
return(e1-e2)*(e1-e2)+dp *dp
double Z_lmin
Definition: Generator.h:58
virtual ~Generator()
Definition: Generator.cc:74
std::vector< int > pdgFilter
Definition: Generator.h:59
tuple cout
Definition: gather_cfg.py:121
volatile std::atomic< bool > shutdown_flag false
bool particlePassesPrimaryCuts(const G4PrimaryParticle *p) const
Definition: Generator.cc:397
bool fEtaCuts
Definition: Generator.h:44
double Z_hector
Definition: Generator.h:58
Definition: DDAxes.h:10
bool fPCuts
Definition: Generator.h:43