Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GridDensityVertexFinderTests.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file GridDensityVertexFinderTests.cpp
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/.
8 
9 #include <boost/test/data/test_case.hpp>
10 #include <boost/test/tools/output_test_stream.hpp>
11 #include <boost/test/unit_test.hpp>
12 
34 
35 #include <algorithm>
36 #include <cmath>
37 #include <iostream>
38 #include <memory>
39 #include <random>
40 #include <string>
41 #include <system_error>
42 #include <vector>
43 
44 namespace bdata = boost::unit_test::data;
45 using namespace Acts::UnitLiterals;
47 
48 namespace Acts {
49 namespace Test {
50 
52 
53 // Create a test context
56 
57 const double zVertexPos1 = 12.;
58 const double zVertexPos2 = -3.;
59 // x position
60 std::normal_distribution<double> xdist(1_mm, 0.1_mm);
61 // y position
62 std::normal_distribution<double> ydist(-0.7_mm, 0.1_mm);
63 // z1 position
64 std::normal_distribution<double> z1dist(zVertexPos1 * 1_mm, 1_mm);
65 // z2 position
66 std::normal_distribution<double> z2dist(zVertexPos2 * 1_mm, 0.5_mm);
67 // Track pT distribution
68 std::uniform_real_distribution<double> pTDist(0.1_GeV, 100_GeV);
69 // Track phi distribution
70 std::uniform_real_distribution<double> phiDist(-M_PI, M_PI);
71 // Track eta distribution
72 std::uniform_real_distribution<double> etaDist(-4., 4.);
73 
78 BOOST_AUTO_TEST_CASE(grid_density_vertex_finder_test) {
79  bool debugMode = true;
80 
81  // Note that the AdaptiveGridTrackDensity and the GaussianGridTrackDensity
82  // only furnish exactly the same results for uneven mainGridSize, where the
83  // binnings of the two track densities align. For even mainGridSize the
84  // binning of GaussianGridTrackDensity is:
85  // ..., [-binSize, 0), [0, binSize), ...
86  // and the binning of AdaptiveGridTrackDensity is:
87  // ..., [-0.5*binSize, 0.5*binSize), [0.5*binSize, 1.5*binSize), ...
88  // This is because the AdaptiveGridTrackDensity always has 0 as a bin center.
89  // As a consequence of these different binnings, results would be shifted for
90  // binSize/2 if mainGridSize is even.
91  const int mainGridSize = 3001;
92  const int trkGridSize = 35;
93 
94  Covariance covMat = Covariance::Identity();
95 
96  // Perigee surface for track parameters
97  Vector3 pos0{0, 0, 0};
98  std::shared_ptr<PerigeeSurface> perigeeSurface =
99  Surface::makeShared<PerigeeSurface>(pos0);
100 
103 
105  Finder1::Config cfg1;
106  cfg1.cacheGridStateForTrackRemoval = false;
107  Finder1 finder1(cfg1);
108  Finder1::State state1;
109 
110  using AdaptiveGridDensity = AdaptiveGridTrackDensity<trkGridSize>;
111  // Use custom grid density here with same bin size as Finder1
112  AdaptiveGridDensity::Config adaptiveDensityConfig(2. / 30.01 * 1_mm);
113  AdaptiveGridDensity adaptiveDensity(adaptiveDensityConfig);
114 
116  Finder2::Config cfg2(adaptiveDensity);
117  cfg2.cacheGridStateForTrackRemoval = false;
118  Finder2 finder2(cfg2);
119  Finder2::State state2;
120 
121  int mySeed = 31415;
122  std::mt19937 gen(mySeed);
123  unsigned int nTracks = 200;
124 
125  std::vector<BoundTrackParameters> trackVec;
126  trackVec.reserve(nTracks);
127 
128  // Create nTracks tracks for test case
129  for (unsigned int i = 0; i < nTracks; i++) {
130  // The position of the particle
131  Vector3 pos(xdist(gen), ydist(gen), 0);
132 
133  // Create momentum and charge of track
134  double pt = pTDist(gen);
135  double phi = phiDist(gen);
136  double eta = etaDist(gen);
137  double charge = etaDist(gen) > 0 ? 1 : -1;
138 
139  // project the position on the surface
140  Vector3 direction = makeDirectionFromPhiEta(phi, eta);
141  auto intersection =
142  perigeeSurface->intersect(geoContext, pos, direction).closest();
143  pos = intersection.position();
144 
145  // Produce most of the tracks at near z1 position,
146  // some near z2. Highest track density then expected at z1
147  pos[eZ] = ((i % 4) == 0) ? z2dist(gen) : z1dist(gen);
148 
149  trackVec.push_back(BoundTrackParameters::create(
150  perigeeSurface, geoContext, makeVector4(pos, 0),
151  direction, charge / pt, covMat,
153  .value());
154  }
155 
156  std::vector<const BoundTrackParameters*> trackPtrVec;
157  for (const auto& trk : trackVec) {
158  trackPtrVec.push_back(&trk);
159  }
160 
161  auto res1 = finder1.find(trackPtrVec, vertexingOptions, state1);
162  if (!res1.ok()) {
163  std::cout << res1.error().message() << std::endl;
164  }
165 
166  auto res2 = finder2.find(trackPtrVec, vertexingOptions, state2);
167  if (!res2.ok()) {
168  std::cout << res2.error().message() << std::endl;
169  }
170 
171  double zResult1 = 0;
172  if (res1.ok()) {
173  BOOST_CHECK(!(*res1).empty());
174  Vector3 result1 = (*res1).back().position();
175  if (debugMode) {
176  std::cout << "Vertex position result 1: " << result1 << std::endl;
177  }
178  CHECK_CLOSE_ABS(result1[eZ], zVertexPos1, 1_mm);
179  zResult1 = result1[eZ];
180  }
181 
182  double zResult2 = 0;
183  if (res2.ok()) {
184  BOOST_CHECK(!(*res2).empty());
185  Vector3 result2 = (*res2).back().position();
186  if (debugMode) {
187  std::cout << "Vertex position result 2: " << result2 << std::endl;
188  }
189  CHECK_CLOSE_ABS(result2[eZ], zVertexPos1, 1_mm);
190  zResult2 = result2[eZ];
191  }
192 
193  // Both finders should give same results
194  BOOST_CHECK(zResult1 == zResult2);
195 }
196 
197 BOOST_AUTO_TEST_CASE(grid_density_vertex_finder_track_caching_test) {
198  bool debugMode = true;
199 
200  const int mainGridSize = 3001;
201  const int trkGridSize = 35;
202 
203  Covariance covMat = Covariance::Identity();
204 
205  // Perigee surface for track parameters
206  Vector3 pos0{0, 0, 0};
207  std::shared_ptr<PerigeeSurface> perigeeSurface =
208  Surface::makeShared<PerigeeSurface>(pos0);
209 
212 
215 
216  // Use custom grid density here
217  GridDensity::Config densityConfig(100_mm);
218  densityConfig.useHighestSumZPosition = true;
219  GridDensity density(densityConfig);
220 
221  Finder1::Config cfg(density);
222  cfg.cacheGridStateForTrackRemoval = true;
223  Finder1 finder1(cfg);
224 
225  using AdaptiveGridDensity = AdaptiveGridTrackDensity<trkGridSize>;
226  // Use custom grid density here with same bin size as Finder1
227  AdaptiveGridDensity::Config adaptiveDensityConfig(2. / 30.01 * 1_mm);
228  adaptiveDensityConfig.useHighestSumZPosition = true;
229  AdaptiveGridDensity adaptiveDensity(adaptiveDensityConfig);
230 
232  Finder2::Config cfg2(adaptiveDensity);
233  cfg2.cacheGridStateForTrackRemoval = true;
234  Finder2 finder2(cfg2);
235 
236  int mySeed = 31415;
237  std::mt19937 gen(mySeed);
238  unsigned int nTracks = 200;
239 
240  std::vector<BoundTrackParameters> trackVec;
241  trackVec.reserve(nTracks);
242 
243  // Create nTracks tracks for test case
244  for (unsigned int i = 0; i < nTracks; i++) {
245  // The position of the particle
246  Vector3 pos(xdist(gen), ydist(gen), 0);
247 
248  // Create momentum and charge of track
249  double pt = pTDist(gen);
250  double phi = phiDist(gen);
251  double eta = etaDist(gen);
252  double charge = etaDist(gen) > 0 ? 1 : -1;
253 
254  // project the position on the surface
255  Vector3 direction = makeDirectionFromPhiEta(phi, eta);
256  auto intersection =
257  perigeeSurface->intersect(geoContext, pos, direction).closest();
258  pos = intersection.position();
259 
260  // Produce most of the tracks at near z1 position,
261  // some near z2. Highest track density then expected at z1
262  pos[eZ] = ((i % 4) == 0) ? z2dist(gen) : z1dist(gen);
263 
264  trackVec.push_back(BoundTrackParameters::create(
265  perigeeSurface, geoContext, makeVector4(pos, 0),
266  direction, charge / pt, covMat,
268  .value());
269  }
270 
271  std::vector<const BoundTrackParameters*> trackPtrVec;
272  for (const auto& trk : trackVec) {
273  trackPtrVec.push_back(&trk);
274  }
275 
276  Finder1::State state1;
277  Finder2::State state2;
278 
279  double zResult1 = 0;
280  double zResult2 = 0;
281 
282  auto res1 = finder1.find(trackPtrVec, vertexingOptions, state1);
283  if (!res1.ok()) {
284  std::cout << res1.error().message() << std::endl;
285  }
286  if (res1.ok()) {
287  BOOST_CHECK(!(*res1).empty());
288  Vector3 result = (*res1).back().position();
289  if (debugMode) {
290  std::cout << "Vertex position after first fill 1: " << result
291  << std::endl;
292  }
293  CHECK_CLOSE_ABS(result[eZ], zVertexPos1, 1_mm);
294  zResult1 = result[eZ];
295  }
296 
297  auto res2 = finder2.find(trackPtrVec, vertexingOptions, state2);
298  if (!res2.ok()) {
299  std::cout << res2.error().message() << std::endl;
300  }
301  if (res2.ok()) {
302  BOOST_CHECK(!(*res2).empty());
303  Vector3 result = (*res2).back().position();
304  if (debugMode) {
305  std::cout << "Vertex position after first fill 2: " << result
306  << std::endl;
307  }
308  CHECK_CLOSE_ABS(result[eZ], zVertexPos1, 1_mm);
309  zResult2 = result[eZ];
310  }
311 
312  BOOST_CHECK(zResult1 == zResult2);
313 
314  int trkCount = 0;
315  std::vector<const BoundTrackParameters*> removedTracks;
316  for (const auto& trk : trackVec) {
317  if ((trkCount % 4) != 0) {
318  removedTracks.push_back(&trk);
319  }
320  trkCount++;
321  }
322 
323  state1.tracksToRemove = removedTracks;
324  state2.tracksToRemove = removedTracks;
325 
326  auto res3 = finder1.find(trackPtrVec, vertexingOptions, state1);
327  if (!res3.ok()) {
328  std::cout << res3.error().message() << std::endl;
329  }
330  if (res3.ok()) {
331  BOOST_CHECK(!(*res3).empty());
332  Vector3 result = (*res3).back().position();
333  if (debugMode) {
334  std::cout
335  << "Vertex position after removing tracks near first density peak 1: "
336  << result << std::endl;
337  }
338  CHECK_CLOSE_ABS(result[eZ], zVertexPos2, 1_mm);
339  zResult1 = result[eZ];
340  }
341 
342  auto res4 = finder2.find(trackPtrVec, vertexingOptions, state2);
343  if (!res4.ok()) {
344  std::cout << res4.error().message() << std::endl;
345  }
346  if (res4.ok()) {
347  BOOST_CHECK(!(*res4).empty());
348  Vector3 result = (*res4).back().position();
349  if (debugMode) {
350  std::cout
351  << "Vertex position after removing tracks near first density peak 2: "
352  << result << std::endl;
353  }
354  CHECK_CLOSE_ABS(result[eZ], zVertexPos2, 1_mm);
355  zResult2 = result[eZ];
356  }
357 
358  BOOST_CHECK(zResult1 == zResult2);
359 }
360 
364 BOOST_AUTO_TEST_CASE(grid_density_vertex_finder_seed_width_test) {
365  bool debugMode = true;
366 
367  const int mainGridSize = 3001;
368  const int trkGridSize = 35;
369 
370  Covariance covMat = Covariance::Identity();
371 
372  // Perigee surface for track parameters
373  Vector3 pos0{0, 0, 0};
374  std::shared_ptr<PerigeeSurface> perigeeSurface =
375  Surface::makeShared<PerigeeSurface>(pos0);
376 
379  Vertex<BoundTrackParameters> constraintVtx;
380  constraintVtx.setCovariance(SquareMatrix3::Identity());
381  vertexingOptions.constraint = constraintVtx;
382 
384  Finder1::Config cfg1;
385  cfg1.cacheGridStateForTrackRemoval = false;
386  cfg1.estimateSeedWidth = true;
387  Finder1 finder1(cfg1);
388  Finder1::State state1;
389 
390  using AdaptiveGridDensity = AdaptiveGridTrackDensity<trkGridSize>;
391  // Use custom grid density here with same bin size as Finder1
392  AdaptiveGridDensity::Config adaptiveDensityConfig(2. / 30.01 * 1_mm);
393  AdaptiveGridDensity adaptiveDensity(adaptiveDensityConfig);
394 
396  Finder2::Config cfg2(adaptiveDensity);
397  cfg2.cacheGridStateForTrackRemoval = false;
398  cfg2.estimateSeedWidth = true;
399  Finder2 finder2(cfg2);
400  Finder2::State state2;
401 
402  int mySeed = 31415;
403  std::mt19937 gen(mySeed);
404  unsigned int nTracks = 20;
405 
406  std::vector<BoundTrackParameters> trackVec;
407  trackVec.reserve(nTracks);
408 
409  // Create nTracks tracks for test case
410  for (unsigned int i = 0; i < nTracks; i++) {
411  // The position of the particle
412  Vector3 pos(xdist(gen), ydist(gen), 0);
413 
414  // Create momentum and charge of track
415  double pt = pTDist(gen);
416  double phi = phiDist(gen);
417  double eta = etaDist(gen);
418  double charge = etaDist(gen) > 0 ? 1 : -1;
419 
420  // project the position on the surface
421  Vector3 direction = makeDirectionFromPhiEta(phi, eta);
422  auto intersection =
423  perigeeSurface->intersect(geoContext, pos, direction).closest();
424  pos = intersection.position();
425 
426  pos[eZ] = z1dist(gen);
427 
428  trackVec.push_back(BoundTrackParameters::create(
429  perigeeSurface, geoContext, makeVector4(pos, 0),
430  direction, charge / pt, covMat,
432  .value());
433  }
434 
435  std::vector<const BoundTrackParameters*> trackPtrVec;
436  for (const auto& trk : trackVec) {
437  trackPtrVec.push_back(&trk);
438  }
439 
440  // Test finder 1
441  auto res1 = finder1.find(trackPtrVec, vertexingOptions, state1);
442  if (!res1.ok()) {
443  std::cout << res1.error().message() << std::endl;
444  }
445 
446  double covZZ1 = 0;
447  if (res1.ok()) {
448  BOOST_CHECK(!(*res1).empty());
449  SquareMatrix3 cov = (*res1).back().covariance();
450  BOOST_CHECK(constraintVtx.covariance() != cov);
451  BOOST_CHECK(cov(eZ, eZ) != 0.);
452  covZZ1 = cov(eZ, eZ);
453  if (debugMode) {
454  std::cout << "Estimated z-seed width 1: " << cov(eZ, eZ) << std::endl;
455  }
456  }
457 
458  // Test finder 2
459  auto res2 = finder2.find(trackPtrVec, vertexingOptions, state2);
460  if (!res2.ok()) {
461  std::cout << res2.error().message() << std::endl;
462  }
463 
464  double covZZ2 = 0;
465  if (res2.ok()) {
466  BOOST_CHECK(!(*res2).empty());
467  SquareMatrix3 cov = (*res2).back().covariance();
468  BOOST_CHECK(constraintVtx.covariance() != cov);
469  BOOST_CHECK(cov(eZ, eZ) != 0.);
470  covZZ2 = cov(eZ, eZ);
471  if (debugMode) {
472  std::cout << "Estimated z-seed width 2: " << cov(eZ, eZ) << std::endl;
473  }
474  }
475 
476  // Test for same seed width
477  CHECK_CLOSE_ABS(covZZ1, covZZ2, 1e-4);
478 }
479 
480 } // namespace Test
481 } // namespace Acts