def plot_ratios(in_wave, out_wave): # compare filters for cumsum and integration diff_window = np.array([1.0, -1.0]) padded = thinkdsp.zero_pad(diff_window, len(in_wave)) diff_wave = thinkdsp.Wave(padded, framerate=in_wave.framerate) diff_filter = diff_wave.make_spectrum() cumsum_filter = diff_filter.copy() cumsum_filter.hs = 1 / cumsum_filter.hs cumsum_filter.plot(label='cumsum filter', color=GRAY, linewidth=7) integ_filter = cumsum_filter.copy() integ_filter.hs = integ_filter.framerate / (PI2 * 1j * integ_filter.fs) integ_filter.plot(label='integral filter') thinkplot.config(xlim=[0, integ_filter.max_freq], yscale='log', legend=True) thinkplot.save('diff_int8') # compare cumsum filter to actual ratios cumsum_filter.plot(label='cumsum filter', color=GRAY, linewidth=7) in_spectrum = in_wave.make_spectrum() out_spectrum = out_wave.make_spectrum() ratio_spectrum = out_spectrum.ratio(in_spectrum, thresh=1) ratio_spectrum.plot(label='ratio', style='.', markersize=4) thinkplot.config(xlabel='Frequency (Hz)', ylabel='Amplitude ratio', xlim=[0, integ_filter.max_freq], yscale='log', legend=True) thinkplot.save('diff_int9')
def fft_autocorr(signal): N = len(signal) signal = thinkdsp.zero_pad(signal, 2*N) window = np.flipud(signal) corrs = fft_convolve(signal, window) corrs = np.roll(corrs, N//2+1)[:N] return corrs
def fft_autocorr(signal): """Computes the autocorrelation function using FFT. """ N = len(signal) signal = thinkdsp.zero_pad(signal, 2*N) window = np.flipud(signal) corrs = fft_convolve(signal, window) corrs = np.roll(corrs, N//2+1)[:N] return corrs
def make_filter(window, wave): """Computes the filter that corresponds to a window. window: NumPy array wave: wave used to choose the length and framerate returns: new Spectrum """ padded = thinkdsp.zero_pad(window, len(wave)) window_wave = thinkdsp.Wave(padded, framerate=wave.framerate) window_spectrum = window_wave.make_spectrum() return window_spectrum
def plot_diff_filters(wave): window1 = np.array([1, -1]) window2 = np.array([-1, 4, -3]) / 2.0 window3 = np.array([2, -9, 18, -11]) / 6.0 window4 = np.array([-3, 16, -36, 48, -25]) / 12.0 window5 = np.array([12, -75, 200, -300, 300, -137]) / 60.0 thinkplot.preplot(5) for i, window in enumerate([window1, window2, window3, window4, window5]): padded = thinkdsp.zero_pad(window, len(wave)) fft_window = np.fft.rfft(padded) n = len(fft_window) thinkplot.plot(abs(fft_window)[:], label=i + 1) thinkplot.show()
def plot_diff_filters(wave): window1 = np.array([1, -1]) window2 = np.array([-1, 4, -3]) / 2.0 window3 = np.array([2, -9, 18, -11]) / 6.0 window4 = np.array([-3, 16, -36, 48, -25]) / 12.0 window5 = np.array([12, -75, 200, -300, 300, -137]) / 60.0 thinkplot.preplot(5) for i, window in enumerate([window1, window2, window3, window4, window5]): padded = thinkdsp.zero_pad(window, len(wave)) fft_window = np.fft.rfft(padded) n = len(fft_window) thinkplot.plot(abs(fft_window)[:], label=i+1) thinkplot.show()
def plot_gaussian(): """Makes a plot showing the effect of convolution with a boxcar window. """ # start with a square signal signal = thinkdsp.SquareSignal(freq=440) wave = signal.make_wave(duration=1, framerate=44100) spectrum = wave.make_spectrum() # and a boxcar window boxcar = np.ones(11) boxcar /= sum(boxcar) # and a gaussian window gaussian = scipy.signal.gaussian(M=11, std=2) gaussian /= sum(gaussian) thinkplot.preplot(2) thinkplot.plot(boxcar, label='boxcar') thinkplot.plot(gaussian, label='Gaussian') thinkplot.config(xlabel='Index', legend=True) thinkplot.save(root='convolution7') ys = np.convolve(wave.ys, gaussian, mode='same') smooth = thinkdsp.Wave(ys, framerate=wave.framerate) spectrum2 = smooth.make_spectrum() # plot the ratio of the original and smoothed spectrum amps = spectrum.amps amps2 = spectrum2.amps ratio = amps2 / amps ratio[amps<560] = 0 # plot the same ratio along with the FFT of the window padded = thinkdsp.zero_pad(gaussian, len(wave)) dft_gaussian = np.fft.rfft(padded) thinkplot.plot(abs(dft_gaussian), color=GRAY, label='Gaussian filter') thinkplot.plot(ratio, label='amplitude ratio') thinkplot.config(xlabel='Frequency (Hz)', ylabel='Amplitude ratio', xlim=[0, 22050]) thinkplot.save(root='convolution8')
def plot_fft_convolve(): """Makes a plot showing that FFT-based convolution works. """ names = ['date', 'open', 'high', 'low', 'close', 'volume'] df = pd.read_csv('fb.csv', header=0, names=names, parse_dates=[0]) close = df.close.values[::-1] # compute a 30-day average using np.convolve window = scipy.signal.gaussian(M=30, std=6) window /= window.sum() smoothed = np.convolve(close, window, mode='valid') # compute the same thing using fft_convolve N = len(close) padded = thinkdsp.zero_pad(window, N) M = len(window) smoothed4 = fft_convolve(close, padded)[M-1:] # check for the biggest difference diff = smoothed - smoothed4 print(max(abs(diff))) # compute autocorrelation using np.correlate corrs = np.correlate(close, close, mode='same') corrs2 = fft_autocorr(close) # check for the biggest difference diff = corrs - corrs2 print(max(abs(diff))) # plot the results lags = np.arange(N) - N//2 thinkplot.plot(lags, corrs, color=GRAY, linewidth=7, label='np.convolve') thinkplot.plot(lags, corrs2.real, linewidth=2, label='fft_convolve') thinkplot.config(xlabel='Lag', ylabel='Correlation', xlim=[-N//2, N//2]) thinkplot.save(root='convolution9')
def plot_filter(M=11, std=2): signal = thinkdsp.SquareSignal(freq=440) wave = signal.make_wave(duration=1, framerate=44100) spectrum = wave.make_spectrum() gaussian = scipy.signal.gaussian(M=M, std=std) gaussian /= sum(gaussian) high = gaussian.max() thinkplot.preplot(cols=2) thinkplot.plot(gaussian) thinkplot.config(xlabel='Index', ylabel='Window', xlim=[0, len(gaussian) - 1], ylim=[0, 1.1 * high]) ys = np.convolve(wave.ys, gaussian, mode='same') smooth = thinkdsp.Wave(ys, framerate=wave.framerate) spectrum2 = smooth.make_spectrum() # plot the ratio of the original and smoothed spectrum amps = spectrum.amps amps2 = spectrum2.amps ratio = amps2 / amps ratio[amps < 560] = 0 # plot the same ratio along with the FFT of the window padded = thinkdsp.zero_pad(gaussian, len(wave)) dft_gaussian = np.fft.rfft(padded) thinkplot.subplot(2) thinkplot.plot(abs(dft_gaussian), color=GRAY, label='Gaussian filter') thinkplot.plot(ratio, label='amplitude ratio') thinkplot.show(xlabel='Frequency (Hz)', ylabel='Amplitude ratio', xlim=[0, 22050], ylim=[0, 1.05])
def plot_derivative(wave, wave2): # compute the derivative by spectral decomposition spectrum = wave.make_spectrum() spectrum3 = wave.make_spectrum() spectrum3.differentiate() # plot the derivative computed by diff and differentiate wave3 = spectrum3.make_wave() wave2.plot(color='0.7', label='diff') wave3.plot(label='derivative') thinkplot.config(xlabel='days', xlim=[0, 1650], ylabel='dollars', loc='upper left') thinkplot.save(root='diff_int4') # plot the amplitude ratio compared to the diff filter amps = spectrum.amps amps3 = spectrum3.amps ratio3 = amps3 / amps thinkplot.preplot(1) thinkplot.plot(ratio3, label='ratio') window = np.array([1.0, -1.0]) padded = thinkdsp.zero_pad(window, len(wave)) fft_window = np.fft.rfft(padded) thinkplot.plot(abs(fft_window), color='0.7', label='filter') thinkplot.config(xlabel='frequency (1/days)', xlim=[0, 1650/2], ylabel='amplitude ratio', #ylim=[0, 4], loc='upper left') thinkplot.save(root='diff_int5')
def plot_ratios(wave, wave2): spectrum = wave.make_spectrum() spectrum2 = wave2.make_spectrum() amps = spectrum.amps amps2 = spectrum2.amps n = min(len(amps), len(amps2)) ratio = amps2[:n] / amps[:n] thinkplot.preplot(1) thinkplot.plot(ratio, label='ratio') window = np.array([1.0, -1.0]) padded = thinkdsp.zero_pad(window, len(wave)) fft_window = np.fft.rfft(padded) thinkplot.plot(abs(fft_window), color='0.7', label='filter') thinkplot.config(xlabel='Frequency (1/days)', #xlim=[0, spectrum.fs[-1]], ylabel='Amplitude ratio', #ylim=[0, 4], loc='upper left') thinkplot.save(root='diff_int3')
# In[3]: signal = thinkdsp.SquareSignal(freq=440) wave = signal.make_wave(duration=1, framerate=4400) segment = wave.segment(duration=0.01) # In[4]: window = np.ones(11) window /= sum(window) # In[5]: ys = segment.ys N = len(ys) padded = thinkdsp.zero_pad(window, N) # In[6]: prod = padded * ys # In[7]: sum(ys) # In[8]: convolved = np.convolve(ys, window, mode='valid') smooth2 = thinkdsp.Wave(convolved, framerate=wave.framerate) smooth2
def plot_boxcar(): """Makes a plot showing the effect of convolution with a boxcar window. """ # start with a square signal signal = thinkdsp.SquareSignal(freq=440) wave = signal.make_wave(duration=1, framerate=44100) # and a boxcar window window = np.ones(11) window /= sum(window) # select a short segment of the wave segment = wave.segment(duration=0.01) # and pad with window out to the length of the array N = len(segment) padded = thinkdsp.zero_pad(window, N) # compute the first element of the smoothed signal prod = padded * segment.ys print(sum(prod)) # compute the rest of the smoothed signal smoothed = np.zeros(N) rolled = padded for i in range(N): smoothed[i] = sum(rolled * segment.ys) rolled = np.roll(rolled, 1) # plot the results segment.plot(color=GRAY) smooth = thinkdsp.Wave(smoothed, framerate=wave.framerate) smooth.plot() thinkplot.config(xlabel='Time(s)', ylim=[-1.05, 1.05]) thinkplot.save(root='convolution2') # compute the same thing using np.convolve segment.plot(color=GRAY) ys = np.convolve(segment.ys, window, mode='valid') smooth2 = thinkdsp.Wave(ys, framerate=wave.framerate) smooth2.plot() thinkplot.config(xlabel='Time(s)', ylim=[-1.05, 1.05]) thinkplot.save(root='convolution3') # plot the spectrum before and after smoothing spectrum = wave.make_spectrum() spectrum.plot(color=GRAY) ys = np.convolve(wave.ys, window, mode='same') smooth = thinkdsp.Wave(ys, framerate=wave.framerate) spectrum2 = smooth.make_spectrum() spectrum2.plot() thinkplot.config(xlabel='Frequency (Hz)', ylabel='Amplitude', xlim=[0, 22050]) thinkplot.save(root='convolution4') # plot the ratio of the original and smoothed spectrum amps = spectrum.amps amps2 = spectrum2.amps ratio = amps2 / amps ratio[amps<560] = 0 thinkplot.plot(ratio) thinkplot.config(xlabel='Frequency (Hz)', ylabel='Amplitude ratio', xlim=[0, 22050]) thinkplot.save(root='convolution5') # plot the same ratio along with the FFT of the window padded = thinkdsp.zero_pad(window, len(wave)) dft_window = np.fft.rfft(padded) thinkplot.plot(abs(dft_window), color=GRAY, label='DFT(window)') thinkplot.plot(ratio, label='amplitude ratio') thinkplot.config(xlabel='Frequency (Hz)', ylabel='Amplitude ratio', xlim=[0, 22050]) thinkplot.save(root='convolution6')