multipage2 / pages /Wind (Low Resolution): ERA.py
mattritchey's picture
Update pages/Wind (Low Resolution): ERA.py
11d905e verified
# -*- coding: utf-8 -*-
"""
Created on Fri Oct 14 10:35:25 2022
@author: mritchey
"""
# streamlit run "C:\Users\mritchey\.spyder-py3\Python Scripts\streamlit projects\ERA\ERA2.py"
import datetime
import glob
import os
import branca.colormap as cm
import folium
import numpy as np
import pandas as pd
import plotly.express as px
import streamlit as st
from geopy.extra.rate_limiter import RateLimiter
from geopy.geocoders import Nominatim
from matplotlib import colors as colors
from streamlit_folium import st_folium
import rioxarray
import xarray as xr
import cdsapi
import os
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
def graph_within_date_range(d, number_days_range):
year, month, day = d[:4], d[4:6], d[6:8]
date = pd.Timestamp(d)
start_date, end_date = date - \
pd.Timedelta(days=number_days_range), date + \
pd.Timedelta(days=number_days_range+1)
start_date = start_date.strftime("%Y-%m-%d")
end_date = end_date.strftime("%Y-%m-%d")
url = f'https://archive-api.open-meteo.com/v1/archive?latitude={lat}&longitude={lon}&start_date={start_date}&end_date={end_date}&hourly=temperature_2m,precipitation,windspeed_10m,wind_gusts_10m&models=best_match&temperature_unit=fahrenheit&windspeed_unit=mph&precipitation_unit=inch'
df = pd.read_json(url).reset_index()
data = pd.DataFrame({c['index']: c['hourly'] for r, c in df.iterrows()})
data['time'] = pd.to_datetime(data['time'])
data['date'] = pd.to_datetime(data['time'].dt.date)
data = data.query("temperature_2m==temperature_2m")
data_agg = data.groupby(['date']).agg({'temperature_2m': ['min', 'mean', 'max'],
'precipitation': ['sum'],
'windspeed_10m': ['min', 'mean', 'max'],
'wind_gusts_10m': ['min', 'mean', 'max']
})
data_agg.columns = data_agg.columns.to_series().str.join('_')
data_agg = data_agg.query("temperature_2m_min==temperature_2m_min")
return data.drop(columns=['date']), data_agg
@st.cache(allow_output_mutation=True)
def get_era5_data(year, month, day):
c = cdsapi.Client(key=os.environ['key'],
url="https://cds.climate.copernicus.eu/api/v2")
c.retrieve(
'reanalysis-era5-single-levels',
{
'product_type': 'reanalysis',
'variable': ['10m_u_component_of_wind', '10m_v_component_of_wind',
'instantaneous_10m_wind_gust',
'2m_temperature', 'total_precipitation'],
'year': year,
'month': [month],
'day': [day],
'time': ['00:00', '06:00', '12:00', '18:00'],
'area': [49.5, -125, 24.5, -66.5, ],
'format': 'netcdf',
},
'data.nc')
@st.cache
def convert_df(df):
return df.to_csv(index=0).encode('utf-8')
try:
for i in glob.glob('*.grib2'):
os.remove(i)
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")
date = st.sidebar.date_input(
"Date", pd.Timestamp(2022, 9, 28))
d = date.strftime('%Y%m%d')
date = date.strftime('%Y-%m-%d')
time = st.sidebar.selectbox('Time (UTC):', ('12 AM', '6 AM', '12 PM', '6 PM',))
type_var = st.sidebar.selectbox(
'Type:', ('Gust', 'Wind', 'Temp', 'Precipitation'))
number_days_range = st.sidebar.selectbox(
'Within Day Range:', (5, 10, 30, 90, 180))
hourly_daily = st.sidebar.radio('Aggregate Data', ('Hourly', 'Daily'))
# Keys
var_key = {'Gust': 'i10fg', 'Wind': 'wind10',
'Temp': 't2m', 'Precipitation': 'tp'}
variable = var_key[type_var]
unit_key = {'Gust': 'MPH', 'Wind': 'MPH',
'Temp': 'F', 'Precipitation': 'In.'}
unit = unit_key[type_var]
cols_key = {'Gust': ['wind_gusts_10m'], 'Wind': ['windspeed_10m'], 'Temp': ['temperature_2m'],
'Precipitation': ['precipitation']}
cols_key_agg = {'Gust': ['windgusts_10m_min', 'windgusts_10m_mean',
'windgusts_10m_max'],
'Wind': ['windspeed_10m_min', 'windspeed_10m_mean',
'windspeed_10m_max'],
'Temp': ['temperature_2m_min', 'temperature_2m_mean', 'temperature_2m_max'],
'Precipitation': ['precipitation_sum']}
if hourly_daily == 'Hourly':
cols = cols_key[type_var]
else:
cols = cols_key_agg[type_var]
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 = '00:00'
else:
t = datetime.time(int(time[:2].strip()), 00).strftime('%H')+'00'
year, month, day = d[:4], d[4:6], d[6:8]
get_era5_data(year, month, day)
ds = xr.open_dataset('data.nc')
ds = ds.sel(time=f'{date}T{t}').drop('time')
#Convert Units
ds = ds.assign(t2m=(ds.t2m - 273.15) * 9/5 + 32)
ds = ds.assign(i10fg=(ds.i10fg*2.237))
ds = ds.assign(tp=(ds.tp/24.5))
ds = ds.assign(wind10=((ds.v10**2+ds.u10**2)**.5)*2.237)
lat, lon = geocode(address)
var_value = ds[variable].sel(
longitude=lon, latitude=lat, method="nearest").values.item()
var_value = round(var_value, 1)
img = ds[variable].values
boundary = ds.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=5, height=500)
folium.Marker(
location=[lat, lon],
popup=f"{var_value} {unit}"
).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('ERA5 Model')
# st.write(
# f"{type_wind.title()} Speed: {wind_mph[0].round(2)} MPH at {time} UTC")
st_folium(m, height=500)
df_all, df_all_agg = graph_within_date_range(d, number_days_range)
if hourly_daily == 'Hourly':
fig = px.line(df_all, x="time", y=cols)
df_downloald = df_all
else:
fig = px.line(df_all_agg.reset_index(), x="date", y=cols)
df_downloald = df_all_agg.reset_index()
with col2:
st.title('Analysis')
st.plotly_chart(fig)
csv = convert_df(df_downloald)
st.download_button(
label="Download data as CSV",
data=csv,
file_name=f'{d}.csv',
mime='text/csv')
st.markdown(""" <style>
#MainMenu {visibility: hidden;}
footer {visibility: hidden;}
</style> """, unsafe_allow_html=True)