Skip to content

Major KFParticle alteration#4332

Open
cdean-github wants to merge 9 commits into
sPHENIX-Collaboration:masterfrom
cdean-github:master
Open

Major KFParticle alteration#4332
cdean-github wants to merge 9 commits into
sPHENIX-Collaboration:masterfrom
cdean-github:master

Conversation

@cdean-github

@cdean-github cdean-github commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work for users)
  • Requiring change in macros repository (Please provide links to the macros pull request in the last section)
  • I am a member of GitHub organization of sPHENIX Collaboration, EIC, or ECCE (contact Chris Pinkenburg to join)

What kind of change does this PR introduce? (Bug fix, feature, ...)

As was discussed at yesterdays TG meeting, it is preferable to perform track DCA, pT and IP checks after a secondary vertex has been reconstructed. The act of creating a mother particle and associating the tracks to it causes a refit of the track which means the output nTuple variables are different to the requested cuts. This means that you can have candidates in your output that would fail the selection.

I rewrote significant chunks of the initial reconstruction to allow this. I also moved the check that tracks come from the same bunch crossing to earlier in the code in an attempt to speed up event processing. I'll post timing plots later.

I also renamed the IP branches and selections to PV_DCA as this feels less confusing. IPchi2 is now PV_DCA_StdDev to reflect that the number is actually the number of standard deviations away from the PV.

Finally, I ran the code through codex to identify logic errors. It found a few that I have patched out.

@jdosbo @adfrawley @petermic @hupereir this should cover the suggestions

new_old_DCA_comp_Lmabda_redo new_old_IP_comp_Lambda_redo new_old_mass_comp_Lambda_redo

TODOs (if applicable)

Links to other PRs in macros and calibration repositories (if applicable)

AI can make mistakes, so please use best judgment when reading this summary.

This PR refactors KFParticle reconstruction and output bookkeeping to use PV-based DCA quantities instead of the previous IP/IPchi2 selection logic, and also improves truth-matching and track association in HFTrackEfficiency.

Motivation / context

  • Secondary-vertex track refits can change track observables after mother reconstruction, so selections and stored ntuple values needed to be evaluated in the updated reconstruction context.
  • The new naming (PV_DCA, PV_DCA_StdDev) better reflects the physics meaning of the quantities.
  • Some event-processing checks were moved earlier for speed.

Key changes

  • Reworked KFParticle selection flow so track DCA, pT, and IP-like checks happen after secondary-vertex reconstruction.
  • Renamed IP-based cuts/branches/setters to PV_DCA / PV_DCA_StdDev across:
    • KFParticle_sPHENIX
    • KFParticle_Tools
    • KFParticle_nTuple
    • KFParticle_truthAndDetTools
  • Updated ntuple content:
    • removed old IP/IPchi2 branches
    • added PV_DCA, PV_DCA_StdDev, and XY variants
    • updated fill logic to compute new values
  • Changed reconstruction helpers to thread primaryVertices through prong-finding and combination building.
  • Moved same-bunch-crossing checks earlier in the KFParticle flow.
  • Improved HFTrackEfficiency truth matching:
    • switched from PHG4ParticleSvtxMap-style lookup to SvtxEvalStack / SvtxTrackEval
    • uses best_track_from(...) for reco association
  • Patched several logic issues noted during review, including one setter fix (setMinTPOThits target member).

Potential risk areas

  • IO format changes: ntuple branch names and stored content are changed, so downstream analysis code may break.
  • Reconstruction behavior changes: selection timing and PV-DCA-based cuts may alter candidate yields, masses, and efficiencies.
  • Thread-safety / state handling: new evaluator state and lazy initialization should be checked carefully in multi-event workflows.
  • Performance: moving the bunch-crossing check earlier should help, but the added PV-based recomputation and truth-eval usage may affect runtime.

Possible future improvements

  • Provide a migration note or compatibility layer for old IP/IPchi2 ntuple consumers.
  • Add validation plots/tests comparing old vs new selections and efficiencies.
  • Document the new PV_DCA definitions and branch mapping more explicitly for analysts.
  • Audit remaining code paths for any lingering IP-based naming or assumptions.

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@cdean-github, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 35 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 25e25e91-ceb0-4e73-a542-18831fadb193

📥 Commits

Reviewing files that changed from the base of the PR and between 6f8ee41 and 4104405.

