ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/dhidas/OSUAnalysis/Tools/src/TopPairEventCandidate.cpp
Revision: 1.5
Committed: Sat Dec 31 07:50:50 2011 UTC (13 years, 4 months ago) by clseitz
Branch: MAIN
CVS Tags: HEAD
Changes since 1.4: +1 -1 lines
Log Message:
all the changes

File Contents

# Content
1 /*
2 * TopPairEventCandidate.cpp
3 *
4 * Created on: 9 Jul 2010
5 * Author: kreczko
6 */
7
8 #include "../interface/TopPairEventCandidate.h"
9 #include <iostream>
10 #include <iomanip>
11 using namespace std;
12
13 namespace BAT {
14
15 const double TopPairEventCandidate::pdgWmass = 80.399;
16 const double TopPairEventCandidate::wMassWidth = 8.0; // Derived from 10% jet resolution on old jet resolution twiki page
17 const double TopPairEventCandidate::pdgTopMass = 172.9;
18 const double TopPairEventCandidate::topMassWidth = 17.0; // See above
19 // Above values from PDG 2011
20
21 // The following are obsolete and are only retained in
22 // case the old ttbar code might be useful during
23 // testing.
24 const double TopPairEventCandidate::W_mass = TopPairEventCandidate::pdgWmass;
25 const double TopPairEventCandidate::matched_hadronic_W_mass = TopPairEventCandidate::pdgWmass;
26 const double TopPairEventCandidate::matched_hadronic_W_mass_sigma = TopPairEventCandidate::wMassWidth;
27 const double TopPairEventCandidate::matched_leptonic_top_mass = TopPairEventCandidate::pdgTopMass;
28 const double TopPairEventCandidate::matched_leptonic_top_mass_sigma = TopPairEventCandidate::topMassWidth;
29 const double TopPairEventCandidate::matched_hadronic_top_mass = TopPairEventCandidate::pdgTopMass;
30 const double TopPairEventCandidate::matched_hadronic_top_mass_sigma = TopPairEventCandidate::topMassWidth;
31 const double TopPairEventCandidate::matched_ptratio = 0.19;
32 const double TopPairEventCandidate::matched_ptratio_sigma = 0.4;
33 const double TopPairEventCandidate::matched_pt_ttbarSystem = 0.;
34 const double TopPairEventCandidate::matched_pt_ttbarSystem_sigma = 50.;
35 const double TopPairEventCandidate::matched_HTSystem = 1;
36 const double TopPairEventCandidate::matched_HTSystem_sigma = 0.1;
37 const double TopPairEventCandidate::matched_angle = 0.95;
38 const double TopPairEventCandidate::matched_angle_sigma = 0.31;
39
40 NeutrinoSelectionCriterion::value TopPairEventCandidate::usedNeutrinoSelection; // = NeutrinoSelectionCriterion::chi2;
41 TTbarReconstructionCriterion::value TopPairEventCandidate::usedTTbarReconstruction; // = TTbarReconstructionCriterion::TopMassDifference;
42
43
44 TopPairEventCandidate::TopPairEventCandidate() :
45 Event(),
46 leptonFromW(),
47 leptonicBJet(),
48 hadronicBJet(),
49 jet1FromW(),
50 jet2FromW(),
51 neutrino1(),
52 neutrino2(),
53 leptonicW1(),
54 leptonicW2(),
55 hadronicW(),
56 leptonicTop1(),
57 leptonicTop2(),
58 hadronicTop(),
59 selectedNeutrino(0),
60 currentSelectedNeutrino(0),
61 hadronicBIndex(0),
62 leptonicBIndex(0),
63 jet1FromWIndex(0),
64 jet2FromWIndex(0),
65 doneReconstruction(false),
66 conversionTagger(new ConversionTagger()),
67 doneConversionTagging(false),
68 solutions(),
69 compareSolutions(){
70 }
71
72 TopPairEventCandidate::TopPairEventCandidate(const Event& event) :
73 Event(event),
74 leptonFromW(),
75 leptonicBJet(),
76 hadronicBJet(),
77 jet1FromW(),
78 jet2FromW(),
79 neutrino1(),
80 neutrino2(),
81 leptonicW1(),
82 leptonicW2(),
83 hadronicW(),
84 leptonicTop1(),
85 leptonicTop2(),
86 hadronicTop(),
87 selectedNeutrino(0),
88 currentSelectedNeutrino(0),
89 hadronicBIndex(0),
90 leptonicBIndex(0),
91 jet1FromWIndex(0),
92 jet2FromWIndex(0),
93 doneReconstruction(false),
94 conversionTagger(new ConversionTagger()),
95 doneConversionTagging(false) {
96
97 }
98
99 TopPairEventCandidate::~TopPairEventCandidate() {
100 }
101
102 bool TopPairEventCandidate::passesScrapingFilter() const {
103 if (tracks.size() > 10) {
104 if (numberOfHighPurityTracks / (1.0 * tracks.size()) > 0.25)
105 return true;
106 else
107 return false;
108 } else
109 return isBeamScraping == false;
110 }
111
112 bool TopPairEventCandidate::passesHighLevelTrigger() const {
113 if (isRealData()) {
114 bool trigOn = false;
115 if (runNumber < 140041)
116 return HLT(HLTriggers::HLT_Ele10_LW_L1R);
117 else if (runNumber >= 140041 && runNumber <= 143962)
118 return HLT(HLTriggers::HLT_Ele15_SW_L1R);
119 else if (runNumber > 143962 && runNumber <= 146427)
120 return HLT(HLTriggers::HLT_Ele15_SW_CaloEleId_L1R);
121 else if (runNumber > 146427 && runNumber <= 147116)
122 return HLT(HLTriggers::HLT_Ele17_SW_CaloEleId_L1R);
123 else if (runNumber > 147116 && runNumber <= 148818)
124 return HLT(HLTriggers::HLT_Ele17_SW_TightEleId_L1R);
125 else if (runNumber >= 148819 && runNumber < 149181)
126 return HLT(HLTriggers::HLT_Ele22_SW_TighterEleId_L1R);
127 //return HLT(HLTriggers::HLT_Ele22_SW_TighterEleId_L1R_v2);
128 else if(runNumber >= 149181 && runNumber < 160000)
129 return HLT(HLTriggers::HLT_Ele22_SW_TighterEleId_L1R);
130 //return HLT(HLTriggers::HLT_Ele22_SW_TighterEleId_L1R_v3);
131
132 else if (runNumber >= 160404 && runNumber <= 163869)
133 trigOn = HLT(HLTriggers::HLT_Ele27_CaloIdVT_CaloIsoT_TrkIdT_TrkIsoT);
134 /*else if (runNumber >= 165970 && runNumber <= 166346)
135 trigOn = HLT(HLTriggers::HLT_Ele32_CaloIdVT_CaloIsoT_TrkIdT_TrkIsoT);*/
136 else if (runNumber >= 165970 && runNumber <= 178380)
137 trigOn =
138 HLT(HLTriggers::HLT_Ele25_CaloIdVT_CaloIsoT_TrkIdT_TrkIsoT_TriCentralJet30);
139 else if (runNumber >= 178420)
140 trigOn =
141 HLT(HLTriggers::HLT_Ele25_CaloIdVT_CaloIsoT_TrkIdT_TrkIsoT_TriCentralPFJet30);
142 if (trigOn)
143 return (true);
144 // Now try muon triggers if electron triggers failed
145 /* else if ((runNumber >= 160404 && runNumber <= 163869) ||
146 (runNumber >= 165088 && runNumber <= 166967))
147 return (HLT(HLTriggers::HLT_Mu30) || HLT(HLTriggers::HLT_IsoMu17));
148 else if (runNumber >= 167039 && runNumber <= 167913)
149 return (HLT(HLTriggers::HLT_IsoMu17_eta2p1) ||
150 HLT(HLTriggers::HLT_IsoMu24));
151 else if (runNumber >= 170249 && runNumber <= 173198)
152 return (HLT(HLTriggers::HLT_Mu40)||HLT(HLTriggers::HLT_Mu30) || HLT(HLTriggers::HLT_IsoMu24));
153 else if (runNumber >= 173236 && runNumber <= 173692)
154 return (HLT(HLTriggers::HLT_Mu40_eta2p1) || HLT(HLTriggers::HLT_IsoMu20));
155 else if (runNumber >= 175860 && runNumber <= 178160)
156 return ((HLT(HLTriggers::HLT_Mu40_eta2p1) || HLT(HLTriggers::HLT_IsoMu24_eta2p1));
157 else if (runNumber >= 178162)
158 return (HLT(HLTriggers::HLT_IsoMu30_eta2p1) || (HLT(HLTriggers::HLT_Mu40_eta2p1));*/
159 else if (runNumber >= 160404)
160 return (HLT(HLTriggers::HLT_IsoMu24_eta2p1) || HLT(HLTriggers::HLT_IsoMu24));
161 else return false;
162 } else return (HLT(HLTriggers::HLT_IsoMu24));// || HLT(HLTriggers::HLT_Ele32_CaloIdVT_CaloIsoT_TrkIdT_TrkIsoT) || HLT(HLTriggers::HLT_Ele27_CaloIdVT_CaloIsoT_TrkIdT_TrkIsoT)); // do not use HLT for MC
163 }
164
165 bool TopPairEventCandidate::hasOneGoodPrimaryVertex() const {
166 return goodVertices.size() >= 1;
167 }
168
169 bool TopPairEventCandidate::hasOnlyOneGoodIsolatedElectron() const {
170 if(Event::usePFIsolation)
171 return goodPFIsolatedElectrons.size() == 1;
172 else
173 return goodIsolatedElectrons.size() == 1;
174 }
175
176 bool TopPairEventCandidate::isolatedElectronDoesNotComeFromConversion() const {
177 bool passConversion = false;
178 if (Event::usePFIsolation) {
179 if (goodPFIsolatedElectrons.size() > 0)
180 passConversion = goodPFIsolatedElectrons.front()->isFromConversion() == false;
181 } else {
182 if (goodIsolatedElectrons.size() > 0)
183 passConversion = goodIsolatedElectrons.front()->isFromConversion() == false;
184 }
185
186 return passConversion;
187 }
188
189 bool TopPairEventCandidate::isolatedElectronNotTaggedAsFromConversion() const {
190 bool passConversion = false;
191 ElectronPointer electron;
192 if (Event::usePFIsolation) {
193 if (goodPFIsolatedElectrons.size() > 0)
194 electron = goodPFIsolatedElectrons.front();
195 } else {
196 if (goodIsolatedElectrons.size() > 0)
197 electron = goodIsolatedElectrons.front();
198 }
199 if (electron != 0) {
200 if (useCustomConversionTagger) {
201 conversionTagger->calculateConversionVariables(electron, tracks, 3.8, 0.45);
202 passConversion = conversionTagger->isFromConversion(0.02, 0.02) == false;
203 } else {
204 passConversion = electron->isTaggedAsConversion(0.02, 0.02) == false;
205 }
206 }
207
208 return passConversion;
209 }
210
211 bool TopPairEventCandidate::hasNoIsolatedMuon() const {
212 return looseMuons.size() == 0;
213 }
214
215 bool TopPairEventCandidate::hasAtLeastOneGoodJet() const {
216 return goodJets.size() >= 1;
217 }
218
219 bool TopPairEventCandidate::hasAtLeastTwoGoodJets() const {
220 return goodJets.size() >= 2;
221 }
222
223 bool TopPairEventCandidate::hasAtLeastThreeGoodJets() const {
224 return goodJets.size() >= 3;
225 }
226
227 bool TopPairEventCandidate::hasAtLeastFourGoodJets() const {
228 return goodJets.size() >= 4;
229 }
230
231 bool TopPairEventCandidate::isNotAZBosonEvent() const {
232 float invariantMass = 0;
233 bool isZEvent = false;
234 ElectronPointer isoElectron;
235
236 if (Event::usePFIsolation && goodPFIsolatedElectrons.size() > 0)
237 isoElectron = goodPFIsolatedElectrons.front();
238 else if (goodIsolatedElectrons.size() > 0)
239 isoElectron = goodIsolatedElectrons.front();
240
241 if (isoElectron != NULL && allElectrons.size() > 1) {
242 for (unsigned int index = 0; index < allElectrons.size(); ++index) {
243 const ElectronPointer looseElectron = allElectrons.at(index);
244 bool passLooseIso = false;
245
246 if (Event::usePFIsolation)
247 passLooseIso = looseElectron->isLoose() && looseElectron->pfIsolation() < 1.;
248 else
249 passLooseIso = looseElectron->isLoose() && looseElectron->relativeIsolation() < 1.;
250
251 if (passLooseIso)
252 invariantMass = isoElectron->invariantMass(looseElectron);
253 else
254 invariantMass = 0;
255
256 bool passesLowerLimit = invariantMass > 76;
257 bool passesUpperLimit = invariantMass < 106;
258 if (passesLowerLimit && passesUpperLimit)
259 isZEvent = true;
260 }
261
262 }
263
264
265 return isZEvent == false;
266 }
267
268 bool TopPairEventCandidate::passesMETCut() const{
269 return met->et() > 20.;
270 }
271
272 bool TopPairEventCandidate::passesAsymmetricJetCuts() const {
273 if(goodJets.size() < 2)// good jets have a cut of 30 GeV!
274 return false;
275 JetPointer leadingJet = goodJets.front();
276 JetPointer secondLeadingJet = goodJets.at(1);
277 return leadingJet->pt() > 70 && secondLeadingJet->pt() > 50;
278
279 }
280
281 bool TopPairEventCandidate::hasAtLeastOneBtag() const {
282 return goodBJets.size() >= 1;
283 }
284
285 bool TopPairEventCandidate::hasAtLeastTwoBtags() const{
286 return goodBJets.size() >= 2;
287 }
288
289 bool TopPairEventCandidate::passesFullTTbarEPlusJetSelection() const {
290 // unsigned int newstep = (int) TTbarEPlusJetsSelection::NUMBER_OF_SELECTION_STEPS - 1;
291 ///////////////////////////// from Lucaz
292 return passesSelectionStepUpTo(TTbarEPlusJetsSelection::AtLeastFourGoodJets);//(TTbarEPlusJetsSelection::Step) newstep);
293 //
294 }
295
296 bool TopPairEventCandidate::passesSelectionStepUpTo(enum TTbarEPlusJetsSelection::Step step) const {
297 if (step == TTbarEPlusJetsSelection::FilterOutScraping)
298 return passesSelectionStep(step);
299 else {
300 unsigned int newstep = (int) step - 1;
301 return passesSelectionStep(step) && passesSelectionStepUpTo((TTbarEPlusJetsSelection::Step) newstep);
302 }
303 }
304
305 bool TopPairEventCandidate::passesNMinus1(enum TTbarEPlusJetsSelection::Step omitted) const {
306 bool passes(true);
307
308 for (unsigned int cut = 0; cut < TTbarEPlusJetsSelection::NUMBER_OF_SELECTION_STEPS; ++cut) {
309 if (cut == (unsigned int) omitted)
310 continue;
311 passes = passes && passesSelectionStep((TTbarEPlusJetsSelection::Step) cut);
312 }
313 return passes;
314 }
315
316 bool TopPairEventCandidate::passesSelectionStep(enum TTbarEPlusJetsSelection::Step step) const {
317 switch (step) {
318 case TTbarEPlusJetsSelection::FilterOutScraping:
319 return passesScrapingFilter();
320 case TTbarEPlusJetsSelection::HighLevelTrigger:
321 return passesHighLevelTrigger();
322 case TTbarEPlusJetsSelection::GoodPrimaryvertex:
323 return hasOneGoodPrimaryVertex();
324 case TTbarEPlusJetsSelection::OneIsolatedElectron:
325 return hasOnlyOneGoodIsolatedElectron();
326 case TTbarEPlusJetsSelection::ConversionRejection:
327 return isolatedElectronDoesNotComeFromConversion();
328 case TTbarEPlusJetsSelection::ConversionFinder:
329 return isolatedElectronNotTaggedAsFromConversion();
330 case TTbarEPlusJetsSelection::LooseMuonVeto:
331 return hasNoIsolatedMuon();
332 case TTbarEPlusJetsSelection::AtLeastOneGoodJets:
333 return hasAtLeastOneGoodJet();
334 case TTbarEPlusJetsSelection::AtLeastTwoGoodJets:
335 return hasAtLeastTwoGoodJets();
336 case TTbarEPlusJetsSelection::AtLeastThreeGoodJets:
337 return hasAtLeastThreeGoodJets();
338 case TTbarEPlusJetsSelection::AtLeastFourGoodJets:
339 return hasAtLeastFourGoodJets();
340 case TTbarEPlusJetsSelection::Zveto:
341 return isNotAZBosonEvent();
342 case TTbarEPlusJetsSelection::MissingTransverseEnergy:
343 return passesMETCut();
344 case TTbarEPlusJetsSelection::AsymmetricJetCuts:
345 return passesAsymmetricJetCuts();
346 case TTbarEPlusJetsSelection::AtLeastOneBtag:
347 return hasAtLeastOneBtag();
348 case TTbarEPlusJetsSelection::AtLeastTwoBtags:
349 return hasAtLeastTwoBtags();
350 default:
351 return false;
352 }
353 }
354
355 bool TopPairEventCandidate::passesRelIsoSelection() const{
356 bool passesFirst3 = passesSelectionStepUpTo(TTbarEPlusJetsSelection::GoodPrimaryvertex);
357 bool passGoodElectrons = goodElectrons.size() > 0 && goodIsolatedElectrons.size() < 2;
358 bool passesBothIsolationvetos = false;
359 if (passGoodElectrons) {
360 const ElectronPointer electron = MostIsolatedElectron();
361 if (electron->isGood()) {
362 if (useCustomConversionTagger) {
363 conversionTagger->calculateConversionVariables(electron, tracks, 3.8, 0.45);
364 passesBothIsolationvetos = electron->isFromConversion() == false && conversionTagger->isFromConversion(
365 0.02, 0.02) == false;
366 }
367 else{
368 passesBothIsolationvetos = electron->isFromConversion() == false && electron->isTaggedAsConversion(
369 0.02, 0.02) == false;
370 }
371 }
372
373 }
374 bool muonVeto = hasNoIsolatedMuon();
375 bool Zveto = isNotAZBosonEvent();
376 return passesFirst3 && passGoodElectrons && passesBothIsolationvetos && muonVeto && Zveto;
377 }
378
379 bool TopPairEventCandidate::passesRelIsoControlSelection() const{
380 bool passesFirst3 = passesSelectionStepUpTo(TTbarEPlusJetsSelection::GoodPrimaryvertex);
381 bool passGoodElectrons = allElectrons.size() > 0 && goodIsolatedElectrons.size() < 2;
382 bool passesBothIsolationvetos = false;
383 if (passGoodElectrons) {
384 const ElectronPointer electron = MostIsolatedElectron();
385 if (electron->isQCDElectron()) {
386 if (useCustomConversionTagger) {
387 conversionTagger->calculateConversionVariables(electron, tracks, 3.8, 0.45);
388 passesBothIsolationvetos = electron->isFromConversion() == false && conversionTagger->isFromConversion(
389 0.02, 0.02) == false;
390 } else {
391 passesBothIsolationvetos = electron->isFromConversion() == false && electron->isTaggedAsConversion(
392 0.02, 0.02) == false;
393 }
394 }
395
396 }
397 bool muonVeto = hasNoIsolatedMuon();
398 bool Zveto = isNotAZBosonEvent();
399 return passesFirst3 && passGoodElectrons && passesBothIsolationvetos && muonVeto && Zveto;
400 }
401
402 bool TopPairEventCandidate::passesPFIsoSelection() const{
403 bool passesFirst3 = passesSelectionStepUpTo(TTbarEPlusJetsSelection::GoodPrimaryvertex);
404 bool passGoodElectrons = goodElectrons.size() > 0 && goodPFIsolatedElectrons.size() < 2;
405 bool passesBothIsolationvetos = false;
406 if (passGoodElectrons) {
407 const ElectronPointer electron = MostPFIsolatedElectron();
408 if (electron->isGood()) {
409 if (useCustomConversionTagger) {
410 conversionTagger->calculateConversionVariables(electron, tracks, 3.8, 0.45);
411 passesBothIsolationvetos = electron->isFromConversion() == false && conversionTagger->isFromConversion(
412 0.02, 0.02) == false;
413 }
414 else{
415 passesBothIsolationvetos = electron->isFromConversion() == false && electron->isTaggedAsConversion(
416 0.02, 0.02) == false;
417 }
418 }
419
420 }
421 bool muonVeto = hasNoIsolatedMuon();
422 bool Zveto = isNotAZBosonEvent();
423 return passesFirst3 && passGoodElectrons && passesBothIsolationvetos && muonVeto && Zveto;
424 }
425
426 bool TopPairEventCandidate::passesPFIsoControlSelection() const{
427 bool passesFirst3 = passesSelectionStepUpTo(TTbarEPlusJetsSelection::GoodPrimaryvertex);
428 bool passGoodElectrons = allElectrons.size() > 0 && goodPFIsolatedElectrons.size() < 2;
429 bool passesBothIsolationvetos = false;
430 if (passGoodElectrons) {
431 const ElectronPointer electron = MostPFIsolatedElectron();
432 if (electron->isQCDElectron()) {
433 if (useCustomConversionTagger) {
434 conversionTagger->calculateConversionVariables(electron, tracks, 3.8, 0.45);
435 passesBothIsolationvetos = electron->isFromConversion() == false && conversionTagger->isFromConversion(
436 0.02, 0.02) == false;
437 } else {
438 passesBothIsolationvetos = electron->isFromConversion() == false && electron->isTaggedAsConversion(
439 0.02, 0.02) == false;
440 }
441 }
442
443 }
444 bool muonVeto = hasNoIsolatedMuon();
445 bool Zveto = isNotAZBosonEvent();
446 return passesFirst3 && passGoodElectrons && passesBothIsolationvetos && muonVeto && Zveto;
447 }
448
449 bool TopPairEventCandidate::passesConversionSelection() const {
450 bool passesFirst6 = passesSelectionStepUpTo(TTbarEPlusJetsSelection::Zveto);
451 bool isConversion1 = isolatedElectronDoesNotComeFromConversion() == false;
452 bool isConversion2 = isolatedElectronNotTaggedAsFromConversion() == false;
453 bool atLeast4Jets = hasAtLeastFourGoodJets();
454 return passesFirst6 && (isConversion1 || isConversion2) && atLeast4Jets;
455 }
456
457 bool TopPairEventCandidate::passesAntiIsolationSelection() const {
458 //require at least one good electron and no isolated good electrons
459 if (!(goodElectrons.size() > 0 && goodIsolatedElectrons.size() == 0))
460 return false;
461
462 bool passesFirst3 = passesSelectionStep(TTbarEPlusJetsSelection::GoodPrimaryvertex);
463
464
465 bool muonVeto = passesSelectionStep(TTbarEPlusJetsSelection::LooseMuonVeto);
466 bool zveto = passesSelectionStep(TTbarEPlusJetsSelection::Zveto);
467 bool conversionVeto = (goodElectrons.front()->isFromConversion() || goodElectrons.front()->isTaggedAsConversion(
468 0.2, 0.2)) == false;
469 bool jets = hasAtLeastFourGoodJets();
470 return passesFirst3 && muonVeto && zveto && conversionVeto && jets;
471 }
472
473 void TopPairEventCandidate::reconstructTTbar(LeptonPointer lepton) {
474 if (goodJets.size() < 4)
475 throw ReconstructionException("Not enough jets available to reconstruct top event using Mass Equality method.");
476 leptonFromW = lepton;
477 selectedNeutrino = 0;
478 currentSelectedNeutrino = 0;
479 reconstructNeutrinos();
480 double chosen_TopMassDifference(9999999.);
481 double chosen_Chi2Total(9999999.);
482
483 for (unsigned short hadBindex = 0; hadBindex < goodJets.size(); ++hadBindex) {
484 for (unsigned short lepBindex = 0; lepBindex < goodJets.size(); ++lepBindex) {
485 if (lepBindex == hadBindex)
486 continue;
487 for (unsigned short jet1Index = 0; jet1Index < goodJets.size(); ++jet1Index) {
488 if (jet1Index == lepBindex || jet1Index == hadBindex)
489 continue;
490 for (unsigned short jet2Index = 0; jet2Index < goodJets.size(); ++jet2Index) {
491 if (jet2Index == jet1Index || jet2Index == lepBindex || jet2Index == hadBindex)
492 continue;
493 hadronicBJet = goodJets.at(hadBindex);
494 leptonicBJet = goodJets.at(lepBindex);
495 jet1FromW = goodJets.at(jet1Index);
496 jet2FromW = goodJets.at(jet2Index);
497
498 leptonicW1 = ParticlePointer(new Particle(*neutrino1 + *leptonFromW));
499 leptonicW2 = ParticlePointer(new Particle(*neutrino2 + *leptonFromW));
500 hadronicW = ParticlePointer(new Particle(*jet1FromW + *jet2FromW));
501 leptonicTop1 = ParticlePointer(new Particle(*leptonicBJet + *leptonicW1));
502 leptonicTop2 = ParticlePointer(new Particle(*leptonicBJet + *leptonicW2));
503 hadronicTop = ParticlePointer(new Particle(*hadronicBJet + *hadronicW));
504 fillHypotheses();
505 selectNeutrinoSolution();
506 double TopMassDifference = calculateTopMassDifference(currentSelectedNeutrino);
507 double chi2 = getTotalChi2(currentSelectedNeutrino);
508 switch (usedTTbarReconstruction) {
509 case TTbarReconstructionCriterion::TopMassDifference:
510 if (TopMassDifference < chosen_TopMassDifference) {
511 hadronicBIndex = hadBindex;
512 leptonicBIndex = lepBindex;
513 jet1FromWIndex = jet1Index;
514 jet2FromWIndex = jet2Index;
515 chosen_TopMassDifference = TopMassDifference;
516 selectedNeutrino = currentSelectedNeutrino;
517 }
518 break;
519
520 case TTbarReconstructionCriterion::chi2:
521 if (chi2 < chosen_Chi2Total) {
522 hadronicBIndex = hadBindex;
523 leptonicBIndex = lepBindex;
524 jet1FromWIndex = jet1Index;
525 jet2FromWIndex = jet2Index;
526 chosen_Chi2Total = chi2;
527 selectedNeutrino = currentSelectedNeutrino;
528 }
529 break;
530 }
531 }
532 }
533 }
534 }
535 std::sort(solutions.begin(), solutions.end(), compareSolutions);
536 hadronicBJet = goodJets.at(hadronicBIndex);
537 leptonicBJet = goodJets.at(leptonicBIndex);
538 jet1FromW = goodJets.at(jet1FromWIndex);
539 jet2FromW = goodJets.at(jet2FromWIndex);
540 leptonicW1 = ParticlePointer(new Particle(*neutrino1 + *leptonFromW));
541 leptonicW2 = ParticlePointer(new Particle(*neutrino2 + *leptonFromW));
542 hadronicW = ParticlePointer(new Particle(*jet1FromW + *jet2FromW));
543 leptonicTop1 = ParticlePointer(new Particle(*leptonicBJet + *leptonicW1));
544 leptonicTop2 = ParticlePointer(new Particle(*leptonicBJet + *leptonicW2));
545 hadronicTop = ParticlePointer(new Particle(*hadronicBJet + *hadronicW));
546 if (selectedNeutrino == 1)
547 ttbarResonance = ParticlePointer(new Particle(*leptonicTop1 + *hadronicTop));
548 else
549 ttbarResonance = ParticlePointer(new Particle(*leptonicTop2 + *hadronicTop));
550 doneReconstruction = true;
551 }
552
553
554 void TopPairEventCandidate::reconstructNeutrinos() {
555 boost::array<double, 2> neutrinoPzs = computeNeutrinoPz();
556 double energy1 = sqrt(met->et() * met->et() + neutrinoPzs.at(0) * neutrinoPzs.at(0));
557 double energy2 = sqrt(met->et() * met->et() + neutrinoPzs.at(1) * neutrinoPzs.at(1));
558 neutrino1 = ParticlePointer(new Particle(energy1, met->px(), met->py(), neutrinoPzs.at(0)));
559 neutrino2 = ParticlePointer(new Particle(energy2, met->px(), met->py(), neutrinoPzs.at(1)));
560
561 if (isnan(neutrino1->energy()) && isnan(neutrino2->energy()))
562 throw ReconstructionException("No physical neutrino solution found");
563 else if (isnan(neutrino1->energy()))
564 neutrino1 = neutrino2;
565 else if (isnan(neutrino2->energy()))
566 neutrino2 = neutrino1;
567 }
568
569 const boost::array<double, 2> TopPairEventCandidate::computeNeutrinoPz() {
570 if (leptonFromW == 0)
571 throw ReconstructionException("Could not reconstruct neutrinos: no isolated leptons found");
572 if (met->energy() == 0)
573 throw ReconstructionException("Could not reconstruct neutrinos: no MET found");
574 boost::array<double, 2> neutrinoPzs;
575
576 // Two unknowns, neutrino E and pz. But since neutrino mass = 0, can
577 // solve for pz. Result is long and messy, as follows.
578
579 double pz1(0), pz2(0);
580 double ee = leptonFromW->energy();
581 double pxe = leptonFromW->px();
582 double pye = leptonFromW->py();
583 double pze = leptonFromW->pz();
584 double pxnu = met->px();
585 double pynu = met->py();
586
587 double a = W_mass * W_mass + 2.0 * pxe * pxnu + 2.0 * pye * pynu;
588 double A = 4.0 * (ee * ee - pze * pze);
589 double B = -4.0 * a * pze;
590 double C = 4.0 * ee * ee * (pxnu * pxnu + pynu * pynu) - a * a;
591
592 double tmproot = B * B - 4.0 * A * C;
593 if (tmproot < 0) {
594 pz1 = pz2 = -B / (2 * A); // Take real part
595 } else {
596 pz1 = (-B + TMath::Sqrt(tmproot)) / (2.0 * A);
597 pz2 = (-B - TMath::Sqrt(tmproot)) / (2.0 * A);
598
599 }
600 neutrinoPzs[0] = pz1;
601 neutrinoPzs[1] = pz2;
602 return neutrinoPzs;
603 }
604
605
606 void TopPairEventCandidate::fillHypotheses() {
607 TtbarHypothesisPointer hypothesis1(fillHypothesis(1));
608 TtbarHypothesisPointer hypothesis2(fillHypothesis(2));
609 solutions.push_back(hypothesis1);
610 solutions.push_back(hypothesis2);
611
612 }
613
614 const TtbarHypothesisPointer TopPairEventCandidate::fillHypothesis(unsigned short int neutrinoSolution) {
615 TtbarHypothesisPointer hypothesis(new TtbarHypothesis());
616 hypothesis->leptonFromW = leptonFromW;
617 hypothesis->leptonicBjet = leptonicBJet;
618 hypothesis->hadronicBJet = hadronicBJet;
619 hypothesis->jet1FromW = jet1FromW;
620 hypothesis->jet2FromW = jet2FromW;
621 hypothesis->hadronicW = hadronicW;
622 hypothesis->hadronicTop = hadronicTop;
623 hypothesis->hadronicChi2 = getHadronicChi2();
624 if(neutrinoSolution == 1) {
625 hypothesis->neutrinoFromW = neutrino1;
626 hypothesis->leptonicW = leptonicW1;
627 hypothesis->leptonicTop = leptonicTop1;
628 }
629 else {
630 hypothesis->neutrinoFromW = neutrino2;
631 hypothesis->leptonicW = leptonicW2;
632 hypothesis->leptonicTop = leptonicTop2;
633 }
634
635 hypothesis->totalChi2 = getTotalChi2(neutrinoSolution);
636 hypothesis->globalChi2 = getGlobalChi2(neutrinoSolution);
637 hypothesis->leptonicChi2 = getLeptonicChi2(neutrinoSolution);
638 ParticlePointer resonance(new Particle(*hypothesis->leptonicTop + *hypothesis->hadronicTop));
639 hypothesis->resonance = resonance;
640 return hypothesis;
641 }
642
643 void TopPairEventCandidate::selectNeutrinoSolution() {
644
645 if (leptonicTop1->mass() < 0 && leptonicTop2->mass() < 0) {
646 inspectReconstructedEvent();
647 throw ReconstructionException("No valid neutrino solution found");
648 } else if (leptonicTop1->mass() < 0 && leptonicTop2->mass() > 0) {
649 currentSelectedNeutrino = 2;
650 } else if (leptonicTop1->mass() > 0 && leptonicTop2->mass() < 0) {
651 currentSelectedNeutrino = 1;
652 } else {// both solutions give positive mass
653 switch (usedNeutrinoSelection) {
654 case NeutrinoSelectionCriterion::TopMassDifference:
655 fabs(leptonicTop1->mass()-hadronicTop->mass()) < fabs(leptonicTop2->mass()-hadronicTop->mass()) ?
656 currentSelectedNeutrino = 1 : currentSelectedNeutrino = 2;
657 break;
658 case NeutrinoSelectionCriterion::chi2:
659 getTotalChi2(1) < getTotalChi2(2) ? currentSelectedNeutrino = 1 : currentSelectedNeutrino = 2;
660 break;
661
662 case NeutrinoSelectionCriterion::pzClosestToLepton:
663 fabs(neutrino1->pz() - leptonFromW->pz()) < fabs(neutrino2->pz()
664 - leptonFromW->pz()) ? currentSelectedNeutrino = 1 : currentSelectedNeutrino = 2;
665 break;
666
667 case NeutrinoSelectionCriterion::mostCentral:
668 fabs(neutrino1->pz()) < fabs(neutrino2->pz()) ? currentSelectedNeutrino = 1 : currentSelectedNeutrino = 2;
669 break;
670
671 case NeutrinoSelectionCriterion::pzClosestToLeptonOrMostcentralIfAbove300:
672 fabs(neutrino1->pz() - leptonFromW->pz()) < fabs(neutrino2->pz()
673 - leptonFromW->pz()) ? currentSelectedNeutrino = 1 : currentSelectedNeutrino = 2;
674 if (fabs(neutrino1->pz()) > 300 || fabs(neutrino2->pz()) > 300)
675 fabs(neutrino1->pz()) < fabs(neutrino2->pz()) ? currentSelectedNeutrino = 1 : currentSelectedNeutrino
676 = 2;
677 break;
678
679 case NeutrinoSelectionCriterion::largestValueOfCosine:
680 TVector3 p3W, p3e;
681 //TODO clean up
682 p3W = leptonicW1->getFourVector().Vect();
683 p3e = leptonFromW->getFourVector().Vect();
684
685 double sinthcm1 = 2. * (p3e.Perp(p3W)) / W_mass;
686 p3W = leptonicW2->getFourVector().Vect();
687 double sinthcm2 = 2. * (p3e.Perp(p3W)) / W_mass;
688
689 double costhcm1 = TMath::Sqrt(1. - sinthcm1 * sinthcm1);
690 double costhcm2 = TMath::Sqrt(1. - sinthcm2 * sinthcm2);
691 costhcm1 > costhcm2 ? currentSelectedNeutrino = 1 : currentSelectedNeutrino = 2;
692 break;
693
694 }
695 }
696
697 }
698
699 double TopPairEventCandidate::calculateTopMassDifference(unsigned short int neutrinoSolution) const {
700
701 double LeptonicTop1MassDifference = fabs(leptonicTop1->mass()-hadronicTop->mass());
702 double LeptonicTop2MassDifference = fabs(leptonicTop2->mass()-hadronicTop->mass());
703
704 if (neutrinoSolution == 1)
705 return LeptonicTop1MassDifference;
706 else
707 return LeptonicTop2MassDifference;
708
709 }
710
711 double TopPairEventCandidate::getTotalChi2() {
712 double totalChi2(9999999);
713 double firstTotalChi2 = getTotalChi2(1);
714 double secondTotalChi2 = getTotalChi2(2);
715 selectedNeutrino == 1 ? totalChi2 = firstTotalChi2 : totalChi2 = secondTotalChi2;
716 // if (firstTotalChi2 < secondTotalChi2) {
717 // selectedNeutrino = 1;
718 // totalChi2 = firstTotalChi2;
719 // } else {
720 // selectedNeutrino = 2;
721 // totalChi2 = secondTotalChi2;
722 // }
723 return totalChi2;
724 }
725
726 double TopPairEventCandidate::getTotalChi2(unsigned short int neutrinoSolution) const {
727 return getLeptonicChi2(neutrinoSolution) + getHadronicChi2() + getGlobalChi2(neutrinoSolution);
728 }
729
730 double TopPairEventCandidate::getLeptonicChi2(unsigned short int neutrinoSolution) const {
731 double topMass(0);
732 double angle = leptonicBJet->angle(leptonFromW);
733 if (neutrinoSolution == 1)
734 topMass = leptonicTop1->mass();
735 else
736 topMass = leptonicTop2->mass();
737
738 return getLeptonicChi2(topMass, angle);
739 }
740
741 double TopPairEventCandidate::getLeptonicChi2(double topMass, double angle) const {
742 cout << "Using old TTBar getLeptonicChi2 \n";
743 double massDifference = TMath::Power(topMass - matched_leptonic_top_mass, 2);
744 double massError = 2 * matched_leptonic_top_mass_sigma * matched_leptonic_top_mass_sigma;
745 double massTerm = massDifference / massError;
746
747 double angleDifference = TMath::Power(angle - matched_angle, 2);
748 double angleError = 2 * matched_angle_sigma * matched_angle_sigma;
749 double angleTerm = angleDifference / angleError;
750 return 1.0 / sqrt(2.0) * (angleTerm + massTerm);
751 }
752
753 double TopPairEventCandidate::getHadronicChi2() const {
754 double ptRatioDifference = TMath::Power(PtRatio() - matched_ptratio, 2);
755 double ptRatioError = 2 * matched_ptratio_sigma * matched_ptratio_sigma;
756 double ptRatioTerm = ptRatioDifference / ptRatioError;
757
758 double WmassDifference = TMath::Power(hadronicW->mass() - matched_hadronic_W_mass, 2);
759 double WmassError = 2 * matched_hadronic_W_mass_sigma * matched_hadronic_W_mass_sigma;
760 double WmassTerm = WmassDifference / WmassError;
761
762 double topMassDifference = TMath::Power(hadronicTop->mass() - matched_hadronic_top_mass, 2);
763 double topMassError = 2 * matched_hadronic_top_mass_sigma * matched_hadronic_top_mass_sigma;
764 double topMassTerm = topMassDifference / topMassError;
765 return 1 / sqrt(3) * (topMassTerm + WmassTerm + ptRatioTerm);
766
767 ///////////////////////////// Latest Bristol code may have dropped ptRatioTerm
768 // return 1 / sqrt(2) * (topMassTerm + WmassTerm);// + ptRatioTerm);
769 //
770 }
771
772 double TopPairEventCandidate::PtRatio() const {
773 return TMath::Log(hadronicTop->pt() / hadronicW->pt());
774 }
775
776 double TopPairEventCandidate::getGlobalChi2(unsigned short neutrinoSolution) const {
777 double pttbar = PtTtbarSystem(neutrinoSolution);
778 double pttbarDifference = TMath::Power(pttbar - matched_pt_ttbarSystem, 2);
779 double pttbarError = (2 * matched_pt_ttbarSystem_sigma * matched_pt_ttbarSystem_sigma);
780 double pttbarTerm = pttbarDifference / pttbarError;
781
782 double htSystemDifference = TMath::Power(HTSystem() - matched_HTSystem, 2);
783 double htSystemError = matched_HTSystem_sigma * matched_HTSystem_sigma * 2;
784 double htSystemTerm = htSystemDifference / htSystemError;
785 return 1 / sqrt(2) * (pttbarTerm + htSystemTerm);
786 }
787
788 double TopPairEventCandidate::PtTtbarSystem(unsigned short neutrinoSolution) const {
789 ParticlePointer combined;
790 if (neutrinoSolution == 1)
791 combined = ParticlePointer(new Particle(*leptonicTop1 + *hadronicTop));
792 else
793 combined = ParticlePointer(new Particle(*leptonicTop2 + *hadronicTop));
794 return combined->pt();
795 }
796
797 double TopPairEventCandidate::HT(unsigned short jetLimit) const {
798 double HT(0);
799 unsigned short limit = goodJets.size();
800 if (limit > jetLimit + 1)
801 limit = jetLimit + 1;
802
803 for (unsigned short index = 0; index < limit; ++index)
804 HT += goodJets.at(index)->pt();
805
806 return HT;
807 }
808
809 double TopPairEventCandidate::HTSystem() const {
810 return sumPt() / HT(8);
811 }
812
813 double TopPairEventCandidate::sumPt() const {
814 return leptonicBJet->pt() + hadronicBJet->pt() + jet1FromW->pt() + jet2FromW->pt();
815 }
816
817 void TopPairEventCandidate::throwExpeptionIfNotReconstructed(TString location) const {
818 if (doneReconstruction == false)
819 throw ReconstructionException(TString("Can't access reconstructed particles before reconstruction: ") + location);
820 }
821
822 const LeptonPointer TopPairEventCandidate::getLeptonFromWDecay() const {
823 return leptonFromW;
824 }
825
826 const ParticlePointer TopPairEventCandidate::getNeutrinoFromWDecay() const {
827 throwExpeptionIfNotReconstructed("TopPairEventCandidate::getNeutrinoFromWDecay");
828 if (selectedNeutrino == 1)
829 return neutrino1;
830 else
831 return neutrino2;
832 }
833
834 const JetPointer TopPairEventCandidate::getHadronicBJet() const {
835 throwExpeptionIfNotReconstructed("TopPairEventCandidate::getHadronicBJet");
836 return hadronicBJet;
837 }
838
839 const JetPointer TopPairEventCandidate::getLeptonicBJet() const {
840 throwExpeptionIfNotReconstructed("TopPairEventCandidate::getLeptonicBJet");
841 return leptonicBJet;
842 }
843
844
845 const ParticlePointer TopPairEventCandidate::getLeptonicW() const
846 {
847 throwExpeptionIfNotReconstructed("TopPairEventCandidate::getLeptonicW");
848 if (selectedNeutrino == 1)
849 return leptonicW1;
850 else
851 return leptonicW2;
852 }
853
854
855 const JetPointer TopPairEventCandidate::getJet1FromHadronicW() const {
856 throwExpeptionIfNotReconstructed("TopPairEventCandidate::getJet1FromHadronicW");
857 return jet1FromW;
858 }
859
860 const JetPointer TopPairEventCandidate::getJet2FromHadronicW() const {
861 throwExpeptionIfNotReconstructed("TopPairEventCandidate::getJet2FromHadronicW");
862 return jet2FromW;
863 }
864
865 const ParticlePointer TopPairEventCandidate::getHadronicW() const {
866 throwExpeptionIfNotReconstructed("TopPairEventCandidate::getHadronicW");
867 return hadronicW;
868 }
869
870 const ParticlePointer TopPairEventCandidate::getLeptonicTop() const {
871 throwExpeptionIfNotReconstructed("TopPairEventCandidate::getLeptonicTop");
872 if (selectedNeutrino == 1)
873 return leptonicTop1;
874 else
875 return leptonicTop2;
876 }
877
878 const ParticlePointer TopPairEventCandidate::getHadronicTop() const {
879 throwExpeptionIfNotReconstructed("TopPairEventCandidate::getHadronicTop");
880 return hadronicTop;
881 }
882
883 const ParticlePointer TopPairEventCandidate::getResonance() const {
884 throwExpeptionIfNotReconstructed("TopPairEventCandidate::getResonance");
885 return ttbarResonance;
886 }
887
888 double TopPairEventCandidate::M3() const {
889 double m3(0), max_pt(0);
890 if (goodJets.size() >= 3) {
891 for (unsigned int index1 = 0; index1 < goodJets.size() - 2; ++index1) {
892 for (unsigned int index2 = index1 + 1; index2 < goodJets.size() - 1; ++index2) {
893 for (unsigned int index3 = index2 + 1; index3 < goodJets.size(); ++index3) {
894 FourVector m3Vector(goodJets.at(index1)->getFourVector() + goodJets.at(index2)->getFourVector()
895 + goodJets.at(index3)->getFourVector());
896 double currentPt = m3Vector.Pt();
897 if (currentPt > max_pt) {
898 max_pt = currentPt;
899 m3 = m3Vector.M();
900 }
901 }
902 }
903 }
904 }
905
906 return m3;
907 }
908
909
910 double TtbarHypothesis::M3() const {
911 double m3(0), max_et(0);
912 JetCollection mcJets;
913 mcJets.clear();
914 mcJets.push_back(jet1FromW);
915 mcJets.push_back(jet2FromW);
916 mcJets.push_back(leptonicBjet);
917 mcJets.push_back(hadronicBJet);
918 if (mcJets.size() >= 3) {
919 for (unsigned int index1 = 0; index1 < mcJets.size() - 2; ++index1) {
920 for (unsigned int index2 = index1 + 1; index2 < mcJets.size() - 1; ++index2) {
921 for (unsigned int index3 = index2 + 1; index3 < mcJets.size(); ++index3) {
922 FourVector m3Vector(mcJets.at(index1)->getFourVector() + mcJets.at(index2)->getFourVector()
923 + mcJets.at(index3)->getFourVector());
924 double currentEt = m3Vector.Et();
925 if (currentEt > max_et) {
926 max_et = currentEt;
927 m3 = m3Vector.M();
928 }
929 }
930 }
931 }
932 }
933
934 return m3;
935 }
936
937 double TopPairEventCandidate::mttbar() const {
938 return getResonance()->mass();
939 }
940
941 const std::vector<TtbarHypothesisPointer>& TopPairEventCandidate::Solutions() const{
942 return solutions;
943 }
944
945 void TopPairEventCandidate::inspectReconstructedEvent() const {
946 cout << "run " << runNumber << ", event " << eventNumber << endl;
947 cout << "leptonic b jet, goodJet index " << leptonicBIndex << endl;
948 EventContentPrinter::printJet(leptonicBJet);
949
950 cout << "lepton from W" << endl;
951 // EventContentPrinter::printElectron(electronFromW);
952
953 cout << "MET" << endl;
954 EventContentPrinter::printParticle(met);
955 cout << endl;
956
957 cout << "reconstructed neutrino 1(selected: " << selectedNeutrino << ")" << endl;
958 EventContentPrinter::printParticle(neutrino1);
959 cout << endl;
960
961 cout << "reconstructed neutrino 2(selected: " << selectedNeutrino << ")" << endl;
962 EventContentPrinter::printParticle(neutrino2);
963 cout << endl;
964
965 cout << "leptonic W 1 (selected: " << selectedNeutrino << ")" << endl;
966 EventContentPrinter::printParticle(leptonicW1);
967 cout << endl;
968
969 cout << "leptonic W 2 (selected: " << selectedNeutrino << ")" << endl;
970 EventContentPrinter::printParticle(leptonicW2);
971 cout << endl;
972
973 cout << "leptonic top 1 (selected: " << selectedNeutrino << ")" << endl;
974 EventContentPrinter::printParticle(leptonicTop1);
975 cout << endl;
976
977 cout << "leptonic top 2 (selected: " << selectedNeutrino << ")" << endl;
978 EventContentPrinter::printParticle(leptonicTop2);
979 cout << endl;
980
981 cout << "hadronic b jet, goodJet index " << hadronicBIndex << endl;
982 EventContentPrinter::printJet(hadronicBJet);
983
984 cout << "jet1 from W, goodJet index " << jet1FromWIndex << endl;
985 EventContentPrinter::printJet(jet1FromW);
986
987 cout << "jet 2 from W, goodJet index " << jet2FromWIndex << endl;
988 EventContentPrinter::printJet(jet2FromW);
989
990 cout << "hadronic W" << endl;
991 EventContentPrinter::printParticle(hadronicW);
992 cout << endl;
993
994 cout << "hadronic top" << endl;
995 EventContentPrinter::printParticle(hadronicTop);
996 cout << endl;
997 }
998
999 double TopPairEventCandidate::fullHT() const {
1000 double ht(met->pt());
1001
1002 for (unsigned int index = 0; index < goodPFIsolatedElectrons.size(); ++index) {
1003 ht += goodPFIsolatedElectrons.at(index)->pt();
1004 }
1005
1006 for (unsigned int index = 0; index < goodIsolatedMuons.size(); ++index) {
1007 ht += goodIsolatedMuons.at(index)->pt();
1008 }
1009
1010 for (unsigned int index = 0; index < goodJets.size(); ++index) {
1011 ht += goodJets.at(index)->pt();
1012 }
1013 return ht;
1014 }
1015
1016 double TopPairEventCandidate::transverseWmass(const LeptonPointer lepton) const {
1017 double energySquared = pow(lepton->et() + met->et(), 2);
1018 double momentumSquared = pow(lepton->px() + met->px(), 2) + pow(lepton->py() + met->py(), 2);
1019 double tMassSquared = energySquared - momentumSquared;
1020
1021 if (tMassSquared > 0)
1022 return sqrt(tMassSquared);
1023 else
1024 return -1;
1025 }
1026
1027 void TopPairEventCandidate::reconstruct(Rule rule, const LeptonPointer lepton) {
1028 //TODO: change this into if(!Rule::meetsInitialConditaion())
1029 if (goodJets.size() < 4 || lepton == 0)
1030 throw ReconstructionException("Not enough jets available to reconstruct top event using Mass Equality method.");
1031 leptonFromW = lepton;
1032 selectedNeutrino = 0;
1033 currentSelectedNeutrino = 0;
1034
1035 reconstructNeutrinos();
1036 double chosen_TopMassDifference(9999999.);
1037 double chosen_Chi2Total(9999999.);
1038 for (unsigned short hadBindex = 0; hadBindex < goodJets.size(); ++hadBindex) {
1039 if (rule->hardHadronicBJetCondition(goodJets.at(hadBindex)))
1040 continue;
1041
1042 for (unsigned short lepBindex = 0; lepBindex < goodJets.size(); ++lepBindex) {
1043 if (lepBindex == hadBindex || rule->hardLeptonicBJetCondition(goodJets.at(lepBindex)))
1044 continue;
1045
1046 for (unsigned short jet1Index = 0; jet1Index < goodJets.size(); ++jet1Index) {
1047 if (jet1Index == lepBindex || jet1Index == hadBindex || rule->hardHadronicJetFromWCondition(
1048 goodJets.at(jet1Index)))
1049 continue;
1050
1051 for (unsigned short jet2Index = 0; jet2Index < goodJets.size(); ++jet2Index) {
1052 if (jet2Index == jet1Index || jet2Index == lepBindex || jet2Index == hadBindex
1053 || rule->hardHadronicJetFromWCondition(goodJets.at(jet2Index)))
1054 continue;
1055
1056 hadronicBJet = goodJets.at(hadBindex);
1057 leptonicBJet = goodJets.at(lepBindex);
1058 jet1FromW = goodJets.at(jet1Index);
1059 jet2FromW = goodJets.at(jet2Index);
1060
1061 leptonicW1 = ParticlePointer(new Particle(*neutrino1 + *leptonFromW));
1062 leptonicW2 = ParticlePointer(new Particle(*neutrino2 + *leptonFromW));
1063 hadronicW = ParticlePointer(new Particle(*jet1FromW + *jet2FromW));
1064 leptonicTop1 = ParticlePointer(new Particle(*leptonicBJet + *leptonicW1));
1065 leptonicTop2 = ParticlePointer(new Particle(*leptonicBJet + *leptonicW2));
1066 hadronicTop = ParticlePointer(new Particle(*hadronicBJet + *hadronicW));
1067 fillHypotheses();
1068 selectNeutrinoSolution();
1069 double TopMassDifference = calculateTopMassDifference(currentSelectedNeutrino);
1070 double chi2 = getTotalChi2(currentSelectedNeutrino);
1071 switch (usedTTbarReconstruction) {
1072 case TTbarReconstructionCriterion::TopMassDifference:
1073 if (TopMassDifference < chosen_TopMassDifference) {
1074 hadronicBIndex = hadBindex;
1075 leptonicBIndex = lepBindex;
1076 jet1FromWIndex = jet1Index;
1077 jet2FromWIndex = jet2Index;
1078 chosen_TopMassDifference = TopMassDifference;
1079 selectedNeutrino = currentSelectedNeutrino;
1080 }
1081 break;
1082
1083 case TTbarReconstructionCriterion::chi2:
1084 if (chi2 < chosen_Chi2Total) {
1085 hadronicBIndex = hadBindex;
1086 leptonicBIndex = lepBindex;
1087 jet1FromWIndex = jet1Index;
1088 jet2FromWIndex = jet2Index;
1089 chosen_Chi2Total = chi2;
1090 selectedNeutrino = currentSelectedNeutrino;
1091 }
1092 break;
1093 }
1094 }
1095 }
1096 }
1097 }
1098 compare_disc sorting;
1099 std::sort(solutions.begin(), solutions.end(), sorting);
1100 hadronicBJet = solutions.front()->hadronicBJet;
1101 leptonicBJet = solutions.front()->leptonicBjet;
1102 jet1FromW = solutions.front()->jet1FromW;
1103 jet2FromW = solutions.front()->jet2FromW;
1104 leptonicW1 = solutions.front()->leptonicW;
1105 leptonicW2 = solutions.front()->leptonicW;
1106 hadronicW = solutions.front()->hadronicW;
1107 // leptonicW1 = ParticlePointer(new Particle(*neutrino1 + *leptonFromW));
1108 // leptonicW2 = ParticlePointer(new Particle(*neutrino2 + *leptonFromW));
1109 // hadronicW = ParticlePointer(new Particle(*jet1FromW + *jet2FromW));
1110 leptonicTop1 = solutions.front()->leptonicTop;
1111 leptonicTop2 = solutions.front()->leptonicTop;
1112 hadronicTop = solutions.front()->hadronicTop;
1113 ttbarResonance = solutions.front()->resonance;
1114 if (selectedNeutrino == 1)
1115 ttbarResonance = ParticlePointer(new Particle(*leptonicTop1 + *hadronicTop));
1116 else
1117 ttbarResonance = ParticlePointer(new Particle(*leptonicTop2 + *hadronicTop));
1118 doneReconstruction = true;
1119 }
1120
1121 }