khushidhar1210 commited on
Commit
4862d3a
Β·
verified Β·
1 Parent(s): 1511ce3

for elevation

Browse files
Files changed (1) hide show
  1. app.py +103 -53
app.py CHANGED
@@ -1,6 +1,6 @@
1
  import geopandas as gpd
2
  import pandas as pd
3
- from shapely.geometry import Polygon, LineString, Point, LinearRing
4
  from shapely.ops import unary_union
5
  import xml.etree.ElementTree as ET
6
  import zipfile
@@ -9,100 +9,150 @@ import matplotlib.pyplot as plt
9
  import streamlit as st
10
  from transformers import pipeline
11
 
12
- def p(kml_file):
13
- cont = kml_file.decode('utf-8')
 
 
 
 
 
 
 
 
 
 
 
 
14
  k = ET.ElementTree(ET.fromstring(cont))
15
  root = k.getroot()
16
  ns = {'kml': 'http://www.opengis.net/kml/2.2'}
17
-
18
  shapes = []
19
  for mark in root.findall('.//kml:Placemark', ns):
20
- polygon = mark.find('.//kml:Polygon/kml:coordinates', ns)
 
21
  if polygon is not None:
22
  coordinates = polygon.text.strip().split()
23
  coords = [(float(lon), float(lat), float(alt)) for lon, lat, alt in [coord.split(',') for coord in coordinates]]
24
- shapes.append(Polygon([LinearRing(coords)]))
25
-
 
26
  line = mark.find('.//kml:LineString/kml:coordinates', ns)
27
  if line is not None:
28
  coordinates = line.text.strip().split()
29
  coords = [(float(lon), float(lat), float(alt)) for lon, lat, alt in [coord.split(',') for coord in coordinates]]
30
  shapes.append(LineString(coords))
31
-
 
32
  point = mark.find('.//kml:Point/kml:coordinates', ns)
33
  if point is not None:
34
  lon, lat, alt = map(float, point.text.strip().split(','))
35
  shapes.append(Point(lon, lat, alt))
36
-
37
  return shapes if shapes else None
38
 
39
- def ext(kmz_file):
 
40
  with zipfile.ZipFile(kmz_file, 'r') as zip_ref:
41
  zip_ref.extractall('temp_kml')
42
  kml_file = [f for f in os.listdir('temp_kml') if f.endswith('.kml')][0]
43
  with open(os.path.join('temp_kml', kml_file), 'rb') as f:
44
- return p(f.read())
45
 
46
- def choose(upf):
47
- file_bytes = upf.read()
48
- return ext(file_bytes) if upf.name.endswith('.kmz') else p(file_bytes)
 
49
 
50
- st.title("Flood Zone Analysis with Polygon Z Support")
51
- upf = st.file_uploader("Upload KML/KMZ file", type=['kml', 'kmz'])
 
52
 
53
- def bound(f, gdf):
54
- if f.empty:
 
55
  return "Invalid KML shape or no valid polygon found.", None
56
- overlaps = [gdf[gdf.intersects(kml_shape)] for kml_shape in f if not gdf[gdf.intersects(kml_shape)].empty]
57
- return overlaps if overlaps else "Boundary doesn't match", unary_union([geom for intersect in overlaps for geom in intersect.geometry])
58
 
59
- def land(overlaps, every_int):
60
- all = pd.concat(overlaps)
61
- all['area_acres'] = all.geometry.area / 4046.86
62
- fza = {zone: all[all['FLD_ZONE'] == zone]['area_acres'].sum() for zone in all['FLD_ZONE'].unique()}
63
- non = all[~all['FLD_ZONE'].isin(['A', 'AE', 'AH', 'AO', 'VE'])]['area_acres'].sum()
64
- return fza, non, every_int.area / 4046.86
 
 
 
 
 
 
 
 
 
65
 
66
- def summ(fza, non, total_acreage):
 
 
 
 
 
 
 
 
 
 
 
 
67
  summarizer = pipeline("summarization", model="gpt2")
68
- flood_zone_summary = "\n".join([f" Zone {zone}: {fza.get(zone, 0):.2f} acres" for zone in ['A', 'AE', 'AH', 'AO', 'VE']])
 
69
  prompt = f"""
70
  **Total Land Area**: {total_acreage:.2f} acres
71
- **Usable Area**: {non:.2f} acres
72
  **Flood-prone Zones**:
73
- {flood_zone_summary}
74
- Summarize the above given data in a 2-3 sentences.
75
  """
76
  response = summarizer(prompt, max_length=200, min_length=30, do_sample=False)
77
  return response[0]['summary_text']
78
 
79
- if upf is not None:
80
- dela = gpd.GeoDataFrame(pd.concat([gpd.read_file(f) for f in ["K_FLD_HAZ_AR.shp", "N_FLD_HAZ_AR.shp", "S_FLD_HAZ_AR.shp"]], ignore_index=True))
81
- dela = dela.set_crs("EPSG:4326").to_crs(epsg=3857)
 
 
 
 
 
