YashMK89 commited on
Commit
78c832c
·
verified ·
1 Parent(s): 55bded4

update app.py

Browse files
Files changed (1) hide show
  1. app.py +35 -118
app.py CHANGED
@@ -73,48 +73,24 @@ elif imagery_base == "MODIS":
73
  with open(dataset_file) as f:
74
  data = json.load(f)
75
  elif imagery_base == "Custom Input":
76
- custom_dataset_id = st.text_input(
77
- "Enter Custom Earth Engine Dataset ID (e.g., ee.Image('ACA/reef_habitat/v2_0') or ee.ImageCollection('AHN/AHN4'))",
78
- value=""
79
- )
80
  if custom_dataset_id:
81
  try:
82
- if custom_dataset_id.startswith("ee.Image("):
83
- dataset_id = custom_dataset_id.replace("ee.Image('", "").replace("')", "")
84
- is_image = True
85
- elif custom_dataset_id.startswith("ee.ImageCollection("):
86
- dataset_id = custom_dataset_id.replace("ee.ImageCollection('", "").replace("')", "")
87
- is_image = False
88
- else:
89
- dataset_id = custom_dataset_id
90
- try:
91
- ee.Image(dataset_id).getInfo()
92
- is_image = True
93
- except:
94
- is_image = False
95
-
96
- if is_image:
97
- image = ee.Image(dataset_id)
98
- band_names = image.bandNames().getInfo()
99
- data = {
100
- f"Custom Image: {dataset_id}": {
101
- "sub_options": {dataset_id: f"Custom Image ({dataset_id})"},
102
- "bands": {dataset_id: band_names}
103
- }
104
  }
105
- st.write(f"Fetched bands for {dataset_id} (Image): {', '.join(band_names)}")
106
- else:
107
- collection = ee.ImageCollection(dataset_id)
108
- band_names = collection.first().bandNames().getInfo()
109
- data = {
110
- f"Custom ImageCollection: {dataset_id}": {
111
- "sub_options": {dataset_id: f"Custom ImageCollection ({dataset_id})"},
112
- "bands": {dataset_id: band_names}
113
- }
114
- }
115
- st.write(f"Fetched bands for {dataset_id} (ImageCollection): {', '.join(band_names)}")
116
  except Exception as e:
117
- st.error(f"Error fetching dataset: {str(e)}. Please check the dataset ID.")
118
  data = {}
119
  else:
120
  st.warning("Please enter a custom dataset ID to proceed.")
@@ -138,25 +114,15 @@ if main_selection:
138
  sub_options = data[main_selection]["sub_options"]
139
  sub_selection = st.selectbox(f"Select Specific {imagery_base} Dataset ID", list(sub_options.keys()))
140
 
 
141
  if sub_selection:
142
  st.write(f"You selected: {main_selection} -> {sub_options[sub_selection]}")
143
  st.write(f"Dataset ID: {sub_selection}")
144
- dataset_id = sub_selection
145
 
146
  # Earth Engine Index Calculator Section
147
  st.header("Earth Engine Index Calculator")
148
 
149
- # Define validate_formula function
150
- def validate_formula(formula, selected_bands):
151
- allowed_chars = set(" +-*/()0123456789.")
152
- terms = re.findall(r'[a-zA-Z][a-zA-Z0-9_]*', formula)
153
- invalid_terms = [term for term in terms if term not in selected_bands]
154
- if invalid_terms:
155
- return False, f"Invalid terms in formula: {', '.join(invalid_terms)}. Use only {', '.join(selected_bands)}."
156
- if not all(char in allowed_chars or char in ''.join(selected_bands) for char in formula):
157
- return False, "Formula contains invalid characters. Use only bands, numbers, and operators (+, -, *, /, ())"
158
- return True, ""
159
-
160
  # Load band information based on selected dataset
161
  if main_selection and sub_selection:
162
  dataset_bands = data[main_selection]["bands"].get(sub_selection, [])
@@ -170,27 +136,38 @@ if main_selection and sub_selection:
170
  help=f"Select 1 or 2 bands from: {', '.join(dataset_bands)}"
171
  )
172
 
173
- # Ensure minimum 1
174
  if len(selected_bands) < 1:
