Proceed with vol 1 medicine opd
mkdir -p /home/daytona/workspace/medicine-opd-vol1 && ls /home/daytona/workspace…
What happened
/home/daytona/workspace/medicine-opd-vol1/Yes generate it
Proceed and generate
Proceed and generate
~/medicine-opd-vol1/generate_vol1.py
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import mm
from reportlab.platypus import (SimpleDocTemplate, Paragraph, Spacer, Table,
TableStyle, HRFlowable, PageBreak, KeepTogether)
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
OUTPUT = "/home/daytona/workspace/medicine-opd-vol1/Vol1_Medicine_OPD.pdf"
doc = SimpleDocTemplate(
OUTPUT, pagesize=A4,
leftMargin=18*mm, rightMargin=18*mm,
topMargin=18*mm, bottomMargin=18*mm
)
W = A4[0] - 36*mm # usable width
styles = getSampleStyleSheet()
# Custom styles
TITLE = ParagraphStyle("TITLE", fontSize=22, fontName="Helvetica-Bold",
textColor=colors.HexColor("#1a237e"), alignment=TA_CENTER,
spaceAfter=4)
SUBTITLE = ParagraphStyle("SUBTITLE", fontSize=13, fontName="Helvetica",
textColor=colors.HexColor("#37474f"), alignment=TA_CENTER,
spaceAfter=2)
TOPIC_HEAD = ParagraphStyle("TOPIC_HEAD", fontSize=15, fontName="Helvetica-Bold",
textColor=colors.white, alignment=TA_LEFT,
spaceAfter=0, spaceBefore=0, leading=20)
SECTION = ParagraphStyle("SECTION", fontSize=10, fontName="Helvetica-Bold",
textColor=colors.HexColor("#1a237e"), spaceBefore=6, spaceAfter=2)
BODY = ParagraphStyle("BODY", fontSize=9, fontName="Helvetica",
leading=13, spaceAfter=2, alignment=TA_JUSTIFY)
BULLET = ParagraphStyle("BULLET", fontSize=9, fontName="Helvetica",
leading=13, leftIndent=12, spaceAfter=1)
SMALL = ParagraphStyle("SMALL", fontSize=8, fontName="Helvetica-Oblique",
textColor=colors.HexColor("#546e7a"), spaceAfter=2)
RX_DRUG = ParagraphStyle("RX_DRUG", fontSize=9, fontName="Helvetica-Bold",
leftIndent=8, spaceAfter=1)
RX_DOSE = ParagraphStyle("RX_DOSE", fontSize=9, fontName="Helvetica",
leftIndent=24, spaceAfter=3)
TOC_ENTRY = ParagraphStyle("TOC_ENTRY", fontSize=10, fontName="Helvetica",
leading=16, spaceAfter=0)
TOC_NUM = ParagraphStyle("TOC_NUM", fontSize=10, fontName="Helvetica-Bold",
textColor=colors.HexColor("#1a237e"), leading=16, spaceAfter=0)
ACCENT = colors.HexColor("#1a237e")
ACCENT2 = colors.HexColor("#283593")
LIGHT_BG = colors.HexColor("#e8eaf6")
STRIPE = colors.HexColor("#f5f5f5")
GREEN = colors.HexColor("#1b5e20")
RED = colors.HexColor("#b71c1c")
AMBER = colors.HexColor("#e65100")
def topic_header(title, number):
data = [[Paragraph(f"{number}. {title}", TOPIC_HEAD)]]
t = Table(data, colWidths=[W])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), ACCENT),
("TOPPADDING", (0,0), (-1,-1), 8),
("BOTTOMPADDING", (0,0), (-1,-1), 8),
("LEFTPADDING", (0,0), (-1,-1), 10),
]))
return t
def section_box(label):
return Paragraph(f"▶ {label}", SECTION)
def hr():
return HRFlowable(width="100%", thickness=0.5, color=colors.HexColor("#b0bec5"), spaceAfter=4)
def inv_table(rows):
"""Two-column investigation table."""
data = [["Investigation", "Expected / Target"]] + rows
col_w = [W*0.48, W*0.48]
t = Table(data, colWidths=col_w, hAlign="LEFT")
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), ACCENT),
("TEXTCOLOR", (0,0), (-1,0), colors.white),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 8.5),
("FONTNAME", (0,1), (-1,-1), "Helvetica"),
("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.white, STRIPE]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#cfd8dc")),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 6),
]))
return t
def rx_table(rows):
"""Prescription table: Drug | Dose | Frequency | Duration."""
data = [["Drug", "Dose", "Frequency", "Duration"]] + rows
col_w = [W*0.32, W*0.20, W*0.26, W*0.18]
t = Table(data, colWidths=col_w, hAlign="LEFT")
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), GREEN),
("TEXTCOLOR", (0,0), (-1,0), colors.white),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 8.5),
("FONTNAME", (0,1), (-1,-1), "Helvetica"),
("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.white, colors.HexColor("#f1f8e9")]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#c8e6c9")),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 6),
]))
return t
def note_box(text, color=None):
bg = color or colors.HexColor("#fff9c4")
data = [[Paragraph(f"<b>NOTE:</b> {text}", SMALL)]]
t = Table(data, colWidths=[W])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("LEFTPADDING", (0,0), (-1,-1), 8),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("BOX", (0,0), (-1,-1), 0.8, colors.HexColor("#f9a825")),
]))
return t
# ─── CONTENT ──────────────────────────────────────────────────────────────────
story = []
# ── COVER PAGE ──
story.append(Spacer(1, 30*mm))
story.append(Paragraph("VOL 1 — MEDICINE OPD", TITLE))
story.append(Spacer(1, 4*mm))
story.append(Paragraph("Structured Case Notes + Prescription Format", SUBTITLE))
story.append(Spacer(1, 3*mm))
story.append(HRFlowable(width="60%", thickness=2, color=ACCENT, hAlign="CENTER"))
story.append(Spacer(1, 6*mm))
topics_list = [
"Hypertension", "Diabetes Mellitus (Type 2)", "Thyroid Disorders",
"Dyslipidemia", "Anaemia", "Fever Workup", "UTI",
"URTI", "LRTI", "Asthma", "COPD",
"Epilepsy", "Headache", "Vertigo", "Gout", "Osteoarthritis"
]
toc_data = []
for i, t in enumerate(topics_list, 1):
toc_data.append([
Paragraph(f"{i:02d}.", TOC_NUM),
Paragraph(t, TOC_ENTRY)
])
toc_table = Table(toc_data, colWidths=[14*mm, W - 14*mm])
toc_table.setStyle(TableStyle([
("FONTSIZE", (0,0), (-1,-1), 10),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LINEBELOW", (0,0), (-1,-1), 0.3, colors.HexColor("#e0e0e0")),
]))
story.append(toc_table)
story.append(Spacer(1, 10*mm))
story.append(Paragraph("Format: History | Examination | Investigations | Diagnosis | Management | Prescription",
SMALL))
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════
# 1. HYPERTENSION
# ═══════════════════════════════════════════════════════════════════
story.append(topic_header("HYPERTENSION", 1))
story.append(Spacer(1, 4))
story.append(section_box("HISTORY"))
story.append(Paragraph("<b>Chief Complaint:</b> Headache / dizziness / incidental BP elevation / chest discomfort", BODY))
story.append(Paragraph("<b>History of Present Illness:</b>", BODY))
for b in ["Duration of high BP; first detected how (routine check / symptoms)",
"Headache — occipital, morning worse; nausea/vomiting",
"Visual disturbances, epistaxis, palpitations",
"Chest pain / breathlessness (cardiac involvement)",
"Swelling of legs (renal / cardiac)",
"Haematuria (renal cause)",
"Symptoms of secondary HTN: weight gain, moon face (Cushing's); sweating/palpitations (phaeochromocytoma); muscle cramps (Conn's)"]:
story.append(Paragraph(f"• {b}", BULLET))
story.append(Paragraph("<b>Past History:</b> DM, CKD, CAD, stroke, dyslipidemia", BODY))
story.append(Paragraph("<b>Drug History:</b> NSAIDs, OCP, steroids, decongestants", BODY))
story.append(Paragraph("<b>Family History:</b> HTN, CAD, stroke", BODY))
story.append(Paragraph("<b>Personal History:</b> Salt intake, alcohol, smoking, physical activity, stress", BODY))
story.append(section_box("EXAMINATION"))
ex_rows = [
["BP", "Both arms; lying & standing (postural drop)"],
["Pulse", "Rate, rhythm, volume, radio-femoral delay"],
["BMI / Waist circumference", "Obesity assessment"],
["Fundus", "AV nipping, flame haemorrhages, papilloedema (Keith-Wagener grading)"],
["CVS", "Apex beat displacement, S3/S4, murmurs"],
["Abdomen", "Renal bruits (renovascular), ballotable kidneys"],
["Neuro", "Focal deficits (end-organ damage)"],
]
story.append(inv_table(ex_rows))
story.append(Spacer(1, 4))
story.append(section_box("INVESTIGATIONS"))
story.append(inv_table([
["FBS / HbA1c", "Rule out DM comorbidity"],
["Lipid profile", "Cardiovascular risk assessment"],
["S. Creatinine + eGFR", "CKD screening"],
["Urine R/E + ACR", "Proteinuria (end-organ)"],
["Serum electrolytes", "Hypokalemia → Conn's syndrome"],
["ECG", "LVH (Sokolow-Lyon criteria), strain pattern"],
["Echo (2D)", "If LVH / cardiac symptoms"],
["Renal USG", "If CKD suspected / bilateral renal bruits"],
["Thyroid profile", "Secondary HTN screening"],
["24-hr urine metanephrines", "If phaeochromocytoma suspected"],
]))
story.append(Spacer(1, 4))
story.append(section_box("CLASSIFICATION (JNC 8 / ACC-AHA 2017)"))
cls_rows = [
["Normal", "<120/<80"],
["Elevated", "120-129/<80"],
["Stage 1 HTN", "130-139 / 80-89"],
["Stage 2 HTN", "≥140 / ≥90"],
["Hypertensive Crisis", "≥180 / ≥120"],
]
story.append(inv_table(cls_rows))
story.append(Spacer(1, 4))
story.append(section_box("MANAGEMENT"))
story.append(Paragraph("<b>Non-pharmacological (all stages):</b>", BODY))
for b in ["DASH diet (low sodium <2g/day, high K, fruits, vegetables)",
"Weight reduction (target BMI <25)",
"Regular aerobic exercise 30 min, 5 days/week",
"Smoking cessation; limit alcohol (<2 units/day men, <1 women)",
"Stress management"]:
story.append(Paragraph(f"• {b}", BULLET))
story.append(Paragraph("<b>Pharmacological — First-line agents:</b>", BODY))
story.append(Paragraph("A = ACE inhibitor/ARB | B = Beta-blocker | C = CCB (amlodipine) | D = Diuretic (thiazide)", SMALL))
for b in ["Stage 1: Lifestyle + single agent (A or C or D based on comorbidity)",
"Stage 2: Two-drug combo (A+C preferred; A+D if oedema prone)",
"Compelling indications: DM/CKD → ACEi/ARB first; CAD → Beta-blocker; HF → ACEi + BB + diuretic",
"Target BP: General <130/80; CKD/DM <130/80; Elderly ≥65 yr <130/80"]:
story.append(Paragraph(f"• {b}", BULLET))
story.append(section_box("PRESCRIPTION"))
story.append(rx_table([
["Tab. Amlodipine", "5 mg", "Once daily (morning)", "Ongoing"],
["Tab. Telmisartan", "40 mg", "Once daily (morning)", "Ongoing"],
["Tab. Hydrochlorothiazide", "12.5 mg", "Once daily (morning)", "Ongoing (if needed)"],
["Tab. Atorvastatin", "10-40 mg", "Once at bedtime", "Ongoing (if CVD risk)"],
["Tab. Aspirin (low-dose)", "75 mg", "Once daily after food", "If 10-yr CVD risk >10%"],
]))
story.append(Spacer(1, 3))
story.append(note_box("Monitor BP every 2 weeks till target achieved, then monthly. Check renal function and electrolytes after starting ACEi/ARB at 1 month."))
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════
# 2. DIABETES MELLITUS TYPE 2
# ═══════════════════════════════════════════════════════════════════
story.append(topic_header("DIABETES MELLITUS (TYPE 2)", 2))
story.append(Spacer(1, 4))
story.append(section_box("HISTORY"))
for b in ["Polyuria, polydipsia, polyphagia, unexplained weight loss",
"Fatigue, recurrent infections (UTI, skin, fungal)",
"Blurring of vision (osmotic lens changes or retinopathy)",
"Tingling/numbness feet (peripheral neuropathy)",
"Foot wounds that do not heal (diabetic foot)",
"Family history of DM, gestational DM",
"Diet history: high carbohydrate, sedentary lifestyle",
"Current medications: steroids, antipsychotics (drug-induced DM)",
"Symptoms of hypoglycaemia: sweating, tremors, palpitations"]:
story.append(Paragraph(f"• {b}", BULLET))
story.append(section_box("EXAMINATION"))
story.append(inv_table([
["BMI / Waist-hip ratio", "Central obesity — metabolic syndrome"],
["BP", "HTN comorbidity (>130/80 target)"],
["Fundus", "NPDR/PDR — dot & blot haemorrhages, neovascularization"],
["Feet", "Loss of sensation (monofilament), ABI, deformities, ulcers"],
["Kidney size", "Nephromegaly in early DM nephropathy"],
["Thyroid", "Hypothyroidism comorbidity common in T2DM"],
["Skin", "Acanthosis nigricans (insulin resistance)"],
]))
story.append(Spacer(1, 4))
story.append(section_box("DIAGNOSTIC CRITERIA (ADA 2024)"))
story.append(inv_table([
["FPG", "≥126 mg/dL (fasting ≥8 hrs)"],
["2-hr OGTT (75g)", "≥200 mg/dL"],
["HbA1c", "≥6.5%"],
["Random plasma glucose", "≥200 mg/dL + symptoms"],
["Prediabetes FPG", "100-125 mg/dL"],
["Prediabetes HbA1c", "5.7-6.4%"],
]))
story.append(Spacer(1, 4))
story.append(section_box("INVESTIGATIONS"))
story.append(inv_table([
["FBS / PPBS / HbA1c", "Diagnosis + glycaemic monitoring (3-monthly HbA1c)"],
["Lipid profile", "Dyslipidemia — high TG, low HDL pattern in T2DM"],
["S. Creatinine + eGFR", "DM nephropathy baseline"],
["Urine ACR (albumin:creatinine)", "Microalbuminuria: 30-300 mg/g = nephropathy stage A2"],
["LFT", "NAFLD association"],
["TSH", "Hypothyroidism comorbidity"],
["ECG / 2D Echo", "Silent CAD screening"],
["Urine R/E", "Glycosuria, proteinuria, infection"],
["Nerve conduction study", "Peripheral neuropathy (if symptoms)"],
["Fundus examination", "Annual diabetic retinopathy screening"],
]))
story.append(Spacer(1, 4))
story.append(section_box("MANAGEMENT"))
story.append(Paragraph("<b>Lifestyle:</b> MNT (1500-1800 kcal/day, low GI diet), 150 min/week moderate exercise, smoking cessation, weight loss 5-10% if overweight", BODY))
story.append(Paragraph("<b>Glycaemic Targets:</b> HbA1c <7% (general); <6.5% if young + no hypoglycaemia risk; <8% if elderly/frail", BODY))
story.append(Paragraph("<b>Algorithm:</b> Metformin first-line → Add 2nd agent based on comorbidity (SGLT2i if CVD/CKD; GLP-1 RA if obesity; DPP4i if well tolerated) → Triple therapy → Insulin if HbA1c >10% or symptomatic", BODY))
story.append(section_box("PRESCRIPTION"))
story.append(rx_table([
["Tab. Metformin SR", "500-1000 mg", "Twice daily with food", "Ongoing"],
["Tab. Glimepiride", "1-2 mg", "Once daily before breakfast", "Ongoing (add-on)"],
["Tab. Dapagliflozin (SGLT2i)", "10 mg", "Once daily", "If CVD/CKD present"],
["Tab. Sitagliptin (DPP4i)", "100 mg", "Once daily", "Alternative 2nd agent"],
["Tab. Atorvastatin", "20-40 mg", "Once at bedtime", "All T2DM >40 yrs"],
["Tab. Aspirin (low-dose)", "75-150 mg", "Once after food", "If 10-yr CVD risk >10%"],
["Inj. Insulin Glargine", "0.2 U/kg", "Once at bedtime", "If HbA1c >10%"],
]))
story.append(Spacer(1, 3))
story.append(note_box("Annual monitoring: HbA1c (every 3 months), lipids (yearly), urine ACR, creatinine, fundus, feet exam. Sick-day rules: do NOT stop metformin without doctor advice during illness but hold SGLT2i."))
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════
# 3. THYROID DISORDERS
# ═══════════════════════════════════════════════════════════════════
story.append(topic_header("THYROID DISORDERS", 3))
story.append(Spacer(1, 4))
story.append(section_box("HYPOTHYROIDISM"))
story.append(Paragraph("<b>Symptoms:</b> Fatigue, weight gain, cold intolerance, constipation, dry skin, hair loss, hoarseness, menstrual irregularity (menorrhagia), depression, slowed reflexes, myxoedema (severe)", BODY))
story.append(Paragraph("<b>Signs:</b> Dry coarse skin, puffy face, periorbital oedema, bradycardia, goitre, delayed ankle jerk relaxation, anaemia", BODY))
story.append(section_box("HYPERTHYROIDISM (THYROTOXICOSIS)"))
story.append(Paragraph("<b>Symptoms:</b> Weight loss despite good appetite, heat intolerance, palpitations, tremor, diarrhoea, irritability, scanty periods, neck swelling", BODY))
story.append(Paragraph("<b>Signs:</b> Tachycardia/AF, warm moist skin, fine tremor, goitre ± bruit, exophthalmos/lid lag (Graves'), pretibial myxoedema, proximal myopathy", BODY))
story.append(section_box("INVESTIGATIONS"))
story.append(inv_table([
["TSH", "Primary screening test (↑ in hypothyroid; ↓ in hyperthyroid)"],
["Free T4 (FT4)", "Confirms overt disease"],
["Free T3 (FT3)", "T3 toxicosis; hyperthyroid with normal FT4"],
["Anti-TPO antibodies", "Hashimoto's thyroiditis (hypothyroid)"],
["TSH receptor antibodies (TRAb)", "Graves' disease (hyperthyroid)"],
["Thyroid USG", "Goitre, nodules, vascularity (Graves' — increased)"],
["Tc-99m thyroid scan", "Hot/cold nodules, autonomous adenoma"],
["FBC, lipids, LFT", "Hypothyroid: ↑cholesterol, anaemia"],
["ECG", "AF in hyperthyroidism"],
]))
story.append(Spacer(1, 4))
story.append(section_box("MANAGEMENT — HYPOTHYROIDISM"))
story.append(rx_table([
["Tab. Levothyroxine (T4)", "25-50 mcg (start low)", "Once daily, empty stomach", "Lifelong"],
["", "Titrate every 6-8 wks", "↑ by 25 mcg steps", "Target TSH 0.5-2.5 mU/L"],
]))
story.append(Spacer(1, 3))
story.append(note_box("Start low in elderly / CAD (25 mcg). Take 30-60 min before breakfast. Avoid calcium, iron within 4 hrs. Recheck TSH at 6-8 weeks after each dose change."))
story.append(Spacer(1, 4))
story.append(section_box("MANAGEMENT — HYPERTHYROIDISM (GRAVES')"))
story.append(rx_table([
["Tab. Carbimazole", "20-40 mg/day (divided)", "2-3 times daily", "12-18 months"],
["Tab. Propranolol", "20-40 mg", "3 times daily", "Till euthyroid (symptom control)"],
["Tab. Carbimazole (block-replace)", "40 mg + Levothyroxine 100 mcg", "Once daily", "Alternative regime"],
]))
story.append(Spacer(1, 3))
story.append(note_box("Monitor TFT every 4-6 weeks. Warn patient: sore throat / fever → stop carbimazole immediately, check WBC (agranulocytosis risk). Radioiodine or surgery for relapse/large goitre."))
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════
# 4. DYSLIPIDEMIA
# ═══════════════════════════════════════════════════════════════════
story.append(topic_header("DYSLIPIDEMIA", 4))
story.append(Spacer(1, 4))
story.append(section_box("HISTORY"))
for b in ["Usually asymptomatic — incidental on routine lipid profile",
"Xanthomas (tendons, elbows), xanthelasma (periorbital)",
"Premature CAD / family history of early MI",
"Diet: high saturated fat, trans fat, refined carbs",
"Alcohol intake (↑ triglycerides)",
"Secondary causes: hypothyroidism, DM, nephrotic syndrome, CKD, medications (steroids, thiazides, beta-blockers)"]:
story.append(Paragraph(f"• {b}", BULLET))
story.append(section_box("INVESTIGATIONS"))
story.append(inv_table([
["Fasting lipid profile (12 hrs)", "TC, LDL-C, HDL-C, TG, non-HDL-C, VLDL"],
["LDL-C (Friedewald)", "TC - HDL - TG/5 (valid if TG<400)"],
["TSH", "Rule out hypothyroidism"],
["FBS / HbA1c", "Rule out DM"],
["S. Creatinine + urine protein", "Rule out nephrotic syndrome/CKD"],
["LFT (ALT/AST)", "Baseline before statin; monitor if symptoms"],
["CK level", "Baseline before statin; check if myalgia develops"],
["10-year CVD risk (PCE/Framingham)", "Guides treatment intensity"],
]))
story.append(Spacer(1, 4))
story.append(section_box("TARGET LDL-C BY RISK CATEGORY (ACC/AHA 2019)"))
story.append(inv_table([
["Very High Risk (ASCVD established / DM with end-organ)", "LDL-C <55 mg/dL"],
["High Risk (DM without ASCVD / 10-yr risk ≥20%)", "LDL-C <70 mg/dL"],
["Intermediate Risk (10-yr risk 7.5-20%)", "LDL-C <100 mg/dL"],
["Low Risk (10-yr risk <7.5%)", "LDL-C <130 mg/dL"],
]))
story.append(Spacer(1, 4))
story.append(section_box("MANAGEMENT"))
story.append(Paragraph("<b>Lifestyle:</b> Low saturated fat (<7% calories), soluble fibre 10-25g/day, plant sterols 2g/day, aerobic exercise, weight loss, stop smoking, limit alcohol", BODY))
story.append(Paragraph("<b>High-intensity statin:</b> Atorvastatin 40-80 mg or Rosuvastatin 20-40 mg (LDL reduction >50%)", BODY))
story.append(Paragraph("<b>Moderate-intensity statin:</b> Atorvastatin 10-20 mg / Rosuvastatin 5-10 mg (LDL reduction 30-50%)", BODY))
story.append(section_box("PRESCRIPTION"))
story.append(rx_table([
["Tab. Atorvastatin", "20-80 mg", "Once at bedtime", "Ongoing"],
["Tab. Rosuvastatin", "10-40 mg", "Once at bedtime", "Alternative high-intensity"],
["Tab. Ezetimibe", "10 mg", "Once daily", "Add-on if LDL not at target"],
["Cap. Omega-3 (Icosapent ethyl)", "2-4 g/day", "Divided doses with food", "High TG (>500 mg/dL)"],
["Tab. Fenofibrate", "145 mg", "Once daily with meal", "Isolated hypertriglyceridemia"],
]))
story.append(Spacer(1, 3))
story.append(note_box("Check LFT + CK at baseline and 6-8 weeks. Myalgia with normal CK → continue. CK >10x ULN → stop statin. Repeat lipid profile at 6-8 weeks after starting to assess response."))
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════
# 5. ANAEMIA
# ═══════════════════════════════════════════════════════════════════
story.append(topic_header("ANAEMIA", 5))
story.append(Spacer(1, 4))
story.append(section_box("HISTORY"))
for b in ["Fatigue, weakness, exertional dyspnoea, palpitations",
"Pallor noted by patient or family",
"Diet: vegetarian/vegan (B12/folate deficiency risk), poor iron intake",
"Blood loss: heavy menstruation, PR bleed, haemoptysis, haematuria",
"GI symptoms: dysphagia (Plummer-Vinson), weight loss (malignancy)",
"Drug history: NSAIDs (GI bleed), methotrexate (folate antagonist), chemotherapy",
"Jaundice, dark urine, splenomegaly (haemolysis)",
"Family history: thalassaemia, sickle cell disease",
"Pica: craving for clay/ice (IDA)"]:
story.append(Paragraph(f"• {b}", BULLET))
story.append(section_box("EXAMINATION"))
story.append(inv_table([
["Conjunctival/palmar pallor", "Severity of anaemia"],
["Koilonychia (spoon nails)", "Iron deficiency anaemia"],
["Angular stomatitis, glossitis", "IDA / B12 deficiency"],
["Icterus", "Haemolytic anaemia"],
["Splenomegaly", "Haemolysis, haematological malignancy"],
["Lymphadenopathy", "Lymphoma, chronic disease"],
["Neurological (subacute combined degeneration)", "B12 deficiency — posterior column loss"],
]))
story.append(Spacer(1, 4))
story.append(section_box("INVESTIGATIONS — APPROACH BY MCV"))
story.append(inv_table([
["MCV <80 (Microcytic)", "IDA, Thalassaemia, Anaemia of chronic disease (ACD), Sideroblastic"],
["MCV 80-100 (Normocytic)", "ACD, Haemolysis, Aplastic, CKD, Acute blood loss"],
["MCV >100 (Macrocytic)", "B12/Folate deficiency, Alcohol, Hypothyroidism, Liver disease"],
]))
story.append(Spacer(1, 3))
story.append(inv_table([
["CBC with reticulocyte count", "Type, severity, marrow response"],
["Peripheral blood smear", "Morphology — hypochromic microcytic, target cells, sickle, macro-ovalocytes"],
["Serum iron, TIBC, ferritin", "IDA: ↓ferritin, ↓iron, ↑TIBC; ACD: ↑ferritin, ↓iron, ↓TIBC"],
["Serum B12 + folate", "Macrocytic anaemia"],
["Reticulocyte count", "High → haemolysis; Low → aplastic/nutritional"],
["Direct Coombs test (DCT)", "Autoimmune haemolytic anaemia"],
["HPLC (Hb electrophoresis)", "Thalassaemia, Hb variants"],
["Bone marrow biopsy", "Aplastic anaemia, myelodysplasia"],
["Upper GI endoscopy / colonoscopy", "If occult blood loss suspected (>40 yrs)"],
]))
story.append(Spacer(1, 4))
story.append(section_box("PRESCRIPTION — IRON DEFICIENCY ANAEMIA"))
story.append(rx_table([
["Tab. Ferrous sulphate", "200 mg (65 mg elemental)", "Twice daily empty stomach", "3-6 months"],
["Tab. Ferrous ascorbate + Folic acid", "100 mg + 1.5 mg", "Once daily", "If GI intolerance"],
["Inj. Iron sucrose (IV)", "200 mg in 100mL NS over 30 min", "3 doses alternate days", "If oral intolerance/malabsorption"],
["Tab. Folic acid", "5 mg", "Once daily", "3 months (megaloblastic)"],
["Inj. Cyanocobalamin (B12)", "1000 mcg IM", "Daily x7 days, then weekly x4", "B12 deficiency"],
]))
story.append(Spacer(1, 3))
story.append(note_box("Take oral iron with vitamin C (orange juice) to enhance absorption. Avoid with tea, coffee, calcium. Expect reticulocyte peak at 7-10 days. Continue iron 3 months after Hb normalises to replenish stores. Treat underlying cause."))
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════
# 6. FEVER WORKUP
# ═══════════════════════════════════════════════════════════════════
story.append(topic_header("FEVER WORKUP", 6))
story.append(Spacer(1, 4))
story.append(section_box("HISTORY"))
for b in ["Onset, duration, pattern (continuous/remittent/intermittent/hectic)",
"Height of fever, chills and rigors (malaria, bacteraemia)",
"Diurnal variation: evening rise (TB), morning rise (unusual)",
"Associated symptoms: rash, arthralgia, lymphadenopathy",
"Headache + neck stiffness (meningitis)",
"Jaundice + hepatosplenomegaly (hepatitis, malaria, enteric)",
"Diarrhoea (enteric fever, viral gastroenteritis)",
"Dysuria (UTI)",
"Cough + chest pain (pneumonia)",
"Travel history, animal exposure (leptospirosis, brucellosis)",
"Sexual history (HIV, STI)",
"Tick/sandfly bite (rickettsial, kala-azar)"]:
story.append(Paragraph(f"• {b}", BULLET))
story.append(section_box("FEVER PATTERN GUIDE"))
story.append(inv_table([
["Intermittent (quotidian)", "Malaria (P. vivax / P. ovale — 48h; P. malariae — 72h)"],
["Continuous / Sustained", "Typhoid, Lobar pneumonia, Meningitis"],
["Remittent", "Viral infections, TB"],
["Hectic (Picket-fence)", "Abscess, endocarditis, lymphoma"],
["Pel-Ebstein (cyclical)", "Hodgkin's lymphoma"],
["PUO (>3 weeks, T>38.3°C)", "TB, Lymphoma, SLE, Infective endocarditis, Kala-azar"],
]))
story.append(Spacer(1, 4))
story.append(section_box("INVESTIGATIONS — SYSTEMATIC APPROACH"))
story.append(inv_table([
["CBC + differential + ESR", "Leukocytosis (bacterial); Leukopenia (viral/typhoid); Eosinophilia (parasitic)"],
["Peripheral smear (PS) for MP", "Malaria (thick + thin smear; Leishman stain)"],
["Blood culture (x2-3 sets)", "Typhoid, bacteraemia, endocarditis — before antibiotics"],
["Widal test", "Typhoid (O ≥1:160, H ≥1:160 significant from 2nd week)"],
["Dengue NS1 Ag + IgM/IgG", "Dengue fever (NS1 positive days 1-5)"],
["Malaria Rapid Antigen (RDT)", "P. falciparum (HRP2 antigen)"],
["Scrub typhus IgM (ELISA)", "Eschar + fever in endemic areas"],
["Urine R/E + culture", "UTI as source"],
["CXR", "Pneumonia, TB, pleural effusion"],
["LFT + S. Bilirubin", "Hepatitis, leptospirosis"],
["Leptospira IgM (MAT/ELISA)", "Flood exposure, rodent contact"],
["HIV Ag/Ab (4th gen)", "Prolonged fever, lymphadenopathy"],
["ANA / dsDNA / complement", "If connective tissue disease suspected (PUO)"],
]))
story.append(Spacer(1, 4))
story.append(section_box("EMPIRICAL MANAGEMENT (WHILE AWAITING CULTURES)"))
story.append(rx_table([
["Tab. Paracetamol", "500-1000 mg", "Every 6-8 hrs (max 4g/day)", "For fever control"],
["Tab. Doxycycline", "100 mg", "Twice daily x14-21 days", "Scrub typhus / rickettsial"],
["Tab. Chloroquine", "600 mg stat → 300 mg at 6h, 24h, 48h", "Supervised", "P. vivax malaria"],
["Inj. Artesunate IV (refer)", "2.4 mg/kg at 0, 12, 24h then daily", "IV in hospital", "Severe P. falciparum"],
["Tab. Azithromycin", "500 mg", "Once daily x3 days", "Enteric fever (1st line)"],
]))
story.append(Spacer(1, 3))
story.append(note_box("Do NOT start antibiotics before collecting blood cultures. In dengue: avoid NSAIDs and aspirin (bleeding risk). Alert signs: petechiae, gum bleeding, restlessness, rapid shallow breathing → refer urgently."))
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════
# 7. UTI
# ═══════════════════════════════════════════════════════════════════
story.append(topic_header("URINARY TRACT INFECTION (UTI)", 7))
story.append(Spacer(1, 4))
story.append(section_box("HISTORY"))
for b in ["Dysuria (burning micturition), frequency, urgency",
"Suprapubic pain / discomfort",
"Haematuria (macroscopic or microscopic)",
"Fever, chills, rigors, loin pain, vomiting (upper UTI / pyelonephritis)",
"Vaginal discharge (rule out STI/vaginitis)",
"Previous UTI episodes — frequency, last episode",
"Pregnancy (asymptomatic bacteriuria must be treated)",
"Catheter use (CAUTI)",
"Diabetes, immunosuppression, renal stones",
"In males: symptoms of BPH, prostatitis (perineal pain, obstructive symptoms)"]:
story.append(Paragraph(f"• {b}", BULLET))
story.append(section_box("CLASSIFICATION"))
story.append(inv_table([
["Uncomplicated cystitis", "Young healthy non-pregnant women; lower UTI"],
["Pyelonephritis", "Upper UTI; fever, flank pain, CVA tenderness"],
["Complicated UTI", "Males, pregnancy, catheter, structural abnormality, DM, immunosuppressed"],
["Recurrent UTI", "≥2 episodes in 6 months or ≥3 in 1 year"],
["Asymptomatic bacteriuria", "≥10⁵ CFU/mL without symptoms (treat only in pregnancy/pre-urological surgery)"],
]))
story.append(Spacer(1, 4))
story.append(section_box("INVESTIGATIONS"))
story.append(inv_table([
["Urine R/E (dipstick)", "Nitrites (gram-negative bacteria), leukocyte esterase, WBCs, RBCs"],
["Urine microscopy", "Pyuria (>10 WBC/hpf), bacteriuria"],
["Urine culture + sensitivity (C/S)", "Midstream clean-catch; >10⁵ CFU/mL significant; before antibiotics"],
["CBC + CRP", "Pyelonephritis: leukocytosis, elevated CRP/ESR"],
["S. Creatinine + eGFR", "Renal involvement"],
["Urine pregnancy test (women)", "Affects antibiotic choice"],
["Renal USG", "Calculi, hydronephrosis, abscess (in complicated/recurrent UTI)"],
["CT KUB", "If renal abscess / stones suspected"],
]))
story.append(Spacer(1, 4))
story.append(section_box("PRESCRIPTION"))
story.append(Paragraph("<b>Uncomplicated Cystitis (Women):</b>", BODY))
story.append(rx_table([
["Tab. Nitrofurantoin", "100 mg (macrocrystal)", "Twice daily with food", "5 days"],
["Tab. Trimethoprim-Sulfamethoxazole", "160/800 mg (DS)", "Twice daily", "3 days (if local resistance <20%)"],
["Tab. Fosfomycin trometamol", "3 g sachet in water", "Single dose", "Single dose"],
["Tab. Cefuroxime", "250 mg", "Twice daily", "5-7 days (alternative)"],
]))
story.append(Spacer(1, 3))
story.append(Paragraph("<b>Pyelonephritis / Complicated UTI:</b>", BODY))
story.append(rx_table([
["Tab. Ciprofloxacin", "500 mg", "Twice daily", "7-14 days"],
["Tab. Co-amoxiclav", "625 mg", "3 times daily with food", "7-14 days"],
["Tab. Cefixime", "200 mg", "Twice daily", "7-10 days"],
["Tab. Paracetamol", "500-1000 mg", "Every 6 hrs PRN", "For fever/pain"],
["ORS / IV fluids", "Force fluids 2-3 L/day orally", "Throughout", "Hydration"],
]))
story.append(Spacer(1, 3))
story.append(note_box("Always send urine C/S before starting antibiotics. Review and de-escalate based on sensitivity results at 48-72 hrs. Avoid fluoroquinolones as first-line if local resistance >20%. Repeat urine culture 1 week after completing treatment in pregnant patients."))
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════
# 8. URTI
# ═══════════════════════════════════════════════════════════════════
story.append(topic_header("UPPER RESPIRATORY TRACT INFECTION (URTI)", 8))
story.append(Spacer(1, 4))
story.append(section_box("HISTORY & CLINICAL FEATURES"))
story.append(inv_table([
["Common Cold (Viral Rhinitis)", "Rhinorrhoea (clear), sneezing, sore throat, low-grade fever, myalgia. Duration 7-10 days."],
["Acute Pharyngitis / Tonsillitis", "Sore throat, odynophagia, tonsillar exudate, fever, cervical lymphadenopathy"],
["Acute Sinusitis", "Facial pain/pressure, nasal congestion, purulent discharge, fever"],
["Acute Otitis Media", "Ear pain, hearing loss, fever (mainly children)"],
["Acute Epiglottitis", "Drooling, stridor, muffled voice, high fever — EMERGENCY"],
]))
story.append(Spacer(1, 4))
story.append(section_box("CENTOR SCORE (Strep Pharyngitis)"))
story.append(inv_table([
["Tonsillar exudate", "+1 point"],
["Swollen tender anterior cervical nodes", "+1 point"],
["Temperature >38°C", "+1 point"],
["Absence of cough", "+1 point"],
["Score 0-1: viral (no antibiotic)", "Score ≥3: treat or throat swab culture"],
]))
story.append(Spacer(1, 4))
story.append(section_box("INVESTIGATIONS"))
story.append(inv_table([
["Rapid strep antigen test (RADT)", "Group A Streptococcus — high specificity"],
["Throat culture", "If RADT negative but high suspicion"],
["CBC", "Lymphocytosis → viral; Neutrophilia → bacterial"],
["Monospot / EBV Paul-Bunnell", "Infectious mononucleosis (EBV)"],
["CXR", "Only if LRTI suspected (cough >3 weeks, focal signs)"],
]))
story.append(Spacer(1, 4))
story.append(section_box("PRESCRIPTION — VIRAL URTI (SYMPTOMATIC)"))
story.append(rx_table([
["Tab. Paracetamol", "500-1000 mg", "Every 6-8 hrs", "3-5 days (fever/pain)"],
["Tab./Syrup Cetirizine", "10 mg", "Once at night", "3-5 days (rhinorrhoea)"],
["Tab. Phenylephrine (decongestant)", "10 mg", "Every 4 hrs (max 3 days)", "Nasal congestion only"],
["Saline nasal spray", "2 puffs each nostril", "3-4 times daily", "Nasal irrigation"],
["Throat lozenges / Gargle (warm salt water)", "PRN", "4-6 times daily", "Sore throat"],
]))
story.append(Spacer(1, 3))
story.append(Paragraph("<b>Bacterial (Strep) Pharyngitis / Sinusitis:</b>", BODY))
story.append(rx_table([
["Tab. Amoxicillin", "500 mg", "3 times daily", "10 days (strep pharyngitis)"],
["Tab. Amoxicillin-clavulanate", "625 mg", "3 times daily", "7-10 days (sinusitis)"],
["Tab. Azithromycin", "500 mg day 1, then 250 mg", "Once daily", "5 days (penicillin allergy)"],
]))
story.append(Spacer(1, 3))
story.append(note_box("Do NOT prescribe antibiotics for viral URTI (common cold). Antibiotics do not shorten duration and increase resistance. Advise rest, fluids, steam inhalation. If symptoms persist >10 days or worsen after initial improvement → consider bacterial sinusitis."))
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════
# 9. LRTI (COMMUNITY-ACQUIRED PNEUMONIA)
# ═══════════════════════════════════════════════════════════════════
story.append(topic_header("LOWER RESPIRATORY TRACT INFECTION (LRTI / CAP)", 9))
story.append(Spacer(1, 4))
story.append(section_box("HISTORY"))
for b in ["Productive cough — colour of sputum (yellow/green = bacterial; rust-coloured = pneumococcal; pink frothy = pulmonary oedema)",
"Fever with chills / rigors",
"Pleuritic chest pain (sharp, worse on breathing)",
"Dyspnoea, respiratory rate",
"Duration, smoking history",
"Immunosuppression, recent hospitalisation (HCAP vs CAP)",
"Aspiration risk: elderly, alcoholism, impaired swallowing"]:
story.append(Paragraph(f"• {b}", BULLET))
story.append(section_box("CURB-65 SEVERITY SCORE"))
story.append(inv_table([
["C — Confusion (new)", "+1 point"],
["U — Urea >7 mmol/L (BUN >19 mg/dL)", "+1 point"],
["R — Respiratory rate ≥30/min", "+1 point"],
["B — BP: systolic <90 or diastolic ≤60", "+1 point"],
["65 — Age ≥65 years", "+1 point"],
["Score 0-1: Outpatient (low risk)", "Score 2: Consider admission"],
["Score ≥3: Hospitalise; ≥4 or 5: ICU consideration", ""],
]))
story.append(Spacer(1, 4))
story.append(section_box("INVESTIGATIONS"))
story.append(inv_table([
["CXR PA view", "Lobar/segmental consolidation, pleural effusion, cavitation"],
["CBC + differential", "Neutrophilia (bacterial); lymphocytosis (viral/atypical)"],
["CRP / Procalcitonin (PCT)", "PCT >0.25 → bacterial; guides antibiotic decision"],
["Blood cultures (x2)", "Before antibiotics in moderate-severe CAP"],
["Sputum Gram stain + C/S", "Productive cough; send before antibiotics"],
["ABG / SpO2", "Respiratory failure assessment; target SpO2 ≥94%"],
["S. Creatinine, LFT", "Organ function, antibiotic dosing"],
["Urine Legionella Ag", "Severe CAP / travel / AC exposure"],
["Urine Pneumococcal Ag", "Moderate-severe CAP"],
["HIV test", "Young patients / atypical presentation"],
]))
story.append(Spacer(1, 4))
story.append(section_box("PRESCRIPTION — OUTPATIENT CAP (CURB-65: 0-1)"))
story.append(rx_table([
["Tab. Amoxicillin", "500 mg-1 g", "3 times daily", "5-7 days"],
["Tab. Azithromycin", "500 mg", "Once daily", "5 days (atypical cover)"],
["Tab. Doxycycline", "100 mg", "Twice daily", "5-7 days (alternative)"],
["Tab. Paracetamol", "1 g", "Every 6-8 hrs", "For fever/pain"],
["Salbutamol MDI (if wheeze)", "2-4 puffs", "Every 4-6 hrs", "PRN"],
]))
story.append(Spacer(1, 3))
story.append(Paragraph("<b>Moderate CAP (in-patient):</b> IV Amoxicillin-clavulanate 1.2g TDS + Azithromycin 500mg OD IV/PO", BODY))
story.append(note_box("Step-down from IV to oral when: afebrile 24-48 hrs, HR <100, RR <24, SpO2 ≥94% on room air, tolerating oral intake. Total course: 5-7 days (uncomplicated). CXR follow-up at 6-8 weeks in smokers >50 yr to exclude malignancy."))
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════
# 10. ASTHMA
# ═══════════════════════════════════════════════════════════════════
story.append(topic_header("ASTHMA", 10))
story.append(Spacer(1, 4))
story.append(section_box("HISTORY"))
for b in ["Recurrent episodes of wheeze, breathlessness, chest tightness, cough",
"Nocturnal/early morning worsening (hallmark)",
"Triggers: dust, pollen, cold air, exercise, NSAIDS, beta-blockers, stress, URI",
"Diurnal variation: PEF worse in morning",
"Personal/family history of atopy: allergic rhinitis, eczema, food allergy",
"Occupational exposure (baker's asthma, isocyanates)",
"Symptom frequency per week, night waking, activity limitation",
"Current medications, previous hospitalisations/ICU admissions"]:
story.append(Paragraph(f"• {b}", BULLET))
story.append(section_box("GINA 2024 CLASSIFICATION"))
story.append(inv_table([
["Intermittent", "Symptoms <2 days/wk, no night symptoms, PEF ≥80% predicted, variability <20%"],
["Mild persistent", "Symptoms >2 days/wk but <daily, 1-2 night/month, PEF ≥80%"],
["Moderate persistent", "Daily symptoms, >1 night/wk, PEF 60-80%, variability 20-30%"],
["Severe persistent", "Continuous symptoms, frequent night symptoms, PEF <60%"],
]))
story.append(Spacer(1, 4))
story.append(section_box("INVESTIGATIONS"))
story.append(inv_table([
["Spirometry (FEV1/FVC)", "Obstruction: FEV1/FVC <0.7; Reversibility: ↑FEV1 ≥12% and ≥200mL post-salbutamol"],
["Peak Expiratory Flow (PEF)", "Diurnal variability >20% supports diagnosis"],
["CXR", "Hyperinflation; rule out pneumothorax, infection"],
["FeNO (Fractional exhaled NO)", ">25 ppb → eosinophilic airway inflammation"],
["Skin prick test / Specific IgE", "Identify allergen triggers"],
["CBC", "Eosinophilia in atopic asthma"],
["Sputum eosinophils", "Type 2 inflammation; guides biologic therapy"],
["ABG (in acute attack)", "PaCO2 normal/↑ = impending respiratory failure"],
]))
story.append(Spacer(1, 4))
story.append(section_box("GINA STEPWISE TREATMENT LADDER"))
story.append(inv_table([
["Step 1 (intermittent)", "Low-dose ICS-formoterol as needed (SMART preferred) OR SABA PRN"],
["Step 2 (mild persistent)", "Daily low-dose ICS + SABA PRN; or low-dose ICS-formoterol PRN"],
["Step 3 (moderate persistent)", "Low-dose ICS + LABA daily; or medium-dose ICS"],
["Step 4 (severe)", "Medium-high dose ICS + LABA; refer specialist"],
["Step 5 (add-ons)", "LAMA (tiotropium), LTRA (montelukast), Anti-IL5 biologics (mepolizumab, benralizumab)"],
]))
story.append(Spacer(1, 4))
story.append(section_box("PRESCRIPTION"))
story.append(rx_table([
["Inhaler: Budesonide/Formoterol (ICS/LABA)", "160/4.5 mcg", "1-2 puffs twice daily + PRN", "Maintenance (steps 3-4)"],
["Inhaler: Salbutamol MDI (SABA)", "100 mcg", "2 puffs every 4-6 hrs PRN", "Reliever"],
["Tab. Montelukast (LTRA)", "10 mg", "Once at night", "Add-on / allergic rhinitis"],
["Tab. Prednisolone (acute exacerb.)", "40-50 mg", "Once daily morning", "5 days (exacerbation)"],
["Spacer device", "—", "Always use with MDI", "Improved delivery"],
]))
story.append(Spacer(1, 3))
story.append(note_box("Inhaler technique must be checked and demonstrated at every visit. Spacer improves drug delivery by 20-30%. Review step therapy every 3 months — step down if controlled for ≥3 months. Written Asthma Action Plan for all patients."))
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════
# 11. COPD
# ═══════════════════════════════════════════════════════════════════
story.append(topic_header("CHRONIC OBSTRUCTIVE PULMONARY DISEASE (COPD)", 11))
story.append(Spacer(1, 4))
story.append(section_box("HISTORY"))
for b in ["Chronic productive cough (>3 months/year x2 consecutive years = chronic bronchitis)",
"Progressive exertional dyspnoea — MRC dyspnoea scale",
"Wheeze (less prominent than asthma)",
"Smoking history: pack-years (1 pack/day x1 year = 1 pack-year; significant ≥10 pack-years)",
"Biomass fuel exposure (cooking smoke — women in developing countries)",
"Recurrent respiratory infections",
"Weight loss (severe COPD — pink puffer/barrel chest)",
"Peripheral oedema, cyanosis (cor pulmonale in severe COPD)",
"Medications: inhaler technique, adherence, previous exacerbations"]:
story.append(Paragraph(f"• {b}", BULLET))
story.append(section_box("GOLD 2024 CLASSIFICATION"))
story.append(inv_table([
["GOLD 1 (Mild)", "FEV1 ≥80% predicted"],
["GOLD 2 (Moderate)", "FEV1 50-79%"],
["GOLD 3 (Severe)", "FEV1 30-49%"],
["GOLD 4 (Very Severe)", "FEV1 <30%"],
["ABE Groups", "A = low symptoms, low risk; B = high symptoms, low risk; E = high exacerbation risk"],
]))
story.append(Spacer(1, 4))
story.append(section_box("INVESTIGATIONS"))
story.append(inv_table([
["Spirometry (post-bronchodilator)", "FEV1/FVC <0.7 confirms obstruction; not fully reversible"],
["CXR", "Hyperinflation, flat diaphragm, bullae, barrel chest"],
["HRCT chest", "Emphysema extent, bronchiectasis, bullae"],
["6-Minute Walk Test (6MWT)", "Exercise capacity, prognosis"],
["ABG", "Hypoxaemia (PaO2 <60 → LTOT indication), hypercapnia"],
["CBC", "Polycythaemia (chronic hypoxia); anaemia exacerbates symptoms"],
["Echo", "Cor pulmonale — RV hypertrophy, TR, PAH"],
["Alpha-1 antitrypsin level", "Young (<45 yr), non-smoker with COPD"],
["Sputum C/S (during exacerbation)", "H. influenzae, Moraxella, Pseudomonas"],
["mMRC / CAT score", "Symptom burden — guides pharmacotherapy group"],
]))
story.append(Spacer(1, 4))
story.append(section_box("PRESCRIPTION — STABLE COPD"))
story.append(rx_table([
["Inhaler: Tiotropium (LAMA)", "18 mcg", "1 cap via HandiHaler once daily", "Group B/E (backbone)"],
["Inhaler: Indacaterol/Glycopyrronium (LABA/LAMA)", "110/50 mcg", "1 puff once daily", "Preferred combo"],
["Inhaler: Budesonide/Formoterol (ICS/LABA)", "160/4.5 mcg", "1-2 puffs twice daily", "Group E + eosinophils >300"],
["Inhaler: Salbutamol MDI (SABA)", "100 mcg", "2 puffs every 4-6 hrs PRN", "Reliever"],
["Tab. Roflumilast (PDE4i)", "500 mcg", "Once daily with food", "Severe COPD + chronic bronchitis"],
["Tab. Azithromycin", "250 mg", "3 times/week", "Frequent exacerbators (non-smokers)"],
]))
story.append(Spacer(1, 3))
story.append(note_box("Smoking cessation is the SINGLE most effective intervention — reduces FEV1 decline. Pulmonary rehabilitation improves exercise capacity even in severe COPD. Long-term O2 therapy (LTOT) if PaO2 <55 mmHg or <60 mmHg with cor pulmonale — minimum 15 hrs/day. Annual influenza vaccine; one-time pneumococcal vaccine."))
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════
# 12. EPILEPSY
# ═══════════════════════════════════════════════════════════════════
story.append(topic_header("EPILEPSY", 12))
story.append(Spacer(1, 4))
story.append(section_box("HISTORY"))
for b in ["Description of episode: witness account essential",
"Onset: sudden vs gradual; aura (visual, olfactory, déjà vu — focal onset)",
"Semiology: tonic-clonic jerks, head/eye deviation, automatisms (lip-smacking, hand fumbling)",
"Duration of ictus and post-ictal period (confusion, Todd's paresis — lateralises focus)",
"Loss of consciousness, tongue bite, urinary incontinence",
"Frequency, clustering, diurnal pattern (nocturnal → frontal lobe)",
"Triggers: sleep deprivation, alcohol, flashing lights, stress, fever (febrile in children)",
"Birth history, head injury, CNS infection, febrile seizures, family history",
"Current medications and adherence"]:
story.append(Paragraph(f"• {b}", BULLET))
story.append(section_box("SEIZURE CLASSIFICATION (ILAE 2017)"))
story.append(inv_table([
["Focal onset aware (simple partial)", "Consciousness preserved; aura, Jacksonian march"],
["Focal onset impaired awareness (complex partial)", "Consciousness impaired; automatisms"],
["Focal to bilateral tonic-clonic", "Previously called secondary generalised"],
["Generalised onset tonic-clonic (GTCS)", "Bilateral from onset; no aura"],
["Absence seizures", "Blank stare 5-30 sec; 3Hz spike-wave on EEG; children"],
["Myoclonic seizures", "Brief jerks; morning predominance (JME)"],
]))
story.append(Spacer(1, 4))
story.append(section_box("INVESTIGATIONS"))
story.append(inv_table([
["EEG (interictal)", "Epileptiform discharges; activate with hyperventilation, photic stimulation, sleep"],
["MRI brain (preferred over CT)", "Structural cause: tumour, hippocampal sclerosis, cortical dysplasia, AVM"],
["CT brain (urgent)", "Acute seizure: exclude haemorrhage, space-occupying lesion"],
["CBC, LFT, RFT, electrolytes", "Metabolic causes: hyponatraemia, hypoglycaemia, hepatic encephalopathy"],
["Blood glucose (fingerprick)", "Hypoglycaemia — always exclude first"],
["CSF analysis", "If CNS infection suspected (meningitis/encephalitis)"],
["Anti-epileptic drug levels", "Phenytoin, valproate, carbamazepine — toxicity/compliance monitoring"],
]))
story.append(Spacer(1, 4))
story.append(section_box("PRESCRIPTION — AED BY SEIZURE TYPE"))
story.append(rx_table([
["Tab. Sodium Valproate", "500 mg-1 g/day", "Twice daily", "GTCS, absence, myoclonic (avoid pregnancy)"],
["Tab. Levetiracetam", "500 mg-1.5 g", "Twice daily", "All seizure types; safe in pregnancy"],
["Tab. Carbamazepine", "200-400 mg", "Twice daily (with food)", "Focal seizures (not absence)"],
["Tab. Lamotrigine", "25-200 mg (slow titrate)", "Twice daily", "Focal + generalised; safe in pregnancy"],
["Tab. Clobazam", "10 mg", "Once at night / twice daily", "Add-on; catamenial epilepsy"],
["Tab. Topiramate", "25-100 mg", "Twice daily", "Focal + generalised; weight loss benefit"],
]))
story.append(Spacer(1, 3))
story.append(note_box("Never stop AED abruptly — taper over weeks. Driving restrictions apply (inform patient). Contraception advice — enzyme-inducing AEDs (CBZ, PHT) reduce OCP efficacy. Pregnancy: take folic acid 5 mg/day. VPA teratogenic — avoid in women of childbearing potential (UK MHRA 2024)."))
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════
# 13. HEADACHE
# ═══════════════════════════════════════════════════════════════════
story.append(topic_header("HEADACHE", 13))
story.append(Spacer(1, 4))
story.append(section_box("HISTORY — RED FLAGS (SNOOP4)"))
for b in ["S — Systemic symptoms (fever, weight loss, night sweats → infection/malignancy/vasculitis)",
"N — Neurological signs (focal deficits, altered consciousness → SOL, stroke)",
"O — Onset sudden/thunderclap (worst headache ever, maximal at onset → SAH until proven otherwise)",
"O — Older age (>50 new headache → GCA, tumour)",
"P — Positional change (worse lying flat → ↑ICP; worse standing → CSF leak)",
"P — Papilloedema (↑ICP)",
"P — Progressive worsening headache",
"P — Precipitated by Valsalva (cough/sneeze → Chiari, posterior fossa lesion)"]:
story.append(Paragraph(f"• {b}", BULLET))
story.append(section_box("HEADACHE DIFFERENTIAL"))
story.append(inv_table([
["Migraine", "Unilateral, pulsating, moderate-severe, 4-72 hrs; nausea/vomiting, photo/phonophobia; aura (visual zig-zag 20-30 min before)"],
["Tension-type headache (TTH)", "Bilateral, pressing/tightening, mild-moderate, hours to days; no nausea; no photophobia/phonophobia"],
["Cluster headache", "Unilateral periorbital/temporal excruciating pain, 15-180 min; ipsilateral autonomic: lacrimation, rhinorrhoea, Horner's; male predominance; restlessness"],
["Subarachnoid haemorrhage", "Thunderclap onset, worst ever, neck stiffness, photophobia, reduced GCS → CT brain urgently"],
["Raised ICP headache", "Morning headache worse on lying, vomiting, papilloedema → tumour/hydrocephalus/SOL"],
["Meningitis", "Fever + headache + neck stiffness; Kernig's/Brudzinski's positive; photophobia"],
["GCA (>50 yr)", "Temporal headache, jaw claudication, ESR >50, scalp tenderness; risk of blindness"],
]))
story.append(Spacer(1, 4))
story.append(section_box("INVESTIGATIONS (if red flags present)"))
story.append(inv_table([
["CT brain (non-contrast urgent)", "SAH, haemorrhage, space-occupying lesion"],
["LP (after CT)", "SAH: xanthochromia after 12 hrs; Meningitis: WBCs, protein, glucose, C/S"],
["MRI brain + MRA", "Preferred for migraineurs; vascular malformations, pituitary lesions"],
["ESR + CRP + platelets", "Giant cell arteritis (GCA) workup"],
["Temporal artery biopsy", "Gold standard for GCA"],
]))
story.append(Spacer(1, 4))
story.append(section_box("PRESCRIPTION — MIGRAINE"))
story.append(Paragraph("<b>Acute Attack:</b>", BODY))
story.append(rx_table([
["Tab. Sumatriptan", "50-100 mg", "At onset; repeat after 2 hrs if needed (max 200 mg/day)", "Acute migraine"],
["Tab. Ibuprofen", "400-600 mg", "With food at onset", "Mild-moderate attack"],
["Tab. Naproxen sodium", "550 mg", "At onset; repeat after 1 hr (max 1100 mg/day)", "Alternative NSAID"],
["Tab. Domperidone / Metoclopramide", "10 mg", "At onset (antiemetic)", "Nausea control"],
]))
story.append(Spacer(1, 3))
story.append(Paragraph("<b>Migraine Prophylaxis (≥4 attacks/month or prolonged attacks):</b>", BODY))
story.append(rx_table([
["Tab. Propranolol", "40-80 mg", "Twice daily", "First-line prophylaxis"],
["Tab. Amitriptyline", "10-25 mg", "Once at night", "Comorbid depression/TTH"],
["Tab. Topiramate", "25-100 mg", "Twice daily (titrate slowly)", "Weight loss benefit"],
["Tab. Sodium Valproate", "500-1000 mg", "Twice daily", "Avoid in pregnancy/women of childbearing age"],
]))
story.append(Spacer(1, 3))
story.append(note_box("Medication overuse headache (MOH): analgesics used >10 days/month for ≥3 months → rebound headache. Treat by withdrawing offending analgesic. Headache diary helps track frequency, triggers, medication use."))
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════
# 14. VERTIGO
# ═══════════════════════════════════════════════════════════════════
story.append(topic_header("VERTIGO", 14))
story.append(Spacer(1, 4))
story.append(section_box("HISTORY — KEY DIFFERENTIATING FEATURES"))
story.append(inv_table([
["BPPV", "Brief (seconds to 1-2 min), triggered by head position change (turning in bed, looking up). No hearing loss. Most common."],
["Vestibular Neuritis", "Sudden severe prolonged vertigo (days), nausea/vomiting, no hearing loss, preceded by URTI"],
["Meniere's Disease", "Episodic vertigo (20 min - 24 hrs) + sensorineural hearing loss + tinnitus + aural fullness (tetrad)"],
["Acoustic Neuroma (VS)", "Progressive unilateral SNHL + tinnitus ± facial numbness; slow onset vertigo"],
["Central Vertigo (brainstem/cerebellum)", "Continuous, less severe spinning; prominent diplopia, dysphagia, ataxia, facial weakness — EMERGENCY"],
]))
story.append(Spacer(1, 4))
story.append(section_box("DIZZINESS HISTORY"))
for b in ["Nature: true vertigo (room spinning) vs presyncope vs disequilibrium vs non-specific dizziness",
"Duration of individual episode; onset (acute/gradual/positional)",
"Associated: nausea, vomiting, tinnitus, hearing loss (peripheral vs central clue)",
"Neurological symptoms: diplopia, dysarthria, dysphagia, facial numbness, limb weakness (brainstem)",
"Recent viral illness (vestibular neuritis)",
"Medications: aminoglycosides (gentamicin — vestibulotoxic), loop diuretics, antiepileptics, antihypertensives (postural hypotension)"]:
story.append(Paragraph(f"• {b}", BULLET))
story.append(section_box("EXAMINATION + INVESTIGATIONS"))
story.append(inv_table([
["Dix-Hallpike test", "BPPV: upbeat torsional nystagmus with latency, fatigable, geotropic"],
["HINTS exam (Head Impulse, Nystagmus, Test of Skew)", "Differentiates central vs peripheral (HINTS+ = central)"],
["Pure tone audiogram (PTA)", "Meniere's: low-frequency SNHL; acoustic neuroma: unilateral SNHL"],
["MRI brain + IAM (FLAIR + DWI)", "Central cause (cerebellar infarct, MS plaque, acoustic neuroma); DWI for acute stroke"],
["Electronystagmography (ENG)", "Vestibular function assessment"],
["BP lying and standing", "Postural hypotension — most common in elderly"],
["ECG / Holter", "Cardiac arrhythmia as cause of presyncope/dizziness"],
]))
story.append(Spacer(1, 4))
story.append(section_box("PRESCRIPTION"))
story.append(Paragraph("<b>Acute Vertigo (Symptomatic):</b>", BODY))
story.append(rx_table([
["Tab. Cinnarizine", "25 mg", "3 times daily", "Acute vestibular episodes"],
["Tab. Betahistine", "16-24 mg", "3 times daily with food", "Meniere's disease (prophylaxis)"],
["Tab. Prochlorperazine", "5-10 mg", "3 times daily", "Acute nausea/vomiting with vertigo"],
["Tab. Diazepam", "2-5 mg", "2-3 times daily (short-term)", "Acute severe vertigo only"],
["Vestibular rehabilitation exercises", "—", "Daily (Brandt-Daroff)", "BPPV + vestibular neuritis"],
]))
story.append(Spacer(1, 3))
story.append(note_box("Epley manoeuvre (canalith repositioning) is the treatment of choice for posterior canal BPPV — success rate >90%. Refer if: neurological signs present (central cause), unilateral SNHL + tinnitus (acoustic neuroma), recurrent Meniere's not responding to betahistine."))
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════
# 15. GOUT
# ═══════════════════════════════════════════════════════════════════
story.append(topic_header("GOUT", 15))
story.append(Spacer(1, 4))
story.append(section_box("HISTORY"))
for b in ["Sudden onset severe joint pain, typically at night",
"First MTP joint most common (podagra — 50% first attack)",
"Joint: hot, red, swollen, exquisitely tender (cannot bear sheet touching it)",
"Triggers: alcohol (especially beer/spirits), red meat, seafood, fructose-rich drinks, dehydration, surgery, trauma, diuretics, aspirin",
"Previous attacks — frequency, joints involved",
"Tophi: ears, elbows, Achilles tendon (chronic tophaceous gout)",
"Associated: hypertension, DM, CKD, obesity, metabolic syndrome",
"Medications: diuretics (thiazide/loop), low-dose aspirin, cyclosporine, pyrazinamide (all ↑uric acid)"]:
story.append(Paragraph(f"• {b}", BULLET))
story.append(section_box("INVESTIGATIONS"))
story.append(inv_table([
["Serum uric acid", "Often normal during acute attack; >6.8 mg/dL = hyperuricaemia"],
["Joint aspirate (gold standard)", "Negatively birefringent needle-shaped monosodium urate (MSU) crystals"],
["X-ray affected joint", "Acute: soft tissue swelling; Chronic: 'punched-out' erosions with overhanging edge"],
["Ultrasound joint", "Double contour sign (urate over cartilage), tophi, power Doppler for inflammation"],
["DECT (Dual-energy CT)", "Highly sensitive for urate deposits; not routine"],
["CBC, CRP, ESR", "Elevated during acute attack — septic arthritis must be excluded"],
["Urine uric acid (24 hr)", "Overproducer vs underexcretor — guides ULT choice"],
["Renal function + eGFR", "Urate nephropathy; adjust allopurinol dose with CKD"],
]))
story.append(Spacer(1, 4))
story.append(section_box("PRESCRIPTION — ACUTE GOUT"))
story.append(rx_table([
["Tab. Colchicine", "1 mg stat then 0.5 mg after 1 hr", "Then 0.5 mg twice daily", "First-line; start within 12 hrs of attack"],
["Tab. Naproxen", "750 mg stat, then 250 mg", "3 times daily", "7-10 days (if no CKD/GI risk)"],
["Tab. Indomethacin", "50 mg", "3 times daily with food", "5-7 days"],
["Tab. Prednisolone", "30-40 mg", "Once daily tapering over 7-10 days", "If NSAIDs/colchicine contraindicated"],
]))
story.append(Spacer(1, 3))
story.append(Paragraph("<b>Urate-Lowering Therapy (ULT) — start 2-4 weeks AFTER acute attack resolves:</b>", BODY))
story.append(rx_table([
["Tab. Allopurinol", "100 mg/day (start low)", "Once daily; titrate by 100mg/4-weekly", "Target SUA <6 mg/dL; <5 if tophi"],
["Tab. Febuxostat", "40-80 mg", "Once daily", "If allopurinol intolerant; avoid in CVD"],
["Tab. Colchicine (prophylaxis)", "0.5 mg", "Twice daily", "First 3-6 months of ULT (to prevent flares)"],
]))
story.append(Spacer(1, 3))
story.append(note_box("Do NOT start allopurinol during an acute attack. Test for HLA-B*5801 before starting allopurinol in South-East Asian patients (Korean/Thai/Han Chinese) — risk of severe cutaneous reactions (SJS/DRESS). Dietary advice: avoid offal, beer, spirits, fructose. Low-fat dairy products may be protective."))
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════
# 16. OSTEOARTHRITIS
# ═══════════════════════════════════════════════════════════════════
story.append(topic_header("OSTEOARTHRITIS", 16))
story.append(Spacer(1, 4))
story.append(section_box("HISTORY"))
for b in ["Joint pain — worse with activity, better with rest (opposite of RA)",
"Morning stiffness <30 min (RA: >1 hour)",
"Joints most commonly affected: knees, hips, DIPs, PIPs, 1st CMC (thumb base), spine (OA spondylosis)",
"Crepitus on movement",
"Limitation of range of motion, difficulty stairs/squatting",
"Bony enlargement: Heberden's nodes (DIP), Bouchard's nodes (PIP)",
"Risk factors: age, female sex, obesity, previous joint injury, occupational stress, genetic",
"Inflammatory features that suggest RA/crystal arthritis: warm swollen joints, elevated ESR/CRP, bilateral symmetric"]:
story.append(Paragraph(f"• {b}", BULLET))
story.append(section_box("INVESTIGATIONS"))
story.append(inv_table([
["X-ray of affected joint", "Classic OA: joint space narrowing, subchondral sclerosis, osteophytes, subchondral cysts"],
["CBC, ESR, CRP", "Usually normal in OA (elevated → inflammatory arthritis)"],
["Rheumatoid factor (RF) + anti-CCP", "Exclude RA"],
["Serum uric acid", "Exclude gout"],
["MRI joint", "Early cartilage loss, bone marrow oedema, meniscal tears (knee OA)"],
["Joint aspirate (if effusion)", "Exclude septic arthritis; OA fluid: non-inflammatory (<2000 WBCs)"],
["BMI + vitamin D level", "Obesity management; Vit D deficiency worsens pain"],
]))
story.append(Spacer(1, 4))
story.append(section_box("MANAGEMENT — NON-PHARMACOLOGICAL (FIRST-LINE)"))
for b in ["Weight loss — most effective intervention for knee OA (10% weight loss = significant symptom improvement)",
"Physiotherapy: quadriceps strengthening, range of motion exercises",
"Occupational therapy: joint protection techniques, assistive devices (walking stick — contralateral hand)",
"TENS, warm/cold packs, massage",
"Patient education: self-management, activity pacing"]:
story.append(Paragraph(f"• {b}", BULLET))
story.append(section_box("PRESCRIPTION"))
story.append(rx_table([
["Tab. Paracetamol", "500-1000 mg", "Every 6-8 hrs (max 4g/day)", "First-line oral analgesic"],
["Tab. Ibuprofen / Naproxen", "400 mg / 250-500 mg", "With food, twice-thrice daily", "Step 2; use lowest dose, shortest duration"],
["Tab. Celecoxib (COX-2 inhibitor)", "100-200 mg", "Once or twice daily", "If GI risk; avoid in CVD"],
["Topical Diclofenac gel 1%", "Apply 4 cm strip", "3-4 times daily", "Knee/hand OA — safer than oral NSAID"],
["Intra-articular Triamcinolone", "40 mg injection", "Once every 3 months (max)", "Acute flare with effusion"],
["Intra-articular Hyaluronic acid", "2 mL injection weekly x3", "Series of injections", "Moderate OA (viscosupplementation)"],
["Tab. Duloxetine", "30-60 mg", "Once daily", "Chronic pain, central sensitisation"],
["Tab. Cholecalciferol (Vit D3)", "60,000 IU weekly x8", "Then 60,000 IU monthly", "If Vit D deficient"],
["Glucosamine + Chondroitin", "1500 mg + 1200 mg", "Once daily", "Adjunct (moderate evidence)"],
]))
story.append(Spacer(1, 3))
story.append(note_box("Opioids are NOT recommended for OA. Refer to orthopaedics for total knee/hip replacement when: severe pain not controlled with pharmacotherapy, significant functional limitation, radiographic bone-on-bone OA. PPI gastroprotection mandatory if NSAID prescribed to >65 yr, H. pylori positive, or concurrent steroid/anticoagulant use."))
story.append(Spacer(1, 4))
story.append(HRFlowable(width="100%", thickness=1, color=ACCENT))
story.append(Spacer(1, 3))
story.append(Paragraph("Vol 1 — Medicine OPD | Structured Case Notes + Prescription Format | July 2026", SMALL))
# ─── BUILD ────────────────────────────────────────────────────────────────────
doc.build(story)
print(f"PDF generated: {OUTPUT}")
Failed to create session: bad request: failed to resolve container IP after 3 attempts: no IP address found. Is the Sandbox started?
We encountered an error while processing your request. Please try again or reach out to us for help.
Why not proceeding and generating
Proceed and generate