sujataprakashdatycs commited on
Commit
834ba3e
Β·
verified Β·
1 Parent(s): 27681e9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +412 -29
app.py CHANGED
@@ -138,18 +138,26 @@ def process_pipeline(pdf_file, hcc_code, model_version, csv_path=CSV_PATH, outpu
138
  try:
139
  start = time.time()
140
  step = 0
141
- total_steps = 8 # Step 0 added for demographics
142
 
143
- def log(msg, step_progress=None):
 
144
  elapsed = time.time() - start
145
- progress_html = ""
146
- if step_progress is not None:
147
- progress_html = f"""
148
- <div style="width:100%; background:#eee; border-radius:6px; margin:5px 0;">
149
- <div style="width:{step_progress*100}%; background:#1e40af; height:12px; border-radius:6px;"></div>
150
- </div>
151
- """
152
- return f"{progress_html}{msg}<br/><small>⏳ Elapsed: {elapsed:.1f} sec</small>"
 
 
 
 
 
 
 
153
 
154
  if pdf_file is None:
155
  yield log("⚠️ Please upload a patient chart PDF.", 0)
@@ -164,27 +172,27 @@ def process_pipeline(pdf_file, hcc_code, model_version, csv_path=CSV_PATH, outpu
164
  patient_name = os.path.splitext(os.path.basename(pdf_path))[0]
165
  print(f"[PROCESSING] {patient_name}")
166
 
167
- # Step 0: Extract Demographics
168
  step += 1
169
  progress((step, total_steps), desc="Extracting demographics")
170
- yield log(f"🧍 Step {step}/{total_steps}: Extracting patient demographics...", step/total_steps)
171
  demographics_engine = PatientInfoExtractionEngine(pdf_path)
172
  demographics_info = demographics_engine.run()
173
  print(f"[DEMOGRAPHICS] Extracted: {demographics_info}")
174
 
175
- # Step 1: Diagnoses
176
  step += 1
177
  progress((step, total_steps), desc="Extracting diagnoses")
178
- yield log(f"πŸ” Step {step}/{total_steps}: Extracting possible HCC Diagnoses...", step/total_steps)
179
  diagnoses = HCCDiagnosisListEngine(hcc_code_str, model_version, csv_path).run()
180
  if not diagnoses:
181
- yield log(f"❌ No diagnoses found for HCC {hcc_code_str}.", step/total_steps)
182
  return
183
 
184
- # Step 2: Chart checking
185
  step += 1
186
  progress((step, total_steps), desc="Checking chart")
187
- yield log(f"πŸ“„ Step {step}/{total_steps}: Checking diagnoses in patient chart...", step/total_steps)
188
  all_checked_results = ChartDiagnosisChecker(pdf_path).run(diagnoses)
189
  confirmed_diagnoses = [
190
  d for d in all_checked_results
@@ -192,46 +200,46 @@ def process_pipeline(pdf_file, hcc_code, model_version, csv_path=CSV_PATH, outpu
192
  or d.get("answer_implicit", "").lower() == "yes"
193
  ]
194
  if not confirmed_diagnoses:
195
- yield log(f"❌ No confirmed diagnoses for HCC {hcc_code_str} in {patient_name}.", step/total_steps)
196
  return
197
 
198
- # Step 3: Tests
199
  step += 1
200
  progress((step, total_steps), desc="Finding tests")
201
- yield log(f"πŸ§ͺ Step {step}/{total_steps}: Finding relevant tests...", step/total_steps)
202
  diagnoses_with_tests = TestFindingAgent(hcc_code=hcc_code_str, model_version=model_version).run(confirmed_diagnoses)
203
 
204
- # Step 4: Clinical Status
205
  step += 1
206
  progress((step, total_steps), desc="Determining clinical status")
207
- yield log(f"βš•οΈ Step {step}/{total_steps}: Determining clinical status...", step/total_steps)
208
  diagnoses_with_status = ClinicalStatusAgent().run(diagnoses_with_tests)
209
  active_diagnoses = [d for d in diagnoses_with_status if d.get("clinical_status") == "ACTIVE"]
210
 
211
- # Step 5: MEAT
212
  step += 1
213
  progress((step, total_steps), desc="Validating MEAT")
214
  if active_diagnoses:
215
- yield log(f"πŸ– Step {step}/{total_steps}: Validating MEAT...", step/total_steps)
216
  validated_meat_diagnoses = MEATValidatorAgent().run(active_diagnoses)
217
  else:
218
  validated_meat_diagnoses = []
219
- yield log("ℹ️ No ACTIVE diagnoses found. Skipping MEAT/Comorbidity.", step/total_steps)
220
 
221
- # Step 6: Comorbidities
222
  step += 1
223
  progress((step, total_steps), desc="Checking comorbidities")
224
  diagnoses_passed_meat = [d for d in validated_meat_diagnoses if any(d.get("meat", {}).values())]
225
  if diagnoses_passed_meat:
226
- yield log(f"🀝 Step {step}/{total_steps}: Checking comorbidities...", step/total_steps)
227
  comorbidity_results = ComorbidityCheckerAgent(pdf_path, hcc_code_str, model_version).run(diagnoses_passed_meat)
228
  else:
229
  comorbidity_results = []
230
 
231
- # Step 7: Final Report
232
  step += 1
233
  progress((step, total_steps), desc="Generating report")
234
- yield log(f"βœ… Step {step}/{total_steps}: Generating final report...", step/total_steps)
235
 
236
  # Merge results
237
  status_map = {d["diagnosis"]: d for d in diagnoses_with_status}
@@ -373,6 +381,381 @@ if __name__ == "__main__":
373
 
374
 
375
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
376
 
377
 
378
 
 
138
  try:
139
  start = time.time()
140
  step = 0
141
+ total_steps = 8 # Total number of steps in the pipeline
142
 
143
+ # --- MODIFIED: Log function to display a segmented progress bar ---
144
+ def log(msg, current_step=0):
145
  elapsed = time.time() - start
146
+
147
+ # Generate the segmented progress bar HTML
148
+ bar_html = '<div style="display: flex; width: 100%; gap: 2px; height: 12px; margin: 5px 0;">'
149
+ for i in range(1, total_steps + 1):
150
+ if i < current_step:
151
+ color = "#1e40af" # Completed (Dark Blue)
152
+ elif i == current_step:
153
+ color = "#3b82f6" # In Progress (Lighter Blue)
154
+ else:
155
+ color = "#e5e7eb" # Pending (Grey)
156
+ bar_html += f'<div style="flex-grow: 1; background-color: {color}; border-radius: 3px;"></div>'
157
+ bar_html += '</div>'
158
+
159
+ return f"{bar_html}{msg}<br/><small>⏳ Elapsed: {elapsed:.1f} sec</small>"
160
+ # --- END OF MODIFICATION ---
161
 
162
  if pdf_file is None:
163
  yield log("⚠️ Please upload a patient chart PDF.", 0)
 
172
  patient_name = os.path.splitext(os.path.basename(pdf_path))[0]
173
  print(f"[PROCESSING] {patient_name}")
174
 
175
+ # Step 1: Extract Demographics
176
  step += 1
177
  progress((step, total_steps), desc="Extracting demographics")
178
+ yield log(f"🧍 Step {step}/{total_steps}: Extracting patient demographics...", step)
179
  demographics_engine = PatientInfoExtractionEngine(pdf_path)
180
  demographics_info = demographics_engine.run()
181
  print(f"[DEMOGRAPHICS] Extracted: {demographics_info}")
182
 
183
+ # Step 2: Diagnoses
184
  step += 1
185
  progress((step, total_steps), desc="Extracting diagnoses")
186
+ yield log(f"πŸ” Step {step}/{total_steps}: Extracting possible HCC Diagnoses...", step)
187
  diagnoses = HCCDiagnosisListEngine(hcc_code_str, model_version, csv_path).run()
188
  if not diagnoses:
189
+ yield log(f"❌ No diagnoses found for HCC {hcc_code_str}.", step)
190
  return
191
 
192
+ # Step 3: Chart checking
193
  step += 1
194
  progress((step, total_steps), desc="Checking chart")
195
+ yield log(f"πŸ“„ Step {step}/{total_steps}: Checking diagnoses in patient chart...", step)
196
  all_checked_results = ChartDiagnosisChecker(pdf_path).run(diagnoses)
197
  confirmed_diagnoses = [
198
  d for d in all_checked_results
 
200
  or d.get("answer_implicit", "").lower() == "yes"
201
  ]
202
  if not confirmed_diagnoses:
203
+ yield log(f"❌ No confirmed diagnoses for HCC {hcc_code_str} in {patient_name}.", step)
204
  return
205
 
206
+ # Step 4: Tests
207
  step += 1
208
  progress((step, total_steps), desc="Finding tests")
209
+ yield log(f"πŸ§ͺ Step {step}/{total_steps}: Finding relevant tests...", step)
210
  diagnoses_with_tests = TestFindingAgent(hcc_code=hcc_code_str, model_version=model_version).run(confirmed_diagnoses)
211
 
212
+ # Step 5: Clinical Status
213
  step += 1
214
  progress((step, total_steps), desc="Determining clinical status")
215
+ yield log(f"βš•οΈ Step {step}/{total_steps}: Determining clinical status...", step)
216
  diagnoses_with_status = ClinicalStatusAgent().run(diagnoses_with_tests)
217
  active_diagnoses = [d for d in diagnoses_with_status if d.get("clinical_status") == "ACTIVE"]
218
 
219
+ # Step 6: MEAT
220
  step += 1
221
  progress((step, total_steps), desc="Validating MEAT")
222
  if active_diagnoses:
223
+ yield log(f"πŸ– Step {step}/{total_steps}: Validating MEAT...", step)
224
  validated_meat_diagnoses = MEATValidatorAgent().run(active_diagnoses)
225
  else:
226
  validated_meat_diagnoses = []
227
+ yield log("ℹ️ No ACTIVE diagnoses found. Skipping MEAT/Comorbidity.", step)
228
 
229
+ # Step 7: Comorbidities
230
  step += 1
231
  progress((step, total_steps), desc="Checking comorbidities")
232
  diagnoses_passed_meat = [d for d in validated_meat_diagnoses if any(d.get("meat", {}).values())]
233
  if diagnoses_passed_meat:
234
+ yield log(f"🀝 Step {step}/{total_steps}: Checking comorbidities...", step)
235
  comorbidity_results = ComorbidityCheckerAgent(pdf_path, hcc_code_str, model_version).run(diagnoses_passed_meat)
236
  else:
237
  comorbidity_results = []
238
 
239
+ # Step 8: Final Report
240
  step += 1
241
  progress((step, total_steps), desc="Generating report")
242
+ yield log(f"βœ… Step {step}/{total_steps}: Generating final report...", step)
243
 
244
  # Merge results
245
  status_map = {d["diagnosis"]: d for d in diagnoses_with_status}
 
381
 
382
 
383
 
384
+ # import os
385
+ # import gradio as gr
386
+ # import json
387
+ # import time
388
+ # import base64
389
+ # from dotenv import load_dotenv
390
+ # from ClinicalStatusAgent import ClinicalStatusAgent
391
+ # from TestFindingAgent import TestFindingAgent
392
+ # from ComorbidityCheckerAgent import ComorbidityCheckerAgent
393
+ # from HCCDiagnosisListEngine import HCCDiagnosisListEngine
394
+ # from chartdiagnosischecker import ChartDiagnosisChecker
395
+ # from MeatValidatorAgent import MEATValidatorAgent
396
+ # from PatientInfoExtractionEngine import PatientInfoExtractionEngine
397
+
398
+ # load_dotenv()
399
+ # APP_TITLE = "Risk Adjustment (HCC Chart Validation)"
400
+ # CSV_PATH = "hcc_mapping.csv"
401
+ # SAMPLE_PDF = "sample_patient_chart.pdf" # Place a sample PDF in the same folder
402
+
403
+
404
+ # # ---------- JSON to Markdown ----------
405
+ # def json_to_markdown(data) -> str:
406
+ # try:
407
+ # if isinstance(data, dict) and "final_analysis" in data:
408
+ # patient_id = data.get("patient_id", "Unknown Patient")
409
+ # hcc_code = data.get("hcc_code", "N/A")
410
+ # model_version = data.get("model_version", "N/A")
411
+ # analyses = data.get("final_analysis", [])
412
+
413
+ # # Demographics
414
+ # patient_name = data.get("patient_name", "")
415
+ # dob = data.get("dob", "")
416
+ # age = data.get("age", "")
417
+ # gender = data.get("gender", "")
418
+ # address = data.get("address", "")
419
+ # phone = data.get("phone", "")
420
+ # patient_identifier = data.get("patient_identifier", "")
421
+
422
+ # elif isinstance(data, list):
423
+ # patient_id = "N/A"
424
+ # hcc_code = "N/A"
425
+ # model_version = "N/A"
426
+ # analyses = data
427
+ # patient_name = dob = age = gender = address = phone = patient_identifier = ""
428
+ # else:
429
+ # return "<div style='color:red; font-weight:bold;'>⚠️ Invalid data format for report.</div>"
430
+
431
+ # md = f"""
432
+ # <div style="border:2px solid #4CAF50; padding:15px; border-radius:10px; background:#f9fdf9;">
433
+ # <h2 style="color:#2e7d32;">πŸ“‹ HCC Chart Validation Report </h2>
434
+ # <p><b>🧾 Patient ID:</b> {patient_id}</p>
435
+ # <p><b>🏷️ HCC Code:</b> {hcc_code}</p>
436
+ # <p><b>βš™οΈ Model Version:</b> {model_version}</p>
437
+ # """
438
+
439
+ # # Add demographics
440
+ # if any([patient_name, dob, age, gender, address, phone, patient_identifier]):
441
+ # md += "<hr style='border:0;border-top:1px solid #c8e6c9;margin:10px 0;'/>"
442
+ # md += "<h3 style='color:#1b5e20;'>πŸ‘€ Patient Demographics</h3>"
443
+ # if patient_name: md += f"<p><b>Name:</b> {patient_name}</p>"
444
+ # if patient_identifier: md += f"<p><b>Patient Identifier:</b> {patient_identifier}</p>"
445
+ # if dob: md += f"<p><b>Date of Birth:</b> {dob}</p>"
446
+ # if age: md += f"<p><b>Age:</b> {age}</p>"
447
+ # if gender: md += f"<p><b>Gender:</b> {gender}</p>"
448
+ # if address: md += f"<p><b>Address:</b> {address}</p>"
449
+ # if phone: md += f"<p><b>Phone:</b> {phone}</p>"
450
+
451
+ # md += "</div><br/>"
452
+
453
+ # # Render analyses
454
+ # for idx, diag in enumerate(analyses, 1):
455
+ # md += f"""
456
+ # <div style="border:1px solid #ccc; padding:12px; border-radius:8px; margin-bottom:12px;">
457
+ # <h3 style="color:#1565c0;">{idx}. {diag.get("diagnosis", "Unknown Diagnosis")}</h3>
458
+ # <p><b>ICD-10:</b> {diag.get("icd10", "N/A")}</p>
459
+ # <p><b>Reference:</b> <a href="{diag.get("reference","")}" target="_blank">{diag.get("reference","")}</a></p>
460
+ # """
461
+ # explicit_ans = diag.get("answer_explicit", "N/A")
462
+ # explicit_rat = diag.get("rationale_explicit", "")
463
+ # implicit_ans = diag.get("answer_implicit", "N/A")
464
+ # implicit_rat = diag.get("rationale_implicit", "")
465
+
466
+ # if explicit_ans.lower() == "yes":
467
+ # md += f"<p><b>Explicit:</b> {explicit_ans} β€” {explicit_rat}</p>"
468
+ # else:
469
+ # md += f"<p><b>Implicit:</b> {implicit_ans} β€” {implicit_rat}</p>"
470
+
471
+ # md += f"""
472
+ # <p><b>Clinical Status:</b> {diag.get("clinical_status","N/A")}</p>
473
+ # <p><b>Status Rationale:</b> {diag.get("status_rationale","")}</p>
474
+ # """
475
+ # if "tests" in diag:
476
+ # md += "<details><summary><b>πŸ§ͺ Tests & Procedures</b></summary><ul>"
477
+ # tests = diag["tests"]
478
+ # if "vitals" in tests:
479
+ # md += "<li><b>Vitals:</b><ul>"
480
+ # for k, v in tests["vitals"].items():
481
+ # md += f"<li>{k}: {v}</li>"
482
+ # md += "</ul></li>"
483
+ # if "procedures" in tests:
484
+ # md += "<li><b>Procedures:</b><ul>"
485
+ # for k, v in tests["procedures"].items():
486
+ # md += f"<li>{k}: {v}</li>"
487
+ # md += "</ul></li>"
488
+ # if "lab_test" in tests:
489
+ # md += "<li><b>Lab Tests:</b><ul>"
490
+ # for k, v in tests["lab_test"].items():
491
+ # md += f"<li>{k}: {v}</li>"
492
+ # md += "</ul></li>"
493
+ # md += "</ul></details>"
494
+
495
+ # if "meat" in diag:
496
+ # md += "<details><summary><b>πŸ– MEAT Validation</b></summary><ul>"
497
+ # for k, v in diag["meat"].items():
498
+ # emoji = "βœ…" if v else "❌"
499
+ # md += f"<li>{k.capitalize()}: {emoji}</li>"
500
+ # md += "</ul>"
501
+ # md += f"<p><b>MEAT Rationale:</b> {diag.get('meat_rationale','')}</p>"
502
+ # md += "</details>"
503
+
504
+ # if "comorbidities" in diag and diag["comorbidities"]:
505
+ # md += "<details><summary><b>🩺 Comorbidities</b></summary><ul>"
506
+ # for c in diag["comorbidities"]:
507
+ # emoji = "βœ…" if c.get("is_present") else "❌"
508
+ # md += f"<li>{emoji} <b>{c.get('condition')}</b><br/><i>{c.get('rationale')}</i></li>"
509
+ # md += "</ul></details>"
510
+
511
+ # md += "</div>"
512
+
513
+ # return md
514
+
515
+ # except Exception as e:
516
+ # return f"<div style='color:red; font-weight:bold;'>⚠️ Error rendering report: {e}</div>"
517
+
518
+
519
+ # # ---------- Processing Pipeline with Gradio Progress ----------
520
+ # def process_pipeline(pdf_file, hcc_code, model_version, csv_path=CSV_PATH, output_folder="outputs", progress=gr.Progress()):
521
+ # try:
522
+ # start = time.time()
523
+ # step = 0
524
+ # total_steps = 8 # Step 0 added for demographics
525
+
526
+ # def log(msg, step_progress=None):
527
+ # elapsed = time.time() - start
528
+ # progress_html = ""
529
+ # if step_progress is not None:
530
+ # progress_html = f"""
531
+ # <div style="width:100%; background:#eee; border-radius:6px; margin:5px 0;">
532
+ # <div style="width:{step_progress*100}%; background:#1e40af; height:12px; border-radius:6px;"></div>
533
+ # </div>
534
+ # """
535
+ # return f"{progress_html}{msg}<br/><small>⏳ Elapsed: {elapsed:.1f} sec</small>"
536
+
537
+ # if pdf_file is None:
538
+ # yield log("⚠️ Please upload a patient chart PDF.", 0)
539
+ # return
540
+ # hcc_code_str = str(hcc_code or "").strip()
541
+ # if not hcc_code_str:
542
+ # yield log("⚠️ Please enter a valid HCC Code before running validation.", 0)
543
+ # return
544
+
545
+ # os.makedirs(output_folder, exist_ok=True)
546
+ # pdf_path = pdf_file.name
547
+ # patient_name = os.path.splitext(os.path.basename(pdf_path))[0]
548
+ # print(f"[PROCESSING] {patient_name}")
549
+
550
+ # # Step 0: Extract Demographics
551
+ # step += 1
552
+ # progress((step, total_steps), desc="Extracting demographics")
553
+ # yield log(f"🧍 Step {step}/{total_steps}: Extracting patient demographics...", step/total_steps)
554
+ # demographics_engine = PatientInfoExtractionEngine(pdf_path)
555
+ # demographics_info = demographics_engine.run()
556
+ # print(f"[DEMOGRAPHICS] Extracted: {demographics_info}")
557
+
558
+ # # Step 1: Diagnoses
559
+ # step += 1
560
+ # progress((step, total_steps), desc="Extracting diagnoses")
561
+ # yield log(f"πŸ” Step {step}/{total_steps}: Extracting possible HCC Diagnoses...", step/total_steps)
562
+ # diagnoses = HCCDiagnosisListEngine(hcc_code_str, model_version, csv_path).run()
563
+ # if not diagnoses:
564
+ # yield log(f"❌ No diagnoses found for HCC {hcc_code_str}.", step/total_steps)
565
+ # return
566
+
567
+ # # Step 2: Chart checking
568
+ # step += 1
569
+ # progress((step, total_steps), desc="Checking chart")
570
+ # yield log(f"πŸ“„ Step {step}/{total_steps}: Checking diagnoses in patient chart...", step/total_steps)
571
+ # all_checked_results = ChartDiagnosisChecker(pdf_path).run(diagnoses)
572
+ # confirmed_diagnoses = [
573
+ # d for d in all_checked_results
574
+ # if d.get("answer_explicit", "").lower() == "yes"
575
+ # or d.get("answer_implicit", "").lower() == "yes"
576
+ # ]
577
+ # if not confirmed_diagnoses:
578
+ # yield log(f"❌ No confirmed diagnoses for HCC {hcc_code_str} in {patient_name}.", step/total_steps)
579
+ # return
580
+
581
+ # # Step 3: Tests
582
+ # step += 1
583
+ # progress((step, total_steps), desc="Finding tests")
584
+ # yield log(f"πŸ§ͺ Step {step}/{total_steps}: Finding relevant tests...", step/total_steps)
585
+ # diagnoses_with_tests = TestFindingAgent(hcc_code=hcc_code_str, model_version=model_version).run(confirmed_diagnoses)
586
+
587
+ # # Step 4: Clinical Status
588
+ # step += 1
589
+ # progress((step, total_steps), desc="Determining clinical status")
590
+ # yield log(f"βš•οΈ Step {step}/{total_steps}: Determining clinical status...", step/total_steps)
591
+ # diagnoses_with_status = ClinicalStatusAgent().run(diagnoses_with_tests)
592
+ # active_diagnoses = [d for d in diagnoses_with_status if d.get("clinical_status") == "ACTIVE"]
593
+
594
+ # # Step 5: MEAT
595
+ # step += 1
596
+ # progress((step, total_steps), desc="Validating MEAT")
597
+ # if active_diagnoses:
598
+ # yield log(f"πŸ– Step {step}/{total_steps}: Validating MEAT...", step/total_steps)
599
+ # validated_meat_diagnoses = MEATValidatorAgent().run(active_diagnoses)
600
+ # else:
601
+ # validated_meat_diagnoses = []
602
+ # yield log("ℹ️ No ACTIVE diagnoses found. Skipping MEAT/Comorbidity.", step/total_steps)
603
+
604
+ # # Step 6: Comorbidities
605
+ # step += 1
606
+ # progress((step, total_steps), desc="Checking comorbidities")
607
+ # diagnoses_passed_meat = [d for d in validated_meat_diagnoses if any(d.get("meat", {}).values())]
608
+ # if diagnoses_passed_meat:
609
+ # yield log(f"🀝 Step {step}/{total_steps}: Checking comorbidities...", step/total_steps)
610
+ # comorbidity_results = ComorbidityCheckerAgent(pdf_path, hcc_code_str, model_version).run(diagnoses_passed_meat)
611
+ # else:
612
+ # comorbidity_results = []
613
+
614
+ # # Step 7: Final Report
615
+ # step += 1
616
+ # progress((step, total_steps), desc="Generating report")
617
+ # yield log(f"βœ… Step {step}/{total_steps}: Generating final report...", step/total_steps)
618
+
619
+ # # Merge results
620
+ # status_map = {d["diagnosis"]: d for d in diagnoses_with_status}
621
+ # meat_map = {d["diagnosis"]: d for d in validated_meat_diagnoses}
622
+ # comorbidity_map = {d["diagnosis"]: d for d in comorbidity_results}
623
+
624
+ # final_analysis = []
625
+ # for entry in all_checked_results:
626
+ # diag_name = entry["diagnosis"]
627
+ # updated_entry = entry.copy()
628
+ # if diag_name in status_map:
629
+ # updated_entry.update(status_map[diag_name])
630
+ # if diag_name in meat_map:
631
+ # updated_entry.update(meat_map[diag_name])
632
+ # if diag_name in comorbidity_map:
633
+ # updated_entry.update(comorbidity_map[diag_name])
634
+ # final_analysis.append(updated_entry)
635
+
636
+ # filtered_final_analysis = [
637
+ # e for e in final_analysis
638
+ # if e.get("answer_explicit", "").lower() == "yes"
639
+ # or e.get("answer_implicit", "").lower() == "yes"
640
+ # ]
641
+
642
+ # # Include demographics in output
643
+ # output_data = {
644
+ # "patient_id": patient_name,
645
+ # "hcc_code": hcc_code_str,
646
+ # "model_version": model_version,
647
+ # "patient_name": demographics_info.get("name", ""),
648
+ # "dob": demographics_info.get("dob", ""),
649
+ # "age": demographics_info.get("age", ""),
650
+ # "gender": demographics_info.get("gender", ""),
651
+ # "address": demographics_info.get("address", ""),
652
+ # "phone": demographics_info.get("phone", ""),
653
+ # "patient_identifier": demographics_info.get("patient_identifier", ""),
654
+ # "final_analysis": filtered_final_analysis
655
+ # }
656
+
657
+ # elapsed = time.time() - start
658
+ # yield json_to_markdown(output_data) + f"<br/><div style='color:green;'>βœ… Completed in {elapsed:.1f} sec</div>"
659
+
660
+ # except Exception as e:
661
+ # print(f"[ERROR] {e}")
662
+ # yield f"<div style='color:red; font-weight:bold;'>⚠️ Error: {e}</div>"
663
+
664
+
665
+ # # ---------- Gradio Theme ----------
666
+ # simple_theme = gr.themes.Soft(
667
+ # primary_hue=gr.themes.colors.blue,
668
+ # secondary_hue=gr.themes.colors.slate,
669
+ # neutral_hue=gr.themes.colors.slate,
670
+ # ).set(
671
+ # button_primary_background_fill="#1e40af",
672
+ # button_primary_background_fill_hover="#1d4ed8",
673
+ # button_primary_text_color="white",
674
+ # background_fill_primary="white",
675
+ # background_fill_secondary="#f8fafc",
676
+ # )
677
+
678
+
679
+ # # ---------- Helper for Sample PDF ----------
680
+ # def load_sample_pdf():
681
+ # if not os.path.exists(SAMPLE_PDF):
682
+ # raise FileNotFoundError(f"Sample PDF not found at {SAMPLE_PDF}")
683
+ # class PDFWrapper:
684
+ # def __init__(self, path):
685
+ # self.name = path
686
+ # return PDFWrapper(SAMPLE_PDF)
687
+
688
+
689
+ # # ---------- Helper for PDF Preview ----------
690
+ # def pdf_to_iframe(file):
691
+ # if file is None:
692
+ # return "<p style='color:orange;'>No PDF uploaded.</p>"
693
+ # try:
694
+ # with open(file.name, "rb") as f:
695
+ # pdf_bytes = f.read()
696
+ # encoded = base64.b64encode(pdf_bytes).decode("utf-8")
697
+ # return f"""
698
+ # <iframe
699
+ # src="data:application/pdf;base64,{encoded}"
700
+ # width="100%" height="600px"
701
+ # style="border:1px solid #ccc;"
702
+ # ></iframe>
703
+ # """
704
+ # except Exception as e:
705
+ # return f"<p style='color:red;'>Failed to display PDF: {e}</p>"
706
+
707
+
708
+ # # ---------- Gradio UI ----------
709
+ # with gr.Blocks(theme=simple_theme, title=APP_TITLE) as interface:
710
+ # gr.HTML(f"""
711
+ # <h1 style='text-align:center;color:#1e40af;'> 🏩 {APP_TITLE}</h1>
712
+ # <p style='text-align:center;color:#64748b;'>
713
+ # Upload a chart, set HCC + model version, and validate MEAT criteria.
714
+ # </p>
715
+ # """)
716
+
717
+ # with gr.Row():
718
+ # pdf_upload = gr.File(label="Upload Patient Chart (PDF)", file_types=[".pdf"], scale=1)
719
+ # hcc_code = gr.Textbox(label="HCC Code (e.g., 12)", placeholder="Enter HCC code", scale=1)
720
+ # model_version = gr.Dropdown(choices=["V24", "V28"], label="Model Version", value="V24", scale=1)
721
+ # run_btn = gr.Button("πŸš€ Run Validation", variant="primary", scale=1)
722
+
723
+ # with gr.Row():
724
+ # with gr.Column(scale=2):
725
+ # pdf_preview = gr.HTML(label="πŸ“‘ PDF Preview", value="<p>Upload a PDF to preview</p>")
726
+ # with gr.Column(scale=2):
727
+ # output_md = gr.Markdown(
728
+ # label="Validation Report",
729
+ # value="<div style='border:2px solid #1e40af; border-radius:12px; padding:15px; background-color:#f0f9ff;'>πŸ“„ Upload a PDF and click <b>Run Validation</b> to start.</div>",
730
+ # )
731
+
732
+ # pdf_upload.change(fn=pdf_to_iframe, inputs=pdf_upload, outputs=pdf_preview)
733
+
734
+ # run_btn.click(
735
+ # fn=process_pipeline,
736
+ # inputs=[pdf_upload, hcc_code, model_version],
737
+ # outputs=[output_md],
738
+ # )
739
+
740
+ # gr.Examples(
741
+ # examples=[[SAMPLE_PDF]],
742
+ # inputs=[pdf_upload],
743
+ # outputs=[output_md],
744
+ # fn=lambda x: process_pipeline(load_sample_pdf(), hcc_code="12", model_version="V24"),
745
+ # cache_examples=False
746
+ # )
747
+
748
+
749
+ # if __name__ == "__main__":
750
+ # interface.queue().launch(
751
+ # server_name="0.0.0.0",
752
+ # server_port=int(os.environ.get("PORT", 7860))
753
+ # )
754
+
755
+
756
+
757
+
758
+
759
 
760
 
761