15#include "Acts/Definitions/Units.hpp"
16#include "Acts/Definitions/Tolerance.hpp"
18#include "Acts/Propagator/ActorList.hpp"
19#include "Acts/Propagator/StandardAborters.hpp"
20#include "Acts/Propagator/SurfaceCollector.hpp"
21#include "Acts/Propagator/MaterialInteractor.hpp"
23#include "Acts/Utilities/AngleHelpers.hpp"
25#include "Acts/Utilities/VectorHelpers.hpp"
26#include "Acts/Utilities/Result.hpp"
27#include "Acts/Utilities/Helpers.hpp"
28#include "Acts/Utilities/Logger.hpp"
35using namespace Acts::VectorHelpers;
36using namespace Acts::UnitLiterals;
37using namespace Acts::AngleHelpers;
47 inline std::array<double, 2> pack(
const double eta,
const double phi) {
48 return std::array{
eta,
phi};
69 std::vector<std::pair<std::string, CaloSample>> volIndexNames{};
70 for (std::size_t
id = 0 ;
id < Acts::toUnderlying(CaloSample::Unknown); ++id){
71 const auto smpId =
static_cast<CaloSample>(id);
73 ATH_MSG_DEBUG(__func__<<
"() "<<__LINE__<<
" - "<<volIndexNames.back().first<<
" -> "
74 <<volIndexNames.back().second);
76 return StatusCode::SUCCESS;
82 const std::size_t nPhiBins = std::ceil((2.*std::numbers::pi) /
m_broadDeltaPhi);
83 ATH_MSG_DEBUG(__func__<<
"() "<<__LINE__<<
" - Create grid to sort the clusters with "<<nEtaBins
84 <<
" bins in eta and "<<nPhiBins<<
" bins in phi.");
86 PhiAxis_t{-std::numbers::pi, std::numbers::pi, nPhiBins}};
88 std::size_t selected{0ul};
96 bin.push_back(cluster);
99 ATH_MSG_DEBUG(__func__<<
"() "<<__LINE__<<
" - Selected "<<selected
100 <<
" out of "<<clusters.size()<<
" calo clusters.");
108 ATH_MSG_DEBUG(__func__<<
"() "<<__LINE__<<
" - Extrapolate track with pT: "<<(track->pt() * 1.e-3)
109 <<
" [GeV], eta: "<<track->eta()<<
", phi: "<<(track->phi() / 1._degree)<<
", q: "<<track->charge());
113 const Acts::GeometryContext tgContext =
m_ctxProvider.getGeometryContext(ctx);
114 auto extension = std::make_unique<CaloExtension>(track);
116 auto lastTrackPars = extension->lastParameters();
117 if (!lastTrackPars) {
118 ATH_MSG_WARNING(__func__<<
"() "<<__LINE__<<
" - The track does not have any Acts::BoundTrack parameters");
124 propOpts.recordPassive =
true;
125 propOpts.recordSensitive =
true;
126 ATH_MSG_DEBUG(__func__<<
"() "<<__LINE__<<
" - Start to propagate \n"<<(*lastTrackPars)<<
"\n, position: "
127 <<
Amg::toString(lastTrackPars->position(tgContext))<<
" through the calorimeter.");
128 auto surfaceRecord =
m_extrapolationTool->propagateAndRecord(ctx, *lastTrackPars, propOpts);
129 if (!surfaceRecord.ok()) {
130 ATH_MSG_WARNING(__func__<<
"() "<<__LINE__<<
" - Propagation through calorimeter did not succeed");
134 for (Acts::BoundTrackParameters& record : *surfaceRecord) {
136 if (caloEntrance->inside(tgContext, record.position(tgContext), Acts::s_onSurfaceTolerance) ||
137 record.referenceSurface().geometryId().withBoundary(0) == caloEntrance->geometryId()) {
140 const Acts::GeometryIdentifier volId{record.referenceSurface().geometryId().withBoundary(0).withSensitive(0)};
142 ATH_MSG_VERBOSE(__func__<<
"() "<<__LINE__<<
" - Append calorimeter parameters:\n"
143 <<record<<
",\n position:"<<
Amg::toString(record.position(tgContext))
144 <<
", surface: "<<record.referenceSurface().bounds()<<
", volume: "<<vol->volumeName()<<
".");
145 extension->appendParameters(std::move(record));
147 if (extension->empty()){
162 const Acts::GeometryContext tgContext =
m_ctxProvider.getGeometryContext(ctx);
166 const auto& clusterAxes = coneClusters.multiAxis();
169 ATH_CHECK(writeHandle.
record(std::make_unique<CaloExtensionContainer>()));
176 Link_t& extensionLink = decorHandle(*track);
187 const auto trackPos = pack(track->eta(), track->phi());
188 for (
const auto binIdx : clusterAxes.getNeighborHoodIndices(
189 clusterAxes.getLocalBinsFromPoint(trackPos))){
190 ATH_MSG_VERBOSE(__func__<<
"() "<<__LINE__<<
"() - Try to match "<<coneClusters.at(binIdx).size()<<
191 " clusters from bin "<<binIdx<<
". Central bin "
192 <<clusterAxes.getGlobalBinFromPoint(trackPos));
193 matchClusters(tgContext, coneClusters.at(binIdx), *extension);
196 extensionLink =
Link_t{writeHandle.
key(), writeHandle->size(), ctx};
197 writeHandle->push_back(std::move(extension));
200 return StatusCode::SUCCESS;
203 std::span<const xAOD::CaloCluster* const> clusterContainer,
211 for (
const Acts::BoundTrackParameters& recordedPars: caloExtension.
parameters()) {
212 const Acts::Surface& surf = recordedPars.referenceSurface();
213 ATH_MSG_VERBOSE(__func__<<
"() "<<__LINE__<<
" - Try to match "<<recordedPars
214 <<
",\nsurface:"<<surf.geometryId()<<
", bounds: "<<surf.bounds());
216 const float dEta = clusterEta(*matchMe) - Acts::VectorHelpers::eta(recordedPars);
218 ATH_MSG_VERBOSE(__func__<<
"() "<<__LINE__<<
" - dEta: "<<dEta<<
", dPhi: "<<dPhi<<
".");
227 <<
" clusters: "<<clusterContainer.size()<<
".");
231 const Acts::BoundTrackParameters& lastTrkPars)
const {
234 const double etaClust = clusterEta(cluster);
237 const Amg::Vector3D globTrkPos = lastTrkPars.position(tgContext);
238 const double trkEta = Acts::VectorHelpers::eta(lastTrkPars);
243 auto passDeltaPhi = [&]() ->
bool {
245 const double clusterPhi = globalClusterPosWrtPerigee.phi();
246 const double trkPhi = lastTrkPars.phi();
252 const double phiRotRescaled =
PhiROT(cluster.
et(), trkEta,
253 lastTrkPars.charge(),
254 globTrkPos.perp(), isEndCap);
261 const double phiRotTrack =
PhiROT(lastTrkPars.transverseMomentum(), trkEta,
262 lastTrkPars.charge(), globTrkPos.perp(), isEndCap);
269 ATH_MSG_VERBOSE(__func__<<
"() "<<__LINE__<<
" - broad dPhi matching fails with track phi: "<<
270 trkPhi<<
", phiRotCluster: "<<phiRotRescaled<<
", phiRotTrack: "<<phiRotTrack<<
", "
271 "cluster phi: "<<cluster.
phi()<<
", phi corrected: "<<clusterPhi);
275 if (!passDeltaPhi()) {
280 std::abs(globalClusterPosWrtPerigee.eta() - trkEta) <
m_broadDeltaEta) {
283 ATH_MSG_VERBOSE(__func__<<
"() "<<__LINE__<<
" broad dEta matching fails with track eta: "
284 <<trkEta<<
", cluster eta: "<<etaClust<<
", corrected eta: "<<globalClusterPosWrtPerigee.eta());
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_DEBUG(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_VERBOSE(x,...)
ElementLink< xAOD::TruthParticleContainer > Link_t
Handle class for reading from StoreGate.
Handle class for adding a decoration to an object.
Handle class for recording to StoreGate.
ToolHandle< InDet::IInDetTrackSelectionTool > m_trackSelector
Track quality selection tool (optional).
Gaudi::Property< float > m_minClustEt
Minimum requirement on the cluster's transversal energy in order to be considered.
ToolHandle< IegammaCaloClusterSelector > m_clusterSelector
Tool to filter the calo clusters.
virtual StatusCode execute(const EventContext &ctx) const override final
Gaudi::Property< float > m_narrowDeltaPhi
std::unique_ptr< CaloExtension > propagateToCaloExit(const EventContext &ctx, const xAOD::TrackParticle *track) const
Propagates the Track from the last track measurement to the calorimeter exit and records all surface ...
Acts::Grid< ClusterVec_t, EtaAxis_t, PhiAxis_t > SortedCluster_t
Define the segmen cluster grid made out of calo cluster containers segmented in eta & phi.
Gaudi::Property< bool > m_useHGTD
Toggle whether the ITk or the HGTD envelope shall be used to reject non-calo track states.
std::vector< const xAOD::CaloCluster * > ClusterVec_t
Use an Acts::Grid to segment the cluster in eta / phi space to reduce the matching combinatorics betw...
SortedCluster_t selectAndSort(const xAOD::CaloClusterContainer &clusters, const CaloDetDescrManager *detMgr) const
Selects the calo clusters for the matching to the ID tracks based on the eta range and on a minimum t...
bool checkBroadCriteria(const Acts::GeometryContext &tgContext, const xAOD::CaloCluster &cluster, const Acts::BoundTrackParameters &lastTrkPars) const
Checks whether the track @ its last measurement state is roughly compatible with the calorimeter clus...
virtual StatusCode initialize() override final
ServiceHandle< ActsTrk::ITrackingGeometrySvc > m_trackingGeometrySvc
Tracking geometry service.
SG::WriteDecorHandleKey< xAOD::TrackParticleContainer > m_extensionDecorKey
Decorate the link to the associated CaloExtension directly onto the ID / ITk track.
Gaudi::Property< float > m_broadDeltaPhi
Gaudi::Property< float > m_trackPt
The minimum momentum cut applied on the ID tracks to be considered.
Gaudi::Property< float > m_maxClustEta
Maximum cut on the cluster's eta in order to be considered.
SG::WriteHandleKey< CaloExtensionContainer > m_caloExtensionKey
Acts::Axis< Acts::AxisType::Equidistant, Acts::AxisBoundaryType::Bound > EtaAxis_t
Along eta define an equidistance binning without any overflow bin.
Acts::Axis< Acts::AxisType::Equidistant, Acts::AxisBoundaryType::Closed > PhiAxis_t
Along phi define an equidistance binning but with a circular wrapping connection between the two edge...
SG::ReadHandleKey< xAOD::CaloClusterContainer > m_clusterContainerKey
The input calorimeter cluster collection.
Gaudi::Property< float > m_narrowDeltaEta
Narrow windows.
xAOD::CaloCluster::CaloSample CaloSample
Gaudi::Property< float > m_broadDeltaEta
Broad windowsto initially match the calo cluster with the track exit parameters.
ActsTrk::ContextUtility m_ctxProvider
Context provider for geometry, magnetic field and calibration contexts.
SG::ReadHandleKey< xAOD::TrackParticleContainer > m_trackParticleContainerKey
The input track particle collection.
ToolHandle< IExtrapolationTool > m_extrapolationTool
Acts extrapolation tool to record the surface intersections.
void matchClusters(const Acts::GeometryContext &tgContext, std::span< const xAOD::CaloCluster *const > clusterContainer, CaloExtension &caloExtension) const
Match the selected calorimeter clusters to the calo extension.
SG::ReadCondHandleKey< CaloDetDescrManager > m_caloDetDescrMgrKey
Calo description manager.
The CaloExtension holds the ID extrapolation states through the calorimeter and the associated CaloCl...
const ClusterVec_t & associatedClusters() const
Returns the view on the asociated clusters.
void associateCluster(const xAOD::CaloCluster *clust)
Associates a calorimeter cluster with the calo extension.
std::optional< Acts::BoundTrackParameters > lastTrackParameters() const
Returns the track parameters asssociated with the last measurement state of the ID track.
const Acts::BoundTrackParameters & parameters(const std::size_t parIdx) const
Returns the extension parameters associated with the n-th extension.
This class provides the client interface for accessing the detector description information common to...
static std::string getSamplingName(CaloSample theSample)
Returns a string (name) for each CaloSampling.
ElementLink implementation for ROOT usage.
virtual const std::string & key() const override final
Return the StoreGate ID for the referenced object.
Handle class for adding a decoration to an object.
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
virtual double eta() const
The pseudorapidity ( ) 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.
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
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).
P4Helpers provides static helper functions for kinematic calculation on objects deriving from I4Momen...
double deltaPhi(double phiA, double phiB)
delta Phi in range [-pi,pi[
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
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
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
TrackParticle_v1 TrackParticle
Reference the current persistent version:
TrackParticleContainer_v1 TrackParticleContainer
Definition of the current "TrackParticle container version".
CaloClusterContainer_v1 CaloClusterContainer
Define the latest version of the calorimeter cluster container.