UjjwalKGupta commited on
Commit
6e78575
·
verified ·
1 Parent(s): b8832c5

Add DEM and Slope Maps

Browse files
Files changed (1) hide show
  1. app.py +64 -8
app.py CHANGED
@@ -218,6 +218,44 @@ def get_wayback_data():
218
  print(f"An unexpected error occurred in get_wayback_data: {e}")
219
  return pd.DataFrame() # Return empty dataframe on failure
220
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
221
  def add_indices(image, nir_band, red_band, blue_band, green_band, swir1_band, swir2_band, evi_vars):
222
  """Calculates and adds multiple vegetation indices to an Earth Engine image."""
223
  # It's safer to work with the image bands directly
@@ -291,7 +329,7 @@ WAYBACK_DF = get_wayback_data()
291
  def process_and_display(file_obj, url_str, buffer_m, progress=gr.Progress()):
292
  """Main function to process the uploaded file or URL and generate initial outputs."""
293
  if file_obj is None and not (url_str and url_str.strip()):
294
- return None, "Please upload a file or provide a URL.", None, None, None
295
 
296
  progress(0, desc="Reading and processing geometry...")
297
  try:
@@ -313,7 +351,7 @@ def process_and_display(file_obj, url_str, buffer_m, progress=gr.Progress()):
313
  break
314
 
315
  if geometry_gdf is None:
316
- return None, "No valid polygon found in the provided file or URL.", None, None, None
317
 
318
  geometry_gdf = to_best_crs(geometry_gdf)
319
 
@@ -326,16 +364,23 @@ def process_and_display(file_obj, url_str, buffer_m, progress=gr.Progress()):
326
  )
327
 
328
  except Exception as e:
329
- return None, f"Error processing file: {e}", None, None, None
 
 
 
 
 
 
 
 
330
 
331
- progress(0.5, desc="Generating map and stats...")
332
 
333
- # Create map
334
  m = folium.Map()
335
 
336
  if not WAYBACK_DF.empty:
337
  # The DataFrame is already sorted by date, so the last item is the latest.
