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