Skip to content

refactor(alert): move AHDC track-finding from AHDCEngine to ALERTEngine#1242

Open
mathieuouillon wants to merge 14 commits into
developmentfrom
rgl_trackfinding_gnn
Open

refactor(alert): move AHDC track-finding from AHDCEngine to ALERTEngine#1242
mathieuouillon wants to merge 14 commits into
developmentfrom
rgl_trackfinding_gnn

Conversation

@mathieuouillon
Copy link
Copy Markdown
Collaborator

AHDCEngine now only reads AHDC::adc, applies calibration via HitReader, and writes AHDC::hits. The full track-finding pipeline (preclustering, AI/CV_Distance/CV_Hough finder, DOCA refinement, helix fit) runs in ALERTEngine on top of AHDC::hits + ATOF::hits/clusters, alongside the existing projection / matching / prePID / Kalman steps.

The track finder is selected via the ALERT.Mode YAML key (was AHDC.Mode); ModelTrackFinding only loads when AI_Track_Finding is selected. The ATOF::tdc gate now fires after the AHDC pipeline so events without ATOF still get their AHDC::* banks, matching the pre-refactor behavior.

@mathieuouillon
Copy link
Copy Markdown
Collaborator Author

Note: AHDC::hits.adc is stored as int (calibrated ADC truncated). Track.get_sum_adc rounds Hit.getADC() per hit, so when track-finding ran inside AHDCEngine it summed the original full-precision double. Reading back from the bank here gives integer adc values, so sum_adc and dEdx in AHDC::track can drift by 0-1 per hit relative to the pre-refactor output (≈1-6 counts in sum_adc on ~1% of events). Eliminating the drift would require widening AHDC::hits.adc from I to F/D in the schema.

@mathieuouillon
Copy link
Copy Markdown
Collaborator Author

Compared AHDC::track row counts between the two finders on the same 1000-event input (clas_021903.evio.00000, recon-util -n 1000), toggling only the ALERT.Mode YAML key.

Metric MLP GNN
Total tracks 9 35
Mean tracks / event 0.009 0.035
Events with ≥1 track 9 34

GNN finds ~3.9× more tracks overall.


Per-event breakdown (1000 events)

Bucket Count
Both finders have tracks 9
Only MLP has tracks 0
Only GNN has tracks 25
Neither has tracks 966
MLP rows > GNN rows (per event) 0
MLP rows < GNN rows (per event) 25
MLP rows == GNN rows 975

@mathieuouillon mathieuouillon force-pushed the rgl_trackfinding_gnn branch 2 times, most recently from 26ba2cb to d09f721 Compare May 11, 2026 12:24
@mathieuouillon mathieuouillon marked this pull request as ready for review May 11, 2026 12:24
@mathieuouillon
Copy link
Copy Markdown
Collaborator Author

Tested on 100 files for the run 22991, no error or warning with clara

Comment thread reconstruction/alert/src/main/java/org/jlab/rec/ahdc/TrackFindingMode.java Outdated
Comment thread reconstruction/alert/src/main/java/org/jlab/rec/ahdc/TrackFindingMode.java Outdated
Comment thread reconstruction/alert/src/main/java/org/jlab/rec/ahdc/AI/GNNGraphBuilder.java Outdated
@mathieuouillon mathieuouillon force-pushed the rgl_trackfinding_gnn branch from dc61b1e to 36f990b Compare May 18, 2026 17:13
@mathieuouillon
Copy link
Copy Markdown
Collaborator Author

Now the default for the track finding is the GNN

@mathieuouillon
Copy link
Copy Markdown
Collaborator Author

Ok @whit2333 I think I fix all the problems you mention.

@mathieuouillon mathieuouillon force-pushed the rgl_trackfinding_gnn branch from 3278d25 to 8693354 Compare May 22, 2026 15:16
@baltzell baltzell requested a review from whit2333 May 23, 2026 02:21
AHDCEngine now only reads AHDC::adc, applies calibration via HitReader, and writes AHDC::hits. The full track-finding pipeline (preclustering, AI/CV_Distance/CV_Hough finder, DOCA refinement, helix fit) runs in ALERTEngine on top of AHDC::hits + ATOF::hits/clusters, alongside the existing projection / matching / prePID / Kalman steps.

