Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-05 08:10:05

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2021-2024 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 http://mozilla.org/MPL/2.0/.
0008 
0009 #include "Acts/Definitions/Algebra.hpp"
0010 #include "Acts/Detector/Detector.hpp"
0011 #include "Acts/Geometry/TrackingGeometry.hpp"
0012 #include "Acts/MagneticField/MagneticFieldProvider.hpp"
0013 #include "Acts/Plugins/Geant4/Geant4DetectorElement.hpp"
0014 #include "Acts/Plugins/Geant4/Geant4DetectorSurfaceFactory.hpp"
0015 #include "Acts/Plugins/Geant4/Geant4PhysicalVolumeSelectors.hpp"
0016 #include "Acts/Plugins/Python/Utilities.hpp"
0017 #include "Acts/Utilities/Logger.hpp"
0018 #include "ActsExamples/Framework/AlgorithmContext.hpp"
0019 #include "ActsExamples/Framework/IContextDecorator.hpp"
0020 #include "ActsExamples/Geant4/DetectorConstructionFactory.hpp"
0021 #include "ActsExamples/Geant4/GdmlDetectorConstruction.hpp"
0022 #include "ActsExamples/Geant4/Geant4Manager.hpp"
0023 #include "ActsExamples/Geant4/Geant4Simulation.hpp"
0024 #include "ActsExamples/Geant4/RegionCreator.hpp"
0025 #include "ActsExamples/Geant4Detector/Geant4Detector.hpp"
0026 #include "ActsExamples/MuonSpectrometerMockupDetector/MockupSectorBuilder.hpp"
0027 #include "ActsExamples/TelescopeDetector/TelescopeDetector.hpp"
0028 #include "ActsExamples/TelescopeDetector/TelescopeG4DetectorConstruction.hpp"
0029 
0030 #include <array>
0031 #include <memory>
0032 #include <optional>
0033 #include <string>
0034 #include <tuple>
0035 #include <unordered_map>
0036 #include <utility>
0037 #include <vector>
0038 
0039 #include <G4RunManager.hh>
0040 #include <G4Transform3D.hh>
0041 #include <G4UserEventAction.hh>
0042 #include <G4UserRunAction.hh>
0043 #include <pybind11/pybind11.h>
0044 #include <pybind11/stl.h>
0045 
0046 class G4UserSteppingAction;
0047 class G4VUserPhysicsList;
0048 namespace Acts {
0049 class MagneticFieldProvider;
0050 class TrackingGeometry;
0051 class Volume;
0052 }  // namespace Acts
0053 namespace ActsExamples {
0054 class RandomNumbers;
0055 }  // namespace ActsExamples
0056 
0057 namespace py = pybind11;
0058 using namespace pybind11::literals;
0059 
0060 using namespace ActsExamples;
0061 using namespace Acts;
0062 using namespace Acts::Python;
0063 
0064 namespace Acts::Python {
0065 void addGeant4HepMC3(Context& ctx);
0066 }
0067 
0068 PYBIND11_MODULE(ActsPythonBindingsGeant4, mod) {
0069   py::class_<DetectorConstructionFactory,
0070              std::shared_ptr<DetectorConstructionFactory>>(
0071       mod, "DetectorConstructionFactory");
0072 
0073   py::class_<Geant4Manager, std::unique_ptr<Geant4Manager, py::nodelete>>(
0074       mod, "Geant4Manager")
0075       .def_static("instance", &Geant4Manager::instance,
0076                   py::return_value_policy::reference)
0077       .def("currentHandle", &Geant4Manager::currentHandle);
0078 
0079   py::class_<Geant4Handle, std::shared_ptr<Geant4Handle>>(mod, "Geant4Handle")
0080       .def("tweakLogging", &Geant4Handle::tweakLogging);
0081 
0082   {
0083     using Algorithm = Geant4SimulationBase;
0084     using Config = Algorithm::Config;
0085     auto alg =
0086         py::class_<Algorithm, IAlgorithm, std::shared_ptr<Algorithm>>(
0087             mod, "Geant4SimulationBase")
0088             .def_property_readonly("geant4Handle", &Algorithm::geant4Handle);
0089 
0090     auto c1 = py::class_<Config, std::shared_ptr<Config>>(alg, "Config")
0091                   .def(py::init<>());
0092     ACTS_PYTHON_STRUCT_BEGIN(c1, Config);
0093     ACTS_PYTHON_MEMBER(inputParticles);
0094     ACTS_PYTHON_MEMBER(randomNumbers);
0095     ACTS_PYTHON_MEMBER(detectorConstructionFactory);
0096     ACTS_PYTHON_MEMBER(geant4Handle);
0097     ACTS_PYTHON_STRUCT_END();
0098   }
0099 
0100   {
0101     using Algorithm = Geant4Simulation;
0102     using Config = Algorithm::Config;
0103     auto alg =
0104         py::class_<Algorithm, Geant4SimulationBase, std::shared_ptr<Algorithm>>(
0105             mod, "Geant4Simulation")
0106             .def(py::init<const Config&, Acts::Logging::Level>(),
0107                  py::arg("config"), py::arg("level"))
0108             .def_property_readonly("config", &Algorithm::config);
0109 
0110     auto c1 = py::class_<Config, Geant4SimulationBase::Config,
0111                          std::shared_ptr<Config>>(alg, "Config")
0112                   .def(py::init<>());
0113     ACTS_PYTHON_STRUCT_BEGIN(c1, Config);
0114     ACTS_PYTHON_MEMBER(outputSimHits);
0115     ACTS_PYTHON_MEMBER(outputParticlesInitial);
0116     ACTS_PYTHON_MEMBER(outputParticlesFinal);
0117     ACTS_PYTHON_MEMBER(trackingGeometry);
0118     ACTS_PYTHON_MEMBER(magneticField);
0119     ACTS_PYTHON_MEMBER(physicsList);
0120     ACTS_PYTHON_MEMBER(volumeMappings);
0121     ACTS_PYTHON_MEMBER(materialMappings);
0122     ACTS_PYTHON_MEMBER(killVolume);
0123     ACTS_PYTHON_MEMBER(killAfterTime);
0124     ACTS_PYTHON_MEMBER(killSecondaries);
0125     ACTS_PYTHON_MEMBER(recordHitsOfSecondaries);
0126     ACTS_PYTHON_MEMBER(keepParticlesWithoutHits);
0127     ACTS_PYTHON_STRUCT_END();
0128   }
0129 
0130   {
0131     using Algorithm = Geant4MaterialRecording;
0132     using Config = Algorithm::Config;
0133     auto alg =
0134         py::class_<Algorithm, Geant4SimulationBase, std::shared_ptr<Algorithm>>(
0135             mod, "Geant4MaterialRecording")
0136             .def(py::init<const Config&, Acts::Logging::Level>(),
0137                  py::arg("config"), py::arg("level"))
0138             .def_property_readonly("config", &Algorithm::config);
0139 
0140     auto c = py::class_<Config, Geant4SimulationBase::Config,
0141                         std::shared_ptr<Config>>(alg, "Config")
0142                  .def(py::init<>());
0143     ACTS_PYTHON_STRUCT_BEGIN(c, Config);
0144     ACTS_PYTHON_MEMBER(outputMaterialTracks);
0145     ACTS_PYTHON_MEMBER(excludeMaterials);
0146     ACTS_PYTHON_STRUCT_END();
0147   }
0148 
0149   {
0150     py::class_<GdmlDetectorConstructionFactory, DetectorConstructionFactory,
0151                std::shared_ptr<GdmlDetectorConstructionFactory>>(
0152         mod, "GdmlDetectorConstructionFactory")
0153         .def(py::init<std::string,
0154                       std::vector<std::shared_ptr<RegionCreator>>>(),
0155              py::arg("path"),
0156              py::arg("regionCreators") =
0157                  std::vector<std::shared_ptr<RegionCreator>>());
0158   }
0159 
0160   {
0161     py::class_<
0162         Telescope::TelescopeG4DetectorConstructionFactory,
0163         DetectorConstructionFactory,
0164         std::shared_ptr<Telescope::TelescopeG4DetectorConstructionFactory>>(
0165         mod, "TelescopeG4DetectorConstructionFactory")
0166         .def(py::init<const Telescope::TelescopeDetector::Config&,
0167                       std::vector<std::shared_ptr<RegionCreator>>>(),
0168              py::arg("cfg"),
0169              py::arg("regionCreators") =
0170                  std::vector<std::shared_ptr<RegionCreator>>());
0171   }
0172 
0173   {
0174     using ISelector = Acts::IGeant4PhysicalVolumeSelector;
0175     auto is = py::class_<ISelector, std::shared_ptr<ISelector>>(
0176         mod, "IVolumeSelector");
0177 
0178     using NameSelector = Acts::Geant4PhysicalVolumeSelectors::NameSelector;
0179     auto ns = py::class_<NameSelector, std::shared_ptr<NameSelector>>(
0180                   mod, "VolumeNameSelector", is)
0181                   .def(py::init<const std::vector<std::string>&, bool>());
0182 
0183     using Factory = Acts::Geant4DetectorSurfaceFactory;
0184     auto o = py::class_<Factory::Options>(mod, "SurfaceFactoryOptions")
0185                  .def(py::init<>());
0186     ACTS_PYTHON_STRUCT_BEGIN(o, Factory::Options);
0187     ACTS_PYTHON_MEMBER(scaleConversion);
0188     ACTS_PYTHON_MEMBER(convertMaterial);
0189     ACTS_PYTHON_MEMBER(convertedMaterialThickness);
0190     ACTS_PYTHON_MEMBER(sensitiveSurfaceSelector);
0191     ACTS_PYTHON_MEMBER(passiveSurfaceSelector);
0192     ACTS_PYTHON_STRUCT_END();
0193   }
0194 
0195   {
0196     py::class_<Acts::Geant4DetectorElement,
0197                std::shared_ptr<Acts::Geant4DetectorElement>>(
0198         mod, "Geant4DetectorElement");
0199 
0200     using Geant4Detector = Geant4::Geant4Detector;
0201 
0202     auto g =
0203         py::class_<Geant4Detector, std::shared_ptr<Geant4Detector>>(
0204             mod, "Geant4Detector")
0205             .def(py::init<>())
0206             .def(
0207                 "constructDetector",
0208                 [](Geant4Detector& self, const Geant4Detector::Config& cfg,
0209                    Logging::Level logLevel) {
0210                   auto logger = getDefaultLogger("Geant4Detector", logLevel);
0211                   return self.constructDetector(cfg, *logger);
0212                 },
0213                 py::arg("cfg"), py::arg("logLevel") = Logging::INFO)
0214             .def(
0215                 "constructTrackingGeometry",
0216                 [](Geant4Detector& self, const Geant4Detector::Config& cfg,
0217                    Logging::Level logLevel) {
0218                   auto logger = getDefaultLogger("Geant4Detector", logLevel);
0219                   return self.constructTrackingGeometry(cfg, *logger);
0220                 },
0221                 py::arg("cfg"), py::arg("logLevel") = Logging::INFO);
0222 
0223     auto c = py::class_<Geant4Detector::Config>(g, "Config").def(py::init<>());
0224     ACTS_PYTHON_STRUCT_BEGIN(c, Geant4Detector::Config);
0225     ACTS_PYTHON_MEMBER(name);
0226     ACTS_PYTHON_MEMBER(g4World);
0227     ACTS_PYTHON_MEMBER(g4SurfaceOptions);
0228     ACTS_PYTHON_MEMBER(protoDetector);
0229     ACTS_PYTHON_MEMBER(geometryIdentifierHook);
0230     ACTS_PYTHON_MEMBER(logLevel);
0231     ACTS_PYTHON_STRUCT_END();
0232   }
0233 
0234   {
0235     /// Helper function to test if the automatic geometry conversion works
0236     ///
0237     /// @param gdmlFileName is the name of the GDML file
0238     /// @param sensitiveMatches is a list of strings to match sensitive volumes
0239     /// @param passiveMatches is a list of strings to match passive volumes
0240     mod.def("convertSurfaces", [](const std::string& gdmlFileName,
0241                                   const std::vector<std::string>&
0242                                       sensitiveMatches,
0243                                   const std::vector<std::string>&
0244                                       passiveMatches) {
0245       // Initiate the detector construction & retrieve world
0246       ActsExamples::GdmlDetectorConstruction gdmlContruction(gdmlFileName);
0247       const auto* world = gdmlContruction.Construct();
0248 
0249       // Create the selectors
0250       auto sensitiveSelectors =
0251           std::make_shared<Acts::Geant4PhysicalVolumeSelectors::NameSelector>(
0252               sensitiveMatches, false);
0253       auto passiveSelectors =
0254           std::make_shared<Acts::Geant4PhysicalVolumeSelectors::NameSelector>(
0255               passiveMatches, false);
0256 
0257       Acts::Geant4DetectorSurfaceFactory::Cache cache;
0258       Acts::Geant4DetectorSurfaceFactory::Options options;
0259       options.sensitiveSurfaceSelector = sensitiveSelectors;
0260       options.passiveSurfaceSelector = passiveSelectors;
0261 
0262       G4Transform3D nominal;
0263       Acts::Geant4DetectorSurfaceFactory factory;
0264       factory.construct(cache, nominal, *world, options);
0265 
0266       // Capture the sensitive elements and the surfaces
0267       using Elements =
0268           std::vector<std::shared_ptr<Acts::Geant4DetectorElement>>;
0269       Elements detectorElements;
0270       detectorElements.reserve(cache.sensitiveSurfaces.size());
0271       using Surfaces = std::vector<std::shared_ptr<Acts::Surface>>;
0272       Surfaces surfaces;
0273       surfaces.reserve(cache.sensitiveSurfaces.size());
0274       std::for_each(cache.sensitiveSurfaces.begin(),
0275                     cache.sensitiveSurfaces.end(), [&](const auto& sensitive) {
0276                       detectorElements.push_back(std::get<0>(sensitive));
0277                       surfaces.push_back(std::get<1>(sensitive));
0278                     });
0279 
0280       // Capture the passive surfaces
0281       Surfaces passiveSurfaces;
0282       passiveSurfaces.reserve(cache.passiveSurfaces.size());
0283       for (const auto& passive : cache.passiveSurfaces) {
0284         passiveSurfaces.push_back(passive);
0285       }
0286 
0287       // Return a convenient tuple for drawing
0288       return std::tuple<Elements, Surfaces, Surfaces>(
0289           std::move(detectorElements), std::move(surfaces),
0290           std::move(passiveSurfaces));
0291     });
0292   }
0293 
0294   {
0295     using MockupSectorBuilder = MockupSectorBuilder;
0296     using Config = MockupSectorBuilder::Config;
0297     using ChamberConfig = MockupSectorBuilder::ChamberConfig;
0298 
0299     auto ms =
0300         py::class_<MockupSectorBuilder, std::shared_ptr<MockupSectorBuilder>>(
0301             mod, "MockupSectorBuilder")
0302             .def(py::init<const Config&>())
0303             .def("buildChamber", &MockupSectorBuilder::buildChamber)
0304             .def("buildSector", &MockupSectorBuilder::buildSector)
0305             .def("drawSector", &MockupSectorBuilder::drawSector);
0306 
0307     auto c = py::class_<Config>(ms, "Config").def(py::init<>());
0308     ACTS_PYTHON_STRUCT_BEGIN(c, Config);
0309     ACTS_PYTHON_MEMBER(gdmlPath);
0310     ACTS_PYTHON_MEMBER(NumberOfSectors);
0311     ACTS_PYTHON_MEMBER(toleranceOverlap);
0312     ACTS_PYTHON_STRUCT_END();
0313 
0314     auto cch = py::class_<ChamberConfig>(ms, "ChamberConfig").def(py::init<>());
0315     ACTS_PYTHON_STRUCT_BEGIN(cch, ChamberConfig);
0316     ACTS_PYTHON_MEMBER(name);
0317     ACTS_PYTHON_MEMBER(SensitiveNames);
0318     ACTS_PYTHON_MEMBER(PassiveNames);
0319     ACTS_PYTHON_STRUCT_END();
0320   }
0321 
0322   {
0323     using Tool = RegionCreator;
0324     using Config = Tool::Config;
0325     auto tool = py::class_<Tool, std::shared_ptr<Tool>>(mod, "RegionCreator")
0326                     .def(py::init<const Config&, std::string, Logging::Level>(),
0327                          py::arg("config"), py::arg("name"),
0328                          py::arg("logLevel") = Logging::INFO)
0329                     .def_property_readonly("config", &Tool::config);
0330 
0331     auto c = py::class_<Config>(tool, "Config").def(py::init<>());
0332     ACTS_PYTHON_STRUCT_BEGIN(c, Config);
0333     ACTS_PYTHON_MEMBER(gammaCut);
0334     ACTS_PYTHON_MEMBER(electronCut);
0335     ACTS_PYTHON_MEMBER(positronCut);
0336     ACTS_PYTHON_MEMBER(protonCut);
0337     ACTS_PYTHON_MEMBER(volumes);
0338     ACTS_PYTHON_STRUCT_END();
0339   }
0340 
0341   Acts::Python::Context ctx;
0342   ctx.modules["geant4"] = mod;
0343 
0344   addGeant4HepMC3(ctx);
0345 }