diff --git a/.github/workflows/analysis.yml b/.github/workflows/analysis.yml index 09e54f5971f..1e8c7d9d118 100644 --- a/.github/workflows/analysis.yml +++ b/.github/workflows/analysis.yml @@ -46,21 +46,10 @@ jobs: run: > ccache -z && cmake -B build -S . - -GNinja - -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + --preset=github-ci -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-Werror --coverage -g -gz -g1" - -DACTS_BUILD_UNITTESTS=on - -DACTS_BUILD_EXAMPLES_UNITTESTS=ON - -DACTS_BUILD_EVERYTHING=ON -DACTS_BUILD_ODD=OFF - -DACTS_BUILD_EXAMPLES_PYTHON_BINDINGS=ON - -DACTS_BUILD_EXAMPLES_EDM4HEP=ON - -DACTS_BUILD_ANALYSIS_APPS=ON - -DACTS_BUILD_PLUGIN_ONNX=ON - -DACTS_BUILD_PLUGIN_ACTSVG=ON - -DACTS_ENABLE_LOG_FAILURE_THRESHOLD=ON - -DCMAKE_EXPORT_COMPILE_COMMANDS=ON - name: Build run: cmake --build build - name: ccache stats @@ -106,11 +95,9 @@ jobs: - name: Configure run: > cmake -B build -S . - -GNinja + --preset=github-ci -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_CXX_FLAGS="-Werror" - -DACTS_BUILD_EVERYTHING=ON - -DCMAKE_EXPORT_COMPILE_COMMANDS=ON - name: Measure run: cmakeperf collect build/compile_commands.json -o perf.csv - name: Results diff --git a/.github/workflows/builds.yml b/.github/workflows/builds.yml index 9ffbffa7acc..28877e10e2f 100644 --- a/.github/workflows/builds.yml +++ b/.github/workflows/builds.yml @@ -56,22 +56,9 @@ jobs: git config --global user.email '<>' && ccache -z && cmake -B build -S . - -GNinja - -DCMAKE_CXX_COMPILER_LAUNCHER=ccache - -DCMAKE_BUILD_TYPE=Release - -DCMAKE_CXX_FLAGS=-Werror - -DCMAKE_CXX_STANDARD=20 + --preset=github-ci -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}" - -DACTS_ENABLE_LOG_FAILURE_THRESHOLD=ON - -DACTS_BUILD_EVERYTHING=ON - -DACTS_BUILD_EXAMPLES_UNITTESTS=ON - -DACTS_BUILD_ODD=ON - -DACTS_BUILD_EXAMPLES_PYTHON_BINDINGS=ON - -DACTS_BUILD_EXAMPLES_EDM4HEP=ON - -DACTS_FORCE_ASSERTIONS=ON - -DACTS_BUILD_ANALYSIS_APPS=ON -DACTS_BUILD_PLUGIN_ONNX=ON - -DACTS_BUILD_PLUGIN_ACTSVG=ON -DACTS_BUILD_PLUGIN_GEOMODEL=ON - name: Build @@ -276,21 +263,9 @@ jobs: run: > ccache -z && cmake -B build -S . - -GNinja - -DCMAKE_CXX_COMPILER_LAUNCHER=ccache - -DCMAKE_BUILD_TYPE=Release - -DCMAKE_CXX_FLAGS=-Werror + --preset=github-ci -DCMAKE_CXX_STANDARD=${{ matrix.std }} -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}" - -DACTS_ENABLE_LOG_FAILURE_THRESHOLD=ON - -DACTS_BUILD_EVERYTHING=ON - -DACTS_BUILD_EXAMPLES_UNITTESTS=ON - -DACTS_BUILD_ODD=ON - -DACTS_BUILD_EXAMPLES_PYTHON_BINDINGS=ON - -DACTS_BUILD_EXAMPLES_EDM4HEP=ON - -DACTS_FORCE_ASSERTIONS=OFF - -DACTS_BUILD_ANALYSIS_APPS=ON - -DACTS_BUILD_PLUGIN_ACTSVG=ON - name: Build run: cmake --build build @@ -335,7 +310,7 @@ jobs: INSTALL_DIR: ${{ github.workspace }}/install_acts DEPENDENCY_DIR: ${{ github.workspace }}/install ACTS_LOG_FAILURE_THRESHOLD: WARNING - DEPENDENCY_URL: https://acts.web.cern.ch/ACTS/ci/macOS/cmake/deps.8e12bbf.tar.zst + DEPENDENCY_URL: https://acts.web.cern.ch/ACTS/ci/macOS/cmake/deps.8a95213.tar.zst # Works around an issue where root's RPATH is wrong for tbb, thus won't find it DYLD_LIBRARY_PATH: "${{ github.workspace }}/install/tbb/2021.11.0/lib" steps: @@ -352,11 +327,9 @@ jobs: brew install cmake ninja ccache xerces-c && wget --verbose --progress=dot:giga --continue --retry-connrefused --tries=5 --timeout=2 -O deps.tar.zst ${{ env.DEPENDENCY_URL }} && mkdir ${{ env.DEPENDENCY_DIR }} - && ls ${{ env.DEPENDENCY_DIR }} && tar -xf deps.tar.zst -C ${{ env.DEPENDENCY_DIR }} - && ls ${{ env.DEPENDENCY_DIR }} - && ls ${{ env.DEPENDENCY_DIR }}/python - && ${{ env.DEPENDENCY_DIR }}/python/3.12.2/bin/python3 -m pip install pyyaml jinja2 + && PATH="${{ env.DEPENDENCY_DIR }}/bin:$PATH" + && python3 -m pip install pyyaml jinja2 - name: Restore ccache uses: actions/cache/restore@v4 @@ -373,24 +346,13 @@ jobs: # versions such as the one installed via homebrew run: > ccache -z - && source ${{ env.DEPENDENCY_DIR }}/setup.sh + && PATH="${{ env.DEPENDENCY_DIR }}/bin:$PATH" && cmake -B build -S . - -GNinja - -DCMAKE_CXX_COMPILER_LAUNCHER=ccache - -DPython_EXECUTABLE=${{ env.DEPENDENCY_DIR }}/python/3.12.2/bin/python3 - -DDD4HEP_DEBUG_CMAKE=ON - -DCMAKE_BUILD_TYPE=Release - -DCMAKE_CXX_FLAGS=-Werror - -DCMAKE_CXX_STANDARD=20 + --preset=github-ci + -DCMAKE_PREFIX_PATH="${{ env.DEPENDENCY_DIR }}" + -DPython_EXECUTABLE=${{ env.DEPENDENCY_DIR }}/bin/python3 -DCMAKE_INSTALL_PREFIX="${{ env.INSTALL_DIR }}" - -DCMAKE_PREFIX_PATH=/usr/local/acts - -DACTS_BUILD_EVERYTHING=ON - -DACTS_BUILD_EXAMPLES_UNITTESTS=ON - -DACTS_BUILD_ODD=ON - -DACTS_ENABLE_LOG_FAILURE_THRESHOLD=ON - -DACTS_FORCE_ASSERTIONS=ON - -DACTS_BUILD_EXAMPLES_EDM4HEP=ON - -DACTS_BUILD_PLUGIN_ACTSVG=ON + -DACTS_BUILD_EXAMPLES_PYTHON_BINDINGS=OFF - name: Build run: cmake --build build - name: ccache stats @@ -413,7 +375,7 @@ jobs: path: ${{ env.INSTALL_DIR }} - name: Downstream configure run: > - source ${{ env.DEPENDENCY_DIR }}/setup.sh + PATH="${{ env.DEPENDENCY_DIR }}/bin:$PATH" && cmake -B build-downstream -S Tests/DownstreamProject -GNinja -DCMAKE_BUILD_TYPE=Release @@ -423,7 +385,6 @@ jobs: - name: Downstream build run: cmake --build build-downstream - name: Downstream run - run: | - source ${{ env.DEPENDENCY_DIR }}/setup.sh - source ${{ env.DEPENDENCY_DIR}}/dd4hep/*/bin/thisdd4hep.sh - ./build-downstream/bin/ShowActsVersion + run: > + PATH="${{ env.DEPENDENCY_DIR }}/bin:$PATH" + && ./build-downstream/bin/ShowActsVersion diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d3325fd503c..c8dea9ff2a2 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -26,14 +26,11 @@ clang_tidy: && ln -sf /usr/bin/clang-tidy-18 /usr/bin/clang-tidy - > cmake -B build -S . - -GNinja + --preset=gitlab-ci-clangtidy -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang - -DCMAKE_BUILD_TYPE=Release - -DCMAKE_CXX_FLAGS="-Werror" - -DACTS_BUILD_EVERYTHING=on - -DACTS_BUILD_EXAMPLES_UNITTESTS=ON - -DACTS_RUN_CLANG_TIDY=on + -DACTS_RUN_CLANG_TIDY=ON + -DACTS_BUILD_ODD=OFF # Main clang-tidy run during cmake compilation - CI/clang_tidy/run_clang_tidy.sh clang-tidy build @@ -48,6 +45,7 @@ clang_tidy: clang-tidy/clang-tidy.json --exclude "*thirdparty*" --exclude "*ActsPodioEdm*" + --exclude "*build/_deps/*" # Check the combined report against the defined limits - CI/clang_tidy/check_clang_tidy.py --report clang-tidy/clang-tidy.json --config CI/clang_tidy/limits.yml @@ -79,18 +77,8 @@ build_exatrkx_cpu: # Here we only do a minimal build without examples to save ressources - > cmake -B build -S src - -DCMAKE_CXX_COMPILER_LAUNCHER=ccache - -GNinja - -DCMAKE_BUILD_TYPE=Release - -DCMAKE_CXX_FLAGS=-w - -DACTS_BUILD_PLUGIN_EXATRKX=ON - -DACTS_BUILD_EXAMPLES_EXATRKX=OFF - -DACTS_BUILD_UNITTESTS=OFF - -DACTS_EXATRKX_ENABLE_TORCH=ON - -DACTS_EXATRKX_ENABLE_ONNX=OFF + --preset=gitlab-ci-exatrkx -DACTS_EXATRKX_ENABLE_CUDA=OFF - -DACTS_BUILD_EXAMPLES_PYTHON_BINDINGS=OFF - -DACTS_ENABLE_LOG_FAILURE_THRESHOLD=ON - ccache -z - cmake --build build -- -j2 @@ -127,20 +115,8 @@ build_exatrkx: - mkdir build - > cmake -B build -S src - -DCMAKE_CXX_COMPILER_LAUNCHER=ccache - -GNinja - -DCMAKE_BUILD_TYPE=Release - -DCMAKE_CXX_FLAGS=-w - -DCMAKE_CUDA_FLAGS=-w + --preset=gitlab-ci-exatrkx -DCMAKE_CUDA_ARCHITECTURES="75;86" - -DACTS_BUILD_PLUGIN_EXATRKX=ON - -DACTS_BUILD_EXAMPLES_EXATRKX=ON - -DACTS_BUILD_UNITTESTS=ON - -DACTS_EXATRKX_ENABLE_TORCH=ON - -DACTS_EXATRKX_ENABLE_ONNX=OFF - -DACTS_EXATRKX_ENABLE_CUDA=ON - -DACTS_BUILD_EXAMPLES_PYTHON_BINDINGS=ON - -DACTS_ENABLE_LOG_FAILURE_THRESHOLD=ON - ccache -z - cmake --build build -- -j2 @@ -206,21 +182,8 @@ build_linux_ubuntu: - mkdir build - > cmake -B build -S src - -GNinja - -DCMAKE_CXX_COMPILER_LAUNCHER=ccache - -DCMAKE_BUILD_TYPE=RelWithDebInfo - -DCMAKE_CXX_FLAGS=-Werror - -DCMAKE_CXX_STANDARD=20 - -DACTS_ENABLE_LOG_FAILURE_THRESHOLD=ON - -DACTS_BUILD_EVERYTHING=ON - -DACTS_BUILD_EXAMPLES_UNITTESTS=ON - -DACTS_BUILD_ODD=ON - -DACTS_BUILD_EXAMPLES_PYTHON_BINDINGS=ON - -DACTS_BUILD_EXAMPLES_EDM4HEP=ON - -DACTS_FORCE_ASSERTIONS=ON - -DACTS_BUILD_ANALYSIS_APPS=ON + --preset=gitlab-ci -DACTS_BUILD_PLUGIN_ONNX=ON - -DACTS_BUILD_PLUGIN_ACTSVG=ON - ccache -z - cmake --build build -- -j2 @@ -245,7 +208,7 @@ linux_test_examples: - source build/this_acts_withdeps.sh - cd src - pip3 install -r Examples/Python/tests/requirements.txt - - pytest -rFsv -k "not exatrkx" -v + - pytest -rFsv -k "not exatrkx" -v -s linux_physmon: stage: test @@ -304,20 +267,8 @@ linux_physmon: - mkdir build - > cmake -B build -S src - -GNinja - -DCMAKE_CXX_COMPILER_LAUNCHER=ccache - -DCMAKE_BUILD_TYPE=Release - -DCMAKE_CXX_FLAGS=-Werror + --preset=gitlab-ci -DCMAKE_CXX_STANDARD=${CXXSTD} - -DACTS_ENABLE_LOG_FAILURE_THRESHOLD=ON - -DACTS_BUILD_EVERYTHING=ON - -DACTS_BUILD_EXAMPLES_UNITTESTS=ON - -DACTS_BUILD_ODD=ON - -DACTS_BUILD_EXAMPLES_PYTHON_BINDINGS=ON - -DACTS_BUILD_EXAMPLES_EDM4HEP=ON - -DACTS_FORCE_ASSERTIONS=ON - -DACTS_BUILD_ANALYSIS_APPS=ON - -DACTS_BUILD_PLUGIN_ACTSVG=ON - ccache -z - cmake --build build -- -j2 @@ -411,35 +362,8 @@ linux_ubuntu_2204_clang: script: - > cmake -B build -S src - -GNinja - -DCMAKE_CXX_COMPILER_LAUNCHER=ccache - -DCMAKE_BUILD_TYPE=Release - -DCMAKE_CXX_FLAGS=-Werror - -DCMAKE_CXX_STANDARD=20 + --preset=gitlab-ci -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}" - -DACTS_ENABLE_LOG_FAILURE_THRESHOLD=ON - -DACTS_BUILD_EXAMPLES_PYTHON_BINDINGS=ON - -DACTS_FORCE_ASSERTIONS=OFF - -DACTS_BUILD_UNITTESTS=ON - -DACTS_BUILD_INTEGRATIONTESTS=ON - -DACTS_BUILD_BENCHMARKS=ON - -DACTS_BUILD_EXAMPLES=ON - -DACTS_BUILD_PLUGIN_DD4HEP=OFF - -DACTS_BUILD_PLUGIN_TGEO=ON - -DACTS_BUILD_PLUGIN_IDENTIFICATION=ON - -DACTS_BUILD_PLUGIN_JSON=ON - -DACTS_BUILD_FATRAS=ON - -DACTS_BUILD_PLUGIN_LEGACY=ON - -DACTS_BUILD_EXAMPLES_DD4HEP=OFF - -DACTS_BUILD_PLUGIN_EDM4HEP=OFF - -DACTS_BUILD_EXAMPLES_GEANT4=ON - -DACTS_BUILD_EXAMPLES_HEPMC3=ON - -DACTS_BUILD_EXAMPLES_PYTHIA8=ON - -DACTS_BUILD_FATRAS_GEANT4=ON - -DACTS_BUILD_FATRAS=ON - -DACTS_BUILD_ALIGNMENT=ON - -DACTS_BUILD_ANALYSIS_APPS=ON - -DACTS_BUILD_PLUGIN_ACTSVG=ON - ccache -z - cmake --build build -- -j2 diff --git a/CI/physmon/reference/performance_ambi_orthogonal.root b/CI/physmon/reference/performance_ambi_orthogonal.root index 4d0dbc9c6a8..0b90c87805d 100644 Binary files a/CI/physmon/reference/performance_ambi_orthogonal.root and b/CI/physmon/reference/performance_ambi_orthogonal.root differ diff --git a/CI/physmon/reference/performance_ambi_seeded.root b/CI/physmon/reference/performance_ambi_seeded.root index 82e218a0cd6..27dbfdb416e 100644 Binary files a/CI/physmon/reference/performance_ambi_seeded.root and b/CI/physmon/reference/performance_ambi_seeded.root differ diff --git a/CI/physmon/reference/performance_ambi_ttbar.root b/CI/physmon/reference/performance_ambi_ttbar.root index 852fda6e398..2dd55c52b42 100644 Binary files a/CI/physmon/reference/performance_ambi_ttbar.root and b/CI/physmon/reference/performance_ambi_ttbar.root differ diff --git a/CI/physmon/reference/performance_amvf_gridseeder_seeded_hist.root b/CI/physmon/reference/performance_amvf_gridseeder_seeded_hist.root index 3c119aa300d..6cea895170f 100644 Binary files a/CI/physmon/reference/performance_amvf_gridseeder_seeded_hist.root and b/CI/physmon/reference/performance_amvf_gridseeder_seeded_hist.root differ diff --git a/CI/physmon/reference/performance_amvf_gridseeder_ttbar_hist.root b/CI/physmon/reference/performance_amvf_gridseeder_ttbar_hist.root index 353b7cf9536..312055b4dfc 100644 Binary files a/CI/physmon/reference/performance_amvf_gridseeder_ttbar_hist.root and b/CI/physmon/reference/performance_amvf_gridseeder_ttbar_hist.root differ diff --git a/CI/physmon/reference/performance_amvf_orthogonal_hist.root b/CI/physmon/reference/performance_amvf_orthogonal_hist.root index 0d4d3a142bb..f184cb85191 100644 Binary files a/CI/physmon/reference/performance_amvf_orthogonal_hist.root and b/CI/physmon/reference/performance_amvf_orthogonal_hist.root differ diff --git a/CI/physmon/reference/performance_amvf_seeded_hist.root b/CI/physmon/reference/performance_amvf_seeded_hist.root index 3ee4f1708dc..a93155fe12b 100644 Binary files a/CI/physmon/reference/performance_amvf_seeded_hist.root and b/CI/physmon/reference/performance_amvf_seeded_hist.root differ diff --git a/CI/physmon/reference/performance_amvf_truth_estimated_hist.root b/CI/physmon/reference/performance_amvf_truth_estimated_hist.root index 678b6200850..28b36526661 100644 Binary files a/CI/physmon/reference/performance_amvf_truth_estimated_hist.root and b/CI/physmon/reference/performance_amvf_truth_estimated_hist.root differ diff --git a/CI/physmon/reference/performance_amvf_truth_smeared_hist.root b/CI/physmon/reference/performance_amvf_truth_smeared_hist.root index e277e233c96..53703832364 100644 Binary files a/CI/physmon/reference/performance_amvf_truth_smeared_hist.root and b/CI/physmon/reference/performance_amvf_truth_smeared_hist.root differ diff --git a/CI/physmon/reference/performance_amvf_ttbar_hist.root b/CI/physmon/reference/performance_amvf_ttbar_hist.root index 4b65e64925c..47d53557498 100644 Binary files a/CI/physmon/reference/performance_amvf_ttbar_hist.root and b/CI/physmon/reference/performance_amvf_ttbar_hist.root differ diff --git a/CI/physmon/reference/performance_ckf_orthogonal.root b/CI/physmon/reference/performance_ckf_orthogonal.root index 3b74c04e73b..1649924f0e4 100644 Binary files a/CI/physmon/reference/performance_ckf_orthogonal.root and b/CI/physmon/reference/performance_ckf_orthogonal.root differ diff --git a/CI/physmon/reference/performance_ckf_seeded.root b/CI/physmon/reference/performance_ckf_seeded.root index fd993815661..1e4d7392a93 100644 Binary files a/CI/physmon/reference/performance_ckf_seeded.root and b/CI/physmon/reference/performance_ckf_seeded.root differ diff --git a/CI/physmon/reference/performance_ckf_truth_estimated.root b/CI/physmon/reference/performance_ckf_truth_estimated.root index b6940e6288d..f48c7f92896 100644 Binary files a/CI/physmon/reference/performance_ckf_truth_estimated.root and b/CI/physmon/reference/performance_ckf_truth_estimated.root differ diff --git a/CI/physmon/reference/performance_ckf_truth_smeared.root b/CI/physmon/reference/performance_ckf_truth_smeared.root index 0705062a396..0311e42de0d 100644 Binary files a/CI/physmon/reference/performance_ckf_truth_smeared.root and b/CI/physmon/reference/performance_ckf_truth_smeared.root differ diff --git a/CI/physmon/reference/performance_ckf_ttbar.root b/CI/physmon/reference/performance_ckf_ttbar.root index ae3df7e82fa..6a97b0ab1b4 100644 Binary files a/CI/physmon/reference/performance_ckf_ttbar.root and b/CI/physmon/reference/performance_ckf_ttbar.root differ diff --git a/CI/physmon/reference/performance_gsf.root b/CI/physmon/reference/performance_gsf.root index faa6c70a7df..c6eb98c5d55 100644 Binary files a/CI/physmon/reference/performance_gsf.root and b/CI/physmon/reference/performance_gsf.root differ diff --git a/CI/physmon/reference/performance_gx2f.root b/CI/physmon/reference/performance_gx2f.root index d49ca45dda0..5ef556b0cda 100644 Binary files a/CI/physmon/reference/performance_gx2f.root and b/CI/physmon/reference/performance_gx2f.root differ diff --git a/CI/physmon/reference/performance_ivf_orthogonal_hist.root b/CI/physmon/reference/performance_ivf_orthogonal_hist.root index 082a997c97a..1fd1a743e75 100644 Binary files a/CI/physmon/reference/performance_ivf_orthogonal_hist.root and b/CI/physmon/reference/performance_ivf_orthogonal_hist.root differ diff --git a/CI/physmon/reference/performance_ivf_seeded_hist.root b/CI/physmon/reference/performance_ivf_seeded_hist.root index 836226fc0c1..e2559f1677f 100644 Binary files a/CI/physmon/reference/performance_ivf_seeded_hist.root and b/CI/physmon/reference/performance_ivf_seeded_hist.root differ diff --git a/CI/physmon/reference/performance_ivf_truth_estimated_hist.root b/CI/physmon/reference/performance_ivf_truth_estimated_hist.root index ee316bb11c1..265d2cdb22e 100644 Binary files a/CI/physmon/reference/performance_ivf_truth_estimated_hist.root and b/CI/physmon/reference/performance_ivf_truth_estimated_hist.root differ diff --git a/CI/physmon/reference/performance_ivf_truth_smeared_hist.root b/CI/physmon/reference/performance_ivf_truth_smeared_hist.root index cf00b7c3884..89ebd7fbd05 100644 Binary files a/CI/physmon/reference/performance_ivf_truth_smeared_hist.root and b/CI/physmon/reference/performance_ivf_truth_smeared_hist.root differ diff --git a/CI/physmon/reference/performance_truth_tracking.root b/CI/physmon/reference/performance_truth_tracking.root index 48964c4aa49..80b20677291 100644 Binary files a/CI/physmon/reference/performance_truth_tracking.root and b/CI/physmon/reference/performance_truth_tracking.root differ diff --git a/CI/physmon/reference/tracksummary_ckf_orthogonal_hist.root b/CI/physmon/reference/tracksummary_ckf_orthogonal_hist.root index d3423b1dc32..17568bda0d1 100644 Binary files a/CI/physmon/reference/tracksummary_ckf_orthogonal_hist.root and b/CI/physmon/reference/tracksummary_ckf_orthogonal_hist.root differ diff --git a/CI/physmon/reference/tracksummary_ckf_seeded_hist.root b/CI/physmon/reference/tracksummary_ckf_seeded_hist.root index 6f850818a06..d94d7d61036 100644 Binary files a/CI/physmon/reference/tracksummary_ckf_seeded_hist.root and b/CI/physmon/reference/tracksummary_ckf_seeded_hist.root differ diff --git a/CI/physmon/reference/tracksummary_ckf_truth_estimated_hist.root b/CI/physmon/reference/tracksummary_ckf_truth_estimated_hist.root index 8eab3640285..45967d27ba1 100644 Binary files a/CI/physmon/reference/tracksummary_ckf_truth_estimated_hist.root and b/CI/physmon/reference/tracksummary_ckf_truth_estimated_hist.root differ diff --git a/CI/physmon/reference/tracksummary_ckf_truth_smeared_hist.root b/CI/physmon/reference/tracksummary_ckf_truth_smeared_hist.root index a1eeba9fb60..bcc83d6d6fa 100644 Binary files a/CI/physmon/reference/tracksummary_ckf_truth_smeared_hist.root and b/CI/physmon/reference/tracksummary_ckf_truth_smeared_hist.root differ diff --git a/CI/physmon/reference/tracksummary_ckf_ttbar_hist.root b/CI/physmon/reference/tracksummary_ckf_ttbar_hist.root index ad78496556d..49a8555ee7e 100644 Binary files a/CI/physmon/reference/tracksummary_ckf_ttbar_hist.root and b/CI/physmon/reference/tracksummary_ckf_ttbar_hist.root differ diff --git a/CI/physmon/workflows/physmon_ckf_tracking.py b/CI/physmon/workflows/physmon_ckf_tracking.py index a9f1b4bf8fd..969224f14aa 100755 --- a/CI/physmon/workflows/physmon_ckf_tracking.py +++ b/CI/physmon/workflows/physmon_ckf_tracking.py @@ -91,9 +91,19 @@ def run_ckf_tracking(truthSmearedSeeded, truthEstimatedSeeded, label): setup.trackingGeometry, setup.field, TruthSeedRanges(pt=(500 * u.MeV, None), nHits=(9, None)), - ParticleSmearingSigmas( - pRel=0.01 - ), # only used by SeedingAlgorithm.TruthSmeared + ParticleSmearingSigmas( # only used by SeedingAlgorithm.TruthSmeared + # zero eveything so the CKF has a chance to find the measurements + d0=0, + d0PtA=0, + d0PtB=0, + z0=0, + z0PtA=0, + z0PtB=0, + t0=0, + phi=0, + theta=0, + ptRel=0, + ), SeedFinderConfigArg( r=(33 * u.mm, 200 * u.mm), deltaR=(1 * u.mm, 60 * u.mm), @@ -125,9 +135,10 @@ def run_ckf_tracking(truthSmearedSeeded, truthEstimatedSeeded, label): 1 * u.mm, 1 * u.degree, 1 * u.degree, - 0.1 / u.GeV, + 0.1 * u.e / u.GeV, 1 * u.ns, ], + initialSigmaPtRel=0.01, initialVarInflation=[1.0] * 6, geoSelectionConfigFile=setup.geoSel, rnd=rnd, # only used by SeedingAlgorithm.TruthSmeared diff --git a/CI/physmon/workflows/physmon_vertexing.py b/CI/physmon/workflows/physmon_vertexing.py index c20dace32c8..2486923b019 100755 --- a/CI/physmon/workflows/physmon_vertexing.py +++ b/CI/physmon/workflows/physmon_vertexing.py @@ -105,9 +105,10 @@ def run_vertexing(fitter, mu, events): 1 * u.mm, 1 * u.degree, 1 * u.degree, - 0.1 / u.GeV, + 0.1 * u.e / u.GeV, 1 * u.ns, ], + initialSigmaPtRel=0.1, initialVarInflation=[1.0] * 6, geoSelectionConfigFile=setup.geoSel, ) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6d9a7695884..1f550182648 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,6 @@ project(Acts VERSION ${_acts_version} LANGUAGES CXX) # NOTE if you are adding a new option make sure that is defined in such a way # that it is off/empty by default. if you think that is not possible, then # it probably is not an optional component. -option(ACTS_BUILD_EVERYTHING "Build with most options enabled (except HepMC3 and documentation)" OFF) # core related options set(ACTS_PARAMETER_DEFINITIONS_HEADER "" CACHE FILEPATH "Use a different (track) parameter definitions header") set(ACTS_SOURCELINK_SBO_SIZE "" CACHE STRING "Customize the SBO size used by SourceLink") @@ -50,17 +49,11 @@ option(ACTS_BUILD_PLUGIN_JSON "Build json plugin" OFF) option(ACTS_USE_SYSTEM_NLOHMANN_JSON "Use nlohmann::json provided by the system instead of the bundled version" ${ACTS_USE_SYSTEM_LIBS}) option(ACTS_BUILD_PLUGIN_LEGACY "Build legacy plugin" OFF) option(ACTS_BUILD_PLUGIN_ONNX "Build ONNX plugin" OFF) -option(ACTS_SETUP_COVFIE "Explicitly set up covfie for the project" OFF) option(ACTS_USE_SYSTEM_COVFIE "Use a system-provided covfie installation" ${ACTS_USE_SYSTEM_LIBS}) -option(ACTS_SETUP_DETRAY "Explicitly set up detray for the project" OFF) option(ACTS_USE_SYSTEM_DETRAY "Use a system-provided detray installation" ${ACTS_USE_SYSTEM_LIBS}) -option(ACTS_SETUP_TRACCC "Explicitly set up traccc for the project" OFF) option(ACTS_USE_SYSTEM_TRACCC "Use a system-provided traccc installation" ${ACTS_USE_SYSTEM_LIBS}) -option(ACTS_SETUP_DFELIBS "Explicitly set up dfelibs for the project" ON) option(ACTS_USE_SYSTEM_DFELIBS "Use a system-provided dfelibs installation" ${ACTS_USE_SYSTEM_LIBS}) -option(ACTS_SETUP_VECMEM "Explicitly set up vecmem for the project" OFF) option(ACTS_USE_SYSTEM_VECMEM "Use a system-provided vecmem installation" ${ACTS_USE_SYSTEM_LIBS}) -option(ACTS_SETUP_ALGEBRAPLUGINS "Explicitly set up algebra-plugins for the project" OFF) option(ACTS_USE_SYSTEM_ALGEBRAPLUGINS "Use a system-provided algebra-plugins installation" ${ACTS_USE_SYSTEM_LIBS}) option(ACTS_BUILD_PLUGIN_TGEO "Build TGeo plugin" OFF) # fatras related options @@ -69,7 +62,6 @@ option(ACTS_BUILD_FATRAS_GEANT4 "Build Geant4 Fatras package" OFF) # alignment related options option(ACTS_BUILD_ALIGNMENT "Build Alignment package" OFF) # examples related options -option(ACTS_BUILD_EXAMPLES "Build standalone examples" OFF) option(ACTS_BUILD_EXAMPLES_DD4HEP "Build DD4hep-based code in the examples" OFF) option(ACTS_BUILD_EXAMPLES_EDM4HEP "Build EDM4hep-based code in the examples" OFF) option(ACTS_BUILD_EXAMPLES_EXATRKX "Build the Exa.TrkX example code" OFF) @@ -110,20 +102,6 @@ set(ACTS_LOG_FAILURE_THRESHOLD "" CACHE STRING "Log level above which an excepti # handle option inter-dependencies and the everything flag # NOTE: ordering is important here. dependencies must come before dependees include(ActsOptionHelpers) -# options without inter-dependencies -set_option_if(ACTS_BUILD_BENCHMARKS ACTS_BUILD_EVERYTHING) -set_option_if(ACTS_BUILD_UNITTESTS ACTS_BUILD_EVERYTHING) -set_option_if(ACTS_BUILD_NONCOMPILE_TESTS ACTS_BUILD_EVERYTHING) -set_option_if(ACTS_BUILD_INTEGRATIONTESTS ACTS_BUILD_EVERYTHING) -set_option_if(ACTS_BUILD_EXAMPLES_DD4HEP ACTS_BUILD_EVERYTHING) -set_option_if(ACTS_BUILD_EXAMPLES_GEANT4 ACTS_BUILD_EVERYTHING) -set_option_if(ACTS_BUILD_EXAMPLES_HEPMC3 ACTS_BUILD_EVERYTHING) -set_option_if(ACTS_BUILD_EXAMPLES_PYTHIA8 ACTS_BUILD_EVERYTHING) -set_option_if(ACTS_BUILD_FATRAS_GEANT4 ACTS_BUILD_EVERYTHING) -set_option_if(ACTS_BUILD_FATRAS ACTS_BUILD_FATRAS_GEANT4) -set_option_if(ACTS_BUILD_ALIGNMENT ACTS_BUILD_EVERYTHING) -set_option_if(ACTS_BUILD_EXAMPLES_EDM4HEP ACTS_BUILD_EVERYTHING) -set_option_if(ACTS_BUILD_ANALYSIS_APPS ACTS_BUILD_EVERYTHING) # any examples component activates the general examples option set_option_if( @@ -134,36 +112,49 @@ set_option_if( OR ACTS_BUILD_EXAMPLES_HEPMC3 OR ACTS_BUILD_EXAMPLES_PYTHIA8 OR ACTS_BUILD_EXAMPLES_EXATRKX - OR ACTS_BUILD_EXAMPLES_PYTHON_BINDINGS - OR ACTS_BUILD_EVERYTHING) + OR ACTS_BUILD_EXAMPLES_PYTHON_BINDINGS) # core plugins might be required by examples or depend on each other set_option_if( ACTS_BUILD_PLUGIN_DD4HEP - ACTS_BUILD_EXAMPLES_DD4HEP OR ACTS_BUILD_EVERYTHING OR + ACTS_BUILD_EXAMPLES_DD4HEP OR ACTS_BUILD_EXAMPLES_EDM4HEP) set_option_if( ACTS_BUILD_PLUGIN_EDM4HEP - ACTS_BUILD_EXAMPLES_EDM4HEP OR ACTS_BUILD_EVERYTHING) + ACTS_BUILD_EXAMPLES_EDM4HEP) set_option_if( ACTS_BUILD_PLUGIN_PODIO - ACTS_BUILD_EVERYTHING) + ACTS_BUILD_EXAMPLES_EDM4HEP) set_option_if( ACTS_BUILD_PLUGIN_GEANT4 - ACTS_BUILD_EXAMPLES_GEANT4 OR ACTS_BUILD_EVERYTHING) + ACTS_BUILD_EXAMPLES_GEANT4) set_option_if( ACTS_BUILD_PLUGIN_TGEO - ACTS_BUILD_PLUGIN_DD4HEP OR ACTS_BUILD_EXAMPLES OR ACTS_BUILD_EVERYTHING) + ACTS_BUILD_PLUGIN_DD4HEP OR + ACTS_BUILD_EXAMPLES) +set_option_if( + ACTS_BUILD_PLUGIN_IDENTIFICATION + ACTS_BUILD_PLUGIN_TGEO OR + ACTS_BUILD_PLUGIN_PODIO OR + ACTS_BUILD_EXAMPLES) set_option_if( ACTS_BUILD_PLUGIN_JSON - ACTS_BUILD_EXAMPLES OR ACTS_BUILD_EVERYTHING) + ACTS_BUILD_EXAMPLES) set_option_if( ACTS_BUILD_FATRAS - ACTS_BUILD_EXAMPLES OR ACTS_BUILD_EVERYTHING) -set_option_if(ACTS_BUILD_PLUGIN_LEGACY ACTS_BUILD_EVERYTHING) -set_option_if(ACTS_BUILD_PLUGIN_EXATRKX ACTS_BUILD_EXAMPLES_EXATRKX) -set_option_if(ACTS_BUILD_PLUGIN_FPEMON - ACTS_BUILD_EXAMPLES OR ACTS_BUILD_EVERYTHING) + ACTS_BUILD_EXAMPLES) +set_option_if( + ACTS_BUILD_PLUGIN_EXATRKX + ACTS_BUILD_EXAMPLES_EXATRKX) +set_option_if( + ACTS_BUILD_PLUGIN_FPEMON + ACTS_BUILD_EXAMPLES) +set_option_if( + ACTS_BUILD_PLUGIN_DETRAY + ACTS_BUILD_PLUGIN_TRACCC) +set_option_if( + ACTS_BUILD_PLUGIN_COVFIE + ACTS_BUILD_PLUGIN_DETRAY) # feature tests include(CheckCXXSourceCompiles) @@ -214,6 +205,11 @@ set(_acts_onnxruntime_version 1.12.0) set(_acts_root_version 6.20) set(_acts_tbb_version 2020.1) set(_acts_pythia8_version 8.309) +set(_acts_detray_version 0.72.0) +set(_acts_traccc_version 0.13.0) +set(_acts_covfie_version 0.10.0) +set(_acts_vecmem_version 1.4.0) +set(_acts_algebraplugins_version 0.22.0) # recommended dependency version. if there is an opportunity to reach # this version we will try so. @@ -258,30 +254,10 @@ if (ACTS_SETUP_EIGEN3) endif() endif() -if (ACTS_SETUP_DFELIBS) - if (ACTS_USE_SYSTEM_DFELIBS) - find_package(dfelibs ${_acts_dfelibs_version} REQUIRED) - else() - add_subdirectory(thirdparty/dfelibs) - endif() -endif() - -if (ACTS_SETUP_VECMEM) - if (ACTS_USE_SYSTEM_VECMEM) - find_package(vecmem ${_acts_vecmem_version} REQUIRED) - else() - add_subdirectory(thirdparty/vecmem) - # Make the "VecMem language code" available for the whole project. - include( "${VECMEM_LANGUAGE_DIR}/vecmem-check-language.cmake" ) - endif() -endif() - -if (ACTS_SETUP_ALGEBRAPLUGINS) - if (ACTS_USE_SYSTEM_ALGEBRAPLUGINS) - find_package(algebra-plugins ${_acts_algebraplugins_version} REQUIRED) - else() - add_subdirectory(thirdparty/algebra-plugins) - endif() +if (ACTS_USE_SYSTEM_DFELIBS) + find_package(dfelibs ${_acts_dfelibs_version} REQUIRED) +else() + add_subdirectory(thirdparty/dfelibs) endif() find_package(Filesystem REQUIRED) @@ -316,30 +292,6 @@ endmacro() # find packages explicitly for each component even if this means searching for # the same package twice. This avoids having complex if/else trees to sort out # when a particular package is actually needed. - -# plugin dependencies -if(ACTS_SETUP_COVFIE) - if(ACTS_USE_SYSTEM_COVFIE) - find_package(covfie ${_acts_covfie_version} REQUIRED CONFIG) - else() - add_subdirectory(thirdparty/covfie) - endif() -endif() -if(ACTS_SETUP_DETRAY) - if(ACTS_USE_SYSTEM_DETRAY) - find_package(detray ${_acts_detray_version} REQUIRED CONFIG) - else() - add_subdirectory(thirdparty/detray) - endif() -endif() -if(ACTS_SETUP_TRACCC) - if(ACTS_USE_SYSTEM_TRACCC) - find_package(traccc ${_acts_traccc_version} REQUIRED CONFIG) - else() - add_subdirectory(thirdparty/traccc) - endif() -endif() - if(ACTS_BUILD_PLUGIN_ACTSVG) if(ACTS_USE_SYSTEM_ACTSVG) find_package(actsvg ${_acts_actsvg_version} REQUIRED CONFIG) @@ -418,6 +370,43 @@ endif() if(ACTS_BUILD_PLUGIN_GEANT4) find_package(Geant4 REQUIRED CONFIG COMPONENTS gdml) endif() +if(ACTS_BUILD_PLUGIN_DETRAY) + if(ACTS_USE_SYSTEM_DETRAY) + find_package(detray ${_acts_detray_version} REQUIRED CONFIG) + else() + add_subdirectory(thirdparty/detray) + endif() + + if (ACTS_USE_SYSTEM_VECMEM) + find_package(vecmem ${_acts_vecmem_version} REQUIRED) + else() + add_subdirectory(thirdparty/vecmem) + # Make the "VecMem language code" available for the whole project. + include( "${VECMEM_LANGUAGE_DIR}/vecmem-check-language.cmake" ) + endif() + + if (ACTS_USE_SYSTEM_ALGEBRAPLUGINS) + find_package(algebra-plugins ${_acts_algebraplugins_version} REQUIRED) + else() + add_subdirectory(thirdparty/algebra-plugins) + endif() +endif() +if(ACTS_BUILD_PLUGIN_COVFIE) + if(ACTS_USE_SYSTEM_COVFIE) + find_package(covfie ${_acts_covfie_version} REQUIRED CONFIG) + else() + add_subdirectory(thirdparty/covfie) + endif() +endif() +if(ACTS_BUILD_PLUGIN_TRACCC) + # traccc also depends on vecmem and covfie, but those plugins should always + # be enabled if traccc is. + if(ACTS_USE_SYSTEM_TRACCC) + find_package(traccc ${_acts_traccc_version} REQUIRED CONFIG) + else() + add_subdirectory(thirdparty/traccc) + endif() +endif() # examples dependencies if(ACTS_BUILD_EXAMPLES) diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 00000000000..4f314fa0212 --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,114 @@ +{ + "version": 3, + "configurePresets": [ + { + "name": "common", + "hidden": true, + "generator": "Ninja", + "cacheVariables": { + "CMAKE_CXX_STANDARD": "20", + "CMAKE_CXX_COMPILER_LAUNCHER": "ccache", + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON", + "ACTS_ENABLE_LOG_FAILURE_THRESHOLD": "OFF", + "ACTS_BUILD_FATRAS": "ON", + "ACTS_BUILD_ODD": "ON", + "ACTS_BUILD_UNITTESTS": "ON", + "ACTS_BUILD_INTEGRATIONTESTS": "ON", + "ACTS_BUILD_PLUGIN_LEGACY": "ON", + "ACTS_BUILD_EXAMPLES_DD4HEP": "ON", + "ACTS_BUILD_EXAMPLES_PYTHON_BINDINGS": "ON", + "ACTS_BUILD_EXAMPLES_UNITTESTS": "ON" + } + }, + { + "name": "dev", + "displayName": "Development", + "inherits": "common", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "RelWithDebInfo", + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON", + "ACTS_FORCE_ASSERTIONS": "ON" + } + }, + { + "name": "perf", + "displayName": "Performance", + "inherits": "common", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release", + "CMAKE_CXX_FLAGS": "-O3 -DNDEBUG -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer", + "ACTS_BUILD_BENCHMARKS": "ON" + } + }, + { + "name": "ci-common", + "hidden": true, + "inherits": "common", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release", + "CMAKE_CXX_FLAGS": "-Werror", + "ACTS_FORCE_ASSERTIONS": "ON", + "ACTS_ENABLE_LOG_FAILURE_THRESHOLD": "ON", + "ACTS_BUILD_BENCHMARKS": "ON", + "ACTS_BUILD_NONCOMPILE_TESTS": "ON", + "ACTS_BUILD_ANALYSIS_APPS": "ON", + "ACTS_BUILD_ALIGNMENT": "ON", + "ACTS_BUILD_FATRAS_GEANT4": "ON", + "ACTS_BUILD_PLUGIN_ACTSVG": "ON", + "ACTS_BUILD_EXAMPLES_EDM4HEP": "ON", + "ACTS_BUILD_EXAMPLES_GEANT4": "ON", + "ACTS_BUILD_EXAMPLES_HEPMC3": "ON", + "ACTS_BUILD_EXAMPLES_PYTHIA8": "ON" + } + }, + { + "name": "github-ci", + "displayName": "GitHub-CI", + "inherits": "ci-common", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release" + } + }, + { + "name": "gitlab-ci", + "displayName": "GitLab-CI", + "inherits": "ci-common", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "RelWithDebInfo", + "ACTS_BUILD_PLUGIN_FPEMON": "ON" + } + }, + { + "name": "gitlab-ci-clangtidy", + "displayName": "GitLab-CI", + "inherits": "ci-common", + "cacheVariables": { + "ACTS_BUILD_PLUGIN_ACTSVG": "OFF", + "ACTS_BUILD_ODD": "OFF", + "ACTS_BUILD_EXAMPLES_PYTHON_BINDINGS": "OFF", + "ACTS_RUN_CLANG_TIDY": "ON" + } + }, + { + "name": "gitlab-ci-exatrkx", + "displayName": "GitLab-CI", + "generator": "Ninja", + "cacheVariables": { + "CMAKE_CXX_STANDARD": "20", + "CMAKE_CXX_COMPILER_LAUNCHER": "ccache", + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON", + "CMAKE_BUILD_TYPE": "Release", + "CMAKE_CXX_FLAGS": "-w", + "CMAKE_CUDA_FLAGS": "-w", + "ACTS_BUILD_PLUGIN_EXATRKX": "ON", + "ACTS_BUILD_EXAMPLES_EXATRKX": "ON", + "ACTS_BUILD_UNITTESTS": "ON", + "ACTS_EXATRKX_ENABLE_TORCH": "ON", + "ACTS_EXATRKX_ENABLE_ONNX": "OFF", + "ACTS_EXATRKX_ENABLE_CUDA": "ON", + "ACTS_BUILD_EXAMPLES_PYTHON_BINDINGS": "ON", + "ACTS_ENABLE_LOG_FAILURE_THRESHOLD": "ON" + } + } + ] +} \ No newline at end of file diff --git a/Core/include/Acts/AmbiguityResolution/GreedyAmbiguityResolution.hpp b/Core/include/Acts/AmbiguityResolution/GreedyAmbiguityResolution.hpp index 39f967b3494..cffdb128220 100644 --- a/Core/include/Acts/AmbiguityResolution/GreedyAmbiguityResolution.hpp +++ b/Core/include/Acts/AmbiguityResolution/GreedyAmbiguityResolution.hpp @@ -1,6 +1,6 @@ // This file is part of the Acts project. // -// Copyright (C) 2020 CERN for the benefit of the Acts project +// Copyright (C) 2023-2024 CERN for the benefit of the Acts project // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this diff --git a/Core/include/Acts/AmbiguityResolution/GreedyAmbiguityResolution.ipp b/Core/include/Acts/AmbiguityResolution/GreedyAmbiguityResolution.ipp index ee2d14b1564..2f231ff216b 100644 --- a/Core/include/Acts/AmbiguityResolution/GreedyAmbiguityResolution.ipp +++ b/Core/include/Acts/AmbiguityResolution/GreedyAmbiguityResolution.ipp @@ -1,6 +1,6 @@ // This file is part of the Acts project. // -// Copyright (C) 2020 CERN for the benefit of the Acts project +// Copyright (C) 2023-2024 CERN for the benefit of the Acts project // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -9,6 +9,7 @@ #pragma once #include "Acts/AmbiguityResolution/GreedyAmbiguityResolution.hpp" +#include "Acts/EventData/TrackStateType.hpp" #include @@ -36,7 +37,9 @@ void GreedyAmbiguityResolution::computeInitialState( } std::vector measurements; for (auto ts : track.trackStatesReversed()) { - if (ts.typeFlags().test(Acts::TrackStateFlag::MeasurementFlag)) { + bool isMeasurement = ts.typeFlags().test(TrackStateFlag::MeasurementFlag); + bool isOutlier = ts.typeFlags().test(TrackStateFlag::OutlierFlag); + if (isMeasurement && !isOutlier) { SourceLink sourceLink = ts.getUncalibratedSourceLink(); // assign a new measurement index if the source link was not seen yet auto emplace = measurementIndexMap.try_emplace( diff --git a/Core/include/Acts/AmbiguityResolution/ScoreBasedAmbiguityResolution.ipp b/Core/include/Acts/AmbiguityResolution/ScoreBasedAmbiguityResolution.ipp index cb3f5803342..5175248a05c 100644 --- a/Core/include/Acts/AmbiguityResolution/ScoreBasedAmbiguityResolution.ipp +++ b/Core/include/Acts/AmbiguityResolution/ScoreBasedAmbiguityResolution.ipp @@ -58,7 +58,22 @@ ScoreBasedAmbiguityResolution::computeInitialState( } auto detectorId = volume_it->second; - if (ts.typeFlags().test(Acts::TrackStateFlag::MeasurementFlag)) { + if (ts.typeFlags().test(Acts::TrackStateFlag::HoleFlag)) { + ACTS_DEBUG("Track state type is HoleFlag"); + trackFeaturesVector[detectorId].nHoles++; + } else if (ts.typeFlags().test(Acts::TrackStateFlag::OutlierFlag)) { + Acts::SourceLink sourceLink = ts.getUncalibratedSourceLink(); + ACTS_DEBUG("Track state type is OutlierFlag"); + trackFeaturesVector[detectorId].nOutliers++; + + // assign a new measurement index if the source link was not seen yet + auto emplace = MeasurementIndexMap.try_emplace( + sourceLink, MeasurementIndexMap.size()); + + bool isOutliner = true; + + measurements.push_back({emplace.first->second, detectorId, isOutliner}); + } else if (ts.typeFlags().test(Acts::TrackStateFlag::MeasurementFlag)) { Acts::SourceLink sourceLink = ts.getUncalibratedSourceLink(); ACTS_DEBUG("Track state type is MeasurementFlag"); @@ -74,21 +89,6 @@ ScoreBasedAmbiguityResolution::computeInitialState( bool isoutliner = false; measurements.push_back({emplace.first->second, detectorId, isoutliner}); - } else if (ts.typeFlags().test(Acts::TrackStateFlag::OutlierFlag)) { - Acts::SourceLink sourceLink = ts.getUncalibratedSourceLink(); - ACTS_DEBUG("Track state type is OutlierFlag"); - trackFeaturesVector[detectorId].nOutliers++; - - // assign a new measurement index if the source link was not seen yet - auto emplace = MeasurementIndexMap.try_emplace( - sourceLink, MeasurementIndexMap.size()); - - bool isOutliner = true; - - measurements.push_back({emplace.first->second, detectorId, isOutliner}); - } else if (ts.typeFlags().test(Acts::TrackStateFlag::HoleFlag)) { - ACTS_DEBUG("Track state type is HoleFlag"); - trackFeaturesVector[detectorId].nHoles++; } } measurementsPerTrack.push_back(std::move(measurements)); diff --git a/Core/include/Acts/Detector/Detector.hpp b/Core/include/Acts/Detector/Detector.hpp index bbdec5931d8..6ce3d4bc488 100644 --- a/Core/include/Acts/Detector/Detector.hpp +++ b/Core/include/Acts/Detector/Detector.hpp @@ -102,6 +102,13 @@ class Detector : public std::enable_shared_from_this { /// @return the map which can be queried with GeometryID for ranges const GeometryHierarchyMap& sensitiveHierarchyMap() const; + /// Search for a surface with the given identifier. + /// + /// @param id is the geometry identifier of the surface + /// @retval nullptr if no such surface exists + /// @retval pointer to the found surface otherwise. + const Surface* findSurface(GeometryIdentifier id) const; + /// @brief Visit all reachable surfaces of the detector /// /// @tparam visitor_t Type of the callable visitor diff --git a/Core/include/Acts/EventData/MultiTrajectoryHelpers.hpp b/Core/include/Acts/EventData/MultiTrajectoryHelpers.hpp index 1bc2c6e6f8b..84d4c763a7b 100644 --- a/Core/include/Acts/EventData/MultiTrajectoryHelpers.hpp +++ b/Core/include/Acts/EventData/MultiTrajectoryHelpers.hpp @@ -1,12 +1,13 @@ // This file is part of the Acts project. // -// Copyright (C) 2020 CERN for the benefit of the Acts project +// Copyright (C) 2020-2024 CERN for the benefit of the Acts project // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. #pragma once + #include "Acts/EventData/MultiTrajectory.hpp" #include "Acts/EventData/TrackContainer.hpp" #include "Acts/EventData/TransformationHelpers.hpp" @@ -44,21 +45,27 @@ using VolumeTrajectoryStateContainer = /// @brief Getter for global trajectory info /// /// @param multiTraj The MultiTrajectory object -/// @param entryIndex The entry index of trajectory to investigate +/// @param tipIndex The entry index of trajectory to investigate /// /// @return The trajectory summary info template -TrajectoryState trajectoryState(const traj_t& multiTraj, - std::size_t entryIndex) { +TrajectoryState trajectoryState(const traj_t& multiTraj, std::size_t tipIndex) { TrajectoryState trajState; - multiTraj.visitBackwards(entryIndex, [&](const auto& state) { + multiTraj.visitBackwards(tipIndex, [&](const auto& state) { // Get the volume Id of this surface const auto& geoID = state.referenceSurface().geometryId(); const auto& volume = geoID.volume(); const auto& layer = geoID.layer(); trajState.nStates++; auto typeFlags = state.typeFlags(); - if (typeFlags.test(Acts::TrackStateFlag::MeasurementFlag)) { + if (typeFlags.test(Acts::TrackStateFlag::HoleFlag)) { + trajState.nHoles++; + } else if (typeFlags.test(Acts::TrackStateFlag::OutlierFlag)) { + trajState.nOutliers++; + trajState.outlierChi2.push_back(state.chi2()); + trajState.outlierVolume.push_back(volume); + trajState.outlierLayer.push_back(layer); + } else if (typeFlags.test(Acts::TrackStateFlag::MeasurementFlag)) { if (typeFlags.test(Acts::TrackStateFlag::SharedHitFlag)) { trajState.nSharedHits++; } @@ -68,13 +75,6 @@ TrajectoryState trajectoryState(const traj_t& multiTraj, trajState.measurementLayer.push_back(layer); trajState.chi2Sum += state.chi2(); trajState.NDF += state.calibratedSize(); - } else if (typeFlags.test(Acts::TrackStateFlag::OutlierFlag)) { - trajState.nOutliers++; - trajState.outlierChi2.push_back(state.chi2()); - trajState.outlierVolume.push_back(volume); - trajState.outlierLayer.push_back(layer); - } else if (typeFlags.test(Acts::TrackStateFlag::HoleFlag)) { - trajState.nHoles++; } }); return trajState; @@ -85,7 +85,7 @@ TrajectoryState trajectoryState(const traj_t& multiTraj, /// @tparam source_link_t Type of source link /// /// @param multiTraj The MultiTrajectory object -/// @param entryIndex The entry index of trajectory to investigate +/// @param tipIndex The entry index of trajectory to investigate /// track states at different sub-detectors. /// @param volumeIds The container for sub-detector Ids /// @@ -93,10 +93,10 @@ TrajectoryState trajectoryState(const traj_t& multiTraj, /// different volumes) template VolumeTrajectoryStateContainer trajectoryState( - const traj_t& multiTraj, std::size_t entryIndex, + const traj_t& multiTraj, std::size_t tipIndex, const std::vector& volumeIds) { VolumeTrajectoryStateContainer trajStateContainer; - multiTraj.visitBackwards(entryIndex, [&](const auto& state) { + multiTraj.visitBackwards(tipIndex, [&](const auto& state) { // Get the volume Id of this surface const auto& geoID = state.referenceSurface().geometryId(); const auto& volume = geoID.volume(); @@ -111,7 +111,14 @@ VolumeTrajectoryStateContainer trajectoryState( trajState.nStates++; trajState.NDF += state.calibratedSize(); auto typeFlags = state.typeFlags(); - if (typeFlags.test(Acts::TrackStateFlag::MeasurementFlag)) { + if (typeFlags.test(Acts::TrackStateFlag::HoleFlag)) { + trajState.nHoles++; + } else if (typeFlags.test(Acts::TrackStateFlag::OutlierFlag)) { + trajState.nOutliers++; + trajState.outlierChi2.push_back(state.chi2()); + trajState.outlierVolume.push_back(volume); + trajState.outlierLayer.push_back(layer); + } else if (typeFlags.test(Acts::TrackStateFlag::MeasurementFlag)) { if (typeFlags.test(Acts::TrackStateFlag::SharedHitFlag)) { trajState.nSharedHits++; } @@ -120,13 +127,6 @@ VolumeTrajectoryStateContainer trajectoryState( trajState.measurementVolume.push_back(volume); trajState.measurementLayer.push_back(layer); trajState.chi2Sum += state.chi2(); - } else if (typeFlags.test(Acts::TrackStateFlag::OutlierFlag)) { - trajState.nOutliers++; - trajState.outlierChi2.push_back(state.chi2()); - trajState.outlierVolume.push_back(volume); - trajState.outlierLayer.push_back(layer); - } else if (typeFlags.test(Acts::TrackStateFlag::HoleFlag)) { - trajState.nHoles++; } return true; }); diff --git a/Core/include/Acts/EventData/TrackHelpers.hpp b/Core/include/Acts/EventData/TrackHelpers.hpp index d88d1104850..f51e5428af0 100644 --- a/Core/include/Acts/EventData/TrackHelpers.hpp +++ b/Core/include/Acts/EventData/TrackHelpers.hpp @@ -1,54 +1,27 @@ // This file is part of the Acts project. // -// Copyright (C) 2023 CERN for the benefit of the Acts project +// Copyright (C) 2023-2024 CERN for the benefit of the Acts project // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. + #pragma once -#include "Acts/EventData/MultiTrajectory.hpp" -#include "Acts/EventData/TrackContainer.hpp" +// This header is deprecated and will be removed in the future. +// Please use the new header instead: +#include "Acts/Utilities/TrackHelpers.hpp" namespace Acts { -/// Helper function to calculate a number of track level quantities and store -/// them on the track itself -/// @note The input track needs to be mutable, so @c ReadOnly=false -/// @tparam track_container_t the track container backend -/// @tparam track_state_container_t the track state container backend -/// @tparam holder_t the holder type for the track container backends -/// @param track A mutable track proxy to operate on -template class holder_t> -void calculateTrackQuantities( - Acts::TrackProxy - track) { - track.chi2() = 0; - track.nDoF() = 0; - - track.nHoles() = 0; - track.nMeasurements() = 0; - track.nSharedHits() = 0; - track.nOutliers() = 0; - - for (const auto& trackState : track.trackStatesReversed()) { - auto typeFlags = trackState.typeFlags(); - - if (typeFlags.test(Acts::TrackStateFlag::MeasurementFlag)) { - if (typeFlags.test(Acts::TrackStateFlag::SharedHitFlag)) { - track.nSharedHits()++; - } +// Funny header deprecation strategy +namespace { +[[deprecated( + "This header is deprecated - use " + "Acts/Utilities/TrackHelpers.hpp")]] constexpr static int + utilities_trackhelpers_hpp_is_deprecated = 0; +constexpr static int please_dont_use_utilities_trackhelpers_hpp = + utilities_trackhelpers_hpp_is_deprecated; +} // namespace - track.nMeasurements()++; - track.chi2() += trackState.chi2(); - track.nDoF() += trackState.calibratedSize(); - } else if (typeFlags.test(Acts::TrackStateFlag::OutlierFlag)) { - track.nOutliers()++; - } else if (typeFlags.test(Acts::TrackStateFlag::HoleFlag)) { - track.nHoles()++; - } - } -} } // namespace Acts diff --git a/Core/include/Acts/EventData/TrackStateType.hpp b/Core/include/Acts/EventData/TrackStateType.hpp index 5e43d6cb20c..3901eb7852c 100644 --- a/Core/include/Acts/EventData/TrackStateType.hpp +++ b/Core/include/Acts/EventData/TrackStateType.hpp @@ -1,6 +1,6 @@ // This file is part of the Acts project. // -// Copyright (C) 2023 CERN for the benefit of the Acts project +// Copyright (C) 2023-2024 CERN for the benefit of the Acts project // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -39,32 +39,35 @@ class TrackStateType { using raw_type = std::uint64_t; static constexpr std::size_t kRawBits = std::numeric_limits::type>::digits; + + // Delete default constructor + TrackStateType() = delete; + /// Constructor from a reference to the underlying value container /// @param raw the value container - TrackStateType(raw_type& raw) : m_raw{&raw} {} + TrackStateType(raw_type& raw) : m_raw{&raw} { assert(m_raw != nullptr); } - /// Assign the value from another set of flags - /// @param other the other set of flags to assign - /// @return this object - TrackStateType& operator=(const TrackStateType& other) { - assert(other.m_raw != nullptr); - *m_raw = *other.m_raw; - return *this; - } + // Delete copy constructor + TrackStateType(const TrackStateType&) = delete; + + // Delete move constructor + TrackStateType(TrackStateType&&) = delete; + + // Disable assignment + TrackStateType& operator=(const TrackStateType&) = delete; + + // Disable move assignment + TrackStateType& operator=(TrackStateType&&) = delete; /// Assign the value from another set of flags /// @param other the other set of flags to assign /// @return this object TrackStateType& operator=(const ConstTrackStateType& other); - /// Automatically convert to const track state type - operator ConstTrackStateType(); - /// Return if the bit at position @p pos is 1 /// @param pos the bit position /// @return if the bit at @p pos is one or not bool test(std::size_t pos) const { - assert(m_raw != nullptr); std::bitset bs{*m_raw}; return bs.test(pos); } @@ -73,7 +76,6 @@ class TrackStateType { /// @param pos the position of the bit to change /// @param value the value to change the bit to void set(std::size_t pos, bool value = true) { - assert(m_raw != nullptr); std::bitset bs{*m_raw}; bs.set(pos, value); *m_raw = bs.to_ullong(); @@ -83,8 +85,7 @@ class TrackStateType { /// @param pos the position of the bit to change void reset(std::size_t pos) { set(pos, false); } - friend std::ostream& operator<<(std::ostream& os, TrackStateType t) { - assert(t.m_raw != nullptr); + friend std::ostream& operator<<(std::ostream& os, const TrackStateType& t) { std::bitset bs{*t.m_raw}; std::bitset trunc; for (std::size_t i = 0; i < TrackStateFlag::NumTrackStateFlags; i++) { @@ -107,21 +108,37 @@ class ConstTrackStateType { static constexpr std::size_t kRawBits = std::numeric_limits::type>::digits; + // Delete default constructor + ConstTrackStateType() = delete; + /// Constructor from a reference to the underlying value container /// @param raw the value container - ConstTrackStateType(const raw_type& raw) : m_raw{&raw} {} + ConstTrackStateType(const raw_type& raw) : m_raw{&raw} { + assert(m_raw != nullptr); + } + + // Disable copy constructor + ConstTrackStateType(const ConstTrackStateType& other) = delete; + + // Delete move constructor + ConstTrackStateType(ConstTrackStateType&& other) = delete; + + // Disable assignment + ConstTrackStateType& operator=(const ConstTrackStateType&) = delete; + + // Disable move assignment + ConstTrackStateType& operator=(ConstTrackStateType&&) = delete; /// Return if the bit at position @p pos is 1 /// @param pos the bit position /// @return if the bit at @p pos is one or not bool test(std::size_t pos) const { - assert(m_raw != nullptr); std::bitset bs{*m_raw}; return bs.test(pos); } - friend std::ostream& operator<<(std::ostream& os, ConstTrackStateType t) { - assert(t.m_raw != nullptr); + friend std::ostream& operator<<(std::ostream& os, + const ConstTrackStateType& t) { std::bitset bs{*t.m_raw}; std::bitset trunc; for (std::size_t i = 0; i < TrackStateFlag::NumTrackStateFlags; i++) { @@ -139,12 +156,8 @@ class ConstTrackStateType { inline TrackStateType& TrackStateType::operator=( const ConstTrackStateType& other) { - assert(other.m_raw != nullptr); *m_raw = *other.m_raw; return *this; } -inline TrackStateType::operator ConstTrackStateType() { - return {*m_raw}; -} } // namespace Acts diff --git a/Core/include/Acts/EventData/detail/TestSourceLink.hpp b/Core/include/Acts/EventData/detail/TestSourceLink.hpp index 421180eb279..d215867036c 100644 --- a/Core/include/Acts/EventData/detail/TestSourceLink.hpp +++ b/Core/include/Acts/EventData/detail/TestSourceLink.hpp @@ -10,6 +10,7 @@ #include "Acts/Definitions/Algebra.hpp" #include "Acts/Definitions/TrackParametrization.hpp" +#include "Acts/Detector/Detector.hpp" #include "Acts/EventData/MultiTrajectory.hpp" #include "Acts/EventData/SourceLink.hpp" #include "Acts/Geometry/GeometryContext.hpp" @@ -27,6 +28,8 @@ namespace Acts::detail::Test { +struct TestSourceLinkSurfaceAccessor; + /// A minimal source link implementation for testing. /// /// Instead of storing a reference to a measurement or raw data, the measurement @@ -35,6 +38,8 @@ namespace Acts::detail::Test { /// identifier is stored that can be used to store additional information. How /// this is interpreted depends on the specific tests. struct TestSourceLink final { + using SurfaceAccessor = TestSourceLinkSurfaceAccessor; + GeometryIdentifier m_geometryId{}; std::size_t sourceId = 0u; // use eBoundSize to indicate unused indices @@ -87,17 +92,30 @@ struct TestSourceLink final { return os; } constexpr std::size_t index() const { return sourceId; } +}; - struct SurfaceAccessor { - const Acts::TrackingGeometry& trackingGeometry; +struct TestSourceLinkSurfaceAccessor { + const TrackingGeometry& geometry; - const Acts::Surface* operator()(const Acts::SourceLink& sourceLink) const { - const auto& testSourceLink = sourceLink.get(); - return trackingGeometry.findSurface(testSourceLink.m_geometryId); - } - }; + const Acts::Surface* operator()(const Acts::SourceLink& sourceLink) const { + const auto& testSourceLink = sourceLink.get(); + return geometry.findSurface(testSourceLink.m_geometryId); + } }; +namespace Experimental { + +struct TestSourceLinkSurfaceAccessor { + const Acts::Experimental::Detector& geometry; + + const Acts::Surface* operator()(const Acts::SourceLink& sourceLink) const { + const auto& testSourceLink = sourceLink.get(); + return geometry.findSurface(testSourceLink.m_geometryId); + } +}; + +} // namespace Experimental + inline std::ostream& operator<<(std::ostream& os, const TestSourceLink& sourceLink) { return sourceLink.print(os); diff --git a/Core/include/Acts/Geometry/CuboidVolumeBuilder.hpp b/Core/include/Acts/Geometry/CuboidVolumeBuilder.hpp index 2f9ba2946cd..6ebccf761d7 100644 --- a/Core/include/Acts/Geometry/CuboidVolumeBuilder.hpp +++ b/Core/include/Acts/Geometry/CuboidVolumeBuilder.hpp @@ -81,6 +81,8 @@ class CuboidVolumeBuilder : public ITrackingVolumeBuilder { std::array envelopeZ{0, 0}; // An optional rotation for this std::optional rotation{std::nullopt}; + // Dimension for the binning + Acts::BinningValue binningDimension = Acts::BinningValue::binX; }; /// @brief This struct stores the data for the construction of a cuboid @@ -102,6 +104,8 @@ class CuboidVolumeBuilder : public ITrackingVolumeBuilder { std::string name = "Volume"; // Material std::shared_ptr volumeMaterial = nullptr; + // Dimension for the binning + Acts::BinningValue binningDimension = Acts::BinningValue::binX; }; /// @brief This struct stores the configuration of the tracking geometry diff --git a/Core/include/Acts/Navigation/InternalNavigation.hpp b/Core/include/Acts/Navigation/InternalNavigation.hpp index 4301676e1c5..75f8ec87ea9 100644 --- a/Core/include/Acts/Navigation/InternalNavigation.hpp +++ b/Core/include/Acts/Navigation/InternalNavigation.hpp @@ -25,49 +25,51 @@ namespace Acts::Experimental { struct AllPortalsNavigation : public IInternalNavigation { - /// A ordered portal provider + /// Fills all portals into the navigation state /// /// @param gctx is the Geometry context of this call /// @param nState is the navigation state to be updated /// - /// @note that the intersections are ordered, such that the - /// smallest intersection pathlength >= overstep tolerance is the lowest - /// - /// @return an ordered list of portal candidates - inline void update(const GeometryContext& gctx, - NavigationState& nState) const { + /// @note no intersection ordering is done at this stage + inline void fill([[maybe_unused]] const GeometryContext& gctx, + NavigationState& nState) const { if (nState.currentVolume == nullptr) { throw std::runtime_error( "AllPortalsNavigation: no detector volume set to navigation state."); } - // Retrieval necessary - if (nState.surfaceCandidates.empty()) { - // Fill internal portals if existing - for (const auto v : nState.currentVolume->volumes()) { - const auto& iPortals = v->portals(); - PortalsFiller::fill(nState, iPortals); - } - // Filling the new portal candidates - const auto& portals = nState.currentVolume->portals(); - PortalsFiller::fill(nState, portals); + // Fill internal portals if existing + for (const auto v : nState.currentVolume->volumes()) { + const auto& iPortals = v->portals(); + PortalsFiller::fill(nState, iPortals); } - // Sort and update - updateCandidates(gctx, nState); + // Filling the new portal candidates + const auto& portals = nState.currentVolume->portals(); + PortalsFiller::fill(nState, portals); } -}; -struct AllPortalsAndSurfacesNavigation : public IInternalNavigation { - /// An ordered list of portals and surfaces provider + /// A ordered portal provider - update method that calls fill and initialize /// /// @param gctx is the Geometry context of this call /// @param nState is the navigation state to be updated /// /// @note that the intersections are ordered, such that the /// smallest intersection pathlength >= overstep tolerance is the lowest - /// - /// @return an ordered list of portal and surface candidates inline void update(const GeometryContext& gctx, NavigationState& nState) const { + fill(gctx, nState); + intitializeCandidates(gctx, nState); + } +}; + +struct AllPortalsAndSurfacesNavigation : public IInternalNavigation { + /// Fills all portals and surfaces into the navigation state + /// + /// @param gctx is the Geometry context of this call + /// @param nState is the navigation state to be updated + /// + /// @note no intersection ordering is done at this stage + inline void fill([[maybe_unused]] const GeometryContext& gctx, + NavigationState& nState) const { if (nState.currentDetector == nullptr) { throw std::runtime_error( "AllPortalsAndSurfacesNavigation: no detector volume set to " @@ -75,20 +77,31 @@ struct AllPortalsAndSurfacesNavigation : public IInternalNavigation { "state."); } // A volume switch has happened, update list of portals & surfaces - if (nState.surfaceCandidates.empty()) { - // Fill internal portals if existing - for (const auto v : nState.currentVolume->volumes()) { - const auto& iPortals = v->portals(); - PortalsFiller::fill(nState, iPortals); - } - // Assign the new volume - const auto& portals = nState.currentVolume->portals(); - const auto& surfaces = nState.currentVolume->surfaces(); - PortalsFiller::fill(nState, portals); - SurfacesFiller::fill(nState, surfaces); + for (const auto v : nState.currentVolume->volumes()) { + const auto& iPortals = v->portals(); + PortalsFiller::fill(nState, iPortals); } - // Update internal candidates - updateCandidates(gctx, nState); + // Assign the new volume + const auto& portals = nState.currentVolume->portals(); + const auto& surfaces = nState.currentVolume->surfaces(); + PortalsFiller::fill(nState, portals); + SurfacesFiller::fill(nState, surfaces); + } + + /// A ordered list of portals and surfaces provider + /// - update method that calls fill and initialize + /// + /// @param gctx is the Geometry context of this call + /// @param nState is the navigation state to be updated + /// + /// @note that the intersections are ordered, such that the + /// smallest intersection pathlength >= overstep tolerance is the lowest + /// + /// @return an ordered list of portal and surface candidates + inline void update(const GeometryContext& gctx, + NavigationState& nState) const { + fill(gctx, nState); + intitializeCandidates(gctx, nState); } }; @@ -124,15 +137,32 @@ struct AdditionalSurfacesNavigation : public IInternalNavigation { /// The volumes held by this collection std::vector surfaces = {}; - /// Extract the sub volumes from the volume + /// Extract the additional surfaces from the this volume /// /// @param gctx the geometry contextfor this extraction call (ignored) /// @param nState is the navigation state /// - inline void update([[maybe_unused]] const GeometryContext& gctx, - NavigationState& nState) const { + /// @note no intersection ordering is done at this stage + inline void fill([[maybe_unused]] const GeometryContext& gctx, + NavigationState& nState) const { SurfacesFiller::fill(nState, surfaces); } + + /// Extract the additional surfaces from the this volume + /// - update method that calls fill and initialize + /// + /// @param gctx is the Geometry context of this call + /// @param nState is the navigation state to be updated + /// + /// @note that the intersections are ordered, such that the + /// smallest intersection pathlength >= overstep tolerance is the lowest + /// + /// @return an ordered list of portal and surface candidates + inline void update(const GeometryContext& gctx, + NavigationState& nState) const { + fill(gctx, nState); + intitializeCandidates(gctx, nState); + } }; /// @brief An indexed surface implementation access diff --git a/Core/include/Acts/Navigation/MultiLayerNavigation.hpp b/Core/include/Acts/Navigation/MultiLayerNavigation.hpp index a18e8c438cc..15042881147 100644 --- a/Core/include/Acts/Navigation/MultiLayerNavigation.hpp +++ b/Core/include/Acts/Navigation/MultiLayerNavigation.hpp @@ -48,10 +48,13 @@ class MultiLayerNavigation : public IInternalNavigation { MultiLayerNavigation() = delete; - /// Update the navigation state + /// Fill the navigation state + /// + /// @note no initialization is done here (sorting and update) + /// /// @param gctx is the geometry context /// @param nState is the navigation state - void update(const GeometryContext& gctx, NavigationState& nState) const { + void fill(const GeometryContext& gctx, NavigationState& nState) const { // get the local position and direction auto lposition = transform * nState.position; auto ldirection = transform.linear() * nState.direction; @@ -72,8 +75,16 @@ class MultiLayerNavigation : public IInternalNavigation { resolveDuplicates(gctx, surfCandidates); SurfacesFiller::fill(nState, surfCandidates); - - updateCandidates(gctx, nState); + } + /// Fill the update the navigation state with candidates + /// + /// @note initialization is done here (sorting and update) + /// + /// @param gctx is the geometry context + /// @param nState is the navigation state + void update(const GeometryContext& gctx, NavigationState& nState) const { + fill(gctx, nState); + intitializeCandidates(gctx, nState); } /// Cast into a lookup position diff --git a/Core/include/Acts/Navigation/NavigationStateUpdaters.hpp b/Core/include/Acts/Navigation/NavigationStateUpdaters.hpp index 8bd00d6a406..3903d1e123c 100644 --- a/Core/include/Acts/Navigation/NavigationStateUpdaters.hpp +++ b/Core/include/Acts/Navigation/NavigationStateUpdaters.hpp @@ -34,36 +34,45 @@ namespace Acts::Experimental { /// @param nState [in,out] is the navigation state to be updated /// /// @todo for surfaces skip the non-reached ones, while keep for portals -inline void updateCandidates(const GeometryContext& gctx, - NavigationState& nState) { +inline void intitializeCandidates(const GeometryContext& gctx, + NavigationState& nState) { const auto& position = nState.position; const auto& direction = nState.direction; - NavigationState::SurfaceCandidates nextSurfaceCandidates; + nState.surfaceCandidateIndex = 0; - for (NavigationState::SurfaceCandidate c : nState.surfaceCandidates) { - // Get the surface representation: either native surface of portal - const Surface& sRep = - c.surface != nullptr ? *c.surface : c.portal->surface(); + NavigationState::SurfaceCandidates confirmedCandidates; + confirmedCandidates.reserve(nState.surfaceCandidates.size()); + for (auto& sc : nState.surfaceCandidates) { + // Get the surface representation: either native surface of portal + const Surface& surface = + sc.surface != nullptr ? *sc.surface : sc.portal->surface(); // Only allow overstepping if it's not a portal ActsScalar overstepTolerance = - c.portal != nullptr ? s_onSurfaceTolerance : nState.overstepTolerance; - - // Get the intersection @todo make a templated intersector - // TODO surface tolerance - auto sIntersection = sRep.intersect( - gctx, position, direction, c.boundaryTolerance, s_onSurfaceTolerance); + sc.portal != nullptr ? s_onSurfaceTolerance : nState.overstepTolerance; + // Boundary tolerance is forced to 0 for portals + BoundaryTolerance boundaryTolerance = + sc.portal != nullptr ? BoundaryTolerance::None() : sc.boundaryTolerance; + // Check the surface intersection + auto sIntersection = surface.intersect( + gctx, position, direction, boundaryTolerance, s_onSurfaceTolerance); for (auto& si : sIntersection.split()) { - c.objectIntersection = si; - if (c.objectIntersection.isValid() && - c.objectIntersection.pathLength() > overstepTolerance) { - nextSurfaceCandidates.emplace_back(c); + if (si.isValid() && si.pathLength() > overstepTolerance) { + confirmedCandidates.emplace_back(NavigationState::SurfaceCandidate{ + si, sc.surface, sc.portal, boundaryTolerance}); } } } - nState.surfaceCandidates = std::move(nextSurfaceCandidates); + std::sort(confirmedCandidates.begin(), confirmedCandidates.end(), + [&](const auto& a, const auto& b) { + return a.objectIntersection.pathLength() < + b.objectIntersection.pathLength(); + }); + + nState.surfaceCandidates = std::move(confirmedCandidates); + nState.surfaceCandidateIndex = 0; } /// @brief This sets a single object, e.g. single surface or single volume @@ -84,15 +93,32 @@ class SingleObjectNavigation : public navigation_type { } } - /// @brief updates the navigation state with a single object that is filled in + /// @brief Fill the navigation state with a single object that it holds /// /// @param gctx is the Geometry context of this call /// @param nState the navigation state to which the surfaces are attached /// /// @note this is attaching objects without intersecting nor checking + void fill([[maybe_unused]] const GeometryContext& gctx, + NavigationState& nState) const { + filler_type::fill(nState, m_object); + } + + /// @brief Update the navigation state with a single object that it holds + /// + /// @note it calls fill and then initializes the candidates (including intersection) + /// + /// @param gctx is the Geometry context of this call + /// @param nState the navigation state to which the surfaces are attached + /// + /// @note this is attaching objects and will perform a check void update([[maybe_unused]] const GeometryContext& gctx, NavigationState& nState) const { - filler_type::fill(nState, m_object); + fill(gctx, nState); + // If the delegate type is of type IInternalNavigation + if constexpr (std::is_base_of_v) { + intitializeCandidates(gctx, nState); + } } /// Const Access to the object @@ -103,7 +129,7 @@ class SingleObjectNavigation : public navigation_type { const object_type* m_object = nullptr; }; -/// @brief This uses state less extractor and fillers to manipulate +/// @brief This uses stateless extractor and fillers to manipulate /// the navigation state /// /// @tparam navigation_type distinguishes between internal and external navigation @@ -114,17 +140,34 @@ template class StaticAccessNavigation : public navigation_type { public: - /// @brief updates the navigation state with a single object that is filled in + /// @brief fills the navigation state with extracted objects /// /// @param gctx is the Geometry context of this call /// @param nState the navigation state to which the surfaces are attached /// /// @note this is attaching objects without intersecting nor checking - void update([[maybe_unused]] const GeometryContext& gctx, - NavigationState& nState) const { + void fill([[maybe_unused]] const GeometryContext& gctx, + NavigationState& nState) const { auto extracted = extractor_type::extract(gctx, nState); filler_type::fill(nState, extracted); } + + /// @brief Update the navigation state with extracted objects + /// + /// @note it calls fill and then initializes the candidates (including intersection) + /// + /// @param gctx is the Geometry context of this call + /// @param nState the navigation state to which the surfaces are attached + /// + /// @note this will perform the intersection test + void update([[maybe_unused]] const GeometryContext& gctx, + NavigationState& nState) const { + fill(gctx, nState); + // If the delegate type is of type IInternalNavigation + if constexpr (std::is_base_of_v) { + intitializeCandidates(gctx, nState); + } + } }; /// @brief This is an index grid based navigation state updator, it uses @@ -139,7 +182,6 @@ class StaticAccessNavigation : public navigation_type { /// @tparam grid_t is the type of the grid /// @tparam extractor_type is the helper to extract the object /// @tparam filler_type is the helper to fill the object into the nState -/// template class IndexedGridNavigation : public navigation_type { @@ -170,32 +212,43 @@ class IndexedGridNavigation : public navigation_type { IndexedGridNavigation() = delete; - /// @brief updates the navigation state with objects from the grid according - /// to the filling type AFTER applying `p3loc = transform * p3` + /// @brief fill the navigation state with objects from the grid entries + /// AFTER applying `p3loc = transform * p3` and casting to subsbpace /// /// @param gctx is the Geometry context of this call /// @param nState the navigation state to which the surfaces are attached /// - /// @note this is attaching objects without intersecting nor checking - void update(const GeometryContext& gctx, NavigationState& nState) const { - // Extract the index grid entry + /// @note this will only fill the state without intersecting + void fill(const GeometryContext& gctx, NavigationState& nState) const { + // Extract the index grid entry a const auto& entry = grid.atPosition(GridAccessHelpers::castPosition( transform * nState.position, casts)); auto extracted = extractor.extract(gctx, nState, entry); filler_type::fill(nState, extracted); + } + /// @brief Update the navigation state with objects from the entries + /// AFTER applying `p3loc = transform * p3` and casting to subsbpace + /// + /// @note it calls fill and then initializes the candidates (including intersection) + /// + /// @param gctx is the Geometry context of this call + /// @param nState the navigation state to which the surfaces are attached + /// + /// @note this will perform the intersection test for internal navigation paths + void update(const GeometryContext& gctx, NavigationState& nState) const { + fill(gctx, nState); // If the delegate type is of type IInternalNavigation if constexpr (std::is_base_of_v) { - // Update the candidates - updateCandidates(gctx, nState); + // Update the candidates: initial update + intitializeCandidates(gctx, nState); } } }; -/// This is a chained extractor/filler implementation -/// Since there is no control whether it is a static or -/// payload extractor, these have to be provided by a tuple +/// This is a chained updated, which can either performed a chained filling, +/// or a chaine update (which included intersection test) /// /// @tparam navigation_type distinguishes between internal and external navigation /// @tparam updators_t the updators that will be called in sequence @@ -213,16 +266,30 @@ class ChainedNavigation : public navigation_type { ChainedNavigation(const std::tuple&& upts) : updators(std::move(upts)) {} - /// A combined navigation state updator w/o intersection specifics + /// A combined navigation state updated to fill the candidates from + /// a sequence of pre-defined updators + /// + /// @param gctx is the Geometry context of this call + /// @param nState the navigation state to which the objects are attached + /// + void fill(const GeometryContext& gctx, NavigationState& nState) const { + // Unfold the tuple and add the attachers + std::apply([&](auto&&... updator) { ((updator.fill(gctx, nState)), ...); }, + updators); + } + + /// A combined navigation state to fill & update the candidatesthe candidates /// /// @param gctx is the Geometry context of this call /// @param nState the navigation state to which the objects are attached /// + /// @note It will call the chained filling and then perform a single update on + /// the candidates to avoid copying and multiple intersection tests void update(const GeometryContext& gctx, NavigationState& nState) const { // Unfold the tuple and add the attachers - std::apply( - [&](auto&&... updator) { ((updator.update(gctx, nState)), ...); }, - updators); + fill(gctx, nState); + // Update the candidates: initial update + intitializeCandidates(gctx, nState); } }; diff --git a/Core/include/Acts/Propagator/DirectNavigator.hpp b/Core/include/Acts/Propagator/DirectNavigator.hpp index d389c36e7e0..42af0ee7f57 100644 --- a/Core/include/Acts/Propagator/DirectNavigator.hpp +++ b/Core/include/Acts/Propagator/DirectNavigator.hpp @@ -134,7 +134,11 @@ class DirectNavigator { template void initialize(propagator_state_t& state, const stepper_t& /*stepper*/) const { - ACTS_VERBOSE("initialize"); + ACTS_VERBOSE("Initialize. Surface sequence for navigation:"); + for (auto surface : state.navigation.options.surfaces) { + ACTS_VERBOSE(surface->geometryId() + << " - " << surface->center(state.geoContext).transpose()); + } // We set the current surface to the start surface state.navigation.currentSurface = state.navigation.options.startSurface; diff --git a/Core/include/Acts/Propagator/MultiEigenStepperLoop.ipp b/Core/include/Acts/Propagator/MultiEigenStepperLoop.ipp index 5f5a49e7833..fd090814bd0 100644 --- a/Core/include/Acts/Propagator/MultiEigenStepperLoop.ipp +++ b/Core/include/Acts/Propagator/MultiEigenStepperLoop.ipp @@ -80,7 +80,7 @@ auto MultiEigenStepperLoop::curvilinearState(State& state, cmps.emplace_back(state.components[i].weight, cp.fourPosition(state.geoContext), cp.direction(), - (cp.charge() / cp.absoluteMomentum()), + cp.qOverP(), cp.covariance().value_or(BoundSquareMatrix::Zero())); accumulatedPathLength += state.components[i].weight * pl; } diff --git a/Core/include/Acts/Propagator/Navigator.hpp b/Core/include/Acts/Propagator/Navigator.hpp index 9d8efc93428..4e33c6b1bc0 100644 --- a/Core/include/Acts/Propagator/Navigator.hpp +++ b/Core/include/Acts/Propagator/Navigator.hpp @@ -177,13 +177,8 @@ class Navigator { /// Navigation state: the target surface const Surface* targetSurface = nullptr; - /// Indicator for start layer treatment - bool startLayerResolved = false; /// Indicator if the target is reached bool targetReached = false; - /// Indicator that the last VolumeHierarchy surface was reached - /// skip the next layer targeting to the next boundary/volume - bool lastHierarchySurfaceReached = false; /// Navigation state : a break has been detected bool navigationBreak = false; // The navigation stage (@todo: integrate break, target) @@ -269,7 +264,7 @@ class Navigator { ACTS_VERBOSE(volInfo(state) << "Initialization."); // Set the world volume if it is not set - if (!state.navigation.worldVolume) { + if (state.navigation.worldVolume == nullptr) { state.navigation.worldVolume = m_cfg.trackingGeometry->highestTrackingVolume(); } @@ -289,7 +284,7 @@ class Navigator { // - short-cut through object association, saves navigation in the // - geometry and volume tree search for the lowest volume if (state.navigation.startSurface != nullptr && - state.navigation.startSurface->associatedLayer()) { + state.navigation.startSurface->associatedLayer() != nullptr) { ACTS_VERBOSE( volInfo(state) << "Fast start initialization through association from Surface."); @@ -326,10 +321,26 @@ class Navigator { ACTS_VERBOSE(volInfo(state) << "Start volume resolved."); } } + // Set the start volume as current volume state.navigation.currentVolume = state.navigation.startVolume; // Set the start layer as current layer state.navigation.currentLayer = state.navigation.startLayer; + + if (state.navigation.startLayer != nullptr) { + ACTS_VERBOSE(volInfo(state) << "Start layer to be resolved."); + // We provide the layer to the resolve surface method in this case + bool startResolved = resolveSurfaces(state, stepper); + if (!startResolved && + state.navigation.startLayer == state.navigation.targetLayer) { + ACTS_VERBOSE(volInfo(state) + << "Start is target layer and we have no surface " + "candidates. Nothing left to do."); + // set the navigation break + state.navigation.navigationBreak = true; + stepper.releaseStepSize(state.stepping, ConstrainedStep::actor); + } + } } /// @brief Navigator pre step call @@ -471,7 +482,6 @@ class Navigator { state.navigation.navSurfaceIndex = state.navigation.navSurfaces.size(); state.navigation.navLayers.clear(); state.navigation.navLayerIndex = state.navigation.navLayers.size(); - state.navigation.lastHierarchySurfaceReached = false; // Update volume information // get the attached volume information const BoundarySurface* boundary = state.navigation.navBoundary().second; @@ -597,23 +607,6 @@ class Navigator { if (state.navigation.navigationBreak) { return false; } - // Make sure resolve Surfaces is called on the start layer - if (state.navigation.startLayer != nullptr && - !state.navigation.startLayerResolved) { - ACTS_VERBOSE(volInfo(state) << "Start layer to be resolved."); - // We provide the layer to the resolve surface method in this case - state.navigation.startLayerResolved = true; - bool startResolved = resolveSurfaces(state, stepper); - if (!startResolved && - state.navigation.startLayer == state.navigation.targetLayer) { - ACTS_VERBOSE(volInfo(state) - << "Start is target layer, nothing left to do."); - // set the navigation break - state.navigation.navigationBreak = true; - stepper.releaseStepSize(state.stepping, ConstrainedStep::actor); - } - return startResolved; - } // The call that we are on a layer and have not yet resolved the surfaces // No surfaces, do not return to stepper @@ -624,6 +617,7 @@ class Navigator { << "No surfaces present, target at layer first."); return false; } + auto layerID = state.navigation.navSurface().object()->geometryId().layer(); std::pair externalSurfaceRange = @@ -681,12 +675,11 @@ class Navigator { } else { ACTS_VERBOSE(volInfo(state) << "Last surface on layer reached, and no layer."); - // first clear the surface cache - state.navigation.lastHierarchySurfaceReached = true; state.navigation.navigationBreak = (state.navigation.currentVolume == state.navigation.targetVolume); } } + // Do not return to the propagator return false; } @@ -713,8 +706,7 @@ class Navigator { bool targetLayers(propagator_state_t& state, const stepper_t& stepper) const { using namespace UnitLiterals; - if (state.navigation.navigationBreak || - state.navigation.lastHierarchySurfaceReached) { + if (state.navigation.navigationBreak) { return false; } @@ -728,6 +720,7 @@ class Navigator { return true; } } + // loop over the available navigation layer candidates while (state.navigation.navLayerIndex != state.navigation.navLayers.size()) { @@ -1182,7 +1175,7 @@ class Navigator { template bool inactive(propagator_state_t& state, const stepper_t& stepper) const { // Void behavior in case no tracking geometry is present - if (!m_cfg.trackingGeometry) { + if (m_cfg.trackingGeometry == nullptr) { return true; } // turn the navigator into void when you are instructed to do nothing diff --git a/Core/include/Acts/Propagator/detail/PointwiseMaterialInteraction.hpp b/Core/include/Acts/Propagator/detail/PointwiseMaterialInteraction.hpp index bd68a1576dd..e3c32247b64 100644 --- a/Core/include/Acts/Propagator/detail/PointwiseMaterialInteraction.hpp +++ b/Core/include/Acts/Propagator/detail/PointwiseMaterialInteraction.hpp @@ -142,6 +142,7 @@ struct PointwiseMaterialInteraction { template void updateState(propagator_state_t& state, const stepper_t& stepper, NoiseUpdateMode updateMode = addNoise) { + const auto& particleHypothesis = stepper.particleHypothesis(state.stepping); // in forward(backward) propagation, energy decreases(increases) and // variances increase(decrease) const auto nextE = std::hypot(mass, momentum) - Eloss * navDir; @@ -152,9 +153,10 @@ struct PointwiseMaterialInteraction { // TODO 10 MeV might be quite low and we should make this configurable static constexpr double minP = 10 * Acts::UnitConstants::MeV; nextP = std::max(minP, nextP); + const double nextQOverP = + std::copysign(particleHypothesis.qOverP(nextP, absQ), qOverP); // update track parameters and covariance - stepper.update(state.stepping, pos, dir, - std::copysign(absQ / nextP, qOverP), time); + stepper.update(state.stepping, pos, dir, nextQOverP, time); state.stepping.cov(eBoundPhi, eBoundPhi) = updateVariance( state.stepping.cov(eBoundPhi, eBoundPhi), variancePhi, updateMode); state.stepping.cov(eBoundTheta, eBoundTheta) = diff --git a/Core/include/Acts/TrackFinding/CombinatorialKalmanFilter.hpp b/Core/include/Acts/TrackFinding/CombinatorialKalmanFilter.hpp index 974a534ae0e..21fd84c536b 100644 --- a/Core/include/Acts/TrackFinding/CombinatorialKalmanFilter.hpp +++ b/Core/include/Acts/TrackFinding/CombinatorialKalmanFilter.hpp @@ -18,9 +18,9 @@ #include "Acts/EventData/MultiTrajectoryHelpers.hpp" #include "Acts/EventData/ProxyAccessor.hpp" #include "Acts/EventData/TrackContainer.hpp" -#include "Acts/EventData/TrackHelpers.hpp" #include "Acts/EventData/TrackParameters.hpp" #include "Acts/EventData/TrackStatePropMask.hpp" +#include "Acts/EventData/Types.hpp" #include "Acts/Geometry/GeometryContext.hpp" #include "Acts/MagneticField/MagneticFieldContext.hpp" #include "Acts/Material/MaterialSlab.hpp" @@ -39,6 +39,7 @@ #include "Acts/Utilities/HashedString.hpp" #include "Acts/Utilities/Logger.hpp" #include "Acts/Utilities/Result.hpp" +#include "Acts/Utilities/TrackHelpers.hpp" #include "Acts/Utilities/Zip.hpp" #include @@ -64,6 +65,8 @@ struct CombinatorialKalmanFilterExtensions { using traj_t = typename track_container_t::TrackStateContainerBackend; using candidate_container_t = typename std::vector; + using TrackProxy = typename track_container_t::TrackProxy; + using TrackStateProxy = typename track_container_t::TrackStateProxy; using BranchStopperResult = CombinatorialKalmanFilterBranchStopperResult; @@ -73,9 +76,8 @@ struct CombinatorialKalmanFilterExtensions { Delegate>( candidate_container_t& trackStates, bool&, const Logger&)>; - using BranchStopper = Delegate; + using BranchStopper = + Delegate; /// The Calibrator is a dedicated calibration algorithm that allows to /// calibrate measurements using track information, this could be e.g. sagging @@ -96,23 +98,17 @@ struct CombinatorialKalmanFilterExtensions { private: /// Default measurement selector which will return all measurements /// @param candidates Measurement track state candidates - static Result< - std::pair::iterator, - typename std::vector< - typename track_container_t::TrackStateProxy>::iterator>> - voidMeasurementSelector( - typename std::vector& - candidates, - bool& /*isOutlier*/, const Logger& /*logger*/) { + static Result::iterator, + typename std::vector::iterator>> + voidMeasurementSelector(typename std::vector& candidates, + bool& /*isOutlier*/, const Logger& /*logger*/) { return std::pair{candidates.begin(), candidates.end()}; }; /// Default branch stopper which will never stop /// @return false static BranchStopperResult voidBranchStopper( - const typename track_container_t::TrackProxy& /*track*/, - const typename track_container_t::TrackStateProxy& /*trackState*/) { + const TrackProxy& /*track*/, const TrackStateProxy& /*trackState*/) { return BranchStopperResult::Continue; } }; @@ -127,9 +123,16 @@ using SourceLinkAccessorDelegate = /// expected max number of track states that are expected to be added by /// stateCandidateCreator /// @note if the number of states exceeds this number dynamic memory allocation will occur. -//. the number is chosen to yield a container size of 64 bytes. +/// the number is chosen to yield a container size of 64 bytes. static constexpr std::size_t s_maxBranchesPerSurface = 10; +namespace CkfTypes { + +template +using BranchVector = boost::container::small_vector; + +} // namespace CkfTypes + /// Combined options for the combinatorial Kalman filter. /// /// @tparam source_link_iterator_t Type of the source link iterator @@ -139,6 +142,10 @@ struct CombinatorialKalmanFilterOptions { using SourceLinkIterator = source_link_iterator_t; using SourceLinkAccessor = SourceLinkAccessorDelegate; + using TrackStateContainerBackend = + typename track_container_t::TrackStateContainerBackend; + using TrackStateProxy = typename track_container_t::TrackStateProxy; + /// PropagatorOptions with context /// /// @param gctx The geometry context for this track finding/fitting @@ -192,6 +199,7 @@ struct CombinatorialKalmanFilterOptions { using BoundState = std::tuple; /// Delegate definition to create track states for selected measurements + /// /// @note expected to iterator over the given sourcelink range, /// select measurements, and create track states for /// which new tips are to be created, more over the outlier @@ -209,19 +217,14 @@ struct CombinatorialKalmanFilterOptions { /// @param trajectory the trajectory to which the new states are to be added /// @param logger a logger for messages using TrackStateCandidateCreator = - Delegate>( + Delegate>( const GeometryContext& geoContext, const CalibrationContext& calibrationContext, const Surface& surface, const BoundState& boundState, source_link_iterator_t slBegin, source_link_iterator_t slEnd, TrackIndexType prevTip, - typename track_container_t::TrackStateContainerBackend& - bufferTrajectory, - std::vector& - trackStateCandidates, - typename track_container_t::TrackStateContainerBackend& trajectory, - const Logger& logger)>; + TrackStateContainerBackend& bufferTrajectory, + std::vector& trackStateCandidates, + TrackStateContainerBackend& trajectory, const Logger& logger)>; /// The delegate to create new track states. TrackStateCandidateCreator trackStateCandidateCreator; @@ -235,24 +238,28 @@ struct CombinatorialKalmanFilterOptions { template struct CombinatorialKalmanFilterResult { + using TrackStateContainerBackend = + typename track_container_t::TrackStateContainerBackend; + using TrackProxy = typename track_container_t::TrackProxy; + using TrackStateProxy = typename track_container_t::TrackStateProxy; + /// The track container to store the found tracks track_container_t* tracks{nullptr}; /// Fitted states that the actor has handled. - typename track_container_t::TrackStateContainerBackend* trackStates{nullptr}; + TrackStateContainerBackend* trackStates{nullptr}; /// Indices into `tracks` which mark active branches - std::vector activeBranches; + std::vector activeBranches; /// Indices into `tracks` which mark active branches - std::vector collectedTracks; + std::vector collectedTracks; /// This is used internally to store candidate trackstates - std::shared_ptr - stateBuffer; + std::shared_ptr stateBuffer; /// Track state candidates buffer - std::vector trackStateCandidates; + std::vector trackStateCandidates; /// Indicator if track finding has been done bool finished = false; @@ -299,8 +306,10 @@ class CombinatorialKalmanFilter { private: using BoundState = std::tuple; - - using IndexType = typename track_container_t::TrackStateProxy::IndexType; + using TrackStateContainerBackend = + typename track_container_t::TrackStateContainerBackend; + using TrackProxy = typename track_container_t::TrackProxy; + using TrackStateProxy = typename track_container_t::TrackStateProxy; /// The propagator for the transport and material update propagator_t m_propagator; @@ -331,23 +340,20 @@ class CombinatorialKalmanFilter { /// @param trajectory the trajectory to which new track states for selected measurements will be added /// @param logger the logger for messages. template - Result> - createSourceLinkTrackStates( + Result> createSourceLinkTrackStates( const GeometryContext& gctx, const CalibrationContext& calibrationContext, [[maybe_unused]] const Surface& surface, const BoundState& boundState, source_link_iterator_t slBegin, source_link_iterator_t slEnd, - IndexType prevTip, - typename track_container_t::TrackStateContainerBackend& - bufferTrajectory, - std::vector& - trackStateCandidates, - typename track_container_t::TrackStateContainerBackend& trajectory, - const Logger& logger) const { - using ResultTrackStateList = Acts::Result< - boost::container::small_vector>; + TrackIndexType prevTip, TrackStateContainerBackend& bufferTrajectory, + std::vector& trackStateCandidates, + TrackStateContainerBackend& trajectory, const Logger& logger) const { + using PM = TrackStatePropMask; + + using ResultTrackStateList = + Acts::Result>; ResultTrackStateList resultTrackStateList{ - boost::container::small_vector()}; + CkfTypes::BranchVector()}; const auto& [boundParams, jacobian, pathLength] = boundState; trackStateCandidates.clear(); @@ -360,8 +366,6 @@ class CombinatorialKalmanFilter { bufferTrajectory.clear(); - using PM = TrackStatePropMask; - // Calibrate all the source links on the surface since the selection has // to be done based on calibrated measurement for (auto it = slBegin; it != slEnd; ++it) { @@ -370,7 +374,6 @@ class CombinatorialKalmanFilter { // prepare the track state PM mask = PM::Predicted | PM::Jacobian | PM::Calibrated; - if (it != slBegin) { // not the first TrackState, only need uncalibrated and calibrated mask = PM::Calibrated; @@ -397,7 +400,6 @@ class CombinatorialKalmanFilter { } ts.pathLength() = pathLength; - ts.setReferenceSurface(boundParams.referenceSurface().getSharedPtr()); // now calibrate the track state @@ -405,12 +407,10 @@ class CombinatorialKalmanFilter { trackStateCandidates.push_back(ts); } + bool isOutlier = false; - Result< - std::pair::iterator, - typename std::vector< - typename track_container_t::TrackStateProxy>::iterator>> + Result::iterator, + typename std::vector::iterator>> selectorResult = measurementSelector(trackStateCandidates, isOutlier, logger); if (!selectorResult.ok()) { @@ -420,7 +420,6 @@ class CombinatorialKalmanFilter { ResultTrackStateList::failure(selectorResult.error()); } else { auto selectedTrackStateRange = *selectorResult; - resultTrackStateList = processSelectedTrackStates( selectedTrackStateRange.first, selectedTrackStateRange.second, trajectory, isOutlier, logger); @@ -436,37 +435,31 @@ class CombinatorialKalmanFilter { /// @param trackStates the trajectory to which the new track states are added /// @param isOutlier true if the candidate(s) is(are) an outlier(s). /// @param logger the logger for messages - Result> - processSelectedTrackStates( - typename std::vector< - typename track_container_t::TrackStateProxy>::const_iterator begin, - typename std::vector< - typename track_container_t::TrackStateProxy>::const_iterator end, - typename track_container_t::TrackStateContainerBackend& trackStates, - bool isOutlier, const Logger& logger) const { - Acts::Result< - boost::container::small_vector> - resultTrackStateList{ - boost::container::small_vector()}; - boost::container::small_vector& - trackStateList = *resultTrackStateList; - trackStateList.reserve(end - begin); + Result> processSelectedTrackStates( + typename std::vector::const_iterator begin, + typename std::vector::const_iterator end, + TrackStateContainerBackend& trackStates, bool isOutlier, + const Logger& logger) const { using PM = TrackStatePropMask; - std::optional - firstTrackState{std::nullopt}; + using ResultTrackStateList = + Acts::Result>; + ResultTrackStateList resultTrackStateList{ + CkfTypes::BranchVector()}; + CkfTypes::BranchVector& trackStateList = + *resultTrackStateList; + trackStateList.reserve(end - begin); + + std::optional firstTrackState{std::nullopt}; for (auto it = begin; it != end; ++it) { auto& candidateTrackState = *it; PM mask = PM::Predicted | PM::Filtered | PM::Jacobian | PM::Calibrated; - if (it != begin) { // subsequent track states don't need storage for these as they will // be shared mask &= ~PM::Predicted & ~PM::Jacobian; } - if (isOutlier) { // outlier won't have separate filtered parameters mask &= ~PM::Filtered; @@ -491,19 +484,18 @@ class CombinatorialKalmanFilter { trackState.copyFrom(candidateTrackState, mask, false); auto typeFlags = trackState.typeFlags(); + typeFlags.set(TrackStateFlag::ParameterFlag); + typeFlags.set(TrackStateFlag::MeasurementFlag); if (trackState.referenceSurface().surfaceMaterial() != nullptr) { typeFlags.set(TrackStateFlag::MaterialFlag); } - typeFlags.set(TrackStateFlag::ParameterFlag); - if (isOutlier) { // propagate information that this is an outlier state ACTS_VERBOSE( "Creating outlier track state with tip = " << trackState.index()); - // Set the outlier flag needed by the next step to identify outlier - // states typeFlags.set(TrackStateFlag::OutlierFlag); } + trackStateList.push_back(trackState.index()); } return resultTrackStateList; @@ -526,6 +518,8 @@ class CombinatorialKalmanFilter { /// Broadcast the result_type using result_type = CombinatorialKalmanFilterResult; + using BranchStopperResult = CombinatorialKalmanFilterBranchStopperResult; + /// The target surface aborter SurfaceReached targetReached{std::numeric_limits::lowest()}; @@ -560,6 +554,8 @@ class CombinatorialKalmanFilter { ACTS_VERBOSE("CombinatorialKalmanFilter step"); + assert(!result.activeBranches.empty() && "No active branches"); + // Initialize path limit reached aborter if (result.pathLimitReached.internalLimit == std::numeric_limits::max()) { @@ -627,14 +623,12 @@ class CombinatorialKalmanFilter { } if (!result.activeBranches.empty()) { - // Record the active tip as trajectory entry indices and remove it - // from the list + // Record the active branch and remove it from the list storeLastActiveBranch(result); - // Remove the tip from list of active tips result.activeBranches.pop_back(); } - // If no more active tip, done with filtering; Otherwise, reset - // propagation state to track state at last tip of active tips + // If no more active branches, done with filtering; Otherwise, reset + // propagation state to track state at next active branch if (result.activeBranches.empty()) { ACTS_VERBOSE("Kalman filtering finds " << result.collectedTracks.size() << " tracks"); @@ -705,10 +699,12 @@ class CombinatorialKalmanFilter { Result filter(const Surface* surface, propagator_state_t& state, const stepper_t& stepper, const navigator_t& navigator, result_type& result) const { + using PM = TrackStatePropMask; + std::size_t nBranchesOnSurface = 0; - // Count the number of source links on the surface - auto [slBegin, slEnd] = m_sourcelinkAccessor(*surface); - if (slBegin != slEnd) { + + if (auto [slBegin, slEnd] = m_sourcelinkAccessor(*surface); + slBegin != slEnd) { // Screen output message ACTS_VERBOSE("Measurement surface " << surface->geometryId() << " detected."); @@ -730,51 +726,99 @@ class CombinatorialKalmanFilter { auto& [boundParams, jacobian, pathLength] = boundState; boundParams.covariance() = state.stepping.cov; - // Retrieve the previous tip and its state - // The states created on this surface will have the common previous tip auto currentBranch = result.activeBranches.back(); - IndexType prevTip = currentBranch.tipIndex(); + TrackIndexType prevTip = currentBranch.tipIndex(); // Create trackstates for all source links (will be filtered later) // Results are stored in result => no return value - - using TrackStatesResult = Acts::Result< - boost::container::small_vector>; - + using TrackStatesResult = + Acts::Result>; TrackStatesResult tsRes = trackStateCandidateCreator( state.geoContext, *calibrationContextPtr, *surface, boundState, slBegin, slEnd, prevTip, *result.stateBuffer, result.trackStateCandidates, *result.trackStates, logger()); - if (!tsRes.ok()) { ACTS_ERROR( "Processing of selected track states failed: " << tsRes.error()); return tsRes.error(); } - Result> procRes = - processNewTrackStates(state.geoContext, *tsRes, result); + const CkfTypes::BranchVector& newTrackStateList = + *tsRes; + + Result> procRes = + processNewTrackStates(state.geoContext, newTrackStateList, result); if (!procRes.ok()) { ACTS_ERROR("Processing of selected track states failed: " << procRes.error()); return procRes.error(); } - auto [nNewBranchesOnSurface, isOutlier] = *procRes; + auto [nNewBranchesOnSurface, nStoppedBranches] = *procRes; nBranchesOnSurface = nNewBranchesOnSurface; - if (nBranchesOnSurface > 0 && !isOutlier) { - // If there are measurement track states on this surface - ACTS_VERBOSE("Filtering step successful with " << nBranchesOnSurface - << " branches"); - // Update stepping state using filtered parameters of last track - // state on this surface - auto ts = result.activeBranches.back().outermostTrackState(); - stepper.update(state.stepping, - MultiTrajectoryHelpers::freeFiltered( - state.options.geoContext, ts), - ts.filtered(), ts.filteredCovariance(), *surface); - ACTS_VERBOSE("Stepping state is updated with filtered parameter:"); - ACTS_VERBOSE("-> " << ts.filtered().transpose() - << " of track state with tip = " << ts.index()); + if (nStoppedBranches >= newTrackStateList.size()) { + // All branches on the surface have been stopped. Reset happens at the + // end of the function + ACTS_VERBOSE("All branches on surface " << surface->geometryId() + << " have been stopped"); + } else if (nBranchesOnSurface > 0) { + if (currentBranch.outermostTrackState().typeFlags().test( + TrackStateFlag::OutlierFlag)) { + // We don't need to update the stepper given an outlier state + ACTS_VERBOSE("Outlier state detected on surface " + << surface->geometryId()); + } else { + // If there are measurement track states on this surface + ACTS_VERBOSE("Filtering step successful with " << nBranchesOnSurface + << " branches"); + // Update stepping state using filtered parameters of last track + // state on this surface + auto ts = result.activeBranches.back().outermostTrackState(); + stepper.update(state.stepping, + MultiTrajectoryHelpers::freeFiltered( + state.options.geoContext, ts), + ts.filtered(), ts.filteredCovariance(), *surface); + ACTS_VERBOSE("Stepping state is updated with filtered parameter:"); + ACTS_VERBOSE("-> " << ts.filtered().transpose() + << " of track state with tip = " << ts.index()); + } + } else { // nBranchesOnSurface == 0 + ACTS_VERBOSE("Detected hole after measurement selection on surface " + << surface->geometryId()); + + // After `processNewTrackStates` `currentBranch` is invalidated + currentBranch = result.activeBranches.back(); + prevTip = currentBranch.tipIndex(); + + // Setting the number of branches on the surface to 1 as the hole + // still counts as a branch + nBranchesOnSurface = 1; + + auto stateMask = PM::Predicted | PM::Jacobian; + + currentBranch.nHoles()++; + + // Add a hole track state to the multitrajectory + TrackIndexType currentTip = addNonSourcelinkState( + stateMask, boundState, result, true, prevTip); + auto nonSourcelinkState = + result.trackStates->getTrackState(currentTip); + currentBranch.tipIndex() = currentTip; + + BranchStopperResult branchStopperResult = + m_extensions.branchStopper(currentBranch, nonSourcelinkState); + + // Check the branch + if (branchStopperResult == BranchStopperResult::Continue) { + // Remembered the active branch and its state + } else { + // No branch on this surface + nBranchesOnSurface = 0; + if (branchStopperResult == BranchStopperResult::StopAndKeep) { + storeLastActiveBranch(result); + } + // Remove the branch from list + result.activeBranches.pop_back(); + } } // Update state and stepper with post material effects @@ -786,9 +830,8 @@ class CombinatorialKalmanFilter { // first, but could be changed later nBranchesOnSurface = 1; - // Retrieve the previous tip and its state auto currentBranch = result.activeBranches.back(); - IndexType prevTip = currentBranch.tipIndex(); + TrackIndexType prevTip = currentBranch.tipIndex(); // The surface could be either sensitive or passive bool isSensitive = (surface->associatedDetectorElement() != nullptr); @@ -800,8 +843,7 @@ class CombinatorialKalmanFilter { // No source links on surface, add either hole or passive material // TrackState. No storage allocation for uncalibrated/calibrated // measurement and filtered parameter - auto stateMask = - TrackStatePropMask::Predicted | TrackStatePropMask::Jacobian; + auto stateMask = PM::Predicted | PM::Jacobian; if (isSensitive) { // Increment of number of holes @@ -826,29 +868,25 @@ class CombinatorialKalmanFilter { boundParams.covariance() = state.stepping.cov; // Add a hole or material track state to the multitrajectory - IndexType currentTip = addNonSourcelinkState( + TrackIndexType currentTip = addNonSourcelinkState( stateMask, boundState, result, isSensitive, prevTip); auto nonSourcelinkState = result.trackStates->getTrackState(currentTip); currentBranch.tipIndex() = currentTip; - using BranchStopperResult = - CombinatorialKalmanFilterBranchStopperResult; BranchStopperResult branchStopperResult = m_extensions.branchStopper(currentBranch, nonSourcelinkState); // Check the branch if (branchStopperResult == BranchStopperResult::Continue) { - // Remembered the active tip and its state + // Remembered the active branch and its state } else { // No branch on this surface nBranchesOnSurface = 0; - if (branchStopperResult == BranchStopperResult::StopAndKeep) { storeLastActiveBranch(result); } - - // Remove the tip from list of active tips + // Remove the branch from list result.activeBranches.pop_back(); } @@ -862,7 +900,7 @@ class CombinatorialKalmanFilter { nBranchesOnSurface = 1; } - // Reset current tip if there is no branch on current surface + // Reset current branch if there is no branch on current surface if (nBranchesOnSurface == 0) { ACTS_DEBUG("Branch on surface " << surface->geometryId() << " is stopped"); @@ -880,44 +918,51 @@ class CombinatorialKalmanFilter { return Result::success(); } - /// process new, incompomplete track states and set the filtered state + /// Process new, incompomplete track states and set the filtered state + /// /// @note will process the given list of new states, run the updater /// or share the predicted state for states flagged as outliers - /// and add them to the list of active tips + /// and add them to the list of active branches /// /// @param gctx The geometry context for this track finding/fitting /// @param newTrackStateList index list of new track states - /// @param result which contains among others the new states, and the list of active tips - /// @return tuple of the number of newly added tips and outlier flag or an error - Result> processNewTrackStates( + /// @param result which contains among others the new states, and the list of active branches + /// @return the number of newly added branches and number of stopped branches or an error + Result> processNewTrackStates( const Acts::GeometryContext& gctx, - const boost::container::small_vector< - IndexType, s_maxBranchesPerSurface>& newTrackStateList, + const CkfTypes::BranchVector& newTrackStateList, result_type& result) const { + using PM = TrackStatePropMask; + unsigned int nBranchesOnSurface = 0; - bool isOutlier = false; - for (IndexType tipIndex : newTrackStateList) { - // Inherit the tip state from the previous and will be updated later - auto trackState = result.trackStates->getTrackState(tipIndex); - - auto newBranch = result.activeBranches.back(); - if (nBranchesOnSurface > 0) { - newBranch = result.tracks->makeTrack(); - result.activeBranches.push_back(newBranch); - } - newBranch.tipIndex() = trackState.index(); + unsigned int nStoppedBranches = 0; + + auto rootBranch = result.activeBranches.back(); + + // Build the new branches by forking the root branch + CkfTypes::BranchVector newBranches; + for (auto [i, tipIndex] : enumerate(newTrackStateList)) { + auto newBranch = (i == 0) ? rootBranch : rootBranch.shallowCopy(); + newBranch.tipIndex() = tipIndex; + newBranches.push_back(newBranch); + } + + // Remove the root branch + result.activeBranches.pop_back(); + + // Update and select from the new branches + for (TrackProxy newBranch : newBranches) { + auto trackState = newBranch.outermostTrackState(); + TrackStateType typeFlags = trackState.typeFlags(); - using PM = Acts::TrackStatePropMask; - TrackStateType typeFlags(trackState.typeFlags()); if (typeFlags.test(TrackStateFlag::OutlierFlag)) { - // Increment number of outliers - isOutlier = true; - newBranch.nOutliers()++; // No Kalman update for outlier // Set the filtered parameter index to be the same with predicted // parameter trackState.shareFrom(PM::Predicted, PM::Filtered); - } else { + // Increment number of outliers + newBranch.nOutliers()++; + } else if (typeFlags.test(TrackStateFlag::MeasurementFlag)) { // Kalman update auto updateRes = m_extensions.updater(gctx, trackState, *updaterLogger); @@ -925,16 +970,20 @@ class CombinatorialKalmanFilter { ACTS_ERROR("Update step failed: " << updateRes.error()); return updateRes.error(); } - ACTS_VERBOSE( - "Creating measurement track state with tip = " << tipIndex); + ACTS_VERBOSE("Appended measurement track state with tip = " + << newBranch.tipIndex()); // Set the measurement flag typeFlags.set(TrackStateFlag::MeasurementFlag); // Increment number of measurements newBranch.nMeasurements()++; + } else { + ACTS_WARNING("Cannot handle this track state flags"); + nStoppedBranches++; + continue; } - using BranchStopperResult = - CombinatorialKalmanFilterBranchStopperResult; + result.activeBranches.push_back(newBranch); + BranchStopperResult branchStopperResult = m_extensions.branchStopper(newBranch, trackState); @@ -943,21 +992,17 @@ class CombinatorialKalmanFilter { // Record the number of branches on surface nBranchesOnSurface++; } else { + // Record the number of stopped branches + nStoppedBranches++; if (branchStopperResult == BranchStopperResult::StopAndKeep) { storeLastActiveBranch(result); } - - // Pushing the pop in case it is still the first branch - if (nBranchesOnSurface > 0) { - result.activeBranches.pop_back(); - } + // Remove the branch from list + result.activeBranches.pop_back(); } } - // Finally pop the current branch if there are no branches on surface - if (nBranchesOnSurface == 0) { - result.activeBranches.pop_back(); - } - return std::make_tuple(nBranchesOnSurface, isOutlier); + + return std::pair{nBranchesOnSurface, nStoppedBranches}; } /// @brief CombinatorialKalmanFilter actor operation: add a hole or material track state @@ -969,10 +1014,12 @@ class CombinatorialKalmanFilter { /// @param prevTip The index of the previous state /// /// @return The tip of added state - IndexType addNonSourcelinkState(TrackStatePropMask stateMask, - const BoundState& boundState, - result_type& result, bool isSensitive, - IndexType prevTip) const { + TrackIndexType addNonSourcelinkState(TrackStatePropMask stateMask, + const BoundState& boundState, + result_type& result, bool isSensitive, + TrackIndexType prevTip) const { + using PM = TrackStatePropMask; + // Add a track state auto trackStateProxy = result.trackStates->makeTrackState(stateMask, prevTip); @@ -1003,8 +1050,7 @@ class CombinatorialKalmanFilter { // Set the filtered parameter index to be the same with predicted // parameter - trackStateProxy.shareFrom(TrackStatePropMask::Predicted, - TrackStatePropMask::Filtered); + trackStateProxy.shareFrom(PM::Predicted, PM::Filtered); return trackStateProxy.index(); } @@ -1020,7 +1066,6 @@ class CombinatorialKalmanFilter { /// @param stepper The stepper in use /// @param navigator The navigator in use /// @param updateStage The material update stage - /// template void materialInteractor(const Surface* surface, propagator_state_t& state, @@ -1073,18 +1118,15 @@ class CombinatorialKalmanFilter { void storeLastActiveBranch(result_type& result) const { auto currentBranch = result.activeBranches.back(); - IndexType currentTip = currentBranch.tipIndex(); + TrackIndexType currentTip = currentBranch.tipIndex(); - // @TODO: Keep information on tip state around so we don't have to - // recalculate it later ACTS_VERBOSE("Find track with entry index = " << currentTip << " and there are nMeasurements = " << currentBranch.nMeasurements() << ", nOutliers = " << currentBranch.nOutliers() << ", nHoles = " << currentBranch.nHoles() << " on track"); - std::optional - lastMeasurement; + std::optional lastMeasurement; for (const auto& trackState : currentBranch.trackStatesReversed()) { if (trackState.typeFlags().test(TrackStateFlag::MeasurementFlag)) { lastMeasurement = trackState; @@ -1146,10 +1188,7 @@ class CombinatorialKalmanFilter { bool operator()(propagator_state_t& /*state*/, const stepper_t& /*stepper*/, const navigator_t& /*navigator*/, const result_t& result, const Logger& /*logger*/) const { - if (result.finished) { - return true; - } - return false; + return !result.lastError.ok() || result.finished; } }; @@ -1205,8 +1244,10 @@ class CombinatorialKalmanFilter { using Aborters = AbortList; // Create relevant options for the propagation options - typename propagator_t::template Options propOptions( - tfOptions.geoContext, tfOptions.magFieldContext); + using PropagatorOptions = + typename propagator_t::template Options; + PropagatorOptions propOptions(tfOptions.geoContext, + tfOptions.magFieldContext); // Set the trivial propagator options propOptions.setPlainOptions(tfOptions.propagatorPlainOptions); @@ -1239,15 +1280,16 @@ class CombinatorialKalmanFilter { } auto propState = - m_propagator.template makeState(initialParameters, propOptions); + m_propagator.template makeState(initialParameters, + propOptions); auto& r = propState .template get>(); r.tracks = &trackContainer; r.trackStates = &trackContainer.trackStateContainer(); - r.stateBuffer = std::make_shared< - typename track_container_t::TrackStateContainerBackend>(); + r.stateBuffer = std::make_shared(); auto rootBranch = trackContainer.makeTrack(); r.activeBranches.push_back(rootBranch); @@ -1267,29 +1309,23 @@ class CombinatorialKalmanFilter { auto& propRes = *result; - /// Get the result of the CombinatorialKalmanFilter + // Get the result of the CombinatorialKalmanFilter auto combKalmanResult = std::move(propRes.template get< CombinatorialKalmanFilterResult>()); - /// The propagation could already reach max step size - /// before the track finding is finished during two phases: - // -> filtering for track finding; - // -> surface targeting to get fitted parameters at target surface. - // This is regarded as a failure. - // @TODO: Implement distinguishment between the above two cases if - // necessary - if (combKalmanResult.lastError.ok() && !combKalmanResult.finished) { - combKalmanResult.lastError = Result( + Result error = combKalmanResult.lastError; + if (error.ok() && !combKalmanResult.finished) { + error = Result( CombinatorialKalmanFilterError::PropagationReachesMaxSteps); } - - if (!combKalmanResult.lastError.ok()) { + if (!error.ok()) { ACTS_ERROR("CombinatorialKalmanFilter failed: " << combKalmanResult.lastError.error() << " " << combKalmanResult.lastError.error().message() - << " with the initial parameters: \n" - << initialParameters.parameters()); + << " with the initial parameters: " + << initialParameters.parameters().transpose()); + return error.error(); } for (const auto& track : combKalmanResult.collectedTracks) { diff --git a/Core/include/Acts/TrackFitting/GaussianSumFitter.hpp b/Core/include/Acts/TrackFitting/GaussianSumFitter.hpp index 49debb5d4cc..cd5cacce204 100644 --- a/Core/include/Acts/TrackFitting/GaussianSumFitter.hpp +++ b/Core/include/Acts/TrackFitting/GaussianSumFitter.hpp @@ -8,7 +8,6 @@ #pragma once -#include "Acts/EventData/TrackHelpers.hpp" #include "Acts/EventData/VectorMultiTrajectory.hpp" #include "Acts/Propagator/DirectNavigator.hpp" #include "Acts/Propagator/MultiStepperAborters.hpp" @@ -18,6 +17,7 @@ #include "Acts/TrackFitting/GsfOptions.hpp" #include "Acts/TrackFitting/detail/GsfActor.hpp" #include "Acts/Utilities/Logger.hpp" +#include "Acts/Utilities/TrackHelpers.hpp" namespace Acts { diff --git a/Core/include/Acts/TrackFitting/GlobalChiSquareFitter.hpp b/Core/include/Acts/TrackFitting/GlobalChiSquareFitter.hpp index 49da43f4dcf..16da26e3d37 100644 --- a/Core/include/Acts/TrackFitting/GlobalChiSquareFitter.hpp +++ b/Core/include/Acts/TrackFitting/GlobalChiSquareFitter.hpp @@ -16,11 +16,11 @@ #include "Acts/EventData/MultiTrajectory.hpp" #include "Acts/EventData/MultiTrajectoryHelpers.hpp" #include "Acts/EventData/SourceLink.hpp" -#include "Acts/EventData/TrackHelpers.hpp" #include "Acts/EventData/TrackParameters.hpp" #include "Acts/EventData/VectorMultiTrajectory.hpp" #include "Acts/EventData/VectorTrackContainer.hpp" #include "Acts/Geometry/GeometryContext.hpp" +#include "Acts/Geometry/TrackingVolume.hpp" #include "Acts/MagneticField/MagneticFieldContext.hpp" #include "Acts/Material/MaterialSlab.hpp" #include "Acts/Propagator/AbortList.hpp" @@ -38,6 +38,7 @@ #include "Acts/Utilities/Delegate.hpp" #include "Acts/Utilities/Logger.hpp" #include "Acts/Utilities/Result.hpp" +#include "Acts/Utilities/TrackHelpers.hpp" #include #include @@ -221,6 +222,10 @@ struct Gx2FitterResult { // Count how many surfaces have been hit std::size_t surfaceCount = 0; + + // Monitor which volume we start in. We do not allow to switch the start of a + // following iteration in a different volume. + const TrackingVolume* startVolume = nullptr; }; /// addToGx2fSums Function @@ -397,6 +402,10 @@ class Gx2Fitter { /// Calibration context for the fit const CalibrationContext* calibrationContext{nullptr}; + /// Monitor which volume we start in. We do not allow to switch the start of + /// a following iteration in a different volume. + const TrackingVolume* startVolume = nullptr; + /// @brief Gx2f actor operation /// /// @tparam propagator_state_t is the type of Propagator state @@ -424,7 +433,7 @@ class Gx2Fitter { } // End the propagation and return to the fitter - if (result.finished) { + if (result.finished || !result.result.ok()) { // Remove the missing surfaces that occur after the last measurement if (result.measurementStates > 0) { result.missedActiveSurfaces.resize(result.measurementHoles); @@ -433,6 +442,19 @@ class Gx2Fitter { return; } + if (startVolume != nullptr && + startVolume != state.navigation.startVolume) { + ACTS_INFO("The update pushed us to a new volume from '" + << startVolume->volumeName() << "' to '" + << state.navigation.startVolume->volumeName() + << "'. Starting to abort."); + result.result = Result( + Experimental::GlobalChiSquareFitterError::UpdatePushedToNewVolume); + + return; + } + result.startVolume = state.navigation.startVolume; + // Update: // - Waiting for a current surface auto surface = navigator.currentSurface(state.navigation); @@ -716,6 +738,10 @@ class Gx2Fitter { // want to fit e.g. q/p and adjusts itself later. std::size_t ndfSystem = std::numeric_limits::max(); + // Monitor which volume we start in. We do not allow to switch the start of + // a following iteration in a different volume. + const TrackingVolume* startVolume = nullptr; + ACTS_VERBOSE("params:\n" << params); /// Actual Fitting ///////////////////////////////////////////////////////// @@ -750,6 +776,7 @@ class Gx2Fitter { gx2fActor.extensions = gx2fOptions.extensions; gx2fActor.calibrationContext = &gx2fOptions.calibrationContext.get(); gx2fActor.actorLogger = m_actorLogger.get(); + gx2fActor.startVolume = startVolume; auto propagatorState = m_propagator.makeState(params, propagatorOptions); @@ -762,6 +789,7 @@ class Gx2Fitter { auto propagationResult = m_propagator.template propagate(propagatorState); + // Run the fitter auto result = m_propagator.template makeResult(std::move(propagatorState), propagationResult, propagatorOptions, false); @@ -776,6 +804,13 @@ class Gx2Fitter { auto& propRes = *result; GX2FResult gx2fResult = std::move(propRes.template get()); + if (!gx2fResult.result.ok()) { + ACTS_INFO("GlobalChiSquareFitter failed in actor: " + << gx2fResult.result.error() << ", " + << gx2fResult.result.error().message()); + return gx2fResult.result.error(); + } + auto track = trackContainerTemp.makeTrack(); tipIndex = gx2fResult.lastMeasurementIndex; @@ -903,6 +938,7 @@ class Gx2Fitter { } oldChi2sum = chi2sum; + startVolume = gx2fResult.startVolume; } ACTS_DEBUG("Finished to iterate"); ACTS_VERBOSE("final params:\n" << params); diff --git a/Core/include/Acts/TrackFitting/GlobalChiSquareFitterError.hpp b/Core/include/Acts/TrackFitting/GlobalChiSquareFitterError.hpp index f84505769a6..ac47142b07d 100644 --- a/Core/include/Acts/TrackFitting/GlobalChiSquareFitterError.hpp +++ b/Core/include/Acts/TrackFitting/GlobalChiSquareFitterError.hpp @@ -18,6 +18,7 @@ enum class GlobalChiSquareFitterError { AIsNotInvertible = 1, DidNotConverge = 2, NotEnoughMeasurements = 3, + UpdatePushedToNewVolume = 4, }; std::error_code make_error_code( diff --git a/Core/include/Acts/TrackFitting/KalmanFitter.hpp b/Core/include/Acts/TrackFitting/KalmanFitter.hpp index 7492e55cd9f..3d2ca45711c 100644 --- a/Core/include/Acts/TrackFitting/KalmanFitter.hpp +++ b/Core/include/Acts/TrackFitting/KalmanFitter.hpp @@ -14,7 +14,6 @@ #include "Acts/EventData/MultiTrajectory.hpp" #include "Acts/EventData/MultiTrajectoryHelpers.hpp" #include "Acts/EventData/SourceLink.hpp" -#include "Acts/EventData/TrackHelpers.hpp" #include "Acts/EventData/TrackParameters.hpp" #include "Acts/EventData/VectorMultiTrajectory.hpp" #include "Acts/Geometry/GeometryContext.hpp" @@ -32,6 +31,7 @@ #include "Acts/Utilities/Delegate.hpp" #include "Acts/Utilities/Logger.hpp" #include "Acts/Utilities/Result.hpp" +#include "Acts/Utilities/TrackHelpers.hpp" #include #include diff --git a/Core/include/Acts/TrackFitting/detail/GsfActor.hpp b/Core/include/Acts/TrackFitting/detail/GsfActor.hpp index 5debb37ebd1..e2aa93238b2 100644 --- a/Core/include/Acts/TrackFitting/detail/GsfActor.hpp +++ b/Core/include/Acts/TrackFitting/detail/GsfActor.hpp @@ -368,6 +368,7 @@ struct GsfActor { result_type& result) const { const auto& surface = *navigator.currentSurface(state.navigation); const auto p_prev = old_bound.absoluteMomentum(); + const auto& particleHypothesis = old_bound.particleHypothesis(); // Evaluate material slab auto slab = surface.surfaceMaterial()->materialSlab( @@ -423,7 +424,8 @@ struct GsfActor { }(); assert(p_prev + delta_p > 0. && "new momentum must be > 0"); - new_pars[eBoundQOverP] = old_bound.charge() / (p_prev + delta_p); + new_pars[eBoundQOverP] = + particleHypothesis.qOverP(p_prev + delta_p, old_bound.charge()); // compute inverse variance of p from mixture and update covariance auto new_cov = old_bound.covariance().value(); diff --git a/Core/include/Acts/Utilities/BinAdjustment.hpp b/Core/include/Acts/Utilities/BinAdjustment.hpp index f83af5971a8..7b4a90eb630 100644 --- a/Core/include/Acts/Utilities/BinAdjustment.hpp +++ b/Core/include/Acts/Utilities/BinAdjustment.hpp @@ -239,37 +239,29 @@ static inline BinUtility adjustBinUtility(const BinUtility& bu, static inline BinUtility adjustBinUtility(const BinUtility& bu, const Surface& surface, const GeometryContext& gctx) { - // The surface type is a cylinder - if (surface.type() == Surface::Cylinder) { - // Cast to Cylinder bounds and return - auto cBounds = dynamic_cast(&(surface.bounds())); - // Return specific adjustment - return adjustBinUtility(bu, *cBounds, surface.transform(gctx)); - - } else if (surface.type() == Surface::Disc) { - // Cast to Cylinder bounds and return - auto rBounds = dynamic_cast(&(surface.bounds())); - // Return specific adjustment - return adjustBinUtility(bu, *rBounds, surface.transform(gctx)); - } else if (surface.type() == Surface::Plane) { - if (surface.bounds().type() == SurfaceBounds::eRectangle) { - // Cast to Plane bounds and return - auto pBounds = dynamic_cast(&(surface.bounds())); - // Return specific adjustment - return adjustBinUtility(bu, *pBounds, surface.transform(gctx)); - } else if (surface.bounds().type() == SurfaceBounds::eTrapezoid) { - // Cast to Plane bounds and return - auto pBounds = dynamic_cast(&(surface.bounds())); - // Return specific adjustment - return adjustBinUtility(bu, *pBounds, surface.transform(gctx)); - } else { - throw std::invalid_argument( - "Bin adjustment not implemented for this type of plane surface yet!"); + if (auto b = dynamic_cast(&(surface.bounds())); + b != nullptr) { + return adjustBinUtility(bu, *b, surface.transform(gctx)); + } + if (auto b = dynamic_cast(&(surface.bounds())); + b != nullptr) { + return adjustBinUtility(bu, *b, surface.transform(gctx)); + } + if (surface.type() == Surface::Plane) { + if (auto b = dynamic_cast(&(surface.bounds())); + b != nullptr) { + return adjustBinUtility(bu, *b, surface.transform(gctx)); + } + if (auto b = dynamic_cast(&(surface.bounds())); + b != nullptr) { + return adjustBinUtility(bu, *b, surface.transform(gctx)); } } + std::stringstream ss; + ss << surface.toStream({}); throw std::invalid_argument( - "Bin adjustment not implemented for this surface yet!"); + "Bin adjustment not implemented for this surface yet:\n" + ss.str()); } } // namespace Acts diff --git a/Core/include/Acts/Utilities/BoundingBox.ipp b/Core/include/Acts/Utilities/BoundingBox.ipp index eb7b3356894..086e288e338 100644 --- a/Core/include/Acts/Utilities/BoundingBox.ipp +++ b/Core/include/Acts/Utilities/BoundingBox.ipp @@ -445,7 +445,7 @@ box_t* octree_inner(std::vector>& store, const std::vector& lprims, std::size_t depth) { using VertexType = typename box_t::VertexType; - assert(lprims.size() > 0); + assert(!lprims.empty()); if (lprims.size() == 1) { // just return return lprims.front(); diff --git a/Core/include/Acts/Utilities/TrackHelpers.hpp b/Core/include/Acts/Utilities/TrackHelpers.hpp index f9883bfeb63..2fe845f6c39 100644 --- a/Core/include/Acts/Utilities/TrackHelpers.hpp +++ b/Core/include/Acts/Utilities/TrackHelpers.hpp @@ -363,6 +363,45 @@ Result extrapolateTracksToReferenceSurface( return result; } +/// Helper function to calculate a number of track level quantities and store +/// them on the track itself +/// @note The input track needs to be mutable, so @c ReadOnly=false +/// @tparam track_container_t the track container backend +/// @tparam track_state_container_t the track state container backend +/// @tparam holder_t the holder type for the track container backends +/// @param track A mutable track proxy to operate on +template class holder_t> +void calculateTrackQuantities( + Acts::TrackProxy + track) { + track.chi2() = 0; + track.nDoF() = 0; + + track.nHoles() = 0; + track.nMeasurements() = 0; + track.nSharedHits() = 0; + track.nOutliers() = 0; + + for (const auto &trackState : track.trackStatesReversed()) { + auto typeFlags = trackState.typeFlags(); + + if (typeFlags.test(Acts::TrackStateFlag::HoleFlag)) { + track.nHoles()++; + } else if (typeFlags.test(Acts::TrackStateFlag::OutlierFlag)) { + track.nOutliers()++; + } else if (typeFlags.test(Acts::TrackStateFlag::MeasurementFlag)) { + if (typeFlags.test(Acts::TrackStateFlag::SharedHitFlag)) { + track.nSharedHits()++; + } + track.nMeasurements()++; + track.chi2() += trackState.chi2(); + track.nDoF() += trackState.calibratedSize(); + } + } +} + } // namespace Acts namespace std { diff --git a/Core/src/AmbiguityResolution/GreedyAmbiguityResolution.cpp b/Core/src/AmbiguityResolution/GreedyAmbiguityResolution.cpp index 73f4a65d974..73a94da94a2 100644 --- a/Core/src/AmbiguityResolution/GreedyAmbiguityResolution.cpp +++ b/Core/src/AmbiguityResolution/GreedyAmbiguityResolution.cpp @@ -1,6 +1,6 @@ // This file is part of the Acts project. // -// Copyright (C) 2023 CERN for the benefit of the Acts project +// Copyright (C) 2023-2024 CERN for the benefit of the Acts project // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this diff --git a/Core/src/Detector/Detector.cpp b/Core/src/Detector/Detector.cpp index 61a5e6b155c..c63fe1e8802 100644 --- a/Core/src/Detector/Detector.cpp +++ b/Core/src/Detector/Detector.cpp @@ -207,3 +207,8 @@ const Acts::GeometryHierarchyMap& Acts::Experimental::Detector::sensitiveHierarchyMap() const { return m_sensitiveHierarchyMap; } + +const Acts::Surface* Acts::Experimental::Detector::findSurface( + GeometryIdentifier geoID) const { + return *m_sensitiveHierarchyMap.find(geoID); +} diff --git a/Core/src/Geometry/CuboidVolumeBuilder.cpp b/Core/src/Geometry/CuboidVolumeBuilder.cpp index 4d01bd78227..02b600b37ef 100644 --- a/Core/src/Geometry/CuboidVolumeBuilder.cpp +++ b/Core/src/Geometry/CuboidVolumeBuilder.cpp @@ -97,7 +97,7 @@ std::shared_ptr Acts::CuboidVolumeBuilder::buildLayer( pl.envelope[BinningValue::binY] = cfg.envelopeY; pl.envelope[BinningValue::binZ] = cfg.envelopeZ; return layerCreator.planeLayer(gctx, cfg.surfaces, cfg.binsY, cfg.binsZ, - BinningValue::binX, pl, trafo); + cfg.binningDimension, pl, trafo); } std::pair Acts::CuboidVolumeBuilder::binningRange( @@ -121,10 +121,10 @@ std::pair Acts::CuboidVolumeBuilder::binningRange( for (const auto& layercfg : cfg.layerCfg) { // recreating the protolayer for each layer => slow, but only few sensors ProtoLayer pl{gctx, layercfg.surfaces}; - pl.envelope[BinningValue::binX] = layercfg.envelopeX; + pl.envelope[cfg.binningDimension] = layercfg.envelopeX; - double surfacePosMin = pl.min(BinningValue::binX); - double surfacePosMax = pl.max(BinningValue::binX); + double surfacePosMin = pl.min(cfg.binningDimension); + double surfacePosMax = pl.max(cfg.binningDimension); // Test if new extreme is found and set it if (surfacePosMin < minMax.first) { @@ -137,9 +137,9 @@ std::pair Acts::CuboidVolumeBuilder::binningRange( // Use the volume boundaries as limits for the binning minMax.first = std::min( - minMax.first, minVolumeBoundaries(toUnderlying(BinningValue::binX))); + minMax.first, minVolumeBoundaries(toUnderlying(cfg.binningDimension))); minMax.second = std::max( - minMax.second, maxVolumeBoundaries(toUnderlying(BinningValue::binX))); + minMax.second, maxVolumeBoundaries(toUnderlying(cfg.binningDimension))); return minMax; } @@ -176,7 +176,7 @@ std::shared_ptr Acts::CuboidVolumeBuilder::buildVolume( lacCnf, getDefaultLogger("LayerArrayCreator", Logging::INFO)); std::unique_ptr layArr( layArrCreator.layerArray(gctx, layVec, minMax.first, minMax.second, - BinningType::arbitrary, BinningValue::binX)); + BinningType::arbitrary, cfg.binningDimension)); // Build confined volumes if (cfg.trackingVolumes.empty()) { diff --git a/Core/src/Geometry/ProtoLayer.cpp b/Core/src/Geometry/ProtoLayer.cpp index bc81e3f5e89..af2313e2ce6 100644 --- a/Core/src/Geometry/ProtoLayer.cpp +++ b/Core/src/Geometry/ProtoLayer.cpp @@ -67,7 +67,10 @@ std::ostream& ProtoLayer::toStream(std::ostream& sl) const { void ProtoLayer::measure(const GeometryContext& gctx, const std::vector& surfaces) { for (const auto& sf : surfaces) { - auto sfPolyhedron = sf->polyhedronRepresentation(gctx, 1); + // To prevent problematic isInsidePolygon check for straw surfaces with only + // one lseg + int lseg = (sf->type() != Surface::Straw) ? 1 : 2; + auto sfPolyhedron = sf->polyhedronRepresentation(gctx, lseg); const DetectorElementBase* element = sf->associatedDetectorElement(); const auto* regSurface = dynamic_cast(sf); if (element != nullptr && regSurface != nullptr) { diff --git a/Core/src/Geometry/ProtoLayerHelper.cpp b/Core/src/Geometry/ProtoLayerHelper.cpp index 9d00aea6369..6a2c7fc1ce8 100644 --- a/Core/src/Geometry/ProtoLayerHelper.cpp +++ b/Core/src/Geometry/ProtoLayerHelper.cpp @@ -43,7 +43,10 @@ std::vector Acts::ProtoLayerHelper::protoLayers( // Loop over surfaces and sort into clusters for (auto& sf : surfaces) { - auto sfExtent = sf->polyhedronRepresentation(gctx, 1).extent(); + // To prevent problematic isInsidePolygon check for straw surfaces with only + // one lseg + int lseg = (sf->type() != Surface::Straw) ? 1 : 2; + auto sfExtent = sf->polyhedronRepresentation(gctx, lseg).extent(); sfExtent.envelope()[sorting.first] = {sorting.second, sorting.second}; auto& sfCluster = findCluster(sfExtent); sfCluster.first.extend(sfExtent); diff --git a/Core/src/Material/VolumeMaterialMapper.cpp b/Core/src/Material/VolumeMaterialMapper.cpp index f46edb9cfa4..2bb9113f4a9 100644 --- a/Core/src/Material/VolumeMaterialMapper.cpp +++ b/Core/src/Material/VolumeMaterialMapper.cpp @@ -402,8 +402,6 @@ void Acts::VolumeMaterialMapper::mapMaterialTrack( << " at position = (" << mVolumes.position.x() << ", " << mVolumes.position.y() << ", " << mVolumes.position.z() << ")"); - - mappingVolumes.push_back(mVolumes); } // Run the mapping process, i.e. take the recorded material and map it // onto the mapping volume: diff --git a/Core/src/Propagator/SympyStepper.cpp b/Core/src/Propagator/SympyStepper.cpp index 25fc6983cc9..77b075be31c 100644 --- a/Core/src/Propagator/SympyStepper.cpp +++ b/Core/src/Propagator/SympyStepper.cpp @@ -162,6 +162,8 @@ Result SympyStepper::stepImpl( state.pars.template segment<1>(eFreeTime).data(), state.derivative.data(), state.covTransport ? state.jacTransport.data() : nullptr); + // Protect against division by zero + errorEstimate = std::max(1e-20, errorEstimate); if (ok) { break; diff --git a/Core/src/TrackFitting/GlobalChiSquareFitterError.cpp b/Core/src/TrackFitting/GlobalChiSquareFitterError.cpp index dff5795c932..f1fd9accd3a 100644 --- a/Core/src/TrackFitting/GlobalChiSquareFitterError.cpp +++ b/Core/src/TrackFitting/GlobalChiSquareFitterError.cpp @@ -30,6 +30,8 @@ class GlobalChiSquareFitterErrorCategory : public std::error_category { return "Gx2f: Did not converge in 'nUpdateMax' updates."; case GlobalChiSquareFitterError::NotEnoughMeasurements: return "Gx2f: Not enough measurements."; + case GlobalChiSquareFitterError::UpdatePushedToNewVolume: + return "Gx2f: Update pushed the parameters to a new volume."; default: return "unknown"; } diff --git a/Examples/Algorithms/Fatras/src/FatrasSimulation.cpp b/Examples/Algorithms/Fatras/src/FatrasSimulation.cpp index a470c28873e..513082320b0 100644 --- a/Examples/Algorithms/Fatras/src/FatrasSimulation.cpp +++ b/Examples/Algorithms/Fatras/src/FatrasSimulation.cpp @@ -1,6 +1,6 @@ // This file is part of the Acts project. // -// Copyright (C) 2017-2021 CERN for the benefit of the Acts project +// Copyright (C) 2017-2024 CERN for the benefit of the Acts project // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -12,10 +12,10 @@ #include "Acts/EventData/TrackParameters.hpp" #include "Acts/Geometry/GeometryContext.hpp" #include "Acts/MagneticField/MagneticFieldContext.hpp" -#include "Acts/Propagator/EigenStepper.hpp" #include "Acts/Propagator/Navigator.hpp" #include "Acts/Propagator/Propagator.hpp" #include "Acts/Propagator/StraightLineStepper.hpp" +#include "Acts/Propagator/SympyStepper.hpp" #include "Acts/Surfaces/Surface.hpp" #include "Acts/Utilities/Logger.hpp" #include "Acts/Utilities/Result.hpp" @@ -83,16 +83,14 @@ namespace { // Magnetic-field specific PIMPL implementation. // -// This always uses the EigenStepper with default extensions for charged -// particle propagation and is thus limited to propagation in vacuum at the -// moment. -// @TODO: Remove this, unneeded after #675 +// This always uses the SympyStepper for charged particle propagation and is +// thus limited to propagation in vacuum at the moment. struct FatrasSimulationT final : ActsExamples::detail::FatrasSimulation { using CutPMin = ActsFatras::Min; // typedefs for charge particle simulation // propagate charged particles numerically in the given magnetic field - using ChargedStepper = Acts::EigenStepper<>; + using ChargedStepper = Acts::SympyStepper; using ChargedPropagator = Acts::Propagator; // charged particles w/ standard em physics list and selectable hits using ChargedSelector = CutPMin; diff --git a/Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/TrackFindingAlgorithm.hpp b/Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/TrackFindingAlgorithm.hpp index 1e3bc2cdbe4..8d31a99b0f8 100644 --- a/Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/TrackFindingAlgorithm.hpp +++ b/Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/TrackFindingAlgorithm.hpp @@ -115,6 +115,9 @@ class TrackFindingAlgorithm final : public IAlgorithm { Acts::TrackExtrapolationStrategy::firstOrLast; /// Run finding in two directions bool twoWay = true; + /// Whether to run the finding in seed parameter direction or reverse + /// direction + bool reverseSearch = false; /// Whether to use seed deduplication /// This is only available if `inputSeeds` is set. bool seedDeduplication = false; diff --git a/Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/TrackParamsEstimationAlgorithm.hpp b/Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/TrackParamsEstimationAlgorithm.hpp index 202112f75e7..0111aa7fbcd 100644 --- a/Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/TrackParamsEstimationAlgorithm.hpp +++ b/Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/TrackParamsEstimationAlgorithm.hpp @@ -63,13 +63,16 @@ class TrackParamsEstimationAlgorithm final : public IAlgorithm { /// Output prototrack collection - only tracks with successful parameter /// estimation are propagated (optional) std::string outputProtoTracks; + /// Tracking geometry for surface lookup. std::shared_ptr trackingGeometry; /// Magnetic field variant. std::shared_ptr magneticField; + /// The minimum magnetic field to trigger the track parameters estimation double bFieldMin = 0.1 * Acts::UnitConstants::T; - /// Initial covariance matrix diagonal. + + /// Initial sigmas for the track parameters. std::array initialSigmas = { 1 * Acts::UnitConstants::mm, 1 * Acts::UnitConstants::mm, @@ -77,23 +80,13 @@ class TrackParamsEstimationAlgorithm final : public IAlgorithm { 1 * Acts::UnitConstants::degree, 0 * Acts::UnitConstants::e / Acts::UnitConstants::GeV, 1 * Acts::UnitConstants::ns}; - /// Initial q/p coefficient covariance matrix diagonal. - std::array initialSimgaQoverPCoefficients = { - 0 * Acts::UnitConstants::mm / - (Acts::UnitConstants::e * Acts::UnitConstants::GeV), - 0 * Acts::UnitConstants::mm / - (Acts::UnitConstants::e * Acts::UnitConstants::GeV), - 0 * Acts::UnitConstants::degree / - (Acts::UnitConstants::e * Acts::UnitConstants::GeV), - 0 * Acts::UnitConstants::degree / - (Acts::UnitConstants::e * Acts::UnitConstants::GeV), - 0.1, - 0 * Acts::UnitConstants::ns / - (Acts::UnitConstants::e * Acts::UnitConstants::GeV)}; + /// Relative pt resolution used for the initial sigma of q/p. + double initialSigmaPtRel = 0.1; /// Inflate initial covariance. std::array initialVarInflation = {1., 1., 1., 1., 1., 1.}; /// Inflate time covariance if no time measurement is available. double noTimeVarInflation = 100.; + /// Particle hypothesis. Acts::ParticleHypothesis particleHypothesis = Acts::ParticleHypothesis::pion(); diff --git a/Examples/Algorithms/TrackFinding/src/TrackFindingAlgorithm.cpp b/Examples/Algorithms/TrackFinding/src/TrackFindingAlgorithm.cpp index fb9e7d55560..f4352ea46ce 100644 --- a/Examples/Algorithms/TrackFinding/src/TrackFindingAlgorithm.cpp +++ b/Examples/Algorithms/TrackFinding/src/TrackFindingAlgorithm.cpp @@ -20,11 +20,11 @@ #include "Acts/EventData/VectorTrackContainer.hpp" #include "Acts/Geometry/GeometryIdentifier.hpp" #include "Acts/Propagator/AbortList.hpp" -#include "Acts/Propagator/EigenStepper.hpp" #include "Acts/Propagator/MaterialInteractor.hpp" #include "Acts/Propagator/Navigator.hpp" #include "Acts/Propagator/Propagator.hpp" #include "Acts/Propagator/StandardAborters.hpp" +#include "Acts/Propagator/SympyStepper.hpp" #include "Acts/Surfaces/PerigeeSurface.hpp" #include "Acts/Surfaces/Surface.hpp" #include "Acts/TrackFinding/CombinatorialKalmanFilter.hpp" @@ -348,7 +348,8 @@ ProcessCode TrackFindingAlgorithm::execute(const AlgorithmContext& ctx) const { Acts::PropagatorPlainOptions firstPropOptions(ctx.geoContext, ctx.magFieldContext); firstPropOptions.maxSteps = m_cfg.maxSteps; - firstPropOptions.direction = Acts::Direction::Forward; + firstPropOptions.direction = m_cfg.reverseSearch ? Acts::Direction::Backward + : Acts::Direction::Forward; Acts::PropagatorPlainOptions secondPropOptions(ctx.geoContext, ctx.magFieldContext); @@ -359,19 +360,20 @@ ProcessCode TrackFindingAlgorithm::execute(const AlgorithmContext& ctx) const { TrackFinderOptions firstOptions(ctx.geoContext, ctx.magFieldContext, ctx.calibContext, slAccessorDelegate, extensions, firstPropOptions); + firstOptions.targetSurface = m_cfg.reverseSearch ? pSurface.get() : nullptr; TrackFinderOptions secondOptions(ctx.geoContext, ctx.magFieldContext, ctx.calibContext, slAccessorDelegate, extensions, secondPropOptions); - secondOptions.targetSurface = pSurface.get(); + secondOptions.targetSurface = m_cfg.reverseSearch ? nullptr : pSurface.get(); - using Extrapolator = Acts::Propagator, Acts::Navigator>; + using Extrapolator = Acts::Propagator; using ExtrapolatorOptions = Extrapolator::template Options, Acts::AbortList>; Extrapolator extrapolator( - Acts::EigenStepper<>(m_cfg.magneticField), + Acts::SympyStepper(m_cfg.magneticField), Acts::Navigator({m_cfg.trackingGeometry}, logger().cloneWithSuffix("Navigator")), logger().cloneWithSuffix("Propagator")); @@ -558,27 +560,50 @@ ProcessCode TrackFindingAlgorithm::execute(const AlgorithmContext& ctx) const { (*std::next(secondTrackCopy.trackStatesReversed().begin())) .index(); - Acts::calculateTrackQuantities(trackCandidate); - - // TODO This extrapolation should not be necessary - // TODO The CKF is targeting this surface and should communicate - // the resulting parameters - // TODO Removing this requires changes in the core CKF - // implementation - auto secondExtrapolationResult = - Acts::extrapolateTrackToReferenceSurface( - trackCandidate, *pSurface, extrapolator, - extrapolationOptions, m_cfg.extrapolationStrategy, - logger()); - if (!secondExtrapolationResult.ok()) { - m_nFailedExtrapolation++; - ACTS_ERROR("Second extrapolation for seed " - << iSeed << " and track " << secondTrack.index() - << " failed with error " - << secondExtrapolationResult.error()); - continue; + // finalize the track candidate + + if (!m_cfg.reverseSearch) { + // these parameters are already extrapolated by the CKF and have + // the optimal resolution. note that we did not smooth all the + // states. + + trackCandidate.parameters() = secondTrackCopy.parameters(); + trackCandidate.covariance() = secondTrackCopy.covariance(); + trackCandidate.setReferenceSurface( + secondTrackCopy.referenceSurface().getSharedPtr()); + } else { + // smooth the full track and extrapolate to the reference + + auto secondSmoothingResult = + Acts::smoothTrack(ctx.geoContext, trackCandidate, logger()); + if (!secondSmoothingResult.ok()) { + m_nFailedSmoothing++; + ACTS_ERROR("Second smoothing for seed " + << iSeed << " and track " << secondTrack.index() + << " failed with error " + << secondSmoothingResult.error()); + continue; + } + + trackCandidate.reverseTrackStates(true); + + auto secondExtrapolationResult = + Acts::extrapolateTrackToReferenceSurface( + trackCandidate, *pSurface, extrapolator, + extrapolationOptions, m_cfg.extrapolationStrategy, + logger()); + if (!secondExtrapolationResult.ok()) { + m_nFailedExtrapolation++; + ACTS_ERROR("Second extrapolation for seed " + << iSeed << " and track " << secondTrack.index() + << " failed with error " + << secondExtrapolationResult.error()); + continue; + } } + Acts::calculateTrackQuantities(trackCandidate); + addTrack(trackCandidate); ++nSecond; diff --git a/Examples/Algorithms/TrackFinding/src/TrackFindingAlgorithmFunction.cpp b/Examples/Algorithms/TrackFinding/src/TrackFindingAlgorithmFunction.cpp index 1e91b33e217..71298d98767 100644 --- a/Examples/Algorithms/TrackFinding/src/TrackFindingAlgorithmFunction.cpp +++ b/Examples/Algorithms/TrackFinding/src/TrackFindingAlgorithmFunction.cpp @@ -12,9 +12,9 @@ #include "Acts/EventData/TrackStatePropMask.hpp" #include "Acts/EventData/VectorMultiTrajectory.hpp" #include "Acts/EventData/VectorTrackContainer.hpp" -#include "Acts/Propagator/EigenStepper.hpp" #include "Acts/Propagator/Navigator.hpp" #include "Acts/Propagator/Propagator.hpp" +#include "Acts/Propagator/SympyStepper.hpp" #include "Acts/TrackFinding/CombinatorialKalmanFilter.hpp" #include "Acts/TrackFitting/GainMatrixSmoother.hpp" #include "Acts/Utilities/Logger.hpp" @@ -34,7 +34,7 @@ class TrackingGeometry; namespace { -using Stepper = Acts::EigenStepper<>; +using Stepper = Acts::SympyStepper; using Navigator = Acts::Navigator; using Propagator = Acts::Propagator; using CKF = diff --git a/Examples/Algorithms/TrackFinding/src/TrackParamsEstimationAlgorithm.cpp b/Examples/Algorithms/TrackFinding/src/TrackParamsEstimationAlgorithm.cpp index 81f21b27173..4b8344b2ad7 100644 --- a/Examples/Algorithms/TrackFinding/src/TrackParamsEstimationAlgorithm.cpp +++ b/Examples/Algorithms/TrackFinding/src/TrackParamsEstimationAlgorithm.cpp @@ -44,22 +44,32 @@ Acts::BoundSquareMatrix makeInitialCovariance( for (std::size_t i = Acts::eBoundLoc0; i < Acts::eBoundSize; ++i) { double sigma = config.initialSigmas[i]; + double variance = sigma * sigma; - // Add momentum dependent uncertainties - sigma += - config.initialSimgaQoverPCoefficients[i] * params[Acts::eBoundQOverP]; + if (i == Acts::eBoundQOverP) { + // note that we rely on the fact that sigma theta is already computed + double varianceTheta = result(Acts::eBoundTheta, Acts::eBoundTheta); - double var = sigma * sigma; + // transverse momentum contribution + variance += + std::pow(config.initialSigmaPtRel * params[Acts::eBoundQOverP], 2); + + // theta contribution + variance += + varianceTheta * std::pow(params[Acts::eBoundQOverP] * + std::tan(params[Acts::eBoundTheta]), + 2); + } // Inflate the time uncertainty if no time measurement is available if (i == Acts::eBoundTime && !sp.t().has_value()) { - var *= config.noTimeVarInflation; + variance *= config.noTimeVarInflation; } // Inflate the initial covariance - var *= config.initialVarInflation[i]; + variance *= config.initialVarInflation[i]; - result(i, i) = var; + result(i, i) = variance; } return result; diff --git a/Examples/Algorithms/TrackFindingExaTrkX/include/ActsExamples/TrackFindingExaTrkX/TrackFindingFromPrototrackAlgorithm.hpp b/Examples/Algorithms/TrackFindingExaTrkX/include/ActsExamples/TrackFindingExaTrkX/TrackFindingFromPrototrackAlgorithm.hpp index 0c5f1ce960c..f3271821219 100644 --- a/Examples/Algorithms/TrackFindingExaTrkX/include/ActsExamples/TrackFindingExaTrkX/TrackFindingFromPrototrackAlgorithm.hpp +++ b/Examples/Algorithms/TrackFindingExaTrkX/include/ActsExamples/TrackFindingExaTrkX/TrackFindingFromPrototrackAlgorithm.hpp @@ -11,7 +11,6 @@ #include "Acts/EventData/MultiTrajectory.hpp" #include "Acts/EventData/VectorMultiTrajectory.hpp" #include "Acts/MagneticField/MagneticFieldProvider.hpp" -#include "Acts/Propagator/EigenStepper.hpp" #include "Acts/Surfaces/PerigeeSurface.hpp" #include "Acts/TrackFinding/MeasurementSelector.hpp" #include "Acts/TrackFitting/GainMatrixSmoother.hpp" diff --git a/Examples/Algorithms/TrackFitting/src/GlobalChiSquareFitterFunction.cpp b/Examples/Algorithms/TrackFitting/src/GlobalChiSquareFitterFunction.cpp index 47ff781da06..4078e3977a5 100644 --- a/Examples/Algorithms/TrackFitting/src/GlobalChiSquareFitterFunction.cpp +++ b/Examples/Algorithms/TrackFitting/src/GlobalChiSquareFitterFunction.cpp @@ -18,9 +18,9 @@ #include "Acts/EventData/detail/CorrectedTransformationFreeToBound.hpp" #include "Acts/Geometry/GeometryIdentifier.hpp" #include "Acts/Propagator/DirectNavigator.hpp" -#include "Acts/Propagator/EigenStepper.hpp" #include "Acts/Propagator/Navigator.hpp" #include "Acts/Propagator/Propagator.hpp" +#include "Acts/Propagator/SympyStepper.hpp" #include "Acts/TrackFitting/GlobalChiSquareFitter.hpp" #include "Acts/TrackFitting/KalmanFitter.hpp" #include "Acts/Utilities/Delegate.hpp" @@ -47,7 +47,7 @@ class TrackingGeometry; namespace { -using Stepper = Acts::EigenStepper<>; +using Stepper = Acts::SympyStepper; using Propagator = Acts::Propagator; using Fitter = Acts::Experimental::Gx2Fitter; diff --git a/Examples/Algorithms/TrackFitting/src/KalmanFitterFunction.cpp b/Examples/Algorithms/TrackFitting/src/KalmanFitterFunction.cpp index 58a0d23aef6..c96abb3ab9a 100644 --- a/Examples/Algorithms/TrackFitting/src/KalmanFitterFunction.cpp +++ b/Examples/Algorithms/TrackFitting/src/KalmanFitterFunction.cpp @@ -16,9 +16,9 @@ #include "Acts/EventData/detail/CorrectedTransformationFreeToBound.hpp" #include "Acts/Geometry/GeometryIdentifier.hpp" #include "Acts/Propagator/DirectNavigator.hpp" -#include "Acts/Propagator/EigenStepper.hpp" #include "Acts/Propagator/Navigator.hpp" #include "Acts/Propagator/Propagator.hpp" +#include "Acts/Propagator/SympyStepper.hpp" #include "Acts/TrackFitting/GainMatrixSmoother.hpp" #include "Acts/TrackFitting/GainMatrixUpdater.hpp" #include "Acts/TrackFitting/KalmanFitter.hpp" @@ -46,7 +46,7 @@ class TrackingGeometry; namespace { -using Stepper = Acts::EigenStepper<>; +using Stepper = Acts::SympyStepper; using Propagator = Acts::Propagator; using Fitter = Acts::KalmanFitter; using DirectPropagator = Acts::Propagator; diff --git a/Examples/Algorithms/TrackFitting/src/RefittingAlgorithm.cpp b/Examples/Algorithms/TrackFitting/src/RefittingAlgorithm.cpp index 8b86fb8aea9..f3d0df6d1ad 100644 --- a/Examples/Algorithms/TrackFitting/src/RefittingAlgorithm.cpp +++ b/Examples/Algorithms/TrackFitting/src/RefittingAlgorithm.cpp @@ -67,6 +67,11 @@ ActsExamples::ProcessCode ActsExamples::RefittingAlgorithm::execute( continue; } + if (!track.hasReferenceSurface()) { + ACTS_VERBOSE("Skip track " << itrack << ": missing ref surface"); + continue; + } + TrackFitterFunction::GeneralFitterOptions options{ ctx.geoContext, ctx.magFieldContext, ctx.calibContext, &track.referenceSurface(), @@ -91,6 +96,8 @@ ActsExamples::ProcessCode ActsExamples::RefittingAlgorithm::execute( trackSourceLinks.push_back(Acts::SourceLink{sl}); } + std::reverse(surfSequence.begin(), surfSequence.end()); + if (surfSequence.empty()) { ACTS_WARNING("Empty track " << itrack << " found."); continue; diff --git a/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSmearing.cpp b/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSmearing.cpp index 3642cff8b3d..af8b2fc2575 100644 --- a/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSmearing.cpp +++ b/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSmearing.cpp @@ -1,6 +1,6 @@ // This file is part of the Acts project. // -// Copyright (C) 2019 CERN for the benefit of the Acts project +// Copyright (C) 2019-2024 CERN for the benefit of the Acts project // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -76,7 +76,7 @@ ActsExamples::ProcessCode ActsExamples::ParticleSmearing::execute( const auto theta = Acts::VectorHelpers::theta(particle.direction()); const auto pt = particle.transverseMomentum(); const auto p = particle.absoluteMomentum(); - const auto q = particle.charge(); + const auto qOverP = particle.qOverP(); const auto particleHypothesis = m_cfg.particleHypothesis.value_or(particle.hypothesis()); @@ -87,16 +87,17 @@ ActsExamples::ProcessCode ActsExamples::ParticleSmearing::execute( const double sigmaZ0 = m_cfg.sigmaZ0 + m_cfg.sigmaZ0PtA * std::exp(-1.0 * std::abs(m_cfg.sigmaZ0PtB) * pt); - const double sigmaP = m_cfg.sigmaPRel * p; - // var(q/p) = (d(1/p)/dp)² * var(p) = (-1/p²)² * var(p) - const double sigmaQOverP = sigmaP / (p * p); // shortcuts for other resolutions const double sigmaT0 = m_cfg.sigmaT0; const double sigmaPhi = m_cfg.sigmaPhi; const double sigmaTheta = m_cfg.sigmaTheta; + const double sigmaQOverP = + std::sqrt(std::pow(m_cfg.sigmaPtRel * qOverP, 2) + + std::pow(sigmaTheta * (qOverP * std::tan(theta)), 2)); Acts::BoundVector params = Acts::BoundVector::Zero(); // smear the position/time + // note that we smear d0 and z0 in the perigee frame params[Acts::eBoundLoc0] = sigmaD0 * stdNormal(rng); params[Acts::eBoundLoc1] = sigmaZ0 * stdNormal(rng); params[Acts::eBoundTime] = time + sigmaT0 * stdNormal(rng); @@ -105,14 +106,12 @@ ActsExamples::ProcessCode ActsExamples::ParticleSmearing::execute( phi + sigmaPhi * stdNormal(rng), theta + sigmaTheta * stdNormal(rng)); params[Acts::eBoundPhi] = newPhi; params[Acts::eBoundTheta] = newTheta; - // compute smeared absolute momentum vector - const double newP = std::max(0.0, p + sigmaP * stdNormal(rng)); - params[Acts::eBoundQOverP] = particleHypothesis.qOverP(newP, q); + // compute smeared q/p + params[Acts::eBoundQOverP] = qOverP + sigmaQOverP * stdNormal(rng); ACTS_VERBOSE("Smearing particle (pos, time, phi, theta, q/p):"); ACTS_VERBOSE(" from: " << particle.position().transpose() << ", " << time - << ", " << phi << ", " << theta << ", " - << (q != 0 ? q / p : 1 / p)); + << ", " << phi << ", " << theta << ", " << qOverP); ACTS_VERBOSE(" to: " << perigee ->localToGlobal( ctx.geoContext, @@ -130,25 +129,45 @@ ActsExamples::ProcessCode ActsExamples::ParticleSmearing::execute( if (m_cfg.initialSigmas) { // use the initial sigmas if set for (std::size_t i = Acts::eBoundLoc0; i < Acts::eBoundSize; ++i) { - cov(i, i) = m_cfg.initialVarInflation[i] * (*m_cfg.initialSigmas)[i] * - (*m_cfg.initialSigmas)[i]; + double sigma = (*m_cfg.initialSigmas)[i]; + double variance = sigma * sigma; + + if (i == Acts::eBoundQOverP) { + // note that we rely on the fact that sigma theta is already + // computed + double varianceTheta = cov(Acts::eBoundTheta, Acts::eBoundTheta); + + // transverse momentum contribution + variance += std::pow( + m_cfg.initialSigmaPtRel * params[Acts::eBoundQOverP], 2); + + // theta contribution + variance += varianceTheta * + std::pow(params[Acts::eBoundQOverP] * + std::tan(params[Acts::eBoundTheta]), + 2); + } + + // Inflate the initial covariance + variance *= m_cfg.initialVarInflation[i]; + + cov(i, i) = variance; } } else { // otherwise use the smearing sigmas - cov(Acts::eBoundLoc0, Acts::eBoundLoc0) = - m_cfg.initialVarInflation[Acts::eBoundLoc0] * sigmaD0 * sigmaD0; - cov(Acts::eBoundLoc1, Acts::eBoundLoc1) = - m_cfg.initialVarInflation[Acts::eBoundLoc1] * sigmaZ0 * sigmaZ0; - cov(Acts::eBoundTime, Acts::eBoundTime) = - m_cfg.initialVarInflation[Acts::eBoundTime] * sigmaT0 * sigmaT0; - cov(Acts::eBoundPhi, Acts::eBoundPhi) = - m_cfg.initialVarInflation[Acts::eBoundPhi] * sigmaPhi * sigmaPhi; - cov(Acts::eBoundTheta, Acts::eBoundTheta) = - m_cfg.initialVarInflation[Acts::eBoundTheta] * sigmaTheta * - sigmaTheta; - cov(Acts::eBoundQOverP, Acts::eBoundQOverP) = - m_cfg.initialVarInflation[Acts::eBoundQOverP] * sigmaQOverP * - sigmaQOverP; + + Acts::BoundVector sigmas = Acts::BoundVector( + {sigmaD0, sigmaZ0, sigmaPhi, sigmaTheta, sigmaQOverP, sigmaT0}); + + for (std::size_t i = Acts::eBoundLoc0; i < Acts::eBoundSize; ++i) { + double sigma = sigmas[i]; + double variance = sigma * sigma; + + // Inflate the initial covariance + variance *= m_cfg.initialVarInflation[i]; + + cov(i, i) = variance; + } } parameters.emplace_back(perigee, params, cov, particleHypothesis); diff --git a/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSmearing.hpp b/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSmearing.hpp index 19de5a1f47d..68ebad5b14d 100644 --- a/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSmearing.hpp +++ b/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSmearing.hpp @@ -1,6 +1,6 @@ // This file is part of the Acts project. // -// Copyright (C) 2019 CERN for the benefit of the Acts project +// Copyright (C) 2019-2024 CERN for the benefit of the Acts project // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -41,6 +41,11 @@ class ParticleSmearing final : public IAlgorithm { std::string inputParticles; /// Output smeared tracks parameters collection. std::string outputTrackParameters; + + /// Random numbers service. + std::shared_ptr randomNumbers = nullptr; + + // Smearing parameters /// Constant term of the d0 resolution. double sigmaD0 = 20 * Acts::UnitConstants::um; /// Pt-dependent d0 resolution of the form sigma_d0 = A*exp(-1.*abs(B)*pt). @@ -57,18 +62,17 @@ class ParticleSmearing final : public IAlgorithm { double sigmaPhi = 1 * Acts::UnitConstants::degree; /// Theta angular resolution. double sigmaTheta = 1 * Acts::UnitConstants::degree; - /// Relative momentum resolution. - double sigmaPRel = 0.05; - /// Optional. Initial covariance matrix diagonal. Overwrites the default if - /// set. - std::optional> initialSigmas = std::array{ - 1 * Acts::UnitConstants::mm, 1 * Acts::UnitConstants::mm, - 1 * Acts::UnitConstants::degree, 1 * Acts::UnitConstants::degree, - 0.1 / Acts::UnitConstants::GeV, 1 * Acts::UnitConstants::ns}; + /// Relative transverse momentum resolution. + double sigmaPtRel = 0.05; + + /// Optional. Initial sigmas for the track parameters which overwrites the + /// smearing params if set. + std::optional> initialSigmas; + /// Relative pt resolution used for the initial sigma of q/p. + double initialSigmaPtRel = 0.1; /// Inflate the initial covariance matrix - std::array initialVarInflation = {1., 1., 1., 1., 1., 1.}; - /// Random numbers service. - std::shared_ptr randomNumbers = nullptr; + std::array initialVarInflation = {1e4, 1e4, 1e4, 1e4, 1e4, 1e4}; + /// Optional particle hypothesis override. std::optional particleHypothesis = std::nullopt; }; diff --git a/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ProtoTrackTruthMatcher.cpp b/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ProtoTrackTruthMatcher.cpp deleted file mode 100644 index e44ca738cdf..00000000000 --- a/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ProtoTrackTruthMatcher.cpp +++ /dev/null @@ -1,151 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2024 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include "ActsExamples/TruthTracking/ProtoTrackTruthMatcher.hpp" - -#include "Acts/Utilities/Enumerate.hpp" -#include "ActsExamples/EventData/SimParticle.hpp" -#include "ActsExamples/Validation/TrackClassification.hpp" - -#include -#include -#include -#include - -namespace ActsExamples { - -ProtoTrackTruthMatcher::ProtoTrackTruthMatcher(const Config& config, - Acts::Logging::Level level) - : IAlgorithm("ProtoTrackTruthMatcher", level), m_cfg(config) { - if (m_cfg.inputProtoTracks.empty()) { - throw std::invalid_argument("Missing input proto tracks"); - } - if (m_cfg.inputParticles.empty()) { - throw std::invalid_argument("Missing input particles"); - } - if (m_cfg.inputMeasurementParticlesMap.empty()) { - throw std::invalid_argument("Missing input measurement particles map"); - } - if (m_cfg.outputProtoTrackParticleMatching.empty()) { - throw std::invalid_argument( - "Missing output proto track particles matching"); - } - if (m_cfg.outputParticleProtoTrackMatching.empty()) { - throw std::invalid_argument("Missing output particle proto track matching"); - } - - m_inputProtoTracks.initialize(m_cfg.inputProtoTracks); - m_inputParticles.initialize(m_cfg.inputParticles); - m_inputMeasurementParticlesMap.initialize(m_cfg.inputMeasurementParticlesMap); - m_outputProtoTrackParticleMatching.initialize( - m_cfg.outputProtoTrackParticleMatching); - m_outputParticleProtoTrackMatching.initialize( - m_cfg.outputParticleProtoTrackMatching); -} - -ActsExamples::ProcessCode ProtoTrackTruthMatcher::execute( - const ActsExamples::AlgorithmContext& ctx) const { - // Read input proto tracks - const auto& protoTracks = m_inputProtoTracks(ctx); - - // Read truth input collections - const auto& particles = m_inputParticles(ctx); - const auto& hitParticlesMap = m_inputMeasurementParticlesMap(ctx); - - ProtoTrackParticleMatching protoTrackParticleMatching; - ParticleProtoTrackMatching particleProtoTrackMatching; - - // TODO this may be computed in a separate algorithm - // TODO can we wire this through? - std::map particleTruthHitCount; - for (const auto& [_, pid] : hitParticlesMap) { - particleTruthHitCount[pid]++; - } - - // For each particle within a track, how many hits did it contribute - std::vector particleHitCounts; - - for (const auto& [index, protoTrack] : Acts::enumerate(protoTracks)) { - // Get the majority truth particle to this track - identifyContributingParticles(hitParticlesMap, protoTrack, - particleHitCounts); - if (particleHitCounts.empty()) { - ACTS_DEBUG("No truth particle associated with this proto track " - << index); - continue; - } - - // Get the majority particleId and majority particle counts - // Note that the majority particle might not be in the truth seeds - // collection - ActsFatras::Barcode majorityParticleId = - particleHitCounts.front().particleId; - std::size_t nMajorityHits = particleHitCounts.front().hitCount; - - if (particles.find(majorityParticleId) == particles.end()) { - ACTS_DEBUG( - "The majority particle is not in the input particle collection, " - "majorityParticleId = " - << majorityParticleId); - continue; - } - - // Check if the trajectory is matched with truth. - // If not, it will be classified as 'fake' - const bool recoMatched = - static_cast(nMajorityHits) / protoTrack.size() >= - m_cfg.matchingRatio; - const bool truthMatched = - static_cast(nMajorityHits) / - particleTruthHitCount.at(majorityParticleId) >= - m_cfg.matchingRatio; - - if ((!m_cfg.doubleMatching && recoMatched) || - (m_cfg.doubleMatching && recoMatched && truthMatched)) { - auto& trackParticleMatch = protoTrackParticleMatching[index] = { - TrackMatchClassification::Matched, majorityParticleId, - particleHitCounts}; - - auto& particleTrackMatch = particleProtoTrackMatching[majorityParticleId]; - if (!particleTrackMatch.track) { - particleTrackMatch.track = index; - } else { - // we already have a track associated with this particle and have to - // resolve the ambiguity. - // we will use the track with more hits and smaller chi2 - const auto& otherProtoTrack = - protoTracks.at(particleTrackMatch.track.value()); - if (otherProtoTrack.size() < protoTrack.size()) { - protoTrackParticleMatching[particleTrackMatch.track.value()] - .classification = TrackMatchClassification::Duplicate; - particleTrackMatch.track = index; - } else { - trackParticleMatch.classification = - TrackMatchClassification::Duplicate; - } - - ++particleTrackMatch.duplicates; - } - } else { - protoTrackParticleMatching[index] = {TrackMatchClassification::Fake, - std::nullopt, particleHitCounts}; - - auto& particleTrackMatch = particleProtoTrackMatching[majorityParticleId]; - ++particleTrackMatch.fakes; - } - } - - m_outputProtoTrackParticleMatching(ctx, - std::move(protoTrackParticleMatching)); - m_outputParticleProtoTrackMatching(ctx, - std::move(particleProtoTrackMatching)); - - return ProcessCode::SUCCESS; -} - -} // namespace ActsExamples diff --git a/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ProtoTrackTruthMatcher.hpp b/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ProtoTrackTruthMatcher.hpp deleted file mode 100644 index 34364722f85..00000000000 --- a/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ProtoTrackTruthMatcher.hpp +++ /dev/null @@ -1,68 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2024 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -#include "Acts/Utilities/Logger.hpp" -#include "ActsExamples/EventData/ProtoTrack.hpp" -#include "ActsExamples/EventData/SimHit.hpp" -#include "ActsExamples/EventData/SimParticle.hpp" -#include "ActsExamples/EventData/TruthMatching.hpp" -#include "ActsExamples/Framework/DataHandle.hpp" -#include "ActsExamples/Framework/IAlgorithm.hpp" -#include "ActsExamples/Framework/ProcessCode.hpp" - -#include - -namespace ActsExamples { - -struct AlgorithmContext; - -/// Matches proto track to truth particles and vice versa -class ProtoTrackTruthMatcher final : public IAlgorithm { - public: - struct Config { - /// Input proto tracks collection - std::string inputProtoTracks; - /// Input particles collection. - std::string inputParticles; - /// Input hit-particles map collection. - std::string inputMeasurementParticlesMap; - /// Output proto track-particle matching. - std::string outputProtoTrackParticleMatching; - /// Output particle-proto track matching. - std::string outputParticleProtoTrackMatching; - - /// Matching ratio for track to particle matching - double matchingRatio = 0.5; - /// Whether to use double matching (track to particle and particle to track) - bool doubleMatching = false; - }; - - ProtoTrackTruthMatcher(const Config& config, Acts::Logging::Level level); - - ProcessCode execute(const AlgorithmContext& ctx) const final; - - /// Get readonly access to the config parameters - const Config& config() const { return m_cfg; } - - private: - Config m_cfg; - - ReadDataHandle m_inputProtoTracks{this, - "InputProtoTracks"}; - ReadDataHandle m_inputParticles{this, "InputParticles"}; - ReadDataHandle m_inputMeasurementParticlesMap{ - this, "InputMeasurementParticlesMap"}; - WriteDataHandle m_outputProtoTrackParticleMatching{ - this, "OutputProtoTrackParticleMatching"}; - WriteDataHandle m_outputParticleProtoTrackMatching{ - this, "OutputParticleProtoTrackMatching"}; -}; - -} // namespace ActsExamples diff --git a/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/TrackTruthMatcher.hpp b/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/TrackTruthMatcher.hpp index 55f64586c0d..ffb0a545540 100644 --- a/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/TrackTruthMatcher.hpp +++ b/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/TrackTruthMatcher.hpp @@ -41,7 +41,7 @@ class TrackTruthMatcher final : public IAlgorithm { /// Matching ratio for track to particle matching double matchingRatio = 0.5; /// Whether to use double matching (track to particle and particle to track) - bool doubleMatching = false; + bool doubleMatching = true; }; TrackTruthMatcher(const Config& config, Acts::Logging::Level level); diff --git a/Examples/Algorithms/TruthTracking/CMakeLists.txt b/Examples/Algorithms/TruthTracking/CMakeLists.txt index c138bf921fa..df9a5d6c36b 100644 --- a/Examples/Algorithms/TruthTracking/CMakeLists.txt +++ b/Examples/Algorithms/TruthTracking/CMakeLists.txt @@ -5,7 +5,6 @@ add_library( ActsExamples/TruthTracking/TrackParameterSelector.cpp ActsExamples/TruthTracking/TrackModifier.cpp ActsExamples/TruthTracking/TrackTruthMatcher.cpp - ActsExamples/TruthTracking/ProtoTrackTruthMatcher.cpp ActsExamples/TruthTracking/TruthSeedSelector.cpp ActsExamples/TruthTracking/TruthTrackFinder.cpp ActsExamples/TruthTracking/TruthVertexFinder.cpp diff --git a/Examples/Algorithms/Utilities/CMakeLists.txt b/Examples/Algorithms/Utilities/CMakeLists.txt index 855f3bd49b7..82a314a699d 100644 --- a/Examples/Algorithms/Utilities/CMakeLists.txt +++ b/Examples/Algorithms/Utilities/CMakeLists.txt @@ -5,6 +5,7 @@ add_library( src/TrajectoriesToPrototracks.cpp src/TrackSelectorAlgorithm.cpp src/TracksToTrajectories.cpp + src/PrototracksToTracks.cpp src/HitSelector.cpp src/TracksToParameters.cpp) target_include_directories( diff --git a/Examples/Algorithms/Utilities/include/ActsExamples/Utilities/ProtoTracksToTracks.hpp b/Examples/Algorithms/Utilities/include/ActsExamples/Utilities/ProtoTracksToTracks.hpp new file mode 100644 index 00000000000..c2bdcacccc3 --- /dev/null +++ b/Examples/Algorithms/Utilities/include/ActsExamples/Utilities/ProtoTracksToTracks.hpp @@ -0,0 +1,53 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2023 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 http://mozilla.org/MPL/2.0/. + +#pragma once + +#include "ActsExamples/EventData/IndexSourceLink.hpp" +#include "ActsExamples/EventData/Measurement.hpp" +#include "ActsExamples/EventData/ProtoTrack.hpp" +#include "ActsExamples/EventData/Track.hpp" +#include "ActsExamples/Framework/DataHandle.hpp" +#include "ActsExamples/Framework/IAlgorithm.hpp" + +namespace ActsExamples { + +class PrototracksToTracks final : public IAlgorithm { + public: + struct Config { + std::string inputProtoTracks; + std::string inputMeasurements; + std::string outputTracks = "tracks_from_prototracks"; + }; + + /// Construct the algorithm. + /// + /// @param cfg is the algorithm configuration + /// @param lvl is the logging level + PrototracksToTracks(Config cfg, Acts::Logging::Level lvl); + + /// Run the algorithm. + /// + /// @param ctx is the algorithm context with event information + /// @return a process code indication success or failure + ProcessCode execute(const AlgorithmContext& ctx) const final; + + /// Const access to the config + const Config& config() const { return m_cfg; } + + private: + Config m_cfg; + + WriteDataHandle m_outputTracks{this, "OutputTracks"}; + ReadDataHandle m_inputMeasurements{this, + "InputMeasurements"}; + ReadDataHandle m_inputProtoTracks{this, + "InputProtoTracks"}; +}; + +} // namespace ActsExamples diff --git a/Examples/Algorithms/Utilities/src/PrototracksToTracks.cpp b/Examples/Algorithms/Utilities/src/PrototracksToTracks.cpp new file mode 100644 index 00000000000..fe015fbc3f9 --- /dev/null +++ b/Examples/Algorithms/Utilities/src/PrototracksToTracks.cpp @@ -0,0 +1,88 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2023 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 http://mozilla.org/MPL/2.0/. + +#include "ActsExamples/Utilities/ProtoTracksToTracks.hpp" + +#include "Acts/Surfaces/PerigeeSurface.hpp" +#include "ActsExamples/EventData/IndexSourceLink.hpp" +#include "ActsExamples/EventData/ProtoTrack.hpp" +#include "ActsExamples/EventData/SimSeed.hpp" +#include "ActsExamples/Framework/WhiteBoard.hpp" +#include "ActsExamples/Utilities/EventDataTransforms.hpp" + +#include + +namespace ActsExamples { + +PrototracksToTracks::PrototracksToTracks(Config cfg, Acts::Logging::Level lvl) + : IAlgorithm("PrototracksToTracks", lvl), m_cfg(std::move(cfg)) { + m_outputTracks.initialize(m_cfg.outputTracks); + m_inputMeasurements.initialize(m_cfg.inputMeasurements); + m_inputProtoTracks.initialize(m_cfg.inputProtoTracks); +} + +ProcessCode PrototracksToTracks::execute(const AlgorithmContext& ctx) const { + auto trackContainer = std::make_shared(); + auto mtj = std::make_shared(); + TrackContainer tracks(trackContainer, mtj); + + boost::container::flat_map slMap; + for (const auto& varm : m_inputMeasurements(ctx)) { + std::visit( + [&](const auto& m) { + const auto idx = + m.sourceLink().template get().index(); + slMap.insert(std::pair{idx, m.sourceLink()}); + }, + varm); + } + + const auto& prototracks = m_inputProtoTracks(ctx); + ACTS_DEBUG("Received " << prototracks.size() << " prototracks"); + + float avgSize = 0; + std::size_t minSize = std::numeric_limits::max(); + std::size_t maxSize = 0; + + for (const auto& protoTrack : prototracks) { + if (protoTrack.empty()) { + continue; + } + + avgSize += static_cast(protoTrack.size()); + minSize = std::min(minSize, protoTrack.size()); + maxSize = std::max(maxSize, protoTrack.size()); + + auto track = tracks.makeTrack(); + for (auto idx : protoTrack) { + auto trackStateProxy = + track.appendTrackState(Acts::TrackStatePropMask::None); + trackStateProxy.typeFlags().set(Acts::TrackStateFlag::MeasurementFlag); + trackStateProxy.setUncalibratedSourceLink(slMap.at(idx)); + } + + track.nMeasurements() = static_cast(protoTrack.size()); + track.nHoles() = 0; + track.nOutliers() = 0; + } + + ConstTrackContainer constTracks{ + std::make_shared( + std::move(*trackContainer)), + std::make_shared(std::move(*mtj))}; + + ACTS_DEBUG("Produced " << constTracks.size() << " tracks"); + ACTS_DEBUG("Avg track size: " << avgSize / constTracks.size()); + ACTS_DEBUG("Min track size: " << minSize << ", max track size " << maxSize); + + m_outputTracks(ctx, std::move(constTracks)); + + return ProcessCode::SUCCESS; +} + +} // namespace ActsExamples diff --git a/Examples/Algorithms/Vertexing/include/ActsExamples/Vertexing/AdaptiveMultiVertexFinderAlgorithm.hpp b/Examples/Algorithms/Vertexing/include/ActsExamples/Vertexing/AdaptiveMultiVertexFinderAlgorithm.hpp index 735edcd1b0c..519c9e3e911 100644 --- a/Examples/Algorithms/Vertexing/include/ActsExamples/Vertexing/AdaptiveMultiVertexFinderAlgorithm.hpp +++ b/Examples/Algorithms/Vertexing/include/ActsExamples/Vertexing/AdaptiveMultiVertexFinderAlgorithm.hpp @@ -13,8 +13,8 @@ #include "Acts/EventData/TrackParameters.hpp" #include "Acts/Geometry/GeometryIdentifier.hpp" #include "Acts/MagneticField/MagneticFieldProvider.hpp" -#include "Acts/Propagator/EigenStepper.hpp" #include "Acts/Propagator/Propagator.hpp" +#include "Acts/Propagator/SympyStepper.hpp" #include "Acts/Utilities/Helpers.hpp" #include "Acts/Utilities/Logger.hpp" #include "Acts/Vertexing/AdaptiveGridDensityVertexFinder.hpp" @@ -54,7 +54,7 @@ struct AlgorithmContext; class AdaptiveMultiVertexFinderAlgorithm final : public IAlgorithm { public: - using Propagator = Acts::Propagator>; + using Propagator = Acts::Propagator; using Linearizer = Acts::HelicalTrackLinearizer; using Fitter = Acts::AdaptiveMultiVertexFitter; using Options = Acts::VertexingOptions; diff --git a/Examples/Algorithms/Vertexing/include/ActsExamples/Vertexing/IterativeVertexFinderAlgorithm.hpp b/Examples/Algorithms/Vertexing/include/ActsExamples/Vertexing/IterativeVertexFinderAlgorithm.hpp index 15cbe4cbecf..85410f8ebb3 100644 --- a/Examples/Algorithms/Vertexing/include/ActsExamples/Vertexing/IterativeVertexFinderAlgorithm.hpp +++ b/Examples/Algorithms/Vertexing/include/ActsExamples/Vertexing/IterativeVertexFinderAlgorithm.hpp @@ -15,8 +15,8 @@ #include "Acts/EventData/TrackParameters.hpp" #include "Acts/Geometry/GeometryIdentifier.hpp" #include "Acts/MagneticField/MagneticFieldProvider.hpp" -#include "Acts/Propagator/EigenStepper.hpp" #include "Acts/Propagator/Propagator.hpp" +#include "Acts/Propagator/SympyStepper.hpp" #include "Acts/Utilities/Logger.hpp" #include "Acts/Vertexing/FullBilloirVertexFitter.hpp" #include "Acts/Vertexing/HelicalTrackLinearizer.hpp" @@ -51,7 +51,7 @@ struct AlgorithmContext; class IterativeVertexFinderAlgorithm final : public IAlgorithm { public: - using Propagator = Acts::Propagator>; + using Propagator = Acts::Propagator; using Linearizer = Acts::HelicalTrackLinearizer; using Fitter = Acts::FullBilloirVertexFitter; using Seeder = Acts::TrackDensityVertexFinder; diff --git a/Examples/Algorithms/Vertexing/include/ActsExamples/Vertexing/VertexFitterAlgorithm.hpp b/Examples/Algorithms/Vertexing/include/ActsExamples/Vertexing/VertexFitterAlgorithm.hpp index 578f266865e..4050e542155 100644 --- a/Examples/Algorithms/Vertexing/include/ActsExamples/Vertexing/VertexFitterAlgorithm.hpp +++ b/Examples/Algorithms/Vertexing/include/ActsExamples/Vertexing/VertexFitterAlgorithm.hpp @@ -14,7 +14,6 @@ #include "Acts/EventData/TrackParameters.hpp" #include "Acts/Geometry/GeometryIdentifier.hpp" #include "Acts/MagneticField/MagneticFieldProvider.hpp" -#include "Acts/Propagator/EigenStepper.hpp" #include "Acts/Propagator/Propagator.hpp" #include "Acts/Utilities/Logger.hpp" #include "Acts/Vertexing/FullBilloirVertexFitter.hpp" diff --git a/Examples/Algorithms/Vertexing/src/AdaptiveMultiVertexFinderAlgorithm.cpp b/Examples/Algorithms/Vertexing/src/AdaptiveMultiVertexFinderAlgorithm.cpp index ec933e739f1..0844ed89f1d 100644 --- a/Examples/Algorithms/Vertexing/src/AdaptiveMultiVertexFinderAlgorithm.cpp +++ b/Examples/Algorithms/Vertexing/src/AdaptiveMultiVertexFinderAlgorithm.cpp @@ -11,7 +11,7 @@ #include "Acts/Definitions/Algebra.hpp" #include "Acts/Definitions/Units.hpp" #include "Acts/EventData/GenericBoundTrackParameters.hpp" -#include "Acts/Propagator/EigenStepper.hpp" +#include "Acts/Propagator/SympyStepper.hpp" #include "Acts/Utilities/AnnealingUtility.hpp" #include "Acts/Utilities/Logger.hpp" #include "Acts/Utilities/Result.hpp" @@ -49,8 +49,8 @@ AdaptiveMultiVertexFinderAlgorithm::AdaptiveMultiVertexFinderAlgorithm( : IAlgorithm("AdaptiveMultiVertexFinder", level), m_cfg(config), m_propagator{[&]() { - // Set up EigenStepper - Acts::EigenStepper<> stepper(m_cfg.bField); + // Set up SympyStepper + Acts::SympyStepper stepper(m_cfg.bField); // Set up the propagator return std::make_shared(stepper); diff --git a/Examples/Algorithms/Vertexing/src/IterativeVertexFinderAlgorithm.cpp b/Examples/Algorithms/Vertexing/src/IterativeVertexFinderAlgorithm.cpp index 237a68010a9..7ffa7abdd5f 100644 --- a/Examples/Algorithms/Vertexing/src/IterativeVertexFinderAlgorithm.cpp +++ b/Examples/Algorithms/Vertexing/src/IterativeVertexFinderAlgorithm.cpp @@ -9,7 +9,7 @@ #include "ActsExamples/Vertexing/IterativeVertexFinderAlgorithm.hpp" #include "Acts/Definitions/Algebra.hpp" -#include "Acts/Propagator/EigenStepper.hpp" +#include "Acts/Propagator/SympyStepper.hpp" #include "Acts/Propagator/VoidNavigator.hpp" #include "Acts/Utilities/Logger.hpp" #include "Acts/Utilities/Result.hpp" @@ -68,8 +68,8 @@ ProcessCode IterativeVertexFinderAlgorithm::execute( } } - // Set up EigenStepper - Acts::EigenStepper<> stepper(m_cfg.bField); + // Set up SympyStepper + Acts::SympyStepper stepper(m_cfg.bField); // Set up propagator with void navigator auto propagator = std::make_shared( diff --git a/Examples/Algorithms/Vertexing/src/VertexFitterAlgorithm.cpp b/Examples/Algorithms/Vertexing/src/VertexFitterAlgorithm.cpp index b105ab31880..22b14b62a07 100644 --- a/Examples/Algorithms/Vertexing/src/VertexFitterAlgorithm.cpp +++ b/Examples/Algorithms/Vertexing/src/VertexFitterAlgorithm.cpp @@ -10,7 +10,7 @@ #include "Acts/Definitions/Algebra.hpp" #include "Acts/MagneticField/MagneticFieldProvider.hpp" -#include "Acts/Propagator/EigenStepper.hpp" +#include "Acts/Propagator/SympyStepper.hpp" #include "Acts/Propagator/VoidNavigator.hpp" #include "Acts/Utilities/Result.hpp" #include "Acts/Vertexing/TrackAtVertex.hpp" @@ -42,14 +42,14 @@ ActsExamples::VertexFitterAlgorithm::VertexFitterAlgorithm( ActsExamples::ProcessCode ActsExamples::VertexFitterAlgorithm::execute( const ActsExamples::AlgorithmContext& ctx) const { - using Propagator = Acts::Propagator>; + using Propagator = Acts::Propagator; using PropagatorOptions = Propagator::Options<>; using Linearizer = Acts::HelicalTrackLinearizer; using VertexFitter = Acts::FullBilloirVertexFitter; using VertexFitterOptions = Acts::VertexingOptions; - // Set up EigenStepper - Acts::EigenStepper<> stepper(m_cfg.bField); + // Set up SympyStepper + Acts::SympyStepper stepper(m_cfg.bField); // Setup the propagator with void navigator auto propagator = std::make_shared( diff --git a/Examples/Framework/include/ActsExamples/EventData/IndexSourceLink.hpp b/Examples/Framework/include/ActsExamples/EventData/IndexSourceLink.hpp index 0e532e8ff26..aaaac49d78a 100644 --- a/Examples/Framework/include/ActsExamples/EventData/IndexSourceLink.hpp +++ b/Examples/Framework/include/ActsExamples/EventData/IndexSourceLink.hpp @@ -8,6 +8,7 @@ #pragma once +#include "Acts/Detector/Detector.hpp" #include "Acts/EventData/SourceLink.hpp" #include "Acts/Geometry/TrackingGeometry.hpp" #include "Acts/Surfaces/Surface.hpp" @@ -18,6 +19,8 @@ namespace ActsExamples { +struct IndexSourceLinkSurfaceAccessor; + /// A source link that stores just an index. /// /// This is intentionally kept as barebones as possible. The source link @@ -29,6 +32,8 @@ namespace ActsExamples { /// easily changed without having to also change the source link. class IndexSourceLink final { public: + using SurfaceAccessor = IndexSourceLinkSurfaceAccessor; + /// Construct from geometry identifier and index. constexpr IndexSourceLink(Acts::GeometryIdentifier gid, Index idx) : m_geometryId(gid), m_index(idx) {} @@ -46,15 +51,6 @@ class IndexSourceLink final { Acts::GeometryIdentifier geometryId() const { return m_geometryId; } - struct SurfaceAccessor { - const Acts::TrackingGeometry& trackingGeometry; - - const Acts::Surface* operator()(const Acts::SourceLink& sourceLink) const { - const auto& indexSourceLink = sourceLink.get(); - return trackingGeometry.findSurface(indexSourceLink.geometryId()); - } - }; - private: Acts::GeometryIdentifier m_geometryId; Index m_index = 0; @@ -70,6 +66,28 @@ class IndexSourceLink final { } }; +struct IndexSourceLinkSurfaceAccessor { + const Acts::TrackingGeometry& geometry; + + const Acts::Surface* operator()(const Acts::SourceLink& sourceLink) const { + const auto& indexSourceLink = sourceLink.get(); + return geometry.findSurface(indexSourceLink.geometryId()); + } +}; + +namespace Experimental { + +struct IndexSourceLinkSurfaceAccessor { + const Acts::Experimental::Detector& geometry; + + const Acts::Surface* operator()(const Acts::SourceLink& sourceLink) const { + const auto& indexSourceLink = sourceLink.get(); + return geometry.findSurface(indexSourceLink.geometryId()); + } +}; + +} // namespace Experimental + /// Container of index source links. /// /// Since the source links provide a `.geometryId()` accessor, they can be diff --git a/Examples/Framework/include/ActsExamples/EventData/TruthMatching.hpp b/Examples/Framework/include/ActsExamples/EventData/TruthMatching.hpp index 6dee54ae21c..f83e254421f 100644 --- a/Examples/Framework/include/ActsExamples/EventData/TruthMatching.hpp +++ b/Examples/Framework/include/ActsExamples/EventData/TruthMatching.hpp @@ -46,9 +46,6 @@ struct ParticleMatchEntry { std::uint32_t fakes{}; }; -using ProtoTrackParticleMatching = std::map; -using ParticleProtoTrackMatching = std::map; - using TrackParticleMatching = std::map; using ParticleTrackMatching = std::map; diff --git a/Examples/Framework/src/Validation/ResPlotTool.cpp b/Examples/Framework/src/Validation/ResPlotTool.cpp index 188284b4d4f..3a53fd2877a 100644 --- a/Examples/Framework/src/Validation/ResPlotTool.cpp +++ b/Examples/Framework/src/Validation/ResPlotTool.cpp @@ -178,8 +178,7 @@ void ActsExamples::ResPlotTool::fill( phi(truthParticle.direction()); truthParameter[Acts::BoundIndices::eBoundTheta] = theta(truthParticle.direction()); - truthParameter[Acts::BoundIndices::eBoundQOverP] = - truthParticle.charge() / truthParticle.absoluteMomentum(); + truthParameter[Acts::BoundIndices::eBoundQOverP] = truthParticle.qOverP(); truthParameter[Acts::BoundIndices::eBoundTime] = truthParticle.time(); // get the truth eta and pT diff --git a/Examples/Io/Performance/ActsExamples/Io/Performance/TrackFinderPerformanceWriter.cpp b/Examples/Io/Performance/ActsExamples/Io/Performance/TrackFinderPerformanceWriter.cpp index 7aa1b652376..b8e2f980ec7 100644 --- a/Examples/Io/Performance/ActsExamples/Io/Performance/TrackFinderPerformanceWriter.cpp +++ b/Examples/Io/Performance/ActsExamples/Io/Performance/TrackFinderPerformanceWriter.cpp @@ -37,7 +37,7 @@ struct ActsExamples::TrackFinderPerformanceWriter::Impl { ReadDataHandle inputParticles; ReadDataHandle inputMeasurementParticlesMap; - ReadDataHandle inputProtoTrackParticleMatching; + ReadDataHandle inputTrackParticleMatching; TFile* file = nullptr; @@ -90,11 +90,10 @@ struct ActsExamples::TrackFinderPerformanceWriter::Impl { : cfg(std::move(c)), inputParticles{parent, "InputParticles"}, inputMeasurementParticlesMap{parent, "InputMeasurementParticlesMap"}, - inputProtoTrackParticleMatching{parent, - "InputProtoTrackParticleMatching"}, + inputTrackParticleMatching{parent, "InputTrackParticleMatching"}, _logger(l) { - if (cfg.inputProtoTracks.empty()) { - throw std::invalid_argument("Missing proto tracks input collection"); + if (cfg.inputTracks.empty()) { + throw std::invalid_argument("Missing track input collection"); } if (cfg.inputParticles.empty()) { throw std::invalid_argument("Missing particles input collection"); @@ -102,7 +101,7 @@ struct ActsExamples::TrackFinderPerformanceWriter::Impl { if (cfg.inputMeasurementParticlesMap.empty()) { throw std::invalid_argument("Missing hit-particles map input collection"); } - if (cfg.inputProtoTrackParticleMatching.empty()) { + if (cfg.inputTrackParticleMatching.empty()) { throw std::invalid_argument( "Missing proto track-particle matching input collection"); } @@ -112,8 +111,7 @@ struct ActsExamples::TrackFinderPerformanceWriter::Impl { inputParticles.initialize(cfg.inputParticles); inputMeasurementParticlesMap.initialize(cfg.inputMeasurementParticlesMap); - inputProtoTrackParticleMatching.initialize( - cfg.inputProtoTrackParticleMatching); + inputTrackParticleMatching.initialize(cfg.inputTrackParticleMatching); // the output file can not be given externally since TFile accesses to the // same file from multiple threads are unsafe. @@ -155,10 +153,10 @@ struct ActsExamples::TrackFinderPerformanceWriter::Impl { const Acts::Logger& logger() const { return _logger; } - void write(std::uint64_t eventId, const ProtoTrackContainer& tracks, + void write(std::uint64_t eventId, const TrackContainer& tracks, const SimParticleContainer& particles, const HitParticlesMap& hitParticlesMap, - const ProtoTrackParticleMatching& protoTrackParticleMatching) { + const TrackParticleMatching& trackParticleMatching) { const auto& particleHitsMap = invertIndexMultimap(hitParticlesMap); // How often a particle was reconstructed. @@ -171,15 +169,13 @@ struct ActsExamples::TrackFinderPerformanceWriter::Impl { // write per-track performance measures { std::lock_guard guardTrk(trkMutex); - for (std::size_t itrack = 0; itrack < tracks.size(); ++itrack) { - const auto& track = tracks[itrack]; - + for (auto track : tracks) { // Get the truth-matched particle - auto imatched = protoTrackParticleMatching.find(itrack); - if (imatched == protoTrackParticleMatching.end()) { + auto imatched = trackParticleMatching.find(track.index()); + if (imatched == trackParticleMatching.end()) { ACTS_DEBUG( "No truth particle associated with this proto track, index = " - << itrack); + << track.index()); continue; } const auto& particleMatch = imatched->second; @@ -204,8 +200,8 @@ struct ActsExamples::TrackFinderPerformanceWriter::Impl { } trkEventId = eventId; - trkTrackId = itrack; - trkNumHits = track.size(); + trkTrackId = track.index(); + trkNumHits = track.nMeasurements(); trkNumParticles = particleMatch.contributingParticles.size(); trkParticleId.clear(); trkParticleNumHitsTotal.clear(); @@ -272,7 +268,7 @@ struct ActsExamples::TrackFinderPerformanceWriter::Impl { ActsExamples::TrackFinderPerformanceWriter::TrackFinderPerformanceWriter( ActsExamples::TrackFinderPerformanceWriter::Config config, Acts::Logging::Level level) - : WriterT(config.inputProtoTracks, "TrackFinderPerformanceWriter", level), + : WriterT(config.inputTracks, "TrackFinderPerformanceWriter", level), m_impl(std::make_unique(this, std::move(config), logger())) {} ActsExamples::TrackFinderPerformanceWriter::~TrackFinderPerformanceWriter() = @@ -280,13 +276,12 @@ ActsExamples::TrackFinderPerformanceWriter::~TrackFinderPerformanceWriter() = ActsExamples::ProcessCode ActsExamples::TrackFinderPerformanceWriter::writeT( const ActsExamples::AlgorithmContext& ctx, - const ActsExamples::ProtoTrackContainer& tracks) { + const ActsExamples::TrackContainer& tracks) { const auto& particles = m_impl->inputParticles(ctx); const auto& hitParticlesMap = m_impl->inputMeasurementParticlesMap(ctx); - const auto& protoTrackParticleMatching = - m_impl->inputProtoTrackParticleMatching(ctx); + const auto& trackParticleMatching = m_impl->inputTrackParticleMatching(ctx); m_impl->write(ctx.eventNumber, tracks, particles, hitParticlesMap, - protoTrackParticleMatching); + trackParticleMatching); return ProcessCode::SUCCESS; } diff --git a/Examples/Io/Performance/ActsExamples/Io/Performance/TrackFinderPerformanceWriter.hpp b/Examples/Io/Performance/ActsExamples/Io/Performance/TrackFinderPerformanceWriter.hpp index ee293230f00..481eca1db3f 100644 --- a/Examples/Io/Performance/ActsExamples/Io/Performance/TrackFinderPerformanceWriter.hpp +++ b/Examples/Io/Performance/ActsExamples/Io/Performance/TrackFinderPerformanceWriter.hpp @@ -24,17 +24,17 @@ struct AlgorithmContext; /// /// Only considers the track finding itself, i.e. grouping of hits into tracks, /// and computes relevant per-track and per-particles statistics. -class TrackFinderPerformanceWriter final : public WriterT { +class TrackFinderPerformanceWriter final : public WriterT { public: struct Config { - /// Input reconstructed proto tracks collection. - std::string inputProtoTracks; + /// Input reconstructed track collection. + std::string inputTracks; /// Input particles collection. std::string inputParticles; /// Input hit-particles map collection. std::string inputMeasurementParticlesMap; /// Input proto track-particle matching. - std::string inputProtoTrackParticleMatching; + std::string inputTrackParticleMatching; /// Output filename. std::string filePath = "performance_track_finder.root"; /// Output file mode @@ -59,7 +59,7 @@ class TrackFinderPerformanceWriter final : public WriterT { private: ProcessCode writeT(const AlgorithmContext& ctx, - const ProtoTrackContainer& tracks) override; + const TrackContainer& tracks) override; struct Impl; diff --git a/Examples/Io/Performance/ActsExamples/Io/Performance/TrackFitterPerformanceWriter.cpp b/Examples/Io/Performance/ActsExamples/Io/Performance/TrackFitterPerformanceWriter.cpp index 8e18eb6d02a..3c4c263b533 100644 --- a/Examples/Io/Performance/ActsExamples/Io/Performance/TrackFitterPerformanceWriter.cpp +++ b/Examples/Io/Performance/ActsExamples/Io/Performance/TrackFitterPerformanceWriter.cpp @@ -128,9 +128,15 @@ ActsExamples::ProcessCode ActsExamples::TrackFitterPerformanceWriter::writeT( << track.index() << " tip index = " << track.tipIndex()); continue; } + const auto& particleMatch = imatched->second; + + if (!particleMatch.particle.has_value()) { + ACTS_DEBUG("No truth particle associated with this track."); + continue; + } // Get the barcode of the majority truth particle - SimBarcode majorityParticleId = imatched->second.particle.value(); + SimBarcode majorityParticleId = particleMatch.particle.value(); // Find the truth particle via the barcode auto ip = particles.find(majorityParticleId); diff --git a/Examples/Io/Performance/ActsExamples/Io/Performance/VertexPerformanceWriter.cpp b/Examples/Io/Performance/ActsExamples/Io/Performance/VertexPerformanceWriter.cpp index 99055b51e1c..240b7f7f3b8 100644 --- a/Examples/Io/Performance/ActsExamples/Io/Performance/VertexPerformanceWriter.cpp +++ b/Examples/Io/Performance/ActsExamples/Io/Performance/VertexPerformanceWriter.cpp @@ -12,8 +12,8 @@ #include "Acts/Definitions/TrackParametrization.hpp" #include "Acts/EventData/GenericBoundTrackParameters.hpp" #include "Acts/EventData/TrackParameters.hpp" -#include "Acts/Propagator/EigenStepper.hpp" #include "Acts/Propagator/Propagator.hpp" +#include "Acts/Propagator/SympyStepper.hpp" #include "Acts/Surfaces/PerigeeSurface.hpp" #include "Acts/Surfaces/Surface.hpp" #include "Acts/Utilities/Logger.hpp" @@ -436,8 +436,8 @@ ProcessCode VertexPerformanceWriter::writeT( // We compare the reconstructed momenta to the true momenta at the vertex. For // this, we propagate the reconstructed tracks to the PCA of the true vertex // position. Setting up propagator: - Acts::EigenStepper<> stepper(m_cfg.bField); - using Propagator = Acts::Propagator>; + Acts::SympyStepper stepper(m_cfg.bField); + using Propagator = Acts::Propagator; auto propagator = std::make_shared(stepper); struct ToTruthMatching { diff --git a/Examples/Io/Root/src/RootAthenaDumpReader.cpp b/Examples/Io/Root/src/RootAthenaDumpReader.cpp index f23bc407557..8300237ef9e 100644 --- a/Examples/Io/Root/src/RootAthenaDumpReader.cpp +++ b/Examples/Io/Root/src/RootAthenaDumpReader.cpp @@ -366,7 +366,7 @@ ActsExamples::ProcessCode ActsExamples::RootAthenaDumpReader::read( } else { digiPars.values = {CLloc_direction1[im]}; digiPars.indices = {Acts::eBoundLoc0}; - assert(locCov.size() >= 1); + assert(!locCov.empty()); digiPars.variances = {locCov[0]}; } diff --git a/Examples/Io/Root/src/RootTrackSummaryWriter.cpp b/Examples/Io/Root/src/RootTrackSummaryWriter.cpp index e282a6ec41b..fec57d13827 100644 --- a/Examples/Io/Root/src/RootTrackSummaryWriter.cpp +++ b/Examples/Io/Root/src/RootTrackSummaryWriter.cpp @@ -254,15 +254,15 @@ ProcessCode RootTrackSummaryWriter::writeT(const AlgorithmContext& ctx, const auto& geoID = state.referenceSurface().geometryId(); const auto& volume = geoID.volume(); const auto& layer = geoID.layer(); - if (state.typeFlags().test(Acts::TrackStateFlag::MeasurementFlag)) { - measurementChi2.push_back(state.chi2()); - measurementVolume.push_back(volume); - measurementLayer.push_back(layer); - } if (state.typeFlags().test(Acts::TrackStateFlag::OutlierFlag)) { outlierChi2.push_back(state.chi2()); outlierVolume.push_back(volume); outlierLayer.push_back(layer); + } else if (state.typeFlags().test( + Acts::TrackStateFlag::MeasurementFlag)) { + measurementChi2.push_back(state.chi2()); + measurementVolume.push_back(volume); + measurementLayer.push_back(layer); } } // IDs are stored as double (as the vector of vector of int is not known @@ -425,7 +425,11 @@ ProcessCode RootTrackSummaryWriter::writeT(const AlgorithmContext& ctx, param[Acts::eBoundTime] - t_time}; for (unsigned int i = 0; i < Acts::eBoundSize; ++i) { - pull[i] = res[i] / error[i]; // MARK: fpeMask(FLTINV, 1, #2284) + // MARK: fpeMaskBegin(FLTDIV, 1, #2348) + // MARK: fpeMaskBegin(FLTINV, 1, #2348) + pull[i] = res[i] / error[i]; + // MARK: fpeMaskEnd(FLTINV) + // MARK: fpeMaskEnd(FLTDIV) } } diff --git a/Examples/Python/CMakeLists.txt b/Examples/Python/CMakeLists.txt index d15a8cf8b7f..26d02477550 100644 --- a/Examples/Python/CMakeLists.txt +++ b/Examples/Python/CMakeLists.txt @@ -28,6 +28,7 @@ pybind11_add_module(ActsPythonBindings src/Vertexing.cpp src/AmbiguityResolution.cpp src/EventData.cpp + src/Utilities.cpp ) install(TARGETS ActsPythonBindings DESTINATION ${_python_install_dir}) diff --git a/Examples/Python/python/acts/examples/reconstruction.py b/Examples/Python/python/acts/examples/reconstruction.py index cff5eea0cff..4a903a2b7c9 100644 --- a/Examples/Python/python/acts/examples/reconstruction.py +++ b/Examples/Python/python/acts/examples/reconstruction.py @@ -21,7 +21,7 @@ ParticleSmearingSigmas = namedtuple( "ParticleSmearingSigmas", - ["d0", "d0PtA", "d0PtB", "z0", "z0PtA", "z0PtB", "t0", "phi", "theta", "pRel"], + ["d0", "d0PtA", "d0PtB", "z0", "z0PtA", "z0PtB", "t0", "phi", "theta", "ptRel"], defaults=[None] * 10, ) @@ -220,6 +220,7 @@ def addSeeding( truthSeedRanges: Optional[TruthSeedRanges] = TruthSeedRanges(), particleSmearingSigmas: ParticleSmearingSigmas = ParticleSmearingSigmas(), initialSigmas: Optional[list] = None, + initialSigmaPtRel: Optional[float] = None, initialVarInflation: Optional[list] = None, seedFinderConfigArg: SeedFinderConfigArg = SeedFinderConfigArg(), seedFinderOptionsArg: SeedFinderOptionsArg = SeedFinderOptionsArg(), @@ -252,7 +253,7 @@ def addSeeding( 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, pRel) + particleSmearingSigmas : ParticleSmearingSigmas(d0, d0PtA, d0PtB, z0, z0PtA, z0PtB, t0, phi, theta, ptRel) ParticleSmearing configuration. Defaults specified in Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSmearing.hpp initialSigmas : list @@ -308,14 +309,15 @@ def addSeeding( if seedingAlgorithm == SeedingAlgorithm.TruthSmeared: logger.info("Using smeared truth particles for seeding") addTruthSmearedSeeding( - s, - rnd, - selectedParticles, - particleSmearingSigmas, - initialSigmas, - initialVarInflation, - particleHypothesis, - logLevel, + s=s, + rnd=rnd, + selectedParticles=selectedParticles, + particleSmearingSigmas=particleSmearingSigmas, + initialSigmas=initialSigmas, + initialSigmaPtRel=initialSigmaPtRel, + initialVarInflation=initialVarInflation, + particleHypothesis=particleHypothesis, + logLevel=logLevel, ) else: spacePoints = addSpacePointsMaking( @@ -389,6 +391,7 @@ def addSeeding( magneticField=field, **acts.examples.defaultKWArgs( initialSigmas=initialSigmas, + initialSigmaPtRel=initialSigmaPtRel, initialVarInflation=initialVarInflation, particleHypothesis=particleHypothesis, ), @@ -478,6 +481,7 @@ def addTruthSmearedSeeding( selectedParticles: str, particleSmearingSigmas: ParticleSmearingSigmas, initialSigmas: Optional[List[float]], + initialSigmaPtRel: Optional[float], initialVarInflation: Optional[List[float]], particleHypothesis: Optional[acts.ParticleHypothesis], logLevel: acts.logging.Level = None, @@ -504,8 +508,9 @@ def addTruthSmearedSeeding( sigmaT0=particleSmearingSigmas.t0, sigmaPhi=particleSmearingSigmas.phi, sigmaTheta=particleSmearingSigmas.theta, - sigmaPRel=particleSmearingSigmas.pRel, + sigmaPtRel=particleSmearingSigmas.ptRel, initialSigmas=initialSigmas, + initialSigmaPtRel=initialSigmaPtRel, initialVarInflation=initialVarInflation, particleHypothesis=particleHypothesis, ), @@ -1108,6 +1113,7 @@ def addKalmanTracks( inputMeasurementParticlesMap="measurement_particles_map", outputTrackParticleMatching="kf_track_particle_matching", outputParticleTrackMatching="kf_particle_track_matching", + doubleMatching=True, ) s.addAlgorithm(matchAlg) s.addWhiteboardAlias( @@ -1159,6 +1165,7 @@ def addTruthTrackingGsf( inputMeasurementParticlesMap="measurement_particles_map", outputTrackParticleMatching="gsf_track_particle_matching", outputParticleTrackMatching="gsf_particle_track_matching", + doubleMatching=True, ) s.addAlgorithm(matchAlg) s.addWhiteboardAlias( @@ -1184,6 +1191,7 @@ def addCKFTracks( ] = None, ckfConfig: CkfConfig = CkfConfig(), twoWay: bool = True, + reverseSearch: bool = False, outputDirCsv: Optional[Union[Path, str]] = None, outputDirRoot: Optional[Union[Path, str]] = None, writeTrajectories: bool = True, @@ -1293,6 +1301,7 @@ def addCKFTracks( trackSelectorCfg=trkSelCfg, maxSteps=ckfConfig.maxSteps, twoWay=twoWay, + reverseSearch=reverseSearch, seedDeduplication=ckfConfig.seedDeduplication, stayOnSeed=ckfConfig.stayOnSeed, pixelVolumes=ckfConfig.pixelVolumes, @@ -1304,20 +1313,21 @@ def addCKFTracks( s.addAlgorithm(trackFinder) s.addWhiteboardAlias("tracks", trackFinder.config.outputTracks) - matcher = acts.examples.TrackTruthMatcher( + matchAlg = acts.examples.TrackTruthMatcher( level=customLogLevel(), inputTracks=trackFinder.config.outputTracks, inputParticles="particles_selected", inputMeasurementParticlesMap="measurement_particles_map", outputTrackParticleMatching="ckf_track_particle_matching", outputParticleTrackMatching="ckf_particle_track_matching", + doubleMatching=True, ) - s.addAlgorithm(matcher) + s.addAlgorithm(matchAlg) s.addWhiteboardAlias( - "track_particle_matching", matcher.config.outputTrackParticleMatching + "track_particle_matching", matchAlg.config.outputTrackParticleMatching ) s.addWhiteboardAlias( - "particle_track_matching", matcher.config.outputParticleTrackMatching + "particle_track_matching", matchAlg.config.outputParticleTrackMatching ) addTrackWriters( @@ -1384,6 +1394,7 @@ def addGx2fTracks( inputMeasurementParticlesMap="measurement_particles_map", outputTrackParticleMatching="gx2f_track_particle_matching", outputParticleTrackMatching="gx2f_particle_track_matching", + doubleMatching=True, ) s.addAlgorithm(matchAlg) s.addWhiteboardAlias( @@ -1623,20 +1634,23 @@ def addExaTrkX( s.addAlgorithm(findingAlg) s.addWhiteboardAlias("prototracks", findingAlg.config.outputProtoTracks) - matchAlg = acts.examples.ProtoTrackTruthMatcher( + # TODO convert prototracks to tracks + + matchAlg = acts.examples.TrackTruthMatcher( level=customLogLevel(), inputProtoTracks=findingAlg.config.outputProtoTracks, inputParticles="particles", inputMeasurementParticlesMap="measurement_particles_map", - outputProtoTrackParticleMatching="exatrkx_prototrack_particle_matching", - outputParticleProtoTrackMatching="exatrkx_particle_prototrack_matching", + outputTrackParticleMatching="exatrkx_track_particle_matching", + outputParticleTrackMatching="exatrkx_particle_track_matching", + doubleMatching=True, ) s.addAlgorithm(matchAlg) s.addWhiteboardAlias( - "prototrack_particle_matching", matchAlg.config.outputProtoTrackParticleMatching + "track_particle_matching", matchAlg.config.outputTrackParticleMatching ) s.addWhiteboardAlias( - "particle_prototrack_matching", matchAlg.config.outputParticleProtoTrackMatching + "particle_track_matching", matchAlg.config.outputParticleTrackMatching ) # Write truth track finding / seeding performance @@ -1648,7 +1662,7 @@ def addExaTrkX( # the original selected particles after digitization inputParticles="particles_initial", inputMeasurementParticlesMap="measurement_particles_map", - inputProtoTrackParticleMatching=matchAlg.config.outputProtoTrackParticleMatching, + inputTrackParticleMatching=matchAlg.config.outputTrackParticleMatching, filePath=str(Path(outputDirRoot) / "performance_track_finding.root"), ) ) @@ -1693,6 +1707,7 @@ def addAmbiguityResolution( inputMeasurementParticlesMap="measurement_particles_map", outputTrackParticleMatching="ambi_track_particle_matching", outputParticleTrackMatching="ambi_particle_track_matching", + doubleMatching=True, ) s.addAlgorithm(matchAlg) s.addWhiteboardAlias( diff --git a/Examples/Python/src/ModuleEntry.cpp b/Examples/Python/src/ModuleEntry.cpp index bd585e8ce79..a4411e52114 100644 --- a/Examples/Python/src/ModuleEntry.cpp +++ b/Examples/Python/src/ModuleEntry.cpp @@ -66,6 +66,7 @@ void addTrackFitting(Context& ctx); void addTrackFinding(Context& ctx); void addVertexing(Context& ctx); void addAmbiguityResolution(Context& ctx); +void addUtilities(Context& ctx); // Plugins void addDigitization(Context& ctx); @@ -130,6 +131,7 @@ PYBIND11_MODULE(ActsPythonBindings, m) { addTrackFinding(ctx); addVertexing(ctx); addAmbiguityResolution(ctx); + addUtilities(ctx); addDigitization(ctx); addPythia8(ctx); diff --git a/Examples/Python/src/Output.cpp b/Examples/Python/src/Output.cpp index 767717fb8dd..4dc3902141f 100644 --- a/Examples/Python/src/Output.cpp +++ b/Examples/Python/src/Output.cpp @@ -183,10 +183,10 @@ void addOutput(Context& ctx) { fileMode, treeName); ACTS_PYTHON_DECLARE_WRITER(ActsExamples::TrackFinderPerformanceWriter, mex, - "TrackFinderPerformanceWriter", inputProtoTracks, + "TrackFinderPerformanceWriter", inputTracks, inputParticles, inputMeasurementParticlesMap, - inputProtoTrackParticleMatching, filePath, - fileMode, treeNameTracks, treeNameParticles); + inputTrackParticleMatching, filePath, fileMode, + treeNameTracks, treeNameParticles); ACTS_PYTHON_DECLARE_WRITER(ActsExamples::TrackFitterPerformanceWriter, mex, "TrackFitterPerformanceWriter", inputTracks, diff --git a/Examples/Python/src/Propagation.cpp b/Examples/Python/src/Propagation.cpp index 19982cf0c33..51d5e6d029c 100644 --- a/Examples/Python/src/Propagation.cpp +++ b/Examples/Python/src/Propagation.cpp @@ -1,6 +1,6 @@ // This file is part of the Acts project. // -// Copyright (C) 2021 CERN for the benefit of the Acts project +// Copyright (C) 2021-2024 CERN for the benefit of the Acts project // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this diff --git a/Examples/Python/src/TrackFinding.cpp b/Examples/Python/src/TrackFinding.cpp index 2e82a9585c8..807ba6ee43f 100644 --- a/Examples/Python/src/TrackFinding.cpp +++ b/Examples/Python/src/TrackFinding.cpp @@ -27,12 +27,6 @@ #include "ActsExamples/TrackFinding/SpacePointMaker.hpp" #include "ActsExamples/TrackFinding/TrackFindingAlgorithm.hpp" #include "ActsExamples/TrackFinding/TrackParamsEstimationAlgorithm.hpp" -#include "ActsExamples/Utilities/MeasurementMapSelector.hpp" -#include "ActsExamples/Utilities/PrototracksToSeeds.hpp" -#include "ActsExamples/Utilities/SeedsToPrototracks.hpp" -#include "ActsExamples/Utilities/TracksToParameters.hpp" -#include "ActsExamples/Utilities/TracksToTrajectories.hpp" -#include "ActsExamples/Utilities/TrajectoriesToPrototracks.hpp" #include #include @@ -290,7 +284,7 @@ void addTrackFinding(Context& ctx) { ActsExamples::TrackParamsEstimationAlgorithm, mex, "TrackParamsEstimationAlgorithm", inputSeeds, inputProtoTracks, outputTrackParameters, outputSeeds, outputProtoTracks, trackingGeometry, - magneticField, bFieldMin, initialSigmas, initialSimgaQoverPCoefficients, + magneticField, bFieldMin, initialSigmas, initialSigmaPtRel, initialVarInflation, noTimeVarInflation, particleHypothesis); { @@ -332,6 +326,7 @@ void addTrackFinding(Context& ctx) { ACTS_PYTHON_MEMBER(trackSelectorCfg); ACTS_PYTHON_MEMBER(maxSteps); ACTS_PYTHON_MEMBER(twoWay); + ACTS_PYTHON_MEMBER(reverseSearch); ACTS_PYTHON_MEMBER(seedDeduplication); ACTS_PYTHON_MEMBER(stayOnSeed); ACTS_PYTHON_MEMBER(pixelVolumes); @@ -341,18 +336,6 @@ void addTrackFinding(Context& ctx) { ACTS_PYTHON_STRUCT_END(); } - ACTS_PYTHON_DECLARE_ALGORITHM(ActsExamples::TrajectoriesToPrototracks, mex, - "TrajectoriesToPrototracks", inputTrajectories, - outputProtoTracks); - - ACTS_PYTHON_DECLARE_ALGORITHM(ActsExamples::TracksToTrajectories, mex, - "TracksToTrajectories", inputTracks, - outputTrajectories); - - ACTS_PYTHON_DECLARE_ALGORITHM(ActsExamples::TracksToParameters, mex, - "TracksToParameters", inputTracks, - outputTrackParameters); - { auto constructor = [](const std::vector>>()) .def(py::init(constructor)); } - - ACTS_PYTHON_DECLARE_ALGORITHM(ActsExamples::SeedsToPrototracks, mex, - "SeedsToPrototracks", inputSeeds, - outputProtoTracks); - - ACTS_PYTHON_DECLARE_ALGORITHM( - ActsExamples::PrototracksToSeeds, mex, "PrototracksToSeeds", - inputProtoTracks, inputSpacePoints, outputSeeds, outputProtoTracks); - - ACTS_PYTHON_DECLARE_ALGORITHM( - ActsExamples::MeasurementMapSelector, mex, "MeasurementMapSelector", - inputMeasurementParticleMap, inputSourceLinks, - outputMeasurementParticleMap, geometrySelection); } } // namespace Acts::Python diff --git a/Examples/Python/src/TruthTracking.cpp b/Examples/Python/src/TruthTracking.cpp index 2e6eea303f4..d6e6bd042a6 100644 --- a/Examples/Python/src/TruthTracking.cpp +++ b/Examples/Python/src/TruthTracking.cpp @@ -1,6 +1,6 @@ // This file is part of the Acts project. // -// Copyright (C) 2021 CERN for the benefit of the Acts project +// Copyright (C) 2021-2024 CERN for the benefit of the Acts project // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -11,7 +11,6 @@ #include "Acts/Utilities/TypeTraits.hpp" #include "ActsExamples/TruthTracking/ParticleSelector.hpp" #include "ActsExamples/TruthTracking/ParticleSmearing.hpp" -#include "ActsExamples/TruthTracking/ProtoTrackTruthMatcher.hpp" #include "ActsExamples/TruthTracking/TrackModifier.hpp" #include "ActsExamples/TruthTracking/TrackParameterSelector.hpp" #include "ActsExamples/TruthTracking/TrackTruthMatcher.hpp" @@ -92,8 +91,9 @@ void addTruthTracking(Context& ctx) { ACTS_PYTHON_DECLARE_ALGORITHM( ActsExamples::ParticleSmearing, mex, "ParticleSmearing", inputParticles, outputTrackParameters, sigmaD0, sigmaD0PtA, sigmaD0PtB, sigmaZ0, - sigmaZ0PtA, sigmaZ0PtB, sigmaT0, sigmaPhi, sigmaTheta, sigmaPRel, - initialSigmas, initialVarInflation, particleHypothesis, randomNumbers); + sigmaZ0PtA, sigmaZ0PtB, sigmaT0, sigmaPhi, sigmaTheta, sigmaPtRel, + initialSigmas, initialSigmaPtRel, initialVarInflation, particleHypothesis, + randomNumbers); { using Alg = ActsExamples::ParticleSelector; @@ -208,12 +208,6 @@ void addTruthTracking(Context& ctx) { ActsExamples::TrackTruthMatcher, mex, "TrackTruthMatcher", inputTracks, inputParticles, inputMeasurementParticlesMap, outputTrackParticleMatching, outputParticleTrackMatching, matchingRatio, doubleMatching); - - ACTS_PYTHON_DECLARE_ALGORITHM( - ActsExamples::ProtoTrackTruthMatcher, mex, "ProtoTrackTruthMatcher", - inputProtoTracks, inputParticles, inputMeasurementParticlesMap, - outputProtoTrackParticleMatching, outputParticleProtoTrackMatching, - matchingRatio, doubleMatching); } } // namespace Acts::Python diff --git a/Examples/Python/src/Utilities.cpp b/Examples/Python/src/Utilities.cpp new file mode 100644 index 00000000000..05852a03645 --- /dev/null +++ b/Examples/Python/src/Utilities.cpp @@ -0,0 +1,62 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2024 CERN for the benefit of the Acts project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include "Acts/Plugins/Python/Utilities.hpp" + +#include "ActsExamples/Utilities/MeasurementMapSelector.hpp" +#include "ActsExamples/Utilities/ProtoTracksToTracks.hpp" +#include "ActsExamples/Utilities/PrototracksToSeeds.hpp" +#include "ActsExamples/Utilities/SeedsToPrototracks.hpp" +#include "ActsExamples/Utilities/TracksToParameters.hpp" +#include "ActsExamples/Utilities/TracksToTrajectories.hpp" +#include "ActsExamples/Utilities/TrajectoriesToPrototracks.hpp" + +#include +#include + +namespace py = pybind11; + +using namespace ActsExamples; +using namespace Acts; + +namespace Acts::Python { + +void addUtilities(Context& ctx) { + auto [m, mex] = ctx.get("main", "examples"); + + ACTS_PYTHON_DECLARE_ALGORITHM(ActsExamples::TrajectoriesToPrototracks, mex, + "TrajectoriesToPrototracks", inputTrajectories, + outputProtoTracks); + + ACTS_PYTHON_DECLARE_ALGORITHM(ActsExamples::TracksToTrajectories, mex, + "TracksToTrajectories", inputTracks, + outputTrajectories); + + ACTS_PYTHON_DECLARE_ALGORITHM(ActsExamples::TracksToParameters, mex, + "TracksToParameters", inputTracks, + outputTrackParameters); + + ACTS_PYTHON_DECLARE_ALGORITHM(ActsExamples::SeedsToPrototracks, mex, + "SeedsToPrototracks", inputSeeds, + outputProtoTracks); + + ACTS_PYTHON_DECLARE_ALGORITHM( + ActsExamples::PrototracksToSeeds, mex, "PrototracksToSeeds", + inputProtoTracks, inputSpacePoints, outputSeeds, outputProtoTracks); + + ACTS_PYTHON_DECLARE_ALGORITHM( + ActsExamples::MeasurementMapSelector, mex, "MeasurementMapSelector", + inputMeasurementParticleMap, inputSourceLinks, + outputMeasurementParticleMap, geometrySelection); + + ACTS_PYTHON_DECLARE_ALGORITHM(ActsExamples::PrototracksToTracks, mex, + "PrototracksToTracks", inputMeasurements, + inputProtoTracks, outputTracks); +} + +} // namespace Acts::Python diff --git a/Examples/Python/tests/root_file_hashes.txt b/Examples/Python/tests/root_file_hashes.txt index 082d537dc98..313275c994a 100644 --- a/Examples/Python/tests/root_file_hashes.txt +++ b/Examples/Python/tests/root_file_hashes.txt @@ -29,10 +29,10 @@ test_truth_tracking_kalman[odd-0.0]__performance_track_finder.root: 39aec6316cce test_truth_tracking_kalman[odd-1000.0]__trackstates_fitter.root: 72c79be1458c4f9c9a1661778c900f0875d257f2d391c4183a698825448919a1 test_truth_tracking_kalman[odd-1000.0]__tracksummary_fitter.root: a53253b509b5779a5d856f8c09d76a499b217b55ba4b0e52d9076ffad726463f test_truth_tracking_kalman[odd-1000.0]__performance_track_finder.root: 39aec6316cceb90e314e16b02947faa691c18f57c3a851a25e547a8fc05a4593 -test_truth_tracking_gsf[generic]__trackstates_gsf.root: 07129b8de01647382be66fe381103698175f4d232b5988e349d8d3c6d7cc0ba5 -test_truth_tracking_gsf[generic]__tracksummary_gsf.root: 618a47def602f4a9b387ed2c7eb0c33aa26ca91c0e177ca0fcef67c092d791f0 -test_truth_tracking_gsf[odd]__trackstates_gsf.root: b59fbc111cc8597fc400420c0223b6b84ba63a1f0ac2ac093293638f874b3017 -test_truth_tracking_gsf[odd]__tracksummary_gsf.root: ee806a7cddbc4bd41a74dceead569762954e8161af221ad60d637c6264e41752 +test_truth_tracking_gsf[generic]__trackstates_gsf.root: 1466671bee7b7cfffe90459d9aef316dcee104e6c32a2df4f2f11ea9f12ddc14 +test_truth_tracking_gsf[generic]__tracksummary_gsf.root: b698e3d21eacc34fc8b0ce1d3fbe07405a4b8b549e07f0160573e64c3b401f04 +test_truth_tracking_gsf[odd]__trackstates_gsf.root: 194198c9c9657b02192e573ba9969230663f179104e32e180101ffcd677b4745 +test_truth_tracking_gsf[odd]__tracksummary_gsf.root: 80e60784d4d6eabe734f6fc1ffe04aefa0276cf8798430c590a06f40a07a484f test_particle_gun__particles.root: 5fe7dda2933ee6b9615b064d192322fe07831133cd998e5ed99a3b992b713a10 test_material_mapping__material-map_tracks.root: 938b1a855369e9304401cb10d2751df3fd7acf32a2573f2057eb1691cd94edf3 test_material_mapping__propagation-material.root: d081c2c54403941bc7876fa552425eef29b496883dcdaab01113462895d0905e @@ -43,23 +43,23 @@ test_digitization_example[geometric]__measurements.root: 85efa861d14207fd7d1798d test_digitization_example_input[smeared]__particles.root: 5fe7dda2933ee6b9615b064d192322fe07831133cd998e5ed99a3b992b713a10 test_digitization_example_input[smeared]__measurements.root: 243c2f69b7b0db9dbeaa7494d4ea0f3dd1691dc90f16e10df6c0491ff4dc7d62 test_digitization_example_input[geometric]__particles.root: 5fe7dda2933ee6b9615b064d192322fe07831133cd998e5ed99a3b992b713a10 -test_digitization_example_input[geometric]__measurements.root: 393e5d0278dceedb9be0efccafc5fceb024e2ef8ed919f351910c60606399f88 -test_ckf_tracks_example[generic-full_seeding]__trackstates_ckf.root: fa3460d2bed49028a9b6c0b3553486b8fddc979d6e508a1813780b4ea1a04f02 -test_ckf_tracks_example[generic-full_seeding]__tracksummary_ckf.root: b8ddfc25b013ec181e2a9f77925b86e57528140ccb6250696a9869272e1afa10 +test_digitization_example_input[geometric]__measurements.root: 63ec81635979058fb8976f94455bf490cf92b7b142c4a05cc39de6225f5de2fb +test_ckf_tracks_example[generic-full_seeding]__trackstates_ckf.root: d17d81d46bc2fd8d62868530dbc54762df4409ad35df1baeb11c33889e9933e8 +test_ckf_tracks_example[generic-full_seeding]__tracksummary_ckf.root: 112943712fa29d70a1396cd0d842027e95e77554e95b19d97db74e27acd22bbc test_ckf_tracks_example[generic-full_seeding]__performance_seeding_trees.root: 0e0676ffafdb27112fbda50d1cf627859fa745760f98073261dcf6db3f2f991e -test_ckf_tracks_example[generic-truth_estimated]__trackstates_ckf.root: e3a3412df2169c321ce76454e5c9fa21563d3abe8b0743170d7003462879b6f3 -test_ckf_tracks_example[generic-truth_estimated]__tracksummary_ckf.root: 2fab4f59cc4c919cb2449b1a335701d2a417782dfa38b233f68495c002308a64 +test_ckf_tracks_example[generic-truth_estimated]__trackstates_ckf.root: 7679bbbdb47abcbee87048ce373966d5f58bab6b04312844ede351ea653a573f +test_ckf_tracks_example[generic-truth_estimated]__tracksummary_ckf.root: 0df341fc0833c33474cd8835d2e3318b6bd492a07b3b4ae5aa74068593679854 test_ckf_tracks_example[generic-truth_estimated]__performance_seeding.root: 1facb05c066221f6361b61f015cdf0918e94d9f3fce2269ec7b6a4dffeb2bc7e -test_ckf_tracks_example[generic-truth_smeared]__trackstates_ckf.root: 7b45ed4c0079d15128e62b0068810c23545f5965188c7b9a3cb6768a0ad5d4b8 -test_ckf_tracks_example[generic-truth_smeared]__tracksummary_ckf.root: 472cd838f89f11498211f6f4d4412a21992fa1d76a511f3299e50cc5cb1d5ea3 -test_ckf_tracks_example[odd-full_seeding]__trackstates_ckf.root: b746ecc33657442f2c0a7094907cf75cf65cdfeb960adc64fd2c57478c5ce3b1 -test_ckf_tracks_example[odd-full_seeding]__tracksummary_ckf.root: 331758a5c689733302eda21571ced8b3c3c513834f276ab31c0872f35e646d34 +test_ckf_tracks_example[generic-truth_smeared]__trackstates_ckf.root: b9fe81e4d9084ad91790de2106fe7cb94a5a5942fed3a7e34250ef667a72f39b +test_ckf_tracks_example[generic-truth_smeared]__tracksummary_ckf.root: a1b9f1bffff115e165f4a43de480931f6a7bd0fcbcd6c827b9baa339f8e823c9 +test_ckf_tracks_example[odd-full_seeding]__trackstates_ckf.root: 935359233aa503a077faf2394ba988d0da97ea5db4f6d3294a95fb93c5625c68 +test_ckf_tracks_example[odd-full_seeding]__tracksummary_ckf.root: 59537c52d23a77dbed9230c7b92cf653f7592c72fb882e8a24a2b33f1d27019e test_ckf_tracks_example[odd-full_seeding]__performance_seeding_trees.root: 43c58577aafe07645e5660c4f43904efadf91d8cda45c5c04c248bbe0f59814f -test_ckf_tracks_example[odd-truth_estimated]__trackstates_ckf.root: 8d6f6092c3de68bfc67451684de0e1d81902f718e852459de8dc7b6701d97ab8 -test_ckf_tracks_example[odd-truth_estimated]__tracksummary_ckf.root: 5611ea2a2aef8fcd3c159acddf011d62bc5d4a8b8a04e87941f5044dadeaac80 +test_ckf_tracks_example[odd-truth_estimated]__trackstates_ckf.root: 4c80c03534ac82960808fad88d38c2d9f794320fbebd494e310208300def01e9 +test_ckf_tracks_example[odd-truth_estimated]__tracksummary_ckf.root: 3a092423e717b1fe76f78f6b95eb6df67648a196e8c4da32158061d4bc490578 test_ckf_tracks_example[odd-truth_estimated]__performance_seeding.root: 1a36b7017e59f1c08602ef3c2cb0483c51df248f112e3780c66594110719c575 -test_ckf_tracks_example[odd-truth_smeared]__trackstates_ckf.root: 9dbd4b23e05914b50c981d9d0f73314cc8527b80d26b238a385dbdeec45c87e5 -test_ckf_tracks_example[odd-truth_smeared]__tracksummary_ckf.root: e2aaf2bdafb5757698ee7a1db542c4612ab35ea305dbfb7908dc204974a85ffe +test_ckf_tracks_example[odd-truth_smeared]__trackstates_ckf.root: c3e59a27c1ec5d2187b390373ff80e4f61cf2ead9916c1456ccb60ab4c52b4f6 +test_ckf_tracks_example[odd-truth_smeared]__tracksummary_ckf.root: b92e4760aaa6e152116dae071f6c64efee20b8612188a173d88fc02c82ea85cf 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 @@ -85,19 +85,23 @@ test_exatrkx[cpu-torch]__performance_track_finding.root: 36b3045589c4c17c038dbc8 test_exatrkx[gpu-onnx]__performance_track_finding.root: 9090de10ffb1489d3f1993e2a3081a3038227e3e5c453e98a9a4f33ea3d6d817 test_exatrkx[gpu-torch]__performance_track_finding.root: 36b3045589c4c17c038dbc87943366f4af4440f7eea6887afb763871ac149b05 test_ML_Ambiguity_Solver__performance_ambiML.root: 284ff5c3a08c0b810938e4ac2f8ba8fe2babb17d4c202b624ed69fff731a9006 -test_truth_tracking_kalman[generic-False-0.0]__trackstates_fitter.root: 08f4812a640256e09c693fe19ba40308d168a917f463ef2706002a268d903a26 -test_truth_tracking_kalman[generic-False-0.0]__tracksummary_fitter.root: bedccd1c0f3df8a9e037792eead3b9243c0ce671a29838740ad1816054c2cbd0 -test_truth_tracking_kalman[generic-False-1000.0]__trackstates_fitter.root: 257258fcac29f72a02dd314504bc9ffd7b9a11ff0a70db719693b7d0cea9d23d -test_truth_tracking_kalman[generic-False-1000.0]__tracksummary_fitter.root: f1ebb0734350ab0857352987a66f6c77db67227a54a73d3524ccdef5e80bf952 -test_truth_tracking_kalman[generic-True-0.0]__trackstates_fitter.root: 08f4812a640256e09c693fe19ba40308d168a917f463ef2706002a268d903a26 -test_truth_tracking_kalman[generic-True-0.0]__tracksummary_fitter.root: bedccd1c0f3df8a9e037792eead3b9243c0ce671a29838740ad1816054c2cbd0 -test_truth_tracking_kalman[generic-True-1000.0]__trackstates_fitter.root: 257258fcac29f72a02dd314504bc9ffd7b9a11ff0a70db719693b7d0cea9d23d -test_truth_tracking_kalman[generic-True-1000.0]__tracksummary_fitter.root: f1ebb0734350ab0857352987a66f6c77db67227a54a73d3524ccdef5e80bf952 -test_truth_tracking_kalman[odd-False-0.0]__trackstates_fitter.root: 774a5689d1d7de09d81943e4ceee0b786ae62daa5231757e3bf1ae520de5e6ef -test_truth_tracking_kalman[odd-False-0.0]__tracksummary_fitter.root: a7d6e0710b32219afc8879b4976c9bd388c4adb47b513b1cc8d0a3aaeba5c10b -test_truth_tracking_kalman[odd-False-1000.0]__trackstates_fitter.root: 75427e63ccf720e9ca8c5aa91b894b42ad91d0f474125fb7157008691c8935f0 -test_truth_tracking_kalman[odd-False-1000.0]__tracksummary_fitter.root: 3488f9e188faf706b312e0156a5d6c4a871163ed46cd6f35a1dc90f11aa3e93e -test_truth_tracking_kalman[odd-True-0.0]__trackstates_fitter.root: 774a5689d1d7de09d81943e4ceee0b786ae62daa5231757e3bf1ae520de5e6ef -test_truth_tracking_kalman[odd-True-0.0]__tracksummary_fitter.root: a7d6e0710b32219afc8879b4976c9bd388c4adb47b513b1cc8d0a3aaeba5c10b -test_truth_tracking_kalman[odd-True-1000.0]__trackstates_fitter.root: 75427e63ccf720e9ca8c5aa91b894b42ad91d0f474125fb7157008691c8935f0 -test_truth_tracking_kalman[odd-True-1000.0]__tracksummary_fitter.root: 3488f9e188faf706b312e0156a5d6c4a871163ed46cd6f35a1dc90f11aa3e93e +test_truth_tracking_kalman[generic-False-0.0]__trackstates_fitter.root: a87b908ee14a3de3e8f894cb69dc011e23ec2de6fd92a71a91c367f18a7934f6 +test_truth_tracking_kalman[generic-False-0.0]__tracksummary_fitter.root: bf46a89e429fa77a380d5ee48babb8af2044196eff872825e84c0d4401357114 +test_truth_tracking_kalman[generic-False-1000.0]__trackstates_fitter.root: 5b945782c1ff59c7c30d3d2a23992292735bc3da27da6424309da9c9e9660322 +test_truth_tracking_kalman[generic-False-1000.0]__tracksummary_fitter.root: 055a74d2747d360398cc846cc2791204491528896de78cca66b188e3ff530dc1 +test_truth_tracking_kalman[generic-True-0.0]__trackstates_fitter.root: a87b908ee14a3de3e8f894cb69dc011e23ec2de6fd92a71a91c367f18a7934f6 +test_truth_tracking_kalman[generic-True-0.0]__tracksummary_fitter.root: bf46a89e429fa77a380d5ee48babb8af2044196eff872825e84c0d4401357114 +test_truth_tracking_kalman[generic-True-1000.0]__trackstates_fitter.root: 5b945782c1ff59c7c30d3d2a23992292735bc3da27da6424309da9c9e9660322 +test_truth_tracking_kalman[generic-True-1000.0]__tracksummary_fitter.root: 055a74d2747d360398cc846cc2791204491528896de78cca66b188e3ff530dc1 +test_truth_tracking_kalman[odd-False-0.0]__trackstates_fitter.root: 6e4a34638a4d76607597db1e02525f6c6a386ca44727cae255a0aa0c2b588c7f +test_truth_tracking_kalman[odd-False-0.0]__tracksummary_fitter.root: a45dbd0b6d221ec1b153f6e90d84601fe7a799134604c63be8e94bf8cd22af43 +test_truth_tracking_kalman[odd-False-1000.0]__trackstates_fitter.root: 7e0b19d1f8c818269925b95817b9c92c68af3b841fdbd21560aa55688ddec786 +test_truth_tracking_kalman[odd-False-1000.0]__tracksummary_fitter.root: 15a542955428dec0776c8317a33b7ef6c14858888ffc7406b00ac7044694b137 +test_truth_tracking_kalman[odd-True-0.0]__trackstates_fitter.root: 6e4a34638a4d76607597db1e02525f6c6a386ca44727cae255a0aa0c2b588c7f +test_truth_tracking_kalman[odd-True-0.0]__tracksummary_fitter.root: a45dbd0b6d221ec1b153f6e90d84601fe7a799134604c63be8e94bf8cd22af43 +test_truth_tracking_kalman[odd-True-1000.0]__trackstates_fitter.root: 7e0b19d1f8c818269925b95817b9c92c68af3b841fdbd21560aa55688ddec786 +test_truth_tracking_kalman[odd-True-1000.0]__tracksummary_fitter.root: 15a542955428dec0776c8317a33b7ef6c14858888ffc7406b00ac7044694b137 +test_refitting[odd]__trackstates_gsf_refit.root: 1071ab66ec9a7d1ddddfb12beac8da6e9c489242f5fe2aee238b88aee0744823 +test_refitting[odd]__tracksummary_gsf_refit.root: 16951808df6363d2acb99e385aec35ad723b634403ca0724a552ae9d3a2ae237 +test_refitting[generic]__trackstates_gsf_refit.root: dbad2648b761e021bd21296755a0c73230da6e4796b306f6ac59424c40c9b80b +test_refitting[generic]__tracksummary_gsf_refit.root: bf46a89e429fa77a380d5ee48babb8af2044196eff872825e84c0d4401357114 diff --git a/Examples/Python/tests/test_examples.py b/Examples/Python/tests/test_examples.py index 032ee122138..bcb6b9695f2 100644 --- a/Examples/Python/tests/test_examples.py +++ b/Examples/Python/tests/test_examples.py @@ -628,12 +628,15 @@ def test_truth_tracking_gsf(tmp_path, assert_root_hash, detector_config): assert_root_hash(fn, fp) -def test_refitting(tmp_path, detector_config): +def test_refitting(tmp_path, detector_config, assert_root_hash): from truth_tracking_gsf_refitting import runRefittingGsf field = acts.ConstantBField(acts.Vector3(0, 0, 2 * u.T)) - seq = Sequencer(events=1, numThreads=1) + seq = Sequencer( + events=10, + numThreads=1, + ) # Only check if it runs without errors right known # Changes in fitter behaviour should be caught by other tests @@ -644,6 +647,18 @@ def test_refitting(tmp_path, detector_config): s=seq, ).run() + root_files = [ + ("trackstates_gsf_refit.root", "trackstates"), + ("tracksummary_gsf_refit.root", "tracksummary"), + ] + + for fn, tn in root_files: + fp = tmp_path / fn + assert fp.exists() + assert fp.stat().st_size > 1024 + if tn is not None: + assert_root_hash(fn, fp) + def test_particle_gun(tmp_path, assert_root_hash): from particle_gun import runParticleGun @@ -1044,7 +1059,7 @@ def test_ckf_tracks_example( field = acts.ConstantBField(acts.Vector3(0, 0, 2 * u.T)) events = 100 - s = Sequencer(events=events, numThreads=1) # Digitization is not thread-safe + s = Sequencer(events=events, numThreads=-1) root_files = [ ( diff --git a/Examples/Scripts/Optimization/ckf.py b/Examples/Scripts/Optimization/ckf.py index 6c655e46ffe..bf927850ecc 100755 --- a/Examples/Scripts/Optimization/ckf.py +++ b/Examples/Scripts/Optimization/ckf.py @@ -184,7 +184,19 @@ def runCKFTracks( trackingGeometry, field, TruthSeedRanges(pt=(500.0 * u.MeV, None), nHits=(9, None)), - ParticleSmearingSigmas(pRel=0.01), # only used by SeedingAlgorithm.TruthSmeared + ParticleSmearingSigmas( # only used by SeedingAlgorithm.TruthSmeared + # zero eveything so the CKF has a chance to find the measurements + d0=0, + d0PtA=0, + d0PtB=0, + z0=0, + z0PtA=0, + z0PtB=0, + t0=0, + phi=0, + theta=0, + ptRel=0, + ), SeedFinderConfigArg( r=(None, 200 * u.mm), # rMin=default, 33mm deltaR=(DeltaRMin * u.mm, DeltaRMax * u.mm), @@ -209,6 +221,16 @@ def runCKFTracks( else SeedingAlgorithm.Default ) ), + initialSigmas=[ + 1 * u.mm, + 1 * u.mm, + 1 * u.degree, + 1 * u.degree, + 0.1 * u.e / u.GeV, + 1 * u.ns, + ], + initialSigmaPtRel=0.01, + initialVarInflation=[1.0] * 6, geoSelectionConfigFile=geometrySelection, outputDirRoot=outputDir, rnd=rnd, # only used by SeedingAlgorithm.TruthSmeared diff --git a/Examples/Scripts/Python/ckf_tracks.py b/Examples/Scripts/Python/ckf_tracks.py index 7d96d4816a1..b5b7d21d28c 100755 --- a/Examples/Scripts/Python/ckf_tracks.py +++ b/Examples/Scripts/Python/ckf_tracks.py @@ -23,6 +23,7 @@ def runCKFTracks( ): from acts.examples.simulation import ( addParticleGun, + MomentumConfig, EtaConfig, PhiConfig, ParticleConfig, @@ -39,6 +40,8 @@ def runCKFTracks( SeedingAlgorithm, TruthEstimatedSeedingAlgorithmConfigArg, addCKFTracks, + TrackSelectorConfig, + CkfConfig, ) s = s or acts.examples.Sequencer( @@ -52,9 +55,10 @@ def runCKFTracks( if inputParticlePath is None: addParticleGun( s, - EtaConfig(-2.0, 2.0), - ParticleConfig(4, acts.PdgParticle.eMuon, True), + MomentumConfig(1 * u.GeV, 10 * u.GeV, transverse=True), + EtaConfig(-2.0, 2.0, uniform=True), PhiConfig(0.0, 360.0 * u.degree), + ParticleConfig(4, acts.PdgParticle.eMuon, randomizeCharge=True), multiplicity=2, rnd=rnd, ) @@ -91,7 +95,19 @@ def runCKFTracks( trackingGeometry, field, TruthSeedRanges(pt=(500.0 * u.MeV, None), nHits=(9, None)), - ParticleSmearingSigmas(pRel=0.01), # only used by SeedingAlgorithm.TruthSmeared + ParticleSmearingSigmas( # only used by SeedingAlgorithm.TruthSmeared + # zero eveything so the CKF has a chance to find the measurements + d0=0, + d0PtA=0, + d0PtB=0, + z0=0, + z0PtA=0, + z0PtB=0, + t0=0, + phi=0, + theta=0, + ptRel=0, + ), SeedFinderConfigArg( r=(None, 200 * u.mm), # rMin=default, 33mm deltaR=(1 * u.mm, 60 * u.mm), @@ -114,6 +130,16 @@ def runCKFTracks( else SeedingAlgorithm.Default ) ), + initialSigmas=[ + 1 * u.mm, + 1 * u.mm, + 1 * u.degree, + 1 * u.degree, + 0.1 * u.e / u.GeV, + 1 * u.ns, + ], + initialSigmaPtRel=0.01, + initialVarInflation=[1.0] * 6, geoSelectionConfigFile=geometrySelection, outputDirRoot=outputDir, rnd=rnd, # only used by SeedingAlgorithm.TruthSmeared @@ -123,6 +149,20 @@ def runCKFTracks( s, trackingGeometry, field, + TrackSelectorConfig( + pt=(500 * u.MeV, None), + absEta=(None, 3.0), + loc0=(-4.0 * u.mm, 4.0 * u.mm), + nMeasurementsMin=7, + maxHoles=2, + maxOutliers=2, + ), + CkfConfig( + chi2CutOff=15, + numMeasurementsCutOff=10, + seedDeduplication=True if not truthSmearedSeeded else False, + stayOnSeed=True if not truthSmearedSeeded else False, + ), outputDirRoot=outputDir, outputDirCsv=outputDir / "csv" if outputCsv else None, ) diff --git a/Examples/Scripts/Python/full_chain_itk.py b/Examples/Scripts/Python/full_chain_itk.py index 366096b5f72..6231127096c 100755 --- a/Examples/Scripts/Python/full_chain_itk.py +++ b/Examples/Scripts/Python/full_chain_itk.py @@ -102,9 +102,10 @@ 1 * u.mm, 1 * u.degree, 1 * u.degree, - 0.1 / u.GeV, + 0.1 * u.e / u.GeV, 1 * u.ns, ], + initialSigmaPtRel=0.1, initialVarInflation=[1.0] * 6, geoSelectionConfigFile=geo_dir / "itk-hgtd/geoSelection-ITk.json", outputDirRoot=outputDir, diff --git a/Examples/Scripts/Python/full_chain_odd.py b/Examples/Scripts/Python/full_chain_odd.py index eba903e7d2b..0c6b5fd1f38 100755 --- a/Examples/Scripts/Python/full_chain_odd.py +++ b/Examples/Scripts/Python/full_chain_odd.py @@ -318,6 +318,16 @@ if args.ttbar else TruthSeedRanges() ), + initialSigmas=[ + 1 * u.mm, + 1 * u.mm, + 1 * u.degree, + 1 * u.degree, + 0.1 * u.e / u.GeV, + 1 * u.ns, + ], + initialSigmaPtRel=0.1, + initialVarInflation=[1.0] * 6, geoSelectionConfigFile=oddSeedingSel, outputDirRoot=outputDir if args.output_root else None, outputDirCsv=outputDir if args.output_csv else None, @@ -348,6 +358,8 @@ maxOutliers=2, ), CkfConfig( + chi2CutOff=15, + numMeasurementsCutOff=10, seedDeduplication=True, stayOnSeed=True, pixelVolumes={16, 17, 18}, diff --git a/Examples/Scripts/Python/seeding.py b/Examples/Scripts/Python/seeding.py index 49054db9c48..076262fd194 100755 --- a/Examples/Scripts/Python/seeding.py +++ b/Examples/Scripts/Python/seeding.py @@ -100,7 +100,6 @@ def runSeeding( from acts.examples.reconstruction import ( addSeeding, TruthSeedRanges, - ParticleSmearingSigmas, SeedFinderConfigArg, SeedFinderOptionsArg, ) @@ -110,7 +109,6 @@ def runSeeding( trackingGeometry, field, TruthSeedRanges(pt=(1.0 * u.GeV, None), eta=(-2.5, 2.5), nHits=(9, None)), - ParticleSmearingSigmas(pRel=0.01), # only used by SeedingAlgorithm.TruthSmeared 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 9c9690ecbdd..bd95153c1ff 100755 --- a/Examples/Scripts/Python/truth_tracking_gsf.py +++ b/Examples/Scripts/Python/truth_tracking_gsf.py @@ -96,7 +96,6 @@ def runTruthTrackingGsf( seedingAlgorithm=SeedingAlgorithm.TruthSmeared, particleHypothesis=acts.ParticleHypothesis.electron, truthSeedRanges=TruthSeedRanges( - pt=(1 * u.GeV, None), nHits=(7, None), ), ) diff --git a/Examples/Scripts/Python/truth_tracking_gsf_refitting.py b/Examples/Scripts/Python/truth_tracking_gsf_refitting.py index e1a3003fc26..d16784cefcb 100755 --- a/Examples/Scripts/Python/truth_tracking_gsf_refitting.py +++ b/Examples/Scripts/Python/truth_tracking_gsf_refitting.py @@ -48,6 +48,39 @@ def runRefittingGsf( ) ) + s.addAlgorithm( + acts.examples.TrackTruthMatcher( + level=acts.logging.INFO, + inputTracks="gsf_tracks", + inputParticles="truth_seeds_selected", + inputMeasurementParticlesMap="measurement_particles_map", + outputTrackParticleMatching="refit_track_particle_matching", + outputParticleTrackMatching="refit_particle_track_matching", + ) + ) + + s.addWriter( + acts.examples.RootTrackStatesWriter( + level=acts.logging.INFO, + inputTracks="gsf_tracks", + inputParticles="truth_seeds_selected", + inputTrackParticleMatching="refit_track_particle_matching", + inputSimHits="simhits", + inputMeasurementSimHitsMap="measurement_simhits_map", + filePath=str(outputDir / "trackstates_gsf_refit.root"), + ) + ) + + s.addWriter( + acts.examples.RootTrackSummaryWriter( + level=acts.logging.INFO, + inputTracks="tracks", + inputParticles="truth_seeds_selected", + inputTrackParticleMatching="refit_track_particle_matching", + filePath=str(outputDir / "tracksummary_gsf_refit.root"), + ) + ) + s.addWriter( acts.examples.TrackFitterPerformanceWriter( level=acts.logging.INFO, diff --git a/Examples/Scripts/Python/truth_tracking_gx2f.py b/Examples/Scripts/Python/truth_tracking_gx2f.py index d6c9505b4b3..6ef9cceecb8 100644 --- a/Examples/Scripts/Python/truth_tracking_gx2f.py +++ b/Examples/Scripts/Python/truth_tracking_gx2f.py @@ -44,7 +44,7 @@ def runTruthTrackingGx2f( addParticleGun( s, ParticleConfig(num=1, pdg=acts.PdgParticle.eMuon, randomizeCharge=True), - EtaConfig(-2.5, 2.5, uniform=True), + EtaConfig(-3.0, 3.0, uniform=True), MomentumConfig(1.0 * u.GeV, 100.0 * u.GeV, transverse=True), PhiConfig(0.0, 360.0 * u.degree), vtxGen=acts.examples.GaussianVertexGenerator( @@ -93,7 +93,6 @@ def runTruthTrackingGx2f( seedingAlgorithm=SeedingAlgorithm.TruthSmeared, particleHypothesis=acts.ParticleHypothesis.muon, truthSeedRanges=TruthSeedRanges( - pt=(1 * u.GeV, None), nHits=(7, None), ), ) diff --git a/Examples/Scripts/Python/truth_tracking_kalman.py b/Examples/Scripts/Python/truth_tracking_kalman.py index 2390048e25d..e0956b46bd5 100755 --- a/Examples/Scripts/Python/truth_tracking_kalman.py +++ b/Examples/Scripts/Python/truth_tracking_kalman.py @@ -98,7 +98,6 @@ def runTruthTrackingKalman( seedingAlgorithm=SeedingAlgorithm.TruthSmeared, particleHypothesis=acts.ParticleHypothesis.muon, truthSeedRanges=TruthSeedRanges( - pt=(1 * u.GeV, None), nHits=(7, None), ), ) diff --git a/README.md b/README.md index 600c2c6eda6..6cb20bfbe6c 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ More information can be found in the [Acts documentation](https://acts.readthedo ## Quick start Acts is developed in C++ and is build using [CMake](https://cmake.org). Building -the core library requires a C++17 compatible compiler, +the core library requires a C++20 compatible compiler, [Boost](https://www.boost.org), and [Eigen](https://eigen.tuxfamily.org). The following commands will clone the repository, configure, and build the core library diff --git a/Tests/DownstreamProject/CMakeLists.txt b/Tests/DownstreamProject/CMakeLists.txt index f6901184ac7..53b805e674b 100644 --- a/Tests/DownstreamProject/CMakeLists.txt +++ b/Tests/DownstreamProject/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.11) project(ActsDownstreamProject) -# find all optional components that are build with ACTS_BUILD_EVERYTHING=on +# find all optional components that are build find_package( Acts CONFIG REQUIRED COMPONENTS diff --git a/Tests/UnitTests/Core/Detector/DetectorTests.cpp b/Tests/UnitTests/Core/Detector/DetectorTests.cpp index 6f009e42523..d5fe8f18c11 100644 --- a/Tests/UnitTests/Core/Detector/DetectorTests.cpp +++ b/Tests/UnitTests/Core/Detector/DetectorTests.cpp @@ -264,7 +264,12 @@ BOOST_AUTO_TEST_CASE(DetectorConstructionWithHierarchyMap) { "DetWithSurfaces", {cylVolume}, Acts::Experimental::tryRootVolumes()); const auto& sensitiveHierarchyMap = det->sensitiveHierarchyMap(); + + const Acts::Surface* surface0 = + det->findSurface(Acts::GeometryIdentifier{}.setSensitive(1)); + BOOST_CHECK_EQUAL(sensitiveHierarchyMap.size(), 6u); + BOOST_CHECK_NE(surface0, nullptr); } BOOST_AUTO_TEST_SUITE_END() diff --git a/Tests/UnitTests/Core/EventData/CMakeLists.txt b/Tests/UnitTests/Core/EventData/CMakeLists.txt index f56a6dce91b..f6b5905d07d 100644 --- a/Tests/UnitTests/Core/EventData/CMakeLists.txt +++ b/Tests/UnitTests/Core/EventData/CMakeLists.txt @@ -12,5 +12,6 @@ target_sources(ActsUnitTestTrack PUBLIC TrackTestsExtra.cpp) add_unittest(SourceLink SourceLinkTests.cpp) add_unittest(TrackStatePropMask TrackStatePropMaskTests.cpp) add_unittest(ParticleHypothesis ParticleHypothesisTests.cpp) +add_unittest(MultiTrajectoryHelpers MultiTrajectoryHelpersTests.cpp) add_non_compile_test(MultiTrajectory TrackContainerComplianceTests.cpp) diff --git a/Tests/UnitTests/Core/EventData/MultiTrajectoryHelpersTests.cpp b/Tests/UnitTests/Core/EventData/MultiTrajectoryHelpersTests.cpp new file mode 100644 index 00000000000..9c2e88362f0 --- /dev/null +++ b/Tests/UnitTests/Core/EventData/MultiTrajectoryHelpersTests.cpp @@ -0,0 +1,123 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2024 CERN for the benefit of the Acts project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include + +#include "Acts/EventData/MultiTrajectoryHelpers.hpp" +#include "Acts/EventData/VectorMultiTrajectory.hpp" +#include "Acts/Geometry/GeometryIdentifier.hpp" +#include "Acts/Surfaces/PerigeeSurface.hpp" +#include "Acts/Surfaces/PlaneSurface.hpp" + +namespace Acts::Test { + +BOOST_AUTO_TEST_SUITE(MultiTrajectoryHelpers) + +BOOST_AUTO_TEST_CASE(trajectoryState) { + auto surface = Surface::makeShared(Vector3(0, 0, 0)); + + VectorMultiTrajectory traj; + + auto ts = traj.makeTrackState(TrackStatePropMask::None); + ts.typeFlags().set(MeasurementFlag); + ts.setReferenceSurface(surface); + + ts = traj.makeTrackState(TrackStatePropMask::None, ts.index()); + ts.typeFlags().set(OutlierFlag); + ts.setReferenceSurface(surface); + + ts = traj.makeTrackState(TrackStatePropMask::None, ts.index()); + ts.typeFlags().set(MeasurementFlag); + ts.typeFlags().set(SharedHitFlag); + ts.setReferenceSurface(surface); + + ts = traj.makeTrackState(TrackStatePropMask::None, ts.index()); + ts.typeFlags().set(HoleFlag); + ts.setReferenceSurface(surface); + + ts = traj.makeTrackState(TrackStatePropMask::None, ts.index()); + ts.typeFlags().set(OutlierFlag); + ts.setReferenceSurface(surface); + + ts = traj.makeTrackState(TrackStatePropMask::None, ts.index()); + ts.typeFlags().set(HoleFlag); + ts.setReferenceSurface(surface); + + ts = traj.makeTrackState(TrackStatePropMask::None, ts.index()); + ts.typeFlags().set(MeasurementFlag); + ts.typeFlags().set(SharedHitFlag); + ts.setReferenceSurface(surface); + + ts = traj.makeTrackState(TrackStatePropMask::None, ts.index()); + ts.typeFlags().set(OutlierFlag); + ts.setReferenceSurface(surface); + + auto state = Acts::MultiTrajectoryHelpers::trajectoryState(traj, ts.index()); + BOOST_CHECK_EQUAL(state.nHoles, 2); + BOOST_CHECK_EQUAL(state.nMeasurements, 3); + BOOST_CHECK_EQUAL(state.nOutliers, 3); + BOOST_CHECK_EQUAL(state.nSharedHits, 2); +} + +BOOST_AUTO_TEST_CASE(trajectoryStateVolume) { + GeometryIdentifier::Value searchVolume = 1; + GeometryIdentifier::Value otherVolume = 2; + std::vector volumes = {searchVolume}; + + auto searchSurface = Surface::makeShared(Vector3(0, 0, 0)); + searchSurface->assignGeometryId(GeometryIdentifier().setVolume(searchVolume)); + auto otherSurface = Surface::makeShared(Vector3(0, 0, 0)); + otherSurface->assignGeometryId(GeometryIdentifier().setVolume(otherVolume)); + + VectorMultiTrajectory traj; + + auto ts = traj.makeTrackState(TrackStatePropMask::None); + ts.typeFlags().set(MeasurementFlag); + ts.setReferenceSurface(searchSurface); + + ts = traj.makeTrackState(TrackStatePropMask::None, ts.index()); + ts.typeFlags().set(OutlierFlag); + ts.setReferenceSurface(searchSurface); + + ts = traj.makeTrackState(TrackStatePropMask::None, ts.index()); + ts.typeFlags().set(MeasurementFlag); + ts.typeFlags().set(SharedHitFlag); + ts.setReferenceSurface(searchSurface); + + ts = traj.makeTrackState(TrackStatePropMask::None, ts.index()); + ts.typeFlags().set(HoleFlag); + ts.setReferenceSurface(searchSurface); + + ts = traj.makeTrackState(TrackStatePropMask::None, ts.index()); + ts.typeFlags().set(OutlierFlag); + ts.setReferenceSurface(searchSurface); + + ts = traj.makeTrackState(TrackStatePropMask::None, ts.index()); + ts.typeFlags().set(HoleFlag); + ts.setReferenceSurface(searchSurface); + + ts = traj.makeTrackState(TrackStatePropMask::None, ts.index()); + ts.typeFlags().set(MeasurementFlag); + ts.typeFlags().set(SharedHitFlag); + ts.setReferenceSurface(otherSurface); + + ts = traj.makeTrackState(TrackStatePropMask::None, ts.index()); + ts.typeFlags().set(OutlierFlag); + ts.setReferenceSurface(otherSurface); + + auto state = + Acts::MultiTrajectoryHelpers::trajectoryState(traj, ts.index(), volumes); + BOOST_CHECK_EQUAL(state.at(searchVolume).nHoles, 2); + BOOST_CHECK_EQUAL(state.at(searchVolume).nMeasurements, 2); + BOOST_CHECK_EQUAL(state.at(searchVolume).nOutliers, 2); + BOOST_CHECK_EQUAL(state.at(searchVolume).nSharedHits, 1); +} + +BOOST_AUTO_TEST_SUITE_END() + +} // namespace Acts::Test diff --git a/Tests/UnitTests/Core/EventData/SourceLinkTests.cpp b/Tests/UnitTests/Core/EventData/SourceLinkTests.cpp index 67b4bf1d890..ecd59253455 100644 --- a/Tests/UnitTests/Core/EventData/SourceLinkTests.cpp +++ b/Tests/UnitTests/Core/EventData/SourceLinkTests.cpp @@ -22,6 +22,7 @@ BOOST_AUTO_TEST_SUITE(EventDataSourceLink) BOOST_AUTO_TEST_CASE(TestSourceLinkCoverage) { using Acts::detail::Test::TestSourceLink; + TestSourceLink ts; Acts::Vector2 stddev(0.01, 0.1); Acts::SquareMatrix2 cov = stddev.cwiseProduct(stddev).asDiagonal(); diff --git a/Tests/UnitTests/Core/EventData/TrackTests.cpp b/Tests/UnitTests/Core/EventData/TrackTests.cpp index 9b549630151..698ea737d2a 100644 --- a/Tests/UnitTests/Core/EventData/TrackTests.cpp +++ b/Tests/UnitTests/Core/EventData/TrackTests.cpp @@ -14,7 +14,6 @@ #include "Acts/EventData/MultiTrajectory.hpp" #include "Acts/EventData/ProxyAccessor.hpp" #include "Acts/EventData/TrackContainer.hpp" -#include "Acts/EventData/TrackHelpers.hpp" #include "Acts/EventData/TrackProxy.hpp" #include "Acts/EventData/TrackStatePropMask.hpp" #include "Acts/EventData/VectorMultiTrajectory.hpp" @@ -466,44 +465,6 @@ BOOST_AUTO_TEST_CASE(ForwardIteration) { act.end()); } -BOOST_AUTO_TEST_CASE(CalculateQuantities) { - TrackContainer tc{VectorTrackContainer{}, VectorMultiTrajectory{}}; - auto t = tc.makeTrack(); - - auto ts = t.appendTrackState(); - ts.typeFlags().set(MeasurementFlag); - - ts = t.appendTrackState(); - ts.typeFlags().set(OutlierFlag); - - ts = t.appendTrackState(); - ts.typeFlags().set(MeasurementFlag); - ts.typeFlags().set(SharedHitFlag); - - ts = t.appendTrackState(); - ts.typeFlags().set(HoleFlag); - - ts = t.appendTrackState(); - ts.typeFlags().set(OutlierFlag); - - ts = t.appendTrackState(); - ts.typeFlags().set(HoleFlag); - - ts = t.appendTrackState(); - ts.typeFlags().set(MeasurementFlag); - ts.typeFlags().set(SharedHitFlag); - - ts = t.appendTrackState(); - ts.typeFlags().set(OutlierFlag); - - calculateTrackQuantities(t); - - BOOST_CHECK_EQUAL(t.nHoles(), 2); - BOOST_CHECK_EQUAL(t.nMeasurements(), 3); - BOOST_CHECK_EQUAL(t.nOutliers(), 3); - BOOST_CHECK_EQUAL(t.nSharedHits(), 2); -} - BOOST_AUTO_TEST_CASE(ShallowCopy) { TrackContainer tc{VectorTrackContainer{}, VectorMultiTrajectory{}}; auto t = tc.makeTrack(); diff --git a/Tests/UnitTests/Core/Navigation/DetectorNavigatorTests.cpp b/Tests/UnitTests/Core/Navigation/DetectorNavigatorTests.cpp index d9d8dac01e6..2ad242c1acc 100644 --- a/Tests/UnitTests/Core/Navigation/DetectorNavigatorTests.cpp +++ b/Tests/UnitTests/Core/Navigation/DetectorNavigatorTests.cpp @@ -176,7 +176,7 @@ BOOST_AUTO_TEST_CASE(DetectorNavigatorTestsInitialization) { detector->findDetectorVolume(geoContext, start.position())); BOOST_CHECK_EQUAL(initState.currentSurface, nullptr); BOOST_CHECK_EQUAL(initState.currentPortal, nullptr); - BOOST_CHECK_EQUAL(initState.surfaceCandidates.size(), 1); + BOOST_CHECK_EQUAL(initState.surfaceCandidates.size(), 2u); } } diff --git a/Tests/UnitTests/Core/TrackFitting/Gx2fTests.cpp b/Tests/UnitTests/Core/TrackFitting/Gx2fTests.cpp index caa15e9c6d8..44ebc963829 100644 --- a/Tests/UnitTests/Core/TrackFitting/Gx2fTests.cpp +++ b/Tests/UnitTests/Core/TrackFitting/Gx2fTests.cpp @@ -31,6 +31,9 @@ #include "Acts/Tests/CommonHelpers/PredefinedMaterials.hpp" #include "Acts/TrackFitting/GlobalChiSquareFitter.hpp" #include "Acts/Utilities/Logger.hpp" +#include "Acts/Visualization/EventDataView3D.hpp" +#include "Acts/Visualization/GeometryView3D.hpp" +#include "Acts/Visualization/ObjVisualization3D.hpp" #include @@ -44,6 +47,37 @@ const auto gx2fLogger = Acts::getDefaultLogger("Gx2f", logLevel); namespace Acts::Test { +/// @brief Helper function to visualise measurements in a 3D environment. +/// +/// This function iterates through the provided measurements and visualises each +/// one using the specified 3D visualisation helper. The visualisation takes +/// into account the surface transformations and localisation errors. +/// +/// @param helper The 3D visualisation helper used to draw the measurements. +/// @param measurements A collection of measurements to be visualised, containing source links with parameters and covariance information. +/// @param geometry A shared pointer to the constant tracking geometry used to find surfaces associated with measurements. +/// @param geoCtx The geometry context used for transformations and accessing geometry-related information. +/// @param locErrorScale Scaling factor for localisation errors. Default value is 1.0. +/// @param viewConfig Configuration settings for the visualisation view. Default value is s_viewMeasurement. +static void drawMeasurements( + IVisualization3D& helper, const Measurements& measurements, + const std::shared_ptr& geometry, + const Acts::GeometryContext& geoCtx, double locErrorScale = 1., + const ViewConfig& viewConfig = s_viewMeasurement) { + std::cout << "\n*** Draw measurements ***\n" << std::endl; + + for (auto& singleMeasurement : measurements.sourceLinks) { + auto cov = singleMeasurement.covariance; + auto lposition = singleMeasurement.parameters; + + auto surf = geometry->findSurface(singleMeasurement.m_geometryId); + auto transf = surf->transform(geoCtx); + + EventDataView3D::drawMeasurement(helper, lposition, cov, transf, + locErrorScale, viewConfig); + } +} + //// Construct initial track parameters. Acts::CurvilinearTrackParameters makeParameters( const ActsScalar x = 0.0_m, const ActsScalar y = 0.0_m, @@ -78,6 +112,7 @@ static std::vector prepareSourceLinks( /// /// @param geoCtx /// @param nSurfaces Number of surfaces +/// @param surfaceIndexWithMaterial A set of index of the material surfaces std::shared_ptr makeToyDetector( const Acts::GeometryContext& geoCtx, const std::size_t nSurfaces = 5, const std::set& surfaceIndexWithMaterial = {}) { @@ -88,7 +123,7 @@ std::shared_ptr makeToyDetector( // Define the dimensions of the square surfaces const double halfSizeSurface = 1_m; - // Rotation of the surfaces + // Rotation of the surfaces around the y-axis const double rotationAngle = M_PI * 0.5; const Vector3 xPos(cos(rotationAngle), 0., sin(rotationAngle)); const Vector3 yPos(0., 1., 0.); @@ -150,7 +185,7 @@ std::shared_ptr makeToyDetector( 2 * halfSizeSurface}; volumeConfig.position = {volumeConfig.length.x() / 2, 0., 0.}; volumeConfig.layerCfg = layerConfig; - volumeConfig.name = "Test volume"; + volumeConfig.name = "TestVolume"; // Outer volume - Build TrackingGeometry configuration CuboidVolumeBuilder::Config config; @@ -175,6 +210,117 @@ std::shared_ptr makeToyDetector( return detector; } +/// @brief Create a simple telescope detector in the Y direction. +/// +/// We cannot reuse the previous detector, since the cuboid volume builder only +/// allows merging of YZ-faces. +/// +/// @param geoCtx +/// @param nSurfaces Number of surfaces +std::shared_ptr makeToyDetectorYdirection( + const Acts::GeometryContext& geoCtx, const std::size_t nSurfaces = 5) { + if (nSurfaces < 1) { + throw std::invalid_argument("At least 1 surfaces needs to be created."); + } + + // Define the dimensions of the square surfaces + const double halfSizeSurface = 1_m; + + // Rotation of the surfaces around the x-axis + const double rotationAngle = M_PI * 0.5; + const Vector3 xPos(1., 0., 0.); + const Vector3 yPos(0., cos(rotationAngle), sin(rotationAngle)); + const Vector3 zPos(0., -sin(rotationAngle), cos(rotationAngle)); + + // Construct builder + CuboidVolumeBuilder cvb; + + // Create configurations for surfaces + std::vector surfaceConfig; + for (std::size_t surfPos = 1; surfPos <= nSurfaces; surfPos++) { + // Position of the surfaces + CuboidVolumeBuilder::SurfaceConfig cfg; + cfg.position = {0., surfPos * UnitConstants::m, 0.}; + + // Rotation of the surfaces + cfg.rotation.col(0) = xPos; + cfg.rotation.col(1) = yPos; + cfg.rotation.col(2) = zPos; + + // Boundaries of the surfaces (shape) + cfg.rBounds = std::make_shared( + RectangleBounds(halfSizeSurface, halfSizeSurface)); + + // Thickness of the detector element + cfg.thickness = 1_um; + + cfg.detElementConstructor = + [](const Transform3& trans, + const std::shared_ptr& bounds, + double thickness) { + return new DetectorElementStub(trans, bounds, thickness); + }; + surfaceConfig.push_back(cfg); + } + + // Build layer configurations + std::vector layerConfig; + for (auto& sCfg : surfaceConfig) { + CuboidVolumeBuilder::LayerConfig cfg; + cfg.surfaceCfg = {sCfg}; + cfg.active = true; + cfg.envelopeX = {-0.1_mm, 0.1_mm}; + cfg.envelopeY = {-0.1_mm, 0.1_mm}; + cfg.envelopeZ = {-0.1_mm, 0.1_mm}; + cfg.binningDimension = Acts::BinningValue::binY; + layerConfig.push_back(cfg); + } + + // Inner Volume - Build volume configuration + CuboidVolumeBuilder::VolumeConfig volumeConfig; + volumeConfig.length = {2 * halfSizeSurface, (nSurfaces + 1) * 1_m, + 2 * halfSizeSurface}; + volumeConfig.position = {0., volumeConfig.length.y() / 2, 0.}; + volumeConfig.layerCfg = layerConfig; + volumeConfig.name = "TestVolume"; + volumeConfig.binningDimension = Acts::BinningValue::binY; + + // This basically adds an empty volume in y-direction + // Second inner Volume - Build volume configuration + CuboidVolumeBuilder::VolumeConfig volumeConfig2; + // volumeConfig2.length = volumeConfig.length; + volumeConfig2.length = {2 * halfSizeSurface, (nSurfaces + 1) * 1_m, + 2 * halfSizeSurface}; + ; + volumeConfig2.position = {volumeConfig2.length.x(), + volumeConfig2.length.y() / 2, 0.}; + volumeConfig2.name = "AdditionalVolume"; + volumeConfig2.binningDimension = Acts::BinningValue::binY; + + // Outer volume - Build TrackingGeometry configuration and fill + CuboidVolumeBuilder::Config config; + config.length = {4 * halfSizeSurface, (nSurfaces + 1) * 1_m, + 2 * halfSizeSurface}; + config.position = {volumeConfig.length.x() / 2, volumeConfig.length.y() / 2, + 0.}; + config.volumeCfg = {volumeConfig, volumeConfig2}; + + cvb.setConfig(config); + + TrackingGeometryBuilder::Config tgbCfg; + + tgbCfg.trackingVolumeBuilders.push_back( + [=](const auto& context, const auto& inner, const auto&) { + return cvb.trackingVolume(context, inner, nullptr); + }); + + TrackingGeometryBuilder tgb(tgbCfg); + + std::unique_ptr detector = + tgb.trackingGeometry(geoCtx); + return detector; +} + struct Detector { // geometry std::shared_ptr geometry; @@ -377,6 +523,120 @@ BOOST_AUTO_TEST_CASE(Fit5Iterations) { ACTS_INFO("*** Test: Fit5Iterations -- Finish"); } +BOOST_AUTO_TEST_CASE(UpdatePushedToNewVolume) { + ACTS_INFO("*** Test: UpdatePushedToNewVolume -- Start"); + + std::default_random_engine rng(42); + + ACTS_DEBUG("Create the detector"); + const std::size_t nSurfaces = 5; + Detector detector; + detector.geometry = makeToyDetectorYdirection(geoCtx, nSurfaces); + + ACTS_DEBUG("Set the start parameters for measurement creation and fit"); + const auto parametersMeasurements = + makeParameters(0_mm, 0_mm, 0_mm, 42_ns, 90_degree, 90_degree, 1_GeV, 1_e); + const auto startParametersFit = makeParameters( + 1500_mm, 0_mm, 0_mm, 42_ns, -45_degree, -90_degree, 1_GeV, 1_e); + + ACTS_DEBUG("Create the measurements"); + using SimPropagator = + Acts::Propagator; + const SimPropagator simPropagator = makeStraightPropagator(detector.geometry); + const auto measurements = + createMeasurements(simPropagator, geoCtx, magCtx, parametersMeasurements, + resMapAllPixel, rng); + const auto sourceLinks = prepareSourceLinks(measurements.sourceLinks); + ACTS_VERBOSE("sourceLinks.size() = " << sourceLinks.size()); + + BOOST_REQUIRE_EQUAL(sourceLinks.size(), nSurfaces); + + ACTS_DEBUG("Set up the fitter"); + const Surface* rSurface = ¶metersMeasurements.referenceSurface(); + + using RecoStepper = EigenStepper<>; + const auto recoPropagator = + makeConstantFieldPropagator(detector.geometry, 0_T); + + using RecoPropagator = decltype(recoPropagator); + using Gx2Fitter = + Experimental::Gx2Fitter; + const Gx2Fitter fitter(recoPropagator, gx2fLogger->clone()); + + Experimental::Gx2FitterExtensions extensions; + extensions.calibrator + .connect<&testSourceLinkCalibrator>(); + TestSourceLink::SurfaceAccessor surfaceAccessor{*detector.geometry}; + extensions.surfaceAccessor + .connect<&TestSourceLink::SurfaceAccessor::operator()>(&surfaceAccessor); + + const Experimental::Gx2FitterOptions gx2fOptions( + geoCtx, magCtx, calCtx, extensions, + PropagatorPlainOptions(geoCtx, magCtx), rSurface, false, false, + FreeToBoundCorrection(false), 5, 0); + + Acts::TrackContainer tracks{Acts::VectorTrackContainer{}, + Acts::VectorMultiTrajectory{}}; + + ACTS_DEBUG("Fit the track"); + ACTS_VERBOSE("startParameter unsmeared:\n" << parametersMeasurements); + ACTS_VERBOSE("startParameter fit:\n" << startParametersFit); + const auto res = fitter.fit(sourceLinks.begin(), sourceLinks.end(), + startParametersFit, gx2fOptions, tracks); + + // Helper to visualise the detector + { + std::cout << "\n*** Create .obj of Detector ***\n" << std::endl; + // Only need for obj + ObjVisualization3D obj; + + bool triangulate = true; + ViewConfig viewSensitive = ViewConfig({0, 180, 240}); + viewSensitive.triangulate = triangulate; + ViewConfig viewPassive = ViewConfig({240, 280, 0}); + viewPassive.triangulate = triangulate; + ViewConfig viewVolume = ViewConfig({220, 220, 0}); + viewVolume.triangulate = triangulate; + ViewConfig viewContainer = ViewConfig({220, 220, 0}); + viewContainer.triangulate = triangulate; + ViewConfig viewGrid = ViewConfig({220, 0, 0}); + viewGrid.nSegments = 8; + viewGrid.offset = 3.; + viewGrid.triangulate = triangulate; + + std::string tag = "gx2f_toydet"; + + const Acts::TrackingVolume& tgVolume = + *(detector.geometry->highestTrackingVolume()); + + GeometryView3D::drawTrackingVolume(obj, tgVolume, geoCtx, viewContainer, + viewVolume, viewPassive, viewSensitive, + viewGrid, true, tag); + } + // Helper to visualise the measurements + { + std::cout << "\n*** Create .obj of measurements ***\n" << std::endl; + ObjVisualization3D obj; + + double localErrorScale = 10000000.; + ViewConfig mcolor({255, 145, 48}); + mcolor.offset = 2; + // mcolor.visible = true; + + drawMeasurements(obj, measurements, detector.geometry, geoCtx, + localErrorScale, mcolor); + + obj.write("meas"); + } + + BOOST_REQUIRE(!res.ok()); + BOOST_CHECK_EQUAL( + res.error(), + Acts::Experimental::GlobalChiSquareFitterError::UpdatePushedToNewVolume); + + ACTS_INFO("*** Test: UpdatePushedToNewVolume -- Finish"); +} + BOOST_AUTO_TEST_CASE(MixedDetector) { ACTS_INFO("*** Test: MixedDetector -- Start"); @@ -853,7 +1113,7 @@ BOOST_AUTO_TEST_CASE(FindHoles) { sourceLinks.pop_back(); ACTS_VERBOSE("sourceLinks.size() [after pop] = " << sourceLinks.size()); - // We remove the second to last measurement in the list. This effectivly + // We remove the second to last measurement in the list. This effectively // creates a hole on that surface. const std::size_t indexHole = sourceLinks.size() - 2; ACTS_VERBOSE("Remove measurement " << indexHole); diff --git a/Tests/UnitTests/Core/Utilities/CMakeLists.txt b/Tests/UnitTests/Core/Utilities/CMakeLists.txt index daf84311957..af362d6d564 100644 --- a/Tests/UnitTests/Core/Utilities/CMakeLists.txt +++ b/Tests/UnitTests/Core/Utilities/CMakeLists.txt @@ -52,3 +52,5 @@ add_unittest(ParticleData ParticleDataTests.cpp) add_unittest(Zip ZipTests.cpp) add_unittest(TransformRange TransformRangeTests.cpp) add_unittest(QuickMath QuickMathTests.cpp) + +add_unittest(TrackHelpers TrackHelpersTests.cpp) diff --git a/Tests/UnitTests/Core/Utilities/TrackHelpersTests.cpp b/Tests/UnitTests/Core/Utilities/TrackHelpersTests.cpp new file mode 100644 index 00000000000..fcba710499c --- /dev/null +++ b/Tests/UnitTests/Core/Utilities/TrackHelpersTests.cpp @@ -0,0 +1,59 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2024 CERN for the benefit of the Acts project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include + +#include "Acts/EventData/TrackContainer.hpp" +#include "Acts/EventData/VectorMultiTrajectory.hpp" +#include "Acts/EventData/VectorTrackContainer.hpp" +#include "Acts/Utilities/TrackHelpers.hpp" + +namespace Acts::Test { + +BOOST_AUTO_TEST_SUITE(Utilities) + +BOOST_AUTO_TEST_CASE(CalculateQuantities) { + TrackContainer tc{VectorTrackContainer{}, VectorMultiTrajectory{}}; + auto t = tc.makeTrack(); + + auto ts = t.appendTrackState(); + ts.typeFlags().set(MeasurementFlag); + + ts = t.appendTrackState(); + ts.typeFlags().set(OutlierFlag); + + ts = t.appendTrackState(); + ts.typeFlags().set(MeasurementFlag); + ts.typeFlags().set(SharedHitFlag); + + ts = t.appendTrackState(); + ts.typeFlags().set(HoleFlag); + + ts = t.appendTrackState(); + ts.typeFlags().set(OutlierFlag); + + ts = t.appendTrackState(); + ts.typeFlags().set(HoleFlag); + + ts = t.appendTrackState(); + ts.typeFlags().set(MeasurementFlag); + ts.typeFlags().set(SharedHitFlag); + + ts = t.appendTrackState(); + ts.typeFlags().set(OutlierFlag); + + calculateTrackQuantities(t); + BOOST_CHECK_EQUAL(t.nHoles(), 2); + BOOST_CHECK_EQUAL(t.nMeasurements(), 3); + BOOST_CHECK_EQUAL(t.nOutliers(), 3); + BOOST_CHECK_EQUAL(t.nSharedHits(), 2); +} + +BOOST_AUTO_TEST_SUITE_END() + +} // namespace Acts::Test diff --git a/Tests/UnitTests/Plugins/EDM4hep/ConvertTrackEDM4hepTest.cpp b/Tests/UnitTests/Plugins/EDM4hep/ConvertTrackEDM4hepTest.cpp index 3f154dfe424..d3636eef0e2 100644 --- a/Tests/UnitTests/Plugins/EDM4hep/ConvertTrackEDM4hepTest.cpp +++ b/Tests/UnitTests/Plugins/EDM4hep/ConvertTrackEDM4hepTest.cpp @@ -12,7 +12,6 @@ #include "Acts/EventData/Charge.hpp" #include "Acts/EventData/GenericBoundTrackParameters.hpp" #include "Acts/EventData/MultiTrajectory.hpp" -#include "Acts/EventData/TrackHelpers.hpp" #include "Acts/EventData/TrackStatePropMask.hpp" #include "Acts/EventData/VectorMultiTrajectory.hpp" #include "Acts/EventData/VectorTrackContainer.hpp" @@ -25,6 +24,7 @@ #include "Acts/Surfaces/Surface.hpp" #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp" #include "Acts/Utilities/Logger.hpp" +#include "Acts/Utilities/TrackHelpers.hpp" #include "Acts/Utilities/Zip.hpp" #include diff --git a/cmake/ActsConfig.cmake.in b/cmake/ActsConfig.cmake.in index 362f293ce19..8e8caad4935 100644 --- a/cmake/ActsConfig.cmake.in +++ b/cmake/ActsConfig.cmake.in @@ -96,6 +96,12 @@ if(PluginPodio IN_LIST Acts_COMPONENTS) include(${CMAKE_CURRENT_LIST_DIR}/ActsPodioEdmTargets.cmake) endif() +if(PluginDetray IN_LIST Acts_COMPONENTS) + find_dependency(vecmem @vecmem_VERSION@ CONFIG EXACT) + find_dependency(algebra-plugins @algebra-plugins_VERSION@ CONFIG EXACT) + find_dependency(detray @detray_VERSION@ CONFIG EXACT) +endif() + # load **all** available components. we can not just include the requested # components since there can be interdependencies between them. if(NOT Acts_FIND_QUIETLY) @@ -108,4 +114,3 @@ foreach(_component ${Acts_COMPONENTS}) # include the targets file to create the imported targets for the user include(${CMAKE_CURRENT_LIST_DIR}/Acts${_component}Targets.cmake) endforeach() - diff --git a/cmake/ActsExternSources.cmake b/cmake/ActsExternSources.cmake index 95559701a04..f58a901a1c5 100644 --- a/cmake/ActsExternSources.cmake +++ b/cmake/ActsExternSources.cmake @@ -15,11 +15,11 @@ set( ACTS_COVFIE_SOURCE mark_as_advanced( ACTS_COVFIE_SOURCE ) set( ACTS_DETRAY_SOURCE - "URL;https://github.com/acts-project/detray/archive/refs/tags/v0.65.1.tar.gz;URL_MD5;fbf57a881565fa6019d79d13409b588f" CACHE STRING "Source to take DETRAY from") + "URL;https://github.com/acts-project/detray/archive/refs/tags/v0.72.1.tar.gz;URL_MD5;342ab0bfba45c5764c8eef3842897c16" CACHE STRING "Source to take DETRAY from") mark_as_advanced( ACTS_DETRAY_SOURCE ) set( ACTS_TRACCC_SOURCE - "URL;https://github.com/acts-project/traccc/archive/refs/tags/v0.10.0.tar.gz;URL_MD5;131399d26e3280c4d7f7ca2995efd256" CACHE STRING "Source to take TRACCC from") + "URL;https://github.com/acts-project/traccc/archive/refs/tags/v0.13.0.tar.gz;URL_MD5;1ddf757ddcbaa08fd7db3a7752ef7f98" CACHE STRING "Source to take TRACCC from") mark_as_advanced( ACTS_TRACCC_SOURCE ) set( ACTS_DFELIBS_SOURCE diff --git a/cmake/FindFilesystem.cmake b/cmake/FindFilesystem.cmake index c34988752dd..de3f25cb567 100644 --- a/cmake/FindFilesystem.cmake +++ b/cmake/FindFilesystem.cmake @@ -126,9 +126,6 @@ cmake_push_check_state() set(CMAKE_REQUIRED_QUIET ${Filesystem_FIND_QUIETLY}) -# All of our tests required C++17 or later -set(CMAKE_CXX_STANDARD 17) - # Normalize and check the component list we were given set(want_components ${Filesystem_FIND_COMPONENTS}) if(Filesystem_FIND_COMPONENTS STREQUAL "") diff --git a/docs/acts_project.md b/docs/acts_project.md index eecdfc0fe90..6027024a462 100644 --- a/docs/acts_project.md +++ b/docs/acts_project.md @@ -1,6 +1,6 @@ # The ACTS project -The *A Common Tracking Software (ACTS)* project is an attempt to preserve and evolve the track reconstruction software of the LHC era towards HL-LHC and beyond. It has been initiated in 2016 starting from the [ATLAS Common Tracking Software](https://gitlab.cern.ch/atlas/athena/-/tree/main/Tracking). Given the changing computing landscape, dedicated care of parallel code execution is taken, and is written in `C++17`. +The *A Common Tracking Software (ACTS)* project is an attempt to preserve and evolve the track reconstruction software of the LHC era towards HL-LHC and beyond. It has been initiated in 2016 starting from the [ATLAS Common Tracking Software](https://gitlab.cern.ch/atlas/athena/-/tree/main/Tracking). Given the changing computing landscape, dedicated care of parallel code execution is taken, and is written in `C++20`. A [coherent write-up of the project](https://link.springer.com/article/10.1007/s41781-021-00078-8) has been published in 2022 in Springer's CSBS. @@ -33,4 +33,3 @@ ACTS should also provide a testbed for fruitful algorithm R&D, and hence is clos In addition, two dedicated R&D lines are part of the `acts-project`, one for machine learning based/inspired modules [acts-machine-learning](mailto:acts-machine-learning@cern.ch), and one for massively parallel code execution [acts-parallelization](mailto:acts-parallelization@cern.ch), which mainly focuses on GPU accelerators and portability. Code spill-over from the R&D lines into the main ACTS repository are performed on demand and depending on the maturity of the R&D projects. - diff --git a/docs/examples/howto/run_ckf_auto_tuning.rst b/docs/examples/howto/run_ckf_auto_tuning.rst index ac0109f1719..20c9892a189 100644 --- a/docs/examples/howto/run_ckf_auto_tuning.rst +++ b/docs/examples/howto/run_ckf_auto_tuning.rst @@ -21,7 +21,7 @@ Once all the dependencies are installed, Build ACTS with python bindings and Pyt .. code-block:: console - $ cmake -DACTS_BUILD_EXAMPLES_PYTHIA8=ON -DACTS_BUILD_PLUGIN_DD4HEP=OFF -DACTS_BUILD_PLUGIN_JSON=ON -DACTS_BUILD_PLUGIN_TGEO=ON -DACTS_BUILD_EXAMPLES=ON -DACTS_BUILD_EXAMPLES_DD4HEP=OFF -DACTS_BUILD_EXAMPLES_GEANT4=ON -DACTS_BUILD_INTEGRATIONTESTS=OFF -DACTS_BUILD_UNITTESTS=OFF -DACTS_BUILD_EXAMPLES_PYTHON_BINDINGS=ON -DACTS_BUILD_ODD=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=17 -S . -B build/ + $ cmake -DACTS_BUILD_EXAMPLES_PYTHIA8=ON -DACTS_BUILD_PLUGIN_DD4HEP=OFF -DACTS_BUILD_PLUGIN_JSON=ON -DACTS_BUILD_PLUGIN_TGEO=ON -DACTS_BUILD_EXAMPLES_DD4HEP=OFF -DACTS_BUILD_EXAMPLES_GEANT4=ON -DACTS_BUILD_INTEGRATIONTESTS=OFF -DACTS_BUILD_UNITTESTS=OFF -DACTS_BUILD_EXAMPLES_PYTHON_BINDINGS=ON -DACTS_BUILD_ODD=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=17 -S . -B build/ $ make $ source build/python/setup.sh diff --git a/docs/getting_started.md b/docs/getting_started.md index 791768e067c..805ee54aa0f 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -3,7 +3,7 @@ ## Quick start ACTS is developed in C++ and is built using [CMake](https://cmake.org). Building -the core library requires a C++17 compatible compiler, +the core library requires a C++20 compatible compiler, [Boost](https://www.boost.org), and [Eigen](https://eigen.tuxfamily.org). The following commands will clone the repository, configure, and build the core library: @@ -257,7 +257,6 @@ components. | Option | Description | |-------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| ACTS_BUILD_EVERYTHING | Build with most options enabled (except
HepMC3 and documentation)
type: `bool`, default: `OFF` | | ACTS_PARAMETER_DEFINITIONS_HEADER | Use a different (track) parameter
definitions header
type: `filepath`, default: `""` | | ACTS_SOURCELINK_SBO_SIZE | Customize the SBO size used by
SourceLink
type: `string`, default: `""` | | ACTS_FORCE_ASSERTIONS | Force assertions regardless of build
type
type: `bool`, default: `OFF` | @@ -283,23 +282,16 @@ components. | ACTS_USE_SYSTEM_NLOHMANN_JSON | Use nlohmann::json provided by the
system instead of the bundled version
type: `bool`, default: `ACTS_USE_SYSTEM_LIBS -> OFF` | | ACTS_BUILD_PLUGIN_LEGACY | Build legacy plugin
type: `bool`, default: `OFF` | | ACTS_BUILD_PLUGIN_ONNX | Build ONNX plugin
type: `bool`, default: `OFF` | -| ACTS_SETUP_COVFIE | Explicitly set up covfie for the project
type: `bool`, default: `OFF` | | ACTS_USE_SYSTEM_COVFIE | Use a system-provided covfie
installation
type: `bool`, default: `ACTS_USE_SYSTEM_LIBS -> OFF` | -| ACTS_SETUP_DETRAY | Explicitly set up detray for the project
type: `bool`, default: `OFF` | | ACTS_USE_SYSTEM_DETRAY | Use a system-provided detray
installation
type: `bool`, default: `ACTS_USE_SYSTEM_LIBS -> OFF` | -| ACTS_SETUP_TRACCC | Explicitly set up traccc for the project
type: `bool`, default: `OFF` | | ACTS_USE_SYSTEM_TRACCC | Use a system-provided traccc
installation
type: `bool`, default: `ACTS_USE_SYSTEM_LIBS -> OFF` | -| ACTS_SETUP_DFELIBS | Explicitly set up dfelibs for the
project
type: `bool`, default: `ON` | | ACTS_USE_SYSTEM_DFELIBS | Use a system-provided dfelibs
installation
type: `bool`, default: `ACTS_USE_SYSTEM_LIBS -> OFF` | -| ACTS_SETUP_VECMEM | Explicitly set up vecmem for the project
type: `bool`, default: `OFF` | | ACTS_USE_SYSTEM_VECMEM | Use a system-provided vecmem
installation
type: `bool`, default: `ACTS_USE_SYSTEM_LIBS -> OFF` | -| ACTS_SETUP_ALGEBRAPLUGINS | Explicitly set up algebra-plugins for
the project
type: `bool`, default: `OFF` | | ACTS_USE_SYSTEM_ALGEBRAPLUGINS | Use a system-provided algebra-plugins
installation
type: `bool`, default: `ACTS_USE_SYSTEM_LIBS -> OFF` | | ACTS_BUILD_PLUGIN_TGEO | Build TGeo plugin
type: `bool`, default: `OFF` | | ACTS_BUILD_FATRAS | Build FAst TRAcking Simulation package
type: `bool`, default: `OFF` | | ACTS_BUILD_FATRAS_GEANT4 | Build Geant4 Fatras package
type: `bool`, default: `OFF` | | ACTS_BUILD_ALIGNMENT | Build Alignment package
type: `bool`, default: `OFF` | -| ACTS_BUILD_EXAMPLES | Build standalone examples
type: `bool`, default: `OFF` | | ACTS_BUILD_EXAMPLES_DD4HEP | Build DD4hep-based code in the examples
type: `bool`, default: `OFF` | | ACTS_BUILD_EXAMPLES_EDM4HEP | Build EDM4hep-based code in the examples
type: `bool`, default: `OFF` | | ACTS_BUILD_EXAMPLES_EXATRKX | Build the Exa.TrkX example code
type: `bool`, default: `OFF` | @@ -329,13 +321,17 @@ components. | ACTS_LOG_FAILURE_THRESHOLD | Log level above which an exception
should be automatically thrown. If
ACTS_ENABLE_LOG_FAILURE_THRESHOLD is set
and this is unset, this will enable a
runtime check of the log level.
type: `string`, default: `""` | - All ACTS-specific options are disabled or empty by default and must be -specifically requested. Some of the options have interdependencies that are -automatically handled, e.g. enabling any of the specific -`ACTS_BUILD_EXAMPLES_...` options will also enable the overall -`ACTS_BUILD_EXAMPLES` option. You only need to tell the build system what you -want and it will figure out the rest. +specifically requested. + +ACTS comes with a couple of CMakePresets which allow to collect and +origanize common configuration workflows. On the surface the current +list of presets contains: + +- `dev` as a base for developer configurations. This enables everything + necessary for running the ODD full chain examples with Fatras. It + sets the cpp standard to 20, the generator to ninja and enables ccache. +- `perf` is similar to `dev` but tweaked for performance measurements. In addition to the ACTS-specific options, many generic options are available that modify various aspects of the build. The following options are some of the diff --git a/thirdparty/README.md b/thirdparty/README.md index 2c3c037f3a7..ca89ca9e040 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -41,3 +41,23 @@ CMake instructions to build [Pybind11](https://github.com/pybind/pybind11), whic ## FRNN CMake instructions to build [FRNN](https://github.com/lxxue/FRNN), which is used by the Exa.TrkX plugin. + +## Algebra plugins + +CMake instruction to build [algebra-plugins](https://github.com/acts-project/algebra-plugins), which is used by the traccc plugin. + +## VecMem + +CMake instruction to build [VecMem](https://github.com/acts-project/vecmem), which is used by the traccc plugin. + +## Covfie + +CMake instruction to build [covfie](https://github.com/acts-project/covfie), which is used by the traccc plugin. + +## Detray + +CMake instruction to build [detray](https://github.com/acts-project/detray), which is used by the traccc plugin. + +## Traccc + +CMake instruction to build [traccc](https://github.com/acts-project/traccc), which is used by the traccc plugin. diff --git a/thirdparty/algebra-plugins/CMakeLists.txt b/thirdparty/algebra-plugins/CMakeLists.txt index e625715417f..75fb0f9ad77 100644 --- a/thirdparty/algebra-plugins/CMakeLists.txt +++ b/thirdparty/algebra-plugins/CMakeLists.txt @@ -19,8 +19,8 @@ set(ALGEBRA_PLUGINS_BUILD_TESTING FALSE CACHE BOOL "Turn off the build of the Algebra Plugins unit tests") set(ALGEBRA_PLUGINS_INCLUDE_EIGEN TRUE CACHE BOOL "Turn on the build of algebra::eigen") -set(ALGEBRA_PLUGINS_INCLUDE_VC TRUE CACHE BOOL - "Turn on the build of algebra::vc_array") +set(ALGEBRA_PLUGINS_INCLUDE_VC FALSE CACHE BOOL + "Turn off the build of algebra::vc_array") set(ALGEBRA_PLUGINS_INCLUDE_VECMEM TRUE CACHE BOOL "Turn on the build of algebra::vecmem_array") @@ -31,8 +31,8 @@ set(ALGEBRA_PLUGINS_INCLUDE_SMATRIX ${DETRAY_SMATRIX_PLUGIN} set(ALGEBRA_PLUGINS_SETUP_EIGEN3 OFF CACHE BOOL "Do not have Algebra Plugins set up Eigen3 for itself") -set(ALGEBRA_PLUGINS_SETUP_VC ON CACHE BOOL - "Have Algebra Plugins set up Vc for itself") +set(ALGEBRA_PLUGINS_SETUP_VC OFF CACHE BOOL + "Do not have Algebra Plugins set up Vc for itself") set(ALGEBRA_PLUGINS_USE_SYSTEM_VC OFF CACHE BOOL "Have Algebra Plugins build Vc itself") set(ALGEBRA_PLUGINS_SETUP_VECMEM FALSE CACHE BOOL diff --git a/thirdparty/detray/CMakeLists.txt b/thirdparty/detray/CMakeLists.txt index 8ec164e2440..074737ae7a5 100644 --- a/thirdparty/detray/CMakeLists.txt +++ b/thirdparty/detray/CMakeLists.txt @@ -27,8 +27,8 @@ set( DETRAY_BUILD_TUTORIALS OFF CACHE BOOL "Turn off the build of the Detray tutorials" ) set( DETRAY_EIGEN_PLUGIN ON CACHE BOOL "Turn on the build of the Detray Eigen code" ) -set( DETRAY_VC_PLUGIN ON CACHE BOOL - "Turn on the build of the Detray Vc code" ) +set( DETRAY_VC_PLUGIN OFF CACHE BOOL + "Turn off the build of the Detray Vc code" ) set( DETRAY_SETUP_VECMEM OFF CACHE BOOL "Do not set up VecMem as part of Detray" ) @@ -48,10 +48,8 @@ set( DETRAY_SETUP_ACTSVG OFF CACHE BOOL "Do not set up Actsvg as part of Detray" ) set( DETRAY_SETUP_DFELIBS OFF CACHE BOOL "Do not set up Dfelibs as part of Detray" ) -#set( DETRAY_VC_PLUGIN OFF CACHE BOOL -# "Do not build Vc based math plugin" ) -#set( DETRAY_SVG_DISPLAY ON CACHE BOOL -# "Build the ActSVG display module" ) +set( DETRAY_SVG_DISPLAY ${ACTS_BUILD_PLUGIN_ACTSVG} CACHE BOOL + "Build the ActSVG display module depending on the ACTS_BUILD_PLUGIN_ACTSVG" ) #Now set up its build. diff --git a/thirdparty/traccc/CMakeLists.txt b/thirdparty/traccc/CMakeLists.txt index b62c9ba35f0..73597b29f36 100644 --- a/thirdparty/traccc/CMakeLists.txt +++ b/thirdparty/traccc/CMakeLists.txt @@ -22,7 +22,7 @@ set( TRACCC_SETUP_VECMEM OFF CACHE BOOL "Do not set up Actsvg as part of Traccc" ) set( TRACCC_SETUP_EIGEN3 OFF CACHE BOOL "Do not set up Eigen3 as part of Traccc" ) -set( TRACCC_SETUP_THRUST OFF CACHE BOOL +set( TRACCC_SETUP_THRUST ON CACHE BOOL "Do not set up Thrust as part of Traccc" ) set( TRACCC_SETUP_ALGEBRA_PLUGINS OFF CACHE BOOL "Do not set up Algebra Plugins as part of Traccc" ) @@ -34,6 +34,8 @@ set( TRACCC_SETUP_DETRAY OFF CACHE BOOL "Do not set up Detray as part of Traccc" ) set( TRACCC_SETUP_ACTS OFF CACHE BOOL "Do not set up ACTS as part of Traccc" ) +set( TRACCC_SETUP_TBB OFF CACHE BOOL + "Do not set up TBB as part of Traccc" ) set( TRACCC_BUILD_TESTING OFF CACHE BOOL "Turn off the build of the Traccc unit tests" )