YashMK89 commited on
Commit
71db07d
·
verified ·
1 Parent(s): 9739e03

update app.py

Browse files
Files changed (1) hide show
  1. app.py +89 -114
app.py CHANGED
@@ -87,13 +87,6 @@ elif index_choice.lower() == 'custom formula':
87
  custom_formula = st.text_input("Enter Custom Formula (e.g., '(B5 - B4) / (B5 + B4)')")
88
  st.write(f"Custom Formula: {custom_formula}") # Display the custom formula after the user inputs it
89
 
90
- # Reducer selection
91
- reducer_choice = st.selectbox(
92
- "Select Reducer",
93
- ['mean', 'sum', 'median', 'min', 'max', 'count'],
94
- index=0 # Default to 'mean'
95
- )
96
-
97
  # Function to check if the polygon geometry is valid and convert it to the correct format
98
  def convert_to_ee_geometry(geometry):
99
  if geometry.is_valid:
@@ -164,29 +157,6 @@ if parameters_changed():
164
  'file_upload': file_upload
165
  }
166
 
167
- # Function to get the corresponding reducer based on user input
168
- def get_reducer(reducer_name):
169
- """
170
- Map user-friendly reducer names to Earth Engine reducer objects.
171
-
172
- Args:
173
- reducer_name (str): The name of the reducer (e.g., 'mean', 'sum', 'median').
174
-
175
- Returns:
176
- ee.Reducer: The corresponding Earth Engine reducer.
177
- """
178
- reducers = {
179
- 'mean': ee.Reducer.mean(),
180
- 'sum': ee.Reducer.sum(),
181
- 'median': ee.Reducer.median(),
182
- 'min': ee.Reducer.min(),
183
- 'max': ee.Reducer.max(),
184
- 'count': ee.Reducer.count(),
185
- }
186
-
187
- # Default to 'mean' if the reducer_name is not recognized
188
- return reducers.get(reducer_name.lower(), ee.Reducer.mean())
189
-
190
  # Function to perform index calculations
191
  def calculate_ndvi(image, geometry):
192
  ndvi = image.normalizedDifference(['B8', 'B4']).rename('NDVI')
@@ -253,19 +223,22 @@ def get_most_recent_image(image_collection):
253
  # Function to handle the custom formula choice and calculation
254
  def process_custom_formula(image, roi, custom_formula):
255
  if custom_formula:
 
256
  result = calculate_custom_formula(image, roi, custom_formula)
257
  if result:
258
- return result.getInfo()
 
 
 
 
 
259
  return None
260
 
261
- locations_df = None # Initialize locations_df to None
262
- polygons_df = None # Ensure polygons_df is initialized at the beginning
263
-
264
  # Process each point (with additional checks for file validity)
265
  # Check the shape type and assign polygons_df only for Polygon data
266
  if file_upload:
267
- # locations_df = None # Initialize locations_df to None
268
- # polygons_df = None # Ensure polygons_df is initialized at the beginning
269
 
270
  file_extension = os.path.splitext(file_upload.name)[1].lower()
271
 
@@ -336,8 +309,6 @@ if file_upload:
336
  .filterDate(ee.Date(start_date_str), ee.Date(end_date_str)) \
337
  .filterBounds(roi)
338
 
339
- # # Apply frequency-based filtering and reduction
340
- # result, result_date = calculate_index_by_frequency(collection, frequency_choice, roi, reducer)
341
  image = get_most_recent_image(collection)
342
  if not image:
343
  st.warning(f"No images found for {location_name}.")
@@ -380,85 +351,90 @@ if file_upload:
380
  'Latitude': latitude,
381
  'Longitude': longitude,
382
  'Calculated Value': calculated_value
383
- # 'Date': result_date # Add the date of the calculation
384
  })
385
  else:
386
  st.warning(f"No value calculated for {location_name}.")
387
  else:
388
  st.warning(f"No value calculated for {location_name}.")
