YashMK89 commited on
Commit
ef6db6b
·
verified ·
1 Parent(s): 36ab619

update app.py

Browse files
Files changed (1) hide show
  1. app.py +208 -70
app.py CHANGED
@@ -6,6 +6,7 @@ import pandas as pd
6
  import geopandas as gpd
7
  from datetime import datetime
8
  import leafmap.foliumap as leafmap
 
9
 
10
  # Set up the page layout
11
  st.set_page_config(layout="wide")
@@ -191,7 +192,7 @@ def calculate_custom_formula(image, geometry, formula, scale=30):
191
  image (ee.Image): The input image.
192
  geometry (ee.Geometry): The region of interest (ROI) geometry.
193
  formula (str): A string representing the mathematical formula to apply to the image.
194
- scale (int): The scale for the reduceRegion operation (default is 30).
195
 
196
  Returns:
197
  ee.Dictionary: The result of applying the custom formula in the region.
@@ -210,62 +211,84 @@ def calculate_custom_formula(image, geometry, formula, scale=30):
210
  scale=scale
211
  )
212
 
213
- return result.get('CustomResult')
214
- def get_images_by_day(image_collection_filtered, start_date_str, end_date_str, roi, location_name, latitude, longitude, index_choice, custom_formula):
215
- # Compute the daily images and their mean
216
- days = ee.List.sequence(ee.Date(start_date_str).millis(), ee.Date(end_date_str).millis(), 86400000)
217
-
218
- # This part assumes we process each day individually
219
- daily_results = []
220
- for day in days.getInfo():
221
- # Filter images for this particular day
222
- day_images = image_collection_filtered.filterDate(ee.Date(day), ee.Date(day).advance(1, 'day'))
223
-
224
- # Compute the mean value for this day
225
- mean_image = day_images.mean() # Compute the daily mean image
226
-
227
- # Perform the index calculation on the mean image
228
- result = None
229
- if index_choice.lower() == 'ndvi':
230
- result = calculate_ndvi(mean_image, roi)
231
- elif index_choice.lower() == 'ndwi':
232
- result = calculate_ndwi(mean_image, roi)
233
- elif index_choice.lower() == 'average no₂':
234
- if 'NO2' in mean_image.bandNames().getInfo():
235
- result = calculate_avg_no2_sentinel5p(mean_image, roi)
236
- else:
237
- st.warning(f"No NO2 band found for {location_name}. Please use Sentinel-5P for NO₂ data.")
238
- elif index_choice.lower() == 'custom formula' and custom_formula:
239
- result = calculate_custom_formula(mean_image, roi, custom_formula)
240
-
241
- if result is not None:
242
- # Extract the calculated value from the result
243
- if isinstance(result, ee.Number):
244
- calculated_value = result.getInfo() # For ee.Number, getInfo() is used to get the value
245
- elif isinstance(result, ee.Dictionary):
246
- calculated_value = result.get('CustomResult', None).getInfo() # For ee.Dictionary, use get() to access 'CustomResult' and then getInfo()
247
-
248
- if calculated_value is not None:
249
- daily_results.append({
250
- 'Location Name': location_name,
251
- 'Latitude': latitude,
252
- 'Longitude': longitude,
253
- 'Date': day,
254
- 'Calculated Value': calculated_value
255
- })
256
-
257
- return daily_results
258
 
259
- # Process each point for daily index calculation
260
- if file_upload is not None:
261
- if shape_type == "Point":
262
- if file_upload.name.endswith(".csv"):
 
 
 
 
 
 
 
263
  locations_df = read_csv(file_upload)
264
- elif file_upload.name.endswith(".geojson"):
265
  locations_df = read_geojson(file_upload)
266
- elif file_upload.name.endswith(".kml"):
267
  locations_df = read_kml(file_upload)
268
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
269
  for idx, row in locations_df.iterrows():
270
  latitude = row['latitude']
271
  longitude = row['longitude']
@@ -278,29 +301,144 @@ if file_upload is not None:
278
  # Define the region of interest (ROI)
