1 |
#include <vector>
|
2 |
#include "MathUtils.h"
|
3 |
#include "FSR.h"
|
4 |
#include "IsolationSelection.h"
|
5 |
#include "CommonDefs.h"
|
6 |
#include "TLorentzVector.h"
|
7 |
#include "Various.h"
|
8 |
|
9 |
extern vector<bool> PFnoPUflag;
|
10 |
|
11 |
//----------------------------------------------------------------------------------------
|
12 |
void addPhotonToEventData(EventData &ret, TLorentzVector &pvec)
|
13 |
//
|
14 |
// add a photon to the list of fsr photons in the EventData
|
15 |
//
|
16 |
{
|
17 |
assert(ret.fsrPhotons.size() < 3);
|
18 |
SimpleLepton photon;
|
19 |
photon.vec.SetPtEtaPhiM( pvec.Pt(), pvec.Eta(), pvec.Phi(), 0);
|
20 |
|
21 |
// don't add the same photon twice...
|
22 |
if(ret.fsrPhotons.size() > 0)
|
23 |
if(dr(ret.fsrPhotons[0], photon) < 0.01) return;
|
24 |
if(ret.fsrPhotons.size() > 1)
|
25 |
if(dr(ret.fsrPhotons[1], photon) < 0.01) return;
|
26 |
|
27 |
if(ret.fsrPhotons.size() == 2) {
|
28 |
// only want to save two, so if there's already two in the vector, store the highest two out of the three photons
|
29 |
sort( ret.fsrPhotons.begin(), ret.fsrPhotons.end(), SimpleLepton::lep_pt_sort );
|
30 |
assert(ret.fsrPhotons[0].vec.Pt() > ret.fsrPhotons[1].vec.Pt());
|
31 |
if(ret.fsrPhotons[1].vec.Pt() < photon.vec.Pt()) {
|
32 |
ret.fsrPhotons.erase(ret.fsrPhotons.begin() + 1);
|
33 |
ret.fsrPhotons.push_back(photon);
|
34 |
}
|
35 |
} else
|
36 |
ret.fsrPhotons.push_back(photon);
|
37 |
sort( ret.fsrPhotons.begin(), ret.fsrPhotons.end(), SimpleLepton::lep_pt_sort );
|
38 |
}
|
39 |
//--------------------------------------------------------------------------------------------------
|
40 |
// typeI = PF IDed photons.
|
41 |
//----------------------------------------------------------------------------------------
|
42 |
pair<TLorentzVector,int> findFsrPhoton( ControlFlags & ctrl,
|
43 |
EventData &ret,
|
44 |
const ChargedParticle *lep, // the non-constant copy of lepvec[i] (or [j])
|
45 |
const int lepIndex,
|
46 |
vector<SimpleLepton> &lepvec, // really lepvec_i (or _j)
|
47 |
const Array<PFCandidate> * pfArr,
|
48 |
const Array<Electron> *eleArr,
|
49 |
TLorentzVector * Zvec)
|
50 |
//--------------------------------------------------------------------------------------------------
|
51 |
{
|
52 |
if( lepvec[lepIndex].fsrRecoveryAttempted ) return pair<TLorentzVector,int>(TLorentzVector(0,0,0,0), -1);
|
53 |
|
54 |
vector<PFCandidate> photons;
|
55 |
vector<int> photonIndices; // index in the PFCandidate Array (wrong pT for muons FSRs)
|
56 |
for( int i=0; i<pfArr->GetEntries(); i++ ) {
|
57 |
if( !(PFnoPUflag[i])) continue;
|
58 |
const PFCandidate *pfOrig = (PFCandidate*)((*pfArr)[i]);
|
59 |
PFCandidate pf(*pfOrig);
|
60 |
|
61 |
bool isMuonFsr(false);
|
62 |
if(abs(pf.PFType())==PFCandidate::eMuon && pf.EECal()>0) {
|
63 |
TLorentzVector pfvec;
|
64 |
pfvec.SetPtEtaPhiM(pf.EECal()*pf.Pt()/pf.P(), pf.Eta(), pf.Phi(), 0);
|
65 |
pf.SetMom(pfvec.Px(), pfvec.Py(), pfvec.Pz(), pfvec.E());
|
66 |
pf.SetPFType(PFCandidate::eGamma);
|
67 |
isMuonFsr = true;
|
68 |
}
|
69 |
|
70 |
if(abs(pf.PFType()) != PFCandidate::eGamma) continue;
|
71 |
if(pf.Pt() <= 2 ) continue;
|
72 |
if(fabs(pf.Eta()) >= 2.4 ) continue;
|
73 |
|
74 |
float dR = MathUtils::DeltaR(pf.Phi(),pf.Eta(), lepvec[lepIndex].vec.Phi(), lepvec[lepIndex].vec.Eta());
|
75 |
|
76 |
if( ctrl.debug ) {
|
77 |
cout << " --> pass pre, " << setprecision(5) << pf.Pt() << " " << dR;
|
78 |
if(isMuonFsr) cout << " (muon fsr)";
|
79 |
cout << endl;
|
80 |
}
|
81 |
|
82 |
// veto if close to an electron SC
|
83 |
bool flagEleSC = false;
|
84 |
for( int j=0; j<lepvec.size(); j++ ) {
|
85 |
if( !(abs(lepvec[j].type) == 11 ) ) continue;
|
86 |
if( !(lepvec[j].status.looseIDAndPre()) ) continue;
|
87 |
double eeta=lepvec[j].vec.Eta(); double ephi=lepvec[j].vec.Phi();
|
88 |
float dPhi = fabs(MathUtils::DeltaPhi(pf.Phi(),ephi));
|
89 |
float dEta = fabs(pf.Eta()-eeta);
|
90 |
float sc_dR = MathUtils::DeltaR(pf.Phi(),pf.Eta(), ephi, eeta);
|
91 |
if(ctrl.debug) cout << " sc_dR:" << sc_dR << endl;
|
92 |
if( (dPhi<2.&& dEta<0.05) || sc_dR<0.15 ) {
|
93 |
flagEleSC = true;
|
94 |
break;
|
95 |
}
|
96 |
if( flagEleSC ) break;
|
97 |
}
|
98 |
if( flagEleSC ) continue;
|
99 |
if( ctrl.debug ) cout << " no match SC" << endl;
|
100 |
|
101 |
// check that input lepton is the closest lepton to this photon
|
102 |
bool found_closer_lepton=false;
|
103 |
for( int j=0; j<lepvec.size(); j++ ) {
|
104 |
if( j == lepIndex ) continue;
|
105 |
if( !(lepvec[j].status.looseIDAndPre()) ) continue;
|
106 |
float tmp_dR = MathUtils::DeltaR(pf.Phi(),pf.Eta(),
|
107 |
lepvec[j].vec.Phi(), lepvec[j].vec.Eta());
|
108 |
if( tmp_dR < dR ) {
|
109 |
if(ctrl.debug) cout << " found closer lepton (j=" << j << " : " << tmp_dR << " vs " << dR << ") skipping..." << endl;
|
110 |
found_closer_lepton=true;
|
111 |
break;
|
112 |
}
|
113 |
}
|
114 |
if( found_closer_lepton ) continue;
|
115 |
|
116 |
// Z mass OK?
|
117 |
TLorentzVector pvec;
|
118 |
pvec.SetPtEtaPhiM( pf.Pt(), pf.Eta(), pf.Phi(), 0.);
|
119 |
float newMass = (pvec + *Zvec).M();
|
120 |
if( !( newMass > 4. &&
|
121 |
newMass < 100. &&
|
122 |
(fabs(newMass-Z_MASS) < fabs(Zvec->M()-Z_MASS))
|
123 |
) ) continue;
|
124 |
if( ctrl.debug ) cout << " better mass " << Zvec->M() << " -> " << newMass << endl;
|
125 |
|
126 |
// "keep all photons close to one of the 4L leptons ..."
|
127 |
bool use(false);
|
128 |
if(dR < 0.07) {
|
129 |
if( ctrl.debug ) cout << " push loose " << i << endl;
|
130 |
use = true;
|
131 |
} else if(dR<0.5 && pf.Pt()>4 && isoDr03ForFsr(ctrl, &pf, lep, pfArr, false) < 1) { // "need tighter cuts for other photons ..."
|
132 |
if( ctrl.debug ) cout << " push tight " << i << endl;
|
133 |
use = true;
|
134 |
}
|
135 |
if(use) {
|
136 |
photons.push_back(pf);
|
137 |
photonIndices.push_back(i); // note: will *not* have the right kinematics for muon fsr candidates
|
138 |
}
|
139 |
}
|
140 |
|
141 |
// choose the best one
|
142 |
float highest_pt(-1),smallest_dR(9999999);
|
143 |
int highest_pt_index(-1),smallest_dR_index(-1);
|
144 |
PFCandidate *hiPtPf(NULL),*smallDrPf(NULL);
|
145 |
for( int i=0; i<photons.size(); i++ ) {
|
146 |
const PFCandidate pfPhoton = photons[i];
|
147 |
if(pfPhoton.Pt() > highest_pt) {
|
148 |
highest_pt_index = photonIndices[i]; // index in the PFCandidate Array (wrong pT for muons FSRs)
|
149 |
highest_pt = pfPhoton.Pt();
|
150 |
hiPtPf = &photons[i];
|
151 |
}
|
152 |
float this_dR = MathUtils::DeltaR(pfPhoton.Phi(), pfPhoton.Eta(), lep->Phi(), lep->Eta());
|
153 |
if(this_dR < smallest_dR) {
|
154 |
smallest_dR_index = photonIndices[i]; // index in the PFCandidate Array (wrong pT for muons FSRs)
|
155 |
smallest_dR = this_dR;
|
156 |
smallDrPf = &photons[i];
|
157 |
}
|
158 |
}
|
159 |
|
160 |
const PFCandidate *pfBest(NULL);
|
161 |
int iPfOrig(-1); // index of the final photon in the original PFCandidate array
|
162 |
if(highest_pt > 4) {
|
163 |
if(ctrl.debug) cout << " using hi pt " << highest_pt_index << endl;
|
164 |
pfBest = hiPtPf;
|
165 |
iPfOrig = highest_pt_index;
|
166 |
} else if(smallest_dR < 99999) {
|
167 |
if(ctrl.debug) cout << " using small dR " << smallest_dR_index << endl;
|
168 |
pfBest = smallDrPf;
|
169 |
iPfOrig = smallest_dR_index;
|
170 |
} else {
|
171 |
return pair<TLorentzVector,int>(TLorentzVector(0,0,0,0), -1);
|
172 |
}
|
173 |
|
174 |
// add to the lepton
|
175 |
assert(pfBest);
|
176 |
TLorentzVector phvec;
|
177 |
phvec.SetPtEtaPhiM( pfBest->Pt(), pfBest->Eta(), pfBest->Phi(), 0);
|
178 |
return pair<TLorentzVector,int>(phvec, iPfOrig);
|
179 |
}
|