Moving the plot regrading to the offset - python-3.x

Dears,
I wrote this code to calculate the distance between two mouse clicks on the plot. Now I am trying to move the plot to the left or to the right with regards to the calculated offset so that the two plots are exactly match. any idea how to achieve that? I tried to add and subtract normally but it did not work.
import matplotlib.pyplot as plt
from matplotlib.widgets import Cursor
import mplcursors
from math import sqrt
import numpy as np
import tkinter as tk
from tkinter import simpledialog
class DistancePlot:
def __init__(self):
ROOT = tk.Tk()
ROOT.withdraw()
ROOT.geometry("500x200")
#my_frame = Frame(ROOT)
#my_frame.pack(fill="both", expand=True)
USER_INP = (simpledialog.askinteger(title="Plot dialig",
prompt="Enter the number of the plots "))
if USER_INP is not None:
def f(x):
return np.sin(x) + np.random.normal(scale=0.1, size=len(x))
self.x = np.linspace(1, 10)
self.fig, self.ax= plt.subplots()
for i in range(USER_INP):
plt.plot(self.x, f(self.x))
self.ax.set_xlabel('X-axis')
self.ax.set_ylabel('Y-axis')
self.d1 = (0.0, 0.0)
self.d2 = (0.0, 0.0)
self.first_click = True
self.cursor=Cursor(self.ax, horizOn=True, vertOn=True, color='black', linewidth=1.0)
self.fig.canvas.mpl_connect('button_press_event', self.onclick)
mplcursors.cursor(hover=True)
plt.show()
else:
def quit(self):
self.ROOT.destroy()
def onclick(self, event):
z1, r1 = event.xdata, event.ydata
print(z1, r1)
if self.first_click:
self.first_click = False
self.d1 = (z1, r1)
else:
self.first_click = True
self.d2 = (z1, r1)
distance = sqrt((((self.d1[0]) - (self.d2[0])) ** 2) + (((self.d1[1]) - (self.d2[1])) ** 2))
print("The shift between ", self.d1, "and", self.d2, "is", distance)
dp = DistancePlot()
the answer in the comment was helpful but this is not exactly what I want, I tried to use the same logic to get to my solution but it didn't work and I will share it with you.
import matplotlib.pyplot as plt
from matplotlib.widgets import Cursor
import mplcursors
import numpy as np
import tkinter as tk
#from tkinter import simpledialog
class DistancePlot:
def __init__(self):
ROOT = tk.Tk()
ROOT.withdraw()
ROOT.geometry("500x200")
# USER_INP = 1
#random sine wave
x = np.linspace(1, 10)
def f(x):
return np.sin(x) + np.random.normal(scale=0.1, size=len(x))
#fixed sine wave
time= np.arange(0, 10, 0.1)
amplitude = np.sin(time)
self.fig, self.ax = plt.subplots()
self.ax.plot(x, f(x))
self.ax.plot(time, amplitude)
self.ax.set_xlabel('X-axis')
self.ax.set_ylabel('Y-axis')
self.d1 = np.zeros(2)
self.d2 = np.zeros(2)
self.first_click = True
self.cursor = Cursor(self.ax, horizOn=True, vertOn=True, color='black', linewidth=1)
self.fig.canvas.mpl_connect('button_press_event', self.onclick)
mplcursors.cursor(hover=True)
plt.show()
def onclick(self, event):
z1, r1 = event.xdata, event.ydata
print(z1, r1)
if self.first_click:
self.first_click = False
self.d1 = np.array((z1, r1))
else:
self.first_click = True
self.d2 = np.array((z1, r1))
#distance = sqrt((((self.d1[0]) - (self.d2[0])) ** 2) + (((self.d1[1]) - (self.d2[1])) ** 2))
#print("The distance between ", self.d1, "and", self.d2, "is", distance)
delta = self.d2 - self.d1
print("The delta between ", self.d1, "and", self.d2, "is", delta)
if (abs(self.d2[0]) > abs(self.d1[0])).all():
self.ax.lines[0].set_data(self.ax.lines[0].get_data() - delta.reshape(2,1))
self.ax.relim()
self.ax.autoscale_view()
plt.draw()
else:
self.ax.lines[0].set_data(self.ax.lines[0].get_data() + delta.reshape(2,1))
self.ax.relim()
self.ax.autoscale_view()
plt.draw()
dp = DistancePlot()
what I want is use a reference graph and match it with another graph, if the graph I am adding is leading I want it to be subtracted and if it lagging I want it to move forward so adding it to the delta.

