10#include "GaudiKernel/EventContext.h"
19#include "Acts/Geometry/TrackingGeometry.hpp"
20#include "Acts/Surfaces/CurvilinearSurface.hpp"
21#include "Acts/Surfaces/PerigeeSurface.hpp"
22#include "Acts/Surfaces/PlaneSurface.hpp"
23#include "Acts/Utilities/Zip.hpp"
33 ISvcLocator* pSvcLocator)
51 const static std::map<std::string, std::size_t> volIndex = {
52 {
"PreSamplerB_Layer", 0},
59 std::vector<std::string> unmatchedVolumes;
62 auto name = vol->volumeName();
63 if( volIndex.contains(name) ) {
64 ATH_MSG_DEBUG(vol->volumeName() <<
" - " << vol->geometryId() <<
" - surfaces: " << vol->surfaces().size());
67 unmatchedVolumes.push_back(name);
73 if( geoId == Acts::GeometryIdentifier{} ) {
74 ATH_MSG_ERROR(
"Could not find geometry ID for barrel calo layer '" << layerInfo.first <<
"'");
78 for(
const auto &name : unmatchedVolumes ) {
83 return StatusCode::FAILURE;
87 return StatusCode::SUCCESS;
93 ATH_MSG_INFO(
"===> ACTS egamma Selected Tracks Statistics ======");
98 ATH_MSG_INFO(
"<=================================================");
100 return StatusCode::SUCCESS;
119 output_collection_t *viewCopy = outputTrkPartContainer.
ptr();
127 auto perigeeSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(Acts::Vector3::Zero());
130 std::vector<const xAOD::CaloCluster*> passingClusters;
131 passingClusters.reserve(clusterTES->size());
134 passingClusters.push_back(cluster);
138 if( passingClusters.empty() ) {
140 return StatusCode::SUCCESS;
148 ATH_MSG_DEBUG(
"Track eta " << track->eta() <<
" outside coverage " <<
165 viewCopy->push_back(track);
173 return StatusCode::SUCCESS;
180 const std::shared_ptr<const Acts::Surface>& perigeeSurface)
const
182 using namespace Acts::UnitLiterals;
185 << cluster.
eta() <<
", " << cluster.
phi());
188 unsigned int lastMeasIdx = 0;
194 Acts::Vector3 lastPos{track.parameterX(lastMeasIdx),
195 track.parameterY(lastMeasIdx),
196 track.parameterZ(lastMeasIdx)};
197 Acts::Vector3 lastMom{track.parameterPX(lastMeasIdx),
198 track.parameterPY(lastMeasIdx),
199 track.parameterPZ(lastMeasIdx)};
200 lastMom *= Acts::UnitConstants::MeV;
202 ATH_MSG_DEBUG(
"Last measurement global position: " << lastPos.transpose());
204 Acts::BoundVector lastBoundParams = Acts::BoundVector::Zero();
205 lastBoundParams[Acts::eBoundPhi] = Acts::VectorHelpers::phi(lastMom);
206 lastBoundParams[Acts::eBoundTheta] = Acts::VectorHelpers::theta(lastMom);
207 lastBoundParams[Acts::eBoundQOverP] = track.charge() / lastMom.norm();
209 std::shared_ptr<const Acts::Surface> lastSurface =
210 Acts::CurvilinearSurface(lastPos, lastMom.normalized()).planeSurface()->getSharedPtr();
211 Acts::BoundTrackParameters boundPars{
215 Acts::ParticleHypothesis::electron()
219 auto extractCaloMatch = [&](
const auto &caloMatches) {
220 if( caloMatches.at(2).has_value() ) {
221 return caloMatches.at(2);;
223 ATH_MSG_DEBUG(
"No calo match at EM2, trying any other layer");
224 for(
const auto &matchOpt : caloMatches ) {
225 if( matchOpt.has_value() ) {
226 ATH_MSG_DEBUG(
"Using calo match at layer " << matchOpt->layer);
230 return std::optional<CaloMatch>{};
234 auto caloMatch = extractCaloMatch(caloMatches);
235 if( !caloMatch.has_value() ) {
236 ATH_MSG_DEBUG(
"Could not extrapolate to calo from last measurement");
241 ATH_MSG_DEBUG(
"Calo match from last measurement at " << caloMatch->layer
242 <<
", dEta: " << caloMatch->deltaEta
243 <<
", dPhi: " << caloMatch->deltaPhi);
247 ATH_MSG_DEBUG(
"Fails narrow window eta match, deta=" << caloMatch->deltaEta);
254 ATH_MSG_DEBUG(
"Match from Last measurement is successful, deta=" << caloMatch->deltaEta
255 <<
" , dphi=" << caloMatch->deltaPhi);
260 Acts::BoundVector paramsAtPerigee = Acts::BoundVector::Zero();
261 paramsAtPerigee[Acts::eBoundLoc0] = track.d0();
262 paramsAtPerigee[Acts::eBoundLoc1] = track.z0();
263 paramsAtPerigee[Acts::eBoundPhi] = track.phi0();
264 paramsAtPerigee[Acts::eBoundTheta] = track.theta();
265 paramsAtPerigee[Acts::eBoundQOverP] = track.charge() / (cluster.
e() * Acts::UnitConstants::MeV);
267 Acts::BoundTrackParameters rescaledParsPerigee{
271 Acts::ParticleHypothesis::electron()
274 const auto caloMatchesRescaled =
extrapolateToCalo(rescaledParsPerigee, cluster, ctx);
275 auto caloMatchRescaled = extractCaloMatch(caloMatchesRescaled);
277 if( !caloMatchRescaled.has_value() ) {
278 ATH_MSG_DEBUG(
"Could not extrapolate to calo from rescaled perigee");
283 ATH_MSG_DEBUG(
"Calo match from perigee rescaled at " << caloMatchRescaled->layer
284 <<
", dEta: " << caloMatchRescaled->deltaEta
285 <<
", dPhi: " << caloMatchRescaled->deltaPhi);
290 ATH_MSG_DEBUG(
"Match from Perigee Rescaled is successful, dphi=" << caloMatchRescaled->deltaPhi);
302 const Trk::Perigee& perigee = track.perigeeParameters();
305 const double trkPhi = perigee.parameters()[
Trk::phi];
306 const double z_perigee = perigee.
position().z();
316 const double Et = cluster.
e() / std::cosh(perigee.
eta());
326 cluster, perigee.
position(), isEndCap);
331 Et, perigee.
eta(), track.charge(), perigee.
position().perp(), isEndCap);
335 track.pt(), perigee.
eta(), track.charge(), perigee.
position().perp(), isEndCap);
337 const double clusterPhiCorrected = globalClusterPosWrtPerigee.phi();
347 const bool failPhiRescalded = std::abs(deltaPhiRescaled) >
m_broadDeltaPhi;
355 if (failPhiRescalded && failPhiTrack && failPhiStd) {
357 "FAILS broad window phi match (track phi, phirotCluster , phiRotTrack , " <<
358 "cluster phi corrected, cluster phi): ( " <<
360 phiRotRescaled <<
", " <<
361 phiRotTrack <<
", " <<
362 clusterPhiCorrected <<
", " <<
369 const double clusterEtaCorrected = globalClusterPosWrtPerigee.eta();
371 const bool failEtaCorrected = std::abs(globalClusterPosWrtPerigee.eta() - perigee.
eta()) >
m_broadDeltaEta;
373 if (failEta && failEtaCorrected) {
375 "FAILS broad window eta match (track eta, cluster eta, cluster eta corrected): ( " <<
376 perigee.
eta() <<
", " <<
377 cluster.
eta() <<
", " <<
378 clusterEtaCorrected <<
" )"
388 const EventContext& ctx)
const
396 const auto &[steps, _] =
res.value();
398 std::array<std::optional<CaloMatch>, 4> matches{};
399 for(
const auto &step : steps) {
400 if( step.surface ==
nullptr || step.surface->geometryId().sensitive() == 0 ) {
403 const auto &p = step.position;
409 ATH_MSG_VERBOSE(
"Extrapolated step at pos [r,z]: " << std::hypot(p.x(), p.y())
410 <<
", " << p.z() <<
" - : " << step.geoID);
412 auto found = std::ranges::find_if(
m_barrelCaloGeoIds, [&](
const Acts::GeometryIdentifier &
id){
413 return id.volume() == step.geoID.volume();
421 assert(layerIdx >= 0 && layerIdx < 4);
423 if( matches.at(layerIdx).has_value() ) {
428 auto eta = Acts::VectorHelpers::eta(p);
429 auto phi = Acts::VectorHelpers::phi(p);
431 double deltaEta =
eta - cluster.
etaBE(layerIdx);
434 ATH_MSG_DEBUG(
"Step at pos [r,z]: " << std::hypot(p.x(), p.y()) <<
435 ", layerIdx: " << layerIdx <<
436 ", " << p.z() <<
" - : " << step.geoID <<
437 ", dEta: " << deltaEta <<
", dPhi: " <<
deltaPhi);
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_VERBOSE(x)
#define ATH_MSG_WARNING(x)
Definition of CaloDetDescrManager.
Helpers for checking error return status codes and reporting errors.
std::pair< std::vector< unsigned int >, bool > res
Handle class for reading from StoreGate.
Handle class for recording to StoreGate.
Gaudi::Accumulators::Counter m_AllClusters
virtual StatusCode finalize() override final
virtual StatusCode initialize() override final
bool checkBroadCriteria(const xAOD::CaloCluster &cluster, const xAOD::TrackParticle &track) const
ToolHandle< ActsTrk::IExtrapolationTool > m_extrapolationTool
SG::ReadHandleKey< xAOD::TrackParticleContainer > m_trackParticleContainerKey
virtual StatusCode execute(const EventContext &ctx) const override final
static constexpr double s_calorimeterEtaCoverage
static constexpr double s_maxExtrapolationRadius
PublicToolHandle< ActsTrk::ITrackingGeometryTool > m_trackingGeometryTool
Gaudi::Property< double > m_narrowDeltaEta
Narrow windows.
bool matchWithExtrapolation(const EventContext &ctx, const xAOD::CaloCluster &cluster, const xAOD::TrackParticle &track, const std::shared_ptr< const Acts::Surface > &perigeeSurface) const
Track selection method.
Gaudi::Property< double > m_broadDeltaPhi
Gaudi::Accumulators::Counter m_SelectedClusters
Gaudi::Property< double > m_narrowDeltaPhi
SG::WriteHandleKey< ConstDataVector< xAOD::TrackParticleContainer > > m_OutputTrkPartContainerKey
std::array< Acts::GeometryIdentifier, 4 > m_barrelCaloGeoIds
SG::ReadHandleKey< xAOD::CaloClusterContainer > m_clusterContainerKey
Names of input output collections.
Gaudi::Property< double > m_narrowDeltaPhiBrem
Gaudi::Accumulators::Counter m_SelectedTracks
Gaudi::Property< double > m_narrowRescale
std::array< std::optional< CaloMatch >, 4 > extrapolateToCalo(const Acts::BoundTrackParameters ¶meters, const xAOD::CaloCluster &cluster, const EventContext &ctx) const
SG::ReadCondHandleKey< CaloDetDescrManager > m_caloDetDescrMgrKey
Gaudi::Property< double > m_broadDeltaEta
Broad windows.
Gaudi::Accumulators::Counter m_AllTracks
Gaudi::Property< double > m_narrowRescaleBrem
ActsEgammaSelectedTrackCopy(const std::string &name, ISvcLocator *pSvcLocator)
Default constructor.
ToolHandle< IegammaCaloClusterSelector > m_egammaCaloClusterSelector
Tool to filter the calo clusters.
An algorithm that can be simultaneously executed in multiple threads.
This class provides the client interface for accessing the detector description information common to...
DataVector adapter that acts like it holds const pointers.
const_pointer_type cptr()
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.
pointer_type ptr()
Dereference the pointer.
double eta() const
Access method for pseudorapidity - from momentum.
const Amg::Vector3D & position() const
Access method for the position.
float phiBE(const unsigned layer) const
Get the phi in one layer of the EM Calo.
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.
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[
@ VIEW_ELEMENTS
this data object is a view, it does not own its elmts
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
ParametersT< TrackParametersDim, Charged, PerigeeSurface > Perigee
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:
@ LastMeasurement
Parameter defined at the position of the last measurement.