Spaces:
Sleeping
Sleeping
mattritchey
commited on
Commit
•
dae43e8
1
Parent(s):
d9f906d
Update app.py
Browse files
app.py
CHANGED
@@ -1,9 +1,9 @@
|
|
1 |
|
2 |
-
|
|
|
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
|
|
|
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
|
78 |
-
|
79 |
# Create a base map
|
80 |
-
m = folium.Map(location=[lat, lon], zoom_start=
|
81 |
folium.Marker(location=[lat, lon], popup=address).add_to(m)
|
82 |
-
|
83 |
# Define the image bounds (SW and NE corners)
|
84 |
-
image_bounds
|
85 |
-
|
|
|
86 |
# Add ImageOverlays for each image
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
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', (
|
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('
|
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 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
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(
|
274 |
try:
|
275 |
-
|
|
|
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 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
292 |
else:
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
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>
|