diff --git a/.github/workflows/analysis.yml b/.github/workflows/analysis.yml index 2ce3bfdc278..c946b38cd66 100644 --- a/.github/workflows/analysis.yml +++ b/.github/workflows/analysis.yml @@ -20,8 +20,9 @@ env: CTEST_OUTPUT_ON_FAILURE: 1 CCACHE_DIR: ${{ github.workspace }}/ccache CCACHE_MAXSIZE: 1.25G - CCACHE_KEY_SUFFIX: r1 + CCACHE_KEY_SUFFIX: r2 ACTS_LOG_FAILURE_THRESHOLD: WARNING + DEPENDENCY_URL: https://acts.web.cern.ch/ACTS/ci/ubuntu-24.04/deps.v4.tar.zst # NOTE this only builds core unittests to reduce the output size. if we # found a way to have Github actions not fail regularly with this job @@ -29,18 +30,21 @@ env: jobs: build_debug: runs-on: ubuntu-latest - container: ghcr.io/acts-project/ubuntu2404:58 + container: ghcr.io/acts-project/ubuntu2404:63 steps: - uses: actions/checkout@v4 + - name: Install dependencies + run: CI/dependencies.sh + - name: Cache build uses: actions/cache@v4 with: - path: ${{ github.workspace }}/ccache - key: ${{ runner.os }}-ccache-linux_ubuntu_debug_${{ env.CCACHE_KEY_SUFFIX }}_${{ github.sha }} + path: ${{ env.CCACHE_DIR }} + key: ccache-${{ runner.os }}-${{ github.job }}-${{ env.CCACHE_KEY_SUFFIX }}-${{ github.sha }} restore-keys: | - ${{ runner.os }}-ccache-linux_ubuntu_debug_${{ env.CCACHE_KEY_SUFFIX }}_ + ccache-${{ runner.os }}-${{ github.job }}-${{ env.CCACHE_KEY_SUFFIX }}- - name: Configure run: > @@ -49,6 +53,7 @@ jobs: --preset=github-ci -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-Werror --coverage -g -gz -g1" + -DPython_EXECUTABLE=$(which python3) -DACTS_BUILD_ODD=OFF - name: Build run: cmake --build build @@ -86,10 +91,14 @@ jobs: build_performance: runs-on: ubuntu-latest - container: ghcr.io/acts-project/ubuntu2404:58 + container: ghcr.io/acts-project/ubuntu2404:63 if: github.ref == 'refs/heads/main' steps: - uses: actions/checkout@v4 + + - name: Install dependencies + run: CI/dependencies.sh + - name: Install dependencies run: pip3 install git+https://github.com/paulgessinger/cmakeperf.git@2a409b5 - name: Configure @@ -98,6 +107,7 @@ jobs: --preset=github-ci -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_CXX_FLAGS="-Werror" + -DPython_EXECUTABLE=$(which python3) -DACTS_BUILD_ODD=OFF - name: Measure run: cmakeperf collect build/compile_commands.json -o perf.csv diff --git a/.github/workflows/builds.yml b/.github/workflows/builds.yml index 06312a6b339..010b7ff8963 100644 --- a/.github/workflows/builds.yml +++ b/.github/workflows/builds.yml @@ -19,32 +19,34 @@ env: HOMEBREW_NO_INSTALL_CLEANUP: 1 CCACHE_DIR: ${{ github.workspace }}/ccache CCACHE_MAXSIZE: 500M - CCACHE_KEY_SUFFIX: r1 + CCACHE_KEY_SUFFIX: r2 jobs: linux_ubuntu: runs-on: ubuntu-latest - container: ghcr.io/acts-project/ubuntu2404:58 + container: ghcr.io/acts-project/ubuntu2404:63 env: INSTALL_DIR: ${{ github.workspace }}/install ACTS_LOG_FAILURE_THRESHOLD: WARNING - steps: - - name: Install git lfs - run: apt-get update && apt-get install -y git-lfs + DEPENDENCY_URL: https://acts.web.cern.ch/ACTS/ci/ubuntu-24.04/deps.v4.tar.zst + steps: - uses: actions/checkout@v4 with: submodules: true lfs: true + - name: Install dependencies + run: CI/dependencies.sh + - name: Restore ccache uses: actions/cache/restore@v4 id: ccache-restore with: - path: ${{ github.workspace }}/ccache - key: ${{ runner.os }}-ccache-linux_ubuntu_${{ env.CCACHE_KEY_SUFFIX }}_${{ github.sha }} + path: ${{ env.CCACHE_DIR }} + key: ccache-${{ runner.os }}-${{ github.job }}-${{ env.CCACHE_KEY_SUFFIX }}-${{ github.sha }} restore-keys: | - ${{ runner.os }}-ccache-linux_ubuntu_${{ env.CCACHE_KEY_SUFFIX }}_ + ccache-${{ runner.os }}-${{ github.job }}-${{ env.CCACHE_KEY_SUFFIX }}- - name: Configure # setting CMAKE_CXX_STANDARD=20 is a workaround for a bug in the @@ -58,6 +60,7 @@ jobs: cmake -B build -S . --preset=github-ci -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}" + -DPython_EXECUTABLE=$(which python3) -DACTS_BUILD_PLUGIN_ONNX=ON - name: Build @@ -82,7 +85,6 @@ jobs: - name: Install run: cmake --build build --target install - - name: Package build run: tar czf build.tar.gz -C build --exclude "*.o" --exclude "bin/ActsUnitTest*" --exclude "bin/ActsIntegrationTest*" . @@ -108,20 +110,21 @@ jobs: linux_examples_test: runs-on: ubuntu-latest - container: ghcr.io/acts-project/ubuntu2404:58 + container: ghcr.io/acts-project/ubuntu2404:63 needs: [linux_ubuntu] env: ACTS_SEQUENCER_DISABLE_FPEMON: true + DEPENDENCY_URL: https://acts.web.cern.ch/ACTS/ci/ubuntu-24.04/deps.v4.tar.zst steps: - - name: Install git lfs - run: apt-get update && apt-get install -y git-lfs - - uses: actions/checkout@v4 with: submodules: true lfs: true + - name: Install dependencies + run: CI/dependencies.sh + - uses: actions/download-artifact@v4 with: name: acts-linux-ubuntu @@ -136,29 +139,31 @@ jobs: PYTEST_MD_REPORT_VERBOSE: 0 PYTEST_MD_REPORT_OUTPUT: pytest.md run: > - /usr/local/bin/geant4-config --install-datasets + geant4-config --install-datasets && source build/this_acts_withdeps.sh - && pip3 install -r Examples/Python/tests/requirements.txt - && pip3 install pytest-md-report + && python3 -m pip install -r Examples/Python/tests/requirements.txt + && python3 -m pip install pytest-md-report && pytest -rFsv -k "not exatrkx" -v && cat ${PYTEST_MD_REPORT_OUTPUT} >> $GITHUB_STEP_SUMMARY linux_physmon: runs-on: ubuntu-latest - container: ghcr.io/acts-project/ubuntu2404:58 + container: ghcr.io/acts-project/ubuntu2404:63 needs: [linux_ubuntu] env: ACTS_SEQUENCER_DISABLE_FPEMON: true + DEPENDENCY_URL: https://acts.web.cern.ch/ACTS/ci/ubuntu-24.04/deps.v4.tar.zst steps: - - name: Install git lfs - run: apt-get update && apt-get install -y git-lfs time - - uses: actions/checkout@v4 with: submodules: true lfs: true + - run: apt-get update && apt-get install -y time + - name: Install dependencies + run: CI/dependencies.sh + - uses: actions/download-artifact@v4 with: name: acts-linux-ubuntu @@ -178,10 +183,15 @@ jobs: run: > echo "::group::Dependencies" && git config --global safe.directory "$GITHUB_WORKSPACE" - && pip3 install histcmp==0.6.7 matplotlib - && pip3 install -r Examples/Scripts/requirements.txt - && /usr/local/bin/geant4-config --install-datasets + && python3 -m pip install histcmp==0.6.8 matplotlib + && python3 -m pip install -r Examples/Scripts/requirements.txt + && geant4-config --install-datasets + && venv_python=$(which python3) + && echo $venv_python && source build/this_acts_withdeps.sh + && export PATH=$(dirname $venv_python):$PATH + && echo $PATH + && which python3 && echo "::endgroup::" && CI/physmon/phys_perf_mon.sh all physmon @@ -232,27 +242,28 @@ jobs: std: 20 - image: ubuntu2204_clang std: 20 - container: ghcr.io/acts-project/${{ matrix.image }}:58 + container: ghcr.io/acts-project/${{ matrix.image }}:63 env: INSTALL_DIR: ${{ github.workspace }}/install ACTS_LOG_FAILURE_THRESHOLD: WARNING + DEPENDENCY_URL: https://acts.web.cern.ch/ACTS/ci/ubuntu-22.04/deps.v4.tar.zst steps: - - name: Install git lfs - run: apt-get update && apt-get install -y git-lfs - - uses: actions/checkout@v4 with: submodules: true lfs: true + - name: Install dependencies + run: CI/dependencies.sh + - name: Restore ccache uses: actions/cache/restore@v4 id: ccache-restore with: - path: ${{ github.workspace }}/ccache - key: ${{ runner.os }}-ccache-linux_${{ matrix.image }}_${{ env.CCACHE_KEY_SUFFIX }}_${{ github.sha }} + path: ${{ env.CCACHE_DIR }} + key: ccache-${{ runner.os }}-${{ github.job }}-${{ env.CCACHE_KEY_SUFFIX }}-${{ github.sha }} restore-keys: | - ${{ runner.os }}-ccache-linux_${{ matrix.image }}_${{ env.CCACHE_KEY_SUFFIX }}_ + ccache-${{ runner.os }}-${{ github.job }}-${{ env.CCACHE_KEY_SUFFIX }}- - name: Configure @@ -265,6 +276,7 @@ jobs: --preset=github-ci -DCMAKE_CXX_STANDARD=${{ matrix.std }} -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}" + -DPython_EXECUTABLE=$(which python3) - name: Build run: cmake --build build @@ -307,11 +319,8 @@ jobs: runs-on: macos-14 env: 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-14/deps.v2.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" + DEPENDENCY_URL: https://acts.web.cern.ch/ACTS/ci/macos-14/deps.v4.tar.zst steps: - uses: actions/checkout@v4 with: @@ -324,61 +333,65 @@ jobs: - name: Install dependencies run: > 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 }} - && tar -xf deps.tar.zst -C ${{ env.DEPENDENCY_DIR }} - && PATH="${{ env.DEPENDENCY_DIR }}/bin:$PATH" - && python3 -m pip install pyyaml jinja2 + && CI/dependencies.sh - name: Restore ccache uses: actions/cache/restore@v4 id: ccache-restore with: - path: ${{ github.workspace }}/ccache - key: ${{ runner.os }}-ccache_${{ env.CCACHE_KEY_SUFFIX }}_${{ github.sha }} + path: ${{ env.CCACHE_DIR }} + key: ccache-${{ runner.os }}-${{ github.job }}-${{ env.CCACHE_KEY_SUFFIX }}-${{ github.sha }} restore-keys: | - ${{ runner.os }}-ccache_${{ env.CCACHE_KEY_SUFFIX }}_ + ccache-${{ runner.os }}-${{ github.job }}-${{ env.CCACHE_KEY_SUFFIX }}- - name: Configure run: > ccache -z - && PATH="${{ env.DEPENDENCY_DIR }}/bin:$PATH" && cmake -B build -S . --preset=github-ci -DCMAKE_PREFIX_PATH="${{ env.DEPENDENCY_DIR }}" - -DPython_EXECUTABLE=${{ env.DEPENDENCY_DIR }}/bin/python3 -DCMAKE_INSTALL_PREFIX="${{ env.INSTALL_DIR }}" + -DPython_EXECUTABLE=$(which python3) + - name: Build run: cmake --build build + - name: ccache stats run: ccache -s + - name: Save ccache uses: actions/cache/save@v4 if: always() with: path: ${{ github.workspace }}/ccache key: ${{ steps.ccache-restore.outputs.cache-primary-key }} + - name: Unit tests run: cmake --build build --target test + - name: Integration tests run: cmake --build build --target integrationtests + - name: Install run: cmake --build build --target install + - uses: actions/upload-artifact@v4 with: name: acts-macos path: ${{ env.INSTALL_DIR }} + - name: Downstream configure run: > - PATH="${{ env.DEPENDENCY_DIR }}/bin:$PATH" - && cmake -B build-downstream -S Tests/DownstreamProject + cmake -B build-downstream -S Tests/DownstreamProject -GNinja -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS=-Werror -DCMAKE_CXX_STANDARD=20 -DCMAKE_PREFIX_PATH="${INSTALL_DIR}" + - name: Downstream build run: cmake --build build-downstream + - name: Downstream run run: > PATH="${{ env.DEPENDENCY_DIR }}/bin:$PATH" diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2e6b5f42fa9..a5cbbce542e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,12 +1,14 @@ variables: CCACHE_DIR: ${CI_PROJECT_DIR}/ccache CCACHE_MAXSIZE: 2G - CCACHE_KEY_SUFFIX: r1 + CCACHE_KEY_SUFFIX: r2 CTEST_OUTPUT_ON_FAILURE: 1 + DEPENDENCY_TAG: v4 + clang_tidy: stage: build - image: ghcr.io/acts-project/ubuntu2404:58 + image: ghcr.io/acts-project/ubuntu2404:63 tags: - large artifacts: @@ -14,6 +16,8 @@ clang_tidy: - src/clang-tidy/ when: always expire_in: 1 week + variables: + DEPENDENCY_URL: https://acts.web.cern.ch/ACTS/ci/ubuntu-24.04/deps.$DEPENDENCY_TAG.tar.zst script: - git clone $CLONE_URL src - cd src @@ -24,11 +28,15 @@ clang_tidy: && ln -sf /usr/bin/clang++-18 /usr/bin/clang++ && ln -sf /usr/bin/clang-18 /usr/bin/clang && ln -sf /usr/bin/clang-tidy-18 /usr/bin/clang-tidy + + - source CI/dependencies.sh + - > cmake -B build -S . --preset=gitlab-ci-clangtidy -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang + -DPython_EXECUTABLE=$(which python3) -DACTS_RUN_CLANG_TIDY=ON -DACTS_BUILD_ODD=OFF @@ -36,7 +44,7 @@ clang_tidy: - CI/clang_tidy/run_clang_tidy.sh clang-tidy build # Install dependencies for processing scripts - - pip install -r CI/clang_tidy/requirements.txt + - python3 -m pip install -r CI/clang_tidy/requirements.txt # Parse the main clang-tidy run - > @@ -55,14 +63,19 @@ clang_tidy: build_exatrkx_cpu: stage: build - image: ghcr.io/acts-project/ubuntu2204_exatrkx:58 + image: ghcr.io/acts-project/ubuntu2204_exatrkx:63 + variables: + DEPENDENCY_URL: https://acts.web.cern.ch/ACTS/ci/ubuntu-22.04/deps.$DEPENDENCY_TAG.tar.zst tags: - large cache: - key: ccache-exatrkx-cpu-$CI_COMMIT_REF_SLUG + key: ccache-${CI_JOB_NAME}-${CI_COMMIT_REF_SLUG}-${CCACHE_KEY_SUFFIX} + fallback_keys: + - ccache-${CI_JOB_NAME}-${CI_DEFAULT_BRANCH}-${CCACHE_KEY_SUFFIX} + when: always paths: - - ${CI_PROJECT_DIR}/ccache + - ${CCACHE_DIR} script: - export PATH=/usr/local/sbin:/usr/sbin:/sbin:$PATH @@ -72,12 +85,14 @@ build_exatrkx_cpu: - git clone $CLONE_URL src - cd src - git checkout $HEAD_SHA + - source CI/dependencies.sh - cd .. - mkdir build # Here we only do a minimal build without examples to save resources - > cmake -B build -S src --preset=gitlab-ci-exatrkx + -DPython_EXECUTABLE=$(which python3) -DACTS_EXATRKX_ENABLE_CUDA=OFF - ccache -z @@ -86,14 +101,19 @@ build_exatrkx_cpu: build_exatrkx: stage: build - image: ghcr.io/acts-project/ubuntu2204_exatrkx:58 + image: ghcr.io/acts-project/ubuntu2204_exatrkx:63 + variables: + DEPENDENCY_URL: https://acts.web.cern.ch/ACTS/ci/ubuntu-22.04/deps.$DEPENDENCY_TAG.tar.zst tags: - large cache: - key: ccache-exatrkx-$CI_COMMIT_REF_SLUG + key: ccache-${CI_JOB_NAME}-${CI_COMMIT_REF_SLUG}-${CCACHE_KEY_SUFFIX} + fallback_keys: + - ccache-${CI_JOB_NAME}-${CI_DEFAULT_BRANCH}-${CCACHE_KEY_SUFFIX} + when: always paths: - - ${CI_PROJECT_DIR}/ccache + - ${CCACHE_DIR} artifacts: paths: @@ -111,11 +131,13 @@ build_exatrkx: - git clone $CLONE_URL src - cd src - git checkout $HEAD_SHA + - source CI/dependencies.sh - cd .. - mkdir build - > cmake -B build -S src --preset=gitlab-ci-exatrkx + -DPython_EXECUTABLE=$(which python3) -DCMAKE_CUDA_ARCHITECTURES="75;86" - ccache -z @@ -126,7 +148,7 @@ build_exatrkx: # stage: test # needs: # - build_exatrkx -# image: ghcr.io/acts-project/ubuntu2204_exatrkx:58 +# image: ghcr.io/acts-project/ubuntu2204_exatrkx:63 # tags: # - docker-gpu-nvidia # script: @@ -136,7 +158,7 @@ build_exatrkx: # stage: test # needs: # - build_exatrkx -# image: ghcr.io/acts-project/ubuntu2204_exatrkx:58 +# image: ghcr.io/acts-project/ubuntu2204_exatrkx:63 # tags: # - docker-gpu-nvidia # script: @@ -152,13 +174,17 @@ build_exatrkx: build_linux_ubuntu: stage: build - image: ghcr.io/acts-project/ubuntu2404:58 + image: ghcr.io/acts-project/ubuntu2404:63 + variables: + DEPENDENCY_URL: https://acts.web.cern.ch/ACTS/ci/ubuntu-24.04/deps.$DEPENDENCY_TAG.tar.zst cache: - key: ccache-${CI_JOB_NAME_SLUG}-${HEAD_REF}-${CCACHE_KEY_SUFFIX} - when: 'always' + key: ccache-${CI_JOB_NAME}-${CI_COMMIT_REF_SLUG}-${CCACHE_KEY_SUFFIX} + fallback_keys: + - ccache-${CI_JOB_NAME}-${CI_DEFAULT_BRANCH}-${CCACHE_KEY_SUFFIX} + when: always paths: - - ${CI_PROJECT_DIR}/ccache + - ${CCACHE_DIR} artifacts: paths: @@ -177,12 +203,14 @@ build_linux_ubuntu: - git checkout $HEAD_SHA - git submodule init - git submodule update + - source CI/dependencies.sh - cd .. - mkdir build - > cmake -B build -S src --preset=gitlab-ci + -DPython_EXECUTABLE=$(which python3) -DACTS_BUILD_PLUGIN_ONNX=ON - ccache -z @@ -191,7 +219,9 @@ build_linux_ubuntu: linux_test_examples: stage: test - image: ghcr.io/acts-project/ubuntu2404:58 + image: ghcr.io/acts-project/ubuntu2404:63 + variables: + DEPENDENCY_URL: https://acts.web.cern.ch/ACTS/ci/ubuntu-24.04/deps.$DEPENDENCY_TAG.tar.zst needs: [build_linux_ubuntu] script: @@ -202,17 +232,20 @@ linux_test_examples: - git checkout $HEAD_SHA - git submodule init - git submodule update + - source CI/dependencies.sh - cd .. - - /usr/local/bin/geant4-config --install-datasets + - geant4-config --install-datasets - source build/this_acts_withdeps.sh - cd src - - pip3 install -r Examples/Python/tests/requirements.txt + - python3 -m pip install -r Examples/Python/tests/requirements.txt - pytest -rFsv -k "not exatrkx" -v -s linux_physmon: stage: test - image: ghcr.io/acts-project/ubuntu2404:58 + image: ghcr.io/acts-project/ubuntu2404:63 + variables: + DEPENDENCY_URL: https://acts.web.cern.ch/ACTS/ci/ubuntu-24.04/deps.$DEPENDENCY_TAG.tar.zst needs: [build_linux_ubuntu] artifacts: @@ -229,13 +262,19 @@ linux_physmon: - git checkout $HEAD_SHA - git submodule init - git submodule update + - source CI/dependencies.sh - cd .. - git config --global safe.directory "$GITHUB_WORKSPACE" - - pip3 install histcmp==0.6.7 matplotlib - - pip3 install -r src/Examples/Scripts/requirements.txt - - /usr/local/bin/geant4-config --install-datasets + - python3 -m pip install histcmp==0.6.8 matplotlib + - python3 -m pip install -r src/Examples/Scripts/requirements.txt + - geant4-config --install-datasets + - venv_python=$(which python3) + - echo $venv_python - source build/this_acts_withdeps.sh + - export PATH=$(dirname $venv_python):$PATH + - echo $PATH + - which python3 - cd src - CI/physmon/phys_perf_mon.sh all physmon @@ -243,17 +282,19 @@ linux_physmon: ### UBUNTU EXTRA JOB MATRIX ### ############################### -.linux_ubuntu_extra: &linux_ubuntu_extra +.linux_ubuntu_extra: variables: INSTALL_DIR: ${CI_PROJECT_DIR}/install stage: build cache: - key: ccache-${CI_JOB_NAME_SLUG}-${HEAD_REF}-${CCACHE_KEY_SUFFIX} - when: 'always' + key: ccache-${CI_JOB_NAME}-${CI_COMMIT_REF_SLUG}-${CCACHE_KEY_SUFFIX} + fallback_keys: + - ccache-${CI_JOB_NAME}-${CI_DEFAULT_BRANCH}-${CCACHE_KEY_SUFFIX} + when: always paths: - - ${CI_PROJECT_DIR}/ccache + - ${CCACHE_DIR} script: - git clone $CLONE_URL src @@ -262,12 +303,14 @@ linux_physmon: - git checkout $HEAD_SHA - git submodule init - git submodule update + - source CI/dependencies.sh - cd .. - mkdir build - > cmake -B build -S src --preset=gitlab-ci + -DPython_EXECUTABLE=$(which python3) -DCMAKE_CXX_STANDARD=${CXXSTD} - ccache -z @@ -295,25 +338,27 @@ linux_physmon: # Downstream run - ./build-downstream/bin/ShowActsVersion -linux_ubuntu_2404: - <<: *linux_ubuntu_extra +linux_ubuntu_2204: + extends: .linux_ubuntu_extra variables: CXXSTD: 20 - image: ghcr.io/acts-project/ubuntu2404:58 + DEPENDENCY_URL: https://acts.web.cern.ch/ACTS/ci/ubuntu-22.04/deps.$DEPENDENCY_TAG.tar.zst + image: ghcr.io/acts-project/ubuntu2204:63 linux_ubuntu_2204_clang: - <<: *linux_ubuntu_extra + extends: .linux_ubuntu_extra variables: CXXSTD: 20 - image: ghcr.io/acts-project/ubuntu2204_clang:58 + DEPENDENCY_URL: https://acts.web.cern.ch/ACTS/ci/ubuntu-22.04/deps.$DEPENDENCY_TAG.tar.zst + image: ghcr.io/acts-project/ubuntu2204_clang:63 ###################### ### LCG JOB MATRIX ### ###################### -.lcg: &lcg_base_job - image: ghcr.io/acts-project/${OS}-base:58 +.lcg_base_job: + image: ghcr.io/acts-project/${OS}-base:63 stage: build tags: - cvmfs @@ -325,10 +370,12 @@ linux_ubuntu_2204_clang: SETUP: cache: - key: ccache-${CI_JOB_NAME_SLUG}-${HEAD_REF}-${CCACHE_KEY_SUFFIX} - when: 'always' + key: ccache-${CI_JOB_NAME}-${CI_COMMIT_REF_SLUG}-${CCACHE_KEY_SUFFIX} + fallback_keys: + - ccache-${CI_JOB_NAME}-${CI_DEFAULT_BRANCH}-${CCACHE_KEY_SUFFIX} + when: always paths: - - ${CI_PROJECT_DIR}/ccache + - ${CCACHE_DIR} before_script: - 'echo "LCG_VERSION: ${LCG_VERSION}"' @@ -364,6 +411,7 @@ linux_ubuntu_2204_clang: cmake -B build -S src --preset=gitlab-ci -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}" + -DPython_EXECUTABLE=$(which python3) -DACTS_BUILD_PLUGIN_GEOMODEL=OFF # GeoModel is not in LCG at this point - ccache -z @@ -374,7 +422,7 @@ linux_ubuntu_2204_clang: lcg_105: - <<: *lcg_base_job + extends: .lcg_base_job variables: LCG_VERSION: "105" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ea1ef7ec79a..76af4847b7f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -44,7 +44,7 @@ repos: - id: license name: license language: system - entry: CI/check_license.py + entry: CI/check_license.py --fix files: \.(cpp|hpp|ipp|cu|cuh)$ - repo: local diff --git a/CI/check_unused_files.py b/CI/check_unused_files.py index 420ba932d14..c1f099d672a 100755 --- a/CI/check_unused_files.py +++ b/CI/check_unused_files.py @@ -41,8 +41,6 @@ def main(): ".gitignore", "README.md", "CMakeLists.txt", - "DetUtils.h", - "CommandLineArguments.h", # Filename not completed in source "vertexing_event_mu20_beamspot.csv", "vertexing_event_mu20_tracks.csv", diff --git a/CI/dependencies.sh b/CI/dependencies.sh new file mode 100755 index 00000000000..7c8879b499e --- /dev/null +++ b/CI/dependencies.sh @@ -0,0 +1,103 @@ +#!/bin/bash + +function run() { + set -x + "$@" + { set +x; } 2> /dev/null +} + +function set_env { + key="$1" + value="$2" + + echo "=> ${key}=${value}" + + if [ -n "${GITHUB_ACTIONS:-}" ]; then + echo "${key}=${value}" >> $GITHUB_ENV + else + export ${key}=${value} + fi +} + +url=${1:-${DEPENDENCY_URL:-}} + +if [ -n "${GITHUB_ACTIONS:-}" ]; then + destination="${GITHUB_WORKSPACE}/dependencies" +elif [ -n "${GITLAB_CI:-}" ];then + destination="${CI_PROJECT_DIR}/dependencies" +else + destination=${2} +fi + +set_env DEPENDENCY_DIR "${destination}" + +if [ -z "${url}" ]; then + echo "url is not set" + exit 1 +fi + +echo "URL: $url" +echo "DESTINATION: $destination" + +# check curl location +CURL=$(command -v curl) +if [ -z "$CURL" ]; then + echo "curl is not available" + exit 1 +fi + +UNZSTD=$(command -v unzstd) +if [ -z "$UNZSTD" ]; then + echo "unzstd is not available" + exit 1 +fi + +TAR=$(command -v tar) +if [ -z "$TAR" ]; then + echo "tar is not available" + exit 1 +fi + +run mkdir -p "${destination}" + +run $CURL \ + --retry 5 \ + --connect-timeout 2 \ + --location $url \ + | unzstd \ + | tar \ + -x \ + --strip-components=1 \ + --directory "${destination}" + +# Patch up geant4-config data install script +out=$(${destination}/bin/geant4-config --datasets) +line=$(echo "$out" | head -n1) +orig_share=$(echo "$line" | perl -pe 's|.*?(\/.*)\/share.*|\1|') +orig_share_escaped=$(echo $orig_share|perl -pe 's|/|\\/|g') +destination_escaped=$(echo "$destination"|perl -pe 's|/|\\/|g') +perl -pi.bak -e "s/$orig_share_escaped/$destination_escaped/g" ${destination}/bin/geant4-config + +if [ -n "${GITHUB_ACTIONS:-}" ]; then + echo "Running in GitHub Actions" + venv="${GITHUB_WORKSPACE}/venv" +fi + +if [ -n "${GITLAB_CI:-}" ];then + echo "Running in GitLab CI" + venv="${CI_PROJECT_DIR}/venv" +fi + +if [ -n "${CI:-}" ];then + run "${destination}/bin/python3" -m venv "${venv}" + run "${venv}/bin/python3" -m pip install pyyaml jinja2 + set_env PATH "${venv}/bin:${destination}/bin/:${PATH}" +fi + +set_env CMAKE_PREFIX_PATH "${destination}" +set_env LD_LIBRARY_PATH "${destination}/lib" +set_env ROOT_INCLUDE_PATH "${destination}/include" +# Geant4 puts CLHEP in a subdirectory +set_env ROOT_INCLUDE_PATH "${destination}/include/Geant4" +# Pythia8 looks for settings in this directory +set_env PYTHIA8DATA "${destination}/share/Pythia8/xmldoc" diff --git a/CI/physmon/phys_perf_mon.sh b/CI/physmon/phys_perf_mon.sh index 841fad5c376..c2944f0dd06 100755 --- a/CI/physmon/phys_perf_mon.sh +++ b/CI/physmon/phys_perf_mon.sh @@ -15,7 +15,7 @@ function run() { export run - +run which python3 shopt -s extglob @@ -223,13 +223,22 @@ function trackfinding() { fi run_histcmp \ - $outdir/data/$path/performance_ckf.root \ - $refdir/$path/performance_ckf.root \ - "CKF | ${name}" \ - $path/performance_ckf.html \ - $path/performance_ckf_plots \ + $outdir/data/$path/performance_finding_ckf.root \ + $refdir/$path/performance_finding_ckf.root \ + "CKF finding performance | ${name}" \ + $path/performance_finding_ckf.html \ + $path/performance_finding_ckf_plots \ --config $default_config + run_histcmp \ + $outdir/data/$path/performance_fitting_ckf.root \ + $refdir/$path/performance_fitting_ckf.root \ + "CKF fitting performance | ${name}" \ + $path/performance_fitting_ckf.html \ + $path/performance_fitting_ckf_plots \ + --config $default_config + + run Examples/Scripts/generic_plotter.py \ $outdir/data/$path/tracksummary_ckf.root \ tracksummary \ @@ -244,17 +253,17 @@ function trackfinding() { run_histcmp \ $outdir/data/$path/tracksummary_ckf_hist.root \ $refdir/$path/tracksummary_ckf_hist.root \ - "Track Summary CKF | ${name}" \ + "CKF track summary | ${name}" \ $path/tracksummary_ckf.html \ $path/tracksummary_ckf_plots - if [ -f $refdir/$path/performance_ckf_ambi.root ]; then + if [ -f $refdir/$path/performance_finding_ckf_ambi.root ]; then run_histcmp \ - $outdir/data/$path/performance_ckf_ambi.root \ - $refdir/$path/performance_ckf_ambi.root \ - "Ambisolver | ${name}" \ - $path/performance_ckf_ambi.html \ - $path/performance_ckf_ambi + $outdir/data/$path/performance_finding_ckf_ambi.root \ + $refdir/$path/performance_finding_ckf_ambi.root \ + "Ambisolver finding performance | ${name}" \ + $path/performance_finding_ckf_ambi.html \ + $path/performance_finding_ckf_ambi fi } diff --git a/CI/physmon/reference/simulation/particles_ttbar_hist.root b/CI/physmon/reference/simulation/particles_ttbar_hist.root index 9100c71418a..4b8b8c552e0 100644 Binary files a/CI/physmon/reference/simulation/particles_ttbar_hist.root and b/CI/physmon/reference/simulation/particles_ttbar_hist.root differ diff --git a/CI/physmon/reference/simulation/vertices_ttbar_hist.root b/CI/physmon/reference/simulation/vertices_ttbar_hist.root index 9e54eaed90e..7dc8182b96a 100644 Binary files a/CI/physmon/reference/simulation/vertices_ttbar_hist.root and b/CI/physmon/reference/simulation/vertices_ttbar_hist.root differ diff --git a/CI/physmon/reference/trackfinding_1muon/orthogonal/performance_ckf.root b/CI/physmon/reference/trackfinding_1muon/orthogonal/performance_ckf.root deleted file mode 100644 index 305a3bf724f..00000000000 Binary files a/CI/physmon/reference/trackfinding_1muon/orthogonal/performance_ckf.root and /dev/null differ diff --git a/CI/physmon/reference/trackfinding_1muon/orthogonal/performance_finding_ckf.root b/CI/physmon/reference/trackfinding_1muon/orthogonal/performance_finding_ckf.root new file mode 100644 index 00000000000..b2e59570e85 Binary files /dev/null and b/CI/physmon/reference/trackfinding_1muon/orthogonal/performance_finding_ckf.root differ diff --git a/CI/physmon/reference/trackfinding_1muon/orthogonal/performance_fitting_ckf.root b/CI/physmon/reference/trackfinding_1muon/orthogonal/performance_fitting_ckf.root new file mode 100644 index 00000000000..36c779d4846 Binary files /dev/null and b/CI/physmon/reference/trackfinding_1muon/orthogonal/performance_fitting_ckf.root differ diff --git a/CI/physmon/reference/trackfinding_1muon/orthogonal/performance_seeding.root b/CI/physmon/reference/trackfinding_1muon/orthogonal/performance_seeding.root index d55d3833570..1049ad5b18b 100644 Binary files a/CI/physmon/reference/trackfinding_1muon/orthogonal/performance_seeding.root and b/CI/physmon/reference/trackfinding_1muon/orthogonal/performance_seeding.root differ diff --git a/CI/physmon/reference/trackfinding_1muon/seeded/performance_ckf.root b/CI/physmon/reference/trackfinding_1muon/seeded/performance_ckf.root deleted file mode 100644 index a9a127efa07..00000000000 Binary files a/CI/physmon/reference/trackfinding_1muon/seeded/performance_ckf.root and /dev/null differ diff --git a/CI/physmon/reference/trackfinding_1muon/seeded/performance_finding_ckf.root b/CI/physmon/reference/trackfinding_1muon/seeded/performance_finding_ckf.root new file mode 100644 index 00000000000..7f59b99cf7e Binary files /dev/null and b/CI/physmon/reference/trackfinding_1muon/seeded/performance_finding_ckf.root differ diff --git a/CI/physmon/reference/trackfinding_1muon/seeded/performance_fitting_ckf.root b/CI/physmon/reference/trackfinding_1muon/seeded/performance_fitting_ckf.root new file mode 100644 index 00000000000..5ba97ecd168 Binary files /dev/null and b/CI/physmon/reference/trackfinding_1muon/seeded/performance_fitting_ckf.root differ diff --git a/CI/physmon/reference/trackfinding_1muon/seeded/performance_seeding.root b/CI/physmon/reference/trackfinding_1muon/seeded/performance_seeding.root index 0c64e9fe631..d91320f3d9a 100644 Binary files a/CI/physmon/reference/trackfinding_1muon/seeded/performance_seeding.root and b/CI/physmon/reference/trackfinding_1muon/seeded/performance_seeding.root differ diff --git a/CI/physmon/reference/trackfinding_1muon/truth_estimated/performance_ckf.root b/CI/physmon/reference/trackfinding_1muon/truth_estimated/performance_ckf.root deleted file mode 100644 index 8b9f8ae4d1d..00000000000 Binary files a/CI/physmon/reference/trackfinding_1muon/truth_estimated/performance_ckf.root and /dev/null differ diff --git a/CI/physmon/reference/trackfinding_1muon/truth_estimated/performance_finding_ckf.root b/CI/physmon/reference/trackfinding_1muon/truth_estimated/performance_finding_ckf.root new file mode 100644 index 00000000000..b4def41bfb5 Binary files /dev/null and b/CI/physmon/reference/trackfinding_1muon/truth_estimated/performance_finding_ckf.root differ diff --git a/CI/physmon/reference/trackfinding_1muon/truth_estimated/performance_fitting_ckf.root b/CI/physmon/reference/trackfinding_1muon/truth_estimated/performance_fitting_ckf.root new file mode 100644 index 00000000000..3fcdb6021d1 Binary files /dev/null and b/CI/physmon/reference/trackfinding_1muon/truth_estimated/performance_fitting_ckf.root differ diff --git a/CI/physmon/reference/trackfinding_1muon/truth_estimated/performance_seeding.root b/CI/physmon/reference/trackfinding_1muon/truth_estimated/performance_seeding.root index 06abee42be7..4d134bc87d3 100644 Binary files a/CI/physmon/reference/trackfinding_1muon/truth_estimated/performance_seeding.root and b/CI/physmon/reference/trackfinding_1muon/truth_estimated/performance_seeding.root differ diff --git a/CI/physmon/reference/trackfinding_1muon/truth_smeared/performance_ckf.root b/CI/physmon/reference/trackfinding_1muon/truth_smeared/performance_ckf.root deleted file mode 100644 index e38e388edce..00000000000 Binary files a/CI/physmon/reference/trackfinding_1muon/truth_smeared/performance_ckf.root and /dev/null differ diff --git a/CI/physmon/reference/trackfinding_1muon/truth_smeared/performance_finding_ckf.root b/CI/physmon/reference/trackfinding_1muon/truth_smeared/performance_finding_ckf.root new file mode 100644 index 00000000000..10f10907b8d Binary files /dev/null and b/CI/physmon/reference/trackfinding_1muon/truth_smeared/performance_finding_ckf.root differ diff --git a/CI/physmon/reference/trackfinding_1muon/truth_smeared/performance_fitting_ckf.root b/CI/physmon/reference/trackfinding_1muon/truth_smeared/performance_fitting_ckf.root new file mode 100644 index 00000000000..1ca5e629d35 Binary files /dev/null and b/CI/physmon/reference/trackfinding_1muon/truth_smeared/performance_fitting_ckf.root differ diff --git a/CI/physmon/reference/trackfinding_4muon_50vertices/performance_ckf.root b/CI/physmon/reference/trackfinding_4muon_50vertices/performance_ckf.root deleted file mode 100644 index c4507b9636a..00000000000 Binary files a/CI/physmon/reference/trackfinding_4muon_50vertices/performance_ckf.root and /dev/null differ diff --git a/CI/physmon/reference/trackfinding_4muon_50vertices/performance_ckf_ambi.root b/CI/physmon/reference/trackfinding_4muon_50vertices/performance_ckf_ambi.root deleted file mode 100644 index 35b860dcb8e..00000000000 Binary files a/CI/physmon/reference/trackfinding_4muon_50vertices/performance_ckf_ambi.root and /dev/null differ diff --git a/CI/physmon/reference/trackfinding_4muon_50vertices/performance_finding_ckf.root b/CI/physmon/reference/trackfinding_4muon_50vertices/performance_finding_ckf.root new file mode 100644 index 00000000000..71bfd26dfb8 Binary files /dev/null and b/CI/physmon/reference/trackfinding_4muon_50vertices/performance_finding_ckf.root differ diff --git a/CI/physmon/reference/trackfinding_4muon_50vertices/performance_finding_ckf_ambi.root b/CI/physmon/reference/trackfinding_4muon_50vertices/performance_finding_ckf_ambi.root new file mode 100644 index 00000000000..39d7dc1a31f Binary files /dev/null and b/CI/physmon/reference/trackfinding_4muon_50vertices/performance_finding_ckf_ambi.root differ diff --git a/CI/physmon/reference/trackfinding_4muon_50vertices/performance_fitting_ckf.root b/CI/physmon/reference/trackfinding_4muon_50vertices/performance_fitting_ckf.root new file mode 100644 index 00000000000..b90f40313eb Binary files /dev/null and b/CI/physmon/reference/trackfinding_4muon_50vertices/performance_fitting_ckf.root differ diff --git a/CI/physmon/reference/trackfinding_4muon_50vertices/performance_fitting_ckf_ambi.root b/CI/physmon/reference/trackfinding_4muon_50vertices/performance_fitting_ckf_ambi.root new file mode 100644 index 00000000000..ff59dc310eb Binary files /dev/null and b/CI/physmon/reference/trackfinding_4muon_50vertices/performance_fitting_ckf_ambi.root differ diff --git a/CI/physmon/reference/trackfinding_4muon_50vertices/performance_seeding.root b/CI/physmon/reference/trackfinding_4muon_50vertices/performance_seeding.root index 0a59b0fba85..e79e159caa2 100644 Binary files a/CI/physmon/reference/trackfinding_4muon_50vertices/performance_seeding.root and b/CI/physmon/reference/trackfinding_4muon_50vertices/performance_seeding.root differ diff --git a/CI/physmon/reference/trackfinding_ttbar_pu200/performance_ckf.root b/CI/physmon/reference/trackfinding_ttbar_pu200/performance_ckf.root deleted file mode 100644 index 2c7626e0516..00000000000 Binary files a/CI/physmon/reference/trackfinding_ttbar_pu200/performance_ckf.root and /dev/null differ diff --git a/CI/physmon/reference/trackfinding_ttbar_pu200/performance_ckf_ambi.root b/CI/physmon/reference/trackfinding_ttbar_pu200/performance_ckf_ambi.root deleted file mode 100644 index c5d08a93db0..00000000000 Binary files a/CI/physmon/reference/trackfinding_ttbar_pu200/performance_ckf_ambi.root and /dev/null differ diff --git a/CI/physmon/reference/trackfinding_ttbar_pu200/performance_finding_ckf.root b/CI/physmon/reference/trackfinding_ttbar_pu200/performance_finding_ckf.root new file mode 100644 index 00000000000..d4b5a8b9dde Binary files /dev/null and b/CI/physmon/reference/trackfinding_ttbar_pu200/performance_finding_ckf.root differ diff --git a/CI/physmon/reference/trackfinding_ttbar_pu200/performance_finding_ckf_ambi.root b/CI/physmon/reference/trackfinding_ttbar_pu200/performance_finding_ckf_ambi.root new file mode 100644 index 00000000000..a083efffaff Binary files /dev/null and b/CI/physmon/reference/trackfinding_ttbar_pu200/performance_finding_ckf_ambi.root differ diff --git a/CI/physmon/reference/trackfinding_ttbar_pu200/performance_fitting_ckf.root b/CI/physmon/reference/trackfinding_ttbar_pu200/performance_fitting_ckf.root new file mode 100644 index 00000000000..09d2dc033af Binary files /dev/null and b/CI/physmon/reference/trackfinding_ttbar_pu200/performance_fitting_ckf.root differ diff --git a/CI/physmon/reference/trackfinding_ttbar_pu200/performance_fitting_ckf_ambi.root b/CI/physmon/reference/trackfinding_ttbar_pu200/performance_fitting_ckf_ambi.root new file mode 100644 index 00000000000..949d8cebfc3 Binary files /dev/null and b/CI/physmon/reference/trackfinding_ttbar_pu200/performance_fitting_ckf_ambi.root differ diff --git a/CI/physmon/reference/trackfinding_ttbar_pu200/performance_seeding.root b/CI/physmon/reference/trackfinding_ttbar_pu200/performance_seeding.root index 5e072e1393c..500783b48a4 100644 Binary files a/CI/physmon/reference/trackfinding_ttbar_pu200/performance_seeding.root and b/CI/physmon/reference/trackfinding_ttbar_pu200/performance_seeding.root differ diff --git a/CI/physmon/reference/trackfinding_ttbar_pu200/performance_vertexing_amvf_gauss_notime_hist.root b/CI/physmon/reference/trackfinding_ttbar_pu200/performance_vertexing_amvf_gauss_notime_hist.root index 26472832eeb..8d1bf337631 100644 Binary files a/CI/physmon/reference/trackfinding_ttbar_pu200/performance_vertexing_amvf_gauss_notime_hist.root and b/CI/physmon/reference/trackfinding_ttbar_pu200/performance_vertexing_amvf_gauss_notime_hist.root differ diff --git a/CI/physmon/reference/trackfinding_ttbar_pu200/performance_vertexing_amvf_grid_time_hist.root b/CI/physmon/reference/trackfinding_ttbar_pu200/performance_vertexing_amvf_grid_time_hist.root index 1a1651abd5c..25110c369be 100644 Binary files a/CI/physmon/reference/trackfinding_ttbar_pu200/performance_vertexing_amvf_grid_time_hist.root and b/CI/physmon/reference/trackfinding_ttbar_pu200/performance_vertexing_amvf_grid_time_hist.root differ diff --git a/CI/physmon/reference/trackfinding_ttbar_pu200/tracksummary_ckf_hist.root b/CI/physmon/reference/trackfinding_ttbar_pu200/tracksummary_ckf_hist.root index 74c3632898b..f803f21ee8f 100644 Binary files a/CI/physmon/reference/trackfinding_ttbar_pu200/tracksummary_ckf_hist.root and b/CI/physmon/reference/trackfinding_ttbar_pu200/tracksummary_ckf_hist.root differ diff --git a/CI/physmon/reference/trackfitting_gsf/performance_trackfitting.root b/CI/physmon/reference/trackfitting_gsf/performance_trackfitting.root index 3d2eaa11044..b3543963d9f 100644 Binary files a/CI/physmon/reference/trackfitting_gsf/performance_trackfitting.root and b/CI/physmon/reference/trackfitting_gsf/performance_trackfitting.root differ diff --git a/CI/physmon/reference/trackfitting_gx2f/performance_trackfitting.root b/CI/physmon/reference/trackfitting_gx2f/performance_trackfitting.root index 8fae64cd735..21533ce8076 100644 Binary files a/CI/physmon/reference/trackfitting_gx2f/performance_trackfitting.root and b/CI/physmon/reference/trackfitting_gx2f/performance_trackfitting.root differ diff --git a/CI/physmon/reference/trackfitting_kf/performance_trackfitting.root b/CI/physmon/reference/trackfitting_kf/performance_trackfitting.root index aade25ba5a2..4e3f44e2b34 100644 Binary files a/CI/physmon/reference/trackfitting_kf/performance_trackfitting.root and b/CI/physmon/reference/trackfitting_kf/performance_trackfitting.root differ diff --git a/CI/physmon/reference/trackrefitting_gsf/performance_trackrefitting.root b/CI/physmon/reference/trackrefitting_gsf/performance_trackrefitting.root index d888ad406d8..b6b8d6fd126 100644 Binary files a/CI/physmon/reference/trackrefitting_gsf/performance_trackrefitting.root and b/CI/physmon/reference/trackrefitting_gsf/performance_trackrefitting.root differ diff --git a/CI/physmon/reference/trackrefitting_kf/performance_trackrefitting.root b/CI/physmon/reference/trackrefitting_kf/performance_trackrefitting.root index aade25ba5a2..99385589d48 100644 Binary files a/CI/physmon/reference/trackrefitting_kf/performance_trackrefitting.root and b/CI/physmon/reference/trackrefitting_kf/performance_trackrefitting.root differ diff --git a/CI/physmon/workflows/physmon_trackfinding_1muon.py b/CI/physmon/workflows/physmon_trackfinding_1muon.py index d06f99fbdb6..aaa4bc9f71d 100755 --- a/CI/physmon/workflows/physmon_trackfinding_1muon.py +++ b/CI/physmon/workflows/physmon_trackfinding_1muon.py @@ -11,13 +11,13 @@ EtaConfig, PhiConfig, ParticleConfig, + ParticleSelectorConfig, addFatras, addDigitization, ) from acts.examples.reconstruction import ( addSeeding, - TruthSeedRanges, ParticleSmearingSigmas, SeedFinderConfigArg, SeedFinderOptionsArg, @@ -72,6 +72,11 @@ def run_ckf_tracking(label, seeding): setup.field, enableInteractions=True, rnd=rnd, + postSelectParticles=ParticleSelectorConfig( + pt=(0.9 * u.GeV, None), + measurements=(9, None), + removeNeutral=True, + ), ) addDigitization( @@ -86,7 +91,6 @@ def run_ckf_tracking(label, seeding): s, setup.trackingGeometry, setup.field, - TruthSeedRanges(pt=(500 * u.MeV, None), nHits=(9, None)), ParticleSmearingSigmas( # only used by SeedingAlgorithm.TruthSmeared # zero eveything so the CKF has a chance to find the measurements d0=0, @@ -108,7 +112,7 @@ def run_ckf_tracking(label, seeding): maxSeedsPerSpM=1, sigmaScattering=5, radLengthPerSeed=0.1, - minPt=500 * u.MeV, + minPt=0.5 * u.GeV, impactMax=3 * u.mm, ), SeedFinderOptionsArg(bFieldInZ=2 * u.T), @@ -134,7 +138,7 @@ def run_ckf_tracking(label, seeding): setup.trackingGeometry, setup.field, TrackSelectorConfig( - pt=(500 * u.MeV, None), + pt=(0.9 * u.GeV, None), loc0=(-4.0 * u.mm, 4.0 * u.mm), nMeasurementsMin=6, maxHoles=2, @@ -159,8 +163,9 @@ def run_ckf_tracking(label, seeding): if seeding != SeedingAlgorithm.TruthSmeared else [] ) + [ - "performance_ckf.root", "tracksummary_ckf.root", + "performance_finding_ckf.root", + "performance_fitting_ckf.root", ]: perf_file = tp / file assert perf_file.exists(), f"Performance file not found {perf_file}" diff --git a/CI/physmon/workflows/physmon_trackfinding_4muon_50vertices.py b/CI/physmon/workflows/physmon_trackfinding_4muon_50vertices.py index e1ece122c45..1a119c8ed6c 100755 --- a/CI/physmon/workflows/physmon_trackfinding_4muon_50vertices.py +++ b/CI/physmon/workflows/physmon_trackfinding_4muon_50vertices.py @@ -11,12 +11,12 @@ EtaConfig, PhiConfig, ParticleConfig, + ParticleSelectorConfig, addFatras, addDigitization, ) from acts.examples.reconstruction import ( addSeeding, - TruthSeedRanges, SeedFinderConfigArg, SeedFinderOptionsArg, SeedingAlgorithm, @@ -69,6 +69,11 @@ setup.trackingGeometry, setup.field, rnd=rnd, + postSelectParticles=ParticleSelectorConfig( + pt=(0.9 * u.GeV, None), + measurements=(9, None), + removeNeutral=True, + ), ) addDigitization( @@ -83,7 +88,6 @@ s, setup.trackingGeometry, setup.field, - TruthSeedRanges(pt=(500.0 * u.MeV, None), nHits=(9, None)), SeedFinderConfigArg( r=(33 * u.mm, 200 * u.mm), deltaR=(1 * u.mm, 60 * u.mm), @@ -92,7 +96,7 @@ maxSeedsPerSpM=1, sigmaScattering=5, radLengthPerSeed=0.1, - minPt=500 * u.MeV, + minPt=0.5 * u.GeV, impactMax=3 * u.mm, ), SeedFinderOptionsArg(bFieldInZ=2 * u.T, beamPos=(0.0, 0.0)), @@ -116,7 +120,7 @@ setup.trackingGeometry, setup.field, TrackSelectorConfig( - pt=(500 * u.MeV, None), + pt=(0.9 * u.GeV, None), loc0=(-4.0 * u.mm, 4.0 * u.mm), nMeasurementsMin=6, maxHoles=2, @@ -192,8 +196,12 @@ s.run() shutil.move( - tp / "performance_ambi.root", - tp / "performance_ckf_ambi.root", + tp / "performance_finding_ambi.root", + tp / "performance_finding_ckf_ambi.root", + ) + shutil.move( + tp / "performance_fitting_ambi.root", + tp / "performance_fitting_ckf_ambi.root", ) for vertexing in ["ivf_notime", "amvf_gauss_notime", "amvf_grid_time"]: shutil.move( @@ -204,8 +212,10 @@ for file in [ "performance_seeding.root", "tracksummary_ckf.root", - "performance_ckf.root", - "performance_ckf_ambi.root", + "performance_finding_ckf.root", + "performance_fitting_ckf.root", + "performance_finding_ckf_ambi.root", + "performance_fitting_ckf_ambi.root", "performance_vertexing_ivf_notime.root", "performance_vertexing_amvf_gauss_notime.root", "performance_vertexing_amvf_grid_time.root", diff --git a/CI/physmon/workflows/physmon_trackfinding_ttbar_pu200.py b/CI/physmon/workflows/physmon_trackfinding_ttbar_pu200.py index 172fa55270a..99f12d0170d 100755 --- a/CI/physmon/workflows/physmon_trackfinding_ttbar_pu200.py +++ b/CI/physmon/workflows/physmon_trackfinding_ttbar_pu200.py @@ -13,7 +13,6 @@ ) from acts.examples.reconstruction import ( addSeeding, - TruthSeedRanges, SeedFinderConfigArg, SeedFinderOptionsArg, SeedingAlgorithm, @@ -68,6 +67,11 @@ rho=(0.0, 24 * u.mm), absZ=(0.0, 1.0 * u.m), ), + postSelectParticles=ParticleSelectorConfig( + pt=(0.5 * u.GeV, None), + measurements=(9, None), + removeNeutral=True, + ), ) addDigitization( @@ -82,7 +86,6 @@ s, setup.trackingGeometry, setup.field, - TruthSeedRanges(pt=(500.0 * u.MeV, None), nHits=(9, None)), SeedFinderConfigArg( r=(33 * u.mm, 200 * u.mm), deltaR=(1 * u.mm, 60 * u.mm), @@ -91,7 +94,7 @@ maxSeedsPerSpM=1, sigmaScattering=5, radLengthPerSeed=0.1, - minPt=500 * u.MeV, + minPt=0.5 * u.GeV, impactMax=3 * u.mm, ), SeedFinderOptionsArg(bFieldInZ=2 * u.T, beamPos=(0.0, 0.0)), @@ -115,7 +118,7 @@ setup.trackingGeometry, setup.field, TrackSelectorConfig( - pt=(500 * u.MeV, None), + pt=(0.5 * u.GeV, None), loc0=(-4.0 * u.mm, 4.0 * u.mm), nMeasurementsMin=6, maxHoles=2, @@ -177,8 +180,12 @@ s.run() shutil.move( - tp / "performance_ambi.root", - tp / "performance_ckf_ambi.root", + tp / "performance_finding_ambi.root", + tp / "performance_finding_ckf_ambi.root", + ) + shutil.move( + tp / "performance_fitting_ambi.root", + tp / "performance_fitting_ckf_ambi.root", ) for vertexing in ["amvf_gauss_notime", "amvf_grid_time"]: shutil.move( @@ -189,8 +196,10 @@ for file in [ "performance_seeding.root", "tracksummary_ckf.root", - "performance_ckf.root", - "performance_ckf_ambi.root", + "performance_finding_ckf.root", + "performance_fitting_ckf.root", + "performance_finding_ckf_ambi.root", + "performance_fitting_ckf_ambi.root", "performance_vertexing_amvf_gauss_notime.root", "performance_vertexing_amvf_grid_time.root", ]: diff --git a/CMakeLists.txt b/CMakeLists.txt index e8e9ab3f583..f81002cab83 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -227,6 +227,7 @@ endif() set(_acts_actsvg_version 0.4.50) set(_acts_boost_version 1.71.0) set(_acts_dd4hep_version 1.21) +set(_acts_geant4_version 11.1.3) set(_acts_edm4hep_version 0.7) set(_acts_eigen3_version 3.4.0) set(_acts_podio_version 1.0.1) # will try this first @@ -453,7 +454,7 @@ if(ACTS_BUILD_PLUGIN_EDM4HEP) find_package(EDM4HEP ${_acts_edm4hep_version} REQUIRED CONFIG) endif() if(ACTS_BUILD_PLUGIN_GEANT4) - find_package(Geant4 REQUIRED CONFIG COMPONENTS gdml) + find_package(Geant4 ${_acts_geant4_version} REQUIRED CONFIG COMPONENTS gdml) endif() if(ACTS_BUILD_PLUGIN_TRACCC) diff --git a/Core/CMakeLists.txt b/Core/CMakeLists.txt index eeb6bc8b92a..554656f514c 100644 --- a/Core/CMakeLists.txt +++ b/Core/CMakeLists.txt @@ -110,6 +110,7 @@ add_subdirectory(src/MagneticField) add_subdirectory(src/Material) add_subdirectory(src/Navigation) add_subdirectory(src/Propagator) +add_subdirectory(src/Seeding) add_subdirectory(src/Surfaces) add_subdirectory(src/TrackFinding) add_subdirectory(src/TrackFitting) diff --git a/Core/include/Acts/EventData/GenericBoundTrackParameters.hpp b/Core/include/Acts/EventData/GenericBoundTrackParameters.hpp index 27b411a99cc..f624cd88aee 100644 --- a/Core/include/Acts/EventData/GenericBoundTrackParameters.hpp +++ b/Core/include/Acts/EventData/GenericBoundTrackParameters.hpp @@ -250,6 +250,17 @@ class GenericBoundTrackParameters { return m_surface->referenceFrame(geoCtx, position(geoCtx), momentum()); } + /// Reflect the parameters in place. + void reflectInPlace() { m_params = reflectBoundParameters(m_params); } + + /// Reflect the parameters. + /// @return Reflected parameters. + GenericBoundTrackParameters reflect() const { + GenericBoundTrackParameters reflected = *this; + reflected.reflectInPlace(); + return reflected; + } + private: BoundVector m_params; std::optional m_cov; diff --git a/Core/include/Acts/EventData/GenericCurvilinearTrackParameters.hpp b/Core/include/Acts/EventData/GenericCurvilinearTrackParameters.hpp index a42ac2f116f..6e4ed9bae7a 100644 --- a/Core/include/Acts/EventData/GenericCurvilinearTrackParameters.hpp +++ b/Core/include/Acts/EventData/GenericCurvilinearTrackParameters.hpp @@ -111,6 +111,14 @@ class GenericCurvilinearTrackParameters Vector3 position() const { return GenericBoundTrackParameters::position({}); } + + /// Reflect the parameters. + /// @return Reflected parameters. + GenericCurvilinearTrackParameters reflect() const { + GenericCurvilinearTrackParameters reflected = *this; + reflected.reflectInPlace(); + return reflected; + } }; } // namespace Acts diff --git a/Core/include/Acts/EventData/GenericFreeTrackParameters.hpp b/Core/include/Acts/EventData/GenericFreeTrackParameters.hpp index 1e7846318ef..214aa2e1551 100644 --- a/Core/include/Acts/EventData/GenericFreeTrackParameters.hpp +++ b/Core/include/Acts/EventData/GenericFreeTrackParameters.hpp @@ -12,9 +12,11 @@ #include "Acts/Definitions/Common.hpp" #include "Acts/Definitions/TrackParametrization.hpp" #include "Acts/EventData/TrackParametersConcept.hpp" +#include "Acts/EventData/TransformationHelpers.hpp" #include "Acts/EventData/detail/PrintParameters.hpp" #include "Acts/Utilities/MathHelpers.hpp" #include "Acts/Utilities/UnitVectors.hpp" +#include "Acts/Utilities/VectorHelpers.hpp" #include #include @@ -55,6 +57,29 @@ class GenericFreeTrackParameters { m_cov(std::move(cov)), m_particleHypothesis(std::move(particleHypothesis)) {} + /// Construct from four-position, direction, absolute momentum, and charge. + /// + /// @param pos4 Track position/time four-vector + /// @param dir Track direction three-vector; normalization is ignored. + /// @param qOverP Charge over momentum + /// @param cov Free parameters covariance matrix + /// @param particleHypothesis Particle hypothesis + GenericFreeTrackParameters(const Vector4& pos4, const Vector3& dir, + Scalar qOverP, std::optional cov, + ParticleHypothesis particleHypothesis) + : m_params(FreeVector::Zero()), + m_cov(std::move(cov)), + m_particleHypothesis(std::move(particleHypothesis)) { + m_params[eFreePos0] = pos4[ePos0]; + m_params[eFreePos1] = pos4[ePos1]; + m_params[eFreePos2] = pos4[ePos2]; + m_params[eFreeTime] = pos4[eTime]; + m_params[eFreeDir0] = dir[eMom0]; + m_params[eFreeDir1] = dir[eMom1]; + m_params[eFreeDir2] = dir[eMom2]; + m_params[eFreeQOverP] = qOverP; + } + /// Construct from four-position, angles, absolute momentum, and charge. /// /// @param pos4 Track position/time four-vector @@ -135,9 +160,9 @@ class GenericFreeTrackParameters { Scalar time() const { return m_params[eFreeTime]; } /// Phi direction. - Scalar phi() const { return phi(direction()); } + Scalar phi() const { return VectorHelpers::phi(direction()); } /// Theta direction. - Scalar theta() const { return theta(direction()); } + Scalar theta() const { return VectorHelpers::theta(direction()); } /// Charge over momentum. Scalar qOverP() const { return m_params[eFreeQOverP]; } @@ -175,6 +200,17 @@ class GenericFreeTrackParameters { return m_particleHypothesis; } + /// Reflect the parameters in place. + void reflectInPlace() { m_params = reflectFreeParameters(m_params); } + + /// Reflect the parameters. + /// @return Reflected parameters. + GenericFreeTrackParameters reflect() const { + GenericFreeTrackParameters reflected = *this; + reflected.reflectInPlace(); + return reflected; + } + private: FreeVector m_params; std::optional m_cov; diff --git a/Core/include/Acts/EventData/TrackParameterHelpers.hpp b/Core/include/Acts/EventData/TrackParameterHelpers.hpp new file mode 100644 index 00000000000..c9089ff9ab9 --- /dev/null +++ b/Core/include/Acts/EventData/TrackParameterHelpers.hpp @@ -0,0 +1,55 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#pragma once + +#include "Acts/Definitions/TrackParametrization.hpp" +#include "Acts/Utilities/detail/periodic.hpp" + +namespace Acts { + +/// Normalize the bound parameter angles +/// +/// @param boundParams The bound parameters to normalize +/// +/// @return The normalized bound parameters +inline BoundVector normalizeBoundParameters(const BoundVector& boundParams) { + BoundVector result = boundParams; + std::tie(result[eBoundPhi], result[eBoundTheta]) = + detail::normalizePhiTheta(result[eBoundPhi], result[eBoundTheta]); + return result; +} + +/// Add bound parameters and take care of angle periodicity for phi and theta. +/// This is intended for small differences only i.e. KF updates. +/// +/// @param lhs The left hand side bound parameters +/// @param rhs The right hand side bound parameters +/// +/// @return The sum of the bound parameters +inline BoundVector addBoundParameters(const BoundVector& lhs, + const BoundVector& rhs) { + return normalizeBoundParameters(lhs + rhs); +} + +/// Subtract bound parameters and take care of angle periodicity for phi and +/// theta. This is intended for small differences only i.e. KF updates. +/// +/// @param lhs The left hand side bound parameters +/// @param rhs The right hand side bound parameters +/// +/// @return The difference of the bound parameters +inline BoundVector subtractBoundParameters(const BoundVector& lhs, + const BoundVector& rhs) { + BoundVector result = lhs - rhs; + result[eBoundPhi] = detail::radian_sym(result[eBoundPhi]); + result[eBoundTheta] = detail::radian_sym(result[eBoundTheta]); + return result; +} + +} // namespace Acts diff --git a/Core/include/Acts/EventData/TrackProxy.hpp b/Core/include/Acts/EventData/TrackProxy.hpp index ce674e9cfa4..5939022e2e8 100644 --- a/Core/include/Acts/EventData/TrackProxy.hpp +++ b/Core/include/Acts/EventData/TrackProxy.hpp @@ -324,7 +324,8 @@ class TrackProxy { return std::distance(tsRange.begin(), tsRange.end()); } - /// Return the number of measurements for the track. Const version + /// Return a mutable reference to the number of measurements for the track. + /// Mutable version /// @note Only available if the track proxy is not read-only /// @return The number of measurements unsigned int& nMeasurements() @@ -333,8 +334,7 @@ class TrackProxy { return component(); } - /// Return a mutable reference to the number of measurements for the track. - /// Mutable version + /// Return the number of measurements for the track. Const version /// @return The number of measurements unsigned int nMeasurements() const { return component(); diff --git a/Core/include/Acts/EventData/TransformationHelpers.hpp b/Core/include/Acts/EventData/TransformationHelpers.hpp index 7fa297f4abc..39240bf469e 100644 --- a/Core/include/Acts/EventData/TransformationHelpers.hpp +++ b/Core/include/Acts/EventData/TransformationHelpers.hpp @@ -13,11 +13,39 @@ #include "Acts/Definitions/TrackParametrization.hpp" #include "Acts/Geometry/GeometryContext.hpp" #include "Acts/Utilities/Result.hpp" +#include "Acts/Utilities/detail/periodic.hpp" namespace Acts { class Surface; +/// Reflect bound track parameters. +/// +/// @param boundParams Bound track parameters vector +/// @return Reflected bound track parameters vector +inline BoundVector reflectBoundParameters(const BoundVector& boundParams) { + BoundVector reflected = boundParams; + auto [phi, theta] = detail::normalizePhiTheta( + boundParams[eBoundPhi] - M_PI, M_PI - boundParams[eBoundTheta]); + reflected[eBoundPhi] = phi; + reflected[eBoundTheta] = theta; + reflected[eBoundQOverP] = -boundParams[eBoundQOverP]; + return reflected; +} + +/// Reflect free track parameters. +/// +/// @param freeParams Free track parameters vector +/// @return Reflected free track parameters vector +inline FreeVector reflectFreeParameters(const FreeVector& freeParams) { + FreeVector reflected = freeParams; + reflected[eFreeDir0] = -freeParams[eFreeDir0]; + reflected[eFreeDir1] = -freeParams[eFreeDir1]; + reflected[eFreeDir2] = -freeParams[eFreeDir2]; + reflected[eFreeQOverP] = -freeParams[eFreeQOverP]; + return reflected; +} + /// Transform bound track parameters into equivalent free track parameters. /// /// @param surface Surface onto which the input parameters are bound diff --git a/Core/include/Acts/EventData/detail/GenerateParameters.hpp b/Core/include/Acts/EventData/detail/GenerateParameters.hpp index 0d38bb8d966..023314e2527 100644 --- a/Core/include/Acts/EventData/detail/GenerateParameters.hpp +++ b/Core/include/Acts/EventData/detail/GenerateParameters.hpp @@ -8,33 +8,48 @@ #pragma once +#include "Acts/Definitions/Algebra.hpp" #include "Acts/Definitions/TrackParametrization.hpp" -#include "Acts/Utilities/detail/periodic.hpp" +#include "Acts/Definitions/Units.hpp" +#include "Acts/Utilities/AngleHelpers.hpp" #include +#include #include #include namespace Acts::detail::Test { -/// Generate a random parameters vector and covariance matrix. -/// -/// @return std:::pair template -inline auto generateParametersCovariance(generator_t& rng) - -> std::pair, - Eigen::Matrix> { +inline auto generateParameters(generator_t& rng) + -> Eigen::Matrix { + using Scalar = scalar_t; + using ParametersVector = Eigen::Matrix; + + std::normal_distribution standardNormal(0, 1); + + ParametersVector params; + for (auto i = 0u; i < kSize; ++i) { + params[i] = standardNormal(rng); + } + + return params; +} + +template +inline auto generateCovariance(generator_t& rng) + -> Eigen::Matrix { using Scalar = scalar_t; using ParametersVector = Eigen::Matrix; using CovarianceMatrix = Eigen::Matrix; - std::normal_distribution distNormal(0, 1); + std::normal_distribution standardNormal(0, 1); std::uniform_real_distribution distCorr(-1, 1); // generate standard deviations ParametersVector stddev; for (auto i = 0u; i < kSize; ++i) { - stddev[i] = std::abs(distNormal(rng)); + stddev[i] = std::abs(standardNormal(rng)); } // generate correlation matrix CovarianceMatrix corr; @@ -48,32 +63,216 @@ inline auto generateParametersCovariance(generator_t& rng) // construct the covariance matrix CovarianceMatrix cov = stddev.asDiagonal() * corr * stddev.asDiagonal(); - // generate random parameters - // this is ignoring the correlations; since this does not need to generate - // credible data, this should be fine. - ParametersVector params; - for (auto i = 0u; i < kSize; ++i) { - params[i] = stddev[i] * distNormal(rng); + return cov; +} + +/// Generate a random parameters vector and covariance matrix. +/// +/// @return std:::pair +template +inline auto generateParametersCovariance(generator_t& rng) + -> std::pair, + Eigen::Matrix> { + auto params = generateParameters(rng); + auto cov = generateCovariance(rng); + return {params, cov}; +} + +struct GenerateBoundDirectionOptions { + /// Low, high (exclusive) for the transverse direction angle. + double phiMin = -std::numbers::pi; + double phiMax = std::numbers::pi; + + /// Low, high (inclusive) for the longitudinal direction angle. + /// + /// This intentionally uses theta instead of eta so it can represent the + /// full direction space with finite values. + /// + /// @note This is the standard generation, for detector performance + /// classification, where a flat distribution in eta can be useful, + /// this can be set by the etaUniform flag; + /// + double thetaMin = AngleHelpers::thetaFromEta(6.0); + double thetaMax = AngleHelpers::thetaFromEta(-6.0); + + bool etaUniform = true; +}; + +template +inline std::pair generateBoundDirection( + generator_t& rng, const GenerateBoundDirectionOptions& options) { + using UniformReal = std::uniform_real_distribution; + + // since we want to draw the direction uniform on the unit sphere, we must + // draw from cos(theta) instead of theta. see e.g. + // https://mathworld.wolfram.com/SpherePointPicking.html + double cosThetaMin = std::cos(options.thetaMin); + // ensure upper bound is included. see e.g. + // https://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution + double cosThetaMax = std::nextafter(std::cos(options.thetaMax), + std::numeric_limits::max()); + + // in case we force uniform eta generation + double etaMin = Acts::AngleHelpers::etaFromTheta(options.thetaMin); + double etaMax = Acts::AngleHelpers::etaFromTheta(options.thetaMax); + + UniformReal phiDist(options.phiMin, options.phiMax); + UniformReal cosThetaDist(cosThetaMin, cosThetaMax); + UniformReal etaDist(etaMin, etaMax); + + // draw parameters + double phi = phiDist(rng); + + double theta = 0; + if (!options.etaUniform) { + const double cosTheta = cosThetaDist(rng); + theta = std::acos(cosTheta); + } else { + const double eta = etaDist(rng); + theta = AngleHelpers::thetaFromEta(eta); } + return {phi, theta}; +} + +struct GenerateQoverPOptions { + /// Low, high (exclusive) for absolute/transverse momentum. + double pMin = 1 * UnitConstants::GeV; + double pMax = 100 * UnitConstants::GeV; + + /// Indicate if the momentum referse to transverse momentum + bool pTransverse = true; + + /// Charge of the parameters. + double charge = 1; + + /// Randomize the charge and flip the PDG particle number sign accordingly. + bool randomizeCharge = true; +}; + +template +inline double generateQoverP(generator_t& rng, + const GenerateQoverPOptions& options, + double theta) { + using UniformIndex = std::uniform_int_distribution; + using UniformReal = std::uniform_real_distribution; + + // choose between particle/anti-particle if requested + // the upper limit of the distribution is inclusive + UniformIndex particleTypeChoice(0u, options.randomizeCharge ? 1u : 0u); + // (anti-)particle choice is one random draw but defines two properties + const double qChoices[] = { + options.charge, + -options.charge, + }; + UniformReal pDist(options.pMin, options.pMax); + + // draw parameters + const std::uint8_t type = particleTypeChoice(rng); + const double q = qChoices[type]; + + const double p = + pDist(rng) * (options.pTransverse ? 1. / std::sin(theta) : 1.); + const double qOverP = (q != 0) ? q / p : 1 / p; + + return qOverP; +} + +struct GenerateBoundParametersOptions { + struct { + double loc0Mean = 0 * UnitConstants::mm; + double loc0Std = 1 * UnitConstants::mm; + + double loc1Mean = 0 * UnitConstants::mm; + double loc1Std = 1 * UnitConstants::mm; + + double timeMean = 0 * UnitConstants::ns; + double timeStd = 1 * UnitConstants::ns; + } position; + + GenerateBoundDirectionOptions direction; + + GenerateQoverPOptions qOverP; +}; + +template +inline BoundVector generateBoundParameters( + generator_t& rng, const GenerateBoundParametersOptions& options) { + std::normal_distribution standardNormal(0, 1); + + const double loc0 = options.position.loc0Mean + + options.position.loc0Std * standardNormal(rng); + const double loc1 = options.position.loc1Mean + + options.position.loc1Std * standardNormal(rng); + + auto [phi, theta] = generateBoundDirection(rng, options.direction); + auto qOverP = generateQoverP(rng, options.qOverP, theta); + + const double time = options.position.timeMean + + options.position.timeStd * standardNormal(rng); + + return {loc0, loc1, phi, theta, qOverP, time}; +} + +template +inline std::pair generateBoundParametersCovariance( + generator_t& rng, const GenerateBoundParametersOptions& options) { + auto params = generateBoundParameters(rng, options); + auto cov = generateCovariance(rng); return {params, cov}; } -/// Generate a random bound parameters vector and covariance matrix. +struct GenerateFreeParametersOptions { + struct { + double xMean = 0 * UnitConstants::mm; + double xStd = 1 * UnitConstants::mm; + + double yMean = 0 * UnitConstants::mm; + double yStd = 1 * UnitConstants::mm; + + double zMean = 0 * UnitConstants::mm; + double zStd = 1 * UnitConstants::mm; + + double timeMean = 0 * UnitConstants::ns; + double timeStd = 1 * UnitConstants::ns; + } position; + + GenerateBoundDirectionOptions direction; + + GenerateQoverPOptions qOverP; +}; + template -inline auto generateBoundParametersCovariance(generator_t& rng) { - auto parCov = generateParametersCovariance(rng); - auto [phi, theta] = detail::normalizePhiTheta(parCov.first[eBoundPhi], - parCov.first[eBoundTheta]); - parCov.first[eBoundPhi] = phi; - parCov.first[eBoundTheta] = theta; - return parCov; +inline FreeVector generateFreeParameters( + generator_t& rng, const GenerateFreeParametersOptions& options) { + std::normal_distribution standardNormal(0, 1); + + const double x = + options.position.xMean + options.position.xStd * standardNormal(rng); + const double y = + options.position.yMean + options.position.yStd * standardNormal(rng); + const double z = + options.position.zMean + options.position.zStd * standardNormal(rng); + const double time = options.position.timeMean + + options.position.timeStd * standardNormal(rng); + + auto [phi, theta] = generateBoundDirection(rng, options.direction); + + Vector3 direction = makeDirectionFromPhiTheta(phi, theta); + + auto qOverP = generateQoverP(rng, options.qOverP, theta); + + FreeVector freeParams; + freeParams << x, y, z, time, direction, qOverP; + return freeParams; } -/// Generate a random free parameters vector and covariance matrix. template -inline auto generateFreeParametersCovariance(generator_t& rng) { - return generateParametersCovariance(rng); +inline std::pair generateFreeParametersCovariance( + generator_t& rng, const GenerateFreeParametersOptions& options) { + auto params = generateFreeParameters(rng, options); + auto cov = generateCovariance(rng); + return {params, cov}; } } // namespace Acts::detail::Test diff --git a/Core/include/Acts/EventData/detail/MultiTrajectoryTestsCommon.hpp b/Core/include/Acts/EventData/detail/MultiTrajectoryTestsCommon.hpp index ec64dbe5241..93ef7a3eb7c 100644 --- a/Core/include/Acts/EventData/detail/MultiTrajectoryTestsCommon.hpp +++ b/Core/include/Acts/EventData/detail/MultiTrajectoryTestsCommon.hpp @@ -331,7 +331,7 @@ class MultiTrajectoryTestsCommon { auto tsb = traj.getTrackState(index); // then modify one and check that the other was modified as well { - auto [par, cov] = generateBoundParametersCovariance(rng); + auto [par, cov] = generateBoundParametersCovariance(rng, {}); tsb.predicted() = par; tsb.predictedCovariance() = cov; BOOST_CHECK_EQUAL(tsa.predicted(), par); @@ -340,7 +340,7 @@ class MultiTrajectoryTestsCommon { BOOST_CHECK_EQUAL(tsb.predictedCovariance(), cov); } { - auto [par, cov] = generateBoundParametersCovariance(rng); + auto [par, cov] = generateBoundParametersCovariance(rng, {}); tsb.filtered() = par; tsb.filteredCovariance() = cov; BOOST_CHECK_EQUAL(tsa.filtered(), par); @@ -349,7 +349,7 @@ class MultiTrajectoryTestsCommon { BOOST_CHECK_EQUAL(tsb.filteredCovariance(), cov); } { - auto [par, cov] = generateBoundParametersCovariance(rng); + auto [par, cov] = generateBoundParametersCovariance(rng, {}); tsb.smoothed() = par; tsb.smoothedCovariance() = cov; BOOST_CHECK_EQUAL(tsa.smoothed(), par); @@ -377,7 +377,7 @@ class MultiTrajectoryTestsCommon { } { // reset measurements w/ full parameters - auto [measPar, measCov] = generateBoundParametersCovariance(rng); + auto [measPar, measCov] = generateBoundParametersCovariance(rng, {}); tsb.allocateCalibrated(eBoundSize); tsb.template calibrated() = measPar; tsb.template calibratedCovariance() = measCov; @@ -390,7 +390,7 @@ class MultiTrajectoryTestsCommon { } { // reset only the effective measurements - auto [measPar, measCov] = generateBoundParametersCovariance(rng); + auto [measPar, measCov] = generateBoundParametersCovariance(rng, {}); std::size_t nMeasurements = tsb.effectiveCalibrated().rows(); auto effPar = measPar.head(nMeasurements); auto effCov = measCov.topLeftCorner(nMeasurements, nMeasurements); diff --git a/Core/include/Acts/EventData/detail/TestTrackState.hpp b/Core/include/Acts/EventData/detail/TestTrackState.hpp index 3a83f401cd3..c1471566c5b 100644 --- a/Core/include/Acts/EventData/detail/TestTrackState.hpp +++ b/Core/include/Acts/EventData/detail/TestTrackState.hpp @@ -65,7 +65,7 @@ struct TestTrackState { } // create track parameters - auto [trkPar, trkCov] = generateBoundParametersCovariance(rng); + auto [trkPar, trkCov] = generateBoundParametersCovariance(rng, {}); // trkPar[eBoundPhi] = 45_degree; // trkPar[eBoundTheta] = 90_degree; // trkPar[eBoundQOverP] = 5.; diff --git a/Core/include/Acts/Geometry/CylinderVolumeBounds.hpp b/Core/include/Acts/Geometry/CylinderVolumeBounds.hpp index 1951d96b2da..002af04cd59 100644 --- a/Core/include/Acts/Geometry/CylinderVolumeBounds.hpp +++ b/Core/include/Acts/Geometry/CylinderVolumeBounds.hpp @@ -128,7 +128,7 @@ class CylinderVolumeBounds : public VolumeBounds { /// Copy Constructor /// /// @param cylbo is the source cylinder volume bounds for the copy - CylinderVolumeBounds(const CylinderVolumeBounds& cylbo) = default; + CylinderVolumeBounds(const CylinderVolumeBounds& cylbo); ~CylinderVolumeBounds() override = default; CylinderVolumeBounds& operator=(const CylinderVolumeBounds& cylbo) = default; diff --git a/Core/include/Acts/Geometry/NavigationPolicyFactory.hpp b/Core/include/Acts/Geometry/NavigationPolicyFactory.hpp new file mode 100644 index 00000000000..4d9542af826 --- /dev/null +++ b/Core/include/Acts/Geometry/NavigationPolicyFactory.hpp @@ -0,0 +1,220 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#pragma once + +#include "Acts/Navigation/INavigationPolicy.hpp" +#include "Acts/Navigation/MultiNavigationPolicy.hpp" + +#include +#include +namespace Acts { + +class TrackingVolume; +class GeometryContext; +class Logger; +class INavigationPolicy; + +namespace detail { +template +class NavigationPolicyFactoryImpl; +} + +/// Base class for navigation policy factories. The factory can be assembled +/// iteratively by using `make` followed by a number of calls to the `add` +/// function of the helper type. Example: +/// +/// ```cpp +/// auto factory = NavigationPolicyFactory::make() +/// .add(arg1, arg2) +/// .add(/*no args*/) +/// .asUniquePtr(); +/// ``` +class NavigationPolicyFactory { + public: + virtual ~NavigationPolicyFactory() = default; + + // This needs to be listed here, but the return type cannot be spelled out + // yet. + static auto make(); + + // This will potentially get serialization interface and deserialization + // functionality + + virtual std::unique_ptr build( + const GeometryContext& gctx, const TrackingVolume& volume, + const Logger& logger) const = 0; +}; + +namespace detail { + +template +concept NavigationPolicyIsolatedFactoryConcept = requires(F f) { + { + f(std::declval(), + std::declval(), std::declval(), + std::declval()...) + } -> std::derived_from; + + requires NavigationPolicyConcept(), + std::declval(), std::declval(), + std::declval()...))>; + + requires(std::is_copy_constructible_v && ...); +}; + +template <> +class NavigationPolicyFactoryImpl<> { + public: + template + friend class NavigationPolicyFactoryImpl; + NavigationPolicyFactoryImpl() = default; + + /// Create a factory with the specified policy added + /// @tparam P The policy type to add + /// @param args The arguments to pass to the policy constructor + /// @note Arguments need to be copy constructible because the factory must be + /// able to execute multiple times. + /// @return A new policy factory including the @c P policy. + template + requires(std::is_constructible_v && + (std::is_copy_constructible_v && ...)) + constexpr auto add(Args&&... args) && { + auto factory = [=](const GeometryContext& gctx, + const TrackingVolume& volume, const Logger& logger) { + return P{gctx, volume, logger, args...}; + }; + + return NavigationPolicyFactoryImpl{ + std::make_tuple(std::move(factory))}; + } + + /// Create a factory with a policy returned by a factory function + /// @tparam Fn The type of the function to construct the policy + /// @param args The arguments to pass to the policy factory + /// @note Arguments need to be copy constructible because the factory must be + /// able to execute multiple times. + /// @return A new policy factory including the function + template + requires(NavigationPolicyIsolatedFactoryConcept) + constexpr auto add(Fn&& fn, Args&&... args) { + auto factory = [=](const GeometryContext& gctx, + const TrackingVolume& volume, const Logger& logger) { + return fn(gctx, volume, logger, args...); + }; + + return NavigationPolicyFactoryImpl{ + std::make_tuple(std::move(factory))}; + } +}; + +template +class NavigationPolicyFactoryImpl : public NavigationPolicyFactory { + public: + /// Create a factory with the specified policy added + /// @tparam P The policy type to add + /// @param args The arguments to pass to the policy constructor + /// @note Arguments need to be copy constructible because the factory must be + /// able to execute multiple times. + /// @return A new policy factory including the @c P policy. + template + requires(std::is_constructible_v && + (std::is_copy_constructible_v && ...)) + constexpr auto add(Args&&... args) && { + auto factory = [=](const GeometryContext& gctx, + const TrackingVolume& volume, const Logger& logger) { + return P{gctx, volume, logger, args...}; + }; + + return NavigationPolicyFactoryImpl{ + std::tuple_cat(std::move(m_factories), + std::make_tuple(std::move(factory)))}; + } + + /// Create a factory with a policy returned by a factory function + /// @tparam Fn The type of the function to construct the policy + /// @param args The arguments to pass to the policy factory + /// @note Arguments need to be copy constructible because the factory must be + /// able to execute multiple times. + /// @return A new policy factory including the function + template + requires(NavigationPolicyIsolatedFactoryConcept) + constexpr auto add(Fn&& fn, Args&&... args) && { + auto factory = [=](const GeometryContext& gctx, + const TrackingVolume& volume, const Logger& logger) { + return fn(gctx, volume, logger, args...); + }; + + return NavigationPolicyFactoryImpl{ + std::tuple_cat(std::move(m_factories), + std::make_tuple(std::move(factory)))}; + } + + /// Move the factory into a unique pointer + /// @note Only callable on rvalue references + /// @return A unique pointer to the factory + constexpr std::unique_ptr> + asUniquePtr() && { + return std::make_unique>( + std::move(*this)); + } + + /// Construct a navigation policy using the factories + /// @param gctx The geometry context + /// @param volume The tracking volume + /// @param logger The logger + auto operator()(const GeometryContext& gctx, const TrackingVolume& volume, + const Logger& logger) const { + return std::apply( + [&](auto&&... factories) { + // Deduce policy type explicitly here... + using policy_type = decltype(MultiNavigationPolicy{ + std::invoke(factories, std::declval(), + std::declval(), + std::declval())...}); + + // ... so we can create a unique_ptr of the concrete type here rather + // than the base. (`make_unique` can't do type deduction) + return std::make_unique( + std::invoke(factories, gctx, volume, logger)...); + }, + m_factories); + } + + /// Construct a navigation policy using the factories + /// @param gctx The geometry context + /// @param volume The tracking volume + /// @param logger The logger + std::unique_ptr build( + const GeometryContext& gctx, const TrackingVolume& volume, + const Logger& logger) const override { + return operator()(gctx, volume, logger); + } + + private: + template + friend class NavigationPolicyFactoryImpl; + + NavigationPolicyFactoryImpl(std::tuple&& factories) + : m_factories(std::move(factories)) {} + + std::tuple m_factories; +}; + +} // namespace detail + +inline auto NavigationPolicyFactory::make() { + return detail::NavigationPolicyFactoryImpl<>{}; +} + +} // namespace Acts diff --git a/Core/include/Acts/Geometry/TrackingVolume.hpp b/Core/include/Acts/Geometry/TrackingVolume.hpp index c980314fa6d..f47f8b440fc 100644 --- a/Core/include/Acts/Geometry/TrackingVolume.hpp +++ b/Core/include/Acts/Geometry/TrackingVolume.hpp @@ -13,13 +13,13 @@ #include "Acts/Geometry/BoundarySurfaceT.hpp" #include "Acts/Geometry/GeometryContext.hpp" #include "Acts/Geometry/GeometryIdentifier.hpp" -#include "Acts/Geometry/GlueVolumesDescriptor.hpp" #include "Acts/Geometry/Layer.hpp" #include "Acts/Geometry/Portal.hpp" #include "Acts/Geometry/TrackingVolumeVisitorConcept.hpp" #include "Acts/Geometry/Volume.hpp" #include "Acts/Material/IVolumeMaterial.hpp" -#include "Acts/Surfaces/BoundaryTolerance.hpp" +#include "Acts/Navigation/NavigationDelegate.hpp" +#include "Acts/Navigation/NavigationStream.hpp" #include "Acts/Surfaces/Surface.hpp" #include "Acts/Surfaces/SurfaceArray.hpp" #include "Acts/Surfaces/SurfaceVisitorConcept.hpp" @@ -35,7 +35,7 @@ #include #include -#include +#include namespace Acts { @@ -43,7 +43,6 @@ class GlueVolumesDescriptor; class VolumeBounds; template struct NavigationOptions; -class GeometryIdentifier; class IMaterialDecorator; class ISurfaceMaterial; class IVolumeMaterial; @@ -51,6 +50,7 @@ class Surface; class TrackingVolume; struct GeometryIdentifierHook; class Portal; +class INavigationPolicy; /// Interface types of the Gen1 geometry model /// @note This interface is being replaced, and is subject to removal @@ -117,8 +117,8 @@ class TrackingVolume : public Volume { ~TrackingVolume() override; TrackingVolume(const TrackingVolume&) = delete; TrackingVolume& operator=(const TrackingVolume&) = delete; - TrackingVolume(TrackingVolume&&) = default; - TrackingVolume& operator=(TrackingVolume&&) = default; + TrackingVolume(TrackingVolume&&); + TrackingVolume& operator=(TrackingVolume&&); /// Constructor for a container Volume /// - vacuum filled volume either as a for other tracking volumes @@ -155,7 +155,6 @@ class TrackingVolume : public Volume { /// @param volumeName is a string identifier TrackingVolume(Volume& volume, const std::string& volumeName = "undefined"); - // @TODO: This needs to be refactored to include Gen3 volumes /// Return the associated sub Volume, returns THIS if no subVolume exists /// @param gctx The current geometry context object, e.g. alignment /// @param position is the global position associated with that search @@ -498,6 +497,21 @@ class TrackingVolume : public Volume { const ViewConfig& portalViewConfig, const ViewConfig& sensitiveViewConfig) const; + /// Register a navigation policy with this volume. The argument can not be + /// nullptr. + /// @param policy is the navigation policy to be registered + void setNavigationPolicy(std::unique_ptr policy); + + /// Populate the navigation stream with navigation candidates from this + /// volume. Internally, this consults the registered navigation policy, where + /// the default is a noop. + /// @param args are the navigation arguments + /// @param stream is the navigation stream to be updated + /// @param logger is the logger + void initializeNavigationCandidates(const NavigationArguments& args, + AppendOnlyNavigationStream& stream, + const Logger& logger) const; + private: void connectDenseBoundarySurfaces( MutableTrackingVolumeVector& confinedDenseVolumes); @@ -561,6 +575,10 @@ class TrackingVolume : public Volume { std::vector> m_volumes; std::vector> m_portals; std::vector> m_surfaces; + + std::unique_ptr m_navigationPolicy; + + NavigationDelegate m_navigationDelegate{}; }; } // namespace Acts diff --git a/Core/include/Acts/Navigation/INavigationPolicy.hpp b/Core/include/Acts/Navigation/INavigationPolicy.hpp new file mode 100644 index 00000000000..6794dbdea09 --- /dev/null +++ b/Core/include/Acts/Navigation/INavigationPolicy.hpp @@ -0,0 +1,73 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#pragma once + +#include "Acts/Navigation/NavigationDelegate.hpp" +#include "Acts/Navigation/NavigationStream.hpp" +#include "Acts/Utilities/DelegateChainBuilder.hpp" + +#include + +namespace Acts { + +class TrackingVolume; +class INavigationPolicy; + +/// Concept for a navigation policy +/// This exists so `updateState` can be a non-virtual method and we still have a +/// way to enforce it exists. +template +concept NavigationPolicyConcept = requires { + requires std::is_base_of_v; + // Has a conforming update method + requires requires(T policy, const NavigationArguments& args) { + policy.initializeCandidates(args, + std::declval(), + std::declval()); + }; +}; + +/// Base class for all navigation policies. The policy needs to be *connected* +/// to a delegate via a virtual method for it to become active. The update +/// method is not part of the class interface. The conventional `updateState` +/// method is only required for use with the navigation policy factory, +/// otherwise `connect` is free to connect any function. +class INavigationPolicy { + public: + /// Noop update function that is suitable as a default for default navigation + /// delegates. + static void noopInitializeCandidates(const NavigationArguments& /*unused*/, + AppendOnlyNavigationStream& /*unused*/, + const Logger& /*unused*/) {} + + /// Virtual destructor so policies can be held through this base class. + virtual ~INavigationPolicy() = default; + + /// Connect a policy with a delegate (usually a member of a volume). + /// This method exists to allow a policy to ensure a non-virtual function is + /// registered with the delegate. + /// @param delegate The delegate to connect to + virtual void connect(NavigationDelegate& delegate) const = 0; + + protected: + /// Internal helper function for derived classes that conform to the concept + /// and have a conventional `updateState` method. Mainly used to save some + /// boilerplate. + /// @tparam T The type of the navigation policy + /// @param delegate The delegate to connect to + template + void connectDefault(NavigationDelegate& delegate) const { + // This cannot be a concept because we use it in CRTP below + const auto* self = static_cast(this); + DelegateChainBuilder{delegate}.add<&T::initializeCandidates>(self).store( + delegate); + } +}; + +} // namespace Acts diff --git a/Core/include/Acts/Navigation/MultiNavigationPolicy.hpp b/Core/include/Acts/Navigation/MultiNavigationPolicy.hpp new file mode 100644 index 00000000000..c5c8a397aea --- /dev/null +++ b/Core/include/Acts/Navigation/MultiNavigationPolicy.hpp @@ -0,0 +1,78 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#pragma once + +#include "Acts/Navigation/INavigationPolicy.hpp" + +namespace Acts { + +/// Base class for multi navigation policies +class MultiNavigationPolicyBase : public INavigationPolicy {}; + +/// Combined navigation policy that calls all contained other navigation +/// policies. This class only works with policies complying with +/// `NavigationPolicyConcept`, which means that they have a conventional +/// `updateState` method. +/// +/// Internally, this uses a delegate chain factory to produce an unrolled +/// delegate chain. +/// +/// @tparam Policies The navigation policies to be combined +template + requires(sizeof...(Policies) > 0) +class MultiNavigationPolicy final : public MultiNavigationPolicyBase { + public: + /// Constructor from a set of child policies. + /// @param policies The child policies + MultiNavigationPolicy(Policies&&... policies) + : m_policies{std::move(policies)...} {} + + /// Implementation of the connection to a navigation delegate. + /// It uses the delegate chain factory to produce a delegate chain and stores + /// that chain in the owning navigation delegate. + /// @param delegate The navigation delegate to connect to + void connect(NavigationDelegate& delegate) const override { + auto factory = add(DelegateChainBuilder{delegate}, + std::index_sequence_for{}); + + factory.store(delegate); + } + + /// Access the contained policies + /// @return The contained policies + const std::tuple& policies() const { return m_policies; } + + private: + /// Internal helper to build the delegate chain + template + constexpr auto add( + auto factory, + std::integer_sequence /*unused*/) const { + return add(factory); + } + + /// Internal helper to build the delegate chain + template + constexpr auto add(auto factory) const { + using policy_type = std::tuple_element_t; + auto* policy = &std::get(m_policies); + + auto added = + factory.template add<&policy_type::initializeCandidates>(policy); + + if constexpr (sizeof...(Is) > 0) { + return add(added); + } else { + return added; + } + } + + std::tuple m_policies; +}; +} // namespace Acts diff --git a/Core/include/Acts/Navigation/NavigationDelegate.hpp b/Core/include/Acts/Navigation/NavigationDelegate.hpp new file mode 100644 index 00000000000..8e243818d30 --- /dev/null +++ b/Core/include/Acts/Navigation/NavigationDelegate.hpp @@ -0,0 +1,35 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#pragma once + +#include "Acts/Definitions/Algebra.hpp" +#include "Acts/Navigation/NavigationStream.hpp" +#include "Acts/Surfaces/BoundaryTolerance.hpp" +#include "Acts/Utilities/Delegate.hpp" + +namespace Acts { + +class NavigationStream; +class Logger; + +/// Struct that serves as the argument to the navigation delegate. +/// It is not supposed to be used as an lvalue. +struct NavigationArguments { + Vector3 position; + Vector3 direction; + + BoundaryTolerance tolerance = BoundaryTolerance::None(); +}; + +/// Central alias for the navigation delegate. This type is owning to support +/// (type-erased) navigation delegate chains (i.e. multiple policies). +using NavigationDelegate = OwningDelegate; + +} // namespace Acts diff --git a/Core/include/Acts/Navigation/NavigationStream.hpp b/Core/include/Acts/Navigation/NavigationStream.hpp index 71443e48915..97e154214d7 100644 --- a/Core/include/Acts/Navigation/NavigationStream.hpp +++ b/Core/include/Acts/Navigation/NavigationStream.hpp @@ -10,9 +10,11 @@ #include "Acts/Definitions/Algebra.hpp" #include "Acts/Geometry/GeometryContext.hpp" +#include "Acts/Geometry/Portal.hpp" #include "Acts/Surfaces/BoundaryTolerance.hpp" #include "Acts/Utilities/Intersection.hpp" +#include #include #include @@ -22,7 +24,6 @@ namespace Acts { namespace Experimental { class Portal; } -using namespace Experimental; class Surface; @@ -55,6 +56,7 @@ class NavigationStream { ObjectIntersection intersection = ObjectIntersection::invalid(); /// The portal + const Acts::Experimental::Portal* gen2Portal = nullptr; const Portal* portal = nullptr; /// The boundary tolerance BoundaryTolerance bTolerance = BoundaryTolerance::None(); @@ -116,25 +118,27 @@ class NavigationStream { /// /// @param surface the surface to be filled /// @param bTolerance the boundary tolerance used for the intersection - void addSurfaceCandidate(const Surface* surface, + void addSurfaceCandidate(const Surface& surface, const BoundaryTolerance& bTolerance); /// Fill n surfaces into the candidate vector /// /// @param surfaces the surfaces that are filled in /// @param bTolerance the boundary tolerance used for the intersection - void addSurfaceCandidates(const std::vector& surfaces, + void addSurfaceCandidates(std::span surfaces, const BoundaryTolerance& bTolerance); /// Fill one portal into the candidate vector /// + void addPortalCandidate(const Experimental::Portal& portal); /// @param portal the portals that are filled in - void addPortalCandidate(const Portal* portal); + + void addPortalCandidate(const Portal& portal); /// Fill n portals into the candidate vector /// /// @param portals the portals that are filled in - void addPortalCandidates(const std::vector& portals); + void addPortalCandidates(std::span portals); /// Initialize the stream from a query point /// @@ -175,4 +179,14 @@ class NavigationStream { std::size_t m_currentIndex = 0u; }; +struct AppendOnlyNavigationStream { + explicit AppendOnlyNavigationStream(NavigationStream& stream); + void addSurfaceCandidate(const Surface& surface, + const BoundaryTolerance& bTolerance); + void addPortalCandidate(const Portal& portal); + + private: + NavigationStream* m_stream; +}; + } // namespace Acts diff --git a/Core/include/Acts/Navigation/SurfaceArrayNavigationPolicy.hpp b/Core/include/Acts/Navigation/SurfaceArrayNavigationPolicy.hpp new file mode 100644 index 00000000000..9143cf0087d --- /dev/null +++ b/Core/include/Acts/Navigation/SurfaceArrayNavigationPolicy.hpp @@ -0,0 +1,83 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include "Acts/Navigation/INavigationPolicy.hpp" + +#pragma once + +namespace Acts { + +class SurfaceArray; + +/// A navigation policy that internally uses the Gen1 @c SurfaceArray class +class SurfaceArrayNavigationPolicy : public INavigationPolicy { + public: + /// Enum for configuring which type of surface array to produce. This affects + /// the projection that is used for creating the binning structure. + enum class LayerType { Cylinder, Disc, Plane }; + + /// Config struct to configure the surface array navigation + struct Config { + /// The type of the layer + LayerType layerType = LayerType::Cylinder; + /// The number of bins in the local directions. The interpretation depends + /// on the layer type. + std::pair bins; + }; + + /// Main constructor, which internally creates the surface array acceleration + /// structure. + /// @note Expects that all relevant surfaces are registered with @p volume. + /// Only selects sensitive surfaces for the surface array. + /// @param gctx The geometry context + /// @param volume The *layer volume* to construct the surface array from + /// @param logger A logging instance + /// @param config The configuration for the surface array + explicit SurfaceArrayNavigationPolicy(const GeometryContext& gctx, + const TrackingVolume& volume, + const Logger& logger, Config config); + + /// Update the navigation state from the surface array + /// @param args The navigation arguments + /// @param stream The navigation stream to update + /// @param logger The logger + void initializeCandidates(const NavigationArguments& args, + AppendOnlyNavigationStream& stream, + const Logger& logger) const; + + /// Connect this policy with a navigation delegate + /// @param delegate The navigation delegate to connect to + void connect(NavigationDelegate& delegate) const override; + + /// Output stream operator for the contained layer type enum + /// @param os The output stream + /// @param layerType The layer type to print + friend std::ostream& operator<<(std::ostream& os, + const LayerType& layerType) { + switch (layerType) { + case LayerType::Cylinder: + os << "Cylinder"; + break; + case LayerType::Disc: + os << "Disc"; + break; + case LayerType::Plane: + os << "Plane"; + break; + } + return os; + } + + private: + std::unique_ptr m_surfaceArray{}; + const TrackingVolume& m_volume; +}; + +static_assert(NavigationPolicyConcept); + +} // namespace Acts diff --git a/Core/include/Acts/Navigation/TryAllNavigationPolicy.hpp b/Core/include/Acts/Navigation/TryAllNavigationPolicy.hpp new file mode 100644 index 00000000000..e7dc4bb3ddc --- /dev/null +++ b/Core/include/Acts/Navigation/TryAllNavigationPolicy.hpp @@ -0,0 +1,63 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#pragma once + +#include "Acts/Navigation/INavigationPolicy.hpp" +#include "Acts/Navigation/NavigationStream.hpp" + +namespace Acts { + +class TrackingVolume; +class GeometryContext; +class Logger; + +/// Policy which adds **all** candidates of the configured type to the +/// stream +class TryAllNavigationPolicy final : public INavigationPolicy { + public: + struct Config { + bool portals = true; + bool sensitives = true; + }; + + /// Constructor from a volume + /// @param config The configuration for the policy + /// @param gctx is the geometry context + /// @param volume is the volume to navigate + /// @param logger is the logger + TryAllNavigationPolicy(const Config& config, const GeometryContext& gctx, + const TrackingVolume& volume, const Logger& logger); + + /// Constructor from a volume + /// @param gctx is the geometry context + /// @param volume is the volume to navigate + /// @param logger is the logger + TryAllNavigationPolicy(const GeometryContext& gctx, + const TrackingVolume& volume, const Logger& logger); + + /// Add all candidates to the stream + /// @param args are the navigation arguments + /// @param stream is the navigation stream to update + /// @param logger is the logger + void initializeCandidates(const NavigationArguments& args, + AppendOnlyNavigationStream& stream, + const Logger& logger) const; + + /// Connect the policy to a navigation delegate + /// @param delegate is the navigation delegate + void connect(NavigationDelegate& delegate) const override; + + private: + Config m_cfg; + const TrackingVolume* m_volume; +}; + +static_assert(NavigationPolicyConcept); + +} // namespace Acts diff --git a/Core/include/Acts/Seeding/EstimateTrackParamsFromSeed.hpp b/Core/include/Acts/Seeding/EstimateTrackParamsFromSeed.hpp index 7a5c597f626..f3850e102ce 100644 --- a/Core/include/Acts/Seeding/EstimateTrackParamsFromSeed.hpp +++ b/Core/include/Acts/Seeding/EstimateTrackParamsFromSeed.hpp @@ -287,4 +287,41 @@ std::optional estimateTrackParamsFromSeed( return params; } +/// Configuration for the estimation of the covariance matrix of the track +/// parameters with `estimateTrackParamCovariance`. +struct EstimateTrackParamCovarianceConfig { + /// The initial sigmas for the track parameters + BoundVector initialSigmas = {1. * UnitConstants::mm, + 1. * UnitConstants::mm, + 1. * UnitConstants::degree, + 1. * UnitConstants::degree, + 1. * UnitConstants::e / UnitConstants::GeV, + 1. * UnitConstants::ns}; + + /// The initial relative uncertainty of the q/pt + double initialSigmaPtRel = 0.1; + + /// The inflation factors for the variances of the track parameters + BoundVector initialVarInflation = {1., 1., 1., 1., 1., 1.}; + /// The inflation factor for time uncertainty if the time parameter was not + /// estimated + double noTimeVarInflation = 100.; +}; + +/// Estimate the covariance matrix of the given track parameters based on the +/// provided configuration. The assumption is that we can model the uncertainty +/// of the track parameters as a diagonal matrix with the provided initial +/// sigmas. The inflation factors are used to inflate the initial variances +/// based on the provided configuration. The uncertainty of q/p is estimated +/// based on the relative uncertainty of the q/pt and the theta uncertainty. +/// +/// @param config is the configuration for the estimation +/// @param params is the track parameters +/// @param hasTime is true if the track parameters have time +/// +/// @return the covariance matrix of the track parameters +BoundMatrix estimateTrackParamCovariance( + const EstimateTrackParamCovarianceConfig& config, const BoundVector& params, + bool hasTime); + } // namespace Acts diff --git a/Core/include/Acts/Seeding/HoughTransformUtils.hpp b/Core/include/Acts/Seeding/HoughTransformUtils.hpp index a7a84d8908c..4fcece48034 100644 --- a/Core/include/Acts/Seeding/HoughTransformUtils.hpp +++ b/Core/include/Acts/Seeding/HoughTransformUtils.hpp @@ -14,6 +14,7 @@ #include "Acts/Utilities/Logger.hpp" #include "Acts/Utilities/Result.hpp" +#include #include #include #include diff --git a/Core/include/Acts/Seeding/PathSeeder.hpp b/Core/include/Acts/Seeding/PathSeeder.hpp index 1d3fd49f66b..d4475c022df 100644 --- a/Core/include/Acts/Seeding/PathSeeder.hpp +++ b/Core/include/Acts/Seeding/PathSeeder.hpp @@ -9,10 +9,13 @@ #pragma once #include "Acts/EventData/SourceLink.hpp" +#include "Acts/EventData/TrackParameters.hpp" +#include "Acts/Seeding/detail/UtilityFunctions.hpp" #include "Acts/Surfaces/Surface.hpp" #include "Acts/Utilities/Delegate.hpp" +#include "Acts/Utilities/GridIterator.hpp" -namespace Acts::Experimental { +namespace Acts { /// @brief Seeding algorigthm that extracts /// the IP parameters and sorts the source links @@ -23,7 +26,7 @@ namespace Acts::Experimental { /// source links -- as follows: First the source links /// are sorted into a user-defined grid. Then, iteration over the source links /// is performed. If a source link is attached to a surface that is -/// in the first tracking layer, as defined by the user, the IP parameters +/// in the reference tracking layer, as defined by the user, the IP parameters /// are estimated and the tracking layers are intersected to construct the /// core of the "Path". The source links in the subsequent layers are then /// added to the seed if they lie within the path width of the core. @@ -39,84 +42,34 @@ namespace Acts::Experimental { /// /// @note Handling of the rotated surfaces has to happen /// in the user-defined delegate functions. - -template class PathSeeder { public: - using GridType = grid_t; - - /// @brief The seed struct - /// - /// The seed struct contains the IP parameters - /// and the source links that are associated with - /// the seed. - struct Seed { - /// The IP momentum magnitude - ActsScalar ipP; - - /// The IP momentum direction - Vector3 ipDir; - - /// The IP vertex position - Vector3 ipVertex; - - /// The source links associated with the seed - std::vector sourceLinks; - - Seed() = delete; - Seed(ActsScalar ipPmag, Vector3 ipPdir, Vector3 ipPos, - std::vector sls) - : ipP(ipPmag), - ipDir(std::move(ipPdir)), - ipVertex(std::move(ipPos)), - sourceLinks(std::move(sls)) {}; - }; - - /// @brief Delegate to provide the relevant grid - /// filled with source links for the given geometry - /// member - /// - /// @arg The geometry identifier to use - /// - /// @return The grid filled with source links - using SourceLinkGridLookup = Delegate; + using PathSeed = + std::pair>; /// @brief Delegate to estimate the IP parameters - /// and the momentum direction at the first tracking layer - /// - /// @arg The geometry context to use - /// @arg The global position of the pivot source link - /// - /// @return Particle charge, the IP momentum magnitude, the IP vertex position, - /// the IP momentum direction, the momentum direction at the - /// first tracking layer - using TrackEstimator = - Delegate( - const GeometryContext&, const Vector3&)>; - - /// @brief Delegate to transform the source link to the - /// appropriate global frame. + /// and the momentum direction at the reference tracking layer /// - /// @arg The geometry context to use - /// @arg The source link to calibrate + /// @arg Geometry context to use + /// @arg Pivot source link /// - /// @return The global position of the source link measurement - using SourceLinkCalibrator = - Delegate; + /// @return Pair of the track parameters at the IP and + /// the reference tracking layer + using TrackEstimator = Delegate< + std::pair( + const GeometryContext&, const SourceLink&)>; /// @brief Delegate to find the intersections for the given pivot /// source link /// /// @arg The geometry context to use - /// @arg The global position of the pivot source link - /// @arg The momentum direction of the pivot source link - /// at the first tracking layer - /// @arg The IP momentum magnitude - /// @arg The particle charge + /// @arg Track parameters at the reference tracking layer + /// + /// @return Vector of pairs of the geometry identifier + /// and the local intersection point using IntersectionLookup = - Delegate>( - const GeometryContext&, const Vector3&, const Vector3&, - const ActsScalar&, const ActsScalar&)>; + Delegate>( + const GeometryContext&, const CurvilinearTrackParameters&)>; /// @brief Delegate to provide the path width around /// the intersection point to pull the source links @@ -133,24 +86,18 @@ class PathSeeder { /// @brief The nested configuration struct struct Config { - /// Binned SourceLink provider - SourceLinkGridLookup sourceLinkGridLookup; /// Parameters estimator TrackEstimator trackEstimator; - /// SourceLink calibrator - SourceLinkCalibrator sourceLinkCalibrator; /// Intersection finder IntersectionLookup intersectionFinder; /// Path width provider PathWidthLookup pathWidthProvider; - /// First layer extent - Extent firstLayerExtent; - /// Direction of the telescope extent - BinningValue orientation = BinningValue::binX; + /// Reference layer IDs + std::vector refLayerIds; }; /// @brief Constructor - PathSeeder(const Config& config) : m_cfg(std::move(config)) {}; + PathSeeder(const Config& config) : m_cfg(config) {}; /// @brief Destructor ~PathSeeder() = default; @@ -159,101 +106,86 @@ class PathSeeder { /// sort the source links into the seeds /// /// @param gctx The geometry context - /// @param sourceLinks The source links to seed + /// @param sourceLinkGridLookup The lookup table for the source links + /// @param seedCollection The collection of seeds to fill /// /// @return The vector of seeds - std::vector getSeeds(const GeometryContext& gctx, - const std::vector& sourceLinks) const { - // Get plane of the telescope - // sensitive surfaces - int bin0 = static_cast(BinningValue::binX); - int bin1 = static_cast(BinningValue::binY); - if (m_cfg.orientation == BinningValue::binX) { - bin0 = static_cast(BinningValue::binY); - bin1 = static_cast(BinningValue::binZ); - } else if (m_cfg.orientation == BinningValue::binY) { - bin0 = static_cast(BinningValue::binX); - bin1 = static_cast(BinningValue::binZ); - } - + template + void findSeeds(const GeometryContext& gctx, + const std::unordered_map& + sourceLinkGridLookup, + container_t& seedCollection) const { // Create the seeds - std::vector seeds; - for (const auto& sl : sourceLinks) { - Vector3 globalPos = m_cfg.sourceLinkCalibrator(gctx, sl); - - // Check if the hit is in the - // first tracking layer - if (!m_cfg.firstLayerExtent.contains(globalPos)) { - continue; - } - - // Get the IP parameters - auto [q, ipP, ipVertex, ipDir, flDir] = - m_cfg.trackEstimator(gctx, globalPos); - - // Intersect with the surfaces - std::vector> intersections = - m_cfg.intersectionFinder(gctx, globalPos, flDir, ipP, q); - - // Continue if no intersections - if (intersections.empty()) { - continue; - } - // Vector to store the source links - std::vector seedSourceLinks; - - // Store the pivot source link - seedSourceLinks.push_back(sl); + for (auto& refGeoId : m_cfg.refLayerIds) { + auto refGrid = sourceLinkGridLookup.at(refGeoId); - // Iterate over the intersections - // and get the source links - // in the subsequent layers - for (auto& [geoId, refPoint] : intersections) { - // Get the path width - auto [pathWidth0, pathWidth1] = m_cfg.pathWidthProvider(gctx, geoId); + for (auto it = refGrid.begin(); it != refGrid.end(); it++) { + std::vector pivotSourceLinks = *it; - // Get the bounds of the path - ActsScalar top0 = refPoint[bin0] + pathWidth0; - ActsScalar bot0 = refPoint[bin0] - pathWidth0; - ActsScalar top1 = refPoint[bin1] + pathWidth1; - ActsScalar bot1 = refPoint[bin1] - pathWidth1; + for (const auto& pivot : pivotSourceLinks) { + // Get the IP parameters + auto [ipParameters, refLayerParameters] = + m_cfg.trackEstimator(gctx, pivot); - // Get the lookup table for the source links - auto grid = m_cfg.sourceLinkGridLookup(geoId); + // Intersect with the surfaces + std::vector> intersections = + m_cfg.intersectionFinder(gctx, refLayerParameters); - // Get the range of bins to search for source links - auto botLeftBin = grid.localBinsFromPosition(Vector2(bot0, bot1)); - auto topRightBin = grid.localBinsFromPosition(Vector2(top0, top1)); - - // Get the source links from the lookup table - // by iterating over the bin ranges - auto currentBin = botLeftBin; - while (currentBin.at(1) <= topRightBin.at(1)) { - while (currentBin.at(0) <= topRightBin.at(0)) { - auto sourceLinksToAdd = grid.atLocalBins(currentBin); + // Continue if no intersections + if (intersections.empty()) { + continue; + } - seedSourceLinks.insert(seedSourceLinks.end(), - sourceLinksToAdd.begin(), - sourceLinksToAdd.end()); - currentBin.at(0)++; + // Iterate over the intersections + // and get the source links + // in the subsequent layers + std::vector seedSourceLinks; + for (auto& [geoId, refPoint] : intersections) { + // Get the path width + auto [pathWidth0, pathWidth1] = + m_cfg.pathWidthProvider(gctx, geoId); + + // Get the bounds of the path + ActsScalar top0 = refPoint[0] + pathWidth0; + ActsScalar bot0 = refPoint[0] - pathWidth0; + ActsScalar top1 = refPoint[1] + pathWidth1; + ActsScalar bot1 = refPoint[1] - pathWidth1; + + // Get the lookup table for the source links + auto grid = sourceLinkGridLookup.at(geoId); + + // Get the range of bins to search for source links + auto botLeftBin = grid.localBinsFromPosition(Vector2(bot0, bot1)); + auto topRightBin = grid.localBinsFromPosition(Vector2(top0, top1)); + + // Get the source links from the lookup table + // by iterating over the bin ranges + auto currentBin = botLeftBin; + while (currentBin.at(1) <= topRightBin.at(1)) { + while (currentBin.at(0) <= topRightBin.at(0)) { + auto sourceLinksToAdd = grid.atLocalBins(currentBin); + + seedSourceLinks.insert(seedSourceLinks.end(), + sourceLinksToAdd.begin(), + sourceLinksToAdd.end()); + + currentBin.at(0)++; + } + currentBin.at(1)++; + currentBin.at(0) = botLeftBin.at(0); + } } - currentBin.at(1)++; - currentBin.at(0) = botLeftBin.at(0); + PathSeed seed = {ipParameters, seedSourceLinks}; + + // Add the seed to the collection + Acts::detail::pushBackOrInsertAtEnd(seedCollection, seed); } } - - // Store the IP parameters and - // add the source links to the seed - Seed seed{ipP, ipDir, ipVertex, seedSourceLinks}; - - // Add the seed to the list - seeds.push_back(seed); } - return seeds; - }; + } private: Config m_cfg; }; -} // namespace Acts::Experimental +} // namespace Acts diff --git a/Core/include/Acts/Seeding/detail/UtilityFunctions.hpp b/Core/include/Acts/Seeding/detail/UtilityFunctions.hpp index 9cc61c4fe3f..b4fa190fa37 100644 --- a/Core/include/Acts/Seeding/detail/UtilityFunctions.hpp +++ b/Core/include/Acts/Seeding/detail/UtilityFunctions.hpp @@ -8,6 +8,8 @@ #pragma once +#include "Acts/EventData/SourceLink.hpp" + #include namespace Acts::detail { @@ -29,6 +31,10 @@ concept isCollectionThatSupportsInsert = coll.insert(std::ranges::end(coll), val); }; +template +concept SourceLinkGrid = + std::same_as>; + // Define some functions template diff --git a/Core/include/Acts/TrackFinding/TrackSelector.hpp b/Core/include/Acts/TrackFinding/TrackSelector.hpp index d0e8526dc35..bca7fa8d2a0 100644 --- a/Core/include/Acts/TrackFinding/TrackSelector.hpp +++ b/Core/include/Acts/TrackFinding/TrackSelector.hpp @@ -12,11 +12,11 @@ #include "Acts/EventData/TrackStateType.hpp" #include "Acts/Geometry/GeometryHierarchyMap.hpp" #include "Acts/Geometry/GeometryIdentifier.hpp" +#include "Acts/Utilities/AngleHelpers.hpp" #include #include #include -#include #include #include @@ -142,7 +142,7 @@ class TrackSelector { std::vector cutSets = {}; /// Eta bin edges for varying cuts by eta - std::vector absEtaEdges = {}; + std::vector absEtaEdges = {0, inf}; /// Get the number of eta bins /// @return Number of eta bins @@ -150,7 +150,7 @@ class TrackSelector { /// Construct an empty (accepts everything) configuration. /// Results in a single cut set and one abs eta bin from 0 to infinity. - EtaBinnedConfig() : cutSets{{}}, absEtaEdges{{0, inf}} {}; + EtaBinnedConfig() : cutSets{{}} {}; /// Constructor to create a config object that is not upper-bounded. /// This is useful to use the "fluent" API to populate the configuration. @@ -163,13 +163,12 @@ class TrackSelector { /// @param absEtaEdgesIn is the vector of eta bin edges EtaBinnedConfig(std::vector absEtaEdgesIn) : absEtaEdges{std::move(absEtaEdgesIn)} { - cutSets.resize(absEtaEdges.size() - 1); + cutSets.resize(nEtaBins()); } /// Auto-converting constructor from a single cut configuration. /// Results in a single absolute eta bin from 0 to infinity. - EtaBinnedConfig(Config cutSet) - : cutSets{std::move(cutSet)}, absEtaEdges{{0, inf}} {} + EtaBinnedConfig(Config cutSet) : cutSets{std::move(cutSet)} {} /// Add a new eta bin with the given upper bound. /// @param etaMax Upper bound of the new eta bin @@ -195,11 +194,17 @@ class TrackSelector { /// @return True if the configuration has a bin for the given eta bool hasCuts(double eta) const; - /// Get the index of the eta bin for a given eta + /// Get the index of the eta bin for a given eta. + /// throws an exception if Eta is outside the abs eta bin edges. /// @param eta Eta value /// @return Index of the eta bin std::size_t binIndex(double eta) const; + /// Get the index of the eta bin for a given eta + /// @param eta Eta value + /// @return Index of the eta bin, or >= nEtaBins() if Eta is outside the abs eta bin edges. + std::size_t binIndexNoCheck(double eta) const; + /// Get the cuts for a given eta /// @param eta Eta value /// @return Cuts for the given eta @@ -237,8 +242,7 @@ class TrackSelector { private: EtaBinnedConfig m_cfg; - bool m_isUnbinned; - bool m_noEtaCuts; + bool m_isUnbinned = false; }; inline TrackSelector::Config& TrackSelector::Config::loc0(double min, @@ -350,14 +354,22 @@ inline bool TrackSelector::EtaBinnedConfig::hasCuts(double eta) const { } inline std::size_t TrackSelector::EtaBinnedConfig::binIndex(double eta) const { - if (!hasCuts(eta)) { + std::size_t index = binIndexNoCheck(eta); + if (!(index < nEtaBins())) { throw std::invalid_argument{"Eta is outside the abs eta bin edges"}; } + return index; +} +inline std::size_t TrackSelector::EtaBinnedConfig::binIndexNoCheck( + double eta) const { auto binIt = std::upper_bound(absEtaEdges.begin(), absEtaEdges.end(), std::abs(eta)); - std::size_t index = std::distance(absEtaEdges.begin(), binIt) - 1; - return index; + std::size_t index = std::distance(absEtaEdges.begin(), binIt); + if (index == 0) { + index = absEtaEdges.size() + 1; // positive value to check for underflow + } + return index - 1; } inline const TrackSelector::Config& TrackSelector::EtaBinnedConfig::getCuts( @@ -407,7 +419,7 @@ bool TrackSelector::isValidTrack(const track_proxy_t& track) const { auto absEta = [&]() { if (_absEta == kUnset) { - _eta = -std::log(std::tan(theta / 2)); + _eta = AngleHelpers::etaFromTheta(theta); _absEta = std::abs(_eta); } return _absEta; @@ -428,8 +440,8 @@ bool TrackSelector::isValidTrack(const track_proxy_t& track) const { return track.hasReferenceSurface() && within(track.transverseMomentum(), cuts.ptMin, cuts.ptMax) && - (m_noEtaCuts || (within(absEta(), cuts.absEtaMin, cuts.absEtaMax) && - within(_eta, cuts.etaMin, cuts.etaMax))) && + (!m_isUnbinned || (within(absEta(), cuts.absEtaMin, cuts.absEtaMax) && + within(_eta, cuts.etaMin, cuts.etaMax))) && within(track.phi(), cuts.phiMin, cuts.phiMax) && within(track.loc0(), cuts.loc0Min, cuts.loc0Max) && within(track.loc1(), cuts.loc1Min, cuts.loc1Max) && @@ -452,26 +464,19 @@ inline TrackSelector::TrackSelector( "TrackSelector cut / eta bin configuration is inconsistent"}; } - m_isUnbinned = false; if (m_cfg.nEtaBins() == 1) { static const std::vector infVec = {0, inf}; - bool limitEta = m_cfg.absEtaEdges != infVec; - m_isUnbinned = !limitEta; // single bin, no eta edges given - - const Config& cuts = m_cfg.cutSets[0]; - - if (limitEta && (cuts.etaMin != -inf || cuts.etaMax != inf || - cuts.absEtaMin != 0.0 || cuts.absEtaMax != inf)) { - throw std::invalid_argument{ - "Explicit eta cuts are only valid for single eta bin"}; - } + m_isUnbinned = + m_cfg.absEtaEdges == infVec; // single bin, no eta edges given } - m_noEtaCuts = m_isUnbinned; - for (const auto& cuts : m_cfg.cutSets) { - if (cuts.etaMin != -inf || cuts.etaMax != inf || cuts.absEtaMin != 0.0 || - cuts.absEtaMax != inf) { - m_noEtaCuts = false; + if (!m_isUnbinned) { + for (const auto& cuts : m_cfg.cutSets) { + if (cuts.etaMin != -inf || cuts.etaMax != inf || cuts.absEtaMin != 0.0 || + cuts.absEtaMax != inf) { + throw std::invalid_argument{ + "Explicit eta cuts are only valid for single eta bin"}; + } } } } diff --git a/Core/include/Acts/TrackFitting/BetheHeitlerApprox.hpp b/Core/include/Acts/TrackFitting/BetheHeitlerApprox.hpp index 653bef7e899..666ebf6aa23 100644 --- a/Core/include/Acts/TrackFitting/BetheHeitlerApprox.hpp +++ b/Core/include/Acts/TrackFitting/BetheHeitlerApprox.hpp @@ -125,6 +125,7 @@ class AtlasBetheHeitlerApprox { constexpr static double m_singleGaussianLimit = 0.002; double m_lowLimit = 0.10; double m_highLimit = 0.20; + bool m_clampToRange = false; public: /// Construct the Bethe-Heitler approximation description with two @@ -138,16 +139,19 @@ class AtlasBetheHeitlerApprox { /// @param highTransform whether the high data need to be transformed /// @param lowLimit the upper limit for the low data /// @param highLimit the upper limit for the high data + /// @param clampToRange whether to clamp the input x/x0 to the allowed range constexpr AtlasBetheHeitlerApprox(const Data &lowData, const Data &highData, bool lowTransform, bool highTransform, double lowLimit = 0.1, - double highLimit = 0.2) + double highLimit = 0.2, + bool clampToRange = false) : m_lowData(lowData), m_highData(highData), m_lowTransform(lowTransform), m_highTransform(highTransform), m_lowLimit(lowLimit), - m_highLimit(highLimit) {} + m_highLimit(highLimit), + m_clampToRange(clampToRange) {} /// Returns the number of components the returned mixture will have constexpr auto numComponents() const { return NComponents; } @@ -155,7 +159,13 @@ class AtlasBetheHeitlerApprox { /// Checks if an input is valid for the parameterization /// /// @param x pathlength in terms of the radiation length - constexpr bool validXOverX0(ActsScalar x) const { return x < m_highLimit; } + constexpr bool validXOverX0(ActsScalar x) const { + if (m_clampToRange) { + return true; + } else { + return x < m_highLimit; + } + } /// Generates the mixture from the polynomials and reweights them, so /// that the sum of all weights is 1 @@ -164,6 +174,11 @@ class AtlasBetheHeitlerApprox { auto mixture(ActsScalar x) const { using Array = boost::container::static_vector; + + if (m_clampToRange) { + x = std::clamp(x, 0.0, m_highLimit); + } + // Build a polynom auto poly = [](ActsScalar xx, const std::array &coeffs) { @@ -238,9 +253,11 @@ class AtlasBetheHeitlerApprox { /// the parameterization for high x/x0 /// @param lowLimit the upper limit for the low x/x0-data /// @param highLimit the upper limit for the high x/x0-data + /// @param clampToRange forwarded to constructor static auto loadFromFiles(const std::string &low_parameters_path, const std::string &high_parameters_path, - double lowLimit = 0.1, double highLimit = 0.2) { + double lowLimit = 0.1, double highLimit = 0.2, + bool clampToRange = false) { auto read_file = [](const std::string &filepath) { std::ifstream file(filepath); @@ -284,7 +301,8 @@ class AtlasBetheHeitlerApprox { const auto [highData, highTransform] = read_file(high_parameters_path); return AtlasBetheHeitlerApprox(lowData, highData, lowTransform, - highTransform, lowLimit, highLimit); + highTransform, lowLimit, highLimit, + clampToRange); } }; @@ -292,6 +310,7 @@ class AtlasBetheHeitlerApprox { /// configuration, that are stored as static data in the source code. /// This may not be an optimal configuration, but should allow to run /// the GSF without the need to load files -AtlasBetheHeitlerApprox<6, 5> makeDefaultBetheHeitlerApprox(); +AtlasBetheHeitlerApprox<6, 5> makeDefaultBetheHeitlerApprox( + bool clampToRange = false); } // namespace Acts diff --git a/Core/include/Acts/TrackFitting/detail/GainMatrixUpdaterImpl.hpp b/Core/include/Acts/TrackFitting/detail/GainMatrixUpdaterImpl.hpp index 7a6e1ec6434..0dce3c2ba21 100644 --- a/Core/include/Acts/TrackFitting/detail/GainMatrixUpdaterImpl.hpp +++ b/Core/include/Acts/TrackFitting/detail/GainMatrixUpdaterImpl.hpp @@ -8,6 +8,7 @@ #pragma once +#include "Acts/EventData/TrackParameterHelpers.hpp" #include "Acts/TrackFitting/GainMatrixUpdater.hpp" #include "Acts/Utilities/Logger.hpp" @@ -60,6 +61,8 @@ std::tuple GainMatrixUpdater::visitMeasurementImpl( trackState.filtered = trackState.predicted + K * (calibrated - H * trackState.predicted); + // Normalize phi and theta + trackState.filtered = normalizeBoundParameters(trackState.filtered); trackState.filteredCovariance = (BoundSquareMatrix::Identity() - K * H) * trackState.predictedCovariance; ACTS_VERBOSE("Filtered parameters: " << trackState.filtered.transpose()); diff --git a/Core/include/Acts/Utilities/AngleHelpers.hpp b/Core/include/Acts/Utilities/AngleHelpers.hpp new file mode 100644 index 00000000000..02feec2323e --- /dev/null +++ b/Core/include/Acts/Utilities/AngleHelpers.hpp @@ -0,0 +1,35 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#pragma once + +#include + +namespace Acts::AngleHelpers { + +/// Calculate the pseudorapidity from the polar angle theta. +/// +/// @param theta is the polar angle in radian towards the z-axis. +/// +/// @return the pseudorapidity towards the z-axis. +template +Scalar etaFromTheta(Scalar theta) { + return -std::log(std::tan(0.5 * theta)); +} + +/// Calculate the polar angle theta from the pseudorapidity. +/// +/// @param eta is the pseudorapidity towards the z-axis. +/// +/// @return the polar angle in radian towards the z-axis. +template +Scalar thetaFromEta(Scalar eta) { + return 2 * std::atan(std::exp(-eta)); +} + +} // namespace Acts::AngleHelpers diff --git a/Core/include/Acts/Utilities/BoundingBox.ipp b/Core/include/Acts/Utilities/BoundingBox.ipp index 330353014fa..d989507fa85 100644 --- a/Core/include/Acts/Utilities/BoundingBox.ipp +++ b/Core/include/Acts/Utilities/BoundingBox.ipp @@ -346,8 +346,7 @@ template Acts::AxisAlignedBoundingBox Acts::AxisAlignedBoundingBox::transformed( const transform_type& trf) const { - VertexType vmin, vmax; - std::tie(vmin, vmax) = transformVertices(trf); + const auto [vmin, vmax] = transformVertices(trf); return self_t(m_entity, vmin, vmax); } @@ -463,8 +462,7 @@ box_t* octree_inner(std::vector>& store, std::array, 8> octants; // calc center of boxes - VertexType vmin, vmax; - std::tie(vmin, vmax) = box_t::wrap(lprims); + const auto [vmin, vmax] = box_t::wrap(lprims); VertexType glob_ctr = (vmin + vmax) / 2.; for (auto* box : lprims) { diff --git a/Core/include/Acts/Utilities/GridAxisGenerators.hpp b/Core/include/Acts/Utilities/GridAxisGenerators.hpp index 2ebeb78406f..18e6a1cdd2e 100644 --- a/Core/include/Acts/Utilities/GridAxisGenerators.hpp +++ b/Core/include/Acts/Utilities/GridAxisGenerators.hpp @@ -110,7 +110,7 @@ struct EqEq { nBins0); Acts::Axis bEq(range1[0u], range1[1u], nBins1); - return std::tie(aEq, bEq); + return {aEq, bEq}; } }; @@ -160,7 +160,7 @@ struct EqVar { Acts::Axis eqA(range[0u], range[1u], nBins); Acts::Axis varB(edges); - return std::tie(eqA, varB); + return {eqA, varB}; } }; @@ -210,7 +210,7 @@ struct VarEq { Acts::Axis varA(edges); Acts::Axis eqB(range[0u], range[1u], nBins); - return std::tie(varA, eqB); + return {varA, eqB}; } }; @@ -257,7 +257,7 @@ struct VarVar { return_type operator()() const { Acts::Axis varA(edges0); Acts::Axis varB(edges1); - return std::tie(varA, varB); + return {varA, varB}; } }; diff --git a/Core/include/Acts/Utilities/Helpers.hpp b/Core/include/Acts/Utilities/Helpers.hpp index 2308d2a3014..4bf9d1c89c3 100644 --- a/Core/include/Acts/Utilities/Helpers.hpp +++ b/Core/include/Acts/Utilities/Helpers.hpp @@ -179,7 +179,7 @@ std::tuple range_medium(const T& tseries) { auto [minIt, maxIt] = std::ranges::minmax_element(tseries); typename T::value_type range = (*maxIt - *minIt); ActsScalar medium = static_cast((*maxIt + *minIt) * 0.5); - return std::tie(range, medium); + return {range, medium}; } template diff --git a/Core/include/Acts/Vertexing/detail/KalmanVertexUpdaterImpl.hpp b/Core/include/Acts/Vertexing/detail/KalmanVertexUpdaterImpl.hpp index 4c08820e693..f8f99b98f20 100644 --- a/Core/include/Acts/Vertexing/detail/KalmanVertexUpdaterImpl.hpp +++ b/Core/include/Acts/Vertexing/detail/KalmanVertexUpdaterImpl.hpp @@ -254,9 +254,7 @@ void updateVertexWithTrackImpl(Vertex& vtx, TrackAtVertex& trk, int sign) { calculateUpdate(vtx, trk.linearizedState, trackWeight, sign, cache); // Get fit quality parameters wrt to old vertex - double chi2 = 0.; - double ndf = 0.; - std::tie(chi2, ndf) = vtx.fitQuality(); + auto [chi2, ndf] = vtx.fitQuality(); // Chi2 of the track parameters double trkChi2 = trackParametersChi2(trk.linearizedState, cache); diff --git a/Core/src/Detector/detail/CuboidalDetectorHelper.cpp b/Core/src/Detector/detail/CuboidalDetectorHelper.cpp index 114b8512e7f..ac2acd2482a 100644 --- a/Core/src/Detector/detail/CuboidalDetectorHelper.cpp +++ b/Core/src/Detector/detail/CuboidalDetectorHelper.cpp @@ -373,7 +373,7 @@ Acts::Experimental::detail::CuboidalDetectorHelper::xyzBoundaries( } for (auto [im, map] : enumerate(valueMaps)) { - for (auto [key, value] : map) { + for (auto [key, _] : map) { boundaries[im].push_back(key); } std::ranges::sort(boundaries[im]); diff --git a/Core/src/Geometry/CylinderVolumeBounds.cpp b/Core/src/Geometry/CylinderVolumeBounds.cpp index c7bb8192f4a..d9af620ea45 100644 --- a/Core/src/Geometry/CylinderVolumeBounds.cpp +++ b/Core/src/Geometry/CylinderVolumeBounds.cpp @@ -309,4 +309,7 @@ void CylinderVolumeBounds::set( } } +CylinderVolumeBounds::CylinderVolumeBounds(const CylinderVolumeBounds& cylbo) = + default; + } // namespace Acts diff --git a/Core/src/Geometry/TrackingVolume.cpp b/Core/src/Geometry/TrackingVolume.cpp index e7d069b80c5..611904537f0 100644 --- a/Core/src/Geometry/TrackingVolume.cpp +++ b/Core/src/Geometry/TrackingVolume.cpp @@ -16,6 +16,8 @@ #include "Acts/Material/IMaterialDecorator.hpp" #include "Acts/Material/IVolumeMaterial.hpp" #include "Acts/Material/ProtoVolumeMaterial.hpp" +#include "Acts/Navigation/INavigationPolicy.hpp" +#include "Acts/Navigation/NavigationStream.hpp" #include "Acts/Propagator/Navigator.hpp" #include "Acts/Surfaces/RegularSurface.hpp" #include "Acts/Surfaces/Surface.hpp" @@ -28,6 +30,8 @@ #include #include +#include + namespace Acts { // constructor for arguments @@ -47,6 +51,10 @@ TrackingVolume::TrackingVolume( createBoundarySurfaces(); interlinkLayers(); connectDenseBoundarySurfaces(denseVolumeVector); + + DelegateChainBuilder{m_navigationDelegate} + .add<&INavigationPolicy::noopInitializeCandidates>() + .store(m_navigationDelegate); } TrackingVolume::TrackingVolume(Volume& volume, const std::string& volumeName) @@ -61,6 +69,8 @@ TrackingVolume::TrackingVolume(const Transform3& transform, {}, volumeName) {} TrackingVolume::~TrackingVolume() = default; +TrackingVolume::TrackingVolume(TrackingVolume&&) = default; +TrackingVolume& TrackingVolume::operator=(TrackingVolume&&) = default; const TrackingVolume* TrackingVolume::lowestTrackingVolume( const GeometryContext& gctx, const Vector3& position, @@ -735,4 +745,20 @@ void TrackingVolume::visualize(IVisualization3D& helper, } } +void TrackingVolume::setNavigationPolicy( + std::unique_ptr policy) { + if (policy == nullptr) { + throw std::invalid_argument("Navigation policy is nullptr"); + } + + m_navigationPolicy = std::move(policy); + m_navigationPolicy->connect(m_navigationDelegate); +} + +void TrackingVolume::initializeNavigationCandidates( + const NavigationArguments& args, AppendOnlyNavigationStream& stream, + const Logger& logger) const { + m_navigationDelegate(args, stream, logger); +} + } // namespace Acts diff --git a/Core/src/MagneticField/BFieldMapUtils.cpp b/Core/src/MagneticField/BFieldMapUtils.cpp index 14bc273966b..e7216aa3bf9 100644 --- a/Core/src/MagneticField/BFieldMapUtils.cpp +++ b/Core/src/MagneticField/BFieldMapUtils.cpp @@ -254,12 +254,9 @@ Acts::solenoidFieldMap(std::pair rlim, std::pair zlim, std::pair nbins, const SolenoidBField& field) { - double rMin = 0, rMax = 0, zMin = 0, zMax = 0; - std::tie(rMin, rMax) = rlim; - std::tie(zMin, zMax) = zlim; - - std::size_t nBinsR = 0, nBinsZ = 0; - std::tie(nBinsR, nBinsZ) = nbins; + auto [rMin, rMax] = rlim; + auto [zMin, zMax] = zlim; + const auto [nBinsR, nBinsZ] = nbins; double stepZ = std::abs(zMax - zMin) / (nBinsZ - 1); double stepR = std::abs(rMax - rMin) / (nBinsR - 1); diff --git a/Core/src/Material/BinnedSurfaceMaterialAccumulater.cpp b/Core/src/Material/BinnedSurfaceMaterialAccumulater.cpp index ca2a460d4d2..a4d2366b743 100644 --- a/Core/src/Material/BinnedSurfaceMaterialAccumulater.cpp +++ b/Core/src/Material/BinnedSurfaceMaterialAccumulater.cpp @@ -119,9 +119,9 @@ void Acts::BinnedSurfaceMaterialAccumulater::accumulate( } // After mapping this track, average the touched bins - for (auto tmapBin : touchedMapBins) { - std::vector> trackBins = {tmapBin.second}; - tmapBin.first->trackAverage(trackBins, true); + for (const auto& [key, value] : touchedMapBins) { + std::vector> trackBins = {value}; + key->trackAverage(trackBins, true); } // Empty bin correction diff --git a/Core/src/Material/SurfaceMaterialMapper.cpp b/Core/src/Material/SurfaceMaterialMapper.cpp index 4890354217a..f4ad7ecc6f9 100644 --- a/Core/src/Material/SurfaceMaterialMapper.cpp +++ b/Core/src/Material/SurfaceMaterialMapper.cpp @@ -416,19 +416,19 @@ void Acts::SurfaceMaterialMapper::mapInteraction( } // After mapping this track, average the touched bins - for (auto tmapBin : touchedMapBins) { - std::vector> trackBins = {tmapBin.second}; + for (const auto& [key, value] : touchedMapBins) { + std::vector> trackBins = {value}; if (m_cfg.computeVariance) { // This only makes sense for the binned material auto binnedMaterial = dynamic_cast( - touchedMaterialBin[tmapBin.first].get()); + touchedMaterialBin[key].get()); if (binnedMaterial != nullptr) { - tmapBin.first->trackVariance( + key->trackVariance( trackBins, binnedMaterial->fullMaterial()[trackBins[0][1]][trackBins[0][0]]); } } - tmapBin.first->trackAverage(trackBins); + key->trackAverage(trackBins); } // After mapping this track, average the untouched but intersected bins @@ -493,14 +493,14 @@ void Acts::SurfaceMaterialMapper::mapSurfaceInteraction( } // After mapping this track, average the touched bins - for (auto tmapBin : touchedMapBins) { - std::vector> trackBins = {tmapBin.second}; + for (const auto& [key, value] : touchedMapBins) { + std::vector> trackBins = {value}; if (m_cfg.computeVariance) { // This only makes sense for the binned material auto binnedMaterial = dynamic_cast( - touchedMaterialBin[tmapBin.first].get()); + touchedMaterialBin[key].get()); if (binnedMaterial != nullptr) { - tmapBin.first->trackVariance( + key->trackVariance( trackBins, binnedMaterial->fullMaterial()[trackBins[0][1]][trackBins[0][0]], true); @@ -508,6 +508,6 @@ void Acts::SurfaceMaterialMapper::mapSurfaceInteraction( } // No need to do an extra pass for untouched surfaces they would have been // added to the material interaction in the initial mapping - tmapBin.first->trackAverage(trackBins, true); + key->trackAverage(trackBins, true); } } diff --git a/Core/src/Navigation/CMakeLists.txt b/Core/src/Navigation/CMakeLists.txt index 81cbf616d44..72bbf65b853 100644 --- a/Core/src/Navigation/CMakeLists.txt +++ b/Core/src/Navigation/CMakeLists.txt @@ -1 +1,7 @@ -target_sources(ActsCore PRIVATE NavigationStream.cpp) +target_sources( + ActsCore + PRIVATE + NavigationStream.cpp + TryAllNavigationPolicy.cpp + SurfaceArrayNavigationPolicy.cpp +) diff --git a/Core/src/Navigation/NavigationStream.cpp b/Core/src/Navigation/NavigationStream.cpp index bf15367cd3b..c36eed12bbe 100644 --- a/Core/src/Navigation/NavigationStream.cpp +++ b/Core/src/Navigation/NavigationStream.cpp @@ -13,10 +13,12 @@ #include -bool Acts::NavigationStream::initialize(const GeometryContext& gctx, - const QueryPoint& queryPoint, - const BoundaryTolerance& cTolerance, - ActsScalar onSurfaceTolerance) { +namespace Acts { + +bool NavigationStream::initialize(const GeometryContext& gctx, + const QueryPoint& queryPoint, + const BoundaryTolerance& cTolerance, + ActsScalar onSurfaceTolerance) { // Position and direction from the query point const Vector3& position = queryPoint.position; const Vector3& direction = queryPoint.direction; @@ -36,7 +38,7 @@ bool Acts::NavigationStream::initialize(const GeometryContext& gctx, // A container collecting additional candidates from multiple // valid interseciton std::vector additionalCandidates = {}; - for (auto& [sIntersection, portal, bTolerance] : m_candidates) { + for (auto& [sIntersection, gen2Portal, portal, bTolerance] : m_candidates) { // Get the surface from the object intersection const Surface* surface = sIntersection.object(); // Intersect the surface @@ -58,7 +60,10 @@ bool Acts::NavigationStream::initialize(const GeometryContext& gctx, originalCandidateUpdated = true; } else { additionalCandidates.emplace_back( - Candidate{rsIntersection, portal, bTolerance}); + Candidate{.intersection = rsIntersection, + .gen2Portal = gen2Portal, + .portal = portal, + .bTolerance = bTolerance}); } } } @@ -74,7 +79,7 @@ bool Acts::NavigationStream::initialize(const GeometryContext& gctx, // The we find the first invalid candidate auto firstInvalid = std::ranges::find_if(m_candidates, [](const Candidate& a) { - const auto& [aIntersection, aPortal, aTolerance] = a; + const auto& [aIntersection, aGen2Portal, aPortal, aTolerance] = a; return !aIntersection.isValid(); }); @@ -88,32 +93,28 @@ bool Acts::NavigationStream::initialize(const GeometryContext& gctx, return true; } -bool Acts::NavigationStream::update(const GeometryContext& gctx, - const QueryPoint& queryPoint, - ActsScalar onSurfaceTolerance) { - // Position and direction from the query point - const Vector3& position = queryPoint.position; - const Vector3& direction = queryPoint.direction; - +bool NavigationStream::update(const GeometryContext& gctx, + const QueryPoint& queryPoint, + ActsScalar onSurfaceTolerance) { // Loop over the (currently valid) candidates and update for (; m_currentIndex < m_candidates.size(); ++m_currentIndex) { // Get the candidate, and resolve the tuple Candidate& candidate = currentCandidate(); - auto& [sIntersection, portal, bTolerance] = candidate; // Get the surface from the object intersection - const Surface* surface = sIntersection.object(); + const Surface* surface = candidate.intersection.object(); // (re-)Intersect the surface - auto multiIntersection = surface->intersect(gctx, position, direction, - bTolerance, onSurfaceTolerance); + auto multiIntersection = + surface->intersect(gctx, queryPoint.position, queryPoint.direction, + candidate.bTolerance, onSurfaceTolerance); // Split them into valid intersections for (const auto& rsIntersection : multiIntersection.split()) { // Skip wrong index solution - if (rsIntersection.index() != sIntersection.index()) { + if (rsIntersection.index() != candidate.intersection.index()) { continue; } // Valid solution is either on surface or updates the distance if (rsIntersection.isValid()) { - sIntersection = rsIntersection; + candidate.intersection = rsIntersection; return true; } } @@ -122,32 +123,57 @@ bool Acts::NavigationStream::update(const GeometryContext& gctx, return false; } -void Acts::NavigationStream::addSurfaceCandidate( - const Surface* surface, const BoundaryTolerance& bTolerance) { - m_candidates.emplace_back(Candidate{ - ObjectIntersection::invalid(surface), nullptr, bTolerance}); +void NavigationStream::addSurfaceCandidate( + const Surface& surface, const BoundaryTolerance& bTolerance) { + m_candidates.emplace_back( + Candidate{.intersection = ObjectIntersection::invalid(&surface), + .bTolerance = bTolerance}); } -void Acts::NavigationStream::addSurfaceCandidates( - const std::vector& surfaces, - const BoundaryTolerance& bTolerance) { +void NavigationStream::addSurfaceCandidates( + std::span surfaces, const BoundaryTolerance& bTolerance) { std::ranges::for_each(surfaces, [&](const auto* surface) { - m_candidates.emplace_back(Candidate{ - ObjectIntersection::invalid(surface), nullptr, bTolerance}); + m_candidates.emplace_back( + Candidate{.intersection = ObjectIntersection::invalid(surface), + .bTolerance = bTolerance}); }); } -void Acts::NavigationStream::addPortalCandidate(const Portal* portal) { - m_candidates.emplace_back( - Candidate{ObjectIntersection::invalid(&(portal->surface())), - portal, BoundaryTolerance::None()}); +void NavigationStream::addPortalCandidate(const Experimental::Portal& portal) { + m_candidates.emplace_back(Candidate{ + .intersection = ObjectIntersection::invalid(&portal.surface()), + .gen2Portal = &portal, + .bTolerance = BoundaryTolerance::None()}); +} + +void NavigationStream::addPortalCandidate(const Portal& portal) { + m_candidates.emplace_back(Candidate{ + .intersection = ObjectIntersection::invalid(&portal.surface()), + .portal = &portal, + .bTolerance = BoundaryTolerance::None()}); } -void Acts::NavigationStream::addPortalCandidates( - const std::vector& portals) { +void NavigationStream::addPortalCandidates( + std::span portals) { std::ranges::for_each(portals, [&](const auto& portal) { - m_candidates.emplace_back( - Candidate{ObjectIntersection::invalid(&(portal->surface())), - portal, BoundaryTolerance::None()}); + m_candidates.emplace_back(Candidate{ + .intersection = + ObjectIntersection::invalid(&(portal->surface())), + .gen2Portal = portal, + .bTolerance = BoundaryTolerance::None()}); }); } + +AppendOnlyNavigationStream::AppendOnlyNavigationStream(NavigationStream& stream) + : m_stream{&stream} {} + +void AppendOnlyNavigationStream::addPortalCandidate(const Portal& portal) { + m_stream->addPortalCandidate(portal); +} + +void AppendOnlyNavigationStream::addSurfaceCandidate( + const Surface& surface, const BoundaryTolerance& bTolerance) { + m_stream->addSurfaceCandidate(surface, bTolerance); +} + +} // namespace Acts diff --git a/Core/src/Navigation/SurfaceArrayNavigationPolicy.cpp b/Core/src/Navigation/SurfaceArrayNavigationPolicy.cpp new file mode 100644 index 00000000000..f40621fdd06 --- /dev/null +++ b/Core/src/Navigation/SurfaceArrayNavigationPolicy.cpp @@ -0,0 +1,83 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include "Acts/Navigation/SurfaceArrayNavigationPolicy.hpp" + +#include "Acts/Geometry/SurfaceArrayCreator.hpp" +#include "Acts/Geometry/TrackingVolume.hpp" +#include "Acts/Navigation/NavigationStream.hpp" + +#include + +namespace Acts { + +SurfaceArrayNavigationPolicy::SurfaceArrayNavigationPolicy( + const GeometryContext& gctx, const TrackingVolume& volume, + const Logger& logger, Config config) + : m_volume(volume) { + ACTS_VERBOSE("Constructing SurfaceArrayNavigationPolicy for volume " + << volume.volumeName()); + ACTS_VERBOSE("~> Layer type is " << config.layerType); + ACTS_VERBOSE("~> bins: " << config.bins.first << " x " << config.bins.second); + + SurfaceArrayCreator::Config sacConfig; + SurfaceArrayCreator sac{sacConfig, logger.clone("SrfArrCrtr")}; + + std::vector> surfaces; + surfaces.reserve(volume.surfaces().size()); + for (const auto& surface : volume.surfaces()) { + if (surface.associatedDetectorElement() == nullptr) { + continue; + } + surfaces.push_back(surface.getSharedPtr()); + } + + if (config.layerType == LayerType::Disc) { + auto [binsR, binsPhi] = config.bins; + m_surfaceArray = + sac.surfaceArrayOnDisc(gctx, std::move(surfaces), binsPhi, binsR); + } else if (config.layerType == LayerType::Cylinder) { + auto [binsPhi, binsZ] = config.bins; + m_surfaceArray = + sac.surfaceArrayOnCylinder(gctx, std::move(surfaces), binsPhi, binsZ); + // m_surfaces = sac.createCylinderSurfaces(config.bins.first, + // config.bins.second); + } else if (config.layerType == LayerType::Plane) { + ACTS_ERROR("Plane layers are not yet supported"); + throw std::invalid_argument("Plane layers are not yet supported"); + } else { + throw std::invalid_argument("Unknown layer type"); + } + + if (!m_surfaceArray) { + ACTS_ERROR("Failed to create surface array"); + throw std::runtime_error("Failed to create surface array"); + } +} + +void SurfaceArrayNavigationPolicy::initializeCandidates( + const NavigationArguments& args, AppendOnlyNavigationStream& stream, + const Logger& logger) const { + ACTS_VERBOSE("SrfArrNavPol (volume=" << m_volume.volumeName() << ")"); + + ACTS_VERBOSE("Querying sensitive surfaces at " << args.position.transpose()); + const std::vector& sensitiveSurfaces = + m_surfaceArray->neighbors(args.position); + ACTS_VERBOSE("~> Surface array reports " << sensitiveSurfaces.size() + << " sensitive surfaces"); + + for (const auto* surface : sensitiveSurfaces) { + stream.addSurfaceCandidate(*surface, args.tolerance); + }; +} + +void SurfaceArrayNavigationPolicy::connect(NavigationDelegate& delegate) const { + connectDefault(delegate); +} + +} // namespace Acts diff --git a/Core/src/Navigation/TryAllNavigationPolicy.cpp b/Core/src/Navigation/TryAllNavigationPolicy.cpp new file mode 100644 index 00000000000..40ca70c4079 --- /dev/null +++ b/Core/src/Navigation/TryAllNavigationPolicy.cpp @@ -0,0 +1,54 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include "Acts/Navigation/TryAllNavigationPolicy.hpp" + +#include "Acts/Geometry/TrackingVolume.hpp" +#include "Acts/Navigation/NavigationStream.hpp" + +namespace Acts { + +TryAllNavigationPolicy::TryAllNavigationPolicy(const Config& config, + const GeometryContext& /*gctx*/, + const TrackingVolume& volume, + const Logger& logger) + : m_cfg{config}, m_volume(&volume) { + assert(m_volume != nullptr); + ACTS_VERBOSE("TryAllNavigationPolicy created for volume " + << m_volume->volumeName()); +} + +TryAllNavigationPolicy::TryAllNavigationPolicy(const GeometryContext& gctx, + const TrackingVolume& volume, + const Logger& logger) + : TryAllNavigationPolicy({}, gctx, volume, logger) {} + +void TryAllNavigationPolicy::initializeCandidates( + const NavigationArguments& args, AppendOnlyNavigationStream& stream, + const Logger& logger) const { + ACTS_VERBOSE("TryAllNavigationPolicy"); + assert(m_volume != nullptr); + + if (m_cfg.portals) { + for (const auto& portal : m_volume->portals()) { + stream.addPortalCandidate(portal); + } + } + + if (m_cfg.sensitives) { + for (const auto& surface : m_volume->surfaces()) { + stream.addSurfaceCandidate(surface, args.tolerance); + }; + } +} + +void TryAllNavigationPolicy::connect(NavigationDelegate& delegate) const { + connectDefault(delegate); +} + +} // namespace Acts diff --git a/Core/src/Seeding/CMakeLists.txt b/Core/src/Seeding/CMakeLists.txt new file mode 100644 index 00000000000..770037b1dfd --- /dev/null +++ b/Core/src/Seeding/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(ActsCore PRIVATE EstimateTrackParamsFromSeed.cpp) diff --git a/Core/src/Seeding/EstimateTrackParamsFromSeed.cpp b/Core/src/Seeding/EstimateTrackParamsFromSeed.cpp new file mode 100644 index 00000000000..83d950fc3a1 --- /dev/null +++ b/Core/src/Seeding/EstimateTrackParamsFromSeed.cpp @@ -0,0 +1,50 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include "Acts/Seeding/EstimateTrackParamsFromSeed.hpp" + +#include "Acts/Definitions/TrackParametrization.hpp" + +Acts::BoundMatrix Acts::estimateTrackParamCovariance( + const EstimateTrackParamCovarianceConfig& config, const BoundVector& params, + bool hasTime) { + assert((params[eBoundTheta] > 0 && params[eBoundTheta] < M_PI) && + "Theta must be in the range (0, pi)"); + + BoundSquareMatrix result = BoundSquareMatrix::Zero(); + + for (std::size_t i = eBoundLoc0; i < eBoundSize; ++i) { + double sigma = config.initialSigmas[i]; + double variance = sigma * sigma; + + if (i == eBoundQOverP) { + // note that we rely on the fact that sigma theta is already computed + double varianceTheta = result(eBoundTheta, eBoundTheta); + + // transverse momentum contribution + variance += std::pow(config.initialSigmaPtRel * params[eBoundQOverP], 2); + + // theta contribution + variance += + varianceTheta * + std::pow(params[eBoundQOverP] / std::tan(params[eBoundTheta]), 2); + } + + if (i == eBoundTime && !hasTime) { + // Inflate the time uncertainty if no time measurement is available + variance *= config.noTimeVarInflation; + } + + // Inflate the initial covariance + variance *= config.initialVarInflation[i]; + + result(i, i) = variance; + } + + return result; +} diff --git a/Core/src/TrackFinding/AmbiguityTrackClustering.cpp b/Core/src/TrackFinding/AmbiguityTrackClustering.cpp index ca6b39571af..ff0e95cbb3d 100644 --- a/Core/src/TrackFinding/AmbiguityTrackClustering.cpp +++ b/Core/src/TrackFinding/AmbiguityTrackClustering.cpp @@ -22,26 +22,26 @@ Acts::detail::clusterDuplicateTracks( std::unordered_map hitToTrack; // Loop over all the tracks - for (auto track = trackMap.rbegin(); track != trackMap.rend(); ++track) { - std::vector hits = track->second.second; + for (const auto& [_, trackValue] : trackMap) { + std::vector hits = trackValue.second; auto matchedTrack = hitToTrack.end(); // Loop over all the hits in the track - for (auto hit = hits.begin(); hit != hits.end(); hit++) { + for (const auto& hit : hits) { // Check if the hit is already associated to a track - matchedTrack = hitToTrack.find(*hit); + matchedTrack = hitToTrack.find(hit); if (matchedTrack != hitToTrack.end()) { // Add the track to the cluster associated to the matched track - cluster.at(matchedTrack->second).push_back(track->second.first); + cluster.at(matchedTrack->second).push_back(trackValue.first); break; } } // None of the hits have been matched to a track create a new cluster if (matchedTrack == hitToTrack.end()) { - cluster.emplace(track->second.first, - std::vector(1, track->second.first)); + cluster.emplace(trackValue.first, + std::vector(1, trackValue.first)); for (const auto& hit : hits) { // Add the hits of the new cluster to the hitToTrack - hitToTrack.emplace(hit, track->second.first); + hitToTrack.emplace(hit, trackValue.first); } } } diff --git a/Core/src/TrackFinding/GbtsConnector.cpp b/Core/src/TrackFinding/GbtsConnector.cpp index acebffa9f74..d947894871c 100644 --- a/Core/src/TrackFinding/GbtsConnector.cpp +++ b/Core/src/TrackFinding/GbtsConnector.cpp @@ -9,6 +9,7 @@ // TODO: update to C++17 style #include "Acts/TrackFinding/GbtsConnector.hpp" +#include #include #include #include @@ -57,15 +58,8 @@ GbtsConnector::GbtsConnector(std::ifstream &inFile) { continue; } - std::map>::iterator it = - m_connMap.find(stage); - - if (it == m_connMap.end()) { - std::vector v(1, pC); - m_connMap.insert(std::make_pair(stage, v)); - } else { - (*it).second.push_back(pC); - } + auto &connections = m_connMap[stage]; + connections.push_back(pC); } // re-arrange the connection stages @@ -74,9 +68,8 @@ GbtsConnector::GbtsConnector(std::ifstream &inFile) { std::map> newConnMap; - for (const auto &conn : m_connMap) { - std::copy(conn.second.begin(), conn.second.end(), - std::back_inserter(lConns)); + for (const auto &[_, value] : m_connMap) { + std::ranges::copy(value, std::back_inserter(lConns)); } int stageCounter = 0; @@ -111,19 +104,19 @@ GbtsConnector::GbtsConnector(std::ifstream &inFile) { std::set zeroLayers; - for (const auto &layerCounts : mCounter) { - if (layerCounts.second.second != 0) { + for (const auto &[key, value] : mCounter) { + if (value.second != 0) { continue; } - zeroLayers.insert(layerCounts.first); + zeroLayers.insert(key); } // remove connections which use zeroLayer as destination std::vector theStage; - std::list::iterator cIt = lConns.begin(); + auto cIt = lConns.begin(); while (cIt != lConns.end()) { if (zeroLayers.contains((*cIt)->m_dst)) { @@ -144,10 +137,9 @@ GbtsConnector::GbtsConnector(std::ifstream &inFile) { // the doublet making is done using "outside-in" approach hence the reverse // iterations - for (std::map>::reverse_iterator it = - newConnMap.rbegin(); - it != newConnMap.rend(); ++it, currentStage++) { - const std::vector &vConn = (*it).second; + for (auto it = newConnMap.rbegin(); it != newConnMap.rend(); + it++, currentStage++) { + const auto &[_, vConn] = *it; // loop over links, extract all connections for the stage, group sources by // L1 (dst) index @@ -157,8 +149,7 @@ GbtsConnector::GbtsConnector(std::ifstream &inFile) { for (const auto *conn : vConn) { unsigned int dst = conn->m_dst; - std::map>::iterator - l1MapIt = l1ConnMap.find(dst); + auto l1MapIt = l1ConnMap.find(dst); if (l1MapIt != l1ConnMap.end()) { (*l1MapIt).second.push_back(conn); } else { @@ -171,8 +162,8 @@ GbtsConnector::GbtsConnector(std::ifstream &inFile) { lgv.reserve(l1ConnMap.size()); - for (const auto &l1Group : l1ConnMap) { - lgv.push_back(LayerGroup(l1Group.first, l1Group.second)); + for (const auto &[key, value] : l1ConnMap) { + lgv.emplace_back(LayerGroup(key, value)); } m_layerGroups.insert(std::make_pair(currentStage, lgv)); @@ -183,12 +174,9 @@ GbtsConnector::GbtsConnector(std::ifstream &inFile) { GbtsConnector::~GbtsConnector() { m_layerGroups.clear(); - for (std::map>::iterator it = - m_connMap.begin(); - it != m_connMap.end(); ++it) { - for (std::vector::iterator cIt = (*it).second.begin(); - cIt != (*it).second.end(); ++cIt) { - delete (*cIt); + for (const auto &[_, connections] : m_connMap) { + for (auto *conn : connections) { + delete conn; } } } diff --git a/Core/src/TrackFitting/BetheHeitlerApprox.cpp b/Core/src/TrackFitting/BetheHeitlerApprox.cpp index b19b9921902..272d6e08c8d 100644 --- a/Core/src/TrackFitting/BetheHeitlerApprox.cpp +++ b/Core/src/TrackFitting/BetheHeitlerApprox.cpp @@ -8,7 +8,8 @@ #include "Acts/TrackFitting/BetheHeitlerApprox.hpp" -Acts::AtlasBetheHeitlerApprox<6, 5> Acts::makeDefaultBetheHeitlerApprox() { +Acts::AtlasBetheHeitlerApprox<6, 5> Acts::makeDefaultBetheHeitlerApprox( + bool clampToRange) { // Tracking/TrkFitter/TrkGaussianSumFilterUtils/Data/BetheHeitler_cdf_nC6_O5.par // clang-format off constexpr static AtlasBetheHeitlerApprox<6, 5>::Data cdf_cmps6_order5_data = {{ @@ -51,6 +52,7 @@ Acts::AtlasBetheHeitlerApprox<6, 5> Acts::makeDefaultBetheHeitlerApprox() { }}; // clang-format on - return AtlasBetheHeitlerApprox<6, 5>( - cdf_cmps6_order5_data, cdf_cmps6_order5_data, true, true, 0.2, 0.2); + return AtlasBetheHeitlerApprox<6, 5>(cdf_cmps6_order5_data, + cdf_cmps6_order5_data, true, true, 0.2, + 0.2, clampToRange); } diff --git a/Core/src/TrackFitting/GainMatrixSmoother.cpp b/Core/src/TrackFitting/GainMatrixSmoother.cpp index 19d54bdcf4b..711540ff0bf 100644 --- a/Core/src/TrackFitting/GainMatrixSmoother.cpp +++ b/Core/src/TrackFitting/GainMatrixSmoother.cpp @@ -9,6 +9,7 @@ #include "Acts/TrackFitting/GainMatrixSmoother.hpp" #include "Acts/Definitions/TrackParametrization.hpp" +#include "Acts/EventData/TrackParameterHelpers.hpp" #include "Acts/EventData/detail/CovarianceHelper.hpp" #include "Acts/TrackFitting/KalmanFitterError.hpp" @@ -57,7 +58,10 @@ Result GainMatrixSmoother::calculate( "Prev. predicted parameters: " << predicted(prev_ts).transpose()); // Calculate the smoothed parameters - smoothed(ts) = filtered(ts) + G * (smoothed(prev_ts) - predicted(prev_ts)); + smoothed(ts) = filtered(ts) + G * subtractBoundParameters(smoothed(prev_ts), + predicted(prev_ts)); + // Normalize phi and theta + smoothed(ts) = normalizeBoundParameters(smoothed(ts)); ACTS_VERBOSE("Smoothed parameters are: " << smoothed(ts).transpose()); ACTS_VERBOSE("Calculate smoothed covariance:"); diff --git a/Core/src/TrackFitting/MbfSmoother.cpp b/Core/src/TrackFitting/MbfSmoother.cpp index 8ed74106bfb..2614834aadb 100644 --- a/Core/src/TrackFitting/MbfSmoother.cpp +++ b/Core/src/TrackFitting/MbfSmoother.cpp @@ -8,6 +8,8 @@ #include "Acts/TrackFitting/MbfSmoother.hpp" +#include "Acts/EventData/TrackParameterHelpers.hpp" + namespace Acts { void MbfSmoother::calculateSmoothed(InternalTrackState& ts, @@ -17,6 +19,8 @@ void MbfSmoother::calculateSmoothed(InternalTrackState& ts, bigLambdaHat * ts.filteredCovariance; ts.smoothed = ts.filtered - ts.filteredCovariance * smallLambdaHat; + // Normalize phi and theta + ts.smoothed = normalizeBoundParameters(ts.smoothed); } void MbfSmoother::visitNonMeasurement(const InternalTrackState& ts, diff --git a/Core/src/Vertexing/AdaptiveMultiVertexFinder.cpp b/Core/src/Vertexing/AdaptiveMultiVertexFinder.cpp index 34d20e32e0a..dddd49e715a 100644 --- a/Core/src/Vertexing/AdaptiveMultiVertexFinder.cpp +++ b/Core/src/Vertexing/AdaptiveMultiVertexFinder.cpp @@ -589,10 +589,10 @@ Result AdaptiveMultiVertexFinder::deleteLastVertex( return removeResult.error(); } - for (auto& entry : fitterState.tracksAtVerticesMap) { + for (auto& [key, value] : fitterState.tracksAtVerticesMap) { // Delete all linearized tracks for current (bad) vertex - if (entry.first.second == &vtx) { - entry.second.isLinearized = false; + if (key.second == &vtx) { + value.isLinearized = false; } } diff --git a/Core/src/Vertexing/ImpactPointEstimator.cpp b/Core/src/Vertexing/ImpactPointEstimator.cpp index 53e19277c85..3caac09b57b 100644 --- a/Core/src/Vertexing/ImpactPointEstimator.cpp +++ b/Core/src/Vertexing/ImpactPointEstimator.cpp @@ -9,10 +9,10 @@ #include "Acts/Vertexing/ImpactPointEstimator.hpp" #include "Acts/Definitions/Algebra.hpp" -#include "Acts/Propagator/Propagator.hpp" #include "Acts/Propagator/PropagatorOptions.hpp" #include "Acts/Surfaces/PerigeeSurface.hpp" #include "Acts/Surfaces/PlaneSurface.hpp" +#include "Acts/Utilities/AngleHelpers.hpp" #include "Acts/Utilities/MathHelpers.hpp" #include "Acts/Vertexing/VertexingError.hpp" @@ -526,7 +526,7 @@ Result> ImpactPointEstimator::getLifetimeSignOfTrack( const double theta = params[BoundIndices::eBoundTheta]; double vs = std::sin(std::atan2(direction[1], direction[0]) - phi) * d0; - double eta = -std::log(std::tan(theta / 2.)); + double eta = AngleHelpers::etaFromTheta(theta); double dir_eta = VectorHelpers::eta(direction); double zs = (dir_eta - eta) * z0; diff --git a/Examples/Algorithms/Alignment/src/AlignmentAlgorithmFunction.cpp b/Examples/Algorithms/Alignment/src/AlignmentAlgorithmFunction.cpp index d36a6df9b95..de6780d817b 100644 --- a/Examples/Algorithms/Alignment/src/AlignmentAlgorithmFunction.cpp +++ b/Examples/Algorithms/Alignment/src/AlignmentAlgorithmFunction.cpp @@ -31,7 +31,7 @@ struct AlignmentFunctionImpl : public ActsExamples::AlignmentAlgorithm::AlignmentFunction { Alignment align; - AlignmentFunctionImpl(Alignment&& a) : align(std::move(a)) {} + explicit AlignmentFunctionImpl(Alignment&& a) : align(std::move(a)) {} ActsExamples::AlignmentAlgorithm::AlignmentResult operator()( const std::vector>& diff --git a/Examples/Algorithms/Digitization/include/ActsExamples/Digitization/DigitizationConfig.hpp b/Examples/Algorithms/Digitization/include/ActsExamples/Digitization/DigitizationConfig.hpp index 3521d0bef7d..6a933f50075 100644 --- a/Examples/Algorithms/Digitization/include/ActsExamples/Digitization/DigitizationConfig.hpp +++ b/Examples/Algorithms/Digitization/include/ActsExamples/Digitization/DigitizationConfig.hpp @@ -130,7 +130,7 @@ class DigitizationConfig { bool doMerge, double mergeNsigma, bool mergeCommonCorner, Acts::GeometryHierarchyMap &&digiCfgs); - DigitizationConfig( + explicit DigitizationConfig( Acts::GeometryHierarchyMap &&digiCfgs); /// Input collection of simulated hits. diff --git a/Examples/Algorithms/Digitization/src/MeasurementCreation.cpp b/Examples/Algorithms/Digitization/src/MeasurementCreation.cpp index 9d5169ca6c9..066901cc0cf 100644 --- a/Examples/Algorithms/Digitization/src/MeasurementCreation.cpp +++ b/Examples/Algorithms/Digitization/src/MeasurementCreation.cpp @@ -30,6 +30,7 @@ ActsExamples::VariableBoundMeasurementProxy ActsExamples::createMeasurement( return Acts::visit_measurement( dParams.indices.size(), [&](auto dim) -> VariableBoundMeasurementProxy { auto [indices, par, cov] = measurementConstituents(dParams); - return container.emplaceMeasurement(geometryId, indices, par, cov); + return VariableBoundMeasurementProxy{ + container.emplaceMeasurement(geometryId, indices, par, cov)}; }); } diff --git a/Examples/Algorithms/Geant4/include/ActsExamples/Geant4/MaterialPhysicsList.hpp b/Examples/Algorithms/Geant4/include/ActsExamples/Geant4/MaterialPhysicsList.hpp index b53567b77a0..9cfb45d0453 100644 --- a/Examples/Algorithms/Geant4/include/ActsExamples/Geant4/MaterialPhysicsList.hpp +++ b/Examples/Algorithms/Geant4/include/ActsExamples/Geant4/MaterialPhysicsList.hpp @@ -29,9 +29,9 @@ class MaterialPhysicsList final : public G4VUserPhysicsList { /// /// @param cfg the configuration struct for this Stepping action /// @param logger is an Acts::Logger for unique logging - MaterialPhysicsList(std::unique_ptr logger = - Acts::getDefaultLogger("MaterialPhysicsList", - Acts::Logging::INFO)); + explicit MaterialPhysicsList(std::unique_ptr logger = + Acts::getDefaultLogger("MaterialPhysicsList", + Acts::Logging::INFO)); ~MaterialPhysicsList() override = default; /// @brief Interface particle construction method diff --git a/Examples/Algorithms/Geant4/include/ActsExamples/Geant4/PhysicsListFactory.hpp b/Examples/Algorithms/Geant4/include/ActsExamples/Geant4/PhysicsListFactory.hpp index d3c4b9f33c2..6bbc39b4f04 100644 --- a/Examples/Algorithms/Geant4/include/ActsExamples/Geant4/PhysicsListFactory.hpp +++ b/Examples/Algorithms/Geant4/include/ActsExamples/Geant4/PhysicsListFactory.hpp @@ -28,7 +28,7 @@ class PhysicsListFactoryFunction final : public PhysicsListFactory { public: using Function = std::function()>; - PhysicsListFactoryFunction(Function function); + explicit PhysicsListFactoryFunction(Function function); std::unique_ptr factorize() const final; diff --git a/Examples/Algorithms/Geant4/include/ActsExamples/Geant4/SteppingActionList.hpp b/Examples/Algorithms/Geant4/include/ActsExamples/Geant4/SteppingActionList.hpp index 569914007d8..b4a6d7e5d68 100644 --- a/Examples/Algorithms/Geant4/include/ActsExamples/Geant4/SteppingActionList.hpp +++ b/Examples/Algorithms/Geant4/include/ActsExamples/Geant4/SteppingActionList.hpp @@ -28,7 +28,7 @@ class SteppingActionList : public G4UserSteppingAction { std::vector> actions; }; - SteppingActionList(const Config &cfg) : m_cfg(cfg) {} + explicit SteppingActionList(const Config &cfg) : m_cfg(cfg) {} void UserSteppingAction(const G4Step *step) override { for (const auto &action : m_cfg.actions) { diff --git a/Examples/Algorithms/Geant4HepMC/src/EventAction.hpp b/Examples/Algorithms/Geant4HepMC/src/EventAction.hpp index 5c078e21cf8..dcf82b9543f 100644 --- a/Examples/Algorithms/Geant4HepMC/src/EventAction.hpp +++ b/Examples/Algorithms/Geant4HepMC/src/EventAction.hpp @@ -28,7 +28,7 @@ class EventAction final : public G4UserEventAction { static EventAction* instance(); /// Construct the action and ensure singleton usage. - EventAction(std::vector processFilter); + explicit EventAction(std::vector processFilter); ~EventAction() override; /// Interface method for begin of the event diff --git a/Examples/Algorithms/Geant4HepMC/src/SteppingAction.hpp b/Examples/Algorithms/Geant4HepMC/src/SteppingAction.hpp index 51144f3e83c..c19ed0a8560 100644 --- a/Examples/Algorithms/Geant4HepMC/src/SteppingAction.hpp +++ b/Examples/Algorithms/Geant4HepMC/src/SteppingAction.hpp @@ -20,7 +20,7 @@ namespace ActsExamples::Geant4::HepMC3 { /// Collects the particles history. class SteppingAction : public G4UserSteppingAction { public: - SteppingAction(std::vector eventRejectionProcess); + explicit SteppingAction(std::vector eventRejectionProcess); ~SteppingAction() override; /// Static access method to the instance diff --git a/Examples/Algorithms/Generators/ActsExamples/Generators/MultiplicityGenerators.hpp b/Examples/Algorithms/Generators/ActsExamples/Generators/MultiplicityGenerators.hpp index 42290a5e471..32c6d708235 100644 --- a/Examples/Algorithms/Generators/ActsExamples/Generators/MultiplicityGenerators.hpp +++ b/Examples/Algorithms/Generators/ActsExamples/Generators/MultiplicityGenerators.hpp @@ -19,7 +19,7 @@ struct FixedMultiplicityGenerator : public EventGenerator::MultiplicityGenerator { std::size_t n = 1; - FixedMultiplicityGenerator(std::size_t _n) : n{_n} {} + explicit FixedMultiplicityGenerator(std::size_t _n) : n{_n} {} FixedMultiplicityGenerator() = default; std::size_t operator()(RandomEngine& /*rng*/) const override { return n; } @@ -28,7 +28,7 @@ struct FixedMultiplicityGenerator struct PoissonMultiplicityGenerator : public EventGenerator::MultiplicityGenerator { double mean = 1; - PoissonMultiplicityGenerator(double _mean) : mean{_mean} {} + explicit PoissonMultiplicityGenerator(double _mean) : mean{_mean} {} PoissonMultiplicityGenerator() = default; std::size_t operator()(RandomEngine& rng) const override { diff --git a/Examples/Algorithms/Generators/ActsExamples/Generators/ParametricParticleGenerator.cpp b/Examples/Algorithms/Generators/ActsExamples/Generators/ParametricParticleGenerator.cpp index 104c8c0f04d..dcc7ac573f3 100644 --- a/Examples/Algorithms/Generators/ActsExamples/Generators/ParametricParticleGenerator.cpp +++ b/Examples/Algorithms/Generators/ActsExamples/Generators/ParametricParticleGenerator.cpp @@ -11,7 +11,7 @@ #include "Acts/Definitions/Algebra.hpp" #include "Acts/Definitions/Common.hpp" #include "Acts/Definitions/ParticleData.hpp" -#include "ActsExamples/EventData/SimHit.hpp" +#include "Acts/Utilities/AngleHelpers.hpp" #include "ActsFatras/EventData/Barcode.hpp" #include "ActsFatras/EventData/Particle.hpp" @@ -35,8 +35,8 @@ ParametricParticleGenerator::ParametricParticleGenerator(const Config& cfg) m_cosThetaMax(std::nextafter(std::cos(m_cfg.thetaMax), std::numeric_limits::max())), // in case we force uniform eta generation - m_etaMin(-std::log(std::tan(0.5 * m_cfg.thetaMin))), - m_etaMax(-std::log(std::tan(0.5 * m_cfg.thetaMax))) {} + m_etaMin(Acts::AngleHelpers::etaFromTheta(m_cfg.thetaMin)), + m_etaMax(Acts::AngleHelpers::etaFromTheta(m_cfg.thetaMax)) {} std::pair ParametricParticleGenerator::operator()(RandomEngine& rng) { @@ -64,8 +64,8 @@ ParametricParticleGenerator::operator()(RandomEngine& rng) { SimParticleContainer::sequence_type particles; // create the primary vertex - auto& primaryVertex = - vertices.emplace_back(0, SimVertex::Vector4(0., 0., 0., 0.)); + auto& primaryVertex = vertices.emplace_back( + SimVertexBarcode{0}, SimVertex::Vector4(0., 0., 0., 0.)); // counter will be reused as barcode particle number which must be non-zero. for (std::size_t ip = 1; ip <= m_cfg.numParticles; ++ip) { @@ -89,7 +89,7 @@ ParametricParticleGenerator::operator()(RandomEngine& rng) { sinTheta = std::sqrt(1 - cosTheta * cosTheta); } else { const double eta = etaDist(rng); - const double theta = 2 * std::atan(std::exp(-eta)); + const double theta = Acts::AngleHelpers::thetaFromEta(eta); sinTheta = std::sin(theta); cosTheta = std::cos(theta); } diff --git a/Examples/Algorithms/Generators/ActsExamples/Generators/ParametricParticleGenerator.hpp b/Examples/Algorithms/Generators/ActsExamples/Generators/ParametricParticleGenerator.hpp index 3bb8ff9d836..a7d9bfe3e08 100644 --- a/Examples/Algorithms/Generators/ActsExamples/Generators/ParametricParticleGenerator.hpp +++ b/Examples/Algorithms/Generators/ActsExamples/Generators/ParametricParticleGenerator.hpp @@ -64,7 +64,7 @@ class ParametricParticleGenerator : public EventGenerator::ParticlesGenerator { std::optional mass; }; - ParametricParticleGenerator(const Config& cfg); + explicit ParametricParticleGenerator(const Config& cfg); /// Generate a single primary vertex with the given number of particles. std::pair operator()( diff --git a/Examples/Algorithms/GeneratorsPythia8/ActsExamples/Generators/Pythia8ProcessGenerator.cpp b/Examples/Algorithms/GeneratorsPythia8/ActsExamples/Generators/Pythia8ProcessGenerator.cpp index e19e785ac5c..ae7c2b85403 100644 --- a/Examples/Algorithms/GeneratorsPythia8/ActsExamples/Generators/Pythia8ProcessGenerator.cpp +++ b/Examples/Algorithms/GeneratorsPythia8/ActsExamples/Generators/Pythia8ProcessGenerator.cpp @@ -121,7 +121,8 @@ Pythia8Generator::operator()(RandomEngine& rng) { } // create the primary vertex - vertices.emplace_back(0, SimVertex::Vector4(0., 0., 0., 0.)); + vertices.emplace_back(SimVertexBarcode{0}, + SimVertex::Vector4(0., 0., 0., 0.)); // convert generated final state particles into internal format for (int ip = 0; ip < m_pythia8->event.size(); ++ip) { @@ -166,7 +167,8 @@ Pythia8Generator::operator()(RandomEngine& rng) { } else { // no matching secondary vertex exists -> create new one particleId.setVertexSecondary(vertices.size()); - auto& vertex = vertices.emplace_back(particleId.vertexId(), pos4); + auto& vertex = vertices.emplace_back( + static_cast(particleId.vertexId()), pos4); vertex.outgoing.insert(particleId); ACTS_VERBOSE("created new secondary vertex " << pos4.transpose()); } diff --git a/Examples/Algorithms/Propagation/include/ActsExamples/Propagation/PropagatorInterface.hpp b/Examples/Algorithms/Propagation/include/ActsExamples/Propagation/PropagatorInterface.hpp index c063a2a1a48..2aa3b2292ac 100644 --- a/Examples/Algorithms/Propagation/include/ActsExamples/Propagation/PropagatorInterface.hpp +++ b/Examples/Algorithms/Propagation/include/ActsExamples/Propagation/PropagatorInterface.hpp @@ -50,7 +50,7 @@ class PropagatorInterface { template class ConcretePropagator : public PropagatorInterface { public: - ConcretePropagator(propagator_t propagator) + explicit ConcretePropagator(propagator_t propagator) : m_propagator{std::move(propagator)} {} Acts::Result execute( diff --git a/Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/TrackFindingAlgorithm.hpp b/Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/TrackFindingAlgorithm.hpp index deb15750a5f..c56e9508c9b 100644 --- a/Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/TrackFindingAlgorithm.hpp +++ b/Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/TrackFindingAlgorithm.hpp @@ -179,6 +179,7 @@ class TrackFindingAlgorithm final : public IAlgorithm { mutable std::atomic m_nFoundTracks{0}; mutable std::atomic m_nSelectedTracks{0}; mutable std::atomic m_nStoppedBranches{0}; + mutable std::atomic m_nSkippedSecondPass{0}; mutable tbb::combinable m_memoryStatistics{[]() { diff --git a/Examples/Algorithms/TrackFinding/src/TrackFindingAlgorithm.cpp b/Examples/Algorithms/TrackFinding/src/TrackFindingAlgorithm.cpp index 2a36701dc3b..b1ef900c5b9 100644 --- a/Examples/Algorithms/TrackFinding/src/TrackFindingAlgorithm.cpp +++ b/Examples/Algorithms/TrackFinding/src/TrackFindingAlgorithm.cpp @@ -203,7 +203,7 @@ class BranchStopper { } else if constexpr (std::is_same_v< T, Acts::TrackSelector::EtaBinnedConfig>) { double theta = trackState.parameters()[Acts::eBoundTheta]; - double eta = -std::log(std::tan(0.5 * theta)); + double eta = Acts::AngleHelpers::etaFromTheta(theta); return config.hasCuts(eta) ? &config.getCuts(eta) : nullptr; } }, @@ -532,6 +532,15 @@ ProcessCode TrackFindingAlgorithm::execute(const AlgorithmContext& ctx) const { Acts::BoundTrackParameters secondInitialParameters = trackCandidate.createParametersFromState(firstMeasurement); + if (!secondInitialParameters.referenceSurface().insideBounds( + secondInitialParameters.localPosition())) { + m_nSkippedSecondPass++; + ACTS_DEBUG( + "Smoothing of first pass fit produced out-of-bounds parameters " + "relative to the surface. Skipping second pass."); + continue; + } + auto secondRootBranch = tracksTemp.makeTrack(); secondRootBranch.copyFrom(trackCandidate, false); auto secondResult = @@ -681,6 +690,7 @@ ProcessCode TrackFindingAlgorithm::finalize() { ACTS_INFO("- found tracks: " << m_nFoundTracks); ACTS_INFO("- selected tracks: " << m_nSelectedTracks); ACTS_INFO("- stopped branches: " << m_nStoppedBranches); + ACTS_INFO("- skipped second pass: " << m_nSkippedSecondPass); auto memoryStatistics = m_memoryStatistics.combine([](const auto& a, const auto& b) { diff --git a/Examples/Algorithms/TrackFinding/src/TrackFindingAlgorithmFunction.cpp b/Examples/Algorithms/TrackFinding/src/TrackFindingAlgorithmFunction.cpp index 65e0cf41970..e9f6ae315f3 100644 --- a/Examples/Algorithms/TrackFinding/src/TrackFindingAlgorithmFunction.cpp +++ b/Examples/Algorithms/TrackFinding/src/TrackFindingAlgorithmFunction.cpp @@ -35,7 +35,7 @@ struct TrackFinderFunctionImpl : public ActsExamples::TrackFindingAlgorithm::TrackFinderFunction { CKF trackFinder; - TrackFinderFunctionImpl(CKF&& f) : trackFinder(std::move(f)) {} + explicit TrackFinderFunctionImpl(CKF&& f) : trackFinder(std::move(f)) {} ActsExamples::TrackFindingAlgorithm::TrackFinderResult operator()( const ActsExamples::TrackParameters& initialParameters, diff --git a/Examples/Algorithms/TrackFinding/src/TrackParamsEstimationAlgorithm.cpp b/Examples/Algorithms/TrackFinding/src/TrackParamsEstimationAlgorithm.cpp index a54b10d2e7d..c8a30c7147d 100644 --- a/Examples/Algorithms/TrackFinding/src/TrackParamsEstimationAlgorithm.cpp +++ b/Examples/Algorithms/TrackFinding/src/TrackParamsEstimationAlgorithm.cpp @@ -32,48 +32,6 @@ namespace ActsExamples { -namespace { - -Acts::BoundSquareMatrix makeInitialCovariance( - const TrackParamsEstimationAlgorithm::Config& config, - const Acts::BoundVector& params, const SimSpacePoint& sp) { - Acts::BoundSquareMatrix result = Acts::BoundSquareMatrix::Zero(); - - for (std::size_t i = Acts::eBoundLoc0; i < Acts::eBoundSize; ++i) { - double sigma = config.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 = result(Acts::eBoundTheta, Acts::eBoundTheta); - - // 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()) { - variance *= config.noTimeVarInflation; - } - - // Inflate the initial covariance - variance *= config.initialVarInflation[i]; - - result(i, i) = variance; - } - - return result; -} - -} // namespace - TrackParamsEstimationAlgorithm::TrackParamsEstimationAlgorithm( TrackParamsEstimationAlgorithm::Config cfg, Acts::Logging::Level lvl) : IAlgorithm("TrackParamsEstimationAlgorithm", lvl), m_cfg(std::move(cfg)) { @@ -166,8 +124,15 @@ ProcessCode TrackParamsEstimationAlgorithm::execute( const auto& params = optParams.value(); - Acts::BoundSquareMatrix cov = - makeInitialCovariance(m_cfg, params, *bottomSP); + Acts::EstimateTrackParamCovarianceConfig config{ + .initialSigmas = + Eigen::Map{m_cfg.initialSigmas.data()}, + .initialSigmaPtRel = m_cfg.initialSigmaPtRel, + .initialVarInflation = Eigen::Map{ + m_cfg.initialVarInflation.data()}}; + + Acts::BoundSquareMatrix cov = Acts::estimateTrackParamCovariance( + config, params, bottomSP->t().has_value()); trackParameters.emplace_back(surface->getSharedPtr(), params, cov, m_cfg.particleHypothesis); diff --git a/Examples/Algorithms/TrackFindingExaTrkX/src/TrackFindingAlgorithmExaTrkX.cpp b/Examples/Algorithms/TrackFindingExaTrkX/src/TrackFindingAlgorithmExaTrkX.cpp index 05fe35a6ea0..df4b8998540 100644 --- a/Examples/Algorithms/TrackFindingExaTrkX/src/TrackFindingAlgorithmExaTrkX.cpp +++ b/Examples/Algorithms/TrackFindingExaTrkX/src/TrackFindingAlgorithmExaTrkX.cpp @@ -40,14 +40,6 @@ struct LoopHook : public Acts::ExaTrkXHook { } }; -// TODO do we have these function in the repo somewhere? -float theta(float r, float z) { - return std::atan2(r, z); -} -float eta(float r, float z) { - return -std::log(std::tan(0.5 * theta(r, z))); -} - } // namespace ActsExamples::TrackFindingAlgorithmExaTrkX::TrackFindingAlgorithmExaTrkX( @@ -187,7 +179,7 @@ ActsExamples::ProcessCode ActsExamples::TrackFindingAlgorithmExaTrkX::execute( break; case NF::eZ: f[ift] = sp.z(); break; case NF::eX: f[ift] = sp.x(); break; case NF::eY: f[ift] = sp.y(); - break; case NF::eEta: f[ift] = eta(std::hypot(sp.x(), sp.y()), sp.z()); + break; case NF::eEta: f[ift] = Acts::VectorHelpers::eta(Acts::Vector3{sp.x(), sp.y(), sp.z()}); break; case NF::eClusterX: f[ift] = cl1->sizeLoc0; break; case NF::eClusterY: f[ift] = cl1->sizeLoc1; break; case NF::eCellSum: f[ift] = cl1->sumActivations(); @@ -198,8 +190,8 @@ ActsExamples::ProcessCode ActsExamples::TrackFindingAlgorithmExaTrkX::execute( break; case NF::eCluster2Phi: f[ift] = std::atan2(cl2->globalPosition[Acts::ePos1], cl2->globalPosition[Acts::ePos0]); break; case NF::eCluster1Z: f[ift] = cl1->globalPosition[Acts::ePos2]; break; case NF::eCluster2Z: f[ift] = cl2->globalPosition[Acts::ePos2]; - break; case NF::eCluster1Eta: f[ift] = eta(std::hypot(cl1->globalPosition[Acts::ePos0], cl1->globalPosition[Acts::ePos1]), cl1->globalPosition[Acts::ePos2]); - break; case NF::eCluster2Eta: f[ift] = eta(std::hypot(cl2->globalPosition[Acts::ePos0], cl2->globalPosition[Acts::ePos1]), cl2->globalPosition[Acts::ePos2]); + break; case NF::eCluster1Eta: f[ift] = Acts::VectorHelpers::eta(Acts::Vector3{cl1->globalPosition[Acts::ePos0], cl1->globalPosition[Acts::ePos1], cl1->globalPosition[Acts::ePos2]}); + break; case NF::eCluster2Eta: f[ift] = Acts::VectorHelpers::eta(Acts::Vector3{cl2->globalPosition[Acts::ePos0], cl2->globalPosition[Acts::ePos1], cl2->globalPosition[Acts::ePos2]}); } // clang-format on diff --git a/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.cpp b/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.cpp index d9248358160..5fa3ee0e4b2 100644 --- a/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.cpp +++ b/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.cpp @@ -29,9 +29,16 @@ ActsExamples::ParticleSelector::ParticleSelector(const Config& config, if (m_cfg.outputParticles.empty()) { throw std::invalid_argument("Missing output particles collection"); } + if (!m_cfg.outputParticlesFinal.empty() && + m_cfg.inputParticlesFinal.empty()) { + throw std::invalid_argument( + "Output final particles collection requires input final particles"); + } m_inputParticles.initialize(m_cfg.inputParticles); + m_inputParticlesFinal.maybeInitialize(m_cfg.inputParticlesFinal); m_outputParticles.initialize(m_cfg.outputParticles); + m_outputParticlesFinal.maybeInitialize(m_cfg.outputParticlesFinal); ACTS_DEBUG("selection particle rho [" << m_cfg.rhoMin << "," << m_cfg.rhoMax << ")"); @@ -52,29 +59,15 @@ ActsExamples::ParticleSelector::ParticleSelector(const Config& config, ACTS_DEBUG("remove charged particles " << m_cfg.removeCharged); ACTS_DEBUG("remove neutral particles " << m_cfg.removeNeutral); ACTS_DEBUG("remove secondary particles " << m_cfg.removeSecondaries); - - // We only initialize this if we actually select on this - if (m_cfg.measurementsMin > 0 || - m_cfg.measurementsMax < std::numeric_limits::max()) { - m_inputMap.initialize(m_cfg.inputMeasurementParticlesMap); - ACTS_DEBUG("selection particle number of measurements [" - << m_cfg.measurementsMin << "," << m_cfg.measurementsMax << ")"); - } } ActsExamples::ProcessCode ActsExamples::ParticleSelector::execute( const AlgorithmContext& ctx) const { - using ParticlesMeasurmentMap = - boost::container::flat_multimap; - // prepare input/ output types - const auto& inputParticles = m_inputParticles(ctx); - - // Make global particles measurement map if necessary - std::optional particlesMeasMap; - if (m_inputMap.isInitialized()) { - particlesMeasMap = invertIndexMultimap(m_inputMap(ctx)); - } + const SimParticleContainer& inputParticles = m_inputParticles(ctx); + const SimParticleContainer& inputParticlesFinal = + (m_inputParticlesFinal.isInitialized()) ? m_inputParticlesFinal(ctx) + : inputParticles; std::size_t nInvalidCharge = 0; std::size_t nInvalidMeasurementCount = 0; @@ -96,17 +89,14 @@ ActsExamples::ProcessCode ActsExamples::ParticleSelector::execute( nInvalidCharge += static_cast(!validCharge); - // default valid measurement count to true and only change if we have loaded - // the measurement particles map bool validMeasurementCount = true; - if (particlesMeasMap) { - auto [b, e] = particlesMeasMap->equal_range(p.particleId()); + if (auto finalParticleIt = inputParticlesFinal.find(p.particleId()); + finalParticleIt != inputParticlesFinal.end()) { validMeasurementCount = - within(static_cast(std::distance(b, e)), - m_cfg.measurementsMin, m_cfg.measurementsMax); - - ACTS_VERBOSE("Found " << std::distance(b, e) << " measurements for " - << p.particleId()); + within(finalParticleIt->numberOfHits(), m_cfg.measurementsMin, + m_cfg.measurementsMax); + } else { + ACTS_WARNING("No final particle found for " << p.particleId()); } nInvalidMeasurementCount += @@ -136,14 +126,30 @@ ActsExamples::ProcessCode ActsExamples::ParticleSelector::execute( SimParticleContainer outputParticles; outputParticles.reserve(inputParticles.size()); + SimParticleContainer outputParticlesFinal; + if (m_outputParticlesFinal.isInitialized()) { + outputParticlesFinal.reserve(inputParticles.size()); + } + // copy selected particles for (const auto& inputParticle : inputParticles) { - if (isValidParticle(inputParticle)) { - // the input parameters should already be - outputParticles.insert(outputParticles.end(), inputParticle); + if (!isValidParticle(inputParticle)) { + continue; + } + + outputParticles.insert(outputParticles.end(), inputParticle); + + if (m_outputParticlesFinal.isInitialized()) { + if (auto particleFinalIt = + inputParticlesFinal.find(inputParticle.particleId()); + particleFinalIt != inputParticlesFinal.end()) { + outputParticlesFinal.insert(outputParticlesFinal.end(), + *particleFinalIt); + } } } outputParticles.shrink_to_fit(); + outputParticlesFinal.shrink_to_fit(); ACTS_DEBUG("event " << ctx.eventNumber << " selected " << outputParticles.size() << " from " @@ -153,5 +159,9 @@ ActsExamples::ProcessCode ActsExamples::ParticleSelector::execute( << nInvalidMeasurementCount); m_outputParticles(ctx, std::move(outputParticles)); + if (m_outputParticlesFinal.isInitialized()) { + m_outputParticlesFinal(ctx, std::move(outputParticlesFinal)); + } + return ProcessCode::SUCCESS; } diff --git a/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.hpp b/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.hpp index d6c8440fdc7..de05bf621ca 100644 --- a/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.hpp +++ b/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.hpp @@ -29,10 +29,14 @@ class ParticleSelector final : public IAlgorithm { struct Config { /// The input particles collection. std::string inputParticles; - /// Input measurement particles map (Optional) - std::string inputMeasurementParticlesMap; + /// Optional. The input final state particles collection. + /// If provided, this will be used to access the number of measurements. + std::string inputParticlesFinal; /// The output particles collection. std::string outputParticles; + /// Optional. The output final state particles collection. + std::string outputParticlesFinal; + // Minimum/maximum distance from the origin in the transverse plane. double rhoMin = 0; double rhoMax = std::numeric_limits::infinity(); @@ -79,11 +83,13 @@ class ParticleSelector final : public IAlgorithm { Config m_cfg; ReadDataHandle m_inputParticles{this, "InputParticles"}; - ReadDataHandle> m_inputMap{ - this, "InputMeasurementParticlesMap"}; + ReadDataHandle m_inputParticlesFinal{ + this, "InputParticlesFinal"}; WriteDataHandle m_outputParticles{this, "OutputParticles"}; + WriteDataHandle m_outputParticlesFinal{ + this, "OutputParticlesFinal"}; }; } // namespace ActsExamples diff --git a/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSmearing.cpp b/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSmearing.cpp index 937a5bc1863..cfc62ab9da9 100644 --- a/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSmearing.cpp +++ b/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSmearing.cpp @@ -11,6 +11,7 @@ #include "Acts/Definitions/Algebra.hpp" #include "Acts/Definitions/TrackParametrization.hpp" #include "Acts/EventData/ParticleHypothesis.hpp" +#include "Acts/Seeding/EstimateTrackParamsFromSeed.hpp" #include "Acts/Surfaces/PerigeeSurface.hpp" #include "Acts/Surfaces/Surface.hpp" #include "Acts/Utilities/Helpers.hpp" @@ -128,31 +129,16 @@ ActsExamples::ProcessCode ActsExamples::ParticleSmearing::execute( Acts::BoundSquareMatrix cov = Acts::BoundSquareMatrix::Zero(); if (m_cfg.initialSigmas) { // use the initial sigmas if set - for (std::size_t i = Acts::eBoundLoc0; i < Acts::eBoundSize; ++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); + Acts::EstimateTrackParamCovarianceConfig config{ + .initialSigmas = + Eigen::Map{ + m_cfg.initialSigmas->data()}, + .initialSigmaPtRel = m_cfg.initialSigmaPtRel, + .initialVarInflation = Eigen::Map{ + m_cfg.initialVarInflation.data()}}; - // 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; - } + cov = Acts::estimateTrackParamCovariance(config, params, false); } else { // otherwise use the smearing sigmas diff --git a/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/TrackParameterSelector.cpp b/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/TrackParameterSelector.cpp index 13b0481e178..18b9cf9090c 100644 --- a/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/TrackParameterSelector.cpp +++ b/Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/TrackParameterSelector.cpp @@ -9,6 +9,7 @@ #include "ActsExamples/TruthTracking/TrackParameterSelector.hpp" #include "Acts/Definitions/TrackParametrization.hpp" +#include "Acts/Utilities/AngleHelpers.hpp" #include "ActsExamples/EventData/Track.hpp" #include "ActsExamples/Framework/AlgorithmContext.hpp" @@ -41,7 +42,7 @@ ActsExamples::ProcessCode ActsExamples::TrackParameterSelector::execute( }; auto isValidTrack = [&](const auto& trk) { const auto theta = trk.template get(); - const auto eta = -std::log(std::tan(theta / 2)); + const auto eta = Acts::AngleHelpers::etaFromTheta(theta); // define charge selection return within(trk.transverseMomentum(), m_cfg.ptMin, m_cfg.ptMax) && within(std::abs(eta), m_cfg.absEtaMin, m_cfg.absEtaMax) && diff --git a/Examples/Algorithms/Vertexing/src/AdaptiveMultiVertexFinderAlgorithm.cpp b/Examples/Algorithms/Vertexing/src/AdaptiveMultiVertexFinderAlgorithm.cpp index 9ef72913e37..5330e55c76c 100644 --- a/Examples/Algorithms/Vertexing/src/AdaptiveMultiVertexFinderAlgorithm.cpp +++ b/Examples/Algorithms/Vertexing/src/AdaptiveMultiVertexFinderAlgorithm.cpp @@ -249,7 +249,8 @@ ProcessCode AdaptiveMultiVertexFinderAlgorithm::execute( // Count the number of particles associated with each vertex std::size_t particleCount = 0; for (const auto& particle : truthParticles) { - if (particle.particleId().vertexId() == truthVertex.vertexId()) { + if (static_cast(particle.particleId().vertexId()) == + truthVertex.vertexId()) { ++particleCount; } } diff --git a/Examples/Detectors/DD4hepDetector/include/ActsExamples/DD4hepDetector/DD4hepDetector.hpp b/Examples/Detectors/DD4hepDetector/include/ActsExamples/DD4hepDetector/DD4hepDetector.hpp index fec8cfdd052..015b511825f 100644 --- a/Examples/Detectors/DD4hepDetector/include/ActsExamples/DD4hepDetector/DD4hepDetector.hpp +++ b/Examples/Detectors/DD4hepDetector/include/ActsExamples/DD4hepDetector/DD4hepDetector.hpp @@ -52,7 +52,8 @@ struct DD4hepDetector { DD4hepDetector() = default; /// @brief Constructor from geometry service /// @param _geometryService the geometry service - DD4hepDetector(std::shared_ptr _geometryService); + explicit DD4hepDetector( + std::shared_ptr _geometryService); /// @brief Default destructor ~DD4hepDetector() = default; diff --git a/Examples/Detectors/DD4hepDetector/include/ActsExamples/DD4hepDetector/DD4hepGeometryService.hpp b/Examples/Detectors/DD4hepDetector/include/ActsExamples/DD4hepDetector/DD4hepGeometryService.hpp index 6fb17141814..edbb720825c 100644 --- a/Examples/Detectors/DD4hepDetector/include/ActsExamples/DD4hepDetector/DD4hepGeometryService.hpp +++ b/Examples/Detectors/DD4hepDetector/include/ActsExamples/DD4hepDetector/DD4hepGeometryService.hpp @@ -52,7 +52,7 @@ class DD4hepGeometryService { /// Log level for the geometry service. Acts::Logging::Level logLevel = Acts::Logging::Level::INFO; /// Log level for DD4hep itself - Acts::Logging::Level dd4hepLogLevel = Acts::Logging::Level::INFO; + Acts::Logging::Level dd4hepLogLevel = Acts::Logging::Level::WARNING; /// XML-file with the detector description std::vector xmlFileNames; /// The name of the service @@ -87,7 +87,7 @@ class DD4hepGeometryService { std::make_shared(); }; - DD4hepGeometryService(const Config& cfg); + explicit DD4hepGeometryService(const Config& cfg); DD4hepGeometryService(const DD4hepGeometryService&) = delete; DD4hepGeometryService(DD4hepGeometryService&&) = delete; ~DD4hepGeometryService(); diff --git a/Examples/Detectors/MagneticField/include/ActsExamples/MagneticField/ScalableBField.hpp b/Examples/Detectors/MagneticField/include/ActsExamples/MagneticField/ScalableBField.hpp index bd7f7af38df..5def5740fa4 100644 --- a/Examples/Detectors/MagneticField/include/ActsExamples/MagneticField/ScalableBField.hpp +++ b/Examples/Detectors/MagneticField/include/ActsExamples/MagneticField/ScalableBField.hpp @@ -26,7 +26,7 @@ class ScalableBField final : public Acts::MagneticFieldProvider { Acts::ActsScalar scalor = 1.; /// @brief constructor with context - Cache(const Acts::MagneticFieldContext& mctx) { + explicit Cache(const Acts::MagneticFieldContext& mctx) { scalor = mctx.get().scalor; } }; diff --git a/Examples/Detectors/MuonSpectrometerMockupDetector/include/ActsExamples/MuonSpectrometerMockupDetector/MockupSectorBuilder.hpp b/Examples/Detectors/MuonSpectrometerMockupDetector/include/ActsExamples/MuonSpectrometerMockupDetector/MockupSectorBuilder.hpp index 62ae610224e..5b349bec9af 100644 --- a/Examples/Detectors/MuonSpectrometerMockupDetector/include/ActsExamples/MuonSpectrometerMockupDetector/MockupSectorBuilder.hpp +++ b/Examples/Detectors/MuonSpectrometerMockupDetector/include/ActsExamples/MuonSpectrometerMockupDetector/MockupSectorBuilder.hpp @@ -55,7 +55,7 @@ class MockupSectorBuilder { /// Constructor ///@param config The configuration struct - MockupSectorBuilder(const Config& config); + explicit MockupSectorBuilder(const Config& config); /// Destructor ~MockupSectorBuilder() = default; diff --git a/Examples/Detectors/TGeoDetector/include/ActsExamples/TGeoDetector/TGeoDetector.hpp b/Examples/Detectors/TGeoDetector/include/ActsExamples/TGeoDetector/TGeoDetector.hpp index 8982e3dbfb9..0fae0df1c5a 100644 --- a/Examples/Detectors/TGeoDetector/include/ActsExamples/TGeoDetector/TGeoDetector.hpp +++ b/Examples/Detectors/TGeoDetector/include/ActsExamples/TGeoDetector/TGeoDetector.hpp @@ -75,7 +75,7 @@ struct TGeoDetector { struct LayerTriplet { LayerTriplet() = default; - LayerTriplet(T value) + explicit LayerTriplet(T value) : negative{value}, central{value}, positive{value} {} LayerTriplet(T _negative, T _central, T _positive) diff --git a/Examples/Framework/CMakeLists.txt b/Examples/Framework/CMakeLists.txt index 692db8f2f15..efe06302800 100644 --- a/Examples/Framework/CMakeLists.txt +++ b/Examples/Framework/CMakeLists.txt @@ -13,6 +13,7 @@ add_library( src/Framework/WhiteBoard.cpp src/Framework/RandomNumbers.cpp src/Framework/Sequencer.cpp + src/Framework/DataHandle.cpp src/Utilities/EventDataTransforms.cpp src/Utilities/Paths.cpp src/Utilities/Options.cpp diff --git a/Examples/Framework/ML/src/NeuralCalibrator.cpp b/Examples/Framework/ML/src/NeuralCalibrator.cpp index 68d24d35468..67c6e76db57 100644 --- a/Examples/Framework/ML/src/NeuralCalibrator.cpp +++ b/Examples/Framework/ML/src/NeuralCalibrator.cpp @@ -176,7 +176,8 @@ void ActsExamples::NeuralCalibrator::calibrate( Acts::visit_measurement(measurement.size(), [&](auto N) -> void { constexpr std::size_t kMeasurementSize = decltype(N)::value; const ConstFixedBoundMeasurementProxy fixedMeasurement = - measurement; + static_cast>( + measurement); Acts::ActsVector calibratedParameters = fixedMeasurement.parameters(); diff --git a/Examples/Framework/include/ActsExamples/EventData/Measurement.hpp b/Examples/Framework/include/ActsExamples/EventData/Measurement.hpp index 12286417c61..a0bf4559509 100644 --- a/Examples/Framework/include/ActsExamples/EventData/Measurement.hpp +++ b/Examples/Framework/include/ActsExamples/EventData/Measurement.hpp @@ -205,7 +205,7 @@ class MeasurementProxyBase { MeasurementProxyBase(Container& container_, Index index_) : m_container(&container_), m_index(index_) {} template - MeasurementProxyBase( + explicit MeasurementProxyBase( const MeasurementProxyBase& other) requires(ReadOnly == OtherReadOnly || ReadOnly) : m_container(&other.container()), m_index(other.index()) {} @@ -358,7 +358,7 @@ class FixedMeasurementProxy assert(container().m_entries.at(index()).size == Size && "Size mismatch"); } template - FixedMeasurementProxy( + explicit FixedMeasurementProxy( const MeasurementProxyBase& other) requires(ReadOnly == OtherReadOnly || ReadOnly) : Base(other) { @@ -450,7 +450,7 @@ class VariableMeasurementProxy VariableMeasurementProxy(Container& container_, Index index_) : Base(container_, index_) {} template - VariableMeasurementProxy( + explicit VariableMeasurementProxy( const MeasurementProxyBase& other) requires(ReadOnly == OtherReadOnly || ReadOnly) : Base(other) {} diff --git a/Examples/Framework/include/ActsExamples/EventData/ScalingCalibrator.hpp b/Examples/Framework/include/ActsExamples/EventData/ScalingCalibrator.hpp index 706ef5291cd..a91b6d840cb 100644 --- a/Examples/Framework/include/ActsExamples/EventData/ScalingCalibrator.hpp +++ b/Examples/Framework/include/ActsExamples/EventData/ScalingCalibrator.hpp @@ -47,7 +47,7 @@ class ScalingCalibrator : public MeasurementCalibrator { } }; - ScalingCalibrator(const std::filesystem::path& path); + explicit ScalingCalibrator(const std::filesystem::path& path); void calibrate( const MeasurementContainer& measurements, diff --git a/Examples/Framework/include/ActsExamples/EventData/SimVertex.hpp b/Examples/Framework/include/ActsExamples/EventData/SimVertex.hpp index d012ac3eb80..0bdfbb4925c 100644 --- a/Examples/Framework/include/ActsExamples/EventData/SimVertex.hpp +++ b/Examples/Framework/include/ActsExamples/EventData/SimVertex.hpp @@ -21,8 +21,9 @@ class SimVertexBarcode { using Value = SimBarcode::Value; constexpr SimVertexBarcode() = default; - constexpr SimVertexBarcode(Value encoded) : m_id(SimBarcode(encoded)) {} - constexpr SimVertexBarcode(SimBarcode vertexId) + explicit constexpr SimVertexBarcode(Value encoded) + : m_id(SimBarcode(encoded)) {} + explicit constexpr SimVertexBarcode(SimBarcode vertexId) : m_id(vertexId.setParticle(0).setSubParticle(0)) { if (vertexId != vertexId.vertexId()) { throw std::invalid_argument("SimVertexBarcode: invalid vertexId"); diff --git a/Examples/Framework/include/ActsExamples/EventData/SpacePointContainer.hpp b/Examples/Framework/include/ActsExamples/EventData/SpacePointContainer.hpp index 14f50ff249a..dbf94345f0a 100644 --- a/Examples/Framework/include/ActsExamples/EventData/SpacePointContainer.hpp +++ b/Examples/Framework/include/ActsExamples/EventData/SpacePointContainer.hpp @@ -31,8 +31,10 @@ class SpacePointContainer { // the memory backend is independetly handled. This is only interfacing it to // ACTS SpacePointContainer(CollectionType&& container) = delete; - SpacePointContainer(CollectionType& container) : m_storage(container) {} - SpacePointContainer(CollectionType* container) : m_storage(container) {} + explicit SpacePointContainer(CollectionType& container) + : m_storage(container) {} + explicit SpacePointContainer(CollectionType* container) + : m_storage(container) {} // No copy constructor or copy operation allowed SpacePointContainer(const SpacePointContainer&) = delete; diff --git a/Examples/Framework/include/ActsExamples/Framework/DataHandle.hpp b/Examples/Framework/include/ActsExamples/Framework/DataHandle.hpp index 2aaa469446c..eebe8cae749 100644 --- a/Examples/Framework/include/ActsExamples/Framework/DataHandle.hpp +++ b/Examples/Framework/include/ActsExamples/Framework/DataHandle.hpp @@ -8,11 +8,9 @@ #pragma once -#include "Acts/Utilities/ThrowAssert.hpp" #include "ActsExamples/Framework/SequenceElement.hpp" #include "ActsExamples/Framework/WhiteBoard.hpp" -#include #include #include @@ -54,14 +52,33 @@ class DataHandleBase { std::optional m_key{}; }; -template -class ReadDataHandle; +class WriteDataHandleBase : public DataHandleBase { + protected: + WriteDataHandleBase(SequenceElement* parent, const std::string& name) + : DataHandleBase{parent, name} {} + + public: + void initialize(const std::string& key); + + bool isCompatible(const DataHandleBase& other) const final; +}; + +class ReadDataHandleBase : public DataHandleBase { + protected: + ReadDataHandleBase(SequenceElement* parent, const std::string& name) + : DataHandleBase{parent, name} {} + + public: + void initialize(const std::string& key); + + bool isCompatible(const DataHandleBase& other) const final; +}; template -class WriteDataHandle final : public DataHandleBase { +class WriteDataHandle final : public WriteDataHandleBase { public: WriteDataHandle(SequenceElement* parent, const std::string& name) - : DataHandleBase{parent, name} { + : WriteDataHandleBase{parent, name} { m_parent->registerWriteHandle(*this); } @@ -77,37 +94,17 @@ class WriteDataHandle final : public DataHandleBase { wb.add(m_key.value(), std::move(value)); } - void initialize(const std::string& key) { - if (key.empty()) { - throw std::invalid_argument{"Write handle '" + fullName() + - "' cannot receive empty key"}; - } - m_key = key; - } - - bool isCompatible(const DataHandleBase& other) const override { - return dynamic_cast*>(&other) != nullptr; - } - const std::type_info& typeInfo() const override { return typeid(T); }; }; template -class ReadDataHandle final : public DataHandleBase { +class ReadDataHandle final : public ReadDataHandleBase { public: ReadDataHandle(SequenceElement* parent, const std::string& name) - : DataHandleBase{parent, name} { + : ReadDataHandleBase{parent, name} { m_parent->registerReadHandle(*this); } - void initialize(const std::string& key) { - if (key.empty()) { - throw std::invalid_argument{"Read handle '" + fullName() + - "' cannot receive empty key"}; - } - m_key = key; - } - const T& operator()(const AlgorithmContext& ctx) const { return (*this)(ctx.eventStore); } @@ -120,10 +117,6 @@ class ReadDataHandle final : public DataHandleBase { return wb.get(m_key.value()); } - bool isCompatible(const DataHandleBase& other) const override { - return dynamic_cast*>(&other) != nullptr; - } - const std::type_info& typeInfo() const override { return typeid(T); }; }; diff --git a/Examples/Framework/include/ActsExamples/Framework/RandomNumbers.hpp b/Examples/Framework/include/ActsExamples/Framework/RandomNumbers.hpp index 5389ae5a8b6..6f9f9abbcd6 100644 --- a/Examples/Framework/include/ActsExamples/Framework/RandomNumbers.hpp +++ b/Examples/Framework/include/ActsExamples/Framework/RandomNumbers.hpp @@ -44,7 +44,7 @@ class RandomNumbers { std::uint64_t seed = 1234567890u; ///< random seed }; - RandomNumbers(const Config& cfg); + explicit RandomNumbers(const Config& cfg); /// Spawn an algorithm-local random number generator. To avoid inefficiencies /// and multiple uses of a given RNG seed, this should only be done once per diff --git a/Examples/Framework/include/ActsExamples/Framework/Sequencer.hpp b/Examples/Framework/include/ActsExamples/Framework/Sequencer.hpp index fa1c53618a0..a8f2ad27950 100644 --- a/Examples/Framework/include/ActsExamples/Framework/Sequencer.hpp +++ b/Examples/Framework/include/ActsExamples/Framework/Sequencer.hpp @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -89,7 +88,7 @@ class Sequencer { std::size_t fpeStackTraceLength = 8; }; - Sequencer(const Config &cfg); + explicit Sequencer(const Config &cfg); /// Add a context decorator to the set of context decorators. /// diff --git a/Examples/Framework/include/ActsExamples/Framework/WhiteBoard.hpp b/Examples/Framework/include/ActsExamples/Framework/WhiteBoard.hpp index ca5e1904879..777d27fe898 100644 --- a/Examples/Framework/include/ActsExamples/Framework/WhiteBoard.hpp +++ b/Examples/Framework/include/ActsExamples/Framework/WhiteBoard.hpp @@ -76,7 +76,7 @@ class WhiteBoard { struct HolderT : public IHolder { T value; - HolderT(T&& v) : value(std::move(v)) {} + explicit HolderT(T&& v) : value(std::move(v)) {} const std::type_info& type() const override { return typeid(T); } }; diff --git a/Examples/Framework/include/ActsExamples/Utilities/tbbWrap.hpp b/Examples/Framework/include/ActsExamples/Utilities/tbbWrap.hpp index 985cbb2180b..84784c55d31 100644 --- a/Examples/Framework/include/ActsExamples/Utilities/tbbWrap.hpp +++ b/Examples/Framework/include/ActsExamples/Utilities/tbbWrap.hpp @@ -161,7 +161,7 @@ class queuing_mutex { #endif } - scoped_lock(queuing_mutex& ACTS_EXAMPLES_WITH_TBB(m)) { + explicit scoped_lock(queuing_mutex& ACTS_EXAMPLES_WITH_TBB(m)) { #ifndef ACTS_EXAMPLES_NO_TBB if (enableTBB()) { tbb.emplace(*m.tbb); diff --git a/Examples/Framework/include/ActsExamples/Validation/EffPlotTool.hpp b/Examples/Framework/include/ActsExamples/Validation/EffPlotTool.hpp index 534549fbaa4..7ac49098a0a 100644 --- a/Examples/Framework/include/ActsExamples/Validation/EffPlotTool.hpp +++ b/Examples/Framework/include/ActsExamples/Validation/EffPlotTool.hpp @@ -34,6 +34,7 @@ class EffPlotTool { {"Eta", PlotHelpers::Binning("#eta", 40, -4, 4)}, {"Phi", PlotHelpers::Binning("#phi", 100, -3.15, 3.15)}, {"Pt", PlotHelpers::Binning("pT [GeV/c]", 40, 0, 100)}, + {"Z0", PlotHelpers::Binning("z_0 [mm]", 50, -200, 200)}, {"DeltaR", PlotHelpers::Binning("#Delta R", 100, 0, 0.3)}}; }; @@ -42,6 +43,7 @@ class EffPlotTool { TEfficiency* trackEff_vs_pT{nullptr}; ///< Tracking efficiency vs pT TEfficiency* trackEff_vs_eta{nullptr}; ///< Tracking efficiency vs eta TEfficiency* trackEff_vs_phi{nullptr}; ///< Tracking efficiency vs phi + TEfficiency* trackEff_vs_z0{nullptr}; ///< Tracking efficiency vs z0 TEfficiency* trackEff_vs_DeltaR{ nullptr}; ///< Tracking efficiency vs distance to the closest truth ///< particle diff --git a/Examples/Framework/src/EventData/MeasurementCalibration.cpp b/Examples/Framework/src/EventData/MeasurementCalibration.cpp index 963ef57ea24..b4764844770 100644 --- a/Examples/Framework/src/EventData/MeasurementCalibration.cpp +++ b/Examples/Framework/src/EventData/MeasurementCalibration.cpp @@ -38,7 +38,8 @@ void ActsExamples::PassThroughCalibrator::calibrate( Acts::visit_measurement(measurement.size(), [&](auto N) -> void { constexpr std::size_t kMeasurementSize = decltype(N)::value; const ConstFixedBoundMeasurementProxy fixedMeasurement = - measurement; + static_cast>( + measurement); trackState.allocateCalibrated(kMeasurementSize); trackState.calibrated() = fixedMeasurement.parameters(); diff --git a/Examples/Framework/src/EventData/ScalingCalibrator.cpp b/Examples/Framework/src/EventData/ScalingCalibrator.cpp index 12da0078659..ae5c1eca4fe 100644 --- a/Examples/Framework/src/EventData/ScalingCalibrator.cpp +++ b/Examples/Framework/src/EventData/ScalingCalibrator.cpp @@ -165,7 +165,8 @@ void ActsExamples::ScalingCalibrator::calibrate( Acts::visit_measurement(measurement.size(), [&](auto N) -> void { constexpr std::size_t kMeasurementSize = decltype(N)::value; const ConstFixedBoundMeasurementProxy fixedMeasurement = - measurement; + static_cast>( + measurement); Acts::ActsVector calibratedParameters = fixedMeasurement.parameters(); diff --git a/Examples/Framework/src/Framework/DataHandle.cpp b/Examples/Framework/src/Framework/DataHandle.cpp new file mode 100644 index 00000000000..621b6201d0f --- /dev/null +++ b/Examples/Framework/src/Framework/DataHandle.cpp @@ -0,0 +1,39 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include "ActsExamples/Framework/DataHandle.hpp" + +namespace ActsExamples { + +void WriteDataHandleBase::initialize(const std::string& key) { + if (key.empty()) { + throw std::invalid_argument{"Write handle '" + fullName() + + "' cannot receive empty key"}; + } + m_key = key; +} + +bool WriteDataHandleBase::isCompatible(const DataHandleBase& other) const { + return dynamic_cast(&other) != nullptr && + typeInfo() == other.typeInfo(); +} + +void ReadDataHandleBase::initialize(const std::string& key) { + if (key.empty()) { + throw std::invalid_argument{"Read handle '" + fullName() + + "' cannot receive empty key"}; + } + m_key = key; +} + +bool ReadDataHandleBase::isCompatible(const DataHandleBase& other) const { + return dynamic_cast(&other) != nullptr && + typeInfo() == other.typeInfo(); +} + +} // namespace ActsExamples diff --git a/Examples/Framework/src/Framework/Sequencer.cpp b/Examples/Framework/src/Framework/Sequencer.cpp index 78444c58ac4..5c1a76b5bd4 100644 --- a/Examples/Framework/src/Framework/Sequencer.cpp +++ b/Examples/Framework/src/Framework/Sequencer.cpp @@ -367,7 +367,7 @@ struct StopWatch { Timepoint start; Duration& store; - StopWatch(Duration& s) : start(Clock::now()), store(s) {} + explicit StopWatch(Duration& s) : start(Clock::now()), store(s) {} ~StopWatch() { store += Clock::now() - start; } }; @@ -611,7 +611,7 @@ void Sequencer::fpeReport() const { auto merged = std::accumulate( fpe.begin(), fpe.end(), Acts::FpeMonitor::Result{}, [](const auto& lhs, const auto& rhs) { return lhs.merged(rhs); }); - if (!merged) { + if (!merged.hasStackTraces()) { // no FPEs to report continue; } diff --git a/Examples/Framework/src/Validation/EffPlotTool.cpp b/Examples/Framework/src/Validation/EffPlotTool.cpp index a30c1499796..eb92cfa7b63 100644 --- a/Examples/Framework/src/Validation/EffPlotTool.cpp +++ b/Examples/Framework/src/Validation/EffPlotTool.cpp @@ -27,6 +27,7 @@ void ActsExamples::EffPlotTool::book( PlotHelpers::Binning bEta = m_cfg.varBinning.at("Eta"); PlotHelpers::Binning bPt = m_cfg.varBinning.at("Pt"); PlotHelpers::Binning bDeltaR = m_cfg.varBinning.at("DeltaR"); + PlotHelpers::Binning bZ0 = m_cfg.varBinning.at("Z0"); ACTS_DEBUG("Initialize the histograms for efficiency plots"); // efficiency vs pT effPlotCache.trackEff_vs_pT = PlotHelpers::bookEff( @@ -37,6 +38,9 @@ void ActsExamples::EffPlotTool::book( // efficiency vs phi effPlotCache.trackEff_vs_phi = PlotHelpers::bookEff( "trackeff_vs_phi", "Tracking efficiency;Truth #phi;Efficiency", bPhi); + // efficiency vs z0 + effPlotCache.trackEff_vs_z0 = PlotHelpers::bookEff( + "trackeff_vs_z0", "Tracking efficiency;Truth z_0 [mm];Efficiency", bZ0); // efficiancy vs distance to the closest truth particle effPlotCache.trackEff_vs_DeltaR = PlotHelpers::bookEff( "trackeff_vs_DeltaR", @@ -47,6 +51,7 @@ void ActsExamples::EffPlotTool::clear(EffPlotCache& effPlotCache) const { delete effPlotCache.trackEff_vs_pT; delete effPlotCache.trackEff_vs_eta; delete effPlotCache.trackEff_vs_phi; + delete effPlotCache.trackEff_vs_z0; delete effPlotCache.trackEff_vs_DeltaR; } @@ -56,6 +61,7 @@ void ActsExamples::EffPlotTool::write( effPlotCache.trackEff_vs_pT->Write(); effPlotCache.trackEff_vs_eta->Write(); effPlotCache.trackEff_vs_phi->Write(); + effPlotCache.trackEff_vs_z0->Write(); effPlotCache.trackEff_vs_DeltaR->Write(); } @@ -65,10 +71,12 @@ void ActsExamples::EffPlotTool::fill(EffPlotTool::EffPlotCache& effPlotCache, const auto t_phi = phi(truthParticle.direction()); const auto t_eta = eta(truthParticle.direction()); const auto t_pT = truthParticle.transverseMomentum(); + const auto t_z0 = truthParticle.position().z(); const auto t_deltaR = deltaR; PlotHelpers::fillEff(effPlotCache.trackEff_vs_pT, t_pT, status); PlotHelpers::fillEff(effPlotCache.trackEff_vs_eta, t_eta, status); PlotHelpers::fillEff(effPlotCache.trackEff_vs_phi, t_phi, status); + PlotHelpers::fillEff(effPlotCache.trackEff_vs_z0, t_z0, status); PlotHelpers::fillEff(effPlotCache.trackEff_vs_DeltaR, t_deltaR, status); } diff --git a/Examples/Framework/src/Validation/ResPlotTool.cpp b/Examples/Framework/src/Validation/ResPlotTool.cpp index 14321050144..c1e3e4a6c1b 100644 --- a/Examples/Framework/src/Validation/ResPlotTool.cpp +++ b/Examples/Framework/src/Validation/ResPlotTool.cpp @@ -158,21 +158,27 @@ void ActsExamples::ResPlotTool::fill( auto trackParameter = fittedParamters.parameters(); // get the perigee surface - auto pSurface = &fittedParamters.referenceSurface(); + const auto& pSurface = fittedParamters.referenceSurface(); // get the truth position and momentum ParametersVector truthParameter = ParametersVector::Zero(); // get the truth perigee parameter - auto lpResult = pSurface->globalToLocal(gctx, truthParticle.position(), - truthParticle.direction()); - if (lpResult.ok()) { + auto intersection = + pSurface + .intersect(gctx, truthParticle.position(), truthParticle.direction()) + .closest(); + if (intersection.isValid()) { + auto lpResult = pSurface.globalToLocal(gctx, intersection.position(), + truthParticle.direction()); + assert(lpResult.ok()); + truthParameter[Acts::BoundIndices::eBoundLoc0] = lpResult.value()[Acts::BoundIndices::eBoundLoc0]; truthParameter[Acts::BoundIndices::eBoundLoc1] = lpResult.value()[Acts::BoundIndices::eBoundLoc1]; } else { - ACTS_ERROR("Global to local transformation did not succeed."); + ACTS_ERROR("Cannot get the truth perigee parameter"); } truthParameter[Acts::BoundIndices::eBoundPhi] = phi(truthParticle.direction()); diff --git a/Examples/Framework/src/Validation/TrackClassification.cpp b/Examples/Framework/src/Validation/TrackClassification.cpp index a89f7c2a07a..d1e79d15835 100644 --- a/Examples/Framework/src/Validation/TrackClassification.cpp +++ b/Examples/Framework/src/Validation/TrackClassification.cpp @@ -53,8 +53,9 @@ void ActsExamples::identifyContributingParticles( for (auto hitIndex : protoTrack) { // register all particles that generated this hit - for (auto hitParticle : makeRange(hitParticlesMap.equal_range(hitIndex))) { - increaseHitCount(particleHitCounts, hitParticle.second); + for (const auto& [_, value] : + makeRange(hitParticlesMap.equal_range(hitIndex))) { + increaseHitCount(particleHitCounts, value); } } sortHitCount(particleHitCounts); @@ -79,8 +80,9 @@ void ActsExamples::identifyContributingParticles( IndexSourceLink sl = state.getUncalibratedSourceLink().template get(); auto hitIndex = sl.index(); - for (auto hitParticle : makeRange(hitParticlesMap.equal_range(hitIndex))) { - increaseHitCount(particleHitCounts, hitParticle.second); + for (const auto& [_, value] : + makeRange(hitParticlesMap.equal_range(hitIndex))) { + increaseHitCount(particleHitCounts, value); } return true; }); @@ -102,8 +104,9 @@ void ActsExamples::identifyContributingParticles( IndexSourceLink sl = state.getUncalibratedSourceLink().template get(); auto hitIndex = sl.index(); - for (auto hitParticle : makeRange(hitParticlesMap.equal_range(hitIndex))) { - increaseHitCount(particleHitCounts, hitParticle.second); + for (const auto& [_, value] : + makeRange(hitParticlesMap.equal_range(hitIndex))) { + increaseHitCount(particleHitCounts, value); } } sortHitCount(particleHitCounts); diff --git a/Examples/HelloWorld/HelloLoggerAlgorithm.hpp b/Examples/HelloWorld/HelloLoggerAlgorithm.hpp index 934c0b67f5c..3cafd2c4f55 100644 --- a/Examples/HelloWorld/HelloLoggerAlgorithm.hpp +++ b/Examples/HelloWorld/HelloLoggerAlgorithm.hpp @@ -17,7 +17,7 @@ namespace ActsExamples { /// A simple algorithm that just prints hello world. class HelloLoggerAlgorithm : public ActsExamples::IAlgorithm { public: - HelloLoggerAlgorithm(Acts::Logging::Level level); + explicit HelloLoggerAlgorithm(Acts::Logging::Level level); // Log a few messages. ActsExamples::ProcessCode execute(const AlgorithmContext& ctx) const override; diff --git a/Examples/Io/CMakeLists.txt b/Examples/Io/CMakeLists.txt index dcf7c16a0a1..8b7f2861a6e 100644 --- a/Examples/Io/CMakeLists.txt +++ b/Examples/Io/CMakeLists.txt @@ -2,8 +2,6 @@ add_subdirectory(Csv) add_subdirectory_if(EDM4hep ACTS_BUILD_EXAMPLES_EDM4HEP) add_subdirectory_if(HepMC3 ACTS_BUILD_EXAMPLES_HEPMC3) add_subdirectory(Json) -add_subdirectory(NuclearInteractions) add_subdirectory(Obj) -add_subdirectory(Performance) add_subdirectory(Root) add_subdirectory_if(Svg ACTS_BUILD_PLUGIN_ACTSVG) diff --git a/Examples/Io/Csv/include/ActsExamples/Io/Csv/CsvInputOutput.hpp b/Examples/Io/Csv/include/ActsExamples/Io/Csv/CsvInputOutput.hpp index 7f4e7b894c3..e141f470988 100644 --- a/Examples/Io/Csv/include/ActsExamples/Io/Csv/CsvInputOutput.hpp +++ b/Examples/Io/Csv/include/ActsExamples/Io/Csv/CsvInputOutput.hpp @@ -236,7 +236,7 @@ class DsvReader { /// Open a file at the given path. /// /// \param path Path to the input file - DsvReader(const std::string& path); + explicit DsvReader(const std::string& path); /// Read the next line from the file. /// diff --git a/Examples/Io/NuclearInteractions/CMakeLists.txt b/Examples/Io/NuclearInteractions/CMakeLists.txt deleted file mode 100644 index 3f7ad2b9b9b..00000000000 --- a/Examples/Io/NuclearInteractions/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -add_library( - ActsExamplesIoNuclearInteractions - SHARED - src/RootNuclearInteractionParametersWriter.cpp - src/detail/NuclearInteractionParametrisation.cpp -) -target_include_directories( - ActsExamplesIoNuclearInteractions - PUBLIC $ -) -target_link_libraries( - ActsExamplesIoNuclearInteractions - PUBLIC ActsCore ActsExamplesFramework Threads::Threads - PRIVATE ROOT::Core ROOT::Hist ROOT::Tree -) - -install( - TARGETS ActsExamplesIoNuclearInteractions - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} -) diff --git a/Examples/Io/Performance/CMakeLists.txt b/Examples/Io/Performance/CMakeLists.txt deleted file mode 100644 index b41bf76ea07..00000000000 --- a/Examples/Io/Performance/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ -add_library( - ActsExamplesIoPerformance - SHARED - ActsExamples/Io/Performance/CKFPerformanceWriter.cpp - ActsExamples/Io/Performance/SeedingPerformanceWriter.cpp - ActsExamples/Io/Performance/TrackFinderPerformanceWriter.cpp - ActsExamples/Io/Performance/TrackFitterPerformanceWriter.cpp - ActsExamples/Io/Performance/VertexPerformanceWriter.cpp -) -target_include_directories( - ActsExamplesIoPerformance - PUBLIC $ -) -target_link_libraries( - ActsExamplesIoPerformance - PUBLIC ActsExamplesFramework - PRIVATE ActsCore ROOT::Core ROOT::Tree -) - -install( - TARGETS ActsExamplesIoPerformance - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} -) diff --git a/Examples/Io/Root/CMakeLists.txt b/Examples/Io/Root/CMakeLists.txt index 3ac12286395..353d68debab 100644 --- a/Examples/Io/Root/CMakeLists.txt +++ b/Examples/Io/Root/CMakeLists.txt @@ -23,6 +23,13 @@ add_library( src/RootVertexReader.cpp src/RootVertexWriter.cpp src/RootAthenaDumpReader.cpp + src/RootNuclearInteractionParametersWriter.cpp + src/detail/NuclearInteractionParametrisation.cpp + src/TrackFinderPerformanceWriter.cpp + src/SeedingPerformanceWriter.cpp + src/TrackFinderNTupleWriter.cpp + src/TrackFitterPerformanceWriter.cpp + src/VertexNTupleWriter.cpp ) target_include_directories( ActsExamplesIoRoot diff --git a/Examples/Io/Root/include/ActsExamples/Io/Root/RootAthenaDumpReader.hpp b/Examples/Io/Root/include/ActsExamples/Io/Root/RootAthenaDumpReader.hpp index e917e07038d..2a09d8492b2 100644 --- a/Examples/Io/Root/include/ActsExamples/Io/Root/RootAthenaDumpReader.hpp +++ b/Examples/Io/Root/include/ActsExamples/Io/Root/RootAthenaDumpReader.hpp @@ -173,6 +173,7 @@ class RootAthenaDumpReader : public IReader { std::vector> m_eventMap; std::shared_ptr m_inputchain; long unsigned int m_events; + bool m_haveStripFeatures = true; static constexpr unsigned int maxCL = 1500000; static constexpr unsigned int maxSP = 1500000; @@ -189,7 +190,7 @@ class RootAthenaDumpReader : public IReader { int CLindex[maxCL] = {}; //[nCL] // Clusters - std::vector *CLhardware; + std::vector *CLhardware{}; Double_t CLx[maxCL] = {}; //[nCL] Double_t CLy[maxCL] = {}; //[nCL] Double_t CLz[maxCL] = {}; //[nCL] @@ -199,13 +200,13 @@ class RootAthenaDumpReader : public IReader { Int_t CLphi_module[maxCL] = {}; //[nCL] Int_t CLside[maxCL] = {}; //[nCL] ULong64_t CLmoduleID[maxCL] = {}; //[nCL] - std::vector> *CLparticleLink_eventIndex; - std::vector> *CLparticleLink_barcode; - std::vector> *CLbarcodesLinked; - std::vector> *CLparticle_charge; - std::vector> *CLphis; - std::vector> *CLetas; - std::vector> *CLtots; + std::vector> *CLparticleLink_eventIndex{}; + std::vector> *CLparticleLink_barcode{}; + std::vector> *CLbarcodesLinked{}; + std::vector> *CLparticle_charge{}; + std::vector> *CLphis{}; + std::vector> *CLetas{}; + std::vector> *CLtots{}; Double_t CLloc_direction1[maxCL] = {}; //[nCL] Double_t CLloc_direction2[maxCL] = {}; //[nCL] Double_t CLloc_direction3[maxCL] = {}; //[nCL] @@ -223,7 +224,7 @@ class RootAthenaDumpReader : public IReader { Float_t CLnorm_x[maxCL] = {}; //[nCL] Float_t CLnorm_y[maxCL] = {}; //[nCL] Float_t CLnorm_z[maxCL] = {}; //[nCL] - std::vector> *CLlocal_cov; + std::vector> *CLlocal_cov{}; // Particles Int_t nPartEVT = 0; @@ -246,8 +247,8 @@ class RootAthenaDumpReader : public IReader { Int_t Part_vProdNout[maxPart] = {}; //[nPartEVT] Int_t Part_vProdStatus[maxPart] = {}; //[nPartEVT] Int_t Part_vProdBarcode[maxPart] = {}; //[nPartEVT] - std::vector> *Part_vParentID; - std::vector> *Part_vParentBarcode; + std::vector> *Part_vParentID{}; + std::vector> *Part_vParentBarcode{}; // Spacepoints Int_t nSP = 0; @@ -263,27 +264,27 @@ class RootAthenaDumpReader : public IReader { double SPcovz[maxSP] = {}; //[nSP] float SPhl_topstrip[maxSP] = {}; //[nSP] float SPhl_botstrip[maxSP] = {}; //[nSP] - std::vector> *SPtopStripDirection; - std::vector> *SPbottomStripDirection; - std::vector> *SPstripCenterDistance; - std::vector> *SPtopStripCenterPosition; + std::vector> *SPtopStripDirection{}; + std::vector> *SPbottomStripDirection{}; + std::vector> *SPstripCenterDistance{}; + std::vector> *SPtopStripCenterPosition{}; // Tracks Int_t nTRK = 0; Int_t TRKindex[maxTRK] = {}; //[nTRK] Int_t TRKtrack_fitter[maxTRK] = {}; //[nTRK] Int_t TRKparticle_hypothesis[maxTRK] = {}; //[nTRK] - std::vector> *TRKproperties; - std::vector> *TRKpattern; + std::vector> *TRKproperties{}; + std::vector> *TRKpattern{}; Int_t TRKndof[maxTRK] = {}; //[nTRK] Int_t TRKmot[maxTRK] = {}; //[nTRK] Int_t TRKoot[maxTRK] = {}; //[nTRK] Float_t TRKchiSq[maxTRK] = {}; //[nTRK] - std::vector> *TRKmeasurementsOnTrack_pixcl_sctcl_index; - std::vector> *TRKoutliersOnTrack_pixcl_sctcl_index; + std::vector> *TRKmeasurementsOnTrack_pixcl_sctcl_index{}; + std::vector> *TRKoutliersOnTrack_pixcl_sctcl_index{}; Int_t TRKcharge[maxTRK] = {}; //[nTRK] - std::vector> *TRKperigee_position; - std::vector> *TRKperigee_momentum; + std::vector> *TRKperigee_position{}; + std::vector> *TRKperigee_momentum{}; Int_t TTCindex[maxTRK] = {}; //[nTRK] Int_t TTCevent_index[maxTRK] = {}; //[nTRK] Int_t TTCparticle_link[maxTRK] = {}; //[nTRK] @@ -293,10 +294,10 @@ class RootAthenaDumpReader : public IReader { Int_t nDTT = 0; Int_t DTTindex[maxDTT] = {}; //[nDTT] Int_t DTTsize[maxDTT] = {}; //[nDTT] - std::vector> *DTTtrajectory_eventindex; - std::vector> *DTTtrajectory_barcode; - std::vector> *DTTstTruth_subDetType; - std::vector> *DTTstTrack_subDetType; - std::vector> *DTTstCommon_subDetType; + std::vector> *DTTtrajectory_eventindex{}; + std::vector> *DTTtrajectory_barcode{}; + std::vector> *DTTstTruth_subDetType{}; + std::vector> *DTTstTrack_subDetType{}; + std::vector> *DTTstCommon_subDetType{}; }; } // namespace ActsExamples diff --git a/Examples/Io/NuclearInteractions/include/ActsExamples/Io/NuclearInteractions/RootNuclearInteractionParametersWriter.hpp b/Examples/Io/Root/include/ActsExamples/Io/Root/RootNuclearInteractionParametersWriter.hpp similarity index 97% rename from Examples/Io/NuclearInteractions/include/ActsExamples/Io/NuclearInteractions/RootNuclearInteractionParametersWriter.hpp rename to Examples/Io/Root/include/ActsExamples/Io/Root/RootNuclearInteractionParametersWriter.hpp index 8edad2c2a7d..d688920fc76 100644 --- a/Examples/Io/NuclearInteractions/include/ActsExamples/Io/NuclearInteractions/RootNuclearInteractionParametersWriter.hpp +++ b/Examples/Io/Root/include/ActsExamples/Io/Root/RootNuclearInteractionParametersWriter.hpp @@ -12,7 +12,7 @@ #include "ActsExamples/EventData/ExtractedSimulationProcess.hpp" #include "ActsExamples/Framework/ProcessCode.hpp" #include "ActsExamples/Framework/WriterT.hpp" -#include "ActsExamples/Io/NuclearInteractions/detail/NuclearInteractionParametrisation.hpp" +#include "ActsExamples/Io/Root/detail/NuclearInteractionParametrisation.hpp" #include #include diff --git a/Examples/Io/Root/include/ActsExamples/Io/Root/RootParticleWriter.hpp b/Examples/Io/Root/include/ActsExamples/Io/Root/RootParticleWriter.hpp index 99cf6b5cd61..8be9f05b735 100644 --- a/Examples/Io/Root/include/ActsExamples/Io/Root/RootParticleWriter.hpp +++ b/Examples/Io/Root/include/ActsExamples/Io/Root/RootParticleWriter.hpp @@ -39,7 +39,7 @@ class RootParticleWriter final : public WriterT { std::string inputParticles; /// Optional. If given, the the energy loss and traversed material is /// computed and written. - std::string inputFinalParticles; + std::string inputParticlesFinal; /// Path to the output file. std::string filePath; /// Output file access mode. @@ -74,8 +74,8 @@ class RootParticleWriter final : public WriterT { private: Config m_cfg; - ReadDataHandle m_inputFinalParticles{ - this, "InputFinalParticles"}; + ReadDataHandle m_inputParticlesFinal{ + this, "InputParticlesFinal"}; std::mutex m_writeMutex; diff --git a/Examples/Io/Performance/ActsExamples/Io/Performance/SeedingPerformanceWriter.hpp b/Examples/Io/Root/include/ActsExamples/Io/Root/SeedingPerformanceWriter.hpp similarity index 100% rename from Examples/Io/Performance/ActsExamples/Io/Performance/SeedingPerformanceWriter.hpp rename to Examples/Io/Root/include/ActsExamples/Io/Root/SeedingPerformanceWriter.hpp diff --git a/Examples/Io/Performance/ActsExamples/Io/Performance/TrackFinderPerformanceWriter.hpp b/Examples/Io/Root/include/ActsExamples/Io/Root/TrackFinderNTupleWriter.hpp similarity index 88% rename from Examples/Io/Performance/ActsExamples/Io/Performance/TrackFinderPerformanceWriter.hpp rename to Examples/Io/Root/include/ActsExamples/Io/Root/TrackFinderNTupleWriter.hpp index 287cf361999..799471be784 100644 --- a/Examples/Io/Performance/ActsExamples/Io/Performance/TrackFinderPerformanceWriter.hpp +++ b/Examples/Io/Root/include/ActsExamples/Io/Root/TrackFinderNTupleWriter.hpp @@ -24,7 +24,7 @@ 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 TrackFinderNTupleWriter final : public WriterT { public: struct Config { /// Input reconstructed track collection. @@ -48,9 +48,9 @@ class TrackFinderPerformanceWriter final : public WriterT { /// Constructor /// @param config the configuration /// @param level The log level - TrackFinderPerformanceWriter(Config config, Acts::Logging::Level level); + TrackFinderNTupleWriter(Config config, Acts::Logging::Level level); - ~TrackFinderPerformanceWriter() override; + ~TrackFinderNTupleWriter() override; ProcessCode finalize() override; @@ -59,7 +59,7 @@ class TrackFinderPerformanceWriter final : public WriterT { private: ProcessCode writeT(const AlgorithmContext& ctx, - const TrackContainer& tracks) override; + const ConstTrackContainer& tracks) override; struct Impl; diff --git a/Examples/Io/Performance/ActsExamples/Io/Performance/CKFPerformanceWriter.hpp b/Examples/Io/Root/include/ActsExamples/Io/Root/TrackFinderPerformanceWriter.hpp similarity index 95% rename from Examples/Io/Performance/ActsExamples/Io/Performance/CKFPerformanceWriter.hpp rename to Examples/Io/Root/include/ActsExamples/Io/Root/TrackFinderPerformanceWriter.hpp index 0d9e4c96feb..b3b6c36436c 100644 --- a/Examples/Io/Performance/ActsExamples/Io/Performance/CKFPerformanceWriter.hpp +++ b/Examples/Io/Root/include/ActsExamples/Io/Root/TrackFinderPerformanceWriter.hpp @@ -41,7 +41,7 @@ struct AlgorithmContext; /// done by setting the Config::rootFile pointer to an existing file. /// /// Safe to use from multiple writer threads - uses a std::mutex lock. -class CKFPerformanceWriter final : public WriterT { +class TrackFinderPerformanceWriter final : public WriterT { public: struct Config { /// Input (found) tracks collection. @@ -68,8 +68,8 @@ class CKFPerformanceWriter final : public WriterT { }; /// Construct from configuration and log level. - CKFPerformanceWriter(Config cfg, Acts::Logging::Level lvl); - ~CKFPerformanceWriter() override; + TrackFinderPerformanceWriter(Config cfg, Acts::Logging::Level lvl); + ~TrackFinderPerformanceWriter() override; /// Finalize plots. ProcessCode finalize() override; diff --git a/Examples/Io/Performance/ActsExamples/Io/Performance/TrackFitterPerformanceWriter.hpp b/Examples/Io/Root/include/ActsExamples/Io/Root/TrackFitterPerformanceWriter.hpp similarity index 100% rename from Examples/Io/Performance/ActsExamples/Io/Performance/TrackFitterPerformanceWriter.hpp rename to Examples/Io/Root/include/ActsExamples/Io/Root/TrackFitterPerformanceWriter.hpp diff --git a/Examples/Io/Performance/ActsExamples/Io/Performance/VertexPerformanceWriter.hpp b/Examples/Io/Root/include/ActsExamples/Io/Root/VertexNTupleWriter.hpp similarity index 97% rename from Examples/Io/Performance/ActsExamples/Io/Performance/VertexPerformanceWriter.hpp rename to Examples/Io/Root/include/ActsExamples/Io/Root/VertexNTupleWriter.hpp index 8043dd1cac0..514dbfc8850 100644 --- a/Examples/Io/Performance/ActsExamples/Io/Performance/VertexPerformanceWriter.hpp +++ b/Examples/Io/Root/include/ActsExamples/Io/Root/VertexNTupleWriter.hpp @@ -38,15 +38,14 @@ enum class RecoVertexClassification { Split, }; -/// @class VertexPerformanceWriter +/// @class VertexNTupleWriter /// /// Writes out the number of reconstructed primary vertices along with /// the number of primary vertices in detector acceptance as well as /// reconstructable primary vertices after track fitting. /// Additionally it matches the reco vertices to their truth vertices /// and write out the difference in x,y and z position. -class VertexPerformanceWriter final - : public WriterT> { +class VertexNTupleWriter final : public WriterT> { public: struct Config { /// Input vertex collection. @@ -90,9 +89,9 @@ class VertexPerformanceWriter final /// /// @param config Configuration struct /// @param level Message level declaration - VertexPerformanceWriter(const Config& config, Acts::Logging::Level level); + VertexNTupleWriter(const Config& config, Acts::Logging::Level level); - ~VertexPerformanceWriter() override; + ~VertexNTupleWriter() override; /// End-of-run hook ProcessCode finalize() override; diff --git a/Examples/Io/NuclearInteractions/include/ActsExamples/Io/NuclearInteractions/detail/NuclearInteractionParametrisation.hpp b/Examples/Io/Root/include/ActsExamples/Io/Root/detail/NuclearInteractionParametrisation.hpp similarity index 98% rename from Examples/Io/NuclearInteractions/include/ActsExamples/Io/NuclearInteractions/detail/NuclearInteractionParametrisation.hpp rename to Examples/Io/Root/include/ActsExamples/Io/Root/detail/NuclearInteractionParametrisation.hpp index b0a6174a0d6..e00fb79c63a 100644 --- a/Examples/Io/NuclearInteractions/include/ActsExamples/Io/NuclearInteractions/detail/NuclearInteractionParametrisation.hpp +++ b/Examples/Io/Root/include/ActsExamples/Io/Root/detail/NuclearInteractionParametrisation.hpp @@ -34,7 +34,7 @@ struct EventFraction { /// /// @param [in] event Tuple containing the initial particle, the particle /// before the interaction and all final state particles after the interaction - EventFraction(const ActsExamples::ExtractedSimulationProcess& event) + explicit EventFraction(const ActsExamples::ExtractedSimulationProcess& event) : initialParticle(event.initial), interactingParticle(event.before), finalParticles(event.after) {} diff --git a/Examples/Io/Root/src/RootAthenaDumpReader.cpp b/Examples/Io/Root/src/RootAthenaDumpReader.cpp index eea524fe544..a732bb3b49e 100644 --- a/Examples/Io/Root/src/RootAthenaDumpReader.cpp +++ b/Examples/Io/Root/src/RootAthenaDumpReader.cpp @@ -84,6 +84,11 @@ RootAthenaDumpReader::RootAthenaDumpReader( m_outputMeasurements.initialize(m_cfg.outputMeasurements); } + if (m_inputchain->GetBranch("SPtopStripDirection") == nullptr) { + ACTS_WARNING("Additional SP strip features not available"); + m_haveStripFeatures = false; + } + // Set the branches // Set object pointer @@ -192,13 +197,13 @@ RootAthenaDumpReader::RootAthenaDumpReader( m_inputchain->SetBranchAddress("SPcovz", SPcovz); m_inputchain->SetBranchAddress("SPhl_topstrip", SPhl_topstrip); m_inputchain->SetBranchAddress("SPhl_botstrip", SPhl_botstrip); - m_inputchain->SetBranchAddress("SPtopStripDirection", SPtopStripDirection); + m_inputchain->SetBranchAddress("SPtopStripDirection", &SPtopStripDirection); m_inputchain->SetBranchAddress("SPbottomStripDirection", - SPbottomStripDirection); + &SPbottomStripDirection); m_inputchain->SetBranchAddress("SPstripCenterDistance", - SPstripCenterDistance); + &SPstripCenterDistance); m_inputchain->SetBranchAddress("SPtopStripCenterPosition", - SPtopStripCenterPosition); + &SPtopStripCenterPosition); m_inputchain->SetBranchAddress("nTRK", &nTRK); m_inputchain->SetBranchAddress("TRKindex", TRKindex); @@ -578,21 +583,25 @@ RootAthenaDumpReader::readSpacepoints( sLinks.emplace_back(second); using Vector3f = Eigen::Matrix; - const Vector3f topStripDirection{SPtopStripDirection->at(isp).at(0), - SPtopStripDirection->at(isp).at(1), - SPtopStripDirection->at(isp).at(2)}; - const Vector3f bottomStripDirection{ - SPbottomStripDirection->at(isp).at(0), - SPbottomStripDirection->at(isp).at(1), - SPbottomStripDirection->at(isp).at(2)}; - const Vector3f stripCenterDistance{SPstripCenterDistance->at(isp).at(0), - SPstripCenterDistance->at(isp).at(1), - SPstripCenterDistance->at(isp).at(2)}; - const Vector3f topStripCenterPosition{ - SPtopStripCenterPosition->at(isp).at(0), - SPtopStripCenterPosition->at(isp).at(1), - SPtopStripCenterPosition->at(isp).at(2)}; - + Vector3f topStripDirection = Vector3f::Zero(); + Vector3f bottomStripDirection = Vector3f::Zero(); + Vector3f stripCenterDistance = Vector3f::Zero(); + Vector3f topStripCenterPosition = Vector3f::Zero(); + + if (m_haveStripFeatures) { + topStripDirection = {SPtopStripDirection->at(isp).at(0), + SPtopStripDirection->at(isp).at(1), + SPtopStripDirection->at(isp).at(2)}; + bottomStripDirection = {SPbottomStripDirection->at(isp).at(0), + SPbottomStripDirection->at(isp).at(1), + SPbottomStripDirection->at(isp).at(2)}; + stripCenterDistance = {SPstripCenterDistance->at(isp).at(0), + SPstripCenterDistance->at(isp).at(1), + SPstripCenterDistance->at(isp).at(2)}; + topStripCenterPosition = {SPtopStripCenterPosition->at(isp).at(0), + SPtopStripCenterPosition->at(isp).at(1), + SPtopStripCenterPosition->at(isp).at(2)}; + } sp = SimSpacePoint(globalPos, std::nullopt, spCovr, spCovz, std::nullopt, sLinks, SPhl_topstrip[isp], SPhl_botstrip[isp], topStripDirection.cast(), diff --git a/Examples/Io/NuclearInteractions/src/RootNuclearInteractionParametersWriter.cpp b/Examples/Io/Root/src/RootNuclearInteractionParametersWriter.cpp similarity index 96% rename from Examples/Io/NuclearInteractions/src/RootNuclearInteractionParametersWriter.cpp rename to Examples/Io/Root/src/RootNuclearInteractionParametersWriter.cpp index 64a324242c8..995f7bdf57d 100644 --- a/Examples/Io/NuclearInteractions/src/RootNuclearInteractionParametersWriter.cpp +++ b/Examples/Io/Root/src/RootNuclearInteractionParametersWriter.cpp @@ -6,7 +6,7 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. -#include "ActsExamples/Io/NuclearInteractions/RootNuclearInteractionParametersWriter.hpp" +#include "ActsExamples/Io/Root/RootNuclearInteractionParametersWriter.hpp" #include "Acts/Definitions/Algebra.hpp" #include "Acts/Definitions/Common.hpp" @@ -227,7 +227,7 @@ std::pair, std::vector> buildMap( } /// @brief This method builds decomposed cumulative probability distributions -/// out of a vector of proability distributions +/// out of a vector of probability distributions /// /// @param [in] histos Vector of probability distributions /// @@ -410,27 +410,27 @@ ActsExamples::RootNuclearInteractionParametersWriter::finalize() { gDirectory->WriteObject(&mapNIprob.second, "NuclearInteractionBinContents"); ACTS_DEBUG("Nuclear interaction probability parametrised"); - ACTS_DEBUG("Starting calulcation of probability of interaction type"); - // Write the interaction type proability + ACTS_DEBUG("Starting calculation of probability of interaction type"); + // Write the interaction type probability const auto softProbability = Parametrisation::softProbability(m_eventFractionCollection); gDirectory->WriteObject(&softProbability, "SoftInteraction"); - ACTS_DEBUG("Calulcation of probability of interaction type finished"); + ACTS_DEBUG("Calculation of probability of interaction type finished"); // Write the PDG id production distribution ACTS_DEBUG( - "Starting calulcation of transition probabilities between PDG IDs"); + "Starting calculation of transition probabilities between PDG IDs"); const auto pdgIdMap = Parametrisation::cumulativePDGprobability(m_eventFractionCollection); std::vector branchingPdgIds; std::vector targetPdgIds; std::vector targetPdgProbability; - for (const auto& targetPdgIdMap : pdgIdMap) { - for (const auto& producedPdgIdMap : targetPdgIdMap.second) { - branchingPdgIds.push_back(targetPdgIdMap.first); - targetPdgIds.push_back(producedPdgIdMap.first); - targetPdgProbability.push_back(producedPdgIdMap.second); + for (const auto& [targetKey, targetValue] : pdgIdMap) { + for (const auto& [producedKey, producedValue] : targetValue) { + branchingPdgIds.push_back(targetKey); + targetPdgIds.push_back(producedKey); + targetPdgProbability.push_back(producedValue); } } @@ -438,7 +438,7 @@ ActsExamples::RootNuclearInteractionParametersWriter::finalize() { gDirectory->WriteObject(&targetPdgIds, "TargetPdgIds"); gDirectory->WriteObject(&targetPdgProbability, "TargetPdgProbability"); ACTS_DEBUG( - "Calulcation of transition probabilities between PDG IDs finished"); + "Calculation of transition probabilities between PDG IDs finished"); // Write the multiplicity and kinematics distribution ACTS_DEBUG("Starting parametrisation of multiplicity probabilities"); diff --git a/Examples/Io/Root/src/RootParticleWriter.cpp b/Examples/Io/Root/src/RootParticleWriter.cpp index fbd1333c38c..436601eb97d 100644 --- a/Examples/Io/Root/src/RootParticleWriter.cpp +++ b/Examples/Io/Root/src/RootParticleWriter.cpp @@ -36,7 +36,7 @@ ActsExamples::RootParticleWriter::RootParticleWriter( throw std::invalid_argument("Missing tree name"); } - m_inputFinalParticles.maybeInitialize(m_cfg.inputFinalParticles); + m_inputParticlesFinal.maybeInitialize(m_cfg.inputParticlesFinal); // open root file and create the tree m_outputFile = TFile::Open(m_cfg.filePath.c_str(), m_cfg.fileMode.c_str()); @@ -73,7 +73,7 @@ ActsExamples::RootParticleWriter::RootParticleWriter( m_outputTree->Branch("generation", &m_generation); m_outputTree->Branch("sub_particle", &m_subParticle); - if (m_inputFinalParticles.isInitialized()) { + if (m_inputParticlesFinal.isInitialized()) { m_outputTree->Branch("e_loss", &m_eLoss); m_outputTree->Branch("total_x0", &m_pathInX0); m_outputTree->Branch("total_l0", &m_pathInL0); @@ -102,8 +102,8 @@ ActsExamples::ProcessCode ActsExamples::RootParticleWriter::finalize() { ActsExamples::ProcessCode ActsExamples::RootParticleWriter::writeT( const AlgorithmContext& ctx, const SimParticleContainer& particles) { const SimParticleContainer* finalParticles = nullptr; - if (m_inputFinalParticles.isInitialized()) { - finalParticles = &m_inputFinalParticles(ctx); + if (m_inputParticlesFinal.isInitialized()) { + finalParticles = &m_inputParticlesFinal(ctx); } // ensure exclusive access to tree/file while writing diff --git a/Examples/Io/Root/src/RootVertexReader.cpp b/Examples/Io/Root/src/RootVertexReader.cpp index 93a986a6c04..336e0364f9b 100644 --- a/Examples/Io/Root/src/RootVertexReader.cpp +++ b/Examples/Io/Root/src/RootVertexReader.cpp @@ -114,7 +114,7 @@ ProcessCode RootVertexReader::read(const AlgorithmContext& context) { for (unsigned int i = 0; i < nVertices; i++) { SimVertex v; - v.id = (*m_vertexId)[i]; + v.id = SimVertexBarcode{(*m_vertexId)[i]}; v.process = static_cast((*m_process)[i]); v.position4 = Acts::Vector4((*m_vx)[i] * Acts::UnitConstants::mm, (*m_vy)[i] * Acts::UnitConstants::mm, diff --git a/Examples/Io/Performance/ActsExamples/Io/Performance/SeedingPerformanceWriter.cpp b/Examples/Io/Root/src/SeedingPerformanceWriter.cpp similarity index 99% rename from Examples/Io/Performance/ActsExamples/Io/Performance/SeedingPerformanceWriter.cpp rename to Examples/Io/Root/src/SeedingPerformanceWriter.cpp index b2d87be68f9..4ac7ea269ef 100644 --- a/Examples/Io/Performance/ActsExamples/Io/Performance/SeedingPerformanceWriter.cpp +++ b/Examples/Io/Root/src/SeedingPerformanceWriter.cpp @@ -6,7 +6,7 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. -#include "SeedingPerformanceWriter.hpp" +#include "ActsExamples/Io/Root/SeedingPerformanceWriter.hpp" #include "Acts/Utilities/MultiIndex.hpp" #include "Acts/Utilities/VectorHelpers.hpp" diff --git a/Examples/Io/Performance/ActsExamples/Io/Performance/TrackFinderPerformanceWriter.cpp b/Examples/Io/Root/src/TrackFinderNTupleWriter.cpp similarity index 91% rename from Examples/Io/Performance/ActsExamples/Io/Performance/TrackFinderPerformanceWriter.cpp rename to Examples/Io/Root/src/TrackFinderNTupleWriter.cpp index abef2ef0664..3ddfc2b6f84 100644 --- a/Examples/Io/Performance/ActsExamples/Io/Performance/TrackFinderPerformanceWriter.cpp +++ b/Examples/Io/Root/src/TrackFinderNTupleWriter.cpp @@ -6,7 +6,7 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. -#include "ActsExamples/Io/Performance/TrackFinderPerformanceWriter.hpp" +#include "ActsExamples/Io/Root/TrackFinderNTupleWriter.hpp" #include "Acts/Definitions/Units.hpp" #include "ActsExamples/EventData/Index.hpp" @@ -32,7 +32,7 @@ #include #include -struct ActsExamples::TrackFinderPerformanceWriter::Impl { +struct ActsExamples::TrackFinderNTupleWriter::Impl { Config cfg; ReadDataHandle inputParticles; @@ -86,7 +86,7 @@ struct ActsExamples::TrackFinderPerformanceWriter::Impl { // extra logger reference for the logging macros const Acts::Logger& _logger; - Impl(TrackFinderPerformanceWriter* parent, Config&& c, const Acts::Logger& l) + Impl(TrackFinderNTupleWriter* parent, Config&& c, const Acts::Logger& l) : cfg(std::move(c)), inputParticles{parent, "InputParticles"}, inputMeasurementParticlesMap{parent, "InputMeasurementParticlesMap"}, @@ -153,7 +153,7 @@ struct ActsExamples::TrackFinderPerformanceWriter::Impl { const Acts::Logger& logger() const { return _logger; } - void write(std::uint64_t eventId, const TrackContainer& tracks, + void write(std::uint64_t eventId, const ConstTrackContainer& tracks, const SimParticleContainer& particles, const HitParticlesMap& hitParticlesMap, const TrackParticleMatching& trackParticleMatching) { @@ -265,18 +265,17 @@ struct ActsExamples::TrackFinderPerformanceWriter::Impl { } }; -ActsExamples::TrackFinderPerformanceWriter::TrackFinderPerformanceWriter( - ActsExamples::TrackFinderPerformanceWriter::Config config, +ActsExamples::TrackFinderNTupleWriter::TrackFinderNTupleWriter( + ActsExamples::TrackFinderNTupleWriter::Config config, Acts::Logging::Level level) - : WriterT(config.inputTracks, "TrackFinderPerformanceWriter", level), + : WriterT(config.inputTracks, "TrackFinderNTupleWriter", level), m_impl(std::make_unique(this, std::move(config), logger())) {} -ActsExamples::TrackFinderPerformanceWriter::~TrackFinderPerformanceWriter() = - default; +ActsExamples::TrackFinderNTupleWriter::~TrackFinderNTupleWriter() = default; -ActsExamples::ProcessCode ActsExamples::TrackFinderPerformanceWriter::writeT( +ActsExamples::ProcessCode ActsExamples::TrackFinderNTupleWriter::writeT( const ActsExamples::AlgorithmContext& ctx, - const ActsExamples::TrackContainer& tracks) { + const ActsExamples::ConstTrackContainer& tracks) { const auto& particles = m_impl->inputParticles(ctx); const auto& hitParticlesMap = m_impl->inputMeasurementParticlesMap(ctx); const auto& trackParticleMatching = m_impl->inputTrackParticleMatching(ctx); @@ -285,13 +284,12 @@ ActsExamples::ProcessCode ActsExamples::TrackFinderPerformanceWriter::writeT( return ProcessCode::SUCCESS; } -ActsExamples::ProcessCode -ActsExamples::TrackFinderPerformanceWriter::finalize() { +ActsExamples::ProcessCode ActsExamples::TrackFinderNTupleWriter::finalize() { m_impl->close(); return ProcessCode::SUCCESS; } -const ActsExamples::TrackFinderPerformanceWriter::Config& -ActsExamples::TrackFinderPerformanceWriter::config() const { +const ActsExamples::TrackFinderNTupleWriter::Config& +ActsExamples::TrackFinderNTupleWriter::config() const { return m_impl->cfg; } diff --git a/Examples/Io/Performance/ActsExamples/Io/Performance/CKFPerformanceWriter.cpp b/Examples/Io/Root/src/TrackFinderPerformanceWriter.cpp similarity index 95% rename from Examples/Io/Performance/ActsExamples/Io/Performance/CKFPerformanceWriter.cpp rename to Examples/Io/Root/src/TrackFinderPerformanceWriter.cpp index e7fa1525615..ecec2fd59ce 100644 --- a/Examples/Io/Performance/ActsExamples/Io/Performance/CKFPerformanceWriter.cpp +++ b/Examples/Io/Root/src/TrackFinderPerformanceWriter.cpp @@ -6,7 +6,7 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. -#include "ActsExamples/Io/Performance/CKFPerformanceWriter.hpp" +#include "ActsExamples/Io/Root/TrackFinderPerformanceWriter.hpp" #include "Acts/EventData/TrackParameters.hpp" #include "Acts/Utilities/VectorHelpers.hpp" @@ -27,9 +27,9 @@ using Acts::VectorHelpers::phi; namespace ActsExamples { -CKFPerformanceWriter::CKFPerformanceWriter(CKFPerformanceWriter::Config cfg, - Acts::Logging::Level lvl) - : WriterT(cfg.inputTracks, "CKFPerformanceWriter", lvl), +TrackFinderPerformanceWriter::TrackFinderPerformanceWriter( + TrackFinderPerformanceWriter::Config cfg, Acts::Logging::Level lvl) + : WriterT(cfg.inputTracks, "TrackFinderPerformanceWriter", lvl), m_cfg(std::move(cfg)), m_effPlotTool(m_cfg.effPlotToolConfig, lvl), m_fakeRatePlotTool(m_cfg.fakeRatePlotToolConfig, lvl), @@ -76,7 +76,7 @@ CKFPerformanceWriter::CKFPerformanceWriter(CKFPerformanceWriter::Config cfg, m_trackSummaryPlotTool.book(m_trackSummaryPlotCache); } -CKFPerformanceWriter::~CKFPerformanceWriter() { +TrackFinderPerformanceWriter::~TrackFinderPerformanceWriter() { m_effPlotTool.clear(m_effPlotCache); m_fakeRatePlotTool.clear(m_fakeRatePlotCache); m_duplicationPlotTool.clear(m_duplicationPlotCache); @@ -86,7 +86,7 @@ CKFPerformanceWriter::~CKFPerformanceWriter() { } } -ProcessCode CKFPerformanceWriter::finalize() { +ProcessCode TrackFinderPerformanceWriter::finalize() { float eff_tracks = static_cast(m_nTotalMatchedTracks) / m_nTotalTracks; float fakeRate_tracks = static_cast(m_nTotalFakeTracks) / m_nTotalTracks; @@ -147,8 +147,8 @@ ProcessCode CKFPerformanceWriter::finalize() { return ProcessCode::SUCCESS; } -ProcessCode CKFPerformanceWriter::writeT(const AlgorithmContext& ctx, - const ConstTrackContainer& tracks) { +ProcessCode TrackFinderPerformanceWriter::writeT( + const AlgorithmContext& ctx, const ConstTrackContainer& tracks) { // The number of majority particle hits and fitted track parameters using Acts::VectorHelpers::perp; diff --git a/Examples/Io/Performance/ActsExamples/Io/Performance/TrackFitterPerformanceWriter.cpp b/Examples/Io/Root/src/TrackFitterPerformanceWriter.cpp similarity index 98% rename from Examples/Io/Performance/ActsExamples/Io/Performance/TrackFitterPerformanceWriter.cpp rename to Examples/Io/Root/src/TrackFitterPerformanceWriter.cpp index 54441ad7aa8..2063f03b53b 100644 --- a/Examples/Io/Performance/ActsExamples/Io/Performance/TrackFitterPerformanceWriter.cpp +++ b/Examples/Io/Root/src/TrackFitterPerformanceWriter.cpp @@ -6,7 +6,7 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. -#include "ActsExamples/Io/Performance/TrackFitterPerformanceWriter.hpp" +#include "ActsExamples/Io/Root/TrackFitterPerformanceWriter.hpp" #include "Acts/EventData/MultiTrajectoryHelpers.hpp" #include "Acts/EventData/TrackParameters.hpp" diff --git a/Examples/Io/Performance/ActsExamples/Io/Performance/VertexPerformanceWriter.cpp b/Examples/Io/Root/src/VertexNTupleWriter.cpp similarity index 98% rename from Examples/Io/Performance/ActsExamples/Io/Performance/VertexPerformanceWriter.cpp rename to Examples/Io/Root/src/VertexNTupleWriter.cpp index dfc790433f9..c5a800741d3 100644 --- a/Examples/Io/Performance/ActsExamples/Io/Performance/VertexPerformanceWriter.cpp +++ b/Examples/Io/Root/src/VertexNTupleWriter.cpp @@ -6,7 +6,7 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. -#include "ActsExamples/Io/Performance/VertexPerformanceWriter.hpp" +#include "ActsExamples/Io/Root/VertexNTupleWriter.hpp" #include "Acts/Definitions/Algebra.hpp" #include "Acts/Definitions/TrackParametrization.hpp" @@ -106,9 +106,9 @@ std::uint32_t getNumberOfTruePriVertices( } // namespace -VertexPerformanceWriter::VertexPerformanceWriter( - const VertexPerformanceWriter::Config& config, Acts::Logging::Level level) - : WriterT(config.inputVertices, "VertexPerformanceWriter", level), +VertexNTupleWriter::VertexNTupleWriter(const VertexNTupleWriter::Config& config, + Acts::Logging::Level level) + : WriterT(config.inputVertices, "VertexNTupleWriter", level), m_cfg(config) { if (m_cfg.filePath.empty()) { throw std::invalid_argument("Missing output filename"); @@ -253,13 +253,13 @@ VertexPerformanceWriter::VertexPerformanceWriter( m_outputTree->Branch("trk_pullQOverPFitted", &m_pullQOverPFitted); } -VertexPerformanceWriter::~VertexPerformanceWriter() { +VertexNTupleWriter::~VertexNTupleWriter() { if (m_outputFile != nullptr) { m_outputFile->Close(); } } -ProcessCode VertexPerformanceWriter::finalize() { +ProcessCode VertexNTupleWriter::finalize() { m_outputFile->cd(); m_outputTree->Write(); m_outputFile->Close(); @@ -267,7 +267,7 @@ ProcessCode VertexPerformanceWriter::finalize() { return ProcessCode::SUCCESS; } -ProcessCode VertexPerformanceWriter::writeT( +ProcessCode VertexNTupleWriter::writeT( const AlgorithmContext& ctx, const std::vector& vertices) { const double nan = std::numeric_limits::quiet_NaN(); @@ -497,7 +497,7 @@ ProcessCode VertexPerformanceWriter::writeT( fmap[vtxId].second += weight; } double truthMajorityVertexTrackWeights = 0; - SimVertexBarcode truthMajorityVertexId = 0; + SimVertexBarcode truthMajorityVertexId{0}; for (const auto& [vtxId, counter] : fmap) { if (counter.second > truthMajorityVertexTrackWeights) { truthMajorityVertexId = vtxId; @@ -629,7 +629,8 @@ ProcessCode VertexPerformanceWriter::writeT( // Count number of reconstructible tracks on truth vertex int nTracksOnTruthVertex = 0; for (const auto& particle : selectedParticles) { - if (particle.particleId().vertexId() == truthVertex.vertexId()) { + if (static_cast(particle.particleId().vertexId()) == + truthVertex.vertexId()) { ++nTracksOnTruthVertex; } } diff --git a/Examples/Io/NuclearInteractions/src/detail/NuclearInteractionParametrisation.cpp b/Examples/Io/Root/src/detail/NuclearInteractionParametrisation.cpp similarity index 99% rename from Examples/Io/NuclearInteractions/src/detail/NuclearInteractionParametrisation.cpp rename to Examples/Io/Root/src/detail/NuclearInteractionParametrisation.cpp index f9df3d38f85..91f59c56648 100644 --- a/Examples/Io/NuclearInteractions/src/detail/NuclearInteractionParametrisation.cpp +++ b/Examples/Io/Root/src/detail/NuclearInteractionParametrisation.cpp @@ -6,7 +6,7 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. -#include "ActsExamples/Io/NuclearInteractions/detail/NuclearInteractionParametrisation.hpp" +#include "ActsExamples/Io/Root/detail/NuclearInteractionParametrisation.hpp" #include "Acts/Definitions/Common.hpp" #include "ActsFatras/EventData/Particle.hpp" diff --git a/Examples/Python/CMakeLists.txt b/Examples/Python/CMakeLists.txt index ff1e5901f43..0eb4b1ff4ec 100644 --- a/Examples/Python/CMakeLists.txt +++ b/Examples/Python/CMakeLists.txt @@ -21,6 +21,7 @@ pybind11_add_module(ActsPythonBindings src/Output.cpp src/Input.cpp src/Propagation.cpp + src/Navigation.cpp src/Generators.cpp src/Obj.cpp src/TruthTracking.cpp @@ -54,11 +55,9 @@ target_link_libraries( ActsExamplesDetectorTGeo ActsExamplesMagneticField ActsExamplesIoRoot - ActsExamplesIoNuclearInteractions ActsExamplesIoCsv ActsExamplesIoObj ActsExamplesIoJson - ActsExamplesIoPerformance ActsExamplesGenerators ActsExamplesPrinters ActsExamplesTrackFinding @@ -68,6 +67,10 @@ target_link_libraries( ActsExamplesDetectorTelescope ActsExamplesUtilities ActsExamplesAmbiguityResolution + ActsExamplesTruthTracking + ActsExamplesDigitization + ActsExamplesPropagation + ActsExamplesMaterialMapping ) set(py_files diff --git a/Examples/Python/python/acts/examples/odd.py b/Examples/Python/python/acts/examples/odd.py index a28058af78b..5e187948ee2 100644 --- a/Examples/Python/python/acts/examples/odd.py +++ b/Examples/Python/python/acts/examples/odd.py @@ -90,7 +90,7 @@ def geoid_hook(geoid, surface): dd4hepConfig = acts.examples.dd4hep.DD4hepGeometryService.Config( xmlFileNames=[str(odd_xml)], logLevel=customLogLevel(), - dd4hepLogLevel=customLogLevel(), + dd4hepLogLevel=customLogLevel(minLevel=acts.logging.WARNING), geometryIdentifierHook=acts.GeometryIdentifierHook(geoid_hook), ) detector = acts.examples.dd4hep.DD4hepDetector() diff --git a/Examples/Python/python/acts/examples/reconstruction.py b/Examples/Python/python/acts/examples/reconstruction.py index 3bb898ca998..fd02c6bddac 100644 --- a/Examples/Python/python/acts/examples/reconstruction.py +++ b/Examples/Python/python/acts/examples/reconstruction.py @@ -2,7 +2,6 @@ from typing import Optional, Union, List from enum import Enum from collections import namedtuple -import math import acts import acts.examples @@ -14,12 +13,6 @@ "Default TruthSmeared TruthEstimated Orthogonal HoughTransform Gbts Hashing", ) -TruthSeedRanges = namedtuple( - "TruthSeedRanges", - ["rho", "z", "phi", "eta", "absEta", "pt", "nHits"], - defaults=[(None, None)] * 7, -) - ParticleSmearingSigmas = namedtuple( "ParticleSmearingSigmas", ["d0", "d0PtA", "d0PtB", "z0", "z0PtA", "z0PtB", "t0", "phi", "theta", "ptRel"], @@ -231,7 +224,6 @@ class VertexFinder(Enum): @acts.examples.NamedTypeArgs( seedingAlgorithm=SeedingAlgorithm, - truthSeedRanges=TruthSeedRanges, particleSmearingSigmas=ParticleSmearingSigmas, seedFinderConfigArg=SeedFinderConfigArg, seedFinderOptionsArg=SeedFinderOptionsArg, @@ -251,7 +243,6 @@ def addSeeding( layerMappingConfigFile: Optional[Union[Path, str]] = None, connector_inputConfigFile: Optional[Union[Path, str]] = None, seedingAlgorithm: SeedingAlgorithm = SeedingAlgorithm.Default, - truthSeedRanges: Optional[TruthSeedRanges] = TruthSeedRanges(), particleSmearingSigmas: ParticleSmearingSigmas = ParticleSmearingSigmas(), initialSigmas: Optional[list] = None, initialSigmaPtRel: Optional[float] = None, @@ -273,6 +264,7 @@ def addSeeding( acts.ParticleHypothesis ] = acts.ParticleHypothesis.pion, inputParticles: str = "particles", + selectedParticles: str = "particles_selected", outputDirRoot: Optional[Union[Path, str]] = None, outputDirCsv: Optional[Union[Path, str]] = None, logLevel: Optional[acts.logging.Level] = None, @@ -289,10 +281,6 @@ def addSeeding( Json file for space point geometry selection. Not required for SeedingAlgorithm.TruthSmeared. seedingAlgorithm : SeedingAlgorithm, Default seeding algorithm to use: one of Default (no truth information used), TruthSmeared, TruthEstimated - truthSeedRanges : TruthSeedRanges(rho, z, phi, eta, absEta, pt, nHits) - TruthSeedSelector configuration. Each range is specified as a tuple of (min,max). - Defaults of no cuts specified in Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/TruthSeedSelector.hpp - If specified as None, don't run ParticleSmearing at all (and use addCKFTracks(selectedParticles="particles")) particleSmearingSigmas : ParticleSmearingSigmas(d0, d0PtA, d0PtB, z0, z0PtA, z0PtB, t0, phi, theta, ptRel) ParticleSmearing configuration. Defaults specified in Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSmearing.hpp @@ -324,6 +312,8 @@ def addSeeding( The hypothesis used for track finding. Defaults to pion. inputParticles : str, "particles" input particles name in the WhiteBoard + selectedParticles : str, "particles_selected" + selected particles name in the WhiteBoard outputDirRoot : Path|str, path, None the output folder for the Root output, None triggers no output logLevel : acts.logging.Level, None @@ -336,18 +326,6 @@ def addSeeding( logger = acts.logging.getLogger("addSeeding") logger.setLevel(logLevel) - if truthSeedRanges is not None: - selectedParticles = "truth_seeds_selected" - addSeedingTruthSelection( - s, - inputParticles, - selectedParticles, - truthSeedRanges, - logLevel, - ) - else: - selectedParticles = inputParticles - # Create starting parameters from either particle smearing or combined seed # finding and track parameters estimation if seedingAlgorithm == SeedingAlgorithm.TruthSmeared: @@ -506,41 +484,6 @@ def addSeeding( return s -def addSeedingTruthSelection( - s: acts.examples.Sequencer, - inputParticles: str, - outputParticles: str, - truthSeedRanges: TruthSeedRanges, - logLevel: acts.logging.Level = None, -): - """adds truth particles filtering before filtering - For parameters description see addSeeding - """ - selAlg = acts.examples.TruthSeedSelector( - **acts.examples.defaultKWArgs( - ptMin=truthSeedRanges.pt[0], - ptMax=truthSeedRanges.pt[1], - etaMin=truthSeedRanges.eta[0], - etaMax=truthSeedRanges.eta[1], - nHitsMin=truthSeedRanges.nHits[0], - nHitsMax=truthSeedRanges.nHits[1], - rhoMin=truthSeedRanges.rho[0], - rhoMax=truthSeedRanges.rho[1], - zMin=truthSeedRanges.z[0], - zMax=truthSeedRanges.z[1], - phiMin=truthSeedRanges.phi[0], - phiMax=truthSeedRanges.phi[1], - absEtaMin=truthSeedRanges.absEta[0], - absEtaMax=truthSeedRanges.absEta[1], - ), - level=logLevel, - inputParticles=inputParticles, - inputMeasurementParticlesMap="measurement_particles_map", - outputParticles=outputParticles, - ) - s.addAlgorithm(selAlg) - - def addTruthSmearedSeeding( s: acts.examples.Sequencer, rnd: Optional[acts.examples.RandomNumbers], @@ -1233,7 +1176,7 @@ def addSeedFilterML( from acts.examples.onnx import SeedFilterMLAlgorithm inputParticles = "particles" - selectedParticles = "truth_seeds_selected" + selectedParticles = "particles_selected" seeds = "seeds" estParams = "estimatedparameters" @@ -1375,8 +1318,13 @@ def addTruthTrackingGsf( ) -> None: customLogLevel = acts.examples.defaultLogging(s, logLevel) + # NOTE we specify clampToRange as True to silence warnings in the test about + # queries to the loss distribution outside the specified range, since no dedicated + # approximation for the ODD is done yet. + bha = acts.examples.AtlasBetheHeitlerApprox.makeDefault(clampToRange=True) + gsfOptions = { - "betheHeitlerApprox": acts.examples.AtlasBetheHeitlerApprox.makeDefault(), + "betheHeitlerApprox": bha, "maxComponents": 12, "componentMergeMethod": acts.examples.ComponentMergeMethod.maxWeight, "mixtureReductionAlgorithm": acts.examples.MixtureReductionAlgorithm.KLDistance, @@ -1433,9 +1381,11 @@ def addCKFTracks( reverseSearch: bool = False, outputDirCsv: Optional[Union[Path, str]] = None, outputDirRoot: Optional[Union[Path, str]] = None, - writeTrajectories: bool = True, - logLevel: Optional[acts.logging.Level] = None, + writeTrackSummary: bool = True, + writeTrackStates: bool = False, + writePerformance: bool = True, writeCovMat=False, + logLevel: Optional[acts.logging.Level] = None, ) -> None: """This function steers the seeding @@ -1579,11 +1529,12 @@ def addCKFTracks( tracks=trackFinder.config.outputTracks, outputDirCsv=outputDirCsv, outputDirRoot=outputDirRoot, - writeStates=writeTrajectories, - writeSummary=writeTrajectories, - writeCKFperformance=True, - logLevel=logLevel, + writeSummary=writeTrackSummary, + writeStates=writeTrackStates, + writeFitterPerformance=writePerformance, + writeFinderPerformance=writePerformance, writeCovMat=writeCovMat, + logLevel=logLevel, ) return s @@ -1655,9 +1606,10 @@ def addTrackWriters( tracks: str = "tracks", outputDirCsv: Optional[Union[Path, str]] = None, outputDirRoot: Optional[Union[Path, str]] = None, - writeStates: bool = True, writeSummary: bool = True, - writeCKFperformance: bool = True, + writeStates: bool = False, + writeFitterPerformance: bool = False, + writeFinderPerformance: bool = False, logLevel: Optional[acts.logging.Level] = None, writeCovMat=False, ): @@ -1668,15 +1620,22 @@ def addTrackWriters( if not outputDirRoot.exists(): outputDirRoot.mkdir() + if writeSummary: + trackSummaryWriter = acts.examples.RootTrackSummaryWriter( + level=customLogLevel(), + inputTracks=tracks, + inputParticles="particles_selected", + inputTrackParticleMatching="track_particle_matching", + filePath=str(outputDirRoot / f"tracksummary_{name}.root"), + treeName="tracksummary", + writeCovMat=writeCovMat, + ) + s.addWriter(trackSummaryWriter) + if writeStates: - # write track states from CKF trackStatesWriter = acts.examples.RootTrackStatesWriter( level=customLogLevel(), inputTracks=tracks, - # @note The full particles collection is used here to avoid lots of warnings - # since the unselected CKF track might have a majority particle not in the - # filtered particle collection. This could be avoided when a separate track - # selection algorithm is used. inputParticles="particles_selected", inputTrackParticleMatching="track_particle_matching", inputSimHits="simhits", @@ -1686,34 +1645,26 @@ def addTrackWriters( ) s.addWriter(trackStatesWriter) - if writeSummary: - # write track summary from CKF - trackSummaryWriter = acts.examples.RootTrackSummaryWriter( + if writeFitterPerformance: + trackFitterPerformanceWriter = acts.examples.TrackFitterPerformanceWriter( level=customLogLevel(), inputTracks=tracks, - # @note The full particles collection is used here to avoid lots of warnings - # since the unselected CKF track might have a majority particle not in the - # filtered particle collection. This could be avoided when a separate track - # selection algorithm is used. inputParticles="particles_selected", inputTrackParticleMatching="track_particle_matching", - filePath=str(outputDirRoot / f"tracksummary_{name}.root"), - treeName="tracksummary", - writeCovMat=writeCovMat, + filePath=str(outputDirRoot / f"performance_fitting_{name}.root"), ) - s.addWriter(trackSummaryWriter) + s.addWriter(trackFitterPerformanceWriter) - if writeCKFperformance: - # Write CKF performance data - ckfPerfWriter = acts.examples.CKFPerformanceWriter( + if writeFinderPerformance: + trackFinderPerfWriter = acts.examples.TrackFinderPerformanceWriter( level=customLogLevel(), inputTracks=tracks, - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputTrackParticleMatching="track_particle_matching", inputParticleTrackMatching="particle_track_matching", - filePath=str(outputDirRoot / f"performance_{name}.root"), + filePath=str(outputDirRoot / f"performance_finding_{name}.root"), ) - s.addWriter(ckfPerfWriter) + s.addWriter(trackFinderPerfWriter) if outputDirCsv is not None: outputDirCsv = Path(outputDirCsv) @@ -1897,7 +1848,7 @@ def addExaTrkX( # Write truth track finding / seeding performance if outputDirRoot is not None: s.addWriter( - acts.examples.TrackFinderPerformanceWriter( + acts.examples.TrackFinderNTupleWriter( level=customLogLevel(), inputProtoTracks=findingAlg.config.outputProtoTracks, # the original selected particles after digitization @@ -1920,9 +1871,11 @@ def addAmbiguityResolution( tracks: str = "tracks", outputDirCsv: Optional[Union[Path, str]] = None, outputDirRoot: Optional[Union[Path, str]] = None, - writeTrajectories: bool = True, - logLevel: Optional[acts.logging.Level] = None, + writeTrackSummary: bool = True, + writeTrackStates: bool = False, + writePerformance: bool = True, writeCovMat=False, + logLevel: Optional[acts.logging.Level] = None, ) -> None: from acts.examples import GreedyAmbiguityResolutionAlgorithm @@ -1964,11 +1917,12 @@ def addAmbiguityResolution( tracks=alg.config.outputTracks, outputDirCsv=outputDirCsv, outputDirRoot=outputDirRoot, - writeStates=writeTrajectories, - writeSummary=writeTrajectories, - writeCKFperformance=True, - logLevel=logLevel, + writeSummary=writeTrackStates, + writeStates=writeTrackSummary, + writeFitterPerformance=writePerformance, + writeFinderPerformance=writePerformance, writeCovMat=writeCovMat, + logLevel=logLevel, ) return s @@ -1984,9 +1938,11 @@ def addScoreBasedAmbiguityResolution( outputDirCsv: Optional[Union[Path, str]] = None, outputDirRoot: Optional[Union[Path, str]] = None, ambiVolumeFile: Optional[Union[Path, str]] = None, - writeTrajectories: bool = True, - logLevel: Optional[acts.logging.Level] = None, + writeTrackSummary: bool = True, + writeTrackStates: bool = False, + writePerformance: bool = True, writeCovMat=False, + logLevel: Optional[acts.logging.Level] = None, ) -> None: from acts.examples import ScoreBasedAmbiguityResolutionAlgorithm @@ -2018,11 +1974,12 @@ def addScoreBasedAmbiguityResolution( tracks=algScoreBased.config.outputTracks, outputDirCsv=outputDirCsv, outputDirRoot=outputDirRoot, - writeStates=writeTrajectories, - writeSummary=writeTrajectories, - writeCKFperformance=True, - logLevel=logLevel, + writeSummary=writeTrackStates, + writeStates=writeTrackSummary, + writeFitterPerformance=writePerformance, + writeFinderPerformance=writePerformance, writeCovMat=writeCovMat, + logLevel=logLevel, ) return s @@ -2037,7 +1994,10 @@ def addAmbiguityResolutionML( onnxModelFile: Optional[Union[Path, str]] = None, outputDirCsv: Optional[Union[Path, str]] = None, outputDirRoot: Optional[Union[Path, str]] = None, - writeTrajectories: bool = True, + writeTrackSummary: bool = True, + writeTrackStates: bool = False, + writePerformance: bool = True, + writeCovMat=False, logLevel: Optional[acts.logging.Level] = None, ) -> None: from acts.examples.onnx import AmbiguityResolutionMLAlgorithm @@ -2075,9 +2035,11 @@ def addAmbiguityResolutionML( tracks=algGreedy.config.outputTracks, outputDirCsv=outputDirCsv, outputDirRoot=outputDirRoot, - writeStates=writeTrajectories, - writeSummary=writeTrajectories, - writeCKFperformance=True, + writeSummary=writeTrackStates, + writeStates=writeTrackSummary, + writeFitterPerformance=writePerformance, + writeFinderPerformance=writePerformance, + writeCovMat=writeCovMat, logLevel=logLevel, ) @@ -2093,7 +2055,10 @@ def addAmbiguityResolutionMLDBScan( onnxModelFile: Optional[Union[Path, str]] = None, outputDirCsv: Optional[Union[Path, str]] = None, outputDirRoot: Optional[Union[Path, str]] = None, - writeTrajectories: bool = True, + writeTrackSummary: bool = True, + writeTrackStates: bool = False, + writePerformance: bool = True, + writeCovMat=False, logLevel: Optional[acts.logging.Level] = None, ) -> None: from acts.examples import AmbiguityResolutionMLDBScanAlgorithm @@ -2119,9 +2084,11 @@ def addAmbiguityResolutionMLDBScan( trajectories=alg.config.outputTracks, outputDirRoot=outputDirRoot, outputDirCsv=outputDirCsv, - writeStates=writeTrajectories, - writeSummary=writeTrajectories, - writeCKFperformance=True, + writeSummary=writeTrackStates, + writeStates=writeTrackSummary, + writeFitterPerformance=writePerformance, + writeFinderPerformance=writePerformance, + writeCovMat=writeCovMat, logLevel=logLevel, ) @@ -2180,7 +2147,7 @@ def addVertexFitting( VertexFitterAlgorithm, IterativeVertexFinderAlgorithm, AdaptiveMultiVertexFinderAlgorithm, - VertexPerformanceWriter, + VertexNTupleWriter, ) customLogLevel = acts.examples.defaultLogging(s, logLevel) @@ -2263,7 +2230,7 @@ def addVertexFitting( if not outputDirRoot.exists(): outputDirRoot.mkdir() s.addWriter( - VertexPerformanceWriter( + VertexNTupleWriter( level=customLogLevel(), inputVertices=outputVertices, inputTracks=tracks, @@ -2289,7 +2256,7 @@ def addSingleSeedVertexFinding( ) -> None: from acts.examples import ( SingleSeedVertexFinderAlgorithm, - VertexPerformanceWriter, + VertexNTupleWriter, ) customLogLevel = acts.examples.defaultLogging(s, logLevel) @@ -2310,7 +2277,7 @@ def addSingleSeedVertexFinding( outputDirRoot.mkdir() s.addWriter( - VertexPerformanceWriter( + VertexNTupleWriter( level=customLogLevel(), inputAllTruthParticles=inputParticles, inputSelectedTruthParticles=selectedParticles, diff --git a/Examples/Python/python/acts/examples/simulation.py b/Examples/Python/python/acts/examples/simulation.py index b3b1046dc70..8f6b6d0e603 100644 --- a/Examples/Python/python/acts/examples/simulation.py +++ b/Examples/Python/python/acts/examples/simulation.py @@ -355,7 +355,8 @@ def addParticleSelection( config: ParticleSelectorConfig, inputParticles: str, outputParticles: str, - inputMeasurementParticlesMap: str = "", + inputParticlesFinal: Optional[str] = None, + outputParticlesFinal: Optional[str] = None, logLevel: Optional[acts.logging.Level] = None, ) -> None: """ @@ -371,12 +372,18 @@ def addParticleSelection( the identifier for the input particles to be selected outputParticles: str the identifier for the final selected particle collection + inputParticlesFinal: str, None + the identifier for the input final particles to be selected + outputParticlesFinal: str, None + the identifier for the final selected final particle collection """ customLogLevel = acts.examples.defaultLogging(s, logLevel) s.addAlgorithm( acts.examples.ParticleSelector( **acts.examples.defaultKWArgs( + inputParticlesFinal=inputParticlesFinal, + outputParticlesFinal=outputParticlesFinal, rhoMin=config.rho[0], rhoMax=config.rho[1], absZMin=config.absZ[0], @@ -402,7 +409,6 @@ def addParticleSelection( level=customLogLevel(), inputParticles=inputParticles, outputParticles=outputParticles, - inputMeasurementParticlesMap=inputMeasurementParticlesMap, ) ) @@ -489,27 +495,22 @@ def addFatras( # Selector if postSelectParticles is not None: particlesInitial = "fatras_particles_initial_selected" - addParticleSelection( - s, - postSelectParticles, - inputParticles=alg.config.outputParticlesInitial, - outputParticles=particlesInitial, - ) - particlesFinal = "fatras_particles_final_selected" addParticleSelection( s, postSelectParticles, - inputParticles=alg.config.outputParticlesFinal, - outputParticles=particlesFinal, + inputParticles=outputParticlesInitial, + inputParticlesFinal=outputParticlesFinal, + outputParticles=particlesInitial, + outputParticlesFinal=particlesFinal, ) - s.addWhiteboardAlias("particles_selected", particlesFinal) + s.addWhiteboardAlias("particles_selected", particlesInitial) else: - particlesInitial = alg.config.outputParticlesInitial - particlesFinal = alg.config.outputParticlesFinal + particlesInitial = outputParticlesInitial + particlesFinal = outputParticlesFinal # Only add alias for 'particles_initial' as this is the one we use most - s.addWhiteboardAlias("particles", particlesInitial) + s.addWhiteboardAlias("particles", outputParticlesInitial) # Output addSimWriters( @@ -573,7 +574,7 @@ def addSimWriters( acts.examples.RootParticleWriter( level=customLogLevel(), inputParticles=particlesInitial, - inputFinalParticles=particlesFinal, + inputParticlesFinal=particlesFinal, filePath=str(outputDirRoot / "particles_simulation.root"), ) ) @@ -739,27 +740,22 @@ def addGeant4( # Selector if postSelectParticles is not None: particlesInitial = "geant4_particles_initial_postselected" - addParticleSelection( - s, - postSelectParticles, - inputParticles=alg.config.outputParticlesInitial, - outputParticles=particlesInitial, - ) - particlesFinal = "geant4_particles_final_postselected" addParticleSelection( s, postSelectParticles, - inputParticles=alg.config.outputParticlesFinal, - outputParticles=particlesFinal, + inputParticles=outputParticlesInitial, + inputParticlesFinal=outputParticlesFinal, + outputParticles=particlesInitial, + outputParticlesFinal=particlesFinal, ) - s.addWhiteboardAlias("particles_selected", particlesFinal) + s.addWhiteboardAlias("particles_selected", particlesInitial) else: - particlesInitial = alg.config.outputParticlesInitial - particlesFinal = alg.config.outputParticlesFinal + particlesInitial = outputParticlesInitial + particlesFinal = outputParticlesFinal # Only add alias for 'particles_initial' as this is the one we use most - s.addWhiteboardAlias("particles", particlesInitial) + s.addWhiteboardAlias("particles", outputParticlesInitial) # Output addSimWriters( diff --git a/Examples/Python/src/Generators.cpp b/Examples/Python/src/Generators.cpp index ad4a7034840..800c912aa89 100644 --- a/Examples/Python/src/Generators.cpp +++ b/Examples/Python/src/Generators.cpp @@ -7,25 +7,21 @@ // file, You can obtain one at https://mozilla.org/MPL/2.0/. #include "Acts/Definitions/Algebra.hpp" -#include "Acts/Definitions/PdgParticle.hpp" #include "Acts/Plugins/Python/Utilities.hpp" +#include "Acts/Utilities/AngleHelpers.hpp" #include "Acts/Utilities/Logger.hpp" #include "ActsExamples/EventData/SimParticle.hpp" -#include "ActsExamples/Framework/RandomNumbers.hpp" #include "ActsExamples/Generators/EventGenerator.hpp" #include "ActsExamples/Generators/MultiplicityGenerators.hpp" #include "ActsExamples/Generators/ParametricParticleGenerator.hpp" #include "ActsExamples/Generators/VertexGenerators.hpp" -#include #include #include #include #include -#include #include #include -#include #include #include @@ -36,16 +32,6 @@ class IReader; namespace py = pybind11; -namespace { -double thetaToEta(double theta) { - assert(theta != 0); - return -1 * std::log(std::tan(theta / 2.)); -} -double etaToTheta(double eta) { - return 2 * std::atan(std::exp(-eta)); -} -} // namespace - namespace Acts::Python { void addGenerators(Context& ctx) { @@ -218,12 +204,12 @@ void addGenerators(Context& ctx) { .def_property( "eta", [](Config& cfg) { - return std::pair{thetaToEta(cfg.thetaMin), - thetaToEta(cfg.thetaMax)}; + return std::pair{Acts::AngleHelpers::etaFromTheta(cfg.thetaMin), + Acts::AngleHelpers::etaFromTheta(cfg.thetaMax)}; }, [](Config& cfg, std::pair value) { - cfg.thetaMin = etaToTheta(value.first); - cfg.thetaMax = etaToTheta(value.second); + cfg.thetaMin = Acts::AngleHelpers::thetaFromEta(value.first); + cfg.thetaMax = Acts::AngleHelpers::thetaFromEta(value.second); }); } diff --git a/Examples/Python/src/ModuleEntry.cpp b/Examples/Python/src/ModuleEntry.cpp index 1a0e27db907..a74d277f7a5 100644 --- a/Examples/Python/src/ModuleEntry.cpp +++ b/Examples/Python/src/ModuleEntry.cpp @@ -50,6 +50,7 @@ void addBinning(Context& ctx); void addEventData(Context& ctx); void addPropagation(Context& ctx); +void addNavigation(Context& ctx); void addGeometry(Context& ctx); void addGeometryBuildingGen1(Context& ctx); @@ -123,6 +124,7 @@ PYBIND11_MODULE(ActsPythonBindings, m) { addOutput(ctx); addPropagation(ctx); + addNavigation(ctx); addGeometryBuildingGen1(ctx); addGeometry(ctx); addExperimentalGeometry(ctx); diff --git a/Examples/Python/src/Navigation.cpp b/Examples/Python/src/Navigation.cpp new file mode 100644 index 00000000000..ac2f1a77ef6 --- /dev/null +++ b/Examples/Python/src/Navigation.cpp @@ -0,0 +1,203 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include "Acts/Geometry/CylinderVolumeBounds.hpp" +#include "Acts/Geometry/NavigationPolicyFactory.hpp" +#include "Acts/Geometry/TrackingVolume.hpp" +#include "Acts/Navigation/SurfaceArrayNavigationPolicy.hpp" +#include "Acts/Navigation/TryAllNavigationPolicy.hpp" +#include "Acts/Plugins/Python/Utilities.hpp" +#include "Acts/Surfaces/CylinderBounds.hpp" +#include "Acts/Surfaces/CylinderSurface.hpp" +#include "Acts/Utilities/Logger.hpp" +#include "Acts/Utilities/TypeTag.hpp" + +#include +#include +#include + +#include +#include +#include + +namespace py = pybind11; +using namespace pybind11::literals; + +namespace Acts::Python { + +struct AnyNavigationPolicyFactory : public Acts::NavigationPolicyFactory { + virtual std::unique_ptr add( + TypeTag /*type*/) = 0; + + virtual std::unique_ptr add( + TypeTag /*type*/, + SurfaceArrayNavigationPolicy::Config config) = 0; +}; + +template , + typename... Policies> +struct NavigationPolicyFactoryT : public AnyNavigationPolicyFactory { + NavigationPolicyFactoryT(Factory impl) + requires(sizeof...(Policies) > 0) + : m_impl(std::move(impl)) {} + + NavigationPolicyFactoryT() + requires(sizeof...(Policies) == 0) + : m_impl{} {} + + std::unique_ptr add( + TypeTag /*type*/) override { + return add(); + } + + std::unique_ptr add( + TypeTag /*type*/, + SurfaceArrayNavigationPolicy::Config config) override { + return add(std::move(config)); + } + + std::unique_ptr build( + const GeometryContext& gctx, const TrackingVolume& volume, + const Logger& logger) const override { + if constexpr (sizeof...(Policies) > 0) { + return m_impl.build(gctx, volume, logger); + } else { + throw std::runtime_error("No policies added to the factory"); + } + } + + private: + template + std::unique_ptr add(Args&&... args) { + if constexpr (!((std::is_same_v || ...))) { + auto impl = + std::move(m_impl).template add(std::forward(args)...); + return std::make_unique< + NavigationPolicyFactoryT>( + std::move(impl)); + } else { + throw std::invalid_argument("Policy already added to the factory"); + } + } + + Factory m_impl; +}; + +class NavigationPolicyFactory : public Acts::NavigationPolicyFactory { + public: + // This overload is for all the navigation policies that don't have extra + // arguments + NavigationPolicyFactory& addNoArguments(const py::object& cls) { + auto m = py::module_::import("acts"); + if (py::object o = m.attr("TryAllNavigationPolicy"); cls.is(o)) { + m_impl = m_impl->add(Type); + } + // Add other policies here + return *this; + } + + NavigationPolicyFactory& addSurfaceArray( + const py::object& /*cls*/, + const SurfaceArrayNavigationPolicy::Config& config) { + m_impl = m_impl->add(Type, config); + return *this; + } + + std::unique_ptr build( + const GeometryContext& gctx, const TrackingVolume& volume, + const Logger& logger) const override { + return m_impl->build(gctx, volume, logger); + } + + private: + std::unique_ptr m_impl = + std::make_unique>(); +}; + +namespace Test { +class DetectorElementStub : public DetectorElementBase { + public: + DetectorElementStub() : DetectorElementBase() {} + + const Transform3& transform(const GeometryContext&) const override { + return m_transform; + } + + /// Return surface representation - const return pattern + const Surface& surface() const override { + throw std::runtime_error("Not implemented"); + } + + /// Non-const return pattern + Surface& surface() override { throw std::runtime_error("Not implemented"); } + + /// Returns the thickness of the module + /// @return double that indicates the thickness of the module + double thickness() const override { return 0; } + + private: + Transform3 m_transform; +}; + +} // namespace Test + +void addNavigation(Context& ctx) { + auto m = ctx.get("main"); + + py::class_>( + m, "_NavigationPolicyFactory"); + + py::class_(m, "TryAllNavigationPolicy"); + + py::class_>( + m, "NavigationPolicyFactory") + // only to mirror the C++ API + .def_static("make", []() { return NavigationPolicyFactory{}; }) + .def("add", &NavigationPolicyFactory::addNoArguments) + .def("add", &NavigationPolicyFactory::addSurfaceArray) + .def("_buildTest", [](NavigationPolicyFactory& self) { + auto vol1 = std::make_shared( + Transform3::Identity(), + std::make_shared(30, 40, 100)); + vol1->setVolumeName("TestVolume"); + + auto detElem = std::make_unique(); + + auto surface = Surface::makeShared( + Transform3::Identity(), std::make_shared(30, 40)); + surface->assignDetectorElement(*detElem); + + vol1->addSurface(std::move(surface)); + + std::unique_ptr result = + self.build(GeometryContext{}, *vol1, + *getDefaultLogger("Test", Logging::VERBOSE)); + }); + + { + auto saPolicy = py::class_( + m, "SurfaceArrayNavigationPolicy"); + + using LayerType = SurfaceArrayNavigationPolicy::LayerType; + py::enum_(saPolicy, "LayerType") + .value("Cylinder", LayerType::Cylinder) + .value("Disc", LayerType::Disc) + .value("Plane", LayerType::Plane); + + using Config = SurfaceArrayNavigationPolicy::Config; + auto c = py::class_(saPolicy, "Config").def(py::init<>()); + ACTS_PYTHON_STRUCT_BEGIN(c, Config); + ACTS_PYTHON_MEMBER(layerType); + ACTS_PYTHON_MEMBER(bins); + ACTS_PYTHON_STRUCT_END(); + } +} + +} // namespace Acts::Python diff --git a/Examples/Python/src/Output.cpp b/Examples/Python/src/Output.cpp index 11472d8e203..dce56dc681e 100644 --- a/Examples/Python/src/Output.cpp +++ b/Examples/Python/src/Output.cpp @@ -26,16 +26,11 @@ #include "ActsExamples/Io/Csv/CsvTrackParameterWriter.hpp" #include "ActsExamples/Io/Csv/CsvTrackWriter.hpp" #include "ActsExamples/Io/Csv/CsvTrackingGeometryWriter.hpp" -#include "ActsExamples/Io/NuclearInteractions/RootNuclearInteractionParametersWriter.hpp" -#include "ActsExamples/Io/Performance/CKFPerformanceWriter.hpp" -#include "ActsExamples/Io/Performance/SeedingPerformanceWriter.hpp" -#include "ActsExamples/Io/Performance/TrackFinderPerformanceWriter.hpp" -#include "ActsExamples/Io/Performance/TrackFitterPerformanceWriter.hpp" -#include "ActsExamples/Io/Performance/VertexPerformanceWriter.hpp" #include "ActsExamples/Io/Root/RootBFieldWriter.hpp" #include "ActsExamples/Io/Root/RootMaterialTrackWriter.hpp" #include "ActsExamples/Io/Root/RootMaterialWriter.hpp" #include "ActsExamples/Io/Root/RootMeasurementWriter.hpp" +#include "ActsExamples/Io/Root/RootNuclearInteractionParametersWriter.hpp" #include "ActsExamples/Io/Root/RootParticleWriter.hpp" #include "ActsExamples/Io/Root/RootPropagationStepsWriter.hpp" #include "ActsExamples/Io/Root/RootPropagationSummaryWriter.hpp" @@ -46,6 +41,11 @@ #include "ActsExamples/Io/Root/RootTrackStatesWriter.hpp" #include "ActsExamples/Io/Root/RootTrackSummaryWriter.hpp" #include "ActsExamples/Io/Root/RootVertexWriter.hpp" +#include "ActsExamples/Io/Root/SeedingPerformanceWriter.hpp" +#include "ActsExamples/Io/Root/TrackFinderNTupleWriter.hpp" +#include "ActsExamples/Io/Root/TrackFinderPerformanceWriter.hpp" +#include "ActsExamples/Io/Root/TrackFitterPerformanceWriter.hpp" +#include "ActsExamples/Io/Root/VertexNTupleWriter.hpp" #include "ActsExamples/MaterialMapping/IMaterialWriter.hpp" #include "ActsExamples/Plugins/Obj/ObjPropagationStepsWriter.hpp" #include "ActsExamples/Plugins/Obj/ObjTrackingGeometryWriter.hpp" @@ -163,7 +163,7 @@ void addOutput(Context& ctx) { ACTS_PYTHON_STRUCT_END(); } - // Bindings for the binning in e.g., CKFPerformanceWriter + // Bindings for the binning in e.g., TrackFinderPerformanceWriter { py::class_(mex, "Binning") .def(py::init(), "title"_a, "bins"_a, @@ -194,14 +194,14 @@ void addOutput(Context& ctx) { ACTS_PYTHON_DECLARE_WRITER(ActsExamples::RootParticleWriter, mex, "RootParticleWriter", inputParticles, - inputFinalParticles, filePath, fileMode, treeName); + inputParticlesFinal, filePath, fileMode, treeName); ACTS_PYTHON_DECLARE_WRITER(ActsExamples::RootVertexWriter, mex, "RootVertexWriter", inputVertices, filePath, fileMode, treeName); - ACTS_PYTHON_DECLARE_WRITER(ActsExamples::TrackFinderPerformanceWriter, mex, - "TrackFinderPerformanceWriter", inputTracks, + ACTS_PYTHON_DECLARE_WRITER(ActsExamples::TrackFinderNTupleWriter, mex, + "TrackFinderNTupleWriter", inputTracks, inputParticles, inputMeasurementParticlesMap, inputTrackParticleMatching, filePath, fileMode, treeNameTracks, treeNameParticles); @@ -353,7 +353,7 @@ void addOutput(Context& ctx) { treeName, fileMode, writeCovMat, writeGsfSpecific, writeGx2fSpecific); ACTS_PYTHON_DECLARE_WRITER( - ActsExamples::VertexPerformanceWriter, mex, "VertexPerformanceWriter", + ActsExamples::VertexNTupleWriter, mex, "VertexNTupleWriter", inputVertices, inputTracks, inputTruthVertices, inputParticles, inputSelectedParticles, inputTrackParticleMatching, bField, filePath, treeName, fileMode, vertexMatchThreshold, trackMatchThreshold, useTracks); @@ -395,12 +395,13 @@ void addOutput(Context& ctx) { trackingGeometry, outputDir, outputPrecision, writeSensitive, writeBoundary, writeSurfaceGrid, writeLayerVolume, writePerEvent); - ACTS_PYTHON_DECLARE_WRITER( - ActsExamples::CKFPerformanceWriter, mex, "CKFPerformanceWriter", - inputTracks, inputParticles, inputTrackParticleMatching, - inputParticleTrackMatching, filePath, fileMode, effPlotToolConfig, - fakeRatePlotToolConfig, duplicationPlotToolConfig, - trackSummaryPlotToolConfig, writeMatchingDetails); + ACTS_PYTHON_DECLARE_WRITER(ActsExamples::TrackFinderPerformanceWriter, mex, + "TrackFinderPerformanceWriter", inputTracks, + inputParticles, inputTrackParticleMatching, + inputParticleTrackMatching, filePath, fileMode, + effPlotToolConfig, fakeRatePlotToolConfig, + duplicationPlotToolConfig, + trackSummaryPlotToolConfig, writeMatchingDetails); ACTS_PYTHON_DECLARE_WRITER( ActsExamples::RootNuclearInteractionParametersWriter, mex, diff --git a/Examples/Python/src/TrackFitting.cpp b/Examples/Python/src/TrackFitting.cpp index 20c6010c8ee..c8dc72f9eef 100644 --- a/Examples/Python/src/TrackFitting.cpp +++ b/Examples/Python/src/TrackFitting.cpp @@ -39,6 +39,7 @@ namespace py = pybind11; using namespace ActsExamples; using namespace Acts; +using namespace py::literals; namespace Acts::Python { @@ -106,12 +107,17 @@ void addTrackFitting(Context& ctx) { .value("KLDistance", MixtureReductionAlgorithm::KLDistance); py::class_(mex, "AtlasBetheHeitlerApprox") - .def_static("loadFromFiles", - &ActsExamples::BetheHeitlerApprox::loadFromFiles, - py::arg("lowParametersPath"), py::arg("highParametersPath"), - py::arg("lowLimit") = 0.1, py::arg("highLimit") = 0.2) - .def_static("makeDefault", - []() { return Acts::makeDefaultBetheHeitlerApprox(); }); + .def_static( + "loadFromFiles", &ActsExamples::BetheHeitlerApprox::loadFromFiles, + "lowParametersPath"_a, "highParametersPath"_a, "lowLimit"_a = 0.1, + "highLimit"_a = 0.2, "clampToRange"_a = false) + .def_static( + "makeDefault", + [](bool clampToRange) { + return Acts::makeDefaultBetheHeitlerApprox(clampToRange); + }, + "clampToRange"_a = false); + mex.def( "makeGsfFitterFunction", [](std::shared_ptr trackingGeometry, diff --git a/Examples/Python/src/TruthTracking.cpp b/Examples/Python/src/TruthTracking.cpp index 85d34698b7b..2c43b3cfc4d 100644 --- a/Examples/Python/src/TruthTracking.cpp +++ b/Examples/Python/src/TruthTracking.cpp @@ -108,8 +108,9 @@ void addTruthTracking(Context& ctx) { ACTS_PYTHON_STRUCT_BEGIN(c, Config); ACTS_PYTHON_MEMBER(inputParticles); - ACTS_PYTHON_MEMBER(inputMeasurementParticlesMap); + ACTS_PYTHON_MEMBER(inputParticlesFinal); ACTS_PYTHON_MEMBER(outputParticles); + ACTS_PYTHON_MEMBER(outputParticlesFinal); ACTS_PYTHON_MEMBER(rhoMin); ACTS_PYTHON_MEMBER(rhoMax); ACTS_PYTHON_MEMBER(absZMin); diff --git a/Examples/Python/tests/root_file_hashes.txt b/Examples/Python/tests/root_file_hashes.txt index 6ddb1a405cd..3ade64a68ed 100644 --- a/Examples/Python/tests/root_file_hashes.txt +++ b/Examples/Python/tests/root_file_hashes.txt @@ -1,17 +1,17 @@ -test_pythia8__pythia8_particles.root: a8b53c12e771091bc2f5ace0198e9f6c5ac1909e2e6d0e3e4945e8174048ef62 +test_pythia8__pythia8_particles.root: 91c852f3e0e20bcd382c616a7b643985d092decd42bdd653deae67ed8652e8d8 test_fatras__particles_simulation.root: bc970873fef0c2efd86ed5413623802353d2cd04abea72de14e8cdfc0e40076f test_fatras__hits.root: 6e4beb045fa1712c4d14c280ba33c3fa13e4aff9de88d55c3e32f62ad226f724 -test_geant4__particles_simulation.root: 3c9c6265183b04c9d62ed5f2d0709c6dd74e33fbb53ac0aeb3274f6600257fc1 -test_geant4__hits.root: adf5dcdf000a580412dc5089e17460897d6535c978eafa021584ba4281d0a1ac +test_geant4__particles_simulation.root: 49926c71a9b54e13aa1cc7596d3302baf3c87d8e2c1d0267cb4523f6abdc0ac2 +test_geant4__hits.root: 4c9e704a75f47ed2e61652679a1d6f18fa4d9cf53faa8f8f5bbf7995634207aa test_seeding__estimatedparams.root: 69c0e268f9025a0991a212ea2a7f26f53112fecf614b475605bd1cb08415ba56 test_seeding__performance_seeding.root: 992f9c611d30dde0d3f3ab676bab19ada61ab6a4442828e27b65ec5e5b7a2880 test_seeding__particles.root: 7855b021f39ad238bca098e4282667be0666f2d1630e5bcb9d51d3b5ee39fa14 -test_seeding__particles_simulation.root: 87d9c6c82422ca381a17735096b36c547eacb5dda2f26d7377614bd97a70ab1a -test_hashing_seeding__estimatedparams.root: 1f43b760e80089b5674e106d00d962d74be564cbf33ae38222052ebb6f9cbf3a +test_seeding__particles_simulation.root: f937a4cc474e80cfbb6eac4384e42e9c5c7ac981fcd6870d624cc898d1a0c006 +test_hashing_seeding__estimatedparams.root: 1ab38fbedeaff1380fc022e2970e6c74163d770613205100bd34c3e88283e387 test_seeding_orthogonal__estimatedparams.root: ca5896ec325daf5c8012291bc454269c61c32fe3d7e33bd1fa3b812826930299 test_seeding_orthogonal__performance_seeding.root: 60fbedcf5cb2b37cd8e526251940564432890d3a159d231ed819e915a904682c test_seeding_orthogonal__particles.root: 7855b021f39ad238bca098e4282667be0666f2d1630e5bcb9d51d3b5ee39fa14 -test_seeding_orthogonal__particles_simulation.root: 87d9c6c82422ca381a17735096b36c547eacb5dda2f26d7377614bd97a70ab1a +test_seeding_orthogonal__particles_simulation.root: f937a4cc474e80cfbb6eac4384e42e9c5c7ac981fcd6870d624cc898d1a0c006 test_itk_seeding__estimatedparams.root: 1cc05f9f2aefb5f71a85b31e97bc4e5845fedfcef6c53199495a6340c6b6210b test_itk_seeding__performance_seeding.root: 78ebda54cd0f026ba4b7f316724ffd946de56a932735914baf1b7bba9505c29d test_itk_seeding__particles.root: 0b6f4ad438010ac48803d48ed98e80b5e87d310bae6c2c02b16cd94d7a4d7d07 @@ -20,7 +20,7 @@ test_propagation__propagation_summary.root: 280c1a6fcfe71974ac39587b4afad27a3164 test_material_recording__geant4_material_tracks.root: c022b9362249b29f57a07926b20644e3ab4ab8ebcf03f773fbf46c446fc1a0a1 test_truth_tracking_gsf[generic]__trackstates_gsf.root: 4df2c69d5dd7d5446a547651e4e962daf17924f5c8617165a93a3223c8ba18fd test_truth_tracking_gsf[generic]__tracksummary_gsf.root: 8c01d139cb865afa1959c62dbca76f3a1fb8b684c57ea4c2968baa6ffedadb6f -test_truth_tracking_gsf[odd]__trackstates_gsf.root: 8e6559aaec4fada8b82cfcad5801f3a609c6c905c3172fc044473cef7de77870 +test_truth_tracking_gsf[odd]__trackstates_gsf.root: c7397e53ea093f2432943ae263fc99bc9aa774504ea6152c6907066a06d21caf test_truth_tracking_gsf[odd]__tracksummary_gsf.root: 4562341f12a61ea0d5e25872b6bf466b79a73781dc95fc18ef9c6515f0a47916 test_particle_gun__particles.root: 5fe7dda2933ee6b9615b064d192322fe07831133cd998e5ed99a3b992b713a10 test_material_mapping__material-map_tracks.root: 938b1a855369e9304401cb10d2751df3fd7acf32a2573f2057eb1691cd94edf3 @@ -33,22 +33,22 @@ test_digitization_example_input[smeared]__particles.root: 5fe7dda2933ee6b9615b06 test_digitization_example_input[smeared]__measurements.root: 243c2f69b7b0db9dbeaa7494d4ea0f3dd1691dc90f16e10df6c0491ff4dc7d62 test_digitization_example_input[geometric]__particles.root: 5fe7dda2933ee6b9615b064d192322fe07831133cd998e5ed99a3b992b713a10 test_digitization_example_input[geometric]__measurements.root: 63ec81635979058fb8976f94455bf490cf92b7b142c4a05cc39de6225f5de2fb -test_ckf_tracks_example[generic-full_seeding]__trackstates_ckf.root: 35249a79237804bce337d797986e1082c6987f0700e30877f6f217f9ac91d36a +test_ckf_tracks_example[generic-full_seeding]__trackstates_ckf.root: 7c48ec32a2cb1723416a9791a8067ef09825fcf71a6cf561c1f6d2ab9dc1c1ad test_ckf_tracks_example[generic-full_seeding]__tracksummary_ckf.root: e6b9e539998ba007e9b7d2c8d9d022c47726a39e8ab9b1724c52b1d78234be03 test_ckf_tracks_example[generic-full_seeding]__performance_seeding_trees.root: 0e0676ffafdb27112fbda50d1cf627859fa745760f98073261dcf6db3f2f991e -test_ckf_tracks_example[generic-truth_estimated]__trackstates_ckf.root: a8c5c6f6c1e6303b887d47b509b7f71a2ffa5f38638fe46ce5bce76fd20d64ca +test_ckf_tracks_example[generic-truth_estimated]__trackstates_ckf.root: df730fd00a7e6a0941f5f94c07ea9cffdb763853272d284d25bec0eb2072bb2e test_ckf_tracks_example[generic-truth_estimated]__tracksummary_ckf.root: 417f7326e1e1bb4519f1378145ac733bdda6653eb9871fd69e455e0269d996a6 test_ckf_tracks_example[generic-truth_estimated]__performance_seeding.root: 1facb05c066221f6361b61f015cdf0918e94d9f3fce2269ec7b6a4dffeb2bc7e -test_ckf_tracks_example[generic-truth_smeared]__trackstates_ckf.root: de11c0868a70ade0dcc80465d4e6dcf1dd7fcf8149603b47ee7d87d862a6534a -test_ckf_tracks_example[generic-truth_smeared]__tracksummary_ckf.root: f18e9ecce6d9585fd150c5aafc9ac225a5bab342aaab50a28283ba879691af1f -test_ckf_tracks_example[odd-full_seeding]__trackstates_ckf.root: 463d6aaed4d869652b5b184940e789cde0fb441bdd135813b85462a515e6480a -test_ckf_tracks_example[odd-full_seeding]__tracksummary_ckf.root: a8ad83a07b48d4cfcf70d0e6fdc3c8997eb03c1f8c2a7be27ea888b099000d79 +test_ckf_tracks_example[generic-truth_smeared]__trackstates_ckf.root: 82a6744980553e6274df78eea15f0dec22676b1c04e14afc3828bff9bbf5e1b1 +test_ckf_tracks_example[generic-truth_smeared]__tracksummary_ckf.root: 06d6ae1d05cb611b19df3c59531997c9b0108f5ef6027d76c4827bd2d9edb921 +test_ckf_tracks_example[odd-full_seeding]__trackstates_ckf.root: 0fb43661cc3a7973c28940a283dc168ceb13bc60badf1f520096edaa5982a039 +test_ckf_tracks_example[odd-full_seeding]__tracksummary_ckf.root: c2e029e462d4ca77df2c7f8963093da43be66c8279ca2cc9aee8c0bc35259eec test_ckf_tracks_example[odd-full_seeding]__performance_seeding_trees.root: 43c58577aafe07645e5660c4f43904efadf91d8cda45c5c04c248bbe0f59814f -test_ckf_tracks_example[odd-truth_estimated]__trackstates_ckf.root: 247dd581cc177625c0286718261c004e2149536d70c8281dfaf697879a84d76d -test_ckf_tracks_example[odd-truth_estimated]__tracksummary_ckf.root: 1b08a80e73aedf5cf38a3a407794b82297bec37f556ad4efcda3489a1b17d4d2 +test_ckf_tracks_example[odd-truth_estimated]__trackstates_ckf.root: 39ac67c47f371c576d7094bca987a04e0315bd286dc79503a63a5f568b58ac97 +test_ckf_tracks_example[odd-truth_estimated]__tracksummary_ckf.root: 59e2c75e9524653a80a9fd62fe99e958f73f80aa09240dcbb4ea469372e4811d test_ckf_tracks_example[odd-truth_estimated]__performance_seeding.root: 1a36b7017e59f1c08602ef3c2cb0483c51df248f112e3780c66594110719c575 -test_ckf_tracks_example[odd-truth_smeared]__trackstates_ckf.root: 7adfc2bf5ee35a126b713187dd8b11f4497cf864a4a83e57a40885688974413e -test_ckf_tracks_example[odd-truth_smeared]__tracksummary_ckf.root: 7a9de8a8bd1c09f7b4d1c547f824af6c8123afb044dd429180b0d13e47d6f975 +test_ckf_tracks_example[odd-truth_smeared]__trackstates_ckf.root: 35a65e15a6f479f628a96f56ee78e1ac371d71a686ee0c974944d681499fe6bd +test_ckf_tracks_example[odd-truth_smeared]__tracksummary_ckf.root: 3e257de624674fa9a19dcc72598c78c29a52633821acaa56dc2aa39a1395f1b5 test_vertex_fitting_reading[Truth-False-100]__performance_vertexing.root: 76ef6084d758dfdfc0151ddec2170e12d73394424e3dac4ffe46f0f339ec8293 test_vertex_fitting_reading[Iterative-False-100]__performance_vertexing.root: 60372210c830a04f95ceb78c6c68a9b0de217746ff59e8e73053750c837b57eb test_vertex_fitting_reading[Iterative-True-100]__performance_vertexing.root: e34f217d524a5051dbb04a811d3407df3ebe2cc4bb7f54f6bda0847dbd7b52c3 @@ -73,11 +73,11 @@ test_root_clusters_writer[kwargsConstructor]__clusters.root: e842df4fe04eefff3df test_exatrkx[cpu-torch]__performance_track_finding.root: 36b3045589c4c17c038dbc87943366f4af4440f7eea6887afb763871ac149b05 test_exatrkx[gpu-onnx]__performance_track_finding.root: 9090de10ffb1489d3f1993e2a3081a3038227e3e5c453e98a9a4f33ea3d6d817 test_exatrkx[gpu-torch]__performance_track_finding.root: 36b3045589c4c17c038dbc87943366f4af4440f7eea6887afb763871ac149b05 -test_ML_Ambiguity_Solver__performance_ambiML.root: 284ff5c3a08c0b810938e4ac2f8ba8fe2babb17d4c202b624ed69fff731a9006 -test_refitting[odd]__trackstates_gsf_refit.root: a61fe2d80d5d10d3b3505000e8abb589d88302bf5f54b625948793418f2a7fe8 -test_refitting[odd]__tracksummary_gsf_refit.root: 082789fc1a85e578b3cf9a750723d2dcee01b5019e871c6a63e0b271f4e907b1 -test_refitting[generic]__trackstates_gsf_refit.root: 9fa7af9eff12081504c0d648f6debae64f6996e0ca610cf58187d23aa5a13251 -test_refitting[generic]__tracksummary_gsf_refit.root: 35b5ac6f208cae093fff94038d217a2e9915a5ce075da2a95718dda696f2d4a2 +test_ML_Ambiguity_Solver__performance_finding_ambiML.root: 166dd8bb189097c4957b7b02c04c41267868d72d9a08c4bb892985b06849cb76 +test_refitting[odd]__trackstates_gsf_refit.root: e297749dc1e7eda3b8dea13defa0499986c584740d93e723a901b498b8e90c71 +test_refitting[odd]__tracksummary_gsf_refit.root: d5085882e45a0b699194dff9f40a36e9291227bf65f9aaaf9087f9242ef5ae22 +test_refitting[generic]__trackstates_gsf_refit.root: 4424fdf2f27575db825c1a59f8e53a1595946211cbd5b2c8d3a2f71cdcc77ae9 +test_refitting[generic]__tracksummary_gsf_refit.root: 562deecee4cfb97ceee72eff53d63da079e3249fb62d6bcd556e6f27d495dfd9 test_truth_tracking_kalman[generic-False-0.0]__trackstates_kf.root: 9f77962b92037cb760b1629a602b1dae61f45e659c45d9a87baa784f6190960e test_truth_tracking_kalman[generic-False-0.0]__tracksummary_kf.root: 562deecee4cfb97ceee72eff53d63da079e3249fb62d6bcd556e6f27d495dfd9 test_truth_tracking_kalman[generic-False-1000.0]__trackstates_kf.root: 56a1bd989b9c1316b9098c65fa75df9e6683e62e35ae68d8f72d27220be0fd7d diff --git a/Examples/Python/tests/test_examples.py b/Examples/Python/tests/test_examples.py index 0e34a8a3c1c..26f69f4aa82 100644 --- a/Examples/Python/tests/test_examples.py +++ b/Examples/Python/tests/test_examples.py @@ -407,6 +407,7 @@ def test_itk_seeding(tmp_path, trk_geo, field, assert_root_hash): EtaConfig, MomentumConfig, ParticleConfig, + ParticleSelectorConfig, addFatras, addDigitization, ) @@ -428,6 +429,12 @@ def test_itk_seeding(tmp_path, trk_geo, field, assert_root_hash): outputDirCsv=tmp_path / "csv", outputDirRoot=str(tmp_path), rnd=rnd, + postSelectParticles=ParticleSelectorConfig( + pt=(0.9 * u.GeV, None), + eta=(-4, 4), + measurements=(9, None), + removeNeutral=True, + ), ) srcdir = Path(__file__).resolve().parent.parent.parent.parent @@ -442,7 +449,6 @@ def test_itk_seeding(tmp_path, trk_geo, field, assert_root_hash): from acts.examples.reconstruction import ( addSeeding, - TruthSeedRanges, ) from acts.examples.itk import itkSeedingAlgConfig, InputSpacePointsType @@ -450,7 +456,6 @@ def test_itk_seeding(tmp_path, trk_geo, field, assert_root_hash): seq, trk_geo, field, - TruthSeedRanges(pt=(1.0 * u.GeV, None), eta=(-4, 4), nHits=(9, None)), *itkSeedingAlgConfig(InputSpacePointsType.PixelSpacePoints), acts.logging.VERBOSE, geoSelectionConfigFile=srcdir @@ -689,7 +694,7 @@ def test_refitting(tmp_path, detector_config, assert_root_hash): field = acts.ConstantBField(acts.Vector3(0, 0, 2 * u.T)) seq = Sequencer( - events=3, + events=10, numThreads=1, ) @@ -1141,7 +1146,7 @@ def test_ckf_tracks_example( root_files = [ ( - "performance_ckf.root", + "performance_finding_ckf.root", None, ), ( @@ -1285,7 +1290,7 @@ def test_full_chain_odd_example_pythia_geant4(tmp_path): def test_ML_Ambiguity_Solver(tmp_path, assert_root_hash): # This test literally only ensures that the full chain example can run without erroring out - root_file = "performance_ambiML.root" + root_file = "performance_finding_ambiML.root" output_dir = "odd_output" assert not (tmp_path / root_file).exists() diff --git a/Examples/Python/tests/test_navigation.py b/Examples/Python/tests/test_navigation.py new file mode 100644 index 00000000000..55ec8ac9540 --- /dev/null +++ b/Examples/Python/tests/test_navigation.py @@ -0,0 +1,42 @@ +import pytest + +import acts + +import acts.examples + + +def test_navigation_policy_factory(): + + policy = ( + acts.NavigationPolicyFactory.make() + .add(acts.TryAllNavigationPolicy) + .add( + acts.SurfaceArrayNavigationPolicy, + acts.SurfaceArrayNavigationPolicy.Config( + layerType=acts.SurfaceArrayNavigationPolicy.LayerType.Disc, + bins=(10, 10), + ), + ) + ) + + policy._buildTest() + + policy = acts.NavigationPolicyFactory.make().add(acts.TryAllNavigationPolicy) + + policy._buildTest() + + +def test_navigation_policy_factory_build_empty(): + policy = acts.NavigationPolicyFactory.make() + + with pytest.raises(RuntimeError): + policy._buildTest() + + +def test_navigation_policy_factory_add_multiple(): + with pytest.raises(ValueError): + ( + acts.NavigationPolicyFactory.make() + .add(acts.TryAllNavigationPolicy) + .add(acts.TryAllNavigationPolicy) + ) diff --git a/Examples/Python/tests/test_reader.py b/Examples/Python/tests/test_reader.py index 3d458cb8009..b83b1317cc8 100644 --- a/Examples/Python/tests/test_reader.py +++ b/Examples/Python/tests/test_reader.py @@ -290,8 +290,11 @@ def test_edm4hep_simhit_particle_reader(tmp_path): tmp_file = str(tmp_path / "output_edm4hep.root") odd_xml_file = str(getOpenDataDetectorDirectory() / "xml" / "OpenDataDetector.xml") - with multiprocessing.get_context("spawn").Pool() as pool: - pool.apply(generate_input_test_edm4hep_simhit_reader, (odd_xml_file, tmp_file)) + p = multiprocessing.Process( + target=generate_input_test_edm4hep_simhit_reader, args=(odd_xml_file, tmp_file) + ) + p.start() + p.join() assert os.path.exists(tmp_file) diff --git a/Examples/Python/tests/test_writer.py b/Examples/Python/tests/test_writer.py index a3098c743c9..95cd67decd1 100644 --- a/Examples/Python/tests/test_writer.py +++ b/Examples/Python/tests/test_writer.py @@ -21,7 +21,7 @@ from acts import UnitConstants as u from acts.examples import ( ObjPropagationStepsWriter, - TrackFinderPerformanceWriter, + TrackFinderNTupleWriter, SeedingPerformanceWriter, RootPropagationStepsWriter, RootParticleWriter, @@ -31,7 +31,7 @@ RootSimHitWriter, RootTrackStatesWriter, RootTrackSummaryWriter, - VertexPerformanceWriter, + VertexNTupleWriter, RootMeasurementWriter, CsvParticleWriter, CsvSimHitWriter, @@ -250,7 +250,7 @@ def test_csv_simhits_writer(tmp_path, fatras, conf_const): [ RootPropagationStepsWriter, RootParticleWriter, - TrackFinderPerformanceWriter, + TrackFinderNTupleWriter, SeedingPerformanceWriter, RootTrackParameterWriter, RootMaterialTrackWriter, @@ -259,7 +259,7 @@ def test_csv_simhits_writer(tmp_path, fatras, conf_const): RootSimHitWriter, RootTrackStatesWriter, RootTrackSummaryWriter, - VertexPerformanceWriter, + VertexNTupleWriter, SeedingPerformanceWriter, ], ) diff --git a/Examples/Scripts/Optimization/ckf.py b/Examples/Scripts/Optimization/ckf.py index bf927850ecc..c1761141262 100755 --- a/Examples/Scripts/Optimization/ckf.py +++ b/Examples/Scripts/Optimization/ckf.py @@ -116,13 +116,13 @@ def runCKFTracks( EtaConfig, PhiConfig, ParticleConfig, + ParticleSelectorConfig, addFatras, addDigitization, ) from acts.examples.reconstruction import ( addSeeding, - TruthSeedRanges, ParticleSmearingSigmas, SeedFinderConfigArg, SeedFinderOptionsArg, @@ -169,6 +169,11 @@ def runCKFTracks( trackingGeometry, field, rnd=rnd, + postSelectParticles=ParticleSelectorConfig( + pt=(0.5 * u.GeV, None), + measurements=(9, None), + removeNeutral=True, + ), ) addDigitization( @@ -183,7 +188,6 @@ def runCKFTracks( s, trackingGeometry, field, - TruthSeedRanges(pt=(500.0 * u.MeV, None), nHits=(9, None)), ParticleSmearingSigmas( # only used by SeedingAlgorithm.TruthSmeared # zero eveything so the CKF has a chance to find the measurements d0=0, diff --git a/Examples/Scripts/Python/ckf_tracks.py b/Examples/Scripts/Python/ckf_tracks.py index 9dc665eb835..97f56d17ff0 100755 --- a/Examples/Scripts/Python/ckf_tracks.py +++ b/Examples/Scripts/Python/ckf_tracks.py @@ -27,13 +27,13 @@ def runCKFTracks( EtaConfig, PhiConfig, ParticleConfig, + ParticleSelectorConfig, addFatras, addDigitization, ) from acts.examples.reconstruction import ( addSeeding, - TruthSeedRanges, ParticleSmearingSigmas, SeedFinderConfigArg, SeedFinderOptionsArg, @@ -80,6 +80,11 @@ def runCKFTracks( trackingGeometry, field, rnd=rnd, + postSelectParticles=ParticleSelectorConfig( + pt=(0.5 * u.GeV, None), + measurements=(9, None), + removeNeutral=True, + ), ) addDigitization( @@ -94,7 +99,6 @@ def runCKFTracks( s, trackingGeometry, field, - TruthSeedRanges(pt=(500.0 * u.MeV, None), nHits=(9, None)), ParticleSmearingSigmas( # only used by SeedingAlgorithm.TruthSmeared # zero eveything so the CKF has a chance to find the measurements d0=0, @@ -166,6 +170,7 @@ def runCKFTracks( ), outputDirRoot=outputDir, outputDirCsv=outputDir / "csv" if outputCsv else None, + writeTrackStates=True, ) return s diff --git a/Examples/Scripts/Python/full_chain_itk.py b/Examples/Scripts/Python/full_chain_itk.py index 5e268f87fcb..51746c127a1 100755 --- a/Examples/Scripts/Python/full_chain_itk.py +++ b/Examples/Scripts/Python/full_chain_itk.py @@ -5,6 +5,7 @@ MomentumConfig, EtaConfig, ParticleConfig, + ParticleSelectorConfig, addPythia8, addFatras, ParticleSelectorConfig, @@ -13,7 +14,6 @@ from acts.examples.reconstruction import ( addSeeding, SeedingAlgorithm, - TruthSeedRanges, addCKFTracks, CkfConfig, TrackSelectorConfig, @@ -72,6 +72,12 @@ if ttbar_pu200 else ParticleSelectorConfig() ), + postSelectParticles=ParticleSelectorConfig( + pt=(1.0 * u.GeV, None), + eta=(-4.0, 4.0), + measurements=(9, None), + removeNeutral=True, + ), outputDirRoot=outputDir, ) @@ -88,11 +94,6 @@ s, trackingGeometry, field, - ( - TruthSeedRanges(pt=(1.0 * u.GeV, None), eta=(-4.0, 4.0), nHits=(9, None)) - if ttbar_pu200 - else TruthSeedRanges() - ), seedingAlgorithm=SeedingAlgorithm.Default, *acts.examples.itk.itkSeedingAlgConfig( acts.examples.itk.InputSpacePointsType.PixelSpacePoints diff --git a/Examples/Scripts/Python/full_chain_itk_Gbts.py b/Examples/Scripts/Python/full_chain_itk_Gbts.py index 7a45b7e5a71..a87f5ca6656 100755 --- a/Examples/Scripts/Python/full_chain_itk_Gbts.py +++ b/Examples/Scripts/Python/full_chain_itk_Gbts.py @@ -5,6 +5,7 @@ MomentumConfig, EtaConfig, ParticleConfig, + ParticleSelectorConfig, addPythia8, addFatras, ParticleSelectorConfig, @@ -13,7 +14,6 @@ from acts.examples.reconstruction import ( addSeeding, SeedingAlgorithm, - TruthSeedRanges, addCKFTracks, TrackSelectorConfig, ) @@ -67,6 +67,12 @@ if ttbar_pu200 else ParticleSelectorConfig() ), + postSelectParticles=ParticleSelectorConfig( + pt=(1.0 * u.GeV, None), + eta=(-4.0, 4.0), + measurements=(9, None), + removeNeutral=True, + ), outputDirRoot=outputDir, ) @@ -84,11 +90,6 @@ s, trackingGeometry, field, - ( - TruthSeedRanges(pt=(1.0 * u.GeV, None), eta=(-4.0, 4.0), nHits=(9, None)) - if ttbar_pu200 - else TruthSeedRanges() - ), seedingAlgorithm=SeedingAlgorithm.Gbts, *acts.examples.itk.itkSeedingAlgConfig( acts.examples.itk.InputSpacePointsType.PixelSpacePoints diff --git a/Examples/Scripts/Python/full_chain_odd.py b/Examples/Scripts/Python/full_chain_odd.py index 22f20d3b257..fd98f759577 100755 --- a/Examples/Scripts/Python/full_chain_odd.py +++ b/Examples/Scripts/Python/full_chain_odd.py @@ -13,6 +13,7 @@ EtaConfig, PhiConfig, ParticleConfig, + ParticleSelectorConfig, addPythia8, addFatras, addGeant4, @@ -22,7 +23,6 @@ ) from acts.examples.reconstruction import ( addSeeding, - TruthSeedRanges, CkfConfig, addCKFTracks, TrackSelectorConfig, @@ -271,6 +271,12 @@ pt=(150 * u.MeV, None), removeNeutral=True, ), + postSelectParticles=ParticleSelectorConfig( + pt=(1.0 * u.GeV, None), + eta=(-3.0, 3.0), + measurements=(9, None), + removeNeutral=True, + ), outputDirRoot=outputDir if args.output_root else None, outputDirCsv=outputDir if args.output_csv else None, rnd=rnd, @@ -293,6 +299,12 @@ if args.ttbar else ParticleSelectorConfig() ), + postSelectParticles=ParticleSelectorConfig( + pt=(1.0 * u.GeV, None), + eta=(-3.0, 3.0), + measurements=(9, None), + removeNeutral=True, + ), enableInteractions=True, outputDirRoot=outputDir if args.output_root else None, outputDirCsv=outputDir if args.output_csv else None, @@ -314,11 +326,6 @@ s, trackingGeometry, field, - ( - TruthSeedRanges(pt=(1.0 * u.GeV, None), eta=(-3.0, 3.0), nHits=(9, None)) - if args.ttbar - else TruthSeedRanges() - ), initialSigmas=[ 1 * u.mm, 1 * u.mm, diff --git a/Examples/Scripts/Python/full_chain_odd_LRT.py b/Examples/Scripts/Python/full_chain_odd_LRT.py index a5fd294ceda..2188bb98d6b 100644 --- a/Examples/Scripts/Python/full_chain_odd_LRT.py +++ b/Examples/Scripts/Python/full_chain_odd_LRT.py @@ -21,7 +21,6 @@ ) from acts.examples.reconstruction import ( addSeeding, - TruthSeedRanges, CkfConfig, addCKFTracks, TrackSelectorConfig, @@ -273,6 +272,12 @@ pt=(150 * u.MeV, None), removeNeutral=True, ), + postSelectParticles=ParticleSelectorConfig( + pt=(1.0 * u.GeV, None), + eta=(-3.0, 3.0), + measurements=(9, None), + removeNeutral=True, + ), outputDirRoot=outputDir if args.output_root else None, outputDirCsv=outputDir if args.output_csv else None, rnd=rnd, @@ -295,6 +300,12 @@ if args.ttbar else ParticleSelectorConfig() ), + postSelectParticles=ParticleSelectorConfig( + pt=(1.0 * u.GeV, None), + eta=(-3.0, 3.0), + measurements=(9, None), + removeNeutral=True, + ), enableInteractions=True, outputDirRoot=outputDir if args.output_root else None, outputDirCsv=outputDir if args.output_csv else None, @@ -316,11 +327,6 @@ s, trackingGeometry, field, - ( - TruthSeedRanges(pt=(1.0 * u.GeV, None), eta=(-3.0, 3.0), nHits=(9, None)) - if args.ttbar - else TruthSeedRanges() - ), geoSelectionConfigFile=oddSeedingSel, outputDirRoot=outputDir if args.output_root else None, outputDirCsv=outputDir if args.output_csv else None, diff --git a/Examples/Scripts/Python/hashing_seeding.py b/Examples/Scripts/Python/hashing_seeding.py index a5608a0f329..3148a03837d 100755 --- a/Examples/Scripts/Python/hashing_seeding.py +++ b/Examples/Scripts/Python/hashing_seeding.py @@ -14,7 +14,6 @@ from acts.examples.reconstruction import ( addSeeding, - TruthSeedRanges, addCKFTracks, TrackSelectorConfig, SeedingAlgorithm, @@ -210,7 +209,15 @@ def runHashingSeeding( trackingGeometry, field, preSelectParticles=ParticleSelectorConfig( - eta=(-eta, eta), pt=(150 * u.MeV, None), removeNeutral=True + eta=(-eta, eta), + pt=(150 * u.MeV, None), + removeNeutral=True, + ), + postSelectParticles=ParticleSelectorConfig( + pt=(1.0 * u.GeV, None), + eta=(-eta, eta), + measurements=(9, None), + removeNeutral=True, ), enableInteractions=True, # outputDirRoot=outputDir, # RootParticle ERROR when setting the outputDirRoot @@ -272,7 +279,6 @@ def runHashingSeeding( seedFinderOptionsArg, hashingTrainingConfigArg, hashingAlgorithmConfigArg, - TruthSeedRanges(pt=(1.0 * u.GeV, None), eta=(-eta, eta), nHits=(9, None)), seedingAlgorithm=seedingAlgorithm, geoSelectionConfigFile=geoSelectionConfigFile, initialSigmas=initialSigmas, @@ -338,10 +344,6 @@ def runHashingSeeding( phiBins=phiBins, ) - truthSeedRanges = TruthSeedRanges( - pt=(1.0 * u.GeV, None), eta=(-eta, eta), nHits=(9, None) - ) - doHashing = config.doHashing bucketSize = config.bucketSize npileup = config.mu diff --git a/Examples/Scripts/Python/seeding.py b/Examples/Scripts/Python/seeding.py index 4c87ba9b82b..afe8983eec7 100755 --- a/Examples/Scripts/Python/seeding.py +++ b/Examples/Scripts/Python/seeding.py @@ -57,6 +57,7 @@ def runSeeding( EtaConfig, PhiConfig, ParticleConfig, + ParticleSelectorConfig, addFatras, addDigitization, ) @@ -86,6 +87,12 @@ def runSeeding( outputDirRoot=outputDir, rnd=rnd, preSelectParticles=None, + postSelectParticles=ParticleSelectorConfig( + pt=(1.0 * u.GeV, None), + eta=(-2.5, 2.5), + measurements=(9, None), + removeNeutral=True, + ), ) srcdir = Path(__file__).resolve().parent.parent.parent.parent @@ -97,9 +104,9 @@ def runSeeding( / "Examples/Algorithms/Digitization/share/default-smearing-config-generic.json", rnd=rnd, ) + from acts.examples.reconstruction import ( addSeeding, - TruthSeedRanges, SeedFinderConfigArg, SeedFinderOptionsArg, ) @@ -108,7 +115,6 @@ def runSeeding( s, trackingGeometry, field, - TruthSeedRanges(pt=(1.0 * u.GeV, None), eta=(-2.5, 2.5), nHits=(9, None)), SeedFinderConfigArg( r=(None, 200 * u.mm), # rMin=default, 33mm deltaR=(1 * u.mm, 60 * u.mm), diff --git a/Examples/Scripts/Python/truth_tracking_gsf.py b/Examples/Scripts/Python/truth_tracking_gsf.py index 82c99bb38aa..ae8aca06d6c 100755 --- a/Examples/Scripts/Python/truth_tracking_gsf.py +++ b/Examples/Scripts/Python/truth_tracking_gsf.py @@ -24,13 +24,13 @@ def runTruthTrackingGsf( EtaConfig, PhiConfig, MomentumConfig, + ParticleSelectorConfig, addFatras, addDigitization, ) from acts.examples.reconstruction import ( addSeeding, SeedingAlgorithm, - TruthSeedRanges, addTruthTrackingGsf, ) @@ -77,6 +77,12 @@ def runTruthTrackingGsf( field, rnd=rnd, enableInteractions=True, + postSelectParticles=ParticleSelectorConfig( + pt=(0.9 * u.GeV, None), + measurements=(7, None), + removeNeutral=True, + removeSecondaries=True, + ), ) addDigitization( @@ -95,9 +101,6 @@ def runTruthTrackingGsf( inputParticles="particles_input", seedingAlgorithm=SeedingAlgorithm.TruthSmeared, particleHypothesis=acts.ParticleHypothesis.electron, - truthSeedRanges=TruthSeedRanges( - nHits=(7, None), - ), ) addTruthTrackingGsf( @@ -122,7 +125,7 @@ def runTruthTrackingGsf( acts.examples.RootTrackStatesWriter( level=acts.logging.INFO, inputTracks="tracks", - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputTrackParticleMatching="track_particle_matching", inputSimHits="simhits", inputMeasurementSimHitsMap="measurement_simhits_map", @@ -134,7 +137,7 @@ def runTruthTrackingGsf( acts.examples.RootTrackSummaryWriter( level=acts.logging.INFO, inputTracks="tracks", - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputTrackParticleMatching="track_particle_matching", filePath=str(outputDir / "tracksummary_gsf.root"), writeGsfSpecific=True, @@ -145,7 +148,7 @@ def runTruthTrackingGsf( acts.examples.TrackFitterPerformanceWriter( level=acts.logging.INFO, inputTracks="tracks", - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputTrackParticleMatching="track_particle_matching", filePath=str(outputDir / "performance_gsf.root"), ) diff --git a/Examples/Scripts/Python/truth_tracking_gsf_refitting.py b/Examples/Scripts/Python/truth_tracking_gsf_refitting.py index 797bfc59569..686f4af06c2 100755 --- a/Examples/Scripts/Python/truth_tracking_gsf_refitting.py +++ b/Examples/Scripts/Python/truth_tracking_gsf_refitting.py @@ -25,8 +25,13 @@ def runRefittingGsf( s=s, ) + # NOTE we specify clampToRange as True to silence warnings in the test about + # queries to the loss distribution outside the specified range, since no dedicated + # approximation for the ODD is done yet. + bha = acts.examples.AtlasBetheHeitlerApprox.makeDefault(clampToRange=True) + gsfOptions = { - "betheHeitlerApprox": acts.examples.AtlasBetheHeitlerApprox.makeDefault(), + "betheHeitlerApprox": bha, "maxComponents": 12, "componentMergeMethod": acts.examples.ComponentMergeMethod.maxWeight, "mixtureReductionAlgorithm": acts.examples.MixtureReductionAlgorithm.KLDistance, @@ -49,7 +54,7 @@ def runRefittingGsf( acts.examples.TrackTruthMatcher( level=acts.logging.INFO, inputTracks="gsf_refit_tracks", - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputMeasurementParticlesMap="measurement_particles_map", outputTrackParticleMatching="refit_track_particle_matching", outputParticleTrackMatching="refit_particle_track_matching", @@ -60,7 +65,7 @@ def runRefittingGsf( acts.examples.RootTrackStatesWriter( level=acts.logging.INFO, inputTracks="gsf_refit_tracks", - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputTrackParticleMatching="refit_track_particle_matching", inputSimHits="simhits", inputMeasurementSimHitsMap="measurement_simhits_map", @@ -72,7 +77,7 @@ def runRefittingGsf( acts.examples.RootTrackSummaryWriter( level=acts.logging.INFO, inputTracks="tracks", - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputTrackParticleMatching="refit_track_particle_matching", filePath=str(outputDir / "tracksummary_gsf_refit.root"), ) @@ -82,7 +87,7 @@ def runRefittingGsf( acts.examples.TrackFitterPerformanceWriter( level=acts.logging.INFO, inputTracks="tracks", - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputTrackParticleMatching="track_particle_matching", filePath=str(outputDir / "performance_gsf_refit.root"), ) diff --git a/Examples/Scripts/Python/truth_tracking_gx2f.py b/Examples/Scripts/Python/truth_tracking_gx2f.py index 46352ac8d21..8503dc982f4 100644 --- a/Examples/Scripts/Python/truth_tracking_gx2f.py +++ b/Examples/Scripts/Python/truth_tracking_gx2f.py @@ -23,13 +23,13 @@ def runTruthTrackingGx2f( EtaConfig, PhiConfig, MomentumConfig, + ParticleSelectorConfig, addFatras, addDigitization, ) from acts.examples.reconstruction import ( addSeeding, SeedingAlgorithm, - TruthSeedRanges, addGx2fTracks, ) @@ -74,6 +74,12 @@ def runTruthTrackingGx2f( field, rnd=rnd, enableInteractions=True, + postSelectParticles=ParticleSelectorConfig( + pt=(0.9 * u.GeV, None), + measurements=(7, None), + removeNeutral=True, + removeSecondaries=True, + ), ) addDigitization( @@ -92,9 +98,6 @@ def runTruthTrackingGx2f( inputParticles="particles_input", seedingAlgorithm=SeedingAlgorithm.TruthSmeared, particleHypothesis=acts.ParticleHypothesis.muon, - truthSeedRanges=TruthSeedRanges( - nHits=(7, None), - ), ) addGx2fTracks( @@ -122,7 +125,7 @@ def runTruthTrackingGx2f( acts.examples.RootTrackStatesWriter( level=acts.logging.INFO, inputTracks="tracks", - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputTrackParticleMatching="track_particle_matching", inputSimHits="simhits", inputMeasurementSimHitsMap="measurement_simhits_map", @@ -134,7 +137,7 @@ def runTruthTrackingGx2f( acts.examples.RootTrackSummaryWriter( level=acts.logging.INFO, inputTracks="tracks", - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputTrackParticleMatching="track_particle_matching", filePath=str(outputDir / "tracksummary_gx2f.root"), writeGx2fSpecific=True, @@ -145,7 +148,7 @@ def runTruthTrackingGx2f( acts.examples.TrackFitterPerformanceWriter( level=acts.logging.INFO, inputTracks="tracks", - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputTrackParticleMatching="track_particle_matching", filePath=str(outputDir / "performance_gx2f.root"), ) diff --git a/Examples/Scripts/Python/truth_tracking_kalman.py b/Examples/Scripts/Python/truth_tracking_kalman.py index 276cb962c8f..91c18f1dd28 100755 --- a/Examples/Scripts/Python/truth_tracking_kalman.py +++ b/Examples/Scripts/Python/truth_tracking_kalman.py @@ -27,13 +27,13 @@ def runTruthTrackingKalman( EtaConfig, PhiConfig, MomentumConfig, + ParticleSelectorConfig, addFatras, addDigitization, ) from acts.examples.reconstruction import ( addSeeding, SeedingAlgorithm, - TruthSeedRanges, addKalmanTracks, ) @@ -82,6 +82,12 @@ def runTruthTrackingKalman( field, rnd=rnd, enableInteractions=True, + postSelectParticles=ParticleSelectorConfig( + pt=(0.9 * u.GeV, None), + measurements=(7, None), + removeNeutral=True, + removeSecondaries=True, + ), ) else: logger.info("Reading hits from %s", inputHitsPath.resolve()) @@ -110,9 +116,6 @@ def runTruthTrackingKalman( inputParticles="particles_input", seedingAlgorithm=SeedingAlgorithm.TruthSmeared, particleHypothesis=acts.ParticleHypothesis.muon, - truthSeedRanges=TruthSeedRanges( - nHits=(7, None), - ), ) addKalmanTracks( @@ -139,7 +142,7 @@ def runTruthTrackingKalman( acts.examples.RootTrackStatesWriter( level=acts.logging.INFO, inputTracks="tracks", - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputTrackParticleMatching="track_particle_matching", inputSimHits="simhits", inputMeasurementSimHitsMap="measurement_simhits_map", @@ -151,7 +154,7 @@ def runTruthTrackingKalman( acts.examples.RootTrackSummaryWriter( level=acts.logging.INFO, inputTracks="tracks", - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputTrackParticleMatching="track_particle_matching", filePath=str(outputDir / "tracksummary_kf.root"), ) @@ -161,7 +164,7 @@ def runTruthTrackingKalman( acts.examples.TrackFitterPerformanceWriter( level=acts.logging.INFO, inputTracks="tracks", - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputTrackParticleMatching="track_particle_matching", filePath=str(outputDir / "performance_kf.root"), ) diff --git a/Examples/Scripts/Python/truth_tracking_kalman_refitting.py b/Examples/Scripts/Python/truth_tracking_kalman_refitting.py index 7e795b9e310..46578423f33 100755 --- a/Examples/Scripts/Python/truth_tracking_kalman_refitting.py +++ b/Examples/Scripts/Python/truth_tracking_kalman_refitting.py @@ -51,7 +51,7 @@ def runRefittingKf( acts.examples.TrackTruthMatcher( level=acts.logging.INFO, inputTracks="kf_refit_tracks", - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputMeasurementParticlesMap="measurement_particles_map", outputTrackParticleMatching="refit_track_particle_matching", outputParticleTrackMatching="refit_particle_track_matching", @@ -62,7 +62,7 @@ def runRefittingKf( acts.examples.RootTrackStatesWriter( level=acts.logging.INFO, inputTracks="kf_refit_tracks", - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputTrackParticleMatching="refit_track_particle_matching", inputSimHits="simhits", inputMeasurementSimHitsMap="measurement_simhits_map", @@ -74,7 +74,7 @@ def runRefittingKf( acts.examples.RootTrackSummaryWriter( level=acts.logging.INFO, inputTracks="tracks", - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputTrackParticleMatching="refit_track_particle_matching", filePath=str(outputDir / "tracksummary_kf_refit.root"), ) @@ -84,7 +84,7 @@ def runRefittingKf( acts.examples.TrackFitterPerformanceWriter( level=acts.logging.INFO, inputTracks="tracks", - inputParticles="truth_seeds_selected", + inputParticles="particles_selected", inputTrackParticleMatching="track_particle_matching", filePath=str(outputDir / "performance_kf_refit.root"), ) diff --git a/Examples/Scripts/TrackingPerformance/TreeReader.h b/Examples/Scripts/TrackingPerformance/TreeReader.h index 1346d5197ea..4ab47746dc0 100644 --- a/Examples/Scripts/TrackingPerformance/TreeReader.h +++ b/Examples/Scripts/TrackingPerformance/TreeReader.h @@ -36,7 +36,7 @@ struct ParticleInfo { /// struct TreeReader { // The constructor - TreeReader(TTree* tree_) : tree(tree_) {} + explicit TreeReader(TTree* tree_) : tree(tree_) {} // Get entry void getEntry(unsigned int i) const { @@ -400,7 +400,7 @@ struct TrackSummaryReader : public TreeReader { }; /// Struct used for reading particles written out by the -/// TrackFinderPerformanceWriter +/// TrackFinderNTupleWriter /// struct ParticleReader : public TreeReader { // Delete the default constructor diff --git a/Examples/Scripts/fullMaterial.C b/Examples/Scripts/fullMaterial.C index d984a99c675..85ee1092eb5 100644 --- a/Examples/Scripts/fullMaterial.C +++ b/Examples/Scripts/fullMaterial.C @@ -13,6 +13,8 @@ * Author: jhrdinka */ +#include "Acts/Utilities/AngleHelpers.hpp" + #include "TFile.h" #include "TH1F.h" #include "TH2F.h" @@ -111,7 +113,7 @@ fullMaterial(std::string inFile, for (auto& mrecord : mrecords) { std::vector steps = mrecord.materialSteps(); float theta = mrecord.theta(); - float eta = -log(tan(theta * 0.5)); + float eta = Acts::AngleHelpers::etaFromTheta(theta); float phi = VectorHelpers::phi(mrecord); float thickness = 0.; diff --git a/Examples/Scripts/momentumDistributions.C b/Examples/Scripts/momentumDistributions.C index b4aa6e4e3d9..e16a1b709db 100644 --- a/Examples/Scripts/momentumDistributions.C +++ b/Examples/Scripts/momentumDistributions.C @@ -6,6 +6,8 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. +#include "Acts/Utilities/AngleHelpers.hpp" + #include "TFile.h" #include "TH1F.h" #include "TH2F.h" @@ -106,7 +108,7 @@ void momentumDistributions(std::string inFile, std::string treeName, for (int j = 0; j < x->size(); j++) { float hitTheta = std::atan2(std::hypot(x->at(j), y->at(j)), z->at(j)); - hitsEta->Fill(-log(tan(hitTheta * 0.5))); + hitsEta->Fill(Acts::AngleHelpers::etaFromTheta(hitTheta)); hitsTheta->Fill(hitTheta); hitsZ->Fill(z->at(j)); } diff --git a/Fatras/include/ActsFatras/Kernel/Simulation.hpp b/Fatras/include/ActsFatras/Kernel/Simulation.hpp index cbc1115225a..2d8280737f0 100644 --- a/Fatras/include/ActsFatras/Kernel/Simulation.hpp +++ b/Fatras/include/ActsFatras/Kernel/Simulation.hpp @@ -245,6 +245,9 @@ struct Simulation { continue; } + assert(result->particle.particleId() == initialParticle.particleId() && + "Particle id must not change during simulation"); + copyOutputs(result.value(), simulatedParticlesInitial, simulatedParticlesFinal, hits); // since physics processes are independent, there can be particle id @@ -256,6 +259,10 @@ struct Simulation { } } + assert( + (simulatedParticlesInitial.size() == simulatedParticlesFinal.size()) && + "Inconsistent final sizes of the simulated particle containers"); + // the overall function call succeeded, i.e. no fatal errors occurred. // yet, there might have been some particle for which the propagation // failed. thus, the successful result contains a list of failed particles. @@ -284,12 +291,13 @@ struct Simulation { // initial particle state was already pushed to the container before // store final particle state at the end of the simulation particlesFinal.push_back(result.particle); + std::copy(result.hits.begin(), result.hits.end(), std::back_inserter(hits)); + // move generated secondaries that should be simulated to the output std::copy_if( result.generatedParticles.begin(), result.generatedParticles.end(), std::back_inserter(particlesInitial), [this](const Particle &particle) { return selectParticle(particle); }); - std::copy(result.hits.begin(), result.hits.end(), std::back_inserter(hits)); } /// Renumber particle ids in the tail of the container. diff --git a/Fatras/include/ActsFatras/Kernel/detail/SimulationActor.hpp b/Fatras/include/ActsFatras/Kernel/detail/SimulationActor.hpp index cc6d7200868..acbaaaa713d 100644 --- a/Fatras/include/ActsFatras/Kernel/detail/SimulationActor.hpp +++ b/Fatras/include/ActsFatras/Kernel/detail/SimulationActor.hpp @@ -69,7 +69,17 @@ struct SimulationActor { void act(propagator_state_t &state, stepper_t &stepper, navigator_t &navigator, result_type &result, const Acts::Logger &logger) const { - assert(generator && "The generator pointer must be valid"); + assert(generator != nullptr && "The generator pointer must be valid"); + + if (state.stage == Acts::PropagatorStage::prePropagation) { + // first step is special: there is no previous state and we need to arm + // the decay simulation for all future steps. + result.particle = + makeParticle(initialParticle, state, stepper, navigator); + result.properTimeLimit = + decay.generateProperTimeLimit(*generator, initialParticle); + return; + } // actors are called once more after the propagation terminated if (!result.isAlive) { @@ -82,28 +92,11 @@ struct SimulationActor { return; } - // check if we are still on the start surface and skip if so - if ((navigator.startSurface(state.navigation) != nullptr) && - (navigator.startSurface(state.navigation) == - navigator.currentSurface(state.navigation))) { - return; - } - // update the particle state first. this also computes the proper time which // needs the particle state from the previous step for reference. that means // this must happen for every step (not just on surface) and before // everything, e.g. any interactions that could modify the state. - if (std::isnan(result.properTimeLimit)) { - // first step is special: there is no previous state and we need to arm - // the decay simulation for all future steps. - result.particle = - makeParticle(initialParticle, state, stepper, navigator); - result.properTimeLimit = - decay.generateProperTimeLimit(*generator, initialParticle); - } else { - result.particle = - makeParticle(result.particle, state, stepper, navigator); - } + result.particle = makeParticle(result.particle, state, stepper, navigator); // decay check. needs to happen at every step, not just on surfaces. if (std::isfinite(result.properTimeLimit) && diff --git a/Fatras/include/ActsFatras/Utilities/LandauDistribution.hpp b/Fatras/include/ActsFatras/Utilities/LandauDistribution.hpp index 5fe4f57280c..2b29bd89066 100644 --- a/Fatras/include/ActsFatras/Utilities/LandauDistribution.hpp +++ b/Fatras/include/ActsFatras/Utilities/LandauDistribution.hpp @@ -51,7 +51,7 @@ class LandauDistribution { /// Construct directly from the distribution parameters. LandauDistribution(double location, double scale) : m_cfg(location, scale) {} /// Construct from a parameter object. - LandauDistribution(const param_type &cfg) : m_cfg(cfg) {} + explicit LandauDistribution(const param_type &cfg) : m_cfg(cfg) {} // Explicitlely defaulted construction and assignment LandauDistribution() = default; LandauDistribution(const LandauDistribution &) = default; diff --git a/Plugins/ActSVG/include/Acts/Plugins/ActSVG/IndexedSurfacesSvgConverter.hpp b/Plugins/ActSVG/include/Acts/Plugins/ActSVG/IndexedSurfacesSvgConverter.hpp index 79397aba878..788ac36aca5 100644 --- a/Plugins/ActSVG/include/Acts/Plugins/ActSVG/IndexedSurfacesSvgConverter.hpp +++ b/Plugins/ActSVG/include/Acts/Plugins/ActSVG/IndexedSurfacesSvgConverter.hpp @@ -170,7 +170,7 @@ ProtoIndexedSurfaceGrid convertImpl(const GeometryContext& gctx, } } } - return std::tie(pSurfaces, pGrid, highlightIndices); + return {pSurfaces, pGrid, highlightIndices}; } /// @brief Convert the single delegate if it is of the type of the reference diff --git a/Plugins/ActSVG/include/Acts/Plugins/ActSVG/SvgUtils.hpp b/Plugins/ActSVG/include/Acts/Plugins/ActSVG/SvgUtils.hpp index 38189871efb..d2326694b5d 100644 --- a/Plugins/ActSVG/include/Acts/Plugins/ActSVG/SvgUtils.hpp +++ b/Plugins/ActSVG/include/Acts/Plugins/ActSVG/SvgUtils.hpp @@ -59,7 +59,7 @@ struct Style { str._hl_width = highlightStrokeWidth; str._dasharray = strokeDasharray; - return std::tie(fll, str); + return {fll, str}; } /// Conversion to fill, stroke and font diff --git a/Plugins/ActSVG/src/SurfaceArraySvgConverter.cpp b/Plugins/ActSVG/src/SurfaceArraySvgConverter.cpp index 794bb1d43b5..5cffbe73a1a 100644 --- a/Plugins/ActSVG/src/SurfaceArraySvgConverter.cpp +++ b/Plugins/ActSVG/src/SurfaceArraySvgConverter.cpp @@ -206,5 +206,5 @@ Acts::Svg::SurfaceArrayConverter::convert( // Return the surfaces and the grid std::vector pSurfaceBatches = {pSurfaces}; std::vector pAssociationBatchs = {pAssociations}; - return std::tie(pSurfaceBatches, pGrid, pAssociationBatchs); + return {pSurfaceBatches, pGrid, pAssociationBatchs}; } diff --git a/Plugins/DD4hep/include/Acts/Plugins/DD4hep/DD4hepDetectorStructure.hpp b/Plugins/DD4hep/include/Acts/Plugins/DD4hep/DD4hepDetectorStructure.hpp index a11601b579b..eb69176aa19 100644 --- a/Plugins/DD4hep/include/Acts/Plugins/DD4hep/DD4hepDetectorStructure.hpp +++ b/Plugins/DD4hep/include/Acts/Plugins/DD4hep/DD4hepDetectorStructure.hpp @@ -55,9 +55,9 @@ class DD4hepDetectorStructure { /// @param logger is the screen output logger /// /// @note this needs to be provided - DD4hepDetectorStructure(std::unique_ptr logger = - getDefaultLogger("DD4hepLayerStructure", - Acts::Logging::INFO)); + explicit DD4hepDetectorStructure(std::unique_ptr logger = + getDefaultLogger("DD4hepLayerStructure", + Acts::Logging::INFO)); DD4hepDetectorStructure() = delete; diff --git a/Plugins/DD4hep/include/Acts/Plugins/DD4hep/DD4hepDetectorSurfaceFactory.hpp b/Plugins/DD4hep/include/Acts/Plugins/DD4hep/DD4hepDetectorSurfaceFactory.hpp index d6855443af2..b120358d537 100644 --- a/Plugins/DD4hep/include/Acts/Plugins/DD4hep/DD4hepDetectorSurfaceFactory.hpp +++ b/Plugins/DD4hep/include/Acts/Plugins/DD4hep/DD4hepDetectorSurfaceFactory.hpp @@ -90,7 +90,7 @@ class DD4hepDetectorSurfaceFactory { /// The DD4hep detector element factory /// /// @param mlogger a screen output logger - DD4hepDetectorSurfaceFactory( + explicit DD4hepDetectorSurfaceFactory( std::unique_ptr mlogger = getDefaultLogger( "DD4hepDetectorSurfaceFactory", Acts::Logging::INFO)); diff --git a/Plugins/DD4hep/include/Acts/Plugins/DD4hep/DD4hepFieldAdapter.hpp b/Plugins/DD4hep/include/Acts/Plugins/DD4hep/DD4hepFieldAdapter.hpp index 9d2007235e5..6f7b8077348 100644 --- a/Plugins/DD4hep/include/Acts/Plugins/DD4hep/DD4hepFieldAdapter.hpp +++ b/Plugins/DD4hep/include/Acts/Plugins/DD4hep/DD4hepFieldAdapter.hpp @@ -22,7 +22,7 @@ class DD4hepFieldAdapter : public Acts::MagneticFieldProvider { struct Cache {}; public: - DD4hepFieldAdapter(dd4hep::OverlayedField field); + explicit DD4hepFieldAdapter(dd4hep::OverlayedField field); MagneticFieldProvider::Cache makeCache( const Acts::MagneticFieldContext& mctx) const override; diff --git a/Plugins/DD4hep/src/DD4hepDetectorStructure.cpp b/Plugins/DD4hep/src/DD4hepDetectorStructure.cpp index ca4ae439004..00a5017fca9 100644 --- a/Plugins/DD4hep/src/DD4hepDetectorStructure.cpp +++ b/Plugins/DD4hep/src/DD4hepDetectorStructure.cpp @@ -75,7 +75,7 @@ Acts::Experimental::DD4hepDetectorStructure::construct( detail::BlueprintDrawer::dotStream(bpf, *dd4hepBlueprint); bpf.close(); // Return without building - return std::tie(detector, detectorStore); + return {detector, detectorStore}; } // Create a Cylindrical detector builder from this blueprint @@ -100,5 +100,5 @@ Acts::Experimental::DD4hepDetectorStructure::construct( "DD4hepDetectorStructure: Only cylindrical detectors are (currently) " "supported."); } - return std::tie(detector, detectorStore); + return {detector, detectorStore}; } diff --git a/Plugins/Detray/include/Acts/Plugins/Detray/DetrayConversionUtils.hpp b/Plugins/Detray/include/Acts/Plugins/Detray/DetrayConversionUtils.hpp index 201aeb2807d..2f827a08bea 100644 --- a/Plugins/Detray/include/Acts/Plugins/Detray/DetrayConversionUtils.hpp +++ b/Plugins/Detray/include/Acts/Plugins/Detray/DetrayConversionUtils.hpp @@ -20,6 +20,10 @@ namespace Acts { +namespace Experimental { +class DetectorVolume; +} + using DetrayHostDetector = detray::detector; namespace DetrayConversionUtils { @@ -28,12 +32,37 @@ namespace DetrayConversionUtils { /// /// This object is used to synchronize link information between the /// different converters (geometry, material, surface grids) -struct GeometryIdCache { - /// This is a multimap to pass volume local surface link information - /// The portal splitting requires a multimap implementation here - std::multimap localSurfaceLinks; +struct Cache { + /// Explicit constructor with detector volumes + /// + /// @param detectorVolumes the number of detector volumes + Cache(const std::vector& dVolumes) + : detectorVolumes(dVolumes) {} + + /// The volumes of the detector for index lookup + std::vector detectorVolumes; /// This is a map to pass on volume link information std::map volumeLinks; + /// This is a multimap to pass volume local surface link information + /// The portal splitting requires a multimap implementation here + /// + /// These are volume local, hence indexed per volumes + std::map> + localSurfaceLinks; + + /// Find the position of the volume to point to + /// + /// @param volume the volume to find + /// + /// @note throws exception if volume is not found + std::size_t volumeIndex( + const Acts::Experimental::DetectorVolume* volume) const { + auto candidate = std::ranges::find(detectorVolumes, volume); + if (candidate != detectorVolumes.end()) { + return std::distance(detectorVolumes.begin(), candidate); + } + throw std::invalid_argument("Volume not found in the cache"); + } }; /// Convert the binning option diff --git a/Plugins/Detray/include/Acts/Plugins/Detray/DetrayConverter.hpp b/Plugins/Detray/include/Acts/Plugins/Detray/DetrayConverter.hpp index 2c8ca2c7fac..104c71e1893 100644 --- a/Plugins/Detray/include/Acts/Plugins/Detray/DetrayConverter.hpp +++ b/Plugins/Detray/include/Acts/Plugins/Detray/DetrayConverter.hpp @@ -38,8 +38,9 @@ class DetrayConverter { }; /// Constructor with logger - DetrayConverter(std::unique_ptr logger = - getDefaultLogger("DetrayConverter", Logging::INFO)); + explicit DetrayConverter( + std::unique_ptr logger = getDefaultLogger("DetrayConverter", + Logging::INFO)); /// Convert an Acts::Experimental::Detector to a detray::detector object /// @@ -54,7 +55,7 @@ class DetrayConverter { const Experimental::Detector& detector, vecmem::memory_resource& mr, const Options& options) { // The building cache object - DetrayConversionUtils::GeometryIdCache geoIdCache; + DetrayConversionUtils::Cache cCache(detector.volumes()); typename detector_t::name_map names = {{0u, detector.name()}}; @@ -62,7 +63,7 @@ class DetrayConverter { detray::detector_builder detectorBuilder{}; // (1) geometry detray::io::detector_payload detectorPayload = - DetrayGeometryConverter::convertDetector(geoIdCache, gctx, detector, + DetrayGeometryConverter::convertDetector(cCache, gctx, detector, logger()); detray::io::geometry_reader::convert(detectorBuilder, names, detectorPayload); @@ -72,7 +73,7 @@ class DetrayConverter { if (options.convertMaterial) { detray::io::detector_homogeneous_material_payload materialSlabsPayload = DetrayMaterialConverter::convertHomogeneousSurfaceMaterial( - geoIdCache, detector, logger()); + cCache, detector, logger()); detray::io::homogeneous_material_reader::convert( detectorBuilder, names, std::move(materialSlabsPayload)); } @@ -85,7 +86,7 @@ class DetrayConverter { detray::io::material_id> materialGridsPayload = DetrayMaterialConverter::convertGridSurfaceMaterial( - geoIdCache, detector, logger()); + cCache, detector, logger()); detray::io::material_map_reader>::convert(detectorBuilder, names, std::move( diff --git a/Plugins/Detray/include/Acts/Plugins/Detray/DetrayGeometryConverter.hpp b/Plugins/Detray/include/Acts/Plugins/Detray/DetrayGeometryConverter.hpp index 2df31096746..b6ea1373125 100644 --- a/Plugins/Detray/include/Acts/Plugins/Detray/DetrayGeometryConverter.hpp +++ b/Plugins/Detray/include/Acts/Plugins/Detray/DetrayGeometryConverter.hpp @@ -64,25 +64,25 @@ detray::io::surface_payload convertSurface(const GeometryContext& gctx, /// Conversion method for Portal object to detray::portal payloads /// +/// @param cCache [in, out] object /// @param gctx the geometry context /// @param portal the portal to be converted /// @param ip the portal index /// @param volume the volume to which the portal belongs /// @param orientedSurfaces the oriented surfaces of the portal -/// @param detectorVolumes the detector volumes for the link lookup /// /// @note due to portal splitting this can add up in N portals for one initial one /// /// @brief convert the acts portal to detray surface payload and populate the payload std::vector convertPortal( - const GeometryContext& gctx, const Experimental::Portal& portal, - std::size_t ip, const Experimental::DetectorVolume& volume, - const std::vector& orientedSurfaces, - const std::vector& detectorVolumes); + DetrayConversionUtils::Cache& cCache, const GeometryContext& gctx, + const Experimental::Portal& portal, std::size_t ip, + const Experimental::DetectorVolume& volume, + const std::vector& orientedSurfaces); /// Conversion method for volume objects to detray::volume payloads /// -/// @param geoIdCache [in, out] object +/// @param cCache [in, out] object /// @param gctx the geometry context /// @param volume the volume to be converted /// @param detectorVolumes the detector volumes for the link lookup @@ -90,23 +90,20 @@ std::vector convertPortal( /// /// @return the volume_payload for portals and volumes by @param volume acts object detray::io::volume_payload convertVolume( - DetrayConversionUtils::GeometryIdCache& geoIdCache, - const GeometryContext& gctx, const Experimental::DetectorVolume& volume, - const std::vector& detectorVolumes, - const Acts::Logger& logger); + DetrayConversionUtils::Cache& cCache, const GeometryContext& gctx, + const Experimental::DetectorVolume& volume, const Acts::Logger& logger); /// Conversion method for detector objects to detray::detector payload /// -/// @param geoIdCache [in, out] object +/// @param cCache [in, out] object /// @param gctx the geometry context /// @param detector the detector to be converted /// @param logger the logger object for screen output /// /// @return the detector_payload for portals and volumes by @param detector acts object detray::io::detector_payload convertDetector( - DetrayConversionUtils::GeometryIdCache& geoIdCache, - const GeometryContext& gctx, const Experimental::Detector& detector, - const Acts::Logger& logger); + DetrayConversionUtils::Cache& cCache, const GeometryContext& gctx, + const Experimental::Detector& detector, const Acts::Logger& logger); } // namespace DetrayGeometryConverter } // namespace Acts diff --git a/Plugins/Detray/include/Acts/Plugins/Detray/DetrayMaterialConverter.hpp b/Plugins/Detray/include/Acts/Plugins/Detray/DetrayMaterialConverter.hpp index d3be849e362..70a2c8cec73 100644 --- a/Plugins/Detray/include/Acts/Plugins/Detray/DetrayMaterialConverter.hpp +++ b/Plugins/Detray/include/Acts/Plugins/Detray/DetrayMaterialConverter.hpp @@ -35,15 +35,15 @@ detray::io::material_slab_payload convertMaterialSlab( /// Conversion method for homogeneous material /// -/// @param geoIdCache object to have the link association from the geometry building +/// @param cCache object to have the link association from the geometry building /// @param detector the detector object /// @param logger the logger object for screen output /// /// @return the volume_payload for portals and volumes by @param volume acts object detray::io::detector_homogeneous_material_payload -convertHomogeneousSurfaceMaterial( - const DetrayConversionUtils::GeometryIdCache& geoIdCache, - const Experimental::Detector& detector, const Logger& logger); +convertHomogeneousSurfaceMaterial(const DetrayConversionUtils::Cache& cCache, + const Experimental::Detector& detector, + const Logger& logger); /// Conversion method for grid based surface material /// @@ -58,16 +58,16 @@ convertGridSurfaceMaterial(const ISurfaceMaterial& material, /// Conversion method for material grids /// -/// @param geoIdCache object to have the link association from the geometry building +/// @param cCache object to have the link association from the geometry building /// @param detector the detector object /// @param logger the logger object for screen output /// /// @return the volume_payload for portals and volumes by @param volume acts object detray::io::detector_grids_payload -convertGridSurfaceMaterial( - const DetrayConversionUtils::GeometryIdCache& geoIdCache, - const Experimental::Detector& detector, const Logger& logger); +convertGridSurfaceMaterial(const DetrayConversionUtils::Cache& cCache, + const Experimental::Detector& detector, + const Logger& logger); } // namespace DetrayMaterialConverter diff --git a/Plugins/Detray/src/DetrayGeometryConverter.cpp b/Plugins/Detray/src/DetrayGeometryConverter.cpp index 664900841f0..23eb56a0f8c 100644 --- a/Plugins/Detray/src/DetrayGeometryConverter.cpp +++ b/Plugins/Detray/src/DetrayGeometryConverter.cpp @@ -27,25 +27,6 @@ using namespace detray; -namespace { - -/// Find the position of the volume to point to -/// -/// @param volume the volume to find -/// @param the collection of volumes -/// -/// @note return -1 if not found, to be interpreted by the caller -int findVolume( - const Acts::Experimental::DetectorVolume* volume, - const std::vector& volumes) { - auto candidate = std::ranges::find(volumes, volume); - if (candidate != volumes.end()) { - return std::distance(volumes.begin(), candidate); - } - return -1; -} -} // namespace - detray::io::transform_payload Acts::DetrayGeometryConverter::convertTransform( const Transform3& t) { detray::io::transform_payload tfPayload; @@ -87,10 +68,10 @@ detray::io::surface_payload Acts::DetrayGeometryConverter::convertSurface( std::vector Acts::DetrayGeometryConverter::convertPortal( - const GeometryContext& gctx, const Experimental::Portal& portal, - std::size_t ip, const Experimental::DetectorVolume& volume, - const std::vector& orientedSurfaces, - const std::vector& detectorVolumes) { + DetrayConversionUtils::Cache& cCache, const GeometryContext& gctx, + const Experimental::Portal& portal, std::size_t ip, + const Experimental::DetectorVolume& volume, + const std::vector& orientedSurfaces) { std::vector portals{}; const RegularSurface& surface = portal.surface(); @@ -135,7 +116,7 @@ Acts::DetrayGeometryConverter::convertPortal( // in order to make sure the size is adjusted if (singleLink != nullptr) { // Single link can be written out - std::size_t vLink = findVolume(singleLink->object(), detectorVolumes); + std::size_t vLink = cCache.volumeIndex(singleLink->object()); auto portalPayload = convertSurface(gctx, *surfaceAdjusted, true); portalPayload.mask.volume_link.link = vLink; portals.push_back(portalPayload); @@ -161,10 +142,10 @@ Acts::DetrayGeometryConverter::convertPortal( auto surfaceType = surfaceAdjusted->type(); std::vector vIndices = {}; for (const auto& v : volumes) { - vIndices.push_back(findVolume(v, detectorVolumes)); + vIndices.push_back(cCache.volumeIndex(v)); } - // Pick the surface dimension - via poly + // Pick the surface dimension std::array clipRange = {0., 0.}; std::vector boundValues = surfaceAdjusted->bounds().values(); if (surfaceType == Surface::SurfaceType::Cylinder && @@ -227,6 +208,7 @@ Acts::DetrayGeometryConverter::convertPortal( 0., 0., clippedBoundaries[ib - 1u] + subBoundValues[CylinderBounds::BoundValues::eHalfLengthZ])); + auto subSurface = Surface::makeShared(subTransform, subBounds); subSurface->assignGeometryId(surface.geometryId()); @@ -251,6 +233,7 @@ Acts::DetrayGeometryConverter::convertPortal( auto subBounds = std::make_shared(subBoundValues); auto subSurface = Surface::makeShared( portal.surface().transform(gctx), subBounds); + subSurface->assignGeometryId(surface.geometryId()); auto portalPayload = convertSurface(gctx, *subSurface, true); portalPayload.mask.volume_link.link = clippedIndices[ib - 1u]; @@ -260,7 +243,6 @@ Acts::DetrayGeometryConverter::convertPortal( } } else { - // End of world portal // Write surface with invalid link auto portalPayload = convertSurface(gctx, *surfaceAdjusted, true); using NavigationLink = @@ -271,27 +253,27 @@ Acts::DetrayGeometryConverter::convertPortal( portals.push_back(portalPayload); } } - return portals; } detray::io::volume_payload Acts::DetrayGeometryConverter::convertVolume( - DetrayConversionUtils::GeometryIdCache& geoIdCache, - const GeometryContext& gctx, + DetrayConversionUtils::Cache& cCache, const GeometryContext& gctx, const Acts::Experimental::DetectorVolume& volume, - const std::vector& detectorVolumes, const Acts::Logger& logger) { ACTS_DEBUG("DetrayGeometryConverter: converting volume " << volume.name() << " with " << volume.surfaces().size() << " surfaces and " << volume.portals().size() << " portals"); detray::io::volume_payload volumePayload; + std::size_t volumeIndex = cCache.volumeIndex(&volume); volumePayload.name = volume.name(); - volumePayload.index.link = findVolume(&volume, detectorVolumes); + volumePayload.index.link = volumeIndex; volumePayload.transform = convertTransform(volume.transform(gctx)); // Remember the link - geoIdCache.volumeLinks[volume.geometryId()] = volumePayload.index.link; + cCache.volumeLinks[volume.geometryId()] = volumePayload.index.link; + + std::multimap localSurfaceLinks; // iterate over surfaces and portals keeping the same surf_pd.index_in_coll std::size_t sIndex = 0; @@ -299,7 +281,7 @@ detray::io::volume_payload Acts::DetrayGeometryConverter::convertVolume( io::surface_payload surfacePayload = convertSurface(gctx, *surface, false); // Set the index in the collection & remember it in the cache surfacePayload.index_in_coll = sIndex++; - geoIdCache.localSurfaceLinks.insert( + localSurfaceLinks.insert( {surface->geometryId(), surfacePayload.index_in_coll.value()}); // Set mask to volume link surfacePayload.mask.volume_link.link = @@ -314,30 +296,32 @@ detray::io::volume_payload Acts::DetrayGeometryConverter::convertVolume( int portalCounter = 0; for (const auto& [ip, p] : enumerate(volume.portals())) { auto portals = - convertPortal(gctx, *p, ip, volume, orientedSurfaces, detectorVolumes); - + convertPortal(cCache, gctx, *p, ip, volume, orientedSurfaces); + ACTS_VERBOSE(" > portal " << ip << " split into " << portals.size() + << " surfaces"); GeometryIdentifier geoID = p->surface().geometryId(); std::for_each(portals.begin(), portals.end(), [&](auto& portalPayload) { // Set the index in the collection & remember it in the cache portalPayload.index_in_coll = sIndex++; - geoIdCache.localSurfaceLinks.insert( - {geoID, portalPayload.index_in_coll.value()}); + localSurfaceLinks.insert({geoID, portalPayload.index_in_coll.value()}); // Add it to the surfaces volumePayload.surfaces.push_back(portalPayload); portalCounter++; }); } - ACTS_VERBOSE(" > " << volume.portals().size() - << " initial ACTS portals split into final " - << portalCounter << " detray portals"); + cCache.localSurfaceLinks[volumeIndex] = localSurfaceLinks; + ACTS_DEBUG(" > " << volume.portals().size() + << " initial ACTS portals split into final " << portalCounter + << " detray portals"); + ACTS_VERBOSE(" > Local surface link cache has " << localSurfaceLinks.size() + << " entries"); return volumePayload; } detray::io::detector_payload Acts::DetrayGeometryConverter::convertDetector( - DetrayConversionUtils::GeometryIdCache& geoIdCache, - const GeometryContext& gctx, const Acts::Experimental::Detector& detector, - const Acts::Logger& logger) { + DetrayConversionUtils::Cache& cCache, const GeometryContext& gctx, + const Acts::Experimental::Detector& detector, const Acts::Logger& logger) { ACTS_DEBUG("DetrayGeometryConverter: converting detector" << detector.name() << " with " << detector.volumes().size() << " volumes."); @@ -347,7 +331,7 @@ detray::io::detector_payload Acts::DetrayGeometryConverter::convertDetector( for (const auto volume : detector.volumes()) { detectorPayload.volumes.push_back( - convertVolume(geoIdCache, gctx, *volume, detector.volumes(), logger)); + convertVolume(cCache, gctx, *volume, logger)); } return detectorPayload; diff --git a/Plugins/Detray/src/DetrayMaterialConverter.cpp b/Plugins/Detray/src/DetrayMaterialConverter.cpp index dd82b0d1b93..c08bdc447bf 100644 --- a/Plugins/Detray/src/DetrayMaterialConverter.cpp +++ b/Plugins/Detray/src/DetrayMaterialConverter.cpp @@ -52,13 +52,13 @@ Acts::DetrayMaterialConverter::convertMaterialSlab( detray::io::detector_homogeneous_material_payload Acts::DetrayMaterialConverter::convertHomogeneousSurfaceMaterial( - const DetrayConversionUtils::GeometryIdCache& geoIdCache, + const DetrayConversionUtils::Cache& cCache, const Experimental::Detector& detector, const Logger& logger) { detray::io::detector_homogeneous_material_payload materialPayload; for (const auto volume : detector.volumes()) { - auto volumeIndex = geoIdCache.volumeLinks.find(volume->geometryId()); - if (volumeIndex != geoIdCache.volumeLinks.end()) { + auto volumeIndex = cCache.volumeLinks.find(volume->geometryId()); + if (volumeIndex != cCache.volumeLinks.end()) { // The volume material payload & its link detray::io::material_volume_payload volumePayload; detray::io::single_link_payload volumeLink; @@ -80,18 +80,24 @@ Acts::DetrayMaterialConverter::convertHomogeneousSurfaceMaterial( auto materialSlab = homogeneousMaterial->materialSlab(); detray::io::material_slab_payload slabPayload = convertMaterialSlab(materialSlab); - // Find the surfaces and assign - auto surfaceIndices = - geoIdCache.localSurfaceLinks.equal_range(surface->geometryId()); - // Loop over the equal range and fill one grid each, this is needed - // as the initial portal could be split into multiple surfaces - for (auto itr = surfaceIndices.first; itr != surfaceIndices.second; - ++itr) { - // Make an identified link copy for every matching surface - detray::io::single_link_payload surfaceLink; - surfaceLink.link = itr->second; - slabPayload.surface = surfaceLink; - volumePayload.mat_slabs.push_back(slabPayload); + // Find the surfaces to assign + auto vIndex = cCache.volumeIndex(volume); + auto localSurfaceLinks = cCache.localSurfaceLinks.find(vIndex); + if (localSurfaceLinks != cCache.localSurfaceLinks.end()) { + // Find the surface link + auto surfaceIndices = + localSurfaceLinks->second.equal_range(surface->geometryId()); + // Loop over the equal range and fill one grid each, this is needed + // as the initial portal could be split into multiple surfaces + for (auto itr = surfaceIndices.first; itr != surfaceIndices.second; + ++itr) { + // Make an identified link copy for every matching surface + slabPayload.surface.link = itr->second; + volumePayload.mat_slabs.push_back(slabPayload); + } + } else { + ACTS_WARNING( + "DetrayMaterialConverter: no local surface links found"); } } } @@ -232,7 +238,7 @@ Acts::DetrayMaterialConverter::convertGridSurfaceMaterial( detray::io::detector_grids_payload Acts::DetrayMaterialConverter::convertGridSurfaceMaterial( - const DetrayConversionUtils::GeometryIdCache& geoIdCache, + const DetrayConversionUtils::Cache& cCache, const Experimental::Detector& detector, const Logger& logger) { // The material grid payload detray::io::detector_grids_payloadvisitSurfaces(selector); - ACTS_DEBUG("DetrayMaterialConverter: found " - << selector.surfaces.size() - << " surfaces/portals with material in volume " - << volume->name()); + ACTS_VERBOSE("DetrayMaterialConverter: found " + << selector.surfaces.size() + << " surfaces/portals with material in volume " + << volume->name()); // Find the voluem index first - auto volumeIndex = geoIdCache.volumeLinks.find(volume->geometryId()); - if (volumeIndex != geoIdCache.volumeLinks.end()) { + auto volumeIndex = cCache.volumeLinks.find(volume->geometryId()); + if (volumeIndex != cCache.volumeLinks.end()) { std::vector volumeMaterialGrids = {}; // Now convert the surfaces for (const auto& surface : selector.surfaces) { - // Find the surface index - auto surfaceIndices = - geoIdCache.localSurfaceLinks.equal_range(surface->geometryId()); - DetrayMaterialGrid materialGrid = - convertGridSurfaceMaterial(*surface->surfaceMaterial(), logger); - // Ignore if an empty payload is returned - if (materialGrid.axes.empty() && materialGrid.bins.empty()) { - continue; - } - // Loop over the equal range and fill one grid each, this is needed - // as the initial portal could be split into multiple surfaces - for (auto itr = surfaceIndices.first; itr != surfaceIndices.second; - ++itr) { - // Fill the surface index - materialGrid.owner_link = - detray::io::single_link_payload{itr->second}; - // Fill the grid - volumeMaterialGrids.push_back(materialGrid); + // Find the surfaces to assign + auto vIndex = cCache.volumeIndex(volume); + auto localSurfaceLinks = cCache.localSurfaceLinks.find(vIndex); + if (localSurfaceLinks != cCache.localSurfaceLinks.end()) { + // Find the surface link + auto surfaceIndices = + localSurfaceLinks->second.equal_range(surface->geometryId()); + + ACTS_VERBOSE( + "DetrayMaterialConverter: assigning to " + << std::distance(surfaceIndices.first, surfaceIndices.second) + << " surfaces with material in volume " << volume->name()); + DetrayMaterialGrid materialGrid = + convertGridSurfaceMaterial(*surface->surfaceMaterial(), logger); + // Ignore if an empty payload is returned + if (materialGrid.axes.empty() || materialGrid.bins.empty()) { + continue; + } + + // Loop over the equal range and fill one grid each, this is needed + // as the initial portal could be split into multiple surfaces + for (auto itr = surfaceIndices.first; itr != surfaceIndices.second; + ++itr) { + // Fill the surface index + materialGrid.owner_link = + detray::io::single_link_payload{itr->second}; + // Fill the grid + volumeMaterialGrids.push_back(materialGrid); + } } } // Register the grids of this volume materialGrids.grids.insert({volumeIndex->second, volumeMaterialGrids}); - } else { ACTS_WARNING( "DetrayMaterialConverter: volume not found in cache, should not " diff --git a/Plugins/FpeMonitoring/include/Acts/Plugins/FpeMonitoring/FpeMonitor.hpp b/Plugins/FpeMonitoring/include/Acts/Plugins/FpeMonitoring/FpeMonitor.hpp index d1b9fabec64..022a07a3426 100644 --- a/Plugins/FpeMonitoring/include/Acts/Plugins/FpeMonitoring/FpeMonitor.hpp +++ b/Plugins/FpeMonitoring/include/Acts/Plugins/FpeMonitoring/FpeMonitor.hpp @@ -40,7 +40,7 @@ std::ostream &operator<<(std::ostream &os, FpeType type); class FpeMonitor { public: struct Buffer { - Buffer(std::size_t bufferSize) + explicit Buffer(std::size_t bufferSize) : m_data{std::make_unique(bufferSize)}, m_size{bufferSize} {} @@ -105,12 +105,12 @@ class FpeMonitor { Result() = default; - operator bool() const { return !m_stracktraces.empty(); } + bool hasStackTraces() const { return !m_stackTraces.empty(); } void add(Acts::FpeType type, void *stackPtr, std::size_t bufferSize); private: - std::vector m_stracktraces; + std::vector m_stackTraces; std::array m_counts{}; friend FpeMonitor; diff --git a/Plugins/FpeMonitoring/src/FpeMonitor.cpp b/Plugins/FpeMonitoring/src/FpeMonitor.cpp index db41dc1f8b2..09dce1f4b0a 100644 --- a/Plugins/FpeMonitoring/src/FpeMonitor.cpp +++ b/Plugins/FpeMonitoring/src/FpeMonitor.cpp @@ -61,10 +61,10 @@ FpeMonitor::Result FpeMonitor::Result::merged(const Result &with) const { result.m_counts[i] = m_counts[i] + with.m_counts[i]; } - std::copy(with.m_stracktraces.begin(), with.m_stracktraces.end(), - std::back_inserter(result.m_stracktraces)); - std::copy(m_stracktraces.begin(), m_stracktraces.end(), - std::back_inserter(result.m_stracktraces)); + std::copy(with.m_stackTraces.begin(), with.m_stackTraces.end(), + std::back_inserter(result.m_stackTraces)); + std::copy(m_stackTraces.begin(), m_stackTraces.end(), + std::back_inserter(result.m_stackTraces)); result.deduplicate(); @@ -76,8 +76,8 @@ void FpeMonitor::Result::merge(const Result &with) { m_counts[i] = m_counts[i] + with.m_counts[i]; } - std::copy(with.m_stracktraces.begin(), with.m_stracktraces.end(), - std::back_inserter(m_stracktraces)); + std::copy(with.m_stackTraces.begin(), with.m_stackTraces.end(), + std::back_inserter(m_stackTraces)); deduplicate(); } @@ -87,20 +87,20 @@ void FpeMonitor::Result::add(FpeType type, void *stackPtr, auto st = std::make_unique( boost::stacktrace::stacktrace::from_dump(stackPtr, bufferSize)); - auto it = std::ranges::find_if(m_stracktraces, [&](const FpeInfo &el) { + auto it = std::ranges::find_if(m_stackTraces, [&](const FpeInfo &el) { return areFpesEquivalent({el.type, *el.st}, {type, *st}); }); - if (it != m_stracktraces.end()) { + if (it != m_stackTraces.end()) { it->count += 1; } else { - m_stracktraces.push_back({1, type, std::move(st)}); + m_stackTraces.push_back({1, type, std::move(st)}); } } bool FpeMonitor::Result::contains( FpeType type, const boost::stacktrace::stacktrace &st) const { - return std::ranges::any_of(m_stracktraces, [&](const FpeInfo &el) { + return std::ranges::any_of(m_stackTraces, [&](const FpeInfo &el) { return areFpesEquivalent({el.type, *el.st}, {type, st}); }); } @@ -128,12 +128,12 @@ unsigned int FpeMonitor::Result::count(FpeType type) const { } unsigned int FpeMonitor::Result::numStackTraces() const { - return m_stracktraces.size(); + return m_stackTraces.size(); } const std::vector & FpeMonitor::Result::stackTraces() const { - return m_stracktraces; + return m_stackTraces; } bool FpeMonitor::Result::encountered(FpeType type) const { @@ -161,18 +161,18 @@ void FpeMonitor::Result::summary(std::ostream &os, std::size_t depth) const { void FpeMonitor::Result::deduplicate() { std::vector copy{}; - copy = std::move(m_stracktraces); - m_stracktraces.clear(); + copy = std::move(m_stackTraces); + m_stackTraces.clear(); for (auto &info : copy) { - auto it = std::ranges::find_if(m_stracktraces, [&info](const FpeInfo &el) { + auto it = std::ranges::find_if(m_stackTraces, [&info](const FpeInfo &el) { return areFpesEquivalent({el.type, *el.st}, {info.type, *info.st}); }); - if (it != m_stracktraces.end()) { + if (it != m_stackTraces.end()) { it->count += info.count; continue; } - m_stracktraces.push_back({info.count, info.type, std::move(info.st)}); + m_stackTraces.push_back({info.count, info.type, std::move(info.st)}); } } diff --git a/Plugins/Geant4/include/Acts/Plugins/Geant4/Geant4PhysicalVolumeSelectors.hpp b/Plugins/Geant4/include/Acts/Plugins/Geant4/Geant4PhysicalVolumeSelectors.hpp index 1fab98ea834..fd05274a34d 100644 --- a/Plugins/Geant4/include/Acts/Plugins/Geant4/Geant4PhysicalVolumeSelectors.hpp +++ b/Plugins/Geant4/include/Acts/Plugins/Geant4/Geant4PhysicalVolumeSelectors.hpp @@ -70,7 +70,7 @@ struct PositionSelector : public IGeant4PhysicalVolumeSelector { /// Constructor with arguments /// @param ranges the provided map of axes of ranges - PositionSelector( + explicit PositionSelector( const std::map>& ranges) : m_ranges(ranges) {} diff --git a/Plugins/Hashing/include/Acts/Plugins/Hashing/HashingTraining.ipp b/Plugins/Hashing/include/Acts/Plugins/Hashing/HashingTraining.ipp index ff9e35c1149..3e24e828177 100644 --- a/Plugins/Hashing/include/Acts/Plugins/Hashing/HashingTraining.ipp +++ b/Plugins/Hashing/include/Acts/Plugins/Hashing/HashingTraining.ipp @@ -8,7 +8,9 @@ #include "Acts/Definitions/Algebra.hpp" #include "Acts/Definitions/Units.hpp" +#include "Acts/Utilities/AngleHelpers.hpp" +#include #include #include @@ -49,7 +51,7 @@ AnnoyModel HashingTrainingAlgorithm::execute( Scalar y = spacePoint->y() / Acts::UnitConstants::mm; // Helix transform - Scalar phi = atan2(y, x); + Scalar phi = std::atan2(y, x); std::vector vec(f); // Avoid potential null pointer dereference @@ -59,9 +61,9 @@ AnnoyModel HashingTrainingAlgorithm::execute( if (f >= 2) { Scalar z = spacePoint->z() / Acts::UnitConstants::mm; Scalar r2 = x * x + y * y; - Scalar rho = sqrt(r2 + z * z); - Scalar theta = acos(z / rho); - Scalar eta = -log(tan(0.5 * theta)); + Scalar rho = std::sqrt(r2 + z * z); + Scalar theta = std::acos(z / rho); + Scalar eta = Acts::AngleHelpers::etaFromTheta(theta); vec[1] = eta; } diff --git a/Plugins/Json/include/Acts/Plugins/Json/GeometryHierarchyMapJsonConverter.hpp b/Plugins/Json/include/Acts/Plugins/Json/GeometryHierarchyMapJsonConverter.hpp index 70f070e9dd7..74ce7109975 100644 --- a/Plugins/Json/include/Acts/Plugins/Json/GeometryHierarchyMapJsonConverter.hpp +++ b/Plugins/Json/include/Acts/Plugins/Json/GeometryHierarchyMapJsonConverter.hpp @@ -42,7 +42,7 @@ class GeometryHierarchyMapJsonConverter { /// Construct the converter. /// /// @param valueIdentifier user-defined identifier for the stored value - GeometryHierarchyMapJsonConverter(std::string valueIdentifier) + explicit GeometryHierarchyMapJsonConverter(std::string valueIdentifier) : m_valueIdentifier(std::move(valueIdentifier)) { if (m_valueIdentifier.empty()) { throw std::invalid_argument("Value identifier must be non-empty"); diff --git a/Plugins/Json/include/Acts/Plugins/Json/GridJsonConverter.hpp b/Plugins/Json/include/Acts/Plugins/Json/GridJsonConverter.hpp index 20065d488bb..3215bd66eae 100644 --- a/Plugins/Json/include/Acts/Plugins/Json/GridJsonConverter.hpp +++ b/Plugins/Json/include/Acts/Plugins/Json/GridJsonConverter.hpp @@ -9,6 +9,7 @@ #pragma once #include "Acts/Plugins/Json/ActsJson.hpp" +#include "Acts/Plugins/Json/TrackParametersJsonConverter.hpp" #include "Acts/Utilities/AxisFwd.hpp" #include "Acts/Utilities/GridAccessHelpers.hpp" #include "Acts/Utilities/IAxis.hpp" @@ -266,15 +267,17 @@ auto fromJson(const nlohmann::json& jGrid, if constexpr (GridType::DIM == 1u) { for (const auto& jd : jData) { std::array lbin = jd[0u]; - value_type values = jd[1u]; - grid.atLocalBins(lbin) = values; + if (!jd[1u].is_null()) { + grid.atLocalBins(lbin) = jd[1u].get(); + } } } if constexpr (GridType::DIM == 2u) { for (const auto& jd : jData) { std::array lbin = jd[0u]; - value_type values = jd[1u]; - grid.atLocalBins(lbin) = values; + if (!jd[1u].is_null()) { + grid.atLocalBins(lbin) = jd[1u].get(); + } } } return grid; diff --git a/Plugins/Json/include/Acts/Plugins/Json/IndexedGridJsonHelper.hpp b/Plugins/Json/include/Acts/Plugins/Json/IndexedGridJsonHelper.hpp index b7717073036..581130a8852 100644 --- a/Plugins/Json/include/Acts/Plugins/Json/IndexedGridJsonHelper.hpp +++ b/Plugins/Json/include/Acts/Plugins/Json/IndexedGridJsonHelper.hpp @@ -83,7 +83,7 @@ updator_type generateFromJson(const nlohmann::json& jUpdater, -> std::tuple, std::size_t> { std::array range = jAxis["range"]; std::size_t bins = jAxis["bins"]; - return std::make_tuple(range, bins); + return {range, bins}; }; /// Helper extractor for variable axis diff --git a/Plugins/Json/include/Acts/Plugins/Json/TrackParametersJsonConverter.hpp b/Plugins/Json/include/Acts/Plugins/Json/TrackParametersJsonConverter.hpp new file mode 100644 index 00000000000..ebf7d5c6054 --- /dev/null +++ b/Plugins/Json/include/Acts/Plugins/Json/TrackParametersJsonConverter.hpp @@ -0,0 +1,221 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#pragma once + +#include "Acts/EventData/TrackParameters.hpp" +#include "Acts/Plugins/Json/ActsJson.hpp" +#include "Acts/Plugins/Json/SurfaceJsonConverter.hpp" + +#include + +namespace { + +// Alias to bound adl_serializer specialization +// only to track parameters +template +concept TrackParameters = Acts::FreeTrackParametersConcept || + Acts::BoundTrackParametersConcept; + +// Shorthand for bound track parameters +template +concept IsGenericBound = + std::same_as>; + +} // namespace + +namespace Acts { +NLOHMANN_JSON_SERIALIZE_ENUM(Acts::PdgParticle, + + {{Acts::PdgParticle::eInvalid, "Invalid"}, + {Acts::PdgParticle::eElectron, "Electron"}, + {Acts::PdgParticle::eAntiElectron, + "AntiElectron"}, + {Acts::PdgParticle::ePositron, "Positron"}, + {Acts::PdgParticle::eMuon, "Muon"}, + {Acts::PdgParticle::eAntiMuon, "AntiMuon"}, + {Acts::PdgParticle::eTau, "Tau"}, + {Acts::PdgParticle::eAntiTau, "AntiTau"}, + {Acts::PdgParticle::eGamma, "Gamma"}, + {Acts::PdgParticle::ePionZero, "PionZero"}, + {Acts::PdgParticle::ePionPlus, "PionPlus"}, + {Acts::PdgParticle::ePionMinus, "PionMinus"}, + {Acts::PdgParticle::eKaonPlus, "KaonPlus"}, + {Acts::PdgParticle::eKaonMinus, "KaonMinus"}, + {Acts::PdgParticle::eNeutron, "Neutron"}, + {Acts::PdgParticle::eAntiNeutron, "AntiNeutron"}, + {Acts::PdgParticle::eProton, "Proton"}, + {Acts::PdgParticle::eAntiProton, "AntiProton"}, + {Acts::PdgParticle::eLead, "Lead"}} + +) +} + +namespace nlohmann { + +/// @brief Serialize a track parameters object to json +/// +/// nlohmann::json serializer specialized for track parameters +/// as they are not default constructible. Is able to serialize +/// either bound or free track parameters given that the constructor +/// convention is followed. +/// +/// @tparam parameters_t The track parameters type +template +struct adl_serializer { + /// Covariance matrix type attached to the parameters + using CovarianceMatrix = typename parameters_t::CovarianceMatrix; + + /// @brief Serialize track parameters object to json + /// + /// @param j Json object to write to + /// @param t Track parameters object to serialize + static void to_json(nlohmann::json& j, const parameters_t& t) { + // Serialize parameters + // common to all track parameters + j["direction"] = t.direction(); + j["qOverP"] = t.qOverP(); + j["particleHypothesis"] = t.particleHypothesis().absolutePdg(); + + // Covariance is optional + j["covariance"]; + if (t.covariance().has_value()) { + // Extract covariance matrix + // parameters and serialize + auto cov = t.covariance().value(); + constexpr unsigned int size = cov.rows(); + std::array covData{}; + for (std::size_t n = 0; n < size; ++n) { + for (std::size_t m = 0; m < size; ++m) { + covData[n * size + m] = cov(n, m); + } + } + j["covariance"] = covData; + } + // Bound track parameters have + // reference surface attached + // and position takes a geometry context + if constexpr (IsGenericBound) { + Acts::GeometryContext gctx; + j["position"] = t.fourPosition(gctx); + + j["referenceSurface"] = + Acts::SurfaceJsonConverter::toJson(gctx, t.referenceSurface()); + } else { + j["position"] = t.fourPosition(); + } + } + + /// @brief Deserialize track parameters object from json + /// + /// @param j Json object to read from + /// @return Track parameters object + static parameters_t from_json(const nlohmann::json& j) { + // Extract common parameters + std::array posData = j.at("position"); + Acts::Vector4 position(posData[0], posData[1], posData[2], posData[3]); + + std::array dirData = j.at("direction"); + Acts::Vector3 direction(dirData[0], dirData[1], dirData[2]); + + Acts::ActsScalar qOverP = j.at("qOverP"); + Acts::PdgParticle absPdg = j.at("particleHypothesis"); + + // Covariance is optional + std::optional cov; + if (j.at("covariance").is_null()) { + cov = std::nullopt; + } else { + // Extract covariance matrix + // parameters and deserialize + CovarianceMatrix mat; + constexpr unsigned int size = mat.rows(); + std::array covData = j.at("covariance"); + for (std::size_t n = 0; n < size; ++n) { + for (std::size_t m = 0; m < size; ++m) { + mat(n, m) = covData[n * size + m]; + } + } + cov.emplace(std::move(mat)); + } + + // Create particle hypothesis + typename parameters_t::ParticleHypothesis particle(absPdg); + + // Bound track parameters have + // reference surface attached + // and constructor is hidden + // behind a factory method + if constexpr (IsGenericBound) { + Acts::GeometryContext gctx; + auto referenceSurface = + Acts::SurfaceJsonConverter::fromJson(j.at("referenceSurface")); + + auto res = parameters_t::create(referenceSurface, gctx, position, + direction, qOverP, cov, particle); + + if (!res.ok()) { + throw std::invalid_argument("Invalid bound track parameters"); + } + return res.value(); + } else { + return parameters_t(position, direction, qOverP, cov, particle); + } + } +}; + +/// @brief Serialize a shared pointer to track parameters object to json +/// +/// nlohmann::json serializer specialized for shared pointers to track +/// parameters as they are not default constructible. Is able to serialize +/// either bound or free track parameters given that the constructor +/// convention is followed. +/// +/// @tparam parameters_t The track parameters type +template +struct adl_serializer> { + using CovarianceMatrix = typename parameters_t::CovarianceMatrix; + static void to_json(nlohmann::json& j, + const std::shared_ptr& t) { + if (t == nullptr) { + return; + } + j = *t; + } + + static std::shared_ptr from_json(const nlohmann::json& j) { + return std::make_shared(j.get()); + } +}; + +/// @brief Serialize a unique pointer to track parameters object to json +/// +/// nlohmann::json serializer specialized for unique pointers to track +/// parameters as they are not default constructible. Is able to serialize +/// either bound or free track parameters given that the constructor +/// convention is followed. +/// +/// @tparam parameters_t The track parameters type +template +struct adl_serializer> { + using CovarianceMatrix = typename parameters_t::CovarianceMatrix; + static void to_json(nlohmann::json& j, + const std::unique_ptr& t) { + if (t == nullptr) { + return; + } + j = *t; + } + + static std::unique_ptr from_json(const nlohmann::json& j) { + return std::make_unique(j.get()); + } +}; + +} // namespace nlohmann diff --git a/Plugins/Json/src/DetrayJsonHelper.cpp b/Plugins/Json/src/DetrayJsonHelper.cpp index aa61a9d8aeb..e902657da21 100644 --- a/Plugins/Json/src/DetrayJsonHelper.cpp +++ b/Plugins/Json/src/DetrayJsonHelper.cpp @@ -50,7 +50,7 @@ std::tuple> maskFromBounds( break; } } - return std::tie(type, boundaries); + return {type, boundaries}; } void addVolumeLink(nlohmann::json& jSurface, int vLink) { diff --git a/Plugins/Json/src/MaterialMapJsonConverter.cpp b/Plugins/Json/src/MaterialMapJsonConverter.cpp index 76fc01f8569..2424156ec1d 100644 --- a/Plugins/Json/src/MaterialMapJsonConverter.cpp +++ b/Plugins/Json/src/MaterialMapJsonConverter.cpp @@ -253,8 +253,8 @@ nlohmann::json Acts::MaterialMapJsonConverter::materialMapsToJson( VolumeMaterialMap volumeMap = maps.second; std::vector> mapVolumeInit; - for (auto it = volumeMap.begin(); it != volumeMap.end(); it++) { - mapVolumeInit.push_back({it->first, it->second.get()}); + for (const auto& [key, value] : volumeMap) { + mapVolumeInit.push_back({key, value.get()}); } GeometryHierarchyMap hierarchyVolumeMap( mapVolumeInit); @@ -263,8 +263,8 @@ nlohmann::json Acts::MaterialMapJsonConverter::materialMapsToJson( SurfaceMaterialMap surfaceMap = maps.first; std::vector> mapSurfaceInit; - for (auto it = surfaceMap.begin(); it != surfaceMap.end(); it++) { - mapSurfaceInit.push_back({it->first, it->second.get()}); + for (const auto& [key, value] : surfaceMap) { + mapSurfaceInit.push_back({key, value.get()}); } GeometryHierarchyMap hierarchySurfaceMap( mapSurfaceInit); diff --git a/Plugins/Podio/include/Acts/Plugins/Podio/PodioDynamicColumns.hpp b/Plugins/Podio/include/Acts/Plugins/Podio/PodioDynamicColumns.hpp index d72e78bd9f2..295937efe7e 100644 --- a/Plugins/Podio/include/Acts/Plugins/Podio/PodioDynamicColumns.hpp +++ b/Plugins/Podio/include/Acts/Plugins/Podio/PodioDynamicColumns.hpp @@ -18,7 +18,7 @@ namespace Acts::podio_detail { struct ConstDynamicColumnBase { - ConstDynamicColumnBase(std::string_view name) : m_name{name} {} + explicit ConstDynamicColumnBase(std::string_view name) : m_name{name} {} virtual ~ConstDynamicColumnBase() = default; @@ -45,7 +45,8 @@ struct ConstDynamicColumn : public ConstDynamicColumnBase { }; struct DynamicColumnBase : public ConstDynamicColumnBase { - DynamicColumnBase(std::string_view name) : ConstDynamicColumnBase{name} {} + explicit DynamicColumnBase(std::string_view name) + : ConstDynamicColumnBase{name} {} virtual std::any get(std::size_t i) = 0; std::any get(std::size_t i) const override = 0; diff --git a/Tests/UnitTests/Core/EventData/BoundTrackParametersTests.cpp b/Tests/UnitTests/Core/EventData/BoundTrackParametersTests.cpp index a05d273f7a1..9daf24c8a79 100644 --- a/Tests/UnitTests/Core/EventData/BoundTrackParametersTests.cpp +++ b/Tests/UnitTests/Core/EventData/BoundTrackParametersTests.cpp @@ -76,6 +76,14 @@ void checkParameters(const BoundTrackParameters& params, double l0, double l1, eps); CHECK_CLOSE_OR_SMALL(params.momentum(), p * unitDir, eps, eps); BOOST_CHECK_EQUAL(params.charge(), q); + + // reflection + BoundTrackParameters reflectedParams = params; + reflectedParams.reflectInPlace(); + CHECK_CLOSE_OR_SMALL(params.reflect().parameters(), + reflectedParams.parameters(), eps, eps); + CHECK_CLOSE_OR_SMALL(reflectedParams.reflect().parameters(), + params.parameters(), eps, eps); } void runTest(const std::shared_ptr& surface, double l0, diff --git a/Tests/UnitTests/Core/EventData/CMakeLists.txt b/Tests/UnitTests/Core/EventData/CMakeLists.txt index 61b5079da8e..1efda4cff29 100644 --- a/Tests/UnitTests/Core/EventData/CMakeLists.txt +++ b/Tests/UnitTests/Core/EventData/CMakeLists.txt @@ -16,5 +16,6 @@ add_unittest(MultiTrajectoryHelpers MultiTrajectoryHelpersTests.cpp) add_unittest(SubspaceHelpers SubspaceHelpersTests.cpp) add_unittest(SeedEdm SeedEdmTests.cpp) add_unittest(SpacePointContainerEdm SpacePointContainerEdmTests.cpp) +add_unittest(TrackParameterHelpers TrackParameterHelpersTests.cpp) add_non_compile_test(MultiTrajectory TrackContainerComplianceTests.cpp) diff --git a/Tests/UnitTests/Core/EventData/CurvilinearTrackParametersTests.cpp b/Tests/UnitTests/Core/EventData/CurvilinearTrackParametersTests.cpp index 122d4b075d0..143515148d4 100644 --- a/Tests/UnitTests/Core/EventData/CurvilinearTrackParametersTests.cpp +++ b/Tests/UnitTests/Core/EventData/CurvilinearTrackParametersTests.cpp @@ -72,6 +72,15 @@ void checkParameters(const CurvilinearTrackParameters& params, double phi, // curvilinear reference surface CHECK_CLOSE_OR_SMALL(referenceSurface->center(geoCtx), pos, eps, eps); CHECK_CLOSE_OR_SMALL(referenceSurface->normal(geoCtx), unitDir, eps, eps); + + // reflection + CurvilinearTrackParameters reflectedParams = params; + reflectedParams.reflectInPlace(); + CHECK_CLOSE_OR_SMALL(params.reflect().parameters(), + reflectedParams.parameters(), eps, eps); + CHECK_CLOSE_OR_SMALL(reflectedParams.reflect().parameters(), + params.parameters(), eps, eps); + // TODO verify reference frame } diff --git a/Tests/UnitTests/Core/EventData/FreeTrackParametersTests.cpp b/Tests/UnitTests/Core/EventData/FreeTrackParametersTests.cpp index 71b0dc0a20e..fb7a11f3f68 100644 --- a/Tests/UnitTests/Core/EventData/FreeTrackParametersTests.cpp +++ b/Tests/UnitTests/Core/EventData/FreeTrackParametersTests.cpp @@ -67,6 +67,14 @@ void checkParameters(const FreeTrackParameters& params, const Vector4& pos4, eps); CHECK_CLOSE_OR_SMALL(params.time(), params.template get(), eps, eps); + + // reflection + FreeTrackParameters reflectedParams = params; + reflectedParams.reflectInPlace(); + CHECK_CLOSE_OR_SMALL(params.reflect().parameters(), + reflectedParams.parameters(), eps, eps); + CHECK_CLOSE_OR_SMALL(reflectedParams.reflect().parameters(), + params.parameters(), eps, eps); } } // namespace diff --git a/Tests/UnitTests/Core/EventData/TrackParameterHelpersTests.cpp b/Tests/UnitTests/Core/EventData/TrackParameterHelpersTests.cpp new file mode 100644 index 00000000000..0a6f3064594 --- /dev/null +++ b/Tests/UnitTests/Core/EventData/TrackParameterHelpersTests.cpp @@ -0,0 +1,43 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include + +#include "Acts/Definitions/TrackParametrization.hpp" +#include "Acts/EventData/TrackParameterHelpers.hpp" +#include "Acts/Tests/CommonHelpers/FloatComparisons.hpp" + +BOOST_AUTO_TEST_SUITE(TrackParameterHelpers) + +BOOST_AUTO_TEST_CASE(normalizeBoundParameters) { + CHECK_CLOSE_OR_SMALL(Acts::normalizeBoundParameters({1, 2, 3, 4, 5, 6}), + Acts::BoundVector(1, 2, -0.141593, 2.28319, 5, 6), 1e-3, + 1e-3); +} + +BOOST_AUTO_TEST_CASE(addBoundParameters) { + CHECK_CLOSE_OR_SMALL( + Acts::addBoundParameters({1, 2, 3, 4, 5, 6}, {0, 0, 0, 0, 0, 0}), + Acts::normalizeBoundParameters({1, 2, 3, 4, 5, 6}), 1e-3, 1e-3); + CHECK_CLOSE_OR_SMALL( + Acts::addBoundParameters({1, 2, 3, 4, 5, 6}, {0, 0, 1, 1, 0, 0}), + Acts::normalizeBoundParameters({1, 2, 4, 5, 5, 6}), 1e-3, 1e-3); +} + +BOOST_AUTO_TEST_CASE(subtractBoundParameters) { + CHECK_CLOSE_OR_SMALL( + Acts::subtractBoundParameters({1, 2, 3, 4, 5, 6}, {1, 2, 3, 4, 5, 6}), + Acts::BoundVector(0, 0, 0, 0, 0, 0), 1e-3, 1e-3); + CHECK_CLOSE_OR_SMALL( + Acts::addBoundParameters( + Acts::subtractBoundParameters({1, 2, 3, 4, 5, 6}, {0, 0, 1, 1, 0, 0}), + {0, 0, 1, 1, 0, 0}), + Acts::normalizeBoundParameters({1, 2, 3, 4, 5, 6}), 1e-3, 1e-3); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/Tests/UnitTests/Core/Navigation/CMakeLists.txt b/Tests/UnitTests/Core/Navigation/CMakeLists.txt index edca953321d..a18c2d34c9c 100644 --- a/Tests/UnitTests/Core/Navigation/CMakeLists.txt +++ b/Tests/UnitTests/Core/Navigation/CMakeLists.txt @@ -5,3 +5,4 @@ add_unittest(NavigationStream NavigationStreamTests.cpp) add_unittest(NavigationStateUpdaters NavigationStateUpdatersTests.cpp) add_unittest(DetectorNavigator DetectorNavigatorTests.cpp) add_unittest(MultiWireNavigation MultiWireNavigationTests.cpp) +add_unittest(NavigationPolicy NavigationPolicyTests.cpp) diff --git a/Tests/UnitTests/Core/Navigation/NavigationPolicyTests.cpp b/Tests/UnitTests/Core/Navigation/NavigationPolicyTests.cpp new file mode 100644 index 00000000000..181e1ad2a1f --- /dev/null +++ b/Tests/UnitTests/Core/Navigation/NavigationPolicyTests.cpp @@ -0,0 +1,240 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include + +#include "Acts/Definitions/Units.hpp" +#include "Acts/Geometry/CylinderVolumeBounds.hpp" +#include "Acts/Geometry/NavigationPolicyFactory.hpp" +#include "Acts/Geometry/TrackingVolume.hpp" +#include "Acts/Navigation/INavigationPolicy.hpp" +#include "Acts/Navigation/MultiNavigationPolicy.hpp" +#include "Acts/Navigation/NavigationDelegate.hpp" +#include "Acts/Navigation/NavigationStream.hpp" +#include "Acts/Navigation/TryAllNavigationPolicy.hpp" + +using namespace Acts; +using namespace Acts::UnitLiterals; + +BOOST_AUTO_TEST_SUITE(NavigationPolicyTests) + +GeometryContext gctx; +auto logger = getDefaultLogger("NavigationPolicyTests", Logging::VERBOSE); + +struct APolicy : public INavigationPolicy { + APolicy(const GeometryContext& /*gctx*/, const TrackingVolume& /*volume*/, + const Logger& /*logger*/) {} + + void initializeCandidates(const NavigationArguments& /*unused*/, + AppendOnlyNavigationStream& /*unused*/, + const Logger& /*unused*/) const { + const_cast(this)->executed = true; + } + + void connect(NavigationDelegate& delegate) const override { + connectDefault(delegate); + } + + bool executed = false; +}; + +struct BPolicy : public INavigationPolicy { + struct Config { + int value; + }; + + BPolicy(const GeometryContext& /*gctx*/, const TrackingVolume& /*volume*/, + const Logger& /*logger*/, Config config) + : m_config(config) {} + + void connect(NavigationDelegate& delegate) const override { + connectDefault(delegate); + } + + void initializeCandidates(const NavigationArguments& /*unused*/, + AppendOnlyNavigationStream& /*unused*/, + const Logger& /*unused*/) const { + const_cast(this)->executed = true; + const_cast(this)->value = m_config.value; + } + + bool executed = false; + int value = 0; + + Config m_config; +}; + +BOOST_AUTO_TEST_CASE(DirectTest) { + TrackingVolume volume{ + Transform3::Identity(), + std::make_shared(250_mm, 400_mm, 310_mm), + "PixelLayer3"}; + + MultiNavigationPolicy policy{APolicy{gctx, volume, *logger}, + BPolicy{gctx, volume, *logger, {.value = 4242}}}; + + NavigationDelegate delegate; + policy.connect(delegate); + + NavigationStream main; + AppendOnlyNavigationStream stream{main}; + delegate(NavigationArguments{.position = Vector3::Zero(), + .direction = Vector3::Zero()}, + stream, *logger); + + BOOST_CHECK(std::get(policy.policies()).executed); + BOOST_CHECK(std::get(policy.policies()).executed); + BOOST_CHECK_EQUAL(std::get(policy.policies()).value, 4242); +} + +BOOST_AUTO_TEST_CASE(FactoryTest) { + TrackingVolume volume{ + Transform3::Identity(), + std::make_shared(250_mm, 400_mm, 310_mm), + "PixelLayer3"}; + + BPolicy::Config config{.value = 42}; + + std::function( + const GeometryContext&, const TrackingVolume&, const Logger&)> + factory = NavigationPolicyFactory::make() + .add() // no arguments + .add(config); // config struct as argument + + auto policyBase = factory(gctx, volume, *logger); + auto policyBase2 = factory(gctx, volume, *logger); + + auto& policy = + dynamic_cast&>(*policyBase); + + NavigationDelegate delegate; + policy.connect(delegate); + + NavigationStream main; + AppendOnlyNavigationStream stream{main}; + delegate(NavigationArguments{.position = Vector3::Zero(), + .direction = Vector3::Zero()}, + stream, *logger); + + BOOST_CHECK(std::get(policy.policies()).executed); + BOOST_CHECK(std::get(policy.policies()).executed); + BOOST_CHECK_EQUAL(std::get(policy.policies()).value, 42); + + auto& policy2 = + dynamic_cast&>(*policyBase2); + + NavigationDelegate delegate2; + policyBase2->connect(delegate2); + + delegate2(NavigationArguments{.position = Vector3::Zero(), + .direction = Vector3::Zero()}, + stream, *logger); + + BOOST_CHECK(std::get(policy2.policies()).executed); + BOOST_CHECK(std::get(policy2.policies()).executed); + BOOST_CHECK_EQUAL(std::get(policy2.policies()).value, 42); +} + +BOOST_AUTO_TEST_CASE(AsUniquePtrTest) { + TrackingVolume volume{ + Transform3::Identity(), + std::make_shared(250_mm, 400_mm, 310_mm), + "PixelLayer3"}; + + std::unique_ptr factory = + NavigationPolicyFactory::make().add().asUniquePtr(); + + auto policyBase = factory->build(gctx, volume, *logger); + auto& policy = dynamic_cast&>(*policyBase); + + NavigationDelegate delegate; + policyBase->connect(delegate); + + NavigationStream main; + AppendOnlyNavigationStream stream{main}; + delegate(NavigationArguments{.position = Vector3::Zero(), + .direction = Vector3::Zero()}, + stream, *logger); + + BOOST_CHECK(std::get(policy.policies()).executed); +} + +struct CPolicy : public INavigationPolicy {}; + +template +struct CPolicySpecialized : public CPolicy { + struct Config { + T value; + }; + + CPolicySpecialized(const TrackingVolume& /*volume*/, Config config) + : m_config(config) {} + + void connect(NavigationDelegate& delegate) const override { + connectDefault>(delegate); + } + + void initializeCandidates(const NavigationArguments& /*unused*/, + AppendOnlyNavigationStream& /*stream*/, + const Logger& /*logger*/) const { + auto* self = const_cast*>(this); + self->executed = true; + self->value = m_config.value; + } + + bool executed = false; + int value = 0; + + Config m_config; +}; + +struct IsolatedConfig { + int value; +}; + +auto makeCPolicy(const GeometryContext& /*gctx*/, const TrackingVolume& volume, + const Logger& /*logger*/, IsolatedConfig config) { + // I can do arbitrary stuff here + CPolicySpecialized::Config config2{.value = config.value}; + return CPolicySpecialized(volume, config2); +} + +BOOST_AUTO_TEST_CASE(IsolatedFactory) { + TrackingVolume volume{ + Transform3::Identity(), + std::make_shared(250_mm, 400_mm, 310_mm), + "PixelLayer3"}; + + IsolatedConfig config{.value = 44}; + auto factory = + NavigationPolicyFactory::make().add().add(makeCPolicy, config); + + auto factory2 = + NavigationPolicyFactory::make().add(makeCPolicy, config).add(); + + auto policyBase = factory(gctx, volume, *logger); + auto& policy = + dynamic_cast>&>( + *policyBase); + + NavigationDelegate delegate; + policyBase->connect(delegate); + + NavigationStream main; + AppendOnlyNavigationStream stream{main}; + delegate(NavigationArguments{.position = Vector3::Zero(), + .direction = Vector3::Zero()}, + stream, *logger); + + BOOST_CHECK(std::get(policy.policies()).executed); + BOOST_CHECK(std::get>(policy.policies()).executed); + BOOST_CHECK_EQUAL(std::get>(policy.policies()).value, + 44); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/Tests/UnitTests/Core/Navigation/NavigationStreamTests.cpp b/Tests/UnitTests/Core/Navigation/NavigationStreamTests.cpp index 097dde2ed64..9ca578b0aba 100644 --- a/Tests/UnitTests/Core/Navigation/NavigationStreamTests.cpp +++ b/Tests/UnitTests/Core/Navigation/NavigationStreamTests.cpp @@ -94,7 +94,7 @@ BOOST_AUTO_TEST_CASE(NavigationStream_InitializePlanes) { NavigationStream nStreamTemplate; for (const auto& surface : surfaces) { - nStreamTemplate.addSurfaceCandidate(surface.get(), + nStreamTemplate.addSurfaceCandidate(*surface, Acts::BoundaryTolerance::None()); } BOOST_CHECK_EQUAL(nStreamTemplate.remainingCandidates(), 4u); @@ -140,7 +140,7 @@ BOOST_AUTO_TEST_CASE(NavigationStream_InitializePlanes) { // (5) Test de-duplication nStream = nStreamTemplate; - nStreamTemplate.addSurfaceCandidate(surfaces[0].get(), + nStreamTemplate.addSurfaceCandidate(*surfaces.at(0), Acts::BoundaryTolerance::None()); // One surface is duplicated in the stream BOOST_CHECK_EQUAL(nStreamTemplate.remainingCandidates(), 5u); @@ -159,7 +159,7 @@ BOOST_AUTO_TEST_CASE(NavigationStream_UpdatePlanes) { // reachable and intersections inside bounds NavigationStream nStreamTemplate; for (const auto& surface : surfaces) { - nStreamTemplate.addSurfaceCandidate(surface.get(), + nStreamTemplate.addSurfaceCandidate(*surface, Acts::BoundaryTolerance::None()); } BOOST_CHECK_EQUAL(nStreamTemplate.remainingCandidates(), 4u); @@ -231,7 +231,8 @@ BOOST_AUTO_TEST_CASE(NavigationStream_InitializeCylinders) { // Let us fill the surfaces into the navigation stream NavigationStream nStreamTemplate; for (const auto& surface : surfaces) { - nStreamTemplate.addSurfaceCandidates({surface.get()}, + const Surface* pointer = surface.get(); + nStreamTemplate.addSurfaceCandidates({&pointer, 1}, Acts::BoundaryTolerance::None()); } BOOST_CHECK_EQUAL(nStreamTemplate.remainingCandidates(), 4u); diff --git a/Tests/UnitTests/Core/Seeding/PathSeederTest.cpp b/Tests/UnitTests/Core/Seeding/PathSeederTest.cpp index 70a8f9ebaa0..e8338925747 100644 --- a/Tests/UnitTests/Core/Seeding/PathSeederTest.cpp +++ b/Tests/UnitTests/Core/Seeding/PathSeederTest.cpp @@ -38,6 +38,8 @@ using namespace Acts::UnitLiterals; using Axis = Acts::Axis; using Grid = Acts::Grid, Axis, Axis>; +using TrackParameters = CurvilinearTrackParameters; + GeometryContext gctx; // Parameters for the geometry @@ -46,6 +48,12 @@ const ActsScalar halfZ = 10.; const ActsScalar deltaX = 10.; const ActsScalar deltaYZ = 1.; +const Vector4 trueVertex(-5., 0., 0., 0); +const std::vector truePhis = {-0.15, -0.1, -0.05, 0, + 0.05, 0.1, 0.15}; +const ActsScalar trueTheta = M_PI_2; +const ActsScalar trueQOverP = 1. / 1._GeV; + // Intersection finding to get the // region of interest for seeding class NoFieldIntersectionFinder { @@ -57,11 +65,13 @@ class NoFieldIntersectionFinder { // Find the intersections along the path // and return them in the order of the path // length - std::vector> operator()( - const GeometryContext& geoCtx, const Vector3& position, - const Vector3& direction, [[maybe_unused]] const ActsScalar& Pmag = 0, - [[maybe_unused]] const ActsScalar& Charge = 0) const { - std::vector> sIntersections; + std::vector> operator()( + const GeometryContext& geoCtx, + const TrackParameters& trackParameters) const { + Vector3 position = trackParameters.position(); + Vector3 direction = trackParameters.direction(); + + std::vector> sIntersections; // Intersect the surfaces for (auto& surface : m_surfaces) { // Get the intersection @@ -76,7 +86,11 @@ class NoFieldIntersectionFinder { if (closestForward.status() == IntersectionStatus::reachable && closestForward.pathLength() > 0.0) { sIntersections.push_back( - {closestForward.object()->geometryId(), closestForward.position()}); + {closestForward.object()->geometryId(), + surface + ->globalToLocal(geoCtx, closestForward.position(), + Vector3{0, 1, 0}) + .value()}); continue; } } @@ -84,92 +98,85 @@ class NoFieldIntersectionFinder { } }; -// Grid to store the source links for -// the seeding fast lookup -class SourceLinkGrid { +// A simple path width provider to set +// the grid lookup boundaries around the +// intersection point +class PathWidthProvider { + public: + std::pair width; + + std::pair operator()( + const GeometryContext& /*gctx*/, + const GeometryIdentifier& /*geoId*/) const { + return width; + } +}; + +// Estimator of the particle's energy, +// vertex, momentum direction at the IP +// and the direction at the first hit +class TrackEstimator { public: - using GridType = Grid; + Vector3 m_ip; + SourceLinkSurfaceAccessor m_surfaceAccessor; + + std::pair operator()( + const GeometryContext& geoCtx, const SourceLink& pivot) const { + auto testSourceLink = pivot.get(); + Vector3 pivot3 = m_surfaceAccessor(pivot)->localToGlobal( + geoCtx, testSourceLink.parameters, Vector3{0, 1, 0}); + + Vector3 direction = (pivot3 - m_ip).normalized(); - /// Lookup table collection - std::unordered_map m_lookupTables; + Vector4 ip = {m_ip.x(), m_ip.y(), m_ip.z(), 0}; + ActsScalar qOverP = 1_e / 1._GeV; + ActsScalar phi = Acts::VectorHelpers::phi(direction); + ActsScalar theta = Acts::VectorHelpers::theta(direction); + ParticleHypothesis particle = ParticleHypothesis::electron(); + + TrackParameters ipParams(ip, phi, theta, qOverP, std::nullopt, particle); + TrackParameters firstLayerParams(ip, phi, theta, qOverP, std::nullopt, + particle); + + return {ipParams, firstLayerParams}; + } +}; - /// Surface accessor +// Construct grid with the source links +struct ConstructSourceLinkGrid { SourceLinkSurfaceAccessor m_surfaceAccessor; - void initialize(const GeometryContext& geoCtx, - std::vector sourceLinks) { + std::unordered_map construct( + std::vector sourceLinks) { // Lookup table for each layer - std::unordered_map lookupTable; + std::unordered_map lookupTable; // Construct a binned grid for each layer for (int i : {14, 15, 16, 17}) { - Axis xAxis(-halfY, halfY, 50); - Axis yAxis(-halfZ, halfZ, 50); + Axis xAxis(-halfY, halfY, 100); + Axis yAxis(-halfZ, halfZ, 100); + + Grid grid(std::make_tuple(xAxis, yAxis)); + + GeometryIdentifier geoId; + + geoId.setSensitive(i); - GridType grid(std::make_tuple(xAxis, yAxis)); - lookupTable.insert({i, grid}); + lookupTable.insert({geoId, grid}); } // Fill the grid with source links for (auto& sl : sourceLinks) { - auto ssl = sl.get(); - auto id = ssl.m_geometryId; + auto tsl = sl.get(); + auto id = tsl.m_geometryId; - // Grid works with global positions - Vector3 globalPos = m_surfaceAccessor(sl)->localToGlobal( - geoCtx, ssl.parameters, Vector3{0, 1, 0}); - - auto bin = - lookupTable.at(id.sensitive()) - .localBinsFromPosition(Vector2(globalPos.y(), globalPos.z())); - lookupTable.at(id.sensitive()).atLocalBins(bin).push_back(sl); + auto bin = lookupTable.at(id).localBinsFromPosition(tsl.parameters); + lookupTable.at(id).atLocalBins(bin).push_back(sl); } - m_lookupTables = lookupTable; - }; - - // Get the source link grid for a given geometry id - GridType operator()(const GeometryIdentifier& geoId) const { - return m_lookupTables.at(geoId.sensitive()); - } -}; - -// A simple path width provider to set -// the grid lookup boundaries around the -// intersection point -std::pair getPathWidth( - const GeometryContext& /*gctx*/, const GeometryIdentifier& /*geoId*/) { - return {0.1, 0.1}; -} - -// Calibrator to transform the source links -// to global coordinates -class SourceLinkCalibrator { - public: - SourceLinkSurfaceAccessor m_surfaceAccessor; - - Vector3 operator()(const GeometryContext& geoCtx, - const SourceLink& sourceLink) const { - auto ssl = sourceLink.get(); - auto res = m_surfaceAccessor(sourceLink) - ->localToGlobal(geoCtx, ssl.parameters, Vector3{0, 1, 0}); - return res; + return lookupTable; } }; -// Estimator of the particle's energy, -// vertex, momentum direction at the IP -// and the direction at the first hit -class TrackEstimator { - public: - Vector3 ip; - - std::tuple operator()( - const GeometryContext& /*geoCtx*/, const Vector3& pivot) const { - Vector3 direction = (pivot - ip).normalized(); - return {1_e, 1._GeV, ip, direction, direction}; - }; -}; - // Construct a simple telescope detector std::shared_ptr constructTelescopeDetector() { RotationMatrix3 rotation; @@ -257,7 +264,7 @@ std::shared_ptr constructTelescopeDetector() { // Connect the volumes auto portalContainer = Experimental::detail::CuboidalDetectorHelper::connect( - gctx, volumes, BinningValue::binX, {}, Logging::VERBOSE); + gctx, volumes, BinningValue::binX, {}, Logging::INFO); // Make sure that the geometry ids are // independent of the potential Id generation @@ -302,23 +309,19 @@ std::vector createSourceLinks( } } - Vector3 vertex(-5., 0., 0.); - std::vector phis = {-0.15, -0.1, -0.05, 0, 0.05, 0.1, 0.15}; - std::vector sourceLinks; - for (ActsScalar phi : phis) { - Vector3 direction(cos(phi), sin(phi), 0.); + for (ActsScalar phi : truePhis) { + TrackParameters trackParameters(trueVertex, phi, trueTheta, trueQOverP, + std::nullopt, + ParticleHypothesis::electron()); - auto intersections = intersectionFinder(geoCtx, vertex, direction); + auto intersections = intersectionFinder(geoCtx, trackParameters); SquareMatrix2 cov = SquareMatrix2::Identity(); for (auto& [id, refPoint] : intersections) { - auto surf = *detector.sensitiveHierarchyMap().find(id); - Vector2 val = surf->globalToLocal(geoCtx, refPoint, direction).value(); - - detail::Test::TestSourceLink sourceLink(eBoundLoc0, eBoundLoc1, val, cov, - id, id.value()); + detail::Test::TestSourceLink sourceLink(eBoundLoc0, eBoundLoc1, refPoint, + cov, id, id.value()); SourceLink sl{sourceLink}; sourceLinks.push_back(sl); @@ -339,30 +342,27 @@ BOOST_AUTO_TEST_CASE(PathSeederZeroField) { auto sourceLinks = createSourceLinks(gctx, *detector); // Prepare the PathSeeder - auto pathSeederCfg = Acts::Experimental::PathSeeder::Config(); + auto pathSeederCfg = Acts::PathSeeder::Config(); // Grid to bin the source links SurfaceAccessor surfaceAccessor{*detector}; - SourceLinkGrid sourceLinkGrid; - sourceLinkGrid.m_surfaceAccessor.connect<&SurfaceAccessor::operator()>( - &surfaceAccessor); - pathSeederCfg.sourceLinkGridLookup.connect<&SourceLinkGrid::operator()>( - &sourceLinkGrid); + auto sourceLinkGridConstructor = ConstructSourceLinkGrid(); + sourceLinkGridConstructor.m_surfaceAccessor + .connect<&SurfaceAccessor::operator()>(&surfaceAccessor); + + // Create the grid + std::unordered_map sourceLinkGrid = + sourceLinkGridConstructor.construct(sourceLinks); // Estimator of the IP and first hit // parameters of the track TrackEstimator trackEstimator; - trackEstimator.ip = Vector3(-5., 0., 0.); + trackEstimator.m_ip = Vector3(-5., 0., 0.); + trackEstimator.m_surfaceAccessor.connect<&SurfaceAccessor::operator()>( + &surfaceAccessor); pathSeederCfg.trackEstimator.connect<&TrackEstimator::operator()>( &trackEstimator); - // Transforms the source links to global coordinates - SourceLinkCalibrator sourceLinkCalibrator; - sourceLinkCalibrator.m_surfaceAccessor.connect<&SurfaceAccessor::operator()>( - &surfaceAccessor); - pathSeederCfg.sourceLinkCalibrator.connect<&SourceLinkCalibrator::operator()>( - &sourceLinkCalibrator); - // Intersection finder NoFieldIntersectionFinder intersectionFinder; for (auto volume : detector->volumes()) { @@ -374,29 +374,35 @@ BOOST_AUTO_TEST_CASE(PathSeederZeroField) { .connect<&NoFieldIntersectionFinder::operator()>(&intersectionFinder); // Path width provider - pathSeederCfg.pathWidthProvider.connect<&getPathWidth>(); + PathWidthProvider pathWidthProvider; - // First tracking layer - Extent firstLayerExtent; - firstLayerExtent.set(BinningValue::binX, -0.1, 0.1); - firstLayerExtent.set(BinningValue::binY, -halfY - deltaYZ, halfY + deltaYZ); - firstLayerExtent.set(BinningValue::binZ, -halfZ - deltaYZ, halfZ + deltaYZ); + pathSeederCfg.pathWidthProvider.connect<&PathWidthProvider::operator()>( + &pathWidthProvider); - pathSeederCfg.firstLayerExtent = firstLayerExtent; + GeometryIdentifier geoId; + geoId.setSensitive(14); + pathSeederCfg.refLayerIds.push_back(geoId); // Create the PathSeeder - Acts::Experimental::PathSeeder pathSeeder(pathSeederCfg); + Acts::PathSeeder pathSeeder(pathSeederCfg); // Get the seeds - sourceLinkGrid.initialize(gctx, sourceLinks); - auto seeds = pathSeeder.getSeeds(gctx, sourceLinks); + pathWidthProvider.width = {1e-3, 1e-3}; + + std::vector seeds; + + // SeedTreeContainer seeds; + pathSeeder.findSeeds(gctx, sourceLinkGrid, seeds); // Check the seeds BOOST_CHECK_EQUAL(seeds.size(), 7); - for (auto& seed : seeds) { - BOOST_CHECK_EQUAL(seed.sourceLinks.size(), 4); - BOOST_CHECK_EQUAL(seed.ipVertex, Vector3(-5., 0., 0.)); - BOOST_CHECK_EQUAL(seed.ipP, 1._GeV); + + for (std::size_t i = 0; i < seeds.size(); i++) { + auto seed = seeds.at(i); + BOOST_CHECK_EQUAL(seed.second.size(), 4); + BOOST_CHECK_EQUAL(seed.first.phi(), truePhis.at(i)); + BOOST_CHECK_EQUAL(seed.first.theta(), trueTheta); + BOOST_CHECK_EQUAL(seed.first.qOverP(), trueQOverP); } } diff --git a/Tests/UnitTests/Core/TrackFitting/FitterTestsCommon.hpp b/Tests/UnitTests/Core/TrackFitting/FitterTestsCommon.hpp index 4eb411751bb..6692974ef63 100644 --- a/Tests/UnitTests/Core/TrackFitting/FitterTestsCommon.hpp +++ b/Tests/UnitTests/Core/TrackFitting/FitterTestsCommon.hpp @@ -90,7 +90,7 @@ auto makeStraightPropagator(std::shared_ptr geo) { cfg.resolveMaterial = true; cfg.resolveSensitive = true; Acts::Navigator navigator( - cfg, Acts::getDefaultLogger("Navigator", Acts::Logging::VERBOSE)); + cfg, Acts::getDefaultLogger("Navigator", Acts::Logging::INFO)); Acts::StraightLineStepper stepper; return Acts::Propagator( stepper, std::move(navigator)); @@ -105,7 +105,7 @@ auto makeConstantFieldPropagator( cfg.resolveMaterial = true; cfg.resolveSensitive = true; Acts::Navigator navigator( - cfg, Acts::getDefaultLogger("Navigator", Acts::Logging::VERBOSE)); + cfg, Acts::getDefaultLogger("Navigator", Acts::Logging::INFO)); auto field = std::make_shared(Acts::Vector3(0.0, 0.0, bz)); stepper_t stepper(std::move(field)); diff --git a/Tests/UnitTests/Core/Utilities/AngleHelpersTests.cpp b/Tests/UnitTests/Core/Utilities/AngleHelpersTests.cpp new file mode 100644 index 00000000000..5898986e6d5 --- /dev/null +++ b/Tests/UnitTests/Core/Utilities/AngleHelpersTests.cpp @@ -0,0 +1,29 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include + +#include "Acts/Tests/CommonHelpers/FloatComparisons.hpp" +#include "Acts/Utilities/AngleHelpers.hpp" + +#include + +using Acts::AngleHelpers::etaFromTheta; +using Acts::AngleHelpers::thetaFromEta; + +BOOST_AUTO_TEST_SUITE(AngleHelpers) + +BOOST_AUTO_TEST_CASE(EtaThetaConversion) { + CHECK_CLOSE_ABS(0.0, etaFromTheta(std::numbers::pi / 2), 1e-6); + + CHECK_CLOSE_ABS(1.0, etaFromTheta(thetaFromEta(1.0)), 1e-6); + + CHECK_CLOSE_ABS(1.0, thetaFromEta(etaFromTheta(1.0)), 1e-6); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/Tests/UnitTests/Core/Utilities/CMakeLists.txt b/Tests/UnitTests/Core/Utilities/CMakeLists.txt index 2c00476c116..cb5249b6be9 100644 --- a/Tests/UnitTests/Core/Utilities/CMakeLists.txt +++ b/Tests/UnitTests/Core/Utilities/CMakeLists.txt @@ -56,6 +56,8 @@ add_unittest(ParticleData ParticleDataTests.cpp) add_unittest(Zip ZipTests.cpp) add_unittest(TransformRange TransformRangeTests.cpp) add_unittest(MathHelpers MathHelpersTests.cpp) +add_unittest(AngleHelpers AngleHelpersTests.cpp) +add_unittest(VectorHelpers VectorHelpersTests.cpp) add_unittest(TrackHelpers TrackHelpersTests.cpp) add_unittest(GraphViz GraphVizTests.cpp) diff --git a/Tests/UnitTests/Core/Utilities/KDTreeTests.cpp b/Tests/UnitTests/Core/Utilities/KDTreeTests.cpp index b1a70c399c7..15146e2eb60 100644 --- a/Tests/UnitTests/Core/Utilities/KDTreeTests.cpp +++ b/Tests/UnitTests/Core/Utilities/KDTreeTests.cpp @@ -482,12 +482,10 @@ BOOST_FIXTURE_TEST_CASE(range_search_combinatorial, TreeFixture3DDoubleInt2) { std::vector valid; - for (const std::pair, int>& i : - test_vector) { - const std::array& c = i.first; + for (const auto& [c, value] : test_vector) { if (xmin <= c[0] && c[0] < xmax && ymin <= c[1] && c[1] < ymax && zmin <= c[2] && c[2] < zmax) { - valid.push_back(i.second); + valid.push_back(value); } } diff --git a/Tests/UnitTests/Core/Utilities/VectorHelpersTests.cpp b/Tests/UnitTests/Core/Utilities/VectorHelpersTests.cpp new file mode 100644 index 00000000000..17ffe9d93a5 --- /dev/null +++ b/Tests/UnitTests/Core/Utilities/VectorHelpersTests.cpp @@ -0,0 +1,30 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include + +#include "Acts/Definitions/Algebra.hpp" +#include "Acts/Tests/CommonHelpers/FloatComparisons.hpp" +#include "Acts/Utilities/VectorHelpers.hpp" + +#include + +using Acts::VectorHelpers::eta; +using Acts::VectorHelpers::theta; + +BOOST_AUTO_TEST_SUITE(AngleHelpers) + +BOOST_AUTO_TEST_CASE(EtaFromVector) { + CHECK_CLOSE_ABS(0.0, eta(Acts::Vector3{1, 0, 0}), 1e-6); +} + +BOOST_AUTO_TEST_CASE(ThetaFromVector) { + CHECK_CLOSE_ABS(std::numbers::pi / 2, theta(Acts::Vector3{1, 0, 0}), 1e-6); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/Tests/UnitTests/Examples/EventData/MeasurementTests.cpp b/Tests/UnitTests/Examples/EventData/MeasurementTests.cpp index d59ff4a135e..2428aa2429f 100644 --- a/Tests/UnitTests/Examples/EventData/MeasurementTests.cpp +++ b/Tests/UnitTests/Examples/EventData/MeasurementTests.cpp @@ -85,7 +85,8 @@ BOOST_DATA_TEST_CASE(VariableBoundOneEmplace, bd::make(boundIndices), index) { BOOST_AUTO_TEST_CASE(VariableBoundAll) { MeasurementContainer container; - auto [params, cov] = generateBoundParametersCovariance(rng); + auto [params, cov] = + generateParametersCovariance(rng); FixedBoundMeasurementProxy meas = container.makeMeasurement(geoId); @@ -106,7 +107,8 @@ BOOST_AUTO_TEST_CASE(VariableBoundAll) { BOOST_AUTO_TEST_CASE(VariableBoundAllEmplace) { MeasurementContainer container; - auto [params, cov] = generateBoundParametersCovariance(rng); + auto [params, cov] = + generateParametersCovariance(rng); FixedBoundMeasurementProxy meas = container.emplaceMeasurement( @@ -144,7 +146,8 @@ BOOST_AUTO_TEST_CASE(VariableBoundReassign) { BOOST_CHECK(!meas.contains(eBoundQOverP)); // reassign w/ all parameters - auto [paramsN, covN] = generateBoundParametersCovariance(rng); + auto [paramsN, covN] = + generateParametersCovariance(rng); meas = container.makeMeasurement(eBoundSize, geoId); meas.setSubspaceIndices(std::array{eBoundLoc0, eBoundLoc1, eBoundTime, diff --git a/Tests/UnitTests/Examples/Io/Json/JsonDigitizationConfigTests.cpp b/Tests/UnitTests/Examples/Io/Json/JsonDigitizationConfigTests.cpp index ab30e2a98f0..f7c1db0f496 100644 --- a/Tests/UnitTests/Examples/Io/Json/JsonDigitizationConfigTests.cpp +++ b/Tests/UnitTests/Examples/Io/Json/JsonDigitizationConfigTests.cpp @@ -57,7 +57,7 @@ struct Fixture { // generate random track parameters auto [par, cov] = - Acts::detail::Test::generateBoundParametersCovariance(rng); + Acts::detail::Test::generateBoundParametersCovariance(rng, {}); boundParams = par; freeParams = diff --git a/Tests/UnitTests/Fatras/Digitization/UncorrelatedHitSmearerTests.cpp b/Tests/UnitTests/Fatras/Digitization/UncorrelatedHitSmearerTests.cpp index e4fde7f3b2d..2a4ad0b2a6e 100644 --- a/Tests/UnitTests/Fatras/Digitization/UncorrelatedHitSmearerTests.cpp +++ b/Tests/UnitTests/Fatras/Digitization/UncorrelatedHitSmearerTests.cpp @@ -96,7 +96,7 @@ struct Fixture { // generate random track parameters auto [par, cov] = - Acts::detail::Test::generateBoundParametersCovariance(rng); + Acts::detail::Test::generateBoundParametersCovariance(rng, {}); boundParams = par; freeParams = diff --git a/Tests/UnitTests/Fatras/Kernel/SimulationActorTests.cpp b/Tests/UnitTests/Fatras/Kernel/SimulationActorTests.cpp index e52d586c30b..3306c5702d6 100644 --- a/Tests/UnitTests/Fatras/Kernel/SimulationActorTests.cpp +++ b/Tests/UnitTests/Fatras/Kernel/SimulationActorTests.cpp @@ -244,7 +244,13 @@ BOOST_AUTO_TEST_CASE(HitsOnEmptySurface) { BOOST_CHECK_EQUAL(f.actor.initialParticle.absoluteMomentum(), f.p); BOOST_CHECK_EQUAL(f.actor.initialParticle.energy(), f.e); + // call.actor: pre propagation + f.state.stage = Acts::PropagatorStage::prePropagation; + f.actor.act(f.state, f.stepper, f.navigator, f.result, + Acts::getDummyLogger()); + // call.actor: surface selection -> one hit, no material -> no secondary + f.state.stage = Acts::PropagatorStage::postStep; f.actor.act(f.state, f.stepper, f.navigator, f.result, Acts::getDummyLogger()); BOOST_CHECK(f.result.isAlive); @@ -271,6 +277,7 @@ BOOST_AUTO_TEST_CASE(HitsOnEmptySurface) { BOOST_CHECK_EQUAL(f.state.stepping.p, f.result.particle.absoluteMomentum()); // call.actor again: one more hit, still no secondary + f.state.stage = Acts::PropagatorStage::postStep; f.actor.act(f.state, f.stepper, f.navigator, f.result, Acts::getDummyLogger()); BOOST_CHECK(f.result.isAlive); @@ -317,7 +324,13 @@ BOOST_AUTO_TEST_CASE(HitsOnMaterialSurface) { BOOST_CHECK_EQUAL(f.actor.initialParticle.absoluteMomentum(), f.p); BOOST_CHECK_EQUAL(f.actor.initialParticle.energy(), f.e); + // call.actor: pre propagation + f.state.stage = Acts::PropagatorStage::prePropagation; + f.actor.act(f.state, f.stepper, f.navigator, f.result, + Acts::getDummyLogger()); + // call.actor: surface selection -> one hit, material -> one secondary + f.state.stage = Acts::PropagatorStage::postStep; f.actor.act(f.state, f.stepper, f.navigator, f.result, Acts::getDummyLogger()); BOOST_CHECK(f.result.isAlive); @@ -346,6 +359,7 @@ BOOST_AUTO_TEST_CASE(HitsOnMaterialSurface) { tol); // call.actor again: one more hit, one more secondary + f.state.stage = Acts::PropagatorStage::postStep; f.actor.act(f.state, f.stepper, f.navigator, f.result, Acts::getDummyLogger()); BOOST_CHECK(f.result.isAlive); @@ -392,7 +406,13 @@ BOOST_AUTO_TEST_CASE(NoHitsEmptySurface) { BOOST_CHECK_EQUAL(f.actor.initialParticle.absoluteMomentum(), f.p); BOOST_CHECK_EQUAL(f.actor.initialParticle.energy(), f.e); + // call.actor: pre propagation + f.state.stage = Acts::PropagatorStage::prePropagation; + f.actor.act(f.state, f.stepper, f.navigator, f.result, + Acts::getDummyLogger()); + // call.actor: no surface sel. -> no hit, no material -> no secondary + f.state.stage = Acts::PropagatorStage::postStep; f.actor.act(f.state, f.stepper, f.navigator, f.result, Acts::getDummyLogger()); BOOST_CHECK(f.result.isAlive); @@ -419,6 +439,7 @@ BOOST_AUTO_TEST_CASE(NoHitsEmptySurface) { BOOST_CHECK_EQUAL(f.state.stepping.p, f.result.particle.absoluteMomentum()); // call.actor again: no hit, still no secondary + f.state.stage = Acts::PropagatorStage::postStep; f.actor.act(f.state, f.stepper, f.navigator, f.result, Acts::getDummyLogger()); BOOST_CHECK(f.result.isAlive); @@ -455,7 +476,13 @@ BOOST_AUTO_TEST_CASE(NoHitsEmptySurface) { BOOST_AUTO_TEST_CASE(NoHitsMaterialSurface) { Fixture f(125_MeV, makeMaterialSurface()); + // call.actor: pre propagation + f.state.stage = Acts::PropagatorStage::prePropagation; + f.actor.act(f.state, f.stepper, f.navigator, f.result, + Acts::getDummyLogger()); + // call.actor: no surface sel. -> no hit, material -> one secondary + f.state.stage = Acts::PropagatorStage::postStep; f.actor.act(f.state, f.stepper, f.navigator, f.result, Acts::getDummyLogger()); BOOST_CHECK(f.result.isAlive); @@ -483,6 +510,7 @@ BOOST_AUTO_TEST_CASE(NoHitsMaterialSurface) { tol); // call.actor again: still no hit, one more secondary + f.state.stage = Acts::PropagatorStage::postStep; f.actor.act(f.state, f.stepper, f.navigator, f.result, Acts::getDummyLogger()); BOOST_CHECK(f.result.isAlive); @@ -523,7 +551,13 @@ BOOST_AUTO_TEST_CASE(Decay) { // inverse Lorentz factor for proper time dilation: 1/gamma = m/E const auto gammaInv = f.m / f.e; + // call.actor: pre propagation + f.state.stage = Acts::PropagatorStage::prePropagation; + f.actor.act(f.state, f.stepper, f.navigator, f.result, + Acts::getDummyLogger()); + // first step w/ defaults leaves particle alive + f.state.stage = Acts::PropagatorStage::postStep; f.actor.act(f.state, f.stepper, f.navigator, f.result, Acts::getDummyLogger()); BOOST_CHECK(f.result.isAlive); @@ -536,6 +570,7 @@ BOOST_AUTO_TEST_CASE(Decay) { BOOST_CHECK_EQUAL(f.result.particle.properTime(), 0_ns); // second step w/ defaults increases proper time + f.state.stage = Acts::PropagatorStage::postStep; f.state.stepping.time += 1_ns; f.actor.act(f.state, f.stepper, f.navigator, f.result, Acts::getDummyLogger()); @@ -549,6 +584,7 @@ BOOST_AUTO_TEST_CASE(Decay) { CHECK_CLOSE_REL(f.result.particle.properTime(), gammaInv * 1_ns, tol); // third step w/ proper time limit decays the particle + f.state.stage = Acts::PropagatorStage::postStep; f.state.stepping.time += 1_ns; f.result.properTimeLimit = f.result.particle.properTime() + gammaInv * 0.5_ns; f.actor.act(f.state, f.stepper, f.navigator, f.result, diff --git a/Tests/UnitTests/Plugins/Detray/DetrayGeometryConverterTests.cpp b/Tests/UnitTests/Plugins/Detray/DetrayGeometryConverterTests.cpp index 97c1c7dff13..2ed99f4a68b 100644 --- a/Tests/UnitTests/Plugins/Detray/DetrayGeometryConverterTests.cpp +++ b/Tests/UnitTests/Plugins/Detray/DetrayGeometryConverterTests.cpp @@ -107,10 +107,11 @@ BOOST_AUTO_TEST_CASE(DetrayVolumeConversion) { auto [volumes, portals, rootVolumes] = beampipe->construct(tContext); auto volume = volumes.front(); - DetrayConversionUtils::GeometryIdCache geoIdCache; + std::vector dVolumes = {volume.get()}; + DetrayConversionUtils::Cache cCache(dVolumes); detray::io::volume_payload payload = DetrayGeometryConverter::convertVolume( - geoIdCache, tContext, *volume, {volume.get()}, *logger); + cCache, tContext, *volume, *logger); // Check the volume payload BOOST_CHECK(payload.name == "BeamPipe"); @@ -134,10 +135,10 @@ BOOST_AUTO_TEST_CASE(CylindricalDetector) { auto detector = buildCylindricalDetector(tContext); // Convert the detector - DetrayConversionUtils::GeometryIdCache geoIdCache; + DetrayConversionUtils::Cache cCache(detector->volumes()); detray::io::detector_payload payload = - DetrayGeometryConverter::convertDetector(geoIdCache, tContext, *detector, + DetrayGeometryConverter::convertDetector(cCache, tContext, *detector, *logger); // Test the payload - we have six volumes diff --git a/Tests/UnitTests/Plugins/Json/CMakeLists.txt b/Tests/UnitTests/Plugins/Json/CMakeLists.txt index 1f8573fdf50..141f86fb3fe 100644 --- a/Tests/UnitTests/Plugins/Json/CMakeLists.txt +++ b/Tests/UnitTests/Plugins/Json/CMakeLists.txt @@ -15,3 +15,4 @@ add_unittest(UtilitiesJsonConverter UtilitiesJsonConverterTests.cpp) add_unittest(SurfaceBoundsJsonConverter SurfaceBoundsJsonConverterTests.cpp) add_unittest(SurfaceJsonConverter SurfaceJsonConverterTests.cpp) add_unittest(VolumeBoundsJsonConverter VolumeBoundsJsonConverterTests.cpp) +add_unittest(TrackParametersJsonConverter TrackParametersJsonConverterTests.cpp) diff --git a/Tests/UnitTests/Plugins/Json/TrackParametersJsonConverterTests.cpp b/Tests/UnitTests/Plugins/Json/TrackParametersJsonConverterTests.cpp new file mode 100644 index 00000000000..566464a1889 --- /dev/null +++ b/Tests/UnitTests/Plugins/Json/TrackParametersJsonConverterTests.cpp @@ -0,0 +1,97 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include + +#include "Acts/Plugins/Json/TrackParametersJsonConverter.hpp" +#include "Acts/Surfaces/PlaneSurface.hpp" +#include "Acts/Surfaces/RectangleBounds.hpp" +#include "Acts/Tests/CommonHelpers/FloatComparisons.hpp" + +#include +#include + +#include + +BOOST_AUTO_TEST_SUITE(TrackParametersJsonIO) + +BOOST_AUTO_TEST_CASE(TrackParametersJsonIO) { + Acts::GeometryContext gctx; + + // Track parameters + Acts::Vector4 position(1., 2., 3., 4.); + Acts::ActsScalar phi = 0.1; + Acts::ActsScalar theta = 0.2; + Acts::ActsScalar qOverP = 3.0; + Acts::ParticleHypothesis particle = Acts::ParticleHypothesis::electron(); + Acts::FreeMatrix freeCov = Acts::FreeMatrix::Identity(); + Acts::BoundMatrix boundCov = Acts::BoundMatrix::Identity(); + + auto surface = Acts::Surface::makeShared( + Acts::Transform3::Identity(), + std::make_shared(10., 10.)); + surface->assignGeometryId(Acts::GeometryIdentifier(1u)); + + // Free track parameters conversion + Acts::FreeTrackParameters ftp(position, phi, theta, qOverP, freeCov, + particle); + + nlohmann::json ftpJson = ftp; + + Acts::FreeTrackParameters ftpRead = ftpJson; + + BOOST_CHECK_EQUAL(ftp.position(), ftpRead.position()); + BOOST_CHECK_EQUAL(ftp.direction(), ftpRead.direction()); + BOOST_CHECK_EQUAL(ftp.qOverP(), ftpRead.qOverP()); + BOOST_CHECK_EQUAL(ftp.covariance().value(), ftpRead.covariance().value()); + BOOST_CHECK_EQUAL(ftp.particleHypothesis(), ftpRead.particleHypothesis()); + + // Curvilinear track parameters conversion + Acts::CurvilinearTrackParameters ctp(position, phi, theta, qOverP, boundCov, + particle); + + nlohmann::json ctpJson = ctp; + + Acts::CurvilinearTrackParameters ctpRead = ctpJson; + + BOOST_CHECK_EQUAL(ctp.position(), ctpRead.position()); + BOOST_CHECK_EQUAL(ctp.direction(), ctpRead.direction()); + BOOST_CHECK_EQUAL(ctp.qOverP(), ctpRead.qOverP()); + BOOST_CHECK_EQUAL(ctp.covariance().value(), ctpRead.covariance().value()); + BOOST_CHECK_EQUAL(ctp.particleHypothesis(), ctpRead.particleHypothesis()); + + BOOST_CHECK(ctp.referenceSurface().transform(gctx).isApprox( + ctpRead.referenceSurface().transform(gctx))); + BOOST_CHECK_EQUAL(ctp.referenceSurface().geometryId(), + ctpRead.referenceSurface().geometryId()); + BOOST_CHECK_EQUAL(ctp.referenceSurface().bounds(), + ctpRead.referenceSurface().bounds()); + + // Bound track parameters conversion + Acts::BoundVector boundPosition{1., 2., 3., 4., 5., 6.}; + Acts::BoundTrackParameters btp(surface, boundPosition, boundCov, particle); + + nlohmann::json btpJson = btp; + + Acts::BoundTrackParameters btpRead = btpJson; + + BOOST_CHECK_EQUAL(btp.position(gctx), btpRead.position(gctx)); + BOOST_CHECK_EQUAL(btp.direction(), btpRead.direction()); + BOOST_CHECK_EQUAL(btp.qOverP(), btpRead.qOverP()); + BOOST_CHECK_EQUAL(btp.covariance().value(), btpRead.covariance().value()); + BOOST_CHECK_EQUAL(btp.particleHypothesis(), btpRead.particleHypothesis()); + + BOOST_CHECK(btp.referenceSurface().transform(gctx).isApprox( + btpRead.referenceSurface().transform(gctx))); + BOOST_CHECK_EQUAL(btp.referenceSurface().geometryId(), + btpRead.referenceSurface().geometryId()); + BOOST_CHECK_EQUAL(btp.referenceSurface().bounds(), + btpRead.referenceSurface().bounds()); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/cmake/ActsConfig.cmake.in b/cmake/ActsConfig.cmake.in index 7ed4b3884a5..97d510f1319 100644 --- a/cmake/ActsConfig.cmake.in +++ b/cmake/ActsConfig.cmake.in @@ -52,9 +52,7 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/Modules) # `find_dependency` is a wrapper around `find_package` that automatically # handles QUIET and REQUIRED parameters. include(CMakeFindDependencyMacro) -if(@ACTS_USE_SYSTEM_BOOST@) - find_dependency(Boost @Boost_VERSION_STRING@ CONFIG EXACT) -endif() +find_dependency(Boost @Boost_VERSION_STRING@ CONFIG EXACT) if(@ACTS_USE_SYSTEM_EIGEN3@) find_dependency(Eigen3 @Eigen3_VERSION@ CONFIG EXACT) endif() @@ -86,10 +84,6 @@ endif() # dependencies that we have built ourselves but cannot be # straightforwardly handed to cmake -if(NOT @ACTS_USE_SYSTEM_BOOST@) - add_library(Boost::boost INTERFACE IMPORTED GLOBAL) - target_include_directories(Boost::boost INTERFACE "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}") -endif() if(NOT @ACTS_USE_SYSTEM_EIGEN3@) add_library(Eigen3::Eigen INTERFACE IMPORTED GLOBAL) target_include_directories(Eigen3::Eigen INTERFACE "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}") diff --git a/thirdparty/README.md b/thirdparty/README.md index bd271826e1c..243479db0aa 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -17,9 +17,7 @@ CMake instructions to build [nlohmann::json](https://github.com/nlohmann/json). ## boost For convenience, it's possible to use the ACTS build system to build the minimum -required version of [boost](https://www.boost.org/) (currently 1.71.0). No source is -bundled here, and if requested via "-DACTS_USE_SYSTEM_BOOST=OFF", only the filesystem, -program_options, and test libraries will be built. +required version of [boost](https://www.boost.org/) (currently 1.71.0). Warning: during installation, the built boost libraries will be installed alongside the ACTS libraries, with a version suffix. This location may be known to the system linker.