Can interact only with the last graph - python

I'm practicing tkinter and matplotlib.
I wrote this piece of code which creates an entered number of frames and in each frame a different plot is embedded. I can then go from plot to plot by switching between the created frames and turn a drawing mode on. What the drawing mode do is enable me to click on the plot and create a horizontal line on it.
But when I turn drawing mode on I can only interact with the last graph.
Any ideas why this is happening?
The piece of code:
from tkinter import *
from random import *
import matplotlib
matplotlib.use('TkAgg')
from matplotlib import pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
numberOfFrames = eval(input('Number of frames to be crated: '))
x = []
y = []
class app(Tk):
def __init__(self):
Tk.__init__(self)
self.geometry('640x400')
self.frames = []
self.currentPage = 0
def nextpage():
try:
frame = self.frames[self.currentPage+1]
frame.tkraise()
self.currentPage += 1
except:
pass
def backpage():
if self.currentPage == 0:
pass
else:
frame = self.frames[self.currentPage-1]
frame.tkraise()
self.currentPage -= 1
def DrawOn():
def onclick(event):
plt.hlines(event.ydata,event.xdata-0.1,event.xdata+0.1,
colors='r',linestyle='solid')
canvas.show()
fig.canvas.mpl_connect('button_press_event', onclick)
for i in range(numberOfFrames):
frame = Frame(self)
frame.grid(row=0, column=0, sticky="nsew")
self.frames.append(frame)
fig = plt.figure()
for j in range(2):
x.append(randint(1,10))
y.append(randint(1,10))
plt.plot(x,y)
canvas = FigureCanvasTkAgg(fig, self.frames[i])
canvas.get_tk_widget().pack(fill='both', expand=True)
toolbar = NavigationToolbar2TkAgg(canvas, self.frames[i])
toolbar.update()
canvas._tkcanvas.pack(fill='both', expand=True)
label = Label(self.frames[i], text='Page %d'%(i+1))
label.pack()
Next = Button(self.frames[i], text='Next', command = nextpage)
Next.pack(side=LEFT)
Back = Button(self.frames[i], text='Back', command = backpage)
Back.pack(side=LEFT)
Draw = Button(self.frames[i], text='Draw', command = DrawOn)
Draw.pack(side=LEFT)
self.frames[0].tkraise()
run = app()
run.mainloop()

That's the alteration I made to my code. It made possible to interact with all the embedded graphs. I'm not sure if it is the best way to do it, but it seems to work.
from tkinter import *
from random import *
import matplotlib
matplotlib.use('TkAgg')
from matplotlib import pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
numberOfFrames = eval(input('Number of frames to be crated: '))
x = []
y = []
class app(Tk):
def __init__(self):
Tk.__init__(self)
self.geometry('640x400')
self.frames = []
self.currentPage = 0
self.figs = []
self.axeslist = []
self.canvaslist = []
def nextpage():
try:
frame = self.frames[self.currentPage+1]
frame.tkraise()
self.currentPage += 1
except:
pass
def backpage():
if self.currentPage == 0:
pass
else:
frame = self.frames[self.currentPage-1]
frame.tkraise()
self.currentPage -= 1
def DrawOn():
def onclick(event):
self.axeslist[self.currentPage].hlines(event.ydata,event.xdata-0.1,event.xdata+0.1,
colors='r',linestyle='solid')
self.canvaslist[self.currentPage].show()
print(event.xdata,event.ydata)
for i in self.figs:
i.canvas.mpl_connect('button_press_event', onclick)
for i in range(numberOfFrames):
frame = Frame(self)
frame.grid(row=0, column=0, sticky="nsew")
self.frames.append(frame)
fig = plt.figure()
self.figs.append(fig)
ax = self.figs[i].add_subplot(111)
self.axeslist.append(ax)
for j in range(2):
x.append(randint(1,10))
y.append(randint(1,10))
plt.plot(x,y)
canvas1 = FigureCanvasTkAgg(self.figs[i], self.frames[i])
self.canvaslist.append(canvas1)
self.canvaslist[i].get_tk_widget().pack(fill='both', expand=True)
toolbar = NavigationToolbar2TkAgg(self.canvaslist[i], self.frames[i])
toolbar.update()
self.canvaslist[i]._tkcanvas.pack(fill='both', expand=True)
label = Label(self.frames[i], text='Page %d'%(i+1))
label.pack()
Next = Button(self.frames[i], text='Next', command = nextpage)
Next.pack(side=LEFT)
Back = Button(self.frames[i], text='Back', command = backpage)
Back.pack(side=LEFT)
Draw = Button(self.frames[i], text='Draw', command = DrawOn)
Draw.pack(side=LEFT)
self.frames[0].tkraise()
run = app()
run.mainloop()

Related

How to plot an automatic graph using mouse without clicking MATPLOTLIB

