Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GsfMixtureReductionTests.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file GsfMixtureReductionTests.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2022-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/unit_test.hpp>
10 
16 
17 #include <algorithm>
18 #include <array>
19 #include <cstddef>
20 #include <memory>
21 #include <numeric>
22 #include <tuple>
23 #include <utility>
24 #include <vector>
25 
26 using namespace Acts;
27 
28 BOOST_AUTO_TEST_CASE(test_distance_matrix_min_distance) {
29  std::vector<GsfComponent> cmps = {
30  {1. / 3., BoundVector::Constant(-2.), BoundSquareMatrix::Identity()},
31  {1. / 3., BoundVector::Constant(+0.), BoundSquareMatrix::Identity()},
32  {1. / 3., BoundVector::Constant(+1.), BoundSquareMatrix::Identity()},
33  {1. / 3., BoundVector::Constant(+4.), BoundSquareMatrix::Identity()}};
34 
35  const auto proj = [](auto &a) -> decltype(auto) { return a; };
36  detail::SymmetricKLDistanceMatrix mat(cmps, proj);
37 
38  const auto [i, j] = mat.minDistancePair();
39  BOOST_CHECK(std::min(i, j) == 1);
40  BOOST_CHECK(std::max(i, j) == 2);
41 }
42 
43 BOOST_AUTO_TEST_CASE(test_distance_matrix_masking) {
44  std::vector<GsfComponent> cmps = {
45  {1. / 3., BoundVector::Constant(-2.), BoundSquareMatrix::Identity()},
46  {1. / 3., BoundVector::Constant(+0.), BoundSquareMatrix::Identity()},
47  {1. / 3., BoundVector::Constant(+1.), BoundSquareMatrix::Identity()},
48  {1. / 3., BoundVector::Constant(+4.), BoundSquareMatrix::Identity()}};
49 
50  const auto proj = [](auto &a) -> decltype(auto) { return a; };
51  const std::size_t cmp_to_mask = 2;
52 
53  detail::SymmetricKLDistanceMatrix mat_full(cmps, proj);
54  mat_full.maskAssociatedDistances(cmp_to_mask);
55 
56  cmps.erase(cmps.begin() + cmp_to_mask);
57  detail::SymmetricKLDistanceMatrix mat_small(cmps, proj);
58 
59  const auto [full_i, full_j] = mat_full.minDistancePair();
60  const auto [small_i, small_j] = mat_small.minDistancePair();
61 
62  BOOST_CHECK(std::min(full_i, full_j) == 0);
63  BOOST_CHECK(std::max(full_i, full_j) == 1);
64  BOOST_CHECK(full_i == small_i);
65  BOOST_CHECK(full_j == small_j);
66 }
67 
68 BOOST_AUTO_TEST_CASE(test_distance_matrix_recompute_distance) {
69  std::vector<GsfComponent> cmps = {
70  {1. / 3., BoundVector::Constant(-2.), BoundSquareMatrix::Identity()},
71  {1. / 3., BoundVector::Constant(+0.), BoundSquareMatrix::Identity()},
72  {1. / 3., BoundVector::Constant(+1.), BoundSquareMatrix::Identity()},
73  {1. / 3., BoundVector::Constant(+4.), BoundSquareMatrix::Identity()}};
74 
75  const auto proj = [](auto &a) -> decltype(auto) { return a; };
76  detail::SymmetricKLDistanceMatrix mat(cmps, proj);
77 
78  {
79  const auto [i, j] = mat.minDistancePair();
80  BOOST_CHECK(std::min(i, j) == 1);
81  BOOST_CHECK(std::max(i, j) == 2);
82  }
83 
84  cmps[3].boundPars = BoundVector::Constant(0.1);
85  mat.recomputeAssociatedDistances(3, cmps, proj);
86 
87  {
88  const auto [i, j] = mat.minDistancePair();
89  BOOST_CHECK(std::min(i, j) == 1);
90  BOOST_CHECK(std::max(i, j) == 3);
91  }
92 
93  cmps[0].boundPars = BoundVector::Constant(1.01);
94  mat.recomputeAssociatedDistances(0, cmps, proj);
95 
96  {
97  const auto [i, j] = mat.minDistancePair();
98  BOOST_CHECK(std::min(i, j) == 0);
99  BOOST_CHECK(std::max(i, j) == 2);
100  }
101 }
102 
103 BOOST_AUTO_TEST_CASE(test_mixture_reduction) {
104  auto meanAndSumOfWeights = [](const auto &cmps) {
105  const auto mean = std::accumulate(
106  cmps.begin(), cmps.end(), Acts::BoundVector::Zero().eval(),
107  [](auto sum, const auto &cmp) -> Acts::BoundVector {
108  return sum + cmp.weight * cmp.boundPars;
109  });
110 
111  const double sumOfWeights = std::accumulate(
112  cmps.begin(), cmps.end(), 0.0,
113  [](auto sum, const auto &cmp) { return sum + cmp.weight; });
114 
115  return std::make_tuple(mean, sumOfWeights);
116  };
117 
118  // Assume that the components are on a generic plane surface
119  auto surface = Acts::Surface::makeShared<PlaneSurface>(Vector3{0, 0, 0},
120  Vector3{1, 0, 0});
121  const std::size_t NComps = 4;
122  std::vector<GsfComponent> cmps;
123 
124  for (auto i = 0ul; i < NComps; ++i) {
125  GsfComponent a;
126  a.boundPars = BoundVector::Zero();
127  a.boundCov = BoundSquareMatrix::Identity();
128  a.weight = 1.0 / NComps;
129  cmps.push_back(a);
130  }
131 
132  cmps[0].boundPars[eBoundQOverP] = 0.5_GeV;
133  cmps[1].boundPars[eBoundQOverP] = 1.5_GeV;
134  cmps[2].boundPars[eBoundQOverP] = 3.5_GeV;
135  cmps[3].boundPars[eBoundQOverP] = 4.5_GeV;
136 
137  // Check start properties
138  const auto [mean0, sumOfWeights0] = meanAndSumOfWeights(cmps);
139 
140  BOOST_CHECK_CLOSE(mean0[eBoundQOverP], 2.5_GeV, 1.e-8);
141  BOOST_CHECK_CLOSE(sumOfWeights0, 1.0, 1.e-8);
142 
143  // Reduce by factor of 2 and check if weights and QoP are correct
145 
146  BOOST_CHECK(cmps.size() == 2);
147 
148  std::sort(cmps.begin(), cmps.end(), [](const auto &a, const auto &b) {
149  return a.boundPars[eBoundQOverP] < b.boundPars[eBoundQOverP];
150  });
151  BOOST_CHECK_CLOSE(cmps[0].boundPars[eBoundQOverP], 1.0_GeV, 1.e-8);
152  BOOST_CHECK_CLOSE(cmps[1].boundPars[eBoundQOverP], 4.0_GeV, 1.e-8);
153 
154  const auto [mean1, sumOfWeights1] = meanAndSumOfWeights(cmps);
155 
156  BOOST_CHECK_CLOSE(mean1[eBoundQOverP], 2.5_GeV, 1.e-8);
157  BOOST_CHECK_CLOSE(sumOfWeights1, 1.0, 1.e-8);
158 
159  // Reduce by factor of 2 and check if weights and QoP are correct
161 
162  BOOST_CHECK(cmps.size() == 1);
163  BOOST_CHECK_CLOSE(cmps[0].boundPars[eBoundQOverP], 2.5_GeV, 1.e-8);
164  BOOST_CHECK_CLOSE(cmps[0].weight, 1.0, 1.e-8);
165 }