mattritchey commited on
Commit
7a58278
1 Parent(s): 9389526

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +249 -0
app.py ADDED
@@ -0,0 +1,249 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import plotly.graph_objects as go
3
+ from folium.raster_layers import ImageOverlay
4
+ import re
5
+ import glob
6
+ import pickle
7
+ import h5py
8
+ import rasterio
9
+ import streamlit as st
10
+ import os
11
+ import branca.colormap as cm
12
+ import folium
13
+ import numpy as np
14
+ import pandas as pd
15
+ from geopy.extra.rate_limiter import RateLimiter
16
+ from geopy.geocoders import Nominatim
17
+ from streamlit_plotly_events import plotly_events
18
+ import warnings
19
+ from folium import plugins
20
+ warnings.filterwarnings("ignore")
21
+
22
+
23
+ @st.cache_data
24
+ def convert_df(df):
25
+ return df.to_csv(index=0).encode('utf-8')
26
+
27
+
28
+ @st.cache_data
29
+ def geocode(address):
30
+ try:
31
+ address2 = address.replace(' ', '+').replace(',', '%2C')
32
+ df = pd.read_json(
33
+ f'https://geocoding.geo.census.gov/geocoder/locations/onelineaddress?address={address2}&benchmark=2020&format=json')
34
+ results = df.iloc[:1, 0][0][0]['coordinates']
35
+ lat, lon = results['y'], results['x']
36
+ except:
37
+ geolocator = Nominatim(user_agent="GTA Lookup")
38
+ geocode = RateLimiter(geolocator.geocode, min_delay_seconds=1)
39
+ location = geolocator.geocode(address)
40
+ lat, lon = location.latitude, location.longitude
41
+ return pd.DataFrame({'Lat': lat, 'Lon': lon}, index=[0])
42
+
43
+
44
+ @st.cache_data
45
+ def get_data(row, col, radius):
46
+ files = [
47
+ "data/GUST_hrrr_2021_all_max.h5",
48
+ "data/GUST_hrrr_2022_all_max.h5",
49
+ "data/mritchey/GUST_hrrr_2023_all_max.h5",
50
+ "data/GUST_hrrr_202401_202409_max.h5",
51
+ ]
52
+
53
+ all_data = []
54
+ all_dates = []
55
+ for f in files:
56
+ with h5py.File(f, 'r') as f:
57
+ data = f['GUST'][:, row-radius:row +
58
+ radius+1, col-radius:col+radius+1]
59
+ dates = f['dates'][:]
60
+ all_data.append(data)
61
+ all_dates.append(dates)
62
+
63
+ data_mat = np.concatenate(all_data)
64
+ data_mat = np.where(data_mat < 0, 0, data_mat)*2.23694
65
+
66
+ dates_mat = np.concatenate(all_dates)
67
+
68
+ data_actual = np.array([i[radius, radius] for i in data_mat])
69
+
70
+ data_max = np.max(data_mat, axis=(1, 2))
71
+ data_max_2 = np.max(data_mat, axis=0)
72
+ data_max_2 = data_max_2
73
+
74
+ df = pd.DataFrame({'Date': dates_mat,
75
+ 'Actual': data_actual,
76
+ 'Max': data_max})
77
+
78
+ df['Date'] = pd.to_datetime(df['Date'], format='%Y%m%d')
79
+ # df['Date']=df['Date']+pd.Timedelta(days=1)
80
+
81
+ return df, data_max_2
82
+
83
+
84
+ def lat_lon_to_row_col(lat, lon):
85
+ crs_dic = pickle.load(open('data/hrrr_crs.pkl', 'rb'))
86
+ transform = crs_dic['affine']
87
+ trans_rtma = crs_dic['proj_4326']
88
+ lon_rtma, lat_rtma = trans_rtma.transform(lon, lat)
89
+
90
+ row, col = rasterio.transform.rowcol(transform, lon_rtma, lat_rtma)
91
+ row, col = int(row), int(col)
92
+ return row, col
93
+
94
+
95
+ def map_folium(lat, lon, files_dates_selected, actual_point, max_point):
96
+ popup_content = f"""
97
+ <div style="font-size: 7pt; width: 100px; height: 100px;">
98
+ <b>{address}</b><br>
99
+ <b>Gust: {actual_point:,.2f} MPH</b><br>
100
+ <b>Max: {max_point:,.2f} MPH</b><br>
101
+ </div>
102
+ """
103
+ # Create a base map
104
+ m = folium.Map(location=[lat, lon], zoom_start=6)
105
+ folium.Marker(location=[lat, lon],
106
+
107
+ popup=folium.Popup(popup_content, max_width=400)
108
+
109
+
110
+ ).add_to(m)
111
+
112
+ # Define the image bounds (SW and NE corners)
113
+ image_bounds = [[21.081227294744885, -134.02385805744265],
114
+ [52.62502506520796, -60.98015065638055]]
115
+
116
+ # Add ImageOverlays for each image
117
+
118
+ overlay = ImageOverlay(image=files_dates_selected, bounds=image_bounds,
119
+ opacity=.75,
120
+ mercator_project=False)
121
+
122
+ overlay.add_to(m)
123
+ colormap_hail = cm.LinearColormap(
124
+ colors=['blue', 'lightblue', 'pink', 'red'], vmin=0, vmax=75)
125
+ # Add the color legend to the map
126
+ colormap_hail.caption = 'Legend: Wind Gust (MPH)'
127
+ colormap_hail.add_to(m)
128
+
129
+ plugins.Fullscreen().add_to(m)
130
+
131
+ return m
132
+
133
+
134
+ def get_all_data(lat, lon, radius, start_date, end_date):
135
+ #Geocode and get Data
136
+
137
+ row, col = lat_lon_to_row_col(lat, lon)
138
+
139
+ df_data, max_values = get_data(row, col, radius)
140
+
141
+ df_data = df_data.query(f"'{start_date}'<=Date<='{end_date}'")
142
+ df_data['Actual'] = df_data['Actual'].astype(float).round(2)
143
+ df_data['Max'] = df_data['Max'].astype(float).round(2)
144
+
145
+ fig = go.Figure()
146
+
147
+ # Add bars for actual values
148
+ fig.add_trace(go.Bar(
149
+ x=df_data['Date'],
150
+ y=df_data['Actual'],
151
+ name='Actual Value',
152
+ marker_color='#2D5986',
153
+ hoverinfo='text', # Show text information only
154
+ text=df_data.apply(
155
+ lambda row: f'Date: {row["Date"].date()}<br>Gust: {row["Actual"]}<br>Max: {row["Max"]}', axis=1)
156
+
157
+ ))
158
+
159
+ # Update layout
160
+ fig.update_layout(
161
+ title='',
162
+ xaxis_title='Date',
163
+ yaxis_title='Gust (MPH)',
164
+ barmode='group'
165
+ )
166
+
167
+ return fig, df_data
168
+
169
+
170
+ #Set up 2 Columns
171
+ st.set_page_config(layout="wide")
172
+ col1, col2 = st.columns((2))
173
+
174
+ os.chdir(r'C:\Users\mritchey')
175
+
176
+ #Input Values
177
+ address = st.sidebar.text_input("Address", "123 Main Street, Dallas, TX 75126")
178
+ date_focus = st.sidebar.date_input("Date", pd.Timestamp(2021, 7, 1))
179
+ within_days = st.sidebar.selectbox('Days Within', (90, 180, 365))
180
+ circle_radius = st.sidebar.selectbox('Box Radius (Miles)', (5, 10, 25))
181
+ interactive_map = st.sidebar.radio(
182
+ 'Interactive Map (Lower Res)', (False, True))
183
+
184
+
185
+ start_date = date_focus+pd.Timedelta(days=-within_days)
186
+ end_date = date_focus+pd.Timedelta(days=within_days)
187
+
188
+ date_range = pd.date_range(start=start_date, end=end_date).strftime('%Y%m%d')
189
+
190
+ result = geocode(address)
191
+ lat, lon = result.values[0]
192
+ radius = int(np.ceil(circle_radius*1.6/2.5))
193
+
194
+ fig, df_data = get_all_data(lat, lon, radius, start_date, end_date)
195
+
196
+ _, actual_point, max_point = df_data.query(f"Date=='{date_focus}'").values[0]
197
+
198
+ files = glob.glob(
199
+ r'data\**\*.webp', recursive=True)
200
+
201
+ with col1:
202
+ st.title('Gust')
203
+ try:
204
+
205
+ selected_points = plotly_events(fig)
206
+ csv = convert_df(df_data)
207
+ st.download_button(
208
+ label="Download data as CSV",
209
+ data=csv,
210
+ file_name='data.csv',
211
+ mime='text/csv')
212
+ except:
213
+ pass
214
+
215
+
216
+ with col2:
217
+ st.title('GUST MAP')
218
+
219
+ if selected_points:
220
+ # Extract the details of the first selected point
221
+ selected_index = selected_points[0]['pointIndex']
222
+ selected_data = df_data.iloc[selected_index]
223
+
224
+
225
+ _, actual_point, max_point = df_data.query(
226
+ f"Date=='{selected_data['Date']}'").values[0]
227
+ files_dates_selected = [i for i in files if selected_data['Date'].strftime(
228
+ '%Y%m%d') in re.search(r'(\d{8})', i).group()][0]
229
+ m = map_folium(lat, lon, files_dates_selected, actual_point, max_point)
230
+ m.save("map_new.html")
231
+
232
+ st.write('Date: ' + selected_data['Date'].strftime('%m-%d-%Y'))
233
+ st.components.v1.html(
234
+ open("map_new.html", 'r').read(), height=500, width=500)
235
+
236
+ else:
237
+ files_dates_selected = [i for i in files if date_focus.strftime(
238
+ '%Y%m%d') in re.search(r'(\d{8})', i).group()][0]
239
+ st.write('Date: ' + date_focus.strftime('%m-%d-%Y'))
240
+ m = map_folium(lat, lon, files_dates_selected, actual_point, max_point)
241
+ m.save("map_new.html")
242
+ st.components.v1.html(
243
+ open("map_new.html", 'r').read(), height=500, width=500)
244
+
245
+
246
+ st.markdown(""" <style>
247
+ #MainMenu {visibility: hidden;}
248
+ footer {visibility: hidden;}
249
+ </style> """, unsafe_allow_html=True)