import streamlit as st
import numpy as np
import pandas as pd
import joblib
# Set page config
st.set_page_config(page_title="Stress Detection using One-Class SVM", layout="centered")
# Custom CSS for background and styles
st.markdown(
"""
""",
unsafe_allow_html=True
)
st.title("Stress Detection")
st.markdown("Select a mode to detect stress from sensor readings:")
# Load model and scaler
try:
model = joblib.load("one_class_svm_stress_model.pkl")
scaler = joblib.load("scaler.pkl")
except Exception as e:
st.error(f"Error loading model or scaler: {e}")
st.stop()
# Load or create hardcoded dataset
try:
df = pd.read_csv("simulated_stress_data.csv")
df = df[['HR', 'HRV', 'EDA']].head(100)
except:
df = pd.DataFrame({
"HR": np.random.randint(60, 120, 100),
"HRV": np.random.uniform(20, 80, 100),
"EDA": np.random.uniform(0.1, 5.0, 100)
})
# Radio button selection
mode = st.radio("Choose input mode:", ["Manual Readings", "Generate Readings", "Test Dataset"], horizontal=True)
# Manual Input
if mode == "Manual Readings":
hr = st.number_input("Heart Rate (HR)", min_value=60, max_value=120, value=80)
hrv = st.number_input("Heart Rate Variability (HRV)", min_value=20.0, max_value=80.0, value=50.0)
eda = st.number_input("Electrodermal Activity (EDA)", min_value=0.1, max_value=5.0, value=2.0)
if st.button("Predict"):
sample = np.array([[hr, hrv, eda]])
scaled = scaler.transform(sample)
pred = model.predict(scaled)
label = "Stress" if pred[0] == -1 else "No Stress"
st.markdown(
f"""
HR: {hr} bpm
HRV: {hrv:.2f} ms
EDA: {eda:.2f} µS
""", unsafe_allow_html=True
)
st.subheader("Prediction")
if label == "No Stress":
st.success(label)
else:
st.error(label)
# Generate Random Input
elif mode == "Generate Readings":
if st.button("Generate and Predict"):
hr = np.random.randint(60, 120)
hrv = np.random.uniform(20, 80)
eda = np.random.uniform(0.1, 5.0)
sample = np.array([[hr, hrv, eda]])
scaled = scaler.transform(sample)
pred = model.predict(scaled)
label = "Stress" if pred[0] == -1 else "No Stress"
st.markdown(
f"""
HR: {hr} bpm
HRV: {hrv:.2f} ms
EDA: {eda:.2f} µS
""", unsafe_allow_html=True
)
st.subheader("Prediction")
if label == "No Stress":
st.success(label)
else:
st.error(label)
# Test Dataset (Scrollable)
elif mode == "Test Dataset":
st.markdown("### Select a row from test dataset for prediction:")
# Session state for pagination and prediction result
if "page" not in st.session_state:
st.session_state.page = 0
if "last_prediction" not in st.session_state:
st.session_state.last_prediction = None
st.session_state.last_row = None
rows_per_page = 5
df_filtered = df
total_pages = max(1, (len(df_filtered) - 1) // rows_per_page + 1)
# CSS for table rows
st.markdown("""
""", unsafe_allow_html=True)
# Display scrollable table
with st.container():
#st.markdown('', unsafe_allow_html=True)
# Tighter Pagination Controls
col1, col2, col3 = st.columns([1.2, 1.2, 3])
with col1:
if st.button("⬅️ Previous"):
if st.session_state.page > 0:
st.session_state.page -= 1
with col2:
if st.button("Next ➡️"):
if st.session_state.page < total_pages - 1:
st.session_state.page += 1
with col3:
st.markdown(
f"Page {st.session_state.page + 1} of {total_pages}
",
unsafe_allow_html=True
)
# Final prediction display at the end
if st.session_state.last_prediction and st.session_state.last_row is not None:
row = st.session_state.last_row
label = st.session_state.last_prediction
st.markdown("---")
st.markdown("### Prediction")
st.markdown(
f"""
HR: {row['HR']} bpm
HRV: {row['HRV']:.2f} ms
EDA: {row['EDA']:.2f} µS
""", unsafe_allow_html=True
)
if label == "No Stress":
st.success(label)
else:
st.error(label)