feat: add phi_hat delay tracking to BasebandReplayChannel#85
Conversation
Implement delay-tracking (phi_hat) replay matching the MATLAB/Python reference implementations: re-insert phase and delay drift via time-shifted interpolation. Update the file reader to accept phi_hat, theta_hat, or neither, plus the optional f_resamp factor, per the UACR file-format spec. Fix a pre-existing one-step offset in the phase-vector indexing that affected both phi_hat and theta_hat modes. Promote phase fields and fc to Float64 for delay-grid precision while keeping h as ComplexF32 for memory. Add test cases (physics, zero-phase identity, constant-phase recovery), resolving the open TODO. Validated against the Python reference on a real channel (black.mat): per-receiver correlation 0.9997, lag 0, power ratio 1.0.
|
@Yugam2508 there seem to be a merge conflict. Would you like to resolve it before I review? |
Apologies, resolved. |
|
Scope can be |
| @@ -0,0 +1,86 @@ | |||
| using TestItems | |||
|
|
|||
| @testsnippet ReplaySetup begin | |||
There was a problem hiding this comment.
Should we add a test that checks the whole replayed impulse response against a Python version (can be a stored version so we don't have to call Python)? We need to cover various cases with phi, theta, etc, so we may need more than one channels in the tests?
There was a problem hiding this comment.
working on this, will update it soon.
There was a problem hiding this comment.
Pull request overview
Adds full phi_hat (delay-tracking) support and updated UACR .mat parsing to BasebandReplayChannel, bringing the Julia replay channel in line with the referenced channel-library formats and behavior.
Changes:
- Implement
phi_hatphase reinsertion + delay-drift (time-grid) re-interpolation intransmit, plusf_resamppassband resampling support. - Update
.matloader to acceptphi_hat,theta_hat, or neither (pure convolution), and validate phase/IR duration. - Add replay-focused tests and include
SignalAnalysisas a test dependency; ignore large channel/noise data artifacts via.gitignore.
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
src/replay.jl |
Implements phi_hat drift handling, updates file loading logic, adds f_resamp, and adjusts phase indexing. |
test/test_replay.jl |
Adds physics/identity/constant-phase replay tests for the updated replay channel behavior. |
test/Project.toml |
Adds SignalAnalysis dependency needed by the new replay tests. |
.gitignore |
Ignores large binary channel/noise data files (*.mat, *.bin). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Apply Copilot review suggestions to BasebandReplayChannel: - guard power normalisation against divide-by-zero on all-zero output - use a view in the drift interpolation to avoid a per-receiver copy - represent an absent theta_hat as a 0x0 matrix, consistent with phi_hat
What this does
Brings the Julia
BasebandReplayChannelto parity with the MATLAB/Pythonreference implementations in the uwa-channels
project, so it works with current channel-library files.
Changes
phi_hat). Implements the previously-stubbed(
# TODO: apply drift) delay-tracking mode: re-inserts both the phase(via
cis.(φ)) and the delay drift (Δτ = φ / 2πfc, applied byre-interpolating on a time-shifted grid), matching the reference.
phi_hat,theta_hat, or neither (pureconvolution), plus the optional
f_resamppassband factor, per theUACR file-format spec.
Previously
theta_hatwas mandatory.phase-vector indexing (
start * step→(start-1) * step + 1) thataffected both
phi_hatandtheta_hatmodes.fctoFloat64(delay-gridand long-signal carrier accuracy) while keeping
hasComplexF32topreserve the memory characteristics for large channels.
test/test_replay.jl(physics, zero-phase identity,constant-phase recovery), resolving the open
# TODO: add test cases.Validation
channel (
black.mat): per-receiver correlation 0.9997, lag 0,power ratio 1.0 across all 8 receivers.
Implementation note: interpolation differences
This is a port to Julia-native primitives, not a line-by-line translation, so
it is not expected to be bit-identical to the Python reference. Two sites use
different (but equivalent-in-the-interior) interpolation:
time axis with scipy
CubicSpline; this PR usesDSP.resample(polyphaseFIR), consistent with how
transmitalready resamples the baseband signal.CubicSpline(not-a-knot boundaries); this PR usesInterpolations.BSpline(Cubic(Line()))with linear extrapolation outsidethe grid.
Both schemes are cubic and agree in the signal interior, differing most at the
edges due to the different boundary conditions. This is what accounts for the
residual in the cross-validation (0.9997 rather than 1.0): the two
implementations agree on the physics and diverge only at the level of numerical
interpolation, not algorithm. If bit-level parity with the reference is
preferred, the drift interpolation can be switched to a not-a-knot cubic to
match — happy to do so on request.
Notes
pm(channel models are closely related todata-driven propagation models).
marked
# TODO: support UACR noise models. Will work on it next.