ATLAS Offline Software
EGammaAmbiguityTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
13 
15 #include "xAODTracking/Vertex.h"
17 
18 #include "xAODEgamma/Egamma.h"
19 #include "xAODEgamma/Electron.h"
20 #include "xAODEgamma/Photon.h"
24 
25 #include "xAODEgamma/EgammaDefs.h"
28 
29 #define CHECK_HITS(EXP) \
30  if (!(EXP)) { \
31  ATH_MSG_WARNING("Failed \"" << #EXP << "\""); \
32  return false; \
33  }
34 
35 //=============================================================================
36 // Standard constructor
37 //=============================================================================
38 EGammaAmbiguityTool::EGammaAmbiguityTool(const std::string& myname)
39  : asg::AsgTool(myname)
40 {
42  "minNoSiHits",
43  m_MinNoSiHits = 4,
44  "Minimum number of silicon hits to be an electron==>not photon for sure");
46  "minNoPixHits",
47  m_MinNoPixHits = 2,
48  "Minimum number of Pixel hits to be an electron==>not photon for sure");
49  declareProperty("maxEoverPCut",
50  m_maxEoverPCut = 10,
51  "Maximum EoverP , more that this is ambiguous");
53  "minPCut", m_minPtCut = 2000, "Minimum Pt, less than that is ambiguous");
54  declareProperty("maxDeltaR_innermost",
56  "Maximum value for Rconv - RfirstHit for Si+Si conversions "
57  "where both tracks have innermost hits");
58  declareProperty("noVertexNoInnermostAsAmb",
60  "If true classify as ambiguous when there is no vertex and "
61  "no innermost Hits. "
62  "If false classify no vertex as for sure not photon");
63  declareProperty("AcceptAmbiguous",
64  m_acceptAmbiguous = true,
65  "When used as a selector accept the ambiguous as default");
66 }
67 
69  ATH_MSG_DEBUG("Initializing " << name() << "...");
70  return StatusCode::SUCCESS;
71 }
72 
73 // ====================================================================
74 // return value: AuthorElectron, AuthorPhoton, AuthorAmbiguous, AuthorUnknown
76  const xAOD::Vertex* vx,
77  const xAOD::TrackParticle* tp,
79 
81  // Result should stay the same before after calibration corrections
82  double cluster_e = (cluster->clusterSize() != xAOD::CaloCluster::SW_35ele &&
85  ? cluster->altE()
86  : cluster->e();
87 
88  //Number of hits from the track
89  uint8_t trkPixelHits(0);
90  uint8_t trkSiHits(0);
91  if (tp && !tp->summaryValue(trkPixelHits,xAOD::numberOfPixelHits)){
92  ATH_MSG_WARNING("Could not retrieve number of pixel hits from track");
93  }
94  if (tp && !tp->summaryValue(trkSiHits, xAOD::numberOfSCTHits)){
95  ATH_MSG_WARNING("Could not retrieve number of SCT hits from track");
96  }
97  trkSiHits += trkPixelHits;
98 
99  //Check if the vertex is double silicon
101  bool vxDoubleSi = (convType == xAOD::EgammaParameters::doubleSi);
102 
103  // Check if the track particle and the ones associated to the conversion vertex
104  // have innermost pixel hits
105  bool trkHasInnermostHit = tp && hasInnermostPixelHit(*tp);
106  size_t nTrkVxWithInnermostHit = vxDoubleSi ? nTrkWithInnermostPixelHits(*vx) : 0;
107 
108  //See if the Si+Si conversion shares one track with the electron
109  //if not we might have a trident.
110  //if yes and the track is not good we definetely matched the conversion as electron.
111  bool shareTrack = tp && trkSiHits>=m_MinNoSiHits && vxDoubleSi && isInVertex(*tp, *vx);
112 
113  //Debug messages
114  ATH_MSG_DEBUG("Vertex, SiSi, tracks with innermost pixel hits: "
115  << (vx != nullptr) << ", " << vxDoubleSi << ", " << nTrkVxWithInnermostHit);
116  ATH_MSG_DEBUG("Track, Si hits, pixel hits, has innermost pixel hit: "
117  << (tp != nullptr) << ", " << (int) trkSiHits << ", " << (int) trkPixelHits
118  << " , " << (int) trkHasInnermostHit);
119  ATH_MSG_DEBUG("Share track : " << shareTrack);
120 
121  //The Electron collection will NOT contain Photons
122  //The Photon collection will NOT contain Electrons
123 
124  //So for conversions vs electrons better to go to ambiguous
125  //except if we are sure.
126 
127  //Practically a photon here means definetely not Electron
128  //And vice-versa
129 
130  //Photon ==> Surely not electron
131  // - no track
132  // - or no track with the minimum requirent hits to be an electron
133  // - or Si+Si vertex and
134  // - No pixel
135  // - The electron track is part of the conversion
136  // In this case we do not want this to be in Electrons
137  if (!tp ||
138  trkSiHits<m_MinNoSiHits ||
139  (vxDoubleSi && !trkPixelHits && shareTrack)){
140  ATH_MSG_DEBUG("Returning Photon");
143  }
144 
145  // Ambigous due to E/P, Min Pt, pixel hits
146  // We are not sure it is a Photon, but is not good enough either to be surely
147  // an Electron
148  // - E/P >10 or track Pt < 2.0 GeV or no-pixel then Ambiguous
149  double track_ep = cluster_e * fabs(tp->qOverP());
150 
151  if(tp->pt()<m_minPtCut) {
152  ATH_MSG_DEBUG("Returning Ambiguous due min Pt");
155  }
156 
157  if( track_ep > m_maxEoverPCut) {
158  ATH_MSG_DEBUG("Returning Ambiguous due to E over P");
161  }
162 
163 
164  if(!trkPixelHits) {
165  ATH_MSG_DEBUG("Returning Ambiguous due to no pixels");
168  }
169 
170  // Electron ==> Surely not Photon
171  // - No vertex Matched (and trk has "innermost pixel hits" when
172  // m_noVertexNoInnermostAsAmb is true,
173  // othewise ambiguous)
174  // - Track with at least the minimum Si and Pixel hits (previous selection for
175  // photons/ambiguous)
176  // - And has E/P < 10 and Pt > 2.0 GeV (previous for ambiguous)
177  // - Or if a vertex exists and:
178  // * is not Si+Si
179  // * is Si+Si but only 1 trk has "innermost pixel hits"
180  // * is Si+Si and both tracks have "innermost pixel hits" but
181  // Rconv - RfirstHit > maxDeltaR_innermost
182  // In this case we do not want this to be in Photons
183 
184  if (!vx) {
185  if (trkHasInnermostHit || !m_noVertexNoInnermostAsAmb) {
186  ATH_MSG_DEBUG("Returning Electron");
189  } else {
190  // the true photons falling here are classified as unconverted photons
191  // but it may happen that they are late single-track conversions
192  // very few true electrons are falling here, since there is no innermost
193  // hits
194  ATH_MSG_DEBUG("Returning Ambiguous due to no conv vertex and track with "
195  "no innermost hits");
198  }
199  }
200 
201  // here we have a conv vertex
202  if (trkHasInnermostHit && (!vxDoubleSi || nTrkVxWithInnermostHit == 1 ||
203  !passDeltaR_innermost(*vx))) {
204  ATH_MSG_DEBUG("Returning Electron");
207  }
208 
209  // Ambiguous all else, these will go to both electrons and photons
210  // A matched Si+Si vertex (where either both or none of the tracks have
211  // "innermost pixel hits")
212  // and a track with "innermost pixel hits"
213  // A non Si+Si vertex matched and a track with no "innermost pixel hits"
214 
215  //If we have no double si
216  //or if the single track p matches the cluster E than the vertex p
217  //mark TrackEoverPBetterThanVertexEover.
218  //Otherwise maek as TrackEoverPBetterThanVertexEover
219  //as the double si vertex is a better match to the cluster E.
220  const double track_p = fabs(1.0/tp->qOverP());
221  const double vertex_p=xAOD::EgammaHelpers::momentumAtVertex(*vx).mag() ;
222  type = !vxDoubleSi || (fabs(track_p - cluster_e) < fabs(vertex_p- cluster_e))?
225  //end of types
226 
227  ATH_MSG_DEBUG("Returning Ambiguous");
229 }
230 
232  const xAOD::Vertex* vx,
233  const xAOD::TrackParticle* tp) const{
234 
236  return ambiguityResolve(cluster,
237  vx,
238  tp,
239  type);
240 
241 }
242 
243 
244 
250 
251  //Fwd and Topo seeded not handled
254  ATH_MSG_DEBUG("Author Fwd of Topo seeded. Do not do overlap or ambiguity");
255  return egamma.author();
256  }
257 
258  //No overlap found so either photon or electron
259  if (!egamma.ambiguousObject()){
261  ATH_MSG_DEBUG("No overlaping object found");
262  return egamma.author();
263  }
264 
265  // Overlap found. define the electron and the photon
266  const xAOD::Electron* electron = static_cast<const xAOD::Electron*>(
267  egamma.type() == xAOD::Type::Electron ? &egamma : egamma.ambiguousObject());
268  const xAOD::Photon* photon = static_cast<const xAOD::Photon*>(
269  egamma.type() == xAOD::Type::Photon ? &egamma : egamma.ambiguousObject());
270 
271  //Error if cannot define any of them
272  if (!electron || !photon){
273  ATH_MSG_WARNING("Could not cast to electron and/or photon");
274  return egamma.author();
275  }
276 
277  //pass the proper input to the ambiguity resolve method
279  unsigned int result = ambiguityResolve(electron->caloCluster(),
280  photon->vertex(),
281  electron->trackParticle(),
282  type);
283  ATH_MSG_DEBUG("Performed ambiguity resolution, resulting type is: "<< type);
284  return result;
285 }
286 
289  unsigned int author = ambiguityResolve(egamma);
290 
293  return true;
294  }
295 
297  return true;
298  }
299 
300  return (author == (egamma.type() == xAOD::Type::Electron ?
302 }
303 
309 {
310  uint8_t trkExpectHit(0);
311  uint8_t trkNhits(0);
312  CHECK_HITS( tp.summaryValue(trkNhits,xAOD::numberOfInnermostPixelLayerHits) );
313  if (trkNhits) {return true;}
314 
315  CHECK_HITS( tp.summaryValue(trkExpectHit,xAOD::expectInnermostPixelLayerHit) );
316  if (trkExpectHit) {return false;}
317 
319  if (trkNhits) {return true;}
320 
321  CHECK_HITS( tp.summaryValue(trkExpectHit,xAOD::expectNextToInnermostPixelLayerHit) );
322  if (trkExpectHit) {return false;}
323 
324  CHECK_HITS( tp.summaryValue(trkNhits,xAOD::numberOfPixelHits) );
325  return (trkNhits >= m_MinNoPixHits);
326 }
327 
331  size_t n = 0;
332  for (size_t i = 0; i < vx.nTrackParticles(); ++i){
333  const xAOD::TrackParticle *tp = vx.trackParticle(i);
334  if (!tp) {ATH_MSG_WARNING("Null pointer to track particle in vertex");}
335  else if (hasInnermostPixelHit(*tp)) {++n;}
336  }
337  return n;
338 }
339 
342  for (size_t i = 0; i < vx.nTrackParticles(); ++i){
343  const xAOD::TrackParticle *tp = vx.trackParticle(i);
344  if (!tp) {ATH_MSG_WARNING("Null pointer to track particle in vertex");}
345  if (tp == &trk) {return true;}
346  }
347  return false;
348 }
349 
352 {
353  static const SG::AuxElement::Accessor<float> minRfirstHitAcc("minRfirstHit");
354  if (not minRfirstHitAcc.isAvailable(vx)) {
355  ATH_MSG_WARNING("minRfirstHit not available");
356  return false;
357  }
358  return xAOD::EgammaHelpers::conversionRadius(&vx) - minRfirstHitAcc(vx) < m_maxDeltaR_innermost;
359 }
CHECK_HITS
#define CHECK_HITS(EXP)
Definition: EGammaAmbiguityTool.cxx:29
xAOD::Electron
Electron_v1 Electron
Definition of the current "egamma version".
Definition: Event/xAOD/xAODEgamma/xAODEgamma/Electron.h:17
get_generator_info.result
result
Definition: get_generator_info.py:21
xAOD::Vertex_v1::nTrackParticles
size_t nTrackParticles() const
Get the number of tracks associated with this vertex.
Definition: Vertex_v1.cxx:270
EGammaAmbiguityTool::m_maxDeltaR_innermost
float m_maxDeltaR_innermost
Maximum value for Rconv - RfirstHit for Si+Si conversions where both tracks have innermost hits.
Definition: EGammaAmbiguityTool.h:93
xAOD::uint8_t
uint8_t
Definition: Muon_v1.cxx:575
SG::Accessor
Helper class to provide type-safe access to aux data.
Definition: Control/AthContainers/AthContainers/Accessor.h:66
EGammaAmbiguityTool::m_MinNoSiHits
int m_MinNoSiHits
Minimum number of silicon hits to be an electron and not a photon.
Definition: EGammaAmbiguityTool.h:85
EGammaAmbiguityTool::ambiguityResolve
virtual unsigned int ambiguityResolve(const xAOD::CaloCluster *cluster, const xAOD::Vertex *vx, const xAOD::TrackParticle *tp, xAOD::AmbiguityTool::AmbiguityType &type) const override final
Return value: AuthorElectron, AuthorPhoton, AuthorAmbiguous, AuthorUnknown.
Definition: EGammaAmbiguityTool.cxx:75
EGammaAmbiguityTool::nTrkWithInnermostPixelHits
size_t nTrkWithInnermostPixelHits(const xAOD::Vertex &vx) const
Return the number of tracks with "innermost pixel hits" (see above) in the given vertex.
Definition: EGammaAmbiguityTool.cxx:330
xAODP4Helpers.h
AthCommonDataStore< AthCommonMsg< AlgTool > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T > &t)
Definition: AthCommonDataStore.h:145
xAOD::AmbiguityTool::unknown
@ unknown
Definition: IEGammaAmbiguityTool.h:42
asg
Definition: DataHandleTestTool.h:28
xAOD::CaloCluster_v1::SuperCluster
@ SuperCluster
Definition: CaloCluster_v1.h:107
ParticleTest.tp
tp
Definition: ParticleTest.py:25
EGammaAmbiguityTool.h
xAOD::numberOfPixelHits
@ numberOfPixelHits
these are the pixel hits, including the b-layer [unit8_t].
Definition: TrackingPrimitives.h:259
xAOD::expectInnermostPixelLayerHit
@ expectInnermostPixelLayerHit
Do we expect a 0th-layer barrel hit for this track?
Definition: TrackingPrimitives.h:236
xAOD::Egamma_v1
Definition: Egamma_v1.h:56
EGammaAmbiguityTool::accept
virtual bool accept(const xAOD::Egamma &egamma) const override final
Accept or reject egamma object based on ambiguity resolution (e.g.
Definition: EGammaAmbiguityTool.cxx:288
xAOD::EgammaParameters::ConversionType
ConversionType
Definition: EgammaEnums.h:268
xAOD::EgammaParameters::AuthorFwdElectron
const uint16_t AuthorFwdElectron
Electron reconstructed by the Forward cluster-based algorithm.
Definition: EgammaDefs.h:30
EGammaAmbiguityTool::hasInnermostPixelHit
bool hasInnermostPixelHit(const xAOD::TrackParticle &tp) const
Return true if track has innermost pixel hit or next-to-innermost in case innermost is not expected o...
Definition: EGammaAmbiguityTool.cxx:308
egamma
Definition: egamma.h:58
EgammaContainer.h
xAOD::CaloCluster_v1::clusterSize
ClusterSize clusterSize() const
Get cluster size.
Definition: CaloCluster_v1.cxx:364
Egamma.h
xAOD::CaloCluster_v1
Description of a calorimeter cluster.
Definition: CaloCluster_v1.h:59
EgammaxAODHelpers.h
xAOD::AmbiguityTool::electron
@ electron
Definition: IEGammaAmbiguityTool.h:34
xAOD::expectNextToInnermostPixelLayerHit
@ expectNextToInnermostPixelLayerHit
Do we expect a 1st-layer barrel hit for this track?
Definition: TrackingPrimitives.h:247
ElectronContainer.h
lumiFormat.i
int i
Definition: lumiFormat.py:92
CaloCluster.h
xAOD::EgammaParameters::AuthorCaloTopo35
const uint16_t AuthorCaloTopo35
Photon reconstructed by SW CaloTopo35 seeded clusters.
Definition: EgammaDefs.h:38
xAOD::EgammaParameters::AuthorAmbiguous
const uint16_t AuthorAmbiguous
Object Reconstructed by standard cluster-based algorithm.
Definition: EgammaDefs.h:32
beamspotman.n
n
Definition: beamspotman.py:731
Photon.h
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
xAOD::CaloCluster_v1::SW_35gam
@ SW_35gam
Definition: CaloCluster_v1.h:93
xAOD::AmbiguityTool::ambiguousVertexEoverPBetterThanTrackEoverP
@ ambiguousVertexEoverPBetterThanTrackEoverP
Definition: IEGammaAmbiguityTool.h:40
xAOD::EgammaHelpers::momentumAtVertex
Amg::Vector3D momentumAtVertex(const xAOD::Photon *, bool debug=false)
return the momentum at the vertex (which can be 0)
Definition: PhotonxAODHelpers.cxx:88
xAOD::EgammaParameters::doubleSi
@ doubleSi
two tracks, both with Si hits
Definition: EgammaEnums.h:279
xAOD::AmbiguityTool::ambiguousTrackEoverPBetterThanVertexEoverP
@ ambiguousTrackEoverPBetterThanVertexEoverP
Definition: IEGammaAmbiguityTool.h:35
EGammaAmbiguityTool::m_acceptAmbiguous
bool m_acceptAmbiguous
@When used as a selector reject/accpet ambiguous cases
Definition: EGammaAmbiguityTool.h:97
EGammaAmbiguityTool::initialize
virtual StatusCode initialize() override final
Gaudi Service Interface method implementations.
Definition: EGammaAmbiguityTool.cxx:68
EGammaAmbiguityTool::m_MinNoPixHits
int m_MinNoPixHits
Minimum number of pixel hits to be an electron and not a photon.
Definition: EGammaAmbiguityTool.h:87
xAOD::Vertex_v1::trackParticle
const TrackParticle * trackParticle(size_t i) const
Get the pointer to a given track that was used in vertex reco.
Definition: Vertex_v1.cxx:249
xAOD::AmbiguityTool::AmbiguityType
AmbiguityType
Definition: IEGammaAmbiguityTool.h:33
Vertex.h
egamma::author
unsigned int author() const
Reconstruction Author
Definition: egamma.h:244
xAOD::numberOfNextToInnermostPixelLayerHits
@ numberOfNextToInnermostPixelLayerHits
these are the hits in the 1st pixel barrel layer
Definition: TrackingPrimitives.h:248
xAOD::AmbiguityTool::photon
@ photon
Definition: IEGammaAmbiguityTool.h:41
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:192
xAOD::AmbiguityTool::ambiguousNoInnermost
@ ambiguousNoInnermost
Definition: IEGammaAmbiguityTool.h:39
xAOD::CaloCluster_v1::altE
flt_t altE() const
Get Energy in signal state ALTCALIBRATED.
xAOD::EgammaHelpers::conversionRadius
float conversionRadius(const xAOD::Vertex *vx)
return the conversion radius or 9999.
Definition: PhotonxAODHelpers.cxx:76
xAOD::Electron_v1
Definition: Electron_v1.h:34
xAOD::AmbiguityTool::ambiguousTrackHighEoverP
@ ambiguousTrackHighEoverP
Definition: IEGammaAmbiguityTool.h:37
xAOD::Photon
Photon_v1 Photon
Definition of the current "egamma version".
Definition: Event/xAOD/xAODEgamma/xAODEgamma/Photon.h:17
EGammaAmbiguityTool::passDeltaR_innermost
bool passDeltaR_innermost(const xAOD::Vertex &vx) const
Return true if the vertex passes the requirement on Rconv - RfirstHit.
Definition: EGammaAmbiguityTool.cxx:351
TrackParticle.h
xAOD::photon
@ photon
Definition: TrackingPrimitives.h:199
EGammaAmbiguityTool::isInVertex
bool isInVertex(const xAOD::TrackParticle &, const xAOD::Vertex &) const
Return true if the given TrackParticle is part of the vertex.
Definition: EGammaAmbiguityTool.cxx:341
EGammaAmbiguityTool::m_noVertexNoInnermostAsAmb
bool m_noVertexNoInnermostAsAmb
no vertex && no innermost hit -> amb.
Definition: EGammaAmbiguityTool.h:95
xAOD::AmbiguityTool::ambiguousTrackNoPixel
@ ambiguousTrackNoPixel
Definition: IEGammaAmbiguityTool.h:38
xAOD::Vertex_v1
Class describing a Vertex.
Definition: Vertex_v1.h:42
EGammaAmbiguityTool::EGammaAmbiguityTool
EGammaAmbiguityTool(const std::string &myname)
Standard constructor.
Definition: EGammaAmbiguityTool.cxx:38
xAOD::Photon_v1
Definition: Photon_v1.h:37
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
EGammaAmbiguityTool::m_minPtCut
float m_minPtCut
Minimum Pt, less that this is ambiguous.
Definition: EGammaAmbiguityTool.h:91
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
CaloCondBlobAlgs_fillNoiseFromASCII.author
string author
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:26
EgammaDefs.h
xAOD::EgammaParameters::electron
@ electron
Definition: EgammaEnums.h:18
xAOD::EgammaHelpers::conversionType
xAOD::EgammaParameters::ConversionType conversionType(const xAOD::Photon *ph)
return the photon conversion type (see EgammaEnums)
Definition: PhotonxAODHelpers.cxx:26
xAOD::EgammaParameters::AuthorPhoton
const uint16_t AuthorPhoton
Object Reconstructed by standard cluster-based algorithm.
Definition: EgammaDefs.h:28
xAOD::numberOfSCTHits
@ numberOfSCTHits
number of hits in SCT [unit8_t].
Definition: TrackingPrimitives.h:268
SG::ConstAccessor< T, AuxAllocator_t< T > >::isAvailable
bool isAvailable(const ELT &e) const
Test to see if this variable exists in the store.
Electron.h
xAOD::TrackParticle_v1
Class describing a TrackParticle.
Definition: TrackParticle_v1.h:43
xAOD::AmbiguityTool::ambiguousTrackLowPt
@ ambiguousTrackLowPt
Definition: IEGammaAmbiguityTool.h:36
xAOD::CaloCluster_v1::SW_35ele
@ SW_35ele
Definition: CaloCluster_v1.h:89
PhotonContainer.h
xAOD::CaloCluster_v1::e
virtual double e() const
The total energy of the particle.
Definition: CaloCluster_v1.cxx:265
xAOD::numberOfInnermostPixelLayerHits
@ numberOfInnermostPixelLayerHits
these are the hits in the 0th pixel barrel layer
Definition: TrackingPrimitives.h:237
EGammaAmbiguityTool::m_maxEoverPCut
float m_maxEoverPCut
Maximum EoverP, more that this is ambiguous.
Definition: EGammaAmbiguityTool.h:89
xAOD::EgammaParameters::AuthorElectron
const uint16_t AuthorElectron
Object Reconstructed by standard cluster-based algorithm.
Definition: EgammaDefs.h:24