-
Notifications
You must be signed in to change notification settings - Fork 8
Add TrackingValidation workflow for tracking performance studies #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
ArinaPon
wants to merge
15
commits into
key4hep:main
Choose a base branch
from
ArinaPon:pr-tracking-validation
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
55b053d
Add tracking validation consumer
1aed2bd
Rename TrackingValidation consumer source file
2d0e91e
Add TrackingPerformance package and build configuration
847ce7b
Finalize TrackingValidation README
454ad53
Clean README for TrackingValidation PR
7f7f4e8
Refactor TrackingValidation helpers and update documentation
6cdea70
Improve TrackingValidation documentation
b54ec73
Improve TrackingValidation documentation
d957a97
Improve TrackingValidation documentation
a5e107d
Finalize TrackingValidation steering, test, and documentation
4db05df
Finalize TrackingValidation steering, test, and documentation
5fca60d
Finalize test cleanup and helper documentation
180d9e9
Finalize test workflow and documentation
dc3701e
Make tracking validation test script executable
9484462
Address review comments
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,103 @@ | ||
| #[[ | ||
| Copyright (c) 2020-2024 Key4hep-Project. | ||
|
|
||
| This file is part of Key4hep. | ||
| See https://key4hep.github.io/key4hep-doc/ for further info. | ||
|
|
||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||
| you may not use this file except in compliance with the License. | ||
| You may obtain a copy of the License at | ||
|
|
||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
|
|
||
| Unless required by applicable law or agreed to in writing, software | ||
| distributed under the License is distributed on an "AS IS" BASIS, | ||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| See the License for the specific language governing permissions and | ||
| limitations under the License. | ||
| ]] | ||
|
|
||
| set(PackageName TrackingPerformance) | ||
|
|
||
| project(${PackageName}) | ||
|
|
||
| include(ExternalData) | ||
| list(APPEND ExternalData_URL_TEMPLATES | ||
| "https://key4hep.web.cern.ch:443/testFiles/k4RecTracker/%(hash)" | ||
| ) | ||
|
|
||
| file(GLOB sources | ||
| ${PROJECT_SOURCE_DIR}/src/*.cc | ||
| ${PROJECT_SOURCE_DIR}/src/*.cpp | ||
| ${PROJECT_SOURCE_DIR}/src/components/*.cpp | ||
| ) | ||
|
|
||
| file(GLOB headers | ||
| ${PROJECT_SOURCE_DIR}/include/*.h | ||
| ) | ||
|
|
||
| find_package(ROOT REQUIRED COMPONENTS Core RIO Tree MathCore MathMore Graf Graf3d Hist) | ||
|
|
||
| gaudi_add_module(${PackageName} | ||
| SOURCES ${sources} | ||
| LINK | ||
| Gaudi::GaudiKernel | ||
| EDM4HEP::edm4hep | ||
| k4FWCore::k4FWCore | ||
| ROOT::MathCore | ||
| ROOT::MathMore | ||
| ROOT::Physics | ||
| ROOT::Graf | ||
| ROOT::Graf3d | ||
| ROOT::Hist | ||
| ) | ||
|
|
||
| target_include_directories(${PackageName} PUBLIC | ||
| $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> | ||
| $<INSTALL_INTERFACE:include> | ||
| ${MarlinUtil_INCLUDE_DIRS} | ||
| ${DELPHES_INCLUDE_DIRS} | ||
| ) | ||
|
|
||
| set_target_properties(${PackageName} PROPERTIES | ||
| PUBLIC_HEADER "${headers}" | ||
| ) | ||
|
|
||
| file(GLOB test_python_scripts | ||
| ${PROJECT_SOURCE_DIR}/test/*.py | ||
| ) | ||
|
|
||
| set(test_shell_scripts | ||
| ${PROJECT_SOURCE_DIR}/test/testTrackingValidation.sh | ||
| ) | ||
|
|
||
| set(test_scripts | ||
| ${test_python_scripts} | ||
| ${test_shell_scripts} | ||
| ) | ||
|
|
||
| file(COPY ${test_scripts} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/test) | ||
|
|
||
| install(TARGETS ${PackageName} | ||
| EXPORT ${CMAKE_PROJECT_NAME}Targets | ||
| RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT bin | ||
| LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT shlib | ||
| PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${CMAKE_PROJECT_NAME}" COMPONENT dev | ||
| ) | ||
| message(STATUS "CMAKE_SOURCE_DIR = ${CMAKE_SOURCE_DIR}") | ||
| message(STATUS "CMAKE_CURRENT_SOURCE_DIR = ${CMAKE_CURRENT_SOURCE_DIR}") | ||
| message(STATUS "PROJECT_SOURCE_DIR = ${PROJECT_SOURCE_DIR}") | ||
| install(FILES ${test_scripts} DESTINATION test) | ||
|
|
||
| SET(test_name "testTrackingValidation") | ||
|
|
||
| ExternalData_Add_Test(testTrackingValidation | ||
| NAME ${test_name} | ||
| COMMAND sh +x TrackingPerformance/test/testTrackingValidation.sh | ||
| DATA{${CMAKE_SOURCE_DIR}/TrackingPerformance/test/inputFiles/SimpleGatrIDEAv3o1.onnx} | ||
| ) | ||
|
|
||
| set_test_env(${test_name}) | ||
| set_tests_properties(${test_name} PROPERTIES WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}") | ||
| ExternalData_Add_Target(${test_name}) | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,178 @@ | ||
| # TrackingValidation | ||
|
|
||
| ## Overview | ||
|
|
||
| `TrackingValidation` is a validation algorithm for studying the performance (efficiency, purity, residuals, resolutions) of track finding and track fitting in the tracking reconstruction. | ||
| It is designed to compare reconstructed and fitted tracks with Monte Carlo truth information and, when enabled, with tracks obtained from perfect tracking, i.e. tracks fitted using the correct simHits from the particle truth information. The algorithm writes validation information to a ROOT output file containing TTrees and summary plots that can be used later for performance studies and plotting. | ||
|
|
||
| Typical use cases include: | ||
| - validation of track-finder performance, | ||
| - validation of fitted-track parameters against MC truth, | ||
| - comparison between standard reconstructed tracks and perfectly associated reference tracks. | ||
|
|
||
| --- | ||
|
|
||
| ## Inputs | ||
|
|
||
| `TrackingValidation` expects EDM4hep event content in which the relevant collections have already been produced by the preceding steps of the reconstruction chain. | ||
|
|
||
| ### Input collection types | ||
|
|
||
| `TrackingValidation` consumes the following input collections: | ||
|
|
||
| - **MC particle collection** | ||
| Type: `edm4hep::MCParticleCollection` | ||
| Used as the truth reference for particle-level validation. | ||
|
|
||
| - **Planar digi-to-sim link collections** | ||
| Type: `std::vector<const edm4hep::TrackerHitSimTrackerHitLinkCollection*>` | ||
| Used to connect reconstructed planar hits to the originating simulated particles. | ||
|
|
||
| - **Drift-chamber digi-to-sim link collections** | ||
| Type: `std::vector<const edm4hep::TrackerHitSimTrackerHitLinkCollection*>` | ||
| Used to connect reconstructed drift-chamber hits to the originating simulated particles. | ||
|
|
||
| - **Finder track collection** | ||
| Type: `edm4hep::TrackCollection` | ||
| Collection of tracks produced by the track-finding stage. | ||
|
|
||
| - **Fitted track collection** | ||
| Type: `edm4hep::TrackCollection` | ||
| Collection of tracks produced by the standard fitting stage. | ||
|
|
||
| - **Perfect fitted-track collections (optional)** | ||
| Type: `std::vector<const edm4hep::TrackCollection*>` | ||
| Optional reference collections produced from perfect truth-based associations, used when perfect-fit validation is enabled. | ||
|
|
||
| --- | ||
|
|
||
| ## Outputs | ||
|
|
||
| The algorithm writes a ROOT file specified by `OutputFile`. | ||
|
|
||
| The file contains validation TTrees for finder-level and fitter-level studies, together with summary performance plots produced in `finalize()`. The fitter validation trees store residuals of the reconstructed track parameters with respect to the chosen reference. | ||
|
|
||
| ### Output content by mode | ||
|
|
||
| The exact content filled in the output depends on the validation mode selected through `Mode`: | ||
|
|
||
| - **`Mode = 0` (full-pipeline mode)** | ||
| Both finder-level and fitter-level validation are performed. | ||
| The output includes the association trees and the fitter residual trees. | ||
|
|
||
| - **`Mode = 1` (finder-only mode)** | ||
| Only the finder-level validation is performed. | ||
| The finder and perfect-association trees are filled, while the fitter trees are booked in the file but are not filled. | ||
|
|
||
| - **`Mode = 2` (fitter-only mode)** | ||
| Only the fitter-level validation is performed. | ||
| The fitter trees are filled, while the finder and perfect-association trees are booked in the file but are not filled. | ||
|
|
||
| ### Effect of `DoPerfectFit` | ||
|
|
||
| The flag `DoPerfectFit` controls the handling of the `fitter_vs_perfect` output: | ||
|
|
||
| - if **`DoPerfectFit = true`** and perfect fitted-track collections are provided, the fitter-to-perfect comparison is filled; | ||
| - if **`DoPerfectFit = false`**, the `fitter_vs_perfect` tree is still created but its per-event content remains empty; | ||
| - if **`DoPerfectFit = true`** but no perfect fitted-track collection is provided, the tree is still written and a warning is issued. | ||
|
|
||
| ### Summary plots | ||
|
|
||
| In `finalize()`, the algorithm also writes summary plots to the same ROOT file, including: | ||
|
|
||
| - tracking efficiency vs momentum, | ||
| - `d0` resolution vs momentum, | ||
| - momentum resolution vs momentum, | ||
| - transverse-momentum resolution vs momentum. | ||
|
|
||
| --- | ||
|
|
||
| ## Finder validation: efficiency and purity | ||
|
|
||
| To evaluate finder performance, each reconstructed track is matched to the truth particle with which it shares the largest number of hits. | ||
|
|
||
| For each particle-track pair, the algorithm stores two standard hit-based quantities: | ||
|
|
||
| - **track hit purity**: the fraction of hits on the reconstructed track that originate from the matched truth particle; | ||
| - **track hit efficiency**: the fraction of the truth-particle hits that are recovered in the reconstructed track. | ||
|
|
||
| The summary **tracking efficiency** can then be defined in more than one way. | ||
|
|
||
| - **`FinderEfficiencyDefinition = 1`** | ||
| A truth particle is counted as reconstructed if it is associated to at least one finder track with | ||
| `purity >= FinderPurityThreshold`. | ||
| In the default configuration, `FinderPurityThreshold = 0.75`, following the CMS association convention in which a reconstructed track is associated to a simulated particle if more than 75% of its hits originate from that particle. The tracking efficiency is then defined as the fraction of simulated tracks associated to at least one reconstructed track. :contentReference[oaicite:0]{index=0} | ||
|
|
||
| - **`FinderEfficiencyDefinition = 2`** | ||
| A truth particle is counted as reconstructed if it is associated to at least one finder track with | ||
| `purity >= 0.5` **and** `efficiency >= 0.5`. | ||
| This corresponds to the stricter two-ratio variant, where both the purity of the reconstructed track and the fraction of recovered truth hits must exceed 50%. | ||
|
|
||
| In the current implementation, the denominator of the efficiency plot includes generator-level particles with status 1 and at least one truth-linked hit. | ||
| For more details on the CMS association convention and the related definitions of tracking efficiency, fake rate, and duplicate rate, see the CMS performance note [*Performance of the track selection DNN in Run 3*](https://cds.cern.ch/record/2854696/files/DP2023_009.pdf). | ||
|
|
||
|
|
||
|
|
||
|
|
||
| --- | ||
|
|
||
| ## How to run | ||
|
|
||
| `TrackingValidation` is tested through a small end-to-end workflow driven by `ctest`. The test starts from a simulated EDM4hep file, runs the reconstruction and validation steering, and writes the final validation ROOT output. | ||
|
|
||
| In the current setup: | ||
|
|
||
| - the simulation step is performed with `ddsim` in the shell test, | ||
| - the reconstruction and validation steps are controlled by `runTrackingValidation.py`, | ||
| - the full test is launched through `ctest`. | ||
|
|
||
| Run the test from the build directory: | ||
|
|
||
| ```bash | ||
| cd k4DetectorPerformance/build | ||
| ctest -V -R testTrackingValidation | ||
| ``` | ||
|
|
||
| The validation output is written to: | ||
|
|
||
| ```text | ||
| k4DetectorPerformance/TrackingPerformance/test/validation_output_test.root | ||
| ``` | ||
| ### Test configuration and steering options | ||
|
|
||
| The current test runs the full reconstruction and validation chain with the following settings: | ||
|
|
||
| - `TRACKINGPERF_RUN_SIM = 1` | ||
| simulation step in the shell test (`0` = skip simulation and use an existing EDM4hep input file via `TRACKINGPERF_INPUT_FILE_OVERRIDE`, `1` = run simulation with `ddsim`); | ||
|
|
||
| - `runDigi = 1` | ||
| digitization step (`0` = skip digitization, `1` = run digitization); | ||
|
|
||
| - `runFinder = 1` | ||
| track-finder step (`0` = skip track finder, `1` = run track finder); | ||
|
|
||
| - `runFitter = 1` | ||
| reconstructed-track fitter (`0` = skip reco fitter, `1` = run reco fitter); | ||
|
|
||
| - `runPerfectTracking = 1` | ||
| perfect-tracking and perfect-fitter chain (`0` = skip perfect tracking/perfect fitter, `1` = run them); | ||
|
|
||
| - `runValidation = 1` | ||
| validation step (`0` = skip validation, `1` = run validation); | ||
|
|
||
| - `useDCH = 1` | ||
| drift-chamber collections (`0` = disable DCH, `1` = use DCH); | ||
|
|
||
| - `mode = 0` | ||
| validation mode (`0` = full validation, `1` = finder-only validation, `2` = fitter-only validation); | ||
|
|
||
| - `doPerfectFit = 1` | ||
| fitter-versus-perfect comparison (`0` = disable fitter-vs-perfect filling, `1` = enable it); | ||
|
|
||
| - `finderEfficiencyDefinition = 1` | ||
| tracking-efficiency definition (`1` = purity-based definition, `2` = purity >= 0.5 and efficiency >= 0.5); | ||
|
|
||
| - `finderPurityThreshold = 0.75` | ||
| purity threshold used when `FinderEfficiencyDefinition = 1`. | ||
|
|
||
| These command-line flags are defined in `runTrackingValidation.py`, which allows the same steering file to be used either for the full chain or for reduced workflows in which some reconstruction steps are skipped and only the validation is run. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| /* | ||
| * Copyright (c) 2020-2024 Key4hep-Project. | ||
| * | ||
| * This file is part of Key4hep. | ||
| * See https://key4hep.github.io/key4hep-doc/ for further info. | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| #ifndef TRACKINGVALIDATIONHELPERS_H | ||
| #define TRACKINGVALIDATIONHELPERS_H | ||
|
|
||
| #include "edm4hep/MCParticle.h" | ||
| #include "edm4hep/Track.h" | ||
| #include "edm4hep/TrackState.h" | ||
| #include "podio/ObjectID.h" | ||
|
|
||
| #include <cstdint> | ||
|
|
||
| namespace TrackingValidationHelpers { | ||
|
|
||
| /// Container for helix parameters in the fitter convention | ||
| struct HelixParams { | ||
| float D0 = 0.f; | ||
| float Z0 = 0.f; | ||
| float phi = 0.f; | ||
| float omega = 0.f; | ||
| float tanLambda = 0.f; | ||
| float p = 0.f; | ||
| float pT = 0.f; | ||
| }; | ||
|
|
||
| /// Helper container for PCA position and tangent angle | ||
| struct PCAInfoHelper { | ||
| float pcaX = 0.f; | ||
| float pcaY = 0.f; | ||
| float pcaZ = 0.f; | ||
| float phi0 = 0.f; | ||
| bool ok = false; | ||
| }; | ||
|
|
||
| /// Build a unique integer key from a podio object identifier | ||
| uint64_t oidKey(const podio::ObjectID& id); | ||
|
|
||
| /// Safe wrapper around std::atan2 | ||
| float safeAtan2(float y, float x); | ||
|
|
||
| /// Wrap a phi difference into the interval [-pi, pi] | ||
| float wrapDeltaPhi(float a, float b); | ||
|
|
||
| /** | ||
| * @brief Compute the PCA position and tangent angle in mm using a GenFit-like convention. | ||
| * | ||
| * The function derives the point of closest approach to the reference point | ||
| * and the corresponding tangent direction from the input position, momentum, | ||
| * charge sign, and magnetic field. | ||
| */ | ||
|
|
||
| PCAInfoHelper PCAInfo_mm(float x, float y, float z, | ||
| float px, float py, float pz, | ||
| int chargeSign, | ||
| float refX, float refY, | ||
| float Bz); | ||
|
|
||
|
|
||
| /** | ||
| * @brief Build truth helix parameters in the same convention used by the fitter. | ||
| * | ||
| * The returned parameters are derived from the MC particle kinematics and vertex | ||
| * using the same reference-point and helix convention adopted for fitted tracks, | ||
| * so that residuals can be computed consistently. | ||
| */ | ||
|
|
||
| HelixParams truthFromMC_GenfitConvention(const edm4hep::MCParticle& mc, | ||
| float Bz, | ||
| float refX, float refY, float refZ); | ||
|
|
||
| /// Retrieve the track state stored at the interaction point | ||
| bool getAtIPState(const edm4hep::Track& trk, edm4hep::TrackState& out); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This could return a |
||
|
|
||
| /// Compute the transverse momentum from a track state | ||
| float ptFromState(const edm4hep::TrackState& st, float Bz); | ||
|
|
||
| /// Compute the total momentum from a track state | ||
| float momentumFromState(const edm4hep::TrackState& st, float Bz); | ||
|
|
||
| } // namespace TrackingValidationHelpers | ||
|
|
||
| #endif | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
podio::ObjectIDis hashable (since podio v01-03) and it should be possible to directly use it in e.g.std::unordered_mapas a key type. There should be no need for constructing auint64_tfor this purpose.