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