mattritchey commited on
Commit
dae43e8
1 Parent(s): d9f906d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +74 -158
app.py CHANGED
@@ -1,9 +1,9 @@
1
 
2
- from branca.element import Template, MacroElement
 
3
  from folium.raster_layers import ImageOverlay
4
  import re
5
  import glob
6
- import altair as alt
7
  import pickle
8
  import h5py
9
  import rasterio
@@ -15,7 +15,7 @@ import numpy as np
15
  import pandas as pd
16
  from geopy.extra.rate_limiter import RateLimiter
17
  from geopy.geocoders import Nominatim
18
-
19
  import warnings
20
  warnings.filterwarnings("ignore")
21
 
@@ -47,11 +47,13 @@ def get_data(row, col, radius=8):
47
  "data/2021_hail.h5",
48
  "data/2020_hail.h5"
49
  ]
 
50
  all_data = []
51
  all_dates = []
52
  for i in files:
53
  with h5py.File(i, 'r') as f:
54
- data = f['hail'][:, row - radius: row + radius+ 1, col-radius: col+radius+1]
 
55
  dates = f['dates'][:]
56
  all_data.append(data)
57
  all_dates.append(dates)
@@ -69,101 +71,28 @@ def get_data(row, col, radius=8):
69
  'Max': data_max})
70
 
71
  df['Date'] = pd.to_datetime(df['Date'], format='%Y%m%d')
72
- df['Date']=df['Date']+pd.Timedelta(days=1)
73
 
74
  return df, data_max_2
75
 
76
 
77
- def map_folium(lat, lon,files_dates_selected, within_days ):
78
-
79
  # Create a base map
80
- m = folium.Map(location=[lat, lon], zoom_start=5)
81
  folium.Marker(location=[lat, lon], popup=address).add_to(m)
82
-
83
  # Define the image bounds (SW and NE corners)
84
- image_bounds = [[20.0000010001429, -129.99999999985712], [54.9999999998571, -60.00000200014287]]
85
-
 
86
  # Add ImageOverlays for each image
87
- dates = []
88
- for f in files_dates_selected:
89
- overlay = ImageOverlay(image=f, bounds=image_bounds,
90
- opacity=.75,
91
- mercator_project=False)
92
- filename = os.path.basename(f)
93
- date_str = re.search(r'(\d{8})', filename).group()
94
- formatted_date = f"{date_str[:4]}-{date_str[4:6]}-{date_str[6:8]}"
95
- dates.append(formatted_date)
96
- overlay.add_to(m)
97
-
98
-
99
- # HTML template for the slider control with dates
100
- template_1 = '{% macro html(this, kwargs) %}' + f"""
101
-
102
-
103
-
104
- <div id="slider-control" style="position: fixed; top: 50px; left: 50px; z-index: 9999; background-color: white; padding: 10px; border-radius: 5px; box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.3);">
105
- <label for="image-slider">Select Date:</label>
106
- <input type="range" min="0" max="{len(dates)-1}" value="{within_days}" class="slider" id="image-slider" style="width: 150px;" oninput="updateFromSlider(this.value)">
107
- <input type="text" id="date-input" placeholder="YYYY-MM-DD" oninput="updateFromInput(this.value)">
108
- <span id="slider-value">{dates[within_days]}</span>
109
- </div>
110
- <script>"""
111
-
112
- template_2 = f"""
113
- var dates = {dates};"""
114
-
115
- template_3 = """
116
- var currentIndex = 0;
117
-
118
- function updateImage(index) {
119
- index = Math.round(index); // Ensure the index is an integer
120
- // Update the displayed date
121
- document.getElementById('slider-value').innerHTML = dates[index];
122
- document.getElementById('date-input').value = dates[index];
123
-
124
- // Hide all images
125
- document.querySelectorAll('.leaflet-image-layer').forEach(function(layer) {
126
- layer.style.display = 'none';
127
- });
128
-
129
- // Show the current image
130
- document.querySelectorAll('.leaflet-image-layer')[index].style.display = 'block';
131
-
132
- currentIndex = index;
133
- }
134
-
135
- function updateFromSlider(value) {
136
- updateImage(parseFloat(value));
137
- }
138
-
139
- function updateFromInput(inputDate) {
140
- var index = dates.indexOf(inputDate);
141
- if (index !== -1) {
142
- document.getElementById('image-slider').value = index;
143
- updateImage(index);
144
- } else {
145
- alert('Invalid date. Please enter a date in the format YYYY-MM-DD that exists in the dataset.');
146
- }
147
- }
148
-
149
- // Initially show only the first image
150
- document.addEventListener('DOMContentLoaded', function() {
151
- document.querySelectorAll('.leaflet-image-layer').forEach(function(layer, index) {
152
- layer.style.display = index === 0 ? 'block' : 'none';
153
- });
154
- });
155
- </script>
156
- {% endmacro %}
157
- """
158
- template = template_1+template_2+template_3
159
-
160
-
161
- # Add the custom control to the map
162
- macro = MacroElement()
163
- macro._template = Template(template)
164
- m.get_root().add_child(macro)
165
-
166
-
167
  colormap_hail = cm.LinearColormap(
168
  colors=['blue', 'lightblue', 'pink', 'red'], vmin=0.01, vmax=2)
