Spaces:
Sleeping
Sleeping
| # -*- 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 |