1 |
nmohr |
1.1 |
#ifndef TOPMASSRECO_H
|
2 |
|
|
#define TOPMASSRECO_H
|
3 |
|
|
|
4 |
|
|
#include <cmath>
|
5 |
|
|
#include <vector>
|
6 |
|
|
|
7 |
|
|
#include "VHbbAnalysis/VHbbDataFormats/interface/VHbbCandidate.h"
|
8 |
|
|
|
9 |
|
|
struct topHypo {
|
10 |
|
|
TLorentzVector p4;
|
11 |
|
|
TLorentzVector p4W;
|
12 |
|
|
} topQuark;
|
13 |
|
|
|
14 |
|
|
struct topMassReco {
|
15 |
|
|
|
16 |
|
|
topHypo operator()(const VHbbCandidate vhCand) const {
|
17 |
|
|
//Look for additional jet that is most b-tagged
|
18 |
|
|
topQuark.p4 = TLorentzVector(0,0,0,0);
|
19 |
|
|
topQuark.p4W = TLorentzVector(0,0,0,0);
|
20 |
|
|
int topJet=-99;
|
21 |
|
|
double minBtag=-9999.;
|
22 |
|
|
for(unsigned int j=0; j < vhCand.additionalJets.size(); j++ ){
|
23 |
|
|
if (vhCand.additionalJets[j].csv > minBtag) topJet = j;
|
24 |
|
|
}
|
25 |
|
|
if(topJet < 0) return topQuark; //If no additional jet, do no computation
|
26 |
|
|
const TLorentzVector bJet = vhCand.additionalJets[topJet].p4;
|
27 |
|
|
const TLorentzVector met = vhCand.V.mets.at(0).p4;
|
28 |
|
|
// just support semiletonic top
|
29 |
|
|
if( vhCand.candidateType == VHbbCandidate::Zee || vhCand.candidateType == VHbbCandidate::Zmumu || vhCand.candidateType == VHbbCandidate::Znn ) return topQuark;
|
30 |
|
|
else if( vhCand.candidateType == VHbbCandidate::Wmun ){
|
31 |
|
|
const double leptonMass = 0.105;
|
32 |
|
|
const TLorentzVector lepton = vhCand.V.muons[0].p4;
|
33 |
|
|
return calcMass(lepton,bJet,met,leptonMass);
|
34 |
|
|
}
|
35 |
|
|
else if( vhCand.candidateType == VHbbCandidate::Wen ){
|
36 |
|
|
const double leptonMass = 0.005;
|
37 |
|
|
const TLorentzVector lepton = vhCand.V.electrons[0].p4;
|
38 |
|
|
return calcMass(lepton,bJet,met,leptonMass);
|
39 |
|
|
}
|
40 |
|
|
else return topQuark;
|
41 |
|
|
}
|
42 |
|
|
|
43 |
|
|
static topHypo calcMass(const TLorentzVector lepton, const TLorentzVector bJet,const TLorentzVector met, const double leptonMass){
|
44 |
|
|
const double mW = 80.4;
|
45 |
|
|
double pzNu=0;
|
46 |
|
|
|
47 |
|
|
//Did not recalculate any formulas, but seems to check the neutrino solutions to get met z component
|
48 |
|
|
const double a = mW*mW - leptonMass*leptonMass + 2.0*lepton.Px()*met.Px()+2.0*lepton.Py()*met.Py();
|
49 |
|
|
const double A = 4.0*(lepton.E()*lepton.E() - lepton.Pz()*lepton.Pz());
|
50 |
|
|
const double B = -4.0*a*lepton.Pz();
|
51 |
|
|
const double C = 4.0*lepton.E()*lepton.E()*(met.Px()*met.Px()+met.Py()*met.Py()) - a*a;
|
52 |
|
|
const double tmpRoot = B*B - 4.0*A*C;
|
53 |
|
|
if (tmpRoot<0) pzNu = - B/(2*A);
|
54 |
|
|
else{
|
55 |
|
|
const double tmpSol1 = (-B + TMath::Sqrt(tmpRoot))/(2.0*A);
|
56 |
|
|
const double tmpSol2 = (-B - TMath::Sqrt(tmpRoot))/(2.0*A);
|
57 |
|
|
if (fabs(tmpSol2-lepton.Pz()) < fabs(tmpSol1-lepton.Pz())){
|
58 |
|
|
pzNu = tmpSol2;
|
59 |
|
|
}
|
60 |
|
|
else pzNu = tmpSol1;
|
61 |
|
|
}
|
62 |
|
|
const double nuE = TMath::Sqrt(met.Px()*met.Px()+met.Py()*met.Py()+pzNu*pzNu);
|
63 |
|
|
|
64 |
|
|
//new met vector
|
65 |
|
|
TLorentzVector metHyp = TLorentzVector(met.Px(),met.Py(),pzNu,nuE);
|
66 |
|
|
|
67 |
|
|
//W = lepton+met
|
68 |
|
|
topQuark.p4W = (lepton+metHyp);
|
69 |
|
|
//Top = lepton+jet+met
|
70 |
|
|
topQuark.p4 = (lepton+bJet+metHyp);
|
71 |
|
|
|
72 |
|
|
return topQuark;
|
73 |
|
|
}
|
74 |
|
|
|
75 |
|
|
};
|
76 |
|
|
|
77 |
|
|
#endif
|