MSU576 commited on
Commit
368c464
Β·
verified Β·
1 Parent(s): 6911e08

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +170 -1
app.py CHANGED
@@ -1019,7 +1019,7 @@ EE_JSON = os.getenv("EARTHENGINE_TOKEN")
1019
  if EE_JSON:
1020
  try:
1021
  creds = ee.ServiceAccountCredentials(
1022
- email=os.getenv("SERVICE_ACCOUNT)", # <-- replace with your service account email
1023
  key_data=EE_JSON # pass raw JSON string, not dict
1024
  )
1025
  ee.Initialize(creds)
@@ -1042,7 +1042,176 @@ if "ee_initialized" not in st.session_state:
1042
  ee.Initialize()
1043
  st.session_state["ee_initialized"] = True
1044
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1045
 
 
 
1046
 
1047
 
1048
  # GeoMate Ask (RAG) β€” simple chat with memory per site and auto-extract numeric values
 
1019
  if EE_JSON:
1020
  try:
1021
  creds = ee.ServiceAccountCredentials(
1022
+ email=os.getenv("SERVICE_ACCOUNT"), # <-- replace with your service account email
1023
  key_data=EE_JSON # pass raw JSON string, not dict
1024
  )
1025
  ee.Initialize(creds)
 
1042
  ee.Initialize()
1043
  st.session_state["ee_initialized"] = True
1044
 
1045
+ def locator_page():
1046
+ st.title("🌍 GeoMate Interactive Earth Explorer")
1047
+
1048
+ # -------------------------------
1049
+ # Create Map
1050
+ # -------------------------------
1051
+ m = geemap.Map(center=[20, 78], zoom=3, draw_export=True)
1052
+
1053
+ # --- Add Multiple Basemaps ---
1054
+ basemaps = [
1055
+ "HYBRID", "ROADMAP", "TERRAIN", "SATELLITE",
1056
+ "Esri.WorldImagery", "Esri.WorldTopoMap", "Esri.WorldShadedRelief",
1057
+ "Esri.NatGeoWorldMap", "Esri.OceanBasemap",
1058
+ "CartoDB.Positron", "CartoDB.DarkMatter",
1059
+ "Stamen.Terrain", "Stamen.Watercolor",
1060
+ "OpenStreetMap",
1061
+ ]
1062
+ for b in basemaps:
1063
+ try:
1064
+ m.add_basemap(b)
1065
+ except Exception:
1066
+ pass
1067
+
1068
+ # -------------------------------
1069
+ # Boundaries & Grid
1070
+ # -------------------------------
1071
+ countries = ee.FeatureCollection("USDOS/LSIB_SIMPLE/2017")
1072
+ m.addLayer(
1073
+ countries.style(**{"color": "black", "fillColor": "00000000", "width": 1}),
1074
+ {}, "Country Boundaries"
1075
+ )
1076
+
1077
+ states = ee.FeatureCollection("FAO/GAUL_SIMPLIFIED_500m/2015/level1")
1078
+ m.addLayer(
1079
+ states.style(**{"color": "purple", "fillColor": "00000000", "width": 0.5}),
1080
+ {}, "State/Province Boundaries"
1081
+ )
1082
+
1083
+ graticule = geemap.latlon_grid(5.0, region=ee.Geometry.Rectangle([-180, -90, 180, 90]))
1084
+ m.addLayer(graticule.style(**{"color": "gray", "width": 0.5}), {}, "Lat/Lon Grid")
1085
+
1086
+ # -------------------------------
1087
+ # Datasets
1088
+ # -------------------------------
1089
+ soil = ee.Image("OpenLandMap/SOL/SOL_CLAY-WFRACTION_USDA-4B1C_M/v01").select("b200")
1090
+ soil_vis = {"min": 0, "max": 60, "palette": ["yellow", "brown", "red"]}
1091
+ m.addLayer(soil, soil_vis, "Soil Clay (200cm)")
1092
+
1093
+ dem = ee.Image("USGS/SRTMGL1_003")
1094
+ dem_vis = {"min": 0, "max": 4000, "palette": ["blue", "green", "brown", "white"]}
1095
+ m.addLayer(dem, dem_vis, "Topography (SRTM DEM)")
1096
+
1097
+ seismic = ee.Image("GEM/2015/GlobalSeismicHazard").select("b0") # use band b0
1098
+ m.addLayer(seismic, {"min": 0, "max": 1, "palette": ["white", "red"]}, "Seismic Hazard")
1099
+
1100
+ water = ee.Image("JRC/GSW1_4/GlobalSurfaceWater").select("occurrence")
1101
+ flood_vis = {"min": 0, "max": 100, "palette": ["white", "blue"]}
1102
+ m.addLayer(water, flood_vis, "Flood Hazard")
1103
+
1104
+ landcover = ee.Image("ESA/WorldCover/v200/2021")
1105
+ landcover_vis = {
1106
+ "bands": ["Map"], "min": 10, "max": 100,
1107
+ "palette": [
1108
+ "006400", "ffbb22", "ffff4c", "f096ff", "fa0000",
1109
+ "b4b4b4", "f0f0f0", "0064c8", "0096a0", "00cf75"
1110
+ ]
1111
+ }
1112
+ m.addLayer(landcover, landcover_vis, "Landcover 2021")
1113
+
1114
+ # -------------------------------
1115
+ # Drawing Instructions
1116
+ # -------------------------------
1117
+ st.markdown("πŸ‘‰ Use the **drawing tool** (polygon/rectangle) on the map to select a region.")
1118
+ m.add_draw_control(polyline=False, circle=False, circlemarker=False, rectangle=True, polygon=True)
1119
+ m.to_streamlit(height=700, responsive=True)
1120
+
1121
+ # -------------------------------
1122
+ # ROI Analysis
1123
+ # -------------------------------
1124
+ if m.user_roi is not None:
1125
+ roi = m.user_roi
1126
+ st.success("βœ… Polygon selected!")
1127
+
1128
+ def safe_get(val):
1129
+ try:
1130
+ return round(val, 2) if val is not None else "N/A"
1131
+ except Exception:
1132
+ return "N/A"
1133
+
1134
+ # Soil
1135
+ soil_val = soil.reduceRegion(
1136
+ ee.Reducer.mean(), roi, 1000, 1e9
1137
+ ).get("b200").getInfo()
1138
+
1139
+ # Elevation
1140
+ elev_val = dem.reduceRegion(
1141
+ ee.Reducer.mean(), roi, 1000, 1e9
1142
+ ).get("elevation").getInfo()
1143
+
1144
+ # Seismic
1145
+ seismic_val = seismic.reduceRegion(
1146
+ ee.Reducer.mean(), roi, 5000, 1e9
1147
+ ).get("b0").getInfo()
1148
+
1149
+ # Flood
1150
+ flood_val = water.reduceRegion(
1151
+ ee.Reducer.mean(), roi, 30, 1e9
1152
+ ).get("occurrence").getInfo()
1153
+
1154
+ # Landcover Histogram
1155
+ lc_stats = landcover.reduceRegion(
1156
+ reducer=ee.Reducer.frequencyHistogram(),
1157
+ geometry=roi,
1158
+ scale=30,
1159
+ maxPixels=1e9
1160
+ ).get("Map").getInfo()
1161
+
1162
+ # -------------------------------
1163
+ # UI Outputs
1164
+ # -------------------------------
1165
+ st.subheader("πŸ“Š Regional Data Summary")
1166
+ st.write(f"**Average Clay (200cm):** {safe_get(soil_val)} %")
1167
+ st.write(f"**Average Elevation:** {safe_get(elev_val)} m")
1168
+ st.write(f"**Seismic Hazard (PGA):** {safe_get(seismic_val)} g")
1169
+ st.write(f"**Flood Occurrence Probability:** {safe_get(flood_val)} %")
1170
+
1171
+ # Landcover chart
1172
+ if lc_stats:
1173
+ labels = [str(k) for k in lc_stats.keys()]
1174
+ values = list(lc_stats.values())
1175
+ fig, ax = plt.subplots(figsize=(6, 4))
1176
+ ax.pie(values, labels=labels, autopct="%1.1f%%", startangle=90)
1177
+ ax.set_title("Landcover Distribution")
1178
+ st.pyplot(fig)
1179
+
1180
+ # Soil histogram
1181
+ soil_hist = soil.reduceRegion(
1182
+ reducer=ee.Reducer.histogram(maxBuckets=10),
1183
+ geometry=roi,
1184
+ scale=1000,
1185
+ maxPixels=1e9
1186
+ ).get("b200").getInfo()
1187
+ if soil_hist:
1188
+ fig, ax = plt.subplots(figsize=(6, 4))
1189
+ ax.bar(
1190
+ soil_hist["bucketMeans"], soil_hist["histogram"],
1191
+ width=2, color="brown", alpha=0.7
1192
+ )
1193
+ ax.set_xlabel("Clay fraction (%)")
1194
+ ax.set_ylabel("Pixel count")
1195
+ ax.set_title("Soil Clay Distribution")
1196
+ st.pyplot(fig)
1197
+
1198
+ # -------------------------------
1199
+ # Save to soil_json for reports
1200
+ # -------------------------------
1201
+ if "soil_json" not in st.session_state:
1202
+ st.session_state["soil_json"] = {}
1203
+
1204
+ st.session_state["soil_json"].update({
1205
+ "Soil": f"{safe_get(soil_val)} %",
1206
+ "Elevation": f"{safe_get(elev_val)} m",
1207
+ "Seismic Hazard": f"{safe_get(seismic_val)} g",
1208
+ "Flood Probability": f"{safe_get(flood_val)} %",
1209
+ "Landcover Stats": lc_stats if lc_stats else {}
1210
+ })
1211
+ st.success("πŸ“‘ Data saved to soil_json for report integration!")
1212
 
1213
+ else:
1214
+ st.warning("⚠️ No polygon selected yet.")
1215
 
1216
 
1217
  # GeoMate Ask (RAG) β€” simple chat with memory per site and auto-extract numeric values