Having a quick look a the cepstrum.
Reproducing this paper of mine.
In [2]:
import numpy as np
from scipy.fftpack import fft, rfft, irfft, fftfreq, rfftfreq
import scipy.signal
import matplotlib.pyplot as plt
%matplotlib inline
In [3]:
# Create RC series
dt = 0.001 # s, equiv. 1 ms
T = 1.0 # s
thick = 0.040 # s, equiv. 40 ms
rc = 0.3
t = np.linspace(0, T, T/dt)
rcs = np.zeros_like(t)
rcs[1000*(T-thick)/2] = rc
rcs[-1000*(T-thick)/2] = -rc
ax1 = plt.subplot(111)
ax1.plot(t, rcs)
ax1.set_ylim(-0.4, 0.4)
plt.show()
In [4]:
RCS = fft(rcs)
freq = fftfreq(rcs.size, d=dt)
keep = freq>=0 # only positive frequencies
RCS = RCS[keep]
freq = freq[keep]
In [11]:
import matplotlib.gridspec as gridspec
gs = gridspec.GridSpec(1, 2,width_ratios=[1,2])
plt.figure(figsize=(15,5))
ax1 = plt.subplot(gs[0])
ax1.plot(t, rcs)
ax1.set_ylim(-0.4, 0.4)
ax2 = plt.subplot(gs[1])
ax2.plot(freq, np.abs(RCS))
ax2.set_xlim(0,200)
plt.savefig("/home/matt/images/cepstrum.png")
plt.show()
In [5]:
def ricker(f, duration=0.512, dt=0.001):
t = np.linspace(-duration/2, (duration-dt)/2, duration/dt)
y = (1.0 - 2.0*(np.pi**2)*(f**2)*(t**2)) * np.exp(-(np.pi**2)*(f**2)*(t**2))
return t, y
In [6]:
dt = 0.001 # s, equiv. 1 ms
T = 0.256 # s
thick = 0.023 # s, equiv. 23 ms
rc = 0.3
t = np.linspace(0, T, T/dt)
rcs = np.zeros_like(t)
rcs[1000*(T-thick)/2] = rc
rcs[-1000*(T-thick)/2] = -rc
tw, w = ricker(f=43., length=0.064, dt=dt)
s = np.convolve(rcs, w, mode='same')
ax1 = plt.subplot(111)
ax1.plot(t, s)
ax1.set_ylim(-0.4, 0.4)
plt.show()
In [7]:
plt.plot(tw,w)
Out[7]:
In [8]:
S = fft(s)
freq = fftfreq(s.size, d=dt)
keep = freq>=0 # only positive frequencies
Sk = S[keep]
freqk = freq[keep]
In [9]:
plt.figure(figsize=(15,5))
ax1 = plt.subplot(111)
ax1.plot(freqk, np.abs(Sk))
ax1.set_xlim(0, 250)
plt.show()
In [10]:
freqk = freqk[:]
Sk = np.abs(Sk)
In [11]:
Q = fft(Sk)
quef = fftfreq(Sk.size, d=freqk[1]-freqk[0])
keep = quef>=0 # only positive frequencies
Qk = Q[keep]
quefk = quef[keep]
In [12]:
quefk
Out[12]:
In [13]:
Qk[:15]
Out[13]:
In [14]:
plt.figure(figsize=(15,5))
ax1 = plt.subplot(111)
ax1.plot(quefk, np.abs(Qk))
plt.show()
In [29]:
import agilegeo.wavelet as ag
In [76]:
dt = 0.001 # s, equiv. 1 ms
T = 0.256 # s
thick = 0.021 # s, equiv. 21 ms
rc = 0.3
# RC SERIES
t = np.linspace(0, T, T/dt)
rcs = np.zeros_like(t)
rcs[1000*(T-3*thick)/2] = rc
rcs[-1000*(T-3*thick)/2] = -rc
rcs[1000*(T-2*thick)/2] = -rc
rcs[-1000*(T-2*thick)/2] = rc
rcs[1000*(T-thick)/2] = rc
rcs[-1000*(T-thick)/2] = -rc
# WAVELET
duration = 0.256
f = f=[10,16,64,80]
#tw, w = ricker(f=32., duration=0.128, dt=dt)
w = ag.ormsby(f=f, duration=duration, dt=dt)
tw = np.linspace(-duration/2, (duration-dt)/2, duration/dt)
# CONVOLVE
s = np.convolve(rcs, w, mode='same')
# Plot it
plt.figure(figsize=(20,3))
ax1 = plt.subplot(131)
ax1.plot(tw, w)
ax1.set_ylim(-0.5, 1.1)
ax1 = plt.subplot(132)
ax1.plot(t, rcs)
ax1.set_xlim(0, 0.256)
ax1.set_ylim(-0.4, 0.4)
ax1 = plt.subplot(133)
ax1.plot(t, s)
ax1.set_xlim(0, 0.256)
ax1.set_ylim(-0.4, 0.4)
plt.show()
In [70]:
W = fft(w)
freqw = fftfreq(w.size, d=dt)
RCS = fft(rcs)
S = fft(s)
freq = fftfreq(s.size, d=dt)
keep = freq>=0
keepw = freqw>=0
Wk = W[keepw]
freqwk = freqw[keepw]
RCSk = RCS[keep]
Sk = S[keep]
freqk = freq[keep]
plt.figure(figsize=(20,3))
ax1 = plt.subplot(131)
ax1.plot(freqwk, np.abs(Wk))
ax1.set_xlim(0,200)
ax2 = plt.subplot(132)
ax2.plot(freqk, np.abs(RCSk))
ax2.set_xlim(0,200)
ax3 = plt.subplot(133)
ax3.plot(freqk, np.abs(Sk))
ax3.set_xlim(0, 200)
plt.show()
In [71]:
Wk = np.abs(Wk)
RCSk = np.abs(RCSk)
Sk = np.abs(Sk)
Qw = fft(Wk)
Qr = fft(RCSk)
Qs = fft(Sk)
quefw = fftfreq(Wk.size, d=freqwk[1]-freqwk[0])
quefr = fftfreq(RCSk.size, d=freqk[1]-freqk[0])
quefs = fftfreq(Sk.size, d=freqk[1]-freqk[0])
keepw = quefw>=0 # only positive frequencies
Qwk = Qw[keepw]
quefwk = quefw[keepw]
keep = quefr>=0 # only positive frequencies
Qrk = Qr[keep]
Qsk = Qs[keep]
quefk = quef[keep]
plt.figure(figsize=(15,3))
ax1 = plt.subplot(131)
ax1.plot(quefwk, np.abs(Qwk))
ax2 = plt.subplot(132)
ax2.plot(quefk, np.abs(Qrk))
ax3 = plt.subplot(133)
ax3.plot(quefk, np.abs(Qsk))
plt.show()
This does not quite look right... I wonder if I went wrong somewhere. It looks much cleaner than my effort in Excel. But the first cepstral peak should be at about 21 ms (given this thickness) — and it's actually appearing at double that, roughly.
In [ ]: