hail_h5 / app.py
mattritchey's picture
Update app.py
be07f73 verified
# -*- coding: utf-8 -*-
"""
Created on Fri Oct 14 10:35:25 2022
@author: mritchey
"""
import gzip
import pickle
import h5py
import rasterio
from PIL import Image
import streamlit as st
import os
import branca.colormap as cm
import folium
from streamlit_folium import st_folium
import numpy as np
import pandas as pd
import plotly.express as px
from geopy.extra.rate_limiter import RateLimiter
from geopy.geocoders import Nominatim
import rioxarray
import xarray as xr
import warnings
warnings.filterwarnings("ignore")
@st.cache_data
def convert_df(df):
return df.to_csv(index=0).encode('utf-8')
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 pd.DataFrame({'Lat': lat, 'Lon': lon}, index=[0])
def map_folium(data, zoom=12):
m = folium.Map(location=[lat, lon], zoom_start=zoom, height=300)
folium.Marker(
location=[lat, lon],
popup=address).add_to(m)
# folium.GeoJson(gdf['buffer']).add_to(m)
folium.raster_layers.ImageOverlay(
data, opacity=0.8, bounds=[[bottom, left], [top, right]],
interactive=True
).add_to(m)
return m
# @st.cache_data
def crop_hail_jpg_filter(f, crop_coords, scaling_factor=255):
date = f[-19:-11]
image = Image.open(f)
cropped_image = image.crop(crop_coords)
image = (np.array(cropped_image)/scaling_factor)
if image.sum() > 0:
return date, image
# @st.cache_data
def get_data(row, col, radius):
files = [
"2023_hail.h5",
"2022_hail.h5"]
all_data = []
all_dates = []
for f in files:
with h5py.File(f, 'r') as f:
data = f['hail'][:, row-radius:row +
radius+1, col-radius:col+radius+1]
dates = f['dates'][:]
all_data.append(data)
all_dates.append(dates)
data_mat = np.concatenate(all_data)
data_mat = np.where(data_mat < 0, 0, data_mat)*0.0393701
dates_mat = np.concatenate(all_dates)
data_actual = [i[radius, radius] for i in data_mat]
data_max = np.max(data_mat, axis=(1, 2))
data_max_2 = np.max(data_mat, axis=0)
df = pd.DataFrame({'Date': dates_mat,
'Actual': data_actual,
'Max': data_max})
df['Date'] = pd.to_datetime(df['Date'], format='%Y%m%d')
return df, data_max_2
#Set up 2 Columns
st.set_page_config(layout="wide")
col1, col2 = st.columns((2))
#Input Values
address = st.sidebar.text_input("Address", "123 Main Street, Dallas, TX 75126")
start_date = st.sidebar.date_input("Start Date", pd.Timestamp(2022, 1, 1))
end_date = st.sidebar.date_input("End Date", pd.Timestamp(2023, 12, 31))
circle_radius = st.sidebar.selectbox('Box Radius (Miles)', (5, 10, 25))
zoom_dic = {5: 12, 10: 11, 25: 10}
zoom = zoom_dic[circle_radius]
#Geocode and get Data
result = geocode(address)
lat, lon = result.values[0]
#Raster Data
extracted_file = 'hail_stage.grib2'
ds_stage = xr.open_dataarray(extracted_file,engine='rasterio')
transform = ds_stage.rio.transform()
row, col = rasterio.transform.rowcol(transform, lon, lat)
radius = int(np.ceil(circle_radius*1.6))
crop_coords = col-radius, row-radius, col+radius+1, row+radius+1
# Get Data
df_data, max_values = get_data(row, col, radius)
df_data=df_data.query(f"'{start_date}'<=Date<='{end_date}'")
# Bin Data
bin_edges = [0, 0.1, 0.2, 0.4, 0.8, 1.2, 1.6, 2, 3, 4, np.inf]
bin_names = ["<0.1", "0.1-0.2", "0.2-0.4", "0.4-0.8", "0.8-1.2", "1.2-1.6", "1.6-2",
"2-3", "3-4", ">4"]
colors_values = ['#ffffff', '#ffff00', '#d1ab00', '#ff9b00', '#fe0000', '#cd0000', '#ff30ce',
'#ff30cd', '#9a009b', '#4a4d4c']
color_discrete_map = dict(zip(bin_names, colors_values))
fig = px.bar(df_data, x="Date", y="Actual", color="Actual",
# barmode="stack",
# color='red',
# color_discrete_map=color_discrete_map,
)
# Crop the raster using the bounds
cropped_data = ds_stage[0][row-radius:row+radius+1, col-radius:col+radius+1]
cropped_data.values = max_values
# Max Values Bin for RGB
def hex_to_rgb(hex_code):
hex_code = hex_code.lstrip('#') # Remove the '#' character if present
rgb = tuple(int(hex_code[i:i+2], 16) for i in (0, 2, 4))
return rgb
def hex_to_rgba(hex_code, alpha=.8):
if hex_code == '#ffffff':
alpha = 0.0
alpha_scaled = int(alpha * 255)
rgb = hex_to_rgb(hex_code)
rgba = rgb + (alpha_scaled,)
return rgba
bin_indices = np.digitize(max_values, bin_edges)-1
bin_colors = np.take(colors_values, bin_indices)
max_values_rgb = np.array([hex_to_rgba(i) for i in bin_colors.flatten()]).reshape(
max_values.shape[0], max_values.shape[0], 4)
#Mapping
img = max_values_rgb.astype('uint8')
boundary = cropped_data.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.StepColormap(colors=list(color_discrete_map.values()),
index=bin_edges,
# vmin=vmin, vmax=vmax
)
m = map_folium(img, zoom)
with col1:
st.title('Hail Mesh')
st_folium(m, height=500)
with col2:
st.title(f'Hail')
try:
st.plotly_chart(fig)
csv = convert_df(df_data)
st.download_button(
label="Download data as CSV",
data=csv,
file_name='data.csv',
mime='text/csv')
except:
pass
# st.bokeh_chart(hv.render(nice_plot*points_lat_lon, backend='bokeh'),use_container_width=True)
st.markdown(""" <style>
#MainMenu {visibility: hidden;}
footer {visibility: hidden;}
</style> """, unsafe_allow_html=True)