History taking in ent
| Component | Content |
|---|---|
| Presenting complaint (PC) | Chief symptom in the patient's own words |
| History of presenting complaint (HPC) | SOCRATES for each symptom |
| Past medical/surgical history | Especially prior ENT operations (tonsillectomy, myringotomy, septoplasty, etc.) |
| Drug history | Ototoxic drugs (aminoglycosides, loop diuretics, cisplatin), antihypertensives, decongestants, anticoagulants |
| Allergies | Drug allergies + atopic history (rhinitis, asthma, eczema) |
| Family history | Hearing loss, neurofibromatosis type 2, autoimmune disorders, head and neck neoplasms |
| Social history | Smoking, alcohol, occupation (noise exposure, chemical exposure), travel history, sexual history |
| Systems review | Weight loss, fatigue, fever, neurological symptoms |
| Question | Significance |
|---|---|
| Duration of each attack (seconds/minutes/hours/days) | BPPV = seconds; Meniere's = 20 min - 12 hrs; vestibular neuritis = days |
| Frequency (daily/weekly/monthly) | Pattern recognition |
| Effect of head movements | Positional = BPPV |
| Inducing position/posture | Rolling to one side points to specific semicircular canal |
| Associated hearing loss, tinnitus, aural pressure | Points to inner ear (Meniere's disease) |
| Prior ear disease or ear surgery | Labyrinthine fistula, cholesteatoma |
| Family history, diabetes, neurofibromatosis | Genetic/systemic cause |
| Head trauma, medications, comorbidities | Ototoxicity, post-traumatic |

| Red Flag | Possible Cause |
|---|---|
| Hoarseness > 3 weeks | Laryngeal carcinoma |
| Unilateral bloodstained nasal discharge | Nasal/sinus malignancy |
| Unilateral serous otitis media in adult | Nasopharyngeal carcinoma |
| Progressive unilateral sensorineural hearing loss | Acoustic neuroma (vestibular schwannoma) |
| Trismus + peritonsillar swelling | Peritonsillar abscess |
| Stridor | Airway compromise |
| Neck lump + constitutional symptoms | Lymphoma, metastatic carcinoma |
| Progressive dysphagia + weight loss | Hypopharyngeal/oesophageal carcinoma |
| Facial nerve palsy + parotid lump | Parotid malignancy |
1
| Letter | Stands for | Example questions in ENT |
|---|---|---|
| S | Site | "Which ear?" / "Which side of the nose?" |
| O | Onset | "When did it start? Was it sudden or gradual?" |
| C | Character | "Is the pain sharp, dull, throbbing? Is the discharge watery or thick?" |
| R | Radiation | "Does the pain spread anywhere - jaw, neck?" |
| A | Associations | "Any hearing loss with the pain? Any fever?" |
| T | Timing | "Is it constant or does it come and go? Any pattern?" |
| E | Exacerbating/Relieving | "What makes it worse or better?" |
| S | Severity | "On a scale of 1-10, how bad is it? How is it affecting your daily life?" |
| Drug Category | ENT Relevance |
|---|---|
| Aminoglycoside antibiotics (gentamicin, streptomycin, neomycin) | Ototoxicity - cochlear and vestibular damage |
| Loop diuretics (furosemide) | Ototoxicity, especially combined with aminoglycosides |
| Cytotoxic drugs (cisplatin, carboplatin) | Ototoxicity |
| Quinine / antimalarials | Tinnitus, hearing loss |
| Aspirin and NSAIDs (high dose) | Reversible tinnitus |
| Antihypertensives / beta-blockers | Nasal stuffiness; relevant in OSA workup |
| Anticoagulants (warfarin, DOACs) | Epistaxis |
| Nasal decongestants (oxymetazoline) | Rhinitis medicamentosa with prolonged use |
| ACE inhibitors | Chronic cough (can be mistaken for throat/laryngeal problem) |
| Bisphosphonates | Osteonecrosis of the jaw - relevant in head and neck surgery |
| Condition | Reason to ask |
|---|---|
| Hearing loss | Genetic SNHL (connexin 26/GJB2 mutation, Pendred syndrome, Usher syndrome) |
| Neurofibromatosis type 2 | Bilateral acoustic neuromas - autosomal dominant |
| Otosclerosis | Autosomal dominant with variable penetrance |
| Hereditary haemorrhagic telangiectasia (Osler-Weber-Rendu) | Recurrent severe epistaxis |
| Head and neck malignancy | Increased risk |
| Autoimmune disorders | Sjogren's, SLE, rheumatoid arthritis - can affect ENT |
| Allergic disease | Atopy runs in families |
| Cleft palate / craniofacial abnormalities | Associated middle ear disease |
| Factor | ENT Relevance |
|---|---|
| Smoking | Laryngeal/pharyngeal/oral cancer, chronic rhinitis, worsens OSA |
| Alcohol | Head and neck cancer risk (synergistic with smoking), parotid enlargement |
| Occupation | Noise-induced hearing loss (factory workers, musicians, military); voice overuse (teachers, singers, call centre workers); chemical exposures (woodworkers - adenocarcinoma of ethmoid); farming (fungal sinusitis) |
| Recreational activities | Loud music/concerts (noise-induced hearing loss); swimming (otitis externa, otitis media); diving (barotrauma - perilymph fistula) |
| Air travel | Ear barotrauma, sinus pain |
| International travel | Tuberculosis (scrofula - cervical lymphadenopathy), rhinoscleroma, leishmaniasis |
| Sexual history | HPV (oropharyngeal cancer - base of tongue, tonsil); syphilis; HIV |
| Pets | Allergen exposure (cat dander, dog hair) |
| Marital/living situation | Bed partner history in OSA; passive smoking in children with recurrent otitis media |
Printable fornat
ls -la /home/daytona/workspace/ 2>/dev/null || mkdir -p /home/daytona/workspace && ls -la /home/daytona/workspace/
mkdir -p /home/daytona/workspace/ent-history && echo "done"
~/ent-history/generate_pdf.py
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether
)
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
OUTPUT = "/home/daytona/workspace/ent-history/ENT_History_Taking.pdf"
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
leftMargin=2*cm,
rightMargin=2*cm,
topMargin=2*cm,
bottomMargin=2*cm,
title="ENT History Taking",
author="Orris Medical"
)
styles = getSampleStyleSheet()
# Custom styles
TEAL = colors.HexColor("#006B6B")
LIGHT_TEAL = colors.HexColor("#E6F4F4")
DARK = colors.HexColor("#1A1A2E")
ACCENT = colors.HexColor("#D97706")
LIGHT_GREY = colors.HexColor("#F5F5F5")
MID_GREY = colors.HexColor("#CCCCCC")
title_style = ParagraphStyle(
"Title", parent=styles["Title"],
fontSize=20, textColor=TEAL,
spaceAfter=4, alignment=TA_CENTER,
fontName="Helvetica-Bold"
)
subtitle_style = ParagraphStyle(
"Subtitle", parent=styles["Normal"],
fontSize=10, textColor=colors.grey,
spaceAfter=12, alignment=TA_CENTER,
fontName="Helvetica-Oblique"
)
section_style = ParagraphStyle(
"Section", parent=styles["Heading1"],
fontSize=12, textColor=colors.white,
spaceBefore=10, spaceAfter=4,
fontName="Helvetica-Bold",
backColor=TEAL,
leftIndent=-6, rightIndent=-6,
borderPad=4
)
subsection_style = ParagraphStyle(
"Subsection", parent=styles["Heading2"],
fontSize=10, textColor=TEAL,
spaceBefore=6, spaceAfter=2,
fontName="Helvetica-Bold"
)
body_style = ParagraphStyle(
"Body", parent=styles["Normal"],
fontSize=9, leading=13,
textColor=DARK,
fontName="Helvetica"
)
bullet_style = ParagraphStyle(
"Bullet", parent=styles["Normal"],
fontSize=9, leading=12,
leftIndent=14, firstLineIndent=-10,
textColor=DARK,
fontName="Helvetica",
bulletIndent=4
)
bullet2_style = ParagraphStyle(
"Bullet2", parent=styles["Normal"],
fontSize=8.5, leading=11,
leftIndent=26, firstLineIndent=-10,
textColor=DARK,
fontName="Helvetica"
)
redflag_style = ParagraphStyle(
"RedFlag", parent=styles["Normal"],
fontSize=9, leading=12,
textColor=colors.HexColor("#7B0000"),
fontName="Helvetica-Bold"
)
note_style = ParagraphStyle(
"Note", parent=styles["Normal"],
fontSize=8, leading=11,
textColor=colors.grey,
fontName="Helvetica-Oblique",
alignment=TA_CENTER
)
def section_header(text):
return [
Spacer(1, 6),
Paragraph(f" {text}", section_style),
Spacer(1, 4),
]
def subsection(text):
return Paragraph(text, subsection_style)
def body(text):
return Paragraph(text, body_style)
def bullet(text, level=1):
style = bullet_style if level == 1 else bullet2_style
return Paragraph(f"\u2022 {text}", style)
def spacer(h=4):
return Spacer(1, h)
# Table helper
def make_table(data, col_widths, row_colors=None):
t = Table(data, colWidths=col_widths, repeatRows=1)
style_cmds = [
("BACKGROUND", (0, 0), (-1, 0), TEAL),
("TEXTCOLOR", (0, 0), (-1, 0), colors.white),
("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"),
("FONTSIZE", (0, 0), (-1, 0), 8.5),
("FONTNAME", (0, 1), (-1, -1), "Helvetica"),
("FONTSIZE", (0, 1), (-1, -1), 8.5),
("ROWBACKGROUNDS", (0, 1), (-1, -1), [colors.white, LIGHT_GREY]),
("GRID", (0, 0), (-1, -1), 0.4, MID_GREY),
("VALIGN", (0, 0), (-1, -1), "TOP"),
("LEFTPADDING", (0, 0), (-1, -1), 5),
("RIGHTPADDING", (0, 0), (-1, -1), 5),
("TOPPADDING", (0, 0), (-1, -1), 4),
("BOTTOMPADDING", (0, 0), (-1, -1), 4),
("WORDWRAP", (0, 0), (-1, -1), True),
]
t.setStyle(TableStyle(style_cmds))
return t
# ─── Build story ────────────────────────────────────────────────────────────────
story = []
# Title block
story.append(Spacer(1, 8))
story.append(Paragraph("ENT History Taking", title_style))
story.append(Paragraph("Ear • Nose & Sinuses • Throat & Larynx • Head & Neck", subtitle_style))
story.append(HRFlowable(width="100%", thickness=2, color=TEAL, spaceAfter=6))
# ── SECTION 1: GENERAL FRAMEWORK ────────────────────────────────────────────────
story += section_header("1. GENERAL FRAMEWORK")
story.append(subsection("Opening the Consultation"))
for b in [
"Greet the patient; confirm name and age",
"Open with an open-ended question: \"What has brought you in today?\"",
"Allow the patient to speak uninterrupted for the first 1–2 minutes",
"Record the <b>Presenting Complaint (PC)</b> in the patient's own words",
]:
story.append(bullet(b))
story.append(spacer())
story.append(subsection("SOCRATES — History of Presenting Complaint (HPC)"))
socrates_data = [
["Letter", "Stands for", "Example in ENT"],
["S", "Site", "Which ear? Which side of the nose?"],
["O", "Onset", "When did it start? Sudden or gradual?"],
["C", "Character", "Sharp/dull pain? Watery/thick discharge?"],
["R", "Radiation", "Does pain spread to jaw or neck?"],
["A", "Associations", "Any hearing loss with the pain? Fever?"],
["T", "Timing", "Constant or comes and goes? Any pattern?"],
["E", "Exacerbating/Relieving", "What makes it worse or better?"],
["S", "Severity", "1–10 scale. Effect on daily life?"],
]
story.append(make_table(socrates_data, [0.6*cm, 3*cm, 4*cm, 9.3*cm]))
story.append(spacer())
# ── SECTION 2: EAR ──────────────────────────────────────────────────────────────
story += section_header("2. EAR (Otological History)")
story.append(subsection("A. Hearing Loss"))
for b in [
"Onset: sudden vs. gradual; progressive, intermittent, or continuous",
"Unilateral or bilateral",
"Fluctuating (Ménière's) or steadily worsening",
"Associated tinnitus, vertigo, aural fullness",
"History of noise exposure, ototoxic medications, head trauma, ear infections or surgery",
"Worsening with pregnancy or oral contraceptive use (otosclerosis)",
"Family history of deafness (connexin 26/GJB2, Usher syndrome, Pendred syndrome)",
]:
story.append(bullet(b))
story.append(spacer(4))
story.append(subsection("B. Otalgia (Ear Pain)"))
for b in [
"Primary otalgia: pain originates in the ear",
"Referred otalgia — common sources via cranial nerves:",
]:
story.append(bullet(b))
referred = [
["CN V (trigeminal)", "Dental disease, TMJ dysfunction"],
["CN IX (glossopharyngeal)", "Tonsil, oropharynx, base of tongue"],
["CN X (vagus)", "Larynx, hypopharynx, oesophagus"],
["C2–C3 cervical", "Cervical spine, posterior fossa"],
]
ref_table = Table(referred, colWidths=[5.5*cm, 11.5*cm])
ref_table.setStyle(TableStyle([
("FONTNAME", (0, 0), (-1, -1), "Helvetica"),
("FONTSIZE", (0, 0), (-1, -1), 8.5),
("ROWBACKGROUNDS", (0, 0), (-1, -1), [colors.white, LIGHT_GREY]),
("GRID", (0, 0), (-1, -1), 0.4, MID_GREY),
("LEFTPADDING", (0, 0), (-1, -1), 5),
("TOPPADDING", (0, 0), (-1, -1), 3),
("BOTTOMPADDING", (0, 0), (-1, -1), 3),
]))
story.append(ref_table)
story.append(spacer(4))
story.append(subsection("C. Otorrhoea (Ear Discharge)"))
for b in [
"Character: watery / mucoid / mucopurulent / bloody / foul cheesy (→ cholesteatoma)",
"Duration and frequency; relation to upper respiratory infection",
"Painless chronic discharge → consider chronic suppurative otitis media (CSOM)",
]:
story.append(bullet(b))
story.append(spacer(4))
story.append(subsection("D. Tinnitus"))
for b in [
"Subjective (most common) or objective/pulsatile (→ vascular cause)",
"Unilateral or bilateral; pitch and character (ringing, buzzing, roaring)",
"Associated hearing loss or vertigo",
"Effect on sleep and quality of life",
]:
story.append(bullet(b))
story.append(spacer(4))
story.append(subsection("E. Vertigo / Dizziness — Minimum History (K.J. Lee)"))
vertigo_data = [
["Question", "Significance"],
["Duration of each attack", "Seconds = BPPV; 20 min–12 h = Ménière's; Days = vestibular neuritis"],
["Frequency", "Daily / weekly / monthly — pattern recognition"],
["Effect of head movements", "Positional → BPPV"],
["Inducing position/posture", "Rolling onto one side → specific canal involved"],
["Associated hearing loss, tinnitus, aural fullness", "→ Inner ear (Ménière's disease)"],
["Prior ear disease or surgery", "Labyrinthine fistula, cholesteatoma"],
["Family history, diabetes, neurofibromatosis", "Genetic / systemic cause"],
["Head trauma, medications, comorbidities", "Ototoxicity, post-traumatic"],
]
story.append(make_table(vertigo_data, [5.5*cm, 11.5*cm]))
story.append(spacer())
# ── SECTION 3: NOSE ─────────────────────────────────────────────────────────────
story += section_header("3. NOSE & SINUSES (Rhinological History)")
nose_items = {
"A. Nasal Obstruction": [
"Unilateral or bilateral; constant or intermittent",
"Worse at certain times (day/night, seasonal) → allergy vs. structural",
"Associated mouth breathing, snoring, sleep apnoea symptoms",
],
"B. Rhinorrhoea (Discharge)": [
"Clear/watery → allergy, CSF leak (unilateral, salty taste, halo sign)",
"Mucoid → sinusitis; mucopurulent → bacterial infection",
"Unilateral bloodstained discharge in adult → exclude malignancy (red flag)",
],
"C. Epistaxis": [
"Site: anterior (Little's area, most common) vs. posterior",
"Frequency, duration, estimated volume",
"Precipitating factors: trauma, nose-picking, anticoagulants, hypertension",
"Family history → hereditary haemorrhagic telangiectasia (Osler-Weber-Rendu)",
],
"D. Anosmia / Hyposmia": [
"Sudden onset: post-URI or post-traumatic",
"Gradual/fluctuating: sinusitis, allergies, neurodegenerative disease",
"Congenital anosmia → Kallmann syndrome (hypogonadism)",
"Distinguish: flavour complaints (smell) vs. basic taste (sweet/sour/salty/bitter — taste)",
],
"E. Facial Pain / Pressure": [
"Forehead → frontal sinus; cheeks → maxillary; between eyes → ethmoid; top of head → sphenoid",
"Worse on bending forward → sinusitis",
"Associated nasal discharge or blockage",
],
"F. Sneezing, Itching, Postnasal Drip": [
"Suggests allergic rhinitis; identify allergens (dust, pollen, animals, occupational)",
"Seasonal vs. perennial pattern",
],
}
for heading, bullets in nose_items.items():
story.append(subsection(heading))
for b in bullets:
story.append(bullet(b))
story.append(spacer(3))
# ── SECTION 4: THROAT ───────────────────────────────────────────────────────────
story += section_header("4. THROAT & LARYNX (Laryngopharyngeal History)")
throat_items = {
"A. Dysphagia (Difficulty Swallowing)": [
"Level: oral / pharyngeal (nasal regurgitation, coughing) / oesophageal",
"Solids only → mechanical obstruction (stricture, carcinoma)",
"Solids and liquids → motility disorder",
"Progressive (→ carcinoma) or intermittent (web, dysmotility)",
"Associated odynophagia, weight loss, hoarseness, regurgitation",
],
"B. Dysphonia / Hoarseness": [
"Duration > 3 weeks → RED FLAG: laryngoscopy mandatory to exclude malignancy",
"Breathy voice → vocal cord palsy; rough/harsh → nodules, laryngitis",
"Strained / effortful voice → spasmodic dysphonia",
"Voice use history: singers, teachers, call-centre workers (vocal abuse)",
"Reflux, smoking history",
],
"C. Sore Throat": [
"Acute vs. chronic; fever",
"Trismus + peritonsillar swelling → peritonsillar abscess",
"Difficulty breathing / muffled voice / drooling → epiglottitis (EMERGENCY)",
"Recurrent tonsillitis: number of episodes per year, days off school/work",
],
"D. Stridor": [
"Inspiratory → supraglottic/glottic; expiratory → subglottic/tracheal; biphasic → fixed obstruction",
"Acute: foreign body, epiglottitis, angioedema",
"Chronic: subglottic stenosis, laryngeal papillomatosis",
"Always a potential airway emergency — act accordingly",
],
"E. Neck Lump": [
"Location, onset, duration, growth rate",
"Constitutional symptoms: fever, night sweats, weight loss → lymphoma",
"Skin changes, fixation to underlying structures",
"Exposure history: TB contact, cat scratch disease, EBV",
"Associated dysphagia, hoarseness, voice change",
],
}
for heading, bullets in throat_items.items():
story.append(subsection(heading))
for b in bullets:
story.append(bullet(b))
story.append(spacer(3))
# ── SECTION 5: DRUG HISTORY ─────────────────────────────────────────────────────
story += section_header("5. DRUG HISTORY — ENT-Relevant Medications")
drug_data = [
["Drug / Class", "ENT Relevance"],
["Aminoglycosides (gentamicin, streptomycin, neomycin)", "Ototoxicity — cochlear and vestibular damage"],
["Loop diuretics (furosemide)", "Ototoxicity, especially combined with aminoglycosides"],
["Cytotoxics (cisplatin, carboplatin)", "Ototoxicity — high-frequency SNHL"],
["Quinine / antimalarials", "Tinnitus, reversible hearing loss"],
["Aspirin / NSAIDs (high dose)", "Reversible tinnitus"],
["ACE inhibitors", "Chronic dry cough (mistaken for laryngeal/throat problem)"],
["Anticoagulants (warfarin, DOACs)", "Epistaxis"],
["Nasal decongestants (oxymetazoline)", "Rhinitis medicamentosa with prolonged use (>5 days)"],
["Bisphosphonates", "Osteonecrosis of the jaw — relevant pre-operatively"],
]
story.append(make_table(drug_data, [7*cm, 10*cm]))
story.append(spacer())
# ── SECTION 6: FAMILY / SOCIAL HISTORY ─────────────────────────────────────────
story += section_header("6. FAMILY & SOCIAL HISTORY")
story.append(subsection("Family History — Key Conditions"))
fh_data = [
["Condition", "Reason"],
["Hearing loss", "Genetic SNHL (connexin 26/GJB2, Pendred, Usher syndromes)"],
["Neurofibromatosis type 2", "Bilateral acoustic neuromas — autosomal dominant"],
["Otosclerosis", "Autosomal dominant, variable penetrance"],
["Hereditary haemorrhagic telangiectasia", "Recurrent severe epistaxis"],
["Head and neck malignancy", "Increased personal risk"],
["Autoimmune disorders", "Sjogren's, SLE — salivary glands, sudden SNHL"],
["Cleft palate / craniofacial abnormalities", "Associated middle ear disease"],
]
story.append(make_table(fh_data, [6*cm, 11*cm]))
story.append(spacer(6))
story.append(subsection("Social History"))
sh_data = [
["Factor", "ENT Relevance"],
["Smoking", "Laryngeal/pharyngeal/oral cancer; chronic rhinitis; worsens OSA"],
["Alcohol", "Head and neck cancer (synergistic with smoking); parotid enlargement"],
["Occupation", "Noise exposure (factory, military, musicians); voice overuse (teachers, singers); woodworking (ethmoid adenocarcinoma)"],
["Recreational activities", "Loud music (NIHL); swimming (otitis externa); diving (barotrauma)"],
["Air travel", "Ear barotrauma, sinus pressure"],
["International travel", "TB (scrofula), rhinoscleroma, leishmaniasis"],
["Sexual history", "HPV (oropharyngeal cancer — base of tongue, tonsil); syphilis; HIV"],
["Pets", "Allergen exposure (cat dander, dog hair)"],
["Bed partner history", "Essential in OSA assessment — corroborates apnoeic episodes"],
]
story.append(make_table(sh_data, [4.5*cm, 12.5*cm]))
story.append(spacer())
# ── SECTION 7: OSA ──────────────────────────────────────────────────────────────
story += section_header("7. SLEEP / OSA HISTORY")
for b in [
"Sleep habits, hygiene, typical sleep/wake times, shift work",
"Daytime sleepiness — Epworth Sleepiness Scale (score > 10 is significant)",
"Observed apnoeic episodes, choking, gasping (bed partner history is invaluable)",
"Morning headaches, nocturia, poor concentration and memory",
"Comorbidities: hypertension, obesity, metabolic syndrome, cardiovascular disease",
"Occupational risk: drivers / heavy machinery operators may have legal reporting implications",
]:
story.append(bullet(b))
story.append(spacer())
# ── SECTION 8: RED FLAGS ────────────────────────────────────────────────────────
story += section_header("8. RED FLAG SYMPTOMS — Always Screen Actively")
rf_data = [
["Red Flag", "Possible Cause — Action"],
["Hoarseness > 3 weeks", "Laryngeal carcinoma → urgent laryngoscopy"],
["Unilateral bloodstained nasal discharge", "Sinonasal malignancy → urgent ENT referral"],
["Unilateral serous otitis media in adult", "Nasopharyngeal carcinoma → nasopharyngoscopy"],
["Progressive unilateral SNHL", "Acoustic neuroma (vestibular schwannoma) → MRI IAMs"],
["Trismus + peritonsillar swelling", "Peritonsillar abscess → urgent drainage"],
["Stridor", "Airway compromise → treat as emergency"],
["Neck lump + constitutional symptoms", "Lymphoma / metastatic carcinoma → urgent biopsy"],
["Progressive dysphagia + weight loss", "Hypopharyngeal / oesophageal carcinoma"],
["Facial nerve palsy + parotid lump", "Parotid malignancy → urgent imaging and biopsy"],
["Unilateral nasal polyp", "Inverted papilloma, malignancy — not simple polyp"],
]
style_rf = TableStyle([
("BACKGROUND", (0, 0), (-1, 0), colors.HexColor("#7B0000")),
("TEXTCOLOR", (0, 0), (-1, 0), colors.white),
("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"),
("FONTSIZE", (0, 0), (-1, 0), 8.5),
("FONTNAME", (0, 1), (-1, -1), "Helvetica"),
("FONTSIZE", (0, 1), (-1, -1), 8.5),
("ROWBACKGROUNDS", (0, 1), (-1, -1), [colors.white, colors.HexColor("#FFF5F5")]),
("GRID", (0, 0), (-1, -1), 0.4, MID_GREY),
("VALIGN", (0, 0), (-1, -1), "TOP"),
("LEFTPADDING", (0, 0), (-1, -1), 5),
("RIGHTPADDING", (0, 0), (-1, -1), 5),
("TOPPADDING", (0, 0), (-1, -1), 4),
("BOTTOMPADDING", (0, 0), (-1, -1), 4),
])
rf_table = Table(rf_data, colWidths=[6.5*cm, 10.5*cm], repeatRows=1)
rf_table.setStyle(style_rf)
story.append(rf_table)
story.append(spacer(10))
# Footer note
story.append(HRFlowable(width="100%", thickness=1, color=TEAL, spaceBefore=4, spaceAfter=4))
story.append(Paragraph(
"Sources: K.J. Lee's Essential Otolaryngology (9th ed.) • Cummings Otolaryngology Head and Neck Surgery (7th ed.)",
note_style
))
# Build
doc.build(story)
print(f"PDF saved to: {OUTPUT}")
cd /home/daytona/workspace/ent-history && python generate_pdf.py 2>&1
ENT History Taking
PDF Document · PDF