Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PodioUtil.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file PodioUtil.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 
10 
31 #include "ActsPodioEdm/Surface.h"
32 
33 #include <limits>
34 #include <memory>
35 
36 namespace Acts::PodioUtil {
37 
38 namespace {
39 template <typename bounds_t>
40 std::shared_ptr<const bounds_t> createBounds(
42  constexpr size_t S = bounds_t::eSize;
43  throw_assert(surface.boundValuesSize == S,
44  "Unexpected number of bound values");
45 
46  std::array<double, S> values{};
47  for (size_t i = 0; i < S; i++) {
48  values.at(i) = surface.boundValues.at(i);
49  }
50  return std::make_shared<bounds_t>(values);
51 }
52 } // namespace
53 
55  const Acts::Surface& surface) {
56  ActsPodioEdm::Surface result;
57 
58  std::optional<Identifier> identifier = helper.surfaceToIdentifier(surface);
59  if (identifier.has_value()) {
60  result.identifier = identifier.value();
61  } else {
62  result.identifier = kNoIdentifier;
63  assert(surface.associatedDetectorElement() == nullptr &&
64  "Unidentified surface does not have detector element");
65  // @TODO: Surface type is not well-defined for curvilinear surface: looks like any plane surface
66  result.surfaceType = surface.type();
67  // @TODO: Test line bounds, does not have bounds, so nullptr
68  result.boundsType = surface.bounds().type();
69  result.geometryId = surface.geometryId().value();
70  auto values = surface.bounds().values();
71 
72  if (values.size() > result.boundValues.size()) {
73  throw std::runtime_error{"Too many bound values to store"};
74  }
75 
76  for (size_t i = 0; i < values.size(); i++) {
77  result.boundValues.at(i) = values.at(i);
78  }
79  result.boundValuesSize = values.size();
80 
81  Eigen::Map<ActsSquareMatrix<4>> trf{result.transform.data()};
82 
83  // This is safe ONLY(!) if there is no associated detector element, since
84  // the surface will not inspect the geometry context at all by itself.
86  trf = surface.transform(gctx).matrix();
87  }
88 
89  return result;
90 }
91 
92 std::shared_ptr<const Surface> convertSurfaceFromPodio(
93  const ConversionHelper& helper, const ActsPodioEdm::Surface& surface) {
94  if (surface.surfaceType == kNoSurface) {
95  return nullptr;
96  }
97 
98  Eigen::Map<const ActsSquareMatrix<4>> mat{surface.transform.data()};
99  Transform3 transform{mat};
100 
101  using T = Surface::SurfaceType;
102  using B = SurfaceBounds;
103 
104  std::shared_ptr<const Surface> result;
105 
106  if (const Surface* srf = helper.identifierToSurface(surface.identifier);
107  srf != nullptr) {
108  result = srf->getSharedPtr();
109  }
110 
111  if (result) {
112  return result;
113  }
114 
115  switch (surface.surfaceType) {
116  default:
117  throw std::runtime_error{"Invalid surface type encountered"};
118 
119  case T::Cone:
120  throw_assert(surface.boundsType == B::eCone, "Unexpected bounds type");
121  result = Acts::Surface::makeShared<ConeSurface>(
122  transform, createBounds<ConeBounds>(surface));
123  break;
124 
125  case T::Cylinder:
126  throw_assert(surface.boundsType == B::eCylinder,
127  "Unexpected bounds type");
128  result = Acts::Surface::makeShared<CylinderSurface>(
129  transform, createBounds<CylinderBounds>(surface));
130  break;
131 
132  case T::Disc: {
133  std::shared_ptr<const DiscBounds> dBounds;
134  switch (surface.boundsType) {
135  default:
136  throw std::runtime_error{"Invalid bounds type encountered"};
137 
138  case B::eDisc:
139  dBounds = createBounds<RadialBounds>(surface);
140  break;
141 
142  case B::eAnnulus:
143  dBounds = createBounds<AnnulusBounds>(surface);
144  break;
145 
146  case B::eDiscTrapezoid:
147  dBounds = createBounds<DiscTrapezoidBounds>(surface);
148  break;
149  }
150  result = Acts::Surface::makeShared<DiscSurface>(transform, dBounds);
151  break;
152  }
153 
154  case T::Perigee:
155  throw_assert(surface.boundsType == B::eBoundless,
156  "Unexpected bounds type");
157  result = Acts::Surface::makeShared<PerigeeSurface>(transform);
158  break;
159 
160  case T::Plane: {
161  std::shared_ptr<const PlanarBounds> pBounds;
162  switch (surface.boundsType) {
163  default:
164  throw std::runtime_error{"Invalid bounds type encountered"};
165 
166  case B::eDiamond:
167  pBounds = createBounds<DiamondBounds>(surface);
168  break;
169  case B::eEllipse:
170  pBounds = createBounds<EllipseBounds>(surface);
171  break;
172  case B::eRectangle:
173  pBounds = createBounds<RectangleBounds>(surface);
174  break;
175  case B::eConvexPolygon:
176  template_switch_lambda<6, 32>(surface.boundValuesSize, [&](auto N) {
177  constexpr size_t nValues = decltype(N)::value;
178  constexpr size_t nVertices = nValues / 2;
179  pBounds = createBounds<ConvexPolygonBounds<nVertices>>(surface);
180  });
181  // @TODO: Maybe handle dynamic convex polygons?
182  break;
183  }
184  assert(pBounds && "No PlanarBounds");
185  result = Acts::Surface::makeShared<PlaneSurface>(transform, pBounds);
186 
187  break;
188  }
189 
190  case T::Straw:
191  throw_assert(surface.boundsType == B::eLine, "Unexpected bounds type");
192  result = Acts::Surface::makeShared<StrawSurface>(
193  transform, createBounds<LineBounds>(surface));
194  break;
195 
196  case T::Curvilinear:
197  throw_assert(surface.boundsType == B::eBoundless,
198  "Unexpected bounds type");
199  result = Acts::Surface::makeShared<PlaneSurface>(transform);
200  break;
201  }
202 
203  return result;
204 }
205 
206 } // namespace Acts::PodioUtil