EIC 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/unit_test.hpp>
10 
14 #include "Acts/Geometry/Volume.hpp"
22 
23 #include <system_error>
24 #include <variant>
25 
26 namespace ActsFatras {
27 
28 BOOST_AUTO_TEST_SUITE(Digitization)
29 
30 namespace {
31 struct AddSmearer {
32  unsigned int stats = 0;
33 
34  Acts::Result<std::pair<double, double>> operator()(double value) {
35  ++stats;
37  std::make_pair<double, double>(value + 1., 3.));
38  }
39 };
40 
41 struct SterileSmearer {
42  Acts::Result<std::pair<double, double>> operator()(double value) {
44  std::make_pair<double, double>(value + 0., 0.));
45  }
46 };
47 
48 struct InvalidSmearer {
49  Acts::Result<std::pair<double, double>> operator()(double /*ignored*/) {
51  ActsFatras::DigitizationError::SmearError);
52  }
53 };
54 
55 const auto pid = Barcode().setVertexPrimary(12).setParticle(23);
56 const auto gid =
58 
59 auto rec = std::make_shared<Acts::RectangleBounds>(1000, 1000);
60 auto tSurface = Acts::Surface::makeShared<Acts::PlaneSurface>(
61  Acts::Transform3D::Identity(), rec);
62 
63 } // namespace
64 
65 BOOST_AUTO_TEST_CASE(BoundParameterSmeering) {
67 
68  // some hit position
69  auto p4 = Hit::Vector4(3, 2, 0, 10.);
70  // before/after four-momenta are the same
71  auto m4 = Hit::Vector4(1, 2, 1, 4);
72  auto hit = Hit(gid, pid, p4, m4, m4, 12u);
73 
74  SmearInput sInput{hit, geoCtx, tSurface};
75 
76  AddSmearer tAddFnc;
77  SterileSmearer tSterileFnc;
78  InvalidSmearer tInvalidFnc;
79 
81  auto oneDim = oneDimSmearer(sInput, {tAddFnc});
82 
83  BOOST_CHECK(oneDim.ok());
84 
85  const auto& smearedOne = oneDim.value();
86  BOOST_CHECK(smearedOne.contains<Acts::eBoundLoc0>());
87 
88  const auto& sParametersOne = smearedOne.getParameters();
89  const auto& sCovarianceOne = smearedOne.getCovariance().value();
90 
91  CHECK_CLOSE_ABS(sParametersOne[0], 4., Acts::s_epsilon);
92  CHECK_CLOSE_ABS(sCovarianceOne(0, 0), 9., Acts::s_epsilon);
93 
95  auto twoDim = twoDimSmearer(sInput, {tAddFnc, tAddFnc});
96 
97  BOOST_CHECK(twoDim.ok());
98  const auto& smearedTwo = twoDim.value();
99  BOOST_CHECK(smearedTwo.contains<Acts::eBoundLoc0>());
100  BOOST_CHECK(smearedTwo.contains<Acts::eBoundLoc1>());
101 
102  const auto& sParametersTwo = smearedTwo.getParameters();
103  const auto& sCovarianceTwo = smearedTwo.getCovariance().value();
104 
105  CHECK_CLOSE_ABS(sParametersTwo[0], 4., Acts::s_epsilon);
106  CHECK_CLOSE_ABS(sParametersTwo[1], 3., Acts::s_epsilon);
107  CHECK_CLOSE_ABS(sCovarianceTwo(0, 0), 9., Acts::s_epsilon);
108  CHECK_CLOSE_ABS(sCovarianceTwo(1, 1), 9., Acts::s_epsilon);
109 
110  // Check smearing of time
112  auto locYTime = locYTimeSmearer(sInput, {tAddFnc, tAddFnc});
113  BOOST_CHECK(locYTime.ok());
114  const auto& smearedLocyTime = locYTime.value();
115  BOOST_CHECK(smearedLocyTime.contains<Acts::eBoundLoc1>());
116  BOOST_CHECK(smearedLocyTime.contains<Acts::eBoundTime>());
117  CHECK_CLOSE_ABS(smearedLocyTime.getParameter<Acts::eBoundLoc1>(), 3.,
119  CHECK_CLOSE_ABS(smearedLocyTime.getParameter<Acts::eBoundTime>(), 11.,
121 
122  // Use sterile BoundParametersSmearer to check if direction is properly
123  // translated
125  auto phiTheta = phiThetaSmearer(sInput, {tSterileFnc, tSterileFnc});
126  BOOST_CHECK(phiTheta.ok());
127  auto phiThetaParSet = phiTheta.value();
128  BOOST_CHECK(phiThetaParSet.contains<Acts::eBoundPhi>());
129  BOOST_CHECK(phiThetaParSet.contains<Acts::eBoundTheta>());
130  CHECK_CLOSE_ABS(phiThetaParSet.getParameter<Acts::eBoundPhi>(),
131  Acts::VectorHelpers::phi(hit.unitDirection()),
133  CHECK_CLOSE_ABS(phiThetaParSet.getParameter<Acts::eBoundTheta>(),
134  Acts::VectorHelpers::theta(hit.unitDirection()),
136 
137  // Finally check an invalid smearing
139  invalidHitFirstSmearer;
140  auto invalidHitFirst =
141  invalidHitFirstSmearer(sInput, {tInvalidFnc, tSterileFnc});
142  BOOST_CHECK(not invalidHitFirst.ok());
143 
146  invalidHitMiddleSmearer;
147 
148  auto invalidHitMiddle = invalidHitMiddleSmearer(
149  sInput, {tSterileFnc, tSterileFnc, tInvalidFnc, tSterileFnc});
150  BOOST_CHECK(not invalidHitMiddle.ok());
151 
153  invalidHitLastSmearer;
154  auto invalidHitLast =
155  invalidHitLastSmearer(sInput, {tSterileFnc, tInvalidFnc});
156  BOOST_CHECK(not invalidHitLast.ok());
157 
158  // Test the variant approach for smearers
159  using StripSmearer = std::pair<BoundParametersSmearer<Acts::eBoundLoc0>,
160  std::array<SmearFunction, 1>>;
161 
162  using PixelSmearer =
163  std::pair<BoundParametersSmearer<Acts::eBoundLoc0, Acts::eBoundLoc1>,
164  std::array<SmearFunction, 2>>;
165 
166  using SiliconSmearer = std::variant<StripSmearer, PixelSmearer>;
167 
168  using SiliconParSets =
169  std::variant<Acts::ParameterSet<Acts::BoundIndices, Acts::eBoundLoc0>,
171  Acts::eBoundLoc1>>;
172 
173  StripSmearer stripSmearer(oneDimSmearer, {tAddFnc});
174  PixelSmearer pixelSmearer(twoDimSmearer, {tAddFnc, tAddFnc});
175 
176  std::map<std::string, SiliconSmearer> siSmearers;
177  siSmearers["pixel"] = pixelSmearer;
178  siSmearers["strip"] = stripSmearer;
179 
180  std::map<std::string, Hit> siHits;
181  siHits["pixel"] = hit;
182  siHits["strip"] = hit;
183 
184  std::vector<SiliconParSets> siParSets;
185 
186  for (auto& [key, value] : siHits) {
187  std::string key_id = key;
188  std::visit(
189  [&](auto&& sm) {
190  auto sParSet = sm.first(sInput, sm.second);
191  if (sParSet.ok()) {
192  siParSets.push_back(sParSet.value());
193  // siParSets.push_Back(sParSet);
194  std::cout << "Smearing a hit for " << key_id << std::endl;
195  std::cout << " - contains loc0 : "
196  << sParSet.value().template contains<Acts::eBoundLoc0>()
197  << std::endl;
198  std::cout << " - contains loc1 : "
199  << sParSet.value().template contains<Acts::eBoundLoc1>()
200  << std::endl;
201  }
202  },
203  siSmearers[key]);
204  }
205 
206  BOOST_CHECK_EQUAL(siParSets.size(), 2u);
207 }
208 
209 BOOST_AUTO_TEST_CASE(FreeParameterSmeering) {
210  using FreeSmearer =
212 
214 
215  FreeSmearer freeSmearer;
216 
217  // some hit position
218  auto p4 = Hit::Vector4(3, 2, 0, 10.);
219  // before/after four-momenta are the same
220  auto m4 = Hit::Vector4(1, 2, 1, 4);
221  auto hit = Hit(gid, pid, p4, m4, m4, 12u);
222 
223  AddSmearer tAddFnc;
224  SterileSmearer tSterileFnc;
225 
226  auto freeSmearing =
227  freeSmearer({hit, geoCtx}, {tSterileFnc, tAddFnc, tSterileFnc});
228 
229  BOOST_CHECK(freeSmearing.ok());
230  const auto& freeSet = freeSmearing.value();
231  BOOST_CHECK(freeSet.contains<Acts::eFreePos0>());
232  BOOST_CHECK(freeSet.contains<Acts::eFreePos1>());
233  CHECK_CLOSE_ABS(freeSet.getParameter<Acts::eFreePos0>(), 3., Acts::s_epsilon);
234  CHECK_CLOSE_ABS(freeSet.getParameter<Acts::eFreePos1>(), 3., Acts::s_epsilon);
235  CHECK_CLOSE_ABS(freeSet.getParameter<Acts::eFreeDir2>(),
236  m4.segment<3>(0).normalized()[2], Acts::s_epsilon);
237 }
238 
239 BOOST_AUTO_TEST_SUITE_END()
240 
241 } // namespace ActsFatras