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