Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TrackSelectorTests.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file TrackSelectorTests.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2023 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/unit_test.hpp>
11 
13 
14 #include <limits>
15 
16 using namespace Acts;
17 namespace bdata = boost::unit_test::data;
18 
19 struct MockTrack {
20  double m_theta;
21  double m_phi;
22  double m_pt;
23  double m_loc0;
24  double m_loc1;
25  double m_time;
27 
28  double theta() const { return m_theta; }
29  double phi() const { return m_phi; }
30  double transverseMomentum() const { return m_pt; }
31  double loc0() const { return m_loc0; }
32  double loc1() const { return m_loc1; }
33  double time() const { return m_time; }
34  double nMeasurements() const { return m_nMeasurements; }
35 };
36 
37 double thetaFromEta(double eta) {
38  return 2 * std::atan(std::exp(-eta));
39 }
40 
41 BOOST_AUTO_TEST_SUITE(TrackSelectorTests)
42 
43 std::vector<double> etaValues{-5.0, -4.5, -4.0, -3.5, -3.0, -2.5, -2.0, -1.5,
44  -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, 2.5,
45  3.0, 3.5, 4.0, 4.5, 5.0, 1.0};
46 
47 BOOST_DATA_TEST_CASE(TestSingleBinCase, bdata::make(etaValues), eta) {
49 
50  MockTrack baseTrack{};
51  baseTrack.m_theta = thetaFromEta(eta);
52  baseTrack.m_phi = 0.5;
53  baseTrack.m_pt = 0.5;
54  baseTrack.m_loc0 = 0.5;
55  baseTrack.m_loc1 = 0.5;
56  baseTrack.m_time = 0.5;
57  baseTrack.m_nMeasurements = 0.5;
58 
59  {
60  TrackSelector selector{cfgBase};
61  // should select anything
62  BOOST_CHECK(selector.isValidTrack(baseTrack));
63  }
64 
65  auto check = [&](const auto& var, const auto& minPtr, const auto& maxPtr,
66  const auto& propPtr) {
67  BOOST_TEST_INFO_SCOPE("Testing " << var);
68  MockTrack track = baseTrack;
69 
70  auto cfgMinOnly = cfgBase;
71  auto cfgMaxOnly = cfgBase;
72  auto cfgMinMax = cfgBase;
73 
74  cfgMinOnly.cutSets.at(0).*minPtr = -1;
75  cfgMinMax.cutSets.at(0).*minPtr = -1;
76  cfgMaxOnly.cutSets.at(0).*maxPtr = 1;
77  cfgMinMax.cutSets.at(0).*maxPtr = 1;
78 
79  TrackSelector minOnly{cfgMinOnly};
80  TrackSelector maxOnly{cfgMaxOnly};
81  TrackSelector minMax{cfgMinMax};
82 
83  BOOST_CHECK(minOnly.isValidTrack(track));
84  BOOST_CHECK(maxOnly.isValidTrack(track));
85  BOOST_CHECK(minMax.isValidTrack(track));
86 
87  // push track outside of minimum
88  track.*propPtr = -1.1;
89 
90  BOOST_CHECK(!minOnly.isValidTrack(track));
91  BOOST_CHECK(maxOnly.isValidTrack(track));
92  BOOST_CHECK(!minMax.isValidTrack(track));
93 
94  // push track outside of maximum
95  track.*propPtr = 1.1;
96 
97  BOOST_CHECK(minOnly.isValidTrack(track));
98  BOOST_CHECK(!maxOnly.isValidTrack(track));
99  BOOST_CHECK(!minMax.isValidTrack(track));
100  };
101 
104 
107 
110 
113 
114  {
115  BOOST_TEST_INFO_SCOPE("pt min");
116  auto cfg = cfgBase;
117  cfg.cutSets.at(0).ptMin = {0.2};
118  TrackSelector selector{cfg};
119  MockTrack track = baseTrack;
120  BOOST_CHECK(selector.isValidTrack(track));
121  track.m_pt = 0.1;
122  BOOST_CHECK(!selector.isValidTrack(track));
123  }
124 
125  {
126  BOOST_TEST_INFO_SCOPE("pt max");
127  auto cfg = cfgBase;
128  cfg.cutSets.at(0).ptMax = {1.0};
129  TrackSelector selector{cfg};
130  MockTrack track = baseTrack;
131  BOOST_CHECK(selector.isValidTrack(track));
132  track.m_pt = 1.1;
133  BOOST_CHECK(!selector.isValidTrack(track));
134  }
135 
136  {
137  BOOST_TEST_INFO_SCOPE("pt min max");
138  auto cfg = cfgBase;
139  cfg.cutSets.at(0).ptMin = {0.2};
140  cfg.cutSets.at(0).ptMax = {1.0};
141  TrackSelector selector{cfg};
142  MockTrack track = baseTrack;
143  BOOST_CHECK(selector.isValidTrack(track));
144  track.m_pt = 0.1;
145  BOOST_CHECK(!selector.isValidTrack(track));
146  track.m_pt = 1.1;
147  BOOST_CHECK(!selector.isValidTrack(track));
148  }
149 
150  {
151  BOOST_TEST_INFO_SCOPE("eta min");
152  auto cfg = cfgBase;
153  cfg.cutSets.at(0).etaMin = {-1.0};
154  TrackSelector selector{cfg};
155  MockTrack track = baseTrack;
156  track.m_theta = thetaFromEta(0.5);
157  BOOST_CHECK(selector.isValidTrack(track));
158  track.m_theta = thetaFromEta(-1.1);
159  BOOST_CHECK(!selector.isValidTrack(track));
160  }
161 
162  {
163  BOOST_TEST_INFO_SCOPE("eta max");
164  auto cfg = cfgBase;
165  cfg.cutSets.at(0).etaMax = {1.0};
166  TrackSelector selector{cfg};
167  MockTrack track = baseTrack;
168  track.m_theta = thetaFromEta(0.5);
169  BOOST_CHECK(selector.isValidTrack(track));
170  track.m_theta = thetaFromEta(1.1);
171  BOOST_CHECK(!selector.isValidTrack(track));
172  }
173 
174  {
175  BOOST_TEST_INFO_SCOPE("eta min max");
176  auto cfg = cfgBase;
177  cfg.cutSets.at(0).etaMin = {-1.0};
178  cfg.cutSets.at(0).etaMax = {1.0};
179  TrackSelector selector{cfg};
180  MockTrack track = baseTrack;
181  track.m_theta = thetaFromEta(0.5);
182  BOOST_CHECK(selector.isValidTrack(track));
183  track.m_theta = thetaFromEta(-1.1);
184  BOOST_CHECK(!selector.isValidTrack(track));
185  track.m_theta = thetaFromEta(1.1);
186  BOOST_CHECK(!selector.isValidTrack(track));
187  }
188 
189  {
190  BOOST_TEST_INFO_SCOPE("abs eta min");
191  auto cfg = cfgBase;
192  cfg.cutSets.at(0).absEtaMin = {0.2};
193  TrackSelector selector{cfg};
194  MockTrack track = baseTrack;
195  track.m_theta = thetaFromEta(0.5);
196  BOOST_CHECK(selector.isValidTrack(track));
197  track.m_theta = thetaFromEta(-0.5);
198  BOOST_CHECK(selector.isValidTrack(track));
199 
200  track.m_theta = thetaFromEta(0.1);
201  BOOST_CHECK(!selector.isValidTrack(track));
202  track.m_theta = thetaFromEta(-0.1);
203  BOOST_CHECK(!selector.isValidTrack(track));
204  }
205 
206  {
207  BOOST_TEST_INFO_SCOPE("abs eta max");
208  auto cfg = cfgBase;
209  cfg.cutSets.at(0).absEtaMax = {1.0};
210  TrackSelector selector{cfg};
211  MockTrack track = baseTrack;
212  track.m_theta = thetaFromEta(0.5);
213  BOOST_CHECK(selector.isValidTrack(track));
214  track.m_theta = thetaFromEta(-0.5);
215  BOOST_CHECK(selector.isValidTrack(track));
216 
217  track.m_theta = thetaFromEta(1.1);
218  BOOST_CHECK(!selector.isValidTrack(track));
219  track.m_theta = thetaFromEta(-1.1);
220  BOOST_CHECK(!selector.isValidTrack(track));
221  }
222 
223  {
224  BOOST_TEST_INFO_SCOPE("abs eta min max");
225  auto cfg = cfgBase;
226  cfg.cutSets.at(0).absEtaMin = {0.2};
227  cfg.cutSets.at(0).absEtaMax = {1.0};
228  TrackSelector selector{cfg};
229  MockTrack track = baseTrack;
230  track.m_theta = thetaFromEta(0.5);
231  BOOST_CHECK(selector.isValidTrack(track));
232  track.m_theta = thetaFromEta(-0.5);
233  BOOST_CHECK(selector.isValidTrack(track));
234 
235  track.m_theta = thetaFromEta(0.1);
236  BOOST_CHECK(!selector.isValidTrack(track));
237  track.m_theta = thetaFromEta(-0.1);
238  BOOST_CHECK(!selector.isValidTrack(track));
239 
240  track.m_theta = thetaFromEta(1.1);
241  BOOST_CHECK(!selector.isValidTrack(track));
242  track.m_theta = thetaFromEta(-1.1);
243  BOOST_CHECK(!selector.isValidTrack(track));
244  }
245 
246  {
247  BOOST_TEST_INFO_SCOPE("nMeas min");
248  auto cfg = cfgBase;
249  cfg.cutSets.at(0).minMeasurements = {1};
250  TrackSelector selector{cfg};
251  MockTrack track = baseTrack;
252  track.m_nMeasurements = {2};
253  BOOST_CHECK(selector.isValidTrack(track));
254  track.m_nMeasurements = {1};
255  BOOST_CHECK(selector.isValidTrack(track));
256  track.m_nMeasurements = {0};
257  BOOST_CHECK(!selector.isValidTrack(track));
258  }
259 }
260 
261 BOOST_AUTO_TEST_CASE(TestSingleBinEtaCutByBinEdge) {
263 
264  BOOST_TEST_INFO_SCOPE(selector.config());
265 
266  MockTrack track{};
267  track.m_theta = thetaFromEta(0.0);
268  BOOST_CHECK(!selector.isValidTrack(track));
269 
270  track.m_theta = thetaFromEta(0.5);
271  BOOST_CHECK(!selector.isValidTrack(track));
272 
273  // cannot easily check on-edge behavior because of floating point arithmetic
274  // (it won't be exactly 1.0 in selector)
275  track.m_theta = thetaFromEta(1.01);
276  BOOST_CHECK(selector.isValidTrack(track));
277 
278  track.m_theta = thetaFromEta(1.5);
279  BOOST_CHECK(selector.isValidTrack(track));
280 
281  track.m_theta = thetaFromEta(2.0);
282  BOOST_CHECK(!selector.isValidTrack(track));
283 }
284 
285 BOOST_AUTO_TEST_CASE(TestMultiBinCuts) {
286  MockTrack baseTrack{};
287  baseTrack.m_theta = thetaFromEta(1.0);
288  baseTrack.m_phi = 0.5;
289  baseTrack.m_pt = 0.5;
290  baseTrack.m_loc0 = 0.5;
291  baseTrack.m_loc1 = 0.5;
292  baseTrack.m_time = 0.5;
293  baseTrack.m_nMeasurements = 0.5;
294 
296 
297  using factory_ptr_t = Config& (Config::*)(double, double);
298  using prop_ptr_t = double MockTrack::*;
299 
300  auto check = [&](const char* name, const factory_ptr_t& factory,
301  const prop_ptr_t& prop) {
302  BOOST_TEST_CONTEXT(name) {
304 
305  cfg.addCuts(2.0, [&](auto& c) { (c.*factory)(-1.0, 1.0); })
306  .addCuts([&](auto& c) { (c.*factory)(-2.0, 2.0); });
307 
308  TrackSelector selector{cfg};
309 
310  BOOST_TEST_INFO_SCOPE(cfg);
311 
312  {
313  // exactly at zero
314  MockTrack track = baseTrack;
315  track.m_theta = thetaFromEta(0.0);
316 
317  BOOST_CHECK(selector.isValidTrack(track));
318 
319  track.*prop = -1.1;
320  BOOST_CHECK(!selector.isValidTrack(track));
321 
322  track.*prop = 1.1;
323  BOOST_CHECK(!selector.isValidTrack(track));
324  }
325 
326  {
327  // first bin
328  MockTrack track = baseTrack;
329  track.m_theta = thetaFromEta(1.0);
330 
331  BOOST_CHECK(selector.isValidTrack(track));
332 
333  track.*prop = -1.1;
334  BOOST_CHECK(!selector.isValidTrack(track));
335 
336  track.*prop = 1.1;
337  BOOST_CHECK(!selector.isValidTrack(track));
338  }
339 
340  {
341  // first bin edge
342  MockTrack track = baseTrack;
343  track.m_theta =
344  thetaFromEta(2.0 - std::numeric_limits<double>::epsilon());
345 
346  BOOST_CHECK(selector.isValidTrack(track));
347 
348  track.*prop = -1.1;
349  BOOST_CHECK(!selector.isValidTrack(track));
350 
351  track.*prop = 1.1;
352  BOOST_CHECK(!selector.isValidTrack(track));
353  }
354 
355  {
356  // second bin lower edge
357  MockTrack track = baseTrack;
358  track.m_theta = thetaFromEta(2.0);
359 
360  BOOST_CHECK(selector.isValidTrack(track));
361 
362  track.*prop = -1.1;
363  BOOST_CHECK(selector.isValidTrack(track));
364 
365  track.*prop = 1.1;
366  BOOST_CHECK(selector.isValidTrack(track));
367 
368  track.*prop = -2.1;
369  BOOST_CHECK(!selector.isValidTrack(track));
370 
371  track.*prop = 2.1;
372  BOOST_CHECK(!selector.isValidTrack(track));
373  }
374 
375  {
376  // second bin
377  MockTrack track = baseTrack;
378  track.m_theta = thetaFromEta(666.0);
379 
380  track.*prop = -1.1;
381  BOOST_CHECK(selector.isValidTrack(track));
382 
383  track.*prop = 1.1;
384  BOOST_CHECK(selector.isValidTrack(track));
385 
386  track.*prop = -2.1;
387  BOOST_CHECK(!selector.isValidTrack(track));
388 
389  track.*prop = 2.1;
390  BOOST_CHECK(!selector.isValidTrack(track));
391  }
392  }
393  };
394 
396  check("loc1", &Config::loc1, &MockTrack::m_loc1);
399  check("pt", &Config::pt, &MockTrack::m_pt);
400 }
401 
402 BOOST_AUTO_TEST_CASE(TestBinSelection) {
403  using EtaBinnedConfig = TrackSelector::EtaBinnedConfig;
404  constexpr double inf = std::numeric_limits<double>::infinity();
405 
406  {
407  EtaBinnedConfig cfg{std::vector<double>{0, inf}};
408  for (int i = -1; i <= 1; i = i + 2) {
409  BOOST_CHECK_EQUAL(cfg.binIndex(i * 0.0), 0);
410  BOOST_CHECK_EQUAL(cfg.binIndex(i * 1.0), 0);
411  BOOST_CHECK_EQUAL(cfg.binIndex(i * 2.0), 0);
412  BOOST_CHECK_EQUAL(cfg.binIndex(i * 3.0), 0);
413  BOOST_CHECK_EQUAL(cfg.binIndex(i * 10.0), 0);
414  BOOST_CHECK_EQUAL(cfg.binIndex(i * 1000.0), 0);
415  }
416  }
417 
418  {
419  EtaBinnedConfig cfg{std::vector<double>{0, 0.5, 1.5, 2.5, 3.0, inf}};
420  for (int i = -1; i <= 1; i = i + 2) {
421  BOOST_CHECK_EQUAL(cfg.binIndex(i * 0.0), 0);
422  BOOST_CHECK_EQUAL(cfg.binIndex(i * 1.0), 1);
423  BOOST_CHECK_EQUAL(cfg.binIndex(i * 2.0), 2);
424  BOOST_CHECK_EQUAL(cfg.binIndex(i * 3.0), 4);
425  BOOST_CHECK_EQUAL(cfg.binIndex(i * 10.0), 4);
426  BOOST_CHECK_EQUAL(cfg.binIndex(i * 1000.0), 4);
427  }
428  }
429 
430  {
431  EtaBinnedConfig cfg{std::vector<double>{0, 1, 2}};
432  for (int i = -1; i <= 1; i = i + 2) {
433  BOOST_CHECK_EQUAL(cfg.binIndex(i * 0.0), 0);
434  BOOST_CHECK_EQUAL(cfg.binIndex(i * 1.0), 1);
435  BOOST_CHECK_EQUAL(
436  cfg.binIndex(i * (2.0 - std::numeric_limits<double>::epsilon())), 1);
437  BOOST_CHECK_THROW(cfg.binIndex(i * 2.0), std::invalid_argument);
438  }
439  }
440 }
441 
442 BOOST_AUTO_TEST_CASE(TestConstructor) {
443  // valid multi bin construction
444  {
445  TrackSelector::EtaBinnedConfig cfg{std::vector<double>{0, 1, 4}};
446  cfg.cutSets.at(0).ptMin = 0.9;
447  cfg.cutSets.at(1).ptMin = 0.4;
449  }
450 
451  {
452  // Track selector config with 2 eta bins
453  TrackSelector::EtaBinnedConfig cfg{std::vector<double>{0, 1, 4}};
454 
455  // just the right amount!
457 
458  // not enough cut cets
459  cfg.cutSets.resize(1);
460  BOOST_CHECK_THROW(TrackSelector{cfg}, std::invalid_argument);
461 
462  // too many cut sets
463  cfg.cutSets.resize(3);
464  BOOST_CHECK_THROW(TrackSelector{cfg}, std::invalid_argument);
465  }
466 
467  // Constructor straight from cut config
469  TrackSelector selector{cuts};
470  BOOST_CHECK_EQUAL(selector.config().absEtaEdges.size(), 2);
471 
472  {
473  // Invalid sequence of chained construction
475  cfg.addCuts(2.0, [](auto& c) { c.loc0(-1.0, 1.0); });
476  BOOST_CHECK_THROW(cfg.addCuts(1.0), std::invalid_argument);
477  BOOST_CHECK_THROW(TrackSelector::EtaBinnedConfig(0).addCuts(-2.0),
478  std::invalid_argument);
479  }
480 
481  {
483 
484  cfg.addCuts(2.0, [](auto& c) { c.loc0(-1.0, 1.0); });
485  BOOST_CHECK_EQUAL(cfg.nEtaBins(), 1);
486  BOOST_CHECK_EQUAL(cfg.getCuts(1.5).loc0Min, -1.0);
487  BOOST_CHECK_EQUAL(cfg.getCuts(1.5).loc0Max, 1.0);
488 
489  cfg.addCuts(3.0, [](auto& c) { c.loc0(-2.0, 2.0); });
490  BOOST_CHECK_EQUAL(cfg.nEtaBins(), 2);
491  BOOST_CHECK_EQUAL(cfg.getCuts(2.5).loc0Min, -2.0);
492  BOOST_CHECK_EQUAL(cfg.getCuts(2.5).loc0Max, 2.0);
493 
494  cfg.addCuts(4.0, [](auto& c) { c.loc0(-3.0, 3.0); });
495  BOOST_CHECK_EQUAL(cfg.nEtaBins(), 3);
496  BOOST_CHECK_EQUAL(cfg.getCuts(3.5).loc0Min, -3.0);
497  BOOST_CHECK_EQUAL(cfg.getCuts(3.5).loc0Max, 3.0);
498  }
499 }
500 
501 BOOST_AUTO_TEST_SUITE_END()