Esmaeilkiani commited on
Commit
33af4fe
1 Parent(s): 1f9fc78

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +116 -168
app.py CHANGED
@@ -1,177 +1,125 @@
1
  import streamlit as st
2
  import ee
3
- import geemap
4
  import pandas as pd
5
- from datetime import datetime, timedelta
6
  import matplotlib.pyplot as plt
7
- import folium
 
8
  import os
 
9
 
10
- # Constants
11
- NDRE_HARVEST_THRESHOLD = 0.3
12
- NDMI_HARVEST_THRESHOLD = 0.4
13
- CSV_URL = "https://huggingface.co/spaces/Esmaeilkiani/AppSugarcane/resolve/main/Farm_Details_Export.csv"
14
- PRIVATE_KEY_PATH = os.environ.get("ee-esmaeilkiani1387-1b2c5e812a1d.json")
15
-
16
- # Page configuration
17
- st.set_page_config(page_title="Sugarcane Field Monitoring", layout="wide")
18
-
19
- # GEE Authentication
20
- def authenticate_gee():
21
- try:
22
- credentials = ee.ServiceAccountCredentials(None, PRIVATE_KEY_PATH)
23
- ee.Initialize(credentials)
24
- return True
25
- except Exception as e:
26
- st.error(f"Failed to authenticate with Google Earth Engine: {str(e)}")
27
- return False
28
-
29
- # Load farm data
30
- @st.cache_data
31
- def load_farm_data():
32
- try:
33
- df = pd.read_csv(CSV_URL)
34
- if not all(col in df.columns for col in ["farm_name", "latitude", "longitude"]):
35
- raise ValueError("CSV file is missing required columns")
36
- return df
37
- except Exception as e:
38
- st.error(f"Error loading farm data: {str(e)}")
39
- return None
40
-
41
- # Get indices data from GEE
42
- def get_indices_data(farm_coords, start_date, end_date):
43
- point = ee.Geometry.Point(farm_coords)
44
- s2 = ee.ImageCollection("COPERNICUS/S2_SR")
45
-
46
- filtered = s2.filterBounds(point).filterDate(start_date, end_date)
47
-
48
- def add_indices(image):
49
- ndre = image.normalizedDifference(['B8', 'B5']).rename('NDRE')
50
- ndmi = image.normalizedDifference(['B8A', 'B11']).rename('NDMI')
51
- return image.addBands([ndre, ndmi])
52
-
53
- with_indices = filtered.map(add_indices)
54
-
55
- time_series = with_indices.select(['NDRE', 'NDMI']).getRegion(point, 500)
56
-
57
- return time_series
58
-
59
- # Extract index data from GEE results
60
- def extract_index_data(data, index_name):
61
- try:
62
- dates = [datetime.utcfromtimestamp(d[3] / 1000) for d in data[1:]]
63
- values = [float(d[4]) if d[4] is not None else None for d in data[1:]]
64
- return pd.DataFrame({
65
- 'date': dates,
66
- index_name: values
67
- }).dropna().set_index('date')
68
- except Exception as e:
69
- st.error(f"Error extracting {index_name} data: {str(e)}")
70
- return pd.DataFrame()
71
-
72
- # Main application
73
- def main():
74
- if not authenticate_gee():
75
- return
76
-
77
- st.title("Sugarcane Field Monitoring")
78
-
79
- farm_data = load_farm_data()
80
- if farm_data is None:
81
- return
82
-
83
- # Sidebar
84
- st.sidebar.header("Settings")
85
- farm_name = st.sidebar.selectbox("Select Farm", farm_data['farm_name'].tolist())
86
- start_date = st.sidebar.date_input("Start Date", datetime.now() - timedelta(days=30))
87
- end_date = st.sidebar.date_input("End Date", datetime.now())
88
 
89
- if end_date > datetime.now().date():
90
- st.sidebar.error("End date cannot be in the future.")
91
- return
 
 
 
92
 
93
- indices = st.sidebar.multiselect("Select Indices", ["NDRE", "NDMI"], default=["NDRE", "NDMI"])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
 
