Spaces:
Sleeping
Sleeping
import geopandas as gpd | |
import pandas as pd | |
from shapely.geometry import shape | |
from shapely.ops import unary_union | |
import xml.etree.ElementTree as ET | |
import zipfile | |
import os | |
from transformers import AutoTokenizer, AutoModelForCausalLM | |
import torch | |
import matplotlib.pyplot as plt | |
import streamlit as st | |
# Function to parse KML | |
def parse_kml(kml_file): | |
with open(kml_file, 'rt') as f: | |
doc = f.read() | |
k = ET.ElementTree(ET.fromstring(doc)) | |
root = k.getroot() | |
ns = {'kml': 'http://www.opengis.net/kml/2.2'} | |
shapes = [] | |
for placemark in root.findall('.//kml:Placemark', ns): | |
polygon = placemark.find('.//kml:Polygon/kml:coordinates', ns) | |
if polygon is not None: | |
coordinates = polygon.text.strip().split() | |
coords = [(float(lon), float(lat)) for lon, lat, _ in [coord.split(',') for coord in coordinates]] | |
shapes.append(shape({'type': 'Polygon', 'coordinates': [coords]})) | |
line = placemark.find('.//kml:LineString/kml:coordinates', ns) | |
if line is not None: | |
coordinates = line.text.strip().split() | |
coords = [(float(lon), float(lat)) for lon, lat in [coord.split(',') for coord in coordinates]] | |
shapes.append(shape({'type': 'LineString', 'coordinates': coords})) | |
point = placemark.find('.//kml:Point/kml:coordinates', ns) | |
if point is not None: | |
lon, lat, _ = point.text.strip().split(',') | |
shapes.append(shape({'type': 'Point', 'coordinates': (float(lon), float(lat))})) | |
return shapes if shapes else None | |
def extract_kmz(kmz_file): | |
with zipfile.ZipFile(kmz_file, 'r') as zip_ref: | |
zip_ref.extractall('temp_kml') | |
kml_file = [f for f in os.listdir('temp_kml') if f.endswith('.kml')][0] | |
return parse_kml(os.path.join('temp_kml', kml_file)) | |
# Function to handle KML/KMZ file input | |
def handle_kml_upload(uploaded_file): | |
if uploaded_file.name.endswith('.kmz'): | |
kml_shapes = extract_kmz(uploaded_file) | |
else: | |
kml_shapes = parse_kml(uploaded_file) | |
return kml_shapes | |
# Streamlit file uploader widget | |
st.title("Flood Zone Analysis") | |
uploaded_file = st.file_uploader("Upload KML/KMZ file", type=['kml', 'kmz']) | |
if uploaded_file is not None: | |
# Step 1: Read in the shapefiles | |
shapefile_1 = gpd.read_file("K_FLD_HAZ_AR.shp") | |
shapefile_2 = gpd.read_file("N_FLD_HAZ_AR.shp") | |
shapefile_3 = gpd.read_file("S_FLD_HAZ_AR.shp") | |
# Step 2: Concatenate them into a single GeoDataFrame | |
merged_gdf = gpd.GeoDataFrame(pd.concat([shapefile_1, shapefile_2, shapefile_3], ignore_index=True)) | |
# Step 3: Ensure CRS consistency | |
merged_gdf = merged_gdf.set_crs(shapefile_1.crs, allow_override=True) | |
# Step 4: Reproject GeoDataFrame to a common projected CRS (EPSG:3857) | |
merged_gdf = merged_gdf.to_crs(epsg=3857) | |
# Step 5: Validate and fix invalid geometries | |
merged_gdf['geometry'] = merged_gdf['geometry'].apply(lambda x: x.buffer(0) if not x.is_valid else x) | |
# Step 6: Process uploaded KML/KMZ file | |
kml_shapes = handle_kml_upload(uploaded_file) | |
if kml_shapes: | |
# Ensure that the KML shapes are valid geometries | |
kml_gdf = gpd.GeoDataFrame(geometry=kml_shapes, crs="EPSG:4326") | |
# Convert to projected CRS (EPSG:3857) for consistency with shapefile | |
kml_gdf = kml_gdf.to_crs(epsg=3857) | |
# Compare KML and Shapefile | |
intersection, merged_geometry = compare_kml_with_shapefile(kml_gdf.geometry, merged_gdf) | |
if isinstance(intersection, str): | |
st.write(intersection) | |
else: | |
flood_zone_areas, non_flooded_area, merged_area = calculate_acreage_and_usable_land(intersection, merged_geometry) | |
st.write(f"Flood Zone Areas:") | |
for zone, area in flood_zone_areas.items(): | |
st.write(f" Zone {zone}: {area:.2f} acres") | |
st.write(f"\nNon-Flooded Land Area: {non_flooded_area:.2f} acres") | |
st.write(f"\nMerged Area of Intersected Boundary: {merged_area:.2f} acres") | |
summary = summarize_flood_data_llama(flood_zone_areas, non_flooded_area, merged_area) | |
st.write(f"LLM Summary: {summary}") | |
# Step 10: Visualize the intersection of KML shapes and merged shapefile | |
fig, ax = plt.subplots(figsize=(10, 10)) | |
# Plot the merged shapefile (blue color) | |
merged_gdf.plot(ax=ax, color='blue', alpha=0.5) | |
# Highlight the intersection area (overlap with KML) | |
if intersection: | |
# Combine the intersection geometries into a single geometry for display | |
intersection_geom = unary_union([geom for intersect in intersection for geom in intersect.geometry]) | |
gpd.GeoDataFrame(geometry=[intersection_geom], crs=merged_gdf.crs).plot(ax=ax, color='red', alpha=0.7) | |
# Plot the KML boundary (green color) | |
kml_gdf.plot(ax=ax, color='green', alpha=0.3) | |
# Display the plot | |
st.pyplot(fig) | |
else: | |
st.write("No valid geometries found in the uploaded KML file.") | |
else: | |
st.write("Please upload a KML/KMZ file to continue.") | |