Esmaeilkiani commited on
Commit
2178497
·
verified ·
1 Parent(s): 078c656

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +84 -344
app.py CHANGED
@@ -1,353 +1,93 @@
1
  import streamlit as st
2
  import ee
3
  import geemap.foliumap as geemap
4
- import pandas as pd
5
- import matplotlib.pyplot as plt
6
- import datetime
7
- import os
8
 
9
- # Set page title and layout
10
- st.set_page_config(page_title="سیستم پایش مزارع نیشکر", layout="wide")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
- # Header
13
- st.title("سیستم پایش هوشمند مزارع نیشکر")
14
- st.markdown("---")
15
 
16
- # Initialize Earth Engine
17
- @st.cache_resource
18
- def initialize_ee():
19
- try:
20
- # Path to your service account key file
21
- service_account = 'esmaeil-kiani1387-gmail-com@ee-esmaeilkiani13877.iam.gserviceaccount.com'
22
- credentials_path = 'ee-esmaeilkiani13877-9a054809a4bb.json'
23
-
24
- # Check if credentials file exists
25
- if os.path.exists(credentials_path):
26
- credentials = ee.ServiceAccountCredentials(service_account, credentials_path)
27
- ee.Initialize(credentials)
28
- return True
29
- else:
30
- st.error("فایل احراز هویت یافت نشد. لطفا مسیر فایل را بررسی کنید.")
31
- return False
32
- except Exception as e:
33
- st.error(f"خطا در اتصال به Google Earth Engine: {str(e)}")
34
- return False
35
 
36
- # Initialize Earth Engine
37
- ee_initialized = initialize_ee()
 
 
 
 
38
 
39
- if ee_initialized:
40
- # Define coordinates for the area of interest
41
- LATITUDE = 31.534442
42
- LONGITUDE = 48.724416
43
-
44
- # Create a point geometry
45
- point = ee.Geometry.Point([LONGITUDE, LATITUDE])
46
-
47
- # Create a buffer around the point (5 km radius)
48
- aoi = point.buffer(5000)
49
-
50
- # Sidebar for controls
51
- with st.sidebar:
52
- st.header("تنظیمات")
53
-
54
- # Date selection
55
- st.subheader("انتخاب بازه زمانی")
56
- today = datetime.datetime.now()
57
- default_start_date = today - datetime.timedelta(days=365)
58
- start_date = st.date_input("تاریخ شروع", default_start_date)
59
- end_date = st.date_input("تاریخ پایان", today)
60
-
61
- # Convert dates to strings
62
- start_date_str = start_date.strftime("%Y-%m-%d")
63
- end_date_str = end_date.strftime("%Y-%m-%d")
64
-
65
- # Cloud cover filter
66
- cloud_cover = st.slider("حداکثر درصد ابر", 0, 100, 10)
67
-
68
- # Index selection
69
- index_options = {
70
- "NDVI (شاخص تفاضل نرمال شده پوشش گیاهی)": "NDVI",
71
- "EVI (شاخص پوشش گیاهی بهبود یافته)": "EVI",
72
- "SAVI (شاخص پوشش گیاهی تعدیل شده خاک)": "SAVI",
73
- "NDMI (شاخص رطوبت تفاضل نرمال شده)": "NDMI"
74
- }
75
- selected_index = st.selectbox("انتخاب شاخص", list(index_options.keys()))
76
- index_code = index_options[selected_index]
77
-
78
- # Analysis type
79
- analysis_type = st.selectbox(
80
- "نوع تحلیل",
81
- ["پایش سلامت و رشد", "مدیریت آبیاری", "مدیریت آفات", "مدیریت برداشت", "مدیریت زمین"]
82
- )
83
-
84
- st.markdown("---")
85
- st.info("برای بهترین نتیجه، تصاویر با درصد ابر کمتر از 10 درصد توصیه می‌شود.")
86
 
