Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-10-13 08:18:26

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
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   /// @param surface is the test surface
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 // We only implement the mutable visitor here, because pybind11 always casts
0103 // away const ness in any case
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 }  // namespace
0127 
0128 namespace ActsPython {
0129 
0130 /// This adds the geometry bindings to the python module
0131 /// @param m the module to add the bindings to
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 }  // namespace ActsPython