I'm looking to plot Data automatically using mouse without clicking From a DZT file.
i Created a program in order to plot data as you can see in this graph:
As you can see in this picture, x axes going from 0 to 3525 ans every x is a signal so i have more than 3500 signals making this graph.
for exemple if i want to see the signal of x=999, it looks like this.
what i want really to do is every time when i pass my mouse without clicking on the graph it should plot it's signal automatically .
i try to use a lot of methods but rally i dont know how to do it.
i'll be grateful for your help
this is my file:
https://www.grosfichiers.com/mvabGETFfna
This is my program:
from tkinter import *
from tkinter import messagebox, filedialog
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import os
from readgssi import readgssi
root = Tk()
root.title("IHM")
root.geometry("1000x800")
Resources_frame = LabelFrame(root, bd=2, relief=GROOVE, text="Conversion Area")
Resources_frame.place(x=5, y=5, width=250, height=80)
lbl_ra = Label(Resources_frame, text="Select your File ")
lbl_ra.grid(row=0, column=0, sticky=W)
lbl_ra = Label(Resources_frame, text="Convert Selected file ")
lbl_ra.grid(row=1, column=0, sticky=W)
NumberOfSimples = ''
DataAScan = ''
Data = ''
xData = ''
xAxes = ''
def ReadDZT():
file_path = filedialog.askopenfilename()
file_name, file_extension = os.path.splitext(file_path)
print(file_extension)
if file_extension == '.DZT':
messagebox.showinfo("INFO", "Your DZT File Has Been Selected Successfully")
hdr, arrs, gps = readgssi.readgssi(infile=file_path, verbose=True)
TimeRange = hdr['rhf_range']
Samples = hdr['rh_nsamp']
X_Axes = np.array(range(0, Samples))
xAxes = X_Axes[2::1]
df = pd.DataFrame(arrs[0])
Data = df.iloc[2::1, 0::1]
fig2 = plt.figure()
plt.plot(xAxes, Data[999])
plt.show()
fig = plt.figure()
plt.imshow(Data, aspect='auto', cmap='bone')
plt.show()
elif file_extension == '.csv':
messagebox.showinfo("INFO", "Your CSV File Has Been Selected Successfully")
df = pd.read_csv(file_path)
NumberOfSimples = df.iloc[2::1, 0]
Data = df.iloc[::1, ::1]
DataAScan = df.iloc[2::1, 999]
fig1 = plt.figure()
plt.plot(NumberOfSimples, DataAScan)
plt.show()
fig2 = plt.figure()
plt.imshow(Data, aspect='auto', cmap='bone')
plt.show()
else:
messagebox.showwarning("WARNING", "You Have Been Selected a Different Format")
# =============Resources Buttons================#
btn_rs = Button(Resources_frame, relief=GROOVE, padx=8, pady=1, text="Browse", command=ReadDZT).grid(row=0,
column=1)
root.mainloop()
As indicated in the previous question Ploting a graph automatically using mouse coordinate (and I think this question should have been an edit of it), the mouse motion can be monitored with plt.connect('motion_notify_event', mouse_move). The slice of Data to be plotted in fig2 simply corresponds to the x-coordinate of the mouse, that is Data[int(event.xdata)] in mouse_move(event).
Therefore, in mouse_move(event), you:
Clear the axis: ax2.clear() (where ax2 is the AxesSubplot object of fig2)
Plot the slice ax2.plot(self.xAxes, self.Data[int(event.xdata)])
Update the figure fig2.canvas.draw_idle()
However, I had issues with using simultaneously the matplotlib figures and the tkinter GUI because of the separate event loops. Therefore I embedded the figures in the tkinter GUI directly (see e.g. https://matplotlib.org/3.4.0/gallery/user_interfaces/embedding_in_tk_sgskip.html).
I also put the graph related code in a class to keep the loaded data in attributes to avoid using global variables.
import tkinter as tk
from tkinter import messagebox, filedialog
import pandas as pd
import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
from matplotlib.figure import Figure
import numpy as np
import os
from readgssi import readgssi
class Graphs(tk.Toplevel):
def __init__(self, master=None, **kw):
tk.Toplevel.__init__(self, master, **kw)
self.rowconfigure(0, weight=1)
self.rowconfigure(2, weight=1)
# data
self.Data = []
self.xData = []
self.xAxes = []
self.line = None
# figure1 : 2D data map
self.fig1 = Figure()
self.ax1 = self.fig1.add_subplot(111)
self.canvas1 = FigureCanvasTkAgg(self.fig1, self)
self.canvas1.draw()
self.canvas1.get_tk_widget().grid(sticky='ewsn')
self.toolbar1 = NavigationToolbar2Tk(self.canvas1, self, pack_toolbar=False)
self.toolbar1.grid(sticky="ew")
# figure 2: slice plot
self.fig2 = Figure()
self.ax2 = self.fig2.add_subplot(111)
self.canvas2 = FigureCanvasTkAgg(self.fig2, self)
self.canvas2.draw()
self.canvas2.get_tk_widget().grid(sticky='ewsn')
self.toolbar2 = NavigationToolbar2Tk(self.canvas2, self, pack_toolbar=False)
self.toolbar2.grid(sticky="ew")
# bind plotting to mouse motion
self.canvas1.mpl_connect('motion_notify_event', self.mouse_move)
def mouse_move(self, event):
x = event.xdata
if len(self.Data) and x is not None: # there is something to plot
self.ax2.clear()
x = int(x)
self.ax2.plot(self.xAxes, self.Data[x])
self.line.set_data([x, x], [len(self.Data), 0])
self.canvas1.draw_idle()
self.canvas2.draw_idle()
def readDZT(self):
file_path = filedialog.askopenfilename()
file_name, file_extension = os.path.splitext(file_path)
if file_extension == '.DZT':
messagebox.showinfo("INFO", "Your DZT File Has Been Selected Successfully")
hdr, arrs, gps = readgssi.readgssi(infile=file_path, verbose=True)
Samples = hdr['rh_nsamp']
X_Axes = np.array(range(0, Samples))
self.xAxes = X_Axes[2::1]
df = pd.DataFrame(arrs[0])
self.Data = df.iloc[2::1, 0::1]
# clear plots
self.ax1.clear()
self.ax2.clear()
# plot slice
self.ax2.plot(self.xAxes, self.Data[999])
self.canvas2.draw_idle()
# plot 2D map
self.ax1.imshow(self.Data, aspect='auto', cmap='bone')
self.line = self.ax1.plot([999, 999], [len(self.Data), 0], 'r')[0]
self.ax1.set_ylim(len(self.Data), 0)
self.canvas1.draw_idle()
else:
messagebox.showwarning("WARNING", "You Have Been Selected a Different Format")
root = tk.Tk()
root.title("IHM")
root.geometry("1000x800")
Resources_frame = tk.LabelFrame(root, bd=2, relief=tk.GROOVE, text="Conversion Area")
Resources_frame.place(x=5, y=5, width=250, height=80)
tk.Label(Resources_frame, text="Select your File ").grid(row=0, column=0, sticky=tk.W)
tk.Label(Resources_frame, text="Convert Selected file ").grid(row=1, column=0, sticky=tk.W)
graphs = Graphs(root)
btn_rs = tk.Button(Resources_frame, relief=tk.GROOVE, padx=8, pady=1, text="Browse",
command=graphs.readDZT).grid(row=0, column=1)
root.mainloop()

how to update curve plot in animation ( tkinter) of python

from the following code, I could update the line by clicking the "replot" button. I have to use both set_data() and also plot a new plot, otherwise the old plot is still here.
However, I want the program automatically to update the curve inside of animate(), I use a 5 secs control to trigger replot() function, but it fails. if I do not use blit=True, just use blit=False, then everything is fine. Then my question is how to update the curve in animation triggered by condition, and also need to keep blit=True?
from multiprocessing import Process
import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
##, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
import matplotlib.animation as animation
from matplotlib import style
import tkinter as tk
from tkinter import ttk
from tkinter import *
import matplotlib.pyplot as plt
import numpy as np
import time
#f = Figure(figsize=(6,6), dpi=100)
f = Figure(figsize=(6,6), dpi=100)
subplot_1 = f.add_subplot(211)
subplot_2 = f.add_subplot(212)
#subplot_1 = f.add_subplot(211)
#subplot_2 = f.add_subplot(212)
a_count = 0
b_count = 0
LARGE_FONT= ("Verdana", 12)
style.use("ggplot")
count_plot = 0
first_replot = 0
start_time = 0
a_t = [1,2,3,4,5]
a_T = np.ones(5)
def replot():
global a_t, count_plot,theory_line,a_T
a_T = np.ones(5)*2
#f.axes[0].clear
#theory_line[0].remove()
theory_line[0].set_data(a_t,a_T)
#theory_line.clear()
#theory_line = subplot_1.plot(a_t,a_T,'g-')
#subplot_1.draw
canvas.draw
def animate(i):
global a_count,b_count,first_replot
time1 = np.random.rand(2, 25)
data = np.random.rand(2, 25)*2
if (time.time() - start_time > 5) and (first_replot == 0):
replot()
first_replot = 1
a = subplot_1.scatter(time1,data,c='blue',s=2)
return a,
class home(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.wm_title(self, "Graph ")
self.geometry("1000x1000")
container = tk.Frame(self)
container.pack(side="top", fill="both", expand = True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
F=Graph
frame=Graph(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(Graph)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
def get_frame(self, frame_class):
return self.frames[frame_class]
##
class Graph(tk.Frame):
def __init__(self, parent, controller):
global canvas
tk.Frame.__init__(self, parent)
label = tk.Label(self, text=" ", font=LARGE_FONT)
label.pack(pady=120,padx=10)
collectbtn=Button(self,text='collect',command=self.clickstart)
collectbtn.place(x=200,y=100)
collectbtn=Button(self,text='replot',command=self.clickreplot)
collectbtn.place(x=280,y=100)
canvas = FigureCanvasTkAgg(f, self)
## canvas.draw()
canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)
canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=True)
def clickstart(self):
global theory_line,start_time
theory_line = subplot_1.plot(a_t,a_T,'c-')
#animate(0)
start_time = time.time()
aniplot_photon = animation.FuncAnimation(f, animate, blit=True,interval=100)
#aniplot_photon = animation.FuncAnimation(f, animate, interval=100)
canvas.draw()
def clickreplot(self):
replot()
canvas.draw()
app = home()
app.mainloop()
Not sure about the programming logic, but I think there maybe at least three issues.
start_time won't be reset if you don't click 'collect', so it won't replot every 5 seconds.
def clickstart(self):
....
start_time = time.time()
aniplot_photon = animation.FuncAnimation(f, animate, blit=True,interval=100)
....
first_replot initially set to 0, after 'collect' clicked and 5 seconds passed, then the value of first_replot will be always 1. It means no more replot in function 'animate'.
canvas.draw at last line of function 'replot', should be canvas.draw().

How to define a choice (symbol) from combobox widget as a (global) variable?

I would like to come directly to the point, so I will firstly just ask all my questions which I have.
In Class Win1 I have a combobox, my question is: Is there a possibility to define the entry/chosen symbol as a variable and is there a possibility to define the variable as global, without having to redefine classes?
This is my second question, which is at the moment less relevant than the first one.
When this code is running, first one window shows up, then a second one and so on. When turning this code into a software/app/..., will the software then also show one window than a second one or will everything be in one window?
import math
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
matplotlib.use('TkAgg')
#------------------------------------------------------------------------------
import tkinter
import tkinter as tk
from tkinter import ttk
import tkinter.font as tkFont
import tkinter.ttk as ttk
from tkinter import *
from tkinter.ttk import Combobox
#------------------------------------------------------------------------------
import numpy as np
#------------------------------------------------------------------------------
import pandas as pd
from pandas import DataFrame
from pandas.compat import StringIO
from pandas_datareader import data as web
#------------------------------------------------------------------------------
import yfinance as yf
#------------------------------------------------------------------------------
from statistics import mean
#------------------------------------------------------------------------------
import requests
#------------------------------------------------------------------------------
import time
from datetime import datetime
from datetime import date
from datetime import timedelta
import calendar
#------------------------------------------------------------------------------
import random
#------------------------------------------------------------------------------
from alpha_vantage.timeseries import TimeSeries
from alpha_vantage.techindicators import TechIndicators
#------------------------------------------------------------------------------
import sys
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)
# Implement the default Matplotlib key bindings.
from matplotlib.backend_bases import key_press_handler
#------------------------------------------------------------------------------
#symbol = 'TSLA'
global_symbol = ""#None
#combobox = ""
def onSymbolSelected(self,event = None):
global global_symbol
global_symbol = self.combobox.get() # this assume combo is a property of Win1
def config_plot():
fig, ax = plt.subplots()
return(fig, ax)
class Win1:
def __init__(self, master):
self.master = master
self.master.geometry("400x400")
self.frame = tk.Frame(self.master)
#symbol = Entry(root, text ='', bd=5)
#userInput1 = StringVar(None)
#self.master = Entry(root, textvariable=userInput1)
#self.master.pack()
SMI = ['ROG.SW','NOVN.SW','NESN.SW','SRAIL.SW','ABB','ADEN.SW','ALC.SW','CSGN.SW','GEBN.SW','GIVN.SW',
'LONN.SW','CFR.SW','SIKA.SW','UHR.SW','SLHN.SW','SREN.SW','SCMN.SW','UBSG.SW','ZURN.SW']
SMI.sort()
NYSE = ['NYSE:MMM','NYSE:AXP','NYSE:AAPL','NYSE:BA','NYSE:CAT','NYSE:CVX','NYSE:CSCO','NYSE:KO','NYSE:DOW','NYSE:XOM',
'NYSE:GS','NYSE:HD','NYSE:IBM','NYSE:INTC','NSYE:JNJ','NYSE:JPM','NYSE:MCD','NYSE:MRK','NYSE:MSFT','NYSE:NKE',
'NYSE:PFE','NYSE:PG','NYSE:RTX','NYSE:TRV','NYSE:UNH','NYSE:VZ','NYSE:V','NYSE:WMT','NYSE:WBA','NYSE:DIS']
NYSE.sort()
DAX = ['ETR:ADS','ETR:ALV','ETR:BAS','ETR:BAYN','ETR:BEI','ETR:BMW','ETR:CON','ETR:1COV','ETR:DAI','ETR:DBK',
'ETR:LHA','ETR:DPW','ETR:DTE','ETR:EOAN','ETR:FRE','ETR:FME','ETR:HEI','ETR:HEN3','ETR:IFX','ETR:MTX',
'ETR:MUV2','ETR:RWE','ETR:SAP','ETR:SIE','ETR:VOW3','ETR:VNA','ETR:WDI']
DAX.sort()
Stockxx = []
Stockxx.sort()
symbol = ['ROG.SW','SMI','NYSE','DAX','Stockxx']
symbol.sort()
#symbol.current()
#root= Tk()
self.combobox = StringVar()
self.combobox = ttk.Combobox(master, values = symbol)
#def onSymbolSelected(self, Event = None):
# global global_symbol
# global_symbol = self.combobox.get()
self.combobox.bind("<<ComboboxSelected>>", onSymbolSelected)#onSymbolSelected)
#cb = ttk.Combobox(master, values = symbol)
#print(var)
# note that this is the StringVar ICUS, not the combobox ICUSTOMER.
#label_var = tk.Label( textvariable= var)
#print(label_var)
#label_ICustVar.grid(row = 3, column = 3)
self.combobox.place(x=100, y=50)
button1 = Button(root, text="Click Here", fg = 'blue', width=20, command = lambda: self.new_window("2", Win2))
button1.pack(side='bottom',padx=15,pady=15)
# this assume combo is a property of Win1
#self.butnew("Hauptfunktionen", "2", Win2)
#self.butnew("Weitere Funktionen", "3", Win3)
self.quit = tk.Button(self.frame, text = f"Close this window", command = self.close_window)
self.quit.pack()
self.frame.pack()
print(symbol,"asfjöasldkjflödas")
print(global_symbol,"ioöbajbo")
def close_window(self):
self.master.destroy()
#def onSymbolSelected(self,event = None):
# global global_symbol
# global_symbol = self.combo.get() # this assume combo is a property of Win1
def butnew(self, text, number, _class):
tk.Button(self.frame, text = text, command= lambda: self.new_window(number, _class)).pack(side='left')
def new_window(self, number, _class):
self.new = tk.Toplevel(self.master)
_class(self.new, number)
class Win2:
def __init__(self, master, number):
self.master = master
self.master.geometry("1080x540")
self.frame = tk.Frame(self.master)
self.frame = Frame(self.master)
self.fig, self.ax = config_plot()
self.graphIndex = 0
self.canvas = FigureCanvasTkAgg(self.fig, self.master)
self.config_window()
self.quit = tk.Button(self.frame, text = f"Close this window", command = self.close_window)
self.quit.pack(side=LEFT)
self.draw_graph_one()
self.butnew("Weitere Funktionen", "3", Win3)
self.frame.pack(expand=YES, fill=BOTH)
def butnew(self, text, number, _class):
tk.Button(self.frame, text = text, command= lambda: self.new_window(number, _class)).pack(side='left')
def new_window(self, number, _class):
self.new = tk.Toplevel(self.master)
_class(self.new, number)
def draw_graph_one(self):
ts = TimeSeries(key='YOUR_API_KEY',output_format='pandas')
data1, meta_data1 = ts.get_monthly(symbol=global_symbol)
df1 = data1['4. close']
self.ax.clear()
self.ax.plot(df1)
self.ax.set(title='Historical Chart')
self.canvas.draw()
#------------------------------------------------------------------------fertig
def draw_graph_two(self):
ts = TimeSeries(key='YOUR_API_KEY',output_format='pandas')
data2, meta_data2 = ts.get_intraday(symbol=global_symbol, interval='1min', outputsize='compact')
df2 = data2['4. close']
self.ax.clear()
self.ax.plot(df2)
self.ax.set(title='Intraday')
self.canvas.draw()
#------------------------------------------------------------------------fertig
def draw_graph_three(self):
ti = TechIndicators(key='YOUR_API_KEY',output_format='pandas')
data3, meta_data3 = ti.get_bbands(symbol=global_symbol, interval='15min', time_period=30)
df3 = data3
ts = TimeSeries(key='YOUR_API_KEY',output_format='pandas')
data2, meta_data2 = ts.get_intraday(symbol=global_symbol, interval='15min', outputsize='full')
df2 = data2['4. close']
self.ax.clear()
self.ax.plot(df2, linestyle='-.')
self.ax.plot(df3)
self.ax.set(title='Bollinger Bands')
self.canvas.draw()
#------------------------------------------------------------------------fertig
def draw_graph_four(self):
ti = TechIndicators(key='YOUR_API_KEY',output_format='pandas')
data44, meta_data44 = ti.get_sma(symbol=global_symbol, interval='30min', time_period=60)
df44 = data44
ts = TimeSeries(key='YOUR_API_KEY',output_format='pandas')
data1, meta_data1 = ts.get_intraday(symbol=global_symbol, interval='30min', outputsize='full')
df1 = data1['4. close']
self.ax.clear()
self.ax.plot(df1)#, color='yellow')
self.ax.plot(df44)#, color='black')
self.ax.set(title='Simple Moving Average')
self.canvas.draw()
#------------------------------------------------------------------------fertig
def draw_graph_five(self):
ts = TimeSeries(key='YOUR_API_KEY',output_format='pandas')
data1, meta_data1 = ts.get_monthly(symbol=global_symbol)#, interval='1min', outputsize='full')
df1 = data1['4. close']
ts = TimeSeries(key='YOUR_API_KEY',output_format='pandas')
dataG, meta_dataG = ts.get_monthly(symbol='UCITS ETF')#, interval='1min', outputsize='full')
dG = dataG['4. close']
self.ax.clear()
self.ax.plot(df1)
self.ax.plot(dG)
self.ax.set(title='Comparision with Global Index')
self.canvas.draw()
#------------------------------------------------------------------------------
def draw_graph_six(self):
ti = TechIndicators(key='YOUR_API_KEY',output_format='pandas')
data23, meta_data23 = ti.get_cci(symbol=global_symbol, interval='30min', time_period=60)
df23 = data23
self.ax.clear()
self.ax.plot(df23)
self.ax.set(title='Commodity Channel Index')
self.canvas.draw()
#------------------------------------------------------------------------fertig
def draw_graph_seven(self):
ti = TechIndicators(key='YOUR_API_KEY',output_format='pandas')
data13, meta_data23 = ti.get_dx(symbol=global_symbol, interval='30min', time_period=60)
df13 = data13
self.ax.clear()
self.ax.plot(df13)
self.ax.set(title='Directional Movement Index')
self.canvas.draw()
#------------------------------------------------------------------------------
def draw_graph_eight(self):
self.ax.clear()
self.ax.plot()
self.ax.set(title='Further Information')
self.canvas.draw()
#------------------------------------------------------------------------------
def draw_graph_nine(self):
self.ax.clear()
self.ax.plot()
self.ax.set(title='Further Information')
self.canvas.draw()
def on_key_press(event):
print("you pressed {}".format(event.key))
key_press_handler(event, self.canvas, toolbar)
def config_window(self):
self.canvas.mpl_connect("key_press_event", self.on_key_press)
toolbar = NavigationToolbar2Tk(self.canvas, self.master)
toolbar.update()
self.canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1)
self.button_switch1 = Button(self.master, text="Historical Chart", command=self.draw_graph_one)
self.button_switch1.pack(side=LEFT)
self.button_switch2 = Button(self.master, text="Intraday", command=self.draw_graph_two)
self.button_switch2.pack(side=LEFT)
self.button_switch3 = Button(self.master, text="Bollinger Bands", command=self.draw_graph_three)
self.button_switch3.pack(side=LEFT)
self.button_switch4 = Button(self.master, text="SMA", command=self.draw_graph_four)
self.button_switch4.pack(side=LEFT)
self.button_switch5 = Button(self.master, text="Comparison with Index", command=self.draw_graph_five)
self.button_switch5.pack(side=LEFT)
self.button_switch6 = Button(self.master, text="CCI", command=self.draw_graph_six)
self.button_switch6.pack(side=LEFT)
self.button_switch7 = Button(self.master, text="DX", command=self.draw_graph_seven)
self.button_switch7.pack(side=LEFT)
self.button_switch8 = Button(self.master, text="Technical Analysis", command=self.draw_graph_eight)
self.button_switch8.pack(side=LEFT)
self.button_switch9 = Button(self.master, text="Technical Analysis", command=self.draw_graph_nine)
self.button_switch9.pack(side=LEFT)
def close_window(self):
self.master.destroy()
class Win3:
def __init__(self, master, number):
self.master = master
self.master.geometry("1080x540")
self.frame = tk.Frame(self.master)
#self.frame = Frame(self.master)
self.fig, self.ax = config_plot()
self.graphIndex = 0
self.canvas = FigureCanvasTkAgg(self.fig, self.master)
self.config_window()
self.quit = tk.Button(self.frame, text = f"Close this window", command = self.close_window)
self.quit.pack(side=LEFT)
self.frame.pack(expand=YES, fill=BOTH)
def on_key_press(event):
print("you pressed {}".format(event.key))
key_press_handler(event, self.canvas, toolbar)
def config_window(self):
self.canvas.mpl_connect("key_press_event", self.on_key_press)
toolbar = NavigationToolbar2Tk(self.canvas, self.master)
toolbar.update()
self.canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1)
def close_window(self):
f.master.destroy()
root = tk.Tk()
app = Win1(root)
root.mainloop()
Sorry for asking so many questions, unfortunately I didn't completely understand the answers from my previous question. Thank you very much for your help.
Ok, so I instead of opening a new thread, I decided just to expand my program directly here, since my new question is based on the old one. So I changed the program and my it doesn't work totally. The problem is that global_symbol doesn't change its value and I don't understand where the problem lies, I tried many things (leaving some lines, adding, etc) but none of them really worked. So does anyone of you guys know where the problem lies?
For question 1/ What you can do (worst case) is add a callback to your combobox. This callback can then update a "global variable"
Callback setting on combobox :
self.combo = ttk.Combobox(master, values = symbol)
self.combo.bind("<<ComboboxSelected>>", onSymbolSelected)
symbol declaration outside of Win1
global_symbol = None
callback implementation in Win1
def onSymbolSelected(self,event = None)
global global_symbol
global_symbol = self.combo.get() # this assume combo is a property of Win1

