CMS 3D CMS Logo

EmissionVetoHook1.cc
Go to the documentation of this file.
1 #include "Pythia8/Pythia.h"
2 
3 using namespace Pythia8;
4 
6 
9  throw edm::Exception(edm::errors::Configuration,"Pythia8Interface")
10  << "EmissionVeto: " << message << std::endl;
11 }
12 
13 //--------------------------------------------------------------------------
14 
15 // Routines to calculate the pT (according to pTdefMode) in a splitting:
16 // ISR: i (radiator after) -> j (emitted after) k (radiator before)
17 // FSR: i (radiator before) -> j (emitted after) k (radiator after)
18 // For the Pythia pT definition, a recoiler (after) must be specified.
19 
20 // Compute the Pythia pT separation. Based on pTLund function in History.cc
21 double EmissionVetoHook1::pTpythia(const Pythia8::Event &e, int RadAfterBranch,
22  int EmtAfterBranch, int RecAfterBranch, bool FSR) {
23 
24  // Convenient shorthands for later
25  Pythia8::Vec4 radVec = e[RadAfterBranch].p();
26  Pythia8::Vec4 emtVec = e[EmtAfterBranch].p();
27  Pythia8::Vec4 recVec = e[RecAfterBranch].p();
28  int radID = e[RadAfterBranch].id();
29 
30  // Calculate virtuality of splitting
31  double sign = (FSR) ? 1. : -1.;
32  Pythia8::Vec4 Q(radVec + sign * emtVec);
33  double Qsq = sign * Q.m2Calc();
34 
35  // Mass term of radiator
36  double m2Rad = (abs(radID) >= 4 && abs(radID) < 7) ?
37  Pythia8::pow2(particleDataPtr->m0(radID)) : 0.;
38 
39  // z values for FSR and ISR
40  double z, pTnow;
41  if (FSR) {
42  // Construct 2 -> 3 variables
43  Pythia8::Vec4 sum = radVec + recVec + emtVec;
44  double m2Dip = sum.m2Calc();
45  double x1 = 2. * (sum * radVec) / m2Dip;
46  double x3 = 2. * (sum * emtVec) / m2Dip;
47  z = x1 / (x1 + x3);
48  pTnow = z * (1. - z);
49 
50  } else {
51  // Construct dipoles before/after splitting
52  Pythia8::Vec4 qBR(radVec - emtVec + recVec);
53  Pythia8::Vec4 qAR(radVec + recVec);
54  z = qBR.m2Calc() / qAR.m2Calc();
55  pTnow = (1. - z);
56  }
57 
58  // Virtuality with correct sign
59  pTnow *= (Qsq - sign * m2Rad);
60 
61  // Can get negative pT for massive splittings
62  if (pTnow < 0.) {
63  std::cout << "Warning: pTpythia was negative" << std::endl;
64  return -1.;
65  }
66 
67 #ifdef DBGOUTPUT
68  std::cout << "pTpythia: rad = " << RadAfterBranch << ", emt = "
69  << EmtAfterBranch << ", rec = " << RecAfterBranch
70  << ", pTnow = " << sqrt(pTnow) << std::endl;
71 #endif
72 
73  // Return pT
74  return sqrt(pTnow);
75 }
76 
77 // Compute the POWHEG pT separation between i and j
78 double EmissionVetoHook1::pTpowheg(const Pythia8::Event &e, int i, int j, bool FSR) {
79 
80  // pT value for FSR and ISR
81  double pTnow = 0.;
82  if (FSR) {
83  // POWHEG d_ij (in CM frame). Note that the incoming beams have not
84  // been updated in the parton systems pointer yet (i.e. prior to any
85  // potential recoil).
86  int iInA = partonSystemsPtr->getInA(0);
87  int iInB = partonSystemsPtr->getInB(0);
88  double betaZ = - ( e[iInA].pz() + e[iInB].pz() ) /
89  ( e[iInA].e() + e[iInB].e() );
90  Pythia8::Vec4 iVecBst(e[i].p()), jVecBst(e[j].p());
91  iVecBst.bst(0., 0., betaZ);
92  jVecBst.bst(0., 0., betaZ);
93  pTnow = sqrt( (iVecBst + jVecBst).m2Calc() *
94  iVecBst.e() * jVecBst.e() /
95  Pythia8::pow2(iVecBst.e() + jVecBst.e()) );
96 
97  } else {
98  // POWHEG pT_ISR is just kinematic pT
99  pTnow = e[j].pT();
100  }
101 
102  // Check result
103  if (pTnow < 0.) {
104  std::cout << "Warning: pTpowheg was negative" << std::endl;
105  return -1.;
106  }
107 
108 #ifdef DBGOUTPUT
109  std::cout << "pTpowheg: i = " << i << ", j = " << j
110  << ", pTnow = " << pTnow << std::endl;
111 #endif
112 
113  return pTnow;
114 }
115 
116 // Calculate pT for a splitting based on pTdefMode.
117 // If j is -1, all final-state partons are tried.
118 // If i, k, r and xSR are -1, then all incoming and outgoing
119 // partons are tried.
120 // xSR set to 0 means ISR, while xSR set to 1 means FSR
121 double EmissionVetoHook1::pTcalc(const Pythia8::Event &e, int i, int j, int k, int r, int xSRin) {
122 
123  // Loop over ISR and FSR if necessary
124  double pTemt = -1., pTnow;
125  int xSR1 = (xSRin == -1) ? 0 : xSRin;
126  int xSR2 = (xSRin == -1) ? 2 : xSRin + 1;
127  for (int xSR = xSR1; xSR < xSR2; xSR++) {
128  // FSR flag
129  bool FSR = (xSR == 0) ? false : true;
130 
131  // If all necessary arguments have been given, then directly calculate.
132  // POWHEG ISR and FSR, need i and j.
133  if ((pTdefMode == 0 || pTdefMode == 1) && i > 0 && j > 0) {
134  pTemt = pTpowheg(e, i, j, (pTdefMode == 0) ? false : FSR);
135 
136  // Pythia ISR, need i, j and r.
137  } else if (!FSR && pTdefMode == 2 && i > 0 && j > 0 && r > 0) {
138  pTemt = pTpythia(e, i, j, r, FSR);
139 
140  // Pythia FSR, need k, j and r.
141  } else if (FSR && pTdefMode == 2 && j > 0 && k > 0 && r > 0) {
142  pTemt = pTpythia(e, k, j, r, FSR);
143 
144  // Otherwise need to try all possible combintations.
145  } else {
146  // Start by finding incoming legs to the hard system after
147  // branching (radiator after branching, i for ISR).
148  // Use partonSystemsPtr to find incoming just prior to the
149  // branching and track mothers.
150  int iInA = partonSystemsPtr->getInA(0);
151  int iInB = partonSystemsPtr->getInB(0);
152  while (e[iInA].mother1() != 1) { iInA = e[iInA].mother1(); }
153  while (e[iInB].mother1() != 2) { iInB = e[iInB].mother1(); }
154 
155  // If we do not have j, then try all final-state partons
156  int jNow = (j > 0) ? j : 0;
157  int jMax = (j > 0) ? j + 1 : e.size();
158  for (; jNow < jMax; jNow++) {
159 
160  // Final-state only
161  if (!e[jNow].isFinal()) continue;
162  // Exclude photons (and W/Z!)
163  if (QEDvetoMode==0 && e[jNow].colType() == 0) continue;
164 
165  // POWHEG
166  if (pTdefMode == 0 || pTdefMode == 1) {
167 
168  // ISR - only done once as just kinematical pT
169  if (!FSR) {
170  pTnow = pTpowheg(e, iInA, jNow, (pTdefMode == 0) ? false : FSR);
171  if (pTnow > 0.) pTemt = (pTemt < 0) ? pTnow : std::min(pTemt, pTnow);
172 
173  // FSR - try all outgoing partons from system before branching
174  // as i. Note that for the hard system, there is no
175  // "before branching" information.
176  } else {
177 
178  int outSize = partonSystemsPtr->sizeOut(0);
179  for (int iMem = 0; iMem < outSize; iMem++) {
180  int iNow = partonSystemsPtr->getOut(0, iMem);
181 
182  // if i != jNow and no carbon copies
183  if (iNow == jNow) continue;
184  // Exlude photons (and W/Z!)
185  if (QEDvetoMode==0 && e[iNow].colType() == 0) continue;
186  if (jNow == e[iNow].daughter1()
187  && jNow == e[iNow].daughter2()) continue;
188 
189  pTnow = pTpowheg(e, iNow, jNow, (pTdefMode == 0)
190  ? false : FSR);
191  if (pTnow > 0.) pTemt = (pTemt < 0)
192  ? pTnow : std::min(pTemt, pTnow);
193  } // for (iMem)
194 
195  } // if (!FSR)
196 
197  // Pythia
198  } else if (pTdefMode == 2) {
199 
200  // ISR - other incoming as recoiler
201  if (!FSR) {
202  pTnow = pTpythia(e, iInA, jNow, iInB, FSR);
203  if (pTnow > 0.) pTemt = (pTemt < 0) ? pTnow : std::min(pTemt, pTnow);
204  pTnow = pTpythia(e, iInB, jNow, iInA, FSR);
205  if (pTnow > 0.) pTemt = (pTemt < 0) ? pTnow : std::min(pTemt, pTnow);
206 
207  // FSR - try all final-state coloured partons as radiator
208  // after emission (k).
209  } else {
210  for (int kNow = 0; kNow < e.size(); kNow++) {
211  if (kNow == jNow || !e[kNow].isFinal()) continue;
212  if (QEDvetoMode==0 && e[kNow].colType() == 0) continue;
213 
214  // For this kNow, need to have a recoiler.
215  // Try two incoming.
216  pTnow = pTpythia(e, kNow, jNow, iInA, FSR);
217  if (pTnow > 0.) pTemt = (pTemt < 0)
218  ? pTnow : std::min(pTemt, pTnow);
219  pTnow = pTpythia(e, kNow, jNow, iInB, FSR);
220  if (pTnow > 0.) pTemt = (pTemt < 0)
221  ? pTnow : std::min(pTemt, pTnow);
222 
223  // Try all other outgoing.
224  for (int rNow = 0; rNow < e.size(); rNow++) {
225  if (rNow == kNow || rNow == jNow ||
226  !e[rNow].isFinal()) continue;
227  if(QEDvetoMode==0 && e[rNow].colType() == 0) continue;
228  pTnow = pTpythia(e, kNow, jNow, rNow, FSR);
229  if (pTnow > 0.) pTemt = (pTemt < 0)
230  ? pTnow : std::min(pTemt, pTnow);
231  } // for (rNow)
232 
233  } // for (kNow)
234  } // if (!FSR)
235  } // if (pTdefMode)
236  } // for (j)
237  }
238  } // for (xSR)
239 
240 #ifdef DBGOUTPUT
241  std::cout << "pTcalc: i = " << i << ", j = " << j << ", k = " << k
242  << ", r = " << r << ", xSR = " << xSRin
243  << ", pTemt = " << pTemt << std::endl;
244 #endif
245 
246  return pTemt;
247 }
248 
249 //--------------------------------------------------------------------------
250 
251 // Extraction of pThard based on the incoming event.
252 // Assume that all the final-state particles are in a continuous block
253 // at the end of the event and the final entry is the POWHEG emission.
254 // If there is no POWHEG emission, then pThard is set to QRen.
255 bool EmissionVetoHook1::doVetoMPIStep(int nMPI, const Pythia8::Event &e) {
256 
257  if(nFinalMode == 3 && pThardMode != 0)
258  fatalEmissionVeto(std::string("When nFinalMode is set to 3, ptHardMode should be set to 0, since the emission variables in doVetoMPIStep are not set correctly case when there are three possible particle Born particle counts."));
259 
260  // Extra check on nMPI
261  if (nMPI > 1) return false;
262 
263  // Find if there is a POWHEG emission. Go backwards through the
264  // event record until there is a non-final particle. Also sum pT and
265  // find pT_1 for possible MPI vetoing
266  // Flag if POWHEG radiation is present and index at the same time
267  int count = 0, inonfinal = 0;
268  double pT1 = 0., pTsum = 0.;
269  isEmt = false;
270  int iEmt = -1;
271 
272  for (int i = e.size() - 1; i > 0; i--) {
273  inonfinal = i;
274  if (e[i].isFinal()) {
275  count++;
276  pT1 = e[i].pT();
277  pTsum += e[i].pT();
278  // the following was added for bbbar4l and will be triggered by specifying nfinalmode == 2
279  // the solution provided by Tomas may not be process independent but should work for hvq and bb4l
280  // if the particle is a light quark or a gluon and
281  // comes for a light quark or a gluon (not a resonance, not a top)
282  // then it is the POWHEG emission (hvq) or the POWHEG emission in production (bb4l)
283  if (nFinalMode == 2) {
284  if ((abs(e[i].id()) < 6 || e[i].id() == 21) &&
285  (abs(e[e[i].mother1()].id()) < 6 || e[e[i].mother1()].id() == 21)) {
286  isEmt = true;
287  iEmt = i;
288  }
289  }
290  } else break;
291  }
292 
293  nFinal = nFinalExt;
294  if (nFinal < 0 || nFinalMode == 1) { // nFinal is not specified from external, try to find out
295  int first = -1, myid;
296  int last = -1;
297  for(int ip = 2; ip < e.size(); ip++) {
298  myid = e[ip].id();
299  if(abs(myid) < 6 || abs(myid) == 21) continue;
300  first = ip;
301  break;
302  }
303  if(first < 0) fatalEmissionVeto(std::string("signal particles not found"));
304  for(int ip = first; ip < e.size(); ip++) {
305  myid = e[ip].id();
306  if(abs(myid) < 6 || abs(myid) == 21) continue;
307  last = ip;
308  }
309  nFinal = last - inonfinal;
310  }
311 
312  // don't perform a cross check in case of nfinalmode == 2
313  if (nFinalMode != 2) {
314 
315  // Extra check that we have the correct final state
316  // In POWHEG WGamma, both w+0/1 jets and w+gamma+0/1 jets are generated at the same time, which leads to three different possible numbers of particles
317  // Normally, there would be only two possible numbers of particles for X and X+1 jet
318  if(nFinalMode == 3){
319  if (count != nFinal && count != nFinal + 1 && count != nFinal - 1)
320  fatalEmissionVeto(std::string("Wrong number of final state particles in event"));
321  } else {
322  if (count != nFinal && count != nFinal + 1)
323  fatalEmissionVeto(std::string("Wrong number of final state particles in event"));
324  }
325  // Flag if POWHEG radiation present and index
326  if (count == nFinal + 1) isEmt = true;
327  if (isEmt) iEmt = e.size() - 1;
328  }
329 
330  // If there is no radiation or if pThardMode is 0 then set pThard to QRen.
331  if (!isEmt || pThardMode == 0) {
332  pThard = infoPtr->QRen();
333 
334  // If pThardMode is 1 then the pT of the POWHEG emission is checked against
335  // all other incoming and outgoing partons, with the minimal value taken
336  } else if (pThardMode == 1) {
337  pThard = pTcalc(e, -1, iEmt, -1, -1, -1);
338 
339  // If pThardMode is 2, then the pT of all final-state partons is checked
340  // against all other incoming and outgoing partons, with the minimal value
341  // taken
342  } else if (pThardMode == 2) {
343  pThard = pTcalc(e, -1, -1, -1, -1, -1);
344 
345  }
346 
347  // Find MPI veto pT if necessary
348  if (MPIvetoOn) {
349  pTMPI = (isEmt) ? pTsum / 2. : pT1;
350  }
351 
352  if(Verbosity)
353  std::cout << "doVetoMPIStep: QFac = " << infoPtr->QFac()
354  << ", QRen = " << infoPtr->QRen()
355  << ", pThard = " << pThard << std::endl << std::endl;
356 
357  // Initialise other variables
358  accepted = false;
359  nAcceptSeq = 0; // should not reset nISRveto = nFSRveto = nFSRvetoBB4l here
360 
361  // Do not veto the event
362  return false;
363 }
364 
365 //--------------------------------------------------------------------------
366 
367 // ISR veto
368 
369 bool EmissionVetoHook1::doVetoISREmission(int, const Pythia8::Event &e, int iSys) {
370  // Must be radiation from the hard system
371  if (iSys != 0) return false;
372 
373  // If we already have accepted 'vetoCount' emissions in a row, do nothing
374  if (vetoOn && nAcceptSeq >= vetoCount) return false;
375 
376  // Pythia radiator after, emitted and recoiler after.
377  int iRadAft = -1, iEmt = -1, iRecAft = -1;
378  for (int i = e.size() - 1; i > 0; i--) {
379  if (iRadAft == -1 && e[i].status() == -41) iRadAft = i;
380  else if (iEmt == -1 && e[i].status() == 43) iEmt = i;
381  else if (iRecAft == -1 && e[i].status() == -42) iRecAft = i;
382  if (iRadAft != -1 && iEmt != -1 && iRecAft != -1) break;
383  }
384  if (iRadAft == -1 || iEmt == -1 || iRecAft == -1) {
385  e.list();
386  fatalEmissionVeto(std::string("Couldn't find Pythia ISR emission"));
387  }
388 
389  // pTemtMode == 0: pT of emitted w.r.t. radiator
390  // pTemtMode == 1: std::min(pT of emitted w.r.t. all incoming/outgoing)
391  // pTemtMode == 2: std::min(pT of all outgoing w.r.t. all incoming/outgoing)
392  int xSR = (pTemtMode == 0) ? 0 : -1;
393  int i = (pTemtMode == 0) ? iRadAft : -1;
394  int j = (pTemtMode != 2) ? iEmt : -1;
395  int k = -1;
396  int r = (pTemtMode == 0) ? iRecAft : -1;
397  double pTemt = pTcalc(e, i, j, k, r, xSR);
398 
399 #ifdef DBGOUTPUT
400  std::cout << "doVetoISREmission: pTemt = " << pTemt << std::endl << std::endl;
401 #endif
402 
403  // If a Born configuration, and a colorless FS, and QEDvetoMode=2,
404  // then don't veto photons, W, or Z harder than pThard
405  bool vetoParton = (!isEmt && e[iEmt].colType()==0 && QEDvetoMode==2)
406  ? false: true;
407 
408  // Veto if pTemt > pThard
409  if (pTemt > pThard) {
410  if(!vetoParton) {
411  // Don't veto ANY emissions afterwards
412  nAcceptSeq = vetoCount-1;
413  } else {
414  nAcceptSeq = 0;
415  nISRveto++;
416  return true;
417  }
418  }
419 
420  // Else mark that an emission has been accepted and continue
421  nAcceptSeq++;
422  accepted = true;
423  return false;
424 }
425 
426 //--------------------------------------------------------------------------
427 
428 // FSR veto
429 
430 bool EmissionVetoHook1::doVetoFSREmission(int, const Pythia8::Event &e, int iSys, bool inResonance) {
431 
432  // Must be radiation from the hard system
433  if (iSys != 0) return false;
434 
435  // only use for outside resonance vetos in combination with bb4l:FSREmission:veto
436  if (!inResonance && settingsPtr->flag("POWHEG:bb4l:FSREmission:veto")==1) return false;
437 
438  // If we already have accepted 'vetoCount' emissions in a row, do nothing
439  if (vetoOn && nAcceptSeq >= vetoCount) return false;
440 
441  // Pythia radiator (before and after), emitted and recoiler (after)
442  int iRecAft = e.size() - 1;
443  int iEmt = e.size() - 2;
444  int iRadAft = e.size() - 3;
445  int iRadBef = e[iEmt].mother1();
446  if ( (e[iRecAft].status() != 52 && e[iRecAft].status() != -53) ||
447  e[iEmt].status() != 51 || e[iRadAft].status() != 51) {
448  e.list();
449  fatalEmissionVeto(std::string("Couldn't find Pythia FSR emission"));
450  }
451 
452  // Behaviour based on pTemtMode:
453  // 0 - pT of emitted w.r.t. radiator before
454  // 1 - std::min(pT of emitted w.r.t. all incoming/outgoing)
455  // 2 - std::min(pT of all outgoing w.r.t. all incoming/outgoing)
456  int xSR = (pTemtMode == 0) ? 1 : -1;
457  int i = (pTemtMode == 0) ? iRadBef : -1;
458  int k = (pTemtMode == 0) ? iRadAft : -1;
459  int r = (pTemtMode == 0) ? iRecAft : -1;
460 
461  // When pTemtMode is 0 or 1, iEmt has been selected
462  double pTemt = -1.;
463  if (pTemtMode == 0 || pTemtMode == 1) {
464  // Which parton is emitted, based on emittedMode:
465  // 0 - Pythia definition of emitted
466  // 1 - Pythia definition of radiated after emission
467  // 2 - Random selection of emitted or radiated after emission
468  // 3 - Try both emitted and radiated after emission
469  int j = iRadAft;
470  if (emittedMode == 0 || (emittedMode == 2 && rndmPtr->flat() < 0.5)) j++;
471 
472  for (int jLoop = 0; jLoop < 2; jLoop++) {
473  if (jLoop == 0) pTemt = pTcalc(e, i, j, k, r, xSR);
474  else if (jLoop == 1) pTemt = std::min(pTemt, pTcalc(e, i, j, k, r, xSR));
475 
476  // For emittedMode == 3, have tried iRadAft, now try iEmt
477  if (emittedMode != 3) break;
478  if (k != -1) std::swap(j, k); else j = iEmt;
479  }
480 
481  // If pTemtMode is 2, then try all final-state partons as emitted
482  } else if (pTemtMode == 2) {
483  pTemt = pTcalc(e, i, -1, k, r, xSR);
484 
485  }
486 
487 #ifdef DBGOUTPUT
488  std::cout << "doVetoFSREmission: pTemt = " << pTemt << std::endl << std::endl;
489 #endif
490 
491  // If a Born configuration, and a colorless FS, and QEDvetoMode=2,
492  // then don't veto photons, W, or Z harder than pThard
493  bool vetoParton = (!isEmt && e[iEmt].colType()==0 && QEDvetoMode==2)
494  ? false: true;
495 
496  // Veto if pTemt > pThard
497  if (pTemt > pThard) {
498  if(!vetoParton) {
499  // Don't veto ANY emissions afterwards
500  nAcceptSeq = vetoCount-1;
501  } else {
502  nAcceptSeq = 0;
503  nFSRveto++;
504  return true;
505  }
506  }
507 
508  // Else mark that an emission has been accepted and continue
509  nAcceptSeq++;
510  accepted = true;
511  return false;
512 }
513 
514 //--------------------------------------------------------------------------
515 
516 // MPI veto
517 
518 bool EmissionVetoHook1::doVetoMPIEmission(int, const Pythia8::Event &e) {
519  if (MPIvetoOn) {
520  if (e[e.size() - 1].pT() > pTMPI) {
521 #ifdef DBGOUTPUT
522  std::cout << "doVetoMPIEmission: pTnow = " << e[e.size() - 1].pT()
523  << ", pTMPI = " << pTMPI << std::endl << std::endl;
524 #endif
525  return true;
526  }
527  }
528  return false;
529 }
530 
bool doVetoFSREmission(int, const Pythia8::Event &e, int iSys, bool) override
ExtVec< T, 4 > Vec4
Definition: ExtVec.h:62
bool doVetoISREmission(int, const Pythia8::Event &e, int iSys) override
Verbosity
Definition: Verbosity.h:5
void swap(edm::DataFrameContainer &lhs, edm::DataFrameContainer &rhs)
T sqrt(T t)
Definition: SSEVec.h:18
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
T min(T a, T b)
Definition: MathUtil.h:58
double pTpowheg(const Pythia8::Event &e, int i, int j, bool FSR)
int k[5][pyjets_maxn]
bool doVetoMPIStep(int nMPI, const Pythia8::Event &e) override
double pTcalc(const Pythia8::Event &e, int i, int j, int k, int r, int xSRin)
bool accepted(std::vector< std::string_view > const &, std::string_view)
double pTpythia(const Pythia8::Event &e, int RadAfterBranch, int EmtAfterBranch, int RecAfterBranch, bool FSR)
void fatalEmissionVeto(std::string message)
bool doVetoMPIEmission(int, const Pythia8::Event &e) override