169
  # Add the color legend to the map
@@ -174,7 +103,6 @@ def map_folium(lat, lon,files_dates_selected, within_days ):
174
 
175
 
176
 
177
-
178
  #Set up 2 Columns
179
  st.set_page_config(layout="wide")
180
  col1, col2 = st.columns((2))
@@ -183,7 +111,7 @@ col1, col2 = st.columns((2))
183
  #Input Values
184
  address = st.sidebar.text_input("Address", "123 Main Street, Dallas, TX 75126")
185
  date_focus = st.sidebar.date_input("Date", pd.Timestamp(2023, 7, 1))
186
- within_days = st.sidebar.selectbox('Days Within', (30, 90))
187
  # start_date = st.sidebar.date_input("Start Date", pd.Timestamp(2023, 1, 1))
188
  # end_date = st.sidebar.date_input("End Date", pd.Timestamp(2023, 12, 31))
189
 
@@ -194,48 +122,19 @@ date_range = pd.date_range(start=start_date, end=end_date).strftime('%Y%m%d')
194
 
195
  circle_radius = st.sidebar.selectbox('Box Radius (Miles)', (5, 10, 25))
196
 
197
- zoom_dic = {5: 12, 10: 11, 25: 10}
198
- zoom = zoom_dic[circle_radius]
199
 
200
  #Geocode and get Data
201
  result = geocode(address)
202
  lat, lon = result.values[0]
203
 
204
 
205
- crs_dic = pickle.load(open('data/mrms_hail_crs.pkl', 'rb'))
206
  transform = crs_dic['affine']
207
 
208
  row, col = rasterio.transform.rowcol(transform, lon, lat)
209
- row, col =int(row), int(col)
210
- st.write(row,col)
211
 
212
- # center=row,col
213
  radius = int(np.ceil(circle_radius*1.6))
214
- # crop_coords = col-radius, row-radius, col+radius+1, row+radius+1
215
-
216
- files = [
217
- "data/2023_hail.h5",
218
- "data/2022_hail.h5",
219
- "data/2021_hail.h5",
220
- "data/2020_hail.h5"
221
- ]
222
- all_data = []
223
- all_dates = []
224
- for i in files:
225
- with h5py.File(i, 'r') as f:
226
- data = f['hail'][:, row - radius: row + radius+ 1, col-radius: col+radius+1]
227
- dates = f['dates'][:]
228
- all_data.append(data)
229
- all_dates.append(dates)
230
-
231
-
232
-
233
- files = glob.glob(r'webp/**/*.webp', recursive=True)
234
- files_dates_selected = [i for i in files if any(
235
- i for j in date_range if str(j) in re.search(r'(\d{8})', i).group())]
236
-
237
-
238
-
239
 
240
  # Get Data
241
  df_data, max_values = get_data(row, col, radius)
@@ -245,34 +144,37 @@ df_data['Max'] = df_data['Max'].round(3)
245
  df_data['Actual'] = df_data['Actual'].round(3)
246
 
247
 