389
-
390
-
391
- # Check if polygons_df is populated for polygons
392
- if polygons_df is not None:
393
- st.write("Preview of the uploaded polygons data:")
394
- st.dataframe(polygons_df.head())
395
-
396
- m = leafmap.Map(center=[polygons_df.geometry.centroid.y.mean(), polygons_df.geometry.centroid.x.mean()], zoom=10)
397
-
398
- for _, row in polygons_df.iterrows():
399
- polygon = row['geometry']
400
- if polygon.is_valid:
401
- gdf = gpd.GeoDataFrame([row], geometry=[polygon], crs=polygons_df.crs)
402
- m.add_gdf(gdf=gdf, layer_name=row.get('name', 'Unnamed Polygon'))
403
-
404
- st.write("Map of Uploaded Polygons:")
405
- m.to_streamlit()
406
- st.session_state.map_data = m
407
-
408
- # Processing for each polygon
409
- for idx, row in polygons_df.iterrows():
410
- polygon = row['geometry']
411
- location_name = row.get('name', f"Polygon_{idx}")
412
-
413
- try:
414
- roi = convert_to_ee_geometry(polygon) # Convert to Earth Engine geometry
415
- except ValueError as e:
416
- st.error(str(e))
417
- continue
418
-
419
- # Load the Sentinel image collection
420
- collection = ee.ImageCollection(sub_options[sub_selection]) \
421
- .filterDate(ee.Date(start_date_str), ee.Date(end_date_str)) \
422
- .filterBounds(roi)
423
-
424
- image = get_most_recent_image(collection) # Get the most recent image from the collection
425
-
426
- if not image:
427
- st.warning(f"No images found for {location_name}.")
428
- else:
429
- st.write(f"Found an image for {location_name}.")
430
-
431
- # Perform the calculation based on the selected index
432
- result = None
433
- if index_choice.lower() == 'ndvi':
434
- result = calculate_ndvi(image, roi)
435
- elif index_choice.lower() == 'ndwi':
436
- result = calculate_ndwi(image, roi)
437
- elif index_choice.lower() == 'average no₂':
438
- if 'NO2' in image.bandNames().getInfo():
439
- result = calculate_avg_no2_sentinel5p(image, roi)
440
- else:
441
- st.warning(f"No NO2 band found for {location_name}. Please use Sentinel-5P for NO₂ data.")
442
- elif index_choice.lower() == 'custom formula' and custom_formula:
443
- result = process_custom_formula(image, roi, custom_formula)
444
-
445
- if result is not None:
446
- # Extract the calculated value (this could be a dictionary or numeric value)
447
- calculated_value = None
448
-
449
- # If the result is a dictionary (e.g., custom formula result)
450
- if isinstance(result, dict) and 'CustomResult' in result:
451
- calculated_value = result['CustomResult']
452
- # If the result is a numeric value (e.g., NDVI, NDWI, or NO2)
453
- elif isinstance(result, (int, float)):
454
- calculated_value = result
455
-
456
- # If a valid calculated_value is found, append the result
457
- if calculated_value is not None:
458
- st.session_state.results.append({
459
- 'Location Name': location_name,
460
- 'Calculated Value': calculated_value
461
- })
 
 
 
 
 
 
462
 
463
 
464
  # After processing, show the results
@@ -479,5 +455,4 @@ if st.session_state.results:
479
  data=result_df.to_csv(index=False).encode('utf-8'),
480
  file_name=filename,
481
  mime='text/csv'
482
- )
483
-
 
87
  custom_formula = st.text_input("Enter Custom Formula (e.g., '(B5 - B4) / (B5 + B4)')")
88
  st.write(f"Custom Formula: {custom_formula}") # Display the custom formula after the user inputs it
89
 
 
 
 
 
 
 
 
90
  # Function to check if the polygon geometry is valid and convert it to the correct format
91
  def convert_to_ee_geometry(geometry):
92
  if geometry.is_valid:
 
157
  'file_upload': file_upload
158
  }
159
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
  # Function to perform index calculations
161
  def calculate_ndvi(image, geometry):
162
  ndvi = image.normalizedDifference(['B8', 'B4']).rename('NDVI')
 
223
  # Function to handle the custom formula choice and calculation
224
  def process_custom_formula(image, roi, custom_formula):
225
  if custom_formula:
226
+ # Call the calculate_custom_formula function which processes the custom formula
227
  result = calculate_custom_formula(image, roi, custom_formula)
228
  if result:
229
+ # If result is a dictionary (which is likely for custom formula), extract the value
230
+ if isinstance(result, dict) and 'CustomResult' in result:
231
+ return result['CustomResult'] # Directly return the value from the dictionary
232
+ # Otherwise, it's an Earth Engine object, so we get the value with getInfo()
233
+ else:
234
+ return result.getInfo() # Return the result for an Earth Engine object
235
  return None
236
 
 
 
 
237
  # Process each point (with additional checks for file validity)
238
  # Check the shape type and assign polygons_df only for Polygon data
239
  if file_upload:
