ATLAS Offline Software
Loading...
Searching...
No Matches
TauElectronVetoVariables.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#ifndef XAOD_ANALYSIS
6
8
12#include "GaudiKernel/SystemOfUnits.h"
13
14#include "Acts/Geometry/TrackingGeometry.hpp"
15#include "Acts/Material/MaterialInteraction.hpp"
16#include "Acts/Propagator/detail/SteppingLogger.hpp"
17#include "Acts/Surfaces/CurvilinearSurface.hpp"
18#include "Acts/Surfaces/PlaneSurface.hpp"
19
22
23#include <algorithm>
24#include <cmath>
25#include <unordered_map>
26#include <array>
27
28#include "TVector2.h"
29
30using Gaudi::Units::GeV;
31
34
36
38 ATH_CHECK( m_caloExtensionTool.retrieve() );
39 if (!m_ParticleCacheKey.key().empty()) {
40 ATH_CHECK(m_ParticleCacheKey.initialize());
41 } else {
42 m_useOldCalo = true;
43 }
44 } else {
45
48
49 std::array<std::string,11> caloNames = { "PreSamplerENegZ_Layer", "PreSamplerEPosZ_Layer",
50 "EME1NegZ_Layer", "EME1PosZ_Layer", "EMB1_Layer",
51 "EME2NegZ_Layer", "EME2PosZ_Layer", "EMB2_Layer",
52 "EME3NegZ_Layer", "EME3PosZ_Layer", "EMB3_Layer",
53 };
54
55 m_trackingGeometrySvc->trackingGeometry()->visitVolumes([&](const Acts::TrackingVolume *vol) {
56 const auto & name = vol->volumeName();
57 ATH_MSG_DEBUG(name << " - " << vol->geometryId() << " - surfaces: " << vol->surfaces().size());
58 if (std::ranges::contains(caloNames, name)){
59 ATH_MSG_DEBUG("About to insert caloName " << name << " into map");
60 m_caloNameGeoIDMap[vol->geometryId().volume()] = name;
61 }
62 });
63 }
64 return StatusCode::SUCCESS;
65}
66
67
69 const EventContext& ctx) const {
70 if (pTau.nTracks() < 1) {
71 return StatusCode::SUCCESS;
72 }
73 ATH_MSG_DEBUG("in execute()");
74 float detPhiTrk = 0.;
75 float detEtaTrk = 0.;
76 float sumETCellsLAr = 0.;
77 float eta0cut = 0.075;
78 float eta1cut = 0.0475;
79 float eta2cut = 0.075;
80 float eta3cut = 1.5;
81 float phi0cut = 0.3;
82 float phi1cut = 0.3;
83 float phi2cut = 0.075;
84 float phi3cut = 0.075;
85 const CaloCell *pCell;
86 int trackIndex = -1;
87
88 //---------------------------------------------------------------------
89 // Calculate eta, phi impact point of leading track at calorimeter layers EM 0,1,2,3
90 //---------------------------------------------------------------------
92 constexpr size_t numberOfEM_Layers{4};
93 constexpr double invalidCoordinate{-11111.};
94 constexpr double invalidCoordinateThreshold{-11110.};
95 std::array<double, numberOfEM_Layers> extrapolatedEta{};
96 std::array<double, numberOfEM_Layers> extrapolatedPhi{};
97 extrapolatedEta.fill(invalidCoordinate);
98 extrapolatedPhi.fill(invalidCoordinate);
99
100 const xAOD::TrackParticle *orgTrack = pTau.track(0)->track();
101 trackIndex = orgTrack->index();
102
103 /*get the CaloExtension object*/
105 const Trk::CaloExtension * caloExtension = nullptr;
106 std::unique_ptr<Trk::CaloExtension> uniqueExtension ;
107 if (m_useOldCalo) {
108 /* If CaloExtensionBuilder is unavailable, use the calo extension tool */
109 ATH_MSG_VERBOSE("Using the CaloExtensionTool");
110 uniqueExtension = m_caloExtensionTool->caloExtension(ctx, *orgTrack);
111 caloExtension = uniqueExtension.get();
112 } else {
113 /*get the CaloExtension object*/
114 ATH_MSG_VERBOSE("Using the CaloExtensionBuilder Cache");
116 caloExtension = (*particleCache)[trackIndex];
117 ATH_MSG_VERBOSE("Getting element " << trackIndex << " from the particleCache");
118 if( not caloExtension ){
119 ATH_MSG_VERBOSE("Cache does not contain a calo extension -> Calculating with the a CaloExtensionTool" );
120 uniqueExtension = m_caloExtensionTool->caloExtension(ctx, *orgTrack);
121 caloExtension = uniqueExtension.get();
122 }
123 }
124 if( not caloExtension){
125 ATH_MSG_DEBUG("extrapolation of leading track to calo surfaces failed : caloExtension is nullptr" );
126 return StatusCode::RECOVERABLE;
127 }
128 const std::vector<Trk::CurvilinearParameters>& clParametersVector = caloExtension->caloLayerIntersections();
129 if(clParametersVector.empty() ){
130 ATH_MSG_DEBUG("extrapolation of leading track to calo surfaces failed : caloLayerIntersection is empty" );
131 return StatusCode::RECOVERABLE;
132 }
133 // loop over calo layers
134 for( const Trk::CurvilinearParameters& cur : clParametersVector ){
135 // only use entry layer
136 if( !parsIdHelper.isEntryToVolume(cur.cIdentifier()) ) continue;
137 CaloSampling::CaloSample sample = parsIdHelper.caloSample(cur.cIdentifier());
138 int index = -1;
139 if( sample == CaloSampling::PreSamplerE || sample == CaloSampling::PreSamplerB ) index = 0;
140 else if( sample == CaloSampling::EME1 || sample == CaloSampling::EMB1 ) index = 1;
141 else if( sample == CaloSampling::EME2 || sample == CaloSampling::EMB2 ) index = 2;
142 else if( sample == CaloSampling::EME3 || sample == CaloSampling::EMB3 ) index = 3;
143 if( index < 0 ) continue;
144 extrapolatedEta[index] = cur.position().eta();
145 extrapolatedPhi[index] = cur.position().phi();
146 }
147 }
148 else
149 { // use ACTS Based extrapolation
150 unsigned int lastMeasIdx = 0;
151 if (!orgTrack->indexOfParameterAtPosition(lastMeasIdx, xAOD::LastMeasurement)) {
152 ATH_MSG_ERROR("TrackParticle has no last measurement parameters");
153 return StatusCode::FAILURE;
154 }
155
156 Acts::Vector3 lastPos{orgTrack->parameterX(lastMeasIdx),
157 orgTrack->parameterY(lastMeasIdx),
158 orgTrack->parameterZ(lastMeasIdx)};
159 Acts::Vector3 lastMom{ActsTrk::energyToActs(orgTrack->parameterPX(lastMeasIdx)),
160 ActsTrk::energyToActs(orgTrack->parameterPY(lastMeasIdx)),
161 ActsTrk::energyToActs(orgTrack->parameterPZ(lastMeasIdx))};
162
163 Acts::BoundVector lastBoundParams = Acts::BoundVector::Zero();
164 lastBoundParams[Acts::eBoundPhi] = lastMom.phi();
165 lastBoundParams[Acts::eBoundTheta] = lastMom.theta();
166 lastBoundParams[Acts::eBoundQOverP] = orgTrack->charge() / lastMom.norm();
167
168 std::shared_ptr<const Acts::Surface> lastSurface = Acts::CurvilinearSurface(lastPos, lastMom.normalized()).planeSurface()->getSharedPtr();
169
170 Acts::BoundTrackParameters boundPars{
171 std::move(lastSurface),
172 lastBoundParams,
173 std::nullopt,
174 Acts::ParticleHypothesis::pion()
175 };
176
177 Acts::Result<std::pair<std::vector<Acts::detail::Step>, Acts::RecordedMaterial>> result = m_extrapolationTool.get()->propagationSteps(ctx, boundPars);
178
179 if( !result.ok() ) {
180 ATH_MSG_WARNING("Error during extrapolation: " << result.error().message());
181 return StatusCode::RECOVERABLE;
182 }
183
184 const auto &[steps, _] = result.value();
185
186 for(const auto &step : steps) {
187
188 if( step.surface == nullptr || step.surface->geometryId().sensitive() == 0 ) {
189 continue;
190 }
191
192 Acts::GeometryIdentifier thisGeoID = step.geoID;
193 ATH_MSG_DEBUG("Got step with geoID " << thisGeoID);
194
195 if (m_caloNameGeoIDMap.contains(thisGeoID.volume())){
196 ATH_MSG_DEBUG("This step is in the calorimeter");
197 const auto &p = step.position;
198
199 // match to EM or Had calorimeter
200 std::string layer = m_caloNameGeoIDMap.at(thisGeoID.volume());
201
202 int index = -1;
203 if( layer.find("PreSampler") != std::string::npos) index = 0;
204 else if( (layer.find("EME1") != std::string::npos) || (layer.find("EMB1") != std::string::npos) ) index = 1;
205 else if( (layer.find("EME2") != std::string::npos) || (layer.find("EMB2") != std::string::npos) ) index = 2;
206 else if( (layer.find("EME3") != std::string::npos) || (layer.find("EMB3") != std::string::npos) ) index = 3;
207
208 if( index < 0 ) continue;
209
210 extrapolatedEta[index] = Acts::VectorHelpers::eta(p);
211 extrapolatedPhi[index] = Acts::VectorHelpers::phi(p);
212 }
213 }
214 }
215
216
217
218 for (size_t i = 0; i < numberOfEM_Layers; ++i) {
219 if ( extrapolatedEta[i] < invalidCoordinateThreshold || extrapolatedPhi[i] < invalidCoordinateThreshold ){
220 ATH_MSG_DEBUG("extrapolation of leading track to calo surfaces failed for sampling : " << i );
221 return StatusCode::SUCCESS;
222 }
223 }
224
225 // Loop through jets, get links to clusters
226 //Local variable cellSeen uses 25000 bytes of stack space
227 //coverity[STACK_USE]
228 std::bitset<200000> cellSeen{};
229 const std::unordered_map<int, int> samplingLookup{
230 {4,0}, {5,1}, {6,2}, {7,3}, {8,12},
231 {15, 12}, {16,13}, {17,14}, {18,12}, {19, 13}, {20,14}
232 };
233 const auto notFound{samplingLookup.end()};
234
235 std::vector<xAOD::CaloVertexedTopoCluster> vertexedClusterList = pTau.vertexedClusters();
236 for (const xAOD::CaloVertexedTopoCluster& vertexedCluster : vertexedClusterList){
237
238 const xAOD::CaloCluster& cluster = vertexedCluster.clust();
239 auto cell_links = cluster.getCellLinks();
240 if (cell_links == nullptr) {
241 ATH_MSG_DEBUG("NO Cell links found for cluster with pT " << cluster.pt());
242 continue;
243 }
245 CaloClusterCellLink::const_iterator pCellIterE = cluster.getCellLinks()->end();
246 for (; pCellIter != pCellIterE; ++pCellIter) {
247 double cellEta{}, cellPhi{}, cellET{};
248 pCell = *pCellIter;
249 if (cellSeen.test(pCell->caloDDE()->calo_hash())) continue;
250 else cellSeen.set(pCell->caloDDE()->calo_hash());
251 if (m_doVertexCorrection && pTau.vertex()!=nullptr) {
252 CaloVertexedCell vxCell (*pCell, pTau.vertex()->position());
253 cellPhi = vxCell.phi();
254 cellEta = vxCell.eta();
255 cellET = vxCell.et();
256 } else {
257 cellPhi = pCell->phi();
258 cellEta = pCell->eta();
259 cellET = pCell->et();
260 }
261 int sampling = pCell->caloDDE()->getSampling();
262 if (const auto & pElement {samplingLookup.find(sampling)};pElement != notFound){
263 sampling = pElement->second;
264 }
265 int i = 2;
266 if (sampling < 4) i = sampling;
267 if (sampling == 12 || sampling == 13 || sampling == 14) i = 3;
268 detPhiTrk = TVector2::Phi_mpi_pi(cellPhi-extrapolatedPhi[i]);
269 detEtaTrk = std::abs( cellEta - extrapolatedEta[i] );
270 if ((sampling == 0 && detEtaTrk < eta0cut && detPhiTrk < phi0cut) ||
271 (sampling == 1 && detEtaTrk < eta1cut && detPhiTrk < phi1cut) ||
272 (sampling == 2 && detEtaTrk < eta2cut && detPhiTrk < phi2cut) ||
273 (sampling == 3 && detEtaTrk < eta3cut && detPhiTrk < phi3cut)) {
274 sumETCellsLAr += cellET;
275 }
276 } //end cell loop
277 }// end jet constituent loop
278
279 pTau.setDetail(xAOD::TauJetParameters::sumEMCellEtOverLeadTrkPt , static_cast<float>( ( sumETCellsLAr / ( pTau.track(0)->pt() ) ) ) );
280 return StatusCode::SUCCESS;
281}
282
283#endif
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_VERBOSE(x,...)
Evaluate cell kinematics with a different vertex.
Data object for each calorimeter readout cell.
Definition CaloCell.h:57
virtual double phi() const override final
get phi (through CaloDetDescrElement)
Definition CaloCell.h:375
const CaloDetDescrElement * caloDDE() const
get pointer to CaloDetDescrElement (data member)
Definition CaloCell.h:321
virtual double eta() const override final
get eta (through CaloDetDescrElement)
Definition CaloCell.h:382
virtual double et() const override final
get et
Definition CaloCell.h:423
CaloCell_ID::CaloSample getSampling() const
cell sampling
Evaluate cell kinematics with a different vertex.
virtual double eta() const final
The pseudorapidity of the particle.
virtual double phi() const final
The aximuthal angle of the particle.
virtual double et() const
transverse energy defined to be e*sin(theta)
SG::ReadHandleKey< CaloExtensionCollection > m_ParticleCacheKey
std::map< unsigned int, std::string > m_caloNameGeoIDMap
Gaudi::Property< bool > m_useOldCalo
Gaudi::Property< bool > m_useACTSExtrapolator
ToolHandle< Trk::IParticleCaloExtensionTool > m_caloExtensionTool
ToolHandle< ActsTrk::IExtrapolationTool > m_extrapolationTool
ServiceHandle< ActsTrk::ITrackingGeometrySvc > m_trackingGeometrySvc
TauElectronVetoVariables(const std::string &name)
virtual StatusCode initialize() override
Tool initializer.
virtual StatusCode executeTool(xAOD::TauJet &pTau, const EventContext &ctx) const override
Execute - called for each tau candidate.
Gaudi::Property< bool > m_doVertexCorrection
TauRecToolBase(const std::string &name)
Tracking class to hold the extrapolation through calorimeter Layers Both the caloEntryLayerIntersecti...
const std::vector< CurvilinearParameters > & caloLayerIntersections() const
access to the intersections with the calorimeter layers.
helper class to encode and decode a TrackParametersIdentifier
bool isEntryToVolume(TrackParametersIdentifier id) const
returns true if the id belongs to the volume entrance
CaloSampling::CaloSample caloSample(TrackParametersIdentifier id) const
CaloSample encoded in id, returns CaloSampling::Unknown if id is not valid.
const CaloClusterCellLink * getCellLinks() const
Get a pointer to the CaloClusterCellLink object (const version).
virtual double pt() const
The transverse momentum ( ) of the particle (negative for negative-energy clusters).
Evaluate cluster kinematics with a different vertex / signal state.
std::vector< xAOD::CaloVertexedTopoCluster > vertexedClusters() const
const TauTrack * track(size_t i, TauJetParameters::TauTrackFlag flag=TauJetParameters::TauTrackFlag::classifiedCharged, int *container_index=0) const
Get the pointer to a given tauTrack associated with this tau /*container index needed by trackNonCons...
void setDetail(TauJetParameters::Detail detail, int value)
const Vertex * vertex() const
size_t nTracks(TauJetParameters::TauTrackFlag flag=TauJetParameters::TauTrackFlag::classifiedCharged) const
virtual double pt() const
The transverse momentum ( ) of the particle.
const TrackParticle * track() const
bool indexOfParameterAtPosition(unsigned int &index, ParameterPosition position) const
Function to determine if this TrackParticle contains track parameters at a certain position,...
float parameterPX(unsigned int index) const
Returns the parameter x momentum component, for 'index'.
float parameterX(unsigned int index) const
Returns the parameter x position, for 'index'.
float parameterPY(unsigned int index) const
Returns the parameter y momentum component, for 'index'.
float parameterZ(unsigned int index) const
Returns the parameter z position, for 'index'.
float parameterY(unsigned int index) const
Returns the parameter y position, for 'index'.
float charge() const
Returns the charge.
float parameterPZ(unsigned int index) const
Returns the parameter z momentum component, for 'index'.
const Amg::Vector3D & position() const
Returns the 3-pos.
constexpr double energyToActs(const double athenaE)
Converts an energy scalar from Athena to Acts units.
CurvilinearParametersT< TrackParametersDim, Charged, PlaneSurface > CurvilinearParameters
Definition index.py:1
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
TrackParticle_v1 TrackParticle
Reference the current persistent version:
TauJet_v3 TauJet
Definition of the current "tau version".
Definition TauJet.h:17
@ LastMeasurement
Parameter defined at the position of the last measurement.