Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ZScanVertexFinderTests.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file ZScanVertexFinderTests.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2019 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 
35 
36 #include <algorithm>
37 #include <array>
38 #include <cmath>
39 #include <functional>
40 #include <iostream>
41 #include <memory>
42 #include <random>
43 #include <string>
44 #include <system_error>
45 #include <tuple>
46 #include <type_traits>
47 #include <utility>
48 #include <vector>
49 
50 namespace bdata = boost::unit_test::data;
51 using namespace Acts::UnitLiterals;
52 
53 namespace Acts {
54 namespace Test {
55 
59 
60 // Create a test context
63 
64 // Vertex x/y position distribution
65 std::uniform_real_distribution<> vXYDist(-0.1_mm, 0.1_mm);
66 // Vertex z position distribution
67 std::uniform_real_distribution<> vZDist(-20_mm, 20_mm);
68 // Track d0 distribution
69 std::uniform_real_distribution<> d0Dist(-0.01_mm, 0.01_mm);
70 // Track z0 distribution
71 std::uniform_real_distribution<> z0Dist(-0.2_mm, 0.2_mm);
72 // Track pT distribution
73 std::uniform_real_distribution<> pTDist(0.4_GeV, 10_GeV);
74 // Track phi distribution
75 std::uniform_real_distribution<> phiDist(-M_PI, M_PI);
76 // Track theta distribution
77 std::uniform_real_distribution<> thetaDist(1.0, M_PI - 1.0);
78 // Track charge helper distribution
79 std::uniform_real_distribution<> qDist(-1, 1);
80 // Track IP resolution distribution
81 std::uniform_real_distribution<> resIPDist(0., 100_um);
82 // Track angular distribution
83 std::uniform_real_distribution<> resAngDist(0., 0.1);
84 // Track q/p resolution distribution
85 std::uniform_real_distribution<> resQoPDist(-0.01, 0.01);
86 
90 BOOST_AUTO_TEST_CASE(zscan_finder_test) {
91  unsigned int nTests = 50;
92 
93  for (unsigned int iTest = 0; iTest < nTests; ++iTest) {
94  // Number of tracks
95  unsigned int nTracks = 30;
96 
97  // Set up RNG
98  int mySeed = 31415;
99  std::mt19937 gen(mySeed);
100 
101  // Set up constant B-Field
102  auto bField = std::make_shared<ConstantBField>(Vector3{0.0, 0.0, 1_T});
103 
104  // Set up Eigenstepper
106 
107  // Set up propagator with void navigator
108  auto propagator = std::make_shared<Propagator>(stepper);
109 
110  using BilloirFitter =
112 
113  // Create perigee surface
114  std::shared_ptr<PerigeeSurface> perigeeSurface =
115  Surface::makeShared<PerigeeSurface>(Vector3(0., 0., 0.));
116 
117  // Create position of vertex and perigee surface
118  double x = vXYDist(gen);
119  double y = vXYDist(gen);
120  double z = vZDist(gen);
121 
122  // Calculate d0 and z0 corresponding to vertex position
123  double d0_v = std::hypot(x, y);
124  double z0_v = z;
125 
126  // Start constructing nTracks tracks in the following
127  std::vector<BoundTrackParameters> tracks;
128 
129  // Construct random track emerging from vicinity of vertex position
130  // Vector to store track objects used for vertex fit
131  for (unsigned int iTrack = 0; iTrack < nTracks; iTrack++) {
132  // Construct positive or negative charge randomly
133  double q = qDist(gen) < 0 ? -1. : 1.;
134 
135  // Construct random track parameters
136  BoundVector paramVec = BoundVector::Zero();
137  paramVec[eBoundLoc0] = d0_v + d0Dist(gen);
138  paramVec[eBoundLoc1] = z0_v + z0Dist(gen);
139  paramVec[eBoundPhi] = phiDist(gen);
140  paramVec[eBoundTheta] = thetaDist(gen);
141  paramVec[eBoundQOverP] = q / pTDist(gen);
142 
143  // Resolutions
144  double resD0 = resIPDist(gen);
145  double resZ0 = resIPDist(gen);
146  double resPh = resAngDist(gen);
147  double resTh = resAngDist(gen);
148  double resQp = resQoPDist(gen);
149 
150  // Fill vector of track objects with simple covariance matrix
151  Covariance covMat;
152 
153  covMat << resD0 * resD0, 0., 0., 0., 0., 0., 0., resZ0 * resZ0, 0., 0.,
154  0., 0., 0., 0., resPh * resPh, 0., 0., 0., 0., 0., 0., resTh * resTh,
155  0., 0., 0., 0., 0., 0., resQp * resQp, 0., 0., 0., 0., 0., 0., 1.;
156 
157  tracks.emplace_back(perigeeSurface, paramVec, std::move(covMat),
159  }
160 
161  std::vector<const BoundTrackParameters*> tracksPtr;
162  for (const auto& trk : tracks) {
163  tracksPtr.push_back(&trk);
164  }
165 
166  using VertexFinder = ZScanVertexFinder<BilloirFitter>;
167 
168  static_assert(VertexFinderConcept<VertexFinder>,
169  "Vertex finder does not fulfill vertex finder concept.");
170 
171  // Impact point estimator
173 
174  IPEstimator::Config ipEstimatorCfg(bField, propagator);
175  IPEstimator ipEstimator(ipEstimatorCfg);
176 
177  VertexFinder::Config cfg(ipEstimator);
178 
179  VertexFinder finder(cfg);
180 
183 
184  VertexFinder::State state;
185  auto res = finder.find(tracksPtr, vertexingOptions, state);
186 
187  BOOST_CHECK(res.ok());
188 
189  if (!res.ok()) {
190  std::cout << res.error().message() << std::endl;
191  }
192 
193  if (res.ok()) {
194  BOOST_CHECK(!(*res).empty());
195  Vector3 result = (*res).back().position();
196  CHECK_CLOSE_ABS(result[eZ], z, 1_mm);
197  }
198  }
199 }
200 
201 // Dummy user-defined InputTrack type
202 struct InputTrack {
203  InputTrack(const BoundTrackParameters& params) : m_parameters(params) {}
204 
205  const BoundTrackParameters& parameters() const { return m_parameters; }
206 
207  // store e.g. link to original objects here
208 
209  private:
210  BoundTrackParameters m_parameters;
211 };
212 
216 BOOST_AUTO_TEST_CASE(zscan_finder_usertrack_test) {
217  unsigned int nTests = 50;
218 
219  for (unsigned int iTest = 0; iTest < nTests; ++iTest) {
220  // Number of tracks
221  unsigned int nTracks = 30;
222 
223  // Set up RNG
224  int mySeed = 31415;
225  std::mt19937 gen(mySeed);
226 
227  // Set up constant B-Field
228  auto bField = std::make_shared<ConstantBField>(Vector3{0.0, 0.0, 1_T});
229 
230  // Set up Eigenstepper
232 
233  // Set up propagator with void navigator
234  auto propagator = std::make_shared<Propagator>(stepper);
235 
237 
238  // Create perigee surface
239  std::shared_ptr<PerigeeSurface> perigeeSurface =
240  Surface::makeShared<PerigeeSurface>(Vector3(0., 0., 0.));
241 
242  // Create position of vertex and perigee surface
243  double x = vXYDist(gen);
244  double y = vXYDist(gen);
245  double z = vZDist(gen);
246 
247  // Calculate d0 and z0 corresponding to vertex position
248  double d0_v = std::hypot(x, y);
249  double z0_v = z;
250 
251  // Start constructing nTracks tracks in the following
252  std::vector<InputTrack> tracks;
253 
254  // Construct random track emerging from vicinity of vertex position
255  // Vector to store track objects used for vertex fit
256  for (unsigned int iTrack = 0; iTrack < nTracks; iTrack++) {
257  // Construct positive or negative charge randomly
258  double q = qDist(gen) < 0 ? -1. : 1.;
259 
260  // Construct random track parameters
261  BoundVector paramVec;
262  double z0track = z0_v + z0Dist(gen);
263  paramVec << d0_v + d0Dist(gen), z0track, phiDist(gen), thetaDist(gen),
264  q / pTDist(gen), 0.;
265 
266  // Resolutions
267  double resD0 = resIPDist(gen);
268  double resZ0 = resIPDist(gen);
269  double resPh = resAngDist(gen);
270  double resTh = resAngDist(gen);
271  double resQp = resQoPDist(gen);
272 
273  // Fill vector of track objects with simple covariance matrix
274  Covariance covMat;
275 
276  covMat << resD0 * resD0, 0., 0., 0., 0., 0., 0., resZ0 * resZ0, 0., 0.,
277  0., 0., 0., 0., resPh * resPh, 0., 0., 0., 0., 0., 0., resTh * resTh,
278  0., 0., 0., 0., 0., 0., resQp * resQp, 0., 0., 0., 0., 0., 0., 1.;
279 
280  tracks.emplace_back(BoundTrackParameters(perigeeSurface, paramVec,
281  std::move(covMat),
283  }
284 
285  std::vector<const InputTrack*> tracksPtr;
286  for (const auto& trk : tracks) {
287  tracksPtr.push_back(&trk);
288  }
289 
290  using VertexFinder = ZScanVertexFinder<BilloirFitter>;
291 
292  static_assert(VertexFinderConcept<VertexFinder>,
293  "Vertex finder does not fulfill vertex finder concept.");
294 
295  // Impact point estimator
297 
298  IPEstimator::Config ipEstimatorCfg(bField, propagator);
299  IPEstimator ipEstimator(ipEstimatorCfg);
300 
301  VertexFinder::Config cfg(ipEstimator);
302 
303  // Create a custom std::function to extract BoundTrackParameters from
304  // user-defined InputTrack
305  std::function<BoundTrackParameters(InputTrack)> extractParameters =
306  [](const InputTrack& params) { return params.parameters(); };
307 
308  VertexFinder finder(cfg, extractParameters);
309  VertexFinder::State state;
310 
312 
313  auto res = finder.find(tracksPtr, vertexingOptions, state);
314 
315  BOOST_CHECK(res.ok());
316 
317  if (!res.ok()) {
318  std::cout << res.error().message() << std::endl;
319  }
320 
321  if (res.ok()) {
322  BOOST_CHECK(!(*res).empty());
323  Vector3 result = (*res).back().position();
324  CHECK_CLOSE_ABS(result[eZ], z, 1_mm);
325  }
326  }
327 }
328 
329 } // namespace Test
330 } // namespace Acts