# -*- 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\hrrr\windtrial2_streamlit_hrrr 2.py" import base64 import datetime import itertools 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 s3fs import streamlit as st import xarray as xr from geogif import gif from geopy.extra.rate_limiter import RateLimiter from geopy.geocoders import Nominatim from joblib import Parallel, delayed from matplotlib import colors as colors from pyproj import CRS, Transformer from streamlit_folium import st_folium @st.cache def convert_df(df): # IMPORTANT: Cache the conversion to prevent computation on every rerun return df.to_csv(index=0).encode('utf-8') @st.cache 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_data_date_time(date_time, lat, lon): date, time = date_time path = f"hrrrzarr/sfc/{date}/{date}_{time[-2:]}z_{analysis_forecast}.zarr/{vertical_level}/{variable}" try: ds = xr.open_mfdataset([lookup(path), lookup(f"{path}/{vertical_level}")], engine="zarr") result = ds.sel(projection_x_coordinate=lon, projection_y_coordinate=lat, method="nearest")[ variable].values*2.23694 except: result = None date2 = pd.to_datetime(str(date)+str(time), format='%Y%m%d%H') df = pd.DataFrame({'Date': date2, 'MPH': result}, index=[0]) return df def mapvalue2color(value, cmap): if np.isnan(value): return (1, 0, 0, 0) else: return colors.to_rgba(cmap(value), 0.7) def lookup(path): return s3fs.S3Map(path, s3=s3) s3 = s3fs.S3FileSystem(anon=True) st.set_page_config(layout="wide") col1, col2 = st.columns((2)) address = st.sidebar.text_input( "Address", "123 Main Street, Columbus, OH 43215") 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')) analysis_forecast1 = st.sidebar.radio( 'Analysis or Forecast:', ('Analysis', 'Forecast')) entire_day = st.sidebar.radio( 'Graph Entire Day/Forecast (Takes a Bit):', ('No', 'Yes')) animate_forecast = st.sidebar.radio( 'Animate Forecast:', ('No', 'Yes')) if analysis_forecast1 == 'Analysis': analysis_forecast = 'anl' else: analysis_forecast = 'fcst' 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] if type_wind == 'Gust': variable = type_wind.upper() vertical_level = 'surface' else: vertical_level = '10m_above_ground' if analysis_forecast == 'anl': variable = 'WIND_max_fcst' else: variable = 'WIND_1hr_max_fcst' path = f"hrrrzarr/sfc/{d}/{d}_{t[:2]}z_{analysis_forecast}.zarr/{vertical_level}/{variable}" ds = xr.open_mfdataset([lookup(path), lookup(f"{path}/{vertical_level}")], engine="zarr") lat, lon = geocode(address) ds = ds.rename(projection_x_coordinate="x", projection_y_coordinate="y") crs = CRS.from_cf({"grid_mapping_name": "lambert_conformal_conic", "longitude_of_central_meridian": -97.5, "latitude_of_projection_origin": 38.5, "standard_parallel": 38.5}) ds = ds.rio.write_crs(crs, inplace=True) ds[variable] = ds[variable].astype("float64") projected = ds.rio.reproject("EPSG:4326") if analysis_forecast == 'fcst': projected_org = projected projected = projected.sel(time=projected.time.values[0]) else: pass wind_mph = projected.sel(x=lon, y=lat, method="nearest")[ variable].values*2.23694 affine = projected.rio.transform() rows, columns = rasterio.transform.rowcol(affine, lon, lat) size = 40 projected2 = projected[variable][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.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('HRRR Model') st.write(f"{type_wind.title()} Speed: {wind_mph.round(2)} MPH at {time} UTC") st_folium(m, height=500) proj = Transformer.from_crs(4326, crs, always_xy=True) lon2, lat2 = proj.transform(lon, lat) if entire_day == 'Yes': if analysis_forecast == 'anl': times = [f'0{str(i)}'[-2:] for i in range(0, 24)] dates_times = list(itertools.product([d], times)) results = Parallel(n_jobs=-1, prefer="threads")( delayed(get_data_date_time)(i, lat2, lon2) for i in dates_times) df_all = pd.concat(results) df_all['MPH'] = df_all['MPH'].round(2) else: result = ds[variable].sel(x=lon2, y=lat2, method="nearest")*2.23694 df_all = result.to_dataframe()[variable].reset_index() df_all.columns = ['Date', 'MPH'] df_all['MPH'] = df_all['MPH'].round(2) if animate_forecast == 'Yes': # Not working gif(projected_org[variable], to='ds.gif', date_format='%m-%d-%Y: %I%p', cmap="RdBu_r", vmax=35) st.download_button( label="Download Gif", data='ds.gif', file_name='ds.gif', ) file_ = open("ds.gif", "rb") contents = file_.read() data_url = base64.b64encode(contents).decode("utf-8") file_.close() st.markdown( f'ds gif', unsafe_allow_html=True, ) fig = px.line(df_all, x="Date", y="MPH") with col2: st.title(f'{analysis_forecast1}') st.plotly_chart(fig) csv = convert_df(df_all) st.download_button( label="Download data as CSV", data=csv, file_name='data.csv', mime='text/csv') else: pass st.markdown(""" """, unsafe_allow_html=True)