ATLAS Offline Software
Loading...
Searching...
No Matches
ElectronSelector.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//
6// ElectronSelector.cxx : Class designed to reconstruct di-electrons events
7// in particular Z0 -> e+ e- events.
8//==================================================================================
9
10//==================================================================================
11// Include files...
12//==================================================================================
13
14// This files header
16// Package Headers
18
19// ATLAS headers
22#include "CLHEP/Random/RandFlat.h"
23
24#include <sstream>
25// Static declarations
26std::atomic<unsigned int> ElectronSelector::s_uNumInstances;
27
28//==================================================================================
29// Public Methods
30//==================================================================================
32 m_doDebug ( false ),
33 m_ptCut ( 10. ),
34 m_etaCut ( 2.47 ) // 2.47 is the official acceptance for central electrons. Forward electrons is another story...
35{
37
38 std::stringstream xTmp; xTmp << s_uNumInstances;
39 m_xSampleName = "ElectronSelector_" + xTmp.str();
40
41 m_pxElectron = nullptr;
42
43 m_msgStream = new MsgStream(Athena::getMessageSvc(), "InDetPerformanceMonitoring" );
44}
45
52
55{
56 (*m_msgStream) << MSG::DEBUG << " -- ElectronSelector::Init -- START -- " << endmsg;
57
58 // PARENT::Init();
59
60 //---Electron Likelihood tool---
61 // m_doIDCuts = true;
62 (*m_msgStream) << MSG::INFO << "ElectronSelector::Init -- Setting up electron LH tool." << endmsg;
63 m_LHTool2015 = new AsgElectronLikelihoodTool ("m_LHTool2015");
64
65 const std::string elecWorkingPoint = "LooseLHElectron"; // "MediumLHElectron" "TightLHElectron"
66
67 if((m_LHTool2015->setProperty("WorkingPoint",elecWorkingPoint.c_str())).isFailure()) {
68 (*m_msgStream) << MSG::WARNING << "Failure loading ConfigFile for electron likelihood tool with working point: " << elecWorkingPoint.c_str() << endmsg;
69 }
70 else {
71 (*m_msgStream) << MSG::INFO << "Loading ConfigFile for electron likelihood tool with working point: " << elecWorkingPoint << ". SUCCESS " << endmsg;
72 }
73
74 // check config files at: https://twiki.cern.ch/twiki/bin/viewauth/AtlasProtected/EGammaIdentificationRun2
75 std::string confDir = "ElectronPhotonSelectorTools/offline/mc20_20210514/ElectronLikelihoodVeryLooseOfflineConfig2017_Smooth.conf";
76 if ( (m_LHTool2015->setProperty("ConfigFile", confDir)).isSuccess()) {
77 (*m_msgStream) << MSG::INFO << "Electron likelihood config ("<< confDir.c_str() << ") setting SUCCESS!" << endmsg;
78 }
79 else {
80 (*m_msgStream) << MSG::WARNING << "Electron likelihood config ("<< confDir.c_str() << ") setting FAILURE" << endmsg;
81 }
82
83 if (m_LHTool2015->initialize().isSuccess()) {
84 (*m_msgStream) << MSG::INFO << "Electron likelihood tool initialize() SUCCESS!" << endmsg;
85 }
86 else {
87 (*m_msgStream) << MSG::WARNING << "Electron likelihood tool initialize() FAILURE!" << endmsg;
88 }
89
90 (*m_msgStream) << MSG::DEBUG << " --ElectronSelector::Init -- COMPLETED -- " << endmsg;
91 return;
92}
93
96{
97 (*m_msgStream) << MSG::DEBUG << " --ElectronSelector::PrepareElectronList -- START -- " << endmsg;
98 Clear(); // clear current list records
99
100 using electron_iterator = xAOD::ElectronContainer::const_iterator;
101 electron_iterator iter = pxElecContainer->begin();
102 electron_iterator iterEnd = pxElecContainer->end();
103
104 // Loop over the Electrons
105 int electroncount = 0;
106 for(; iter != iterEnd ; ++iter) {
107 electroncount++;
108 (*m_msgStream) << MSG::DEBUG << " -- ElectronSelector::PrepareElectronList -- candiate electron " << electroncount
109 << " has author " << (*iter)->author(xAOD::EgammaParameters::AuthorElectron)
110 << endmsg;
111 const xAOD::Electron * ELE = (*iter);
112 if ( RecordElectron(ELE) ) {
113 (*m_msgStream) << MSG::DEBUG << " -- ElectronSelector::PrepareElectronList -- candiate electron " << electroncount
114 << " is good "
115 << endmsg;
116 }
117 }
118 bool progressingwell = true;
119
120 (*m_msgStream) << MSG::DEBUG << " -- ElectronSelector::PrepareElectronList -- finished recording electrons. "
121 << " recorded electrons: " << m_pxElTrackList.size()
122 << " out of tested electron candidates:" << electroncount << endmsg;
123 if (m_pxElTrackList.size() < 2) progressingwell = false;
124 if (progressingwell) progressingwell = OrderElectronList ();
125 if (progressingwell) progressingwell = RetrieveVertices ();
126
127 if (!progressingwell) {
128 (*m_msgStream) << MSG::DEBUG << " -- ElectronSelector::PrepareElectronList -- FAILED -- this event has not even a good e+e- pair " << endmsg;
129 this->Clear(); // reset the content as it is not going to be used
130 }
131
132 (*m_msgStream) << MSG::DEBUG << " -- ElectronSelector::PrepareElectronList -- COMPLETED -- electroncount -- m_pxElTrackList.size() / all = "
133 << m_pxElTrackList.size() << " / " << electroncount
134 << endmsg;
135 return;
136}
137
140{
141 // start assuming electron candidate is good
142 bool electronisgood = true;
143
144 // check the electron satisfies the working point
145 if (!m_LHTool2015->accept(thisElec) ) {
146 electronisgood = false;
147 (*m_msgStream) << MSG::DEBUG << " -- electron fails workingpoint selection -- " << endmsg;
148 }
149
150 //Get the track particle
151 const xAOD::TrackParticle* theTrackParticle = thisElec->trackParticle();
152
153 if (!theTrackParticle) {
154 electronisgood = false;
155 (*m_msgStream) << MSG::DEBUG << " -- electron fails trackparticle -- " << endmsg;
156 }
157
158 if (electronisgood && thisElec->author(xAOD::EgammaParameters::AuthorElectron) != 1) {
159 electronisgood = false;
160 (*m_msgStream) << MSG::DEBUG << " -- electron fails author -- " << thisElec->author(xAOD::EgammaParameters::AuthorElectron) << endmsg;
161 }
162
163 if (electronisgood && theTrackParticle->pt() * m_CGeV < m_ptCut ) { // pt cut given in GeV
164 electronisgood = false;
165 (*m_msgStream) << MSG::DEBUG << " -- electron fails pt cut -- pt= " << theTrackParticle->pt()
166 << " < " << m_ptCut << " (cut value) "
167 << endmsg;
168 }
169
170 const xAOD::CaloCluster* cluster = thisElec->caloCluster();
171 if(!cluster) {
172 electronisgood = false;
173 (*m_msgStream) << MSG::DEBUG << " -- electron candidate has no CaloCluster " << endmsg;
174 }
175
176 if (electronisgood && (cluster->e() * sin(theTrackParticle->theta())) * m_CGeV < m_ptCut) { // cut on et of the cluster
177 electronisgood = false;
178 (*m_msgStream) << MSG::DEBUG << " -- electron fails cluster Et cut -- Et= " << (cluster->e() * cos(theTrackParticle->theta()))* m_CGeV
179 << " < " << m_ptCut << " (cut value) "
180 << endmsg;
181 }
182
183 if (electronisgood && (std::abs(cluster->eta())> m_etaCut || std::abs(theTrackParticle->eta())> m_etaCut) ) { // cut in eta for the cluster and the track
184 electronisgood = false;
185 (*m_msgStream) << MSG::DEBUG << " -- electron fails eta cut -- cluster_eta= " << cluster->eta() << endmsg;
186 }
187
188 if (electronisgood) {
189 // store this electron
190 m_pxElTrackList.push_back(theTrackParticle);
191
192 (*m_msgStream) << MSG::DEBUG << " * RecordElectron * good electron found -> store this electron with pt " << theTrackParticle->pt()
193 << " --> current m_pxElTrackList.size(): " << m_pxElTrackList.size()
194 << std::endl;
195 }
196
197 return electronisgood;
198}
199
202{
203 m_pxElTrackList.clear();
206
207 // -1 means not assigned
208 m_elecneg1 = -1;
209 m_elecneg2 = -1;
210 m_elecpos1 = -1;
211 m_elecpos2 = -1;
212
213 return;
214}
215
218{
219 (*m_msgStream) << MSG::DEBUG << " -- ElectronSelector::OrderElectronList -- START -- list size: " << m_pxElTrackList.size( ) << endmsg;
220 if (m_pxElTrackList.size() < 2) {
221 return false;
222 }
223 struct LeadingElectrons {
224 double leadingPt{};
225 double subleadingPt{};
226 int leadingIndex{-1};
227 int subleadingIndex{-1};
228 std::size_t count{};
229 };
230 //
231 LeadingElectrons negative;
232 LeadingElectrons positive;
233 const auto updateLeading = [](LeadingElectrons& electrons, double pt, int index) {
234 ++electrons.count;
235 if (pt > electrons.leadingPt) {
236 electrons.subleadingPt = electrons.leadingPt;
237 electrons.subleadingIndex = electrons.leadingIndex;
238 electrons.leadingPt = pt;
239 electrons.leadingIndex = index;
240 } else if (pt > electrons.subleadingPt) {
241 electrons.subleadingPt = pt;
242 electrons.subleadingIndex = index;
243 }
244 };
245
246 for (std::size_t index = 0; index < m_pxElTrackList.size(); ++index){
247 const xAOD::TrackParticle* electron = m_pxElTrackList[index];
248 if (electron->charge() < 0.) { // negative electrons
249 updateLeading(negative, electron->pt(), static_cast<int>(index));
250 } else if (electron->charge() > 0.) { // positive electrons
251 updateLeading(positive, electron->pt(), static_cast<int>(index));
252 }
253 }
254
255 if (negative.count == 0 || positive.count == 0) {
256 if (m_doDebug) {
257 std::cout << " -- ElectronSelector::OrderElectronList -- "
258 "No opposite-charge electrons --> DISCARD ALL ELECTRONS --\n";
259 }
260 Clear();
261 return false;
262 }
263 m_elecneg1 = negative.leadingIndex;
264 m_elecneg2 = negative.subleadingIndex;
265 m_elecpos1 = positive.leadingIndex;
266 m_elecpos2 = positive.subleadingIndex;
267 //
268 if (m_doDebug) {
269 std::cout << " -- ElectronSelector::OrderElectronList -- electron summary list taking "
270 << negative.count + positive.count << " electrons from the input list of "
271 << m_pxElTrackList.size() << " electrons:\n";
272 //
273 if (m_elecneg1 >= 0) {
274 std::cout << " leading e-: " << m_elecneg1
275 << " Pt = " << negative.leadingPt << '\n';
276 }
277 //
278 if (m_elecneg2 >= 0) {
279 std::cout << " second e-: "<< m_elecneg2
280 << " Pt = " << negative.subleadingPt << '\n';
281 }
282 //
283 if (m_elecpos1 >= 0) {
284 std::cout << " leading e+: " << m_elecpos1
285 << " Pt = " << positive.leadingPt << '\n';
286 }
287 //
288 if (m_elecpos2 >= 0) {
289 std::cout << " second e+: " << m_elecpos2
290 << " Pt = " << positive.subleadingPt << '\n';
291 }
292 }
293 const auto addElectron = [this](auto& output, int index) {
294 if (index >= 0) {
295 output.push_back(m_pxElTrackList[static_cast<std::size_t>(index)]);
296 }
297 };
302 //
303 (*m_msgStream) << MSG::DEBUG << " -- ElectronSelector::OrderElectronList -- COMPLETED -- status: true\n";
304 return true;
305}
306
309{
310 if (m_doDebug) std::cout << " -- ElectronSelector::RetrieveVertices -- START -- list size: "
312 << "\n";
313 bool goodvertices = false;
314 const int nverticesfound = 1; // WARNING default must be 0 --> set to 1 for R22 --> needs to be fixed
315 if (nverticesfound >= 1) goodvertices = true;
316 if (m_doDebug) std::cout << " -- ElectronSelector::RetrieveVertices -- COMPLETED -- status: " << goodvertices << std::endl;
317 return goodvertices;
318}
319
322{
323 if (i >= m_goodElecNegTrackParticleList.size()) { // requesting out of range electron
324 return nullptr;
325 }
327}
328
331{
332 if (i >= m_goodElecPosTrackParticleList.size()) { // requesting out of range electron
333 return nullptr;
334 }
336}
#define endmsg
Electron selector tool to select objects in Athena using an underlying pure ROOT tool.
DataModel_detail::const_iterator< DataVector > const_iterator
Definition DataVector.h:838
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
AsgElectronLikelihoodTool * m_LHTool2015
const xAOD::TrackParticle * GetElecPosTrackParticle(size_t i)
MsgStream * m_msgStream
std::vector< const xAOD::TrackParticle * > m_pxElTrackList
const xAOD::Muon * m_pxElectron
static std::atomic< unsigned int > s_uNumInstances
bool RecordElectron(const xAOD::Electron *)
const xAOD::TrackParticle * GetElecNegTrackParticle(size_t i)
std::vector< const xAOD::TrackParticle * > m_goodElecPosTrackParticleList
std::vector< const xAOD::TrackParticle * > m_goodElecNegTrackParticleList
void PrepareElectronList(const xAOD::ElectronContainer *pxElecContainer)
std::string m_xSampleName
virtual double eta() const
The pseudorapidity ( ) of the particle.
virtual double e() const
The total energy of the particle.
uint16_t author(uint16_t bitmask=EgammaParameters::AuthorALL) const
Get author.
const xAOD::CaloCluster * caloCluster(size_t index=0) const
Pointer to the xAOD::CaloCluster/s that define the electron candidate.
const xAOD::TrackParticle * trackParticle(size_t index=0) const
Pointer to the xAOD::TrackParticle/s that match the electron candidate.
float theta() const
Returns the parameter, which has range 0 to .
virtual double pt() const override final
The transverse momentum ( ) of the particle.
virtual double eta() const override final
The pseudorapidity ( ) of the particle.
singleton-like access to IMessageSvc via open function and helper
int count(std::string s, const std::string &regx)
count how many occurances of a regx are in a string
Definition hcg.cxx:148
IMessageSvc * getMessageSvc(bool quiet=false)
Definition index.py:1
const uint16_t AuthorElectron
Object Reconstructed by standard cluster-based algorithm.
Definition EgammaDefs.h:24
ElectronContainer_v1 ElectronContainer
Definition of the current "electron container version".
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
TrackParticle_v1 TrackParticle
Reference the current persistent version:
Electron_v1 Electron
Definition of the current "egamma version".