2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
6 * @file DeltaRMatchingTool.icc
7 * @author Marco Aparo, Thomas Strebler
11 #include "TrackMatchingLookup.h"
12 #include "TrackParametersHelper.h"
15 #include <cmath> // std::fabs
16 #include <algorithm> // for std::sort, std::lower_bound, std::upper_bound, std::set_intersection
17 #include <iterator> // std::back_inserter
20 /// ------------------------
21 /// ----- matchVectors -----
22 /// ------------------------
23 template< typename T, typename R >
24 StatusCode IDTPM::DeltaRMatchingToolBase<T, R>::matchVectors(
25 const std::vector< const T* >& vTest,
26 const std::vector< const R* >& vRef,
27 ITrackMatchingLookup& matches ) const
29 for( const T* t : vTest ) {
33 /// intialising large distance
36 /// Find matched reference
37 const R* r = getMatchedRef( *t, vRef, dist );
39 /// Skip if no reference is found
42 ATH_MSG_DEBUG( "Found matched reference with pT = " << pT(*r) <<
43 " with dist = " << dist );
45 /// Updating lookup table with new match
46 ATH_CHECK( matches.update( *t, *r, dist ) );
49 return StatusCode::SUCCESS;
53 /// -------------------------
54 /// ----- getMatchedRef -----
55 /// -------------------------
56 template< typename T, typename R >
57 const R* IDTPM::DeltaRMatchingToolBase<T, R>::getMatchedRef(
58 const T& t, const std::vector< const R* >& vRef, float& dist ) const
60 ATH_MSG_DEBUG( "Reference vector size before sorting = " << vRef.size() );
62 /// Initially making copies of the whole reference vector
63 std::vector< const R* > vec_pt( vRef );
64 std::vector< const R* > vec_eta( vRef );
65 std::vector< const R* > vec_phi( vRef );
67 /// Sorting vec_pt by increasing pT
68 std::sort( vec_pt.begin(), vec_pt.end(),
69 []( const R* r1, const R* r2 ) -> bool{
70 return ( pT(*r1) < pT(*r2) ); } );
72 /// Sorting vec_eta by increasing eta
73 std::sort( vec_eta.begin(), vec_eta.end(),
74 []( const R* r1, const R* r2 ) -> bool{
75 return ( eta(*r1) < eta(*r2) ); } );
77 /// Sorting vec_phi by increasing phi
78 std::sort( vec_phi.begin(), vec_phi.end(),
79 []( const R* r1, const R* r2 ) -> bool{
80 return ( phi(*r1) < phi(*r2) ); } );
82 ATH_MSG_DEBUG( "Reference vector size after pT sorting = " << vec_pt.size() );
83 ATH_MSG_DEBUG( "Reference vector size after eta sorting = " << vec_eta.size() );
84 ATH_MSG_DEBUG( "Reference vector size after phi sorting = " << vec_phi.size() );
86 /// Perform search in reference vectors to select the references
87 /// in the [eta(t)-dR, eta(t)+dR], [phi(t)-dR, phi(t)+dR] ranges
88 /// and, if applicable, in the [pT(t)*(1-pTres),pT(t)*(1+pTres)] range
89 typename std::vector< const R* >::iterator it_pt_lower =
90 m_pTResMax < 0 ? vec_pt.begin() :
91 std::lower_bound( vec_pt.begin(), vec_pt.end(),
92 pT(t) * ( 1. - m_pTResMax ),
93 []( const R* r, const float& val ) -> bool{
94 return pT(*r) < val; } );
96 typename std::vector< const R* >::iterator it_pt_upper =
97 m_pTResMax < 0 ? vec_pt.end() :
98 std::upper_bound( vec_pt.begin(), vec_pt.end(),
99 pT(t) * ( 1. + m_pTResMax ),
100 []( const float& val, const R* r ) -> bool{
101 return val < pT(*r); } );
103 typename std::vector< const R* >::iterator it_eta_lower =
104 m_dRmax < 0 ? vec_eta.begin() :
105 std::lower_bound( vec_eta.begin(), vec_eta.end(),
107 []( const R* r, const float& val ) -> bool{
108 return eta(*r) < val; } );
110 typename std::vector< const R* >::iterator it_eta_upper =
111 m_dRmax < 0 ? vec_eta.end() :
112 std::upper_bound( vec_eta.begin(), vec_eta.end(),
114 []( const float& val, const R* r ) -> bool{
115 return val < eta(*r); } );
117 /// Dealing with cyclic nature of phi:
118 /// Determining whether phi range wraps around +-PI
119 bool wrapLow = phi(t) - m_dRmax < -M_PI;
120 bool wrapHigh = phi(t) + m_dRmax > M_PI;
121 bool wrap = wrapLow or wrapHigh;
123 typename std::vector< const R* >::iterator it_phi_lower =
124 m_dRmax < 0 ? vec_phi.begin() :
125 std::lower_bound( vec_phi.begin(), vec_phi.end(),
126 phi(t) - m_dRmax + ( wrapLow ? 2.*M_PI : 0 ),
127 []( const R* r, const float& val ) -> bool{
128 return phi(*r) < val; } );
130 typename std::vector< const R* >::iterator it_phi_upper =
131 m_dRmax < 0 ? vec_phi.end() :
132 std::upper_bound( vec_phi.begin(), vec_phi.end(),
133 phi(t) + m_dRmax + ( wrapHigh ? -2.*M_PI : 0 ),
134 []( const float& val, const R* r ) -> bool{
135 return val < phi(*r); } );
137 /// Break early if no reference track passed the selection
138 if( m_pTResMax > 0 and it_pt_upper < it_pt_lower ) {
139 ATH_MSG_DEBUG( "Break early: out of pTres range" );
143 if( m_dRmax > 0 and it_eta_upper < it_eta_lower ) {
144 ATH_MSG_DEBUG( "Break early: out of eta range" );
148 if( m_dRmax > 0 and ( ( !wrap and it_phi_upper < it_phi_lower ) or
149 ( wrap and it_phi_upper > it_phi_lower ) ) ) {
150 ATH_MSG_DEBUG( "Break early: out of phi range" );
154 /// Initialise base set
155 std::vector< const R* > set( vec_pt );
157 /// Sort, pointer-based; necessary for set_intersection
158 std::sort( set.begin(), set.end() );
160 /// Compute subset of selected truth particles
161 std::vector< const R* > subset_pt( it_pt_lower, it_pt_upper );
162 std::vector< const R* > subset_eta( it_eta_lower, it_eta_upper );
163 std::vector< const R* > subset_phi;
165 subset_phi = std::vector< const R* >( it_phi_lower, it_phi_upper );
167 subset_phi = std::vector< const R* >( vec_phi.begin(), it_phi_upper );
168 subset_phi.insert( subset_phi.end(), it_phi_lower, vec_phi.end() );
171 ATH_MSG_DEBUG( "Reference vector subset_pt size = " << subset_pt.size() );
172 ATH_MSG_DEBUG( "Reference vector subset_eta size = " << subset_eta.size() );
173 ATH_MSG_DEBUG( "Reference vector subset_phi size = " << subset_phi.size() );
175 /// Add subsets according to specified cut values
176 std::vector< std::vector< const R* > > subsets;
177 if( m_pTResMax > 0 ) {
178 subsets.push_back( subset_pt );
181 subsets.push_back( subset_eta );
182 subsets.push_back( subset_phi );
185 /// Compute successive intersections between base set and subset
186 for( std::vector< const R* > subset : subsets ) {
188 /// -- Sort, pointer-based; necessary for set::set_intersection
189 std::sort( subset.begin(), subset.end() );
191 /// -- Set intersection
192 std::vector< const R* > intersection;
193 std::set_intersection(
194 set.begin(), set.end(),
195 subset.begin(), subset.end(),
196 std::back_inserter( intersection ) );
198 /// -- Break early if intersection is empty
199 if( intersection.empty() ) {
200 ATH_MSG_DEBUG( "Break early: empty intersection" );
206 /// vector "set" now contains all matched reference tracks
207 ATH_MSG_DEBUG( "Reference vector subsets intersection size = " << set.size() );
208 /// Now picking the best match...
210 /// If only pT-matching, return the closest track in pTres
212 int i_pTres_best(-1);
213 float pTres_best(999.);
214 for( size_t i=0 ; i<set.size() ; i++ ) {
216 std::fabs( pT(t) - pT( *(set.at(i)) ) ) / std::fabs( pT(t) );
217 if( pTres_tmp < pTres_best ) {
218 pTres_best = pTres_tmp;
222 if( i_pTres_best < 0 ) return nullptr;
224 return set.at( i_pTres_best );
227 /// Otherwise, compute dR for all remaining reference tracks
228 /// and return the closest one in dR
231 for( size_t i=0 ; i<set.size() ; i++ ) {
232 float dR_tmp = deltaR( t, *(set.at(i)) );
233 if( dR_tmp < dR_best and dR_tmp < m_dRmax ) {
238 if( i_dR_best < 0 ) return nullptr;
240 return set.at(i_dR_best);