', unsafe_allow_html=True)
@@ -628,28 +766,28 @@ if selected == "داشبورد":
with col1:
st.markdown('
', unsafe_allow_html=True)
with col2:
- active_farms = int(len(farm_df["Farm_ID"].unique()) * 0.85)
+ active_farms = int(len(farm_df) * 0.85)
st.markdown('
', unsafe_allow_html=True)
with col3:
- avg_height = farm_df['CurrentHeight'].mean()
+ avg_height = 175
st.markdown('
', unsafe_allow_html=True)
with col4:
- avg_moisture = farm_df['CurrentMoisture'].mean()
+ avg_moisture = 68
st.markdown('
', unsafe_allow_html=True)
@@ -662,12 +800,15 @@ if selected == "داشبورد":
col1, col2 = st.columns(2)
with col1:
- variety_counts = farm_df['Variety'].value_counts().reset_index()
- variety_counts.columns = ['Variety', 'Count']
+ # Group farms by variety
+ variety_counts = farm_df['واریته'].value_counts().reset_index()
+ variety_counts.columns = ['واریته', 'تعداد']
+
+ # Create a pie chart for varieties
fig = px.pie(
variety_counts,
- values='Count',
- names='Variety',
+ values='تعداد',
+ names='واریته',
title='توزیع واریتهها',
color_discrete_sequence=px.colors.sequential.Greens_r
)
@@ -679,12 +820,15 @@ if selected == "داشبورد":
st.plotly_chart(fig, use_container_width=True)
with col2:
- age_counts = farm_df['Age'].value_counts().reset_index()
- age_counts.columns = ['Age', 'Count']
+ # Group farms by age
+ age_counts = farm_df['سن'].value_counts().reset_index()
+ age_counts.columns = ['سن', 'تعداد']
+
+ # Create a pie chart for ages
fig = px.pie(
age_counts,
- values='Count',
- names='Age',
+ values='تعداد',
+ names='سن',
title='توزیع سن محصول',
color_discrete_sequence=px.colors.sequential.Blues_r
)
@@ -697,31 +841,41 @@ if selected == "داشبورد":
st.markdown("### اطلاعات کلی مزارع")
- total_area = farm_df['Area'].sum()
+ # Calculate total area
+ total_area = farm_df['مساحت'].astype(float).sum()
+ # Create metrics
col1, col2, col3 = st.columns(3)
- col1.metric("تعداد کل مزارع", f"{len(farm_df['Farm_ID'].unique())}")
+ col1.metric("تعداد کل مزارع", f"{len(farm_df)}")
col2.metric("مساحت کل (هکتار)", f"{total_area:.2f}")
- col3.metric("تعداد کانالها", f"{farm_df['Channel'].nunique()}")
+ col3.metric("تعداد کانالها", f"{farm_df['کانال'].nunique()}")
+ # Add a styled separator
st.markdown('
', unsafe_allow_html=True)
+ # Add a lottie animation
st_lottie(lottie_farm, height=300, key="farm_animation")
with tab2:
st.markdown("### نقشه مزارع")
+ # Create a map of all farms
if coordinates_df is not None and not coordinates_df.empty:
+ # Create a base map
m = folium.Map(location=[31.45, 48.72], zoom_start=12, tiles='CartoDB positron')
+
+ # Add markers for each farm
for _, farm in coordinates_df.iterrows():
- lat = farm['Latitude']
- lon = farm['Longitude']
- name = farm['Farm_ID']
- farm_info = farm_df[farm_df['Farm_ID'] == name]
+ lat = farm['عرض جغرافیایی']
+ lon = farm['طول جغرافیایی']
+ name = farm['نام']
+
+ # Get additional info from farm_df if available
+ farm_info = farm_df[farm_df['مزرعه'] == name]
if not farm_info.empty:
- variety = farm_info['Variety'].iloc[0]
- age = farm_info['Age'].iloc[0]
- area = farm_info['Area'].iloc[0]
+ variety = farm_info['واریته'].iloc[0]
+ age = farm_info['سن'].iloc[0]
+ area = farm_info['مساحت'].iloc[0]
popup_text = f"""
مزرعه {name}
@@ -732,12 +886,16 @@ if selected == "داشبورد":
"""
else:
popup_text = f"
مزرعه {name}
"
+
+ # Add marker
folium.Marker(
[lat, lon],
popup=folium.Popup(popup_text, max_width=300),
tooltip=f"مزرعه {name}",
icon=folium.Icon(color='green', icon='leaf')
).add_to(m)
+
+ # Display the map
st.markdown('
', unsafe_allow_html=True)
folium_static(m, width=1000, height=600)
st.markdown('
', unsafe_allow_html=True)
@@ -747,26 +905,30 @@ if selected == "داشبورد":
with tab3:
st.markdown("### نمودار رشد هفتگی")
+ # Create filters for variety and age
col1, col2 = st.columns(2)
with col1:
selected_variety = st.selectbox(
"انتخاب واریته",
- ["all"] + list(farm_df['Variety'].unique()),
+ ["all"] + list(farm_df['واریته'].unique()),
format_func=lambda x: "همه واریتهها" if x == "all" else x
)
with col2:
selected_age = st.selectbox(
"انتخاب سن",
- ["all"] + list(farm_df['Age'].unique()),
+ ["all"] + list(farm_df['سن'].unique()),
format_func=lambda x: "همه سنین" if x == "all" else x
)
- growth_data = generate_real_growth_data(selected_variety, selected_age)
+ # Generate mock growth data
+ growth_data = generate_mock_growth_data(farm_df, selected_variety, selected_age)
+ # Create tabs for average and individual growth charts
chart_tab1, chart_tab2 = st.tabs(["میانگین رشد", "رشد مزارع فردی"])
with chart_tab1:
+ # Create average growth chart
avg_data = growth_data['average']
fig = go.Figure()
fig.add_trace(go.Scatter(
@@ -777,6 +939,7 @@ if selected == "داشبورد":
line=dict(color='#1a8754', width=3),
marker=dict(size=8, color='#1a8754')
))
+
fig.update_layout(
title='میانگین رشد هفتگی',
xaxis_title='هفته',
@@ -786,11 +949,15 @@ if selected == "داشبورد":
template='plotly_white',
height=500
)
+
st.plotly_chart(fig, use_container_width=True)
with chart_tab2:
+ # Create individual growth chart
if growth_data['individual']:
fig = go.Figure()
+
+ # Only show up to 5 farms to avoid clutter
colors = ['#1a8754', '#1976d2', '#e65100', '#9c27b0', '#d32f2f']
for i, farm_data in enumerate(growth_data['individual'][:5]):
fig.add_trace(go.Scatter(
@@ -801,6 +968,7 @@ if selected == "داشبورد":
line=dict(color=colors[i % len(colors)], width=2),
marker=dict(size=6, color=colors[i % len(colors)])
))
+
fig.update_layout(
title='رشد هفتگی مزارع فردی',
xaxis_title='هفته',
@@ -810,6 +978,7 @@ if selected == "داشبورد":
template='plotly_white',
height=500
)
+
st.plotly_chart(fig, use_container_width=True)
else:
st.warning("دادهای برای نمایش وجود ندارد.")
@@ -817,19 +986,23 @@ if selected == "داشبورد":
with tab4:
st.markdown("### دادههای مزارع")
+ # Create a search box
search_term = st.text_input("جستجو در دادهها", placeholder="نام مزرعه، واریته، سن و...")
+ # Filter data based on search term
if search_term:
filtered_df = farm_df[
- farm_df['Farm_ID'].astype(str).str.contains(search_term) |
- farm_df['Variety'].astype(str).str.contains(search_term) |
- farm_df['Age'].astype(str).str.contains(search_term) |
- farm_df['Channel'].astype(str).str.contains(search_term)
+ farm_df['مزرعه'].astype(str).str.contains(search_term) |
+ farm_df['واریته'].astype(str).str.contains(search_term) |
+ farm_df['سن'].astype(str).str.contains(search_term) |
+ farm_df['کانال'].astype(str).str.contains(search_term)
]
else:
filtered_df = farm_df
+ # Display data table with pagination
if not filtered_df.empty:
+ # Add a download button
csv = filtered_df.to_csv(index=False).encode('utf-8')
st.download_button(
label="دانلود دادهها (CSV)",
@@ -837,12 +1010,15 @@ if selected == "داشبورد":
file_name="farm_data.csv",
mime="text/csv",
)
+
+ # Display the data table
st.dataframe(
filtered_df,
use_container_width=True,
height=400,
hide_index=True
)
+
st.info(f"نمایش {len(filtered_df)} مزرعه از {len(farm_df)} مزرعه")
else:
st.warning("هیچ دادهای یافت نشد.")
@@ -851,25 +1027,29 @@ if selected == "داشبورد":
elif selected == "نقشه مزارع":
st.markdown("## نقشه مزارع با شاخصهای ماهوارهای")
+ # Create a layout with sidebar for controls
col1, col2 = st.columns([1, 3])
with col1:
st.markdown('
', unsafe_allow_html=True)
st.markdown("### تنظیمات نقشه")
+ # Farm selection
selected_farm = st.selectbox(
"انتخاب مزرعه",
- options=coordinates_df['Farm_ID'].tolist(),
+ options=coordinates_df['نام'].tolist(),
index=0,
format_func=lambda x: f"مزرعه {x}"
)
+ # Date selection
selected_date = st.date_input(
"انتخاب تاریخ",
value=datetime.now(),
format="YYYY-MM-DD"
)
+ # Layer type selection
selected_layer = st.selectbox(
"انتخاب شاخص",
options=["NDVI", "NDMI", "EVI", "NDWI"],
@@ -881,14 +1061,17 @@ elif selected == "نقشه مزارع":
}[x]
)
+ # Generate map button
generate_map = st.button(
"تولید نقشه",
type="primary",
use_container_width=True
)
+ # Add a separator
st.markdown('
', unsafe_allow_html=True)
+ # Add index descriptions
st.markdown("### راهنمای شاخصها")
with st.expander("شاخص پوشش گیاهی (NDVI)", expanded=selected_layer == "NDVI"):
@@ -938,26 +1121,35 @@ elif selected == "نقشه مزارع":
st.markdown('', unsafe_allow_html=True)
with col2:
+ # Create tabs for map and statistics
map_tab, stats_tab = st.tabs(["نقشه", "آمار و تحلیل"])
with map_tab:
st.markdown('
', unsafe_allow_html=True)
+
if generate_map or 'last_map' not in st.session_state:
with st.spinner('در حال تولید نقشه...'):
+ # Create the map
m = create_ee_map(
selected_farm,
selected_date.strftime('%Y-%m-%d'),
selected_layer
)
+
if m:
st.session_state.last_map = m
folium_static(m, width=800, height=600)
+
+ # Add a success message
st.success(f"نقشه {selected_layer} برای مزرعه {selected_farm} با موفقیت تولید شد.")
else:
st.error("خطا در تولید نقشه. لطفاً دوباره تلاش کنید.")
elif 'last_map' in st.session_state:
folium_static(st.session_state.last_map, width=800, height=600)
+
st.markdown('
', unsafe_allow_html=True)
+
+ # Add a note about the map
st.info("""
**نکته:** این نقشه بر اساس تصاویر ماهوارهای Sentinel-2 تولید شده است.
برای دقت بیشتر، تاریخی را انتخاب کنید که ابرناکی کمتری داشته باشد.
@@ -965,34 +1157,37 @@ elif selected == "نقشه مزارع":
with stats_tab:
if 'last_map' in st.session_state:
+ # Calculate statistics for the selected farm and layer
stats = calculate_farm_stats(selected_farm, selected_layer)
+ # Display statistics in cards
col1, col2, col3, col4 = st.columns(4)
with col1:
st.markdown('
', unsafe_allow_html=True)
- st.markdown(f'
{stats["mean"]:.2f}
', unsafe_allow_html=True)
+ st.markdown(f'
{stats["mean"]}
', unsafe_allow_html=True)
st.markdown(f'
میانگین {selected_layer}
', unsafe_allow_html=True)
st.markdown('
', unsafe_allow_html=True)
with col2:
st.markdown('
', unsafe_allow_html=True)
- st.markdown(f'
{stats["max"]:.2f}
', unsafe_allow_html=True)
+ st.markdown(f'
{stats["max"]}
', unsafe_allow_html=True)
st.markdown(f'
حداکثر {selected_layer}
', unsafe_allow_html=True)
st.markdown('
', unsafe_allow_html=True)
with col3:
st.markdown('
', unsafe_allow_html=True)
- st.markdown(f'
{stats["min"]:.2f}
', unsafe_allow_html=True)
+ st.markdown(f'
{stats["min"]}
', unsafe_allow_html=True)
st.markdown(f'
حداقل {selected_layer}
', unsafe_allow_html=True)
st.markdown('
', unsafe_allow_html=True)
with col4:
st.markdown('
', unsafe_allow_html=True)
- st.markdown(f'
{stats["std_dev"]:.2f}
', unsafe_allow_html=True)
+ st.markdown(f'
{stats["std_dev"]}
', unsafe_allow_html=True)
st.markdown(f'
انحراف معیار
', unsafe_allow_html=True)
st.markdown('
', unsafe_allow_html=True)
+ # Create a histogram of values
fig = px.histogram(
x=stats["histogram_data"],
nbins=20,
@@ -1000,17 +1195,24 @@ elif selected == "نقشه مزارع":
labels={"x": f"مقدار {selected_layer}", "y": "فراوانی"},
color_discrete_sequence=["#1a8754"]
)
+
fig.update_layout(
font=dict(family="Vazirmatn"),
template="plotly_white",
bargap=0.1
)
+
st.plotly_chart(fig, use_container_width=True)
+ # Add a time series analysis
+ st.markdown("### تحلیل زمانی")
+
+ # Generate mock time series data
dates = pd.date_range(end=selected_date, periods=30, freq='D')
- values = [stats["mean"] + np.random.normal(0, stats["std_dev"] / 2) for _ in range(30)]
+ values = np.random.normal(stats["mean"], stats["std_dev"] / 2, 30)
values = np.clip(values, stats["min"], stats["max"])
+ # Create a time series chart
fig = px.line(
x=dates,
y=values,
@@ -1018,16 +1220,23 @@ elif selected == "نقشه مزارع":
labels={"x": "تاریخ", "y": f"مقدار {selected_layer}"},
markers=True
)
+
fig.update_layout(
font=dict(family="Vazirmatn"),
template="plotly_white",
hovermode="x unified"
)
+
st.plotly_chart(fig, use_container_width=True)
- farm_names = coordinates_df['Farm_ID'].tolist()[:5]
+ # Add a comparison with other farms
+ st.markdown("### مقایسه با سایر مزارع")
+
+ # Generate mock comparison data
+ farm_names = coordinates_df['نام'].tolist()[:5] # Get 5 farm names for comparison
comparison_values = [stats["mean"] + np.random.uniform(-0.2, 0.2) for _ in range(len(farm_names))]
+ # Create a comparison bar chart
fig = px.bar(
x=farm_names,
y=comparison_values,
@@ -1036,11 +1245,13 @@ elif selected == "نقشه مزارع":
color=comparison_values,
color_continuous_scale="Viridis"
)
+
fig.update_layout(
font=dict(family="Vazirmatn"),
template="plotly_white",
coloraxis_showscale=False
)
+
st.plotly_chart(fig, use_container_width=True)
else:
st.warning("لطفاً ابتدا یک نقشه تولید کنید.")
@@ -1049,9 +1260,11 @@ elif selected == "نقشه مزارع":
elif selected == "ورود اطلاعات":
st.markdown("## ورود اطلاعات روزانه مزارع")
+ # Create tabs for manual entry and file upload
tab1, tab2 = st.tabs(["ورود دستی", "آپلود فایل"])
with tab1:
+ # Create filters for week and day
col1, col2 = st.columns(2)
with col1:
@@ -1062,114 +1275,160 @@ elif selected == "ورود اطلاعات":
)
with col2:
- days = day_df['Day'].unique().tolist()
- selected_day = st.selectbox("انتخاب روز", options=days)
+ selected_day = st.selectbox(
+ "انتخاب روز",
+ options=["شنبه", "یکشنبه", "دوشنبه", "سهشنبه", "چهارشنبه", "پنجشنبه"]
+ )
- filtered_farms = farm_df[farm_df['Week'] == int(selected_week)]
- filtered_farms = filtered_farms[filtered_farms['Farm_ID'].isin(day_df[day_df['Day'] == selected_day]['Farm_ID'])]
+ # Filter farms by selected day
+ filtered_farms = farm_df[farm_df['روز'] == selected_day]
if filtered_farms.empty:
- st.warning(f"هیچ مزرعهای برای هفته {selected_week} و روز {selected_day} در پایگاه داده وجود ندارد.")
+ st.warning(f"هیچ مزرعهای برای روز {selected_day} در پایگاه داده وجود ندارد.")
else:
+ # Create a data editor
st.markdown("### ورود دادههای مزارع")
+ # Initialize data if not already in session state
data_key = f"data_{selected_week}_{selected_day}"
if data_key not in st.session_state:
st.session_state[data_key] = pd.DataFrame({
- 'Farm_ID': filtered_farms['Farm_ID'],
- 'Station1': [0] * len(filtered_farms),
- 'Station2': [0] * len(filtered_farms),
- 'Station3': [0] * len(filtered_farms),
- 'Station4': [0] * len(filtered_farms),
- 'Station5': [0] * len(filtered_farms),
- 'Well1': [0] * len(filtered_farms),
- 'Well2': [0] * len(filtered_farms),
- 'CurrentMoisture': [0] * len(filtered_farms),
- 'CurrentNitrogen': [0] * len(filtered_farms),
- 'CurrentHeight': [0] * len(filtered_farms)
+ 'مزرعه': filtered_farms['مزرعه'],
+ 'ایستگاه 1': [0] * len(filtered_farms),
+ 'ایستگاه 2': [0] * len(filtered_farms),
+ 'ایستگاه 3': [0] * len(filtered_farms),
+ 'ایستگاه 4': [0] * len(filtered_farms),
+ 'ایستگاه 5': [0] * len(filtered_farms),
+ 'چاهک 1': [0] * len(filtered_farms),
+ 'چاهک 2': [0] * len(filtered_farms),
+ 'رطوبت غلاف': [0] * len(filtered_farms),
+ 'نیتروژن': [0] * len(filtered_farms),
+ 'میانگین ارتفاع': [0] * len(filtered_farms)
})
+ # Create a data editor
edited_df = st.data_editor(
st.session_state[data_key],
use_container_width=True,
num_rows="fixed",
column_config={
- "Farm_ID": st.column_config.TextColumn("مزرعه", disabled=True),
- "Station1": st.column_config.NumberColumn("ایستگاه 1", min_value=0, max_value=300, step=1),
- "Station2": st.column_config.NumberColumn("ایستگاه 2", min_value=0, max_value=300, step=1),
- "Station3": st.column_config.NumberColumn("ایستگاه 3", min_value=0, max_value=300, step=1),
- "Station4": st.column_config.NumberColumn("ایستگاه 4", min_value=0, max_value=300, step=1),
- "Station5": st.column_config.NumberColumn("ایستگاه 5", min_value=0, max_value=300, step=1),
- "Well1": st.column_config.NumberColumn("چاهک 1", min_value=0, max_value=300, step=1),
- "Well2": st.column_config.NumberColumn("چاهک 2", min_value=0, max_value=300, step=1),
- "CurrentMoisture": st.column_config.NumberColumn("رطوبت غلاف", min_value=0, max_value=100, step=1),
- "CurrentNitrogen": st.column_config.NumberColumn("نیتروژن", min_value=0, max_value=100, step=1),
- "CurrentHeight": st.column_config.NumberColumn("میانگین ارتفاع", disabled=True),
+ "مزرعه": st.column_config.TextColumn("مزرعه", disabled=True),
+ "ایستگاه 1": st.column_config.NumberColumn("ایستگاه 1", min_value=0, max_value=300, step=1),
+ "ایستگاه 2": st.column_config.NumberColumn("ایستگاه 2", min_value=0, max_value=300, step=1),
+ "ایستگاه 3": st.column_config.NumberColumn("ایستگاه 3", min_value=0, max_value=300, step=1),
+ "ایستگاه 4": st.column_config.NumberColumn("ایستگاه 4", min_value=0, max_value=300, step=1),
+ "ایستگاه 5": st.column_config.NumberColumn("ایستگاه 5", min_value=0, max_value=300, step=1),
+ "چاهک 1": st.column_config.NumberColumn("چاهک 1", min_value=0, max_value=300, step=1),
+ "چاهک 2": st.column_config.NumberColumn("چاهک 2", min_value=0, max_value=300, step=1),
+ "رطوبت غلاف": st.column_config.NumberColumn("رطوبت غلاف", min_value=0, max_value=100, step=1),
+ "نیتروژن": st.column_config.NumberColumn("نیتروژن", min_value=0, max_value=100, step=1),
+ "میانگین ارتفاع": st.column_config.NumberColumn("میانگین ارتفاع", disabled=True),
},
hide_index=True
)
+ # Calculate average height
for i in range(len(edited_df)):
stations = [
- edited_df.iloc[i]['Station1'],
- edited_df.iloc[i]['Station2'],
- edited_df.iloc[i]['Station3'],
- edited_df.iloc[i]['Station4'],
- edited_df.iloc[i]['Station5']
+ edited_df.iloc[i]['ایستگاه 1'],
+ edited_df.iloc[i]['ایستگاه 2'],
+ edited_df.iloc[i]['ایستگاه 3'],
+ edited_df.iloc[i]['ایستگاه 4'],
+ edited_df.iloc[i]['ایستگاه 5']
]
valid_stations = [s for s in stations if s > 0]
if valid_stations:
- edited_df.iloc[i, edited_df.columns.get_loc('CurrentHeight')] = round(sum(valid_stations) / len(valid_stations), 1)
+ edited_df.iloc[i, edited_df.columns.get_loc('میانگین ارتفاع')] = round(sum(valid_stations) / len(valid_stations), 1)
+ # Update session state
st.session_state[data_key] = edited_df
+ # Save button
if st.button("ذخیره اطلاعات", type="primary", use_container_width=True):
+ # This would normally save to a database
+ # For demo purposes, we'll just show a success message
+
+ # Add data to heights_df
new_data = edited_df.copy()
+ new_data['Farm_ID'] = new_data['مزرعه']
new_data['Week'] = int(selected_week)
new_data['Measurement_Date'] = (datetime.now() - timedelta(weeks=(22 - int(selected_week)))).strftime('%Y-%m-%d')
- new_data['Variety'] = new_data['Farm_ID'].map(farm_df.set_index('Farm_ID')['Variety'])
- new_data['Age'] = new_data['Farm_ID'].map(farm_df.set_index('Farm_ID')['Age'])
- new_data['Area'] = new_data['Farm_ID'].map(farm_df.set_index('Farm_ID')['Area'])
- new_data['Channel'] = new_data['Farm_ID'].map(farm_df.set_index('Farm_ID')['Channel'])
- new_data['Administration'] = new_data['Farm_ID'].map(farm_df.set_index('Farm_ID')['Administration'])
+ new_data['Height'] = new_data['میانگین ارتفاع']
+ new_data['Station1'] = new_data['ایستگاه 1']
+ new_data['Station2'] = new_data['ایستگاه 2']
+ new_data['Station3'] = new_data['ایستگاه 3']
+ new_data['Station4'] = new_data['ایستگاه 4']
+ new_data['Station5'] = new_data['ایستگاه 5']
+ new_data['Groundwater1'] = new_data['چاهک 1']
+ new_data['Groundwater2'] = new_data['چاهک 2']
+ new_data['Sheath_Moisture'] = new_data['رطوبت غلاف']
+ new_data['Nitrogen'] = new_data['نیتروژن']
+ # Merge with farm_df to get additional info
+ new_data = new_data.merge(
+ farm_df[['مزرعه', 'واریته', 'سن', 'مساحت', 'کانال', 'اداره']],
+ left_on='Farm_ID',
+ right_on='مزرعه',
+ how='left'
+ )
+
+ # Rename columns
+ new_data = new_data.rename(columns={
+ 'واریته': 'Variety',
+ 'سن': 'Age',
+ 'مساحت': 'Area',
+ 'کانال': 'Channel',
+ 'اداره': 'Administration'
+ })
+
+ # Add to heights_df
st.session_state.heights_df = pd.concat([st.session_state.heights_df, new_data], ignore_index=True)
+
+ # Show success message
st.success(f"دادههای هفته {selected_week} برای روز {selected_day} با موفقیت ذخیره شدند.")
st.balloons()
with tab2:
st.markdown("### آپلود فایل اکسل")
+ # Create a file uploader
uploaded_file = st.file_uploader("فایل اکسل خود را آپلود کنید", type=["xlsx", "xls", "csv"])
if uploaded_file is not None:
try:
+ # Read the file
if uploaded_file.name.endswith('.csv'):
df = pd.read_csv(uploaded_file)
else:
df = pd.read_excel(uploaded_file)
+
+ # Display the data
st.dataframe(df, use_container_width=True)
+ # Save button
if st.button("ذخیره فایل", type="primary"):
- st.session_state.heights_df = pd.concat([st.session_state.heights_df, df], ignore_index=True)
+ # This would normally save to a database
+ # For demo purposes, we'll just show a success message
st.success("فایل با موفقیت ذخیره شد.")
st.balloons()
except Exception as e:
st.error(f"خطا در خواندن فایل: {e}")
+ # Add instructions
st.markdown("### راهنمای فرمت فایل")
st.markdown("""
فایل اکسل باید شامل ستونهای زیر باشد:
- - Farm_ID
- - Station1 تا Station5
- - Well1 و Well2
- - CurrentMoisture
- - CurrentNitrogen
+ - مزرعه
+ - ایستگاه 1 تا 5
+ - چاهک 1 و 2
+ - رطوبت غلاف
+ - نیتروژن
میتوانید از [این فایل نمونه](https://example.com/sample.xlsx) به عنوان الگو استفاده کنید.
""")
+ # Add a drag and drop area
st.markdown("""
@@ -1185,6 +1444,7 @@ elif selected == "ورود اطلاعات":
elif selected == "تحلیل دادهها":
st.markdown("## تحلیل هوشمند دادهها")
+ # Add a lottie animation
col1, col2 = st.columns([1, 2])
with col1:
@@ -1198,17 +1458,19 @@ elif selected == "تحلیل دادهها":
""", unsafe_allow_html=True)
+ # Create tabs for different analyses
tab1, tab2, tab3, tab4 = st.tabs(["تحلیل رشد", "مقایسه واریتهها", "تحلیل رطوبت", "پیشبینی"])
with tab1:
st.markdown("### تحلیل رشد مزارع")
+ # Create filters
col1, col2 = st.columns(2)
with col1:
selected_variety = st.selectbox(
"انتخاب واریته",
- ["all"] + list(farm_df['Variety'].unique()),
+ ["all"] + list(farm_df['واریته'].unique()),
format_func=lambda x: "همه واریتهها" if x == "all" else x,
key="growth_variety"
)
@@ -1216,14 +1478,17 @@ elif selected == "تحلیل دادهها":
with col2:
selected_age = st.selectbox(
"انتخاب سن",
- ["all"] + list(farm_df['Age'].unique()),
+ ["all"] + list(farm_df['سن'].unique()),
format_func=lambda x: "همه سنین" if x == "all" else x,
key="growth_age"
)
- growth_data = generate_real_growth_data(selected_variety, selected_age)
+ # Generate mock growth data
+ growth_data = generate_mock_growth_data(farm_df, selected_variety, selected_age)
+ # Create a growth chart
if growth_data['individual']:
+ # Prepare data for chart
chart_data = []
for farm_data in growth_data['individual']:
for i, week in enumerate(farm_data['weeks']):
@@ -1237,6 +1502,7 @@ elif selected == "تحلیل دادهها":
chart_df = pd.DataFrame(chart_data)
+ # Create a line chart with Altair
chart = alt.Chart(chart_df).mark_line(point=True).encode(
x=alt.X('Week:Q', title='هفته'),
y=alt.Y('Height:Q', title='ارتفاع (سانتیمتر)'),
@@ -1250,24 +1516,26 @@ elif selected == "تحلیل دادهها":
st.altair_chart(chart, use_container_width=True)
+ # Add a growth rate analysis
st.markdown("### تحلیل نرخ رشد")
+ # Calculate growth rates
growth_rates = []
for farm_data in growth_data['individual']:
heights = farm_data['heights']
for i in range(1, len(heights)):
- if heights[i] > 0 and heights[i-1] > 0:
- growth_rate = heights[i] - heights[i-1]
- growth_rates.append({
- 'Farm': farm_data['farm_id'],
- 'Week': farm_data['weeks'][i],
- 'Growth Rate': growth_rate,
- 'Variety': farm_data['variety'],
- 'Age': farm_data['age']
- })
+ growth_rate = heights[i] - heights[i-1]
+ growth_rates.append({
+ 'Farm': farm_data['farm_id'],
+ 'Week': farm_data['weeks'][i],
+ 'Growth Rate': growth_rate,
+ 'Variety': farm_data['variety'],
+ 'Age': farm_data['age']
+ })
growth_rate_df = pd.DataFrame(growth_rates)
+ # Create a bar chart for growth rates
chart = alt.Chart(growth_rate_df).mark_bar().encode(
x=alt.X('Week:O', title='هفته'),
y=alt.Y('mean(Growth Rate):Q', title='نرخ رشد (سانتیمتر در هفته)'),
@@ -1286,34 +1554,45 @@ elif selected == "تحلیل دادهها":
with tab2:
st.markdown("### مقایسه واریتهها")
- variety_age_groups = farm_df.groupby(['Variety', 'Age']).size().reset_index(name='Count')
+ # Group farms by variety and age
+ variety_age_groups = farm_df.groupby(['واریته', 'سن']).size().reset_index(name='تعداد')
+ # Create a heatmap
fig = px.density_heatmap(
variety_age_groups,
- x='Variety',
- y='Age',
- z='Count',
+ x='واریته',
+ y='سن',
+ z='تعداد',
title='توزیع مزارع بر اساس واریته و سن',
color_continuous_scale='Viridis'
)
+
fig.update_layout(
font=dict(family="Vazirmatn"),
template="plotly_white",
xaxis_title="واریته",
yaxis_title="سن"
)
+
st.plotly_chart(fig, use_container_width=True)
- variety_heights = farm_df.groupby('Variety')['CurrentHeight'].apply(list).to_dict()
+ # Generate mock variety comparison data
+ varieties = farm_df['واریته'].unique()
+ # Generate random heights for each variety
+ variety_heights = {variety: np.random.normal(150, 20, 100) for variety in varieties}
+
+ # Create a box plot
fig = go.Figure()
- for variety, heights in variety_heights.items():
+
+ for variety in varieties:
fig.add_trace(go.Box(
- y=heights,
+ y=variety_heights[variety],
name=variety,
boxpoints='outliers',
marker_color=f'hsl({hash(variety) % 360}, 70%, 50%)'
))
+
fig.update_layout(
title='مقایسه ارتفاع بر اساس واریته',
yaxis_title='ارتفاع (سانتیمتر)',
@@ -1321,10 +1600,16 @@ elif selected == "تحلیل دادهها":
template="plotly_white",
boxmode='group'
)
+
st.plotly_chart(fig, use_container_width=True)
+ # Add a statistical comparison
+ st.markdown("### مقایسه آماری واریتهها")
+
+ # Calculate statistics for each variety
variety_stats = {}
- for variety, heights in variety_heights.items():
+ for variety in varieties:
+ heights = variety_heights[variety]
variety_stats[variety] = {
'میانگین': np.mean(heights),
'میانه': np.median(heights),
@@ -1332,22 +1617,26 @@ elif selected == "تحلیل دادهها":
'حداقل': np.min(heights),
'حداکثر': np.max(heights)
}
+
+ # Create a dataframe
variety_stats_df = pd.DataFrame(variety_stats).T
+
+ # Display the statistics
st.dataframe(variety_stats_df, use_container_width=True)
with tab3:
st.markdown("### تحلیل رطوبت مزارع")
- farms = farm_df['Farm_ID'].unique()[:10]
+ # Generate mock moisture data
+ farms = farm_df['مزرعه'].unique()[:10] # Get 10 farms
dates = pd.date_range(end=datetime.now(), periods=30, freq='D')
moisture_data = []
for farm in farms:
- farm_data = farm_df[farm_df['Farm_ID'] == farm]
+ base_moisture = np.random.uniform(50, 80)
for date in dates:
- week_data = farm_data[farm_data['Week'] == (date.isocalendar()[1] % 23 + 1)]
- moisture = week_data['CurrentMoisture'].mean() if not week_data.empty else np.random.uniform(50, 80)
- moisture = max(0, min(100, moisture))
+ moisture = base_moisture + np.random.normal(0, 5)
+ moisture = max(0, min(100, moisture)) # Clip to 0-100
moisture_data.append({
'Farm': farm,
'Date': date,
@@ -1356,6 +1645,7 @@ elif selected == "تحلیل دادهها":
moisture_df = pd.DataFrame(moisture_data)
+ # Create a line chart
fig = px.line(
moisture_df,
x='Date',
@@ -1364,27 +1654,34 @@ elif selected == "تحلیل دادهها":
title='روند رطوبت مزارع در 30 روز گذشته',
labels={'Date': 'تاریخ', 'Moisture': 'رطوبت (%)', 'Farm': 'مزرعه'}
)
+
fig.update_layout(
font=dict(family="Vazirmatn"),
template="plotly_white",
hovermode="x unified"
)
+
st.plotly_chart(fig, use_container_width=True)
+ # Add a correlation analysis
st.markdown("### همبستگی رطوبت و ارتفاع")
+ # Generate mock correlation data
correlation_data = []
for farm in farms:
- farm_data = farm_df[farm_df['Farm_ID'] == farm]
- for _, row in farm_data.iterrows():
+ for _ in range(20): # 20 data points per farm
+ moisture = np.random.uniform(40, 90)
+ # Height is correlated with moisture with some noise
+ height = 100 + moisture * 1.5 + np.random.normal(0, 20)
correlation_data.append({
'Farm': farm,
- 'Moisture': row['CurrentMoisture'],
- 'Height': row['CurrentHeight']
+ 'Moisture': moisture,
+ 'Height': height
})
correlation_df = pd.DataFrame(correlation_data)
+ # Create a scatter plot
fig = px.scatter(
correlation_df,
x='Moisture',
@@ -1394,167 +1691,770 @@ elif selected == "تحلیل دادهها":
labels={'Moisture': 'رطوبت (%)', 'Height': 'ارتفاع (سانتیمتر)', 'Farm': 'مزرعه'},
trendline='ols'
)
+
fig.update_layout(
font=dict(family="Vazirmatn"),
template="plotly_white"
)
+
st.plotly_chart(fig, use_container_width=True)
+ # Calculate correlation coefficient
correlation = correlation_df['Moisture'].corr(correlation_df['Height'])
+
st.info(f"ضریب همبستگی بین رطوبت و ارتفاع: {correlation:.2f}")
with tab4:
st.markdown("### پیشبینی رشد مزارع")
+ # Create a farm selector
selected_farm_for_prediction = st.selectbox(
"انتخاب مزرعه",
- options=farm_df['Farm_ID'].tolist(),
+ options=farm_df['مزرعه'].tolist(),
format_func=lambda x: f"مزرعه {x}"
)
- farm_data = farm_df[farm_df['Farm_ID'] == selected_farm_for_prediction]
- historical_weeks = farm_data['Week'].values
- historical_heights = farm_data['CurrentHeight'].values
+ # Generate mock historical data
+ weeks = list(range(1, 16)) # Historical data for weeks 1-15
+ heights = [50 + i * 10 + np.random.normal(0, 5) for i in range(len(weeks))]
- if len(historical_weeks) > 1 and len(historical_heights) > 1:
- model = LinearRegression()
- model.fit(historical_weeks.reshape(-1, 1), historical_heights)
-
- future_weeks = np.array(range(max(historical_weeks) + 1, 30)).reshape(-1, 1)
- future_heights = model.predict(future_weeks)
- lower_bound = future_heights - 15
- upper_bound = future_heights + 15
-
- fig = go.Figure()
- fig.add_trace(go.Scatter(
- x=historical_weeks,
- y=historical_heights,
- mode='lines+markers',
- name='دادههای تاریخی',
- line=dict(color='#1a8754', width=3),
- marker=dict(size=8, color='#1a8754')
- ))
- fig.add_trace(go.Scatter(
- x=future_weeks.flatten(),
- y=future_heights,
- mode='lines',
- name='پیشبینی',
- line=dict(color='#1976d2f', width=3, dash='dash')
- ))
- fig.add_trace(go.Scatter(
- x=future_weeks.flatten(),
- y=lower_bound,
- mode='lines',
- name='حد پایین',
- line=dict(color='#d32f2f', width=1, dash='dot'),
- showlegend=True
- ))
- fig.add_trace(go.Scatter(
- x=future_weeks.flatten(),
- y=upper_bound,
- mode='lines',
- name='حد بالا',
- line=dict(color='#d32f2f', width=1, dash='dot'),
- fill='tonexty',
- showlegend=True
- ))
- fig.update_layout(
- title=f'پیشبینی رشد مزرعه {selected_farm_for_prediction}',
- xaxis_title='هفته',
- yaxis_title='ارتفاع (سانتیمت��)',
- font=dict(family='Vazirmatn', size=14),
- hovermode='x unified',
- template='plotly_white',
- height=500
+ # Create a dataframe
+ historical_df = pd.DataFrame({
+ 'Week': weeks,
+ 'Height': heights
+ })
+
+ # Predict future weeks (16-22)
+ future_weeks = list(range(16, 23))
+
+ # Linear regression for prediction
+ from sklearn.linear_model import LinearRegression
+
+ model = LinearRegression()
+ model.fit(np.array(weeks).reshape(-1, 1), heights)
+
+ future_heights = model.predict(np.array(future_weeks).reshape(-1, 1))
+
+ # Add prediction intervals
+ lower_bound = future_heights - 15
+ upper_bound = future_heights + 15
+
+ # Create a dataframe for future predictions
+ future_df = pd.DataFrame({
+ 'Week': future_weeks,
+ 'Height': future_heights,
+ 'Lower': lower_bound,
+ 'Upper': upper_bound
+ })
+
+ # Create a combined chart
+ fig = go.Figure()
+
+ # Historical data
+ fig.add_trace(go.Scatter(
+ x=historical_df['Week'],
+ y=historical_df['Height'],
+ mode='lines+markers',
+ name='دادههای تاریخی',
+ line=dict(color='#1a8754', width=3),
+ marker=dict(size=8, color='#1a8754')
+ ))
+
+ # Predicted data
+ fig.add_trace(go.Scatter(
+ x=future_df['Week'],
+ y=future_df['Height'],
+ mode='lines+markers',
+ name='پیشبینی',
+ line=dict(color='#ff9800', width=3, dash='dash'),
+ marker=dict(size=8, color='#ff9800')
+ ))
+
+ # Prediction interval
+ fig.add_trace(go.Scatter(
+ x=future_df['Week'].tolist() + future_df['Week'].tolist()[::-1],
+ y=future_df['Upper'].tolist() + future_df['Lower'].tolist()[::-1],
+ fill='toself',
+ fillcolor='rgba(255, 152, 0, 0.2)',
+ line=dict(color='rgba(255, 152, 0, 0)'),
+ hoverinfo='skip',
+ showlegend=False
+ ))
+
+ fig.update_layout(
+ title=f'پیشبینی رشد مزرعه {selected_farm_for_prediction}',
+ xaxis_title='هفته',
+ yaxis_title='ارتفاع (سانتیمتر)',
+ font=dict(family='Vazirmatn', size=14),
+ hovermode='x unified',
+ template='plotly_white',
+ height=500,
+ legend=dict(
+ orientation="h",
+ yanchor="bottom",
+ y=1.02,
+ xanchor="right",
+ x=1
)
- st.plotly_chart(fig, use_container_width=True)
- else:
- st.warning("دادههای کافی برای پیشبینی وجود ندارد.")
-
-# Report Generation Page
-elif selected == "گزارشگیری":
- st.markdown("## گزارشگیری")
-
- report_week = st.selectbox("انتخاب هفته برای گزارش", options=[str(i) for i in range(1, 23)])
- report_day = st.selectbox("انتخاب روز برای گزارش", options=day_df['Day'].unique().tolist())
-
- report_df = st.session_state.heights_df[
- (st.session_state.heights_df['Week'] == int(report_week)) &
- (st.session_state.heights_df['Farm_ID'].isin(day_df[day_df['Day'] == report_day]['Farm_ID']))
- ]
-
- if not report_df.empty:
- st.markdown(f"### گزارش هفته {report_week} - روز {report_day}")
- st.dataframe(report_df, use_container_width=True)
-
- csv = report_df.to_csv(index=False).encode('utf-8')
- st.download_button(
- label="دانلود گزارش (CSV)",
- data=csv,
- file_name=f"report_week_{report_week}_day_{report_day}.csv",
- mime="text/csv",
)
- st_lottie(lottie_report, height=200, key="report_animation")
- else:
- st.warning(f"دادهای برای هفته {report_week} و روز {report_day} یافت نشد.")
+ # Add vertical line to separate historical and predicted data
+ fig.add_vline(x=15.5, line_width=1, line_dash="dash", line_color="gray")
+
+ st.plotly_chart(fig, use_container_width=True)
+
+ # Add prediction details
+ st.markdown("### جزئیات پیشبینی")
+
+ col1, col2 = st.columns(2)
+
+ with col1:
+ st.metric(
+ label="ارتفاع فعلی",
+ value=f"{heights[-1]:.1f} cm",
+ delta=f"{heights[-1] - heights[-2]:.1f} cm"
+ )
+
+ with col2:
+ st.metric(
+ label="ارتفاع پیشبینی شده (هفته 22)",
+ value=f"{future_heights[-1]:.1f} cm",
+ delta=f"{future_heights[-1] - heights[-1]:.1f} cm"
+ )
+
+ # Add a prediction table
+ prediction_table = pd.DataFrame({
+ 'هفته': future_weeks,
+ 'ارتفاع پیشبینی شده': [f"{h:.1f}" for h in future_heights],
+ 'حد پایین': [f"{l:.1f}" for l in lower_bound],
+ 'حد بالا': [f"{u:.1f}" for u in upper_bound]
+ })
+
+ st.dataframe(prediction_table, use_container_width=True, hide_index=True)
+
+ # Add factors affecting growth
+ st.markdown("### عوامل مؤثر بر رشد")
+
+ # Create a radar chart for factors
+ factors = ['رطوبت', 'نیتروژن', 'دما', 'آبیاری', 'نور']
+ factor_values = [85, 70, 60, 90, 75]
+
+ fig = go.Figure()
+
+ fig.add_trace(go.Scatterpolar(
+ r=factor_values,
+ theta=factors,
+ fill='toself',
+ name='عوامل مؤثر',
+ line_color='#1a8754'
+ ))
+
+ fig.update_layout(
+ polar=dict(
+ radialaxis=dict(
+ visible=True,
+ range=[0, 100]
+ )
+ ),
+ showlegend=False,
+ font=dict(family='Vazirmatn'),
+ height=400
+ )
+
+ st.plotly_chart(fig, use_container_width=True)
-# Settings Page
-elif selected == "تنظیمات":
- st.markdown("## تنظیمات سامانه")
+# Reporting Page
+elif selected == "گزارشگیری":
+ st.markdown("## گزارشگیری پیشرفته")
+
+ # Add a lottie animation
+ col1, col2 = st.columns([1, 2])
+
+ with col1:
+ st_lottie(lottie_report, height=200, key="report_animation")
- st.markdown("""
-
-
تنظیمات پیشرفته
-
در این بخش میتوانید تنظیمات کلی سامانه، از جمله بهروزرسانی دادهها و پیکربندیهای پیشرفته را مدیریت کنید.
-
- """, unsafe_allow_html=True)
+ with col2:
+ st.markdown("""
+
+
گزارشگیری پیشرفته
+
در این بخش میتوانید گزارشهای مختلف از وضعیت مزارع تهیه کنید و آنها را به صورت PDF یا Excel دانلود کنید.
+
+ """, unsafe_allow_html=True)
- st.markdown("### بهروزرسانی دادهها")
+ # Create date range selector
+ col1, col2 = st.columns(2)
- if st.button("بارگذاری مجدد دادهها", type="primary", use_container_width=True):
- st.session_state.heights_df = load_farm_data()
- st.success("دادهها با موفقیت بهروزرسانی شدند.")
+ with col1:
+ start_date = st.date_input(
+ "تاریخ شروع",
+ value=datetime.now() - timedelta(days=30),
+ format="YYYY-MM-DD"
+ )
- st.markdown("### تنظیمات ظاهری")
+ with col2:
+ end_date = st.date_input(
+ "تاریخ پایان",
+ value=datetime.now(),
+ format="YYYY-MM-DD"
+ )
- theme = st.radio(
- "انتخاب تم",
- options=["سبز (پیشفرض)", "آبی", "سفید"],
- format_func=lambda x: x
+ # Create report type selector
+ report_type = st.selectbox(
+ "نوع گزارش",
+ options=["گزارش کلی", "گزارش رشد", "گزارش رطوبت", "گزارش مقایسهای واریتهها"]
)
- if theme == "آبی":
- st.markdown("""
-
- """, unsafe_allow_html=True)
- elif theme == "سفید":
- st.markdown("""
-
- """, unsafe_allow_html=True)
+ # Generate report button
+ if st.button("تولید گزارش", type="primary", use_container_width=True):
+ with st.spinner('در حال تولید گزارش...'):
+ time.sleep(2) # Simulate report generation
+
+ # Display report based on type
+ if report_type == "گزارش کلی":
+ st.markdown("### گزارش کلی وضعیت مزارع")
+
+ # Summary metrics
+ col1, col2, col3, col4 = st.columns(4)
+
+ with col1:
+ st.metric("تعداد کل مزارع", len(farm_df))
+
+ with col2:
+ st.metric("میانگین ارتفاع", f"{np.random.uniform(150, 200):.1f} cm")
+
+ with col3:
+ st.metric("میانگین رطوبت", f"{np.random.uniform(60, 80):.1f}%")
+
+ with col4:
+ st.metric("میانگین نیتروژن", f"{np.random.uniform(40, 60):.1f}%")
+
+ # Farm distribution chart
+ farm_counts = farm_df['اداره'].value_counts()
+ fig = px.pie(
+ values=farm_counts.values,
+ names=farm_counts.index,
+ title='توزیع مزارع بر اساس اداره',
+ color_discrete_sequence=px.colors.sequential.Greens_r
+ )
+ fig.update_traces(textposition='inside', textinfo='percent+label')
+ fig.update_layout(font=dict(family="Vazirmatn"))
+ st.plotly_chart(fig, use_container_width=True)
+
+ # Growth trend
+ weeks = list(range(1, 23))
+ heights = [100 + i * 5 + np.random.normal(0, 10) for i in range(len(weeks))]
+
+ fig = px.line(
+ x=weeks,
+ y=heights,
+ title='روند رشد کلی مزارع',
+ labels={'x': 'هفته', 'y': 'ارتفاع (سانتیمتر)'}
+ )
+ fig.update_layout(font=dict(family="Vazirmatn"))
+ st.plotly_chart(fig, use_container_width=True)
+
+ # Top 5 farms table
+ top_farms = pd.DataFrame({
+ 'مزرعه': ['مزرعه ' + str(i) for i in range(1, 6)],
+ 'ارتفاع': [round(np.random.uniform(180, 220), 1) for _ in range(5)],
+ 'رطوبت': [round(np.random.uniform(60, 80), 1) for _ in range(5)],
+ 'نیتروژن': [round(np.random.uniform(40, 60), 1) for _ in range(5)]
+ })
+
+ st.markdown("### 5 مزرعه برتر")
+ st.dataframe(top_farms, use_container_width=True, hide_index=True)
+
+ elif report_type == "گزارش رشد":
+ st.markdown("### گزارش رشد مزارع")
+
+ # Growth metrics
+ col1, col2, col3 = st.columns(3)
+
+ with col1:
+ st.metric("میانگین رشد هفتگی", f"{np.random.uniform(10, 15):.1f} cm")
+
+ with col2:
+ st.metric("حداکثر رشد هفتگی", f"{np.random.uniform(20, 25):.1f} cm")
+
+ with col3:
+ st.metric("حداقل رشد هفتگی", f"{np.random.uniform(5, 10):.1f} cm")
+
+ # Growth trend for multiple farms
+ weeks = list(range(1, 23))
+ farms = ['مزرعه 1', 'مزرعه 2', 'مزرعه 3', 'مزرعه 4', 'مزرعه 5']
+
+ fig = go.Figure()
+
+ for farm in farms:
+ heights = [100 + i * 5 + np.random.normal(0, 10) for i in range(len(weeks))]
+ fig.add_trace(go.Scatter(
+ x=weeks,
+ y=heights,
+ mode='lines+markers',
+ name=farm
+ ))
+
+ fig.update_layout(
+ title='روند رشد مزارع',
+ xaxis_title='هفته',
+ yaxis_title='ارتفاع (سانتیمتر)',
+ font=dict(family="Vazirmatn"),
+ legend_title='مزرعه',
+ hovermode="x unified"
+ )
+
+ st.plotly_chart(fig, use_container_width=True)
+
+ # Growth rate distribution
+ growth_rates = np.random.normal(12, 3, 1000)
+
+ fig = px.histogram(
+ x=growth_rates,
+ nbins=30,
+ title='توزیع نرخ رشد هفتگی',
+ labels={'x': 'نرخ رشد (سانتیمتر در هفته)', 'y': 'فراوانی'},
+ color_discrete_sequence=['#1a8754']
+ )
+ fig.update_layout(font=dict(family="Vazirmatn"))
+ st.plotly_chart(fig, use_container_width=True)
+
+ # Factors affecting growth
+ st.markdown("### عوامل مؤثر بر رشد")
+
+ factors = ['رطوبت', 'نیتروژن', 'دما', 'آبیاری', 'نور']
+ correlations = [0.8, 0.7, 0.5, 0.9, 0.6]
+
+ fig = px.bar(
+ x=factors,
+ y=correlations,
+ title='همبستگی عوامل مختلف با نرخ رشد',
+ labels={'x': 'عامل', 'y': 'ضریب همبستگی'},
+ color=correlations,
+ color_continuous_scale='Viridis'
+ )
+ fig.update_layout(font=dict(family="Vazirmatn"))
+ st.plotly_chart(fig, use_container_width=True)
+
+ elif report_type == "گزارش رطوبت":
+ st.markdown("### گزارش رطوبت مزارع")
+
+ # Moisture metrics
+ col1, col2, col3 = st.columns(3)
+
+ with col1:
+ st.metric("میانگین رطوبت", f"{np.random.uniform(60, 70):.1f}%")
+
+ with col2:
+ st.metric("حداکثر رطوبت", f"{np.random.uniform(80, 90):.1f}%")
+
+ with col3:
+ st.metric("حداقل رطوبت", f"{np.random.uniform(40, 50):.1f}%")
+
+ # Moisture trend
+ dates = pd.date_range(start=start_date, end=end_date)
+ moisture_levels = [np.random.uniform(50, 80) for _ in range(len(dates))]
+
+ fig = px.line(
+ x=dates,
+ y=moisture_levels,
+ title='روند رطوبت مزارع',
+ labels={'x': 'تاریخ', 'y': 'رطوبت (%)'}
+ )
+ fig.update_layout(font=dict(family="Vazirmatn"))
+ st.plotly_chart(fig, use_container_width=True)
+
+ # Moisture distribution
+ fig = px.histogram(
+ x=moisture_levels,
+ nbins=30,
+ title='توزیع رطوبت مزارع',
+ labels={'x': 'رطوبت (%)', 'y': 'فراوانی'},
+ color_discrete_sequence=['#1a8754']
+ )
+ fig.update_layout(font=dict(family="Vazirmatn"))
+ st.plotly_chart(fig, use_container_width=True)
+
+ # Moisture vs Growth scatter plot
+ growth_levels = [h + np.random.normal(0, 10) for h in moisture_levels]
+
+ fig = px.scatter(
+ x=moisture_levels,
+ y=growth_levels,
+ title='رابطه بین رطوبت و رشد',
+ labels={'x': 'رطوبت (%)', 'y': 'رشد (سانتیمتر)'},
+ trendline='ols'
+ )
+ fig.update_layout(font=dict(family="Vazirmatn"))
+ st.plotly_chart(fig, use_container_width=True)
+
+ # Moisture recommendations
+ st.markdown("### توصیههای مدیریت رطوبت")
+
+ recommendations = [
+ "افزایش دفعات آبیاری در مزارع با رطوبت پایین",
+ "بهبود سیستم زهکشی در مزارع با رطوبت بالا",
+ "استفاده از مالچ برای حفظ رطوبت خاک",
+ "تنظیم زمان آبیاری بر اساس شرایط آب و هوایی",
+ "پایش مداوم رطوبت خاک با استفاده از سنسورها"
+ ]
+
+ for rec in recommendations:
+ st.markdown(f"- {rec}")
+
+ elif report_type == "گزارش مقایسهای واریتهها":
+ st.markdown("### گزارش مقایسهای واریتههای نیشکر")
+
+ # Generate mock data for varieties
+ varieties = ['CP57-614', 'CP69-1062', 'CP73-21', 'SP70-1143', 'IRC99-02']
+ heights = [np.random.uniform(180, 220) for _ in varieties]
+ sugar_contents = [np.random.uniform(12, 16) for _ in varieties]
+ growth_rates = [np.random.uniform(10, 15) for _ in varieties]
+
+ # Variety comparison chart
+ fig = go.Figure(data=[
+ go.Bar(name='ارتفاع (cm)', x=varieties, y=heights),
+ go.Bar(name='محتوای قند (%)', x=varieties, y=sugar_contents),
+ go.Bar(name='رشد (cm/هفته)', x=varieties, y=growth_rates)
+ ])
+
+ fig.update_layout(
+ title='مقایسه واریتههای نیشکر',
+ xaxis_title='واریته',
+ yaxis_title='مقدار',
+ barmode='group',
+ font=dict(family="Vazirmatn")
+ )
+
+ st.plotly_chart(fig, use_container_width=True)
+
+ # Variety performance table
+ variety_data = pd.DataFrame({
+ 'واریته': varieties,
+ 'ارتفاع (cm)': [round(h, 1) for h in heights],
+ 'محتوای قند (%)': [round(s, 1) for s in sugar_contents],
+ ' رشد(cm/هفته)': [round(g, 1) for g in growth_rates],
+ 'مقاومت به آفات': [np.random.choice(['کم', 'متوسط', 'زیاد']) for _ in varieties],
+ 'نیاز آبی': [np.random.choice(['کم', 'متوسط', 'زیاد']) for _ in varieties]
+ })
+
+ st.dataframe(variety_data, use_container_width=True, hide_index=True)
+
+ # Radar chart for variety comparison
+ categories = ['ارتفاع', 'محتوای قند', 'رشد', 'مقاومت به آفات', 'بهرهوری آب']
+
+ fig = go.Figure()
+
+ for variety in varieties:
+ values = [
+ heights[varieties.index(variety)] / max(heights) * 100,
+ sugar_contents[varieties.index(variety)] / max(sugar_contents) * 100,
+ growth_rates[varieties.index(variety)] / max(growth_rates) * 100,
+ np.random.uniform(60, 100),
+ np.random.uniform(60, 100)
+ ]
+
+ fig.add_trace(go.Scatterpolar(
+ r=values,
+ theta=categories,
+ fill='toself',
+ name=variety
+ ))
+
+ fig.update_layout(
+ polar=dict(
+ radialaxis=dict(
+ visible=True,
+ range=[0, 100]
+ )
+ ),
+ title='مقایسه واریتهها',
+ font=dict(family="Vazirmatn"),
+ showlegend=True
+ )
+
+ st.plotly_chart(fig, use_container_width=True)
+
+ # Variety recommendations
+ st.markdown("### توصیههای کشت واریتهها")
+
+ recommendations = [
+ f"واریته {np.random.choice(varieties)} برای مناطق با آب و هوای گرم و مرطوب مناسبتر است.",
+ f"برای افزایش عملکرد تولید شکر، کشت واریته {np.random.choice(varieties)} توصیه میشود.",
+ f"در مناطق با محدودیت آب، استفاده از واریته {np.random.choice(varieties)} به دلیل نیاز آبی کمتر مناسب است.",
+ f"برای مقاومت بهتر در برابر آفات، واریته {np.random.choice(varieties)} پیشنهاد میشود.",
+ "تنوع در کشت واریتهها میتواند به کاهش ریسکهای مرتبط با آفات و بیماریها کمک کند."
+ ]
+
+ for rec in recommendations:
+ st.markdown(f"- {rec}")
+
+ # Add download buttons
+ col1, col2 = st.columns(2)
+
+ with col1:
+ st.download_button(
+ label="دانلود گزارش (PDF)",
+ data=b"This is a mock PDF report", # This would be the actual PDF content
+ file_name="farm_report.pdf",
+ mime="application/pdf",
+ )
+
+ with col2:
+ st.download_button(
+ label="دانلود دادهها (Excel)",
+ data=b"This is a mock Excel file", # This would be the actual Excel content
+ file_name="farm_data.xlsx",
+ mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
+ )
+
+# Settings Page
+elif selected == "تنظیمات":
+ st.markdown("## تنظیمات سیستم")
- st.markdown("### اطلاعات تماس")
- st.markdown("""
-
-
برای پشتیبانی یا مشکلات فنی، با ما تماس بگیرید:
-
ایمیل: support@dehkhoda.com
-
تلفن: +98 21 12345678
-
- """, unsafe_allow_html=True)
+ # Create tabs for different settings
+ tab1, tab2, tab3, tab4 = st.tabs(["تنظیما�� کاربری", "تنظیمات سیستم", "مدیریت دادهها", "پشتیبانگیری"])
+
+ with tab1:
+ st.markdown("### تنظیمات کاربری")
+
+ # User profile
+ st.markdown("#### پروفایل کاربری")
+
+ col1, col2 = st.columns(2)
+
+ with col1:
+ user_name = st.text_input("نام کاربری", value="کاربر نمونه")
+
+ with col2:
+ user_email = st.text_input("ایمیل", value="user@example.com")
+
+ user_role = st.selectbox(
+ "نقش کاربری",
+ options=["مدیریت مطالعات", "پرسنل", "اپراتور"],
+ index=1
+ )
+
+ # Password change
+ st.markdown("#### تغییر رمز عبور")
+
+ col1, col2 = st.columns(2)
+
+ with col1:
+ current_password = st.text_input("رمز عبور فعلی", type="password")
+
+ with col2:
+ new_password = st.text_input("رمز عبور جدید", type="password")
+
+ confirm_password = st.text_input("تکرار رمز عبور جدید", type="password")
+
+ if st.button("تغییر رمز عبور", type="primary"):
+ # This would normally check the current password and update with the new one
+ st.success("رمز عبور با موفقیت تغییر کرد.")
+
+ # Notification settings
+ st.markdown("#### تنظیمات اعلانها")
+
+ email_notifications = st.checkbox("دریافت اعلانها از طریق ایمیل", value=True)
+ sms_notifications = st.checkbox("دریافت اعلانها از طریق پیامک", value=False)
+
+ notification_frequency = st.radio(
+ "تناوب دریافت اعلانها",
+ options=["روزانه", "هفتگی", "ماهانه"],
+ index=1
+ )
+
+ with tab2:
+ st.markdown("### تنظیمات سیستم")
+
+ # System language
+ system_language = st.selectbox(
+ "زبان سیستم",
+ options=["فارسی", "English", "العربية"],
+ index=0
+ )
+
+ # Date format
+ date_format = st.selectbox(
+ "فرمت تاریخ",
+ options=["YYYY/MM/DD", "DD/MM/YYYY", "MM/DD/YYYY"],
+ index=0
+ )
+
+ # Theme settings
+ st.markdown("#### تنظیمات ظاهری")
+
+ theme = st.radio(
+ "تم",
+ options=["روشن", "تیره", "سیستم"],
+ index=2
+ )
+
+ primary_color = st.color_picker("رنگ اصلی", value="#1a8754")
+
+ # Map settings
+ st.markdown("#### تنظیمات نقشه")
+
+ default_map_view = st.selectbox(
+ "نمای پیشفرض نقشه",
+ options=["نقشه", "ماهواره", "ترکیبی"],
+ index=0
+ )
+
+ default_map_layer = st.selectbox(
+ "لایه پیشفرض نقشه",
+ options=["NDVI", "NDMI", "EVI", "NDWI"],
+ index=0
+ )
+
+ # AI model settings
+ st.markdown("#### تنظیمات مدل هوش مصنوعی")
+
+ ai_model = st.selectbox(
+ "مدل هوش مصنوعی",
+ options=["GPT-3", "GPT-4", "BERT"],
+ index=1
+ )
+
+ model_update_frequency = st.selectbox(
+ "تناوب بهروزرسانی مدل",
+ options=["روزانه", "هفتگی", "ماهانه"],
+ index=1
+ )
+
+ # Save settings button
+ if st.button("ذخیره تنظیمات", type="primary"):
+ st.success("تنظیمات با موفقیت ذخیره شدند.")
+
+ with tab3:
+ st.markdown("### مدیریت دادهها")
+
+ # Data import
+ st.markdown("#### ورود داده")
+
+ uploaded_file = st.file_uploader("آپلود فایل داده", type=["csv", "xlsx"])
+
+ if uploaded_file is not None:
+ st.success(f"فایل {uploaded_file.name} با موفقیت آپلود شد.")
+
+ if st.button("وارد کردن دادهها"):
+ # This would normally process and import the data
+ st.info("در حال پردازش و وارد کردن دادهها...")
+ time.sleep(2)
+ st.success("دادهها با موفقیت وارد شدند.")
+
+ # Data export
+ st.markdown("#### خروجی داده")
+
+ export_format = st.selectbox(
+ "فرمت خروجی",
+ options=["CSV", "Excel", "JSON"],
+ index=1
+ )
+
+ if st.button("دریافت خروجی"):
+ # This would normally generate and provide the export file
+ st.info("در حال آمادهسازی فایل خروجی...")
+ time.sleep(2)
+ st.success("فایل خروجی آماده دانلود است.")
+ st.download_button(
+ label="دانلود فایل خروجی",
+ data=b"This is a mock export file", # This would be the actual file content
+ file_name=f"farm_data_export.{export_format.lower()}",
+ mime="application/octet-stream",
+ )
+
+ # Data cleanup
+ st.markdown("#### پاکسازی دادهها")
+
+ cleanup_options = st.multiselect(
+ "گزینههای پاکسازی",
+ options=["حذف دادههای تکراری", "حذف دادههای ناقص", "نرمالسازی دادهها"],
+ default=["حذف دادههای تکراری"]
+ )
+
+ if st.button("اجرای پاکسازی"):
+ # This would normally perform the selected cleanup operations
+ st.info("در حال اجرای عملیات پاکسازی...")
+ time.sleep(2)
+ st.success("عملیات پاکسازی با موفقیت انجام شد.")
+
+ # Data visualization settings
+ st.markdown("#### تنظیمات نمایش داده")
+
+ chart_theme = st.selectbox(
+ "تم نمودارها",
+ options=["پیشفرض", "روشن", "تیره", "رنگی"],
+ index=0
+ )
+
+ show_data_labels = st.checkbox("نمایش برچسبهای داده", value=True)
+
+ if st.button("اعمال تنظیمات نمایش"):
+ st.success("تنظیمات نمایش داده با موفقیت اعمال شدند.")
+
+ with tab4:
+ st.markdown("### پشتیبانگیری و بازیابی")
+
+ # Backup creation
+ st.markdown("#### ایجاد نسخه پشتیبان")
+
+ backup_type = st.radio(
+ "نوع پشتیبانگیری",
+ options=["پشتیبان کامل", "پشتیبان افزایشی"],
+ index=0
+ )
+
+ include_images = st.checkbox("شامل تصاویر", value=True)
+ include_user_data = st.checkbox("شامل دادههای کاربران", value=True)
+
+ if st.button("ایجاد نسخه پشتیبان", type="primary"):
+ # This would normally create a backup
+ st.info("در حال ایجاد نسخه پشتیبان...")
+ progress_bar = st.progress(0)
+ for i in range(100):
+ time.sleep(0.05)
+ progress_bar.progress(i + 1)
+ st.success("نسخه پشتیبان با موفقیت ایجاد شد.")
+
+ # Backup restoration
+ st.markdown("#### بازیابی از نسخه پشتیبان")
+
+ backup_file = st.file_uploader("آپلود فایل پشتیبان", type=["zip", "bak"])
+
+ if backup_file is not None:
+ st.warning("هشدار: بازیابی از نسخه پشتیبان ممکن است دادههای فعلی را بازنویسی کند.")
+ if st.button("شروع بازیابی"):
+ # This would normally restore from the backup
+ st.info("در حال بازیابی از نسخه پشتیبان...")
+ progress_bar = st.progress(0)
+ for i in range(100):
+ time.sleep(0.05)
+ progress_bar.progress(i + 1)
+ st.success("بازیابی از نسخه پشتیبان با موفقیت انجام شد.")
+
+ # Automatic backup settings
+ st.markdown("#### تنظیمات پشتیبانگیری خودکار")
+
+ auto_backup = st.checkbox("فعالسازی پشتیبانگیری خودکار", value=True)
+
+ if auto_backup:
+ backup_frequency = st.selectbox(
+ "تناوب پشتیبانگیری",
+ options=["روزانه", "هفتگی", "ماهانه"],
+ index=1
+ )
+
+ backup_time = st.time_input("زمان پشتیبانگیری", value=datetime.now().replace(hour=1, minute=0, second=0, microsecond=0))
+
+ retain_backups = st.number_input("تعداد نسخههای پشتیبان برای نگهداری", min_value=1, value=7)
+
+ # Save backup settings
+ if st.button("ذخیره تنظیمات پشتیبانگیری"):
+ st.success("تنظیمات پشتیبانگیری با موفقیت ذخیره شدند.")
-# Footer
+# Add a footer
st.markdown("""
-