updated UI code ✅✅
Browse files- mediSync/app.py +41 -52
mediSync/app.py
CHANGED
|
@@ -29,6 +29,15 @@ from utils.visualization import (
|
|
| 29 |
plot_multimodal_results,
|
| 30 |
plot_report_entities,
|
| 31 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
|
| 33 |
# Set up logging
|
| 34 |
logging.basicConfig(
|
|
@@ -41,7 +50,6 @@ logger = logging.getLogger(__name__)
|
|
| 41 |
# Create temporary directory for sample data if it doesn't exist
|
| 42 |
os.makedirs(os.path.join(parent_dir, "data", "sample"), exist_ok=True)
|
| 43 |
|
| 44 |
-
|
| 45 |
# Import configuration for end consultation logic
|
| 46 |
try:
|
| 47 |
from .config import get_flask_urls, get_doctors_page_urls, TIMEOUT_SETTINGS
|
|
@@ -153,8 +161,7 @@ class MediSyncApp:
|
|
| 153 |
html_result = f"""
|
| 154 |
<div class="medisync-card medisync-card-bg medisync-force-text">
|
| 155 |
<h2 class="medisync-title medisync-blue">
|
| 156 |
-
<
|
| 157 |
-
<span style="font-size:1.45em; font-weight:900; letter-spacing:1px; text-shadow:0 2px 8px #00bfae33;">X-ray Analysis Results</span>
|
| 158 |
</h2>
|
| 159 |
<p><strong>Primary Finding:</strong> {results.get("primary_finding", "Unknown")}</p>
|
| 160 |
<p><strong>Confidence:</strong> {results.get("confidence", 0):.1%}</p>
|
|
@@ -203,8 +210,7 @@ class MediSyncApp:
|
|
| 203 |
html_result = f"""
|
| 204 |
<div class="medisync-card medisync-card-bg medisync-force-text">
|
| 205 |
<h2 class="medisync-title medisync-green">
|
| 206 |
-
<
|
| 207 |
-
<span style="font-size:1.45em; font-weight:900; letter-spacing:1px; text-shadow:0 2px 8px #28a74533;">Text Analysis Results</span>
|
| 208 |
</h2>
|
| 209 |
<p><strong>Severity Level:</strong> {results.get("severity", {}).get("level", "Unknown")}</p>
|
| 210 |
<p><strong>Severity Score:</strong> {results.get("severity", {}).get("score", 0)}/4</p>
|
|
@@ -273,8 +279,7 @@ class MediSyncApp:
|
|
| 273 |
html_result = f"""
|
| 274 |
<div class="medisync-card medisync-card-bg medisync-force-text">
|
| 275 |
<h2 class="medisync-title medisync-purple">
|
| 276 |
-
<
|
| 277 |
-
<span style="font-size:1.45em; font-weight:900; letter-spacing:1px; text-shadow:0 2px 8px #6c63ff33;">Multimodal Analysis Results</span>
|
| 278 |
</h2>
|
| 279 |
<h3>Overview</h3>
|
| 280 |
<p><strong>Primary Finding:</strong> {results.get("primary_finding", "Unknown")}</p>
|
|
@@ -435,9 +440,7 @@ def create_interface():
|
|
| 435 |
margin-bottom: 0.7em;
|
| 436 |
letter-spacing: 1px;
|
| 437 |
text-shadow: 0 2px 8px #00bfae33, 0 1px 0 #fff;
|
| 438 |
-
display:
|
| 439 |
-
align-items: center;
|
| 440 |
-
gap: 10px;
|
| 441 |
}
|
| 442 |
.medisync-blue { color: #00bfae; }
|
| 443 |
.medisync-green { color: #28a745; }
|
|
@@ -503,23 +506,13 @@ def create_interface():
|
|
| 503 |
html[data-theme="dark"] .medisync-force-text, html[data-theme="dark"] .medisync-force-text * {
|
| 504 |
color: #f8fafc !important;
|
| 505 |
}
|
| 506 |
-
/* End consultation status output
|
| 507 |
#end_consultation_status, #end_consultation_status * {
|
| 508 |
-
color:
|
| 509 |
background: #fff !important;
|
| 510 |
-
}
|
| 511 |
-
html[data-theme="dark"] #end_consultation_status, html[data-theme="dark"] #end_consultation_status * {
|
| 512 |
-
color: #f8fafc !important;
|
| 513 |
-
background: #23272f !important;
|
| 514 |
-
}
|
| 515 |
-
/* Style for the popup/status after end consultation for visibility */
|
| 516 |
-
#end_consultation_status, #end_consultation_status * {
|
| 517 |
font-size: 1.12rem !important;
|
| 518 |
font-weight: 600 !important;
|
| 519 |
}
|
| 520 |
-
html[data-theme="dark"] #end_consultation_status, html[data-theme="dark"] #end_consultation_status * {
|
| 521 |
-
color: #f8fafc !important;
|
| 522 |
-
}
|
| 523 |
/* Style the buttons inside the end consultation status popup */
|
| 524 |
#end_consultation_status button {
|
| 525 |
font-size: 1rem !important;
|
|
@@ -539,22 +532,19 @@ def create_interface():
|
|
| 539 |
) as interface:
|
| 540 |
gr.Markdown(
|
| 541 |
"""
|
| 542 |
-
<div style="
|
| 543 |
-
<
|
| 544 |
-
|
| 545 |
-
MediSync
|
| 546 |
-
<img src="https://cdn.jsdelivr.net/gh/saqib-ali-buriro/medivance-assets/ai_heartbeat.png" alt="AI Heartbeat" style="height: 32px; vertical-align: middle; margin-left: 8px;">
|
| 547 |
</span>
|
| 548 |
-
<img src="https://cdn.jsdelivr.net/gh/saqib-ali-buriro/medivance-assets/doctor_icon.png" alt="Doctor" style="height: 38px; border-radius: 8px; background: #fff; box-shadow: 0 2px 8px 0 rgba(26,115,232,0.10); margin-left: 8px;">
|
| 549 |
</div>
|
| 550 |
-
<div style="font-size: 1.22rem; margin-bottom: 1.2em; font-weight: 600;
|
| 551 |
-
<span
|
| 552 |
</div>
|
| 553 |
<div style="font-size: 1.09rem; margin-bottom: 1.2em;">
|
| 554 |
-
<span
|
| 555 |
</div>
|
| 556 |
<div style="margin-bottom: 1.2em;">
|
| 557 |
-
<ul style="font-size: 1.04rem;
|
| 558 |
<li>Upload a chest X-ray image</li>
|
| 559 |
<li>Enter the corresponding medical report text</li>
|
| 560 |
<li>Choose the analysis type: <b>Image</b>, <b>Text</b>, or <b>Multimodal</b></li>
|
|
@@ -661,8 +651,7 @@ def create_interface():
|
|
| 661 |
"""
|
| 662 |
<div class="medisync-card medisync-card-bg medisync-force-text">
|
| 663 |
<h2 class="medisync-title medisync-blue">
|
| 664 |
-
<
|
| 665 |
-
<span style="font-size:1.45em; font-weight:900; letter-spacing:1px; text-shadow:0 2px 8px #00bfae33;">About MediSync</span>
|
| 666 |
</h2>
|
| 667 |
<p>
|
| 668 |
<b>MediSync</b> is an AI-powered healthcare solution that uses multi-modal analysis to provide comprehensive insights from medical images and reports.
|
|
@@ -708,17 +697,17 @@ def create_interface():
|
|
| 708 |
)
|
| 709 |
|
| 710 |
def handle_end_consultation(appointment_id):
|
| 711 |
-
#
|
| 712 |
if not appointment_id or appointment_id.strip() == "":
|
| 713 |
-
return "<div
|
| 714 |
result = complete_appointment(appointment_id.strip())
|
| 715 |
if result["status"] == "success":
|
| 716 |
doctors_urls = get_doctors_page_urls()
|
| 717 |
html_response = f"""
|
| 718 |
-
<div
|
| 719 |
-
<h3 style="color: #
|
| 720 |
-
<p
|
| 721 |
-
<p
|
| 722 |
<button onclick="window.open('{doctors_urls['local']}', '_blank')"
|
| 723 |
style="background-color: #00bfae; color: white; padding: 8px 18px; border: none; border-radius: 6px; cursor: pointer; margin-top: 10px;">
|
| 724 |
Return to Doctors Page (Local)
|
|
@@ -732,15 +721,15 @@ def create_interface():
|
|
| 732 |
else:
|
| 733 |
if "Cannot connect to Flask app" in result['message']:
|
| 734 |
html_response = f"""
|
| 735 |
-
<div
|
| 736 |
-
<h3 style="color: #
|
| 737 |
-
<p
|
| 738 |
-
<p
|
| 739 |
-
<p
|
| 740 |
<ol>
|
| 741 |
-
<li
|
| 742 |
-
<li
|
| 743 |
-
<li
|
| 744 |
</ol>
|
| 745 |
<div style="margin-top: 15px;">
|
| 746 |
<button onclick="window.open('http://127.0.0.1:600/complete_appointment_manual?appointment_id={appointment_id.strip()}', '_blank')"
|
|
@@ -760,10 +749,10 @@ def create_interface():
|
|
| 760 |
"""
|
| 761 |
else:
|
| 762 |
html_response = f"""
|
| 763 |
-
<div
|
| 764 |
-
<h3 style="color: #
|
| 765 |
-
<p
|
| 766 |
-
<p
|
| 767 |
</div>
|
| 768 |
"""
|
| 769 |
return html_response
|
|
|
|
| 29 |
plot_multimodal_results,
|
| 30 |
plot_report_entities,
|
| 31 |
)
|
| 32 |
+
import logging
|
| 33 |
+
import os
|
| 34 |
+
import sys
|
| 35 |
+
import tempfile
|
| 36 |
+
from pathlib import Path
|
| 37 |
+
import requests
|
| 38 |
+
import gradio as gr
|
| 39 |
+
import matplotlib.pyplot as plt
|
| 40 |
+
from PIL import Image
|
| 41 |
|
| 42 |
# Set up logging
|
| 43 |
logging.basicConfig(
|
|
|
|
| 50 |
# Create temporary directory for sample data if it doesn't exist
|
| 51 |
os.makedirs(os.path.join(parent_dir, "data", "sample"), exist_ok=True)
|
| 52 |
|
|
|
|
| 53 |
# Import configuration for end consultation logic
|
| 54 |
try:
|
| 55 |
from .config import get_flask_urls, get_doctors_page_urls, TIMEOUT_SETTINGS
|
|
|
|
| 161 |
html_result = f"""
|
| 162 |
<div class="medisync-card medisync-card-bg medisync-force-text">
|
| 163 |
<h2 class="medisync-title medisync-blue">
|
| 164 |
+
<b>X-ray Analysis Results</b>
|
|
|
|
| 165 |
</h2>
|
| 166 |
<p><strong>Primary Finding:</strong> {results.get("primary_finding", "Unknown")}</p>
|
| 167 |
<p><strong>Confidence:</strong> {results.get("confidence", 0):.1%}</p>
|
|
|
|
| 210 |
html_result = f"""
|
| 211 |
<div class="medisync-card medisync-card-bg medisync-force-text">
|
| 212 |
<h2 class="medisync-title medisync-green">
|
| 213 |
+
<b>Text Analysis Results</b>
|
|
|
|
| 214 |
</h2>
|
| 215 |
<p><strong>Severity Level:</strong> {results.get("severity", {}).get("level", "Unknown")}</p>
|
| 216 |
<p><strong>Severity Score:</strong> {results.get("severity", {}).get("score", 0)}/4</p>
|
|
|
|
| 279 |
html_result = f"""
|
| 280 |
<div class="medisync-card medisync-card-bg medisync-force-text">
|
| 281 |
<h2 class="medisync-title medisync-purple">
|
| 282 |
+
<b>Multimodal Analysis Results</b>
|
|
|
|
| 283 |
</h2>
|
| 284 |
<h3>Overview</h3>
|
| 285 |
<p><strong>Primary Finding:</strong> {results.get("primary_finding", "Unknown")}</p>
|
|
|
|
| 440 |
margin-bottom: 0.7em;
|
| 441 |
letter-spacing: 1px;
|
| 442 |
text-shadow: 0 2px 8px #00bfae33, 0 1px 0 #fff;
|
| 443 |
+
/* Remove display:flex and gap for simple bold text */
|
|
|
|
|
|
|
| 444 |
}
|
| 445 |
.medisync-blue { color: #00bfae; }
|
| 446 |
.medisync-green { color: #28a745; }
|
|
|
|
| 506 |
html[data-theme="dark"] .medisync-force-text, html[data-theme="dark"] .medisync-force-text * {
|
| 507 |
color: #f8fafc !important;
|
| 508 |
}
|
| 509 |
+
/* End consultation status output: remove color and theme, keep text black and simple */
|
| 510 |
#end_consultation_status, #end_consultation_status * {
|
| 511 |
+
color: #000 !important;
|
| 512 |
background: #fff !important;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 513 |
font-size: 1.12rem !important;
|
| 514 |
font-weight: 600 !important;
|
| 515 |
}
|
|
|
|
|
|
|
|
|
|
| 516 |
/* Style the buttons inside the end consultation status popup */
|
| 517 |
#end_consultation_status button {
|
| 518 |
font-size: 1rem !important;
|
|
|
|
| 532 |
) as interface:
|
| 533 |
gr.Markdown(
|
| 534 |
"""
|
| 535 |
+
<div style="margin-bottom: 0.5em;">
|
| 536 |
+
<span style="font-size: 2.4rem; font-weight: bold; letter-spacing: 1.5px;">
|
| 537 |
+
<b>MediSync</b>
|
|
|
|
|
|
|
| 538 |
</span>
|
|
|
|
| 539 |
</div>
|
| 540 |
+
<div style="font-size: 1.22rem; margin-bottom: 1.2em; font-weight: 600;">
|
| 541 |
+
<span>AI-powered Multi-Modal Medical Analysis System</span>
|
| 542 |
</div>
|
| 543 |
<div style="font-size: 1.09rem; margin-bottom: 1.2em;">
|
| 544 |
+
<span>Seamlessly analyze X-ray images and medical reports for comprehensive healthcare insights.</span>
|
| 545 |
</div>
|
| 546 |
<div style="margin-bottom: 1.2em;">
|
| 547 |
+
<ul style="font-size: 1.04rem;">
|
| 548 |
<li>Upload a chest X-ray image</li>
|
| 549 |
<li>Enter the corresponding medical report text</li>
|
| 550 |
<li>Choose the analysis type: <b>Image</b>, <b>Text</b>, or <b>Multimodal</b></li>
|
|
|
|
| 651 |
"""
|
| 652 |
<div class="medisync-card medisync-card-bg medisync-force-text">
|
| 653 |
<h2 class="medisync-title medisync-blue">
|
| 654 |
+
<b>About MediSync</b>
|
|
|
|
| 655 |
</h2>
|
| 656 |
<p>
|
| 657 |
<b>MediSync</b> is an AI-powered healthcare solution that uses multi-modal analysis to provide comprehensive insights from medical images and reports.
|
|
|
|
| 697 |
)
|
| 698 |
|
| 699 |
def handle_end_consultation(appointment_id):
|
| 700 |
+
# Output status: keep text black, simple, no color or theme
|
| 701 |
if not appointment_id or appointment_id.strip() == "":
|
| 702 |
+
return "<div style='color: #000; background: #fff; padding: 10px; border-radius: 5px;'>Please enter your appointment ID first.</div>"
|
| 703 |
result = complete_appointment(appointment_id.strip())
|
| 704 |
if result["status"] == "success":
|
| 705 |
doctors_urls = get_doctors_page_urls()
|
| 706 |
html_response = f"""
|
| 707 |
+
<div style='color: #000; background: #fff; padding: 15px; border-radius: 5px; margin: 10px 0;'>
|
| 708 |
+
<h3 style="color: #000;">✅ Consultation Completed Successfully!</h3>
|
| 709 |
+
<p>✔️ {result['message']}</p>
|
| 710 |
+
<p>Your appointment has been marked as completed.</p>
|
| 711 |
<button onclick="window.open('{doctors_urls['local']}', '_blank')"
|
| 712 |
style="background-color: #00bfae; color: white; padding: 8px 18px; border: none; border-radius: 6px; cursor: pointer; margin-top: 10px;">
|
| 713 |
Return to Doctors Page (Local)
|
|
|
|
| 721 |
else:
|
| 722 |
if "Cannot connect to Flask app" in result['message']:
|
| 723 |
html_response = f"""
|
| 724 |
+
<div style='color: #000; background: #fff; padding: 15px; border-radius: 5px; margin: 10px 0;'>
|
| 725 |
+
<h3 style="color: #000;">⚠️ Consultation Ready to Complete</h3>
|
| 726 |
+
<p>Your consultation analysis is complete! However, we cannot automatically mark your appointment as completed because the Flask app is not accessible from this environment.</p>
|
| 727 |
+
<p><strong>Appointment ID:</strong> {appointment_id.strip()}</p>
|
| 728 |
+
<p><strong>Next Steps:</strong></p>
|
| 729 |
<ol>
|
| 730 |
+
<li>Copy your appointment ID: <code>{appointment_id.strip()}</code></li>
|
| 731 |
+
<li>Return to your Flask app (doctors page)</li>
|
| 732 |
+
<li>Manually complete the appointment using the appointment ID</li>
|
| 733 |
</ol>
|
| 734 |
<div style="margin-top: 15px;">
|
| 735 |
<button onclick="window.open('http://127.0.0.1:600/complete_appointment_manual?appointment_id={appointment_id.strip()}', '_blank')"
|
|
|
|
| 749 |
"""
|
| 750 |
else:
|
| 751 |
html_response = f"""
|
| 752 |
+
<div style='color: #000; background: #fff; padding: 15px; border-radius: 5px; margin: 10px 0;'>
|
| 753 |
+
<h3 style="color: #000;">❌ Error Completing Consultation</h3>
|
| 754 |
+
<p>{result['message']}</p>
|
| 755 |
+
<p>Please try again or contact support if the problem persists.</p>
|
| 756 |
</div>
|
| 757 |
"""
|
| 758 |
return html_response
|