StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
MergingHooks.cc
1 // MergingHooks.cc is a part of the PYTHIA event generator.
2 // Copyright (C) 2014 Torbjorn Sjostrand.
3 // PYTHIA is licenced under the GNU GPL version 2, see COPYING for details.
4 // Please respect the MCnet Guidelines, see GUIDELINES for details.
5 
6 // This file is written by Stefan Prestel.
7 // Function definitions (not found in the header) for the HardProcess and
8 // MergingHooks classes.
9 
10 #include "Pythia8/MergingHooks.h"
11 
12 namespace Pythia8 {
13 
14 //==========================================================================
15 
16 // The HardProcess class.
17 
18 //--------------------------------------------------------------------------
19 
20 // Declaration of hard process class
21 // This class holds information on the desired hard 2->2 process to be merged
22 // This class is a container class for History class use.
23 
24 // Initialisation on the process string
25 
26 void HardProcess::initOnProcess( string process, ParticleData* particleData) {
27  state.init("(hard process)", particleData);
28  translateProcessString(process);
29 }
30 
31 //--------------------------------------------------------------------------
32 
33 // Initialisation on the path to LHE file
34 
35 void HardProcess::initOnLHEF( string LHEfile, ParticleData* particleData) {
36  state.init("(hard process)", particleData);
37  translateLHEFString(LHEfile);
38 }
39 
40 //--------------------------------------------------------------------------
41 
42 // Function to access the LHE file and read relevant information.
43 // The merging scale will be read from the +1 jet sample, called
44 // LHEpath_1.lhe
45 // while the hard process will be read from
46 // LHEpath_0.lhe
47 // Currently, only read from MadEvent- or Sherpa-generated LHE files
48 // is automatic, else the user is asked to supply the necessary
49 // information.
50 
51 void HardProcess::translateLHEFString( string LHEpath){
52 
53  // Open path to LHEF and extract merging scale
54  ifstream infile;
55  infile.open( (char*)( LHEpath +"_0.lhe").c_str());
56 
57  // Check with ME generator has been used
58  int iLine =0;
59  int nLinesMax = 200;
60  string lineGenerator;
61  while( iLine < nLinesMax
62  && lineGenerator.find("SHERPA", 0) == string::npos
63  && lineGenerator.find("POWHEG-BOX", 0) == string::npos
64  && lineGenerator.find("Pythia8", 0) == string::npos
65  && lineGenerator.find("MadGraph", 0) == string::npos){
66  iLine++;
67  lineGenerator = " ";
68  getline(infile,lineGenerator);
69  }
70  infile.close();
71 
72  vector <int> incom;
73  vector <int> inter;
74  vector <int> outgo;
75  // Particle identifiers, ordered in such a way that e.g. the "u"
76  // in a mu is not mistaken for an u quark
77  int inParticleNumbers[] = {
78  // Leptons
79  -11,11,-12,12,-13,13,-14,14,-15,15,-16,16,
80  // Jet container
81  2212,2212,0,0,0,0,
82  // Quarks
83  -1,1,-2,2,-3,3,-4,4,-5,5,-6,6};
84 
85  string inParticleNamesSH[] = {
86  // Leptons
87  "-11","11","-12","12","-13","13","-14","14","-15","15","-16","16",
88  // Jet container
89  "-93","93","-90","90","-91","91",
90  // Quarks
91  "-1","1","-2","2","-3","3","-4","4","-5","5","-6","6"};
92  string inParticleNamesMG[] = {
93  // Leptons
94  "e+","e-","ve~","ve","mu+","mu-","vm~","vm","ta+","ta-","vt~","vt",
95  // Jet container
96  "p~","p","l+","l-","vl~","vl",
97  // Quarks
98  "d~","d","u~","u","s~","s","c~","c","b~","b","t~","t"};
99 
100  // Declare intermediate particle identifiers
101  int interParticleNumbers[] = {
102  // Electroweak gauge bosons
103  22,23,-24,24,25,2400,
104  // Top quarks
105  -6,6,
106  // Dummy index as back-up
107  0,
108  // All squarks
109  -1000001,1000001,-1000002,1000002,-1000003,1000003,-1000004,1000004,
110  -1000005,1000005,-1000006,1000006,-2000001,2000001,-2000002,2000002,
111  -2000003,2000003,-2000004,2000004,-2000005,2000005,-2000006,2000006};
112  // Declare names of intermediate particles
113  string interParticleNamesMG[] = {
114  // Electroweak gauge bosons
115  "a","z","w-","w+","h","W",
116  // Top quarks
117  "t~","t",
118  // Dummy index as back-up
119  "xx",
120  // All squarks
121  "dl~","dl","ul~","ul","sl~","sl","cl~","cl","b1~","b1","t1~","t1",
122  "dr~","dr","ur~","ur","sr~","sr","cr~","cr","b2~","b2","t2~","t2"};
123 
124  // Declare final state particle identifiers
125  int outParticleNumbers[] = {
126  // Leptons
127  -11,11,-12,12,-13,13,-14,14,-15,15,-16,16,
128  // Jet container and lepton containers
129  2212,2212,0,0,0,0,1200,1100,5000,
130  // Quarks
131  -1,1,-2,2,-3,3,-4,4,-5,5,-6,6,
132  // SM uncoloured bosons
133  22,23,-24,24,25,2400,
134  // Neutralino in SUSY
135  1000022,
136  // All squarks
137  -1000001,1000001,-1000002,1000002,-1000003,1000003,-1000004,1000004,
138  -1000005,1000005,-1000006,1000006,-2000001,2000001,-2000002,2000002,
139  -2000003,2000003,-2000004,2000004,-2000005,2000005,-2000006,2000006};
140  // Declare names of final state particles
141  string outParticleNamesMG[] = {
142  // Leptons
143  "e+","e-","ve~","ve","mu+","mu-","vm~","vm","ta+","ta-","vt~","vt",
144  // Jet container and lepton containers
145  "j~","j","l+","l-","vl~","vl","NEUTRINOS","LEPTONS","BQUARKS",
146  // Quarks
147  "d~","d","u~","u","s~","s","c~","c","b~","b","t~","t",
148  // SM uncoloured bosons
149  "a","z","w-","w+","h","W",
150  // Neutralino in SUSY
151  "n1",
152  // All squarks
153  "dl~","dl","ul~","ul","sl~","sl","cl~","cl","b1~","b1","t1~","t1",
154  "dr~","dr","ur~","ur","sr~","sr","cr~","cr","b2~","b2","t2~","t2"};
155 
156  string outParticleNamesSH[] = {
157  // Leptons
158  "-11","11","-12","12","-13","13","-14","14","-15","15","-16","16",
159  // Jet container and lepton containers
160  "-93","93","-90","90","-91","91","0","0","0",
161  // Quarks
162  "-1","1","-2","2","-3","3","-4","4","-5","5","-6","6",
163  // SM uncoloured bosons
164  "22","23","-24","24","25","0",
165  // Neutralino in SUSY
166  "1000022",
167  // All squarks
168  "-1000001","1000001","-1000002","1000002","-1000003","1000003",
169  "-1000004","1000004",
170  "-1000005","1000005","-1000006","1000006","-2000001","2000001",
171  "-2000002","2000002",
172  "-2000003","2000003","-2000004","2000004","-2000005","2000005",
173  "-2000006","2000006"};
174 
175  // Declare size of particle name arrays
176  int nIn = 30;
177  int nInt = 33;
178  int nOut = 64;
179 
180  // Save type of the generator, in order to be able to extract
181  // the tms definition
182  int meGenType = (lineGenerator.find("MadGraph", 0) != string::npos) ? -1
183  : (lineGenerator.find("SHERPA", 0) != string::npos) ? -2
184  : (lineGenerator.find("POWHEG-BOX", 0) != string::npos) ? -3
185  : (lineGenerator.find("Pythia8", 0) != string::npos) ? -4
186  : 0;
187 
188  if (meGenType == -2){
189  // Now read merging scale
190  // Open path to LHEF and extract merging scale
191  infile.open( (char*)( LHEpath +"_1.lhe").c_str());
192  string lineTMS;
193  while(lineTMS.find("NJetFinder ", 0) == string::npos){
194  lineTMS = " ";
195  getline(infile,lineTMS);
196  }
197  infile.close();
198  lineTMS = lineTMS.substr(0,lineTMS.find(" 0.0 ",0));
199  lineTMS = lineTMS.substr(lineTMS.find(" ", 0)+3,lineTMS.size());
200  // Remove whitespaces
201  while(lineTMS.find(" ", 0) != string::npos)
202  lineTMS.erase(lineTMS.begin()+lineTMS.find(" ",0));
203  // Replace d with e
204  if ( lineTMS.find("d", 0) != string::npos)
205  lineTMS.replace(lineTMS.find("d", 0),1,1,'e');
206  tms = atof((char*)lineTMS.c_str());
207 
208  // Now read hard process
209  // Open path to LHEF and extract hard process
210  infile.open( (char*)( LHEpath +"_0.lhe").c_str());
211  string line;
212  while(line.find("Process", 0) == string::npos){
213  line = " ";
214  getline(infile,line);
215  }
216  infile.close();
217  line = line.substr(line.find(" ",0),line.size());
218 
219  // Cut string into incoming and outgoing pieces
220  vector <string> pieces;
221  pieces.push_back( line.substr(0,line.find("->", 0)) );
222  // Do not count additional final jets
223  int end = (line.find("{", 0) != string::npos) ? line.find("{", 0)-2
224  : line.size();
225  pieces.push_back( line.substr(line.find("->", 0)+2, end) );
226 
227  // Get incoming particles
228  for(int i=0; i < nIn; ++i) {
229  for(int n = pieces[0].find(inParticleNamesSH[i], 0);
230  n != int(string::npos);
231  n = pieces[0].find(inParticleNamesSH[i], n)) {
232  incom.push_back(inParticleNumbers[i]);
233  pieces[0].erase(pieces[0].begin()+n,
234  pieces[0].begin()+n+inParticleNamesSH[i].size());
235  n=0;
236  }
237  }
238  // Get intermediate particles
239  // If intermediates are still empty, fill intermediate with default value
240  inter.push_back(0);
241  // Get final particles
242  for(int i=0; i < nOut; ++i) {
243  for(int n = pieces[1].find(outParticleNamesSH[i], 0);
244  n != int(string::npos);
245  n = pieces[1].find(outParticleNamesSH[i], n)) {
246  outgo.push_back(outParticleNumbers[i]);
247  pieces[1].erase(pieces[1].begin()+n,
248  pieces[1].begin()+n+outParticleNamesSH[i].size());
249  n=0;
250  }
251  }
252 
253  } else if (meGenType == -1 || meGenType == -3 || meGenType == -4){
254 
255  // Now read merging scale
256  string lineTMS;
257 
258  if (meGenType == -1) {
259  // Open path to LHEF and extract merging scale
260  infile.open( (char*)( LHEpath +"_1.lhe").c_str());
261  while(lineTMS.find("ktdurham", 0) == string::npos){
262  lineTMS = " ";
263  getline(infile,lineTMS);
264  }
265  lineTMS = lineTMS.substr(0,lineTMS.find("=",0));
266  infile.close();
267  } else {
268  lineTMS = "30.";
269  }
270 
271  // Remove whitespaces
272  while(lineTMS.find(" ", 0) != string::npos)
273  lineTMS.erase(lineTMS.begin()+lineTMS.find(" ",0));
274  // Replace d with e
275  if ( lineTMS.find("d", 0) != string::npos)
276  lineTMS.replace(lineTMS.find("d", 0),1,1,'e');
277  tms = atof((char*)lineTMS.c_str());
278 
279  // Now read hard process
280  // Open path to LHEF and extract hard process
281  infile.open( (char*)( LHEpath +"_0.lhe").c_str());
282  string line;
283  while(line.find("@1", 0) == string::npos){
284  line = " ";
285  getline(infile,line);
286  }
287  infile.close();
288  line = line.substr(0,line.find("@",0));
289 
290  // Count number of resonances
291  int appearances = 0;
292  for(int n = line.find("(", 0); n != int(string::npos);
293  n = line.find("(", n)) {
294  appearances++;
295  n++;
296  }
297 
298  // Cut string in incoming, resonance+decay and outgoing pieces
299  vector <string> pieces;
300  for(int i =0; i < appearances;++i) {
301  int n = line.find("(", 0);
302  pieces.push_back(line.substr(0,n));
303  line = line.substr(n+1,line.size());
304  }
305  // Cut last resonance from rest
306  if (appearances > 0) {
307  pieces.push_back( line.substr(0,line.find(")",0)) );
308  pieces.push_back( line.substr(line.find(")",0)+1,line.size()) );
309  }
310 
311  // If the string was not cut into pieces, i.e. no resonance was
312  // required, cut string using '>' as delimiter
313  if (pieces.empty() ){
314  appearances = 0;
315  for(int n = line.find(">", 0); n != int(string::npos);
316  n = line.find(">", n)) {
317  appearances++;
318  n++;
319  }
320 
321  // Cut string in incoming and outgoing pieces
322  for(int i =0; i < appearances;++i) {
323  int n = line.find(">", 0);
324  pieces.push_back(line.substr(0,n));
325  line = line.substr(n+1,line.size());
326  }
327 
328  if (appearances == 1) pieces.push_back(line);
329  if (appearances > 1) {
330  pieces.push_back( line.substr(0,line.find(">",0)) );
331  pieces.push_back( line.substr(line.find(">",0)+1,line.size()) );
332  }
333  }
334 
335  // Get incoming particles
336  for(int i=0; i < nIn; ++i) {
337  for(int n = pieces[0].find(inParticleNamesMG[i], 0);
338  n != int(string::npos);
339  n = pieces[0].find(inParticleNamesMG[i], n)) {
340  incom.push_back(inParticleNumbers[i]);
341  pieces[0].erase(pieces[0].begin()+n,
342  pieces[0].begin()+n+inParticleNamesMG[i].size());
343  n=0;
344  }
345  }
346 
347  // Check intermediate resonances and decay products
348  for(int i =1; i < int(pieces.size()); ++i){
349  // Seperate strings into intermediate and outgoing, if not already done
350  int k = pieces[i].find(">", 0);
351 
352  string intermediate = (pieces[i].find(">", 0) != string::npos) ?
353  pieces[i].substr(0,k) : "";
354  string outgoing = (pieces[i].find(">", 0) != string::npos) ?
355  pieces[i].substr(k+1,pieces[i].size()) : pieces[i];
356 
357  // Get intermediate particles
358  for(int j=0; j < nInt; ++j) {
359  for(int n = intermediate.find(interParticleNamesMG[j], 0);
360  n != int(string::npos);
361  n = intermediate.find(interParticleNamesMG[j], n)) {
362  inter.push_back(interParticleNumbers[j]);
363  intermediate.erase(intermediate.begin()+n,
364  intermediate.begin()+n+interParticleNamesMG[j].size());
365  n=0;
366  }
367  }
368 
369  // Get outgoing particles
370  for(int j=0; j < nOut; ++j) {
371  for(int n = outgoing.find(outParticleNamesMG[j], 0);
372  n != int(string::npos);
373  n = outgoing.find(outParticleNamesMG[j], n)) {
374  outgo.push_back(outParticleNumbers[j]);
375  outgoing.erase(outgoing.begin()+n,
376  outgoing.begin()+n+outParticleNamesMG[j].size());
377  n=0;
378  }
379  }
380 
381  // For arbitrary or non-existing intermediate, remember zero for each
382  // two outgoing particles, without bosons.
383  if (inter.empty()) {
384 
385  // For final state bosons, bookkeep the final state boson as
386  // intermediate as well.
387  int nBosons = 0;
388  for(int l=0; l < int(outgo.size()); ++l)
389  if ( (abs(outgo[l]) > 20 && abs(outgo[l]) <= 25) || outgo[l] == 2400)
390  nBosons++;
391 
392  int nZeros = (outgo.size() - nBosons)/2;
393  for(int l=0; l < nZeros; ++l)
394  inter.push_back(0);
395  }
396 
397  // For final state bosons, bookkeep the final state boson as
398  // intermediate as well.
399  for(int l=0; l < int(outgo.size()); ++l)
400  if ( (abs(outgo[l]) > 20 && abs(outgo[l]) <= 25) || outgo[l] == 2400)
401  inter.push_back(outgo[l]);
402 
403  }
404 
405  } else {
406 
407  cout << "Reading of tms and hard process information from LHEF currently"
408  << " only automated for MadEvent- or SHERPA-produced LHEF" << endl;
409  int tempInt = 0;
410  cout << "Use default process pp -> e+ve + jets? (0:no / 1:yes): ";
411  cin >> tempInt;
412  cout << endl;
413 
414  if (tempInt == 0){
415  tempInt = 0;
416  double tempDouble = 0.0;
417  cout << "Please specify merging scale (kT Durham, in GeV): ";
418  cin >> tempDouble;
419  tms = tempDouble;
420  cout << endl;
421  cout << "Please specify first incoming particle ";
422  cout << "(p+/p- = 2212, e- = 11, e+ = -11): ";
423  cin >> tempInt;
424  incom.push_back(tempInt);
425  tempInt = 0;
426  cout << endl;
427  cout << "Please specify second incoming particle ";
428  cout << "(p+/p- = 2212, e- = 11, e+ = -11): ";
429  cin >> tempInt;
430  incom.push_back(tempInt);
431  tempInt = 0;
432  cout << endl;
433  cout << "Please specify intermediate particle, if any ";
434  cout << "(0 for none, else PDG code): ";
435  cin >> tempInt;
436  inter.push_back(tempInt);
437  cout << endl;
438  do {
439  tempInt = 0;
440  cout << "Please specify outgoing particle ";
441  cout << "(jet=2212, else PDG code, exit with 99): ";
442  cin >> tempInt;
443  if (tempInt != 99) outgo.push_back(tempInt);
444  } while(tempInt != 99);
445  cout << endl;
446  } else {
447  cout << "LHE file not produced by SHERPA or MG/ME - ";
448  cout << "Using default process and tms" << endl;
449  incom.push_back(2212);
450  incom.push_back(2212);
451  inter.push_back(24);
452  outgo.push_back(-11);
453  outgo.push_back(12);
454  tms = 10.;
455  }
456  }
457 
458  // Now store incoming, intermediate and outgoing
459  // Set intermediate tags
460  for(int i=0; i < int(inter.size()); ++i)
461  hardIntermediate.push_back(inter[i]);
462 
463  // Set the incoming particle tags
464  if (incom.size() != 2)
465  cout << "Only two incoming particles allowed" << endl;
466  else {
467  hardIncoming1 = incom[0];
468  hardIncoming2 = incom[1];
469  }
470 
471  // Remember final state bosons
472  int nBosons = 0;
473  for(int i=0; i < int(outgo.size()); ++i)
474  if ( (abs(outgo[i]) > 20 && abs(outgo[i]) <= 25) || outgo[i] == 2400)
475  nBosons++;
476  // Remember b-quark container
477  int nBQuarks = 0;
478  for(int i=0; i < int(outgo.size()); ++i)
479  if ( outgo[i] == 5000)
480  nBQuarks++;
481  // Remember jet container
482  int nJets = 0;
483  for(int i=0; i < int(outgo.size()); ++i)
484  if ( outgo[i] == 2212)
485  nJets++;
486  // Remember lepton container
487  int nLeptons = 0;
488  for(int i=0; i < int(outgo.size()); ++i)
489  if ( outgo[i] == 1100)
490  nLeptons++;
491  // Remember lepton container
492  int nNeutrinos = 0;
493  for(int i=0; i < int(outgo.size()); ++i)
494  if ( outgo[i] == 1200)
495  nNeutrinos++;
496  int nContainers = nLeptons + nNeutrinos + nJets + nBQuarks;
497 
498  // Set final particle identifiers
499  if ( (outgo.size() - nBosons - nContainers)%2 == 1) {
500  cout << "Only even number of outgoing particles allowed" << endl;
501  for(int i=0; i < int(outgo.size()); ++i)
502  cout << outgo[i] << endl;
503  } else {
504 
505  // Push back particles / antiparticles
506  for(int i=0; i < int(outgo.size()); ++i)
507  if (outgo[i] > 0
508  && outgo[i] != 2212
509  && outgo[i] != 5000
510  && outgo[i] != 1100
511  && outgo[i] != 1200
512  && outgo[i] != 2400
513  && outgo[i] != 1000022)
514  hardOutgoing2.push_back( outgo[i]);
515  else if (outgo[i] < 0)
516  hardOutgoing1.push_back( outgo[i]);
517 
518  // Save final state W-boson container as particle
519  for(int i=0; i < int(outgo.size()); ++i)
520  if ( outgo[i] == 2400)
521  hardOutgoing2.push_back( outgo[i]);
522 
523  // Push back jets, distribute evenly amongst particles / antiparticles
524  // Push back majorana particles, distribute evenly
525  int iNow = 0;
526  for(int i=0; i < int(outgo.size()); ++i)
527  if ( (outgo[i] == 2212
528  || outgo[i] == 5000
529  || outgo[i] == 1200
530  || outgo[i] == 1000022)
531  && iNow%2 == 0 ){
532  hardOutgoing2.push_back( outgo[i]);
533  iNow++;
534  } else if ( (outgo[i] == 2212
535  || outgo[i] == 5000
536  || outgo[i] == 1100
537  || outgo[i] == 1000022)
538  && iNow%2 == 1 ){
539  hardOutgoing1.push_back( outgo[i]);
540  iNow++;
541  }
542  }
543 
544  // Done
545 }
546 
547 //--------------------------------------------------------------------------
548 
549 // Function to translate a string specitying the core process into the
550 // internal notation
551 // Currently, the input string has to be in MadEvent notation
552 
553 void HardProcess::translateProcessString( string process){
554 
555  vector <int> incom;
556  vector <int> inter;
557  vector <int> outgo;
558  // Particle identifiers, ordered in such a way that e.g. the "u"
559  // in a mu is not mistaken for an u quark
560  int inParticleNumbers[] = {
561  // Leptons
562  -11,11,-12,12,-13,13,-14,14,-15,15,-16,16,
563  // Jet container
564  2212,2212,0,0,0,0,
565  // Quarks
566  -1,1,-2,2,-3,3,-4,4,-5,5,-6,6};
567  string inParticleNamesMG[] = {
568  // Leptons
569  "e+","e-","ve~","ve","mu+","mu-","vm~","vm","ta+","ta-","vt~","vt",
570  // Jet container
571  "p~","p","l+","l-","vl~","vl",
572  // Quarks
573  "d~","d","u~","u","s~","s","c~","c","b~","b","t~","t"};
574 
575  // Declare intermediate particle identifiers
576  int interParticleNumbers[] = {
577  // Electroweak gauge bosons
578  22,23,-24,24,25,2400,
579  // Top quarks
580  -6,6,
581  // Dummy index as back-up
582  0,
583  // All squarks
584  -1000001,1000001,-1000002,1000002,-1000003,1000003,-1000004,1000004,
585  -1000005,1000005,-1000006,1000006,-2000001,2000001,-2000002,2000002,
586  -2000003,2000003,-2000004,2000004,-2000005,2000005,-2000006,2000006};
587  // Declare names of intermediate particles
588  string interParticleNamesMG[] = {
589  // Electroweak gauge bosons
590  "a","z","w-","w+","h","W",
591  // Top quarks
592  "t~","t",
593  // Dummy index as back-up
594  "xx",
595  // All squarks
596  "dl~","dl","ul~","ul","sl~","sl","cl~","cl","b1~","b1","t1~","t1",
597  "dr~","dr","ur~","ur","sr~","sr","cr~","cr","b2~","b2","t2~","t2"};
598 
599  // Declare final state particle identifiers
600  int outParticleNumbers[] = {
601  // Leptons
602  -11,11,-12,12,-13,13,-14,14,-15,15,-16,16,
603  // Jet container and lepton containers
604  2212,2212,0,0,0,0,1200,1100,5000,
605  // Quarks
606  -1,1,-2,2,-3,3,-4,4,-5,5,-6,6,
607  // SM uncoloured bosons
608  22,23,-24,24,25,2400,
609  // Neutralino in SUSY
610  1000022,
611  // All squarks
612  -1000001,1000001,-1000002,1000002,-1000003,1000003,-1000004,1000004,
613  -1000005,1000005,-1000006,1000006,-2000001,2000001,-2000002,2000002,
614  -2000003,2000003,-2000004,2000004,-2000005,2000005,-2000006,2000006};
615  // Declare names of final state particles
616  string outParticleNamesMG[] = {
617  // Leptons
618  "e+","e-","ve~","ve","mu+","mu-","vm~","vm","ta+","ta-","vt~","vt",
619  // Jet container and lepton containers
620  "j~","j","l+","l-","vl~","vl","NEUTRINOS","LEPTONS","BQUARKS",
621  // Quarks
622  "d~","d","u~","u","s~","s","c~","c","b~","b","t~","t",
623  // SM uncoloured bosons
624  "a","z","w-","w+","h","W",
625  // Neutralino in SUSY
626  "n1",
627  // All squarks
628  "dl~","dl","ul~","ul","sl~","sl","cl~","cl","b1~","b1","t1~","t1",
629  "dr~","dr","ur~","ur","sr~","sr","cr~","cr","b2~","b2","t2~","t2"};
630 
631  // Declare size of particle name arrays
632  int nIn = 30;
633  int nInt = 33;
634  int nOut = 64;
635 
636  // Start mapping user-defined particles onto particle ids.
637  //string fullProc = "pp>{blaa,124}LEPTONS,NEUTRINOS";
638  string fullProc = process;
639 
640  // Find user-defined hard process content
641  // Count number of user particles
642  int nUserParticles = 0;
643  for(int n = fullProc.find("{", 0); n != int(string::npos);
644  n = fullProc.find("{", n)) {
645  nUserParticles++;
646  n++;
647  }
648  // Cut user-defined particles from remaining process
649  vector <string> userParticleStrings;
650  for(int i =0; i < nUserParticles;++i) {
651  int n = fullProc.find("{", 0);
652  userParticleStrings.push_back(fullProc.substr(0,n));
653  fullProc = fullProc.substr(n+1,fullProc.size());
654  }
655  // Cut remaining process string from rest
656  if (nUserParticles > 0)
657  userParticleStrings.push_back(
658  fullProc.substr( 0, fullProc.find("}",0) ) );
659  // Remove curly brackets and whitespace
660  for(int i =0; i < int(userParticleStrings.size());++i) {
661  while(userParticleStrings[i].find("{", 0) != string::npos)
662  userParticleStrings[i].erase(userParticleStrings[i].begin()
663  +userParticleStrings[i].find("{", 0));
664  while(userParticleStrings[i].find("}", 0) != string::npos)
665  userParticleStrings[i].erase(userParticleStrings[i].begin()
666  +userParticleStrings[i].find("}", 0));
667  while(userParticleStrings[i].find(" ", 0) != string::npos)
668  userParticleStrings[i].erase(userParticleStrings[i].begin()
669  +userParticleStrings[i].find(" ", 0));
670  }
671  // Convert particle numbers in user particle to integers
672  vector<int>userParticleNumbers;
673  if ( int(userParticleStrings.size()) > 1) {
674  for( int i = 1; i < int(userParticleStrings.size()); ++i) {
675  userParticleNumbers.push_back(
676  atoi((char*)userParticleStrings[i].substr(
677  userParticleStrings[i].find(",",0)+1,
678  userParticleStrings[i].size()).c_str() ) );
679  }
680  }
681  // Save remaining process string
682  if (nUserParticles > 0)
683  userParticleStrings.push_back(
684  fullProc.substr(
685  fullProc.find("}",0)+1, fullProc.size() ) );
686  // Remove curly brackets and whitespace
687  for( int i = 0; i < int(userParticleStrings.size()); ++i) {
688  while(userParticleStrings[i].find("{", 0) != string::npos)
689  userParticleStrings[i].erase(userParticleStrings[i].begin()
690  +userParticleStrings[i].find("{", 0));
691  while(userParticleStrings[i].find("}", 0) != string::npos)
692  userParticleStrings[i].erase(userParticleStrings[i].begin()
693  +userParticleStrings[i].find("}", 0));
694  while(userParticleStrings[i].find(" ", 0) != string::npos)
695  userParticleStrings[i].erase(userParticleStrings[i].begin()
696  +userParticleStrings[i].find(" ", 0));
697  }
698 
699  // Start mapping residual process string onto particle IDs.
700  // Declare leftover process after user-defined particles have been converted
701  string residualProc;
702  if ( int(userParticleStrings.size()) > 1 )
703  residualProc = userParticleStrings.front() + userParticleStrings.back();
704  else
705  residualProc = fullProc;
706 
707  // Remove comma separation
708  while(residualProc.find(",", 0) != string::npos)
709  residualProc.erase(residualProc.begin()+residualProc.find(",",0));
710 
711  // Count number of resonances
712  int appearances = 0;
713  for(int n = residualProc.find("(", 0); n != int(string::npos);
714  n = residualProc.find("(", n)) {
715  appearances++;
716  n++;
717  }
718 
719  // Cut string in incoming, resonance+decay and outgoing pieces
720  vector <string> pieces;
721  for(int i =0; i < appearances;++i) {
722  int n = residualProc.find("(", 0);
723  pieces.push_back(residualProc.substr(0,n));
724  residualProc = residualProc.substr(n+1,residualProc.size());
725  }
726  // Cut last resonance from rest
727  if (appearances > 0) {
728  pieces.push_back( residualProc.substr(0,residualProc.find(")",0)) );
729  pieces.push_back( residualProc.substr(
730  residualProc.find(")",0)+1, residualProc.size()) );
731  }
732 
733  // If the string was not cut into pieces, i.e. no resonance was
734  // required, cut string using '>' as delimiter
735  if (pieces.empty() ){
736  appearances = 0;
737  for(int n = residualProc.find(">", 0); n != int(string::npos);
738  n = residualProc.find(">", n)) {
739  appearances++;
740  n++;
741  }
742 
743  // Cut string in incoming and outgoing pieces
744  for(int i =0; i < appearances;++i) {
745  int n = residualProc.find(">", 0);
746  pieces.push_back(residualProc.substr(0,n));
747  residualProc = residualProc.substr(n+1,residualProc.size());
748  }
749 
750  if (appearances == 1) pieces.push_back(residualProc);
751  if (appearances > 1) {
752  pieces.push_back( residualProc.substr(0,residualProc.find(">",0)) );
753  pieces.push_back( residualProc.substr(
754  residualProc.find(">",0)+1, residualProc.size()) );
755  }
756  }
757 
758  // Get incoming particles
759  for(int i=0; i < nIn; ++i) {
760  for(int n = pieces[0].find(inParticleNamesMG[i], 0);
761  n != int(string::npos);
762  n = pieces[0].find(inParticleNamesMG[i], n)) {
763  incom.push_back(inParticleNumbers[i]);
764  pieces[0].erase(pieces[0].begin()+n,
765  pieces[0].begin()+n+inParticleNamesMG[i].size());
766  n=0;
767  }
768  }
769 
770  // Check intermediate resonances and decay products
771  for(int i =1; i < int(pieces.size()); ++i){
772  // Seperate strings into intermediate and outgoing, if not already done
773  int k = pieces[i].find(">", 0);
774 
775  string intermediate = (pieces[i].find(">", 0) != string::npos) ?
776  pieces[i].substr(0,k) : "";
777  string outgoing = (pieces[i].find(">", 0) != string::npos) ?
778  pieces[i].substr(k+1,pieces[i].size()) : pieces[i];
779 
780  // Get intermediate particles
781  for(int j=0; j < nInt; ++j) {
782  for(int n = intermediate.find(interParticleNamesMG[j], 0);
783  n != int(string::npos);
784  n = intermediate.find(interParticleNamesMG[j], n)) {
785  inter.push_back(interParticleNumbers[j]);
786  intermediate.erase(intermediate.begin()+n,
787  intermediate.begin()+n+interParticleNamesMG[j].size());
788  n=0;
789  }
790  }
791 
792  // Get outgoing particles
793  for(int j=0; j < nOut; ++j) {
794  for(int n = outgoing.find(outParticleNamesMG[j], 0);
795  n != int(string::npos);
796  n = outgoing.find(outParticleNamesMG[j], n)) {
797  outgo.push_back(outParticleNumbers[j]);
798  outgoing.erase(outgoing.begin()+n,
799  outgoing.begin()+n+outParticleNamesMG[j].size());
800  n=0;
801  }
802  }
803 
804  // For arbitrary or non-existing intermediate, remember zero for each
805  // two outgoing particles, without bosons.
806  if (inter.empty()) {
807 
808  // For final state bosons, bookkeep the final state boson as
809  // intermediate as well.
810  int nBosons = 0;
811  for(int l=0; l < int(outgo.size()); ++l)
812  if ( (abs(outgo[l]) > 20 && abs(outgo[l]) <= 25) || outgo[l] == 2400)
813  nBosons++;
814 
815  int nZeros = (outgo.size() - nBosons)/2;
816  for(int l=0; l < nZeros; ++l)
817  inter.push_back(0);
818  }
819 
820  // For final state bosons, bookkeep the final state boson as
821  // intermediate as well.
822  for(int l=0; l < int(outgo.size()); ++l)
823  if ( (abs(outgo[l]) > 20 && abs(outgo[l]) <= 25) || outgo[l] == 2400)
824  inter.push_back(outgo[l]);
825 
826  }
827 
828  // Now store incoming, intermediate and outgoing
829  // Set intermediate tags
830  for(int i=0; i < int(inter.size()); ++i)
831  hardIntermediate.push_back(inter[i]);
832 
833  // Set the incoming particle tags
834  if (incom.size() != 2)
835  cout << "Only two incoming particles allowed" << endl;
836  else {
837  hardIncoming1 = incom[0];
838  hardIncoming2 = incom[1];
839  }
840 
841  // Now store final particle identifiers
842  // Start with user-defined particles.
843  for( int i = 0; i < int(userParticleNumbers.size()); ++i)
844  if (userParticleNumbers[i] > 0) {
845  hardOutgoing2.push_back( userParticleNumbers[i]);
846  hardIntermediate.push_back(0);
847  // For non-existing intermediate, remember zero.
848  } else if (userParticleNumbers[i] < 0) {
849  hardOutgoing1.push_back( userParticleNumbers[i]);
850  // For non-existing intermediate, remember zero.
851  hardIntermediate.push_back(0);
852  }
853 
854  // Push back particles / antiparticles
855  for(int i=0; i < int(outgo.size()); ++i)
856  if (outgo[i] > 0
857  && outgo[i] != 2212
858  && outgo[i] != 5000
859  && outgo[i] != 1100
860  && outgo[i] != 1200
861  && outgo[i] != 2400
862  && outgo[i] != 1000022)
863  hardOutgoing2.push_back( outgo[i]);
864  else if (outgo[i] < 0)
865  hardOutgoing1.push_back( outgo[i]);
866 
867  // Save final state W-boson container as particle
868  for(int i=0; i < int(outgo.size()); ++i)
869  if ( outgo[i] == 2400)
870  hardOutgoing2.push_back( outgo[i]);
871 
872  // Push back jets, distribute evenly among particles / antiparticles
873  // Push back majorana particles, distribute evenly
874  int iNow = 0;
875  for(int i=0; i < int(outgo.size()); ++i)
876  if ( (outgo[i] == 2212
877  || outgo[i] == 5000
878  || outgo[i] == 1200
879  || outgo[i] == 1000022)
880  && iNow%2 == 0 ){
881  hardOutgoing2.push_back( outgo[i]);
882  iNow++;
883  } else if ( (outgo[i] == 2212
884  || outgo[i] == 5000
885  || outgo[i] == 1100
886  || outgo[i] == 1000022)
887  && iNow%2 == 1 ){
888  hardOutgoing1.push_back( outgo[i]);
889  iNow++;
890  }
891 
892  // Done
893 }
894 
895 //--------------------------------------------------------------------------
896 
897 // Function to check if the candidates stored in Pos1 and Pos2, together with
898 // a proposed candidate iPos are allowed.
899 
900 bool HardProcess::allowCandidates(int iPos, vector<int> Pos1,
901  vector<int> Pos2, const Event& event){
902 
903  bool allowed = true;
904 
905  // Find colour-partner of new candidate
906  int type = (event[iPos].col() > 0) ? 1 : (event[iPos].acol() > 0) ? -1 : 0;
907 
908  if (type == 0) return true;
909 
910  if (type == 1){
911  int col = event[iPos].col();
912  int iPartner = 0;
913  for(int i=0; i < int(event.size()); ++i)
914  if ( i != iPos
915  && (( event[i].isFinal() && event[i].acol() == col)
916  ||( event[i].status() == -21 && event[i].col() == col) ))
917  iPartner = i;
918 
919  vector<int> partners;
920  for(int i=0; i < int(event.size()); ++i)
921  for(int j=0; j < int(Pos1.size()); ++j)
922  if ( Pos1[j] != 0 && i != Pos1[j] && event[Pos1[j]].colType() != 0
923  && (( event[i].isFinal() && event[i].col() == event[Pos1[j]].acol())
924  ||( event[i].status() == -21
925  && event[i].acol() == event[Pos1[j]].acol()) ))
926  partners.push_back(i);
927 
928  // Never allow equal initial partners!
929  if (event[iPartner].status() == -21){
930  for(int i=0; i < int(partners.size()); ++i)
931  if ( partners[i] == iPartner)
932  allowed = false;
933  }
934 
935  } else {
936  int col = event[iPos].acol();
937  int iPartner = 0;
938  for(int i=0; i < int(event.size()); ++i)
939  if ( i != iPos
940  && (( event[i].isFinal() && event[i].col() == col)
941  ||(!event[i].isFinal() && event[i].acol() == col) ))
942  iPartner = i;
943 
944  vector<int> partners;
945  for(int i=0; i < int(event.size()); ++i)
946  for(int j=0; j < int(Pos2.size()); ++j)
947  if ( Pos2[j] != 0 && i != Pos2[j] && event[Pos2[j]].colType() != 0
948  && (( event[i].isFinal() && event[i].acol() == event[Pos2[j]].col())
949  ||( event[i].status() == -21
950  && event[i].col() == event[Pos2[j]].col()) ))
951  partners.push_back(i);
952 
953  // Never allow equal initial partners!
954  if (event[iPartner].status() == -21){
955  for(int i=0; i < int(partners.size()); ++i){
956  if ( partners[i] == iPartner)
957  allowed = false;
958  }
959  }
960 
961  }
962 
963  return allowed;
964 
965 }
966 
967 //--------------------------------------------------------------------------
968 
969 // Function to identify the hard subprocess in the current event
970 
971 void HardProcess::storeCandidates( const Event& event, string process){
972 
973  // Store the reference event
974  state.clear();
975  state = event;
976 
977  // Local copy of intermediate bosons
978  vector<int> intermediates;
979  for(int i =0; i < int(hardIntermediate.size());++i)
980  intermediates.push_back( hardIntermediate[i]);
981 
982  // Local copy of outpoing partons
983  vector<int> outgoing1;
984  for(int i =0; i < int(hardOutgoing1.size());++i)
985  outgoing1.push_back( hardOutgoing1[i]);
986  vector<int> outgoing2;
987  for(int i =0; i < int(hardOutgoing2.size());++i)
988  outgoing2.push_back( hardOutgoing2[i]);
989 
990  // Clear positions of intermediate and outgoing particles
991  PosIntermediate.resize(0);
992  PosOutgoing1.resize(0);
993  PosOutgoing2.resize(0);
994  for(int i =0; i < int(hardIntermediate.size());++i)
995  PosIntermediate.push_back(0);
996  for(int i =0; i < int(hardOutgoing1.size());++i)
997  PosOutgoing1.push_back(0);
998  for(int i =0; i < int(hardOutgoing2.size());++i)
999  PosOutgoing2.push_back(0);
1000 
1001  // For QCD dijet or e+e- > jets hard process, do not store any candidates,
1002  // as to not discrimintate clusterings
1003  if ( process.compare("pp>jj") == 0
1004  || process.compare("e+e->jj") == 0
1005  || process.compare("e+e->(z>jj)") == 0 ){
1006  for(int i =0; i < int(hardOutgoing1.size());++i)
1007  PosOutgoing1[i] = 0;
1008  for(int i =0; i < int(hardOutgoing2.size());++i)
1009  PosOutgoing2[i] = 0;
1010  // Done
1011  return;
1012  }
1013 
1014  // Initialise vector of particles that were already identified as
1015  // hard process particles
1016  vector<int> iPosChecked;
1017 
1018  // If the hard process is specified only by containers, then add all
1019  // particles matching with the containers to the hard process.
1020  bool hasOnlyContainers = true;
1021  for(int i =0; i < int(hardOutgoing1.size());++i)
1022  if ( hardOutgoing1[i] != 1100
1023  && hardOutgoing1[i] != 1200
1024  && hardOutgoing1[i] != 5000)
1025  hasOnlyContainers = false;
1026  for(int i =0; i < int(hardOutgoing2.size());++i)
1027  if ( hardOutgoing2[i] != 1100
1028  && hardOutgoing2[i] != 1200
1029  && hardOutgoing2[i] != 5000)
1030  hasOnlyContainers = false;
1031 
1032  if (hasOnlyContainers){
1033 
1034  PosOutgoing1.resize(0);
1035  PosOutgoing2.resize(0);
1036 
1037  // Try to find all unmatched hard process leptons.
1038  // Loop through event to find outgoing lepton
1039  for(int i=0; i < int(event.size()); ++i){
1040 
1041  // Skip non-final particles
1042  if ( !event[i].isFinal() ) continue;
1043 
1044  // Skip all particles that have already been identified
1045  bool skip = false;
1046  for(int k=0; k < int(iPosChecked.size()); ++k){
1047  if (i == iPosChecked[k])
1048  skip = true;
1049  }
1050  if (skip) continue;
1051 
1052  for(int j=0; j < int(outgoing2.size()); ++j){
1053 
1054  // If the particle matches an outgoing neutrino, save it
1055  if ( outgoing2[j] == 1100
1056  && ( event[i].idAbs() == 11
1057  || event[i].idAbs() == 13
1058  || event[i].idAbs() == 15) ){
1059  PosOutgoing2.push_back(i);
1060  iPosChecked.push_back(i);
1061  }
1062 
1063  // If the particle matches an outgoing lepton, save it
1064  if ( outgoing2[j] == 1200
1065  && ( event[i].idAbs() == 12
1066  || event[i].idAbs() == 14
1067  || event[i].idAbs() == 16) ){
1068  PosOutgoing2.push_back(i);
1069  iPosChecked.push_back(i);
1070  }
1071 
1072  // If the particle matches an outgoing b-quark, save it
1073  if ( outgoing2[j] == 5000 && event[i].idAbs() == 5 ){
1074  PosOutgoing2.push_back(i);
1075  iPosChecked.push_back(i);
1076  }
1077 
1078  }
1079 
1080  // Skip all particles that have already been identified
1081  skip = false;
1082  for(int k=0; k < int(iPosChecked.size()); ++k){
1083  if (i == iPosChecked[k])
1084  skip = true;
1085  }
1086  if (skip) continue;
1087 
1088  for(int j=0; j < int(outgoing1.size()); ++j){
1089 
1090  // If the particle matches an outgoing neutrino, save it
1091  if ( outgoing1[j] == 1100
1092  && ( event[i].idAbs() == 11
1093  || event[i].idAbs() == 13
1094  || event[i].idAbs() == 15) ){
1095  PosOutgoing1.push_back(i);
1096  iPosChecked.push_back(i);
1097  }
1098 
1099  // If the particle matches an outgoing lepton, save it
1100  if ( outgoing1[j] == 1200
1101  && ( event[i].idAbs() == 12
1102  || event[i].idAbs() == 14
1103  || event[i].idAbs() == 16) ){
1104  PosOutgoing1.push_back(i);
1105  iPosChecked.push_back(i);
1106  }
1107 
1108  // If the particle matches an outgoing b-quark, save it
1109  if ( outgoing1[j] == 5000 && event[i].idAbs() == 5 ){
1110  PosOutgoing1.push_back(i);
1111  iPosChecked.push_back(i);
1112  }
1113 
1114  }
1115  }
1116 
1117  // Done
1118  return;
1119  }
1120 
1121  // Now begin finding candidates when not only containers are used.
1122 
1123  // First try to find final state bosons
1124  for(int i=0; i < int(intermediates.size()); ++i){
1125 
1126  // Do nothing if the intermediate boson is absent
1127  if (intermediates[i] == 0) continue;
1128 
1129  // Do nothing if this boson does not match any final state boson
1130  bool matchesFinalBoson = false;
1131  for(int j =0; j< int(outgoing1.size()); ++j){
1132  if ( intermediates[i] == outgoing1[j] )
1133  matchesFinalBoson = true;
1134  }
1135  for(int j =0; j< int(outgoing2.size()); ++j){
1136  if ( intermediates[i] == outgoing2[j] )
1137  matchesFinalBoson = true;
1138  }
1139  if (!matchesFinalBoson) continue;
1140 
1141  // Loop through event
1142  for(int j=0; j < int(event.size()); ++j) {
1143 
1144  // Skip all particles that have already been identified
1145  bool skip = false;
1146  for(int m=0; m < int(iPosChecked.size()); ++m)
1147  if (j == iPosChecked[m]) skip = true;
1148  if (skip) continue;
1149 
1150  // If the particle has a requested intermediate id, check if
1151  // if is a final state boson
1152  if ( (event[j].id() == intermediates[i])
1153  ||(event[j].idAbs() == 24 && intermediates[i] == 2400) ) {
1154 
1155  PosIntermediate[i] = j;
1156  intermediates[i] = 0;
1157  // Be careful only to replace one index at a time!
1158  bool indexSet = false;
1159 
1160  for(int k=0; k < int(outgoing1.size()); ++k) {
1161  if (event[j].id() == outgoing1[k] && !indexSet){
1162  PosOutgoing1[k] = j;
1163  outgoing1[k] = 99;
1164  indexSet = true;
1165  }
1166  }
1167 
1168  for(int k=0; k < int(outgoing2.size()); ++k) {
1169  if (event[j].id() == outgoing2[k] && !indexSet){
1170  PosOutgoing2[k] = j;
1171  outgoing2[k] = 99;
1172  indexSet = true;
1173  }
1174  }
1175 
1176  // Check for W-boson container
1177  for(int k=0; k < int(outgoing2.size()); ++k) {
1178  if (event[j].idAbs() == 24 && outgoing2[k] == 2400 && !indexSet ){
1179  PosOutgoing2[k] = j;
1180  outgoing2[k] = 99;
1181  indexSet = true;
1182  }
1183  }
1184 
1185  iPosChecked.push_back(j);
1186 
1187  }
1188  }
1189  }
1190 
1191  // Second try to find particles coupled to intermediate bosons
1192  for(int i=0; i < int(intermediates.size()); ++i){
1193 
1194  // Do nothing if the intermediate boson is absent
1195  if (intermediates[i] == 0) continue;
1196 
1197  // Loop through event
1198  for(int j=0; j < int(event.size()); ++j) {
1199  // If the particle has a requested intermediate id, check if
1200  // daughters are hard process particles
1201  if ( (event[j].id() == intermediates[i])
1202  ||(event[j].idAbs() == 24 && intermediates[i] == 2400) ) {
1203  // If this particle is a potential intermediate
1204  PosIntermediate[i] = j;
1205  intermediates[i] = 0;
1206  // If id's of daughters are good, store position
1207  int iPos1 = event[j].daughter1();
1208  int iPos2 = event[j].daughter2();
1209 
1210  // Loop through daughters to check if these contain some hard
1211  // outgoing particles
1212  for( int k=iPos1; k <= iPos2; ++k){
1213  int id = event[k].id();
1214 
1215  // Skip all particles that have already been identified
1216  bool skip = false;
1217  for(int m=0; m < int(iPosChecked.size()); ++m)
1218  if (k == iPosChecked[m]) skip = true;
1219  if (skip) continue;
1220 
1221  // Check if daughter is hard outgoing particle
1222  for(int l=0; l < int(outgoing2.size()); ++l)
1223  if ( outgoing2[l] != 99 ){
1224  // Found particle id
1225  if (id == outgoing2[l]
1226  // Found jet
1227  || (id > 0 && abs(id) < 10 && outgoing2[l] == 2212) ){
1228  // Store position
1229  PosOutgoing2[l] = k;
1230  // Remove the matched particle from the list
1231  outgoing2[l] = 99;
1232  iPosChecked.push_back(k);
1233  break;
1234  }
1235 
1236  }
1237 
1238  // Check if daughter is hard outgoing antiparticle
1239  for(int l=0; l < int(outgoing1.size()); ++l)
1240  if ( outgoing1[l] != 99 ){
1241  // Found particle id
1242  if (id == outgoing1[l]
1243  // Found jet
1244  || (id < 0 && abs(id) < 10 && outgoing1[l] == 2212) ){
1245  // Store position
1246  PosOutgoing1[l] = k;
1247  // Remove the matched particle from the list
1248  outgoing1[l] = 99;
1249  iPosChecked.push_back(k);
1250  break;
1251  }
1252 
1253  }
1254 
1255  } // End loop through daughters
1256  } // End if ids match
1257  } // End loop through event
1258  } // End loop though requested intermediates
1259 
1260  // If all outgoing particles were found, done
1261  bool done = true;
1262  for(int i=0; i < int(outgoing1.size()); ++i)
1263  if (outgoing1[i] != 99)
1264  done = false;
1265  for(int i=0; i < int(outgoing2.size()); ++i)
1266  if (outgoing2[i] != 99)
1267  done = false;
1268  // Return
1269  if (done) return;
1270 
1271  // Leptons not associated with resonance are allowed.
1272  // Try to find all unmatched hard process leptons.
1273  // Loop through event to find outgoing lepton
1274  for(int i=0; i < int(event.size()); ++i){
1275  // Skip non-final particles and final partons
1276  if ( !event[i].isFinal() || event[i].colType() != 0)
1277  continue;
1278  // Skip all particles that have already been identified
1279  bool skip = false;
1280  for(int k=0; k < int(iPosChecked.size()); ++k){
1281  if (i == iPosChecked[k])
1282  skip = true;
1283  }
1284  if (skip) continue;
1285 
1286  // Check if any hard outgoing leptons remain
1287  for(int j=0; j < int(outgoing2.size()); ++j){
1288  // Do nothing if this particle has already be found,
1289  // or if this particle is a jet or quark
1290  if ( outgoing2[j] == 99
1291  || outgoing2[j] == 2212
1292  || abs(outgoing2[j]) < 10)
1293  continue;
1294 
1295  // If the particle matches an outgoing lepton, save it
1296  if ( event[i].id() == outgoing2[j] ){
1297  PosOutgoing2[j] = i;
1298  outgoing2[j] = 99;
1299  iPosChecked.push_back(i);
1300  }
1301  }
1302 
1303  // Check if any hard outgoing antileptons remain
1304  for(int j=0; j < int(outgoing1.size()); ++j){
1305  // Do nothing if this particle has already be found,
1306  // or if this particle is a jet or quark
1307  if ( outgoing1[j] == 99
1308  || outgoing1[j] == 2212
1309  || abs(outgoing1[j]) < 10)
1310  continue;
1311 
1312  // If the particle matches an outgoing lepton, save it
1313  if (event[i].id() == outgoing1[j] ){
1314  PosOutgoing1[j] = i;
1315  outgoing1[j] = 99;
1316  iPosChecked.push_back(i);
1317  }
1318  }
1319  }
1320 
1321  multimap<int,int> out2copy;
1322  for(int i=0; i < int(event.size()); ++i)
1323  for(int j=0; j < int(outgoing2.size()); ++j)
1324  // Do nothing if this particle has already be found,
1325  // or if this particle is a jet.
1326  if ( outgoing2[j] != 99
1327  && outgoing2[j] != 2212
1328  && ( abs(outgoing2[j]) < 10
1329  || (abs(outgoing2[j]) > 1000000 && abs(outgoing2[j]) < 1000010)
1330  || (abs(outgoing2[j]) > 2000000 && abs(outgoing2[j]) < 2000010)
1331  || abs(outgoing2[j]) == 1000021 )
1332  && event[i].isFinal()
1333  && event[i].id() == outgoing2[j] ){
1334  out2copy.insert(make_pair(j, i));
1335  }
1336 
1337  multimap<int,int> out1copy;
1338  for(int i=0; i < int(event.size()); ++i)
1339  for(int j=0; j < int(outgoing1.size()); ++j)
1340  // Do nothing if this particle has already be found,
1341  // or if this particle is a jet.
1342  if ( outgoing1[j] != 99
1343  && outgoing1[j] != 2212
1344  && ( abs(outgoing1[j]) < 10
1345  || (abs(outgoing1[j]) > 1000000 && abs(outgoing1[j]) < 1000010)
1346  || (abs(outgoing1[j]) > 2000000 && abs(outgoing1[j]) < 2000010)
1347  || abs(outgoing2[j]) == 1000021 )
1348  && event[i].isFinal()
1349  && event[i].id() == outgoing1[j] ){
1350  out1copy.insert(make_pair(j, i));
1351  }
1352 
1353  if ( out1copy.size() > out2copy.size()){
1354 
1355  // In case the index of the multimap is filled twice, make sure not to
1356  // arbitrarily overwrite set values.
1357  vector<int> indexWasSet;
1358  for ( multimap<int, int>::iterator it = out2copy.begin();
1359  it != out2copy.end(); ++it ) {
1360  if ( allowCandidates(it->second, PosOutgoing1, PosOutgoing2, event) ){
1361 
1362  // Skip all particles that have already been identified
1363  bool skip = false;
1364  for(int k=0; k < int(iPosChecked.size()); ++k)
1365  if (it->second == iPosChecked[k]) skip = true;
1366  // Skip all indices that have already been identified
1367  for(int k=0; k < int(indexWasSet.size()); ++k)
1368  if (it->first == indexWasSet[k]) skip = true;
1369  if (skip) continue;
1370 
1371  // Save parton
1372  PosOutgoing2[it->first] = it->second;
1373  // remove entry form lists
1374  outgoing2[it->first] = 99;
1375  iPosChecked.push_back(it->second);
1376  indexWasSet.push_back(it->first);
1377  }
1378  }
1379 
1380  indexWasSet.resize(0);
1381  for ( multimap<int, int>::iterator it = out1copy.begin();
1382  it != out1copy.end(); ++it ) {
1383  if ( allowCandidates(it->second, PosOutgoing1, PosOutgoing2, event) ){
1384 
1385  // Skip all particles that have already been identified
1386  bool skip = false;
1387  for(int k=0; k < int(iPosChecked.size()); ++k)
1388  if (it->second == iPosChecked[k]) skip = true;
1389  // Skip all indices that have already been identified
1390  for(int k=0; k < int(indexWasSet.size()); ++k)
1391  if (it->first == indexWasSet[k]) skip = true;
1392  if (skip) continue;
1393 
1394  // Save parton
1395  PosOutgoing1[it->first] = it->second;
1396  // remove entry form lists
1397  outgoing1[it->first] = 99;
1398  iPosChecked.push_back(it->second);
1399  indexWasSet.push_back(it->first);
1400  }
1401  }
1402 
1403  } else {
1404 
1405  // In case the index of the multimap is filled twice, make sure not to
1406  // arbitraryly overwrite set values.
1407  vector<int> indexWasSet;
1408  for ( multimap<int, int>::iterator it = out1copy.begin();
1409  it != out1copy.end(); ++it ) {
1410  if ( allowCandidates(it->second, PosOutgoing1, PosOutgoing2, event) ){
1411 
1412  // Skip all particles that have already been identified
1413  bool skip = false;
1414  for(int k=0; k < int(iPosChecked.size()); ++k)
1415  if (it->second == iPosChecked[k]) skip = true;
1416  // Skip all indices that have already been identified
1417  for(int k=0; k < int(indexWasSet.size()); ++k)
1418  if (it->first == indexWasSet[k]) skip = true;
1419  if (skip) continue;
1420 
1421  // Save parton
1422  PosOutgoing1[it->first] = it->second;
1423  // remove entry form lists
1424  outgoing1[it->first] = 99;
1425  iPosChecked.push_back(it->second);
1426  indexWasSet.push_back(it->first);
1427  }
1428  }
1429 
1430  indexWasSet.resize(0);
1431  for ( multimap<int, int>::iterator it = out2copy.begin();
1432  it != out2copy.end(); ++it ) {
1433  if ( allowCandidates(it->second, PosOutgoing1, PosOutgoing2, event) ){
1434 
1435  // Skip all particles that have already been identified
1436  bool skip = false;
1437  for(int k=0; k < int(iPosChecked.size()); ++k)
1438  if (it->second == iPosChecked[k]) skip = true;
1439  // Skip all indices that have already been identified
1440  for(int k=0; k < int(indexWasSet.size()); ++k)
1441  if (it->first == indexWasSet[k]) skip = true;
1442  if (skip) continue;
1443 
1444  // Save parton
1445  PosOutgoing2[it->first] = it->second;
1446  // remove entry form lists
1447  outgoing2[it->first] = 99;
1448  iPosChecked.push_back(it->second);
1449  indexWasSet.push_back(it->first);
1450  }
1451  }
1452  }
1453 
1454  // It sometimes happens that MadEvent does not put a
1455  // heavy coloured resonance into the LHE file, even if requested.
1456  // This means that the decay products of this resonance need to be
1457  // found separately.
1458  // Loop through event to find hard process (anti)quarks
1459  for(int i=0; i < int(event.size()); ++i){
1460 
1461  // Skip non-final particles and final partons
1462  if ( !event[i].isFinal() || event[i].colType() == 0)
1463  continue;
1464 
1465  // Skip all particles that have already been identified
1466  bool skip = false;
1467  for(int k=0; k < int(iPosChecked.size()); ++k){
1468  if (i == iPosChecked[k])
1469  skip = true;
1470  }
1471  if (skip) continue;
1472 
1473  // Check if any hard outgoing quarks remain
1474  for(int j=0; j < int(outgoing2.size()); ++j){
1475  // Do nothing if this particle has already be found,
1476  // or if this particle is a jet, lepton container or lepton
1477  if ( outgoing2[j] == 99
1478  || outgoing2[j] == 2212
1479  || abs(outgoing2[j]) > 10)
1480  continue;
1481  // If the particle matches an outgoing quark, save it
1482  if (event[i].id() == outgoing2[j]){
1483  // Save parton
1484  PosOutgoing2[j] = i;
1485  // remove entry form lists
1486  outgoing2[j] = 99;
1487  iPosChecked.push_back(i);
1488  }
1489  }
1490 
1491  // Check if any hard outgoing antiquarks remain
1492  for(int j=0; j < int(outgoing1.size()); ++j){
1493  // Do nothing if this particle has already be found,
1494  // or if this particle is a jet, lepton container or lepton
1495  if ( outgoing1[j] == 99
1496  || outgoing1[j] == 2212
1497  || abs(outgoing1[j]) > 10)
1498  continue;
1499  // If the particle matches an outgoing antiquark, save it
1500  if (event[i].id() == outgoing1[j]){
1501  // Save parton
1502  PosOutgoing1[j] = i;
1503  // Remove parton from list
1504  outgoing1[j] = 99;
1505  iPosChecked.push_back(i);
1506  }
1507  }
1508  }
1509 
1510  // Done
1511 }
1512 
1513 //--------------------------------------------------------------------------
1514 
1515 // Function to check if the particle event[iPos] matches any of
1516 // the stored outgoing particles of the hard subprocess
1517 
1518 bool HardProcess::matchesAnyOutgoing(int iPos, const Event& event){
1519 
1520  // Match quantum numbers of any first outgoing candidate
1521  bool matchQN1 = false;
1522  // Match quantum numbers of any second outgoing candidate
1523  bool matchQN2 = false;
1524  // Match parton in the hard process,
1525  // or parton from decay of electroweak boson in hard process,
1526  // or parton from decay of electroweak boson from decay of top
1527  bool matchHP = false;
1528 
1529  // Check outgoing candidates
1530  for(int i=0; i < int(PosOutgoing1.size()); ++i)
1531  // Compare particle properties
1532  if ( event[iPos].id() == state[PosOutgoing1[i]].id()
1533  && event[iPos].colType() == state[PosOutgoing1[i]].colType()
1534  && event[iPos].chargeType() == state[PosOutgoing1[i]].chargeType()
1535  && ( ( event[iPos].col() > 0
1536  && event[iPos].col() == state[PosOutgoing1[i]].col())
1537  || ( event[iPos].acol() > 0
1538  && event[iPos].acol() == state[PosOutgoing1[i]].acol()))
1539  && event[iPos].charge() == state[PosOutgoing1[i]].charge() )
1540  matchQN1 = true;
1541 
1542  // Check outgoing candidates
1543  for(int i=0; i < int(PosOutgoing2.size()); ++i)
1544  // Compare particle properties
1545  if ( event[iPos].id() == state[PosOutgoing2[i]].id()
1546  && event[iPos].colType() == state[PosOutgoing2[i]].colType()
1547  && event[iPos].chargeType() == state[PosOutgoing2[i]].chargeType()
1548  && ( ( event[iPos].col() > 0
1549  && event[iPos].col() == state[PosOutgoing2[i]].col())
1550  || ( event[iPos].acol() > 0
1551  && event[iPos].acol() == state[PosOutgoing2[i]].acol()))
1552  && event[iPos].charge() == state[PosOutgoing2[i]].charge() )
1553  matchQN2 = true;
1554 
1555  // Check if maps to hard process:
1556  // Check that particle is in hard process
1557  if ( event[iPos].mother1()*event[iPos].mother2() == 12
1558  // Or particle has taken recoil from first splitting
1559  || ( event[iPos].status() == 44
1560  && event[event[iPos].mother1()].mother1()
1561  *event[event[iPos].mother1()].mother2() == 12 )
1562  // Or particle has on-shell resonace as mother
1563  || ( event[iPos].status() == 23
1564  && event[event[iPos].mother1()].mother1()
1565  *event[event[iPos].mother1()].mother2() == 12 )
1566  // Or particle has on-shell resonace as mother,
1567  // which again has and on-shell resonance as mother
1568  || ( event[iPos].status() == 23
1569  && event[event[iPos].mother1()].status() == -22
1570  && event[event[event[iPos].mother1()].mother1()].status() == -22
1571  && event[event[event[iPos].mother1()].mother1()].mother1()
1572  *event[event[event[iPos].mother1()].mother1()].mother2() == 12 ) )
1573  matchHP = true;
1574 
1575  // Done
1576  return ( matchHP && (matchQN1 || matchQN2) );
1577 
1578 }
1579 
1580 
1581 //--------------------------------------------------------------------------
1582 
1583 // Function to check if instead of the particle event[iCandidate], another
1584 // particle could serve as part of the hard process. Assumes that iCandidate
1585 // is already stored as part of the hard process.
1586 
1587 bool HardProcess::findOtherCandidates(int iPos, const Event& event,
1588  bool doReplace){
1589 
1590  // Return value
1591  bool foundCopy = false;
1592 
1593  // Save stored candidates' properties.
1594  int id = event[iPos].id();
1595  int col = event[iPos].col();
1596  int acl = event[iPos].acol();
1597 
1598  // If the particle's mother is an identified intermediate resonance,
1599  // then do not attempt any replacement.
1600  int iMoth1 = event[iPos].mother1();
1601  int iMoth2 = event[iPos].mother2();
1602  if ( iMoth1 > 0 && iMoth2 == 0 ) {
1603  bool hasIdentifiedMother = false;
1604  for(int i=0; i < int(PosIntermediate.size()); ++i)
1605  // Compare particle properties
1606  if ( event[iMoth1].id() == state[PosIntermediate[i]].id()
1607  && event[iMoth1].colType() == state[PosIntermediate[i]].colType()
1608  && event[iMoth1].chargeType() == state[PosIntermediate[i]].chargeType()
1609  && event[iMoth1].col() == state[PosIntermediate[i]].col()
1610  && event[iMoth1].acol() == state[PosIntermediate[i]].acol()
1611  && event[iMoth1].charge() == state[PosIntermediate[i]].charge() )
1612  hasIdentifiedMother = true;
1613  if(hasIdentifiedMother && event[iMoth1].id() != id) return false;
1614  }
1615 
1616  // Find candidate amongst the already stored ME process candidates.
1617  vector<int> candidates1;
1618  vector<int> candidates2;
1619  // Check outgoing candidates
1620  for(int i=0; i < int(PosOutgoing1.size()); ++i)
1621  // Compare particle properties
1622  if ( id == state[PosOutgoing1[i]].id()
1623  && col == state[PosOutgoing1[i]].col()
1624  && acl == state[PosOutgoing1[i]].acol() )
1625  candidates1.push_back(i);
1626  // Check outgoing candidates
1627  for(int i=0; i < int(PosOutgoing2.size()); ++i)
1628  // Compare particle properties
1629  if ( id == state[PosOutgoing2[i]].id()
1630  && col == state[PosOutgoing2[i]].col()
1631  && acl == state[PosOutgoing2[i]].acol() )
1632  candidates2.push_back(i);
1633 
1634  // If more / less than one stored candidate for iPos has been found, exit.
1635  if ( candidates1.size() + candidates2.size() != 1 ) return false;
1636 
1637  // Now check for other allowed candidates.
1638  map<int,int> further1;
1639  for(int i=0; i < int(state.size()); ++i)
1640  for(int j=0; j < int(PosOutgoing1.size()); ++j)
1641  // Do nothing if this particle has already be found,
1642  // or if this particle is a jet, lepton container or lepton
1643  if ( state[i].isFinal()
1644  && i != PosOutgoing1[j]
1645  && state[PosOutgoing1[j]].id() == id
1646  && state[i].id() == id ){
1647  // Declare vector of already existing candiates.
1648  vector<int> newPosOutgoing1;
1649  for(int k=0; k < int(PosOutgoing1.size()); ++k)
1650  if ( k != j ) newPosOutgoing1.push_back( PosOutgoing1[k] );
1651  // If allowed, remember replacment parton.
1652  if ( allowCandidates(i, newPosOutgoing1, PosOutgoing2, state) )
1653  further1.insert(make_pair(j, i));
1654  }
1655 
1656  // Now check for other allowed candidates.
1657  map<int,int> further2;
1658  for(int i=0; i < int(state.size()); ++i)
1659  for(int j=0; j < int(PosOutgoing2.size()); ++j)
1660  // Do nothing if this particle has already be found,
1661  // or if this particle is a jet, lepton container or lepton
1662  if ( state[i].isFinal()
1663  && i != PosOutgoing2[j]
1664  && state[PosOutgoing2[j]].id() == id
1665  && state[i].id() == id ){
1666  // Declare vector of already existing candidates.
1667  vector<int> newPosOutgoing2;
1668  for(int k=0; k < int(PosOutgoing2.size()); ++k)
1669  if ( k != j ) newPosOutgoing2.push_back( PosOutgoing2[k] );
1670  // If allowed, remember replacment parton.
1671  if ( allowCandidates(i, PosOutgoing1, newPosOutgoing2, state) )
1672  further2.insert(make_pair(j, i));
1673  }
1674 
1675  // Decide of a replacment candidate has been found.
1676  foundCopy = (doReplace)
1677  ? exchangeCandidates(candidates1, candidates2, further1, further2)
1678  : (further1.size() + further2.size() > 0);
1679 
1680  // Done
1681  return foundCopy;
1682 
1683 }
1684 
1685 //--------------------------------------------------------------------------
1686 
1687 // Function to exchange hard process candidates.
1688 
1689 bool HardProcess::exchangeCandidates( vector<int> candidates1,
1690  vector<int> candidates2, map<int,int> further1, map<int,int> further2) {
1691 
1692  int nOld1 = candidates1.size();
1693  int nOld2 = candidates2.size();
1694  int nNew1 = further1.size();
1695  int nNew2 = further2.size();
1696  bool exchanged = false;
1697  // Replace, if one-to-one correspondence exists.
1698  if ( nOld1 == 1 && nOld2 == 0 && nNew1 == 1 && nNew2 == 0){
1699  PosOutgoing1[further1.begin()->first] = further1.begin()->second;
1700  exchanged = true;
1701  } else if ( nOld1 == 0 && nOld2 == 1 && nNew1 == 0 && nNew2 == 1){
1702  PosOutgoing2[further2.begin()->first] = further2.begin()->second;
1703  exchanged = true;
1704  // Else simply swap with the first candidate.
1705  } else if ( nNew1 > 1 && nNew2 == 0 ) {
1706  PosOutgoing1[further1.begin()->first] = further1.begin()->second;
1707  exchanged = true;
1708  } else if ( nNew1 == 0 && nNew2 > 0 ) {
1709  PosOutgoing2[further2.begin()->first] = further2.begin()->second;
1710  exchanged = true;
1711  }
1712 
1713  // Done
1714  return exchanged;
1715 
1716 }
1717 
1718 //--------------------------------------------------------------------------
1719 
1720 // Function to get the number of coloured final state partons in the
1721 // hard process
1722 
1723 int HardProcess::nQuarksOut(){
1724  int nFin =0;
1725  for(int i =0; i< int(hardOutgoing1.size()); ++i){
1726  if (hardOutgoing1[i] == 2212 || abs(hardOutgoing1[i]) < 10) nFin++;
1727  }
1728  for(int i =0; i< int(hardOutgoing2.size()); ++i){
1729  if (hardOutgoing2[i] == 2212 || abs(hardOutgoing2[i]) < 10) nFin++;
1730  }
1731  // For very loose hard process definition, check number of hard process
1732  // b-quarks explicitly.
1733  for(int i =0; i< int(hardOutgoing1.size()); ++i)
1734  if (hardOutgoing1[i] == 5000)
1735  for(int j =0; j< int(PosOutgoing1.size()); ++j)
1736  if (state[PosOutgoing1[j]].idAbs() == 5)
1737  nFin++;
1738  for(int i =0; i< int(hardOutgoing2.size()); ++i)
1739  if (hardOutgoing2[i] == 5000)
1740  for(int j =0; j< int(PosOutgoing2.size()); ++j)
1741  if (state[PosOutgoing2[j]].idAbs() == 5)
1742  nFin++;
1743  return nFin;
1744 }
1745 
1746 //--------------------------------------------------------------------------
1747 
1748 // Function to get the number of uncoloured final state particles in the
1749 // hard process
1750 
1751 int HardProcess::nLeptonOut(){
1752  int nFin =0;
1753  for(int i =0; i< int(hardOutgoing1.size()); ++i){
1754  if (abs(hardOutgoing1[i]) > 10 && abs(hardOutgoing1[i]) < 20) nFin++;
1755  // Bookkeep MSSM neutralinos as leptons
1756  if (abs(hardOutgoing1[i]) == 1000022) nFin++;
1757  // Bookkeep sleptons as leptons
1758  if ( abs(hardOutgoing1[i]) == 1000011 || abs(hardOutgoing1[i]) == 2000011
1759  || abs(hardOutgoing1[i]) == 1000013 || abs(hardOutgoing1[i]) == 2000013
1760  || abs(hardOutgoing1[i]) == 1000015 || abs(hardOutgoing1[i]) == 2000015)
1761  nFin++;
1762  }
1763  for(int i =0; i< int(hardOutgoing2.size()); ++i){
1764  if (abs(hardOutgoing2[i]) > 10 && abs(hardOutgoing2[i]) < 20) nFin++;
1765  // Bookkeep MSSM neutralinos as leptons
1766  if (abs(hardOutgoing2[i]) == 1000022) nFin++;
1767  // Bookkeep sleptons as leptons
1768  if ( abs(hardOutgoing2[i]) == 1000011 || abs(hardOutgoing2[i]) == 2000011
1769  || abs(hardOutgoing2[i]) == 1000013 || abs(hardOutgoing2[i]) == 2000013
1770  || abs(hardOutgoing2[i]) == 1000015 || abs(hardOutgoing2[i]) == 2000015)
1771  nFin++;
1772  }
1773 
1774  // For very loose hard process definition, check number of hard process
1775  // lepton explicitly.
1776  // Check lepton / neutrino containers as leptons
1777  for(int i =0; i< int(hardOutgoing1.size()); ++i)
1778  if (hardOutgoing1[i] == 1100)
1779  for(int j =0; j< int(PosOutgoing1.size()); ++j)
1780  if ( abs(state[PosOutgoing1[j]].id()) == 11
1781  || abs(state[PosOutgoing1[j]].id()) == 13
1782  || abs(state[PosOutgoing1[j]].id()) == 15 )
1783  nFin++;
1784  for(int i =0; i< int(hardOutgoing2.size()); ++i)
1785  if (hardOutgoing2[i] == 1200)
1786  for(int j =0; j< int(PosOutgoing2.size()); ++j)
1787  if ( abs(state[PosOutgoing2[j]].id()) == 12
1788  || abs(state[PosOutgoing2[j]].id()) == 14
1789  || abs(state[PosOutgoing2[j]].id()) == 16 )
1790  nFin++;
1791  return nFin;
1792 }
1793 
1794 //--------------------------------------------------------------------------
1795 
1796 // Function to get the number of uncoloured final state particles in the
1797 // hard process
1798 
1799 int HardProcess::nBosonsOut(){
1800  int nFin =0;
1801  for(int i =0; i< int(hardOutgoing1.size()); ++i){
1802  if (abs(hardOutgoing1[i]) > 20 && abs(hardOutgoing1[i]) <= 25) nFin++;
1803  }
1804  for(int i =0; i< int(hardOutgoing2.size()); ++i){
1805  if (abs(hardOutgoing2[i]) > 20 && abs(hardOutgoing2[i]) <= 25) nFin++;
1806  if ( hardOutgoing2[i] == 2400) nFin++;
1807  }
1808  return nFin;
1809 }
1810 
1811 //--------------------------------------------------------------------------
1812 
1813 // Function to get the number of coloured initial state partons in the
1814 // hard process
1815 
1816 int HardProcess::nQuarksIn(){
1817  int nIn =0;
1818  if (hardIncoming1 == 2212 || abs(hardIncoming1) < 10) nIn++;
1819  if (hardIncoming2 == 2212 || abs(hardIncoming2) < 10) nIn++;
1820  return nIn;
1821 }
1822 
1823 //--------------------------------------------------------------------------
1824 
1825 // Function to get the number of uncoloured initial state particles in the
1826 // hard process
1827 
1828 int HardProcess::nLeptonIn(){
1829  int nIn =0;
1830  if (abs(hardIncoming1) > 10 && abs(hardIncoming1) < 20) nIn++;
1831  if (abs(hardIncoming2) > 10 && abs(hardIncoming2) < 20) nIn++;
1832  return nIn;
1833 }
1834 
1835 //--------------------------------------------------------------------------
1836 
1837 // Function to report if a resonace decay was found in the
1838 // 2->2 hard sub-process in the current state
1839 
1840 int HardProcess::hasResInCurrent(){
1841  for(int i =0; i< int(PosIntermediate.size()); ++i)
1842  if (PosIntermediate[i] == 0) return 0;
1843  // Do not count final state bosons as resonaces
1844  for(int i =0; i< int(PosIntermediate.size()); ++i){
1845  for(int j =0; j< int(PosOutgoing1.size()); ++j){
1846  if ( PosIntermediate[i] == PosOutgoing1[j] )
1847  return 0;
1848  }
1849  for(int j =0; j< int(PosOutgoing2.size()); ++j){
1850  if ( PosIntermediate[i] == PosOutgoing2[j] )
1851  return 0;
1852  }
1853  }
1854  return 1;
1855 }
1856 
1857 //--------------------------------------------------------------------------
1858 
1859 // Function to report the number of resonace decays in the 2->2 sub-process
1860 // of the current state
1861 
1862 int HardProcess::nResInCurrent(){
1863  int nRes = 0;
1864  for(int i =0; i< int(PosIntermediate.size()); ++i){
1865  if (PosIntermediate[i] != 0) {
1866  bool matchesFinalBoson = false;
1867  for(int j =0; j< int(PosOutgoing1.size()); ++j){
1868  if ( PosIntermediate[i] == PosOutgoing1[j] )
1869  matchesFinalBoson = true;
1870  }
1871  for(int j =0; j< int(PosOutgoing2.size()); ++j){
1872  if ( PosIntermediate[i] == PosOutgoing2[j] )
1873  matchesFinalBoson = true;
1874  }
1875  if (!matchesFinalBoson) nRes++;
1876  }
1877  }
1878  return nRes;
1879 }
1880 
1881 //--------------------------------------------------------------------------
1882 
1883 // Function to report if a resonace decay was found in the
1884 // 2->2 hard core process
1885 
1886 bool HardProcess::hasResInProc(){
1887 
1888  for(int i =0; i< int(hardIntermediate.size()); ++i)
1889  if (hardIntermediate[i] == 0) return false;
1890  // Do not count final state bosons as resonaces
1891  for(int i =0; i< int(hardIntermediate.size()); ++i){
1892  for(int j =0; j< int(hardOutgoing1.size()); ++j){
1893  if ( hardIntermediate[i] == hardOutgoing1[j] )
1894  return false;
1895  }
1896  for(int j =0; j< int(hardOutgoing2.size()); ++j){
1897  if ( hardIntermediate[i] == hardOutgoing2[j] )
1898  return false;
1899  }
1900  }
1901  return true;
1902 }
1903 
1904 //--------------------------------------------------------------------------
1905 
1906 // Function to print the hard process (for debug)
1907 
1908 void HardProcess::list() const {
1909  cout << " Hard Process: ";
1910  cout << " \t " << hardIncoming1 << " + " << hardIncoming2;
1911  cout << " \t -----> \t ";
1912  for(int i =0; i < int(hardIntermediate.size());++i)
1913  cout << hardIntermediate[i] << " ";
1914  cout << " \t -----> \t ";
1915  for(int i =0; i < int(hardOutgoing1.size());++i)
1916  cout << hardOutgoing1[i] << " ";
1917  for(int i =0; i < int(hardOutgoing2.size());++i)
1918  cout << hardOutgoing2[i] << " ";
1919  cout << endl;
1920 }
1921 
1922 //--------------------------------------------------------------------------
1923 
1924 // Function to list the hard process candiates in the matrix element state
1925 // (for debug)
1926 
1927 void HardProcess::listCandidates() const {
1928  cout << " Hard Process candidates: ";
1929  cout << " \t " << hardIncoming1 << " + " << hardIncoming2;
1930  cout << " \t -----> \t ";
1931  for(int i =0; i < int(PosIntermediate.size());++i)
1932  cout << PosIntermediate[i] << " ";
1933  cout << " \t -----> \t ";
1934  for(int i =0; i < int(PosOutgoing1.size());++i)
1935  cout << PosOutgoing1[i] << " ";
1936  for(int i =0; i < int(PosOutgoing2.size());++i)
1937  cout << PosOutgoing2[i] << " ";
1938  cout << endl;
1939 }
1940 
1941 //--------------------------------------------------------------------------
1942 
1943 // Function to clear hard process information
1944 
1945 void HardProcess::clear() {
1946 
1947  // Clear flavour of the first incoming particle
1948  hardIncoming1 = hardIncoming2 = 0;
1949  // Clear outgoing particles
1950  hardOutgoing1.resize(0);
1951  hardOutgoing2.resize(0);
1952  // Clear intermediate bosons in the hard 2->2
1953  hardIntermediate.resize(0);
1954 
1955  // Clear reference event
1956  state.clear();
1957 
1958  // Clear potential positions of outgoing particles in reference event
1959  PosOutgoing1.resize(0);
1960  PosOutgoing2.resize(0);
1961  // Clear potential positions of intermediate bosons in reference event
1962  PosIntermediate.resize(0);
1963 
1964  // Clear merging scale read from LHE file
1965  tms = 0.;
1966 
1967 }
1968 
1969 //==========================================================================
1970 
1971 // The MergingHooks class.
1972 
1973 //--------------------------------------------------------------------------
1974 
1975 // Initialise MergingHooks class
1976 
1977 void MergingHooks::init( Settings settings, Info* infoPtrIn,
1978  ParticleData* particleDataPtrIn, PartonSystems* partonSystemsPtrIn,
1979  ostream& os){
1980 
1981  // Save pointers
1982  infoPtr = infoPtrIn;
1983  particleDataPtr = particleDataPtrIn;
1984  partonSystemsPtr = partonSystemsPtrIn;
1985 
1986  // Initialise AlphaS objects for reweighting
1987  double alphaSvalueFSR = settings.parm("TimeShower:alphaSvalue");
1988  int alphaSorderFSR = settings.mode("TimeShower:alphaSorder");
1989  int alphaSnfmax = settings.mode("StandardModel:alphaSnfmax");
1990  int alphaSuseCMWFSR= settings.flag("TimeShower:alphaSuseCMW");
1991  AlphaS_FSRSave.init(alphaSvalueFSR, alphaSorderFSR, alphaSnfmax,
1992  alphaSuseCMWFSR);
1993  double alphaSvalueISR = settings.parm("SpaceShower:alphaSvalue");
1994  int alphaSorderISR = settings.mode("SpaceShower:alphaSorder");
1995  int alphaSuseCMWISR= settings.flag("SpaceShower:alphaSuseCMW");
1996  AlphaS_ISRSave.init(alphaSvalueISR, alphaSorderISR, alphaSnfmax,
1997  alphaSuseCMWISR);
1998 
1999  // Initialise AlphaEM objects for reweighting
2000  int alphaEMFSRorder = settings.mode("TimeShower:alphaEMorder");
2001  AlphaEM_FSRSave.init(alphaEMFSRorder, &settings);
2002 
2003  // Initialise merging switches
2004  doUserMergingSave = settings.flag("Merging:doUserMerging");
2005  // Initialise automated MadGraph kT merging
2006  doMGMergingSave = settings.flag("Merging:doMGMerging");
2007  // Initialise kT merging
2008  doKTMergingSave = settings.flag("Merging:doKTMerging");
2009  // Initialise evolution-pT merging
2010  doPTLundMergingSave = settings.flag("Merging:doPTLundMerging");
2011  // Initialise \Delta_R_{ij}, pT_i Q_{ij} merging
2012  doCutBasedMergingSave = settings.flag("Merging:doCutBasedMerging");
2013  // Initialise exact definition of kT
2014  ktTypeSave = settings.mode("Merging:ktType");
2015 
2016  // Initialise NL3 switches.
2017  doNL3TreeSave = settings.flag("Merging:doNL3Tree");
2018  doNL3LoopSave = settings.flag("Merging:doNL3Loop");
2019  doNL3SubtSave = settings.flag("Merging:doNL3Subt");
2020  bool doNL3 = doNL3TreeSave || doNL3LoopSave || doNL3SubtSave;
2021 
2022  // Initialise UNLOPS switches.
2023  doUNLOPSTreeSave = settings.flag("Merging:doUNLOPSTree");
2024  doUNLOPSLoopSave = settings.flag("Merging:doUNLOPSLoop");
2025  doUNLOPSSubtSave = settings.flag("Merging:doUNLOPSSubt");
2026  doUNLOPSSubtNLOSave = settings.flag("Merging:doUNLOPSSubtNLO");
2027  bool doUNLOPS = doUNLOPSTreeSave || doUNLOPSLoopSave
2028  || doUNLOPSSubtSave || doUNLOPSSubtNLOSave;
2029 
2030  // Initialise UMEPS switches
2031  doUMEPSTreeSave = settings.flag("Merging:doUMEPSTree");
2032  doUMEPSSubtSave = settings.flag("Merging:doUMEPSSubt");
2033  nReclusterSave = settings.mode("Merging:nRecluster");
2034  nQuarksMergeSave = settings.mode("Merging:nQuarksMerge");
2035  bool doUMEPS = doUMEPSTreeSave || doUMEPSSubtSave;
2036 
2037  // Flag to only do phase space cut.
2038  doEstimateXSection = settings.flag("Merging:doXSectionEstimate");
2039 
2040  // Get core process from user input
2041  processSave = settings.word("Merging:Process");
2042 
2043  // Clear hard process
2044  hardProcess.clear();
2045 
2046  // Initialise input event.
2047  inputEvent.init("(hard process)", particleDataPtr);
2048  doRemoveDecayProducts = settings.flag("Merging:mayRemoveDecayProducts");
2049 
2050  // Initialise the hard process
2051  if ( doMGMergingSave )
2052  hardProcess.initOnLHEF(lheInputFile, particleDataPtr);
2053  else
2054  hardProcess.initOnProcess(processSave, particleDataPtr);
2055 
2056  // Parameters for reconstruction of evolution scales
2057  includeMassiveSave = settings.flag("Merging:includeMassive");
2058  enforceStrongOrderingSave = settings.flag("Merging:enforceStrongOrdering");
2059  scaleSeparationFactorSave = settings.parm("Merging:scaleSeparationFactor");
2060  orderInRapiditySave = settings.flag("Merging:orderInRapidity");
2061 
2062  // Parameters for choosing history probabilistically
2063  nonJoinedNormSave = settings.parm("Merging:nonJoinedNorm");
2064  fsrInRecNormSave = settings.parm("Merging:fsrInRecNorm");
2065  pickByFullPSave = settings.flag("Merging:pickByFullP");
2066  pickByPoPT2Save = settings.flag("Merging:pickByPoPT2");
2067  includeRedundantSave = settings.flag("Merging:includeRedundant");
2068 
2069  // Parameters for scale choices
2070  unorderedScalePrescipSave =
2071  settings.mode("Merging:unorderedScalePrescrip");
2072  unorderedASscalePrescipSave =
2073  settings.mode("Merging:unorderedASscalePrescrip");
2074  unorderedPDFscalePrescipSave =
2075  settings.mode("Merging:unorderedPDFscalePrescrip");
2076  incompleteScalePrescipSave =
2077  settings.mode("Merging:incompleteScalePrescrip");
2078 
2079  // Parameter for allowing swapping of one colour index while reclustering
2080  allowColourShufflingSave =
2081  settings.flag("Merging:allowColourShuffling");
2082 
2083  // Parameters to allow setting hard process scales to default (dynamical)
2084  // Pythia values.
2085  resetHardQRenSave = settings.flag("Merging:usePythiaQRenHard");
2086  resetHardQFacSave = settings.flag("Merging:usePythiaQFacHard");
2087 
2088  // Parameters for choosing history by sum(|pT|)
2089  pickBySumPTSave = settings.flag("Merging:pickBySumPT");
2090  herwigAcollFSRSave = settings.parm("Merging:aCollFSR");
2091  herwigAcollISRSave = settings.parm("Merging:aCollISR");
2092 
2093  // Information on the shower cut-off scale
2094  pT0ISRSave = settings.parm("SpaceShower:pT0Ref");
2095  pTcutSave = settings.parm("SpaceShower:pTmin");
2096  pTcutSave = max(pTcutSave,pT0ISRSave);
2097 
2098  // Initialise CKKWL weight
2099  weightCKKWLSave = 1.;
2100  weightFIRSTSave = 0.;
2101  nMinMPISave = 100;
2102  muMISave = -1.;
2103 
2104  // Initialise merging scale
2105  tmsValueSave = 0.;
2106  tmsListSave.resize(0);
2107 
2108  kFactor0jSave = settings.parm("Merging:kFactor0j");
2109  kFactor1jSave = settings.parm("Merging:kFactor1j");
2110  kFactor2jSave = settings.parm("Merging:kFactor2j");
2111 
2112  muFSave = settings.parm("Merging:muFac");
2113  muRSave = settings.parm("Merging:muRen");
2114  muFinMESave = settings.parm("Merging:muFacInME");
2115  muRinMESave = settings.parm("Merging:muRenInME");
2116 
2117  doWClusteringSave = settings.flag("Merging:allowWClustering");
2118  doSQCDClusteringSave = settings.flag("Merging:allowSQCDClustering");
2119  DparameterSave = settings.parm("Merging:Dparameter");
2120 
2121  // Save merging scale on maximal number of jets
2122  if ( doKTMergingSave || doUserMergingSave || doPTLundMergingSave
2123  || doUMEPS ) {
2124  // Read merging scale (defined in kT) from input parameter.
2125  tmsValueSave = settings.parm("Merging:TMS");
2126  nJetMaxSave = settings.mode("Merging:nJetMax");
2127  nJetMaxNLOSave = -1;
2128  } else if (doMGMergingSave) {
2129  // Read merging scale (defined in kT) from LHE file.
2130  tmsValueSave = hardProcess.tms;
2131  nJetMaxSave = settings.mode("Merging:nJetMax");
2132  nJetMaxNLOSave = -1;
2133  } else if (doCutBasedMergingSave) {
2134 
2135  // Save list of cuts defining the merging scale.
2136  nJetMaxSave = settings.mode("Merging:nJetMax");
2137  nJetMaxNLOSave = -1;
2138  // Write tms cut values to list of cut values,
2139  // ordered by DeltaR_{ij}, pT_{i}, Q_{ij}.
2140  tmsListSave.resize(0);
2141  double drms = settings.parm("Merging:dRijMS");
2142  double ptms = settings.parm("Merging:pTiMS");
2143  double qms = settings.parm("Merging:QijMS");
2144  tmsListSave.push_back(drms);
2145  tmsListSave.push_back(ptms);
2146  tmsListSave.push_back(qms);
2147 
2148  }
2149 
2150  if ( doNL3 || doUNLOPS || doEstimateXSection ) {
2151  tmsValueSave = settings.parm("Merging:TMS");
2152  nJetMaxSave = settings.mode("Merging:nJetMax");
2153  nJetMaxNLOSave = settings.mode("Merging:nJetMaxNLO");
2154  }
2155 
2156  bool writeBanner = doKTMergingSave || doMGMergingSave
2157  || doUserMergingSave
2158  || doNL3 || doUNLOPS || doUMEPS
2159  || doPTLundMergingSave || doCutBasedMergingSave;
2160 
2161  if (!writeBanner) return;
2162 
2163  // Write banner
2164  os << "\n *------------------ MEPS Merging Initialization ---------------"
2165  << "---*";
2166  os << "\n | "
2167  << " |\n";
2168  if ( doKTMergingSave || doMGMergingSave || doUserMergingSave
2169  || doPTLundMergingSave || doCutBasedMergingSave )
2170  os << " | CKKW-L merge "
2171  << " |\n"
2172  << " |"<< setw(34) << processSave << " with up to"
2173  << setw(3) << nJetMaxSave << " additional jets |\n";
2174  else if ( doNL3 )
2175  os << " | NL3 merge "
2176  << " |\n"
2177  << " |" << setw(31) << processSave << " with jets up to"
2178  << setw(3) << nJetMaxNLOSave << " correct to NLO |\n"
2179  << " | and up to" << setw(3) << nJetMaxSave
2180  << " additional jets included by CKKW-L merging at LO |\n";
2181  else if ( doUNLOPS )
2182  os << " | UNLOPS merge "
2183  << " |\n"
2184  << " |" << setw(31) << processSave << " with jets up to"
2185  << setw(3)<< nJetMaxNLOSave << " correct to NLO |\n"
2186  << " | and up to" << setw(3) << nJetMaxSave
2187  << " additional jets included by UMEPS merging at LO |\n";
2188  else if ( doUMEPS )
2189  os << " | UMEPS merge "
2190  << " |\n"
2191  << " |" << setw(34) << processSave << " with up to"
2192  << setw(3) << nJetMaxSave << " additional jets |\n";
2193 
2194  if ( doKTMergingSave )
2195  os << " | Merging scale is defined in kT, with value ktMS = "
2196  << tmsValueSave << " GeV";
2197  else if ( doMGMergingSave )
2198  os << " | Perform automanted MG/ME merging \n"
2199  << " | Merging scale is defined in kT, with value ktMS = "
2200  << setw(6) << fixed << setprecision(1) << tmsValueSave << " GeV |";
2201  else if ( doUserMergingSave )
2202  os << " | Merging scale is defined by the user, with value tMS = "
2203  << setw(6) << fixed << setprecision(1) << tmsValueSave << " |";
2204  else if ( doPTLundMergingSave )
2205  os << " | Merging scale is defined by Lund pT, with value tMS = "
2206  << setw(6) << fixed << setprecision(1) << tmsValueSave << " GeV |";
2207  else if ( doCutBasedMergingSave )
2208  os << " | Merging scale is defined by combination of Delta R_{ij}, pT_i "
2209  << " |\n"
2210  << " | and Q_{ij} cut, with values "
2211  << " |\n"
2212  << " | Delta R_{ij,min} = "
2213  << setw(7) << scientific << setprecision(2) << tmsListSave[0]
2214  << " |\n"
2215  << " | pT_{i,min} = "
2216  << setw(6) << fixed << setprecision(1) << tmsListSave[1]
2217  << " GeV |\n"
2218  << " | Q_{ij,min} = "
2219  << setw(6) << fixed << setprecision(1) << tmsListSave[2]
2220  << " GeV |";
2221  else if ( doNL3TreeSave )
2222  os << " | Generate tree-level O(alpha_s)-subtracted events "
2223  << " |\n"
2224  << " | Merging scale is defined by Lund pT, with value tMS = "
2225  << setw(6) << fixed << setprecision(1) << tmsValueSave << " GeV |";
2226  else if ( doNL3LoopSave )
2227  os << " | Generate virtual correction unit-weight events "
2228  << " |\n"
2229  << " | Merging scale is defined by Lund pT, with value tMS = "
2230  << setw(6) << fixed << setprecision(1) << tmsValueSave << " GeV |";
2231  else if ( doNL3SubtSave )
2232  os << " | Generate reclustered tree-level events "
2233  << " |\n"
2234  << " | Merging scale is defined by Lund pT, with value tMS = "
2235  << setw(6) << fixed << setprecision(1) << tmsValueSave << " GeV |";
2236  else if ( doUNLOPSTreeSave )
2237  os << " | Generate tree-level O(alpha_s)-subtracted events "
2238  << " |\n"
2239  << " | Merging scale is defined by Lund pT, with value tMS = "
2240  << setw(6) << fixed << setprecision(1) << tmsValueSave << " GeV |";
2241  else if ( doUNLOPSLoopSave )
2242  os << " | Generate virtual correction unit-weight events "
2243  << " |\n"
2244  << " | Merging scale is defined by Lund pT, with value tMS = "
2245  << setw(6) << fixed << setprecision(1) << tmsValueSave << " GeV |";
2246  else if ( doUNLOPSSubtSave )
2247  os << " | Generate reclustered tree-level events "
2248  << " |\n"
2249  << " | Merging scale is defined by Lund pT, with value tMS = "
2250  << setw(6) << fixed << setprecision(1) << tmsValueSave << " GeV |";
2251  else if ( doUNLOPSSubtNLOSave )
2252  os << " | Generate reclustered loop-level events "
2253  << " |\n"
2254  << " | Merging scale is defined by Lund pT, with value tMS = "
2255  << setw(6) << fixed << setprecision(1) << tmsValueSave << " GeV |";
2256  else if ( doUMEPSTreeSave )
2257  os << " | Generate tree-level events "
2258  << " |\n"
2259  << " | Merging scale is defined by Lund pT, with value tMS = "
2260  << setw(6) << fixed << setprecision(1) << tmsValueSave << " GeV |";
2261  else if ( doUMEPSSubtSave )
2262  os << " | Generate reclustered tree-level events "
2263  << " |\n"
2264  << " | Merging scale is defined by Lund pT, with value tMS = "
2265  << setw(6) << fixed << setprecision(1) << tmsValueSave << " GeV |";
2266 
2267  os << "\n | "
2268  << " |";
2269  os << "\n *-------------- END MEPS Merging Initialization ---------------"
2270  << "---*\n\n";
2271 
2272 }
2273 
2274 //--------------------------------------------------------------------------
2275 
2276 // Function to check if emission should be rejected.
2277 
2278 bool MergingHooks::doVetoEmission( const Event& event) {
2279 
2280  // Do nothing in trial showers, or after first step.
2281  if ( doIgnoreEmissionsSave ) return false;
2282 
2283  // Do nothing in CKKW-L
2284  if ( doUserMerging() || doMGMerging() || doKTMerging()
2285  || doPTLundMerging() || doCutBasedMerging() )
2286  return false;
2287 
2288  // For NLO merging, count and veto emissions above the merging scale
2289  bool veto = false;
2290  // Get number of clustering steps
2291  int nSteps = getNumberOfClusteringSteps(event);
2292  // Get merging scale in current event
2293  double tnow = rhoms( event, false);
2294 
2295  // Get maximal number of additional jets
2296  int nJetMax = nMaxJets();
2297  // Always remove emissions above the merging scale for
2298  // samples containing reclusterings!
2299  if ( nRecluster() > 0 ) nSteps = max(1, min(nJetMax-2, 1));
2300  // Check veto condition
2301  if ( nSteps - 1 < nJetMax && nSteps >= 1 && tnow > tms() ) veto = true;
2302 
2303  // Do not veto if state already includes MPI.
2304  if ( infoPtr->nMPI() > 1 ) veto = false;
2305 
2306  // When performing NL3 merging of tree-level events, reset the
2307  // CKKWL weight.
2308  if ( veto && doNL3Tree() ) setWeightCKKWL(0.);
2309 
2310  // If the emission is allowed, do not check any further emissions
2311  if ( !veto ) doIgnoreEmissionsSave = true;
2312 
2313  // Done
2314  return veto;
2315 
2316 }
2317 
2318 //--------------------------------------------------------------------------
2319 
2320 // Function to check if emission should be rejected.
2321 
2322 bool MergingHooks::doVetoStep( const Event& process, const Event& event,
2323  bool doResonance ) {
2324 
2325  // Do nothing in trial showers, or after first step.
2326  if ( doIgnoreStepSave && !doResonance ) return false;
2327 
2328  // Do nothing in UMEPS or UNLOPS
2329  if ( doUMEPSTree() || doUMEPSSubt() || doUMEPSMerging() || doUNLOPSTree()
2330  || doUNLOPSLoop() || doUNLOPSSubt() || doUNLOPSSubtNLO()
2331  || doUNLOPSMerging() )
2332  return false;
2333 
2334  // Get number of clustering steps. If necessary, remove resonance
2335  // decay products first.
2336  int nSteps = (doResonance) ? getNumberOfClusteringSteps(process)
2337  : getNumberOfClusteringSteps( bareEvent( process, false) );
2338  // Get maximal number of additional jets.
2339  int nJetMax = nMaxJets();
2340  // Get merging scale in current event.
2341  double tnow = tmsNow( event );
2342 
2343  // For non-resonant showers, simply check veto. If event should indeed be
2344  // vetoed, save the current pT and weights in case the veto needs to be
2345  // revoked.
2346  if ( !doResonance ) {
2347 
2348  // Store pT to check if veto needs to be revoked later.
2349  pTsave = infoPtr->pTnow();
2350  if ( nRecluster() == 1) nSteps--;
2351 
2352  // Check merging veto condition.
2353  bool veto = false;
2354  if ( nSteps > nMaxJetsNLO() && nSteps < nJetMax && tnow > tms() ) {
2355  // Set weight to zero if event should be vetoed.
2356  weightCKKWL1Save = 0.;
2357  // Save weight before veto, in case veto needs to be revoked.
2358  weightCKKWL2Save = getWeightCKKWL();
2359  // Reset stored weights.
2360  setWeightCKKWL(0.);
2361  veto = true;
2362  }
2363 
2364  // Done
2365  return veto;
2366 
2367  // For resonant showers, check if any previous veto should be revoked.
2368  // This means we treat showers off resonance decay products identical to
2369  // MPI: If a hard resonance emission has been produced, the event should
2370  // have been kept. Following this reasoning, it might be necessary to revoke
2371  // any previous veto.
2372  } else {
2373 
2374  // Initialise switch to revoke vetoing.
2375  bool revokeVeto = false;
2376 
2377  // Nothing to check if pTsave was not stored, i.e. no emission to
2378  // possibly veto was recorded.
2379  // Only allow revoking the veto for diboson processes, with resonant
2380  // electroweak bosons
2381  bool check = (nHardInLeptons() == 0)&& (nHardOutLeptons() == 2)
2382  && (nHardOutPartons() == 2);
2383 
2384  // For current purpose only!!!
2385  check = false;
2386 
2387  // For hadronic resonance decays at hadron colliders, do not veto
2388  // events with a hard emission of the resonance decay products,
2389  // since such states are not included in the matrix element
2390  if ( pTsave > 0. && check ) {
2391 
2392  // Check how many resonance decay systems are allowed
2393  int nResNow = nResInCurrent();
2394 
2395  // Find systems really containing only emission off a resonance
2396  // decay
2397  vector<int>goodSys;
2398  // Resonance decay systems are considered last, thus at the end of
2399  // the list
2400  int sysSize = partonSystemsPtr->sizeSys();
2401  for ( int i=0; i < nResNow; ++i ) {
2402  if ( partonSystemsPtr->sizeOut(sysSize - 1 - i) == 3 )
2403  goodSys.push_back(sysSize - 1 - i);
2404  }
2405 
2406  // Check the members of the resonance decay systems
2407  for ( int i=0; i < int(goodSys.size()); ++i ) {
2408 
2409  // Save the (three) members of the resonance decay system
2410  int iMem1 = partonSystemsPtr->getOut(goodSys[i],0);
2411  int iMem2 = partonSystemsPtr->getOut(goodSys[i],1);
2412  int iMem3 = partonSystemsPtr->getOut(goodSys[i],2);
2413 
2414  // Now find emitted gluon or gamma
2415  int iEmtGlue = ((event[iMem1].id() == 21) ? iMem1
2416  : ((event[iMem2].id() == 21) ? iMem2
2417  : ((event[iMem3].id() == 21) ? iMem3: 0)));
2418  int iEmtGamm = ((event[iMem1].id() == 22) ? iMem1
2419  : ((event[iMem2].id() == 22) ? iMem2
2420  : ((event[iMem3].id() == 22) ? iMem3: 0)));
2421  // Per system, only one emission
2422  int iEmt = (iEmtGlue != 0) ? iEmtGlue : iEmtGamm;
2423 
2424  int iRad = 0;
2425  int iRec = 0;
2426  if ( iEmt == iMem1 ) {
2427  iRad = (event[iMem2].mother1() != event[iMem2].mother2())
2428  ? iMem2 : iMem3;
2429  iRec = (event[iMem3].mother1() == event[iMem3].mother2())
2430  ? iMem3 : iMem2;
2431  } else if ( iEmt == iMem2 ) {
2432  iRad = (event[iMem1].mother1() != event[iMem1].mother2())
2433  ? iMem1 : iMem3;
2434  iRec = (event[iMem3].mother1() == event[iMem3].mother2())
2435  ? iMem3 : iMem1;
2436  } else {
2437  iRad = (event[iMem1].mother1() != event[iMem1].mother2())
2438  ? iMem1 : iMem2;
2439  iRec = (event[iMem2].mother1() == event[iMem2].mother2())
2440  ? iMem2 : iMem1;
2441  }
2442 
2443  double pTres = rhoPythia(event[iRad], event[iEmt], event[iRec], 1);
2444 
2445  // Revoke previous veto of last emission if a splitting of the
2446  // resonance produced a harder parton, i.e. we are inside the
2447  // PS region
2448  if ( pTres > pTsave ) {
2449  revokeVeto = true;
2450  // Do nothing (i.e. allow other first emission veto) for soft
2451  // splitting
2452  } else {
2453  revokeVeto = false;
2454  }
2455  // Done with one system
2456  }
2457  // Done with all systems
2458  }
2459 
2460  // Check veto condition
2461  bool veto = false;
2462  if ( revokeVeto && check ) {
2463  setWeightCKKWL(weightCKKWL2Save);
2464  } else if ( check ) {
2465  setWeightCKKWL(weightCKKWL1Save);
2466  if ( weightCKKWL1Save == 0. ) veto = true;
2467  }
2468 
2469  // Check veto condition.
2470  if ( !check && nSteps > nMaxJetsNLO() && nSteps < nJetMax && tnow > tms()){
2471  // Set stored weights to zero.
2472  setWeightCKKWL(0.);
2473  // Now allow veto.
2474  veto = true;
2475  }
2476 
2477  // If the emission is allowed, do not check any further emissions
2478  if ( !veto || !doIgnoreStepSave ) doIgnoreStepSave = true;
2479 
2480  // Done
2481  return veto;
2482 
2483  }
2484 
2485  // Done
2486  return false;
2487 
2488 }
2489 
2490 //--------------------------------------------------------------------------
2491 
2492 // Return event stripped from decay products.
2493 
2494 Event MergingHooks::bareEvent(const Event& inputEventIn,
2495  bool storeInputEvent ) {
2496 
2497  // Find and detach decay products.
2498  Event newProcess = Event();
2499  newProcess.init("(hard process-modified)", particleDataPtr);
2500 
2501  // If desired, store input event.
2502  if ( storeInputEvent ) {
2503  resonances.resize(0);
2504  inputEvent.clear();
2505  for (int i = 0; i < inputEventIn.size(); ++i)
2506  inputEvent.append( inputEventIn[i] );
2507  for (int i = 0; i < inputEventIn.sizeJunction(); ++i)
2508  inputEvent.appendJunction( inputEventIn.getJunction(i) );
2509  inputEvent.saveSize();
2510  inputEvent.saveJunctionSize();
2511  }
2512 
2513  // Now remove decay products.
2514  if ( doRemoveDecayProducts ) {
2515 
2516  // Add the beam and initial partons to the event record.
2517  for (int i = 0; i < inputEventIn.size(); ++ i) {
2518  if ( inputEventIn[i].mother1() > 4
2519  || inputEventIn[i].statusAbs() == 22
2520  || inputEventIn[i].statusAbs() == 23)
2521  break;
2522  newProcess.append(inputEventIn[i]);
2523  }
2524 
2525  // Add the intermediate particles to the event record.
2526  for (int i = 0; i < inputEventIn.size(); ++ i) {
2527  if (inputEventIn[i].mother1() > 4) break;
2528  if ( inputEventIn[i].status() == -22) {
2529  int j = newProcess.append(inputEventIn[i]);
2530  newProcess[j].statusPos();
2531  if ( storeInputEvent ) resonances.push_back( make_pair(j, i) );
2532  newProcess[j].daughters(0, 0);
2533  }
2534  }
2535 
2536  // Add remaining outgoing particles to the event record.
2537  for (int i = 0; i < inputEventIn.size(); ++ i) {
2538  if (inputEventIn[i].mother1() > 4) break;
2539  if ( inputEventIn[i].statusAbs() != 11
2540  && inputEventIn[i].statusAbs() != 12
2541  && inputEventIn[i].statusAbs() != 21
2542  && inputEventIn[i].statusAbs() != 22)
2543  newProcess.append(inputEventIn[i]);
2544  }
2545 
2546  // Update event colour tag to maximum in whole process.
2547  int maxColTag = 0;
2548  for (int i = 0; i < inputEventIn.size(); ++ i) {
2549  if ( inputEventIn[i].col() > maxColTag )
2550  maxColTag = inputEventIn[i].col();
2551  if ( inputEventIn[i].acol() > maxColTag )
2552  maxColTag = inputEventIn[i].acol();
2553  }
2554  newProcess.initColTag(maxColTag);
2555 
2556  // Copy junctions from process to newProcess.
2557  for (int i = 0; i < inputEventIn.sizeJunction(); ++i)
2558  newProcess.appendJunction( inputEventIn.getJunction(i));
2559 
2560  newProcess.saveSize();
2561  newProcess.saveJunctionSize();
2562 
2563  } else {
2564  newProcess = inputEventIn;
2565  }
2566 
2567  // Remember scale
2568  newProcess.scale( inputEventIn.scale() );
2569 
2570  // Done
2571  return newProcess;
2572 
2573 }
2574 
2575 //--------------------------------------------------------------------------
2576 
2577 // Write event with decay products attached to argument. Only possible if an
2578 // input event with decay producs had been stored before.
2579 
2580 bool MergingHooks::reattachResonanceDecays(Event& process ) {
2581 
2582  // Now reattach the decay products.
2583  if ( doRemoveDecayProducts && inputEvent.size() > 0 ) {
2584 
2585  int sizeBef = process.size();
2586  // Vector of resonances for which the decay products were already attached.
2587  vector<int> iAftChecked;
2588  // Reset daughters and status of intermediate particles.
2589  for ( int i = 0; i < int(resonances.size()); ++i ) {
2590  for (int j = 0; j < sizeBef; ++j ) {
2591  if ( j != resonances[i].first ) continue;
2592 
2593  int iOldDaughter1 = inputEvent[resonances[i].second].daughter1();
2594  int iOldDaughter2 = inputEvent[resonances[i].second].daughter2();
2595 
2596  // Get momenta in case of reclustering.
2597  int iHardMother = resonances[i].second;
2598  Particle& hardMother = inputEvent[iHardMother];
2599  // Find current mother copy (after clustering).
2600  int iAftMother = 0;
2601  for ( int k = 0; k < process.size(); ++k )
2602  if ( process[k].id() == inputEvent[resonances[i].second].id() ) {
2603  // Only attempt if decays of this resonance were not attached.
2604  bool checked = false;
2605  for ( int l = 0; l < int(iAftChecked.size()); ++l )
2606  if ( k == iAftChecked[l] )
2607  checked = true;
2608  if ( !checked ) {
2609  iAftChecked.push_back(k);
2610  iAftMother = k;
2611  break;
2612  }
2613  }
2614 
2615  Particle& aftMother = process[iAftMother];
2616 
2617  // Resonance can have been moved by clustering,
2618  // so prepare to update colour and momentum information for system.
2619  int colBef = hardMother.col();
2620  int acolBef = hardMother.acol();
2621  int colAft = aftMother.col();
2622  int acolAft = aftMother.acol();
2623  RotBstMatrix M;
2624  M.bst( hardMother.p(), aftMother.p());
2625 
2626  // Attach resonance decay products.
2627  int iNewDaughter1 = 0;
2628  int iNewDaughter2 = 0;
2629  for ( int k = iOldDaughter1; k <= iOldDaughter2; ++k ) {
2630  if ( k == iOldDaughter1 )
2631  iNewDaughter1 = process.append(inputEvent[k] );
2632  else
2633  iNewDaughter2 = process.append(inputEvent[k] );
2634  process.back().statusPos();
2635  Particle& now = process.back();
2636  // Update colour and momentum information.
2637  if (now.col() != 0 && now.col() == colBef ) now.col(colAft);
2638  if (now.acol() != 0 && now.acol() == acolBef) now.acol(acolAft);
2639  now.rotbst( M);
2640  // Update vertex information.
2641  if (now.hasVertex()) now.vProd( aftMother.vDec() );
2642  // Update mothers.
2643  now.mothers(iAftMother,0);
2644  }
2645 
2646  process[iAftMother].daughters( iNewDaughter1, iNewDaughter2 );
2647  process[iAftMother].statusNeg();
2648 
2649  // Loop through event and attach remaining decays
2650  int iDec = 0;
2651  do {
2652  if ( process[iDec].isFinal() && process[iDec].canDecay()
2653  && process[iDec].mayDecay() && process[iDec].isResonance() ) {
2654 
2655  int iD1 = process[iDec].daughter1();
2656  int iD2 = process[iDec].daughter2();
2657 
2658  // Done if no daughters exist.
2659  if ( iD1 == 0 || iD2 == 0 ) continue;
2660 
2661  // Attach daughters.
2662  int iNewDaughter12 = 0;
2663  int iNewDaughter22 = 0;
2664  for ( int k = iD1; k <= iD2; ++k ) {
2665  if ( k == iD1 )
2666  iNewDaughter12 = process.append(inputEvent[k] );
2667  else
2668  iNewDaughter22 = process.append(inputEvent[k] );
2669  process.back().statusPos();
2670  Particle& now = process.back();
2671  // Update colour and momentum information.
2672  if (now.col() != 0 && now.col() == colBef ) now.col(colAft);
2673  if (now.acol()!= 0 && now.acol()== acolBef) now.acol(acolAft);
2674  now.rotbst( M);
2675  // Update vertex information.
2676  if (now.hasVertex()) now.vProd( process[iDec].vDec() );
2677  // Update mothers.
2678  now.mothers(iDec,0);
2679  }
2680 
2681  // Modify mother status and daughters.
2682  process[iDec].status(-22);
2683  process[iDec].daughters(iNewDaughter12, iNewDaughter22);
2684 
2685  // End of loop over all entries.
2686  }
2687  } while (++iDec < process.size());
2688  } // End loop over process entries.
2689  } // End loop over resonances.
2690 
2691  // Update event colour tag to maximum in whole process.
2692  int maxColTag = 0;
2693  for (int i = 0; i < process.size(); ++ i) {
2694  if (process[i].col() > maxColTag) maxColTag = process[i].col();
2695  if (process[i].acol() > maxColTag) maxColTag = process[i].acol();
2696  }
2697  process.initColTag(maxColTag);
2698 
2699  }
2700 
2701  // Done.
2702  return (doRemoveDecayProducts) ? inputEvent.size() > 0 : true;
2703 
2704 }
2705 
2706 //--------------------------------------------------------------------------
2707 
2708 bool MergingHooks::isInHard( int iPos, const Event& event){
2709 
2710  // MPI not part of hard process
2711  if ( event[iPos].statusAbs() > 30 && event[iPos].statusAbs() < 40 )
2712  return false;
2713  // Beam remnants and hadronisation not part of hard process
2714  if ( event[iPos].statusAbs() > 60 )
2715  return false;
2716 
2717  // Still MPI: Check that the particle is not due to radiation off MPIs.
2718  // First get all intermediate MPI partons in the state.
2719  vector<int> mpiParticlePos;
2720  mpiParticlePos.clear();
2721  for ( int i=0; i < event.size(); ++i )
2722  if ( event[i].statusAbs() > 30
2723  && event[i].statusAbs() < 40 )
2724  mpiParticlePos.push_back(i);
2725  // Disregard any parton iPos that has MPI ancestors.
2726  for ( int i=0; i < int(mpiParticlePos.size()); ++i)
2727  if ( event.isAncestor(iPos, mpiParticlePos[i]) )
2728  return false;
2729 
2730  // Disallow other systems.
2731  // Get sub-system of particles for iPos
2732  int iSys = partonSystemsPtr->getSystemOf(iPos, !event[iPos].isFinal() );
2733  if ( iSys > 0 ) {
2734  // Check all partons belonging to the same system as iPos. If any is
2735  // produced in MPI or has MPI ancestors, the whole system is not the
2736  // hard subprocess, i.e. iPos is not in the hard subprocess.
2737  int sysSize = partonSystemsPtr->sizeAll(iSys);
2738  for ( int i = 0; i < sysSize; ++i ) {
2739  int iPosNow = partonSystemsPtr->getAll( iSys, i );
2740  // MPI not part of hard process
2741  if ( event[iPosNow].statusAbs() > 30
2742  && event[iPosNow].statusAbs() < 40 )
2743  return false;
2744  // Disregard any parton iPos that has MPI ancestors.
2745  for ( int j=0; j < int(mpiParticlePos.size()); ++j)
2746  if ( event.isAncestor(iPosNow, mpiParticlePos[j]) )
2747  return false;
2748  // Beam remnants and hadronisation not part of hard process
2749  if ( event[iPosNow].statusAbs() > 60 )
2750  return false;
2751  }
2752  }
2753 
2754  // Check if any ancestor contains the hard incoming partons as daughters.
2755  // Begin loop to trace upwards from the daughter.
2756  bool containsInitialParton = false;
2757  int iUp = iPos;
2758  for ( ; ; ) {
2759  // If out of range then failed to find match.
2760  if (iUp <= 0 || iUp > event.size()) break;
2761  // If positive match then done.
2762  if ( iUp == 3 || iUp == 4 ) {
2763  containsInitialParton = true;
2764  break;
2765  }
2766  if ( event[iUp].mother1() == 1
2767  && (event[iUp].daughter1() == 3 || event[iUp].daughter2() == 3) ) {
2768  containsInitialParton = true;
2769  break;
2770  }
2771  if ( event[iUp].mother1() == 2
2772  && (event[iUp].daughter1() == 4 || event[iUp].daughter2() == 4) ) {
2773  containsInitialParton = true;
2774  break;
2775  }
2776  // If unique mother then keep on moving up the chain.
2777  iUp = event[iUp].mother1();
2778  }
2779 
2780  if ( !containsInitialParton ) return false;
2781 
2782  // Done
2783  return true;
2784 
2785 }
2786 
2787 //--------------------------------------------------------------------------
2788 
2789 // Function to return the number of clustering steps for the current event
2790 
2791 int MergingHooks::getNumberOfClusteringSteps(const Event& event){
2792 
2793  // Count the number of final state partons
2794  int nFinalPartons = 0;
2795  for ( int i=0; i < event.size(); ++i)
2796  if ( event[i].isFinal()
2797  && isInHard( i, event)
2798  && (event[i].isQuark() || event[i].isGluon()) )
2799  nFinalPartons++;
2800 
2801  // Count the number of final state leptons
2802  int nFinalLeptons = 0;
2803  for( int i=0; i < event.size(); ++i)
2804  if ( event[i].isFinal() && isInHard( i, event) && event[i].isLepton())
2805  nFinalLeptons++;
2806 
2807  // Add neutralinos to number of leptons
2808  for( int i=0; i < event.size(); ++i)
2809  if ( event[i].isFinal() && isInHard( i, event)
2810  && event[i].idAbs() == 1000022)
2811  nFinalLeptons++;
2812 
2813  // Add sleptons to number of leptons
2814  for( int i=0; i < event.size(); ++i)
2815  if ( event[i].isFinal() && isInHard( i, event)
2816  && (event[i].idAbs() == 1000011
2817  || event[i].idAbs() == 2000011
2818  || event[i].idAbs() == 1000013
2819  || event[i].idAbs() == 2000013
2820  || event[i].idAbs() == 1000015
2821  || event[i].idAbs() == 2000015) )
2822  nFinalLeptons++;
2823 
2824  // Count the number of final state electroweak bosons
2825  int nFinalBosons = 0;
2826  for( int i=0; i < event.size(); ++i)
2827  if ( event[i].isFinal() && isInHard( i, event)
2828  && ( event[i].idAbs() == 22
2829  || event[i].idAbs() == 23
2830  || event[i].idAbs() == 24
2831  || event[i].idAbs() == 25 ) )
2832  nFinalBosons++;
2833 
2834  // Save sum of all final state particles
2835  int nFinal = nFinalPartons + nFinalLeptons
2836  + 2*(nFinalBosons - nHardOutBosons() );
2837 
2838  // Return the difference to the core process outgoing particles
2839  return (nFinal - nHardOutPartons() - nHardOutLeptons() );
2840 
2841 }
2842 
2843 //--------------------------------------------------------------------------
2844 
2845 // Function to check if event contains an emission not present in the hard
2846 // process.
2847 
2848 bool MergingHooks::isFirstEmission(const Event& event ) {
2849 
2850  // If the beam remnant treatment or hadronisation has already started, do
2851  // no veto.
2852  for ( int i=0; i < event.size(); ++i)
2853  if ( event[i].statusAbs() > 60 ) return false;
2854 
2855  // Count particle types
2856  int nFinalQuarks = 0;
2857  int nFinalGluons = 0;
2858  int nFinalLeptons = 0;
2859  int nFinalBosons = 0;
2860  int nFinalPhotons = 0;
2861  int nFinal = 0;
2862  for( int i=0; i < event.size(); ++i) {
2863  if (event[i].isFinal() && isInHard(i, event) ){
2864  if ( event[i].spinType() == 2 && event[i].colType() == 0)
2865  nFinalLeptons++;
2866  if ( event[i].id() == 23
2867  || event[i].idAbs() == 24
2868  || event[i].id() == 25)
2869  nFinalBosons++;
2870  if ( event[i].id() == 22)
2871  nFinalPhotons++;
2872  if ( event[i].isQuark())
2873  nFinalQuarks++;
2874  if ( event[i].isGluon())
2875  nFinalGluons++;
2876  if ( !event[i].isDiquark() )
2877  nFinal++;
2878  }
2879  }
2880 
2881  // Return highest value if the event does not contain any final state
2882  // coloured particles.
2883  if (nFinalQuarks + nFinalGluons == 0) return false;
2884 
2885  // Use MergingHooks functions to get information on the hard process.
2886  int nLeptons = nHardOutLeptons();
2887 
2888  // The state is already in the PS region if the number of leptons had been
2889  // increased bt QED splittings.
2890  if (nFinalLeptons > nLeptons) return false;
2891 
2892  // If the mumber of photons if larger than in the hard process, QED
2893  // radiation has pushed the state into the PS region.
2894  int nPhotons = 0;
2895  for(int i =0; i< int(hardProcess.hardOutgoing1.size()); ++i)
2896  if (hardProcess.hardOutgoing1[i] == 22)
2897  nPhotons++;
2898  for(int i =0; i< int(hardProcess.hardOutgoing2.size()); ++i)
2899  if (hardProcess.hardOutgoing2[i] == 22)
2900  nPhotons++;
2901  if (nFinalPhotons > nPhotons) return false;
2902 
2903  // Done
2904  return true;
2905 }
2906 
2907 //--------------------------------------------------------------------------
2908 
2909 // Function to set the correct starting scales of the shower
2910 
2911 // Set starting scales
2912 bool MergingHooks::setShowerStartingScales( bool isTrial,
2913  bool doMergeFirstEmm, double& pTscaleIn, const Event& event,
2914  double& pTmaxFSRIn, bool& limitPTmaxFSRIn,
2915  double& pTmaxISRIn, bool& limitPTmaxISRIn,
2916  double& pTmaxMPIIn, bool& limitPTmaxMPIIn ) {
2917 
2918  // MPI treated differently in case of qcd djiet merging, since hard MPI
2919  // can be misidentified as hard process.
2920  bool isPureQCD = ( getProcessString().compare("pp>jj") == 0 );
2921  int nSteps = getNumberOfClusteringSteps( bareEvent(event, false) );
2922  double scale = event.scale();
2923 
2924  bool doRecluster = doUMEPSSubt() || doNL3Subt() || doUNLOPSSubt()
2925  || doUNLOPSSubtNLO();
2926 
2927  // Set correct starting scales for trial showers.
2928  if ( isTrial ) {
2929  // Reset shower scales.
2930  pTmaxISRIn = pTmaxFSRIn = scale;
2931  if ( limitPTmaxISRIn ) pTmaxISRIn = min(scale,muF());
2932  if ( limitPTmaxFSRIn ) pTmaxFSRIn = min(scale,muF());
2933  // Reset MPI scale.
2934  if ( !isPureQCD ) pTmaxMPIIn = scale;
2935  else pTmaxMPIIn = infoPtr->eCM();
2936  // Reset phase space limitation flags
2937  if ( pTscaleIn < infoPtr->eCM() ) {
2938  limitPTmaxISRIn = limitPTmaxFSRIn = true;
2939  if ( !isPureQCD ) limitPTmaxMPIIn = true;
2940  else limitPTmaxMPIIn = false;
2941  }
2942  }
2943 
2944  // Reset starting scales.
2945  if ( isPureQCD && doMergeFirstEmm ) {
2946  // Set correct shower starting scales.
2947  if ( nSteps == 0 && !doRecluster && pTscaleIn < infoPtr->eCM() ) {
2948  pTmaxMPIIn = infoPtr->eCM();
2949  limitPTmaxMPIIn = false;
2950  }
2951  }
2952 
2953  // Reset starting scales.
2954  if ( !isPureQCD && doMergeFirstEmm ) {
2955  // Set correct shower starting scales.
2956  if ( nSteps == 0 && !doRecluster ) {
2957  pTscaleIn = infoPtr->eCM();
2958  limitPTmaxMPIIn = false;
2959  }
2960  if ( limitPTmaxISRIn ) pTscaleIn = min(scale,muF());
2961  if ( limitPTmaxFSRIn ) pTscaleIn = min(scale,muF());
2962  pTmaxISRIn = pTmaxFSRIn = pTscaleIn;
2963  // Reset MPI starting scale. Standard treatment
2964  if ( pTscaleIn < infoPtr->eCM()
2965  && !(nSteps == 0 && !doRecluster
2966  && (limitPTmaxISRIn || limitPTmaxFSRIn)) ) {
2967  pTmaxMPIIn = pTscaleIn;
2968  limitPTmaxMPIIn = true;
2969  }
2970  if (doRecluster) {
2971  pTmaxMPIIn = muMI();
2972  limitPTmaxMPIIn = true;
2973  }
2974  }
2975 
2976  // Done
2977  return true;
2978 
2979 }
2980 
2981 //--------------------------------------------------------------------------
2982 
2983 // Function to return the value of the merging scale function in the current
2984 // event.
2985 
2986 double MergingHooks::tmsNow( const Event& event ) {
2987 
2988  // Get merging scale in current event.
2989  double tnow = 0.;
2990  // Use KT/Durham merging scale definition.
2991  if ( doKTMerging() || doMGMerging() )
2992  tnow = kTms(event);
2993  // Use Lund PT merging scale definition.
2994  else if ( doPTLundMerging() )
2995  tnow = rhoms(event, false);
2996  // Use DeltaR_{ij}, pT_i, Q_{ij} combination merging scale definition.
2997  else if ( doCutBasedMerging() )
2998  tnow = cutbasedms(event);
2999  // Use NLO merging (Lund PT) merging scale definition.
3000  else if ( doNL3Merging() )
3001  tnow = rhoms(event, false);
3002  // Use NLO merging (Lund PT) merging scale definition.
3003  else if ( doUNLOPSMerging() )
3004  tnow = rhoms(event, false);
3005  // Use UMEPS (Lund PT) merging scale definition.
3006  else if ( doUMEPSMerging() )
3007  tnow = rhoms(event, false);
3008  // Use user-defined merging scale.
3009  else
3010  tnow = tmsDefinition(event);
3011  // Return merging scale value. Done
3012  return tnow;
3013 }
3014 
3015 //--------------------------------------------------------------------------
3016 
3017 // Function to check if the properties of the input particle should be
3018 // checked against the cut-based merging scale defintion.
3019 
3020 bool MergingHooks::checkAgainstCut( const Particle& particle){
3021 
3022  // Do not check uncoloured particles.
3023  if (particle.colType() == 0) return false;
3024  // By default, use u-, d-, c-, s- and b-quarks.
3025  if ( particle.idAbs() != 21 && particle.idAbs() > nQuarksMergeSave )
3026  return false;
3027  // Done
3028  return true;
3029 
3030 }
3031 
3032 //--------------------------------------------------------------------------
3033 
3034 // Function to return the minimal kT in the event. If doKTMerging = true, this
3035 // function will be used as a merging scale definition.
3036 
3037 double MergingHooks::kTms(const Event& event) {
3038 
3039  // Only check first emission.
3040  if (!isFirstEmission(event)) return 0.;
3041 
3042  // Find all electroweak decayed bosons in the state.
3043  vector<int> ewResonancePos;
3044  ewResonancePos.clear();
3045  for (int i=0; i < event.size(); ++i)
3046  if ( abs(event[i].status()) == 22
3047  && ( event[i].idAbs() == 22
3048  || event[i].idAbs() == 23
3049  || event[i].idAbs() == 24
3050  || event[i].idAbs() == 25
3051  || event[i].idAbs() == 6 ) )
3052  ewResonancePos.push_back(i);
3053 
3054  // Declare final parton vectors
3055  vector <int> FinalPartPos;
3056  FinalPartPos.clear();
3057  // Search inEvent record for final state partons.
3058  // Exclude decay products of ew resonance.
3059  for (int i=0; i < event.size(); ++i){
3060  if ( event[i].isFinal()
3061  && isInHard( i, event )
3062  && event[i].colType() != 0
3063  && checkAgainstCut(event[i]) ){
3064  bool isDecayProduct = false;
3065  for(int j=0; j < int(ewResonancePos.size()); ++j)
3066  if ( event.isAncestor(i, ewResonancePos[j]) )
3067  isDecayProduct = true;
3068  // Except for e+e- -> jets, do not check radiation in resonance decays.
3069  if ( !isDecayProduct
3070  || getProcessString().compare("e+e->jj") == 0
3071  || getProcessString().compare("e+e->(z>jj)") == 0 )
3072  FinalPartPos.push_back(i);
3073  }
3074  }
3075 
3076  // Find minimal Durham kT in event, using own function: Check
3077  // definition of separation
3078  int type = (event[3].colType() == 0
3079  && event[4].colType() == 0) ? -1 : ktTypeSave;
3080  // Find minimal kT
3081  double ktmin = event[0].e();
3082  for(int i=0; i < int(FinalPartPos.size()); ++i){
3083  double kt12 = ktmin;
3084  // Compute separation to the beam axis for hadronic collisions
3085  if (type == 1 || type == 2) {
3086  double temp = event[FinalPartPos[i]].pT();
3087  kt12 = min(kt12, temp);
3088  }
3089  // Compute separation to other final state jets
3090  for(int j=i+1; j < int(FinalPartPos.size()); ++j) {
3091  double temp = kTdurham( event[FinalPartPos[i]], event[FinalPartPos[j]],
3092  type, DparameterSave);
3093  kt12 = min(kt12, temp);
3094  }
3095  // Keep the minimal Durham separation
3096  ktmin = min(ktmin,kt12);
3097  }
3098 
3099  // Return minimal Durham kT
3100  return ktmin;
3101 
3102 }
3103 
3104 //--------------------------------------------------------------------------
3105 
3106 // Function to compute durham y separation from Particle input.
3107 
3108 double MergingHooks::kTdurham(const Particle& RadAfterBranch,
3109  const Particle& EmtAfterBranch, int Type, double D ){
3110 
3111  // Declare return variable
3112  double ktdur;
3113  // Save 4-momenta of final state particles
3114  Vec4 jet1 = RadAfterBranch.p();
3115  Vec4 jet2 = EmtAfterBranch.p();
3116 
3117  if ( Type == -1) {
3118  // Get angle between jets for e+e- collisions, make sure that
3119  // -1 <= cos(theta) <= 1
3120  double costh;
3121  if (jet1.pAbs()*jet2.pAbs() <=0.) costh = 1.;
3122  else {
3123  costh = costheta(jet1,jet2);
3124  }
3125  // Calculate kt durham separation between jets for e+e- collisions
3126  ktdur = 2.0*min( pow(jet1.e(),2) , (pow(jet2.e(),2)) )*(1.0 - costh);
3127  } else if ( Type == 1 ){
3128  // Get delta_y for hadronic collisions:
3129  // Get mT of first jet
3130  double mT1sq = jet1.m2Calc() + jet1.pT2();
3131  double mT1 = 0.;
3132  if (mT1sq < 0) mT1 = - sqrt(-mT1sq);
3133  else mT1 = sqrt(mT1sq);
3134  // Get mT of second jet
3135  double mT2sq = jet2.m2Calc() + jet2.pT2();
3136  double mT2 = 0.;
3137  if (mT2sq < 0) mT2 = - sqrt(-mT2sq);
3138  else mT2 = sqrt(mT2sq);
3139  // Get rapidity of first jet
3140  double y1 = log( ( jet1.e() + abs(jet1.pz()) ) / mT1 );
3141  if (jet1.pz() < 0) y1 *= -1.;
3142  // Get rapidity of second jet
3143  double y2 = log( ( jet2.e() + abs(jet2.pz()) ) / mT2 );
3144  if (jet2.pz() < 0) y2 *= -1.;
3145  // Get delta_phi for hadronic collisions
3146  double pt1 = sqrt( pow(jet1.px(),2) + pow(jet1.py(),2) );
3147  double pt2 = sqrt( pow(jet2.px(),2) + pow(jet2.py(),2) );
3148  double cosdPhi = ( jet1.px()*jet2.px() + jet1.py()*jet2.py() ) / (pt1*pt2);
3149  double dPhi = acos( cosdPhi );
3150  // Calculate kT durham like fastjet,
3151  // but with rapidity instead of pseudo-rapidity
3152  ktdur = min( pow(pt1,2),pow(pt2,2) )
3153  * ( pow(y1-y2,2) + pow(dPhi,2) ) / pow(D,2);
3154  } else if ( Type == 2 ){
3155 
3156  // Get mT of first jet
3157  double mT1sq = jet1.m2Calc() + jet1.pT2();
3158  double mT1 = 0.;
3159  if (mT1sq < 0) mT1 = - sqrt(-mT1sq);
3160  else mT1 = sqrt(mT1sq);
3161  // Get mT of second jet
3162  double mT2sq = jet2.m2Calc() + jet2.pT2();
3163  double mT2 = 0.;
3164  if (mT2sq < 0) mT2 = - sqrt(-mT2sq);
3165  else mT2 = sqrt(mT2sq);
3166  // Get pseudo-rapidity of first jet
3167  double eta1 = log( ( sqrt(jet1.px()*jet1.px() + jet1.py()*jet1.py()
3168  + jet1.pz()*jet1.pz()) + abs(jet1.pz()) ) / mT1);
3169  if (jet1.pz() < 0) eta1 *= -1.;
3170  // Get pseudo-rapidity of second jet
3171  double eta2 = log( ( sqrt(jet2.px()*jet2.px() + jet2.py()*jet2.py()
3172  + jet2.pz()*jet2.pz()) + abs(jet2.pz()) ) / mT2);
3173  if (jet2.pz() < 0) eta2 *= -1.;
3174 
3175  // Get delta_phi and cos(Delta_phi) for hadronic collisions
3176  double pt1 = sqrt( pow(jet1.px(),2) + pow(jet1.py(),2) );
3177  double pt2 = sqrt( pow(jet2.px(),2) + pow(jet2.py(),2) );
3178  double cosdPhi = ( jet1.px()*jet2.px() + jet1.py()*jet2.py() ) / (pt1*pt2);
3179  double dPhi = acos( cosdPhi );
3180  // Calculate kT durham like fastjet
3181  ktdur = min( pow(pt1,2),pow(pt2,2) )
3182  * ( pow(eta1-eta2,2) + pow(dPhi,2) ) / pow(D,2);
3183  } else if ( Type == 3 ){
3184  // Get cosh(Delta_eta) for hadronic collisions
3185  double eta1 = 0.5*log( (jet1.e() + jet1.pz()) / (jet1.e() - jet1.pz()) );
3186  double eta2 = 0.5*log( (jet2.e() + jet2.pz()) / (jet2.e() - jet2.pz()) );
3187  double coshdEta = cosh( eta1 - eta2 );
3188  // Get delta_phi and cos(Delta_phi) for hadronic collisions
3189  double pt1 = sqrt( pow(jet1.px(),2) + pow(jet1.py(),2) );
3190  double pt2 = sqrt( pow(jet2.px(),2) + pow(jet2.py(),2) );
3191  double cosdPhi = ( jet1.px()*jet2.px() + jet1.py()*jet2.py() ) / (pt1*pt2);
3192  // Calculate kT durham separation "SHERPA-like"
3193  ktdur = 2.0*min( pow(pt1,2),pow(pt2,2) )
3194  * ( coshdEta - cosdPhi ) / pow(D,2);
3195  } else {
3196  ktdur = 0.0;
3197  }
3198  // Return kT
3199  return sqrt(ktdur);
3200 }
3201 
3202 //--------------------------------------------------------------------------
3203 
3204 // Find the minimal Lund pT between coloured partons in the input
3205 // event. If doPTLundMerging = true, this function will be used as a merging
3206 // scale definition.
3207 
3208 double MergingHooks::rhoms( const Event& event, bool withColour){
3209 
3210  // Only check first emission.
3211  if (!isFirstEmission(event)) return 0.;
3212 
3213  // Find all electroweak decayed bosons in the state.
3214  vector<int> ewResonancePos;
3215  ewResonancePos.clear();
3216  for (int i=0; i < event.size(); ++i)
3217  if ( abs(event[i].status()) == 22
3218  && ( event[i].idAbs() == 22
3219  || event[i].idAbs() == 23
3220  || event[i].idAbs() == 24
3221  || event[i].idAbs() == 25
3222  || event[i].idAbs() == 6 ) )
3223  ewResonancePos.push_back(i);
3224 
3225  // Declare final parton vectors
3226  vector <int> FinalPartPos;
3227  FinalPartPos.clear();
3228  // Search inEvent record for final state partons.
3229  // Exclude decay products of ew resonance.
3230  for (int i=0; i < event.size(); ++i){
3231 
3232  if ( event[i].isFinal()
3233  && isInHard( i, event )
3234  && event[i].colType() != 0
3235  && checkAgainstCut(event[i]) ){
3236  bool isDecayProduct = false;
3237  for(int j=0; j < int(ewResonancePos.size()); ++j)
3238  if ( event.isAncestor(i, ewResonancePos[j]) )
3239  isDecayProduct = true;
3240  // Except for e+e- -> jets, do not check radiation in resonance decays.
3241  if ( !isDecayProduct
3242  || getProcessString().compare("e+e->jj") == 0
3243  || getProcessString().compare("e+e->(z>jj)") == 0 )
3244  FinalPartPos.push_back(i);
3245  }
3246  }
3247 
3248  // Get index of first incoming
3249  int in1 = 0;
3250  for (int i=0; i < event.size(); ++i)
3251  if (abs(event[i].status()) == 41 ){
3252  in1 = i;
3253  break;
3254  }
3255 
3256  // Get index of second incoming
3257  int in2 = 0;
3258  for (int i=0; i < event.size(); ++i)
3259  if (abs(event[i].status()) == 42 ){
3260  in2 = i;
3261  break;
3262  }
3263 
3264  // If no incoming of the cascade are found, try incoming
3265  if (in1 == 0 || in2 == 0){
3266  // Find current incoming partons
3267  for(int i=3; i < int(event.size()); ++i){
3268  if ( !isInHard( i, event ) ) continue;
3269  if (event[i].mother1() == 1) in1 = i;
3270  if (event[i].mother1() == 2) in2 = i;
3271  }
3272  }
3273 
3274  // Find minimal pythia pt in event
3275  double ptmin = event[0].e();
3276  for(int i=0; i < int(FinalPartPos.size()); ++i){
3277  double pt12 = ptmin;
3278  // Compute pythia ISR separation i-jet and first incoming
3279  if (event[in1].colType() != 0) {
3280  double temp = rhoPythia( event[in1],
3281  event[FinalPartPos[i]], event[in2], -1 );
3282  pt12 = min(pt12, temp);
3283  }
3284 
3285  // Compute pythia ISR separation i-jet and second incoming
3286  if ( event[in2].colType() != 0) {
3287  double temp = rhoPythia( event[in2],
3288  event[FinalPartPos[i]], event[in1], -1 );
3289  pt12 = min(pt12, temp);
3290  }
3291 
3292  if (withColour) {
3293  // Compute pythia FSR separation between two jets,
3294  // with knowledge of colour connections
3295  for(int j=0; j < int(FinalPartPos.size()); ++j) {
3296 
3297  // Find recoiler in event
3298  if ( i!=j ){
3299  bool isHard = false;
3300  int radAcl = event[FinalPartPos[i]].acol();
3301  int radCol = event[FinalPartPos[i]].col();
3302  int emtAcl = event[FinalPartPos[j]].acol();
3303  int emtCol = event[FinalPartPos[j]].col();
3304  int iRec = -1;
3305  // Check in final state
3306  if (iRec <= 0 && radAcl > 0 && radAcl != emtCol)
3307  iRec = findColour(radAcl, FinalPartPos[i], FinalPartPos[j],
3308  event,1, isHard);
3309  if (iRec <= 0 && radCol > 0 && radCol != emtAcl)
3310  iRec = findColour(radCol, FinalPartPos[i], FinalPartPos[j],
3311  event,1, isHard);
3312  if (iRec <= 0 && emtAcl > 0 && emtAcl != radCol)
3313  iRec = findColour(emtAcl, FinalPartPos[i], FinalPartPos[j],
3314  event,1, isHard);
3315  if (iRec <= 0 && emtCol > 0 && emtCol != radAcl)
3316  iRec = findColour(emtCol, FinalPartPos[i], FinalPartPos[j],
3317  event,1, isHard);
3318 
3319  // Check in initial state
3320  if (iRec <= 0 && radAcl > 0 && radAcl != emtCol)
3321  iRec = findColour(radAcl, FinalPartPos[i], FinalPartPos[j],
3322  event,2, isHard);
3323  if (iRec <= 0 && radCol > 0 && radCol != emtAcl)
3324  iRec = findColour(radCol, FinalPartPos[i], FinalPartPos[j],
3325  event,2, isHard);
3326  if (iRec <= 0 && emtAcl > 0 && emtAcl != radCol)
3327  iRec = findColour(emtAcl, FinalPartPos[i], FinalPartPos[j],
3328  event,2, isHard);
3329  if (iRec <= 0 && emtCol > 0 && emtCol != radAcl)
3330  iRec = findColour(emtCol, FinalPartPos[i], FinalPartPos[j],
3331  event,2, isHard);
3332 
3333  if (iRec > 0) {
3334  double temp = rhoPythia( event[FinalPartPos[i]],
3335  event[FinalPartPos[j]],
3336  event[iRec], 1 );
3337  pt12 = min(pt12, temp);
3338  }
3339  }
3340  }
3341 
3342  } else {
3343  // Compute pythia FSR separation between two jets,
3344  // without any knowledge of colour connections
3345  for(int j=0; j < int(FinalPartPos.size()); ++j) {
3346  for(int k=0; k < int(FinalPartPos.size()); ++k) {
3347  // Allow any parton as recoiler
3348  if ( (i != j) && (i != k) && (j != k) ){
3349 
3350  double temp = 0.;
3351  // Only check splittings allowed by flavour, e.g.
3352  // only q -> qg and g -> qqbar
3353  temp = rhoPythia( event[FinalPartPos[i]],
3354  event[FinalPartPos[j]],
3355  event[FinalPartPos[k]], 1 );
3356  pt12 = min(pt12, temp);
3357  }
3358  }
3359  }
3360 
3361  // Compute pythia FSR separation between two jets, with initial recoiler
3362  // without any knowledge of colour connections
3363  if ( event[in1].colType() != 0 && event[in2].colType() != 0) {
3364  for(int j=0; j < int(FinalPartPos.size()); ++j) {
3365  // Allow both initial partons as recoiler
3366  if ( i != j ){
3367  // Check with first initial as recoiler
3368  double temp = rhoPythia( event[FinalPartPos[i]],
3369  event[FinalPartPos[j]],
3370  event[in1], 1 );
3371  pt12 = min(pt12, temp);
3372  // Check with second initial as recoiler
3373  temp = rhoPythia( event[FinalPartPos[i]],
3374  event[FinalPartPos[j]],
3375  event[in2], 1 );
3376  pt12 = min(pt12, temp);
3377  }
3378  }
3379  }
3380 
3381  }
3382  // Reset minimal y separation
3383  ptmin = min(ptmin,pt12);
3384  }
3385 
3386  return ptmin;
3387 
3388 }
3389 
3390 //--------------------------------------------------------------------------
3391 
3392 // Function to compute "pythia pT separation" from Particle input, as a helper
3393 // for rhoms(...).
3394 
3395 double MergingHooks::rhoPythia(const Particle& RadAfterBranch,
3396  const Particle& EmtAfterBranch,
3397  const Particle& RecAfterBranch, int ShowerType){
3398 
3399  // Save type: 1 = FSR pT definition, else ISR definition
3400  int Type = ShowerType;
3401  // Calculate virtuality of splitting
3402  int sign = (Type==1) ? 1 : -1;
3403  Vec4 Q(RadAfterBranch.p() + sign*EmtAfterBranch.p());
3404  double Qsq = sign * Q.m2Calc();
3405  // Mass term of radiator
3406  double m2Rad = ( includeMassive()
3407  && abs(RadAfterBranch.id()) >= 4
3408  && abs(RadAfterBranch.id()) < 7)
3409  ? pow(particleDataPtr->m0(RadAfterBranch.id()), 2)
3410  : 0.;
3411  // Construct 2->3 variables for FSR
3412  Vec4 sum = RadAfterBranch.p() + RecAfterBranch.p()
3413  + EmtAfterBranch.p();
3414  double m2Dip = sum.m2Calc();
3415  double x1 = 2. * (sum * RadAfterBranch.p()) / m2Dip;
3416  double x3 = 2. * (sum * EmtAfterBranch.p()) / m2Dip;
3417  // Construct momenta of dipole before/after splitting for ISR
3418  Vec4 qBR(RadAfterBranch.p() - EmtAfterBranch.p() + RecAfterBranch.p());
3419  Vec4 qAR(RadAfterBranch.p() + RecAfterBranch.p());
3420  // Calculate z of splitting, different for FSR and ISR
3421  double z = (Type==1) ? x1/(x1+x3)
3422  : (qBR.m2Calc())/( qAR.m2Calc());
3423  // Separation of splitting, different for FSR and ISR
3424  double pTpyth = (Type==1) ? z*(1.-z) : (1.-z);
3425  // pT^2 = separation*virtuality
3426  pTpyth *= (Qsq - sign*m2Rad);
3427  if (pTpyth < 0.) pTpyth = 0.;
3428  // Return pT
3429  return sqrt(pTpyth);
3430 }
3431 
3432 //--------------------------------------------------------------------------
3433 
3434 // Function to find a colour (anticolour) index in the input event.
3435 // Helper for rhoms
3436 // IN int col : Colour tag to be investigated
3437 // int iExclude1 : Identifier of first particle to be excluded
3438 // from search
3439 // int iExclude2 : Identifier of second particle to be excluded
3440 // from search
3441 // Event event : event to be searched for colour tag
3442 // int type : Tag to define if col should be counted as
3443 // colour (type = 1) [->find anti-colour index
3444 // contracted with col]
3445 // anticolour (type = 2) [->find colour index
3446 // contracted with col]
3447 // OUT int : Position of particle in event record
3448 // contraced with col [0 if col is free tag]
3449 
3450 int MergingHooks::findColour(int col, int iExclude1, int iExclude2,
3451  const Event& event, int type, bool isHardIn){
3452 
3453  bool isHard = isHardIn;
3454  int index = 0;
3455 
3456  if (isHard){
3457  // Search event record for matching colour & anticolour
3458  for(int n = 0; n < event.size(); ++n) {
3459  if ( n != iExclude1 && n != iExclude2
3460  && event[n].colType() != 0
3461  &&( event[n].status() > 0 // Check outgoing
3462  || event[n].status() == -21) ) { // Check incoming
3463  if ( event[n].acol() == col ) {
3464  index = -n;
3465  break;
3466  }
3467  if ( event[n].col() == col ){
3468  index = n;
3469  break;
3470  }
3471  }
3472  }
3473  } else {
3474 
3475  // Search event record for matching colour & anticolour
3476  for(int n = 0; n < event.size(); ++n) {
3477  if ( n != iExclude1 && n != iExclude2
3478  && event[n].colType() != 0
3479  &&( event[n].status() == 43 // Check outgoing from ISR
3480  || event[n].status() == 51 // Check outgoing from FSR
3481  || event[n].status() == 52 // Check outgoing from FSR
3482  || event[n].status() == -41 // first initial
3483  || event[n].status() == -42) ) { // second initial
3484  if ( event[n].acol() == col ) {
3485  index = -n;
3486  break;
3487  }
3488  if ( event[n].col() == col ){
3489  index = n;
3490  break;
3491  }
3492  }
3493  }
3494  }
3495  // if no matching colour / anticolour has been found, return false
3496  if ( type == 1 && index < 0) return abs(index);
3497  if ( type == 2 && index > 0) return abs(index);
3498 
3499  return 0;
3500 }
3501 
3502 //--------------------------------------------------------------------------
3503 
3504 // Find the if the event passes the Delta R_{ij}, pT_{i} and Q_{ij} cuts on
3505 // the matrix element, as needed for cut-based merging scale definition.
3506 
3507 double MergingHooks::cutbasedms( const Event& event ){
3508 
3509  // Only check first emission.
3510  if (!isFirstEmission(event)) return -1.;
3511 
3512  // Save allowed final state particles
3513  vector<int> partons;
3514  for( int i=0; i < event.size(); ++i) {
3515  if ( event[i].isFinal()
3516  && isInHard( i, event )
3517  && checkAgainstCut(event[i]) )
3518  partons.push_back(i);
3519  }
3520 
3521  // Declare overall veto
3522  bool doVeto = false;
3523  // Declare vetoes
3524  bool vetoPT = false;
3525  bool vetoRjj = false;
3526  bool vetoMjj = false;
3527  // Declare cuts used in matrix element
3528  double pTjmin = pTiMS();
3529  double mjjmin = QijMS();
3530  double rjjmin = dRijMS();
3531 
3532  // Declare minimum values
3533  double minPT = event[0].e();
3534  double minRJJ = 10.;
3535  double minMJJ = event[0].e();
3536 
3537  // Check matrix element cuts
3538  for( int i=0; i < int(partons.size()); ++i){
3539  // Save pT value
3540  minPT = min(minPT,event[partons[i]].pT());
3541 
3542  // Check two-parton cuts
3543  for( int j=0; j < int(partons.size()); ++j){
3544  if (i!=j){
3545 
3546  // Save delta R value
3547  minRJJ = min(minRJJ, deltaRij( event[partons[i]].p(),
3548  event[partons[j]].p()) );
3549  // Save delta R value
3550  minMJJ = min(minMJJ, ( event[partons[i]].p()
3551  +event[partons[j]].p() ).mCalc() );
3552 
3553  }
3554  }
3555  // Done with cut evaluation
3556  }
3557 
3558  // Check if all partons are in the matrix element region
3559  if (minPT > pTjmin) vetoPT = true;
3560  if (minRJJ > rjjmin) vetoRjj = true;
3561  if (minMJJ > mjjmin) vetoMjj = true;
3562 
3563  // In the matrix element calculation, we have rejected the events if any of
3564  // the cuts had not been fulfilled,
3565  // i.e. we are in the matrix element domain if all cuts are fulfilled.
3566  // We veto any emission in the ME region.
3567  // Disregard the two-parton cuts if only one parton in the final state
3568  if (int(partons.size() == 1))
3569  doVeto = vetoPT;
3570  else
3571  // Veto if the combination of cuts would be in the ME region
3572  doVeto = vetoPT && vetoRjj && vetoMjj;
3573 
3574  // If event is above merging scale, veto
3575  if (doVeto) return 1.;
3576 
3577  // Else, do nothing
3578  return -1.;
3579 
3580 }
3581 
3582 //--------------------------------------------------------------------------
3583 
3584 // Function to compute Delta R separation from 4-vector input.
3585 
3586 double MergingHooks::deltaRij(Vec4 jet1, Vec4 jet2){
3587 
3588  // Declare return variable
3589  double deltaR = 0.;
3590  // Get delta_eta and cosh(Delta_eta) for hadronic collisions
3591  double eta1 = 0.5*log( (jet1.e() + jet1.pz()) / (jet1.e() - jet1.pz()) );
3592  double eta2 = 0.5*log( (jet2.e() + jet2.pz()) / (jet2.e() - jet2.pz()) );
3593  // Get delta_phi and cos(Delta_phi) for hadronic collisions
3594  double pt1 = sqrt( pow(jet1.px(),2) + pow(jet1.py(),2) );
3595  double pt2 = sqrt( pow(jet2.px(),2) + pow(jet2.py(),2) );
3596  double cosdPhi = ( jet1.px()*jet2.px() + jet1.py()*jet2.py() ) / (pt1*pt2);
3597  double dPhi = acos( cosdPhi );
3598  // Calculate kT durham like fastjet
3599  deltaR = sqrt(pow(eta1-eta2,2) + pow(dPhi,2));
3600  // Return kT
3601  return deltaR;
3602 }
3603 
3604 //==========================================================================
3605 
3606 } // end namespace Pythia8
Definition: AgUStep.h:26