Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
AdaptiveMultiVertexFinderTests.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file AdaptiveMultiVertexFinderTests.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2019-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 
40 
41 #include <algorithm>
42 #include <array>
43 #include <chrono>
44 #include <cmath>
45 #include <functional>
46 #include <iostream>
47 #include <map>
48 #include <memory>
49 #include <string>
50 #include <system_error>
51 #include <tuple>
52 #include <utility>
53 #include <vector>
54 
55 #include "VertexingDataHelper.hpp"
56 
57 namespace Acts {
58 namespace Test {
59 
60 using namespace Acts::UnitLiterals;
61 
65 
66 // Create a test context
69 
70 const std::string toolString = "AMVF";
71 
73 BOOST_AUTO_TEST_CASE(adaptive_multi_vertex_finder_test) {
74  // Set debug mode
75  bool debugMode = false;
76  // Set up constant B-Field
77  auto bField = std::make_shared<ConstantBField>(Vector3(0., 0., 2_T));
78 
79  // Set up EigenStepper
80  // EigenStepper<> stepper(bField);
82 
83  // Set up propagator with void navigator
84  auto propagator = std::make_shared<Propagator>(stepper);
85 
86  // IP 3D Estimator
88 
89  IPEstimator::Config ipEstimatorCfg(bField, propagator);
90  IPEstimator ipEstimator(ipEstimatorCfg);
91 
92  std::vector<double> temperatures{8.0, 4.0, 2.0, 1.4142136, 1.2247449, 1.0};
93  AnnealingUtility::Config annealingConfig;
94  annealingConfig.setOfTemperatures = temperatures;
95  AnnealingUtility annealingUtility(annealingConfig);
96 
98 
99  Fitter::Config fitterCfg(ipEstimator);
100 
101  fitterCfg.annealingTool = annealingUtility;
102 
103  // Linearizer for BoundTrackParameters type test
104  Linearizer::Config ltConfig(bField, propagator);
105  Linearizer linearizer(ltConfig);
106 
107  // Test smoothing
108  fitterCfg.doSmoothing = true;
109 
110  Fitter fitter(fitterCfg);
111 
112  using SeedFinder =
115 
116  SeedFinder seedFinder;
117 
119 
120  Finder::Config finderConfig(std::move(fitter), seedFinder, ipEstimator,
121  std::move(linearizer), bField);
122 
123  Finder finder(finderConfig);
124  Finder::State state;
125 
126  auto csvData = readTracksAndVertexCSV(toolString);
127  auto tracks = std::get<TracksData>(csvData);
128 
129  if (debugMode) {
130  std::cout << "Number of tracks in event: " << tracks.size() << std::endl;
131  int maxCout = 10;
132  int count = 0;
133  for (const auto& trk : tracks) {
134  std::cout << count << ". track: " << std::endl;
135  std::cout << "params: " << trk << std::endl;
136  count++;
137  if (count == maxCout) {
138  break;
139  }
140  }
141  }
142 
143  std::vector<const BoundTrackParameters*> tracksPtr;
144  for (const auto& trk : tracks) {
145  tracksPtr.push_back(&trk);
146  }
147 
148  // TODO: test without using beam spot constraint
149  Vertex<BoundTrackParameters> bsConstr = std::get<BeamSpotData>(csvData);
151  geoContext, magFieldContext, bsConstr);
152 
153  auto t1 = std::chrono::system_clock::now();
154  auto findResult = finder.find(tracksPtr, vertexingOptions, state);
155  auto t2 = std::chrono::system_clock::now();
156 
157  auto timediff =
158  std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count();
159 
160  if (!findResult.ok()) {
161  std::cout << findResult.error().message() << std::endl;
162  }
163 
164  BOOST_CHECK(findResult.ok());
165 
166  std::vector<Vertex<BoundTrackParameters>> allVertices = *findResult;
167 
168  if (debugMode) {
169  std::cout << "Time needed: " << timediff << " ms." << std::endl;
170  std::cout << "Number of vertices reconstructed: " << allVertices.size()
171  << std::endl;
172 
173  int count = 0;
174  for (const auto& vtx : allVertices) {
175  count++;
176  std::cout << count << ". Vertex at position: " << vtx.position()[0]
177  << ", " << vtx.position()[1] << ", " << vtx.position()[2]
178  << std::endl;
179  std::cout << count << ". Vertex with cov: " << vtx.covariance()
180  << std::endl;
181  std::cout << "\t with n tracks: " << vtx.tracks().size() << std::endl;
182  }
183  }
184 
185  // Test expected outcomes from athena implementation
186  // Number of reconstructed vertices
187  auto verticesInfo = std::get<VerticesData>(csvData);
188  const int expNRecoVertices = verticesInfo.size();
189 
190  BOOST_CHECK_EQUAL(allVertices.size(), expNRecoVertices);
191 
192  for (int i = 0; i < expNRecoVertices; i++) {
193  auto recoVtx = allVertices[i];
194  auto expVtx = verticesInfo[i];
195  CHECK_CLOSE_ABS(recoVtx.position(), expVtx.position, 0.001_mm);
196  CHECK_CLOSE_ABS(recoVtx.covariance(), expVtx.covariance, 0.001_mm);
197  BOOST_CHECK_EQUAL(recoVtx.tracks().size(), expVtx.nTracks);
198  CHECK_CLOSE_ABS(recoVtx.tracks()[0].trackWeight, expVtx.trk1Weight, 0.003);
199  CHECK_CLOSE_ABS(recoVtx.tracks()[0].vertexCompatibility, expVtx.trk1Comp,
200  0.003);
201  }
202 }
203 
204 // Dummy user-defined InputTrack type
205 struct InputTrack {
206  InputTrack(const BoundTrackParameters& params, int id)
207  : m_parameters(params), m_id(id) {}
208 
209  const BoundTrackParameters& parameters() const { return m_parameters; }
210  // store e.g. link to original objects here
211 
212  int id() const { return m_id; }
213 
214  private:
216 
217  // Some test track ID
218  int m_id;
219 };
220 
222 BOOST_AUTO_TEST_CASE(adaptive_multi_vertex_finder_usertype_test) {
223  // Set debug mode
224  bool debugMode = false;
225  // Set up constant B-Field
226  auto bField = std::make_shared<ConstantBField>(Vector3(0., 0., 2_T));
227 
228  // Set up EigenStepper
229  // EigenStepper<> stepper(bField);
231 
232  // Set up propagator with void navigator
233  auto propagator = std::make_shared<Propagator>(stepper);
234 
235  // Create a custom std::function to extract BoundTrackParameters from
236  // user-defined InputTrack
237  std::function<BoundTrackParameters(InputTrack)> extractParameters =
238  [](const InputTrack& params) { return params.parameters(); };
239 
240  // IP 3D Estimator
242 
243  IPEstimator::Config ipEstimatorCfg(bField, propagator);
244  IPEstimator ipEstimator(ipEstimatorCfg);
245 
246  std::vector<double> temperatures{8.0, 4.0, 2.0, 1.4142136, 1.2247449, 1.0};
247  AnnealingUtility::Config annealingConfig;
248  annealingConfig.setOfTemperatures = temperatures;
249  AnnealingUtility annealingUtility(annealingConfig);
250 
252 
253  Fitter::Config fitterCfg(ipEstimator);
254 
255  fitterCfg.annealingTool = annealingUtility;
256 
257  // Linearizer
258  Linearizer::Config ltConfig(bField, propagator);
259  Linearizer linearizer(ltConfig);
260 
261  // Test smoothing
262  fitterCfg.doSmoothing = true;
263 
264  Fitter fitter(fitterCfg, extractParameters);
265 
266  using SeedFinder =
268 
269  SeedFinder seedFinder(extractParameters);
270 
272 
273  Finder::Config finderConfig(std::move(fitter), seedFinder, ipEstimator,
274  std::move(linearizer), bField);
275  Finder::State state;
276 
277  Finder finder(finderConfig, extractParameters);
278 
279  auto csvData = readTracksAndVertexCSV(toolString);
280  auto tracks = std::get<TracksData>(csvData);
281 
282  std::vector<InputTrack> userTracks;
283  int idCount = 0;
284  for (const auto& trk : tracks) {
285  userTracks.push_back(InputTrack(trk, idCount));
286  idCount++;
287  }
288 
289  if (debugMode) {
290  std::cout << "Number of tracks in event: " << tracks.size() << std::endl;
291  int maxCout = 10;
292  int count = 0;
293  for (const auto& trk : tracks) {
294  std::cout << count << ". track: " << std::endl;
295  std::cout << "params: " << trk << std::endl;
296  count++;
297  if (count == maxCout) {
298  break;
299  }
300  }
301  }
302 
303  std::vector<const InputTrack*> userTracksPtr;
304  for (const auto& trk : userTracks) {
305  userTracksPtr.push_back(&trk);
306  }
307 
308  Vertex<InputTrack> constraintVtx;
309  constraintVtx.setPosition(std::get<BeamSpotData>(csvData).position());
310  constraintVtx.setCovariance(std::get<BeamSpotData>(csvData).covariance());
311 
313  constraintVtx);
314 
315  auto findResult = finder.find(userTracksPtr, vertexingOptions, state);
316 
317  if (!findResult.ok()) {
318  std::cout << findResult.error().message() << std::endl;
319  }
320 
321  BOOST_CHECK(findResult.ok());
322 
323  std::vector<Vertex<InputTrack>> allVertices = *findResult;
324 
325  if (debugMode) {
326  std::cout << "Number of vertices reconstructed: " << allVertices.size()
327  << std::endl;
328 
329  int count = 0;
330  for (const auto& vtx : allVertices) {
331  count++;
332  std::cout << count << ". Vertex at position: " << vtx.position()[0]
333  << ", " << vtx.position()[1] << ", " << vtx.position()[2]
334  << std::endl;
335  std::cout << count << ". Vertex with cov: " << vtx.covariance()
336  << std::endl;
337  std::cout << "\t with n tracks: " << vtx.tracks().size() << std::endl;
338  }
339  for (auto& trk : allVertices[0].tracks()) {
340  std::cout << "Track ID at first vertex: " << trk.originalParams->id()
341  << std::endl;
342  }
343  }
344 
345  auto verticesInfo = std::get<VerticesData>(csvData);
346  const int expNRecoVertices = verticesInfo.size();
347 
348  BOOST_CHECK_EQUAL(allVertices.size(), expNRecoVertices);
349 
350  for (int i = 0; i < expNRecoVertices; i++) {
351  auto recoVtx = allVertices[i];
352  auto expVtx = verticesInfo[i];
353  CHECK_CLOSE_ABS(recoVtx.position(), expVtx.position, 0.001_mm);
354  CHECK_CLOSE_ABS(recoVtx.covariance(), expVtx.covariance, 0.001_mm);
355  BOOST_CHECK_EQUAL(recoVtx.tracks().size(), expVtx.nTracks);
356  CHECK_CLOSE_ABS(recoVtx.tracks()[0].trackWeight, expVtx.trk1Weight, 0.003);
357  CHECK_CLOSE_ABS(recoVtx.tracks()[0].vertexCompatibility, expVtx.trk1Comp,
358  0.003);
359  }
360 }
361 
363 BOOST_AUTO_TEST_CASE(adaptive_multi_vertex_finder_grid_seed_finder_test) {
364  // Set debug mode
365  bool debugMode = false;
366  if (debugMode) {
367  std::cout << "Starting AMVF test with grid seed finder..." << std::endl;
368  }
369  // Set up constant B-Field
370  auto bField = std::make_shared<ConstantBField>(Vector3(0., 0., 2_T));
371 
372  // Set up EigenStepper
373  // EigenStepper<> stepper(bField);
375 
376  // Set up propagator with void navigator
377  auto propagator = std::make_shared<Propagator>(stepper);
378 
379  // IP Estimator
381 
382  IPEstimator::Config ipEstCfg(bField, propagator);
383  IPEstimator ipEst(ipEstCfg);
384 
385  std::vector<double> temperatures{8.0, 4.0, 2.0, 1.4142136, 1.2247449, 1.0};
386  AnnealingUtility::Config annealingConfig;
387  annealingConfig.setOfTemperatures = temperatures;
388  AnnealingUtility annealingUtility(annealingConfig);
389 
391 
392  Fitter::Config fitterCfg(ipEst);
393 
394  fitterCfg.annealingTool = annealingUtility;
395 
396  // Linearizer for BoundTrackParameters type test
397  Linearizer::Config ltConfig(bField, propagator);
398  Linearizer linearizer(ltConfig);
399 
400  // Test smoothing
401  fitterCfg.doSmoothing = true;
402 
403  Fitter fitter(fitterCfg);
404 
406  SeedFinder::Config seedFinderCfg(250);
407  seedFinderCfg.cacheGridStateForTrackRemoval = true;
408 
409  SeedFinder seedFinder(seedFinderCfg);
410 
412 
413  Finder::Config finderConfig(std::move(fitter), seedFinder, ipEst,
414  std::move(linearizer), bField);
415 
416  Finder finder(finderConfig);
417  Finder::State state;
418 
419  auto csvData = readTracksAndVertexCSV(toolString);
420  auto tracks = std::get<TracksData>(csvData);
421 
422  if (debugMode) {
423  std::cout << "Number of tracks in event: " << tracks.size() << std::endl;
424  int maxCout = 10;
425  int count = 0;
426  for (const auto& trk : tracks) {
427  std::cout << count << ". track: " << std::endl;
428  std::cout << "params: " << trk << std::endl;
429  count++;
430  if (count == maxCout) {
431  break;
432  }
433  }
434  }
435 
436  std::vector<const BoundTrackParameters*> tracksPtr;
437  for (const auto& trk : tracks) {
438  tracksPtr.push_back(&trk);
439  }
440 
441  // TODO: test using beam spot constraint
442  Vertex<BoundTrackParameters> bsConstr = std::get<BeamSpotData>(csvData);
444  geoContext, magFieldContext, bsConstr);
445 
446  auto t1 = std::chrono::system_clock::now();
447  auto findResult = finder.find(tracksPtr, vertexingOptions, state);
448  auto t2 = std::chrono::system_clock::now();
449 
450  auto timediff =
451  std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count();
452 
453  if (!findResult.ok()) {
454  std::cout << findResult.error().message() << std::endl;
455  }
456 
457  BOOST_CHECK(findResult.ok());
458 
459  std::vector<Vertex<BoundTrackParameters>> allVertices = *findResult;
460 
461  if (debugMode) {
462  std::cout << "Time needed: " << timediff << " ms." << std::endl;
463  std::cout << "Number of vertices reconstructed: " << allVertices.size()
464  << std::endl;
465 
466  int count = 0;
467  for (const auto& vtx : allVertices) {
468  count++;
469  std::cout << count << ". Vertex at position: " << vtx.position()[0]
470  << ", " << vtx.position()[1] << ", " << vtx.position()[2]
471  << std::endl;
472  std::cout << count << ". Vertex with cov: " << vtx.covariance()
473  << std::endl;
474  std::cout << "\t with n tracks: " << vtx.tracks().size() << std::endl;
475  }
476  }
477  // Test expected outcomes from athena implementation
478  // Number of reconstructed vertices
479  auto verticesInfo = std::get<VerticesData>(csvData);
480  const int expNRecoVertices = verticesInfo.size();
481 
482  BOOST_CHECK_EQUAL(allVertices.size(), expNRecoVertices);
483  std::vector<bool> vtxFound(expNRecoVertices, false);
484 
485  for (const auto& vtx : allVertices) {
486  double vtxZ = vtx.position()[2];
487  double diffZ = 1e5;
488  int foundVtxIdx = -1;
489  for (int i = 0; i < expNRecoVertices; i++) {
490  if (not vtxFound[i]) {
491  if (std::abs(vtxZ - verticesInfo[i].position[2]) < diffZ) {
492  diffZ = std::abs(vtxZ - verticesInfo[i].position[2]);
493  foundVtxIdx = i;
494  }
495  }
496  }
497  if (diffZ < 0.5_mm) {
498  vtxFound[foundVtxIdx] = true;
499  CHECK_CLOSE_ABS(vtx.tracks().size(), verticesInfo[foundVtxIdx].nTracks,
500  1);
501  }
502  }
503  for (bool found : vtxFound) {
504  BOOST_CHECK_EQUAL(found, true);
505  }
506 }
507 
510  adaptive_multi_vertex_finder_adaptive_grid_seed_finder_test) {
511  // Set debug mode
512  bool debugMode = false;
513  if (debugMode) {
514  std::cout << "Starting AMVF test with adaptive grid seed finder..."
515  << std::endl;
516  }
517  // Set up constant B-Field
518  auto bField = std::make_shared<ConstantBField>(Vector3(0., 0., 2_T));
519 
520  // Set up EigenStepper
521  // EigenStepper<> stepper(bField);
523 
524  // Set up propagator with void navigator
525  auto propagator = std::make_shared<Propagator>(stepper);
526 
527  // IP Estimator
529 
530  IPEstimator::Config ipEstCfg(bField, propagator);
531  IPEstimator ipEst(ipEstCfg);
532 
533  std::vector<double> temperatures{8.0, 4.0, 2.0, 1.4142136, 1.2247449, 1.0};
534  AnnealingUtility::Config annealingConfig;
535  annealingConfig.setOfTemperatures = temperatures;
536  AnnealingUtility annealingUtility(annealingConfig);
537 
539 
540  Fitter::Config fitterCfg(ipEst);
541 
542  fitterCfg.annealingTool = annealingUtility;
543 
544  // Linearizer for BoundTrackParameters type test
545  Linearizer::Config ltConfig(bField, propagator);
546  Linearizer linearizer(ltConfig);
547 
548  // Test smoothing
549  fitterCfg.doSmoothing = true;
550 
551  Fitter fitter(fitterCfg);
552 
554  SeedFinder::Config seedFinderCfg(0.05);
555  seedFinderCfg.cacheGridStateForTrackRemoval = true;
556 
557  SeedFinder seedFinder(seedFinderCfg);
558 
560 
561  Finder::Config finderConfig(std::move(fitter), seedFinder, ipEst,
562  std::move(linearizer), bField);
563 
564  Finder finder(finderConfig);
565  Finder::State state;
566 
567  auto csvData = readTracksAndVertexCSV(toolString);
568  auto tracks = std::get<TracksData>(csvData);
569 
570  if (debugMode) {
571  std::cout << "Number of tracks in event: " << tracks.size() << std::endl;
572  int maxCout = 10;
573  int count = 0;
574  for (const auto& trk : tracks) {
575  std::cout << count << ". track: " << std::endl;
576  std::cout << "params: " << trk << std::endl;
577  count++;
578  if (count == maxCout) {
579  break;
580  }
581  }
582  }
583 
584  std::vector<const BoundTrackParameters*> tracksPtr;
585  for (const auto& trk : tracks) {
586  tracksPtr.push_back(&trk);
587  }
588 
589  Vertex<BoundTrackParameters> bsConstr = std::get<BeamSpotData>(csvData);
591  geoContext, magFieldContext, bsConstr);
592 
593  auto t1 = std::chrono::system_clock::now();
594  auto findResult = finder.find(tracksPtr, vertexingOptions, state);
595  auto t2 = std::chrono::system_clock::now();
596 
597  auto timediff =
598  std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count();
599 
600  if (!findResult.ok()) {
601  std::cout << findResult.error().message() << std::endl;
602  }
603 
604  BOOST_CHECK(findResult.ok());
605 
606  std::vector<Vertex<BoundTrackParameters>> allVertices = *findResult;
607 
608  if (debugMode) {
609  std::cout << "Time needed: " << timediff << " ms." << std::endl;
610  std::cout << "Number of vertices reconstructed: " << allVertices.size()
611  << std::endl;
612 
613  int count = 0;
614  for (const auto& vtx : allVertices) {
615  count++;
616  std::cout << count << ". Vertex at position: " << vtx.position()[0]
617  << ", " << vtx.position()[1] << ", " << vtx.position()[2]
618  << std::endl;
619  std::cout << count << ". Vertex with cov: " << vtx.covariance()
620  << std::endl;
621  std::cout << "\t with n tracks: " << vtx.tracks().size() << std::endl;
622  }
623  }
624  // Test expected outcomes from athena implementation
625  // Number of reconstructed vertices
626  auto verticesInfo = std::get<VerticesData>(csvData);
627  const int expNRecoVertices = verticesInfo.size();
628 
629  BOOST_CHECK_EQUAL(allVertices.size(), expNRecoVertices);
630  std::vector<bool> vtxFound(expNRecoVertices, false);
631 
632  for (const auto& vtx : allVertices) {
633  double vtxZ = vtx.position()[2];
634  double diffZ = 1e5;
635  int foundVtxIdx = -1;
636  for (int i = 0; i < expNRecoVertices; i++) {
637  if (not vtxFound[i]) {
638  if (std::abs(vtxZ - verticesInfo[i].position[2]) < diffZ) {
639  diffZ = std::abs(vtxZ - verticesInfo[i].position[2]);
640  foundVtxIdx = i;
641  }
642  }
643  }
644  if (diffZ < 0.5_mm) {
645  vtxFound[foundVtxIdx] = true;
646  CHECK_CLOSE_ABS(vtx.tracks().size(), verticesInfo[foundVtxIdx].nTracks,
647  2);
648  }
649  }
650  for (bool found : vtxFound) {
651  BOOST_CHECK_EQUAL(found, true);
652  }
653 }
654 
655 } // namespace Test
656 } // namespace Acts