175
  st.warning("Please select at least one band.")
176
  st.stop()
177
 
178
  # Show custom formula input if bands are selected
179
  if selected_bands:
 
180
  if len(selected_bands) == 1:
181
  default_formula = f"{selected_bands[0]}"
182
  example = f"'{selected_bands[0]} * 2' or '{selected_bands[0]} + 1'"
183
- else:
184
  default_formula = f"({selected_bands[0]} - {selected_bands[1]}) / ({selected_bands[0]} + {selected_bands[1]})"
185
  example = f"'{selected_bands[0]} * {selected_bands[1]} / 2' or '({selected_bands[0]} - {selected_bands[1]}) / ({selected_bands[0]} + {selected_bands[1]})'"
186
 
187
  custom_formula = st.text_input(
188
- "Enter Custom Formula (e.g., 'B3*B5/2' or '(B8 - B4) / (B8 + B4)')",
189
  value=default_formula,
190
  help=f"Use only these bands: {', '.join(selected_bands)}. Examples: {example}"
191
  )
192
 
193
  # Validate the formula
 
 
 
 
 
 
 
 
 
 
194
  is_valid, error_message = validate_formula(custom_formula, selected_bands)
195
  if not is_valid:
196
  st.error(error_message)
@@ -199,7 +176,10 @@ if main_selection and sub_selection:
199
  st.warning("Please enter a custom formula to proceed.")
200
  st.stop()
201
 
 
202
  st.write(f"Custom Formula: {custom_formula}")
 
 
203
 
204
  # Function to get the corresponding reducer based on user input
205
  def get_reducer(reducer_name):
