sujataprakashdatycs commited on
Commit
12dc640
Β·
verified Β·
1 Parent(s): da57dcf

Update app.py

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