📒 Files selected for processing (3)
  • offline/packages/KFParticle_sPHENIX/KFParticle_Tools.cc
  • offline/packages/KFParticle_sPHENIX/KFParticle_Tools.h
  • offline/packages/KFParticle_sPHENIX/KFParticle_eventReconstruction.cc
📝 Walkthrough

Walkthrough

HFTrackEfficiency migrates truth-to-reco track matching from PHG4ParticleSvtxMap to SvtxEvalStack/SvtxTrackEval. KFParticle_sPHENIX replaces IP/IPchi2-based track, mother, and intermediate-state selection, constraint setters, and ntuple output with primary-vertex DCA (PV_DCA) based quantities throughout Tools, eventReconstruction, nTuple, sPHENIX, and truthAndDetTools files.

Changes

HFTrackEfficiency SvtxEval Migration

Layer / File(s) Summary
SvtxEval headers, members, and link libraries
offline/packages/HFTrackEfficiency/HFTrackEfficiency.h, offline/packages/HFTrackEfficiency/Makefile.am
Adds SvtxEvalStack/SvtxTrackEval includes and private pointer members, comments out m_dst_truth_reco_map, and adds -lg4eval to link libraries.
process_event and findTracks matching logic
offline/packages/HFTrackEfficiency/HFTrackEfficiency.cc
process_event initializes and advances m_svtx_evalstack; findTracks finds daughterG4 via direct PHG4TruthInfoContainer search and picks reco tracks via trackeval->best_track_from(daughterG4), replacing the prior truth_ID/m_dst_truth_reco_map path.

PV-DCA Based Selection Replacing IP-Based Selection

Layer / File(s) Summary
PV-DCA contract and calcMinPV_DCA helper
offline/packages/KFParticle_sPHENIX/KFParticle_Tools.h, offline/packages/KFParticle_sPHENIX/KFParticle_Tools.cc
Declares calcMinPV_DCA and PV-DCA member fields (replacing calcMinIP/IP fields); constructor and isGoodTrack compute PV-DCA and stddev thresholds.
Prong-finding PV wiring
offline/packages/KFParticle_sPHENIX/KFParticle_Tools.cc
findTwoProngs/findNProngs build dummy tracks/mothers to compute DCA against primaryVertices and reject combinations failing isGoodTrack; appendTracksToIntermediates threads primaryVertices through.
constrainToVertex PV-DCA cuts
offline/packages/KFParticle_sPHENIX/KFParticle_Tools.cc
Computes PV-DCA and stddev (XY/3D) and gates candidate acceptance on m_mother_PV_dca* thresholds.
PV-DCA setter API
offline/packages/KFParticle_sPHENIX/KFParticle_sPHENIX.h
Replaces IP/IPchi2 setters for tracks, mother, and intermediates with PV_DCA/PV_DCA_StdDev setters; fixes setMinTPOThits to assign m_nTPOTStates.
eventReconstruction wiring and candidate selection
offline/packages/KFParticle_sPHENIX/KFParticle_eventReconstruction.cc
Passes primaryVertices through decay-building calls, switches intermediate gating to calcMinPV_DCA, renames selectBestCombination metrics to PV_DCAchi2, comments out bunch-crossing filter block, adjusts track window bookkeeping.
nTuple PV_DCA branches and fills
offline/packages/KFParticle_sPHENIX/KFParticle_nTuple.h, offline/packages/KFParticle_sPHENIX/KFParticle_nTuple.cc
Replaces stored IP members and ROOT branches with PV_DCA equivalents for mother, intermediate, and daughter, updating per-event fill logic.
truthAndDetTools PV_DCA truth branches and evaluator use
offline/packages/KFParticle_sPHENIX/KFParticle_truthAndDetTools.h, offline/packages/KFParticle_sPHENIX/KFParticle_truthAndDetTools.cc
Replaces allPV IP/IPchi2 vectors with PV_DCA/PV_DCA_StdDev vectors, switches truth-mother/vertex lookup to trutheval, renames truth branches to PV_DCA.

Sequence Diagram(s)

sequenceDiagram
  participant process_event
  participant SvtxEvalStack
  participant findTracks
  participant SvtxTrackEval
  process_event->>SvtxEvalStack: next_event(topNode)
  process_event->>findTracks: process daughters
  findTracks->>findTracks: search PHG4TruthInfoContainer for daughterG4
  findTracks->>SvtxTrackEval: best_track_from(daughterG4)
  SvtxTrackEval-->>findTracks: matched reco track
