這是我第一次在 python 中使用 gui,如果我的代碼不漂亮,很抱歉。
我正在做的是顯示由 Neurokit2 庫(ecg、emg、rsp)生成的三個人體信號。我使用 matplotlib 影片成功地顯示了信號隨著時間的推移而進展(它有很多缺陷,但我認為如果我搜索足夠長的時間,我可以修復它們)。我現在真正苦苦掙扎的是,我需要顯示三個信號的頻譜圖(雖然只是靜態圖,但不是影片)。
但是每次我嘗試顯示頻譜圖時,它都會干擾影片的情節,產生垃圾圖并凍結程式。
那么如何將這兩個函式完全分開并為每個函式生成不同的視窗呢?
import PySimpleGUI as sg
import matplotlib.pyplot as plt
import neurokit2 as nk
from matplotlib.animation import FuncAnimation
from matplotlib.backends._backend_tk import Toolbar, NavigationToolbar2Tk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
class Toolbar(NavigationToolbar2Tk):
# only display the buttons we need
toolitems = [t for t in NavigationToolbar2Tk.toolitems if
t[0] in ('Home', 'Pan', 'Zoom')]
# t[0] in ('Home', 'Pan', 'Zoom','Save')]
def _init_(self, *args, **kwargs):
super(Toolbar, self)._init_(*args, **kwargs)
def draw_figure(canvas, figure, canvas_toolbar=None):
figure_canvas_agg = FigureCanvasTkAgg(figure, canvas)
figure_canvas_agg.draw_idle()
if canvas_toolbar is not None:
toolbar = Toolbar(figure_canvas_agg, canvas_toolbar)
toolbar.update()
figure_canvas_agg.get_tk_widget().pack(side='top', fill='both', expand=1)
return figure_canvas_agg
def main():
# define the form layout
layout = [[sg.Text('Signal Viewer', size=(40, 1), justification='center', font='Helvetica 20')],
[sg.Canvas(key='controls_cv', pad=((280, 0), 3))],
[sg.Canvas(size=(50, 36), key='-CANVAS-'), sg.Canvas(size=(50, 36), key='-CANVAS0-')],
[sg.Button('ECG', pad=((250, 0), 3)), sg.Button('EMG'), sg.Button('RSP'), sg.Button('Spec')],
[sg.Button('Exit', size=(5, 1), pad=((280, 0), 3), font='Helvetica 14')]]
# create the form and show it without the plot
window = sg.Window('Signal Viewer', layout, finalize=True)
canvas_elem = window['-CANVAS-']
canvas2_e = window['-CANVAS0-']
canvas = canvas_elem.TKCanvas
canvas2 = canvas2_e.TKCanvas
x, y = [], []
fig, ax = plt.subplots()
fig2, ax2 = plt.subplots()
plt.grid(True)
fig_agg = draw_figure(canvas, fig, window.FindElement('controls_cv').TKCanvas)
fig_agg2 = draw_figure(canvas2, fig2)
def wave2(ecg100):
plt.specgram(ecg100, NFFT=64, Fs=256, noverlap=32)
fig_agg2.draw_idle()
def wave_form(ecg100):
def update_time():
t = 0
t_max = len(ecg100)
while t < t_max and t >= 0:
t = ani.direction
yield t
def animate(frame):
st, end = frame / 2, frame 0.5
x.append(ecg100[frame])
plt.cla()
plt.ylim([ecg100.min(), ecg100.max()])
plt.plot(x)
plt.grid()
plt.tight_layout()
ax.set_xlim(st, end)
def on_press(event1):
print(event1.key)
if event1.key.isspace():
if ani.running:
ani.event_source.stop()
else:
ani.event_source.start()
ani.running ^= True
elif event1.key == 'left':
ani.direction = -1
elif event1.key == 'right':
ani.direction = 1
if event1.key in ['left', 'right']:
t = ani.frame_seq.__next__()
animate(t)
fig.canvas.mpl_connect('key_press_event', on_press)
ani = FuncAnimation(plt.gcf(), animate, frames=update_time(), interval=5, repeat=True)
ani.running = True
ani.direction = 1
fig_agg.draw_idle()
while True:
event, values = window.read(timeout=10)
if event in ('Exit', sg.WIN_CLOSED):
exit(69)
elif event in 'ECG':
ecg100 = nk.ecg_simulate(duration=10, noise=0.01, heart_rate=100)
wave_form(ecg100)
wave2(ecg100)
elif event in 'EMG':
ecg100 = nk.emg_simulate(duration=10, sampling_rate=100, burst_number=4)
wave_form(ecg100)
wave2(ecg100)
elif event in 'RSP':
ecg100 = nk.rsp_simulate(duration=30, sampling_rate=50, noise=0.01)
wave_form(ecg100)
wave2(ecg100)
window.close()
if __name__ == '__main__':
main()
函式 wave2 是我想要實作的功能,當我按下“規格”按鈕時,信號會在不同的圖中產生頻譜圖

uj5u.com熱心網友回復:
用戶代碼無法在我的平臺上運行,所以這里只是示例。當然,你可以sg.Canvas在這里使用。
import math
from matplotlib import use as use_agg
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib.pyplot as plt
import PySimpleGUI as sg
def pack_figure(graph, figure):
canvas = FigureCanvasTkAgg(figure, graph.Widget)
plot_widget = canvas.get_tk_widget()
plot_widget.pack(side='top', fill='both', expand=1)
return plot_widget
def plot_figure(index, theta):
fig = plt.figure(index) # Active an existing figure
ax = plt.gca() # Get the current axes
x = [degree for degree in range(1080)]
y = [math.sin((degree theta)/180*math.pi) for degree in range(1080)]
ax.cla() # Clear the current axes
ax.set_title(f"Sensor Data {index}")
ax.set_xlabel("X axis")
ax.set_ylabel("Y axis")
ax.set_xscale('log')
ax.grid()
plt.plot(x, y) # Plot y versus x as lines and/or markers
fig.canvas.draw() # Rendor figure into canvas
# Use Tkinter Agg
use_agg('TkAgg')
layout = [[sg.Graph((640, 480), (0, 0), (640, 480), key='Graph1'), sg.Graph((640, 480), (0, 0), (640, 480), key='Graph2')]]
window = sg.Window('Matplotlib', layout, finalize=True)
# Initial
graph1 = window['Graph1']
graph2 = window['Graph2']
plt.ioff() # Turn the interactive mode off
fig1 = plt.figure(1) # Create a new figure
ax1 = plt.subplot(111) # Add a subplot to the current figure.
fig2 = plt.figure(2) # Create a new figure
ax2 = plt.subplot(111) # Add a subplot to the current figure.
pack_figure(graph1, fig1) # Pack figure under graph
pack_figure(graph2, fig2)
theta1 = 0 # theta for fig1
theta2 = 90 # theta for fig2
plot_figure(1, theta1)
plot_figure(2, theta2)
while True:
event, values = window.read(timeout=10)
if event == sg.WINDOW_CLOSED:
break
elif event == sg.TIMEOUT_EVENT:
theta1 = (theta1 40) % 360
plot_figure(1, theta1)
theta2 = (theta2 40) % 260
plot_figure(2, theta2)
window.close()

轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/326471.html
標籤:Python matplotlib
上一篇:水平條形圖可視化一列
