How do I create a zoom slider for a bokeh animation? - python-3.x

I want to have slider widget to zoom in and out of a bokeh animation. The slider should zoom to a specific point in the figure (for example (100,123)) and have a maximum and minimum zoom level.
I am using curdoc() and bokeh server.
I was wondering how someone with more experience would do that.
thanks

This is a very simple example which you can further customise and improve. Position your point of interest in the middle e.g. (50, 50) and move the slider. This code works for Bokeh v1.0.4
import numpy as np
from bokeh.plotting import figure, show, curdoc
from bokeh.models import Slider, CustomJS, Range1d
from bokeh.layouts import column
slider_zoom = Slider(title = 'Zoom', start = -12, end = 8, value = 0, step = 1)
zoom_value = slider_zoom.value
x = np.linspace(-40, 40, 200)
y = x
p = figure(title = "Zoom Slider", plot_height = 500, plot_width = 600, y_range = Range1d(start = -40, end = 40), background_fill_color = '#efefef')
r = p.line(x, y, color = "red", line_width = 1.5, alpha = 0.8)
r = p.circle(x, y, color = "blue", line_width = 0.5, alpha = 0.8)
last_value = None
def update(attr, old, new):
global last_value
if last_value is not None:
if new > 0:
if new > last_value:
p.y_range.start = p.y_range.start + new
p.y_range.end = p.y_range.end - new
p.x_range.start = p.x_range.start + new
p.x_range.end = p.x_range.end - new
else:
p.y_range.start = p.y_range.start - new
p.y_range.end = p.y_range.end + new
p.x_range.start = p.x_range.start - new
p.x_range.end = p.x_range.end + new
elif new < 0:
if new < last_value:
p.y_range.start = p.y_range.start + new
p.y_range.end = p.y_range.end - new
p.x_range.start = p.x_range.start + new
p.x_range.end = p.x_range.end - new
else:
p.y_range.start = p.y_range.start - new
p.y_range.end = p.y_range.end + new
p.x_range.start = p.x_range.start - new
p.x_range.end = p.x_range.end + new
last_value = new
slider_zoom.on_change('value', update)
layout = column(p, slider_zoom)
curdoc().add_root(layout)
Result:

Related

New FigureCanvasTkAgg always keeps a black border

I want to show some figures using tkinter, but new FigureCanvasTkAgg always keeps a black border. For example, I want to build two figures with red borders, but the new one has a black border, just like this:
enter image description here
But when the display window is not active, the black border disappear:
enter image description here
How to solve this problem? Thank you!
Here's the code:
import tkinter as tk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
class display_window:
def __init__(self, width = 1024, height = 768):
self.figure_dict = {}
self.display_level = tk.Tk()
screen_width = self.display_level.winfo_screenwidth()
screen_height = self.display_level.winfo_screenheight()
init_position_x = int((screen_width - width) / 2)
init_position_y = int((screen_height - height) / 2)
position = str(width) + 'x' + str(height) + '+' + str(init_position_x) + '+' + str(init_position_y)
self.display_level.geometry(position)
self.x_offset = 120
self.y_offset = 10
self.figures_interval = 10
new_figure_button = tk.Button(self.display_level, text='new figure', command=self.new_figure_callback)
new_figure_button.place(x=5, y=5)
def new_figure_callback(self):
fig = Figure(figsize=(3, 2), dpi=100)
fig_plot = fig.add_subplot(111)
fig_plot.grid()
figure_canvas = FigureCanvasTkAgg(fig, self.display_level)
figure_widget = figure_canvas.get_tk_widget()
figure_widget.config(highlightthickness = 2, highlightbackground = "red", cursor='cross')
self.figure_dict[figure_widget] = {
"fig": fig,
"fig_plot": fig_plot,
"figure_canvas": figure_canvas,
}
self.arrange_figures(self.x_offset, self.y_offset, self.figures_interval)
def arrange_figures(self, x_offset, y_offset, figures_interval):
figures_area_width = self.display_level.winfo_width() - x_offset - figures_interval
figures_area_height = self.display_level.winfo_height() - y_offset - figures_interval
figure_count = len(self.figure_dict)
figure_width = figures_area_width
figure_height = (figures_area_height - figures_interval * (figure_count - 1)) / figure_count
for i, it in enumerate(self.figure_dict.keys()):
it.config(height = figure_height, width = figure_width)
it.place(x = x_offset, y = y_offset + i * (figure_height + figures_interval))
if __name__ == '__main__':
display_window()
tk.mainloop()
I want all the figures' borders display as in the config function.

