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 and coloured jNow or photon only
161  if (!e[jNow].isFinal()) continue;
162  if (e[jNow].colType() == 0 && e[jNow].id() != 22) continue;
163 
164  // POWHEG
165  if (pTdefMode == 0 || pTdefMode == 1) {
166 
167  // ISR - only done once as just kinematical pT
168  if (!FSR) {
169  pTnow = pTpowheg(e, iInA, jNow, (pTdefMode == 0) ? false : FSR);
170  if (pTnow > 0.) pTemt = (pTemt < 0) ? pTnow : std::min(pTemt, pTnow);
171 
172  // FSR - try all outgoing partons from system before branching
173  // as i. Note that for the hard system, there is no
174  // "before branching" information.
175  } else {
176 
177  int outSize = partonSystemsPtr->sizeOut(0);
178  for (int iMem = 0; iMem < outSize; iMem++) {
179  int iNow = partonSystemsPtr->getOut(0, iMem);
180 
181  // Coloured only, i != jNow and no carbon copies
182  if (iNow == jNow || e[iNow].colType() == 0) continue;
183  if (jNow == e[iNow].daughter1()
184  && jNow == e[iNow].daughter2()) continue;
185 
186  pTnow = pTpowheg(e, iNow, jNow, (pTdefMode == 0)
187  ? false : FSR);
188  if (pTnow > 0.) pTemt = (pTemt < 0)
189  ? pTnow : std::min(pTemt, pTnow);
190  } // for (iMem)
191 
192  } // if (!FSR)
193 
194  // Pythia
195  } else if (pTdefMode == 2) {
196 
197  // ISR - other incoming as recoiler
198  if (!FSR) {
199  pTnow = pTpythia(e, iInA, jNow, iInB, FSR);
200  if (pTnow > 0.) pTemt = (pTemt < 0) ? pTnow : std::min(pTemt, pTnow);
201  pTnow = pTpythia(e, iInB, jNow, iInA, FSR);
202  if (pTnow > 0.) pTemt = (pTemt < 0) ? pTnow : std::min(pTemt, pTnow);
203 
204  // FSR - try all final-state coloured partons as radiator
205  // after emission (k).
206  } else {
207  for (int kNow = 0; kNow < e.size(); kNow++) {
208  if (kNow == jNow || !e[kNow].isFinal() ||
209  e[kNow].colType() == 0) continue;
210 
211  // For this kNow, need to have a recoiler.
212  // Try two incoming.
213  pTnow = pTpythia(e, kNow, jNow, iInA, FSR);
214  if (pTnow > 0.) pTemt = (pTemt < 0)
215  ? pTnow : std::min(pTemt, pTnow);
216  pTnow = pTpythia(e, kNow, jNow, iInB, FSR);
217  if (pTnow > 0.) pTemt = (pTemt < 0)
218  ? pTnow : std::min(pTemt, pTnow);
219 
220  // Try all other outgoing.
221  for (int rNow = 0; rNow < e.size(); rNow++) {
222  if (rNow == kNow || rNow == jNow ||
223  !e[rNow].isFinal() || e[rNow].colType() == 0) continue;
224  pTnow = pTpythia(e, kNow, jNow, rNow, FSR);
225  if (pTnow > 0.) pTemt = (pTemt < 0)
226  ? pTnow : std::min(pTemt, pTnow);
227  } // for (rNow)
228 
229  } // for (kNow)
230  } // if (!FSR)
231  } // if (pTdefMode)
232  } // for (j)
233  }
234  } // for (xSR)
235 
236 #ifdef DBGOUTPUT
237  std::cout << "pTcalc: i = " << i << ", j = " << j << ", k = " << k
238  << ", r = " << r << ", xSR = " << xSRin
239  << ", pTemt = " << pTemt << std::endl;
240 #endif
241 
242  return pTemt;
243 }
244 
245 //--------------------------------------------------------------------------
246 
247 // Extraction of pThard based on the incoming event.
248 // Assume that all the final-state particles are in a continuous block
249 // at the end of the event and the final entry is the POWHEG emission.
250 // If there is no POWHEG emission, then pThard is set to QRen.
251 
252 bool EmissionVetoHook1::doVetoMPIStep(int nMPI, const Pythia8::Event &e) {
253  // Extra check on nMPI
254  if (nMPI > 1) return false;
255 
256  // Find if there is a POWHEG emission. Go backwards through the
257  // event record until there is a non-final particle. Also sum pT and
258  // find pT_1 for possible MPI vetoing
259  int count = 0, inonfinal = 0;
260  double pT1 = 0., pTsum = 0.;
261  for (int i = e.size() - 1; i > 0; i--) {
262  inonfinal = i;
263  if (e[i].isFinal()) {
264  count++;
265  pT1 = e[i].pT();
266  pTsum += e[i].pT();
267  } else break;
268  }
269 
270  nFinal = nFinalExt;
271 
272  if (nFinal < 0) { // nFinal is not specified from external, try to find out
273  int first = -1, myid;
274  int last = -1;
275  for(int ip = 2; ip < e.size(); ip++) {
276  myid = e[ip].id();
277  if(abs(myid) < 6 || abs(myid) == 21) continue;
278  first = ip;
279  break;
280  }
281  if(first < 0) fatalEmissionVeto(std::string("signal particles not found"));
282  for(int ip = first; ip < e.size(); ip++) {
283  myid = e[ip].id();
284  if(abs(myid) < 6 || abs(myid) == 21) continue;
285  last = ip;
286  }
287  nFinal = last - inonfinal;
288  }
289 
290  // Extra check that we have the correct final state
291  if (count != nFinal && count != nFinal + 1)
292  fatalEmissionVeto(std::string("Wrong number of final state particles in event"));
293 
294  // Flag if POWHEG radiation present and index
295  bool isEmt = (count == nFinal) ? false : true;
296  int iEmt = (isEmt) ? e.size() - 1 : -1;
297 
298  // If there is no radiation or if pThardMode is 0 then set pThard to QRen.
299  if (!isEmt || pThardMode == 0) {
300  pThard = infoPtr->QRen();
301 
302  // If pThardMode is 1 then the pT of the POWHEG emission is checked against
303  // all other incoming and outgoing partons, with the minimal value taken
304  } else if (pThardMode == 1) {
305  pThard = pTcalc(e, -1, iEmt, -1, -1, -1);
306 
307  // If pThardMode is 2, then the pT of all final-state partons is checked
308  // against all other incoming and outgoing partons, with the minimal value
309  // taken
310  } else if (pThardMode == 2) {
311  pThard = pTcalc(e, -1, -1, -1, -1, -1);
312 
313  }
314 
315  // Find MPI veto pT if necessary
316  if (MPIvetoOn) {
317  pTMPI = (isEmt) ? pTsum / 2. : pT1;
318  }
319 
320  if(Verbosity)
321  std::cout << "doVetoMPIStep: QFac = " << infoPtr->QFac()
322  << ", QRen = " << infoPtr->QRen()
323  << ", pThard = " << pThard << std::endl << std::endl;
324 
325  // Initialise other variables
326  accepted = false;
327  nAcceptSeq = 0;
328 
329  // Do not veto the event
330  return false;
331 }
332 
333 //--------------------------------------------------------------------------
334 
335 // ISR veto
336 
337 bool EmissionVetoHook1::doVetoISREmission(int, const Pythia8::Event &e, int iSys) {
338  // Must be radiation from the hard system
339  if (iSys != 0) return false;
340 
341  // If we already have accepted 'vetoCount' emissions in a row, do nothing
342  if (vetoOn && nAcceptSeq >= vetoCount) return false;
343 
344  // Pythia radiator after, emitted and recoiler after.
345  int iRadAft = -1, iEmt = -1, iRecAft = -1;
346  for (int i = e.size() - 1; i > 0; i--) {
347  if (iRadAft == -1 && e[i].status() == -41) iRadAft = i;
348  else if (iEmt == -1 && e[i].status() == 43) iEmt = i;
349  else if (iRecAft == -1 && e[i].status() == -42) iRecAft = i;
350  if (iRadAft != -1 && iEmt != -1 && iRecAft != -1) break;
351  }
352  if (iRadAft == -1 || iEmt == -1 || iRecAft == -1) {
353  e.list();
354  fatalEmissionVeto(std::string("Couldn't find Pythia ISR emission"));
355  }
356 
357  // pTemtMode == 0: pT of emitted w.r.t. radiator
358  // pTemtMode == 1: std::min(pT of emitted w.r.t. all incoming/outgoing)
359  // pTemtMode == 2: std::min(pT of all outgoing w.r.t. all incoming/outgoing)
360  int xSR = (pTemtMode == 0) ? 0 : -1;
361  int i = (pTemtMode == 0) ? iRadAft : -1;
362  int j = (pTemtMode != 2) ? iEmt : -1;
363  int k = -1;
364  int r = (pTemtMode == 0) ? iRecAft : -1;
365  double pTemt = pTcalc(e, i, j, k, r, xSR);
366 
367 #ifdef DBGOUTPUT
368  std::cout << "doVetoISREmission: pTemt = " << pTemt << std::endl << std::endl;
369 #endif
370 
371  // Veto if pTemt > pThard
372  if (pTemt > pThard) {
373  nAcceptSeq = 0;
374  nISRveto++;
375  return true;
376  }
377 
378  // Else mark that an emission has been accepted and continue
379  nAcceptSeq++;
380  accepted = true;
381  return false;
382 }
383 
384 //--------------------------------------------------------------------------
385 
386 // FSR veto
387 
388 bool EmissionVetoHook1::doVetoFSREmission(int, const Pythia8::Event &e, int iSys, bool) {
389  // Must be radiation from the hard system
390  if (iSys != 0) return false;
391 
392  // If we already have accepted 'vetoCount' emissions in a row, do nothing
393  if (vetoOn && nAcceptSeq >= vetoCount) return false;
394 
395  // Pythia radiator (before and after), emitted and recoiler (after)
396  int iRecAft = e.size() - 1;
397  int iEmt = e.size() - 2;
398  int iRadAft = e.size() - 3;
399  int iRadBef = e[iEmt].mother1();
400  if ( (e[iRecAft].status() != 52 && e[iRecAft].status() != -53) ||
401  e[iEmt].status() != 51 || e[iRadAft].status() != 51) {
402  e.list();
403  fatalEmissionVeto(std::string("Couldn't find Pythia FSR emission"));
404  }
405 
406  // Behaviour based on pTemtMode:
407  // 0 - pT of emitted w.r.t. radiator before
408  // 1 - std::min(pT of emitted w.r.t. all incoming/outgoing)
409  // 2 - std::min(pT of all outgoing w.r.t. all incoming/outgoing)
410  int xSR = (pTemtMode == 0) ? 1 : -1;
411  int i = (pTemtMode == 0) ? iRadBef : -1;
412  int k = (pTemtMode == 0) ? iRadAft : -1;
413  int r = (pTemtMode == 0) ? iRecAft : -1;
414 
415  // When pTemtMode is 0 or 1, iEmt has been selected
416  double pTemt = -1.;
417  if (pTemtMode == 0 || pTemtMode == 1) {
418  // Which parton is emitted, based on emittedMode:
419  // 0 - Pythia definition of emitted
420  // 1 - Pythia definition of radiated after emission
421  // 2 - Random selection of emitted or radiated after emission
422  // 3 - Try both emitted and radiated after emission
423  int j = iRadAft;
424  if (emittedMode == 0 || (emittedMode == 2 && rndmPtr->flat() < 0.5)) j++;
425 
426  for (int jLoop = 0; jLoop < 2; jLoop++) {
427  if (jLoop == 0) pTemt = pTcalc(e, i, j, k, r, xSR);
428  else if (jLoop == 1) pTemt = std::min(pTemt, pTcalc(e, i, j, k, r, xSR));
429 
430  // For emittedMode == 3, have tried iRadAft, now try iEmt
431  if (emittedMode != 3) break;
432  if (k != -1) std::swap(j, k); else j = iEmt;
433  }
434 
435  // If pTemtMode is 2, then try all final-state partons as emitted
436  } else if (pTemtMode == 2) {
437  pTemt = pTcalc(e, i, -1, k, r, xSR);
438 
439  }
440 
441 #ifdef DBGOUTPUT
442  std::cout << "doVetoFSREmission: pTemt = " << pTemt << std::endl << std::endl;
443 #endif
444 
445  // Veto if pTemt > pThard
446  if (pTemt > pThard) {
447  nAcceptSeq = 0;
448  nFSRveto++;
449  return true;
450  }
451 
452  // Else mark that an emission has been accepted and continue
453  nAcceptSeq++;
454  accepted = true;
455  return false;
456 }
457 
458 //--------------------------------------------------------------------------
459 
460 // MPI veto
461 
462 bool EmissionVetoHook1::doVetoMPIEmission(int, const Pythia8::Event &e) {
463  if (MPIvetoOn) {
464  if (e[e.size() - 1].pT() > pTMPI) {
465 #ifdef DBGOUTPUT
466  std::cout << "doVetoMPIEmission: pTnow = " << e[e.size() - 1].pT()
467  << ", pTMPI = " << pTMPI << std::endl << std::endl;
468 #endif
469  return true;
470  }
471  }
472  return false;
473 }
474 
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)
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