-trk flag, and the PDS/light pipeline is activated with -pds. When both flags are provided, a final TPC–PDS matching step is performed.
Each detector module is processed independently during signal processing and per-module reconstruction. Cross-module steps run after all individual modules have been processed.
TPC/Charge Pipeline (-trk)
The charge pipeline is orchestrated in workflow.py. For each module, charge_signal_proc handles signal processing and charge_reco handles the actual reconstruction. After all modules are processed, charge_reco_whole performs detector-level stitching and timing.
Read raw data per module
Raw ADC waveforms are read from file for the current module. Dead or masked channels are excluded from processing via
dc.alive_chan.Signal processing (per module)
The
charge_signal_proc function applies a multi-stage noise removal chain. See Signal Processing for the full breakdown.In order:- Raw pedestal computation (
ped.compute_pedestal(noise_type='raw')) - Two iterations of filtered pedestal + mask refinement
- FFT low-pass filter (
noise.FFT_low_pass) - Zero-padding if the sample count became odd after FFT
- Two more iterations of filtered pedestal + mask refinement (pass 2)
- Shield coupling removal for PDVD TDE View 0 (
noise.shield_coupling) - Coherent noise removal (
noise.coherent_noise) - Microphonic noise removal (
noise.median_filter) - Final pedestal computation and mask refinement
Hit finding
hf.find_hits() extracts hit objects from signal regions of interest (ROI) in each channel. An R-tree spatial index is built immediately after with clu.hits_rtree([cf.imod]) for efficient proximity lookups during tracking.2D track finding (Hough transform + Kalman filter)
trk2d.find_tracks_hough([cf.imod]) searches each wire view independently for track candidates using a Hough transform to seed tracks, followed by a Kalman-style filter to extend and validate them. Tracks are found in the position–drift-time (X–Z) plane.2D track stitching within module
stitch.stitch2D_in_module([cf.imod]) merges 2D track segments belonging to the same physical track within a module, using alignment and proximity thresholds.3D track reconstruction (3 views)
trk3d.find_track_3D_rtree_new([cf.imod]) combines 2D tracks from all three wire views using R-tree-based Z-overlap searches and graph-based connected component analysis to build 3D trajectories.3D track reconstruction with missing view
trk3d.find_3D_tracks_with_missing_view([cf.imod]) handles cases where one wire view has no matched 2D track. It attempts to reconstruct a 3D track from the remaining two views using charge and Z-overlap criteria.Single-hit (blip) finder
sh.single_hit_finder([cf.imod]) runs after track reconstruction and searches for isolated charge depositions (blips) in hits not assigned to any track. DBSCAN clustering is used to group nearby free hits across views.Cross-module 3D track stitching
Runs in
charge_reco_whole after all modules have been processed individually.- PDHD:
stitch3D_across_modules([0,1]), thenstitch3D_across_modules([2,3]), thenstitch3D_across_cathode([[0,1],[2,3]]) - PDVD:
stitch3D_across_modules([0,1]), thenstitch3D_across_modules([2,3]), thenstitch3D_across_cathode([[2,3],[0,1]])
PDS/Light Pipeline (-pds)
The light pipeline is orchestrated by pds_signal_proc and pds_reco in workflow.py. It operates on two types of PDS data simultaneously: streaming (continuous readout) and self-triggered data.
PDS reconstruction is only configured for
pdvd and cbbot. It does not work for pdhd, and is not configured for cbtop, cb1top, cb1bot, dp, or 50l.PDS signal processing
pds_signal_proc applies three steps:- First pedestal pass:
ped.compute_pedestal_pds(first=True)— removes the waveform median and builds a signal mask usingraw_adc_thresh = 200ADC. - Median filter:
noise.median_filter_pds()— flattens the baseline using a sliding median window of 4000 samples. - Second pedestal pass:
ped.compute_pedestal_pds(first=False)— refines the pedestal after filtering.
PDS hit/peak finding
hf.find_all_pds_peak() searches for peaks in both streaming and triggered PDS data. The same collection-type hit-finding algorithm used for TPC is applied, with amplitude thresholds of [5, 8] × RMS, a minimum duration of 50 samples, and left/right padding of 30/50 samples.TPC–PDS Matching
When both-trk and -pds are active, match_charge_and_pds calls mat.matching_trk_pds() to associate reconstructed 3D tracks with light clusters.
Tracks are classified into categories (anode-crossers, cathode-crossers, unknown), and each category is matched against light clusters within a configurable time tolerance window (default ±5 μs). Only unambiguous one-to-one matches are recorded.
See PDS Reconstruction for details.