How to make matplotlib animate in a while loop in tkinter

I'm trying to live plot EEG recording in my tkinter app. However, it does not plot while the data is updating in the while loop, and plots only at the end.
import tkinter as tk
from tkinter import ttk, Button, LabelFrame, N, W, messagebox as box
import time
import datetime as dt
from datetime import date
import numpy as np
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib
import matplotlib.animation as animation
import matplotlib.pyplot as plt
class NFB_HomePage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.nfbprotocol = 0
self.metricstime = 0
self.nfbmetric = 0
self.df = []
self.xList = []
self.yList = []
# Start Neurofeedback
self.StartNFB = Button(self, text="Start NFB", width=25, command=self.onStartNFB)
self.StartNFB.grid(row=7, column=0, padx=5, pady=3, sticky=W)
# LabelFrame for EEG Graph
labelframe3 = LabelFrame(self, text="EEG Plot")
labelframe3.grid(row=4, column=2, padx=5, pady=2, sticky=N, rowspan=5, columnspan=4)
self.fig = plt.Figure(figsize=(10, 5), dpi=100)
self.ax1 = self.fig.add_subplot(111)
self.line, = self.ax1.plot([], [], lw=2)
self.canvas = FigureCanvasTkAgg(self.fig, labelframe3)
self.canvas.draw()
self.canvas.get_tk_widget().grid()
self.canvas._tkcanvas.grid(row=0, column=0, padx=5, pady=3, sticky=W)
def createDF(self):
df_timestamp = []
df_data = np.empty([0, 5])
# metrics
df_alpha = np.empty([0, 1])
df_beta = np.empty([0, 1])
df_theta = np.empty([0, 1])
df_delta = np.empty([0, 1])
df_alpha_theta = np.empty([0, 1])
df_metricstime = np.empty([0, 1])
return df_timestamp, df_data, df_alpha, df_beta, df_theta, df_delta, df_alpha_theta, df_metricstime
def onStartNFB(self):
try:
self.start()
# Initialize dataframes
df_timestamp, df_data, df_alpha, df_beta, df_theta, df_delta, df_alpha_theta, df_metricstime = self.createDF()
# Start recording here!
timestart = time.time()
while time.time() < timestart + int(4):
""" 3.1 ACQUIRE DATA """
self.metricstime = dt.datetime.now().strftime('%H:%M:%S.%f')
""" 3.3 COMPUTE NEUROFEEDBACK METRICS """
alpha_metric, beta_metric, theta_metric, delta_metric, alphatheta_metric = float(np.random.normal(size=1)), float(np.random.normal(size=1)), \
float(np.random.normal(size=1)), float(np.random.normal(size=1)), \
float(np.random.normal(size=1))
self.nfbmetric = alpha_metric
# Save the bands to data frame
df_alpha = np.append(df_alpha, [[alpha_metric]], axis=0)
df_beta = np.append(df_beta, [[beta_metric]], axis=0)
df_theta = np.append(df_theta, [[theta_metric]], axis=0)
df_delta = np.append(df_delta, [[delta_metric]], axis=0)
df_alpha_theta = np.append(df_alpha_theta, [[alphatheta_metric]], axis=0)
df_metricstime = np.append(df_metricstime, [[self.metricstime]], axis=0)
# Update graph
self.df = np.concatenate([df_metricstime, df_alpha, df_theta, df_alpha_theta],
axis=1)
print(self.nfbmetric)
except:
raise RuntimeError("Error with Neurofeedback.")
def start(self):
self.ani = animation.FuncAnimation(self.fig, self.animate, interval=int(500))
self.running = True
self.ani._start()
def animate(self,i):
df = self.df
for eachline in df:
if len(eachline) > 1:
dfX = eachline[0]
dfY = eachline[1]
self.xList.append(dfX)
self.yList.append(dfY)
self.ax1.clear()
self.ax1.plot(self.xList, self.yList)
title = "Neurofeedback Band Power"
self.ax1.set_title(title)
app = ExpGUI()
app.geometry("1280x720")
app.mainloop()
Does somebody know what is wrong with my code? I know how to get it to run outside the while loop, but I have problems getting it to run while the data is updating.

