ATLAS Offline Software
ElectronLikelihood.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3  */
4 
6 #include "TopEvent/EventTools.h"
7 //#include "ElectronPhotonSelectorTools/AsgElectronChargeIDSelectorTool.h"
9 #include <iostream>
10 
12 using namespace TopObjectSelectionTools;
13 
14 namespace top {
15  ElectronLikelihood::ElectronLikelihood(const double ptcut, const bool vetoCrack,
16  const std::string& operatingPoint,
17  const std::string& operatingPointLoose, StandardIsolation* isolation,
18  const double d0SigCut, const double delta_z0, const bool applyTTVACut,
19  const bool applyChargeIDCut) :
20  m_ptcut(ptcut),
21  m_vetoCrack(vetoCrack),
22  m_d0SigCut(d0SigCut),
23  m_delta_z0(delta_z0),
24  m_operatingPoint("SetMe"),
25  m_operatingPointLoose("SetMe"),
26  m_operatingPoint_DF("SetMe"),
27  m_operatingPointLoose_DF("SetMe"),
28  m_isolation(isolation),
29  m_applyTTVACut(applyTTVACut),
30  m_applyChargeIDCut(applyChargeIDCut) {
42  std::string egammaNamesAreNotConsistantAnywhere("LikelihoodNotSetProperly");
43  std::string egammaNamesAreNotConsistantAnywhereLoose("LikelihoodNotSetProperly");
44 
45  if (operatingPoint == "LooseLH") {
46  egammaNamesAreNotConsistantAnywhere = "DFCommonElectronsLHLoose";
47  }
48  if (operatingPoint == "LooseAndBLayerLH") {
49  egammaNamesAreNotConsistantAnywhere = "DFCommonElectronsLHLooseBL";
50  }
51  if (operatingPoint == "MediumLH") {
52  egammaNamesAreNotConsistantAnywhere = "DFCommonElectronsLHMedium";
53  }
54  if (operatingPoint == "TightLH") {
55  egammaNamesAreNotConsistantAnywhere = "DFCommonElectronsLHTight";
56  }
57 
58  if (operatingPointLoose == "LooseLH") {
59  egammaNamesAreNotConsistantAnywhereLoose = "DFCommonElectronsLHLoose";
60  }
61  if (operatingPointLoose == "LooseAndBLayerLH") {
62  egammaNamesAreNotConsistantAnywhereLoose = "DFCommonElectronsLHLooseBL";
63  }
64  if (operatingPointLoose == "MediumLH") {
65  egammaNamesAreNotConsistantAnywhereLoose = "DFCommonElectronsLHMedium";
66  }
67  if (operatingPointLoose == "TightLH") {
68  egammaNamesAreNotConsistantAnywhereLoose = "DFCommonElectronsLHTight";
69  }
70 
71  m_operatingPoint_DF = egammaNamesAreNotConsistantAnywhere;
72  m_operatingPointLoose_DF = egammaNamesAreNotConsistantAnywhereLoose;
73  m_operatingPoint = operatingPoint;
74  m_operatingPointLoose = operatingPointLoose;
75 
76  m_deadHVTool.setTypeAndName("AsgDeadHVCellRemovalTool/deadHVTool");
77  top::check(m_deadHVTool.retrieve(), "Failed to setup Egamma DeadHVCellRemovalTool");
78  }
79 
80  ElectronLikelihood::ElectronLikelihood(const double ptcut, const bool vetoCrack,
81  const std::string& operatingPoint,
82  const std::string& operatingPointLoose,
83  StandardIsolation* isolation,
84  const bool applyChargeIDCut)
85  : ElectronLikelihood::ElectronLikelihood(ptcut, vetoCrack, operatingPoint,
86  operatingPointLoose, isolation, 5.0, 0.5, true,
87  applyChargeIDCut) {}
88 
89  ElectronLikelihood::ElectronLikelihood(const double ptcut, const bool vetoCrack,
90  const std::string& operatingPoint,
91  const std::string& operatingPointLoose,
92  StandardIsolation* isolation,
93  const bool applyTTVACut,
94  const bool applyChargeIDCut)
95  : ElectronLikelihood::ElectronLikelihood(ptcut, vetoCrack, operatingPoint,
96  operatingPointLoose, isolation, 5.0, 0.5, applyTTVACut,
97  applyChargeIDCut) {}
98 
101 
102  if (m_isolation && !m_isolation->passSelection(el)) return false;
103 
104  return true;
105  }
106 
109 
110  if (m_isolation && !m_isolation->passSelectionLoose(el)) return false;
111 
112  return true;
113  }
114 
115  bool ElectronLikelihood::passSelectionNoIsolation(const xAOD::Electron& el, const std::string& operatingPoint_DF,
116  const std::string& operatingPoint) const {
117  if (el.pt() < m_ptcut) return false;
118 
119  // removing bad electron cluser - see
120  // https://twiki.cern.ch/twiki/bin/view/AtlasProtected/EGammaIdentificationRun2#Bad_Electron_Photon_Cluster
121  if (!el.isGoodOQ(xAOD::EgammaParameters::BADCLUSELECTRON)) return false;
122 
123  // Try to catch instances for derivations using a different type for this variable
124  try {
125  if (el.auxdataConst<int>(operatingPoint_DF) != 1) return false;
126  }
127  catch (const SG::ExcAuxTypeMismatch& e) {
128  if (el.auxdataConst<char>(operatingPoint_DF) != 1) return false;
129  }
130 
131  if (operatingPoint == "LooseAndBLayerLH") {
132  if (!passBLayerCuts(el)) return false;
133  }
134 
135  //WARNING: There has been a bug previously in our derivations where looseLH failed, but tighter WP succeed
136  //WARNING: This results in a "good" electron with no clusters (due to thinning), and then we crash and burn
137  //WARNING: We are therefore going to test whether the looseLH WP is also passed before we check the cluster eta
138  //WARNING: If it does not (and we passed ID checks above) then this is a dodgy electron
139  //WARNING: So we print a warning to alert the user that this was found, but then we proceed as normal
140  //WARNING: and this electron is vetoed from the selection
141  try {
142  if (el.auxdataConst<int>("DFCommonElectronsLHLoose") != 1) {
143  ATH_MSG_ERROR("This electron fails the DFCommonElectronsLHLoose and has an incorrect decoration.\n pt ("
144  << el.pt() << "), eta (" << el.eta() << ")");
145  return false;
146  }
147  }
148  catch (const SG::ExcAuxTypeMismatch& e) {
149  if (el.auxdataConst<char>("DFCommonElectronsLHLoose") != 1) {
150  ATH_MSG_ERROR("This electron fails the DFCommonElectronsLHLoose and has an incorrect decoration.\n pt ("
151  << el.pt() << "), eta (" << el.eta() << ")");
152  return false;
153  }
154  }
155 
156 
157  //WARNING: Not all electrons keep clusters in the derivation
158  //i.e. bad electrons (which is why we moved the check on the likelihood
159  //before the check on the calo cluster)
160  //This stops a crash
161  //Good electrons should always have a cluster, if not then crash to warn us
162  //Better than checking and silently doing nothing...
163  if (std::fabs(el.caloCluster()->etaBE(2)) > 2.47) return false;
164 
165  //Veto electrons suffering from the 2015+2016/mc16a crack+topocluster association bug
166  //See https://twiki.cern.ch/twiki/bin/viewauth/AtlasProtected/HowToCleanJets2017#EGamma_Crack_Electron_topocluste for details
167  if (el.isAvailable<char>("DFCommonCrackVetoCleaning"))
168  if (!el.auxdataConst<char>("DFCommonCrackVetoCleaning")) return false;
169 
170  if (m_vetoCrack && std::fabs(el.caloCluster()->etaBE(2)) > 1.37 &&
171  std::fabs(el.caloCluster()->etaBE(2)) < 1.52) return false;
172 
173  // Track-to-vertex association
174  if (m_applyTTVACut) {
175  if (!passTTVACuts(el)) return false;
176  }
177 
178  // removing electron cluster in EMEC bad HV regions
179  // https://twiki.cern.ch/twiki/bin/view/AtlasProtected/EGammaIdentificationRun2#Removal_of_Electron_Photon_clust
180  if (!m_deadHVTool->accept(el)) return false;
181 
182 
183  // Electron Charge ID Selector Tool
184  // apply decoration only
185  if (m_applyChargeIDCut && !passChargeIDCut(el)) el.auxdecor<char>("passChargeID") = 0;
186  else el.auxdecor<char>("passChargeID") = 1;
187 
188  return true;
189  }
190 
192 
193  const xAOD::TrackParticle* t = el.trackParticle();
195  }
196 
198  // TTVA:
199  // see https://twiki.cern.ch/twiki/bin/view/AtlasProtected/TrackingCPEOYE2015#Track_to_Vertex_Association
200  if (!el.isAvailable<float>("d0sig")) {
201  ATH_MSG_WARNING("d0 significance not found for electron. Maybe no primary vertex? Won't accept.");
202  return false;
203  }
204 
205  float d0sig = el.auxdataConst<float>("d0sig");
206  if (std::abs(d0sig) >= 5) return false;
207 
208  if (!el.isAvailable<float>("delta_z0_sintheta")) {
209  ATH_MSG_WARNING("delta z0*sin(theta) not found for electron. Maybe no primary vertex? Won't accept.");
210  return false;
211  }
212 
213  float delta_z0_sintheta = el.auxdataConst<float>("delta_z0_sintheta");
214  if (std::abs(delta_z0_sintheta) >= 0.5) return false;
215 
216  return true;
217  }
218 
220  static const SG::AuxElement::ConstAccessor<char> acc_ECIDS("DFCommonElectronsECIDS");
221 
222  top::check(acc_ECIDS.isAvailable(
223  el), "ElectronLikelihood::passChargeIDCut: DFCommonElectronsECIDS is not available");
224  return acc_ECIDS(el) ? true : false;
225  }
226 
227  void ElectronLikelihood::print(std::ostream& os) const {
228  os << "ElectronLikelihood\n";
229  os << " * pT > " << m_ptcut << "\n";
230  os << " * Currently disabled --- |cluster_eta| < 2.47 \n";
231  os << " * Veto 1.37 < |cluster_eta| < 1.52? " << std::boolalpha << m_vetoCrack << "\n";
232  if (!m_isolation) {
233  os << " * No isolation requirement\n";
234  } else {
235  m_isolation->print(os);
236  }
237  os << " * LH Tool Operating Point: " << m_operatingPoint_DF << " \t\t LH Tool Loose Operating Point: " <<
238  m_operatingPointLoose_DF << " \n";
239  }
240 }
top::ElectronLikelihood::m_operatingPoint_DF
std::string m_operatingPoint_DF
Definition: ElectronLikelihood.h:122
top::ElectronLikelihood::m_applyChargeIDCut
bool m_applyChargeIDCut
decide to apply the charge ID selector tool
Definition: ElectronLikelihood.h:132
top
TopConfig A simple configuration that is NOT a singleton.
Definition: AnalysisTrackingHelper.cxx:58
IAsgDeadHVCellRemovalTool::accept
virtual bool accept(const xAOD::Egamma *part) const =0
asg::AnaToolHandle::retrieve
StatusCode retrieve()
initialize the tool
top::StandardIsolation
Apply the cuts to etcone and ptcone like we used to in Run-I.
Definition: IsolationTools.h:231
asg::AnaToolHandle::setTypeAndName
void setTypeAndName(const std::string &val_typeAndName)
set the value of type and name
top::ElectronLikelihood::passTTVACuts
virtual bool passTTVACuts(const xAOD::Electron &el) const
The track-to-vertex association (TTVA) cuts.
Definition: ElectronLikelihood.cxx:197
xAOD::EgammaParameters::BADCLUSELECTRON
const uint32_t BADCLUSELECTRON
Definition: EgammaDefs.h:116
SG::ConstAccessor
Helper class to provide constant type-safe access to aux data.
Definition: ConstAccessor.h:54
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
top::ElectronLikelihood::m_isolation
std::unique_ptr< top::StandardIsolation > m_isolation
The isolation tool, or nullptr if we don't want isolation.
Definition: ElectronLikelihood.h:126
ElectronSelectorHelpers::passBLayerRequirement
bool passBLayerRequirement(const xAOD::TrackParticle &tp)
return true if effective number of BL hits + outliers is at least one
Definition: ElectronSelectorHelpers.cxx:59
Pythia8_A14_NNPDF23LO_forMGHT_EvtGen.ptcut
float ptcut
Definition: Pythia8_A14_NNPDF23LO_forMGHT_EvtGen.py:9
MsgCategory.h
EventTools.h
A few functions for doing operations on particles / events. Currently holds code for dR,...
ElectronSelectorHelpers.h
top::ElectronLikelihood::m_operatingPoint
std::string m_operatingPoint
Definition: ElectronLikelihood.h:120
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
top::ElectronLikelihood::m_deadHVTool
asg::AnaToolHandle< IAsgDeadHVCellRemovalTool > m_deadHVTool
Definition: ElectronLikelihood.h:136
top::ElectronLikelihood::passBLayerCuts
virtual bool passBLayerCuts(const xAOD::Electron &el) const
The BLayer cuts for the loose lepton LH WP.
Definition: ElectronLikelihood.cxx:191
plotIsoValidation.el
el
Definition: plotIsoValidation.py:197
top::check
void check(bool thingToCheck, const std::string &usefulFailureMessage)
Print an error message and terminate if thingToCheck is false.
Definition: EventTools.cxx:15
ReadFromCoolCompare.os
os
Definition: ReadFromCoolCompare.py:231
ElectronLikelihood.h
top::ElectronLikelihood::m_operatingPointLoose
std::string m_operatingPointLoose
Definition: ElectronLikelihood.h:121
top::ElectronLikelihood
To select electrons based on the "likelihood" definition.
Definition: ElectronLikelihood.h:18
top::ElectronLikelihood::print
virtual void print(std::ostream &os) const override
Why would you not want to know what you're running?
Definition: ElectronLikelihood.cxx:227
top::ElectronLikelihood::passSelection
virtual bool passSelection(const xAOD::Electron &el) const override
Selection for the main analysis (i.e.
Definition: ElectronLikelihood.cxx:99
xAOD::Electron_v1
Definition: Electron_v1.h:34
top::ElectronLikelihood::m_operatingPointLoose_DF
std::string m_operatingPointLoose_DF
Definition: ElectronLikelihood.h:123
DiTauMassTools::MaxHistStrategyV2::e
e
Definition: PhysicsAnalysis/TauID/DiTauMassTools/DiTauMassTools/HelperFunctions.h:26
top::ElectronLikelihood::m_ptcut
double m_ptcut
Minimum pT that electrons should have.
Definition: ElectronLikelihood.h:111
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
top::ElectronLikelihood::passSelectionLoose
virtual bool passSelectionLoose(const xAOD::Electron &el) const override
Selection for the loose object definitions (e.g.
Definition: ElectronLikelihood.cxx:107
SG::ConstAccessor::isAvailable
bool isAvailable(const ELT &e) const
Test to see if this variable exists in the store.
xAOD::TrackParticle_v1
Class describing a TrackParticle.
Definition: TrackParticle_v1.h:43
top::ElectronLikelihood::passSelectionNoIsolation
bool passSelectionNoIsolation(const xAOD::Electron &el, const std::string &operatingPoint_DF, const std::string &operatingPoint) const
The loose and tight selections are the same, except they have different use isolation and a different...
Definition: ElectronLikelihood.cxx:115
top::ElectronLikelihood::passChargeIDCut
virtual bool passChargeIDCut(const xAOD::Electron &el) const
The charge flip selector cut.
Definition: ElectronLikelihood.cxx:219
top::ElectronLikelihood::m_applyTTVACut
bool m_applyTTVACut
decide if TTVA cut should be applied at all
Definition: ElectronLikelihood.h:129
SG::ExcAuxTypeMismatch
Exception — Type mismatch for aux variable.
Definition: Control/AthContainers/AthContainers/exceptions.h:132
top::ElectronLikelihood::m_vetoCrack
bool m_vetoCrack
Veto the crack region?
Definition: ElectronLikelihood.h:114
top::ElectronLikelihood::ElectronLikelihood
ElectronLikelihood(const double ptcut, const bool vetoCrack, const std::string &operatingPoint, const std::string &operatingPointLoose, StandardIsolation *isolation, const bool applyChargeIDCut)
Cut on likelihood electrons.
Definition: ElectronLikelihood.cxx:80