87
- # Main content
88
- col1, col2 = st.columns([2, 1])
89
-
90
- with col1:
91
- st.subheader("نقشه پایش مزارع نیشکر")
92
-
93
- # Get Sentinel-2 collection
94
- sentinel = ee.ImageCollection('COPERNICUS/S2_SR') \
95
- .filterDate(start_date_str, end_date_str) \
96
- .filterBounds(aoi) \
97
- .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', cloud_cover))
98
-
99
- # Sort by cloud cover and get the most recent image
100
- recent_image = sentinel.sort('CLOUDY_PIXEL_PERCENTAGE').first()
101
-
102
- # Check if we have an image
103
- if recent_image:
104
- # Function to calculate indices
105
- def calculate_index(image, index_name):
106
- if index_name == 'NDVI':
107
- # NDVI = (NIR - Red) / (NIR + Red)
108
- return image.normalizedDifference(['B8', 'B4']).rename('NDVI')
109
- elif index_name == 'EVI':
110
- # EVI = 2.5 * ((NIR - Red) / (NIR + 6 * Red - 7.5 * Blue + 1))
111
- return image.expression(
112
- '2.5 * ((NIR - RED) / (NIR + 6 * RED - 7.5 * BLUE + 1))', {
113
- 'NIR': image.select('B8'),
114
- 'RED': image.select('B4'),
115
- 'BLUE': image.select('B2')
116
- }).rename('EVI')
117
- elif index_name == 'SAVI':
118
- # SAVI = ((NIR - Red) / (NIR + Red + L)) * (1 + L), where L = 0.5
119
- return image.expression(
120
- '((NIR - RED) / (NIR + RED + 0.5)) * 1.5', {
121
- 'NIR': image.select('B8'),
122
- 'RED': image.select('B4')
123
- }).rename('SAVI')
124
- elif index_name == 'NDMI':
125
- # NDMI = (NIR - SWIR1) / (NIR + SWIR1)
126
- return image.normalizedDifference(['B8', 'B11']).rename('NDMI')
127
-
128
- # Calculate the selected index
129
- index_image = calculate_index(recent_image, index_code)
130
-
131
- # Create a map
132
- Map = geemap.Map()
133
- Map.centerObject(aoi, 13)
134
-
135
- # Add the index layer with appropriate visualization parameters
136
- if index_code == 'NDVI' or index_code == 'EVI' or index_code == 'SAVI':
137
- vis_params = {'min': 0, 'max': 1, 'palette': ['FFFFFF', 'CE7E45', 'DF923D', 'F1B555', 'FCD163', '99B718', '74A901', '66A000', '529400', '3E8601', '207401', '056201', '004C00', '023B01', '012E01', '011D01', '011301']}
138
- elif index_code == 'NDMI':
139
- vis_params = {'min': -1, 'max': 1, 'palette': ['red', 'orange', 'yellow', 'green', 'cyan', 'blue']}
140
-
141
- Map.addLayer(index_image, vis_params, f'{index_code} Index')
142
-
143
- # Add true color layer
144
- true_color_vis = {'bands': ['B4', 'B3', 'B2'], 'min': 0, 'max': 3000}
145
- Map.addLayer(recent_image, true_color_vis, 'True Color', False)
146
-
147
- # Add AOI
148
- Map.addLayer(aoi, {'color': 'red'}, 'Area of Interest')
149
-
150
- # Display the map
151
- Map.to_streamlit(height=600)
152
-
153
- # Display image metadata
154
- image_date = ee.Date(recent_image.get('system:time_start')).format('YYYY-MM-dd').getInfo()
155
- cloud_percentage = recent_image.get('CLOUDY_PIXEL_PERCENTAGE').getInfo()
156
-
157
- st.info(f"تاریخ تصویر: {image_date} | درصد ابر: {cloud_percentage:.2f}%")
158
- else:
159
- st.error("هیچ تصویری با شرایط مورد نظر یافت نشد. لطفا محدوده زمانی یا درصد ابر را تغییر دهید.")
160
-
161
- with col2:
162
- st.subheader("تحلیل و توصیه‌ها")
163
-
164
- if recent_image:
165
- # Calculate statistics for the index
166
- stats = index_image.reduceRegion(
167
- reducer=ee.Reducer.mean().combine(
168
- reducer2=ee.Reducer.stdDev(),
169
- sharedInputs=True
170
- ).combine(
171
- reducer2=ee.Reducer.minMax(),
172
- sharedInputs=True
173
- ),
174
- geometry=aoi,
175
- scale=10,
176
- maxPixels=1e9
177
- ).getInfo()
178
-
179
- # Display statistics
180
- if index_code in stats:
181
- mean_val = stats[f'{index_code}_mean']
182
- std_val = stats[f'{index_code}_stdDev']
183
- min_val = stats[f'{index_code}_min']
184
- max_val = stats[f'{index_code}_max']
185
-
186
- st.write(f"**میانگین {index_code}:** {mean_val:.4f}")
187
- st.write(f"**انحراف معیار:** {std_val:.4f}")
188
- st.write(f"**حداقل:** {min_val:.4f}")
189
- st.write(f"**حداکثر:** {max_val:.4f}")
190
-
191
- # Interpretation based on index and analysis type
192
- st.markdown("### تفسیر و توصیه‌ها")
193
-
194
- if index_code == 'NDVI':
195
- if mean_val > 0.7:
196
- health_status = "عالی"
197
- color = "green"
198
- elif mean_val > 0.5:
199
- health_status = "خوب"
200
- color = "lightgreen"
201
- elif mean_val > 0.3:
202
- health_status = "متوسط"
203
- color = "orange"
204
- else:
205
- health_status = "ضعیف"
206
- color = "red"
207
-
208
- st.markdown(f"**وضعیت سلامت گیاه:** <span style='color:{color}'>{health_status}</span>", unsafe_allow_html=True)
209
-
210
- if analysis_type == "پایش سلامت و رشد":
211
- if mean_val > 0.7:
212
- st.success("گیاهان در وضعیت سلامت عالی قرار دارند. رشد مطلوب است.")
213
- elif mean_val > 0.5:
214
- st.info("گیاهان در وضعیت سلامت خوبی قرار دارند. نظارت منظم توصیه می‌شود.")
215
- elif mean_val > 0.3:
216
- st.warning("سلامت گیاهان متوسط است. بررسی عوامل محدودکننده رشد توصیه می‌شود.")
217
- else:
218
- st.error("سلامت گیاهان ضعیف است. بررسی فوری عوامل تنش‌زا ضروری است.")
219
-
220
- elif analysis_type == "مدیریت آبیاری":
221
- if mean_val < 0.4:
222
- st.error("احتمال تنش آبی وجود دارد. افزایش آبیاری توصیه می‌شود.")
223
- elif mean_val > 0.7:
224
- st.success("وضعیت آبیاری مطلوب است.")
225
- else:
226
- st.info("وضعیت آبیاری قابل قبول است. نظارت منظم توصیه می‌شود.")
227
-
228
- elif index_code == 'NDMI':
229
- if mean_val > 0.4:
230
- moisture_status = "بالا"
231
- color = "blue"
232
- elif mean_val > 0.2:
233
- moisture_status = "مناسب"
234
- color = "green"
235
- elif mean_val > 0:
236
- moisture_status = "متوسط"
237
- color = "orange"
238
- else:
239
- moisture_status = "پایین"
240
- color = "red"
241
-
242
- st.markdown(f"**وضعیت رطوبت:** <span style='color:{color}'>{moisture_status}</span>", unsafe_allow_html=True)
243
-
244
- if analysis_type == "مدیریت آبیاری":
245
- if mean_val < 0:
246
- st.error("رطوبت خاک پایین است. افزایش آبیاری توصیه می‌شود.")
247
- elif mean_val > 0.4:
248
- st.warning("رطوبت خاک بالاست. کاهش آبیاری توصیه می‌شود.")
249
- else:
250
- st.success("رطوبت خاک در محدوده مناسبی قرار دارد.")
251
-
252
- # Add more specific recommendations based on analysis type
253
- st.markdown("### اقدامات پیشنهادی")
254
- if analysis_type == "پایش سلامت و رشد":
255
- st.write("1. بررسی منظم وضعیت سلامت گیاه")
256
- st.write("2. نمونه‌برداری از خاک برای بررسی وضعیت مواد مغذی")
257
- st.write("3. بررسی علائم بیماری‌ها و آفات در مناطق با NDVI پایین")
258
-
259
- elif analysis_type == "مدیریت آبیاری":
260
- st.write("1. تنظیم برنامه آبیاری بر اساس شاخص‌های رطوبتی")
261
- st.write("2. نصب سنسورهای رطوبت خاک در مناطق بحرانی")
262
- st.write("3. بررسی سیستم زهکشی در مناطق با رطوبت بالا")
263
-
264
- elif analysis_type == "مدیریت آفات":
265
- st.write("1. بازرسی دقیق مناطق با NDVI پایین برای شناسایی آفات")
266
- st.write("2. برنامه‌ریزی سم‌پاشی هدفمند در مناطق آلوده")
267
- st.write("3. پایش مستمر مناطق مستعد آلودگی")
268
-
269
- elif analysis_type == "مدیریت برداشت":
270
- st.write("1. اولویت‌بندی مناطق برای برداشت بر اساس شاخص بلوغ")
271
- st.write("2. برنامه‌ریزی مسیرهای بهینه برداشت")
272
- st.write("3. تخمین عملکرد محصول بر اساس شاخص‌های گیاهی")
273
-
274
- elif analysis_type == "مدیریت زمین":
275
- st.write("1. شناسایی مناطق با پتانسیل بهبود")
276
- st.write("2. برنامه‌ریزی کوددهی بر اساس نقشه‌های شاخص گیاهی")
277
- st.write("3. ارزیابی تأثیر روش‌های مدیریتی مختلف")
278
- else:
279
- st.error(f"خطا در محاسبه آمار {index_code}")
280
-
281
- # Historical trend analysis section
282
- if recent_image:
283
- st.markdown("---")
284
- st.subheader("تحلیل روند تاریخی")
285
-
286
- # Get historical data for the selected index
287
- def get_historical_data():
288
- # Create a time series of the selected index
289
- def calculate_index_for_collection(image):
290
- index = calculate_index(image, index_code)
291
- mean = index.reduceRegion(
292
- reducer=ee.Reducer.mean(),
293
- geometry=aoi,
294
- scale=30,
295
- maxPixels=1e9
296
- ).get(index_code)
297
-
298
- return image.set('date', image.date().format('YYYY-MM-dd')).set('index_mean', mean)
299
-
300
- # Get a 12-month collection
301
- collection = sentinel.map(calculate_index_for_collection)
302
-
303
- # Get the dates and index values
304
- dates = collection.aggregate_array('date').getInfo()
305
- values = collection.aggregate_array('index_mean').getInfo()
306
-
307
- # Create a dataframe
308
- data = {'date': dates, 'value': values}
309
- df = pd.DataFrame(data)
310
- df = df.dropna() # Remove any NaN values
311
-
312
- # Convert to datetime
313
- df['date'] = pd.to_datetime(df['date'])
314
-
315
- # Sort by date
316
- df = df.sort_values('date')
317
-
318
- return df
319
-
320
- # Get the historical data
321
- try:
322
- hist_data = get_historical_data()
323
-
324
- if not hist_data.empty:
325
- # Plot the data
326
- fig, ax = plt.subplots(figsize=(10, 4))
327
- ax.plot(hist_data['date'], hist_data['value'], marker='o', linestyle='-')
328
- ax.set_title(f'روند تغییرات {index_code} در طول زمان')
329
- ax.set_xlabel('تاریخ')
330
- ax.set_ylabel(index_code)
331
- ax.grid(True)
332
-
333
- # Display the plot
334
- st.pyplot(fig)
335
-
336
- # Trend analysis
337
- if len(hist_data) > 1:
338
- first_value = hist_data['value'].iloc[0]
339
- last_value = hist_data['value'].iloc[-1]
340
- change = ((last_value - first_value) / first_value) * 100 if first_value != 0 else 0
341
-
342
- if change > 10:
343
- st.success(f"روند صعودی: افزایش {change:.2f}% در شاخص {index_code} از ابتدای دوره")
344
- elif change < -10:
345
- st.error(f"روند نزولی: کاهش {abs(change):.2f}% در شاخص {index_code} از ابتدای دوره")
346
- else:
347
- st.info(f"روند ثابت: تغییر {change:.2f}% در شاخص {index_code} از ابتدای دوره")
348
- else:
349
- st.warning("داده‌های کافی برای تحلیل روند تار��خی وجود ندارد.")
350
- except Exception as e:
351
- st.error(f"خطا در تحلیل روند تاریخی: {str(e)}")
352
- else:
353
- st.error("اتصال به Google Earth Engine برقرار نشد. لطفا تنظیمات احراز هویت را بررسی کنید.")
 
1
  import streamlit as st
2
  import ee
3
  import geemap.foliumap as geemap
4
+ import folium
5
+ from datetime import datetime, timedelta
 
 
6
 
7
+ # تابع برای احراز هویت با استفاده از سرویس اکانت
8
+ def authenticate_gee():
9
+ credentials = ee.ServiceAccountCredentials(
10
+ email='dehkhodamap-e9f0da4ce9f6514021@ee-esmaeilkiani13877.iam.gserviceaccount.com',
11
+ key_data="""-----BEGIN PRIVATE KEY-----
12
+ MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCjeOvgKi+gWK6k
13
+ 2/0RXOA3LAo51DVxA1ja9v0qFOn4FNOStxkwlKvcK8yDQNb53FPORHFIUHvev3y7
14
+ iHr/UEUqnn5Rzjbf0k3qWB/fS377/UP4VznMsFpKiHNxCBtaNS8KLk6Rat6Y7Xfm
15
+ JfpSU7ZjYZmVc81M/7iFofGUSJoHYpxhyt3rjp53huxJNNW5e12TFnLkyg1Ja/9X
16
+ GMTt+vjVcO4XhQCIlaGVdSKS2sHlHgzpzE6KtuUKjDMEBqPkWF4xc16YavYltwPd
17
+ qULCu2/t6dczhYL4NEFj8wL+KJqOojfsyoWmzqPFx1Bbxk4BVPk/lslq9+m9p5kq
18
+ SCG0/9W9AgMBAAECggEAEGchw+x3uu8rFv+79PIMzXxtyj+w3RYo5E/EN2TB1VLB
19
+ qAcXT/ibBgyfCMyIxamF/zx+4XKx+zfbnDWlodi8F/qvUiYO+4ZuqwUMras1orNX
20
+ DqQx+If5h2EJtF3L4NFVVwAuggjnLREm5sEIzRn5Qx+X+ZcVEpTWPxJw2yAt1G+3
21
+ k311KqD+zR7jQfchXU4xQQ1ZoHkdAJ/DPGun6x+HUOq7Gus73A6IzLp12ZoiHN3n
22
+ kY+lG8cMs039QAe/OhZFEo5I9cNSaI688HmsLRivZ26WoPEnwcN0MHQGtXqGmMUI
23
+ CcpgJqllqdWMuBlYcpSadn7rZzPujSlzIxkvieLeAQKBgQDNTYUWZdGbA2sHcBpJ
24
+ rqKwDYF/AwZtjx+hXHVBRbR6DJ1bO2P9n51ioTMP/H9K61OBAMZ7w71xJ2I+9Snv
25
+ cYumPWoiUwiOhTh3O7nYz6mR7sK0HuUCZfYdaxJVnLgNCgj+w9AxYnkzOyL9/QvJ
26
+ knrlMKf4H59NbapBqy5spilq1QKBgQDL1wkGHhoTuLb5Xp3X3CX4S7WMke4T01bO
27
+ PpMmlewVgH5lK5wTcZjB8QRO2QFQtUZTP/Ghv6ZH4h/3P9/ZIF3hV5CSsUkr/eFf
28
+ MY+fQL1K/puwfZbSDcH1GtDToOyoLFIvPXBJo0Llg/oF2TK1zGW3cPszeDf/Tm6x
29
+ UwUMw2BjSQKBgEJzAMyLEBi4NoAlzJxkpcuN04gkloQHexljL6B8yzlls9i/lFGW
30
+ w/4UZs6ZzymUmWZ7tcKBTGO/d5EhEP2rJqQb5KpPbcmTXP9amYCPVjchrGtYRI9O
31
+ KSbEbR7ApuGxic/L2Sri0I/AaEcFDDel7ZkY8oTg11LcV+sBWPlZnrYxAoGBALXj
32
+ /DlpQvu2KA/9TfwAhiE57Zax4S/vtdX0IHqd7TyCnEbK00rGYvksiBuTqIjMOSSw
33
+ On2K9mXOcZe/d4/YQe2CpY9Ag3qt4R2ArBf/POpep66lYp+thxWgCBfP0V1/rxZY
34
+ TIppFJiZW9E8LvPqoBlAx+b1r4IyCrRQ0IDDFo+BAoGBAMCff4XKXHlV2SDOL5uh
35
+ V/f9ApEdF4leuo+hoMryKuSQ9Y/H0A/Lzw6KP5FLvVtqc0Kw2D1oLy8O72a1xwfY
36
+ 8dpZMNzKAWWS7viN0oC+Ebj2Foc2Mn/J6jdhtP/YRLTqvoTWCa2rVcn4R1BurMIf
37
+ La4DJE9BagGdVNTDtynBhKhZ
38
+ -----END PRIVATE KEY-----"""
39
+ )
40
+ ee.Initialize(credentials)
41
 
