JHUGen MELA  v2.4.1
Matrix element calculations as used in JHUGen. MELA is an important tool that was used for the Higgs boson discovery and for precise measurements of its structure and interactions. Please see the website https://spin.pha.jhu.edu/ and papers cited there for more details, and kindly cite those papers when using this code.
MELACandidate.cc
Go to the documentation of this file.
1 #include "MELACandidate.h"
2 #include "TUtilHelpers.hh"
3 #include "MELAStreamHelpers.hh"
4 #include "TMath.h"
5 
6 
9 using namespace PDGHelpers;
10 
11 
13 MELAParticle(),
14 associatedByHighestPt(false),
15 isShallowCopy(false),
16 selfDecayMode(TVar::CandidateDecay_Stable)
17 {}
18 MELACandidate::MELACandidate(int id_, bool associatedByHighestPt_) :
19 MELAParticle(id_),
20 associatedByHighestPt(associatedByHighestPt_),
21 isShallowCopy(false),
22 selfDecayMode(TVar::CandidateDecay_Stable)
23 {}
24 MELACandidate::MELACandidate(int id_, TLorentzVector p4_, bool associatedByHighestPt_) :
25 MELAParticle(id_, p4_),
26 associatedByHighestPt(associatedByHighestPt_),
27 isShallowCopy(false),
28 selfDecayMode(TVar::CandidateDecay_Stable)
29 {}
31 MELAParticle(particle_),
32 associatedByHighestPt(particle_.associatedByHighestPt),
33 isShallowCopy(false),
34 selfDecayMode(particle_.selfDecayMode),
35 associatedLeptons(particle_.associatedLeptons),
36 associatedNeutrinos(particle_.associatedNeutrinos),
37 associatedPhotons(particle_.associatedPhotons),
38 associatedJets(particle_.associatedJets),
39 associatedTops(particle_.associatedTops),
40 sortedDaughters(particle_.sortedDaughters)
41 {
42  // Recreate the intermediate Vs since mother info needs to be reset
45 }
47  MELACandidate tmp(particle_);
48  swap(tmp);
49  return *this;
50 }
52  resetVs();
53  sortedDaughters.clear();
54  associatedTops.clear();
55  associatedJets.clear();
56  associatedLeptons.clear();
57  associatedNeutrinos.clear();
58  associatedPhotons.clear();
59 }
60 
63 
64  // Copy particle content
66  cand->setGenStatus(genStatus);
67  cand->setLifetime(lifetime);
68 
71 
72  // Copy candidate content
73  cand->setShallowCopy(true);
81 
82  return cand;
83 }
85  MELAParticle::swap(particle_);
86  std::swap(associatedByHighestPt, particle_.associatedByHighestPt);
87  std::swap(isShallowCopy, particle_.isShallowCopy);
88  std::swap(selfDecayMode, particle_.selfDecayMode);
89  std::swap(associatedLeptons, particle_.associatedLeptons);
90  std::swap(associatedNeutrinos, particle_.associatedNeutrinos);
91  std::swap(associatedPhotons, particle_.associatedPhotons);
92  std::swap(associatedJets, particle_.associatedJets);
93  std::swap(associatedTops, particle_.associatedTops);
94  std::swap(sortedDaughters, particle_.sortedDaughters);
95  std::swap(sortedVs, particle_.sortedVs);
96 }
97 
99  if (!isShallowCopy){ // Delete owned objects if not a shallow copy
100  for (MELAParticle*& aV:sortedVs) delete aV;
101  }
102  sortedVs.clear();
103  isShallowCopy=false; // Should delete sortedVs now
104 }
106  resetVs();
107  createSortedVs();
108  addAssociatedVs();
109 }
110 
111 
113 void MELACandidate::setAddAssociatedByHighestPt(bool associatedByHighestPt_){ associatedByHighestPt=associatedByHighestPt_; }
116 
119  if (debugVars::debugFlag) MELAout << "Starting MELACandidate::sortDaughters with self decay mode " << selfDecayMode << std::endl;
120  if (debugVars::debugFlag) MELAout << "Starting MELACandidate::sortDaughtersInitial" << std::endl;
122  if (debugVars::debugFlag) MELAout << "Starting MELACandidate::sortDaughtersByBestZ1" << std::endl;
124  if (debugVars::debugFlag) MELAout << "Starting MELACandidate::createSortedVs" << std::endl;
125  createSortedVs();
126 }
127 
128 std::vector<int> MELACandidate::getDaughterIds()const{
129  std::vector<int> result;
130  for (MELAParticle const* const& dau:sortedDaughters){
131  if (dau) result.push_back(dau->id);
132  }
133  return result;
134 }
136  std::vector<int> result;
137  std::vector<std::vector<MELAParticle*> const*> list; list.reserve(3);
138  list.push_back(&associatedLeptons);
139  list.push_back(&associatedPhotons);
140  list.push_back(&associatedJets);
141  for (std::vector<MELAParticle*> const*& ll:list){
142  for (MELAParticle* const& part:(*ll)){
143  if (part) result.push_back(part->id);
144  }
145  }
146  return result;
147 }
149  if ((int)sortedDaughters.size()>index) return sortedDaughters.at(index);
150  else return 0;
151 }
153  if ((int)sortedVs.size()>index) return sortedVs.at(index);
154  else return 0;
155 }
157  if ((int)associatedLeptons.size()>index) return associatedLeptons.at(index);
158  else return 0;
159 }
161  if ((int)associatedNeutrinos.size()>index) return associatedNeutrinos.at(index);
162  else return 0;
163 }
165  if ((int)associatedPhotons.size()>index) return associatedPhotons.at(index);
166  else return 0;
167 }
169  if ((int)associatedJets.size()>index) return associatedJets.at(index);
170  else return 0;
171 }
173  if ((int)associatedTops.size()>index) return associatedTops.at(index);
174  else return 0;
175 }
176 
177 std::vector<MELAParticle*>& MELACandidate::getSortedDaughters(){ return sortedDaughters; }
178 std::vector<MELAParticle*>& MELACandidate::getSortedVs(){ return sortedVs; }
179 std::vector<MELAParticle*>& MELACandidate::getAssociatedLeptons(){ return associatedLeptons; }
180 std::vector<MELAParticle*>& MELACandidate::getAssociatedNeutrinos(){ return associatedNeutrinos; }
181 std::vector<MELAParticle*>& MELACandidate::getAssociatedPhotons(){ return associatedPhotons; }
182 std::vector<MELAParticle*>& MELACandidate::getAssociatedJets(){ return associatedJets; }
183 std::vector<MELATopCandidate_t*>& MELACandidate::getAssociatedTops(){ return associatedTops; }
184 
185 const std::vector<MELAParticle*>& MELACandidate::getSortedDaughters()const{ return sortedDaughters; }
186 const std::vector<MELAParticle*>& MELACandidate::getSortedVs()const{ return sortedVs; }
187 const std::vector<MELAParticle*>& MELACandidate::getAssociatedLeptons()const{ return associatedLeptons; }
188 const std::vector<MELAParticle*>& MELACandidate::getAssociatedNeutrinos()const{ return associatedNeutrinos; }
189 const std::vector<MELAParticle*>& MELACandidate::getAssociatedPhotons()const{ return associatedPhotons; }
190 const std::vector<MELAParticle*>& MELACandidate::getAssociatedJets()const{ return associatedJets; }
191 const std::vector<MELATopCandidate_t*>& MELACandidate::getAssociatedTops()const{ return associatedTops; }
192 
193 std::vector<MELAParticle*> MELACandidate::getAssociatedSortedVs(){
194  std::vector<MELAParticle*> res;
195  std::vector<MELAParticle*>::iterator itEnd=sortedVs.end();
196  std::vector<MELAParticle*>::iterator itBegin=itEnd;
197  for (std::vector<MELAParticle*>::iterator it=sortedVs.begin(); it!=itEnd; it++){
198  bool doSkip=false;
199  for (auto const& dau:sortedDaughters){ if ((*it)->hasDaughter(dau)){ doSkip=true; break; } }
200  if (!doSkip){ itBegin=it; break; }
201  }
202  if (itBegin!=itEnd) std::copy(itBegin, itEnd, std::back_inserter(res));
203  return res;
204 }
205 std::vector<MELAParticle*> MELACandidate::getAssociatedSortedVs()const{
206  std::vector<MELAParticle*> res;
207  std::vector<MELAParticle*>::const_iterator itEnd=sortedVs.cend();
208  std::vector<MELAParticle*>::const_iterator itBegin=itEnd;
209  for (std::vector<MELAParticle*>::const_iterator it=sortedVs.cbegin(); it!=itEnd; it++){
210  bool doSkip=false;
211  for (auto const& dau:sortedDaughters){ if ((*it)->hasDaughter(dau)){ doSkip=true; break; } }
212  if (!doSkip){ itBegin=it; break; }
213  }
214  if (itBegin!=itEnd) std::copy(itBegin, itEnd, std::back_inserter(res));
215  return res;
216 }
217 
219  bool beginWithIdPair = (
225  );
227  int nDaughtersBooked=0;
228  int tmpDindex[2]={ 0 };
229  MELAParticle* df[2] ={ getDaughter(0), 0 };
230  if (df[0]!=0) nDaughtersBooked++;
231  for (int j=1; j<getNDaughters(); j++){
232  MELAParticle* dtmp = getDaughter(j);
233  if (
234  (beginWithIdPair && std::abs(dtmp->charge())-std::abs(df[0]->charge())==0 && std::abs(dtmp->id)==std::abs(df[0]->id)) // First daughter in ZZ/ZW/ZG/GG/ff requires identical |Q| and |id|.
235  ||
236  ( // First daughter in WW/WG requires a pair with |sum(Q)|=1 and opposite id signs, or two unknown jets.
237  beginWithWPair
238  &&
239  (
240  (std::abs(dtmp->charge()+df[0]->charge())==1 && TMath::Sign(1, dtmp->id)==-TMath::Sign(1, df[0]->id))
241  ||
243  )
244  )
245  ){
246  df[1] = dtmp;
247  tmpDindex[1] = j;
248  nDaughtersBooked++;
249  break;
250  }
251  }
252  MELAParticle* ds[2] ={ 0 };
253  int sindex=0;
254  for (int j=1; j<getNDaughters(); j++){
255  if (j==tmpDindex[1]) continue;
256  MELAParticle* dtmp = getDaughter(j);
257  ds[sindex] = dtmp;
258  nDaughtersBooked++;
259  sindex++;
260  if (sindex==2) break;
261  }
262 
263  if (nDaughtersBooked!=getNDaughters()){
264  if (getNDaughters()>4) MELAout << "MELACandidate::sortDaughtersInitial: Number of daughters passed " << getNDaughters() << ">4 is currently not supported." << std::endl;
265  MELAout << "MELACandidate::sortDaughtersInitial: Number of daughters passed (" << getNDaughters() << ") is not the same as number of daughters booked (" << nDaughtersBooked << ")! Aborting, no daughters can be recorded." << std::endl;
266  for (int idau=0; idau<getNDaughters(); idau++){
267  MELAParticle* part = getDaughter(idau);
268  if (part!=0) MELAout << "\t- Passed daughter " << idau << " (X, Y, Z, T, M, Id) = "
269  << part->x() << " " << part->y() << " " << part->z() << " " << part->t() << " " << part->m() << " " << part->id << std::endl;
270  else MELAout << "\t- Passed daughter " << idau << " = 0!" << std::endl;
271  }
272  for (unsigned int j=0; j<2; j++){ if (df[j]!=0) MELAout << "\t- df[" << j << "] (X, Y, Z, T, M, Id) = " << df[j]->x() << " " << df[j]->y() << " " << df[j]->z() << " " << df[j]->t() << " " << df[j]->m() << " " << df[j]->id << std::endl; }
273  for (unsigned int j=0; j<2; j++){ if (ds[j]!=0) MELAout << "\t- ds[" << j << "] (X, Y, Z, T, M, Id) = " << ds[j]->x() << " " << ds[j]->y() << " " << ds[j]->z() << " " << ds[j]->t() << " " << ds[j]->m() << " " << ds[j]->id << std::endl; }
274  return;
275  }
276 
277  if (
278  (df[0]!=0 && df[1]!=0)
279  &&
280  (
281  // Order by ubar(0)v(1)
282  (df[0]->id<df[1]->id && beginWithIdPair)
283  ||
284  (df[0]->id<df[1]->id && df[0]->id<0 && beginWithWPair)
285  ||
286  ((df[0]->id*df[1]->id>0 || (df[0]->id==0 && df[1]->id==0)) && df[0]->phi()<df[1]->phi())
287  )
288  ){
289  MELAParticle* dtmp = df[0];
290  df[0] = df[1];
291  df[1] = dtmp;
292  }
293 
294  if (
295  (ds[0]!=0 && ds[1]!=0)
296  &&
297  (
298  // Order by ubar(0)v(1)
299  (ds[0]->id<ds[1]->id && beginWithIdPair)
300  ||
301  (ds[0]->id<ds[1]->id && ds[0]->id<0 && beginWithWPair)
302  ||
303  ((ds[0]->id*ds[1]->id>0 || (ds[0]->id==0 && ds[1]->id==0)) && ds[0]->phi()<ds[1]->phi())
304  )
305  ){
306  MELAParticle* dtmp = ds[0];
307  ds[0] = ds[1];
308  ds[1] = dtmp;
309  }
310  if (df[1]==0 && df[0]!=0 && ds[0]!=0 && ds[1]!=0){ // Swap GZ to ZG
311  for (int ip=0; ip<2; ip++){
312  MELAParticle* dtmp = ds[ip];
313  ds[ip] = df[ip];
314  df[ip] = dtmp;
315  }
316  }
317  for (int i=0; i<2; i++){
318  if (df[i]!=0) sortedDaughters.push_back(df[i]);
319  }
320  for (int i=0; i<2; i++){
321  if (ds[i]!=0) sortedDaughters.push_back(ds[i]);
322  }
323 }
325  bool beginWithZPair = (
329  );
330  bool beginWithMasslessPair = (
333  );
334  bool beginWithIdPair = beginWithZPair || beginWithMasslessPair;
336 
337  double HVVmass = PDGHelpers::Zeromass;
338  if (beginWithZPair) HVVmass = PDGHelpers::Zmass;
339  else if (beginWithWPair) HVVmass = PDGHelpers::Wmass;
340 
341  MELAParticle* orderedDs[2][2]={ { 0 } };
342  TLorentzVector pZ1(0, 0, 0, 0);
343  TLorentzVector pZ2(0, 0, 0, 0);
344  if (sortedDaughters.size()>2){ // WW, ZZ, ZW, WG, ZG
345  bool dauDiffType = true;
346  if (debugVars::debugFlag) MELAout << "Ndaughters>2" << std::endl;
347 
348  for (int d=0; d<std::min(2, (int)sortedDaughters.size()); d++){
349  if (sortedDaughters.at(d)!=0) pZ1 = pZ1 + sortedDaughters.at(d)->p4;
350  }
351  for (int d=std::min(2, (int)sortedDaughters.size()); d<std::min(4, (int)sortedDaughters.size()); d++){
352  if (sortedDaughters.at(d)!=0) pZ2 = pZ2 + sortedDaughters.at(d)->p4;
353  }
354 
355  if (debugVars::debugFlag) MELAout << "Preliminary pZ1 and pZ2 calculated!" << std::endl;
356 
357  if (sortedDaughters.size()>=4){
358  if (
359  beginWithIdPair &&
360  (
361  (isALepton(sortedDaughters.at(0)->id) && isALepton(sortedDaughters.at(1)->id) && isALepton(sortedDaughters.at(2)->id) && isALepton(sortedDaughters.at(3)->id))
362  ||
364  ||
365  (isAPhoton(sortedDaughters.at(0)->id) && isAPhoton(sortedDaughters.at(1)->id) && isAPhoton(sortedDaughters.at(2)->id) && isAPhoton(sortedDaughters.at(3)->id))
366  ||
368  ||
370  ||
371  (isAGluon(sortedDaughters.at(0)->id) && isAGluon(sortedDaughters.at(1)->id) && isAGluon(sortedDaughters.at(2)->id) && isAGluon(sortedDaughters.at(3)->id))
372  ||
374  )
375  ) dauDiffType=false;
376  }
377 
378  if (
379  (dauDiffType && beginWithIdPair && (
380  sortedDaughters.size()<4 // WG, ZG
381  ||
382  (
383  // WW, ZZ, ZW (mostly relevant for Z1-Z2 sorting)
384  // Zll>Znn>?GG>Zdd>Zuu>?gg>Zjj. 0-2 swap may then give W+W-.
385  sortedDaughters.size()>=4 && (
386  isALepton(sortedDaughters.at(0)->id) ||
387  (isANeutrino(sortedDaughters.at(0)->id) && !isALepton(sortedDaughters.at(2)->id)) ||
388  (isAPhoton(sortedDaughters.at(0)->id) && !isALepton(sortedDaughters.at(2)->id) && !isANeutrino(sortedDaughters.at(2)->id)) ||
389  (isDownTypeQuark(sortedDaughters.at(0)->id) && !isALepton(sortedDaughters.at(2)->id) && !isANeutrino(sortedDaughters.at(2)->id) && !isAPhoton(sortedDaughters.at(2)->id)) ||
390  (isUpTypeQuark(sortedDaughters.at(0)->id) && !isALepton(sortedDaughters.at(2)->id) && !isANeutrino(sortedDaughters.at(2)->id) && !isAPhoton(sortedDaughters.at(2)->id) && !isDownTypeQuark(sortedDaughters.at(2)->id)) ||
391  (isAGluon(sortedDaughters.at(0)->id) && !isALepton(sortedDaughters.at(2)->id) && !isANeutrino(sortedDaughters.at(2)->id) && !isAPhoton(sortedDaughters.at(2)->id) && !isDownTypeQuark(sortedDaughters.at(2)->id) && !isUpTypeQuark(sortedDaughters.at(2)->id)) ||
392  (isAnUnknownJet(sortedDaughters.at(0)->id) && !isALepton(sortedDaughters.at(2)->id) && !isANeutrino(sortedDaughters.at(2)->id) && !isAPhoton(sortedDaughters.at(2)->id) && !isDownTypeQuark(sortedDaughters.at(2)->id) && !isUpTypeQuark(sortedDaughters.at(2)->id) && !isAGluon(sortedDaughters.at(2)->id))
393  )
394  )
395  )
396  )
397  ||
398  // ZZ->4f
399  (
400  !dauDiffType && beginWithIdPair && std::abs(pZ1.M() - HVVmass)<std::abs(pZ2.M() - HVVmass) // Z1 / Z2
401  )
402  ||
403  (sortedDaughters.at(0)!=0 && sortedDaughters.at(1)!=0 && beginWithWPair && (sortedDaughters.at(0)->charge()+sortedDaughters.at(1)->charge())>0) // W+ / W-
404  ){
405  if (debugVars::debugFlag) MELAout << "pZ1 is closer to HVVmass " << HVVmass << std::endl;
406  orderedDs[0][0]=sortedDaughters.at(0);
407  orderedDs[0][1]=sortedDaughters.at(1);
408  orderedDs[1][0]=((int)sortedDaughters.size()>2 ? sortedDaughters.at(2) : 0);
409  orderedDs[1][1]=((int)sortedDaughters.size()>3 ? sortedDaughters.at(3) : 0);
410  }
411  else{
412  if (debugVars::debugFlag) MELAout << "pZ2 is closer to HVVmass " << HVVmass << std::endl;
413  orderedDs[0][0]=((int)sortedDaughters.size()>2 ? sortedDaughters.at(2) : 0);
414  orderedDs[0][1]=((int)sortedDaughters.size()>3 ? sortedDaughters.at(3) : 0);
415  orderedDs[1][0]=sortedDaughters.at(0);
416  orderedDs[1][1]=sortedDaughters.at(1);
417  TLorentzVector ptmp = pZ1;
418  pZ1 = pZ2;
419  pZ2 = ptmp;
420  }
421  }
422  else if (sortedDaughters.size()==2){ // GG, ffbar
423  if (debugVars::debugFlag) MELAout << "Ndaughters==2" << std::endl;
424 
425  if (sortedDaughters.at(0)!=0) pZ1 = pZ1 + sortedDaughters.at(0)->p4;
426  if (sortedDaughters.at(1)!=0) pZ2 = pZ2 + sortedDaughters.at(1)->p4;
427  orderedDs[0][0]=sortedDaughters.at(0);
428  orderedDs[0][1]=0;
429  orderedDs[1][0]=sortedDaughters.at(1);
430  orderedDs[1][1]=0;
431  }
432  if (
433  (
434  (orderedDs[0][1]!=0 && orderedDs[1][1]!=0)
435  &&
436  (orderedDs[0][1]->id == orderedDs[1][1]->id)
437  )
438  ||
439  (
440  (orderedDs[1][0]!=0 && orderedDs[0][0]!=0)
441  &&
442  (orderedDs[1][0]->id == orderedDs[0][0]->id)
443  )
444  ){
445  if (debugVars::debugFlag) MELAout << "Checking alternative pairings." << std::endl;
446 
447  MELAParticle* orderedDps[2][2]={ { 0 } };
448 
449  TLorentzVector pZ1p(0, 0, 0, 0);
450  TLorentzVector pZ2p(0, 0, 0, 0);
451  for (int d=0; d<2; d++){
452  if (orderedDs[d][d]!=0) pZ1p = pZ1p + orderedDs[d][d]->p4;
453  }
454  for (int d=0; d<2; d++){
455  if (orderedDs[1-d][d]!=0) pZ2p = pZ2p + orderedDs[1-d][d]->p4;
456  }
457 
458  if (std::abs(pZ1p.M() - HVVmass)<std::abs(pZ2p.M() - HVVmass)){
459  orderedDps[0][0]=orderedDs[0][0];
460  orderedDps[0][1]=orderedDs[1][1];
461  orderedDps[1][0]=orderedDs[1][0];
462  orderedDps[1][1]=orderedDs[0][1];
463  }
464  else{
465  orderedDps[0][0]=orderedDs[1][0];
466  orderedDps[0][1]=orderedDs[0][1];
467  orderedDps[1][0]=orderedDs[0][0];
468  orderedDps[1][1]=orderedDs[1][1];
469  TLorentzVector ptmp = pZ1p;
470  pZ1p = pZ2p;
471  pZ2p = ptmp;
472  }
473  if (std::abs(pZ1p.M() - HVVmass)<std::abs(pZ1.M() - HVVmass) || (std::abs(pZ1p.M() - HVVmass)==std::abs(pZ1.M() - HVVmass) && pZ2p.Pt()>pZ2.Pt())){
474  for (int i=0; i<2; i++){
475  for (int j=0; j<2; j++) orderedDs[i][j] = orderedDps[i][j];
476  }
477  }
478  }
479  sortedDaughters.clear();
480  for (int i=0; i<2; i++){
481  for (int j=0; j<2; j++){
482  if (orderedDs[i][j]!=0) sortedDaughters.push_back(orderedDs[i][j]);
483  }
484  }
485  if (debugVars::debugFlag) MELAout << "Final number of daughters in sortedDaughters: " << sortedDaughters.size() << std::endl;
486 }
488  TLorentzVector nullVector(0, 0, 0, 0);
489  bool beginWithZPair = (
493  );
495  int VID = 21; // Gamma/Gamma*
496  if (beginWithWPair) VID = 24; // W+/W-
497  else if (beginWithZPair) VID = 23; // Z
498 
499  int icutoff = (sortedDaughters.size()>2 ? 2 : std::min(1, (int)sortedDaughters.size()));
500  int imax = std::min(4, (int)sortedDaughters.size());
501  int V1id=-9000, V2id=-9000;
502  if (icutoff==0) V1id=25;
503  else{
504  double Vcharge[2]={ 0 };
505  for (int d=0; d<icutoff; d++){
506  if (sortedDaughters.at(d)!=0){
507  if (icutoff==2){
508  V1id=VID;
509  Vcharge[0] += sortedDaughters.at(d)->charge();
510  }
511  else if (icutoff==1) V1id=sortedDaughters.at(d)->id;
512  }
513  }
514  for (int d=icutoff; d<imax; d++){
515  if (sortedDaughters.at(d)!=0){
516  if ((imax-icutoff)==2){
517  V2id=(VID!=24 ? VID : -VID);
518  Vcharge[1] += sortedDaughters.at(d)->charge();
519  }
520  else if ((imax-icutoff)==1) V2id=sortedDaughters.at(d)->id;
521  }
522  }
523  // Override selfDecayMode if charges indicate some other final state
524  if (fabs(Vcharge[0]-1.)<0.001) V1id=24;
525  else if (fabs(Vcharge[0]+1.)<0.001) V1id=-24;
526  if (fabs(Vcharge[1]-1.)<0.001) V2id=24;
527  else if (fabs(Vcharge[1]+1.)<0.001) V2id=-24;
528  }
529 
530  // If the number of Zs is less than 2, should still create empty particles
531  MELAParticle* Z1 = new MELAParticle(V1id);
532  MELAParticle* Z2 = new MELAParticle(V2id);
533 
534  // Add daughters and their 4-vectors
535  if (icutoff==0) Z1->p4 = this->p4; // V1=H, V2=invalid
536  else{
537  for (int d=0; d<icutoff; d++){ if (sortedDaughters.at(d)!=0) *Z1 += sortedDaughters.at(d); }
538  for (int d=icutoff; d<imax; d++){ if (sortedDaughters.at(d)!=0) *Z2 += sortedDaughters.at(d); }
539  }
540 
541  // Configure relationships
542  Z1->addMother(this);
543  addSortedV(Z1);
544  Z2->addMother(this);
545  addSortedV(Z2);
546 }
547 TLorentzVector MELACandidate::getAlternativeVMomentum(int index)const{
548  bool beginWithZPair = (
552  );
554 
555  double HVVmass = PDGHelpers::Zeromass;
556  if (beginWithZPair) HVVmass = PDGHelpers::Zmass;
557  else if (beginWithWPair) HVVmass = PDGHelpers::Wmass;
558 
559  TLorentzVector nullFourVector(0, 0, 0, 0);
560  if (sortedDaughters.size()>=4){
561  if (beginWithWPair){
562  TLorentzVector pUU = sortedDaughters.at(0)->p4 + sortedDaughters.at(3)->p4;
563  TLorentzVector pDD = sortedDaughters.at(2)->p4 + sortedDaughters.at(1)->p4;
564  return (index==0 ? pDD : pUU);
565  }
566  else{
567  TLorentzVector pWp = sortedDaughters.at(2)->p4 + sortedDaughters.at(1)->p4;
568  TLorentzVector pWm = sortedDaughters.at(0)->p4 + sortedDaughters.at(3)->p4;
569  if (
570  (
571  (isALepton(sortedDaughters.at(0)->id) && isALepton(sortedDaughters.at(2)->id))
572  ||
573  (isANeutrino(sortedDaughters.at(0)->id) && isANeutrino(sortedDaughters.at(2)->id))
574  ||
575  (isAJet(sortedDaughters.at(0)->id) && isAJet(sortedDaughters.at(2)->id))
576  )
577  &&
578  std::abs(pWp.M() - HVVmass) > std::abs(pWm.M() - HVVmass)
579  ) std::swap(pWp, pWm);
580  return (index==0 ? pWp : pWm);
581  }
582  }
583  else if (sortedDaughters.size()==3){
584  TLorentzVector pVa = sortedDaughters.at(0)->p4 + sortedDaughters.at(2)->p4;
585  TLorentzVector pVb = sortedDaughters.at(1)->p4 + sortedDaughters.at(2)->p4;
586  return (index==0 ? pVa : pVb);
587  }
588  else return nullFourVector;
589 }
591  bool doInterfere = false;
592  if (sortedDaughters.size()>3) doInterfere = (
593  (sortedDaughters.at(0))->id == (sortedDaughters.at(2))->id
594  &&
595  (sortedDaughters.at(1))->id == (sortedDaughters.at(3))->id
596  &&
598  );
599  return doInterfere;
600 }
601 
602 bool MELACandidate::checkDaughtership(MELAParticle const* myParticle)const{
603  return hasDaughter(myParticle);
604 }
605 
608 }
610  addAssociatedParticleToArray(myParticle, associatedLeptons); // Neutrinos are leptons at the ZZ candidate level
612 }
615 }
618 }
621 }
622 void MELACandidate::addAssociatedParticleToArray(MELAParticle* myParticle, std::vector<MELAParticle*>& particleArray){
623  if (checkDaughtership(myParticle)) return;
624  if (associatedByHighestPt) MELACandidate::addByHighestPt(myParticle, particleArray);
625  else MELACandidate::addUnordered(myParticle, particleArray);
626 }
627 void MELACandidate::addAssociatedParticleToArray(MELAThreeBodyDecayCandidate* myParticle, std::vector<MELAThreeBodyDecayCandidate*>& particleArray){
628  if (checkDaughtership(myParticle)) return;
629 
630  // Check if any of the top daughters, if present, are also daughters of the candidate.
631  if (myParticle->getPartnerParticle() && checkDaughtership(myParticle->getPartnerParticle())) return;
632  if (myParticle->getWFermion() && checkDaughtership(myParticle->getWFermion())) return;
633  if (myParticle->getWAntifermion() && checkDaughtership(myParticle->getWAntifermion())) return;
634 
635  if (associatedByHighestPt) MELACandidate::addByHighestPt(myParticle, particleArray);
636  else MELACandidate::addUnordered(myParticle, particleArray);
637 }
638 
642 }
643 void MELACandidate::createAssociatedVs(std::vector<MELAParticle*>& particleArray){
644  for (unsigned int i = 0; i<particleArray.size(); i++){
645  double Qi = particleArray.at(i)->charge();
646  const int& id_i = particleArray.at(i)->id;
647 
648  for (unsigned int j = i+1; j<particleArray.size(); j++){
649  double Qj = particleArray.at(j)->charge();
650  const int& id_j = particleArray.at(j)->id;
651 
652  int bosonId=-1;
653  if ((Qi+Qj)==0 && (id_i+id_j)==0) bosonId = (id_i==0 ? 0 : 23); // Z->(f,fb) or 0->(0,0)
654  else if (PDGHelpers::isAnUnknownJet(id_i) || PDGHelpers::isAnUnknownJet(id_j)) bosonId = 0; // 0->(q,0)/(0,qb)
655  else if ( // W->f fb'
656  abs(Qi+Qj)==1
657  &&
658  (
659  ((PDGHelpers::isALepton(id_i) || PDGHelpers::isALepton(id_j)) && std::abs(id_i+id_j)==1) // Require SF lnu particle-antiparticle pairs
660  ||
661  (PDGHelpers::isUpTypeQuark(id_i) && PDGHelpers::isDownTypeQuark(id_j)) // Require ud- or du-type pairs, qqbar requirement is satisfied with charge.
662  ||
664  )
665  ) bosonId=24*(Qi+Qj);
666 
667  if (bosonId!=-1){
668  MELAParticle* boson = new MELAParticle(bosonId);
669  // Order by f-f'b
670  int firstdaughter = i, seconddaughter = j;
671  if (
672  (particleArray.at(firstdaughter)->id<particleArray.at(seconddaughter)->id)
673  &&
674  (
675  !PDGHelpers::isAWBoson(bosonId)
676  ||
677  (particleArray.at(firstdaughter)->id<0 && PDGHelpers::isAWBoson(bosonId))
678  )
679  ) std::swap(firstdaughter, seconddaughter);
680  *boson += particleArray.at(firstdaughter);
681  *boson += particleArray.at(seconddaughter);
682 
683  boson->addMother(this);
684  addSortedV(boson);
685  }
686  }
687  }
688 }
689 
691  for (auto& dau:getDaughters()){
692  if (!dau->passSelection){
693  passSelection=false;
694  break;
695  }
696  }
697 }
698 
699 void MELACandidate::getRelatedParticles(std::vector<MELAParticle*>& particles) const{
701  for (auto* part:sortedDaughters){ if (part) part->getRelatedParticles(particles); } // Hopefully no particle gets added from here
702  for (auto* part:associatedTops){ if (part) part->getRelatedParticles(particles); }
703  for (auto* part:sortedVs){ if (part) part->getRelatedParticles(particles); }
704  for (auto* part:associatedLeptons){ if (part) part->getRelatedParticles(particles); }
705  for (auto* part:associatedPhotons){ if (part) part->getRelatedParticles(particles); }
706  for (auto* part:associatedJets){ if (part) part->getRelatedParticles(particles); }
707 }
708 void MELACandidate::getDaughterParticles(std::vector<MELAParticle*>& particles) const{
710  for (auto* part:sortedDaughters){ if (part) part->getDaughterParticles(particles); } // Hopefully no particle gets added from here
711  for (auto* sortedV:sortedVs){ // Only add sorted Vs that are actually the intermediates of the sorted daughters
712  if (!sortedV) continue;
713  bool doAddV=false;
714  for (auto& dau:sortedDaughters){ if (dau && sortedV->hasDaughter(dau)){ doAddV=true; break; } }
715  if (doAddV) sortedV->getDaughterParticles(particles);
716  }
717 }
718 
719 void MELACandidate::addUnordered(MELAParticle* myParticle, std::vector<MELAParticle*>& particleArray){
720  bool inserted = MELAParticle::checkParticleExists(myParticle, particleArray); // Test if the particle is already in the vector
721  if (!inserted) particleArray.push_back(myParticle);
722 }
723 void MELACandidate::addUnordered(MELAThreeBodyDecayCandidate* myParticle, std::vector<MELAThreeBodyDecayCandidate*>& particleArray){
724  bool inserted = MELAThreeBodyDecayCandidate::checkCandidateExists(myParticle, particleArray); // Test if the particle is already in the vector
725  if (!inserted) particleArray.push_back(myParticle);
726 }
727 void MELACandidate::addByHighestPt(MELAParticle* myParticle, std::vector<MELAParticle*>& particleArray){
728  bool inserted = MELAParticle::checkParticleExists(myParticle, particleArray); // Test if the particle is already in the vector
729  if (!inserted){
730  for (std::vector<MELAParticle*>::iterator it = particleArray.begin(); it<particleArray.end(); it++){
731  if ((*it)->pt()<myParticle->pt()){
732  inserted=true;
733  particleArray.insert(it, myParticle);
734  break;
735  }
736  }
737  if (!inserted) particleArray.push_back(myParticle);
738  }
739 }
740 void MELACandidate::addByHighestPt(MELAThreeBodyDecayCandidate* myParticle, std::vector<MELAThreeBodyDecayCandidate*>& particleArray){
741  bool inserted = MELAThreeBodyDecayCandidate::checkCandidateExists(myParticle, particleArray); // Test if the particle is already in the vector
742  if (!inserted){
743  for (std::vector<MELAThreeBodyDecayCandidate*>::iterator it = particleArray.begin(); it<particleArray.end(); it++){
744  if ((*it)->pt()<myParticle->pt()){
745  inserted=true;
746  particleArray.insert(it, myParticle);
747  break;
748  }
749  }
750  if (!inserted) particleArray.push_back(myParticle);
751  }
752 }
MELAThreeBodyDecayCandidate::getWAntifermion
MELAParticle * getWAntifermion()
Definition: MELAThreeBodyDecayCandidate.h:23
MELACandidate::getAssociatedTop
MELATopCandidate_t * getAssociatedTop(int index) const
Definition: MELACandidate.cc:172
PDGHelpers::isALepton
bool isALepton(const int id)
Definition: PDGHelpers.cc:62
MELACandidate::daughtersInterfere
bool daughtersInterfere() const
Definition: MELACandidate.cc:590
MELAParticle::MELAParticle
MELAParticle()
Definition: MELAParticle.cc:16
MELACandidate::getSortedVs
std::vector< MELAParticle * > & getSortedVs()
Definition: MELACandidate.cc:178
PDGHelpers::HDecayMode
TVar::CandidateDecayMode HDecayMode
Definition: PDGHelpers.cc:11
MELAParticle::getDaughter
MELAParticle * getDaughter(int index) const
Definition: MELAParticle.cc:68
MELACandidate::setAddAssociatedByHighestPt
void setAddAssociatedByHighestPt(bool associatedByHighestPt_)
Definition: MELACandidate.cc:113
debugVars::debugFlag
bool debugFlag
Definition: MELAParticle.cc:12
MELAParticle::pt
double pt() const
Definition: MELAParticle.h:72
MELACandidate::addAssociatedJet
void addAssociatedJet(MELAParticle *myParticle)
Definition: MELACandidate.cc:616
MELACandidate::isShallowCopy
bool isShallowCopy
Definition: MELACandidate.h:92
MELACandidate::resetVs
void resetVs()
Definition: MELACandidate.cc:98
MELACandidate::selfDecayMode
TVar::CandidateDecayMode selfDecayMode
Definition: MELACandidate.h:93
MELACandidate::operator=
MELACandidate & operator=(const MELACandidate &particle_)
Definition: MELACandidate.cc:46
TVar::CandidateDecay_ZZ
@ CandidateDecay_ZZ
Definition: TVar.hh:41
MELAParticle::getNDaughters
int getNDaughters() const
Definition: MELAParticle.h:50
MELAParticle::swap
void swap(MELAParticle &particle_)
Definition: MELAParticle.cc:52
MELACandidate::associatedByHighestPt
bool associatedByHighestPt
Definition: MELACandidate.h:91
MELACandidate::getAssociatedNeutrino
MELAParticle * getAssociatedNeutrino(int index) const
Definition: MELACandidate.cc:160
PDGHelpers
Definition: PDGHelpers.h:12
MELACandidate::createAssociatedVs
void createAssociatedVs(std::vector< MELAParticle * > &particleArray)
Definition: MELACandidate.cc:643
MELAParticle::getDaughters
std::vector< MELAParticle * > & getDaughters()
Definition: MELAParticle.h:59
MELACandidate::getSortedV
MELAParticle * getSortedV(int index) const
Definition: MELACandidate.cc:152
MELAThreeBodyDecayCandidate::checkCandidateExists
static bool checkCandidateExists(MELAThreeBodyDecayCandidate const *myParticle, std::vector< MELAThreeBodyDecayCandidate * > const &particleArray)
Definition: MELAThreeBodyDecayCandidate.cc:63
MELACandidate::addAssociatedNeutrino
void addAssociatedNeutrino(MELAParticle *myParticle)
Definition: MELACandidate.cc:609
MELAParticle::setGenStatus
void setGenStatus(int status_)
Definition: MELAParticle.h:43
MELACandidate::swap
void swap(MELACandidate &particle_)
Definition: MELACandidate.cc:84
TVar::CandidateDecayMode
CandidateDecayMode
Definition: TVar.hh:37
MELACandidate::associatedNeutrinos
std::vector< MELAParticle * > associatedNeutrinos
Definition: MELACandidate.h:96
TVar::CandidateDecay_Stable
@ CandidateDecay_Stable
Definition: TVar.hh:38
MELACandidate::addAssociatedVs
void addAssociatedVs()
Definition: MELACandidate.cc:639
TVar
Definition: TVar.hh:28
MELACandidate::getAssociatedPhoton
MELAParticle * getAssociatedPhoton(int index) const
Definition: MELACandidate.cc:164
TVar::CandidateDecay_WW
@ CandidateDecay_WW
Definition: TVar.hh:40
MELACandidate::getDaughterIds
virtual std::vector< int > getDaughterIds() const
Definition: MELACandidate.cc:128
MELACandidate::addAssociatedPhoton
void addAssociatedPhoton(MELAParticle *myParticle)
Definition: MELACandidate.cc:613
MELAParticle::t
double t() const
Definition: MELAParticle.h:70
PDGHelpers::isAnUnknownJet
bool isAnUnknownJet(const int id)
Definition: PDGHelpers.cc:22
MELACandidate::getRelatedParticles
void getRelatedParticles(std::vector< MELAParticle * > &particles) const
Definition: MELACandidate.cc:699
MELACandidate::associatedTops
std::vector< MELATopCandidate_t * > associatedTops
Definition: MELACandidate.h:99
MELAParticle::phi
double phi() const
Definition: MELAParticle.h:74
PDGHelpers::isANeutrino
bool isANeutrino(const int id)
Definition: PDGHelpers.cc:67
MELAParticle::checkParticleExists
static bool checkParticleExists(MELAParticle const *myParticle, std::vector< MELAParticle * > const &particleArray)
Definition: MELAParticle.cc:116
MELACandidate::shallowCopy
MELACandidate * shallowCopy()
Definition: MELACandidate.cc:61
PDGHelpers::isAPhoton
bool isAPhoton(const int id)
Definition: PDGHelpers.cc:72
MELAParticle::y
double y() const
Definition: MELAParticle.h:68
MELAParticle::hasDaughter
bool hasDaughter(MELAParticle const *part) const
Definition: MELAParticle.cc:88
MELAStreamHelpers::MELAout
MELAOutputStreamer MELAout
MELAParticle::x
double x() const
Definition: MELAParticle.h:67
MELACandidate::~MELACandidate
~MELACandidate()
Definition: MELACandidate.cc:51
MELAThreeBodyDecayCandidate::getPartnerParticle
MELAParticle * getPartnerParticle()
Definition: MELAThreeBodyDecayCandidate.h:21
MELAParticle::m
double m() const
Definition: MELAParticle.h:66
MELACandidate::recreateVs
void recreateVs()
Definition: MELACandidate.cc:105
MELACandidate::getAssociatedPhotons
std::vector< MELAParticle * > & getAssociatedPhotons()
Definition: MELACandidate.cc:181
PDGHelpers::isDownTypeQuark
bool isDownTypeQuark(const int id)
Definition: PDGHelpers.cc:45
MELACandidate::associatedJets
std::vector< MELAParticle * > associatedJets
Definition: MELACandidate.h:98
MELACandidate::sortedDaughters
std::vector< MELAParticle * > sortedDaughters
Definition: MELACandidate.h:101
MELACandidate::associatedPhotons
std::vector< MELAParticle * > associatedPhotons
Definition: MELACandidate.h:97
MELACandidate::getAssociatedSortedVs
std::vector< MELAParticle * > getAssociatedSortedVs()
Definition: MELACandidate.cc:193
MELAParticle::p4
TLorentzVector p4
Definition: MELAParticle.h:18
MELAParticle::daughters
std::vector< MELAParticle * > daughters
Definition: MELAParticle.h:25
MELAParticle::z
double z() const
Definition: MELAParticle.h:69
testME_all.int
int
Definition: testME_all.py:13
MELACandidate::addSortedV
void addSortedV(MELAParticle *myParticle)
Definition: MELACandidate.h:70
MELACandidate::getAlternativeVMomentum
TLorentzVector getAlternativeVMomentum(int index) const
Definition: MELACandidate.cc:547
PDGHelpers::isAWBoson
bool isAWBoson(const int id)
Definition: PDGHelpers.cc:80
MELAParticle::genStatus
int genStatus
Definition: MELAParticle.h:20
MELAParticle::charge
double charge() const
Definition: MELAParticle.cc:90
MELACandidate::getSortedDaughter
MELAParticle * getSortedDaughter(int index) const
Definition: MELACandidate.cc:148
MELACandidate::getAssociatedLepton
MELAParticle * getAssociatedLepton(int index) const
Definition: MELACandidate.cc:156
MELACandidate::MELACandidate
MELACandidate()
Definition: MELACandidate.cc:12
MELAParticle::setLifetime
void setLifetime(double life_)
Definition: MELAParticle.h:44
MELACandidate::getAssociatedNeutrinos
std::vector< MELAParticle * > & getAssociatedNeutrinos()
Definition: MELACandidate.cc:180
MELACandidate::getAssociatedLeptons
std::vector< MELAParticle * > & getAssociatedLeptons()
Definition: MELACandidate.cc:179
MELACandidate::setDecayMode
void setDecayMode(TVar::CandidateDecayMode flag)
Definition: MELACandidate.cc:112
MELACandidate::checkDaughtership
bool checkDaughtership(MELAParticle const *myParticle) const
Definition: MELACandidate.cc:602
MELACandidate::addUnordered
static void addUnordered(MELAParticle *myParticle, std::vector< MELAParticle * > &particleArray)
Definition: MELACandidate.cc:719
MELAParticle
Definition: MELAParticle.h:13
MELAParticle::lifetime
double lifetime
Definition: MELAParticle.h:21
MELAParticle::getDaughterParticles
virtual void getDaughterParticles(std::vector< MELAParticle * > &particles) const
Definition: MELAParticle.cc:82
TUtilHelpers::copyVector
void copyVector(std::vector< T > const &input, std::vector< T > &target)
Definition: TUtilHelpers.hh:24
MELACandidate::getDaughterParticles
void getDaughterParticles(std::vector< MELAParticle * > &particles) const
Definition: MELACandidate.cc:708
TVar::CandidateDecay_ZW
@ CandidateDecay_ZW
Definition: TVar.hh:42
MELACandidate::sortedVs
std::vector< MELAParticle * > sortedVs
Definition: MELACandidate.h:102
TVar::CandidateDecay_ZG
@ CandidateDecay_ZG
Definition: TVar.hh:43
MELACandidate::addAssociatedTop
void addAssociatedTop(MELATopCandidate_t *myParticle)
Definition: MELACandidate.cc:619
MELAThreeBodyDecayCandidate::getWFermion
MELAParticle * getWFermion()
Definition: MELAThreeBodyDecayCandidate.h:22
modttbhiggs::ds
integer, parameter ds
Definition: mod_TTBHiggs.F90:59
MELACandidate::addAssociatedLepton
void addAssociatedLepton(MELAParticle *myParticle)
Definition: MELACandidate.cc:606
MELACandidate::testShallowCopy
bool testShallowCopy()
Definition: MELACandidate.cc:115
MELAParticle::mothers
std::vector< MELAParticle * > mothers
Definition: MELAParticle.h:24
MELACandidate::getAssociatedJet
MELAParticle * getAssociatedJet(int index) const
Definition: MELACandidate.cc:168
MELACandidate::getAssociatedTops
std::vector< MELATopCandidate_t * > & getAssociatedTops()
Definition: MELACandidate.cc:183
MELAParticle::addMother
void addMother(MELAParticle *myParticle)
Definition: MELAParticle.cc:62
PDGHelpers::Zmass
const double Zmass
Definition: PDGHelpers.h:14
MELAStreamHelpers::MELAerr
MELAOutputStreamer MELAerr
MELACandidate::addByHighestPt
static void addByHighestPt(MELAParticle *myParticle, std::vector< MELAParticle * > &particleArray)
Definition: MELACandidate.cc:727
MELACandidate::addAssociatedParticleToArray
void addAssociatedParticleToArray(MELAParticle *myParticle, std::vector< MELAParticle * > &particleArray)
Definition: MELACandidate.cc:622
MELAParticle::passSelection
bool passSelection
Definition: MELAParticle.h:19
MELACandidate::associatedLeptons
std::vector< MELAParticle * > associatedLeptons
Definition: MELACandidate.h:95
PDGHelpers::Wmass
const double Wmass
Definition: PDGHelpers.h:13
MELACandidate.h
TUtilHelpers.hh
TVar::CandidateDecay_WG
@ CandidateDecay_WG
Definition: TVar.hh:44
MELACandidate::sortDaughtersByBestZ1
void sortDaughtersByBestZ1()
Definition: MELACandidate.cc:324
MELACandidate::getAssociatedJets
std::vector< MELAParticle * > & getAssociatedJets()
Definition: MELACandidate.cc:182
PDGHelpers::isAGluon
bool isAGluon(const int id)
Definition: PDGHelpers.cc:58
MELACandidate::getSortedDaughters
std::vector< MELAParticle * > & getSortedDaughters()
Definition: MELACandidate.cc:177
MELACandidate::sortDaughters
void sortDaughters()
Definition: MELACandidate.cc:117
MELACandidate
Definition: MELACandidate.h:7
MELAStreamHelpers.hh
MELACandidate::createSortedVs
void createSortedVs()
Definition: MELACandidate.cc:487
MELAThreeBodyDecayCandidate
Definition: MELAThreeBodyDecayCandidate.h:7
MELACandidate::testPreSelectedDaughters
void testPreSelectedDaughters()
Definition: MELACandidate.cc:690
MELAParticle::getRelatedParticles
virtual void getRelatedParticles(std::vector< MELAParticle * > &particles) const
Definition: MELAParticle.cc:77
TVar::CandidateDecay_ff
@ CandidateDecay_ff
Definition: TVar.hh:39
PDGHelpers::Zeromass
const double Zeromass
Definition: PDGHelpers.h:17
MELAParticle::id
int id
Definition: MELAParticle.h:17
MELAParticle::setSelected
void setSelected(bool isSelected=true)
Definition: MELAParticle.h:42
MELACandidate::getAssociatedParticleIds
std::vector< int > getAssociatedParticleIds() const
Definition: MELACandidate.cc:135
PDGHelpers::isUpTypeQuark
bool isUpTypeQuark(const int id)
Definition: PDGHelpers.cc:40
PDGHelpers::isAJet
bool isAJet(const int id)
Definition: PDGHelpers.cc:18
MELACandidate::setShallowCopy
void setShallowCopy(bool flag)
Definition: MELACandidate.cc:114
MELACandidate::sortDaughtersInitial
void sortDaughtersInitial()
Definition: MELACandidate.cc:218
TVar::CandidateDecay_GG
@ CandidateDecay_GG
Definition: TVar.hh:45