279
  roi = ee.Geometry.Point([longitude, latitude])
280
 
281
- # Load Sentinel-2 image collection for the selected dataset
282
  collection = ee.ImageCollection(sub_options[sub_selection]) \
283
  .filterDate(ee.Date(start_date_str), ee.Date(end_date_str)) \
284
  .filterBounds(roi)
285
 
286
- # Get daily results
287
- daily_results = get_images_by_day(collection, start_date_str, end_date_str, roi, location_name, latitude, longitude, index_choice, custom_formula)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
288
 
289
- # Store the daily results in session state
290
- for result in daily_results:
291
- st.session_state.results.append(result)
 
 
292
 
293
- if st.session_state.results:
294
- result_df = pd.DataFrame(st.session_state.results)
 
295
 
296
- st.write("Processed Results Table (Daily):")
297
- st.dataframe(result_df[['Location Name', 'Latitude', 'Longitude', 'Date', 'Calculated Value']])
 
298
 
299
- filename = f"{main_selection}_{sub_selection}_{start_date.strftime('%Y/%m/%d')}_{end_date.strftime('%Y/%m/%d')}_daily_{shape_type}.csv"
 
 
 
 
300
 
301
- st.download_button(
302
- label="Download daily results as CSV",
303
- data=result_df.to_csv(index=False).encode('utf-8'),
304
- file_name=filename,
305
- mime='text/csv'
306
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  import geopandas as gpd
7
  from datetime import datetime
8
  import leafmap.foliumap as leafmap
9
+ import re
10
 
11
  # Set up the page layout
12
  st.set_page_config(layout="wide")
 
192
  image (ee.Image): The input image.
193
  geometry (ee.Geometry): The region of interest (ROI) geometry.
194
  formula (str): A string representing the mathematical formula to apply to the image.
195
+ scale (int): The scale for the reduceRegion operation (default is 30).
196
 
197
  Returns:
198
  ee.Dictionary: The result of applying the custom formula in the region.
 
211
  scale=scale
212
  )
213
 
214
+ # Return the result
215
+ return result
216
+
217
+
218
+ # Function to get the most recent image from the collection
219
+ def get_most_recent_image(image_collection):
220
+ image = image_collection.sort('system:time_start', False).first()
221
+ return image
222
+
223
+ # Function to handle the custom formula choice and calculation
224
+ def process_custom_formula(image, roi, custom_formula):
225
+ if custom_formula:
226
+ result = calculate_custom_formula(image, roi, custom_formula)
227
+ if result:
228
+ return result.getInfo()
229
+ return None
230
+
231
+ locations_df = None # Initialize locations_df to None
232
+ polygons_df = None # Ensure polygons_df is initialized at the beginning
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
233
 
234
+ # Process each point (with additional checks for file validity)
235
+ # Check the shape type and assign polygons_df only for Polygon data
236
+ if file_upload:
237
+ # locations_df = None # Initialize locations_df to None
238
+ # polygons_df = None # Ensure polygons_df is initialized at the beginning
239
+
240
+ file_extension = os.path.splitext(file_upload.name)[1].lower()
241
+
242
+ # Read file based on shape type
243
+ if shape_type == 'Point':
244
+ if file_extension == '.csv':
245
  locations_df = read_csv(file_upload)
246
+ elif file_extension == '.geojson':
247
  locations_df = read_geojson(file_upload)
248
+ elif file_extension == '.kml':
249
  locations_df = read_kml(file_upload)
