# -*- coding: utf-8 -*- """ Created on Fri Oct 14 10:35:25 2022 @author: mritchey """ from tqdm import tqdm from joblib import Parallel, delayed import rasterio import glob 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]]).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(start_date,end_date,crop_coords): files = glob.glob(f'png/**/*.png', recursive=True) files_dates = np.array([int(f[-19:-11]) for f in files]) mask = np.where((files_dates >= int(start_date)) & ( files_dates <= int(end_date)), True, False) files = np.array(files)[mask] results = Parallel(n_jobs=96, prefer='threads')( delayed(crop_hail_jpg_filter)(i, crop_coords) for i in tqdm(files)) results = [i for i in results if i is not None] return results #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") d = st.sidebar.date_input("Date", pd.Timestamp(2022, 7, 1)) days_within = st.sidebar.selectbox('Days Within:', ('30', '90', '180', 'Day Of',)) circle_radius = st.sidebar.selectbox('Box Radius (Miles)', (5, 10, 25)) zoom_dic = {5: 12, 10: 11, 25: 10} zoom = zoom_dic[circle_radius] try: days_within = int(days_within) start_date, end_date = d - \ pd.Timedelta(days=days_within), d+pd.Timedelta(days=days_within+1) start_date, end_date = start_date.strftime( '%Y%m%d'), end_date.strftime('%Y%m%d') except: days_within = 0 start_date = end_date=d -pd.Timedelta(days=days_within) start_date = end_date=start_date.strftime('%Y%m%d') #Geocode and get Data result = geocode(address) lat, lon = result.values[0] ds_stage = xr.open_rasterio('hail_stage.grib2') transform = ds_stage.rio.transform() row, col = rasterio.transform.rowcol(transform, lon, lat) # center=row,col radius = int(np.ceil(circle_radius*1.6)) crop_coords = col-radius, row-radius, col+radius+1, row+radius+1 # Get Data results=get_data(start_date,end_date,crop_coords) try: max_values = np.max(np.array([i[1] for i in results]), axis=0)*0.0393701 except: max_values=np.zeros(shape=(2*radius+1,2*radius+1)) # 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)) all_data = [] for date, mat in results: mat = mat*0.0393701 hist_values, _ = np.histogram(mat, bins=bin_edges) df = pd.DataFrame({'bin_edges': bin_edges[:-1], 'Bin': bin_names, 'Values': hist_values}, ) df['Date'] = pd.to_datetime(date) all_data.append(df) try: final = pd.concat(all_data) final = final.query('bin_edges!=0') fig = px.bar(final, x="Date", y="Values", color="Bin", barmode="stack", color_discrete_map=color_discrete_map) except: pass # 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(final) 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(""" """, unsafe_allow_html=True)