Maxillary and mandibular molars. Give complete description and details. अ, it's for viva and for, अ, university examinations. I need it should be very detailed and should be in a PDF form so that, अ, make bullet points of it and with a neat label diagrams of cusps and ridges and every proper detail.
mkdir -p /tmp/workspace/molar-anatomy && echo "Directory ready"
~/molar-anatomy/build_molar_pdf.py
#!/usr/bin/env python3
"""
Maxillary and Mandibular Molars - Comprehensive Exam PDF
Uses ReportLab for PDF generation with labeled diagrams via matplotlib.
"""
import os
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from matplotlib.patches import FancyArrowPatch
import numpy as np
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import cm, mm
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY
from reportlab.platypus import (SimpleDocTemplate, Paragraph, Spacer, Image,
Table, TableStyle, HRFlowable, PageBreak,
KeepTogether)
from reportlab.platypus.flowables import HRFlowable
from reportlab.pdfbase import pdfmetrics
import io
OUTPUT_DIR = "/tmp/workspace/molar-anatomy"
os.makedirs(OUTPUT_DIR, exist_ok=True)
# ─────────────────────────────────────────────
# COLOUR PALETTE
# ─────────────────────────────────────────────
DARK_BLUE = colors.HexColor("#1a3a5c")
MED_BLUE = colors.HexColor("#2E6DA4")
LIGHT_BLUE = colors.HexColor("#D6E8F7")
ACCENT_GOLD = colors.HexColor("#C9870A")
LIGHT_GOLD = colors.HexColor("#FFF5DC")
WHITE = colors.white
LIGHT_GREY = colors.HexColor("#F4F4F4")
DARK_GREY = colors.HexColor("#333333")
RED = colors.HexColor("#C0392B")
GREEN = colors.HexColor("#1E8449")
# ─────────────────────────────────────────────
# DIAGRAM HELPER: annotate with arrow
# ─────────────────────────────────────────────
def annotate(ax, text, xy, xytext, fontsize=7.5, color='black'):
ax.annotate(text, xy=xy, xytext=xytext,
fontsize=fontsize, color=color, fontweight='bold',
ha='center', va='center',
arrowprops=dict(arrowstyle='->', color='gray', lw=1.0),
bbox=dict(boxstyle='round,pad=0.2', fc='white', ec='gray', lw=0.5, alpha=0.85))
# ─────────────────────────────────────────────
# DIAGRAM 1: Maxillary 1st Molar – Occlusal View
# ─────────────────────────────────────────────
def draw_max_first_molar_occlusal():
fig, ax = plt.subplots(figsize=(6, 6))
ax.set_aspect('equal')
ax.set_xlim(-3.5, 3.5); ax.set_ylim(-3.5, 3.5)
ax.axis('off')
fig.patch.set_facecolor('#FAFAFA')
ax.set_facecolor('#FAFAFA')
# Outer crown outline - rhomboidal shape (wider buccally)
crown = plt.Polygon([
(-1.55, -2.3), # MB-buccal
( 1.85, -2.3), # DB-buccal
( 2.1, -1.0), # DB corner
( 1.8, 2.3), # DL corner
(-1.1, 2.3), # ML corner
(-1.8, 0.8), # ML-lingual
(-1.9, -1.0), # MB-lingual
], closed=True, facecolor='#F0E6D3', edgecolor='#5C3A1E', linewidth=2)
ax.add_patch(crown)
# ── CUSPS (as filled ellipses) ──
# Mesiobuccal cusp (largest)
mb = mpatches.Ellipse((-0.65, -1.5), 1.4, 1.3, facecolor='#D4A86A', edgecolor='#5C3A1E', lw=1.2, zorder=3)
ax.add_patch(mb)
# Distobuccal cusp
db = mpatches.Ellipse((0.95, -1.5), 1.2, 1.2, facecolor='#C4984A', edgecolor='#5C3A1E', lw=1.2, zorder=3)
ax.add_patch(db)
# Mesiolingual cusp (LARGEST – cusp of Carabelli)
ml = mpatches.Ellipse((-0.6, 1.3), 1.3, 1.4, facecolor='#E0B97A', edgecolor='#5C3A1E', lw=1.2, zorder=3)
ax.add_patch(ml)
# Distolingual cusp
dl = mpatches.Ellipse((0.9, 1.1), 1.1, 1.1, facecolor='#C4984A', edgecolor='#5C3A1E', lw=1.2, zorder=3)
ax.add_patch(dl)
# 5th cusp (Cusp of Carabelli) – small, on lingual of ML
cab = mpatches.Ellipse((-0.95, 2.05), 0.55, 0.45, facecolor='#A0785A', edgecolor='#5C3A1E', lw=1.0, zorder=4,
linestyle='dashed')
ax.add_patch(cab)
# ── CENTRAL FOSSA ──
cf = mpatches.Ellipse((0.15, -0.1), 0.6, 0.5, facecolor='#8B5E3C', edgecolor='#5C3A1E', lw=1.0, zorder=4)
ax.add_patch(cf)
# ── OBLIQUE RIDGE (hallmark of max molar) ──
ax.plot([-0.1, 0.55], [-0.05, 0.85], color='#7B3F00', lw=3.5, zorder=5, solid_capstyle='round', label='Oblique ridge')
# transverse ridge-like marks
ax.plot([-0.6, 0.15], [-0.8, -0.1], color='#9B6F40', lw=2, zorder=5, solid_capstyle='round')
ax.plot([0.3, 0.9], [-0.8, -0.1], color='#9B6F40', lw=2, zorder=5, solid_capstyle='round')
# ── FOSSAE ──
# Mesial fossa
mf = mpatches.Ellipse((-0.7, -0.9), 0.45, 0.35, facecolor='#7B5B3A', edgecolor='none', zorder=4, alpha=0.7)
ax.add_patch(mf)
# Distal fossa
df_p = mpatches.Ellipse((0.9, -0.9), 0.4, 0.3, facecolor='#7B5B3A', edgecolor='none', zorder=4, alpha=0.7)
ax.add_patch(df_p)
# ── CONTACT AREAS (dotted lines) ──
ax.plot([-1.55, -1.55], [-2.3, -1.0], color='blue', lw=1.5, ls='--', zorder=2)
ax.plot([1.85, 1.85], [-2.3, -1.0], color='blue', lw=1.5, ls='--', zorder=2)
# ── LABELS ──
annotate(ax, 'Mesiobuccal\nCusp (MB)', (-0.65,-1.5), (-2.6,-2.8), color='#2E6DA4')
annotate(ax, 'Distobuccal\nCusp (DB)', (0.95,-1.5), (2.8,-2.8), color='#2E6DA4')
annotate(ax, 'Mesiolingual\nCusp (ML)\n[Largest]', (-0.6,1.3), (-2.8, 2.8), color='#1E8449')
annotate(ax, 'Distolingual\nCusp (DL)', (0.9,1.1), (2.8, 2.8), color='#1E8449')
annotate(ax, 'Cusp of\nCarabelli\n(5th cusp)', (-0.95,2.05), (-2.5, 3.3), color='#8B0000', fontsize=7)
annotate(ax, 'Central\nFossa', (0.15,-0.1), (1.5, -0.3), color='#5C3A1E')
annotate(ax, 'Oblique\nRidge', (0.25, 0.45), (2.1, 0.45), color='#7B3F00')
annotate(ax, 'Mesial\nFossa', (-0.7,-0.9), (-2.2,-0.3), color='#5C3A1E', fontsize=7)
annotate(ax, 'Distal\nFossa', (0.9,-0.9), (2.2,-0.3), color='#5C3A1E', fontsize=7)
# ── DIRECTION LABELS ──
ax.text(0, -3.2, 'BUCCAL', ha='center', va='center', fontsize=9, fontweight='bold', color='#2E6DA4')
ax.text(0, 3.2, 'LINGUAL', ha='center', va='center', fontsize=9, fontweight='bold', color='#1E8449')
ax.text(-3.2, 0, 'MESIAL', ha='center', va='center', fontsize=9, fontweight='bold', color='gray', rotation=90)
ax.text( 3.2, 0, 'DISTAL', ha='center', va='center', fontsize=9, fontweight='bold', color='gray', rotation=270)
ax.set_title('Fig 1: Maxillary 1st Molar – Occlusal View\n(Rhomboidal outline | Oblique Ridge is hallmark)',
fontsize=10, fontweight='bold', color=DARK_BLUE.hexval() if hasattr(DARK_BLUE,'hexval') else '#1a3a5c', pad=10)
path = os.path.join(OUTPUT_DIR, 'max1_occlusal.png')
fig.savefig(path, dpi=150, bbox_inches='tight', facecolor='#FAFAFA')
plt.close(fig)
return path
# ─────────────────────────────────────────────
# DIAGRAM 2: Maxillary 1st Molar – Buccal View
# ─────────────────────────────────────────────
def draw_max_first_molar_buccal():
fig, ax = plt.subplots(figsize=(5.5, 6))
ax.set_aspect('equal')
ax.set_xlim(-3, 3); ax.set_ylim(-1.5, 6)
ax.axis('off')
fig.patch.set_facecolor('#FAFAFA')
ax.set_facecolor('#FAFAFA')
# Crown outline buccal view
crown = plt.Polygon([
(-1.7, 0), # cervical-mesial
( 1.7, 0), # cervical-distal
( 1.8, 1.2), # distal contact
( 1.6, 4.2), # DB cusp tip
( 0.1, 4.8), # between cusps (buccal groove)
(-1.5, 4.5), # MB cusp tip
(-1.85, 1.3), # mesial contact
], closed=True, facecolor='#F0E6D3', edgecolor='#5C3A1E', linewidth=2)
ax.add_patch(crown)
# Cervical line (CEJ)
ax.plot([-1.7, 1.7], [0, 0], color='red', lw=2, ls='--', zorder=5)
# Root block (3 roots)
# Mesiobuccal root (longest, inclined mesially)
mb_root = plt.Polygon([
(-1.85, 0), (-0.7, 0), (-0.5, -1.1), (-1.5, -1.2)
], closed=True, facecolor='#E8D5B0', edgecolor='#5C3A1E', lw=1.5)
ax.add_patch(mb_root)
# Distobuccal root
db_root = plt.Polygon([
(-0.1, 0), (0.9, 0), (0.8, -0.9), (0.0, -1.0)
], closed=True, facecolor='#E8D5B0', edgecolor='#5C3A1E', lw=1.5)
ax.add_patch(db_root)
# Palatal root (mostly hidden in buccal view but shown as merged)
pal_root = plt.Polygon([
(1.0, 0), (1.7, 0), (1.6, -1.1), (0.9, -1.0)
], closed=True, facecolor='#D4C49A', edgecolor='#5C3A1E', lw=1.5)
ax.add_patch(pal_root)
# Buccal groove
ax.plot([0.1, 0.1], [0.2, 3.8], color='#8B5E3C', lw=1.5, zorder=6)
# Cusp triangles
# MB cusp
ax.plot([-1.5, -0.5], [4.5, 4.5], color='#5C3A1E', lw=1, ls=':')
# DB cusp
ax.plot([0.8, 1.6], [4.5, 4.5], color='#5C3A1E', lw=1, ls=':')
# Labels
annotate(ax, 'MB Cusp\n(taller)', (-1.5, 4.5), (-2.5, 5.3), color='#2E6DA4')
annotate(ax, 'DB Cusp\n(shorter)', (1.6, 4.2), (2.5, 5.1), color='#2E6DA4')
annotate(ax, 'Buccal\nGroove', (0.1, 2.5), (1.8, 2.5), color='#5C3A1E')
annotate(ax, 'CEJ\n(cervical line)', (0, 0), (2.2, 0.6), color='red')
annotate(ax, 'MB Root\n(longest)', (-1.1, -0.8), (-2.3, -1.2), color='#8B4513')
annotate(ax, 'DB Root', ( 0.4, -0.7), ( 2.0, -0.5), color='#8B4513')
annotate(ax, 'Palatal Root\n(largest, longest)', (1.3, -0.7), (2.8, -1.2), color='#8B4513', fontsize=7)
ax.text(0, -1.45, '↑ 3 Roots: MB | DB | Palatal (Lingual)', ha='center', fontsize=8,
color='#8B4513', style='italic')
ax.set_title('Fig 2: Maxillary 1st Molar – Buccal View', fontsize=10, fontweight='bold',
color='#1a3a5c', pad=10)
path = os.path.join(OUTPUT_DIR, 'max1_buccal.png')
fig.savefig(path, dpi=150, bbox_inches='tight', facecolor='#FAFAFA')
plt.close(fig)
return path
# ─────────────────────────────────────────────
# DIAGRAM 3: Mandibular 1st Molar – Occlusal View
# ─────────────────────────────────────────────
def draw_mand_first_molar_occlusal():
fig, ax = plt.subplots(figsize=(6.5, 5.5))
ax.set_aspect('equal')
ax.set_xlim(-4, 4); ax.set_ylim(-3.2, 3.2)
ax.axis('off')
fig.patch.set_facecolor('#FAFAFA')
ax.set_facecolor('#FAFAFA')
# Outer crown outline – pentagonal (5 cusps), wider MD than BL
crown = plt.Polygon([
(-2.2, -1.8), # mesio-buccal
( 2.2, -1.8), # disto-buccal
( 2.4, -0.3), # DB corner
( 2.0, 1.8), # DL corner
(-0.4, 2.2), # ML corner
(-2.2, 0.8), # ML-buccal
], closed=True, facecolor='#F0E6D3', edgecolor='#5C3A1E', linewidth=2)
ax.add_patch(crown)
# ── FIVE CUSPS ──
# Mesiobuccal
mbc = mpatches.Ellipse((-1.2, -1.2), 1.3, 1.0, facecolor='#D4A86A', edgecolor='#5C3A1E', lw=1.2, zorder=3)
ax.add_patch(mbc)
# Distobuccal
dbc = mpatches.Ellipse((1.2, -1.2), 1.15, 1.0, facecolor='#C4984A', edgecolor='#5C3A1E', lw=1.2, zorder=3)
ax.add_patch(dbc)
# Distal (5th cusp)
dc = mpatches.Ellipse((2.05, 0.2), 0.9, 0.85, facecolor='#B8894A', edgecolor='#5C3A1E', lw=1.2, zorder=3)
ax.add_patch(dc)
# Mesiolingual (largest)
mlc = mpatches.Ellipse((-1.1, 1.2), 1.3, 1.1, facecolor='#E0B97A', edgecolor='#5C3A1E', lw=1.2, zorder=3)
ax.add_patch(mlc)
# Distolingual
dlc = mpatches.Ellipse((0.9, 1.2), 1.1, 1.0, facecolor='#C4984A', edgecolor='#5C3A1E', lw=1.2, zorder=3)
ax.add_patch(dlc)
# ── CENTRAL FOSSA ──
cf = mpatches.Ellipse((0.1, 0.0), 0.7, 0.5, facecolor='#8B5E3C', edgecolor='#5C3A1E', lw=1, zorder=4)
ax.add_patch(cf)
# ── FOSSAE ──
mf = mpatches.Ellipse((-1.1, 0.0), 0.5, 0.4, facecolor='#7B5B3A', edgecolor='none', zorder=4, alpha=0.7)
ax.add_patch(mf)
df_p = mpatches.Ellipse((1.2, 0.0), 0.5, 0.4, facecolor='#7B5B3A', edgecolor='none', zorder=4, alpha=0.7)
ax.add_patch(df_p)
# ── GROOVES ──
# Buccal groove (central)
ax.plot([0.0, 0.0], [-1.8, -0.3], color='#8B5E3C', lw=1.5, zorder=6)
# Lingual groove
ax.plot([0.0, 0.0], [0.3, 1.8], color='#8B5E3C', lw=1.5, zorder=6)
# Central groove
ax.plot([-1.5, 1.5], [0.0, 0.0], color='#9B6A35', lw=1.2, zorder=5, ls=':')
# ── LABELS ──
annotate(ax, 'Mesiobuccal\nCusp', (-1.2,-1.2), (-3.0,-2.6), color='#2E6DA4')
annotate(ax, 'Distobuccal\nCusp', ( 1.2,-1.2), ( 3.1,-2.6), color='#2E6DA4')
annotate(ax, 'Distal Cusp\n(5th)', (2.05, 0.2), (3.5, 0.2), color='#C9870A')
annotate(ax, 'Mesiolingual\nCusp\n[Largest]', (-1.1, 1.2), (-3.2, 2.6), color='#1E8449')
annotate(ax, 'Distolingual\nCusp', (0.9, 1.2), (2.8, 2.6), color='#1E8449')
annotate(ax, 'Central\nFossa', (0.1, 0.0), (1.4, -0.7), color='#5C3A1E')
annotate(ax, 'Mesial\nFossa', (-1.1, 0.0), (-2.6, -0.5), color='#5C3A1E', fontsize=7)
annotate(ax, 'Distal\nFossa', ( 1.2, 0.0), ( 2.7, -0.5), color='#5C3A1E', fontsize=7)
annotate(ax, 'Buccal\nGroove', (0.0,-1.1), (1.5,-1.5), color='#8B5E3C', fontsize=7)
annotate(ax, 'Lingual\nGroove', (0.0, 1.0), (1.6, 1.6), color='#8B5E3C', fontsize=7)
# ── DIRECTION LABELS ──
ax.text(0, -3.0, 'BUCCAL', ha='center', fontsize=9, fontweight='bold', color='#2E6DA4')
ax.text(0, 3.0, 'LINGUAL', ha='center', fontsize=9, fontweight='bold', color='#1E8449')
ax.text(-3.7, 0, 'MESIAL', ha='center', fontsize=9, fontweight='bold', color='gray', rotation=90)
ax.text( 3.7, 0, 'DISTAL', ha='center', fontsize=9, fontweight='bold', color='gray', rotation=270)
ax.set_title('Fig 3: Mandibular 1st Molar – Occlusal View\n(5 Cusps | Largest molar in mandible | Pentagonal outline)',
fontsize=10, fontweight='bold', color='#1a3a5c', pad=10)
path = os.path.join(OUTPUT_DIR, 'mand1_occlusal.png')
fig.savefig(path, dpi=150, bbox_inches='tight', facecolor='#FAFAFA')
plt.close(fig)
return path
# ─────────────────────────────────────────────
# DIAGRAM 4: Mandibular 1st Molar – Buccal View
# ─────────────────────────────────────────────
def draw_mand_first_molar_buccal():
fig, ax = plt.subplots(figsize=(5.5, 6))
ax.set_aspect('equal')
ax.set_xlim(-3, 3); ax.set_ylim(-1.5, 6)
ax.axis('off')
fig.patch.set_facecolor('#FAFAFA')
ax.set_facecolor('#FAFAFA')
# Crown – wider mesially, 3 buccal cusps visible
crown = plt.Polygon([
(-2.0, 0),
( 2.0, 0),
( 2.1, 1.5),
( 1.7, 4.0), # DB cusp
( 0.2, 4.5), # buccal groove
(-0.2, 4.5),
(-1.8, 4.3), # MB cusp
(-2.2, 1.5),
], closed=True, facecolor='#F0E6D3', edgecolor='#5C3A1E', linewidth=2)
ax.add_patch(crown)
# Mesial buccal cusp higher
ax.plot([-1.9, -1.0], [4.3, 4.3], color='#5C3A1E', lw=0.8, ls=':')
ax.plot([ 1.0, 1.9], [4.0, 4.0], color='#5C3A1E', lw=0.8, ls=':')
# CEJ
ax.plot([-2.0, 2.0], [0, 0], color='red', lw=2, ls='--')
# Buccal groove line
ax.plot([0, 0], [0.3, 3.5], color='#8B5E3C', lw=1.5)
# 2 Roots – mesial & distal
# Mesial root
mes_root = plt.Polygon([
(-2.0, 0), (-0.3, 0), (0.0, -1.2), (-1.5, -1.3)
], closed=True, facecolor='#E8D5B0', edgecolor='#5C3A1E', lw=1.5)
ax.add_patch(mes_root)
# Distal root (shorter, broader)
dis_root = plt.Polygon([
(0.3, 0), (2.0, 0), (1.8, -1.0), (0.4, -1.0)
], closed=True, facecolor='#D4C49A', edgecolor='#5C3A1E', lw=1.5)
ax.add_patch(dis_root)
# Bifurcation point
bif = mpatches.Circle((0.05, 0), 0.12, facecolor='red', edgecolor='none', zorder=5)
ax.add_patch(bif)
# Labels
annotate(ax, 'MB Cusp\n(taller)', (-1.8, 4.3), (-2.7, 5.3), color='#2E6DA4')
annotate(ax, 'DB Cusp', (1.7, 4.0), (2.5, 5.0), color='#2E6DA4')
annotate(ax, 'Buccal\nGroove', (0, 2.0), (1.6, 2.0), color='#5C3A1E')
annotate(ax, 'CEJ', (0, 0), (-2.0, 0.6), color='red')
annotate(ax, 'Mesial Root\n(longer,\nnow 2 canals)', (-0.8, -0.9), (-2.4, -1.1), color='#8B4513', fontsize=7)
annotate(ax, 'Distal Root\n(shorter,\n1 canal)', (1.1, -0.7), (2.4, -1.1), color='#8B4513', fontsize=7)
annotate(ax, 'Bifurcation', (0.05, 0), (1.4, 0.5), color='red', fontsize=7)
ax.set_title('Fig 4: Mandibular 1st Molar – Buccal View', fontsize=10, fontweight='bold',
color='#1a3a5c', pad=10)
path = os.path.join(OUTPUT_DIR, 'mand1_buccal.png')
fig.savefig(path, dpi=150, bbox_inches='tight', facecolor='#FAFAFA')
plt.close(fig)
return path
# ─────────────────────────────────────────────
# DIAGRAM 5: Cusp Ridges Schematic
# ─────────────────────────────────────────────
def draw_cusp_ridges():
fig, axes = plt.subplots(1, 2, figsize=(11, 5))
fig.patch.set_facecolor('#FAFAFA')
for ax in axes:
ax.set_aspect('equal')
ax.axis('off')
ax.set_facecolor('#FAFAFA')
# ── Left: Single cusp ridge anatomy ──
ax = axes[0]
ax.set_xlim(-3, 3); ax.set_ylim(-1, 5)
# Cusp shape
cusp = plt.Polygon([
(-1.5, 0.5), (0, 4.5), (1.5, 0.5)
], closed=True, facecolor='#D4A86A', edgecolor='#5C3A1E', lw=2)
ax.add_patch(cusp)
ax.plot([0, 0], [0.5, 4.5], color='#5C3A1E', lw=2, zorder=5, ls='--') # cusp axis
# Triangular ridge
ax.annotate('', xy=(0, 0.5), xytext=(0, 4.5),
arrowprops=dict(arrowstyle='<->', color='red', lw=1.5))
ax.text(0.25, 2.5, 'Triangular\nRidge', fontsize=8, color='red', fontweight='bold')
# Mesial slope
ax.text(-1.1, 2.2, 'Mesial\nSlope', fontsize=8, color='#2E6DA4', ha='center', rotation=35)
# Distal slope
ax.text(1.1, 2.2, 'Distal\nSlope', fontsize=8, color='#2E6DA4', ha='center', rotation=-35)
# Cusp tip
ax.plot([0], [4.5], 'r*', markersize=15, zorder=6)
ax.text(0.5, 4.5, 'Cusp Tip', fontsize=8, color='red', fontweight='bold')
# Cusp base
ax.plot([-1.5, 1.5], [0.5, 0.5], color='green', lw=2)
ax.text(0, 0.2, 'Cusp Base', fontsize=8, color='green', ha='center')
ax.set_title('A. Cusp Anatomy\n(single cusp, labial view)', fontsize=9, fontweight='bold', color='#1a3a5c')
# ── Right: Ridge types on molar occlusal ──
ax = axes[1]
ax.set_xlim(-3.5, 3.5); ax.set_ylim(-3.5, 3.5)
# Mini crown
mini_crown = plt.Polygon([
(-1.5, -2.2), (1.8, -2.2), (2.0, -0.8), (1.7, 2.2),
(-1.0, 2.2), (-1.7, 0.7), (-1.8, -0.9)
], closed=True, facecolor='#F0E6D3', edgecolor='#5C3A1E', lw=1.5)
ax.add_patch(mini_crown)
# Oblique ridge (MOST IMPORTANT for max molar)
ax.plot([-0.1, 0.7], [-0.1, 0.9], color='red', lw=4, zorder=6, solid_capstyle='round', label='Oblique ridge')
ax.text(1.4, 0.5, 'Oblique\nRidge\n(Max molar\nhallmark)', fontsize=7.5, color='red', fontweight='bold',
bbox=dict(fc='white', ec='red', lw=0.7, boxstyle='round,pad=0.2'))
# Transverse ridge
ax.plot([-0.8, 0.8], [0.0, 0.0], color='purple', lw=2.5, zorder=6, label='Transverse ridge', ls='--')
ax.text(-2.2, 0.25, 'Transverse\nRidge', fontsize=7.5, color='purple', fontweight='bold',
bbox=dict(fc='white', ec='purple', lw=0.7, boxstyle='round,pad=0.2'))
# Marginal ridges
ax.plot([-1.5, 1.8], [-1.9, -1.9], color='blue', lw=2.5, zorder=6, label='Marginal ridge')
ax.plot([-1.0, 1.7], [ 1.9, 1.9], color='blue', lw=2.5, zorder=6)
ax.text(0, -2.8, 'Mesial Marginal Ridge', fontsize=7.5, color='blue', ha='center',
bbox=dict(fc='white', ec='blue', lw=0.7, boxstyle='round,pad=0.2'))
ax.text(0, 2.8, 'Distal Marginal Ridge', fontsize=7.5, color='blue', ha='center',
bbox=dict(fc='white', ec='blue', lw=0.7, boxstyle='round,pad=0.2'))
ax.set_title('B. Ridge Types on Molar\n(Occlusal view – schematic)', fontsize=9, fontweight='bold', color='#1a3a5c')
fig.suptitle('Fig 5: Cusp & Ridge Anatomy', fontsize=11, fontweight='bold', color='#1a3a5c', y=1.01)
path = os.path.join(OUTPUT_DIR, 'ridges.png')
fig.savefig(path, dpi=150, bbox_inches='tight', facecolor='#FAFAFA')
plt.close(fig)
return path
# ─────────────────────────────────────────────
# DIAGRAM 6: Mandibular 2nd Molar Occlusal
# ─────────────────────────────────────────────
def draw_mand_second_molar_occlusal():
fig, ax = plt.subplots(figsize=(6, 5.5))
ax.set_aspect('equal')
ax.set_xlim(-3.5, 3.5); ax.set_ylim(-3, 3)
ax.axis('off')
fig.patch.set_facecolor('#FAFAFA')
ax.set_facecolor('#FAFAFA')
# Rectangular outline (4 cusps)
crown = plt.Polygon([
(-2.0, -2.0), (2.0, -2.0), (2.2, 2.0), (-2.0, 2.0)
], closed=True, facecolor='#F0E6D3', edgecolor='#5C3A1E', linewidth=2)
ax.add_patch(crown)
# 4 CUSPS
mbc = mpatches.Ellipse((-1.0, -1.2), 1.4, 1.0, facecolor='#D4A86A', edgecolor='#5C3A1E', lw=1.2, zorder=3)
ax.add_patch(mbc)
dbc = mpatches.Ellipse(( 1.0, -1.2), 1.3, 1.0, facecolor='#C4984A', edgecolor='#5C3A1E', lw=1.2, zorder=3)
ax.add_patch(dbc)
mlc = mpatches.Ellipse((-1.0, 1.2), 1.3, 1.0, facecolor='#E0B97A', edgecolor='#5C3A1E', lw=1.2, zorder=3)
ax.add_patch(mlc)
dlc = mpatches.Ellipse(( 1.0, 1.2), 1.2, 1.0, facecolor='#C4984A', edgecolor='#5C3A1E', lw=1.2, zorder=3)
ax.add_patch(dlc)
# Central fossa
cf = mpatches.Ellipse((0, 0), 0.7, 0.6, facecolor='#8B5E3C', edgecolor='#5C3A1E', lw=1, zorder=4)
ax.add_patch(cf)
# + shaped groove pattern
ax.plot([0, 0], [-1.8, 1.8], color='#8B5E3C', lw=1.5, zorder=5)
ax.plot([-2.0, 2.0], [0, 0], color='#8B5E3C', lw=1.5, zorder=5)
# Labels
annotate(ax, 'MB Cusp', (-1.0,-1.2), (-2.8,-2.4), color='#2E6DA4')
annotate(ax, 'DB Cusp', ( 1.0,-1.2), ( 2.8,-2.4), color='#2E6DA4')
annotate(ax, 'ML Cusp\n(largest)', (-1.0, 1.2), (-2.8, 2.4), color='#1E8449')
annotate(ax, 'DL Cusp', ( 1.0, 1.2), ( 2.8, 2.4), color='#1E8449')
annotate(ax, 'Central\nFossa', (0, 0), (1.5, -0.5), color='#5C3A1E')
ax.text(0, -0.45, '+ groove\npattern', fontsize=7, ha='center', color='#8B5E3C', style='italic')
ax.text(0, -2.8, 'BUCCAL', ha='center', fontsize=9, fontweight='bold', color='#2E6DA4')
ax.text(0, 2.8, 'LINGUAL', ha='center', fontsize=9, fontweight='bold', color='#1E8449')
ax.text(-3.3, 0, 'MESIAL', ha='center', fontsize=9, fontweight='bold', color='gray', rotation=90)
ax.text( 3.3, 0, 'DISTAL', ha='center', fontsize=9, fontweight='bold', color='gray', rotation=270)
ax.set_title('Fig 6: Mandibular 2nd Molar – Occlusal View\n(4 cusps | Rectangular outline | + groove pattern)',
fontsize=10, fontweight='bold', color='#1a3a5c', pad=10)
path = os.path.join(OUTPUT_DIR, 'mand2_occlusal.png')
fig.savefig(path, dpi=150, bbox_inches='tight', facecolor='#FAFAFA')
plt.close(fig)
return path
# ─────────────────────────────────────────────
# GENERATE ALL DIAGRAMS
# ─────────────────────────────────────────────
print("Generating diagrams...")
p1 = draw_max_first_molar_occlusal()
p2 = draw_max_first_molar_buccal()
p3 = draw_mand_first_molar_occlusal()
p4 = draw_mand_first_molar_buccal()
p5 = draw_cusp_ridges()
p6 = draw_mand_second_molar_occlusal()
print(f"Diagrams: {p1}, {p2}, {p3}, {p4}, {p5}, {p6}")
# ─────────────────────────────────────────────
# PDF GENERATION
# ─────────────────────────────────────────────
PDF_PATH = os.path.join(OUTPUT_DIR, "Maxillary_Mandibular_Molars_Complete.pdf")
doc = SimpleDocTemplate(PDF_PATH, pagesize=A4,
rightMargin=1.8*cm, leftMargin=1.8*cm,
topMargin=2*cm, bottomMargin=2*cm)
styles = getSampleStyleSheet()
# Custom styles
def S(name, **kwargs):
return ParagraphStyle(name, **kwargs)
title_style = S('MyTitle', fontSize=22, leading=28, textColor=DARK_BLUE,
fontName='Helvetica-Bold', alignment=TA_CENTER, spaceAfter=6)
subtitle_style = S('MySubtitle', fontSize=12, leading=16, textColor=MED_BLUE,
fontName='Helvetica', alignment=TA_CENTER, spaceAfter=4)
h1_style = S('H1', fontSize=15, leading=20, textColor=WHITE, fontName='Helvetica-Bold',
backColor=DARK_BLUE, borderPad=6, spaceAfter=6, spaceBefore=14,
leftIndent=-5, rightIndent=-5)
h2_style = S('H2', fontSize=12, leading=16, textColor=WHITE, fontName='Helvetica-Bold',
backColor=MED_BLUE, borderPad=4, spaceAfter=4, spaceBefore=10)
h3_style = S('H3', fontSize=10.5, leading=14, textColor=DARK_BLUE, fontName='Helvetica-Bold',
borderPad=2, spaceAfter=3, spaceBefore=8)
body_style = S('Body', fontSize=9.5, leading=14, textColor=DARK_GREY, fontName='Helvetica',
spaceAfter=2, leftIndent=0)
bullet_style = S('Bullet', fontSize=9.5, leading=14, textColor=DARK_GREY, fontName='Helvetica',
spaceAfter=2, leftIndent=14, bulletIndent=4)
bullet2_style = S('Bullet2', fontSize=9, leading=13, textColor=DARK_GREY, fontName='Helvetica',
spaceAfter=1, leftIndent=28, bulletIndent=18)
note_style = S('Note', fontSize=9, leading=13, textColor=colors.HexColor('#7B3F00'),
fontName='Helvetica-Oblique', backColor=LIGHT_GOLD,
borderPad=5, spaceAfter=4, spaceBefore=4)
exam_style = S('Exam', fontSize=9, leading=13, textColor=colors.HexColor('#1A5276'),
fontName='Helvetica', backColor=LIGHT_BLUE,
borderPad=5, spaceAfter=4, spaceBefore=4)
caption_style = S('Caption', fontSize=8.5, leading=12, textColor=DARK_GREY,
fontName='Helvetica-Oblique', alignment=TA_CENTER, spaceAfter=6)
def H1(text): return Paragraph(f'<b>{text}</b>', h1_style)
def H2(text): return Paragraph(f'<b>{text}</b>', h2_style)
def H3(text): return Paragraph(f'<b>{text}</b>', h3_style)
def B(text): return Paragraph(f'• {text}', bullet_style)
def B2(text): return Paragraph(f'– {text}', bullet2_style)
def N(text): return Paragraph(f'<b>NOTE:</b> {text}', note_style)
def E(text): return Paragraph(f'<b>EXAM TIP:</b> {text}', exam_style)
def SP(n=4): return Spacer(1, n*mm)
def HR(): return HRFlowable(width='100%', thickness=0.5, color=MED_BLUE, spaceAfter=3, spaceBefore=3)
def Cap(t): return Paragraph(t, caption_style)
def Img(path, w=14*cm):
img = Image(path, width=w, height=w * 0.85)
img.hAlign = 'CENTER'
return img
story = []
# ─── COVER ───
story += [
SP(10),
Paragraph('<b>DENTAL ANATOMY</b>', title_style),
Paragraph('Maxillary & Mandibular Molars', S('cov2', fontSize=18, leading=24,
textColor=ACCENT_GOLD, fontName='Helvetica-Bold', alignment=TA_CENTER, spaceAfter=4)),
SP(2),
HR(),
SP(2),
Paragraph('Complete Reference for Viva & University Examinations', subtitle_style),
SP(2),
Paragraph('Includes: Morphology · Cusps · Ridges · Fossae · Grooves · Roots · Comparisons · Clinical Notes',
S('cov3', fontSize=10, leading=14, textColor=DARK_GREY, fontName='Helvetica',
alignment=TA_CENTER, spaceAfter=4)),
SP(8),
HR(),
PageBreak(),
]
# ─── TABLE OF CONTENTS ───
story += [
H1('TABLE OF CONTENTS'),
SP(2),
]
toc_data = [
['Section', 'Topic', 'Page'],
['1', 'Introduction & Classification', '3'],
['2', 'MAXILLARY MOLARS – Overview', '3'],
['3', 'Maxillary 1st Molar – Detailed Morphology', '4'],
['4', 'Maxillary 2nd Molar', '6'],
['5', 'Maxillary 3rd Molar (Wisdom Tooth)', '7'],
['6', 'MANDIBULAR MOLARS – Overview', '8'],
['7', 'Mandibular 1st Molar – Detailed Morphology', '8'],
['8', 'Mandibular 2nd Molar', '10'],
['9', 'Mandibular 3rd Molar', '11'],
['10', 'Cusp & Ridge Terminology', '12'],
['11', 'Comparison Tables', '13'],
['12', 'Clinical Significance', '14'],
['13', 'High-Yield Viva Q&A', '15'],
]
toc_table = Table(toc_data, colWidths=[1.5*cm, 11*cm, 2*cm])
toc_table.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), DARK_BLUE),
('TEXTCOLOR', (0,0), (-1,0), WHITE),
('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
('FONTSIZE', (0,0), (-1,-1), 9),
('ROWBACKGROUNDS', (0,1), (-1,-1), [WHITE, LIGHT_BLUE]),
('GRID', (0,0), (-1,-1), 0.4, colors.grey),
('ALIGN', (2,0), (2,-1), 'CENTER'),
('TOPPADDING', (0,0), (-1,-1), 4),
('BOTTOMPADDING', (0,0), (-1,-1), 4),
]))
story += [toc_table, PageBreak()]
# ═══════════════════════════════════════════
# SECTION 1 – INTRODUCTION
# ═══════════════════════════════════════════
story += [
H1('SECTION 1: INTRODUCTION & CLASSIFICATION'),
SP(2),
H3('What are Molars?'),
B('Molars are the largest, most posterior teeth in the permanent and primary dentitions.'),
B('Function: Grinding and crushing food (mastication).'),
B('Permanent dentition: 12 molars total – 3 per quadrant × 4 quadrants.'),
B('Primary dentition: 8 molars total – 2 per quadrant × 4 quadrants.'),
SP(2),
H3('Eruption Sequence (Permanent)'),
]
erupt_data = [
['Tooth', 'Eruption Age', 'Root Completion'],
['Maxillary 1st Molar', '6–7 years', '9–10 years'],
['Mandibular 1st Molar', '6–7 years', '9–10 years'],
['Maxillary 2nd Molar', '12–13 years', '14–16 years'],
['Mandibular 2nd Molar', '11–13 years', '14–15 years'],
['Maxillary 3rd Molar', '17–21 years', '18–25 years'],
['Mandibular 3rd Molar', '17–21 years', '18–25 years'],
]
et = Table(erupt_data, colWidths=[6*cm, 5*cm, 5*cm])
et.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), MED_BLUE),
('TEXTCOLOR', (0,0), (-1,0), WHITE),
('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
('FONTSIZE', (0,0), (-1,-1), 9),
('ROWBACKGROUNDS', (0,1), (-1,-1), [WHITE, LIGHT_BLUE]),
('GRID', (0,0), (-1,-1), 0.4, colors.grey),
('ALIGN', (1,0), (2,-1), 'CENTER'),
('TOPPADDING', (0,0), (-1,-1), 3),
('BOTTOMPADDING', (0,0), (-1,-1), 3),
]))
story += [et, SP(2),
E('1st molar erupts at 6 yrs = "6-year molar"; 2nd molar at 12 yrs = "12-year molar".'),
PageBreak()]
# ═══════════════════════════════════════════
# SECTION 2 – MAXILLARY MOLARS OVERVIEW
# ═══════════════════════════════════════════
story += [
H1('SECTION 2: MAXILLARY MOLARS – OVERVIEW'),
SP(2),
B('Located in the upper jaw (maxilla) – posterior to the 2nd premolar.'),
B('Three maxillary molars per side: 1st, 2nd, 3rd (wisdom).'),
B('General features of ALL maxillary molars:'),
B2('Crown outline is rhomboidal (wider buccally).'),
B2('3 roots: mesiobuccal (MB), distobuccal (DB), and palatal (lingual) – the palatal root is the longest and largest.'),
B2('4 cusps normally (ML is largest, MB is second).'),
B2('Oblique ridge: a transverse ridge connecting the ML cusp triangular ridge with the DB cusp triangular ridge – UNIQUE TO MAXILLARY MOLARS.'),
B2('2 buccal cusps (MB > DB) and 2 lingual cusps (ML > DL).'),
SP(2),
N('The OBLIQUE RIDGE is the single most distinguishing feature of maxillary molars and is tested repeatedly in exams.'),
PageBreak(),
]
# ═══════════════════════════════════════════
# SECTION 3 – MAXILLARY 1ST MOLAR (DETAILED)
# ═══════════════════════════════════════════
story += [
H1('SECTION 3: MAXILLARY 1ST MOLAR – DETAILED MORPHOLOGY'),
SP(2),
H2('3A. GENERAL CHARACTERISTICS'),
B('Largest tooth in the maxillary arch.'),
B('5 cusps: MB, DB, ML, DL + Cusp of Carabelli (5th accessory cusp on mesiolingual surface of ML cusp).'),
B('4 roots reported in some studies (when MB root divides).'),
B('Crown outline: Rhomboidal when viewed from occlusal.'),
B('Widest dimension: Mesiodistally > buccolingually.'),
SP(2),
H2('3B. CUSPS (Order of Decreasing Size)'),
]
cusp_data = [
['Cusp', 'Size Rank', 'Location', 'Key Notes'],
['Mesiolingual (ML)', '1st (Largest)', 'Lingual-mesial', 'Has Cusp of Carabelli on its lingual surface'],
['Mesiobuccal (MB)', '2nd', 'Buccal-mesial', 'Tallest buccal cusp; gives buccal width'],
['Distobuccal (DB)', '3rd', 'Buccal-distal', 'Shorter than MB'],
['Distolingual (DL)', '4th', 'Lingual-distal', 'Smallest of 4 main cusps'],
['Cusp of Carabelli', '5th (Accessory)', 'Mesiolingual of ML', 'No functional role; 5th cusp; racial variation'],
]
ct = Table(cusp_data, colWidths=[3.8*cm, 2.5*cm, 3.2*cm, 6*cm])
ct.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), ACCENT_GOLD),
('TEXTCOLOR', (0,0), (-1,0), WHITE),
('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
('FONTSIZE', (0,0), (-1,-1), 8.5),
('ROWBACKGROUNDS', (0,1), (-1,-1), [WHITE, LIGHT_GOLD]),
('GRID', (0,0), (-1,-1), 0.4, colors.grey),
('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
('TOPPADDING', (0,0), (-1,-1), 4),
('BOTTOMPADDING', (0,0), (-1,-1), 4),
('WORDWRAP', (0,0), (-1,-1), True),
]))
story += [ct, SP(2),
E('Cusp size order for Max 1st molar: ML > MB > DB > DL > Carabelli. Remembered as "Man Makes Damn Dirty Canals".'),
SP(2),
H2('3C. RIDGES'),
B('Oblique Ridge: Most important! Runs from ML cusp to DB cusp (crosses the tooth diagonally). UNIQUE TO MAXILLARY MOLARS.'),
B('Triangular Ridges: From cusp tip to centre of fossa – present on all 4 main cusps.'),
B('Marginal Ridges: 2 marginal ridges (mesial and distal) forming proximal walls of the occlusal table.'),
B('Buccal Ridges: On the buccal surface of each buccal cusp.'),
B('Lingual Ridges: On the lingual surface of each lingual cusp.'),
SP(2),
H2('3D. FOSSAE & GROOVES'),
B('Central Fossa: Located centrally on the occlusal surface; deepest pit.'),
B('Mesial Fossa: Small; at the mesial aspect between the marginal ridge and central groove.'),
B('Distal Fossa: Between the oblique ridge and distal marginal ridge.'),
B('Buccal Groove: Separates MB and DB cusps on the buccal surface.'),
B('Central Groove: Runs mesiodistally across the occlusal surface.'),
B('Distal Oblique Groove: Runs distal to the oblique ridge.'),
B('Pits: Central pit (in central fossa), mesial pit, distal pit.'),
SP(2),
H2('3E. ROOTS'),
B('3 roots: Mesiobuccal (MB), Distobuccal (DB), Palatal (Lingual).'),
B('Palatal root: Longest, largest, and most divergent – single canal.'),
B('Mesiobuccal root: Contains 2 canals (MB1 and MB2) in ~60–70% of cases – most important clinically!'),
B('Distobuccal root: Shortest buccal root – 1 canal.'),
B('Trifurcation: Roots divide from a common trunk (furcation area).'),
B('Root trunk: The undivided portion from CEJ to furcation.'),
SP(2),
N('MB2 canal in the Max 1st molar is the most commonly missed canal in endodontics – major exam and clinical point.'),
SP(2),
]
# Occlusal diagram
story += [
Img(p1, w=13*cm),
Cap('Fig 1: Maxillary 1st Molar – Occlusal View showing all 5 cusps, oblique ridge, and fossae'),
SP(2),
Img(p2, w=12*cm),
Cap('Fig 2: Maxillary 1st Molar – Buccal View showing 3 roots and crown contour'),
SP(2),
H2('3F. CROWN SURFACES'),
B('Buccal (vestibular) surface: Trapezoidal; MB cusp taller than DB; buccal groove divides two buccal cusps; cervical ridge present.'),
B('Lingual surface: Rounder; ML cusp bulges prominently; Cusp of Carabelli present mesiolingually.'),
B('Mesial surface: Largest proximal surface; mesial contact area in occlusal third.'),
B('Distal surface: Smaller; distal contact area in middle third.'),
B('Occlusal surface: Rhomboidal; 4 cusps + Carabelli; oblique ridge; central, mesial, distal fossae.'),
SP(2),
H2('3G. DIMENSIONS (Approximate)'),
]
dim_data = [
['Parameter', 'Measurement'],
['Crown height (buccal)', '7–8 mm'],
['Mesiodistal diameter', '10–11 mm'],
['Buccolingual diameter', '11–12 mm'],
['MB root length', '12–13 mm'],
['DB root length', '11–12 mm'],
['Palatal root length', '13–14 mm'],
]
dmt = Table(dim_data, colWidths=[8*cm, 7.5*cm])
dmt.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), MED_BLUE),
('TEXTCOLOR', (0,0), (-1,0), WHITE),
('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
('FONTSIZE', (0,0), (-1,-1), 9),
('ROWBACKGROUNDS', (0,1), (-1,-1), [WHITE, LIGHT_BLUE]),
('GRID', (0,0), (-1,-1), 0.4, colors.grey),
('TOPPADDING', (0,0), (-1,-1), 3),
('BOTTOMPADDING', (0,0), (-1,-1), 3),
]))
story += [dmt, PageBreak()]
# ═══════════════════════════════════════════
# SECTION 4 – MAXILLARY 2ND MOLAR
# ═══════════════════════════════════════════
story += [
H1('SECTION 4: MAXILLARY 2ND MOLAR'),
SP(2),
H2('4A. SIMILARITIES TO 1ST MOLAR'),
B('Same basic cusp arrangement: MB, DB, ML, DL (4 main cusps).'),
B('3 roots: MB, DB, palatal – but roots are closer together (converge more).'),
B('Oblique ridge present (but less prominent than 1st molar).'),
SP(2),
H2('4B. DIFFERENCES FROM 1ST MOLAR'),
B('No Cusp of Carabelli (absent or vestigial in 2nd molar).'),
B('Crown is smaller overall.'),
B('Crown outline: More rhomboidal to heart-shaped.'),
B('ML cusp is still the largest, but DL cusp may be reduced or absent in some variations.'),
B('Roots are less divergent – may be fused in some cases.'),
B('Distal shift of DL cusp – crown tilts distally.'),
B('Erupts at 12–13 years.'),
SP(2),
H2('4C. VARIATIONS IN CUSP NUMBER'),
]
var_data = [
['Type', 'Cusps', 'Frequency'],
['Type 1 (Most common)', '4 cusps (ML, MB, DB, DL)', '~60%'],
['Type 2', '3 cusps (ML reduced DL, fused)', '~30%'],
['Type 3', 'Heart-shaped, 3 cusps', 'Rare'],
]
vt = Table(var_data, colWidths=[5.5*cm, 7*cm, 3*cm])
vt.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), ACCENT_GOLD),
('TEXTCOLOR', (0,0), (-1,0), WHITE),
('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
('FONTSIZE', (0,0), (-1,-1), 9),
('ROWBACKGROUNDS', (0,1), (-1,-1), [WHITE, LIGHT_GOLD]),
('GRID', (0,0), (-1,-1), 0.4, colors.grey),
('TOPPADDING', (0,0), (-1,-1), 3),
('BOTTOMPADDING', (0,0), (-1,-1), 3),
]))
story += [vt, SP(2),
E('Key diff: Max 1st molar has Cusp of Carabelli; Max 2nd does NOT. Max 1st has 5 cusps; Max 2nd has 4.'),
SP(2),
H2('4D. ROOTS'),
B('3 roots – same as 1st molar.'),
B('Roots tend to be shorter and may converge or fuse.'),
B('Palatal root remains the longest.'),
B('MB root less commonly has 2 canals compared to 1st molar.'),
PageBreak(),
]
# ═══════════════════════════════════════════
# SECTION 5 – MAXILLARY 3RD MOLAR
# ═══════════════════════════════════════════
story += [
H1('SECTION 5: MAXILLARY 3RD MOLAR (WISDOM TOOTH)'),
SP(2),
B('Most variable tooth in the entire dentition.'),
B('Erupts: 17–21 years; may remain impacted or absent.'),
B('Smaller than 1st and 2nd molars.'),
B('Number of cusps: Highly variable – may have 3, 4, or even more (or fused cusps creating irregular outline).'),
B('Roots: Often fused (taurodont), short, abnormal in shape and number – 1 to 5 roots described.'),
B('Crown: Heart-shaped or round outline; rudimentary appearance.'),
B('Oblique ridge: May be present but often indistinct.'),
B('No successor – it is the last tooth in the arch.'),
SP(2),
H2('5A. CLINICAL IMPORTANCE OF MAXILLARY 3RD MOLAR'),
B('Most commonly impacted tooth in the maxilla.'),
B('Mesioangular impaction is most common.'),
B('Often removed prophylactically or due to pericoronitis.'),
B('Proximity to maxillary sinus and pterygomaxillary fissure is important surgically.'),
B('Root anatomy is unpredictable – endodontic treatment is challenging.'),
SP(2),
N('3rd molars (wisdom teeth) are NOT included in most morphology examinations as standard teeth – focus on 1st and 2nd molars for viva.'),
PageBreak(),
]
# ═══════════════════════════════════════════
# SECTION 6 – MANDIBULAR MOLARS OVERVIEW
# ═══════════════════════════════════════════
story += [
H1('SECTION 6: MANDIBULAR MOLARS – OVERVIEW'),
SP(2),
B('Located in the lower jaw (mandible) – posterior to the 2nd premolar.'),
B('Three mandibular molars per side.'),
B('General features of ALL mandibular molars:'),
B2('Crown outline: Rectangular (wider MD than BL) to trapezoidal.'),
B2('2 roots: Mesial and Distal (bifurcated). Occasionally 3 roots (Radix entomolaris – extra distal-lingual root, more common in Asian populations).'),
B2('Buccal cusps are taller than lingual cusps (opposite to maxillary molars).'),
B2('No oblique ridge.'),
B2('Mesial root is longer and has 2 canals; Distal root is shorter with 1 (sometimes 2) canal(s).'),
SP(2),
E('Key rule: Mandibular molar = 2 roots (M + D). Maxillary molar = 3 roots (MB + DB + Palatal).'),
PageBreak(),
]
# ═══════════════════════════════════════════
# SECTION 7 – MANDIBULAR 1ST MOLAR (DETAILED)
# ═══════════════════════════════════════════
story += [
H1('SECTION 7: MANDIBULAR 1ST MOLAR – DETAILED MORPHOLOGY'),
SP(2),
H2('7A. GENERAL CHARACTERISTICS'),
B('Largest tooth in the mandibular arch.'),
B('First permanent tooth to erupt in the entire dentition (6 years) – called the "6-year molar".'),
B('5 cusps: MB, DB, distal (DC), ML, DL – the distal cusp is the 5th cusp unique to the mandibular 1st molar.'),
B('Crown outline: Pentagonal when viewed from occlusal.'),
B('Wider mesiodistally than buccolingually.'),
SP(2),
H2('7B. CUSPS (Order of Decreasing Size)'),
]
mand_cusp_data = [
['Cusp', 'Size Rank', 'Location', 'Key Notes'],
['Mesiolingual (ML)', '1st (Largest)', 'Lingual-mesial', 'Largest cusp overall'],
['Mesiobuccal (MB)', '2nd', 'Buccal-mesial', 'Tallest buccal cusp'],
['Distobuccal (DB)', '3rd', 'Buccal-distal', 'Slightly shorter than MB'],
['Distolingual (DL)', '4th', 'Lingual-distal', 'Shorter than ML'],
['Distal (DC)', '5th (Smallest)', 'Distal aspect', 'UNIQUE to mandibular 1st molar; makes crown pentagonal'],
]
mct = Table(mand_cusp_data, colWidths=[3.8*cm, 2.5*cm, 3.2*cm, 6*cm])
mct.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), ACCENT_GOLD),
('TEXTCOLOR', (0,0), (-1,0), WHITE),
('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
('FONTSIZE', (0,0), (-1,-1), 8.5),
('ROWBACKGROUNDS', (0,1), (-1,-1), [WHITE, LIGHT_GOLD]),
('GRID', (0,0), (-1,-1), 0.4, colors.grey),
('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
('TOPPADDING', (0,0), (-1,-1), 4),
('BOTTOMPADDING', (0,0), (-1,-1), 4),
]))
story += [mct, SP(2),
E('Mandibular 1st molar cusp size: ML > MB > DB > DL > Distal. The DISTAL cusp makes it unique (5th cusp).'),
SP(2),
H2('7C. RIDGES'),
B('Triangular Ridges: From each cusp tip to central fossa.'),
B('Marginal Ridges: Mesial and distal marginal ridges bordering the occlusal table.'),
B('Transverse Ridges: Union of MB + ML triangular ridges = transverse ridge (mesialy).'),
B('NO oblique ridge (this is characteristic of maxillary molars only).'),
B('Buccal Ridges: On each buccal cusp.'),
B('Lingual Ridges: On each lingual cusp.'),
SP(2),
H2('7D. FOSSAE & GROOVES'),
B('Central Fossa: Large; located in the centre; deepest.'),
B('Mesial Fossa (Anterior fossa): Triangular; between mesial marginal ridge and MB cusp.'),
B('Distal Fossa (Posterior fossa): Between central fossa and distal cusp.'),
B('Buccal Groove: Between MB and DB cusps – runs onto buccal surface; ends in buccal pit.'),
B('Lingual Groove: Between ML and DL cusps – runs onto lingual surface.'),
B('Distal Buccal Groove: Between DB and Distal cusps.'),
B('Central Groove: Main groove running mesiodistally across the occlusal surface.'),
B('Mesiobuccal Groove: Separates MB and ML cusps buccally.'),
B('Pits: Central pit (central fossa), mesial pit, distal pit, buccal pit (end of buccal groove).'),
SP(2),
H2('7E. ROOTS'),
B('2 roots: Mesial and Distal.'),
B('Mesial root: Longer, broader, flattened MD; contains 2 canals (ML + MB) in ~75–80% of cases.'),
B('Distal root: Shorter, rounder; usually 1 canal (occasionally 2).'),
B('Bifurcation: Roots separate close to CEJ – shallow root trunk.'),
B('Mesial root curves distally at apex.'),
B('Both roots flare buccally and lingually (diverge).'),
B('Radix entomolaris (RE): Extra distal-lingual root – seen in Asian populations (up to 40%); important clinically.'),
SP(2),
]
story += [
Img(p3, w=13*cm),
Cap('Fig 3: Mandibular 1st Molar – Occlusal View showing 5 cusps, pentagonal outline, fossae and grooves'),
SP(2),
Img(p4, w=12*cm),
Cap('Fig 4: Mandibular 1st Molar – Buccal View showing 2 roots and bifurcation'),
SP(2),
H2('7F. CROWN SURFACES'),
B('Buccal surface: Trapezoidal; 3 buccal cusps visible (MB, DB, Distal); buccal groove between MB & DB; buccal groove terminates in buccal pit.'),
B('Lingual surface: Shorter cervicoincisal height; 2 lingual cusps (ML, DL); lingual groove divides them.'),
B('Mesial surface: Wide, broad contact area at junction of occlusal and middle thirds; mesial marginal ridge.'),
B('Distal surface: Smaller than mesial; distal marginal ridge; distal root visible.'),
B('Occlusal surface: Pentagonal; 5 cusps; 3 buccal + 2 lingual; buccal > lingual in height.'),
SP(2),
H2('7G. DIMENSIONS (Approximate)'),
]
dim2_data = [
['Parameter', 'Measurement'],
['Crown height (buccal)', '7–8 mm'],
['Mesiodistal diameter', '11–12 mm'],
['Buccolingual diameter', '10–11 mm'],
['Mesial root length', '13–14 mm'],
['Distal root length', '12–13 mm'],
]
dmt2 = Table(dim2_data, colWidths=[8*cm, 7.5*cm])
dmt2.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), MED_BLUE),
('TEXTCOLOR', (0,0), (-1,0), WHITE),
('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
('FONTSIZE', (0,0), (-1,-1), 9),
('ROWBACKGROUNDS', (0,1), (-1,-1), [WHITE, LIGHT_BLUE]),
('GRID', (0,0), (-1,-1), 0.4, colors.grey),
('TOPPADDING', (0,0), (-1,-1), 3),
('BOTTOMPADDING', (0,0), (-1,-1), 3),
]))
story += [dmt2, PageBreak()]
# ═══════════════════════════════════════════
# SECTION 8 – MANDIBULAR 2ND MOLAR
# ═══════════════════════════════════════════
story += [
H1('SECTION 8: MANDIBULAR 2ND MOLAR'),
SP(2),
H2('8A. GENERAL CHARACTERISTICS'),
B('Slightly smaller than 1st molar.'),
B('4 cusps (NO distal cusp – this is a key difference from 1st molar).'),
B('Crown outline: Rectangular (4-cusped) from occlusal.'),
B('Erupts at 11–13 years.'),
SP(2),
H2('8B. CUSPS'),
B('4 cusps: MB, DB, ML, DL – equal in height, giving flat occlusal table.'),
B('All 4 cusps nearly equal in size (ML slightly larger).'),
B('Buccal cusps taller than lingual cusps.'),
SP(2),
H2('8C. GROOVES & FOSSAE'),
B('+ (plus/cross) shaped groove pattern: Central buccal groove + central lingual groove + central groove = classic cross pattern.'),
B('Central fossa: Well-defined.'),
B('Mesial and distal fossae present.'),
SP(2),
N('The + groove pattern is the hallmark of mandibular 2nd molar. Mandibular 1st molar has a Y-shaped or more complex groove pattern.'),
SP(2),
H2('8D. ROOTS'),
B('2 roots: Mesial and distal (same as 1st molar).'),
B('Roots are closer together and less divergent than 1st molar.'),
B('Roots may be parallel or even fused (taurodont variant).'),
B('Mesial root: Usually 2 canals.'),
B('Distal root: Usually 1 canal.'),
SP(2),
Img(p6, w=13*cm),
Cap('Fig 6: Mandibular 2nd Molar – Occlusal View showing 4 cusps, rectangular outline, and + groove pattern'),
SP(2),
E('Key diff between Mand 1st vs 2nd molar: 1st has 5 cusps (pentagonal); 2nd has 4 cusps (rectangular). 1st has Y/5-groove; 2nd has + groove.'),
PageBreak(),
]
# ═══════════════════════════════════════════
# SECTION 9 – MANDIBULAR 3RD MOLAR
# ═══════════════════════════════════════════
story += [
H1('SECTION 9: MANDIBULAR 3RD MOLAR'),
SP(2),
B('Most frequently impacted tooth in the entire dentition.'),
B('Erupts: 17–21 years.'),
B('Number of cusps: Highly variable (3–5 or more).'),
B('Roots: Variable – usually 2 but may be fused, shorter, abnormally shaped.'),
B('Crown: Usually smaller; may resemble 2nd molar.'),
SP(2),
H2('9A. CLINICAL IMPORTANCE OF MANDIBULAR 3RD MOLAR'),
B('Mesioangular impaction: Most common type (44%).'),
B('Pericoronitis: Infection around the crown of a partially erupted 3rd molar.'),
B('Proximity to inferior alveolar nerve (IAN): Risk of nerve damage during extraction.'),
B('Can cause resorption of 2nd molar root if impacted.'),
B('Follicular cyst (dentigerous cyst) can develop around unerupted 3rd molar crown.'),
SP(2),
N('Types of mandibular 3rd molar impaction: Mesioangular (most common) > Horizontal > Vertical > Distoangular (least common).'),
PageBreak(),
]
# ═══════════════════════════════════════════
# SECTION 10 – CUSP & RIDGE TERMINOLOGY
# ═══════════════════════════════════════════
story += [
H1('SECTION 10: CUSP & RIDGE TERMINOLOGY'),
SP(2),
Img(p5, w=15*cm),
Cap('Fig 5: A. Single cusp anatomy; B. Ridge types on molar occlusal surface'),
SP(2),
H2('10A. TYPES OF RIDGES'),
]
ridge_data = [
['Ridge Type', 'Definition', 'Example'],
['Triangular Ridge', 'Ridge descending from cusp tip to centre of occlusal surface', 'On all cusps of all molars'],
['Transverse Ridge', 'Union of 2 triangular ridges (buccal + lingual cusp) crossing tooth transversely', 'Max & Mand molars'],
['Oblique Ridge', 'Union of ML triangular ridge + DB triangular ridge (runs obliquely)', 'MAXILLARY MOLARS ONLY'],
['Marginal Ridge', 'Elevated ridges of enamel forming mesial & distal borders of occlusal surface', 'All posterior teeth'],
['Cusp Ridge', 'Ridges extending from cusp tip toward mesial or distal margins', 'Buccal, lingual ridges'],
['Cervical Ridge', 'Ridge at the cervical third of buccal surface', 'Max molars, primary molars'],
]
rt = Table(ridge_data, colWidths=[3.5*cm, 7.5*cm, 4.5*cm])
rt.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), DARK_BLUE),
('TEXTCOLOR', (0,0), (-1,0), WHITE),
('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
('FONTSIZE', (0,0), (-1,-1), 8.5),
('ROWBACKGROUNDS', (0,1), (-1,-1), [WHITE, LIGHT_BLUE]),
('GRID', (0,0), (-1,-1), 0.4, colors.grey),
('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
('TOPPADDING', (0,0), (-1,-1), 4),
('BOTTOMPADDING', (0,0), (-1,-1), 4),
('WORDWRAP', (0,0), (-1,-1), True),
]))
story += [rt, SP(2),
H2('10B. TYPES OF FOSSAE'),
B('Central Fossa: Deepest, most central pit – junction of several grooves.'),
B('Mesial Fossa (Anterior): Triangular; at mesial aspect of occlusal table.'),
B('Distal Fossa (Posterior): At distal aspect; smaller.'),
B('Lingual Fossa: On lingual surface of upper anterior teeth (not relevant for molars).'),
SP(2),
H2('10C. TYPES OF PITS'),
B('Central Pit: In the central fossa.'),
B('Mesial Pit: In the mesial fossa.'),
B('Distal Pit: In the distal fossa.'),
B('Buccal Pit: At the end of the buccal groove on the buccal surface.'),
B('Lingual Pit: At the end of the lingual groove.'),
SP(2),
N('Pits are the most common site for caries initiation in molars because they are deep and difficult to clean.'),
PageBreak(),
]
# ═══════════════════════════════════════════
# SECTION 11 – COMPARISON TABLES
# ═══════════════════════════════════════════
story += [
H1('SECTION 11: COMPARISON TABLES'),
SP(2),
H2('11A. Maxillary 1st vs 2nd Molar'),
]
comp1 = [
['Feature', 'Max 1st Molar', 'Max 2nd Molar'],
['No. of cusps', '5 (including Carabelli)', '4 (no Carabelli)'],
['Crown outline', 'Rhomboidal', 'Rhomboidal to heart-shaped'],
['Cusp of Carabelli', 'Present', 'Absent'],
['Oblique ridge', 'Well-defined', 'Present but less prominent'],
['Roots', '3 (MB, DB, Palatal)', '3 (closer/converging)'],
['MB root', '2 canals (frequent)', '2 canals (less frequent)'],
['Size', 'Largest maxillary molar', 'Smaller'],
['Eruption', '6–7 years', '12–13 years'],
['Crown MD width', '~10–11 mm', '~9–10 mm'],
]
ct1 = Table(comp1, colWidths=[5*cm, 5.5*cm, 5.5*cm])
ct1.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), DARK_BLUE),
('TEXTCOLOR', (0,0), (-1,0), WHITE),
('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
('FONTSIZE', (0,0), (-1,-1), 8.5),
('ROWBACKGROUNDS', (0,1), (-1,-1), [WHITE, LIGHT_BLUE]),
('GRID', (0,0), (-1,-1), 0.4, colors.grey),
('TOPPADDING', (0,0), (-1,-1), 4),
('BOTTOMPADDING', (0,0), (-1,-1), 4),
]))
story += [ct1, SP(3),
H2('11B. Mandibular 1st vs 2nd Molar'),
]
comp2 = [
['Feature', 'Mand 1st Molar', 'Mand 2nd Molar'],
['No. of cusps', '5 (includes distal cusp)', '4 (no distal cusp)'],
['Crown outline', 'Pentagonal', 'Rectangular'],
['Groove pattern', 'Y-5 (complex)', '+ (cross/plus)'],
['Distal cusp', 'Present (makes it 5-cusped)', 'Absent'],
['Roots', '2 (mesial longer)', '2 (closer, less divergent)'],
['Mesial root canals', '2 canals (75–80%)', '2 canals'],
['Root trunk', 'Short (furcation near CEJ)', 'Slightly longer trunk'],
['Size', 'Largest mand molar', 'Smaller'],
['Eruption', '6–7 years (first perm. tooth)', '11–13 years'],
]
ct2 = Table(comp2, colWidths=[5*cm, 5.5*cm, 5.5*cm])
ct2.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), DARK_BLUE),
('TEXTCOLOR', (0,0), (-1,0), WHITE),
('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
('FONTSIZE', (0,0), (-1,-1), 8.5),
('ROWBACKGROUNDS', (0,1), (-1,-1), [WHITE, LIGHT_BLUE]),
('GRID', (0,0), (-1,-1), 0.4, colors.grey),
('TOPPADDING', (0,0), (-1,-1), 4),
('BOTTOMPADDING', (0,0), (-1,-1), 4),
]))
story += [ct2, SP(3),
H2('11C. Maxillary vs Mandibular Molars – Master Comparison'),
]
master = [
['Feature', 'MAXILLARY MOLARS', 'MANDIBULAR MOLARS'],
['No. of roots', '3 (MB, DB, Palatal)', '2 (Mesial, Distal)'],
['Root type', 'Trifurcation', 'Bifurcation'],
['Largest root', 'Palatal (lingual)', 'Mesial'],
['Oblique ridge', 'PRESENT (hallmark)', 'ABSENT'],
['Crown outline', 'Rhomboidal', 'Rectangular/Pentagonal'],
['Buccal cusps', '2 (MB, DB)', '3 in 1st; 2 in 2nd'],
['Lingual cusps', '2 (ML, DL)', '2 (ML, DL)'],
['Largest cusp', 'Mesiolingual (ML)', 'Mesiolingual (ML)'],
['Buccal vs Lingual cusp height', 'Lingual cusps may be taller', 'Buccal cusps are taller'],
['Carabelli feature', 'On Max 1st molar', 'Absent'],
['Special root', 'Radix paramolaris (rare)', 'Radix entomolaris (Asian pop)'],
['Furcation area', 'Closer to apex', 'Closer to CEJ (shorter trunk)'],
]
mt = Table(master, colWidths=[5*cm, 5.5*cm, 5.5*cm])
mt.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), DARK_BLUE),
('TEXTCOLOR', (0,0), (-1,0), WHITE),
('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
('BACKGROUND', (1,0), (1,0), colors.HexColor('#C9870A')),
('BACKGROUND', (2,0), (2,0), MED_BLUE),
('FONTSIZE', (0,0), (-1,-1), 8.5),
('ROWBACKGROUNDS', (0,1), (-1,-1), [WHITE, LIGHT_BLUE]),
('GRID', (0,0), (-1,-1), 0.4, colors.grey),
('TOPPADDING', (0,0), (-1,-1), 4),
('BOTTOMPADDING', (0,0), (-1,-1), 4),
]))
story += [mt, PageBreak()]
# ═══════════════════════════════════════════
# SECTION 12 – CLINICAL SIGNIFICANCE
# ═══════════════════════════════════════════
story += [
H1('SECTION 12: CLINICAL SIGNIFICANCE'),
SP(2),
H2('12A. Caries Susceptibility'),
B('Pit and fissure caries: Occlusal pits and fissures are the most common site for caries in molars.'),
B('Proximal caries: Common at contact areas (mesial > distal).'),
B('Buccal pit: Mandibular 1st molar buccal pit is prone to caries.'),
B('Prevention: Pit and fissure sealants are used routinely.'),
SP(2),
H2('12B. Endodontic Relevance'),
B('Max 1st molar MB root: 2 canals (MB1 + MB2) present in ~60–70% – most missed canal in endodontics.'),
B('Mand 1st molar mesial root: 2 canals in ~75–80% (ML + MB canals).'),
B('C-shaped canals: Most common in mandibular 2nd molar (especially in Asian populations).'),
B('Pulp chamber floor of lower molars: Trapezoidal shape; 3–4 canal orifices.'),
B('Taurodontism: Enlarged pulp chamber extending into root – root trunk elongated – complicates endodontic treatment.'),
SP(2),
H2('12C. Periodontal Relevance'),
B('Furcation involvement: When bone loss reaches the furcation area – critical for prognosis.'),
B('Furcation classification (Glickman): Class I – early; Class II – partial; Class III – through and through.'),
B('Mandibular molars have furcation close to CEJ (short root trunk) – furcation involvement occurs early.'),
B('Root form: Flat mesial surface of mand mesial root – provides poor bone support.'),
SP(2),
H2('12D. Prosthetic & Restorative Relevance'),
B('MOD (mesio-occluso-distal) preparation is common in molars.'),
B('Cusp coverage is often required due to oblique ridge and cuspal fracture risk.'),
B('Crown height: Adequate occlusal clearance needed for restoration.'),
B('Abutment teeth: Molars are commonly used as abutments in fixed partial dentures and implant-supported restorations.'),
SP(2),
H2('12E. Impaction'),
B('3rd molar impaction: Most common in both arches.'),
B('Surgical access: Mandibular 3rd molar – close to IAN; Maxillary 3rd molar – close to max sinus.'),
SP(2),
N('The first molar is the most important tooth functionally and the most commonly restored tooth. Its early loss (due to caries at 6 years) has major arch integrity implications.'),
PageBreak(),
]
# ═══════════════════════════════════════════
# SECTION 13 – HIGH-YIELD VIVA Q&A
# ═══════════════════════════════════════════
story += [
H1('SECTION 13: HIGH-YIELD VIVA Q&A'),
SP(2),
H2('Maxillary Molar Viva Questions'),
B('<b>Q: What is the hallmark feature of maxillary molars?</b>'),
B2('A: The OBLIQUE RIDGE – connecting triangular ridge of ML cusp to that of DB cusp, crossing the tooth obliquely.'),
B('<b>Q: How many roots does the maxillary 1st molar have?</b>'),
B2('A: 3 roots – MB, DB, and palatal. The palatal root is the longest and largest.'),
B('<b>Q: What is the Cusp of Carabelli?</b>'),
B2('A: An accessory 5th cusp found on the mesiolingual surface of the mesiolingual cusp of the max 1st molar. It has no functional role and shows racial variation.'),
B('<b>Q: What is the order of cusp size in max 1st molar?</b>'),
B2('A: ML > MB > DB > DL > Carabelli (5th).'),
B('<b>Q: Which canal is most commonly missed in max 1st molar?</b>'),
B2('A: MB2 canal in the mesiobuccal root.'),
B('<b>Q: What is the crown outline of max 1st molar?</b>'),
B2('A: Rhomboidal (diamond-shaped) – wider buccally, oblique angles at MB and DL corners.'),
SP(2),
H2('Mandibular Molar Viva Questions'),
B('<b>Q: How many cusps does mandibular 1st molar have?</b>'),
B2('A: 5 cusps – MB, DB, distal (DC), ML, DL. The distal cusp makes it unique.'),
B('<b>Q: What is the crown outline of mandibular 1st molar?</b>'),
B2('A: Pentagonal (5-sided) due to the distal cusp.'),
B('<b>Q: What is the groove pattern of mandibular 2nd molar?</b>'),
B2('A: + (plus/cross) shaped groove pattern – this is its hallmark.'),
B('<b>Q: What are the roots of mandibular molars?</b>'),
B2('A: 2 roots – mesial and distal. Mesial root is longer, broader, has 2 canals.'),
B('<b>Q: What is Radix entomolaris?</b>'),
B2('A: An extra distal-lingual root seen more commonly in Asian populations on mandibular molars.'),
B('<b>Q: Which tooth is called the cornerstone of the dental arch?</b>'),
B2('A: The mandibular 1st molar – first permanent tooth to erupt, most important for establishing occlusion.'),
B('<b>Q: What is taurodontism?</b>'),
B2('A: A variant where the pulp chamber is very large and root trunk is elongated, with roots shorter than normal. Most common in mand 3rd molar; seen in Klinefelter syndrome.'),
B('<b>Q: What is the most common impaction type for mandibular 3rd molar?</b>'),
B2('A: Mesioangular impaction (~44% of cases).'),
B('<b>Q: What is C-shaped canal?</b>'),
B2('A: A continuous arc of one or more canals with a C-shaped cross-section; most common in mandibular 2nd molar, especially in Asian populations.'),
SP(3),
H2('Quick Summary Points for Revision'),
]
summary_data = [
['Tooth', 'Cusps', 'Crown Shape', 'Roots', 'Hallmark Feature'],
['Max 1st Molar', '5 (MB+DB+ML+DL+Carabelli)', 'Rhomboidal', '3 (MB, DB, Palatal)', 'Oblique Ridge + Carabelli'],
['Max 2nd Molar', '4 (MB+DB+ML+DL)', 'Rhomboidal/Heart', '3 (converging)', 'Oblique Ridge; No Carabelli'],
['Mand 1st Molar', '5 (MB+DB+DC+ML+DL)', 'Pentagonal', '2 (M, D)', 'Distal cusp; 1st to erupt'],
['Mand 2nd Molar', '4 (MB+DB+ML+DL)', 'Rectangular', '2 (close/parallel)', '+ groove pattern'],
]
st = Table(summary_data, colWidths=[3.5*cm, 4*cm, 3.5*cm, 3*cm, 4.5*cm])
st.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), DARK_BLUE),
('TEXTCOLOR', (0,0), (-1,0), WHITE),
('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
('FONTSIZE', (0,0), (-1,-1), 8),
('ROWBACKGROUNDS', (0,1), (-1,-1), [LIGHT_GOLD, LIGHT_BLUE]),
('GRID', (0,0), (-1,-1), 0.4, colors.grey),
('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
('TOPPADDING', (0,0), (-1,-1), 5),
('BOTTOMPADDING', (0,0), (-1,-1), 5),
]))
story += [st, SP(4),
HR(),
SP(2),
Paragraph('End of Document – Best of luck for your examinations!',
S('end', fontSize=10, fontName='Helvetica-BoldOblique', textColor=MED_BLUE,
alignment=TA_CENTER)),
]
# ─── BUILD PDF ───
doc.build(story)
print(f"\nPDF created: {PDF_PATH}")
print(f"File size: {os.path.getsize(PDF_PATH)/1024:.1f} KB")
cd /tmp/workspace/molar-anatomy && python3 build_molar_pdf.py 2>&1
cd /tmp/workspace/molar-anatomy && sed -i "s/DARK_BLUE\.hexval() if hasattr(DARK_BLUE,'hexval') else '#1a3a5c'/'#1a3a5c'/g" build_molar_pdf.py && python3 build_molar_pdf.py 2>&1
Maxillary Mandibular Molars Complete
PDF Document · PDF