250
+ else:
251
+ st.error("Unsupported file type. Please upload a CSV, GeoJSON, or KML file for points.")
252
+ elif shape_type == 'Polygon':
253
+ if file_extension == '.geojson':
254
+ polygons_df = read_geojson(file_upload)
255
+ elif file_extension == '.kml':
256
+ polygons_df = read_kml(file_upload)
257
+ else:
258
+ st.error("Unsupported file type. Please upload a GeoJSON or KML file for polygons.")
259
+
260
+
261
+ if locations_df is not None and not locations_df.empty:
262
+ # Ensure the necessary columns exist in the dataframe
263
+ if 'latitude' not in locations_df.columns or 'longitude' not in locations_df.columns:
264
+ st.error("Uploaded file is missing required 'latitude' or 'longitude' columns.")
265
+ else:
266
+ # Display a preview of the points data
267
+ st.write("Preview of the uploaded points data:")
268
+ st.dataframe(locations_df.head())
269
+
270
+ # Create a LeafMap object to display the points
271
+ m = leafmap.Map(center=[locations_df['latitude'].mean(), locations_df['longitude'].mean()], zoom=10)
272
+
273
+ # Add points to the map using a loop
274
+ for _, row in locations_df.iterrows():
275
+ latitude = row['latitude']
276
+ longitude = row['longitude']
277
+
278
+ # Check if latitude or longitude are NaN and skip if they are
279
+ if pd.isna(latitude) or pd.isna(longitude):
280
+ continue # Skip this row and move to the next one
281
+
282
+ m.add_marker(location=[latitude, longitude], popup=row.get('name', 'No Name'))
283
+
284
+ # Display map
285
+ st.write("Map of Uploaded Points:")
286
+ m.to_streamlit()
287
+
288
+ # Store the map in session_state
289
+ st.session_state.map_data = m
290
+
291
+ # Process each point for index calculation
292
  for idx, row in locations_df.iterrows():
293
  latitude = row['latitude']
294
  longitude = row['longitude']
 
301
  # Define the region of interest (ROI)
302
  roi = ee.Geometry.Point([longitude, latitude])
303
 
304
+ # Load Sentinel-2 image collection
305
  collection = ee.ImageCollection(sub_options[sub_selection]) \
306
  .filterDate(ee.Date(start_date_str), ee.Date(end_date_str)) \
307
  .filterBounds(roi)
308
 
309
+ image = get_most_recent_image(collection)
310
+ if not image:
311
+ st.warning(f"No images found for {location_name}.")
312
+ else:
313
+ st.write(f"Found images for {location_name}.")
314
+ # Perform the calculation based on user selection
315
+ # Perform the calculation based on user selection
316
+ result = None
317
+ if index_choice == 'NDVI':
318
+ result = calculate_ndvi(image, roi)
319
+ elif index_choice == 'NDWI':
320
+ result = calculate_ndwi(image, roi)
321
+ elif index_choice == 'Average NO₂':
322
+ if 'NO2' in image.bandNames().getInfo():
323
+ result = calculate_avg_no2_sentinel5p(image, roi)
324
+ else:
325
+ st.warning(f"No NO2 band found for {location_name}. Please use Sentinel-5P for NO₂ data.")
326
+ elif index_choice.lower() == 'custom formula' and custom_formula:
327
+ result = process_custom_formula(image, roi, custom_formula)
328
+
329
+ # Validate result before using getInfo
330
+ if result is not None:
331
+ calculated_value = None # Initialize the calculated_value as None
332
+
333
+ # Check if the result is a dictionary
334
+ if isinstance(result, dict):
335
+ # Extract the value using the appropriate key (adjust the key name as needed)
336
+ calculated_value = result.get('CustomResult', None) # Replace 'CustomResult' if using NDVI, NDWI, etc.
337
+ else:
338
+ try:
339
+ # If it's an Earth Engine object, get the value using getInfo
340
+ calculated_value = result.getInfo()
341
+ except Exception as e:
342
+ st.error(f"Error getting result info: {e}")
343
+
344
+ # If a valid calculated_value is found, append the result to session_state
345
+ if calculated_value is not None:
346
+ st.session_state.results.append({
347
+ 'Location Name': location_name,
348
+ 'Latitude': latitude,
349
+ 'Longitude': longitude,
350
+ 'Calculated Value': calculated_value
351
+ })
352
+ else:
353
+ st.warning(f"No value calculated for {location_name}.")
354
+ else:
355
+ st.warning(f"No value calculated for {location_name}.")
356
+
357
+
358
+ # Check if polygons_df is populated for polygons
359
+ if polygons_df is not None:
360
+ st.write("Preview of the uploaded polygons data:")
361
+ st.dataframe(polygons_df.head())
362
+
363
+ m = leafmap.Map(center=[polygons_df.geometry.centroid.y.mean(), polygons_df.geometry.centroid.x.mean()], zoom=10)
364
 
