mattritchey commited on
Commit
a58de21
·
1 Parent(s): 28c531b

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +187 -0
app.py ADDED
@@ -0,0 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Created on Thu Jun 8 03:39:02 2023
4
+ @author: mritchey
5
+ """
6
+ import pandas as pd
7
+ import numpy as np
8
+ import streamlit as st
9
+ from geopy.extra.rate_limiter import RateLimiter
10
+ from geopy.geocoders import Nominatim
11
+ import folium
12
+ from streamlit_folium import st_folium
13
+ import geopandas as gpd
14
+ from vincenty import vincenty
15
+
16
+ st.set_page_config(layout="wide")
17
+
18
+ @st.cache_resource
19
+ def get_perimeters():
20
+
21
+ gdf_perimeters = gpd.read_file(
22
+ 'https://opendata.arcgis.com/api/v3/datasets/d1c32af3212341869b3c810f1a215824_0/downloads/data?format=shp&spatialRefId=4326&where=1%3D1') # .to_crs(epsg=epsg_input)
23
+ gdf_perimeters = gdf_perimeters[['OBJECTID', 'poly_Incid', 'attr_Fir_7', 'poly_Creat',
24
+ 'poly_DateC', 'poly_Polyg', 'poly_Acres', 'attr_Estim', 'geometry']].copy()
25
+ gdf_perimeters.columns = ['OBJECTID', 'Incident', 'DiscoveryDate', 'poly_Creat',
26
+ 'LastUpdate', 'poly_Polyg', 'Size_acres', 'CurrentEstCost', 'geometry']
27
+ gdf_perimeters['Lat_centroid'] = gdf_perimeters.centroid.y
28
+ gdf_perimeters['Lon_centroid'] = gdf_perimeters.centroid.x
29
+ gdf_perimeters['DiscoveryDate'] = pd.to_datetime(
30
+ gdf_perimeters['DiscoveryDate'])
31
+
32
+ return gdf_perimeters
33
+
34
+
35
+ def map_perimeters(_gdf_data, address):
36
+ geojson_data = _gdf_data[['OBJECTID', 'Incident', 'DiscoveryDate',
37
+ 'Miles to Fire Centroid', 'geometry']].to_json()
38
+
39
+ m = folium.Map(location=[lat, lon],
40
+
41
+ zoom_start=6,
42
+ height=500)
43
+ folium.Marker(
44
+ location=[lat, lon],
45
+ tooltip=f'Address: {address}',
46
+ ).add_to(m)
47
+
48
+ folium.GeoJson(geojson_data,
49
+ tooltip=folium.GeoJsonTooltip(fields=["Incident",
50
+ "DiscoveryDate",
51
+ 'Miles to Fire Centroid']),
52
+ ).add_to(m)
53
+ return m
54
+
55
+ def distance(x):
56
+ left_coords = (x[0], x[1])
57
+ right_coords = (x[2], x[3])
58
+ return vincenty(left_coords, right_coords, miles=True)
59
+
60
+ def geocode(address):
61
+ try:
62
+ address2 = address.replace(' ', '+').replace(',', '%2C')
63
+ df = pd.read_json(
64
+ f'https://geocoding.geo.census.gov/geocoder/locations/onelineaddress?address={address2}&benchmark=2020&format=json')
65
+ results = df.iloc[:1, 0][0][0]['coordinates']
66
+ lat, lon = results['y'], results['x']
67
+ except:
68
+ geolocator = Nominatim(user_agent="GTA Lookup")
69
+ geocode = RateLimiter(geolocator.geocode, min_delay_seconds=1)
70
+ location = geolocator.geocode(address)
71
+ lat, lon = location.latitude, location.longitude
72
+ return lat, lon
73
+
74
+ def extract_vertices(gdf):
75
+ g = [i for i in gdf.geometry]
76
+ all_data = []
77
+ for i in range(len(g)):
78
+ try:
79
+ try:
80
+ x, y = g[i].exterior.coords.xy
81
+ except:
82
+ x, y = g[i].coords.xy
83
+ df = pd.DataFrame({'Lat': y, 'Lon': x})
84
+ except:
85
+ all_data2 = []
86
+ try:
87
+ for j in range(len(g[i])):
88
+ try:
89
+ x, y = g[i][j].exterior.coords.xy
90
+ except:
91
+ x, y = g[i][j].coords.xy
92
+ all_data2.append(pd.DataFrame({'Lat': y, 'Lon': x}))
93
+ df = pd.concat(all_data2)
94
+ except:
95
+ for i in g.geometry:
96
+ x=np.concatenate([poly.exterior.coords.xy[0] for poly in i.geoms])
97
+ y=np.concatenate([poly.exterior.coords.xy[1] for poly in i.geoms])
98
+ df = pd.DataFrame({'Lat': y,
99
+ 'Lon': x, })
100
+ df['index_gdf'] = i
101
+ all_data.append(df)
102
+ return pd.concat(all_data).query('Lat==Lat').reset_index(drop=1).drop(columns='index_gdf')
103
+
104
+
105
+ #Side Bar
106
+ address = st.sidebar.text_input(
107
+ "Address", "1315 10th St, Sacramento, CA 95814")
108
+ date = st.sidebar.date_input("Date", pd.Timestamp(2021, 7, 14), key='date')
109
+ number_days_range = st.sidebar.selectbox(
110
+ 'Within Day Range:', (5, 10, 30, 90, 180))
111
+
112
+ # refresh = st.sidebar.radio(
113
+ # 'Refresh Data (as of 6/7/23): Will Take Time ', (False, True))
114
+ miles_range = st.sidebar.selectbox(
115
+ 'Find Fires within Range (Miles):', (None, 50, 100, 250, 500))
116
+
117
+ size = st.sidebar.radio(
118
+ 'Greater than 100 Acres', ("Yes", "No"))
119
+
120
+ #Get Data
121
+ gdf = get_perimeters()
122
+
123
+ # Geocode Addreses
124
+ lat, lon = geocode(address)
125
+
126
+ #Filter Data
127
+ start_date, end_date = date - \
128
+ pd.Timedelta(days=number_days_range), date + \
129
+ pd.Timedelta(days=number_days_range+1)
130
+ start_date_str, end_date_str = start_date.strftime(
131
+ '%Y-%m-%d'), end_date.strftime('%Y-%m-%d')
132
+ gdf_cut = gdf.query(f"'{start_date_str}'<=DiscoveryDate<='{end_date_str}'")
133
+ gdf_cut['DiscoveryDate'] = gdf_cut['DiscoveryDate'].dt.strftime('%Y-%m-%d')
134
+
135
+
136
+ #Distance to Fire
137
+ gdf_cut["Lat_address"] = lat
138
+ gdf_cut["Lon_address"] = lon
139
+ gdf_cut['Miles to Fire Centroid'] = [
140
+ distance(i) for i in gdf_cut[gdf_cut.columns[-4:]].values]
141
+ gdf_cut['Miles to Fire Centroid'] = gdf_cut['Miles to Fire Centroid'].round(2)
142
+ gdf_cut['Size_acres']=gdf_cut['Size_acres'].round(1)
143
+ if miles_range is not None:
144
+ gdf_cut = gdf_cut.query(f"`Miles to Fire Centroid`<={miles_range}")
145
+
146
+ if size == 'Yes':
147
+ gdf_cut = gdf_cut.query("Size_acres>100")
148
+
149
+ gdf_cut = gdf_cut.sort_values('Miles to Fire Centroid').drop_duplicates().reset_index(drop=1)
150
+ # gdf_cut.index = gdf_cut.index+1
151
+
152
+ #Map Data
153
+ m = map_perimeters(gdf_cut, address)
154
+
155
+ #Incident Edge
156
+ indicents = list(gdf_cut['Incident'].values)
157
+ incident_edge = st.sidebar.selectbox(
158
+ 'Find Distance to Closest Edge:', indicents)
159
+ vertices = extract_vertices(gdf_cut[gdf_cut['Incident']==incident_edge])
160
+ vertices["Lat_address"] = lat
161
+ vertices["Lon_address"] = lon
162
+ vertices['Distance'] = [
163
+ distance(i) for i in vertices.values]
164
+ closest_edge = vertices[vertices['Distance']
165
+ == vertices['Distance'].min()]
166
+
167
+ try:
168
+ lon_point, lat_point = closest_edge[['Lon', 'Lat']].values[0]
169
+ distance_edge = closest_edge['Distance'].round(2).values[0]
170
+ folium.PolyLine([[lat, lon],
171
+ [lat_point, lon_point]],
172
+ color='black',
173
+ tooltip=f'Distance: {distance_edge} Miles'
174
+ ).add_to(m)
175
+ except:
176
+ pass
177
+
178
+ #Display
179
+ col1, col2 = st.columns((2, 3))
180
+ with col1:
181
+ st.header('Fire Perimeters')
182
+ st_folium(m, height=600)
183
+ with col2:
184
+ st.header('Fires')
185
+ gdf_cut2 = gdf_cut[['Incident', 'DiscoveryDate', 'Size_acres','Miles to Fire Centroid']].drop_duplicates().reset_index(drop=1)
186
+ gdf_cut2.index = gdf_cut2.index+1
187
+ gdf_cut2