ATLAS Offline Software
Loading...
Searching...
No Matches
TrigInDetR3PattRecoTools/src/SeedingToolBase.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
7
9
11
13
15
16#include "SeedingToolBase.h"
17
18
19StatusCode SeedingToolBase::initialize() {
20 ATH_CHECK(AthAlgTool::initialize());
21
22 ATH_CHECK(m_layerNumberTool.retrieve());
23
24
25 ATH_CHECK(detStore()->retrieve(m_atlasId, "AtlasID"));
26
27 ATH_CHECK(detStore()->retrieve(m_pixelId, "PixelID"));
28
29 ATH_CHECK(detStore()->retrieve(m_sctId, "SCT_ID"));
30
31 std::string conn_fileName = PathResolver::find_file(m_connectionFile, "DATAPATH");
32 if (conn_fileName.empty()) {
33 ATH_MSG_FATAL("Cannot find layer connections file " << conn_fileName);
34 return StatusCode::FAILURE;
35 }
36 else {
37
38 std::ifstream ifs(conn_fileName.c_str());
39
40 m_connector = std::make_unique<GNNR3_FASTRACK_CONNECTOR>(ifs, m_LRTmode);
41 if (m_etaBinOverride != 0.0f) {
42 m_connector->m_etaBin = m_etaBinOverride;
43 }
44
45 ATH_MSG_INFO("Layer connections are initialized from file " << conn_fileName);
46 }
47
48 const std::vector<TrigInDetSiLayer>* pVL = m_layerNumberTool->layerGeometry();
49
50 std::copy(pVL->begin(),pVL->end(), std::back_inserter(m_layerGeometry));
51
52 m_geo = std::make_unique<TrigFTF_GNNR3_Geometry>(m_layerGeometry, m_connector);
53
55
56 ATH_MSG_INFO("SeedingToolBase initialized ");
57
58 ATH_MSG_DEBUG("Property useML "<< m_useML);
59 ATH_MSG_DEBUG("Property DoPhiFiltering "<<m_filter_phi);
60 ATH_MSG_DEBUG("Property pTmin "<<m_minPt);
61 ATH_MSG_DEBUG("Property LRTmode "<<m_LRTmode);
62
63 return StatusCode::SUCCESS;
64}
65
66StatusCode SeedingToolBase::finalize() {
67 StatusCode sc = AthAlgTool::finalize();
68 return sc;
69}
70
71std::pair<int, int> SeedingToolBase::buildTheGraph(const IRoiDescriptor& roi, const std::unique_ptr<TrigFTF_GNNR3_DataStorage>& storage, std::vector<TrigFTF_GNNR3_Edge>& edgeStorage) const {
72
73 const float M_2PI = 2.0*M_PI;
74
75 const float cut_dphi_max = m_LRTmode ? 0.07 : 0.012;
76 const float cut_dcurv_max = m_LRTmode ? 0.015 : 0.001;
77 const float cut_tau_ratio_max = m_LRTmode ? 0.015 : 0.007;
78 const float min_z0 = m_LRTmode ? -600.0 : roi.zedMinus();
79 const float max_z0 = m_LRTmode ? 600.0 : roi.zedPlus();
80 const float min_deltaPhi = m_LRTmode ? 0.01f : 0.001f;
81
82 const float maxOuterRadius = m_LRTmode ? 1050.0 : 550.0;
83
84 const float cut_zMinU = min_z0 + maxOuterRadius*roi.dzdrMinus();
85 const float cut_zMaxU = max_z0 + maxOuterRadius*roi.dzdrPlus();
86
87 const float ptCoeff = 0.29997*1.9972/2.0;// ~0.3*B/2 - assuming nominal field of 2*T
88
89 float tripletPtMin = 0.8*m_minPt;//correction due to limited pT resolution
90
91 float maxCurv = ptCoeff/tripletPtMin;
92
93 const float maxKappa_high_eta = m_LRTmode ? 1.0*maxCurv : std::sqrt(0.8)*maxCurv;
94 const float maxKappa_low_eta = m_LRTmode ? 1.0*maxCurv : std::sqrt(0.6)*maxCurv;
95 const float dphi_coeff = m_LRTmode ? 1.0*maxCurv : 0.68*maxCurv;
96
97 const float minDeltaRadius = 2.0;
98
99 float deltaPhi = 0.5f*m_phiSliceWidth;//the default sliding window along phi
100
101 unsigned int nConnections = 0;
102
103 edgeStorage.reserve(m_nMaxEdges);
104
105 int nEdges = 0;
106
107 for(const auto& bg : m_geo->bin_groups()) {//loop over bin groups
108
109 TrigFTF_GNNR3_EtaBin& B1 = storage->getEtaBin(bg.first);
110
111 if(B1.empty()) continue;
112
113 float rb1 = B1.getMinBinRadius();
114
115 for(const auto& b2_idx : bg.second) {
116
117 const TrigFTF_GNNR3_EtaBin& B2 = storage->getEtaBin(b2_idx);
118
119 if(B2.empty()) continue;
120
121 float rb2 = B2.getMaxBinRadius();
122
123 if(m_useEtaBinning) {
124 deltaPhi = min_deltaPhi + dphi_coeff*std::fabs(rb2-rb1);
125 }
126
127 unsigned int first_it = 0;
128
129 for(unsigned int n1Idx = 0;n1Idx<B1.m_vn.size();n1Idx++) {//loop over nodes in Layer 1
130
131 std::vector<unsigned int>& v1In = B1.m_in[n1Idx];
132
133 if(v1In.size() >= MAX_SEG_PER_NODE) continue;
134
135 const std::array<float, 5>& n1pars = B1.m_params[n1Idx];
136
137 float phi1 = n1pars[2];
138 float r1 = n1pars[3];
139 float z1 = n1pars[4];
140
141 //sliding window phi1 +/- deltaPhi
142
143 float minPhi = phi1 - deltaPhi;
144 float maxPhi = phi1 + deltaPhi;
145
146 for(unsigned int n2PhiIdx = first_it; n2PhiIdx<B2.m_vPhiNodes.size();n2PhiIdx++) {//sliding window over nodes in Layer 2
147
148 float phi2 = B2.m_vPhiNodes[n2PhiIdx].first;
149
150 if(phi2 < minPhi) {
151 first_it = n2PhiIdx;
152 continue;
153 }
154 if(phi2 > maxPhi) break;
155
156 unsigned int n2Idx = B2.m_vPhiNodes[n2PhiIdx].second;
157
158 const std::vector<unsigned int>& v2In = B2.m_in[n2Idx];
159
160 if(v2In.size() >= MAX_SEG_PER_NODE) continue;
161
162 const std::array<float, 5>& n2pars = B2.m_params[n2Idx];
163
164 float r2 = n2pars[3];
165
166 float dr = r2 - r1;
167
168 if(dr < minDeltaRadius) {
169 continue;
170 }
171
172 float z2 = n2pars[4];
173
174 float dz = z2 - z1;
175 float tau = dz/dr;
176 float ftau = std::fabs(tau);
177 if (ftau > 36.0) {
178 continue;
179 }
180
181 if(ftau < n1pars[0]) continue;
182 if(ftau > n1pars[1]) continue;
183
184 if(ftau < n2pars[0]) continue;
185 if(ftau > n2pars[1]) continue;
186
187 if (m_doubletFilterRZ) {
188
189 float z0 = z1 - r1*tau;
190
191 if(z0 < min_z0 || z0 > max_z0) continue;
192
193 float zouter = z0 + maxOuterRadius*tau;
194
195 if(zouter < cut_zMinU || zouter > cut_zMaxU) continue;
196 }
197
198 float curv = (phi2-phi1)/dr;
199 float abs_curv = std::abs(curv);
200
201 if(ftau < 4.0) {//eta = 2.1
202 if(abs_curv > maxKappa_low_eta) {
203 continue;
204 }
205 }
206 else {
207 if(abs_curv > maxKappa_high_eta) {
208 continue;
209 }
210 }
211
212 float exp_eta = std::sqrt(1+tau*tau)-tau;
213
214 if (m_matchBeforeCreate) {//match edge candidate against edges incoming to n2
215
216 bool isGood = v2In.size() <= 2;//we must have enough incoming edges to decide
217
218 if(!isGood) {
219
220 float uat_1 = 1.0f/exp_eta;
221
222 for(const auto& n2_in_idx : v2In) {
223
224 float tau2 = edgeStorage.at(n2_in_idx).m_p[0];
225 float tau_ratio = tau2*uat_1 - 1.0f;
226
227 if(std::fabs(tau_ratio) > cut_tau_ratio_max){//bad match
228 continue;
229 }
230 isGood = true;//good match found
231 break;
232 }
233 }
234
235 if(!isGood) {//no match found, skip creating [n1 <- n2] edge
236 continue;
237 }
238 }
239
240 float dPhi2 = curv*r2;
241 float dPhi1 = curv*r1;
242
243 if(nEdges < m_nMaxEdges) {
244
245 edgeStorage.emplace_back(B1.m_vn[n1Idx], B2.m_vn[n2Idx], exp_eta, curv, phi1 + dPhi1);
246
247 if(v1In.size() < MAX_SEG_PER_NODE) v1In.push_back(nEdges);
248
249 int outEdgeIdx = nEdges;
250
251 float uat_2 = 1/exp_eta;
252 float Phi2 = phi2 + dPhi2;
253 float curv2 = curv;
254
255 for(const auto& inEdgeIdx : v2In) {//looking for neighbours of the new edge
256
257 TrigFTF_GNNR3_Edge* pS = &(edgeStorage.at(inEdgeIdx));
258
259 if(pS->m_nNei >= N_SEG_CONNS) continue;
260
261 float tau_ratio = pS->m_p[0]*uat_2 - 1.0f;
262
263 if(std::abs(tau_ratio) > cut_tau_ratio_max){//bad match
264 continue;
265 }
266
267 float dPhi = Phi2 - pS->m_p[2];
268
269 if(dPhi<-M_PI) dPhi += M_2PI;
270 else if(dPhi>M_PI) dPhi -= M_2PI;
271
272 if(dPhi < -cut_dphi_max || dPhi > cut_dphi_max) {
273 continue;
274 }
275
276 float dcurv = curv2 - pS->m_p[1];
277
278 if(dcurv < -cut_dcurv_max || dcurv > cut_dcurv_max) {
279 continue;
280 }
281
282 pS->m_vNei[pS->m_nNei++] = outEdgeIdx;
283
284 nConnections++;
285
286 }
287 nEdges++;
288 }
289 } //loop over n2 (outer) nodes
290 } //loop over n1 (inner) nodes
291 } //loop over bins in Layer 2
292 } //loop over bin groups
293
294 return std::make_pair(nEdges, nConnections);
295}
296
297int SeedingToolBase::runCCA(int nEdges, std::vector<TrigFTF_GNNR3_Edge>& edgeStorage) const {
298
299 const int maxIter = 15;
300
301 int maxLevel = 0;
302
303 int iter = 0;
304
305 std::vector<TrigFTF_GNNR3_Edge*> v_old;
306
307 for(int edgeIndex=0;edgeIndex<nEdges;edgeIndex++) {
308
309 TrigFTF_GNNR3_Edge* pS = &(edgeStorage[edgeIndex]);
310 if(pS->m_nNei == 0) continue;
311
312 v_old.push_back(pS);//TO-DO: increment level for segments as they already have at least one neighbour
313 }
314
315 for(;iter<maxIter;iter++) {
316
317 //generate proposals
318 std::vector<TrigFTF_GNNR3_Edge*> v_new;
319 v_new.clear();
320 v_new.reserve(v_old.size());
321
322 for(auto pS : v_old) {
323
324 int next_level = pS->m_level;
325
326 for(int nIdx=0;nIdx<pS->m_nNei;nIdx++) {
327
328 unsigned int nextEdgeIdx = pS->m_vNei[nIdx];
329
330 TrigFTF_GNNR3_Edge* pN = &(edgeStorage[nextEdgeIdx]);
331
332 if(pS->m_level == pN->m_level) {
333 next_level = pS->m_level + 1;
334 v_new.push_back(pS);
335 break;
336 }
337 }
338
339 pS->m_next = next_level;//proposal
340 }
341
342 //update
343
344 int nChanges = 0;
345
346 for(auto pS : v_new) {
347 if(pS->m_next != pS->m_level) {
348 nChanges++;
349 pS->m_level = pS->m_next;
350 if(maxLevel < pS->m_level) maxLevel = pS->m_level;
351 }
352 }
353
354 if(nChanges == 0) break;
355
356
357 v_old = std::move(v_new);
358 v_new.clear();
359 }
360
361 return maxLevel;
362}
363
#define M_PI
Scalar deltaPhi(const MatrixBase< Derived > &vec) const
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_DEBUG(x)
This class provides an interface to generate or decode an identifier for the upper levels of the dete...
#define M_2PI
#define MAX_SEG_PER_NODE
#define N_SEG_CONNS
static Double_t sc
This is an Identifier helper class for the Pixel subdetector.
This is an Identifier helper class for the SCT subdetector.
const ServiceHandle< StoreGateSvc > & detStore() const
Describes the API of the Region of Ineterest geometry.
virtual double zedPlus() const =0
the zed and eta values at the most forward and most rear ends of the RoI
virtual double dzdrMinus() const =0
return the gradients
virtual double zedMinus() const =0
virtual double dzdrPlus() const =0
static std::string find_file(const std::string &logical_file_name, const std::string &search_path)
int runCCA(int, std::vector< GNN_Edge > &) const
ToolHandle< ITrigL2LayerNumberTool > m_layerNumberTool
std::vector< TrigInDetSiLayer > m_layerGeometry
std::pair< int, int > buildTheGraph(const IRoiDescriptor &, const std::unique_ptr< GNN_DataStorage > &, std::vector< GNN_Edge > &) const
std::unique_ptr< GNN_FasTrackConnector > m_connector
std::unique_ptr< const TrigFTF_GNN_Geometry > m_geo
unsigned int m_vNei[N_SEG_CONNS]
float getMaxBinRadius() const
std::vector< std::array< float, 5 > > m_params
float getMinBinRadius() const
std::vector< const TrigFTF_GNNR3_Node * > m_vn
std::vector< std::pair< float, unsigned int > > m_vPhiNodes
std::vector< std::vector< unsigned int > > m_in
::StatusCode StatusCode
StatusCode definition for legacy code.
retrieve(aClass, aKey=None)
Definition PyKernel.py:110