Esmaeilkianii commited on
Commit
4639323
·
verified ·
1 Parent(s): 655ea2a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +168 -29
app.py CHANGED
@@ -3,14 +3,23 @@ import ee
3
  import folium
4
  import pandas as pd
5
  import matplotlib.pyplot as plt
 
6
  import numpy as np
7
  from streamlit_folium import folium_static
8
  from datetime import date, timedelta
9
  import json
10
  import geemap.foliumap as geemap
 
 
 
 
 
 
 
 
11
 
12
  # تنظیمات اولیه
13
- st.set_page_config(page_title="پایش مزارع نیشکر", layout="wide", initial_sidebar_state="expanded")
14
 
15
  # تنظیمات ظاهری برای متون فارسی
16
  st.markdown("""
@@ -49,6 +58,7 @@ credentials = ee.ServiceAccountCredentials(service_account, key_data=key_json_st
49
  ee.Initialize(credentials)
50
 
51
  # تعریف توابع کمکی
 
52
  def load_farm_data():
53
  """بارگذاری اطلاعات مزارع"""
54
  try:
@@ -57,6 +67,7 @@ def load_farm_data():
57
  st.error(f"خطا در بارگذاری اطلاعات مزارع: {str(e)}")
58
  return None
59
 
 
60
  def get_safe_index_value(image, index_type, band_selection, farm_geometry):
61
  """محاسبه ایمن شاخص‌های گیاهی"""
62
  if image is None:
@@ -85,19 +96,122 @@ def calculate_lai(ndvi):
85
  """محاسبه شاخص سطح برگ"""
86
  return -1.325 + 6.331 * ndvi - 2.239 * (ndvi ** 2)
87
 
88
- def add_ee_layer(self, ee_image_object, vis_params, name):
89
- """تابع کمکی برای اضافه کردن لایه Earth Engine به نقشه"""
90
- map_id_dict = ee.Image(ee_image_object).getMapId(vis_params)
91
- folium.raster_layers.TileLayer(
92
- tiles=map_id_dict['tile_fetcher'].url_format,
93
- attr='Map Data &copy; <a href="https://earthengine.google.com/">Google Earth Engine</a>',
94
- name=name,
95
- overlay=True,
96
- control=True
97
- ).add_to(self)
98
 
99
- # اضافه کردن متد به کلاس folium.Map
100
- folium.Map.add_ee_layer = add_ee_layer
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
 
102
  # تابع اصلی برنامه
103
  def main():
@@ -150,8 +264,8 @@ def main():
150
  try:
151
  # محاسبه تاریخ‌های مورد نیاز
152
  end_date = date.today()
153
- start_date = end_date - timedelta(days=6)
154
- date_list = [start_date + timedelta(days=x) for x in range(7)]
155
 
156
  # دریافت تصاویر و محاسبه شاخص‌ها
157
  with st.spinner('در حال پردازش اطلاعات...'):
@@ -180,29 +294,31 @@ def main():
180
  for index in band_selection.keys():
181
  index_values[index].append(0)
182
 
 
 
 
 
 
 
 
183
  # نمایش نمودارها و نقشه NDVI
184
  col1, col2 = st.columns(2)
185
 
186
  with col1:
187
  st.subheader("روند تغییرات شاخص‌ها")
188
- fig, ax = plt.subplots(figsize=(10, 6))
189
- for index in band_selection.keys():
190
- ax.plot(date_list, index_values[index], marker='o', label=index)
191
- ax.set_xlabel('تاریخ')
192
- ax.set_ylabel('مقدار شاخص')
193
- plt.xticks(rotation=45)
194
- plt.legend()
195
- st.pyplot(fig)
196
 
197
  with col2:
198
  st.subheader("شاخص سطح برگ (LAI)")
199
  lai_values = [calculate_lai(ndvi) for ndvi in index_values['NDVI']]
200
- fig, ax = plt.subplots(figsize=(10, 6))
201
- ax.plot(date_list, lai_values, marker='o', color='green')
202
- ax.set_xlabel('تاریخ')
203
- ax.set_ylabel('LAI')
204
- plt.xticks(rotation=45)
205
- st.pyplot(fig)
206
 
207
  # تحلیل وضعیت
208
  st.subheader("تحلیل وضعیت مزرعه")
@@ -250,6 +366,29 @@ def main():
250
  # نمایش نقشه
251
  Map.to_streamlit(height=400)
252
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
253
  except Exception as e:
254
  st.error(f"خطا در پردازش اطلاعات: {str(e)}")
255
 
 
3
  import folium
4
  import pandas as pd
5
  import matplotlib.pyplot as plt
6
+ import seaborn as sns
7
  import numpy as np
8
  from streamlit_folium import folium_static
9
  from datetime import date, timedelta
10
  import json
11
  import geemap.foliumap as geemap
12
+ from fpdf import FPDF
13
+ import io
14
+ import base64
15
+ from PIL import Image
16
+ import plotly.graph_objects as go
17
+ from plotly.subplots import make_subplots
18
+ import plotly.express as px
19
+ from streamlit_plotly_events import plotly_events
20
 
21
  # تنظیمات اولیه
22
+ st.set_page_config(page_title="سامانه پایش هوشمند مزارع نیشکر", layout="wide", initial_sidebar_state="expanded")
23
 
24
  # تنظیمات ظاهری برای متون فارسی
25
  st.markdown("""
 
58
  ee.Initialize(credentials)
59
 
60
  # تعریف توابع کمکی
61
+ @st.cache_data
62
  def load_farm_data():
63
  """بارگذاری اطلاعات مزارع"""
64
  try:
 
67
  st.error(f"خطا در بارگذاری اطلاعات مزارع: {str(e)}")
68
  return None
69
 
70
+ @st.cache_data
71
  def get_safe_index_value(image, index_type, band_selection, farm_geometry):
72
  """محاسبه ایمن شاخص‌های گیاهی"""
73
  if image is None:
 
96
  """محاسبه شاخص سطح برگ"""
97
  return -1.325 + 6.331 * ndvi - 2.239 * (ndvi ** 2)
98
 
99
+ @st.cache_data
100
+ def get_weekly_average_ndvi(farm_geometry, start_date, end_date):
101
+ """محاسبه میانگین هفتگی NDVI"""
102
+ s2_collection = ee.ImageCollection("COPERNICUS/S2") \
103
+ .filterDate(start_date, end_date) \
104
+ .filterBounds(farm_geometry) \
105
+ .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 20))
 
 
 