Here is an approach, moving the first curve over the given distance. Numpy arrays are used to simplify the loops. relim() and autoscale_view() recalculate the x and y limits to fit everything again inside a margin (this step can be skipped if the expected displacement is small).
import matplotlib.pyplot as plt
from matplotlib.widgets import Cursor
import mplcursors
from math import sqrt
import numpy as np
import tkinter as tk
from tkinter import simpledialog
class DistancePlot:
def __init__(self):
ROOT = tk.Tk()
ROOT.withdraw()
ROOT.geometry("500x200")
USER_INP = 2
# USER_INP = (simpledialog.askinteger(title="Plot dialig", prompt="Enter the number of the plots "))
if USER_INP is not None:
def f(x):
return np.sin(x) + np.random.normal(scale=0.1, size=len(x))
self.x = np.linspace(1, 10)
self.fig, self.ax = plt.subplots()
for i in range(USER_INP):
self.ax.plot(self.x, f(self.x))
self.ax.set_xlabel('X-axis')
self.ax.set_ylabel('Y-axis')
self.d1 = np.zeros(2)
self.d2 = np.zeros(2)
self.first_click = True
self.cursor = Cursor(self.ax, horizOn=True, vertOn=True, color='black', linewidth=1)
self.fig.canvas.mpl_connect('button_press_event', self.onclick)
mplcursors.cursor(hover=True)
plt.show()
else:
def quit(self):
self.ROOT.destroy()
def onclick(self, event):
z1, r1 = event.xdata, event.ydata
if self.first_click:
self.first_click = False
self.d1 = np.array((z1, r1))
else:
self.first_click = True
self.d2 = np.array((z1, r1))
distance = sqrt((((self.d1[0]) - (self.d2[0])) ** 2) + (((self.d1[1]) - (self.d2[1])) ** 2))
delta = self.d2 - self.d1
self.ax.lines[0].set_data(self.ax.lines[0].get_data() + delta.reshape(2,1))
self.ax.relim()
self.ax.autoscale_view()
plt.draw()
dp = DistancePlot()
If you only want to move left-right, you can use set_xdata to only change the x-positions. The following example code moves the second curve with the given displacement. If you want to move to the left, the second click should be to the left of the first.
def onclick(self, event):
z1, r1 = event.xdata, event.ydata
if self.first_click:
self.first_click = False
self.d1 = np.array((z1, r1))
else:
self.first_click = True
self.d2 = np.array((z1, r1))
delta_x = self.d1[0] - self.d2[0]
self.ax.lines[1].set_xdata(self.ax.lines[1].get_xdata() + delta_x)
self.ax.relim()
self.ax.autoscale_view()
plt.draw()

Related

Matplotlib Scatter plot interactivity not working

Until this morning I was able to display labels information when hovering the dots on a scatter plot.
Now, if I run the following code it does not display any error but the interactivity is not working and it looks like mplconnect or mlpcursors are completely ignored.
I've tried the same code under windows and Fedora.
Not understanding what's going on.
from matplotlib.pyplot import figure, show
import numpy as npy
from numpy.random import rand
x, y, c, s = rand(4, 100)
def onpick3(event):
ind = event.ind
print('onpick3 scatter:', ind, npy.take(x, ind), npy.take(y, ind))
fig = figure()
ax1 = fig.add_subplot(111)
col = ax1.scatter(x, y, 100*s, c, picker=True)
#fig.savefig('pscoll.eps')
fig.canvas.mpl_connect('pick_event', onpick3)
show()
Or
import matplotlib.pyplot as plt
import numpy as np; np.random.seed(1)
x = np.random.rand(15)
y = np.random.rand(15)
names = np.array(list("ABCDEFGHIJKLMNO"))
c = np.random.randint(1,5,size=15)
norm = plt.Normalize(1,4)
cmap = plt.cm.RdYlGn
fig,ax = plt.subplots()
sc = plt.scatter(x,y,c=c, s=100, cmap=cmap, norm=norm)
annot = ax.annotate("", xy=(0,0), xytext=(20,20),textcoords="offset points",
bbox=dict(boxstyle="round", fc="w"),
arrowprops=dict(arrowstyle="->"))
annot.set_visible(False)
def update_annot(ind):
pos = sc.get_offsets()[ind["ind"][0]]
annot.xy = pos
text = "{}, {}".format(" ".join(list(map(str,ind["ind"]))),
" ".join([names[n] for n in ind["ind"]]))
annot.set_text(text)
annot.get_bbox_patch().set_facecolor(cmap(norm(c[ind["ind"][0]])))
annot.get_bbox_patch().set_alpha(0.4)
def hover(event):
vis = annot.get_visible()
if event.inaxes == ax:
cont, ind = sc.contains(event)
if cont:
update_annot(ind)
annot.set_visible(True)
fig.canvas.draw_idle()
else:
if vis:
annot.set_visible(False)
fig.canvas.draw_idle()
fig.canvas.mpl_connect("motion_notify_event", hover)
plt.show()
This is not my code, I've copied and pasted it from a website but the behavior is the same.
Plotly express solves the problem
import plotly.express as px
alpha = data[data['Ticker']==focus].V1
gamma = data[data['Ticker']==focus].V2
fig = px.scatter(data, x='V1', y='V2', color=Colors.Market_Cap, hover_data=["Ticker"] )
fig.add_shape(type="circle",
xref="x", yref="y",
x0=int(alpha-3), y0=int(gamma-3), x1=int(alpha+3), y1=int(gamma+3),
line_color="LightSeaGreen",
)
fig.show()

Python plots graph into button instead of figure

