ATLAS Offline Software
Loading...
Searching...
No Matches
ElectronSelector.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 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#include <sstream>
19// ATLAS headers
22#include "CLHEP/Random/RandFlat.h"
23
24// Static declarations
25std::atomic<unsigned int> ElectronSelector::s_uNumInstances;
26
27//==================================================================================
28// Public Methods
29//==================================================================================
31 m_doDebug ( false ),
32 m_ptCut ( 10. ),
33 m_etaCut ( 2.47 ) // 2.47 is the official acceptance for central electrons. Forward electrons is another story...
34{
36
37 std::stringstream xTmp; xTmp << s_uNumInstances;
38 m_xSampleName = "ElectronSelector_" + xTmp.str();
39
40 m_pxElectron = nullptr;
41
42 m_msgStream = new MsgStream(Athena::getMessageSvc(), "InDetPerformanceMonitoring" );
43}
44
51
54{
55 (*m_msgStream) << MSG::DEBUG << " -- ElectronSelector::Init -- START -- " << endmsg;
56
57 // PARENT::Init();
58
59 //---Electron Likelihood tool---
60 // m_doIDCuts = true;
61 (*m_msgStream) << MSG::INFO << "ElectronSelector::Init -- Setting up electron LH tool." << endmsg;
62 m_LHTool2015 = new AsgElectronLikelihoodTool ("m_LHTool2015");
63
64 const std::string elecWorkingPoint = "LooseLHElectron"; // "MediumLHElectron" "TightLHElectron"
65
66 if((m_LHTool2015->setProperty("WorkingPoint",elecWorkingPoint.c_str())).isFailure()) {
67 (*m_msgStream) << MSG::WARNING << "Failure loading ConfigFile for electron likelihood tool with working point: " << elecWorkingPoint.c_str() << endmsg;
68 }
69 else {
70 (*m_msgStream) << MSG::INFO << "Loading ConfigFile for electron likelihood tool with working point: " << elecWorkingPoint << ". SUCCESS " << endmsg;
71 }
72
73 // check config files at: https://twiki.cern.ch/twiki/bin/viewauth/AtlasProtected/EGammaIdentificationRun2
74 std::string confDir = "ElectronPhotonSelectorTools/offline/mc20_20210514/ElectronLikelihoodVeryLooseOfflineConfig2017_Smooth.conf";
75 if ( (m_LHTool2015->setProperty("ConfigFile", confDir)).isSuccess()) {
76 (*m_msgStream) << MSG::INFO << "Electron likelihood config ("<< confDir.c_str() << ") setting SUCCESS!" << endmsg;
77 }
78 else {
79 (*m_msgStream) << MSG::WARNING << "Electron likelihood config ("<< confDir.c_str() << ") setting FAILURE" << endmsg;
80 }
81
82 if (m_LHTool2015->initialize().isSuccess()) {
83 (*m_msgStream) << MSG::INFO << "Electron likelihood tool initialize() SUCCESS!" << endmsg;
84 }
85 else {
86 (*m_msgStream) << MSG::WARNING << "Electron likelihood tool initialize() FAILURE!" << endmsg;
87 }
88
89 (*m_msgStream) << MSG::DEBUG << " --ElectronSelector::Init -- COMPLETED -- " << endmsg;
90 return;
91}
92
95{
96 (*m_msgStream) << MSG::DEBUG << " --ElectronSelector::PrepareElectronList -- START -- " << endmsg;
97 Clear(); // clear current list records
98
99 using electron_iterator = xAOD::ElectronContainer::const_iterator;
100 electron_iterator iter = pxElecContainer->begin();
101 electron_iterator iterEnd = pxElecContainer->end();
102
103 // Loop over the Electrons
104 int electroncount = 0;
105 for(; iter != iterEnd ; ++iter) {
106 electroncount++;
107 (*m_msgStream) << MSG::DEBUG << " -- ElectronSelector::PrepareElectronList -- candiate electron " << electroncount
108 << " has author " << (*iter)->author(xAOD::EgammaParameters::AuthorElectron)
109 << endmsg;
110 const xAOD::Electron * ELE = (*iter);
111 if ( RecordElectron(ELE) ) {
112 (*m_msgStream) << MSG::DEBUG << " -- ElectronSelector::PrepareElectronList -- candiate electron " << electroncount
113 << " is good "
114 << endmsg;
115 }
116 }
117 bool progressingwell = true;
118
119 (*m_msgStream) << MSG::DEBUG << " -- ElectronSelector::PrepareElectronList -- finished recording electrons. "
120 << " recorded electrons: " << m_pxElTrackList.size()
121 << " out of tested electron candidates:" << electroncount << endmsg;
122 if (m_pxElTrackList.size() < 2) progressingwell = false;
123 if (progressingwell) progressingwell = OrderElectronList ();
124 if (progressingwell) progressingwell = RetrieveVertices ();
125
126 if (!progressingwell) {
127 (*m_msgStream) << MSG::DEBUG << " -- ElectronSelector::PrepareElectronList -- FAILED -- this event has not even a good e+e- pair " << endmsg;
128 this->Clear(); // reset the content as it is not going to be used
129 }
130
131 (*m_msgStream) << MSG::DEBUG << " -- ElectronSelector::PrepareElectronList -- COMPLETED -- electroncount -- m_pxElTrackList.size() / all = "
132 << m_pxElTrackList.size() << " / " << electroncount
133 << endmsg;
134 return;
135}
136
139{
140 // start assuming electron candidate is good
141 bool electronisgood = true;
142
143 // check the electron satisfies the working point
144 if (!m_LHTool2015->accept(thisElec) ) {
145 electronisgood = false;
146 (*m_msgStream) << MSG::DEBUG << " -- electron fails workingpoint selection -- " << endmsg;
147 }
148
149 //Get the track particle
150 const xAOD::TrackParticle* theTrackParticle = thisElec->trackParticle();
151
152 if (!theTrackParticle) {
153 electronisgood = false;
154 (*m_msgStream) << MSG::DEBUG << " -- electron fails trackparticle -- " << endmsg;
155 }
156
157 if (electronisgood && thisElec->author(xAOD::EgammaParameters::AuthorElectron) != 1) {
158 electronisgood = false;
159 (*m_msgStream) << MSG::DEBUG << " -- electron fails author -- " << thisElec->author(xAOD::EgammaParameters::AuthorElectron) << endmsg;
160 }
161
162 if (electronisgood && theTrackParticle->pt() * m_CGeV < m_ptCut ) { // pt cut given in GeV
163 electronisgood = false;
164 (*m_msgStream) << MSG::DEBUG << " -- electron fails pt cut -- pt= " << theTrackParticle->pt()
165 << " < " << m_ptCut << " (cut value) "
166 << endmsg;
167 }
168
169 const xAOD::CaloCluster* cluster = thisElec->caloCluster();
170 if(!cluster) {
171 electronisgood = false;
172 (*m_msgStream) << MSG::DEBUG << " -- electron candidate has no CaloCluster " << endmsg;
173 }
174
175 if (electronisgood && (cluster->e() * sin(theTrackParticle->theta())) * m_CGeV < m_ptCut) { // cut on et of the cluster
176 electronisgood = false;
177 (*m_msgStream) << MSG::DEBUG << " -- electron fails cluster Et cut -- Et= " << (cluster->e() * cos(theTrackParticle->theta()))* m_CGeV
178 << " < " << m_ptCut << " (cut value) "
179 << endmsg;
180 }
181
182 if (electronisgood && (std::abs(cluster->eta())> m_etaCut || std::abs(theTrackParticle->eta())> m_etaCut) ) { // cut in eta for the cluster and the track
183 electronisgood = false;
184 (*m_msgStream) << MSG::DEBUG << " -- electron fails eta cut -- cluster_eta= " << cluster->eta() << endmsg;
185 }
186
187 if (electronisgood) {
188 // store this electron
189 m_pxElTrackList.push_back(theTrackParticle);
190
191 (*m_msgStream) << MSG::DEBUG << " * RecordElectron * good electron found -> store this electron with pt " << theTrackParticle->pt()
192 << " --> current m_pxElTrackList.size(): " << m_pxElTrackList.size()
193 << std::endl;
194 }
195
196 return electronisgood;
197}
198
201{
202 m_pxElTrackList.clear();
205
206 // -1 means not assigned
207 m_elecneg1 = -1;
208 m_elecneg2 = -1;
209 m_elecpos1 = -1;
210 m_elecpos2 = -1;
211
212 return;
213}
214
217{
218 (*m_msgStream) << MSG::DEBUG << " -- ElectronSelector::OrderElectronList -- START -- list size: " << m_pxElTrackList.size( ) << endmsg;
219
220 bool goodlist = true;
221
222 if (m_pxElTrackList.size() >= 2) { // we need at least 2 electrons
223 double ptMinus1 = 0.;
224 double ptMinus2 = 0.;
225 double ptPlus1 = 0.;
226 double ptPlus2 = 0.;
227
228 int elecnegcount = 0;
229 int elecposcount = 0;
230
231 for (int ielec=0; ielec < (int) m_pxElTrackList.size(); ielec++) {
232 // negative electrons
233 if (m_pxElTrackList.at(ielec)->charge()== -1) { // positive electron
234 elecnegcount++;
235 if (m_pxElTrackList.at(ielec)->pt()> ptMinus1) {
236 // store 1st in 2nd
237 ptMinus2 = ptMinus1;
239 // now store the new one in 1st place
240 ptMinus1 = m_pxElTrackList.at(ielec)->pt();
241 m_elecneg1 = ielec;
242 }
243 else if (m_pxElTrackList.at(ielec)->pt()> ptMinus2) {
244 // store the new one in 2nd place
245 ptMinus2 = m_pxElTrackList.at(ielec)->pt();
246 m_elecneg2 = ielec;
247 }
248 }
249 // positive electrons
250 if (m_pxElTrackList.at(ielec)->charge()== 1) { // positive electron
251 elecposcount++;
252 if (m_pxElTrackList.at(ielec)->pt()> ptPlus1) {
253 // store 1st in 2nd
254 ptPlus2 = ptPlus1;
256 // now store the new one in 1st place
257 ptPlus1 = m_pxElTrackList.at(ielec)->pt();
258 m_elecpos1 = ielec;
259 }
260 else if (m_pxElTrackList.at(ielec)->pt()> ptPlus2) {
261 // store the new one in 2nd place
262 ptPlus2 = m_pxElTrackList.at(ielec)->pt();
263 m_elecpos2 = ielec;
264 }
265 }
266 }
267
268 if (elecposcount == 0 || elecnegcount == 0) {
269 // We need at least one e- and one e+
270 if (m_doDebug) std::cout << " -- ElectronSelector::OrderElectronList -- No opposite charge electrons --> DISCARD ALL ELECTRONS -- " << std::endl;
271 elecposcount = 0;
272 elecnegcount = 0;
273 this->Clear();
274 goodlist = false;
275 }
276
277 if (m_doDebug && elecposcount + elecnegcount >= 2 ){
278 std::cout << " -- ElectronSelector::OrderElectronList -- electron summary list taking " << elecposcount + elecnegcount
279 << " electrons from the input list of " << m_pxElTrackList.size() << " electrons: " << std::endl;
280 if (m_elecneg1 >= 0) std::cout << " leading e-: " << m_elecneg1 << " Pt = " << ptMinus1 << std::endl;
281 if (m_elecneg2 >= 0) std::cout << " second e-: " << m_elecneg2 << " Pt = " << ptMinus2 << std::endl;
282 if (m_elecpos1 >= 0) std::cout << " leading e+: " << m_elecpos1 << " Pt = " << ptPlus1 << std::endl;
283 if (m_elecpos2 >= 0) std::cout << " second e+: " << m_elecpos2 << " Pt = " << ptPlus2 << std::endl;
284 }
285
286 if (elecposcount + elecnegcount >= 2){ // fill the final list of electrons
291 }
292 }
293
294 (*m_msgStream) << MSG::DEBUG << " -- ElectronSelector::OrderElectronList -- COMPLETED -- status: "<< goodlist << std::endl;
295 return goodlist;
296}
297
300{
301 if (m_doDebug) std::cout << " -- ElectronSelector::RetrieveVertices -- START -- list size: "
303 << std::endl;
304 bool goodvertices = false;
305 int nverticesfound = 1; // WARNING default must be 0 --> set to 1 for R22 --> needs to be fixed
306
307 if (m_goodElecNegTrackParticleList.size() >= 1 && m_goodElecPosTrackParticleList.size() >= 1) { // we need at least 1 e- and 1 e+
308 // then, check the distances between the e- and e+ vertices, and make sure at least 1 pair comes from same vertex
309 for (size_t ielec = 0; ielec < m_goodElecNegTrackParticleList.size(); ielec++) {
310 // loop on e-
311 // R21 -> R22 SALVA // TrkParticles have no vertex in R22 --> THIS NEEDS A FIX
312 /*
313 if (m_goodElecNegTrackParticleList.at(ielec)->vertex()) {
314 if (m_doDebug) std::cout << " e-(" << ielec <<")->vertex()->v= (" << m_goodElecNegTrackParticleList.at(ielec)->vertex()->x()
315 << ", " << m_goodElecNegTrackParticleList.at(ielec)->vertex()->y()
316 << ", " << m_goodElecNegTrackParticleList.at(ielec)->vertex()->z()
317 << ") " << std::endl;
318
319 // for (unsigned int iposi = 0; iposi < m_goodElecPosTrackParticleList.size(); iposi++) {
320 for (size_t iposi = 0; iposi < m_goodElecPosTrackParticleList.size(); iposi++) {
321 if (m_goodElecPosTrackParticleList.at(iposi)->vertex()) {
322 if (m_doDebug) std::cout << " e+(" << iposi <<")->vertex()->v= (" << m_goodElecPosTrackParticleList.at(iposi)->vertex()->x()
323 << ", " << m_goodElecPosTrackParticleList.at(iposi)->vertex()->y()
324 << ", " << m_goodElecPosTrackParticleList.at(iposi)->vertex()->z()
325 << ") " << std::endl;
326 float delta_x = std::abs( m_goodElecNegTrackParticleList.at(ielec)->vertex()->x()-m_goodElecPosTrackParticleList.at(iposi)->vertex()->x() );
327 float delta_y = std::abs( m_goodElecNegTrackParticleList.at(ielec)->vertex()->y()-m_goodElecPosTrackParticleList.at(iposi)->vertex()->y() );
328 float delta_z = std::abs( m_goodElecNegTrackParticleList.at(ielec)->vertex()->z()-m_goodElecPosTrackParticleList.at(iposi)->vertex()->z() );
329
330 if (delta_x < m_deltaXYcut && delta_y < m_deltaXYcut && delta_z < m_deltaZcut) {
331 nverticesfound++;
332 if (m_doDebug) std::cout << " ELEC-BINGO !!! e+e- pair in same vertex !!! e-[" << ielec
333 << "] e+[" << iposi<< "] count: " << nverticesfound << std::endl;
334 } // vertex is the same
335 } // positron has vertex
336 } // loop on positrons
337 } // electron has vertex
338 */
339 } // loop on electrons (e-)
340 } // at least one e+e- pair
341
342 if (nverticesfound >= 1) goodvertices = true;
343
344 if (m_doDebug) std::cout << " -- ElectronSelector::RetrieveVertices -- COMPLETED -- status: " << goodvertices << std::endl;
345 return goodvertices;
346}
347
350{
351 if (i >= m_goodElecNegTrackParticleList.size()) { // requesting out of range electron
352 return nullptr;
353 }
355}
356
359{
360 if (i >= m_goodElecPosTrackParticleList.size()) { // requesting out of range electron
361 return nullptr;
362 }
364}
#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
IMessageSvc * getMessageSvc(bool quiet=false)
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".