我正在尝试在Jupyter笔记本中绘制Python stem
图。
情节是这样的:
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
from scipy import fftpack
f = 10
f_s = 100
t = np.linspace(0, 2, 2 * f_s, endpoint=False)
x = np.sin(f * 2 * np.pi * t)
X = fftpack.fft(x)
freqs = fftpack.fftfreq(len(x)) * f_s
fig, ax = plt.subplots()
ax.stem(freqs, np.abs(X))
ax.set_xlabel('Frecuency [Hz]')
ax.set_ylabel('Spectrum')
ax.set_xlim(-f_s / 2, f_s / 2)
ax.set_ylim(-5, 110);
我想像本文Jupyter Notebook: interactive plot with widgets 一样添加一个滑块。 这篇文章中的解决方案
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
from scipy import fftpack
from ipywidgets import *
f = 10
f_s = 100
t = np.linspace(0, 2, 2 * f_s, endpoint=False)
x = np.sin(f * 2 * np.pi * t)
X = fftpack.fft(x)
freqs = fftpack.fftfreq(len(x)) * f_s
fig, ax = plt.subplots()
line, = ax.stem(freqs, np.abs(X))
ax.set_xlabel('Frecuency [Hz]')
ax.set_ylabel('Spectrum')
ax.set_xlim(-f_s / 2, f_s / 2)
ax.set_ylim(-5, 110);
def update(f_s=100):
line.set_ydata(fftpack.fftfreq(len(x)) * f_s)
ax.set_xlim(-f_s / 2, f_s / 2)
fig.canvas.draw()
interact(update);
返回一个错误:
ValueError Traceback (most recent call last)
<ipython-input-18-fd1aaf0ca96d> in <module>()
7
8 fig, ax = plt.subplots()
----> 9 line, = ax.stem(freqs, np.abs(X))
10 ax.set_xlabel('Frecuency [Hz]')
11 ax.set_ylabel('Spectrum')
ValueError: too many values to unpack (expected 1)
答案 0 :(得分:1)
我认为您要展示的内容最重要。如果更改频率,则可能还需要重新计算频谱。因此,我们首先使用线图对其进行更正。
%matplotlib notebook
import matplotlib.pyplot as plt
import numpy as np
from scipy import fftpack
from ipywidgets import *
def func(f_s):
t = np.linspace(0, 2, 2 * f_s, endpoint=False)
x = np.sin(f * 2 * np.pi * t)
X = fftpack.fft(x)
freqs = fftpack.fftfreq(len(x)) * f_s
return freqs, np.abs(X)
f = 10
f_s = 100
fig, ax = plt.subplots()
line, = ax.plot(*func(f_s), marker="o")
ax.set_xlabel('Frecuency [Hz]')
ax.set_ylabel('Spectrum')
ax.set_xlim(-f_s / 2, f_s / 2)
ax.set_ylim(-5, 110);
def update(f_s=100):
if f_s > 0:
x, y = func(f_s)
line.set_data(x, y)
ax.set_xlim(-f_s / 2, f_s / 2)
ax.set_ylim(None, 1.1*y.max())
fig.canvas.draw()
interact(update);
现在stem
绘图的问题在于,它将创建许多需要更新的行。因此,我宁愿建议使用LineCollection
。
%matplotlib notebook
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
import numpy as np
from scipy import fftpack
from ipywidgets import *
def func(f_s):
t = np.linspace(0, 2, 2 * f_s, endpoint=False)
x = np.sin(f * 2 * np.pi * t)
X = fftpack.fft(x)
freqs = fftpack.fftfreq(len(x)) * f_s
return freqs, np.abs(X)
f = 10
f_s = 100
fig, ax = plt.subplots()
x,y = func(f_s)
markers, = ax.plot(x,y, ls="none", marker="o")
baseline = ax.axhline(0, color="crimson")
verts=np.c_[x, np.zeros_like(x), x, y].reshape(len(x),2,2)
col = LineCollection(verts)
ax.add_collection(col)
ax.set_xlabel('Frecuency [Hz]')
ax.set_ylabel('Spectrum')
ax.set_xlim(-f_s / 2, f_s / 2)
ax.set_ylim(None, 110);
def update(f_s=100):
if f_s > 0:
x, y = func(f_s)
markers.set_data(x, y)
verts=np.c_[x, np.zeros_like(x), x, y].reshape(len(x),2,2)
col.set_segments(verts)
ax.set_xlim(-f_s / 2, f_s / 2)
ax.set_ylim(None, 1.1*y.max())
fig.canvas.draw_idle()
interact(update);