Matplotlib update bbox position

I have a code to make a custom pie chart that moves the annotations when it detects a colision on their bboxes.
I want to move the bbox (and thus the text) to avoid the texting overlaping.
I already detect the colision but when I use the “set_points” method it doesn’t update my figure.
The code is as it follows:
fig, ax = plt.subplots(figsize=(6, 3), subplot_kw=dict(aspect="equal"))
wedges, texts = ax.pie(
np.array(values) / sum(values),
wedgeprops=dict(width=0.5),
startangle=startAngle,
colors=color_map,
)
# bbox_props=dict(facecolor='none', edgecolor='none')
bbox_props = dict(boxstyle="square,pad=0.3", fc="w", ec="k", lw=0.72)
kw = dict(arrowprops=dict(arrowstyle="-"), bbox=bbox_props, zorder=0, va="center")
annot_bbox_list = []
for i, p in enumerate(wedges):
ang = (p.theta2 - p.theta1) / 2.0 + p.theta1
y = np.sin(np.deg2rad(ang))
x = np.cos(np.deg2rad(ang))
horizontalalignment = {-1: "right", 1: "left"}[int(np.sign(x))]
connectionstyle = "angle,angleA=0,angleB={}".format(ang)
kw["arrowprops"].update({"connectionstyle": connectionstyle})
actual_annot = ax.annotate(
labels[i] + f" {values[i]:.1%}",
xy=(x, y),
xytext=(1.35 * np.sign(x), 1.4 * y),
horizontalalignment=horizontalalignment,
**kw,
)
actual_bbox = actual_annot.get_window_extent(renderer=fig.canvas.get_renderer())
for (annot, bbox) in annot_bbox_list:
intersect, move = bbox_intersection(bbox, actual_bbox, margin=10)
if intersect:
print(f'{annot.get_text()} e {actual_annot.get_text()} intersectam, movendo a segunda em {move}')
#fig.canvas.draw()
points = actual_bbox.get_points()#.copy()
print('pontos da caixa2 :\n {}'.format(points))
points[0][1] += move
points[1][1] += move
print('pontos novos da caixa2 :\n {}'.format(points))
renderer=fig.canvas.get_renderer()
#actual_annot.update_positions(renderer)
#fig.canvas.draw()
actual_bbox.set_points(points)
fig.draw(renderer)
annot_bbox_list.append((actual_annot, actual_bbox))
diff += np.sign(x)
dict_angulos[startAngle] = diff

Tk Canvas(Python) : How to get the size (width, height) and coordinates of the entire range that Canvas can move with the scroll bar