95
- if st.sidebar.button("Submit"):
96
- farm_row = farm_data[farm_data['farm_name'] == farm_name].iloc[0]
97
- farm_coords = [farm_row['longitude'], farm_row['latitude']]
98
-
99
- with st.spinner("Fetching data..."):
100
- gee_data = get_indices_data(farm_coords, start_date, end_date)
101
-
102
- if gee_data:
103
- ndre_data = extract_index_data(gee_data.getInfo(), "NDRE")
104
- ndmi_data = extract_index_data(gee_data.getInfo(), "NDMI")
105
-
106
- # Plotting
107
- fig, ax = plt.subplots(figsize=(12, 6))
108
-
109
- if "NDRE" in indices and not ndre_data.empty:
110
- ax.plot(ndre_data.index, ndre_data["NDRE"], label="NDRE")
111
- ax.axhline(y=NDRE_HARVEST_THRESHOLD, color='r', linestyle='--', label="NDRE Harvest Threshold")
112
-
113
- if "NDMI" in indices and not ndmi_data.empty:
114
- ax.plot(ndmi_data.index, ndmi_data["NDMI"], label="NDMI")
115
- ax.axhline(y=NDMI_HARVEST_THRESHOLD, color='g', linestyle='--', label="NDMI Harvest Threshold")
116
-
117
- ax.set_xlabel("Date")
118
- ax.set_ylabel("Index Value")
119
- ax.set_title(f"Time Series for {farm_name}")
120
- ax.legend()
121
-
122
- st.pyplot(fig)
123
-
124
- # Harvest Analysis
125
- if "NDRE" in indices and not ndre_data.empty:
126
- if ndre_data["NDRE"].iloc[-1] > NDRE_HARVEST_THRESHOLD:
127
- st.success("NDRE indicates the field may be ready for harvest.")
128
- else:
129
- st.info("NDRE suggests the field is not yet ready for harvest.")
130
-
131
- if "NDMI" in indices and not ndmi_data.empty:
132
- if ndmi_data["NDMI"].iloc[-1] > NDMI_HARVEST_THRESHOLD:
133
- st.success("NDMI indicates good moisture content for harvest.")
134
- else:
135
- st.info("NDMI suggests suboptimal moisture content for harvest.")
136
-
137
- # Map
138
- m = geemap.Map(center=farm_coords, zoom=12)
139
- m.add_basemap("OpenStreetMap")
140
-
141
- if "NDRE" in indices:
142
- ndre_layer = geemap.ee_tile_layer(
143
- with_indices.select('NDRE').mean(),
144
- {'min': 0, 'max': 1, 'palette': ['red', 'yellow', 'green']},
145
- 'NDRE'
146
- )
147
- m.add_layer(ndre_layer)
148
-
149
- if "NDMI" in indices:
150
- ndmi_layer = geemap.ee_tile_layer(
151
- with_indices.select('NDMI').mean(),
152
- {'min': -1, 'max': 1, 'palette': ['red', 'white', 'blue']},
153
- 'NDMI'
154
- )
155
- m.add_layer(ndmi_layer)
156
-
157
- marker = folium.Marker(
158
- location=farm_coords[::-1],
159
- popup=f"Farm: {farm_name}<br>Lat: {farm_coords[1]}<br>Lon: {farm_coords[0]}"
160
- )
161
- marker.add_to(m)
162
-
163
- m.to_streamlit(height=600)
164
-
165
- # Map Download
166
- map_html = m.to_html()
167
- st.download_button(
168
- label="Download Map",
169
- data=map_html,
170
- file_name="sugarcane_field_map.html",
171
- mime="text/html"
172
- )
173
- else:
174
- st.error("Failed to retrieve data from Google Earth Engine.")
175
-
176
- if __name__ == "__main__":
177
- main()
 
1
  import streamlit as st
2
  import ee
3
+ import geemap.foliumap as geemap
4
  import pandas as pd
5
+ import datetime
6
  import matplotlib.pyplot as plt
7
+ import geopandas as gpd
8
+ import zipfile
9
  import os
10
+ import requests
11
 
12
+ # اعتبار سنجی و اتصال به Google Earth Engine
13
+ service_account = 'earth-engine-service-account@ee-esmaeilkiani1387.iam.gserviceaccount.com'
14
+ credentials = ee.ServiceAccountCredentials(service_account, 'ee-esmaeilkiani1387-1b2c5e812a1d.json')
15
+ ee.Initialize(credentials)
16
+
17
+ # خواندن فایل CSV مزارع
18
+ farms_data = pd.read_csv('Farm_Details_Export.csv')
19
+
20
+ # تعریف ناحیه مورد مطالعه با مختصات جدید
21
+ region = ee.Geometry.Polygon(
22
+ [[[48.681879, 31.417603], [48.721447, 31.413209], [48.724279, 31.420826], [48.726768, 31.427418],
23
+ [48.728228, 31.435694], [48.736382, 31.42837], [48.739557, 31.435657], [48.742261, 31.441772],
24
+ [48.752303, 31.452243], [48.75226, 31.459784], [48.759127, 31.473657], [48.766809, 31.472413],
25
+ [48.773203, 31.491188], [48.77758, 31.534579], [48.785563, 31.540797], [48.792601, 31.59696],
26
+ [48.694668, 31.60756], [48.691921, 31.603466], [48.697586, 31.534067], [48.69381, 31.507727],
27
+ [48.685226, 31.468496], [48.681879, 31.417603]]]
28
+ )
29
+
30
+ # تابع برای دانلود و استخراج شیپ‌فایل
31
+ def download_and_extract_shapefile(zip_url, extract_to='.'):
32
+ zip_path = os.path.join(extract_to, 'shapefile.zip')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
 
34
+ # دانلود فایل زیپ
35
+ with requests.get(zip_url, stream=True) as r:
36
+ r.raise_for_status()
37
+ with open(zip_path, 'wb') as f:
38
+ for chunk in r.iter_content(chunk_size=8192):
39
+ f.write(chunk)
40
 
