Code Review Asked by Benny on December 2, 2021
I am writing a python GUI application that plots weather data on a map for a specific region. It plots temperature, dewpoint, wind data, and icons that represent the sky conditions. It extracts the data for longitude/latitude from text files. I timed out how long it takes for the program to plot each type of weather data and I got the following results:
temperature: 10 seconds
dewpoint: 10 seconds
wind: 15 seconds
sky conditions: 90 seconds
So, it doesn’t take too long for it to plot temperature, dewpoint, and wind. However, it takes a very long time for it to plot the sky conditions, which are icon images. My goal is for my application to display any kind of weather data in a few seconds. I am wondering what I can do to my python code to make it more efficient and run faster, so it meets that goal.
I use global variables, which I know is not good programming practice. This is likely one thing I am doing in my code that is slowing things down. I also use numerous function calls, which could also be slowing things down as well. I would like to rewrite my code, so that I don’t use so many global variables and function calls.
The biggest problem I think is when it displays the icons, which are images as stated above. I am new at working with images in python, so I don’t know if python is just slow with dealing with images or not. Any analysis of my code/suggestions to make it better would be greatly appreciated.
import tkinter as tk
from tkinter import ttk
import tkinter.font as tkFont
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import matplotlib.image as mpimg
from mpl_toolkits.basemap import Basemap
from PIL import Image
from matplotlib.offsetbox import OffsetImage, AnnotationBbox
import matplotlib.pyplot as plt
import numpy as np
import requests
def retrieve_filedata():
file = area.get() + '.txt'
f = open(file, 'r')
line = f.readline()
global minlon
minlon = float(line.split(' ')[0])
global minlat
minlat = float(line.split(' ')[1])
global maxlon
maxlon = float(line.split(' ')[2])
global maxlat
maxlat = float(line.split()[3])
global centerlat
centerlat = float(line.split()[4])
global centerlon
centerlon = float(line.split()[5])
lines = f.readlines()[1:] #put longitude and latitudes into array
global lat
lat = []
global lon
lon = []
for x in lines:
lat.append(float(x.split(' ')[0]))
lon.append(float(x.split()[1]))
f.close()
def current_weather():
retrieve_filedata()
key = '4a7a419e4e16e2629a4cedc37cbf7e50'
url = 'https://api.openweathermap.org/data/2.5/weather'
global observation
observation = []
global u
u = []
global v
v = []
global icon
icon = []
for i in range(0,len(lon)):
params = {'lat': lat[i], 'lon': lon[i], 'appid': key, 'units': 'imperial'}
response = requests.get(url, params = params)
weather = response.json()
airtemp = round(weather['main']['temp'])
humidity = weather['main']['humidity'] #relative humidity
kelvin = ((airtemp-32)/1.8)+273 #convert temperature from F to Kelvin
#E = 0.611 * np.exp(5423 * ((1/273) - (1/dewpoint))) vapor pressure
Es = 0.611 * np.exp(5423 * ((1/273) - (1/kelvin))) #saturation vapor pressure
kelvindew = 5423/((5423/273)-np.log(((humidity/100)*Es)/0.611)) #use vapor pressure equation to find dewpoint in Kelvin
dewpoint = round(((kelvindew-273)*1.8)+32) #convert dewpoint from Kelvin to F
windspeed = round(weather['wind']['speed'])
winddirection = weather['wind']['deg']
u.append(-(windspeed)*np.sin(((np.pi)/180)*winddirection))
v.append(-(windspeed)*np.cos(((np.pi)/180)*winddirection))
icon.append(weather['weather'][0]['icon'])
if data.get() == 'Temperature':
observation.append(airtemp)
if data.get() == 'Dewpoint':
observation.append(dewpoint)
def display_winds():
current_weather()
map = Basemap(llcrnrlon= minlon, llcrnrlat= minlat, urcrnrlon= maxlon, urcrnrlat= maxlat ,resolution='i',
lat_0 = centerlat, lon_0 = centerlon)
for i in range(0, len(lon)):
x,y = map(lon[i], lat[i])
map.barbs(x, y, u[i], v[i], length = 5, pivot = 'middle', zorder = 100)
plt.show()
def display_icons():
map = Basemap(llcrnrlon= minlon, llcrnrlat= minlat, urcrnrlon= maxlon, urcrnrlat= maxlat ,resolution='i',
lat_0 = centerlat, lon_0 = centerlon)
image = []
im = []
ab = []
x,y = map(lon, lat)
for i in range(0, len(lon)):
image.append(Image.open(requests.get('http://openweathermap.org/img/wn/' + icon[i] + '@2x.png', stream=True).raw))
im.append(OffsetImage(image[i], zoom = 0.25))
ab.append(AnnotationBbox(im[i], (x[i],y[i]), frameon=False))
map._check_ax().add_artist(ab[i])
plt.show()
def plot_data():
current_weather()
map = Basemap(llcrnrlon= minlon, llcrnrlat= minlat, urcrnrlon= maxlon, urcrnrlat= maxlat ,resolution='i',
lat_0 = centerlat, lon_0 = centerlon)
map.drawmapboundary(fill_color='#A6CAE0')
map.drawcounties(zorder = 20)
map.drawstates()
map.fillcontinents(color='#e6b800',lake_color='#A6CAE0')
for i in range(0, len(lon)):
x,y = map(lon[i], lat[i])
if data.get() == 'Temperature' or data.get() == 'Dewpoint':
plt.text(x, y, observation[i], fontsize = 7)
if data.get() == 'Wind':
display_winds()
if data.get() == 'Sky Conditions':
display_icons()
plt.show()
root = tk.Tk()
canvas = tk.Canvas(root, height = '300', width = '400')
canvas.pack()
#create widgets
titlefont = tkFont.Font(size = 20)
title = tk.Label(text = "Current Weather Map Data", font = titlefont)
arealabel = tk.Label(text = "Choose Region: ")
areavalue = tk.StringVar()
area = ttk.Combobox(root, width = '13', textvariable = areavalue)
datalabel = tk.Label(text = "Choose Data: ")
datavalue = tk.StringVar()
data = ttk.Combobox(root, width = '12', textvariable = datavalue)
button = tk.Button(root, text = "Plot Data", command = plot_data)
#organize widgets
title.place(relx = 0.1, rely = 0.05)
arealabel.place(relx = 0.05, rely = 0.25)
area.place(relx = 0.35, rely = 0.25)
datalabel.place(relx = 0.05, rely = 0.40)
data.place(relx = 0.35, rely = 0.40)
button.place(relx = 0.40, rely = 0.65)
#Insert Values into Area Combobox
area['values'] = ('Pennsylvania', 'Maryland', 'Delaware', 'New Jersey', 'Virginia', 'West Virginia', 'Ohio', 'New York',
'Rhode Island', 'Massachusetts', 'Connecticut', 'Vermont', 'New Hampshire', 'Maine', 'Mid Atlantic', 'New England')
area.current(0)
#Insert Values into Data Combobox
data['values'] = ('Temperature', 'Dewpoint', 'Wind', 'Sky Conditions')
data.current(0)
root.mainloop()
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP