11. Radiology Report Drafting

Chapter 11 of 18 · 15 min

Radiology reports document imaging findings in structured formats. Drafting reports from image analysis and dictation saves radiologist time on documentation while ensuring consistent formatting.

The standard report structure includes: clinical indication, technique, findings, and impression. The impression section synthesizes findings into diagnostic conclusions. Reports must be accurate, complete, and clearly communicate actionable findings.

# radiology_report_draft.py
from dataclasses import dataclass
from typing import Optional, List
import json

@dataclass
class RadiologyReport:
    clinical_indication: str
    technique: str
    findings: List[str]
    impression: str

class RadiologyReportDraft:
    """Draft radiology reports from findings data."""
    
    REPORT_TEMPLATE = """Draft a complete radiology report from the provided information.
    Follow standard radiology report format:
    - CLINICAL INDICATION
    - TECHNIQUE
    - FINDINGS
    - IMPRESSION
    
    Use professional radiology terminology.
    The Impression should summarize key findings and provide differential considerations if relevant.
    Flag any critical/urgent findings in the Impression.
    
    Information:
    {information}
    
    Study Type: {study_type}
    
    Format the report with clear section headers."""

    CRITIQUE_PROMPT = """Review this draft radiology report for:
    1. Accuracy of findings interpretation
    2. Completeness (all expected anatomy mentioned)
    3. Appropriate use of clinical terminology
    4. Impression appropriately summarizes findings
    5. Any discrepancies between Findings and Impression
    
    Report to review:
    {report}
    
    Return critique as JSON with issues identified."""

    def __init__(self, ollama_client):
        self.ollama = ollama_client
        
    def draft_from_findings(self, findings: dict, 
                            study_type: str) -> RadiologyReport:
        """Generate report from structured findings data."""
        
        prompt = self.REPORT_TEMPLATE.format(
            information=json.dumps(findings, indent=2),
            study_type=study_type
        )
        
        response = self.ollama.generate(prompt)
        return self._parse_report(response)
    
    def draft_from_dictation(self, dictation: str,
                              study_type: str,
                              prior_reports: Optional[List[str]] = None) -> RadiologyReport:
        """Generate report from voice dictation."""
        
        context = f"Dictation transcript:\n{dictation}"
        if prior_reports:
            context += f"\n\nPrior imaging for comparison:\n" + "\n".join(prior_reports)
        
        prompt = self.REPORT_TEMPLATE.format(
            information=context,
            study_type=study_type
        )
        
        response = self.ollama.generate(prompt)
        return self._parse_report(response)
    
    def draft_comparison(self, current_findings: dict,
                         prior_report: str) -> RadiologyReport:
        """Generate report comparing to prior study."""
        
        prompt = f"""Draft a comparison radiology report.
        
        Current Study Findings:
        {json.dumps(current_findings, indent=2)}
        
        Prior Report for Comparison:
        {prior_report}
        
        Highlight:
        - New findings compared to prior
        - Resolved or improved findings
        - Stable findings
        - Any discrepancies with prior
        
        Follow standard report format."""
        
        response = self.ollama.generate(prompt)
        return self._parse_report(response)
    
    def critique_report(self, report: RadiologyReport) -> dict:
        """Review draft report for quality issues."""
        
        prompt = self.CRITIQUE_PROMPT.format(
            report=self._format_report_text(report)
        )
        
        response = self.ollama.generate(prompt)
        try:
            return json.loads(response)
        except:
            return {"issues": [], "overall_quality": "unknown"}
    
    def _parse_report(self, response: str) -> RadiologyReport:
        """Parse LLM output into RadiologyReport structure."""
        sections = {
            "clinical_indication": "",
            "technique": "",
            "findings": [],
            "impression": ""
        }
        
        current_section = None
        
        for line in response.split("\n"):
            line = line.strip()
            if "CLINICAL INDICATION" in line.upper():
                current_section = "clinical_indication"
                continue
            elif "TECHNIQUE" in line.upper():
                current_section = "technique"
                continue
            elif "FINDINGS" in line.upper():
                current_section = "findings"
                continue
            elif "IMPRESSION" in line.upper():
                current_section = "impression"
                continue
            
            if current_section and line:
                if current_section == "findings":
                    if line.startswith("-") or line.startswith("•"):
                        sections["findings"].append(line.lstrip("-• "))
                    elif not line.startswith("FINDINGS"):
                        sections["findings"].append(line)
                else:
                    sections[current_section] += line + " "
        
        return RadiologyReport(
            clinical_indication=sections["clinical_indication"].strip(),
            technique=sections["technique"].strip(),
            findings=sections["findings"],
            impression=sections["impression"].strip()
        )
    
    def _format_report_text(self, report: RadiologyReport) -> str:
        return f"""CLINICAL INDICATION: {report.clinical_indication}
TECHNIQUE: {report.technique}
FINDINGS: {'; '.join(report.findings)}
IMPRESSION: {report.impression}"""

Radiology reports carry medicolegal weight. Incorrect reports cause patient harm and provider liability. Draft reports require radiologist review and verification before clinical use. The value lies in reducing documentation burden, not in autonomous reporting.

EXERCISE

Take three dictations of varying quality (one clear, one fragmented, one with background noise). Generate reports from each and evaluate format consistency and clinical coherence.