Upload folder using huggingface_hub
Browse files- home.py +59 -5
- modules/db.py +23 -12
home.py
CHANGED
|
@@ -33,6 +33,43 @@ load_dotenv(override=True)
|
|
| 33 |
# ----- Data shaping helpers -----
|
| 34 |
|
| 35 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
def _fmt(dt: Any) -> str:
|
| 37 |
if isinstance(dt, (datetime,)):
|
| 38 |
return dt.strftime("%Y-%m-%d %H:%M")
|
|
@@ -243,6 +280,7 @@ def load_patient_bundle(
|
|
| 243 |
- test_names (for dropdown)
|
| 244 |
- meta dict with patient basics
|
| 245 |
- final_reports list
|
|
|
|
| 246 |
"""
|
| 247 |
if not patient_id:
|
| 248 |
return pd.DataFrame(), [], {}, []
|
|
@@ -263,6 +301,7 @@ def load_patient_bundle(
|
|
| 263 |
reports = db.get_reports_by_patient(patient_id)
|
| 264 |
trends = db.get_trends_by_patient(patient_id)
|
| 265 |
finals = db.get_final_reports_by_patient(patient_id)
|
|
|
|
| 266 |
|
| 267 |
reports_df = flatten_reports_v2(reports)
|
| 268 |
test_names = trends_index(trends)
|
|
@@ -274,7 +313,7 @@ def load_patient_bundle(
|
|
| 274 |
"Created": _fmt(patient.get("created_at")),
|
| 275 |
}
|
| 276 |
selected_patient_info = f'**{patient.get("name", "-")}** | **{patient.get("gender", "-")}** | Born: {patient.get("dob", "-")} | Created: {_fmt(patient.get("created_at"))}'
|
| 277 |
-
return reports_df, test_names, meta, selected_patient_info, finals
|
| 278 |
|
| 279 |
|
| 280 |
def load_trend_figure(patient_id: str, test_name: str) -> Figure:
|
|
@@ -497,7 +536,7 @@ with gr.Blocks(
|
|
| 497 |
# df_row is a dict representing the selected row
|
| 498 |
if df_selected_row is None:
|
| 499 |
return gr.update(visible=False), None
|
| 500 |
-
report_id = df_selected_row[0]
|
| 501 |
report_file_name = download_final_report(report_id)
|
| 502 |
report_html_content = get_db().get_final_report_html(report_id)
|
| 503 |
# Return modal visibility + the file to bind to download button
|
|
@@ -522,9 +561,13 @@ with gr.Blocks(
|
|
| 522 |
inputs=[report_id_in],
|
| 523 |
outputs=download_btn,
|
| 524 |
)
|
| 525 |
-
|
| 526 |
with gr.Tab("📄 Upload History"):
|
| 527 |
gr.Markdown("### here is your upload history")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 528 |
|
| 529 |
# ---- Events ----
|
| 530 |
def on_load(email):
|
|
@@ -538,7 +581,7 @@ with gr.Blocks(
|
|
| 538 |
)
|
| 539 |
|
| 540 |
def on_patient_select(patient_id):
|
| 541 |
-
reports_df_val, test_names, meta, selected_patient_info, finals = (
|
| 542 |
load_patient_bundle(patient_id)
|
| 543 |
)
|
| 544 |
return (
|
|
@@ -550,12 +593,23 @@ with gr.Blocks(
|
|
| 550 |
headers=["final_report_id", "generated_at"],
|
| 551 |
value=format_final_reports(finals),
|
| 552 |
),
|
|
|
|
|
|
|
|
|
|
|
|
|
| 553 |
)
|
| 554 |
|
| 555 |
patient_list.change(
|
| 556 |
on_patient_select,
|
| 557 |
inputs=[patient_list],
|
| 558 |
-
outputs=[
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 559 |
)
|
| 560 |
|
| 561 |
def on_test_change(patient_id, test_name):
|
|
|
|
| 33 |
# ----- Data shaping helpers -----
|
| 34 |
|
| 35 |
|
| 36 |
+
def get_status_icon(status):
|
| 37 |
+
if status == "completed":
|
| 38 |
+
status = "✅"
|
| 39 |
+
if status == "inprogress":
|
| 40 |
+
status = "⌛"
|
| 41 |
+
return status
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
# Example: flatten your MongoDB document
|
| 45 |
+
def flatten_run_stats(docs):
|
| 46 |
+
rows = []
|
| 47 |
+
for doc in docs:
|
| 48 |
+
latest_milestone_status = get_status_icon(
|
| 49 |
+
doc.get("milestones", [{}])[-1].get("status", "")
|
| 50 |
+
)
|
| 51 |
+
rows.append(
|
| 52 |
+
{
|
| 53 |
+
"id": str(doc.get("_id", "")),
|
| 54 |
+
"upload_date": doc.get("created_at", ""),
|
| 55 |
+
# "user_id": str(doc.get("user_id", "")),
|
| 56 |
+
# "patient_id": str(doc.get("patient_id", "")),
|
| 57 |
+
"source_files": ", ".join(doc.get("source_file_names", [])),
|
| 58 |
+
"action": doc.get("action", ""),
|
| 59 |
+
"status": get_status_icon(doc.get("status")),
|
| 60 |
+
"progress": f"{doc.get("steps_completed", 0)}/{doc.get("steps_total", 0)}",
|
| 61 |
+
# For milestones, show latest milestone name & status
|
| 62 |
+
"latest_milestone": doc.get("milestones", [{}])[-1].get(
|
| 63 |
+
"milestone", ""
|
| 64 |
+
),
|
| 65 |
+
"milestone_status": latest_milestone_status,
|
| 66 |
+
}
|
| 67 |
+
)
|
| 68 |
+
df = pd.DataFrame(rows)
|
| 69 |
+
df = df.fillna("-") # 👈 normalize missing values
|
| 70 |
+
return df
|
| 71 |
+
|
| 72 |
+
|
| 73 |
def _fmt(dt: Any) -> str:
|
| 74 |
if isinstance(dt, (datetime,)):
|
| 75 |
return dt.strftime("%Y-%m-%d %H:%M")
|
|
|
|
| 280 |
- test_names (for dropdown)
|
| 281 |
- meta dict with patient basics
|
| 282 |
- final_reports list
|
| 283 |
+
- run_stats list
|
| 284 |
"""
|
| 285 |
if not patient_id:
|
| 286 |
return pd.DataFrame(), [], {}, []
|
|
|
|
| 301 |
reports = db.get_reports_by_patient(patient_id)
|
| 302 |
trends = db.get_trends_by_patient(patient_id)
|
| 303 |
finals = db.get_final_reports_by_patient(patient_id)
|
| 304 |
+
run_stats = db.get_run_stats_by_patient(patient_id)
|
| 305 |
|
| 306 |
reports_df = flatten_reports_v2(reports)
|
| 307 |
test_names = trends_index(trends)
|
|
|
|
| 313 |
"Created": _fmt(patient.get("created_at")),
|
| 314 |
}
|
| 315 |
selected_patient_info = f'**{patient.get("name", "-")}** | **{patient.get("gender", "-")}** | Born: {patient.get("dob", "-")} | Created: {_fmt(patient.get("created_at"))}'
|
| 316 |
+
return reports_df, test_names, meta, selected_patient_info, finals, run_stats
|
| 317 |
|
| 318 |
|
| 319 |
def load_trend_figure(patient_id: str, test_name: str) -> Figure:
|
|
|
|
| 536 |
# df_row is a dict representing the selected row
|
| 537 |
if df_selected_row is None:
|
| 538 |
return gr.update(visible=False), None
|
| 539 |
+
report_id = df_selected_row[0] # first column is report_id
|
| 540 |
report_file_name = download_final_report(report_id)
|
| 541 |
report_html_content = get_db().get_final_report_html(report_id)
|
| 542 |
# Return modal visibility + the file to bind to download button
|
|
|
|
| 561 |
inputs=[report_id_in],
|
| 562 |
outputs=download_btn,
|
| 563 |
)
|
|
|
|
| 564 |
with gr.Tab("📄 Upload History"):
|
| 565 |
gr.Markdown("### here is your upload history")
|
| 566 |
+
run_stats_df = gr.DataFrame(
|
| 567 |
+
row_count=(0, "dynamic"),
|
| 568 |
+
wrap=True,
|
| 569 |
+
interactive=False,
|
| 570 |
+
)
|
| 571 |
|
| 572 |
# ---- Events ----
|
| 573 |
def on_load(email):
|
|
|
|
| 581 |
)
|
| 582 |
|
| 583 |
def on_patient_select(patient_id):
|
| 584 |
+
reports_df_val, test_names, meta, selected_patient_info, finals, run_stats = (
|
| 585 |
load_patient_bundle(patient_id)
|
| 586 |
)
|
| 587 |
return (
|
|
|
|
| 593 |
headers=["final_report_id", "generated_at"],
|
| 594 |
value=format_final_reports(finals),
|
| 595 |
),
|
| 596 |
+
gr.update(
|
| 597 |
+
headers=["user_id", "patient_id"],
|
| 598 |
+
value=flatten_run_stats(run_stats),
|
| 599 |
+
),
|
| 600 |
)
|
| 601 |
|
| 602 |
patient_list.change(
|
| 603 |
on_patient_select,
|
| 604 |
inputs=[patient_list],
|
| 605 |
+
outputs=[
|
| 606 |
+
meta_box,
|
| 607 |
+
selected_patient_info,
|
| 608 |
+
reports_df,
|
| 609 |
+
test_dd,
|
| 610 |
+
final_df,
|
| 611 |
+
run_stats_df,
|
| 612 |
+
],
|
| 613 |
)
|
| 614 |
|
| 615 |
def on_test_change(patient_id, test_name):
|
modules/db.py
CHANGED
|
@@ -8,6 +8,7 @@ from dotenv import load_dotenv
|
|
| 8 |
from modules.models import StandardizedReport
|
| 9 |
import gridfs
|
| 10 |
|
|
|
|
| 11 |
class SheamiDB:
|
| 12 |
def __init__(self, uri: str, db_name: str = "sheami"):
|
| 13 |
"""Initialize connection to MongoDB Atlas (or local Mongo)."""
|
|
@@ -374,7 +375,7 @@ class SheamiDB:
|
|
| 374 |
# print("updated/inserted", updated, "trends")
|
| 375 |
return updated
|
| 376 |
|
| 377 |
-
def aggregate_trends_snapshot(self, patient_id
|
| 378 |
# fetch trends for this patient
|
| 379 |
trend_docs = self.get_trends_by_patient(patient_id)
|
| 380 |
|
|
@@ -386,15 +387,18 @@ class SheamiDB:
|
|
| 386 |
continue
|
| 387 |
# last point = most recent measurement
|
| 388 |
last_point = max(td, key=lambda x: x.get("date"))
|
| 389 |
-
snapshots.append(
|
| 390 |
-
|
| 391 |
-
|
| 392 |
-
|
| 393 |
-
|
| 394 |
-
|
| 395 |
-
|
|
|
|
|
|
|
| 396 |
return snapshots
|
| 397 |
-
|
|
|
|
| 398 |
# FINAL REPORT FUNCTIONS
|
| 399 |
# ---------------------------
|
| 400 |
def add_final_report_v2(
|
|
@@ -436,12 +440,19 @@ class SheamiDB:
|
|
| 436 |
if not doc or not doc.get("pdf_file_id"):
|
| 437 |
return None
|
| 438 |
return self.fs.get(doc["pdf_file_id"]).read()
|
| 439 |
-
|
| 440 |
def get_final_report_html(self, report_id: str) -> bytes | None:
|
| 441 |
"""
|
| 442 |
Fetch the HTML for a given final_report (if stored).
|
| 443 |
"""
|
| 444 |
doc = self.final_reports.find_one({"_id": ObjectId(report_id)})
|
| 445 |
if not doc or not doc.get("summary"):
|
| 446 |
-
return "<html></html>"#empty tag
|
| 447 |
-
return doc.get("summary")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
from modules.models import StandardizedReport
|
| 9 |
import gridfs
|
| 10 |
|
| 11 |
+
|
| 12 |
class SheamiDB:
|
| 13 |
def __init__(self, uri: str, db_name: str = "sheami"):
|
| 14 |
"""Initialize connection to MongoDB Atlas (or local Mongo)."""
|
|
|
|
| 375 |
# print("updated/inserted", updated, "trends")
|
| 376 |
return updated
|
| 377 |
|
| 378 |
+
def aggregate_trends_snapshot(self, patient_id: str):
|
| 379 |
# fetch trends for this patient
|
| 380 |
trend_docs = self.get_trends_by_patient(patient_id)
|
| 381 |
|
|
|
|
| 387 |
continue
|
| 388 |
# last point = most recent measurement
|
| 389 |
last_point = max(td, key=lambda x: x.get("date"))
|
| 390 |
+
snapshots.append(
|
| 391 |
+
{
|
| 392 |
+
"test_name": t.get("test_name", ""),
|
| 393 |
+
"latest_value": last_point.get("value"),
|
| 394 |
+
"latest_date": last_point.get("date"),
|
| 395 |
+
"unit": last_point.get("unit", ""),
|
| 396 |
+
"reference_range": last_point.get("reference_range", ""),
|
| 397 |
+
}
|
| 398 |
+
)
|
| 399 |
return snapshots
|
| 400 |
+
|
| 401 |
+
# ---------------------------
|
| 402 |
# FINAL REPORT FUNCTIONS
|
| 403 |
# ---------------------------
|
| 404 |
def add_final_report_v2(
|
|
|
|
| 440 |
if not doc or not doc.get("pdf_file_id"):
|
| 441 |
return None
|
| 442 |
return self.fs.get(doc["pdf_file_id"]).read()
|
| 443 |
+
|
| 444 |
def get_final_report_html(self, report_id: str) -> bytes | None:
|
| 445 |
"""
|
| 446 |
Fetch the HTML for a given final_report (if stored).
|
| 447 |
"""
|
| 448 |
doc = self.final_reports.find_one({"_id": ObjectId(report_id)})
|
| 449 |
if not doc or not doc.get("summary"):
|
| 450 |
+
return "<html></html>" # empty tag
|
| 451 |
+
return doc.get("summary")
|
| 452 |
+
|
| 453 |
+
def get_run_stats_by_patient(self, patient_id: str) -> list:
|
| 454 |
+
return list(
|
| 455 |
+
self.run_stats.find({"patient_id": ObjectId(patient_id)}).sort(
|
| 456 |
+
"created_at", -1
|
| 457 |
+
) # -1 for descending order
|
| 458 |
+
)
|