Skip to content
Snippets Groups Projects
Commit 4f68cfb4 authored by Eric Kooistra's avatar Eric Kooistra
Browse files

Improve frequency axis.

parent 51542266
No related branches found
No related tags found
1 merge request!411Resolve RTSD-271
...@@ -110,7 +110,7 @@ def dtft(coefs, Ndtft=None, zeroCenter=True, fftShift=True): ...@@ -110,7 +110,7 @@ def dtft(coefs, Ndtft=None, zeroCenter=True, fftShift=True):
else use 0 to 1.0. else use 0 to 1.0.
Return: Return:
. h: zero padded coefs . h: zero padded coefs
. f: normalized frequency axis for HF, fs = 1 . fn: normalized frequency axis for HF, fs = 1
. HF: dtft(h), the frequency transfer function of h . HF: dtft(h), the frequency transfer function of h
""" """
c_interpolate = 10 c_interpolate = 10
...@@ -125,12 +125,12 @@ def dtft(coefs, Ndtft=None, zeroCenter=True, fftShift=True): ...@@ -125,12 +125,12 @@ def dtft(coefs, Ndtft=None, zeroCenter=True, fftShift=True):
# DFT # DFT
HF = np.fft.fft(h) HF = np.fft.fft(h)
# Normalized frequency axis, fs = 1, ws = 2 pi # Normalized frequency axis, fs = 1, ws = 2 pi
f = np.arange(0, 1, 1 / Ndtft) # f = 0,pos, neg fn = np.arange(0, 1, 1 / Ndtft) # fn = 0,pos, neg
if fftShift: if fftShift:
# FFT shift to center HF, f = neg, 0,pos # FFT shift to center HF, fn = neg, 0,pos
f = f - 0.5 fn = fn - 0.5
HF = np.roll(HF, Ndtft // 2) HF = np.roll(HF, Ndtft // 2)
return h, f, HF return h, fn, HF
############################################################################### ###############################################################################
...@@ -141,7 +141,8 @@ def estimate_gain_at_frequency(f, HF, freq): ...@@ -141,7 +141,8 @@ def estimate_gain_at_frequency(f, HF, freq):
"""Find gain = abs(HF) at frequency in f that is closest to freq. """Find gain = abs(HF) at frequency in f that is closest to freq.
Input: Input:
. f, HF: frequency axis and spectrum as from dtft() with fftShift=True . f: frequency axis as f = fn * fs for fn from dtft() with fftShift=True
. HF: spectrum as from dtft() with fftShift=True
. freq : frequency to look for in f . freq : frequency to look for in f
Return: Return:
. fIndex: index of frequency in f that is closest to freq . fIndex: index of frequency in f that is closest to freq
...@@ -158,19 +159,26 @@ def estimate_gain_at_frequency(f, HF, freq): ...@@ -158,19 +159,26 @@ def estimate_gain_at_frequency(f, HF, freq):
def estimate_frequency_at_gain(f, HF, gain): def estimate_frequency_at_gain(f, HF, gain):
"""Find positive frequency in f that has gain = abs(HF) closest to gain. """Find positive frequency in f that has gain = abs(HF) closest to gain.
Look only in positive frequencies and from highest frequency to lowest
frequency to avoid band pass ripple gain variation in LPF.
Input: Input:
. f, HF: frequency axis and spectrum as from dtft() with fftShift=True . f: frequency axis as f = fn * fs for fn from dtft() with fftShift=True
. HF: spectrum as from dtft() with fftShift=True
. gain : gain to look for in HF . gain : gain to look for in HF
Return: Return:
. fIndex: index of frequency in f that has abs(HF) closest to gain . fIndex: index of frequency in f that has abs(HF) closest to gain
. fValue: frequency at fIndex . fValue: frequency at fIndex
. fGain : gain = abs(HF) at fIndex . fGain : gain = abs(HF) at fIndex
""" """
# Look only in positive frequencies
pos = len(f[f <= 0]) pos = len(f[f <= 0])
HFpos = HF[pos:] HFpos = HF[pos:]
HFgain = np.abs(HFpos) HFgain = np.abs(HFpos)
HFdiff = np.abs(HFgain - gain) HFdiff = np.abs(HFgain - gain)
fIndex = pos + HFdiff.argmin() # Flip to avoid detections in LPF band pass
HFdiff = np.flipud(HFdiff)
fIndex = pos + len(HFpos) - 1 - HFdiff.argmin()
fValue = f[fIndex] fValue = f[fIndex]
fGain = np.abs(HF[fIndex]) fGain = np.abs(HF[fIndex])
return fIndex, fValue, fGain return fIndex, fValue, fGain
......
...@@ -57,7 +57,7 @@ def plot_time_response(h, title='', color='r', markers=False): ...@@ -57,7 +57,7 @@ def plot_time_response(h, title='', color='r', markers=False):
plt.grid(True) plt.grid(True)
def plot_iir_filter_analysis(b, a, fs=1, whole=False, Ntime=100, step=False, log=False, show=[]): def plot_iir_filter_analysis(b, a, fs=1.0, whole=False, Ntime=100, step=False, log=False, show=[]):
"""Plot and print iir filter analysis results. """Plot and print iir filter analysis results.
Input: Input:
...@@ -137,25 +137,22 @@ def plot_iir_filter_analysis(b, a, fs=1, whole=False, Ntime=100, step=False, log ...@@ -137,25 +137,22 @@ def plot_iir_filter_analysis(b, a, fs=1, whole=False, Ntime=100, step=False, log
return z, p, k return z, p, k
def plot_spectra(f, HF, fs=1.0, fLim=None, dbLim=None): def plot_spectra(fn, HF, fs=1.0, fLim=None, dbLim=None):
"""Plot spectra for power, magnitude, phase, real, imag """Plot spectra for power, magnitude, phase, real, imag
Input: Input:
. f: normalized frequency axis for HF (fs = 1) . fn: normalized frequency axis for HF (fs = 1)
. HF: spectrum, e.g. frequency transfer function HF = DTFT(h) . HF: spectrum, e.g. frequency transfer function HF = DTFT(h)
. fs: sample frequency in Hz, scale f by fs, fs >= 1 . fs: sample frequency in Hz
""" """
Hmag = np.abs(HF) Hmag = np.abs(HF)
Hphs = np.unwrap(np.angle(HF)) Hphs = np.unwrap(np.angle(HF))
Hpow_dB = pow_db(HF) # power response Hpow_dB = pow_db(HF) # power response
fn = f * fs f = fn * fs # scale fn by fs
if fs > 1: flabel = 'Frequency [fs = %f]' % fs
flabel = 'Frequency [fs / %d]' % fs
else:
flabel = 'Frequency [fs]'
plt.figure(1) plt.figure(1)
plt.plot(fn, Hpow_dB) plt.plot(f, Hpow_dB)
plt.title('Power spectrum') plt.title('Power spectrum')
plt.ylabel('Power [dB]') plt.ylabel('Power [dB]')
plt.xlabel(flabel) plt.xlabel(flabel)
...@@ -166,8 +163,8 @@ def plot_spectra(f, HF, fs=1.0, fLim=None, dbLim=None): ...@@ -166,8 +163,8 @@ def plot_spectra(f, HF, fs=1.0, fLim=None, dbLim=None):
plt.grid(True) plt.grid(True)
plt.figure(2) plt.figure(2)
plt.plot(fn, HF.real, 'r') plt.plot(f, HF.real, 'r')
plt.plot(fn, HF.imag, 'g') plt.plot(f, HF.imag, 'g')
plt.title('Complex voltage spectrum') plt.title('Complex voltage spectrum')
plt.ylabel('Voltage') plt.ylabel('Voltage')
plt.xlabel(flabel) plt.xlabel(flabel)
...@@ -177,7 +174,7 @@ def plot_spectra(f, HF, fs=1.0, fLim=None, dbLim=None): ...@@ -177,7 +174,7 @@ def plot_spectra(f, HF, fs=1.0, fLim=None, dbLim=None):
plt.grid(True) plt.grid(True)
plt.figure(3) plt.figure(3)
plt.plot(fn, Hmag) plt.plot(f, Hmag)
plt.title('Magnitude spectrum') # = amplitude plt.title('Magnitude spectrum') # = amplitude
plt.ylabel('Voltage') plt.ylabel('Voltage')
plt.xlabel(flabel) plt.xlabel(flabel)
...@@ -186,7 +183,7 @@ def plot_spectra(f, HF, fs=1.0, fLim=None, dbLim=None): ...@@ -186,7 +183,7 @@ def plot_spectra(f, HF, fs=1.0, fLim=None, dbLim=None):
plt.grid(True) plt.grid(True)
plt.figure(4) plt.figure(4)
plt.plot(fn, Hphs) plt.plot(f, Hphs)
plt.title('Phase spectrum (note -1: pi = -pi)') plt.title('Phase spectrum (note -1: pi = -pi)')
plt.ylabel('Phase [rad]') plt.ylabel('Phase [rad]')
plt.xlabel(flabel) plt.xlabel(flabel)
...@@ -195,18 +192,19 @@ def plot_spectra(f, HF, fs=1.0, fLim=None, dbLim=None): ...@@ -195,18 +192,19 @@ def plot_spectra(f, HF, fs=1.0, fLim=None, dbLim=None):
plt.grid(True) plt.grid(True)
def plot_power_spectrum(f, HF, fmt='r', fs=1.0, fLim=None, dbLim=None): def plot_power_spectrum(fn, HF, fmt='r', fs=1.0, fLim=None, dbLim=None):
"""Plot power spectrum """Plot power spectrum
Input: Input:
. f: normalized frequency axis for HF (fs = 1) . fn: normalized frequency axis for HF (fs = 1)
. HF: spectrum, e.g. frequency transfer function HF = DTFT(h) . HF: spectrum, e.g. frequency transfer function HF = DTFT(h)
. fmt: curve format string . fmt: curve format string
. fs: sample frequency in Hz, scale f by fs, fs >= 1 . fs: sample frequency in Hz
""" """
f = fn * fs # scale fn by fs
flabel = 'Frequency [fs = %f]' % fs flabel = 'Frequency [fs = %f]' % fs
plt.plot(f * fs, pow_db(HF), fmt) plt.plot(f, pow_db(HF), fmt)
plt.title('Power spectrum') plt.title('Power spectrum')
plt.ylabel('Power [dB]') plt.ylabel('Power [dB]')
plt.xlabel(flabel) plt.xlabel(flabel)
...@@ -221,11 +219,12 @@ def plot_magnitude_spectrum(f, HF, fmt='r', fs=1.0, fLim=None, voltLim=None): ...@@ -221,11 +219,12 @@ def plot_magnitude_spectrum(f, HF, fmt='r', fs=1.0, fLim=None, voltLim=None):
"""Plot magnitude (= voltage) spectrum """Plot magnitude (= voltage) spectrum
Input: Input:
. f: normalized frequency axis for HF (fs = 1) . fn: normalized frequency axis for HF (fs = 1)
. HF: spectrum, e.g. frequency transfer function HF = DTFT(h) . HF: spectrum, e.g. frequency transfer function HF = DTFT(h)
. fmt: curve format string . fmt: curve format string
. fs: sample frequency in Hz, scale f by fs, fs >= 1 . fs: sample frequency in Hz
""" """
f = fn * fs # scale fn by fs
flabel = 'Frequency [fs = %f]' % fs flabel = 'Frequency [fs = %f]' % fs
plt.plot(f * fs, np.abs(HF), fmt) plt.plot(f * fs, np.abs(HF), fmt)
...@@ -239,28 +238,27 @@ def plot_magnitude_spectrum(f, HF, fmt='r', fs=1.0, fLim=None, voltLim=None): ...@@ -239,28 +238,27 @@ def plot_magnitude_spectrum(f, HF, fmt='r', fs=1.0, fLim=None, voltLim=None):
plt.grid(True) plt.grid(True)
def plot_two_power_spectra(f1, HF1, name1, f2, HF2, name2, fs=1.0, fLim=None, dbLim=None, showRoll=False): def plot_two_power_spectra(fn1, HF1, name1, fn2, HF2, name2, fs=1.0, fLim=None, dbLim=None, showRoll=False):
"""Plot two power spectra in same plot for comparison """Plot two power spectra in same plot for comparison
Input: Input:
. f1,f2: normalized frequency axis for HF1, HF2 (fs = 1) . fn1,fn2: normalized frequency axis for HF1, HF2 (fs = 1)
. HF1, HF2: spectrum, e.g. frequency transfer function HF = DTFT(h) . HF1, HF2: spectrum, e.g. frequency transfer function HF = DTFT(h)
. fs: sample frequency in Hz, scale f by fs, fs >= 1 . fs: sample frequency in Hz
""" """
if fs > 1: f1 = fn1 * fs # scale fn1 by fs
flabel = 'Frequency [fs / %d]' % fs f2 = fn2 * fs # scale fn1 by fs
else: flabel = 'Frequency [fs = %f]' % fs
flabel = 'Frequency [fs]'
if showRoll: if showRoll:
plt.plot(f1 * fs, pow_db(HF1), 'r', plt.plot(f1, pow_db(HF1), 'r',
f1 * fs, np.roll(pow_db(HF1), len(f1) // 2), 'r--', f1, np.roll(pow_db(HF1), len(f1) // 2), 'r--',
f2 * fs, pow_db(HF2), 'b', f2, pow_db(HF2), 'b',
f2 * fs, np.roll(pow_db(HF2), len(f2) // 2), 'b--') f2, np.roll(pow_db(HF2), len(f2) // 2), 'b--')
plt.legend([name1, '', name2, '']) plt.legend([name1, '', name2, ''])
else: else:
plt.plot(f1 * fs, pow_db(HF1), 'r', plt.plot(f1, pow_db(HF1), 'r',
f2 * fs, pow_db(HF2), 'b') f2, pow_db(HF2), 'b')
plt.legend([name1, name2]) plt.legend([name1, name2])
plt.title('Power spectrum') plt.title('Power spectrum')
plt.ylabel('Power [dB]') plt.ylabel('Power [dB]')
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment