Most literature about sampling explains the need for anti-alias filters in terms of periodic signals, preventing a periodic signal with frequency greater than half the sampling frequency from appearing as a mirrored low frequency signal.
However I acquire transient signals (not periodic) in my measurements, one-sided exponential pulses which have a very fast (high frequency) component followed by a slow decay (lower frequency). These are wideband signals. Quantities I care about are the timing of the fast edge, the integral of the pulse, and the rate of decay of the pulse. For timing measurements, a constant group delay is fine.
All of these measurements are taken using ADCs, for the equipment we use there is usually an anti-aliasing filter, 2nd order linear phase, with 3db attenuation at half the sampling frequency.
An exponential pulse, with simulated output after applying linear phase AA filters and downsampling is shown here
import numpy as np
from astropy import units as u
from astropy.visualization import quantity_support
quantity_support()
import scipy
import matplotlib.pyplot as plt
def t_range(time_length, n):
return np.linspace(0 * time_length.unit, time_length, n+1)[:-1]
def freq_from_t(t, n=None, unit=u.MHz):
if n is None:
n = len(t)
f = np.fft.rfftfreq(n, t[1]-t[0]).to(unit)
return f
def apply_sample_rate(t, signal, sample_rate, filter_order=2):
if filter_order is None:
signal_filtered = np.copy(signal)
else:
f = freq_from_t(t)
cutoff = sample_rate.to(u.MHz) / 2
f_frac = cutoff / f[-1].to(u.MHz)
sos = scipy.signal.bessel(filter_order, f_frac, output='sos')
signal_filtered = scipy.signal.sosfilt(sos, signal)
# now filter the signal
samp_step_t = (1 / sample_rate).to(t[0].unit)
t_sampled = np.arange(start=t[0].value, stop=t[-1].value, step=samp_step_t.value) * t[0].unit
signal_filtered_sampled = np.interp(t_sampled, t, signal_filtered)
return t_sampled, signal_filtered_sampled
t = t_range(150 * u.ns, 10000)
signal = np.exp(-(t-(15 * u.ns)) / (20 * u.ns))
signal[t < 15 * u.ns] = 0
sampling_freq = 100 * u.MHz
plt.plot(t, signal, label='Original')
plt.plot(*apply_sample_rate(t, signal, sampling_freq, filter_order=None), '-o', label='No AA Filter, Downsampled')
plt.plot(*apply_sample_rate(t, signal, sampling_freq, filter_order=2), '-x', label='AA 2nd Order Bessel, Downsampled')
plt.plot(*apply_sample_rate(t, signal, sampling_freq, filter_order=4), '-+', label='AA 4th Order Bessel, Downsampled')
plt.legend()
My question, is what benefit is an AA filter providing for these short pulses? Is an AA filter necessary at all? I can do my measurements on sampled waveform with no AA filter just fine. I am not considering noise yet, but trying to understand if an AA filter has any benefit in this ideal case.