Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GNN_TrackingFilter.hpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file GNN_TrackingFilter.hpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2021 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
9 #pragma once
10 
11 // TODO: update to C++17 style
12 #include "Acts/Seeding/GNN_DataStorage.hpp" //includes geo which has trigindetsilayer, may move this to trigbase
13 
14 #include <algorithm>
15 #include <cmath>
16 #include <cstring>
17 #include <iostream>
18 #include <list>
19 #include <vector>
20 
21 template <typename external_spacepoint_t>
23  public:
24  struct Compare {
25  bool operator()(const struct TrigFTF_GNN_EdgeState* s1,
26  const struct TrigFTF_GNN_EdgeState* s2) {
27  return s1->m_J > s2->m_J;
28  }
29  };
30 
31  TrigFTF_GNN_EdgeState() = default;
32 
34 
36  m_initialized = true;
37 
38  m_J = 0.0;
39  m_vs.clear();
40 
41  // n2->n1
42 
43  float dx = pS->m_n1->m_sp_FTF.SP->x() - pS->m_n2->m_sp_FTF.SP->x();
44  float dy = pS->m_n1->m_sp_FTF.SP->y() - pS->m_n2->m_sp_FTF.SP->y();
45  float L = std::sqrt(dx * dx + dy * dy);
46 
47  m_s = dy / L;
48  m_c = dx / L;
49 
50  // transform for extrapolation and update
51  // x' = x*m_c + y*m_s
52  // y' = -x*m_s + y*m_c
53 
54  m_refY = pS->m_n2->m_sp_FTF.SP->r();
55  m_refX =
56  pS->m_n2->m_sp_FTF.SP->x() * m_c + pS->m_n2->m_sp_FTF.SP->y() * m_s;
57 
58  // X-state: y, dy/dx, d2y/dx2
59 
60  m_X[0] =
61  -pS->m_n2->m_sp_FTF.SP->x() * m_s + pS->m_n2->m_sp_FTF.SP->y() * m_c;
62  m_X[1] = 0.0;
63  m_X[2] = 0.0;
64 
65  // Y-state: z, dz/dr
66 
67  m_Y[0] = pS->m_n2->m_sp_FTF.SP->z();
68  m_Y[1] = (pS->m_n1->m_sp_FTF.SP->z() - pS->m_n2->m_sp_FTF.SP->z()) /
69  (pS->m_n1->m_sp_FTF.SP->r() - pS->m_n2->m_sp_FTF.SP->r());
70 
71  memset(&m_Cx[0][0], 0, sizeof(m_Cx));
72  memset(&m_Cy[0][0], 0, sizeof(m_Cy));
73 
74  m_Cx[0][0] = 0.25;
75  m_Cx[1][1] = 0.001;
76  m_Cx[2][2] = 0.001;
77 
78  m_Cy[0][0] = 1.5;
79  m_Cy[1][1] = 0.001;
80  }
81 
82  void clone(const struct TrigFTF_GNN_EdgeState& st) {
83  memcpy(&m_X[0], &st.m_X[0], sizeof(m_X));
84  memcpy(&m_Y[0], &st.m_Y[0], sizeof(m_Y));
85  memcpy(&m_Cx[0][0], &st.m_Cx[0][0], sizeof(m_Cx));
86  memcpy(&m_Cy[0][0], &st.m_Cy[0][0], sizeof(m_Cy));
87  m_refX = st.m_refX;
88  m_refY = st.m_refY;
89  m_c = st.m_c;
90  m_s = st.m_s;
91  m_J = st.m_J;
92  m_vs.clear();
93  m_vs.reserve(st.m_vs.size());
94  std::copy(st.m_vs.begin(), st.m_vs.end(), std::back_inserter(m_vs));
95 
96  m_initialized = true;
97  }
98 
99  float m_J{};
100 
101  std::vector<Acts::TrigFTF_GNN_Edge<external_spacepoint_t>*> m_vs;
102 
103  float m_X[3]{}, m_Y[2]{}, m_Cx[3][3]{}, m_Cy[2][2]{};
104  float m_refX{}, m_refY{}, m_c{}, m_s{};
105 
106  bool m_initialized{false};
107 };
108 
109 #define MAX_EDGE_STATE 2500
110 
111 template <typename external_spacepoint_t>
113  public:
115  const std::vector<Acts::TrigInDetSiLayer>& g,
117  : m_geo(g), m_segStore(sb) {}
118 
121  if (pS->m_level == -1) {
122  return; // already collected
123  }
125 
126  // create track state
127 
130 
131  pInitState->initialize(pS);
132 
133  m_stateVec.clear();
134 
135  // recursive branching and propagation
136 
137  propagate(pS, *pInitState);
138 
139  if (m_stateVec.empty()) {
140  return;
141  }
142  std::sort(m_stateVec.begin(), m_stateVec.end(),
144 
146 
147  output.clone(*best);
148 
150  }
151 
152  protected:
156  return;
157  }
160 
162  new_ts.clone(ts);
163 
164  new_ts.m_vs.push_back(pS);
165 
166  bool accepted = update(pS, new_ts); // update using n1 of the segment
167 
168  if (!accepted) {
169  return; // stop further propagation
170  }
171  int level = pS->m_level;
172 
173  std::list<Acts::TrigFTF_GNN_Edge<external_spacepoint_t>*> lCont;
174 
175  for (int nIdx = 0; nIdx < pS->m_nNei;
176  nIdx++) { // loop over the neighbours of this segment
177  unsigned int nextSegmentIdx = pS->m_vNei[nIdx];
178 
180  &(m_segStore.at(nextSegmentIdx));
181 
182  if (pN->m_level == -1) {
183  continue; // already collected
184  }
185  if (pN->m_level == level - 1) {
186  lCont.push_back(pN);
187  }
188  }
189  if (lCont.empty()) { // the end of chain
190 
191  // store in the vector
193  if (m_stateVec.empty()) { // add the first segment state
196  p->clone(new_ts);
197  m_stateVec.push_back(p);
198  } else { // compare with the best and add
199  float best_so_far = (*m_stateVec.begin())->m_J;
200  if (new_ts.m_J > best_so_far) {
203  p->clone(new_ts);
204  m_stateVec.push_back(p);
205  }
206  }
207  }
208  } else { // branching
209  int nBranches = 0;
210  for (typename std::list<
212  lCont.begin();
213  sIt != lCont.end(); ++sIt, nBranches++) {
214  propagate((*sIt), new_ts); // recursive call
215  }
216  }
217  }
218 
221  const float sigma_t = 0.0003;
222  const float sigma_w = 0.00009;
223 
224  const float sigmaMS = 0.016;
225 
226  const float sigma_x = 0.25; // was 0.22
227  const float sigma_y = 2.5; // was 1.7
228 
229  const float weight_x = 0.5;
230  const float weight_y = 0.5;
231 
232  const float maxDChi2_x = 60.0; // 35.0;
233  const float maxDChi2_y = 60.0; // 31.0;
234 
235  const float add_hit = 14.0;
236 
237  if (ts.m_Cx[2][2] < 0.0 || ts.m_Cx[1][1] < 0.0 || ts.m_Cx[0][0] < 0.0) {
238  std::cout << "Negative cov_x" << std::endl;
239  }
240 
241  if (ts.m_Cy[1][1] < 0.0 || ts.m_Cy[0][0] < 0.0) {
242  std::cout << "Negative cov_y" << std::endl;
243  }
244 
245  // add ms.
246 
247  ts.m_Cx[2][2] += sigma_w * sigma_w;
248  ts.m_Cx[1][1] += sigma_t * sigma_t;
249 
250  int type1 = getLayerType(pS->m_n1->m_sp_FTF.combined_ID);
251 
252  float t2 = type1 == 0 ? 1.0 + ts.m_Y[1] * ts.m_Y[1]
253  : 1.0 + 1.0 / (ts.m_Y[1] * ts.m_Y[1]);
254  float s1 = sigmaMS * t2;
255  float s2 = s1 * s1;
256 
257  s2 *= std::sqrt(t2);
258 
259  ts.m_Cy[1][1] += s2;
260 
261  // extrapolation
262 
263  float X[3], Y[2];
264  float Cx[3][3], Cy[2][2];
265 
266  float refX{}, refY{}, mx{}, my{};
267 
268  float x{}, y{}, z{}, r{};
269 
270  x = pS->m_n1->m_sp_FTF.SP->x();
271  y = pS->m_n1->m_sp_FTF.SP->y();
272  z = pS->m_n1->m_sp_FTF.SP->z();
273  r = pS->m_n1->m_sp_FTF.SP->r();
274 
275  refX = x * ts.m_c + y * ts.m_s;
276  mx = -x * ts.m_s + y * ts.m_c; // measured X[0]
277  refY = r;
278  my = z; // measured Y[0]
279 
280  float A = refX - ts.m_refX;
281  float B = 0.5 * A * A;
282  float dr = refY - ts.m_refY;
283 
284  X[0] = ts.m_X[0] + ts.m_X[1] * A + ts.m_X[2] * B;
285  X[1] = ts.m_X[1] + ts.m_X[2] * A;
286  X[2] = ts.m_X[2];
287 
288  Cx[0][0] = ts.m_Cx[0][0] + 2 * ts.m_Cx[0][1] * A + 2 * ts.m_Cx[0][2] * B +
289  A * A * ts.m_Cx[1][1] + 2 * A * B * ts.m_Cx[1][2] +
290  B * B * ts.m_Cx[2][2];
291  Cx[0][1] = Cx[1][0] = ts.m_Cx[0][1] + ts.m_Cx[1][1] * A +
292  ts.m_Cx[1][2] * B + ts.m_Cx[0][2] * A +
293  A * A * ts.m_Cx[1][2] + A * B * ts.m_Cx[2][2];
294  Cx[0][2] = Cx[2][0] = ts.m_Cx[0][2] + ts.m_Cx[1][2] * A + ts.m_Cx[2][2] * B;
295 
296  Cx[1][1] = ts.m_Cx[1][1] + 2 * A * ts.m_Cx[1][2] + A * A * ts.m_Cx[2][2];
297  Cx[1][2] = Cx[2][1] = ts.m_Cx[1][2] + ts.m_Cx[2][2] * A;
298 
299  Cx[2][2] = ts.m_Cx[2][2];
300 
301  Y[0] = ts.m_Y[0] + ts.m_Y[1] * dr;
302  Y[1] = ts.m_Y[1];
303 
304  Cy[0][0] = ts.m_Cy[0][0] + 2 * ts.m_Cy[0][1] * dr + dr * dr * ts.m_Cy[1][1];
305  Cy[0][1] = Cy[1][0] = ts.m_Cy[0][1] + dr * ts.m_Cy[1][1];
306  Cy[1][1] = ts.m_Cy[1][1];
307 
308  // chi2 test
309 
310  float resid_x = mx - X[0];
311  float resid_y = my - Y[0];
312 
313  float CHx[3] = {Cx[0][0], Cx[0][1], Cx[0][2]};
314  float CHy[2] = {Cy[0][0], Cy[0][1]};
315 
316  float sigma_rz = 0.0;
317 
319 
320  if (type == 0) { // barrel TO-DO: split into barrel Pixel and barrel SCT
321  sigma_rz = sigma_y * sigma_y;
322  } else {
323  sigma_rz = sigma_y * ts.m_Y[1];
324  sigma_rz = sigma_rz * sigma_rz;
325  }
326 
327  float Dx = 1.0 / (Cx[0][0] + sigma_x * sigma_x);
328 
329  float Dy = 1.0 / (Cy[0][0] + sigma_rz);
330 
331  float dchi2_x = resid_x * resid_x * Dx;
332  float dchi2_y = resid_y * resid_y * Dy;
333 
334  if (dchi2_x > maxDChi2_x || dchi2_y > maxDChi2_y) {
335  return false;
336  }
337 
338  ts.m_J += add_hit - dchi2_x * weight_x - dchi2_y * weight_y;
339 
340  // state update
341 
342  float Kx[3] = {Dx * Cx[0][0], Dx * Cx[0][1], Dx * Cx[0][2]};
343  float Ky[2] = {Dy * Cy[0][0], Dy * Cy[0][1]};
344 
345  for (int i = 0; i < 3; i++) {
346  ts.m_X[i] = X[i] + Kx[i] * resid_x;
347  }
348  for (int i = 0; i < 2; i++) {
349  ts.m_Y[i] = Y[i] + Ky[i] * resid_y;
350  }
351 
352  for (int i = 0; i < 3; i++) {
353  for (int j = 0; j < 3; j++) {
354  ts.m_Cx[i][j] = Cx[i][j] - Kx[i] * CHx[j];
355  }
356  }
357 
358  for (int i = 0; i < 2; i++) {
359  for (int j = 0; j < 2; j++) {
360  ts.m_Cy[i][j] = Cy[i][j] - Ky[i] * CHy[j];
361  }
362  }
363  ts.m_refX = refX;
364  ts.m_refY = refY;
365  return true;
366  }
367 
368  int getLayerType(int l) {
369  auto iterator = find_if(m_geo.begin(), m_geo.end(), [l](auto n) {
370  return n.m_subdet == l;
371  }); // iterator to vector member with this id
372  int index = std::distance(m_geo.begin(), iterator);
373 
374  return m_geo.at(index).m_type;
375  }
376 
377  const std::vector<Acts::TrigInDetSiLayer>& m_geo;
378 
379  std::vector<Acts::TrigFTF_GNN_Edge<external_spacepoint_t>>& m_segStore;
380 
381  std::vector<TrigFTF_GNN_EdgeState<external_spacepoint_t>*> m_stateVec;
382 
384 
386 };