Matplotlib crash in gui

I would like to draw a matrix with imshow with tkinter in a gui. The problem is that after further updates, the gui crash. I don't manage to find answer on the web. You could help me please?
The code:
from numpy import *
from Tkinter import *
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
root = Tk()
f1 = Figure()
canvas = FigureCanvasTkAgg(f1, master=root)
canvas.show()
canvas.get_tk_widget().pack(fill="x")
a = f1.add_subplot(111)
a.get_axes().set_frame_on(True)
ini = [[i] * 100 for i in range(100)]
cax = a.matshow(ini)
while True:
mat = random.randint(0, 2**16-1, (1000, 1000))
cax.set_data(mat)
canvas.draw()
root.mainloop()
Thank you for your suggestion fhdrsdg but doing this way freeze the windows during the exection of redraw which is boring especially when this previous has a lot of stuff to do.
Here is my code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from Tkinter import Button, Label, Text, Checkbutton, Radiobutton, Frame, Tk, Entry, INSERT, StringVar, IntVar, Toplevel, END
from ttk import Notebook, Combobox
from numpy import arange, zeros, array, uint16, empty, divide, random, ravel
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
from matplotlib import cm
from matplotlib.image import AxesImage
import time
from threading import Thread
import os
class Image_direct(Thread):
def __init__(self):
Thread.__init__(self)
self.encore = True
def run(self):
"""This loop can be long ~10s"""
while self.encore:
time.sleep(1)
app.cax.set_extent((0, 1023, 1023, 0))
mat = random.randint(0, 2**16-1, (1024, 1024)).astype("uint16")
app.update_camera(mat)
def stop(self):
self.encore = False
class Deu(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.creer_applets()
def creer_applets(self):
self.fen4 = Frame(fen)
self.fen4.pack(side="bottom", fill="both")
self.fen1 = Frame(fen, width=200)
self.fen1.pack(side="left", fill="both", expand=False)
self.note = Notebook(fen, width=1)
self.tab_mat = Frame(self.note)
self.note.add(self.tab_mat, text = "Caméra", compound="top")
self.note.pack(side="left", fill="both", expand=True)
self.fen3 = Frame(fen, width=250)
self.fen3.pack(side="left", fill="both", expand=False)
Button(self.fen4, text="Quit", command=self.aurevoir).pack(fill="x", side="top")
self.interp = StringVar()
self.interp.set("none")
liste_interp = ["none", "nearest", "bilinear", "bicubic", "spline16", "spline36", "hanning", "hamming", "hermite", "kaiser", "quadric", "catrom", "gaussian", "bessel", "mitchell", "sinc", "lanczos"]
self.choix_interp = Combobox(self.tab_mat, textvariable=self.interp, state="readonly", width=10)
self.choix_interp['values'] = liste_interp
self.cmap = StringVar()
self.cmap.set("jet")
palettes = sorted(m for m in cm.datad if not m.endswith("_r"))
self.choix_palette = Combobox(self.tab_mat, textvariable=self.cmap, state="readonly", width=10)
self.choix_palette['values'] = palettes
self.bouton_palette = Button(self.tab_mat, text="Changer la palette", command=self.changer_cmap)
self.f1 = Figure()
self.canvas1 = FigureCanvasTkAgg(self.f1, master=self.tab_mat)
self.canvas1.show()
self.canvas1.get_tk_widget().pack(fill="both", expand=1)
NavigationToolbar2TkAgg(self.canvas1, self.tab_mat)
self.a = self.f1.add_subplot(111)
self.bg = self.canvas1.copy_from_bbox(self.a.bbox)
self.a.get_axes().set_frame_on(True)
ini = random.randint(0, 2**16-1, (1024, 1024))
self.cax = self.a.matshow(ini, cmap=self.cmap.get(), interpolation=self.interp.get(), picker=True, alpha=1.0)
self.a.format_coord = lambda x, y: 'x=%d, y=%d, z=%d' % (x, y, ini[round(y), round(x)])
self.cbar = self.f1.colorbar(self.cax)
self.cbar.set_label("coups")
self.bouton_palette.pack(side="left")
self.choix_interp.pack(side="left")
self.choix_palette.pack(side="left")
Button(self.tab_mat, text=">", command=lambda: self.changer_cbar(1)).pack(side="right")
self.cbar_auto = IntVar()
self.chb3 = Checkbutton(self.tab_mat, text="Auto?", variable=self.cbar_auto, onvalue=1, offvalue=0, indicatoron=0, command=lambda: self.changer_cbar(0))
self.chb3.select()
self.chb3.pack(side="right")
Button(self.tab_mat, text="<", command=lambda: self.changer_cbar(-1)).pack(side="right")
self.bouton_direct_on = Button(self.fen3, width=20, text="Démarrer le direct", command=self.image_direct_on)
self.bouton_direct_on.place(x=0, y=400)
self.bouton_direct_off = Button(self.fen3, width=20, text="Arrêter le direct", command=self.image_direct_off)
self.bouton_direct_off.config(state="disabled")
self.bouton_direct_off.place(x=0, y=430)
def changer_cbar(self, sens):
if sens == -1:
self.cbar.set_clim(vmin=self.cax.get_array().min(), vmax=0.9*self.cbar.get_clim()[1])
elif sens == 0 and self.cbar_auto.get():
self.cbar.set_clim(vmin=self.cax.get_array().min(), vmax=self.cax.get_array().max())
elif sens == 1:
self.cbar.set_clim(vmin=self.cax.get_array().min(), vmax=2*self.cbar.get_clim()[1])
self.cax.set_clim(self.cbar.get_clim())
self.canvas1.restore_region(self.bg)
self.a.draw_artist(self.f1)
self.canvas1.blit(self.f1.bbox)
def changer_cmap(self):
self.cax.set_cmap(self.cmap.get())
self.cax.set_interpolation(self.interp.get())
self.canvas1.draw()
def update_camera(self, mat):
xmin = min([int(i) for i in app.a.get_xlim()])
xmax = max([int(i) for i in app.a.get_xlim()])
ymin = min([int(i) for i in app.a.get_ylim()])
ymax = max([int(i) for i in app.a.get_ylim()])
self.a.format_coord = lambda x, y: 'x=%d, y=%d, z=%d' % (x, y, mat[round(y), round(x)])
self.cax.set_data(mat)
self.changer_cbar(0)
def image_direct_on(self):
self.bouton_direct_off.config(state="normal")
self.bouton_direct_on.config(state="disabled")
self.dire = Image_direct()
self.dire.setDaemon(True)
self.dire.start()
def image_direct_off(self):
self.bouton_direct_off.config(state="disabled")
self.bouton_direct_on.config(state="normal")
self.dire.stop()
del self.dire
def aurevoir(self):
try:
self.dire.isAlive()
except:
pass
else:
self.dire.stop()
fen.quit()
fen.destroy()
if __name__ == '__main__':
fen = Tk()
fen.geometry("1300x750")
app = Deu(fen)
fen.mainloop()
What is strange is that:
the crash occurs when the cursor is on the image
under linux, there is no crash.
It can happen in few seconds or few minutes when the cursor is over the image or when I zoom/dezoom the image. Then the window becomes white, and a pop-up appears with the message "pythonw.exe not responding". Idle says nothing. I am in the complete fog :/
I think the problem is with running the while True loop.
Try to limit the time between each repetition using the after method.
The following code updates the canvas every 100ms
from numpy import *
from Tkinter import *
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
root = Tk()
f1 = Figure()
canvas = FigureCanvasTkAgg(f1, master=root)
canvas.show()
canvas.get_tk_widget().pack(fill="x")
a = f1.add_subplot(111)
a.get_axes().set_frame_on(True)
ini = [[i] * 100 for i in range(100)]
cax = a.matshow(ini)
def redraw():
mat = random.randint(0, 2**16-1, (1000, 1000))
cax.set_data(mat)
canvas.draw()
root.after(100, redraw)
redraw()
root.mainloop()

Categories

Resources