ATLAS Offline Software
ElectronSelector.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 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
20 #include "StoreGate/StoreGateSvc.h"
21 #include "CLHEP/Random/RandFlat.h"
22 
23 #include "GaudiKernel/IToolSvc.h"
24 
25 
26 // Static declarations
27 std::atomic<unsigned int> ElectronSelector::s_uNumInstances;
28 
29 //==================================================================================
30 // Public Methods
31 //==================================================================================
33  m_doDebug ( false ),
34  m_ptCut ( 10. ),
35  m_etaCut ( 2.47 ) // 2.47 is the official acceptance for central electrons. Forward electrons is another story...
36 {
38 
39  std::stringstream xTmp; xTmp << s_uNumInstances;
40  m_xSampleName = "ElectronSelector_" + xTmp.str();
41 
42  m_pxElectron = nullptr;
43 
44  m_msgStream = new MsgStream(PerfMonServices::getMessagingService(), "InDetPerformanceMonitoring" );
45 }
46 
49 {
51  delete m_msgStream;
52 }
53 
56 {
57  (*m_msgStream) << MSG::DEBUG << " -- ElectronSelector::Init -- START -- " << endmsg;
58  ISvcLocator* serviceLocator = Gaudi::svcLocator();
59  IToolSvc* toolSvc;
60  StatusCode sc = serviceLocator->service("ToolSvc", toolSvc, true);
61 
62  if ( sc.isFailure() || toolSvc == nullptr ) {
63  (*m_msgStream) << MSG::ERROR << " * ElectronSelector::Init * Unable to retrieve ToolSvc " << endmsg;
64  return;
65  }
66 
67  // PARENT::Init();
68 
69  //---Electron Likelihood tool---
70  // m_doIDCuts = true;
71  (*m_msgStream) << MSG::INFO << "ElectronSelector::Init -- Setting up electron LH tool." << endmsg;
72  m_LHTool2015 = new AsgElectronLikelihoodTool ("m_LHTool2015");
73 
74  const std::string elecWorkingPoint = "LooseLHElectron"; // "MediumLHElectron" "TightLHElectron"
75 
76  if((m_LHTool2015->setProperty("WorkingPoint",elecWorkingPoint.c_str())).isFailure()) {
77  (*m_msgStream) << MSG::WARNING << "Failure loading ConfigFile for electron likelihood tool with working point: " << elecWorkingPoint.c_str() << endmsg;
78  }
79  else {
80  (*m_msgStream) << MSG::INFO << "Loading ConfigFile for electron likelihood tool with working point: " << elecWorkingPoint << ". SUCCESS " << endmsg;
81  }
82 
83  // check config files at: https://twiki.cern.ch/twiki/bin/viewauth/AtlasProtected/EGammaIdentificationRun2
84  std::string confDir = "ElectronPhotonSelectorTools/offline/mc20_20210514/ElectronLikelihoodVeryLooseOfflineConfig2017_Smooth.conf";
85  if ( (m_LHTool2015->setProperty("ConfigFile", confDir)).isSuccess()) {
86  (*m_msgStream) << MSG::INFO << "Electron likelihood config ("<< confDir.c_str() << ") setting SUCCESS!" << endmsg;
87  }
88  else {
89  (*m_msgStream) << MSG::WARNING << "Electron likelihood config ("<< confDir.c_str() << ") setting FAILURE" << endmsg;
90  }
91 
92  if (m_LHTool2015->initialize().isSuccess()) {
93  (*m_msgStream) << MSG::INFO << "Electron likelihood tool initialize() SUCCESS!" << endmsg;
94  }
95  else {
96  (*m_msgStream) << MSG::WARNING << "Electron likelihood tool initialize() FAILURE!" << endmsg;
97  }
98 
99  (*m_msgStream) << MSG::DEBUG << " --ElectronSelector::Init -- COMPLETED -- " << endmsg;
100  return;
101 }
102 
105 {
106  (*m_msgStream) << MSG::DEBUG << " --ElectronSelector::PrepareElectronList -- START -- " << endmsg;
107  Clear(); // clear current list records
108 
109  using electron_iterator = xAOD::ElectronContainer::const_iterator;
110  electron_iterator iter = pxElecContainer->begin();
111  electron_iterator iterEnd = pxElecContainer->end();
112 
113  // Loop over the Electrons
114  int electroncount = 0;
115  for(; iter != iterEnd ; ++iter) {
116  electroncount++;
117  (*m_msgStream) << MSG::DEBUG << " -- ElectronSelector::PrepareElectronList -- candiate electron " << electroncount
118  << " has author " << (*iter)->author(xAOD::EgammaParameters::AuthorElectron)
119  << endmsg;
120  const xAOD::Electron * ELE = (*iter);
121  if ( RecordElectron(ELE) ) {
122  (*m_msgStream) << MSG::DEBUG << " -- ElectronSelector::PrepareElectronList -- candiate electron " << electroncount
123  << " is good "
124  << endmsg;
125  }
126  }
127  bool progressingwell = true;
128 
129  (*m_msgStream) << MSG::DEBUG << " -- ElectronSelector::PrepareElectronList -- finished recording electrons. "
130  << " recorded electrons: " << m_pxElTrackList.size()
131  << " out of tested electron candidates:" << electroncount << endmsg;
132  if (m_pxElTrackList.size() < 2) progressingwell = false;
133  if (progressingwell) progressingwell = OrderElectronList ();
134  if (progressingwell) progressingwell = RetrieveVertices ();
135 
136  if (!progressingwell) {
137  (*m_msgStream) << MSG::DEBUG << " -- ElectronSelector::PrepareElectronList -- FAILED -- this event has not even a good e+e- pair " << endmsg;
138  this->Clear(); // reset the content as it is not going to be used
139  }
140 
141  (*m_msgStream) << MSG::DEBUG << " -- ElectronSelector::PrepareElectronList -- COMPLETED -- electroncount -- m_pxElTrackList.size() / all = "
142  << m_pxElTrackList.size() << " / " << electroncount
143  << endmsg;
144  return;
145 }
146 
149 {
150  // start assuming electron candidate is good
151  bool electronisgood = true;
152 
153  // check the electron satisfies the working point
154  if (!m_LHTool2015->accept(thisElec) ) {
155  electronisgood = false;
156  (*m_msgStream) << MSG::DEBUG << " -- electron fails workingpoint selection -- " << endmsg;
157  }
158 
159  //Get the track particle
160  const xAOD::TrackParticle* theTrackParticle = thisElec->trackParticle();
161 
162  if (!theTrackParticle) {
163  electronisgood = false;
164  (*m_msgStream) << MSG::DEBUG << " -- electron fails trackparticle -- " << endmsg;
165  }
166 
167  if (electronisgood && thisElec->author(xAOD::EgammaParameters::AuthorElectron) != 1) {
168  electronisgood = false;
169  (*m_msgStream) << MSG::DEBUG << " -- electron fails author -- " << thisElec->author(xAOD::EgammaParameters::AuthorElectron) << endmsg;
170  }
171 
172  if (electronisgood && theTrackParticle->pt() * m_CGeV < m_ptCut ) { // pt cut given in GeV
173  electronisgood = false;
174  (*m_msgStream) << MSG::DEBUG << " -- electron fails pt cut -- pt= " << theTrackParticle->pt()
175  << " < " << m_ptCut << " (cut value) "
176  << endmsg;
177  }
178 
179  const xAOD::CaloCluster* cluster = thisElec->caloCluster();
180  if(!cluster) {
181  electronisgood = false;
182  (*m_msgStream) << MSG::DEBUG << " -- electron candidate has no CaloCluster " << endmsg;
183  }
184 
185  if (electronisgood && (cluster->e() * sin(theTrackParticle->theta())) * m_CGeV < m_ptCut) { // cut on et of the cluster
186  electronisgood = false;
187  (*m_msgStream) << MSG::DEBUG << " -- electron fails cluster Et cut -- Et= " << (cluster->e() * cos(theTrackParticle->theta()))* m_CGeV
188  << " < " << m_ptCut << " (cut value) "
189  << endmsg;
190  }
191 
192  if (electronisgood && (std::abs(cluster->eta())> m_etaCut || std::abs(theTrackParticle->eta())> m_etaCut) ) { // cut in eta for the cluster and the track
193  electronisgood = false;
194  (*m_msgStream) << MSG::DEBUG << " -- electron fails eta cut -- cluster_eta= " << cluster->eta() << endmsg;
195  }
196 
197  if (electronisgood) {
198  // store this electron
199  m_pxElTrackList.push_back(theTrackParticle);
200 
201  (*m_msgStream) << MSG::DEBUG << " * RecordElectron * good electron found -> store this electron with pt " << theTrackParticle->pt()
202  << " --> current m_pxElTrackList.size(): " << m_pxElTrackList.size()
203  << std::endl;
204  }
205 
206  return electronisgood;
207 }
208 
211 {
212  m_pxElTrackList.clear();
215 
216  // -1 means not assigned
217  m_elecneg1 = -1;
218  m_elecneg2 = -1;
219  m_elecpos1 = -1;
220  m_elecpos2 = -1;
221 
222  return;
223 }
224 
227 {
228  (*m_msgStream) << MSG::DEBUG << " -- ElectronSelector::OrderElectronList -- START -- list size: " << m_pxElTrackList.size( ) << endmsg;
229 
230  bool goodlist = true;
231 
232  if (m_pxElTrackList.size() >= 2) { // we need at least 2 electrons
233  double ptMinus1 = 0.;
234  double ptMinus2 = 0.;
235  double ptPlus1 = 0.;
236  double ptPlus2 = 0.;
237 
238  int elecnegcount = 0;
239  int elecposcount = 0;
240 
241  for (int ielec=0; ielec < (int) m_pxElTrackList.size(); ielec++) {
242  // negative electrons
243  if (m_pxElTrackList.at(ielec)->charge()== -1) { // positive electron
244  elecnegcount++;
245  if (m_pxElTrackList.at(ielec)->pt()> ptMinus1) {
246  // store 1st in 2nd
247  ptMinus2 = ptMinus1;
249  // now store the new one in 1st place
250  ptMinus1 = m_pxElTrackList.at(ielec)->pt();
251  m_elecneg1 = ielec;
252  }
253  else if (m_pxElTrackList.at(ielec)->pt()> ptMinus2) {
254  // store the new one in 2nd place
255  ptMinus2 = m_pxElTrackList.at(ielec)->pt();
256  m_elecneg2 = ielec;
257  }
258  }
259  // positive electrons
260  if (m_pxElTrackList.at(ielec)->charge()== 1) { // positive electron
261  elecposcount++;
262  if (m_pxElTrackList.at(ielec)->pt()> ptPlus1) {
263  // store 1st in 2nd
264  ptPlus2 = ptPlus1;
266  // now store the new one in 1st place
267  ptPlus1 = m_pxElTrackList.at(ielec)->pt();
268  m_elecpos1 = ielec;
269  }
270  else if (m_pxElTrackList.at(ielec)->pt()> ptPlus2) {
271  // store the new one in 2nd place
272  ptPlus2 = m_pxElTrackList.at(ielec)->pt();
273  m_elecpos2 = ielec;
274  }
275  }
276  }
277 
278  if (elecposcount == 0 || elecnegcount == 0) {
279  // We need at least one e- and one e+
280  if (m_doDebug) std::cout << " -- ElectronSelector::OrderElectronList -- No opposite charge electrons --> DISCARD ALL ELECTRONS -- " << std::endl;
281  elecposcount = 0;
282  elecnegcount = 0;
283  this->Clear();
284  goodlist = false;
285  }
286 
287  if (m_doDebug && elecposcount + elecnegcount >= 2 ){
288  std::cout << " -- ElectronSelector::OrderElectronList -- electron summary list taking " << elecposcount + elecnegcount
289  << " electrons from the input list of " << m_pxElTrackList.size() << " electrons: " << std::endl;
290  if (m_elecneg1 >= 0) std::cout << " leading e-: " << m_elecneg1 << " Pt = " << ptMinus1 << std::endl;
291  if (m_elecneg2 >= 0) std::cout << " second e-: " << m_elecneg2 << " Pt = " << ptMinus2 << std::endl;
292  if (m_elecpos1 >= 0) std::cout << " leading e+: " << m_elecpos1 << " Pt = " << ptPlus1 << std::endl;
293  if (m_elecpos2 >= 0) std::cout << " second e+: " << m_elecpos2 << " Pt = " << ptPlus2 << std::endl;
294  }
295 
296  if (elecposcount + elecnegcount >= 2){ // fill the final list of electrons
301  }
302  }
303 
304  (*m_msgStream) << MSG::DEBUG << " -- ElectronSelector::OrderElectronList -- COMPLETED -- status: "<< goodlist << std::endl;
305  return goodlist;
306 }
307 
310 {
311  if (m_doDebug) std::cout << " -- ElectronSelector::RetrieveVertices -- START -- list size: "
313  << std::endl;
314  bool goodvertices = false;
315  int nverticesfound = 1; // WARNING default must be 0 --> set to 1 for R22 --> needs to be fixed
316 
317  if (m_goodElecNegTrackParticleList.size() >= 1 && m_goodElecPosTrackParticleList.size() >= 1) { // we need at least 1 e- and 1 e+
318  // then, check the distances between the e- and e+ vertices, and make sure at least 1 pair comes from same vertex
319  for (size_t ielec = 0; ielec < m_goodElecNegTrackParticleList.size(); ielec++) {
320  // loop on e-
321  // R21 -> R22 SALVA // TrkParticles have no vertex in R22 --> THIS NEEDS A FIX
322  /*
323  if (m_goodElecNegTrackParticleList.at(ielec)->vertex()) {
324  if (m_doDebug) std::cout << " e-(" << ielec <<")->vertex()->v= (" << m_goodElecNegTrackParticleList.at(ielec)->vertex()->x()
325  << ", " << m_goodElecNegTrackParticleList.at(ielec)->vertex()->y()
326  << ", " << m_goodElecNegTrackParticleList.at(ielec)->vertex()->z()
327  << ") " << std::endl;
328 
329  // for (unsigned int iposi = 0; iposi < m_goodElecPosTrackParticleList.size(); iposi++) {
330  for (size_t iposi = 0; iposi < m_goodElecPosTrackParticleList.size(); iposi++) {
331  if (m_goodElecPosTrackParticleList.at(iposi)->vertex()) {
332  if (m_doDebug) std::cout << " e+(" << iposi <<")->vertex()->v= (" << m_goodElecPosTrackParticleList.at(iposi)->vertex()->x()
333  << ", " << m_goodElecPosTrackParticleList.at(iposi)->vertex()->y()
334  << ", " << m_goodElecPosTrackParticleList.at(iposi)->vertex()->z()
335  << ") " << std::endl;
336  float delta_x = std::abs( m_goodElecNegTrackParticleList.at(ielec)->vertex()->x()-m_goodElecPosTrackParticleList.at(iposi)->vertex()->x() );
337  float delta_y = std::abs( m_goodElecNegTrackParticleList.at(ielec)->vertex()->y()-m_goodElecPosTrackParticleList.at(iposi)->vertex()->y() );
338  float delta_z = std::abs( m_goodElecNegTrackParticleList.at(ielec)->vertex()->z()-m_goodElecPosTrackParticleList.at(iposi)->vertex()->z() );
339 
340  if (delta_x < m_deltaXYcut && delta_y < m_deltaXYcut && delta_z < m_deltaZcut) {
341  nverticesfound++;
342  if (m_doDebug) std::cout << " ELEC-BINGO !!! e+e- pair in same vertex !!! e-[" << ielec
343  << "] e+[" << iposi<< "] count: " << nverticesfound << std::endl;
344  } // vertex is the same
345  } // positron has vertex
346  } // loop on positrons
347  } // electron has vertex
348  */
349  } // loop on electrons (e-)
350  } // at least one e+e- pair
351 
352  if (nverticesfound >= 1) goodvertices = true;
353 
354  if (m_doDebug) std::cout << " -- ElectronSelector::RetrieveVertices -- COMPLETED -- status: " << goodvertices << std::endl;
355  return goodvertices;
356 }
357 
360 {
361  if (i >= m_goodElecNegTrackParticleList.size()) { // requesting out of range electron
362  return nullptr;
363  }
365 }
366 
369 {
370  if (i >= m_goodElecPosTrackParticleList.size()) { // requesting out of range electron
371  return nullptr;
372  }
374 }
ElectronSelector::m_etaCut
float m_etaCut
Definition: ElectronSelector.h:76
ElectronSelector::m_pxElTrackList
std::vector< const xAOD::TrackParticle * > m_pxElTrackList
Definition: ElectronSelector.h:68
ElectronSelector::GetElecNegTrackParticle
const xAOD::TrackParticle * GetElecNegTrackParticle(size_t i)
Definition: ElectronSelector.cxx:359
xAOD::TrackParticle_v1::pt
virtual double pt() const override final
The transverse momentum ( ) of the particle.
Definition: TrackParticle_v1.cxx:73
PerfMonServices::getMessagingService
static IMessageSvc * getMessagingService()
Definition: PerfMonServices.h:36
ElectronSelector::m_goodElecPosTrackParticleList
std::vector< const xAOD::TrackParticle * > m_goodElecPosTrackParticleList
Definition: ElectronSelector.h:70
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
DataVector::const_iterator
DataModel_detail::const_iterator< DataVector > const_iterator
Standard const_iterator.
Definition: DataVector.h:837
ElectronSelector::GetElecPosTrackParticle
const xAOD::TrackParticle * GetElecPosTrackParticle(size_t i)
Definition: ElectronSelector.cxx:368
ElectronSelector::m_doDebug
bool m_doDebug
Definition: ElectronSelector.h:73
xAOD::TrackParticle_v1::eta
virtual double eta() const override final
The pseudorapidity ( ) of the particle.
Definition: TrackParticle_v1.cxx:77
ElectronSelector::s_uNumInstances
static std::atomic< unsigned int > s_uNumInstances
Definition: ElectronSelector.h:56
xAOD::Egamma_v1::author
uint16_t author(uint16_t bitmask=EgammaParameters::AuthorALL) const
Get author.
Definition: Egamma_v1.cxx:166
AsgElectronLikelihoodTool::accept
virtual asg::AcceptData accept(const xAOD::IParticle *part) const override final
The main accept method: using the generic interface.
Definition: AsgElectronLikelihoodTool.cxx:868
xAOD::Electron_v1::trackParticle
const xAOD::TrackParticle * trackParticle(size_t index=0) const
Pointer to the xAOD::TrackParticle/s that match the electron candidate.
Definition: Electron_v1.cxx:55
ElectronSelector::OrderElectronList
bool OrderElectronList()
Definition: ElectronSelector.cxx:226
drawFromPickle.cos
cos
Definition: drawFromPickle.py:36
PerfMonServices.h
AsgElectronLikelihoodTool
Electron selector tool to select objects in Athena using an underlying pure ROOT tool.
Definition: AsgElectronLikelihoodTool.h:30
AthenaPoolTestRead.sc
sc
Definition: AthenaPoolTestRead.py:27
ElectronSelector::m_elecpos2
int m_elecpos2
Definition: ElectronSelector.h:85
ElectronSelector::m_msgStream
MsgStream * m_msgStream
Definition: ElectronSelector.h:64
ElectronSelector::m_goodElecNegTrackParticleList
std::vector< const xAOD::TrackParticle * > m_goodElecNegTrackParticleList
Definition: ElectronSelector.h:69
xAOD::CaloCluster_v1
Description of a calorimeter cluster.
Definition: CaloCluster_v1.h:59
xAOD::CaloCluster_v1::eta
virtual double eta() const
The pseudorapidity ( ) of the particle.
Definition: CaloCluster_v1.cxx:251
lumiFormat.i
int i
Definition: lumiFormat.py:92
endmsg
#define endmsg
Definition: AnalysisConfig_Ntuple.cxx:63
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ElectronSelector::RecordElectron
bool RecordElectron(const xAOD::Electron *)
Definition: ElectronSelector.cxx:148
ElectronSelector::PrepareElectronList
void PrepareElectronList(const xAOD::ElectronContainer *pxElecContainer)
Definition: ElectronSelector.cxx:104
ElectronSelector::m_pxElectron
const xAOD::Muon * m_pxElectron
Definition: ElectronSelector.h:67
ElectronSelector::ElectronSelector
ElectronSelector()
Definition: ElectronSelector.cxx:32
xAOD::Egamma_v1::caloCluster
const xAOD::CaloCluster * caloCluster(size_t index=0) const
Pointer to the xAOD::CaloCluster/s that define the electron candidate.
Definition: Egamma_v1.cxx:388
DataVector
Derived DataVector<T>.
Definition: DataVector.h:581
ElectronSelector::m_LHTool2015
AsgElectronLikelihoodTool * m_LHTool2015
Definition: ElectronSelector.h:79
xAOD::Electron_v1
Definition: Electron_v1.h:34
DataVector::end
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
ElectronSelector::m_CGeV
const float m_CGeV
Definition: ElectronSelector.h:88
ElectronSelector::RetrieveVertices
bool RetrieveVertices()
Definition: ElectronSelector.cxx:309
ElectronSelector.h
DEBUG
#define DEBUG
Definition: page_access.h:11
ElectronSelector::Clear
void Clear()
Definition: ElectronSelector.cxx:210
ElectronSelector::m_elecneg1
int m_elecneg1
Definition: ElectronSelector.h:82
AsgElectronLikelihoodTool::initialize
virtual StatusCode initialize() override
Gaudi Service Interface method implementations.
Definition: AsgElectronLikelihoodTool.cxx:80
xAOD::TrackParticle_v1
Class describing a TrackParticle.
Definition: TrackParticle_v1.h:43
drawFromPickle.sin
sin
Definition: drawFromPickle.py:36
ElectronSelector::m_ptCut
float m_ptCut
Definition: ElectronSelector.h:75
ElectronSelector::~ElectronSelector
~ElectronSelector()
Definition: ElectronSelector.cxx:48
EventAnalysis::m_xSampleName
std::string m_xSampleName
Definition: EventAnalysis.h:80
ElectronSelector::Init
void Init()
Definition: ElectronSelector.cxx:55
ElectronSelector::m_elecpos1
int m_elecpos1
Definition: ElectronSelector.h:84
xAOD::TrackParticle_v1::theta
float theta() const
Returns the parameter, which has range 0 to .
StoreGateSvc.h
xAOD::CaloCluster_v1::e
virtual double e() const
The total energy of the particle.
Definition: CaloCluster_v1.cxx:265
DataVector::begin
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
xAOD::EgammaParameters::AuthorElectron
const uint16_t AuthorElectron
Object Reconstructed by standard cluster-based algorithm.
Definition: EgammaDefs.h:24
ElectronSelector::m_elecneg2
int m_elecneg2
Definition: ElectronSelector.h:83