Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UncorrelatedHitSmearerTests.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file UncorrelatedHitSmearerTests.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/unit_test.hpp>
11 
28 
29 #include <algorithm>
30 #include <array>
31 #include <cstddef>
32 #include <cstdint>
33 #include <iterator>
34 #include <limits>
35 #include <memory>
36 #include <ostream>
37 #include <random>
38 #include <utility>
39 
40 namespace {
41 
42 namespace bd = boost::unit_test::data;
43 
44 using RandomGenerator = std::default_random_engine;
45 
46 struct SterileSmearer {
48  RandomGenerator& /*rng*/) {
50  std::make_pair<double, double>(value + 0., 0.));
51  }
52 };
53 
54 struct AddSmearer {
55  double offset = 1.0;
56 
58  RandomGenerator& /*rng*/) {
60  std::make_pair<double, double>(value + offset, 3.));
61  }
62 };
63 
64 struct InvalidSmearer {
65  Acts::Result<std::pair<double, double>> operator()(double /*ignored*/,
66  RandomGenerator& /*rng*/) {
68  ActsFatras::DigitizationError::SmearingError);
69  }
70 };
71 
72 struct Fixture {
73  RandomGenerator rng;
74  // identifiers
77  // geometry information
78  std::shared_ptr<Acts::Surface> surface;
80  // local and global track parameters
81  Acts::BoundVector boundParams;
82  Acts::FreeVector freeParams;
83  // hit information
84  ActsFatras::Hit hit;
85 
86  Fixture(uint64_t rngSeed)
87  : rng(rngSeed),
88  gid(Acts::GeometryIdentifier().setVolume(1).setLayer(2).setSensitive(
89  3)),
90  pid(ActsFatras::Barcode().setVertexPrimary(12).setParticle(23)),
91  surface(Acts::Surface::makeShared<Acts::PlaneSurface>(
92  Acts::Transform3(Acts::Translation3(3, 2, 1)))) {
93  using namespace Acts::UnitLiterals;
95 
96  surface->assignGeometryId(gid);
97 
98  // generate random track parameters
100  boundParams = par;
102  boundParams);
103 
104  // construct hit from free parameters
105  Acts::Vector4 r4;
106  r4.segment<3>(Acts::ePos0) = freeParams.segment<3>(Acts::eFreePos0);
107  r4[Acts::eTime] = freeParams[Acts::eFreeTime];
108  // construct 4-momentum vector assuming m=0
109  Acts::Vector4 p4;
110  p4.segment<3>(Acts::eMom0) =
111  freeParams.segment<3>(Acts::eFreeDir0).normalized();
112  p4[Acts::eEnergy] = 1;
113  p4 *= std::abs(1_e / freeParams[Acts::eFreeQOverP]);
114  // same 4-momentum before/after hit
115  hit = ActsFatras::Hit(gid, pid, r4, p4, p4, 13);
116  }
117 };
118 
119 // track parameter indices to test smearing with. q/p smearing is not supported
120 // in either case.
121 const Acts::BoundIndices boundIndices[] = {
124 };
125 const Acts::FreeIndices freeIndices[] = {
128 };
129 
130 constexpr auto tol = 128 * std::numeric_limits<double>::epsilon();
131 
132 } // namespace
133 
134 BOOST_AUTO_TEST_SUITE(FatrasUncorrelatedHitSmearer)
135 
136 BOOST_DATA_TEST_CASE(Bound1, bd::make(boundIndices), index) {
137  Fixture f(123);
139  s.indices = {index};
140 
141  // smearing does not do anything
142  {
143  s.smearFunctions.fill(SterileSmearer{});
144  auto ret = s(f.rng, f.hit, *f.surface, f.geoCtx);
145  BOOST_CHECK(ret.ok());
146  auto [par, cov] = ret.value();
147  CHECK_CLOSE_REL(par[0], f.boundParams[index], tol);
148  }
149  // smearing adds something
150  {
151  s.smearFunctions.fill(AddSmearer{-42.0});
152  auto ret = s(f.rng, f.hit, *f.surface, f.geoCtx);
153  BOOST_CHECK(ret.ok());
154  auto [par, cov] = ret.value();
155  CHECK_CLOSE_REL(par[0], f.boundParams[index] - 42.0, tol);
156  }
157  // smearing fails
158  {
159  s.smearFunctions.fill(InvalidSmearer{});
160  auto ret = s(f.rng, f.hit, *f.surface, f.geoCtx);
161  BOOST_CHECK(not ret.ok());
162  BOOST_CHECK(ret.error());
163  }
164 }
165 
167  Fixture f(12356);
168  // without q/p
170  s;
171  std::copy(std::begin(boundIndices), std::end(boundIndices),
172  s.indices.begin());
173 
174  // smearing does not do anything
175  {
176  s.smearFunctions.fill(SterileSmearer{});
177  auto ret = s(f.rng, f.hit, *f.surface, f.geoCtx);
178  BOOST_CHECK(ret.ok());
179  auto [par, cov] = ret.value();
180  for (size_t i = 0; i < s.indices.size(); ++i) {
181  BOOST_TEST_INFO("Comparing smeared measurement "
182  << i << " originating from bound parameter "
183  << s.indices[i]);
184  CHECK_CLOSE_REL(par[i], f.boundParams[s.indices[i]], tol);
185  }
186  }
187  // smearing adds something
188  {
189  s.smearFunctions.fill(AddSmearer{-23.0});
190  auto ret = s(f.rng, f.hit, *f.surface, f.geoCtx);
191  BOOST_CHECK(ret.ok());
192  auto [par, cov] = ret.value();
193  for (size_t i = 0; i < s.indices.size(); ++i) {
194  BOOST_TEST_INFO("Comparing smeared measurement "
195  << i << " originating from bound parameter "
196  << s.indices[i]);
197  CHECK_CLOSE_REL(par[i], f.boundParams[s.indices[i]] - 23.0, tol);
198  }
199  }
200  // one smearer fails
201  {
202  s.smearFunctions.fill(SterileSmearer{});
203  s.smearFunctions[3] = InvalidSmearer{};
204  auto ret = s(f.rng, f.hit, *f.surface, f.geoCtx);
205  BOOST_CHECK(not ret.ok());
206  BOOST_CHECK(ret.error());
207  }
208 }
209 
210 BOOST_DATA_TEST_CASE(Free1, bd::make(freeIndices), index) {
211  Fixture f(1234);
213  s.indices = {index};
214 
215  // smearing does not do anything
216  {
217  s.smearFunctions.fill(SterileSmearer{});
218  auto ret = s(f.rng, f.hit);
219  BOOST_CHECK(ret.ok());
220  auto [par, cov] = ret.value();
221  CHECK_CLOSE_REL(par[0], f.freeParams[index], tol);
222  }
223  // smearing adds something
224  {
225  s.smearFunctions.fill(AddSmearer{-42.0});
226  auto ret = s(f.rng, f.hit);
227  BOOST_CHECK(ret.ok());
228  auto [par, cov] = ret.value();
229  CHECK_CLOSE_REL(par[0], f.freeParams[index] - 42.0, tol);
230  }
231  // smearing fails
232  {
233  s.smearFunctions.fill(InvalidSmearer{});
234  auto ret = s(f.rng, f.hit);
235  BOOST_CHECK(not ret.ok());
236  BOOST_CHECK(ret.error());
237  }
238 }
239 
241  Fixture f(123567);
242  // without q/p
244  std::copy(std::begin(freeIndices), std::end(freeIndices), s.indices.begin());
245 
246  // smearing does not do anything
247  {
248  s.smearFunctions.fill(SterileSmearer{});
249  auto ret = s(f.rng, f.hit);
250  BOOST_CHECK(ret.ok());
251  auto [par, cov] = ret.value();
252  for (size_t i = 0; i < s.indices.size(); ++i) {
253  BOOST_TEST_INFO("Comparing smeared measurement "
254  << i << " originating from free parameter "
255  << s.indices[i]);
256  CHECK_CLOSE_REL(par[i], f.freeParams[s.indices[i]], tol);
257  }
258  }
259  // smearing adds something
260  {
261  s.smearFunctions.fill(AddSmearer{42.0});
262  auto ret = s(f.rng, f.hit);
263  BOOST_CHECK(ret.ok());
264  auto [par, cov] = ret.value();
265  for (size_t i = 0; i < s.indices.size(); ++i) {
266  BOOST_TEST_INFO("Comparing smeared measurement "
267  << i << " originating from free parameter "
268  << s.indices[i]);
269  CHECK_CLOSE_REL(par[i], f.freeParams[s.indices[i]] + 42.0, tol);
270  }
271  }
272  // one smearer fails
273  {
274  s.smearFunctions.fill(SterileSmearer{});
275  s.smearFunctions[3] = InvalidSmearer{};
276  auto ret = s(f.rng, f.hit);
277  BOOST_CHECK(not ret.ok());
278  BOOST_CHECK(ret.error());
279  }
280 }
281 
282 BOOST_AUTO_TEST_SUITE_END()