Spaces:
Running
Running
# -*- coding: utf-8 -*- | |
""" | |
Created on Thu Jun 8 03:39:02 2023 | |
@author: mritchey | |
""" | |
import pandas as pd | |
import numpy as np | |
import streamlit as st | |
from geopy.extra.rate_limiter import RateLimiter | |
from geopy.geocoders import Nominatim | |
import folium | |
from streamlit_folium import st_folium | |
import geopandas as gpd | |
from vincenty import vincenty | |
st.set_page_config(layout="wide") | |
def get_perimeters(): | |
gdf_perimeters = gpd.read_file( | |
'https://opendata.arcgis.com/api/v3/datasets/d1c32af3212341869b3c810f1a215824_0/downloads/data?format=shp&spatialRefId=4326&where=1%3D1') # .to_crs(epsg=epsg_input) | |
gdf_perimeters = gdf_perimeters[['OBJECTID', 'poly_Incid', 'attr_Fir_7', 'poly_Creat', | |
'poly_DateC', 'poly_Polyg', 'poly_Acres', 'attr_Estim', 'geometry']].copy() | |
gdf_perimeters.columns = ['OBJECTID', 'Incident', 'DiscoveryDate', 'poly_Creat', | |
'LastUpdate', 'poly_Polyg', 'Size_acres', 'CurrentEstCost', 'geometry'] | |
gdf_perimeters['Lat_centroid'] = gdf_perimeters.centroid.y | |
gdf_perimeters['Lon_centroid'] = gdf_perimeters.centroid.x | |
gdf_perimeters['DiscoveryDate'] = pd.to_datetime( | |
gdf_perimeters['DiscoveryDate']) | |
return gdf_perimeters | |
def map_perimeters(_gdf_data, address): | |
geojson_data = _gdf_data[['OBJECTID', 'Incident', 'DiscoveryDate', | |
'Miles to Fire Centroid', 'geometry']].to_json() | |
m = folium.Map(location=[lat, lon], | |
zoom_start=8, | |
height=500) | |
folium.Marker( | |
location=[lat, lon], | |
tooltip=f'Address: {address}', | |
).add_to(m) | |
folium.GeoJson(geojson_data, | |
tooltip=folium.GeoJsonTooltip(fields=["Incident", | |
"DiscoveryDate", | |
'Miles to Fire Centroid']), | |
).add_to(m) | |
return m | |
def distance(x): | |
left_coords = (x[0], x[1]) | |
right_coords = (x[2], x[3]) | |
return vincenty(left_coords, right_coords, miles=True) | |
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 lat, lon | |
def extract_vertices_1(multipolygon): | |
vertices = [] | |
for polygon in multipolygon.geoms: # Access the individual polygons | |
x, y = polygon.exterior.xy # Get exterior coordinates | |
vertices.extend(zip(x, y)) # Combine x and y coordinates | |
return vertices | |
def extract_vertices_final(gdf): | |
all_data = [] | |
for idx, geom in enumerate(gdf.geometry): | |
if geom.geom_type == 'MultiPolygon': | |
vertices = extract_vertices_1(geom) | |
else: | |
x, y = geom.exterior.xy # Handle single polygons | |
vertices = list(zip(x, y)) | |
df = pd.DataFrame(vertices, columns=['Lon', 'Lat']) | |
df['index_gdf'] = idx # Add index from GeoDataFrame | |
all_data.append(df[['Lat','Lon','index_gdf']]) | |
return pd.concat(all_data).query('Lat==Lat').reset_index(drop=1).drop(columns='index_gdf') | |
#Side Bar | |
address = st.sidebar.text_input( | |
"Address", "407 N Macneil St, San Fernando, CA 91340") | |
date = st.sidebar.date_input("Date", pd.Timestamp.today(), key='date') | |
number_days_range = st.sidebar.selectbox( | |
'Within Day Range:', (60, 5, 10,30, 90, 180)) | |
# refresh = st.sidebar.radio( | |
# 'Refresh Data (as of 6/7/23): Will Take Time ', (False, True)) | |
miles_range = st.sidebar.selectbox( | |
'Find Fires within Range (Miles):', (None, 50, 100, 250, 500)) | |
size = st.sidebar.radio( | |
'Greater than 100 Acres', ("Yes", "No")) | |
#Get Data | |
gdf = get_perimeters() | |
# Geocode Addreses | |
lat, lon = geocode(address) | |
#Filter Data | |
start_date, end_date = date - \ | |
pd.Timedelta(days=number_days_range), date + \ | |
pd.Timedelta(days=number_days_range+1) | |
start_date_str, end_date_str = start_date.strftime( | |
'%Y-%m-%d'), end_date.strftime('%Y-%m-%d') | |
gdf_cut = gdf.query(f"'{start_date_str}'<=DiscoveryDate<='{end_date_str}'") | |
gdf_cut['DiscoveryDate'] = gdf_cut['DiscoveryDate'].dt.strftime('%Y-%m-%d') | |
#Distance to Fire | |
gdf_cut["Lat_address"] = lat | |
gdf_cut["Lon_address"] = lon | |
gdf_cut['Miles to Fire Centroid'] = [ | |
distance(i) for i in gdf_cut[gdf_cut.columns[-4:]].values] | |
gdf_cut['Miles to Fire Centroid'] = gdf_cut['Miles to Fire Centroid'].round(2) | |
gdf_cut['Size_acres']=gdf_cut['Size_acres'].round(1) | |
if miles_range is not None: | |
gdf_cut = gdf_cut.query(f"`Miles to Fire Centroid`<={miles_range}") | |
if size == 'Yes': | |
gdf_cut = gdf_cut.query("Size_acres>100") | |
gdf_cut = gdf_cut.sort_values('Miles to Fire Centroid').drop_duplicates().reset_index(drop=1) | |
# gdf_cut.index = gdf_cut.index+1 | |
#Map Data | |
m = map_perimeters(gdf_cut, address) | |
#Incident Edge | |
indicents = list(gdf_cut['Incident'].values) | |
incident_edge = st.sidebar.selectbox( | |
'Find Distance to Closest Edge:', indicents) | |
vertices = extract_vertices_final(gdf_cut[gdf_cut['Incident']==incident_edge]) | |
vertices["Lat_address"] = lat | |
vertices["Lon_address"] = lon | |
vertices['Distance'] = [ | |
distance(i) for i in vertices.values] | |
closest_edge = vertices[vertices['Distance'] | |
== vertices['Distance'].min()] | |
try: | |
lon_point, lat_point = closest_edge[['Lon', 'Lat']].values[0] | |
distance_edge = closest_edge['Distance'].round(2).values[0] | |
folium.PolyLine([[lat, lon], | |
[lat_point, lon_point]], | |
color='black', | |
tooltip=f'Distance: {distance_edge} Miles' | |
).add_to(m) | |
except: | |
pass | |
#Display | |
col1, col2 = st.columns((2, 3)) | |
with col1: | |
st.header('Fire Perimeters') | |
st_folium(m, height=600) | |
with col2: | |
st.header('Fires') | |
gdf_cut2 = gdf_cut[['Incident', 'DiscoveryDate', 'Size_acres','Miles to Fire Centroid']].drop_duplicates().reset_index(drop=1) | |
gdf_cut2.index = gdf_cut2.index+1 | |
gdf_cut2 |