I'm a total beginner to python (started some days ago).
This little program is supposed to draw sinus waves, and the buttons at the bottom should increase / decrease the frequency of the plotted sinus. But my program plots the sinus into the button, for whatever reason. Where is the mistake? I've tried so much already... Thanks in advance ❤
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Button
class Function:
def __init__(self, amplitude, frequency):
self.amplitude = amplitude
self.frequency = frequency
self.time = np.arange(0.0, 1.0, 0.001)
self.signal= amplitude*np.sin(2*np.pi*frequency*self.time)
def status(self):
print("The frequency is: ", self.frequency)
print("The amplitude is: ", self.amplitude)
def setFrequency(self, frequency):
self.frequency = frequency
def setAmplitue(self, amplitude):
self.amplitude = amplitude
def show(self):
plt.plot(self.time, self.signal, linewidth = 2)
plt.ylabel("Sinus")
plt.xlabel("x")
pass
func = Function(1, 20)
func.show()
def IncreaseFrequency(event):
global func
if (func.frequency < 100):
func.setFrequency(func.frequency + 10)
else:
func.setFrequency(10)
func.show()
plt.draw()
pass
def LowerFrequency(event):
global func
if (func.frequency > 10):
func.setFrequency(func.frequency - 10)
else:
func.setFrequency(100)
func.show()
plt.draw()
pass
buttonIncrSize = plt.axes([0.7, 0.01, 0.1, 0.05])
buttonLowerSize = plt.axes([0.81, 0.01, 0.1, 0.05])
buttonIncrFreq = Button(buttonIncrSize, 'Next')
buttonLowerFreq = Button(buttonLowerSize, 'Previous')
buttonIncrFreq.on_clicked(IncreaseFrequency)
buttonLowerFreq.on_clicked(LowerFrequency)
plt.show()
First what looks kind of weird is that after lowering or increasing your frequency, you never update the self.signal, which should change if your frequency changes.
Secondly, from what I could see on this link, plt.plot returns an Line2D object which you can use to set the y data on your plot using line2D.set_ydata(new_ydata).
After changing the y data, just update the plot using plt.draw() and that should work.
EDIT: Indeed I didn't have access to my PC but ran this now and didn't work. After some search:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Button
import matplotlib
class Function:
def __init__(self, amplitude, frequency):
self.amplitude = amplitude
self.frequency = frequency
self.time = np.arange(0.0, 1.0, 0.001)
self.signal = amplitude * np.sin(2 * np.pi * frequency * self.time)
def status(self):
print("The frequency is: ", self.frequency)
print("The amplitude is: ", self.amplitude)
def setFrequency(self, frequency):
self.frequency = frequency
self.signal = self.amplitude * np.sin(2 * np.pi * frequency * self.time)
def setAmplitude(self, amplitude):
self.amplitude = amplitude
self.signal = self.amplitude * np.sin(2 * np.pi * frequency * self.time)
def show(self):
plt.cla()
plt.plot(self.time,self.signal,lw=2)
plt.draw()
plt.ylabel("Sinus")
plt.xlabel("x")
def IncreaseFrequency(event):
global func
if (func.frequency < 100):
func.setFrequency(func.frequency + 10)
else:
func.setFrequency(10)
func.show()
def LowerFrequency(event):
global func
if (func.frequency > 10):
func.setFrequency(func.frequency - 10)
else:
func.setFrequency(100)
func.show()
fig, ax = plt.subplots()
func = Function(1, 20)
func.show()
buttonIncrSize = plt.axes([0.7, 0.01, 0.1, 0.05])
buttonLowerSize = plt.axes([0.81, 0.01, 0.1, 0.05])
buttonIncrFreq = Button(buttonIncrSize, 'Next')
buttonLowerFreq = Button(buttonLowerSize, 'Previous')
buttonIncrFreq.on_clicked(IncreaseFrequency)
buttonLowerFreq.on_clicked(LowerFrequency)
plt.sca(fig.axes[0])
plt.show()
Main change being the plt.sca(fig.axes[0]) which allows to select the current axis for plt. When you run plt.axes() it sets the current axes of plt to the button, hence subsequently plotting your graph in that button.
Also added plt.cla() which clears the current plotting area.

How to connect matplotlib cursor mouse_move object with slider value?

