vikramvasudevan commited on
Commit
e77038b
·
verified ·
1 Parent(s): fa47807

Upload folder using huggingface_hub

Browse files
Files changed (4) hide show
  1. home.py +45 -9
  2. modules/db.py +27 -1
  3. plot_helper.py +21 -1
  4. ui.py +1 -1
home.py CHANGED
@@ -26,6 +26,7 @@ from plot_helper import (
26
  MAX_CHARTS_IN_PAGE,
27
  NUM_COLS,
28
  build_trend_figure,
 
29
  reset_trends,
30
  update_trends,
31
  )
@@ -278,7 +279,7 @@ def format_patient_info(patient):
278
 
279
  async def load_patient_bundle(
280
  patient_id: str,
281
- ) -> Tuple[pd.DataFrame, List[str], Dict[str, Any], List[Dict[str, Any]]]:
282
  """
283
  Given patient_id, return:
284
  - reports_df
@@ -286,7 +287,9 @@ async def load_patient_bundle(
286
  - meta dict with patient basics
287
  - final_reports list
288
  - run_stats list
289
- - vitals
 
 
290
  """
291
  if not patient_id:
292
  return pd.DataFrame(), [], {}, []
@@ -302,6 +305,7 @@ async def load_patient_bundle(
302
  run_stats = await db.get_run_stats_by_patient(patient_id)
303
  latest_vitals = await render_latest_vitals_card_layout(patient_id)
304
  vitals_history = await db.get_vitals_by_patient(patient_id)
 
305
 
306
  reports_df = flatten_reports_v2(reports)
307
  test_names = trends_index(trends)
@@ -322,6 +326,7 @@ async def load_patient_bundle(
322
  run_stats,
323
  vitals_history,
324
  latest_vitals,
 
325
  )
326
 
327
 
@@ -605,18 +610,39 @@ def build_home_page(
605
  label="Unit", placeholder="e.g., bpm, cm"
606
  )
607
 
608
- save_vitals_btn = gr.Button("Save Readings", variant="huggingface", scale=0)
 
 
609
  save_vitals_status = gr.Markdown()
610
  # Latest Vitals
611
  with gr.Row():
612
  latest_vitals_cards = [
613
  gr.Label(visible=False) for _ in range(20)
614
  ]
615
- # Historical Vitals
616
- vitals_df = gr.DataFrame(
617
- headers=["Date", "Name", "Value", "Unit", "AI Status"],
618
- interactive=False,
619
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
620
  with gr.Tab("🧪 Tests", id=2):
621
  reports_df = gr.DataFrame(
622
  headers=[
@@ -794,6 +820,7 @@ def build_home_page(
794
  run_stats,
795
  vitals_history,
796
  latest_vitals,
 
797
  ) = await load_patient_bundle(patient_id)
798
  (*trends, page, page_info, prev_btn, next_btn) = await update_trends(
799
  patient_id=patient_id, page=0, num_cols=NUM_COLS
@@ -815,6 +842,7 @@ def build_home_page(
815
  value=flatten_vitals(vitals_history),
816
  ),
817
  *latest_vitals,
 
818
  *trends,
819
  page,
820
  page_info,
@@ -841,6 +869,7 @@ def build_home_page(
841
  value=[],
842
  ),
843
  gr.update(),
 
844
  *trends,
845
  page,
846
  page_info,
@@ -895,6 +924,7 @@ def build_home_page(
895
  run_stats_df,
896
  vitals_df,
897
  *latest_vitals_cards,
 
898
  *chart_outputs,
899
  current_page,
900
  page_info,
@@ -990,7 +1020,12 @@ def build_home_page(
990
  vitals_custom_value,
991
  vitals_custom_unit,
992
  ],
993
- outputs=[save_vitals_status, vitals_df, *latest_vitals_cards],
 
 
 
 
 
994
  )
995
 
996
  # open modal and set states
@@ -1019,6 +1054,7 @@ def build_home_page(
1019
  run_stats_df,
1020
  vitals_df,
1021
  *latest_vitals_cards,
 
1022
  *chart_outputs,
1023
  current_page,
1024
  page_info,
 
26
  MAX_CHARTS_IN_PAGE,
27
  NUM_COLS,
28
  build_trend_figure,
29
+ render_vitals_plot_layout,
30
  reset_trends,
31
  update_trends,
32
  )
 
279
 
280
  async def load_patient_bundle(
281
  patient_id: str,
282
+ ):
283
  """
284
  Given patient_id, return:
285
  - reports_df
 
287
  - meta dict with patient basics
288
  - final_reports list
289
  - run_stats list
290
+ - vitals history
291
+ - latest vitals
292
+ - vitals plots
293
  """
294
  if not patient_id:
295
  return pd.DataFrame(), [], {}, []
 
305
  run_stats = await db.get_run_stats_by_patient(patient_id)
306
  latest_vitals = await render_latest_vitals_card_layout(patient_id)
307
  vitals_history = await db.get_vitals_by_patient(patient_id)
308
+ vitals_plots = await render_vitals_plot_layout(patient_id)
309
 
310
  reports_df = flatten_reports_v2(reports)
311
  test_names = trends_index(trends)
 
326
  run_stats,
327
  vitals_history,
328
  latest_vitals,
329
+ vitals_plots,
330
  )
331
 
332
 
 
610
  label="Unit", placeholder="e.g., bpm, cm"
611
  )
612
 
613
+ save_vitals_btn = gr.Button(
614
+ "Save Readings", variant="huggingface", scale=0
615
+ )
616
  save_vitals_status = gr.Markdown()
617
  # Latest Vitals
618
  with gr.Row():
619
  latest_vitals_cards = [
620
  gr.Label(visible=False) for _ in range(20)
621
  ]
622
+ with gr.Row():
623
+ # Historical Vitals
624
+ with gr.Column(scale=1):
625
+ vitals_df = gr.DataFrame(
626
+ headers=[
627
+ "Date",
628
+ "Name",
629
+ "Value",
630
+ "Unit",
631
+ "AI Status",
632
+ ],
633
+ interactive=False,
634
+ )
635
+ with gr.Column(scale=2):
636
+ vitals_plots = []
637
+ rows = math.ceil(
638
+ 20 / 2
639
+ ) # default num_cols_per_row columns per row
640
+ for r in range(rows):
641
+ with gr.Row():
642
+ for c in range(
643
+ 2
644
+ ): # num_cols_per_row cols per row
645
+ vitals_plots.append(gr.Plot(visible=True))
646
  with gr.Tab("🧪 Tests", id=2):
647
  reports_df = gr.DataFrame(
648
  headers=[
 
820
  run_stats,
821
  vitals_history,
822
  latest_vitals,
823
+ vitals_plots,
824
  ) = await load_patient_bundle(patient_id)
825
  (*trends, page, page_info, prev_btn, next_btn) = await update_trends(
826
  patient_id=patient_id, page=0, num_cols=NUM_COLS
 
842
  value=flatten_vitals(vitals_history),
843
  ),
844
  *latest_vitals,
845
+ *vitals_plots,
846
  *trends,
847
  page,
848
  page_info,
 
869
  value=[],
870
  ),
871
  gr.update(),
872
+ gr.update(),
873
  *trends,
874
  page,
875
  page_info,
 
924
  run_stats_df,
925
  vitals_df,
926
  *latest_vitals_cards,
927
+ *vitals_plots,
928
  *chart_outputs,
929
  current_page,
930
  page_info,
 
1020
  vitals_custom_value,
1021
  vitals_custom_unit,
1022
  ],
1023
+ outputs=[
1024
+ save_vitals_status,
1025
+ vitals_df,
1026
+ *latest_vitals_cards,
1027
+ *vitals_plots,
1028
+ ],
1029
  )
1030
 
1031
  # open modal and set states
 
1054
  run_stats_df,
1055
  vitals_df,
1056
  *latest_vitals_cards,
1057
+ *vitals_plots,
1058
  *chart_outputs,
1059
  current_page,
1060
  page_info,
modules/db.py CHANGED
@@ -10,7 +10,7 @@ from motor.motor_asyncio import AsyncIOMotorGridFSBucket
10
  from motor.motor_asyncio import AsyncIOMotorClient, AsyncIOMotorGridFSBucket
11
  import os
12
  from dotenv import load_dotenv
13
-
14
 
15
  class SheamiDB:
16
  def __init__(self, uri: str = None, db_name: str = "sheami"):
@@ -741,3 +741,29 @@ class SheamiDB:
741
  else:
742
  vitals = {}
743
  return vitals
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  from motor.motor_asyncio import AsyncIOMotorClient, AsyncIOMotorGridFSBucket
11
  import os
12
  from dotenv import load_dotenv
13
+ import pandas as pd
14
 
15
  class SheamiDB:
16
  def __init__(self, uri: str = None, db_name: str = "sheami"):
 
741
  else:
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"},
749
+ {"$project": {
750
+ "date": 1,
751
+ "name": "$readings.name",
752
+ "value": "$readings.value",
753
+ "unit": "$readings.unit"
754
+ }},
755
+ {"$sort": {"date": 1}}
756
+ ]).to_list(length=None)
757
+
758
+ df = pd.DataFrame(docs)
759
+ trend_docs = []
760
+ if "name" in df:
761
+ for vital_name, group in df.groupby("name"):
762
+ trend_docs.append({
763
+ "test_name": vital_name,
764
+ "trend_data": group[["date", "value"]].to_dict("records"),
765
+ "unit": group["unit"].iloc[0], # assume consistent unit
766
+ # TODO: optional: enrich with AI-based reference ranges
767
+ "test_reference_range": {}
768
+ })
769
+ return trend_docs
plot_helper.py CHANGED
@@ -7,6 +7,7 @@ import numpy as np
7
  import pandas as pd
