From 8eba09e4ca2ecd6ab34330788f21e0f1c04e976d Mon Sep 17 00:00:00 2001 From: Andreas Salzburger Date: Fri, 6 Dec 2024 11:05:21 +0100 Subject: [PATCH 01/12] feat: TGeo python binding (#3885) This PR adds some first python bindings for the `TGeo` plugin. The added functionality is mainly for testing reason, it allows to you test whether sensitive elements from a `TGeo` description (or those one picks as sensitive) can be translated into TGeoDetectorElements. --- Examples/Python/CMakeLists.txt | 7 +++ Examples/Python/src/ModuleEntry.cpp | 2 + Examples/Python/src/TGeo.cpp | 87 +++++++++++++++++++++++++++++ Examples/Python/src/TGeoStub.cpp | 15 +++++ 4 files changed, 111 insertions(+) create mode 100644 Examples/Python/src/TGeo.cpp create mode 100644 Examples/Python/src/TGeoStub.cpp diff --git a/Examples/Python/CMakeLists.txt b/Examples/Python/CMakeLists.txt index 0eb4b1ff4ec..dc359db0d0d 100644 --- a/Examples/Python/CMakeLists.txt +++ b/Examples/Python/CMakeLists.txt @@ -97,6 +97,13 @@ else() target_sources(ActsPythonBindings PRIVATE src/GeoModelStub.cpp) endif() +if(ACTS_BUILD_PLUGIN_TGEO) + target_link_libraries(ActsPythonBindings PUBLIC ActsPluginTGeo) + target_sources(ActsPythonBindings PRIVATE src/TGeo.cpp) +else() + target_sources(ActsPythonBindings PRIVATE src/TGeoStub.cpp) +endif() + if(ACTS_BUILD_PLUGIN_TRACCC) target_link_libraries(ActsPythonBindings PUBLIC ActsPluginDetray) target_sources(ActsPythonBindings PRIVATE src/Detray.cpp) diff --git a/Examples/Python/src/ModuleEntry.cpp b/Examples/Python/src/ModuleEntry.cpp index a74d277f7a5..a78f04f9565 100644 --- a/Examples/Python/src/ModuleEntry.cpp +++ b/Examples/Python/src/ModuleEntry.cpp @@ -75,6 +75,7 @@ void addUtilities(Context& ctx); void addDigitization(Context& ctx); void addPythia8(Context& ctx); void addGeoModel(Context& ctx); +void addTGeo(Context& ctx); void addJson(Context& ctx); void addDetray(Context& ctx); void addHepMC3(Context& ctx); @@ -146,6 +147,7 @@ PYBIND11_MODULE(ActsPythonBindings, m) { addPythia8(ctx); addJson(ctx); addGeoModel(ctx); + addTGeo(ctx); addDetray(ctx); addHepMC3(ctx); addExaTrkXTrackFinding(ctx); diff --git a/Examples/Python/src/TGeo.cpp b/Examples/Python/src/TGeo.cpp new file mode 100644 index 00000000000..c67c2f3d653 --- /dev/null +++ b/Examples/Python/src/TGeo.cpp @@ -0,0 +1,87 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include "Acts/Plugins/Python/Utilities.hpp" +#include "Acts/Plugins/TGeo/TGeoDetectorElement.hpp" +#include "Acts/Plugins/TGeo/TGeoLayerBuilder.hpp" +#include "Acts/Plugins/TGeo/TGeoParser.hpp" + +#include + +#include +#include +#include +#include +#include + +namespace py = pybind11; +using namespace pybind11::literals; + +namespace Acts::Python { +void addTGeo(Context& ctx) { + auto [m, mex] = ctx.get("main", "examples"); + + auto tgeo = mex.def_submodule("tgeo"); + + { + py::class_>( + tgeo, "TGeoDetectorElement") + .def("surface", [](const Acts::TGeoDetectorElement& self) { + return self.surface().getSharedPtr(); + }); + } + + { + /// Helper function to test if the automatic geometry conversion works + /// + /// @param rootFileName is the name of the GDML file + /// @param sensitiveMatches is a list of strings to match sensitive volumes + /// @param localAxes is the TGeo->ACTS axis conversion convention + /// @param scaleConversion is a unit scalor conversion factor + tgeo.def("_convertToElements", + [](const std::string& rootFileName, + const std::vector& sensitiveMatches, + const std::string& localAxes, double scaleConversion) { + // Return vector + std::vector> + tgElements; + // TGeo import + TGeoManager::Import(rootFileName.c_str()); + if (gGeoManager != nullptr) { + auto tVolume = gGeoManager->GetTopVolume(); + if (tVolume != nullptr) { + TGeoHMatrix gmatrix = TGeoIdentity(tVolume->GetName()); + + TGeoParser::Options tgpOptions; + tgpOptions.volumeNames = {tVolume->GetName()}; + tgpOptions.targetNames = sensitiveMatches; + tgpOptions.unit = scaleConversion; + TGeoParser::State tgpState; + tgpState.volume = tVolume; + tgpState.onBranch = true; + + TGeoParser::select(tgpState, tgpOptions, gmatrix); + tgElements.reserve(tgpState.selectedNodes.size()); + + for (const auto& snode : tgpState.selectedNodes) { + auto identifier = Acts::TGeoDetectorElement::Identifier(); + auto tgElement = TGeoLayerBuilder::defaultElementFactory( + identifier, *snode.node, *snode.transform, localAxes, + scaleConversion, nullptr); + tgElements.emplace_back(tgElement); + } + } + } + // Return the elements + return tgElements; + }); + } +} + +} // namespace Acts::Python diff --git a/Examples/Python/src/TGeoStub.cpp b/Examples/Python/src/TGeoStub.cpp new file mode 100644 index 00000000000..09a800e693f --- /dev/null +++ b/Examples/Python/src/TGeoStub.cpp @@ -0,0 +1,15 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +namespace Acts::Python { +struct Context; +} // namespace Acts::Python + +namespace Acts::Python { +void addTGeo(Context& /*ctx*/) {} +} // namespace Acts::Python From 2862173924e232c0ed3800ba6fc0f9abb59f3d6e Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Fri, 6 Dec 2024 17:42:32 +0100 Subject: [PATCH 02/12] ci: Lint updates (#3958) 1. Remove redundant extra CI jobs that are covered by the pre-commit job 2. Make codespell write changes (more convenient to use from pre-commit) --- .github/workflows/checks.yml | 81 ++---------------------------------- .pre-commit-config.yaml | 3 +- 2 files changed, 5 insertions(+), 79 deletions(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index e84044776a8..59ba76bb00a 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -38,51 +38,6 @@ jobs: - name: Run pre-commit run: pre-commit run --all-files --show-diff-on-failure - license: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: '3.12' - - name: Check - run: > - sudo apt-get install -y git - && CI/check_license.py . --exclude "*thirdparty/*" - include_guards: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: '3.12' - - name: Check - run: > - CI/check_include_guards.py . --fail-global --exclude "*thirdparty/*" - pragma_once: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Check - run: > - CI/check_pragma_once.sh - type_t: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: '3.12' - - name: Check - run: > - CI/check_type_t.py . --exclude "thirdparty/*" - boost_test_macro: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Check - run: > - CI/check_boost_test_macro.sh smearing_config: runs-on: ubuntu-latest steps: @@ -93,39 +48,7 @@ jobs: - name: Check run: > CI/check_smearing_config.py . - cmake_options: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: '3.12' - - name: Check - run: > - docs/parse_cmake_options.py CMakeLists.txt --write docs/getting_started.md --verify - spelling: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: '3.12' - - name: Install codespell - run: > - pip install codespell==2.2.5 - - name: Check - run: > - CI/check_spelling - math_macros: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: '3.12' - - name: Check - run: > - CI/check_math_macros.py . --exclude "thirdparty/*" + missing_includes: runs-on: ubuntu-latest steps: @@ -136,6 +59,7 @@ jobs: - name: Check run: > CI/missing_include_check.sh + fpe_masks: runs-on: ubuntu-latest steps: @@ -149,6 +73,7 @@ jobs: - name: Check run: > CI/check_fpe_masks.py --token ${{ secrets.GITHUB_TOKEN }} + unused_files: runs-on: ubuntu-latest steps: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4158678a3e0..d4c224bf3c7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -35,7 +35,8 @@ repos: - id: codespell args: [ "-S", "*.ipynb,*.onnx,_build,*.svg", - "-I", "./CI/codespell_ignore.txt" + "-I", "./CI/codespell_ignore.txt", + "-w" ] exclude: ^CI/.*$ From 12ea68c11818c0a95ab0687719cbda781037870c Mon Sep 17 00:00:00 2001 From: Benjamin Huth <37871400+benjaminhuth@users.noreply.github.com> Date: Fri, 6 Dec 2024 20:24:21 +0100 Subject: [PATCH 03/12] ci: Reenable some ExaTrkX tests (#3395) These tests should work even though cugraph is not available anymore... ## Summary by CodeRabbit - **New Features** - Introduced new test jobs for enhanced testing capabilities. - Added a new algorithm for converting prototracks to tracks, improving data processing. - **Bug Fixes** - Updated input parameters for existing algorithms to ensure consistency and accuracy in data flow. - **Chores** - Improved cache management in the CI pipeline for better build efficiency. - Updated hash values for test files to reflect recent changes. --- .gitlab-ci.yml | 67 ++++++++++------- .../TrackFindingExaTrkX/CMakeLists.txt | 1 + .../python/acts/examples/reconstruction.py | 24 ++++--- Examples/Python/tests/root_file_hashes.txt | 2 +- Examples/Scripts/Python/exatrkx.py | 71 ++++++++++++------- 5 files changed, 102 insertions(+), 63 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c897c947010..e278b18eade 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -142,33 +142,46 @@ build_exatrkx: - cmake --build build -- -j6 - ccache -s -# test_exatrkx_unittests: -# stage: test -# needs: -# - build_exatrkx -# image: ghcr.io/acts-project/ubuntu2204_exatrkx:63 -# tags: -# - docker-gpu-nvidia -# script: -# - ctest --test-dir build -R ExaTrkX -# -# test_exatrkx_python: -# stage: test -# needs: -# - build_exatrkx -# image: ghcr.io/acts-project/ubuntu2204_exatrkx:63 -# tags: -# - docker-gpu-nvidia -# script: -# - apt-get update -y -# - apt-get install -y python3 libxxhash0 -# - source build/this_acts_withdeps.sh -# - git clone $CLONE_URL src -# - cd src -# - git checkout $HEAD_SHA -# - pip3 install -r Examples/Python/tests/requirements.txt -# - nvidia-smi -# - pytest -rFsv -k test_exatrkx +test_exatrkx_unittests: + stage: test + needs: + - build_exatrkx + image: ghcr.io/acts-project/ubuntu2204_exatrkx:63 + variables: + DEPENDENCY_URL: https://acts.web.cern.ch/ACTS/ci/ubuntu-22.04/deps.$DEPENDENCY_TAG.tar.zst + tags: + - docker-gpu-nvidia + script: + + - apt-get update -y + - git clone $CLONE_URL src + - source src/CI/dependencies.sh + - ctest --test-dir build -R ExaTrkX + +test_exatrkx_python: + stage: test + needs: + - build_exatrkx + image: ghcr.io/acts-project/ubuntu2204_exatrkx:63 + variables: + DEPENDENCY_URL: https://acts.web.cern.ch/ACTS/ci/ubuntu-22.04/deps.$DEPENDENCY_TAG.tar.zst + tags: + - docker-gpu-nvidia + script: + - apt-get update -y + - git clone $CLONE_URL src + - cd src + - git checkout $HEAD_SHA + - nvidia-smi + - source CI/dependencies.sh + - source ../build/this_acts_withdeps.sh + - python3 -m pip install -r Examples/Python/tests/requirements.txt + - echo $PYTHONPATH + - which python3 + - python3 --version + - python3 -c "import acts" + - pytest -rFsv -k torch --collect-only + - pytest -rFsv -k gpu-torch # For now only test torch GPU pipeline build_linux_ubuntu: stage: build diff --git a/Examples/Algorithms/TrackFindingExaTrkX/CMakeLists.txt b/Examples/Algorithms/TrackFindingExaTrkX/CMakeLists.txt index 85866466ec6..64255b89b14 100644 --- a/Examples/Algorithms/TrackFindingExaTrkX/CMakeLists.txt +++ b/Examples/Algorithms/TrackFindingExaTrkX/CMakeLists.txt @@ -5,6 +5,7 @@ add_library( src/PrototracksToParameters.cpp src/TrackFindingFromPrototrackAlgorithm.cpp src/TruthGraphBuilder.cpp + src/createFeatures.cpp ) target_include_directories( diff --git a/Examples/Python/python/acts/examples/reconstruction.py b/Examples/Python/python/acts/examples/reconstruction.py index 727bf9e9785..43792827e8d 100644 --- a/Examples/Python/python/acts/examples/reconstruction.py +++ b/Examples/Python/python/acts/examples/reconstruction.py @@ -1786,13 +1786,12 @@ def addExaTrkX( if backend == ExaTrkXBackend.Torch: metricLearningConfig["modelPath"] = str(modelDir / "embed.pt") - metricLearningConfig["numFeatures"] = 3 + metricLearningConfig["selectedFeatures"] = [0, 1, 2] filterConfig["modelPath"] = str(modelDir / "filter.pt") - filterConfig["nChunks"] = 10 - filterConfig["numFeatures"] = 3 + filterConfig["selectedFeatures"] = [0, 1, 2] gnnConfig["modelPath"] = str(modelDir / "gnn.pt") gnnConfig["undirected"] = True - gnnConfig["numFeatures"] = 3 + gnnConfig["selectedFeatures"] = [0, 1, 2] graphConstructor = acts.examples.TorchMetricLearning(**metricLearningConfig) edgeClassifiers = [ @@ -1824,11 +1823,18 @@ def addExaTrkX( s.addAlgorithm(findingAlg) s.addWhiteboardAlias("prototracks", findingAlg.config.outputProtoTracks) - # TODO convert prototracks to tracks + s.addAlgorithm( + acts.examples.PrototracksToTracks( + level=customLogLevel(), + inputProtoTracks="prototracks", + inputMeasurements="measurements", + outputTracks="tracks", + ) + ) matchAlg = acts.examples.TrackTruthMatcher( level=customLogLevel(), - inputProtoTracks=findingAlg.config.outputProtoTracks, + inputTracks="tracks", inputParticles="particles", inputMeasurementParticlesMap="measurement_particles_map", outputTrackParticleMatching="exatrkx_track_particle_matching", @@ -1843,14 +1849,12 @@ def addExaTrkX( "particle_track_matching", matchAlg.config.outputParticleTrackMatching ) - # Write truth track finding / seeding performance if outputDirRoot is not None: s.addWriter( acts.examples.TrackFinderNTupleWriter( level=customLogLevel(), - inputProtoTracks=findingAlg.config.outputProtoTracks, - # the original selected particles after digitization - inputParticles="particles_initial", + inputTracks="tracks", + inputParticles="particles", inputParticleMeasurementsMap="particle_measurements_map", inputTrackParticleMatching=matchAlg.config.outputTrackParticleMatching, filePath=str(Path(outputDirRoot) / "performance_track_finding.root"), diff --git a/Examples/Python/tests/root_file_hashes.txt b/Examples/Python/tests/root_file_hashes.txt index 6eeaaebff44..e1b2833c2eb 100644 --- a/Examples/Python/tests/root_file_hashes.txt +++ b/Examples/Python/tests/root_file_hashes.txt @@ -72,7 +72,7 @@ test_root_clusters_writer[configKwConstructor]__clusters.root: e842df4fe04eefff3 test_root_clusters_writer[kwargsConstructor]__clusters.root: e842df4fe04eefff3df5f32cd1026e93286be62b8040dc700a2aff557c56dec8 test_exatrkx[cpu-torch]__performance_track_finding.root: 36b3045589c4c17c038dbc87943366f4af4440f7eea6887afb763871ac149b05 test_exatrkx[gpu-onnx]__performance_track_finding.root: 9090de10ffb1489d3f1993e2a3081a3038227e3e5c453e98a9a4f33ea3d6d817 -test_exatrkx[gpu-torch]__performance_track_finding.root: 36b3045589c4c17c038dbc87943366f4af4440f7eea6887afb763871ac149b05 +test_exatrkx[gpu-torch]__performance_track_finding.root: 6b658fa22c7532e082eaab7aa4b71b852f1c324adcc59d1156aff45124b222d9 test_ML_Ambiguity_Solver__performance_finding_ambiML.root: 166dd8bb189097c4957b7b02c04c41267868d72d9a08c4bb892985b06849cb76 test_refitting[odd]__trackstates_gsf_refit.root: e297749dc1e7eda3b8dea13defa0499986c584740d93e723a901b498b8e90c71 test_refitting[odd]__tracksummary_gsf_refit.root: d5085882e45a0b699194dff9f40a36e9291227bf65f9aaaf9087f9242ef5ae22 diff --git a/Examples/Scripts/Python/exatrkx.py b/Examples/Scripts/Python/exatrkx.py index b2a151fc4e7..5a8920a318a 100755 --- a/Examples/Scripts/Python/exatrkx.py +++ b/Examples/Scripts/Python/exatrkx.py @@ -1,16 +1,52 @@ #!/usr/bin/env python3 from pathlib import Path +import os +import sys import acts.examples import acts +from acts.examples.reconstruction import addExaTrkX, ExaTrkXBackend from acts import UnitConstants as u +from digitization import runDigitization + + +def runGNNTrackFinding( + trackingGeometry, + field, + outputDir, + digiConfigFile, + geometrySelection, + backend, + modelDir, + outputRoot=False, + outputCsv=False, + s=None, +): + s = runDigitization( + trackingGeometry, + field, + outputDir, + digiConfigFile=digiConfigFile, + particlesInput=None, + outputRoot=outputRoot, + outputCsv=outputCsv, + s=s, + ) + + addExaTrkX( + s, + trackingGeometry, + geometrySelection, + modelDir, + backend=backend, + outputDirRoot=outputDir if outputRoot else None, + ) + + s.run() + if "__main__" == __name__: - import os - import sys - from digitization import runDigitization - from acts.examples.reconstruction import addExaTrkX, ExaTrkXBackend backend = ExaTrkXBackend.Torch @@ -19,16 +55,10 @@ if "torch" in sys.argv: backend = ExaTrkXBackend.Torch - srcdir = Path(__file__).resolve().parent.parent.parent.parent - detector, trackingGeometry, decorators = acts.examples.GenericDetector.create() field = acts.ConstantBField(acts.Vector3(0, 0, 2 * u.T)) - inputParticlePath = Path("particles.root") - if not inputParticlePath.exists(): - inputParticlePath = None - srcdir = Path(__file__).resolve().parent.parent.parent.parent geometrySelection = ( @@ -60,24 +90,15 @@ rnd = acts.examples.RandomNumbers() outputDir = Path(os.getcwd()) - s = runDigitization( + runGNNTrackFinding( trackingGeometry, field, outputDir, - digiConfigFile=digiConfigFile, - particlesInput=inputParticlePath, - outputRoot=True, - outputCsv=True, - s=s, - ) - - addExaTrkX( - s, - trackingGeometry, + digiConfigFile, geometrySelection, + backend, modelDir, - outputDir, - backend=backend, + outputRoot=True, + outputCsv=False, + s=s, ) - - s.run() From 03315f87b1c6a1d4ff17341e160f484753af81e1 Mon Sep 17 00:00:00 2001 From: Andreas Stefl Date: Fri, 6 Dec 2024 23:41:36 +0100 Subject: [PATCH 04/12] fix: Distinguish between hits and measurements in `ParticleSelector` in Examples (#3947) This clears out an oversight in a previous PR https://github.com/acts-project/acts/pull/3742 where I replaced numbers of measurements with number of hits. This number can be different and should not be confused. I add an optional input for the particle to measurement map which is then queried if present and used for the number of measurement cuts. blocked by: - https://github.com/acts-project/acts/pull/3944 ## Summary by CodeRabbit ## Release Notes - **New Features** - Enhanced particle selection with new configuration options for minimum and maximum hit counts. - Updated particle selection criteria to focus on hit counts instead of measurement counts. - **Bug Fixes** - Improved validation checks for input measurements to ensure proper initialization. - **Documentation** - Updated comments and documentation to reflect changes in parameter naming from "measurements" to "hits." - **Tests** - Adjusted test cases to align with the new parameter naming conventions. - **Chores** - Minor code formatting and organization improvements throughout various scripts. --- .../workflows/physmon_trackfinding_1muon.py | 2 +- .../physmon_trackfinding_4muon_50vertices.py | 2 +- .../physmon_trackfinding_ttbar_pu200.py | 2 +- .../TruthTracking/ParticleSelector.cpp | 43 +++++++++++++++---- .../TruthTracking/ParticleSelector.hpp | 11 ++++- .../Python/python/acts/examples/simulation.py | 5 ++- Examples/Python/src/TruthTracking.cpp | 2 + Examples/Python/tests/test_examples.py | 2 +- Examples/Scripts/Optimization/ckf.py | 2 +- Examples/Scripts/Python/ckf_tracks.py | 2 +- Examples/Scripts/Python/full_chain_itk.py | 2 +- .../Scripts/Python/full_chain_itk_Gbts.py | 2 +- Examples/Scripts/Python/full_chain_odd.py | 4 +- Examples/Scripts/Python/full_chain_odd_LRT.py | 4 +- Examples/Scripts/Python/full_chain_test.py | 2 +- Examples/Scripts/Python/hashing_seeding.py | 2 +- Examples/Scripts/Python/seeding.py | 2 +- Examples/Scripts/Python/truth_tracking_gsf.py | 2 +- .../Scripts/Python/truth_tracking_gx2f.py | 2 +- .../Scripts/Python/truth_tracking_kalman.py | 2 +- 20 files changed, 69 insertions(+), 28 deletions(-) diff --git a/CI/physmon/workflows/physmon_trackfinding_1muon.py b/CI/physmon/workflows/physmon_trackfinding_1muon.py index 90305112099..028b30ce5e5 100755 --- a/CI/physmon/workflows/physmon_trackfinding_1muon.py +++ b/CI/physmon/workflows/physmon_trackfinding_1muon.py @@ -74,7 +74,7 @@ def run_ckf_tracking(label, seeding): rnd=rnd, postSelectParticles=ParticleSelectorConfig( pt=(0.9 * u.GeV, None), - measurements=(9, None), + hits=(9, None), removeNeutral=True, ), ) diff --git a/CI/physmon/workflows/physmon_trackfinding_4muon_50vertices.py b/CI/physmon/workflows/physmon_trackfinding_4muon_50vertices.py index 1a119c8ed6c..85debced2b4 100755 --- a/CI/physmon/workflows/physmon_trackfinding_4muon_50vertices.py +++ b/CI/physmon/workflows/physmon_trackfinding_4muon_50vertices.py @@ -71,7 +71,7 @@ rnd=rnd, postSelectParticles=ParticleSelectorConfig( pt=(0.9 * u.GeV, None), - measurements=(9, None), + hits=(9, None), removeNeutral=True, ), ) diff --git a/CI/physmon/workflows/physmon_trackfinding_ttbar_pu200.py b/CI/physmon/workflows/physmon_trackfinding_ttbar_pu200.py index 4b4c75e1f36..de4021a5055 100755 --- a/CI/physmon/workflows/physmon_trackfinding_ttbar_pu200.py +++ b/CI/physmon/workflows/physmon_trackfinding_ttbar_pu200.py @@ -71,7 +71,7 @@ ), postSelectParticles=ParticleSelectorConfig( pt=(0.5 * u.GeV, None), - measurements=(9, None), + hits=(9, None), removeNeutral=True, ), ) diff --git a/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.cpp b/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.cpp index b4ef0928da0..6896763f32c 100644 --- a/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.cpp +++ b/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.cpp @@ -8,8 +8,8 @@ #include "ActsExamples/TruthTracking/ParticleSelector.hpp" -#include "Acts/Definitions/Common.hpp" #include "Acts/Utilities/VectorHelpers.hpp" +#include "ActsExamples/EventData/Index.hpp" #include "ActsExamples/EventData/SimParticle.hpp" #include "ActsExamples/Framework/AlgorithmContext.hpp" @@ -17,8 +17,10 @@ #include #include -ActsExamples::ParticleSelector::ParticleSelector(const Config& config, - Acts::Logging::Level level) +namespace ActsExamples { + +ParticleSelector::ParticleSelector(const Config& config, + Acts::Logging::Level level) : IAlgorithm("ParticleSelector", level), m_cfg(config) { if (m_cfg.inputParticles.empty()) { throw std::invalid_argument("Missing input particles collection"); @@ -28,8 +30,17 @@ ActsExamples::ParticleSelector::ParticleSelector(const Config& config, } m_inputParticles.initialize(m_cfg.inputParticles); + m_inputParticleMeasurementsMap.maybeInitialize( + m_cfg.inputParticleMeasurementsMap); m_outputParticles.initialize(m_cfg.outputParticles); + if (!m_inputParticleMeasurementsMap.isInitialized() && + (m_cfg.measurementsMin > 0 || + m_cfg.measurementsMax < std::numeric_limits::max())) { + throw std::invalid_argument( + "Measurement-based cuts require the inputMeasurementParticlesMap"); + } + ACTS_DEBUG("selection particle rho [" << m_cfg.rhoMin << "," << m_cfg.rhoMax << ")"); ACTS_DEBUG("selection particle |z| [" << m_cfg.absZMin << "," << m_cfg.absZMax @@ -46,6 +57,8 @@ ActsExamples::ParticleSelector::ParticleSelector(const Config& config, << ")"); ACTS_DEBUG("selection particle m [" << m_cfg.mMin << "," << m_cfg.mMax << ")"); + ACTS_DEBUG("selection particle hits [" << m_cfg.hitsMin << "," + << m_cfg.hitsMax << ")"); ACTS_DEBUG("selection particle measurements [" << m_cfg.measurementsMin << "," << m_cfg.measurementsMax << ")"); ACTS_DEBUG("remove charged particles " << m_cfg.removeCharged); @@ -59,12 +72,18 @@ ActsExamples::ParticleSelector::ParticleSelector(const Config& config, << m_cfg.maxPrimaryVertexId << ")"); } -ActsExamples::ProcessCode ActsExamples::ParticleSelector::execute( - const AlgorithmContext& ctx) const { +ProcessCode ParticleSelector::execute(const AlgorithmContext& ctx) const { // prepare input/ output types const SimParticleContainer& inputParticles = m_inputParticles(ctx); + const static InverseMultimap emptyMeasurementParticlesMap; + const InverseMultimap& inputMeasurementParticlesMap = + m_inputParticleMeasurementsMap.isInitialized() + ? m_inputParticleMeasurementsMap(ctx) + : emptyMeasurementParticlesMap; + std::size_t nInvalidCharge = 0; + std::size_t nInvalidHitCount = 0; std::size_t nInvalidMeasurementCount = 0; // helper functions to select tracks @@ -87,9 +106,14 @@ ActsExamples::ProcessCode ActsExamples::ParticleSelector::execute( nInvalidCharge += static_cast(!validCharge); - bool validMeasurementCount = - within(p.numberOfHits(), m_cfg.measurementsMin, m_cfg.measurementsMax); + const bool validHitCount = + within(p.numberOfHits(), m_cfg.hitsMin, m_cfg.hitsMax); + nInvalidHitCount += static_cast(!validHitCount); + const std::size_t measurementCount = + inputMeasurementParticlesMap.count(p.particleId()); + const bool validMeasurementCount = + within(measurementCount, m_cfg.measurementsMin, m_cfg.measurementsMax); nInvalidMeasurementCount += static_cast(!validMeasurementCount); @@ -103,7 +127,7 @@ ActsExamples::ProcessCode ActsExamples::ParticleSelector::execute( } return validPdg && validCharge && validSecondary && validPrimaryVertexId && - validMeasurementCount && + validHitCount && validMeasurementCount && within(p.transverseMomentum(), m_cfg.ptMin, m_cfg.ptMax) && within(std::abs(eta), m_cfg.absEtaMin, m_cfg.absEtaMax) && within(eta, m_cfg.etaMin, m_cfg.etaMax) && @@ -132,6 +156,7 @@ ActsExamples::ProcessCode ActsExamples::ParticleSelector::execute( << outputParticles.size() << " from " << inputParticles.size() << " particles"); ACTS_DEBUG("filtered out because of charge: " << nInvalidCharge); + ACTS_DEBUG("filtered out because of hit count: " << nInvalidHitCount); ACTS_DEBUG("filtered out because of measurement count: " << nInvalidMeasurementCount); @@ -139,3 +164,5 @@ ActsExamples::ProcessCode ActsExamples::ParticleSelector::execute( return ProcessCode::SUCCESS; } + +} // namespace ActsExamples diff --git a/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.hpp b/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.hpp index 4bd465d1b4d..4c57c5cbeef 100644 --- a/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.hpp +++ b/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.hpp @@ -9,6 +9,7 @@ #pragma once #include "Acts/Utilities/Logger.hpp" +#include "ActsExamples/EventData/Index.hpp" #include "ActsExamples/EventData/SimParticle.hpp" #include "ActsExamples/Framework/DataHandle.hpp" #include "ActsExamples/Framework/IAlgorithm.hpp" @@ -26,6 +27,9 @@ class ParticleSelector final : public IAlgorithm { struct Config { /// The input particles collection. std::string inputParticles; + /// (Optionally) The input particle measurements map. Only required for + /// measurement-based cuts. + std::string inputParticleMeasurementsMap; /// The output particles collection. std::string outputParticles; @@ -51,7 +55,10 @@ class ParticleSelector final : public IAlgorithm { // Rest mass cuts double mMin = 0; double mMax = std::numeric_limits::infinity(); - /// Measurement number cuts + // Hit count cuts + std::size_t hitsMin = 0; + std::size_t hitsMax = std::numeric_limits::max(); + // Measurement number cuts std::size_t measurementsMin = 0; std::size_t measurementsMax = std::numeric_limits::max(); /// Remove charged particles. @@ -81,6 +88,8 @@ class ParticleSelector final : public IAlgorithm { Config m_cfg; ReadDataHandle m_inputParticles{this, "InputParticles"}; + ReadDataHandle> m_inputParticleMeasurementsMap{ + this, "InputParticleMeasurementsMap"}; WriteDataHandle m_outputParticles{this, "OutputParticles"}; diff --git a/Examples/Python/python/acts/examples/simulation.py b/Examples/Python/python/acts/examples/simulation.py index 411f4410361..ff690e2a777 100644 --- a/Examples/Python/python/acts/examples/simulation.py +++ b/Examples/Python/python/acts/examples/simulation.py @@ -41,12 +41,13 @@ "absEta", # (min,max) "pt", # (min,max) "m", # (min,max) + "hits", # (min,max) "measurements", # (min,max) "removeCharged", # bool "removeNeutral", # bool "removeSecondaries", # bool ], - defaults=[(None, None)] * 9 + [None] * 3, + defaults=[(None, None)] * 10 + [None] * 3, ) @@ -393,6 +394,8 @@ def addParticleSelection( ptMax=config.pt[1], mMin=config.m[0], mMax=config.m[1], + hitsMin=config.hits[0], + hitsMax=config.hits[1], measurementsMin=config.measurements[0], measurementsMax=config.measurements[1], removeCharged=config.removeCharged, diff --git a/Examples/Python/src/TruthTracking.cpp b/Examples/Python/src/TruthTracking.cpp index 4799d93dbdb..4d3569f4656 100644 --- a/Examples/Python/src/TruthTracking.cpp +++ b/Examples/Python/src/TruthTracking.cpp @@ -84,6 +84,8 @@ void addTruthTracking(Context& ctx) { ACTS_PYTHON_MEMBER(mMax); ACTS_PYTHON_MEMBER(ptMin); ACTS_PYTHON_MEMBER(ptMax); + ACTS_PYTHON_MEMBER(hitsMin); + ACTS_PYTHON_MEMBER(hitsMax); ACTS_PYTHON_MEMBER(measurementsMin); ACTS_PYTHON_MEMBER(measurementsMax); ACTS_PYTHON_MEMBER(removeCharged); diff --git a/Examples/Python/tests/test_examples.py b/Examples/Python/tests/test_examples.py index 2261e58cea4..8441514c26b 100644 --- a/Examples/Python/tests/test_examples.py +++ b/Examples/Python/tests/test_examples.py @@ -427,7 +427,7 @@ def test_itk_seeding(tmp_path, trk_geo, field, assert_root_hash): postSelectParticles=ParticleSelectorConfig( pt=(0.9 * u.GeV, None), eta=(-4, 4), - measurements=(9, None), + hits=(9, None), removeNeutral=True, ), ) diff --git a/Examples/Scripts/Optimization/ckf.py b/Examples/Scripts/Optimization/ckf.py index e0cd5fd9870..0077f35317b 100755 --- a/Examples/Scripts/Optimization/ckf.py +++ b/Examples/Scripts/Optimization/ckf.py @@ -171,7 +171,7 @@ def runCKFTracks( rnd=rnd, postSelectParticles=ParticleSelectorConfig( pt=(0.5 * u.GeV, None), - measurements=(9, None), + hits=(9, None), removeNeutral=True, ), ) diff --git a/Examples/Scripts/Python/ckf_tracks.py b/Examples/Scripts/Python/ckf_tracks.py index 75ec8a7c316..15a50466799 100755 --- a/Examples/Scripts/Python/ckf_tracks.py +++ b/Examples/Scripts/Python/ckf_tracks.py @@ -82,7 +82,7 @@ def runCKFTracks( rnd=rnd, postSelectParticles=ParticleSelectorConfig( pt=(0.5 * u.GeV, None), - measurements=(9, None), + hits=(9, None), removeNeutral=True, ), ) diff --git a/Examples/Scripts/Python/full_chain_itk.py b/Examples/Scripts/Python/full_chain_itk.py index b5c17278a1e..afb1df6a12b 100755 --- a/Examples/Scripts/Python/full_chain_itk.py +++ b/Examples/Scripts/Python/full_chain_itk.py @@ -74,7 +74,7 @@ postSelectParticles=ParticleSelectorConfig( pt=(1.0 * u.GeV, None), eta=(-4.0, 4.0), - measurements=(9, None), + hits=(9, None), removeNeutral=True, ), outputDirRoot=outputDir, diff --git a/Examples/Scripts/Python/full_chain_itk_Gbts.py b/Examples/Scripts/Python/full_chain_itk_Gbts.py index ac9cc8ae8fc..a939bd7e930 100755 --- a/Examples/Scripts/Python/full_chain_itk_Gbts.py +++ b/Examples/Scripts/Python/full_chain_itk_Gbts.py @@ -69,7 +69,7 @@ postSelectParticles=ParticleSelectorConfig( pt=(1.0 * u.GeV, None), eta=(-4.0, 4.0), - measurements=(9, None), + hits=(9, None), removeNeutral=True, ), outputDirRoot=outputDir, diff --git a/Examples/Scripts/Python/full_chain_odd.py b/Examples/Scripts/Python/full_chain_odd.py index 7ddaa02054f..50a13219afa 100755 --- a/Examples/Scripts/Python/full_chain_odd.py +++ b/Examples/Scripts/Python/full_chain_odd.py @@ -278,7 +278,7 @@ postSelectParticles=ParticleSelectorConfig( pt=(1.0 * u.GeV, None), eta=(-3.0, 3.0), - measurements=(9, None), + hits=(9, None), removeNeutral=True, ), outputDirRoot=outputDir if args.output_root else None, @@ -306,7 +306,7 @@ postSelectParticles=ParticleSelectorConfig( pt=(1.0 * u.GeV, None), eta=(-3.0, 3.0), - measurements=(9, None), + hits=(9, None), removeNeutral=True, ), enableInteractions=True, diff --git a/Examples/Scripts/Python/full_chain_odd_LRT.py b/Examples/Scripts/Python/full_chain_odd_LRT.py index cfa03b5336c..57f7ce85876 100644 --- a/Examples/Scripts/Python/full_chain_odd_LRT.py +++ b/Examples/Scripts/Python/full_chain_odd_LRT.py @@ -273,7 +273,7 @@ postSelectParticles=ParticleSelectorConfig( pt=(1.0 * u.GeV, None), eta=(-3.0, 3.0), - measurements=(9, None), + hits=(9, None), removeNeutral=True, ), outputDirRoot=outputDir if args.output_root else None, @@ -300,7 +300,7 @@ postSelectParticles=ParticleSelectorConfig( pt=(1.0 * u.GeV, None), eta=(-3.0, 3.0), - measurements=(9, None), + hits=(9, None), removeNeutral=True, ), enableInteractions=True, diff --git a/Examples/Scripts/Python/full_chain_test.py b/Examples/Scripts/Python/full_chain_test.py index 595dbd43a4e..49d7dacfeed 100755 --- a/Examples/Scripts/Python/full_chain_test.py +++ b/Examples/Scripts/Python/full_chain_test.py @@ -370,7 +370,7 @@ def full_chain(args): postSelectParticles = ParticleSelectorConfig( pt=(ptMin, None), eta=etaRange if not args.generic_detector else (None, None), - measurements=(9, None), + hits=(9, None), removeNeutral=True, ) diff --git a/Examples/Scripts/Python/hashing_seeding.py b/Examples/Scripts/Python/hashing_seeding.py index 770c34e5185..10f68b5cea9 100755 --- a/Examples/Scripts/Python/hashing_seeding.py +++ b/Examples/Scripts/Python/hashing_seeding.py @@ -215,7 +215,7 @@ def runHashingSeeding( postSelectParticles=ParticleSelectorConfig( pt=(1.0 * u.GeV, None), eta=(-eta, eta), - measurements=(9, None), + hits=(9, None), removeNeutral=True, ), enableInteractions=True, diff --git a/Examples/Scripts/Python/seeding.py b/Examples/Scripts/Python/seeding.py index 3beb6071aae..1e5b9e50d6b 100755 --- a/Examples/Scripts/Python/seeding.py +++ b/Examples/Scripts/Python/seeding.py @@ -90,7 +90,7 @@ def runSeeding( postSelectParticles=ParticleSelectorConfig( pt=(1.0 * u.GeV, None), eta=(-2.5, 2.5), - measurements=(9, None), + hits=(9, None), removeNeutral=True, ), ) diff --git a/Examples/Scripts/Python/truth_tracking_gsf.py b/Examples/Scripts/Python/truth_tracking_gsf.py index ae8aca06d6c..4f194a65662 100755 --- a/Examples/Scripts/Python/truth_tracking_gsf.py +++ b/Examples/Scripts/Python/truth_tracking_gsf.py @@ -79,7 +79,7 @@ def runTruthTrackingGsf( enableInteractions=True, postSelectParticles=ParticleSelectorConfig( pt=(0.9 * u.GeV, None), - measurements=(7, None), + hits=(7, None), removeNeutral=True, removeSecondaries=True, ), diff --git a/Examples/Scripts/Python/truth_tracking_gx2f.py b/Examples/Scripts/Python/truth_tracking_gx2f.py index 8503dc982f4..31ebb447d42 100644 --- a/Examples/Scripts/Python/truth_tracking_gx2f.py +++ b/Examples/Scripts/Python/truth_tracking_gx2f.py @@ -76,7 +76,7 @@ def runTruthTrackingGx2f( enableInteractions=True, postSelectParticles=ParticleSelectorConfig( pt=(0.9 * u.GeV, None), - measurements=(7, None), + hits=(7, None), removeNeutral=True, removeSecondaries=True, ), diff --git a/Examples/Scripts/Python/truth_tracking_kalman.py b/Examples/Scripts/Python/truth_tracking_kalman.py index 91c18f1dd28..971f0c4bab4 100755 --- a/Examples/Scripts/Python/truth_tracking_kalman.py +++ b/Examples/Scripts/Python/truth_tracking_kalman.py @@ -84,7 +84,7 @@ def runTruthTrackingKalman( enableInteractions=True, postSelectParticles=ParticleSelectorConfig( pt=(0.9 * u.GeV, None), - measurements=(7, None), + hits=(7, None), removeNeutral=True, removeSecondaries=True, ), From 5e8efd662189ef54fddbd328c535309a97d4c857 Mon Sep 17 00:00:00 2001 From: Andreas Stefl Date: Sat, 7 Dec 2024 00:58:52 +0100 Subject: [PATCH 05/12] refactor: Remove `SurfaceSortingAlgorithm` from Examples (#3952) In https://github.com/acts-project/acts/pull/3944 we found out that this algorithm is not needed anymore ## Summary by CodeRabbit - **New Features** - Enhanced configurability for machine learning-based seed filtering with the addition of an ONNX model parameter. - Streamlined seeding and track fitting algorithms for improved modularity. - **Bug Fixes** - Removed unnecessary complexity by eliminating the `directNavigation` parameter from multiple functions. - **Documentation** - Updated test suite to improve clarity and maintainability. - **Chores** - Removed obsolete files and references related to the `SurfaceSortingAlgorithm` class to streamline the codebase. --- .../Algorithms/TrackFitting/CMakeLists.txt | 1 - .../TrackFitting/SurfaceSortingAlgorithm.hpp | 55 ------------ .../src/SurfaceSortingAlgorithm.cpp | 84 ------------------- .../python/acts/examples/reconstruction.py | 12 --- Examples/Python/src/TrackFitting.cpp | 17 ---- Examples/Python/tests/root_file_hashes.txt | 24 ++---- Examples/Python/tests/test_algorithms.py | 2 - Examples/Python/tests/test_examples.py | 4 +- .../Scripts/Python/truth_tracking_kalman.py | 2 - 9 files changed, 9 insertions(+), 192 deletions(-) delete mode 100644 Examples/Algorithms/TrackFitting/include/ActsExamples/TrackFitting/SurfaceSortingAlgorithm.hpp delete mode 100644 Examples/Algorithms/TrackFitting/src/SurfaceSortingAlgorithm.cpp diff --git a/Examples/Algorithms/TrackFitting/CMakeLists.txt b/Examples/Algorithms/TrackFitting/CMakeLists.txt index 07e26091384..a6a9a5afe3b 100644 --- a/Examples/Algorithms/TrackFitting/CMakeLists.txt +++ b/Examples/Algorithms/TrackFitting/CMakeLists.txt @@ -2,7 +2,6 @@ add_library( ActsExamplesTrackFitting SHARED src/RefittingCalibrator.cpp - src/SurfaceSortingAlgorithm.cpp src/TrackFittingAlgorithm.cpp src/KalmanFitterFunction.cpp src/RefittingAlgorithm.cpp diff --git a/Examples/Algorithms/TrackFitting/include/ActsExamples/TrackFitting/SurfaceSortingAlgorithm.hpp b/Examples/Algorithms/TrackFitting/include/ActsExamples/TrackFitting/SurfaceSortingAlgorithm.hpp deleted file mode 100644 index 6315e192e67..00000000000 --- a/Examples/Algorithms/TrackFitting/include/ActsExamples/TrackFitting/SurfaceSortingAlgorithm.hpp +++ /dev/null @@ -1,55 +0,0 @@ -// This file is part of the ACTS project. -// -// Copyright (C) 2016 CERN for the benefit of the ACTS project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at https://mozilla.org/MPL/2.0/. - -#pragma once - -#include "Acts/Utilities/Logger.hpp" -#include "ActsExamples/EventData/Measurement.hpp" -#include "ActsExamples/EventData/ProtoTrack.hpp" -#include "ActsExamples/EventData/SimHit.hpp" -#include "ActsExamples/Framework/DataHandle.hpp" -#include "ActsExamples/Framework/IAlgorithm.hpp" -#include "ActsExamples/Framework/ProcessCode.hpp" - -#include - -namespace ActsExamples { - -class SurfaceSortingAlgorithm final : public IAlgorithm { - public: - struct Config { - /// Input proto track collection - std::string inputProtoTracks; - /// Input simulated hit collection - std::string inputSimHits; - /// Input measurement to simulated hit map for truth position - std::string inputMeasurementSimHitsMap; - /// Output proto track collection - std::string outputProtoTracks; - }; - - SurfaceSortingAlgorithm(Config cfg, Acts::Logging::Level level); - - ActsExamples::ProcessCode execute(const AlgorithmContext& ctx) const final; - - /// Get readonly access to the config parameters - const Config& config() const { return m_cfg; } - - private: - Config m_cfg; - - ReadDataHandle m_inputProtoTracks{this, - "InputProtoTracks"}; - ReadDataHandle m_inputSimHits{this, "InputSimHits"}; - ReadDataHandle m_inputMeasurementSimHitsMap{ - this, "InputMeasurementSimHitsMap"}; - WriteDataHandle m_outputProtoTracks{this, - "OutputProtoTracks"}; -}; - -} // namespace ActsExamples diff --git a/Examples/Algorithms/TrackFitting/src/SurfaceSortingAlgorithm.cpp b/Examples/Algorithms/TrackFitting/src/SurfaceSortingAlgorithm.cpp deleted file mode 100644 index 57a79ab2db0..00000000000 --- a/Examples/Algorithms/TrackFitting/src/SurfaceSortingAlgorithm.cpp +++ /dev/null @@ -1,84 +0,0 @@ -// This file is part of the ACTS project. -// -// Copyright (C) 2016 CERN for the benefit of the ACTS project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at https://mozilla.org/MPL/2.0/. - -#include "ActsExamples/TrackFitting/SurfaceSortingAlgorithm.hpp" - -#include "ActsExamples/EventData/ProtoTrack.hpp" -#include "ActsFatras/EventData/Hit.hpp" - -#include -#include -#include -#include - -namespace ActsExamples { - -SurfaceSortingAlgorithm::SurfaceSortingAlgorithm(Config cfg, - Acts::Logging::Level level) - : IAlgorithm("SurfaceSortingAlgorithm", level), m_cfg(std::move(cfg)) { - if (m_cfg.inputProtoTracks.empty()) { - throw std::invalid_argument("Missing input proto track collection"); - } - if (m_cfg.inputSimHits.empty()) { - throw std::invalid_argument("Missing input simulated hits collection"); - } - if (m_cfg.inputMeasurementSimHitsMap.empty()) { - throw std::invalid_argument("Missing input measurement sim hits map"); - } - if (m_cfg.outputProtoTracks.empty()) { - throw std::invalid_argument("Missing output proto track collection"); - } - - m_inputProtoTracks.initialize(m_cfg.inputProtoTracks); - m_inputSimHits.initialize(m_cfg.inputSimHits); - m_inputMeasurementSimHitsMap.initialize(m_cfg.inputMeasurementSimHitsMap); - m_outputProtoTracks.initialize(m_cfg.outputProtoTracks); -} - -ProcessCode SurfaceSortingAlgorithm::execute( - const AlgorithmContext& ctx) const { - const auto& protoTracks = m_inputProtoTracks(ctx); - const auto& simHits = m_inputSimHits(ctx); - const auto& simHitsMap = m_inputMeasurementSimHitsMap(ctx); - - ProtoTrackContainer sortedTracks; - sortedTracks.reserve(protoTracks.size()); - std::map trackHitList; - - for (std::size_t itrack = 0; itrack < protoTracks.size(); ++itrack) { - const auto& protoTrack = protoTracks[itrack]; - - ProtoTrack sortedProtoTrack; - sortedProtoTrack.reserve(protoTrack.size()); - trackHitList.clear(); - - if (protoTrack.empty()) { - continue; - } - - for (const auto hit : protoTrack) { - const auto simHitIndex = simHitsMap.find(hit)->second; - auto simHit = simHits.nth(simHitIndex); - auto simHitTime = simHit->time(); - trackHitList.insert(std::make_pair(simHitTime, hit)); - } - - /// Map will now be sorted by truth hit time - for (auto const& [time, hit] : trackHitList) { - sortedProtoTrack.emplace_back(hit); - } - - sortedTracks.emplace_back(std::move(sortedProtoTrack)); - } - - m_outputProtoTracks(ctx, std::move(sortedTracks)); - - return ProcessCode::SUCCESS; -} - -} // namespace ActsExamples diff --git a/Examples/Python/python/acts/examples/reconstruction.py b/Examples/Python/python/acts/examples/reconstruction.py index 43792827e8d..0e30961fe39 100644 --- a/Examples/Python/python/acts/examples/reconstruction.py +++ b/Examples/Python/python/acts/examples/reconstruction.py @@ -1288,7 +1288,6 @@ def addKalmanTracks( s: acts.examples.Sequencer, trackingGeometry: acts.TrackingGeometry, field: acts.MagneticFieldProvider, - directNavigation: bool = False, reverseFilteringMomThreshold: float = 0 * u.GeV, inputProtoTracks: str = "truth_particle_tracks", multipleScattering: bool = True, @@ -1299,17 +1298,6 @@ def addKalmanTracks( ) -> None: customLogLevel = acts.examples.defaultLogging(s, logLevel) - if directNavigation: - srfSortAlg = acts.examples.SurfaceSortingAlgorithm( - level=customLogLevel(), - inputProtoTracks=inputProtoTracks, - inputSimHits="simhits", - inputMeasurementSimHitsMap="measurement_simhits_map", - outputProtoTracks="sorted_truth_particle_tracks", - ) - s.addAlgorithm(srfSortAlg) - inputProtoTracks = srfSortAlg.config.outputProtoTracks - kalmanOptions = { "multipleScattering": multipleScattering, "energyLoss": energyLoss, diff --git a/Examples/Python/src/TrackFitting.cpp b/Examples/Python/src/TrackFitting.cpp index c8dc72f9eef..6d1b9818e51 100644 --- a/Examples/Python/src/TrackFitting.cpp +++ b/Examples/Python/src/TrackFitting.cpp @@ -6,35 +6,23 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. -#include "Acts/Definitions/Algebra.hpp" #include "Acts/EventData/detail/CorrectedTransformationFreeToBound.hpp" #include "Acts/Plugins/Python/Utilities.hpp" #include "Acts/TrackFitting/BetheHeitlerApprox.hpp" #include "Acts/TrackFitting/GsfOptions.hpp" #include "Acts/Utilities/Logger.hpp" -#include "ActsExamples/EventData/Cluster.hpp" #include "ActsExamples/EventData/MeasurementCalibration.hpp" #include "ActsExamples/EventData/ScalingCalibrator.hpp" #include "ActsExamples/TrackFitting/RefittingAlgorithm.hpp" -#include "ActsExamples/TrackFitting/SurfaceSortingAlgorithm.hpp" #include "ActsExamples/TrackFitting/TrackFitterFunction.hpp" #include "ActsExamples/TrackFitting/TrackFittingAlgorithm.hpp" #include #include -#include #include #include -namespace Acts { -class MagneticFieldProvider; -class TrackingGeometry; -} // namespace Acts -namespace ActsExamples { -class IAlgorithm; -} // namespace ActsExamples - namespace py = pybind11; using namespace ActsExamples; @@ -46,11 +34,6 @@ namespace Acts::Python { void addTrackFitting(Context& ctx) { auto mex = ctx.get("examples"); - ACTS_PYTHON_DECLARE_ALGORITHM(ActsExamples::SurfaceSortingAlgorithm, mex, - "SurfaceSortingAlgorithm", inputProtoTracks, - inputSimHits, inputMeasurementSimHitsMap, - outputProtoTracks); - ACTS_PYTHON_DECLARE_ALGORITHM( ActsExamples::TrackFittingAlgorithm, mex, "TrackFittingAlgorithm", inputMeasurements, inputProtoTracks, inputInitialTrackParameters, diff --git a/Examples/Python/tests/root_file_hashes.txt b/Examples/Python/tests/root_file_hashes.txt index e1b2833c2eb..07d42c66ad1 100644 --- a/Examples/Python/tests/root_file_hashes.txt +++ b/Examples/Python/tests/root_file_hashes.txt @@ -78,19 +78,11 @@ test_refitting[odd]__trackstates_gsf_refit.root: e297749dc1e7eda3b8dea13defa0499 test_refitting[odd]__tracksummary_gsf_refit.root: d5085882e45a0b699194dff9f40a36e9291227bf65f9aaaf9087f9242ef5ae22 test_refitting[generic]__trackstates_gsf_refit.root: 4424fdf2f27575db825c1a59f8e53a1595946211cbd5b2c8d3a2f71cdcc77ae9 test_refitting[generic]__tracksummary_gsf_refit.root: 562deecee4cfb97ceee72eff53d63da079e3249fb62d6bcd556e6f27d495dfd9 -test_truth_tracking_kalman[generic-False-0.0]__trackstates_kf.root: 9f77962b92037cb760b1629a602b1dae61f45e659c45d9a87baa784f6190960e -test_truth_tracking_kalman[generic-False-0.0]__tracksummary_kf.root: 562deecee4cfb97ceee72eff53d63da079e3249fb62d6bcd556e6f27d495dfd9 -test_truth_tracking_kalman[generic-False-1000.0]__trackstates_kf.root: 56a1bd989b9c1316b9098c65fa75df9e6683e62e35ae68d8f72d27220be0fd7d -test_truth_tracking_kalman[generic-False-1000.0]__tracksummary_kf.root: 2d85be3a5dff01a1076e80f8c225aca32f65b30dc9c3551b610ac2f12d006a39 -test_truth_tracking_kalman[generic-True-0.0]__trackstates_kf.root: 9f77962b92037cb760b1629a602b1dae61f45e659c45d9a87baa784f6190960e -test_truth_tracking_kalman[generic-True-0.0]__tracksummary_kf.root: 562deecee4cfb97ceee72eff53d63da079e3249fb62d6bcd556e6f27d495dfd9 -test_truth_tracking_kalman[generic-True-1000.0]__trackstates_kf.root: 56a1bd989b9c1316b9098c65fa75df9e6683e62e35ae68d8f72d27220be0fd7d -test_truth_tracking_kalman[generic-True-1000.0]__tracksummary_kf.root: 2d85be3a5dff01a1076e80f8c225aca32f65b30dc9c3551b610ac2f12d006a39 -test_truth_tracking_kalman[odd-False-0.0]__trackstates_kf.root: 7e144571b19aaf00002aef4f5bec5d488b96fb9ed8e1b2904c3756b31be83513 -test_truth_tracking_kalman[odd-False-0.0]__tracksummary_kf.root: d5085882e45a0b699194dff9f40a36e9291227bf65f9aaaf9087f9242ef5ae22 -test_truth_tracking_kalman[odd-False-1000.0]__trackstates_kf.root: efdf37f56fa3ef85265cda61853f4c0f989e3d4f4745b5e351c9bcca78cd93cc -test_truth_tracking_kalman[odd-False-1000.0]__tracksummary_kf.root: b84fabd6c1b71c360019cd719400746ccff1e565a983ca23d0621790b8843e44 -test_truth_tracking_kalman[odd-True-0.0]__trackstates_kf.root: 7e144571b19aaf00002aef4f5bec5d488b96fb9ed8e1b2904c3756b31be83513 -test_truth_tracking_kalman[odd-True-0.0]__tracksummary_kf.root: d5085882e45a0b699194dff9f40a36e9291227bf65f9aaaf9087f9242ef5ae22 -test_truth_tracking_kalman[odd-True-1000.0]__trackstates_kf.root: efdf37f56fa3ef85265cda61853f4c0f989e3d4f4745b5e351c9bcca78cd93cc -test_truth_tracking_kalman[odd-True-1000.0]__tracksummary_kf.root: b84fabd6c1b71c360019cd719400746ccff1e565a983ca23d0621790b8843e44 +test_truth_tracking_kalman[generic-0.0]__trackstates_kf.root: 9f77962b92037cb760b1629a602b1dae61f45e659c45d9a87baa784f6190960e +test_truth_tracking_kalman[generic-0.0]__tracksummary_kf.root: 562deecee4cfb97ceee72eff53d63da079e3249fb62d6bcd556e6f27d495dfd9 +test_truth_tracking_kalman[generic-1000.0]__trackstates_kf.root: 56a1bd989b9c1316b9098c65fa75df9e6683e62e35ae68d8f72d27220be0fd7d +test_truth_tracking_kalman[generic-1000.0]__tracksummary_kf.root: 2d85be3a5dff01a1076e80f8c225aca32f65b30dc9c3551b610ac2f12d006a39 +test_truth_tracking_kalman[odd-0.0]__trackstates_kf.root: 7e144571b19aaf00002aef4f5bec5d488b96fb9ed8e1b2904c3756b31be83513 +test_truth_tracking_kalman[odd-0.0]__tracksummary_kf.root: d5085882e45a0b699194dff9f40a36e9291227bf65f9aaaf9087f9242ef5ae22 +test_truth_tracking_kalman[odd-1000.0]__trackstates_kf.root: efdf37f56fa3ef85265cda61853f4c0f989e3d4f4745b5e351c9bcca78cd93cc +test_truth_tracking_kalman[odd-1000.0]__tracksummary_kf.root: b84fabd6c1b71c360019cd719400746ccff1e565a983ca23d0621790b8843e44 diff --git a/Examples/Python/tests/test_algorithms.py b/Examples/Python/tests/test_algorithms.py index 6311dc6460a..0f1e1f01a61 100644 --- a/Examples/Python/tests/test_algorithms.py +++ b/Examples/Python/tests/test_algorithms.py @@ -17,7 +17,6 @@ TrackParameterSmearing, TrackSelectorAlgorithm, TrackFittingAlgorithm, - SurfaceSortingAlgorithm, ParticlesPrinter, TrackParametersPrinter, PropagationAlgorithm, @@ -47,7 +46,6 @@ TrackParameterSmearing, TrackSelectorAlgorithm, TrackFittingAlgorithm, - SurfaceSortingAlgorithm, ParticlesPrinter, TrackParametersPrinter, PropagationAlgorithm, diff --git a/Examples/Python/tests/test_examples.py b/Examples/Python/tests/test_examples.py index 8441514c26b..daf40b6685a 100644 --- a/Examples/Python/tests/test_examples.py +++ b/Examples/Python/tests/test_examples.py @@ -579,9 +579,8 @@ def test_event_recording(tmp_path): @pytest.mark.parametrize("revFiltMomThresh", [0 * u.GeV, 1 * u.TeV]) -@pytest.mark.parametrize("directNavigation", [False, True]) def test_truth_tracking_kalman( - tmp_path, assert_root_hash, revFiltMomThresh, directNavigation, detector_config + tmp_path, assert_root_hash, revFiltMomThresh, detector_config ): root_files = [ ("trackstates_kf.root", "trackstates", 19), @@ -607,7 +606,6 @@ def test_truth_tracking_kalman( digiConfigFile=detector_config.digiConfigFile, outputDir=tmp_path, reverseFilteringMomThreshold=revFiltMomThresh, - directNavigation=directNavigation, s=seq, ) diff --git a/Examples/Scripts/Python/truth_tracking_kalman.py b/Examples/Scripts/Python/truth_tracking_kalman.py index 971f0c4bab4..3b857fd41da 100755 --- a/Examples/Scripts/Python/truth_tracking_kalman.py +++ b/Examples/Scripts/Python/truth_tracking_kalman.py @@ -17,7 +17,6 @@ def runTruthTrackingKalman( inputParticlePath: Optional[Path] = None, inputHitsPath: Optional[Path] = None, decorators=[], - directNavigation=False, reverseFilteringMomThreshold=0 * u.GeV, s: acts.examples.Sequencer = None, ): @@ -122,7 +121,6 @@ def runTruthTrackingKalman( s, trackingGeometry, field, - directNavigation, reverseFilteringMomThreshold, ) From 1ebd328a63591dd259e9f5f65e7a56bb227c1bf3 Mon Sep 17 00:00:00 2001 From: "Alexander J. Pfleger" <70842573+AJPfleger@users.noreply.github.com> Date: Sat, 7 Dec 2024 12:48:54 +0100 Subject: [PATCH 06/12] fix: typo in variable in vertex muon scan script (#3959) ## Summary by CodeRabbit - **Bug Fixes** - Corrected error handling in the vertex_mu_scan script to properly append NaN values to the time array. - **Chores** - Made spelling corrections in the CI/codespell_ignore.txt file to enhance clarity and correctness. --- CI/codespell_ignore.txt | 1 - Examples/Scripts/vertex_mu_scan.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/CI/codespell_ignore.txt b/CI/codespell_ignore.txt index 13a3328440f..40dd321d0f5 100644 --- a/CI/codespell_ignore.txt +++ b/CI/codespell_ignore.txt @@ -5,7 +5,6 @@ coner dthe iself sortings -fime gaus te parm diff --git a/Examples/Scripts/vertex_mu_scan.py b/Examples/Scripts/vertex_mu_scan.py index ee8977fe9df..0de15b20097 100755 --- a/Examples/Scripts/vertex_mu_scan.py +++ b/Examples/Scripts/vertex_mu_scan.py @@ -39,7 +39,7 @@ def main(files: List[Path], output: str, title: str = ""): if time_file.exists(): time = numpy.append(time, float(time_file.read_text())) else: - fime.append(float("nan")) + time.append(float("nan")) rf = uproot.open(f"{file}:vertexing") From f16ed67a706a0b1ab3ea84291a8d737f705881e6 Mon Sep 17 00:00:00 2001 From: Stephen Nicholas Swatman Date: Sat, 7 Dec 2024 14:57:20 +0100 Subject: [PATCH 07/12] fix: Checkout branch in ExaTrk CI (#3967) Currently, the ExaTrk CI is trying to run a dependency script before having properly checked out the right branch, possible causing a CI error. This commit ensures that the target branch is properly checked out before trying to use any files in the repository. ## Summary by CodeRabbit - **Chores** - Improved CI/CD pipeline configuration for better build and test job management. - Standardized caching mechanisms and dependency handling across jobs. - Enhanced clarity and maintainability of the configuration. --- .gitlab-ci.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e278b18eade..25aff340111 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -155,7 +155,10 @@ test_exatrkx_unittests: - apt-get update -y - git clone $CLONE_URL src - - source src/CI/dependencies.sh + - cd src + - git checkout $HEAD_SHA + - source CI/dependencies.sh + - cd .. - ctest --test-dir build -R ExaTrkX test_exatrkx_python: From 9067679f3908b08e8ce55c5c61d75fde0b9061a9 Mon Sep 17 00:00:00 2001 From: Stephen Nicholas Swatman Date: Sat, 7 Dec 2024 16:29:01 +0100 Subject: [PATCH 08/12] feat: Add monadic functions to `Result` (#3957) In order to make the `Result` type easier to use, this commit adds three new functions: * `Result::value_or` allows the user to obtain the value or a provided default value. * `Result::transform` models functorial mapping, allowing users to modify values inside results. * `Result::and_then` models monadic binding, allowing users to build complex chains of actions on results. Implemented are lvalue and rvalue versions of these functions as well as tests. ![image](https://github.com/user-attachments/assets/591e64a2-e4fb-4ce6-9d34-166b28f7a837) ## Summary by CodeRabbit - **New Features** - Enhanced `Result` class with new methods for improved error handling and value transformation: - `value_or`: Retrieve valid value or default. - `transform`: Apply a function to the valid value. - `and_then`: Chain functions based on the result's validity. - **Tests** - Added comprehensive test cases to validate the new functionalities of the `Result` class, ensuring reliability and correctness: - `ValueOrResult`: Validates the `value_or` method. - `TransformResult`: Assesses the `transform` method. - `AndThenResult`: Evaluates the `and_then` method. --- Core/include/Acts/Utilities/Result.hpp | 141 ++++++++++++++++++ .../UnitTests/Core/Utilities/ResultTests.cpp | 88 +++++++++++ 2 files changed, 229 insertions(+) diff --git a/Core/include/Acts/Utilities/Result.hpp b/Core/include/Acts/Utilities/Result.hpp index 9410fa0edfe..475019fc99b 100644 --- a/Core/include/Acts/Utilities/Result.hpp +++ b/Core/include/Acts/Utilities/Result.hpp @@ -30,6 +30,9 @@ class Result { Result(std::variant&& var) : m_var(std::move(var)) {} public: + using ValueType = T; + using ErrorType = E; + /// Default construction is disallowed. Result() = delete; @@ -172,6 +175,144 @@ class Result { return std::move(std::get(m_var)); } + /// Retrieves the valid value from the result object, or returns a default + /// value if no valid value exists. + /// + /// @param[in] v The default value to use if no valid value exists. + /// @note This is the lvalue version. + /// @note This function always returns by value. + /// @return Either the valid value, or the given substitute. + template + std::conditional_t, const T&, T> value_or(U&& v) const& + requires(std::same_as, T>) + { + if (ok()) { + return value(); + } else { + return std::forward(v); + } + } + + /// Retrieves the valid value from the result object, or returns a default + /// value if no valid value exists. + /// + /// @param[in] v The default value to use if no valid value exists. + /// @note This is the rvalue version which moves the value out. + /// @note This function always returns by value. + /// @return Either the valid value, or the given substitute. + template + T value_or(U&& v) && + requires(std::same_as, T>) + { + if (ok()) { + return std::move(*this).value(); + } else { + return std::forward(v); + } + } + + /// Transforms the value contained in this result. + /// + /// Applying a function `f` to a valid value `x` returns `f(x)`, while + /// applying `f` to an invalid value returns another invalid value. + /// + /// @param[in] callable The transformation function to apply. + /// @note This is the lvalue version. + /// @note This functions is `fmap` on the functor in `A` of `Result`. + /// @return The modified valid value if exists, or an error otherwise. + template + auto transform(C&& callable) const& + requires std::invocable + { + using CallableReturnType = decltype(std::declval()(std::declval())); + using R = Result, E>; + if (ok()) { + return R::success(callable(value())); + } else { + return R::failure(error()); + } + } + + /// Transforms the value contained in this result. + /// + /// Applying a function `f` to a valid value `x` returns `f(x)`, while + /// applying `f` to an invalid value returns another invalid value. + /// + /// @param[in] callable The transformation function to apply. + /// @note This is the rvalue version. + /// @note This functions is `fmap` on the functor in `A` of `Result`. + /// @return The modified valid value if exists, or an error otherwise. + template + auto transform(C&& callable) && + requires std::invocable + { + using CallableReturnType = decltype(std::declval()(std::declval())); + using R = Result, E>; + if (ok()) { + return R::success(callable(std::move(*this).value())); + } else { + return R::failure(std::move(*this).error()); + } + } + + /// Bind a function to this result monadically. + /// + /// This function takes a function `f` and, if this result contains a valid + /// value `x`, returns `f(x)`. If the type of `x` is `T`, then `f` is + /// expected to accept type `T` and return `Result`. In this case, + /// `transform` would return the unhelpful type `Result>`, so + /// `and_then` strips away the outer layer to return `Result`. If the + /// value is invalid, this returns an invalid value in `Result`. + /// + /// @param[in] callable The transformation function to apply. + /// @note This is the lvalue version. + /// @note This functions is `>>=` on the functor in `A` of `Result`. + /// @return The modified valid value if exists, or an error otherwise. + template + auto and_then(C&& callable) const& + requires std::invocable + { + using R = decltype(std::declval()(std::declval())); + + static_assert(std::same_as, + "bind must take a callable with the same error type"); + + if (ok()) { + return callable(value()); + } else { + return R::failure(error()); + } + } + + /// Bind a function to this result monadically. + /// + /// This function takes a function `f` and, if this result contains a valid + /// value `x`, returns `f(x)`. If the type of `x` is `T`, then `f` is + /// expected to accept type `T` and return `Result`. In this case, + /// `transform` would return the unhelpful type `Result>`, so + /// `and_then` strips away the outer layer to return `Result`. If the + /// value is invalid, this returns an invalid value in `Result`. + /// + /// @param[in] callable The transformation function to apply. + /// @note This is the rvalue version. + /// @note This functions is `>>=` on the functor in `A` of `Result`. + /// @return The modified valid value if exists, or an error otherwise. + template + auto and_then(C&& callable) && + requires std::invocable + { + using R = decltype(std::declval()(std::declval())); + + static_assert(std::same_as, + "bind must take a callable with the same error type"); + + if (ok()) { + return callable(std::move(*this).value()); + } else { + return R::failure(std::move(*this).error()); + } + } + private: std::variant m_var; diff --git a/Tests/UnitTests/Core/Utilities/ResultTests.cpp b/Tests/UnitTests/Core/Utilities/ResultTests.cpp index 0a873f16d4c..748e0d7211e 100644 --- a/Tests/UnitTests/Core/Utilities/ResultTests.cpp +++ b/Tests/UnitTests/Core/Utilities/ResultTests.cpp @@ -333,6 +333,94 @@ BOOST_AUTO_TEST_CASE(BoolResult) { BOOST_CHECK_EQUAL(res.error(), MyError::Failure); } +BOOST_AUTO_TEST_CASE(ValueOrResult) { + using Result = Result; + + Result res = Result::success(5); + BOOST_CHECK_EQUAL(res.value_or(42), 5); + + res = Result::failure(MyError::Failure); + BOOST_CHECK_EQUAL(res.value_or(42), 42); + + BOOST_CHECK_EQUAL(Result::success(5).value_or(42), 5); + BOOST_CHECK_EQUAL(Result::failure(MyError::Failure).value_or(42), 42); + + int val = 25; + const int cval = 30; + + BOOST_CHECK_EQUAL(Result::success(5).value_or(val), 5); + BOOST_CHECK_EQUAL(Result::success(5).value_or(cval), 5); + BOOST_CHECK_EQUAL(Result::failure(MyError::Failure).value_or(val), 25); + BOOST_CHECK_EQUAL(Result::failure(MyError::Failure).value_or(cval), 30); + + res = Result::success(5); + + BOOST_CHECK_EQUAL(res.value_or(val), 5); + BOOST_CHECK_EQUAL(&(res.value_or(val)), &res.value()); + BOOST_CHECK_EQUAL(res.value_or(cval), 5); + BOOST_CHECK_EQUAL(&(res.value_or(cval)), &res.value()); + + res = Result::failure(MyError::Failure); + + BOOST_CHECK_EQUAL(res.value_or(val), 25); + BOOST_CHECK_EQUAL(res.value_or(cval), 30); + BOOST_CHECK_EQUAL(&(res.value_or(val)), &val); + BOOST_CHECK_EQUAL(&(res.value_or(cval)), &cval); +} + +BOOST_AUTO_TEST_CASE(TransformResult) { + using Result = Result; + + auto f1 = [](int x) { return 2 * x; }; + + Result res = Result::success(5); + Result res2 = res.transform(f1); + BOOST_CHECK(res2.ok()); + BOOST_CHECK_EQUAL(*res2, 10); + + res = Result::failure(MyError::Failure); + res2 = res.transform(f1); + BOOST_CHECK(!res2.ok()); + + BOOST_CHECK(Result::success(5).transform(f1).ok()); + BOOST_CHECK_EQUAL(Result::success(5).transform(f1).value(), 10); + + BOOST_CHECK(!Result::failure(MyError::Failure).transform(f1).ok()); +} + +BOOST_AUTO_TEST_CASE(AndThenResult) { + using Result1 = Result; + using Result2 = Result; + + auto f1 = [](int x) -> Result2 { + return Result2::success("hello " + std::to_string(x)); + }; + auto f2 = [](int) -> Result2 { return Result2::failure(MyError::Failure); }; + + Result1 res = Result1::success(5); + Result2 res2 = res.and_then(f1); + BOOST_CHECK(res2.ok()); + BOOST_CHECK_EQUAL(*res2, "hello 5"); + + res2 = res.and_then(f2); + BOOST_CHECK(!res2.ok()); + + res = Result1::failure(MyError::Failure); + res2 = res.and_then(f1); + BOOST_CHECK(!res2.ok()); + + res2 = res.and_then(f2); + BOOST_CHECK(!res2.ok()); + + BOOST_CHECK(Result1::success(5).and_then(f1).ok()); + BOOST_CHECK_EQUAL(Result1::success(5).and_then(f1).value(), "hello 5"); + + BOOST_CHECK(!Result1::success(5).and_then(f2).ok()); + + BOOST_CHECK(!Result1::failure(MyError::Failure).and_then(f1).ok()); + + BOOST_CHECK(!Result1::failure(MyError::Failure).and_then(f2).ok()); +} BOOST_AUTO_TEST_SUITE_END() } // namespace Acts::Test From 341d2b0b64cd4ccfc26cb69dea2006a875e5eab5 Mon Sep 17 00:00:00 2001 From: Andreas Stefl Date: Sat, 7 Dec 2024 18:22:45 +0100 Subject: [PATCH 09/12] refactor: Rework detector handling in Examples (#3498) - Concrete detector interface for examples - Align interfaces of different detectors - Remove `DD4hepGeometryService` - Improve DDG4 construction - `unique_ptr` for DD4hep detector with dedicated name - Concrete `Geant4Mapping` instance for conversion - Simplify CMake for optional Geant4 construction for different detectors - Move Geant4 construction code to detector folder --- CI/physmon/physmon_common.py | 4 +- Core/include/Acts/Utilities/Logger.hpp | 4 +- Examples/Algorithms/Geant4/CMakeLists.txt | 38 +--- .../DDG4/DDG4DetectorConstruction.hpp | 74 -------- ...tory.hpp => Geant4ConstructionOptions.hpp} | 16 +- .../ActsExamples/Geant4/Geant4Simulation.hpp | 22 +-- .../ActsExamples/Geant4/RegionCreator.hpp | 25 +-- .../TelescopeG4DetectorConstruction.hpp | 56 ------ .../Geant4/src/DDG4DetectorConstruction.cpp | 76 -------- .../Geant4/src/GdmlDetectorConstruction.cpp | 49 ----- .../Geant4/src/Geant4Simulation.cpp | 8 +- .../Algorithms/Geant4/src/RegionCreator.cpp | 19 +- .../Geant4HepMC/EventRecording.hpp | 9 +- .../Geant4HepMC/src/EventRecording.cpp | 6 +- Examples/Detectors/CMakeLists.txt | 2 + Examples/Detectors/Common/CMakeLists.txt | 14 ++ .../ActsExamples/DetectorCommons/Detector.hpp | 69 +++++++ Examples/Detectors/Common/src/Detector.cpp | 58 ++++++ .../ContextualDetector/CMakeLists.txt | 8 +- .../ContextualDetector/AlignedDetector.hpp | 32 +--- .../src/AlignedDetector.cpp | 91 +++++---- .../Detectors/DD4hepDetector/CMakeLists.txt | 37 +++- .../DD4hepDetector/DD4hepDetector.hpp | 150 ++++++++------- .../DD4hepDetector/DD4hepGeometryService.hpp | 137 -------------- .../DDG4DetectorConstruction.hpp | 50 +++++ .../DD4hepDetector/src/DD4hepDetector.cpp | 163 ++++++++++------ .../src/DD4hepDetectorGeant4.cpp | 22 +++ .../src/DD4hepDetectorGeant4Stub.cpp | 19 ++ .../src/DD4hepGeometryService.cpp | 174 ------------------ .../src/DDG4DetectorConstruction.cpp | 52 ++++++ .../Detectors/Geant4Detector/CMakeLists.txt | 17 +- .../Geant4Detector/GdmlDetector.hpp | 36 ++++ .../GdmlDetectorConstruction.hpp | 28 +-- .../Geant4Detector/Geant4Detector.hpp | 51 +---- .../Geant4Detector/src/GdmlDetector.cpp | 27 +++ .../src/GdmlDetectorConstruction.cpp | 41 +++++ .../Geant4Detector/src/Geant4Detector.cpp | 77 +++----- .../Detectors/GenericDetector/CMakeLists.txt | 8 +- .../GenericDetector/GenericDetector.hpp | 37 ++-- .../GenericDetector/src/GenericDetector.cpp | 32 ++-- .../Detectors/GeoModelDetector/CMakeLists.txt | 41 +++++ .../GeoModelDetector/GeoModelDetector.hpp | 37 ++++ .../GeoModelGeant4DetectorConstruction.hpp} | 31 +--- .../GeoModelDetector/src/GeoModelDetector.cpp | 24 +++ .../src/GeoModelDetectorGeant4.cpp | 21 +++ .../src/GeoModelDetectorGeant4Stub.cpp | 19 ++ .../GeoModelGeant4DetectorConstruction.cpp} | 33 ++-- .../src/MockupSectorBuilder.cpp | 17 +- .../Detectors/TGeoDetector/CMakeLists.txt | 2 + .../TGeoDetector/JsonTGeoDetectorConfig.hpp | 10 +- .../TGeoDetector/TGeoDetector.hpp | 32 ++-- .../TGeoDetector/src/TGeoDetector.cpp | 26 ++- .../TelescopeDetector/CMakeLists.txt | 23 ++- .../TelescopeDetector/TelescopeDetector.hpp | 27 ++- .../TelescopeG4DetectorConstruction.hpp | 38 ++++ .../src/TelescopeDetector.cpp | 43 ++--- .../src/TelescopeDetectorGeant4.cpp | 20 ++ .../src/TelescopeDetectorGeant4Stub.cpp | 19 ++ .../src/TelescopeG4DetectorConstruction.cpp | 29 +-- .../ActsExamples/Io/EDM4hep/EDM4hepReader.hpp | 2 +- Examples/Io/EDM4hep/src/EDM4hepReader.cpp | 5 +- Examples/Python/CMakeLists.txt | 55 +----- Examples/Python/python/acts/_adapter.py | 50 ----- .../Python/python/acts/examples/__init__.py | 4 +- .../Python/python/acts/examples/dd4hep.py | 7 +- .../python/acts/examples/geant4/dd4hep.py | 20 -- .../python/acts/examples/geant4/geomodel.py | 6 - Examples/Python/python/acts/examples/itk.py | 6 +- Examples/Python/python/acts/examples/odd.py | 36 +--- .../Python/python/acts/examples/simulation.py | 44 +---- Examples/Python/src/Covfie.cpp | 2 + Examples/Python/src/DD4hepComponent.cpp | 50 ++--- Examples/Python/src/Detector.cpp | 171 ++++++++--------- Examples/Python/src/Geant4Component.cpp | 110 ++++------- Examples/Python/src/Geant4DD4hepComponent.cpp | 34 ---- .../Python/src/Geant4GeoModelComponent.cpp | 36 ---- Examples/Python/src/Geant4HepMC3.cpp | 6 +- Examples/Python/src/GeoModel.cpp | 18 ++ Examples/Python/src/GeometryBuildingGen1.cpp | 23 ++- Examples/Python/src/ModuleEntry.cpp | 17 +- Examples/Python/tests/conftest.py | 39 ++-- Examples/Python/tests/test_detectors.py | 25 ++- Examples/Python/tests/test_examples.py | 89 ++++----- Examples/Python/tests/test_reader.py | 12 +- Examples/Python/tests/test_writer.py | 18 +- .../GsfDebugger/make_gsf_verbose_log.py | 6 +- Examples/Scripts/Optimization/ckf.py | 4 +- .../Orion/material_mapping_optimisation.py | 15 +- Examples/Scripts/Python/ckf_tracks.py | 4 +- Examples/Scripts/Python/digitization.py | 4 +- .../Scripts/Python/digitization_config.py | 3 +- Examples/Scripts/Python/event_recording.py | 13 +- Examples/Scripts/Python/exatrkx.py | 4 +- Examples/Scripts/Python/fatras.py | 4 +- Examples/Scripts/Python/full_chain_odd.py | 6 +- Examples/Scripts/Python/full_chain_odd_LRT.py | 6 +- Examples/Scripts/Python/full_chain_test.py | 8 +- Examples/Scripts/Python/geant4.py | 4 +- Examples/Scripts/Python/geant4_parallel.py | 4 +- Examples/Scripts/Python/geometry.py | 10 +- Examples/Scripts/Python/hashing_seeding.py | 8 +- Examples/Scripts/Python/material_mapping.py | 4 +- .../Scripts/Python/material_mapping_core.py | 3 +- Examples/Scripts/Python/material_recording.py | 26 +-- .../Scripts/Python/material_validation.py | 6 +- .../Python/material_validation_core.py | 5 +- Examples/Scripts/Python/propagation.py | 14 +- Examples/Scripts/Python/seeding.py | 5 +- .../Scripts/Python/telescope_simulation.py | 3 +- ...elescope_track_params_lookup_generation.py | 3 +- Examples/Scripts/Python/truth_tracking_gsf.py | 6 +- .../Python/truth_tracking_gsf_refitting.py | 6 +- .../Scripts/Python/truth_tracking_gx2f.py | 6 +- .../Scripts/Python/truth_tracking_kalman.py | 6 +- .../Python/truth_tracking_kalman_refitting.py | 7 +- .../Python/truth_tracking_telescope.py | 3 +- Examples/Scripts/Python/vertex_fitting.py | 3 +- docs/examples/full_chain_odd.md | 6 +- docs/examples/howto/material_mapping.rst | 4 +- docs/examples/python_bindings.rst | 3 +- docs/getting_started.md | 4 +- 121 files changed, 1584 insertions(+), 1857 deletions(-) delete mode 100644 Examples/Algorithms/Geant4/include/ActsExamples/DDG4/DDG4DetectorConstruction.hpp rename Examples/Algorithms/Geant4/include/ActsExamples/Geant4/{DetectorConstructionFactory.hpp => Geant4ConstructionOptions.hpp} (53%) delete mode 100644 Examples/Algorithms/Geant4/include/ActsExamples/TelescopeDetector/TelescopeG4DetectorConstruction.hpp delete mode 100644 Examples/Algorithms/Geant4/src/DDG4DetectorConstruction.cpp delete mode 100644 Examples/Algorithms/Geant4/src/GdmlDetectorConstruction.cpp create mode 100644 Examples/Detectors/Common/CMakeLists.txt create mode 100644 Examples/Detectors/Common/include/ActsExamples/DetectorCommons/Detector.hpp create mode 100644 Examples/Detectors/Common/src/Detector.cpp delete mode 100644 Examples/Detectors/DD4hepDetector/include/ActsExamples/DD4hepDetector/DD4hepGeometryService.hpp create mode 100644 Examples/Detectors/DD4hepDetector/include/ActsExamples/DD4hepDetector/DDG4DetectorConstruction.hpp create mode 100644 Examples/Detectors/DD4hepDetector/src/DD4hepDetectorGeant4.cpp create mode 100644 Examples/Detectors/DD4hepDetector/src/DD4hepDetectorGeant4Stub.cpp delete mode 100644 Examples/Detectors/DD4hepDetector/src/DD4hepGeometryService.cpp create mode 100644 Examples/Detectors/DD4hepDetector/src/DDG4DetectorConstruction.cpp create mode 100644 Examples/Detectors/Geant4Detector/include/ActsExamples/Geant4Detector/GdmlDetector.hpp rename Examples/{Algorithms/Geant4/include/ActsExamples/Geant4 => Detectors/Geant4Detector/include/ActsExamples/Geant4Detector}/GdmlDetectorConstruction.hpp (56%) create mode 100644 Examples/Detectors/Geant4Detector/src/GdmlDetector.cpp create mode 100644 Examples/Detectors/Geant4Detector/src/GdmlDetectorConstruction.cpp create mode 100644 Examples/Detectors/GeoModelDetector/CMakeLists.txt create mode 100644 Examples/Detectors/GeoModelDetector/include/ActsExamples/GeoModelDetector/GeoModelDetector.hpp rename Examples/{Algorithms/Geant4/include/ActsExamples/GeoModelG4/GeoModelDetectorConstruction.hpp => Detectors/GeoModelDetector/include/ActsExamples/GeoModelDetector/GeoModelGeant4DetectorConstruction.hpp} (52%) create mode 100644 Examples/Detectors/GeoModelDetector/src/GeoModelDetector.cpp create mode 100644 Examples/Detectors/GeoModelDetector/src/GeoModelDetectorGeant4.cpp create mode 100644 Examples/Detectors/GeoModelDetector/src/GeoModelDetectorGeant4Stub.cpp rename Examples/{Algorithms/Geant4/src/GeoModelDetectorConstruction.cpp => Detectors/GeoModelDetector/src/GeoModelGeant4DetectorConstruction.cpp} (53%) create mode 100644 Examples/Detectors/TelescopeDetector/include/ActsExamples/TelescopeDetector/TelescopeG4DetectorConstruction.hpp create mode 100644 Examples/Detectors/TelescopeDetector/src/TelescopeDetectorGeant4.cpp create mode 100644 Examples/Detectors/TelescopeDetector/src/TelescopeDetectorGeant4Stub.cpp rename Examples/{Algorithms/Geant4 => Detectors/TelescopeDetector}/src/TelescopeG4DetectorConstruction.cpp (87%) delete mode 100644 Examples/Python/python/acts/examples/geant4/dd4hep.py delete mode 100644 Examples/Python/python/acts/examples/geant4/geomodel.py delete mode 100644 Examples/Python/src/Geant4DD4hepComponent.cpp delete mode 100644 Examples/Python/src/Geant4GeoModelComponent.cpp diff --git a/CI/physmon/physmon_common.py b/CI/physmon/physmon_common.py index 32c056e2820..a451dee943b 100644 --- a/CI/physmon/physmon_common.py +++ b/CI/physmon/physmon_common.py @@ -33,7 +33,9 @@ def makeSetup() -> PhysmonSetup: level=acts.logging.INFO, ) - detector, trackingGeometry, decorators = getOpenDataDetector(matDeco) + detector = getOpenDataDetector(matDeco) + trackingGeometry = detector.trackingGeometry() + decorators = detector.contextDecorators() setup = PhysmonSetup( detector=detector, trackingGeometry=trackingGeometry, diff --git a/Core/include/Acts/Utilities/Logger.hpp b/Core/include/Acts/Utilities/Logger.hpp index 83dc989ca85..b9e499b74f3 100644 --- a/Core/include/Acts/Utilities/Logger.hpp +++ b/Core/include/Acts/Utilities/Logger.hpp @@ -7,11 +7,9 @@ // file, You can obtain one at https://mozilla.org/MPL/2.0/. #pragma once + // STL include(s) -#include #include -#include -#include #include #include #include diff --git a/Examples/Algorithms/Geant4/CMakeLists.txt b/Examples/Algorithms/Geant4/CMakeLists.txt index a7dd786bccf..cb056036f00 100644 --- a/Examples/Algorithms/Geant4/CMakeLists.txt +++ b/Examples/Algorithms/Geant4/CMakeLists.txt @@ -1,8 +1,6 @@ add_library( ActsExamplesGeant4 SHARED - src/GdmlDetectorConstruction.cpp - src/TelescopeG4DetectorConstruction.cpp src/Geant4Simulation.cpp src/MagneticFieldWrapper.cpp src/MaterialPhysicsList.cpp @@ -32,43 +30,9 @@ target_link_libraries( PUBLIC ActsCore ActsExamplesFramework - ActsExamplesDetectorTelescope + ActsExamplesDetectorsCommon Boost::headers ${Geant4_LIBRARIES} ) -if(ACTS_BUILD_EXAMPLES_DD4HEP) - if(${DD4hep_VERSION} VERSION_LESS 1.11) - target_include_directories( - ActsExamplesGeant4 - PRIVATE ${DD4hep_INCLUDE_DIRS} - ) - target_link_libraries( - ActsExamplesGeant4 - PRIVATE ${DD4hep_DDCORE_LIBRARY} ${DD4hep_DDG4_LIBRARY} - ) - else() - target_link_libraries( - ActsExamplesGeant4 - PUBLIC ActsExamplesDetectorDD4hep DD4hep::DDCore DD4hep::DDG4 - ) - endif() - - target_sources(ActsExamplesGeant4 PUBLIC src/DDG4DetectorConstruction.cpp) -endif() - -if(ACTS_BUILD_PLUGIN_GEOMODEL) - target_sources( - ActsExamplesGeant4 - PUBLIC src/GeoModelDetectorConstruction.cpp - ) - - find_library(GeoModel2G4_LIBRARY GeoModel2G4 REQUIRED) - - target_link_libraries( - ActsExamplesGeant4 - PUBLIC ActsPluginGeoModel ${GeoModel2G4_LIBRARY} - ) -endif() - install(TARGETS ActsExamplesGeant4 LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) diff --git a/Examples/Algorithms/Geant4/include/ActsExamples/DDG4/DDG4DetectorConstruction.hpp b/Examples/Algorithms/Geant4/include/ActsExamples/DDG4/DDG4DetectorConstruction.hpp deleted file mode 100644 index 6706b5c20e4..00000000000 --- a/Examples/Algorithms/Geant4/include/ActsExamples/DDG4/DDG4DetectorConstruction.hpp +++ /dev/null @@ -1,74 +0,0 @@ -// This file is part of the ACTS project. -// -// Copyright (C) 2016 CERN for the benefit of the ACTS project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at https://mozilla.org/MPL/2.0/. - -#pragma once - -#include "ActsExamples/Geant4/DetectorConstructionFactory.hpp" -#include "ActsExamples/Geant4/RegionCreator.hpp" - -#include - -#include - -class G4VPhysicalVolume; - -namespace dd4hep { -class Detector; -} - -namespace ActsExamples { - -struct DD4hepDetector; - -/// Construct the Geant4 detector from a DD4hep description. -class DDG4DetectorConstruction final : public G4VUserDetectorConstruction { - public: - DDG4DetectorConstruction( - std::shared_ptr detector, - std::vector> regionCreators = {}); - ~DDG4DetectorConstruction() final; - - /// Convert the stored DD4hep detector to a Geant4 description. - /// - /// Transfers ownership of the created object as all volumes (including world) - /// are deleted in ~G4PhysicalVolumeStore(). - /// - /// @note for facilitating configuration within the ACTS framework the world - /// volume is cached - G4VPhysicalVolume* Construct() final; - - private: - /// The Acts DD4hep detector instance - std::shared_ptr m_detector; - /// Region creators - std::vector> m_regionCreators; - /// The world volume - G4VPhysicalVolume* m_world = nullptr; - - /// The DD4hep detector instance - dd4hep::Detector& dd4hepDetector() const; -}; - -class DDG4DetectorConstructionFactory final - : public Geant4::DetectorConstructionFactory { - public: - DDG4DetectorConstructionFactory( - std::shared_ptr detector, - std::vector> regionCreators = {}); - ~DDG4DetectorConstructionFactory() final; - - std::unique_ptr factorize() const override; - - private: - /// The Acts DD4hep detector instance - std::shared_ptr m_detector; - /// Region creators - std::vector> m_regionCreators; -}; - -} // namespace ActsExamples diff --git a/Examples/Algorithms/Geant4/include/ActsExamples/Geant4/DetectorConstructionFactory.hpp b/Examples/Algorithms/Geant4/include/ActsExamples/Geant4/Geant4ConstructionOptions.hpp similarity index 53% rename from Examples/Algorithms/Geant4/include/ActsExamples/Geant4/DetectorConstructionFactory.hpp rename to Examples/Algorithms/Geant4/include/ActsExamples/Geant4/Geant4ConstructionOptions.hpp index 16cb2c3eae6..a767227ae3e 100644 --- a/Examples/Algorithms/Geant4/include/ActsExamples/Geant4/DetectorConstructionFactory.hpp +++ b/Examples/Algorithms/Geant4/include/ActsExamples/Geant4/Geant4ConstructionOptions.hpp @@ -9,18 +9,16 @@ #pragma once #include - -#include +#include namespace ActsExamples::Geant4 { +class RegionCreator; +} // namespace ActsExamples::Geant4 -/// Silly Geant4 will destroy the detector construction after the run manager is -/// destructed. This class works around it by factorizing a factory. -class DetectorConstructionFactory { - public: - virtual ~DetectorConstructionFactory() = default; +namespace ActsExamples { - virtual std::unique_ptr factorize() const = 0; +struct Geant4ConstructionOptions { + std::vector> regionCreators; }; -} // namespace ActsExamples::Geant4 +} // namespace ActsExamples diff --git a/Examples/Algorithms/Geant4/include/ActsExamples/Geant4/Geant4Simulation.hpp b/Examples/Algorithms/Geant4/include/ActsExamples/Geant4/Geant4Simulation.hpp index 917b87a7a27..089c1c2b3cd 100644 --- a/Examples/Algorithms/Geant4/include/ActsExamples/Geant4/Geant4Simulation.hpp +++ b/Examples/Algorithms/Geant4/include/ActsExamples/Geant4/Geant4Simulation.hpp @@ -10,6 +10,7 @@ #include "Acts/Material/MaterialInteraction.hpp" #include "Acts/Utilities/Logger.hpp" +#include "ActsExamples/DetectorCommons/Detector.hpp" #include "ActsExamples/EventData/PropagationSummary.hpp" #include "ActsExamples/EventData/SimHit.hpp" #include "ActsExamples/EventData/SimParticle.hpp" @@ -17,6 +18,7 @@ #include "ActsExamples/Framework/IAlgorithm.hpp" #include "ActsExamples/Framework/ProcessCode.hpp" #include "ActsExamples/Framework/RandomNumbers.hpp" +#include "ActsExamples/Geant4/Geant4ConstructionOptions.hpp" #include "ActsExamples/Geant4/SensitiveSurfaceMapper.hpp" #include @@ -44,10 +46,8 @@ namespace ActsExamples { struct Geant4Handle; namespace Geant4 { -class DetectorConstructionFactory; class SensitiveSurfaceMapper; struct EventStore; -class RegionCreator; } // namespace Geant4 /// Abstracts common Geant4 Acts algorithm behaviour. @@ -61,10 +61,11 @@ class Geant4SimulationBase : public IAlgorithm { /// Random number service. std::shared_ptr randomNumbers; - /// Detector construction object. - /// G4RunManager will take care of deletion - std::shared_ptr - detectorConstructionFactory; + /// Geant4 construction options. + Geant4ConstructionOptions constructionOptions; + + /// Detector instance to access Geant4 geometry construction. + std::shared_ptr detector; /// Optional Geant4 instance overwrite. std::shared_ptr geant4Handle; @@ -81,8 +82,7 @@ class Geant4SimulationBase : public IAlgorithm { /// Algorithm execute method, called once per event with context /// /// @param ctx the AlgorithmContext for this event - ActsExamples::ProcessCode execute( - const ActsExamples::AlgorithmContext& ctx) const override; + ProcessCode execute(const ActsExamples::AlgorithmContext& ctx) const override; /// Readonly access to the configuration virtual const Config& config() const = 0; @@ -166,8 +166,7 @@ class Geant4Simulation final : public Geant4SimulationBase { /// Algorithm execute method, called once per event with context /// /// @param ctx the AlgorithmContext for this event - ActsExamples::ProcessCode execute( - const ActsExamples::AlgorithmContext& ctx) const final; + ProcessCode execute(const ActsExamples::AlgorithmContext& ctx) const final; /// Readonly access to the configuration const Config& config() const final { return m_cfg; } @@ -209,8 +208,7 @@ class Geant4MaterialRecording final : public Geant4SimulationBase { /// Algorithm execute method, called once per event with context /// /// @param ctx the AlgorithmContext for this event - ActsExamples::ProcessCode execute( - const ActsExamples::AlgorithmContext& ctx) const final; + ProcessCode execute(const ActsExamples::AlgorithmContext& ctx) const final; /// Readonly access to the configuration const Config& config() const final { return m_cfg; } diff --git a/Examples/Algorithms/Geant4/include/ActsExamples/Geant4/RegionCreator.hpp b/Examples/Algorithms/Geant4/include/ActsExamples/Geant4/RegionCreator.hpp index 5327e4f37eb..8977449eff8 100644 --- a/Examples/Algorithms/Geant4/include/ActsExamples/Geant4/RegionCreator.hpp +++ b/Examples/Algorithms/Geant4/include/ActsExamples/Geant4/RegionCreator.hpp @@ -13,6 +13,8 @@ #include #include +class G4Region; + namespace ActsExamples::Geant4 { /// Geant4 Region Creator @@ -24,6 +26,9 @@ class RegionCreator { public: /// Nested configuration struct for the Geant4 region creator struct Config { + /// Region name + std::string name; + /// Process cut to be applied for gammas, in mm double gammaCut{}; @@ -37,35 +42,25 @@ class RegionCreator { double protonCut{}; /// Volume list to be included in this region - std::vector volumes{}; + std::vector volumes; }; /// Region creator constructor /// /// @param cfg is the configuration struct - /// @param name is the region name - /// @param level is the logging level to be used - RegionCreator(const Config& cfg, std::string name, - Acts::Logging::Level level); + explicit RegionCreator(const Config& cfg); /// Construct the region - void construct(); + /// @note The lifetime of the returned region is managed by Geant4 + G4Region* buildRegion( + const Acts::Logger& logger = Acts::getDummyLogger()) const; /// Readonly access to the configuration const Config& config() const { return m_cfg; } private: - /// Region name - std::string m_name; - /// Config instance Config m_cfg; - - /// Private access method to the logging instance - const Acts::Logger& logger() const { return *m_logger; } - - /// The looging instance - std::unique_ptr m_logger; }; } // namespace ActsExamples::Geant4 diff --git a/Examples/Algorithms/Geant4/include/ActsExamples/TelescopeDetector/TelescopeG4DetectorConstruction.hpp b/Examples/Algorithms/Geant4/include/ActsExamples/TelescopeDetector/TelescopeG4DetectorConstruction.hpp deleted file mode 100644 index dba44638152..00000000000 --- a/Examples/Algorithms/Geant4/include/ActsExamples/TelescopeDetector/TelescopeG4DetectorConstruction.hpp +++ /dev/null @@ -1,56 +0,0 @@ -// This file is part of the ACTS project. -// -// Copyright (C) 2016 CERN for the benefit of the ACTS project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at https://mozilla.org/MPL/2.0/. - -#pragma once - -#include "ActsExamples/Geant4/DetectorConstructionFactory.hpp" -#include "ActsExamples/Geant4/RegionCreator.hpp" -#include "ActsExamples/TelescopeDetector/TelescopeDetector.hpp" - -#include "G4VUserDetectorConstruction.hh" - -class G4VPhysicalVolume; -class G4LogicalVolume; - -namespace ActsExamples { - -class TelescopeG4DetectorConstruction final - : public G4VUserDetectorConstruction { - public: - TelescopeG4DetectorConstruction( - const TelescopeDetector::Config& cfg, - std::vector> regionCreators = {}); - - G4VPhysicalVolume* Construct() final; - - private: - /// The configuration of the telescope detector - TelescopeDetector::Config m_cfg; - /// Region creators - std::vector> m_regionCreators; - /// The world volume - G4VPhysicalVolume* m_world{}; -}; - -class TelescopeG4DetectorConstructionFactory final - : public Geant4::DetectorConstructionFactory { - public: - TelescopeG4DetectorConstructionFactory( - const TelescopeDetector::Config& cfg, - std::vector> regionCreators = {}); - - std::unique_ptr factorize() const override; - - private: - /// The configuration of the telescope detector - TelescopeDetector::Config m_cfg; - /// Region creators - std::vector> m_regionCreators; -}; - -} // namespace ActsExamples diff --git a/Examples/Algorithms/Geant4/src/DDG4DetectorConstruction.cpp b/Examples/Algorithms/Geant4/src/DDG4DetectorConstruction.cpp deleted file mode 100644 index 1b24da8f273..00000000000 --- a/Examples/Algorithms/Geant4/src/DDG4DetectorConstruction.cpp +++ /dev/null @@ -1,76 +0,0 @@ -// This file is part of the ACTS project. -// -// Copyright (C) 2016 CERN for the benefit of the ACTS project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at https://mozilla.org/MPL/2.0/. - -#include "ActsExamples/DDG4/DDG4DetectorConstruction.hpp" - -#include "ActsExamples/DD4hepDetector/DD4hepDetector.hpp" - -#include -#include - -#include -#include -#include -#include -#include -#include - -class G4VPhysicalVolume; - -namespace ActsExamples { - -DDG4DetectorConstruction::DDG4DetectorConstruction( - std::shared_ptr detector, - std::vector> regionCreators) - : G4VUserDetectorConstruction(), - m_detector(std::move(detector)), - m_regionCreators(std::move(regionCreators)) {} - -DDG4DetectorConstruction::~DDG4DetectorConstruction() = default; - -dd4hep::Detector& DDG4DetectorConstruction::dd4hepDetector() const { - return m_detector->geometryService->detector(); -} - -// See DD4hep::Simulation::Geant4DetectorConstruction::Construct() -G4VPhysicalVolume* DDG4DetectorConstruction::Construct() { - if (m_world == nullptr) { - dd4hep::sim::Geant4Mapping& g4map = dd4hep::sim::Geant4Mapping::instance(); - auto conv = dd4hep::sim::Geant4Converter(dd4hepDetector(), - dd4hep::PrintLevel::VERBOSE); - dd4hep::sim::Geant4GeometryInfo* geoInfo = - conv.create(dd4hepDetector().world()).detach(); - g4map.attach(geoInfo); - // All volumes are deleted in ~G4PhysicalVolumeStore() - m_world = geoInfo->world(); - // Create Geant4 volume manager - g4map.volumeManager(); - - // Create regions - for (const auto& regionCreator : m_regionCreators) { - regionCreator->construct(); - } - } - return m_world; -} - -DDG4DetectorConstructionFactory::DDG4DetectorConstructionFactory( - std::shared_ptr detector, - std::vector> regionCreators) - : m_detector(std::move(detector)), - m_regionCreators(std::move(regionCreators)) {} - -DDG4DetectorConstructionFactory::~DDG4DetectorConstructionFactory() = default; - -std::unique_ptr -DDG4DetectorConstructionFactory::factorize() const { - return std::make_unique(m_detector, - m_regionCreators); -} - -} // namespace ActsExamples diff --git a/Examples/Algorithms/Geant4/src/GdmlDetectorConstruction.cpp b/Examples/Algorithms/Geant4/src/GdmlDetectorConstruction.cpp deleted file mode 100644 index 242597ac175..00000000000 --- a/Examples/Algorithms/Geant4/src/GdmlDetectorConstruction.cpp +++ /dev/null @@ -1,49 +0,0 @@ -// This file is part of the ACTS project. -// -// Copyright (C) 2016 CERN for the benefit of the ACTS project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at https://mozilla.org/MPL/2.0/. - -#include "ActsExamples/Geant4/GdmlDetectorConstruction.hpp" - -#include - -#include - -class G4VPhysicalVolume; - -using namespace ActsExamples; - -GdmlDetectorConstruction::GdmlDetectorConstruction( - std::string path, - std::vector> regionCreators) - : G4VUserDetectorConstruction(), - m_path(std::move(path)), - m_regionCreators(std::move(regionCreators)) {} - -G4VPhysicalVolume* GdmlDetectorConstruction::Construct() { - if (m_world == nullptr) { - G4GDMLParser parser; - // TODO how to handle errors - parser.Read(m_path); - m_world = parser.GetWorldVolume(); - - // Create regions - for (const auto& regionCreator : m_regionCreators) { - regionCreator->construct(); - } - } - return m_world; -} - -GdmlDetectorConstructionFactory::GdmlDetectorConstructionFactory( - std::string path, - std::vector> regionCreators) - : m_path(std::move(path)), m_regionCreators(std::move(regionCreators)) {} - -std::unique_ptr -GdmlDetectorConstructionFactory::factorize() const { - return std::make_unique(m_path, m_regionCreators); -} diff --git a/Examples/Algorithms/Geant4/src/Geant4Simulation.cpp b/Examples/Algorithms/Geant4/src/Geant4Simulation.cpp index 0f26f8037b1..9ae93e97087 100644 --- a/Examples/Algorithms/Geant4/src/Geant4Simulation.cpp +++ b/Examples/Algorithms/Geant4/src/Geant4Simulation.cpp @@ -15,7 +15,6 @@ #include "ActsExamples/Framework/IAlgorithm.hpp" #include "ActsExamples/Framework/RandomNumbers.hpp" #include "ActsExamples/Framework/WhiteBoard.hpp" -#include "ActsExamples/Geant4/DetectorConstructionFactory.hpp" #include "ActsExamples/Geant4/EventStore.hpp" #include "ActsExamples/Geant4/Geant4Manager.hpp" #include "ActsExamples/Geant4/MagneticFieldWrapper.hpp" @@ -54,7 +53,7 @@ Geant4SimulationBase::Geant4SimulationBase(const Config& cfg, std::string name, if (cfg.inputParticles.empty()) { throw std::invalid_argument("Missing input particle collection"); } - if (cfg.detectorConstructionFactory == nullptr) { + if (cfg.detector == nullptr) { throw std::invalid_argument("Missing detector construction factory"); } if (cfg.randomNumbers == nullptr) { @@ -82,7 +81,10 @@ void Geant4SimulationBase::commonInitialization() { } // G4RunManager will take care of deletion m_detectorConstruction = - config().detectorConstructionFactory->factorize().release(); + config() + .detector + ->buildGeant4DetectorConstruction(config().constructionOptions) + .release(); runManager().SetUserInitialization(m_detectorConstruction); runManager().InitializeGeometry(); } diff --git a/Examples/Algorithms/Geant4/src/RegionCreator.cpp b/Examples/Algorithms/Geant4/src/RegionCreator.cpp index c38dcf83078..f3561293035 100644 --- a/Examples/Algorithms/Geant4/src/RegionCreator.cpp +++ b/Examples/Algorithms/Geant4/src/RegionCreator.cpp @@ -8,6 +8,8 @@ #include "ActsExamples/Geant4/RegionCreator.hpp" +#include "Acts/Utilities/Logger.hpp" + #include #include #include @@ -15,15 +17,11 @@ namespace ActsExamples::Geant4 { -RegionCreator::RegionCreator(const Config& cfg, std::string name, - Acts::Logging::Level level) - : m_name(std::move(name)), - m_cfg(cfg), - m_logger(Acts::getDefaultLogger(m_name, level)) {} +RegionCreator::RegionCreator(const Config& cfg) : m_cfg(cfg) {} -void RegionCreator::construct() { +G4Region* RegionCreator::buildRegion(const Acts::Logger& logger) const { // create a new G4Region - G4Region* region = new G4Region(m_name); + G4Region* region = new G4Region(m_cfg.name); // loop over volumes and find the ones in the list std::size_t nVolumes{0}; @@ -43,12 +41,13 @@ void RegionCreator::construct() { if (nVolumesCurrent == 0) { ACTS_WARNING("No volumes matching \"" << volumeName << "\" found in G4 LogicalVolumeStore. " - << m_name << " G4PhysicsRegion may not behave as intended."); + << m_cfg.name + << " G4PhysicsRegion may not behave as intended."); } nVolumes += nVolumesCurrent; } - ACTS_INFO("Created region " << m_name); + ACTS_INFO("Created region " << m_cfg.name); ACTS_INFO("A total of " << nVolumes << " volumes were assigned"); // create a G4ProductionCuts object and set appropriate values @@ -66,6 +65,8 @@ void RegionCreator::construct() { // assign cuts to the region region->SetProductionCuts(cuts); + + return region; } } // namespace ActsExamples::Geant4 diff --git a/Examples/Algorithms/Geant4HepMC/include/ActsExamples/Geant4HepMC/EventRecording.hpp b/Examples/Algorithms/Geant4HepMC/include/ActsExamples/Geant4HepMC/EventRecording.hpp index 6f45940182c..fead7f18d97 100644 --- a/Examples/Algorithms/Geant4HepMC/include/ActsExamples/Geant4HepMC/EventRecording.hpp +++ b/Examples/Algorithms/Geant4HepMC/include/ActsExamples/Geant4HepMC/EventRecording.hpp @@ -9,11 +9,13 @@ #pragma once #include "Acts/Utilities/Logger.hpp" +#include "ActsExamples/DetectorCommons/Detector.hpp" #include "ActsExamples/EventData/SimParticle.hpp" #include "ActsExamples/Framework/DataHandle.hpp" #include "ActsExamples/Framework/IAlgorithm.hpp" #include "ActsExamples/Framework/ProcessCode.hpp" #include "ActsExamples/Framework/SequenceElement.hpp" +#include "ActsExamples/Geant4/Geant4ConstructionOptions.hpp" #include #include @@ -38,8 +40,11 @@ class EventRecording final : public ActsExamples::IAlgorithm { /// The recorded events output std::string outputHepMcTracks = "geant-outcome-tracks"; - std::shared_ptr - detectorConstructionFactory; + /// Geant4 construction options. + Geant4ConstructionOptions constructionOptions; + + /// Detector instance to access Geant4 geometry construction. + std::shared_ptr detector; /// random number seed 1 int seed1 = 12345; diff --git a/Examples/Algorithms/Geant4HepMC/src/EventRecording.cpp b/Examples/Algorithms/Geant4HepMC/src/EventRecording.cpp index 93c27b0c1c1..51826af837a 100644 --- a/Examples/Algorithms/Geant4HepMC/src/EventRecording.cpp +++ b/Examples/Algorithms/Geant4HepMC/src/EventRecording.cpp @@ -10,7 +10,6 @@ #include "ActsExamples/EventData/SimParticle.hpp" #include "ActsExamples/Framework/WhiteBoard.hpp" -#include "ActsExamples/Geant4/DetectorConstructionFactory.hpp" #include @@ -41,7 +40,7 @@ EventRecording::EventRecording(const EventRecording::Config& config, if (m_cfg.outputHepMcTracks.empty()) { throw std::invalid_argument("Missing output event collection"); } - if (m_cfg.detectorConstructionFactory == nullptr) { + if (m_cfg.detector == nullptr) { throw std::invalid_argument("Missing detector construction object"); } @@ -52,7 +51,8 @@ EventRecording::EventRecording(const EventRecording::Config& config, // G4RunManager deals with the lifetime of these objects m_runManager->SetUserInitialization( - m_cfg.detectorConstructionFactory->factorize().release()); + m_cfg.detector->buildGeant4DetectorConstruction(m_cfg.constructionOptions) + .release()); m_runManager->SetUserInitialization(new FTFP_BERT); m_runManager->SetUserAction(new Geant4::HepMC3::RunAction()); m_runManager->SetUserAction( diff --git a/Examples/Detectors/CMakeLists.txt b/Examples/Detectors/CMakeLists.txt index 7e7aed5daed..ee63c6a3eb5 100644 --- a/Examples/Detectors/CMakeLists.txt +++ b/Examples/Detectors/CMakeLists.txt @@ -1,3 +1,4 @@ +add_subdirectory(Common) add_subdirectory(ContextualDetector) add_subdirectory_if(DD4hepDetector ACTS_BUILD_EXAMPLES_DD4HEP) add_subdirectory(GenericDetector) @@ -7,3 +8,4 @@ add_subdirectory(TGeoDetector) add_subdirectory(ITkModuleSplitting) add_subdirectory(TelescopeDetector) add_subdirectory_if(MuonSpectrometerMockupDetector ACTS_BUILD_EXAMPLES_GEANT4) +add_subdirectory_if(GeoModelDetector ACTS_BUILD_PLUGIN_GEOMODEL) diff --git a/Examples/Detectors/Common/CMakeLists.txt b/Examples/Detectors/Common/CMakeLists.txt new file mode 100644 index 00000000000..1464b2274c8 --- /dev/null +++ b/Examples/Detectors/Common/CMakeLists.txt @@ -0,0 +1,14 @@ +add_library(ActsExamplesDetectorsCommon SHARED src/Detector.cpp) +target_include_directories( + ActsExamplesDetectorsCommon + PUBLIC $ +) +target_link_libraries( + ActsExamplesDetectorsCommon + PUBLIC ActsCore ActsExamplesFramework +) + +install( + TARGETS ActsExamplesDetectorsCommon + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} +) diff --git a/Examples/Detectors/Common/include/ActsExamples/DetectorCommons/Detector.hpp b/Examples/Detectors/Common/include/ActsExamples/DetectorCommons/Detector.hpp new file mode 100644 index 00000000000..40e026f1935 --- /dev/null +++ b/Examples/Detectors/Common/include/ActsExamples/DetectorCommons/Detector.hpp @@ -0,0 +1,69 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#pragma once + +#include "Acts/Geometry/GeometryContext.hpp" + +#include +#include + +namespace Acts { +class GeometryContext; +class TrackingGeometry; +class DetectorElementBase; +class Logger; +namespace Experimental { +class Detector; +} // namespace Experimental +} // namespace Acts + +namespace ActsExamples { +class IContextDecorator; +struct Geant4ConstructionOptions; +} // namespace ActsExamples + +class G4VUserDetectorConstruction; + +namespace ActsExamples { + +/// Base class for detector instances +class Detector { + public: + explicit Detector(std::unique_ptr logger); + virtual ~Detector(); + + virtual const Acts::GeometryContext& nominalGeometryContext() const; + + virtual std::shared_ptr trackingGeometry() + const; + virtual std::shared_ptr gen2Geometry() const; + virtual std::vector> contextDecorators() + const; + + /// Build the Geant4 detector construction + /// @note This throws an exception if Geant4 is not enabled + /// @param options The Geant4 construction options + /// @return The Geant4 detector construction + virtual std::unique_ptr + buildGeant4DetectorConstruction( + const Geant4ConstructionOptions& options) const; + + protected: + const Acts::Logger& logger() const; + + std::unique_ptr m_logger; + + Acts::GeometryContext m_nominalGeometryContext; + std::shared_ptr m_trackingGeometry; + std::shared_ptr m_gen2Geometry; + std::vector> m_detectorStore; + std::vector> m_contextDecorators; +}; + +} // namespace ActsExamples diff --git a/Examples/Detectors/Common/src/Detector.cpp b/Examples/Detectors/Common/src/Detector.cpp new file mode 100644 index 00000000000..ce1291a2485 --- /dev/null +++ b/Examples/Detectors/Common/src/Detector.cpp @@ -0,0 +1,58 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include "ActsExamples/DetectorCommons/Detector.hpp" + +#include "Acts/Detector/Detector.hpp" +#include "Acts/Geometry/GeometryContext.hpp" +#include "Acts/Geometry/TrackingGeometry.hpp" +#include "Acts/Utilities/Logger.hpp" +#include "ActsExamples/Framework/IContextDecorator.hpp" + +namespace ActsExamples { + +Detector::Detector(std::unique_ptr logger) + : m_logger(std::move(logger)) {} + +Detector::~Detector() = default; + +std::vector> Detector::contextDecorators() + const { + return m_contextDecorators; +} + +std::unique_ptr +Detector::buildGeant4DetectorConstruction( + const Geant4ConstructionOptions& /*options*/) const { + throw std::runtime_error("Geant4 detector construction is not available."); +} + +const Acts::GeometryContext& Detector::nominalGeometryContext() const { + return m_nominalGeometryContext; +} + +std::shared_ptr Detector::trackingGeometry() + const { + if (m_trackingGeometry == nullptr) { + throw std::runtime_error("Tracking geometry is not built"); + } + return m_trackingGeometry; +} + +std::shared_ptr Detector::gen2Geometry() const { + if (m_gen2Geometry == nullptr) { + throw std::runtime_error("Gen2 geometry is not built"); + } + return m_gen2Geometry; +} + +const Acts::Logger& Detector::logger() const { + return *m_logger; +} + +} // namespace ActsExamples diff --git a/Examples/Detectors/ContextualDetector/CMakeLists.txt b/Examples/Detectors/ContextualDetector/CMakeLists.txt index 2cb61207c53..550a4cb450a 100644 --- a/Examples/Detectors/ContextualDetector/CMakeLists.txt +++ b/Examples/Detectors/ContextualDetector/CMakeLists.txt @@ -5,13 +5,19 @@ add_library( src/InternalAlignmentDecorator.cpp src/ExternalAlignmentDecorator.cpp ) + target_include_directories( ActsExamplesDetectorContextual PUBLIC $ ) + target_link_libraries( ActsExamplesDetectorContextual - PUBLIC ActsCore ActsExamplesFramework ActsExamplesDetectorGeneric + PUBLIC + ActsCore + ActsExamplesFramework + ActsExamplesDetectorsCommon + ActsExamplesDetectorGeneric ) install( diff --git a/Examples/Detectors/ContextualDetector/include/ActsExamples/ContextualDetector/AlignedDetector.hpp b/Examples/Detectors/ContextualDetector/include/ActsExamples/ContextualDetector/AlignedDetector.hpp index cfd12568d63..0859c174e5a 100644 --- a/Examples/Detectors/ContextualDetector/include/ActsExamples/ContextualDetector/AlignedDetector.hpp +++ b/Examples/Detectors/ContextualDetector/include/ActsExamples/ContextualDetector/AlignedDetector.hpp @@ -10,31 +10,18 @@ #include "Acts/Definitions/Units.hpp" #include "Acts/Utilities/Logger.hpp" +#include "ActsExamples/DetectorCommons/Detector.hpp" #include "ActsExamples/GenericDetector/GenericDetector.hpp" #include -#include -#include -#include - -namespace Acts { -class TrackingGeometry; -class IMaterialDecorator; -} // namespace Acts namespace ActsExamples { -class IContextDecorator; -class GenericDetectorElement; - class InternallyAlignedDetectorElement; class InternalAlignmentDecorator; -class AlignedDetector { +class AlignedDetector : public Detector { public: - using ContextDecorators = std::vector>; - using TrackingGeometryPtr = std::shared_ptr; - struct Config : public GenericDetector::Config { /// Seed for the decorator random numbers. std::size_t seed = 1324354657; @@ -59,21 +46,14 @@ class AlignedDetector { enum class Mode { Internal, External }; Mode mode = Mode::Internal; - }; - std::pair finalize( - const Config& cfg, - std::shared_ptr mdecorator); + std::shared_ptr materialDecorator; + }; - std::vector>>& - detectorStore() { - return m_detectorStore; - } + explicit AlignedDetector(const Config& cfg); private: - /// The Store of the detector elements (lifetime: job) - std::vector>> - m_detectorStore; + Config m_cfg; }; } // namespace ActsExamples diff --git a/Examples/Detectors/ContextualDetector/src/AlignedDetector.cpp b/Examples/Detectors/ContextualDetector/src/AlignedDetector.cpp index 9a9c5901543..3284723cebc 100644 --- a/Examples/Detectors/ContextualDetector/src/AlignedDetector.cpp +++ b/Examples/Detectors/ContextualDetector/src/AlignedDetector.cpp @@ -9,7 +9,6 @@ #include "ActsExamples/ContextualDetector/AlignedDetector.hpp" #include "Acts/Geometry/GeometryContext.hpp" -#include "Acts/Geometry/TrackingGeometry.hpp" #include "Acts/Utilities/Logger.hpp" #include "ActsExamples/ContextualDetector/AlignmentDecorator.hpp" #include "ActsExamples/ContextualDetector/ExternalAlignmentDecorator.hpp" @@ -19,94 +18,88 @@ #include "ActsExamples/Framework/RandomNumbers.hpp" #include "ActsExamples/GenericDetector/BuildGenericDetector.hpp" +#include + namespace ActsExamples { -auto AlignedDetector::finalize( - const Config& cfg, - std::shared_ptr mdecorator) - -> std::pair { - ContextDecorators aContextDecorators; +AlignedDetector::AlignedDetector(const Config& cfg) + : Detector(Acts::getDefaultLogger("AlignedDetector", cfg.logLevel)), + m_cfg(cfg) { + if (m_cfg.mode == Config::Mode::External) { + InternallyAlignedDetectorElement::ContextType nominalContext; + m_nominalGeometryContext = Acts::GeometryContext(nominalContext); + } else { + InternallyAlignedDetectorElement::ContextType nominalContext; + nominalContext.nominal = true; + m_nominalGeometryContext = Acts::GeometryContext(nominalContext); + } // Let's create a random number service RandomNumbers::Config randomNumberConfig; - randomNumberConfig.seed = cfg.seed; + randomNumberConfig.seed = m_cfg.seed; auto randomNumberSvc = std::make_shared(randomNumberConfig); auto fillDecoratorConfig = [&](AlignmentDecorator::Config& config) { - config.iovSize = cfg.iovSize; - config.flushSize = cfg.flushSize; - config.doGarbageCollection = cfg.doGarbageCollection; + config.iovSize = m_cfg.iovSize; + config.flushSize = m_cfg.flushSize; + config.doGarbageCollection = m_cfg.doGarbageCollection; // The misalignments - config.gSigmaX = cfg.sigmaInPlane; - config.gSigmaY = cfg.sigmaInPlane; - config.gSigmaZ = cfg.sigmaOutPlane; - config.aSigmaX = cfg.sigmaOutRot; - config.aSigmaY = cfg.sigmaOutRot; - config.aSigmaZ = cfg.sigmaInRot; + config.gSigmaX = m_cfg.sigmaInPlane; + config.gSigmaY = m_cfg.sigmaInPlane; + config.gSigmaZ = m_cfg.sigmaOutPlane; + config.aSigmaX = m_cfg.sigmaOutRot; + config.aSigmaY = m_cfg.sigmaOutRot; + config.aSigmaZ = m_cfg.sigmaInRot; config.randomNumberSvc = randomNumberSvc; - config.firstIovNominal = cfg.firstIovNominal; + config.firstIovNominal = m_cfg.firstIovNominal; }; - TrackingGeometryPtr aTrackingGeometry; - if (cfg.mode == Config::Mode::External) { - ExternallyAlignedDetectorElement::ContextType nominalContext; - Acts::GeometryContext geometryContext(nominalContext); - + if (m_cfg.mode == Config::Mode::External) { ExternalAlignmentDecorator::Config agcsConfig; fillDecoratorConfig(agcsConfig); std::vector>> - detectorStore; + specificDetectorStore; - aTrackingGeometry = + m_trackingGeometry = Generic::buildDetector( - geometryContext, detectorStore, cfg.buildLevel, - std::move(mdecorator), cfg.buildProto, cfg.surfaceLogLevel, - cfg.layerLogLevel, cfg.volumeLogLevel); - - agcsConfig.trackingGeometry = aTrackingGeometry; + m_nominalGeometryContext, specificDetectorStore, m_cfg.buildLevel, + m_cfg.materialDecorator, m_cfg.buildProto, m_cfg.surfaceLogLevel, + m_cfg.layerLogLevel, m_cfg.volumeLogLevel); + agcsConfig.trackingGeometry = m_trackingGeometry; // need to upcast to store in this object as well - for (auto& lstore : detectorStore) { - auto& target = m_detectorStore.emplace_back(); + for (auto& lstore : specificDetectorStore) { for (auto& ldet : lstore) { - target.push_back(ldet); + m_detectorStore.push_back(ldet); } } - aContextDecorators.push_back(std::make_shared( + m_contextDecorators.push_back(std::make_shared( std::move(agcsConfig), - Acts::getDefaultLogger("AlignmentDecorator", cfg.decoratorLogLevel))); + Acts::getDefaultLogger("AlignmentDecorator", m_cfg.decoratorLogLevel))); } else { - InternallyAlignedDetectorElement::ContextType nominalContext; - nominalContext.nominal = true; - Acts::GeometryContext geometryContext(nominalContext); - InternalAlignmentDecorator::Config agcsConfig; fillDecoratorConfig(agcsConfig); - aTrackingGeometry = + m_trackingGeometry = Generic::buildDetector( - geometryContext, agcsConfig.detectorStore, cfg.buildLevel, - std::move(mdecorator), cfg.buildProto, cfg.surfaceLogLevel, - cfg.layerLogLevel, cfg.volumeLogLevel); + m_nominalGeometryContext, agcsConfig.detectorStore, + m_cfg.buildLevel, m_cfg.materialDecorator, m_cfg.buildProto, + m_cfg.surfaceLogLevel, m_cfg.layerLogLevel, m_cfg.volumeLogLevel); // need to upcast to store in this object as well for (auto& lstore : agcsConfig.detectorStore) { - auto& target = m_detectorStore.emplace_back(); for (auto& ldet : lstore) { - target.push_back(ldet); + m_detectorStore.push_back(ldet); } } - aContextDecorators.push_back(std::make_shared( + m_contextDecorators.push_back(std::make_shared( std::move(agcsConfig), - Acts::getDefaultLogger("AlignmentDecorator", cfg.decoratorLogLevel))); + Acts::getDefaultLogger("AlignmentDecorator", m_cfg.decoratorLogLevel))); } - - // return the pair of geometry and the alignment decorator(s) - return {std::move(aTrackingGeometry), std::move(aContextDecorators)}; } } // namespace ActsExamples diff --git a/Examples/Detectors/DD4hepDetector/CMakeLists.txt b/Examples/Detectors/DD4hepDetector/CMakeLists.txt index 244b4f20a6d..d09e8e1345f 100644 --- a/Examples/Detectors/DD4hepDetector/CMakeLists.txt +++ b/Examples/Detectors/DD4hepDetector/CMakeLists.txt @@ -1,9 +1,4 @@ -add_library( - ActsExamplesDetectorDD4hep - SHARED - src/DD4hepDetector.cpp - src/DD4hepGeometryService.cpp -) +add_library(ActsExamplesDetectorDD4hep SHARED src/DD4hepDetector.cpp) target_include_directories( ActsExamplesDetectorDD4hep @@ -11,9 +6,37 @@ target_include_directories( ) target_link_libraries( ActsExamplesDetectorDD4hep - PUBLIC ActsCore ActsPluginDD4hep ActsExamplesFramework + PUBLIC + ActsCore + ActsPluginDD4hep + ActsExamplesFramework + ActsExamplesDetectorsCommon ) +if(ACTS_BUILD_EXAMPLES_GEANT4) + if(${DD4hep_VERSION} VERSION_LESS 1.11) + target_link_libraries( + ActsExamplesDetectorDD4hep + PUBLIC ActsExamplesGeant4 ${DD4hep_DDG4_LIBRARY} + ) + else() + target_link_libraries( + ActsExamplesDetectorDD4hep + PUBLIC ActsExamplesGeant4 DD4hep::DDG4 + ) + endif() + + target_sources( + ActsExamplesDetectorDD4hep + PUBLIC src/DDG4DetectorConstruction.cpp src/DD4hepDetectorGeant4.cpp + ) +else() + target_sources( + ActsExamplesDetectorDD4hep + PUBLIC src/DD4hepDetectorGeant4Stub.cpp + ) +endif() + if(${DD4hep_VERSION} VERSION_LESS 1.11) target_include_directories( ActsExamplesDetectorDD4hep diff --git a/Examples/Detectors/DD4hepDetector/include/ActsExamples/DD4hepDetector/DD4hepDetector.hpp b/Examples/Detectors/DD4hepDetector/include/ActsExamples/DD4hepDetector/DD4hepDetector.hpp index 422af198ff5..acb17042e78 100644 --- a/Examples/Detectors/DD4hepDetector/include/ActsExamples/DD4hepDetector/DD4hepDetector.hpp +++ b/Examples/Detectors/DD4hepDetector/include/ActsExamples/DD4hepDetector/DD4hepDetector.hpp @@ -8,84 +8,96 @@ #pragma once -#include "Acts/Plugins/DD4hep/DD4hepDetectorElement.hpp" -#include "Acts/Plugins/DD4hep/DD4hepDetectorStructure.hpp" -#include "ActsExamples/DD4hepDetector/DD4hepGeometryService.hpp" - +#include "Acts/Definitions/Units.hpp" +#include "Acts/Geometry/GeometryIdentifier.hpp" +#include "Acts/Geometry/TrackingGeometry.hpp" +#include "Acts/Material/IMaterialDecorator.hpp" +#include "Acts/Utilities/BinningType.hpp" +#include "Acts/Utilities/Logger.hpp" +#include "ActsExamples/DetectorCommons/Detector.hpp" + +#include #include -#include -#include +#include #include +class TGeoNode; + namespace dd4hep { class Detector; +class DetElement; } // namespace dd4hep -namespace Acts { -class TrackingGeometry; -class IMaterialDecorator; -class DD4hepFieldAdapter; -namespace Experimental { -class Detector; -} // namespace Experimental -} // namespace Acts - namespace ActsExamples { -class IContextDecorator; - -struct DD4hepDetector { - /// @brief The context decorators - using ContextDecorators = std::vector>; - - /// @brief The tracking geometry - using TrackingGeometryPtr = std::shared_ptr; - - /// @brief The detector geometry - using DetectorPtr = std::shared_ptr; - - /// @brief Default constructor - DD4hepDetector() = default; - /// @brief Constructor from geometry service - /// @param _geometryService the geometry service - explicit DD4hepDetector( - std::shared_ptr _geometryService); - /// @brief Default destructor - ~DD4hepDetector() = default; - - /// @brief The DD4hep geometry service - std::shared_ptr geometryService = nullptr; - - /// @brief Build the tracking geometry from the DD4hep geometry - /// - /// @param config is the configuration of the geometry service - /// @param mdecorator is the material decorator provided - /// - /// @return a pair of tracking geometry and context decorators - std::pair finalize( - DD4hepGeometryService::Config config, - std::shared_ptr mdecorator); - - /// @brief Build the detector from the DD4hep geometry - /// - /// @param gctx is the geometry context - /// @param options is the options struct for the building process - /// - /// @note the lifetime of the detector store has to exceed that of the - /// detector object as the converted surfaces point back to the - /// detector elements - /// - /// @return a tuple of detector, context decorators, and the element store - std::tuple - finalize( - const Acts::GeometryContext& gctx, - const Acts::Experimental::DD4hepDetectorStructure::Options& options = {}); - - void drop(); - - /// @brief Access to the DD4hep field - /// @return a shared pointer to the DD4hep field - std::shared_ptr field() const; +void sortFCChhDetElements(std::vector& det); + +/// @class DD4hepDetector +/// +/// @brief geometries from dd4hep input +/// +/// The DD4hepDetector creates the DD4hep, the TGeo and the ACTS +/// TrackingGeometry from DD4hep xml input. +class DD4hepDetector : public Detector { + public: + struct Config { + /// Log level for the geometry service. + Acts::Logging::Level logLevel = Acts::Logging::Level::INFO; + /// Log level for DD4hep itself + Acts::Logging::Level dd4hepLogLevel = Acts::Logging::Level::WARNING; + /// XML-file with the detector description + std::vector xmlFileNames; + /// The name of the service + std::string name = "default"; + /// Binningtype in phi + Acts::BinningType bTypePhi = Acts::equidistant; + /// Binningtype in r + Acts::BinningType bTypeR = Acts::arbitrary; + /// Binningtype in z + Acts::BinningType bTypeZ = Acts::equidistant; + /// The tolerance added to the geometrical extension in r + /// of the layers contained to build the volume envelope around + /// @note this parameter only needs to be set if the volumes containing + /// the + /// layers (e.g. barrel, endcap volumes) have no specific shape + /// (assemblies) + double envelopeR = 1 * Acts::UnitConstants::mm; + /// The tolerance added to the geometrical extension in z + /// of the layers contained to build the volume envelope around + /// @note this parameter only needs to be set if the volumes containing + /// the layers (e.g. barrel, endcap volumes) have no specific shape + /// (assemblies) + double envelopeZ = 1 * Acts::UnitConstants::mm; + double defaultLayerThickness = 1e-10; + std::function& detectors)> + sortDetectors = sortFCChhDetElements; + /// Material decorator + std::shared_ptr materialDecorator; + + /// Optional geometry identifier hook to be used during closure + std::shared_ptr geometryIdentifierHook = + std::make_shared(); + }; + + explicit DD4hepDetector(const Config& cfg); + + /// Interface method to access to the DD4hep geometry + dd4hep::Detector& dd4hepDetector(); + + /// Interface method to Access the TGeo geometry + /// @return The world TGeoNode (physical volume) + TGeoNode& tgeoGeometry(); + + std::unique_ptr buildGeant4DetectorConstruction( + const Geant4ConstructionOptions& options) const override; + + private: + Config m_cfg; + + /// Pointer to the interface to the DD4hep geometry + std::shared_ptr m_detector; + + std::unique_ptr buildDD4hepGeometry() const; }; } // namespace ActsExamples diff --git a/Examples/Detectors/DD4hepDetector/include/ActsExamples/DD4hepDetector/DD4hepGeometryService.hpp b/Examples/Detectors/DD4hepDetector/include/ActsExamples/DD4hepDetector/DD4hepGeometryService.hpp deleted file mode 100644 index 1111f8de8e7..00000000000 --- a/Examples/Detectors/DD4hepDetector/include/ActsExamples/DD4hepDetector/DD4hepGeometryService.hpp +++ /dev/null @@ -1,137 +0,0 @@ -// This file is part of the ACTS project. -// -// Copyright (C) 2016 CERN for the benefit of the ACTS project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at https://mozilla.org/MPL/2.0/. - -#pragma once - -#include "Acts/Geometry/GeometryContext.hpp" -#include "Acts/Geometry/GeometryIdentifier.hpp" -#include "ActsExamples/Framework/ProcessCode.hpp" -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -class TGeoNode; -namespace Acts { -class IMaterialDecorator; -class TrackingGeometry; -} // namespace Acts -namespace dd4hep { -class Detector; -} // namespace dd4hep - -namespace ActsExamples { - -void sortFCChhDetElements(std::vector& det); - -/// @class DD4hepGeometryService -/// -/// @brief service creating geometries from dd4hep input -/// -/// The DD4hepGeometryService creates the DD4hep, the TGeo and the ACTS -/// TrackingGeometry -/// from DD4hep xml input. The geometries are created only on demand. -class DD4hepGeometryService { - public: - struct Config { - /// Log level for the geometry service. - Acts::Logging::Level logLevel = Acts::Logging::Level::INFO; - /// Log level for DD4hep itself - Acts::Logging::Level dd4hepLogLevel = Acts::Logging::Level::WARNING; - /// XML-file with the detector description - std::vector xmlFileNames; - /// The name of the service - std::string name = "default"; - /// Binningtype in phi - Acts::BinningType bTypePhi = Acts::equidistant; - /// Binningtype in r - Acts::BinningType bTypeR = Acts::arbitrary; - /// Binningtype in z - Acts::BinningType bTypeZ = Acts::equidistant; - /// The tolerance added to the geometrical extension in r - /// of the layers contained to build the volume envelope around - /// @note this parameter only needs to be set if the volumes containing - /// the - /// layers (e.g. barrel, endcap volumes) have no specific shape - /// (assemblies) - double envelopeR = 1 * Acts::UnitConstants::mm; - /// The tolerance added to the geometrical extension in z - /// of the layers contained to build the volume envelope around - /// @note this parameter only needs to be set if the volumes containing - /// the layers (e.g. barrel, endcap volumes) have no specific shape - /// (assemblies) - double envelopeZ = 1 * Acts::UnitConstants::mm; - double defaultLayerThickness = 10e-10; - std::function& detectors)> - sortDetectors = sortFCChhDetElements; - /// Material decorator - std::shared_ptr matDecorator; - - /// Optional geometry identifier hook to be used during closure - std::shared_ptr geometryIdentifierHook = - std::make_shared(); - }; - - explicit DD4hepGeometryService(const Config& cfg); - DD4hepGeometryService(const DD4hepGeometryService&) = delete; - DD4hepGeometryService(DD4hepGeometryService&&) = delete; - ~DD4hepGeometryService(); - DD4hepGeometryService& operator=(const DD4hepGeometryService&) = delete; - DD4hepGeometryService& operator=(DD4hepGeometryService&&) = delete; - - /// Interface method to access to the DD4hep geometry - dd4hep::Detector& detector(); - - /// Interface method to access the DD4hep geometry - /// @return The world DD4hep DetElement - dd4hep::DetElement& geometry(); - - /// Interface method to Access the TGeo geometry - /// @return The world TGeoNode (physical volume) - TGeoNode& tgeoGeometry(); - - /// Interface method to access the ACTS TrackingGeometry - /// - /// @param gctx is the geometry context object - std::shared_ptr trackingGeometry( - const Acts::GeometryContext& gctx); - - void drop(); - - private: - /// Private method to initiate building of the DD4hep geometry - ProcessCode buildDD4hepGeometry(); - - /// Private method to initiate building of the ACTS tracking geometry - ProcessCode buildTrackingGeometry(const Acts::GeometryContext& gctx); - - /// The config class - Config m_cfg; - /// Pointer to the interface to the DD4hep geometry - dd4hep::Detector* m_detector = nullptr; - /// The world DD4hep DetElement - dd4hep::DetElement m_geometry; - /// The ACTS TrackingGeometry - std::shared_ptr m_trackingGeometry; - - const Acts::Logger& logger() const { return *m_logger; } - - std::unique_ptr m_logger; -}; - -} // namespace ActsExamples diff --git a/Examples/Detectors/DD4hepDetector/include/ActsExamples/DD4hepDetector/DDG4DetectorConstruction.hpp b/Examples/Detectors/DD4hepDetector/include/ActsExamples/DD4hepDetector/DDG4DetectorConstruction.hpp new file mode 100644 index 00000000000..aef260161c3 --- /dev/null +++ b/Examples/Detectors/DD4hepDetector/include/ActsExamples/DD4hepDetector/DDG4DetectorConstruction.hpp @@ -0,0 +1,50 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#pragma once + +#include "ActsExamples/Geant4/Geant4ConstructionOptions.hpp" + +#include + +#include + +class G4VPhysicalVolume; + +namespace dd4hep { +class Detector; +} // namespace dd4hep + +namespace ActsExamples { +class DD4hepDetector; + +/// Construct the Geant4 detector from a DD4hep description. +class DDG4DetectorConstruction final : public G4VUserDetectorConstruction { + public: + explicit DDG4DetectorConstruction(std::shared_ptr detector, + const Geant4ConstructionOptions& options); + + /// Convert the stored DD4hep detector to a Geant4 description. + /// + /// Transfers ownership of the created object as all volumes (including world) + /// are deleted in ~G4PhysicalVolumeStore(). + /// + /// @note for facilitating configuration within the ACTS framework the world + /// volume is cached + G4VPhysicalVolume* Construct() final; + + private: + /// The DD4hep detector instance + std::shared_ptr m_detector; + /// Construction options + Geant4ConstructionOptions m_options; + /// The world volume + G4VPhysicalVolume* m_world = nullptr; +}; + +} // namespace ActsExamples diff --git a/Examples/Detectors/DD4hepDetector/src/DD4hepDetector.cpp b/Examples/Detectors/DD4hepDetector/src/DD4hepDetector.cpp index a2c12dfaaa7..a411a32a028 100644 --- a/Examples/Detectors/DD4hepDetector/src/DD4hepDetector.cpp +++ b/Examples/Detectors/DD4hepDetector/src/DD4hepDetector.cpp @@ -8,77 +8,136 @@ #include "ActsExamples/DD4hepDetector/DD4hepDetector.hpp" -#include "Acts/Geometry/GeometryContext.hpp" -#include "Acts/Plugins/DD4hep/DD4hepFieldAdapter.hpp" -#include "ActsExamples/DD4hepDetector/DD4hepGeometryService.hpp" +#include "Acts/Plugins/DD4hep/ConvertDD4hepDetector.hpp" +#include "Acts/Utilities/Logger.hpp" +#include #include #include -#include #include #include -#include -#include +#include +#include +#include +#include namespace ActsExamples { -DD4hepDetector::DD4hepDetector( - std::shared_ptr _geometryService) - : geometryService(std::move(_geometryService)) {} - -auto DD4hepDetector::finalize( - DD4hepGeometryService::Config config, - std::shared_ptr mdecorator) - -> std::pair { - Acts::GeometryContext dd4HepContext; - config.matDecorator = std::move(mdecorator); - geometryService = std::make_shared(config); - TrackingGeometryPtr dd4tGeometry = - geometryService->trackingGeometry(dd4HepContext); - if (!dd4tGeometry) { - throw std::runtime_error{ - "Did not receive tracking geometry from DD4hep geometry service"}; - } - ContextDecorators dd4ContextDecorators = {}; - // return the pair of geometry and empty decorators - return {std::move(dd4tGeometry), std::move(dd4ContextDecorators)}; -} - -auto DD4hepDetector::finalize( - const Acts::GeometryContext& gctx, - const Acts::Experimental::DD4hepDetectorStructure::Options& options) - -> std::tuple { - if (geometryService == nullptr) { - throw std::runtime_error{ - "No DD4hep geometry service configured, can not build " - "TrackingGeometry."}; +DD4hepDetector::DD4hepDetector(const Config& cfg) + : Detector(Acts::getDefaultLogger("DD4hepDetector", cfg.logLevel)), + m_cfg(cfg) { + if (m_cfg.xmlFileNames.empty()) { + throw std::invalid_argument("Missing DD4hep XML filenames"); } - auto world = geometryService->geometry(); - // Build the detector structure - Acts::Experimental::DD4hepDetectorStructure dd4hepStructure( - Acts::getDefaultLogger("DD4hepDetectorStructure", options.logLevel)); + m_nominalGeometryContext = Acts::GeometryContext(); - /// @return a detector and the detector store - auto [detector, detectorElements] = - dd4hepStructure.construct(gctx, world, options); + m_detector = buildDD4hepGeometry(); - // Prepare the return objects - ContextDecorators contextDecorators = {}; + auto logger = Acts::getDefaultLogger("DD4hepConversion", m_cfg.logLevel); + m_trackingGeometry = Acts::convertDD4hepDetector( + m_detector->world(), *logger, m_cfg.bTypePhi, m_cfg.bTypeR, m_cfg.bTypeZ, + m_cfg.envelopeR, m_cfg.envelopeZ, m_cfg.defaultLayerThickness, + m_cfg.sortDetectors, m_nominalGeometryContext, m_cfg.materialDecorator, + m_cfg.geometryIdentifierHook); +} - return {detector, contextDecorators, detectorElements}; +dd4hep::Detector& DD4hepDetector::dd4hepDetector() { + return *m_detector; } -void DD4hepDetector::drop() { - geometryService->drop(); +TGeoNode& DD4hepDetector::tgeoGeometry() { + return *m_detector->world().placement().ptr(); } -std::shared_ptr DD4hepDetector::field() const { - const auto& detector = geometryService->detector(); +std::unique_ptr DD4hepDetector::buildDD4hepGeometry() const { + const int old_gErrorIgnoreLevel = gErrorIgnoreLevel; + switch (m_cfg.dd4hepLogLevel) { + case Acts::Logging::Level::VERBOSE: + dd4hep::setPrintLevel(dd4hep::PrintLevel::VERBOSE); + break; + case Acts::Logging::Level::DEBUG: + dd4hep::setPrintLevel(dd4hep::PrintLevel::DEBUG); + break; + case Acts::Logging::Level::INFO: + dd4hep::setPrintLevel(dd4hep::PrintLevel::INFO); + break; + case Acts::Logging::Level::WARNING: + dd4hep::setPrintLevel(dd4hep::PrintLevel::WARNING); + gErrorIgnoreLevel = kWarning; + break; + case Acts::Logging::Level::ERROR: + dd4hep::setPrintLevel(dd4hep::PrintLevel::ERROR); + gErrorIgnoreLevel = kError; + break; + case Acts::Logging::Level::FATAL: + dd4hep::setPrintLevel(dd4hep::PrintLevel::FATAL); + gErrorIgnoreLevel = kFatal; + break; + case Acts::Logging::Level::MAX: + dd4hep::setPrintLevel(dd4hep::PrintLevel::ALWAYS); + break; + } + // completely silence std::cout as DD4HEP is using it for logging + if (m_cfg.dd4hepLogLevel >= Acts::Logging::Level::WARNING) { + std::cout.setstate(std::ios_base::failbit); + } + + std::unique_ptr detector = + dd4hep::Detector::make_unique(m_cfg.name); + for (auto& file : m_cfg.xmlFileNames) { + detector->fromCompact(file.c_str()); + } + detector->volumeManager(); + detector->apply("DD4hepVolumeManager", 0, nullptr); + + // restore the logging + gErrorIgnoreLevel = old_gErrorIgnoreLevel; + std::cout.clear(); - return std::make_shared(detector.field()); + return detector; } } // namespace ActsExamples + +void ActsExamples::sortFCChhDetElements(std::vector& det) { + std::vector tracker; + std::vector eCal; + std::vector hCal; + std::vector muon; + for (auto& detElement : det) { + std::string detName = detElement.name(); + if (detName.find("Muon") != std::string::npos) { + muon.push_back(detElement); + } else if (detName.find("ECal") != std::string::npos) { + eCal.push_back(detElement); + } else if (detName.find("HCal") != std::string::npos) { + hCal.push_back(detElement); + } else { + tracker.push_back(detElement); + } + } + sort(muon.begin(), muon.end(), + [](const dd4hep::DetElement& a, const dd4hep::DetElement& b) { + return (a.id() < b.id()); + }); + sort(eCal.begin(), eCal.end(), + [](const dd4hep::DetElement& a, const dd4hep::DetElement& b) { + return (a.id() < b.id()); + }); + sort(hCal.begin(), hCal.end(), + [](const dd4hep::DetElement& a, const dd4hep::DetElement& b) { + return (a.id() < b.id()); + }); + sort(tracker.begin(), tracker.end(), + [](const dd4hep::DetElement& a, const dd4hep::DetElement& b) { + return (a.id() < b.id()); + }); + det.clear(); + det = tracker; + + det.insert(det.end(), eCal.begin(), eCal.end()); + det.insert(det.end(), hCal.begin(), hCal.end()); + det.insert(det.end(), muon.begin(), muon.end()); +} diff --git a/Examples/Detectors/DD4hepDetector/src/DD4hepDetectorGeant4.cpp b/Examples/Detectors/DD4hepDetector/src/DD4hepDetectorGeant4.cpp new file mode 100644 index 00000000000..ab2510fe8ae --- /dev/null +++ b/Examples/Detectors/DD4hepDetector/src/DD4hepDetectorGeant4.cpp @@ -0,0 +1,22 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include "ActsExamples/DD4hepDetector/DD4hepDetector.hpp" +#include "ActsExamples/DD4hepDetector/DDG4DetectorConstruction.hpp" + +#include + +namespace ActsExamples { + +std::unique_ptr +DD4hepDetector::buildGeant4DetectorConstruction( + const Geant4ConstructionOptions& options) const { + return std::make_unique(m_detector, options); +} + +} // namespace ActsExamples diff --git a/Examples/Detectors/DD4hepDetector/src/DD4hepDetectorGeant4Stub.cpp b/Examples/Detectors/DD4hepDetector/src/DD4hepDetectorGeant4Stub.cpp new file mode 100644 index 00000000000..ea08bab2bfc --- /dev/null +++ b/Examples/Detectors/DD4hepDetector/src/DD4hepDetectorGeant4Stub.cpp @@ -0,0 +1,19 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include "ActsExamples/DD4hepDetector/DD4hepDetector.hpp" + +namespace ActsExamples { + +std::unique_ptr +DD4hepDetector::buildGeant4DetectorConstruction( + const Geant4ConstructionOptions& /*options*/) const { + throw std::runtime_error("Geant4 is not enabled"); +} + +} // namespace ActsExamples diff --git a/Examples/Detectors/DD4hepDetector/src/DD4hepGeometryService.cpp b/Examples/Detectors/DD4hepDetector/src/DD4hepGeometryService.cpp deleted file mode 100644 index c746dd84343..00000000000 --- a/Examples/Detectors/DD4hepDetector/src/DD4hepGeometryService.cpp +++ /dev/null @@ -1,174 +0,0 @@ -// This file is part of the ACTS project. -// -// Copyright (C) 2016 CERN for the benefit of the ACTS project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at https://mozilla.org/MPL/2.0/. - -#include "ActsExamples/DD4hepDetector/DD4hepGeometryService.hpp" - -#include "Acts/Geometry/TrackingGeometry.hpp" -#include "Acts/Plugins/DD4hep/ConvertDD4hepDetector.hpp" -#include "Acts/Utilities/Logger.hpp" - -#include -#include -#include - -#include -#include -#include -#include -#include - -namespace ActsExamples { - -DD4hepGeometryService::DD4hepGeometryService(const Config& cfg) - : m_cfg(cfg), - m_logger{Acts::getDefaultLogger("DD4hepGeometryService", cfg.logLevel)} { - if (m_cfg.xmlFileNames.empty()) { - throw std::invalid_argument("Missing DD4hep XML filenames"); - } -} - -DD4hepGeometryService::~DD4hepGeometryService() { - drop(); -} - -ProcessCode DD4hepGeometryService::buildDD4hepGeometry() { - const int old_gErrorIgnoreLevel = gErrorIgnoreLevel; - switch (m_cfg.dd4hepLogLevel) { - case Acts::Logging::Level::VERBOSE: - dd4hep::setPrintLevel(dd4hep::PrintLevel::VERBOSE); - break; - case Acts::Logging::Level::DEBUG: - dd4hep::setPrintLevel(dd4hep::PrintLevel::DEBUG); - break; - case Acts::Logging::Level::INFO: - dd4hep::setPrintLevel(dd4hep::PrintLevel::INFO); - break; - case Acts::Logging::Level::WARNING: - dd4hep::setPrintLevel(dd4hep::PrintLevel::WARNING); - gErrorIgnoreLevel = kWarning; - break; - case Acts::Logging::Level::ERROR: - dd4hep::setPrintLevel(dd4hep::PrintLevel::ERROR); - gErrorIgnoreLevel = kError; - break; - case Acts::Logging::Level::FATAL: - dd4hep::setPrintLevel(dd4hep::PrintLevel::FATAL); - gErrorIgnoreLevel = kFatal; - break; - case Acts::Logging::Level::MAX: - dd4hep::setPrintLevel(dd4hep::PrintLevel::ALWAYS); - break; - } - // completely silence std::cout as DD4HEP is using it for logging - if (m_cfg.dd4hepLogLevel >= Acts::Logging::Level::WARNING) { - std::cout.setstate(std::ios_base::failbit); - } - - m_detector = &dd4hep::Detector::getInstance(); - for (auto& file : m_cfg.xmlFileNames) { - m_detector->fromCompact(file.c_str()); - } - m_detector->volumeManager(); - m_detector->apply("DD4hepVolumeManager", 0, nullptr); - m_geometry = m_detector->world(); - - // restore the logging - gErrorIgnoreLevel = old_gErrorIgnoreLevel; - std::cout.clear(); - - return ProcessCode::SUCCESS; -} - -dd4hep::Detector& DD4hepGeometryService::detector() { - if (m_detector == nullptr) { - buildDD4hepGeometry(); - } - return *m_detector; -} - -dd4hep::DetElement& DD4hepGeometryService::geometry() { - if (!m_geometry) { - buildDD4hepGeometry(); - } - return m_geometry; -} - -TGeoNode& DD4hepGeometryService::tgeoGeometry() { - if (!m_geometry) { - buildDD4hepGeometry(); - } - return *m_geometry.placement().ptr(); -} - -ProcessCode DD4hepGeometryService::buildTrackingGeometry( - const Acts::GeometryContext& gctx) { - // Set the tracking geometry - auto logger = Acts::getDefaultLogger("DD4hepConversion", m_cfg.logLevel); - m_trackingGeometry = Acts::convertDD4hepDetector( - geometry(), *logger, m_cfg.bTypePhi, m_cfg.bTypeR, m_cfg.bTypeZ, - m_cfg.envelopeR, m_cfg.envelopeZ, m_cfg.defaultLayerThickness, - m_cfg.sortDetectors, gctx, m_cfg.matDecorator, - m_cfg.geometryIdentifierHook); - return ProcessCode::SUCCESS; -} - -std::shared_ptr -DD4hepGeometryService::trackingGeometry(const Acts::GeometryContext& gctx) { - if (!m_trackingGeometry) { - buildTrackingGeometry(gctx); - } - return m_trackingGeometry; -} - -void DD4hepGeometryService::drop() { - if (m_detector == nullptr) { - return; - } - dd4hep::Detector::destroyInstance(m_cfg.name); - m_detector = nullptr; - m_geometry = dd4hep::DetElement(); - m_trackingGeometry = nullptr; -} - -void sortFCChhDetElements(std::vector& det) { - std::vector tracker; - std::vector eCal; - std::vector hCal; - std::vector muon; - - for (auto& detElement : det) { - std::string detName = detElement.name(); - if (detName.find("Muon") != std::string::npos) { - muon.push_back(detElement); - } else if (detName.find("ECal") != std::string::npos) { - eCal.push_back(detElement); - } else if (detName.find("HCal") != std::string::npos) { - hCal.push_back(detElement); - } else { - tracker.push_back(detElement); - } - } - - auto byId = [](const dd4hep::DetElement& a, - const dd4hep::DetElement& b) -> bool { - return a.id() < b.id(); - }; - sort(muon.begin(), muon.end(), byId); - sort(eCal.begin(), eCal.end(), byId); - sort(hCal.begin(), hCal.end(), byId); - sort(tracker.begin(), tracker.end(), byId); - - det.clear(); - det = tracker; - - det.insert(det.end(), eCal.begin(), eCal.end()); - det.insert(det.end(), hCal.begin(), hCal.end()); - det.insert(det.end(), muon.begin(), muon.end()); -} - -} // namespace ActsExamples diff --git a/Examples/Detectors/DD4hepDetector/src/DDG4DetectorConstruction.cpp b/Examples/Detectors/DD4hepDetector/src/DDG4DetectorConstruction.cpp new file mode 100644 index 00000000000..41700ae063e --- /dev/null +++ b/Examples/Detectors/DD4hepDetector/src/DDG4DetectorConstruction.cpp @@ -0,0 +1,52 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include "ActsExamples/DD4hepDetector/DDG4DetectorConstruction.hpp" + +#include "ActsExamples/DD4hepDetector/DD4hepDetector.hpp" +#include "ActsExamples/Geant4/RegionCreator.hpp" + +#include +#include +#include +#include +#include + +class G4VPhysicalVolume; + +namespace ActsExamples { + +DDG4DetectorConstruction::DDG4DetectorConstruction( + std::shared_ptr detector, + const Geant4ConstructionOptions& options) + : m_detector(std::move(detector)), m_options(options) {} + +// See DD4hep::Simulation::Geant4DetectorConstruction::Construct() +G4VPhysicalVolume* DDG4DetectorConstruction::Construct() { + if (m_world == nullptr) { + dd4hep::sim::Geant4Mapping g4map(*m_detector); + dd4hep::sim::Geant4Converter g4conv(*m_detector, + dd4hep::PrintLevel::VERBOSE); + dd4hep::sim::Geant4GeometryInfo* geoInfo = + g4conv.create(m_detector->world()).detach(); + g4map.attach(geoInfo); + // All volumes are deleted in ~G4PhysicalVolumeStore() + m_world = geoInfo->world(); + // Create Geant4 volume manager + g4map.volumeManager(); + + // Create regions + for (const auto& regionCreator : m_options.regionCreators) { + regionCreator->buildRegion(); + } + } + + return m_world; +} + +} // namespace ActsExamples diff --git a/Examples/Detectors/Geant4Detector/CMakeLists.txt b/Examples/Detectors/Geant4Detector/CMakeLists.txt index 8a83657de5a..541271e65a5 100644 --- a/Examples/Detectors/Geant4Detector/CMakeLists.txt +++ b/Examples/Detectors/Geant4Detector/CMakeLists.txt @@ -1,11 +1,24 @@ -add_library(ActsExamplesDetectorGeant4 SHARED src/Geant4Detector.cpp) +add_library( + ActsExamplesDetectorGeant4 + SHARED + src/Geant4Detector.cpp + src/GdmlDetectorConstruction.cpp + src/GdmlDetector.cpp +) + target_include_directories( ActsExamplesDetectorGeant4 PUBLIC $ ) + target_link_libraries( ActsExamplesDetectorGeant4 - PUBLIC ActsCore ActsExamplesFramework ActsExamplesGeant4 ActsPluginGeant4 + PUBLIC + ActsCore + ActsExamplesFramework + ActsExamplesGeant4 + ActsPluginGeant4 + ActsExamplesDetectorsCommon ) install( diff --git a/Examples/Detectors/Geant4Detector/include/ActsExamples/Geant4Detector/GdmlDetector.hpp b/Examples/Detectors/Geant4Detector/include/ActsExamples/Geant4Detector/GdmlDetector.hpp new file mode 100644 index 00000000000..df2c00778be --- /dev/null +++ b/Examples/Detectors/Geant4Detector/include/ActsExamples/Geant4Detector/GdmlDetector.hpp @@ -0,0 +1,36 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#pragma once + +#include "Acts/Utilities/Logger.hpp" +#include "ActsExamples/DetectorCommons/Detector.hpp" + +#include + +namespace ActsExamples { + +class GdmlDetector : public Detector { + public: + struct Config { + std::string path; + + /// Logging level of the child tools + Acts::Logging::Level logLevel = Acts::Logging::INFO; + }; + + explicit GdmlDetector(const Config& cfg); + + std::unique_ptr buildGeant4DetectorConstruction( + const Geant4ConstructionOptions& options) const override; + + private: + Config m_cfg; +}; + +} // namespace ActsExamples diff --git a/Examples/Algorithms/Geant4/include/ActsExamples/Geant4/GdmlDetectorConstruction.hpp b/Examples/Detectors/Geant4Detector/include/ActsExamples/Geant4Detector/GdmlDetectorConstruction.hpp similarity index 56% rename from Examples/Algorithms/Geant4/include/ActsExamples/Geant4/GdmlDetectorConstruction.hpp rename to Examples/Detectors/Geant4Detector/include/ActsExamples/Geant4Detector/GdmlDetectorConstruction.hpp index 69156e94e06..c712023f19e 100644 --- a/Examples/Algorithms/Geant4/include/ActsExamples/Geant4/GdmlDetectorConstruction.hpp +++ b/Examples/Detectors/Geant4Detector/include/ActsExamples/Geant4Detector/GdmlDetectorConstruction.hpp @@ -8,8 +8,7 @@ #pragma once -#include "ActsExamples/Geant4/DetectorConstructionFactory.hpp" -#include "ActsExamples/Geant4/RegionCreator.hpp" +#include "ActsExamples/Geant4/Geant4ConstructionOptions.hpp" #include @@ -24,9 +23,8 @@ class GdmlDetectorConstruction final : public G4VUserDetectorConstruction { public: /// @param path is the path to the Gdml file /// @param regionCreators are the region creators - GdmlDetectorConstruction( - std::string path, - std::vector> regionCreators = {}); + GdmlDetectorConstruction(std::string path, + const Geant4ConstructionOptions& options); /// Read the file and parse it to construct the Geant4 description /// @@ -37,26 +35,10 @@ class GdmlDetectorConstruction final : public G4VUserDetectorConstruction { private: /// Path to the Gdml file std::string m_path; - /// Region creators - std::vector> m_regionCreators; + /// Construction options + Geant4ConstructionOptions m_options; /// Cached world volume G4VPhysicalVolume* m_world = nullptr; }; -class GdmlDetectorConstructionFactory final - : public Geant4::DetectorConstructionFactory { - public: - GdmlDetectorConstructionFactory( - std::string path, - std::vector> regionCreators = {}); - - std::unique_ptr factorize() const override; - - private: - /// Path to the Gdml file - std::string m_path; - /// Region creators - std::vector> m_regionCreators; -}; - } // namespace ActsExamples diff --git a/Examples/Detectors/Geant4Detector/include/ActsExamples/Geant4Detector/Geant4Detector.hpp b/Examples/Detectors/Geant4Detector/include/ActsExamples/Geant4Detector/Geant4Detector.hpp index 32c7a7568ea..cad39584a36 100644 --- a/Examples/Detectors/Geant4Detector/include/ActsExamples/Geant4Detector/Geant4Detector.hpp +++ b/Examples/Detectors/Geant4Detector/include/ActsExamples/Geant4Detector/Geant4Detector.hpp @@ -12,6 +12,7 @@ #include "Acts/Geometry/GeometryIdentifier.hpp" #include "Acts/Plugins/Geant4/Geant4DetectorSurfaceFactory.hpp" #include "Acts/Utilities/Logger.hpp" +#include "ActsExamples/DetectorCommons/Detector.hpp" #include #include @@ -20,29 +21,9 @@ class G4VPhysicalVolume; -namespace Acts { -class TrackingGeometry; -class Geant4DetectorElement; -class Surface; - -namespace Experimental { -class Detector; -} -} // namespace Acts - namespace ActsExamples { -class IContextDecorator; - -struct Geant4Detector { - using DetectorElements = - std::vector>; - using DetectorPtr = std::shared_ptr; - using Surfaces = std::vector>; - - using ContextDecorators = std::vector>; - using TrackingGeometryPtr = std::shared_ptr; - +struct Geant4Detector : public Detector { /// Nested configuration struct struct Config { /// The detector/geometry name @@ -60,32 +41,20 @@ struct Geant4Detector { Acts::Logging::Level logLevel = Acts::Logging::INFO; }; - /// @brief Construct an Acts::Detector from a Geant4 world volume - /// @param cfg the configuration of the Geant4 detector - /// @param logger a logger instance - /// @return a tuple of an Acts::Detector object, a ContextDecorator & the created detector elements - std::tuple - constructDetector(const Config& cfg, const Acts::Logger& logger); - - /// @brief Construct a TrackingGeometry from a Geant4 world volume using the KDTreeTrackingGeometryBuilder builder - /// - /// @param cfg the configuration of the Geant4 detector - /// @param kdtCfg the configuration of the KDTreeTrackingGeometryBuilder - /// @param logger a logger instance - /// - /// @return a tuple of an Acts::TrackingGeometry object, a ContextDecorator & the created detector elements - std::tuple - constructTrackingGeometry(const Config& cfg, const Acts::Logger& logger); - - private: /// @brief Convert Geant4VPhysicalVolume objects into Acts components /// /// @param cfg the configuration of the Geant4 detector /// @param logger a logger instance /// /// @return a tuple of surfaces and detector elements - std::tuple convertGeant4Volumes( - const Config& cfg, const Acts::Logger& logger) const; + static std::tuple>, + std::vector>> + buildGeant4Volumes(const Config& cfg, const Acts::Logger& logger); + + explicit Geant4Detector(const Config& cfg); + + private: + Config m_cfg; }; } // namespace ActsExamples diff --git a/Examples/Detectors/Geant4Detector/src/GdmlDetector.cpp b/Examples/Detectors/Geant4Detector/src/GdmlDetector.cpp new file mode 100644 index 00000000000..75f0a6ba036 --- /dev/null +++ b/Examples/Detectors/Geant4Detector/src/GdmlDetector.cpp @@ -0,0 +1,27 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include "ActsExamples/Geant4Detector/GdmlDetector.hpp" + +#include "ActsExamples/Geant4Detector/GdmlDetectorConstruction.hpp" + +#include + +namespace ActsExamples { + +GdmlDetector::GdmlDetector(const Config& cfg) + : Detector(Acts::getDefaultLogger("GdmlDetector", cfg.logLevel)), + m_cfg(cfg) {} + +std::unique_ptr +GdmlDetector::buildGeant4DetectorConstruction( + const Geant4ConstructionOptions& options) const { + return std::make_unique(m_cfg.path, options); +} + +} // namespace ActsExamples diff --git a/Examples/Detectors/Geant4Detector/src/GdmlDetectorConstruction.cpp b/Examples/Detectors/Geant4Detector/src/GdmlDetectorConstruction.cpp new file mode 100644 index 00000000000..b617cf687b6 --- /dev/null +++ b/Examples/Detectors/Geant4Detector/src/GdmlDetectorConstruction.cpp @@ -0,0 +1,41 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include "ActsExamples/Geant4Detector/GdmlDetectorConstruction.hpp" + +#include "ActsExamples/Geant4/Geant4ConstructionOptions.hpp" +#include "ActsExamples/Geant4/RegionCreator.hpp" + +#include + +#include + +namespace ActsExamples { + +GdmlDetectorConstruction::GdmlDetectorConstruction( + std::string path, const Geant4ConstructionOptions& options) + : G4VUserDetectorConstruction(), + m_path(std::move(path)), + m_options(options) {} + +G4VPhysicalVolume* GdmlDetectorConstruction::Construct() { + if (m_world == nullptr) { + G4GDMLParser parser; + // TODO how to handle errors + parser.Read(m_path); + m_world = parser.GetWorldVolume(); + + // Create regions + for (const auto& regionCreator : m_options.regionCreators) { + regionCreator->buildRegion(); + } + } + return m_world; +} + +} // namespace ActsExamples diff --git a/Examples/Detectors/Geant4Detector/src/Geant4Detector.cpp b/Examples/Detectors/Geant4Detector/src/Geant4Detector.cpp index 67ab547db26..15642e9f912 100644 --- a/Examples/Detectors/Geant4Detector/src/Geant4Detector.cpp +++ b/Examples/Detectors/Geant4Detector/src/Geant4Detector.cpp @@ -9,14 +9,16 @@ #include "ActsExamples/Geant4Detector/Geant4Detector.hpp" #include "Acts/Geometry/CylinderVolumeHelper.hpp" -#include "Acts/Geometry/GeometryContext.hpp" #include "Acts/Geometry/KDTreeTrackingGeometryBuilder.hpp" #include "Acts/Geometry/LayerArrayCreator.hpp" #include "Acts/Geometry/LayerCreator.hpp" #include "Acts/Geometry/SurfaceArrayCreator.hpp" #include "Acts/Geometry/TrackingGeometry.hpp" #include "Acts/Geometry/TrackingVolumeArrayCreator.hpp" +#include "Acts/Plugins/Geant4/Geant4DetectorElement.hpp" +#include "Acts/Surfaces/Surface.hpp" +#include #include #include @@ -25,88 +27,67 @@ namespace ActsExamples { -auto Geant4Detector::constructDetector(const Geant4Detector::Config& cfg, - const Acts::Logger& logger) - -> std::tuple { - if (cfg.g4World == nullptr) { - throw std::invalid_argument( - "Geant4Detector: no world Geant4 volume provided"); - } - - ACTS_INFO("Building an Acts::Detector called '" - << cfg.name << "' from the Geant4PhysVolume '" - << cfg.g4World->GetName() << "'"); - - DetectorPtr detector = nullptr; - ContextDecorators decorators = {}; - - auto [surfaces, elements] = convertGeant4Volumes(cfg, logger); - - return std::tie(detector, decorators, elements); -} - -auto Geant4Detector::constructTrackingGeometry( - const Geant4Detector::Config& cfg, const Acts::Logger& logger) - -> std::tuple { - if (cfg.g4World == nullptr) { +Geant4Detector::Geant4Detector(const Config& cfg) + : Detector(Acts::getDefaultLogger("Geant4Detector", cfg.logLevel)), + m_cfg(cfg) { + if (m_cfg.g4World == nullptr) { throw std::invalid_argument( "Geant4Detector: no world Geant4 volume provided"); } ACTS_INFO("Building an Acts::TrackingGeometry called '" - << cfg.name << "' from the Geant4PhysVolume '" - << cfg.g4World->GetName() << "'"); + << m_cfg.name << "' from the Geant4PhysVolume '" + << m_cfg.g4World->GetName() << "'"); - ContextDecorators decorators = {}; + m_nominalGeometryContext = Acts::GeometryContext(); - auto [surfaces, elements] = convertGeant4Volumes(cfg, logger); + auto [surfaces, elements] = buildGeant4Volumes(cfg, logger()); // Surface array creator auto surfaceArrayCreator = std::make_shared( - Acts::SurfaceArrayCreator::Config(), logger.clone("SurfaceArrayCreator")); + Acts::SurfaceArrayCreator::Config(), + logger().clone("SurfaceArrayCreator")); // Layer Creator Acts::LayerCreator::Config lcConfig; lcConfig.surfaceArrayCreator = surfaceArrayCreator; auto layerCreator = std::make_shared( - lcConfig, logger.clone("LayerCreator")); + lcConfig, logger().clone("LayerCreator")); // Layer array creator Acts::LayerArrayCreator::Config lacConfig; auto layerArrayCreator = std::make_shared( - lacConfig, logger.clone("LayerArrayCreator")); + lacConfig, logger().clone("LayerArrayCreator")); // Tracking volume array creator Acts::TrackingVolumeArrayCreator::Config tvacConfig; auto tVolumeArrayCreator = std::make_shared( - tvacConfig, logger.clone("TrackingVolumeArrayCreator")); + tvacConfig, logger().clone("TrackingVolumeArrayCreator")); // configure the cylinder volume helper Acts::CylinderVolumeHelper::Config cvhConfig; cvhConfig.layerArrayCreator = layerArrayCreator; cvhConfig.trackingVolumeArrayCreator = tVolumeArrayCreator; auto cylinderVolumeHelper = std::make_shared( - cvhConfig, logger.clone("CylinderVolumeHelper")); + cvhConfig, logger().clone("CylinderVolumeHelper")); // Configure the tracking geometry builder, copy the surfaces in Acts::KDTreeTrackingGeometryBuilder::Config kdtCfg; kdtCfg.surfaces = surfaces; kdtCfg.layerCreator = layerCreator; kdtCfg.trackingVolumeHelper = cylinderVolumeHelper; - kdtCfg.protoDetector = cfg.protoDetector; - kdtCfg.geometryIdentifierHook = cfg.geometryIdentifierHook; + kdtCfg.protoDetector = m_cfg.protoDetector; + kdtCfg.geometryIdentifierHook = m_cfg.geometryIdentifierHook; // The KDT tracking geometry builder auto kdtBuilder = Acts::KDTreeTrackingGeometryBuilder( - kdtCfg, logger.clone("KDTreeTrackingGeometryBuilder")); + kdtCfg, logger().clone("KDTreeTrackingGeometryBuilder")); - Acts::GeometryContext tContext; - TrackingGeometryPtr trackingGeometry = kdtBuilder.trackingGeometry(tContext); - - return std::tie(trackingGeometry, decorators, elements); + m_trackingGeometry = kdtBuilder.trackingGeometry(m_nominalGeometryContext); } -auto Geant4Detector::convertGeant4Volumes(const Geant4Detector::Config& cfg, - const Acts::Logger& logger) const - -> std::tuple { +std::tuple>, + std::vector>> +Geant4Detector::buildGeant4Volumes(const Config& cfg, + const Acts::Logger& logger) { // Generate the surface cache Acts::Geant4DetectorSurfaceFactory::Cache g4SurfaceCache; G4Transform3D g4ToWorld; @@ -123,8 +104,8 @@ auto Geant4Detector::convertGeant4Volumes(const Geant4Detector::Config& cfg, ACTS_INFO("Found " << g4SurfaceCache.convertedMaterials << " converted Geant4 Material slabs."); - Surfaces surfaces = {}; - DetectorElements elements = {}; + std::vector> surfaces; + std::vector> elements; // Reserve the right amount of surfaces surfaces.reserve(g4SurfaceCache.sensitiveSurfaces.size() + @@ -133,14 +114,14 @@ auto Geant4Detector::convertGeant4Volumes(const Geant4Detector::Config& cfg, // Add the sensitive surfaces for (const auto& [e, s] : g4SurfaceCache.sensitiveSurfaces) { - elements.push_back(e); surfaces.push_back(s); + elements.push_back(e); } // Add the passive surfaces surfaces.insert(surfaces.end(), g4SurfaceCache.passiveSurfaces.begin(), g4SurfaceCache.passiveSurfaces.end()); - return std::tie(surfaces, elements); + return {std::move(surfaces), std::move(elements)}; } } // namespace ActsExamples diff --git a/Examples/Detectors/GenericDetector/CMakeLists.txt b/Examples/Detectors/GenericDetector/CMakeLists.txt index 242e710df42..7260a22b128 100644 --- a/Examples/Detectors/GenericDetector/CMakeLists.txt +++ b/Examples/Detectors/GenericDetector/CMakeLists.txt @@ -5,12 +5,16 @@ add_library( src/GenericDetector.cpp src/GenericDetectorElement.cpp ) + target_include_directories( ActsExamplesDetectorGeneric PUBLIC $ ) -target_link_libraries(ActsExamplesDetectorGeneric PUBLIC ActsCore) -target_link_libraries(ActsExamplesDetectorGeneric PUBLIC ActsExamplesFramework) + +target_link_libraries( + ActsExamplesDetectorGeneric + PUBLIC ActsCore ActsExamplesFramework ActsExamplesDetectorsCommon +) install( TARGETS ActsExamplesDetectorGeneric diff --git a/Examples/Detectors/GenericDetector/include/ActsExamples/GenericDetector/GenericDetector.hpp b/Examples/Detectors/GenericDetector/include/ActsExamples/GenericDetector/GenericDetector.hpp index 21a1f85bec6..5b8517baad1 100644 --- a/Examples/Detectors/GenericDetector/include/ActsExamples/GenericDetector/GenericDetector.hpp +++ b/Examples/Detectors/GenericDetector/include/ActsExamples/GenericDetector/GenericDetector.hpp @@ -9,44 +9,35 @@ #pragma once #include "Acts/Utilities/Logger.hpp" +#include "ActsExamples/DetectorCommons/Detector.hpp" #include #include -#include -#include namespace Acts { -class TrackingGeometry; class IMaterialDecorator; -} // namespace Acts - -namespace ActsExamples { -class IContextDecorator; -} // namespace ActsExamples +} namespace ActsExamples { class GenericDetectorElement; -struct GenericDetector { - using ContextDecorators = std::vector>; - using TrackingGeometryPtr = std::shared_ptr; - +class GenericDetector : public Detector { + public: struct Config { - std::size_t buildLevel{3}; - Acts::Logging::Level surfaceLogLevel{Acts::Logging::INFO}; - Acts::Logging::Level layerLogLevel{Acts::Logging::INFO}; - Acts::Logging::Level volumeLogLevel{Acts::Logging::INFO}; - bool buildProto{false}; + std::size_t buildLevel = 3; + Acts::Logging::Level logLevel = Acts::Logging::INFO; + Acts::Logging::Level surfaceLogLevel = Acts::Logging::INFO; + Acts::Logging::Level layerLogLevel = Acts::Logging::INFO; + Acts::Logging::Level volumeLogLevel = Acts::Logging::INFO; + bool buildProto = false; + std::shared_ptr materialDecorator; }; - /// The Store of the detector elements (lifetime: job) - std::vector>> - detectorStore; + explicit GenericDetector(const Config& cfg); - std::pair finalize( - const Config& cfg, - std::shared_ptr mdecorator); + private: + Config m_cfg; }; } // namespace ActsExamples diff --git a/Examples/Detectors/GenericDetector/src/GenericDetector.cpp b/Examples/Detectors/GenericDetector/src/GenericDetector.cpp index b80b769708d..f996d225e79 100644 --- a/Examples/Detectors/GenericDetector/src/GenericDetector.cpp +++ b/Examples/Detectors/GenericDetector/src/GenericDetector.cpp @@ -8,26 +8,28 @@ #include "ActsExamples/GenericDetector/GenericDetector.hpp" -#include "Acts/Geometry/TrackingGeometry.hpp" #include "ActsExamples/GenericDetector/BuildGenericDetector.hpp" #include "ActsExamples/GenericDetector/GenericDetectorElement.hpp" namespace ActsExamples { -auto GenericDetector::finalize( - const Config& cfg, - std::shared_ptr mdecorator) - -> std::pair { - GenericDetectorElement::ContextType nominalContext; - /// Return the generic detector - TrackingGeometryPtr gGeometry = - Generic::buildDetector( - nominalContext, detectorStore, cfg.buildLevel, std::move(mdecorator), - cfg.buildProto, cfg.surfaceLogLevel, cfg.layerLogLevel, - cfg.volumeLogLevel); - ContextDecorators gContextDecorators = {}; - // return the pair of geometry and empty decorators - return {std::move(gGeometry), std::move(gContextDecorators)}; +GenericDetector::GenericDetector(const Config& cfg) + : Detector(Acts::getDefaultLogger("GenericDetector", cfg.logLevel)), + m_cfg(cfg) { + m_nominalGeometryContext = Acts::GeometryContext(); + + std::vector>> + specificDetectorStore; + m_trackingGeometry = Generic::buildDetector( + m_nominalGeometryContext, specificDetectorStore, m_cfg.buildLevel, + m_cfg.materialDecorator, m_cfg.buildProto, m_cfg.surfaceLogLevel, + m_cfg.layerLogLevel, m_cfg.volumeLogLevel); + + for (const auto& something : specificDetectorStore) { + for (const auto& element : something) { + m_detectorStore.push_back(element); + } + } } } // namespace ActsExamples diff --git a/Examples/Detectors/GeoModelDetector/CMakeLists.txt b/Examples/Detectors/GeoModelDetector/CMakeLists.txt new file mode 100644 index 00000000000..af7c6d7e494 --- /dev/null +++ b/Examples/Detectors/GeoModelDetector/CMakeLists.txt @@ -0,0 +1,41 @@ +add_library(ActsExamplesDetectorGeoModel SHARED src/GeoModelDetector.cpp) + +target_include_directories( + ActsExamplesDetectorGeoModel + PUBLIC $ +) + +target_link_libraries( + ActsExamplesDetectorGeoModel + PUBLIC + ActsCore + ActsExamplesFramework + ActsPluginGeoModel + ActsExamplesDetectorsCommon +) + +if(ACTS_BUILD_EXAMPLES_GEANT4) + find_library(GeoModel2G4_LIBRARY GeoModel2G4 REQUIRED) + + target_link_libraries( + ActsExamplesDetectorGeoModel + PUBLIC ActsExamplesGeant4 ${GeoModel2G4_LIBRARY} + ) + + target_sources( + ActsExamplesDetectorGeoModel + PUBLIC + src/GeoModelGeant4DetectorConstruction.cpp + src/GeoModelDetectorGeant4.cpp + ) +else() + target_sources( + ActsExamplesDetectorDD4hep + PUBLIC src/GeoModelDetectorGeant4Stub.cpp + ) +endif() + +install( + TARGETS ActsExamplesDetectorGeoModel + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} +) diff --git a/Examples/Detectors/GeoModelDetector/include/ActsExamples/GeoModelDetector/GeoModelDetector.hpp b/Examples/Detectors/GeoModelDetector/include/ActsExamples/GeoModelDetector/GeoModelDetector.hpp new file mode 100644 index 00000000000..6d687dcc625 --- /dev/null +++ b/Examples/Detectors/GeoModelDetector/include/ActsExamples/GeoModelDetector/GeoModelDetector.hpp @@ -0,0 +1,37 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#pragma once + +#include "Acts/Plugins/GeoModel/GeoModelTree.hpp" +#include "Acts/Utilities/Logger.hpp" +#include "ActsExamples/DetectorCommons/Detector.hpp" + +#include + +namespace ActsExamples { + +struct GeoModelDetector : public Detector { + struct Config { + std::string path; + + /// Logging level of the child tools + Acts::Logging::Level logLevel = Acts::Logging::INFO; + }; + + explicit GeoModelDetector(const Config& cfg); + + std::unique_ptr buildGeant4DetectorConstruction( + const Geant4ConstructionOptions& options) const override; + + private: + Config m_cfg; + Acts::GeoModelTree m_geoModel; +}; + +} // namespace ActsExamples diff --git a/Examples/Algorithms/Geant4/include/ActsExamples/GeoModelG4/GeoModelDetectorConstruction.hpp b/Examples/Detectors/GeoModelDetector/include/ActsExamples/GeoModelDetector/GeoModelGeant4DetectorConstruction.hpp similarity index 52% rename from Examples/Algorithms/Geant4/include/ActsExamples/GeoModelG4/GeoModelDetectorConstruction.hpp rename to Examples/Detectors/GeoModelDetector/include/ActsExamples/GeoModelDetector/GeoModelGeant4DetectorConstruction.hpp index d3070bbc590..fd8390d566c 100644 --- a/Examples/Algorithms/Geant4/include/ActsExamples/GeoModelG4/GeoModelDetectorConstruction.hpp +++ b/Examples/Detectors/GeoModelDetector/include/ActsExamples/GeoModelDetector/GeoModelGeant4DetectorConstruction.hpp @@ -9,8 +9,7 @@ #pragma once #include "Acts/Plugins/GeoModel/GeoModelTree.hpp" -#include "ActsExamples/Geant4/DetectorConstructionFactory.hpp" -#include "ActsExamples/Geant4/RegionCreator.hpp" +#include "ActsExamples/Geant4/Geant4ConstructionOptions.hpp" #include @@ -19,13 +18,13 @@ class G4VPhysicalVolume; namespace ActsExamples { /// Construct the Geant4 detector from a GeoModel world volume -class GeoModelDetectorConstruction final : public G4VUserDetectorConstruction { +class GeoModelGeant4DetectorConstruction final + : public G4VUserDetectorConstruction { public: /// @param geoModelTree is the GeoModel tree containing the world volume /// @param regionCreators are the region creators - GeoModelDetectorConstruction( - const Acts::GeoModelTree& geoModelTree, - std::vector> regionCreators = {}); + GeoModelGeant4DetectorConstruction(const Acts::GeoModelTree& geoModelTree, + const Geant4ConstructionOptions& options); /// Read the file and parse it to construct the Geant4 description /// @@ -36,26 +35,10 @@ class GeoModelDetectorConstruction final : public G4VUserDetectorConstruction { private: /// The GeoModel tree Acts::GeoModelTree m_geoModelTree; - /// Region creators - std::vector> m_regionCreators; + /// Construction options + Geant4ConstructionOptions m_options; /// The world volume G4VPhysicalVolume* m_g4World = nullptr; }; -class GeoModelDetectorConstructionFactory final - : public Geant4::DetectorConstructionFactory { - public: - GeoModelDetectorConstructionFactory( - const Acts::GeoModelTree& geoModelTree, - std::vector> regionCreators = {}); - - std::unique_ptr factorize() const override; - - private: - /// The GeoModel tree - Acts::GeoModelTree m_geoModelTree; - /// Region creators - std::vector> m_regionCreators; -}; - } // namespace ActsExamples diff --git a/Examples/Detectors/GeoModelDetector/src/GeoModelDetector.cpp b/Examples/Detectors/GeoModelDetector/src/GeoModelDetector.cpp new file mode 100644 index 00000000000..12e151385ed --- /dev/null +++ b/Examples/Detectors/GeoModelDetector/src/GeoModelDetector.cpp @@ -0,0 +1,24 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include "ActsExamples/GeoModelDetector/GeoModelDetector.hpp" + +#include "Acts/Plugins/GeoModel/GeoModelReader.hpp" +#include "Acts/Plugins/GeoModel/GeoModelTree.hpp" + +#include + +namespace ActsExamples { + +GeoModelDetector::GeoModelDetector(const Config& cfg) + : Detector(Acts::getDefaultLogger("GeoModelDetector", cfg.logLevel)), + m_cfg(cfg) { + m_geoModel = Acts::GeoModelReader::readFromDb(m_cfg.path); +} + +} // namespace ActsExamples diff --git a/Examples/Detectors/GeoModelDetector/src/GeoModelDetectorGeant4.cpp b/Examples/Detectors/GeoModelDetector/src/GeoModelDetectorGeant4.cpp new file mode 100644 index 00000000000..1035ea9bcca --- /dev/null +++ b/Examples/Detectors/GeoModelDetector/src/GeoModelDetectorGeant4.cpp @@ -0,0 +1,21 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include "ActsExamples/GeoModelDetector/GeoModelDetector.hpp" +#include "ActsExamples/GeoModelDetector/GeoModelGeant4DetectorConstruction.hpp" + +namespace ActsExamples { + +std::unique_ptr +GeoModelDetector::buildGeant4DetectorConstruction( + const Geant4ConstructionOptions& options) const { + return std::make_unique(m_geoModel, + options); +} + +} // namespace ActsExamples diff --git a/Examples/Detectors/GeoModelDetector/src/GeoModelDetectorGeant4Stub.cpp b/Examples/Detectors/GeoModelDetector/src/GeoModelDetectorGeant4Stub.cpp new file mode 100644 index 00000000000..2d19ee1770a --- /dev/null +++ b/Examples/Detectors/GeoModelDetector/src/GeoModelDetectorGeant4Stub.cpp @@ -0,0 +1,19 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include "ActsExamples/GeoModelDetector/GeoModelDetector.hpp" + +namespace ActsExamples { + +std::unique_ptr +GeoModelDetector::buildGeant4DetectorConstruction( + const Geant4ConstructionOptions& /*options*/) const { + throw std::runtime_error("Geant4 is not enabled"); +} + +} // namespace ActsExamples diff --git a/Examples/Algorithms/Geant4/src/GeoModelDetectorConstruction.cpp b/Examples/Detectors/GeoModelDetector/src/GeoModelGeant4DetectorConstruction.cpp similarity index 53% rename from Examples/Algorithms/Geant4/src/GeoModelDetectorConstruction.cpp rename to Examples/Detectors/GeoModelDetector/src/GeoModelGeant4DetectorConstruction.cpp index 8d33622714b..d58151ba921 100644 --- a/Examples/Algorithms/Geant4/src/GeoModelDetectorConstruction.cpp +++ b/Examples/Detectors/GeoModelDetector/src/GeoModelGeant4DetectorConstruction.cpp @@ -6,9 +6,10 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. -#include "ActsExamples/GeoModelG4/GeoModelDetectorConstruction.hpp" +#include "ActsExamples/GeoModelDetector/GeoModelGeant4DetectorConstruction.hpp" -#include +#include "ActsExamples/Geant4/Geant4ConstructionOptions.hpp" +#include "ActsExamples/Geant4/RegionCreator.hpp" #include #include @@ -17,22 +18,22 @@ #include #include -using namespace ActsExamples; +namespace ActsExamples { -GeoModelDetectorConstruction::GeoModelDetectorConstruction( +GeoModelGeant4DetectorConstruction::GeoModelGeant4DetectorConstruction( const Acts::GeoModelTree& geoModelTree, - std::vector> regionCreators) + const Geant4ConstructionOptions& options) : G4VUserDetectorConstruction(), m_geoModelTree(geoModelTree), - m_regionCreators(std::move(regionCreators)) { + m_options(options) { if (geoModelTree.worldVolume == nullptr) { throw std::invalid_argument( - "GeoModelDetectorConstruction: " + "GeoModelGeant4DetectorConstruction: " "GeoModel world volume is nullptr"); } } -G4VPhysicalVolume* GeoModelDetectorConstruction::Construct() { +G4VPhysicalVolume* GeoModelGeant4DetectorConstruction::Construct() { if (m_g4World == nullptr) { ExtParameterisedVolumeBuilder builder(m_geoModelTree.worldVolumeName); G4LogicalVolume* g4WorldLog = builder.Build(m_geoModelTree.worldVolume); @@ -41,21 +42,11 @@ G4VPhysicalVolume* GeoModelDetectorConstruction::Construct() { m_geoModelTree.worldVolumeName, nullptr, false, 0); // Create regions - for (const auto& regionCreator : m_regionCreators) { - regionCreator->construct(); + for (const auto& regionCreator : m_options.regionCreators) { + regionCreator->buildRegion(); } } return m_g4World; } -GeoModelDetectorConstructionFactory::GeoModelDetectorConstructionFactory( - const Acts::GeoModelTree& geoModelTree, - std::vector> regionCreators) - : m_geoModelTree(geoModelTree), - m_regionCreators(std::move(regionCreators)) {} - -std::unique_ptr -GeoModelDetectorConstructionFactory::factorize() const { - return std::make_unique(m_geoModelTree, - m_regionCreators); -} +} // namespace ActsExamples diff --git a/Examples/Detectors/MuonSpectrometerMockupDetector/src/MockupSectorBuilder.cpp b/Examples/Detectors/MuonSpectrometerMockupDetector/src/MockupSectorBuilder.cpp index 585aef06756..71cd8c83907 100644 --- a/Examples/Detectors/MuonSpectrometerMockupDetector/src/MockupSectorBuilder.cpp +++ b/Examples/Detectors/MuonSpectrometerMockupDetector/src/MockupSectorBuilder.cpp @@ -28,7 +28,7 @@ #include "Acts/Visualization/GeometryView3D.hpp" #include "Acts/Visualization/ObjVisualization3D.hpp" #include "Acts/Visualization/ViewConfig.hpp" -#include "ActsExamples/Geant4/GdmlDetectorConstruction.hpp" +#include "ActsExamples/Geant4Detector/GdmlDetectorConstruction.hpp" #include "ActsExamples/Geant4Detector/Geant4Detector.hpp" #include @@ -47,7 +47,7 @@ namespace ActsExamples { MockupSectorBuilder::MockupSectorBuilder( const MockupSectorBuilder::Config& config) { mCfg = config; - GdmlDetectorConstruction geo_gdml(mCfg.gdmlPath); + GdmlDetectorConstruction geo_gdml(mCfg.gdmlPath, {}); g4World = geo_gdml.Construct(); } @@ -78,13 +78,14 @@ MockupSectorBuilder::buildChamber( g4SurfaceOptions.passiveSurfaceSelector = g4Passive; g4WorldConfig.g4SurfaceOptions = g4SurfaceOptions; - auto g4detector = Geant4Detector(); - - auto [detector, surfaces, detectorElements] = - g4detector.constructDetector(g4WorldConfig, Acts::getDummyLogger()); + auto g4Detector = Geant4Detector(g4WorldConfig); + // Trigger the build of the detector + auto [surface, elements] = Geant4Detector::buildGeant4Volumes( + g4WorldConfig, + *Acts::getDefaultLogger("MockupSectorBuilder", Acts::Logging::INFO)); // The vector that holds the converted sensitive surfaces of the chamber - std::vector> strawSurfaces = {}; + std::vector> strawSurfaces; std::array, 3> min_max; std::fill(min_max.begin(), min_max.end(), @@ -92,7 +93,7 @@ MockupSectorBuilder::buildChamber( -std::numeric_limits::max())); // Convert the physical volumes of the detector elements to straw surfaces - for (auto& detectorElement : detectorElements) { + for (const auto& detectorElement : elements) { auto context = Acts::GeometryContext(); auto g4conv = Acts::Geant4PhysicalVolumeConverter(); diff --git a/Examples/Detectors/TGeoDetector/CMakeLists.txt b/Examples/Detectors/TGeoDetector/CMakeLists.txt index 3df36c62f15..11fac0c179c 100644 --- a/Examples/Detectors/TGeoDetector/CMakeLists.txt +++ b/Examples/Detectors/TGeoDetector/CMakeLists.txt @@ -9,6 +9,7 @@ target_include_directories( ActsExamplesDetectorTGeo PUBLIC $ ) + target_link_libraries( ActsExamplesDetectorTGeo PUBLIC @@ -17,6 +18,7 @@ target_link_libraries( ActsPluginJson ActsExamplesFramework ActsExamplesDetectorGeneric + ActsExamplesDetectorsCommon ActsExamplesITkModuleSplitting ) diff --git a/Examples/Detectors/TGeoDetector/include/ActsExamples/TGeoDetector/JsonTGeoDetectorConfig.hpp b/Examples/Detectors/TGeoDetector/include/ActsExamples/TGeoDetector/JsonTGeoDetectorConfig.hpp index c1b006f6593..893367aa890 100644 --- a/Examples/Detectors/TGeoDetector/include/ActsExamples/TGeoDetector/JsonTGeoDetectorConfig.hpp +++ b/Examples/Detectors/TGeoDetector/include/ActsExamples/TGeoDetector/JsonTGeoDetectorConfig.hpp @@ -18,6 +18,8 @@ #include #include +#include + // Namespace of the module splitters namespace Acts { @@ -53,9 +55,7 @@ NLOHMANN_JSON_SERIALIZE_ENUM(Acts::BinningType, } // namespace Acts -namespace ActsExamples { - -namespace Options { +namespace ActsExamples::Options { /// Read config for options interval void from_json(const nlohmann::json& j, Interval& interval) { @@ -70,7 +70,9 @@ void to_json(nlohmann::json& j, const Interval& interval) { {"upper", interval.upper.value_or(0)}}; } -} // namespace Options +} // namespace ActsExamples::Options + +namespace ActsExamples { void from_json(const nlohmann::json& j, TGeoITkModuleSplitter::Config& msc) { msc.barrelMap = diff --git a/Examples/Detectors/TGeoDetector/include/ActsExamples/TGeoDetector/TGeoDetector.hpp b/Examples/Detectors/TGeoDetector/include/ActsExamples/TGeoDetector/TGeoDetector.hpp index 41134fdfa54..3cad24ecdd8 100644 --- a/Examples/Detectors/TGeoDetector/include/ActsExamples/TGeoDetector/TGeoDetector.hpp +++ b/Examples/Detectors/TGeoDetector/include/ActsExamples/TGeoDetector/TGeoDetector.hpp @@ -9,9 +9,11 @@ #pragma once #include "Acts/Geometry/GeometryIdentifier.hpp" +#include "Acts/Material/IMaterialDecorator.hpp" #include "Acts/Plugins/TGeo/TGeoLayerBuilder.hpp" #include "Acts/Utilities/BinningType.hpp" #include "Acts/Utilities/Logger.hpp" +#include "ActsExamples/DetectorCommons/Detector.hpp" #include "ActsExamples/Utilities/Options.hpp" #include @@ -22,27 +24,12 @@ #include #include -namespace Acts { -class TGeoDetectorElement; -class TrackingGeometry; -class IMaterialDecorator; -} // namespace Acts - namespace ActsExamples { -class IContextDecorator; - -struct TGeoDetector { - using DetectorElementPtr = std::shared_ptr; - using DetectorStore = std::vector; - - using ContextDecorators = std::vector>; - using TrackingGeometryPtr = std::shared_ptr; - - /// The Store of the detector elements (lifetime: job) - DetectorStore detectorStore; - +class TGeoDetector : public Detector { + public: struct Config { + Acts::Logging::Level logLevel = Acts::Logging::WARNING; Acts::Logging::Level surfaceLogLevel = Acts::Logging::WARNING; Acts::Logging::Level layerLogLevel = Acts::Logging::WARNING; Acts::Logging::Level volumeLogLevel = Acts::Logging::WARNING; @@ -66,6 +53,8 @@ struct TGeoDetector { std::shared_ptr geometryIdentifierHook = std::make_shared(); + std::shared_ptr materialDecorator; + enum SubVolume : std::size_t { Negative = 0, Central, Positive }; template @@ -147,9 +136,10 @@ struct TGeoDetector { static void readTGeoLayerBuilderConfigsFile(const std::string& path, Config& config); - std::pair finalize( - const Config& cfg, - std::shared_ptr mdecorator); + explicit TGeoDetector(const Config& cfg); + + private: + Config m_cfg; }; } // namespace ActsExamples diff --git a/Examples/Detectors/TGeoDetector/src/TGeoDetector.cpp b/Examples/Detectors/TGeoDetector/src/TGeoDetector.cpp index f594b681d49..884cfc8345d 100644 --- a/Examples/Detectors/TGeoDetector/src/TGeoDetector.cpp +++ b/Examples/Detectors/TGeoDetector/src/TGeoDetector.cpp @@ -10,6 +10,7 @@ #include "Acts/Geometry/CylinderVolumeBuilder.hpp" #include "Acts/Geometry/CylinderVolumeHelper.hpp" +#include "Acts/Geometry/DetectorElementBase.hpp" #include "Acts/Geometry/GeometryContext.hpp" #include "Acts/Geometry/ITrackingVolumeBuilder.hpp" #include "Acts/Geometry/LayerArrayCreator.hpp" @@ -26,7 +27,6 @@ #include "Acts/Utilities/Logger.hpp" #include "ActsExamples/TGeoDetector/JsonTGeoDetectorConfig.hpp" #include "ActsExamples/TGeoDetector/TGeoITkModuleSplitter.hpp" -#include "ActsExamples/Utilities/Options.hpp" #include #include @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -41,7 +42,6 @@ #include "TGeoManager.h" namespace ActsExamples { -using namespace Options; namespace { @@ -159,7 +159,7 @@ std::vector makeLayerBuilderConfigs( /// @param vm is the variable map from the options std::shared_ptr buildTGeoDetector( const TGeoDetector::Config& config, const Acts::GeometryContext& context, - std::vector>& + std::vector>& detElementStore, std::shared_ptr mdecorator, const Acts::Logger& logger) { @@ -364,18 +364,14 @@ void TGeoDetector::readTGeoLayerBuilderConfigsFile(const std::string& path, } } -auto TGeoDetector::finalize( - const Config& cfg, - std::shared_ptr mdecorator) - -> std::pair { - Acts::GeometryContext tGeoContext; - auto logger = Acts::getDefaultLogger("TGeoDetector", Acts::Logging::INFO); - TrackingGeometryPtr tgeoTrackingGeometry = buildTGeoDetector( - cfg, tGeoContext, detectorStore, std::move(mdecorator), *logger); - - ContextDecorators tgeoContextDecorators = {}; - // Return the pair of geometry and empty decorators - return {std::move(tgeoTrackingGeometry), std::move(tgeoContextDecorators)}; +TGeoDetector::TGeoDetector(const Config& cfg) + : Detector(Acts::getDefaultLogger("TGeoDetector", cfg.logLevel)), + m_cfg(cfg) { + m_nominalGeometryContext = Acts::GeometryContext(); + + m_trackingGeometry = + buildTGeoDetector(m_cfg, m_nominalGeometryContext, m_detectorStore, + m_cfg.materialDecorator, logger()); } void TGeoDetector::Config::readJson(const std::string& jsonFile) { diff --git a/Examples/Detectors/TelescopeDetector/CMakeLists.txt b/Examples/Detectors/TelescopeDetector/CMakeLists.txt index 9b41a082c42..793465cd6ca 100644 --- a/Examples/Detectors/TelescopeDetector/CMakeLists.txt +++ b/Examples/Detectors/TelescopeDetector/CMakeLists.txt @@ -5,15 +5,36 @@ add_library( src/TelescopeDetectorElement.cpp src/BuildTelescopeDetector.cpp ) + target_include_directories( ActsExamplesDetectorTelescope PUBLIC $ ) + target_link_libraries( ActsExamplesDetectorTelescope - PUBLIC ActsCore ActsExamplesFramework + PUBLIC ActsCore ActsExamplesFramework ActsExamplesDetectorsCommon ) +if(ACTS_BUILD_EXAMPLES_GEANT4) + target_link_libraries( + ActsExamplesDetectorTelescope + PUBLIC ActsExamplesGeant4 + ) + + target_sources( + ActsExamplesDetectorTelescope + PUBLIC + src/TelescopeDetectorGeant4.cpp + src/TelescopeG4DetectorConstruction.cpp + ) +else() + target_sources( + ActsExamplesDetectorTelescope + PUBLIC src/TelescopeDetectorGeant4Stub.cpp + ) +endif() + install( TARGETS ActsExamplesDetectorTelescope LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} diff --git a/Examples/Detectors/TelescopeDetector/include/ActsExamples/TelescopeDetector/TelescopeDetector.hpp b/Examples/Detectors/TelescopeDetector/include/ActsExamples/TelescopeDetector/TelescopeDetector.hpp index 76b81984fb0..17145d4d301 100644 --- a/Examples/Detectors/TelescopeDetector/include/ActsExamples/TelescopeDetector/TelescopeDetector.hpp +++ b/Examples/Detectors/TelescopeDetector/include/ActsExamples/TelescopeDetector/TelescopeDetector.hpp @@ -9,26 +9,21 @@ #pragma once #include "Acts/Definitions/Units.hpp" -#include "Acts/Geometry/DetectorElementBase.hpp" +#include "Acts/Utilities/Logger.hpp" +#include "ActsExamples/DetectorCommons/Detector.hpp" #include #include -#include #include namespace Acts { -class TrackingGeometry; class IMaterialDecorator; } // namespace Acts namespace ActsExamples { -class IContextDecorator; - -struct TelescopeDetector { - using ContextDecorators = std::vector>; - using TrackingGeometryPtr = std::shared_ptr; - +class TelescopeDetector : public Detector { + public: struct Config { std::vector positions{{0, 30, 60, 120, 150, 180}}; std::vector stereos{{0, 0, 0, 0, 0, 0}}; @@ -37,15 +32,17 @@ struct TelescopeDetector { double thickness{80 * Acts::UnitConstants::um}; int surfaceType{0}; int binValue{2}; + std::shared_ptr materialDecorator; + Acts::Logging::Level logLevel{Acts::Logging::WARNING}; }; - Config config; - /// The store of the detector elements (lifetime: job) - std::vector> detectorStore; + explicit TelescopeDetector(const Config& cfg); + + std::unique_ptr buildGeant4DetectorConstruction( + const Geant4ConstructionOptions& options) const override; - std::pair finalize( - const Config& cfg, - const std::shared_ptr& mdecorator); + private: + Config m_cfg; }; } // namespace ActsExamples diff --git a/Examples/Detectors/TelescopeDetector/include/ActsExamples/TelescopeDetector/TelescopeG4DetectorConstruction.hpp b/Examples/Detectors/TelescopeDetector/include/ActsExamples/TelescopeDetector/TelescopeG4DetectorConstruction.hpp new file mode 100644 index 00000000000..62ee1cc0c28 --- /dev/null +++ b/Examples/Detectors/TelescopeDetector/include/ActsExamples/TelescopeDetector/TelescopeG4DetectorConstruction.hpp @@ -0,0 +1,38 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#pragma once + +#include "ActsExamples/Geant4/Geant4ConstructionOptions.hpp" +#include "ActsExamples/TelescopeDetector/TelescopeDetector.hpp" + +#include "G4VUserDetectorConstruction.hh" + +class G4VPhysicalVolume; +class G4LogicalVolume; + +namespace ActsExamples { + +class TelescopeG4DetectorConstruction final + : public G4VUserDetectorConstruction { + public: + TelescopeG4DetectorConstruction(const TelescopeDetector::Config& cfg, + const Geant4ConstructionOptions& options); + + G4VPhysicalVolume* Construct() final; + + private: + /// The configuration of the telescope detector + TelescopeDetector::Config m_cfg; + /// The Geant4 construction options + Geant4ConstructionOptions m_options; + /// The world volume + G4VPhysicalVolume* m_world{}; +}; + +} // namespace ActsExamples diff --git a/Examples/Detectors/TelescopeDetector/src/TelescopeDetector.cpp b/Examples/Detectors/TelescopeDetector/src/TelescopeDetector.cpp index ccba63a1c34..414658204b8 100644 --- a/Examples/Detectors/TelescopeDetector/src/TelescopeDetector.cpp +++ b/Examples/Detectors/TelescopeDetector/src/TelescopeDetector.cpp @@ -9,59 +9,42 @@ #include "ActsExamples/TelescopeDetector/TelescopeDetector.hpp" #include "Acts/Geometry/GeometryContext.hpp" -#include "Acts/Geometry/TrackingGeometry.hpp" -#include "Acts/Utilities/BinningType.hpp" #include "ActsExamples/TelescopeDetector/BuildTelescopeDetector.hpp" -#include "ActsExamples/TelescopeDetector/TelescopeDetectorElement.hpp" -#include #include namespace ActsExamples { -auto TelescopeDetector::finalize( - const Config& cfg, const std::shared_ptr& - /*mdecorator*/) -> std::pair { - TelescopeDetectorElement::ContextType nominalContext; - - if (cfg.surfaceType > 1) { +TelescopeDetector::TelescopeDetector(const Config& cfg) + : Detector(Acts::getDefaultLogger("TelescopeDetector", cfg.logLevel)), + m_cfg(cfg) { + if (m_cfg.surfaceType > 1) { throw std::invalid_argument( "The surface type could either be 0 for plane surface or 1 for disc " "surface."); } - if (cfg.binValue > 2) { + if (m_cfg.binValue > 2) { throw std::invalid_argument("The axis value could only be 0, 1, or 2."); } // Check if the bounds values are valid - if (cfg.surfaceType == 1 && cfg.bounds[0] >= cfg.bounds[1]) { + if (m_cfg.surfaceType == 1 && m_cfg.bounds[0] >= m_cfg.bounds[1]) { throw std::invalid_argument( "The minR should be smaller than the maxR for disc surface bounds."); } - if (cfg.positions.size() != cfg.stereos.size()) { + if (m_cfg.positions.size() != m_cfg.stereos.size()) { throw std::invalid_argument( "The number of provided positions must match the number of " "provided stereo angles."); } - config = cfg; - - // Sort the provided distances - std::vector positions = cfg.positions; - std::vector stereos = cfg.stereos; - std::ranges::sort(positions); - - Acts::GeometryContext geometryContext(nominalContext); + m_nominalGeometryContext = Acts::GeometryContext(); - // Return the telescope detector - TrackingGeometryPtr gGeometry = - buildTelescopeDetector(geometryContext, detectorStore, positions, stereos, - cfg.offsets, cfg.bounds, cfg.thickness, - static_cast(cfg.surfaceType), - static_cast(cfg.binValue)); - ContextDecorators gContextDecorators = {}; - // return the pair of geometry and empty decorators - return {std::move(gGeometry), std::move(gContextDecorators)}; + m_trackingGeometry = buildTelescopeDetector( + m_nominalGeometryContext, m_detectorStore, m_cfg.positions, m_cfg.stereos, + m_cfg.offsets, m_cfg.bounds, m_cfg.thickness, + static_cast(m_cfg.surfaceType), + static_cast(m_cfg.binValue)); } } // namespace ActsExamples diff --git a/Examples/Detectors/TelescopeDetector/src/TelescopeDetectorGeant4.cpp b/Examples/Detectors/TelescopeDetector/src/TelescopeDetectorGeant4.cpp new file mode 100644 index 00000000000..f385a0a98ef --- /dev/null +++ b/Examples/Detectors/TelescopeDetector/src/TelescopeDetectorGeant4.cpp @@ -0,0 +1,20 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include "ActsExamples/TelescopeDetector/TelescopeDetector.hpp" +#include "ActsExamples/TelescopeDetector/TelescopeG4DetectorConstruction.hpp" + +namespace ActsExamples { + +std::unique_ptr +TelescopeDetector::buildGeant4DetectorConstruction( + const Geant4ConstructionOptions& options) const { + return std::make_unique(m_cfg, options); +} + +} // namespace ActsExamples diff --git a/Examples/Detectors/TelescopeDetector/src/TelescopeDetectorGeant4Stub.cpp b/Examples/Detectors/TelescopeDetector/src/TelescopeDetectorGeant4Stub.cpp new file mode 100644 index 00000000000..93bc305c292 --- /dev/null +++ b/Examples/Detectors/TelescopeDetector/src/TelescopeDetectorGeant4Stub.cpp @@ -0,0 +1,19 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include "ActsExamples/TelescopeDetector/TelescopeDetector.hpp" + +namespace ActsExamples { + +std::unique_ptr +TelescopeDetector::buildGeant4DetectorConstruction( + const Geant4ConstructionOptions& /*options*/) const { + throw std::runtime_error("Geant4 is not enabled"); +} + +} // namespace ActsExamples diff --git a/Examples/Algorithms/Geant4/src/TelescopeG4DetectorConstruction.cpp b/Examples/Detectors/TelescopeDetector/src/TelescopeG4DetectorConstruction.cpp similarity index 87% rename from Examples/Algorithms/Geant4/src/TelescopeG4DetectorConstruction.cpp rename to Examples/Detectors/TelescopeDetector/src/TelescopeG4DetectorConstruction.cpp index e8412a18c93..2566c069f61 100644 --- a/Examples/Algorithms/Geant4/src/TelescopeG4DetectorConstruction.cpp +++ b/Examples/Detectors/TelescopeDetector/src/TelescopeG4DetectorConstruction.cpp @@ -8,16 +8,10 @@ #include "ActsExamples/TelescopeDetector/TelescopeG4DetectorConstruction.hpp" -#include "Acts/Utilities/BinningType.hpp" #include "Acts/Utilities/ThrowAssert.hpp" +#include "ActsExamples/Geant4/RegionCreator.hpp" #include "ActsExamples/TelescopeDetector/BuildTelescopeDetector.hpp" - -#include -#include -#include -#include -#include -#include +#include "ActsExamples/TelescopeDetector/TelescopeDetector.hpp" #include "G4Box.hh" #include "G4LogicalVolume.hh" @@ -30,8 +24,8 @@ namespace ActsExamples { TelescopeG4DetectorConstruction::TelescopeG4DetectorConstruction( const TelescopeDetector::Config& cfg, - std::vector> regionCreators) - : m_cfg(cfg), m_regionCreators(std::move(regionCreators)) { + const Geant4ConstructionOptions& options) + : m_cfg(cfg), m_options(options) { throw_assert(cfg.surfaceType == static_cast(TelescopeSurfaceType::Plane), "only plan is supported right now"); } @@ -160,22 +154,11 @@ G4VPhysicalVolume* TelescopeG4DetectorConstruction::Construct() { } // Create regions - for (const auto& regionCreator : m_regionCreators) { - regionCreator->construct(); + for (const auto& regionCreator : m_options.regionCreators) { + regionCreator->buildRegion(); } return m_world; } -TelescopeG4DetectorConstructionFactory::TelescopeG4DetectorConstructionFactory( - const TelescopeDetector::Config& cfg, - std::vector> regionCreators) - : m_cfg(cfg), m_regionCreators(std::move(regionCreators)) {} - -std::unique_ptr -TelescopeG4DetectorConstructionFactory::factorize() const { - return std::make_unique(m_cfg, - m_regionCreators); -} - } // namespace ActsExamples diff --git a/Examples/Io/EDM4hep/include/ActsExamples/Io/EDM4hep/EDM4hepReader.hpp b/Examples/Io/EDM4hep/include/ActsExamples/Io/EDM4hep/EDM4hepReader.hpp index 07c4e771857..60c6a7fb3cf 100644 --- a/Examples/Io/EDM4hep/include/ActsExamples/Io/EDM4hep/EDM4hepReader.hpp +++ b/Examples/Io/EDM4hep/include/ActsExamples/Io/EDM4hep/EDM4hepReader.hpp @@ -25,7 +25,7 @@ namespace ActsExamples { -struct DD4hepDetector; +class DD4hepDetector; /// Read particles from EDM4hep. /// diff --git a/Examples/Io/EDM4hep/src/EDM4hepReader.cpp b/Examples/Io/EDM4hep/src/EDM4hepReader.cpp index 0b82a20181b..0be54783e8e 100644 --- a/Examples/Io/EDM4hep/src/EDM4hepReader.cpp +++ b/Examples/Io/EDM4hep/src/EDM4hepReader.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -323,8 +324,8 @@ ProcessCode EDM4hepReader::read(const AlgorithmContext& ctx) { [&](std::uint64_t cellId) { ACTS_VERBOSE("CellID: " << cellId); - const auto& vm = m_cfg.dd4hepDetector->geometryService->detector() - .volumeManager(); + const auto& vm = + m_cfg.dd4hepDetector->dd4hepDetector().volumeManager(); const auto detElement = vm.lookupDetElement(cellId); diff --git a/Examples/Python/CMakeLists.txt b/Examples/Python/CMakeLists.txt index dc359db0d0d..b7e7a5b4112 100644 --- a/Examples/Python/CMakeLists.txt +++ b/Examples/Python/CMakeLists.txt @@ -91,7 +91,10 @@ else() endif() if(ACTS_BUILD_PLUGIN_GEOMODEL) - target_link_libraries(ActsPythonBindings PUBLIC ActsPluginGeoModel) + target_link_libraries( + ActsPythonBindings + PUBLIC ActsPluginGeoModel ActsExamplesDetectorGeoModel + ) target_sources(ActsPythonBindings PRIVATE src/GeoModel.cpp) else() target_sources(ActsPythonBindings PRIVATE src/GeoModelStub.cpp) @@ -177,56 +180,6 @@ if(ACTS_BUILD_EXAMPLES_GEANT4) ) list(APPEND py_files examples/geant4/__init__.py) - if(ACTS_BUILD_PLUGIN_DD4HEP AND ACTS_BUILD_EXAMPLES_DD4HEP) - pybind11_add_module(ActsPythonBindingsDDG4 src/Geant4DD4hepComponent.cpp) - target_link_libraries( - ActsPythonBindingsDDG4 - PUBLIC - ActsPythonUtilities - ActsExamplesGeant4 - ActsExamplesDetectorDD4hep - ) - add_dependencies(ActsPythonBindings ActsPythonBindingsDDG4) - - install( - TARGETS ActsPythonBindingsDDG4 DESTINATION ${_python_install_dir} - ) - set_target_properties( - ActsPythonBindingsDDG4 - PROPERTIES INSTALL_RPATH "\$ORIGIN/../../${CMAKE_INSTALL_LIBDIR}" - ) - set_target_properties( - ActsPythonBindingsDDG4 - PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${_python_dir}/acts - ) - list(APPEND py_files examples/geant4/dd4hep.py) - endif() - - if(ACTS_BUILD_PLUGIN_GEOMODEL) - pybind11_add_module(ActsPythonBindingsGeoModelG4 src/Geant4GeoModelComponent.cpp) - target_link_libraries( - ActsPythonBindingsGeoModelG4 - PUBLIC ActsPythonUtilities ActsExamplesGeant4 - ) - add_dependencies(ActsPythonBindings ActsPythonBindingsGeoModelG4) - install( - TARGETS - ActsPythonBindingsGeoModelG4 - DESTINATION - ${_python_install_dir} - ) - set_target_properties( - ActsPythonBindingsGeoModelG4 - PROPERTIES INSTALL_RPATH "\$ORIGIN/../../${CMAKE_INSTALL_LIBDIR}" - ) - set_target_properties( - ActsPythonBindingsGeoModelG4 - PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${_python_dir}/acts - ) - - list(APPEND py_files examples/geant4/geomodel.py) - endif() - if(ACTS_BUILD_EXAMPLES_HEPMC3) target_link_libraries( ActsPythonBindingsGeant4 diff --git a/Examples/Python/python/acts/_adapter.py b/Examples/Python/python/acts/_adapter.py index 493fb53b508..ad1962fd079 100644 --- a/Examples/Python/python/acts/_adapter.py +++ b/Examples/Python/python/acts/_adapter.py @@ -2,9 +2,6 @@ import functools from typing import Optional, Callable, Dict, Any from pathlib import Path -from collections import namedtuple - -import acts def _make_config_adapter(fn): @@ -93,53 +90,6 @@ def _patch_config(m): if name == "Config": _patchKwargsConstructor(cls) - if name.endswith("Detector"): - continue - if hasattr(cls, "Config"): cls.__init__ = _make_config_adapter(cls.__init__) _patchKwargsConstructor(cls.Config) - - -def _detector_create(cls, config_class=None): - def create(*args, mdecorator=None, **kwargs): - if mdecorator is not None: - if not isinstance(mdecorator, inspect.unwrap(acts.IMaterialDecorator)): - raise TypeError("Material decorator is not valid") - if config_class is None: - cfg = cls.Config() - else: - cfg = config_class() - _kwargs = {} - for k, v in kwargs.items(): - try: - setattr(cfg, k, v) - except AttributeError: - _kwargs[k] = v - det = cls() - tg, deco = det.finalize(cfg, mdecorator, *args, **_kwargs) - Detector = namedtuple( - "Detector", ["detector", "trackingGeometry", "decorators"] - ) - - class DetectorContextManager(Detector): - def __new__(cls, detector, trackingGeometry, decorators): - return super(DetectorContextManager, cls).__new__( - cls, detector, trackingGeometry, decorators - ) - - def __enter__(self): - return self - - def __exit__(self, *args): - pass - - return DetectorContextManager(det, tg, deco) - - return create - - -def _patch_detectors(m): - for name, cls in inspect.getmembers(m, inspect.isclass): - if name.endswith("Detector"): - cls.create = _detector_create(cls) diff --git a/Examples/Python/python/acts/examples/__init__.py b/Examples/Python/python/acts/examples/__init__.py index 162e0272d77..5c1a903ad50 100644 --- a/Examples/Python/python/acts/examples/__init__.py +++ b/Examples/Python/python/acts/examples/__init__.py @@ -7,7 +7,7 @@ from acts.ActsPythonBindings._examples import * from acts import ActsPythonBindings import acts -from acts._adapter import _patch_config, _patch_detectors, _patchKwargsConstructor +from acts._adapter import _patch_config, _patchKwargsConstructor _propagators = [] _concrete_propagators = [] @@ -34,8 +34,6 @@ def ConcretePropagator(propagator): _patch_config(ActsPythonBindings._examples) -_patch_detectors(ActsPythonBindings._examples) - # Manually patch ExaTrkX constructors # Need to do it this way, since they are not always present for module in [ diff --git a/Examples/Python/python/acts/examples/dd4hep.py b/Examples/Python/python/acts/examples/dd4hep.py index cd23533dfda..811c97f5657 100644 --- a/Examples/Python/python/acts/examples/dd4hep.py +++ b/Examples/Python/python/acts/examples/dd4hep.py @@ -12,14 +12,9 @@ print("Error encountered importing DD4hep. Likely you need to set LD_LIBRARY_PATH.") sys.exit(1) -from acts._adapter import _patch_config, _detector_create, _patch_detectors +from acts._adapter import _patch_config from acts import ActsPythonBindingsDD4hep _patch_config(ActsPythonBindingsDD4hep) -_patch_detectors(ActsPythonBindingsDD4hep) -ActsPythonBindingsDD4hep.DD4hepDetector.create = _detector_create( - ActsPythonBindingsDD4hep.DD4hepDetector, - ActsPythonBindingsDD4hep.DD4hepGeometryService.Config, -) from acts.ActsPythonBindingsDD4hep import * diff --git a/Examples/Python/python/acts/examples/geant4/dd4hep.py b/Examples/Python/python/acts/examples/geant4/dd4hep.py deleted file mode 100644 index 2d16253e403..00000000000 --- a/Examples/Python/python/acts/examples/geant4/dd4hep.py +++ /dev/null @@ -1,20 +0,0 @@ -import subprocess -import sys - - -# Cannot conveniently catch linker errors, so we launch a suprocess to -# try importing and see if it works in order to provide a useful error message -try: - subprocess.check_call( - [sys.executable, "-c", "from acts import ActsPythonBindingsDDG4"] - ) -except subprocess.CalledProcessError as e: - print("Error encountered importing DD4hep. Likely you need to set LD_LIBRARY_PATH.") - sys.exit(1) - -from acts._adapter import _patch_config -from acts import ActsPythonBindingsDDG4 - -_patch_config(ActsPythonBindingsDDG4) - -from acts.ActsPythonBindingsDDG4 import * diff --git a/Examples/Python/python/acts/examples/geant4/geomodel.py b/Examples/Python/python/acts/examples/geant4/geomodel.py deleted file mode 100644 index bbc5882eaf3..00000000000 --- a/Examples/Python/python/acts/examples/geant4/geomodel.py +++ /dev/null @@ -1,6 +0,0 @@ -from acts._adapter import _patch_config -from acts import ActsPythonBindingsGeoModelG4 - -_patch_config(ActsPythonBindingsGeoModelG4) - -from acts.ActsPythonBindingsGeoModelG4 import * diff --git a/Examples/Python/python/acts/examples/itk.py b/Examples/Python/python/acts/examples/itk.py index b8e2eba8796..0141e367ee9 100644 --- a/Examples/Python/python/acts/examples/itk.py +++ b/Examples/Python/python/acts/examples/itk.py @@ -53,7 +53,7 @@ def buildITkGeometry( if jsonconfig: jsonFile = geo_dir / "itk-hgtd/tgeo-atlas-itk-hgtd.json" logger.info("Create geometry from %s", jsonFile.absolute()) - return TGeoDetector.create( + return TGeoDetector( jsonFile=str(jsonFile), fileName=str(tgeo_fileName), surfaceLogLevel=customLogLevel(), @@ -72,7 +72,7 @@ def buildITkGeometry( # in the root file (it changed ATLAS-P2-23 -> ATLAS-P2-RUN4-01-00-00). # `TGeoParser` searches the tree below `subVolumeName` for all elements that match any of the # list of `sensitiveNames` wildcards and also fall inside the `rRange`/`zRange` selections. - # If no `TGeoDetectorElements`` are found for an ACTS `Volume()`, then `TGeoDetector.create()` + # If no `TGeoDetectorElements`` are found for an ACTS `Volume()`, then `TGeoDetector()` # raises an exception along the lines of: # 1. Missing tracking geometry - or # 2. Incorrect binning configuration found: Number of configurations does not match number of protolayers @@ -83,7 +83,7 @@ def buildITkGeometry( # * browsing `TGeoManager` with ROOT's `TBrowser` (easy to navigate, but have to scan through long lists by eye). # If the detector has moved significantly, it may be necessary to change the `rRange`/`zRange`. # This specification should be kept in sync with `itk-hgtd/tgeo-atlas-itk-hgtd.json`. - return TGeoDetector.create( + return TGeoDetector( fileName=str(tgeo_fileName), mdecorator=matDeco, buildBeamPipe=True, diff --git a/Examples/Python/python/acts/examples/odd.py b/Examples/Python/python/acts/examples/odd.py index 5e187948ee2..e0edef15776 100644 --- a/Examples/Python/python/acts/examples/odd.py +++ b/Examples/Python/python/acts/examples/odd.py @@ -1,7 +1,6 @@ import os import sys import math -from collections import namedtuple from pathlib import Path from typing import Optional import acts @@ -87,36 +86,19 @@ def geoid_hook(geoid, surface): return geoid - dd4hepConfig = acts.examples.dd4hep.DD4hepGeometryService.Config( - xmlFileNames=[str(odd_xml)], - logLevel=customLogLevel(), - dd4hepLogLevel=customLogLevel(minLevel=acts.logging.WARNING), - geometryIdentifierHook=acts.GeometryIdentifierHook(geoid_hook), - ) - detector = acts.examples.dd4hep.DD4hepDetector() - if mdecorator is None: mdecorator = acts.examples.RootMaterialDecorator( fileName=str(odd_dir / "data/odd-material-maps.root"), level=customLogLevel(minLevel=acts.logging.WARNING), ) - trackingGeometry, decorators = detector.finalize(dd4hepConfig, mdecorator) - - OpenDataDetector = namedtuple( - "OpenDataDetector", ["detector", "trackingGeometry", "decorators"] + dd4hepConfig = acts.examples.dd4hep.DD4hepDetector.Config( + xmlFileNames=[str(odd_xml)], + name="OpenDataDetector", + logLevel=customLogLevel(), + dd4hepLogLevel=customLogLevel(minLevel=acts.logging.WARNING), + geometryIdentifierHook=acts.GeometryIdentifierHook(geoid_hook), + materialDecorator=mdecorator, ) - - class OpenDataDetectorContextManager(OpenDataDetector): - def __new__(cls, detector, trackingGeometry, decorators): - return super(OpenDataDetectorContextManager, cls).__new__( - cls, detector, trackingGeometry, decorators - ) - - def __enter__(self): - return self - - def __exit__(self, *args): - self.detector.drop() - - return OpenDataDetectorContextManager(detector, trackingGeometry, decorators) + detector = acts.examples.dd4hep.DD4hepDetector(dd4hepConfig) + return detector diff --git a/Examples/Python/python/acts/examples/simulation.py b/Examples/Python/python/acts/examples/simulation.py index ff690e2a777..a82c16e4198 100644 --- a/Examples/Python/python/acts/examples/simulation.py +++ b/Examples/Python/python/acts/examples/simulation.py @@ -585,40 +585,6 @@ def addSimWriters( ) -def getG4DetectorConstructionFactory( - detector: Any, - regionList: List[Any] = [], -) -> Any: - try: - from acts.examples import TelescopeDetector - from acts.examples.geant4 import TelescopeG4DetectorConstructionFactory - - if type(detector) is TelescopeDetector: - return TelescopeG4DetectorConstructionFactory(detector, regionList) - except Exception as e: - print(e) - - try: - from acts.examples.dd4hep import DD4hepDetector - from acts.examples.geant4.dd4hep import DDG4DetectorConstructionFactory - - if type(detector) is DD4hepDetector: - return DDG4DetectorConstructionFactory(detector, regionList) - except Exception as e: - print(e) - - try: - from acts import geomodel as gm - from acts.examples.geant4.geomodel import GeoModelDetectorConstructionFactory - - if type(detector) is gm.GeoModelTree: - return GeoModelDetectorConstructionFactory(detector, regionList) - except Exception as e: - print(e) - - raise AttributeError(f"cannot find a suitable detector construction for {detector}") - - # holds the Geant4Handle for potential reuse __geant4Handle = None @@ -629,7 +595,6 @@ def addGeant4( trackingGeometry: Union[acts.TrackingGeometry, acts.Detector], field: acts.MagneticFieldProvider, rnd: acts.examples.RandomNumbers, - g4DetectorConstructionFactory: Optional[Any] = None, volumeMappings: List[str] = [], materialMappings: List[str] = ["Silicon"], inputParticles: str = "particles_input", @@ -697,13 +662,6 @@ def addGeant4( s.addWhiteboardAlias("particles_selected", particlesPreSelected) - if g4DetectorConstructionFactory is None: - if detector is None: - raise AttributeError("detector not given") - g4DetectorConstructionFactory = getG4DetectorConstructionFactory( - detector, regionList - ) - global __geant4Handle smmConfig = SensitiveSurfaceMapper.Config() @@ -717,7 +675,7 @@ def addGeant4( alg = Geant4Simulation( level=customLogLevel(), geant4Handle=__geant4Handle, - detectorConstructionFactory=g4DetectorConstructionFactory, + detector=detector, randomNumbers=rnd, inputParticles=particlesPreSelected, outputParticles=outputParticles, diff --git a/Examples/Python/src/Covfie.cpp b/Examples/Python/src/Covfie.cpp index 5a630400d88..27ceb17373f 100644 --- a/Examples/Python/src/Covfie.cpp +++ b/Examples/Python/src/Covfie.cpp @@ -9,6 +9,8 @@ #include "Acts/Plugins/Covfie/FieldConversion.hpp" #include "Acts/Plugins/Python/Utilities.hpp" +#include + #include #include diff --git a/Examples/Python/src/DD4hepComponent.cpp b/Examples/Python/src/DD4hepComponent.cpp index e38a33cf82c..1efd050fef5 100644 --- a/Examples/Python/src/DD4hepComponent.cpp +++ b/Examples/Python/src/DD4hepComponent.cpp @@ -14,12 +14,11 @@ #include "Acts/Plugins/Python/Utilities.hpp" #include "Acts/Utilities/Logger.hpp" #include "ActsExamples/DD4hepDetector/DD4hepDetector.hpp" -#include "ActsExamples/DD4hepDetector/DD4hepGeometryService.hpp" -#include "ActsExamples/Framework/IContextDecorator.hpp" #include #include +#include #include #include @@ -29,15 +28,19 @@ using namespace Acts::Python; PYBIND11_MODULE(ActsPythonBindingsDD4hep, m) { { - using Config = DD4hepGeometryService::Config; - auto s = py::class_>( - m, "DD4hepGeometryService") - .def(py::init()) - .def("drop", &DD4hepGeometryService::drop); - - auto c = py::class_(s, "Config").def(py::init<>()); - ACTS_PYTHON_STRUCT_BEGIN(c, Config); + py::class_>( + m, "DD4hepDetectorElement"); + } + + { + auto f = + py::class_>( + m, "DD4hepDetector") + .def(py::init()); + + auto c = py::class_(f, "Config").def(py::init<>()); + ACTS_PYTHON_STRUCT_BEGIN(c, DD4hepDetector::Config); ACTS_PYTHON_MEMBER(logLevel); ACTS_PYTHON_MEMBER(dd4hepLogLevel); ACTS_PYTHON_MEMBER(xmlFileNames); @@ -48,6 +51,7 @@ PYBIND11_MODULE(ActsPythonBindingsDD4hep, m) { ACTS_PYTHON_MEMBER(envelopeR); ACTS_PYTHON_MEMBER(envelopeZ); ACTS_PYTHON_MEMBER(defaultLayerThickness); + ACTS_PYTHON_MEMBER(materialDecorator); ACTS_PYTHON_MEMBER(geometryIdentifierHook); ACTS_PYTHON_STRUCT_END(); @@ -60,12 +64,6 @@ PYBIND11_MODULE(ActsPythonBindingsDD4hep, m) { "DD4hepFieldAdapter"); } - { - py::class_>( - m, "DD4hepDetectorElement"); - } - { m.def("createDD4hepIdGeoIdMap", [](const Acts::TrackingGeometry& tGeometry) @@ -146,22 +144,4 @@ PYBIND11_MODULE(ActsPythonBindingsDD4hep, m) { options.geoIdGenerator = chainedGeoIdGenerator; }); } - - { - py::class_>( - m, "DD4hepDetector") - .def(py::init<>()) - .def(py::init>()) - .def("finalize", - py::overload_cast>( - &DD4hepDetector::finalize)) - .def("finalize", - py::overload_cast< - const Acts::GeometryContext&, - const Acts::Experimental::DD4hepDetectorStructure::Options&>( - &DD4hepDetector::finalize)) - .def("drop", &DD4hepDetector::drop) - .def_property_readonly("field", &DD4hepDetector::field); - } } diff --git a/Examples/Python/src/Detector.cpp b/Examples/Python/src/Detector.cpp index 94770ce7283..59a7cd13d06 100644 --- a/Examples/Python/src/Detector.cpp +++ b/Examples/Python/src/Detector.cpp @@ -6,11 +6,15 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. +#include "Acts/Detector/Detector.hpp" + +#include "Acts/Geometry/DetectorElementBase.hpp" #include "Acts/Geometry/TrackingGeometry.hpp" #include "Acts/Material/IMaterialDecorator.hpp" #include "Acts/Plugins/Python/Utilities.hpp" #include "Acts/Utilities/BinningType.hpp" #include "ActsExamples/ContextualDetector/AlignedDetector.hpp" +#include "ActsExamples/DetectorCommons/Detector.hpp" #include "ActsExamples/Framework/IContextDecorator.hpp" #include "ActsExamples/GenericDetector/GenericDetector.hpp" #include "ActsExamples/TGeoDetector/TGeoDetector.hpp" @@ -33,6 +37,7 @@ namespace Acts::Python { void addDetector(Context& ctx) { auto [m, mex] = ctx.get("main", "examples"); + { py::class_>( mex, "IContextDecorator") @@ -41,68 +46,69 @@ void addDetector(Context& ctx) { } { - using Detector = GenericDetector; - using Config = Detector::Config; - - auto gd = - py::class_>(mex, "GenericDetector") - .def(py::init<>()) - .def("finalize", - py::overload_cast< - const Config&, - std::shared_ptr>( - &Detector::finalize)); - - py::class_(gd, "Config") - .def(py::init<>()) - .def_readwrite("buildLevel", &Config::buildLevel) - .def_readwrite("surfaceLogLevel", &Config::surfaceLogLevel) - .def_readwrite("layerLogLevel", &Config::layerLogLevel) - .def_readwrite("volumeLogLevel", &Config::volumeLogLevel) - .def_readwrite("buildProto", &Config::buildProto); + py::class_>(mex, "DetectorBase") + .def("nominalGeometryContext", &Detector::nominalGeometryContext) + .def("trackingGeometry", &Detector::trackingGeometry) + .def("gen2Geometry", &Detector::gen2Geometry) + .def("contextDecorators", &Detector::contextDecorators) + .def("__enter__", + [](const std::shared_ptr& self) { return self; }) + .def("__exit__", + [](std::shared_ptr& self, + const std::optional&, + const std::optional&, + const std::optional&) { self.reset(); }); } { - using Detector = TelescopeDetector; - using Config = Detector::Config; - - auto td = - py::class_>(mex, - "TelescopeDetector") - .def(py::init<>()) - .def("finalize", - py::overload_cast< - const Config&, - const std::shared_ptr&>( - &Detector::finalize)); - - py::class_(td, "Config") - .def(py::init<>()) - .def_readwrite("positions", &Config::positions) - .def_readwrite("stereos", &Config::stereos) - .def_readwrite("offsets", &Config::offsets) - .def_readwrite("bounds", &Config::bounds) - .def_readwrite("thickness", &Config::thickness) - .def_readwrite("surfaceType", &Config::surfaceType) - .def_readwrite("binValue", &Config::binValue); + auto d = + py::class_>( + mex, "GenericDetector") + .def(py::init()); + + auto c = py::class_(d, "Config").def(py::init<>()); + ACTS_PYTHON_STRUCT_BEGIN(c, GenericDetector::Config); + ACTS_PYTHON_MEMBER(buildLevel); + ACTS_PYTHON_MEMBER(logLevel); + ACTS_PYTHON_MEMBER(surfaceLogLevel); + ACTS_PYTHON_MEMBER(layerLogLevel); + ACTS_PYTHON_MEMBER(volumeLogLevel); + ACTS_PYTHON_MEMBER(buildProto); + ACTS_PYTHON_MEMBER(materialDecorator); + ACTS_PYTHON_STRUCT_END(); } { - using Detector = AlignedDetector; - using Config = Detector::Config; + auto d = + py::class_>(mex, "TelescopeDetector") + .def(py::init()); + + auto c = + py::class_(d, "Config").def(py::init<>()); + ACTS_PYTHON_STRUCT_BEGIN(c, TelescopeDetector::Config); + ACTS_PYTHON_MEMBER(positions); + ACTS_PYTHON_MEMBER(stereos); + ACTS_PYTHON_MEMBER(offsets); + ACTS_PYTHON_MEMBER(bounds); + ACTS_PYTHON_MEMBER(thickness); + ACTS_PYTHON_MEMBER(surfaceType); + ACTS_PYTHON_MEMBER(binValue); + ACTS_PYTHON_MEMBER(materialDecorator); + ACTS_PYTHON_MEMBER(logLevel); + ACTS_PYTHON_STRUCT_END(); + } + { auto d = - py::class_>(mex, "AlignedDetector") - .def(py::init<>()) - .def("finalize", - py::overload_cast< - const Config&, - std::shared_ptr>( - &Detector::finalize)); - - auto c = py::class_(d, "Config") + py::class_>( + mex, "AlignedDetector") + .def(py::init()); + + auto c = py::class_( + d, "Config") .def(py::init<>()); - ACTS_PYTHON_STRUCT_BEGIN(c, Config); + ACTS_PYTHON_STRUCT_BEGIN(c, AlignedDetector::Config); ACTS_PYTHON_MEMBER(seed); ACTS_PYTHON_MEMBER(iovSize); ACTS_PYTHON_MEMBER(flushSize); @@ -116,23 +122,15 @@ void addDetector(Context& ctx) { ACTS_PYTHON_MEMBER(mode); ACTS_PYTHON_STRUCT_END(); - py::enum_(c, "Mode") - .value("Internal", Config::Mode::Internal) - .value("External", Config::Mode::External); + py::enum_(c, "Mode") + .value("Internal", AlignedDetector::Config::Mode::Internal) + .value("External", AlignedDetector::Config::Mode::External); } { - using Detector = TGeoDetector; - using Config = Detector::Config; - - auto d = - py::class_>(mex, "TGeoDetector") - .def(py::init<>()) - .def("finalize", - py::overload_cast< - const Config&, - std::shared_ptr>( - &Detector::finalize)); + auto d = py::class_>( + mex, "TGeoDetector") + .def(py::init()); py::class_(mex, "Interval") .def(py::init<>()) @@ -140,23 +138,25 @@ void addDetector(Context& ctx) { .def_readwrite("lower", &Options::Interval::lower) .def_readwrite("upper", &Options::Interval::upper); - auto c = py::class_(d, "Config").def(py::init<>()); + auto c = py::class_(d, "Config").def(py::init<>()); - c.def_property( - "jsonFile", nullptr, - [](Config& cfg, const std::string& file) { cfg.readJson(file); }); + c.def_property("jsonFile", nullptr, + [](TGeoDetector::Config& cfg, const std::string& file) { + cfg.readJson(file); + }); - py::enum_(c, "SubVolume") - .value("Negative", Config::SubVolume::Negative) - .value("Central", Config::SubVolume::Central) - .value("Positive", Config::SubVolume::Positive); + py::enum_(c, "SubVolume") + .value("Negative", TGeoDetector::Config::SubVolume::Negative) + .value("Central", TGeoDetector::Config::SubVolume::Central) + .value("Positive", TGeoDetector::Config::SubVolume::Positive); py::enum_(c, "BinningType") .value("equidistant", Acts::BinningType::equidistant) .value("arbitrary", Acts::BinningType::arbitrary); - auto volume = py::class_(c, "Volume").def(py::init<>()); - ACTS_PYTHON_STRUCT_BEGIN(volume, Config::Volume); + auto volume = + py::class_(c, "Volume").def(py::init<>()); + ACTS_PYTHON_STRUCT_BEGIN(volume, TGeoDetector::Config::Volume); ACTS_PYTHON_MEMBER(name); ACTS_PYTHON_MEMBER(binToleranceR); ACTS_PYTHON_MEMBER(binTolerancePhi); @@ -185,15 +185,18 @@ void addDetector(Context& ctx) { auto regTriplet = [&c](const std::string& name, auto v) { using type = decltype(v); - py::class_>(c, name.c_str()) + py::class_>(c, name.c_str()) .def(py::init<>()) .def(py::init()) .def(py::init()) - .def_readwrite("negative", &Config::LayerTriplet::negative) - .def_readwrite("central", &Config::LayerTriplet::central) - .def_readwrite("positive", &Config::LayerTriplet::positive) - .def("at", py::overload_cast( - &Config::LayerTriplet::at)); + .def_readwrite("negative", + &TGeoDetector::Config::LayerTriplet::negative) + .def_readwrite("central", + &TGeoDetector::Config::LayerTriplet::central) + .def_readwrite("positive", + &TGeoDetector::Config::LayerTriplet::positive) + .def("at", py::overload_cast( + &TGeoDetector::Config::LayerTriplet::at)); }; regTriplet("LayerTripletBool", true); @@ -204,7 +207,7 @@ void addDetector(Context& ctx) { regTriplet("LayerTripletVectorBinning", std::vector>{}); - ACTS_PYTHON_STRUCT_BEGIN(c, Config); + ACTS_PYTHON_STRUCT_BEGIN(c, TGeoDetector::Config); ACTS_PYTHON_MEMBER(surfaceLogLevel); ACTS_PYTHON_MEMBER(layerLogLevel); ACTS_PYTHON_MEMBER(volumeLogLevel); diff --git a/Examples/Python/src/Geant4Component.cpp b/Examples/Python/src/Geant4Component.cpp index d1f59e3973f..96129e6cc2f 100644 --- a/Examples/Python/src/Geant4Component.cpp +++ b/Examples/Python/src/Geant4Component.cpp @@ -16,17 +16,15 @@ #include "Acts/Plugins/Python/Utilities.hpp" #include "Acts/Surfaces/SurfaceVisitorConcept.hpp" #include "Acts/Utilities/Logger.hpp" -#include "ActsExamples/Framework/IContextDecorator.hpp" -#include "ActsExamples/Geant4/DetectorConstructionFactory.hpp" -#include "ActsExamples/Geant4/GdmlDetectorConstruction.hpp" +#include "ActsExamples/Geant4/Geant4ConstructionOptions.hpp" #include "ActsExamples/Geant4/Geant4Manager.hpp" #include "ActsExamples/Geant4/Geant4Simulation.hpp" #include "ActsExamples/Geant4/RegionCreator.hpp" #include "ActsExamples/Geant4/SensitiveSurfaceMapper.hpp" +#include "ActsExamples/Geant4Detector/GdmlDetector.hpp" +#include "ActsExamples/Geant4Detector/GdmlDetectorConstruction.hpp" #include "ActsExamples/Geant4Detector/Geant4Detector.hpp" #include "ActsExamples/MuonSpectrometerMockupDetector/MockupSectorBuilder.hpp" -#include "ActsExamples/TelescopeDetector/TelescopeDetector.hpp" -#include "ActsExamples/TelescopeDetector/TelescopeG4DetectorConstruction.hpp" #include #include @@ -86,10 +84,6 @@ struct ExperimentalSensitiveCandidates }; PYBIND11_MODULE(ActsPythonBindingsGeant4, mod) { - py::class_>( - mod, "DetectorConstructionFactory"); - py::class_>( mod, "Geant4Manager") .def_static("instance", &Geant4Manager::instance, @@ -99,6 +93,15 @@ PYBIND11_MODULE(ActsPythonBindingsGeant4, mod) { py::class_>(mod, "Geant4Handle") .def("tweakLogging", &Geant4Handle::tweakLogging); + { + py::class_>( + mod, "Geant4ConstructionOptions") + .def(py::init<>()) + .def_readwrite("regionCreators", + &Geant4ConstructionOptions::regionCreators); + } + { using Algorithm = Geant4SimulationBase; using Config = Algorithm::Config; @@ -112,7 +115,7 @@ PYBIND11_MODULE(ActsPythonBindingsGeant4, mod) { ACTS_PYTHON_STRUCT_BEGIN(c1, Config); ACTS_PYTHON_MEMBER(inputParticles); ACTS_PYTHON_MEMBER(randomNumbers); - ACTS_PYTHON_MEMBER(detectorConstructionFactory); + ACTS_PYTHON_MEMBER(detector); ACTS_PYTHON_MEMBER(geant4Handle); ACTS_PYTHON_STRUCT_END(); } @@ -140,7 +143,7 @@ PYBIND11_MODULE(ActsPythonBindingsGeant4, mod) { sm.def("create", [](const Config& cfg, Acts::Logging::Level level, - const std::shared_ptr tGeometry) { + const std::shared_ptr& tGeometry) { // Set a new surface finder Config ccfg = cfg; auto candidateSurfaces = @@ -169,10 +172,11 @@ PYBIND11_MODULE(ActsPythonBindingsGeant4, mod) { sm.def( "remapSensitiveNames", [](Geant4::SensitiveSurfaceMapper& self, State& state, - GeometryContext& gctx, Geant4::DetectorConstructionFactory& factory, - Transform3& transform) { + GeometryContext& gctx, Detector& detector, Transform3& transform) { return self.remapSensitiveNames( - state, gctx, factory.factorize()->Construct(), transform); + state, gctx, + detector.buildGeant4DetectorConstruction({})->Construct(), + transform); }, "state"_a, "gctx"_a, "g4physicalVolume"_a, "motherTransform"_a); sm.def("checkMapping", &Geant4::SensitiveSurfaceMapper::checkMapping, @@ -230,30 +234,6 @@ PYBIND11_MODULE(ActsPythonBindingsGeant4, mod) { ACTS_PYTHON_STRUCT_END(); } - { - py::class_>( - mod, "GdmlDetectorConstructionFactory") - .def(py::init>>(), - py::arg("path"), - py::arg("regionCreators") = - std::vector>()); - } - - { - py::class_>( - mod, "TelescopeG4DetectorConstructionFactory") - .def(py::init>>(), - py::arg("cfg"), - py::arg("regionCreators") = - std::vector>()); - } - { using ISelector = Acts::IGeant4PhysicalVolumeSelector; auto is = py::class_>( @@ -277,33 +257,13 @@ PYBIND11_MODULE(ActsPythonBindingsGeant4, mod) { } { - py::class_>( - mod, "Geant4DetectorElement"); - - using Detector = Geant4Detector; - using Config = Detector::Config; - - auto g = - py::class_>(mod, "Geant4Detector") - .def(py::init<>()) - .def( - "constructDetector", - [](Detector& self, const Config& cfg, Logging::Level logLevel) { - auto logger = getDefaultLogger("Geant4Detector", logLevel); - return self.constructDetector(cfg, *logger); - }, - py::arg("cfg"), py::arg("logLevel") = Logging::INFO) - .def( - "constructTrackingGeometry", - [](Detector& self, const Config& cfg, Logging::Level logLevel) { - auto logger = getDefaultLogger("Geant4Detector", logLevel); - return self.constructTrackingGeometry(cfg, *logger); - }, - py::arg("cfg"), py::arg("logLevel") = Logging::INFO); - - auto c = py::class_(g, "Config").def(py::init<>()); - ACTS_PYTHON_STRUCT_BEGIN(c, Config); + auto f = + py::class_>( + mod, "Geant4Detector") + .def(py::init()); + + auto c = py::class_(f, "Config").def(py::init<>()); + ACTS_PYTHON_STRUCT_BEGIN(c, Geant4Detector::Config); ACTS_PYTHON_MEMBER(name); ACTS_PYTHON_MEMBER(g4World); ACTS_PYTHON_MEMBER(g4SurfaceOptions); @@ -313,6 +273,18 @@ PYBIND11_MODULE(ActsPythonBindingsGeant4, mod) { ACTS_PYTHON_STRUCT_END(); } + { + auto f = py::class_>( + mod, "GdmlDetector") + .def(py::init()); + + auto c = py::class_(f, "Config").def(py::init<>()); + ACTS_PYTHON_STRUCT_BEGIN(c, GdmlDetector::Config); + ACTS_PYTHON_MEMBER(path); + ACTS_PYTHON_MEMBER(logLevel); + ACTS_PYTHON_STRUCT_END(); + } + { /// Helper function to test if the automatic geometry conversion works /// @@ -326,7 +298,7 @@ PYBIND11_MODULE(ActsPythonBindingsGeant4, mod) { passiveMatches, bool convertMaterial) { // Initiate the detector construction & retrieve world - ActsExamples::GdmlDetectorConstruction gdmlContruction(gdmlFileName); + ActsExamples::GdmlDetectorConstruction gdmlContruction(gdmlFileName, {}); const auto* world = gdmlContruction.Construct(); // Create the selectors @@ -406,10 +378,8 @@ PYBIND11_MODULE(ActsPythonBindingsGeant4, mod) { { using Tool = Geant4::RegionCreator; using Config = Tool::Config; - auto tool = py::class_>(mod, "RegionCreator") - .def(py::init(), - py::arg("config"), py::arg("name"), - py::arg("logLevel") = Logging::INFO) + auto tool = py::class_(mod, "RegionCreator") + .def(py::init(), py::arg("config")) .def_property_readonly("config", &Tool::config); auto c = py::class_(tool, "Config").def(py::init<>()); diff --git a/Examples/Python/src/Geant4DD4hepComponent.cpp b/Examples/Python/src/Geant4DD4hepComponent.cpp deleted file mode 100644 index 409bca273d1..00000000000 --- a/Examples/Python/src/Geant4DD4hepComponent.cpp +++ /dev/null @@ -1,34 +0,0 @@ -// This file is part of the ACTS project. -// -// Copyright (C) 2016 CERN for the benefit of the ACTS project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at https://mozilla.org/MPL/2.0/. - -#include "ActsExamples/DD4hepDetector/DD4hepDetector.hpp" -#include "ActsExamples/DDG4/DDG4DetectorConstruction.hpp" -#include "ActsExamples/Geant4/RegionCreator.hpp" - -#include -#include -#include - -namespace py = pybind11; - -using namespace ActsExamples; -using namespace Acts; - -PYBIND11_MODULE(ActsPythonBindingsDDG4, m) { - py::module_::import("acts.ActsPythonBindingsGeant4"); - - py::class_>( - m, "DDG4DetectorConstructionFactory") - .def(py::init, - std::vector>>(), - py::arg("detector"), - py::arg("regionCreators") = - std::vector>()); -} diff --git a/Examples/Python/src/Geant4GeoModelComponent.cpp b/Examples/Python/src/Geant4GeoModelComponent.cpp deleted file mode 100644 index d9c372984db..00000000000 --- a/Examples/Python/src/Geant4GeoModelComponent.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// This file is part of the ACTS project. -// -// Copyright (C) 2016 CERN for the benefit of the ACTS project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at https://mozilla.org/MPL/2.0/. - -#include "ActsExamples/Geant4/DetectorConstructionFactory.hpp" -#include "ActsExamples/Geant4/RegionCreator.hpp" -#include "ActsExamples/GeoModelG4/GeoModelDetectorConstruction.hpp" - -#include -#include -#include - -class GeoVPhysVol; - -namespace py = pybind11; - -using namespace ActsExamples; -using namespace Acts; - -PYBIND11_MODULE(ActsPythonBindingsGeoModelG4, m) { - py::module_::import("acts.ActsPythonBindingsGeant4"); - - py::class_>( - m, "GeoModelDetectorConstructionFactory") - .def(py::init>>(), - py::arg("geoModelTree"), - py::arg("regionCreators") = - std::vector>()); -} diff --git a/Examples/Python/src/Geant4HepMC3.cpp b/Examples/Python/src/Geant4HepMC3.cpp index 913a23da60f..596cf744660 100644 --- a/Examples/Python/src/Geant4HepMC3.cpp +++ b/Examples/Python/src/Geant4HepMC3.cpp @@ -7,11 +7,8 @@ // file, You can obtain one at https://mozilla.org/MPL/2.0/. #include "Acts/Plugins/Python/Utilities.hpp" -#include "ActsExamples/Geant4/DetectorConstructionFactory.hpp" #include "ActsExamples/Geant4HepMC/EventRecording.hpp" -#include - #include #include @@ -29,8 +26,7 @@ void addGeant4HepMC3(Context& ctx) { ACTS_PYTHON_DECLARE_ALGORITHM( EventRecording, h3, "EventRecording", inputParticles, outputHepMcTracks, - detectorConstructionFactory, seed1, seed2, processesCombine, - processSelect, processesReject); + detector, seed1, seed2, processesCombine, processSelect, processesReject); } } // namespace Acts::Python diff --git a/Examples/Python/src/GeoModel.cpp b/Examples/Python/src/GeoModel.cpp index 58609a573d5..899781a1f2c 100644 --- a/Examples/Python/src/GeoModel.cpp +++ b/Examples/Python/src/GeoModel.cpp @@ -27,6 +27,7 @@ #include "Acts/Surfaces/DiscSurface.hpp" #include "Acts/Surfaces/PlaneSurface.hpp" #include "Acts/Surfaces/RectangleBounds.hpp" +#include "ActsExamples/GeoModelDetector/GeoModelDetector.hpp" #include "ActsExamples/ITkModuleSplitting/ITkModuleSplitting.hpp" #include @@ -40,6 +41,7 @@ namespace py = pybind11; using namespace pybind11::literals; namespace Acts::Python { + void addGeoModel(Context& ctx) { auto m = ctx.get("main"); @@ -59,6 +61,21 @@ void addGeoModel(Context& ctx) { return self.surface().getSharedPtr(); }); + { + auto f = + py::class_>( + gm, "GeoModelDetector") + .def(py::init()); + + auto c = py::class_(f, "Config") + .def(py::init<>()); + ACTS_PYTHON_STRUCT_BEGIN(c, ActsExamples::GeoModelDetector::Config); + ACTS_PYTHON_MEMBER(path); + ACTS_PYTHON_MEMBER(logLevel); + ACTS_PYTHON_STRUCT_END(); + } + // Shape converters { py::class_ #include -#include #include #include @@ -44,14 +41,15 @@ void addGeometryBuildingGen1(Context &ctx) { [](const Acts::LayerCreator &self, const GeometryContext &gctx, SurfacePtrVector surfaces, std::size_t binsPhi, std::size_t binsZ) { - return self.cylinderLayer(gctx, surfaces, binsPhi, binsZ); + return self.cylinderLayer(gctx, std::move(surfaces), binsPhi, + binsZ); }) - .def("discLayer", - [](const Acts::LayerCreator &self, const GeometryContext &gctx, - SurfacePtrVector surfaces, std::size_t binsR, - std::size_t binsPhi) { - return self.discLayer(gctx, surfaces, binsR, binsPhi); - }); + .def("discLayer", [](const Acts::LayerCreator &self, + const GeometryContext &gctx, + SurfacePtrVector surfaces, std::size_t binsR, + std::size_t binsPhi) { + return self.discLayer(gctx, std::move(surfaces), binsR, binsPhi); + }); auto config = py::class_(creator, "Config").def(py::init<>()); @@ -115,8 +113,9 @@ void addGeometryBuildingGen1(Context &ctx) { GeometryContext gctx, const LayerVector &layers, std::shared_ptr volumeBounds, const Transform3 &trafo, const std::string &name) { - return self.createTrackingVolume( - gctx, layers, {}, volumeBounds, {}, trafo, name); + return self.createTrackingVolume(gctx, layers, {}, + std::move(volumeBounds), {}, + trafo, name); }) .def("createContainerTrackingVolume", &Acts::CylinderVolumeHelper::createContainerTrackingVolume); diff --git a/Examples/Python/src/ModuleEntry.cpp b/Examples/Python/src/ModuleEntry.cpp index a78f04f9565..9f494dddee6 100644 --- a/Examples/Python/src/ModuleEntry.cpp +++ b/Examples/Python/src/ModuleEntry.cpp @@ -7,25 +7,10 @@ // file, You can obtain one at https://mozilla.org/MPL/2.0/. #include "Acts/ActsVersion.hpp" -#include "Acts/Geometry/GeometryContext.hpp" -#include "Acts/Geometry/GeometryIdentifier.hpp" -#include "Acts/MagneticField/MagneticFieldContext.hpp" -#include "Acts/Plugins/FpeMonitoring/FpeMonitor.hpp" #include "Acts/Plugins/Python/Utilities.hpp" -#include "Acts/Utilities/CalibrationContext.hpp" -#include "Acts/Utilities/Logger.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include + #include #include -#include #include #include diff --git a/Examples/Python/tests/conftest.py b/Examples/Python/tests/conftest.py index 4bd8a430730..c1eb489bb62 100644 --- a/Examples/Python/tests/conftest.py +++ b/Examples/Python/tests/conftest.py @@ -237,14 +237,17 @@ def _basic_prop_seq_factory(geo, s=None): @pytest.fixture def trk_geo(): - detector, geo, contextDecorators = acts.examples.GenericDetector.create() - yield geo + detector = acts.examples.GenericDetector() + trackingGeometry = detector.trackingGeometry() + yield trackingGeometry DetectorConfig = namedtuple( "DetectorConfig", [ - "detectorTuple", + "detector", + "trackingGeometry", + "decorators", "geometrySelection", "digiConfigFile", "name", @@ -257,9 +260,13 @@ def detector_config(request): srcdir = Path(__file__).resolve().parent.parent.parent.parent if request.param == "generic": - detectorTuple = acts.examples.GenericDetector.create() + detector = acts.examples.GenericDetector() + trackingGeometry = detector.trackingGeometry() + decorators = detector.contextDecorators() return DetectorConfig( - detectorTuple, + detector, + trackingGeometry, + decorators, geometrySelection=( srcdir / "Examples/Algorithms/TrackFinding/share/geoSelection-genericDetector.json" @@ -278,9 +285,13 @@ def detector_config(request): srcdir / "thirdparty/OpenDataDetector/data/odd-material-maps.root", level=acts.logging.INFO, ) - detectorTuple = getOpenDataDetector(matDeco) + detector = getOpenDataDetector(matDeco) + trackingGeometry = detector.trackingGeometry() + decorators = detector.contextDecorators() return DetectorConfig( - detectorTuple, + detector, + trackingGeometry, + decorators, digiConfigFile=( srcdir / "thirdparty/OpenDataDetector/config/odd-digi-smearing-config.json" @@ -375,14 +386,8 @@ def _do_material_recording(d: Path): s = acts.examples.Sequencer(events=2, numThreads=1) - with getOpenDataDetector() as (detector, trackingGeometry, decorators): - detectorConstructionFactory = ( - acts.examples.geant4.dd4hep.DDG4DetectorConstructionFactory(detector) - ) - - runMaterialRecording( - detectorConstructionFactory, str(d), tracksPerEvent=100, s=s - ) + with getOpenDataDetector() as detector: + runMaterialRecording(detector, str(d), tracksPerEvent=100, s=s) s.run() @@ -396,7 +401,9 @@ def material_recording_session(): pytest.skip("DD4hep recording requested, but DD4hep is not set up") with tempfile.TemporaryDirectory() as d: - p = multiprocessing.Process(target=_do_material_recording, args=(d,)) + # explicitly ask for "spawn" as CI failures were observed with "fork" + spawn_context = multiprocessing.get_context("spawn") + p = spawn_context.Process(target=_do_material_recording, args=(d,)) p.start() p.join() if p.exitcode != 0: diff --git a/Examples/Python/tests/test_detectors.py b/Examples/Python/tests/test_detectors.py index 3de27524db9..bbfb715697f 100644 --- a/Examples/Python/tests/test_detectors.py +++ b/Examples/Python/tests/test_detectors.py @@ -27,41 +27,50 @@ def check_extra_odd(srf): def test_generic_geometry(): - detector, geo, contextDecorators = acts.examples.GenericDetector.create() + detector = acts.examples.GenericDetector() + trackingGeometry = detector.trackingGeometry() + contextDecorators = detector.contextDecorators() assert detector is not None - assert geo is not None + assert trackingGeometry is not None assert contextDecorators is not None - assert count_surfaces(geo) == 18728 + assert count_surfaces(trackingGeometry) == 18728 def test_telescope_geometry(): n_surfaces = 10 - detector, geo, contextDecorators = acts.examples.TelescopeDetector.create( + config = acts.examples.TelescopeDetector.Config( bounds=[100, 100], positions=[10 * i for i in range(n_surfaces)], stereos=[0] * n_surfaces, binValue=0, ) + detector = acts.examples.TelescopeDetector(config) + trackingGeometry = detector.trackingGeometry() + contextDecorators = detector.contextDecorators() assert detector is not None - assert geo is not None + assert trackingGeometry is not None assert contextDecorators is not None - assert count_surfaces(geo) == n_surfaces + assert count_surfaces(trackingGeometry) == n_surfaces @pytest.mark.skipif(not dd4hepEnabled, reason="DD4hep is not set up") def test_odd(): - with getOpenDataDetector() as (detector, trackingGeometry, decorators): + with getOpenDataDetector() as detector: + trackingGeometry = detector.trackingGeometry() + trackingGeometry.visitSurfaces(check_extra_odd) assert count_surfaces(trackingGeometry) == 18824 def test_aligned_detector(): - detector, trackingGeometry, decorators = acts.examples.AlignedDetector.create() + detector = acts.examples.AlignedDetector() + trackingGeometry = detector.trackingGeometry() + decorators = detector.contextDecorators() assert detector is not None assert trackingGeometry is not None diff --git a/Examples/Python/tests/test_examples.py b/Examples/Python/tests/test_examples.py index daf40b6685a..4e7ea9b14c3 100644 --- a/Examples/Python/tests/test_examples.py +++ b/Examples/Python/tests/test_examples.py @@ -149,7 +149,7 @@ def test_geant4(tmp_path, assert_root_hash): # This test literally only ensures that the geant 4 example can run without erroring out # just to make sure it can build the odd - with getOpenDataDetector() as (detector, trackingGeometry, decorators): + with getOpenDataDetector(): pass csv = tmp_path / "csv" @@ -592,8 +592,7 @@ def test_truth_tracking_kalman( fp = tmp_path / fn assert not fp.exists() - print("with") - with detector_config.detectorTuple as (detector, trackingGeometry, decorators): + with detector_config.detector: from truth_tracking_kalman import runTruthTrackingKalman field = acts.ConstantBField(acts.Vector3(0, 0, 2 * u.T)) @@ -601,7 +600,7 @@ def test_truth_tracking_kalman( seq = Sequencer(events=10, numThreads=1) runTruthTrackingKalman( - trackingGeometry=trackingGeometry, + trackingGeometry=detector_config.trackingGeometry, field=field, digiConfigFile=detector_config.digiConfigFile, outputDir=tmp_path, @@ -610,7 +609,6 @@ def test_truth_tracking_kalman( ) seq.run() - print("done") for fn, tn, ee in root_files: fp = tmp_path / fn @@ -657,10 +655,10 @@ def test_truth_tracking_gsf(tmp_path, assert_root_hash, detector_config): fp = tmp_path / fn assert not fp.exists() - with detector_config.detectorTuple as (detector, trackingGeometry, decorators): + with detector_config.detector: runTruthTrackingGsf( - trackingGeometry=trackingGeometry, - decorators=decorators, + trackingGeometry=detector_config.trackingGeometry, + decorators=detector_config.decorators, field=field, digiConfigFile=detector_config.digiConfigFile, outputDir=tmp_path, @@ -689,11 +687,11 @@ def test_refitting(tmp_path, detector_config, assert_root_hash): numThreads=1, ) - with detector_config.detectorTuple as (detector, trackingGeometry, decorators): + with detector_config.detector: # Only check if it runs without errors right known # Changes in fitter behaviour should be caught by other tests runRefittingGsf( - trackingGeometry=trackingGeometry, + trackingGeometry=detector_config.trackingGeometry, field=field, digiConfigFile=detector_config.digiConfigFile, outputDir=tmp_path, @@ -757,7 +755,10 @@ def test_material_mapping(material_recording, tmp_path, assert_root_hash): s = Sequencer(numThreads=1) - with getOpenDataDetector(mdecorator) as (detector, trackingGeometry, decorators): + with getOpenDataDetector(mdecorator) as detector: + trackingGeometry = detector.trackingGeometry() + decorators = detector.contextDecorators() + runMaterialMapping( trackingGeometry, decorators, @@ -790,11 +791,12 @@ def test_material_mapping(material_recording, tmp_path, assert_root_hash): s = Sequencer(events=10, numThreads=1) - with getOpenDataDetector(mdecorator=acts.IMaterialDecorator.fromFile(mat_file)) as ( - detector, - trackingGeometry, - decorators, - ): + with getOpenDataDetector( + mdecorator=acts.IMaterialDecorator.fromFile(mat_file) + ) as detector: + trackingGeometry = detector.trackingGeometry() + decorators = detector.contextDecorators() + runMaterialValidation( 10, 1000, trackingGeometry, decorators, field, outputDir=str(tmp_path), s=s ) @@ -824,11 +826,12 @@ def test_volume_material_mapping(material_recording, tmp_path, assert_root_hash) s = Sequencer(numThreads=1) - with getOpenDataDetector(mdecorator=acts.IMaterialDecorator.fromFile(geo_map)) as ( - detector, - trackingGeometry, - decorators, - ): + with getOpenDataDetector( + mdecorator=acts.IMaterialDecorator.fromFile(geo_map) + ) as detector: + trackingGeometry = detector.trackingGeometry() + decorators = detector.contextDecorators() + runMaterialMapping( trackingGeometry, decorators, @@ -862,11 +865,12 @@ def test_volume_material_mapping(material_recording, tmp_path, assert_root_hash) s = Sequencer(events=10, numThreads=1) - with getOpenDataDetector(mdecorator=acts.IMaterialDecorator.fromFile(mat_file)) as ( - detector, - trackingGeometry, - decorators, - ): + with getOpenDataDetector( + mdecorator=acts.IMaterialDecorator.fromFile(mat_file) + ) as detector: + trackingGeometry = detector.trackingGeometry() + decorators = detector.contextDecorators() + runMaterialValidation( 10, 1000, @@ -886,11 +890,12 @@ def test_volume_material_mapping(material_recording, tmp_path, assert_root_hash) @pytest.mark.parametrize( - "geoFactory,nobj", + "detectorFactory,aligned,nobj", [ - (GenericDetector.create, 450), + (GenericDetector, True, 450), pytest.param( getOpenDataDetector, + True, 540, marks=[ pytest.mark.skipif(not dd4hepEnabled, reason="DD4hep not set up"), @@ -898,12 +903,14 @@ def test_volume_material_mapping(material_recording, tmp_path, assert_root_hash) pytest.mark.odd, ], ), - (functools.partial(AlignedDetector.create, iovSize=1), 450), + (functools.partial(AlignedDetector, iovSize=1), False, 450), ], ) @pytest.mark.slow -def test_geometry_example(geoFactory, nobj, tmp_path): - detector, trackingGeometry, decorators = geoFactory() +def test_geometry_example(detectorFactory, aligned, nobj, tmp_path): + detector = detectorFactory() + trackingGeometry = detector.trackingGeometry() + decorators = detector.contextDecorators() from geometry import runGeometry @@ -940,12 +947,12 @@ def test_geometry_example(geoFactory, nobj, tmp_path): contents = [f.read_text() for f in detector_files] ref = contents[0] for c in contents[1:]: - if isinstance(detector, AlignedDetector): - assert c != ref, "Detector writeout is expected to be different" - else: + if aligned: assert c == ref, "Detector writeout is expected to be identical" + else: + assert c != ref, "Detector writeout is expected to be different" - if not isinstance(detector, AlignedDetector): + if aligned: for f in [json_dir / f"event{i:>09}-detector.json" for i in range(events)]: assert detector_file.exists() with f.open() as fh: @@ -1163,10 +1170,10 @@ def test_ckf_tracks_example( from ckf_tracks import runCKFTracks - with detector_config.detectorTuple as (detector, trackingGeometry, decorators): + with detector_config.detector: runCKFTracks( - trackingGeometry, - decorators, + detector_config.trackingGeometry, + detector_config.decorators, field=field, outputCsv=True, outputDir=tmp_path, @@ -1199,7 +1206,7 @@ def test_full_chain_odd_example(tmp_path): # This test literally only ensures that the full chain example can run without erroring out # just to make sure it can build the odd - with getOpenDataDetector() as (detector, trackingGeometry, decorators): + with getOpenDataDetector(): pass script = ( @@ -1232,7 +1239,7 @@ def test_full_chain_odd_example_pythia_geant4(tmp_path): # This test literally only ensures that the full chain example can run without erroring out # just to make sure it can build the odd - with getOpenDataDetector() as (detector, trackingGeometry, decorators): + with getOpenDataDetector(): pass script = ( @@ -1286,7 +1293,7 @@ def test_ML_Ambiguity_Solver(tmp_path, assert_root_hash): assert not (tmp_path / root_file).exists() # just to make sure it can build the odd - with getOpenDataDetector() as (detector, trackingGeometry, decorators): + with getOpenDataDetector(): pass script = ( diff --git a/Examples/Python/tests/test_reader.py b/Examples/Python/tests/test_reader.py index 104a4e0f98f..46b1c9c229f 100644 --- a/Examples/Python/tests/test_reader.py +++ b/Examples/Python/tests/test_reader.py @@ -290,7 +290,9 @@ def test_edm4hep_simhit_particle_reader(tmp_path): tmp_file = str(tmp_path / "output_edm4hep.root") odd_xml_file = str(getOpenDataDetectorDirectory() / "xml" / "OpenDataDetector.xml") - p = multiprocessing.Process( + # explicitly ask for "spawn" as CI failures were observed with "fork" + spawn_context = multiprocessing.get_context("spawn") + p = spawn_context.Process( target=generate_input_test_edm4hep_simhit_reader, args=(odd_xml_file, tmp_file) ) p.start() @@ -300,7 +302,9 @@ def test_edm4hep_simhit_particle_reader(tmp_path): s = Sequencer(numThreads=1) - with getOpenDataDetector() as (detector, trackingGeometry, decorators): + with getOpenDataDetector() as detector: + trackingGeometry = detector.trackingGeometry() + s.addReader( EDM4hepReader( level=acts.logging.INFO, @@ -386,7 +390,9 @@ def test_edm4hep_measurement_reader(tmp_path, fatras, conf_const): def test_edm4hep_tracks_reader(tmp_path): from acts.examples.edm4hep import EDM4hepTrackWriter, EDM4hepTrackReader - detector, trackingGeometry, decorators = acts.examples.GenericDetector.create() + detector = acts.examples.GenericDetector() + trackingGeometry = detector.trackingGeometry() + field = acts.ConstantBField(acts.Vector3(0, 0, 2 * u.T)) from truth_tracking_kalman import runTruthTrackingKalman diff --git a/Examples/Python/tests/test_writer.py b/Examples/Python/tests/test_writer.py index ac64fa4048f..2de90c931ab 100644 --- a/Examples/Python/tests/test_writer.py +++ b/Examples/Python/tests/test_writer.py @@ -199,7 +199,8 @@ def test_root_simhits_writer(tmp_path, fatras, conf_const, assert_root_hash): @pytest.mark.root def test_root_tracksummary_writer(tmp_path, fatras, conf_const): - detector, trackingGeometry, decorators = GenericDetector.create() + detector = GenericDetector() + trackingGeometry = detector.trackingGeometry() field = acts.ConstantBField(acts.Vector3(0, 0, 2 * u.T)) s = Sequencer(numThreads=1, events=10) @@ -361,9 +362,10 @@ def test_csv_writer_interface(writer, conf_const, tmp_path, trk_geo): def test_root_material_writer(tmp_path, assert_root_hash): from acts.examples.dd4hep import DD4hepDetector - detector, trackingGeometry, _ = DD4hepDetector.create( + detector = DD4hepDetector( xmlFileNames=[str(getOpenDataDetectorDirectory() / "xml/OpenDataDetector.xml")] ) + trackingGeometry = detector.trackingGeometry() out = tmp_path / "material.root" @@ -385,9 +387,10 @@ def test_root_material_writer(tmp_path, assert_root_hash): def test_json_material_writer(tmp_path, fmt): from acts.examples.dd4hep import DD4hepDetector - detector, trackingGeometry, _ = DD4hepDetector.create( + detector = DD4hepDetector( xmlFileNames=[str(getOpenDataDetectorDirectory() / "xml/OpenDataDetector.xml")] ) + trackingGeometry = detector.trackingGeometry() out = (tmp_path / "material").with_suffix("." + fmt.name.lower()) @@ -404,7 +407,8 @@ def test_json_material_writer(tmp_path, fmt): @pytest.mark.csv def test_csv_multitrajectory_writer(tmp_path): - detector, trackingGeometry, decorators = GenericDetector.create() + detector = GenericDetector() + trackingGeometry = detector.trackingGeometry() field = acts.ConstantBField(acts.Vector3(0, 0, 2 * u.T)) from truth_tracking_kalman import runTruthTrackingKalman @@ -602,7 +606,8 @@ def test_edm4hep_particle_writer(tmp_path, conf_const, ptcl_gun): def test_edm4hep_multitrajectory_writer(tmp_path): from acts.examples.edm4hep import EDM4hepMultiTrajectoryWriter - detector, trackingGeometry, decorators = GenericDetector.create() + detector = GenericDetector() + trackingGeometry = detector.trackingGeometry() field = acts.ConstantBField(acts.Vector3(0, 0, 2 * u.T)) from truth_tracking_kalman import runTruthTrackingKalman @@ -651,7 +656,8 @@ def test_edm4hep_multitrajectory_writer(tmp_path): def test_edm4hep_tracks_writer(tmp_path): from acts.examples.edm4hep import EDM4hepTrackWriter - detector, trackingGeometry, decorators = GenericDetector.create() + detector = GenericDetector() + trackingGeometry = detector.trackingGeometry() field = acts.ConstantBField(acts.Vector3(0, 0, 2 * u.T)) from truth_tracking_kalman import runTruthTrackingKalman diff --git a/Examples/Scripts/GsfDebugger/make_gsf_verbose_log.py b/Examples/Scripts/GsfDebugger/make_gsf_verbose_log.py index c72e183feae..7f4b466ee84 100755 --- a/Examples/Scripts/GsfDebugger/make_gsf_verbose_log.py +++ b/Examples/Scripts/GsfDebugger/make_gsf_verbose_log.py @@ -1,7 +1,6 @@ #!/bin/python3 -import sys + from pathlib import Path -import os import acts import acts.examples @@ -20,7 +19,8 @@ ) assert digiConfigFile.exists() - detector, trackingGeometry, decorators = acts.examples.GenericDetector.create() + detector = acts.examples.GenericDetector() + trackingGeometry = detector.trackingGeometry() field = acts.ConstantBField(acts.Vector3(0, 0, 2 * u.T)) diff --git a/Examples/Scripts/Optimization/ckf.py b/Examples/Scripts/Optimization/ckf.py index 0077f35317b..7de27b98465 100755 --- a/Examples/Scripts/Optimization/ckf.py +++ b/Examples/Scripts/Optimization/ckf.py @@ -259,7 +259,9 @@ def runCKFTracks( srcdir = Path(__file__).resolve().parent.parent.parent.parent - detector, trackingGeometry, decorators = GenericDetector.create() + detector = GenericDetector() + trackingGeometry = detector.trackingGeometry() + decorators = detector.contextDecorators() field = acts.ConstantBField(acts.Vector3(0, 0, 2 * u.T)) diff --git a/Examples/Scripts/Python/Auto-tuning/Orion/material_mapping_optimisation.py b/Examples/Scripts/Python/Auto-tuning/Orion/material_mapping_optimisation.py index 821320a33a2..d64c7056d7c 100755 --- a/Examples/Scripts/Python/Auto-tuning/Orion/material_mapping_optimisation.py +++ b/Examples/Scripts/Python/Auto-tuning/Orion/material_mapping_optimisation.py @@ -167,7 +167,8 @@ def runMaterialMappingVariance( matDeco = acts.IMaterialDecorator.fromFile( str(os.path.join(inputPath, "geometry-map.json")) ) - detectorTemp, trackingGeometryTemp, decoratorsTemp = getOpenDataDetector(matDeco) + detectorTemp = getOpenDataDetector(matDeco) + trackingGeometryTemp = detectorTemp.trackingGeometry() matMapDeco = acts.MappingMaterialDecorator( tGeometry=trackingGeometryTemp, level=acts.logging.ERROR ) @@ -175,7 +176,9 @@ def runMaterialMappingVariance( matMapDeco.setBinningMap(binMap) # Decorate the detector with the MappingMaterialDecorator - detector, trackingGeometry, decorators = getOpenDataDetector(matMapDeco) + detector = getOpenDataDetector(matMapDeco) + trackingGeometry = detector.trackingGeometry() + decorators = detector.contextDecorators() # Sequence for the mapping, only use one thread when mapping material sMap = acts.examples.Sequencer( @@ -207,7 +210,9 @@ def runMaterialMappingVariance( # Use the material map from the previous mapping as an input cborMap = os.path.join(pathExp, (mapName + ".cbor")) matDecoVar = acts.IMaterialDecorator.fromFile(cborMap) - detectorVar, trackingGeometryVar, decoratorsVar = getOpenDataDetector(matDecoVar) + detectorVar = getOpenDataDetector(matDecoVar) + trackingGeometryVar = detectorVar.trackingGeometry() + decoratorsVar = detectorVar.contextDecorators() s = acts.examples.Sequencer(events=events, numThreads=1, logLevel=acts.logging.INFO) for decorator in decoratorsVar: s.addContextDecorator(decorator) @@ -463,7 +468,9 @@ def surfaceExperiment(key, nbJobs, pathDB, pathResult, pipeBin, pipeResult, doPl matDeco = acts.IMaterialDecorator.fromFile( str(os.path.join(args.inputPath, "geometry-map.json")) ) - detector, trackingGeometry, decorators = getOpenDataDetector(matDeco) + detector = getOpenDataDetector(matDeco) + trackingGeometry = detector.trackingGeometry() + decorators = detector.contextDecorators() # Use the MappingMaterialDecorator to create a binning map that can be optimised matMapDeco = acts.MappingMaterialDecorator( diff --git a/Examples/Scripts/Python/ckf_tracks.py b/Examples/Scripts/Python/ckf_tracks.py index 15a50466799..1ef32c844ee 100755 --- a/Examples/Scripts/Python/ckf_tracks.py +++ b/Examples/Scripts/Python/ckf_tracks.py @@ -179,7 +179,9 @@ def runCKFTracks( if "__main__" == __name__: srcdir = Path(__file__).resolve().parent.parent.parent.parent - detector, trackingGeometry, decorators = GenericDetector.create() + detector = GenericDetector() + trackingGeometry = detector.trackingGeometry() + decorators = detector.contextDecorators() field = acts.ConstantBField(acts.Vector3(0, 0, 2 * u.T)) diff --git a/Examples/Scripts/Python/digitization.py b/Examples/Scripts/Python/digitization.py index a69a8f01c45..3e2479983af 100755 --- a/Examples/Scripts/Python/digitization.py +++ b/Examples/Scripts/Python/digitization.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 + from pathlib import Path from typing import Optional @@ -75,7 +76,8 @@ def runDigitization( if "__main__" == __name__: - detector, trackingGeometry, _ = acts.examples.GenericDetector.create() + detector = acts.examples.GenericDetector() + trackingGeometry = detector.trackingGeometry() digiConfigFile = ( Path(__file__).resolve().parent.parent.parent.parent diff --git a/Examples/Scripts/Python/digitization_config.py b/Examples/Scripts/Python/digitization_config.py index 1b6de07f477..13e41dc1898 100755 --- a/Examples/Scripts/Python/digitization_config.py +++ b/Examples/Scripts/Python/digitization_config.py @@ -33,7 +33,8 @@ def runDigitizationConfig( if "__main__" == __name__: - detector, trackingGeometry, _ = GenericDetector.create() + detector = GenericDetector() + trackingGeometry = detector.trackingGeometry() runDigitizationConfig( trackingGeometry=trackingGeometry, diff --git a/Examples/Scripts/Python/event_recording.py b/Examples/Scripts/Python/event_recording.py index 04cbb135dbe..8c31799c768 100755 --- a/Examples/Scripts/Python/event_recording.py +++ b/Examples/Scripts/Python/event_recording.py @@ -7,7 +7,6 @@ import acts.examples.hepmc3 import acts.examples.dd4hep import acts.examples.geant4 -import acts.examples.geant4.dd4hep import acts.examples.geant4.hepmc3 from acts.examples.odd import getOpenDataDetector @@ -15,7 +14,7 @@ u = acts.UnitConstants -def runEventRecording(detectorConstructionFactory, outputDir, s=None): +def runEventRecording(detector, outputDir, s=None): hepmc_dir = os.path.join(outputDir, "hepmc3") if not os.path.exists(hepmc_dir): os.mkdir(hepmc_dir) @@ -54,7 +53,7 @@ def runEventRecording(detectorConstructionFactory, outputDir, s=None): outputHepMcTracks="geant-event", seed1=43, seed2=44, - detectorConstructionFactory=detectorConstructionFactory, + detector=detector, ) erAlg = acts.examples.geant4.hepmc3.EventRecording( @@ -76,13 +75,9 @@ def runEventRecording(detectorConstructionFactory, outputDir, s=None): if "__main__" == __name__: - detector, trackingGeometry, decorators = getOpenDataDetector() - - detectorConstructionFactory = ( - acts.examples.geant4.dd4hep.DDG4DetectorConstructionFactory(detector) - ) + detector = getOpenDataDetector() runEventRecording( - detectorConstructionFactory=detectorConstructionFactory, + detector=detector, outputDir=os.getcwd(), ).run() diff --git a/Examples/Scripts/Python/exatrkx.py b/Examples/Scripts/Python/exatrkx.py index 5a8920a318a..77cb9b1a785 100755 --- a/Examples/Scripts/Python/exatrkx.py +++ b/Examples/Scripts/Python/exatrkx.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 + from pathlib import Path import os import sys @@ -55,7 +56,8 @@ def runGNNTrackFinding( if "torch" in sys.argv: backend = ExaTrkXBackend.Torch - detector, trackingGeometry, decorators = acts.examples.GenericDetector.create() + detector = acts.examples.GenericDetector() + trackingGeometry = detector.trackingGeometry() field = acts.ConstantBField(acts.Vector3(0, 0, 2 * u.T)) diff --git a/Examples/Scripts/Python/fatras.py b/Examples/Scripts/Python/fatras.py index 58fb8b5f565..9a28ed8eed2 100755 --- a/Examples/Scripts/Python/fatras.py +++ b/Examples/Scripts/Python/fatras.py @@ -31,8 +31,8 @@ def runFatras(trackingGeometry, field, outputDir, s: acts.examples.Sequencer = N if "__main__" == __name__: gdc = acts.examples.GenericDetector.Config() - detector = acts.examples.GenericDetector() - trackingGeometry, contextDecorators = detector.finalize(gdc, None) + gd = acts.examples.GenericDetector(gdc) + trackingGeometry, decorators, _ = gd.trackingGeometry() field = acts.ConstantBField(acts.Vector3(0, 0, 2 * u.T)) diff --git a/Examples/Scripts/Python/full_chain_odd.py b/Examples/Scripts/Python/full_chain_odd.py index 50a13219afa..3b7261c47dd 100755 --- a/Examples/Scripts/Python/full_chain_odd.py +++ b/Examples/Scripts/Python/full_chain_odd.py @@ -168,9 +168,9 @@ oddSeedingSel = geoDir / "config/odd-seeding-config.json" oddMaterialDeco = acts.IMaterialDecorator.fromFile(oddMaterialMap) -detector, trackingGeometry, decorators = getOpenDataDetector( - odd_dir=geoDir, mdecorator=oddMaterialDeco -) +detector = getOpenDataDetector(odd_dir=geoDir, mdecorator=oddMaterialDeco) +trackingGeometry = detector.trackingGeometry() +decorators = detector.contextDecorators() field = acts.ConstantBField(acts.Vector3(0.0, 0.0, 2.0 * u.T)) rnd = acts.examples.RandomNumbers(seed=42) diff --git a/Examples/Scripts/Python/full_chain_odd_LRT.py b/Examples/Scripts/Python/full_chain_odd_LRT.py index 57f7ce85876..36a552af0c8 100644 --- a/Examples/Scripts/Python/full_chain_odd_LRT.py +++ b/Examples/Scripts/Python/full_chain_odd_LRT.py @@ -160,9 +160,9 @@ oddSeedingSel = geoDir / "config/odd-seeding-config.json" oddMaterialDeco = acts.IMaterialDecorator.fromFile(oddMaterialMap) -detector, trackingGeometry, decorators = getOpenDataDetector( - odd_dir=geoDir, mdecorator=oddMaterialDeco -) +detector = getOpenDataDetector(odd_dir=geoDir, mdecorator=oddMaterialDeco) +trackingGeometry = detector.trackingGeometry() +decorators = detector.contextDecorators() field = acts.ConstantBField(acts.Vector3(0.0, 0.0, 2.0 * u.T)) rnd = acts.examples.RandomNumbers(seed=42) diff --git a/Examples/Scripts/Python/full_chain_test.py b/Examples/Scripts/Python/full_chain_test.py index 49d7dacfeed..e7c945094f6 100755 --- a/Examples/Scripts/Python/full_chain_test.py +++ b/Examples/Scripts/Python/full_chain_test.py @@ -285,7 +285,9 @@ def full_chain(args): args.digi_config = geo_dir / "Examples/Algorithms/Digitization/share/default-smearing-config-generic.json" seedingConfigFile = geo_dir / "Examples/Algorithms/TrackFinding/share/geoSelection-genericDetector.json" args.bf_constant = True - detector, trackingGeometry, decorators = acts.examples.GenericDetector.create() + detector = acts.examples.GenericDetector() + trackingGeometry = detector.trackingGeometry() + decorators = detector.contextDecorators() elif args.odd: import acts.examples.odd etaRange = (-3.0, 3.0) @@ -301,10 +303,12 @@ def full_chain(args): if args.material_config is None: args.material_config = geo_dir / "data/odd-material-maps.root" args.bf_constant = True - detector, trackingGeometry, decorators = acts.examples.odd.getOpenDataDetector( + detector = getOpenDataDetector( odd_dir=geo_dir, mdecorator=acts.IMaterialDecorator.fromFile(args.material_config), ) + trackingGeometry = detector.trackingGeometry() + decorators = detector.contextDecorators() elif args.itk: import acts.examples.itk as itk etaRange = (-4.0, 4.0) diff --git a/Examples/Scripts/Python/geant4.py b/Examples/Scripts/Python/geant4.py index 65e154c2704..49a41cc32fd 100755 --- a/Examples/Scripts/Python/geant4.py +++ b/Examples/Scripts/Python/geant4.py @@ -81,5 +81,7 @@ def runGeant4( [detector, contextors, store] = dd4hepDetector.finalize(geoContext, cOptions) runGeant4(detector, detector, field, Path.cwd()).run() else: - detector, trackingGeometry, decorators = getOpenDataDetector() + detector = getOpenDataDetector() + trackingGeometry = detector.trackingGeometry() + decorators = detector.contextDecorators() runGeant4(detector, trackingGeometry, field, Path.cwd()).run() diff --git a/Examples/Scripts/Python/geant4_parallel.py b/Examples/Scripts/Python/geant4_parallel.py index d9a8f59f8c2..7f39fc18ec8 100755 --- a/Examples/Scripts/Python/geant4_parallel.py +++ b/Examples/Scripts/Python/geant4_parallel.py @@ -61,7 +61,9 @@ def runGeant4EventRange(detector, trackingGeometry, beginEvent, endEvent, output if "__main__" == __name__: from acts.examples.odd import getOpenDataDetector - detector, trackingGeometry, decorators = getOpenDataDetector() + detector = getOpenDataDetector() + trackingGeometry = detector.trackingGeometry() + decorators = detector.contextDecorators() n_events = 100 n_jobs = 8 diff --git a/Examples/Scripts/Python/geometry.py b/Examples/Scripts/Python/geometry.py index 396fec3151a..e3a9f14b99a 100755 --- a/Examples/Scripts/Python/geometry.py +++ b/Examples/Scripts/Python/geometry.py @@ -7,8 +7,6 @@ from acts import MaterialMapJsonConverter from acts.examples.odd import getOpenDataDetector from acts.examples import ( - GenericDetector, - AlignedDetector, WhiteBoard, AlgorithmContext, ProcessCode, @@ -90,9 +88,11 @@ def runGeometry( if "__main__" == __name__: - # detector, trackingGeometry, decorators = AlignedDetector.create() - # detector, trackingGeometry, decorators = GenericDetector.create() - detector, trackingGeometry, decorators = getOpenDataDetector() + # detector = AlignedDetector() + # detector = GenericDetector() + detector = getOpenDataDetector() + trackingGeometry = detector.trackingGeometry() + decorators = detector.contextDecorators() runGeometry(trackingGeometry, decorators, outputDir=os.getcwd()) diff --git a/Examples/Scripts/Python/hashing_seeding.py b/Examples/Scripts/Python/hashing_seeding.py index 10f68b5cea9..b13ee204604 100755 --- a/Examples/Scripts/Python/hashing_seeding.py +++ b/Examples/Scripts/Python/hashing_seeding.py @@ -125,9 +125,8 @@ def getDetectorInfo(self): oddSeedingSel = geoDir / "config/odd-seeding-config.json" oddMaterialDeco = acts.IMaterialDecorator.fromFile(oddMaterialMap) - detector, trackingGeometry, decorators = getOpenDataDetector( - odd_dir=geoDir, mdecorator=oddMaterialDeco - ) + detector = getOpenDataDetector(odd_dir=geoDir, mdecorator=oddMaterialDeco) + trackingGeometry = detector.trackingGeometry() digiConfig = oddDigiConfig @@ -136,7 +135,8 @@ def getDetectorInfo(self): elif self.detector == DetectorName.generic: print("Create detector and tracking geometry") - detector, trackingGeometry, a = acts.examples.GenericDetector.create() + detector = acts.examples.GenericDetector() + trackingGeometry = detector.trackingGeometry() digiConfig = ( actsExamplesDir / "Algorithms/Digitization/share/default-smearing-config-generic.json" diff --git a/Examples/Scripts/Python/material_mapping.py b/Examples/Scripts/Python/material_mapping.py index 775115cf61b..559c3b7a663 100755 --- a/Examples/Scripts/Python/material_mapping.py +++ b/Examples/Scripts/Python/material_mapping.py @@ -155,7 +155,9 @@ def runMaterialMapping( mapName = args.outFile.split(".")[0] - detector, trackingGeometry, decorators = getOpenDataDetector(None) + detector = getOpenDataDetector(None) + trackingGeometry = detector.trackingGeometry() + decorators = detector.contextDecorators() runMaterialMapping( trackingGeometry, diff --git a/Examples/Scripts/Python/material_mapping_core.py b/Examples/Scripts/Python/material_mapping_core.py index 0bd9a7415de..e5a6e865246 100644 --- a/Examples/Scripts/Python/material_mapping_core.py +++ b/Examples/Scripts/Python/material_mapping_core.py @@ -300,7 +300,8 @@ def runMaterialMapping(surfaces, inputFile, outputFile, outputMap, loglevel): if args.matconfig != "": matDeco = acts.IMaterialDecorator.fromFile(args.matconfig) - [detector, trackingGeometry, decorators] = getOpenDataDetector(matDeco) + detector = getOpenDataDetector(matDeco) + trackingGeometry = detector.trackingGeometry() materialSurfaces = trackingGeometry.extractMaterialSurfaces() diff --git a/Examples/Scripts/Python/material_recording.py b/Examples/Scripts/Python/material_recording.py index 9de5914d45a..fe4ff238ca5 100755 --- a/Examples/Scripts/Python/material_recording.py +++ b/Examples/Scripts/Python/material_recording.py @@ -15,7 +15,6 @@ import acts.examples.dd4hep import acts.examples.geant4 -import acts.examples.geant4.dd4hep from acts.examples.odd import getOpenDataDetector try: @@ -30,7 +29,7 @@ def runMaterialRecording( - detectorConstructionFactory, + detector, outputDir, tracksPerEvent=10000, s=None, @@ -73,7 +72,7 @@ def runMaterialRecording( g4Alg = acts.examples.geant4.Geant4MaterialRecording( level=acts.logging.INFO, - detectorConstructionFactory=detectorConstructionFactory, + detector=detector, randomNumbers=rnd, inputParticles=evGen.config.outputParticles, outputMaterialTracks="material-tracks", @@ -108,27 +107,16 @@ def main(): args = p.parse_args() - detectorConstructionFactory = None + detector = None if args.input == "": - detector, trackingGeometry, decorators = getOpenDataDetector() - - detectorConstructionFactory = ( - acts.examples.geant4.dd4hep.DDG4DetectorConstructionFactory(detector) - ) + detector = getOpenDataDetector() elif args.input.endswith(".gdml"): - detectorConstructionFactory = ( - acts.examples.geant4.GdmlDetectorConstructionFactory(args.input) - ) + detector = acts.examples.geant4.GdmlDetector(path=args.input) elif args.input.endswith(".sqlite") or args.input.endswith(".db"): - geoModelTree = acts.geomodel.readFromDb(args.input) - detectorConstructionFactory = ( - acts.examples.geant4.geomodel.GeoModelDetectorConstructionFactory( - geoModelTree - ) - ) + detector = acts.examples.GeoModelDetector(path=args.input) runMaterialRecording( - detectorConstructionFactory=detectorConstructionFactory, + detector=detector, tracksPerEvent=args.tracks, outputDir=os.getcwd(), s=acts.examples.Sequencer(events=args.events, numThreads=1), diff --git a/Examples/Scripts/Python/material_validation.py b/Examples/Scripts/Python/material_validation.py index 94c0f21b94a..a516262d2d4 100755 --- a/Examples/Scripts/Python/material_validation.py +++ b/Examples/Scripts/Python/material_validation.py @@ -97,9 +97,9 @@ def runMaterialValidation( acts.IMaterialDecorator.fromFile(args.map) if args.map != None else None ) - detector, trackingGeometry, decorators = getOpenDataDetector( - mdecorator=materialDecorator - ) + detector = getOpenDataDetector(materialDecorator) + trackingGeometry = detector.trackingGeometry() + decorators = detector.contextDecorators() field = acts.ConstantBField(acts.Vector3(0, 0, 0 * acts.UnitConstants.T)) diff --git a/Examples/Scripts/Python/material_validation_core.py b/Examples/Scripts/Python/material_validation_core.py index 7e2ae129dcf..1d81054c091 100644 --- a/Examples/Scripts/Python/material_validation_core.py +++ b/Examples/Scripts/Python/material_validation_core.py @@ -244,9 +244,8 @@ def runMaterialValidation(s, ntracks, surfaces, outputFile, seed, loglevel): materialSurfaces = detector.extractMaterialSurfaces() else: - [detector, trackingGeometry, decorators] = getOpenDataDetector( - materialDecorator - ) + detector = getOpenDataDetector(materialDecorator) + trackingGeometry = detector.trackingGeometry() materialSurfaces = trackingGeometry.extractMaterialSurfaces() diff --git a/Examples/Scripts/Python/propagation.py b/Examples/Scripts/Python/propagation.py index 59be3385ca0..72401d8113e 100755 --- a/Examples/Scripts/Python/propagation.py +++ b/Examples/Scripts/Python/propagation.py @@ -72,14 +72,10 @@ def runPropagation(trackingGeometry, field, outputDir, s=None, decorators=[]): # matDeco = acts.IMaterialDecorator.fromFile("material.root") ## Generic detector: Default - ( - detector, - trackingGeometry, - contextDecorators, - ) = GenericDetector.create(mdecorator=matDeco) + detector = GenericDetector(mdecorator=matDeco) ## Alternative: Aligned detector in a couple of modes - # detector, trackingGeometry, contextDecorators = AlignedDetector.create( + # detector = AlignedDetector( # decoratorLogLevel=acts.logging.INFO, # # These parameters need to be tuned so that GC doesn't break # # with multiple threads @@ -94,8 +90,10 @@ def runPropagation(trackingGeometry, field, outputDir, s=None, decorators=[]): ## Alternative: DD4hep detector # dd4hepCfg = acts.examples.DD4hepDetector.Config() # dd4hepCfg.xmlFileNames = [str(getOpenDataDetectorDirectory()/"xml/OpenDataDetector.xml")] - # detector = acts.examples.DD4hepDetector() - # trackingGeometry, contextDecorators = detector.finalize(dd4hepCfg, None) + # detector = acts.examples.DD4hepDetector(dd4hepCfg) + + trackingGeometry = detector.trackingGeometry() + contextDecorators = detector.contextDecorators() ## Magnetic field setup: Default: constant 2T longitudinal field field = acts.ConstantBField(acts.Vector3(0, 0, 2 * acts.UnitConstants.T)) diff --git a/Examples/Scripts/Python/seeding.py b/Examples/Scripts/Python/seeding.py index 1e5b9e50d6b..ce1914accc7 100755 --- a/Examples/Scripts/Python/seeding.py +++ b/Examples/Scripts/Python/seeding.py @@ -152,8 +152,9 @@ def runSeeding( ) args = p.parse_args() - # detector, trackingGeometry, decorators = getOpenDataDetector() - detector, trackingGeometry, decorators = acts.examples.GenericDetector.create() + # detector = getOpenDataDetector() + detector = acts.examples.GenericDetector() + trackingGeometry = detector.trackingGeometry() field = acts.ConstantBField(acts.Vector3(0, 0, 2 * u.T)) diff --git a/Examples/Scripts/Python/telescope_simulation.py b/Examples/Scripts/Python/telescope_simulation.py index e47c7969232..97e6214c893 100755 --- a/Examples/Scripts/Python/telescope_simulation.py +++ b/Examples/Scripts/Python/telescope_simulation.py @@ -16,12 +16,13 @@ u = acts.UnitConstants if "__main__" == __name__: - detector, trackingGeometry, decorators = acts.examples.TelescopeDetector.create( + detector = acts.examples.TelescopeDetector( bounds=[200, 200], positions=[30, 60, 90, 120, 150, 180, 210, 240, 270], stereos=[0, 0, 0, 0, 0, 0, 0, 0, 0], binValue=2, ) + trackingGeometry = detector.trackingGeometry() field = acts.ConstantBField(acts.Vector3(0, 0, 2 * u.T)) diff --git a/Examples/Scripts/Python/telescope_track_params_lookup_generation.py b/Examples/Scripts/Python/telescope_track_params_lookup_generation.py index ecdffc20ec3..4f3eada72b1 100644 --- a/Examples/Scripts/Python/telescope_track_params_lookup_generation.py +++ b/Examples/Scripts/Python/telescope_track_params_lookup_generation.py @@ -99,13 +99,14 @@ def estimateLookup(trackingGeometry, numEvents, outputPath): args = p.parse_args() # Initialize the geometry - detector, trackingGeometry, decorators = acts.examples.TelescopeDetector.create( + detector = acts.examples.TelescopeDetector( bounds=[4, 10], positions=[30, 60, 90], stereos=[0, 0, 0], binValue=2, surfaceType=0, ) + trackingGeometry = detector.trackingGeometry() # Estimate the lookup estimateLookup(trackingGeometry, args.events, args.output) diff --git a/Examples/Scripts/Python/truth_tracking_gsf.py b/Examples/Scripts/Python/truth_tracking_gsf.py index 4f194a65662..7d6e05c07c7 100755 --- a/Examples/Scripts/Python/truth_tracking_gsf.py +++ b/Examples/Scripts/Python/truth_tracking_gsf.py @@ -163,13 +163,15 @@ def runTruthTrackingGsf( # ODD from acts.examples.odd import getOpenDataDetector - detector, trackingGeometry, decorators = getOpenDataDetector() + detector = getOpenDataDetector() + trackingGeometry = detector.trackingGeometry() digiConfigFile = ( srcdir / "thirdparty/OpenDataDetector/config/odd-digi-smearing-config.json" ) ## GenericDetector - # detector, trackingGeometry, _ = acts.examples.GenericDetector.create() + # detector = acts.examples.GenericDetector() + # trackingGeometry = detector.trackingGeometry() # digiConfigFile = ( # srcdir # / "Examples/Algorithms/Digitization/share/default-smearing-config-generic.json" diff --git a/Examples/Scripts/Python/truth_tracking_gsf_refitting.py b/Examples/Scripts/Python/truth_tracking_gsf_refitting.py index 686f4af06c2..79bd5c41b50 100755 --- a/Examples/Scripts/Python/truth_tracking_gsf_refitting.py +++ b/Examples/Scripts/Python/truth_tracking_gsf_refitting.py @@ -102,13 +102,15 @@ def runRefittingGsf( # ODD from acts.examples.odd import getOpenDataDetector - detector, trackingGeometry, decorators = getOpenDataDetector() + detector = getOpenDataDetector() + trackingGeometry = detector.trackingGeometry() digiConfigFile = ( srcdir / "thirdparty/OpenDataDetector/config/odd-digi-smearing-config.json" ) ## GenericDetector - # detector, trackingGeometry, _ = acts.examples.GenericDetector.create() + # detector = acts.examples.GenericDetector() + # trackingGeometry = detector.trackingGeometry() # digiConfigFile = ( # srcdir # / "Examples/Algorithms/Digitization/share/default-smearing-config-generic.json" diff --git a/Examples/Scripts/Python/truth_tracking_gx2f.py b/Examples/Scripts/Python/truth_tracking_gx2f.py index 31ebb447d42..2c692ca87cc 100644 --- a/Examples/Scripts/Python/truth_tracking_gx2f.py +++ b/Examples/Scripts/Python/truth_tracking_gx2f.py @@ -163,13 +163,15 @@ def runTruthTrackingGx2f( # ODD from acts.examples.odd import getOpenDataDetector - detector, trackingGeometry, decorators = getOpenDataDetector() + detector = getOpenDataDetector() + trackingGeometry = detector.trackingGeometry() digiConfigFile = ( srcdir / "thirdparty/OpenDataDetector/config/odd-digi-smearing-config.json" ) ## GenericDetector - # detector, trackingGeometry, _ = acts.examples.GenericDetector.create() + # detector = acts.examples.GenericDetector() + # trackingGeometry = detector.trackingGeometry() # digiConfigFile = ( # srcdir # / "Examples/Algorithms/Digitization/share/default-smearing-config-generic.json" diff --git a/Examples/Scripts/Python/truth_tracking_kalman.py b/Examples/Scripts/Python/truth_tracking_kalman.py index 3b857fd41da..0102f1db8ee 100755 --- a/Examples/Scripts/Python/truth_tracking_kalman.py +++ b/Examples/Scripts/Python/truth_tracking_kalman.py @@ -177,13 +177,15 @@ def runTruthTrackingKalman( # ODD from acts.examples.odd import getOpenDataDetector - detector, trackingGeometry, decorators = getOpenDataDetector() + detector = getOpenDataDetector() + trackingGeometry = detector.trackingGeometry() digiConfigFile = ( srcdir / "thirdparty/OpenDataDetector/config/odd-digi-smearing-config.json" ) ## GenericDetector - # detector, trackingGeometry, _ = acts.examples.GenericDetector.create() + # detector = acts.examples.GenericDetector() + # trackingGeometry = detector.trackingGeometry() # digiConfigFile = ( # srcdir # / "Examples/Algorithms/Digitization/share/default-smearing-config-generic.json" diff --git a/Examples/Scripts/Python/truth_tracking_kalman_refitting.py b/Examples/Scripts/Python/truth_tracking_kalman_refitting.py index 46578423f33..2d84808a15c 100755 --- a/Examples/Scripts/Python/truth_tracking_kalman_refitting.py +++ b/Examples/Scripts/Python/truth_tracking_kalman_refitting.py @@ -100,13 +100,16 @@ def runRefittingKf( # ODD from acts.examples.odd import getOpenDataDetector - detector, trackingGeometry, decorators = getOpenDataDetector() + detector = getOpenDataDetector() + trackingGeometry = detector.trackingGeometry() + decorators = detector.contextDecorators() digiConfigFile = ( srcdir / "thirdparty/OpenDataDetector/config/odd-digi-smearing-config.json" ) ## GenericDetector - # detector, trackingGeometry, _ = acts.examples.GenericDetector.create() + # detector = acts.examples.GenericDetector() + # trackingGeometry = detector.trackingGeometry() # digiConfigFile = ( # srcdir # / "Examples/Algorithms/Digitization/share/default-smearing-config-generic.json" diff --git a/Examples/Scripts/Python/truth_tracking_telescope.py b/Examples/Scripts/Python/truth_tracking_telescope.py index b179fb9afa7..503c05b0a19 100755 --- a/Examples/Scripts/Python/truth_tracking_telescope.py +++ b/Examples/Scripts/Python/truth_tracking_telescope.py @@ -10,11 +10,12 @@ u = acts.UnitConstants if "__main__" == __name__: - detector, trackingGeometry, decorators = acts.examples.TelescopeDetector.create( + detector = acts.examples.TelescopeDetector( bounds=[200, 200], positions=[30, 60, 90, 120, 150, 180, 210, 240, 270], stereos=[0] * 9, ) + trackingGeometry = detector.trackingGeometry() srcdir = Path(__file__).resolve().parent.parent.parent.parent diff --git a/Examples/Scripts/Python/vertex_fitting.py b/Examples/Scripts/Python/vertex_fitting.py index c6088f618a6..5add3b8f1c1 100755 --- a/Examples/Scripts/Python/vertex_fitting.py +++ b/Examples/Scripts/Python/vertex_fitting.py @@ -119,7 +119,8 @@ def runVertexFitting( if "__main__" == __name__: - detector, trackingGeometry, decorators = acts.examples.GenericDetector.create() + detector = acts.examples.GenericDetector() + trackingGeometry = detector.trackingGeometry() field = acts.ConstantBField(acts.Vector3(0, 0, 2 * u.T)) diff --git a/docs/examples/full_chain_odd.md b/docs/examples/full_chain_odd.md index 5589d9f18d8..24f7dd8ca52 100644 --- a/docs/examples/full_chain_odd.md +++ b/docs/examples/full_chain_odd.md @@ -12,9 +12,9 @@ oddDir = getOpenDataDetectorDirectory() oddMaterialMap = oddDir / "data/odd-material-maps.root" oddMaterialDeco = acts.IMaterialDecorator.fromFile(oddMaterialMap) -detector, trackingGeometry, decorators = getOpenDataDetector( - mdecorator=oddMaterialDeco, -) +detector = getOpenDataDetector(mdecorator=oddMaterialDeco) +trackingGeometry = detector.trackingGeometry() +decorators = detector.contextDecorators() ``` In our simple example we assume a homogeneous magnetic field along the beam axis with 2 T. The magnetic field is passed to all the different algorithms in our simulation and the reconstruction pipeline. diff --git a/docs/examples/howto/material_mapping.rst b/docs/examples/howto/material_mapping.rst index a8657a470a6..601d0b25ba9 100644 --- a/docs/examples/howto/material_mapping.rst +++ b/docs/examples/howto/material_mapping.rst @@ -55,7 +55,9 @@ For the following example we will be remapping the material of the ODD, we will .. code-block:: console - detector, trackingGeometry, decorators = getOpenDataDetector() + detector = getOpenDataDetector() + trackingGeometry = detector.trackingGeometry() + decorators = detector.contextDecorators() This algorithm is useful to obtain a visualisation of your detector using the different types of output available (``output-obj`` gives ``.obj`` with a 3D representation of the different subdetectors, for example). Here, we use ``output-json`` to obtain a map of all the surfaces and volumes in the detector with a ``ProtoSurfaceMaterial`` (or a ``ProtoVolumeMaterial``), ``mat-output-allmaterial`` ensure that a ``ProtoSurfaceMaterial`` (or a ``ProtoVolumeMaterial``) is associated to all the surfaces (or volumes), enforcing all of them to be written. Four types of surfaces exist: diff --git a/docs/examples/python_bindings.rst b/docs/examples/python_bindings.rst index fe0cd1dcb9f..69cead57aa7 100644 --- a/docs/examples/python_bindings.rst +++ b/docs/examples/python_bindings.rst @@ -22,7 +22,8 @@ sets up the particle propagation and runs a few events. import acts import acts.examples - detector, trackingGeometry, contextDecorators = acts.examples.GenericDetector.create() + detector = acts.examples.GenericDetector() + trackingGeometry = detector.trackingGeometry() s = acts.examples.Sequencer(events=10) rnd = acts.examples.RandomNumbers(seed=42) diff --git a/docs/getting_started.md b/docs/getting_started.md index aff8e38a3b0..03365dd9f40 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -375,7 +375,9 @@ You can now use the ODD in the python binding by using: ```python oddMaterialDeco = acts.IMaterialDecorator.fromFile("PATH_TO_Acts/thirdparty/OpenDataDetector/data/odd-material-maps.root") -detector, trackingGeometry, decorators = getOpenDataDetector(oddMaterialDeco) +detector = getOpenDataDetector(oddMaterialDeco) +trackingGeometry = detector.trackingGeometry() +decorators = detector.contextDecorators() ``` ## Using ACTS From 47db0b917b575cc1b956fff0dbc3b09f925ed3c5 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Mon, 9 Dec 2024 10:46:03 +0100 Subject: [PATCH 10/12] chore: Sonar fixes after detector refactor (#3968) Blocked by: - #3498 ## Summary by CodeRabbit - **New Features** - Enhanced safety in the `DD4hepDetector` class by using const references in loop iterations. - Updated sorting mechanism for several vectors to utilize modern C++ practices. - **Bug Fixes** - Adjusted data types in the `Config` struct of the `AlignedDetector` class for better performance and accuracy. - Removed obsolete member variable from the `Config` struct in the `AlignedDetector` class. Co-authored-by: Andreas Stefl <487211+andiwand@users.noreply.github.com> --- .../ActsExamples/Geant4/Geant4Simulation.hpp | 2 +- .../ContextualDetector/AlignedDetector.hpp | 10 ++--- .../DD4hepDetector/src/DD4hepDetector.cpp | 38 +++++++++---------- 3 files changed, 23 insertions(+), 27 deletions(-) diff --git a/Examples/Algorithms/Geant4/include/ActsExamples/Geant4/Geant4Simulation.hpp b/Examples/Algorithms/Geant4/include/ActsExamples/Geant4/Geant4Simulation.hpp index 089c1c2b3cd..df9dd637eca 100644 --- a/Examples/Algorithms/Geant4/include/ActsExamples/Geant4/Geant4Simulation.hpp +++ b/Examples/Algorithms/Geant4/include/ActsExamples/Geant4/Geant4Simulation.hpp @@ -208,7 +208,7 @@ class Geant4MaterialRecording final : public Geant4SimulationBase { /// Algorithm execute method, called once per event with context /// /// @param ctx the AlgorithmContext for this event - ProcessCode execute(const ActsExamples::AlgorithmContext& ctx) const final; + ProcessCode execute(const ActsExamples::AlgorithmContext& ctx) const override; /// Readonly access to the configuration const Config& config() const final { return m_cfg; } diff --git a/Examples/Detectors/ContextualDetector/include/ActsExamples/ContextualDetector/AlignedDetector.hpp b/Examples/Detectors/ContextualDetector/include/ActsExamples/ContextualDetector/AlignedDetector.hpp index 0859c174e5a..7a184f16fc1 100644 --- a/Examples/Detectors/ContextualDetector/include/ActsExamples/ContextualDetector/AlignedDetector.hpp +++ b/Examples/Detectors/ContextualDetector/include/ActsExamples/ContextualDetector/AlignedDetector.hpp @@ -13,8 +13,6 @@ #include "ActsExamples/DetectorCommons/Detector.hpp" #include "ActsExamples/GenericDetector/GenericDetector.hpp" -#include - namespace ActsExamples { class InternallyAlignedDetectorElement; @@ -24,11 +22,11 @@ class AlignedDetector : public Detector { public: struct Config : public GenericDetector::Config { /// Seed for the decorator random numbers. - std::size_t seed = 1324354657; + unsigned int seed = 1324354657; /// Size of a valid IOV. - std::size_t iovSize = 100; + unsigned int iovSize = 100; /// Span until garbage collection is active. - std::size_t flushSize = 200; + unsigned int flushSize = 200; /// Run the garbage collection? bool doGarbageCollection = true; /// Sigma of the in-plane misalignment @@ -46,8 +44,6 @@ class AlignedDetector : public Detector { enum class Mode { Internal, External }; Mode mode = Mode::Internal; - - std::shared_ptr materialDecorator; }; explicit AlignedDetector(const Config& cfg); diff --git a/Examples/Detectors/DD4hepDetector/src/DD4hepDetector.cpp b/Examples/Detectors/DD4hepDetector/src/DD4hepDetector.cpp index a411a32a028..6ad70fa7d70 100644 --- a/Examples/Detectors/DD4hepDetector/src/DD4hepDetector.cpp +++ b/Examples/Detectors/DD4hepDetector/src/DD4hepDetector.cpp @@ -86,8 +86,8 @@ std::unique_ptr DD4hepDetector::buildDD4hepGeometry() const { std::unique_ptr detector = dd4hep::Detector::make_unique(m_cfg.name); - for (auto& file : m_cfg.xmlFileNames) { - detector->fromCompact(file.c_str()); + for (const auto& file : m_cfg.xmlFileNames) { + detector->fromCompact(file); } detector->volumeManager(); detector->apply("DD4hepVolumeManager", 0, nullptr); @@ -106,7 +106,7 @@ void ActsExamples::sortFCChhDetElements(std::vector& det) { std::vector eCal; std::vector hCal; std::vector muon; - for (auto& detElement : det) { + for (const auto& detElement : det) { std::string detName = detElement.name(); if (detName.find("Muon") != std::string::npos) { muon.push_back(detElement); @@ -118,22 +118,22 @@ void ActsExamples::sortFCChhDetElements(std::vector& det) { tracker.push_back(detElement); } } - sort(muon.begin(), muon.end(), - [](const dd4hep::DetElement& a, const dd4hep::DetElement& b) { - return (a.id() < b.id()); - }); - sort(eCal.begin(), eCal.end(), - [](const dd4hep::DetElement& a, const dd4hep::DetElement& b) { - return (a.id() < b.id()); - }); - sort(hCal.begin(), hCal.end(), - [](const dd4hep::DetElement& a, const dd4hep::DetElement& b) { - return (a.id() < b.id()); - }); - sort(tracker.begin(), tracker.end(), - [](const dd4hep::DetElement& a, const dd4hep::DetElement& b) { - return (a.id() < b.id()); - }); + std::ranges::sort( + muon, [](const dd4hep::DetElement& a, const dd4hep::DetElement& b) { + return (a.id() < b.id()); + }); + std::ranges::sort( + eCal, [](const dd4hep::DetElement& a, const dd4hep::DetElement& b) { + return (a.id() < b.id()); + }); + std::ranges::sort( + hCal, [](const dd4hep::DetElement& a, const dd4hep::DetElement& b) { + return (a.id() < b.id()); + }); + std::ranges::sort( + tracker, [](const dd4hep::DetElement& a, const dd4hep::DetElement& b) { + return (a.id() < b.id()); + }); det.clear(); det = tracker; From 0a11443eef9ff85e9a0b5f1a6b15f6f424eaef98 Mon Sep 17 00:00:00 2001 From: Andreas Stefl Date: Mon, 9 Dec 2024 12:31:07 +0100 Subject: [PATCH 11/12] chore: Clean event generator includes in Examples (#3964) --- .../Generators/ActsExamples/Generators/EventGenerator.cpp | 5 ----- .../Generators/ActsExamples/Generators/EventGenerator.hpp | 1 - .../ActsExamples/Generators/ParametricParticleGenerator.cpp | 1 - .../ActsExamples/Generators/Pythia8ProcessGenerator.cpp | 2 -- 4 files changed, 9 deletions(-) diff --git a/Examples/Algorithms/Generators/ActsExamples/Generators/EventGenerator.cpp b/Examples/Algorithms/Generators/ActsExamples/Generators/EventGenerator.cpp index 9d5c1b873d3..7c1b629430e 100644 --- a/Examples/Algorithms/Generators/ActsExamples/Generators/EventGenerator.cpp +++ b/Examples/Algorithms/Generators/ActsExamples/Generators/EventGenerator.cpp @@ -8,19 +8,14 @@ #include "ActsExamples/Generators/EventGenerator.hpp" -#include "Acts/Surfaces/PerigeeSurface.hpp" #include "ActsExamples/EventData/SimVertex.hpp" -#include "ActsExamples/EventData/Track.hpp" #include "ActsExamples/Framework/AlgorithmContext.hpp" #include "ActsFatras/EventData/Barcode.hpp" -#include "ActsFatras/EventData/Particle.hpp" #include #include -#include #include #include -#include namespace ActsExamples { diff --git a/Examples/Algorithms/Generators/ActsExamples/Generators/EventGenerator.hpp b/Examples/Algorithms/Generators/ActsExamples/Generators/EventGenerator.hpp index 7a76ac03d71..1690b203d2e 100644 --- a/Examples/Algorithms/Generators/ActsExamples/Generators/EventGenerator.hpp +++ b/Examples/Algorithms/Generators/ActsExamples/Generators/EventGenerator.hpp @@ -24,7 +24,6 @@ #include namespace ActsExamples { -struct AlgorithmContext; /// Event generator based on separate particles and vertex generators. /// diff --git a/Examples/Algorithms/Generators/ActsExamples/Generators/ParametricParticleGenerator.cpp b/Examples/Algorithms/Generators/ActsExamples/Generators/ParametricParticleGenerator.cpp index 00411fc64c3..9da5e1a6e1a 100644 --- a/Examples/Algorithms/Generators/ActsExamples/Generators/ParametricParticleGenerator.cpp +++ b/Examples/Algorithms/Generators/ActsExamples/Generators/ParametricParticleGenerator.cpp @@ -13,7 +13,6 @@ #include "Acts/Utilities/AngleHelpers.hpp" #include "ActsExamples/EventData/SimParticle.hpp" #include "ActsFatras/EventData/Barcode.hpp" -#include "ActsFatras/EventData/Particle.hpp" #include #include diff --git a/Examples/Algorithms/GeneratorsPythia8/ActsExamples/Generators/Pythia8ProcessGenerator.cpp b/Examples/Algorithms/GeneratorsPythia8/ActsExamples/Generators/Pythia8ProcessGenerator.cpp index 1b774a7bdf0..916addff0ae 100644 --- a/Examples/Algorithms/GeneratorsPythia8/ActsExamples/Generators/Pythia8ProcessGenerator.cpp +++ b/Examples/Algorithms/GeneratorsPythia8/ActsExamples/Generators/Pythia8ProcessGenerator.cpp @@ -11,10 +11,8 @@ #include "Acts/Utilities/MathHelpers.hpp" #include "ActsExamples/EventData/SimVertex.hpp" #include "ActsFatras/EventData/Barcode.hpp" -#include "ActsFatras/EventData/Particle.hpp" #include -#include #include #include #include From 94ae506310982400b4c8b0739a3fa6cec89c9527 Mon Sep 17 00:00:00 2001 From: Andreas Stefl Date: Mon, 9 Dec 2024 14:20:57 +0100 Subject: [PATCH 12/12] fix: Workaround Pythia8 race condition in ttbar physmon (#3965) Until https://github.com/acts-project/acts/issues/3963 is fixed we have to stick to single threaded processing with ttbar ## Summary by CodeRabbit - **Bug Fixes** - Adjusted threading configuration to single-threaded execution to enhance stability and prevent race conditions during simulations. --- CI/physmon/workflows/physmon_trackfinding_ttbar_pu200.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CI/physmon/workflows/physmon_trackfinding_ttbar_pu200.py b/CI/physmon/workflows/physmon_trackfinding_ttbar_pu200.py index de4021a5055..d26e5e78873 100755 --- a/CI/physmon/workflows/physmon_trackfinding_ttbar_pu200.py +++ b/CI/physmon/workflows/physmon_trackfinding_ttbar_pu200.py @@ -35,9 +35,10 @@ with tempfile.TemporaryDirectory() as temp: + # Running with a single thread to avoid rance conditions with Pythia8, see https://github.com/acts-project/acts/issues/3963 s = acts.examples.Sequencer( events=3, - numThreads=-1, + numThreads=1, # run with single thread logLevel=acts.logging.INFO, )