Repository: acts-project/acts
Pull request #4090: feat: Allow compiling examples without ROOT
Author: login: benjaminhuth
Labels: name: Infrastructure
description: Changes to build tools, continous integration, ...
name: Component - Examples
description: Affects the Examples module
name: Component - Documentation
description: Affects the documentation
Created: 2025-02-14T13:05:50Z | Merged: 2025-04-09T14:17:36Z

First step towards `pip install acts`?

--- END COMMIT MESSAGE ---

Any further description goes here, @-mentions are ok here!

- Use a *conventional commits* prefix: [quick summary](https://www.conventionalcommits.org/en/v1.0.0/#summary)
  - We mostly use `feat`, `fix`, `refactor`, `docs`, `chore` and `build` types.
- A milestone will be assigned by one of the maintainers


<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

- **New Features**
  - Introduced a configurable build option that enables advanced ROOT I/O components.
  - Enhanced Python integration with new input and output capabilities when ROOT I/O is activated.

- **Refactor**
  - Updated module inclusion to conditionally incorporate ROOT functionalities, modernizing input handling and streamlining dependencies.

- **Documentation**
  - Revised build instructions to document the new option for enabling ROOT I/O–based modules.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->


Diff:
diff --git a/.github/workflows/builds.yml b/.github/workflows/builds.yml
index 82c89d9d5a4..a1e1aefef24 100644
--- a/.github/workflows/builds.yml
+++ b/.github/workflows/builds.yml
@@ -111,6 +111,22 @@ jobs:
       - name: Downstream run
         run: ./build-downstream/bin/ShowActsVersion
 
+      # We configure and build without ROOT in the same job to garantuee that we can use the ccache cache
+      - name: Configure (without ROOT)
+        run: >
+          ccache -z &&
+          rm -rf build &&
+          cmake -B build -S .
+          --preset=github-ci-no-root
+          -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}"
+          -DPython_EXECUTABLE=$(which python3)
+
+      - name: Build (without ROOT)
+        run: cmake --build build
+
+      - name: ccache stats (without ROOT)
+        run: ccache -s
+
   linux_examples_test:
     runs-on: ubuntu-latest
     container: ghcr.io/acts-project/ubuntu2404:63
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7d9f6178b0f..67ce1eeb240 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -103,6 +103,7 @@ option(ACTS_BUILD_EXAMPLES_HEPMC3 "Build HepMC3-based code in the examples" OFF)
 option(ACTS_BUILD_EXAMPLES_HASHING "Build Hashing-based code in the examples" OFF)
 option(ACTS_BUILD_EXAMPLES_PYTHIA8 "Build Pythia8-based code in the examples" OFF)
 option(ACTS_BUILD_EXAMPLES_PYTHON_BINDINGS "Build python bindings for the examples" OFF)
+option(ACTS_BUILD_EXAMPLES_ROOT "Build modules based on ROOT I/O" ON)
 option(ACTS_BUILD_ANALYSIS_APPS "Build Analysis applications in the examples" OFF)
 # test related options
 option(ACTS_BUILD_BENCHMARKS "Build benchmarks" OFF)
@@ -506,6 +507,8 @@ endif()
 if(ACTS_BUILD_EXAMPLES)
     set(THREADS_PREFER_PTHREAD_FLAG ON)
     find_package(Threads REQUIRED)
+endif()
+if(ACTS_BUILD_EXAMPLES_ROOT)
     # for simplicity always request all potentially required components.
     find_package(
         ROOT
diff --git a/CMakePresets.json b/CMakePresets.json
index d6b965d9060..e7dc9982256 100644
--- a/CMakePresets.json
+++ b/CMakePresets.json
@@ -17,6 +17,7 @@
                 "ACTS_BUILD_PLUGIN_LEGACY": "ON",
                 "ACTS_BUILD_EXAMPLES_DD4HEP": "ON",
                 "ACTS_BUILD_EXAMPLES_PYTHON_BINDINGS": "ON",
+                "ACTS_BUILD_EXAMPLES_ROOT": "ON",
                 "ACTS_BUILD_EXAMPLES_UNITTESTS": "ON"
             }
         },
@@ -82,6 +83,14 @@
                 "CMAKE_BUILD_TYPE": "Release"
             }
         },
+        {
+            "name": "github-ci-no-root",
+            "displayName": "GitHub-CI (without ROOT)",
+            "inherits": "github-ci",
+            "cacheVariables": {
+                "ACTS_BUILD_EXAMPLES_ROOT": "OFF"
+            }
+        },
         {
             "name": "gitlab-ci",
             "displayName": "GitLab-CI",
@@ -122,6 +131,7 @@
                 "CMAKE_CXX_FLAGS": "-w",
                 "CMAKE_CUDA_FLAGS": "-w",
                 "ACTS_BUILD_PLUGIN_EXATRKX": "ON",
+                "ACTS_BUILD_EXAMPLES_ROOT": "ON",
                 "ACTS_BUILD_EXAMPLES_EXATRKX": "ON",
                 "ACTS_BUILD_UNITTESTS": "ON",
                 "ACTS_EXATRKX_ENABLE_TORCH": "ON",
diff --git a/Examples/Io/CMakeLists.txt b/Examples/Io/CMakeLists.txt
index 8b7f2861a6e..0d3da57e125 100644
--- a/Examples/Io/CMakeLists.txt
+++ b/Examples/Io/CMakeLists.txt
@@ -3,5 +3,5 @@ add_subdirectory_if(EDM4hep ACTS_BUILD_EXAMPLES_EDM4HEP)
 add_subdirectory_if(HepMC3 ACTS_BUILD_EXAMPLES_HEPMC3)
 add_subdirectory(Json)
 add_subdirectory(Obj)
-add_subdirectory(Root)
+add_subdirectory_if(Root ACTS_BUILD_EXAMPLES_ROOT)
 add_subdirectory_if(Svg ACTS_BUILD_PLUGIN_ACTSVG)
diff --git a/Examples/Python/CMakeLists.txt b/Examples/Python/CMakeLists.txt
index 03b10152879..74dd5c61600 100644
--- a/Examples/Python/CMakeLists.txt
+++ b/Examples/Python/CMakeLists.txt
@@ -55,7 +55,6 @@ target_link_libraries(
         ActsExamplesDetectorContextual
         ActsExamplesDetectorTGeo
         ActsExamplesMagneticField
-        ActsExamplesIoRoot
         ActsExamplesIoCsv
         ActsExamplesIoObj
         ActsExamplesIoJson
@@ -84,6 +83,16 @@ set(py_files
     _adapter.py
 )
 
+if(ACTS_BUILD_EXAMPLES_ROOT)
+    target_link_libraries(ActsPythonBindings PUBLIC ActsExamplesIoRoot)
+    target_sources(
+        ActsPythonBindings
+        PRIVATE src/RootInput.cpp src/RootOutput.cpp
+    )
+else()
+    target_sources(ActsPythonBindings PRIVATE src/RootStub.cpp)
+endif()
+
 if(ACTS_BUILD_PLUGIN_JSON)
     target_link_libraries(ActsPythonBindings PUBLIC ActsPluginJson)
     target_sources(ActsPythonBindings PRIVATE src/Json.cpp)
diff --git a/Examples/Python/src/Input.cpp b/Examples/Python/src/Input.cpp
index a69b4545062..3fbe14a083b 100644
--- a/Examples/Python/src/Input.cpp
+++ b/Examples/Python/src/Input.cpp
@@ -17,15 +17,7 @@
 #include "ActsExamples/Io/Csv/CsvSimHitReader.hpp"
 #include "ActsExamples/Io/Csv/CsvSpacePointReader.hpp"
 #include "ActsExamples/Io/Csv/CsvTrackParameterReader.hpp"
-#include "ActsExamples/Io/Root/RootAthenaDumpReader.hpp"
-#include "ActsExamples/Io/Root/RootAthenaNTupleReader.hpp"
-#include "ActsExamples/Io/Root/RootMaterialTrackReader.hpp"
-#include "ActsExamples/Io/Root/RootParticleReader.hpp"
-#include "ActsExamples/Io/Root/RootSimHitReader.hpp"
-#include "ActsExamples/Io/Root/RootTrackSummaryReader.hpp"
-#include "ActsExamples/Io/Root/RootVertexReader.hpp"
-
-#include <memory>
+#include "ActsExamples/TrackFinding/ITrackParamsLookupReader.hpp"
 
 #include <pybind11/pybind11.h>
 #include <pybind11/stl.h>
@@ -45,24 +37,6 @@ void addInput(Context& ctx) {
                              "BufferedReader", upstreamReader, selectionSeed,
                              bufferSize);
 
-  // ROOT READERS
-  ACTS_PYTHON_DECLARE_READER(ActsExamples::RootParticleReader, mex,
-                             "RootParticleReader", outputParticles, treeName,
-                             filePath);
-
-  ACTS_PYTHON_DECLARE_READER(ActsExamples::RootVertexReader, mex,
-                             "RootVertexReader", outputVertices, treeName,
-                             filePath);
-
-  ACTS_PYTHON_DECLARE_READER(ActsExamples::RootMaterialTrackReader, mex,
-                             "RootMaterialTrackReader", outputMaterialTracks,
-                             treeName, fileList, readCachedSurfaceInformation);
-
-  ACTS_PYTHON_DECLARE_READER(ActsExamples::RootTrackSummaryReader, mex,
-                             "RootTrackSummaryReader", outputTracks,
-                             outputParticles, treeName, filePath);
-
-  // CSV READERS
   ACTS_PYTHON_DECLARE_READER(ActsExamples::CsvParticleReader, mex,
                              "CsvParticleReader", inputDir, inputStem,
                              outputParticles);
@@ -90,34 +64,13 @@ void addInput(Context& ctx) {
                              "CsvTrackParameterReader", inputDir, inputStem,
                              outputTrackParameters, beamspot);
 
-  ACTS_PYTHON_DECLARE_READER(ActsExamples::RootAthenaNTupleReader, mex,
-                             "RootAthenaNTupleReader", inputTreeName,
-                             inputFilePath, outputTrackParameters,
-                             outputTruthVtxParameters, outputRecoVtxParameters,
-                             outputBeamspotConstraint);
-
-  ACTS_PYTHON_DECLARE_READER(
-      ActsExamples::RootAthenaDumpReader, mex, "RootAthenaDumpReader", treename,
-      inputfiles, outputMeasurements, outputPixelSpacePoints,
-      outputStripSpacePoints, outputSpacePoints, outputClusters,
-      outputMeasurementParticlesMap, outputParticleMeasurementsMap,
-      outputParticles, onlySpacepoints, onlyPassedParticles, skipOverlapSPsPhi,
-      skipOverlapSPsEta, geometryIdMap, trackingGeometry, absBoundaryTolerance,
-      onlySpacepoints, noTruth, readCellData);
-
-#ifdef WITH_GEOMODEL_PLUGIN
-  ACTS_PYTHON_DECLARE_READER(ActsExamples::RootAthenaDumpGeoIdCollector, mex,
-                             "RootAthenaDumpGeoIdCollector", treename,
-                             inputfile, trackingGeometry, geometryIdMap);
-#endif
-
-  ACTS_PYTHON_DECLARE_READER(ActsExamples::RootSimHitReader, mex,
-                             "RootSimHitReader", treeName, filePath,
-                             outputSimHits);
-
   ACTS_PYTHON_DECLARE_READER(ActsExamples::CsvExaTrkXGraphReader, mex,
                              "CsvExaTrkXGraphReader", inputDir, inputStem,
                              outputGraph);
+
+  py::class_<ActsExamples::ITrackParamsLookupReader,
+             std::shared_ptr<ActsExamples::ITrackParamsLookupReader>>(
+      mex, "ITrackParamsLookupReader");
 }
 
 }  // namespace Acts::Python