41
+ # استخراج فایل زیپ
42
+ with zipfile.ZipFile(zip_path, 'r') as zip_ref:
43
+ zip_ref.extractall(extract_to)
44
+
45
+ # یافتن فایل .shp
46
+ for file in os.listdir(extract_to):
47
+ if file.endswith('.shp'):
48
+ return os.path.join(extract_to, file)
49
+
50
+ return None
51
+
52
+ # تابع برای خواندن و نمایش شیپ‌فایل
53
+ def load_and_display_shapefile(shapefile_path):
54
+ gdf = gpd.read_file(shapefile_path)
55
+ geojson = gdf.to_json()
56
 
57
+ map_ = geemap.Map(center=[31.5, 48.7], zoom=10)
58
+ map_.add_geojson(geojson, layer_name="Shapefile Layer")
59
+ map_.to_streamlit(height=600)
60
+
61
+ # آدرس شیپ‌فایل آپلود شده در هاگینگ فیس (لینک مستقیم فایل زیپ)
62
+ zip_url = 'https://huggingface.co/spaces/Esmaeilkiani/AppSugarcane/raw/main/Dehkhodaa.rar'
63
+
64
+ # دانلود و نمایش شیپ‌فایل
65
+ shapefile_path = download_and_extract_shapefile(zip_url)
66
+ if shapefile_path:
67
+ st.write("شیپ‌فایل با موفقیت بارگذاری شد!")
68
+ load_and_display_shapefile(shapefile_path)
69
+ else:
70
+ st.write("خطا در بارگذاری شیپ‌فایل.")
71
+
72
+ # انتخاب بازه زمانی با کلیدهای یکتا
73
+ start_date = st.date_input("تاریخ شروع", datetime.date(2023, 1, 1), key="start_date")
74
+ end_date = st.date_input("تاریخ پایان", datetime.date(2023, 12, 31), key="end_date")
75
+
76
+ # انتخاب شاخص
77
+ index_option = st.selectbox("شاخص مورد نظر را انتخاب کنید:", ["NDVI", "NDMI", "NDRE"])
78
+
79
+ # انتخاب مزرعه از فایل CSV
80
+ farm_name = st.sidebar.selectbox("نام مزرعه را انتخاب کنید:", farms_data['farm_name'].unique())
81
+
82
+ # پیدا کردن مختصات مزرعه انتخاب شده
83
+ selected_farm = farms_data[farms_data['farm_name'] == farm_name]
84
+ latitude = selected_farm['latitude'].values[0]
85
+ longitude = selected_farm['longitude'].values[0]
86
+ farm_age = selected_farm['age'].values[0]
87
+ farm_variety = selected_farm['variety'].values[0]
88
+
89
+ # دکمه برای نمایش نقشه
90
+ if st.button("نمایش نقشه"):
91
+ if index_option == "NDVI":
92
+ index_map, vis_params = get_ndvi_map(start_date.isoformat(), end_date.isoformat())
93
+ elif index_option == "NDMI":
94
+ index_map, vis_params = get_ndmi_map(start_date.isoformat(), end_date.isoformat())
95
+ else:
96
+ index_map, vis_params = get_ndre_map(start_date.isoformat(), end_date.isoformat())
97
+
98
+ # ایجاد نقشه با Geemap
99
+ map_ = geemap.Map(center=[latitude, longitude], zoom=14)
100
+ map_.addLayer(index_map.clip(region), vis_params, index_option)
101
+ map_.add_colorbar(vis_params, label=index_option)
102
+
103
+ # افزودن مزرعه به نقشه
104
+ map_.add_marker([latitude, longitude], popup=f"نام: {farm_name}<br>سن: {farm_age}<br>واریته: {farm_variety}")
105
+ map_.add_ee_layer(region, {'color': 'FF0000'}, 'منطقه مورد مطالعه')
106
+
107
+ # نمایش نقشه در Streamlit
108
+ map_.to_streamlit(height=600)
109
+
110
+ # محاسبه NDRE میانگین
111
+ ndre_image = get_ndre_map(start_date.isoformat(), end_date.isoformat())[0]
112
+ mean_ndre = ndre_image.reduceRegion(reducer=ee.Reducer.mean(), geometry=region, scale=30).get('NDRE').getInfo()
113
+
114
+ # نمودار تصمیم‌گیری برای برداشت
115
+ fig, ax = plt.subplots()
116
+ ax.bar(['NDRE', 'مناسب برای برداشت'], [mean_ndre, 0.5], color=['green', 'orange'])
117
+ ax.set_ylim(0, 1)
118
+ ax.set_title(f"شاخص NDRE برای مزرعه {farm_name}")
119
+ st.pyplot(fig)
120
+
121
+ # نمایش وضعیت برداشت
122
+ if mean_ndre > 0.5:
123
+ st.write(f"مزرعه {farm_name} به حد قابل قبول برای برداشت رسیده است (NDRE = {mean_ndre:.2f}).")
124
+ else:
125
+ st.write(f"مزرعه {farm_name} هنوز آماده برداشت نیست (NDRE = {mean_ndre:.2f}).")