Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ConvertTrackPodioTest.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file ConvertTrackPodioTest.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/tools/old/interface.hpp>
11 #include <boost/test/unit_test.hpp>
12 #include <boost/test/unit_test_suite.hpp>
13 
41 #include "ActsPodioEdm/Surface.h"
42 #include <ActsPodioEdm/TrackCollection.h>
43 
44 #include <algorithm>
45 #include <iterator>
46 #include <memory>
47 #include <random>
48 #include <stdexcept>
49 
50 using namespace Acts;
51 using namespace Acts::UnitLiterals;
52 using namespace Acts::HashedStringLiteral;
53 BOOST_AUTO_TEST_SUITE(PodioTrackConversion)
54 
55 class NullHelper : public PodioUtil::ConversionHelper {
56  public:
57  std::optional<PodioUtil::Identifier> surfaceToIdentifier(
58  const Surface& /*surface*/) const override {
59  return {};
60  }
61  const Surface* identifierToSurface(
62  PodioUtil::Identifier /*identifier*/) const override {
63  return nullptr;
64  }
65 
66  SourceLink identifierToSourceLink(
67  PodioUtil::Identifier /*identifier*/) const override {
68  return SourceLink{0};
69  }
70 
71  PodioUtil::Identifier sourceLinkToIdentifier(
72  const SourceLink& /*sourceLink*/) override {
73  return 0;
74  }
75 };
76 
77 struct MapHelper : public NullHelper {
78  std::optional<PodioUtil::Identifier> surfaceToIdentifier(
79  const Surface& surface) const override {
80  for (auto&& [id, srf] : surfaces) {
81  if (srf == &surface) {
82  return id;
83  }
84  }
85  return {};
86  }
88  auto it = surfaces.find(id);
89  if (it == surfaces.end()) {
90  return nullptr;
91  }
92 
93  return it->second;
94  }
95 
96  std::unordered_map<PodioUtil::Identifier, const Surface*> surfaces;
97 };
98 
99 BOOST_AUTO_TEST_CASE(ConvertSurface) {
100  auto rBounds = std::make_shared<RectangleBounds>(15, 20);
101 
102  auto trf = Transform3::Identity();
103  trf.translation().setRandom();
104 
105  auto free = Acts::Surface::makeShared<PlaneSurface>(trf, rBounds);
106 
107  NullHelper helper;
108  auto surface = PodioUtil::convertSurfaceToPodio(helper, *free);
109 
110  auto free2 = PodioUtil::convertSurfaceFromPodio(helper, surface);
111 
113 
114  BOOST_REQUIRE(free2);
115  BOOST_CHECK_EQUAL(free->type(), free2->type());
116  BOOST_CHECK_EQUAL(free->bounds().type(), free2->bounds().type());
117  BOOST_CHECK_EQUAL(free->center(gctx), free2->center(gctx));
118 
119  const auto* rBounds2 = dynamic_cast<const RectangleBounds*>(&free2->bounds());
120  BOOST_REQUIRE_NE(rBounds2, nullptr);
121 
122  BOOST_CHECK_EQUAL(rBounds2->halfLengthX(), rBounds->halfLengthX());
123  BOOST_CHECK_EQUAL(rBounds2->halfLengthY(), rBounds->halfLengthY());
124 
125  // this could probably use some more complete checks
126 }
127 
128 BOOST_AUTO_TEST_CASE(ConvertTrack) {
129  auto rBounds = std::make_shared<RectangleBounds>(15, 20);
130  auto trf = Transform3::Identity();
131  trf.translation().setRandom();
132  auto free = Acts::Surface::makeShared<PlaneSurface>(trf, rBounds);
133 
134  MapHelper helper;
135 
136  auto refCov = BoundMatrix::Random().eval();
137 
138  podio::Frame frame;
139 
140  {
143  ActsPodioEdm::TrackCollection& tracks = ptc.trackCollection();
144 
145  Acts::TrackContainer tc{ptc, tsc};
146 
147  BOOST_CHECK(!tc.hasColumn("int_column"_hash));
148  BOOST_CHECK(!tc.hasColumn("float_column"_hash));
149  tc.addColumn<int32_t>("int_column");
150  tc.addColumn<float>("float_column");
151  BOOST_CHECK(tc.hasColumn("int_column"_hash));
152  BOOST_CHECK(tc.hasColumn("float_column"_hash));
153 
154  BOOST_CHECK_EQUAL(tc.size(), 0);
155 
156  auto t = tc.getTrack(tc.addTrack());
157  BOOST_CHECK_EQUAL(t.tipIndex(), MultiTrajectoryTraits::kInvalid);
158 
159  BOOST_CHECK_EQUAL(tsc.size(), 0);
160  auto ts1 = t.appendTrackState();
161  auto ts2 = t.appendTrackState();
162  auto ts3 = t.appendTrackState();
163  BOOST_CHECK_EQUAL(tsc.size(), 3);
164  BOOST_CHECK_EQUAL(ts1.index(), 0);
165  BOOST_CHECK_EQUAL(ts2.index(), 1);
166  BOOST_CHECK_EQUAL(ts3.index(), 2);
167 
168  BOOST_CHECK_EQUAL(t.nTrackStates(), 3);
169  BOOST_CHECK_EQUAL(t.tipIndex(), 2);
170 
171  BOOST_CHECK_EQUAL(tc.size(), 1);
172 
173  auto pTrack = tracks.at(0);
174  BOOST_CHECK_EQUAL(pTrack.data().tipIndex, 2);
175 
176  t.parameters() << 1, 2, 3, 4, 5, 6;
177  Eigen::Map<BoundVector> pars{pTrack.data().parameters.data()};
178  BoundVector bv;
179  bv << 1, 2, 3, 4, 5, 6;
180  BOOST_CHECK_EQUAL(pars, bv);
181 
182  t.covariance() = refCov;
183 
184  Eigen::Map<const BoundMatrix> cov{pTrack.data().covariance.data()};
185  BOOST_CHECK_EQUAL(refCov, cov);
186 
187  t.nMeasurements() = 17;
188  BOOST_CHECK_EQUAL(pTrack.data().nMeasurements, 17);
189 
190  t.nHoles() = 34;
191  BOOST_CHECK_EQUAL(pTrack.data().nHoles, 34);
192 
193  t.chi2() = 882.3f;
194  BOOST_CHECK_EQUAL(pTrack.data().chi2, 882.3f);
195 
196  t.nDoF() = 9;
197  BOOST_CHECK_EQUAL(pTrack.data().ndf, 9);
198 
199  t.nOutliers() = 77;
200  BOOST_CHECK_EQUAL(pTrack.data().nOutliers, 77);
201 
202  t.nSharedHits() = 99;
203  BOOST_CHECK_EQUAL(pTrack.data().nSharedHits, 99);
204 
206  t.setReferenceSurface(free);
207  const auto& free2 = t.referenceSurface();
208  BOOST_CHECK_EQUAL(free->center(gctx), free2.center(gctx));
209 
210  const auto* rBounds2 =
211  dynamic_cast<const RectangleBounds*>(&free2.bounds());
212  BOOST_REQUIRE_NE(rBounds2, nullptr);
213 
214  BOOST_CHECK_EQUAL(rBounds2->halfLengthX(), rBounds->halfLengthX());
215  BOOST_CHECK_EQUAL(rBounds2->halfLengthY(), rBounds->halfLengthY());
216 
217  BOOST_CHECK_EQUAL(pTrack.getReferenceSurface().identifier,
219 
220  auto t2 = tc.getTrack(tc.addTrack());
221  auto t3 = tc.getTrack(tc.addTrack());
222  BOOST_CHECK_EQUAL(tc.size(), 3);
223 
224  // Register surface "with the detector"
225  helper.surfaces[666] = free.get();
226  t2.setReferenceSurface(free);
227  auto pTrack2 = tracks.at(1);
228  BOOST_CHECK_EQUAL(pTrack2.getReferenceSurface().identifier, 666);
229 
230  t.component<int32_t, "int_column"_hash>() = -11;
231  t2.component<int32_t, "int_column"_hash>() = 42;
232  t3.component<int32_t, "int_column"_hash>() = -98;
233 
234  t.component<float, "float_column"_hash>() = -11.2f;
235  t2.component<float, "float_column"_hash>() = 42.4f;
236  t3.component<float, "float_column"_hash>() = -98.9f;
237 
238  ptc.releaseInto(frame);
239  tsc.releaseInto(frame);
240 
241  BOOST_REQUIRE_NE(frame.get("tracks"), nullptr);
242  BOOST_CHECK_EQUAL(frame.get("tracks")->size(), 3);
243  BOOST_REQUIRE_NE(frame.get("tracks_extra__int_column"), nullptr);
244  BOOST_REQUIRE_NE(frame.get("tracks_extra__float_column"), nullptr);
245 
246  BOOST_REQUIRE_NE(frame.get("trackStates"), nullptr);
247  BOOST_CHECK_EQUAL(frame.get("trackStates")->size(), 3);
248  }
249 
250  {
251  Acts::ConstPodioTrackStateContainer tsc{helper, frame};
252  Acts::ConstPodioTrackContainer ptc{helper, frame};
253  // const ActsPodioEdm::TrackCollection& tracks = ptc.trackCollection();
254 
255  Acts::TrackContainer tc{ptc, tsc};
256 
257  BOOST_CHECK(tc.hasColumn("int_column"_hash));
258  BOOST_CHECK(tc.hasColumn("float_column"_hash));
259 
260  BOOST_CHECK_EQUAL(tc.size(), 3);
261 
262  auto t = tc.getTrack(0);
263  const auto& freeRecreated = t.referenceSurface();
264  // Not the exact same surface, it's recreated from values
265  BOOST_CHECK_NE(free.get(), &freeRecreated);
266 
267  BOOST_CHECK_EQUAL(t.nMeasurements(), 17);
268 
269  BOOST_CHECK_EQUAL(t.nHoles(), 34);
270 
271  BOOST_CHECK_EQUAL(t.chi2(), 882.3f);
272 
273  BOOST_CHECK_EQUAL(t.nDoF(), 9);
274 
275  BOOST_CHECK_EQUAL(t.nOutliers(), 77);
276 
277  BOOST_CHECK_EQUAL(t.nSharedHits(), 99);
278 
279  BOOST_CHECK_EQUAL(t.tipIndex(), 2);
280  BOOST_CHECK_EQUAL(t.nTrackStates(), 3);
281 
282  auto t2 = tc.getTrack(1);
283  // Is the exact same surface, because it's looked up in the "detector"
284  BOOST_CHECK_EQUAL(free.get(), &t2.referenceSurface());
285  BoundVector bv;
286  bv << 1, 2, 3, 4, 5, 6;
287  BOOST_CHECK_EQUAL(t.parameters(), bv);
288 
289  BOOST_CHECK_EQUAL(t.covariance(), refCov);
290 
291  auto t3 = tc.getTrack(2);
292  BOOST_CHECK(!t3.hasReferenceSurface());
293 
294  BOOST_CHECK_EQUAL((t.component<int32_t, "int_column"_hash>()), -11);
295  BOOST_CHECK_EQUAL((t2.component<int32_t, "int_column"_hash>()), 42);
296  BOOST_CHECK_EQUAL((t3.component<int32_t, "int_column"_hash>()), -98);
297 
298  BOOST_CHECK_EQUAL((t.component<float, "float_column"_hash>()), -11.2f);
299  BOOST_CHECK_EQUAL((t2.component<float, "float_column"_hash>()), 42.4f);
300  BOOST_CHECK_EQUAL((t3.component<float, "float_column"_hash>()), -98.9f);
301  }
302 }
303 
304 // @TODO: Add ensure dynamic columns
305 
306 BOOST_AUTO_TEST_SUITE_END()