From 8925fb52f9619b11165b2d9a1e58033b694e53b7 Mon Sep 17 00:00:00 2001 From: Wouter Deconinck Date: Fri, 18 Oct 2024 08:47:28 -0500 Subject: [PATCH 1/6] fix: `#include ` in HoughTransformUtils for `std::sort` (#3758) With gcc-14, the following compilation failure is reported: ``` 438 In file included from /home/wdconinc/git/acts/Core/include/Acts/Seeding/HoughTransformUtils.hpp:374, 439 from /home/wdconinc/git/acts/Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/MuonHoughSeeder.hpp:12, 440 from /home/wdconinc/git/acts/Examples/Algorithms/TrackFinding/src/MuonHoughSeeder.cpp:9: 441 /home/wdconinc/git/acts/Core/include/Acts/Seeding/HoughTransformUtils.ipp: In member function 'std::vector::Maximum> Acts::HoughTransformUtils::PeakFind ers::IslandsAroundMax::findPeaks(const Acts::HoughTransformUtils::HoughPlane&, const Acts::HoughTransformUtils::HoughAxisRanges&)': >> 442 /home/wdconinc/git/acts/Core/include/Acts/Seeding/HoughTransformUtils.ipp:224:8: error: 'sort' is not a member of 'std'; did you mean 'qsort'? 443 224 | std::sort(candidates.begin(), candidates.end(), 444 | ^~~~ 445 | qsort >> 446 make[2]: *** [Examples/Algorithms/TrackFinding/CMakeFiles/ActsExamplesTrackFinding.dir/build.make:177: Examples/Algorithms/TrackFinding/CMakeFiles/ActsExamplesTrackFinding.dir/src/MuonHoughSeeder.cpp.o] Error 1 447 make[2]: *** Waiting for unfinished jobs.... ``` This appears to be due to a missing `#include ` before the use of `std::sort` in the `.ipp` file. This PR adds the `algorithm` header to the `.hpp` file. --- Core/include/Acts/Seeding/HoughTransformUtils.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Core/include/Acts/Seeding/HoughTransformUtils.hpp b/Core/include/Acts/Seeding/HoughTransformUtils.hpp index a7a84d8908c..4fcece48034 100644 --- a/Core/include/Acts/Seeding/HoughTransformUtils.hpp +++ b/Core/include/Acts/Seeding/HoughTransformUtils.hpp @@ -14,6 +14,7 @@ #include "Acts/Utilities/Logger.hpp" #include "Acts/Utilities/Result.hpp" +#include #include #include #include From a3e1303c703ea0a1f9843ebe42b3358f310e08f7 Mon Sep 17 00:00:00 2001 From: Andreas Stefl Date: Fri, 18 Oct 2024 17:45:01 +0200 Subject: [PATCH 2/6] refactor: Group all ROOT writers together (#3746) Our ROOT writers are quite scattered and I would like to group them back together. --- Examples/Io/CMakeLists.txt | 2 -- .../Io/NuclearInteractions/CMakeLists.txt | 20 ------------------- Examples/Io/Root/CMakeLists.txt | 7 +++++++ .../Io/Root}/CKFPerformanceWriter.hpp | 0 ...RootNuclearInteractionParametersWriter.hpp | 2 +- .../Io/Root}/SeedingPerformanceWriter.hpp | 0 .../Io/Root}/TrackFinderPerformanceWriter.hpp | 0 .../Io/Root}/TrackFitterPerformanceWriter.hpp | 0 .../Io/Root}/VertexPerformanceWriter.hpp | 0 .../NuclearInteractionParametrisation.hpp | 0 .../src}/CKFPerformanceWriter.cpp | 2 +- ...RootNuclearInteractionParametersWriter.cpp | 2 +- .../src}/SeedingPerformanceWriter.cpp | 2 +- .../src}/TrackFinderPerformanceWriter.cpp | 2 +- .../src}/TrackFitterPerformanceWriter.cpp | 2 +- .../src}/VertexPerformanceWriter.cpp | 2 +- .../NuclearInteractionParametrisation.cpp | 2 +- Examples/Python/CMakeLists.txt | 2 -- Examples/Python/src/Output.cpp | 12 +++++------ 19 files changed, 21 insertions(+), 38 deletions(-) delete mode 100644 Examples/Io/NuclearInteractions/CMakeLists.txt rename Examples/Io/{Performance/ActsExamples/Io/Performance => Root/include/ActsExamples/Io/Root}/CKFPerformanceWriter.hpp (100%) rename Examples/Io/{NuclearInteractions/include/ActsExamples/Io/NuclearInteractions => Root/include/ActsExamples/Io/Root}/RootNuclearInteractionParametersWriter.hpp (97%) rename Examples/Io/{Performance/ActsExamples/Io/Performance => Root/include/ActsExamples/Io/Root}/SeedingPerformanceWriter.hpp (100%) rename Examples/Io/{Performance/ActsExamples/Io/Performance => Root/include/ActsExamples/Io/Root}/TrackFinderPerformanceWriter.hpp (100%) rename Examples/Io/{Performance/ActsExamples/Io/Performance => Root/include/ActsExamples/Io/Root}/TrackFitterPerformanceWriter.hpp (100%) rename Examples/Io/{Performance/ActsExamples/Io/Performance => Root/include/ActsExamples/Io/Root}/VertexPerformanceWriter.hpp (100%) rename Examples/Io/{NuclearInteractions/include/ActsExamples/Io/NuclearInteractions => Root/include/ActsExamples/Io/Root}/detail/NuclearInteractionParametrisation.hpp (100%) rename Examples/Io/{Performance/ActsExamples/Io/Performance => Root/src}/CKFPerformanceWriter.cpp (99%) rename Examples/Io/{NuclearInteractions => Root}/src/RootNuclearInteractionParametersWriter.cpp (99%) rename Examples/Io/{Performance/ActsExamples/Io/Performance => Root/src}/SeedingPerformanceWriter.cpp (99%) rename Examples/Io/{Performance/ActsExamples/Io/Performance => Root/src}/TrackFinderPerformanceWriter.cpp (99%) rename Examples/Io/{Performance/ActsExamples/Io/Performance => Root/src}/TrackFitterPerformanceWriter.cpp (98%) rename Examples/Io/{Performance/ActsExamples/Io/Performance => Root/src}/VertexPerformanceWriter.cpp (99%) rename Examples/Io/{NuclearInteractions => Root}/src/detail/NuclearInteractionParametrisation.cpp (99%) diff --git a/Examples/Io/CMakeLists.txt b/Examples/Io/CMakeLists.txt index dcf7c16a0a1..8b7f2861a6e 100644 --- a/Examples/Io/CMakeLists.txt +++ b/Examples/Io/CMakeLists.txt @@ -2,8 +2,6 @@ add_subdirectory(Csv) add_subdirectory_if(EDM4hep ACTS_BUILD_EXAMPLES_EDM4HEP) add_subdirectory_if(HepMC3 ACTS_BUILD_EXAMPLES_HEPMC3) add_subdirectory(Json) -add_subdirectory(NuclearInteractions) add_subdirectory(Obj) -add_subdirectory(Performance) add_subdirectory(Root) add_subdirectory_if(Svg ACTS_BUILD_PLUGIN_ACTSVG) diff --git a/Examples/Io/NuclearInteractions/CMakeLists.txt b/Examples/Io/NuclearInteractions/CMakeLists.txt deleted file mode 100644 index 3f7ad2b9b9b..00000000000 --- a/Examples/Io/NuclearInteractions/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -add_library( - ActsExamplesIoNuclearInteractions - SHARED - src/RootNuclearInteractionParametersWriter.cpp - src/detail/NuclearInteractionParametrisation.cpp -) -target_include_directories( - ActsExamplesIoNuclearInteractions - PUBLIC $ -) -target_link_libraries( - ActsExamplesIoNuclearInteractions - PUBLIC ActsCore ActsExamplesFramework Threads::Threads - PRIVATE ROOT::Core ROOT::Hist ROOT::Tree -) - -install( - TARGETS ActsExamplesIoNuclearInteractions - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} -) diff --git a/Examples/Io/Root/CMakeLists.txt b/Examples/Io/Root/CMakeLists.txt index 3ac12286395..f384c291bc1 100644 --- a/Examples/Io/Root/CMakeLists.txt +++ b/Examples/Io/Root/CMakeLists.txt @@ -23,6 +23,13 @@ add_library( src/RootVertexReader.cpp src/RootVertexWriter.cpp src/RootAthenaDumpReader.cpp + src/RootNuclearInteractionParametersWriter.cpp + src/detail/NuclearInteractionParametrisation.cpp + src/CKFPerformanceWriter.cpp + src/SeedingPerformanceWriter.cpp + src/TrackFinderPerformanceWriter.cpp + src/TrackFitterPerformanceWriter.cpp + src/VertexPerformanceWriter.cpp ) target_include_directories( ActsExamplesIoRoot diff --git a/Examples/Io/Performance/ActsExamples/Io/Performance/CKFPerformanceWriter.hpp b/Examples/Io/Root/include/ActsExamples/Io/Root/CKFPerformanceWriter.hpp similarity index 100% rename from Examples/Io/Performance/ActsExamples/Io/Performance/CKFPerformanceWriter.hpp rename to Examples/Io/Root/include/ActsExamples/Io/Root/CKFPerformanceWriter.hpp diff --git a/Examples/Io/NuclearInteractions/include/ActsExamples/Io/NuclearInteractions/RootNuclearInteractionParametersWriter.hpp b/Examples/Io/Root/include/ActsExamples/Io/Root/RootNuclearInteractionParametersWriter.hpp similarity index 97% rename from Examples/Io/NuclearInteractions/include/ActsExamples/Io/NuclearInteractions/RootNuclearInteractionParametersWriter.hpp rename to Examples/Io/Root/include/ActsExamples/Io/Root/RootNuclearInteractionParametersWriter.hpp index 8edad2c2a7d..d688920fc76 100644 --- a/Examples/Io/NuclearInteractions/include/ActsExamples/Io/NuclearInteractions/RootNuclearInteractionParametersWriter.hpp +++ b/Examples/Io/Root/include/ActsExamples/Io/Root/RootNuclearInteractionParametersWriter.hpp @@ -12,7 +12,7 @@ #include "ActsExamples/EventData/ExtractedSimulationProcess.hpp" #include "ActsExamples/Framework/ProcessCode.hpp" #include "ActsExamples/Framework/WriterT.hpp" -#include "ActsExamples/Io/NuclearInteractions/detail/NuclearInteractionParametrisation.hpp" +#include "ActsExamples/Io/Root/detail/NuclearInteractionParametrisation.hpp" #include #include diff --git a/Examples/Io/Performance/ActsExamples/Io/Performance/SeedingPerformanceWriter.hpp b/Examples/Io/Root/include/ActsExamples/Io/Root/SeedingPerformanceWriter.hpp similarity index 100% rename from Examples/Io/Performance/ActsExamples/Io/Performance/SeedingPerformanceWriter.hpp rename to Examples/Io/Root/include/ActsExamples/Io/Root/SeedingPerformanceWriter.hpp diff --git a/Examples/Io/Performance/ActsExamples/Io/Performance/TrackFinderPerformanceWriter.hpp b/Examples/Io/Root/include/ActsExamples/Io/Root/TrackFinderPerformanceWriter.hpp similarity index 100% rename from Examples/Io/Performance/ActsExamples/Io/Performance/TrackFinderPerformanceWriter.hpp rename to Examples/Io/Root/include/ActsExamples/Io/Root/TrackFinderPerformanceWriter.hpp diff --git a/Examples/Io/Performance/ActsExamples/Io/Performance/TrackFitterPerformanceWriter.hpp b/Examples/Io/Root/include/ActsExamples/Io/Root/TrackFitterPerformanceWriter.hpp similarity index 100% rename from Examples/Io/Performance/ActsExamples/Io/Performance/TrackFitterPerformanceWriter.hpp rename to Examples/Io/Root/include/ActsExamples/Io/Root/TrackFitterPerformanceWriter.hpp diff --git a/Examples/Io/Performance/ActsExamples/Io/Performance/VertexPerformanceWriter.hpp b/Examples/Io/Root/include/ActsExamples/Io/Root/VertexPerformanceWriter.hpp similarity index 100% rename from Examples/Io/Performance/ActsExamples/Io/Performance/VertexPerformanceWriter.hpp rename to Examples/Io/Root/include/ActsExamples/Io/Root/VertexPerformanceWriter.hpp diff --git a/Examples/Io/NuclearInteractions/include/ActsExamples/Io/NuclearInteractions/detail/NuclearInteractionParametrisation.hpp b/Examples/Io/Root/include/ActsExamples/Io/Root/detail/NuclearInteractionParametrisation.hpp similarity index 100% rename from Examples/Io/NuclearInteractions/include/ActsExamples/Io/NuclearInteractions/detail/NuclearInteractionParametrisation.hpp rename to Examples/Io/Root/include/ActsExamples/Io/Root/detail/NuclearInteractionParametrisation.hpp diff --git a/Examples/Io/Performance/ActsExamples/Io/Performance/CKFPerformanceWriter.cpp b/Examples/Io/Root/src/CKFPerformanceWriter.cpp similarity index 99% rename from Examples/Io/Performance/ActsExamples/Io/Performance/CKFPerformanceWriter.cpp rename to Examples/Io/Root/src/CKFPerformanceWriter.cpp index e7fa1525615..7b5b5aaf291 100644 --- a/Examples/Io/Performance/ActsExamples/Io/Performance/CKFPerformanceWriter.cpp +++ b/Examples/Io/Root/src/CKFPerformanceWriter.cpp @@ -6,7 +6,7 @@ // 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/Io/Performance/CKFPerformanceWriter.hpp" +#include "ActsExamples/Io/Root/CKFPerformanceWriter.hpp" #include "Acts/EventData/TrackParameters.hpp" #include "Acts/Utilities/VectorHelpers.hpp" diff --git a/Examples/Io/NuclearInteractions/src/RootNuclearInteractionParametersWriter.cpp b/Examples/Io/Root/src/RootNuclearInteractionParametersWriter.cpp similarity index 99% rename from Examples/Io/NuclearInteractions/src/RootNuclearInteractionParametersWriter.cpp rename to Examples/Io/Root/src/RootNuclearInteractionParametersWriter.cpp index 64a324242c8..e0d635443e5 100644 --- a/Examples/Io/NuclearInteractions/src/RootNuclearInteractionParametersWriter.cpp +++ b/Examples/Io/Root/src/RootNuclearInteractionParametersWriter.cpp @@ -6,7 +6,7 @@ // 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/Io/NuclearInteractions/RootNuclearInteractionParametersWriter.hpp" +#include "ActsExamples/Io/Root/RootNuclearInteractionParametersWriter.hpp" #include "Acts/Definitions/Algebra.hpp" #include "Acts/Definitions/Common.hpp" diff --git a/Examples/Io/Performance/ActsExamples/Io/Performance/SeedingPerformanceWriter.cpp b/Examples/Io/Root/src/SeedingPerformanceWriter.cpp similarity index 99% rename from Examples/Io/Performance/ActsExamples/Io/Performance/SeedingPerformanceWriter.cpp rename to Examples/Io/Root/src/SeedingPerformanceWriter.cpp index b2d87be68f9..4ac7ea269ef 100644 --- a/Examples/Io/Performance/ActsExamples/Io/Performance/SeedingPerformanceWriter.cpp +++ b/Examples/Io/Root/src/SeedingPerformanceWriter.cpp @@ -6,7 +6,7 @@ // 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 "SeedingPerformanceWriter.hpp" +#include "ActsExamples/Io/Root/SeedingPerformanceWriter.hpp" #include "Acts/Utilities/MultiIndex.hpp" #include "Acts/Utilities/VectorHelpers.hpp" diff --git a/Examples/Io/Performance/ActsExamples/Io/Performance/TrackFinderPerformanceWriter.cpp b/Examples/Io/Root/src/TrackFinderPerformanceWriter.cpp similarity index 99% rename from Examples/Io/Performance/ActsExamples/Io/Performance/TrackFinderPerformanceWriter.cpp rename to Examples/Io/Root/src/TrackFinderPerformanceWriter.cpp index abef2ef0664..14e04252283 100644 --- a/Examples/Io/Performance/ActsExamples/Io/Performance/TrackFinderPerformanceWriter.cpp +++ b/Examples/Io/Root/src/TrackFinderPerformanceWriter.cpp @@ -6,7 +6,7 @@ // 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/Io/Performance/TrackFinderPerformanceWriter.hpp" +#include "ActsExamples/Io/Root/TrackFinderPerformanceWriter.hpp" #include "Acts/Definitions/Units.hpp" #include "ActsExamples/EventData/Index.hpp" diff --git a/Examples/Io/Performance/ActsExamples/Io/Performance/TrackFitterPerformanceWriter.cpp b/Examples/Io/Root/src/TrackFitterPerformanceWriter.cpp similarity index 98% rename from Examples/Io/Performance/ActsExamples/Io/Performance/TrackFitterPerformanceWriter.cpp rename to Examples/Io/Root/src/TrackFitterPerformanceWriter.cpp index 54441ad7aa8..2063f03b53b 100644 --- a/Examples/Io/Performance/ActsExamples/Io/Performance/TrackFitterPerformanceWriter.cpp +++ b/Examples/Io/Root/src/TrackFitterPerformanceWriter.cpp @@ -6,7 +6,7 @@ // 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/Io/Performance/TrackFitterPerformanceWriter.hpp" +#include "ActsExamples/Io/Root/TrackFitterPerformanceWriter.hpp" #include "Acts/EventData/MultiTrajectoryHelpers.hpp" #include "Acts/EventData/TrackParameters.hpp" diff --git a/Examples/Io/Performance/ActsExamples/Io/Performance/VertexPerformanceWriter.cpp b/Examples/Io/Root/src/VertexPerformanceWriter.cpp similarity index 99% rename from Examples/Io/Performance/ActsExamples/Io/Performance/VertexPerformanceWriter.cpp rename to Examples/Io/Root/src/VertexPerformanceWriter.cpp index dfc790433f9..f032e39af35 100644 --- a/Examples/Io/Performance/ActsExamples/Io/Performance/VertexPerformanceWriter.cpp +++ b/Examples/Io/Root/src/VertexPerformanceWriter.cpp @@ -6,7 +6,7 @@ // 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/Io/Performance/VertexPerformanceWriter.hpp" +#include "ActsExamples/Io/Root/VertexPerformanceWriter.hpp" #include "Acts/Definitions/Algebra.hpp" #include "Acts/Definitions/TrackParametrization.hpp" diff --git a/Examples/Io/NuclearInteractions/src/detail/NuclearInteractionParametrisation.cpp b/Examples/Io/Root/src/detail/NuclearInteractionParametrisation.cpp similarity index 99% rename from Examples/Io/NuclearInteractions/src/detail/NuclearInteractionParametrisation.cpp rename to Examples/Io/Root/src/detail/NuclearInteractionParametrisation.cpp index f9df3d38f85..91f59c56648 100644 --- a/Examples/Io/NuclearInteractions/src/detail/NuclearInteractionParametrisation.cpp +++ b/Examples/Io/Root/src/detail/NuclearInteractionParametrisation.cpp @@ -6,7 +6,7 @@ // 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/Io/NuclearInteractions/detail/NuclearInteractionParametrisation.hpp" +#include "ActsExamples/Io/Root/detail/NuclearInteractionParametrisation.hpp" #include "Acts/Definitions/Common.hpp" #include "ActsFatras/EventData/Particle.hpp" diff --git a/Examples/Python/CMakeLists.txt b/Examples/Python/CMakeLists.txt index ff1e5901f43..c932b3ef081 100644 --- a/Examples/Python/CMakeLists.txt +++ b/Examples/Python/CMakeLists.txt @@ -54,11 +54,9 @@ target_link_libraries( ActsExamplesDetectorTGeo ActsExamplesMagneticField ActsExamplesIoRoot - ActsExamplesIoNuclearInteractions ActsExamplesIoCsv ActsExamplesIoObj ActsExamplesIoJson - ActsExamplesIoPerformance ActsExamplesGenerators ActsExamplesPrinters ActsExamplesTrackFinding diff --git a/Examples/Python/src/Output.cpp b/Examples/Python/src/Output.cpp index 11472d8e203..3ef89801c41 100644 --- a/Examples/Python/src/Output.cpp +++ b/Examples/Python/src/Output.cpp @@ -26,16 +26,12 @@ #include "ActsExamples/Io/Csv/CsvTrackParameterWriter.hpp" #include "ActsExamples/Io/Csv/CsvTrackWriter.hpp" #include "ActsExamples/Io/Csv/CsvTrackingGeometryWriter.hpp" -#include "ActsExamples/Io/NuclearInteractions/RootNuclearInteractionParametersWriter.hpp" -#include "ActsExamples/Io/Performance/CKFPerformanceWriter.hpp" -#include "ActsExamples/Io/Performance/SeedingPerformanceWriter.hpp" -#include "ActsExamples/Io/Performance/TrackFinderPerformanceWriter.hpp" -#include "ActsExamples/Io/Performance/TrackFitterPerformanceWriter.hpp" -#include "ActsExamples/Io/Performance/VertexPerformanceWriter.hpp" +#include "ActsExamples/Io/Root/CKFPerformanceWriter.hpp" #include "ActsExamples/Io/Root/RootBFieldWriter.hpp" #include "ActsExamples/Io/Root/RootMaterialTrackWriter.hpp" #include "ActsExamples/Io/Root/RootMaterialWriter.hpp" #include "ActsExamples/Io/Root/RootMeasurementWriter.hpp" +#include "ActsExamples/Io/Root/RootNuclearInteractionParametersWriter.hpp" #include "ActsExamples/Io/Root/RootParticleWriter.hpp" #include "ActsExamples/Io/Root/RootPropagationStepsWriter.hpp" #include "ActsExamples/Io/Root/RootPropagationSummaryWriter.hpp" @@ -46,6 +42,10 @@ #include "ActsExamples/Io/Root/RootTrackStatesWriter.hpp" #include "ActsExamples/Io/Root/RootTrackSummaryWriter.hpp" #include "ActsExamples/Io/Root/RootVertexWriter.hpp" +#include "ActsExamples/Io/Root/SeedingPerformanceWriter.hpp" +#include "ActsExamples/Io/Root/TrackFinderPerformanceWriter.hpp" +#include "ActsExamples/Io/Root/TrackFitterPerformanceWriter.hpp" +#include "ActsExamples/Io/Root/VertexPerformanceWriter.hpp" #include "ActsExamples/MaterialMapping/IMaterialWriter.hpp" #include "ActsExamples/Plugins/Obj/ObjPropagationStepsWriter.hpp" #include "ActsExamples/Plugins/Obj/ObjTrackingGeometryWriter.hpp" From 26d18cb6c0dbff65f5a708e33d01b65fd68bb3c1 Mon Sep 17 00:00:00 2001 From: Andreas Stefl Date: Fri, 18 Oct 2024 19:14:10 +0200 Subject: [PATCH 3/6] refactor: Rework particle selection in Examples (#3742) - remove `TruthSeedRanges` as this a duplication of `ParticleSelector ` - enhance `ParticleSelector` by also input/output final particle selections which are necessary to access the number of hits - raise some pT cuts to the usual 1 GeV - handle downstream changes blocked by - https://github.com/acts-project/acts/pull/3744 --- ...ance_vertexing_amvf_gauss_notime_hist.root | Bin 48549 -> 48441 bytes ...ormance_vertexing_amvf_grid_time_hist.root | Bin 48986 -> 48857 bytes .../tracksummary_ckf_hist.root | Bin 40304 -> 40310 bytes .../workflows/physmon_trackfinding_1muon.py | 10 ++- .../physmon_trackfinding_4muon_50vertices.py | 10 ++- .../physmon_trackfinding_ttbar_pu200.py | 7 +- .../TruthTracking/ParticleSelector.cpp | 70 ++++++++++------- .../TruthTracking/ParticleSelector.hpp | 14 +++- .../Io/Root/RootParticleWriter.hpp | 6 +- Examples/Io/Root/src/RootParticleWriter.cpp | 8 +- .../python/acts/examples/reconstruction.py | 74 ++---------------- .../Python/python/acts/examples/simulation.py | 54 ++++++------- Examples/Python/src/Output.cpp | 2 +- Examples/Python/src/TruthTracking.cpp | 3 +- Examples/Python/tests/root_file_hashes.txt | 4 +- Examples/Python/tests/test_examples.py | 9 ++- Examples/Scripts/Optimization/ckf.py | 8 +- Examples/Scripts/Python/ckf_tracks.py | 8 +- Examples/Scripts/Python/full_chain_itk.py | 13 +-- .../Scripts/Python/full_chain_itk_Gbts.py | 13 +-- Examples/Scripts/Python/full_chain_odd.py | 19 +++-- Examples/Scripts/Python/full_chain_odd_LRT.py | 18 +++-- Examples/Scripts/Python/hashing_seeding.py | 16 ++-- Examples/Scripts/Python/seeding.py | 9 ++- Examples/Scripts/Python/truth_tracking_gsf.py | 17 ++-- .../Python/truth_tracking_gsf_refitting.py | 8 +- .../Scripts/Python/truth_tracking_gx2f.py | 17 ++-- .../Scripts/Python/truth_tracking_kalman.py | 17 ++-- .../Python/truth_tracking_kalman_refitting.py | 8 +- 29 files changed, 223 insertions(+), 219 deletions(-) diff --git a/CI/physmon/reference/trackfinding_ttbar_pu200/performance_vertexing_amvf_gauss_notime_hist.root b/CI/physmon/reference/trackfinding_ttbar_pu200/performance_vertexing_amvf_gauss_notime_hist.root index 26472832eebf549bf73f890ecd9ae4e63a36ae89..64abc1fadafc7b2d4c68e0987cb93e581a30a9fc 100644 GIT binary patch delta 4682 zcmeHLdsI_L8oxILe8dv8zCwTi@0rxxiz<*-Lq%^*t7r0IX9X4&D`I7 z^L_LE<|DPQc&C5mNmEs-bc%X%o}#EYit6yBsIwZTy^ncDF;5|%`G{xQ4=Bnhfuem& zb@rd#9sh8j+rEqeyHmG8aGQhR0)=L&G7pJO%2K!ZGhe7lQ4^{W1M@J<=&ylB1g9?` zf@T>ZAS1th(r$>#P>J3LuNoxqBYF%in2x~^3|bjk@K*$mehxn6wMFHx*}ZpVtNpQo z;kNMTt5@oF83&fo&INr_2dFb2m#QaCRr;JC_uOsw?C6PZhpmSE_f2!)n`v@v%SZVI zm707XO2zy|-bzulJ6<3HTkS&86lJg-Y787{0osN$0{ExlHNKc0`#bZj-?7XQ&u0mM z#y|v8j06T~D_e~M&^NqnG@Hha*Q4T`*by5)u*om>M6eTETQ_5e}6fwinOxn-40vEdEMxPAb8y?5glb=~|9avLLupc9;V! z8i4}eS`HxB!FIWt1NhB{{(i0j8#zE|54;h|oe}mJ4u`P-j%UOaAk~SWcf-W82T8G&k@X)cqs`)Numpt9+oL)w>KjGnk~Nn^o0WuNTOBFDwY9TtaI4Da*` zA9XKe<-|U#qb7^H=bEh6j6Ub{Nxo&?u0e73jWef;?Z14vX#Wuhb&98Y>kp4BleLKr z%L=VKg zH{r9egx)!kubaBR3hr9pZvTf?2iV}=6)C0LPQHAxX8n{X=cvE;X5}nc{X@VGQL>G8 zoiNGCNeeY2_kBi|b#``kOU0?J0X4!I=AoM}9&4F%r#;uHZc3nA!N9W4=Pe`WU~|@! zGq0Ww{;iE?u_4j0DyMMlt&_Qa$J0tKRYxAXe4h^O*?z=HkTSYSFjEl54>#O1VYv0L zpWtal6^qD@L;QNuo=)`U_w47cmB1zFYalH%FufvRup8 zOMe>ve%I~Vr<;rZ)Yqqa^tB}L>Y+PLgSO*04KDV0ke@e3URf~zjG|vCPV4eE(hfNA z6|ygj>Z@l}w%$$Xx#E>jwP&?ur%#UhHSZrC=UvLfGZ@w8iE-ux;Q(UsTX_RCw@!i^ zR=pxIpN^vX@l%+&dV~No5fD8Lx5b$A@PWifCDsm%KoRVUwc(twbUAnw$I0c42C%S| z)6W_QyyKlQ3C@JLM<9#Igz|V+KRnS=Ypw!a^E9|I!HzKF{7tlk+Qd~HU~Lf`n-t3d zlAgir06#X9YXtY# z76D<4*=%%e;C|Axx7#;LPt8bA#Pb;2b9$GZ4qlvtZ_NYyEg>F9_4M;uB;YH)KndKhT_T(CS1Xy!giMV>W^e(A47;%AFz`Ofabc}3NIc0g;mA?oTqgos3Wa*JuuDa-sZc<4 zQ14eWI9T+Mli|e?@Y`ZbGE47S3AEWEBp~ZfxNz5K0^pdH_QK#Y2?1DV!Y#mx0IVlr zU4@9lfn7NT-riF}me>1pDlFS)%pu246~T)KrjeOAeGjVO(7_%8=-p}#?^acFwxcnI zr5bm_g}0+!4tuqMWCrU_Xm>c10N8|DTUb}Si2!(SM~*`0I<~yRj;oJ^H|r~DAxgE6 zP(+!3AefS~EXNa^ZxG^oxWB;;f4^$@Z;EkqpgA@MzgOmFhJrr}=PT#RV`<@ zBalYr;5~B+x$vBur=V&^0{7){fA*?Y^O2M)5B^SVmWO7|MR4D5FzIT|Lyya~-v$j6O(jqLxCz cJmshrw~l!pqShxt%&$5VP^-f;Yfd@!PmS{4)c^nh delta 4749 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 OsvmHxqksLJa^~NR_{^CA delta 4721 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 IFd6i}06v*i1ONa4 delta 15761 zcmb`u1z23mvIaVXOR(UsK?5YX6WlEjoIrvFNN~4>YtTW1L+}I%?iws;un^n{8riVm?s=E559`0v7oT$BxjUxzj*a`xHOhBMCTM#Jq z4Eo;{`bC0%wGp5{rXUdV6bQs@4gx2Alx_;t#o224v`J~}sg=jvy3QIwOUr(1r&{p&bQG?NG?_L*C z685?{QG|f5BFZrsB#8)e1y@0a6g1TEx}!KF?^X2Lw?>2q%dQM(Gg@XHG}ACj2guzp zz9+-$RrFv72HsNDm=;@3SwES)M!g8J-x>VK=J#E0n4VGKG~FSXIJrm3Wx;#!)MHR^ zz3Fnzmm`ylaa>vl+aR0ZW?vrHRBtlx{g%FY;<`ySsU-LnHXrsj|QnOGVc8Fw?INqrLl-*&2}Ci?XzVd^q0|M>bPXsFds5E#8fu^mBRe=n;uN{`BM}&F$^!#lv!^jSr&f z+31lAf5Cq~;uoMr#V9dBAh7x0B*W$j3;Laeae=@fki;m&Hj-MN5e6kinB+0t)k~p4 zrOE_BL-w&Gild?Ns~7g>P(cR4J%SO+!U!4e2&FlG6CybpI$A)=`6yyk5$}NoVO`SQ zQC5hGJp!Zu>lmmIpm2QzNf&Pfk{K&$m*X+0z%tWhRY+7`MlbJ$py#)dnY8=*ibeb4 zlPKAW(iTE{dPF0KfJuUlfysnn6eKYMMwyKUW$D3DIhG;^q<=ydAL8~IMi-|#`hbt^ zE)Ex9?F!1O$aH*^^kpFvK9?G=jnAK%R+b-+*=HOC+Sq(X4xJcY5CS&zwO+zr=&u=} zfS^fs08*vQD)$Y{wJq9~OCtObixexpBl zh=D>@Jr{cEruSpXH}tWQ8xh7D6)xtzdw%ymv}VG=nbl^*Xn>XzsWG~Ob&!{%zUELr zB7qCRw*4l8(GLbC%*x^YU%2M#Zo{8{(>q3w?XZ?iWm9IYQQX zlC4@*YEf12Y?|f>nN{h#1_lY^`&Y-6x4!awJPRYhQZe!^;(kKToFukTXa#451sZ;1 zt?zliN5$0alu}6hy#vXT02*KFqh1+l3dWN?>usKQ)7UK``qtbNbbB(&oAY!ma`ba1 zPsp$U)JoM@*F1B4yc0{0h=kGypK($_7v5WO2b~Q=xmNiTZ2H&d`_J_0*Pb%L7nmb+ z=pm&sN1`IUtKa!SJKY>I-BoeB74+RjA2{%M3s4GqcO>4vk*M1(y*iRm>D*pG5ltnv zlF9Ld7|x+r@LH)k7iRNf6G@7d$V)d*I}F_e+zi~lTvzMrXWLP8PNWrK!XrO4kAL^` z(^j(4JG8Qi$6oWt{zey#TVY$%CF`jj%1BDJQp*K!o*LW+c1_8$hkLcw^>fz6Z60m4 zONw4>MHp=SgpJQji`vHf`AVL+qy=572x`tJ^C~m7P8qq6@~BM-;Z-ATJpj zJ&B^ZL1yzyM`$|M2;mhz2R{#oLM8=68oSeF@fsL7?B5=2u28@W5sG2SmNXLWT8WKE zmS6tp-T-f>(6d@(C%r^tAA3!srbDyOOuaNtSLXX^JD6kWNtQ!}!&bA1+*5TTqk_q^YExY-sj;n}Rv*lMLv5LsSOS(CJ!&-09N zc9R3l^Gnx5;W?zvw|Wx9C+5wUSvH+Dd%^r_so(j%S1e3VJ$5=eCkaO&@78dOdaMyn zvZ!)m<5h-I3!`mV4DI>*wOfV)$Of_Sqp%w#ogh>1NbnAhs0O9)eTWSnSXEm;mW5A8 zjbOn0(M2_uw4TasZt%wTV?KD@fL$ifrnVW_xOcHD)8$0spKkYnz3S>Wa}vUOHfB!(>eQh+?m0v!QSAxOgO%v*A3C zMvh`HtuRKnO7yszMtJEDRo2`;A1WxryFUH0dgX=j)h)vX5aGHl8og!tZr4_H*?Vfp zojGo(>SG@916Xx)cw7sx+1*4OO^6F>UTsff z<#$q>!Luw5sV;vUC)?`x_`&<}YWSt^CzJ?Rv{;1K=++Hm1~`s|bIF|Qqxpe;uJDJm z4rUxKYlF1RlF5upneq$FUEAhrNJYzfTh{=2lAcuIQRk4hh;QtGcligiWH%>d$~SNZ zW3L-UJ|Q#voBJ!XZ=0x(LIuV<0Fl#0#ItC?;CTc8<<7E4OX$!WGo)7Ox$+Uen5RG_ z0*}Oqm3f%;W%kVqAuG}Dc1>x<+5XkSJo@fcjo-xfkkAE*a%WEUVXw{e3yXa(Zvfcj z9vH%!ygFj?Cn87D7yGPhswUEO*n{Sw=h3?v;@}$>$i03Xecay8=%yvN4>VF|Kw{Km z;9QFr%+=UA>GbWFazJJA3N=xmFYyRd`3ONp;S2XyT~ceEs6=``r(pMXkWs6x5v^{rL|X2^ATTj#z8uDf{yw(8|>VF{AR2uVI%T= zgf$ zNZ-%t;NflE#q6GD?Xp_b0v|>qwoa?BC9=F-=V&2#bjk|arExF-WSESaO~I;ar{(l^ zv-#%_dXEe?&Vvfp`*u12l%0p~^6Txz5H-v}+$E<41s4AG_T#}>6KZ4$yv&iu$SDV? zjoJ=Sy#ns~cgCu}`4_&r-HCS6pL~rGRDc)5?!I-C17w$RzlOaZ#`8m=5$VCpMj`Nv zkZldQUx|IMT=qjrA~x#*>h?7P!3dPGRcQo%D1O=n6%Cw=pGYVJ9m-mgZ~F&l25{~N z5K({krvt->{OllrkKOMW@MqRmq9K`mM110by}B*z!E~bi1@Vz4U1k7Y#t&62I%d82 zrcXPag}}X~Co2O4CgwxdPY;{U%j?#Q>n&b-4w`_sxi~#P#SBYjsKA}<47WvQJ>wi} zJhwsqZo{+V5Vf{#eRSNK1CaK7Y0jB|c+pzo3w}%W=5-cJ#44>(SpTtRF}D`agF=aL zMB7&UGQ6sVU!(0d;nu`Z_Pp!ZWwqNqzH_AU=^-GhwiWL!?B>@ca@;)RZ19!)>mEad zjFc9pf)GvWel3xR%P^Ws+YOhkPc^hI zyq*E4a_I~6IkClOAgMtQrQb`Jw! zg5;CWlw`G9O5q&0hath3vjdm|z}%G~R;A5gbt$>Y*1XbW0)-D@~nbbyC7g((~k-1u41BDr~VexDF=i?qd3r0Pec@rasS; zwa-pRGG6}sYpsXJsn(jpb1xf}nnZq{9ga<{>hlI%Bsr|dI~2>Y4iY*H8k`)zdut<5 zlVdaFblO^H>ht=ZzRT0~dcF+Jv^Se4txi@$b+LRIL{!CNQJu@-g`8_Y`RvHwo=>pe zbL+YCAKQ94*jBr)Gx6C=+8gNlPNm*I|GrsaaAj$qQfYk&@((Rwf`s_iV%tGv zQY%-vIr$Lxv2;Q*6du2vU3r*|!FXq5Xes}O2Qt*zeRXGxKxO?F43hulFDY56tKA_) z+89sreRzGDj-&CdpFA>CRaKtSTL3Xs4dOjRXH@<`N3ziViT?DBzxb_WA|atcEiM8t z+e}D;wWO_HDktRwR)QH<@j-{V{`7XD!mz(KYZ*N@*(UEGHrh~q*#+2ad$P^c zYqWSDo?f~fF+nr;ImT7KU%NT=TmSTIg1vL{=6N$HQF^i_k#n2Vm%uNs3l z`VPy|1sK?_=(0F$U`tNtxs9`%*yhaJBe5a< zQb_iSgYioje@v!FSM12)kap_nV;k?i=`Hsw^6*m;p}ETwku~L&V*z|17EZ=tzup@w zBY&u4?}yi=S5Yj|%AvQBTT`=Wi*C^|LI2*-=}ye~me_La8`FvceJ-}pmDBFpcYVGS zeh0)%)6;!)jCzHiiYZ0kaA~wmY4C)J-(pJsl-{zuh1YS&7Jy>rf3a}^$v=!-C}h^b zAZZw6p0-%wi(%i`vooywXTHpO<|*}V#Za}^i2Z&@@9JDrLlbs369RxgVu`LEJZ1ss ze1n(}E_H)Q{j7}RTZj=UM+2vWn=At9dYkv97pG0j)D-PX)FUbrL^L>S;~;AXA1kW-X{OWi z^CNnc5|+}q$*_n`VTR5PuQb9rdLv;J_V`lfQrRPEyX=dgB}peJ9!(rx`P&}W2&AaQ zf2HCDz6z`wv(H@EC^C#N^a(=Sd0Ka@S8TmkRdl|K_qfNCr_naWu$1BaQ%k-sFMVMt z{uip53y#^^@syT<+>u-2J!$($!TYb}>ToOTTtW{{u_bwdhT!ojuWho?9dadJ(foBC z(G!t~i*exWW8qwj|C(XM(B-a5BrBoh1MVYa*gbO@oN9x6JZq+qa4O&lD$>QbN>m7x| z!|H*JqCA%I1bImh=2nHVBfy*n_0#ps+bI@>+~$T_aQ~Gu&f%$O`WS(Y^^D%x@eY+) zsMT>l{5RC8%U6`0YE>*sK7@svCR;tvyNk+?Z&{O+$ypwzb>Frqm9PP4Yv0i}D~DFj zXq@Qg6WL$5o^6Z{b+Ff^dWu}TpLycVy`d9*9MhWts)_y)JzliTsUo?ty7{a*o=#4b zs6_Cj^Nb2?GF!fLVVR6zfz*M&&JrrF`_jGRxPUm%%Ba(>@$7_#{-USSSMiBFzV%^t_DdaeA>>oe$i4ja zbF}j7X@?+{RCODqNtvMK)5VK2uC&uGm!88zVIHB#Js&r>-EJlT<2_qKDaAc4^5n#G zzV+(Ma|*1;ug#)1E5)}^eEe6B777liEg}w68*xf^VU})&6lrmx0!HEBrv)Ernlq&? zVheT0inw1Yc@`$UvS6wzOQQIio^GRh4HC~X1Wb0ao;SJeW81hF`)S#wC*O`qGP~Ll zq|aZOo0*%ryhuia#F@)q6!b`TGcqJb(?rF4 z6BGKBxp!)Q+z)NX%%cvURL(3Kx_2PTEy_`SUCw1^;_Z6XJ!rO#l-m)yf)uQmUJ$SmjP7WC7fUS==%^qE=id~^xFzH=Mb$?UEp5z?m zM)EIzC&m)8-imA_T+rdfGw7?LaesaYJNU$XPY)yERQUR)A!HuT#%gL$*kE4L8z~jZ zTn!+Q};k8*}Py95Vl9Y|*NXFNdlbB^^mdtYwHl(iL$f6BF=g ze0xT>;l(bdg6PC|L(+M6&z0inn*B+l*yP-h8-d&W(3UbyWX9kP*}N6#++kr&&B+^l zPz*W#&sfGkgfgJ;$o*}q3Mxp5VFxnsVu_PvWClt_b0MLl1L&V+kPvVLxg)4w!rjNm zS%QD;XIuUW!sX0!fqaG9MiWm^_?p$2!S5qqgP=@FBEp;0=r*9B!!c z9BQIcD-1XfW_Zt}Aix}14ygSVEi zGN!aw=K8-2*H$b}wGj7xv359|ox|Z(psuEPkX~D5NgClkaw5j!hmL!!rvE%%^5`-d z9{1o);r(H9b>(`FQWl$Oo<-7Cr@0>&k;|)b%b&xS`2{C{U2>JLkT=&LGk&Q#j#^OvTo)=x8ZHB!h^j5qUtx<6AKK%thV znT>_nAfTxk!P(>QPVVW5Et1r6Ol9RK5+cHdLiy?^Z^lpWS+31*SR^7;n^d%@IO|xG zzC`F&W5jYHKoar@=9X<5)>J|>NV>xF0xI-XPmZBQ^)!|v)9qI<7xfL~cA z`y$Jas)Q!nUZ(uhh?J_n|2~dknZg(;w{C8Y>X%vhvQN{ZMs4AlRcUXkr&$36oKAVW z!Q?&Jd#K;}d=FFhQhJj;hUyg6@*b%dynCsrA@l42f`a>*W=f+T(ix$~cr>6vSDF{C zajQU(s3^p)LZ6WQ%75t-55bPu$c(4;K#ibWVIYms1uv1R&I6a0=~3hLZP9Twz7%G%Qx@T+CF`>SbQ zG|jcWDV-x88)sa^7T-@PNN?};>tAC;##RrFge?Vzil}Qu%F|pO3`&vP*VscUe5?30 zHJBjHPMW*yGw*eBz1JJuW{R$75S_J*R6<1&gyBwnbKFvX67hinB*k_>1!-b|>q<(q zi7#ItB~BsIZJY&h_4G-y9OJd_>P0yRyqOqaaIK_ihQ6?9)r8n|O?ngmRfW;TdNF4R zxdv_1#^^}wDbj!fNYt8!O)ds(|4VUAm2`3HphiT3$`fYhb>SJ*^|ECxu6bl`{ zvCzcsuZGu^;Vn1%+58dFJtP5QIwVTrPCDw(Ph4}~YtV({aXn~P`t}(Z?i4*hdOZCB zAfJ+K4>_E3upaG_xtB_R>XN>mI^(eCr4WKc6JQI!giuMS81KMTv-g!ou68I5BK~xC7ar-_8i)k>&AWhQLyqH*g zXau2Jm%rcouBDd+nMum)IqJ7+3B9c#3IIXEA9CxQ+2l~>waKL2f_34(u-JmJ((Ro& zZSFx+AHQC3V78gI?6iGWKWiHdEKZ5Yuvikpy~A0~UkcIK(;sb{C#WO2W+?Pfm-lKS zkC?n1zj?l2C`Vknm*agr9cR#|V~i_*+3tp}s+r8WG*pzX8p$mD33Y&xw=erN9&pg~ zLzBKb4tvx<^Kb`kU3TNVy&}w3r%F&|Bm{^fV2kQi|Bm|*AzB;0+NQTVs$xoLdG zyeaap=sC-s(`lX$**B*FhFBz_8~QDW{&`bpb4DK)b;;S7fU$1M z;cZpcwYPfnY3~P7Qm=X2oq3Xj9tX$k*D8`)<~qw~jRtQ0>xVX8j%sOZjV^JIrbXUh z>!UDA;6#P7E&&ctfHvO#)8yt20Unq}DiIr4qv*789~dd`>8i$bS)aICX0GgPEM-*Fed2NpqKzhkCF zBxD~#e3z;b0S5KJ-=%8A46y`2O*!+^s_!QYGGy&)?fP)SqJ@+V{DUJ0p3IbD(iZ2&D_32xV9L zCyfuK{!t7uXs$?+ElqhKstdWJFfjMwa2+8qv&)npv?On4+!@}D1JC|smbNvF z#88XJdz5%@X0a50oFet4+`RkN`s}dvBS0!^1+*@OU(h~8`tqu~JN+bu?UO6#FyI1E zG}NfXZtAN)$i)O(wn-GzaEk2dKNTxgv=JCYn?N}>K6`+Lq8FfR18Gzs!Z|@{2&8SV zwQbh~(?49Rw8h~!d;k?E{<<9RK9)$30Gy@<=ovHR>pK`0Y3$s@H^@!j==^C8tHl`eNjsASOFov47&3 zl{%DXxWHpWGYiMNaL;ef#VRO>t6_J`3_J>@(7>jCK`mC|Udx1z{6PtEiN+sWv1gd$ zKF1i1eHMBaqo{;ors)@jfXWZgww&uARIl&{_&Iqikt;0%&IbUqr2SL}oYyr*5@nda z@L+wTEXrhz){%IA*?i;BcvV}D>Uf|JZk*hxs-&1AY`RU}%PA}sPmN6#!Bhl+502qH zCeOlXsQa++nw_(-7yb<>!DV*y*ib}Zy&-4Wp_F&sGBvDl3DJkiI9iApO~>mLrL1`J zwCV$U!SUujz@T7HECP!w?soR)dSLKvb#%!!u@(CT<%^FwfztN*LZ0N-3mw40lj|Qv zFEw)Nt)GUQ1%sN5@{4IIywd9m{hue#alPEYJF)%Th^w9xe7Hd%PgyTn%s|(nw)o+Z z_86EAg|G_Y9_nO(-3vG;pJ~$m4;wSWTgETWBb-(v-84-!1p`Iaq(a@o`eRevXzE*$ z+l2iO<$7%hbV|`^+sl;U*-)>!+ldzgY<2nQ9nmiX*Sf9O21MB4-+9%&9rOf|dfGx| z3)~5lwl0{ovE51A8zP8G9MK=r)&-Nc-#o*n<_N>Kv?IL#fHhlR5{pbcn+HcYQ*tB| zu2;1d(Gt&PF`FQHM;GnQ1;`6zx5$95loa=Tt`rNkE zeAf$NJ~+0+GHY-@k4#lYe{{B8^jR)Fa)RU92Eh58Me>Zhhz#*fPgin7>|dbA1!8A{ zo*xAD72&ZW?an-BGj(Q{;|6blZ9O;o7Ot)lJ?{Bs^4T#2@=JuGSvXg4I?j3{31P+A3euj*bb&Xaug;wihya|t*O$@SxL(c?5h62TC) z1`>3w#;21=kWzFV1rUfpHA3o_{p9#ZJxA{q5|kGiqZXovCxTvO*goZ>zvuNryK*38 zgH-|fl|z1?0Nc5jzf)d2S4?uo%XHpksT+l#pZe>^j1nr^k=Lrm44TT=<{q;%_gB!3 z#<>yuAIBgW=@Wgl_nv-f{R+f}zH>MfT1~uXu6a~DjExj#jjznkg+a9n45~)BTNq+RWhEYCca@fY6heC`73_y8MOMkD@pDMkN`=f( zb&M?xFWe{|Gwd5$mA}wPo02553%OKh@BZR&;b2K*SUAcO{qxuc8NG+KNyz7`&6lxX z6#TGj;YI!M!KC2&RvAieQJ>j*2#bjWrvqev+r1ejt{Q0jln@`-#cC9@6E96o5|d#6 zq>2kJj#|=7qfkEkGnKY3>ni%OLTo-E9H`l5=j{Ww4DsG-#oKS|9ih5P5lpx_KMvWP zin4Z7T;k@(#sxQv_6j#G4-CjhRRp{X;cU^0?VHdcj5tAGCA5P`QJf*hKz!dBd(XKRFKW`@ip``(S+{J5_dnzLmlC zsVAJNpn~($YWv-$TfxU_JcH`%E;sAx9z%yh>m2wqPknj~#l+}~=rV*}g0qeG2RC=y zE$zAHDx>Fmq8}pn?q!Sv5AGAj81_AcIB^@19@XOoBCE=4M%uS@UsRsH&zmd zOZ7_I&o1X9pu4|kHW;gb$YDo{8*Ou`rhx5{?kC-egX3j6-F`s@z(Off+S5rkMV0biU0~tO%=C<(P4+-@L{Hn_=gtDO4TzumHlzL%s;<1Ga9B&U#-@! zh6dNa`66suhhMGVVD?G>G1c>v59!F}t#YP^%L^z;2(vB>O2l@%Ek;dP=VBXd8_s2v zZ+(R`i;Ye1&-gZ`6sLF)oimqFIG%RQBJ-YJU9N7@eshWAZeuXK_UDFL@Bgf$V5zvX zU{EDYjN_UVQlO4nlw2Hk=TrP(ww;CSZ%;pJ%EzB-=(R8>F?web;D%2OqdhQljgXl4 z^Kh~wn3aO=+9lH5pc~*5&PrmZb~+4sS<6XgDcCIB3?8OJJnThL)L$oNE5-6HRI@$q7cI79E>4_!wz>3W3AsxH3PEoG%v zm$6@=@PI{LPWW?3UrANj{_#nMZ_`0-f&fkV&y34;_tq!6 zyr+$vYDGS}$>4v+#T9;U&(BOe(&E8Z6fKxQdYn=Gx%73AUYog*;J16#zU-|8KOgjD zB0KvT)SS_)`p^5?#OwuA_$ddH*xn~IE$$|Nc0Vd;A|v1yEC8v#d3YpK?QS<}zlb96 z=6qZPZBXL!^)+1WC#z$irj?`i(^WGF!04>2-&-H2A0(gh#Pn)zy}f7Frjmt}YW78E zc*mTk@+K}ve(CWB&MOyhCQW~JUsK+Vt5ZwdQy+Mv8skiGgU6Pi^IjIb)1VFXT1fuA zDUo4#jr|Ey=|vx@c~Bg5yZ8?b{OfvD5KIP4gF&^w^mvOE1Zv>7DCuGl<08M|raia;%tn`<1Ybhfo1w`>r)^>rk8zpyg%l^Y9lX<=na*LFk+u}!SgV>kGH zu3tEztH^0ngV3qSsZhW^JRWMG0wazsvGJ8L3tX-PssF%h)r=;Cj9$&j44*^b0UjDl zVbC=vqwTEuN#C~Jhx^eVq+2oj8lMwSVc_bWPh6~p3fH|tTWNJpkwA_yg%5Jpu2@4n}AURg;bOKhs1$4<16rp?)2 zws5bM1KGUuE8(xc@pmoWOw}9$X)aOBv$eK6%eyaT-YCp5y>z5rfTMTSc>P(_oT6|+ zZ%xokRovcUxoc3D6~d4&4~M$xh-X?1={3~>dbn`c&T=7q;fu-L^>H64ZIb~fNYLu zk{v0kFkixzFpOJy^a(LG8PdnLuviLZa7mjc#wC~IYVhWKa`F?Q6m1zQw{{xHygj@; zu4C8p9z4LvnU9(r@*sQ3WtGZ#acMXAskS92nF@Sx`g19GV;*-Z|LLC&Ji_11l+Y;H zCNZQv6d#!RQwhYjsHoq$@0CXHf&z#l{L#s^S462^x+}6uuETU9Mh%5ocYqcBZOni36Bb+yA^+OX(fpf;%{Na)U1g`QS{rh3JA(?IsZv0!I7 zz;7SGuK%~ACS;JGZ&6|N*nI!nVG;U!U=^6x^YG3dhLl9G!5;d5m;Mj@-?G%9VE?b_ z|Ih?-DA|8c8HN)5b$kVS00$?E82HDe$-gDcL31Xd*42Nc)%{0S9hB(5r)WV3@GH^u zclHl7J@Y@(e}2F6e@Oy?()}+R|9|fL|L*f2_kdyP0sr5#TmNB42-@F&-(P^v*01DN zj^8r@0{ugF>pw**Ayd(m+;?Y5{>b~i!#wQF2&$=~io~yg$?vK8+vyU;2ncHo#oxU( z$dC;_#3}~;ucTp^!}g2j4_^&Z6hj8P|Cg&q`&Sv}rTr@Z<)G2P?*HMNL3Cs3VC6qt zGe~GG4bR=^|M1Lyj~>m`-rmqu0~YUrPR~F4YNY=^Ij&^5un_RSt{{-6P(nx<O1LjGONNelgB}?yp=BW1&E~g6<5!$?8q07@ zSexYUc`y*T(lkS@jaY_#MO}uIiRpP1tpjqleb7+J#h(#^L3cq<_;u?EBG1|NGEfw< zg!WT?kyZ*E#z^QSrb7t#TFl2&LQas;B`?i!%}TwQ+j`Q3IxceY;c72P6l>3*vBrQwzXE5_6NPZFU?(;;GunMLj%Y?K zF*AgCzAL+$h)p$Te11C+9yls40-Dlkjo3?c@b#~vku%g{g(tjzLP+oQ9%|Na*gfG za6Y_3@-SI3$=ne!M+e(-JYB@9KxTaW62Dd8iCv*Cd0O}a-5K%IfFA@Z zgOCa4I~nX%kbQoD+13cgZA0-31bHpwM0FyR2^06poSG}7>Len)OLXCgoEJzf0 zB(CZ6P#|0|lP(CvgCKj#8wc0YWMW=Jg8oz*)J~j42$(4*V8kk1~_NUI7MV`_2bxM6V-_ zL%d9$D9m__iS?qR8@F35X6Ili(f|%Sp~)(o=!gB;Uxe^lxca?+#JV{SJsjeQnqN&t z?tl;7n>=ewGW+hfmiMI}8t)X`X6Veo9YpC4P>Y+bnHK>rV4m`z>) diff --git a/CI/physmon/workflows/physmon_trackfinding_1muon.py b/CI/physmon/workflows/physmon_trackfinding_1muon.py index d06f99fbdb6..3c87bdee32d 100755 --- a/CI/physmon/workflows/physmon_trackfinding_1muon.py +++ b/CI/physmon/workflows/physmon_trackfinding_1muon.py @@ -11,13 +11,13 @@ EtaConfig, PhiConfig, ParticleConfig, + ParticleSelectorConfig, addFatras, addDigitization, ) from acts.examples.reconstruction import ( addSeeding, - TruthSeedRanges, ParticleSmearingSigmas, SeedFinderConfigArg, SeedFinderOptionsArg, @@ -72,6 +72,11 @@ def run_ckf_tracking(label, seeding): setup.field, enableInteractions=True, rnd=rnd, + postSelectParticles=ParticleSelectorConfig( + pt=(0.9 * u.GeV, None), + measurements=(9, None), + removeNeutral=True, + ), ) addDigitization( @@ -86,7 +91,6 @@ def run_ckf_tracking(label, seeding): s, setup.trackingGeometry, setup.field, - TruthSeedRanges(pt=(500 * u.MeV, None), nHits=(9, None)), ParticleSmearingSigmas( # only used by SeedingAlgorithm.TruthSmeared # zero eveything so the CKF has a chance to find the measurements d0=0, @@ -134,7 +138,7 @@ def run_ckf_tracking(label, seeding): setup.trackingGeometry, setup.field, TrackSelectorConfig( - pt=(500 * u.MeV, None), + pt=(0.9 * u.GeV, None), loc0=(-4.0 * u.mm, 4.0 * u.mm), nMeasurementsMin=6, maxHoles=2, diff --git a/CI/physmon/workflows/physmon_trackfinding_4muon_50vertices.py b/CI/physmon/workflows/physmon_trackfinding_4muon_50vertices.py index e1ece122c45..f6c3fe110fd 100755 --- a/CI/physmon/workflows/physmon_trackfinding_4muon_50vertices.py +++ b/CI/physmon/workflows/physmon_trackfinding_4muon_50vertices.py @@ -11,12 +11,12 @@ EtaConfig, PhiConfig, ParticleConfig, + ParticleSelectorConfig, addFatras, addDigitization, ) from acts.examples.reconstruction import ( addSeeding, - TruthSeedRanges, SeedFinderConfigArg, SeedFinderOptionsArg, SeedingAlgorithm, @@ -69,6 +69,11 @@ setup.trackingGeometry, setup.field, rnd=rnd, + postSelectParticles=ParticleSelectorConfig( + pt=(0.9 * u.GeV, None), + measurements=(9, None), + removeNeutral=True, + ), ) addDigitization( @@ -83,7 +88,6 @@ s, setup.trackingGeometry, setup.field, - TruthSeedRanges(pt=(500.0 * u.MeV, None), nHits=(9, None)), SeedFinderConfigArg( r=(33 * u.mm, 200 * u.mm), deltaR=(1 * u.mm, 60 * u.mm), @@ -116,7 +120,7 @@ setup.trackingGeometry, setup.field, TrackSelectorConfig( - pt=(500 * u.MeV, None), + pt=(0.9 * u.GeV, None), loc0=(-4.0 * u.mm, 4.0 * u.mm), nMeasurementsMin=6, maxHoles=2, diff --git a/CI/physmon/workflows/physmon_trackfinding_ttbar_pu200.py b/CI/physmon/workflows/physmon_trackfinding_ttbar_pu200.py index 172fa55270a..c8b163c9022 100755 --- a/CI/physmon/workflows/physmon_trackfinding_ttbar_pu200.py +++ b/CI/physmon/workflows/physmon_trackfinding_ttbar_pu200.py @@ -13,7 +13,6 @@ ) from acts.examples.reconstruction import ( addSeeding, - TruthSeedRanges, SeedFinderConfigArg, SeedFinderOptionsArg, SeedingAlgorithm, @@ -68,6 +67,11 @@ rho=(0.0, 24 * u.mm), absZ=(0.0, 1.0 * u.m), ), + postSelectParticles=ParticleSelectorConfig( + pt=(0.5 * u.GeV, None), + measurements=(9, None), + removeNeutral=True, + ), ) addDigitization( @@ -82,7 +86,6 @@ s, setup.trackingGeometry, setup.field, - TruthSeedRanges(pt=(500.0 * u.MeV, None), nHits=(9, None)), SeedFinderConfigArg( r=(33 * u.mm, 200 * u.mm), deltaR=(1 * u.mm, 60 * u.mm), diff --git a/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.cpp b/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.cpp index d9248358160..5fa3ee0e4b2 100644 --- a/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.cpp +++ b/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.cpp @@ -29,9 +29,16 @@ ActsExamples::ParticleSelector::ParticleSelector(const Config& config, if (m_cfg.outputParticles.empty()) { throw std::invalid_argument("Missing output particles collection"); } + if (!m_cfg.outputParticlesFinal.empty() && + m_cfg.inputParticlesFinal.empty()) { + throw std::invalid_argument( + "Output final particles collection requires input final particles"); + } m_inputParticles.initialize(m_cfg.inputParticles); + m_inputParticlesFinal.maybeInitialize(m_cfg.inputParticlesFinal); m_outputParticles.initialize(m_cfg.outputParticles); + m_outputParticlesFinal.maybeInitialize(m_cfg.outputParticlesFinal); ACTS_DEBUG("selection particle rho [" << m_cfg.rhoMin << "," << m_cfg.rhoMax << ")"); @@ -52,29 +59,15 @@ ActsExamples::ParticleSelector::ParticleSelector(const Config& config, ACTS_DEBUG("remove charged particles " << m_cfg.removeCharged); ACTS_DEBUG("remove neutral particles " << m_cfg.removeNeutral); ACTS_DEBUG("remove secondary particles " << m_cfg.removeSecondaries); - - // We only initialize this if we actually select on this - if (m_cfg.measurementsMin > 0 || - m_cfg.measurementsMax < std::numeric_limits::max()) { - m_inputMap.initialize(m_cfg.inputMeasurementParticlesMap); - ACTS_DEBUG("selection particle number of measurements [" - << m_cfg.measurementsMin << "," << m_cfg.measurementsMax << ")"); - } } ActsExamples::ProcessCode ActsExamples::ParticleSelector::execute( const AlgorithmContext& ctx) const { - using ParticlesMeasurmentMap = - boost::container::flat_multimap; - // prepare input/ output types - const auto& inputParticles = m_inputParticles(ctx); - - // Make global particles measurement map if necessary - std::optional particlesMeasMap; - if (m_inputMap.isInitialized()) { - particlesMeasMap = invertIndexMultimap(m_inputMap(ctx)); - } + const SimParticleContainer& inputParticles = m_inputParticles(ctx); + const SimParticleContainer& inputParticlesFinal = + (m_inputParticlesFinal.isInitialized()) ? m_inputParticlesFinal(ctx) + : inputParticles; std::size_t nInvalidCharge = 0; std::size_t nInvalidMeasurementCount = 0; @@ -96,17 +89,14 @@ ActsExamples::ProcessCode ActsExamples::ParticleSelector::execute( nInvalidCharge += static_cast(!validCharge); - // default valid measurement count to true and only change if we have loaded - // the measurement particles map bool validMeasurementCount = true; - if (particlesMeasMap) { - auto [b, e] = particlesMeasMap->equal_range(p.particleId()); + if (auto finalParticleIt = inputParticlesFinal.find(p.particleId()); + finalParticleIt != inputParticlesFinal.end()) { validMeasurementCount = - within(static_cast(std::distance(b, e)), - m_cfg.measurementsMin, m_cfg.measurementsMax); - - ACTS_VERBOSE("Found " << std::distance(b, e) << " measurements for " - << p.particleId()); + within(finalParticleIt->numberOfHits(), m_cfg.measurementsMin, + m_cfg.measurementsMax); + } else { + ACTS_WARNING("No final particle found for " << p.particleId()); } nInvalidMeasurementCount += @@ -136,14 +126,30 @@ ActsExamples::ProcessCode ActsExamples::ParticleSelector::execute( SimParticleContainer outputParticles; outputParticles.reserve(inputParticles.size()); + SimParticleContainer outputParticlesFinal; + if (m_outputParticlesFinal.isInitialized()) { + outputParticlesFinal.reserve(inputParticles.size()); + } + // copy selected particles for (const auto& inputParticle : inputParticles) { - if (isValidParticle(inputParticle)) { - // the input parameters should already be - outputParticles.insert(outputParticles.end(), inputParticle); + if (!isValidParticle(inputParticle)) { + continue; + } + + outputParticles.insert(outputParticles.end(), inputParticle); + + if (m_outputParticlesFinal.isInitialized()) { + if (auto particleFinalIt = + inputParticlesFinal.find(inputParticle.particleId()); + particleFinalIt != inputParticlesFinal.end()) { + outputParticlesFinal.insert(outputParticlesFinal.end(), + *particleFinalIt); + } } } outputParticles.shrink_to_fit(); + outputParticlesFinal.shrink_to_fit(); ACTS_DEBUG("event " << ctx.eventNumber << " selected " << outputParticles.size() << " from " @@ -153,5 +159,9 @@ ActsExamples::ProcessCode ActsExamples::ParticleSelector::execute( << nInvalidMeasurementCount); m_outputParticles(ctx, std::move(outputParticles)); + if (m_outputParticlesFinal.isInitialized()) { + m_outputParticlesFinal(ctx, std::move(outputParticlesFinal)); + } + return ProcessCode::SUCCESS; } diff --git a/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.hpp b/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.hpp index d6c8440fdc7..de05bf621ca 100644 --- a/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.hpp +++ b/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.hpp @@ -29,10 +29,14 @@ class ParticleSelector final : public IAlgorithm { struct Config { /// The input particles collection. std::string inputParticles; - /// Input measurement particles map (Optional) - std::string inputMeasurementParticlesMap; + /// Optional. The input final state particles collection. + /// If provided, this will be used to access the number of measurements. + std::string inputParticlesFinal; /// The output particles collection. std::string outputParticles; + /// Optional. The output final state particles collection. + std::string outputParticlesFinal; + // Minimum/maximum distance from the origin in the transverse plane. double rhoMin = 0; double rhoMax = std::numeric_limits::infinity(); @@ -79,11 +83,13 @@ class ParticleSelector final : public IAlgorithm { Config m_cfg; ReadDataHandle m_inputParticles{this, "InputParticles"}; - ReadDataHandle> m_inputMap{ - this, "InputMeasurementParticlesMap"}; + ReadDataHandle m_inputParticlesFinal{ + this, "InputParticlesFinal"}; WriteDataHandle m_outputParticles{this, "OutputParticles"}; + WriteDataHandle m_outputParticlesFinal{ + this, "OutputParticlesFinal"}; }; } // namespace ActsExamples diff --git a/Examples/Io/Root/include/ActsExamples/Io/Root/RootParticleWriter.hpp b/Examples/Io/Root/include/ActsExamples/Io/Root/RootParticleWriter.hpp index 99cf6b5cd61..8be9f05b735 100644 --- a/Examples/Io/Root/include/ActsExamples/Io/Root/RootParticleWriter.hpp +++ b/Examples/Io/Root/include/ActsExamples/Io/Root/RootParticleWriter.hpp @@ -39,7 +39,7 @@ class RootParticleWriter final : public WriterT { std::string inputParticles; /// Optional. If given, the the energy loss and traversed material is /// computed and written. - std::string inputFinalParticles; + std::string inputParticlesFinal; /// Path to the output file. std::string filePath; /// Output file access mode. @@ -74,8 +74,8 @@ class RootParticleWriter final : public WriterT { private: Config m_cfg; - ReadDataHandle m_inputFinalParticles{ - this, "InputFinalParticles"}; + ReadDataHandle m_inputParticlesFinal{ + this, "InputParticlesFinal"}; std::mutex m_writeMutex; diff --git a/Examples/Io/Root/src/RootParticleWriter.cpp b/Examples/Io/Root/src/RootParticleWriter.cpp index fbd1333c38c..436601eb97d 100644 --- a/Examples/Io/Root/src/RootParticleWriter.cpp +++ b/Examples/Io/Root/src/RootParticleWriter.cpp @@ -36,7 +36,7 @@ ActsExamples::RootParticleWriter::RootParticleWriter( throw std::invalid_argument("Missing tree name"); } - m_inputFinalParticles.maybeInitialize(m_cfg.inputFinalParticles); + m_inputParticlesFinal.maybeInitialize(m_cfg.inputParticlesFinal); // open root file and create the tree m_outputFile = TFile::Open(m_cfg.filePath.c_str(), m_cfg.fileMode.c_str()); @@ -73,7 +73,7 @@ ActsExamples::RootParticleWriter::RootParticleWriter( m_outputTree->Branch("generation", &m_generation); m_outputTree->Branch("sub_particle", &m_subParticle); - if (m_inputFinalParticles.isInitialized()) { + if (m_inputParticlesFinal.isInitialized()) { m_outputTree->Branch("e_loss", &m_eLoss); m_outputTree->Branch("total_x0", &m_pathInX0); m_outputTree->Branch("total_l0", &m_pathInL0); @@ -102,8 +102,8 @@ ActsExamples::ProcessCode ActsExamples::RootParticleWriter::finalize() { ActsExamples::ProcessCode ActsExamples::RootParticleWriter::writeT( const AlgorithmContext& ctx, const SimParticleContainer& particles) { const SimParticleContainer* finalParticles = nullptr; - if (m_inputFinalParticles.isInitialized()) { - finalParticles = &m_inputFinalParticles(ctx); + if (m_inputParticlesFinal.isInitialized()) { + finalParticles = &m_inputParticlesFinal(ctx); } // ensure exclusive access to tree/file while writing diff --git a/Examples/Python/python/acts/examples/reconstruction.py b/Examples/Python/python/acts/examples/reconstruction.py index 371345a17b5..38d64100fd3 100644 --- a/Examples/Python/python/acts/examples/reconstruction.py +++ b/Examples/Python/python/acts/examples/reconstruction.py @@ -14,12 +14,6 @@ "Default TruthSmeared TruthEstimated Orthogonal HoughTransform Gbts Hashing", ) -TruthSeedRanges = namedtuple( - "TruthSeedRanges", - ["rho", "z", "phi", "eta", "absEta", "pt", "nHits"], - defaults=[(None, None)] * 7, -) - ParticleSmearingSigmas = namedtuple( "ParticleSmearingSigmas", ["d0", "d0PtA", "d0PtB", "z0", "z0PtA", "z0PtB", "t0", "phi", "theta", "ptRel"], @@ -231,7 +225,6 @@ class VertexFinder(Enum): @acts.examples.NamedTypeArgs( seedingAlgorithm=SeedingAlgorithm, - truthSeedRanges=TruthSeedRanges, particleSmearingSigmas=ParticleSmearingSigmas, seedFinderConfigArg=SeedFinderConfigArg, seedFinderOptionsArg=SeedFinderOptionsArg, @@ -251,7 +244,6 @@ def addSeeding( layerMappingConfigFile: Optional[Union[Path, str]] = None, connector_inputConfigFile: Optional[Union[Path, str]] = None, seedingAlgorithm: SeedingAlgorithm = SeedingAlgorithm.Default, - truthSeedRanges: Optional[TruthSeedRanges] = TruthSeedRanges(), particleSmearingSigmas: ParticleSmearingSigmas = ParticleSmearingSigmas(), initialSigmas: Optional[list] = None, initialSigmaPtRel: Optional[float] = None, @@ -273,6 +265,7 @@ def addSeeding( acts.ParticleHypothesis ] = acts.ParticleHypothesis.pion, inputParticles: str = "particles", + selectedParticles: str = "particles_selected", outputDirRoot: Optional[Union[Path, str]] = None, outputDirCsv: Optional[Union[Path, str]] = None, logLevel: Optional[acts.logging.Level] = None, @@ -289,10 +282,6 @@ def addSeeding( Json file for space point geometry selection. Not required for SeedingAlgorithm.TruthSmeared. seedingAlgorithm : SeedingAlgorithm, Default seeding algorithm to use: one of Default (no truth information used), TruthSmeared, TruthEstimated - truthSeedRanges : TruthSeedRanges(rho, z, phi, eta, absEta, pt, nHits) - TruthSeedSelector configuration. Each range is specified as a tuple of (min,max). - Defaults of no cuts specified in Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/TruthSeedSelector.hpp - If specified as None, don't run ParticleSmearing at all (and use addCKFTracks(selectedParticles="particles")) particleSmearingSigmas : ParticleSmearingSigmas(d0, d0PtA, d0PtB, z0, z0PtA, z0PtB, t0, phi, theta, ptRel) ParticleSmearing configuration. Defaults specified in Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSmearing.hpp @@ -324,6 +313,8 @@ def addSeeding( The hypothesis used for track finding. Defaults to pion. inputParticles : str, "particles" input particles name in the WhiteBoard + selectedParticles : str, "particles_selected" + selected particles name in the WhiteBoard outputDirRoot : Path|str, path, None the output folder for the Root output, None triggers no output logLevel : acts.logging.Level, None @@ -336,18 +327,6 @@ def addSeeding( logger = acts.logging.getLogger("addSeeding") logger.setLevel(logLevel) - if truthSeedRanges is not None: - selectedParticles = "truth_seeds_selected" - addSeedingTruthSelection( - s, - inputParticles, - selectedParticles, - truthSeedRanges, - logLevel, - ) - else: - selectedParticles = inputParticles - # Create starting parameters from either particle smearing or combined seed # finding and track parameters estimation if seedingAlgorithm == SeedingAlgorithm.TruthSmeared: @@ -506,41 +485,6 @@ def addSeeding( return s -def addSeedingTruthSelection( - s: acts.examples.Sequencer, - inputParticles: str, - outputParticles: str, - truthSeedRanges: TruthSeedRanges, - logLevel: acts.logging.Level = None, -): - """adds truth particles filtering before filtering - For parameters description see addSeeding - """ - selAlg = acts.examples.TruthSeedSelector( - **acts.examples.defaultKWArgs( - ptMin=truthSeedRanges.pt[0], - ptMax=truthSeedRanges.pt[1], - etaMin=truthSeedRanges.eta[0], - etaMax=truthSeedRanges.eta[1], - nHitsMin=truthSeedRanges.nHits[0], - nHitsMax=truthSeedRanges.nHits[1], - rhoMin=truthSeedRanges.rho[0], - rhoMax=truthSeedRanges.rho[1], - zMin=truthSeedRanges.z[0], - zMax=truthSeedRanges.z[1], - phiMin=truthSeedRanges.phi[0], - phiMax=truthSeedRanges.phi[1], - absEtaMin=truthSeedRanges.absEta[0], - absEtaMax=truthSeedRanges.absEta[1], - ), - level=logLevel, - inputParticles=inputParticles, - inputMeasurementParticlesMap="measurement_particles_map", - outputParticles=outputParticles, - ) - s.addAlgorithm(selAlg) - - def addTruthSmearedSeeding( s: acts.examples.Sequencer, rnd: Optional[acts.examples.RandomNumbers], @@ -1233,7 +1177,7 @@ def addSeedFilterML( from acts.examples.onnx import SeedFilterMLAlgorithm inputParticles = "particles" - selectedParticles = "truth_seeds_selected" + selectedParticles = "particles_selected" seeds = "seeds" estParams = "estimatedparameters" @@ -1678,10 +1622,6 @@ def addTrackWriters( trackStatesWriter = acts.examples.RootTrackStatesWriter( level=customLogLevel(), inputTracks=tracks, - # @note The full particles collection is used here to avoid lots of warnings - # since the unselected CKF track might have a majority particle not in the - # filtered particle collection. This could be avoided when a separate track - # selection algorithm is used. inputParticles="particles_selected", inputTrackParticleMatching="track_particle_matching", inputSimHits="simhits", @@ -1696,10 +1636,6 @@ def addTrackWriters( trackSummaryWriter = acts.examples.RootTrackSummaryWriter( level=customLogLevel(), inputTracks=tracks, - # @note The full particles collection is used here to avoid lots of warnings - # since the unselected CKF track might have a majority particle not in the - # filtered particle collection. This could be avoided when a separate track - # selection algorithm is used. inputParticles="particles_selected", inputTrackParticleMatching="track_particle_matching", filePath=str(outputDirRoot / f"tracksummary_{name}.root"), @@ -1713,7 +1649,7 @@ def addTrackWriters( ckfPerfWriter = acts.examples.CKFPerformanceWriter( level=customLogLevel(), inputTracks=tracks, - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputTrackParticleMatching="track_particle_matching", inputParticleTrackMatching="particle_track_matching", filePath=str(outputDirRoot / f"performance_{name}.root"), diff --git a/Examples/Python/python/acts/examples/simulation.py b/Examples/Python/python/acts/examples/simulation.py index b3b1046dc70..8f6b6d0e603 100644 --- a/Examples/Python/python/acts/examples/simulation.py +++ b/Examples/Python/python/acts/examples/simulation.py @@ -355,7 +355,8 @@ def addParticleSelection( config: ParticleSelectorConfig, inputParticles: str, outputParticles: str, - inputMeasurementParticlesMap: str = "", + inputParticlesFinal: Optional[str] = None, + outputParticlesFinal: Optional[str] = None, logLevel: Optional[acts.logging.Level] = None, ) -> None: """ @@ -371,12 +372,18 @@ def addParticleSelection( the identifier for the input particles to be selected outputParticles: str the identifier for the final selected particle collection + inputParticlesFinal: str, None + the identifier for the input final particles to be selected + outputParticlesFinal: str, None + the identifier for the final selected final particle collection """ customLogLevel = acts.examples.defaultLogging(s, logLevel) s.addAlgorithm( acts.examples.ParticleSelector( **acts.examples.defaultKWArgs( + inputParticlesFinal=inputParticlesFinal, + outputParticlesFinal=outputParticlesFinal, rhoMin=config.rho[0], rhoMax=config.rho[1], absZMin=config.absZ[0], @@ -402,7 +409,6 @@ def addParticleSelection( level=customLogLevel(), inputParticles=inputParticles, outputParticles=outputParticles, - inputMeasurementParticlesMap=inputMeasurementParticlesMap, ) ) @@ -489,27 +495,22 @@ def addFatras( # Selector if postSelectParticles is not None: particlesInitial = "fatras_particles_initial_selected" - addParticleSelection( - s, - postSelectParticles, - inputParticles=alg.config.outputParticlesInitial, - outputParticles=particlesInitial, - ) - particlesFinal = "fatras_particles_final_selected" addParticleSelection( s, postSelectParticles, - inputParticles=alg.config.outputParticlesFinal, - outputParticles=particlesFinal, + inputParticles=outputParticlesInitial, + inputParticlesFinal=outputParticlesFinal, + outputParticles=particlesInitial, + outputParticlesFinal=particlesFinal, ) - s.addWhiteboardAlias("particles_selected", particlesFinal) + s.addWhiteboardAlias("particles_selected", particlesInitial) else: - particlesInitial = alg.config.outputParticlesInitial - particlesFinal = alg.config.outputParticlesFinal + particlesInitial = outputParticlesInitial + particlesFinal = outputParticlesFinal # Only add alias for 'particles_initial' as this is the one we use most - s.addWhiteboardAlias("particles", particlesInitial) + s.addWhiteboardAlias("particles", outputParticlesInitial) # Output addSimWriters( @@ -573,7 +574,7 @@ def addSimWriters( acts.examples.RootParticleWriter( level=customLogLevel(), inputParticles=particlesInitial, - inputFinalParticles=particlesFinal, + inputParticlesFinal=particlesFinal, filePath=str(outputDirRoot / "particles_simulation.root"), ) ) @@ -739,27 +740,22 @@ def addGeant4( # Selector if postSelectParticles is not None: particlesInitial = "geant4_particles_initial_postselected" - addParticleSelection( - s, - postSelectParticles, - inputParticles=alg.config.outputParticlesInitial, - outputParticles=particlesInitial, - ) - particlesFinal = "geant4_particles_final_postselected" addParticleSelection( s, postSelectParticles, - inputParticles=alg.config.outputParticlesFinal, - outputParticles=particlesFinal, + inputParticles=outputParticlesInitial, + inputParticlesFinal=outputParticlesFinal, + outputParticles=particlesInitial, + outputParticlesFinal=particlesFinal, ) - s.addWhiteboardAlias("particles_selected", particlesFinal) + s.addWhiteboardAlias("particles_selected", particlesInitial) else: - particlesInitial = alg.config.outputParticlesInitial - particlesFinal = alg.config.outputParticlesFinal + particlesInitial = outputParticlesInitial + particlesFinal = outputParticlesFinal # Only add alias for 'particles_initial' as this is the one we use most - s.addWhiteboardAlias("particles", particlesInitial) + s.addWhiteboardAlias("particles", outputParticlesInitial) # Output addSimWriters( diff --git a/Examples/Python/src/Output.cpp b/Examples/Python/src/Output.cpp index 3ef89801c41..bda45b3cab7 100644 --- a/Examples/Python/src/Output.cpp +++ b/Examples/Python/src/Output.cpp @@ -194,7 +194,7 @@ void addOutput(Context& ctx) { ACTS_PYTHON_DECLARE_WRITER(ActsExamples::RootParticleWriter, mex, "RootParticleWriter", inputParticles, - inputFinalParticles, filePath, fileMode, treeName); + inputParticlesFinal, filePath, fileMode, treeName); ACTS_PYTHON_DECLARE_WRITER(ActsExamples::RootVertexWriter, mex, "RootVertexWriter", inputVertices, filePath, diff --git a/Examples/Python/src/TruthTracking.cpp b/Examples/Python/src/TruthTracking.cpp index 85d34698b7b..2c43b3cfc4d 100644 --- a/Examples/Python/src/TruthTracking.cpp +++ b/Examples/Python/src/TruthTracking.cpp @@ -108,8 +108,9 @@ void addTruthTracking(Context& ctx) { ACTS_PYTHON_STRUCT_BEGIN(c, Config); ACTS_PYTHON_MEMBER(inputParticles); - ACTS_PYTHON_MEMBER(inputMeasurementParticlesMap); + ACTS_PYTHON_MEMBER(inputParticlesFinal); ACTS_PYTHON_MEMBER(outputParticles); + ACTS_PYTHON_MEMBER(outputParticlesFinal); ACTS_PYTHON_MEMBER(rhoMin); ACTS_PYTHON_MEMBER(rhoMax); ACTS_PYTHON_MEMBER(absZMin); diff --git a/Examples/Python/tests/root_file_hashes.txt b/Examples/Python/tests/root_file_hashes.txt index 54c81ea9ba1..077296bac57 100644 --- a/Examples/Python/tests/root_file_hashes.txt +++ b/Examples/Python/tests/root_file_hashes.txt @@ -6,12 +6,12 @@ test_geant4__hits.root: adf5dcdf000a580412dc5089e17460897d6535c978eafa021584ba42 test_seeding__estimatedparams.root: 69c0e268f9025a0991a212ea2a7f26f53112fecf614b475605bd1cb08415ba56 test_seeding__performance_seeding.root: 992f9c611d30dde0d3f3ab676bab19ada61ab6a4442828e27b65ec5e5b7a2880 test_seeding__particles.root: 7855b021f39ad238bca098e4282667be0666f2d1630e5bcb9d51d3b5ee39fa14 -test_seeding__particles_simulation.root: 87d9c6c82422ca381a17735096b36c547eacb5dda2f26d7377614bd97a70ab1a +test_seeding__particles_simulation.root: f937a4cc474e80cfbb6eac4384e42e9c5c7ac981fcd6870d624cc898d1a0c006 test_hashing_seeding__estimatedparams.root: 1f43b760e80089b5674e106d00d962d74be564cbf33ae38222052ebb6f9cbf3a test_seeding_orthogonal__estimatedparams.root: ca5896ec325daf5c8012291bc454269c61c32fe3d7e33bd1fa3b812826930299 test_seeding_orthogonal__performance_seeding.root: 60fbedcf5cb2b37cd8e526251940564432890d3a159d231ed819e915a904682c test_seeding_orthogonal__particles.root: 7855b021f39ad238bca098e4282667be0666f2d1630e5bcb9d51d3b5ee39fa14 -test_seeding_orthogonal__particles_simulation.root: 87d9c6c82422ca381a17735096b36c547eacb5dda2f26d7377614bd97a70ab1a +test_seeding_orthogonal__particles_simulation.root: f937a4cc474e80cfbb6eac4384e42e9c5c7ac981fcd6870d624cc898d1a0c006 test_itk_seeding__estimatedparams.root: 1cc05f9f2aefb5f71a85b31e97bc4e5845fedfcef6c53199495a6340c6b6210b test_itk_seeding__performance_seeding.root: 78ebda54cd0f026ba4b7f316724ffd946de56a932735914baf1b7bba9505c29d test_itk_seeding__particles.root: 0b6f4ad438010ac48803d48ed98e80b5e87d310bae6c2c02b16cd94d7a4d7d07 diff --git a/Examples/Python/tests/test_examples.py b/Examples/Python/tests/test_examples.py index d5bb593ca9f..9a2c45c7657 100644 --- a/Examples/Python/tests/test_examples.py +++ b/Examples/Python/tests/test_examples.py @@ -407,6 +407,7 @@ def test_itk_seeding(tmp_path, trk_geo, field, assert_root_hash): EtaConfig, MomentumConfig, ParticleConfig, + ParticleSelectorConfig, addFatras, addDigitization, ) @@ -428,6 +429,12 @@ def test_itk_seeding(tmp_path, trk_geo, field, assert_root_hash): outputDirCsv=tmp_path / "csv", outputDirRoot=str(tmp_path), rnd=rnd, + postSelectParticles=ParticleSelectorConfig( + pt=(0.9 * u.GeV, None), + eta=(-4, 4), + measurements=(9, None), + removeNeutral=True, + ), ) srcdir = Path(__file__).resolve().parent.parent.parent.parent @@ -442,7 +449,6 @@ def test_itk_seeding(tmp_path, trk_geo, field, assert_root_hash): from acts.examples.reconstruction import ( addSeeding, - TruthSeedRanges, ) from acts.examples.itk import itkSeedingAlgConfig, InputSpacePointsType @@ -450,7 +456,6 @@ def test_itk_seeding(tmp_path, trk_geo, field, assert_root_hash): seq, trk_geo, field, - TruthSeedRanges(pt=(1.0 * u.GeV, None), eta=(-4, 4), nHits=(9, None)), *itkSeedingAlgConfig(InputSpacePointsType.PixelSpacePoints), acts.logging.VERBOSE, geoSelectionConfigFile=srcdir diff --git a/Examples/Scripts/Optimization/ckf.py b/Examples/Scripts/Optimization/ckf.py index bf927850ecc..c1761141262 100755 --- a/Examples/Scripts/Optimization/ckf.py +++ b/Examples/Scripts/Optimization/ckf.py @@ -116,13 +116,13 @@ def runCKFTracks( EtaConfig, PhiConfig, ParticleConfig, + ParticleSelectorConfig, addFatras, addDigitization, ) from acts.examples.reconstruction import ( addSeeding, - TruthSeedRanges, ParticleSmearingSigmas, SeedFinderConfigArg, SeedFinderOptionsArg, @@ -169,6 +169,11 @@ def runCKFTracks( trackingGeometry, field, rnd=rnd, + postSelectParticles=ParticleSelectorConfig( + pt=(0.5 * u.GeV, None), + measurements=(9, None), + removeNeutral=True, + ), ) addDigitization( @@ -183,7 +188,6 @@ def runCKFTracks( s, trackingGeometry, field, - TruthSeedRanges(pt=(500.0 * u.MeV, None), nHits=(9, None)), ParticleSmearingSigmas( # only used by SeedingAlgorithm.TruthSmeared # zero eveything so the CKF has a chance to find the measurements d0=0, diff --git a/Examples/Scripts/Python/ckf_tracks.py b/Examples/Scripts/Python/ckf_tracks.py index 9dc665eb835..e2b24436c0a 100755 --- a/Examples/Scripts/Python/ckf_tracks.py +++ b/Examples/Scripts/Python/ckf_tracks.py @@ -27,13 +27,13 @@ def runCKFTracks( EtaConfig, PhiConfig, ParticleConfig, + ParticleSelectorConfig, addFatras, addDigitization, ) from acts.examples.reconstruction import ( addSeeding, - TruthSeedRanges, ParticleSmearingSigmas, SeedFinderConfigArg, SeedFinderOptionsArg, @@ -80,6 +80,11 @@ def runCKFTracks( trackingGeometry, field, rnd=rnd, + postSelectParticles=ParticleSelectorConfig( + pt=(0.5 * u.GeV, None), + measurements=(9, None), + removeNeutral=True, + ), ) addDigitization( @@ -94,7 +99,6 @@ def runCKFTracks( s, trackingGeometry, field, - TruthSeedRanges(pt=(500.0 * u.MeV, None), nHits=(9, None)), ParticleSmearingSigmas( # only used by SeedingAlgorithm.TruthSmeared # zero eveything so the CKF has a chance to find the measurements d0=0, diff --git a/Examples/Scripts/Python/full_chain_itk.py b/Examples/Scripts/Python/full_chain_itk.py index 5e268f87fcb..51746c127a1 100755 --- a/Examples/Scripts/Python/full_chain_itk.py +++ b/Examples/Scripts/Python/full_chain_itk.py @@ -5,6 +5,7 @@ MomentumConfig, EtaConfig, ParticleConfig, + ParticleSelectorConfig, addPythia8, addFatras, ParticleSelectorConfig, @@ -13,7 +14,6 @@ from acts.examples.reconstruction import ( addSeeding, SeedingAlgorithm, - TruthSeedRanges, addCKFTracks, CkfConfig, TrackSelectorConfig, @@ -72,6 +72,12 @@ if ttbar_pu200 else ParticleSelectorConfig() ), + postSelectParticles=ParticleSelectorConfig( + pt=(1.0 * u.GeV, None), + eta=(-4.0, 4.0), + measurements=(9, None), + removeNeutral=True, + ), outputDirRoot=outputDir, ) @@ -88,11 +94,6 @@ s, trackingGeometry, field, - ( - TruthSeedRanges(pt=(1.0 * u.GeV, None), eta=(-4.0, 4.0), nHits=(9, None)) - if ttbar_pu200 - else TruthSeedRanges() - ), seedingAlgorithm=SeedingAlgorithm.Default, *acts.examples.itk.itkSeedingAlgConfig( acts.examples.itk.InputSpacePointsType.PixelSpacePoints diff --git a/Examples/Scripts/Python/full_chain_itk_Gbts.py b/Examples/Scripts/Python/full_chain_itk_Gbts.py index 7a45b7e5a71..a87f5ca6656 100755 --- a/Examples/Scripts/Python/full_chain_itk_Gbts.py +++ b/Examples/Scripts/Python/full_chain_itk_Gbts.py @@ -5,6 +5,7 @@ MomentumConfig, EtaConfig, ParticleConfig, + ParticleSelectorConfig, addPythia8, addFatras, ParticleSelectorConfig, @@ -13,7 +14,6 @@ from acts.examples.reconstruction import ( addSeeding, SeedingAlgorithm, - TruthSeedRanges, addCKFTracks, TrackSelectorConfig, ) @@ -67,6 +67,12 @@ if ttbar_pu200 else ParticleSelectorConfig() ), + postSelectParticles=ParticleSelectorConfig( + pt=(1.0 * u.GeV, None), + eta=(-4.0, 4.0), + measurements=(9, None), + removeNeutral=True, + ), outputDirRoot=outputDir, ) @@ -84,11 +90,6 @@ s, trackingGeometry, field, - ( - TruthSeedRanges(pt=(1.0 * u.GeV, None), eta=(-4.0, 4.0), nHits=(9, None)) - if ttbar_pu200 - else TruthSeedRanges() - ), seedingAlgorithm=SeedingAlgorithm.Gbts, *acts.examples.itk.itkSeedingAlgConfig( acts.examples.itk.InputSpacePointsType.PixelSpacePoints diff --git a/Examples/Scripts/Python/full_chain_odd.py b/Examples/Scripts/Python/full_chain_odd.py index 22f20d3b257..fd98f759577 100755 --- a/Examples/Scripts/Python/full_chain_odd.py +++ b/Examples/Scripts/Python/full_chain_odd.py @@ -13,6 +13,7 @@ EtaConfig, PhiConfig, ParticleConfig, + ParticleSelectorConfig, addPythia8, addFatras, addGeant4, @@ -22,7 +23,6 @@ ) from acts.examples.reconstruction import ( addSeeding, - TruthSeedRanges, CkfConfig, addCKFTracks, TrackSelectorConfig, @@ -271,6 +271,12 @@ pt=(150 * u.MeV, None), removeNeutral=True, ), + postSelectParticles=ParticleSelectorConfig( + pt=(1.0 * u.GeV, None), + eta=(-3.0, 3.0), + measurements=(9, None), + removeNeutral=True, + ), outputDirRoot=outputDir if args.output_root else None, outputDirCsv=outputDir if args.output_csv else None, rnd=rnd, @@ -293,6 +299,12 @@ if args.ttbar else ParticleSelectorConfig() ), + postSelectParticles=ParticleSelectorConfig( + pt=(1.0 * u.GeV, None), + eta=(-3.0, 3.0), + measurements=(9, None), + removeNeutral=True, + ), enableInteractions=True, outputDirRoot=outputDir if args.output_root else None, outputDirCsv=outputDir if args.output_csv else None, @@ -314,11 +326,6 @@ s, trackingGeometry, field, - ( - TruthSeedRanges(pt=(1.0 * u.GeV, None), eta=(-3.0, 3.0), nHits=(9, None)) - if args.ttbar - else TruthSeedRanges() - ), initialSigmas=[ 1 * u.mm, 1 * u.mm, diff --git a/Examples/Scripts/Python/full_chain_odd_LRT.py b/Examples/Scripts/Python/full_chain_odd_LRT.py index a5fd294ceda..2188bb98d6b 100644 --- a/Examples/Scripts/Python/full_chain_odd_LRT.py +++ b/Examples/Scripts/Python/full_chain_odd_LRT.py @@ -21,7 +21,6 @@ ) from acts.examples.reconstruction import ( addSeeding, - TruthSeedRanges, CkfConfig, addCKFTracks, TrackSelectorConfig, @@ -273,6 +272,12 @@ pt=(150 * u.MeV, None), removeNeutral=True, ), + postSelectParticles=ParticleSelectorConfig( + pt=(1.0 * u.GeV, None), + eta=(-3.0, 3.0), + measurements=(9, None), + removeNeutral=True, + ), outputDirRoot=outputDir if args.output_root else None, outputDirCsv=outputDir if args.output_csv else None, rnd=rnd, @@ -295,6 +300,12 @@ if args.ttbar else ParticleSelectorConfig() ), + postSelectParticles=ParticleSelectorConfig( + pt=(1.0 * u.GeV, None), + eta=(-3.0, 3.0), + measurements=(9, None), + removeNeutral=True, + ), enableInteractions=True, outputDirRoot=outputDir if args.output_root else None, outputDirCsv=outputDir if args.output_csv else None, @@ -316,11 +327,6 @@ s, trackingGeometry, field, - ( - TruthSeedRanges(pt=(1.0 * u.GeV, None), eta=(-3.0, 3.0), nHits=(9, None)) - if args.ttbar - else TruthSeedRanges() - ), geoSelectionConfigFile=oddSeedingSel, outputDirRoot=outputDir if args.output_root else None, outputDirCsv=outputDir if args.output_csv else None, diff --git a/Examples/Scripts/Python/hashing_seeding.py b/Examples/Scripts/Python/hashing_seeding.py index a5608a0f329..3148a03837d 100755 --- a/Examples/Scripts/Python/hashing_seeding.py +++ b/Examples/Scripts/Python/hashing_seeding.py @@ -14,7 +14,6 @@ from acts.examples.reconstruction import ( addSeeding, - TruthSeedRanges, addCKFTracks, TrackSelectorConfig, SeedingAlgorithm, @@ -210,7 +209,15 @@ def runHashingSeeding( trackingGeometry, field, preSelectParticles=ParticleSelectorConfig( - eta=(-eta, eta), pt=(150 * u.MeV, None), removeNeutral=True + eta=(-eta, eta), + pt=(150 * u.MeV, None), + removeNeutral=True, + ), + postSelectParticles=ParticleSelectorConfig( + pt=(1.0 * u.GeV, None), + eta=(-eta, eta), + measurements=(9, None), + removeNeutral=True, ), enableInteractions=True, # outputDirRoot=outputDir, # RootParticle ERROR when setting the outputDirRoot @@ -272,7 +279,6 @@ def runHashingSeeding( seedFinderOptionsArg, hashingTrainingConfigArg, hashingAlgorithmConfigArg, - TruthSeedRanges(pt=(1.0 * u.GeV, None), eta=(-eta, eta), nHits=(9, None)), seedingAlgorithm=seedingAlgorithm, geoSelectionConfigFile=geoSelectionConfigFile, initialSigmas=initialSigmas, @@ -338,10 +344,6 @@ def runHashingSeeding( phiBins=phiBins, ) - truthSeedRanges = TruthSeedRanges( - pt=(1.0 * u.GeV, None), eta=(-eta, eta), nHits=(9, None) - ) - doHashing = config.doHashing bucketSize = config.bucketSize npileup = config.mu diff --git a/Examples/Scripts/Python/seeding.py b/Examples/Scripts/Python/seeding.py index 4c87ba9b82b..e50f9390c12 100755 --- a/Examples/Scripts/Python/seeding.py +++ b/Examples/Scripts/Python/seeding.py @@ -57,6 +57,7 @@ def runSeeding( EtaConfig, PhiConfig, ParticleConfig, + ParticleSelectorConfig, addFatras, addDigitization, ) @@ -86,6 +87,12 @@ def runSeeding( outputDirRoot=outputDir, rnd=rnd, preSelectParticles=None, + postSelectParticles=ParticleSelectorConfig( + pt=(1.0 * u.GeV, None), + eta=(-2.5, 2.5), + measurements=(9, None), + removeNeutral=True, + ), ) srcdir = Path(__file__).resolve().parent.parent.parent.parent @@ -99,7 +106,6 @@ def runSeeding( ) from acts.examples.reconstruction import ( addSeeding, - TruthSeedRanges, SeedFinderConfigArg, SeedFinderOptionsArg, ) @@ -108,7 +114,6 @@ def runSeeding( s, trackingGeometry, field, - TruthSeedRanges(pt=(1.0 * u.GeV, None), eta=(-2.5, 2.5), nHits=(9, None)), SeedFinderConfigArg( r=(None, 200 * u.mm), # rMin=default, 33mm deltaR=(1 * u.mm, 60 * u.mm), diff --git a/Examples/Scripts/Python/truth_tracking_gsf.py b/Examples/Scripts/Python/truth_tracking_gsf.py index 82c99bb38aa..ae8aca06d6c 100755 --- a/Examples/Scripts/Python/truth_tracking_gsf.py +++ b/Examples/Scripts/Python/truth_tracking_gsf.py @@ -24,13 +24,13 @@ def runTruthTrackingGsf( EtaConfig, PhiConfig, MomentumConfig, + ParticleSelectorConfig, addFatras, addDigitization, ) from acts.examples.reconstruction import ( addSeeding, SeedingAlgorithm, - TruthSeedRanges, addTruthTrackingGsf, ) @@ -77,6 +77,12 @@ def runTruthTrackingGsf( field, rnd=rnd, enableInteractions=True, + postSelectParticles=ParticleSelectorConfig( + pt=(0.9 * u.GeV, None), + measurements=(7, None), + removeNeutral=True, + removeSecondaries=True, + ), ) addDigitization( @@ -95,9 +101,6 @@ def runTruthTrackingGsf( inputParticles="particles_input", seedingAlgorithm=SeedingAlgorithm.TruthSmeared, particleHypothesis=acts.ParticleHypothesis.electron, - truthSeedRanges=TruthSeedRanges( - nHits=(7, None), - ), ) addTruthTrackingGsf( @@ -122,7 +125,7 @@ def runTruthTrackingGsf( acts.examples.RootTrackStatesWriter( level=acts.logging.INFO, inputTracks="tracks", - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputTrackParticleMatching="track_particle_matching", inputSimHits="simhits", inputMeasurementSimHitsMap="measurement_simhits_map", @@ -134,7 +137,7 @@ def runTruthTrackingGsf( acts.examples.RootTrackSummaryWriter( level=acts.logging.INFO, inputTracks="tracks", - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputTrackParticleMatching="track_particle_matching", filePath=str(outputDir / "tracksummary_gsf.root"), writeGsfSpecific=True, @@ -145,7 +148,7 @@ def runTruthTrackingGsf( acts.examples.TrackFitterPerformanceWriter( level=acts.logging.INFO, inputTracks="tracks", - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputTrackParticleMatching="track_particle_matching", filePath=str(outputDir / "performance_gsf.root"), ) diff --git a/Examples/Scripts/Python/truth_tracking_gsf_refitting.py b/Examples/Scripts/Python/truth_tracking_gsf_refitting.py index e8b41c9aae8..686f4af06c2 100755 --- a/Examples/Scripts/Python/truth_tracking_gsf_refitting.py +++ b/Examples/Scripts/Python/truth_tracking_gsf_refitting.py @@ -54,7 +54,7 @@ def runRefittingGsf( acts.examples.TrackTruthMatcher( level=acts.logging.INFO, inputTracks="gsf_refit_tracks", - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputMeasurementParticlesMap="measurement_particles_map", outputTrackParticleMatching="refit_track_particle_matching", outputParticleTrackMatching="refit_particle_track_matching", @@ -65,7 +65,7 @@ def runRefittingGsf( acts.examples.RootTrackStatesWriter( level=acts.logging.INFO, inputTracks="gsf_refit_tracks", - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputTrackParticleMatching="refit_track_particle_matching", inputSimHits="simhits", inputMeasurementSimHitsMap="measurement_simhits_map", @@ -77,7 +77,7 @@ def runRefittingGsf( acts.examples.RootTrackSummaryWriter( level=acts.logging.INFO, inputTracks="tracks", - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputTrackParticleMatching="refit_track_particle_matching", filePath=str(outputDir / "tracksummary_gsf_refit.root"), ) @@ -87,7 +87,7 @@ def runRefittingGsf( acts.examples.TrackFitterPerformanceWriter( level=acts.logging.INFO, inputTracks="tracks", - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputTrackParticleMatching="track_particle_matching", filePath=str(outputDir / "performance_gsf_refit.root"), ) diff --git a/Examples/Scripts/Python/truth_tracking_gx2f.py b/Examples/Scripts/Python/truth_tracking_gx2f.py index 46352ac8d21..8503dc982f4 100644 --- a/Examples/Scripts/Python/truth_tracking_gx2f.py +++ b/Examples/Scripts/Python/truth_tracking_gx2f.py @@ -23,13 +23,13 @@ def runTruthTrackingGx2f( EtaConfig, PhiConfig, MomentumConfig, + ParticleSelectorConfig, addFatras, addDigitization, ) from acts.examples.reconstruction import ( addSeeding, SeedingAlgorithm, - TruthSeedRanges, addGx2fTracks, ) @@ -74,6 +74,12 @@ def runTruthTrackingGx2f( field, rnd=rnd, enableInteractions=True, + postSelectParticles=ParticleSelectorConfig( + pt=(0.9 * u.GeV, None), + measurements=(7, None), + removeNeutral=True, + removeSecondaries=True, + ), ) addDigitization( @@ -92,9 +98,6 @@ def runTruthTrackingGx2f( inputParticles="particles_input", seedingAlgorithm=SeedingAlgorithm.TruthSmeared, particleHypothesis=acts.ParticleHypothesis.muon, - truthSeedRanges=TruthSeedRanges( - nHits=(7, None), - ), ) addGx2fTracks( @@ -122,7 +125,7 @@ def runTruthTrackingGx2f( acts.examples.RootTrackStatesWriter( level=acts.logging.INFO, inputTracks="tracks", - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputTrackParticleMatching="track_particle_matching", inputSimHits="simhits", inputMeasurementSimHitsMap="measurement_simhits_map", @@ -134,7 +137,7 @@ def runTruthTrackingGx2f( acts.examples.RootTrackSummaryWriter( level=acts.logging.INFO, inputTracks="tracks", - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputTrackParticleMatching="track_particle_matching", filePath=str(outputDir / "tracksummary_gx2f.root"), writeGx2fSpecific=True, @@ -145,7 +148,7 @@ def runTruthTrackingGx2f( acts.examples.TrackFitterPerformanceWriter( level=acts.logging.INFO, inputTracks="tracks", - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputTrackParticleMatching="track_particle_matching", filePath=str(outputDir / "performance_gx2f.root"), ) diff --git a/Examples/Scripts/Python/truth_tracking_kalman.py b/Examples/Scripts/Python/truth_tracking_kalman.py index 276cb962c8f..91c18f1dd28 100755 --- a/Examples/Scripts/Python/truth_tracking_kalman.py +++ b/Examples/Scripts/Python/truth_tracking_kalman.py @@ -27,13 +27,13 @@ def runTruthTrackingKalman( EtaConfig, PhiConfig, MomentumConfig, + ParticleSelectorConfig, addFatras, addDigitization, ) from acts.examples.reconstruction import ( addSeeding, SeedingAlgorithm, - TruthSeedRanges, addKalmanTracks, ) @@ -82,6 +82,12 @@ def runTruthTrackingKalman( field, rnd=rnd, enableInteractions=True, + postSelectParticles=ParticleSelectorConfig( + pt=(0.9 * u.GeV, None), + measurements=(7, None), + removeNeutral=True, + removeSecondaries=True, + ), ) else: logger.info("Reading hits from %s", inputHitsPath.resolve()) @@ -110,9 +116,6 @@ def runTruthTrackingKalman( inputParticles="particles_input", seedingAlgorithm=SeedingAlgorithm.TruthSmeared, particleHypothesis=acts.ParticleHypothesis.muon, - truthSeedRanges=TruthSeedRanges( - nHits=(7, None), - ), ) addKalmanTracks( @@ -139,7 +142,7 @@ def runTruthTrackingKalman( acts.examples.RootTrackStatesWriter( level=acts.logging.INFO, inputTracks="tracks", - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputTrackParticleMatching="track_particle_matching", inputSimHits="simhits", inputMeasurementSimHitsMap="measurement_simhits_map", @@ -151,7 +154,7 @@ def runTruthTrackingKalman( acts.examples.RootTrackSummaryWriter( level=acts.logging.INFO, inputTracks="tracks", - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputTrackParticleMatching="track_particle_matching", filePath=str(outputDir / "tracksummary_kf.root"), ) @@ -161,7 +164,7 @@ def runTruthTrackingKalman( acts.examples.TrackFitterPerformanceWriter( level=acts.logging.INFO, inputTracks="tracks", - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputTrackParticleMatching="track_particle_matching", filePath=str(outputDir / "performance_kf.root"), ) diff --git a/Examples/Scripts/Python/truth_tracking_kalman_refitting.py b/Examples/Scripts/Python/truth_tracking_kalman_refitting.py index 7e795b9e310..46578423f33 100755 --- a/Examples/Scripts/Python/truth_tracking_kalman_refitting.py +++ b/Examples/Scripts/Python/truth_tracking_kalman_refitting.py @@ -51,7 +51,7 @@ def runRefittingKf( acts.examples.TrackTruthMatcher( level=acts.logging.INFO, inputTracks="kf_refit_tracks", - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputMeasurementParticlesMap="measurement_particles_map", outputTrackParticleMatching="refit_track_particle_matching", outputParticleTrackMatching="refit_particle_track_matching", @@ -62,7 +62,7 @@ def runRefittingKf( acts.examples.RootTrackStatesWriter( level=acts.logging.INFO, inputTracks="kf_refit_tracks", - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputTrackParticleMatching="refit_track_particle_matching", inputSimHits="simhits", inputMeasurementSimHitsMap="measurement_simhits_map", @@ -74,7 +74,7 @@ def runRefittingKf( acts.examples.RootTrackSummaryWriter( level=acts.logging.INFO, inputTracks="tracks", - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputTrackParticleMatching="refit_track_particle_matching", filePath=str(outputDir / "tracksummary_kf_refit.root"), ) @@ -84,7 +84,7 @@ def runRefittingKf( acts.examples.TrackFitterPerformanceWriter( level=acts.logging.INFO, inputTracks="tracks", - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputTrackParticleMatching="track_particle_matching", filePath=str(outputDir / "performance_kf_refit.root"), ) From d6c14510dd347320e7c2dd7d81c60fd199935055 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Fri, 18 Oct 2024 20:30:15 +0200 Subject: [PATCH 4/6] fix: TrackFinding: skip second pass if out of bounds (#3751) --- .../TrackFinding/TrackFindingAlgorithm.hpp | 1 + .../TrackFinding/src/TrackFindingAlgorithm.cpp | 10 ++++++++++ Examples/Python/tests/root_file_hashes.txt | 12 ++++++------ 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/TrackFindingAlgorithm.hpp b/Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/TrackFindingAlgorithm.hpp index deb15750a5f..c56e9508c9b 100644 --- a/Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/TrackFindingAlgorithm.hpp +++ b/Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/TrackFindingAlgorithm.hpp @@ -179,6 +179,7 @@ class TrackFindingAlgorithm final : public IAlgorithm { mutable std::atomic m_nFoundTracks{0}; mutable std::atomic m_nSelectedTracks{0}; mutable std::atomic m_nStoppedBranches{0}; + mutable std::atomic m_nSkippedSecondPass{0}; mutable tbb::combinable m_memoryStatistics{[]() { diff --git a/Examples/Algorithms/TrackFinding/src/TrackFindingAlgorithm.cpp b/Examples/Algorithms/TrackFinding/src/TrackFindingAlgorithm.cpp index 2a36701dc3b..f2a5104e2b0 100644 --- a/Examples/Algorithms/TrackFinding/src/TrackFindingAlgorithm.cpp +++ b/Examples/Algorithms/TrackFinding/src/TrackFindingAlgorithm.cpp @@ -532,6 +532,15 @@ ProcessCode TrackFindingAlgorithm::execute(const AlgorithmContext& ctx) const { Acts::BoundTrackParameters secondInitialParameters = trackCandidate.createParametersFromState(firstMeasurement); + if (!secondInitialParameters.referenceSurface().insideBounds( + secondInitialParameters.localPosition())) { + m_nSkippedSecondPass++; + ACTS_DEBUG( + "Smoothing of first pass fit produced out-of-bounds parameters " + "relative to the surface. Skipping second pass."); + continue; + } + auto secondRootBranch = tracksTemp.makeTrack(); secondRootBranch.copyFrom(trackCandidate, false); auto secondResult = @@ -681,6 +690,7 @@ ProcessCode TrackFindingAlgorithm::finalize() { ACTS_INFO("- found tracks: " << m_nFoundTracks); ACTS_INFO("- selected tracks: " << m_nSelectedTracks); ACTS_INFO("- stopped branches: " << m_nStoppedBranches); + ACTS_INFO("- skipped second pass: " << m_nSkippedSecondPass); auto memoryStatistics = m_memoryStatistics.combine([](const auto& a, const auto& b) { diff --git a/Examples/Python/tests/root_file_hashes.txt b/Examples/Python/tests/root_file_hashes.txt index 077296bac57..4374b827580 100644 --- a/Examples/Python/tests/root_file_hashes.txt +++ b/Examples/Python/tests/root_file_hashes.txt @@ -41,14 +41,14 @@ test_ckf_tracks_example[generic-truth_estimated]__tracksummary_ckf.root: 417f732 test_ckf_tracks_example[generic-truth_estimated]__performance_seeding.root: 1facb05c066221f6361b61f015cdf0918e94d9f3fce2269ec7b6a4dffeb2bc7e test_ckf_tracks_example[generic-truth_smeared]__trackstates_ckf.root: edf0b06ce9ee0e4fcb153e41859af7b5153271de18f49a6842a23ad2d66b7e09 test_ckf_tracks_example[generic-truth_smeared]__tracksummary_ckf.root: 06d6ae1d05cb611b19df3c59531997c9b0108f5ef6027d76c4827bd2d9edb921 -test_ckf_tracks_example[odd-full_seeding]__trackstates_ckf.root: 463d6aaed4d869652b5b184940e789cde0fb441bdd135813b85462a515e6480a -test_ckf_tracks_example[odd-full_seeding]__tracksummary_ckf.root: a8ad83a07b48d4cfcf70d0e6fdc3c8997eb03c1f8c2a7be27ea888b099000d79 +test_ckf_tracks_example[odd-full_seeding]__trackstates_ckf.root: 6411378b31c1612120318773f8b807ce83a76e07c90a5f308ea86c6b34d02661 +test_ckf_tracks_example[odd-full_seeding]__tracksummary_ckf.root: c2e029e462d4ca77df2c7f8963093da43be66c8279ca2cc9aee8c0bc35259eec test_ckf_tracks_example[odd-full_seeding]__performance_seeding_trees.root: 43c58577aafe07645e5660c4f43904efadf91d8cda45c5c04c248bbe0f59814f -test_ckf_tracks_example[odd-truth_estimated]__trackstates_ckf.root: 247dd581cc177625c0286718261c004e2149536d70c8281dfaf697879a84d76d -test_ckf_tracks_example[odd-truth_estimated]__tracksummary_ckf.root: 1b08a80e73aedf5cf38a3a407794b82297bec37f556ad4efcda3489a1b17d4d2 +test_ckf_tracks_example[odd-truth_estimated]__trackstates_ckf.root: 465bb9e982982eb2e79fc97cae9f513ff5937041da546081281f1f959d8173ea +test_ckf_tracks_example[odd-truth_estimated]__tracksummary_ckf.root: 59e2c75e9524653a80a9fd62fe99e958f73f80aa09240dcbb4ea469372e4811d test_ckf_tracks_example[odd-truth_estimated]__performance_seeding.root: 1a36b7017e59f1c08602ef3c2cb0483c51df248f112e3780c66594110719c575 -test_ckf_tracks_example[odd-truth_smeared]__trackstates_ckf.root: a9621b535ea2912d172142394f51f68e4e7dc255b32d479d6305fa599152b420 -test_ckf_tracks_example[odd-truth_smeared]__tracksummary_ckf.root: af1a6bb16a070db7ed8043e2188d56f0034843099fc3c332731c4cf86ba39c57 +test_ckf_tracks_example[odd-truth_smeared]__trackstates_ckf.root: 9cbf99353d71ee4e6779bffb231043b41db6219c9544a80fe5172f4a4fe60cbe +test_ckf_tracks_example[odd-truth_smeared]__tracksummary_ckf.root: 3e257de624674fa9a19dcc72598c78c29a52633821acaa56dc2aa39a1395f1b5 test_vertex_fitting_reading[Truth-False-100]__performance_vertexing.root: 76ef6084d758dfdfc0151ddec2170e12d73394424e3dac4ffe46f0f339ec8293 test_vertex_fitting_reading[Iterative-False-100]__performance_vertexing.root: 60372210c830a04f95ceb78c6c68a9b0de217746ff59e8e73053750c837b57eb test_vertex_fitting_reading[Iterative-True-100]__performance_vertexing.root: e34f217d524a5051dbb04a811d3407df3ebe2cc4bb7f54f6bda0847dbd7b52c3 From 3ea63a021225bc0909fd3d692f7cefdf33469918 Mon Sep 17 00:00:00 2001 From: Andreas Salzburger Date: Fri, 18 Oct 2024 21:43:47 +0200 Subject: [PATCH 5/6] fix: DetrayMaterialConversion for Gen2 (#3748) The Detray material conversion was broken due to missing locality of the index map. It renames the cache object to simply `Cache` since it does more now, and through the namespace it gets clear that it is the conversion cache. --- .../Plugins/Detray/DetrayConversionUtils.hpp | 37 ++++++- .../Acts/Plugins/Detray/DetrayConverter.hpp | 8 +- .../Detray/DetrayGeometryConverter.hpp | 25 +++-- .../Detray/DetrayMaterialConverter.hpp | 16 +-- .../Detray/src/DetrayGeometryConverter.cpp | 74 ++++++-------- .../Detray/src/DetrayMaterialConverter.cpp | 98 +++++++++++-------- .../Detray/DetrayGeometryConverterTests.cpp | 9 +- 7 files changed, 147 insertions(+), 120 deletions(-) diff --git a/Plugins/Detray/include/Acts/Plugins/Detray/DetrayConversionUtils.hpp b/Plugins/Detray/include/Acts/Plugins/Detray/DetrayConversionUtils.hpp index 201aeb2807d..2f827a08bea 100644 --- a/Plugins/Detray/include/Acts/Plugins/Detray/DetrayConversionUtils.hpp +++ b/Plugins/Detray/include/Acts/Plugins/Detray/DetrayConversionUtils.hpp @@ -20,6 +20,10 @@ namespace Acts { +namespace Experimental { +class DetectorVolume; +} + using DetrayHostDetector = detray::detector; namespace DetrayConversionUtils { @@ -28,12 +32,37 @@ namespace DetrayConversionUtils { /// /// This object is used to synchronize link information between the /// different converters (geometry, material, surface grids) -struct GeometryIdCache { - /// This is a multimap to pass volume local surface link information - /// The portal splitting requires a multimap implementation here - std::multimap localSurfaceLinks; +struct Cache { + /// Explicit constructor with detector volumes + /// + /// @param detectorVolumes the number of detector volumes + Cache(const std::vector& dVolumes) + : detectorVolumes(dVolumes) {} + + /// The volumes of the detector for index lookup + std::vector detectorVolumes; /// This is a map to pass on volume link information std::map volumeLinks; + /// This is a multimap to pass volume local surface link information + /// The portal splitting requires a multimap implementation here + /// + /// These are volume local, hence indexed per volumes + std::map> + localSurfaceLinks; + + /// Find the position of the volume to point to + /// + /// @param volume the volume to find + /// + /// @note throws exception if volume is not found + std::size_t volumeIndex( + const Acts::Experimental::DetectorVolume* volume) const { + auto candidate = std::ranges::find(detectorVolumes, volume); + if (candidate != detectorVolumes.end()) { + return std::distance(detectorVolumes.begin(), candidate); + } + throw std::invalid_argument("Volume not found in the cache"); + } }; /// Convert the binning option diff --git a/Plugins/Detray/include/Acts/Plugins/Detray/DetrayConverter.hpp b/Plugins/Detray/include/Acts/Plugins/Detray/DetrayConverter.hpp index 2c8ca2c7fac..441b8f121f0 100644 --- a/Plugins/Detray/include/Acts/Plugins/Detray/DetrayConverter.hpp +++ b/Plugins/Detray/include/Acts/Plugins/Detray/DetrayConverter.hpp @@ -54,7 +54,7 @@ class DetrayConverter { const Experimental::Detector& detector, vecmem::memory_resource& mr, const Options& options) { // The building cache object - DetrayConversionUtils::GeometryIdCache geoIdCache; + DetrayConversionUtils::Cache cCache(detector.volumes()); typename detector_t::name_map names = {{0u, detector.name()}}; @@ -62,7 +62,7 @@ class DetrayConverter { detray::detector_builder detectorBuilder{}; // (1) geometry detray::io::detector_payload detectorPayload = - DetrayGeometryConverter::convertDetector(geoIdCache, gctx, detector, + DetrayGeometryConverter::convertDetector(cCache, gctx, detector, logger()); detray::io::geometry_reader::convert(detectorBuilder, names, detectorPayload); @@ -72,7 +72,7 @@ class DetrayConverter { if (options.convertMaterial) { detray::io::detector_homogeneous_material_payload materialSlabsPayload = DetrayMaterialConverter::convertHomogeneousSurfaceMaterial( - geoIdCache, detector, logger()); + cCache, detector, logger()); detray::io::homogeneous_material_reader::convert( detectorBuilder, names, std::move(materialSlabsPayload)); } @@ -85,7 +85,7 @@ class DetrayConverter { detray::io::material_id> materialGridsPayload = DetrayMaterialConverter::convertGridSurfaceMaterial( - geoIdCache, detector, logger()); + cCache, detector, logger()); detray::io::material_map_reader>::convert(detectorBuilder, names, std::move( diff --git a/Plugins/Detray/include/Acts/Plugins/Detray/DetrayGeometryConverter.hpp b/Plugins/Detray/include/Acts/Plugins/Detray/DetrayGeometryConverter.hpp index 2df31096746..b6ea1373125 100644 --- a/Plugins/Detray/include/Acts/Plugins/Detray/DetrayGeometryConverter.hpp +++ b/Plugins/Detray/include/Acts/Plugins/Detray/DetrayGeometryConverter.hpp @@ -64,25 +64,25 @@ detray::io::surface_payload convertSurface(const GeometryContext& gctx, /// Conversion method for Portal object to detray::portal payloads /// +/// @param cCache [in, out] object /// @param gctx the geometry context /// @param portal the portal to be converted /// @param ip the portal index /// @param volume the volume to which the portal belongs /// @param orientedSurfaces the oriented surfaces of the portal -/// @param detectorVolumes the detector volumes for the link lookup /// /// @note due to portal splitting this can add up in N portals for one initial one /// /// @brief convert the acts portal to detray surface payload and populate the payload std::vector convertPortal( - const GeometryContext& gctx, const Experimental::Portal& portal, - std::size_t ip, const Experimental::DetectorVolume& volume, - const std::vector& orientedSurfaces, - const std::vector& detectorVolumes); + DetrayConversionUtils::Cache& cCache, const GeometryContext& gctx, + const Experimental::Portal& portal, std::size_t ip, + const Experimental::DetectorVolume& volume, + const std::vector& orientedSurfaces); /// Conversion method for volume objects to detray::volume payloads /// -/// @param geoIdCache [in, out] object +/// @param cCache [in, out] object /// @param gctx the geometry context /// @param volume the volume to be converted /// @param detectorVolumes the detector volumes for the link lookup @@ -90,23 +90,20 @@ std::vector convertPortal( /// /// @return the volume_payload for portals and volumes by @param volume acts object detray::io::volume_payload convertVolume( - DetrayConversionUtils::GeometryIdCache& geoIdCache, - const GeometryContext& gctx, const Experimental::DetectorVolume& volume, - const std::vector& detectorVolumes, - const Acts::Logger& logger); + DetrayConversionUtils::Cache& cCache, const GeometryContext& gctx, + const Experimental::DetectorVolume& volume, const Acts::Logger& logger); /// Conversion method for detector objects to detray::detector payload /// -/// @param geoIdCache [in, out] object +/// @param cCache [in, out] object /// @param gctx the geometry context /// @param detector the detector to be converted /// @param logger the logger object for screen output /// /// @return the detector_payload for portals and volumes by @param detector acts object detray::io::detector_payload convertDetector( - DetrayConversionUtils::GeometryIdCache& geoIdCache, - const GeometryContext& gctx, const Experimental::Detector& detector, - const Acts::Logger& logger); + DetrayConversionUtils::Cache& cCache, const GeometryContext& gctx, + const Experimental::Detector& detector, const Acts::Logger& logger); } // namespace DetrayGeometryConverter } // namespace Acts diff --git a/Plugins/Detray/include/Acts/Plugins/Detray/DetrayMaterialConverter.hpp b/Plugins/Detray/include/Acts/Plugins/Detray/DetrayMaterialConverter.hpp index d3be849e362..70a2c8cec73 100644 --- a/Plugins/Detray/include/Acts/Plugins/Detray/DetrayMaterialConverter.hpp +++ b/Plugins/Detray/include/Acts/Plugins/Detray/DetrayMaterialConverter.hpp @@ -35,15 +35,15 @@ detray::io::material_slab_payload convertMaterialSlab( /// Conversion method for homogeneous material /// -/// @param geoIdCache object to have the link association from the geometry building +/// @param cCache object to have the link association from the geometry building /// @param detector the detector object /// @param logger the logger object for screen output /// /// @return the volume_payload for portals and volumes by @param volume acts object detray::io::detector_homogeneous_material_payload -convertHomogeneousSurfaceMaterial( - const DetrayConversionUtils::GeometryIdCache& geoIdCache, - const Experimental::Detector& detector, const Logger& logger); +convertHomogeneousSurfaceMaterial(const DetrayConversionUtils::Cache& cCache, + const Experimental::Detector& detector, + const Logger& logger); /// Conversion method for grid based surface material /// @@ -58,16 +58,16 @@ convertGridSurfaceMaterial(const ISurfaceMaterial& material, /// Conversion method for material grids /// -/// @param geoIdCache object to have the link association from the geometry building +/// @param cCache object to have the link association from the geometry building /// @param detector the detector object /// @param logger the logger object for screen output /// /// @return the volume_payload for portals and volumes by @param volume acts object detray::io::detector_grids_payload -convertGridSurfaceMaterial( - const DetrayConversionUtils::GeometryIdCache& geoIdCache, - const Experimental::Detector& detector, const Logger& logger); +convertGridSurfaceMaterial(const DetrayConversionUtils::Cache& cCache, + const Experimental::Detector& detector, + const Logger& logger); } // namespace DetrayMaterialConverter diff --git a/Plugins/Detray/src/DetrayGeometryConverter.cpp b/Plugins/Detray/src/DetrayGeometryConverter.cpp index 664900841f0..23eb56a0f8c 100644 --- a/Plugins/Detray/src/DetrayGeometryConverter.cpp +++ b/Plugins/Detray/src/DetrayGeometryConverter.cpp @@ -27,25 +27,6 @@ using namespace detray; -namespace { - -/// Find the position of the volume to point to -/// -/// @param volume the volume to find -/// @param the collection of volumes -/// -/// @note return -1 if not found, to be interpreted by the caller -int findVolume( - const Acts::Experimental::DetectorVolume* volume, - const std::vector& volumes) { - auto candidate = std::ranges::find(volumes, volume); - if (candidate != volumes.end()) { - return std::distance(volumes.begin(), candidate); - } - return -1; -} -} // namespace - detray::io::transform_payload Acts::DetrayGeometryConverter::convertTransform( const Transform3& t) { detray::io::transform_payload tfPayload; @@ -87,10 +68,10 @@ detray::io::surface_payload Acts::DetrayGeometryConverter::convertSurface( std::vector Acts::DetrayGeometryConverter::convertPortal( - const GeometryContext& gctx, const Experimental::Portal& portal, - std::size_t ip, const Experimental::DetectorVolume& volume, - const std::vector& orientedSurfaces, - const std::vector& detectorVolumes) { + DetrayConversionUtils::Cache& cCache, const GeometryContext& gctx, + const Experimental::Portal& portal, std::size_t ip, + const Experimental::DetectorVolume& volume, + const std::vector& orientedSurfaces) { std::vector portals{}; const RegularSurface& surface = portal.surface(); @@ -135,7 +116,7 @@ Acts::DetrayGeometryConverter::convertPortal( // in order to make sure the size is adjusted if (singleLink != nullptr) { // Single link can be written out - std::size_t vLink = findVolume(singleLink->object(), detectorVolumes); + std::size_t vLink = cCache.volumeIndex(singleLink->object()); auto portalPayload = convertSurface(gctx, *surfaceAdjusted, true); portalPayload.mask.volume_link.link = vLink; portals.push_back(portalPayload); @@ -161,10 +142,10 @@ Acts::DetrayGeometryConverter::convertPortal( auto surfaceType = surfaceAdjusted->type(); std::vector vIndices = {}; for (const auto& v : volumes) { - vIndices.push_back(findVolume(v, detectorVolumes)); + vIndices.push_back(cCache.volumeIndex(v)); } - // Pick the surface dimension - via poly + // Pick the surface dimension std::array clipRange = {0., 0.}; std::vector boundValues = surfaceAdjusted->bounds().values(); if (surfaceType == Surface::SurfaceType::Cylinder && @@ -227,6 +208,7 @@ Acts::DetrayGeometryConverter::convertPortal( 0., 0., clippedBoundaries[ib - 1u] + subBoundValues[CylinderBounds::BoundValues::eHalfLengthZ])); + auto subSurface = Surface::makeShared(subTransform, subBounds); subSurface->assignGeometryId(surface.geometryId()); @@ -251,6 +233,7 @@ Acts::DetrayGeometryConverter::convertPortal( auto subBounds = std::make_shared(subBoundValues); auto subSurface = Surface::makeShared( portal.surface().transform(gctx), subBounds); + subSurface->assignGeometryId(surface.geometryId()); auto portalPayload = convertSurface(gctx, *subSurface, true); portalPayload.mask.volume_link.link = clippedIndices[ib - 1u]; @@ -260,7 +243,6 @@ Acts::DetrayGeometryConverter::convertPortal( } } else { - // End of world portal // Write surface with invalid link auto portalPayload = convertSurface(gctx, *surfaceAdjusted, true); using NavigationLink = @@ -271,27 +253,27 @@ Acts::DetrayGeometryConverter::convertPortal( portals.push_back(portalPayload); } } - return portals; } detray::io::volume_payload Acts::DetrayGeometryConverter::convertVolume( - DetrayConversionUtils::GeometryIdCache& geoIdCache, - const GeometryContext& gctx, + DetrayConversionUtils::Cache& cCache, const GeometryContext& gctx, const Acts::Experimental::DetectorVolume& volume, - const std::vector& detectorVolumes, const Acts::Logger& logger) { ACTS_DEBUG("DetrayGeometryConverter: converting volume " << volume.name() << " with " << volume.surfaces().size() << " surfaces and " << volume.portals().size() << " portals"); detray::io::volume_payload volumePayload; + std::size_t volumeIndex = cCache.volumeIndex(&volume); volumePayload.name = volume.name(); - volumePayload.index.link = findVolume(&volume, detectorVolumes); + volumePayload.index.link = volumeIndex; volumePayload.transform = convertTransform(volume.transform(gctx)); // Remember the link - geoIdCache.volumeLinks[volume.geometryId()] = volumePayload.index.link; + cCache.volumeLinks[volume.geometryId()] = volumePayload.index.link; + + std::multimap localSurfaceLinks; // iterate over surfaces and portals keeping the same surf_pd.index_in_coll std::size_t sIndex = 0; @@ -299,7 +281,7 @@ detray::io::volume_payload Acts::DetrayGeometryConverter::convertVolume( io::surface_payload surfacePayload = convertSurface(gctx, *surface, false); // Set the index in the collection & remember it in the cache surfacePayload.index_in_coll = sIndex++; - geoIdCache.localSurfaceLinks.insert( + localSurfaceLinks.insert( {surface->geometryId(), surfacePayload.index_in_coll.value()}); // Set mask to volume link surfacePayload.mask.volume_link.link = @@ -314,30 +296,32 @@ detray::io::volume_payload Acts::DetrayGeometryConverter::convertVolume( int portalCounter = 0; for (const auto& [ip, p] : enumerate(volume.portals())) { auto portals = - convertPortal(gctx, *p, ip, volume, orientedSurfaces, detectorVolumes); - + convertPortal(cCache, gctx, *p, ip, volume, orientedSurfaces); + ACTS_VERBOSE(" > portal " << ip << " split into " << portals.size() + << " surfaces"); GeometryIdentifier geoID = p->surface().geometryId(); std::for_each(portals.begin(), portals.end(), [&](auto& portalPayload) { // Set the index in the collection & remember it in the cache portalPayload.index_in_coll = sIndex++; - geoIdCache.localSurfaceLinks.insert( - {geoID, portalPayload.index_in_coll.value()}); + localSurfaceLinks.insert({geoID, portalPayload.index_in_coll.value()}); // Add it to the surfaces volumePayload.surfaces.push_back(portalPayload); portalCounter++; }); } - ACTS_VERBOSE(" > " << volume.portals().size() - << " initial ACTS portals split into final " - << portalCounter << " detray portals"); + cCache.localSurfaceLinks[volumeIndex] = localSurfaceLinks; + ACTS_DEBUG(" > " << volume.portals().size() + << " initial ACTS portals split into final " << portalCounter + << " detray portals"); + ACTS_VERBOSE(" > Local surface link cache has " << localSurfaceLinks.size() + << " entries"); return volumePayload; } detray::io::detector_payload Acts::DetrayGeometryConverter::convertDetector( - DetrayConversionUtils::GeometryIdCache& geoIdCache, - const GeometryContext& gctx, const Acts::Experimental::Detector& detector, - const Acts::Logger& logger) { + DetrayConversionUtils::Cache& cCache, const GeometryContext& gctx, + const Acts::Experimental::Detector& detector, const Acts::Logger& logger) { ACTS_DEBUG("DetrayGeometryConverter: converting detector" << detector.name() << " with " << detector.volumes().size() << " volumes."); @@ -347,7 +331,7 @@ detray::io::detector_payload Acts::DetrayGeometryConverter::convertDetector( for (const auto volume : detector.volumes()) { detectorPayload.volumes.push_back( - convertVolume(geoIdCache, gctx, *volume, detector.volumes(), logger)); + convertVolume(cCache, gctx, *volume, logger)); } return detectorPayload; diff --git a/Plugins/Detray/src/DetrayMaterialConverter.cpp b/Plugins/Detray/src/DetrayMaterialConverter.cpp index dd82b0d1b93..c08bdc447bf 100644 --- a/Plugins/Detray/src/DetrayMaterialConverter.cpp +++ b/Plugins/Detray/src/DetrayMaterialConverter.cpp @@ -52,13 +52,13 @@ Acts::DetrayMaterialConverter::convertMaterialSlab( detray::io::detector_homogeneous_material_payload Acts::DetrayMaterialConverter::convertHomogeneousSurfaceMaterial( - const DetrayConversionUtils::GeometryIdCache& geoIdCache, + const DetrayConversionUtils::Cache& cCache, const Experimental::Detector& detector, const Logger& logger) { detray::io::detector_homogeneous_material_payload materialPayload; for (const auto volume : detector.volumes()) { - auto volumeIndex = geoIdCache.volumeLinks.find(volume->geometryId()); - if (volumeIndex != geoIdCache.volumeLinks.end()) { + auto volumeIndex = cCache.volumeLinks.find(volume->geometryId()); + if (volumeIndex != cCache.volumeLinks.end()) { // The volume material payload & its link detray::io::material_volume_payload volumePayload; detray::io::single_link_payload volumeLink; @@ -80,18 +80,24 @@ Acts::DetrayMaterialConverter::convertHomogeneousSurfaceMaterial( auto materialSlab = homogeneousMaterial->materialSlab(); detray::io::material_slab_payload slabPayload = convertMaterialSlab(materialSlab); - // Find the surfaces and assign - auto surfaceIndices = - geoIdCache.localSurfaceLinks.equal_range(surface->geometryId()); - // Loop over the equal range and fill one grid each, this is needed - // as the initial portal could be split into multiple surfaces - for (auto itr = surfaceIndices.first; itr != surfaceIndices.second; - ++itr) { - // Make an identified link copy for every matching surface - detray::io::single_link_payload surfaceLink; - surfaceLink.link = itr->second; - slabPayload.surface = surfaceLink; - volumePayload.mat_slabs.push_back(slabPayload); + // Find the surfaces to assign + auto vIndex = cCache.volumeIndex(volume); + auto localSurfaceLinks = cCache.localSurfaceLinks.find(vIndex); + if (localSurfaceLinks != cCache.localSurfaceLinks.end()) { + // Find the surface link + auto surfaceIndices = + localSurfaceLinks->second.equal_range(surface->geometryId()); + // Loop over the equal range and fill one grid each, this is needed + // as the initial portal could be split into multiple surfaces + for (auto itr = surfaceIndices.first; itr != surfaceIndices.second; + ++itr) { + // Make an identified link copy for every matching surface + slabPayload.surface.link = itr->second; + volumePayload.mat_slabs.push_back(slabPayload); + } + } else { + ACTS_WARNING( + "DetrayMaterialConverter: no local surface links found"); } } } @@ -232,7 +238,7 @@ Acts::DetrayMaterialConverter::convertGridSurfaceMaterial( detray::io::detector_grids_payload Acts::DetrayMaterialConverter::convertGridSurfaceMaterial( - const DetrayConversionUtils::GeometryIdCache& geoIdCache, + const DetrayConversionUtils::Cache& cCache, const Experimental::Detector& detector, const Logger& logger) { // The material grid payload detray::io::detector_grids_payloadvisitSurfaces(selector); - ACTS_DEBUG("DetrayMaterialConverter: found " - << selector.surfaces.size() - << " surfaces/portals with material in volume " - << volume->name()); + ACTS_VERBOSE("DetrayMaterialConverter: found " + << selector.surfaces.size() + << " surfaces/portals with material in volume " + << volume->name()); // Find the voluem index first - auto volumeIndex = geoIdCache.volumeLinks.find(volume->geometryId()); - if (volumeIndex != geoIdCache.volumeLinks.end()) { + auto volumeIndex = cCache.volumeLinks.find(volume->geometryId()); + if (volumeIndex != cCache.volumeLinks.end()) { std::vector volumeMaterialGrids = {}; // Now convert the surfaces for (const auto& surface : selector.surfaces) { - // Find the surface index - auto surfaceIndices = - geoIdCache.localSurfaceLinks.equal_range(surface->geometryId()); - DetrayMaterialGrid materialGrid = - convertGridSurfaceMaterial(*surface->surfaceMaterial(), logger); - // Ignore if an empty payload is returned - if (materialGrid.axes.empty() && materialGrid.bins.empty()) { - continue; - } - // Loop over the equal range and fill one grid each, this is needed - // as the initial portal could be split into multiple surfaces - for (auto itr = surfaceIndices.first; itr != surfaceIndices.second; - ++itr) { - // Fill the surface index - materialGrid.owner_link = - detray::io::single_link_payload{itr->second}; - // Fill the grid - volumeMaterialGrids.push_back(materialGrid); + // Find the surfaces to assign + auto vIndex = cCache.volumeIndex(volume); + auto localSurfaceLinks = cCache.localSurfaceLinks.find(vIndex); + if (localSurfaceLinks != cCache.localSurfaceLinks.end()) { + // Find the surface link + auto surfaceIndices = + localSurfaceLinks->second.equal_range(surface->geometryId()); + + ACTS_VERBOSE( + "DetrayMaterialConverter: assigning to " + << std::distance(surfaceIndices.first, surfaceIndices.second) + << " surfaces with material in volume " << volume->name()); + DetrayMaterialGrid materialGrid = + convertGridSurfaceMaterial(*surface->surfaceMaterial(), logger); + // Ignore if an empty payload is returned + if (materialGrid.axes.empty() || materialGrid.bins.empty()) { + continue; + } + + // Loop over the equal range and fill one grid each, this is needed + // as the initial portal could be split into multiple surfaces + for (auto itr = surfaceIndices.first; itr != surfaceIndices.second; + ++itr) { + // Fill the surface index + materialGrid.owner_link = + detray::io::single_link_payload{itr->second}; + // Fill the grid + volumeMaterialGrids.push_back(materialGrid); + } } } // Register the grids of this volume materialGrids.grids.insert({volumeIndex->second, volumeMaterialGrids}); - } else { ACTS_WARNING( "DetrayMaterialConverter: volume not found in cache, should not " diff --git a/Tests/UnitTests/Plugins/Detray/DetrayGeometryConverterTests.cpp b/Tests/UnitTests/Plugins/Detray/DetrayGeometryConverterTests.cpp index 97c1c7dff13..2ed99f4a68b 100644 --- a/Tests/UnitTests/Plugins/Detray/DetrayGeometryConverterTests.cpp +++ b/Tests/UnitTests/Plugins/Detray/DetrayGeometryConverterTests.cpp @@ -107,10 +107,11 @@ BOOST_AUTO_TEST_CASE(DetrayVolumeConversion) { auto [volumes, portals, rootVolumes] = beampipe->construct(tContext); auto volume = volumes.front(); - DetrayConversionUtils::GeometryIdCache geoIdCache; + std::vector dVolumes = {volume.get()}; + DetrayConversionUtils::Cache cCache(dVolumes); detray::io::volume_payload payload = DetrayGeometryConverter::convertVolume( - geoIdCache, tContext, *volume, {volume.get()}, *logger); + cCache, tContext, *volume, *logger); // Check the volume payload BOOST_CHECK(payload.name == "BeamPipe"); @@ -134,10 +135,10 @@ BOOST_AUTO_TEST_CASE(CylindricalDetector) { auto detector = buildCylindricalDetector(tContext); // Convert the detector - DetrayConversionUtils::GeometryIdCache geoIdCache; + DetrayConversionUtils::Cache cCache(detector->volumes()); detray::io::detector_payload payload = - DetrayGeometryConverter::convertDetector(geoIdCache, tContext, *detector, + DetrayGeometryConverter::convertDetector(cCache, tContext, *detector, *logger); // Test the payload - we have six volumes From 2a82fda91bedcda0bb39760d1c515fea30b22c7d Mon Sep 17 00:00:00 2001 From: Benjamin Huth <37871400+benjaminhuth@users.noreply.github.com> Date: Fri, 18 Oct 2024 23:22:23 +0200 Subject: [PATCH 6/6] fix: Potential segfault in AthenaDumpReader (#3721) Some data seem to be not present in every root file being around... --- .../Io/Root/RootAthenaDumpReader.hpp | 53 ++++++++++--------- Examples/Io/Root/src/RootAthenaDumpReader.cpp | 47 +++++++++------- 2 files changed, 55 insertions(+), 45 deletions(-) diff --git a/Examples/Io/Root/include/ActsExamples/Io/Root/RootAthenaDumpReader.hpp b/Examples/Io/Root/include/ActsExamples/Io/Root/RootAthenaDumpReader.hpp index e917e07038d..2a09d8492b2 100644 --- a/Examples/Io/Root/include/ActsExamples/Io/Root/RootAthenaDumpReader.hpp +++ b/Examples/Io/Root/include/ActsExamples/Io/Root/RootAthenaDumpReader.hpp @@ -173,6 +173,7 @@ class RootAthenaDumpReader : public IReader { std::vector> m_eventMap; std::shared_ptr m_inputchain; long unsigned int m_events; + bool m_haveStripFeatures = true; static constexpr unsigned int maxCL = 1500000; static constexpr unsigned int maxSP = 1500000; @@ -189,7 +190,7 @@ class RootAthenaDumpReader : public IReader { int CLindex[maxCL] = {}; //[nCL] // Clusters - std::vector *CLhardware; + std::vector *CLhardware{}; Double_t CLx[maxCL] = {}; //[nCL] Double_t CLy[maxCL] = {}; //[nCL] Double_t CLz[maxCL] = {}; //[nCL] @@ -199,13 +200,13 @@ class RootAthenaDumpReader : public IReader { Int_t CLphi_module[maxCL] = {}; //[nCL] Int_t CLside[maxCL] = {}; //[nCL] ULong64_t CLmoduleID[maxCL] = {}; //[nCL] - std::vector> *CLparticleLink_eventIndex; - std::vector> *CLparticleLink_barcode; - std::vector> *CLbarcodesLinked; - std::vector> *CLparticle_charge; - std::vector> *CLphis; - std::vector> *CLetas; - std::vector> *CLtots; + std::vector> *CLparticleLink_eventIndex{}; + std::vector> *CLparticleLink_barcode{}; + std::vector> *CLbarcodesLinked{}; + std::vector> *CLparticle_charge{}; + std::vector> *CLphis{}; + std::vector> *CLetas{}; + std::vector> *CLtots{}; Double_t CLloc_direction1[maxCL] = {}; //[nCL] Double_t CLloc_direction2[maxCL] = {}; //[nCL] Double_t CLloc_direction3[maxCL] = {}; //[nCL] @@ -223,7 +224,7 @@ class RootAthenaDumpReader : public IReader { Float_t CLnorm_x[maxCL] = {}; //[nCL] Float_t CLnorm_y[maxCL] = {}; //[nCL] Float_t CLnorm_z[maxCL] = {}; //[nCL] - std::vector> *CLlocal_cov; + std::vector> *CLlocal_cov{}; // Particles Int_t nPartEVT = 0; @@ -246,8 +247,8 @@ class RootAthenaDumpReader : public IReader { Int_t Part_vProdNout[maxPart] = {}; //[nPartEVT] Int_t Part_vProdStatus[maxPart] = {}; //[nPartEVT] Int_t Part_vProdBarcode[maxPart] = {}; //[nPartEVT] - std::vector> *Part_vParentID; - std::vector> *Part_vParentBarcode; + std::vector> *Part_vParentID{}; + std::vector> *Part_vParentBarcode{}; // Spacepoints Int_t nSP = 0; @@ -263,27 +264,27 @@ class RootAthenaDumpReader : public IReader { double SPcovz[maxSP] = {}; //[nSP] float SPhl_topstrip[maxSP] = {}; //[nSP] float SPhl_botstrip[maxSP] = {}; //[nSP] - std::vector> *SPtopStripDirection; - std::vector> *SPbottomStripDirection; - std::vector> *SPstripCenterDistance; - std::vector> *SPtopStripCenterPosition; + std::vector> *SPtopStripDirection{}; + std::vector> *SPbottomStripDirection{}; + std::vector> *SPstripCenterDistance{}; + std::vector> *SPtopStripCenterPosition{}; // Tracks Int_t nTRK = 0; Int_t TRKindex[maxTRK] = {}; //[nTRK] Int_t TRKtrack_fitter[maxTRK] = {}; //[nTRK] Int_t TRKparticle_hypothesis[maxTRK] = {}; //[nTRK] - std::vector> *TRKproperties; - std::vector> *TRKpattern; + std::vector> *TRKproperties{}; + std::vector> *TRKpattern{}; Int_t TRKndof[maxTRK] = {}; //[nTRK] Int_t TRKmot[maxTRK] = {}; //[nTRK] Int_t TRKoot[maxTRK] = {}; //[nTRK] Float_t TRKchiSq[maxTRK] = {}; //[nTRK] - std::vector> *TRKmeasurementsOnTrack_pixcl_sctcl_index; - std::vector> *TRKoutliersOnTrack_pixcl_sctcl_index; + std::vector> *TRKmeasurementsOnTrack_pixcl_sctcl_index{}; + std::vector> *TRKoutliersOnTrack_pixcl_sctcl_index{}; Int_t TRKcharge[maxTRK] = {}; //[nTRK] - std::vector> *TRKperigee_position; - std::vector> *TRKperigee_momentum; + std::vector> *TRKperigee_position{}; + std::vector> *TRKperigee_momentum{}; Int_t TTCindex[maxTRK] = {}; //[nTRK] Int_t TTCevent_index[maxTRK] = {}; //[nTRK] Int_t TTCparticle_link[maxTRK] = {}; //[nTRK] @@ -293,10 +294,10 @@ class RootAthenaDumpReader : public IReader { Int_t nDTT = 0; Int_t DTTindex[maxDTT] = {}; //[nDTT] Int_t DTTsize[maxDTT] = {}; //[nDTT] - std::vector> *DTTtrajectory_eventindex; - std::vector> *DTTtrajectory_barcode; - std::vector> *DTTstTruth_subDetType; - std::vector> *DTTstTrack_subDetType; - std::vector> *DTTstCommon_subDetType; + std::vector> *DTTtrajectory_eventindex{}; + std::vector> *DTTtrajectory_barcode{}; + std::vector> *DTTstTruth_subDetType{}; + std::vector> *DTTstTrack_subDetType{}; + std::vector> *DTTstCommon_subDetType{}; }; } // namespace ActsExamples diff --git a/Examples/Io/Root/src/RootAthenaDumpReader.cpp b/Examples/Io/Root/src/RootAthenaDumpReader.cpp index eea524fe544..a732bb3b49e 100644 --- a/Examples/Io/Root/src/RootAthenaDumpReader.cpp +++ b/Examples/Io/Root/src/RootAthenaDumpReader.cpp @@ -84,6 +84,11 @@ RootAthenaDumpReader::RootAthenaDumpReader( m_outputMeasurements.initialize(m_cfg.outputMeasurements); } + if (m_inputchain->GetBranch("SPtopStripDirection") == nullptr) { + ACTS_WARNING("Additional SP strip features not available"); + m_haveStripFeatures = false; + } + // Set the branches // Set object pointer @@ -192,13 +197,13 @@ RootAthenaDumpReader::RootAthenaDumpReader( m_inputchain->SetBranchAddress("SPcovz", SPcovz); m_inputchain->SetBranchAddress("SPhl_topstrip", SPhl_topstrip); m_inputchain->SetBranchAddress("SPhl_botstrip", SPhl_botstrip); - m_inputchain->SetBranchAddress("SPtopStripDirection", SPtopStripDirection); + m_inputchain->SetBranchAddress("SPtopStripDirection", &SPtopStripDirection); m_inputchain->SetBranchAddress("SPbottomStripDirection", - SPbottomStripDirection); + &SPbottomStripDirection); m_inputchain->SetBranchAddress("SPstripCenterDistance", - SPstripCenterDistance); + &SPstripCenterDistance); m_inputchain->SetBranchAddress("SPtopStripCenterPosition", - SPtopStripCenterPosition); + &SPtopStripCenterPosition); m_inputchain->SetBranchAddress("nTRK", &nTRK); m_inputchain->SetBranchAddress("TRKindex", TRKindex); @@ -578,21 +583,25 @@ RootAthenaDumpReader::readSpacepoints( sLinks.emplace_back(second); using Vector3f = Eigen::Matrix; - const Vector3f topStripDirection{SPtopStripDirection->at(isp).at(0), - SPtopStripDirection->at(isp).at(1), - SPtopStripDirection->at(isp).at(2)}; - const Vector3f bottomStripDirection{ - SPbottomStripDirection->at(isp).at(0), - SPbottomStripDirection->at(isp).at(1), - SPbottomStripDirection->at(isp).at(2)}; - const Vector3f stripCenterDistance{SPstripCenterDistance->at(isp).at(0), - SPstripCenterDistance->at(isp).at(1), - SPstripCenterDistance->at(isp).at(2)}; - const Vector3f topStripCenterPosition{ - SPtopStripCenterPosition->at(isp).at(0), - SPtopStripCenterPosition->at(isp).at(1), - SPtopStripCenterPosition->at(isp).at(2)}; - + Vector3f topStripDirection = Vector3f::Zero(); + Vector3f bottomStripDirection = Vector3f::Zero(); + Vector3f stripCenterDistance = Vector3f::Zero(); + Vector3f topStripCenterPosition = Vector3f::Zero(); + + if (m_haveStripFeatures) { + topStripDirection = {SPtopStripDirection->at(isp).at(0), + SPtopStripDirection->at(isp).at(1), + SPtopStripDirection->at(isp).at(2)}; + bottomStripDirection = {SPbottomStripDirection->at(isp).at(0), + SPbottomStripDirection->at(isp).at(1), + SPbottomStripDirection->at(isp).at(2)}; + stripCenterDistance = {SPstripCenterDistance->at(isp).at(0), + SPstripCenterDistance->at(isp).at(1), + SPstripCenterDistance->at(isp).at(2)}; + topStripCenterPosition = {SPtopStripCenterPosition->at(isp).at(0), + SPtopStripCenterPosition->at(isp).at(1), + SPtopStripCenterPosition->at(isp).at(2)}; + } sp = SimSpacePoint(globalPos, std::nullopt, spCovr, spCovz, std::nullopt, sLinks, SPhl_topstrip[isp], SPhl_botstrip[isp], topStripDirection.cast(),