NUSTxKisaan / app.py
Nazhar's picture
Update app.py
9d7bc88 verified
import streamlit as st
import pandas as pd
import numpy as np
import plotly.express as px
import plotly.graph_objects as go
import folium
from streamlit_folium import folium_static
import branca.colormap as cm
from folium.plugins import HeatMap
from guidelines import eng_guidelines, urdu_guidelines, punjabi_guidelines
from guidelines import eng_howtomanage, urdu_howtomanage, punjabi_howtomanage
from functions import Diseases
from disease_information import conducive_parameters, disease_desc
# Load Dummy Data
df = pd.read_csv("streamlit_sample.csv")
tab1, tab2, tab3, tab4 = st.tabs(["Monitoring", "Stats", "Simulator", "Testing"])
with tab4:
# Define coordinates of locations
coordinates = {
"Chund Bharwana": {'lat': 31.4170, 'lon': 72.2645},
"Lallian": {'lat': 31.8194, 'lon': 72.7984},
"Athara Hazari": {'lat': 31.1648, 'lon': 72.0972},
"Bhowana": {'lat': 31.5659, 'lon': 72.6447},
"Garh Maharaja": {'lat': 30.8338, 'lon': 71.9060}
}
# Define number of members at each location
members = {
'Chund Bharwana': 10,
'Athara Hazari': 12,
'Lallian': 25,
'Garh Maharaja': 10, # Fixed key typo from "Garrh Maharaja"
'Bhowana': 20,
'Toba Tek Singh': 5 # Note: No coordinates available for this location
}
# Dropdown options
sites = list(coordinates.keys()) + ["All"]
# Streamlit UI
c1, c2 = st.columns(2)
with c1:
locations = st.selectbox("Select Location:", sorted(sites), key="testing 2")
with c2:
types = st.selectbox("Rice Type:", ["Basmati Pak", "Super Basmati", "Kissan Basmati"], key="testing 1")
# Function to generate random points around a given location
def generate_random_points(lat, lon, num_points, radius=0.01):
"""Generate random lat/lon points around a given location"""
lats = lat + np.random.uniform(-radius, radius, num_points)
lons = lon + np.random.uniform(-radius, radius, num_points)
return list(zip(lats, lons))
# Initialize Folium Map
if locations == "All":
m = folium.Map(location=[31.5, 72.4], zoom_start=8) # Centered around Punjab
heat_data = []
# Loop through all locations
for loc, coords in coordinates.items():
lat, lon = coords["lat"], coords["lon"]
mem_count = members.get(loc, 0) # Get member count, default to 0 if not found
heat_data.extend(generate_random_points(lat, lon, mem_count)) # Add heatmap points
# Add main location marker
folium.Marker(
location=[lat, lon],
popup=f"{loc} ({mem_count} members)",
tooltip=f"{loc} ({mem_count} members)",
icon=folium.Icon(color="blue", icon="info-sign")
).add_to(m)
# Add HeatMap layer
HeatMap(heat_data, radius=15).add_to(m)
else:
latlon = coordinates.get(locations)
if latlon:
lat, lon = latlon["lat"], latlon["lon"]
mem_vals = members.get(locations, 0)
# Create map centered on the selected location
m = folium.Map(location=[lat, lon], zoom_start=12)
# Add the main marker
folium.Marker(
location=[lat, lon],
popup=f"{locations} ({mem_vals} members)",
tooltip=f"{locations} ({mem_vals} members)",
icon=folium.Icon(color="blue", icon="info-sign")
).add_to(m)
# Generate and add random member points
random_points = generate_random_points(lat, lon, mem_vals)
for point in random_points:
folium.CircleMarker(
location=point,
radius=4,
color="red",
fill=True,
fill_color="red",
fill_opacity=0.6
).add_to(m)
# Display the map in Streamlit
folium_static(m)
with tab2:
stats = {'Chund Bharwana': ['brown_spot', 'bacterial_leaf_blight', 'bakanae'],
'Athara Hazari': ['bacterial_leaf_blight', 'bakanae'],
'Lallian': ['brown_spot', 'sheath_rot', 'sheath_blight', 'bacterial_leaf_blight', 'bakanae', 'rice_blast'],
'Garrh Maharaja': ['bacterial_leaf_blight', 'bakanae'],
'Bhowana': ['brown_spot', 'bacterial_leaf_blight'],
'Toba Tek Singh': ['bacterial_leaf_blight', 'bakanae']}
diseases = sorted(['Brown Spot', 'Bacterial Leaf Blight', 'Bakanae',
'Rice Blast', 'Sheath Blight', 'Sheath Rot',
'Bacterial Panicle Blight', 'False Smut'])
disease = st.selectbox("Select Disease:", diseases, key=3)
sites = sorted(['Athara Hazari', 'Bhowana', 'Chund Bharwana',
'Garrh Maharaja', 'Lallian', 'Toba Tek Singh'])
site = st.selectbox("Select Site:", sites, key=4)
container = st.container(border=True)
# r1c1, r1c2 = st.columns(2)
row2 = st.columns(2)
for col in row2:
tile = col.container(height=120)
tile.title(":balloon:")
with container:
disease_columns = ['brown_spot', 'sheath_rot', 'sheath_blight', 'bacterial_leaf_blight',
'bakanae', 'bacterial_panicle_blight', 'rice_blast', 'false_smut']
df_melted = df.melt(id_vars=['growth_stage'], value_vars=disease_columns,
var_name="Disease", value_name="Presence")
# Filter only where disease is present
df_filtered = df_melted[df_melted['Presence'] == 1]
# Create the interactive Plotly bar chart
fig = px.bar(df_filtered, x="growth_stage", color="Disease",
title="Disease Prevalence Across Growth Stages",
labels={"growth_stage": "Growth Stage", "count": "Count"},
barmode="group")
fig.update_layout(xaxis=dict(tickangle=-45), legend_title_text="Disease")
# Show the figure
st.plotly_chart(fig)
with tab3:
# st.title("Simulator")
coordinates = {"Chund Bharwana": {'lat': 31.4170, 'lon':72.2645},
"Lallian": {'lat': 31.8194, 'lon':72.7984},
"Athara Hazari": {'lat': 31.1648, 'lon':72.0972},
"Bhowana": {'lat': 31.5659, 'lon':72.6447},
"Garh Maharaja": {'lat': 30.8338, 'lon':71.9060}}
members = {'Chund Bharwana': 10,
'Athara Hazari': 12,
'Lallian': 25,
'Garrh Maharaja': 10,
'Bhowana': 20,
'Toba Tek Singh': 5}
# sites = list(coordinates.keys()) + ["All"]
# c1, c2 = st.columns(2)
# with c1:
# locations = st.selectbox("Location:", sorted(sites), key=5)
# with c2:
# types = st.selectbox("Rice Type:", ["Basmati Pak", "Super Basmati", "Kissan Basmati"],key=8)
# Dropdown options
sites = list(coordinates.keys()) + ["All"]
# Streamlit UI
c1, c2 = st.columns(2)
with c1:
locations = st.selectbox("Select Location:", sorted(sites), key=2)
with c2:
types = st.selectbox("Rice Type:", ["Basmati Pak", "Super Basmati", "Kissan Basmati"], key=1)
# Function to generate random points around a given location
def generate_random_points(lat, lon, num_points, radius=0.01):
"""Generate random lat/lon points around a given location"""
lats = lat + np.random.uniform(-radius, radius, num_points)
lons = lon + np.random.uniform(-radius, radius, num_points)
return list(zip(lats, lons))
# Initialize Folium Map
if locations == "All":
m = folium.Map(location=[31.5, 72.4], zoom_start=8) # Centered around Punjab
heat_data = []
# Loop through all locations
for loc, coords in coordinates.items():
lat, lon = coords["lat"], coords["lon"]
mem_count = members.get(loc, 0) # Get member count, default to 0 if not found
heat_data.extend(generate_random_points(lat, lon, mem_count)) # Add heatmap points
# Add main location marker
folium.Marker(
location=[lat, lon],
popup=f"{loc} ({mem_count} members)",
tooltip=f"{loc} ({mem_count} members)",
icon=folium.Icon(color="blue", icon="info-sign")
).add_to(m)
# Add HeatMap layer
HeatMap(heat_data, radius=15).add_to(m)
else:
latlon = coordinates.get(locations)
if latlon:
lat, lon = latlon["lat"], latlon["lon"]
mem_vals = members.get(locations, 0)
# Create map centered on the selected location
m = folium.Map(location=[lat, lon], zoom_start=12)
# Add the main marker
folium.Marker(
location=[lat, lon],
popup=f"{locations} ({mem_vals} members)",
tooltip=f"{locations} ({mem_vals} members)",
icon=folium.Icon(color="blue", icon="info-sign")
).add_to(m)
# Generate and add random member points
random_points = generate_random_points(lat, lon, mem_vals)
for point in random_points:
folium.CircleMarker(
location=point,
radius=4,
color="red",
fill=True,
fill_color="red",
fill_opacity=0.6
).add_to(m)
# Display the map in Streamlit
folium_static(m)
# if locations!="All":
# mem_vals = members[locations]
# latlon = coordinates[locations]
# lat = latlon['lat']
# lon = latlon['lon']
# elif locations=="All":
# mem_vals = sum(list(members.values()))
# lat = 30.8338
# lon = 72.7984
# # st.write("Values:", temp_min, temp_max)
# # Create Folium map centered on an average location
# # left, right = st.columns([0.7, 0.3], gap="medium", vertical_alignment="top")
# # with left:
# m = folium.Map(location=[lat, lon], zoom_start=12)
# folium.Marker(
# location=[lat, lon],
# popup=locations, # Click to see name
# tooltip=locations, # Hover to see name
# icon=folium.Icon(color="blue", icon="info-sign"),
# ).add_to(m)
# folium_static(m)
# with right:
# st.write("Temperature: ",temp_min,"to", temp_max)
# st.write("Humidity: ", humi_min, "to", humi_max)
st.divider()
temperatures = st.slider("Select Temperature Range (°C)", 20.0, 40.0, (25.0, 37.0))
temp_max = temperatures[1]
temp_min = temperatures[0]
humidity = st.slider("Select Humidity Range (%)", 60.0, 100.0, (90.0, 100.0))
humi_max = humidity[1]
humi_min = humidity[0]
# Function Call (Assuming `Diseases` function and `conducive_parameters` exist)
possible_diseases = Diseases(temp_max, temp_min, humi_max, humi_min, conducive_parameters)
if possible_diseases:
formatted_diseases = ", ".join(possible_diseases)
# st.markdown(f"## 🌾 Possible Diseases: **{formatted_diseases}**")
selection = st.pills("**🌾 Possible Diseases:**", possible_diseases, selection_mode="multi")
for disease in selection:
disease_info = conducive_parameters[disease]
details = disease_desc[disease]
# Disease Title
st.markdown(f"### 🦠 {disease}")
with st.expander("See Description"):
st.markdown(details["Description"])
st.markdown(details["Identification"])
if details["Image_count"] == 1:
with st.container():
st.image(details["Image1"])
elif details["Image_count"] == 2:
c1, c2 = st.columns(2, vertical_alignment="center")
c1.image(details["Image1"])
c2.image(details["Image2"])
# Conducive Parameters Section
st.markdown("#### 📌 Conducive Parameters:")
st.markdown(f"**🌡 Optimal Temperature:** `{disease_info['Tmin']} - {disease_info['Tmax']}°C`")
st.markdown(f"**💧 Humidity %:** `{disease_info['Hmin']} - {disease_info['Hmax']}%`")
st.markdown(f"**🌦 Weather Conditions:** {disease_info['Weather Conditions']}.")
st.markdown(f"**⏳ Likely to occur if conditions persist for:** `{disease_info['Duration']}` consecutively.")
st.markdown(f"**🌱 Stages of Occurrence:** `{disease_info['Stages']}`")
st.markdown(f"**🔗 [See More Details]({details['link']})**")
# Separator for clarity
st.markdown("---")
else:
st.markdown("### ✅ No diseases predicted based on the current conditions.")
st.divider()
# with tab2:
# st.title("Interactive Map Viewer")
# coordinates = {"Chund Bharwana": {'lat': 31.4170, 'lon':72.2645},
# "Lallian": {'lat': 31.8194, 'lon':72.7984},
# "Athara Hazari": {'lat': 31.1648, 'lon':72.0972},
# "Bhowana": {'lat': 31.5659, 'lon':72.6447},
# "Garh Maharaja": {'lat': 30.8338, 'lon':71.9060}}
# loc_values = {"Chund Bharwana": 101983,
# "Lallian": 20599,
# "Athara Hazari": 24990,
# "Bhowana": 4192,
# "Garh Maharaja": 17009}
# # Create Folium map centered on an average location
# m = folium.Map(location=[31.5, 72.5], zoom_start=9)
# # Create a colormap
# colormap = cm.linear.RdBu_09.scale(min(loc_values.values()), max(loc_values.values()))
# # Add colored circles representing locations with annotations
# for loc, coords in coordinates.items():
# folium.Circle(
# location=[coords['lat'], coords['lon']],
# radius=5000,
# color=colormap(loc_values[loc]),
# fill=True,
# fill_color=colormap(loc_values[loc]),
# fill_opacity=0.6,
# popup=f"{loc}: {loc_values[loc]}"
# ).add_to(m)
# # Add annotation (marker with text)
# folium.Marker(
# location=[coords['lat'], coords['lon']],
# icon=folium.DivIcon(html=f"""
# <div style="font-size: 12px; font-weight: bold; color: black; padding: 2px; border-radius: 5px;">
# {loc}
# </div>
# """),
# ).add_to(m)
# # Add colormap legend
# colormap.caption = "Value Intensity"
# m.add_child(colormap)
# folium_static(m)
# # st_folium(m)
# # disease_counts = df.groupby('Site')[['brown_spot', 'sheath_rot', 'sheath_blight', 'bacterial_leaf_blight', 'bakanae', 'bacterial_panicle_blight', 'rice_blast', 'false_smut']].sum().reset_index()
# # diseases = ['brown_spot', 'sheath_rot', 'sheath_blight', 'bacterial_leaf_blight', 'bakanae', 'bacterial_panicle_blight', 'rice_blast', 'false_smut']
# colors = ['#440154', '#3b528b', '#21908c', '#5dc963', '#fde725', '#ff9933', '#ff5733', '#c50000'] # Coolwarm-like colors
# disease_columns = ['brown_spot', 'sheath_rot', 'sheath_blight', 'bacterial_leaf_blight',
# 'bakanae', 'bacterial_panicle_blight', 'rice_blast', 'false_smut']
# disease_counts = df.groupby('Site')[disease_columns].sum().reset_index()
# # Melt the dataframe for Plotly
# df_melted = disease_counts.melt(id_vars=['Site'], value_vars=disease_columns,
# var_name="Disease", value_name="Total Cases")
# # Create stacked bar chart
# fig = px.bar(df_melted, x="Site", y="Total Cases", color="Disease",
# title="Disease Occurrence Across Different Sites",
# labels={"Site": "Site", "Total Cases": "Total Cases"},
# barmode="group", color_discrete_sequence=colors)
# # Update layout
# fig.update_layout(xaxis=dict(tickangle=-45), legend_title_text="Diseases")
# # Show the figure
# st.plotly_chart(fig)
with tab1:
# # The ID values range from 1 to the length of the DataFrame
# df['ID'] = range(1, len(df) + 1)
# Streamlit App
st.title("Rice Disease Monitoring")
# Convert Date column to datetime if not already
if not pd.api.types.is_datetime64_any_dtype(df['Expanded_Date']):
df['Expanded_Date'] = pd.to_datetime(df['Expanded_Date'])
r1c1, r1c2, r1c3 = st.columns(3)
with r1c1:
# Create Sidebar
# with st.sidebar:
disease = st.selectbox("Select Disease:", ['Brown Spot', 'Bacterial Leaf Blight', 'Bakanae',
'Rice Blast', 'Sheath Blight', 'Sheath Rot',
'Bacterial Panicle Blight', 'False Smut'], key=6)
if disease == 'Brown Spot':
d = 'brown_spot'
elif disease == 'Sheath Rot':
d = 'sheath_rot'
elif disease == 'Sheath Blight':
d = 'sheath_blight'
elif disease == 'Bacterial Panicle Blight':
d = 'bacterial_panicle_blight'
elif disease == 'Bakanae':
d = 'bakanae'
elif disease == 'Bacterial Leaf Blight':
d = 'bacterial_leaf_blight'
elif disease == 'Rice Blast':
d = 'rice_blast'
elif disease == 'False Smut':
d = 'false_smut'
conducive_col = f"{d}_conducive_day"
with r1c2:
types = st.selectbox("Select Type:", ["Basmati Pak", "Super Basmati", "Kissan Basmati"], key=7)
if types == "Basmati Pak":
type = f"Type 1"
df = df[df['type'] == type]
elif types == "Super Basmati":
type = f"Type 2"
df = df[df['type'] == type]
elif types == "Kissan Basmati":
type = f"Type 3"
df = df[df['type'] == type]
if types == "Basmati Pak":
# Y-values and corresponding annotations
y_values_annotations = {
25: "1 - Seedling/Transplantation",
35: "2 - Tillering",
50: "3 - Panicle Initiation",
70: "4 - Flowering",
100: "5 - Maturity"
}
elif types == "Super Basmati":
# Y-values and corresponding annotations
y_values_annotations = {
30: "1 - Seedling/Transplantation",
55: "2 - Tillering",
70: "3 - Panicle Initiation",
90: "4 - Flowering",
120: "5 - Maturity"
}
elif types == "Kissan Basmati":
# Y-values and corresponding annotations
y_values_annotations = {
35: "1 - Seedling/Transplantation",
75: "2 - Tillering",
90: "3 - Panicle Initiation",
110: "4 - Flowering",
140: "5 - Maturity"
}
# Get unique IDs
unique_ids = df['ID'].unique()
with r1c3:
disease_conducive = st.radio("Show:", ["Disease", "Conducive Days"])
# Create figure
fig = go.Figure()
# Add line plot
for id_val in unique_ids:
df_subset = df[df['ID'] == id_val]
fig.add_trace(go.Scatter(x=df_subset['Date'],
y=df_subset['growth_duration'],
mode='lines',
name=f"Crop ID: {id_val}")) # Use ID as name
if disease_conducive == "Conducive Days":
# Add red markers for conducive day occurrences
conducive_dates = df_subset[df_subset[conducive_col] == 1]
print(f"Conducive shape: {conducive_dates.shape}")
fig.add_trace(go.Scatter(
x=conducive_dates['Date'],
y=conducive_dates['growth_duration'],
mode='markers',
marker=dict(color='red', size=10),
name=f"{disease} Conducive Day"
))
elif disease_conducive == "Disease":
# Add red markers for disease occurrences
disease_dates = df_subset[df_subset[d] == 1]
print(f"Disease shape: {disease_dates.shape}")
fig.add_trace(go.Scatter(
x=disease_dates['Date'],
y=disease_dates['growth_duration'],
mode='markers',
marker=dict(color='red', size=10),
name=disease
))
# Add horizontal lines with annotations
for y, annotation_text in y_values_annotations.items():
fig.add_shape(
go.layout.Shape(
type="line",
x0=df['Date'].min(),
x1=df['Date'].max(),
y0=y,
y1=y,
line=dict(color="grey", width=1, dash="dash"),
)
)
fig.add_annotation(
x=df['Date'].min(), # X-position of the annotation
y=y, # Y-position (same as the line)
text=annotation_text, # Annotation text
showarrow=False, # Hide the arrow
xanchor='left', # Anchor the annotation to the left
yanchor='bottom', # Anchor the annotation to the bottom
)
# Update layout
fig.update_layout(
title='Growth Duration Over Time',
xaxis_title='Date',
yaxis_title='Growth Duration (days)'
)
# Plotly Figure
# fig = px.line(df_disease, x='Date', y='growth_duration', title='Growth Duration Over Time', markers=True)
# fig.update_layout(xaxis_title='Date', yaxis_title='Growth Duration (days)')
# Display Plot
st.plotly_chart(fig)
tab1.subheader("Guidlines for the Farmers")
t1, t2, t3 = tab1.tabs(["English", "اردو", "پنجابی"])
with t1:
# st.write(eng_guidelines)
if disease:
st.header(disease)
st.subheader("Instructions")
st.write(eng_guidelines[d]["instructions"])
st.subheader("Guidelines")
st.markdown(eng_howtomanage[disease])
# for guideline in eng_howtomanage[disease]:
# st.markdown(f"- {guideline}")
# print("\n\n\n\n\n")
st.divider()
with t2:
# st.write(urdu_guidelines)
# u1, u2 = t2.columns(2)
if disease:
# with u2:
# st.header(f'<div dir="rtl" style="text-align: right;">{urdu_guidelines[d]["name_ur"]}</div>', anchor=False, unsafe_allow_html=True)
# st.subheader("ہدایات", anchor=False)
# st.write(f'<div dir="rtl" style="text-align: right;">{urdu_guidelines[d]["instructions"]}</div>', unsafe_allow_html=True)
st.markdown(f"""
<h2 style='text-align: right;'>{urdu_guidelines[d]["name_ur"]}</h2>
<h3 style='text-align: right;'>ہدایات</h3>
<p style='text-align: right;'>{urdu_guidelines[d]["instructions"]}</p>
<h3 style='text-align: right;'>رہنما اصول</h3>
""", unsafe_allow_html=True)
# with u2:
# st.subheader("رہنما اصول", anchor=False)
# st.markdown(f'<div dir="rtl" style="text-align: right;">- {urdu_howtomanage[disease]}</div>', unsafe_allow_html=True)
for guideline in urdu_howtomanage[disease]:
st.markdown(f'<div dir="rtl" style="text-align: right;">- {guideline}</div>', unsafe_allow_html=True)
# print("\n\n\n\n\n")
st.divider()
with t3:
# st.write(punjabi_guidelines)
if disease:
st.markdown(f"""
<h2 style='text-align: right;'>{urdu_guidelines[d]["name_ur"]}</h2>
<h3 style='text-align: right;'>ہدایات</h3>
<p style='text-align: right;'>{punjabi_guidelines[d]["instructions"]}</p>
<h3 style='text-align: right;'>رہنما اصول</h3>
""", unsafe_allow_html=True)
# st.markdown(f'<div dir="rtl" style="text-align: right;">- {punjabi_howtomanage[disease]}</div>', unsafe_allow_html=True)
for guideline in punjabi_howtomanage[disease]:
st.markdown(f'<div dir="rtl" style="text-align: right;">- {guideline}</div>', unsafe_allow_html=True)
# print("\n\n\n\n\n")
st.divider()