Cone Beam Tomographic Imaging Anatomy of the Maxillofacial Region Christos Angelopoulos, DDS, MS
Cone Beam Tomographic Imaging Anatomy Maxillofacial Region Angelopoulos book overview
http://drawbridgedds.com/PM_PDF/Cone_Beam_Tomographic_Imagin…
Summarize this article as a study guide PDF I can download
ls -la /home/daytona/workspace/ 2>/dev/null && python3 -c "import reportlab; print('reportlab ok')" && python3 -c "from reportlab.platypus import SimpleDocTemplate; print('platypus ok')"
mkdir -p /home/daytona/workspace/cbct-study-guide && echo "dir created"
~/cbct-study-guide/generate_pdf.py
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether
)
from reportlab.lib.pagesizes import letter
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import inch
from reportlab.lib import colors
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY
OUTPUT = "/home/daytona/workspace/cbct-study-guide/CBCT_Maxillofacial_Anatomy_Study_Guide.pdf"
# ── Colour palette ──────────────────────────────────────────────────────────
NAVY = colors.HexColor("#1B3A6B")
TEAL = colors.HexColor("#2E7D8C")
LIGHT = colors.HexColor("#E8F4F8")
ACCENT = colors.HexColor("#F0A500")
WHITE = colors.white
DARK = colors.HexColor("#1A1A2E")
GREY = colors.HexColor("#F5F5F5")
MID = colors.HexColor("#DDDDDD")
doc = SimpleDocTemplate(
OUTPUT,
pagesize=letter,
leftMargin=0.75*inch, rightMargin=0.75*inch,
topMargin=0.75*inch, bottomMargin=0.75*inch,
title="CBCT Maxillofacial Anatomy – Study Guide",
author="Christos Angelopoulos, DDS, MS (summarised)"
)
styles = getSampleStyleSheet()
# Custom styles
S = {
"cover_title": ParagraphStyle("cover_title",
fontName="Helvetica-Bold", fontSize=22, textColor=WHITE,
alignment=TA_CENTER, spaceAfter=6, leading=28),
"cover_sub": ParagraphStyle("cover_sub",
fontName="Helvetica", fontSize=13, textColor=colors.HexColor("#D0E8F0"),
alignment=TA_CENTER, spaceAfter=4),
"cover_byline": ParagraphStyle("cover_byline",
fontName="Helvetica-Oblique", fontSize=10, textColor=colors.HexColor("#A0C4D0"),
alignment=TA_CENTER),
"h1": ParagraphStyle("h1",
fontName="Helvetica-Bold", fontSize=14, textColor=WHITE,
backColor=NAVY, borderPad=6, spaceBefore=14, spaceAfter=4,
leftIndent=-6, rightIndent=-6, leading=18),
"h2": ParagraphStyle("h2",
fontName="Helvetica-Bold", fontSize=11, textColor=NAVY,
spaceBefore=10, spaceAfter=3, leading=14),
"h3": ParagraphStyle("h3",
fontName="Helvetica-Bold", fontSize=10, textColor=TEAL,
spaceBefore=6, spaceAfter=2, leading=13),
"body": ParagraphStyle("body",
fontName="Helvetica", fontSize=9.5, textColor=DARK,
leading=14, spaceAfter=4, alignment=TA_JUSTIFY),
"bullet": ParagraphStyle("bullet",
fontName="Helvetica", fontSize=9.5, textColor=DARK,
leading=14, spaceAfter=3, leftIndent=18, bulletIndent=6),
"sub_bullet": ParagraphStyle("sub_bullet",
fontName="Helvetica", fontSize=9, textColor=DARK,
leading=13, spaceAfter=2, leftIndent=32, bulletIndent=20),
"callout": ParagraphStyle("callout",
fontName="Helvetica-Oblique", fontSize=9.5, textColor=NAVY,
backColor=LIGHT, borderPad=8, leading=14, spaceAfter=6,
leftIndent=12, rightIndent=12),
"key_term": ParagraphStyle("key_term",
fontName="Helvetica-Bold", fontSize=9.5, textColor=NAVY, leading=14),
"table_hdr": ParagraphStyle("table_hdr",
fontName="Helvetica-Bold", fontSize=9, textColor=WHITE,
alignment=TA_CENTER, leading=12),
"table_cell": ParagraphStyle("table_cell",
fontName="Helvetica", fontSize=9, textColor=DARK, leading=12),
"footer": ParagraphStyle("footer",
fontName="Helvetica-Oblique", fontSize=8, textColor=colors.grey,
alignment=TA_CENTER),
"qa_q": ParagraphStyle("qa_q",
fontName="Helvetica-Bold", fontSize=9.5, textColor=NAVY,
leading=13, spaceAfter=2),
"qa_a": ParagraphStyle("qa_a",
fontName="Helvetica", fontSize=9.5, textColor=DARK,
leading=13, spaceAfter=6, leftIndent=14),
}
def H1(text):
return Paragraph(f" {text}", S["h1"])
def H2(text):
return Paragraph(text, S["h2"])
def H3(text):
return Paragraph(text, S["h3"])
def P(text):
return Paragraph(text, S["body"])
def B(text, level=1):
style = S["bullet"] if level == 1 else S["sub_bullet"]
marker = "•" if level == 1 else "◦"
return Paragraph(f"{marker} {text}", style)
def Callout(text):
return Paragraph(f"💡 {text}", S["callout"])
def SP(n=6):
return Spacer(1, n)
def HR():
return HRFlowable(width="100%", thickness=1, color=MID, spaceAfter=4, spaceBefore=4)
story = []
# ════════════════════════════════════════════════════════════════════════════
# COVER BANNER (table used as coloured box)
# ════════════════════════════════════════════════════════════════════════════
cover_content = [
[Paragraph("<br/><br/>", S["cover_title"])],
[Paragraph("CBCT IMAGING", S["cover_title"])],
[Paragraph("Anatomy of the Maxillofacial Region", S["cover_sub"])],
[Paragraph("Study Guide", S["cover_sub"])],
[Paragraph("<br/>", S["cover_sub"])],
[Paragraph("Based on: Angelopoulos C. Cone Beam Tomographic Imaging Anatomy of the Maxillofacial Region.", S["cover_byline"])],
[Paragraph("Dental Clinics of North America 2008;52(4):731–752", S["cover_byline"])],
[Paragraph("<br/>", S["cover_byline"])],
]
cover_table = Table(cover_content, colWidths=[7*inch])
cover_table.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), NAVY),
("ROWPADDING", (0,0), (-1,-1), 4),
("BOX", (0,0), (-1,-1), 2, ACCENT),
("ALIGN", (0,0), (-1,-1), "CENTER"),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
]))
story.append(cover_table)
story.append(SP(20))
# ════════════════════════════════════════════════════════════════════════════
# SECTION 1 — OVERVIEW & KEY CONCEPT
# ════════════════════════════════════════════════════════════════════════════
story.append(H1("1. OVERVIEW & CORE CONCEPT"))
story.append(SP(6))
story.append(P(
"Cone Beam CT (CBCT) acquires a <b>three-dimensional volumetric dataset</b> of the "
"maxillofacial region. Unlike traditional dental radiographs (intraoral, panoramic), CBCT "
"data can be reformatted into <b>any imaging plane</b> — eliminating superimposition and "
"revealing true spatial anatomy."
))
story.append(SP(4))
story.append(Callout(
"The main challenge for dental professionals: unfamiliarity with multiplanar (tomographic) "
"imaging. Traditional projections show 2D shadows; CBCT reveals the true third dimension."
))
story.append(SP(4))
story.append(H2("Multiplanar Reformatting (MPR)"))
story.append(B("Volumetric data is stored and can be re-sliced in <b>any flat or curved plane</b>"))
story.append(B("Eliminates superimposition of neighbouring structures"))
story.append(B("Standard planes: <b>Axial, Coronal, Sagittal</b>"))
story.append(B("Additional: <b>Cross-sectional</b> (perpendicular to the dental arch) and oblique"))
story.append(B("Same structure will appear differently in each plane — familiarity takes practice"))
story.append(SP(6))
# ════════════════════════════════════════════════════════════════════════════
# SECTION 2 — THE THREE IMAGING PLANES
# ════════════════════════════════════════════════════════════════════════════
story.append(H1("2. THE THREE STANDARD IMAGING PLANES"))
story.append(SP(6))
# Plane comparison table
plane_data = [
[Paragraph("Plane", S["table_hdr"]),
Paragraph("Orientation", S["table_hdr"]),
Paragraph("Key Structures Visible", S["table_hdr"])],
[Paragraph("Axial", S["table_cell"]),
Paragraph("Horizontal (top-down)", S["table_cell"]),
Paragraph("Dentition, sinus walls, nasal cavity, zygomatic arches, skull base, cervical vertebrae", S["table_cell"])],
[Paragraph("Coronal", S["table_cell"]),
Paragraph("Frontal (front-to-back)", S["table_cell"]),
Paragraph("Frontal sinuses, orbits, ethmoid air cells, maxillary sinuses, nasal cavity, PPF", S["table_cell"])],
[Paragraph("Sagittal", S["table_cell"]),
Paragraph("Lateral (side-to-side)", S["table_cell"]),
Paragraph("Sphenoid sinus, nasopharynx, cervical vertebrae, sella turcica, palate depth", S["table_cell"])],
[Paragraph("Cross-sectional", S["table_cell"]),
Paragraph("Perpendicular to arch", S["table_cell"]),
Paragraph("Buccal/lingual bone thickness, root position, sinus floor proximity, nerve canal location", S["table_cell"])],
]
plane_tbl = Table(plane_data, colWidths=[1.2*inch, 1.8*inch, 4.0*inch])
plane_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), TEAL),
("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, GREY]),
("BOX", (0,0), (-1,-1), 0.75, MID),
("INNERGRID", (0,0), (-1,-1), 0.5, MID),
("VALIGN", (0,0), (-1,-1), "TOP"),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 6),
]))
story.append(plane_tbl)
story.append(SP(10))
# ════════════════════════════════════════════════════════════════════════════
# SECTION 3 — AXIAL PLANE ANATOMY
# ════════════════════════════════════════════════════════════════════════════
story.append(H1("3. AXIAL PLANE ANATOMY (Level by Level)"))
story.append(SP(6))
story.append(H2("Level 1 — Floor of the Mouth / Mandible"))
story.append(B("Inferior border of the anterior mandible may be visible"))
story.append(B("Mostly soft tissue at this level — minimal diagnostic yield for hard tissue"))
story.append(B("Cervical vertebrae visible toward the inferior end of the imaging volume"))
story.append(B("Neck soft tissues partially included depending on FOV"))
story.append(SP(4))
story.append(H2("Level 2 — Maxillary Sinus & Mandibular Rami"))
story.append(B("Major structures of the <b>maxillary sinus</b>, nasal cavity, and nasopharynx"))
story.append(B("Both sinus compartments visible simultaneously"))
story.append(B("Mandibular rami visible bilaterally"))
story.append(B("Lateral pterygoid muscle may be identified"))
story.append(SP(4))
story.append(H2("Level 3 — Superior Maxillary Sinuses / Skull Base"))
story.append(B("Orbits (O)"))
story.append(B("Frontal sinuses (FS)"))
story.append(B("Oral cavity (OC)"))
story.append(B("Anterior walls of right and left maxillary sinuses"))
story.append(B("Nasolacrimal ducts (marked in green in original atlas)"))
story.append(B("Ethmoid air cells"))
story.append(SP(6))
story.append(Callout(
"Key point: Axial images of the floor of the mouth reveal minimal soft-tissue information. "
"The diagnostic value increases significantly at higher axial levels (sinus and skull base)."
))
story.append(SP(8))
# ════════════════════════════════════════════════════════════════════════════
# SECTION 4 — CORONAL PLANE ANATOMY
# ════════════════════════════════════════════════════════════════════════════
story.append(H1("4. CORONAL PLANE ANATOMY"))
story.append(SP(6))
story.append(P(
"Coronal images are generated perpendicular to the axial plane, slicing front to back. "
"The level of the coronal cut determines which structures are visible."
))
story.append(SP(4))
story.append(H2("At the Premolar Level (Anterior)"))
story.append(B("Frontal sinuses"))
story.append(B("Orbits"))
story.append(B("Anterior aspect of the maxillary sinuses"))
story.append(B("Ethmoid air cells"))
story.append(B("Nasal cavity and nasal septum"))
story.append(B("Maxillary alveolar process and teeth"))
story.append(SP(4))
story.append(H2("At the Molar Level (Mid)"))
story.append(B("Main body of the maxillary sinuses"))
story.append(B("Inferior turbinates / nasal meatus"))
story.append(B("Floor of the orbit"))
story.append(B("Zygomatic process of maxilla"))
story.append(SP(4))
story.append(H2("At the Posterior Level (Sphenoid)"))
story.append(B("Sphenoid sinus"))
story.append(B("Nasopharynx (NP)"))
story.append(B("Foramen ovale bilaterally"))
story.append(B("Pterygoid plates"))
story.append(SP(6))
# ════════════════════════════════════════════════════════════════════════════
# SECTION 5 — PARANASAL SINUSES
# ════════════════════════════════════════════════════════════════════════════
story.append(H1("5. PARANASAL SINUSES"))
story.append(SP(6))
story.append(P(
"The paranasal sinuses are <b>4 pairs of air-filled osseous cavities</b> surrounding the nose "
"and orbits. Healthy sinuses appear <b>dark (black)</b> on CBCT because air attenuates X-rays minimally."
))
story.append(SP(6))
sinus_data = [
[Paragraph("Sinus", S["table_hdr"]),
Paragraph("Bone", S["table_hdr"]),
Paragraph("Shape / Notes", S["table_hdr"]),
Paragraph("Clinical Relevance", S["table_hdr"])],
[Paragraph("Maxillary", S["table_cell"]),
Paragraph("Maxillary bone", S["table_cell"]),
Paragraph("Pyramidal; largest sinus", S["table_cell"]),
Paragraph("Most commonly affected by sinusitis; sinus lift planning", S["table_cell"])],
[Paragraph("Ethmoid", S["table_cell"]),
Paragraph("Ethmoid bone", S["table_cell"]),
Paragraph("Multiple small air cells", S["table_cell"]),
Paragraph("Infection spreads easily; visible in coronal plane", S["table_cell"])],
[Paragraph("Frontal", S["table_cell"]),
Paragraph("Frontal bone", S["table_cell"]),
Paragraph("Highly variable size", S["table_cell"]),
Paragraph("Visible at superior axial/coronal levels", S["table_cell"])],
[Paragraph("Sphenoid", S["table_cell"]),
Paragraph("Sphenoid bone", S["table_cell"]),
Paragraph("Adjacent to sella turcica", S["table_cell"]),
Paragraph("Important landmark for skull base assessment", S["table_cell"])],
]
sinus_tbl = Table(sinus_data, colWidths=[1.1*inch, 1.3*inch, 1.8*inch, 2.8*inch])
sinus_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), TEAL),
("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, GREY]),
("BOX", (0,0), (-1,-1), 0.75, MID),
("INNERGRID", (0,0), (-1,-1), 0.5, MID),
("VALIGN", (0,0), (-1,-1), "TOP"),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 6),
]))
story.append(sinus_tbl)
story.append(SP(10))
# ════════════════════════════════════════════════════════════════════════════
# SECTION 6 — PTERYGOPALATINE FOSSA
# ════════════════════════════════════════════════════════════════════════════
story.append(H1("6. PTERYGOPALATINE FOSSA (PPF)"))
story.append(SP(6))
story.append(Callout(
"The PPF is one of the most clinically important anatomic crossroads in the skull base. "
"A thorough understanding is essential for interpreting CBCT of the posterior maxilla."
))
story.append(SP(6))
story.append(H2("Location"))
story.append(B("Posterior to the maxillary sinuses, in contact with their posterior walls"))
story.append(B("Located at the skull base between the maxilla, sphenoid bone, and palatine bone"))
story.append(SP(4))
story.append(H2("Two Major Osseous Channels"))
ppf_data = [
[Paragraph("Channel", S["table_hdr"]),
Paragraph("Also Called", S["table_hdr"]),
Paragraph("Contents", S["table_hdr"])],
[Paragraph("Vidian canal", S["table_cell"]),
Paragraph("Pterygoid canal", S["table_cell"]),
Paragraph("Fibers of the petrosal nerves (parasympathetic + sympathetic to pterygopalatine ganglion)", S["table_cell"])],
[Paragraph("Foramen rotundum", S["table_cell"]),
Paragraph("—", S["table_cell"]),
Paragraph("Maxillary nerve (V2, second division of trigeminal nerve)", S["table_cell"])],
]
ppf_tbl = Table(ppf_data, colWidths=[1.5*inch, 1.5*inch, 4.0*inch])
ppf_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), NAVY),
("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, GREY]),
("BOX", (0,0), (-1,-1), 0.75, MID),
("INNERGRID", (0,0), (-1,-1), 0.5, MID),
("VALIGN", (0,0), (-1,-1), "TOP"),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 6),
]))
story.append(ppf_tbl)
story.append(SP(6))
story.append(H2("PPF Communications (Potential Spread of Disease)"))
comm_data = [
[Paragraph("Connected Space", S["table_hdr"]),
Paragraph("Via", S["table_hdr"])],
[Paragraph("Middle cranial fossa", S["table_cell"]),
Paragraph("Foramen rotundum (V2) / Vidian canal", S["table_cell"])],
[Paragraph("Orbit", S["table_cell"]),
Paragraph("Inferior orbital fissure", S["table_cell"])],
[Paragraph("Nasal cavity & paranasal sinuses", S["table_cell"]),
Paragraph("Sphenopalatine foramen", S["table_cell"])],
[Paragraph("Infratemporal fossa", S["table_cell"]),
Paragraph("Pterygomaxillary fissure", S["table_cell"])],
[Paragraph("Oral cavity / nasopharynx", S["table_cell"]),
Paragraph("Greater and lesser palatine canals", S["table_cell"])],
]
comm_tbl = Table(comm_data, colWidths=[3.5*inch, 3.5*inch])
comm_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), TEAL),
("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, GREY]),
("BOX", (0,0), (-1,-1), 0.75, MID),
("INNERGRID", (0,0), (-1,-1), 0.5, MID),
("VALIGN", (0,0), (-1,-1), "TOP"),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 6),
]))
story.append(comm_tbl)
story.append(SP(6))
story.append(Callout(
"Clinical pearl: Inflammation or tumour from the orbit, nasal cavity, sinuses, or oral cavity "
"can all spread to and from the PPF — making it a critical region to evaluate on every CBCT."
))
story.append(SP(8))
# ════════════════════════════════════════════════════════════════════════════
# SECTION 7 — CROSS-SECTIONAL IMAGING OF DENTAL STRUCTURES
# ════════════════════════════════════════════════════════════════════════════
story.append(H1("7. CROSS-SECTIONAL IMAGING OF DENTAL STRUCTURES"))
story.append(SP(6))
story.append(P(
"Cross-sectional images are generated <b>perpendicular to the dental arch</b> — this is the view "
"most unique to CBCT and the least familiar to traditional dentists."
))
story.append(SP(4))
story.append(B("Clearly distinguishes <b>buccal</b> from <b>palatal/lingual</b> sides"))
story.append(B("Reveals bone thickness labially and lingually"))
story.append(B("Shows proximity of roots to the <b>maxillary sinus floor</b>"))
story.append(B("Locates the <b>inferior alveolar nerve canal</b> in the mandible"))
story.append(B("Identifies fenestrations, dehiscences, and root dilacerations"))
story.append(B("Essential for <b>implant site assessment</b> — available bone height and width"))
story.append(SP(6))
story.append(Callout(
"CBCT cross-sections allow dentists to see structures from a direction never possible with "
"conventional radiography — the third dimension (bucco-lingual). This is irreplaceable for "
"implant planning, impacted tooth assessment, and endodontic evaluation."
))
story.append(SP(8))
# ════════════════════════════════════════════════════════════════════════════
# SECTION 8 — INCIDENTAL FINDINGS
# ════════════════════════════════════════════════════════════════════════════
story.append(H1("8. INCIDENTAL FINDINGS IN CBCT"))
story.append(SP(6))
story.append(P(
"Because CBCT captures a volume that extends beyond the teeth and jaws, <b>non-dental "
"incidental findings are common</b> and must be systematically evaluated."
))
story.append(SP(4))
inc_data = [
[Paragraph("Region", S["table_hdr"]),
Paragraph("Common Incidental Findings", S["table_hdr"])],
[Paragraph("Paranasal sinuses", S["table_cell"]),
Paragraph("Mucosal thickening, polyps, retention cysts, air-fluid levels, opacification", S["table_cell"])],
[Paragraph("Nasal cavity", S["table_cell"]),
Paragraph("Deviated septum, conchae bullosa, paradoxical turbinate", S["table_cell"])],
[Paragraph("Cervical spine", S["table_cell"]),
Paragraph("Degenerative changes, osteophytes, fractures (rarely)", S["table_cell"])],
[Paragraph("Soft tissues / vasculature", S["table_cell"]),
Paragraph("Calcified carotid artery atheroma — important stroke risk marker", S["table_cell"])],
[Paragraph("Orbit", S["table_cell"]),
Paragraph("Orbital floor defects, masses (rare)", S["table_cell"])],
[Paragraph("Skull base", S["table_cell"]),
Paragraph("Enlarged foramina (tumour infiltration), asymmetry", S["table_cell"])],
]
inc_tbl = Table(inc_data, colWidths=[1.8*inch, 5.2*inch])
inc_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), TEAL),
("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, GREY]),
("BOX", (0,0), (-1,-1), 0.75, MID),
("INNERGRID", (0,0), (-1,-1), 0.5, MID),
("VALIGN", (0,0), (-1,-1), "TOP"),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 6),
]))
story.append(inc_tbl)
story.append(SP(10))
# ════════════════════════════════════════════════════════════════════════════
# SECTION 9 — KEY TERMS GLOSSARY
# ════════════════════════════════════════════════════════════════════════════
story.append(H1("9. KEY TERMS GLOSSARY"))
story.append(SP(6))
terms = [
("CBCT", "Cone Beam Computed Tomography — 3D volumetric imaging modality used in dentistry."),
("MPR", "Multiplanar Reformatting — software reconstruction of CBCT data into any desired plane."),
("FOV", "Field of View — the volume of tissue captured; can be small (dentoalveolar), medium, or large (craniofacial)."),
("Axial plane", "Horizontal cross-section; divides the body into superior and inferior portions."),
("Coronal plane", "Frontal cross-section; divides the body into anterior and posterior portions."),
("Sagittal plane", "Lateral cross-section; divides the body into right and left portions."),
("Pterygopalatine fossa (PPF)", "Key anatomic crossroad at the skull base behind the maxillary sinus; conduit for nerves and potential disease spread."),
("Vidian canal", "Bony canal within the sphenoid; carries parasympathetic and sympathetic fibres."),
("Foramen rotundum", "Opening in the sphenoid bone transmitting the maxillary nerve (V2)."),
("Sphenopalatine foramen", "Opening between PPF and nasal cavity; transmits nasopalatine nerve and sphenopalatine vessels."),
("Nasolacrimal duct", "Drains tears from the lacrimal sac to the inferior nasal meatus; visible on axial CBCT."),
("Inferior orbital fissure", "Connects the orbit to the PPF and infratemporal fossa."),
("Conchae bullosa", "Pneumatisation (air cell) within the middle turbinate — common nasal variant."),
("Mucosal thickening", "Soft-tissue density lining a sinus wall; may indicate sinusitis or allergy."),
]
for term, definition in terms:
row = Table(
[[Paragraph(term, S["key_term"]),
Paragraph(definition, S["table_cell"])]],
colWidths=[2.0*inch, 5.0*inch]
)
row.setStyle(TableStyle([
("BOX", (0,0), (-1,-1), 0.5, MID),
("LEFTPADDING", (0,0), (-1,-1), 6),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(row)
story.append(SP(2))
story.append(SP(8))
# ════════════════════════════════════════════════════════════════════════════
# SECTION 10 — SELF-TEST Q&A
# ════════════════════════════════════════════════════════════════════════════
story.append(H1("10. SELF-TEST: REVIEW QUESTIONS & ANSWERS"))
story.append(SP(6))
qa = [
("Q1. What is the main challenge dental professionals face when first interpreting CBCT images?",
"Unfamiliarity with multiplanar (tomographic) imaging. Traditional dentists are trained on 2D "
"projections (intraoral, panoramic). CBCT provides sections in axial, coronal, sagittal, and "
"cross-sectional planes — showing anatomy from directions never seen before with conventional radiography."),
("Q2. Why do healthy air sinuses appear dark (black) on CBCT?",
"Air attenuates X-rays minimally, so it registers as a very low density (dark) on the image. "
"Any opacification (grey or white) within a sinus indicates fluid, mucosal thickening, or pathology."),
("Q3. Name the 4 pairs of paranasal sinuses and their associated bones.",
"Maxillary sinuses (maxillary bone), Ethmoid air cells (ethmoid bone), "
"Frontal sinuses (frontal bone), Sphenoid sinuses (sphenoid bone)."),
("Q4. What two major osseous channels open into the pterygopalatine fossa?",
"(1) Vidian canal (pterygoid canal) — carries petrosal nerve fibres. "
"(2) Foramen rotundum — carries the maxillary nerve (V2)."),
("Q5. List 4 spaces the PPF communicates with and the pathway used.",
"(1) Middle cranial fossa via foramen rotundum/Vidian canal. "
"(2) Orbit via inferior orbital fissure. "
"(3) Nasal cavity/sinuses via sphenopalatine foramen. "
"(4) Infratemporal fossa via pterygomaxillary fissure."),
("Q6. What is the unique advantage of cross-sectional CBCT images for dental practice?",
"They are generated perpendicular to the dental arch and reveal the bucco-lingual dimension — "
"showing bone thickness, root position, proximity to the sinus floor and inferior alveolar nerve, "
"and the presence of fenestrations or dehiscences. This information is simply unavailable on "
"conventional 2D dental radiographs."),
("Q7. Name three clinically important incidental findings that may appear in a CBCT scan ordered for dental purposes.",
"Any of: (1) Calcified carotid artery atheroma (stroke risk marker). "
"(2) Paranasal sinus pathology (mucosal thickening, polyps, retention cysts). "
"(3) Cervical spine degenerative changes. "
"(4) Nasal septal deviation or conchae bullosa. "
"(5) Orbital floor defects."),
("Q8. At what axial level are the nasolacrimal ducts visible on CBCT?",
"At the superior third of the maxillary sinuses / anterior skull base level, along with the orbits, "
"frontal sinuses, oral cavity, and anterior maxillary sinus walls."),
]
for q, a in qa:
story.append(Paragraph(q, S["qa_q"]))
story.append(Paragraph(a, S["qa_a"]))
story.append(SP(2))
story.append(SP(8))
# ════════════════════════════════════════════════════════════════════════════
# SECTION 11 — CLINICAL PEARLS SUMMARY
# ════════════════════════════════════════════════════════════════════════════
story.append(H1("11. CLINICAL PEARLS AT A GLANCE"))
story.append(SP(6))
pearls = [
"CBCT provides a 3D dataset — always evaluate <b>all three planes</b> and cross-sections, not just the plane of interest.",
"The same anatomical structure will look <b>different in each plane</b> — learning normal appearances in all planes is essential.",
"Healthy sinus = black (air). Any deviation from this warrants assessment for pathology.",
"The PPF is a critical disease-spread corridor — always check it when evaluating posterior maxillary pathology.",
"Never limit your CBCT reading to the dental region of interest — <b>incidental findings are common and clinically significant</b>.",
"Calcified carotid atheromas visible on CBCT represent a potential <b>stroke risk</b> — must be reported and referred.",
"Cross-sectional images are irreplaceable for implant planning (bone height/width), impacted tooth assessment, and nerve canal localisation.",
"CBCT spatial resolution is superior for cortical bone but inferior to medical CT for soft tissue differentiation.",
"The nasolacrimal duct, foramen rotundum, Vidian canal, and sphenopalatine foramen are all identifiable landmarks on CBCT when you know where to look.",
"A <b>systematic, region-by-region approach</b> to reading every CBCT scan prevents missed findings.",
]
for i, pearl in enumerate(pearls, 1):
p_row = Table(
[[Paragraph(str(i), ParagraphStyle("pnum",
fontName="Helvetica-Bold", fontSize=10, textColor=WHITE,
alignment=TA_CENTER, leading=12)),
Paragraph(pearl, S["body"])]],
colWidths=[0.3*inch, 6.7*inch]
)
p_row.setStyle(TableStyle([
("BACKGROUND", (0,0), (0,-1), ACCENT),
("BACKGROUND", (1,0), (1,-1), WHITE),
("BOX", (0,0), (-1,-1), 0.5, MID),
("LEFTPADDING", (0,0), (-1,-1), 6),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
]))
story.append(p_row)
story.append(SP(3))
story.append(SP(12))
# ════════════════════════════════════════════════════════════════════════════
# FOOTER / CITATION
# ════════════════════════════════════════════════════════════════════════════
story.append(HR())
story.append(Paragraph(
"Source: Angelopoulos C. Cone Beam Tomographic Imaging Anatomy of the Maxillofacial Region. "
"<i>Dent Clin North Am.</i> 2008;52(4):731–752. | "
"Study guide prepared for educational use only.",
S["footer"]
))
# ── Build ────────────────────────────────────────────────────────────────────
doc.build(story)
print(f"PDF written to: {OUTPUT}")
python3 /home/daytona/workspace/cbct-study-guide/generate_pdf.py
ls -lh /home/daytona/workspace/cbct-study-guide/CBCT_Maxillofacial_Anatomy_Study_Guide.pdf
CBCT Maxillofacial Anatomy Study Guide
PDF Document · PDF
Pdf looks good please remove the reference in title and add Dr. Shreya chindak
"cover_byline" in ~/cbct-study-guide
~/cbct-study-guide/generate_pdf.py
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/cbct-study-guide/generate_pdf.py'
python3 /home/daytona/workspace/cbct-study-guide/generate_pdf.py
CBCT Maxillofacial Anatomy Study Guide
PDF Document · PDF
Its perfect please remove the source at the end
"Source:" in ~/cbct-study-guide
~/cbct-study-guide/generate_pdf.py
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/cbct-study-guide/generate_pdf.py'
python3 /home/daytona/workspace/cbct-study-guide/generate_pdf.py
CBCT Maxillofacial Anatomy Study Guide
PDF Document · PDF