@@ -454,7 +434,7 @@ def calculate_custom_formula(image, geometry, selected_bands, custom_formula, re
454
  except Exception as e:
455
  st.error(f"Unexpected error: {e}")
456
  return ee.Image(0).rename('custom_result').set('error', str(e))
457
-
458
  # Function to calculate index for a period
459
  def calculate_index_for_period(image, roi, selected_bands, custom_formula, reducer_choice):
460
  return calculate_custom_formula(image, roi, selected_bands, custom_formula, reducer_choice)
@@ -514,30 +494,7 @@ def process_aggregation(locations_df, start_date_str, end_date_str, dataset_id,
514
  if not custom_formula:
515
  st.error("Custom formula cannot be empty. Please provide a formula.")
516
  return aggregated_results
517
-
518
- # Initialize is_image and scale with default values
519
- is_image = False # Default to False, will be updated based on dataset type
520
- scale = 30 # Default scale, will be overridden for ee.Image if possible
521
 
522
- # Check if dataset_id is an ee.Image or ee.ImageCollection
523
- try:
524
- dataset = ee.Image(dataset_id)
525
- is_image = True
526
- # Try to get the nominal scale from the dataset
527
- try:
528
- scale = dataset.projection().nominalScale().getInfo()
529
- except:
530
- st.warning(f"Could not determine nominal scale for {dataset_id}. Using default scale of 30m.")
531
- scale = 30
532
- except:
533
- try:
534
- dataset = ee.ImageCollection(dataset_id)
535
- is_image = False
536
- scale = 30 # Default scale for ImageCollections
537
- except Exception as e:
538
- st.error(f"Invalid dataset ID '{dataset_id}': {str(e)}. Must be a valid ee.Image or ee.ImageCollection.")
539
- return aggregated_results
540
-
541
  total_steps = len(locations_df)
542
  progress_bar = st.progress(0)
543
  progress_text = st.empty()
@@ -565,36 +522,7 @@ def process_aggregation(locations_df, start_date_str, end_date_str, dataset_id,
565
  collection = ee.ImageCollection(dataset_id) \
566
  .filterDate(ee.Date(start_date_str), ee.Date(end_date_str)) \
567
  .filterBounds(roi)
568
-
569
- if is_image:
570
- # Handle any ee.Image dataset
571
- image = dataset
572
- index_image = calculate_custom_formula(image, roi, selected_bands, custom_formula, reducer_choice, scale=scale)
573
- index_value = index_image.reduceRegion(
574
- reducer=get_reducer(reducer_choice),
575
- geometry=roi,
576
- scale=scale # Use the dataset's native scale or default
577
- ).get('custom_result')
578
- calculated_value = index_value.getInfo()
579
-
580
- if isinstance(calculated_value, (int, float)):
581
- aggregated_results.append({
582
- 'Location Name': location_name,
583
- 'Latitude': latitude,
584
- 'Longitude': longitude,
585
- 'Date': 'Static', # Static image has no time dimension
586
- 'Start Date': start_date_str,
587
- 'End Date': end_date_str,
588
- 'Calculated Value': calculated_value
589
- })
590
- else:
591
- st.warning(f"Skipping invalid value for {location_name}")
592
- else:
593
- # Handle ee.ImageCollection (existing logic)
594
- collection = dataset \
595
- .filterDate(ee.Date(start_date_str), ee.Date(end_date_str)) \
596
- .filterBounds(roi)
597
-
598
  if aggregation_period.lower() == 'custom (start date to end date)':
599
  collection = aggregate_data_custom(collection)
600
  elif aggregation_period.lower() == 'weekly':
@@ -674,17 +602,6 @@ def process_aggregation(locations_df, start_date_str, end_date_str, dataset_id,
674
  except ValueError as e:
675
  st.warning(f"Skipping invalid polygon {polygon_name}: {e}")
676
  continue
677
-
678
- if is_image:
679
- # Handle any ee.Image dataset
680
- image = dataset
681
- index_image = calculate_custom_formula(image, roi, selected_bands, custom_formula, reducer_choice, scale=scale)
682
- index_value = index_image.reduceRegion(
683
- reducer=get_reducer(reducer_choice),
684
- geometry=roi,
685
- scale=scale
686
- ).get('custom_result')
687
- calculated_value = index_value.getInfo()
688
 
689
  collection = ee.ImageCollection(dataset_id) \
690
  .filterDate(ee.Date(start_date_str), ee.Date(end_date_str)) \
 
73
  with open(dataset_file) as f:
74
  data = json.load(f)
75
  elif imagery_base == "Custom Input":
76
+ custom_dataset_id = st.text_input("Enter Custom Earth Engine Dataset ID (e.g., ee.ImageCollection('AHN/AHN4'))", value="")
 
 
 
77
  if custom_dataset_id:
78
  try:
79
+ # Remove potential "ee.ImageCollection()" wrapper for simplicity
80
+ if custom_dataset_id.startswith("ee.ImageCollection("):
81
+ custom_dataset_id = custom_dataset_id.replace("ee.ImageCollection('", "").replace("')", "")
82
+ # Fetch dataset info from GEE
83
+ collection = ee.ImageCollection(custom_dataset_id)
84
+ band_names = collection.first().bandNames().getInfo()
85
+ data = {
86
+ f"Custom Dataset: {custom_dataset_id}": {
87
+ "sub_options": {custom_dataset_id: f"Custom Dataset ({custom_dataset_id})"},
88
+ "bands": {custom_dataset_id: band_names}
 
 
 
 
 
 
 
 
 
 
 
 
89
  }
90
+ }
91
+ st.write(f"Fetched bands for {custom_dataset_id}: {', '.join(band_names)}")
 
 
 
 
 
 
 
 
 
92
  except Exception as e:
93
+ st.error(f"Error fetching dataset: {str(e)}. Please check the dataset ID and ensure it's valid in Google Earth Engine.")
94
  data = {}
95
  else:
96
  st.warning("Please enter a custom dataset ID to proceed.")
 
114
  sub_options = data[main_selection]["sub_options"]
115
  sub_selection = st.selectbox(f"Select Specific {imagery_base} Dataset ID", list(sub_options.keys()))
116
 
117
+ # Display the selected dataset ID based on user input
118
  if sub_selection:
119
  st.write(f"You selected: {main_selection} -> {sub_options[sub_selection]}")
120
  st.write(f"Dataset ID: {sub_selection}")
121
+ dataset_id = sub_selection # Use the key directly as the dataset ID
122
 
123
  # Earth Engine Index Calculator Section
124
  st.header("Earth Engine Index Calculator")
125
 
 
 
 
 
 
 
 
 
 
 
 
126
  # Load band information based on selected dataset
127
  if main_selection and sub_selection:
128
  dataset_bands = data[main_selection]["bands"].get(sub_selection, [])
 
136
  help=f"Select 1 or 2 bands from: {', '.join(dataset_bands)}"
137
  )
138
 
139
+ # Ensure minimum 1 and maximum 2 bands are selected
140
  if len(selected_bands) < 1:
141
  st.warning("Please select at least one band.")
142
  st.stop()
143
 
144
  # Show custom formula input if bands are selected
145
  if selected_bands:
146
+ # Provide a default formula based on the number of selected bands
147
  if len(selected_bands) == 1:
148
  default_formula = f"{selected_bands[0]}"
149
  example = f"'{selected_bands[0]} * 2' or '{selected_bands[0]} + 1'"
150
+ else: # len(selected_bands) == 2
151
  default_formula = f"({selected_bands[0]} - {selected_bands[1]}) / ({selected_bands[0]} + {selected_bands[1]})"
152
  example = f"'{selected_bands[0]} * {selected_bands[1]} / 2' or '({selected_bands[0]} - {selected_bands[1]}) / ({selected_bands[0]} + {selected_bands[1]})'"
153
 
154
  custom_formula = st.text_input(
155
+ "Enter Custom Formula",
156
  value=default_formula,
157
  help=f"Use only these bands: {', '.join(selected_bands)}. Examples: {example}"
158
  )
159
 
160
  # Validate the formula
161
+ def validate_formula(formula, selected_bands):
162
+ allowed_chars = set(" +-*/()0123456789.")
163
+ terms = re.findall(r'[a-zA-Z][a-zA-Z0-9_]*', formula)
164
+ invalid_terms = [term for term in terms if term not in selected_bands]
165
+ if invalid_terms:
166
+ return False, f"Invalid terms in formula: {', '.join(invalid_terms)}. Use only {', '.join(selected_bands)}."
167
+ if not all(char in allowed_chars or char in ''.join(selected_bands) for char in formula):
168
+ return False, "Formula contains invalid characters. Use only bands, numbers, and operators (+, -, *, /, ())"
169
+ return True, ""
170
+
171
  is_valid, error_message = validate_formula(custom_formula, selected_bands)
172
  if not is_valid:
173
  st.error(error_message)
 
176
  st.warning("Please enter a custom formula to proceed.")
177
  st.stop()
178
 
179
+ # Display the validated formula
180
  st.write(f"Custom Formula: {custom_formula}")
181
+
182
+ # The rest of your code (reducer, geometry conversion, date input, aggregation, etc.) remains unchanged...
183
 
184
  # Function to get the corresponding reducer based on user input
185
  def get_reducer(reducer_name):
 
434
  except Exception as e:
435
  st.error(f"Unexpected error: {e}")
436
  return ee.Image(0).rename('custom_result').set('error', str(e))
437
+
438
  # Function to calculate index for a period
439
  def calculate_index_for_period(image, roi, selected_bands, custom_formula, reducer_choice):
440
  return calculate_custom_formula(image, roi, selected_bands, custom_formula, reducer_choice)
 
494
  if not custom_formula:
495
  st.error("Custom formula cannot be empty. Please provide a formula.")
496
  return aggregated_results
 
 
 
 
497
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
498
  total_steps = len(locations_df)
499
  progress_bar = st.progress(0)
500
  progress_text = st.empty()
 
522
  collection = ee.ImageCollection(dataset_id) \
523
  .filterDate(ee.Date(start_date_str), ee.Date(end_date_str)) \
524
  .filterBounds(roi)
525
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
526
  if aggregation_period.lower() == 'custom (start date to end date)':
527
  collection = aggregate_data_custom(collection)
528
  elif aggregation_period.lower() == 'weekly':
 
602
  except ValueError as e:
603
  st.warning(f"Skipping invalid polygon {polygon_name}: {e}")
604
  continue
 
 
 
 
 
 
 
 
 
 
 
605
 
606
  collection = ee.ImageCollection(dataset_id) \
607
  .filterDate(ee.Date(start_date_str), ee.Date(end_date_str)) \