Esmaeilkiani's picture
Update app.py
8289c13 verified
raw
history blame
17.7 kB
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 برقرار نشد. لطفا تنظیمات احراز هویت را بررسی کنید.")