Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupport News AboutSign UpSign In
| Download
Views: 7339
1
"""This file contains code used in "Think DSP",
2
by Allen B. Downey, available from greenteapress.com
3
4
Copyright 2014 Allen B. Downey
5
License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html
6
"""
7
8
from __future__ import print_function, division
9
10
import thinkdsp
11
import thinkplot
12
import thinkstats2
13
import numpy as np
14
15
PI2 = 2 * np.pi
16
17
18
def make_sine(offset):
19
"""Makes a 440 Hz sine wave with the given phase offset.
20
21
offset: phase offset in radians
22
23
returns: Wave objects
24
"""
25
signal = thinkdsp.SinSignal(freq=440, offset=offset)
26
wave = signal.make_wave(duration=0.5, framerate=10000)
27
return wave
28
29
30
def corrcoef(xs, ys):
31
"""Coefficient of correlation.
32
33
ddof=0 indicates that we should normalize by N, not N-1.
34
35
xs: sequence
36
ys: sequence
37
38
returns: float
39
"""
40
return np.corrcoef(xs, ys)[0, 1]
41
42
43
def plot_sines():
44
"""Makes figures showing correlation of sine waves with offsets.
45
"""
46
wave1 = make_sine(0)
47
wave2 = make_sine(offset=1)
48
49
thinkplot.preplot(2)
50
wave1.segment(duration=0.01).plot(label='wave1')
51
wave2.segment(duration=0.01).plot(label='wave2')
52
53
corr_matrix = np.corrcoef(wave1.ys, wave2.ys, ddof=0)
54
print(corr_matrix)
55
56
thinkplot.save(root='autocorr1',
57
xlabel='Time (s)',
58
ylim=[-1.05, 1.05])
59
60
offsets = np.linspace(0, PI2, 101)
61
62
corrs = []
63
for offset in offsets:
64
wave2 = make_sine(offset)
65
corr = corrcoef(wave1.ys, wave2.ys)
66
corrs.append(corr)
67
68
thinkplot.plot(offsets, corrs)
69
thinkplot.save(root='autocorr2',
70
xlabel='Offset (radians)',
71
ylabel='Correlation',
72
xlim=[0, PI2],
73
ylim=[-1.05, 1.05])
74
75
76
def plot_shifted(wave, offset=0.002, start=0.2):
77
"""Plots two segments of a wave with different start times.
78
79
wave: Wave
80
offset: difference in start time (seconds)
81
start: start time in seconds
82
"""
83
thinkplot.preplot(num=2)
84
segment1 = wave.segment(start=start, duration=0.01)
85
segment1.plot(linewidth=2, alpha=0.8)
86
87
segment2 = wave.segment(start=start-offset, duration=0.01)
88
segment2.shift(offset)
89
segment2.plot(linewidth=2, alpha=0.4)
90
91
corr = segment1.corr(segment2)
92
text = r'$\rho =$ %.2g' % corr
93
thinkplot.text(start+0.0005, -0.8, text)
94
thinkplot.config(xlabel='Time (s)', ylim=[-1.05, 1.05])
95
96
97
def serial_corr(wave, lag=1):
98
"""Computes serial correlation with given lag.
99
100
wave: Wave
101
lag: integer, how much to shift the wave
102
103
returns: float correlation coefficient
104
"""
105
n = len(wave)
106
y1 = wave.ys[lag:]
107
y2 = wave.ys[:n-lag]
108
corr = corrcoef(y1, y2)
109
return corr
110
111
112
def plot_serial_corr():
113
"""Makes a plot showing serial correlation for pink noise.
114
"""
115
np.random.seed(19)
116
117
betas = np.linspace(0, 2, 21)
118
corrs = []
119
120
for beta in betas:
121
signal = thinkdsp.PinkNoise(beta=beta)
122
wave = signal.make_wave(duration=1.0, framerate=11025)
123
corr = serial_corr(wave)
124
corrs.append(corr)
125
126
thinkplot.plot(betas, corrs)
127
thinkplot.config(xlabel=r'Pink noise parameter, $\beta$',
128
ylabel='Serial correlation',
129
ylim=[0, 1.05])
130
thinkplot.save(root='autocorr3')
131
132
133
def autocorr(wave):
134
"""Computes and plots the autocorrelation function.
135
136
wave: Wave
137
"""
138
lags = range(len(wave.ys)//2)
139
corrs = [serial_corr(wave, lag) for lag in lags]
140
return lags, corrs
141
142
143
def plot_pink_autocorr(beta, label):
144
"""Makes a plot showing autocorrelation for pink noise.
145
146
beta: parameter of pink noise
147
label: string label for the plot
148
"""
149
signal = thinkdsp.PinkNoise(beta=beta)
150
wave = signal.make_wave(duration=1.0, framerate=11025)
151
lags, corrs = autocorr(wave)
152
thinkplot.plot(lags, corrs, label=label)
153
154
155
def plot_autocorr():
156
"""Plots autocorrelation for pink noise with different parameters
157
"""
158
np.random.seed(19)
159
thinkplot.preplot(3)
160
161
for beta in [1.7, 1.0, 0.3]:
162
label = r'$\beta$ = %.1f' % beta
163
plot_pink_autocorr(beta, label)
164
165
thinkplot.config(xlabel='Lag',
166
ylabel='Correlation',
167
xlim=[-5, 1000],
168
ylim=[-0.05, 1.05])
169
thinkplot.save(root='autocorr4')
170
171
172
def plot_singing_chirp():
173
"""Makes a spectrogram of the vocal chirp recording.
174
"""
175
wave = thinkdsp.read_wave('28042__bcjordan__voicedownbew.wav')
176
wave.normalize()
177
178
duration = 0.01
179
segment = wave.segment(start=0.2, duration=duration)
180
181
# plot two copies of the wave with a shift
182
plot_shifted(wave, start=0.2, offset=0.0023)
183
thinkplot.save(root='autocorr7')
184
185
# plot the autocorrelation function
186
lags, corrs = autocorr(segment)
187
thinkplot.plot(lags, corrs)
188
thinkplot.config(xlabel='Lag (index)',
189
ylabel='Correlation',
190
ylim=[-1.05, 1.05],
191
xlim=[0, 225])
192
thinkplot.save(root='autocorr8')
193
194
# plot the spectrogram
195
gram = wave.make_spectrogram(seg_length=1024)
196
gram.plot(high=4200)
197
198
thinkplot.config(xlabel='Time (s)',
199
ylabel='Frequency (Hz)',
200
xlim=[0, 1.4],
201
ylim=[0, 4200])
202
thinkplot.save(root='autocorr5')
203
204
# plot the spectrum of one segment
205
spectrum = segment.make_spectrum()
206
spectrum.plot(high=1000)
207
thinkplot.config(xlabel='Frequency (Hz)', ylabel='Amplitude')
208
thinkplot.save(root='autocorr6')
209
210
211
def plot_correlate():
212
"""Plots the autocorrelation function computed by np.
213
"""
214
wave = thinkdsp.read_wave('28042__bcjordan__voicedownbew.wav')
215
wave.normalize()
216
segment = wave.segment(start=0.2, duration=0.01)
217
218
lags, corrs = autocorr(segment)
219
220
N = len(segment)
221
corrs2 = np.correlate(segment.ys, segment.ys, mode='same')
222
lags = np.arange(-N//2, N//2)
223
thinkplot.plot(lags, corrs2)
224
thinkplot.config(xlabel='Lag',
225
ylabel='Correlation',
226
xlim=[-N//2, N//2])
227
thinkplot.save(root='autocorr9')
228
229
230
def main():
231
plot_sines()
232
plot_serial_corr()
233
plot_autocorr()
234
plot_singing_chirp()
235
plot_correlate()
236
237
238
if __name__ == '__main__':
239
main()
240
241