How to take history of COPD . Long case
| Grade | Description |
|---|---|
| 1 | Breathless only with strenuous exercise |
| 2 | Short of breath when hurrying on the level or walking up a slight hill |
| 3 | Walks slower than most people of same age due to breathlessness, or has to stop for breath when walking at own pace |
| 4 | Stops for breath after walking ~100 m or after a few minutes |
| 5 | Too breathless to leave the house, or breathless when dressing/undressing |
Tip: Ask about the "shopping trolley sign" — less breathless when pushing a trolley/cart than walking freely (due to tripod positioning). This is very specific for COPD.
e.g., 20 cigarettes/day for 30 years = 30 pack-years
| Domain | Asked |
|---|---|
| Cough frequency | Never → all the time |
| Sputum/phlegm | None → chest completely full |
| Chest tightness | None → very tight |
| Breathlessness on exertion | Not breathless → very breathless on one flight of stairs |
| Activity limitation at home | Not limited → very limited |
| Confidence leaving home | Confident → not confident at all |
| Sleep quality | Sleeps soundly → does not sleep due to lung condition |
| Energy levels | Lots of energy → no energy |
| System | Ask About |
|---|---|
| Respiratory | Haemoptysis, pleuritic pain, snoring/OSA (overlap syndrome) |
| Cardiovascular | Ankle oedema (cor pulmonale), palpitations (AF common in COPD), chest pain |
| Neurological | Headaches on waking (CO₂ retention), confusion |
| Musculoskeletal | Back pain (vertebral fractures from osteoporosis/steroids), muscle weakness |
| Nutritional | Weight loss (sarcopenia in emphysema), anorexia |
| Psychiatric | Depression, anxiety (very common; affects exacerbation risk) |
| ENT | Chronic sinusitis, nasal polyps (asthma overlap) |
| Condition | Distinguishing Features in History |
|---|---|
| Asthma | Onset in childhood/young adult, episodic wheeze, atopy, family history, fully reversible |
| Heart failure | Orthopnoea, PND, pink frothy sputum, cardiac risk factors |
| Bronchiectasis | Large volumes of mucopurulent sputum daily, recurrent infections, childhood infections |
| TB | Night sweats, weight loss, contact history, foreign travel |
| Lung cancer | Haemoptysis, weight loss, hoarseness, smoking history |
| Pulmonary fibrosis | Dry cough, clubbing, fine crackles, autoimmune disease |
| GOLD Grade | FEV₁ % Predicted |
|---|---|
| 1 (Mild) | ≥80% |
| 2 (Moderate) | 50–79% |
| 3 (Severe) | 30–49% |
| 4 (Very Severe) | <30% |
Create a quick reference PDF for COPD history-taking
ls -la /home/daytona/workspace/ 2>/dev/null && mkdir -p /home/daytona/workspace/copd-pdf
~/copd-pdf/generate_copd_pdf.py
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import mm
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether
)
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus import PageBreak
OUTPUT = "/home/daytona/workspace/copd-pdf/COPD_History_Quick_Reference.pdf"
# ── Colour palette ──────────────────────────────────────────────────────────
NAVY = colors.HexColor("#1A3A5C")
TEAL = colors.HexColor("#1B7A8E")
LIGHTBLUE = colors.HexColor("#E8F4F8")
MIDBLUE = colors.HexColor("#BEE0EA")
ORANGE = colors.HexColor("#E67E22")
LIGHTORANGE= colors.HexColor("#FDF2E9")
RED = colors.HexColor("#C0392B")
GREEN = colors.HexColor("#1E8449")
LIGHTGREEN = colors.HexColor("#E9F7EF")
GREY = colors.HexColor("#F2F3F4")
DARKGREY = colors.HexColor("#566573")
WHITE = colors.white
BLACK = colors.HexColor("#1C2833")
# ── Styles ───────────────────────────────────────────────────────────────────
styles = getSampleStyleSheet()
def S(name, **kw):
return ParagraphStyle(name, **kw)
title_style = S("Title",
fontName="Helvetica-Bold", fontSize=20, textColor=WHITE,
alignment=TA_CENTER, spaceAfter=4, leading=24)
subtitle_style = S("Subtitle",
fontName="Helvetica", fontSize=10, textColor=MIDBLUE,
alignment=TA_CENTER, spaceAfter=2)
section_header = S("SecHdr",
fontName="Helvetica-Bold", fontSize=9.5, textColor=WHITE,
alignment=TA_LEFT, leftIndent=4, leading=13)
body = S("Body",
fontName="Helvetica", fontSize=8.5, textColor=BLACK,
leading=12, spaceAfter=2)
body_bold = S("BodyBold",
fontName="Helvetica-Bold", fontSize=8.5, textColor=BLACK,
leading=12, spaceAfter=2)
bullet = S("Bullet",
fontName="Helvetica", fontSize=8.5, textColor=BLACK,
leading=12, leftIndent=10, firstLineIndent=-8, spaceAfter=1.5)
bullet_bold = S("BulletBold",
fontName="Helvetica-Bold", fontSize=8.5, textColor=NAVY,
leading=12, leftIndent=10, firstLineIndent=-8, spaceAfter=1.5)
small = S("Small",
fontName="Helvetica", fontSize=7.5, textColor=DARKGREY,
leading=10, spaceAfter=1)
small_italic = S("SmallItalic",
fontName="Helvetica-Oblique", fontSize=7.5, textColor=DARKGREY,
leading=10, spaceAfter=1)
table_hdr = S("TblHdr",
fontName="Helvetica-Bold", fontSize=8, textColor=WHITE,
alignment=TA_CENTER, leading=11)
table_cell = S("TblCell",
fontName="Helvetica", fontSize=8, textColor=BLACK,
leading=11)
table_cell_bold = S("TblCellBold",
fontName="Helvetica-Bold", fontSize=8, textColor=BLACK,
leading=11)
warn = S("Warn",
fontName="Helvetica-BoldOblique", fontSize=8.5, textColor=RED,
leading=12, leftIndent=8, spaceAfter=2)
tip = S("Tip",
fontName="Helvetica-Oblique", fontSize=8, textColor=GREEN,
leading=11, leftIndent=8, spaceAfter=2)
# ── Helper flowables ─────────────────────────────────────────────────────────
def section_box(title, bg=NAVY):
"""Coloured section header bar."""
data = [[Paragraph(f"▌ {title}", section_header)]]
t = Table(data, colWidths=[178*mm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 6),
("RIGHTPADDING", (0,0), (-1,-1), 4),
("ROWBACKGROUNDS",(0,0), (-1,-1), [bg]),
]))
return t
def mini_box(title, bg=TEAL):
"""Smaller sub-header."""
data = [[Paragraph(f" {title}", S("mhdr",
fontName="Helvetica-Bold", fontSize=8.5, textColor=WHITE,
alignment=TA_LEFT, leading=12))]]
t = Table(data, colWidths=[178*mm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 4),
]))
return t
def sp(h=3):
return Spacer(1, h*mm)
def hr():
return HRFlowable(width="100%", thickness=0.5, color=MIDBLUE, spaceAfter=2)
def tbl(data, col_widths, style_extras=None, bg_header=NAVY):
ts = [
("BACKGROUND", (0,0), (-1,0), bg_header),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 8),
("ROWBACKGROUNDS",(0,1), (-1,-1), [WHITE, GREY]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#D5D8DC")),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 5),
("RIGHTPADDING", (0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("ALIGN", (0,0), (-1,0), "CENTER"),
]
if style_extras:
ts.extend(style_extras)
t = Table(data, colWidths=col_widths)
t.setStyle(TableStyle(ts))
return t
# ── Build content ─────────────────────────────────────────────────────────────
def build():
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
leftMargin=16*mm, rightMargin=16*mm,
topMargin=14*mm, bottomMargin=14*mm,
title="COPD History Quick Reference",
author="Orris Medical"
)
story = []
# ── TITLE BANNER ──────────────────────────────────────────────────────────
banner_data = [[
Paragraph("COPD HISTORY TAKING", title_style),
Paragraph("Quick Reference — Long Case", subtitle_style),
]]
banner = Table([[
Paragraph("COPD HISTORY TAKING", title_style),
],[
Paragraph("Quick Reference — Long Case", subtitle_style),
]], colWidths=[178*mm])
banner.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), NAVY),
("TOPPADDING", (0,0), (-1,-1), 8),
("BOTTOMPADDING", (0,0), (-1,-1), 8),
("LEFTPADDING", (0,0), (-1,-1), 6),
("RIGHTPADDING", (0,0), (-1,-1), 6),
]))
story.append(banner)
story.append(sp(3))
# ── PRESENTING COMPLAINT + HPC ────────────────────────────────────────────
story.append(section_box("1. PRESENTING COMPLAINT & HISTORY OF PRESENTING COMPLAINT"))
story.append(sp(1))
# Two-column layout: Dyspnoea + Cough/Sputum
left = [
Paragraph("<b>DYSPNOEA</b> (Cardinal Symptom)", body_bold),
Paragraph("• Onset — gradual over years (typical) vs. acute (exacerbation)", bullet),
Paragraph("• Duration & progression", bullet),
Paragraph("• Exertional threshold — stairs? flat ground? dressing?", bullet),
Paragraph("• Orthopnoea / PND (suggests HF overlap)", bullet),
Paragraph("• 'Shopping trolley sign' — less breathless pushing a cart<br/>"
" <i>(tripod position, specific for COPD)</i>", bullet),
sp(2),
Paragraph("<b>MRC Dyspnoea Scale</b>", body_bold),
]
mrc_data = [
[Paragraph("Grade", table_hdr), Paragraph("Description", table_hdr)],
[Paragraph("1", table_cell), Paragraph("Breathless only with strenuous exercise", table_cell)],
[Paragraph("2", table_cell), Paragraph("Short of breath hurrying on flat or slight hill", table_cell)],
[Paragraph("3", table_cell), Paragraph("Walks slower than peers due to breathlessness", table_cell)],
[Paragraph("4", table_cell), Paragraph("Stops for breath after ~100 m or a few minutes", table_cell)],
[Paragraph("5", table_cell), Paragraph("Too breathless to leave house / breathless dressing", table_cell)],
]
left.append(tbl(mrc_data, [12*mm, 63*mm]))
right = [
Paragraph("<b>COUGH</b>", body_bold),
Paragraph("• Onset & duration — chronic ≥3 months/yr for ≥2 yrs = chronic bronchitis", bullet),
Paragraph("• Character — productive vs. dry", bullet),
Paragraph("• Morning cough ('morning ritual')", bullet),
Paragraph("• Worse in winter / cold air", bullet),
sp(2),
Paragraph("<b>SPUTUM</b>", body_bold),
Paragraph("• Volume per day (teaspoon / tablespoon / egg cup)", bullet),
Paragraph("• Colour: white/grey = stable; yellow/green = infection; rust = pneumococcal; pink frothy = pulm. oedema", bullet),
sp(2),
Paragraph("<b>HAEMOPTYSIS</b>", body_bold),
Paragraph(
"⚠ Clubbing is NOT a feature of COPD. "
"If present → investigate for lung cancer or pulmonary fibrosis.", warn),
sp(2),
Paragraph("<b>WHEEZE & CHEST TIGHTNESS</b>", body_bold),
Paragraph("• Wheeze — persistent or episodic? Response to bronchodilators?", bullet),
Paragraph("• Chest tightness — pleuritic? Central? (cor pulmonale, IHD)", bullet),
]
two_col = Table([[left, right]], colWidths=[89*mm, 89*mm])
two_col.setStyle(TableStyle([
("VALIGN", (0,0), (-1,-1), "TOP"),
("LEFTPADDING", (0,0), (-1,-1), 3),
("RIGHTPADDING", (0,0), (-1,-1), 3),
("TOPPADDING", (0,0), (-1,-1), 2),
("BOTTOMPADDING", (0,0), (-1,-1), 2),
]))
story.append(two_col)
story.append(sp(2))
# ── EXACERBATION HISTORY ──────────────────────────────────────────────────
story.append(section_box("2. EXACERBATION HISTORY", bg=TEAL))
story.append(sp(1))
ex_data = [
[Paragraph("Ask About", table_hdr), Paragraph("Details", table_hdr)],
[Paragraph("Frequency", table_cell_bold), Paragraph("How many per year?", table_cell)],
[Paragraph("Triggers", table_cell_bold), Paragraph("URTI, environmental, seasonal", table_cell)],
[Paragraph("Symptoms", table_cell_bold), Paragraph("↑ dyspnoea, ↑ cough, change in sputum quantity or purulence", table_cell)],
[Paragraph("Severity", table_cell_bold), Paragraph("Treated at home? GP visit? A&E? ICU admission?", table_cell)],
[Paragraph("Hospitalisations", table_cell_bold), Paragraph("Number, dates, intubated or on NIV (BiPAP)?", table_cell)],
[Paragraph("Rescue pack", table_cell_bold), Paragraph("Home supply of steroids/antibiotics?", table_cell)],
]
story.append(tbl(ex_data, [38*mm, 140*mm], bg_header=TEAL))
story.append(sp(2))
# ── RISK FACTORS ──────────────────────────────────────────────────────────
story.append(section_box("3. RISK FACTOR HISTORY (AETIOLOGY)", bg=ORANGE))
story.append(sp(1))
rf_left = [
Paragraph("<b>SMOKING — Most Important</b>", body_bold),
Paragraph("• Type: cigarettes, pipe, cigars, shisha, e-cigarettes", bullet),
Paragraph("• <b>Pack-year = (cigs/day ÷ 20) × years smoked</b>", bullet_bold),
Paragraph(" e.g. 20/day × 30 years = 30 pack-years", small_italic),
Paragraph("• Current smoker or ex-smoker (when stopped?)", bullet),
Paragraph("• Passive/secondhand smoke exposure", bullet),
sp(2),
Paragraph("<b>OCCUPATIONAL EXPOSURE</b>", body_bold),
Paragraph("• Coal mining, gold mining, cotton textile dust", bullet),
Paragraph("• Welding fumes, solvents, agricultural dust", bullet),
Paragraph("• Duration (years), intensity, use of PPE", bullet),
Paragraph("• Ask about ALL past occupations systematically", bullet),
]
rf_right = [
Paragraph("<b>INDOOR / BIOMASS FUEL</b>", body_bold),
Paragraph("• Wood, dung, crop residue burning for cooking/heating", bullet),
Paragraph("• Poorly ventilated kitchens (common in LMICs)", bullet),
sp(2),
Paragraph("<b>CHILDHOOD HISTORY</b>", body_bold),
Paragraph("• Recurrent lower RTIs in childhood", bullet),
Paragraph("• Premature birth (poor lung development)", bullet),
Paragraph("• Severe asthma history", bullet),
sp(2),
Paragraph("<b>ALPHA-1 ANTITRYPSIN (A1AT) DEFICIENCY</b>", body_bold),
Paragraph("• Family history of emphysema in non-smokers", bullet),
Paragraph("• Onset <45 years, lower-lobe predominant emphysema", bullet),
Paragraph("• Associated liver disease (cirrhosis)", bullet),
Paragraph("• All COPD patients should be screened at least once", bullet),
]
rf_two = Table([[rf_left, rf_right]], colWidths=[89*mm, 89*mm])
rf_two.setStyle(TableStyle([
("VALIGN", (0,0), (-1,-1), "TOP"),
("LEFTPADDING", (0,0), (-1,-1), 3),
("RIGHTPADDING", (0,0), (-1,-1), 3),
("TOPPADDING", (0,0), (-1,-1), 2),
("BOTTOMPADDING",(0,0), (-1,-1), 2),
]))
story.append(rf_two)
story.append(sp(2))
# ── PAST MEDICAL HISTORY ──────────────────────────────────────────────────
story.append(section_box("4. PAST MEDICAL HISTORY"))
story.append(sp(1))
pmh_data = [
[Paragraph("Condition", table_hdr), Paragraph("Why It Matters", table_hdr)],
[Paragraph("Asthma / childhood wheeze", table_cell_bold), Paragraph("ACOS (Asthma-COPD Overlap Syndrome)", table_cell)],
[Paragraph("Tuberculosis", table_cell_bold), Paragraph("Can cause airflow obstruction", table_cell)],
[Paragraph("Recurrent chest infections / bronchiectasis", table_cell_bold), Paragraph("Differential; concurrent condition", table_cell)],
[Paragraph("Heart failure / IHD", table_cell_bold), Paragraph("Key comorbidity and differential for dyspnoea", table_cell)],
[Paragraph("Pulmonary hypertension / cor pulmonale", table_cell_bold), Paragraph("Ankle swelling, raised JVP, RVF signs", table_cell)],
[Paragraph("Osteoporosis", table_cell_bold), Paragraph("Common in COPD; worsened by steroids", table_cell)],
[Paragraph("Lung cancer", table_cell_bold), Paragraph("Shared smoking risk factor; haemoptysis", table_cell)],
[Paragraph("Anxiety / depression", table_cell_bold), Paragraph("Very common; impairs QoL, ↑ exacerbation risk", table_cell)],
]
story.append(tbl(pmh_data, [72*mm, 106*mm]))
story.append(sp(2))
# ── DRUG HISTORY ──────────────────────────────────────────────────────────
story.append(section_box("5. DRUG HISTORY", bg=TEAL))
story.append(sp(1))
dh_left = [
Paragraph("<b>INHALERS (ask patient to demonstrate technique)</b>", body_bold),
Paragraph("• SABA — salbutamol, terbutaline", bullet),
Paragraph("• LABA — salmeterol, formoterol, indacaterol", bullet),
Paragraph("• LAMA — tiotropium, umeclidinium, glycopyrronium", bullet),
Paragraph("• ICS — fluticasone, budesonide, beclomethasone", bullet),
Paragraph("• Combinations: LABA/LAMA, LABA/ICS, Triple therapy", bullet),
Paragraph("• Compliance and frequency of use", bullet),
sp(2),
Paragraph("<b>OTHER RESPIRATORY DRUGS</b>", body_bold),
Paragraph("• Theophylline, roflumilast, azithromycin prophylaxis", bullet),
Paragraph("• Oral steroids — dose, duration, side effects", bullet),
Paragraph("• Home nebulisers", bullet),
]
dh_right = [
Paragraph("<b>OXYGEN & NIV</b>", body_bold),
Paragraph("• LTOT: prescribed? Hours/day (goal >15h)?", bullet),
Paragraph("• Portable O₂ vs. concentrator", bullet),
Paragraph("• NIV (BiPAP) — for hypercapnic respiratory failure", bullet),
Paragraph("• Ambulatory oxygen", bullet),
sp(2),
Paragraph("<b>DRUGS THAT WORSEN RESPIRATORY DISEASE</b>", body_bold),
Paragraph("⚠ Beta-blockers — use cardioselective if required", warn),
Paragraph("⚠ NSAIDs — avoid if possible", warn),
Paragraph("⚠ ACE inhibitors — cause cough (may mimic COPD cough)", warn),
sp(2),
Paragraph("<b>ALLERGIES</b>", body_bold),
Paragraph("• Drug name + type of reaction", bullet),
]
dh_two = Table([[dh_left, dh_right]], colWidths=[89*mm, 89*mm])
dh_two.setStyle(TableStyle([
("VALIGN", (0,0), (-1,-1), "TOP"),
("LEFTPADDING", (0,0), (-1,-1), 3),
("RIGHTPADDING", (0,0), (-1,-1), 3),
]))
story.append(dh_two)
story.append(sp(2))
# ── SOCIAL HISTORY + FUNCTIONAL ───────────────────────────────────────────
story.append(section_box("6. SOCIAL & FUNCTIONAL HISTORY", bg=colors.HexColor("#6C3483")))
story.append(sp(1))
soc_left = [
Paragraph("<b>SOCIAL HISTORY</b>", body_bold),
Paragraph("• Smoking (if not already asked)", bullet),
Paragraph("• Alcohol intake", bullet),
Paragraph("• Current / past occupation (exposure history)", bullet),
Paragraph("• Housing — stairs, heating, dampness/mould", bullet),
Paragraph("• Social support — lives alone? Who are the carers?", bullet),
Paragraph("• Employment impact / disability benefits", bullet),
Paragraph("• Air travel — needs oxygen assessment if PaO₂ borderline", bullet),
]
soc_right = [
Paragraph("<b>FUNCTIONAL IMPACT (QoL)</b>", body_bold),
Paragraph("• ADLs — can patient shower, dress, cook independently?", bullet),
Paragraph("• Maximum walking distance", bullet),
Paragraph("• Mobility aids (rollator, wheelchair)", bullet),
Paragraph("• Hobbies, work, social participation", bullet),
sp(2),
Paragraph("<b>CAT SCORE DOMAINS (0–40)</b>", body_bold),
Paragraph("Cough | Sputum | Chest tightness | Breathlessness | Activity at home | Confidence leaving home | Sleep | Energy", small),
Paragraph("Score ≥10 = significant impact on QoL", small_italic),
]
soc_two = Table([[soc_left, soc_right]], colWidths=[89*mm, 89*mm])
soc_two.setStyle(TableStyle([
("VALIGN", (0,0), (-1,-1), "TOP"),
("LEFTPADDING", (0,0), (-1,-1), 3),
("RIGHTPADDING", (0,0), (-1,-1), 3),
]))
story.append(soc_two)
story.append(sp(2))
# ── FAMILY HISTORY + SYSTEMS ──────────────────────────────────────────────
fam_sys_left = [
section_box("7. FAMILY HISTORY", bg=colors.HexColor("#1E8449")),
sp(1),
Paragraph("• COPD or emphysema — especially early-onset / non-smokers", bullet),
Paragraph(" → Suspect <b>A1AT deficiency</b>", bullet),
Paragraph("• Asthma (first-degree relatives)", bullet),
Paragraph("• Lung cancer", bullet),
Paragraph("• Maternal tobacco use during pregnancy", bullet),
]
fam_sys_right = [
section_box("8. SYSTEMS REVIEW", bg=colors.HexColor("#1E8449")),
sp(1),
Paragraph("• <b>CVS:</b> Ankle oedema (cor pulmonale), palpitations (AF), chest pain", bullet),
Paragraph("• <b>Neuro:</b> Morning headaches, confusion (CO₂ retention)", bullet),
Paragraph("• <b>MSK:</b> Back pain (vertebral fractures / steroids), muscle weakness", bullet),
Paragraph("• <b>Nutrition:</b> Weight loss, anorexia (sarcopenia in emphysema)", bullet),
Paragraph("• <b>Psych:</b> Depression, anxiety (very common in COPD)", bullet),
Paragraph("• <b>ENT:</b> Chronic sinusitis, nasal polyps (asthma overlap)", bullet),
Paragraph("• <b>Sleep:</b> Snoring / OSA (obesity-hypoventilation overlap)", bullet),
]
fam_sys = Table([[fam_sys_left, fam_sys_right]], colWidths=[89*mm, 89*mm])
fam_sys.setStyle(TableStyle([
("VALIGN", (0,0), (-1,-1), "TOP"),
("LEFTPADDING", (0,0), (-1,-1), 0),
("RIGHTPADDING", (0,0), (-1,-1), 3),
("TOPPADDING", (0,0), (-1,-1), 0),
("BOTTOMPADDING",(0,0), (-1,-1), 0),
]))
story.append(fam_sys)
story.append(sp(3))
# ── DIFFERENTIALS ─────────────────────────────────────────────────────────
story.append(section_box("9. KEY DIFFERENTIALS TO EXCLUDE IN HISTORY", bg=RED))
story.append(sp(1))
diff_data = [
[Paragraph("Condition", table_hdr), Paragraph("Distinguishing History Features", table_hdr)],
[Paragraph("Asthma", table_cell_bold), Paragraph("Young onset, episodic wheeze, atopy, family history, fully reversible, responds well to ICS", table_cell)],
[Paragraph("Heart Failure", table_cell_bold), Paragraph("Orthopnoea, PND, pink frothy sputum, cardiac risk factors, bilateral ankle oedema", table_cell)],
[Paragraph("Bronchiectasis", table_cell_bold), Paragraph("Large volumes of mucopurulent sputum daily, recurrent infections, childhood lung disease", table_cell)],
[Paragraph("Tuberculosis", table_cell_bold), Paragraph("Night sweats, weight loss, haemoptysis, contact history, foreign travel/endemic area", table_cell)],
[Paragraph("Lung Cancer", table_cell_bold), Paragraph("Haemoptysis, significant weight loss, hoarseness, new finger clubbing, heavy smoker", table_cell)],
[Paragraph("Pulmonary Fibrosis", table_cell_bold), Paragraph("Dry cough, clubbing, fine velcro crackles, autoimmune disease, occupational exposure (birds)", table_cell)],
]
story.append(tbl(diff_data, [38*mm, 140*mm], bg_header=RED))
story.append(sp(3))
# ── GOLD STAGING REMINDER ─────────────────────────────────────────────────
story.append(section_box("10. GOLD STAGING REMINDER (Confirm with Spirometry)", bg=ORANGE))
story.append(sp(1))
gold_left = [
Paragraph("<b>GOLD SPIROMETRIC GRADES</b>", body_bold),
Paragraph("(Post-bronchodilator FEV₁/FVC <0.7)", small),
sp(1),
]
gold_grade_data = [
[Paragraph("Grade", table_hdr), Paragraph("Severity", table_hdr), Paragraph("FEV₁ % Predicted", table_hdr)],
[Paragraph("1", table_cell), Paragraph("Mild", table_cell), Paragraph("≥ 80%", table_cell)],
[Paragraph("2", table_cell), Paragraph("Moderate", table_cell), Paragraph("50–79%", table_cell)],
[Paragraph("3", table_cell), Paragraph("Severe", table_cell), Paragraph("30–49%", table_cell)],
[Paragraph("4", table_cell), Paragraph("Very Severe", table_cell), Paragraph("< 30%", table_cell)],
]
gold_left.append(tbl(gold_grade_data, [15*mm, 30*mm, 40*mm], bg_header=ORANGE))
gold_right = [
Paragraph("<b>GOLD ABE GROUPS (2023)</b>", body_bold),
Paragraph("(Symptoms + Exacerbation Risk)", small),
sp(1),
]
gold_grp_data = [
[Paragraph("Group", table_hdr), Paragraph("Criteria", table_hdr)],
[Paragraph("A", table_cell), Paragraph("0–1 moderate exacerbations, no hospitalisation; low symptoms (CAT <10)", table_cell)],
[Paragraph("B", table_cell), Paragraph("0–1 moderate exacerbations, no hospitalisation; high symptoms (CAT ≥10)", table_cell)],
[Paragraph("E", table_cell), Paragraph("≥2 moderate exacerbations OR ≥1 hospitalisation (regardless of symptoms)", table_cell)],
]
gold_right.append(tbl(gold_grp_data, [12*mm, 75*mm], bg_header=ORANGE))
gold_two = Table([[gold_left, gold_right]], colWidths=[89*mm, 89*mm])
gold_two.setStyle(TableStyle([
("VALIGN", (0,0), (-1,-1), "TOP"),
("LEFTPADDING", (0,0), (-1,-1), 3),
("RIGHTPADDING", (0,0), (-1,-1), 3),
]))
story.append(gold_two)
story.append(sp(3))
# ── CHECKLIST ─────────────────────────────────────────────────────────────
story.append(section_box("QUICK CHECKLIST", bg=colors.HexColor("#2C3E50")))
story.append(sp(1))
checks = [
("Presenting symptoms", "Dyspnoea, cough, sputum, wheeze — onset, severity, progression"),
("MRC Grade", "Quantify exertional breathlessness (1–5)"),
("Exacerbation history", "Frequency, hospitalisations, NIV, rescue packs"),
("Smoking", "Pack-year history, current vs. ex-smoker"),
("Occupational / indoor / environmental exposure", "All jobs, biomass fuels, PPE"),
("Childhood history", "Recurrent RTIs, premature birth"),
("Family history", "A1AT, asthma, lung disease, maternal smoking"),
("Past medical history", "Cardiac disease, asthma, TB, depression"),
("Drug history", "Inhalers with technique, oxygen, steroids, harmful drugs"),
("Functional impact / QoL", "ADLs, walking distance, CAT score"),
("Social history", "Housing, support, employment, travel"),
("Systems review", "Cor pulmonale, CO₂ retention, weight loss, mood"),
("Differentials excluded", "Asthma, HF, bronchiectasis, TB, lung cancer, PF"),
]
check_data = [[
Paragraph("✓", S("chk", fontName="Helvetica-Bold", fontSize=9,
textColor=GREEN, alignment=TA_CENTER, leading=11)),
Paragraph(f"<b>{c[0]}</b>", table_cell_bold),
Paragraph(c[1], table_cell),
] for c in checks]
check_data.insert(0, [
Paragraph("", table_hdr),
Paragraph("Domain", table_hdr),
Paragraph("Key Points", table_hdr),
])
chk_tbl = Table(check_data, colWidths=[7*mm, 55*mm, 116*mm])
chk_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), colors.HexColor("#2C3E50")),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 8),
("ROWBACKGROUNDS",(0,1), (-1,-1), [LIGHTGREEN, WHITE]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#D5D8DC")),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("ALIGN", (0,0), (-1,-1), "LEFT"),
]))
story.append(chk_tbl)
story.append(sp(3))
# ── FOOTER ────────────────────────────────────────────────────────────────
footer_data = [[
Paragraph(
"<i>Sources: Goldman-Cecil Medicine | Washington Manual of Medical Therapeutics | "
"Harrison's Principles of Internal Medicine 22E | Fishman's Pulmonary Diseases & Disorders | "
"GOLD 2023 Guidelines</i>",
S("ftr", fontName="Helvetica-Oblique", fontSize=7, textColor=DARKGREY,
alignment=TA_CENTER, leading=10)
)
]]
footer = Table(footer_data, colWidths=[178*mm])
footer.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), GREY),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 6),
]))
story.append(footer)
doc.build(story)
print(f"PDF created: {OUTPUT}")
build()
cd /home/daytona/workspace/copd-pdf && python generate_copd_pdf.py 2>&1
ls -lh /home/daytona/workspace/copd-pdf/COPD_History_Quick_Reference.pdf
COPD History Quick Reference
PDF Document · PDF
| Section | Contents |
|---|---|
| 1. HPC | Dyspnoea (MRC scale table), cough, sputum, wheeze, haemoptysis warning |
| 2. Exacerbation History | Frequency, triggers, severity, hospitalisations, NIV/intubation |
| 3. Risk Factors | Pack-year formula, occupational exposure, biomass fuel, A1AT deficiency |
| 4. Past Medical History | Key comorbidities and why each matters |
| 5. Drug History | Inhaler classes, O₂/NIV, harmful drugs (beta-blockers, NSAIDs, ACEi) |
| 6. Social & Functional | ADLs, CAT score domains, housing, support |
| 7–8. Family & Systems Review | A1AT flags, cor pulmonale, CO₂ retention, depression |
| 9. Differentials | Asthma, HF, bronchiectasis, TB, lung cancer, PF with distinguishing features |
| 10. GOLD Staging | GOLD 1–4 (FEV₁) + ABE groups (2023) |
| Checklist | 13-point visual checklist for the exam |
How will i exclude cor pulmonale
| Symptom | How to Ask |
|---|---|
| Ankle swelling | "Have you noticed swelling of your ankles or legs?" "Is it worse at the end of the day?" |
| Progressive dyspnoea | Disproportionate breathlessness beyond what the COPD severity would explain |
| Fatigue / exercise intolerance | Low-output RV failure causes profound fatigue |
| Presyncope / syncope | From reduced cardiac output; suggests severe PH |
| Abdominal distension / discomfort | Hepatic congestion from elevated right atrial pressure |
| Anorexia / nausea | Gut congestion |
| Palpitations | AF and supraventricular arrhythmias are common (right atrial enlargement + hypoxaemia + bronchodilators) |
| Test | Cor Pulmonale Finding |
|---|---|
| SpO₂ / ABG | PaO₂ <8 kPa (60 mmHg), PaCO₂ ↑ (late), respiratory acidosis |
| ECG | Right axis deviation, P pulmonale (tall peaked P in II >2.5 mm), RVH (dominant R in V1, deep S in V5/V6), RBBB, S₁Q₃T₃ pattern |
| Test | Finding |
|---|---|
| FBC | Polycythaemia (Hb ↑) — compensatory response to chronic hypoxia |
| U&E | May show diuretic effects; hyponatraemia in severe failure |
| BNP / NT-proBNP | Elevated in RV failure |
| LFTs | Raised in hepatic congestion (↑ ALP, bilirubin) |
| Venous bicarbonate | ↑ suggests chronic CO₂ retention |
| Modality | Finding |
|---|---|
| Chest X-ray | Prominent pulmonary arteries (>16 mm right descending PA), enlarged hilar vessels, RV enlargement (obliteration of retrosternal space on lateral), peripheral pruning of vessels |
| ECG-gated CXR (PA) | Cardiomegaly with RV dominance |
| Echocardiogram (Key investigation) | RV enlargement + hypertrophy, elevated tricuspid regurgitant jet velocity (TRJV >2.8 m/s suggests PH), septal flattening/D-shaped LV in systole, estimated RVSP >35 mmHg |
| Cardiac MRI | Gold standard for RV volume/function; used when echo is inconclusive |
History: Ankle oedema, worsening dyspnoea, syncope, abdominal distension
↓
Examination: Elevated JVP, parasternal heave, loud P₂, TR murmur,
hepatomegaly, pitting oedema
↓
ECG: Right axis deviation, P pulmonale, RVH pattern
↓
CXR: Prominent pulmonary arteries, RV enlargement
↓
Echo: RV hypertrophy, TRJV, estimated RVSP
↓
ABG: Confirm hypoxia/hypercapnia (the primary driver)
↓
RHC (if needed): mPAP ≥20–25 mmHg = confirmed
Can u make reference pdf of history taking of hepatitis, CKD
~/copd-pdf/generate_hep_ckd_pdf.py
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import mm
from reportlab.lib.styles import ParagraphStyle
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, PageBreak
)
from reportlab.lib.enums import TA_CENTER, TA_LEFT
OUTPUT = "/home/daytona/workspace/copd-pdf/Hepatitis_CKD_History_Quick_Reference.pdf"
# ── Palette ──────────────────────────────────────────────────────────────────
NAVY = colors.HexColor("#1A3A5C")
TEAL = colors.HexColor("#117A65")
AMBER = colors.HexColor("#B7770D")
RED = colors.HexColor("#922B21")
PURPLE = colors.HexColor("#6C3483")
BLUE2 = colors.HexColor("#1A5276")
GREEN = colors.HexColor("#1E8449")
DARKGREY = colors.HexColor("#566573")
GREY = colors.HexColor("#F2F3F4")
LIGHTGREY = colors.HexColor("#FDFEFE")
MIDGREY = colors.HexColor("#D5D8DC")
WHITE = colors.white
BLACK = colors.HexColor("#1C2833")
LIGHTYELLOW = colors.HexColor("#FEF9E7")
LIGHTBLUE = colors.HexColor("#EAF2FF")
LIGHTRED = colors.HexColor("#FDEDEC")
LIGHTGREEN= colors.HexColor("#E9F7EF")
PW = 178 * mm # usable page width
# ── Style factory ────────────────────────────────────────────────────────────
def S(name, **kw):
return ParagraphStyle(name, **kw)
title_s = S("T", fontName="Helvetica-Bold", fontSize=18, textColor=WHITE, alignment=TA_CENTER, leading=22)
sub_s = S("Su", fontName="Helvetica", fontSize=9, textColor=colors.HexColor("#AED6F1"), alignment=TA_CENTER, leading=12)
sechdr_s = S("SH", fontName="Helvetica-Bold", fontSize=9.5,textColor=WHITE, alignment=TA_LEFT, leading=13)
body_s = S("B", fontName="Helvetica", fontSize=8.5,textColor=BLACK, leading=12, spaceAfter=2)
bold_s = S("BB", fontName="Helvetica-Bold", fontSize=8.5,textColor=BLACK, leading=12, spaceAfter=2)
bul_s = S("Bu", fontName="Helvetica", fontSize=8.5,textColor=BLACK, leading=12, leftIndent=10, firstLineIndent=-8, spaceAfter=1.5)
buld_s = S("Bd", fontName="Helvetica-Bold", fontSize=8.5,textColor=NAVY, leading=12, leftIndent=10, firstLineIndent=-8, spaceAfter=1.5)
warn_s = S("W", fontName="Helvetica-BoldOblique", fontSize=8.5, textColor=RED, leading=12, leftIndent=8, spaceAfter=2)
tip_s = S("Ti", fontName="Helvetica-Oblique", fontSize=8, textColor=TEAL, leading=11, leftIndent=8, spaceAfter=2)
small_s = S("Sm", fontName="Helvetica", fontSize=7.5,textColor=DARKGREY, leading=10, spaceAfter=1)
smit_s = S("Si", fontName="Helvetica-Oblique", fontSize=7.5,textColor=DARKGREY, leading=10, spaceAfter=1)
th_s = S("Th", fontName="Helvetica-Bold", fontSize=8, textColor=WHITE, alignment=TA_CENTER, leading=11)
tc_s = S("Tc", fontName="Helvetica", fontSize=8, textColor=BLACK, leading=11)
tcb_s = S("Tcb",fontName="Helvetica-Bold", fontSize=8, textColor=BLACK, leading=11)
ftr_s = S("Ft", fontName="Helvetica-Oblique", fontSize=7, textColor=DARKGREY, alignment=TA_CENTER, leading=10)
# ── Helpers ───────────────────────────────────────────────────────────────────
def sp(h=3):
return Spacer(1, h*mm)
def sec(title, bg=NAVY):
d = [[Paragraph(f"▌ {title}", sechdr_s)]]
t = Table(d, colWidths=[PW])
t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), bg),
("TOPPADDING", (0,0),(-1,-1), 4),
("BOTTOMPADDING", (0,0),(-1,-1), 4),
("LEFTPADDING", (0,0),(-1,-1), 6),
("RIGHTPADDING", (0,0),(-1,-1), 4),
]))
return t
def tbl(data, cw, bg=NAVY, extra=None):
ts = [
("BACKGROUND", (0,0),(-1,0), bg),
("TEXTCOLOR", (0,0),(-1,0), WHITE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0),(-1,-1), 8),
("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, GREY]),
("GRID", (0,0),(-1,-1), 0.4, MIDGREY),
("TOPPADDING", (0,0),(-1,-1), 3),
("BOTTOMPADDING", (0,0),(-1,-1), 3),
("LEFTPADDING", (0,0),(-1,-1), 5),
("RIGHTPADDING", (0,0),(-1,-1), 5),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
("ALIGN", (0,0),(-1,0), "CENTER"),
]
if extra:
ts.extend(extra)
t = Table(data, colWidths=cw)
t.setStyle(TableStyle(ts))
return t
def two_col(left_items, right_items, lw=89, rw=89):
t = Table([[left_items, right_items]], colWidths=[lw*mm, rw*mm])
t.setStyle(TableStyle([
("VALIGN", (0,0),(-1,-1), "TOP"),
("LEFTPADDING", (0,0),(-1,-1), 3),
("RIGHTPADDING", (0,0),(-1,-1), 3),
("TOPPADDING", (0,0),(-1,-1), 2),
("BOTTOMPADDING", (0,0),(-1,-1), 2),
]))
return t
def banner(main, sub, bg):
t = Table([[Paragraph(main, title_s)], [Paragraph(sub, sub_s)]], colWidths=[PW])
t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), bg),
("TOPPADDING", (0,0),(-1,-1), 8),
("BOTTOMPADDING", (0,0),(-1,-1), 8),
("LEFTPADDING", (0,0),(-1,-1), 6),
]))
return t
def checklist_table(rows, bg_hdr=colors.HexColor("#2C3E50"), row_colors=None):
data = [[Paragraph("✓", S("c", fontName="Helvetica-Bold", fontSize=9, textColor=GREEN, alignment=TA_CENTER, leading=11)),
Paragraph("Domain", th_s),
Paragraph("Key Points", th_s)]]
for r in rows:
data.append([
Paragraph("□", S("cb", fontName="Helvetica-Bold", fontSize=9, textColor=DARKGREY, alignment=TA_CENTER, leading=11)),
Paragraph(f"<b>{r[0]}</b>", tcb_s),
Paragraph(r[1], tc_s),
])
rc = row_colors or [LIGHTGREEN, WHITE]
t = Table(data, colWidths=[7*mm, 55*mm, 116*mm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), bg_hdr),
("TEXTCOLOR", (0,0),(-1,0), WHITE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0),(-1,-1), 8),
("ROWBACKGROUNDS",(0,1),(-1,-1), rc),
("GRID", (0,0),(-1,-1), 0.4, MIDGREY),
("TOPPADDING", (0,0),(-1,-1), 3),
("BOTTOMPADDING", (0,0),(-1,-1), 3),
("LEFTPADDING", (0,0),(-1,-1), 5),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
]))
return t
# ════════════════════════════════════════════════════════════════════════════
# BUILD
# ════════════════════════════════════════════════════════════════════════════
def build():
doc = SimpleDocTemplate(
OUTPUT, pagesize=A4,
leftMargin=16*mm, rightMargin=16*mm,
topMargin=14*mm, bottomMargin=14*mm,
title="Hepatitis & CKD History Quick Reference",
author="Orris Medical"
)
story = []
# ════════════════════════════════════════════════════════════════════════
# PAGE 1 — HEPATITIS
# ════════════════════════════════════════════════════════════════════════
story.append(banner(
"HEPATITIS — HISTORY TAKING",
"Quick Reference — Long Case | Acute & Chronic Hepatitis (A/B/C/D/E + Autoimmune + Alcoholic)",
colors.HexColor("#6E2C00")
))
story.append(sp(2))
# ── 1. Presenting Complaint ──────────────────────────────────────────────
story.append(sec("1. PRESENTING COMPLAINT", bg=colors.HexColor("#6E2C00")))
story.append(sp(1))
story.append(Paragraph(
"Common presenting symptoms: <b>jaundice</b>, fatigue, right-upper-quadrant (RUQ) pain, "
"nausea/vomiting, anorexia, dark urine, pale stools, pruritus, abdominal distension. "
"Many patients are <b>asymptomatic</b> and diagnosed incidentally on LFTs.",
body_s))
story.append(sp(2))
# ── 2. HPC ───────────────────────────────────────────────────────────────
story.append(sec("2. HISTORY OF PRESENTING COMPLAINT", bg=colors.HexColor("#873600")))
story.append(sp(1))
hpc_left = [
Paragraph("<b>JAUNDICE</b>", bold_s),
Paragraph("• Onset — sudden (acute hepatitis) vs. gradual (chronic/cirrhosis)", bul_s),
Paragraph("• Duration and progression", bul_s),
Paragraph("• Fluctuating (haemolytic/Gilbert's) vs. persistent", bul_s),
Paragraph("• Associated dark urine + pale stools (cholestatic pattern)", bul_s),
Paragraph("• Pruritus — suggests cholestasis (biliary obstruction or PBC)", bul_s),
sp(2),
Paragraph("<b>PAIN</b>", bold_s),
Paragraph("• RUQ/epigastric — dull ache = hepatitis; sharp/colicky = biliary", bul_s),
Paragraph("• Onset, radiation (to right shoulder = biliary)", bul_s),
Paragraph("• Relation to food (biliary colic)", bul_s),
sp(2),
Paragraph("<b>SYSTEMIC SYMPTOMS</b>", bold_s),
Paragraph("• Fatigue, malaise (often presenting complaint in chronic hepatitis)", bul_s),
Paragraph("• Anorexia, nausea, vomiting, weight loss", bul_s),
Paragraph("• Fever, arthralgia, rash — prodrome of Hep A/B", bul_s),
Paragraph("• Low-grade fever vs. rigors (suggests cholangitis)", bul_s),
]
hpc_right = [
Paragraph("<b>COMPLICATIONS / ADVANCED DISEASE</b>", bold_s),
Paragraph("• Abdominal distension — ascites (portal hypertension / liver failure)", bul_s),
Paragraph("• Haematemesis / melaena — oesophageal varices", bul_s),
Paragraph("• Easy bruising / prolonged bleeding — coagulopathy", bul_s),
Paragraph("• Confusion / drowsiness / sleep inversion — hepatic encephalopathy", bul_s),
Paragraph("• Ankle swelling — hypoalbuminaemia or portal HTN", bul_s),
sp(2),
Paragraph("<b>SPECIFIC TO ACUTE HEPATITIS</b>", bold_s),
Paragraph("• Pre-icteric phase: flu-like illness 1–2 weeks before jaundice", bul_s),
Paragraph("• Icteric phase: jaundice, dark urine, pale stools, RUQ discomfort", bul_s),
Paragraph("• Resolution vs. fulminant hepatic failure (encephalopathy, coagulopathy)", bul_s),
sp(2),
Paragraph("<b>SPECIFIC TO CHRONIC HEPATITIS</b>", bold_s),
Paragraph("• Insidious fatigue, vague RUQ discomfort for months–years", bul_s),
Paragraph("• Features of cirrhosis: gynecomastia, testicular atrophy, spider naevi", bul_s),
Paragraph("• Hepatocellular carcinoma screen: weight loss, worsening RUQ pain", bul_s),
]
story.append(two_col(hpc_left, hpc_right))
story.append(sp(2))
# ── 3. Risk Factors / Aetiology ──────────────────────────────────────────
story.append(sec("3. RISK FACTOR HISTORY — AETIOLOGY", bg=AMBER))
story.append(sp(1))
rf_data = [
[Paragraph("Type", th_s), Paragraph("Route", th_s), Paragraph("Key Risk Factors to Ask", th_s)],
[Paragraph("Hep A", tcb_s), Paragraph("Faeco-oral", tc_s),
Paragraph("Travel to endemic areas, contaminated food/water, raw seafood, poor sanitation", tc_s)],
[Paragraph("Hep B", tcb_s), Paragraph("Parenteral / sexual / vertical", tc_s),
Paragraph("IV drug use (shared needles), unprotected sex, multiple partners, blood transfusion pre-1990s, tattoos/piercings, healthcare worker, born to HBsAg+ mother, needlestick", tc_s)],
[Paragraph("Hep C", tcb_s), Paragraph("Parenteral (mainly)", tc_s),
Paragraph("IV drug use (most common), blood transfusion pre-1992, haemodialysis, tattoos, needlestick, sexual contact (lower risk)", tc_s)],
[Paragraph("Hep D", tcb_s), Paragraph("Parenteral (requires HBV)", tc_s),
Paragraph("Co-infection or superinfection with HBV; same risk factors as Hep B", tc_s)],
[Paragraph("Hep E", tcb_s), Paragraph("Faeco-oral", tc_s),
Paragraph("Travel to South/East Asia, Central America, Africa; undercooked pork; immunosuppressed patients (chronic HEV)", tc_s)],
[Paragraph("Alcoholic", tcb_s), Paragraph("Toxin", tc_s),
Paragraph("Alcohol intake: units/week, duration, type; CAGE/AUDIT score; binge pattern", tc_s)],
[Paragraph("Autoimmune", tcb_s), Paragraph("Autoimmune", tc_s),
Paragraph("Female sex, personal/family history of autoimmune disease (thyroid, IBD, T1DM, SLE)", tc_s)],
[Paragraph("NASH/MASH", tcb_s), Paragraph("Metabolic", tc_s),
Paragraph("Obesity, T2DM, hyperlipidaemia, metabolic syndrome, rapid weight loss, TPN", tc_s)],
[Paragraph("Drug-induced", tcb_s), Paragraph("Hepatotoxin", tc_s),
Paragraph("All drugs incl. OTC, herbal/supplements, paracetamol dose, isoniazid, methotrexate, statins, antiepileptics, antiretrovirals", tc_s)],
[Paragraph("Genetic", tcb_s), Paragraph("Inherited", tc_s),
Paragraph("Haemochromatosis (Irish/Northern European, joint pain, diabetes, skin bronzing), Wilson's disease (young patient, neuropsychiatric), A1AT deficiency", tc_s)],
]
story.append(tbl(rf_data, [16*mm, 40*mm, 122*mm], bg=AMBER))
story.append(sp(1))
story.append(Paragraph(
"⚠ Always ask: <b>alcohol history</b> (quantify in units/week), <b>full drug history including herbals</b>, "
"<b>sexual history</b>, <b>IV drug use</b> (non-judgmentally), <b>travel history</b>, <b>tattoos/piercings</b>, "
"<b>blood products received</b> (when, where).",
warn_s))
story.append(sp(2))
# ── 4. Past Medical History ──────────────────────────────────────────────
story.append(sec("4. PAST MEDICAL HISTORY", bg=BLUE2))
story.append(sp(1))
pmh_left = [
Paragraph("<b>Liver disease history</b>", bold_s),
Paragraph("• Previous jaundice (post-op, in pregnancy, childhood)", bul_s),
Paragraph("• Prior hepatitis diagnosis — acute or chronic", bul_s),
Paragraph("• Cirrhosis, portal hypertension, varices, ascites", bul_s),
Paragraph("• Liver biopsy — when, result?", bul_s),
Paragraph("• Hepatocellular carcinoma", bul_s),
sp(2),
Paragraph("<b>Metabolic / systemic</b>", bold_s),
Paragraph("• Diabetes mellitus, obesity, hyperlipidaemia (NASH risk)", bul_s),
Paragraph("• Autoimmune conditions (AIH, IBD, thyroid disease)", bul_s),
Paragraph("• Coeliac disease (abnormal LFTs)", bul_s),
]
pmh_right = [
Paragraph("<b>Surgical / procedural history</b>", bold_s),
Paragraph("• Cholecystectomy, biliary surgery (biliary stricture)", bul_s),
Paragraph("• Blood transfusions — pre-1992 (HCV risk)", bul_s),
Paragraph("• Organ transplant (immunosuppression → chronic HBV/HCV)", bul_s),
Paragraph("• Haemodialysis history (HCV risk)", bul_s),
sp(2),
Paragraph("<b>HIV status</b>", bold_s),
Paragraph("• HIV co-infection accelerates HBV/HCV progression to cirrhosis", bul_s),
Paragraph("• Antiretroviral therapy can cause hepatotoxicity", bul_s),
]
story.append(two_col(pmh_left, pmh_right))
story.append(sp(2))
# ── 5. Drug History ──────────────────────────────────────────────────────
story.append(sec("5. DRUG HISTORY", bg=PURPLE))
story.append(sp(1))
story.append(Paragraph(
"List <b>all medications</b> — prescribed, OTC, herbal, and illicit. Ask about dose and duration. "
"Common hepatotoxic agents include:",
body_s))
drug_data = [
[Paragraph("Category", th_s), Paragraph("Examples", th_s), Paragraph("Pattern", th_s)],
[Paragraph("Analgesics", tc_s), Paragraph("Paracetamol (↑ dose), NSAIDs", tc_s), Paragraph("Hepatocellular", tc_s)],
[Paragraph("Antibiotics", tc_s), Paragraph("Flucloxacillin, co-amoxiclav, isoniazid, nitrofurantoin", tc_s), Paragraph("Hepatocellular / cholestatic", tc_s)],
[Paragraph("Statins", tc_s), Paragraph("All statins", tc_s), Paragraph("Hepatocellular (usually mild)", tc_s)],
[Paragraph("Antiepileptics", tc_s), Paragraph("Phenytoin, sodium valproate, carbamazepine", tc_s), Paragraph("Hepatocellular", tc_s)],
[Paragraph("Chemotherapy", tc_s), Paragraph("Methotrexate, azathioprine", tc_s), Paragraph("Fibrosis / hepatocellular", tc_s)],
[Paragraph("Herbal/supplements", tc_s), Paragraph("Kava, comfrey, green tea extract", tc_s), Paragraph("Variable — often underreported", tc_s)],
[Paragraph("Alcohol", tc_s), Paragraph("Ethanol", tc_s), Paragraph("Steatosis → hepatitis → cirrhosis", tc_s)],
]
story.append(tbl(drug_data, [30*mm, 74*mm, 74*mm], bg=PURPLE))
story.append(sp(2))
# ── 6. Social, Family, Systems ───────────────────────────────────────────
soc_fam_left = [
sec("6. SOCIAL HISTORY", bg=TEAL),
sp(1),
Paragraph("• <b>Alcohol</b> — units/week, years, type; CAGE/AUDIT score", bul_s),
Paragraph("• <b>IV drug use</b> — past or present, sharing needles", bul_s),
Paragraph("• <b>Sexual history</b> — partners, unprotected intercourse, MSM", bul_s),
Paragraph("• <b>Travel</b> — endemic regions for Hep A/E (South Asia, Africa)", bul_s),
Paragraph("• <b>Tattoos/piercings</b> — where, sterile technique?", bul_s),
Paragraph("• <b>Occupation</b> — healthcare worker (needlestick risk)", bul_s),
Paragraph("• <b>Immigration background</b> — HBV endemic countries (SE Asia, Sub-Saharan Africa)", bul_s),
Paragraph("• <b>Household contacts</b> — HBV/HCV infected family members?", bul_s),
Paragraph("• <b>Vaccination history</b> — Hep A / Hep B vaccinated?", bul_s),
]
soc_fam_right = [
sec("7. FAMILY HISTORY", bg=TEAL),
sp(1),
Paragraph("• Liver disease, cirrhosis, liver cancer", bul_s),
Paragraph("• <b>Haemochromatosis</b> — Northern European ancestry; joint/cardiac disease", bul_s),
Paragraph("• <b>Wilson's disease</b> — young patient, neurological symptoms", bul_s),
Paragraph("• <b>A1AT deficiency</b> — emphysema + liver disease", bul_s),
Paragraph("• Autoimmune diseases in family (AIH risk)", bul_s),
sp(1),
sec("8. SYSTEMS REVIEW", bg=GREEN),
sp(1),
Paragraph("• <b>GI:</b> Abdominal pain, change in bowel habit, melaena/haematemesis", bul_s),
Paragraph("• <b>Neuro:</b> Confusion, personality change, sleep inversion → encephalopathy", bul_s),
Paragraph("• <b>MSK:</b> Joint pains (Hep B prodrome, haemochromatosis)", bul_s),
Paragraph("• <b>Skin:</b> Jaundice, spider naevi, palmar erythema, leuconychia, purpura", bul_s),
Paragraph("• <b>Endocrine:</b> Gynaecomastia, loss of body hair, menstrual irregularity", bul_s),
Paragraph("• <b>Renal:</b> Oedema (hypoalbuminaemia), hepatorenal syndrome", bul_s),
]
story.append(two_col(soc_fam_left, soc_fam_right, lw=88, rw=90))
story.append(sp(2))
# ── Differentials ─────────────────────────────────────────────────────────
story.append(sec("9. KEY DIFFERENTIALS TO EXCLUDE", bg=RED))
story.append(sp(1))
diff_data = [
[Paragraph("Diagnosis", th_s), Paragraph("Distinguishing History Features", th_s)],
[Paragraph("Biliary obstruction (stone/cancer)", tcb_s), Paragraph("Colicky RUQ pain radiating to shoulder, fluctuating jaundice, pale stools/dark urine, itching, weight loss (cancer)", tc_s)],
[Paragraph("Alcoholic hepatitis", tcb_s), Paragraph("Heavy alcohol intake, recent binge, fever, tender hepatomegaly, coagulopathy", tc_s)],
[Paragraph("Non-alcoholic steatohepatitis", tcb_s), Paragraph("Obesity, T2DM, metabolic syndrome, no/minimal alcohol, incidental LFT rise", tc_s)],
[Paragraph("Haemolytic jaundice", tcb_s), Paragraph("Family history, anaemia, dark urine without pale stools, fluctuating, no hepatic symptoms", tc_s)],
[Paragraph("Hepatocellular carcinoma", tcb_s), Paragraph("Background cirrhosis, weight loss, worsening ascites, ↑ AFP, RUQ mass", tc_s)],
[Paragraph("Primary biliary cholangitis", tcb_s), Paragraph("Middle-aged woman, severe pruritus, fatigue, autoimmune disease, AMA positive", tc_s)],
]
story.append(tbl(diff_data, [50*mm, 128*mm], bg=RED))
story.append(sp(2))
# ── Checklist ─────────────────────────────────────────────────────────────
story.append(sec("HEPATITIS HISTORY CHECKLIST", bg=colors.HexColor("#2C3E50")))
story.append(sp(1))
hep_checks = [
("Presenting symptom", "Jaundice, fatigue, RUQ pain, dark urine, pale stools, pruritus"),
("Onset & course", "Acute vs. chronic; complications (encephalopathy, variceal bleed, ascites)"),
("Viral risk factors", "IV drug use, sexual history, blood products, tattoos, travel, needlestick"),
("Alcohol history", "Units/week, years drinking, CAGE/AUDIT score"),
("Drug & herbal history", "All medications including OTC, herbal, supplements — dose & duration"),
("Metabolic risk", "Obesity, T2DM, hyperlipidaemia, metabolic syndrome (NASH)"),
("Autoimmune screen", "Personal/family autoimmune disease history"),
("Genetic causes", "Family history of haemochromatosis, Wilson's, A1AT"),
("Past medical history", "Previous jaundice, liver disease, biliary surgery, HIV, dialysis"),
("Family history", "Liver disease, genetic disorders, HBV/HCV in household"),
("Vaccination history", "Hep A and B vaccination status"),
("Systems review", "Encephalopathy, GI bleeding, skin signs, renal, musculoskeletal"),
("Differentials excluded", "Biliary obstruction, haemolysis, HCC, PBC, alcoholic hepatitis"),
]
story.append(checklist_table(hep_checks, bg_hdr=colors.HexColor("#6E2C00"), row_colors=[LIGHTYELLOW, WHITE]))
story.append(sp(2))
# ════════════════════════════════════════════════════════════════════════
# PAGE BREAK → CKD
# ════════════════════════════════════════════════════════════════════════
story.append(PageBreak())
story.append(banner(
"CHRONIC KIDNEY DISEASE (CKD) — HISTORY TAKING",
"Quick Reference — Long Case | CKD Stages 1–5 Including ESRD / Renal Replacement Therapy",
colors.HexColor("#154360")
))
story.append(sp(2))
# ── 1. Presenting Complaint ───────────────────────────────────────────────
story.append(sec("1. PRESENTING COMPLAINT", bg=colors.HexColor("#154360")))
story.append(sp(1))
story.append(Paragraph(
"CKD is often <b>asymptomatic until late stages</b> — many patients are diagnosed incidentally on blood tests. "
"Pain in the renal region and reduced urine output are <b>NOT</b> typical features of CKD. "
"When symptoms do occur, they reflect the uraemic syndrome.",
body_s))
story.append(Paragraph(
"⚠ Ask specifically: Was this an incidental finding? Or were there symptoms prompting testing?",
warn_s))
story.append(sp(2))
# ── 2. HPC ───────────────────────────────────────────────────────────────
story.append(sec("2. HISTORY OF PRESENTING COMPLAINT — URAEMIC SYNDROME", bg=colors.HexColor("#1A5276")))
story.append(sp(1))
uraemic_data = [
[Paragraph("System", th_s), Paragraph("Symptoms to Ask About", th_s), Paragraph("Notes", th_s)],
[Paragraph("General", tcb_s), Paragraph("Fatigue, malaise, weakness, weight loss, anorexia", tc_s), Paragraph("Often earliest symptoms; non-specific", tc_s)],
[Paragraph("GI", tcb_s), Paragraph("Nausea, vomiting, hiccups, metallic taste in mouth, anorexia", tc_s), Paragraph("Uraemic gastritis and gastroparesis", tc_s)],
[Paragraph("Neurological", tcb_s), Paragraph("Confusion, drowsiness, asterixis, seizures (severe); restless legs at night; muscle cramps", tc_s), Paragraph("Uraemic encephalopathy; peripheral neuropathy", tc_s)],
[Paragraph("Cardiovascular", tcb_s), Paragraph("Breathlessness, orthopnoea, ankle swelling, chest pain", tc_s), Paragraph("Fluid overload, LVH, pericarditis (friction rub)", tc_s)],
[Paragraph("Haematological", tcb_s), Paragraph("Pallor, fatigue, dyspnoea on exertion, easy bruising/bleeding", tc_s), Paragraph("Normochromic normocytic anaemia (↓EPO); platelet dysfunction", tc_s)],
[Paragraph("Skin", tcb_s), Paragraph("Pruritus (generalised, severe), sallow/yellow-brown skin", tc_s), Paragraph("Uraemic frost (very late, rare now); calcium-phosphate deposition", tc_s)],
[Paragraph("Bone/MSK", tcb_s), Paragraph("Bone pain, fractures, muscle weakness, proximal myopathy", tc_s), Paragraph("Renal osteodystrophy (↓vit D, ↑PTH, ↑phosphate)", tc_s)],
[Paragraph("Urological", tcb_s), Paragraph("Nocturia (early; loss of concentrating ability), oliguria, haematuria, frothy urine (proteinuria)", tc_s), Paragraph("Haematuria → glomerulonephritis, cancer, stones", tc_s)],
[Paragraph("Sleep / psych", tcb_s), Paragraph("Restless leg syndrome, insomnia, depression, cognitive impairment", tc_s), Paragraph("Very common; QoL impact", tc_s)],
]
story.append(tbl(uraemic_data, [28*mm, 88*mm, 62*mm], bg=colors.HexColor("#1A5276")))
story.append(sp(2))
# ── 3. Risk Factors / Aetiology ──────────────────────────────────────────
story.append(sec("3. RISK FACTOR HISTORY — CAUSES OF CKD", bg=AMBER))
story.append(sp(1))
ckd_cause_left = [
Paragraph("<b>MOST COMMON CAUSES (ask first)</b>", bold_s),
Paragraph("• <b>Diabetes mellitus</b> — type, duration, glycaemic control (HbA1c), proteinuria onset, diabetic retinopathy (marker of nephropathy)", bul_s),
Paragraph("• <b>Hypertension</b> — duration, BP control, medications; may cause OR be caused by CKD", bul_s),
Paragraph("• <b>Glomerulonephritis</b> — haematuria, proteinuria, nephrotic/nephritic syndrome, previous biopsy", bul_s),
Paragraph("• <b>Renovascular disease</b> — atherosclerotic risk factors, flash pulmonary oedema, resistant hypertension", bul_s),
sp(2),
Paragraph("<b>OBSTRUCTIVE / STRUCTURAL</b>", bold_s),
Paragraph("• BPH / prostate cancer — hesitancy, nocturia, poor flow", bul_s),
Paragraph("• Recurrent renal calculi — previous stones, haematuria, colicky pain, metabolic causes", bul_s),
Paragraph("• Recurrent UTIs / reflux nephropathy", bul_s),
Paragraph("• Congenital — horseshoe kidney, duplex system", bul_s),
]
ckd_cause_right = [
Paragraph("<b>SYSTEMIC DISEASES</b>", bold_s),
Paragraph("• SLE / vasculitis — arthralgia, rash, pleuritis, sinusitis, haemoptysis", bul_s),
Paragraph("• Amyloidosis — chronic inflammatory disease, myeloma, weight loss", bul_s),
Paragraph("• Multiple myeloma — back pain, anaemia, hypercalcaemia (age >40 + unexplained CKD)", bul_s),
Paragraph("• Sickle cell disease — sickling crises, chronic haemolysis", bul_s),
sp(2),
Paragraph("<b>HEREDITARY</b>", bold_s),
Paragraph("• <b>Polycystic kidney disease (ADPKD)</b> — family history, loin pain, hypertension, haematuria, liver cysts, cerebral aneurysm", bul_s),
Paragraph("• <b>Alport's syndrome</b> — haematuria, sensorineural deafness, ocular defects, family history", bul_s),
Paragraph("• <b>Fabry's disease</b> — neuropathic pain, angiokeratomas, cardiac disease", bul_s),
sp(2),
Paragraph("<b>NEPHROTOXIC EXPOSURE</b>", bold_s),
Paragraph("• NSAIDs, COX-2 inhibitors (chronic use)", bul_s),
Paragraph("• Contrast nephropathy history", bul_s),
Paragraph("• Lithium — therapeutic levels, duration", bul_s),
Paragraph("• Heavy metals (lead, cadmium) — occupational", bul_s),
Paragraph("• Previous cisplatin / aminoglycoside use", bul_s),
Paragraph("• Aristolochic acid (herbal medicines)", bul_s),
]
story.append(two_col(ckd_cause_left, ckd_cause_right))
story.append(sp(2))
# ── 4. Past Medical History ──────────────────────────────────────────────
story.append(sec("4. PAST MEDICAL HISTORY", bg=BLUE2))
story.append(sp(1))
pmh2_data = [
[Paragraph("Condition", th_s), Paragraph("Why It Matters", th_s)],
[Paragraph("Diabetes mellitus", tcb_s), Paragraph("Most common cause of CKD in developed world; check duration, complications, glycaemic control", tc_s)],
[Paragraph("Hypertension", tcb_s), Paragraph("Cause and consequence of CKD; control critical to slow progression", tc_s)],
[Paragraph("Cardiovascular disease", tcb_s), Paragraph("IHD, heart failure, stroke — major comorbidity and cause of death in CKD", tc_s)],
[Paragraph("Previous AKI", tcb_s), Paragraph("Risk factor for CKD; prior AKI episodes, cause, severity, recovery", tc_s)],
[Paragraph("Urological history", tcb_s), Paragraph("Stones, UTIs, BPH, reflux, haematuria, previous operations", tc_s)],
[Paragraph("Preeclampsia", tcb_s), Paragraph("CKD risk factor; also haematuria / proteinuria in pregnancy", tc_s)],
[Paragraph("Hepatitis B / C / HIV", tcb_s), Paragraph("Membranous/MPGN nephropathy; immunosuppression affects management", tc_s)],
[Paragraph("Gout", tcb_s), Paragraph("Urate nephropathy; shares risk factors with CKD", tc_s)],
]
story.append(tbl(pmh2_data, [45*mm, 133*mm], bg=BLUE2))
story.append(sp(2))
# ── 5. Drug History ──────────────────────────────────────────────────────
story.append(sec("5. DRUG HISTORY — NEPHROTOXIC AGENTS & RENAL DOSING", bg=PURPLE))
story.append(sp(1))
ckd_drug_left = [
Paragraph("<b>NEPHROTOXIC DRUGS TO IDENTIFY</b>", bold_s),
Paragraph("• NSAIDs (ibuprofen, diclofenac) — chronic use", bul_s),
Paragraph("• COX-2 inhibitors", bul_s),
Paragraph("• Lithium — check levels and duration", bul_s),
Paragraph("• Calcineurin inhibitors (ciclosporin, tacrolimus)", bul_s),
Paragraph("• Aminoglycosides — past IV courses", bul_s),
Paragraph("• Contrast agents — previous AKI after imaging?", bul_s),
Paragraph("• Proton pump inhibitors — interstitial nephritis", bul_s),
Paragraph("• Phosphate-containing bowel preps", bul_s),
Paragraph("• Herbal medicines (aristolochic acid)", bul_s),
]
ckd_drug_right = [
Paragraph("<b>CURRENT MEDICATIONS FOR CKD</b>", bold_s),
Paragraph("• ACE inhibitor / ARB — renoprotective; dose?", bul_s),
Paragraph("• <b>SGLT2 inhibitor</b> — dapagliflozin, empagliflozin (renoprotective in DKD)", bul_s),
Paragraph("• Diuretics — loop (furosemide), thiazide", bul_s),
Paragraph("• Phosphate binders — sevelamer, calcium carbonate", bul_s),
Paragraph("• Vitamin D analogues — alfacalcidol, calcitriol", bul_s),
Paragraph("• EPO / ESAs — darbepoetin, erythropoietin", bul_s),
Paragraph("• Antihypertensives — target BP <130/80 in CKD+proteinuria", bul_s),
Paragraph("• Bicarbonate supplementation — for metabolic acidosis", bul_s),
Paragraph("• Allopurinol — for hyperuricaemia", bul_s),
]
story.append(two_col(ckd_drug_left, ckd_drug_right))
story.append(sp(2))
# ── 6. RRT History ───────────────────────────────────────────────────────
story.append(sec("6. RENAL REPLACEMENT THERAPY (RRT) HISTORY — IF APPLICABLE", bg=colors.HexColor("#117A65")))
story.append(sp(1))
rrt_left = [
Paragraph("<b>DIALYSIS</b>", bold_s),
Paragraph("• Type: Haemodialysis (HD) or Peritoneal dialysis (PD)", bul_s),
Paragraph("• HD: frequency (3×/week), duration, unit or home-based", bul_s),
Paragraph("• Access: arteriovenous fistula (AVF), tunnelled line, PD catheter", bul_s),
Paragraph("• Complications: infections, access failure, hypotension on HD", bul_s),
Paragraph("• Adequacy: Kt/V, fluid removal, residual renal function", bul_s),
]
rrt_right = [
Paragraph("<b>TRANSPLANT</b>", bold_s),
Paragraph("• Date, donor (living/deceased), type of match", bul_s),
Paragraph("• Current immunosuppression: tacrolimus, mycophenolate, prednisolone", bul_s),
Paragraph("• Rejection episodes — acute or chronic", bul_s),
Paragraph("• Complications: infections, malignancy, calcineurin toxicity", bul_s),
Paragraph("• Current eGFR of transplant kidney", bul_s),
Paragraph("• Listed for re-transplant?", bul_s),
]
story.append(two_col(rrt_left, rrt_right))
story.append(sp(2))
# ── 7. Social + Family + Systems ─────────────────────────────────────────
soc2_left = [
sec("7. SOCIAL HISTORY", bg=TEAL),
sp(1),
Paragraph("• Occupation — nephrotoxic exposures (lead, cadmium, solvents)", bul_s),
Paragraph("• Diet — high protein, salt, potassium, phosphate intake", bul_s),
Paragraph("• Fluid intake and management", bul_s),
Paragraph("• Smoking — accelerates CKD progression and CVD risk", bul_s),
Paragraph("• Alcohol — NSAID + alcohol = nephrotoxic combination", bul_s),
Paragraph("• Exercise tolerance and functional status", bul_s),
Paragraph("• Transport to dialysis unit (if on HD)", bul_s),
Paragraph("• Social support / carer involvement", bul_s),
Paragraph("• Employment impact / disability", bul_s),
]
soc2_right = [
sec("8. FAMILY HISTORY", bg=TEAL),
sp(1),
Paragraph("• CKD in family members — same or different cause", bul_s),
Paragraph("• <b>ADPKD</b> — autosomal dominant; ask about each parent", bul_s),
Paragraph("• <b>Alport's syndrome</b> — X-linked; family deafness/haematuria", bul_s),
Paragraph("• Diabetes, hypertension in family (risk factors)", bul_s),
Paragraph("• Shared environmental nephrotoxin exposure", bul_s),
sp(1),
sec("9. SYSTEMS REVIEW", bg=GREEN),
sp(1),
Paragraph("• <b>CVS:</b> IHD, LVH, pericarditis (friction rub = uraemia), AF", bul_s),
Paragraph("• <b>Neuro:</b> Peripheral neuropathy, restless legs, encephalopathy", bul_s),
Paragraph("• <b>Eyes:</b> Diabetic retinopathy, hypertensive retinopathy", bul_s),
Paragraph("• <b>Bone:</b> Fractures, bone pain (renal osteodystrophy)", bul_s),
Paragraph("• <b>Psych:</b> Depression, cognitive impairment (very common)", bul_s),
Paragraph("• <b>Sexual:</b> Erectile dysfunction, menstrual irregularity (uraemia)", bul_s),
]
story.append(two_col(soc2_left, soc2_right, lw=88, rw=90))
story.append(sp(2))
# ── CKD Staging Reminder ─────────────────────────────────────────────────
story.append(sec("10. CKD STAGING — KDIGO 2024 (eGFR + Albuminuria)", bg=AMBER))
story.append(sp(1))
ckd_stage_data = [
[Paragraph("Stage", th_s), Paragraph("eGFR (mL/min/1.73m²)", th_s), Paragraph("Severity", th_s)],
[Paragraph("G1", tc_s), Paragraph("≥ 90", tc_s), Paragraph("Normal or high (kidney damage markers present)", tc_s)],
[Paragraph("G2", tc_s), Paragraph("60–89", tc_s), Paragraph("Mildly decreased", tc_s)],
[Paragraph("G3a", tc_s), Paragraph("45–59", tc_s), Paragraph("Mildly to moderately decreased", tc_s)],
[Paragraph("G3b", tc_s), Paragraph("30–44", tc_s), Paragraph("Moderately to severely decreased", tc_s)],
[Paragraph("G4", tc_s), Paragraph("15–29", tc_s), Paragraph("Severely decreased — prepare for RRT", tc_s)],
[Paragraph("G5", tc_s), Paragraph("< 15", tc_s), Paragraph("Kidney failure (ESRD) — RRT or conservative management", tc_s)],
]
story.append(tbl(ckd_stage_data, [13*mm, 50*mm, 115*mm], bg=AMBER))
story.append(sp(1))
story.append(Paragraph(
"Albuminuria categories: A1 <30 mg/g (normal–mildly increased), A2 30–300 mg/g (moderately increased), "
"A3 >300 mg/g (severely increased). Higher albuminuria = faster progression. "
"Combine G and A categories for full staging (e.g. G3bA2).",
smit_s))
story.append(sp(2))
# ── CKD Checklist ─────────────────────────────────────────────────────────
story.append(sec("CKD HISTORY CHECKLIST", bg=colors.HexColor("#2C3E50")))
story.append(sp(1))
ckd_checks = [
("Presenting complaint", "Incidental vs. symptomatic; uraemic symptoms: fatigue, nausea, pruritus, restless legs"),
("Uraemic syndrome review", "GI, neuro, CVS, haematological, skin, bone, urological, sleep symptoms"),
("Cause of CKD", "Diabetes, hypertension, GN, renovascular, obstructive, hereditary, systemic disease"),
("Nephrotoxic drug history", "NSAIDs, lithium, contrast, aminoglycosides, herbal medicines"),
("Current CKD medications", "ACEi/ARB, SGLT2i, diuretics, phosphate binders, EPO, vitamin D"),
("Past medical history", "Diabetes, hypertension, AKI, urological, preeclampsia, cardiovascular"),
("RRT history", "Type of dialysis (HD/PD), access, frequency; transplant history and immunosuppression"),
("Family history", "ADPKD, Alport's, diabetes, hypertension, shared toxin exposure"),
("Social history", "Occupation, diet, smoking, fluid management, transport to dialysis"),
("Systems review", "CVS (IHD, pericarditis), eyes (retinopathy), neuro (neuropathy), bone, psych"),
("CKD staging", "eGFR value, albuminuria category — G and A staging"),
("Differentials", "AKI vs. CKD, obstructive uropathy, myeloma (age >35 with unexplained CKD + anaemia)"),
]
story.append(checklist_table(ckd_checks, bg_hdr=colors.HexColor("#154360"), row_colors=[LIGHTBLUE, WHITE]))
story.append(sp(3))
# ── Footer ────────────────────────────────────────────────────────────────
footer_d = [[Paragraph(
"<i>Sources: Harrison's Principles of Internal Medicine 22E | Barash Clinical Anesthesia 9e | "
"Sleisenger & Fordtran's GI and Liver Disease | Goldman-Cecil Medicine | "
"Tietz Textbook of Laboratory Medicine | KDIGO CKD Guidelines 2024</i>",
ftr_s)]]
footer = Table(footer_d, colWidths=[PW])
footer.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), GREY),
("TOPPADDING", (0,0),(-1,-1), 4),
("BOTTOMPADDING", (0,0),(-1,-1), 4),
("LEFTPADDING", (0,0),(-1,-1), 6),
]))
story.append(footer)
doc.build(story)
print(f"PDF created: {OUTPUT}")
build()
cd /home/daytona/workspace/copd-pdf && python generate_hep_ckd_pdf.py 2>&1
ls -lh /home/daytona/workspace/copd-pdf/
Hepatitis CKD History Quick Reference
PDF Document · PDF
| Section | Contents |
|---|---|
| Presenting Complaint | Jaundice, fatigue, RUQ pain, dark urine, pale stools, pruritus |
| HPC | Acute vs. chronic features, complications (encephalopathy, varices, ascites) |
| Risk Factor Table | Hep A/B/C/D/E, alcoholic, autoimmune, NASH, drug-induced, genetic — routes & specific risk factors |
| Past Medical History | Previous jaundice, biliary surgery, blood products, HIV, dialysis |
| Drug History Table | Hepatotoxic drug classes with patterns (hepatocellular/cholestatic) |
| Social, Family, Systems | Alcohol CAGE/AUDIT, IV drug use, sexual history, travel, vaccination, family genetic causes |
| Differentials | Biliary obstruction, haemolysis, HCC, PBC, alcoholic hepatitis with distinguishing features |
| Checklist | 13-point exam checklist |
| Section | Contents |
|---|---|
| Uraemic Syndrome Table | All systems — GI, neuro, CVS, haematological, skin, bone, urological, sleep |
| Causes of CKD | DM, HTN, GN, ADPKD, Alport's, SLE, myeloma, obstructive, nephrotoxins |
| Past Medical History | Diabetes, hypertension, AKI, cardiovascular, preeclampsia |
| Drug History | Nephrotoxic drugs + current CKD medications (SGLT2i, ACEi, EPO, phosphate binders) |
| RRT History | Haemodialysis, peritoneal dialysis, transplant sections |
| Social, Family, Systems | Diet, fluid, occupation, ADPKD/Alport's family history |
| KDIGO Staging | G1–G5 eGFR table + albuminuria A1–A3 explanation |
| Checklist | 12-point exam checklist |