Signal Processing¶
Lightweight 1D signal-processing helpers used by the FFT / smoothing workflows: apodization windows, FFT zero-fill sizing, echo-centre detection, and a small Signal_Processing class for smoothing, baseline subtraction, and normalization. Every routine takes and returns plain NumPy arrays.
The module-level functions (apodization_window, zerofill_length, echo_center) are called directly; the smoothing / baseline / normalization helpers live on the Signal_Processing class.
Note
savitzky_golay() requires scipy (the math extra: pip install -e .[math]); everything else is NumPy-only.
Functions¶
apodization_window()¶
Returns an apodization window of length n to multiply onto a time-domain signal before an FFT. name is one of:
'None', 'Hann', 'Hamming', 'Blackman', 'Bartlett', 'Flat-top', 'Kaiser', 'Gaussian', 'Tukey'.
param is the shape parameter for the three parametric windows and is ignored by the rest:
| Window | param meaning |
Typical |
|---|---|---|
Kaiser |
β | 8.6 |
Gaussian |
σ as a fraction of n |
0.15 |
Tukey |
α taper fraction (0 → rectangular, 1 → Hann) |
0.5 |
zerofill_length()¶
Target FFT length for a zero-fill choice: 'None' (returns length), '×2' / '×4' / '×8' (or the ASCII 'x2'…), or 'Next pow₂' (the smallest power of two ≥ length). Feed the result to numpy.fft.fft(signal, n).
n = sigproc.zerofill_length(len(signal), '×4')
spectrum = np.fft.fft(signal, n)
freq = np.fft.fftfreq(n, dt)
echo_center()¶
Returns the index of the echo centre in a 1D magnitude envelope. Pass an offset-invariant envelope such as sqrt(I**2 + Q**2) so the carrier modulation from a field/frequency offset has already cancelled and only the echo shape remains — then the centre is the envelope peak, refined by a local centre-of-mass and rounded to the nearest sample.
window is the half-width (in points) of the centre-of-mass window around the peak. With window <= 0 (default) it is sized automatically from the crest width: walk out from the peak until the envelope drops below 70 % of the peak height, then take the narrower of the two sides. Measuring from the crest (rather than a baseline-relative half-maximum) keeps the result on the peak even when the pre-echo baseline is elevated — there a half-maximum can sit at the baseline level, the window blows up, and a slow FID decay drags the centre-of-mass far past the true peak. A positive window forces that exact half-width.
This is used to start an FFT "from the centre of the echo": find k, drop the first k points, and the dead-time first-order phase ramp disappears.
Signal_Processing()¶
Creates the helper object exposing the methods below.
savitzky_golay()¶
Savitzky–Golay smoothing (requires scipy). window must be odd and greater than order; it is auto-corrected (forced odd, clamped to the data length) if not. Raises RuntimeError when scipy is missing.
moving_average()¶
Centred moving-average smoothing; edges are padded by reflection so the output has the same length as y. NumPy-only.
baseline_poly()¶
Fits a polynomial of the given order and subtracts it from the full curve. region selects which points the polynomial is fitted to, so the baseline can be estimated from signal-free regions (e.g. the trace tails):
region |
Points used for the fit |
|---|---|
'all' |
every point (default) |
'first' |
the first npts points |
'last' |
the last npts points |
'ends' |
the first and last npts points |
npts is ignored when region='all' (or when it would select the whole curve).
# remove a linear baseline estimated from the first and last 50 points
y_corr = sp.baseline_poly(x, y, order=1, region='ends', npts=50)
normalize()¶
Normalizes y. mode:
mode |
Result |
|---|---|
'minmax' |
rescaled to [0, 1] |
'max' |
divided by max(|y|) |
'area' |
divided by its absolute area (unit area) |