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