Esmaeilkiani commited on
Commit
a84c078
·
verified ·
1 Parent(s): 489ca6a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +343 -96
app.py CHANGED
@@ -1,106 +1,353 @@
1
  import streamlit as st
 
 
2
  import pandas as pd
3
  import matplotlib.pyplot as plt
4
- import seaborn as sns
5
- from datetime import datetime
6
 
7
- # تنظیمات اولیه صفحه
8
- st.set_page_config(page_title="تحلیل رشد مزارع نیشکر", layout="wide")
9
- st.title("برنامه تحلیل و گزارش‌گیری مزارع نیشکر")
10
 
11
- # بارگذاری یا ایجاد دیتافریم اولیه
12
- if 'data.csv' in st.session_state:
13
- data = pd.read_csv('کراپ لاگ اپ.csv')
14
- else:
15
- # ستون‌های مشابه فایل اکسل شما
16
- columns = [
17
- 'شناسه مزرعه', 'تاریخ', 'رشد هفته جاری', 'رشد هفته گذشته', 'ارتفاع هفته جاری مزرعه',
18
- 'ارتفاع هفته گذشته مزرعه', 'نیتروژن فعلی', 'نیتروژن استاندارد فعلی', 'رطوبت غلاف فعلی',
19
- 'رطوبت استاندارد فعلی', 'واریته', 'سن', 'مساحت داشت', 'ایستگاه 1', 'ایستگاه 2',
20
- 'ایستگاه 3', 'ایستگاه 4', 'ایستگاه 5', 'چاهک 1', 'تاریخ قرائت چاهک 1'
21
- ]
22
- data = pd.DataFrame(columns=columns)
23
- st.session_state['data.csv'] = data
24
-
25
- # بخش ورود داده‌ها
26
- st.header("ورود داده‌های جدید")
27
- with st.form(key='data_form'):
28
- col1, col2, col3 = st.columns(3)
29
- with col1:
30
- farm_id = st.text_input("شناسه مزرعه (مثلاً 01-22R4CP69)")
31
- date = st.date_input("تاریخ")
32
- growth_current = st.number_input("رشد هفته جاری (سانتی‌متر)", min_value=0.0, step=0.1)
33
- growth_previous = st.number_input("رشد هفته گذشته (سانتی‌متر)", min_value=0.0, step=0.1)
34
- height_current = st.number_input("ارتفاع هفته جاری (سانتی‌متر)", min_value=0.0, step=0.1)
35
- height_previous = st.number_input("ارتفاع هفته گذشته (سانتی‌متر)", min_value=0.0, step=0.1)
36
- with col2:
37
- nitrogen_current = st.number_input("نیتروژن فعلی", min_value=0.0, step=0.01)
38
- nitrogen_std_current = st.number_input("نیتروژن استاندارد فعلی", min_value=0.0, step=0.01)
39
- moisture_current = st.number_input("رطوبت غلاف فعلی (%)", min_value=0.0, max_value=100.0, step=0.1)
40
- moisture_std_current = st.number_input("رطوبت استاندارد فعلی (%)", min_value=0.0, max_value=100.0, step=0.1)
41
- variety = st.selectbox("واریته", ['CP69', 'CP48', 'CP57', 'CP73', 'IR01-412'])
42
- with col3:
43
- age = st.text_input("سن (مثلاً R1, P)")
44
- area = st.number_input("مساحت داشت (هکتار)", min_value=0.0, step=0.1)
45
- station1 = st.number_input("ایستگاه 1 (ارتفاع)", min_value=0.0, step=0.1)
46
- station2 = st.number_input("ایستگاه 2 (ارتفاع)", min_value=0.0, step=0.1)
47
- station3 = st.number_input("ایستگاه 3 (ارتفاع)", min_value=0.0, step=0.1)
48
- station4 = st.number_input("ایستگاه 4 (ارتفاع)", min_value=0.0, step=0.1)
49
- station5 = st.number_input("ایستگاه 5 (ارتفاع)", min_value=0.0, step=0.1)
50
- well1 = st.number_input("چاهک 1 (عمق)", min_value=0.0, step=0.1)
51
- well1_date = st.date_input("تاریخ قرائت چاهک 1")
52
 
