2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
4#ifndef TRUTHCLUSTERSPLITTINGTOOLIMPL_ICC
5#define TRUTHCLUSTERSPLITTINGTOOLIMPL_ICC
10#include "ActsGeometry/ActsDetectorElement.h"
11#include <PixelReadoutGeometry/PixelModuleDesign.h>
12#include "AthenaBaseComps/AthMsgStreamMacros.h"
13#include "InDetReadoutGeometry/SiDetectorElement.h"
14#include "InDetMeasurementUtilities/Helpers.h"
18namespace ActsTrk::detail {
20template <typename traj_t>
21StatusCode TruthClusterSplittingToolImpl<traj_t>::initialize()
23 ATH_MSG_DEBUG("Initializing " << AthAlgTool::name() << " ...");
25 ATH_CHECK( BASE::initialize() );
26 ATH_CHECK(m_associationMap_key.initialize());
27 ATH_CHECK( m_truthSelectionTool.retrieve() );
28 ATH_MSG_DEBUG(AthAlgTool::name() << " successfully initialized");
30 ATH_MSG_DEBUG( this->calibrateAfterMeasurementSelection() );
32 return StatusCode::SUCCESS;
35template <typename traj_t>
36const ActsTrk::MeasurementToTruthParticleAssociation*
37TruthClusterSplittingToolImpl<traj_t>::getAssociationMap(const EventContext &ctx) const
39 const MeasurementToTruthParticleAssociation* measToTruth(nullptr);
40 if (!SG::get(measToTruth,m_associationMap_key,ctx).isSuccess()) {
41 throw std::runtime_error(std::format("No truth association map {:}.", m_associationMap_key.key()));
47template <typename traj_t>
48const IAthSelectionTool*
49TruthClusterSplittingToolImpl<traj_t>::getTruthSelectionTool() const
51 assert(m_truthSelectionTool.isValid());
52 return m_truthSelectionTool.get();
56template <typename traj_t>
57std::tuple<typename TruthClusterSplittingCalibrator<traj_t>::BASE::Pos,
58 typename TruthClusterSplittingCalibrator<traj_t>::BASE::Cov,
60TruthClusterSplittingCalibrator<traj_t>::calibrate(
61 const EventContext& /*ctx*/,
62 const Acts::GeometryContext& /*gctx*/,
63 const Acts::CalibrationContext& /*cctx*/,
64 const xAOD::PixelCluster& cluster,
65 const InDetDD::SiDetectorElement& /*sdectx*/,
66 const std::pair<float, float>& /*tan_incidence_angles*/,
67 const Acts::Vector2& /*predicted_local_position*/) const
69 typename BASE::Pos pos = cluster.template localPosition<2>();
70 typename BASE::Cov cov = cluster.template localCovariance<2>();
71 assert(!cluster.rdoList().empty());
73 if (m_options.m_measToTruth->sourceContainer() != cluster.container()) { // check compatibility of association map with cluster
74 throw std::runtime_error(std::format("AssociationMap and pixel cluster (index {:}) are not compatible.", cluster.index()));
76 if (cluster.index() >= m_options.m_measToTruth->size()) { // if cluster index inside container is bigger than number of cluster in container
77 throw std::runtime_error(std::format("PRD index {:} not present in the measurement to truth vector with size {:}", cluster.index(), m_options.m_measToTruth->size()));
80 const auto & tps = m_options.m_measToTruth->at(cluster.index()); // returns truth particles
82 int num_truth_particles = 0;
83 for (const auto& tp : tps) {
84 // Apply same cuts on truth particles as for efficiency plots, see `athena/InnerDetector/InDetValidation/InDetPhysValMonitoring/python/InDetPhysValMonitoringConfig.py#L47-L87`
85 const IAthSelectionTool::CutResult accept = m_options.m_truthSelectionTool->accept(tp);
86 if (!accept) continue;
87 num_truth_particles += 1;
89 // TO-DO: use position truth information of truth particle update "pos" (there are multiple ways how to do so)
91 // check whether cluster created by multiple truth particles
92 unsigned int splitFlag = num_truth_particles > 1
93 ? detail::setTrackStateFlag(Acts::TrackStateFlag::IsSplitHit)
96 return std::make_tuple(std::move(pos), std::move(cov), splitFlag);
100} // namespace ActsTrk