42
+ # احراز هویت هنگام اجرای برنامه
43
+ authenticate_gee()
 
44
 
45
+ # تعریف منطقه مورد نظر (مختصات شرکت نیشکر دهخدا)
46
+ roi = ee.Geometry.Rectangle([48.5, 31.3, 48.7, 31.5])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
 
48
+ # تابع محاسبه رواناب با استفاده از روش SCS-CN
49
+ def calculate_runoff(start_date, end_date):
50
+ # بارش از CHIRPS
51
+ chirps = ee.ImageCollection('UCSB-CHG/CHIRPS/DAILY') \
52
+ .filterDate(start_date, end_date) \
53
+ .filterBounds(roi)
54
 
55
+ # میانگین بارش در منطقه
56
+ precipitation = chirps.mean().clip(roi)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
 
58
+ # فرض یک مقدار ثابت برای CN (شماره منحنی) - در عمل باید دقیق‌تر محاسبه شود
59
+ CN = 75 # برای زمین کشاورزی فرضی
60
+ S = (1000 / CN) - 10 # پتانسیل نگهداری
61
+ P = precipitation # بارش
62
+
63
+ # فرمول SCS-CN برای محاسبه رواناب (Q)
64
+ Q = P.expression(
65
+ '((P - 0.2 * S) ** 2) / (P + 0.8 * S)', {
66
+ 'P': P,
67
+ 'S': S
68
+ }).where(P.lt(0.2 * S), 0) # اگر بارش کمتر از 0.2S باشد، رواناب صفر است
69
+
70
+ return Q
71
+
72
+ # رابط کاربری Streamlit
73
+ st.title("محاسبه و نمایش رواناب منطقه نیشکر دهخدا")
74
+ st.write("این برنامه رواناب را با استفاده از داده‌های Google Earth Engine محاسبه و نمایش می‌دهد.")
75
+
76
+ # انتخاب بازه زمانی
77
+ start_date = st.date_input("تاریخ شروع", value=datetime(2023, 1, 1))
78
+ end_date = st.date_input("تاریخ پایان", value=datetime(2023, 12, 31))
79
+
80
+ if st.button("محاسبه و نمایش نقشه"):
81
+ # محاسبه رواناب
82
+ runoff = calculate_runoff(start_date.strftime('%Y-%m-%d'), end_date.strftime('%Y-%m-%d'))
83
+
84
+ # ایجاد نقشه با folium و geemap
85
+ m = geemap.Map(center=[31.4, 48.6], zoom=10)
86
+ m.addLayer(runoff, {'min': 0, 'max': 50, 'palette': ['blue', 'green', 'yellow', 'red']}, 'رواناب (mm)')
87
+ m.addLayer(roi, {}, 'منطقه نیشکر دهخدا')
88
+
89
+ # نمایش نقشه در Streamlit
90
+ st.write("نقشه رواناب:")
91
+ m.to_streamlit(height=600)
92
+
93
+ st.write("توجه: مقدار شماره منحنی (CN) به صورت فرضی 75 در نظر گرفته شده است. برای دقت بیشتر، باید داده‌های محلی خاک و کاربری زمین استفاده شود.")