Write about opd pt cases with their prescriptions for practice and education purposes also give reasons why are we prescribing it and make it in a pdf form
mkdir -p /home/daytona/workspace/opd-cases && ls /home/daytona/workspace/
~/opd-cases/generate_opd_pdf.py
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import cm
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether, PageBreak
)
from reportlab.platypus import Flowable
from reportlab.lib.colors import HexColor
import datetime
# ── Colour palette ────────────────────────────────────────────────────────────
NAVY = HexColor("#1a3a5c")
TEAL = HexColor("#0d7377")
LIGHT_TEAL = HexColor("#e8f7f8")
GOLD = HexColor("#e8a020")
LIGHT_GOLD = HexColor("#fdf4e3")
LIGHT_GREY = HexColor("#f4f6f9")
MID_GREY = HexColor("#d0d7e2")
RED_SOFT = HexColor("#c0392b")
GREEN_SOFT = HexColor("#1e8449")
WHITE = colors.white
PAGE_W, PAGE_H = A4
# ── Document ──────────────────────────────────────────────────────────────────
OUTPUT = "/home/daytona/workspace/opd-cases/OPD_Patient_Cases_Educational.pdf"
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
leftMargin=2*cm, rightMargin=2*cm,
topMargin=2.5*cm, bottomMargin=2.5*cm,
title="OPD Patient Cases – Educational Prescriptions",
author="Medical Education Unit",
subject="Clinical Practice & Pharmacology"
)
# ── Styles ────────────────────────────────────────────────────────────────────
base = getSampleStyleSheet()
def S(name, **kw):
return ParagraphStyle(name, parent=base["Normal"], **kw)
sTitle = S("sTitle", fontSize=26, textColor=WHITE, alignment=TA_CENTER,
fontName="Helvetica-Bold", leading=32)
sSubTitle = S("sSubTitle", fontSize=12, textColor=LIGHT_TEAL, alignment=TA_CENTER,
fontName="Helvetica", leading=16)
sDate = S("sDate", fontSize=9, textColor=LIGHT_GOLD, alignment=TA_CENTER,
fontName="Helvetica-Oblique")
sCaseNum = S("sCaseNum", fontSize=14, textColor=WHITE, fontName="Helvetica-Bold",
alignment=TA_LEFT, leading=18)
sCaseTitle = S("sCaseTitle", fontSize=11, textColor=LIGHT_TEAL, fontName="Helvetica",
alignment=TA_LEFT, leading=14)
sSection = S("sSection", fontSize=10, textColor=NAVY, fontName="Helvetica-Bold",
spaceAfter=3, leading=14)
sBody = S("sBody", fontSize=9.5, textColor=HexColor("#2c3e50"),
fontName="Helvetica", leading=14, spaceAfter=2)
sBullet = S("sBullet", fontSize=9.5, textColor=HexColor("#2c3e50"),
fontName="Helvetica", leading=14, leftIndent=14, spaceAfter=1,
bulletIndent=4)
sReason = S("sReason", fontSize=9.5, textColor=HexColor("#1a5276"),
fontName="Helvetica-Oblique", leading=14, leftIndent=14, spaceAfter=1)
sWarning = S("sWarning", fontSize=8.5, textColor=RED_SOFT,
fontName="Helvetica-Bold", leading=12, leftIndent=14)
sGreen = S("sGreen", fontSize=8.5, textColor=GREEN_SOFT,
fontName="Helvetica-Bold", leading=12, leftIndent=14)
sFooterNote = S("sFooterNote", fontSize=7.5, textColor=HexColor("#7f8c8d"),
fontName="Helvetica-Oblique", alignment=TA_CENTER)
sTocEntry = S("sTocEntry", fontSize=10, textColor=NAVY, fontName="Helvetica", leading=16)
# ── Helper: coloured banner ───────────────────────────────────────────────────
class ColourBanner(Flowable):
def __init__(self, bg, height=1.4*cm, radius=8):
super().__init__()
self.bg = bg
self.height = height
self.radius = radius
def wrap(self, aw, ah):
self.width = aw
return aw, self.height
def draw(self):
c = self.canv
c.setFillColor(self.bg)
c.roundRect(0, 0, self.width, self.height,
radius=self.radius, stroke=0, fill=1)
def case_header(num, title, subtitle=""):
banner = ColourBanner(NAVY, height=1.55*cm)
items = [banner]
# overlay text using a table over the banner via absolute positioning trick:
# instead, place text directly after banner via a negative spacer trick –
# simplest: use a 1-row table
header_data = [[
Paragraph(f"CASE {num}", sCaseNum),
Paragraph(title, sCaseTitle)
]]
t = Table(header_data, colWidths=[2.8*cm, None])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), NAVY),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("LEFTPADDING",(0,0), (0,0), 12),
("LEFTPADDING",(1,0), (1,0), 6),
("TOPPADDING", (0,0), (-1,-1), 10),
("BOTTOMPADDING",(0,0),(-1,-1),10),
("ROUNDEDCORNERS", [8]),
]))
return [t]
def section_label(text, icon=""):
return Paragraph(f"{icon} {text}" if icon else text, sSection)
def body(text):
return Paragraph(text, sBody)
def bullet(text):
return Paragraph(f"• {text}", sBullet)
def reason(text):
return Paragraph(f"↳ {text}", sReason)
def warn(text):
return Paragraph(f"⚠ {text}", sWarning)
def ok(text):
return Paragraph(f"✔ {text}", sGreen)
def gap(h=0.25):
return Spacer(1, h*cm)
def hr(color=MID_GREY, thickness=0.5):
return HRFlowable(width="100%", thickness=thickness, color=color, spaceAfter=4, spaceBefore=4)
def prescription_table(rows):
"""rows = list of (Drug, Dose/Route, Frequency, Duration)"""
header = ["Drug", "Dose / Route", "Frequency", "Duration"]
data = [header] + rows
col_w = [5.8*cm, 3.8*cm, 3.2*cm, 2.4*cm]
t = Table(data, colWidths=col_w, repeatRows=1)
t.setStyle(TableStyle([
# header
("BACKGROUND", (0,0), (-1,0), TEAL),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,0), 9),
("ALIGN", (0,0), (-1,0), "CENTER"),
# body
("FONTNAME", (0,1), (-1,-1), "Helvetica"),
("FONTSIZE", (0,1), (-1,-1), 9),
("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, LIGHT_TEAL]),
("ALIGN", (1,1), (-1,-1), "CENTER"),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING",(0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (0,-1), 8),
("GRID", (0,0), (-1,-1), 0.4, MID_GREY),
("ROUNDEDCORNERS",[4]),
]))
return t
def info_table(pairs):
"""pairs = [(label, value), ...] – patient info block"""
data = pairs
col_w = [3.8*cm, 11.6*cm]
t = Table(data, colWidths=col_w)
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (0,-1), LIGHT_GREY),
("FONTNAME", (0,0), (0,-1), "Helvetica-Bold"),
("FONTNAME", (1,0), (1,-1), "Helvetica"),
("FONTSIZE", (0,0), (-1,-1), 9),
("TEXTCOLOR", (0,0), (0,-1), NAVY),
("TEXTCOLOR", (1,0), (1,-1), HexColor("#2c3e50")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING",(0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 8),
("GRID", (0,0), (-1,-1), 0.3, MID_GREY),
("ROWBACKGROUNDS",(0,0),(-1,-1), [WHITE, LIGHT_GREY]),
]))
return t
# ══════════════════════════════════════════════════════════════════════════════
# CASES DATA
# ══════════════════════════════════════════════════════════════════════════════
CASES = [
# ── CASE 1 ──────────────────────────────────────────────────────────────
{
"num": 1,
"title": "Acute Upper Respiratory Tract Infection (Viral URTI)",
"patient": [
("Name", "Mr. Ravi Sharma"),
("Age / Sex", "34 years / Male"),
("Occupation", "School Teacher"),
("Vitals", "BP 118/76 mmHg | HR 82/min | Temp 38.1°C | SpO₂ 98% (RA)"),
],
"presenting_complaint": "Sore throat, runny nose, mild headache and low-grade fever for 3 days.",
"history": [
"No past medical history of asthma, diabetes, or hypertension.",
"No known drug allergies.",
"Several colleagues with similar symptoms in the past week.",
"Non-smoker, occasional alcohol."
],
"examination": [
"Throat: mildly erythematous, no exudate, no tonsillar enlargement.",
"Cervical lymph nodes: non-tender, not significantly enlarged.",
"Chest: clear on auscultation.",
"Rapid antigen test (Group A Strep): NEGATIVE."
],
"diagnosis": "Viral URTI (Common Cold / Viral Pharyngitis)",
"prescription": [
("Paracetamol 500 mg", "500 mg – Oral", "TDS (if febrile/pain)", "5 days"),
("Cetirizine 10 mg", "10 mg – Oral", "OD at bedtime", "5 days"),
("Normal Saline Nasal Drops", "2 drops each nostril", "QID", "5 days"),
("ORS Sachets", "1 sachet in 200 mL water", "Sip frequently", "PRN"),
],
"reasoning": [
("Paracetamol",
"Antipyretic and analgesic. Reduces fever and relieves sore throat pain. "
"First-line choice in viral illness; safe hepatic metabolism; no renal prostaglandin inhibition concern."),
("Cetirizine",
"Second-generation H1-antihistamine. Reduces rhinorrhoea, nasal congestion, and sneezing "
"without significant sedation. Preferred over first-generation (e.g. chlorphenamine) due to fewer anticholinergic side effects."),
("Saline Nasal Drops",
"Isotonic saline rinses help clear nasal secretions, reduce mucosal oedema, and improve ciliary function. "
"Safe for all ages; no systemic side effects."),
("ORS",
"Fever increases insensible fluid losses. ORS replaces water and electrolytes, preventing dehydration. "
"Glucose-sodium co-transport mechanism ensures efficient intestinal absorption."),
],
"antibiotics_note": "NO antibiotics prescribed – Strep test negative; viral aetiology confirmed. "
"Antibiotic stewardship is essential to prevent resistance.",
"follow_up": "Return if fever >39°C persists beyond 5 days, dyspnoea, severe odynophagia, or rash develops.",
},
# ── CASE 2 ──────────────────────────────────────────────────────────────
{
"num": 2,
"title": "Type 2 Diabetes Mellitus – New Diagnosis",
"patient": [
("Name", "Mrs. Sunita Verma"),
("Age / Sex", "52 years / Female"),
("Occupation", "Housewife"),
("Vitals", "BP 132/84 mmHg | HR 78/min | BMI 29.4 kg/m² | RBS 268 mg/dL"),
],
"presenting_complaint": "Polyuria, polydipsia, and fatigue for 2 months. Incidental high blood sugar on screening.",
"history": [
"Family history of T2DM (mother).",
"No previous diagnosis of diabetes.",
"HbA1c today: 8.9% | FPG: 214 mg/dL.",
"Mild dyslipidaemia on previous lipid panel (LDL 148 mg/dL).",
"No known drug allergies."
],
"examination": [
"Abdomen: soft, non-tender; no hepatomegaly.",
"Peripheral sensation: intact bilaterally.",
"Fundoscopy: no diabetic retinopathy.",
"Foot exam: normal pulses, no ulcers."
],
"diagnosis": "Type 2 Diabetes Mellitus (newly diagnosed) + Overweight",
"prescription": [
("Metformin 500 mg", "500 mg – Oral", "BD (with meals)", "1 month then review"),
("Aspirin 75 mg", "75 mg – Oral", "OD (with breakfast)", "Long-term"),
("Atorvastatin 10 mg", "10 mg – Oral", "OD at bedtime", "Long-term"),
("Multivitamin + Chromium", "1 tab – Oral", "OD", "3 months"),
],
"reasoning": [
("Metformin",
"First-line oral hypoglycaemic agent for T2DM. Works by reducing hepatic glucose output (via AMPK activation) "
"and improving peripheral insulin sensitivity. Weight-neutral, low hypoglycaemia risk, cardiovascular-safe, "
"affordable. Start at 500 mg to minimise GI side effects; titrate to 1000 mg BD after 4 weeks if tolerated."),
("Aspirin 75 mg",
"Low-dose aspirin for primary cardiovascular prevention in a diabetic patient with multiple CV risk factors "
"(age, female sex, dyslipidaemia, overweight). Inhibits COX-1-mediated thromboxane A2 production, "
"reducing platelet aggregation."),
("Atorvastatin",
"All diabetic patients have elevated CV risk and benefit from statin therapy regardless of baseline LDL. "
"Atorvastatin inhibits HMG-CoA reductase, reducing hepatic cholesterol synthesis and upregulating LDL receptors. "
"Bedtime dosing aligns with peak hepatic cholesterol synthesis (overnight)."),
("Multivitamin + Chromium",
"Chromium potentiates insulin receptor signalling. Diabetes increases micronutrient turnover. "
"Supportive role; not a substitute for pharmacological therapy."),
],
"antibiotics_note": None,
"follow_up": "Review in 4 weeks: FPG, symptoms; up-titrate Metformin. HbA1c at 3 months. "
"Annual fundoscopy, urine microalbumin, and foot exam.",
},
# ── CASE 3 ──────────────────────────────────────────────────────────────
{
"num": 3,
"title": "Hypertension – Stage 1 (Newly Diagnosed)",
"patient": [
("Name", "Mr. Anil Kapoor"),
("Age / Sex", "48 years / Male"),
("Occupation", "Software Engineer"),
("Vitals", "BP 154/96 mmHg (confirmed on 3 separate visits) | HR 76/min | BMI 27.1 kg/m²"),
],
"presenting_complaint": "Occasional headaches and dizziness. BP elevated on routine check.",
"history": [
"No DM, no dyslipidaemia.",
"Smokes 5-6 cigarettes/day; sedentary lifestyle.",
"No organ damage on ECG and renal function.",
"No known drug allergies."
],
"examination": [
"Cardiovascular: normal heart sounds, no murmurs.",
"Fundoscopy: grade 1 hypertensive retinopathy (arteriolar narrowing).",
"Kidney function, electrolytes: normal.",
"ECG: normal sinus rhythm, no LVH."
],
"diagnosis": "Essential Hypertension – Stage 1 (no compelling indication)",
"prescription": [
("Amlodipine 5 mg", "5 mg – Oral", "OD (morning)", "1 month then review"),
("Aspirin 75 mg", "75 mg – Oral", "OD (with food)", "Long-term"),
("Lifestyle counselling", "—", "Ongoing", "Lifelong"),
],
"reasoning": [
("Amlodipine",
"Dihydropyridine calcium channel blocker (CCB). First-line for hypertension especially in non-diabetic patients "
"without compelling indications. Relaxes vascular smooth muscle by blocking L-type Ca²⁺ channels, reducing "
"peripheral vascular resistance. Long half-life (30-50 h) allows OD dosing and avoids BP fluctuations. "
"Preferred over beta-blockers as first-line in absence of heart failure, post-MI, or tachyarrhythmia."),
("Aspirin 75 mg",
"CV risk reduction in hypertensive male smoker aged 48. Only given after BP partially controlled "
"(to avoid haemorrhagic stroke risk at high BP). Irreversibly inhibits COX-1 platelets for their lifespan."),
("Lifestyle counselling",
"DASH diet (restrict Na⁺ <2.3 g/day, increase K⁺, Mg²⁺), aerobic exercise 30 min/day × 5 days/week, "
"smoking cessation, weight reduction. Lifestyle changes can reduce SBP by 5-15 mmHg and may avoid or delay "
"need for additional medications."),
],
"antibiotics_note": None,
"follow_up": "Recheck BP in 4 weeks. If BP not at goal (<130/80 mmHg), add ACE inhibitor (Enalapril 5 mg OD). "
"Annual labs: serum creatinine, electrolytes, lipids.",
},
# ── CASE 4 ──────────────────────────────────────────────────────────────
{
"num": 4,
"title": "Acute Gastroenteritis (Probable Viral)",
"patient": [
("Name", "Master Arjun Singh"),
("Age / Sex", "8 years / Male"),
("Weight", "24 kg"),
("Vitals", "BP 96/62 mmHg | HR 106/min | Temp 37.8°C | No dehydration signs"),
],
"presenting_complaint": "Watery diarrhoea (5-6 episodes/day) and vomiting (3 episodes) for 1 day. Mild abdominal cramps.",
"history": [
"Ate street food the previous day. Sibling at home with similar symptoms.",
"Fully vaccinated (Rotavirus given at 6 and 10 weeks).",
"No blood in stool, no high fever.",
"No known drug allergies."
],
"examination": [
"Abdomen: soft, mildly tender periumbilically, no guarding.",
"Hydration: moist mucosae, good capillary refill (<2 sec), skin turgor normal.",
"Stool exam: no RBCs or pus cells; Rotavirus antigen: positive."
],
"diagnosis": "Acute Viral Gastroenteritis (Rotavirus) – No dehydration",
"prescription": [
("ORS (WHO-recommended)", "75 mL/kg over 4 h, then 10 mL/kg per loose stool", "After each loose stool", "Until diarrhoea stops"),
("Zinc 20 mg", "20 mg – Oral", "OD", "14 days"),
("Ondansetron 2 mg", "2 mg – Oral (dissolve on tongue)", "Q8H (if vomiting)", "3 days"),
("Probiotics (Lactobacillus rhamnosus GG)", "1 sachet – Oral", "BD", "5 days"),
],
"reasoning": [
("ORS",
"Cornerstone of gastroenteritis management. WHO low-osmolarity ORS (Na 75 mEq/L, Glucose 75 mmol/L) "
"exploits glucose-sodium co-transport in the gut to replenish fluid and electrolytes. Reduces stool output "
"by 25% vs. standard ORS. Prevents dehydration and avoids IV fluids."),
("Zinc 20 mg",
"WHO & UNICEF recommendation for all children with diarrhoea. Zinc reduces duration of diarrhoea by ~25% "
"and severity by ~30%. Mechanism: maintains intestinal epithelial integrity, enhances immune function, "
"supports mucosal repair. Continue for 14 days to replenish body stores."),
("Ondansetron",
"5-HT3 receptor antagonist. Reduces vomiting, improving oral fluid retention. "
"Evidence supports single/short-course use in paediatric gastroenteritis; avoids IV rehydration admission. "
"Weight-based dose: 0.1-0.15 mg/kg per dose; max 4 mg in children."),
("Probiotics (LGG)",
"Best-evidenced probiotic strain for acute viral gastroenteritis. Competes with pathogens for colonisation, "
"modulates immune response, reduces diarrhoea duration by approximately 1 day. Safe and well-tolerated."),
],
"antibiotics_note": "NO antibiotics – Viral aetiology confirmed. Antibiotics do not treat viral diarrhoea "
"and increase risk of antibiotic-associated diarrhoea and resistance.",
"follow_up": "Return immediately if signs of dehydration (sunken eyes, dry tongue, decreased urine output) "
"or blood in stool appear. Otherwise review in 48 hours.",
},
# ── CASE 5 ──────────────────────────────────────────────────────────────
{
"num": 5,
"title": "Bronchial Asthma – Mild Persistent (Step 2)",
"patient": [
("Name", "Ms. Priya Nair"),
("Age / Sex", "22 years / Female"),
("Occupation", "College Student"),
("Vitals", "BP 110/70 mmHg | HR 88/min | RR 18/min | SpO₂ 97% | Peak Flow: 72% predicted"),
],
"presenting_complaint": "Recurrent episodes of wheeze, chest tightness, and shortness of breath – especially at night and during exercise.",
"history": [
"Symptoms >2 days/week but not daily; nighttime symptoms 2-3 times/month.",
"Family history of atopy (mother: allergic rhinitis).",
"No hospital admissions; no oral steroids required previously.",
"No known drug allergies. Non-smoker."
],
"examination": [
"Chest: bilateral expiratory wheeze on auscultation.",
"No use of accessory muscles, no cyanosis.",
"Spirometry: FEV1/FVC 71% (obstructive pattern); FEV1 reversibility +15% post-salbutamol.",
],
"diagnosis": "Bronchial Asthma – Mild Persistent (GINA Step 2)",
"prescription": [
("Salbutamol MDI 100 mcg", "2 puffs (200 mcg) – Inhaled", "PRN (rescue)", "Ongoing"),
("Budesonide MDI 200 mcg", "1 puff (200 mcg) – Inhaled", "BD (controller)", "3 months min"),
("Montelukast 10 mg", "10 mg – Oral", "OD at bedtime", "3 months"),
("Spacer device", "Use with all MDIs", "Every dose", "Ongoing"),
],
"reasoning": [
("Salbutamol (SABA)",
"Short-Acting Beta-2 Agonist. Relieves acute bronchospasm by activating beta-2 receptors on bronchial "
"smooth muscle, causing cAMP-mediated relaxation within minutes. Used PRN as rescue; not for regular scheduled use alone "
"(increases risk of poor control if used >2 days/week without controller therapy)."),
("Budesonide (ICS)",
"Inhaled Corticosteroid – preferred controller for Step 2 asthma (GINA guidelines). "
"Reduces airway inflammation, decreases mucus production, and lowers bronchial hyper-responsiveness. "
"Low systemic bioavailability minimises side effects. Must be taken daily even when asymptomatic."),
("Montelukast (LTRA)",
"Leukotriene Receptor Antagonist. Add-on therapy for exercise-induced or allergic asthma. "
"Blocks CysLT1 receptors, preventing leukotriene D4-mediated bronchoconstriction and mucus secretion. "
"Also reduces concomitant allergic rhinitis symptoms. Bedtime dosing targets nocturnal symptoms."),
("Spacer device",
"Reduces oropharyngeal deposition of inhaled drug, improves lung delivery, and reduces ICS-related "
"oral candidiasis risk. Essential for correct MDI technique – increases drug delivery to lungs by 30-50%."),
],
"antibiotics_note": None,
"follow_up": "Assess symptom control and inhaler technique at 4 weeks. "
"Step up to GINA Step 3 (ICS/LABA combination) if control inadequate after 3 months.",
},
# ── CASE 6 ──────────────────────────────────────────────────────────────
{
"num": 6,
"title": "Urinary Tract Infection (Uncomplicated Cystitis in Female)",
"patient": [
("Name", "Mrs. Kavitha Reddy"),
("Age / Sex", "29 years / Female"),
("Occupation", "Nurse"),
("Vitals", "BP 116/74 mmHg | HR 80/min | Temp 37.4°C | No CVA tenderness"),
],
"presenting_complaint": "Burning micturition, increased urinary frequency, and lower abdominal discomfort for 2 days. No fever. No flank pain.",
"history": [
"Second episode this year; previous UTI treated with Nitrofurantoin (resolved fully).",
"Not pregnant (urine hCG negative).",
"No DM, no immunosuppression.",
"No known drug allergies."
],
"examination": [
"Suprapubic tenderness: mild.",
"No costovertebral angle tenderness.",
"Urine dipstick: Leucocytes ++, Nitrites + , Blood trace.",
"Urine C&S sent (empirical treatment started)."
],
"diagnosis": "Uncomplicated Urinary Tract Infection (Cystitis)",
"prescription": [
("Nitrofurantoin 100 mg MR", "100 mg – Oral", "BD (with food)", "5 days"),
("Phenazopyridine 100 mg", "100 mg – Oral", "TDS (after meals)", "2 days only"),
("Cranberry extract 400 mg", "400 mg – Oral", "OD", "1 month (prophylaxis)"),
("Adequate fluid intake (>2 L/day)", "—", "Throughout day", "Ongoing"),
],
"reasoning": [
("Nitrofurantoin MR",
"First-line antibiotic for uncomplicated UTI in non-pregnant women. Active against most E. coli and Staphylococcus saprophyticus – the commonest uropathogens. "
"Mechanism: reduced to reactive intermediates by bacterial reductases, damaging DNA, ribosomes, and cell-wall synthesis. "
"Achieves high urinary concentrations; minimal GI flora disruption. MR formulation improves tolerability. "
"Preferred over fluoroquinolones to preserve broad-spectrum agents."),
("Phenazopyridine",
"Urinary analgesic/anaesthetic dye. Provides rapid relief of dysuria, urgency, and frequency by exerting local "
"anaesthetic effect on urothelium. NOTE: Not an antibiotic – use for ≤2 days only. "
"Warn patient: urine turns orange-red (harmless but may stain clothing)."),
("Cranberry extract",
"Proanthocyanidins in cranberry inhibit P-fimbriae of E. coli from adhering to uroepithelial cells. "
"Evidence supports modest reduction in recurrent UTI frequency. Appropriate for a patient with recurrent infections."),
("Fluid intake",
"Flushing effect helps physically remove bacteria from urethra and bladder. Dilutes urine, reducing irritation. "
"Reduces bacterial load in bladder."),
],
"antibiotics_note": "ANTIBIOTIC NOTE: Review C&S result in 48-72 h – adjust if necessary. "
"Fluoroquinolones (e.g. ciprofloxacin) are AVOIDED as first-line due to growing resistance and collateral damage.",
"follow_up": "Review C&S in 48-72 h. Repeat urine dipstick at 1 week post-treatment. "
"If ≥3 UTIs/year, discuss long-term low-dose prophylaxis.",
},
# ── CASE 7 ──────────────────────────────────────────────────────────────
{
"num": 7,
"title": "Iron Deficiency Anaemia",
"patient": [
("Name", "Mrs. Fatima Sheikh"),
("Age / Sex", "31 years / Female"),
("Occupation", "Garment Worker"),
("Vitals", "BP 108/68 mmHg | HR 96/min | Pallor: moderate | Koilonychia present"),
],
"presenting_complaint": "Fatigue, palpitations, shortness of breath on exertion, and brittle nails for 3 months.",
"history": [
"Heavy menstrual bleeding (menorrhagia) for 6+ months.",
"Poor dietary iron intake (vegetarian, low pulse consumption).",
"Hb: 7.8 g/dL | MCV: 64 fL | MCH: 19 pg | Serum ferritin: 6 ng/mL | TIBC: elevated.",
"No GI bleeding symptoms. No prior anaemia treatment."
],
"examination": [
"Pallor: conjunctival, palmar.",
"Koilonychia (spoon-shaped nails) present.",
"Mild tachycardia; no cardiac murmurs.",
"No hepatosplenomegaly."
],
"diagnosis": "Iron Deficiency Anaemia (secondary to menorrhagia + dietary deficiency)",
"prescription": [
("Ferrous sulphate 200 mg", "200 mg elemental Fe 60 mg – Oral", "TDS (before meals)", "3-6 months"),
("Vitamin C (Ascorbic acid) 500 mg", "500 mg – Oral", "TDS (with iron dose)", "3-6 months"),
("Folic acid 5 mg", "5 mg – Oral", "OD", "3 months"),
("Tranexamic acid 500 mg", "500 mg – Oral", "TDS during menstruation", "Each cycle"),
],
"reasoning": [
("Ferrous sulphate",
"Replaces depleted iron stores. Iron is essential for haemoglobin synthesis and mitochondrial electron transport. "
"Ferrous (Fe²⁺) form has superior GI absorption (~10-20%) vs ferric (Fe³⁺). "
"Pre-meal dosing maximises absorption (less interference from phytates/calcium) but TDS on empty stomach "
"may cause GI upset – adjust timing if needed. Target: Hb rise of 1 g/dL per week."),
("Vitamin C",
"Ascorbic acid reduces Fe³⁺ → Fe²⁺ in the gut, maintaining iron in the absorbable form. Also chelates iron "
"in a soluble complex that resists precipitation at alkaline duodenal pH. Co-administration can increase "
"iron absorption by 2-3 fold."),
("Folic acid",
"Co-existing nutritional deficiency common in menorrhagic women with poor diet. Folic acid required for "
"DNA synthesis and RBC maturation (megaloblastic component may co-exist with IDA). Prevents neural tube "
"defects if patient becomes pregnant."),
("Tranexamic acid",
"Antifibrinolytic agent. Inhibits plasminogen activators, preventing clot dissolution. Reduces menstrual blood "
"loss by 30-58% in menorrhagia. Addresses the root cause of iron loss. Taken only during menstruation, "
"limiting systemic thromboembolic risk."),
],
"antibiotics_note": None,
"follow_up": "Recheck Hb and ferritin at 4 weeks. Continue iron for 3 months after Hb normalises (to replenish stores). "
"Refer to gynaecology if menorrhagia persists.",
},
# ── CASE 8 ──────────────────────────────────────────────────────────────
{
"num": 8,
"title": "Peptic Ulcer Disease / Gastritis (H. pylori Positive)",
"patient": [
("Name", "Mr. Deepak Mehta"),
("Age / Sex", "44 years / Male"),
("Occupation", "Journalist"),
("Vitals", "BP 122/78 mmHg | HR 74/min | Temp 36.8°C | No haematemesis"),
],
"presenting_complaint": "Epigastric pain (burning, worse on empty stomach, relieved by food), nausea, and bloating for 6 weeks.",
"history": [
"Regular NSAID use (Ibuprofen 400 mg TDS for chronic back pain).",
"Smokes 10 cigarettes/day; drinks 2-3 cups of coffee daily.",
"H. pylori rapid urease test (RUT) on endoscopy: POSITIVE.",
"OGD findings: duodenal ulcer 0.8 cm with no active bleeding."
],
"examination": [
"Abdomen: epigastric tenderness on deep palpation.",
"No peritoneal signs, no guarding.",
"No pallor, no melaena on rectal exam."
],
"diagnosis": "H. pylori-positive Peptic Ulcer Disease (Duodenal Ulcer)",
"prescription": [
("Omeprazole 20 mg", "20 mg – Oral", "BD (before meals)", "14 days then OD × 4 wks"),
("Clarithromycin 500 mg", "500 mg – Oral", "BD", "14 days"),
("Amoxicillin 1000 mg", "1000 mg – Oral", "BD", "14 days"),
("Sucralfate 1 g", "1 g – Oral", "QID (1 h before meals + HS)", "4 weeks"),
],
"reasoning": [
("Omeprazole (PPI)",
"Proton Pump Inhibitor – irreversibly inhibits H⁺/K⁺-ATPase on parietal cells, reducing gastric acid by >90%. "
"Creates alkaline environment essential for antibiotic efficacy against H. pylori (antibiotics are pH-sensitive). "
"Also promotes ulcer healing by reducing acid-mediated mucosal injury. BD dosing during eradication therapy; "
"reduce to OD for 4 weeks post-eradication for ulcer healing."),
("Clarithromycin + Amoxicillin (Triple Therapy)",
"Standard first-line H. pylori eradication regimen (OAC: Omeprazole + Amoxicillin + Clarithromycin). "
"Clarithromycin (macrolide): inhibits 50S ribosomal subunit, blocking protein synthesis. "
"Amoxicillin (beta-lactam): inhibits transpeptidase, disrupting cell wall synthesis. "
"Together they achieve eradication rates of 70-85%. Dual antibiotic coverage prevents resistance."),
("Sucralfate",
"Cytoprotective agent. At low pH, polymerises to form a viscous paste that adheres selectively to ulcer base, "
"acting as a physical barrier against acid and pepsin. Also stimulates prostaglandin and mucus production. "
"Use for 4 weeks adjunct to PPI for ulcer base healing."),
],
"antibiotics_note": "NSAID CESSATION: Ibuprofen MUST be stopped. NSAIDs inhibit COX-1, reducing cytoprotective "
"prostaglandins in gastric mucosa. Switch back pain management to Paracetamol or discuss with orthopaedics.",
"follow_up": "H. pylori eradication confirmation (urea breath test or stool antigen) 4 weeks after antibiotics completion. "
"Smoking cessation strongly advised. Repeat OGD in 8 weeks if large ulcer or alarm symptoms.",
},
# ── CASE 9 ──────────────────────────────────────────────────────────────
{
"num": 9,
"title": "Hypothyroidism (Newly Diagnosed Overt)",
"patient": [
("Name", "Mrs. Rohini Das"),
("Age / Sex", "38 years / Female"),
("Occupation", "Accountant"),
("Vitals", "BP 124/82 mmHg | HR 58/min | BMI 31.2 kg/m² | Temp 36.1°C"),
],
"presenting_complaint": "Weight gain (8 kg over 6 months), fatigue, constipation, dry skin, cold intolerance, and hair loss.",
"history": [
"TSH: 48.2 mIU/L (↑) | Free T4: 0.52 ng/dL (↓) | Anti-TPO antibodies: 420 IU/mL (↑).",
"Family history: mother has Hashimoto's thyroiditis.",
"No cardiac disease.",
"No known drug allergies. Not pregnant."
],
"examination": [
"Thyroid: diffuse, firm, non-tender goitre (Grade 1).",
"Skin: dry, coarse; non-pitting oedema in pretibial region.",
"Reflexes: delayed relaxation phase (hung-up reflexes).",
"ECG: sinus bradycardia, low-voltage QRS."
],
"diagnosis": "Overt Primary Hypothyroidism – Hashimoto's Thyroiditis",
"prescription": [
("Levothyroxine (T4) 50 mcg", "50 mcg – Oral", "OD (fasting, 30 min before breakfast)", "Lifelong"),
("Calcium / Vitamin D supplement", "500 mg Ca + 400 IU Vit D – Oral", "OD (4 h after Levothyroxine)", "Ongoing"),
],
"reasoning": [
("Levothyroxine",
"Synthetic T4 (thyroxine) – replaces deficient thyroid hormone. Converted peripherally to active T3 by "
"deiodinases. Starting dose 50 mcg is cautious in a 38-year-old (avoids precipitating angina or arrhythmia). "
"Titrate by 12.5-25 mcg every 6-8 weeks targeting TSH 0.5-2.5 mIU/L. "
"Fasting morning administration critical: food (especially calcium, iron, fibre) significantly reduces "
"LT4 absorption by up to 40%. Treatment is lifelong in Hashimoto's."),
("Calcium + Vitamin D",
"Autoimmune thyroid disease is associated with other autoimmune conditions including hypocalcaemia risk. "
"Calcium must be taken ≥4 hours after LT4 to avoid chelation and absorption interference. "
"Vitamin D deficiency is prevalent in hypothyroid patients and can worsen autoimmune activity."),
],
"antibiotics_note": "IMPORTANT INTERACTIONS: Avoid concurrent iron supplements, antacids, calcium within 4 h of LT4. "
"Amiodarone, rifampicin, and oestrogen alter T4 metabolism – review if added.",
"follow_up": "Recheck TSH and free T4 at 6-8 weeks. Titrate dose. Annual TFTs once stable. "
"Screen for associated autoimmune conditions (coeliac disease, T1DM, vitiligo).",
},
# ── CASE 10 ─────────────────────────────────────────────────────────────
{
"num": 10,
"title": "Acute Bacterial Tonsillitis (Group A Streptococcal)",
"patient": [
("Name", "Miss Sana Qureshi"),
("Age / Sex", "16 years / Female"),
("Occupation", "School Student"),
("Vitals", "BP 108/70 mmHg | HR 98/min | Temp 38.9°C | Centor Score: 4/4"),
],
"presenting_complaint": "Severe sore throat, high fever, and difficulty swallowing for 3 days. No cough.",
"history": [
"Centor criteria: exudate on tonsils, anterior cervical lymphadenopathy, fever >38°C, no cough (score 4).",
"Rapid antigen test (RADT) for Group A Streptococcus: POSITIVE.",
"No penicillin allergy. First episode.",
"No rheumatic fever history."
],
"examination": [
"Throat: bilateral tonsillar enlargement with white exudate.",
"Cervical lymph nodes: tender, enlarged bilaterally (anterior chain).",
"No peritonsillar swelling/abscess.",
"No rash (ruling out scarlet fever)."
],
"diagnosis": "Acute Group A Streptococcal Tonsillitis",
"prescription": [
("Phenoxymethylpenicillin (Pen V) 500 mg", "500 mg – Oral", "QID (every 6 h)", "10 days"),
("Paracetamol 500 mg", "500-1000 mg – Oral", "QID PRN", "5-7 days"),
("Ibuprofen 400 mg", "400 mg – Oral", "TDS (with food)", "3-5 days"),
("Chlorhexidine / Benzydamine gargle", "10 mL – Gargle", "TDS", "5 days"),
],
"reasoning": [
("Phenoxymethylpenicillin (Penicillin V)",
"Drug of choice for Group A Streptococcal pharyngitis/tonsillitis. "
"Beta-lactam: inhibits transpeptidase, blocking peptidoglycan cross-linking in bacterial cell wall – bactericidal. "
"GAS remains uniformly sensitive to penicillin (no resistance documented). "
"10-day course essential to eradicate pharyngeal carriage and prevent: (1) rheumatic fever, (2) post-streptococcal "
"glomerulonephritis, (3) peritonsillar abscess. Shorter courses are associated with higher relapse rates."),
("Paracetamol",
"Antipyretic and analgesic via central prostaglandin inhibition and activation of descending serotonergic pathways. "
"Reduces fever and throat pain. Safe, hepatic metabolism. Maximum 4 g/day in adults; avoid in liver disease."),
("Ibuprofen",
"NSAID – inhibits COX-1 and COX-2, reducing prostaglandin synthesis. Provides superior anti-inflammatory and "
"analgesic effect compared to paracetamol alone for exudative tonsillitis. Combination with paracetamol (alternating) "
"provides superior analgesia. Taken with food to prevent gastric irritation."),
("Chlorhexidine / Benzydamine gargle",
"Topical antiseptic (chlorhexidine) reduces bacterial load in oropharynx. Benzydamine is a topical NSAID/local "
"anaesthetic that reduces mucosal inflammation and pain on swallowing. Adjunct to systemic therapy."),
],
"antibiotics_note": "PENICILLIN ALLERGY ALTERNATIVE: If allergic to penicillin, use Azithromycin 500 mg OD × 5 days "
"or Clarithromycin 250 mg BD × 10 days. Avoid cephalosporins in anaphylaxis history.",
"follow_up": "Review at 48-72 h if no improvement. Complete full 10-day course even if feeling better. "
"Refer to ENT if ≥7 episodes/year (tonsillectomy criteria).",
},
]
# ══════════════════════════════════════════════════════════════════════════════
# BUILD STORY (PDF flowable elements)
# ══════════════════════════════════════════════════════════════════════════════
story = []
# ── Cover page ────────────────────────────────────────────────────────────────
def cover_page():
elems = []
# full-width coloured block
banner = ColourBanner(NAVY, height=6*cm, radius=0)
elems.append(banner)
elems.append(Spacer(1, -5.5*cm)) # overlap
# white hospital icon placeholder text
cover_tbl = Table(
[[Paragraph("OPD PATIENT CASES", sTitle)],
[Paragraph("Educational Prescriptions & Clinical Reasoning", sSubTitle)],
[Spacer(1, 0.4*cm)],
[Paragraph("For Medical Students, Interns & Residents", sSubTitle)],
[Spacer(1, 0.3*cm)],
[Paragraph(f"Compiled: {datetime.date.today().strftime('%B %Y')}", sDate)],
],
colWidths=[15.7*cm]
)
cover_tbl.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), 20),
("RIGHTPADDING", (0,0), (-1,-1), 20),
]))
elems.append(cover_tbl)
elems.append(Spacer(1, 1*cm))
# summary box
sum_data = [
[Paragraph("<b>10</b>", ParagraphStyle("big", fontSize=28, textColor=TEAL, fontName="Helvetica-Bold", alignment=TA_CENTER)),
Paragraph("<b>Specialties</b><br/>covered", ParagraphStyle("sm", fontSize=10, textColor=NAVY, fontName="Helvetica", alignment=TA_CENTER, leading=14))],
[Paragraph("<b>40+</b>", ParagraphStyle("big2", fontSize=28, textColor=GOLD, fontName="Helvetica-Bold", alignment=TA_CENTER)),
Paragraph("<b>Drug explanations</b><br/>with mechanisms", ParagraphStyle("sm2", fontSize=10, textColor=NAVY, fontName="Helvetica", alignment=TA_CENTER, leading=14))],
]
sum_tbl = Table(sum_data, colWidths=[4*cm, 7*cm])
sum_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), LIGHT_TEAL),
("ALIGN", (0,0), (-1,-1), "CENTER"),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("TOPPADDING", (0,0), (-1,-1), 14),
("BOTTOMPADDING", (0,0), (-1,-1), 14),
("ROUNDEDCORNERS", [10]),
("GRID", (0,0), (-1,-1), 0.3, MID_GREY),
]))
elems.append(sum_tbl)
elems.append(Spacer(1, 0.8*cm))
# Disclaimer
disc_style = ParagraphStyle("disc", fontSize=8, textColor=HexColor("#7f8c8d"),
fontName="Helvetica-Oblique", alignment=TA_CENTER, leading=12)
elems.append(Paragraph(
"DISCLAIMER: This document is created solely for educational purposes. "
"Prescriptions are illustrative and should not be used as direct clinical instructions. "
"Always refer to current local guidelines and consult a qualified clinician.",
disc_style
))
elems.append(PageBreak())
return elems
story += cover_page()
# ── TOC ───────────────────────────────────────────────────────────────────────
story.append(Paragraph("Table of Contents", ParagraphStyle(
"toc_h", fontSize=16, textColor=NAVY, fontName="Helvetica-Bold", spaceAfter=12
)))
story.append(hr(TEAL, 1.5))
story.append(gap(0.3))
toc_items = [(f"Case {c['num']}", c['title'], c['diagnosis']) for c in CASES]
for num, title, diag in toc_items:
row = Table(
[[Paragraph(f"<b>{num}</b>", sTocEntry),
Paragraph(title, sTocEntry),
Paragraph(f"<i>{diag}</i>", ParagraphStyle("tocDiag", fontSize=9, textColor=HexColor("#7f8c8d"),
fontName="Helvetica-Oblique"))]],
colWidths=[2*cm, 9*cm, 5*cm]
)
row.setStyle(TableStyle([
("VALIGN", (0,0), (-1,-1), "TOP"),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LINEBELOW", (0,0), (-1,-1), 0.3, MID_GREY),
]))
story.append(row)
story.append(PageBreak())
# ── Cases ─────────────────────────────────────────────────────────────────────
for case in CASES:
# Header
story += case_header(case["num"], case["title"])
story.append(gap(0.35))
# Diagnosis badge
diag_tbl = Table(
[[Paragraph("DIAGNOSIS:", ParagraphStyle("db", fontSize=9, fontName="Helvetica-Bold",
textColor=WHITE)),
Paragraph(case["diagnosis"], ParagraphStyle("dv", fontSize=9, fontName="Helvetica",
textColor=WHITE))]],
colWidths=[2.8*cm, 12.9*cm]
)
diag_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), TEAL),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 8),
("ROUNDEDCORNERS", [6]),
]))
story.append(diag_tbl)
story.append(gap(0.3))
# Patient info
story.append(section_label("PATIENT INFORMATION"))
story.append(info_table(case["patient"]))
story.append(gap(0.3))
# Presenting complaint
story.append(section_label("PRESENTING COMPLAINT"))
story.append(body(case["presenting_complaint"]))
story.append(gap(0.15))
# History
story.append(section_label("HISTORY"))
for h in case["history"]:
story.append(bullet(h))
story.append(gap(0.15))
# Examination
story.append(section_label("EXAMINATION FINDINGS"))
for e in case["examination"]:
story.append(bullet(e))
story.append(gap(0.25))
# Prescription
story.append(section_label("PRESCRIPTION"))
story.append(prescription_table(case["prescription"]))
story.append(gap(0.3))
# Reasoning
story.append(section_label("CLINICAL REASONING – WHY THIS PRESCRIPTION?"))
for drug, rationale in case["reasoning"]:
story.append(body(f"<b>{drug}</b>"))
story.append(reason(rationale))
story.append(gap(0.1))
# Antibiotic note
if case.get("antibiotics_note"):
story.append(gap(0.1))
if "NO antibiotic" in case["antibiotics_note"] or "NO antibiotics" in case["antibiotics_note"]:
story.append(ok(case["antibiotics_note"]))
else:
story.append(warn(case["antibiotics_note"]))
# Follow-up
story.append(gap(0.2))
f_bg = Table(
[[Paragraph("FOLLOW-UP:", ParagraphStyle("fup_l", fontSize=9, fontName="Helvetica-Bold",
textColor=NAVY)),
Paragraph(case["follow_up"], ParagraphStyle("fup_v", fontSize=9, fontName="Helvetica",
textColor=HexColor("#2c3e50")))]],
colWidths=[2.8*cm, 12.9*cm]
)
f_bg.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), LIGHT_GOLD),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 8),
("VALIGN", (0,0), (-1,-1), "TOP"),
("ROUNDEDCORNERS", [6]),
]))
story.append(f_bg)
story.append(gap(0.4))
story.append(hr(MID_GREY))
story.append(PageBreak())
# ── Back matter: quick reference ─────────────────────────────────────────────
story.append(Paragraph("Quick Reference – Drug Class Summary",
ParagraphStyle("qr_h", fontSize=15, textColor=NAVY, fontName="Helvetica-Bold", spaceAfter=8)))
story.append(hr(TEAL, 1.5))
story.append(gap(0.3))
qr_data = [
["Drug Class", "Key Mechanism", "Representative Drug", "Common Use"],
["Analgesic/Antipyretic", "Central PG inhibition", "Paracetamol", "Pain, fever"],
["2nd-gen Antihistamine", "H1 receptor block", "Cetirizine", "Allergic rhinitis, urticaria"],
["Biguanide", "AMPK activation, ↓ hepatic glucose output", "Metformin", "T2DM first-line"],
["CCB (Dihydropyridine)", "L-type Ca²⁺ channel block", "Amlodipine", "Hypertension, angina"],
["ORS / Zinc", "Na-glucose co-transport / epithelial repair", "WHO-ORS + Zinc", "Diarrhoea / dehydration"],
["SABA", "Beta-2 receptor agonist (cAMP)", "Salbutamol", "Acute bronchospasm"],
["ICS", "Anti-inflammatory (GR-mediated)", "Budesonide", "Asthma controller"],
["Antibiotic – Nitrofurantoin", "DNA/ribosome damage via reductase", "Nitrofurantoin MR", "Uncomplicated UTI"],
["Iron supplement", "Replaces Fe stores → Hb synthesis", "Ferrous sulphate", "IDA"],
["PPI", "H⁺/K⁺-ATPase inhibition", "Omeprazole", "PUD, GORD, H. pylori"],
["Thyroid hormone", "T4 → T3 peripheral conversion", "Levothyroxine", "Hypothyroidism"],
["Penicillin (narrow spectrum)", "Transpeptidase inhibition", "Phenoxymethylpenicillin", "GAS tonsillitis"],
["5-HT3 antagonist", "Blocks serotonin-mediated nausea arc", "Ondansetron", "N/V in gastroenteritis"],
["Antifibrinolytic", "Inhibits plasminogen activators", "Tranexamic acid", "Menorrhagia"],
["LTRA", "CysLT1 receptor block", "Montelukast", "Asthma, allergic rhinitis"],
]
qr_tbl = Table(qr_data, colWidths=[4*cm, 5.5*cm, 3.5*cm, 2.6*cm], repeatRows=1)
qr_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), NAVY),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 8.5),
("ALIGN", (0,0), (-1,0), "CENTER"),
("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, LIGHT_GREY]),
("GRID", (0,0), (-1,-1), 0.3, MID_GREY),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 6),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
]))
story.append(qr_tbl)
story.append(gap(0.5))
story.append(Paragraph(
"This document is for educational use only. Drug doses and regimens may vary by local guidelines, "
"patient weight, renal function, and comorbidities. Always verify with current references before clinical application.",
sFooterNote
))
# ── Build ─────────────────────────────────────────────────────────────────────
def add_page_number(canvas, doc):
canvas.saveState()
canvas.setFont("Helvetica", 8)
canvas.setFillColor(HexColor("#7f8c8d"))
page_num = canvas.getPageNumber()
canvas.drawCentredString(PAGE_W / 2, 1.2*cm, f"Page {page_num}")
canvas.setStrokeColor(MID_GREY)
canvas.setLineWidth(0.5)
canvas.line(2*cm, 1.5*cm, PAGE_W - 2*cm, 1.5*cm)
canvas.restoreState()
doc.build(story, onFirstPage=add_page_number, onLaterPages=add_page_number)
print(f"PDF created: {OUTPUT}")
cd /home/daytona/workspace/opd-cases && python generate_opd_pdf.py 2>&1
ls -lh /home/daytona/workspace/opd-cases/OPD_Patient_Cases_Educational.pdf
OPD Patient Cases Educational
PDF Document · PDF
| # | Case | Diagnosis | Key Drugs |
|---|---|---|---|
| 1 | Viral URTI | Common Cold | Paracetamol, Cetirizine, Saline drops |
| 2 | Diabetes Mellitus | T2DM – New | Metformin, Aspirin, Atorvastatin |
| 3 | Hypertension | Stage 1 HTN | Amlodipine, Lifestyle advice |
| 4 | Acute Gastroenteritis | Rotavirus (child) | ORS, Zinc, Ondansetron, Probiotics |
| 5 | Bronchial Asthma | Mild Persistent (GINA Step 2) | Salbutamol, Budesonide, Montelukast |
| 6 | Urinary Tract Infection | Uncomplicated Cystitis | Nitrofurantoin, Phenazopyridine |
| 7 | Iron Deficiency Anaemia | Menorrhagia + dietary | Ferrous sulphate, Vitamin C, Tranexamic acid |
| 8 | Peptic Ulcer / H. pylori | Duodenal Ulcer | PPI + Clarithromycin + Amoxicillin (triple therapy) |
| 9 | Hypothyroidism | Hashimoto's | Levothyroxine, Calcium+Vit D |
| 10 | Bacterial Tonsillitis | Group A Strep | Penicillin V, Paracetamol, Ibuprofen |
Write about 25+ opd pt cases with their prescriptions for practice and education purposes also give reasons why are we prescribing it and make it in a pdf form