338
- latest_item = WAYBACK_DF.iloc[-1]
339
  wayback_url = (
340
  latest_item["ResourceURL_Template"]
341
  .replace("{TileMatrixSet}", "GoogleMapsCompatible")
@@ -373,7 +418,7 @@ def process_and_display(file_obj, url_str, buffer_m, progress=gr.Progress()):
373
  buffer_geometry_json = buffer_geometry_gdf.to_json()
374
 
375
  progress(1, desc="Done!")
376
- return m._repr_html_(), None, stats_df, geometry_json, buffer_geometry_json
377
 
378
 
379
  def calculate_indices(
@@ -520,6 +565,12 @@ with gr.Blocks(theme=gr.themes.Soft(), title="Kamlan: KML Analyzer") as demo:
520
  gr.Markdown("## 2. Results")
521
  stats_output = gr.DataFrame(label="Geometry Metrics")
522
  map_output = gr.HTML(label="Map View")
 
 
 
 
 
 
523
  results_info_box = gr.Textbox(label="Calculation Status", interactive=False)
524
  timeseries_table = gr.DataFrame(label="Time Series Data")
525
  plot_output = gr.Plot(label="Time Series Plot")
@@ -537,7 +588,7 @@ with gr.Blocks(theme=gr.themes.Soft(), title="Kamlan: KML Analyzer") as demo:
537
  process_button.click(
538
  fn=process_and_display,
539
  inputs=[file_input, url_input, buffer_input],
540
- outputs=[map_output, info_box, stats_output, geometry_data, buffer_geometry_data]
541
  )
542
 
543
  def calculate_wrapper(geometry_json, buffer_geometry_json, veg_indices,
@@ -563,6 +614,10 @@ with gr.Blocks(theme=gr.themes.Soft(), title="Kamlan: KML Analyzer") as demo:
563
  # Select the first plot to display, if any exist
564
  first_plot = plots[0] if plots else None
565
 
 
 
 
 
566
  # Return a clean set of outputs for the UI
567
  return status_message, df, first_plot
568
 
@@ -590,3 +645,4 @@ with gr.Blocks(theme=gr.themes.Soft(), title="Kamlan: KML Analyzer") as demo:
590
 
591
  if __name__ == "__main__":
592
  demo.launch(debug=True)
 
 
218
  print(f"An unexpected error occurred in get_wayback_data: {e}")
219
  return pd.DataFrame() # Return empty dataframe on failure
220
 
221
+ def get_dem_slope_maps(ee_geometry):
222
+ """Creates DEM and Slope maps from SRTM data."""
223
+ one_time_setup() # Ensure GEE is initialized
224
+
225
+ # --- DEM Map ---
226
+ dem_map = gee_folium.Map(add_google_map=True) # Add basemap for context
227
+ dem_map.centerObject(ee_geometry)
228
+
229
+ dem_image = ee.Image("USGS/SRTMGL1_003").clip(ee_geometry)
230
+
231
+ stats = dem_image.reduceRegion(reducer=ee.Reducer.minMax(), geometry=ee_geometry, scale=30, maxPixels=1e9).getInfo()
232
+
233
+ # Check if data is available
234
+ if not stats or stats.get('elevation_max') is None:
235
+ dem_map_html = "<div>No DEM data available for this area.</div>"
236
+ slope_map_html = "<div>No Slope data available for this area.</div>"
237
+ return dem_map_html, slope_map_html
238
+
239
+ min_elev, max_elev = stats['elevation_min'], stats['elevation_max']
240
+ vis_params = {"min": min_elev, "max": max_elev, "palette": ["blue", "green", "yellow", "red"]}
241
+
242
+ dem_map.addLayer(dem_image, vis_params, "DEM")
243
+ dem_map.add_colorbar(colors=vis_params["palette"], vmin=vis_params["min"], vmax=vis_params["max"], caption="Elevation (m)")
244
+ dem_map.addLayerControl()
245
+
246
+ # --- Slope Map ---
247
+ slope_map = gee_folium.Map(add_google_map=True) # Add basemap for context
248
+ slope_map.centerObject(ee_geometry)
249
+
250
+ slope_image = ee.Terrain.slope(dem_image)
251
+ slope_vis_params = {"min": 0, "max": 60, "palette": ["blue", "green", "yellow", "red"]}
252
+
253
+ slope_map.addLayer(slope_image, slope_vis_params, "Slope")
254
+ slope_map.add_colorbar(colors=slope_vis_params["palette"], vmin=0, vmax=60, caption="Slope (degrees)")
255
+ slope_map.addLayerControl()
256
+
257
+ return dem_map._repr_html_(), slope_map._repr_html_()
258
+
259
  def add_indices(image, nir_band, red_band, blue_band, green_band, swir1_band, swir2_band, evi_vars):
260
  """Calculates and adds multiple vegetation indices to an Earth Engine image."""
261
  # It's safer to work with the image bands directly
 
329
  def process_and_display(file_obj, url_str, buffer_m, progress=gr.Progress()):
330
  """Main function to process the uploaded file or URL and generate initial outputs."""
331
  if file_obj is None and not (url_str and url_str.strip()):
332
+ return None, "Please upload a file or provide a URL.", None, None, None, None, None
333
 
334
  progress(0, desc="Reading and processing geometry...")
335
  try:
 
351
  break
352
 
353
  if geometry_gdf is None:
354
+ return None, "No valid polygon found in the provided file or URL.", None, None, None, None, None
355
 
356
  geometry_gdf = to_best_crs(geometry_gdf)
357
 
 
364
  )
365
 
366
  except Exception as e:
367
+ return None, f"Error processing file: {e}", None, None, None, None, None
368
+
369
+ progress(0.5, desc="Generating maps and stats...")
370
+
371
+ # Convert to EE geometry
372
+ ee_geometry = ee.Geometry(json.loads(geometry_gdf.to_crs(4326).to_json())['features'][0]['geometry'])
373
+
374
+ # Generate DEM and Slope maps
375
+ dem_html, slope_html = get_dem_slope_maps(ee_geometry)
376
 
 
377
 
378
+ # Create main map
379
  m = folium.Map()
380
 
381
  if not WAYBACK_DF.empty:
382
  # The DataFrame is already sorted by date, so the last item is the latest.
383
+ latest_item = WAYBACK_DF.iloc[0]
384
  wayback_url = (
385
  latest_item["ResourceURL_Template"]
386
  .replace("{TileMatrixSet}", "GoogleMapsCompatible")
 
418
  buffer_geometry_json = buffer_geometry_gdf.to_json()
419
 
420
  progress(1, desc="Done!")
421
+ return m._repr_html_(), None, stats_df, dem_html, slope_html, geometry_json, buffer_geometry_json
422
 
423
 
424
  def calculate_indices(
 
565
  gr.Markdown("## 2. Results")
566
  stats_output = gr.DataFrame(label="Geometry Metrics")
567
  map_output = gr.HTML(label="Map View")
568
+
569
+ gr.Markdown("### Digital Elevation Model (DEM) and Slope")
570
+ with gr.Row():
571
+ dem_map_output = gr.HTML(label="DEM Map")
572
+ slope_map_output = gr.HTML(label="Slope Map")
573
+
574
  results_info_box = gr.Textbox(label="Calculation Status", interactive=False)
575
  timeseries_table = gr.DataFrame(label="Time Series Data")
576
  plot_output = gr.Plot(label="Time Series Plot")
 
588
  process_button.click(
589
  fn=process_and_display,
590
  inputs=[file_input, url_input, buffer_input],
591
+ outputs=[map_output, info_box, stats_output, dem_map_output, slope_map_output, geometry_data, buffer_geometry_data]
592
  )
593
 
594
  def calculate_wrapper(geometry_json, buffer_geometry_json, veg_indices,
 
614
  # Select the first plot to display, if any exist
615
  first_plot = plots[0] if plots else None
616
 
617
+ # Round the dataframe to 3 decimal places for display
618
+ if df is not None:
619
+ df = df.round(3)
620
+
621
  # Return a clean set of outputs for the UI
622
  return status_message, df, first_plot
623
 
 
645
 
646
  if __name__ == "__main__":
647
  demo.launch(debug=True)
648
+