Upload folder using huggingface_hub
Browse files- home.py +8 -1
- modules/db.py +38 -8
- plot_helper.py +16 -3
- ui.py +1 -1
home.py
CHANGED
|
@@ -574,6 +574,7 @@ def build_home_page(
|
|
| 574 |
label="Date",
|
| 575 |
include_time=False,
|
| 576 |
type="datetime",
|
|
|
|
| 577 |
)
|
| 578 |
vitals_height = gr.Number(label="Height (cm)")
|
| 579 |
vitals_weight = gr.Number(label="Weight (kg)")
|
|
@@ -601,6 +602,8 @@ def build_home_page(
|
|
| 601 |
)
|
| 602 |
save_vitals_status = gr.Markdown()
|
| 603 |
# Latest Vitals
|
|
|
|
|
|
|
| 604 |
with gr.Row():
|
| 605 |
latest_vitals_cards = [
|
| 606 |
gr.Label(visible=False) for _ in range(20)
|
|
@@ -608,6 +611,8 @@ def build_home_page(
|
|
| 608 |
with gr.Row():
|
| 609 |
# Historical Vitals
|
| 610 |
with gr.Column(scale=1):
|
|
|
|
|
|
|
| 611 |
vitals_df = gr.DataFrame(
|
| 612 |
headers=[
|
| 613 |
"Date",
|
|
@@ -619,6 +624,8 @@ def build_home_page(
|
|
| 619 |
interactive=False,
|
| 620 |
)
|
| 621 |
with gr.Column(scale=2):
|
|
|
|
|
|
|
| 622 |
vitals_plots = []
|
| 623 |
rows = math.ceil(
|
| 624 |
20 / 2
|
|
@@ -1012,7 +1019,7 @@ def build_home_page(
|
|
| 1012 |
*latest_vitals_cards,
|
| 1013 |
*vitals_plots,
|
| 1014 |
],
|
| 1015 |
-
)
|
| 1016 |
|
| 1017 |
# open modal and set states
|
| 1018 |
def show_upload_reports_modal(user_email, patient_id):
|
|
|
|
| 574 |
label="Date",
|
| 575 |
include_time=False,
|
| 576 |
type="datetime",
|
| 577 |
+
interactive=True,
|
| 578 |
)
|
| 579 |
vitals_height = gr.Number(label="Height (cm)")
|
| 580 |
vitals_weight = gr.Number(label="Weight (kg)")
|
|
|
|
| 602 |
)
|
| 603 |
save_vitals_status = gr.Markdown()
|
| 604 |
# Latest Vitals
|
| 605 |
+
gr.Markdown("## Vitals - Latest")
|
| 606 |
+
gr.Markdown("---")
|
| 607 |
with gr.Row():
|
| 608 |
latest_vitals_cards = [
|
| 609 |
gr.Label(visible=False) for _ in range(20)
|
|
|
|
| 611 |
with gr.Row():
|
| 612 |
# Historical Vitals
|
| 613 |
with gr.Column(scale=1):
|
| 614 |
+
gr.Markdown("## Vitals - History")
|
| 615 |
+
gr.Markdown("---")
|
| 616 |
vitals_df = gr.DataFrame(
|
| 617 |
headers=[
|
| 618 |
"Date",
|
|
|
|
| 624 |
interactive=False,
|
| 625 |
)
|
| 626 |
with gr.Column(scale=2):
|
| 627 |
+
gr.Markdown("## Vitals - Trends")
|
| 628 |
+
gr.Markdown("---")
|
| 629 |
vitals_plots = []
|
| 630 |
rows = math.ceil(
|
| 631 |
20 / 2
|
|
|
|
| 1019 |
*latest_vitals_cards,
|
| 1020 |
*vitals_plots,
|
| 1021 |
],
|
| 1022 |
+
).then(enable_component, outputs=save_vitals_btn)
|
| 1023 |
|
| 1024 |
# open modal and set states
|
| 1025 |
def show_upload_reports_modal(user_email, patient_id):
|
modules/db.py
CHANGED
|
@@ -742,7 +742,7 @@ class SheamiDB:
|
|
| 742 |
vitals = {}
|
| 743 |
return vitals
|
| 744 |
|
| 745 |
-
async def get_vitals_trends_by_patient(self,patient_id):
|
| 746 |
docs = await self.vitals.aggregate([
|
| 747 |
{"$match": {"patient_id": ObjectId(patient_id)}},
|
| 748 |
{"$unwind": "$readings"},
|
|
@@ -757,13 +757,43 @@ class SheamiDB:
|
|
| 757 |
|
| 758 |
df = pd.DataFrame(docs)
|
| 759 |
trend_docs = []
|
|
|
|
| 760 |
if "name" in df:
|
| 761 |
for vital_name, group in df.groupby("name"):
|
| 762 |
-
|
| 763 |
-
|
| 764 |
-
|
| 765 |
-
|
| 766 |
-
|
| 767 |
-
|
| 768 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 769 |
return trend_docs
|
|
|
|
| 742 |
vitals = {}
|
| 743 |
return vitals
|
| 744 |
|
| 745 |
+
async def get_vitals_trends_by_patient(self, patient_id):
|
| 746 |
docs = await self.vitals.aggregate([
|
| 747 |
{"$match": {"patient_id": ObjectId(patient_id)}},
|
| 748 |
{"$unwind": "$readings"},
|
|
|
|
| 757 |
|
| 758 |
df = pd.DataFrame(docs)
|
| 759 |
trend_docs = []
|
| 760 |
+
|
| 761 |
if "name" in df:
|
| 762 |
for vital_name, group in df.groupby("name"):
|
| 763 |
+
if vital_name.lower() in ["bp", "blood pressure"]:
|
| 764 |
+
# Split systolic/diastolic
|
| 765 |
+
systolic, diastolic = [], []
|
| 766 |
+
for _, row in group.iterrows():
|
| 767 |
+
try:
|
| 768 |
+
sys, dia = row["value"].split("/")
|
| 769 |
+
systolic.append({"date": row["date"], "value": int(sys)})
|
| 770 |
+
diastolic.append({"date": row["date"], "value": int(dia)})
|
| 771 |
+
except Exception:
|
| 772 |
+
continue
|
| 773 |
+
|
| 774 |
+
# Append as two separate test series
|
| 775 |
+
trend_docs.append({
|
| 776 |
+
"test_name": "BP - Systolic",
|
| 777 |
+
"trend_data": systolic,
|
| 778 |
+
"unit": "mmHg",
|
| 779 |
+
"test_reference_range": {}
|
| 780 |
+
})
|
| 781 |
+
trend_docs.append({
|
| 782 |
+
"test_name": "BP - Diastolic",
|
| 783 |
+
"trend_data": diastolic,
|
| 784 |
+
"unit": "mmHg",
|
| 785 |
+
"test_reference_range": {}
|
| 786 |
+
})
|
| 787 |
+
else:
|
| 788 |
+
# Other vitals
|
| 789 |
+
trend_docs.append({
|
| 790 |
+
"test_name": vital_name,
|
| 791 |
+
"trend_data": group[["date", "value"]].to_dict("records"),
|
| 792 |
+
"unit": group["unit"].iloc[0],
|
| 793 |
+
"test_reference_range": {}
|
| 794 |
+
})
|
| 795 |
+
|
| 796 |
+
# 🔑 Sort by test_name so BP series appear together
|
| 797 |
+
trend_docs = sorted(trend_docs, key=lambda x: x["test_name"])
|
| 798 |
+
|
| 799 |
return trend_docs
|
plot_helper.py
CHANGED
|
@@ -108,7 +108,9 @@ def build_trend_figure(trend_doc: Dict[str, Any]) -> Figure:
|
|
| 108 |
title=f"{trend_doc.get('test_name','')}",
|
| 109 |
)
|
| 110 |
fig.update_yaxes(autorange=True)
|
| 111 |
-
fig.update_xaxes(
|
|
|
|
|
|
|
| 112 |
return sanitize_plotly_figure(fig)
|
| 113 |
|
| 114 |
|
|
@@ -167,7 +169,13 @@ async def reset_trends():
|
|
| 167 |
page = 0
|
| 168 |
page_info = "Page 0 / 0"
|
| 169 |
|
| 170 |
-
return (
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 171 |
|
| 172 |
|
| 173 |
def _to_jsonable_dt(x):
|
|
@@ -234,4 +242,9 @@ async def render_vitals_plot_layout(patient_id):
|
|
| 234 |
margin=dict(l=30, r=20, t=40, b=30),
|
| 235 |
)
|
| 236 |
figures.append(empty_fig)
|
| 237 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 108 |
title=f"{trend_doc.get('test_name','')}",
|
| 109 |
)
|
| 110 |
fig.update_yaxes(autorange=True)
|
| 111 |
+
fig.update_xaxes(
|
| 112 |
+
autorange=True, tickformat="%Y-%m-%d", tickangle=-45, tickmode="auto"
|
| 113 |
+
)
|
| 114 |
return sanitize_plotly_figure(fig)
|
| 115 |
|
| 116 |
|
|
|
|
| 169 |
page = 0
|
| 170 |
page_info = "Page 0 / 0"
|
| 171 |
|
| 172 |
+
return (
|
| 173 |
+
*outputs,
|
| 174 |
+
page,
|
| 175 |
+
page_info,
|
| 176 |
+
gr.update(interactive=False),
|
| 177 |
+
gr.update(interactive=False),
|
| 178 |
+
)
|
| 179 |
|
| 180 |
|
| 181 |
def _to_jsonable_dt(x):
|
|
|
|
| 242 |
margin=dict(l=30, r=20, t=40, b=30),
|
| 243 |
)
|
| 244 |
figures.append(empty_fig)
|
| 245 |
+
|
| 246 |
+
plots = []
|
| 247 |
+
for fig in figures:
|
| 248 |
+
plots.append(gr.Plot(value=fig, label=fig.layout.title.text))
|
| 249 |
+
fig.update_layout(title=None)
|
| 250 |
+
return plots
|
ui.py
CHANGED
|
@@ -825,7 +825,7 @@ async def save_vitals_readings(
|
|
| 825 |
)
|
| 826 |
|
| 827 |
await get_db().save_readings_to_db(
|
| 828 |
-
patient_id, reading_date
|
| 829 |
)
|
| 830 |
# TODO: call AI here to attach personalized ranges + status
|
| 831 |
# For now, just return the raw readings
|
|
|
|
| 825 |
)
|
| 826 |
|
| 827 |
await get_db().save_readings_to_db(
|
| 828 |
+
patient_id, reading_date, readings, "some_user"
|
| 829 |
)
|
| 830 |
# TODO: call AI here to attach personalized ranges + status
|
| 831 |
# For now, just return the raw readings
|