File indexing completed on 2025-10-13 08:18:26
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Definitions/Algebra.hpp"
0010 #include "Acts/Detector/CuboidalContainerBuilder.hpp"
0011 #include "Acts/Detector/CylindricalContainerBuilder.hpp"
0012 #include "Acts/Detector/Detector.hpp"
0013 #include "Acts/Detector/DetectorBuilder.hpp"
0014 #include "Acts/Detector/DetectorVolume.hpp"
0015 #include "Acts/Detector/DetectorVolumeBuilder.hpp"
0016 #include "Acts/Detector/GeometryIdGenerator.hpp"
0017 #include "Acts/Detector/IndexedRootVolumeFinderBuilder.hpp"
0018 #include "Acts/Detector/KdtSurfacesProvider.hpp"
0019 #include "Acts/Detector/LayerStructureBuilder.hpp"
0020 #include "Acts/Detector/VolumeStructureBuilder.hpp"
0021 #include "Acts/Detector/interface/IDetectorBuilder.hpp"
0022 #include "Acts/Detector/interface/IDetectorComponentBuilder.hpp"
0023 #include "Acts/Detector/interface/IExternalStructureBuilder.hpp"
0024 #include "Acts/Detector/interface/IGeometryIdGenerator.hpp"
0025 #include "Acts/Detector/interface/IInternalStructureBuilder.hpp"
0026 #include "Acts/Detector/interface/IRootVolumeFinderBuilder.hpp"
0027 #include "Acts/Geometry/CylinderVolumeBounds.hpp"
0028 #include "Acts/Geometry/CylinderVolumeStack.hpp"
0029 #include "Acts/Geometry/Extent.hpp"
0030 #include "Acts/Geometry/GeometryContext.hpp"
0031 #include "Acts/Geometry/GeometryHierarchyMap.hpp"
0032 #include "Acts/Geometry/GeometryIdentifier.hpp"
0033 #include "Acts/Geometry/Portal.hpp"
0034 #include "Acts/Geometry/PortalLinkBase.hpp"
0035 #include "Acts/Geometry/PortalShell.hpp"
0036 #include "Acts/Geometry/ProtoLayer.hpp"
0037 #include "Acts/Geometry/TrackingGeometry.hpp"
0038 #include "Acts/Geometry/TrackingGeometryVisitor.hpp"
0039 #include "Acts/Geometry/Volume.hpp"
0040 #include "Acts/Geometry/VolumeAttachmentStrategy.hpp"
0041 #include "Acts/Geometry/VolumeBounds.hpp"
0042 #include "Acts/Geometry/VolumeResizeStrategy.hpp"
0043 #include "Acts/Material/ISurfaceMaterial.hpp"
0044 #include "Acts/Surfaces/Surface.hpp"
0045 #include "Acts/Surfaces/SurfaceArray.hpp"
0046 #include "Acts/Utilities/AxisDefinitions.hpp"
0047 #include "Acts/Utilities/Helpers.hpp"
0048 #include "Acts/Utilities/RangeXD.hpp"
0049 #include "Acts/Visualization/ViewConfig.hpp"
0050 #include "ActsExamples/Geometry/VolumeAssociationTest.hpp"
0051 #include "ActsPython/Utilities/Helpers.hpp"
0052 #include "ActsPython/Utilities/Macros.hpp"
0053
0054 #include <array>
0055 #include <memory>
0056 #include <numbers>
0057 #include <unordered_map>
0058 #include <vector>
0059
0060 #include <boost/algorithm/string/join.hpp>
0061 #include <pybind11/pybind11.h>
0062 #include <pybind11/stl.h>
0063
0064 namespace py = pybind11;
0065 using namespace pybind11::literals;
0066
0067 using namespace Acts;
0068 using namespace ActsExamples;
0069
0070 namespace {
0071 struct GeometryIdentifierHookBinding : public GeometryIdentifierHook {
0072 py::object callable;
0073
0074 GeometryIdentifier decorateIdentifier(GeometryIdentifier identifier,
0075 const Surface& surface) const override {
0076 return callable(identifier, surface.getSharedPtr())
0077 .cast<GeometryIdentifier>();
0078 }
0079 };
0080
0081 struct MaterialSurfaceSelector {
0082 std::vector<const Surface*> surfaces = {};
0083
0084
0085 void operator()(const Surface* surface) {
0086 if (surface->surfaceMaterial() != nullptr &&
0087 !rangeContainsValue(surfaces, surface)) {
0088 surfaces.push_back(surface);
0089 }
0090 }
0091 };
0092
0093 #define _INVOKE(method, name, arg) \
0094 pybind11::gil_scoped_acquire gil; \
0095 pybind11::function override = pybind11::get_override(this, name); \
0096 if (!override) { \
0097 method(arg); \
0098 return; \
0099 } \
0100 override(&arg);
0101
0102
0103
0104 class PyTrackingGeometryVisitor : public TrackingGeometryMutableVisitor {
0105 public:
0106 void visitVolume(TrackingVolume& volume) override {
0107 _INVOKE(TrackingGeometryMutableVisitor::visitVolume, "visitVolume", volume);
0108 }
0109
0110 void visitPortal(Portal& portal) override {
0111 _INVOKE(TrackingGeometryMutableVisitor::visitPortal, "visitPortal", portal);
0112 }
0113
0114 void visitLayer(Layer& layer) override {
0115 _INVOKE(TrackingGeometryMutableVisitor::visitLayer, "visitLayer", layer);
0116 }
0117
0118 void visitSurface(Surface& surface) override {
0119 _INVOKE(TrackingGeometryMutableVisitor::visitSurface, "visitSurface",
0120 surface);
0121 }
0122 };
0123
0124 #undef _INVOKE
0125
0126 }
0127
0128 namespace ActsPython {
0129
0130
0131
0132 void addGeometry(py::module_& m) {
0133 {
0134 py::class_<GeometryContext>(m, "GeometryContext").def(py::init<>());
0135
0136 py::class_<GeometryIdentifier>(m, "GeometryIdentifier")
0137 .def(py::init<>())
0138 .def(py::init<GeometryIdentifier::Value>())
0139 .def(py::init([](int volume, int boundary, int layer, int approach,
0140 int sensitive, int extra) {
0141 return GeometryIdentifier()
0142 .withVolume(volume)
0143 .withBoundary(boundary)
0144 .withLayer(layer)
0145 .withApproach(approach)
0146 .withSensitive(sensitive)
0147 .withExtra(extra);
0148 }),
0149 py::arg("volume") = 0, py::arg("boundary") = 0,
0150 py::arg("layer") = 0, py::arg("approach") = 0,
0151 py::arg("sensitive") = 0, py::arg("extra") = 0)
0152 .def_property(
0153 "layer", &GeometryIdentifier::layer,
0154 [](GeometryIdentifier& self, GeometryIdentifier::Value value) {
0155 self = self.withLayer(value);
0156 })
0157 .def_property(
0158 "volume", &GeometryIdentifier::volume,
0159 [](GeometryIdentifier& self, GeometryIdentifier::Value value) {
0160 self = self.withVolume(value);
0161 })
0162 .def_property(
0163 "boundary", &GeometryIdentifier::boundary,
0164 [](GeometryIdentifier& self, GeometryIdentifier::Value value) {
0165 self = self.withBoundary(value);
0166 })
0167 .def_property(
0168 "approach", &GeometryIdentifier::approach,
0169 [](GeometryIdentifier& self, GeometryIdentifier::Value value) {
0170 self = self.withApproach(value);
0171 })
0172 .def_property(
0173 "sensitive", &GeometryIdentifier::sensitive,
0174 [](GeometryIdentifier& self, GeometryIdentifier::Value value) {
0175 self = self.withSensitive(value);
0176 })
0177 .def_property(
0178 "extra", &GeometryIdentifier::extra,
0179 [](GeometryIdentifier& self, GeometryIdentifier::Value value) {
0180 self = self.withExtra(value);
0181 })
0182 .def_property_readonly("value", &GeometryIdentifier::value)
0183 .def("__str__", [](const GeometryIdentifier& self) {
0184 std::stringstream ss;
0185 ss << self;
0186 return ss.str();
0187 });
0188 }
0189
0190 {
0191 py::enum_<VolumeBounds::BoundsType>(m, "VolumeBoundsType")
0192 .value("Cone", VolumeBounds::BoundsType::eCone)
0193 .value("Cuboid", VolumeBounds::BoundsType::eCuboid)
0194 .value("CutoutCylinder", VolumeBounds::BoundsType::eCutoutCylinder)
0195 .value("Cylinder", VolumeBounds::BoundsType::eCylinder)
0196 .value("GenericCuboid", VolumeBounds::BoundsType::eGenericCuboid)
0197 .value("Trapezoid", VolumeBounds::BoundsType::eTrapezoid)
0198 .value("Other", VolumeBounds::BoundsType::eOther);
0199 }
0200
0201 {
0202 auto trkGeo =
0203 py::class_<TrackingGeometry, std::shared_ptr<TrackingGeometry>>(
0204 m, "TrackingGeometry")
0205 .def(py::init([](const MutableTrackingVolumePtr& volPtr,
0206 std::shared_ptr<const IMaterialDecorator> matDec,
0207 const GeometryIdentifierHook& hook,
0208 Logging::Level level) {
0209 auto logger = getDefaultLogger("TrackingGeometry", level);
0210 auto obj = std::make_shared<TrackingGeometry>(
0211 volPtr, matDec.get(), hook, *logger);
0212 return obj;
0213 }))
0214 .def("visitSurfaces",
0215 [](TrackingGeometry& self, py::function& func) {
0216 self.visitSurfaces(func);
0217 })
0218 .def("geoIdSurfaceMap", &TrackingGeometry::geoIdSurfaceMap)
0219 .def("extractMaterialSurfaces",
0220 [](TrackingGeometry& self) {
0221 MaterialSurfaceSelector selector;
0222 self.visitSurfaces(selector, false);
0223 return selector.surfaces;
0224 })
0225 .def_property_readonly("highestTrackingVolume",
0226 &TrackingGeometry::highestTrackingVolumePtr)
0227 .def("visualize", &TrackingGeometry::visualize, py::arg("helper"),
0228 py::arg("gctx"), py::arg("viewConfig") = s_viewVolume,
0229 py::arg("portalViewConfig") = s_viewPortal,
0230 py::arg("sensitiveViewConfig") = s_viewSensitive);
0231
0232 using apply_ptr_t =
0233 void (TrackingGeometry::*)(TrackingGeometryMutableVisitor&);
0234
0235 trkGeo.def("apply", static_cast<apply_ptr_t>(&TrackingGeometry::apply));
0236 }
0237
0238 {
0239 py::class_<VolumeBounds, std::shared_ptr<VolumeBounds>>(m, "VolumeBounds")
0240 .def("type", &VolumeBounds::type)
0241 .def("__str__", [](const VolumeBounds& self) {
0242 std::stringstream ss;
0243 ss << self;
0244 return ss.str();
0245 });
0246
0247 auto cvb =
0248 py::class_<CylinderVolumeBounds, std::shared_ptr<CylinderVolumeBounds>,
0249 VolumeBounds>(m, "CylinderVolumeBounds")
0250 .def(py::init<double, double, double, double, double, double,
0251 double>(),
0252 "rmin"_a, "rmax"_a, "halfz"_a, "halfphi"_a = std::numbers::pi,
0253 "avgphi"_a = 0., "bevelMinZ"_a = 0., "bevelMaxZ"_a = 0.);
0254
0255 py::enum_<CylinderVolumeBounds::Face>(cvb, "Face")
0256 .value("PositiveDisc", CylinderVolumeBounds::Face::PositiveDisc)
0257 .value("NegativeDisc", CylinderVolumeBounds::Face::NegativeDisc)
0258 .value("OuterCylinder", CylinderVolumeBounds::Face::OuterCylinder)
0259 .value("InnerCylinder", CylinderVolumeBounds::Face::InnerCylinder)
0260 .value("NegativePhiPlane", CylinderVolumeBounds::Face::NegativePhiPlane)
0261 .value("PositivePhiPlane",
0262 CylinderVolumeBounds::Face::PositivePhiPlane);
0263 }
0264
0265 {
0266 py::class_<Volume, std::shared_ptr<Volume>>(m, "Volume");
0267
0268 py::class_<TrackingVolume, Volume, std::shared_ptr<TrackingVolume>>(
0269 m, "TrackingVolume")
0270 .def(py::init<const Transform3&, std::shared_ptr<VolumeBounds>,
0271 std::string>());
0272 }
0273
0274 {
0275 py::class_<GeometryIdentifierHook, std::shared_ptr<GeometryIdentifierHook>>(
0276 m, "GeometryIdentifierHook")
0277 .def(py::init([](py::object callable) {
0278 auto hook = std::make_shared<GeometryIdentifierHookBinding>();
0279 hook->callable = callable;
0280 return hook;
0281 }));
0282 }
0283
0284 {
0285 py::class_<TrackingGeometryMutableVisitor, PyTrackingGeometryVisitor,
0286 std::shared_ptr<TrackingGeometryMutableVisitor>>(
0287 m, "TrackingGeometryMutableVisitor")
0288 .def(py::init<>());
0289 }
0290
0291 py::class_<ExtentEnvelope>(m, "ExtentEnvelope")
0292 .def(py::init<>())
0293 .def(py::init<const Envelope&>())
0294 .def(py::init([](Envelope x, Envelope y, Envelope z, Envelope r,
0295 Envelope phi, Envelope rPhi, Envelope theta,
0296 Envelope eta, Envelope mag) {
0297 return ExtentEnvelope({.x = x,
0298 .y = y,
0299 .z = z,
0300 .r = r,
0301 .phi = phi,
0302 .rPhi = rPhi,
0303 .theta = theta,
0304 .eta = eta,
0305 .mag = mag});
0306 }),
0307 py::arg("x") = zeroEnvelope, py::arg("y") = zeroEnvelope,
0308 py::arg("z") = zeroEnvelope, py::arg("r") = zeroEnvelope,
0309 py::arg("phi") = zeroEnvelope, py::arg("rPhi") = zeroEnvelope,
0310 py::arg("theta") = zeroEnvelope, py::arg("eta") = zeroEnvelope,
0311 py::arg("mag") = zeroEnvelope)
0312 .def_static("Zero", &ExtentEnvelope::Zero)
0313 .def("__getitem__", [](ExtentEnvelope& self,
0314 AxisDirection bValue) { return self[bValue]; })
0315 .def("__setitem__", [](ExtentEnvelope& self, AxisDirection bValue,
0316 const Envelope& value) { self[bValue] = value; })
0317 .def("__str__", [](const ExtentEnvelope& self) {
0318 std::array<std::string, numAxisDirections()> values;
0319
0320 std::stringstream ss;
0321 for (AxisDirection val : allAxisDirections()) {
0322 ss << val << "=(" << self[val][0] << ", " << self[val][1] << ")";
0323 values.at(toUnderlying(val)) = ss.str();
0324 ss.str("");
0325 }
0326
0327 ss.str("");
0328 ss << "ExtentEnvelope(";
0329 ss << boost::algorithm::join(values, ", ");
0330 ss << ")";
0331 return ss.str();
0332 });
0333
0334 py::class_<Extent>(m, "Extent")
0335 .def(py::init<const ExtentEnvelope&>(),
0336 py::arg("envelope") = ExtentEnvelope::Zero())
0337 .def("range",
0338 [](const Extent& self, AxisDirection bval) -> std::array<double, 2> {
0339 return {self.min(bval), self.max(bval)};
0340 })
0341 .def("setRange",
0342 [](Extent& self, AxisDirection bval,
0343 const std::array<double, 2>& range) {
0344 self.set(bval, range[0], range[1]);
0345 })
0346 .def("__str__", &Extent::toString);
0347
0348 {
0349 py::enum_<VolumeAttachmentStrategy>(m, "VolumeAttachmentStrategy")
0350 .value("Gap", VolumeAttachmentStrategy::Gap)
0351 .value("First", VolumeAttachmentStrategy::First)
0352 .value("Second", VolumeAttachmentStrategy::Second)
0353 .value("Midpoint", VolumeAttachmentStrategy::Midpoint);
0354
0355 py::enum_<VolumeResizeStrategy>(m, "VolumeResizeStrategy")
0356 .value("Gap", VolumeResizeStrategy::Gap)
0357 .value("Expand", VolumeResizeStrategy::Expand);
0358 }
0359
0360 py::class_<PortalShellBase>(m, "PortalShellBase");
0361
0362 py::class_<ProtoLayer>(m, "ProtoLayer")
0363 .def(py::init<const GeometryContext&,
0364 const std::vector<std::shared_ptr<Surface>>&,
0365 const Transform3&>(),
0366 "gctx"_a, "surfaces"_a, "transform"_a = Transform3::Identity())
0367 .def("min", &ProtoLayer::min, "bval"_a, "addenv"_a = true)
0368 .def("max", &ProtoLayer::max, "bval"_a, "addenv"_a = true)
0369 .def_property_readonly("surfaces", &ProtoLayer::surfaces);
0370 }
0371
0372 }