Esmaeilkianii commited on
Commit
0831686
·
verified ·
1 Parent(s): 6ac73a2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +123 -86
app.py CHANGED
@@ -27,7 +27,7 @@ st.set_page_config(
27
  initial_sidebar_state="collapsed"
28
  )
29
 
30
- # Professional CSS with horizontal button menu
31
  st.markdown("""
32
  <style>
33
  @font-face {
@@ -38,32 +38,54 @@ st.markdown("""
38
  body {
39
  background: linear-gradient(135deg, #e8f5e9 0%, #c8e6c9 100%);
40
  color: #1a3c34;
 
 
 
 
 
 
 
 
 
 
 
 
41
  }
42
  .top-menu {
43
  display: flex;
44
  justify-content: center;
45
- gap: 15px;
46
  padding: 20px;
47
- background: linear-gradient(180deg, #1b5e20 0%, #4caf50 100%);
48
- border-radius: 0 0 20px 20px;
49
- box-shadow: 0 10px 30px rgba(0,0,0,0.2);
50
- animation: slideDown 0.8s ease-out;
 
 
51
  }
52
  .top-menu button {
53
- background: linear-gradient(45deg, #1b5e20, #66bb6a);
54
  color: white;
55
  border: none;
56
- border-radius: 30px;
57
- padding: 0.8rem 2rem;
58
- font-size: 1.1rem;
59
- box-shadow: 0 5px 15px rgba(0,0,0,0.2);
60
- transition: all 0.4s ease;
 
61
  cursor: pointer;
 
 
 
62
  }
63
  .top-menu button:hover {
64
  transform: translateY(-5px) scale(1.05);
65
- box-shadow: 0 8px 25px rgba(0,0,0,0.3);
66
- background: linear-gradient(45deg, #2e7d32, #81c784);
 
 
 
 
67
  }
68
  .card {
69
  background: rgba(255, 255, 255, 0.97);
@@ -160,14 +182,16 @@ if 'heights_df' not in st.session_state:
160
  'Variety', 'Age', 'Area', 'Channel', 'Administration'
161
  ])
162
 
163
- # Convert Gregorian to Jalali date
164
- def to_jalali(date_str):
165
- try:
166
- greg_date = datetime.strptime(date_str, '%Y-%m-%d')
167
- jalali_date = jdatetime.date.fromgregorian(date=greg_date)
168
- return jalali_date.strftime('%Y/%m/%d')
169
- except:
170
- return date_str
 
 
171
 
172
  # Enhanced Earth Engine Map Function
173
  @st.cache_data
@@ -222,6 +246,60 @@ def create_map(farm_id, date_str, layer_type="NDVI"):
222
  st.error(f"خطا در ایجاد نقشه: {e}")
223
  return None
224
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
225
  # Machine Learning Model
226
  @st.cache_resource
227
  def train_growth_model(_heights_df):
@@ -237,16 +315,16 @@ def train_growth_model(_heights_df):
237
  growth_model = train_growth_model(st.session_state.heights_df)
238
 
239
  # Top menu with buttons
240
- menu_options = ["داشبورد", "ورود اطلاعات", "گزارش‌گیری", "تحلیل داده‌ها", "پیش‌بینی رشد", "امتیازدهی مزارع", "تنظیمات"]
241
  cols = st.columns(len(menu_options))
242
  for i, option in enumerate(menu_options):
243
  with cols[i]:
244
  if st.button(option, key=f"menu_{option}"):
245
- st.session_state['selected_tab'] = option
246
 
247
  # Dashboard
248
  if st.session_state.get('selected_tab') == "داشبورد":
249
- st.markdown('<h1 class="header">🌿 داشبورد هوشمند پایش</h1>', unsafe_allow_html=True)
250
  st.markdown('<div class="card">', unsafe_allow_html=True)
251
 
252
  heights_df = st.session_state.heights_df
@@ -549,69 +627,28 @@ elif st.session_state.get('selected_tab') == "امتیازدهی مزارع":
549
  else:
550
  date = st.date_input("انتخاب تاریخ", datetime.now(), key="score_date")
551
  date_str = date.strftime('%Y-%m-%d')
552
- start_date = (date - timedelta(days=7)).strftime('%Y-%m-%d')
553
- end_date = (date - timedelta(days=1)).strftime('%Y-%m-%d')
554
 
555
- if st.button("محاسبه امتیازها", key="score_btn"):
556
- with st.spinner("در حال محاسبه امتیازها..."):
557
- scoring_data = []
558
- for _, farm in coordinates_df.iterrows():
559
- farm_id = farm['نام']
560
- lat, lon = farm['عرض جغرافیایی'], farm['طول جغرافیایی']
561
- region = ee.Geometry.Point([lon, lat]).buffer(1500)
562
-
563
- # NDVI for growth
564
- s2 = ee.ImageCollection('COPERNICUS/S2_SR') \
565
- .filterDate(start_date, end_date) \
566
- .filterBounds(region) \
567
- .sort('CLOUDY_PIXEL_PERCENTAGE') \
568
- .first()
569
- ndvi = s2.normalizedDifference(['B8', 'B4']).rename('NDVI')
570
- ndvi_value = ndvi.reduceRegion(reducer=ee.Reducer.mean(), geometry=region, scale=10).get('NDVI').getInfo() or 0
571
-
572
- # NDMI for moisture
573
- ndmi = s2.normalizedDifference(['B8', 'B11']).rename('NDMI')
574
- ndmi_value = ndmi.reduceRegion(reducer=ee.Reducer.mean(), geometry=region, scale=10).get('NDMI').getInfo() or 0
575
-
576
- # Scoring based on NDVI
577
- if ndvi_value < 0.1:
578
- growth_status = "بدون پوشش گیاهی"
579
- elif ndvi_value < 0.3:
580
- growth_status = "تنش‌دار"
581
- elif ndvi_value < 0.6:
582
- growth_status = "نرمال"
583
- else:
584
- growth_status = "خوب"
585
-
586
- # Scoring based on NDMI
587
- if ndmi_value < -0.2:
588
- moisture_status = "تنش‌دار"
589
- elif ndmi_value < 0.2:
590
- moisture_status = "نرمال"
591
  else:
592
- moisture_status = "خوب"
593
-
594
- scoring_data.append({
595
- 'مزرعه': farm_id,
596
- 'NDVI': ndvi_value,
597
- 'وضعیت رشد': growth_status,
598
- 'NDMI': ndmi_value,
599
- 'وضعیت رطوبت': moisture_status
600
- })
601
-
602
- scoring_df = pd.DataFrame(scoring_data)
603
- st.subheader(f"امتیازدهی مزارع (هفته قبل از {to_jalali(date_str)})")
604
- st.dataframe(scoring_df, use_container_width=True)
605
-
606
- # Summary
607
- growth_counts = scoring_df['وضعیت رشد'].value_counts()
608
- moisture_counts = scoring_df['وضعیت رطوبت'].value_counts()
609
- st.write("**خلاصه وضعیت رشد:**")
610
- for status, count in growth_counts.items():
611
- st.write(f"{status}: {count} مزرعه")
612
- st.write("**خلاصه وضعیت رطوبت:**")
613
- for status, count in moisture_counts.items():
614
- st.write(f"{status}: {count} مزرعه")
615
  st.markdown('</div>', unsafe_allow_html=True)
616
 
617
  # Settings
 
27
  initial_sidebar_state="collapsed"
28
  )
29
 
30
+ # Modern and vibrant CSS with graphical menu
31
  st.markdown("""
32
  <style>
33
  @font-face {
 
38
  body {
39
  background: linear-gradient(135deg, #e8f5e9 0%, #c8e6c9 100%);
40
  color: #1a3c34;
41
+ margin: 0;
42
+ padding: 0;
43
+ }
44
+ .top-bar {
45
+ background: linear-gradient(90deg, #1b5e20 0%, #4caf50 100%);
46
+ padding: 20px;
47
+ text-align: center;
48
+ color: white;
49
+ font-size: 1.2rem;
50
+ box-shadow: 0 4px 15px rgba(0,0,0,0.3);
51
+ border-radius: 0 0 20px 20px;
52
+ animation: slideDown 0.8s ease-out;
53
  }
54
  .top-menu {
55
  display: flex;
56
  justify-content: center;
57
+ gap: 20px;
58
  padding: 20px;
59
+ background: rgba(255, 255, 255, 0.1);
60
+ backdrop-filter: blur(10px);
61
+ border-radius: 20px;
62
+ box-shadow: 0 8px 32px rgba(0,0,0,0.2);
63
+ margin: 20px auto;
64
+ max-width: 1200px;
65
  }
66
  .top-menu button {
67
+ background: linear-gradient(135deg, #2e7d32 0%, #81c784 100%);
68
  color: white;
69
  border: none;
70
+ border-radius: 15px;
71
+ padding: 15px 25px;
72
+ font-size: 1.2rem;
73
+ font-weight: bold;
74
+ box-shadow: 0 5px 15px rgba(0,0,0,0.3);
75
+ transition: all 0.3s ease;
76
  cursor: pointer;
77
+ display: flex;
78
+ align-items: center;
79
+ gap: 10px;
80
  }
81
  .top-menu button:hover {
82
  transform: translateY(-5px) scale(1.05);
83
+ box-shadow: 0 10px 25px rgba(0,0,0,0.4);
84
+ background: linear-gradient(135deg, #388e3c 0%, #a5d6a7 100%);
85
+ }
86
+ .top-menu button:active {
87
+ transform: translateY(2px);
88
+ box-shadow: 0 3px 10px rgba(0,0,0,0.2);
89
  }
90
  .card {
91
  background: rgba(255, 255, 255, 0.97);
 
182
  'Variety', 'Age', 'Area', 'Channel', 'Administration'
183
  ])
184
 
185
+ # Convert Gregorian to Jalali date and get weekday
186
+ def get_jalali_date_and_day():
187
+ greg_date = datetime.now()
188
+ jalali_date = jdatetime.date.fromgregorian(date=greg_date)
189
+ weekdays = ["دوشنبه", "سه‌شنبه", "چهارشنبه", "پنجشنبه", "جمعه", "شنبه", "یکشنبه"]
190
+ weekday = weekdays[jalali_date.weekday()]
191
+ return jalali_date.strftime('%Y/%m/%d'), weekday
192
+
193
+ jalali_date, current_day = get_jalali_date_and_day()
194
+ st.markdown(f'<div class="top-bar">تاریخ: {jalali_date} | روز: {current_day}</div>', unsafe_allow_html=True)
195
 
196
  # Enhanced Earth Engine Map Function
197
  @st.cache_data
 
246
  st.error(f"خطا در ایجاد نقشه: {e}")
247
  return None
248
 
249
+ # Cached Scoring Function
250
+ @st.cache_data
251
+ def calculate_farm_scores(date_str, farms):
252
+ if not earth_engine_initialized:
253
+ return None
254
+ scoring_data = []
255
+ date_obj = datetime.strptime(date_str, '%Y-%m-%d')
256
+ start_date = (date_obj - timedelta(days=7)).strftime('%Y-%m-%d')
257
+ end_date = (date_obj - timedelta(days=1)).strftime('%Y-%m-%d')
258
+
259
+ for _, farm in farms.iterrows():
260
+ farm_id = farm['نام']
261
+ lat, lon = farm['عرض جغرافیایی'], farm['طول جغرافیایی']
262
+ region = ee.Geometry.Point([lon, lat]).buffer(1500)
263
+
264
+ s2 = ee.ImageCollection('COPERNICUS/S2_SR') \
265
+ .filterDate(start_date, end_date) \
266
+ .filterBounds(region) \
267
+ .sort('CLOUDY_PIXEL_PERCENTAGE') \
268
+ .first()
269
+
270
+ if s2:
271
+ ndvi = s2.normalizedDifference(['B8', 'B4']).rename('NDVI')
272
+ ndvi_value = ndvi.reduceRegion(reducer=ee.Reducer.mean(), geometry=region, scale=10).get('NDVI').getInfo() or 0
273
+
274
+ ndmi = s2.normalizedDifference(['B8', 'B11']).rename('NDMI')
275
+ ndmi_value = ndmi.reduceRegion(reducer=ee.Reducer.mean(), geometry=region, scale=10).get('NDMI').getInfo() or 0
276
+
277
+ if ndvi_value < 0.1:
278
+ growth_status = "بدون پوشش گیاهی"
279
+ elif ndvi_value < 0.3:
280
+ growth_status = "تنش‌دار"
281
+ elif ndvi_value < 0.6:
282
+ growth_status = "نرمال"
283
+ else:
284
+ growth_status = "خوب"
285
+
286
+ if ndmi_value < -0.2:
287
+ moisture_status = "تنش‌دار"
288
+ elif ndmi_value < 0.2:
289
+ moisture_status = "نرمال"
290
+ else:
291
+ moisture_status = "خوب"
292
+
293
+ scoring_data.append({
294
+ 'مزرعه': farm_id,
295
+ 'NDVI': ndvi_value,
296
+ 'وضعیت رشد': growth_status,
297
+ 'NDMI': ndmi_value,
298
+ 'وضعیت رطوبت': moisture_status
299
+ })
300
+
301
+ return pd.DataFrame(scoring_data)
302
+
303
  # Machine Learning Model
304
  @st.cache_resource
305
  def train_growth_model(_heights_df):
 
315
  growth_model = train_growth_model(st.session_state.heights_df)
316
 
317
  # Top menu with buttons
318
+ menu_options = ["📊 داشبورد", "✍️ ورود اطلاعات", "📈 گزارش‌گیری", "🔍 تحلیل داده‌ها", "🔮 پیش‌بینی رشد", " وضعیت مزارع", "⚙️ تنظیمات"]
319
  cols = st.columns(len(menu_options))
320
  for i, option in enumerate(menu_options):
321
  with cols[i]:
322
  if st.button(option, key=f"menu_{option}"):
323
+ st.session_state['selected_tab'] = option.split(' ')[1]
324
 
325
  # Dashboard
326
  if st.session_state.get('selected_tab') == "داشبورد":
327
+ st.markdown('<h1 class="header">🌿 مطالعات کاربردی کشت و صنعت دهخدا </h1>', unsafe_allow_html=True)
328
  st.markdown('<div class="card">', unsafe_allow_html=True)
329
 
330
  heights_df = st.session_state.heights_df
 
627
  else:
628
  date = st.date_input("انتخاب تاریخ", datetime.now(), key="score_date")
629
  date_str = date.strftime('%Y-%m-%d')
 
 
630
 
631
+ filtered_farms = coordinates_df[coordinates_df['نام'].isin(farms_df[farms_df['روز'] == current_day]['مزرعه'])]
632
+ if filtered_farms.empty:
633
+ st.warning(f"هیچ مزرعه‌ای برای روز {current_day} یافت نشد.")
634
+ else:
635
+ if st.button("محاسبه امتیازها", key="score_btn"):
636
+ with st.spinner("در حال محاسبه امتیازها..."):
637
+ scoring_df = calculate_farm_scores(date_str, filtered_farms)
638
+ if scoring_df is not None and not scoring_df.empty:
639
+ st.subheader(f"امتیازدهی مزارع روز {current_day} (هفته قبل از {to_jalali(date_str)})")
640
+ st.dataframe(scoring_df, use_container_width=True)
641
+
642
+ growth_counts = scoring_df['وضعیت رشد'].value_counts()
643
+ moisture_counts = scoring_df['وضعیت رطوبت'].value_counts()
644
+ st.write("**خلاصه وضعیت رشد:**")
645
+ for status, count in growth_counts.items():
646
+ st.write(f"{status}: {count} مزرعه")
647
+ st.write("**خلاصه وضعیت رطوبت:**")
648
+ for status, count in moisture_counts.items():
649
+ st.write(f"{status}: {count} مزرعه")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
650
  else:
651
+ st.warning("داده‌ای برای امتیازدهی در این بازه زمانی یافت نشد.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
652
  st.markdown('</div>', unsafe_allow_html=True)
653
 
654
  # Settings