ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/MitHzz4l/Selection/src/ReferenceSelection.cc
Revision: 1.23
Committed: Mon Dec 17 17:12:07 2012 UTC (12 years, 5 months ago) by dkralph
Content type: text/plain
Branch: MAIN
CVS Tags: compiled
Changes since 1.22: +169 -216 lines
Log Message:
many updates

File Contents

# Content
1 #include "ReferenceSelection.h"
2
3 extern vector<SimpleLepton> failingLeptons;
4 extern vector<SimpleLepton> passingLeptons;
5
6 extern map<unsigned,float> evtrhoMap;
7 extern bool passes_HLT;
8 extern map<TString, map<TString,int>* > counts;
9 extern ElectronMomentumCorrection electron_momentum_correction;
10 extern MuCorr *muCorr;
11 extern TrigInfo ti;
12
13 //----------------------------------------------------------------------------------------
14 void updateSimpleLepton(SimpleLepton &tmplep);
15 //--------------------------------------------------------------------------------------------------
16 EventData apply_HZZ4L_reference_selection(ControlFlags &ctrl, // input control
17 const EventHeader *info, // input event info
18 const Array<Vertex> * vtxArr ,
19 const Array<PFCandidate> *pfCandidates,
20 const Array<PileupEnergyDensity> *puEnergyDensity,
21 const Array<Electron> *electronArr, // input electrons
22 SelectionStatus (*ElectronPreSelector)( ControlFlags &,
23 const Electron*,
24 const Vertex *),
25 SelectionStatus (*ElectronIDSelector)( ControlFlags &,
26 const Electron*,
27 const Vertex *),
28 SelectionStatus (*ElectronIsoSelector)( ControlFlags &,
29 const Electron*,
30 const Vertex *,
31 const Array<PFCandidate> *,
32 const Array<PileupEnergyDensity> *,
33 ElectronTools::EElectronEffectiveAreaTarget,
34 vector<const PFCandidate*>),
35 const Array<Muon> *muonArr, // input muons
36 SelectionStatus (*MuonPreSelector)( ControlFlags &,
37 const Muon*,
38 const Vertex *,
39 const Array<PFCandidate> *),
40 SelectionStatus (*MuonIDSelector)( ControlFlags &,
41 const Muon*,
42 // const Vertex &),
43 const Vertex *,
44 const Array<PFCandidate> *),
45 SelectionStatus (*MuonIsoSelector)( ControlFlags &,
46 const Muon*,
47 const Vertex *,
48 const Array<PFCandidate> *,
49 const Array<PileupEnergyDensity> *,
50 MuonTools::EMuonEffectiveAreaTarget,
51 vector<const PFCandidate*>)
52 )
53 //--------------------------------------------------------------------------------------------------
54 {
55 EventData ret;
56 failingLeptons.clear();
57 passingLeptons.clear();
58
59 MuonTools::EMuonEffectiveAreaTarget eraMu;
60 ElectronTools::EElectronEffectiveAreaTarget eraEle;
61 getEATargets(ctrl,eraMu,eraEle);
62
63 if( ctrl.debug ) {
64 cout << "presel nlep: " << muonArr->GetEntries() + electronArr->GetEntries()
65 << "\tnmuon: " << muonArr->GetEntries()
66 << "\tnelectron: " << electronArr->GetEntries()
67 << endl;
68 }
69
70 // correct muon momentum
71 if(ctrl.correct_muon_momentum) {
72 assert(muCorr->corr2011 && muCorr->corr2012);
73 if(ctrl.debug) cout << "mu corr: " << endl;
74 for(int i=0; i<muonArr->GetEntries(); i++) {
75 const Muon *const_mu = (Muon*)((*muonArr)[i]);
76 Muon *mu = const_cast<Muon*>(const_mu);
77 float ptBefore = mu->Pt();
78 correct_muon_momentum(ctrl,muCorr,mu,info->RunNum());
79 if(ctrl.debug) cout << " " << setw(12) << ptBefore << " --> " << setw(12) << mu->Pt() << " (" << fabs(ptBefore-mu->Pt())/ptBefore << ")" << endl;
80 }
81 }
82
83 const Vertex * vtx;
84 bool goodVertex = setPV( ctrl, vtxArr, vtx );
85 if(!goodVertex) {
86 if(ctrl.debug) cout << "found bad vertex" << endl;
87 ret.status.setStatus(SelectionStatus::FAIL);
88 return ret;
89 }
90 if(ctrl.debug)
91 cout << "vtx :: ntrks: " << vtx->NTracksFit() << endl;
92
93 //***********************************************************
94 // Trigger Selection
95 //***********************************************************
96 if( passes_HLT ) {
97 increment(counts,"trigger");
98 } else {
99 if(ctrl.debug) cout << "fails trigger" << endl;
100 ret.status.setStatus(SelectionStatus::FAIL);
101 return ret;
102 }
103
104 //***********************************************************
105 // Lepton Selection
106 //***********************************************************
107 vector<SimpleLepton> lepvec;
108 vector<const PFCandidate*> photonsToVeto;
109
110 if( ctrl.debug ) cout << "\tnMuons: " << muonArr->GetEntries() << endl;
111 for(int i=0; i<muonArr->GetEntries(); i++)
112 {
113 const Muon *mu = (Muon*)((*muonArr)[i]);
114
115 SelectionStatus musel;
116 musel |= (*MuonPreSelector)(ctrl,mu,vtx,pfCandidates);
117
118 if(ctrl.fakeScheme == "none") { // regular selection
119 if( !musel.passPre() ) continue;
120 } else { // fake denominator selection
121 SelectionStatus denomSel;
122 denomSel |= muonReferencePreSelection(ctrl,mu,vtx,pfCandidates);
123 if(ctrl.muSele != "none") { // don't apply *any* preselection, to get a super hi stat fake sample for BDT training
124 if( !denomSel.passPre() ) continue;
125 }
126 }
127
128 if(ctrl.debug) cout << "muon:: pt: " << mu->Pt() << "\teta: " << mu->Eta() << endl;
129
130 musel |= (*MuonIDSelector)(ctrl,mu,vtx,pfCandidates );
131
132 // NOTE: if we do FSR this is *changed* later on
133 musel |= (*MuonIsoSelector)(ctrl,mu,vtx,pfCandidates,puEnergyDensity,eraMu,photonsToVeto);
134 if(ctrl.debug) cout << "mu status after iso (before fsr) " << musel.getStatus() << endl;
135
136 SimpleLepton tmplep;
137 tmplep.vec.SetPtEtaPhiM(mu->Pt(), mu->Eta(), mu->Phi(), MUON_MASS);
138 tmplep.type = 13;
139 tmplep.index = i;
140 tmplep.charge = mu->Charge();
141 tmplep.ip3dSig = mu->Ip3dPVSignificance();
142 tmplep.is4l = false;
143 tmplep.isEB = (fabs(mu->Eta()) < 1.479 ? 1 : 0 );
144 tmplep.isLoose = musel.loose();
145 tmplep.isTight = mu->IsPFMuon() || mu->IsGlobalMuon();
146 tmplep.status = musel;
147 tmplep.fsrRecoveryAttempted = false; // NOTE: this is *used* inside FSR.cc
148 lepvec.push_back(tmplep);
149 if( ctrl.debug ) cout << endl;
150 }
151
152 if( ctrl.debug ) { cout << "\tnElectron: " << electronArr->GetEntries() << endl; }
153 for(int i=0; i<electronArr->GetEntries(); i++)
154 {
155 const Electron *const_ele = (Electron*)((*electronArr)[i]);
156 Electron *ele = const_cast<Electron*>(const_ele);
157
158 if(ctrl.debug) cout << setprecision(8) << "el:: scEt " << setw(12) << ele->SCluster()->Et() << " P: "
159 << setw(12) << ele->P() << " pT: " << setw(12) << ele->Pt() << " scEta " << setw(12) << ele->SCluster()->Eta() << setprecision(5) << endl;
160
161 // evaluate MVA *before* regression correction (but cut on mvaVal *after*)
162 double mvaVal = getElectronIDMVAval(ctrl, ele, vtx);
163
164 electron_momentum_correction.correct_electron_momentum(ctrl, ele, info, puEnergyDensity->At(0)->RhoKt6PFJets(), vtxArr->GetEntries());
165
166 if(ctrl.debug) cout << setprecision(8) << " corr el: scEt " << setw(12) << ele->SCluster()->Et() << " P: "
167 << setw(12) << ele->P() << " pT: " << setw(12) << ele->Pt() << " scEta " << setw(12) << ele->SCluster()->Eta() << setprecision(5) << endl;
168
169 SelectionStatus elesel;
170 elesel |= (*ElectronPreSelector)(ctrl,ele,vtx);
171
172 if(ctrl.fakeScheme == "none") { // regular selection
173 if( !elesel.passPre() ) continue;
174 } else { // fake denominator selection
175 SelectionStatus denomSel;
176 denomSel |= electronReferencePreSelection(ctrl,ele,vtx);
177 if(ctrl.eleSele != "none") { // don't apply *any* preselection, to get a super hi stat fake sample for BDT training
178 if( !denomSel.passPre() ) continue;
179 }
180 }
181
182
183 elesel |= passElectronIDMVA(ctrl, mvaVal, ele);
184
185 // NOTE: if we do FSR this is *changed* later on
186 elesel |= (*ElectronIsoSelector)(ctrl,ele,vtx,pfCandidates,puEnergyDensity,eraEle,photonsToVeto);
187 if( ctrl.debug ) cout << "el status after iso (no fsr) " << hex << elesel.getStatus() << dec << endl;
188
189 SimpleLepton tmplep;
190 tmplep.vec.SetPtEtaPhiM( ele->Pt(), ele->Eta(), ele->Phi(), ELECTRON_MASS );
191 tmplep.type = 11;
192 tmplep.index = i;
193 tmplep.charge = ele->Charge();
194 tmplep.ip3dSig = ele->Ip3dPVSignificance();
195 tmplep.is4l = false;
196 tmplep.isEB = ele->IsEB();
197 tmplep.scID = ele->SCluster()->GetUniqueID();
198 tmplep.isTight = elesel.tight();
199 tmplep.isLoose = elesel.loose();
200 tmplep.status = elesel;
201 tmplep.fsrRecoveryAttempted = false; // NOTE: this is *used* inside FSR.cc
202 lepvec.push_back(tmplep);
203 if( ctrl.debug ) cout << endl;
204 }
205
206 //********************************************************
207 // Dump Stuff
208 //********************************************************
209 sort( lepvec.begin(), lepvec.end(), SimpleLepton::lep_pt_sort );
210 int nmu=0, nele=0;
211 for( int i=0; i<lepvec.size(); i++ ) {
212 if(ctrl.debug) {
213 bitset<16> tmpbits(lepvec[i].status.getStatus());
214 cout << "lepvec :: evt: " << setw(8) << info->EvtNum() << " index: " << setw(3) << i << " type: " << setw(4) << lepvec[i].type
215 << " pt: " << setw(11) << lepvec[i].vec.Pt() << " eta: " << setw(11) << lepvec[i].vec.Eta() << " status: " << tmpbits;
216 if(!ctrl.doFSR)
217 cout << "\tpf: " << lepvec[i].status.isoPF04 << "\tch: " << lepvec[i].status.chisoPF04 << "\tga: " << lepvec[i].status.gaisoPF04
218 << "\tne: " << lepvec[i].status.neisoPF04 << endl;
219 if( abs(lepvec[i].type) == 11 ) {
220 const Electron *tmpele = (Electron*)((*electronArr)[lepvec[i].index]);
221 cout << "\tSCeta: " << tmpele->SCluster()->Eta()
222 << "\tidMVA: " << lepvec[i].status.idMVA;
223 }
224 cout << endl;
225 }
226 if( abs(lepvec[i].type) == 11 ) nele++;
227 else nmu++;
228 }
229 if( ctrl.debug ) {
230 cout << "postsel nlep: " << lepvec.size()
231 << "\tnmuon: " << nmu
232 << "\tnelectron: " << nele
233 << endl;
234 }
235
236 //********************************************************
237 // Step 2: Lepton Cross-Cleaning: remove electrons that are next to 'good'ish muons
238 //********************************************************
239 vector<vector<SimpleLepton>::iterator> electrons_to_erase;
240 for (vector<SimpleLepton>::iterator it1=lepvec.begin();
241 it1 != lepvec.end(); it1++ ) {
242 if ( abs(it1->type) != 11 ) continue;
243 TVector3 evec = it1->vec.Vect();
244
245 bool erase_this_electron=false;
246 for (vector<SimpleLepton>::iterator it2=lepvec.begin();
247 it2 != lepvec.end(); it2++ ) {
248 if ( it2 == it1 ) continue;
249 if ( abs(it2->type) != 13 ) continue;
250 if( !it2->status.passPre() ) continue;
251 if( !it2->isTight ) continue; // NOTE: isTight is set to it2->isPFMuon || it2->isGlobalMuon
252
253 TVector3 mvec = it2->vec.Vect();
254 if ( evec.DrEtaPhi(mvec) < 0.05 ) {
255 erase_this_electron=true;
256 break;
257 }
258 }
259 if( erase_this_electron ) {
260 if( ctrl.debug ) cout << "erasing electron with pt " << it1->vec.Pt() << endl;
261 electrons_to_erase.push_back(it1);
262 }
263 }
264 for( int i=0; i<electrons_to_erase.size(); i++ ) {
265 lepvec.erase(electrons_to_erase[i]);
266 }
267
268 // fill passing and failing leptons for fakes
269 // (NOTE: isolation hasn't been corrected post-fsr, so this isn't strictly correct)
270 // also note: sip cut not applied
271 for (int i=0; i<lepvec.size(); i++ ) {
272 if( lepvec[i].isLoose )
273 passingLeptons.push_back(lepvec[i]);
274 else
275 failingLeptons.push_back(lepvec[i]);
276 }
277
278 //********************************************************
279 // Step 3: Good Leptons (remove non-id-and-pre'd leptons, and apply |ip3ds| < 4)
280 //********************************************************
281 vector<double> pt_of_leptons_to_erase;
282 for (int i=0; i<lepvec.size(); i++ ) {
283 bool already_pushed=false;
284 if( !(lepvec[i].status.looseIDAndPre()) ) {
285 pt_of_leptons_to_erase.push_back(lepvec[i].vec.Pt());
286 already_pushed = true;
287 if(ctrl.debug)
288 cout << "pushing failed lepton type: " << lepvec[i].type
289 << "\tpt: " << lepvec[i].vec.Pt()
290 << "\teta: " << lepvec[i].vec.Eta()
291 << endl;
292 // failingLeptons.push_back(lepvec[i]); // these should pass preselection
293 } else {
294 // passingLeptons.push_back(lepvec[i]);
295 }
296 if( !already_pushed && fabs(lepvec[i].ip3dSig)>4 )
297 pt_of_leptons_to_erase.push_back(lepvec[i].vec.Pt());
298 }
299 for( int i=0; i<pt_of_leptons_to_erase.size(); i++ ) {
300 for( vector<SimpleLepton>::iterator it=lepvec.begin();
301 it != lepvec.end(); it++ ) {
302 SimpleLepton flep = *it;
303 if( flep.vec.Pt() != pt_of_leptons_to_erase[i] ) continue;
304 if(ctrl.debug) cout << "erasing lepton : "
305 << flep.vec.Pt() << "\t"
306 << flep.type << "\t"
307 << endl;
308 lepvec.erase(it);
309 break;
310 }
311 }
312 if( ctrl.debug ) cout << "good leptons : " << lepvec.size() << endl;
313
314 //********************************************************
315 // Ghost Removal
316 //********************************************************
317 vector<vector<SimpleLepton>::iterator> leptons_to_erase;
318 for (vector<SimpleLepton>::iterator it1=lepvec.begin(); it1 != lepvec.end(); it1++ ) {
319 TVector3 lep1 = it1->vec.Vect();
320
321 bool erase_this_lepton=false;
322 for (vector<SimpleLepton>::iterator it2=it1+1; it2 != lepvec.end(); it2++ ) {
323 TVector3 lep2 = it2->vec.Vect();
324
325 if ( lep1.DrEtaPhi(lep2) <= 0.02 ) {
326 erase_this_lepton=true;
327 break;
328 }
329 }
330 if( erase_this_lepton ) {
331 if( ctrl.debug ) cout << "erasing ghost with pt " << it1->vec.Pt() << endl;
332 leptons_to_erase.push_back(it1);
333 }
334 }
335 for( int i=0; i<leptons_to_erase.size(); i++ ) {
336 lepvec.erase(leptons_to_erase[i]);
337 }
338
339 //********************************************************
340 // Step 4: Z candidate preselection
341 //********************************************************
342 vector<pair<int,int> > ZCandidates; // indices in lepvec of the two leptons
343 vector<pair<SimpleLepton,SimpleLepton> > ZCandidatesLeptons; // fsr-corrected leptons that form the Z
344 vector<pair<SelectionStatus,SelectionStatus> > ZCandidatesSelectionStatus;
345 for(int i = 0; i < lepvec.size(); ++i) {
346 for(int j = i+1; j < lepvec.size(); ++j) {
347 if( abs(lepvec[i].type) != abs(lepvec[j].type) ) continue;
348 if( lepvec[i].charge == lepvec[j].charge ) continue;
349
350 TLorentzVector Zvec = (lepvec[i].vec+lepvec[j].vec);
351
352 vector<SimpleLepton> lepvec_i = lepvec;
353 vector<SimpleLepton> lepvec_j = lepvec;
354
355 if( ctrl.doFSR ) {
356 if(ctrl.debug) cout << endl << "----------------> FSR ("<<i<<","<<j<<") <----------------------" << endl;
357 photonsToVeto.clear();
358 // copies of lepvec that have 1) the photons added to the momenta and 2) the fsrRecoveryAttempted flag set
359 float old_pt_i = lepvec[i].vec.Pt();
360 float old_pt_j = lepvec[j].vec.Pt();
361 float old_M = Zvec.M();
362
363 const ChargedParticle *lepton(NULL);
364 if(ctrl.debug) cout << "i: " << i << endl;
365 if(abs(lepvec[i].type) == 13) lepton = dynamic_cast<const ChargedParticle *>((*muonArr)[lepvec[i].index]);
366 else lepton = dynamic_cast<const ChargedParticle *>((*electronArr)[lepvec[i].index]);
367 pair<TLorentzVector,int> photon_i = findFsrPhoton(ctrl, ret, lepton, i, lepvec_i, pfCandidates, electronArr, &Zvec);
368 if(photon_i.second>=0 && ctrl.debug) cout << " FSR :: oldpt: " << old_pt_i << "\tnewpt: " << lepvec_i[i].vec.Pt() << "\tindex: " << i << endl;
369
370 lepton = NULL;
371 if(ctrl.debug) cout << "j: " << j << endl;
372 if( abs(lepvec[j].type) == 13 ) lepton = dynamic_cast<const ChargedParticle *>((*muonArr)[lepvec[j].index]);
373 else lepton = dynamic_cast<const ChargedParticle *>((*electronArr)[lepvec[j].index]);
374 pair<TLorentzVector,int> photon_j = findFsrPhoton(ctrl, ret, lepton, j, lepvec_j, pfCandidates, electronArr, &Zvec);
375 if(photon_j.second>=0 && ctrl.debug) cout << " FSR :: oldpt: " << old_pt_j << "\tnewpt: " << lepvec_j[j].vec.Pt() << "\tindex: " << j << endl;
376
377 bool useI(false),useJ(false);
378 if(photon_i.second >= 0) { // photon for i
379 if(photon_j.second < 0) {
380 useI = true;
381 } else { // both have photons
382 TLorentzVector lep_i(lepvec_i[i].vec),lep_j(lepvec_j[j].vec);
383 float oldM = (lep_i + lep_j).M();
384 float newM_i = (lep_i + photon_i.first + lep_j).M();
385 float newM_j = (lep_i + lep_j + photon_j.first).M();
386 if(ctrl.debug) cout << " two FSRs " << setw(12) << oldM << setw(12) << newM_i << setw(12) << newM_j << endl;
387 if(fabs(newM_i - Z_MASS) < fabs(newM_j - Z_MASS)) { // if mass with photon i is closer to z pole than with photon j
388 useI = true;
389 } else {
390 useJ = true;
391 }
392 }
393 } else if(photon_j.second >= 0) { // photon for j
394 useJ = true;
395 }
396
397 assert(!(useI && useJ));
398 if(useI) {
399 addPhotonToEventData(ret,photon_i.first);
400 lepvec_i[i].vec += photon_i.first;
401 lepvec_i[i].fsrRecoveryAttempted = true;
402 photonsToVeto.push_back((const PFCandidate*)(pfCandidates->At(photon_i.second)));
403 } else if(useJ) {
404 addPhotonToEventData(ret,photon_j.first);
405 lepvec_j[j].vec += photon_j.first;
406 lepvec_j[j].fsrRecoveryAttempted = true;
407 photonsToVeto.push_back((const PFCandidate*)(pfCandidates->At(photon_j.second)));
408 }
409
410 // recompute isolation excluding the fsr photons
411 if( abs(lepvec[i].type) == 11 ) {
412 const Electron *el = (Electron*)((*electronArr)[lepvec_i[i].index]);
413 lepvec_i[i].status |= (*ElectronIsoSelector)(ctrl,el,vtx,pfCandidates,puEnergyDensity,eraEle,photonsToVeto);
414
415 } else {
416 const Muon *mu = (Muon*)((*muonArr)[lepvec_i[i].index]);
417 lepvec_i[i].status |= (*MuonIsoSelector)(ctrl,mu,vtx,pfCandidates,puEnergyDensity,eraMu,photonsToVeto);
418 }
419 updateSimpleLepton(lepvec_i[i]);
420
421 if( abs(lepvec[j].type) == 11 ) {
422 const Electron *el = (Electron*)((*electronArr)[lepvec_j[j].index]);
423 lepvec_j[j].status |= (*ElectronIsoSelector)(ctrl,el,vtx,pfCandidates,puEnergyDensity,eraEle,photonsToVeto);
424 } else {
425 const Muon *mu = (Muon*)((*muonArr)[lepvec_j[j].index]);
426 lepvec_j[j].status |= (*MuonIsoSelector)(ctrl,mu,vtx,pfCandidates,puEnergyDensity,eraMu,photonsToVeto);
427 }
428 updateSimpleLepton(lepvec_j[j]);
429
430 float new_M = (lepvec_i[i].vec+lepvec_j[j].vec).M();
431 float new_pt_i = lepvec_i[i].vec.Pt();
432 float new_pt_j = lepvec_j[j].vec.Pt();
433 if( ctrl.debug && ret.fsrPhotons.size() > 0) {
434 cout << " ----> post FSR Z:";
435 cout << " oldM: " << setprecision(8) << old_M << "\tnewM:" << setprecision(8) << new_M << endl;
436 cout << " old_pt_i: " << setprecision(8) << old_pt_i << "\tnew_pt_i:" << setprecision(8) << new_pt_i << endl;
437 cout << " old_pt_j: " << setprecision(8) << old_pt_j << "\tnew_pt_j:" << setprecision(8) << new_pt_j << endl;
438 }
439
440 } // doFSR
441
442 // apply isolation criteria with recomputed isolation
443 if( !(lepvec_i[i].status.loose()) || !(lepvec_j[j].status.loose()) ) {
444 if(ctrl.debug) {
445 bitset<16> tmpbits_i(lepvec_i[i].status.getStatus()),tmpbits_j(lepvec_j[j].status.getStatus());
446 cout << " leptons fail selection (i: " << tmpbits_i << ", j: " << tmpbits_j << ")" << endl;
447 }
448 continue;
449 }
450
451 ZCandidates.push_back(pair<int,int> (i,j) );
452 ZCandidatesLeptons.push_back(pair<SimpleLepton,SimpleLepton> (lepvec_i[i],lepvec_j[j]) );
453 if( ctrl.debug ) cout << "Z candidate ("<< i << "," << j << ")" << "\tmass: " << (lepvec_i[i].vec+lepvec_j[j].vec).M() << endl;
454 }
455 }
456
457 if( ZCandidates.size() > 0 ) {
458 ret.status.selectionBits.flip(PASS_ZCANDIDATE);
459 if( ctrl.debug ) cout << "event has >0 Z candidates (" << ZCandidates.size() << " of em)" << endl;
460 } else {
461 ret.status.setStatus(SelectionStatus::FAIL);
462 return ret;
463 }
464
465 //
466 // Select Z1
467 //
468 int best_Z1_index;
469 float best_Z1_mass = 9999.;
470 TLorentzVector Z1vec;
471 for( int i=0; i<ZCandidates.size(); i++ ) {
472 TLorentzVector tmpZ1vec = (ZCandidatesLeptons[i].first.vec) + (ZCandidatesLeptons[i].second.vec);
473 if( fabs(tmpZ1vec.M()-Z_MASS) < fabs(best_Z1_mass-Z_MASS) ) {
474 best_Z1_index=i;
475 best_Z1_mass=tmpZ1vec.M();
476 Z1vec = tmpZ1vec;
477 }
478 }
479 ret.Z1leptons.push_back(ZCandidatesLeptons[best_Z1_index].first);
480 ret.Z1leptons.push_back(ZCandidatesLeptons[best_Z1_index].second);
481
482 if(ctrl.debug)
483 cout << "best mZ1: " << best_Z1_mass << " from (" << ZCandidates[best_Z1_index].first << "," << ZCandidates[best_Z1_index].second << ")" << endl;
484
485 //******************************************************************************
486 // Step 6.3 : require Z1 with 40<m<120
487 //******************************************************************************
488 if( Z1vec.M() > 40. && Z1vec.M() < 120. ) {
489 ret.status.selectionBits.flip(PASS_GOODZ1);
490 } else {
491 ret.status.setStatus(SelectionStatus::FAIL);
492 return ret;
493 }
494
495 //******************************************************************************
496 // Step 6.3 : 4 good leptons
497 //******************************************************************************
498 if( lepvec.size() >= 4 ) {
499 if( ctrl.debug) cout << "four leps" << endl;
500 ret.status.selectionBits.flip(PASS_4L);
501 } else {
502 ret.status.setStatus(SelectionStatus::FAIL);
503 return ret;
504 }
505
506 //********************************************************
507 // Step 5: ZZ candidates
508 //********************************************************
509 int nZZCandidates=0;
510 vector<pair<int,int> > ZZCandidates;
511 if(ctrl.debug) cout << "looping over " << ZCandidates.size() << " Z candidates: " << endl;
512 for(int z2index=0; z2index<ZCandidates.size(); ++z2index) {
513 int z1index = best_Z1_index;
514 if ( z2index == z1index ) { if(ctrl.debug) cout << " Z2 fails z2i = z1i" << endl; continue; }
515 if( ZCandidates[z1index].first == ZCandidates[z2index].first ) { if(ctrl.debug) cout << " Z2 fails icheck1" << endl; continue; }
516 if( ZCandidates[z1index].first == ZCandidates[z2index].second ) { if(ctrl.debug) cout << " Z2 fails icheck2" << endl; continue; }
517 if( ZCandidates[z1index].second == ZCandidates[z2index].first ) { if(ctrl.debug) cout << " Z2 fails icheck3" << endl; continue; }
518 if( ZCandidates[z1index].second == ZCandidates[z2index].second ) { if(ctrl.debug) cout << " Z2 fails icheck4" << endl; continue; }
519
520 ZZCandidates.push_back(pair<int,int> (z1index,z2index));
521 }
522 if(ZZCandidates.size() > 0) {
523 ret.status.selectionBits.flip(PASS_ZZCANDIDATE);
524 if(ctrl.debug) {
525 cout << ZZCandidates.size() << " zz cands" << endl;
526 cout << "-------------------------------------------------------" << endl;
527 // for( int l=0; l<lepvec.size(); l++ ) lepvec[l].print();
528 for(unsigned ican=0; ican<ZCandidatesLeptons.size(); ican++) {
529 ZCandidatesLeptons[ican].first.print();
530 ZCandidatesLeptons[ican].second.print();
531 }
532 cout << "-------------------------------------------------------" << endl;
533 if(ctrl.debug)
534 for(unsigned iph=0; iph<ret.fsrPhotons.size(); iph++)
535 cout << " fsr photon "
536 << setw(12) << ret.fsrPhotons[iph].vec.Pt()
537 << " eta: " << setw(12) << ret.fsrPhotons[iph].vec.Eta()
538 << " phi: " << setw(12) << ret.fsrPhotons[iph].vec.Phi() << endl;
539 }
540 } else {
541 if(ctrl.debug) cout << "no zz cands" << endl;
542 ret.status.setStatus(SelectionStatus::FAIL);
543 return ret;
544 }
545
546 //
547 // Select z2
548 //
549 int best_Z2_index;
550 float best_Z2_pt = -1.;
551 for( int i=0; i<ZZCandidates.size(); i++ ) {
552 int z2index = ZZCandidates[i].second;
553 TLorentzVector Z2 = (ZCandidatesLeptons[z2index].first.vec) +
554 (ZCandidatesLeptons[z2index].second.vec);
555 if( Z2.Pt() > best_Z2_pt ) {
556 best_Z2_index=z2index;
557 best_Z2_pt=Z2.Pt();
558 }
559 }
560 ret.Z2leptons.push_back(ZCandidatesLeptons[best_Z2_index].first); // push back the *fsr-corrected* leptons
561 ret.Z2leptons.push_back(ZCandidatesLeptons[best_Z2_index].second);
562
563 int theZ1type = abs(ZCandidatesLeptons[best_Z1_index].first.type);
564 int theZ2type = abs(ZCandidatesLeptons[best_Z2_index].first.type);
565
566 if(ctrl.debug) cout << "best mZ2: " << (ret.Z2leptons[0].vec+ret.Z2leptons[1].vec).M() << " from ("
567 << ZCandidates[best_Z2_index].first << "," << ZCandidates[best_Z2_index].second << ")" << endl;
568
569 increment(counts,"sfOsHiPt",theZ1type,theZ2type);
570
571 if(ctrl.debug) cout << "ZZ :: evt: " << info->EvtNum()
572 << "\tmZ1: " << (ret.Z1leptons[0].vec+ret.Z1leptons[1].vec).M()
573 << "\tmZ2: " << (ret.Z2leptons[0].vec+ret.Z2leptons[1].vec).M()
574 << endl;
575
576
577 //******************************************************************************
578 // Step 6.4 : require Z2 with 4<m<120
579 //******************************************************************************
580 TLorentzVector Z2vec = (ZCandidatesLeptons[best_Z2_index].first.vec) +
581 (ZCandidatesLeptons[best_Z2_index].second.vec);
582 if( Z2vec.M() > 4 && Z2vec.M() < 120 ) {
583 ret.status.selectionBits.flip(PASS_GOODZ2);
584 increment(counts,"4<mZ2<120",theZ1type,theZ2type);
585 } else {
586 ret.status.setStatus(SelectionStatus::FAIL);
587 return ret;
588 }
589
590
591 //******************************************************************************
592 // Step 6.1 : any two leptons 20/10
593 //******************************************************************************
594 vector<SimpleLepton> zzleptons;
595 zzleptons.push_back( ZCandidatesLeptons[best_Z1_index].first );
596 zzleptons.push_back( ZCandidatesLeptons[best_Z1_index].second );
597 zzleptons.push_back( ZCandidatesLeptons[best_Z2_index].first );
598 zzleptons.push_back( ZCandidatesLeptons[best_Z2_index].second );
599 int nlep_above_10=0,nlep_above_20=0;
600 for( int i=0; i<zzleptons.size(); i++ ) {
601 if( zzleptons[i].vec.Pt() > 10 ) nlep_above_10++;
602 if( zzleptons[i].vec.Pt() > 20 ) nlep_above_20++;
603 }
604 if( nlep_above_10 > 1 && nlep_above_20 > 0 ) {
605 ret.status.selectionBits.flip(PASS_ZZ_20_10);
606 increment(counts,"pt>20,10",theZ1type,theZ2type);
607 if( ctrl.debug ) cout << "passess 20/10 ..." << endl;
608 } else {
609 ret.status.setStatus(SelectionStatus::FAIL);
610 return ret;
611 }
612
613
614
615
616 //******************************************************************************
617 // Step 6.5 : resonance killing (4/4)
618 //******************************************************************************
619 bool resonance = false;
620 for( int i=0; i<zzleptons.size(); i++ ) {
621 for( int j=i+1; j<zzleptons.size(); j++ ) {
622 if( zzleptons[i].charge == zzleptons[j].charge ) continue; // 4/4
623 if( (zzleptons[i].vec+zzleptons[j].vec).M() <= 4. ) {
624 resonance = true;
625 break;
626 }
627 }
628 }
629 if( !resonance ) {
630 ret.status.selectionBits.flip(PASS_RESONANCE);
631 increment(counts,"mll>4",theZ1type,theZ2type);
632 if( ctrl.debug ) cout << "\tpasses resonance killing ... " << endl;
633 } else {
634 ret.status.setStatus(SelectionStatus::FAIL);
635 return ret;
636 }
637
638
639
640 //******************************************************************************
641 // Step 6.6 : m(4l) > 70 , m(4l) > 100
642 //******************************************************************************
643 TLorentzVector zzvec = (ZCandidatesLeptons[best_Z1_index].first.vec) +
644 (ZCandidatesLeptons[best_Z1_index].second.vec) +
645 (ZCandidatesLeptons[best_Z2_index].first.vec) +
646 (ZCandidatesLeptons[best_Z2_index].second.vec);
647
648 if(ctrl.debug)
649 cout << "forming zz from: "
650 << setw(9) << (ZCandidatesLeptons[best_Z1_index].first.vec).Pt()
651 << setw(9) << (ZCandidatesLeptons[best_Z1_index].second.vec).Pt()
652 << setw(9) << (ZCandidatesLeptons[best_Z2_index].first.vec).Pt()
653 << setw(9) << (ZCandidatesLeptons[best_Z2_index].second.vec).Pt() << endl;
654
655 if( zzvec.M() > 70. ) {
656 if(ctrl.debug) cout << "passes mzz > 70, mzz: " << zzvec.M() << endl;
657 ret.status.selectionBits.flip(PASS_m4l_GT_70);
658 increment(counts,"m4l>70",theZ1type,theZ2type);
659 } else {
660 ret.status.setStatus(SelectionStatus::FAIL);
661 return ret;
662 }
663
664 if( (ret.Z2leptons[0].vec+ret.Z2leptons[1].vec).M() > 12 ){
665 if(ctrl.debug) cout << "passes mZ2 > 12" << endl;
666 increment(counts,"mZ2>12",theZ1type,theZ2type);
667 } else {
668 ret.status.setStatus(SelectionStatus::FAIL);
669 return ret;
670 }
671
672 if( zzvec.M() > 100 ) {
673 if(ctrl.debug) cout << "passes mzz > 100, mzz: " << zzvec.M() << endl;
674 increment(counts,"m4l>100",theZ1type,theZ2type);
675 } else {
676 // cout << "NOTE: failed m4l>100 (" << zzvec.M() << "), but saving to ntuple anyway" << endl;
677 }
678
679 //***************************************************************
680 // finish
681 //***************************************************************
682
683 TLorentzVector theZ1 = (ZCandidatesLeptons[best_Z1_index].first.vec) +
684 (ZCandidatesLeptons[best_Z1_index].second.vec);
685 TLorentzVector theZ2 = (ZCandidatesLeptons[best_Z2_index].first.vec) +
686 (ZCandidatesLeptons[best_Z2_index].second.vec);
687 TLorentzVector theZZ = theZ1 + theZ2;
688
689 // if(ret.fsrPhotons.size() > 0) {
690 // if(ctrl.debug)
691 // cout << " fsr photon! pt: "
692 // << setw(12) << ret.fsrPhotons[0].vec.Pt()
693 // << " eta: " << setw(12) << ret.fsrPhotons[0].vec.Eta()
694 // << " phi: " << setw(12) << ret.fsrPhotons[0].vec.Phi() << endl;
695 // }
696 // if(ret.fsrPhotons.size() > 1) {
697 // if(ctrl.debug)
698 // cout << " fsr photon! pt: "
699 // << setw(12) << ret.fsrPhotons[1].vec.Pt()
700 // << " eta: " << setw(12) << ret.fsrPhotons[1].vec.Eta()
701 // << " phi: " << setw(12) << ret.fsrPhotons[1].vec.Phi() << endl;
702 // }
703 if( ctrl.debug ) cout << "run: " << info->RunNum()
704 << "\tevt: " << info->EvtNum()
705 << "\tZ1channel: " << theZ1type
706 << "\tZ2channel: " << theZ2type
707 << "\tmZ1: " << theZ1.M()
708 << "\tmZ2: " << theZ2.M()
709 << "\tm4l: " << theZZ.M()
710 << endl;
711
712 ret.status.setStatus(SelectionStatus::EVTPASS);
713
714 return ret;
715 }
716 //----------------------------------------------------------------------------
717 void updateSimpleLepton(SimpleLepton &tmplep)
718 //----------------------------------------------------------------------------
719 {
720 tmplep.isTight = tmplep.status.tight();
721 tmplep.isLoose = tmplep.status.loose();
722 }