I want to get the canvas area, coordinates and width and height that can be moved with the scroll bar.
That is the part in red in the explanation image.
Is there no choice but to calculate from Scrollbar.get()? I think that an error will occur in this calculation.
Add Information
I want to properly change the canvas display area and scroll bar when the widget to be operated on the canvas is changed by key operation or button operation and the widget exists outside the displayed canvas area.
Also, when I move the widget by mouse dragging it outside the canvas display area, I want the canvas display area to follow the display area smoothly.
The sources for moving the canvas area by mouse drag are as follows:
import tkinter as tk
class TkCanvas():
def __init__(self):
self.canvas_w, self.canvas_h = 600, 600
self.interval = 1000
self.ldrag = False
self.select_cube = None
self.cube = list()
self.create_cube_coord = [0,0,0,0]
self.sx, self.sy = None, None
self.root = tk.Tk()
frame = tk.Frame(self.root)
frame.pack(fill=tk.BOTH, expand=1)
self.canvas = tk.Canvas(frame, width=self.canvas_w, height=self.canvas_h,
relief=tk.SUNKEN, borderwidth=2, bg='green')
self.canvas.grid(row=0, column=0, sticky= tk.N+tk.E+tk.W+tk.S)
self.xscroll = tk.Scrollbar(frame, orient=tk.HORIZONTAL, command=self.canvas.xview)
self.xscroll.grid(row=1, column=0, sticky=tk.E+tk.W)
self.yscroll = tk.Scrollbar(frame, orient=tk.VERTICAL, command=self.canvas.yview)
self.yscroll.grid(row=0, column=1, sticky=tk.N+tk.S)
self.canvas.config(xscrollcommand=self.xscroll.set, yscrollcommand=self.yscroll.set)
frame.grid_rowconfigure(0, weight=1, minsize=0)
frame.grid_columnconfigure(0, weight=1, minsize=0)
self.canvas.bind('<Button-1>',self.left_click)
self.canvas.bind('<Motion>',self.move)
self.canvas.bind('<ButtonRelease-1>',self.left_release)
self.canvas.bind('<Button-3>',self.right_click)
self.canvas.bind('<MouseWheel>',self.wheel)
self.root.after(self.interval,self.run)
self.root.mainloop()
def run(self):
self.root.after(self.interval,self.run)
return
def left_click(self,event):
canvas = self.canvas
x = canvas.canvasx(event.x)
y = canvas.canvasy(event.y)
oid_list = canvas.find_overlapping(x,y,x,y)
if oid_list:
oid_list = list(oid_list)
sorted(oid_list,reverse=True)
self.select_cube = oid_list[-1]
canvas.itemconfigure(
self.select_cube,
fill='skyblue',
outline='blue',
)
self.sx, self.sy = x, y
else:
self.ldrag = True
self.create_cube_coord = [x,y,x,y]
cube = canvas.create_rectangle(
self.create_cube_coord,
fill='pink',
outline='red',
)
self.cube.append(cube)
return
def right_click(self,event):
canvas = self.canvas
x = canvas.canvasx(event.x)
y = canvas.canvasy(event.y)
if not self.ldrag:
oid_list = canvas.find_overlapping(x,y,x,y)
if oid_list:
oid_list = list(oid_list)
sorted(oid_list,reverse=True)
sel = oid_list[-1]
canvas.delete(sel)
index = self.cube.index(sel)
self.cube.pop(index)
self.canvas_scroll_regset()
return
def move(self,event):
canvas = self.canvas
x = canvas.canvasx(event.x)
y = canvas.canvasy(event.y)
if self.ldrag:
px, py = self.create_cube_coord[0],self.create_cube_coord[1]
sx, sy = min(x,px),min(y,py)
ex, ey = max(x,px),max(y,py)
if self.cube.append:
canvas.coords(self.cube[-1],sx, sy, ex, ey)
self.canvas_scroll_regset()
else:
if self.select_cube:
dx = x - self.sx
dy = y - self.sy
canvas.move(self.select_cube,dx,dy)
self.sx, self.sy = x, y
self.canvas_scroll_regset()
return
def wheel(self,event):
self.canvas.yview_scroll(int(-1*(event.delta/120)), "units")
return
def canvas_scroll_regset(self):
canvas = self.canvas
box_coords = canvas.bbox("all")
if box_coords:
ox0, oy0, ox1, oy1 = box_coords
sx = canvas.winfo_x()
sy = canvas.winfo_y()
sw = canvas.winfo_width()
sh = canvas.winfo_height()
cx0 = canvas.canvasx(sx)
cy0 = canvas.canvasy(sy)
cx1 = canvas.canvasx(sx)+sw-1
cy1 = canvas.canvasy(sy)+sh-1
if cx0 < 0:
cx1 -= cx0
cx0 -= cx0
if cy0 < 0:
cy1 -= cy0
cy0 -= cy0
if ox0 < cx0:
sc_x0 = ox0
else:
sc_x0 = cx0
if oy0 < cy0:
sc_y0 = oy0
else:
sc_y0 = cy0
if ox1 > cx1:
sc_x1 = ox1
else:
sc_x1 = cx1
if oy1 > cy1:
sc_y1 = oy1
else:
sc_y1 = cy1
if (sc_x0, sc_y0, sc_x1, sc_y1) != (cx0, cy0, cx1, cy1):
canvas['scrollregion'] = (sc_x0, sc_y0, sc_x1, sc_y1)
else:
canvas['scrollregion'] = (0,0,0,0)
x_f, x_l = self.xscroll.get()
y_f, y_l = self.yscroll.get()
canvas_w, canvas_h = sw/(x_l-x_f)-1, sh/(y_l-y_f)-1
if int(canvas_w) > int(sw):
if x_f > 0.0:
canvas.xview(tk.MOVETO,0.0)
elif x_l < 0.99:
canvas.xview(tk.MOVETO,1.0)
print('x:',x_f, x_l)
if int(canvas_h) > int(sh):
print('y:',y_f, y_l)
def left_release(self,event):
canvas = self.canvas
if self.ldrag:
canvas.itemconfigure(
self.cube[-1],
fill='lightgreen',
outline='green',
)
self.ldrag = False
else:
if self.select_cube:
canvas.itemconfigure(
self.select_cube,
fill='lightgreen',
outline='green',
)
self.select_cube = None
return
t = TkCanvas()
The movement of the canvas area is rattling.

