EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GaussianGridTrackDensity.ipp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file GaussianGridTrackDensity.ipp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2020 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/.
9 
10 #include <algorithm>
11 
12 template <int mainGridSize, int trkGridSize>
15  Acts::ActsVectorF<mainGridSize>& mainGrid) const {
16  if (mainGrid == ActsVectorF<mainGridSize>::Zero()) {
17  return VertexingError::EmptyInput;
18  }
19 
20  int zbin = -1;
21  if (!m_cfg.useHighestSumZPosition) {
22  // Get bin with maximum content
23  mainGrid.maxCoeff(&zbin);
24  } else {
25  // Get z position with highest density sum
26  // of surrounding bins
27  zbin = getHighestSumZPosition(mainGrid);
28  }
29 
30  // Derive corresponding z value
31  return (zbin - mainGridSize / 2 + 0.5f) * m_cfg.binSize;
32 }
33 
34 template <int mainGridSize, int trkGridSize>
38  // Get z maximum value
39  auto maxZRes = getMaxZPosition(mainGrid);
40  if (not maxZRes.ok()) {
41  return maxZRes.error();
42  }
43  float maxZ = *maxZRes;
44 
45  // Get seed width estimate
46  auto widthRes = estimateSeedWidth(mainGrid, maxZ);
47  if (not widthRes.ok()) {
48  return widthRes.error();
49  }
50  float width = *widthRes;
51  std::pair<float, float> returnPair{maxZ, width};
52  return returnPair;
53 }
54 
55 template <int mainGridSize, int trkGridSize>
56 std::pair<int, Acts::ActsVectorF<trkGridSize>>
58  const Acts::BoundTrackParameters& trk,
59  Acts::ActsVectorF<mainGridSize>& mainGrid) const {
60  SymMatrix2D cov = trk.covariance()->block<2, 2>(0, 0);
61  float d0 = trk.parameters()[0];
62  float z0 = trk.parameters()[1];
63 
64  // Calculate offset in d direction to central bin at z-axis
65  int dOffset = std::floor(d0 / m_cfg.binSize - 0.5) + 1;
66  // Calculate bin in z
67  int zBin = int(z0 / m_cfg.binSize + mainGridSize / 2.);
68 
69  if (zBin < 0 || zBin >= mainGridSize) {
70  return {-1, ActsVectorF<trkGridSize>::Zero()};
71  }
72  // Calculate the positions of the bin centers
73  float binCtrD = dOffset * m_cfg.binSize;
74  float binCtrZ = (zBin + 0.5f) * m_cfg.binSize - m_cfg.zMinMax;
75 
76  // Calculate the distance between IP values and their
77  // corresponding bin centers
78  float distCtrD = d0 - binCtrD;
79  float distCtrZ = z0 - binCtrZ;
80 
81  // Check if current track does affect grid density
82  // in central bins at z-axis
83  if ((std::abs(dOffset) > trkGridSize - 1) / 2.) {
84  // Current track is too far away to contribute
85  // to track density at z-axis bins
86  return {-1, ActsVectorF<trkGridSize>::Zero()};
87  }
88 
89  // Create the track grid
90  ActsVectorF<trkGridSize> trackGrid =
91  createTrackGrid(dOffset, cov, distCtrD, distCtrZ);
92  // Add the track grid to the main grid
93  addTrackGridToMainGrid(zBin, trackGrid, mainGrid);
94 
95  return {zBin, trackGrid};
96 }
97 
98 template <int mainGridSize, int trkGridSize>
101  const Acts::ActsVectorF<trkGridSize>& trkGrid,
102  Acts::ActsVectorF<mainGridSize>& mainGrid) const {
103  modifyMainGridWithTrackGrid(zBin, trkGrid, mainGrid, +1);
104 }
105 
106 template <int mainGridSize, int trkGridSize>
109  int zBin, const Acts::ActsVectorF<trkGridSize>& trkGrid,
110  Acts::ActsVectorF<mainGridSize>& mainGrid) const {
111  modifyMainGridWithTrackGrid(zBin, trkGrid, mainGrid, -1);
112 }
113 
114 template <int mainGridSize, int trkGridSize>
117  const Acts::ActsVectorF<trkGridSize>& trkGrid,
119  int modifyModeSign) const {
120  int width = (trkGridSize - 1) / 2;
121  // Overlap left
122  int leftOL = zBin - width;
123  // Overlap right
124  int rightOL = zBin + width - mainGridSize + 1;
125  if (leftOL < 0) {
126  int totalTrkSize = trkGridSize + leftOL;
127  mainGrid.segment(0, totalTrkSize) +=
128  modifyModeSign * trkGrid.segment(-leftOL, totalTrkSize);
129  return;
130  }
131  if (rightOL > 0) {
132  int totalTrkSize = trkGridSize - rightOL;
133  mainGrid.segment(mainGridSize - totalTrkSize, totalTrkSize) +=
134  modifyModeSign * trkGrid.segment(0, totalTrkSize);
135  return;
136  }
137 
138  mainGrid.segment(zBin - width, trkGridSize) += modifyModeSign * trkGrid;
139 }
140 
141 template <int mainGridSize, int trkGridSize>
144  int offset, const Acts::SymMatrix2D& cov, float distCtrD,
145  float distCtrZ) const {
147 
148  int i = (trkGridSize - 1) / 2 + offset;
149  float d = (i - static_cast<float>(trkGridSize) / 2 + 0.5f) * m_cfg.binSize;
150 
151  // Loop over columns
152  for (int j = 0; j < trkGridSize; j++) {
153  float z = (j - static_cast<float>(trkGridSize) / 2 + 0.5f) * m_cfg.binSize;
154  trackGrid(j) = normal2D(d + distCtrD, z + distCtrZ, cov);
155  }
156  return trackGrid;
157 }
158 
159 template <int mainGridSize, int trkGridSize>
162  Acts::ActsVectorF<mainGridSize>& mainGrid, float maxZ) const {
163  if (mainGrid == ActsVectorF<mainGridSize>::Zero()) {
164  return VertexingError::EmptyInput;
165  }
166  // Get z bin of max density z value
167  int zBin = int(maxZ / m_cfg.binSize + mainGridSize / 2.);
168 
169  const float maxValue = mainGrid(zBin);
170  float gridValue = mainGrid(zBin);
171 
172  // Find right half-maximum bin
173  int rhmBin = zBin;
174  while (gridValue > maxValue / 2) {
175  rhmBin += 1;
176  gridValue = mainGrid(rhmBin);
177  }
178 
179  // Use linear approximation to find better z value for FWHM between bins
180  float deltaZ1 = (maxValue / 2 - mainGrid(rhmBin - 1)) *
181  (m_cfg.binSize / (mainGrid(rhmBin - 1) - mainGrid(rhmBin)));
182 
183  // Find left half-maximum bin
184  int lhmBin = zBin;
185  gridValue = mainGrid(zBin);
186  while (gridValue > maxValue / 2) {
187  lhmBin -= 1;
188  gridValue = mainGrid(lhmBin);
189  }
190 
191  // Use linear approximation to find better z value for FWHM between bins
192  float deltaZ2 = (maxValue / 2 - mainGrid(lhmBin + 1)) *
193  (m_cfg.binSize / (mainGrid(rhmBin + 1) - mainGrid(rhmBin)));
194 
195  // Approximate FWHM
196  float fwhm =
197  rhmBin * m_cfg.binSize - deltaZ1 - lhmBin * m_cfg.binSize - deltaZ2;
198 
199  // FWHM = 2.355 * sigma
200  float width = fwhm / 2.355f;
201 
202  return std::isnormal(width) ? width : 0.0f;
203 }
204 
205 template <int mainGridSize, int trkGridSize>
207  float d, float z, const Acts::SymMatrix2D& cov) const {
208  float det = cov.determinant();
209  float coef = 1 / (2 * M_PI * std::sqrt(det));
210  float expo =
211  -1 / (2 * det) *
212  (cov(1, 1) * d * d - d * z * (cov(0, 1) + cov(1, 0)) + cov(0, 0) * z * z);
213  return coef * std::exp(expo);
214 }
215 
216 template <int mainGridSize, int trkGridSize>
219  // Checks the first (up to) 3 density maxima, if they are close, checks which
220  // one has the highest surrounding density sum (the two neighboring bins)
221 
222  // The global maximum
223  int zbin = -1;
224  mainGrid.maxCoeff(&zbin);
225  int zFirstMax = zbin;
226  double firstDensity = mainGrid(zFirstMax);
227  double firstSum = getDensitySum(mainGrid, zFirstMax);
228 
229  // Get the second highest maximum
230  mainGrid[zFirstMax] = 0;
231  mainGrid.maxCoeff(&zbin);
232  int zSecondMax = zbin;
233  double secondDensity = mainGrid(zSecondMax);
234  double secondSum = 0;
235  if (firstDensity - secondDensity <
236  firstDensity * m_cfg.maxRelativeDensityDev) {
237  secondSum = getDensitySum(mainGrid, zSecondMax);
238  }
239 
240  // Get the third highest maximum
241  mainGrid[zSecondMax] = 0;
242  mainGrid.maxCoeff(&zbin);
243  int zThirdMax = zbin;
244  double thirdDensity = mainGrid(zThirdMax);
245  double thirdSum = 0;
246  if (firstDensity - thirdDensity <
247  firstDensity * m_cfg.maxRelativeDensityDev) {
248  thirdSum = getDensitySum(mainGrid, zThirdMax);
249  }
250 
251  // Revert back to original values
252  mainGrid[zFirstMax] = firstDensity;
253  mainGrid[zSecondMax] = secondDensity;
254 
255  // Return the z-bin position of the highest density sum
256  if (secondSum > firstSum || secondSum > thirdSum) {
257  return zSecondMax;
258  }
259  if (thirdSum > secondSum || thirdSum > firstSum) {
260  return zThirdMax;
261  }
262  return zFirstMax;
263 }
264 
265 template <int mainGridSize, int trkGridSize>
267  const Acts::ActsVectorF<mainGridSize>& mainGrid, int pos) const {
268  double sum = mainGrid(pos);
269  // Sum up only the density contributions from the
270  // neighboring bins if they are still within bounds
271  if (pos - 1 >= 0) {
272  sum += mainGrid(pos - 1);
273  }
274  if (pos + 1 <= mainGrid.size() - 1) {
275  sum += mainGrid(pos + 1);
276  }
277  return sum;
278 }