Spaces:
Sleeping
Sleeping
import streamlit as st | |
import pandas as pd | |
import numpy as np | |
from datetime import datetime, timedelta | |
from database import init_db, add_medication, get_all_medications | |
import matplotlib.pyplot as plt | |
from matplotlib.dates import DateFormatter | |
import seaborn as sns | |
import base64 | |
from sklearn.model_selection import train_test_split | |
from sklearn.ensemble import GradientBoostingClassifier, IsolationForest | |
# Initialize the database | |
init_db() | |
# Set page config | |
st.set_page_config( | |
page_title="Medication Tracker", | |
page_icon="π", | |
layout="centered", | |
initial_sidebar_state="expanded", | |
) | |
# Custom CSS for glass style UI | |
st.markdown( | |
""" | |
<style> | |
body { | |
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; | |
background-color: #f0f2f6; | |
color: #333; | |
} | |
.container { | |
max-width: 800px; | |
margin: 0 auto; | |
padding: 2rem; | |
background: rgba(255, 255, 255, 0.85); | |
border-radius: 16px; | |
backdrop-filter: blur(10px); | |
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1); | |
border: 1px solid rgba(255, 255, 255, 0.3); | |
} | |
.log-entry { | |
padding: 1rem; | |
margin-bottom: 1rem; | |
background: rgba(255, 255, 255, 0.9); | |
border-radius: 10px; | |
backdrop-filter: blur(5px); | |
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); | |
} | |
.title { | |
text-align: center; | |
color: #007aff; | |
} | |
.subtitle { | |
text-align: center; | |
color: #333; | |
margin-bottom: 1.5rem; | |
} | |
</style> | |
""", | |
unsafe_allow_html=True | |
) | |
st.markdown('<div class="container">', unsafe_allow_html=True) | |
st.markdown("<h1 class='title'>Medication Tracker π</h1>", unsafe_allow_html=True) | |
st.markdown("<p class='subtitle'>Track your prescription medications easily and get helpful insights.</p>", unsafe_allow_html=True) | |
# Form to log medication | |
st.markdown('<div class="log-form">', unsafe_allow_html=True) | |
st.markdown("<h2>Log Your Medication</h2>", unsafe_allow_html=True) | |
with st.form(key='log_medication'): | |
medication_name = st.text_input("Medication Name", key='medication_name', placeholder="e.g., Aspirin") | |
dosage = st.text_input("Dosage (e.g., 500 mg)", key='dosage', placeholder="e.g., 500 mg") | |
time_of_day = st.selectbox("Time of Day", ["Morning", "Afternoon", "Evening", "Night"], key='time_of_day') | |
date = st.date_input("Date", datetime.today(), key='date') | |
submit_button = st.form_submit_button(label='Log Medication') | |
if submit_button and medication_name and dosage: | |
add_medication(medication_name, dosage, time_of_day, date) | |
st.success(f"Logged: {medication_name} - {dosage} at {time_of_day} on {date}") | |
st.markdown('</div>', unsafe_allow_html=True) | |
# Display logged medications | |
st.markdown('<div class="logged-medications">', unsafe_allow_html=True) | |
st.markdown("<h2>Logged Medications</h2>", unsafe_allow_html=True) | |
medications = get_all_medications() | |
if not medications: | |
st.markdown("No medications logged yet.", unsafe_allow_html=True) | |
else: | |
for med in medications: | |
st.markdown(f'<div class="log-entry"><strong>{med[1]}</strong><br>Dosage: {med[2]}<br>Time: {med[3]}<br>Date: {med[4]}</div>', unsafe_allow_html=True) | |
st.markdown('</div>', unsafe_allow_html=True) | |
# Provide insights and data visualization | |
st.markdown('<div class="insights">', unsafe_allow_html=True) | |
st.markdown("<h2>Insights and Data Visualization</h2>", unsafe_allow_html=True) | |
if medications: | |
df = pd.DataFrame(medications, columns=["ID", "Medication", "Dosage", "Time", "Date"]) | |
# Convert Dosage to numeric | |
df['Dosage'] = df['Dosage'].str.extract('(\d+)').astype(float) | |
most_common_med = df['Medication'].mode()[0] | |
st.markdown(f"Most frequently taken medication: {most_common_med}", unsafe_allow_html=True) | |
avg_dosage_time = df.groupby('Time').size().idxmax() | |
st.markdown(f"Most common time of day for taking medications: {avg_dosage_time}", unsafe_allow_html=True) | |
st.markdown("Take your medications consistently at the same time each day to maintain stable drug levels in your body.", unsafe_allow_html=True) | |
st.markdown("If you have multiple medications, consult your healthcare provider to ensure there are no adverse interactions.", unsafe_allow_html=True) | |
# Visualization | |
st.markdown("<h3>Medication Intake Over Time</h3>", unsafe_allow_html=True) | |
df['Date'] = pd.to_datetime(df['Date']) | |
fig, ax = plt.subplots() | |
for key, grp in df.groupby(['Medication']): | |
ax = grp.plot(ax=ax, kind='line', x='Date', y='Dosage', label=key) | |
date_form = DateFormatter("%Y-%m-%d") | |
ax.xaxis.set_major_formatter(date_form) | |
plt.xlabel("Date") | |
plt.ylabel("Dosage (mg)") | |
plt.title("Medication Intake Over Time") | |
plt.legend(title='Medication') | |
st.pyplot(fig) | |
# Data export | |
csv = df.to_csv(index=False) | |
b64 = base64.b64encode(csv.encode()).decode() # B64 encoding | |
href = f'<a href="data:file/csv;base64,{b64}" download="medications.csv">Download CSV</a>' | |
st.markdown(href, unsafe_allow_html=True) | |
# AI Prediction: Predicting missed doses | |
st.markdown("<h3>Missed Dose Prediction</h3>", unsafe_allow_html=True) | |
df['Missed'] = np.random.choice([0, 1], size=len(df)) # Simulate missed doses for training | |
# Prepare the data | |
X = df[['Dosage', 'Time']].replace({"Morning": 0, "Afternoon": 1, "Evening": 2, "Night": 3}) | |
y = df['Missed'] | |
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) | |
# Train the model | |
model = GradientBoostingClassifier() | |
model.fit(X_train, y_train) | |
# Predict the probability of missing the next dose | |
user_dosage = st.number_input('Enter your dosage for the next dose', value=0) | |
user_time = st.selectbox('Select the time of day for the next dose', ["Morning", "Afternoon", "Evening", "Night"]) | |
user_time_encoded = ["Morning", "Afternoon", "Evening", "Night"].index(user_time) | |
if st.button('Predict Missed Dose'): | |
user_data = pd.DataFrame({'Dosage': [user_dosage], 'Time': [user_time_encoded]}) | |
missed_prob = model.predict_proba(user_data)[:, 1][0] | |
st.markdown(f"**Probability of missing the next dose: {missed_prob:.2f}**") | |
# Medication Interaction Warnings | |
st.markdown("<h3>Medication Interaction Warnings</h3>", unsafe_allow_html=True) | |
interactions = { | |
"Aspirin": ["Warfarin", "Ibuprofen"], | |
"Ibuprofen": ["Aspirin", "Warfarin"], | |
"Warfarin": ["Aspirin", "Ibuprofen"], | |
} | |
user_medications = st.multiselect( | |
'Select your current medications', | |
list(interactions.keys()) | |
) | |
potential_interactions = [] | |
for med in user_medications: | |
for interaction in interactions.get(med, []): | |
if interaction in user_medications and interaction not in potential_interactions: | |
potential_interactions.append(interaction) | |
if potential_interactions: | |
st.warning(f"Potential interactions detected: {', '.join(potential_interactions)}") | |
else: | |
st.success("No interactions detected.") | |
# Adaptive Reminders (Simulated) | |
st.markdown("<h3>Adaptive Reminders</h3>", unsafe_allow_html=True) | |
reminder_times = { | |
"Morning": 8, | |
"Afternoon": 13, | |
"Evening": 18, | |
"Night": 22 | |
} | |
def adaptive_reminder(user_time, success): | |
reminder_times[user_time] = reminder_times.get(user_time, 0) + (1 if success else -1) | |
return reminder_times[user_time] | |
if st.button('Simulate Reminder'): | |
success = np.random.choice([True, False]) # Simulate user response to reminder | |
new_time = adaptive_reminder(user_time, success) | |
st.markdown(f"Adaptive reminder time for {user_time} is now set to {new_time}:00") | |
# Anomaly Detection in Medication Patterns | |
st.markdown("<h3>Anomaly Detection</h3>", unsafe_allow_html=True) | |
if len(df) > 10: # Ensure enough data for anomaly detection | |
isolation_forest = IsolationForest(contamination=0.1) | |
df['Anomaly'] = isolation_forest.fit_predict(df[['Dosage']]) | |
anomalies = df[df['Anomaly'] == -1] | |
if not anomalies.empty: | |
st.markdown("### Anomalies Detected:") | |
st.dataframe(anomalies[['Medication', 'Dosage', 'Time', 'Date']]) | |
else: | |
st.markdown("No anomalies detected in your medication patterns.") | |
st.markdown('</div>', unsafe_allow_html=True) | |
# Footer | |
st.markdown("<hr>", unsafe_allow_html=True) | |
st.markdown("<p><strong>Disclaimer:</strong> This app is for tracking purposes only. Always consult with your healthcare provider for medical advice.</p>", unsafe_allow_html=True) | |
st.markdown('</div>', unsafe_allow_html=True) |