82
  dela['geometry'] = dela['geometry'].apply(lambda x: x.buffer(0) if not x.is_valid else x)
83
-
84
- f = choose(upf)
85
- if f:
86
- kml_gdf = gpd.GeoDataFrame(geometry=f, crs="EPSG:4326").to_crs(epsg=3857)
87
- intersection, every_int = bound(kml_gdf.geometry, dela)
88
- if isinstance(intersection, str):
89
- st.write(intersection)
 
 
 
 
 
90
  else:
91
- flood_zone_areas, non, merged_area = land(intersection, every_int)
92
  st.write(f"Flood Zone Areas:")
93
- for zone, area in flood_zone_areas.items():
94
  st.write(f" Zone {zone}: {area:.2f} acres")
95
- st.write(f"\nNon-Flooded Land Area: {non:.2f} acres")
96
- st.write(f"\nMerged Area of Intersected Boundary: {merged_area:.2f} acres")
97
- st.write(f"GPT-2 Summary: {summ(flood_zone_areas, non, merged_area)}")
98
-
99
- fig, ax = plt.subplots(figsize=(10, 10))
100
- dela.plot(ax=ax, color='blue', alpha=0.5)
101
- if intersection:
 
102
  gpd.GeoDataFrame(geometry=[every_int], crs=dela.crs).plot(ax=ax, color='red', alpha=0.7)
103
- kml_gdf.plot(ax=ax, color='green', alpha=0.3)
104
- st.pyplot(fig)
105
  else:
106
  st.write("No valid geometries found in the uploaded KML file.")
107
  else:
108
- st.write("Please upload a KML/KMZ file to continue.")
 
1
  import geopandas as gpd
2
  import pandas as pd
3
+ from shapely.geometry import Polygon, LineString, Point
4
  from shapely.ops import unary_union
5
  import xml.etree.ElementTree as ET
6
  import zipfile
 
9
  import streamlit as st
10
  from transformers import pipeline
11
 
12
+ # βœ… Function to remove Z values (flatten 3D to 2D)
13
+ def drop_z(geom):
14
+ """Convert 3D geometry to 2D by removing Z values"""
15
+ if geom.geom_type == 'Polygon':
16
+ return Polygon([(x, y) for x, y, _ in geom.exterior.coords])
17
+ elif geom.geom_type == 'LineString':
18
+ return LineString([(x, y) for x, y, _ in geom.coords])
19
+ elif geom.geom_type == 'Point':
20
+ return Point(geom.x, geom.y)
21
+ return geom # Return unchanged if not 3D
22
+
23
+ # βœ… Function to parse KML file
24
+ def parse_kml(kml_file):
25
+ cont = kml_file.decode('utf-8') # Decode bytes to string
26
  k = ET.ElementTree(ET.fromstring(cont))
27
  root = k.getroot()
28
  ns = {'kml': 'http://www.opengis.net/kml/2.2'}
29
+
30
  shapes = []
31
  for mark in root.findall('.//kml:Placemark', ns):
32
+ # Extract Polygon
33
+ polygon = mark.find('.//kml:Polygon/kml:outerBoundaryIs/kml:LinearRing/kml:coordinates', ns)
34
  if polygon is not None:
35
  coordinates = polygon.text.strip().split()
36
  coords = [(float(lon), float(lat), float(alt)) for lon, lat, alt in [coord.split(',') for coord in coordinates]]
37
+ shapes.append(Polygon(coords))
38
+
39
+ # Extract LineString
40
  line = mark.find('.//kml:LineString/kml:coordinates', ns)
41
  if line is not None:
42
  coordinates = line.text.strip().split()
43
  coords = [(float(lon), float(lat), float(alt)) for lon, lat, alt in [coord.split(',') for coord in coordinates]]
44
  shapes.append(LineString(coords))
45
+
46
+ # Extract Point
47
  point = mark.find('.//kml:Point/kml:coordinates', ns)
48
  if point is not None:
49
  lon, lat, alt = map(float, point.text.strip().split(','))
50
  shapes.append(Point(lon, lat, alt))
51
+
52
  return shapes if shapes else None
53
 
54
+ # βœ… Function to extract KMZ file
55
+ def extract_kmz(kmz_file):
56
  with zipfile.ZipFile(kmz_file, 'r') as zip_ref:
57
  zip_ref.extractall('temp_kml')
58
  kml_file = [f for f in os.listdir('temp_kml') if f.endswith('.kml')][0]
59
  with open(os.path.join('temp_kml', kml_file), 'rb') as f:
60
+ return parse_kml(f.read())
61
 
62
+ # βœ… Choose between KML and KMZ
63
+ def choose_file(uploaded_file):
64
+ file_bytes = uploaded_file.read()
65
+ return extract_kmz(file_bytes) if uploaded_file.name.endswith('.kmz') else parse_kml(file_bytes)
66
 
67
+ # βœ… Streamlit UI
68
+ st.title("Flood Zone Analysis")
69
+ uploaded_file = st.file_uploader("Upload KML/KMZ file", type=['kml', 'kmz'])
70
 
