File size: 17,709 Bytes
2edf7af
a84c078
 
2edf7af
ddd1a18
a84c078
 
e8219cc
a84c078
 
e8219cc
a84c078
 
 
e8219cc
a84c078
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e8219cc
a84c078
 
e8219cc
a84c078
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e8219cc
a84c078
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e8219cc
8289c13
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
import streamlit as st
import ee
import geemap.foliumap as geemap
import pandas as pd
import matplotlib.pyplot as plt
import datetime
import os

# Set page title and layout
st.set_page_config(page_title="سیستم پایش مزارع نیشکر", layout="wide")

# Header
st.title("سیستم پایش هوشمند مزارع نیشکر")
st.markdown("---")

# Initialize Earth Engine
@st.cache_resource
def initialize_ee():
    try:
        # Path to your service account key file
        service_account = 'dehkhodamap-e9f0da4ce9f6514021@ee-esmaeilkiani13877.iam.gserviceaccount.com'
        credentials_path = 'ee-esmaeilkiani13877-cfdea6eaf411.json'
        
        # Check if credentials file exists
        if os.path.exists(credentials_path):
            credentials = ee.ServiceAccountCredentials(service_account, credentials_path)
            ee.Initialize(credentials)
            return True
        else:
            st.error("فایل احراز هویت یافت نشد. لطفا مسیر فایل را بررسی کنید.")
            return False
    except Exception as e:
        st.error(f"خطا در اتصال به Google Earth Engine: {str(e)}")
        return False

# Initialize Earth Engine
ee_initialized = initialize_ee()