How to calcul tangente with Bokeh callback custom JS?

I have to make a graphic with a function, his derivative and the tangent.
I'm exercising on python with Bokeh library.
I've tried multiple different calcul to get the tangent. To change the variables,function but without any success.
import numpy as np
from bokeh.layouts import row, widgetbox
from bokeh.models import CustomJS, Slider
from bokeh.plotting import figure, output_file, show, ColumnDataSource
#First Curve
x = np.linspace(-10, 10)
a = -10
y = (x**3)-12*x
#fonction
def f(x):
return ((x**3)-12*x)
def fprime(x):
return ((3*x**2)-12)
yprime = fprime(x)
#prepare list of value for tan
ytan = []
yprimetan = []
tan = []
for a in range (-25,25):
y1 = f(a)
y2= fprime(a)
y3 = y1 * a + y2
ytan.append(y1)
yprimetan.append(y2)
tan.append(y3)
print('liste y ',ytan)
print('liste yprime ',yprimetan)
print('liste tan ',tan)
source = ColumnDataSource(data=dict(x=x,y=ytan))
plot = figure(y_range=(-50, 50), plot_width=800, plot_height=800)
plot.line('x','y', source=source, line_width=3,legend= 'Fonction', line_alpha=0.6)
callback = CustomJS(args=dict(source=source), code="""
var data = source.data;
var A = amp.value;
var B = offset.value;
var x = data['x']
var y = data['y']
for (var i = -10; i < x.length; i++) {
y[i] = B + A *((x[i]**3)-12*x[i]);
}
source.change.emit();
""")
amp_slider = Slider(start=-10, end=10, value=1, step=.1,
title="Amplitude", callback=callback)
callback.args["amp"] = amp_slider
offset_slider = Slider(start=-10, end=10, value=0, step=.1,
title="Offset", callback=callback)
callback.args["offset"] = offset_slider
#Second Curve dérivé
source2 = ColumnDataSource(data=dict(x=x, y=yprimetan))
plot.line('x', 'y', source=source2, line_width=3,legend= 'Dérivé', line_alpha=0.6,color='red')
#Third Curve Tan
source3 = ColumnDataSource(data=dict(x=x,tan=tan,yprime=yprimetan,y=tan))
plot.line('x','tan', source=source3,legend= 'Tangente', line_width=3, line_alpha=0.6,color='green')
callback = CustomJS(args=dict(source=source3), code="""
var data = source.data;
var Z = tangente.value;
var y = data['y']
var yprime = data['yprime']
var tan = data['tan']
var x = data['x']
for (var i = -10; i < x.length; i++) {
tan[i] = yprime[i] * (x[i]-Z) + y[i] ;
}
source.change.emit();
""")
#tan[i]= (3*(x[i]**2)-12) * (Z-x[i]) + ((x[i]**3)-12*x[i])
tan_slider = Slider(start=-10, end=10, value=1, step=.1,
title="Tangente", callback=callback)
callback.args["tangente"] = tan_slider
#Output
layout = row(
plot,
widgetbox(amp_slider, offset_slider,tan_slider),
)
output_file("slider.html", title="slider.py example")
show(layout)
I expect to have a tangent that i can move through the curve.
You can execute the code to see the graphic i have for the moment.

Display multiple images in PIL

