ATLAS Offline Software
DeltaRMatchingTool.icc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 /**
6  * @file DeltaRMatchingTool.icc
7  * @author Marco Aparo, Thomas Strebler
8  **/
9 
10 /// local includes
11 #include "TrackMatchingLookup.h"
12 #include "TrackParametersHelper.h"
13 
14 /// STL include(s)
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
18 
19 
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
28 {
29  for( const T* t : vTest ) {
30  /// Skip invalid test
31  if( not t ) continue;
32 
33  /// intialising large distance
34  float dist(999.);
35 
36  /// Find matched reference
37  const R* r = getMatchedRef( *t, vRef, dist );
38 
39  /// Skip if no reference is found
40  if( not r ) continue;
41 
42  ATH_MSG_DEBUG( "Found matched reference with pT = " << pT(*r) <<
43  " with dist = " << dist );
44 
45  /// Updating lookup table with new match
46  ATH_CHECK( matches.update( *t, *r, dist ) );
47  } // loop over vTest
48 
49  return StatusCode::SUCCESS;
50 }
51 
52 
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
59 {
60  ATH_MSG_DEBUG( "Reference vector size before sorting = " << vRef.size() );
61 
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 );
66 
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) ); } );
71 
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) ); } );
76 
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) ); } );
81 
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() );
85 
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; } );
95 
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); } );
102 
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(),
106  eta(t) - m_dRmax,
107  []( const R* r, const float& val ) -> bool{
108  return eta(*r) < val; } );
109 
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(),
113  eta(t) + m_dRmax,
114  []( const float& val, const R* r ) -> bool{
115  return val < eta(*r); } );
116 
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;
122 
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; } );
129 
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); } );
136 
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" );
140  return nullptr;
141  }
142 
143  if( m_dRmax > 0 and it_eta_upper < it_eta_lower ) {
144  ATH_MSG_DEBUG( "Break early: out of eta range" );
145  return nullptr;
146  }
147 
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" );
151  return nullptr;
152  }
153 
154  /// Initialise base set
155  std::vector< const R* > set( vec_pt );
156 
157  /// Sort, pointer-based; necessary for set_intersection
158  std::sort( set.begin(), set.end() );
159 
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;
164  if( !wrap ) {
165  subset_phi = std::vector< const R* >( it_phi_lower, it_phi_upper );
166  } else {
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() );
169  }
170 
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() );
174 
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 );
179  }
180  if( m_dRmax > 0 ) {
181  subsets.push_back( subset_eta );
182  subsets.push_back( subset_phi );
183  }
184 
185  /// Compute successive intersections between base set and subset
186  for( std::vector< const R* > subset : subsets ) {
187 
188  /// -- Sort, pointer-based; necessary for set::set_intersection
189  std::sort( subset.begin(), subset.end() );
190 
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 ) );
197 
198  /// -- Break early if intersection is empty
199  if( intersection.empty() ) {
200  ATH_MSG_DEBUG( "Break early: empty intersection" );
201  return nullptr;
202  }
203  set = intersection;
204  }
205 
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...
209 
210  /// If only pT-matching, return the closest track in pTres
211  if( m_dRmax < 0 ) {
212  int i_pTres_best(-1);
213  float pTres_best(999.);
214  for( size_t i=0 ; i<set.size() ; i++ ) {
215  float pTres_tmp =
216  std::fabs( pT(t) - pT( *(set.at(i)) ) ) / std::fabs( pT(t) );
217  if( pTres_tmp < pTres_best ) {
218  pTres_best = pTres_tmp;
219  i_pTres_best = i;
220  }
221  }
222  if( i_pTres_best < 0 ) return nullptr;
223  dist = pTres_best;
224  return set.at( i_pTres_best );
225  }
226 
227  /// Otherwise, compute dR for all remaining reference tracks
228  /// and return the closest one in dR
229  int i_dR_best(-1);
230  float dR_best(999.);
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 ) {
234  dR_best = dR_tmp;
235  i_dR_best = i;
236  }
237  }
238  if( i_dR_best < 0 ) return nullptr;
239  dist = dR_best;
240  return set.at(i_dR_best);
241 }