|
LDMX Software
|
This directory contains a runnable example of the real-data (test-beam / Rogue) tracker reconstruction chain, from raw .dat bytes through assembled per-channel waveforms, plus a self-contained plotting script.
This is the real-data counterpart to the simulation chain in
Tracking/python/full_tracking_sequence.py(DigitizationProcessor → StripFitProcessor → StripClusterProcessor → …). The two are designed to converge downstream atFittedSiStripHit/Measurement; the real-data pulse-fit step that bridges the two is not yet implemented (see "Where this fits" below).
| Collection | Type | Produced by |
|---|---|---|
TrackerRawData | std::vector<uint8_t> | SingleSubsystemUnpacker |
RawSiStripHits | std::vector<RawSiStripHit> | RawTrackerDecoder |
TrackerHits | std::vector<RawSiStripHit> | PedestalSubtractor (pedestal-subtracted samples) |
TrackerWaveforms | std::vector<SiStripWaveform> | SiStripWaveformBuilder |
Pedestals and per-channel noise are not stored in the event — they are a conditions object (TrackerPedestals) served by TrackerPedestalProvider, the same way Ecal/Hcal deliver their HGCROC pedestals/gains. PedestalSubtractor queries it for the per-sample means; SiStripWaveformBuilder queries it for the per-channel noise used in the significance cuts. The raw and subtracted hit collections are both RawSiStripHit, distinguished only by name.
just build).The raw .dat files must be mounted into the denv container (anything outside the workspace is not visible by default):
Pedestals must come from a dedicated baseline/pedestal run, not a physics run. PedestalCalculator accumulates per-channel, per-sample mean and RMS noise and writes pedestals.json.
2560 channels = 4 hybrids × 5 APV25 × 128 channels — a full tracker readout.
SiStripWaveformBuilder groups all APV-trigger hits for each (feb, hybrid, pchannel), sorts by trigger, concatenates into a n_triggers × 3-sample waveform, and keeps a channel only if it passes a two-stage significance cut.
Useful flags:
| Flag | Default | Meaning |
|---|---|---|
--high-threshold | 5.0 | per-sample ADC/noise for the high-threshold count cut |
--min-high-samples | 4 | min samples that must exceed high_threshold |
--low-threshold | 3.0 | per-sample ADC/noise for the consecutive-streak cut |
--min-consecutive-low | 5 | min consecutive samples exceeding low_threshold |
--n-triggers | 10 | expected APV triggers per RoR |
--verbose-waveforms | off | print ASCII traces of every kept waveform |
plot_waveforms.py is not an ldmx processor — it is a plain PyROOT + matplotlib script that loads the Tracking Event dictionary, reads the TrackerWaveforms collection straight out of the LDMX_Events tree, and writes PNGs (multi-panel overview, per-waveform panels, and strip occupancy).
The cuts are expressed in units of per-channel noise σ (sample value ÷ the RMS noise from pedestals.json), so they are gain-independent.
Sanity checks observed on real data:
5σ/3σ cuts, peak significances reach **~25–47σ** above baseline (median ~17σ) — real, large APV25 pulses.5σ. This is expected, not a failure; loosen the thresholds (e.g. --high-threshold 2 --min-high-samples 2 --low-threshold 1.5 --min-consecutive-low 2) to inspect near-noise channels.Caveats:
Nσ cuts become too tight. Common-mode subtraction before the noise estimate is a likely future improvement.pedestals.json is keyed by feb:hybrid:apv:channel; a physics run decoded with a mismatched pedestal file will log no pedestal for channel … warnings and pass those hits through with noise = 0 (which the builder then skips).This chain currently ends at SiStripWaveform. To join the shared Acts-based track-finding spine (SeedFinderProcessor → CKFProcessor → …), the real-data waveforms need to become FittedSiStripHits (amplitude + t0 per strip, the same type the simulation produces via StripFitProcessor), after which the existing StripClusterProcessor — which already "runs on both real data and simulation" — turns them into Measurements. The missing pieces are a waveform pulse-fit step and a (feb,hybrid,pchannel) → (layer,strip) geometry mapping.