Skip to content

Commit 2fa8d29

Browse files
minor fixes only
1 parent 5e71128 commit 2fa8d29

2 files changed

Lines changed: 107 additions & 55 deletions

File tree

backend/main.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,13 @@ def history():
103103
async def get_dataset():
104104
data_path = '/app/data/patient_dataset.csv' if os.path.exists('/app/data') else '../data/patient_dataset.csv' if os.path.exists('../data') else 'data/patient_dataset.csv'
105105
if os.path.exists(data_path):
106-
df = pd.read_csv(data_path)
107-
# Return summary or partial data to avoid huge payloads
108-
return df.to_dict(orient="records")
106+
try:
107+
# Force UTF-8 and strip column whitespace
108+
df = pd.read_csv(data_path, encoding='utf-8')
109+
df.columns = [c.strip() for c in df.columns]
110+
return df.to_dict(orient="records")
111+
except Exception as e:
112+
return {"error": f"Failed to read dataset: {str(e)}"}
109113
return {"error": "Dataset not found"}
110114

111115
@app.get("/sync")

frontend/pages/2_Data_Analytics.py

Lines changed: 100 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,12 @@ def load_data():
2020
if resp.status_code == 200:
2121
data = resp.json()
2222
if isinstance(data, list):
23-
return pd.DataFrame(data)
23+
df = pd.DataFrame(data)
24+
# Normalize column names: strip whitespace and ensure common naming
25+
df.columns = [c.strip() for c in df.columns]
26+
# Fix common encoding issues for temperature
27+
df.columns = [c.replace('°C', '°C') for c in df.columns]
28+
return df
2429
st.error(f"Backend Error: {data.get('error', 'Unknown')}")
2530
except Exception as e:
2631
st.error(f"Failed to connect to backend: {e}")
@@ -42,14 +47,34 @@ def load_data():
4247
df = full_df
4348
st.success(f"Loaded **{len(full_df):,}** patient records from backend.")
4449

45-
# ... rest of the file stays same ...
50+
# ── Safety Check for Column Names ──
51+
available_cols = df.columns.tolist()
52+
target_x = "Predicted Disease"
53+
54+
if target_x not in available_cols:
55+
# Fallback to similar name if exact match fails
56+
matches = [c for c in available_cols if "Disease" in c or "Condition" in c]
57+
if matches:
58+
target_x = matches[0]
59+
else:
60+
st.error(f"Required column '{target_x}' missing from dataset. Found: {available_cols}")
61+
st.stop()
62+
4663
st.markdown("### 🫀 Vital Signs Distribution by Condition")
47-
vitals = ["Heart Rate (bpm)", "SpO2 Level (%)", "Systolic Blood Pressure (mmHg)", "Diastolic Blood Pressure (mmHg)", "Body Temperature (°C)"]
64+
65+
# Define possible vitals and filter by what's actually in the DF
66+
vitals_all = ["Heart Rate (bpm)", "SpO2 Level (%)", "Systolic Blood Pressure (mmHg)", "Diastolic Blood Pressure (mmHg)", "Body Temperature (°C)"]
67+
vitals = [v for v in vitals_all if v in available_cols]
68+
69+
if not vitals:
70+
st.error(f"No clinical vital sign columns found in dataset. Found: {available_cols}")
71+
st.stop()
72+
4873
selected_vital = st.selectbox("Select Vital Sign", vitals)
4974