if ee_initialized:
    # Define coordinates for the area of interest
    LATITUDE = 31.534442
    LONGITUDE = 48.724416
    
    # Create a point geometry
    point = ee.Geometry.Point([LONGITUDE, LATITUDE])
    
    # Create a buffer around the point (5 km radius)
    aoi = point.buffer(5000)
    
    # Sidebar for controls
    with st.sidebar:
        st.header("تنظیمات")
        
        # Date selection
        st.subheader("انتخاب بازه زمانی")
        today = datetime.datetime.now()
        default_start_date = today - datetime.timedelta(days=365)
        start_date = st.date_input("تاریخ شروع", default_start_date)
        end_date = st.date_input("تاریخ پایان", today)
        
        # Convert dates to strings
        start_date_str = start_date.strftime("%Y-%m-%d")
        end_date_str = end_date.strftime("%Y-%m-%d")
        
        # Cloud cover filter
        cloud_cover = st.slider("حداکثر درصد ابر", 0, 100, 10)
        
        # Index selection
        index_options = {
            "NDVI (شاخص تفاضل نرمال شده پوشش گیاهی)": "NDVI",
            "EVI (شاخص پوشش گیاهی بهبود یافته)": "EVI",
            "SAVI (شاخص پوشش گیاهی تعدیل شده خاک)": "SAVI",
            "NDMI (شاخص رطوبت تفاضل نرمال شده)": "NDMI"
        }
        selected_index = st.selectbox("انتخاب شاخص", list(index_options.keys()))
        index_code = index_options[selected_index]
        
        # Analysis type
        analysis_type = st.selectbox(
            "نوع تحلیل",
            ["پایش سلامت و رشد", "مدیریت آبیاری", "مدیریت آفات", "مدیریت برداشت", "مدیریت زمین"]
        )
        
        st.markdown("---")
        st.info("برای بهترین نتیجه، تصاویر با درصد ابر کمتر از 10 درصد توصیه می‌شود.")

    # Main content
    col1, col2 = st.columns([2, 1])
    
    with col1:
        st.subheader("نقشه پایش مزارع نیشکر")
        
        # Get Sentinel-2 collection
        sentinel = ee.ImageCollection('COPERNICUS/S2_SR') \
            .filterDate(start_date_str, end_date_str) \
            .filterBounds(aoi) \
            .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', cloud_cover))
        
        # Sort by cloud cover and get the most recent image
        recent_image = sentinel.sort('CLOUDY_PIXEL_PERCENTAGE').first()
        
        # Check if we have an image
        if recent_image:
            # Function to calculate indices
            def calculate_index(image, index_name):
                if index_name == 'NDVI':
                    # NDVI = (NIR - Red) / (NIR + Red)
                    return image.normalizedDifference(['B8', 'B4']).rename('NDVI')
                elif index_name == 'EVI':
                    # EVI = 2.5 * ((NIR - Red) / (NIR + 6 * Red - 7.5 * Blue + 1))
                    return image.expression(
                        '2.5 * ((NIR - RED) / (NIR + 6 * RED - 7.5 * BLUE + 1))', {
                            'NIR': image.select('B8'),
                            'RED': image.select('B4'),
                            'BLUE': image.select('B2')
                        }).rename('EVI')
                elif index_name == 'SAVI':
                    # SAVI = ((NIR - Red) / (NIR + Red + L)) * (1 + L), where L = 0.5
                    return image.expression(
                        '((NIR - RED) / (NIR + RED + 0.5)) * 1.5', {
                            'NIR': image.select('B8'),
                            'RED': image.select('B4')
                        }).rename('SAVI')
                elif index_name == 'NDMI':
                    # NDMI = (NIR - SWIR1) / (NIR + SWIR1)
                    return image.normalizedDifference(['B8', 'B11']).rename('NDMI')
            
            # Calculate the selected index
            index_image = calculate_index(recent_image, index_code)
            
            # Create a map
            Map = geemap.Map()
            Map.centerObject(aoi, 13)
            
            # Add the index layer with appropriate visualization parameters
            if index_code == 'NDVI' or index_code == 'EVI' or index_code == 'SAVI':
                vis_params = {'min': 0, 'max': 1, 'palette': ['FFFFFF', 'CE7E45', 'DF923D', 'F1B555', 'FCD163', '99B718', '74A901', '66A000', '529400', '3E8601', '207401', '056201', '004C00', '023B01', '012E01', '011D01', '011301']}
            elif index_code == 'NDMI':
                vis_params = {'min': -1, 'max': 1, 'palette': ['red', 'orange', 'yellow', 'green', 'cyan', 'blue']}
            
            Map.addLayer(index_image, vis_params, f'{index_code} Index')
            
            # Add true color layer
            true_color_vis = {'bands': ['B4', 'B3', 'B2'], 'min': 0, 'max': 3000}
            Map.addLayer(recent_image, true_color_vis, 'True Color', False)
            
            # Add AOI
            Map.addLayer(aoi, {'color': 'red'}, 'Area of Interest')
            
            # Display the map
            Map.to_streamlit(height=600)
            
            # Display image metadata
            image_date = ee.Date(recent_image.get('system:time_start')).format('YYYY-MM-dd').getInfo()
            cloud_percentage = recent_image.get('CLOUDY_PIXEL_PERCENTAGE').getInfo()
            
            st.info(f"تاریخ تصویر: {image_date} | درصد ابر: {cloud_percentage:.2f}%")
        else:
            st.error("هیچ تصویری با شرایط مورد نظر یافت نشد. لطفا محدوده زمانی یا درصد ابر را تغییر دهید.")
    
    with col2:
        st.subheader("تحلیل و توصیه‌ها")
        
        if recent_image:
            # Calculate statistics for the index
            stats = index_image.reduceRegion(
                reducer=ee.Reducer.mean().combine(
                    reducer2=ee.Reducer.stdDev(),
                    sharedInputs=True
                ).combine(
                    reducer2=ee.Reducer.minMax(),
                    sharedInputs=True
                ),
                geometry=aoi,
                scale=10,
                maxPixels=1e9
            ).getInfo()
            
            # Display statistics
            if index_code in stats:
                mean_val = stats[f'{index_code}_mean']
                std_val = stats[f'{index_code}_stdDev']
                min_val = stats[f'{index_code}_min']
                max_val = stats[f'{index_code}_max']
                
                st.write(f"**میانگین {index_code}:** {mean_val:.4f}")
                st.write(f"**انحراف معیار:** {std_val:.4f}")
                st.write(f"**حداقل:** {min_val:.4f}")
                st.write(f"**حداکثر:** {max_val:.4f}")
                
                # Interpretation based on index and analysis type
                st.markdown("### تفسیر و توصیه‌ها")
                
                if index_code == 'NDVI':
                    if mean_val > 0.7:
                        health_status = "عالی"
                        color = "green"
                    elif mean_val > 0.5:
                        health_status = "خوب"
                        color = "lightgreen"
                    elif mean_val > 0.3:
                        health_status = "متوسط"
                        color = "orange"
                    else:
                        health_status = "ضعیف"
                        color = "red"
                    
                    st.markdown(f"**وضعیت سلامت گیاه:** <span style='color:{color}'>{health_status}</span>", unsafe_allow_html=True)
                    
                    if analysis_type == "پایش سلامت و رشد":
                        if mean_val > 0.7:
                            st.success("گیاهان در وضعیت سلامت عالی قرار دارند. رشد مطلوب است.")
                        elif mean_val > 0.5:
                            st.info("گیاهان در وضعیت سلامت خوبی قرار دارند. نظارت منظم توصیه می‌شود.")
                        elif mean_val > 0.3:
                            st.warning("سلامت گیاهان متوسط است. بررسی عوامل محدودکننده رشد توصیه می‌شود.")
                        else:
                            st.error("سلامت گیاهان ضعیف است. بررسی فوری عوامل تنش‌زا ضروری است.")
                    
                    elif analysis_type == "مدیریت آبیاری":
                        if mean_val < 0.4:
                            st.error("احتمال تنش آبی وجود دارد. افزایش آبیاری توصیه می‌شود.")
                        elif mean_val > 0.7:
                            st.success("وضعیت آبیاری مطلوب است.")
                        else:
                            st.info("وضعیت آبیاری قابل قبول است. نظارت منظم توصیه می‌شود.")
                
                elif index_code == 'NDMI':
                    if mean_val > 0.4:
                        moisture_status = "بالا"
                        color = "blue"
                    elif mean_val > 0.2:
                        moisture_status = "مناسب"
                        color = "green"
                    elif mean_val > 0:
                        moisture_status = "متوسط"
                        color = "orange"
                    else:
                        moisture_status = "پایین"
                        color = "red"
                    
                    st.markdown(f"**وضعیت رطوبت:** <span style='color:{color}'>{moisture_status}</span>", unsafe_allow_html=True)
                    
                    if analysis_type == "مدیریت آبیاری":
                        if mean_val < 0:
                            st.error("رطوبت خاک پایین است. افزایش آبیاری توصیه می‌شود.")
                        elif mean_val > 0.4:
                            st.warning("رطوبت خاک بالاست. کاهش آبیاری توصیه می‌شود.")
                        else:
                            st.success("رطوبت خاک در محدوده مناسبی قرار دارد.")
                
                # Add more specific recommendations based on analysis type
                st.markdown("### اقدامات پیشنهادی")
                if analysis_type == "پایش سلامت و رشد":
                    st.write("1. بررسی منظم وضعیت سلامت گیاه")
                    st.write("2. نمونه‌برداری از خاک برای بررسی وضعیت مواد مغذی")
                    st.write("3. بررسی علائم بیماری‌ها و آفات در مناطق با NDVI پایین")
                
                elif analysis_type == "مدیریت آبیاری":
                    st.write("1. تنظیم برنامه آبیاری بر اساس شاخص‌های رطوبتی")
                    st.write("2. نصب سنسورهای رطوبت خاک در مناطق بحرانی")
                    st.write("3. بررسی سیستم زهکشی در مناطق با رطوبت بالا")
                
                elif analysis_type == "مدیریت آفات":
                    st.write("1. بازرسی دقیق مناطق با NDVI پایین برای شناسایی آفات")
                    st.write("2. برنامه‌ریزی سم‌پاشی هدفمند در مناطق آلوده")
                    st.write("3. پایش مستمر مناطق مستعد آلودگی")
                
                elif analysis_type == "مدیریت برداشت":
                    st.write("1. اولویت‌بندی مناطق برای برداشت بر اساس شاخص بلوغ")
                    st.write("2. برنامه‌ریزی مسیرهای بهینه برداشت")
                    st.write("3. تخمین عملکرد محصول بر اساس شاخص‌های گیاهی")
                
                elif analysis_type == "مدیریت زمین":
                    st.write("1. شناسایی مناطق با پتانسیل بهبود")
                    st.write("2. برنامه‌ریزی کوددهی بر اساس نقشه‌های شاخص گیاهی")
                    st.write("3. ارزیابی تأثیر روش‌های مدیریتی مختلف")
            else:
                st.error(f"خطا در محاسبه آمار {index_code}")
        
        # Historical trend analysis section
        if recent_image:
            st.markdown("---")
            st.subheader("تحلیل روند تاریخی")
            
            # Get historical data for the selected index
            def get_historical_data():
                # Create a time series of the selected index
                def calculate_index_for_collection(image):
                    index = calculate_index(image, index_code)
                    mean = index.reduceRegion(
                        reducer=ee.Reducer.mean(),
                        geometry=aoi,
                        scale=30,
                        maxPixels=1e9
                    ).get(index_code)
                    
                    return image.set('date', image.date().format('YYYY-MM-dd')).set('index_mean', mean)
                
                # Get a 12-month collection
                collection = sentinel.map(calculate_index_for_collection)
                
                # Get the dates and index values
                dates = collection.aggregate_array('date').getInfo()
                values = collection.aggregate_array('index_mean').getInfo()
                
                # Create a dataframe
                data = {'date': dates, 'value': values}
                df = pd.DataFrame(data)
                df = df.dropna()  # Remove any NaN values
                
                # Convert to datetime
                df['date'] = pd.to_datetime(df['date'])
                
                # Sort by date
                df = df.sort_values('date')
                
                return df
            
            # Get the historical data
            try:
                hist_data = get_historical_data()
                
                if not hist_data.empty:
                    # Plot the data
                    fig, ax = plt.subplots(figsize=(10, 4))
                    ax.plot(hist_data['date'], hist_data['value'], marker='o', linestyle='-')
                    ax.set_title(f'روند تغییرات {index_code} در طول زمان')
                    ax.set_xlabel('تاریخ')
                    ax.set_ylabel(index_code)
                    ax.grid(True)
                    
                    # Display the plot
                    st.pyplot(fig)
                    
                    # Trend analysis
                    if len(hist_data) > 1:
                        first_value = hist_data['value'].iloc[0]
                        last_value = hist_data['value'].iloc[-1]
                        change = ((last_value - first_value) / first_value) * 100 if first_value != 0 else 0
                        
                        if change > 10:
                            st.success(f"روند صعودی: افزایش {change:.2f}% در شاخص {index_code} از ابتدای دوره")
                        elif change < -10:
                            st.error(f"روند نزولی: کاهش {abs(change):.2f}% در شاخص {index_code} از ابتدای دوره")
                        else:
                            st.info(f"روند ثابت: تغییر {change:.2f}% در شاخص {index_code} از ابتدای دوره")
                else:
                    st.warning("داده‌های کافی برای تحلیل روند تاریخی وجود ندارد.")
            except Exception as e:
                st.error(f"خطا در تحلیل روند تاریخی: {str(e)}")
else:
    st.error("اتصال به Google Earth Engine برقرار نشد. لطفا تنظیمات احراز هویت را بررسی کنید.")