multipage2 / pages /Wind (High Resolution): RTMA.py
mattritchey's picture
Update pages/Wind (High Resolution): RTMA.py
3016a59 verified
# -*- coding: utf-8 -*-
"""
Created on Fri Oct 14 10:35:25 2022
@author: mritchey
"""
import datetime
import glob
import os
import urllib.request
import branca.colormap as cm
import folium
import numpy as np
import pandas as pd
import plotly.express as px
import rasterio
import rioxarray
import streamlit as st
from geopy.extra.rate_limiter import RateLimiter
from geopy.geocoders import Nominatim
from joblib import Parallel, delayed
from matplotlib import colors as colors
from streamlit_folium import st_folium
from threading import Thread
def download_file_get_data(url, rows, columns):
file = urllib.request.urlretrieve(url, url[-23:])[0]
rds = rioxarray.open_rasterio(file)
wind_mph = rds.rio.reproject("EPSG:4326")[0, rows, columns].values*2.23694
time = url[-15:-11]
return [wind_mph, time]
def threading(df_input, func_input):
starttime = time.time()
tasks_thread = df_input
results_thread = []
def thread_func(value_input):
response = func_input(value_input)
results_thread.append(response)
return True
threads = []
for i in range(len(tasks_thread)):
process = Thread(target=thread_func, args=[tasks_thread[i]])
process.start()
threads.append(process)
for process in threads:
process.join()
print(f'Time: {str(round((time.time()-starttime)/60,5))} Minutes')
return results_thread
def mapvalue2color(value, cmap):
if np.isnan(value):
return (1, 0, 0, 0)
else:
return colors.to_rgba(cmap(value), 0.7)
def geocode(address):
try:
address2 = address.replace(' ', '+').replace(',', '%2C')
df = pd.read_json(
f'https://geocoding.geo.census.gov/geocoder/locations/onelineaddress?address={address2}&benchmark=2020&format=json')
results = df.iloc[:1, 0][0][0]['coordinates']
lat, lon = results['y'], results['x']
except:
geolocator = Nominatim(user_agent="GTA Lookup")
geocode = RateLimiter(geolocator.geocode, min_delay_seconds=1)
location = geolocator.geocode(address)
lat, lon = location.latitude, location.longitude
return lat, lon
@st.cache
def get_grib_data(url, d, t):
file = urllib.request.urlretrieve(url, f'{d}{t}{type_wind}.grib2')[0]
return file
# @st.cache
def graph_entire_day(d, rows, columns):
year, month, day = d[:4], d[4:6], d[6:8]
times = [f'0{str(i)}'[-2:] for i in range(0, 24)]
urls = [
f'https://mtarchive.geol.iastate.edu/{year}/{month}/{day}/grib2/ncep/RTMA/{d}{t}00_{type_wind.upper()}.grib2' for t in times]
results = Parallel(n_jobs=4)(
delayed(download_file_get_data)(i, rows, columns) for i in urls)
df_all = pd.DataFrame(results, columns=['MPH', 'Time'])
df_all['MPH'] = df_all['MPH'].round(2)
df_all['Time'] = pd.to_datetime(d+df_all['Time'], format='%Y%m%d%H%M')
return df_all
@st.cache
def convert_df(df):
return df.to_csv(index=0).encode('utf-8')
# try:
# for i in glob.glob('*.grib2'):
# try:
# os.remove(i)
# except:
# pass
# except:
# pass
st.set_page_config(layout="wide")
col1, col2 = st.columns((2))
address = st.sidebar.text_input(
"Address", "1000 Main St, Cincinnati, OH 45202")
d = st.sidebar.date_input(
"Date", pd.Timestamp(2022, 9, 28)).strftime('%Y%m%d')
time = st.sidebar.selectbox('Time:', ('12 AM', '6 AM', '12 PM', '6 PM',))
type_wind = st.sidebar.selectbox('Type:', ('Gust', 'Wind'))
entire_day = st.sidebar.radio(
'Graph Entire Day (Takes a Bit):', ('No', 'Yes'))
if time[-2:] == 'PM' and int(time[:2].strip()) < 12:
t = datetime.time(int(time[:2].strip())+12, 00).strftime('%H')+'00'
elif time[-2:] == 'AM' and int(time[:2].strip()) == 12:
t = '0000'
else:
t = datetime.time(int(time[:2].strip()), 00).strftime('%H')+'00'
year, month, day = d[:4], d[4:6], d[6:8]
url = f'https://mtarchive.geol.iastate.edu/{year}/{month}/{day}/grib2/ncep/RTMA/{d}{t}_{type_wind.upper()}.grib2'
file = get_grib_data(url, d, t)
lat, lon = geocode(address)
rds = rioxarray.open_rasterio(file)
projected = rds.rio.reproject("EPSG:4326")
wind_mph = projected.sel(x=lon, y=lat, method="nearest").values*2.23694
affine = projected.rio.transform()
rows, columns = rasterio.transform.rowcol(affine, lon, lat)
size = 40
projected2 = projected[0, rows-size:rows+size, columns-size:columns+size]
img = projected2.values*2.23694
boundary = projected2.rio.bounds()
left, bottom, right, top = boundary
img[img < 0.0] = np.nan
clat = (bottom + top)/2
clon = (left + right)/2
vmin = np.floor(np.nanmin(img))
vmax = np.ceil(np.nanmax(img))
colormap = cm.LinearColormap(
colors=['blue', 'lightblue', 'red'], vmin=vmin, vmax=vmax)
m = folium.Map(location=[lat, lon], zoom_start=9, height=500)
folium.Marker(
location=[lat, lon],
popup=f"{wind_mph[0].round(2)} MPH").add_to(m)
folium.raster_layers.ImageOverlay(
image=img,
name='Wind Speed Map',
opacity=.8,
bounds=[[bottom, left], [top, right]],
colormap=lambda value: mapvalue2color(value, colormap)
).add_to(m)
folium.LayerControl().add_to(m)
colormap.caption = 'Wind Speed: MPH'
m.add_child(colormap)
with col1:
st.title('RTMA Model')
url_error='https://mattritchey-rtma.hf.space/'
link = f'[If RTMA not working click here]({url_error})'
st.markdown(link, unsafe_allow_html=True)
st.write(
f"{type_wind.title()} Speed: {wind_mph[0].round(2)} MPH at {time} UTC")
st_folium(m, height=500)
if entire_day == 'Yes':
df_all = graph_entire_day(d, rows, columns)
fig = px.line(df_all, x="Time", y="MPH")
with col2:
st.title('Analysis')
st.plotly_chart(fig)
csv = convert_df(df_all)
st.download_button(
label="Download data as CSV",
data=csv,
file_name=f'{d}.csv',
mime='text/csv')
else:
pass
st.markdown(""" <style>
#MainMenu {visibility: hidden;}
footer {visibility: hidden;}
</style> """, unsafe_allow_html=True)