ATLAS Offline Software
Loading...
Searching...
No Matches
ZeeValidationMonitoringTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7// STL includes
8#include <vector>
9#include <cmath>
10
11// FrameWork includes
12#include "GaudiKernel/IToolSvc.h"
17#include "xAODEgamma/Egamma.h"
18#include "xAODEgamma/Electron.h"
20#include "xAODTracking/Vertex.h"
24
26
29
30using CLHEP::GeV;
31
32namespace ZeeValidation {
33
35 // Public methods:
37
38 // Constructors
40
42 const std::string& name,
43 const IInterface* parent ) :
44 ManagedMonitorToolBase( type, name, parent ),
45 m_isData(false),
46 m_ReconElectronsPlots(0, "Zee/ReconElectrons/", "Electrons"),
47 m_TrueElectronsPlots(0, "Zee/TrueElectrons/", "True Electrons"),
48 m_TrueFwdElectronsPlots(0, "Zee/TrueFwdElectrons/", "True FWD Electrons"),
49 m_ZeePlots(0, "Zee/Zee/", "Zee"),
50 m_FWDZeePlots(0, "Zee/FWDZee/", "FWD Zee"),
54 {
55 declareProperty( "IsData", m_isData = false);
56 declareProperty( "EventInfoContainerName", m_eventInfoName = "EventInfo");
57 declareProperty( "ElectronContainerName", m_elecName = "ElectronCollection" );
58 declareProperty( "ElectronContainerFrwdName", m_elecFwdName = "FwdElectrons" );
59 declareProperty( "PhotonContainerName", m_photonName = "PhotonCollection" );
60 declareProperty( "VertexContainerName", m_vertexName = "PrimaryVertices" );
61 declareProperty( "TrackParticleContainerName", m_trackName = "InDetTrackParticles" );
62 declareProperty( "TruthParticleContainerName", m_truthName = "TruthParticle");
63
64 declareProperty( "PtMinCent", m_PtCentCut = 20.0 );
65 declareProperty( "PtMinFwd", m_PtFwdCut = 15.0 );
66 declareProperty( "MeeLow", m_MeeLowCut = 66.0 );
67 declareProperty( "MeeHigh", m_MeeHighCut = 116.0 );
68 declareProperty( "EtaCent", m_EtaCentCut = 2.47 );
69 declareProperty( "EtaLowFwd", m_EtaLowFwdCut = 2.5 );
70 declareProperty( "EtaHighFwd", m_EtaHighFwdCut = 4.8 );
71 declareProperty( "EtaCrackLow", m_EtaCrackLowCut = 1.37 );
72 declareProperty( "EtaCrackHigh", m_EtaCrackHighCut = 1.52 );
73 declareProperty( "dRminRecoTrue", m_dRminRecoTrue = 0.1);
74 }
75
76 // Destructor
80
81 // Athena algtool's Hooks
84 {
85 ATH_MSG_INFO ("Initializing " << name() << "...");
87
88 return StatusCode::SUCCESS;
89 }
90
92 {
93 plots.initialize();
94 std::vector<HistData> hists = plots.retrieveBookedHistograms();
95
96 for (auto& hist : hists){
97 ATH_MSG_INFO ("Initializing " << hist.first << " " << hist.first->GetName() << " " << hist.second << "...");
98 ATH_CHECK(regHist(hist.first, hist.second,all));
99 }
100 return StatusCode::SUCCESS;
101 }
102
104 {
105 ATH_MSG_INFO ("Booking hists " << name() << "...");
106
107 if (m_detailLevel >= 10) {
109 if( !m_isData )
110 {
113 }
116 }
117
118 return StatusCode::SUCCESS;
119 }
120
122 {
123 ATH_MSG_DEBUG ("Filling hists " << name() << "...");
124 if (m_detailLevel < 10) return StatusCode::SUCCESS;
125
126 const xAOD::EventInfo* eventInfo(0);
127 ATH_CHECK(evtStore() -> retrieve(eventInfo, m_eventInfoName));
128
129 const xAOD::VertexContainer* vertices(0);
130 ATH_CHECK(evtStore() -> retrieve(vertices, m_vertexName));
131
132 const xAOD::ElectronContainer* electrons(0);
133 ATH_CHECK(evtStore() -> retrieve(electrons, m_elecName));
134
135 const xAOD::ElectronContainer* fwd_electrons(0);
136 ATH_CHECK(evtStore() -> retrieve(fwd_electrons, m_elecFwdName));
137
138 const xAOD::PhotonContainer* photons(0);
139 ATH_CHECK(evtStore() -> retrieve(photons, m_photonName));
140
142 // Reconstructed electrons
144
145 int nrecel = 0;
146 for (auto electron : *electrons){
147
148 m_ReconElectronsPlots.h_electron_author -> Fill(electron -> author());
149
150 //select electrons which passed author and pT cut
151 if (!( electron -> author(xAOD::EgammaParameters::AuthorElectron) )) continue;
152 if ( electron -> pt()*(1./GeV) < m_PtCentCut ) continue;
153 nrecel++;
154
155 bool inAcceptance = (std::abs(electron -> eta()) > m_EtaCrackHighCut || std::abs(electron -> eta()) < m_EtaCrackLowCut) && std::abs(electron -> eta()) < m_EtaCentCut;
156
157 if (inAcceptance)
158 m_ReconElectronsPlots.fill(eventInfo, vertices);
159
160 bool loose = false, medium = false, tight = false, lhloose = false, lhmedium = false, lhtight = false, oq = false;
161 electron -> passSelection(loose, "Loose");
162 electron -> passSelection(medium, "Medium");
163 electron -> passSelection(tight, "Tight");
164 electron -> passSelection(lhloose, "LHLoose");
165 electron -> passSelection(lhmedium, "LHMedium");
166 electron -> passSelection(lhtight, "LHTight");
167 if ( electron -> isGoodOQ (xAOD::EgammaParameters::BADCLUSELECTRON) ) oq = true;
168
169 //fill if passed author & pT cuts
170 m_ReconElectronsPlots.fill(electron, 0);
171 if (inAcceptance)
172 m_ReconElectronsPlots.fillinAcc(electron, 0);
173
174 if (oq){ //fill if passed OQ cuts
175 m_ReconElectronsPlots.fill(electron, 1);
176 if (inAcceptance)
177 m_ReconElectronsPlots.fillinAcc(electron, 1);
178 }
179
180 if (oq && loose){ //fill if passed OQ and Loose++ cuts
181 m_ReconElectronsPlots.fill(electron, 2);
182 if (inAcceptance)
183 m_ReconElectronsPlots.fillinAcc(electron, 2);
184 }
185
186 if (oq && medium){ //fill if passed OQ and Medium++ cuts
187 m_ReconElectronsPlots.fill(electron, 3);
188 if (inAcceptance)
189 m_ReconElectronsPlots.fillinAcc(electron, 3);
190 }
191
192 if (oq && tight){ //fill if passed OQ and Tight++ cuts
193 m_ReconElectronsPlots.fill(electron, 4);
194 if (inAcceptance)
195 m_ReconElectronsPlots.fillinAcc(electron, 4);
196 }
197
198
199 if (oq && lhloose){ //fill if passed OQ and Loose++ cuts
200 m_ReconElectronsPlots.fill(electron, 5);
201 if (inAcceptance)
202 m_ReconElectronsPlots.fillinAcc(electron, 5);
203 }
204
205 if (oq && lhmedium){ //fill if passed OQ and Medium++ cuts
206 m_ReconElectronsPlots.fill(electron, 6);
207 if (inAcceptance)
208 m_ReconElectronsPlots.fillinAcc(electron, 6);
209 }
210
211 if (oq && lhtight){ //fill if passed OQ and Tight++ cuts
212 m_ReconElectronsPlots.fill(electron, 7);
213 if (inAcceptance)
214 m_ReconElectronsPlots.fillinAcc(electron, 7);
215 }
216 //shower shape variables
217
218 m_ReconElectronsPlots.fillShowerShape( electron );
219 m_ReconElectronsPlots.fillIsolation( electron );
220 //track variables
221 const xAOD::TrackParticle* track = electron -> trackParticle();
222 if (track){
223 m_ReconElectronsPlots.fillHitInfo( electron );
224 m_ReconElectronsPlots.fillTrackCaloMatch( electron, track );
225 }
226
227 }
228 m_ReconElectronsPlots.h_electron_n -> Fill(nrecel);
229 m_ReconElectronsPlots.h_photon_n -> Fill(photons -> size());
230
232 // Truth electrons
234 if( !m_isData )
235 {
236 const xAOD::TruthParticleContainer* truth_particles(0);
237 ATH_CHECK(evtStore() -> retrieve(truth_particles, m_truthName));
238
239 for(auto truth_part : *truth_particles)
240 {
241 // Select truth particle which passed pT, eta cuts and have pid=11
242 if( std::abs(truth_part -> pdgId()) != 11 || !MC::isStable(truth_part) || HepMC::is_simulation_particle(truth_part) ) continue;
243 if( truth_part -> pt()*(1./GeV) < m_PtCentCut ) continue;
244 if(std::abs(truth_part -> eta()) > m_EtaCentCut ) continue;
245
246 bool inAcceptance = std::abs(truth_part -> eta()) > m_EtaCrackHighCut || std::abs(truth_part -> eta()) < m_EtaCrackLowCut;
247 // Fill plots with all truth particles passed cuts
248 m_TrueElectronsPlots.fill(truth_part, 0);
249 if( inAcceptance )
250 m_TrueElectronsPlots.fillinAcc(truth_part, 0);
251
252 MatchElec(truth_part, electrons); // Matching to reconstructed electrons
253 MatchPhot(truth_part, photons); // Matching to reconstructed photons
254
255 if( m_matchedE && m_drmin_elreco_truth < m_dRminRecoTrue) { //if matched to reconstructed electron
256 m_TrueElectronsPlots.fill(truth_part, 1); //fill "associated" plots: if matched to electron or photon
257 m_TrueElectronsPlots.fill(truth_part, 2); //fill "matched" plots: if matched to electron
258
259 if( inAcceptance )
260 {
261 m_TrueElectronsPlots.fillinAcc(truth_part, 1);
262 m_TrueElectronsPlots.fillinAcc(truth_part, 2);
263 }
264
265 bool loose = false, medium = false, tight = false, lhloose = false, lhmedium = false, lhtight = false, oq = false;
266 m_matched_electron -> passSelection(loose, "Loose");
267 m_matched_electron -> passSelection(medium, "Medium");
268 m_matched_electron -> passSelection(tight, "Tight");
269 m_matched_electron -> passSelection(lhloose, "LHLoose");
270 m_matched_electron -> passSelection(lhmedium, "LHMedium");
271 m_matched_electron -> passSelection(lhtight, "LHTight");
272 if ( m_matched_electron -> isGoodOQ (xAOD::EgammaParameters::BADCLUSELECTRON) ) oq = true;
273
274 if (oq) //fill if passed OQ cuts
275 m_TrueElectronsPlots.fill(truth_part, 3);
276 if (oq && loose) //fill if passed OQ and Loose++ cuts
277 m_TrueElectronsPlots.fill(truth_part, 4);
278 if (oq && medium ) //fill if passed OQ and Medium++ cuts
279 m_TrueElectronsPlots.fill(truth_part, 5);
280 if (oq && tight ) //fill if passed OQ and Tight++ cuts
281 m_TrueElectronsPlots.fill(truth_part, 6);
282 if (oq && lhloose) //fill if passed OQ and LHLoose++ cuts
283 m_TrueElectronsPlots.fill(truth_part, 7);
284 if (oq && lhmedium ) //fill if passed OQ and LHMedium++ cuts
285 m_TrueElectronsPlots.fill(truth_part, 8);
286 if (oq && lhtight ) //fill if passed OQ and LHTight++ cuts
287 m_TrueElectronsPlots.fill(truth_part, 9);
288
289 if (inAcceptance){
290 if (oq)
291 m_TrueElectronsPlots.fillinAcc(truth_part, 3);
292 if (oq && loose)
293 m_TrueElectronsPlots.fillinAcc(truth_part, 4);
294 if (oq && medium )
295 m_TrueElectronsPlots.fillinAcc(truth_part, 5);
296 if (oq && tight )
297 m_TrueElectronsPlots.fillinAcc(truth_part, 6);
298 if (oq && lhloose)
299 m_TrueElectronsPlots.fillinAcc(truth_part, 7);
300 if (oq && lhmedium )
301 m_TrueElectronsPlots.fillinAcc(truth_part, 8);
302 if (oq && lhtight )
303 m_TrueElectronsPlots.fillinAcc(truth_part, 9);
304 }
305
306 //fill plots for electron energy response
307 m_TrueElectronsPlots.fillResponse( truth_part, m_matched_electron);
308 const xAOD::CaloCluster* cluster = m_matched_electron -> caloCluster();
309 if (cluster)
310 m_TrueElectronsPlots.fillResponseCluster( truth_part, cluster );
311 }
312
313 if (!(m_matchedE && m_drmin_elreco_truth < m_dRminRecoTrue) && m_drmin_phreco_truth < m_dRminRecoTrue){ //if matched to reconstructed photon
314 m_TrueElectronsPlots.h_dr_photon -> Fill( m_drmin_phreco_truth );
315
316 m_TrueElectronsPlots.fill(truth_part, 1); //fill "associated" plots: if matched to electron or photon
317 if (inAcceptance)
318 m_TrueElectronsPlots.fillinAcc(truth_part, 1);
319 }
320
321 }
322
324 // Truth FWD electrons
326
327 for (auto truth_part : *truth_particles){
328
329 //select truth particle which passed fwd pT, eta cuts and have pid=11
330 if ( std::abs(truth_part -> pdgId()) != 11 || !MC::isStable(truth_part) || HepMC::is_simulation_particle(truth_part) ) continue;
331 if ( truth_part -> pt()*(1./GeV) < m_PtFwdCut ) continue;
332 if (std::abs( truth_part -> eta() ) < m_EtaLowFwdCut || std::abs( truth_part -> eta() ) > m_EtaHighFwdCut ) continue;
333
334 //fill plots with all truth particles passed fwd cuts
335 m_TrueFwdElectronsPlots.fill(truth_part, 0);
336
337 MatchElec(truth_part, fwd_electrons);
338 if (m_matchedE && m_drmin_elreco_truth < m_dRminRecoTrue){ //if matched to reconstructed electron
339 m_TrueFwdElectronsPlots.fill(truth_part, 1);
340
341 bool loose = false, tight = false;
342 m_matched_electron -> passSelection(loose, "Loose");
343 m_matched_electron -> passSelection(tight, "Tight");
344
345 if (loose) //fill if passed Loose++ cuts
346 m_TrueFwdElectronsPlots.fill(truth_part, 2);
347 if (tight) //fill if passed Tight++ cuts
348 m_TrueFwdElectronsPlots.fill(truth_part, 3);
349
350 //fill plots for electron energy response
351 m_TrueFwdElectronsPlots.fillResponse( truth_part, m_matched_electron);
352
353 }
354 }
355
356 } // if( !m_isData )
357
359 // Z->ee
361
362 const xAOD::Electron *z_el[2] = {0, 0};
363
364 int nel = 0;
365 // first electron loop: collect "good" electrons passing pT, OQ and Medium++ selection
366 for (auto electron : *electrons){
367
368 if (!( electron -> author(xAOD::EgammaParameters::AuthorElectron) )) continue;
369 if (!( electron -> isGoodOQ (xAOD::EgammaParameters::BADCLUSELECTRON) )) continue;
370 if ( electron -> pt()*(1./GeV) < m_PtCentCut ) continue;
371
372 bool medium = false;
373 electron -> passSelection(medium, "Medium");
374 if (medium == false) continue;
375
376 if (nel == 0) {
377 z_el[0] = electron;
378 } else if (nel >= 1 && electron -> pt() > z_el[0] -> pt()) {
379 z_el[1] = z_el[0];
380 z_el[0] = electron;
381 } else if (nel == 1 || (nel >= 2 && electron -> pt() > z_el[1] -> pt())) {
382 z_el[1] = electron;
383 }
384 nel++;
385 }
386
387 // if number of electrons after the first loop < 2, second electron loop:
388 // collect electrons passing pT and at least one of OQ or Medium++ cuts
389 if ( nel < 2 ){
390
391 for (auto electron : *electrons){
392
393 if (!( electron -> author(xAOD::EgammaParameters::AuthorElectron) )) continue;
394 if ( electron -> pt()*(1./GeV) < m_PtCentCut ) continue;
395
396 bool medium = false;
397 electron -> passSelection(medium, "Medium");
398 //to avoid double counting
399 if (( electron -> isGoodOQ(xAOD::EgammaParameters::BADCLUSELECTRON) ) && (medium == true)) continue;
400
401 if (nel == 0) {
402 z_el[0] = electron;
403 } else if (nel >= 1 && electron -> pt() > z_el[0] -> pt()) {
404 z_el[1] = z_el[0];
405 z_el[0] = electron;
406 } else if (nel == 1 || (nel >= 2 && electron -> pt() > z_el[1] -> pt())) {
407 z_el[1] = electron;
408 }
409 nel++;
410 }
411
412 }
413
414 // if number of electrons after the second loop < 2, third electron loop:
415 // collect electrons passing pT cut
416 if ( nel < 2 ){
417
418 for (auto electron : *electrons){
419
420 if (!( electron -> author(xAOD::EgammaParameters::AuthorElectron) )) continue;
421 //to avoid double counting
422 if ( electron -> pt()*(1./GeV) >= m_PtCentCut ) continue;
423
424 if (nel == 0) {
425 z_el[0] = electron;
426 } else if (nel >= 1 && electron -> pt() > z_el[0] -> pt()) {
427 z_el[1] = z_el[0];
428 z_el[0] = electron;
429 } else if (nel == 1 || (nel >= 2 && electron -> pt() > z_el[1] -> pt())) {
430 z_el[1] = electron;
431 }
432 nel++;
433 }
434
435 }
436
437 //if selected at least two electrons
438 if( nel >= 2 ){
439
440 TLorentzVector el4v[2], elclus4v[2], eltrack4v[2];
441 bool inAcceptance[2];
442 for (int i = 0; i < 2; i++) {
443 el4v[i] = z_el[i] -> p4();
444
445 const xAOD::CaloCluster* cluster = z_el[i] -> caloCluster();
446 if (cluster)
447 elclus4v[i] = z_el[i]->caloCluster()-> p4();
448
449 const xAOD::TrackParticle* trackp = z_el[i] -> trackParticle();
450
451 if (trackp){
452
453 eltrack4v[i] = trackp -> p4();
454 uint8_t iPixHits, iSCTHits;
455 bool hits = false;
456 hits = trackp -> summaryValue(iPixHits, xAOD::numberOfPixelHits);
457 hits &= trackp -> summaryValue(iSCTHits, xAOD::numberOfSCTHits);
458
459 if (hits&& (iPixHits + iSCTHits > 3)){
460
461 double e = z_el[i] -> caloCluster() -> e();
462
463 double eta = trackp -> eta();
464 double phi = trackp -> phi();
465 // Create tlv
466 double m = 0;
467 double p = std::sqrt(e*e - m*m);
468 double pt = p * 1/std::cosh(eta);
469 double px = pt * std::cos(phi);
470 double py = pt * std::sin(phi);
471 double pz = p * std::tanh(eta);
472
473 el4v[i] = TLorentzVector(px, py, pz, e);
474 }
475 }
476 inAcceptance[i] = (std::abs(elclus4v[i].Eta()) > m_EtaCrackHighCut || std::abs(elclus4v[i].Eta()) < m_EtaCrackLowCut) && std::abs(elclus4v[i].Eta()) < m_EtaCentCut;
477 }
478
479 TLorentzVector z = el4v[0] + el4v[1];
480
481 bool z_passed_cuts = true;
482 bool OS = true;
483
484 bool bothLoose = false, bothMedium = false, bothTight = false, bothOQ = false;
485 bool loose1 = false, loose2 = false, medium1 = false, medium2 = false, tight1 = false, tight2 = false;
486
487 z_el[0] -> passSelection(loose1, "Loose");
488 z_el[1] -> passSelection(loose2, "Loose");
489 z_el[0] -> passSelection(medium1, "Medium");
490 z_el[1] -> passSelection(medium2, "Medium");
491 z_el[0] -> passSelection(tight1, "Tight");
492 z_el[1] -> passSelection(tight2, "Tight");
493
494 if ( z_el[0] -> isGoodOQ(xAOD::EgammaParameters::BADCLUSELECTRON) && z_el[1] -> isGoodOQ(xAOD::EgammaParameters::BADCLUSELECTRON) ) bothOQ = true;
495 if ( loose1 && loose2 ) bothLoose = true;
496 if ( medium1 && medium2 ) bothMedium = true;
497 if ( tight1 && tight2 ) bothTight = true;
498
499 if (elclus4v[0].Perp()*(1./GeV) < m_PtCentCut || !inAcceptance[0]) z_passed_cuts = false;
500 if (elclus4v[1].Perp()*(1./GeV) < m_PtCentCut || !inAcceptance[1]) z_passed_cuts = false;
501
502 if (z_passed_cuts){
503 m_ZeePlots.fillGenPlots(nel);
504 }
505
506 if (z.M()*(1./GeV) < m_MeeLowCut || z.M()*(1./GeV) > m_MeeHighCut) z_passed_cuts = false;
507 if (z_el[0] -> charge() + z_el[1] -> charge() != 0) OS = false;
508
509 //10 plot levels: Reco OS, OQ OS, Loose OS, Medium OS, Tight OS, Reco SS, OQ SS, Loose SS, Medium SS, Tight SS
510 if(z_passed_cuts && OS){ //fill OS plots if Z passed selection: mass cut, each electron cluster passed pT cut and is out of crack region
511 m_ZeePlots.fillZPlots(z, 0);
512 m_ZeePlots.fillElectronPlots(el4v[0], el4v[1], elclus4v[0], elclus4v[1], eltrack4v[0], eltrack4v[1], z_el[0] -> charge(), z_el[1] -> charge(), 0);
513
514 if (bothOQ){ //if both electrons passed OQ cuts
515 m_ZeePlots.fillZPlots(z, 1);
516 m_ZeePlots.fillElectronPlots(el4v[0], el4v[1], elclus4v[0], elclus4v[1], eltrack4v[0], eltrack4v[1], z_el[0] -> charge(), z_el[1] -> charge(), 1);
517 }
518 if (bothLoose){ //if both electrons passed Loose++ cuts
519 m_ZeePlots.fillZPlots(z, 2);
520 m_ZeePlots.fillElectronPlots(el4v[0], el4v[1], elclus4v[0], elclus4v[1], eltrack4v[0], eltrack4v[1], z_el[0] -> charge(), z_el[1] -> charge(), 2);
521 }
522 if (bothMedium){ //if both electrons passed Medium++ cuts
523 m_ZeePlots.fillZPlots(z, 3);
524 m_ZeePlots.fillElectronPlots(el4v[0], el4v[1], elclus4v[0], elclus4v[1], eltrack4v[0], eltrack4v[1], z_el[0] -> charge(), z_el[1] -> charge(), 3);
525 }
526 if (bothTight){ //if both electrons passed Tight++ cuts
527 m_ZeePlots.fillZPlots(z, 4);
528 m_ZeePlots.fillElectronPlots(el4v[0], el4v[1], elclus4v[0], elclus4v[1], eltrack4v[0], eltrack4v[1], z_el[0] -> charge(), z_el[1] -> charge(), 4);
529 }
530 } //end if Z passed selection and OS
531
532 if(z_passed_cuts && !OS){ //fill SS plots if Z passed selection: mass cut, each electron cluster passed pT cut and is out of crack region
533 m_ZeePlots.fillZPlots(z, 5);
534 m_ZeePlots.fillElectronPlots(el4v[0], el4v[1], elclus4v[0], elclus4v[1], eltrack4v[0], eltrack4v[1], z_el[0] -> charge(), z_el[1] -> charge(), 5);
535
536 if (bothOQ){//if both electrons passed OQ cuts
537 m_ZeePlots.fillZPlots(z, 6);
538 m_ZeePlots.fillElectronPlots(el4v[0], el4v[1], elclus4v[0], elclus4v[1], eltrack4v[0], eltrack4v[1], z_el[0] -> charge(), z_el[1] -> charge(), 6);
539 }
540 if (bothLoose){ //if both electrons passed Loose++ cuts
541 m_ZeePlots.fillZPlots(z, 7);
542 m_ZeePlots.fillElectronPlots(el4v[0], el4v[1], elclus4v[0], elclus4v[1], eltrack4v[0], eltrack4v[1], z_el[0] -> charge(), z_el[1] -> charge(), 7);
543 }
544 if (bothMedium){//if both electrons passed Medium++ cuts
545 m_ZeePlots.fillZPlots(z, 8);
546 m_ZeePlots.fillElectronPlots(el4v[0], el4v[1], elclus4v[0], elclus4v[1], eltrack4v[0], eltrack4v[1], z_el[0] -> charge(), z_el[1] -> charge(), 8);
547 }
548 if (bothTight){
549 m_ZeePlots.fillZPlots(z, 9); //if both electrons passed Tight++ cuts
550 m_ZeePlots.fillElectronPlots(el4v[0], el4v[1], elclus4v[0], elclus4v[1], eltrack4v[0], eltrack4v[1], z_el[0] -> charge(), z_el[1] -> charge(), 9);
551 }
552 } //end if Z passed cut and SS
553
554 }
555
557 // Fwd Z->ee
559
560 const xAOD::Electron *zfwd_el[2] = {0, 0};
561 int nelcent = 0;
562 int nelfwd = 0;
563
564 // first electron loop: collect "good" electrons passing pT, OQ and Medium++ selection
565 for (auto electron : *electrons){
566 //
567 if (!( electron -> author(xAOD::EgammaParameters::AuthorElectron) )) continue;
568 if (!( electron -> isGoodOQ(xAOD::EgammaParameters::BADCLUSELECTRON) )) continue;
569 if ( electron -> pt()*(1./GeV) < m_PtCentCut ) continue;
570
571 bool medium = false;
572 electron -> passSelection(medium, "Medium");
573 if (medium == false) continue;
574
575 if (nelcent == 0) {
576 zfwd_el[0] = electron;
577 } else if (nelcent >= 1 && electron -> pt() > zfwd_el[0] -> pt()) {
578 zfwd_el[0] = electron;
579 }
580 nelcent++;
581 }
582 //if exactly one "good" central electron selected then loop over forward electrons
583 if (nelcent == 1){
584 for (auto fwd_electron : *fwd_electrons){ //first loop: collect fwd Tight++ electrons passed pT cut
585
586 if (!( fwd_electron -> author(xAOD::EgammaParameters::AuthorFwdElectron) )) continue;
587 if ( fwd_electron -> pt()*(1./GeV) < m_PtFwdCut ) continue;
588
589 bool tight = false;
590 fwd_electron -> passSelection(tight, "Tight");
591 if (tight == false) continue;
592
593 if (nelfwd == 0) {
594 zfwd_el[1] = fwd_electron;
595 } else if (nelfwd >= 1 && fwd_electron -> pt() > zfwd_el[1] -> pt()) {
596 zfwd_el[1] = fwd_electron;
597 }
598 nelfwd++;
599 }
600
601 if (nelfwd==0) //if no Tight++ electrons selected collect fwd Loose++ electrons passed pT cut
602 for (auto fwd_electron : *fwd_electrons){
603
604 if (!( fwd_electron -> author(xAOD::EgammaParameters::AuthorFwdElectron) )) continue;
605 if ( fwd_electron -> pt()*(1./GeV) < m_PtFwdCut ) continue;
606
607 bool loose = false;
608 fwd_electron -> passSelection(loose, "Loose");
609 if (loose == false) continue;
610
611 if (nelfwd == 0) {
612 zfwd_el[1] = fwd_electron;
613 } else if (nelfwd >= 1 && fwd_electron -> pt() > zfwd_el[1] -> pt()) {
614 zfwd_el[1] = fwd_electron;
615 }
616 nelfwd++;
617 }
618
619 if (nelfwd==0) //if no Tight++ or Loose++ electrons selected collect remaining electrons
620 for (auto fwd_electron : *fwd_electrons){
621
622 if (!( fwd_electron -> author(xAOD::EgammaParameters::AuthorFwdElectron) )) continue;
623
624 if (nelfwd == 0) {
625 zfwd_el[1] = fwd_electron;
626 } else if (nelfwd >= 1 && fwd_electron -> pt() > zfwd_el[1] -> pt()) {
627 zfwd_el[1] = fwd_electron;
628 }
629 nelfwd++;
630 }
631
632 //if fwd electron was found
633 if (nelfwd > 0){
634
635 TLorentzVector elfwd4v[2];
636 bool inAcceptance[2];
637
638 // rebuild central electron 4v
639 double e = zfwd_el[0] -> caloCluster() -> e();
640 double etaclus = zfwd_el[0] -> caloCluster() -> eta();
641 double eta = zfwd_el[0] -> trackParticle() -> eta();
642 double phi = zfwd_el[0] -> trackParticle() -> phi();
643 // Create tlv
644 float pt = e * 1/std::cosh(eta);
645 float px = pt * std::cos(phi);
646 float py = pt * std::sin(phi);
647 float pz = e * std::tanh(eta);
648
649 elfwd4v[0] = TLorentzVector(px, py, pz, e);
650 inAcceptance[0] = (std::abs(etaclus) > m_EtaCrackHighCut || std::abs(etaclus) < m_EtaCrackLowCut) && std::abs(etaclus) < m_EtaCentCut;
651
652 elfwd4v[1] = zfwd_el[1] -> p4();
653 inAcceptance[1] = std::abs(elfwd4v[1].Eta()) > m_EtaLowFwdCut && std::abs(elfwd4v[1].Eta()) < m_EtaHighFwdCut;
654
655 bool tight_cent = false, loose_fwd = false, tight_fwd = false;
656 bool oq_fwd = false;
657 float ptcone40_value = -100;
658 zfwd_el[0] -> passSelection(tight_cent, "Tight");
659 zfwd_el[1] -> passSelection(loose_fwd, "Loose");
660 zfwd_el[1] -> passSelection(tight_fwd, "Tight");
661 zfwd_el[0] -> isolationValue(ptcone40_value, xAOD::Iso::ptcone40);
662
663 if (zfwd_el[1] -> isGoodOQ (xAOD::EgammaParameters::BADCLUSELECTRON) ) oq_fwd = true;
664
665 TLorentzVector zfwd = elfwd4v[0] + elfwd4v[1];
666
667 bool zfwd_passed_cuts = true;
668 if ( !(tight_cent && ptcone40_value < 2000.)) zfwd_passed_cuts = false;
669 if (zfwd.M()*(1./GeV) < m_MeeLowCut|| zfwd.M()*(1./GeV) >= m_MeeHighCut) zfwd_passed_cuts = false;
670 if (elfwd4v[0].Perp()*(1./GeV) < m_PtCentCut || !inAcceptance[0]) zfwd_passed_cuts = false;
671 if (elfwd4v[1].Perp()*(1./GeV) < m_PtFwdCut || !inAcceptance[1]) zfwd_passed_cuts = false;
672
673 if(zfwd_passed_cuts){ //fill plots if Z passed selection: mass cut, central electron Tight++, each electron passed corresponding pT cut and is out of crack regions
674 m_FWDZeePlots.fillZPlots(zfwd, 0);
675 m_FWDZeePlots.fillElPlots(elfwd4v[0], elfwd4v[1], 0);
676
677 if (oq_fwd){ // fwd electron passed OQ cut
678 m_FWDZeePlots.fillZPlots(zfwd, 1);
679 m_FWDZeePlots.fillElPlots(elfwd4v[0], elfwd4v[1], 1);
680 }
681 if (loose_fwd){ // fwd electron passed Loose++ cut
682 m_FWDZeePlots.fillZPlots(zfwd, 2);
683 m_FWDZeePlots.fillElPlots(elfwd4v[0], elfwd4v[1], 2);
684 }
685 if (tight_fwd){ // fwd electron passed Tight++ cut
686 m_FWDZeePlots.fillZPlots(zfwd, 3);
687 m_FWDZeePlots.fillElPlots(elfwd4v[0], elfwd4v[1], 3);
688 }
689
690 }
691
692 }
693
694 } //end if one central electron
696 return StatusCode::SUCCESS;
697 }
698
700 {
701 ATH_MSG_INFO ("Finalising hists " << name() << "...");
702 //fill efficiencies
703 m_ReconElectronsPlots.finalize();
704 if( !m_isData )
705 {
706 m_TrueElectronsPlots.finalize();
707 m_TrueFwdElectronsPlots.finalize();
708 }
709 m_ZeePlots.finalize();
710 m_FWDZeePlots.finalize();
711
712 return StatusCode::SUCCESS;
713 }
714
718 m_drmin_elreco_truth = 9999.;
719 m_matched_electron = nullptr;
720 m_matchedE = false;
721
722 for (auto electron : *electrons){
723 double dr_reco_truth = truth_electron -> p4().DeltaR(electron -> p4());
724
725 if (dr_reco_truth < m_drmin_elreco_truth){
726 m_drmin_elreco_truth = dr_reco_truth;
727 m_matched_electron = electron;
728 m_matchedE = true;
729 }
730 }
731
732 return;
733 }
734
738 m_drmin_phreco_truth = 9999.;
739 m_matchedP = false;
740
741 for (auto photon : *photons){
742 double dr_reco_truth = truth_electron -> p4().DeltaR(photon -> p4());
743
744 if (dr_reco_truth < m_drmin_phreco_truth){
745 m_drmin_phreco_truth = dr_reco_truth;
746 m_matchedP = true;
747 }
748 }
749
750 return;
751 }
752
753}
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_INFO(x)
#define ATH_MSG_DEBUG(x)
double charge(const T &p)
Definition AtlasPID.h:997
ATLAS-specific HepMC functions.
@ Eta
Definition RPCdef.h:8
#define z
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
ServiceHandle< StoreGateSvc > & evtStore()
virtual StatusCode regHist(TH1 *h, const std::string &system, Interval_t interval, MgmtAttr_t histo_mgmt=ATTRIB_MANAGED, const std::string &chain="", const std::string &merge="")
Registers a TH1 (including TH2, TH3, and TProfile) to be included in the output stream using logical ...
ManagedMonitorToolBase(const std::string &type, const std::string &name, const IInterface *parent)
void MatchElec(const xAOD::TruthParticle *truth_electron, const xAOD::ElectronContainer *electrons)
ZeeValidation::ReconElectronsPlots m_ReconElectronsPlots
ZeeValidationMonitoringTool()
Default constructor:
ZeeValidation::TrueFwdElectronsPlots m_TrueFwdElectronsPlots
ZeeValidation::TrueElectronsPlots m_TrueElectronsPlots
virtual StatusCode procHistograms()
An inheriting class should either override this function or finalHists().
virtual StatusCode fillHistograms()
An inheriting class should either override this function or fillHists().
void MatchPhot(const xAOD::TruthParticle *truth_electron, const xAOD::PhotonContainer *photons)
virtual StatusCode bookHistograms()
An inheriting class should either override this function or bookHists().
const xAOD::CaloCluster * caloCluster(size_t index=0) const
Pointer to the xAOD::CaloCluster/s that define the electron candidate.
bool is_simulation_particle(const T &p)
Method to establish if a particle (or barcode) was created during the simulation (TODO update to be s...
bool isStable(const T &p)
Identify if the particle is stable, i.e. has not decayed.
const uint32_t BADCLUSELECTRON
Definition EgammaDefs.h:116
const uint16_t AuthorElectron
Object Reconstructed by standard cluster-based algorithm.
Definition EgammaDefs.h:24
const uint16_t AuthorFwdElectron
Electron reconstructed by the Forward cluster-based algorithm.
Definition EgammaDefs.h:30
PhotonContainer_v1 PhotonContainer
Definition of the current "photon container version".
ElectronContainer_v1 ElectronContainer
Definition of the current "electron container version".
EventInfo_v1 EventInfo
Definition of the latest event info version.
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
TrackParticle_v1 TrackParticle
Reference the current persistent version:
VertexContainer_v1 VertexContainer
Definition of the current "Vertex container version".
TruthParticle_v1 TruthParticle
Typedef to implementation.
@ numberOfSCTHits
number of hits in SCT [unit8_t].
@ numberOfPixelHits
these are the pixel hits, including the b-layer [unit8_t].
TruthParticleContainer_v1 TruthParticleContainer
Declare the latest version of the truth particle container.
Electron_v1 Electron
Definition of the current "egamma version".