ATLAS Offline Software
Loading...
Searching...
No Matches
ParticleCaloExtensionTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4
6
13#include "TrkTrack/Track.h"
15#include "xAODEgamma/Electron.h"
16#include "xAODMuon/Muon.h"
19namespace Trk {
21 const std::string& n,
22 const IInterface* p)
23 : AthAlgTool(t, n, p)
24 , m_detID(nullptr)
26{
27 declareInterface<IParticleCaloExtensionTool>(this);
28}
29
31
32StatusCode
34{
35 /* Retrieve track extrapolator from ToolService */
36 ATH_CHECK(m_extrapolator.retrieve());
37 // Retrieve the calo surface builder
38 /* Retrieve the Atlas detector ID */
39 ATH_CHECK(detStore()->retrieve(m_detID, "AtlasID"));
40 /* convert string to proper particle type enum*/
41 if (m_particleTypeName == "nonInteracting") {
43 } else if (m_particleTypeName == "muon") {
45 } else if (m_particleTypeName == "pion") {
47 } else {
48 ATH_MSG_WARNING("Unsupported particle type, using strategy based on type "
50 }
51 if (!m_calosurf.empty()) {
52 ATH_CHECK(m_calosurf.retrieve());
53 } else {
54 m_calosurf.disable();
55 }
56 if (!m_monTool.empty()) {
57 ATH_CHECK(m_monTool.retrieve());
58 }
59 return StatusCode::SUCCESS;
60}
61
62std::unique_ptr<Trk::CaloExtension>
64 const xAOD::IParticle& particle) const
65{
66 if (particle.type() == xAOD::Type::TrackParticle) {
67 const xAOD::TrackParticle* trackParticle = static_cast<const xAOD::TrackParticle*>(&particle);
68 return caloExtension(ctx, *trackParticle);
69 }
70 if (particle.type() == xAOD::Type::TruthParticle) {
71 const xAOD::TruthParticle* truthParticle = static_cast<const xAOD::TruthParticle*>(&particle);
72 return caloExtension(ctx, *truthParticle);
73 } else if (particle.type() == xAOD::Type::Electron) {
74 const xAOD::Electron* el = static_cast<const xAOD::Electron*>(&particle);
75 if (el->trackParticle()) {
76 return caloExtension(ctx, *(el->trackParticle()));
77 }
78 } else if (particle.type() == xAOD::Type::Muon) {
79 const xAOD::Muon* muon = static_cast<const xAOD::Muon*>(&particle);
80 if (muon->primaryTrackParticle()) {
81 return caloExtension(ctx, *(muon->primaryTrackParticle()));
82 }
83 } else if (particle.type() == xAOD::Type::NeutralParticle) {
84 const xAOD::NeutralParticle* neutralParticle = static_cast<const xAOD::NeutralParticle*>(&particle);
85 return caloExtension(ctx, *neutralParticle);
86 }
87 ATH_MSG_WARNING("Unsupported IParticle type");
88 return nullptr;
89}
90
93 const EventContext& ctx,
94 const xAOD::IParticle& particle,
96{
97 /*if not there , default ctor for unique_ptr (nullptr)*/
98 std::unique_ptr<Trk::CaloExtension>& extension = cache[particle.index()];
99 if (extension == nullptr) {
100 extension = caloExtension(ctx, particle);
101 }
102 return extension.get();
103}
104
107 const xAOD::IParticle& particle,
108 const CaloExtensionCollection& cache) const
109{
110 size_t index = particle.index();
111 if (index < cache.size()) {
112 return cache[index];
113 }
114 ATH_MSG_WARNING("cache size smaller than particle index");
115 return nullptr;
116}
117
118StatusCode
120 const EventContext& ctx,
121 const xAOD::IParticleContainer& particles,
122 const std::vector<bool>& mask,
123 CaloExtensionCollection& caloextensions) const
124{
125 const size_t numparticles = particles.size();
126
127 if (mask.size() != numparticles) {
128 ATH_MSG_ERROR("mask does not have the same size as in input collection");
129 return StatusCode::FAILURE;
130 }
131 caloextensions.reserve(numparticles);
132 /* Either create a proper CaloExtension or otherwise a dummy one
133 * i.e one with no intersections
134 */
135 for (size_t i = 0; i < numparticles; ++i) {
136 if (mask[i]) {
137 std::unique_ptr<Trk::CaloExtension> extension =
138 caloExtension(ctx, *(particles[i]));
139 caloextensions.push_back(std::move(extension));
140 } else {
141 caloextensions.push_back(nullptr);
142 }
143 }
144 return StatusCode::SUCCESS;
145}
146
147std::unique_ptr<Trk::CaloExtension>
149 const EventContext& ctx,
150 const xAOD::TruthParticle& particle) const
151{
153 // get start parameters
154 const xAOD::TruthVertex* pvtx = particle.prodVtx();
155 if (pvtx == nullptr) {
156 return nullptr;
157 }
158 double charge = particle.charge();
159 Amg::Vector3D pos(pvtx->x(), pvtx->y(), pvtx->z());
160 Amg::Vector3D mom(particle.px(), particle.py(), particle.pz());
161 // Aproximate neutral particles as charged with infinite momentum
162 if (particle.isNeutral()) {
163 charge = 1.;
164 mom.normalize();
165 mom *= 1e10;
166 }
167 Trk::CurvilinearParameters startPars(pos, mom, charge);
168 // get extension
169 return caloExtension(ctx, startPars, alongMomentum, particleType);
170}
171
172std::unique_ptr<Trk::CaloExtension>
174 const EventContext& ctx,
175 const xAOD::NeutralParticle& particle) const
176{
178 // create start parameters
179 const Trk::NeutralPerigee& perigee = particle.perigeeParameters();
180 double charge = 1.;
181 const Amg::Vector3D& pos(perigee.position());
182 Amg::Vector3D mom(perigee.momentum());
183 // Aproximate neutral particles as charged with infinite momentum
184 mom.normalize();
185 mom *= 1e10;
186 Trk::CurvilinearParameters startPars(pos, mom, charge);
187 // get extension
188 return caloExtension(ctx, startPars, alongMomentum, particleType);
189}
190
191std::unique_ptr<Trk::CaloExtension>
193 const EventContext& ctx,
194 const xAOD::TrackParticle& particle) const
195{
196 // Start with what the user opted as strategy
198
199 // wee extrapolate either from the perigee or
200 // from the last measurement.
201 if (m_startFromPerigee || !particle.track()) {
202 bool idExit = true;
203 // Muon Entry is around z 6783 and r 4255
204 if (std::abs(particle.perigeeParameters().position().z()) > 6700.)
205 idExit = false;
206 if (particle.perigeeParameters().position().perp() > 4200.)
207 idExit = false;
208 PropDirection propDir = idExit ? alongMomentum : oppositeMomentum;
209 return caloExtension(
210 ctx, particle.perigeeParameters(), propDir, particleType);
211 }
212
213 // Extrapolation from last track parameters
214 const Track& track = *particle.track();
215 // Look-up the parameters closest to the calorimeter in
216 // ID and muon system
217 ATH_MSG_DEBUG("trying to add calo layers");
218 const TrackParameters* idExitParamers = nullptr;
219 const TrackParameters* muonEntryParamers = nullptr;
221 track.trackStateOnSurfaces()->begin();
222 for (; itTSoS != track.trackStateOnSurfaces()->end(); ++itTSoS) {
223 // select state with track parameters on a measurement
224 if (!(**itTSoS).trackParameters() ||
225 !(**itTSoS).type(TrackStateOnSurface::Measurement) ||
226 (**itTSoS).type(TrackStateOnSurface::Outlier)) {
227 continue;
228 }
229
230 const Identifier& id = (**itTSoS)
231 .trackParameters()
232 ->associatedSurface()
233 .associatedDetectorElementIdentifier();
234 if (m_detID->is_indet(id))
235 idExitParamers = (**itTSoS).trackParameters();
236 if (m_detID->is_muon(id) && !muonEntryParamers)
237 muonEntryParamers = (**itTSoS).trackParameters();
238 }
239 // require at least one of them
240 if (!idExitParamers && !muonEntryParamers) {
241 idExitParamers = track.perigeeParameters();
242 }
243 // pick start parameters, start in ID if possible
244 const TrackParameters* startPars =
245 idExitParamers ? idExitParamers : muonEntryParamers;
246
247 if (!startPars) {
248 ATH_MSG_WARNING("Failed to find start parameters");
249 return nullptr;
250 }
251 PropDirection propDir = idExitParamers ? alongMomentum : oppositeMomentum;
252
253 return caloExtension(ctx, *startPars, propDir, particleType);
254}
255
256std::unique_ptr<Trk::CaloExtension>
258 const TrackParameters& startPars,
259 PropDirection propDir,
261{
262 ATH_MSG_DEBUG("looking up calo states: r "
263 << startPars.position().perp() << " z "
264 << startPars.position().z() << " momentum "
265 << startPars.momentum().mag());
266
267 auto extrapolation_timer = Monitored::Timer<std::chrono::microseconds>( "TIME_extrapolation" );
268 auto group = Monitored::Group(m_monTool, extrapolation_timer);
269 // Start monitoring timer
270 extrapolation_timer.start();
271 /* The last argument to the extrapolate overload
272 * corresponds to a GeometrySignature value from
273 * TrkDetDescrUtils/GeometrySignature.h
274 * The extrapolation stop at the indicated subdetector exit
275 */
276 std::unique_ptr<
277 std::vector<std::pair<std::unique_ptr<Trk::TrackParameters>, int>>>
278 caloParameters = m_extrapolator->collectIntersections(
279 ctx, startPars, propDir, particleType, m_extrapolDetectorID);
280
281 // Stop monitoring timer
282 extrapolation_timer.stop();
283
284 if (!caloParameters) {
285 return nullptr;
286 }
287
288 TrackParametersIdHelper parsIdHelper;
289
290 // create final object
291 std::unique_ptr<TrackParameters> caloEntry = nullptr;
292 std::unique_ptr<TrackParameters> muonEntry = nullptr;
293 std::vector<CurvilinearParameters> caloLayers;
294 caloLayers.reserve(caloParameters->size() - 1);
295 ATH_MSG_DEBUG(" Found calo parameters: " << caloParameters->size()
296 << " extrapolation exit ID="
298
299 for (auto& p : *caloParameters) {
300 if (!p.first) {
301 continue;
302 }
303 // assign parameters
304 // calo aentry muon entry and the crossed calo layers
305 if (p.second == 1 && propDir == Trk::alongMomentum) {
306 caloEntry = std::move(p.first);
307 } else if (p.second == 3 && propDir == Trk::oppositeMomentum) {
308 caloEntry = std::move(p.first);
309 } else if (p.second == 3 && propDir == Trk::alongMomentum) {
310 muonEntry = std::move(p.first);
311 } else if (p.second == 4 && propDir == Trk::oppositeMomentum) {
312 muonEntry = std::move(p.first);
313 } else {
314 bool isEntry = p.second > 0;
315 TrackParametersIdentifier id = parsIdHelper.encode(
317 static_cast<CaloSampling::CaloSample>(abs(p.second) % 1000),
318 isEntry);
319 /*
320 * We construct curvilinear parameters which we push
321 * back to the caloLayers.
322 * curvillinear.
323 */
324 if (p.first->type() != Trk::Curvilinear) {
325 caloLayers.emplace_back(p.first->position(),
326 p.first->momentum(),
327 p.first->charge(),
328 std::nullopt,
329 id);
330 } else {
331 std::optional<AmgSymMatrix(5)> covariance(std::nullopt);
332 if (p.first->covariance()) {
333 covariance = AmgSymMatrix(5)(*(p.first->covariance()));
334 }
335 caloLayers.emplace_back(p.first->position(),
336 p.first->momentum(),
337 p.first->charge(),
338 std::move(covariance),
339 id);
340 }
341 }
342 }
343
344 if (!muonEntry && propDir == Trk::oppositeMomentum &&
345 std::abs(startPars.position().perp() - 4255.) < 1.) {
346 // muonEntry is right at the startPars position
347 muonEntry = startPars.uniqueClone();
348 }
349
350 return std::make_unique<Trk::CaloExtension>(
351 std::move(caloEntry), std::move(muonEntry), std::move(caloLayers));
352}
353
354std::vector<std::unique_ptr<Trk::Surface>>
356 const std::vector<CaloSampling::CaloSample>& clusterLayers,
357 double eta,
358 const CaloDetDescrManager& caloDD) const
359{
360 // Create surfaces at the layers
361 std::vector<std::unique_ptr<Trk::Surface>> caloSurfaces;
362 caloSurfaces.reserve(clusterLayers.size());
363 for (CaloSampling::CaloSample lay : clusterLayers) {
364 auto* surf = m_calosurf->CreateUserSurface(lay, 0., eta, &caloDD);
365 if (surf) {
366 caloSurfaces.emplace_back(surf);
367 }
368 }
369
370 return caloSurfaces;
371}
372
373std::vector<std::pair<CaloSampling::CaloSample,
374 std::unique_ptr<const Trk::TrackParameters>>>
376 const EventContext& ctx,
377 const TrackParameters& startPars,
378 const std::vector<CaloSampling::CaloSample>& clusterLayers,
379 const std::vector<std::unique_ptr<Trk::Surface>>& caloSurfaces,
381{
382 const auto* lastImpact = &startPars;
383 // Go into steps from layer to layer
384 size_t numSteps = caloSurfaces.size();
385 std::vector<std::pair<CaloSampling::CaloSample,
386 std::unique_ptr<const Trk::TrackParameters>>>
387 caloParameters{};
388 caloParameters.reserve(numSteps);
389 for (size_t i = 0; i < numSteps; ++i) {
390 std::unique_ptr<const Trk::TrackParameters> nextImpact =
391 m_extrapolator->extrapolateDirectly(ctx,
392 *lastImpact,
393 *(caloSurfaces[i]),
395 false,
397 if (nextImpact) {
398 caloParameters.emplace_back(clusterLayers[i], std::move(nextImpact));
399 lastImpact = caloParameters.back().second.get();
400 }
401 }
402 return caloParameters;
403}
404
405std::vector<std::pair<CaloSampling::CaloSample,
406 std::unique_ptr<const Trk::TrackParameters>>>
408 const EventContext& ctx,
409 const TrackParameters& startPars,
410 const std::vector<CaloSampling::CaloSample>& clusterLayers,
411 double eta,
412 const CaloDetDescrManager& caloDD,
414{
415
416 // Create surfaces at the layers
417 std::vector<std::unique_ptr<Trk::Surface>> caloSurfaces =
418 caloSurfacesFromLayers(clusterLayers, eta, caloDD);
419
421 ctx, startPars, clusterLayers, caloSurfaces, particleType);
422}
423
424} // end of namespace Trk
Scalar eta() const
pseudorapidity method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
This class provides an interface to generate or decode an identifier for the upper levels of the dete...
double charge(const T &p)
Definition AtlasPID.h:997
DataVector< Trk::CaloExtension > CaloExtensionCollection
#define AmgSymMatrix(dim)
unsigned int TrackParametersIdentifier
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
const ServiceHandle< StoreGateSvc > & detStore() const
This class provides the client interface for accessing the detector description information common to...
DataModel_detail::const_iterator< DataVector > const_iterator
Definition DataVector.h:838
void reserve(size_type n)
Attempt to preallocate enough memory for a specified number of elements.
value_type push_back(value_type pElem)
Add an element to the end of the collection.
size_type size() const noexcept
Returns the number of elements in the collection.
Group of local monitoring quantities and retain correlation when filling histograms
A monitored timer.
Tracking class to hold the extrapolation through calorimeter Layers Both the caloEntryLayerIntersecti...
std::unordered_map< size_t, std::unique_ptr< Trk::CaloExtension > > Cache
const Amg::Vector3D & momentum() const
Access method for the momentum.
const Amg::Vector3D & position() const
Access method for the position.
std::unique_ptr< ParametersBase< DIM, T > > uniqueClone() const
clone method for polymorphic deep copy returning unique_ptr; it is not overriden, but uses the existi...
virtual std::unique_ptr< Trk::CaloExtension > caloExtension(const EventContext &ctx, const xAOD::IParticle &particle) const override final
Method returning the calo layers crossed by the IParticle track or the IParticle itself if it is neut...
std::vector< std::unique_ptr< Trk::Surface > > caloSurfacesFromLayers(const std::vector< CaloSampling::CaloSample > &clusterLayers, double eta, const CaloDetDescrManager &caloDD) const override final
Method returning a vector of calo surfaces give calo layers/samplings.
virtual std::vector< std::pair< CaloSampling::CaloSample, std::unique_ptr< const Trk::TrackParameters > > > surfaceCaloExtension(const EventContext &ctx, const TrackParameters &startPars, const std::vector< CaloSampling::CaloSample > &clusterLayers, const std::vector< std::unique_ptr< Trk::Surface > > &caloSurfaces, ParticleHypothesis particleType) const override final
Method returning a vector of the Track Parameters at layers/samplings.
ToolHandle< ICaloSurfaceBuilder > m_calosurf
Tool to build calorimeter layer surfaces.
ParticleCaloExtensionTool(const std::string &, const std::string &, const IInterface *)
virtual StatusCode caloExtensionCollection(const EventContext &ctx, const xAOD::IParticleContainer &particles, const std::vector< bool > &mask, CaloExtensionCollection &caloextensions) const override final
Method that can be used by algorithms that : A.
ToolHandle< Trk::IExtrapolator > m_extrapolator
virtual StatusCode initialize() override final
Gaudi::Property< unsigned int > m_extrapolDetectorID
Gaudi::Property< std::string > m_particleTypeName
ToolHandle< GenericMonitoringTool > m_monTool
Monitoring tool for recording histograms of the alg in action.
virtual std::vector< std::pair< CaloSampling::CaloSample, std::unique_ptr< const Trk::TrackParameters > > > layersCaloExtension(const EventContext &ctx, const TrackParameters &startPars, const std::vector< CaloSampling::CaloSample > &clusterLayers, double eta, const CaloDetDescrManager &caloDD, ParticleHypothesis particleType) const override final
Method returning a vector of the Track Parameters at layers/samplings.
helper class to encode and decode a TrackParametersIdentifier
TrackParametersIdentifier encode(AtlasDetDescr::AtlasDetTechnology, CaloSampling::CaloSample, bool isEntryToVolume) const
Encodes a TrackParametersIdentifier from AtlasDetDescr::AtlasDetTechnology and CaloSampling::CaloSamp...
@ Measurement
This is a measurement, and will at least contain a Trk::MeasurementBase.
@ Outlier
This TSoS contains an outlier, that is, it contains a MeasurementBase/RIO_OnTrack which was not used ...
Class providing the definition of the 4-vector interface.
float z() const
Vertex longitudinal distance along the beam line form the origin.
float y() const
Vertex y displacement.
float x() const
Vertex x displacement.
Eigen::Matrix< double, 3, 1 > Vector3D
Ensure that the ATLAS eigen extensions are properly loaded.
PropDirection
PropDirection, enum for direction of the propagation.
@ oppositeMomentum
@ alongMomentum
ParametersT< NeutralParametersDim, Neutral, PerigeeSurface > NeutralPerigee
CurvilinearParametersT< TrackParametersDim, Charged, PlaneSurface > CurvilinearParameters
ParticleHypothesis
Enumeration for Particle hypothesis respecting the interaction with material.
ParametersBase< TrackParametersDim, Charged > TrackParameters
Definition index.py:1
@ TrackParticle
The object is a charged track particle.
Definition ObjectType.h:43
@ Muon
The object is a muon.
Definition ObjectType.h:48
@ TruthParticle
The object is a truth particle.
Definition ObjectType.h:67
@ NeutralParticle
The object is a neutral particle.
Definition ObjectType.h:44
@ Electron
The object is an electron.
Definition ObjectType.h:46
NeutralParticle_v1 NeutralParticle
Reference the current persistent version:
TruthVertex_v1 TruthVertex
Typedef to implementation.
Definition TruthVertex.h:15
TrackParticle_v1 TrackParticle
Reference the current persistent version:
TruthParticle_v1 TruthParticle
Typedef to implementation.
Muon_v1 Muon
Reference the current persistent version:
Electron_v1 Electron
Definition of the current "egamma version".
DataVector< IParticle > IParticleContainer
Simple convenience declaration of IParticleContainer.