240
+ locations_df = None # Initialize locations_df to None
241
+ polygons_df = None # Ensure polygons_df is initialized at the beginning
242
 
243
  file_extension = os.path.splitext(file_upload.name)[1].lower()
244
 
 
309
  .filterDate(ee.Date(start_date_str), ee.Date(end_date_str)) \
310
  .filterBounds(roi)
311
 
 
 
312
  image = get_most_recent_image(collection)
313
  if not image:
314
  st.warning(f"No images found for {location_name}.")
 
351
  'Latitude': latitude,
352
  'Longitude': longitude,
353
  'Calculated Value': calculated_value
 
354
  })
355
  else:
356
  st.warning(f"No value calculated for {location_name}.")
357
  else:
358
  st.warning(f"No value calculated for {location_name}.")
359
+
360
+
361
+ # Ensure st.session_state.results is initialized
362
+ if 'results' not in st.session_state:
363
+ st.session_state.results = []
364
+
365
+ # Check if polygons_df is populated for polygons
366
+ if polygons_df is not None and not polygons_df.empty:
367
+ st.write("Preview of the uploaded polygons data:")
368
+ st.dataframe(polygons_df.head())
369
+
370
+ # Initialize map and display polygons
371
+ m = leafmap.Map(center=[polygons_df.geometry.centroid.y.mean(), polygons_df.geometry.centroid.x.mean()], zoom=10)
372
+ for _, row in polygons_df.iterrows():
373
+ polygon = row['geometry']
374
+ if polygon.is_valid:
375
+ gdf = gpd.GeoDataFrame([row], geometry=[polygon], crs=polygons_df.crs)
376
+ m.add_gdf(gdf=gdf, layer_name=row.get('name', 'Unnamed Polygon'))
377
+
378
+ st.write("Map of Uploaded Polygons:")
379
+ m.to_streamlit()
380
+ st.session_state.map_data = m
381
+
382
+ # Process each polygon
383
+ for idx, row in polygons_df.iterrows():
384
+ polygon = row['geometry']
385
+ location_name = row.get('name', f"Polygon_{idx}")
386
+
387
+ try:
388
+ roi = convert_to_ee_geometry(polygon) # Convert to EE Geometry
389
+ except ValueError as e:
390
+ st.error(f"Error converting polygon {location_name}: {str(e)}")
391
+ continue
392
+
393
+ # Fetch image collection
394
+ collection = ee.ImageCollection(sub_options[sub_selection]) \
395
+ .filterDate(ee.Date(start_date_str), ee.Date(end_date_str)) \
396
+ .filterBounds(roi)
397
+
398
+ image = get_most_recent_image(collection)
399
+
400
+ if not image:
401
+ st.warning(f"No images found for {location_name}.")
402
+ else:
403
+ st.write(f"Found an image for {location_name}.")
404
+ result = None
405
+
406
+ # Calculate index based on user's choice
407
+ if index_choice.lower() == 'NDVI':
408
+ result = calculate_ndvi(image, roi)
409
+ elif index_choice.lower() == 'NDWI':
410
+ result = calculate_ndwi(image, roi)
411
+ elif index_choice.lower() == 'Average NO₂':
412
+ if 'NO2' in image.bandNames().getInfo():
413
+ result = calculate_avg_no2_sentinel5p(image, roi)
414
+ else:
415
+ st.warning(f"No NO2 band found for {location_name}. Please use Sentinel-5P for NO₂ data.")
416
+ elif index_choice.lower() == 'custom formula' and custom_formula:
417
+ result = process_custom_formula(image, roi, custom_formula)
418
+
419
+ # Ensure result is properly extracted and displayed
420
+ if result is not None:
421
+ calculated_value = None
422
+
423
+ if isinstance(result, ee.Dictionary):
424
+ # Extract the numeric value for custom formula results
425
+ calculated_value = result.get('constant').getInfo()
426
+ elif isinstance(result, ee.Number):
427
+ # Direct numeric result
428
+ calculated_value = result.getInfo()
429
+
430
+ if calculated_value is not None:
431
+ st.write(f"Calculated {index_choice.upper()} for {location_name}: {calculated_value}")
432
+ st.session_state.results.append({
433
+ 'Location Name': location_name,
434
+ 'Calculated Value': calculated_value
435
+ })
436
+ else:
437
+ st.error(f"Error extracting the result for {location_name}.")
438
 
439
 
440
  # After processing, show the results
 
455
  data=result_df.to_csv(index=False).encode('utf-8'),
456
  file_name=filename,
457
  mime='text/csv'
458
+ )