ATLAS Offline Software
Loading...
Searching...
No Matches
Electrons.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5// This source file implements all of the functions related to Electrons
6// in the SUSYObjDef_xAOD class
7
8// Local include(s):
10
14
25
28//disable #include "IsolationSelection/IIsolationLowPtPLVTool.h"
29
31
32//disable #include "PATCore/TResult.h"
33
34// For getting the beam spot information
36
37#ifndef XAOD_STANDALONE // For now metadata is Athena-only
39#endif
40
41namespace ST {
42
43 const static SG::Decorator<char> dec_passSignalID("passSignalID");
44 const static SG::ConstAccessor<char> acc_passSignalID("passSignalID");
45
46 const static SG::Decorator<char> dec_passChID("passChID");
47 const static SG::ConstAccessor<char> acc_passChID("passChID");
48 const static SG::Decorator<double> dec_ecisBDT("ecisBDT");
49
50 const static SG::Decorator<float> dec_sfChIDEff("chargeIDEffiSF"); //tools' default
51 const static SG::ConstAccessor<float> acc_sfChIDEff("chargeIDEffiSF"); //tools' default
52
53 const static SG::Decorator<float> dec_z0sinTheta("z0sinTheta");
54 const static SG::Decorator<float> dec_d0sig("d0sig");
55 const static SG::Decorator<char> dec_isLRT("isLRT");
56 const static SG::ConstAccessor<char> acc_isLRT("isLRT");
57
58 const static SG::ConstAccessor<char> acc_passECIDS("DFCommonElectronsECIDS"); // Loose 97% WP
59
60
61StatusCode SUSYObjDef_xAOD::MergeElectrons(const xAOD::ElectronContainer & electrons, xAOD::ElectronContainer* outputCol, const std::set<const xAOD::Electron *> &ElectronsToRemove) const{
62
63 if (electrons.empty()) return StatusCode::SUCCESS;
64 for (const xAOD::Electron* electron: electrons) {
65 if (ElectronsToRemove.find(electron) != ElectronsToRemove.end()){
66 ATH_MSG_DEBUG( "Removing electron from output collection (isLRT?) : ("<< static_cast<int>(acc_isLRT(*electron)) << ")" );
67 ATH_MSG_DEBUG( "ELECTRON cl eta: " << electron->caloCluster()->eta());
68 ATH_MSG_DEBUG( "ELECTRON cl phi: " << electron->caloCluster()->phi());
69 continue;
70 // add electron into output
71 } else {
72 ATH_MSG_DEBUG( "Adding electron to output collection (isLRT?) : (" << static_cast<int>(acc_isLRT(*electron)) << ")" );
73 ATH_MSG_DEBUG( "ELECTRON cl eta: " << electron->caloCluster()->eta());
74 ATH_MSG_DEBUG( "ELECTRON cl phi: " << electron->caloCluster()->phi());
75 auto newElectron = new xAOD::Electron(*electron);
76
77 if ( getOriginalObject(*electron) != nullptr ) {
79 } else {
80 setOriginalObjectLink(*electron, *newElectron);
81 }
82
83 outputCol->push_back(newElectron);
84 }
85 }
86 return StatusCode::SUCCESS;
87}
88
89
91 for (const xAOD::Electron *electron: *inElectrons){
92 const xAOD::TrackParticle* idtrack = electron->trackParticle();
93
94 // Save electron if the id track passes the LRT filter
95 if ( acc_lrtFilter.isAvailable(*idtrack) )
96 {
97 if ( static_cast<int>(acc_lrtFilter(*idtrack) ) ){
98 std::unique_ptr<xAOD::Electron> copyElectron = std::make_unique<xAOD::Electron>(*electron);
99
100 // transfer original electron link
101
102 setOriginalObjectLink(*electron, *copyElectron);
103 copy->push_back( std::move(copyElectron) );
104 }
105 }
106 else // Keep electron if flag is not available
107 {
108 std::unique_ptr<xAOD::Electron> copyElectron = std::make_unique<xAOD::Electron>(*electron);
109
110 setOriginalObjectLink(*electron, *copyElectron);
111 copy->push_back( std::move(copyElectron) );
112 }
113 }
114 return StatusCode::SUCCESS;
115}
116
117
118StatusCode SUSYObjDef_xAOD::GetElectrons(xAOD::ElectronContainer*& copy, xAOD::ShallowAuxContainer*& copyaux, bool recordSG, const std::string& elekey, const std::string& lrtelekey, const xAOD::ElectronContainer* containerToBeCopied)
119{
120 if (!m_tool_init) {
121 ATH_MSG_ERROR("SUSYTools was not initialized!!");
122 return StatusCode::FAILURE;
123 }
124
125 // Initializing prompt/LRT OR procedure
126 auto outputCol = std::make_unique<xAOD::ElectronContainer>();
127 std::unique_ptr<xAOD::ElectronAuxContainer> outputAuxCol;
128 outputAuxCol = std::make_unique<xAOD::ElectronAuxContainer>();
129 outputCol->setStore(outputAuxCol.get());
130 ATH_CHECK( m_outElectronLocation.initialize() );
131
132 if (bool(m_eleLRT) && !lrtelekey.empty() && evtStore()->contains<xAOD::ElectronContainer>(lrtelekey)){
133 ATH_MSG_DEBUG("Applying prompt/LRT electron OR procedure");
134
135 // First identify if merged container has already been made (for instances where GetElectrons() is called more than once)
136 if (evtStore()->contains<xAOD::ElectronContainer>("StdWithLRTElectrons")) {
137 ATH_MSG_DEBUG("Merged prompt/LRT container already created in TStore");
138 } else {
139 ATH_MSG_DEBUG("Creating merged prompt/LRT container in TStore");
140
141 // Retrieve prompt and LRT electrons from TStore
142 ATH_CHECK( evtStore()->retrieve(prompt_electrons, elekey) );
143 ATH_CHECK( evtStore()->retrieve(lrt_electrons, lrtelekey) );
144
145 // Remove LRT electrons as flagged by filter for uncertainty
146 auto filtered_electrons = std::make_unique<xAOD::ElectronContainer>();
147 std::unique_ptr<xAOD::ElectronAuxContainer> filtered_electrons_aux = std::make_unique<xAOD::ElectronAuxContainer>();
148 filtered_electrons->setStore(filtered_electrons_aux.get());
149 ATH_CHECK(prepareLRTElectrons(lrt_electrons, filtered_electrons.get()));
150
151 // Check overlap between prompt and LRT collections
152 std::set<const xAOD::Electron *> ElectronsToRemove;
153 m_elecLRTORTool->checkOverlap(*prompt_electrons, *filtered_electrons, ElectronsToRemove);
154
155 // Decorate electrons with prompt/LRT
156 for (const xAOD::Electron* el : *prompt_electrons) dec_isLRT(*el) = 0;
157 for (const xAOD::Electron* el : *filtered_electrons) dec_isLRT(*el) = 1;
158
159 // Create merged StdWithLRTElectrons container
160 outputCol->reserve(prompt_electrons->size() + filtered_electrons->size());
161 ATH_CHECK(MergeElectrons(*prompt_electrons, outputCol.get(), ElectronsToRemove ));
162 ATH_CHECK(MergeElectrons(*filtered_electrons, outputCol.get(), ElectronsToRemove ));
163
164 // Save merged StdWithLRTElectrons container to TStore
165 ATH_CHECK(evtStore()->record(std::move(outputCol), m_outElectronLocation.key()));
166 ATH_CHECK(evtStore()->record(std::move(outputAuxCol), m_outElectronLocation.key() + "Aux.") );
167 }
168 } else if (!lrtelekey.empty()) {
169 if(evtStore()->contains<xAOD::ElectronContainer>(lrtelekey) == false && bool(m_eleLRT) == true) ATH_MSG_WARNING("prompt/LRT OR procedure attempted but " << lrtelekey << " not in ROOT file, check config!");
170 ATH_MSG_DEBUG("Not applying prompt/LRT electron OR procedure");
171 }
172
173 if (m_isPHYSLITE && elekey.find("AnalysisElectrons")==std::string::npos){
174 ATH_MSG_ERROR("You are running on PHYSLITE derivation. Please change the Electrons container to 'AnalysisElectrons'");
175 return StatusCode::FAILURE;
176 }
177
178 const xAOD::ElectronContainer* electrons = nullptr;
179 if (bool(m_eleLRT) && evtStore()->contains<xAOD::ElectronContainer>(lrtelekey)){
180 ATH_MSG_DEBUG("Using container: " << m_outElectronLocation.key());
181 ATH_CHECK( evtStore()->retrieve(electrons, m_outElectronLocation.key()));
182 }
183 else {
184 if (copy==nullptr) { // empty container provided
185 ATH_MSG_DEBUG("Empty container provided");
186 if (containerToBeCopied != nullptr) {
187 ATH_MSG_DEBUG("Containter to be copied not nullptr");
188 electrons = containerToBeCopied;
189 }
190 else {
191 ATH_MSG_DEBUG("Getting Electrons collection");
192 ATH_CHECK( evtStore()->retrieve(electrons, elekey) );
193 }
194 }
195 }
196
197 if (copy==nullptr) { // empty container provided
199 copy = shallowcopy.first.get();
200 copyaux = shallowcopy.second.get();
201 bool setLinks = xAOD::setOriginalObjectLink(*electrons, *copy);
202 if (!setLinks) {
203 ATH_MSG_WARNING("Failed to set original object links on " << elekey);
204 }
205 if (recordSG) {
206 ATH_CHECK( evtStore()->record(std::move(shallowcopy.first), "STCalib" + elekey + m_currentSyst.name()) );
207 ATH_CHECK( evtStore()->record(std::move(shallowcopy.second), "STCalib" + elekey + m_currentSyst.name() + "Aux.") );
208 } else {
209 ATH_MSG_ERROR("Shallow copy not recorded in StoreGate!");
210 return StatusCode::FAILURE;
211 }
212 } else { // use the user-supplied collection instead
213 ATH_MSG_DEBUG("Not retrieving electron collection, using existing one provided by user");
214 electrons=copy; // this does nothing
215 }
216
217 for (const auto electron : *copy) {
220 }
221
222 return StatusCode::SUCCESS;
223}
224
225
226StatusCode SUSYObjDef_xAOD::FillElectron(xAOD::Electron& input, float etcut, float etacut) {
227
228 ATH_MSG_VERBOSE( "Starting FillElectron on el with pre-calibration pt=" << input.pt() );
229
230 // According to https://twiki.cern.ch/twiki/bin/view/AtlasProtected/EGammaIdentificationRun2#Electron_identification:
231 // "Please apply the identification to uncalibrated electron object. ID scale factors are to be applied to calibrated objects."
232 dec_baseline(input) = false;
233 dec_selected(input) = 0;
234 dec_signal(input) = false;
235 dec_isol(input) = false;
236 dec_isolHighPt(input) = false;
237 dec_passSignalID(input) = false;
238 dec_passChID(input) = false;
239 dec_ecisBDT(input) = -999.;
240
241 const xAOD::EventInfo* evtInfo = nullptr;
242 ATH_CHECK( evtStore()->retrieve( evtInfo, "EventInfo" ) );
243 const xAOD::Vertex* pv = this->GetPrimVtx();
244 const xAOD::TrackParticle* track = input.trackParticle();
245 if (!track) {
246 ATH_MSG_DEBUG("No primary track particle for this electron. Skipping.");
247 return StatusCode::SUCCESS;
248 }
249 double primvertex_z = pv ? pv->z() : 0;
250 double el_z0 = track->z0() + track->vz() - primvertex_z;
251 dec_z0sinTheta(input) = el_z0 * TMath::Sin(input.p4().Theta());
252 //protect against exception thrown for null or negative d0sig
253 try{
255 }
256 catch(...){
257 float d0sigError = -99.;
258 ATH_MSG_WARNING("FillElectron : Exception catched from d0significance() calculation. Setting dummy decoration d0sig=" << d0sigError );
259 dec_d0sig(input) = d0sigError;
260 }
261
262 // don't bother calibrating or computing WP
263 if ( input.pt() < 4e3 ) return StatusCode::SUCCESS;
264 if ( !input.caloCluster() ) { ATH_MSG_WARNING( "FillElectron: no caloCluster found: " << input.caloCluster() ); return StatusCode::SUCCESS; }
265
266 //Check DeadHVCellRemoval
267 bool pass_deadHVTool = m_deadHVTool->accept(&input);
268
269 if (m_debug) {
270 unsigned char el_nPixHits(0), el_nSCTHits(0);
271 input.trackParticle()->summaryValue(el_nPixHits, xAOD::numberOfPixelHits);
272 input.trackParticle()->summaryValue(el_nSCTHits, xAOD::numberOfSCTHits);
273
274 ATH_MSG_INFO( "ELECTRON eta: " << input.eta());
275 ATH_MSG_INFO( "ELECTRON phi: " << input.phi());
276 ATH_MSG_INFO( "ELECTRON cl eta: " << input.caloCluster()->eta());
277 ATH_MSG_INFO( "ELECTRON cl phi: " << input.caloCluster()->phi());
278 ATH_MSG_INFO( "ELECTRON cl e: " << input.caloCluster()->e());
279 ATH_MSG_INFO( "ELECTRON trk eta: " << input.trackParticle()->eta());
280 ATH_MSG_INFO( "ELECTRON trk phi: " << input.trackParticle()->phi());
281 ATH_MSG_INFO( "ELECTRON author: " << input.author());
282 ATH_MSG_INFO( "ELECTRON OQ: " << acc_OQ(input));
283 ATH_MSG_INFO( "ELECTRON nPixHits: " << static_cast<int>(el_nPixHits));
284 ATH_MSG_INFO( "ELECTRON nSCTHits: " << static_cast<int>(el_nSCTHits));
285 ATH_MSG_INFO( "ELECTRON deadHVTools: " << static_cast<bool>(pass_deadHVTool));
286 }
287
288 if (!pass_deadHVTool) return StatusCode::SUCCESS;
289 if (!input.isGoodOQ(xAOD::EgammaParameters::BADCLUSELECTRON)) return StatusCode::SUCCESS;
290
291 if ( m_elecSelLikelihoodBaseline.empty()) {
292 ATH_MSG_ERROR("No baseline electron selector defined!");
293 return StatusCode::FAILURE;
294 }
295
296 bool passBaseID = false;
297 if (m_eleIdExpert) {
298 passBaseID = bool(m_elecSelLikelihoodBaseline->accept(&input));
299 } else {
300 if (m_acc_eleIdBaseline.isAvailable(input)) {
301 passBaseID = m_acc_eleIdBaseline(input);
302 } else {
303 ATH_MSG_VERBOSE ("DFCommonElectronsLHxxx variables are not found. Calculating the ID from LH tool..");
304 passBaseID = bool(m_elecSelLikelihoodBaseline->accept(&input));
305 }
306 }
307
308 if ( !passBaseID && !m_force_noElId ) return StatusCode::SUCCESS;
309
310 //baseline ID decoration for TauEl OR
311 //dec_passBaseID(input) = true;
312
313 // calibrate the electron 4-vector here only if within eta window
314 if (std::abs(input.caloCluster()->etaBE(2)) >= etacut) return StatusCode::SUCCESS;
315
317 if ( std::abs( input.caloCluster()->etaBE(2) ) >1.37 && std::abs( input.caloCluster()->etaBE(2) ) <1.52) {
318 return StatusCode::SUCCESS;
319 }
320 }
321
322 // corrections described in https://twiki.cern.ch/twiki/bin/view/AtlasProtected/EGammaCalibrationRun2
323 if ( m_egammaCalibTool->applyCorrection(input) != CP::CorrectionCode::Ok)
324 ATH_MSG_ERROR( "FillElectron: EgammaCalibTool applyCorrection failed ");
325
326 if (m_isoCorrTool->applyCorrection(input) != CP::CorrectionCode::Ok)
327 ATH_MSG_ERROR("FillElectron: IsolationCorrectionTool applyCorrection failed");
328
329 ATH_MSG_VERBOSE( "FillElectron: post-calibration pt=" << input.pt() );
330
331 if (input.pt() < etcut) return StatusCode::SUCCESS;
332
333 if (m_elebaselinez0>0. && std::abs(acc_z0sinTheta(input))>m_elebaselinez0) return StatusCode::SUCCESS;
334 if (m_elebaselined0sig>0. && std::abs(acc_d0sig(input))>m_elebaselined0sig) return StatusCode::SUCCESS;
335
336 //--- Do baseline isolation check
337 if ( !( m_eleBaselineIso_WP.empty() ) && !( m_isoBaselineTool->accept(input) ) ) return StatusCode::SUCCESS;
338
339 dec_baseline(input) = true;
340 dec_selected(input) = 2;
341 //disable if (!m_eleIso_WP.empty() && m_eleIso_WP.find("PLV")!=std::string::npos) ATH_CHECK( ->augmentPLV(input) );
342 if (!m_eleIso_WP.empty()) dec_isol(input) = bool(m_isoTool->accept(input));
343 if (!m_eleIsoHighPt_WP.empty()) dec_isolHighPt(input) = bool(m_isoHighPtTool->accept(input));
344
345 //ChargeIDSelector
346 if( m_runECIS ){
347 if (acc_passECIDS.isAvailable(input)) {
348 dec_passChID(input) = acc_passECIDS(input); // Loose 97% WP!
349 } else {
350 dec_passChID(input) = bool(m_elecChargeIDSelectorTool->accept(&input));
351 //disable double bdt = m_elecChargeIDSelectorTool->calculate(&input).getResult("bdt");
352 //disable dec_ecisBDT(input) = bdt;
353 }
354 }
355 else{
356 dec_passChID(input) = true;
357 }
358
359 ATH_MSG_VERBOSE( "FillElectron: passed baseline selection" );
360
361 return StatusCode::SUCCESS;
362}
363
364
365bool SUSYObjDef_xAOD::IsSignalElectron(const xAOD::Electron & input, float etcut, float d0sigcut, float z0cut, float etacut) const
366{
367 if (!acc_baseline(input)) return false;
368
369 dec_passSignalID(input) = false;
370
371 if (m_eleIdExpert) {
372 if ( !m_elecSelLikelihood.empty() && m_elecSelLikelihood->accept(&input) ) dec_passSignalID(input) = true;
373 }
374 else {
375 if (m_acc_eleId.isAvailable(input)) {
376 dec_passSignalID(input) = m_acc_eleId(input);
377 } else {
378 ATH_MSG_VERBOSE ("DFCommonElectronsLHxxx variables are not found. Calculating the ID from LH tool..");
379 if ( !m_elecSelLikelihood.empty() && m_elecSelLikelihood->accept(&input) ) dec_passSignalID(input) = true;
380 }
381 }
382
383 //overwrite ID selection if forced by user
384 if(m_force_noElId) dec_passSignalID(input) = true;
385
386 if (!acc_passSignalID(input)) return false;
387
388 if (input.p4().Perp2() <= etcut * etcut || input.p4().Perp2() == 0) return false; // eT cut (might be necessary for leading electron to pass trigger)
389 if ( etacut==DUMMYDEF ){
390 if(std::abs(input.caloCluster()->etaBE(2)) > m_eleEta ) return false;
391 }
392 else if ( std::abs(input.caloCluster()->etaBE(2)) > etacut ) return false;
393
394 if (m_eleCrackVeto){
395 if ( std::abs( input.caloCluster()->etaBE(2) ) >1.37 && std::abs( input.caloCluster()->etaBE(2) ) <1.52) {
396 return false;
397 }
398 }
399
400 if (acc_d0sig(input) != 0) {
401 if (d0sigcut > 0.0 && std::abs(acc_d0sig(input)) > d0sigcut) return false; // transverse IP cut
402 }
403
404 if (z0cut > 0.0 && std::abs(acc_z0sinTheta(input)) > z0cut) return false; // longitudinal IP cut
405
406
407 ATH_MSG_VERBOSE( "IsSignalElectron: " << m_eleId << " " << acc_passSignalID(input) << " d0sig " << acc_d0sig(input) << " z0 sin(theta) " << acc_z0sinTheta(input) );
408
409 if (m_doElIsoSignal) {
410 if ( !( (acc_isol(input) && input.pt()<m_eleIsoHighPtThresh) || (acc_isolHighPt(input) && input.pt()>m_eleIsoHighPtThresh)) ) return false;
411 ATH_MSG_VERBOSE( "IsSignalElectron: passed isolation" );
412 }
413
414 if(m_eleChID_signal && !acc_passChID(input)) return false; //add charge flip check to signal definition
415
416 dec_signal(input) = true;
417
418 ATH_MSG_VERBOSE( "IsSignalElectron: passed selection" );
419 return true;
420}
421
422
424 const bool recoSF,
425 const bool idSF,
426 const bool triggerSF,
427 const bool isoSF,
428 const std::string& trigExpr,
429 const bool ecidsSF,
430 const bool cidSF ) {
431
432 if ((m_eleId == "VeryLooseLLH" || m_eleId == "LooseLLH" || m_eleId == "Loose" || m_eleId == "Medium" || m_eleId == "Tight") && (idSF || triggerSF || isoSF)) {
433 ATH_MSG_ERROR("No signal electron ID or trigger scale factors provided for the selected working point!");
434 ATH_MSG_ERROR("I will now die messily.");
435 }
436
437 //shortcut keys for trigger SF config
438 std::string singleLepStr = "singleLepton";
439 std::string diLepStr = "diLepton";
440 std::string multiLepStr = "multiLepton";
441
442 float sf(1.);
443
444 if (recoSF) {
445 double reco_sf(1.);
446
447 CP::CorrectionCode result = m_elecEfficiencySFTool_reco->getEfficiencyScaleFactor(el, reco_sf);
448 switch (result) {
450 sf *= reco_sf;
451 break;
453 ATH_MSG_ERROR( "Failed to retrieve signal electron reco SF");
454 break;
456 ATH_MSG_VERBOSE( "OutOfValidityRange found for signal electron reco SF");
457 break;
458 default:
459 ATH_MSG_WARNING( "Don't know what to do for signal electron reco SF");
460 }
461 }
462
463 if (idSF) {
464 double id_sf(1.);
465
466 CP::CorrectionCode result = m_elecEfficiencySFTool_id->getEfficiencyScaleFactor(el, id_sf);
467 switch (result) {
469 sf *= id_sf;
470 break;
472 ATH_MSG_ERROR( "Failed to retrieve signal electron id SF");
473 break;
475 ATH_MSG_VERBOSE( "OutOfValidityRange found for signal electron id SF");
476 break;
477 default:
478 ATH_MSG_WARNING( "Don't know what to do for signal electron id SF");
479 }
480 }
481
482 if (triggerSF) {
483
484 std::vector<std::string> trigMChains={};
485 std::string theExpr ("");
486 if(trigExpr==singleLepStr) {
487 if (this->treatAsYear()==2015) trigMChains = m_v_trigs15_cache_singleEle;
488 else if (this->treatAsYear()==2016) trigMChains = m_v_trigs16_cache_singleEle;
489 else if (this->treatAsYear()==2017) trigMChains = m_v_trigs17_cache_singleEle;
490 else if (this->treatAsYear()==2018) trigMChains = m_v_trigs18_cache_singleEle;
491 else if (this->treatAsYear()==2022) trigMChains = m_v_trigs22_cache_singleEle;
492 else if (this->treatAsYear()==2023) trigMChains = m_v_trigs23_cache_singleEle;
493 else trigMChains = m_v_trigs24_cache_singleEle;
495 }
496 else{
497 ATH_MSG_WARNING( "Only single lepton trigger SFs are supported in GetSignalElecSF(). Use GetTriggerGlobalEfficiencySF() for dilepton or multilepton triggers!");
498 }
499
500 //check matching
501 this->TrigMatch({&el}, trigMChains);
502
503 if(!acc_trigmatched(el)){
504 ATH_MSG_DEBUG( "Electron was not matched to trigger " << theExpr << " - scale factor does not apply (year " << this->treatAsYear() << ") Returning 1." );
505 }
506 else{ //is trig-matched electron, go for it!
507 if (trigExpr==multiLepStr || trigExpr==diLepStr) {
508 ATH_MSG_WARNING( "The dilepton or multilepton trigger SFs are not supported in GetSignalElecSF(). Use GetTriggerGlobalEfficiencySF()!");
509 }
510 else {
511 double trig_sf = GetEleTriggerEfficiencySF( el , theExpr );
512 sf *= trig_sf;
513 }
514 }
515 }
516
517 if (isoSF) {
518 double iso_sf(1.);
519 CP::CorrectionCode result;
520 if (acc_isolHighPt(el) && el.pt()>m_eleIsoHighPtThresh)
521 result = m_elecEfficiencySFTool_isoHighPt->getEfficiencyScaleFactor(el, iso_sf);
522 else
523 result = m_elecEfficiencySFTool_iso->getEfficiencyScaleFactor(el, iso_sf);
524
525 switch (result) {
527 sf *= iso_sf;
528 break;
530 ATH_MSG_ERROR( "Failed to retrieve signal electron iso SF");
531 break;
533 ATH_MSG_VERBOSE( "OutOfValidityRange found for signal electron iso SF");
534 break;
535 default:
536 ATH_MSG_WARNING( "Don't know what to do for signal electron iso SF");
537 }
538 }
539
540 // Charge flip SF: combined ECIDs & charge ID
541 if ( ecidsSF || cidSF ) {
542 double chf_sf(1.);
543 // 1. ECIDs SF
544 if ( ecidsSF ) {
545 sf *= chf_sf;
546 ATH_MSG_WARNING( "ECID SF ARE NOT YET SUPPORTED IN R22" );
547 }
548 // 2. CID SF
549 if ( cidSF ) {
550 sf *= chf_sf;
551 dec_sfChIDEff(el) = chf_sf;
552 ATH_MSG_WARNING( "CID SF ARE NOT YET SUPPORTED IN R22" );
553 }
554 }
555
556 dec_effscalefact(el) = sf;
557 return sf;
558}
559
560
561double SUSYObjDef_xAOD::GetEleTriggerEfficiencySF(const xAOD::Electron& el, const std::string& trigExpr) const {
562
563 double trig_sf(1.);
564
565 std::string single_str = "SINGLE_E";
566 std::string single_Run3 = "202";
567 std::string dilep_str = "DI_E";
568 std::string multi_str = "MULTI_L";
569
570 CP::CorrectionCode result;
571 if ( trigExpr.find(single_str) != std::string::npos || trigExpr.find(single_Run3) != std::string::npos)
572 result = m_elecEfficiencySFTool_trig_singleLep->getEfficiencyScaleFactor(el, trig_sf);
573 else if ( trigExpr.find(dilep_str) != std::string::npos )
574 ATH_MSG_ERROR( "Use GetTriggerGlobalEfficiency for logical OR of lepton triggers");
575 else if ( trigExpr.find(multi_str) != std::string::npos )
576 ATH_MSG_ERROR( "Use GetTriggerGlobalEfficiency for logical OR of lepton triggers");
577 else
578 ATH_MSG_ERROR( "The trigger expression (" << trigExpr << ") is not supported by the electron trigger SF!");
579
580 switch (result) {
582 ATH_MSG_ERROR( "Failed to retrieve signal electron trigger SF");
583 return 1.;
585 ATH_MSG_VERBOSE( "OutOfValidityRange found for signal electron trigger SF");
586 return 1.;
587 default:
588 break;
589 }
590
591 return trig_sf;
592}
593
594
595double SUSYObjDef_xAOD::GetEleTriggerEfficiency(const xAOD::Electron& el, const std::string& trigExpr) const {
596
597 std::string single_str = "SINGLE_E";
598 std::string single_Run3 = "202";
599 std::string dilep_str = "DI_E";
600 std::string multi_str = "MULTI_L";
601
602 double trig_eff(1.);
603
604 CP::CorrectionCode result;
605 if ( trigExpr.find(single_str) != std::string::npos || trigExpr.find(single_Run3) != std::string::npos)
606 result = m_elecEfficiencySFTool_trigEff_singleLep->getEfficiencyScaleFactor(el, trig_eff);
607 else if ( trigExpr.find(dilep_str) != std::string::npos )
608 ATH_MSG_ERROR( "Use GetTriggerGlobalEfficiency for logical OR of lepton triggers");
609 else if ( trigExpr.find(multi_str) != std::string::npos )
610 ATH_MSG_ERROR( "Use GetTriggerGlobalEfficiency for logical OR of lepton triggers");
611 else
612 ATH_MSG_ERROR( "The trigger expression (" << trigExpr << ") is not supported by the electron trigger efficiency!");
613
614 switch (result) {
616 ATH_MSG_ERROR( "Failed to retrieve signal electron trigger efficiency");
617 return 1.;
619 ATH_MSG_VERBOSE( "OutOfValidityRange found for signal electron trigger efficiency");
620 return 1.;
621 default:
622 break;
623 }
624
625 return trig_eff;
626}
627
628
629
630float SUSYObjDef_xAOD::GetTotalElectronSF(const xAOD::ElectronContainer& electrons, const bool recoSF, const bool idSF, const bool triggerSF, const bool isoSF, const std::string& trigExpr, const bool ecidsSF, const bool cidSF) {
631 float sf(1.);
632
633 for (const xAOD::Electron* electron : electrons) {
634 if (!acc_passOR(*electron)) continue;
635 if (acc_signal(*electron)) { sf *= this->GetSignalElecSF(*electron, recoSF, idSF, triggerSF, isoSF, trigExpr, ecidsSF, cidSF); }
636 else { this->GetSignalElecSF(*electron, recoSF, idSF, triggerSF, isoSF, trigExpr, ecidsSF, cidSF); }
637 }
638
639 return sf;
640}
641
642
643 float SUSYObjDef_xAOD::GetTotalElectronSFsys(const xAOD::ElectronContainer& electrons, const CP::SystematicSet& systConfig, const bool recoSF, const bool idSF, const bool triggerSF, const bool isoSF, const std::string& trigExpr, const bool ecidsSF, const bool cidSF) {
644 float sf(1.);
645
646 //Set the new systematic variation
647 StatusCode ret(StatusCode::SUCCESS);
648 if(!m_elecEfficiencySFTool_reco.empty()){
649 ret = m_elecEfficiencySFTool_reco->applySystematicVariation(systConfig);
650 if (ret != StatusCode::SUCCESS) {
651 ATH_MSG_ERROR("Cannot configure AsgElectronEfficiencyCorrectionTool (reco) for systematic var. " << systConfig.name() );
652 }
653 }
654
655 if(!m_elecEfficiencySFTool_id.empty()){
656 ret = m_elecEfficiencySFTool_id->applySystematicVariation(systConfig);
657 if (ret != StatusCode::SUCCESS) {
658 ATH_MSG_ERROR("Cannot configure AsgElectronEfficiencyCorrectionTool (id) for systematic var. " << systConfig.name() );
659 }
660 }
661
663 ret = m_elecEfficiencySFTool_trig_singleLep->applySystematicVariation(systConfig);
664 if (ret != StatusCode::SUCCESS) {
665 ATH_MSG_ERROR("Cannot configure AsgElectronEfficiencyCorrectionTool (trigger) for systematic var. " << systConfig.name() );
666 }
667 }
668
669 if(!m_elecEfficiencySFTool_iso.empty()){
670 ret = m_elecEfficiencySFTool_iso->applySystematicVariation(systConfig);
671 if (ret != StatusCode::SUCCESS) {
672 ATH_MSG_ERROR("Cannot configure AsgElectronEfficiencyCorrectionTool (iso) for systematic var. " << systConfig.name() );
673 }
674 }
675
677 ret = m_elecEfficiencySFTool_isoHighPt->applySystematicVariation(systConfig);
678 if (ret != StatusCode::SUCCESS) {
679 ATH_MSG_ERROR("Cannot configure AsgElectronEfficiencyCorrectionTool (iso high-pt) for systematic var. " << systConfig.name() );
680 }
681 }
682
683 if(!m_elecChargeEffCorrTool.empty()){
684 ret = m_elecChargeEffCorrTool->applySystematicVariation(systConfig);
685 if (ret != StatusCode::SUCCESS) {
686 ATH_MSG_ERROR("Cannot configure ElectronChargeEfficiencyCorrectionTool for systematic var. " << systConfig.name() );
687 }
688 }
689
690
691 //Get the total SF for new config
692 sf = GetTotalElectronSF(electrons, recoSF, idSF, triggerSF, isoSF, trigExpr, ecidsSF, cidSF);
693
694 //Roll back to default
695 if(!m_elecEfficiencySFTool_reco.empty()){
696 ret = m_elecEfficiencySFTool_reco->applySystematicVariation(m_currentSyst);
697 if (ret != StatusCode::SUCCESS) {
698 ATH_MSG_ERROR("Cannot configure AsgElectronEfficiencyCorrectionTool (reco) back to default.");
699 }
700 }
701
702 if(!m_elecEfficiencySFTool_id.empty()){
703 ret = m_elecEfficiencySFTool_id->applySystematicVariation(m_currentSyst);
704 if (ret != StatusCode::SUCCESS) {
705 ATH_MSG_ERROR("Cannot configure AsgElectronEfficiencyCorrectionTool (id) back to default.");
706 }
707 }
708
710 ret = m_elecEfficiencySFTool_trig_singleLep->applySystematicVariation(m_currentSyst);
711 if (ret != StatusCode::SUCCESS) {
712 ATH_MSG_ERROR("Cannot configure AsgElectronEfficiencyCorrectionTool (trigger) back to default.");
713 }
714 }
715
716 if(!m_elecEfficiencySFTool_iso.empty()){
717 ret = m_elecEfficiencySFTool_iso->applySystematicVariation(m_currentSyst);
718 if (ret != StatusCode::SUCCESS) {
719 ATH_MSG_ERROR("Cannot configure AsgElectronEfficiencyCorrectionTool (iso) back to default.");
720 }
721 }
722
724 ret = m_elecEfficiencySFTool_isoHighPt->applySystematicVariation(m_currentSyst);
725 if (ret != StatusCode::SUCCESS) {
726 ATH_MSG_ERROR("Cannot configure AsgElectronEfficiencyCorrectionTool (iso high-pt) back to default.");
727 }
728 }
729
730 if(!m_elecChargeEffCorrTool.empty()){
731 ret = m_elecChargeEffCorrTool->applySystematicVariation(m_currentSyst);
732 if (ret != StatusCode::SUCCESS) {
733 ATH_MSG_ERROR("Cannot configure ElectronChargeEfficiencyCorrectionTool back to default.");
734 }
735 }
736
737 return sf;
738}
739
740}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
DataVector adapter that acts like it holds const pointers.
ServiceHandle< StoreGateSvc > & evtStore()
Return value from object correction CP tools.
@ Error
Some error happened during the object correction.
@ OutOfValidityRange
Input object is out of validity range.
@ Ok
The correction was done successfully.
Class to wrap a set of SystematicVariations.
std::string name() const
returns: the systematics joined into a single string.
value_type push_back(value_type pElem)
Add an element to the end of the collection.
Helper class to provide constant type-safe access to aux data.
std::vector< std::string > m_v_trigs24_cache_singleEle
StatusCode FillElectron(xAOD::Electron &input, const float etcut, const float etacut) override final
asg::AnaToolHandle< CP::IElectronLRTOverlapRemovalTool > m_elecLRTORTool
asg::AnaToolHandle< CP::IIsolationSelectionTool > m_isoBaselineTool
asg::AnaToolHandle< IAsgElectronEfficiencyCorrectionTool > m_elecEfficiencySFTool_isoHighPt
asg::AnaToolHandle< IAsgElectronLikelihoodTool > m_elecSelLikelihood
StatusCode prepareLRTElectrons(const xAOD::ElectronContainer *inMuons, xAOD::ElectronContainer *copy) const override final
Definition Electrons.cxx:90
std::vector< std::string > m_v_trigs15_cache_singleEle
asg::AnaToolHandle< CP::IIsolationSelectionTool > m_isoHighPtTool
asg::AnaToolHandle< IAsgElectronLikelihoodTool > m_elecSelLikelihoodBaseline
double GetEleTriggerEfficiencySF(const xAOD::Electron &el, const std::string &trigExpr="SINGLE_E_2015_e24_lhmedium_L1EM20VH_OR_e60_lhmedium_OR_e120_lhloose_2016_2018_e26_lhtight_nod0_ivarloose_OR_e60_lhmedium_nod0_OR_e140_lhloose_nod0") const override final
StatusCode MergeElectrons(const xAOD::ElectronContainer &electrons, xAOD::ElectronContainer *outputCol, const std::set< const xAOD::Electron * > &ElectronsToRemove) const override final
Definition Electrons.cxx:61
asg::AnaToolHandle< IAsgElectronEfficiencyCorrectionTool > m_elecEfficiencySFTool_id
const xAOD::ElectronContainer * lrt_electrons
asg::AnaToolHandle< CP::IIsolationSelectionTool > m_isoTool
SG::ConstAccessor< char > m_acc_eleId
asg::AnaToolHandle< IAsgElectronLikelihoodTool > m_elecChargeIDSelectorTool
SG::WriteHandleKey< xAOD::ElectronContainer > m_outElectronLocation
std::vector< std::string > m_v_trigs23_cache_singleEle
double GetEleTriggerEfficiency(const xAOD::Electron &el, const std::string &trigExpr="SINGLE_E_2015_e24_lhmedium_L1EM20VH_OR_e60_lhmedium_OR_e120_lhloose_2016_2018_e26_lhtight_nod0_ivarloose_OR_e60_lhmedium_nod0_OR_e140_lhloose_nod0") const override final
const xAOD::ElectronContainer * prompt_electrons
std::vector< std::string > m_v_trigs18_cache_singleEle
int treatAsYear(const int runNumber=-1) const override final
asg::AnaToolHandle< IAsgDeadHVCellRemovalTool > m_deadHVTool
asg::AnaToolHandle< IAsgElectronEfficiencyCorrectionTool > m_elecEfficiencySFTool_trigEff_singleLep
CP::SystematicSet m_currentSyst
asg::AnaToolHandle< IAsgElectronEfficiencyCorrectionTool > m_elecChargeEffCorrTool
std::string m_eleIsoHighPt_WP
asg::AnaToolHandle< CP::IIsolationCorrectionTool > m_isoCorrTool
float GetSignalElecSF(const xAOD::Electron &el, const bool recoSF=true, const bool idSF=true, const bool triggerSF=true, const bool isoSF=true, const std::string &trigExpr="singleLepton", const bool ecidsSF=false, const bool cidSF=false) override final
SG::ConstAccessor< char > m_acc_eleIdBaseline
StatusCode GetElectrons(xAOD::ElectronContainer *&copy, xAOD::ShallowAuxContainer *&copyaux, const bool recordSG=true, const std::string &elekey="Electrons", const std::string &lrtelekey="LRTElectrons", const xAOD::ElectronContainer *containerToBeCopied=nullptr) override final
std::vector< std::string > m_v_trigs22_cache_singleEle
asg::AnaToolHandle< IAsgElectronEfficiencyCorrectionTool > m_elecEfficiencySFTool_reco
Combined muon collection.
float GetTotalElectronSF(const xAOD::ElectronContainer &electrons, const bool recoSF=true, const bool idSF=true, const bool triggerSF=true, const bool isoSF=true, const std::string &trigExpr="singleLepton", const bool ecidsSF=false, const bool cidSF=false) override final
const xAOD::Vertex * GetPrimVtx() const override final
std::vector< std::string > m_v_trigs17_cache_singleEle
std::vector< std::string > m_v_trigs16_cache_singleEle
bool IsSignalElectron(const xAOD::Electron &input, const float etcut, const float d0sigcut, const float z0cut, const float etacut=DUMMYDEF) const override final
asg::AnaToolHandle< CP::IEgammaCalibrationAndSmearingTool > m_egammaCalibTool
Combined electron collection.
asg::AnaToolHandle< IAsgElectronEfficiencyCorrectionTool > m_elecEfficiencySFTool_trig_singleLep
asg::AnaToolHandle< IAsgElectronEfficiencyCorrectionTool > m_elecEfficiencySFTool_iso
float GetTotalElectronSFsys(const xAOD::ElectronContainer &electrons, const CP::SystematicSet &systConfig, const bool recoSF=true, const bool idSF=true, const bool triggerSF=true, const bool isoSF=true, const std::string &trigExpr="singleLepton", const bool ecidsSF=false, const bool cidSF=false) override final
std::string m_eleBaselineIso_WP
std::string m_electronTriggerSFStringSingle
float beamPosSigmaY() const
The width of the beam spot in the Y direction.
float beamPosSigmaXY() const
The beam spot shape's X-Y correlation.
float beamPosSigmaX() const
The width of the beam spot in the X direction.
Class creating a shallow copy of an existing auxiliary container.
bool contains(const std::string &s, const std::string &regx)
does a string contain the substring
Definition hcg.cxx:116
SG::Decorator< T, ALLOC > Decorator
Helper class to provide type-safe access to aux data, specialized for JaggedVecElt.
Definition AuxElement.h:576
static const SG::ConstAccessor< float > acc_d0sig("d0sig")
static const SG::ConstAccessor< char > acc_isolHighPt("isolHighPt")
static const SG::Decorator< double > dec_effscalefact("effscalefact")
static const SG::Decorator< char > dec_passSignalID("passSignalID")
static const SG::Decorator< char > dec_baseline("baseline")
static const SG::Decorator< char > dec_isolHighPt("isolHighPt")
static const SG::ConstAccessor< float > acc_z0sinTheta("z0sinTheta")
static const SG::ConstAccessor< char > acc_passSignalID("passSignalID")
static const SG::ConstAccessor< char > acc_passECIDS("DFCommonElectronsECIDS")
static const SG::ConstAccessor< char > acc_trigmatched("trigmatched")
static const SG::ConstAccessor< unsigned int > acc_OQ("OQ")
static const SG::Decorator< char > dec_passChID("passChID")
static const SG::ConstAccessor< float > acc_sfChIDEff("chargeIDEffiSF")
static const SG::ConstAccessor< char > acc_signal("signal")
static const SG::ConstAccessor< char > acc_baseline("baseline")
static const SG::Decorator< float > dec_z0sinTheta("z0sinTheta")
static const SG::Decorator< double > dec_ecisBDT("ecisBDT")
static const double DUMMYDEF
static const SG::Decorator< char > dec_isLRT("isLRT")
static const SG::ConstAccessor< char > acc_passOR("passOR")
static const SG::Decorator< float > dec_sfChIDEff("chargeIDEffiSF")
static const SG::ConstAccessor< char > acc_isLRT("isLRT")
static const SG::ConstAccessor< char > acc_lrtFilter("passLRTFilter")
static const SG::ConstAccessor< char > acc_isol("isol")
static const SG::Decorator< char > dec_isol("isol")
static const SG::ConstAccessor< char > acc_passChID("passChID")
static const SG::Decorator< char > dec_signal("signal")
static const SG::Decorator< float > dec_d0sig("d0sig")
static const SG::Decorator< char > dec_selected("selected")
helper namespace for calculating deltaR for unknown object types
const uint32_t BADCLUSELECTRON
Definition EgammaDefs.h:116
double d0significance(const xAOD::TrackParticle *tp, double d0_uncert_beam_spot_2)
typename ShallowCopyResult< T >::type ShallowCopyResult_t
Return type of xAOD::shallowCopy.
Definition ShallowCopy.h:68
ElectronContainer_v1 ElectronContainer
Definition of the current "electron container version".
EventInfo_v1 EventInfo
Definition of the latest event info version.
TrackParticle_v1 TrackParticle
Reference the current persistent version:
const IParticle * getOriginalObject(const IParticle &copy)
This function can be used to conveniently get a pointer back to the original object from which a copy...
Vertex_v1 Vertex
Define the latest version of the vertex class.
ShallowCopyResult_t< T > shallowCopy(const T &cont, const EventContext &ctx)
Create a shallow copy of an existing container.
bool setOriginalObjectLink(const IParticle &original, IParticle &copy)
This function should be used by CP tools when they make a deep copy of an object in their correctedCo...
setBGCode setTAP setLVL2ErrorBits bool
@ numberOfSCTHits
number of hits in SCT [unit8_t].
@ numberOfPixelHits
these are the pixel hits, including the b-layer [unit8_t].
Electron_v1 Electron
Definition of the current "egamma version".