|
import streamlit as st |
|
import plotly.graph_objects as go |
|
import plotly.express as px |
|
import pandas as pd |
|
import numpy as np |
|
import requests |
|
from datetime import datetime, timedelta |
|
import time |
|
|
|
|
|
API_URL = 'http://localhost:5000/api' |
|
|
|
|
|
@st.cache_data |
|
def load_data(): |
|
data = pd.read_csv("dataset.csv", parse_dates=["PACKAGEDATE"]) |
|
data.set_index("PACKAGEDATE", inplace=True) |
|
|
|
|
|
column_mapping = { |
|
"ODA3 CLIMATE_Co2": "CO2", |
|
"ODA3 CLIMATE_Nem": "Humidity", |
|
"ODA3 CLIMATE_Temp": "Temperature", |
|
"ODA3 DOSE_EC_EC": "EC", |
|
"ODA3 DOSE_EC_Wtemp": "Water Temperature", |
|
"ODA3 DOSE_PH_PH": "pH" |
|
} |
|
data = data.rename(columns=column_mapping) |
|
return data |
|
|
|
|
|
OPTIMAL_RANGES = { |
|
'temp': {'min': 20, 'max': 25, 'unit': '°C'}, |
|
'humidity': {'min': 60, 'max': 80, 'unit': '%'}, |
|
'co2': {'min': 400, 'max': 1000, 'unit': 'ppm'}, |
|
'ph': {'min': 6.0, 'max': 7.0, 'unit': ''}, |
|
'ec': {'min': 500, 'max': 1500, 'unit': 'μS/cm'}, |
|
'wtemp': {'min': 18, 'max': 23, 'unit': '°C'} |
|
} |
|
|
|
|
|
st.set_page_config( |
|
page_title="Climate Metrics Dashboard", |
|
page_icon="🌡️", |
|
layout="wide" |
|
) |
|
|
|
|
|
st.title("AGRIDL AI Analysis/Predicted Metrics Dashboard") |
|
st.markdown("Real-time monitoring and prediction system") |
|
|
|
|
|
data = load_data() |
|
|
|
|
|
def get_status_color(value, metric): |
|
range_data = OPTIMAL_RANGES[metric] |
|
if range_data['min'] <= value <= range_data['max']: |
|
return "green" |
|
elif (value < range_data['min'] - (range_data['max'] - range_data['min']) * 0.2 or |
|
value > range_data['max'] + (range_data['max'] - range_data['min']) * 0.2): |
|
return "red" |
|
return "yellow" |
|
|
|
def format_metric_value(value, metric): |
|
unit = OPTIMAL_RANGES[metric]['unit'] |
|
return f"{value}{unit}" |
|
|
|
def display_metric_card(title, value, metric_key): |
|
color = get_status_color(value, metric_key) |
|
st.metric( |
|
label=title, |
|
value=format_metric_value(value, metric_key), |
|
delta=f"Optimal: {OPTIMAL_RANGES[metric_key]['min']}-{OPTIMAL_RANGES[metric_key]['max']}{OPTIMAL_RANGES[metric_key]['unit']}" |
|
) |
|
return st.number_input(f"New {title}", key=f"input_{metric_key}") |
|
|
|
|
|
tab1, tab2, tab3, tab4, tab5 = st.tabs(["Current Metrics", "Historical Data", "Time Analysis", "Data Analysis", "Correlation Matrix"]) |
|
|
|
with tab1: |
|
|
|
col1, col2, col3 = st.columns(3) |
|
with col1: |
|
refresh_metrics = st.button("Refresh Metrics") |
|
with col2: |
|
update_metrics = st.button("Update Metrics") |
|
with col3: |
|
update_predictions = st.button("Update Predictions") |
|
|
|
|
|
try: |
|
if refresh_metrics: |
|
with st.spinner("Loading current metrics..."): |
|
response = requests.get(f"{API_URL}/current-metrics") |
|
if response.ok: |
|
metrics_data = response.json() |
|
st.success("Metrics refreshed successfully!") |
|
else: |
|
st.error("Failed to load metrics") |
|
metrics_data = {} |
|
else: |
|
|
|
metrics_data = { |
|
'temp': 22, |
|
'humidity': 70, |
|
'co2': 800, |
|
'ph': 6.5, |
|
'ec': 1000, |
|
'wtemp': 20 |
|
} |
|
|
|
|
|
col1, col2, col3 = st.columns(3) |
|
new_metrics = {} |
|
|
|
with col1: |
|
new_metrics['temp'] = display_metric_card("Temperature", metrics_data['temp'], 'temp') |
|
new_metrics['ph'] = display_metric_card("pH", metrics_data['ph'], 'ph') |
|
|
|
with col2: |
|
new_metrics['humidity'] = display_metric_card("Humidity", metrics_data['humidity'], 'humidity') |
|
new_metrics['ec'] = display_metric_card("EC", metrics_data['ec'], 'ec') |
|
|
|
with col3: |
|
new_metrics['co2'] = display_metric_card("CO2", metrics_data['co2'], 'co2') |
|
new_metrics['wtemp'] = display_metric_card("Water Temperature", metrics_data['wtemp'], 'wtemp') |
|
|
|
if update_metrics: |
|
updated_metrics = {k: v for k, v in new_metrics.items() if v is not None} |
|
if updated_metrics: |
|
with st.spinner("Updating metrics..."): |
|
response = requests.post(f"{API_URL}/update-metrics", json=updated_metrics) |
|
if response.ok: |
|
st.success("Metrics updated successfully!") |
|
else: |
|
st.error("Failed to update metrics") |
|
|
|
except Exception as e: |
|
st.error(f"An error occurred: {str(e)}") |
|
|
|
with tab2: |
|
st.header("Historical Data Visualization") |
|
|
|
|
|
metric = st.selectbox("Select Metric", data.columns) |
|
|
|
|
|
date_range = st.date_input( |
|
"Select Date Range", |
|
value=(data.index.min(), data.index.max()), |
|
min_value=data.index.min().date(), |
|
max_value=data.index.max().date() |
|
) |
|
|
|
|
|
fig = px.line(data, y=metric, title=f"{metric} Over Time") |
|
fig.update_layout( |
|
xaxis_title="Date", |
|
yaxis_title=metric, |
|
showlegend=True |
|
) |
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
|
|
if st.checkbox("Show Raw Data"): |
|
st.dataframe(data[metric].head(100)) |
|
|
|
with tab3: |
|
st.header("Time-based Analysis") |
|
|
|
|
|
data_hourly = data.resample("H").mean() |
|
data_daily = data.resample("D").mean() |
|
data_monthly = data.resample("M").mean() |
|
|
|
analysis_type = st.radio("Select Analysis Type", ["Hourly", "Daily", "Monthly"]) |
|
metric = st.selectbox("Select Metric for Analysis", data.columns, key="time_analysis") |
|
|
|
if analysis_type == "Hourly": |
|
plot_data = data_hourly |
|
title = "Hourly Average" |
|
elif analysis_type == "Daily": |
|
plot_data = data_daily |
|
title = "Daily Average" |
|
else: |
|
plot_data = data_monthly |
|
title = "Monthly Average" |
|
|
|
fig = px.line(plot_data, y=metric, title=f"{title}: {metric}") |
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
|
|
st.subheader("Statistical Summary") |
|
st.write(plot_data[metric].describe()) |
|
|
|
with tab4: |
|
st.header("Data Analysis") |
|
|
|
|
|
st.subheader("Statistical Summary") |
|
st.write(data.describe()) |
|
|
|
|
|
st.subheader("Distribution Analysis") |
|
metric = st.selectbox("Select Metric for Distribution", data.columns, key="dist_analysis") |
|
|
|
fig = px.histogram(data, x=metric, title=f"Distribution of {metric}") |
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
|
|
fig = px.box(data, y=metric, title=f"Box Plot of {metric}") |
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
with tab5: |
|
st.header("Correlation Analysis") |
|
|
|
|
|
correlation_matrix = data.corr() |
|
|
|
|
|
fig = go.Figure(data=go.Heatmap( |
|
z=correlation_matrix, |
|
x=correlation_matrix.columns, |
|
y=correlation_matrix.columns, |
|
colorscale='RdBu', |
|
zmin=-1, |
|
zmax=1 |
|
)) |
|
|
|
fig.update_layout( |
|
title="Correlation Matrix", |
|
xaxis_title="Metrics", |
|
yaxis_title="Metrics" |
|
) |
|
|
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
|
|
if st.checkbox("Show Detailed Correlation Values"): |
|
st.write(correlation_matrix) |
|
|
|
|
|
if st.sidebar.checkbox("Enable Auto-refresh", value=False): |
|
refresh_interval = st.sidebar.slider("Refresh interval (seconds)", |
|
min_value=30, |
|
max_value=300, |
|
value=60) |
|
st.sidebar.info(f"Dashboard will refresh every {refresh_interval} seconds") |
|
time.sleep(refresh_interval) |
|
st.experimental_rerun() |