106
 
107
+ def calculate_ndvi(image):
108
+ ndvi = image.normalizedDifference(['B8', 'B4']).rename('NDVI')
109
+ return image.addBands(ndvi)
110
+
111
+ ndvi_collection = s2_collection.map(calculate_ndvi)
112
+
113
+ weekly_ndvi = ndvi_collection.select('NDVI').mean()
114
+
115
+ mean_ndvi = weekly_ndvi.reduceRegion(
116
+ reducer=ee.Reducer.mean(),
117
+ geometry=farm_geometry,
118
+ scale=10
119
+ ).get('NDVI').getInfo()
120
+
121
+ return mean_ndvi
122
+
123
+ @st.cache_data
124
+ def perform_clustering(farm_geometry, start_date, end_date):
125
+ """انجام خوشه‌بندی بر اساس NDVI"""
126
+ s2_collection = ee.ImageCollection("COPERNICUS/S2") \
127
+ .filterDate(start_date, end_date) \
128
+ .filterBounds(farm_geometry) \
129
+ .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 20))
130
+
131
+ composite = s2_collection.median()
132
+ ndvi = composite.normalizedDifference(['B8', 'B4']).rename('NDVI')
133
+
134
+ training = ndvi.sample(
135
+ region=farm_geometry,
136
+ scale=10,
137
+ numPixels=100
138
+ )
139
+
140
+ clusterer = ee.Clusterer.wekaKMeans(3).train(training)
141
+ result = ndvi.cluster(clusterer)
142
+
143
+ return result
144
+
145
+ def create_heatmap(df, index_type):
146
+ """ایجاد نقشه حرارتی برای شاخص مورد نظر"""
147
+ pivot_df = df.pivot("name", "date", index_type)
148
+ fig = px.imshow(pivot_df,
149
+ labels=dict(x="تاریخ", y="نام مزرعه", color=index_type),
150
+ x=pivot_df.columns,
151
+ y=pivot_df.index)
152
+ fig.update_layout(title=f"نقشه حرارتی {index_type}")
153
+ return fig
154
+
155
+ def create_comparison_chart(df, farm1, farm2, index_type):
156
+ """ایجاد نمودار مقایسه‌ای بین دو مزرعه"""
157
+ df_farm1 = df[df['name'] == farm1]
158
+ df_farm2 = df[df['name'] == farm2]
159
+
160
+ fig = go.Figure()
161
+ fig.add_trace(go.Scatter(x=df_farm1['date'], y=df_farm1[index_type], name=farm1))
162
+ fig.add_trace(go.Scatter(x=df_farm2['date'], y=df_farm2[index_type], name=farm2))
163
+
164
+ fig.update_layout(title=f"مقایسه {index_type} بین {farm1} و {farm2}",
165
+ xaxis_title="تاریخ",
166
+ yaxis_title=index_type)
167
+ return fig
168
+
169
+ def generate_pdf_report(farm_info, index_values, lai_values, date_list):
170
+ """تولید گزارش PDF"""
171
+ pdf = FPDF()
172
+ pdf.add_page()
173
+ pdf.add_font('Vazir', '', 'Vazir-Regular.ttf', uni=True)
174
+ pdf.set_font('Vazir', '', 14)
175
+
176
+ pdf.cell(200, 10, txt="گزارش وضعیت مزرعه", ln=True, align='C')
177
+ pdf.cell(200, 10, txt=f"ن��م مزرعه: {farm_info['name']}", ln=True)
178
+ pdf.cell(200, 10, txt=f"سن مزرعه: {farm_info['age']} سال", ln=True)
179
+ pdf.cell(200, 10, txt=f"نوع محصول: {farm_info['variety']}", ln=True)
180
+
181
+ # اضافه کردن نمودارها
182
+ for index in index_values.keys():
183
+ plt.figure(figsize=(10, 6))
184
+ plt.plot(date_list, index_values[index], marker='o')
185
+ plt.title(f"روند تغییرات {index}")
186
+ plt.xlabel("تاریخ")
187
+ plt.ylabel("مقدار شاخص")
188
+ plt.xticks(rotation=45)
189
+ img_buffer = io.BytesIO()
190
+ plt.savefig(img_buffer, format='png')
191
+ img_buffer.seek(0)
192
+ pdf.image(img_buffer, x=10, y=None, w=190)
193
+ plt.close()
194
+
195
+ # اضافه کردن توضیحات تحلیلی
196
+ pdf.cell(200, 10, txt="تحلیل وضعیت مزرعه:", ln=True)
197
+ latest_ndvi = index_values['NDVI'][-1]
198
+ latest_ndwi = index_values['NDWI'][-1]
199
+
200
+ if latest_ndvi > 0.5:
201
+ pdf.cell(200, 10, txt="وضعیت پوشش گیاهی مطلوب است.", ln=True)
202
+ elif latest_ndvi > 0.3:
203
+ pdf.cell(200, 10, txt="وضعیت پوشش گیاهی متوسط است.", ln=True)
204
+ else:
205
+ pdf.cell(200, 10, txt="وضعیت پوشش گیاهی نامطلوب است.", ln=True)
206
+
207
+ if latest_ndwi > 0.2:
208
+ pdf.cell(200, 10, txt="وضعیت آب گیاه مطلوب است.", ln=True)
209
+ elif latest_ndwi > 0:
210
+ pdf.cell(200, 10, txt="وضعیت آب گیاه متوسط است.", ln=True)
211
+ else:
212
+ pdf.cell(200, 10, txt="احتمال تنش آبی وجود دارد.", ln=True)
213
+
214
+ return pdf.output(dest='S').encode('latin-1')
215
 
