CMS 3D CMS Logo

PowhegHooksBB4L.h
Go to the documentation of this file.
1 // PowhegHooksBB4L.h
2 
3 // Author: Tomas Jezo, Markus Seidel and Ben Nachman based on
4 // PowhegHooks.h by Richard Corke
5 
6 #ifndef Pythia8_PowhegHooksBB4L_H
7 #define Pythia8_PowhegHooksBB4L_H
8 
9 // Includes
10 #include "Pythia8/Pythia.h"
11 //#include "Pythia8Plugins/PowhegHooks.h"
12 
13 namespace Pythia8 {
14 
15 //==========================================================================
16 
17 // Use userhooks to veto PYTHIA emissions above the POWHEG scale.
18 
19 class PowhegHooksBB4L : public UserHooks {
20 //class PowhegHooksBB4L : public PowhegHooks {
21 
22 public:
23 
24  // Constructor and destructor.
27 //--------------------------------------------------------------------------
28 
29  // Initialize settings
30  bool initAfterBeams() {
31  // settings of the parent class
32 // PowhegHook::initAfterBeams();
33  // settings of this class
34  onlyDistance1 = settingsPtr->flag("POWHEG:bb4l:onlyDistance1");
35  useScaleResonanceInstead = settingsPtr->flag("POWHEG:bb4l:useScaleResonanceInstead");
36  // variables used during the veto
37  topresscale = -1;
38  atopresscale = -1;
39  return true;
40  }
41 
42 //--------------------------------------------------------------------------
43 
44  // Calculates the scale of the hardest emission from within the resonance system
45  // translated by Markus Seidel modified by Tomas Jezo
46  inline double findresscale( const int iRes, const Event& event) {
47  double scale = 0.;
48 
49  int nDau = event[iRes].daughterList().size();
50 
51  if (nDau == 0) {
52  // No resonance found, set scale to high value
53  // Pythia will shower any MC generated resonance unrestricted
54  scale = 1e30;
55  }
56  else if (nDau < 3) {
57  // No radiating resonance found
58  scale = 0.8;
59  }
60  else if (std::abs(event[iRes].id()) == 6) {
61  // Find top daughters
62  int idw = -1, idb = -1, idg = -1;
63 
64  for (int i = 0; i < nDau; i++) {
65  int iDau = event[iRes].daughterList()[i];
66  if (std::abs(event[iDau].id()) == 24) idw = iDau;
67  if (std::abs(event[iDau].id()) == 5) idb = iDau;
68  if (std::abs(event[iDau].id()) == 21) idg = iDau;
69  }
70 
71  // Get daughter 4-vectors in resonance frame
72  Vec4 pw(event[idw].p());
73  pw.bstback(event[iRes].p());
74 
75  Vec4 pb(event[idb].p());
76  pb.bstback(event[iRes].p());
77 
78  Vec4 pg(event[idg].p());
79  pg.bstback(event[iRes].p());
80 
81  // Calculate scale
82  scale = sqrt(2*pg*pb*pg.e()/pb.e());
83  }
84  else {
85  scale = 1e30;
86  }
87 
88  return scale;
89  }
90 
91 //--------------------------------------------------------------------------
92 
93  // The following routine will match daughters of particle `e[iparticle]` to an expected pattern specified via the list of expected particle PDG ID's `ids`,
94  // id wildcard is specified as 0 if match is obtained, the positions and the momenta of these particles are returned in vectors `positions` and `momenta`
95  // respectively
96  // if exitOnExtraLegs==true, it will exit if the decay has more particles than expected, but not less
97  inline bool match_decay(int iparticle, const Event &e, const vector<int> &ids, vector<int> &positions, vector<Vec4> &momenta, bool exitOnExtraLegs = true){
98  // compare sizes
99  if (e[iparticle].daughterList().size() != ids.size()) {
100  if (exitOnExtraLegs && e[iparticle].daughterList().size() > ids.size()) exit(-1);
101  return false;
102  }
103  // compare content
104  for (unsigned int i = 0; i < e[iparticle].daughterList().size(); i++) {
105  int di = e[iparticle].daughterList()[i];
106  if (ids[i] != 0 && e[di].id() != ids[i])
107  return false;
108  }
109  // reset the positions and momenta vectors (because they may be reused)
110  positions.clear();
111  momenta.clear();
112  // construct the array of momenta
113  for (unsigned int i = 0; i < e[iparticle].daughterList().size(); i++) {
114  int di = e[iparticle].daughterList()[i];
115  positions.push_back(di);
116  momenta.push_back(e[di].p());
117  }
118  return true;
119  }
120 
121  inline double qSplittingScale(Vec4 pt, Vec4 p1, Vec4 p2){
122  p1.bstback(pt);
123  p2.bstback(pt);
124  return sqrt( 2*p1*p2*p2.e()/p1.e() );
125  }
126 
127  inline double gSplittingScale(Vec4 pt, Vec4 p1, Vec4 p2){
128  p1.bstback(pt);
129  p2.bstback(pt);
130  return sqrt( 2*p1*p2*p1.e()*p2.e()/(pow(p1.e(),2)+pow(p2.e(),2)) );
131  }
132 
133 
134  inline double getdechardness(int topcharge, const Event &e){
135  // construct pdg ids of top and its decay products
136  int tid = 6*topcharge, wid = 24*topcharge, bid = 5*topcharge, gid = 21, wildcard = 0;
137  // find last top in the record
138  int i_top = -1;
139  Vec4 p_top, p_b, p_g, p_g1, p_g2;
140  for (int i = 0; i < e.size(); i++)
141  if (e[i].id() == tid) {
142  i_top = i;
143  p_top = e[i].p();
144  }
145  if (i_top == -1) return -1.0;
146 
147  // summary of cases
148  // 1.) t > W b
149  // a.) b > 3 ... error
150  // b.) b > b g ... h = sqrt(2*p_g*p_b*p_g.e()/p_b.e())
151  // c.) b > other ... h = -1
152  // return h
153  // 2.) t > W b g
154  // a.) b > 3 ... error
155  // b.) b > b g ... h1 = sqrt(2*p_g*p_b*p_g.e()/p_b.e())
156  // c.) b > other ... h1 = -1
157  // i.) g > 3 ... error
158  // ii.) g > 2 ... h2 = sqrt(2*p_g1*p_g2*p_g1.e()*p_g2.e()/(pow(p_g1.e(),2)+pow(p_g2.e(),2))) );
159  // iii.) g > other ... h2 = -1
160  // return max(h1,h2)
161  // 3.) else ... error
162 
163  vector<Vec4> momenta;
164  vector<int> positions;
165 
166  // 1.) t > b W
167  if ( match_decay(i_top, e, vector<int> {wid, bid}, positions, momenta, false) ) {
168  double h;
169  int i_b = positions[1];
170  // a.+b.) b > 3 or b > b g
171  if ( match_decay(i_b, e, vector<int> {bid, gid}, positions, momenta) )
172  h = qSplittingScale(e[i_top].p(), momenta[0], momenta[1]);
173  // c.) b > other
174  else
175  h = -1;
176  return h;
177  }
178  // 2.) t > b W g
179  else if ( match_decay(i_top, e, vector<int> {wid, bid, gid}, positions, momenta, false) ) {
180  double h1, h2;
181  int i_b = positions[1], i_g = positions[2];
182  // a.+b.) b > 3 or b > b g
183  if ( match_decay(i_b, e, vector<int> {bid, gid}, positions, momenta) )
184  h1 = qSplittingScale(e[i_top].p(), momenta[0], momenta[1]);
185  // c.) b > other
186  else
187  h1 = -1;
188  // i.+ii.) g > 3 or g > 2
189  if ( match_decay(i_g, e, vector<int> {wildcard, wildcard}, positions, momenta) )
190  h2 = gSplittingScale(e[i_top].p(), momenta[0], momenta[1]);
191  // c.) b > other
192  else
193  h2 = -1;
194  return max(h1, h2);
195  }
196  // 3.) else
197  else {
198  exit(-1);
199  }
200  }
201 
202 //--------------------------------------------------------------------------
203 
204  // called after shower -- cannot be used for veto, because the event will get discarded
205  inline bool canVetoPartonLevel() { return true; }
206  inline bool doVetoPartonLevel(const Event &e) {
207  double topdechardness = getdechardness(1, e), atopdechardness = getdechardness(-1, e);
208  if ((topdechardness > topresscale) or (atopdechardness > atopresscale)) {
209 // cout << " PYTHIA Warning in PowhegHooksBB4L::doVetoPartonLevel: passed doVetoFSREmission veto, but wouldn't have passed veto based on the full event listing" << endl;
210  infoPtr->errorMsg("Warning in PowhegHooksBB4L::doVetoPartonLevel: passed doVetoFSREmission veto, but wouldn't have passed veto based on the full event listing");
211  }
212 // cout << " veto scales: " << fixed << setprecision(17) << setw(30) << topresscale << setw(30) << atopresscale << endl;
213  topresscale = -1;
214  atopresscale = -1;
215 
216  return false;
217  }
218 
219  // called before each resonance decay shower
220  inline bool canSetResonanceScale() { return true; }
221  inline double scaleResonance(int iRes, const Event &e) {
222  double scale = 1e30;
223  if (e[iRes].id() == 6)
224  scale = topresscale = findresscale(iRes, e);
225  else if (e[iRes].id() == -6)
226  scale = atopresscale = findresscale(iRes, e);
228  return scale;
229  else
230  return 1e30;
231  }
232 
233 //--------------------------------------------------------------------------
234 
235  // FSR veto
236  inline bool canVetoFSREmission() {
238  return false;
239  else
240  return true;
241  }
242  inline bool doVetoFSREmission(int sizeOld, const Event &e, int iSys, bool inResonance) {
243 
244  // call parent PowhegHook veto
245 // if (PowhegHooks::doVectoFSREmission(sizeOld, Event &e, iSys, inResonance)) return true;
246 
247  if (inResonance) {
248 
249  // get the participants of the splitting: the radiator and the emitted
250  int iEmt = e.size() - 2;
251  int iRadAft = e.size() - 3;
252  int iRadBef = e[iEmt].mother1();
253 
254  // find the top resonance the radiator originates from
255  int iTop = e[iRadBef].mother1();
256  int distance = 1;
257  while (std::abs(e[iTop].id()) != 6 && iTop > 0) {
258  iTop = e[iTop].mother1();
259  distance ++;
260  }
261  if (iTop == 0) {
262  infoPtr->errorMsg("Warning in PowhegHooksBB4L::doVetoFSREmission: emission in resonance not from top quark, not vetoing");
263  return false;
264  }
265  int iTopCharge = (e[iTop].id()>0)?1:-1;
266 
267 
268  // calculate the scale of the emission
269  Vec4 pr(e[iRadAft].p()), pe(e[iEmt].p()), pt(e[iTop].p());
270  double scale;
271  // gluon splitting into two partons
272  if (e[iRadBef].id() == 21)
273  scale = gSplittingScale(pt, pr, pe);
274  // quark emitting a gluon
275  else if (std::abs(e[iRadBef].id()) <= 5)
276  scale = qSplittingScale(pt, pr, pe);
277  // other stuff (which we should not veto)
278  else {
279  scale = 0;
280  }
281 
282  if (iTopCharge > 0) {
283  if (onlyDistance1) {
284  if ((distance == 1) && scale > topresscale) {
285  nFSRveto++;
286  return true;
287  }
288  }
289  else
290  if (scale > topresscale) {
291  nFSRveto++;
292  return true;
293  }
294  }
295  else {
296  if (onlyDistance1) {
297  if ((distance == 1) && scale > atopresscale) {
298  nFSRveto++;
299  return true;
300  }
301  }
302  else
303  if (scale > atopresscale) {
304  nFSRveto++;
305  return true;
306  }
307  }
308  }
309  return false;
310  }
311 
312 //--------------------------------------------------------------------------
313 
314  // Functions to return information
315 
316  inline int getNFSRveto() { return nFSRveto; }
317 
318 //--------------------------------------------------------------------------
319 
320 private:
321  int nFSRveto = 0;
324 };
325 
326 //==========================================================================
327 
328 } // end namespace Pythia8
329 
330 #endif // end Pythia8_PowhegHooksBB4L_H
size
Write out results.
bool doVetoFSREmission(int sizeOld, const Event &e, int iSys, bool inResonance)
FWCore Framework interface EventSetupRecordImplementation h
Helper function to determine trigger accepts.
ExtVec< T, 4 > Vec4
Definition: ExtVec.h:62
double qSplittingScale(Vec4 pt, Vec4 p1, Vec4 p2)
double scaleResonance(int iRes, const Event &e)
double getdechardness(int topcharge, const Event &e)
T sqrt(T t)
Definition: SSEVec.h:18
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventID const &, edm::Timestamp const & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double p2[4]
Definition: TauolaWrapper.h:90
double findresscale(const int iRes, const Event &event)
double gSplittingScale(Vec4 pt, Vec4 p1, Vec4 p2)
bool doVetoPartonLevel(const Event &e)
double p1[4]
Definition: TauolaWrapper.h:89
bool match_decay(int iparticle, const Event &e, const vector< int > &ids, vector< int > &positions, vector< Vec4 > &momenta, bool exitOnExtraLegs=true)
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:40
Definition: event.py:1