I have a figure where 2 axhlines move with mouse movement. I want to put a slider at the bottom where it will change the range of y-axis values covered by these axhlines.
enter image description here
I tried the following code. Problem is that the value of the slider changes but the mouse event object does not update.
Thanks
%matplotlib notebook
import pandas as pd
import numpy as np
import scipy.stats as stats
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
from matplotlib.widgets import Slider
np.random.seed(12345)
df = pd.DataFrame([np.random.normal(32000,200000,3650),
np.random.normal(43000,100000,3650),
np.random.normal(43500,140000,3650),
np.random.normal(48000,70000,3650)],
index=[1992,1993,1994,1995])
df=df.T
data=df.describe().T
data['error']=df.sem()
data['error_range']=df.sem()*1.96
fig, ax = plt.subplots()
def plot_bar(x,y,error,title,alpha_level=0.7):
ax.bar(x,y, yerr=error,
align='center', alpha=alpha_level,
error_kw=dict(ecolor='black', elinewidth=1, capsize=5, capthick=1))
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.set_title(title)
ax.xaxis.set_major_locator(ticker.FixedLocator(data.index))
ax.yaxis.set_major_formatter(ticker.StrMethodFormatter('{x:,.0f}'))
ax.set_ylim([-5000,55000])
ax.set_xlim([1990.5,1995.5])
ax.spines['bottom'].set_position(('data',0))
ax.spines['left'].set_position(('data',1991.4))
plt.tight_layout()
return (ax, ax.get_children()[1:5])
ax, barlist=plot_bar(x=data.index,y=data['mean'],error=data['error_range'],title='Even Harder Option', alpha_level=0.6)
fig.subplots_adjust(bottom=0.1)
axcolor = 'lightgoldenrodyellow'
range_slider = plt.axes([0.2, 0.05, 0.65, 0.03], facecolor=axcolor)
slider = Slider(range_slider, 'Range', 0, 55000, valinit=10000, valstep=100)
def update(val):
slider.val = slider.val
slider.on_changed(update)
class Cursor(object):
_df=None
_bl=None
def __init__(self, ax,data_F, bars, slider):
#global slider
self._df=data_F
self._bl=bars
self.ax = ax
self.lx1 = ax.axhline(color='b')
self.lx2 = ax.axhline(color='b')
self.text1 = ax.text(1990.55, y, '%d' %45,bbox=dict(fc='white',ec='k'), fontsize='x-small')
self.text2 = ax.text(1990.55, y, '%d' %45,bbox=dict(fc='white',ec='k'), fontsize='x-small')
self._sl = slider.val
def mouse_move(self, event):
if not event.inaxes:
return
x, y = event.xdata, event.ydata
r = self._sl
y1 , y2 = y+r/2 , y-r/2
#self.lx1.set_ydata(y)
self.lx1.set_ydata(y+r/2)
self.lx2.set_ydata(y-r/2)
for i in range(4):
#shade = cmap(norm((data['mean'.values[i]-event.ydata)/df_std.values[i]))
prob1=stats.norm.cdf(y1,self._df['mean'].values[i],self._df['error'].values[i])
prob2=stats.norm.cdf(y2,self._df['mean'].values[i],self._df['error'].values[i])
shade = cmap(prob1-prob2)
self._bl[i].set_color(shade)
self.text1.set_text('%d' %y1)
self.text1.set_position((1990.55, y1))
self.text2.set_text('%d' %y2)
self.text2.set_position((1990.55, y2))
plt.draw()
cursor = Cursor(ax, data,barlist, slider)
#plt.connect('range_change', cursor.update)
plt.connect('motion_notify_event', cursor.mouse_move)

Can someone please tell me what is wrong with this code?

