ATLAS Offline Software
Loading...
Searching...
No Matches
egammaSelectedTrackCopy.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/*
6NAME: egammaSelectedTrackCopy
7PACKAGE: offline/Reconstruction/egamma/egammaAlgs/egammaSelectedTrackCopy
8AUTHORS: Anastopoulos
9CREATED: 25/06/2018
10
11PURPOSE: Select track to be refitted later on with GSF
12UPDATE : 25/06/2018
13*/
14
16//
20#include "GaudiKernel/EventContext.h"
29// std includes
30#include <algorithm>
31#include <cmath>
32#include <memory>
33#include <vector>
34
36
37namespace {
38 // Wrap a check to see if a track is valid for reffiting.
39 bool checkIfValidForRefit(const xAOD::TrackParticle *track) {
40 int nhits = summaryValueInt(*track, xAOD::numberOfPixelHits, 0);
41 nhits += summaryValueInt(*track, xAOD::numberOfSCTHits, 0);
42 return nhits >= 4;
43 }
44}
45
47 ISvcLocator* pSvcLocator)
48 : AthReentrantAlgorithm(name, pSvcLocator)
49{}
50
51StatusCode
53{
54 ATH_CHECK(m_clusterContainerKey.initialize());
57 // Needed to declare proper input dependency with scheduler
60
64 ATH_CHECK(m_caloDetDescrMgrKey.initialize());
65
66 return StatusCode::SUCCESS;
67}
68
69StatusCode
70egammaSelectedTrackCopy::egammaSelectedTrackCopy::finalize()
71{
72 ATH_MSG_INFO("===> egamma Selected Tracks Statistics ===========");
73 ATH_MSG_INFO("--- All Central Clusters: " << m_AllClusters);
74 ATH_MSG_INFO("--- Selected Central Clusters: " << m_SelectedClusters);
75 ATH_MSG_INFO("--- All Tracks: " << m_AllTracks);
76 ATH_MSG_INFO("--- Selected Central Tracks: " << m_SelectedTracks);
77 ATH_MSG_INFO("--- All Si Tracks: " << m_AllSiTracks);
78 ATH_MSG_INFO("--- Selected Central Si Tracks: " << m_SelectedSiTracks);
79 ATH_MSG_INFO("--- All TRT Tracks: " << m_AllTRTTracks);
80 ATH_MSG_INFO("--- Selected TRT Tracks: " << m_SelectedTRTTracks);
81 if (m_doForwardTracks) {
82 ATH_MSG_INFO("--- All Forward Clusters: " << m_AllFwdClusters);
83 ATH_MSG_INFO("--- Selected Forward Tracks: " << m_SelectedFwdTracks);
84 }
85 ATH_MSG_INFO("<=================================================");
86
87 return StatusCode::SUCCESS;
88}
89
90StatusCode
91egammaSelectedTrackCopy::execute(const EventContext& ctx) const
92{
94 ATH_CHECK(clusterTES.isValid());
95
97 ATH_CHECK(trackTES.isValid());
98
101 ctx
102 );
103
106 if (m_doForwardTracks) {
109 ctx
110 );
111
112 ATH_CHECK(fwdClusterTES.isValid());
113 m_AllFwdClusters += fwdClusterTES->size();
114 }
115
116 // Here it just needs to be a view copy , i.e the collection of selected
117 // trackParticles we create does not really own its elements.
118 auto viewCopy = std::make_unique<ConstDataVector<xAOD::TrackParticleContainer>>(SG::VIEW_ELEMENTS);
119 // Local counters.
120 auto selectedTracks = m_SelectedTracks.buffer();
121 auto selectedFwdTracks = m_SelectedFwdTracks.buffer();
122 auto allSiTracks = m_AllSiTracks.buffer();
123 auto selectedSiTracks = m_SelectedSiTracks.buffer();
124 auto allTRTTracks = m_AllTRTTracks.buffer();
125 auto selectedTRTTracks = m_SelectedTRTTracks.buffer();
126
128 ATH_CHECK(caloDetDescrMgrHandle.isValid());
129
130 const CaloDetDescrManager* calodetdescrmgr = *caloDetDescrMgrHandle;
131
132 // Check which clusters to seed on.
133 std::vector<const xAOD::CaloCluster*> passingClusters;
134 for (const xAOD::CaloCluster* cluster : *clusterTES) {
135 if (m_egammaCaloClusterSelector->passSelection(cluster, *calodetdescrmgr)) {
136 passingClusters.push_back(cluster);
137 }
138 }
139
140 m_AllTracks += trackTES->size();
141 m_AllClusters += clusterTES->size();
142 m_SelectedClusters += passingClusters.size();
143
144 // Extrapolation cache.
145 for (const xAOD::TrackParticle* track : *trackTES) {
146 bool isNotValidForRefit = !checkIfValidForRefit(track);
147 if (isNotValidForRefit) {
148 ++allTRTTracks;
149 } else {
150 ++allSiTracks;
151 }
152
153 // Check if the track is selected for a central electron
154 // due to a central cluster
155 for (const xAOD::CaloCluster* cluster : passingClusters) {
156 if (selectTrack(ctx, cluster, track, isNotValidForRefit, *calodetdescrmgr)) {
157 viewCopy->push_back(track);
158 ++selectedTracks;
159 if (isNotValidForRefit) {
160 ++selectedTRTTracks;
161 } else {
162 ++selectedSiTracks;
163 }
164 break;
165 }
166 } // Loop on clusters.
167
168 // Check if the track is selected for a forwand electron
169 // due to a forwand cluster
170 if (m_doForwardTracks) {
171 for (const xAOD::CaloCluster* cluster : *fwdClusterTES) {
172 if (selectTrack(ctx, cluster, track, isNotValidForRefit, *calodetdescrmgr)) {
173 viewCopy->push_back(track);
174 ++selectedFwdTracks;
175 break;
176 }
177 } // Loop on fwd cluster
178 }
179 }// Loop on tracks.
180
181 ATH_CHECK(outputTrkPartContainer.record(std::move(viewCopy)));
182
183 return StatusCode::SUCCESS;
184}
185
186bool
188 const xAOD::CaloCluster* cluster,
189 const xAOD::TrackParticle* track,
190 bool trkTRT,
191 const CaloDetDescrManager& caloDD) const
192{
193
194 if (cluster == nullptr || track == nullptr) {
195 return false;
196 }
197
198 const Trk::Perigee& candidatePerigee = track->perigeeParameters();
199
200 // Get Perigee Parameters.
201 const double trkPhi = candidatePerigee.parameters()[Trk::phi];
202 const double trkEta = candidatePerigee.eta();
203 const double z_perigee = candidatePerigee.position().z();
204 const double r_perigee = candidatePerigee.position().perp();
205 const Amg::Vector3D PerigeeXYZPosition(candidatePerigee.position().x(),
206 candidatePerigee.position().y(),
207 z_perigee);
208
209 // Get Cluster parameters.
210 const double clusterEta = xAOD::EgammaHelpers::isFCAL(cluster) ? cluster->eta() : cluster->etaBE(2);
211 const bool isEndCap = !xAOD::EgammaHelpers::isBarrel(cluster);
212
213 // Use trkEta only if sufficient hits in the Si.
214 const double Et = trkTRT ? cluster->et() : cluster->e() / cosh(trkEta);
215
216 // A few sanity checks.
217 if (std::abs(clusterEta) > 10.0 || std::abs(trkEta) > 10.0 || Et < 10.0) {
219 "FAILS sanity checks : Track Eta : " << trkEta <<
220 ", Cluster Eta " << clusterEta
221 );
222
223 return false;
224 }
225
226 // Calculate the eta/phi of the cluster as would be seen from the perigee
227 // position of the Track.
228 const Amg::Vector3D XYZClusterWrtTrackPerigee = CandidateMatchHelpers::approxXYZwrtPoint(
229 *cluster,
230 PerigeeXYZPosition,
231 isEndCap
232 );
233
234 // Calculate the possible rotation of the track.
235 // Once assuming the cluster Et being the better estimate (e.g big brem).
236 const double phiRotRescaled = CandidateMatchHelpers::PhiROT(
237 Et,
238 trkEta,
239 track->charge(),
240 r_perigee,
241 isEndCap
242 );
243
244 // And also assuming the track Pt being correct.
245 const double phiRotTrack = CandidateMatchHelpers::PhiROT(
246 track->pt(),
247 trkEta,
248 track->charge(),
249 r_perigee,
250 isEndCap
251 );
252
253 const double clusterPhiCorrected = XYZClusterWrtTrackPerigee.phi();
254
255 // DeltaPhi between the track and the cluster.
256 const double deltaPhiStd = P4Helpers::deltaPhi(clusterPhiCorrected, trkPhi);
257
258 // DeltaPhi between the track and the cluster accounting for rotation assuming
259 // cluster Et is a better estimator.
260 const double trkPhiRescaled = P4Helpers::deltaPhi(trkPhi, phiRotRescaled);
261 const double deltaPhiRescaled = P4Helpers::deltaPhi(clusterPhiCorrected, trkPhiRescaled);
262
263 // DeltaPhi between the track and the cluster accounting for rotation.
264 const double trkPhiCorrTrack = P4Helpers::deltaPhi(trkPhi, phiRotTrack);
265 const double deltaPhiTrack = P4Helpers::deltaPhi(clusterPhiCorrected, trkPhiCorrTrack);
266
267 // First we will see if it fails the quick match.
268 // Then if it passed it will get 2 chances to be selected.
269 // One if it matches from last measurement.
270 // The second if it matched from Perigee rescales.
271 // Broad phi check.
272 if (
273 (std::abs(deltaPhiRescaled) > m_broadDeltaPhi) &&
274 (std::abs(deltaPhiTrack) > m_broadDeltaPhi) &&
275 (std::abs(deltaPhiStd) > m_broadDeltaPhi)
276 ) {
278 "FAILS broad window phi match (track phi, phirotCluster , phiRotTrack , " <<
279 "cluster phi corrected, cluster phi): ( " <<
280 trkPhi << ", " <<
281 phiRotRescaled << ", " <<
282 phiRotTrack << ", " <<
283 clusterPhiCorrected << ", " <<
284 cluster->phi() << ")"
285 );
286
287 return false;
288 }
289
290 // if TRT we can stop here , we can not check much in eta really.
291 if (trkTRT) { return true; }
292
293 const double clusterEtaCorrected = XYZClusterWrtTrackPerigee.eta();
294
295 // Broad eta check.
296 if (
297 std::abs(cluster->eta() - trkEta) > m_broadDeltaEta &&
298 std::abs(clusterEtaCorrected - trkEta) > m_broadDeltaEta
299 ) {
301 "FAILS broad window eta match (track eta, cluster eta, cluster eta corrected): ( " <<
302 trkEta << ", " <<
303 cluster->etaBE(2) << ", " <<
304 clusterEtaCorrected << " )"
305 );
306
307 return false;
308 }
309
310 std::pair<
311 std::vector<CaloSampling::CaloSample>,
312 std::vector<std::unique_ptr<Trk::Surface>>
313 > layersAndSurfaces = m_extrapolationTool->getClusterLayerSurfaces(*cluster, caloDD);
314
315 // Extrapolate from last measurement to the four EM layers.
316 // Since this is before brem fit last measurement is OK.
317 std::array<double, 4> eta = { -999.0, -999.0, -999.0, -999.0 };
318 std::array<double, 4> phi = { -999.0, -999.0, -999.0, -999.0 };
319 std::array<double, 4> deltaEta = { -999.0, -999.0, -999.0, -999.0 };
320 std::array<double, 4> deltaPhi = { -999.0, -999.0, -999.0, -999.0 };
321 if (m_extrapolationTool ->getMatchAtCalo(
322 ctx,
323 *cluster,
324 *track,
325 layersAndSurfaces.first,
326 layersAndSurfaces.second,
327 eta,
328 phi,
329 deltaEta,
330 deltaPhi,
332 ).isFailure()) {
333 return false;
334 }
335
336 // Selection in narrow eta/phi window from last measurement.
337 if (
338 std::abs(deltaEta[2]) < m_narrowDeltaEta &&
341 ) {
342 ATH_MSG_DEBUG("Match from Last measurement is successful : " << deltaPhi[2]);
343 return true;
344 }
345
346 // Cases where:
347 // - It passes deltaEta[2] from last measurement (rescaling should not affect the eta side).
348 // - and we have a cluster with higher Et.
349 // Rescale up the track to account for radiative loses and retry.
350 if (
351 std::abs(deltaEta[2]) < m_narrowDeltaEta &&
352 cluster->et() > track->pt()
353 ) {
354 // Extrapolate from Perigee Rescaled.
355 std::array<double, 4> etaRes = { -999.0, -999.0, -999.0, -999.0 };
356 std::array<double, 4> phiRes = { -999.0, -999.0, -999.0, -999.0 };
357 std::array<double, 4> deltaEtaRes = { -999.0, -999.0, -999.0, -999.0 };
358 std::array<double, 4> deltaPhiRes = { -999.0, -999.0, -999.0, -999.0 };
359
360 if (m_extrapolationTool->getMatchAtCalo(
361 ctx,
362 *cluster,
363 *track,
364 layersAndSurfaces.first,
365 layersAndSurfaces.second,
366 etaRes,
367 phiRes,
368 deltaEtaRes,
369 deltaPhiRes,
371 ).isFailure()) {
372 return false;
373 }
374
375 // Redo the check with rescale.
376 if (
377 std::abs(deltaEtaRes[2]) < m_narrowDeltaEta &&
378 deltaPhiRes[2] < m_narrowRescale &&
379 deltaPhiRes[2] > -m_narrowRescaleBrem
380 ) {
381 ATH_MSG_DEBUG("Rescale Match success " << deltaPhiRes[2]);
382 return true;
383 }
384 }
385
386 // Default is fail.
387 return false;
388}
389
Scalar eta() const
pseudorapidity method
Scalar deltaPhi(const MatrixBase< Derived > &vec) const
Scalar phi() const
phi method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_INFO(x)
#define ATH_MSG_DEBUG(x)
Definition of CaloDetDescrManager.
Helpers for checking error return status codes and reporting errors.
Handle class for reading from StoreGate.
Handle class for recording to StoreGate.
An algorithm that can be simultaneously executed in multiple threads.
This class provides the client interface for accessing the detector description information common to...
@ fromLastMeasurement
from the last measurement of TrackParticle
@ fromPerigeeRescaled
from the perigee of TrackParticle recaled by Ecluster
virtual bool isValid() override final
Can the handle be successfully dereferenced?
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
double eta() const
Access method for pseudorapidity - from momentum.
const Amg::Vector3D & position() const
Access method for the position.
Gaudi::Accumulators::Counter m_SelectedSiTracks
SG::ReadCondHandleKey< CaloDetDescrManager > m_caloDetDescrMgrKey
Gaudi::Accumulators::Counter m_SelectedClusters
ToolHandle< IegammaCaloClusterSelector > m_egammaCaloClusterSelector
Tool to filter the calo clusters.
Gaudi::Accumulators::Counter m_AllFwdClusters
Gaudi::Property< double > m_narrowDeltaPhiBrem
Gaudi::Property< double > m_narrowDeltaPhi
virtual StatusCode initialize() override final
Gaudi::Accumulators::Counter m_SelectedFwdTracks
Gaudi::Accumulators::Counter m_AllSiTracks
Gaudi::Accumulators::Counter m_AllTracks
Gaudi::Accumulators::Counter m_AllClusters
Gaudi::Property< double > m_broadDeltaEta
Broad windows.
Gaudi::Property< double > m_narrowRescale
SG::ReadDecorHandleKey< xAOD::TrackParticleContainer > m_trackParticleTimeDecorKey
SG::ReadHandleKey< xAOD::TrackParticleContainer > m_trackParticleContainerKey
Gaudi::Accumulators::Counter m_SelectedTRTTracks
Gaudi::Property< double > m_broadDeltaPhi
virtual StatusCode execute(const EventContext &ctx) const override final
Gaudi::Property< bool > m_doForwardTracks
Private member flag to select forward tracks.
Gaudi::Accumulators::Counter m_SelectedTracks
ToolHandle< IEMExtrapolationTools > m_extrapolationTool
Tool for extrapolation.
SG::WriteHandleKey< ConstDataVector< xAOD::TrackParticleContainer > > m_OutputTrkPartContainerKey
Gaudi::Property< double > m_narrowRescaleBrem
bool selectTrack(const EventContext &ctx, const xAOD::CaloCluster *cluster, const xAOD::TrackParticle *track, bool trkTRT, const CaloDetDescrManager &caloDD) const
Broad track selection.
SG::ReadHandleKey< xAOD::CaloClusterContainer > m_fwdClusterContainerKey
Names of forward input output collections.
Gaudi::Property< double > m_narrowDeltaEta
Narrow windows.
Gaudi::Accumulators::Counter m_AllTRTTracks
egammaSelectedTrackCopy(const std::string &name, ISvcLocator *pSvcLocator)
Default constructor.
SG::ReadHandleKey< xAOD::CaloClusterContainer > m_clusterContainerKey
Names of input output collections.
virtual double eta() const
The pseudorapidity ( ) of the particle.
virtual double e() const
The total energy of the particle.
virtual double phi() const
The azimuthal angle ( ) of the particle.
float etaBE(const unsigned layer) const
Get the eta in one layer of the EM Calo.
int summaryValueInt(const xAOD::TrackParticle &tp, const xAOD::SummaryType &info, int deflt=-999)
return the summary value for a TrackParticle or default value (-999) (to be used mostly in python whe...
Eigen::Matrix< double, 3, 1 > Vector3D
double PhiROT(const double pt, const double eta, const int charge, const double r_start, const bool isEndCap)
Function to calculate the approximate rotation in phi/bending of a track until it reaches the calo.
Amg::Vector3D approxXYZwrtPoint(const xAOD::CaloCluster &cluster, const Amg::Vector3D &point, const bool isEndCap)
Function to get the (x,y,z) of the cluster wrt to a point (x0,y0,z0)
double deltaPhi(double phiA, double phiB)
delta Phi in range [-pi,pi[
Definition P4Helpers.h:34
@ VIEW_ELEMENTS
this data object is a view, it does not own its elmts
ParametersT< TrackParametersDim, Charged, PerigeeSurface > Perigee
@ phi
Definition ParamDefs.h:75
bool isBarrel(const xAOD::Egamma *eg)
return true if the cluster is in the barrel
bool isFCAL(const xAOD::CaloCluster *cluster)
return true if the cluster (or the majority of its energy) is in the FCAL0
int summaryValueInt(const xAOD::TrackParticle &tp, const xAOD::SummaryType &info, int deflt=-999)
return the summary value for a TrackParticle or default value (-999) (to be used mostly in python whe...
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
TrackParticle_v1 TrackParticle
Reference the current persistent version:
@ numberOfSCTHits
number of hits in SCT [unit8_t].
@ numberOfPixelHits
these are the pixel hits, including the b-layer [unit8_t].