Loading

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: cb632a3a-81b5-45b4-8525-5a3c8f4e005c

📥 Commits

Reviewing files that changed from the base of the PR and between 3eafa37 and 6f8ee41.

📒 Files selected for processing (11)
  • offline/packages/HFTrackEfficiency/HFTrackEfficiency.cc
  • offline/packages/HFTrackEfficiency/HFTrackEfficiency.h
  • offline/packages/HFTrackEfficiency/Makefile.am
  • offline/packages/KFParticle_sPHENIX/KFParticle_Tools.cc
  • offline/packages/KFParticle_sPHENIX/KFParticle_Tools.h
  • offline/packages/KFParticle_sPHENIX/KFParticle_eventReconstruction.cc
  • offline/packages/KFParticle_sPHENIX/KFParticle_nTuple.cc
  • offline/packages/KFParticle_sPHENIX/KFParticle_nTuple.h
  • offline/packages/KFParticle_sPHENIX/KFParticle_sPHENIX.h
  • offline/packages/KFParticle_sPHENIX/KFParticle_truthAndDetTools.cc
  • offline/packages/KFParticle_sPHENIX/KFParticle_truthAndDetTools.h

Comment on lines +249 to +254
PHG4Particle *daughterG4 {nullptr};

for (unsigned int i = 1; i < decay.size(); ++i)
{
m_dst_track = nullptr;
int truth_ID = -1;
//int truth_ID = -1;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

file='offline/packages/HFTrackEfficiency/HFTrackEfficiency.cc'

echo '--- file size ---'
wc -l "$file"

echo '--- outline ---'
ast-grep outline "$file" --view expanded || true

echo '--- relevant sections ---'
sed -n '230,470p' "$file" | cat -n

echo '--- search truth_ID declarations/usages ---'
rg -n '\btruth_ID\b' "$file" || true

Repository: sPHENIX-Collaboration/coresoftware

Length of output: 11893


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file='offline/packages/HFTrackEfficiency/HFTrackEfficiency.cc'

echo '--- around line 390-445 ---'
sed -n '390,445p' "$file" | cat -n

echo '--- whole repo search for truth_ID ---'
rg -n '\btruth_ID\b' offline/packages/HFTrackEfficiency || true

echo '--- class member search for trackeval / truth-reco map context ---'
rg -n 'class HFTrackEfficiency|truth_ID|m_dst_truth_reco_map|m_truthInfo|trackeval' offline/packages/HFTrackEfficiency -g '!*.o' || true

Repository: sPHENIX-Collaboration/coresoftware

Length of output: 7187


Reset daughterG4 per daughter and restore truth_ID

  • daughterG4 needs to be cleared at the start of each daughter iteration, and the m_nDaughters == 2 scan should break on the first match; otherwise trackeval->best_track_from(daughterG4) can use the last truth particle seen instead of the matched daughter.
  • truth_ID is still assigned in the m_nDaughters == 3 path, but its declaration is commented out in this scope, so this file will not compile.

Comment on lines +281 to +307
//if (m_dst_truth_reco_map)
//{
PHG4TruthInfoContainer::ConstRange range = m_truthInfo->GetParticleRange();

for (PHG4TruthInfoContainer::ConstIterator iter = range.first; iter != range.second; ++iter)
{
PHG4TruthInfoContainer::ConstRange range = m_truthInfo->GetParticleRange();
//PHG4Particle *daughterG4 = iter->second;
daughterG4 = iter->second;

for (PHG4TruthInfoContainer::ConstIterator iter = range.first; iter != range.second; ++iter)
if (std::abs(daughterG4->get_px() - daughterTrueLV->x()) <= 5e-3 &&
std::abs(daughterG4->get_py() - daughterTrueLV->y()) <= 5e-3 &&
std::abs(daughterG4->get_pz() - daughterTrueLV->z()) <= 5e-3 && daughterG4->get_pid() == decay[i].second)
{
PHG4Particle *daughterG4 = iter->second;

if (std::abs(daughterG4->get_px() - daughterTrueLV->x()) <= 5e-3 &&
std::abs(daughterG4->get_py() - daughterTrueLV->y()) <= 5e-3 &&
std::abs(daughterG4->get_pz() - daughterTrueLV->z()) <= 5e-3 && daughterG4->get_pid() == decay[i].second)
{
truth_ID = daughterG4->get_track_id();
break;
}
//truth_ID = daughterG4->get_track_id();
break;
}
}
//}
}
else
{
PHG4TruthInfoContainer::ConstRange range = m_truthInfo->GetParticleRange();

for (PHG4TruthInfoContainer::ConstIterator iter = range.first; iter != range.second; ++iter)
{
PHG4Particle *daughterG4 = iter->second;
//PHG4Particle *daughterG4 = iter->second;
daughterG4 = iter->second;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Possible unguarded null dereference of m_truthInfo.

m_truthInfo is allowed to remain nullptr (only a warning is logged at line 108-115, no abort). This branch now unconditionally calls m_truthInfo->GetParticleRange() where previously (per the summary) this path was gated by if (m_dst_truth_reco_map). If a "G4TruthInfo" node is ever missing on an event, this will crash.

Comment on lines +59 to +61
SvtxEvalStack *m_svtx_evalstack{nullptr};
SvtxTrackEval *trackeval{nullptr};
//PHG4ParticleSvtxMap *m_dst_truth_reco_map{nullptr};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map the target header and implementation first.
git ls-files 'offline/packages/HFTrackEfficiency/*' | sed -n '1,20p'

echo
echo '--- header outline ---'
ast-grep outline offline/packages/HFTrackEfficiency/HFTrackEfficiency.h --view expanded

echo
echo '--- implementation outline ---'
ast-grep outline offline/packages/HFTrackEfficiency/HFTrackEfficiency.cc --view expanded

echo
echo '--- relevant header lines ---'
sed -n '1,160p' offline/packages/HFTrackEfficiency/HFTrackEfficiency.h | nl -ba | sed -n '1,140p'

echo
echo '--- relevant implementation lines ---'
sed -n '1,260p' offline/packages/HFTrackEfficiency/HFTrackEfficiency.cc | nl -ba | sed -n '1,240p'

Repository: sPHENIX-Collaboration/coresoftware

Length of output: 691


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check for any destructor / cleanup / ownership-related code paths.
rg -n "HFTrackEfficiency::~HFTrackEfficiency|delete m_svtx_evalstack|m_svtx_evalstack|unique_ptr|SvtxEvalStack" offline/packages/HFTrackEfficiency

Repository: sPHENIX-Collaboration/coresoftware

Length of output: 774


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- header excerpt ---'
sed -n '1,140p' offline/packages/HFTrackEfficiency/HFTrackEfficiency.h | cat -n

echo
echo '--- implementation excerpt ---'
sed -n '100,140p' offline/packages/HFTrackEfficiency/HFTrackEfficiency.cc | cat -n

Repository: sPHENIX-Collaboration/coresoftware

Length of output: 7731


Replace m_svtx_evalstack with RAII ownership

m_svtx_evalstack is allocated with new in process_event, and HFTrackEfficiency only has a default destructor, so the stack is never released. Please switch this member to std::unique_ptr<SvtxEvalStack> (and include <memory>) to make ownership explicit and avoid a job-lifetime leak.

Source: Path instructions

Comment on lines +414 to +417
m_calculated_mother_PV_dca = motherParticle.GetDistanceFromVertex(vertex_fillbranch);
m_calculated_mother_PV_dca_sig = motherParticle.GetDeviationFromVertex(vertex_fillbranch);
m_calculated_mother_PV_dca_err = m_calculated_mother_PV_dca / std::sqrt(m_calculated_mother_PV_dca_sig);
m_calculated_mother_PV_dca_xy = motherParticle.GetDistanceFromVertexXY(vertex_fillbranch);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map the relevant file and nearby symbols
ast-grep outline offline/packages/KFParticle_sPHENIX/KFParticle_nTuple.cc --view expanded || true

# Locate GetDeviationFromVertex usage and related helpers
rg -n "GetDeviationFromVertex|PV_dca_err|PV_dca_sig|constrainToVertex" offline/packages/KFParticle_sPHENIX -S

# Read the relevant sections with line numbers
sed -n '390,525p' offline/packages/KFParticle_sPHENIX/KFParticle_nTuple.cc

# Inspect the helper file mentioned in the review comment
if [ -f offline/packages/KFParticle_sPHENIX/KFParticle_Tools.cc ]; then
  sed -n '1,220p' offline/packages/KFParticle_sPHENIX/KFParticle_Tools.cc
fi

Repository: sPHENIX-Collaboration/coresoftware

Length of output: 20101


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect any local KFParticle headers or vendored API docs for GetDeviationFromVertex
fd -a "KFParticle*.h" offline packages . 2>/dev/null | sed -n '1,120p'
rg -n "GetDeviationFromVertex\\s*\\(" -S .

Repository: sPHENIX-Collaboration/coresoftware

Length of output: 2657


🌐 Web query:

KFParticle GetDeviationFromVertex returns sqrt(Chi2/NDF) documentation source code

💡 Result:

The KFParticle library, commonly used in high-energy physics experiments like sPHENIX and STAR, defines the function GetDeviationFromVertex to calculate the deviation of a particle from a vertex in units of sqrt(Chi2/NDF) [1][2][3]. Documentation and source code indicate that this function calculates a normalized distance (or deviation) from a specified vertex (or another particle) [1][3][4]. The function is defined in both the KFParticle and KFParticleBase classes [2][3][5]. Key details from the source code and documentation: 1. Purpose: The function is explicitly documented as a method to "Calculate sqrt(Chi2/ndf) deviation from vertex" [3][4]. 2. Signature: It is typically available as overloads accepting a vertex position array (and an optional covariance matrix) or another KFParticle object [2][5][6]. Example signature (from KFParticleBase.h): float GetDeviationFromVertex( const float v[], const float Cv[]=0) const; float GetDeviationFromVertex( const KFParticleBase &Vtx) const; 3. Context: The deviation is calculated using the particle's state and the provided vertex's position [v] and optional covariance matrix [Cv] [3][6]. Authoritative sources for this documentation include: - The sPHENIX Collaboration's Doxygen documentation and code browser for KFParticle [7][3][8]. - The STAR Experiment's (StRoot) KFParticle class documentation and source files [2][9][6]. - The PandaRoot documentation [5]. You can find the implementation and header files in the KFParticle repository on GitHub or via the specific collaboration's software repositories [1][3][10].

Citations:


🌐 Web query:

KFParticle GetDeviationFromVertex sqrt Chi2 ndf source code

💡 Result:

In the KFParticle software package, the GetDeviationFromVertex method is a function designed to calculate the statistical deviation of a particle from a given vertex [1][2][3]. It represents the square root of the normalized chi-square value (sqrt(Chi2/ndf)), providing a measure of how far a particle is from a vertex in terms of standard deviations [1][2][4][5]. Key Technical Details: - Mathematical Basis: The function computes sqrt(Chi2/ndf), where Chi2 is the chi-square fit value and ndf is the number of degrees of freedom [1][6][7]. - Function Purpose: It is commonly used in vertex reconstruction algorithms to assess the compatibility of a particle track with a reconstructed primary or secondary vertex [8][9]. - Implementation: The method exists within the KFParticle class (and its base class, KFParticleBase) [3][4][5]. It typically leverages the GetDistanceFromVertexXY or GetDistanceFromVertex methods to calculate the underlying chi-square, which is then divided by the number of degrees of freedom and square-rooted [2][6]. - Variations: There are variations for 3D space (GetDeviationFromVertex) and 2D projections (GetDeviationFromVertexXY), as well as overloads that accept different types of vertex representations (e.g., arrays, KFParticle objects, or KFPVertex objects) [1][3][10][5]. You can find the implementation in the source files KFParticle.cxx and KFParticleBase.h within the KFParticle repository [2][6][4][11]. The logic usually follows this pattern: 1. Calculate the distance and covariance from the vertex [2][6]. 2. Compute the chi-square difference [2][6]. 3. Return the square root of that value divided by the degrees of freedom [1][2].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail
sed -n '1138,1156p' offline/packages/KFParticle_sPHENIX/KFParticle_Tools.cc
sed -n '1498,1518p' offline/packages/KFParticle_sPHENIX/KFParticle_truthAndDetTools.cc

Repository: sPHENIX-Collaboration/coresoftware

Length of output: 2155


🌐 Web query:

"GetDeviationFromVertex" KFParticle documentation stddev

💡 Result:

In the KFParticle library, the method GetDeviationFromVertex (and its variant GetDeviationFromVertexXY) calculates the square root of the Chi-squared per degree of freedom (sqrt(Chi2/ndf)) representing the deviation of a particle from a given vertex [1][2][3][4]. This value is used to quantify the distance between the particle and the vertex in units of their combined errors (statistical significance of the separation) [5]. It is not a standard deviation in the sense of a simple Gaussian width, but rather a pull-like metric evaluating how compatible the particle's trajectory is with originating from that specific vertex, accounting for the covariance matrices of both the particle and the vertex [1][4][5]. Key details include: - Functionality: It computes a statistical distance (sqrt(Chi2/ndf)) [2][3]. - Inputs: It typically accepts either a raw array representing vertex coordinates and an optional covariance matrix, or an existing KFParticle/KFPVertex object [1][6][7]. - Related Methods: The library also provides GetDistanceFromVertex, which calculates the simple spatial distance in centimeters, distinct from the statistical deviation provided by GetDeviationFromVertex [1][4][5].

Citations:


Fix the *_PV_dca_err calculation

GetDeviationFromVertex() already returns the deviation, so dividing by std::sqrt(*_PV_dca_sig) is incorrect. Use distance / *_PV_dca_sig in the mother, intermediate, and daughter blocks.

Comment thread offline/packages/KFParticle_sPHENIX/KFParticle_Tools.cc
Comment on lines +516 to +519
auto minmax_PV_dca = minmax_element(ip.begin(), ip.end()); // Order the PV_DCA from small to large
minimumPV_DCA = *minmax_PV_dca.first;
auto minmax_PV_dca_stddev = minmax_element(ip_significance.begin(), ip_significance.end()); // Order the PV_DCA chi2 from small to large
minimumPV_DCA_stddev = *minmax_PV_dca_stddev.first;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Guard against an empty PVs collection.

If PVs is empty, ip/ip_significance stay empty and minmax_element returns {end, end}; dereferencing *minmax_PV_dca.first on line 517/519 is undefined behavior (likely a crash). Events with no reconstructed primary vertex would hit this path.

🛡️ Suggested guard
+  if (ip.empty())
+  {
+    minimumPV_DCA = std::numeric_limits<float>::max();
+    minimumPV_DCA_stddev = std::numeric_limits<float>::max();
+    return -1;
+  }
+
   auto minmax_PV_dca = minmax_element(ip.begin(), ip.end());  // Order the PV_DCA from small to large
   minimumPV_DCA = *minmax_PV_dca.first;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
auto minmax_PV_dca = minmax_element(ip.begin(), ip.end()); // Order the PV_DCA from small to large
minimumPV_DCA = *minmax_PV_dca.first;
auto minmax_PV_dca_stddev = minmax_element(ip_significance.begin(), ip_significance.end()); // Order the PV_DCA chi2 from small to large
minimumPV_DCA_stddev = *minmax_PV_dca_stddev.first;
if (ip.empty())
{
minimumPV_DCA = std::numeric_limits<float>::max();
minimumPV_DCA_stddev = std::numeric_limits<float>::max();
return -1;
}
auto minmax_PV_dca = minmax_element(ip.begin(), ip.end()); // Order the PV_DCA from small to large
minimumPV_DCA = *minmax_PV_dca.first;
auto minmax_PV_dca_stddev = minmax_element(ip_significance.begin(), ip_significance.end()); // Order the PV_DCA chi2 from small to large
minimumPV_DCA_stddev = *minmax_PV_dca_stddev.first;

Comment thread offline/packages/KFParticle_sPHENIX/KFParticle_Tools.cc Outdated
cdean-github and others added 4 commits July 2, 2026 18:27
…tion.cc

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@cdean-github

Copy link
Copy Markdown
Contributor Author

This PR actually drastically improves the timing. Probably as I reject combinations from different bunch crossings earlier

perEvtTiming_KFP

@sphenix-jenkins-ci

Copy link
Copy Markdown

Build & test report

Report for commit 6f8ee41ff33e7b4b625da3be3046de85357d79d6:
Jenkins on fire


Automatically generated by sPHENIX Jenkins continuous integration
sPHENIX             jenkins.io

@sphenix-jenkins-ci

Copy link
Copy Markdown

Build & test report

Report for commit d712e8af449657832111561705cd3c190b544afe:
Jenkins on fire


Automatically generated by sPHENIX Jenkins continuous integration
sPHENIX             jenkins.io

@sphenix-jenkins-ci

Copy link
Copy Markdown

Build & test report

Report for commit bdedb9ee01baab1c8a616ddc49cc2e0a7bb9527e:
Jenkins on fire


Automatically generated by sPHENIX Jenkins continuous integration
sPHENIX             jenkins.io

@sphenix-jenkins-ci

Copy link
Copy Markdown

Build & test report

Report for commit 41044057570d44932712b355c14dd4b223a90c72:
Jenkins on fire


Automatically generated by sPHENIX Jenkins continuous integration
sPHENIX             jenkins.io

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant