Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Geometry.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file Geometry.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2021 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 
27 #include "Acts/Geometry/Extent.hpp"
32 #include "Acts/Geometry/Volume.hpp"
39 
40 #include <array>
41 #include <memory>
42 #include <vector>
43 
44 #include <pybind11/pybind11.h>
45 #include <pybind11/stl.h>
46 
47 namespace py = pybind11;
48 using namespace pybind11::literals;
49 
50 namespace {
51 struct GeometryIdentifierHookBinding : public Acts::GeometryIdentifierHook {
52  py::object callable;
53 
54  Acts::GeometryIdentifier decorateIdentifier(
56  const Acts::Surface& surface) const override {
57  return callable(identifier, surface.getSharedPtr())
58  .cast<Acts::GeometryIdentifier>();
59  }
60 };
61 } // namespace
62 
63 namespace Acts::Python {
64 void addGeometry(Context& ctx) {
65  auto m = ctx.get("main");
66 
67  {
68  py::class_<Acts::GeometryIdentifier>(m, "GeometryIdentifier")
69  .def(py::init<>())
70  .def(py::init<Acts::GeometryIdentifier::Value>())
71  .def("setVolume", &Acts::GeometryIdentifier::setVolume)
72  .def("setLayer", &Acts::GeometryIdentifier::setLayer)
73  .def("setBoundary", &Acts::GeometryIdentifier::setBoundary)
74  .def("setApproach", &Acts::GeometryIdentifier::setApproach)
75  .def("setSensitive", &Acts::GeometryIdentifier::setSensitive)
76  .def("setExtra", &Acts::GeometryIdentifier::setExtra)
77  .def("volume", &Acts::GeometryIdentifier::volume)
78  .def("layer", &Acts::GeometryIdentifier::layer)
79  .def("boundary", &Acts::GeometryIdentifier::boundary)
80  .def("approach", &Acts::GeometryIdentifier::approach)
81  .def("sensitive", &Acts::GeometryIdentifier::sensitive)
82  .def("extra", &Acts::GeometryIdentifier::extra);
83  }
84 
85  {
86  py::class_<Acts::Surface, std::shared_ptr<Acts::Surface>>(m, "Surface")
87  .def("geometryId",
88  [](Acts::Surface& self) { return self.geometryId(); })
89  .def("center",
90  [](Acts::Surface& self) {
91  return self.center(Acts::GeometryContext{});
92  })
93  .def("type", [](Acts::Surface& self) { return self.type(); });
94  }
95 
96  {
97  py::enum_<Acts::Surface::SurfaceType>(m, "SurfaceType")
98  .value("Cone", Acts::Surface::SurfaceType::Cone)
99  .value("Cylinder", Acts::Surface::SurfaceType::Cylinder)
100  .value("Disc", Acts::Surface::SurfaceType::Disc)
101  .value("Perigee", Acts::Surface::SurfaceType::Perigee)
102  .value("Plane", Acts::Surface::SurfaceType::Plane)
103  .value("Straw", Acts::Surface::SurfaceType::Straw)
104  .value("Curvilinear", Acts::Surface::SurfaceType::Curvilinear)
105  .value("Other", Acts::Surface::SurfaceType::Other);
106  }
107 
108  {
109  py::enum_<Acts::VolumeBounds::BoundsType>(m, "VolumeBoundsType")
110  .value("Cone", Acts::VolumeBounds::BoundsType::eCone)
111  .value("Cuboid", Acts::VolumeBounds::BoundsType::eCuboid)
112  .value("CutoutCylinder",
113  Acts::VolumeBounds::BoundsType::eCutoutCylinder)
114  .value("Cylinder", Acts::VolumeBounds::BoundsType::eCylinder)
115  .value("GenericCuboid", Acts::VolumeBounds::BoundsType::eGenericCuboid)
116  .value("Trapezoid", Acts::VolumeBounds::BoundsType::eTrapezoid)
117  .value("Other", Acts::VolumeBounds::BoundsType::eOther);
118  }
119 
120  {
121  py::class_<Acts::TrackingGeometry, std::shared_ptr<Acts::TrackingGeometry>>(
122  m, "TrackingGeometry")
123  .def("visitSurfaces",
124  [](Acts::TrackingGeometry& self, py::function& func) {
125  self.visitSurfaces(func);
126  })
127  .def_property_readonly(
128  "worldVolume",
130  }
131 
132  {
133  py::class_<Acts::Volume, std::shared_ptr<Acts::Volume>>(m, "Volume")
134  .def_static(
135  "makeCylinderVolume",
136  [](double r, double halfZ) {
137  auto bounds =
138  std::make_shared<Acts::CylinderVolumeBounds>(0, r, halfZ);
139  return std::make_shared<Acts::Volume>(Transform3::Identity(),
140  bounds);
141  },
142  "r"_a, "halfZ"_a);
143  }
144 
145  {
147  std::shared_ptr<Acts::TrackingVolume>>(m, "TrackingVolume");
148  }
149 
150  {
151  py::class_<Acts::GeometryIdentifierHook,
152  std::shared_ptr<Acts::GeometryIdentifierHook>>(
153  m, "GeometryIdentifierHook")
154  .def(py::init([](py::object callable) {
155  auto hook = std::make_shared<GeometryIdentifierHookBinding>();
156  hook->callable = callable;
157  return hook;
158  }));
159  }
160 
161  {
162  py::class_<Acts::Extent>(m, "Extent")
163  .def(py::init(
164  [](const std::vector<std::tuple<Acts::BinningValue,
165  std::array<Acts::ActsScalar, 2u>>>&
166  franges) {
167  Acts::Extent extent;
168  for (const auto& [bval, frange] : franges) {
169  extent.set(bval, frange[0], frange[1]);
170  }
171  return extent;
172  }))
173  .def("range", [](const Acts::Extent& self, Acts::BinningValue bval) {
174  return std::array<Acts::ActsScalar, 2u>{self.min(bval),
175  self.max(bval)};
176  });
177  }
178 }
179 
181  auto [m, mex] = ctx.get("main", "examples");
182 
183  using namespace Acts::Experimental;
184 
185  // Detector definition
186  py::class_<Detector, std::shared_ptr<Detector>>(m, "Detector");
187 
188  // Detector volume definition
189  py::class_<DetectorVolume, std::shared_ptr<DetectorVolume>>(m,
190  "DetectorVolume");
191 
192  {
193  // The surface hierarchy map
194  using SurfaceHierarchyMap =
196 
197  py::class_<SurfaceHierarchyMap, std::shared_ptr<SurfaceHierarchyMap>>(
198  m, "SurfaceHierarchyMap");
199 
200  // Extract volume / layer surfaces
201  mex.def("extractVolumeLayerSurfaces", [](const SurfaceHierarchyMap& smap,
202  bool sensitiveOnly) {
203  std::map<unsigned int,
204  std::map<unsigned int, std::vector<std::shared_ptr<Surface>>>>
205  surfaceVolumeLayerMap;
206  for (const auto& surface : smap) {
207  auto gid = surface->geometryId();
208  // Exclusion criteria
209  if (sensitiveOnly and gid.sensitive() == 0) {
210  continue;
211  };
212  surfaceVolumeLayerMap[gid.volume()][gid.layer()].push_back(surface);
213  }
214  // Return the surface volume map
215  return surfaceVolumeLayerMap;
216  });
217  }
218 
219  {
220  // Be able to construct a proto binning
221  py::class_<ProtoBinning>(m, "ProtoBinning")
223  const std::vector<Acts::ActsScalar>&, std::size_t>())
225  Acts::ActsScalar, Acts::ActsScalar, std::size_t,
226  std::size_t>());
227  }
228 
229  {
230  // The internal layer structure builder
232  std::shared_ptr<Acts::Experimental::IInternalStructureBuilder>>(
233  m, "IInternalStructureBuilder");
234 
235  auto lsBuilder =
236  py::class_<LayerStructureBuilder,
237  Acts::Experimental::IInternalStructureBuilder,
238  std::shared_ptr<LayerStructureBuilder>>(
239  m, "LayerStructureBuilder")
241  const std::string& name,
243  return std::make_shared<LayerStructureBuilder>(
244  config, getDefaultLogger(name, level));
245  }));
246 
247  auto lsConfig =
248  py::class_<LayerStructureBuilder::Config>(lsBuilder, "Config")
249  .def(py::init<>());
250 
252  ACTS_PYTHON_MEMBER(surfacesProvider);
253  ACTS_PYTHON_MEMBER(supports);
254  ACTS_PYTHON_MEMBER(binnings);
255  ACTS_PYTHON_MEMBER(nSegments);
256  ACTS_PYTHON_MEMBER(auxiliary);
258 
259  // The internal layer structure builder
261  std::shared_ptr<Acts::Experimental::ISurfacesProvider>>(
262  m, "ISurfacesProvider");
263 
265  Acts::Experimental::ISurfacesProvider,
266  std::shared_ptr<LayerStructureBuilder::SurfacesHolder>>(
267  lsBuilder, "SurfacesHolder")
268  .def(py::init<std::vector<std::shared_ptr<Surface>>>());
269  }
270 
271  {
272  using Range2D = Acts::RangeXD<2u, Acts::ActsScalar>;
273  using KdtSurfaces2D = Acts::Experimental::KdtSurfaces<2u, 100u>;
274  using KdtSurfacesProvider2D =
276 
277  py::class_<Range2D>(m, "Range2D")
278  .def(py::init([](const std::array<Acts::ActsScalar, 2u>& range0,
279  const std::array<Acts::ActsScalar, 2u>& range1) {
280  Range2D range;
281  range[0].shrink(range0[0], range0[1]);
282  range[1].shrink(range1[0], range1[1]);
283  return range;
284  }));
285 
286  py::class_<KdtSurfaces2D, std::shared_ptr<KdtSurfaces2D>>(m,
287  "KdtSurfaces2D")
288  .def(py::init<const GeometryContext&,
289  const std::vector<std::shared_ptr<Acts::Surface>>&,
290  const std::array<Acts::BinningValue, 2u>&>())
291  .def("surfaces", [](KdtSurfaces2D& self, const Range2D& range) {
292  return self.surfaces(range);
293  });
294 
295  py::class_<KdtSurfacesProvider2D, Acts::Experimental::ISurfacesProvider,
296  std::shared_ptr<KdtSurfacesProvider2D>>(m,
297  "KdtSurfacesProvider2D")
298  .def(py::init(
299  [](std::shared_ptr<KdtSurfaces2D> kdt, const Extent& extent) {
300  return std::make_shared<KdtSurfacesProvider2D>(kdt, extent);
301  }));
302  }
303 
304  {
305  // The external volume structure builder
307  std::shared_ptr<Acts::Experimental::IExternalStructureBuilder>>(
308  m, "IExternalStructureBuilder");
309 
310  auto vsBuilder =
311  py::class_<VolumeStructureBuilder,
312  Acts::Experimental::IExternalStructureBuilder,
313  std::shared_ptr<VolumeStructureBuilder>>(
314  m, "VolumeStructureBuilder")
316  const std::string& name,
318  return std::make_shared<VolumeStructureBuilder>(
319  config, getDefaultLogger(name, level));
320  }));
321 
322  auto vsConfig =
323  py::class_<VolumeStructureBuilder::Config>(vsBuilder, "Config")
324  .def(py::init<>());
325 
327  ACTS_PYTHON_MEMBER(boundsType);
328  ACTS_PYTHON_MEMBER(boundValues);
330  ACTS_PYTHON_MEMBER(auxiliary);
332  }
333 
334  {
336  std::shared_ptr<Acts::Experimental::IGeometryIdGenerator>>(
337  m, "IGeometryIdGenerator");
338 
339  auto geoIdGen =
341  Acts::Experimental::IGeometryIdGenerator,
342  std::shared_ptr<Acts::Experimental::GeometryIdGenerator>>(
343  m, "GeometryIdGenerator")
345  config,
346  const std::string& name,
348  return std::make_shared<Acts::Experimental::GeometryIdGenerator>(
349  config, getDefaultLogger(name, level));
350  }));
351 
352  auto geoIdGenConfig =
353  py::class_<Acts::Experimental::GeometryIdGenerator::Config>(geoIdGen,
354  "Config")
355  .def(py::init<>());
356 
357  ACTS_PYTHON_STRUCT_BEGIN(geoIdGenConfig,
359  ACTS_PYTHON_MEMBER(containerMode);
360  ACTS_PYTHON_MEMBER(containerId);
361  ACTS_PYTHON_MEMBER(resetSubCounters);
362  ACTS_PYTHON_MEMBER(overrideExistingIds);
364  }
365 
366  {
367  // Put them together to a detector volume
369  std::shared_ptr<Acts::Experimental::IDetectorComponentBuilder>>(
370  m, "IDetectorComponentBuilder");
371 
372  auto dvBuilder =
373  py::class_<DetectorVolumeBuilder,
374  Acts::Experimental::IDetectorComponentBuilder,
375  std::shared_ptr<DetectorVolumeBuilder>>(
376  m, "DetectorVolumeBuilder")
378  const std::string& name,
380  return std::make_shared<DetectorVolumeBuilder>(
381  config, getDefaultLogger(name, level));
382  }))
383  .def("construct", &DetectorVolumeBuilder::construct);
384 
385  auto dvConfig =
386  py::class_<DetectorVolumeBuilder::Config>(dvBuilder, "Config")
387  .def(py::init<>());
388 
390  ACTS_PYTHON_MEMBER(name);
391  ACTS_PYTHON_MEMBER(internalsBuilder);
392  ACTS_PYTHON_MEMBER(externalsBuilder);
393  ACTS_PYTHON_MEMBER(geoIdGenerator);
394  ACTS_PYTHON_MEMBER(auxiliary);
396  }
397 
398  {
399  // The external volume structure builder
401  std::shared_ptr<Acts::Experimental::IRootVolumeFinderBuilder>>(
402  m, "IRootVolumeFinderBuilder");
403 
404  auto irvBuilder =
406  Acts::Experimental::IRootVolumeFinderBuilder,
407  std::shared_ptr<
408  Acts::Experimental::IndexedRootVolumeFinderBuilder>>(
409  m, "IndexedRootVolumeFinderBuilder")
410  .def(py::init<std::vector<Acts::BinningValue>>());
411  }
412 
413  {
414  // Cylindrical container builder
415  auto ccBuilder =
416  py::class_<CylindricalContainerBuilder,
418  std::shared_ptr<CylindricalContainerBuilder>>(
419  m, "CylindricalContainerBuilder")
421  const std::string& name,
423  return std::make_shared<CylindricalContainerBuilder>(
424  config, getDefaultLogger(name, level));
425  }))
426  .def("construct", &CylindricalContainerBuilder::construct);
427 
428  auto ccConfig =
429  py::class_<CylindricalContainerBuilder::Config>(ccBuilder, "Config")
430  .def(py::init<>());
431 
433  ACTS_PYTHON_MEMBER(builders);
434  ACTS_PYTHON_MEMBER(binning);
435  ACTS_PYTHON_MEMBER(rootVolumeFinderBuilder);
436  ACTS_PYTHON_MEMBER(geoIdGenerator);
437  ACTS_PYTHON_MEMBER(geoIdReverseGen);
438  ACTS_PYTHON_MEMBER(auxiliary);
440  }
441 
442  {
443  // Detector builder
444  auto dBuilder =
445  py::class_<DetectorBuilder, std::shared_ptr<DetectorBuilder>>(
446  m, "DetectorBuilder")
447  .def(py::init([](const DetectorBuilder::Config& config,
448  const std::string& name,
450  return std::make_shared<DetectorBuilder>(
451  config, getDefaultLogger(name, level));
452  }))
453  .def("construct", &DetectorBuilder::construct);
454 
455  auto dConfig = py::class_<DetectorBuilder::Config>(dBuilder, "Config")
456  .def(py::init<>());
457 
459  ACTS_PYTHON_MEMBER(name);
460  ACTS_PYTHON_MEMBER(builder);
461  ACTS_PYTHON_MEMBER(geoIdGenerator);
462  ACTS_PYTHON_MEMBER(auxiliary);
464  }
465 
467  "VolumeAssociationTest", name, ntests,
468  randomNumbers, randomRange, detector);
469 }
470 
471 } // namespace Acts::Python