Spaces:
Sleeping
Sleeping
Update src/ui_components_original.py
Browse files- src/ui_components_original.py +94 -65
src/ui_components_original.py
CHANGED
|
@@ -1324,11 +1324,15 @@ button.gr-button:hover, button.gr-button-primary:hover {
|
|
| 1324 |
return app
|
| 1325 |
|
| 1326 |
def _format_comprehensive_analysis_results(self, analysis_result, image_path, questionnaire_data):
|
| 1327 |
-
"""Format comprehensive analysis results with enhanced visual presentation
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1328 |
try:
|
| 1329 |
-
visual_analysis = analysis_result.get("visual_analysis", {})
|
| 1330 |
report = analysis_result.get("report", "")
|
| 1331 |
-
|
| 1332 |
# Extract key metrics
|
| 1333 |
wound_type = visual_analysis.get("wound_type", "Unknown")
|
| 1334 |
length_cm = visual_analysis.get("length_cm", 0)
|
|
@@ -1337,14 +1341,45 @@ button.gr-button:hover, button.gr-button-primary:hover {
|
|
| 1337 |
skin_tone_label = visual_analysis.get("skin_tone_label", "Unknown")
|
| 1338 |
ita_deg = visual_analysis.get("ita_degrees")
|
| 1339 |
tissue_type = visual_analysis.get("tissue_type", "Unknown")
|
| 1340 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1341 |
# Generate risk assessment
|
| 1342 |
risk_assessment = self._generate_risk_assessment(questionnaire_data)
|
| 1343 |
risk_level = risk_assessment.get("risk_level", "Unknown")
|
| 1344 |
risk_score = risk_assessment.get("risk_score", 0)
|
| 1345 |
risk_factors = risk_assessment.get("risk_factors", [])
|
| 1346 |
risk_class = risk_level.lower().replace(" ", "_")
|
| 1347 |
-
|
| 1348 |
# Format risk factors
|
| 1349 |
if risk_factors:
|
| 1350 |
risk_factors_html = "<ul style='margin: 10px 0; padding-left: 20px;'>"
|
|
@@ -1353,10 +1388,10 @@ button.gr-button:hover, button.gr-button-primary:hover {
|
|
| 1353 |
risk_factors_html += "</ul>"
|
| 1354 |
else:
|
| 1355 |
risk_factors_html = "<p style='color: #4a5568; font-style: italic;'>No specific risk factors identified.</p>"
|
| 1356 |
-
|
| 1357 |
-
#
|
| 1358 |
image_gallery_html = "<div class='image-gallery'>"
|
| 1359 |
-
|
| 1360 |
# Original image
|
| 1361 |
if image_path and os.path.exists(image_path):
|
| 1362 |
img_b64 = self.image_to_base64(image_path)
|
|
@@ -1368,21 +1403,44 @@ button.gr-button:hover, button.gr-button-primary:hover {
|
|
| 1368 |
<p>Uploaded wound photograph for analysis</p>
|
| 1369 |
</div>
|
| 1370 |
"""
|
| 1371 |
-
|
| 1372 |
# Detection visualization
|
| 1373 |
detection_path = visual_analysis.get("detection_image_path")
|
| 1374 |
if detection_path and os.path.exists(detection_path):
|
| 1375 |
img_b64 = self.image_to_base64(detection_path)
|
| 1376 |
if img_b64:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1377 |
image_gallery_html += f"""
|
| 1378 |
<div class="image-item">
|
| 1379 |
<img src="{img_b64}" alt="Wound Detection">
|
| 1380 |
<h4>🎯 Wound Detection</h4>
|
| 1381 |
-
<p>AI-powered wound boundary detection with confidence: {
|
| 1382 |
</div>
|
| 1383 |
"""
|
| 1384 |
-
|
| 1385 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1386 |
seg_path = visual_analysis.get("segmentation_image_path")
|
| 1387 |
if seg_path and os.path.exists(seg_path):
|
| 1388 |
img_b64 = self.image_to_base64(seg_path)
|
|
@@ -1394,25 +1452,21 @@ button.gr-button:hover, button.gr-button-primary:hover {
|
|
| 1394 |
<p>Precise wound boundary identification and tissue analysis</p>
|
| 1395 |
</div>
|
| 1396 |
"""
|
| 1397 |
-
|
| 1398 |
-
#
|
| 1399 |
-
|
| 1400 |
-
|
| 1401 |
-
img_b64 = self.image_to_base64(annotated_path)
|
| 1402 |
-
if img_b64:
|
| 1403 |
-
image_gallery_html += f"""
|
| 1404 |
-
<div class="image-item">
|
| 1405 |
-
<img src="{img_b64}" alt="Annotated Measurements">
|
| 1406 |
-
<h4>📏 Measurements</h4>
|
| 1407 |
-
<p>Calibrated dimensional analysis with length and width indicators</p>
|
| 1408 |
-
</div>
|
| 1409 |
-
"""
|
| 1410 |
-
|
| 1411 |
image_gallery_html += "</div>"
|
| 1412 |
-
|
| 1413 |
# Convert report markdown to HTML
|
| 1414 |
report_html = self.markdown_to_html(report) if report else ""
|
| 1415 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1416 |
html_output = f"""
|
| 1417 |
<div style="max-width: 1200px; margin: 0 auto; background: white; border-radius: 16px; box-shadow: 0 8px 32px rgba(0,0,0,0.1); overflow: hidden;">
|
| 1418 |
<div style="background: linear-gradient(135deg, #3182ce 0%, #2c5aa0 100%); color: white; padding: 40px; text-align: center;">
|
|
@@ -1422,18 +1476,18 @@ button.gr-button:hover, button.gr-button-primary:hover {
|
|
| 1422 |
<p style="margin: 0; font-size: 16px;"><strong>Patient:</strong> {html.escape(str(questionnaire_data.get('patient_name', 'Unknown')))} | <strong>Analysis Date:</strong> {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
|
| 1423 |
</div>
|
| 1424 |
</div>
|
| 1425 |
-
|
| 1426 |
<div style="padding: 40px;">
|
| 1427 |
<div class="status-success" style="margin-bottom: 30px;">
|
| 1428 |
-
<strong>✅ Analysis Status:</strong>
|
| 1429 |
</div>
|
| 1430 |
-
|
| 1431 |
<!-- Image Gallery Section -->
|
| 1432 |
<div style="margin-bottom: 40px;">
|
| 1433 |
<h2 style="color: #2d3748; font-size: 24px; margin-bottom: 20px; border-bottom: 2px solid #e53e3e; padding-bottom: 10px;">🖼️ Visual Analysis Gallery</h2>
|
| 1434 |
{image_gallery_html}
|
| 1435 |
</div>
|
| 1436 |
-
|
| 1437 |
<!-- Wound Detection & Classification -->
|
| 1438 |
<div style="background: #f8f9fa; padding: 30px; border-radius: 12px; margin-bottom: 30px;">
|
| 1439 |
<h2 style="color: #2d3748; margin-top: 0;">🔍 Wound Detection & Classification</h2>
|
|
@@ -1456,8 +1510,8 @@ button.gr-button:hover, button.gr-button-primary:hover {
|
|
| 1456 |
</div>
|
| 1457 |
</div>
|
| 1458 |
</div>
|
| 1459 |
-
|
| 1460 |
-
<!-- Wound Measurements -->
|
| 1461 |
<div style="background: #e7f5ff; padding: 30px; border-radius: 12px; margin-bottom: 30px;">
|
| 1462 |
<h2 style="color: #2d3748; margin-top: 0;">📏 Wound Measurements</h2>
|
| 1463 |
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 20px; margin: 20px 0;">
|
|
@@ -1475,33 +1529,7 @@ button.gr-button:hover, button.gr-button-primary:hover {
|
|
| 1475 |
</div>
|
| 1476 |
</div>
|
| 1477 |
</div>
|
| 1478 |
-
|
| 1479 |
-
<!-- Risk Assessment -->
|
| 1480 |
-
<div style="background: #fff4e6; padding: 30px; border-radius: 12px; margin-bottom: 30px;">
|
| 1481 |
-
<h2 style="color: #2d3748; margin-top: 0;">⚠️ Risk Assessment</h2>
|
| 1482 |
-
<div style="display: flex; align-items: center; margin: 20px 0; flex-wrap: wrap;">
|
| 1483 |
-
<div style="background: {'#d4edda' if risk_class == 'low' else '#fff3cd' if risk_class == 'moderate' else '#f8d7da'};
|
| 1484 |
-
color: {'#155724' if risk_class == 'low' else '#856404' if risk_class == 'moderate' else '#721c24'};
|
| 1485 |
-
padding: 15px 30px;
|
| 1486 |
-
border-radius: 30px;
|
| 1487 |
-
font-weight: 700;
|
| 1488 |
-
font-size: 20px;
|
| 1489 |
-
text-transform: uppercase;
|
| 1490 |
-
letter-spacing: 1px;
|
| 1491 |
-
margin-right: 20px;
|
| 1492 |
-
margin-bottom: 10px;">
|
| 1493 |
-
{risk_level} RISK
|
| 1494 |
-
</div>
|
| 1495 |
-
<div style="font-size: 18px; color: #2d3748;">
|
| 1496 |
-
<strong>Risk Score:</strong> {risk_score}/10
|
| 1497 |
-
</div>
|
| 1498 |
-
</div>
|
| 1499 |
-
<div style="background: white; padding: 25px; border-radius: 8px; margin: 15px 0; box-shadow: 0 2px 8px rgba(0,0,0,0.05);">
|
| 1500 |
-
<h3 style="margin-top: 0; color: #2d3748;">Identified Risk Factors:</h3>
|
| 1501 |
-
{risk_factors_html}
|
| 1502 |
-
</div>
|
| 1503 |
-
</div>
|
| 1504 |
-
|
| 1505 |
<!-- Patient Information Summary -->
|
| 1506 |
<div style="background: #f0f8f0; padding: 30px; border-radius: 12px; margin-bottom: 30px;">
|
| 1507 |
<h2 style="color: #2d3748; margin-top: 0;">👤 Patient Information Summary</h2>
|
|
@@ -1517,10 +1545,10 @@ button.gr-button:hover, button.gr-button-primary:hover {
|
|
| 1517 |
{f"<div style='margin-top: 10px;'><strong>Current Medications:</strong> {html.escape(str(questionnaire_data.get('medications', 'None listed')))}</div>" if questionnaire_data.get('medications') else ""}
|
| 1518 |
{f"<div style='margin-top: 10px;'><strong>Known Allergies:</strong> {html.escape(str(questionnaire_data.get('allergies', 'None listed')))}</div>" if questionnaire_data.get('allergies') else ""}
|
| 1519 |
</div>
|
| 1520 |
-
|
| 1521 |
<!-- AI Generated Report -->
|
| 1522 |
{f'<div style="background: #f8f9fa; padding: 30px; border-radius: 12px; margin-bottom: 30px;"><h2 style="color: #2d3748; margin-top: 0;">🤖 AI-Generated Clinical Report</h2><div style="background: white; padding: 25px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.05);">{report_html}</div></div>' if report_html else ''}
|
| 1523 |
-
|
| 1524 |
<!-- Important Disclaimers -->
|
| 1525 |
<div style="background: #fff5f5; border: 2px solid #feb2b2; padding: 25px; border-radius: 12px; margin: 30px 0;">
|
| 1526 |
<h3 style="color: #c53030; margin-top: 0;">⚠️ Important Medical Disclaimers</h3>
|
|
@@ -1531,7 +1559,7 @@ button.gr-button:hover, button.gr-button-primary:hover {
|
|
| 1531 |
<li><strong>Risk Assessment Limitations:</strong> Risk factors are based on provided information and may not reflect the complete clinical picture.</li>
|
| 1532 |
</ul>
|
| 1533 |
</div>
|
| 1534 |
-
|
| 1535 |
<!-- Footer -->
|
| 1536 |
<div style="text-align: center; padding: 30px 0; border-top: 2px solid #e2e8f0; margin-top: 30px;">
|
| 1537 |
<p style="color: #6c757d; font-style: italic; font-size: 16px; margin: 0;">
|
|
@@ -1543,11 +1571,12 @@ button.gr-button:hover, button.gr-button-primary:hover {
|
|
| 1543 |
</div>
|
| 1544 |
"""
|
| 1545 |
return html_output
|
| 1546 |
-
|
| 1547 |
except Exception as e:
|
| 1548 |
logging.error(f"Error formatting comprehensive results: {e}")
|
| 1549 |
return f"<div class='status-error'>❌ Error displaying results: {str(e)}</div>"
|
| 1550 |
|
|
|
|
| 1551 |
def _generate_risk_assessment(self, questionnaire_data):
|
| 1552 |
"""Generate risk assessment based on questionnaire data"""
|
| 1553 |
if not questionnaire_data:
|
|
|
|
| 1324 |
return app
|
| 1325 |
|
| 1326 |
def _format_comprehensive_analysis_results(self, analysis_result, image_path, questionnaire_data):
|
| 1327 |
+
"""Format comprehensive analysis results with enhanced visual presentation
|
| 1328 |
+
- Shows 'Manual Segmentation' card if a manual mask/overlay was used
|
| 1329 |
+
- Removes the Measurements card from the Visual Analysis Gallery
|
| 1330 |
+
"""
|
| 1331 |
+
import os
|
| 1332 |
try:
|
| 1333 |
+
visual_analysis = analysis_result.get("visual_analysis", {}) or {}
|
| 1334 |
report = analysis_result.get("report", "")
|
| 1335 |
+
|
| 1336 |
# Extract key metrics
|
| 1337 |
wound_type = visual_analysis.get("wound_type", "Unknown")
|
| 1338 |
length_cm = visual_analysis.get("length_cm", 0)
|
|
|
|
| 1341 |
skin_tone_label = visual_analysis.get("skin_tone_label", "Unknown")
|
| 1342 |
ita_deg = visual_analysis.get("ita_degrees")
|
| 1343 |
tissue_type = visual_analysis.get("tissue_type", "Unknown")
|
| 1344 |
+
|
| 1345 |
+
# Detect if manual mask was used (look across common keys/flags)
|
| 1346 |
+
manual_used = bool(
|
| 1347 |
+
analysis_result.get("manual_mask_used")
|
| 1348 |
+
or visual_analysis.get("manual_mask_used")
|
| 1349 |
+
)
|
| 1350 |
+
|
| 1351 |
+
# Try to discover manual overlay/binary mask paths (handle multiple possible keys)
|
| 1352 |
+
manual_overlay_path = None
|
| 1353 |
+
for k in [
|
| 1354 |
+
"manual_segmentation_image_path",
|
| 1355 |
+
"manual_overlay_path",
|
| 1356 |
+
"manual_segmentation_overlay_path",
|
| 1357 |
+
]:
|
| 1358 |
+
p = visual_analysis.get(k)
|
| 1359 |
+
if p and os.path.exists(p):
|
| 1360 |
+
manual_overlay_path = p
|
| 1361 |
+
manual_used = True
|
| 1362 |
+
break
|
| 1363 |
+
|
| 1364 |
+
manual_binary_path = None
|
| 1365 |
+
for k in [
|
| 1366 |
+
"manual_roi_mask_path",
|
| 1367 |
+
"manual_mask_binary_path",
|
| 1368 |
+
"manual_mask_path",
|
| 1369 |
+
]:
|
| 1370 |
+
p = visual_analysis.get(k)
|
| 1371 |
+
if p and os.path.exists(p):
|
| 1372 |
+
manual_binary_path = p
|
| 1373 |
+
manual_used = True
|
| 1374 |
+
break
|
| 1375 |
+
|
| 1376 |
# Generate risk assessment
|
| 1377 |
risk_assessment = self._generate_risk_assessment(questionnaire_data)
|
| 1378 |
risk_level = risk_assessment.get("risk_level", "Unknown")
|
| 1379 |
risk_score = risk_assessment.get("risk_score", 0)
|
| 1380 |
risk_factors = risk_assessment.get("risk_factors", [])
|
| 1381 |
risk_class = risk_level.lower().replace(" ", "_")
|
| 1382 |
+
|
| 1383 |
# Format risk factors
|
| 1384 |
if risk_factors:
|
| 1385 |
risk_factors_html = "<ul style='margin: 10px 0; padding-left: 20px;'>"
|
|
|
|
| 1388 |
risk_factors_html += "</ul>"
|
| 1389 |
else:
|
| 1390 |
risk_factors_html = "<p style='color: #4a5568; font-style: italic;'>No specific risk factors identified.</p>"
|
| 1391 |
+
|
| 1392 |
+
# ---------------------- Image Gallery ----------------------
|
| 1393 |
image_gallery_html = "<div class='image-gallery'>"
|
| 1394 |
+
|
| 1395 |
# Original image
|
| 1396 |
if image_path and os.path.exists(image_path):
|
| 1397 |
img_b64 = self.image_to_base64(image_path)
|
|
|
|
| 1403 |
<p>Uploaded wound photograph for analysis</p>
|
| 1404 |
</div>
|
| 1405 |
"""
|
| 1406 |
+
|
| 1407 |
# Detection visualization
|
| 1408 |
detection_path = visual_analysis.get("detection_image_path")
|
| 1409 |
if detection_path and os.path.exists(detection_path):
|
| 1410 |
img_b64 = self.image_to_base64(detection_path)
|
| 1411 |
if img_b64:
|
| 1412 |
+
conf = visual_analysis.get('detection_confidence', 0.0)
|
| 1413 |
+
try:
|
| 1414 |
+
conf_str = f"{float(conf):.1%}"
|
| 1415 |
+
except Exception:
|
| 1416 |
+
conf_str = str(conf)
|
| 1417 |
image_gallery_html += f"""
|
| 1418 |
<div class="image-item">
|
| 1419 |
<img src="{img_b64}" alt="Wound Detection">
|
| 1420 |
<h4>🎯 Wound Detection</h4>
|
| 1421 |
+
<p>AI-powered wound boundary detection with confidence: {conf_str}</p>
|
| 1422 |
</div>
|
| 1423 |
"""
|
| 1424 |
+
|
| 1425 |
+
# Show MANUAL segmentation card if available/used
|
| 1426 |
+
if manual_overlay_path or manual_binary_path:
|
| 1427 |
+
if manual_overlay_path and os.path.exists(manual_overlay_path):
|
| 1428 |
+
img_b64 = self.image_to_base64(manual_overlay_path)
|
| 1429 |
+
elif manual_binary_path and os.path.exists(manual_binary_path):
|
| 1430 |
+
img_b64 = self.image_to_base64(manual_binary_path)
|
| 1431 |
+
else:
|
| 1432 |
+
img_b64 = None
|
| 1433 |
+
|
| 1434 |
+
if img_b64:
|
| 1435 |
+
image_gallery_html += f"""
|
| 1436 |
+
<div class="image-item">
|
| 1437 |
+
<img src="{img_b64}" alt="Manual Segmentation">
|
| 1438 |
+
<h4>✏️ Manual Segmentation</h4>
|
| 1439 |
+
<p>Clinician-adjusted wound boundary used for this report</p>
|
| 1440 |
+
</div>
|
| 1441 |
+
"""
|
| 1442 |
+
|
| 1443 |
+
# Automatic segmentation (still show if present)
|
| 1444 |
seg_path = visual_analysis.get("segmentation_image_path")
|
| 1445 |
if seg_path and os.path.exists(seg_path):
|
| 1446 |
img_b64 = self.image_to_base64(seg_path)
|
|
|
|
| 1452 |
<p>Precise wound boundary identification and tissue analysis</p>
|
| 1453 |
</div>
|
| 1454 |
"""
|
| 1455 |
+
|
| 1456 |
+
# NOTE: Measurements card intentionally REMOVED from gallery as requested
|
| 1457 |
+
# (Do NOT add segmentation_annotated_path card)
|
| 1458 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1459 |
image_gallery_html += "</div>"
|
| 1460 |
+
|
| 1461 |
# Convert report markdown to HTML
|
| 1462 |
report_html = self.markdown_to_html(report) if report else ""
|
| 1463 |
+
|
| 1464 |
+
status_line = (
|
| 1465 |
+
"Analysis completed successfully with <strong>manual</strong> segmentation"
|
| 1466 |
+
if manual_used else
|
| 1467 |
+
"Analysis completed successfully with comprehensive wound assessment"
|
| 1468 |
+
)
|
| 1469 |
+
|
| 1470 |
html_output = f"""
|
| 1471 |
<div style="max-width: 1200px; margin: 0 auto; background: white; border-radius: 16px; box-shadow: 0 8px 32px rgba(0,0,0,0.1); overflow: hidden;">
|
| 1472 |
<div style="background: linear-gradient(135deg, #3182ce 0%, #2c5aa0 100%); color: white; padding: 40px; text-align: center;">
|
|
|
|
| 1476 |
<p style="margin: 0; font-size: 16px;"><strong>Patient:</strong> {html.escape(str(questionnaire_data.get('patient_name', 'Unknown')))} | <strong>Analysis Date:</strong> {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
|
| 1477 |
</div>
|
| 1478 |
</div>
|
| 1479 |
+
|
| 1480 |
<div style="padding: 40px;">
|
| 1481 |
<div class="status-success" style="margin-bottom: 30px;">
|
| 1482 |
+
<strong>✅ Analysis Status:</strong> {status_line}
|
| 1483 |
</div>
|
| 1484 |
+
|
| 1485 |
<!-- Image Gallery Section -->
|
| 1486 |
<div style="margin-bottom: 40px;">
|
| 1487 |
<h2 style="color: #2d3748; font-size: 24px; margin-bottom: 20px; border-bottom: 2px solid #e53e3e; padding-bottom: 10px;">🖼️ Visual Analysis Gallery</h2>
|
| 1488 |
{image_gallery_html}
|
| 1489 |
</div>
|
| 1490 |
+
|
| 1491 |
<!-- Wound Detection & Classification -->
|
| 1492 |
<div style="background: #f8f9fa; padding: 30px; border-radius: 12px; margin-bottom: 30px;">
|
| 1493 |
<h2 style="color: #2d3748; margin-top: 0;">🔍 Wound Detection & Classification</h2>
|
|
|
|
| 1510 |
</div>
|
| 1511 |
</div>
|
| 1512 |
</div>
|
| 1513 |
+
|
| 1514 |
+
<!-- Wound Measurements (numeric section remains) -->
|
| 1515 |
<div style="background: #e7f5ff; padding: 30px; border-radius: 12px; margin-bottom: 30px;">
|
| 1516 |
<h2 style="color: #2d3748; margin-top: 0;">📏 Wound Measurements</h2>
|
| 1517 |
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 20px; margin: 20px 0;">
|
|
|
|
| 1529 |
</div>
|
| 1530 |
</div>
|
| 1531 |
</div>
|
| 1532 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1533 |
<!-- Patient Information Summary -->
|
| 1534 |
<div style="background: #f0f8f0; padding: 30px; border-radius: 12px; margin-bottom: 30px;">
|
| 1535 |
<h2 style="color: #2d3748; margin-top: 0;">👤 Patient Information Summary</h2>
|
|
|
|
| 1545 |
{f"<div style='margin-top: 10px;'><strong>Current Medications:</strong> {html.escape(str(questionnaire_data.get('medications', 'None listed')))}</div>" if questionnaire_data.get('medications') else ""}
|
| 1546 |
{f"<div style='margin-top: 10px;'><strong>Known Allergies:</strong> {html.escape(str(questionnaire_data.get('allergies', 'None listed')))}</div>" if questionnaire_data.get('allergies') else ""}
|
| 1547 |
</div>
|
| 1548 |
+
|
| 1549 |
<!-- AI Generated Report -->
|
| 1550 |
{f'<div style="background: #f8f9fa; padding: 30px; border-radius: 12px; margin-bottom: 30px;"><h2 style="color: #2d3748; margin-top: 0;">🤖 AI-Generated Clinical Report</h2><div style="background: white; padding: 25px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.05);">{report_html}</div></div>' if report_html else ''}
|
| 1551 |
+
|
| 1552 |
<!-- Important Disclaimers -->
|
| 1553 |
<div style="background: #fff5f5; border: 2px solid #feb2b2; padding: 25px; border-radius: 12px; margin: 30px 0;">
|
| 1554 |
<h3 style="color: #c53030; margin-top: 0;">⚠️ Important Medical Disclaimers</h3>
|
|
|
|
| 1559 |
<li><strong>Risk Assessment Limitations:</strong> Risk factors are based on provided information and may not reflect the complete clinical picture.</li>
|
| 1560 |
</ul>
|
| 1561 |
</div>
|
| 1562 |
+
|
| 1563 |
<!-- Footer -->
|
| 1564 |
<div style="text-align: center; padding: 30px 0; border-top: 2px solid #e2e8f0; margin-top: 30px;">
|
| 1565 |
<p style="color: #6c757d; font-style: italic; font-size: 16px; margin: 0;">
|
|
|
|
| 1571 |
</div>
|
| 1572 |
"""
|
| 1573 |
return html_output
|
| 1574 |
+
|
| 1575 |
except Exception as e:
|
| 1576 |
logging.error(f"Error formatting comprehensive results: {e}")
|
| 1577 |
return f"<div class='status-error'>❌ Error displaying results: {str(e)}</div>"
|
| 1578 |
|
| 1579 |
+
|
| 1580 |
def _generate_risk_assessment(self, questionnaire_data):
|
| 1581 |
"""Generate risk assessment based on questionnaire data"""
|
| 1582 |
if not questionnaire_data:
|