365
+ for _, row in polygons_df.iterrows():
366
+ polygon = row['geometry']
367
+ if polygon.is_valid:
368
+ gdf = gpd.GeoDataFrame([row], geometry=[polygon], crs=polygons_df.crs)
369
+ m.add_gdf(gdf=gdf, layer_name=row.get('name', 'Unnamed Polygon'))
370
 
371
+ st.write("Map of Uploaded Polygons:")
372
+ m.to_streamlit()
373
+ st.session_state.map_data = m
374
 
375
+ for idx, row in polygons_df.iterrows():
376
+ polygon = row['geometry']
377
+ location_name = row.get('name', f"Polygon_{idx}")
378
 
379
+ try:
380
+ roi = convert_to_ee_geometry(polygon)
381
+ except ValueError as e:
382
+ st.error(str(e))
383
+ continue
384
 
385
+ collection = ee.ImageCollection(sub_options[sub_selection]) \
386
+ .filterDate(ee.Date(start_date_str), ee.Date(end_date_str)) \
387
+ .filterBounds(roi)
388
+
389
+ image = get_most_recent_image(collection)
390
+
391
+ if not image:
392
+ st.warning(f"No images found for {location_name}.")
393
+ else:
394
+ st.write(f"Found an image for {location_name}.")
395
+ result = None
396
+ if index_choice.lower() == 'ndvi':
397
+ result = calculate_ndvi(image, roi)
398
+ elif index_choice.lower() == 'ndwi':
399
+ result = calculate_ndwi(image, roi)
400
+ elif index_choice.lower() == 'average no₂':
401
+ if 'NO2' in image.bandNames().getInfo():
402
+ result = calculate_avg_no2_sentinel5p(image, roi)
403
+ else:
404
+ st.warning(f"No NO2 band found for {location_name}. Please use Sentinel-5P for NO₂ data.")
405
+ elif index_choice.lower() == 'custom formula' and custom_formula:
406
+ result = process_custom_formula(image, roi, custom_formula)
407
+
408
+ if result is not None:
409
+ # Initialize the calculated_value as None
410
+ calculated_value = None
411
+
412
+ # Check if the result is a dictionary (e.g., custom formula result)
413
+ if isinstance(result, dict) and 'CustomResult' in result:
414
+ calculated_value = result['CustomResult'] # Extract the numeric value from the dictionary
415
+ # If the result is a numeric value (e.g., NDVI, NDWI, or NO2)
416
+ elif isinstance(result, (int, float)):
417
+ calculated_value = result
418
+
419
+ # If a valid calculated_value is found, append the result to session_state
420
+ if calculated_value is not None:
421
+ st.session_state.results.append({
422
+ 'Location Name': location_name,
423
+ 'Calculated Value': calculated_value
424
+ })
425
+
426
+ # After processing, show the results
427
+ if st.session_state.results:
428
+ result_df = pd.DataFrame(st.session_state.results)
429
+
430
+ if shape_type.lower() == 'point':
431
+ st.write("Processed Results Table (Points):")
432
+ st.dataframe(result_df[['Location Name', 'Latitude', 'Longitude', 'Calculated Value']])
433
+ else:
434
+ st.write("Processed Results Table (Polygons):")
435
+ st.dataframe(result_df[['Location Name', 'Calculated Value']])
436
+
437
+ filename = f"{main_selection}_{sub_selection}_{start_date.strftime('%Y/%m/%d')}_{end_date.strftime('%Y/%m/%d')}_{shape_type}.csv"
438
+
439
+ st.download_button(
440
+ label="Download results as CSV",
441
+ data=result_df.to_csv(index=False).encode('utf-8'),
442
+ file_name=filename,
443
+ mime='text/csv'
444
+ )