8
  from common import get_db
9
  from ui import disable_component
 
10
 
11
  MAX_CHARTS_IN_PAGE = 40
12
  NUM_COLS = 4
@@ -108,7 +109,7 @@ 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(autorange=True)
112
  return sanitize_plotly_figure(fig)
113
 
114
 
@@ -216,3 +217,22 @@ def next_page(page, figures_len):
216
 
217
  def prev_page(page):
218
  return max(page - 1, 0)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  import pandas as pd
8
  from common import get_db
9
  from ui import disable_component
10
+ import plotly.express as px
11
 
12
  MAX_CHARTS_IN_PAGE = 40
13
  NUM_COLS = 4
 
109
  title=f"{trend_doc.get('test_name','')}",
110
  )
111
  fig.update_yaxes(autorange=True)
112
+ fig.update_xaxes(autorange=True)
113
  return sanitize_plotly_figure(fig)
114
 
115
 
 
217
 
218
  def prev_page(page):
219
  return max(page - 1, 0)
220
+
221
+
222
+ async def render_vitals_plot_layout(patient_id):
223
+ docs = await get_db().get_vitals_trends_by_patient(patient_id)
224
+ figures = [build_trend_figure(doc) for doc in docs if doc]
225
+ # Pad/truncate to exactly 20 charts
226
+ if len(figures) > 20:
227
+ figures = figures[:20]
228
+ elif len(figures) < 20:
229
+ while len(figures) < 20:
230
+ empty_fig = Figure()
231
+ empty_fig.update_layout(
232
+ title="No Data",
233
+ xaxis=dict(visible=False),
234
+ yaxis=dict(visible=False),
235
+ margin=dict(l=30, r=20, t=40, b=30),
236
+ )
237
+ figures.append(empty_fig)
238
+ return [gr.Plot(value=fig, label=fig.layout.title.text) for fig in figures]
ui.py CHANGED
@@ -905,4 +905,4 @@ async def render_latest_vitals_card_layout(patient_id: str):
905
  while len(cards) < 20:
906
  cards.append(gr.Label(value="-", label="", visible=True))
907
 
908
- return cards
 
905
  while len(cards) < 20:
906
  cards.append(gr.Label(value="-", label="", visible=True))
907
 
908
+ return cards