MiChaelinzo commited on
Commit
66c4a5b
·
verified ·
1 Parent(s): 9603774

Update callbackmanager.py

Browse files
Files changed (1) hide show
  1. callbackmanager.py +161 -152
callbackmanager.py CHANGED
@@ -121,15 +121,14 @@ def analyze_dicom_content_ai(dicom_metadata_json): # Copied from your code
121
  top_p=0.9,
122
  )
123
  the_response = response.choices[0].message.content
124
- return the_response, trace_data_detail_dicom_analysis
125
 
126
  except Exception as e:
127
  error_message = f"AI Analysis Error in analyze_dicom_content_ai (DICOM Metadata): {e}"
128
  trace_data_detail_dicom_analysis["error"] = f"AI Analysis Error: {e}"
129
- return error_message, trace_data_detail_dicom_analysis
130
 
131
 
132
- # ... (Paste other AI analysis functions: analyze_hl7_file_with_ai, analyze_cda_xml_file_with_ai, analyze_pdf_file_with_ai, analyze_csv_file_with_ai here - ensure to adapt file reading for Gradio file paths if necessary) ...
133
  def analyze_hl7_file_with_ai(hl7_file_path):
134
  """Analyzes HL7 file content using Discharge Guard AI."""
135
  try:
@@ -293,7 +292,7 @@ def analyze_pdf_content_ai(pdf_text_content): # Copied from your code
293
  ```text
294
  {pdf_text_content}
295
  ```
296
- * Remember, this analysis is for conceptual informational purposes only and **NOT medical advice.** Focus on summarizing and structuring the extracted data in a clinically relevant way based on the PDF content.
297
  """
298
 
299
  trace_data_detail_pdf_analysis = {
@@ -387,7 +386,6 @@ def analyze_csv_content_ai(csv_content_string): # Copied from your code
387
  return error_message, trace_data_detail_csv_analysis
388
 
389
 
390
- # ... (CallbackManager, display_form, generate_pdf_from_form, generate_pdf_from_meldrx, generate_discharge_paper_one_click, client initialization remain the same) ...
391
  class CallbackManager:
392
  def __init__(self, redirect_uri: str, client_secret: str = None):
393
  client_id = os.getenv("APPID")
@@ -408,71 +406,16 @@ class CallbackManager:
408
  if self.api.authenticate_with_code(code):
409
  self.access_token = self.api.access_token
410
  return (
411
- f"<span style='color:#00FF7F;'>Authentication successful!</span> Access Token: {self.access_token[:10]}... (truncated)" # Neon Green Success
412
  )
413
- return "<span style='color:#FF4500;'>Authentication failed. Please check the code.</span>" # Neon Orange Error
414
 
415
  def get_patient_data(self) -> str:
416
  """Fetch patient data from MeldRx"""
417
  try:
418
  if not self.access_token:
419
  logger.warning("Not authenticated when getting patient data")
420
- return "<span style='color:#FF8C00;'>Not authenticated. Please provide a valid authorization code first.</span>" # Neon Dark Orange
421
-
422
- # For demo purposes, if there's no actual API connected, return mock data
423
- # Remove this in production and use the real API call
424
- if not hasattr(self.api, "get_patients") or self.api.get_patients is None:
425
- logger.info("Using mock patient data (no API connection)")
426
- # Return mock FHIR bundle with patient data
427
- mock_data = {
428
- "resourceType": "Bundle",
429
- "type": "searchset",
430
- "total": 2,
431
- "link": [],
432
- "entry": [
433
- {
434
- "resource": {
435
- "resourceType": "Patient",
436
- "id": "patient1",
437
- "name": [
438
- {
439
- "use": "official",
440
- "family": "Smith",
441
- "given": ["John"],
442
- }
443
- ],
444
- "gender": "male",
445
- "birthDate": "1970-01-01",
446
- "address": [
447
- {"city": "Boston", "state": "MA", "postalCode": "02108"}
448
- ],
449
- }
450
- },
451
- {
452
- "resource": {
453
- "resourceType": "Patient",
454
- "id": "patient2",
455
- "name": [
456
- {
457
- "use": "official",
458
- "family": "Johnson",
459
- "given": ["Jane"],
460
- }
461
- ],
462
- "gender": "female",
463
- "birthDate": "1985-05-15",
464
- "address": [
465
- {
466
- "city": "Cambridge",
467
- "state": "MA",
468
- "postalCode": "02139",
469
- }
470
- ],
471
- }
472
- },
473
- ],
474
- }
475
- return json.dumps(mock_data, indent=2)
476
 
477
  # Real implementation with API call
478
  logger.info("Calling Meldrx API to get patients")
@@ -481,19 +424,18 @@ class CallbackManager:
481
  return (
482
  json.dumps(patients, indent=2)
483
  if patients
484
- else "<span style='color:#FFFF00;'>No patient data returned.</span>" # Neon Yellow
485
  )
486
- return "<span style='color:#DC143C;'>Failed to retrieve patient data.</span>" # Crimson Error
487
  except Exception as e:
488
  error_msg = f"Error in get_patient_data: {str(e)}"
489
  logger.error(error_msg)
490
- return f"<span style='color:#FF6347;'>Error retrieving patient data: {str(e)}</span> {str(e)}" # Tomato Error
491
-
492
 
493
  def get_patient_documents(self, patient_id: str = None):
494
  """Fetch patient documents from MeldRx"""
495
  if not self.access_token:
496
- return "<span style='color:#FF8C00;'>Not authenticated. Please provide a valid authorization code first.</span>" # Neon Dark Orange
497
 
498
  try:
499
  # This would call the actual MeldRx API to get documents for a specific patient
@@ -515,7 +457,7 @@ class CallbackManager:
515
  },
516
  ]
517
  except Exception as e:
518
- return f"<span style='color:#FF6347;'>Error retrieving patient documents: {str(e)}</span>: {str(e)}" # Tomato Error
519
 
520
 
521
  def display_form(
@@ -867,47 +809,76 @@ cyberpunk_theme = gr.themes.Monochrome(
867
  primary_hue="cyan",
868
  secondary_hue="pink",
869
  neutral_hue="slate",
870
- font=["Source Code Pro", "monospace"], # Retro monospace font
871
- font_mono=["Source Code Pro", "monospace"]
872
  )
873
 
874
  # Create the UI with the cyberpunk theme
875
- with gr.Blocks(theme=cyberpunk_theme) as demo: # Apply the theme here
876
- gr.Markdown("<h1 style='color:#00FFFF; text-shadow: 0 0 5px #00FFFF;'>Discharge Guard <span style='color:#FF00FF; text-shadow: 0 0 5px #FF00FF;'>Cyber</span></h1>") # Cyberpunk Title
877
-
878
- with gr.Tab("Authenticate with MeldRx", elem_classes="cyberpunk-tab"): # Optional: Class for tab styling
879
- gr.Markdown("<h2 style='color:#00FFFF; text-shadow: 0 0 3px #00FFFF;'>SMART on FHIR Authentication</h2>") # Neon Tab Header
880
- auth_url_output = gr.Textbox(label="Authorization URL", value=CALLBACK_MANAGER.get_auth_url(), interactive=False)
881
- gr.Markdown("<p style='color:#A9A9A9;'>Copy the URL above, open it in a browser, log in, and paste the <span style='color:#00FFFF;'>entire redirected URL</span> from your browser's address bar below.</p>") # Subdued instructions with neon highlight
882
- redirected_url_input = gr.Textbox(label="Redirected URL") # New textbox for redirected URL
883
- extract_code_button = gr.Button("Extract Authorization Code", elem_classes="cyberpunk-button") # Cyberpunk button style
884
- extracted_code_output = gr.Textbox(label="Extracted Authorization Code", interactive=False) # Textbox to show extracted code
885
-
886
- auth_code_input = gr.Textbox(label="Authorization Code (from above, or paste manually if extraction fails)", interactive=True) # Updated label to be clearer
887
- auth_submit = gr.Button("Submit Code for Authentication", elem_classes="cyberpunk-button") # Cyberpunk button style
888
- auth_result = gr.HTML(label="Authentication Result") # Use HTML for styled result
889
-
890
- patient_data_button = gr.Button("Fetch Patient Data", elem_classes="cyberpunk-button") # Cyberpunk button style
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
891
  patient_data_output = gr.Textbox(label="Patient Data", lines=10)
892
 
893
  # Add button to generate PDF from MeldRx data (No AI)
894
- meldrx_pdf_button = gr.Button("Generate PDF from MeldRx Data (No AI)", elem_classes="cyberpunk-button") # Renamed button
895
- meldrx_pdf_status = gr.Textbox(label="PDF Generation Status (No AI)") # Renamed status
896
- meldrx_pdf_download = gr.File(label="Download Generated PDF (No AI)") # Renamed download
 
 
 
 
 
 
897
 
898
  def process_redirected_url(redirected_url):
899
  """Processes the redirected URL to extract and display the authorization code."""
900
  auth_code, error_message = extract_auth_code_from_url(redirected_url)
901
  if auth_code:
902
- return auth_code, "<span style='color:#00FF7F;'>Authorization code extracted!</span>" # Neon Green Success
903
  else:
904
- return "", f"<span style='color:#FF4500;'>Could not extract authorization code.</span> {error_message or ''}" # Neon Orange Error
905
-
906
 
907
  extract_code_button.click(
908
  fn=process_redirected_url,
909
  inputs=redirected_url_input,
910
- outputs=[extracted_code_output, auth_result],# Reusing auth_result for extraction status
 
 
 
911
  )
912
 
913
  auth_submit.click(
@@ -916,11 +887,19 @@ with gr.Blocks(theme=cyberpunk_theme) as demo: # Apply the theme here
916
  outputs=auth_result,
917
  )
918
 
919
- with gr.Tab("Patient Dashboard", elem_classes="cyberpunk-tab"): # Optional: Class for tab styling
920
- gr.Markdown("<h2 style='color:#00FFFF; text-shadow: 0 0 3px #00FFFF;'>Patient Data</h2>") # Neon Tab Header
921
- dashboard_output = gr.HTML("<p style='color:#A9A9A9;'>Fetch patient data from the Authentication tab first.</p>") # Subdued placeholder text
922
-
923
- refresh_btn = gr.Button("Refresh Data", elem_classes="cyberpunk-button") # Cyberpunk button style
 
 
 
 
 
 
 
 
924
 
925
  # Simple function to update dashboard based on fetched data
926
  def update_dashboard():
@@ -931,7 +910,7 @@ with gr.Blocks(theme=cyberpunk_theme) as demo: # Apply the theme here
931
  or data.startswith("<span style='color:#DC143C;'>Failed")
932
  or data.startswith("<span style='color:#FF6347;'>Error")
933
  ):
934
- return f"<p style='color:#FF8C00;'>{data}</p>" # Show auth errors in orange
935
 
936
  try:
937
  # Parse the data
@@ -945,7 +924,7 @@ with gr.Blocks(theme=cyberpunk_theme) as demo: # Apply the theme here
945
  patients.append(resource)
946
 
947
  # Generate HTML card
948
- html = "<h3 style='color:#00FFFF; text-shadow: 0 0 2px #00FFFF;'>Patients</h3>" # Neon Sub-header
949
  for patient in patients:
950
  # Extract name
951
  name = patient.get("name", [{}])[0]
@@ -968,13 +947,16 @@ with gr.Blocks(theme=cyberpunk_theme) as demo: # Apply the theme here
968
 
969
  return html
970
  except Exception as e:
971
- return f"<p style='color:#FF6347;'>Error parsing patient data: {str(e)}</p>" # Tomato Error
972
  except Exception as e:
973
- return f"<p style='color:#FF6347;'>Error fetching patient data: {str(e)}</p>" # Tomato Error
974
 
 
975
 
976
- with gr.Tab("Discharge Form", elem_classes="cyberpunk-tab"): # Optional: Class for tab styling
977
- gr.Markdown("<h2 style='color:#00FFFF; text-shadow: 0 0 3px #00FFFF;'>Patient Details</h2>") # Neon Tab Header
 
 
978
  with gr.Row():
979
  first_name = gr.Textbox(label="First Name")
980
  last_name = gr.Textbox(label="Last Name")
@@ -988,7 +970,9 @@ with gr.Blocks(theme=cyberpunk_theme) as demo: # Apply the theme here
988
  city = gr.Textbox(label="City")
989
  state = gr.Textbox(label="State")
990
  zip_code = gr.Textbox(label="Zip Code")
991
- gr.Markdown("<h2 style='color:#00FFFF; text-shadow: 0 0 3px #00FFFF;'>Primary Healthcare Professional Details</h2>") # Neon Sub-header
 
 
992
  with gr.Row():
993
  doctor_first_name = gr.Textbox(label="Doctor's First Name")
994
  doctor_last_name = gr.Textbox(label="Doctor's Last Name")
@@ -999,7 +983,9 @@ with gr.Blocks(theme=cyberpunk_theme) as demo: # Apply the theme here
999
  doctor_city = gr.Textbox(label="City")
1000
  doctor_state = gr.Textbox(label="State")
1001
  doctor_zip = gr.Textbox(label="Zip Code")
1002
- gr.Markdown("<h2 style='color:#00FFFF; text-shadow: 0 0 3px #00FFFF;'>Admission and Discharge Details</h2>") # Neon Sub-header
 
 
1003
  with gr.Row():
1004
  admission_date = gr.Textbox(label="Date of Admission")
1005
  referral_source = gr.Textbox(label="Source of Referral")
@@ -1011,24 +997,36 @@ with gr.Blocks(theme=cyberpunk_theme) as demo: # Apply the theme here
1011
  label="Discharge Reason",
1012
  )
1013
  date_of_death = gr.Textbox(label="Date of Death (if applicable)")
1014
- gr.Markdown("<h2 style='color:#00FFFF; text-shadow: 0 0 3px #00FFFF;'>Diagnosis & Procedures</h2>") # Neon Sub-header
 
 
1015
  diagnosis = gr.Textbox(label="Diagnosis")
1016
  procedures = gr.Textbox(label="Operation & Procedures")
1017
- gr.Markdown("<h2 style='color:#00FFFF; text-shadow: 0 0 3px #00FFFF;'>Medication Details</h2>") # Neon Sub-header
 
 
1018
  medications = gr.Textbox(label="Medication on Discharge")
1019
- gr.Markdown("<h2 style='color:#00FFFF; text-shadow: 0 0 3px #00FFFF;'>Prepared By</h2>") # Neon Sub-header
 
 
1020
  with gr.Row():
1021
  preparer_name = gr.Textbox(label="Name")
1022
  preparer_job_title = gr.Textbox(label="Job Title")
1023
 
1024
  # Add buttons for both display form and generate PDF
1025
  with gr.Row():
1026
- submit_display = gr.Button("Display Form", elem_classes="cyberpunk-button") # Cyberpunk button style
1027
- submit_pdf = gr.Button("Generate PDF (No AI)", elem_classes="cyberpunk-button") # Renamed button to clarify no AI and styled
 
 
 
 
1028
 
1029
  # Output areas
1030
- form_output = gr.HTML() # Use HTML to render styled form
1031
- pdf_output = gr.File(label="Download PDF (No AI)") # Renamed output to clarify no AI
 
 
1032
 
1033
  # Connect the display form button
1034
  submit_display.click(
@@ -1064,7 +1062,7 @@ with gr.Blocks(theme=cyberpunk_theme) as demo: # Apply the theme here
1064
  preparer_name,
1065
  preparer_job_title,
1066
  ],
1067
- outputs=form_output
1068
  )
1069
 
1070
  # Connect the generate PDF button (No AI version)
@@ -1101,35 +1099,44 @@ with gr.Blocks(theme=cyberpunk_theme) as demo: # Apply the theme here
1101
  preparer_name,
1102
  preparer_job_title,
1103
  ],
1104
- outputs=pdf_output
1105
  )
1106
 
1107
- with gr.Tab("Medical File Analysis", elem_classes="cyberpunk-tab"): # Optional: Class for tab styling
1108
- gr.Markdown("<h2 style='color:#00FFFF; text-shadow: 0 0 3px #00FFFF;'>Analyze Medical Files with Discharge Guard AI</h2>") # Neon Tab Header
 
 
 
 
1109
  with gr.Column():
1110
  dicom_file = gr.File(
1111
  file_types=[".dcm"], label="Upload DICOM File (.dcm)"
1112
  )
1113
  dicom_ai_output = gr.Textbox(label="DICOM Analysis Report", lines=5)
1114
- analyze_dicom_button = gr.Button("Analyze DICOM with AI", elem_classes="cyberpunk-button") # Cyberpunk button style
 
 
1115
 
1116
- hl7_file = gr.File(
1117
- file_types=[".hl7"], label="Upload HL7 File (.hl7)"
1118
- )
1119
  hl7_ai_output = gr.Textbox(label="HL7 Analysis Report", lines=5)
1120
- analyze_hl7_button = gr.Button("Analyze HL7 with AI", elem_classes="cyberpunk-button") # Cyberpunk button style
 
 
1121
 
1122
- xml_file = gr.File(
1123
- file_types=[".xml"], label="Upload XML File (.xml)"
1124
- )
1125
  xml_ai_output = gr.Textbox(label="XML Analysis Report", lines=5)
1126
- analyze_xml_button = gr.Button("Analyze XML with AI", elem_classes="cyberpunk-button") # Cyberpunk button style
 
 
1127
 
1128
  ccda_file = gr.File(
1129
- file_types=[".xml", ".cda", ".ccd"], label="Upload CCDA File (.xml, .cda, .ccd)"
 
1130
  )
1131
  ccda_ai_output = gr.Textbox(label="CCDA Analysis Report", lines=5)
1132
- analyze_ccda_button = gr.Button("Analyze CCDA with AI", elem_classes="cyberpunk-button") # Cyberpunk button style
 
 
1133
 
1134
  ccd_file = gr.File(
1135
  file_types=[".ccd"],
@@ -1138,44 +1145,46 @@ with gr.Blocks(theme=cyberpunk_theme) as demo: # Apply the theme here
1138
  ccd_ai_output = gr.Textbox(
1139
  label="CCD Analysis Report", lines=5
1140
  ) # Redundant
1141
- analyze_ccd_button = gr.Button("Analyze CCD with AI", elem_classes="cyberpunk-button") # Cyberpunk button style # Redundant
1142
- pdf_file = gr.File(
1143
- file_types=[".pdf"], label="Upload PDF File (.pdf)"
1144
- )
1145
  pdf_ai_output = gr.Textbox(label="PDF Analysis Report", lines=5)
1146
- analyze_pdf_button = gr.Button("Analyze PDF with AI", elem_classes="cyberpunk-button") # Cyberpunk button style
 
 
1147
 
1148
- csv_file = gr.File(
1149
- file_types=[".csv"], label="Upload CSV File (.csv)"
1150
- )
1151
  csv_ai_output = gr.Textbox(label="CSV Analysis Report", lines=5)
1152
- analyze_csv_button = gr.Button("Analyze CSV with AI", elem_classes="cyberpunk-button") # Cyberpunk button style
 
 
1153
 
1154
  # Connect AI Analysis Buttons - using REAL AI functions now
1155
  analyze_dicom_button.click(
1156
  analyze_dicom_file_with_ai, # Call REAL AI function
1157
  inputs=dicom_file,
1158
- outputs=dicom_ai_output
1159
  )
1160
  analyze_hl7_button.click(
1161
  analyze_hl7_file_with_ai, # Call REAL AI function
1162
  inputs=hl7_file,
1163
- outputs=hl7_ai_output
1164
  )
1165
  analyze_xml_button.click(
1166
  analyze_cda_xml_file_with_ai, # Call REAL AI function
1167
  inputs=xml_file,
1168
- outputs=xml_ai_output
1169
  )
1170
  analyze_ccda_button.click(
1171
  analyze_cda_xml_file_with_ai, # Call REAL AI function
1172
  inputs=ccda_file,
1173
- outputs=ccda_ai_output
1174
  )
1175
  analyze_ccd_button.click( # Redundant button, but kept for UI if needed
1176
  analyze_cda_xml_file_with_ai, # Call REAL AI function
1177
  inputs=ccd_file,
1178
- outputs=ccd_ai_output
1179
  )
1180
  analyze_pdf_button.click(
1181
  analyze_pdf_file_with_ai, inputs=pdf_file, outputs=pdf_ai_output
@@ -1187,9 +1196,12 @@ with gr.Blocks(theme=cyberpunk_theme) as demo: # Apply the theme here
1187
  with gr.Tab(
1188
  "One-Click Discharge Paper (AI)", elem_classes="cyberpunk-tab"
1189
  ): # New Tab for One-Click Discharge Paper with AI, styled
1190
- gr.Markdown("<h2 style='color:#00FFFF; text-shadow: 0 0 3px #00FFFF;'>One-Click Medical Discharge Paper Generation with AI Content</h2>") # Neon Tab Header
 
 
1191
  one_click_ai_pdf_button = gr.Button(
1192
- "Generate Discharge Paper with AI (One-Click)", elem_classes="cyberpunk-button"
 
1193
  ) # Updated button label and styled
1194
  one_click_ai_pdf_status = gr.Textbox(
1195
  label="Discharge Paper Generation Status (AI)"
@@ -1206,21 +1218,17 @@ with gr.Blocks(theme=cyberpunk_theme) as demo: # Apply the theme here
1206
 
1207
  # Connect the patient data buttons
1208
  patient_data_button.click(
1209
- fn=CALLBACK_MANAGER.get_patient_data,
1210
- inputs=None,
1211
- outputs=patient_data_output
1212
  )
1213
 
1214
  # Connect refresh button to update dashboard
1215
- refresh_btn.click(
1216
- fn=update_dashboard, inputs=None, outputs=dashboard_output
1217
- )
1218
 
1219
  # Corrected the button click function name here to `generate_pdf_from_meldrx` (No AI PDF)
1220
  meldrx_pdf_button.click(
1221
  fn=generate_pdf_from_meldrx,
1222
  inputs=patient_data_output,
1223
- outputs=[meldrx_pdf_download, meldrx_pdf_status]
1224
  )
1225
 
1226
  # Connect patient data updates to dashboard
@@ -1228,5 +1236,6 @@ with gr.Blocks(theme=cyberpunk_theme) as demo: # Apply the theme here
1228
  fn=update_dashboard, inputs=None, outputs=dashboard_output
1229
  )
1230
 
 
1231
  # Launch with sharing enabled for public access
1232
  demo.launch(ssr_mode=False)
 
121
  top_p=0.9,
122
  )
123
  the_response = response.choices[0].message.content
124
+ return the_response, trace_data_detail_dicom_ai
125
 
126
  except Exception as e:
127
  error_message = f"AI Analysis Error in analyze_dicom_content_ai (DICOM Metadata): {e}"
128
  trace_data_detail_dicom_analysis["error"] = f"AI Analysis Error: {e}"
129
+ return error_message, trace_data_detail_dicom_image_analysis
130
 
131
 
 
132
  def analyze_hl7_file_with_ai(hl7_file_path):
133
  """Analyzes HL7 file content using Discharge Guard AI."""
134
  try:
 
292
  ```text
293
  {pdf_text_content}
294
  ```
295
+ * Remember, this analysis is for conceptual informational purposes only and **NOT medical advice.** Focus on deep summarization and structuring the extracted data in a clinically relevant way based on the PDF content.
296
  """
297
 
298
  trace_data_detail_pdf_analysis = {
 
386
  return error_message, trace_data_detail_csv_analysis
387
 
388
 
 
389
  class CallbackManager:
390
  def __init__(self, redirect_uri: str, client_secret: str = None):
391
  client_id = os.getenv("APPID")
 
406
  if self.api.authenticate_with_code(code):
407
  self.access_token = self.api.access_token
408
  return (
409
+ f"<span style='color:#00FF7F;'>Authentication successful!</span> Access Token: {self.access_token[:10]}... (truncated)" # Neon Green Success
410
  )
411
+ return "<span style='color:#FF4500;'>Authentication failed. Please check the code.</span>" # Neon Orange Error
412
 
413
  def get_patient_data(self) -> str:
414
  """Fetch patient data from MeldRx"""
415
  try:
416
  if not self.access_token:
417
  logger.warning("Not authenticated when getting patient data")
418
+ return "<span style='color:#FF8C00;'>Not authenticated. Please provide a valid authorization code first.</span>" # Neon Dark Orange
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
419
 
420
  # Real implementation with API call
421
  logger.info("Calling Meldrx API to get patients")
 
424
  return (
425
  json.dumps(patients, indent=2)
426
  if patients
427
+ else "<span style='color:#FFFF00;'>No patient data returned.</span>" # Neon Yellow
428
  )
429
+ return "<span style='color:#DC143C;'>Failed to retrieve patient data.</span>" # Crimson Error
430
  except Exception as e:
431
  error_msg = f"Error in get_patient_data: {str(e)}"
432
  logger.error(error_msg)
433
+ return f"<span style='color:#FF6347;'>Error retrieving patient data: {str(e)}</span> {str(e)}" # Tomato Error
 
434
 
435
  def get_patient_documents(self, patient_id: str = None):
436
  """Fetch patient documents from MeldRx"""
437
  if not self.access_token:
438
+ return "<span style='color:#FF8C00;'>Not authenticated. Please provide a valid authorization code first.</span>" # Neon Dark Orange
439
 
440
  try:
441
  # This would call the actual MeldRx API to get documents for a specific patient
 
457
  },
458
  ]
459
  except Exception as e:
460
+ return f"<span style='color:#FF6347;'>Error retrieving patient documents: {str(e)}</span>: {str(e)}" # Tomato Error
461
 
462
 
463
  def display_form(
 
809
  primary_hue="cyan",
810
  secondary_hue="pink",
811
  neutral_hue="slate",
812
+ font=["Source Code Pro", "monospace"], # Retro monospace font
813
+ font_mono=["Source Code Pro", "monospace"],
814
  )
815
 
816
  # Create the UI with the cyberpunk theme
817
+ with gr.Blocks(theme=cyberpunk_theme) as demo: # Apply the theme here
818
+ gr.Markdown(
819
+ "<h1 style='color:#00FFFF; text-shadow: 0 0 5px #00FFFF;'>Discharge Guard <span style='color:#FF00FF; text-shadow: 0 0 5px #FF00FF;'>Cyber</span></h1>"
820
+ ) # Cyberpunk Title
821
+
822
+ with gr.Tab("Authenticate with MeldRx", elem_classes="cyberpunk-tab"): # Optional: Class for tab styling
823
+ gr.Markdown(
824
+ "<h2 style='color:#00FFFF; text-shadow: 0 0 3px #00FFFF;'>SMART on FHIR Authentication</h2>"
825
+ ) # Neon Tab Header
826
+ auth_url_output = gr.Textbox(
827
+ label="Authorization URL",
828
+ value=CALLBACK_MANAGER.get_auth_url(),
829
+ interactive=False,
830
+ )
831
+ gr.Markdown(
832
+ "<p style='color:#A9A9A9;'>Copy the URL above, open it in a browser, log in, and paste the <span style='color:#00FFFF;'>entire redirected URL</span> from your browser's address bar below.</p>"
833
+ ) # Subdued instructions with neon highlight
834
+ redirected_url_input = gr.Textbox(label="Redirected URL") # New textbox for redirected URL
835
+ extract_code_button = gr.Button(
836
+ "Extract Authorization Code", elem_classes="cyberpunk-button"
837
+ ) # Cyberpunk button style
838
+ extracted_code_output = gr.Textbox(
839
+ label="Extracted Authorization Code", interactive=False
840
+ ) # Textbox to show extracted code
841
+
842
+ auth_code_input = gr.Textbox(
843
+ label="Authorization Code (from above, or paste manually if extraction fails)",
844
+ interactive=True,
845
+ ) # Updated label to be clearer
846
+ auth_submit = gr.Button(
847
+ "Submit Code for Authentication", elem_classes="cyberpunk-button"
848
+ ) # Cyberpunk button style
849
+ auth_result = gr.HTML(label="Authentication Result") # Use HTML for styled result
850
+
851
+ patient_data_button = gr.Button(
852
+ "Fetch Patient Data", elem_classes="cyberpunk-button"
853
+ ) # Cyberpunk button style
854
  patient_data_output = gr.Textbox(label="Patient Data", lines=10)
