MiBERev1 / app.py
razaali10's picture
Update app.py
41674c9 verified
Raw
History Blame Contribute Delete
3.95 kB
import streamlit as st
import requests
import folium
from streamlit_folium import st_folium
import geopandas as gpd
from shapely.geometry import shape
st.set_page_config(page_title="MBE App with Catchment Delineation", layout="wide")
st.title("🏞️ Minimum Basement Elevation (MBE) App with Catchment Delineation")
st.markdown("""
This application allows you to:
- Input a **lot address** and one or more **drainage manhole FacilityIDs**
- Query the **City of Surrey's GIS API** layers for:
- Lot boundaries (Layer 148)
- Drainage manholes (Layer 23)
- Drainage mains (Layer 18)
- Contour data (Layer 105)
- Automatically delineate the catchment draining to the manholes using contour-derived DEM
- Calculate catchment area (ha) and compute flow Q using the Rational Method
- Visualize the map with all layers
""")
# Helper function: Try multiple patterns to fetch a lot polygon from Layer 148
def get_lot_geometry(address: str):
base_url = "https://gisservices.surrey.ca/arcgis/rest/services/OpenData/MapServer/148/query"
patterns = [
f"SITEADDRESS LIKE '%{address.upper()}%'",
f"SITEADDRESS LIKE '%{address.replace('Ave', 'Avenue').upper()}%'",
f"SITEADDRESS LIKE '%{address.replace('-', ' ').upper()}%'"
]
for where_clause in patterns:
params = {
"f": "geojson",
"where": where_clause,
"outFields": "*",
"returnGeometry": "true"
}
try:
response = requests.get(base_url, params=params, timeout=10)
if response.status_code == 200:
data = response.json()
features = data.get("features", [])
if features:
return features[0]["geometry"], where_clause
except:
continue
return None, None
# Session state
if "inputs_confirmed" not in st.session_state:
st.session_state.inputs_confirmed = False
if "facility_ids" not in st.session_state:
st.session_state.facility_ids = []
if "lot_address" not in st.session_state:
st.session_state.lot_address = ""
# Input section
st.header("πŸ“₯ Input Lot Address and Manhole FacilityIDs")
lot_address = st.text_input("🏠 Enter Lot Address", placeholder="e.g. 14852 68A Avenue")
manhole_ids = st.text_area("πŸ•³οΈ Enter Drainage Manhole FacilityIDs (comma-separated)", placeholder="e.g. 100796657, 100796658")
if st.button("Submit"):
if lot_address and manhole_ids:
facility_ids = [x.strip() for x in manhole_ids.split(",") if x.strip()]
if facility_ids:
st.session_state.lot_address = lot_address
st.session_state.facility_ids = facility_ids
st.session_state.inputs_confirmed = True
else:
st.error("❌ Please enter at least one valid FacilityID.")
else:
st.error("❌ Please enter both a lot address and at least one manhole FacilityID.")
if st.session_state.inputs_confirmed:
st.success(f"βœ… Lot Address: `{st.session_state.lot_address}`")
st.write(f"πŸ“Œ Manhole FacilityIDs ({len(st.session_state.facility_ids)}):")
st.code(", ".join(st.session_state.facility_ids))
if st.button("➑️ Next: Run Catchment Delineation"):
with st.spinner("πŸ” Fetching lot geometry from GIS..."):
geom, used_query = get_lot_geometry(st.session_state.lot_address)
if geom:
lot_gdf = gpd.GeoDataFrame(geometry=[shape(geom)], crs="EPSG:4326")
center = lot_gdf.geometry[0].centroid.coords[0][::-1]
m = folium.Map(location=center, zoom_start=17)
folium.GeoJson(lot_gdf.geometry[0], name="Lot").add_to(m)
st_folium(m, width=725, height=500)
st.success("βœ… Lot geometry retrieved using:")
st.code(used_query)
else:
st.error("⚠️ No lot geometry found. Try reformatting the address.")