The track finder is selected via the ALERT.Mode YAML key (was AHDC.Mode); ModelTrackFinding only loads when AI_Track_Finding is selected. The ATOF::tdc gate now fires after the AHDC pipeline so events without ATOF still get their AHDC::* banks, matching the pre-refactor behavior.
…erface

Introduce TrackFinder { findTracks(hits) -> TrackFinderResult } with three implementations — AITrackFinder, DistanceTrackFinder, HoughTrackFinder — each owning its own preclustering, cluster building, and mode-specific logic. AITrackFinder owns ModelTrackFinding, the MAX_HITS_FOR_AI Distance fallback, and the greedy non-overlap selection; the "too many candidates" exit becomes TrackFinderResult.invalid() instead of a return-false from processDataEvent. ALERTEngine becomes a thin dispatcher: init() picks the strategy from ALERT.Mode via a switch, and processDataEvent calls findTracks(hits) once. Output is byte-identical to the prior refactor (same 9/999 sum_adc/dEdx precision drift, no new mismatches).
Introduce GNN_Track_Finding as a fourth track-finding mode alongside the renamed MLP_Track_Finding (was AI_Track_Finding), CV_Distance, and CV_Hough. The new path runs a GravNet edge scorer (TorchScript via DJL) on a per-event AHDC + ATOF hit graph, extracts tracks as connected components on edges with sigmoid score >= 0.1, then re-preclusters each surviving track's AHDC hits and pairs them into per-superlayer Clusters so the existing DOCA refinement + helix fit + Kalman stages consume them unchanged.
Selected via ALERT.Mode in YAML. MLP regression is bit-identical (same pre-existing AHDC::track sum_adc/ dEdx precision drift); only COAT::config changes, reflecting the renamed mode.
…Track (fit result)

The AHDC track finders produced org.jlab.rec.ahdc.Track.Track, and the helix fit + Kalman filter then mutated that same object in place. One class was doing two jobs: a track-finder output (hits + clusters) and a fit result (vertex, momentum, chi2). A "Track" should mean the result of track fitting.

Split the conflated class into two:

- TrackCandidate: the track-finder output. Owns hits, clusters, and interclusters. Carries a CandidateType (AHDC_ONLY / AHDC_ATOF, plus a reserved AHDC_VERTEX) describing its specialization; the type is what will dictate how the candidate is fitted. The two old Track constructors (from Clusters, from Hits) move here.

- Track: the fit result, produced by fitting a TrackCandidate. Composes the candidate it was fitted from and adds the fitted vertex, momentum, chi2, path, dEdx, p_drift, sum_residuals. It stays a full facade: every accessor the old Track exposed still works, and the candidate-side ones are delegated to the underlying TrackCandidate.

All four finders (MLP / Distance / Hough / GNN) plus Distance and HoughTransform now produce TrackCandidate; TrackFinderResult wraps List<TrackCandidate>. ALERTEngine's fit stage turns each candidate into a Track, with a switch (CandidateType) dispatch seam.
Add a YAML-config section to the ALERTEngine class javadoc listing every key the engine reads (currently just Mode) together with the valid values of TrackFindingMode.

Flip the default track-finding mode from AI_MLP to AI_GNN: GNN is now the default.
…not DataBank

ove bank I/O to the ALERTEngine boundary:

- TrackFinder.findTracks now takes List<AtofHitStub>. The interface speaks pure domain types; the ATOF-blind finders simply ignore it.
- GNNPrediction / GNNGraphBuilder accept the list directly and iterate it instead of reading from the bank.

Verified byte-identical end-to-end: recon_output on
clas_021903.evio.00000 (config_p0v9.local.yaml, AI_MLP, 1000 events) is
unchanged vs development

 AHDC::track has the same pre-existing 9/999 sum_adc/dEdx
precision drift
…alert

The TrackFinding strategy, the Track/TrackCandidate value types, and the AI/* models live in rec.ahdc today, but they are ALERT-level orchestration
across AHDC and ATOF (GNN literally builds a joint AHDC+ATOF graph). They
belong in rec.alert.* alongside the existing rec.alert.TrackMatchingAI,
rec.alert.AIPID, rec.alert.banks, rec.alert.projections.
@baltzell baltzell force-pushed the rgl_trackfinding_gnn branch from 8693354 to 67662b2 Compare May 23, 2026 03:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants