CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
Pythia6Hadronizer.cc
Go to the documentation of this file.
1 
2 // -*- C++ -*-
3 
4 #include "Pythia6Hadronizer.h"
5 
6 #include "HepMC/GenEvent.h"
7 #include "HepMC/PdfInfo.h"
8 #include "HepMC/PythiaWrapper6_4.h"
9 #include "HepMC/HEPEVT_Wrapper.h"
10 #include "HepMC/IO_HEPEVT.h"
11 
13 
15 
17 
19 
21 
22 
23 HepMC::IO_HEPEVT conv;
24 
25 #include "HepPID/ParticleIDTranslations.hh"
26 
27 // NOTE: here a number of Pythia6 routines are declared,
28 // plus some functionalities to pass around Pythia6 params
29 //
32 
33 namespace gen
34 {
35 
36 extern "C" {
37 
38  //
39  // these two are NOT part of Pythi6 core code but are "custom" add-ons
40  // we keep them interfaced here, rather than in GenExtensions, because
41  // they tweak not at the ME level, but a step further, at the framgmentation
42  //
43  // stop-hadrons
44  //
45  void pystrhad_(); // init stop-hadrons (id's, names, charges...)
46  void pystfr_(int&); // tweaks fragmentation, fragments the string near to a stop,
47  // to form stop-hadron by producing a new q-qbar pair
48  // gluino/r-hadrons
49  void pyglrhad_();
50  void pyglfr_(); // tweaks fragmentation, fragment the string near to a gluino,
51  // to form gluino-hadron, either by producing a new g-g pair,
52  // or two new q-qbar ones
53 
54 
55 } // extern "C"
56 
57 class Pythia6ServiceWithCallback : public Pythia6Service {
58  public:
60 
61  private:
62  void upInit()
64 
65  void upEvnt()
66  {
70  }
71 
72  bool upVeto()
73  {
75  return false;
76 
78  return true;
79 
80  // NOTE: I'm passing NULL pointers, instead of HepMC::GenEvent, etc.
81  return Pythia6Hadronizer::getJetMatching()->match(0, 0, true);
82  }
83 };
84 
85 static struct {
86  int n, npad, k[5][pyjets_maxn];
87  double p[5][pyjets_maxn], v[5][pyjets_maxn];
88 } pyjets_local;
89 
90 JetMatching* Pythia6Hadronizer::fJetMatching = 0;
91 
93  : BaseHadronizer(ps),
94  fPy6Service( new Pythia6ServiceWithCallback(ps) ), // this will store py6 params for further settings
95  fInitialState(PP),
96  fCOMEnergy(ps.getParameter<double>("comEnergy")),
97  fHepMCVerbosity(ps.getUntrackedParameter<bool>("pythiaHepMCVerbosity",false)),
98  fMaxEventsToPrint(ps.getUntrackedParameter<int>("maxEventsToPrint", 0)),
99  fPythiaListVerbosity(ps.getUntrackedParameter<int>("pythiaPylistVerbosity", 0)),
100  fDisplayPythiaBanner(ps.getUntrackedParameter<bool>("displayPythiaBanner",false)),
101  fDisplayPythiaCards(ps.getUntrackedParameter<bool>("displayPythiaCards",false))
102 {
103 
104 
105  // J.Y.: the following 3 parameters are hacked "for a reason"
106  //
107  if ( ps.exists( "PPbarInitialState" ) )
108  {
109  if ( fInitialState == PP )
110  {
112  edm::LogInfo("GeneratorInterface|Pythia6Interface")
113  << "Pythia6 will be initialized for PROTON-ANTIPROTON INITIAL STATE. "
114  << "This is a user-request change from the DEFAULT PROTON-PROTON initial state." << std::endl;
115  std::cout << "Pythia6 will be initialized for PROTON-ANTIPROTON INITIAL STATE." << std::endl;
116  std::cout << "This is a user-request change from the DEFAULT PROTON-PROTON initial state." << std::endl;
117  }
118  else
119  {
120  // probably need to throw on attempt to override ?
121  }
122  }
123  else if ( ps.exists( "ElectronPositronInitialState" ) )
124  {
125  if ( fInitialState == PP )
126  {
128  edm::LogInfo("GeneratorInterface|Pythia6Interface")
129  << "Pythia6 will be initialized for ELECTRON-POSITRON INITIAL STATE. "
130  << "This is a user-request change from the DEFAULT PROTON-PROTON initial state." << std::endl;
131  std::cout << "Pythia6 will be initialized for ELECTRON-POSITRON INITIAL STATE." << std::endl;
132  std::cout << "This is a user-request change from the DEFAULT PROTON-PROTON initial state." << std::endl;
133  }
134  else
135  {
136  // probably need to throw on attempt to override ?
137  }
138  }
139  else if ( ps.exists( "ElectronProtonInitialState" ) )
140  {
141  if ( fInitialState == PP )
142  {
144  fBeam1PZ = (ps.getParameter<edm::ParameterSet>("ElectronProtonInitialState")).getParameter<double>("electronMomentum");
145  fBeam2PZ = (ps.getParameter<edm::ParameterSet>("ElectronProtonInitialState")).getParameter<double>("protonMomentum");
146  edm::LogInfo("GeneratorInterface|Pythia6Interface")
147  << "Pythia6 will be initialized for ELECTRON-PROTON INITIAL STATE. "
148  << "This is a user-request change from the DEFAULT PROTON-PROTON initial state." << std::endl;
149  std::cout << "Pythia6 will be initialized for ELECTRON-PROTON INITIAL STATE." << std::endl;
150  std::cout << "This is a user-request change from the DEFAULT PROTON-PROTON initial state." << std::endl;
151  }
152  else
153  {
154  // probably need to throw on attempt to override ?
155  }
156  }
157  else if ( ps.exists( "PositronProtonInitialState" ) )
158  {
159  if ( fInitialState == PP )
160  {
162  fBeam1PZ = (ps.getParameter<edm::ParameterSet>("ElectronProtonInitialState")).getParameter<double>("positronMomentum");
163  fBeam2PZ = (ps.getParameter<edm::ParameterSet>("ElectronProtonInitialState")).getParameter<double>("protonMomentum");
164  edm::LogInfo("GeneratorInterface|Pythia6Interface")
165  << "Pythia6 will be initialized for POSITRON-PROTON INITIAL STATE. "
166  << "This is a user-request change from the DEFAULT PROTON-PROTON initial state." << std::endl;
167  std::cout << "Pythia6 will be initialized for POSITRON-PROTON INITIAL STATE." << std::endl;
168  std::cout << "This is a user-request change from the DEFAULT PROTON-PROTON initial state." << std::endl;
169  }
170  else
171  {
172  // throw on unknown initial state !
173  throw edm::Exception(edm::errors::Configuration,"Pythia6Interface")
174  <<" UNKNOWN INITIAL STATE. \n The allowed initial states are: PP, PPbar, ElectronPositron, ElectronProton, and PositronProton \n";
175  }
176  }
177 
178 
179  // J.Y.: the following 4 params are "hacked", in the sense
180  // that they're tracked but get in optionally;
181  // this will be fixed once we update all applications
182  //
183 
184  fStopHadronsEnabled = false;
185  if ( ps.exists( "stopHadrons" ) )
186  fStopHadronsEnabled = ps.getParameter<bool>("stopHadrons") ;
187 
188  fGluinoHadronsEnabled = false;
189  if ( ps.exists( "gluinoHadrons" ) )
190  fGluinoHadronsEnabled = ps.getParameter<bool>("gluinoHadrons");
191 
192  fImposeProperTime = false;
193  if ( ps.exists( "imposeProperTime" ) )
194  {
195  fImposeProperTime = ps.getParameter<bool>("imposeProperTime");
196  }
197 
198  fConvertToPDG = false;
199  if ( ps.exists( "doPDGConvert" ) )
200  fConvertToPDG = ps.getParameter<bool>("doPDGConvert");
201 
202  if ( ps.exists("jetMatching") )
203  {
204  edm::ParameterSet jmParams =
206  "jetMatching");
207 
208  fJetMatching = JetMatching::create(jmParams).release();
209  }
210 
211  // first of all, silence Pythia6 banner printout, unless display requested
212  //
213  if ( !fDisplayPythiaBanner )
214  {
215  if (!call_pygive("MSTU(12)=12345"))
216  {
217  throw edm::Exception(edm::errors::Configuration,"PythiaError")
218  <<" Pythia did not accept MSTU(12)=12345";
219  }
220  }
221 
222 // silence printouts from PYGIVE, unless display requested
223 //
224  if ( ! fDisplayPythiaCards )
225  {
226  if (!call_pygive("MSTU(13)=0"))
227  {
228  throw edm::Exception(edm::errors::Configuration,"PythiaError")
229  <<" Pythia did not accept MSTU(13)=0";
230  }
231  }
232 
233  // tmp stuff to deal with EvtGen corrupting pyjets
234  // NPartsBeforeDecays = 0;
235  flushTmpStorage();
236 
237 }
238 
240 {
241  if ( fPy6Service != 0 ) delete fPy6Service;
242  if ( fJetMatching != 0 ) delete fJetMatching;
243 }
244 
246 {
247 
248  pyjets_local.n = 0 ;
249  pyjets_local.npad = 0 ;
250  for ( int ip=0; ip<pyjets_maxn; ip++ )
251  {
252  for ( int i=0; i<5; i++ )
253  {
254  pyjets_local.k[i][ip] = 0;
255  pyjets_local.p[i][ip] = 0.;
256  pyjets_local.v[i][ip] = 0.;
257  }
258  }
259  return;
260 
261 }
262 
264 {
265 
266  pyjets_local.n = pyjets.n;
267  pyjets_local.npad = pyjets.npad;
268  for ( int ip=0; ip<pyjets_maxn; ip++ )
269  {
270  for ( int i=0; i<5; i++ )
271  {
272  pyjets_local.k[i][ip] = pyjets.k[i][ip];
273  pyjets_local.p[i][ip] = pyjets.p[i][ip];
274  pyjets_local.v[i][ip] = pyjets.v[i][ip];
275  }
276  }
277 
278  return ;
279 
280 }
281 
283 {
284 
285  bool lhe = lheEvent() != 0;
286 
287  HepMC::PdfInfo pdf;
288 
289  // if we are in hadronizer mode, we can pass on information from
290  // the LHE input
291  if (lhe)
292  {
293  lheEvent()->fillEventInfo( event().get() );
294  lheEvent()->fillPdfInfo( &pdf );
295  }
296  else
297  {
298  // filling in factorization "Q scale" now! pthat moved to binningValues()
299  //
300 
301  if ( event()->signal_process_id() <= 0) event()->set_signal_process_id( pypars.msti[0] );
302  if ( event()->event_scale() <=0 ) event()->set_event_scale( pypars.pari[22] );
303  if ( event()->alphaQED() <= 0) event()->set_alphaQED( pyint1.vint[56] );
304  if ( event()->alphaQCD() <= 0) event()->set_alphaQCD( pyint1.vint[57] );
305 
306  // get pdf info directly from Pythia6 and set it up into HepMC::GenEvent
307  // S. Mrenna: Prefer vint block
308  //
309  if ( pdf.id1() <= 0) pdf.set_id1( pyint1.mint[14] == 21 ? 0 : pyint1.mint[14] );
310  if ( pdf.id2() <= 0) pdf.set_id2( pyint1.mint[15] == 21 ? 0 : pyint1.mint[15] );
311  if ( pdf.x1() <= 0) pdf.set_x1( pyint1.vint[40] );
312  if ( pdf.x2() <= 0) pdf.set_x2( pyint1.vint[41] );
313  if ( pdf.pdf1() <= 0) pdf.set_pdf1( pyint1.vint[38] / pyint1.vint[40] );
314  if ( pdf.pdf2() <= 0) pdf.set_pdf2( pyint1.vint[39] / pyint1.vint[41] );
315  if ( pdf.scalePDF() <= 0) pdf.set_scalePDF( pyint1.vint[50] );
316  }
317 
318 /* 9/9/2010 - JVY: This is the old piece of code - I can't remember why we implemented it this way.
319  However, it's causing problems with pdf1 & pdf2 when processing LHE samples,
320  specifically, because both are set to -1, it tries to fill with Py6 numbers that
321  are NOT valid/right at this point !
322  In general, for LHE/ME event processing we should implement the correct calculation
323  of the pdf's, rather than using py6 ones.
324 
325  // filling in factorization "Q scale" now! pthat moved to binningValues()
326 
327  if (!lhe || event()->signal_process_id() < 0) event()->set_signal_process_id( pypars.msti[0] );
328  if (!lhe || event()->event_scale() < 0) event()->set_event_scale( pypars.pari[22] );
329  if (!lhe || event()->alphaQED() < 0) event()->set_alphaQED( pyint1.vint[56] );
330  if (!lhe || event()->alphaQCD() < 0) event()->set_alphaQCD( pyint1.vint[57] );
331 
332  // get pdf info directly from Pythia6 and set it up into HepMC::GenEvent
333  // S. Mrenna: Prefer vint block
334  //
335  if (!lhe || pdf.id1() < 0) pdf.set_id1( pyint1.mint[14] == 21 ? 0 : pyint1.mint[14] );
336  if (!lhe || pdf.id2() < 0) pdf.set_id2( pyint1.mint[15] == 21 ? 0 : pyint1.mint[15] );
337  if (!lhe || pdf.x1() < 0) pdf.set_x1( pyint1.vint[40] );
338  if (!lhe || pdf.x2() < 0) pdf.set_x2( pyint1.vint[41] );
339  if (!lhe || pdf.pdf1() < 0) pdf.set_pdf1( pyint1.vint[38] / pyint1.vint[40] );
340  if (!lhe || pdf.pdf2() < 0) pdf.set_pdf2( pyint1.vint[39] / pyint1.vint[41] );
341  if (!lhe || pdf.scalePDF() < 0) pdf.set_scalePDF( pyint1.vint[50] );
342 */
343 
344  event()->set_pdf_info( pdf ) ;
345 
346  // this is "standard" Py6 event weight (corresponds to PYINT1/VINT(97)
347  //
348  if (lhe && std::abs(lheRunInfo()->getHEPRUP()->IDWTUP) == 4)
349  // translate mb to pb (CMS/Gen "convention" as of May 2009)
350  event()->weights().push_back( pyint1.vint[96] * 1.0e9 );
351  else
352  event()->weights().push_back( pyint1.vint[96] );
353  //
354  // this is event weight as 1./VINT(99) (PYINT1/VINT(99) is returned by the PYEVWT)
355  //
356  event()->weights().push_back( 1./(pyint1.vint[98]) );
357 
358  // now create the GenEventInfo product from the GenEvent and fill
359  // the missing pieces
360 
361  eventInfo().reset( new GenEventInfoProduct( event().get() ) );
362 
363  // in Pythia6 pthat is used to subdivide samples into different bins
364  // in LHE mode the binning is done by the external ME generator
365  // which is likely not pthat, so only filling it for Py6 internal mode
366  if (!lhe)
367  {
368  eventInfo()->setBinningValues( std::vector<double>(1, pypars.pari[16]) );
369  }
370 
371  // here we treat long-lived particles
372  //
373  if ( fImposeProperTime || pydat1.mstj[21]==3 || pydat1.mstj[21]==4 ) imposeProperTime();
374 
375  // convert particle IDs Py6->PDG, if requested
376  if ( fConvertToPDG ) {
377  for ( HepMC::GenEvent::particle_iterator part = event()->particles_begin();
378  part != event()->particles_end(); ++part) {
379  (*part)->set_pdg_id(HepPID::translatePythiatoPDT((*part)->pdg_id()));
380  }
381  }
382 
383  // service printouts, if requested
384  //
385  if (fMaxEventsToPrint > 0)
386  {
389  if (fHepMCVerbosity)
390  {
391  std::cout << "Event process = " << pypars.msti[0] << std::endl
392  << "----------------------" << std::endl;
393  event()->print();
394  }
395  }
396 
397  // dump of all settings after all initializations
398  if ( fDisplayPythiaCards ) {
399  fDisplayPythiaCards = false;
400  call_pylist(12);
401  call_pylist(13);
402  std::cout << "\n PYPARS \n" << std::endl;
403  std::cout << std::setw(5) << std::fixed << "I"
404  << std::setw(10) << std::fixed << "MSTP(I)"
405  << std::setw(16) << std::fixed << "PARP(I)"
406  << std::setw(10) << std::fixed << "MSTI(I)"
407  << std::setw(16) << std::fixed << "PARI(I)" << std::endl;
408  for ( unsigned int ind=0; ind < 200; ind++ ) {
409  std::cout << std::setw(5) << std::fixed << ind+1
410  << std::setw(10) << std::fixed << pypars.mstp[ind]
411  << std::setw(16) << std::fixed << pypars.parp[ind]
412  << std::setw(10) << std::fixed << pypars.msti[ind]
413  << std::setw(16) << std::fixed << pypars.pari[ind] << std::endl;
414  }
415  }
416 
417  return;
418 }
419 
421 {
422  Pythia6Service::InstanceWrapper guard(fPy6Service); // grab Py6 instance
423 
425 
426  // generate event with Pythia6
427  //
428 
430  {
431  // call_pygive("MSTJ(1)=-1");
432  call_pygive("MSTJ(14)=-1");
433  }
434 
435  call_pyevnt();
436 
438  {
439  // call_pygive("MSTJ(1)=1");
440  call_pygive("MSTJ(14)=1");
441  int ierr=0;
442  if ( fStopHadronsEnabled )
443  {
444  pystfr_(ierr);
445  if ( ierr != 0 ) // skip failed events
446  {
447  event().reset();
448  return false;
449  }
450  }
452  }
453 
454  if ( pyint1.mint[50] != 0 ) // skip event if py6 considers it bad
455  {
456  event().reset();
457  return false;
458  }
459 
460  call_pyhepc(1);
461  event().reset( conv.read_next_event() );
462 
463  // this is to deal with post-gen tools & residualDecay() that may reuse PYJETS
464  //
465  flushTmpStorage();
466  fillTmpStorage();
467 
468  return true;
469 }
470 
472 {
473  Pythia6Service::InstanceWrapper guard(fPy6Service); // grab Py6 instance
474 
477  if ( fJetMatching )
478  {
481  }
482 
483  // generate event with Pythia6
484  //
486  {
487  call_pygive("MSTJ(1)=-1");
488  call_pygive("MSTJ(14)=-1");
489  }
490 
491  call_pyevnt();
492 
493  if ( FortranCallback::getInstance()->getIterationsPerEvent() > 1 ||
494  hepeup_.nup <= 0 || pypars.msti[0] == 1 )
495  {
496  // update LHE matching statistics
498 
499  event().reset();
500  return false;
501  }
502 
503  // update LHE matching statistics
504  //
506 
508  {
509  call_pygive("MSTJ(1)=1");
510  call_pygive("MSTJ(14)=1");
511  int ierr = 0;
512  if ( fStopHadronsEnabled )
513  {
514  pystfr_(ierr);
515  if ( ierr != 0 ) // skip failed events
516  {
517  event().reset();
518  return false;
519  }
520  }
521 
523  }
524 
525  if ( pyint1.mint[50] != 0 ) // skip event if py6 considers it bad
526  {
527  event().reset();
528  return false;
529  }
530 
531  call_pyhepc(1);
532  event().reset( conv.read_next_event() );
533 
534  // this is to deal with post-gen tools and/or residualDecay(), that may reuse PYJETS
535  //
536  flushTmpStorage();
537  fillTmpStorage();
538 
539  return true;
540 }
541 
543 {
544  return true;
545 }
546 
548 {
549 
550  // event().get()->print();
551 
552  Pythia6Service::InstanceWrapper guard(fPy6Service); // grab Py6 instance
553 
554  // int nDocLines = pypars.msti[3];
555 
556  int NPartsBeforeDecays = pyjets_local.n ;
557  int NPartsAfterDecays = event().get()->particles_size();
558  int barcode = NPartsAfterDecays;
559 
560  // JVY: well, in principle, it's not a 100% fair to go up to NPartsBeforeDecays,
561  // because Photos will attach gamma's to existing vertexes, i.e. in the middle
562  // of the event rather than at the end; but this will only shift poiters down,
563  // so we'll be going again over a few "original" particle...
564  // in the alternative, we may go all the way up to the beginning of the event
565  // and re-check if anything remains to decay, that's fine even if it'll take
566  // some extra CPU...
567 
568  for ( int ipart=NPartsAfterDecays; ipart>NPartsBeforeDecays; ipart-- )
569  {
570  HepMC::GenParticle* part = event().get()->barcode_to_particle( ipart );
571  int status = part->status();
572  if ( status != 1 ) continue; // check only "stable" particles,
573  // as some undecayed may still be marked as such
574  int pdgid = part->pdg_id();
575  int py6ptr = pycomp_( pdgid );
576  if ( pydat3.mdcy[0][py6ptr-1] != 1 ) continue; // particle is not expected to decay
577  int py6id = HepPID::translatePDTtoPythia( pdgid );
578  //
579  // first, will need to zero out, then fill up PYJETS
580  // I better do it directly (by hands) rather than via py1ent
581  // - to avoid (additional) mass smearing
582  //
583  if ( part->momentum().t() <= part->generated_mass() )
584  {
585  continue ; // e==m --> 0-momentum, nothing to decay...
586  }
587  else
588  {
589  pyjets.n = 0;
590  for ( int i=0; i<5; i++ )
591  {
592  pyjets.k[i][0] = 0;
593  pyjets.p[i][0] = 0.;
594  pyjets.v[i][0] = 0.;
595  }
596  pyjets.k[0][0] = 1;
597  pyjets.k[1][0] = py6id;
598  pyjets.p[4][0] = part->generated_mass();
599  pyjets.p[3][0] = part->momentum().t();
600  pyjets.p[0][0] = part->momentum().x();
601  pyjets.p[1][0] = part->momentum().y();
602  pyjets.p[2][0] = part->momentum().z();
603  HepMC::GenVertex* prod_vtx = part->production_vertex();
604  if ( !prod_vtx ) continue; // in principle, should never happen but...
605  pyjets.v[0][0] = prod_vtx->position().x();
606  pyjets.v[1][0] = prod_vtx->position().y();
607  pyjets.v[2][0] = prod_vtx->position().z();
608  pyjets.v[3][0] = prod_vtx->position().t();
609  pyjets.v[4][0] = 0.;
610  pyjets.n = 1;
611  pyjets.npad = pyjets_local.npad;
612  }
613 
614  // now call Py6 decay routine
615  //
616  int parent = 1; // since we always pass to Py6 a single particle
617  pydecy_( parent );
618 
619  // now attach decay products to mother
620  //
621  for ( int iprt1=1; iprt1<pyjets.n; iprt1++ )
622  {
623  part->set_status( 2 );
624 
625  HepMC::GenVertex* DecVtx = new HepMC::GenVertex( HepMC::FourVector(pyjets.v[0][iprt1],
626  pyjets.v[1][iprt1],
627  pyjets.v[2][iprt1],
628  pyjets.v[3][iprt1]) );
629  DecVtx->add_particle_in( part ); // this will cleanup end_vertex if exists, replace with the new one
630  // I presume (vtx) barcode will be given automatically
631 
632  HepMC::FourVector pmom(pyjets.p[0][iprt1],pyjets.p[1][iprt1],
633  pyjets.p[2][iprt1],pyjets.p[3][iprt1] );
634 
635  int dstatus = 0;
636  if ( pyjets.k[0][iprt1] >= 1 && pyjets.k[0][iprt1] <= 10 )
637  {
638  dstatus = 1;
639  }
640  else if ( pyjets.k[0][iprt1] >= 11 && pyjets.k[0][iprt1] <= 20 )
641  {
642  dstatus = 2;
643  }
644  else if ( pyjets.k[0][iprt1] >= 21 && pyjets.k[0][iprt1] <= 30 )
645  {
646  dstatus = 3;
647  }
648  else if ( pyjets.k[0][iprt1] >= 31 && pyjets.k[0][iprt1] <= 100 )
649  {
650  dstatus = pyjets.k[0][iprt1];
651  }
652  HepMC::GenParticle* daughter = new HepMC::GenParticle(pmom,
653  HepPID::translatePythiatoPDT( pyjets.k[1][iprt1] ),
654  dstatus);
655  barcode++;
656  daughter->suggest_barcode( barcode );
657  DecVtx->add_particle_out( daughter );
658 
659  int iprt2;
660  for ( iprt2=iprt1+1; iprt2<pyjets.n; iprt2++ ) // the pointer is shifted by -1, c++ style
661  {
662  if ( pyjets.k[2][iprt2] != parent )
663  {
664  parent = pyjets.k[2][iprt2];
665  break; // another parent particle; reset & break the loop
666  }
667 
668  HepMC::FourVector pmomN(pyjets.p[0][iprt2],pyjets.p[1][iprt2],
669  pyjets.p[2][iprt2],pyjets.p[3][iprt2] );
670 
671  dstatus = 0;
672  if ( pyjets.k[0][iprt2] >= 1 && pyjets.k[0][iprt2] <= 10 )
673  {
674  dstatus = 1;
675  }
676  else if ( pyjets.k[0][iprt2] >= 11 && pyjets.k[0][iprt2] <= 20 )
677  {
678  dstatus = 2;
679  }
680  else if ( pyjets.k[0][iprt2] >= 21 && pyjets.k[0][iprt2] <= 30 )
681  {
682  dstatus = 3;
683  }
684  else if ( pyjets.k[0][iprt2] >= 31 && pyjets.k[0][iprt2] <= 100 )
685  {
686  dstatus = pyjets.k[0][iprt2];
687  }
688  HepMC::GenParticle* daughterN = new HepMC::GenParticle(pmomN,
689  HepPID::translatePythiatoPDT( pyjets.k[1][iprt2] ),
690  dstatus);
691  barcode++;
692  daughterN->suggest_barcode( barcode );
693  DecVtx->add_particle_out( daughterN );
694  }
695 
696  iprt1 = iprt2-1; // reset counter such that it doesn't go over the same child more than once
697  // don't forget to offset back into c++ counting, as it's already +1 forward
698 
699  event().get()->add_vertex( DecVtx );
700 
701  }
702 
703  }
704 
705  // now restore the very original Py6 event record
706  //
707  if ( pyjets_local.n != pyjets.n )
708  {
709  // restore pyjets to its state as it was before external decays -
710  // might have been jammed by action above or by py1ent calls in EvtGen
711  pyjets.n = pyjets_local.n;
712  pyjets.npad = pyjets_local.npad;
713  for ( int ip=0; ip<pyjets_local.n; ip++ )
714  {
715  for ( int i=0; i<5; i++ )
716  {
717  pyjets.k[i][ip] = pyjets_local.k[i][ip];
718  pyjets.p[i][ip] = pyjets_local.p[i][ip];
719  pyjets.v[i][ip] = pyjets_local.v[i][ip];
720  }
721  }
722  }
723 
724  return true;
725 }
726 
728 {
729 
730  Pythia6Service::InstanceWrapper guard(fPy6Service); // grab Py6 instance
731 
733  if ( key == 0 ) fPy6Service->setCSAParams();
735 
736  return true;
737 
738 }
739 
741 {
742  Pythia6Service::InstanceWrapper guard(fPy6Service); // grab Py6 instance
743 
744  // note: CSA mode is NOT supposed to work with external partons !!!
745 
746  // fPy6Service->setGeneralParams();
747 
749 
751 
752  if ( fStopHadronsEnabled )
753  {
754  // overwrite mstp(111), no matter what
755  call_pygive("MSTP(111)=0");
756  pystrhad_();
757  call_pygive("MWID(302)=0"); // I don't know if this is specific to processing ME/LHE only,
758  call_pygive("MDCY(302,1)=0"); // or this should also be the case for full event...
759  // anyway, this comes from experience of processing MG events
760  }
761 
762  if ( fGluinoHadronsEnabled )
763  {
764  // overwrite mstp(111), no matter what
765  call_pygive("MSTP(111)=0");
766  pyglrhad_();
767  //call_pygive("MWID(309)=0");
768  //call_pygive("MDCY(309,1)=0");
769  }
770 
771  call_pyinit("USER", "", "", 0.0);
772 
774 
775  std::vector<std::string> slha = lheRunInfo()->findHeader("slha");
776  if (!slha.empty()) {
777  edm::LogInfo("Generator|LHEInterface")
778  << "Pythia6 hadronisation found an SLHA header, "
779  << "will be passed on to Pythia." << std::endl;
782  }
783 
784  if ( fJetMatching )
785  {
787 // FIXME: the jet matching routine might not be interested in PS callback
788  call_pygive("MSTP(143)=1");
789  }
790 
791  return true;
792 }
793 
795 {
796 
797  Pythia6Service::InstanceWrapper guard(fPy6Service); // grab Py6 instance
798 
800 
801  if ( fStopHadronsEnabled )
802  {
803  // overwrite mstp(111), no matter what
804  call_pygive("MSTP(111)=0");
805  pystrhad_();
806  }
807 
808  if ( fGluinoHadronsEnabled )
809  {
810  // overwrite mstp(111), no matter what
811  call_pygive("MSTP(111)=0");
812  pyglrhad_();
813  }
814 
815  if ( fInitialState == PP ) // default
816  {
817  call_pyinit("CMS", "p", "p", fCOMEnergy);
818  }
819  else if ( fInitialState == PPbar )
820  {
821  call_pyinit( "CMS", "p", "pbar", fCOMEnergy);
822  }
823  else if ( fInitialState == ElectronPositron )
824  {
825  call_pyinit( "CMS", "e+", "e-", fCOMEnergy );
826  }
827  else if ( fInitialState == ElectronProton)
828  {
829  // set p(1,i) & p(2,i) for the beams in pyjets !
830  pyjets.p[0][0] = 0.;
831  pyjets.p[1][0] = 0.;
832  pyjets.p[2][0] = fBeam1PZ;
833  pyjets.p[0][1] = 0.;
834  pyjets.p[1][1] = 0.;
835  pyjets.p[2][1] = fBeam2PZ;
836  // call "3mon" frame & 0.0 win
837  call_pyinit( "3mom", "e-", "p", 0.0 );
838  }
839  else if ( fInitialState == PositronProton)
840  {
841  // set p(1,i) & p(2,i) for the beams in pyjets !
842  pyjets.p[0][0] = 0.;
843  pyjets.p[1][0] = 0.;
844  pyjets.p[2][0] = fBeam1PZ;
845  pyjets.p[0][1] = 0.;
846  pyjets.p[1][1] = 0.;
847  pyjets.p[2][1] = fBeam2PZ;
848  // call "3mon" frame & 0.0 win
849  call_pyinit( "3mom", "e+", "p", 0.0 );
850  }
851  else
852  {
853  // throw on unknown initial state !
854  throw edm::Exception(edm::errors::Configuration,"Pythia6Interface")
855  <<" UNKNOWN INITIAL STATE. \n The allowed initial states are: PP, PPbar, ElectronPositron, ElectronProton, and PositronProton \n";
856  }
857 
858 
860 
862 
863  return true;
864 }
865 
866 bool Pythia6Hadronizer::declareStableParticles( const std::vector<int> pdg )
867 {
868 
869  for ( unsigned int i=0; i<pdg.size(); i++ )
870  {
871  int PyID = HepPID::translatePDTtoPythia( pdg[i] );
872  // int PyID = pdg[i];
873  int pyCode = pycomp_( PyID );
874  if ( pyCode > 0 )
875  {
876  std::ostringstream pyCard ;
877  pyCard << "MDCY(" << pyCode << ",1)=0";
878 /* this is a test printout...
879  std::cout << "pdg= " << pdg[i] << " " << pyCard.str() << std::endl;
880 */
881  call_pygive( pyCard.str() );
882  }
883  }
884 
885  return true;
886 }
887 
888 bool Pythia6Hadronizer::declareSpecialSettings( const std::vector<std::string> settings )
889 {
890 
891  for ( unsigned int iss=0; iss<settings.size(); iss++ )
892  {
893  if ( settings[iss].find("QED-brem-off") == std::string::npos ) continue;
894  size_t fnd1 = settings[iss].find(":");
895  if ( fnd1 == std::string::npos ) continue;
896 
897  std::string value = settings[iss].substr (fnd1+1);
898 
899  if ( value == "all" )
900  {
901  call_pygive( "MSTJ(41)=3" );
902  }
903  else
904  {
905  int number = atoi(value.c_str());
906  int PyID = HepPID::translatePDTtoPythia( number );
907  int pyCode = pycomp_( PyID );
908  if ( pyCode > 0 )
909  {
910 
911  // first of all, check if mstj(39) is 0 or if we're trying to override user's setting
912  // if so, throw an exception and stop, because otherwise the user will get behaviour
913  // that's different from what she/he expects !
914  if ( pydat1_.mstj[38] > 0 && pydat1_.mstj[38] != pyCode )
915  {
916  throw edm::Exception(edm::errors::Configuration,"Pythia6Interface")
917  << " Fatal conflict: \n mandatory internal directive to set MSTJ(39)=" << pyCode
918  << " overrides user setting MSTJ(39)=" << pydat1_.mstj[38] << " - user will not get expected behaviour \n";
919  }
920  std::ostringstream pyCard ;
921  pyCard << "MSTJ(39)=" << pyCode ;
922  call_pygive( pyCard.str() );
923  }
924  }
925  }
926 
927  return true;
928 
929 }
930 
932 {
933 
934  // this is practically a copy/paste of the original code by J.Alcaraz,
935  // taken directly from PythiaSource
936 
937  int dumm=0;
938  HepMC::GenEvent::vertex_const_iterator vbegin = event()->vertices_begin();
939  HepMC::GenEvent::vertex_const_iterator vend = event()->vertices_end();
940  HepMC::GenEvent::vertex_const_iterator vitr = vbegin;
941  for (; vitr != vend; ++vitr )
942  {
943  HepMC::GenVertex::particle_iterator pbegin = (*vitr)->particles_begin(HepMC::children);
944  HepMC::GenVertex::particle_iterator pend = (*vitr)->particles_end(HepMC::children);
945  HepMC::GenVertex::particle_iterator pitr = pbegin;
946  for (; pitr != pend; ++pitr)
947  {
948  if ((*pitr)->end_vertex()) continue;
949  if ((*pitr)->status()!=1) continue;
950 
951  int pdgcode= abs((*pitr)->pdg_id());
952  // Do nothing if the particle is not expected to decay
953  if ( pydat3.mdcy[0][pycomp_(pdgcode)-1] !=1 ) continue;
954 
955  double ctau = pydat2.pmas[3][pycomp_(pdgcode)-1];
956  HepMC::FourVector mom = (*pitr)->momentum();
957  HepMC::FourVector vin = (*vitr)->position();
958  double x = 0.;
959  double y = 0.;
960  double z = 0.;
961  double t = 0.;
962  bool decayInRange = false;
963  while (!decayInRange)
964  {
965  double unif_rand = fPy6Service->call(pyr_, &dumm);
966  // Value of 0 is excluded, so following line is OK
967  double proper_length = - ctau * log(unif_rand);
968  double factor = proper_length/mom.m();
969  x = vin.x() + factor * mom.px();
970  y = vin.y() + factor * mom.py();
971  z = vin.z() + factor * mom.pz();
972  t = vin.t() + factor * mom.e();
973  // Decay must be happen outside a cylindrical region
974  if (pydat1.mstj[21]==4) {
975  if (std::sqrt(x*x+y*y)>pydat1.parj[72] || fabs(z)>pydat1.parj[73]) decayInRange = true;
976  // Decay must be happen outside a given sphere
977  }
978  else if (pydat1.mstj[21]==3) {
979  if (std::sqrt(x*x+y*y+z*z)>pydat1.parj[71]) decayInRange = true;
980  }
981  // Decay is always OK otherwise
982  else {
983  decayInRange = true;
984  }
985  }
986 
987  HepMC::GenVertex* vdec = new HepMC::GenVertex(HepMC::FourVector(x,y,z,t));
988  event()->add_vertex(vdec);
989  vdec->add_particle_in((*pitr));
990  }
991  }
992 
993  return;
994 
995 }
996 
998 {
999 
1000  if ( !runInfo().internalXSec() )
1001  {
1002  // set xsec if not already done (e.g. from LHE cross section collector)
1003  double cs = pypars.pari[0]; // cross section in mb
1004  cs *= 1.0e9; // translate to pb (CMS/Gen "convention" as of May 2009)
1005  runInfo().setInternalXSec( cs );
1006 // FIXME: can we get the xsec statistical error somewhere?
1007  }
1008 
1009  call_pystat(1);
1010 
1011  return;
1012 
1013 }
1014 
1015 const char* Pythia6Hadronizer::classname() const
1016 {
1017  return "gen::Pythia6Hadronizer";
1018 }
1019 
1020 } // namespace gen
#define pydat1
static struct gen::@232 pyjets_local
T getParameter(std::string const &) const
static std::auto_ptr< JetMatching > create(const edm::ParameterSet &params)
Definition: JetMatching.cc:47
T getUntrackedParameter(std::string const &, T const &) const
int i
Definition: DBlmapReader.cc:9
auto_ptr< ClusterSequence > cs
void call(void(&fn)())
list parent
Definition: dbtoconf.py:74
unsigned int fPythiaListVerbosity
Pythia6ServiceWithCallback(const edm::ParameterSet &ps)
unsigned int fMaxEventsToPrint
static HepMC::IO_HEPEVT conv
void fillEventInfo(HepMC::GenEvent *hepmc) const
Definition: LHEEvent.cc:245
static JetMatching * getJetMatching()
struct HEPEUP_ hepeup_
bool call_pygive(const std::string &line)
bool exists(std::string const &parameterName) const
checks if a parameter exists
const char * classname() const
#define abs(x)
Definition: mlp_lapack.h:159
void setLHERunInfo(lhef::LHERunInfo *lheri)
void count(LHERunInfo::CountMode count, double weight=1.0, double matchWeight=1.0)
Definition: LHEEvent.cc:203
virtual void beforeHadronisation(const lhef::LHEEvent *event)
Definition: JetMatching.cc:31
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:7
bool declareSpecialSettings(const std::vector< std::string >)
void setInternalXSec(const XSec &xsec)
#define vend()
Definition: vmac.h:42
void pyglrhad_()
double double double z
double v[5][pyjets_maxn]
std::auto_ptr< HepMC::GenEvent > & event()
#define pypars
GenRunInfoProduct & runInfo()
double p[5][pyjets_maxn]
void call_pylist(int mode)
void resetMatchingStatus()
Definition: JetMatching.h:66
lhef::LHEEvent * lheEvent()
T sqrt(T t)
Definition: SSEVec.h:46
void setSLHAFromHeader(const std::vector< std::string > &lines)
#define vbegin()
Definition: vmac.h:35
void fillPdfInfo(HepMC::PdfInfo *info) const
Definition: LHEEvent.cc:217
#define pyint1
void pydecy_(int &ip)
void setPYUPDAParams(bool afterPyinit)
void pystfr_(int &)
Pythia6Hadronizer(edm::ParameterSet const &ps)
std::auto_ptr< GenEventInfoProduct > & eventInfo()
lhef::LHERunInfo * lheRunInfo()
int k[5][pyjets_maxn]
static FortranCallback * getInstance()
int pycomp_(int &)
Pythia6Service * fPy6Service
void setLHEEvent(lhef::LHEEvent *lhee)
part
Definition: HCALResponse.h:21
virtual void beforeHadronisationExec()
Definition: JetMatching.cc:35
bool isMatchingDone()
Definition: JetMatching.h:67
void pyglfr_()
struct gen::@264 pydat1_
list key
Definition: combine.py:13
virtual int match(const HepMC::GenEvent *partonLevel, const HepMC::GenEvent *finalState, bool showeredFinalState=false)=0
tuple cout
Definition: gather_cfg.py:121
std::vector< std::string > findHeader(const std::string &tag) const
Definition: LHERunInfo.cc:390
Definition: DDAxes.h:10
tuple status
Definition: ntuplemaker.py:245
double pyr_(int *idummy)
virtual void init(const lhef::LHERunInfo *runInfo)
Definition: JetMatching.cc:27
bool declareStableParticles(const std::vector< int >)
void pystrhad_()
static JetMatching * fJetMatching