panel/holoviz dynamically update a section of the template - dynamic

This is my first project with panel.
I can't display a new element in the main of my template.
En effet j'essai d'afficher un graph lorsque je clique sur un button.
my code python
import numpy as np
import pandas as pd
from matplotlib.figure import Figure
import hvplot.pandas
import panel as pn
text_input = pn.widgets.TextInput( placeholder='Your question')
button = pn.widgets.Button(value=True,name='Rechercher', button_type='primary')
def get_dataframe(question):
row_headers = ['vehicle model','driver\'s name','driver\'s firstname','incident
place','lieu latitude','lieu longitude','incident date', 'Number of accident']
data = (('CX 9','Kouakou','Franck','Yamoussoukro',6.816667080,-5.283332825,'2020-10-
19 00:00:00', 1), ('CX 9','Kone','Lamine','Abobo',5.432887077,-4.038891792,'2020-10-16
08:30:51', 1), ('Ranger 4X4
DC','Tano','Hermine','Cocody',5.359376907,-3.995745897,'2021-02-09 08:00:38', 1),
('Pathfinder','Yao','Nadia','Cocody',5.354498386,-3.992352009,'2021-02-15 08:00:23', 1),
('Yaris','Doumbia' ,'Cheick Slymane','Cocody',5.370238781,-3.981418133,'2021-07-10
10:00:22', 1), ('Yaris', 'Doumbia','Cheick
Slymane','Yopougon',5.349046230,-4.073932171,'2020-03-06 20:00:49', 1), ('Yaris',
'Doumbia','Cheick Slymane','Adzope',6.107145786,-3.855350971,'2020-12-20 14:20:47', 1))
df = pd.DataFrame(data, columns=row_headers)
return row_headers,data,df
def line_widget(text_input):
row_headers, data, df = get_dataframe(text_input.value)
idf = df.interactive()
tab = []
accident_pipeline = (idf)
accident_plot = accident_pipeline.hvplot(x=row_headers[0],y='Number of accident',line_width=2, title='Accident par model')
return pn.Row(accident_plot)
app = pn.template.FastListTemplate(title='Dashboard',main=[pn.Row(pn.Column(text_input),button)])
#pn.depends(button_inf=button, question=text_input, watch=True)
def _item_selector(button_inf,question):
if button_inf:
app.main.append(pn.Row(line_widget(question)))
app.servable()
What I get even after clicking the button
fig1
What I want after clicking the button
fig2

Related

Plotly override legend names without traces

I'm trying to change the legend names and I've found many answers but none of them works if you are not using traces. I learned to change the legend title but not the names.
Here it is my code, hopefully somebody can help:
import pandas as pd
import plotly.express as px
import numpy as np
def camasRegion():
df = pd.read_csv('https://raw.githubusercontent.com/MinCiencia/Datos-COVID19/master/output/producto52/Camas_UCI.csv')
dates = df.columns #for some reason I can't use this as x axis
habilitadas = []
ocupadasCovid = []
ocupadasNoCovid = []
region = 'Ñuble'
for i in range(len(df)):
if df.values[i][0] == region:
if df.values[i][1] == 'Camas UCI habilitadas':
for x in range(len(df.columns)):
habilitadas.append(df.values[i][x])
if df.values[i][1] == 'Camas UCI ocupadas COVID-19':
for x in range(len(df.columns)):
ocupadasCovid.append(df.values[i][x])
if df.values[i][1] == 'Camas UCI ocupadas no COVID-19':
for x in range(len(df.columns)):
ocupadasNoCovid.append(df.values[i][x])
fig = px.line(df,
y = [habilitadas, ocupadasCovid, ocupadasNoCovid],
x = range(len(fechas)), #I'm doing this because x = dates doesn't work
title='Camas por región: ('+region+')',)
fig.add_annotation(
x = 1, y = -0.1,
text = 'Fuente: Datos obtenidos desde el Ministerio de Ciencia.',
showarrow = False, xref='paper', yref='paper',
xanchor='right', yanchor='auto', xshift=0, yshift=-20
)
fig.update_layout(
legend_title_text='Estado de cama',
xaxis_title="Días",
yaxis_title="Cantidad de camas",
)
fig.show()
camasRegion()
You can't use dates, because df.columns besides dates contains strings Region and Serie. I simplified your code, it also made it more readable. Try this and let me know, if it still not working for you.
import pandas as pd
import plotly.graph_objects as go
import numpy as np
def camasRegion():
df = pd.read_csv('https://raw.githubusercontent.com/MinCiencia/Datos-COVID19/master/output/producto52/Camas_UCI.csv')
region = "Ñuble"
target_region = df.query('Region == #region').drop('Region', axis=1).set_index('Serie').T
chart = []
for i in target_region:
if i != 'Camas base (2019)': #or you can easily drop it from your dataset
chart += [go.Scatter(x=target_region.index,y=target_region[i], name=i, mode='lines')]
fig = go.Figure(chart)
fig.update_layout(title={'text':f'Camas por región: ({region})', 'x':.45},
template='plotly_white', hovermode='x',
legend_title_text='Estado de cama',
xaxis_title="Días",
yaxis_title="Cantidad de camas")
fig.add_annotation(
x = 1, y = -0.1,
text = 'Fuente: Datos obtenidos desde el Ministerio de Ciencia.',
showarrow = False, xref='paper', yref='paper',
xanchor='right', yanchor='auto', xshift=0, yshift=-20
)
fig.show()
camasRegion()
The result:

Interference between the Matplotlib Graphs in Tkinter GUI

I learned how to embed a matploblib graph into a Tkinter GUI via this post https://matplotlib.org/examples/user_interfaces/embedding_in_tk.html. It seems working fine.
However, I had a problem with getting multiple matplotlib graphs to work correctly simultaneously, let me explain a bit more here. The code below generates two buttons, each links to a new window with two new buttons (load data and plot data). You may generate some dummy two column data, say data1.txt, data2.txt, data3.txt, data4.txt, for plotting. What I observed is (1) If I invoke the window separately, I have no problem loading and plotting data1.txt, data2.txt, data3.txt, data4.txt. However, if I open the two windows at the same time, I can only plot freely and correctly in the second window, while the first window plots nothing. It seems as if the first window were suppressed by the existence of the second.
Can anyone help me understand what is happening here. My matplotlib version is 2.0.2. Tkinter version is $Revision:81008$. Python version 2.7.15. Thank you!
from Tkinter import *
import Tkinter as tk
import ttk
import tkFileDialog
import numpy
##loading matplotlib modules
import matplotlib
matplotlib.use("TkAgg")
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
import matplotlib.gridspec as gridspec
class Overall_Look:
def __init__(self, master):
self.master = master
self.top_frame = ttk.Frame(self.master, padding = (10, 10))
self.top_frame.pack()
##here are the layout for step 1, load structure files
ttk.Button(self.top_frame, text = "Button_1", command = self.plot_one,
style = "TButton").grid(row = 1, column = 0, columnspan = 2, padx = 5, sticky = "sw")
ttk.Button(self.top_frame, text = "Button_2",command = self.plot_two,
style = "TButton").grid(row = 1, column = 2, columnspan = 2, padx = 5, sticky = "sw")
def plot_one(self):
self.plot_one = tk.Toplevel(self.master)
self.GUI = Plot_One(self.plot_one)
def plot_two(self):
self.plot_two = tk.Toplevel(self.master)
self.GUI = Plot_Two(self.plot_two)
class Plot_One():
def __init__(self, master):
self.master = master
self.top_frame = ttk.Frame(self.master, padding = (10, 10))
self.top_frame.pack()
##here are the layout for step 1, load structure files
ttk.Button(self.top_frame, text = "Load Data 1", command = self.load_data_1,
style = "TButton").grid(row = 1, column = 0, columnspan = 2, padx = 5, sticky = "sw")
ttk.Button(self.top_frame, text = "Plot Data 1",command = self.start_plot_one,
style = "TButton").grid(row = 1, column = 2, columnspan = 2, padx = 5)
self.bottom_frame = ttk.Frame(self.master, padding = (10, 10))
self.bottom_frame.pack()
self.fig_1 = plt.figure(figsize=(5, 5), dpi=100) ##create a figure; modify the size here
self.fig_1.add_subplot(111)
self.fig_1.tight_layout()
self.canvas = FigureCanvasTkAgg(self.fig_1, master = self.bottom_frame)
self.canvas.show()
self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
self.toolbar = NavigationToolbar2TkAgg(self.canvas, self.bottom_frame)
self.toolbar.update()
self.canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
def load_data_1(self):
self.data_1 = tkFileDialog.askopenfilename(defaultextension = ".txt",
filetypes = [("Text Documents", "*.txt")])
def start_plot_one(self):
data = numpy.loadtxt(self.data_1).transpose()
x = data[0]
y = data[1]
self.fig_1.clf()
self.fig_1.add_subplot(111)
plt.plot(x, y, 'b-', lw=2)
self.fig_1.tight_layout()
self.canvas.draw()
class Plot_Two():
def __init__(self, master):
self.master = master
self.top_frame = ttk.Frame(self.master, padding = (10, 10))
self.top_frame.pack()
##here are the layout for step 1, load structure files
ttk.Button(self.top_frame, text = "Load Data 2", command = self.load_data_2,
style = "TButton").grid(row = 1, column = 0, columnspan = 2, padx = 5, sticky = "sw")
ttk.Button(self.top_frame, text = "Plot Data 2",command = self.start_plot_two,
style = "TButton").grid(row = 1, column = 2, columnspan = 2, padx = 5)
self.bottom_frame = ttk.Frame(self.master, padding = (10, 10))
self.bottom_frame.pack()
self.fig_2 = plt.figure(figsize=(5, 5), dpi=100) ##create a figure; modify the size here
self.fig_2.add_subplot(111)
self.fig_2.tight_layout()
self.canvas = FigureCanvasTkAgg(self.fig_2, master = self.bottom_frame)
self.canvas.show()
self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
self.toolbar = NavigationToolbar2TkAgg(self.canvas, self.bottom_frame)
self.toolbar.update()
self.canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
def load_data_2(self):
self.data_2 = tkFileDialog.askopenfilename(defaultextension = ".txt",
filetypes = [("Text Documents", "*.txt")])
def start_plot_two(self):
data = numpy.loadtxt(self.data_2).transpose()
x = data[0]
y = data[1]
self.fig_2.clf()
self.fig_2.add_subplot(111)
plt.plot(x, y, 'b-', lw=2)
self.fig_2.tight_layout()
self.canvas.draw()
def main():
root = Tk()
GUI = Overall_Look(root)
root.mainloop()
if __name__ == "__main__": main()

how can i make my figure made by matplotlib response to a mouse click event?

I read the document of matplotlib and write the following code, it supposed to capture my mouse event and move the grey line position when i clicked. I read this code in jupiter notebook online, it stop to show the coordinate of my cursor as it usually do, What's happend? Can anyone help me?
import pandas as pd
import numpy as np
import matplotlib.colors as mcol
import matplotlib.cm as cm
from scipy import stats
from matplotlib.lines import Line2D
import matplotlib.pyplot as plt
import scipy.spatial as spatial
np.random.seed(12345)
df = pd.DataFrame([np.random.normal(33500,150000,3650),
np.random.normal(41000,90000,3650),
np.random.normal(41000,120000,3650),
np.random.normal(48000,55000,3650)],
index=[1992,1993,1994,1995])
fig, ax = plt.subplots()
year_avg = df.mean(axis = 1)
year_std = df.std(axis = 1)
yerr = year_std / np.sqrt(df.shape[1]) * stats.t.ppf(1-0.05/2, df.shape[1]-1)
bars=ax.bar(range(df.shape[0]), year_avg, yerr = yerr, color = 'lightslategrey')
threshold=42000
line=plt.axhline(y = threshold, color = 'grey', alpha = 0.5)
cm1 = mcol.LinearSegmentedColormap.from_list("CmapName",["yellow", "orange", "red"])
cpick = cm.ScalarMappable(cmap=cm1)
percentages = []
cpick.set_array([])
def setColor(bars, yerr,threshold):
for bar, yerr_ in zip(bars, yerr):
low = bar.get_height() - yerr_
high = bar.get_height() + yerr_
percentage = (high-threshold)/(high-low)
if percentage>1: percentage = 1
if percentage<0: percentage=0
percentages.append(percentage)
cpick.to_rgba(percentages)
bars = ax.bar(range(df.shape[0]), year_avg, yerr = yerr, color = cpick.to_rgba(percentages))
return bars
line=plt.axhline(threshold, color = 'grey', alpha = 0.5)
setColor(bars, yerr,threshold)
plt.colorbar(cpick, orientation='horizontal')
plt.xticks(range(df.shape[0]), df.index)
fig = plt.figure()
plt.show()
def onclick(event):
print('%s click: button=%d, x=%d, y=%d, xdata=%f, ydata=%f' %
('double' if event.dblclick else 'single', event.button,
event.x, event.y, event.xdata, event.ydata))
line.set_ydata(event.ydata)
#plt.draw()
cid = fig.canvas.mpl_connect('button_press_event', onclick)

Matplotlib - plot wont show up

I want to plot a function graph (using matplotlib) when a button is pressed, to do so I wrote the following code:
##--IMPORT
#Tkinter
from tkinter import Tk, ttk
from tkinter import Frame, LabelFrame, Button
from tkinter import FALSE
#Numpy
from numpy import linspace
#Sympy
from sympy import symbols,sympify,diff,N,log
#MathPlotLib
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
_x = symbols("x")
_sympyFunction = None
_SP_mainSubPlot = None
def pr_draw(plotToDrawTo):
_sympyFunction = sympify("log(x) + x")
valuesRange = linspace(0.01, 3, 100)
x = []
y = []
#Calculate y and x values
for i in range(0, len(valuesRange)):
tempValue = N(_sympyFunction.subs(_x,valuesRange[i]))
x.append(float(valuesRange[i]))
y.append(float(tempValue))
#Draw function graph
plotToDrawTo.plot(x,y)
##--MAIN
if __name__== "__main__":
_root = Tk()
_root.title("Grafico Approsimativo")
_root.resizable(width = FALSE, height = FALSE)
_mainFrame = Frame(_root, bg = "black")
_mainFrame.pack(fill = "both", expand = True)
#Frames
#Main Left
_F_LeftMainFrame = Frame(_mainFrame)
_F_LeftMainFrame.grid(row = 0, column = 0, sticky = "nw")
_F_RightMainFrame = Frame(_mainFrame, bg = "violet")
_F_RightMainFrame.grid(row = 0, column = 2, sticky = "ne")
#Left Content--------------------------
_B_calculate = Button(_F_LeftMainFrame, text = "Draw", command = lambda: pr_draw(_SP_mainSubPlot))
_B_calculate.grid(row = 0, column = 0, padx = 5, pady = 5, sticky = "w")
#Right Content--------------------------
_F_mainPlotWindow = Figure(figsize = None, dpi = 100)
_SP_mainSubPlot = _F_mainPlotWindow.add_subplot(111)
_SP_mainSubPlot.grid(True)
#HERE
#Set master frame for Figure Obj
canvas = FigureCanvasTkAgg(_F_mainPlotWindow, master = _F_RightMainFrame)
canvas.get_tk_widget().pack()
The problem here is that when the button is pressed, nothing shows up in the plot window, the only way I could get this to work is by calling pr_draw(_SP_mainSubPlot) where I inserted the #HERE line: If the function is called there it will work, but not from the button., why?
You would need to redraw the canvas after you have plotted to it.
Adding the line
plotToDrawTo.figure.canvas.draw_idle()
at the end of your pr_draw function should do that.
Note that I also had to add _root.mainloop() at the end of the script to actually show the window.

Tkinter input for pyplot graph

I am very new to Python(coming from C/C++) and I have some trouble getting this little program to work.
It will get some market date from yahoo and print out two graphs. The graphs were working at first and then I added the tkinter input window. Just press "submit" and "print". The problem is that the graphs are not plotted, I assume it has sth to do with the tkinter not finishing or that it cannot open a second window anymore, any help would be highly appreciated
import pandas.io.data as web
import pandas as pd
import numpy as np
import datetime
import math
import matplotlib.pyplot as plt
import random
from itertools import accumulate
from tkinter import *
from pandas.io.data import DataReader
#Functions
def VWAP(data):
return(np.cumsum(data.Bought*data.Close)/
np.cumsum(data.Bought)).round(2)
def Print():
df2 = web.DataReader(conversion.moniker, 'yahoo', conversion.start_date, conversion.end_date)
df2['30_SMA_Close'] = pd.stats.moments.rolling_mean(df2['Close'], 30)
df2['150_SMA_Close'] = pd.stats.moments.rolling_mean(df2['Close'], 150)
df2["Bought"] = pd.Series(np.random.randint(1,1000,len(df2.index)), index=df2.index)
df2["vwap"] = pd.Series(VWAP(df2), index=df2.index)
#print("VWAP : ", df2["vwap"])
print("----------------PLOT-----------------")
top = plt.subplot2grid((6,6), (0, 0), rowspan=3, colspan=6)
top.plot(df2.index, df2["Close"], label='Close')
top.plot(df2.index, df2['30_SMA_Close'], label='30 Day SMA')
top.plot(df2.index, df2['150_SMA_Close'], label='150 Day SMA')
top.plot(df2.index, df2['vwap'], label='VWAP',color='k',linestyle="--")
plt.title('S&P Price from 2007 - 2012')
plt.legend(loc='upper left', numpoints = 1, prop={'size':7})
bottom = plt.subplot2grid((6,6), (4,0), rowspan=2, colspan=6)
bottom.bar(df2.index, df2['Volume'])
plt.title('S&P Trading Volume in Millions')
plt.gcf().set_size_inches(15,8)
print("----------------PLOT END-----------------")
def conversion():
print("Data conversion")
conversion.moniker = e1.get()
conversion.start_date = datetime.datetime.strptime(e2.get(),'%Y-%m-%d')
conversion.end_date = datetime.datetime.strptime(e3.get(),'%Y-%m-%d')
master = Tk()
Label(master, text="Moniker Name").grid(row=0)
Label(master, text="Start Date").grid(row=1)
Label(master, text="End Date").grid(row=2)
e1 = Entry(master)
e1.insert(10,"SPY")
e2 = Entry(master)
e2.insert(10,"2010-12-31")
e3 = Entry(master)
e3.insert(10,"2014-01-01")
e1.grid(row=0, column=1)
e2.grid(row=1, column=1)
e3.grid(row=2, column=1)
def close_window (): master.destroy()
Button(master, text='Cancel', command=close_window).grid(row=3, column=0, sticky=W, pady=4)
Button(master, text='Submit', command=conversion).grid(row=3, column=1, sticky=W, pady=4)
Button(master, text='Print', command=Print).grid(row=3, column=2, sticky=W, pady=4)
#df2 = web.DataReader(conversion.moniker, 'yahoo', conversion.start_date, conversion.end_date)
#df2 = web.DataReader(conversion.moniker, 'yahoo',datetime.datetime(2010,1,1),datetime.datetime(2014,1,1) )
#mainloop( )
master.destroy()
I can't run all code because I don't have some modules
but if I press submit and then print I got some graph.
I changed almost nothing.
EDIT: I found problem - you need plt.show() before print('PLOT END')
Here my code with mods
button Print calls conversion so I don't need button Submit
dates in plot title.
.
import pandas as pd
import pandas.io.data as web
import numpy as np
import datetime
#import math
import matplotlib.pyplot as plt
import random
#from itertools import accumulate
from tkinter import *
from pandas.io.data import DataReader
#Functions
def VWAP(data):
return(np.cumsum(data.Bought*data.Close)/
np.cumsum(data.Bought)).round(2)
def ploting():
conversion()
df2 = web.DataReader(conversion.moniker, 'yahoo', conversion.start_date, conversion.end_date)
df2['30_SMA_Close'] = pd.stats.moments.rolling_mean(df2['Close'], 30)
df2['150_SMA_Close'] = pd.stats.moments.rolling_mean(df2['Close'], 150)
df2["Bought"] = pd.Series(np.random.randint(1,1000,len(df2.index)), index=df2.index)
df2["vwap"] = pd.Series(VWAP(df2), index=df2.index)
#print("VWAP : ", df2["vwap"])
print("----------------PLOT-----------------")
top = plt.subplot2grid((6,6), (0, 0), rowspan=3, colspan=6)
print top.plot(df2.index, df2["Close"], label='Close')
print top.plot(df2.index, df2['30_SMA_Close'], label='30 Day SMA')
print top.plot(df2.index, df2['150_SMA_Close'], label='150 Day SMA')
print top.plot(df2.index, df2['vwap'], label='VWAP',color='k',linestyle="--")
print plt.title('S&P Price from %s - %s' % (e2.get(), e3.get()))
print plt.legend(loc='upper left', numpoints = 1, prop={'size':7})
bottom = plt.subplot2grid((6,6), (4,0), rowspan=2, colspan=6)
print bottom.bar(df2.index, df2['Volume'])
print plt.title('S&P Trading Volume in Millions')
print plt.gcf().set_size_inches(15,8)
print plt.show() # <---- HERE
print("----------------PLOT END-----------------")
def conversion():
print("Data conversion")
conversion.moniker = e1.get()
conversion.start_date = datetime.datetime.strptime(e2.get(),'%Y-%m-%d')
conversion.end_date = datetime.datetime.strptime(e3.get(),'%Y-%m-%d')
#-----------------------------------------------------------------------------
def close_window ():
master.destroy()
master = Tk()
Label(master, text="Moniker Name").grid(row=0)
Label(master, text="Start Date").grid(row=1)
Label(master, text="End Date").grid(row=2)
e1 = Entry(master)
e1.insert(10,"SPY")
e2 = Entry(master)
e2.insert(10,"2010-12-31")
e3 = Entry(master)
e3.insert(10,"2014-01-01")
e1.grid(row=0, column=1)
e2.grid(row=1, column=1)
e3.grid(row=2, column=1)
Button(master, text='Cancel', command=close_window).grid(row=3, column=0, sticky=W, pady=4)
#Button(master, text='Submit', command=conversion).grid(row=3, column=1, sticky=W, pady=4)
Button(master, text='Plot', command=ploting).grid(row=3, column=2, sticky=W, pady=4)
#df2 = web.DataReader(conversion.moniker, 'yahoo', conversion.start_date, conversion.end_date)
#df2 = web.DataReader(conversion.moniker, 'yahoo', datetime.datetime(2010,1,1),datetime.datetime(2014,1,1) )
master.mainloop()
2008-12-31 - 2013-01-01
1998-12-31 - 2004-01-01