248
- # Create the bar chart
249
- fig = alt.Chart(df_data).mark_bar(size=3, color='red').encode(
250
- x='Date:T', # Temporal data type
251
- y='Actual:Q', # Quantitative data type
252
- color='Actual:Q', # Color based on Actual values
253
- tooltip=[ # Adding tooltips
254
- alt.Tooltip('Date:T', title='Date'),
255
- alt.Tooltip('Actual:Q', title='Actual Value'),
256
- alt.Tooltip('Max:Q', title=f'Max Value with {circle_radius} Miles')
257
- ]
258
- ).configure(
259
- view=alt.ViewConfig(
260
- strokeOpacity=0 # No border around the chart
261
- )
262
- ).configure_axis(
263
- grid=False # Disable grid lines
264
- ).configure_legend(
265
- fillColor='transparent', # Ensure no legend is shown
266
- strokeColor='transparent'
267
- )
268
 
 
 
 
 
 
 
 
269
 
270
 
 
271
 
272
  with col1:
273
- st.title(f'Hail')
274
  try:
275
- st.altair_chart(fig, use_container_width=True)
 
276
  csv = convert_df(df_data)
277
  st.download_button(
278
  label="Download data as CSV",
@@ -285,19 +187,33 @@ with col1:
285
 
286
  with col2:
287
  st.title('Hail Mesh')
288
- if 'is_first_run' not in st.session_state:
289
- # First run
290
- st.session_state.is_first_run = True
291
- st.components.v1.html(open("data/map.html", 'r').read(), height=500, width=500)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
292
  else:
293
- with st.spinner("Loading... Please wait, it's gonna be great..."):
294
- # st_folium(m, height=500)
295
- # Not the first run; create a new map
296
- m=map_folium(lat, lon,files_dates_selected, within_days )
297
- m.save("map_new.html")
298
- st.components.v1.html(open("map_new.html", 'r').read(), height=500, width=500)
299
-
300
- # st.bokeh_chart(hv.render(nice_plot*points_lat_lon, backend='bokeh'),use_container_width=True)
301
 
302
 
303
  st.markdown(""" <style>
 
1
 
2
+
3
+ import plotly.graph_objects as go
4
  from folium.raster_layers import ImageOverlay
5
  import re
6
  import glob
 
7
  import pickle
8
  import h5py
9
  import rasterio
 
15
  import pandas as pd
16
  from geopy.extra.rate_limiter import RateLimiter
17
  from geopy.geocoders import Nominatim
18
+ from streamlit_plotly_events import plotly_events
19
  import warnings
20
  warnings.filterwarnings("ignore")
21
 
 
47
  "data/2021_hail.h5",
48
  "data/2020_hail.h5"
49
  ]
50
+
51
  all_data = []
52
  all_dates = []
53
  for i in files:
54
  with h5py.File(i, 'r') as f:
55
+ data = f['hail'][:, row-radius:row +
56
+ radius+1, col-radius:col+radius+1]
57
  dates = f['dates'][:]
58
  all_data.append(data)
59
  all_dates.append(dates)
 
71
  'Max': data_max})
72
 
73
  df['Date'] = pd.to_datetime(df['Date'], format='%Y%m%d')
74
+ # df['Date']=df['Date']+pd.Timedelta(days=1)
75
 
76
  return df, data_max_2
77
 
78
 
79
+ def map_folium(lat, lon, files_dates_selected):
80
+
81
  # Create a base map
82
+ m = folium.Map(location=[lat, lon], zoom_start=6)
83
  folium.Marker(location=[lat, lon], popup=address).add_to(m)
84
+
85
  # Define the image bounds (SW and NE corners)
86
+ image_bounds = [[20.0000010001429, -129.99999999985712],
87
+ [54.9999999998571, -60.00000200014287]]
88
+
89
  # Add ImageOverlays for each image
90
+
91
+ overlay = ImageOverlay(image=files_dates_selected, bounds=image_bounds,
92
+ opacity=.75,
93
+ mercator_project=False)
94
+
95
+ overlay.add_to(m)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  colormap_hail = cm.LinearColormap(
97
  colors=['blue', 'lightblue', 'pink', 'red'], vmin=0.01, vmax=2)
98
  # Add the color legend to the map
 
103
 
104
 
105
 
 
106
  #Set up 2 Columns
107
  st.set_page_config(layout="wide")
108
  col1, col2 = st.columns((2))
 
111
  #Input Values
112
  address = st.sidebar.text_input("Address", "123 Main Street, Dallas, TX 75126")
113
  date_focus = st.sidebar.date_input("Date", pd.Timestamp(2023, 7, 1))
114
+ within_days = st.sidebar.selectbox('Days Within', (90, 180, 365))
115
  # start_date = st.sidebar.date_input("Start Date", pd.Timestamp(2023, 1, 1))
116
  # end_date = st.sidebar.date_input("End Date", pd.Timestamp(2023, 12, 31))
117
 
 
122
 
123
  circle_radius = st.sidebar.selectbox('Box Radius (Miles)', (5, 10, 25))
124
 
 
 
125
 
126
  #Geocode and get Data
127
  result = geocode(address)
128
  lat, lon = result.values[0]
129
 
130
 
131
+ crs_dic = pickle.load(open('mrms_hail_crs.pkl', 'rb'))
132
  transform = crs_dic['affine']
133
 
134
  row, col = rasterio.transform.rowcol(transform, lon, lat)
135
+ row, col = int(row), int(col)
 
136
 
 
137
  radius = int(np.ceil(circle_radius*1.6))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
 
139
  # Get Data
140
  df_data, max_values = get_data(row, col, radius)
 
144
  df_data['Actual'] = df_data['Actual'].round(3)
145
 
146
 
147
+ fig = go.Figure()
148
+
149
+ # Add bars for actual values
150
+ fig.add_trace(go.Bar(
151
+ x=df_data['Date'],
152
+ y=df_data['Actual'],
153
+ name='Actual Value',
154
+ marker_color='#2D5986',
155
+ hoverinfo='text', # Show text information only
156
+ text=df_data.apply(
157
+ lambda row: f'Date: {row["Date"].date()}<br>Hail: {row["Actual"]}<br>Max: {row["Max"]}', axis=1)
158
+
159
+ ))
160
+
 
 
 
 
 
 
161
 
162
+ # Update layout
163
+ fig.update_layout(
164
+ title='',
165
+ xaxis_title='Date',
166
+ yaxis_title='Hail (Inches)',
167
+ barmode='group'
168
+ )
169
 
170
 
171
+ files = glob.glob(r'webp/**/*.webp', recursive=True)
172
 
173
  with col1:
174
+ st.title('Hail')
175
  try:
176
+
177
+ selected_points = plotly_events(fig)
178
  csv = convert_df(df_data)
179
  st.download_button(
180
  label="Download data as CSV",
 
187
 
188
  with col2:
189
  st.title('Hail Mesh')
190
+
191
+ if selected_points:
192
+ # Extract the details of the first selected point
193
+ selected_index = selected_points[0]['pointIndex']
194
+ selected_data = df_data.iloc[selected_index]
195
+
196
+ # # Display the selected point details
197
+ # st.write("You selected the following point:")
198
+ # st.write(selected_data)
199
+
200
+ files_dates_selected = [i for i in files if selected_data['Date'].strftime(
201
+ '%Y%m%d') in re.search(r'(\d{8})', i).group()][0]
202
+ m = map_folium(lat, lon, files_dates_selected)
203
+ m.save("map_new.html")
204
+
205
+ st.write('Date: ' + selected_data['Date'].strftime('%m-%d-%Y'))
206
+ st.components.v1.html(
207
+ open("map_new.html", 'r').read(), height=500, width=500)
208
+
209
  else:
210
+ files_dates_selected = [i for i in files if date_focus.strftime(
211
+ '%Y%m%d') in re.search(r'(\d{8})', i).group()][0]
212
+ st.write('Date: ' + date_focus.strftime('%m-%d-%Y'))
213
+ m = map_folium(lat, lon, files_dates_selected)
214
+ m.save("map_new.html")
215
+ st.components.v1.html(
216
+ open("map_new.html", 'r').read(), height=500, width=500)
 
217
 
218
 
219
  st.markdown(""" <style>