No active cardiopulmonary disease identified. The lung fields are clear of consolidation, effusion, or pneumothorax. Cardiac size and mediastinal contours are within normal limits.
Create a radiology report summary I can download
mkdir -p /tmp/workspace/radiology-report && ls /tmp/workspace/
~/radiology-report/generate_report.py
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import mm
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable
)
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_RIGHT, TA_JUSTIFY
from reportlab.platypus import KeepTogether
OUTPUT = "/tmp/workspace/radiology-report/Radiology_Report_Shabbir_SK.pdf"
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
rightMargin=20*mm,
leftMargin=20*mm,
topMargin=18*mm,
bottomMargin=18*mm,
title="Radiology Report - Shabbir SK",
author="MNR Medical College and Hospital",
)
W, H = A4
styles = getSampleStyleSheet()
# ── Custom Styles ────────────────────────────────────────────────────────────
NAVY = colors.HexColor("#1a3a5c")
TEAL = colors.HexColor("#1a7fa8")
LIGHT = colors.HexColor("#eaf4fb")
BORDER = colors.HexColor("#2c6e9e")
GRAY = colors.HexColor("#555555")
LGRAY = colors.HexColor("#f2f6f9")
h1 = ParagraphStyle("h1", parent=styles["Normal"],
fontSize=22, leading=28, textColor=NAVY,
fontName="Helvetica-Bold", spaceAfter=4, alignment=TA_CENTER)
h2 = ParagraphStyle("h2", parent=styles["Normal"],
fontSize=11, leading=14, textColor=colors.white,
fontName="Helvetica-Bold", spaceBefore=0, spaceAfter=0)
h3 = ParagraphStyle("h3", parent=styles["Normal"],
fontSize=10, leading=13, textColor=NAVY,
fontName="Helvetica-Bold", spaceBefore=6, spaceAfter=3)
body = ParagraphStyle("body", parent=styles["Normal"],
fontSize=9.5, leading=14, textColor=GRAY,
fontName="Helvetica", spaceAfter=3)
bullet_style = ParagraphStyle("bullet", parent=body,
leftIndent=12, bulletIndent=0, spaceAfter=2)
label = ParagraphStyle("label", parent=styles["Normal"],
fontSize=9, leading=12, textColor=TEAL,
fontName="Helvetica-Bold")
value = ParagraphStyle("value", parent=styles["Normal"],
fontSize=9.5, leading=12, textColor=GRAY,
fontName="Helvetica")
sub = ParagraphStyle("sub", parent=styles["Normal"],
fontSize=8, leading=10, textColor=colors.HexColor("#888888"),
fontName="Helvetica-Oblique", alignment=TA_CENTER)
normal_gray = ParagraphStyle("ngray", parent=styles["Normal"],
fontSize=8.5, leading=12, textColor=GRAY, fontName="Helvetica")
impression_style = ParagraphStyle("imp", parent=styles["Normal"],
fontSize=10, leading=15, textColor=NAVY,
fontName="Helvetica-Bold", spaceAfter=4)
disclaimer_style = ParagraphStyle("disc", parent=styles["Normal"],
fontSize=7.5, leading=11, textColor=colors.HexColor("#888888"),
fontName="Helvetica-Oblique", alignment=TA_JUSTIFY)
def section_header(title):
"""Returns a dark navy band with white title text."""
data = [[Paragraph(title, h2)]]
t = Table(data, colWidths=[W - 40*mm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), NAVY),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
]))
return t
def finding_row(label_txt, finding_txt, normal=True):
status = "NORMAL" if normal else "ABNORMAL"
badge_color = colors.HexColor("#1a8a1a") if normal else colors.HexColor("#cc2200")
badge_style = ParagraphStyle("badge", parent=styles["Normal"],
fontSize=7.5, leading=10, textColor=colors.white,
fontName="Helvetica-Bold", alignment=TA_CENTER)
data = [[
Paragraph(label_txt, label),
Paragraph(finding_txt, normal_gray),
Paragraph(status, badge_style),
]]
t = Table(data, colWidths=[45*mm, 100*mm, 25*mm])
t.setStyle(TableStyle([
("BACKGROUND", (2,0), (2,0), badge_color),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 6),
("RIGHTPADDING", (0,0), (-1,-1), 6),
("ROWBACKGROUNDS",(0,0),(-1,-1), [colors.white, LGRAY]),
("LINEBELOW", (0,0), (-1,-1), 0.4, colors.HexColor("#d0dde8")),
("ROUNDEDCORNERS",(2,0),(2,0),3),
]))
return t
# ─── Build Story ────────────────────────────────────────────────────────────
story = []
# ── Header block ──────────────────────────────────────────────────────────
header_data = [[
Paragraph("RADIOLOGY REPORT", h1),
]]
header_tbl = Table(header_data, colWidths=[W - 40*mm])
header_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), LIGHT),
("TOPPADDING", (0,0), (-1,-1), 14),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 0),
("RIGHTPADDING", (0,0), (-1,-1), 0),
("BOX", (0,0), (-1,-1), 1.5, BORDER),
]))
story.append(header_tbl)
story.append(Paragraph("MNR Medical College and Hospital, Sangareddy", sub))
story.append(Spacer(1, 6*mm))
# ── Patient Info table ──────────────────────────────────────────────────────
info_data = [
[Paragraph("PATIENT NAME", label), Paragraph("Shabbir SK", value),
Paragraph("STUDY DATE", label), Paragraph("15 July 2026", value)],
[Paragraph("AGE / SEX", label), Paragraph("42 Years / Male", value),
Paragraph("STUDY TIME", label), Paragraph("01:11 PM", value)],
[Paragraph("PATIENT ID", label), Paragraph("202607150697", value),
Paragraph("MODALITY", label), Paragraph("X-Ray (Chest PA)", value)],
[Paragraph("REFERRING DR", label), Paragraph("N/A", value),
Paragraph("REPORT DATE", label), Paragraph("15 July 2026", value)],
]
info_tbl = Table(info_data, colWidths=[32*mm, 58*mm, 32*mm, 48*mm])
info_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), colors.white),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 6),
("RIGHTPADDING", (0,0), (-1,-1), 6),
("BOX", (0,0), (-1,-1), 1.2, BORDER),
("INNERGRID", (0,0), (-1,-1), 0.3, colors.HexColor("#d0dde8")),
("ROWBACKGROUNDS",(0,0), (-1,-1), [colors.white, LGRAY]),
]))
story.append(info_tbl)
story.append(Spacer(1, 5*mm))
# ── Technical Adequacy ──────────────────────────────────────────────────────
story.append(section_header(" TECHNICAL ADEQUACY"))
story.append(Spacer(1, 3*mm))
tech_items = [
("Projection", "Posteroanterior (PA) view"),
("Inspiration", "Suboptimal - slightly reduced lung volumes; may mildly crowd bronchovascular markings and exaggerate cardiac diameter"),
("Rotation", "Mild rotation present - medial clavicular ends not perfectly equidistant from thoracic spinous processes"),
("Exposure", "Slightly underpenetrated in the lower zones, partially obscuring retrocardiac and diaphragmatic detail"),
]
tech_data = [[Paragraph(k, label), Paragraph(v, normal_gray)] for k, v in tech_items]
tech_tbl = Table(tech_data, colWidths=[38*mm, 132*mm])
tech_tbl.setStyle(TableStyle([
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
("ROWBACKGROUNDS",(0,0), (-1,-1), [colors.white, LGRAY]),
("LINEBELOW", (0,0), (-1,-1), 0.3, colors.HexColor("#d0dde8")),
("BOX", (0,0), (-1,-1), 0.8, colors.HexColor("#d0dde8")),
]))
story.append(tech_tbl)
story.append(Spacer(1, 5*mm))
# ── Findings ────────────────────────────────────────────────────────────────
story.append(section_header(" RADIOLOGICAL FINDINGS"))
story.append(Spacer(1, 3*mm))
findings = [
("Lung Fields",
"Both lung fields are clear. No focal consolidation, collapse, nodule, or mass identified. Bronchovascular markings within normal limits.",
True),
("Lung Apices",
"Both apices are clear. No apical scarring, cavitary lesion, Ghon focus, or suspicious opacity.",
True),
("Cardiac Silhouette",
"Cardiothoracic ratio < 50%. No definitive cardiomegaly. Right and left cardiac borders are well-defined.",
True),
("Mediastinum",
"Mediastinum is central and not widened. No superior mediastinal widening or mass.",
True),
("Trachea",
"Midline. Mild rightward positional lean, likely rotational artefact. No narrowing or extrinsic compression.",
True),
("Hila",
"Both hila are normal in size, position, and density. No hilar lymphadenopathy.",
True),
("Diaphragm",
"Both hemidiaphragms are smooth and well-defined. Right appropriately higher than left.",
True),
("Costophrenic Angles",
"Both costophrenic angles are sharp and clear. No pleural effusion.",
True),
("Pleural Spaces",
"No pleural thickening, calcification, or pneumothorax bilaterally.",
True),
("Bony Structures",
"Visible ribs and clavicles intact. No fractures, lytic, or sclerotic lesions. Thoracic spine alignment normal.",
True),
("Soft Tissues",
"Unremarkable. A small horizontal density in the left lower lateral chest wall is noted - likely an external artefact (clip/clothing fastener), not intrathoracic.",
True),
]
for lbl, txt, ok in findings:
story.append(finding_row(lbl, txt, ok))
story.append(Spacer(1, 5*mm))
# ── Impression ───────────────────────────────────────────────────────────────
story.append(section_header(" IMPRESSION"))
story.append(Spacer(1, 4*mm))
imp_data = [[
Paragraph(
"No active cardiopulmonary disease identified. The lung fields are clear of consolidation, "
"effusion, or pneumothorax. Cardiac size and mediastinal contours are within normal limits. "
"No acute bony or pleural abnormality detected.",
ParagraphStyle("imp2", parent=styles["Normal"],
fontSize=10.5, leading=16, textColor=NAVY,
fontName="Helvetica-Bold")
)
]]
imp_tbl = Table(imp_data, colWidths=[W - 40*mm])
imp_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), LIGHT),
("BOX", (0,0), (-1,-1), 2, TEAL),
("TOPPADDING", (0,0), (-1,-1), 10),
("BOTTOMPADDING", (0,0), (-1,-1), 10),
("LEFTPADDING", (0,0), (-1,-1), 12),
("RIGHTPADDING", (0,0), (-1,-1), 12),
]))
story.append(imp_tbl)
story.append(Spacer(1, 6*mm))
# ── Signature block ──────────────────────────────────────────────────────────
sig_data = [[
Paragraph("Reported by:", label),
Paragraph("____________________________", normal_gray),
Paragraph("Date:", label),
Paragraph("15 / 07 / 2026", value),
]]
sig_tbl = Table(sig_data, colWidths=[25*mm, 80*mm, 15*mm, 50*mm])
sig_tbl.setStyle(TableStyle([
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 6),
]))
story.append(sig_tbl)
story.append(Spacer(1, 3*mm))
story.append(HRFlowable(width="100%", thickness=0.5, color=colors.HexColor("#d0dde8")))
story.append(Spacer(1, 3*mm))
# ── Disclaimer ───────────────────────────────────────────────────────────────
story.append(Paragraph(
"DISCLAIMER: This radiological description was generated with AI-assisted analysis and is provided for "
"informational purposes only. It does not constitute a formal medical report and must not be used as a "
"substitute for interpretation by a qualified radiologist. All findings should be correlated with the "
"patient's clinical history and physical examination. A formal report must be issued by a licensed "
"radiologist at MNR Medical College and Hospital, Sangareddy.",
disclaimer_style
))
# ─── Build ──────────────────────────────────────────────────────────────────
doc.build(story)
print(f"PDF saved: {OUTPUT}")
python /tmp/workspace/radiology-report/generate_report.py
Radiology Report Shabbir SK
PDF Document · PDF