5075
fig_box = px.box(
51-
df, x="Predicted Disease", y=selected_vital,
52-
color="Predicted Disease",
76+
df, x=target_x, y=selected_vital,
77+
color=target_x,
5378
color_discrete_map=DISEASE_COLORS,
5479
title=f"{selected_vital} Distribution Across Conditions",
5580
template="plotly_dark",
@@ -67,44 +92,56 @@ def load_data():
6792
c1, c2 = st.columns(2)
6893
with c1:
6994
st.markdown("##### Heart Rate vs SpO2 (Scatter Matrix)")
70-
fig_scatter = px.scatter(
71-
df, x="Heart Rate (bpm)", y="SpO2 Level (%)",
72-
color="Predicted Disease",
73-
color_discrete_map=DISEASE_COLORS,
74-
opacity=0.4, size_max=6,
75-
title="Heart Rate vs SpO2 Levels",
76-
template="plotly_dark",
77-
marginal_x="histogram",
78-
marginal_y="histogram"
79-
)
80-
fig_scatter.update_layout(
81-
paper_bgcolor='rgba(0,0,0,0)', plot_bgcolor='rgba(0,0,0,0)',
82-
height=450, legend=dict(orientation="h", yanchor="bottom", y=-0.35)
83-
)
84-
st.plotly_chart(fig_scatter, use_container_width=True)
95+
# Safety check for scatter columns
96+
x_scatter = "Heart Rate (bpm)" if "Heart Rate (bpm)" in available_cols else None
97+
y_scatter = "SpO2 Level (%)" if "SpO2 Level (%)" in available_cols else None
98+
99+
if x_scatter and y_scatter:
100+
fig_scatter = px.scatter(
101+
df, x=x_scatter, y=y_scatter,
102+
color=target_x,
103+
color_discrete_map=DISEASE_COLORS,
104+
opacity=0.4, size_max=6,
105+
title="Heart Rate vs SpO2 Levels",
106+
template="plotly_dark",
107+
marginal_x="histogram",
108+
marginal_y="histogram"
109+
)
110+
fig_scatter.update_layout(
111+
paper_bgcolor='rgba(0,0,0,0)', plot_bgcolor='rgba(0,0,0,0)',
112+
height=450, legend=dict(orientation="h", yanchor="bottom", y=-0.35)
113+
)
114+
st.plotly_chart(fig_scatter, use_container_width=True)
115+
else:
116+
st.warning("Scatter plot unavailable: Required columns missing.")
85117

86118
with c2:
87119
st.markdown("##### Temperature by Condition (Violin Plot)")
88-
fig_violin = px.violin(
89-
df, x="Predicted Disease", y="Body Temperature (°C)",
90-
color="Predicted Disease",
91-
color_discrete_map=DISEASE_COLORS,
92-
box=True, points=False,
93-
title="Body Temperature Distribution",
94-
template="plotly_dark"
95-
)
96-
fig_violin.update_layout(
97-
paper_bgcolor='rgba(0,0,0,0)', plot_bgcolor='rgba(0,0,0,0)',
98-
height=450, showlegend=False, xaxis_title="Condition", yaxis_title="Temperature (°C)"
99-
)
100-
st.plotly_chart(fig_violin, use_container_width=True)
120+
y_violin = "Body Temperature (°C)" if "Body Temperature (°C)" in available_cols else None
121+
122+
if y_violin:
123+
fig_violin = px.violin(
124+
df, x=target_x, y=y_violin,
125+
color=target_x,
126+
color_discrete_map=DISEASE_COLORS,
127+
box=True, points=False,
128+
title="Body Temperature Distribution",
129+
template="plotly_dark"
130+
)
131+
fig_violin.update_layout(
132+
paper_bgcolor='rgba(0,0,0,0)', plot_bgcolor='rgba(0,0,0,0)',
133+
height=450, showlegend=False, xaxis_title="Condition", yaxis_title="Temperature (°C)"
134+
)
135+
st.plotly_chart(fig_violin, use_container_width=True)
136+
else:
137+
st.warning("Violin plot unavailable: Temperature column missing.")
101138

102139
st.markdown("---")
103140

104141
c3, c4 = st.columns(2)
105142
with c3:
106143
st.markdown("##### 🏥 Disease Distribution (Population Count)")
107-
counts = df["Predicted Disease"].value_counts().reset_index()
144+
counts = df[target_x].value_counts().reset_index()
108145
counts.columns = ["Condition", "Patient Count"]
109146
fig_bar = px.bar(
110147
counts, x="Condition", y="Patient Count",
@@ -123,33 +160,44 @@ def load_data():
123160

124161
with c4:
125162
st.markdown("##### 🩸 Blood Pressure Density (Systolic vs Diastolic)")
126-
fig_density = px.density_heatmap(
127-
df, x="Systolic Blood Pressure (mmHg)", y="Diastolic Blood Pressure (mmHg)",
128-
color_continuous_scale="Turbo",
129-
title="Blood Pressure Population Heatmap",
130-
template="plotly_dark",
131-
nbinsx=30, nbinsy=30
132-
)
133-
fig_density.update_layout(
134-
paper_bgcolor='rgba(0,0,0,0)', plot_bgcolor='rgba(0,0,0,0)',
135-
height=420
136-
)
137-
st.plotly_chart(fig_density, use_container_width=True)
163+
x_heat = "Systolic Blood Pressure (mmHg)" if "Systolic Blood Pressure (mmHg)" in available_cols else None
164+
y_heat = "Diastolic Blood Pressure (mmHg)" if "Diastolic Blood Pressure (mmHg)" in available_cols else None
165+
166+
if x_heat and y_heat:
167+
fig_density = px.density_heatmap(
168+
df, x=x_heat, y=y_heat,
169+
color_continuous_scale="Turbo",
170+
title="Blood Pressure Population Heatmap",
171+
template="plotly_dark",
172+
nbinsx=30, nbinsy=30
173+
)
174+
fig_density.update_layout(
175+
paper_bgcolor='rgba(0,0,0,0)', plot_bgcolor='rgba(0,0,0,0)',
176+
height=420
177+
)
178+
st.plotly_chart(fig_density, use_container_width=True)
179+
else:
180+
st.warning("Density heatmap unavailable: Blood Pressure columns missing.")
138181

139182
st.markdown("---")
140183
st.markdown("### 📈 Patient-Specific Real-Time Monitoring")
141-
p_id = st.selectbox("Select Patient ID to view live telemetry:", df['Patient Number'].unique()[:50])
184+
# Use Patient Number if available
185+
id_col = "Patient Number" if "Patient Number" in available_cols else available_cols[0]
186+
p_id = st.selectbox("Select Patient ID to view live telemetry:", df[id_col].unique()[:50])
187+
142188
if p_id:
143-
patient_data = df[df['Patient Number'] == p_id].iloc[0]
144-
disease = patient_data['Predicted Disease']
189+
patient_data = df[df[id_col] == p_id].iloc[0]
190+
disease = patient_data[target_x]
145191
d_color = DISEASE_COLORS.get(disease, "#636efa")
146192
st.markdown(f"**Patient Condition:** <span style='color:{d_color}; font-weight:bold'>{disease}</span>", unsafe_allow_html=True)
147193

148194
periods = 60
149195
dates = pd.date_range(end=pd.Timestamp.now(), periods=periods, freq='25s')
150-
base_hr = patient_data['Heart Rate (bpm)']
151-
base_spo2 = patient_data['SpO2 Level (%)']
152-
base_temp = patient_data['Body Temperature (°C)']
196+
197+
# Safe access for real-time emulation
198+
base_hr = patient_data.get('Heart Rate (bpm)', 75)
199+
base_spo2 = patient_data.get('SpO2 Level (%)', 98)
200+
base_temp = patient_data.get('Body Temperature (°C)', 37.0)
153201
sim_hr = base_hr + np.random.normal(0, 1.2, periods).cumsum()
154202
sim_spo2 = np.clip(base_spo2 + np.random.normal(0, 0.3, periods).cumsum(), 85, 100)
155203
sim_temp = base_temp + np.random.normal(0, 0.05, periods).cumsum()

0 commit comments

Comments
 (0)