-------------------------------Solved(Partially)----------------------------------------
My problem is that when I try to display multiple images on the canvas using PIL, I end up with only the last image.
All the images have slightly different characteristics(angle offset). Also the having a plethora of entries, I have to use a loop for sure. Also I'll need to use PIL(tkinter objects not possible) for the angle offset feature.
Here is the code;
#!/usr/bin/python
# Filename: weather_sim.py
import os
import tkinter as tk
import h5py as hp
import numpy as np
import ntpath as ntp
from PIL import Image, ImageTk
from tkinter.filedialog import askopenfilename
def path_leaf(path):
head, tail = ntp.split(path)
return tail or ntp.basename(head)
class CoordFind:
def __init__(self):
self.LatPx = 0
self.LonPx = 0
def find_px(self, Lat, Lon):
self.LatPx = (Lat - LatN)/LatLc
self.LonPx = (Lon - LonW)/LonLc
class PlottingGUI(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.coord = CoordFind()
self.root = parent
self.root.wm_title("-|-|-|-|||Wind Vector Plotter|||-|-|-|-")
self.root.resizable(False, False)
self.path = "None Selected"
self.HaM = 0
self.Lat = 0
self.Lon = 0
self.WiD = 0
self.WiS = 0
self.fr = tk.Frame(self.root, width = (width+20), height = (height+20), bd = 2)
self.fr.grid(row = 1, column = 0)
self.frBro = tk.Frame(self.root, width = (width+20), height = 50, bd = 2)
self.frBro.grid(row = 0, column = 0)
self.frHi = tk.Frame(self.root, width = (width+20), height = 50, bd = 2)
self.frHi.grid(row = 2, column = 0)
self.cv = tk.Canvas(self.fr, width = width, height = height, background = "white", bd = 0, relief = tk.SUNKEN)
self.cv.grid(row = 0, column = 0)
self.cv.create_image(1, 1, anchor = "nw", image = photo)
self.broButton = tk.Button(self.frBro, text = "Browse Dsets", command = self.analyseDset, height = 3, width = 16, bg = "yellow")
self.broButton.grid(row = 0, column = 0, padx = 20)
self.selFile = tk.Label(self.frBro, text = self.path)
self.selFile.grid(row = 0, column = 1)
self.caution = tk.Label(self.frHi, text = "Optional use. Warning!!, May lead to lags in program", fg = "red")
self.caution.grid(row = 0, column = 1)
self.shoRedBut = tk.Button(self.frHi, text = "Show H1", command = self.show_barbs1().__next__, height = 3, width = 16, bg = "#FF0000", fg = "white", activebackground="#E533B5")
self.shoRedBut.grid(row = 1, column = 0, padx = 7, pady = 2)
self.shoGrnBut = tk.Button(self.frHi, text = "Show H2", command = self.show_barbs2().__next__, height = 3, width = 16, bg = "#00B400", fg = "white", activebackground="#B5E533")
self.shoGrnBut.grid(row = 1, column = 1, padx = 7, pady = 2)
self.shoBluBut = tk.Button(self.frHi, text = "Show H3", command = self.show_barbs3().__next__, height = 3, width = 16, bg = "#0000FF", fg = "white", activebackground="#33B5E5")
self.shoBluBut.grid(row = 1, column = 2, padx = 7, pady = 2)
self.desc1 = tk.Label(self.frHi, text = "100-250 hPa", fg = "white", bg = "black")
self.desc1.grid(row = 2, column = 0)
self.desc2 = tk.Label(self.frHi, text = "250-350 hPa", fg = "white", bg = "black")
self.desc2.grid(row = 2, column = 1)
self.desc3 = tk.Label(self.frHi, text = "350-700 hPa", fg = "white", bg = "black")
self.desc3.grid(row = 2, column = 2)
def analyseDset(self):
self.path = askopenfilename(filetypes = (("Dataset files", "*.h5")
,("All files", "*.*") ))
self.jfname = path_leaf(self.path)
self.selFile = tk.Label(self.frBro, text = self.jfname)
self.selFile.grid(row = 0, column = 1)
self.extDset()
def extDset(self):
hf = hp.File(self.path, 'r')
HaM = hf.get('HEIGHT_ASSIGNMENT_METHOD')
Lat = hf.get('Latitude')
Lon = hf.get('Longitude')
WiD = hf.get('WIND_DIRECTION')
WiS = hf.get('WIND_SPEED')
self.HaM = np.array(HaM)
self.Lat = np.array(Lat)/100
self.Lon = np.array(Lon)/100
self.WiD = np.array(WiD)
self.WiS = np.array(WiS)
self.BrbImR = np.empty((self.HaM.shape[0],1))
self.BrbImB = np.empty((self.HaM.shape[0],1))
def show_barbs1(self):
self.coord = CoordFind()
script_dir = os.path.dirname(os.path.abspath(__file__))
im = Image.open(os.path.join(script_dir, 'Red_Barbs\icons8-wind-speed-43-47-50.png'))
w, h = im.size
im = im.resize((int(w/2), int(h/2)), Image.ANTIALIAS)
vec_im = ImageTk.PhotoImage(im.rotate(45))
for i in range(0, self.HaM.shape[0]):
if self.HaM[i] == 0:
self.coord.find_px(self.Lat[i], self.Lon[i])
x = self.coord.LonPx
y = self.coord.LatPx
self.BrbImR[i] = self.cv.create_image(x, y, image = vec_im)
while True:
for i in range(0, self.HaM.shape[0]):
self.cv.itemconfigure(self.BrbImR[i], state = tk.NORMAL)
self.shoRedBut.configure(text = "Showing H1")
yield
def show_barbs2(self):
self.coord = CoordFind()
BrbImG = np.empty((self.HaM.shape[0],1))
script_dir = os.path.dirname(os.path.abspath(__file__))
im = Image.open(os.path.join(script_dir, 'Green_Barbs\icons8-wind-speed-43-47-50.png'))
w, h = im.size
im = im.resize((int(w/2), int(h/2)), Image.ANTIALIAS)
for i in range(0, self.HaM.shape[0]):
if self.HaM[i] == 1:
vec_im = ImageTk.PhotoImage(im.rotate(self.WiD[i]))
self.coord.find_px(self.Lat[i], self.Lon[i])
x = self.coord.LonPx
y = self.coord.LatPx
BrbImG[i] = self.cv.create_image(x, y, image = vec_im)
while True:
for i in range(0, self.HaM.shape[0]):
self.cv.itemconfigure(BrbImG[i], state = tk.NORMAL)
self.shoGrnBut.configure(text = "Showing H2")
yield
def show_barbs3(self):
self.coord = CoordFind()
script_dir = os.path.dirname(os.path.abspath(__file__))
im = Image.open(os.path.join(script_dir, 'Blue_Barbs\icons8-wind-speed-43-47-50.png'))
w, h = im.size
im = im.resize((int(w/2), int(h/2)), Image.ANTIALIAS)
vec_im = ImageTk.PhotoImage(im.rotate(180))
for i in range(0, self.HaM.shape[0]):
if self.HaM[i] == 2:
self.coord.find_px(self.Lat[i], self.Lon[i])
x = self.coord.LonPx
y = self.coord.LatPx
self.BrbImB[i] = self.cv.create_image(x, y, image = vec_im)
while True:
for i in range(0, self.HaM.shape[0]):
self.cv.itemconfigure(self.BrbImB[i], state = tk.NORMAL)
self.shoBluBut.configure(text = "Showing H3")
yield
if __name__ == "__main__":
root = tk.Tk()
backmap = "Map.png"
photo = ImageTk.PhotoImage(file = backmap)
width = photo.width()
height = photo.height()
LatN = 69.5
LatS = -69.3
LonE = 148.9
LonW = 1.0
LatLc = (LatS - LatN)/height
LonLc = (LonE - LonW)/width
app = PlottingGUI(root)
root.mainloop()
The output currently is this;(For the green arrows as that is what I have tested on)
This is what I want;(But with different angles)
I am using Python 3.6 on Windows 10.
Thanks in advance!!
P.S.: Also there is another problem if someone can help me with that. I would like to be able to choose a particular image based on a range factor(Wind Speed) by doing like a switch-case(or if-elif-else) procedure if possible. But when I try to do that it says "No such File or Directory". I may put it in another Question though.
-------------------------------Solved(Till this point)---------------------------------
EDIT: Solved the problem of displaying multiple arrows according to
choice and at different angles.
Here's the code;
#!/usr/bin/python
# Filename: weather_sim.py
import os
import tkinter as tk
import h5py as hp
import numpy as np
import ntpath as ntp
from PIL import Image, ImageTk
from tkinter.filedialog import askopenfilename
def path_leaf(path):
head, tail = ntp.split(path)
return tail or ntp.basename(head)
class CoordFind:
def __init__(self):
self.LatPx = 0
self.LonPx = 0
def find_px(self, Lat, Lon):
self.LatPx = (Lat - LatN)/LatLc
self.LonPx = (Lon - LonW)/LonLc
class PlottingGUI(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.coord = CoordFind()
self.root = parent
self.root.wm_title("-|-|-|-|||Wind Vector Plotter|||-|-|-|-")
self.root.resizable(False, False)
self.path = "None Selected"
self.HaM = 0
self.Lat = 0
self.Lon = 0
self.WiD = 0
self.WiS = 0
self.ima = []
self.fr = tk.Frame(self.root, width = (width+20), height = (height+20), bd = 2)
self.fr.grid(row = 1, column = 0)
self.frBro = tk.Frame(self.root, width = (width+20), height = 50, bd = 2)
self.frBro.grid(row = 0, column = 0)
self.frHi = tk.Frame(self.root, width = (width+20), height = 50, bd = 2)
self.frHi.grid(row = 2, column = 0)
self.cv = tk.Canvas(self.fr, width = width, height = height, background = "white", bd = 0, relief = tk.SUNKEN)
self.cv.grid(row = 0, column = 0)
self.cv.create_image(1, 1, anchor = "nw", image = photo)
self.broButton = tk.Button(self.frBro, text = "Browse Dsets", command = self.analyseDset, height = 3, width = 16, bg = "yellow")
self.broButton.grid(row = 0, column = 0, padx = 20)
self.selFile = tk.Label(self.frBro, text = self.path)
self.selFile.grid(row = 0, column = 1)
self.caution = tk.Label(self.frHi, text = "Optional use. Warning!!, May lead to lags in program", fg = "red")
self.caution.grid(row = 0, column = 1)
self.shoRedBut = tk.Button(self.frHi, text = "Show H1", command = self.show_barbs1().__next__, height = 3, width = 16, bg = "#FF0000", fg = "white", activebackground="#E533B5")
self.shoRedBut.grid(row = 1, column = 0, padx = 7, pady = 2)
self.shoGrnBut = tk.Button(self.frHi, text = "Show H2", command = self.show_barbs2().__next__, height = 3, width = 16, bg = "#00B400", fg = "white", activebackground="#B5E533")
self.shoGrnBut.grid(row = 1, column = 1, padx = 7, pady = 2)
self.shoBluBut = tk.Button(self.frHi, text = "Show H3", command = self.show_barbs3().__next__, height = 3, width = 16, bg = "#0000FF", fg = "white", activebackground="#33B5E5")
self.shoBluBut.grid(row = 1, column = 2, padx = 7, pady = 2)
self.desc1 = tk.Label(self.frHi, text = "100-250 hPa", fg = "white", bg = "black")
self.desc1.grid(row = 2, column = 0)
self.desc2 = tk.Label(self.frHi, text = "250-350 hPa", fg = "white", bg = "black")
self.desc2.grid(row = 2, column = 1)
self.desc3 = tk.Label(self.frHi, text = "350-700 hPa", fg = "white", bg = "black")
self.desc3.grid(row = 2, column = 2)
def analyseDset(self):
self.path = askopenfilename(filetypes = (("Dataset files", "*.h5")
,("All files", "*.*") ))
self.jfname = path_leaf(self.path)
self.selFile = tk.Label(self.frBro, text = self.jfname)
self.selFile.grid(row = 0, column = 1)
self.extDset()
def extDset(self):
hf = hp.File(self.path, 'r')
HaM = hf.get('HEIGHT_ASSIGNMENT_METHOD')
Lat = hf.get('Latitude')
Lon = hf.get('Longitude')
WiD = hf.get('WIND_DIRECTION')
WiS = hf.get('WIND_SPEED')
self.HaM = np.array(HaM)
self.Lat = np.array(Lat)/100
self.Lon = np.array(Lon)/100
self.WiD = np.array(WiD)
self.WiS = np.array(WiS)
self.BrbImR = np.empty((self.HaM.shape[0],1))
self.BrbImG = np.empty((self.HaM.shape[0],1))
self.BrbImB = np.empty((self.HaM.shape[0],1))
def barb_def(self, WiS):
if WiS < 1:
self.ima = "1.png"
elif WiS < 3:
self.ima = "2.png"
elif WiS < 8:
self.ima = "3.png"
elif WiS < 13:
self.ima = "4.png"
elif WiS < 18:
self.ima = "5.png"
elif WiS < 23:
self.ima = "6.png"
elif WiS < 28:
self.ima = "7.png"
elif WiS < 33:
self.ima = "8.png"
elif WiS < 38:
self.ima = "9.png"
elif WiS < 43:
self.ima = "10.png"
elif WiS < 48:
self.ima = "11.png"
elif WiS < 53:
self.ima = "12.png"
elif WiS < 58:
self.ima = "13.png"
elif WiS < 63:
self.ima = "14.png"
elif WiS < 68:
self.ima = "15.png"
elif WiS < 73:
self.ima = "16.png"
elif WiS < 78:
self.ima = "17.png"
elif WiS < 83:
self.ima = "18.png"
elif WiS < 88:
self.ima = "19.png"
elif WiS < 93:
self.ima = "20.png"
elif WiS < 98:
self.ima = "21.png"
elif WiS < 103:
self.ima = "22.png"
else:
self.ima = "23.png"
def show_barbs1(self):
self.coord = CoordFind()
vec_im = []
im = []
p = []
script_dir = os.path.dirname(os.path.abspath(__file__))
for i in range(0, self.HaM.shape[0]):
self.barb_def(self.WiS[i])
p.append("{}{}".format('Red_Barbs\\', self.ima))
im.append(Image.open(os.path.join(script_dir, p[i])))
w, h = im[i].size
im[i] = im[i].resize((int(w/2), int(h/2)), Image.ANTIALIAS)
vec_im.append(ImageTk.PhotoImage(im[i].rotate(self.WiD[i])))
for i in range(0, self.HaM.shape[0]):
if self.HaM[i] == 0:
self.coord.find_px(self.Lat[i], self.Lon[i])
x = self.coord.LonPx
y = self.coord.LatPx
self.BrbImR[i] = self.cv.create_image(x, y, image = vec_im[i])
while True:
for i in range(0, self.HaM.shape[0]):
self.cv.itemconfigure(self.BrbImR[i], state = tk.NORMAL)
self.shoRedBut.configure(text = "Showing H1")
yield
def show_barbs2(self):
self.coord = CoordFind()
vec_im = []
im = []
p = []
script_dir = os.path.dirname(os.path.abspath(__file__))
for i in range(0, self.HaM.shape[0]):
self.barb_def(self.WiS[i])
p.append("{}{}".format('Green_Barbs\\', self.ima))
im.append(Image.open(os.path.join(script_dir, p[i])))
w, h = im[i].size
im[i] = im[i].resize((int(w/2), int(h/2)), Image.ANTIALIAS)
vec_im.append(ImageTk.PhotoImage(im[i].rotate(self.WiD[i])))
for i in range(0, self.HaM.shape[0]):
if self.HaM[i] == 1:
self.coord.find_px(self.Lat[i], self.Lon[i])
x = self.coord.LonPx
y = self.coord.LatPx
self.BrbImG[i] = self.cv.create_image(x, y, image = vec_im[i])
while True:
for i in range(0, self.HaM.shape[0]):
self.cv.itemconfigure(self.BrbImG[i], state = tk.NORMAL)
self.shoGrnBut.configure(text = "Showing H2")
yield
def show_barbs3(self):
self.coord = CoordFind()
vec_im = []
im = []
p = []
script_dir = os.path.dirname(os.path.abspath(__file__))
for i in range(0, self.HaM.shape[0]):
self.barb_def(self.WiS[i])
p.append("{}{}".format('Blue_Barbs\\', self.ima))
im.append(Image.open(os.path.join(script_dir, p[i])))
w, h = im[i].size
im[i] = im[i].resize((int(w/2), int(h/2)), Image.ANTIALIAS)
vec_im.append(ImageTk.PhotoImage(im[i].rotate(self.WiD[i])))
for i in range(0, self.HaM.shape[0]):
if self.HaM[i] == 2:
self.coord.find_px(self.Lat[i], self.Lon[i])
x = self.coord.LonPx
y = self.coord.LatPx
self.BrbImB[i] = self.cv.create_image(x, y, image = vec_im[i])
while True:
for i in range(0, self.HaM.shape[0]):
self.cv.itemconfigure(self.BrbImB[i], state = tk.NORMAL)
self.shoBluBut.configure(text = "Showing H3")
yield
if __name__ == "__main__":
root = tk.Tk()
backmap = "Map.png"
photo = ImageTk.PhotoImage(file = backmap)
width = photo.width()
height = photo.height()
LatN = 69.5
LatS = -69.3
LonE = 148.9
LonW = 1.0
LatLc = (LatS - LatN)/height
LonLc = (LonE - LonW)/width
app = PlottingGUI(root)
root.mainloop()
But this ended up having a new problem. One set of coloured arrows is showing at a time but when I click the button to display another set it goes "Python stopped working because of some error" and then the shell restarts. Don't know what's the prob though.

Resources