diff --git a/Examples/Python/src/Material.cpp b/Examples/Python/src/Material.cpp
index 308bb2af99f..f794336adf7 100644
--- a/Examples/Python/src/Material.cpp
+++ b/Examples/Python/src/Material.cpp
@@ -25,7 +25,6 @@
 #include "Acts/Plugins/Python/Utilities.hpp"
 #include "Acts/Utilities/Logger.hpp"
 #include "ActsExamples/Framework/ProcessCode.hpp"
-#include "ActsExamples/Io/Root/RootMaterialDecorator.hpp"
 #include "ActsExamples/MaterialMapping/CoreMaterialMapping.hpp"
 #include "ActsExamples/MaterialMapping/MappingMaterialDecorator.hpp"
 #include "ActsExamples/MaterialMapping/MaterialMapping.hpp"
@@ -86,23 +85,6 @@ void addMaterial(Context& ctx) {
                              &Acts::IMaterialDecorator::decorate, py::const_));
   }
 
-  {
-    auto rmd =
-        py::class_<RootMaterialDecorator, Acts::IMaterialDecorator,
-                   std::shared_ptr<RootMaterialDecorator>>(
-            mex, "RootMaterialDecorator")
-            .def(
-                py::init<RootMaterialDecorator::Config, Acts::Logging::Level>(),
-                py::arg("config"), py::arg("level"));
-
-    using Config = RootMaterialDecorator::Config;
-    auto c = py::class_<Config>(rmd, "Config").def(py::init<>());
-
-    ACTS_PYTHON_STRUCT(c, voltag, boutag, laytag, apptag, sentag, ntag, vtag,
-                       otag, mintag, maxtag, ttag, x0tag, l0tag, atag, ztag,
-                       rhotag, fileName);
-  }
-
   {
     py::class_<MappingMaterialDecorator, Acts::IMaterialDecorator,
                std::shared_ptr<MappingMaterialDecorator>>(
diff --git a/Examples/Python/src/ModuleEntry.cpp b/Examples/Python/src/ModuleEntry.cpp
index 9f494dddee6..ef9f088da32 100644
--- a/Examples/Python/src/ModuleEntry.cpp
+++ b/Examples/Python/src/ModuleEntry.cpp
@@ -56,6 +56,9 @@ void addVertexing(Context& ctx);
 void addAmbiguityResolution(Context& ctx);
 void addUtilities(Context& ctx);
 
+void addRootInput(Context& ctx);
+void addRootOutput(Context& ctx);
+
 // Plugins
 void addDigitization(Context& ctx);
 void addPythia8(Context& ctx);
@@ -143,4 +146,7 @@ PYBIND11_MODULE(ActsPythonBindings, m) {
   addCovfie(ctx);
   addTraccc(ctx);
   addHashing(ctx);
+
+  addRootInput(ctx);
+  addRootOutput(ctx);
 }
diff --git a/Examples/Python/src/Output.cpp b/Examples/Python/src/Output.cpp
index c9bc29f720b..3fc337265b3 100644
--- a/Examples/Python/src/Output.cpp
+++ b/Examples/Python/src/Output.cpp
@@ -25,32 +25,11 @@
 #include "ActsExamples/Io/Obj/ObjPropagationStepsWriter.hpp"
 #include "ActsExamples/Io/Obj/ObjSimHitWriter.hpp"
 #include "ActsExamples/Io/Obj/ObjTrackingGeometryWriter.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"
-#include "ActsExamples/Io/Root/RootSeedWriter.hpp"
-#include "ActsExamples/Io/Root/RootSimHitWriter.hpp"
-#include "ActsExamples/Io/Root/RootSpacepointWriter.hpp"
-#include "ActsExamples/Io/Root/RootTrackParameterWriter.hpp"
-#include "ActsExamples/Io/Root/RootTrackStatesWriter.hpp"
-#include "ActsExamples/Io/Root/RootTrackSummaryWriter.hpp"
-#include "ActsExamples/Io/Root/RootVertexWriter.hpp"
-#include "ActsExamples/Io/Root/TrackFinderNTupleWriter.hpp"
-#include "ActsExamples/Io/Root/TrackFinderPerformanceWriter.hpp"
-#include "ActsExamples/Io/Root/TrackFitterPerformanceWriter.hpp"
-#include "ActsExamples/Io/Root/VertexNTupleWriter.hpp"
 #include "ActsExamples/MaterialMapping/IMaterialWriter.hpp"
-#include "ActsExamples/TrackFinding/ITrackParamsLookupReader.hpp"
 #include "ActsExamples/TrackFinding/ITrackParamsLookupWriter.hpp"
 
 #include <memory>
 #include <string>
-#include <vector>
 
 #include <pybind11/pybind11.h>
 #include <pybind11/stl.h>
@@ -147,161 +126,6 @@ void addOutput(Context& ctx) {
                        gridView);
   }
 
-  // Bindings for the binning in e.g., TrackFinderPerformanceWriter
-  {
-    py::class_<PlotHelpers::Binning>(mex, "Binning")
-        .def(py::init<std::string, int, double, double>(), "title"_a, "bins"_a,
-             "bMin"_a, "bMax"_a)
-        .def(py::init<std::string, std::vector<double>>(), "title"_a, "bins"_a);
-
-    py::class_<EffPlotTool::Config>(mex, "EffPlotToolConfig")
-        .def(py::init<std::map<std::string, PlotHelpers::Binning>>(),
-             "varBinning"_a);
-
-    py::class_<FakeRatePlotTool::Config>(mex, "FakeRatePlotToolConfig")
-        .def(py::init<std::map<std::string, PlotHelpers::Binning>>(),
-             "varBinning"_a);
-
-    py::class_<DuplicationPlotTool::Config>(mex, "DuplicationPlotToolConfig")
-        .def(py::init<std::map<std::string, PlotHelpers::Binning>>(),
-             "varBinning"_a);
-  }
-
-  // ROOT WRITERS
-  ACTS_PYTHON_DECLARE_WRITER(ActsExamples::RootPropagationStepsWriter, mex,
-                             "RootPropagationStepsWriter", collection, filePath,
-                             fileMode);
-
-  ACTS_PYTHON_DECLARE_WRITER(ActsExamples::RootPropagationSummaryWriter, mex,
-                             "RootPropagationSummaryWriter",
-                             inputSummaryCollection, filePath, fileMode);
-
-  ACTS_PYTHON_DECLARE_WRITER(ActsExamples::RootParticleWriter, mex,
-                             "RootParticleWriter", inputParticles, filePath,
-                             fileMode, treeName);
-
-  ACTS_PYTHON_DECLARE_WRITER(ActsExamples::RootVertexWriter, mex,
-                             "RootVertexWriter", inputVertices, filePath,
-                             fileMode, treeName);
-
-  ACTS_PYTHON_DECLARE_WRITER(ActsExamples::TrackFinderNTupleWriter, mex,
-                             "TrackFinderNTupleWriter", inputTracks,
-                             inputParticles, inputParticleMeasurementsMap,
-                             inputTrackParticleMatching, filePath, fileMode,
-                             treeNameTracks, treeNameParticles);
-
-  ACTS_PYTHON_DECLARE_WRITER(ActsExamples::TrackFitterPerformanceWriter, mex,
-                             "TrackFitterPerformanceWriter", inputTracks,
-                             inputParticles, inputTrackParticleMatching,
-                             filePath, resPlotToolConfig, effPlotToolConfig,
-                             trackSummaryPlotToolConfig);
-
-  ACTS_PYTHON_DECLARE_WRITER(
-      ActsExamples::RootTrackParameterWriter, mex, "RootTrackParameterWriter",
-      inputTrackParameters, inputProtoTracks, inputParticles, inputSimHits,
-      inputMeasurementParticlesMap, inputMeasurementSimHitsMap, filePath,
-      treeName, fileMode);
-
-  ACTS_PYTHON_DECLARE_WRITER(
-      ActsExamples::RootMaterialTrackWriter, mex, "RootMaterialTrackWriter",
-      inputMaterialTracks, filePath, fileMode, treeName, recalculateTotals,
-      prePostStep, storeSurface, storeVolume, collapseInteractions);
-
-  {
-    using Writer = ActsExamples::RootBFieldWriter;
-    auto w =
-        py::class_<Writer>(mex, "RootBFieldWriter")
-            .def_static(
-                "run",
-                [](const Writer::Config& config, Acts::Logging::Level level) {
-                  Writer::run(config, Acts::getDefaultLogger("RootBFieldWriter",
-                                                             level));
-                },
-                py::arg("config"), py::arg("level"));
-
-    py::enum_<Writer::GridType>(w, "GridType")
-        .value("rz", Writer::GridType::rz)
-        .value("xyz", Writer::GridType::xyz);
-
-    auto c = py::class_<Writer::Config>(w, "Config").def(py::init<>());
-    ACTS_PYTHON_STRUCT(c, treeName, fileName, fileMode, bField, gridType,
-                       rBounds, zBounds, rBins, zBins, phiBins);
-  }
-
-  {
-    using Writer = ActsExamples::RootMeasurementWriter;
-    auto w = py::class_<Writer, IWriter, std::shared_ptr<Writer>>(
-                 mex, "RootMeasurementWriter")
-                 .def(py::init<const Writer::Config&, Acts::Logging::Level>(),
-                      py::arg("config"), py::arg("level"));
-
-    auto c = py::class_<Writer::Config>(w, "Config").def(py::init<>());
-
-    ACTS_PYTHON_STRUCT(c, inputMeasurements, inputClusters, inputSimHits,
-                       inputMeasurementSimHitsMap, filePath, fileMode,
-                       surfaceByIdentifier);
-  }
-
-  py::class_<IMaterialWriter, std::shared_ptr<IMaterialWriter>>(
-      mex, "IMaterialWriter");
-
-  py::class_<ActsExamples::ITrackParamsLookupWriter,
-             std::shared_ptr<ActsExamples::ITrackParamsLookupWriter>>(
-      mex, "ITrackParamsLookupWriter");
-
-  py::class_<ActsExamples::ITrackParamsLookupReader,
-             std::shared_ptr<ActsExamples::ITrackParamsLookupReader>>(
-      mex, "ITrackParamsLookupReader");
-
-  {
-    using Writer = ActsExamples::RootMaterialWriter;
-    auto w = py::class_<Writer, IMaterialWriter, std::shared_ptr<Writer>>(
-                 mex, "RootMaterialWriter")
-                 .def(py::init<const Writer::Config&, Acts::Logging::Level>(),
-                      py::arg("config"), py::arg("level"))
-                 .def("write", py::overload_cast<const Acts::TrackingGeometry&>(
-                                   &Writer::write));
-
-    auto c = py::class_<Writer::Config>(w, "Config").def(py::init<>());
-
-    ACTS_PYTHON_STRUCT(c, processSensitives, processApproaches,
-                       processRepresenting, processBoundaries, processVolumes,
-                       folderSurfaceNameBase, folderVolumeNameBase, voltag,
-                       boutag, laytag, apptag, sentag, ntag, vtag, otag, mintag,
-                       maxtag, ttag, x0tag, l0tag, atag, ztag, rhotag, filePath,
-                       fileMode);
-  }
-
-  ACTS_PYTHON_DECLARE_WRITER(ActsExamples::RootSeedWriter, mex,
-                             "RootSeedWriter", inputSeeds, writingMode,
-                             filePath, fileMode, treeName);
-
-  ACTS_PYTHON_DECLARE_WRITER(ActsExamples::RootSimHitWriter, mex,
-                             "RootSimHitWriter", inputSimHits, filePath,
-                             fileMode, treeName);
-
-  ACTS_PYTHON_DECLARE_WRITER(ActsExamples::RootSpacepointWriter, mex,
-                             "RootSpacepointWriter", inputSpacepoints, filePath,
-                             fileMode, treeName);
-
-  ACTS_PYTHON_DECLARE_WRITER(
-      ActsExamples::RootTrackStatesWriter, mex, "RootTrackStatesWriter",
-      inputTracks, inputParticles, inputTrackParticleMatching, inputSimHits,
-      inputMeasurementSimHitsMap, filePath, treeName, fileMode);
-
-  ACTS_PYTHON_DECLARE_WRITER(
-      ActsExamples::RootTrackSummaryWriter, mex, "RootTrackSummaryWriter",
-      inputTracks, inputParticles, inputTrackParticleMatching, filePath,
-      treeName, fileMode, writeCovMat, writeGsfSpecific, writeGx2fSpecific);
-
-  ACTS_PYTHON_DECLARE_WRITER(
-      ActsExamples::VertexNTupleWriter, mex, "VertexNTupleWriter",
-      inputVertices, inputTracks, inputTruthVertices, inputParticles,
-      inputSelectedParticles, inputTrackParticleMatching, bField, filePath,
-      treeName, fileMode, vertexMatchThreshold, trackMatchThreshold,
-      writeTrackInfo);
-
-  // CSV WRITERS
   ACTS_PYTHON_DECLARE_WRITER(ActsExamples::CsvParticleWriter, mex,
                              "CsvParticleWriter", inputParticles, outputDir,
                              outputStem, outputPrecision);
@@ -338,21 +162,6 @@ void addOutput(Context& ctx) {
       trackingGeometry, outputDir, outputPrecision, writeSensitive,
       writeBoundary, writeSurfaceGrid, writeLayerVolume, writePerEvent);
 
-  ACTS_PYTHON_DECLARE_WRITER(
-      ActsExamples::TrackFinderPerformanceWriter, mex,
-      "TrackFinderPerformanceWriter", inputTracks, inputParticles,
-      inputTrackParticleMatching, inputParticleTrackMatching, filePath,
-      fileMode, effPlotToolConfig, fakeRatePlotToolConfig,
-      duplicationPlotToolConfig, trackSummaryPlotToolConfig,
-      subDetectorTrackSummaryVolumes, writeMatchingDetails);
-
-  ACTS_PYTHON_DECLARE_WRITER(
-      ActsExamples::RootNuclearInteractionParametersWriter, mex,
-      "RootNuclearInteractionParametersWriter", inputSimulationProcesses,
-      filePath, fileMode, interactionProbabilityBins, momentumBins,
-      invariantMassBins, multiplicityMax, writeOptionalHistograms,
-      nSimulatedEvents);
-
   ACTS_PYTHON_DECLARE_WRITER(ActsExamples::CsvTrackParameterWriter, mex,
                              "CsvTrackParameterWriter", inputTrackParameters,
                              inputTracks, outputDir, outputStem,
@@ -380,6 +189,13 @@ void addOutput(Context& ctx) {
   ACTS_PYTHON_DECLARE_WRITER(ActsExamples::CsvExaTrkXGraphWriter, mex,
                              "CsvExaTrkXGraphWriter", inputGraph, outputDir,
                              outputStem);
+
+  py::class_<IMaterialWriter, std::shared_ptr<IMaterialWriter>>(
+      mex, "IMaterialWriter");
+
+  py::class_<ActsExamples::ITrackParamsLookupWriter,
+             std::shared_ptr<ActsExamples::ITrackParamsLookupWriter>>(
+      mex, "ITrackParamsLookupWriter");
 }
 
 }  // namespace Acts::Python
diff --git a/Examples/Python/src/RootInput.cpp b/Examples/Python/src/RootInput.cpp
new file mode 100644
index 00000000000..b82c2d2f7a7
--- /dev/null
+++ b/Examples/Python/src/RootInput.cpp
@@ -0,0 +1,91 @@
+// This file is part of the ACTS project.
+//
+// Copyright (C) 2016 CERN for the benefit of the ACTS project
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#include "Acts/Plugins/Python/Utilities.hpp"
+#include "ActsExamples/Io/Root/RootAthenaDumpReader.hpp"
+#include "ActsExamples/Io/Root/RootAthenaNTupleReader.hpp"
+#include "ActsExamples/Io/Root/RootMaterialDecorator.hpp"
+#include "ActsExamples/Io/Root/RootMaterialTrackReader.hpp"
+#include "ActsExamples/Io/Root/RootParticleReader.hpp"
+#include "ActsExamples/Io/Root/RootSimHitReader.hpp"
+#include "ActsExamples/Io/Root/RootTrackSummaryReader.hpp"
+#include "ActsExamples/Io/Root/RootVertexReader.hpp"
+
+#include <pybind11/pybind11.h>
+#include <pybind11/stl.h>
+
+namespace py = pybind11;
+using namespace pybind11::literals;
+
+using namespace ActsExamples;
+
+namespace Acts::Python {
+
+void addRootInput(Context& ctx) {
+  auto mex = ctx.get("examples");
+
+  ACTS_PYTHON_DECLARE_READER(ActsExamples::RootParticleReader, mex,
+                             "RootParticleReader", outputParticles, treeName,
+                             filePath);
+
+  ACTS_PYTHON_DECLARE_READER(ActsExamples::RootVertexReader, mex,
+                             "RootVertexReader", outputVertices, treeName,
+                             filePath);
+
+  ACTS_PYTHON_DECLARE_READER(ActsExamples::RootMaterialTrackReader, mex,
+                             "RootMaterialTrackReader", outputMaterialTracks,
+                             treeName, fileList, readCachedSurfaceInformation);
+
+  ACTS_PYTHON_DECLARE_READER(ActsExamples::RootTrackSummaryReader, mex,
+                             "RootTrackSummaryReader", outputTracks,
+                             outputParticles, treeName, filePath);
+
+  ACTS_PYTHON_DECLARE_READER(ActsExamples::RootAthenaNTupleReader, mex,
+                             "RootAthenaNTupleReader", inputTreeName,
+                             inputFilePath, outputTrackParameters,
+                             outputTruthVtxParameters, outputRecoVtxParameters,
+                             outputBeamspotConstraint);
+
+  ACTS_PYTHON_DECLARE_READER(
+      ActsExamples::RootAthenaDumpReader, mex, "RootAthenaDumpReader", treename,
+      inputfiles, outputMeasurements, outputPixelSpacePoints,
+      outputStripSpacePoints, outputSpacePoints, outputClusters,
+      outputMeasurementParticlesMap, outputParticleMeasurementsMap,
+      outputParticles, onlySpacepoints, onlyPassedParticles, skipOverlapSPsPhi,
+      skipOverlapSPsEta, geometryIdMap, trackingGeometry, absBoundaryTolerance,
+      onlySpacepoints, noTruth, readCellData);
+
+#ifdef WITH_GEOMODEL_PLUGIN
+  ACTS_PYTHON_DECLARE_READER(ActsExamples::RootAthenaDumpGeoIdCollector, mex,
+                             "RootAthenaDumpGeoIdCollector", treename,
+                             inputfile, trackingGeometry, geometryIdMap);
+#endif
+
+  ACTS_PYTHON_DECLARE_READER(ActsExamples::RootSimHitReader, mex,
+                             "RootSimHitReader", treeName, filePath,
+                             outputSimHits);
+
+  {
+    auto rmd =
+        py::class_<RootMaterialDecorator, Acts::IMaterialDecorator,
+                   std::shared_ptr<RootMaterialDecorator>>(
+            mex, "RootMaterialDecorator")
+            .def(
+                py::init<RootMaterialDecorator::Config, Acts::Logging::Level>(),
+                py::arg("config"), py::arg("level"));
+
+    using Config = RootMaterialDecorator::Config;
+    auto c = py::class_<Config>(rmd, "Config").def(py::init<>());
+
+    ACTS_PYTHON_STRUCT(c, voltag, boutag, laytag, apptag, sentag, ntag, vtag,
+                       otag, mintag, maxtag, ttag, x0tag, l0tag, atag, ztag,
+                       rhotag, fileName);
+  }
+}
+
+}  // namespace Acts::Python
diff --git a/Examples/Python/src/RootOutput.cpp b/Examples/Python/src/RootOutput.cpp
new file mode 100644
index 00000000000..731068c35c0
--- /dev/null
+++ b/Examples/Python/src/RootOutput.cpp
@@ -0,0 +1,214 @@
+// This file is part of the ACTS project.
+//
+// Copyright (C) 2016 CERN for the benefit of the ACTS project
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#include "Acts/Plugins/Python/Utilities.hpp"
+#include "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"
+#include "ActsExamples/Io/Root/RootSeedWriter.hpp"
+#include "ActsExamples/Io/Root/RootSimHitWriter.hpp"
+#include "ActsExamples/Io/Root/RootSpacepointWriter.hpp"
+#include "ActsExamples/Io/Root/RootTrackParameterWriter.hpp"
+#include "ActsExamples/Io/Root/RootTrackStatesWriter.hpp"
+#include "ActsExamples/Io/Root/RootTrackSummaryWriter.hpp"
+#include "ActsExamples/Io/Root/RootVertexWriter.hpp"
+#include "ActsExamples/Io/Root/TrackFinderNTupleWriter.hpp"
+#include "ActsExamples/Io/Root/TrackFinderPerformanceWriter.hpp"
+#include "ActsExamples/Io/Root/TrackFitterPerformanceWriter.hpp"
+#include "ActsExamples/Io/Root/VertexNTupleWriter.hpp"
+
+#include <pybind11/pybind11.h>
+#include <pybind11/stl.h>
+#include <pybind11/stl/filesystem.h>
+
+namespace Acts {
+class TrackingGeometry;
+namespace detail {
+struct Step;
+}  // namespace detail
+}  // namespace Acts
+namespace ActsExamples {
+class IWriter;
+struct AlgorithmContext;
+}  // namespace ActsExamples
+
+namespace py = pybind11;
+using namespace pybind11::literals;
+
+using namespace ActsExamples;
+
+namespace Acts::Python {
+
+void addRootOutput(Context& ctx) {
+  auto [m, mex] = ctx.get("main", "examples");
+
+  // Bindings for the binning in e.g., TrackFinderPerformanceWriter
+  {
+    py::class_<PlotHelpers::Binning>(mex, "Binning")
+        .def(py::init<std::string, int, double, double>(), "title"_a, "bins"_a,
+             "bMin"_a, "bMax"_a)
+        .def(py::init<std::string, std::vector<double>>(), "title"_a, "bins"_a);
+
+    py::class_<EffPlotTool::Config>(mex, "EffPlotToolConfig")
+        .def(py::init<std::map<std::string, PlotHelpers::Binning>>(),
+             "varBinning"_a);
+
+    py::class_<FakeRatePlotTool::Config>(mex, "FakeRatePlotToolConfig")
+        .def(py::init<std::map<std::string, PlotHelpers::Binning>>(),
+             "varBinning"_a);
+
+    py::class_<DuplicationPlotTool::Config>(mex, "DuplicationPlotToolConfig")
+        .def(py::init<std::map<std::string, PlotHelpers::Binning>>(),
+             "varBinning"_a);
+  }
+
+  // ROOT WRITERS
+  ACTS_PYTHON_DECLARE_WRITER(ActsExamples::RootPropagationStepsWriter, mex,
+                             "RootPropagationStepsWriter", collection, filePath,
+                             fileMode);
+
+  ACTS_PYTHON_DECLARE_WRITER(ActsExamples::RootPropagationSummaryWriter, mex,
+                             "RootPropagationSummaryWriter",
+                             inputSummaryCollection, filePath, fileMode);
+
+  ACTS_PYTHON_DECLARE_WRITER(ActsExamples::RootParticleWriter, mex,
+                             "RootParticleWriter", inputParticles, filePath,
+                             fileMode, treeName);
+
+  ACTS_PYTHON_DECLARE_WRITER(ActsExamples::RootVertexWriter, mex,
+                             "RootVertexWriter", inputVertices, filePath,
+                             fileMode, treeName);
+
+  ACTS_PYTHON_DECLARE_WRITER(ActsExamples::TrackFinderNTupleWriter, mex,
+                             "TrackFinderNTupleWriter", inputTracks,
+                             inputParticles, inputParticleMeasurementsMap,
+                             inputTrackParticleMatching, filePath, fileMode,
+                             treeNameTracks, treeNameParticles);
+
+  ACTS_PYTHON_DECLARE_WRITER(ActsExamples::TrackFitterPerformanceWriter, mex,
+                             "TrackFitterPerformanceWriter", inputTracks,
+                             inputParticles, inputTrackParticleMatching,
+                             filePath, resPlotToolConfig, effPlotToolConfig,
+                             trackSummaryPlotToolConfig);
+
+  ACTS_PYTHON_DECLARE_WRITER(
+      ActsExamples::RootTrackParameterWriter, mex, "RootTrackParameterWriter",
+      inputTrackParameters, inputProtoTracks, inputParticles, inputSimHits,
+      inputMeasurementParticlesMap, inputMeasurementSimHitsMap, filePath,
+      treeName, fileMode);
+
+  ACTS_PYTHON_DECLARE_WRITER(
+      ActsExamples::RootMaterialTrackWriter, mex, "RootMaterialTrackWriter",
+      inputMaterialTracks, filePath, fileMode, treeName, recalculateTotals,
+      prePostStep, storeSurface, storeVolume, collapseInteractions);
+
+  {
+    using Writer = ActsExamples::RootBFieldWriter;
+    auto w =
+        py::class_<Writer>(mex, "RootBFieldWriter")
+            .def_static(
+                "run",
+                [](const Writer::Config& config, Acts::Logging::Level level) {
+                  Writer::run(config, Acts::getDefaultLogger("RootBFieldWriter",
+                                                             level));
+                },
+                py::arg("config"), py::arg("level"));
+
+    py::enum_<Writer::GridType>(w, "GridType")
+        .value("rz", Writer::GridType::rz)
+        .value("xyz", Writer::GridType::xyz);
+
+    auto c = py::class_<Writer::Config>(w, "Config").def(py::init<>());
+    ACTS_PYTHON_STRUCT(c, treeName, fileName, fileMode, bField, gridType,
+                       rBounds, zBounds, rBins, zBins, phiBins);
+  }
+
+  {
+    using Writer = ActsExamples::RootMeasurementWriter;
+    auto w = py::class_<Writer, IWriter, std::shared_ptr<Writer>>(
+                 mex, "RootMeasurementWriter")
+                 .def(py::init<const Writer::Config&, Acts::Logging::Level>(),
+                      py::arg("config"), py::arg("level"));
+
+    auto c = py::class_<Writer::Config>(w, "Config").def(py::init<>());
+
+    ACTS_PYTHON_STRUCT(c, inputMeasurements, inputClusters, inputSimHits,
+                       inputMeasurementSimHitsMap, filePath, fileMode,
+                       surfaceByIdentifier);
+  }
+
+  {
+    using Writer = ActsExamples::RootMaterialWriter;
+    auto w = py::class_<Writer, IMaterialWriter, std::shared_ptr<Writer>>(
+                 mex, "RootMaterialWriter")
+                 .def(py::init<const Writer::Config&, Acts::Logging::Level>(),
+                      py::arg("config"), py::arg("level"))
+                 .def("write", py::overload_cast<const Acts::TrackingGeometry&>(
+                                   &Writer::write));
+
+    auto c = py::class_<Writer::Config>(w, "Config").def(py::init<>());
+
+    ACTS_PYTHON_STRUCT(c, processSensitives, processApproaches,
+                       processRepresenting, processBoundaries, processVolumes,
+                       folderSurfaceNameBase, folderVolumeNameBase, voltag,
+                       boutag, laytag, apptag, sentag, ntag, vtag, otag, mintag,
+                       maxtag, ttag, x0tag, l0tag, atag, ztag, rhotag, filePath,
+                       fileMode);
+  }
+
+  ACTS_PYTHON_DECLARE_WRITER(ActsExamples::RootSeedWriter, mex,
+                             "RootSeedWriter", inputSeeds, writingMode,
+                             filePath, fileMode, treeName);
+
+  ACTS_PYTHON_DECLARE_WRITER(ActsExamples::RootSimHitWriter, mex,
+                             "RootSimHitWriter", inputSimHits, filePath,
+                             fileMode, treeName);
+
+  ACTS_PYTHON_DECLARE_WRITER(ActsExamples::RootSpacepointWriter, mex,
+                             "RootSpacepointWriter", inputSpacepoints, filePath,
+                             fileMode, treeName);
+
+  ACTS_PYTHON_DECLARE_WRITER(
+      ActsExamples::RootTrackStatesWriter, mex, "RootTrackStatesWriter",
+      inputTracks, inputParticles, inputTrackParticleMatching, inputSimHits,
+      inputMeasurementSimHitsMap, filePath, treeName, fileMode);
+
+  ACTS_PYTHON_DECLARE_WRITER(
+      ActsExamples::RootTrackSummaryWriter, mex, "RootTrackSummaryWriter",
+      inputTracks, inputParticles, inputTrackParticleMatching, filePath,
+      treeName, fileMode, writeCovMat, writeGsfSpecific, writeGx2fSpecific);
+
+  ACTS_PYTHON_DECLARE_WRITER(
+      ActsExamples::VertexNTupleWriter, mex, "VertexNTupleWriter",
+      inputVertices, inputTracks, inputTruthVertices, inputParticles,
+      inputSelectedParticles, inputTrackParticleMatching, bField, filePath,
+      treeName, fileMode, vertexMatchThreshold, trackMatchThreshold,
+      writeTrackInfo);
+
+  ACTS_PYTHON_DECLARE_WRITER(
+      ActsExamples::TrackFinderPerformanceWriter, mex,
+      "TrackFinderPerformanceWriter", inputTracks, inputParticles,
+      inputTrackParticleMatching, inputParticleTrackMatching, filePath,
+      fileMode, effPlotToolConfig, fakeRatePlotToolConfig,
+      duplicationPlotToolConfig, trackSummaryPlotToolConfig,
+      subDetectorTrackSummaryVolumes, writeMatchingDetails);
+
+  ACTS_PYTHON_DECLARE_WRITER(
+      ActsExamples::RootNuclearInteractionParametersWriter, mex,
+      "RootNuclearInteractionParametersWriter", inputSimulationProcesses,
+      filePath, fileMode, interactionProbabilityBins, momentumBins,
+      invariantMassBins, multiplicityMax, writeOptionalHistograms,
+      nSimulatedEvents);
+}
+
+}  // namespace Acts::Python
diff --git a/Examples/Python/src/RootStub.cpp b/Examples/Python/src/RootStub.cpp
new file mode 100644
index 00000000000..c36f5d6ee08
--- /dev/null
+++ b/Examples/Python/src/RootStub.cpp
@@ -0,0 +1,14 @@
+// This file is part of the ACTS project.
+//
+// Copyright (C) 2016 CERN for the benefit of the ACTS project
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#include "Acts/Plugins/Python/Utilities.hpp"
+
+namespace Acts::Python {
+void addRootInput(Context& /*ctx*/) {}
+void addRootOutput(Context& /*ctx*/) {}
+}  // namespace Acts::Python
diff --git a/Tests/UnitTests/Examples/Io/CMakeLists.txt b/Tests/UnitTests/Examples/Io/CMakeLists.txt
index 2c5d082a6c9..d7b5de5587c 100644
--- a/Tests/UnitTests/Examples/Io/CMakeLists.txt
+++ b/Tests/UnitTests/Examples/Io/CMakeLists.txt
@@ -1,3 +1,3 @@
 add_subdirectory_if(Json ACTS_BUILD_PLUGIN_JSON)
-add_subdirectory(Root)
+add_subdirectory_if(Root ACTS_BUILD_EXAMPLES_ROOT)
 add_subdirectory(Csv)
diff --git a/docs/getting_started.md b/docs/getting_started.md
index 35a84bd1bfa..85cf00ac9b8 100644
--- a/docs/getting_started.md
+++ b/docs/getting_started.md
@@ -300,6 +300,7 @@ components.
 | ACTS_BUILD_EXAMPLES_HASHING         | Build Hashing-based code in the examples<br> type: `bool`, default: `OFF`                                                                                                                                                          |
 | ACTS_BUILD_EXAMPLES_PYTHIA8         | Build Pythia8-based code in the examples<br> type: `bool`, default: `OFF`                                                                                                                                                          |
 | ACTS_BUILD_EXAMPLES_PYTHON_BINDINGS | Build python bindings for the examples<br> type: `bool`, default: `OFF`                                                                                                                                                            |
+| ACTS_BUILD_EXAMPLES_ROOT            | Build modules based on ROOT I/O<br> type: `bool`, default: `ON`                                                                                                                                                                    |
 | ACTS_BUILD_ANALYSIS_APPS            | Build Analysis applications in the<br>examples<br> type: `bool`, default: `OFF`                                                                                                                                                    |
 | ACTS_BUILD_BENCHMARKS               | Build benchmarks<br> type: `bool`, default: `OFF`                                                                                                                                                                                  |
 | ACTS_BUILD_INTEGRATIONTESTS         | Build integration tests<br> type: `bool`, default: `OFF`                                                                                                                                                                           |


Reviews:
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>🧹 Nitpick comments (5)</summary><blockquote>

<details>
<summary>Examples/Python/src/Input.cpp (1)</summary><blockquote>

`70-73`: **A new class binding, introduced you have.**  
Implementation detail for the `ITrackParamsLookupReader` is minimal here, hmmm. Large expansions possible in the future, yes. Document or extend it, you could.

</blockquote></details>
<details>
<summary>Examples/Python/src/RootOutput.cpp (2)</summary><blockquote>

`152-210`: **Wise it is to separate measurement logic, root or otherwise.**  
Two distinct classes for measurement and material writing, you have. Straightforward they seem, but thorough testing with real geometry data, ensure.

---

`212-254`: **Root-based writer macros, many they be.**  
Comprehensive coverage of use cases, indeed. Maintain consistency in file naming and paths, you should.

</blockquote></details>
<details>
<summary>Examples/Python/src/RootInput.cpp (1)</summary><blockquote>

`28-60`: **Function addRootInput, to read data in.**  
A clear approach, using macros for each specialized reader. Verify naming for clarity, you should, especially with many overlapping parameters.

</blockquote></details>
<details>
<summary>Examples/Io/Root/CMakeLists.txt (1)</summary><blockquote>

`50-50`: **Document the purpose of this compile definition, you should!**

While correct the definition is, its purpose and usage in the codebase, unclear they remain.

Add a comment explaining the purpose of ACTS_EXAMPLES_WITH_ROOT:

```diff
+# Define ACTS_EXAMPLES_WITH_ROOT to enable conditional compilation of ROOT-dependent code
 target_compile_definitions(ActsExamplesIoRoot PUBLIC ACTS_EXAMPLES_WITH_ROOT)
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between e4606c60445bbb6bc1cebef110009a3ba0e2e31e and bdfff81d91108b90ba6b8f6e6239616cab99b251.

</details>

<details>
<summary>📒 Files selected for processing (13)</summary>

* `CMakeLists.txt` (2 hunks)
* `CMakePresets.json` (1 hunks)
* `Examples/Io/CMakeLists.txt` (1 hunks)
* `Examples/Io/Root/CMakeLists.txt` (1 hunks)
* `Examples/Python/CMakeLists.txt` (1 hunks)
* `Examples/Python/src/Input.cpp` (2 hunks)
* `Examples/Python/src/Material.cpp` (3 hunks)
* `Examples/Python/src/ModuleEntry.cpp` (2 hunks)
* `Examples/Python/src/Output.cpp` (1 hunks)
* `Examples/Python/src/RootInput.cpp` (1 hunks)
* `Examples/Python/src/RootOutput.cpp` (1 hunks)
* `Examples/Python/src/RootStub.cpp` (1 hunks)
* `docs/getting_started.md` (1 hunks)

</details>

<details>
<summary>✅ Files skipped from review due to trivial changes (2)</summary>

* Examples/Python/src/Material.cpp
* Examples/Python/src/RootStub.cpp

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: merge-sentinel

</details>

<details>
<summary>🔇 Additional comments (14)</summary><blockquote>

<details>
<summary>Examples/Python/src/Input.cpp (1)</summary>

`20-20`: **A new include, necessary it is.**  
Include line matches the new interface usage, correct it appears.

</details>
<details>
<summary>Examples/Python/src/RootOutput.cpp (3)</summary>

`9-30`: **Galore of includes, you have.**  
All relevant headers, correct they seem. Ensure compilation flags remain consistent, you must.

---

`53-74`: **Function addRootOutput, introduced it is.**  
Central binding method it serves, grouping many writers in one place, hmm. Good design pattern for modularizing I/O, it appears.

---

`76-150`: **Writers, declared in plenty they are.**  
Macros yield clarity, yes, though verifying correctness with actual data flow, necessary it is.

</details>
<details>
<summary>Examples/Python/src/RootInput.cpp (2)</summary>

`9-16`: **ROOT-based headers, included.**  
Needed for bridging the I/O functionalities, hmmm. All correct they look.

---

`61-65`: **Conditional compilation, you have.**  
`WITH_GEOMODEL_PLUGIN` usage is wise, but test coverage ensure for both on and off states, hmmm.

</details>
<details>
<summary>Examples/Python/src/ModuleEntry.cpp (2)</summary>

`59-60`: **Clean and orderly, these additions are!**

Following the established pattern of module initialization functions, these declarations do. Approve them, I do.

---

`150-151`: **Wise placement of initialization calls, this is!**

At the end of plugin initializations, these new calls reside. A natural position for ROOT-related functionality, it is.

</details>
<details>
<summary>Examples/Python/src/Output.cpp (1)</summary>

`211-216`: **Well-crafted bindings, these are!**

Using shared_ptr wisely, you do. Following pybind11 best practices, this implementation does.

</details>
<details>
<summary>Examples/Io/CMakeLists.txt (1)</summary>

`6-6`: **Consistent with the Force, this CMake change is!**

Like its siblings EDM4hep and HepMC3, conditional inclusion for Root now exists. A harmonious balance in the build system, this brings.

</details>
<details>
<summary>Examples/Python/CMakeLists.txt (1)</summary>

`86-94`: **Well structured, this conditional compilation is!**

Follow the established patterns it does, hmm. When ROOT not present, stub implementation it provides. Clean and consistent with other similar conditionals in the file, this approach is.

</details>
<details>
<summary>CMakeLists.txt (2)</summary>

`106-106`: **Wisely placed, this new option is.**

Among other example-related options it sits, following the established pattern it does.

---

`511-521`: **Proper ROOT dependency handling, this is.**

When ACTS_BUILD_EXAMPLES_ROOT enabled is, required ROOT components it finds. Compatibility it checks, hmm. Good practices these are.

</details>
<details>
<summary>docs/getting_started.md (1)</summary>

`303-303`: **Well documented, this new option is.**

In the build options table, properly placed it is. Format it follows, description clear it provides.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-02-14T14:52:24Z
user: login: paulgessinger
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-02-14T17:34:16Z
user: login: benjaminhuth
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-02-14T22:14:14Z
user: login: benjaminhuth
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-02-14T22:15:33Z
user: login: coderabbitai[bot]
state: COMMENTED
author_association: NONE
submitted_at: 2025-02-14T22:15:52Z
user: login: paulgessinger
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-07T17:25:01Z
user: login: paulgessinger
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-08T06:44:41Z
user: login: paulgessinger
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-08T06:45:47Z
user: login: paulgessinger
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-08T06:47:31Z
user: login: benjaminhuth
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-08T07:45:17Z
user: login: benjaminhuth
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-08T07:45:52Z
user: login: benjaminhuth
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-08T07:47:51Z
user: login: paulgessinger
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-08T07:55:40Z
user: login: benjaminhuth
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-08T11:20:14Z
user: login: paulgessinger
state: APPROVED
author_association: MEMBER
submitted_at: 2025-04-09T11:49:07Z

Review comments:
diff_hunk: @@ -17,6 +17,7 @@
                 "ACTS_BUILD_PLUGIN_LEGACY": "ON",
                 "ACTS_BUILD_EXAMPLES_DD4HEP": "ON",
                 "ACTS_BUILD_EXAMPLES_PYTHON_BINDINGS": "ON",
+                "ACTS_BUILD_EXAMPLES_ROOT": "ON",
path: CMakePresets.json
user: login: coderabbitai[bot]
body: _:warning: Potential issue_

**Inconsistent default value with CMakeLists.txt, this is.**

In CMakeLists.txt, default value OFF it is, but here ON we see. Confusion this may cause, when different build methods users try. Align these defaults we should, hmm.

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-02-14T14:52:24Z
author_association: NONE
diff_hunk: @@ -25,12 +25,15 @@
 #include "Acts/Plugins/Python/Utilities.hpp"
 #include "Acts/Utilities/Logger.hpp"
 #include "ActsExamples/Framework/ProcessCode.hpp"
-#include "ActsExamples/Io/Root/RootMaterialDecorator.hpp"
 #include "ActsExamples/MaterialMapping/CoreMaterialMapping.hpp"
 #include "ActsExamples/MaterialMapping/MappingMaterialDecorator.hpp"
 #include "ActsExamples/MaterialMapping/MaterialMapping.hpp"
 #include "ActsExamples/MaterialMapping/MaterialValidation.hpp"
 
+#ifdef ACTS_EXAMPLES_WITH_ROOT
path: Examples/Python/src/Material.cpp
user: login: paulgessinger
body: I think we should try to find a way to do this without a preprocessor define. Can we handle this in CMake somehow?
This would probably need to move to the ROOT IO folder. 
created_at: 2025-02-14T17:33:17Z
author_association: MEMBER
diff_hunk: @@ -25,12 +25,15 @@
 #include "Acts/Plugins/Python/Utilities.hpp"
 #include "Acts/Utilities/Logger.hpp"
 #include "ActsExamples/Framework/ProcessCode.hpp"
-#include "ActsExamples/Io/Root/RootMaterialDecorator.hpp"
 #include "ActsExamples/MaterialMapping/CoreMaterialMapping.hpp"
 #include "ActsExamples/MaterialMapping/MappingMaterialDecorator.hpp"
 #include "ActsExamples/MaterialMapping/MaterialMapping.hpp"
 #include "ActsExamples/MaterialMapping/MaterialValidation.hpp"
 
+#ifdef ACTS_EXAMPLES_WITH_ROOT
path: Examples/Python/src/Material.cpp
user: login: benjaminhuth
body: Yeah probably we should put this to `RootInput.cpp` and avoid the preprocessor `ifdef`.
created_at: 2025-02-14T22:14:14Z
author_association: MEMBER
diff_hunk: @@ -17,6 +17,7 @@
                 "ACTS_BUILD_PLUGIN_LEGACY": "ON",
                 "ACTS_BUILD_EXAMPLES_DD4HEP": "ON",
                 "ACTS_BUILD_EXAMPLES_PYTHON_BINDINGS": "ON",
+                "ACTS_BUILD_EXAMPLES_ROOT": "ON",
path: CMakePresets.json
user: login: benjaminhuth
body: The convention is, that in the CmakeLists.txt, all options are off. Therefore, this aligns with our design.
created_at: 2025-02-14T22:15:33Z
author_association: MEMBER
diff_hunk: @@ -17,6 +17,7 @@
                 "ACTS_BUILD_PLUGIN_LEGACY": "ON",
                 "ACTS_BUILD_EXAMPLES_DD4HEP": "ON",
                 "ACTS_BUILD_EXAMPLES_PYTHON_BINDINGS": "ON",
+                "ACTS_BUILD_EXAMPLES_ROOT": "ON",
path: CMakePresets.json
user: login: coderabbitai[bot]
body: @benjaminhuth Understand the wisdom of your ways, I do. Clear it is now - CMakeLists.txt defaults to OFF by design, while presets may override, hmm yes.



(\_/)<br>
(^.^) *ponders deeply about CMake wisdom*

---

<details>
<summary>✏️ Learnings added</summary>

```
Learnt from: benjaminhuth
PR: acts-project/acts#4090
File: CMakePresets.json:20-20
Timestamp: 2025-02-14T22:15:51.190Z
Learning: In the ACTS project, CMake options in CMakeLists.txt are intentionally set to OFF by default, while CMakePresets.json can override these defaults with ON values as per the project's design convention.
```

> Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure [review instructions](https://docs.coderabbit.ai/guides/review-instructions). You can manage existing learnings in the [app](https://app.coderabbit.ai/learnings).

</details>

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-02-14T22:15:52Z
author_association: NONE
diff_hunk: @@ -46,6 +46,7 @@ target_link_libraries(
         Threads::Threads
     PRIVATE ROOT::Core ROOT::Hist ROOT::Tree
 )
+target_compile_definitions(ActsExamplesIoRoot PUBLIC ACTS_EXAMPLES_WITH_ROOT)
path: Examples/Io/Root/CMakeLists.txt
user: login: paulgessinger
body: Do we need this? I don't see where it's used, and usually public defines like this can be a bit painful. If we don't need it I would suggest to drop it.
created_at: 2025-04-07T17:25:01Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,91 @@
+// This file is part of the ACTS project.
+//
+// Copyright (C) 2016 CERN for the benefit of the ACTS project
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#include "Acts/Plugins/Python/Utilities.hpp"
+#include "ActsExamples/Io/Root/RootAthenaDumpReader.hpp"
+#include "ActsExamples/Io/Root/RootAthenaNTupleReader.hpp"
+#include "ActsExamples/Io/Root/RootMaterialDecorator.hpp"
+#include "ActsExamples/Io/Root/RootMaterialTrackReader.hpp"
+#include "ActsExamples/Io/Root/RootParticleReader.hpp"
+#include "ActsExamples/Io/Root/RootSimHitReader.hpp"
+#include "ActsExamples/Io/Root/RootTrackSummaryReader.hpp"
+#include "ActsExamples/Io/Root/RootVertexReader.hpp"
+
+#include <pybind11/pybind11.h>
+#include <pybind11/stl.h>
+
+namespace py = pybind11;
+using namespace pybind11::literals;
+
+using namespace ActsExamples;
+
+namespace Acts::Python {
+
+void addRootInput(Context& ctx) {
path: Examples/Python/src/RootInput.cpp
user: login: paulgessinger
body: I'm wondering if we should put these into a separate sub-package `root` now. I think @asalzburger has been thinking about this recently.
created_at: 2025-04-08T06:44:41Z
author_association: MEMBER
diff_hunk: @@ -103,6 +103,7 @@ option(ACTS_BUILD_EXAMPLES_HEPMC3 "Build HepMC3-based code in the examples" OFF)
 option(ACTS_BUILD_EXAMPLES_HASHING "Build Hashing-based code in the examples" OFF)
 option(ACTS_BUILD_EXAMPLES_PYTHIA8 "Build Pythia8-based code in the examples" OFF)
 option(ACTS_BUILD_EXAMPLES_PYTHON_BINDINGS "Build python bindings for the examples" OFF)
+option(ACTS_BUILD_EXAMPLES_ROOT "Build modules based on ROOT I/O" OFF)
path: CMakeLists.txt
user: login: paulgessinger
body: I saw that you had a discussion with the Robot already about this, but I'm wondering if we shouldn't turn this on by default actually, since it aligns with the *previous* configuration.
created_at: 2025-04-08T06:45:47Z
author_association: MEMBER
diff_hunk: @@ -111,6 +111,22 @@ jobs:
       - name: Downstream run
         run: ./build-downstream/bin/ShowActsVersion
 
+      # We configure and build without ROOT in the same job to garantuee that we can use the ccache cache
+      - name: Configure (without ROOT)
+        run: >
+          ccache -z &&
+          rm -rf build &&
+          cmake -B build -S .
+          --preset=github-ci-no-root
+          -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}"
+          -DPython_EXECUTABLE=$(which python3)
path: .github/workflows/builds.yml
user: login: paulgessinger
body: Maybe we can also disable the unit tests for this config? That shouldn't make a difference for what we're trying to test here, but I think we spend the majority of the time in this step on linking the unit test executables, since that's not sped up by ccache.
created_at: 2025-04-08T06:47:31Z
author_association: MEMBER
diff_hunk: @@ -103,6 +103,7 @@ option(ACTS_BUILD_EXAMPLES_HEPMC3 "Build HepMC3-based code in the examples" OFF)
 option(ACTS_BUILD_EXAMPLES_HASHING "Build Hashing-based code in the examples" OFF)
 option(ACTS_BUILD_EXAMPLES_PYTHIA8 "Build Pythia8-based code in the examples" OFF)
 option(ACTS_BUILD_EXAMPLES_PYTHON_BINDINGS "Build python bindings for the examples" OFF)
+option(ACTS_BUILD_EXAMPLES_ROOT "Build modules based on ROOT I/O" OFF)
path: CMakeLists.txt
user: login: benjaminhuth
body: Can do it, I don't have a strong opinion on this...
created_at: 2025-04-08T07:45:17Z
author_association: MEMBER
diff_hunk: @@ -111,6 +111,22 @@ jobs:
       - name: Downstream run
         run: ./build-downstream/bin/ShowActsVersion
 
+      # We configure and build without ROOT in the same job to garantuee that we can use the ccache cache
+      - name: Configure (without ROOT)
+        run: >
+          ccache -z &&
+          rm -rf build &&
+          cmake -B build -S .
+          --preset=github-ci-no-root
+          -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}"
+          -DPython_EXECUTABLE=$(which python3)
path: .github/workflows/builds.yml
user: login: benjaminhuth
body: I actually found a bug in this PR because unit test where switched on (we have some examples unit test using root)
created_at: 2025-04-08T07:45:52Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,91 @@
+// This file is part of the ACTS project.
+//
+// Copyright (C) 2016 CERN for the benefit of the ACTS project
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#include "Acts/Plugins/Python/Utilities.hpp"
+#include "ActsExamples/Io/Root/RootAthenaDumpReader.hpp"
+#include "ActsExamples/Io/Root/RootAthenaNTupleReader.hpp"
+#include "ActsExamples/Io/Root/RootMaterialDecorator.hpp"
+#include "ActsExamples/Io/Root/RootMaterialTrackReader.hpp"
+#include "ActsExamples/Io/Root/RootParticleReader.hpp"
+#include "ActsExamples/Io/Root/RootSimHitReader.hpp"
+#include "ActsExamples/Io/Root/RootTrackSummaryReader.hpp"
+#include "ActsExamples/Io/Root/RootVertexReader.hpp"
+
+#include <pybind11/pybind11.h>
+#include <pybind11/stl.h>
+
+namespace py = pybind11;
+using namespace pybind11::literals;
+
+using namespace ActsExamples;
+
+namespace Acts::Python {
+
+void addRootInput(Context& ctx) {
path: Examples/Python/src/RootInput.cpp
user: login: benjaminhuth
body: Hmm I think is is definitively a good idea, to abstract the whole `TTree` reading/writing a bit and package it, but this goes beyond the scope of this PR I think...
created_at: 2025-04-08T07:47:51Z
author_association: MEMBER
diff_hunk: @@ -111,6 +111,22 @@ jobs:
       - name: Downstream run
         run: ./build-downstream/bin/ShowActsVersion
 
+      # We configure and build without ROOT in the same job to garantuee that we can use the ccache cache
+      - name: Configure (without ROOT)
+        run: >
+          ccache -z &&
+          rm -rf build &&
+          cmake -B build -S .
+          --preset=github-ci-no-root
+          -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}"
+          -DPython_EXECUTABLE=$(which python3)
path: .github/workflows/builds.yml
user: login: paulgessinger
body: But that should be caught in the first run, shouldn't it?
created_at: 2025-04-08T07:55:40Z
author_association: MEMBER
diff_hunk: @@ -111,6 +111,22 @@ jobs:
       - name: Downstream run
         run: ./build-downstream/bin/ShowActsVersion
 
+      # We configure and build without ROOT in the same job to garantuee that we can use the ccache cache
+      - name: Configure (without ROOT)
+        run: >
+          ccache -z &&
+          rm -rf build &&
+          cmake -B build -S .
+          --preset=github-ci-no-root
+          -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}"
+          -DPython_EXECUTABLE=$(which python3)
path: .github/workflows/builds.yml
user: login: benjaminhuth
body: I meant there is a test depending on ROOT and Examples. And I catched that only because unittest where enabled...
created_at: 2025-04-08T11:20:14Z
author_association: MEMBER

PR comments:
user: login: coderabbitai[bot]
created_at: 2025-02-14T13:05:59Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- This is an auto-generated comment: skip review by coderabbit.ai -->

> [!IMPORTANT]
> ## Review skipped
> 
> Auto incremental reviews are disabled on this repository.
> 
> Please check the settings in the CodeRabbit UI or the `.coderabbit.yaml` file in this repository. To trigger a single review, invoke the `@coderabbitai review` command.
> 
> You can disable this status message by setting the `reviews.review_status` to `false` in the CodeRabbit configuration file.

<!-- end of auto-generated comment: skip review by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough
Hmm, changes made they have been. A new CMake option for ROOT I/O is introduced, it is. Conditional logic in CMake files now controls the inclusion of ROOT dependencies and example subdirectories. In Python bindings, adjustments are done—legacy ROOT readers and writers removed, new functions and interface for track parameter lookup added. Various source files in the Examples/Io and Examples/Python directories updated have been. Configurability increased, it is.

## Changes

| File(s) | Change Summary |
|---------|----------------|
| `CMakeLists.txt`, `CMakePresets.json`, `docs/.../getting_started.md` | New option `ACTS_BUILD_EXAMPLES_ROOT` added; configuration updated to include ROOT I/O examples conditionally. |
| `Examples/Io/CMakeLists.txt`, `Examples/Io/Root/CMakeLists.txt` | Conditional inclusion of the Root subdirectory introduced; compile definition for `ActsExamplesIoRoot` added. |
| `Examples/Python/CMakeLists.txt` | Python bindings configuration updated to conditionally link `ActsExamplesIoRoot` and select source files based on ROOT option. |
| `Examples/Python/src/Input.cpp`, `Examples/Python/src/RootInput.cpp` | Legacy ROOT reader declarations removed; new interface `ITrackParamsLookupReader` and `addRootInput` function added. |
| `Examples/Python/src/Output.cpp`, `Examples/Python/src/RootOutput.cpp` | Old ROOT writer bindings removed; new pybind11 bindings for `IMaterialWriter` and `ITrackParamsLookupWriter`, and new `addRootOutput` function added. |
| `Examples/Python/src/Material.cpp`, `Examples/Python/src/ModuleEntry.cpp`, `Examples/Python/src/RootStub.cpp` | Conditional header inclusion added in Material; new functions added in ModuleEntry and stub implementations provided for ROOT I/O. |

## Sequence Diagram(s)
```mermaid
sequenceDiagram
    participant U as User
    participant C as CMake
    participant P as Python Bindings
    participant R as ROOT Packages

    U->>C: Set ACTS_BUILD_EXAMPLES_ROOT (ON/OFF)
    alt ROOT Enabled
        C->>R: Find and verify ROOT packages
        C->>C: Include Root subdirectory and apply compile definitions
        C->>P: Link ActsExamplesIoRoot and select ROOT input/output sources
        P->>P: Register addRootInput and addRootOutput functions with reader/writer bindings
    else ROOT Disabled
        C->>P: Select stub implementations for ROOT support
    end
```

## Suggested labels
`automerge`

## Suggested reviewers
- andiwand

## Poem
> In code’s galaxy, a new light is born,  
> Conditional paths through the build, we now adorn.  
> Legacy shadows fade, replaced by functions so bright,  
> With ROOT or without, our project feels right.  
> Merge the changes, we must—with joy and might.  
> Hmm, celebrate these shifts, we do tonight!

<!-- walkthrough_end -->
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- tips_start -->

---



<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=acts-project/acts&utm_content=4090):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai plan` to trigger planning for file edits and PR creation.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: NONE
user: login: github-actions[bot]
created_at: 2025-02-14T14:10:34Z
body: # 📊: Physics performance monitoring for c39f97fd517debb02ea0dfb4894e7332fa02de09
[Full contents](https://acts-herald.app.cern.ch/view/acts-project/acts/2911525307)
# physmon summary
  - ✅ [Particles fatras](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/simulation/particles_fatras.html)
  - ✅ [Particles geant4](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/simulation/particles_geant4.html)
  - ✅ [Particles ttbar](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/simulation/particles_ttbar.html)
  - ✅ [Vertices ttbar](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/simulation/vertices_ttbar.html)
  - ✅ [Truth tracking (KF)](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackfitting_kf/performance_trackfitting.html)
  - ✅ [Truth tracking (GSF)](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackfitting_gsf/performance_trackfitting.html)
  - ✅ [Truth tracking (GX2F)](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackfitting_gx2f/performance_trackfitting.html)
  - ✅ [Truth tracking (KF refit)](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackrefitting_kf/performance_trackrefitting.html)
  - ✅ [Truth tracking (GSF refit)](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackrefitting_gsf/performance_trackrefitting.html)
  - ✅ [CKF finding performance | trackfinding | single muon | truth smeared seeding](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackfinding_1muon/truth_smeared/performance_finding_ckf.html)
  - ✅ [CKF fitting performance | trackfinding | single muon | truth smeared seeding](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackfinding_1muon/truth_smeared/performance_fitting_ckf.html)
  - ✅ [CKF track summary | trackfinding | single muon | truth smeared seeding](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackfinding_1muon/truth_smeared/tracksummary_ckf.html)
  - ✅ [Seeding trackfinding | single muon | truth estimated seeding](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackfinding_1muon/truth_estimated/performance_seeding.html)
  - ✅ [CKF finding performance | trackfinding | single muon | truth estimated seeding](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackfinding_1muon/truth_estimated/performance_finding_ckf.html)
  - ✅ [CKF fitting performance | trackfinding | single muon | truth estimated seeding](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackfinding_1muon/truth_estimated/performance_fitting_ckf.html)
  - ✅ [CKF track summary | trackfinding | single muon | truth estimated seeding](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackfinding_1muon/truth_estimated/tracksummary_ckf.html)
  - ✅ [Seeding trackfinding | single muon | default seeding](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackfinding_1muon/seeded/performance_seeding.html)
  - ✅ [CKF finding performance | trackfinding | single muon | default seeding](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackfinding_1muon/seeded/performance_finding_ckf.html)
  - ✅ [CKF fitting performance | trackfinding | single muon | default seeding](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackfinding_1muon/seeded/performance_fitting_ckf.html)
  - ✅ [CKF track summary | trackfinding | single muon | default seeding](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackfinding_1muon/seeded/tracksummary_ckf.html)
  - ✅ [Seeding trackfinding | single muon | orthogonal seeding](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackfinding_1muon/orthogonal/performance_seeding.html)
  - ✅ [CKF finding performance | trackfinding | single muon | orthogonal seeding](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackfinding_1muon/orthogonal/performance_finding_ckf.html)
  - ✅ [CKF fitting performance | trackfinding | single muon | orthogonal seeding](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackfinding_1muon/orthogonal/performance_fitting_ckf.html)
  - ✅ [CKF track summary | trackfinding | single muon | orthogonal seeding](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackfinding_1muon/orthogonal/tracksummary_ckf.html)
  - ✅ [Seeding trackfinding | 4 muon x 50 vertices | default seeding](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackfinding_4muon_50vertices/performance_seeding.html)
  - ✅ [CKF finding performance | trackfinding | 4 muon x 50 vertices | default seeding](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackfinding_4muon_50vertices/performance_finding_ckf.html)
  - ✅ [CKF fitting performance | trackfinding | 4 muon x 50 vertices | default seeding](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackfinding_4muon_50vertices/performance_fitting_ckf.html)
  - ✅ [CKF track summary | trackfinding | 4 muon x 50 vertices | default seeding](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackfinding_4muon_50vertices/tracksummary_ckf.html)
  - ✅ [Ambisolver finding performance | trackfinding | 4 muon x 50 vertices | default seeding](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackfinding_4muon_50vertices/performance_finding_ckf_ambi.html)
  - ✅ [IVF notime | trackfinding | 4 muon x 50 vertices | default seeding](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackfinding_4muon_50vertices/performance_vertexing_ivf_notime.html)
  - ✅ [AMVF gauss notime | trackfinding | 4 muon x 50 vertices | default seeding](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackfinding_4muon_50vertices/performance_vertexing_amvf_gauss_notime.html)
  - ✅ [AMVF grid time | trackfinding | 4 muon x 50 vertices | default seeding](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackfinding_4muon_50vertices/performance_vertexing_amvf_grid_time.html)
  - ✅ [Seeding trackfinding | ttbar with 200 pileup | default seeding](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackfinding_ttbar_pu200/performance_seeding.html)
  - ✅ [CKF finding performance | trackfinding | ttbar with 200 pileup | default seeding](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackfinding_ttbar_pu200/performance_finding_ckf.html)
  - ✅ [CKF fitting performance | trackfinding | ttbar with 200 pileup | default seeding](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackfinding_ttbar_pu200/performance_fitting_ckf.html)
  - ✅ [CKF track summary | trackfinding | ttbar with 200 pileup | default seeding](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackfinding_ttbar_pu200/tracksummary_ckf.html)
  - ✅ [Ambisolver finding performance | trackfinding | ttbar with 200 pileup | default seeding](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackfinding_ttbar_pu200/performance_finding_ckf_ambi.html)
  - ✅ [ML Ambisolver | trackfinding | ttbar with 200 pileup | default seeding](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackfinding_ttbar_pu200/performance_finding_ckf_ml_solver.html)
  - ✅ [AMVF gauss notime | trackfinding | ttbar with 200 pileup | default seeding](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackfinding_ttbar_pu200/performance_vertexing_amvf_gauss_notime.html)
  - ✅ [AMVF grid time | trackfinding | ttbar with 200 pileup | default seeding](https://acts-herald.app.cern.ch/view/acts-project/acts/runs/14357783856/artifacts/physmon/html/trackfinding_ttbar_pu200/performance_vertexing_amvf_grid_time.html)

author_association: CONTRIBUTOR
user: login: sonarqubecloud[bot]
created_at: 2025-02-14T14:44:25Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=acts-project_acts&pullRequest=4090) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [1 New issue](https://sonarcloud.io/project/issues?id=acts-project_acts&pullRequest=4090&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=acts-project_acts&pullRequest=4090&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=acts-project_acts&pullRequest=4090&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=acts-project_acts&pullRequest=4090&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=acts-project_acts&pullRequest=4090&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=acts-project_acts&pullRequest=4090)


author_association: NONE
user: login: paulgessinger
created_at: 2025-04-07T09:23:01Z
body: @benjaminhuth I will be adding a hard HepMC3 dependency in the Examples. We'll have to think about how that would work in this context.
author_association: MEMBER
user: login: sonarqubecloud[bot]
created_at: 2025-04-09T14:17:16Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=acts-project_acts&pullRequest=4090) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [1 New issue](https://sonarcloud.io/project/issues?id=acts-project_acts&pullRequest=4090&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=acts-project_acts&pullRequest=4090&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=acts-project_acts&pullRequest=4090&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=acts-project_acts&pullRequest=4090&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=acts-project_acts&pullRequest=4090&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=acts-project_acts&pullRequest=4090)


author_association: NONE