I'm working on Idle and when I ask to check the file, it says no problems. When I run it though, it crashes the app. I'm also working on a MAC, I don't know if that will influence anything. Can anyone please tell me what's wrong with this code? I'm still fairly new, so any help is appreciated.
Also what I am trying to do is mostly imbed a matplotlib animation into a GUI when the GUI has the entries for the animation data, and a button to call the animation is on the GUI as well. Ideally the button would be clicked and the Animation would show up above the two entries. I have been working on this program for a while, but imbedding the animation/ getting the button to callback the graph has been the most troublesome part.
import tkinter as tk
from tkinter import *
import time
import pyaudio
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
from matplotlib import pyplot as plt
import matplotlib.animation as animation
import numpy as np
import random
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
def get_data():
while True:
return x, mylist
class App(tk.Frame):
def __init__(self, root):
self.root = root
self.root.title("Testing")
self.setupTk()
self.quit_button = Button(master=self.root, text='Quit', command=self._quit)
self.quit_button.pack(side='right')
def _quit(self):
self.root.destroy()
fig = plt.Figure()
x = np.arange(0, 2*np.pi, 0.01) # x-array
def animate(i):
line.set_ydata(np.sin((x+i/10.0))) # update the data
return line,
root = tk.Tk()
label = tk.Label(root,text="SHM Simulation").grid(column=0, row=0)
canvas = FigureCanvasTkAgg(fig, master=root)
canvas.get_tk_widget().grid(column=0,row=1)
entry1= Entry(root, text='Frequency')
canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1)
entry2= Entry(root, text='Duration')
canvas.get_tk.widget().pack(side=TOP, fill=BOTH, expand=1)
entry2.pack()
f=int(entry1.get())
t=float(entry2.get())
def callback():
p=pyaudio.Pyaudio
fs=44100
volume=.7
samples=(np.sin(f*2*np.pi*np.arange(fs*t)/(fs).astype(np/float32)))
stream=p.open(format=pyaudio.paFloat32,
channels=1,
rate=fs,
output=True)
stream.write(volume*samples)
b=Button(root, text='Sound', command=callback)
ax = fig.add_subplot(111)
line, = ax.plot(x, np.sin(x))
ani = animation.FuncAnimation(fig, animate, np.arange(1, 200), interval=25, blit=False)
def on_click(self):
if self.ani is None:
return self.start()
if self.running:
self.ani.event_source.stop()
self.btn.config(text='Un-Pause')
else:
self.ani.event_source.start()
self.btn.config(text='Pause')
self.running = not self.running
def start(self):
self.points = int(self.points_ent.get()) + 1
self.ani = animation.FuncAnimation(
self.fig,
self.update_graph,
frames=self.points,
interval=int(self.interval.get()),
repeat=False)
self.running = True
self.btn.config(text='Pause')
self.ani._start()
print('started animation')
def update_graph(self, i):
self.line.set_data(*get_data()) # update graph
if i >= self.points - 1:
self.btn.config(text='Start')
self.running = False
self.ani = None
return self.line,
def main():
root = tk.Tk()
app = App(root)
app.pack()
root.mainloop()
if __name__ == '__main__':
main
As I was interested in the pyaudio I have tried to make your code runnable with the functionality that I think you had intended. You can build from here to add a random signal to the sine wave or use different signals all together. Main changes is that all functions are now in the class App. Also to have the audio sound and plot to run at the same time I start the audio in a different thread.
Hope this is useful for you.
import threading
import random
import numpy as np
import tkinter as tk
from tkinter import Label, Button, Entry, TOP, BOTH
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
from matplotlib import pyplot as plt
from matplotlib.animation import FuncAnimation
import pyaudio
DEFAULT_FREQUENCY = 220
DEFAULT_DURATION = 5
VOLUME = 0.3
INTERVAL = 100
class App(tk.Frame):
def __init__(self, root):
self.root = root
self.root.title("SHM Simulation - Testing")
label = tk.Label(self.root, text="SHM Simulation")
label.pack()
self.fig, self.ax = plt.subplots(figsize=(5, 5))
self.canvas = FigureCanvasTkAgg(self.fig, master=root)
self.canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1)
self.ax.set_ylim(-1.1, 1.1)
self.ax.set_xlim(-0.1, 2 * np.pi + 0.1)
self.quit_button = Button(master=self.root, text='Quit', command=self.quit)
self.quit_button.pack(side='right')
self.sound_button = Button(self.root, text='Sound off', command=self.toggle_sound)
self.sound_button.pack(side='right')
self.plot_button = Button(self.root, text='Start')
self.plot_button.pack(side='right')
self.plot_button.bind('<Button-1>', self.on_click)
tk.Label(self.root, text='Frequency').pack(side='left')
self.frequency_entry = Entry(self.root)
self.frequency_entry.insert(0, DEFAULT_FREQUENCY)
self.frequency_entry.pack(side='left')
tk.Label(self.root, text='Duration').pack(side='left')
self.duration_entry = Entry(self.root)
self.duration_entry.insert(0, DEFAULT_DURATION)
self.duration_entry.pack(side='left')
self.ani = None
self.running = False
self.audio = pyaudio.PyAudio()
self.sound = False
self.samples = np.array([])
def quit(self):
self.audio.terminate()
self.root.quit()
def get_data(self, frame):
self.ydata = np.sin(self.frequency * self.xdata + frame)
def update_frame(self, frame):
self.get_data(frame)
self.line.set_data(self.xdata, self.ydata)
if frame > self.duration - 1.1 * INTERVAL / 1000 :
self.ani = None
self.running = False
self.plot_button.config(text='Start')
return self.line,
def start_animation(self):
self.xdata = []
self.ydata = []
self.line, = self.ax.plot(self.xdata, self.ydata, lw=3)
self.xdata = np.arange(0, 2 * np.pi, 0.01)
duration_range = np.arange(0, self.duration, INTERVAL / 1000)
self.ani = FuncAnimation(self.fig,
self.update_frame,
frames=duration_range,
interval=INTERVAL,
repeat=False)
if self.sound:
''' start audio in a seperate thread as otherwise audio and
plot will not be at the same time
'''
x = threading.Thread(target=self.play_sound)
x.start()
def callback(self, in_data, frame_count, time_info, status):
out = self.samples[:frame_count]
self.samples = self.samples[frame_count:]
return (out*VOLUME, pyaudio.paContinue)
def play_sound(self):
fs = 44100
self.samples = (np.sin(2 * np.pi * np.arange(fs * self.duration) *
self.frequency / fs)).astype(np.float32)
stream = self.audio.open(format=pyaudio.paFloat32,
channels=1,
rate=fs,
output=True,
stream_callback=self.callback)
stream.start_stream()
# pause audio when self.running is False
while stream.is_active():
while not self.running:
if stream.is_active:
stream.stop_stream()
else:
pass
if self.running and not stream.is_active():
stream.start_stream()
else:
pass
stream.stop_stream()
stream.close()
def toggle_sound(self):
if self.sound:
self.sound_button.configure(text='Sound Off')
else:
self.sound_button.configure(text='Sound On ')
self.sound = not self.sound
def on_click(self, event):
if self.ani is None:
try:
self.ax.lines.pop(0)
except IndexError:
pass
try:
self.frequency = int(self.frequency_entry.get())
self.duration = int(self.duration_entry.get())
except ValueError:
self.frequency = DEFAULT_FREQUENCY
self.frequency_entry.insert(0, DEFAULT_FREQUENCY)
self.duration = DEFAULT_DURATION
self.duration_entry.insert(0, DEFAULT_DURATION)
self.start_animation()
self.running = True
self.plot_button.config(text='Pause')
print('animation started ...')
return
if self.running:
self.ani.event_source.stop()
self.plot_button.config(text='Run ')
else:
self.ani.event_source.start()
self.plot_button.config(text='Pause')
self.running = not self.running
def main():
root = tk.Tk()
app = App(root)
root.mainloop()
if __name__ == '__main__':
main()

Open excel file in Tkinter and plot graphs

