Update app.py
Browse files
app.py
CHANGED
@@ -4,8 +4,14 @@ import plotly.express as px
|
|
4 |
import os
|
5 |
from openai import OpenAI
|
6 |
import bcrypt
|
|
|
7 |
|
8 |
-
# Set up
|
|
|
|
|
|
|
|
|
|
|
9 |
client = OpenAI(api_key=st.secrets["OPENAI_API_KEY"])
|
10 |
|
11 |
# Initialize session state
|
@@ -14,33 +20,31 @@ if 'user' not in st.session_state:
|
|
14 |
if 'user_type' not in st.session_state:
|
15 |
st.session_state.user_type = None
|
16 |
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
def load_data():
|
24 |
-
if os.path.exists(CSV_FILE):
|
25 |
-
return pd.read_csv(CSV_FILE)
|
26 |
-
return pd.DataFrame(columns=['user', 'date', 'pain_level', 'duration', 'triggers', 'symptoms', 'medications', 'notes', 'doctor_analysis', 'patient_advice'])
|
27 |
|
28 |
-
# Function to load user data
|
29 |
-
# @st.cache_data
|
30 |
def load_user_data():
|
31 |
-
|
32 |
-
|
33 |
-
return pd.DataFrame(columns=['username', 'password', 'user_type'])
|
34 |
|
35 |
-
|
36 |
-
|
37 |
-
df.to_csv(CSV_FILE, index=False)
|
38 |
|
39 |
-
|
40 |
-
|
41 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
42 |
|
43 |
-
# Function to get GPT analysis
|
44 |
def get_gpt_analysis(entry_text, system_prompt):
|
45 |
try:
|
46 |
response = client.chat.completions.create(
|
@@ -55,15 +59,12 @@ def get_gpt_analysis(entry_text, system_prompt):
|
|
55 |
st.error(f"Error in GPT analysis: {str(e)}")
|
56 |
return "Analysis unavailable at this time."
|
57 |
|
58 |
-
# Password hashing function
|
59 |
def hash_password(password):
|
60 |
return bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
|
61 |
|
62 |
-
# Password verification function
|
63 |
def verify_password(stored_password, provided_password):
|
64 |
return bcrypt.checkpw(provided_password.encode('utf-8'), stored_password.encode('utf-8'))
|
65 |
|
66 |
-
# Login/Register function
|
67 |
def auth():
|
68 |
if st.session_state.user is None:
|
69 |
st.subheader("User Authentication")
|
@@ -76,8 +77,7 @@ def auth():
|
|
76 |
login_button = st.button("Login")
|
77 |
|
78 |
if login_button:
|
79 |
-
|
80 |
-
user_data = user_df[user_df['username'] == login_username]
|
81 |
if not user_data.empty and verify_password(user_data.iloc[0]['password'], login_password):
|
82 |
st.session_state.user = login_username
|
83 |
st.session_state.user_type = user_data.iloc[0]['user_type']
|
@@ -95,18 +95,16 @@ def auth():
|
|
95 |
register_button = st.button("Register")
|
96 |
|
97 |
if register_button:
|
98 |
-
|
99 |
-
if
|
100 |
st.error("Username already exists. Please choose a different one.")
|
101 |
elif reg_password != confirm_password:
|
102 |
st.error("Passwords do not match.")
|
103 |
-
elif len(reg_password) <
|
104 |
st.error("Password must be at least 8 characters long.")
|
105 |
else:
|
106 |
hashed_password = hash_password(reg_password)
|
107 |
-
|
108 |
-
user_df = pd.concat([user_df, new_user], ignore_index=True)
|
109 |
-
save_user_data(user_df)
|
110 |
st.session_state.user = reg_username
|
111 |
st.session_state.user_type = user_type
|
112 |
st.success("Registered successfully!")
|
@@ -118,7 +116,6 @@ def auth():
|
|
118 |
st.session_state.user_type = None
|
119 |
st.rerun()
|
120 |
|
121 |
-
# Main app
|
122 |
def main():
|
123 |
st.set_page_config(page_title="Migraine Diary App", page_icon="🧠", layout="wide")
|
124 |
st.title("Migraine Diary App")
|
@@ -184,48 +181,43 @@ def add_entry():
|
|
184 |
|
185 |
submitted = st.form_submit_button("Submit Entry")
|
186 |
if submitted:
|
187 |
-
df = load_data()
|
188 |
entry_text = f"Date: {date}\nPain Level: {pain_level}\nDuration: {duration}\nTriggers: {', '.join(triggers)}\nSymptoms: {', '.join(symptoms)}\nMedications: {medications}\nNotes: {notes}"
|
189 |
|
190 |
with st.spinner("Analyzing your entry..."):
|
191 |
doctor_analysis = get_gpt_analysis(entry_text, "You are a neurologist specializing in migraine management. Provide a technical analysis of the patient's migraine diary entry, including potential correlations, patterns, and suggestions for the treating physician. Keep it short and to the point the doctor is busy.")
|
192 |
patient_advice = get_gpt_analysis(entry_text, "You are a supportive health coach specializing in migraine management. Provide friendly, easy-to-understand advice for the patient based on their migraine diary entry. Include actionable tips for managing their condition and potential lifestyle adjustments.")
|
193 |
|
194 |
-
new_entry =
|
195 |
-
'
|
196 |
-
'
|
197 |
-
'pain_level':
|
198 |
-
'duration':
|
199 |
-
'triggers':
|
200 |
-
'symptoms':
|
201 |
-
'medications':
|
202 |
-
'notes':
|
203 |
-
'doctor_analysis':
|
204 |
-
'patient_advice':
|
205 |
-
}
|
206 |
-
|
207 |
-
save_data(df)
|
208 |
st.success("Entry added successfully!")
|
209 |
st.subheader("Advice for You:")
|
210 |
st.write(patient_advice)
|
211 |
|
212 |
def view_entries(is_doctor):
|
213 |
st.header("Migraine Entries")
|
214 |
-
df = load_data()
|
215 |
if is_doctor:
|
216 |
-
user_entries =
|
217 |
st.subheader("All Patient Entries")
|
218 |
else:
|
219 |
-
user_entries =
|
220 |
-
print(st.session_state.user)
|
221 |
-
print(user_entries)
|
222 |
st.subheader("Your Entries")
|
223 |
|
224 |
-
user_entries = user_entries.sort_values(by='
|
225 |
|
226 |
if not user_entries.empty:
|
227 |
for _, entry in user_entries.iterrows():
|
228 |
-
with st.expander(f"Entry for {entry['
|
229 |
st.write(f"Duration: {entry['duration']}")
|
230 |
st.write(f"Triggers: {entry['triggers']}")
|
231 |
st.write(f"Symptoms: {entry['symptoms']}")
|
@@ -240,21 +232,21 @@ def view_entries(is_doctor):
|
|
240 |
|
241 |
def display_dashboard(is_doctor):
|
242 |
st.header("Migraine Dashboard")
|
243 |
-
df = load_data()
|
244 |
|
245 |
if is_doctor:
|
246 |
st.subheader("Select Patient")
|
247 |
-
|
248 |
-
|
|
|
249 |
else:
|
250 |
-
user_entries =
|
251 |
|
252 |
if not user_entries.empty:
|
253 |
col1, col2 = st.columns(2)
|
254 |
|
255 |
with col1:
|
256 |
st.subheader("Pain Level Over Time")
|
257 |
-
fig = px.line(user_entries, x='
|
258 |
st.plotly_chart(fig, use_container_width=True)
|
259 |
|
260 |
with col2:
|
@@ -264,14 +256,24 @@ def display_dashboard(is_doctor):
|
|
264 |
fig = px.bar(x=trigger_counts.index, y=trigger_counts.values, labels={'x': 'Trigger', 'y': 'Count'})
|
265 |
st.plotly_chart(fig, use_container_width=True)
|
266 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
267 |
st.subheader("Migraine Statistics")
|
268 |
-
col1, col2, col3 = st.columns(
|
269 |
col1.metric("Total Entries", len(user_entries))
|
270 |
col2.metric("Average Pain Level", f"{user_entries['pain_level'].mean():.2f}")
|
271 |
col3.metric("Most Common Trigger", trigger_counts.index[0] if not trigger_counts.empty else "N/A")
|
|
|
272 |
|
273 |
st.subheader("Recent Entries")
|
274 |
-
st.dataframe(user_entries[['
|
275 |
else:
|
276 |
st.info("No entries found.")
|
277 |
|
|
|
4 |
import os
|
5 |
from openai import OpenAI
|
6 |
import bcrypt
|
7 |
+
from supabase import create_client, Client
|
8 |
|
9 |
+
# Set up Supabase client
|
10 |
+
supabase_url = st.secrets["SUPABASE_URL"]
|
11 |
+
supabase_key = st.secrets["SUPABASE_KEY"]
|
12 |
+
supabase: Client = create_client(supabase_url, supabase_key)
|
13 |
+
|
14 |
+
# Set up OpenAI client
|
15 |
client = OpenAI(api_key=st.secrets["OPENAI_API_KEY"])
|
16 |
|
17 |
# Initialize session state
|
|
|
20 |
if 'user_type' not in st.session_state:
|
21 |
st.session_state.user_type = None
|
22 |
|
23 |
+
def load_data(username=None):
|
24 |
+
if username:
|
25 |
+
response = supabase.table('entries').select('*').eq('username', username).execute()
|
26 |
+
else:
|
27 |
+
response = supabase.table('entries').select('*').execute()
|
28 |
+
return pd.DataFrame(response.data)
|
|
|
|
|
|
|
|
|
29 |
|
|
|
|
|
30 |
def load_user_data():
|
31 |
+
response = supabase.table('users').select('*').execute()
|
32 |
+
return pd.DataFrame(response.data)
|
|
|
33 |
|
34 |
+
def save_data(entry):
|
35 |
+
supabase.table('entries').insert(entry).execute()
|
|
|
36 |
|
37 |
+
def save_user_data(username, hashed_password, user_type):
|
38 |
+
supabase.table('users').insert({
|
39 |
+
'username': username,
|
40 |
+
'password': hashed_password,
|
41 |
+
'user_type': user_type
|
42 |
+
}).execute()
|
43 |
+
|
44 |
+
def get_user(username):
|
45 |
+
response = supabase.table('users').select('*').eq('username', username).execute()
|
46 |
+
return pd.DataFrame(response.data)
|
47 |
|
|
|
48 |
def get_gpt_analysis(entry_text, system_prompt):
|
49 |
try:
|
50 |
response = client.chat.completions.create(
|
|
|
59 |
st.error(f"Error in GPT analysis: {str(e)}")
|
60 |
return "Analysis unavailable at this time."
|
61 |
|
|
|
62 |
def hash_password(password):
|
63 |
return bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
|
64 |
|
|
|
65 |
def verify_password(stored_password, provided_password):
|
66 |
return bcrypt.checkpw(provided_password.encode('utf-8'), stored_password.encode('utf-8'))
|
67 |
|
|
|
68 |
def auth():
|
69 |
if st.session_state.user is None:
|
70 |
st.subheader("User Authentication")
|
|
|
77 |
login_button = st.button("Login")
|
78 |
|
79 |
if login_button:
|
80 |
+
user_data = get_user(login_username)
|
|
|
81 |
if not user_data.empty and verify_password(user_data.iloc[0]['password'], login_password):
|
82 |
st.session_state.user = login_username
|
83 |
st.session_state.user_type = user_data.iloc[0]['user_type']
|
|
|
95 |
register_button = st.button("Register")
|
96 |
|
97 |
if register_button:
|
98 |
+
existing_user = get_user(reg_username)
|
99 |
+
if not existing_user.empty:
|
100 |
st.error("Username already exists. Please choose a different one.")
|
101 |
elif reg_password != confirm_password:
|
102 |
st.error("Passwords do not match.")
|
103 |
+
elif len(reg_password) < 8:
|
104 |
st.error("Password must be at least 8 characters long.")
|
105 |
else:
|
106 |
hashed_password = hash_password(reg_password)
|
107 |
+
save_user_data(reg_username, hashed_password, user_type)
|
|
|
|
|
108 |
st.session_state.user = reg_username
|
109 |
st.session_state.user_type = user_type
|
110 |
st.success("Registered successfully!")
|
|
|
116 |
st.session_state.user_type = None
|
117 |
st.rerun()
|
118 |
|
|
|
119 |
def main():
|
120 |
st.set_page_config(page_title="Migraine Diary App", page_icon="🧠", layout="wide")
|
121 |
st.title("Migraine Diary App")
|
|
|
181 |
|
182 |
submitted = st.form_submit_button("Submit Entry")
|
183 |
if submitted:
|
|
|
184 |
entry_text = f"Date: {date}\nPain Level: {pain_level}\nDuration: {duration}\nTriggers: {', '.join(triggers)}\nSymptoms: {', '.join(symptoms)}\nMedications: {medications}\nNotes: {notes}"
|
185 |
|
186 |
with st.spinner("Analyzing your entry..."):
|
187 |
doctor_analysis = get_gpt_analysis(entry_text, "You are a neurologist specializing in migraine management. Provide a technical analysis of the patient's migraine diary entry, including potential correlations, patterns, and suggestions for the treating physician. Keep it short and to the point the doctor is busy.")
|
188 |
patient_advice = get_gpt_analysis(entry_text, "You are a supportive health coach specializing in migraine management. Provide friendly, easy-to-understand advice for the patient based on their migraine diary entry. Include actionable tips for managing their condition and potential lifestyle adjustments.")
|
189 |
|
190 |
+
new_entry = {
|
191 |
+
'username': st.session_state.user,
|
192 |
+
'entry_date': date.isoformat(),
|
193 |
+
'pain_level': pain_level,
|
194 |
+
'duration': duration,
|
195 |
+
'triggers': ', '.join(triggers),
|
196 |
+
'symptoms': ', '.join(symptoms),
|
197 |
+
'medications': medications,
|
198 |
+
'notes': notes,
|
199 |
+
'doctor_analysis': doctor_analysis,
|
200 |
+
'patient_advice': patient_advice
|
201 |
+
}
|
202 |
+
save_data(new_entry)
|
|
|
203 |
st.success("Entry added successfully!")
|
204 |
st.subheader("Advice for You:")
|
205 |
st.write(patient_advice)
|
206 |
|
207 |
def view_entries(is_doctor):
|
208 |
st.header("Migraine Entries")
|
|
|
209 |
if is_doctor:
|
210 |
+
user_entries = load_data()
|
211 |
st.subheader("All Patient Entries")
|
212 |
else:
|
213 |
+
user_entries = load_data(st.session_state.user)
|
|
|
|
|
214 |
st.subheader("Your Entries")
|
215 |
|
216 |
+
user_entries = user_entries.sort_values(by='entry_date', ascending=False)
|
217 |
|
218 |
if not user_entries.empty:
|
219 |
for _, entry in user_entries.iterrows():
|
220 |
+
with st.expander(f"Entry for {entry['username']} on {entry['entry_date']} - Pain Level: {entry['pain_level']}"):
|
221 |
st.write(f"Duration: {entry['duration']}")
|
222 |
st.write(f"Triggers: {entry['triggers']}")
|
223 |
st.write(f"Symptoms: {entry['symptoms']}")
|
|
|
232 |
|
233 |
def display_dashboard(is_doctor):
|
234 |
st.header("Migraine Dashboard")
|
|
|
235 |
|
236 |
if is_doctor:
|
237 |
st.subheader("Select Patient")
|
238 |
+
all_users = load_data()['username'].unique()
|
239 |
+
selected_user = st.selectbox("Choose a patient", all_users)
|
240 |
+
user_entries = load_data(selected_user)
|
241 |
else:
|
242 |
+
user_entries = load_data(st.session_state.user)
|
243 |
|
244 |
if not user_entries.empty:
|
245 |
col1, col2 = st.columns(2)
|
246 |
|
247 |
with col1:
|
248 |
st.subheader("Pain Level Over Time")
|
249 |
+
fig = px.line(user_entries, x='entry_date', y='pain_level', title='Pain Level Over Time')
|
250 |
st.plotly_chart(fig, use_container_width=True)
|
251 |
|
252 |
with col2:
|
|
|
256 |
fig = px.bar(x=trigger_counts.index, y=trigger_counts.values, labels={'x': 'Trigger', 'y': 'Count'})
|
257 |
st.plotly_chart(fig, use_container_width=True)
|
258 |
|
259 |
+
col1, col2 = st.columns(2)
|
260 |
+
|
261 |
+
with col1:
|
262 |
+
st.subheader("Common Symptoms")
|
263 |
+
all_symptoms = ', '.join(user_entries['symptoms'].dropna()).split(', ')
|
264 |
+
symptom_counts = pd.Series(all_symptoms).value_counts().head(5)
|
265 |
+
fig = px.bar(x=symptom_counts.index, y=symptom_counts.values, labels={'x': 'Symptom', 'y': 'Count'})
|
266 |
+
st.plotly_chart(fig, use_container_width=True)
|
267 |
+
|
268 |
st.subheader("Migraine Statistics")
|
269 |
+
col1, col2, col3, col4 = st.columns(4)
|
270 |
col1.metric("Total Entries", len(user_entries))
|
271 |
col2.metric("Average Pain Level", f"{user_entries['pain_level'].mean():.2f}")
|
272 |
col3.metric("Most Common Trigger", trigger_counts.index[0] if not trigger_counts.empty else "N/A")
|
273 |
+
col4.metric("Most Common Symptom", symptom_counts.index[0] if not symptom_counts.empty else "N/A")
|
274 |
|
275 |
st.subheader("Recent Entries")
|
276 |
+
st.dataframe(user_entries[['entry_date', 'pain_level', 'duration', 'triggers', 'symptoms']].sort_values(by='entry_date', ascending=False).head())
|
277 |
else:
|
278 |
st.info("No entries found.")
|
279 |
|