216
  # تابع اصلی برنامه
217
  def main():
 
264
  try:
265
  # محاسبه تاریخ‌های مورد نیاز
266
  end_date = date.today()
267
+ start_date = end_date - timedelta(days=30) # افزایش بازه زمانی به یک ماه
268
+ date_list = [start_date + timedelta(days=x) for x in range(31)]
269
 
270
  # دریافت تصاویر و محاسبه شاخص‌ها
271
  with st.spinner('در حال پردازش اطلاعات...'):
 
294
  for index in band_selection.keys():
295
  index_values[index].append(0)
296
 
297
+ # محاسبه میانگین هفتگی NDVI
298
+ weekly_ndvi = get_weekly_average_ndvi(farm_geometry, start_date.strftime("%Y-%m-%d"), end_date.strftime("%Y-%m-%d"))
299
+ st.write(f"میانگین هفتگی NDVI: {weekly_ndvi:.2f}")
300
+
301
+ # انجام خوشه‌بندی
302
+ clustering_result = perform_clustering(farm_geometry, start_date.strftime("%Y-%m-%d"), end_date.strftime("%Y-%m-%d"))
303
+
304
  # نمایش نمودارها و نقشه NDVI
305
  col1, col2 = st.columns(2)
306
 
307
  with col1:
308
  st.subheader("روند تغییرات شاخص‌ها")