855
 
856
  # Add button to generate PDF from MeldRx data (No AI)
857
+ meldrx_pdf_button = gr.Button(
858
+ "Generate PDF from MeldRx Data (No AI)", elem_classes="cyberpunk-button"
859
+ ) # Renamed button
860
+ meldrx_pdf_status = gr.Textbox(
861
+ label="PDF Generation Status (No AI)"
862
+ ) # Renamed status
863
+ meldrx_pdf_download = gr.File(
864
+ label="Download Generated PDF (No AI)"
865
+ ) # Renamed download
866
 
867
  def process_redirected_url(redirected_url):
868
  """Processes the redirected URL to extract and display the authorization code."""
869
  auth_code, error_message = extract_auth_code_from_url(redirected_url)
870
  if auth_code:
871
+ return auth_code, "<span style='color:#00FF7F;'>Authorization code extracted!</span>" # Neon Green Success
872
  else:
873
+ return "", f"<span style='color:#FF4500;'>Could not extract authorization code.</span> {error_message or ''}" # Neon Orange Error
 
874
 
875
  extract_code_button.click(
876
  fn=process_redirected_url,
877
  inputs=redirected_url_input,
878
+ outputs=[
879
+ extracted_code_output,
880
+ auth_result,
881
+ ], # Reusing auth_result for extraction status
882
  )
883
 
884
  auth_submit.click(
 
887
  outputs=auth_result,
888
  )
889
 
890
+ with gr.Tab(
891
+ "Patient Dashboard", elem_classes="cyberpunk-tab"
892
+ ): # Optional: Class for tab styling
893
+ gr.Markdown(
894
+ "<h2 style='color:#00FFFF; text-shadow: 0 0 3px #00FFFF;'>Patient Data</h2>"
895
+ ) # Neon Tab Header
896
+ dashboard_output = gr.HTML(
897
+ "<p style='color:#A9A9A9;'>Fetch patient data from the Authentication tab first.</p>"
898
+ ) # Subdued placeholder text
899
+
900
+ refresh_btn = gr.Button(
901
+ "Refresh Data", elem_classes="cyberpunk-button"
902
+ ) # Cyberpunk button style
903
 
904
  # Simple function to update dashboard based on fetched data
905
  def update_dashboard():
 
910
  or data.startswith("<span style='color:#DC143C;'>Failed")
911
  or data.startswith("<span style='color:#FF6347;'>Error")
912
  ):
913
+ return f"<p style='color:#FF8C00;'>{data}</p>" # Show auth errors in orange
914
 
915
  try:
916
  # Parse the data
 
924
  patients.append(resource)
925
 
926
  # Generate HTML card
927
+ html = "<h3 style='color:#00FFFF; text-shadow: 0 0 2px #00FFFF;'>Patients</h3>" # Neon Sub-header
928
  for patient in patients:
929
  # Extract name
930
  name = patient.get("name", [{}])[0]
 
947
 
948
  return html
949
  except Exception as e:
950
+ return f"<p style='color:#FF6347;'>Error parsing patient data: {str(e)}</p>" # Tomato Error
951
  except Exception as e:
952
+ return f"<p style='color:#FF6347;'>Error fetching patient data: {str(e)}</p>" # Tomato Error
953
 
954
+ refresh_btn.click(fn=update_dashboard, inputs=None, outputs=dashboard_output)
955
 
956
+ with gr.Tab("Discharge Form", elem_classes="cyberpunk-tab"): # Optional: Class for tab styling
957
+ gr.Markdown(
958
+ "<h2 style='color:#00FFFF; text-shadow: 0 0 3px #00FFFF;'>Patient Details</h2>"
959
+ ) # Neon Tab Header
960
  with gr.Row():
961
  first_name = gr.Textbox(label="First Name")
962
  last_name = gr.Textbox(label="Last Name")
 
970
  city = gr.Textbox(label="City")
971
  state = gr.Textbox(label="State")
972
  zip_code = gr.Textbox(label="Zip Code")
973
+ gr.Markdown(
974
+ "<h2 style='color:#00FFFF; text-shadow: 0 0 3px #00FFFF;'>Primary Healthcare Professional Details</h2>"
975
+ ) # Neon Sub-header
976
  with gr.Row():
977
  doctor_first_name = gr.Textbox(label="Doctor's First Name")
978
  doctor_last_name = gr.Textbox(label="Doctor's Last Name")
 
983
  doctor_city = gr.Textbox(label="City")
984
  doctor_state = gr.Textbox(label="State")
985
  doctor_zip = gr.Textbox(label="Zip Code")
986
+ gr.Markdown(
987
+ "<h2 style='color:#00FFFF; text-shadow: 0 0 3px #00FFFF;'>Admission and Discharge Details</h2>"
988
+ ) # Neon Sub-header
989
  with gr.Row():
990
  admission_date = gr.Textbox(label="Date of Admission")
991
  referral_source = gr.Textbox(label="Source of Referral")
 
997
  label="Discharge Reason",
998
  )
999
  date_of_death = gr.Textbox(label="Date of Death (if applicable)")
1000
+ gr.Markdown(
1001
+ "<h2 style='color:#00FFFF; text-shadow: 0 0 3px #00FFFF;'>Diagnosis & Procedures</h2>"
1002
+ ) # Neon Sub-header
1003
  diagnosis = gr.Textbox(label="Diagnosis")
1004
  procedures = gr.Textbox(label="Operation & Procedures")
1005
+ gr.Markdown(
1006
+ "<h2 style='color:#00FFFF; text-shadow: 0 0 3px #00FFFF;'>Medication Details</h2>"
1007
+ ) # Neon Sub-header
1008
  medications = gr.Textbox(label="Medication on Discharge")
1009
+ gr.Markdown(
1010
+ "<h2 style='color:#00FFFF; text-shadow: 0 0 3px #00FFFF;'>Prepared By</h2>"
1011
+ ) # Neon Sub-header
1012
  with gr.Row():
1013
  preparer_name = gr.Textbox(label="Name")
1014
  preparer_job_title = gr.Textbox(label="Job Title")
1015
 
1016
  # Add buttons for both display form and generate PDF
1017
  with gr.Row():
1018
+ submit_display = gr.Button(
1019
+ "Display Form", elem_classes="cyberpunk-button"
1020
+ ) # Cyberpunk button style
1021
+ submit_pdf = gr.Button(
1022
+ "Generate PDF (No AI)", elem_classes="cyberpunk-button"
1023
+ ) # Renamed button to clarify no AI and styled
1024
 
1025
  # Output areas
1026
+ form_output = gr.HTML() # Use HTML to render styled form
1027
+ pdf_output = gr.File(
1028
+ label="Download PDF (No AI)"
1029
+ ) # Renamed output to clarify no AI
1030
 
1031
  # Connect the display form button
1032
  submit_display.click(
 
1062
  preparer_name,
1063
  preparer_job_title,
1064
  ],
1065
+ outputs=form_output,
1066
  )
1067
 
1068
  # Connect the generate PDF button (No AI version)
 
1099
  preparer_name,
1100
  preparer_job_title,
1101
  ],
1102
+ outputs=pdf_output,
1103
  )
1104
 
1105
+ with gr.Tab(
1106
+ "Medical File Analysis", elem_classes="cyberpunk-tab"
1107
+ ): # Optional: Class for tab styling
1108
+ gr.Markdown(
1109
+ "<h2 style='color:#00FFFF; text-shadow: 0 0 3px #00FFFF;'>Analyze Medical Files with Discharge Guard AI</h2>"
1110
+ ) # Neon Tab Header
1111
  with gr.Column():
1112
  dicom_file = gr.File(
1113
  file_types=[".dcm"], label="Upload DICOM File (.dcm)"
1114
  )
1115
  dicom_ai_output = gr.Textbox(label="DICOM Analysis Report", lines=5)
1116
+ analyze_dicom_button = gr.Button(
1117
+ "Analyze DICOM with AI", elem_classes="cyberpunk-button"
1118
+ ) # Cyberpunk button style
1119
 
1120
+ hl7_file = gr.File(file_types=[".hl7"], label="Upload HL7 File (.hl7)")
 
 
1121
  hl7_ai_output = gr.Textbox(label="HL7 Analysis Report", lines=5)
1122
+ analyze_hl7_button = gr.Button(
1123
+ "Analyze HL7 with AI", elem_classes="cyberpunk-button"
1124
+ ) # Cyberpunk button style
1125
 
1126
+ xml_file = gr.File(file_types=[".xml"], label="Upload XML File (.xml)")
 
 
1127
  xml_ai_output = gr.Textbox(label="XML Analysis Report", lines=5)
1128
+ analyze_xml_button = gr.Button(
1129
+ "Analyze XML with AI", elem_classes="cyberpunk-button"
1130
+ ) # Cyberpunk button style
1131
 
1132
  ccda_file = gr.File(
1133
+ file_types=[".xml", ".cda", ".ccd"],
1134
+ label="Upload CCDA File (.xml, .cda, .ccd)",
1135
  )
1136
  ccda_ai_output = gr.Textbox(label="CCDA Analysis Report", lines=5)
1137
+ analyze_ccda_button = gr.Button(
1138
+ "Analyze CCDA with AI", elem_classes="cyberpunk-button"
1139
+ ) # Cyberpunk button style
1140
 
1141
  ccd_file = gr.File(
1142
  file_types=[".ccd"],
 
1145
  ccd_ai_output = gr.Textbox(
1146
  label="CCD Analysis Report", lines=5
1147
  ) # Redundant
1148
+ analyze_ccd_button = gr.Button(
1149
+ "Analyze CCD with AI", elem_classes="cyberpunk-button"
1150
+ ) # Cyberpunk button style # Redundant
1151
+ pdf_file = gr.File(file_types=[".pdf"], label="Upload PDF File (.pdf)")
1152
  pdf_ai_output = gr.Textbox(label="PDF Analysis Report", lines=5)
1153
+ analyze_pdf_button = gr.Button(
1154
+ "Analyze PDF with AI", elem_classes="cyberpunk-button"
1155
+ ) # Cyberpunk button style
1156
 
1157
+ csv_file = gr.File(file_types=[".csv"], label="Upload CSV File (.csv)")
 
 
1158
  csv_ai_output = gr.Textbox(label="CSV Analysis Report", lines=5)
1159
+ analyze_csv_button = gr.Button(
1160
+ "Analyze CSV with AI", elem_classes="cyberpunk-button"
1161
+ ) # Cyberpunk button style
1162
 
1163
  # Connect AI Analysis Buttons - using REAL AI functions now
1164
  analyze_dicom_button.click(
1165
  analyze_dicom_file_with_ai, # Call REAL AI function
1166
  inputs=dicom_file,
1167
+ outputs=dicom_ai_output,
1168
  )
1169
  analyze_hl7_button.click(
1170
  analyze_hl7_file_with_ai, # Call REAL AI function
1171
  inputs=hl7_file,
1172
+ outputs=hl7_ai_output,
1173
  )
1174
  analyze_xml_button.click(
1175
  analyze_cda_xml_file_with_ai, # Call REAL AI function
1176
  inputs=xml_file,
1177
+ outputs=xml_ai_output,
1178
  )
1179
  analyze_ccda_button.click(
1180
  analyze_cda_xml_file_with_ai, # Call REAL AI function
1181
  inputs=ccda_file,
1182
+ outputs=ccda_ai_output,
1183
  )
1184
  analyze_ccd_button.click( # Redundant button, but kept for UI if needed
1185
  analyze_cda_xml_file_with_ai, # Call REAL AI function
1186
  inputs=ccd_file,
1187
+ outputs=ccd_ai_output,
1188
  )
1189
  analyze_pdf_button.click(
1190
  analyze_pdf_file_with_ai, inputs=pdf_file, outputs=pdf_ai_output
 
1196
  with gr.Tab(
1197
  "One-Click Discharge Paper (AI)", elem_classes="cyberpunk-tab"
1198
  ): # New Tab for One-Click Discharge Paper with AI, styled
1199
+ gr.Markdown(
1200
+ "<h2 style='color:#00FFFF; text-shadow: 0 0 3px #00FFFF;'>One-Click Medical Discharge Paper Generation with AI Content</h2>"
1201
+ ) # Neon Tab Header
1202
  one_click_ai_pdf_button = gr.Button(
1203
+ "Generate Discharge Paper with AI (One-Click)",
1204
+ elem_classes="cyberpunk-button",
1205
  ) # Updated button label and styled
1206
  one_click_ai_pdf_status = gr.Textbox(
1207
  label="Discharge Paper Generation Status (AI)"
 
1218
 
1219
  # Connect the patient data buttons
1220
  patient_data_button.click(
1221
+ fn=CALLBACK_MANAGER.get_patient_data, inputs=None, outputs=patient_data_output
 
 
1222
  )
1223
 
1224
  # Connect refresh button to update dashboard
1225
+ refresh_btn.click(fn=update_dashboard, inputs=None, outputs=dashboard_output)
 
 
1226
 
1227
  # Corrected the button click function name here to `generate_pdf_from_meldrx` (No AI PDF)
1228
  meldrx_pdf_button.click(
1229
  fn=generate_pdf_from_meldrx,
1230
  inputs=patient_data_output,
1231
+ outputs=[meldrx_pdf_download, meldrx_pdf_status],
1232
  )
1233
 
1234
  # Connect patient data updates to dashboard
 
1236
  fn=update_dashboard, inputs=None, outputs=dashboard_output
1237
  )
1238
 
1239
+
1240
  # Launch with sharing enabled for public access
1241
  demo.launch(ssr_mode=False)