I've just started writing Python a month ago and now getting into Tkinter. I'm trying to build a program that a user can open an excel file into Tkinter, display the dataframe and the user can choose a certain graph type, insert the variables for the X-axis and Y-axis and plot it. I've build the general layout of the GUI using PAGE but having problems on how to give commands to the widgets on displaying the dataframe and plotting the graph.
Here's my code for the GUI:
import sys
from tkinter.filedialog import askopenfilename
try:
from Tkinter import *
except ImportError:
from tkinter import *
try:
import ttk
py3 = 0
except ImportError:
import tkinter.ttk as ttk
py3 = 1
def vp_start_gui():
'''Starting point when module is the main routine.'''
global val, w, root
root = Tk()
top = New_Toplevel_1 (root)
root.mainloop()
w = None
def create_New_Toplevel_1(root, *args, **kwargs):
'''Starting point when module is imported by another program.'''
global w, w_win, rt
rt = root
w = Toplevel (root)
top = New_Toplevel_1 (w)
return (w, top)
def destroy_New_Toplevel_1():
global w
w.destroy()
w = None
class New_Toplevel_1:
def __init__(self, top=None):
'''This class configures and populates the toplevel window.
top is the toplevel containing window.'''
self._bgcolor = '#d9d9d9' # X11 color: 'gray85'
self._fgcolor = '#000000' # X11 color: 'black'
self._compcolor = '#d9d9d9' # X11 color: 'gray85'
self._ana1color = '#d9d9d9' # X11 color: 'gray85'
self._ana2color = '#d9d9d9' # X11 color: 'gray85'
top.geometry("757x1037+832+67")
top.title("New Toplevel 1")
top.configure(background="#d9d9d9")
top.configure(highlightbackground="#d9d9d9")
top.configure(highlightcolor="black")
self.Canvas1 = Canvas(top)
self.Canvas1.place(relx=0.04, rely=0.58, relheight=0.4, relwidth=0.92)
self.Canvas1.configure(background="white")
self.Canvas1.configure(borderwidth="2")
self.Canvas1.configure(highlightbackground="#d9d9d9")
self.Canvas1.configure(highlightcolor="black")
self.Canvas1.configure(insertbackground="black")
self.Canvas1.configure(relief=RIDGE)
self.Canvas1.configure(selectbackground="#c4c4c4")
self.Canvas1.configure(selectforeground="black")
self.Canvas1.configure(width=695)
self.Button2 = Button(top)
self.Button2.place(relx=0.75, rely=0.52, height=42, width=138)
self.Button2.configure(activebackground="#d9d9d9")
self.Button2.configure(activeforeground="#000000")
self.Button2.configure(background="#d9d9d9")
self.Button2.configure(disabledforeground="#a3a3a3")
self.Button2.configure(foreground="#000000")
self.Button2.configure(highlightbackground="#d9d9d9")
self.Button2.configure(highlightcolor="black")
self.Button2.configure(pady="0")
self.Button2.configure(text='''Generate Graph''')
self.Labelframe1 = LabelFrame(top)
self.Labelframe1.place(relx=0.05, rely=0.39, relheight=0.18
, relwidth=0.44)
self.Labelframe1.configure(relief=GROOVE)
self.Labelframe1.configure(foreground="black")
self.Labelframe1.configure(text='''Type of Graph''')
self.Labelframe1.configure(background="#d9d9d9")
self.Labelframe1.configure(highlightbackground="#d9d9d9")
self.Labelframe1.configure(highlightcolor="black")
self.Labelframe1.configure(width=330)
self.Radiobutton1 = Radiobutton(self.Labelframe1)
self.Radiobutton1.place(relx=0.06, rely=0.22, relheight=0.2
, relwidth=0.31)
self.Radiobutton1.configure(activebackground="#d9d9d9")
self.Radiobutton1.configure(activeforeground="#000000")
self.Radiobutton1.configure(background="#d9d9d9")
self.Radiobutton1.configure(disabledforeground="#a3a3a3")
self.Radiobutton1.configure(foreground="#000000")
self.Radiobutton1.configure(highlightbackground="#d9d9d9")
self.Radiobutton1.configure(highlightcolor="black")
self.Radiobutton1.configure(justify=LEFT)
self.Radiobutton1.configure(text='''Bar Chart''')
self.Radiobutton2 = Radiobutton(self.Labelframe1)
self.Radiobutton2.place(relx=0.06, rely=0.38, relheight=0.2
, relwidth=0.35)
self.Radiobutton2.configure(activebackground="#d9d9d9")
self.Radiobutton2.configure(activeforeground="#000000")
self.Radiobutton2.configure(background="#d9d9d9")
self.Radiobutton2.configure(disabledforeground="#a3a3a3")
self.Radiobutton2.configure(foreground="#000000")
self.Radiobutton2.configure(highlightbackground="#d9d9d9")
self.Radiobutton2.configure(highlightcolor="black")
self.Radiobutton2.configure(justify=LEFT)
self.Radiobutton2.configure(text='''Histogram''')
self.Radiobutton3 = Radiobutton(self.Labelframe1)
self.Radiobutton3.place(relx=0.06, rely=0.54, relheight=0.2
, relwidth=0.37)
self.Radiobutton3.configure(activebackground="#d9d9d9")
self.Radiobutton3.configure(activeforeground="#000000")
self.Radiobutton3.configure(background="#d9d9d9")
self.Radiobutton3.configure(disabledforeground="#a3a3a3")
self.Radiobutton3.configure(foreground="#000000")
self.Radiobutton3.configure(highlightbackground="#d9d9d9")
self.Radiobutton3.configure(highlightcolor="black")
self.Radiobutton3.configure(justify=LEFT)
self.Radiobutton3.configure(text='''Scatter Plot''')
self.Button3 = Button(top)
self.Button3.place(relx=0.28, rely=0.05, height=52, width=122)
self.Button3.configure(activebackground="#d9d9d9")
self.Button3.configure(activeforeground="#000000")
self.Button3.configure(background="#d9d9d9")
self.Button3.configure(disabledforeground="#a3a3a3")
self.Button3.configure(foreground="#000000")
self.Button3.configure(highlightbackground="#d9d9d9")
self.Button3.configure(highlightcolor="black")
self.Button3.configure(pady="0")
self.Button3.configure(text='''Browse''')
self.Button3.configure(width=122)
self.Button3.configure(command=askopenfilename)
self.Label5 = Label(top)
self.Label5.place(relx=0.03, rely=0.06, height=31, width=147)
self.Label5.configure(activebackground="#f9f9f9")
self.Label5.configure(activeforeground="black")
self.Label5.configure(background="#d9d9d9")
self.Label5.configure(disabledforeground="#a3a3a3")
self.Label5.configure(foreground="#000000")
self.Label5.configure(highlightbackground="#d9d9d9")
self.Label5.configure(highlightcolor="black")
self.Label5.configure(text='''Upload File:''')
self.Label5.configure(width=147)
self.Label3 = Label(top)
self.Label3.place(relx=0.05, rely=0.13, height=31, width=111)
self.Label3.configure(background="#d9d9d9")
self.Label3.configure(disabledforeground="#a3a3a3")
self.Label3.configure(foreground="#000000")
self.Label3.configure(text='''Data Frame :''')
self.Text1 = Text(top)
self.Text1.place(relx=0.05, rely=0.16, relheight=0.21, relwidth=0.9)
self.Text1.configure(background="white")
self.Text1.configure(font="TkTextFont")
self.Text1.configure(foreground="black")
self.Text1.configure(highlightbackground="#d9d9d9")
self.Text1.configure(highlightcolor="black")
self.Text1.configure(insertbackground="black")
self.Text1.configure(selectbackground="#c4c4c4")
self.Text1.configure(selectforeground="black")
self.Text1.configure(width=684)
self.Text1.configure(wrap=WORD)
self.Labelframe2 = LabelFrame(top)
self.Labelframe2.place(relx=0.5, rely=0.39, relheight=0.12
, relwidth=0.45)
self.Labelframe2.configure(relief=GROOVE)
self.Labelframe2.configure(foreground="black")
self.Labelframe2.configure(text='''Labelframe''')
self.Labelframe2.configure(background="#d9d9d9")
self.Labelframe2.configure(width=340)
self.Label1 = Label(self.Labelframe2)
self.Label1.place(relx=0.03, rely=0.24, height=31, width=67)
self.Label1.configure(background="#d9d9d9")
self.Label1.configure(disabledforeground="#a3a3a3")
self.Label1.configure(foreground="#000000")
self.Label1.configure(text='''X-axis :''')
self.Label2 = Label(self.Labelframe2)
self.Label2.place(relx=0.03, rely=0.56, height=31, width=66)
self.Label2.configure(background="#d9d9d9")
self.Label2.configure(disabledforeground="#a3a3a3")
self.Label2.configure(foreground="#000000")
self.Label2.configure(text='''Y-axis :''')
self.Entry1 = Entry(self.Labelframe2)
self.Entry1.place(relx=0.24, rely=0.24, relheight=0.29, relwidth=0.72)
self.Entry1.configure(background="white")
self.Entry1.configure(disabledforeground="#a3a3a3")
self.Entry1.configure(font="TkFixedFont")
self.Entry1.configure(foreground="#000000")
self.Entry1.configure(insertbackground="black")
self.Entry1.configure(width=244)
self.Entry2 = Entry(self.Labelframe2)
self.Entry2.place(relx=0.24, rely=0.56, relheight=0.29, relwidth=0.72)
self.Entry2.configure(background="white")
self.Entry2.configure(disabledforeground="#a3a3a3")
self.Entry2.configure(font="TkFixedFont")
self.Entry2.configure(foreground="#000000")
self.Entry2.configure(insertbackground="black")
self.Entry2.configure(width=244)
if __name__ == '__main__':
vp_start_gui()
I know how to save the data into a dataframe and plot graphs in Python, but i'm not sure where to write those codes when GUI is involved. All i was able to do was give a command to the 'Browse' button to search for the excel file.
self.Button3.configure(command=askopenfilename)
Can someone help me:
How to save the excel file chosen from the command into a dataframe
How to display the dataframe into the textbox below
How to plot the graph with the criteria (type of graph and axes) chosen onto the canvas at bottom
Thanks so much in advance.
In class use some self.variable to keep information and then you can use it in other methods in class.
In example I use method load() to load file and create dataframe, and method display() to display this dataframe in text widget.
try:
# Python 2
import Tkinter as tk
import ttk
from tkFileDialog import askopenfilename
except ImportError:
# Python 3
import tkinter as tk
from tkinter import ttk
from tkinter.filedialog import askopenfilename
import pandas as pd
# --- classes ---
class MyWindow:
def __init__(self, parent):
self.parent = parent
self.filename = None
self.df = None
self.text = tk.Text(self.parent)
self.text.pack()
self.button = tk.Button(self.parent, text='LOAD DATA', command=self.load)
self.button.pack()
self.button = tk.Button(self.parent, text='DISPLAY DATA', command=self.display)
self.button.pack()
def load(self):
name = askopenfilename(filetypes=[('CSV', '*.csv',), ('Excel', ('*.xls', '*.xlsx'))])
if name:
if name.endswith('.csv'):
self.df = pd.read_csv(name)
else:
self.df = pd.read_excel(name)
self.filename = name
# display directly
#self.text.insert('end', str(self.df.head()) + '\n')
def display(self):
# ask for file if not loaded yet
if self.df is None:
self.load()
# display if loaded
if self.df is not None:
self.text.insert('end', self.filename + '\n')
self.text.insert('end', str(self.df.head()) + '\n')
# --- main ---
if __name__ == '__main__':
root = tk.Tk()
top = MyWindow(root)
root.mainloop()
Here i have fetch the excel data and store it in the graph, but i want my graph should plot data after 5 second,and the graph should run in the Run time.
from openpyxl import load_workbook
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
# read from excel file
wb = load_workbook('C:\\Users\\Acer-i5-607\\Desktop\\case1.xlsx')
sheet_1 = wb.get_sheet_by_name('case1')
plt.figure(figsize=(6, 4), facecolor='Grey')
G = gridspec.GridSpec(6, 2)
axes_1 = plt.subplot(G[0, :])
x = np.zeros(sheet_1.max_row)
y = np.zeros(len(x))
for i in range(1, sheet_1.max_row):
x[i] = sheet_1.cell(row=i + 1, column=2).value
y[i] = sheet_1.cell(row=i + 1, column=4).value
#print x
#print y
# create the plot
plt.xlabel('time')
plt.ylabel('HR')
plt.plot(x, y, color='cyan', label='HR')
plt.legend(loc='upper right', fontsize='small')
plt.grid(True)
#plt.title('Reading values from an Excel file'
axes_1 = plt.subplot(G[1, :])
x = np.zeros(sheet_1.max_row)
y = np.zeros(len(x))
for i in range(1, sheet_1.max_row):
x[i] = sheet_1.cell(row=i + 1, column=2).value
y[i] = sheet_1.cell(row=i + 1, column=6).value
#print a
#print b
# create the plot
plt.xlabel('time')
plt.ylabel('Pulse')
plt.plot(x, y, color='red', label='Pulse')
plt.legend(loc='upper right', fontsize='small')
plt.grid(True)
axes_1 = plt.subplot(G[2, :])
x = np.zeros(sheet_1.max_row)
y = np.zeros(len(x))
for i in range(1, sheet_1.max_row):
x[i] = sheet_1.cell(row=i + 1, column=2).value
y[i] = sheet_1.cell(row=i + 1, column=7).value
#print x
#print y
# create the plot
plt.xlabel('time')
plt.ylabel('SpO2')
plt.plot(x, y, color='magenta', label='SpO2')
plt.legend(loc='upper right', fontsize='small')
plt.grid(True)
axes_1 = plt.subplot(G[3, :])
x = np.zeros(sheet_1.max_row)
y = np.zeros(len(x))
for i in range(1, sheet_1.max_row):
x[i] = sheet_1.cell(row=i + 1, column=2).value
y[i] = sheet_1.cell(row=i + 1, column=8).value
#print x
#print y
# create the plot
plt.xlabel('time')
plt.ylabel('Perf')
plt.plot(x, y, color='blue', label='Perf')
plt.legend(loc='upper right', fontsize='small')
plt.grid(True)
axes_1 = plt.subplot(G[4, :])
x = np.zeros(sheet_1.max_row)
y = np.zeros(len(x))
for i in range(1, sheet_1.max_row):
x[i] = sheet_1.cell(row=i + 1, column=2).value
y[i] = sheet_1.cell(row=i + 1, column=9).value
#print x
#print y
# create the plot
plt.xlabel('time')
plt.ylabel('etCO2')
plt.plot(x, y, color='yellow', label='etCO2')
plt.legend(loc='upper right', fontsize='small')
plt.grid(True)
axes_1 = plt.subplot(G[5, :])
x = np.zeros(sheet_1.max_row)
y = np.zeros(len(x))
for i in range(1, sheet_1.max_row):
x[i] = sheet_1.cell(row=i + 1, column=2).value
y[i] = sheet_1.cell(row=i + 1, column=10).value
#print x
#print y
# create the plot
plt.xlabel('time')
plt.ylabel('imCO2')
plt.plot(x, y, color='green', label='imCO2')
plt.legend(loc='upper right', fontsize='small')
plt.grid(True)
plt.xlim(0, 60000)
plt.ylim(0, 100)
plt.show()
import tkinter as tk
from tkinter import filedialog
import pandas as pd
import matplotlib.pyplot as plt
root= tk.Tk()
canvas1 = tk.Canvas(root, width = 300, height = 300, bg = 'lightsteelblue')
canvas1.pack()
def getExcel ():
global df
import_file_path = filedialog.askopenfilename()
df = pd.read_excel (import_file_path)
df["Year"] = pd.to_datetime(df["Year"], format="%Y")
ax = df.plot("Year", "Accidents",marker='o',color='r')
plt.grid()
plt.title('Yearly Graph')
ax.figure.autofmt_xdate()
plt.show()
browseButton_Excel = tk.Button(text='Import Excel File', command=getExcel, bg='green', fg='white', font=('helvetica', 12, 'bold'))
canvas1.create_window(150, 150, window=browseButton_Excel)
root.mainloop()

Resources