309
+ fig = make_subplots(rows=len(band_selection), cols=1, shared_xaxes=True)
310
+ for i, (index, values) in enumerate(index_values.items(), start=1):
311
+ fig.add_trace(go.Scatter(x=date_list, y=values, name=index), row=i, col=1)
312
+ fig.update_yaxes(title_text=index, row=i, col=1)
313
+ fig.update_layout(height=600, width=800, title_text="روند تغییرات شاخص‌ها")
314
+ st.plotly_chart(fig)
 
 
315
 
316
  with col2:
317
  st.subheader("شاخص سطح برگ (LAI)")
318
  lai_values = [calculate_lai(ndvi) for ndvi in index_values['NDVI']]
319
+ fig = px.line(x=date_list, y=lai_values, labels={'x': 'تاریخ', 'y': 'LAI'})
320
+ fig.update_layout(title_text="روند تغییرات شاخص سطح برگ")
321
+ st.plotly_chart(fig)
 
 
 
322
 
323
  # تحلیل وضعیت
324
  st.subheader("تحلیل وضعیت مزرعه")
 
366
  # نمایش نقشه
367
  Map.to_streamlit(height=400)
368
 
369
+ # نمایش نقشه حرارتی
370
+ st.subheader("نقشه حرارتی وضعیت مزارع")
371
+ heatmap_fig = create_heatmap(df, index_type)
372
+ st.plotly_chart(heatmap_fig)
373
+
374
+ # مقایسه بین مزارع
375
+ st.subheader("مقایسه بین مزارع")
376
+ farm1 = st.selectbox("انتخاب مزرعه اول", df["name"].unique())
377
+ farm2 = st.selectbox("انتخاب مزرعه دوم", df["name"].unique())
378
+ comparison_fig = create_comparison_chart(df, farm1, farm2, index_type)
379
+ st.plotly_chart(comparison_fig)
380
+
381
+ # تولید گزارش PDF
382
+ st.subheader("دریافت گزارش PDF")
383
+ if st.button("تولید گزارش PDF"):
384
+ pdf_report = generate_pdf_report(farm_info, index_values, lai_values, date_list)
385
+ st.download_button(
386
+ label="دانلود گزارش PDF",
387
+ data=pdf_report,
388
+ file_name=f"گزارش_{farm_info['name']}.pdf",
389
+ mime="application/pdf"
390
+ )
391
+
392
  except Exception as e:
393
  st.error(f"خطا در پردازش اطلاعات: {str(e)}")
394