71
+ # βœ… Compare boundaries
72
+ def check_boundary(kml_shapes, gdf):
73
+ if not kml_shapes:
74
  return "Invalid KML shape or no valid polygon found.", None
 
 
75
 
76
+ kml_gdf = gpd.GeoDataFrame(geometry=kml_shapes, crs="EPSG:4326")
77
+ kml_gdf['geometry'] = kml_gdf['geometry'].apply(drop_z) # Remove Z values
78
+ kml_gdf = kml_gdf.to_crs(epsg=3857)
79
+
80
+ overlaps = []
81
+ for kml_shape in kml_gdf.geometry:
82
+ intersection = gdf[gdf.intersects(kml_shape)]
83
+ if not intersection.empty:
84
+ overlaps.append(intersection)
85
+
86
+ if not overlaps:
87
+ return "Boundary doesn't match", None
88
+
89
+ every_int = unary_union([geom for intersect in overlaps for geom in intersect.geometry])
90
+ return overlaps, every_int
91
 
92
+ # βœ… Calculate land use and flood zones
93
+ def calculate_land(overlaps, every_int):
94
+ all_data = pd.concat(overlaps)
95
+ all_data['area_acres'] = all_data.geometry.area / 4046.86 # Convert to acres
96
+
97
+ flood_zones = {zone: all_data[all_data['FLD_ZONE'] == zone]['area_acres'].sum() for zone in all_data['FLD_ZONE'].unique()}
98
+ non_flooded_area = all_data[~all_data['FLD_ZONE'].isin(['A', 'AE', 'AH', 'AO', 'VE'])]['area_acres'].sum()
99
+ merged_acreage = every_int.area / 4046.86
100
+
101
+ return flood_zones, non_flooded_area, merged_acreage
102
+
103
+ # βœ… Generate summary
104
+ def generate_summary(flood_zones, non_flooded, total_acreage):
105
  summarizer = pipeline("summarization", model="gpt2")
106
+ flood_summary = "\n".join([f" Zone {zone}: {flood_zones.get(zone, 0):.2f} acres" for zone in ['A', 'AE', 'AH', 'AO', 'VE']])
107
+
108
  prompt = f"""
109
  **Total Land Area**: {total_acreage:.2f} acres
110
+ **Usable Area**: {non_flooded:.2f} acres
111
  **Flood-prone Zones**:
112
+ {flood_summary}
113
+ Summarize this in 2-3 sentences.
114
  """
115
  response = summarizer(prompt, max_length=200, min_length=30, do_sample=False)
116
  return response[0]['summary_text']
117
 
118
+ # βœ… Main processing
119
+ if uploaded_file is not None:
120
+ # Load shapefile
121
+ kent = gpd.read_file("K_FLD_HAZ_AR.shp")
122
+ nc = gpd.read_file("N_FLD_HAZ_AR.shp")
123
+ sussex = gpd.read_file("S_FLD_HAZ_AR.shp")
124
+ dela = gpd.GeoDataFrame(pd.concat([kent, nc, sussex], ignore_index=True))
125
+ dela = dela.set_crs(kent.crs, allow_override=True).to_crs(epsg=3857)
126
  dela['geometry'] = dela['geometry'].apply(lambda x: x.buffer(0) if not x.is_valid else x)
127
+
128
+ # Process uploaded KML/KMZ
129
+ kml_shapes = choose_file(uploaded_file)
130
+ if kml_shapes:
131
+ # Remove Z values
132
+ kml_shapes = [drop_z(geom) for geom in kml_shapes]
133
+
134
+ # Compare with SHP
135
+ result, every_int = check_boundary(kml_shapes, dela)
136
+
137
+ if isinstance(result, str):
138
+ st.write(result)
139
  else:
140
+ flood_zones, non_flooded, merged_acreage = calculate_land(result, every_int)
141
  st.write(f"Flood Zone Areas:")
142
+ for zone, area in flood_zones.items():
143
  st.write(f" Zone {zone}: {area:.2f} acres")
144
+ st.write(f"\nNon-Flooded Land Area: {non_flooded:.2f} acres")
145
+ st.write(f"\nMerged Area of Intersected Boundary: {merged_acreage:.2f} acres")
146
+ summary = generate_summary(flood_zones, non_flooded, merged_acreage)
147
+ st.write(f"Summary: {summary}")
148
+
149
+ # Show map
150
+ fig, ax = plt.subplots(figsize=(10, 10))
151
+ dela.plot(ax=ax, color='blue', alpha=0.5)
152
  gpd.GeoDataFrame(geometry=[every_int], crs=dela.crs).plot(ax=ax, color='red', alpha=0.7)
153
+ gpd.GeoDataFrame(geometry=kml_shapes, crs="EPSG:4326").to_crs(epsg=3857).plot(ax=ax, color='green', alpha=0.3)
154
+ st.pyplot(fig)
155
  else:
156
  st.write("No valid geometries found in the uploaded KML file.")
157
  else:
158
+ st.write("Please upload a KML/KMZ file.")