forked from scivision/signal_subspace
-
Notifications
You must be signed in to change notification settings - Fork 0
/
BasicEspritExample.py
executable file
·93 lines (70 loc) · 2.56 KB
/
BasicEspritExample.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#!/usr/bin/env python3
import numpy as np
from scipy.signal import periodogram, remez, freqz, lfilter
from time import time
from matplotlib.pyplot import subplots, show
import subspace
from signal_subspace.filter import fircirc
fs = 48e3
F = 12345.6 # arbitrary
Ntone = 2
M = 10 # arbitrary, # of lags for autocovariance estimate
L = 64
def main():
t = np.arange(0, 0.01, 1/fs)
# %% noisy sinusoid
xc = np.exp(1j*2*np.pi*F*t) + 0.01*(np.random.randn(t.size) + 1j*np.random.randn(t.size))
xr = np.cos(2*np.pi*F*t) + 0.01*np.random.randn(t.size)
# %% estimate sinusoid frequency
festc, sigmac = subspace.subspace.esprit_c(xc, Ntone//2, M, fs)
print('complex')
print(festc)
print(sigmac)
# %% real
# design filter coeff (offline, one-time)
b = remez(L, [0, 0.1, 0.15, 0.35, 0.4, 0.5], [0, 1, 0])
tic = time()
yrpy = lfilter(b, 1, xr)
tscipy = time()-tic
tic = time()
yrfort = subspace.filters.fircircfilter(xr.astype(np.float32), b)[0]
tfort = time()-tic
np.testing.assert_allclose(yrfort, yrpy, rtol=1e-4) # single prec vs double prec
tic = time()
yr = fircirc(b, xr)
print('{:.6f} sec. using circular buffer FIR filter'.format(time()-tic))
np.testing.assert_allclose(yr, yrpy)
# %% estimations
festr, sigmar = subspace.subspace.esprit_r(yr, Ntone, M, fs)
print('real')
print(festr)
print(sigmar)
fg, axs = subplots(2, 4, sharey=False)
plotperiodogram(t, xr, fs, axs[:, 0], 'noisy input signal X')
axs[0, 0].set_ylabel('amplitude [dB]')
axs[1, 0].set_ylabel('amplitude')
plotperiodogram(t, yrpy, fs, axs[:, 1], 'Scipy lfilter() signal, {:.3f} ms'.format(tscipy*1000))
plotperiodogram(t, yrfort, fs, axs[:, 2], 'Fortran filtered signal, {:.3f} ms'.format(tfort*1000))
for a in axs[0, :]:
a.set_xlabel('frequency [Hz]')
a.autoscale(True, axis='x', tight=True)
a.set_ylim(-100, -20)
freq, response = freqz(b)
axs[0, -1].plot(freq*fs/(2*np.pi), 10*np.log10(abs(response)))
axs[0, -1].set_title(f'filter response L={L}')
axs[0, -1].set_ylim(-40, 2)
impulse = np.repeat(0., L)
impulse[0] = 1.
response = lfilter(b, 1, impulse)
axs[1, -1].plot(response)
axs[1, -1].set_xlabel('sample number')
show()
def plotperiodogram(t: np.ndarray, x: np.ndarray, fs: int, ax, ttxt):
fax, Pxx = periodogram(x, fs, 'hanning')
ax[0].plot(fax, 10*np.log10(abs(Pxx)))
ax[0].set_title(ttxt)
ax[1].plot(t, x)
ax[1].set_ylim(-1, 1)
ax[1].set_xlabel('time [sec.]')
if __name__ == "__main__":
main()