This my first time using gui in python so sorry if my code is not pretty.
What I am doing is showing three signals of human body generated by the neurokit2 library (ecg, emg,rsp). I succeeded in showing the signal as it progress with time using matplotlib animation (it has a lot of flaws but I think I can fix them if I searched long enough). What I am truly struggling with for days now is that I need to show a spectrogram of the three signals (not animated though just a static graph).
But each time I try to show the spectrogram, it interferes with the plot of the animation producing garbage graphs and freezes the program.
So how can I totally separate these two functions from each other and produce different windows for each function?
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()
The funtion wave2 is the function that I want to implement for the signal to produce spectrogram in different plot when I press the 'spec' button