53
- submit_button = st.form_submit_button(label="افزودن داده")
54
- if submit_button:
55
- new_data = pd.DataFrame({
56
- 'شناسه مزرعه': [farm_id], 'تاریخ': [date], 'رشد هفته جاری': [growth_current],
57
- 'رشد هفته گذشته': [growth_previous], 'ارتفاع هفته جاری مزرعه': [height_current],
58
- 'ارتفاع هفته گذشته مزرعه': [height_previous], 'نیتروژن فعلی': [nitrogen_current],
59
- 'نیتروژن استاندارد فعلی': [nitrogen_std_current], 'رطوبت غلاف فعلی': [moisture_current],
60
- 'رطوبت استاندارد فعلی': [moisture_std_current], 'واریته': [variety], 'سن': [age],
61
- 'مساحت داشت': [area], 'ایستگاه 1': [station1], 'ایستگاه 2': [station2],
62
- 'ایستگاه 3': [station3], 'ایستگاه 4': [station4], 'ایستگاه 5': [station5],
63
- 'چاهک 1': [well1], 'تاریخ قرائت چاهک 1': [well1_date]
64
- })
65
- data = pd.concat([data, new_data], ignore_index=True)
66
- data.to_csv('data.csv', index=False)
67
- st.session_state['data.csv'] = data
68
- st.success("داده با موفقیت اضافه شد!")
 
 
 
69
 
70
- # نمایش داده‌ها
71
- st.header("داده‌های مزارع نیشکر")
72
- st.dataframe(data)
73
 
74
- # تحلیل و نمودارها
75
- st.header("تحلیل داده‌ها")
76
- if not data.empty:
77
- # نمودار رشد هفتگی بر اساس تاریخ
78
- plt.figure(figsize=(10, 6))
79
- sns.lineplot(x='تاریخ', y='رشد هفته جاری', hue='واریته', data=data)
80
- plt.title('رشد هفتگی مزارع نیشکر بر اساس واریته')
81
- plt.xlabel('تاریخ')
82
- plt.ylabel('رشد هفته جاری (سانتی‌متر)')
83
- plt.xticks(rotation=45)
84
- st.pyplot(plt)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
 
86
- # نمودار مقایسه نیتروژن فعلی و استاندارد
87
- plt.figure(figsize=(10, 6))
88
- sns.scatterplot(x='نیتروژن فعلی', y='نیتروژن استاندارد فعلی', hue='واریته', size='رشد هفته جاری', data=data)
89
- plt.title('مقایسه نیتروژن فعلی و استاندارد')
90
- plt.xlabel('نیتروژن فعلی')
91
- plt.ylabel('نیتروژن استاندارد فعلی')
92
- st.pyplot(plt)
93
-
94
- # نمودار رطوبت فعلی بر اساس واریته
95
- plt.figure(figsize=(10, 6))
96
- sns.boxplot(x='واریته', y='رطوبت غلاف فعلی', data=data)
97
- plt.title('توزیع رطوبت غلاف فعلی بر اساس واریته')
98
- plt.xlabel('واریته')
99
- plt.ylabel('رطوبت غلاف فعلی (%)')
100
- st.pyplot(plt)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  else:
102
- st.write("داده‌ای برای تحلیل وجود ندارد. لطفاً داده‌های جدید وارد کنید.")
103
-
104
- # اجرای برنامه
105
- if __name__ == "__main__":
106
- st.write("برنامه در حال اجرا است...")
 
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 = 'dehkhodamap-e9f0da4ce9f6514021@ee-esmaeilkiani13877.iam.gserviceaccount.com'
22
+ credentials_path = 'ee-esmaeilkiani13877-cfdea6eaf411.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
+ right: