Spaces:
Sleeping
Sleeping
File size: 2,690 Bytes
2c2fc49 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# utils/report.py
from __future__ import annotations
from typing import Dict, Any, Optional
import base64
from io import BytesIO
from PIL import Image
from utils.analysis import (
compute_differential_percentages,
generate_report_from_ai,
)
# -------------------------------------------------
# OPTIONAL IMAGE ENCODING (for API responses)
# -------------------------------------------------
def pil_to_base64(img: Image.Image, format="PNG") -> str:
"""
Convert a PIL image to Base64 (useful for overlay images in API mode).
"""
buffer = BytesIO()
img.save(buffer, format=format)
return base64.b64encode(buffer.getvalue()).decode()
# -------------------------------------------------
# STRUCTURED API RESPONSE GENERATION
# -------------------------------------------------
def build_api_response(
ai_result: Dict[str, Any],
age_group: str,
gender: Optional[str],
reference_csv: str,
overlay_image: Optional[Image.Image] = None,
) -> Dict[str, Any]:
"""
Build a clean JSON response combining:
- coarse counts (RBC/WBC/Platelets)
- WBC subtype counts
- WBC subtype percentages
- generated plain-text report
- optional overlay image (Base64)
"""
coarse = ai_result.get("coarse_counts", {})
subtypes = ai_result.get("wbc_subtypes", {})
pct = compute_differential_percentages(subtypes)
# Generate full text report (human readable)
text_report = generate_report_from_ai(
ai_result=ai_result,
age_group=age_group,
gender=gender,
csv_path=reference_csv,
)
# Build JSON response
response = {
"patient_id": ai_result.get("patient_id"),
"timestamp": ai_result.get("timestamp"),
"fovs_analyzed": ai_result.get("fovs_analyzed"),
"coarse_counts": coarse,
"wbc_subtypes": subtypes,
"wbc_percentages": pct,
"report_text": text_report,
"calibration": ai_result.get("calibration", {}),
}
# Add overlay image only if provided
if overlay_image is not None:
response["overlay_image"] = pil_to_base64(overlay_image)
return response
# -------------------------------------------------
# SIMPLE TEXT-ONLY REPORT (UI mode)
# -------------------------------------------------
def build_text_report(
ai_result: Dict[str, Any],
age_group: str,
gender: Optional[str],
reference_csv: str,
) -> str:
"""
Helper to get only the text report.
Useful for Gradio or CLI mode.
"""
return generate_report_from_ai(
ai_result=ai_result,
age_group=age_group,
gender=gender,
csv_path=reference_csv,
)
|