From b592b39a25eae36fa9a44e165135e50db955ef3c Mon Sep 17 00:00:00 2001 From: Andreas Stefl Date: Wed, 14 Aug 2024 14:45:55 +0200 Subject: [PATCH] fix: Ensure ODD cleanup if sequencer stops in Examples Python tests (#3471) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Looks like pytest will hold on to all the local variables in case a test fails. This becomes a problem if the ODD was constructed and will be constructed in a consecutive test as only one instance can be in flight 🙄 --- CI/physmon/workflows/physmon_simulation.py | 2 - .../workflows/physmon_trackfinding_1muon.py | 1 - .../physmon_trackfinding_4muon_50vertices.py | 1 - .../physmon_trackfinding_ttbar_pu200.py | 1 - .../workflows/physmon_trackfitting_gsf.py | 1 - .../workflows/physmon_trackfitting_gx2f.py | 1 - .../workflows/physmon_trackfitting_kf.py | 1 - .../Geant4/src/DDG4DetectorConstruction.cpp | 6 +- .../Detectors/DD4hepDetector/CMakeLists.txt | 7 +- .../DD4hepDetector/DD4hepDetector.hpp | 7 +- .../DD4hepDetector/DD4hepGeometryService.hpp | 10 +- .../DD4hepDetector/src/DD4hepDetector.cpp | 6 +- .../src/DD4hepGeometryService.cpp | 16 +- Examples/Python/python/acts/_adapter.py | 19 +- .../Python/python/acts/examples/dd4hep.py | 3 +- Examples/Python/python/acts/examples/odd.py | 21 +- Examples/Python/src/DD4hepComponent.cpp | 10 +- Examples/Python/src/Geant4DD4hepComponent.cpp | 1 - Examples/Python/tests/conftest.py | 33 +-- Examples/Python/tests/test_detectors.py | 7 +- Examples/Python/tests/test_examples.py | 265 +++++++++--------- Examples/Python/tests/test_propagation.py | 1 + Examples/Python/tests/test_reader.py | 59 ++-- Examples/Python/tests/test_writer.py | 1 - .../Orion/material_mapping_optimisation.py | 16 -- .../train_seed_solver.py | 5 - Examples/Scripts/Python/geant4.py | 6 +- Examples/Scripts/Python/geant4_parallel.py | 10 +- Examples/Scripts/Python/seeding.py | 4 +- Examples/Scripts/Python/truth_tracking_gsf.py | 2 +- .../Python/truth_tracking_gsf_refitting.py | 2 +- .../Scripts/Python/truth_tracking_gx2f.py | 2 +- .../Scripts/Python/truth_tracking_kalman.py | 2 +- 33 files changed, 264 insertions(+), 265 deletions(-) diff --git a/CI/physmon/workflows/physmon_simulation.py b/CI/physmon/workflows/physmon_simulation.py index e2f0a71ad38..c88d4a081e8 100755 --- a/CI/physmon/workflows/physmon_simulation.py +++ b/CI/physmon/workflows/physmon_simulation.py @@ -98,7 +98,6 @@ ) s.run() - del s for file, name in [ (tp / "fatras" / "particles_simulation.root", "particles_fatras.root"), @@ -134,7 +133,6 @@ ) s.run() - del s for file, name in [ (tp / "pythia8_particles.root", "particles_ttbar.root"), diff --git a/CI/physmon/workflows/physmon_trackfinding_1muon.py b/CI/physmon/workflows/physmon_trackfinding_1muon.py index 62bdbf97ee2..8dee557c794 100755 --- a/CI/physmon/workflows/physmon_trackfinding_1muon.py +++ b/CI/physmon/workflows/physmon_trackfinding_1muon.py @@ -150,7 +150,6 @@ def run_ckf_tracking(label, seeding): ) s.run() - del s for file in ( ["performance_seeding.root"] diff --git a/CI/physmon/workflows/physmon_trackfinding_4muon_50vertices.py b/CI/physmon/workflows/physmon_trackfinding_4muon_50vertices.py index da966a320e1..0efeec3acf2 100755 --- a/CI/physmon/workflows/physmon_trackfinding_4muon_50vertices.py +++ b/CI/physmon/workflows/physmon_trackfinding_4muon_50vertices.py @@ -187,7 +187,6 @@ ) s.run() - del s shutil.move( tp / "performance_ambi.root", diff --git a/CI/physmon/workflows/physmon_trackfinding_ttbar_pu200.py b/CI/physmon/workflows/physmon_trackfinding_ttbar_pu200.py index b855e313745..a9414a89351 100755 --- a/CI/physmon/workflows/physmon_trackfinding_ttbar_pu200.py +++ b/CI/physmon/workflows/physmon_trackfinding_ttbar_pu200.py @@ -167,7 +167,6 @@ ) s.run() - del s shutil.move( tp / "performance_ambi.root", diff --git a/CI/physmon/workflows/physmon_trackfitting_gsf.py b/CI/physmon/workflows/physmon_trackfitting_gsf.py index 34eb0b5a99a..694623e2926 100755 --- a/CI/physmon/workflows/physmon_trackfitting_gsf.py +++ b/CI/physmon/workflows/physmon_trackfitting_gsf.py @@ -28,7 +28,6 @@ ) s.run() - del s perf_file = tp / "performance_gsf.root" assert perf_file.exists(), "Performance file not found" diff --git a/CI/physmon/workflows/physmon_trackfitting_gx2f.py b/CI/physmon/workflows/physmon_trackfitting_gx2f.py index 2644e291757..58ff664e26e 100755 --- a/CI/physmon/workflows/physmon_trackfitting_gx2f.py +++ b/CI/physmon/workflows/physmon_trackfitting_gx2f.py @@ -28,7 +28,6 @@ ) s.run() - del s perf_file = tp / "performance_gx2f.root" assert perf_file.exists(), "Performance file not found" diff --git a/CI/physmon/workflows/physmon_trackfitting_kf.py b/CI/physmon/workflows/physmon_trackfitting_kf.py index 1bb09d1aa57..767c2ff5d69 100755 --- a/CI/physmon/workflows/physmon_trackfitting_kf.py +++ b/CI/physmon/workflows/physmon_trackfitting_kf.py @@ -28,7 +28,6 @@ ) s.run() - del s perf_file = tp / "performance_kf.root" assert perf_file.exists(), "Performance file not found" diff --git a/Examples/Algorithms/Geant4/src/DDG4DetectorConstruction.cpp b/Examples/Algorithms/Geant4/src/DDG4DetectorConstruction.cpp index 74fa7831646..a09314c919c 100644 --- a/Examples/Algorithms/Geant4/src/DDG4DetectorConstruction.cpp +++ b/Examples/Algorithms/Geant4/src/DDG4DetectorConstruction.cpp @@ -42,11 +42,11 @@ G4VPhysicalVolume* ActsExamples::DDG4DetectorConstruction::Construct() { dd4hep::sim::Geant4Mapping& g4map = dd4hep::sim::Geant4Mapping::instance(); auto conv = dd4hep::sim::Geant4Converter(dd4hepDetector(), dd4hep::PrintLevel::VERBOSE); - dd4hep::sim::Geant4GeometryInfo* geo_info = + dd4hep::sim::Geant4GeometryInfo* geoInfo = conv.create(dd4hepDetector().world()).detach(); - g4map.attach(geo_info); + g4map.attach(geoInfo); // All volumes are deleted in ~G4PhysicalVolumeStore() - m_world = geo_info->world(); + m_world = geoInfo->world(); // Create Geant4 volume manager g4map.volumeManager(); diff --git a/Examples/Detectors/DD4hepDetector/CMakeLists.txt b/Examples/Detectors/DD4hepDetector/CMakeLists.txt index 88192fdbd4e..1a335363871 100644 --- a/Examples/Detectors/DD4hepDetector/CMakeLists.txt +++ b/Examples/Detectors/DD4hepDetector/CMakeLists.txt @@ -3,16 +3,15 @@ add_library( src/DD4hepDetector.cpp src/DD4hepGeometryService.cpp) - target_include_directories( ActsExamplesDetectorDD4hep PUBLIC $) target_link_libraries( ActsExamplesDetectorDD4hep PUBLIC - ActsCore ActsPluginDD4hep - ActsExamplesFramework - ROOT::Geom ROOT::GenVector) + ActsCore + ActsPluginDD4hep + ActsExamplesFramework) if(${DD4hep_VERSION} VERSION_LESS 1.11) target_include_directories(ActsExamplesDetectorDD4hep PUBLIC ${DD4hep_INCLUDE_DIRS}) diff --git a/Examples/Detectors/DD4hepDetector/include/ActsExamples/DD4hepDetector/DD4hepDetector.hpp b/Examples/Detectors/DD4hepDetector/include/ActsExamples/DD4hepDetector/DD4hepDetector.hpp index bda365d6df9..899df36fad9 100644 --- a/Examples/Detectors/DD4hepDetector/include/ActsExamples/DD4hepDetector/DD4hepDetector.hpp +++ b/Examples/Detectors/DD4hepDetector/include/ActsExamples/DD4hepDetector/DD4hepDetector.hpp @@ -1,6 +1,6 @@ // This file is part of the Acts project. // -// Copyright (C) 2018-2019 CERN for the benefit of the Acts project +// Copyright (C) 2018-2024 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 @@ -59,9 +59,6 @@ struct DD4hepDetector { /// @brief The DD4hep geometry service std::shared_ptr geometryService = nullptr; - // @brief the compact file names - std::vector compactFiles = {}; - /// @brief Build the tracking geometry from the DD4hep geometry /// /// @param config is the configuration of the geometry service @@ -87,6 +84,8 @@ struct DD4hepDetector { 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; diff --git a/Examples/Detectors/DD4hepDetector/include/ActsExamples/DD4hepDetector/DD4hepGeometryService.hpp b/Examples/Detectors/DD4hepDetector/include/ActsExamples/DD4hepDetector/DD4hepGeometryService.hpp index 25415977e2f..cfef3becff0 100644 --- a/Examples/Detectors/DD4hepDetector/include/ActsExamples/DD4hepDetector/DD4hepGeometryService.hpp +++ b/Examples/Detectors/DD4hepDetector/include/ActsExamples/DD4hepDetector/DD4hepGeometryService.hpp @@ -1,6 +1,6 @@ // This file is part of the Acts project. // -// Copyright (C) 2017 CERN for the benefit of the Acts project +// Copyright (C) 2017-2024 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 @@ -56,7 +56,7 @@ class DD4hepGeometryService { /// XML-file with the detector description std::vector xmlFileNames; /// The name of the service - std::string name; + std::string name = "default"; /// Binningtype in phi Acts::BinningType bTypePhi = Acts::equidistant; /// Binningtype in r @@ -88,7 +88,11 @@ class DD4hepGeometryService { }; 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(); @@ -107,6 +111,8 @@ class DD4hepGeometryService { std::shared_ptr trackingGeometry( const Acts::GeometryContext& gctx); + void drop(); + private: /// Private method to initiate building of the DD4hep geometry ActsExamples::ProcessCode buildDD4hepGeometry(); diff --git a/Examples/Detectors/DD4hepDetector/src/DD4hepDetector.cpp b/Examples/Detectors/DD4hepDetector/src/DD4hepDetector.cpp index 919ff0668bc..e3b607d5fc5 100644 --- a/Examples/Detectors/DD4hepDetector/src/DD4hepDetector.cpp +++ b/Examples/Detectors/DD4hepDetector/src/DD4hepDetector.cpp @@ -1,6 +1,6 @@ // This file is part of the Acts project. // -// Copyright (C) 2019 CERN for the benefit of the Acts project +// Copyright (C) 2019-2024 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 @@ -75,6 +75,10 @@ auto DD4hepDetector::finalize( return {detector, contextDecorators, detectorElements}; } +void DD4hepDetector::drop() { + geometryService->drop(); +} + std::shared_ptr DD4hepDetector::field() const { const auto& detector = geometryService->detector(); diff --git a/Examples/Detectors/DD4hepDetector/src/DD4hepGeometryService.cpp b/Examples/Detectors/DD4hepDetector/src/DD4hepGeometryService.cpp index da57423a65f..780fbca385a 100644 --- a/Examples/Detectors/DD4hepDetector/src/DD4hepGeometryService.cpp +++ b/Examples/Detectors/DD4hepDetector/src/DD4hepGeometryService.cpp @@ -1,6 +1,6 @@ // This file is part of the Acts project. // -// Copyright (C) 2017 CERN for the benefit of the Acts project +// Copyright (C) 2017-2024 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 @@ -35,9 +35,7 @@ ActsExamples::DD4hep::DD4hepGeometryService::DD4hepGeometryService( } ActsExamples::DD4hep::DD4hepGeometryService::~DD4hepGeometryService() { - if (m_detector != nullptr) { - m_detector->destroyInstance(); - } + drop(); } ActsExamples::ProcessCode @@ -133,6 +131,16 @@ ActsExamples::DD4hep::DD4hepGeometryService::trackingGeometry( return m_trackingGeometry; } +void ActsExamples::DD4hep::DD4hepGeometryService::drop() { + if (m_detector == nullptr) { + return; + } + dd4hep::Detector::destroyInstance(m_cfg.name); + m_detector = nullptr; + m_geometry = dd4hep::DetElement(); + m_trackingGeometry = nullptr; +} + void ActsExamples::DD4hep::sortFCChhDetElements( std::vector& det) { std::vector tracker; diff --git a/Examples/Python/python/acts/_adapter.py b/Examples/Python/python/acts/_adapter.py index 112fbf7f631..493fb53b508 100644 --- a/Examples/Python/python/acts/_adapter.py +++ b/Examples/Python/python/acts/_adapter.py @@ -2,6 +2,7 @@ import functools from typing import Optional, Callable, Dict, Any from pathlib import Path +from collections import namedtuple import acts @@ -117,7 +118,23 @@ def create(*args, mdecorator=None, **kwargs): _kwargs[k] = v det = cls() tg, deco = det.finalize(cfg, mdecorator, *args, **_kwargs) - return det, tg, deco + 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 diff --git a/Examples/Python/python/acts/examples/dd4hep.py b/Examples/Python/python/acts/examples/dd4hep.py index f68dc38453a..cd23533dfda 100644 --- a/Examples/Python/python/acts/examples/dd4hep.py +++ b/Examples/Python/python/acts/examples/dd4hep.py @@ -12,10 +12,11 @@ print("Error encountered importing DD4hep. Likely you need to set LD_LIBRARY_PATH.") sys.exit(1) -from acts._adapter import _patch_config, _detector_create +from acts._adapter import _patch_config, _detector_create, _patch_detectors from acts import ActsPythonBindingsDD4hep _patch_config(ActsPythonBindingsDD4hep) +_patch_detectors(ActsPythonBindingsDD4hep) ActsPythonBindingsDD4hep.DD4hepDetector.create = _detector_create( ActsPythonBindingsDD4hep.DD4hepDetector, ActsPythonBindingsDD4hep.DD4hepGeometryService.Config, diff --git a/Examples/Python/python/acts/examples/odd.py b/Examples/Python/python/acts/examples/odd.py index ec8cbcb9438..4e1efb1c783 100644 --- a/Examples/Python/python/acts/examples/odd.py +++ b/Examples/Python/python/acts/examples/odd.py @@ -1,6 +1,7 @@ import os import sys import math +from collections import namedtuple from pathlib import Path from typing import Optional import acts @@ -99,6 +100,22 @@ def geoid_hook(geoid, surface): level=customLogLevel(minLevel=acts.logging.WARNING), ) - trackingGeometry, deco = detector.finalize(dd4hepConfig, mdecorator) + trackingGeometry, decorators = detector.finalize(dd4hepConfig, mdecorator) - return detector, trackingGeometry, deco + OpenDataDetector = namedtuple( + "OpenDataDetector", ["detector", "trackingGeometry", "decorators"] + ) + + 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) diff --git a/Examples/Python/src/DD4hepComponent.cpp b/Examples/Python/src/DD4hepComponent.cpp index 091842f6783..be4d30b5f5e 100644 --- a/Examples/Python/src/DD4hepComponent.cpp +++ b/Examples/Python/src/DD4hepComponent.cpp @@ -1,6 +1,6 @@ // This file is part of the Acts project. // -// Copyright (C) 2021 CERN for the benefit of the Acts project +// Copyright (C) 2021-2024 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 @@ -36,11 +36,12 @@ using namespace Acts::Python; PYBIND11_MODULE(ActsPythonBindingsDD4hep, m) { { - using Config = ActsExamples::DD4hep::DD4hepGeometryService::Config; + using Config = DD4hep::DD4hepGeometryService::Config; auto s = py::class_>( m, "DD4hepGeometryService") - .def(py::init()); + .def(py::init()) + .def("drop", &DD4hep::DD4hepGeometryService::drop); auto c = py::class_(s, "Config").def(py::init<>()); ACTS_PYTHON_STRUCT_BEGIN(c, Config); @@ -88,7 +89,7 @@ PYBIND11_MODULE(ActsPythonBindingsDD4hep, m) { const auto* dd4hepDetElement = dynamic_cast(dde); // Check if it is valid - if (dd4hepDetElement) { + if (dd4hepDetElement != nullptr) { dd4hep::DDSegmentation::VolumeID dd4hepID = dd4hepDetElement->sourceElement().volumeID(); auto geoID = surface->geometryId(); @@ -167,6 +168,7 @@ PYBIND11_MODULE(ActsPythonBindingsDD4hep, m) { const Acts::GeometryContext&, const Acts::Experimental::DD4hepDetectorStructure::Options&>( &DD4hep::DD4hepDetector::finalize)) + .def("drop", &DD4hep::DD4hepDetector::drop) .def_property_readonly("field", &DD4hep::DD4hepDetector::field); } } diff --git a/Examples/Python/src/Geant4DD4hepComponent.cpp b/Examples/Python/src/Geant4DD4hepComponent.cpp index a6684e7eab8..cf2f5a87b8c 100644 --- a/Examples/Python/src/Geant4DD4hepComponent.cpp +++ b/Examples/Python/src/Geant4DD4hepComponent.cpp @@ -6,7 +6,6 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include "Acts/Utilities/TypeTraits.hpp" #include "ActsExamples/DD4hepDetector/DD4hepDetector.hpp" #include "ActsExamples/DDG4/DDG4DetectorConstruction.hpp" #include "ActsExamples/Framework/ProcessCode.hpp" diff --git a/Examples/Python/tests/conftest.py b/Examples/Python/tests/conftest.py index c115506c9a3..352155fb6a3 100644 --- a/Examples/Python/tests/conftest.py +++ b/Examples/Python/tests/conftest.py @@ -253,9 +253,7 @@ def trk_geo(): DetectorConfig = namedtuple( "DetectorConfig", [ - "detector", - "trackingGeometry", - "decorators", + "detectorTuple", "geometrySelection", "digiConfigFile", "name", @@ -268,11 +266,9 @@ def detector_config(request): srcdir = Path(__file__).resolve().parent.parent.parent.parent if request.param == "generic": - detector, trackingGeometry, decorators = acts.examples.GenericDetector.create() + detectorTuple = acts.examples.GenericDetector.create() return DetectorConfig( - detector, - trackingGeometry, - decorators, + detectorTuple, geometrySelection=( srcdir / "Examples/Algorithms/TrackFinding/share/geoSelection-genericDetector.json" @@ -291,11 +287,9 @@ def detector_config(request): srcdir / "thirdparty/OpenDataDetector/data/odd-material-maps.root", level=acts.logging.INFO, ) - detector, trackingGeometry, decorators = getOpenDataDetector(matDeco) + detectorTuple = getOpenDataDetector(matDeco) return DetectorConfig( - detector, - trackingGeometry, - decorators, + detectorTuple, digiConfigFile=( srcdir / "thirdparty/OpenDataDetector/config/odd-digi-smearing-config.json" @@ -305,7 +299,6 @@ def detector_config(request): ), name=request.param, ) - else: raise ValueError(f"Invalid detector {detector}") @@ -390,16 +383,18 @@ def _factory(s): def _do_material_recording(d: Path): from material_recording import runMaterialRecording - detector, trackingGeometry, decorators = getOpenDataDetector() + s = acts.examples.Sequencer(events=2, numThreads=1) - detectorConstructionFactory = ( - acts.examples.geant4.dd4hep.DDG4DetectorConstructionFactory(detector) - ) + with getOpenDataDetector() as (detector, trackingGeometry, decorators): + detectorConstructionFactory = ( + acts.examples.geant4.dd4hep.DDG4DetectorConstructionFactory(detector) + ) - s = acts.examples.Sequencer(events=2, numThreads=1) + runMaterialRecording( + detectorConstructionFactory, str(d), tracksPerEvent=100, s=s + ) - runMaterialRecording(detectorConstructionFactory, str(d), tracksPerEvent=100, s=s) - s.run() + s.run() @pytest.fixture(scope="session") diff --git a/Examples/Python/tests/test_detectors.py b/Examples/Python/tests/test_detectors.py index a9574bee621..e99406c69d6 100644 --- a/Examples/Python/tests/test_detectors.py +++ b/Examples/Python/tests/test_detectors.py @@ -53,11 +53,10 @@ def test_telescope_geometry(): @pytest.mark.skipif(not dd4hepEnabled, reason="DD4hep is not set up") def test_odd(): - detector, trackingGeometry, decorators = getOpenDataDetector() + with getOpenDataDetector() as (detector, trackingGeometry, decorators): + trackingGeometry.visitSurfaces(check_extra_odd) - trackingGeometry.visitSurfaces(check_extra_odd) - - assert count_surfaces(trackingGeometry) == 18824 + assert count_surfaces(trackingGeometry) == 18824 def test_aligned_detector(): diff --git a/Examples/Python/tests/test_examples.py b/Examples/Python/tests/test_examples.py index 4520488a26b..291dca8ac85 100644 --- a/Examples/Python/tests/test_examples.py +++ b/Examples/Python/tests/test_examples.py @@ -87,8 +87,6 @@ def test_pythia8(tmp_path, seq, assert_root_hash): runPythia8(str(tmp_path), outputRoot=True, outputCsv=True, s=seq).run() - del seq - fp = tmp_path / "pythia8_particles.root" assert fp.exists() assert fp.stat().st_size > 2**10 * 50 @@ -125,8 +123,6 @@ def test_fatras(trk_geo, tmp_path, field, assert_root_hash): seq = Sequencer(events=nevents) runFatras(trk_geo, field, str(tmp_path), s=seq).run() - del seq - assert_csv_output(csv, "particles_final") assert_csv_output(csv, "particles_initial") assert_csv_output(csv, "hits") @@ -145,7 +141,10 @@ def test_fatras(trk_geo, tmp_path, field, assert_root_hash): @pytest.mark.skipif(not dd4hepEnabled, reason="DD4hep not set up") def test_geant4(tmp_path, assert_root_hash): # This test literally only ensures that the geant 4 example can run without erroring out - getOpenDataDetector() # just to make sure it can build + + # just to make sure it can build the odd + with getOpenDataDetector() as (detector, trackingGeometry, decorators): + pass csv = tmp_path / "csv" csv.mkdir() @@ -228,8 +227,6 @@ def test_seeding(tmp_path, trk_geo, field, assert_root_hash): runSeeding(trk_geo, field, outputDir=str(tmp_path), s=seq).run() - del seq - for fn, tn in root_files: fp = tmp_path / fn assert fp.exists() @@ -287,8 +284,6 @@ def test_seeding_orthogonal(tmp_path, trk_geo, field, assert_root_hash): seedingAlgorithm=SeedingAlgorithm.Orthogonal, ).run() - del seq - for fn, tn in root_files: fp = tmp_path / fn assert fp.exists() @@ -397,8 +392,6 @@ def test_itk_seeding(tmp_path, trk_geo, field, assert_root_hash): seq.run() - del seq - for fn, tn in root_files: fp = tmp_path / fn assert fp.exists() @@ -523,12 +516,6 @@ def test_event_recording(tmp_path): def test_truth_tracking_kalman( tmp_path, assert_root_hash, revFiltMomThresh, directNavigation, detector_config ): - from truth_tracking_kalman import runTruthTrackingKalman - - field = acts.ConstantBField(acts.Vector3(0, 0, 2 * u.T)) - - seq = Sequencer(events=10, numThreads=1) - root_files = [ ("trackstates_kf.root", "trackstates", 19), ("tracksummary_kf.root", "tracksummary", 10), @@ -539,19 +526,26 @@ def test_truth_tracking_kalman( fp = tmp_path / fn assert not fp.exists() - runTruthTrackingKalman( - trackingGeometry=detector_config.trackingGeometry, - field=field, - digiConfigFile=detector_config.digiConfigFile, - outputDir=tmp_path, - reverseFilteringMomThreshold=revFiltMomThresh, - directNavigation=directNavigation, - s=seq, - ) + print("with") + with detector_config.detectorTuple as (detector, trackingGeometry, decorators): + from truth_tracking_kalman import runTruthTrackingKalman - seq.run() + field = acts.ConstantBField(acts.Vector3(0, 0, 2 * u.T)) + + seq = Sequencer(events=10, numThreads=1) + + runTruthTrackingKalman( + trackingGeometry=trackingGeometry, + field=field, + digiConfigFile=detector_config.digiConfigFile, + outputDir=tmp_path, + reverseFilteringMomThreshold=revFiltMomThresh, + directNavigation=directNavigation, + s=seq, + ) - del seq + seq.run() + print("done") for fn, tn, ee in root_files: fp = tmp_path / fn @@ -598,20 +592,19 @@ def test_truth_tracking_gsf(tmp_path, assert_root_hash, detector_config): fp = tmp_path / fn assert not fp.exists() - runTruthTrackingGsf( - trackingGeometry=detector_config.trackingGeometry, - decorators=detector_config.decorators, - field=field, - digiConfigFile=detector_config.digiConfigFile, - outputDir=tmp_path, - s=seq, - ) - - # See https://github.com/acts-project/acts/issues/1300 - with failure_threshold(acts.logging.FATAL): - seq.run() + with detector_config.detectorTuple as (detector, trackingGeometry, decorators): + runTruthTrackingGsf( + trackingGeometry=trackingGeometry, + decorators=decorators, + field=field, + digiConfigFile=detector_config.digiConfigFile, + outputDir=tmp_path, + s=seq, + ) - del seq + # See https://github.com/acts-project/acts/issues/1300 + with failure_threshold(acts.logging.FATAL): + seq.run() for fn, tn in root_files: fp = tmp_path / fn @@ -631,14 +624,15 @@ def test_refitting(tmp_path, detector_config, assert_root_hash): numThreads=1, ) - # Only check if it runs without errors right known - # Changes in fitter behaviour should be caught by other tests - runRefittingGsf( - trackingGeometry=detector_config.trackingGeometry, - field=field, - outputDir=tmp_path, - s=seq, - ).run() + with detector_config.detectorTuple as (detector, trackingGeometry, decorators): + # Only check if it runs without errors right known + # Changes in fitter behaviour should be caught by other tests + runRefittingGsf( + trackingGeometry=trackingGeometry, + field=field, + outputDir=tmp_path, + s=seq, + ).run() root_files = [ ("trackstates_gsf_refit.root", "trackstates"), @@ -681,11 +675,12 @@ def test_particle_gun(tmp_path, assert_root_hash): @pytest.mark.odd @pytest.mark.skipif(not dd4hepEnabled, reason="DD4hep not set up") def test_material_mapping(material_recording, tmp_path, assert_root_hash): + from material_mapping import runMaterialMapping + from material_validation import runMaterialValidation + map_file = tmp_path / "material-map_tracks.root" assert not map_file.exists() - s = Sequencer(numThreads=1) - odd_dir = getOpenDataDetectorDirectory() config = acts.MaterialMapJsonConverter.Config() mdecorator = acts.JsonMaterialDecorator( @@ -693,24 +688,20 @@ def test_material_mapping(material_recording, tmp_path, assert_root_hash): rConfig=config, jFileName=str(odd_dir / "config/odd-material-mapping-config.json"), ) - detector, trackingGeometry, decorators = getOpenDataDetector(mdecorator) - from material_mapping import runMaterialMapping - - runMaterialMapping( - trackingGeometry, - decorators, - outputDir=str(tmp_path), - inputDir=material_recording, - mappingStep=1, - s=s, - ) + s = Sequencer(numThreads=1) - s.run() + with getOpenDataDetector(mdecorator) as (detector, trackingGeometry, decorators): + runMaterialMapping( + trackingGeometry, + decorators, + outputDir=str(tmp_path), + inputDir=material_recording, + mappingStep=1, + s=s, + ) - # MaterialMapping alg only writes on destruct. - # See https://github.com/acts-project/acts/issues/881 - del s + s.run() mat_file = tmp_path / "material-map.json" @@ -729,25 +720,20 @@ def test_material_mapping(material_recording, tmp_path, assert_root_hash): # test the validation as well - # we need to destroy the ODD to reload with material - del trackingGeometry - del detector - - detector, trackingGeometry, decorators = getOpenDataDetector( - mdecorator=acts.IMaterialDecorator.fromFile(mat_file), - ) - - from material_validation import runMaterialValidation + field = acts.NullBField() s = Sequencer(events=10, numThreads=1) - field = acts.NullBField() - - runMaterialValidation( - 10, 1000, trackingGeometry, decorators, field, outputDir=str(tmp_path), s=s - ) + with getOpenDataDetector(mdecorator=acts.IMaterialDecorator.fromFile(mat_file)) as ( + detector, + trackingGeometry, + decorators, + ): + runMaterialValidation( + 10, 1000, trackingGeometry, decorators, field, outputDir=str(tmp_path), s=s + ) - s.run() + s.run() assert val_file.exists() assert_entries(val_file, "material-tracks", 10000) @@ -758,38 +744,36 @@ def test_material_mapping(material_recording, tmp_path, assert_root_hash): @pytest.mark.odd @pytest.mark.skipif(not dd4hepEnabled, reason="DD4hep not set up") def test_volume_material_mapping(material_recording, tmp_path, assert_root_hash): + from material_mapping import runMaterialMapping + from material_validation import runMaterialValidation + map_file = tmp_path / "material-map-volume_tracks.root" assert not map_file.exists() - s = Sequencer(numThreads=1) - geo_map = Path(__file__).parent / "geometry-volume-map.json" assert geo_map.exists() assert geo_map.stat().st_size > 10 with geo_map.open() as fh: assert json.load(fh) - detector, trackingGeometry, decorators = getOpenDataDetector( - mdecorator=acts.IMaterialDecorator.fromFile(geo_map), - ) - - from material_mapping import runMaterialMapping + s = Sequencer(numThreads=1) - runMaterialMapping( + with getOpenDataDetector(mdecorator=acts.IMaterialDecorator.fromFile(geo_map)) as ( + detector, trackingGeometry, decorators, - mapName="material-map-volume", - outputDir=str(tmp_path), - inputDir=material_recording, - mappingStep=1, - s=s, - ) - - s.run() + ): + runMaterialMapping( + trackingGeometry, + decorators, + mapName="material-map-volume", + outputDir=str(tmp_path), + inputDir=material_recording, + mappingStep=1, + s=s, + ) - # MaterialMapping alg only writes on destruct. - # See https://github.com/acts-project/acts/issues/881 - del s + s.run() mat_file = tmp_path / "material-map-volume.json" @@ -808,32 +792,27 @@ def test_volume_material_mapping(material_recording, tmp_path, assert_root_hash) # test the validation as well - # we need to destroy the ODD to reload with material - del trackingGeometry - del detector - - detector, trackingGeometry, decorators = getOpenDataDetector( - mdecorator=acts.IMaterialDecorator.fromFile(mat_file), - ) - - from material_validation import runMaterialValidation + field = acts.NullBField() s = Sequencer(events=10, numThreads=1) - field = acts.NullBField() - - runMaterialValidation( - 10, - 1000, + with getOpenDataDetector(mdecorator=acts.IMaterialDecorator.fromFile(mat_file)) as ( + detector, trackingGeometry, decorators, - field, - outputDir=str(tmp_path), - outputName="propagation-volume-material", - s=s, - ) + ): + runMaterialValidation( + 10, + 1000, + trackingGeometry, + decorators, + field, + outputDir=str(tmp_path), + outputName="propagation-volume-material", + s=s, + ) - s.run() + s.run() assert val_file.exists() @@ -970,6 +949,7 @@ def test_digitization_example_input( ptcl_dir.mkdir() pgs = Sequencer(events=20, numThreads=-1) runParticleGun(str(ptcl_dir), s=pgs) + pgs.run() s = Sequencer(numThreads=-1) @@ -1083,22 +1063,21 @@ def test_ckf_tracks_example( from ckf_tracks import runCKFTracks - runCKFTracks( - detector_config.trackingGeometry, - detector_config.decorators, - field=field, - outputCsv=True, - outputDir=tmp_path, - geometrySelection=detector_config.geometrySelection, - digiConfigFile=detector_config.digiConfigFile, - truthSmearedSeeded=truthSmeared, - truthEstimatedSeeded=truthEstimated, - s=s, - ) - - s.run() + with detector_config.detectorTuple as (detector, trackingGeometry, decorators): + runCKFTracks( + trackingGeometry, + decorators, + field=field, + outputCsv=True, + outputDir=tmp_path, + geometrySelection=detector_config.geometrySelection, + digiConfigFile=detector_config.digiConfigFile, + truthSmearedSeeded=truthSmeared, + truthEstimatedSeeded=truthEstimated, + s=s, + ) - del s # files are closed in destructors, not great + s.run() assert csv.exists() for rf, tn in root_files: @@ -1118,7 +1097,10 @@ def test_ckf_tracks_example( @pytest.mark.slow def test_full_chain_odd_example(tmp_path): # This test literally only ensures that the full chain example can run without erroring out - getOpenDataDetector() # just to make sure it can build + + # just to make sure it can build the odd + with getOpenDataDetector() as (detector, trackingGeometry, decorators): + pass script = ( Path(__file__).parent.parent.parent.parent @@ -1148,7 +1130,9 @@ def test_full_chain_odd_example(tmp_path): @pytest.mark.slow 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 - getOpenDataDetector() # just to make sure it can build + + # just to make sure it can build the odd + detector, trackingGeometry, decorators = getOpenDataDetector() script = ( Path(__file__).parent.parent.parent.parent @@ -1194,11 +1178,14 @@ def test_full_chain_odd_example_pythia_geant4(tmp_path): @pytest.mark.skipif(not onnxEnabled, reason="ONNX plugin not enabled") @pytest.mark.slow def test_ML_Ambiguity_Solver(tmp_path, assert_root_hash): + # This test literally only ensures that the full chain example can run without erroring out + root_file = "performance_ambiML.root" output_dir = "odd_output" assert not (tmp_path / root_file).exists() - # This test literally only ensures that the full chain example can run without erroring out - getOpenDataDetector() # just to make sure it can build + + # just to make sure it can build the odd + detector, trackingGeometry, decorators = getOpenDataDetector() script = ( Path(__file__).parent.parent.parent.parent diff --git a/Examples/Python/tests/test_propagation.py b/Examples/Python/tests/test_propagation.py index 0d2d6edfb68..84dbd77c3e9 100644 --- a/Examples/Python/tests/test_propagation.py +++ b/Examples/Python/tests/test_propagation.py @@ -90,6 +90,7 @@ def test_steppers(conf_const, trk_geo): "propagation_steps", "chk_alg", level=acts.logging.WARNING ) seq.addAlgorithm(chkAlg) + seq.run() assert acts.StraightLineStepper() diff --git a/Examples/Python/tests/test_reader.py b/Examples/Python/tests/test_reader.py index e7bae0b9721..f4e803776d5 100644 --- a/Examples/Python/tests/test_reader.py +++ b/Examples/Python/tests/test_reader.py @@ -45,8 +45,6 @@ def test_root_particle_reader(tmp_path, conf_const, ptcl_gun): s.run() - del s # to properly close the root file - # reset sequencer for reading s2 = Sequencer(numThreads=1, logLevel=acts.logging.WARNING) @@ -298,40 +296,39 @@ def test_edm4hep_simhit_particle_reader(tmp_path): assert os.path.exists(tmp_file) - detector, trackingGeometry, decorators = getOpenDataDetector() - s = Sequencer(numThreads=1) - s.addReader( - EDM4hepReader( - level=acts.logging.INFO, - inputPath=tmp_file, - inputSimHits=[ - "PixelBarrelReadout", - "PixelEndcapReadout", - "ShortStripBarrelReadout", - "ShortStripEndcapReadout", - "LongStripBarrelReadout", - "LongStripEndcapReadout", - ], - outputParticlesGenerator="particles_input", - outputParticlesInitial="particles_initial", - outputParticlesFinal="particles_final", - outputSimHits="simhits", - dd4hepDetector=detector, - trackingGeometry=trackingGeometry, + with getOpenDataDetector() as (detector, trackingGeometry, decorators): + s.addReader( + EDM4hepReader( + level=acts.logging.INFO, + inputPath=tmp_file, + inputSimHits=[ + "PixelBarrelReadout", + "PixelEndcapReadout", + "ShortStripBarrelReadout", + "ShortStripEndcapReadout", + "LongStripBarrelReadout", + "LongStripEndcapReadout", + ], + outputParticlesGenerator="particles_input", + outputParticlesInitial="particles_initial", + outputParticlesFinal="particles_final", + outputSimHits="simhits", + dd4hepDetector=detector, + trackingGeometry=trackingGeometry, + ) ) - ) - alg = AssertCollectionExistsAlg("simhits", "check_alg", acts.logging.WARNING) - s.addAlgorithm(alg) + alg = AssertCollectionExistsAlg("simhits", "check_alg", acts.logging.WARNING) + s.addAlgorithm(alg) - alg = AssertCollectionExistsAlg( - "particles_input", "check_alg", acts.logging.WARNING - ) - s.addAlgorithm(alg) + alg = AssertCollectionExistsAlg( + "particles_input", "check_alg", acts.logging.WARNING + ) + s.addAlgorithm(alg) - s.run() + s.run() assert alg.events_seen == 10 @@ -421,8 +418,6 @@ def test_edm4hep_tracks_reader(tmp_path): s.run() - del s - s = Sequencer(numThreads=1) s.addReader( EDM4hepTrackReader( diff --git a/Examples/Python/tests/test_writer.py b/Examples/Python/tests/test_writer.py index 9d9dbf15363..ce85a374174 100644 --- a/Examples/Python/tests/test_writer.py +++ b/Examples/Python/tests/test_writer.py @@ -398,7 +398,6 @@ def test_csv_multitrajectory_writer(tmp_path): ) ) s.run() - del s assert len([f for f in csv_dir.iterdir() if f.is_file()]) == 10 assert all(f.stat().st_size > 20 for f in csv_dir.iterdir()) 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 f459252b185..821320a33a2 100755 --- a/Examples/Scripts/Python/Auto-tuning/Orion/material_mapping_optimisation.py +++ b/Examples/Scripts/Python/Auto-tuning/Orion/material_mapping_optimisation.py @@ -174,10 +174,6 @@ def runMaterialMappingVariance( # Update the binning using the bin map corresponding to this trial matMapDeco.setBinningMap(binMap) - del detectorTemp - del trackingGeometryTemp - del decoratorsTemp - # Decorate the detector with the MappingMaterialDecorator detector, trackingGeometry, decorators = getOpenDataDetector(matMapDeco) @@ -199,10 +195,6 @@ def runMaterialMappingVariance( s=sMap, ) sMap.run() - del sMap # Need to be deleted to write the material map to cbor - del detector - del trackingGeometry - del decorators # Compute the variance by rerunning the mapping print( @@ -300,11 +292,6 @@ def runMaterialMappingVariance( ) pipeResult.send(score) - del mapping - del s - del detectorVar - del trackingGeometryVar - del decoratorsVar os.remove(cborMap) @@ -483,7 +470,6 @@ def surfaceExperiment(key, nbJobs, pathDB, pathResult, pipeBin, pipeResult, doPl tGeometry=trackingGeometry, level=acts.logging.WARNING ) binDict = matMapDeco.binningMap() - del detector, decorators # Create the pipes that will be used to transfer data to/from the jobs from multiprocessing import Process, Pipe @@ -605,8 +591,6 @@ def surfaceExperiment(key, nbJobs, pathDB, pathResult, pipeBin, pipeResult, doPl s=rMap, ) rMap.run() - del rMap # Need to be deleted to write the material map to cbor - del resultDetector, resultTrackingGeometry, resultDecorators print( datetime.now().strftime("%H:%M:%S") + " Waiting for all the score to have been stored", diff --git a/Examples/Scripts/Python/MLAmbiguityResolution/train_seed_solver.py b/Examples/Scripts/Python/MLAmbiguityResolution/train_seed_solver.py index f2fac4d814c..de1bf6a0d5c 100644 --- a/Examples/Scripts/Python/MLAmbiguityResolution/train_seed_solver.py +++ b/Examples/Scripts/Python/MLAmbiguityResolution/train_seed_solver.py @@ -329,11 +329,6 @@ def train( dynamic_axes={"x": {0: "batch_size"}, "y": {0: "batch_size"}}, ) -del CKF_files -del data -del x_train, y_train -del input, input_test -del duplicateClassifier # ================================================================== # ttbar events for the test, here we assume 40 events are availables diff --git a/Examples/Scripts/Python/geant4.py b/Examples/Scripts/Python/geant4.py index 54600d98616..eb636c43bdd 100755 --- a/Examples/Scripts/Python/geant4.py +++ b/Examples/Scripts/Python/geant4.py @@ -74,7 +74,7 @@ def runGeant4( # Context and options geoContext = acts.GeometryContext() [detector, contextors, store] = dd4hepDetector.finalize(geoContext, cOptions) - runGeant4(dd4hepDetector, detector, field, Path.cwd()).run() + runGeant4(detector, detector, field, Path.cwd()).run() else: - dd4hepDetector, trackingGeometry, decorators = getOpenDataDetector() - runGeant4(dd4hepDetector, trackingGeometry, field, Path.cwd()).run() + detector, trackingGeometry, decorators = getOpenDataDetector() + runGeant4(detector, trackingGeometry, field, Path.cwd()).run() diff --git a/Examples/Scripts/Python/geant4_parallel.py b/Examples/Scripts/Python/geant4_parallel.py index 50c861be45f..d9a8f59f8c2 100755 --- a/Examples/Scripts/Python/geant4_parallel.py +++ b/Examples/Scripts/Python/geant4_parallel.py @@ -23,16 +23,13 @@ # -def runGeant4EventRange(beginEvent, endEvent, outputDir): +def runGeant4EventRange(detector, trackingGeometry, beginEvent, endEvent, outputDir): import acts import acts.examples from acts.examples.simulation import addParticleGun, addGeant4, EtaConfig - from acts.examples.odd import getOpenDataDetector u = acts.UnitConstants - detector, trackingGeometry, decorators = getOpenDataDetector() - field = acts.ConstantBField(acts.Vector3(0, 0, 2 * u.T)) rnd = acts.examples.RandomNumbers(seed=42) @@ -59,10 +56,13 @@ def runGeant4EventRange(beginEvent, endEvent, outputDir): ) s.run() - del s if "__main__" == __name__: + from acts.examples.odd import getOpenDataDetector + + detector, trackingGeometry, decorators = getOpenDataDetector() + n_events = 100 n_jobs = 8 diff --git a/Examples/Scripts/Python/seeding.py b/Examples/Scripts/Python/seeding.py index 076262fd194..4c87ba9b82b 100755 --- a/Examples/Scripts/Python/seeding.py +++ b/Examples/Scripts/Python/seeding.py @@ -147,8 +147,8 @@ def runSeeding( ) args = p.parse_args() - # detector, trackingGeometry, _ = getOpenDataDetector() - detector, trackingGeometry, _ = acts.examples.GenericDetector.create() + # detector, trackingGeometry, decorators = getOpenDataDetector() + detector, trackingGeometry, decorators = acts.examples.GenericDetector.create() field = acts.ConstantBField(acts.Vector3(0, 0, 2 * u.T)) diff --git a/Examples/Scripts/Python/truth_tracking_gsf.py b/Examples/Scripts/Python/truth_tracking_gsf.py index bd95153c1ff..82c99bb38aa 100755 --- a/Examples/Scripts/Python/truth_tracking_gsf.py +++ b/Examples/Scripts/Python/truth_tracking_gsf.py @@ -160,7 +160,7 @@ def runTruthTrackingGsf( # ODD from acts.examples.odd import getOpenDataDetector - detector, trackingGeometry, _ = getOpenDataDetector() + detector, trackingGeometry, decorators = getOpenDataDetector() digiConfigFile = ( srcdir / "thirdparty/OpenDataDetector/config/odd-digi-smearing-config.json" ) diff --git a/Examples/Scripts/Python/truth_tracking_gsf_refitting.py b/Examples/Scripts/Python/truth_tracking_gsf_refitting.py index d16784cefcb..138540db2af 100755 --- a/Examples/Scripts/Python/truth_tracking_gsf_refitting.py +++ b/Examples/Scripts/Python/truth_tracking_gsf_refitting.py @@ -97,7 +97,7 @@ def runRefittingGsf( if __name__ == "__main__": outputDir = Path.cwd() - # detector, trackingGeometry, _ = getOpenDataDetector() + # detector, trackingGeometry, decorators = getOpenDataDetector() detector, trackingGeometry, decorators = acts.examples.GenericDetector.create() field = acts.ConstantBField(acts.Vector3(0, 0, 2 * u.T)) diff --git a/Examples/Scripts/Python/truth_tracking_gx2f.py b/Examples/Scripts/Python/truth_tracking_gx2f.py index 6ef9cceecb8..e20795b7010 100644 --- a/Examples/Scripts/Python/truth_tracking_gx2f.py +++ b/Examples/Scripts/Python/truth_tracking_gx2f.py @@ -159,7 +159,7 @@ def runTruthTrackingGx2f( # ODD from acts.examples.odd import getOpenDataDetector - detector, trackingGeometry, _ = getOpenDataDetector() + detector, trackingGeometry, decorators = getOpenDataDetector() digiConfigFile = ( srcdir / "thirdparty/OpenDataDetector/config/odd-digi-smearing-config.json" ) diff --git a/Examples/Scripts/Python/truth_tracking_kalman.py b/Examples/Scripts/Python/truth_tracking_kalman.py index 714e0421e41..83d189c6bd6 100755 --- a/Examples/Scripts/Python/truth_tracking_kalman.py +++ b/Examples/Scripts/Python/truth_tracking_kalman.py @@ -163,7 +163,7 @@ def runTruthTrackingKalman( # ODD from acts.examples.odd import getOpenDataDetector - detector, trackingGeometry, _ = getOpenDataDetector() + detector, trackingGeometry, decorators = getOpenDataDetector() digiConfigFile = ( srcdir / "thirdparty/OpenDataDetector/config/odd-digi-smearing-config.json" )