Give me a simple but effective topic in general pharmacology for mbbs 2 yr prof. Exam pov

Reading File
Finding Sources
Searching the Web

MBBS 2nd year pharmacology important topics for professional exam general pharmacology

Finding Sources
Finding Sources
Finding Sources
Finding Sources
Reading File
Finding Sources
Reading File
Reading File
Loading Image
Loading Image
Here is a high-yield, well-structured topic perfectly suited for your MBBS 2nd year prof exam:

DRUG-RECEPTOR PHARMACOLOGY: Agonists, Antagonists & Dose-Response Relationships

Why this topic? It appears in almost every university exam - as short notes, long answers, or MCQs. It forms the conceptual backbone of all of pharmacology. Understanding it means you can answer questions about ANY drug class.

1. THE DRUG-RECEPTOR COMPLEX

A receptor is any biologic molecule (usually a membrane-bound protein) to which a drug binds to produce a measurable response. A drug acting as an agonist binds and activates the receptor. The magnitude of response is proportional to the number of drug-receptor complexes formed.
Key point: Not all drugs act through receptors. Antacids chemically neutralize gastric acid - a non-receptor mechanism. This is a common MCQ trap.

2. THE 4 RECEPTOR FAMILIES (High-yield table)

Four receptor families - transmembrane signaling mechanisms
Receptor TypeMechanismOnsetExample
Ligand-gated ion channels (Ionotropic)Opens ion channel directlyMilliseconds (fastest)Nicotinic ACh receptor
G protein-coupled receptors (Metabotropic)Activates Gs/Gi/Gq → 2nd messengerSecondsα & β adrenoceptors
Enzyme-linked receptors (Tyrosine kinase)Receptor phosphorylates proteinsMinutesInsulin receptor
Intracellular receptors (Nuclear)Alters gene expressionHours (slowest)Steroid receptors

3. RECEPTOR STATES & TYPES OF LIGANDS

Receptors exist in two states: inactive (R) and active (R*).
Ligand TypeIntrinsic ActivityEffect
Full agonist= 1Maximal response (e.g., morphine)
Partial agonist0 < IA < 1Submaximal response; can block full agonist (e.g., buprenorphine, aripiprazole)
Competitive antagonist= 0Blocks agonist reversibly; can be overcome by increasing agonist dose (e.g., atropine, naloxone)
Non-competitive antagonist= 0Blocks irreversibly; Emax reduced, cannot be overcome (e.g., phenoxybenzamine)
Inverse agonist< 0Stabilizes inactive R, opposes constitutive activity
Exam tip: Partial agonists can act as BOTH agonist AND antagonist depending on whether a full agonist is present. Classic example = buprenorphine (used in opioid dependence).

4. DOSE-RESPONSE CURVES (Most commonly examined graphs)

Graded dose-response curve showing EC50 and potency comparison between Drug A and Drug B

Potency vs. Efficacy - the #1 confusing concept in exams

  • Potency = how much drug is needed to produce 50% of maximal effect (EC50). Lower EC50 = more potent.
  • Efficacy = the maximal response a drug can produce (Emax). This is clinically MORE important.
  • A drug can be highly potent but have low efficacy, and vice versa.
Classic exam question: "Morphine and codeine are both opioids. Morphine has greater efficacy (higher Emax). Codeine is less efficacious regardless of dose."

Effect of Competitive vs. Non-Competitive Antagonist on Dose-Response Curve

Antagonist TypeShift of CurveEmaxEC50
CompetitiveRight shift (parallel)UnchangedIncreased
Non-competitiveNo shift / diminishedDecreasedUnchanged or increased

5. THERAPEUTIC INDEX (TI) - Safety Margin

  • TI = TD50 / ED50 (or LD50 / ED50 in animal studies)
  • TD50 = dose producing toxicity in 50% of population
  • ED50 = dose producing effect in 50% of population
  • Narrow TI drugs = dangerous, require monitoring: digoxin, lithium, warfarin, aminoglycosides, phenytoin

6. QUICK SUMMARY FOR REVISION

Agonist      → Binds + Activates → Response
Partial Ag.  → Binds + Partially Activates → Used in dependence Rx
Antagonist   → Binds + No activation → Blocks agonist
  Competitive   → Reversible, right-shifts curve, Emax preserved
  Non-comp      → Irreversible, reduces Emax
Potency      → EC50 (lower = more potent)
Efficacy     → Emax (clinically more important)
TI           → TD50/ED50 (narrow = careful!)

How to answer a 5-mark short note: Write: definition of receptor → 4 receptor families (table/diagram) → agonist/antagonist types → dose-response curve with potency vs. efficacy → therapeutic index. That covers it completely.
Source: Lippincott Illustrated Reviews: Pharmacology

Make a quick reference study guide PDF on this topic

Reading File
Running Command

ls -la /home/daytona/workspace/ && mkdir -p /home/daytona/workspace/pharma-study…

Writing File

~/pharma-study-guide/generate_pdf.py

from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm, mm
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    HRFlowable, PageBreak, KeepTogether
)
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus import Flowable
import urllib.request
import io

OUTPUT = "/home/daytona/workspace/pharma-study-guide/Drug_Receptor_Pharmacology_StudyGuide.pdf"

# ── Colours ──────────────────────────────────────────────────────────────────
NAVY      = colors.HexColor("#1A3A5C")
TEAL      = colors.HexColor("#0D7377")
AMBER     = colors.HexColor("#F4A020")
LIGHT_BG  = colors.HexColor("#EBF5FB")
PALE_TBL  = colors.HexColor("#D6EAF8")
PALE_AMB  = colors.HexColor("#FEF9E7")
PALE_RED  = colors.HexColor("#FDEDEC")
WHITE     = colors.white
DARK_GRAY = colors.HexColor("#2C3E50")
MID_GRAY  = colors.HexColor("#5D6D7E")
LIGHT_GRAY= colors.HexColor("#F2F3F4")
GREEN     = colors.HexColor("#1E8449")
RED_DARK  = colors.HexColor("#922B21")

# ── Styles ────────────────────────────────────────────────────────────────────
styles = getSampleStyleSheet()

def make_style(name, parent="Normal", **kwargs):
    return ParagraphStyle(name, parent=styles[parent], **kwargs)

TITLE_STYLE = make_style("MyTitle",
    fontSize=26, leading=32, textColor=WHITE,
    alignment=TA_CENTER, fontName="Helvetica-Bold", spaceAfter=4)

SUBTITLE_STYLE = make_style("MySubtitle",
    fontSize=12, leading=16, textColor=colors.HexColor("#AED6F1"),
    alignment=TA_CENTER, fontName="Helvetica", spaceAfter=2)

SECTION_STYLE = make_style("SectionHead",
    fontSize=13, leading=16, textColor=WHITE,
    fontName="Helvetica-Bold", spaceBefore=10, spaceAfter=4)

BODY_STYLE = make_style("MyBody",
    fontSize=9.5, leading=14, textColor=DARK_GRAY,
    fontName="Helvetica", spaceBefore=2, spaceAfter=2, alignment=TA_JUSTIFY)

BULLET_STYLE = make_style("MyBullet",
    fontSize=9.5, leading=13, textColor=DARK_GRAY,
    fontName="Helvetica", leftIndent=12, bulletIndent=0,
    spaceBefore=1, spaceAfter=1)

BOX_STYLE = make_style("BoxStyle",
    fontSize=9, leading=13, textColor=DARK_GRAY,
    fontName="Helvetica", leftIndent=6, spaceBefore=2, spaceAfter=2)

HIGHLIGHT_STYLE = make_style("HighLight",
    fontSize=9.5, leading=13, textColor=RED_DARK,
    fontName="Helvetica-Bold", spaceBefore=3, spaceAfter=3)

MONO_STYLE = make_style("Mono",
    fontSize=8.5, leading=12, textColor=DARK_GRAY,
    fontName="Courier", leftIndent=8, spaceBefore=2, spaceAfter=2)

SMALL_STYLE = make_style("Small",
    fontSize=8, leading=11, textColor=MID_GRAY,
    fontName="Helvetica", alignment=TA_CENTER)

TH_STYLE = make_style("TH",
    fontSize=9, leading=12, textColor=WHITE,
    fontName="Helvetica-Bold", alignment=TA_CENTER)

TD_STYLE = make_style("TD",
    fontSize=8.5, leading=12, textColor=DARK_GRAY,
    fontName="Helvetica", alignment=TA_CENTER)

TD_LEFT = make_style("TDLeft",
    fontSize=8.5, leading=12, textColor=DARK_GRAY,
    fontName="Helvetica", alignment=TA_LEFT)


# ── Helper Flowables ──────────────────────────────────────────────────────────
class SectionHeader(Flowable):
    """Coloured banner with white heading text."""
    def __init__(self, text, bg=NAVY, width=None):
        super().__init__()
        self.text = text
        self.bg = bg
        self._w = width or (A4[0] - 2.5*cm)
        self.height = 22

    def draw(self):
        self.canv.setFillColor(self.bg)
        self.canv.roundRect(0, 0, self._w, self.height, 4, fill=1, stroke=0)
        self.canv.setFillColor(WHITE)
        self.canv.setFont("Helvetica-Bold", 11)
        self.canv.drawString(10, 6, self.text)

    def wrap(self, aw, ah):
        return self._w, self.height


class TitleBanner(Flowable):
    def __init__(self, title, subtitle, tag, width=None):
        super().__init__()
        self.title = title
        self.subtitle = subtitle
        self.tag = tag
        self._w = width or (A4[0] - 2.5*cm)
        self.height = 110

    def draw(self):
        c = self.canv
        w, h = self._w, self.height
        # Background gradient-like via two rects
        c.setFillColor(NAVY)
        c.roundRect(0, 0, w, h, 8, fill=1, stroke=0)
        c.setFillColor(TEAL)
        c.roundRect(0, 0, w*0.35, h, 8, fill=1, stroke=0)
        c.setFillColor(NAVY)
        c.rect(w*0.25, 0, w*0.1, h, fill=1, stroke=0)
        # Tag pill
        c.setFillColor(AMBER)
        c.roundRect(w - 145, h - 28, 135, 20, 5, fill=1, stroke=0)
        c.setFillColor(NAVY)
        c.setFont("Helvetica-Bold", 9)
        c.drawCentredString(w - 77, h - 20, self.tag)
        # Title
        c.setFillColor(WHITE)
        c.setFont("Helvetica-Bold", 18)
        c.drawString(14, h - 42, self.title)
        # Subtitle
        c.setFillColor(colors.HexColor("#AED6F1"))
        c.setFont("Helvetica", 10)
        c.drawString(14, h - 58, self.subtitle)
        # Decorative line
        c.setStrokeColor(AMBER)
        c.setLineWidth(2)
        c.line(14, h - 66, w - 14, h - 66)
        # Bottom note
        c.setFillColor(colors.HexColor("#AED6F1"))
        c.setFont("Helvetica", 8)
        c.drawString(14, 8, "Source: Lippincott Illustrated Reviews: Pharmacology  |  For MBBS 2nd Year Prof Exam")

    def wrap(self, aw, ah):
        return self._w, self.height


class ColorBox(Flowable):
    """Coloured info box with left border stripe."""
    def __init__(self, content_para, bg=PALE_TBL, stripe=TEAL, width=None, padding=8):
        super().__init__()
        self.para = content_para
        self.bg = bg
        self.stripe = stripe
        self._w = width or (A4[0] - 2.5*cm)
        self.padding = padding
        self._content_w = self._w - 16 - padding

    def wrap(self, aw, ah):
        _, h = self.para.wrap(self._content_w, ah)
        self._h = h + self.padding * 2
        return self._w, self._h

    def draw(self):
        c = self.canv
        c.setFillColor(self.bg)
        c.roundRect(0, 0, self._w, self._h, 4, fill=1, stroke=0)
        c.setFillColor(self.stripe)
        c.rect(0, 0, 5, self._h, fill=1, stroke=0)
        self.para.drawOn(c, 14, self.padding)


# ── Table builder ─────────────────────────────────────────────────────────────
def make_table(headers, rows, col_widths, header_bg=NAVY):
    data = [[Paragraph(h, TH_STYLE) for h in headers]]
    for row in rows:
        data.append([Paragraph(str(c), TD_LEFT if i == 0 else TD_STYLE)
                     for i, c in enumerate(row)])

    n_rows = len(data)
    style = TableStyle([
        ("BACKGROUND", (0, 0), (-1, 0), header_bg),
        ("ROWBACKGROUNDS", (0, 1), (-1, -1), [WHITE, LIGHT_GRAY]),
        ("GRID", (0, 0), (-1, -1), 0.3, colors.HexColor("#BFC9CA")),
        ("LEFTPADDING",  (0, 0), (-1, -1), 6),
        ("RIGHTPADDING", (0, 0), (-1, -1), 6),
        ("TOPPADDING",   (0, 0), (-1, -1), 5),
        ("BOTTOMPADDING",(0, 0), (-1, -1), 5),
        ("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
        ("ROUNDEDCORNERS", [4, 4, 4, 4]),
    ])
    return Table(data, colWidths=col_widths, style=style, repeatRows=1)


# ── Page template ─────────────────────────────────────────────────────────────
def on_page(canvas, doc):
    canvas.saveState()
    w, h = A4
    # Footer bar
    canvas.setFillColor(NAVY)
    canvas.rect(0, 0, w, 18, fill=1, stroke=0)
    canvas.setFillColor(WHITE)
    canvas.setFont("Helvetica", 7.5)
    canvas.drawString(15, 5, "Drug-Receptor Pharmacology  |  MBBS 2nd Year Quick Reference")
    canvas.drawRightString(w - 15, 5, f"Page {doc.page}")
    # Top accent line
    canvas.setFillColor(TEAL)
    canvas.rect(0, h - 5, w, 5, fill=1, stroke=0)
    canvas.restoreState()


# ── Build document ────────────────────────────────────────────────────────────
def build():
    doc = SimpleDocTemplate(
        OUTPUT,
        pagesize=A4,
        leftMargin=1.25*cm, rightMargin=1.25*cm,
        topMargin=1.2*cm, bottomMargin=1.2*cm,
        title="Drug-Receptor Pharmacology Study Guide",
        author="Orris Medical"
    )
    W = A4[0] - 2.5*cm
    story = []

    # ── TITLE BANNER ─────────────────────────────────────────────────────────
    story.append(TitleBanner(
        "Drug-Receptor Pharmacology",
        "Agonists, Antagonists, Dose-Response Relationships & Therapeutic Index",
        "MBBS 2nd Year Prof Exam", width=W
    ))
    story.append(Spacer(1, 10))

    # ── SECTION 1: Why this topic? ────────────────────────────────────────────
    story.append(SectionHeader("WHY THIS TOPIC?", bg=TEAL, width=W))
    story.append(Spacer(1, 6))
    story.append(Paragraph(
        "Drug-receptor pharmacology is the <b>conceptual backbone</b> of the entire subject. "
        "It appears in virtually every university paper - as short notes (5 marks), long answers (10 marks), "
        "and MCQs. Master this and you can reason about ANY drug class without pure memorisation.",
        BODY_STYLE))
    story.append(Spacer(1, 4))
    box1 = ColorBox(
        Paragraph("📌 <b>Common exam questions:</b> Agonist vs. antagonist (2 marks) | "
                  "Dose-response curve with potency & efficacy (5 marks) | "
                  "Competitive vs. non-competitive antagonism (5 marks) | "
                  "Therapeutic index & narrow TI drugs (3 marks)", BOX_STYLE),
        bg=PALE_AMB, stripe=AMBER, width=W)
    story.append(box1)
    story.append(Spacer(1, 8))

    # ── SECTION 2: Drug-Receptor Complex ──────────────────────────────────────
    story.append(SectionHeader("1.  THE DRUG-RECEPTOR COMPLEX", bg=NAVY, width=W))
    story.append(Spacer(1, 6))
    story.append(Paragraph(
        "A <b>receptor</b> is any biological molecule (usually a membrane-bound protein) to which a drug "
        "binds to produce a measurable response. The response magnitude is proportional to the number of "
        "drug-receptor complexes formed.",
        BODY_STYLE))
    story.append(Spacer(1, 4))
    story.append(Paragraph(
        "<b>Receptor states:</b> Receptors exist in at least two states - <b>inactive (R)</b> and "
        "<b>active (R*)</b> - in reversible equilibrium, usually favouring R.",
        BODY_STYLE))
    story.append(Spacer(1, 4))

    tip1 = ColorBox(
        Paragraph("⚠️ <b>MCQ Trap:</b> Not all drugs act via receptors. "
                  "Antacids chemically neutralise gastric acid (non-receptor mechanism). "
                  "Osmotic diuretics (mannitol) act by osmosis. Always check the mechanism!",
                  BOX_STYLE),
        bg=PALE_RED, stripe=RED_DARK, width=W)
    story.append(tip1)
    story.append(Spacer(1, 8))

    # ── SECTION 3: The 4 Receptor Families ───────────────────────────────────
    story.append(SectionHeader("2.  THE 4 RECEPTOR FAMILIES  (High-Yield)", bg=NAVY, width=W))
    story.append(Spacer(1, 6))

    rec_headers = ["Receptor Type", "Mechanism", "Onset", "Clinical Examples"]
    rec_rows = [
        ["Ligand-gated ion channels\n(Ionotropic / Type I)",
         "Drug opens ion channel directly → rapid ion flux",
         "Milliseconds\n(FASTEST)",
         "Nicotinic ACh receptor\nGABA-A receptor\nGlutamate NMDA receptor"],
        ["G protein-coupled receptors\n(Metabotropic / Type II)",
         "Activates Gs / Gi / Gq → 2nd messengers\n(cAMP, IP3, DAG)",
         "Seconds",
         "α & β adrenoceptors\nMuscarinic receptors\nOpioid receptors"],
        ["Enzyme-linked receptors\n(Tyrosine kinase / Type III)",
         "Ligand binding activates kinase domain\n→ protein phosphorylation",
         "Minutes",
         "Insulin receptor\nGrowth factors (EGF, PDGF)\nAtrial natriuretic peptide"],
        ["Intracellular receptors\n(Nuclear / Type IV)",
         "Lipid-soluble ligand enters cell\n→ alters gene transcription",
         "Hours\n(SLOWEST)",
         "Glucocorticoid receptor\nSex hormone receptors\nThyroid hormone receptor"],
    ]
    story.append(make_table(rec_headers, rec_rows,
                            [3.8*cm, 5.2*cm, 2.4*cm, 5.0*cm]))
    story.append(Spacer(1, 5))
    tip2 = ColorBox(
        Paragraph("🧠 <b>Memory tip:</b> Order fastest → slowest: <b>I</b>on channels → "
                  "<b>G</b> proteins → <b>E</b>nzyme-linked → <b>I</b>ntracellular  "
                  "(mnemonic: <b>I Got Every Item</b>)",
                  BOX_STYLE),
        bg=PALE_TBL, stripe=TEAL, width=W)
    story.append(tip2)
    story.append(Spacer(1, 8))

    # ── SECTION 4: Types of Ligands ───────────────────────────────────────────
    story.append(SectionHeader("3.  TYPES OF LIGANDS  (Agonists & Antagonists)", bg=NAVY, width=W))
    story.append(Spacer(1, 6))
    story.append(Paragraph(
        "<b>Intrinsic activity (IA)</b> = ability of a drug to activate the receptor after binding. "
        "This is the key property that differentiates ligand types.",
        BODY_STYLE))
    story.append(Spacer(1, 5))

    lig_headers = ["Ligand Type", "IA", "Effect on Receptor", "Clinical Example"]
    lig_rows = [
        ["Full Agonist", "= 1", "Maximal activation of R* → maximum response", "Morphine, Adrenaline, Salbutamol"],
        ["Partial Agonist", "0 < IA < 1", "Partial activation; can ALSO block full agonist\n(acts as partial antagonist)", "Buprenorphine (opioid)\nAripiprazole (antipsychotic)\nPindolol (β-blocker)"],
        ["Competitive Antagonist", "= 0", "Blocks agonist reversibly at same site\nRight-shifts curve; Emax unchanged", "Atropine, Naloxone\nTerazosin, Propranolol"],
        ["Non-competitive Antagonist", "= 0", "Blocks irreversibly or allosterically\nReduces Emax; cannot be overcome", "Phenoxybenzamine (α-blocker)"],
        ["Inverse Agonist", "< 0", "Stabilises INACTIVE R; opposes constitutive\nactivity → OPPOSITE effect to agonist", "β-carbolines\nSome antihistamines at H1"],
    ]
    story.append(make_table(lig_headers, lig_rows,
                            [3.6*cm, 1.2*cm, 5.4*cm, 6.2*cm]))
    story.append(Spacer(1, 5))

    tip3 = ColorBox(
        Paragraph("⭐ <b>Examiner favourite:</b> Partial agonists have DUAL action - they stimulate "
                  "when no full agonist is present, but BLOCK the full agonist when it is present. "
                  "Classic example = <b>Buprenorphine</b> used in opioid dependence treatment.",
                  BOX_STYLE),
        bg=PALE_AMB, stripe=AMBER, width=W)
    story.append(tip3)
    story.append(Spacer(1, 10))

    # ── SECTION 5: Dose-Response ──────────────────────────────────────────────
    story.append(SectionHeader("4.  DOSE-RESPONSE RELATIONSHIPS", bg=NAVY, width=W))
    story.append(Spacer(1, 6))

    # Two-column: potency vs efficacy explanation
    col1 = [
        Paragraph("<b>POTENCY</b>", make_style("C1H", fontSize=10, textColor=TEAL, fontName="Helvetica-Bold")),
        Spacer(1, 3),
        Paragraph("• Amount of drug needed to produce 50% max effect", BULLET_STYLE),
        Paragraph("• Measured by <b>EC50</b> (lower EC50 = more potent)", BULLET_STYLE),
        Paragraph("• Reflects <b>affinity</b> for the receptor", BULLET_STYLE),
        Spacer(1, 4),
        Paragraph("Drug A is MORE potent than Drug B if it produces the same effect at a lower dose", BODY_STYLE),
    ]
    col2 = [
        Paragraph("<b>EFFICACY</b>", make_style("C2H", fontSize=10, textColor=GREEN, fontName="Helvetica-Bold")),
        Spacer(1, 3),
        Paragraph("• MAXIMUM response a drug can produce", BULLET_STYLE),
        Paragraph("• Measured by <b>Emax</b>", BULLET_STYLE),
        Paragraph("• Reflects <b>intrinsic activity</b>", BULLET_STYLE),
        Spacer(1, 4),
        Paragraph("<b>Clinically MORE important than potency.</b> A high-efficacy drug is more therapeutically useful.", BODY_STYLE),
    ]
    two_col = Table([[col1, col2]], colWidths=[W/2 - 4, W/2 - 4],
                    style=TableStyle([
                        ("VALIGN", (0, 0), (-1, -1), "TOP"),
                        ("LEFTPADDING", (0, 0), (-1, -1), 8),
                        ("RIGHTPADDING", (0, 0), (-1, -1), 8),
                        ("BOX", (0, 0), (0, 0), 0.5, TEAL),
                        ("BOX", (1, 0), (1, 0), 0.5, GREEN),
                        ("BACKGROUND", (0, 0), (0, 0), colors.HexColor("#E8F8F5")),
                        ("BACKGROUND", (1, 0), (1, 0), colors.HexColor("#EAFAF1")),
                        ("TOPPADDING", (0, 0), (-1, -1), 8),
                        ("BOTTOMPADDING", (0, 0), (-1, -1), 8),
                    ]))
    story.append(two_col)
    story.append(Spacer(1, 8))

    # Competitive vs Non-competitive table
    story.append(Paragraph("<b>Effect of Antagonists on Dose-Response Curve:</b>", BODY_STYLE))
    story.append(Spacer(1, 4))

    drc_headers = ["Antagonist Type", "Curve Shift", "Emax", "EC50", "Key Feature"]
    drc_rows = [
        ["Competitive\n(reversible)", "Parallel RIGHT shift",
         "UNCHANGED\n(same)", "INCREASED", "Increasing agonist dose overcomes the block\n(surmountable)"],
        ["Non-competitive\n(irreversible)", "Compressed / flattened",
         "DECREASED\n(cannot recover)", "Unchanged or↑", "Cannot be overcome by increasing agonist\n(insurmountable)"],
    ]
    story.append(make_table(drc_headers, drc_rows,
                            [3.0*cm, 3.0*cm, 2.4*cm, 2.0*cm, 5.8*cm]))
    story.append(Spacer(1, 5))

    # Diagram-style ASCII curve note
    story.append(Paragraph("<b>Key Graph Points to Draw in Exam:</b>", BODY_STYLE))
    story.append(Spacer(1, 3))
    diagram_data = [
        [Paragraph("<b>Potency Comparison</b>", TH_STYLE),
         Paragraph("<b>Competitive Antagonism</b>", TH_STYLE),
         Paragraph("<b>Non-Competitive Antagonism</b>", TH_STYLE)],
        [Paragraph(
            "• Both curves reach same Emax\n"
            "• Drug A has smaller EC50 → more potent\n"
            "• S-shaped (sigmoidal) on log scale\n"
            "• Linear at low doses on linear scale",
            MONO_STYLE),
         Paragraph(
            "• Curve shifts RIGHT (parallel)\n"
            "• Emax unchanged\n"
            "• EC50 increases\n"
            "• Adding more agonist restores response",
            MONO_STYLE),
         Paragraph(
            "• Curve shifts DOWN/right\n"
            "• Emax REDUCED\n"
            "• Response ceiling lowered\n"
            "• Cannot restore Emax with more agonist",
            MONO_STYLE)],
    ]
    diagram_tbl = Table(diagram_data, colWidths=[W/3 - 3, W/3 - 3, W/3 - 3],
                        style=TableStyle([
                            ("BACKGROUND", (0, 0), (-1, 0), NAVY),
                            ("BACKGROUND", (0, 1), (0, 1), colors.HexColor("#EBF5FB")),
                            ("BACKGROUND", (1, 1), (1, 1), colors.HexColor("#E8F8F5")),
                            ("BACKGROUND", (2, 1), (2, 1), colors.HexColor("#FDEDEC")),
                            ("GRID", (0, 0), (-1, -1), 0.4, colors.HexColor("#BFC9CA")),
                            ("VALIGN", (0, 0), (-1, -1), "TOP"),
                            ("TOPPADDING", (0, 0), (-1, -1), 6),
                            ("BOTTOMPADDING", (0, 0), (-1, -1), 6),
                            ("LEFTPADDING", (0, 0), (-1, -1), 5),
                        ]))
    story.append(diagram_tbl)
    story.append(Spacer(1, 8))

    # ── SECTION 6: Therapeutic Index ─────────────────────────────────────────
    story.append(SectionHeader("5.  THERAPEUTIC INDEX  (Safety Margin)", bg=NAVY, width=W))
    story.append(Spacer(1, 6))

    ti_col1 = [
        Paragraph("<b>Formula:</b>", BODY_STYLE),
        Spacer(1, 4),
        Paragraph("TI = TD50 ÷ ED50", make_style("Formula", fontSize=16, textColor=NAVY,
                  fontName="Helvetica-Bold", alignment=TA_CENTER)),
        Spacer(1, 4),
        Paragraph("(or LD50 ÷ ED50 in animal studies)", SMALL_STYLE),
        Spacer(1, 6),
        Paragraph("• <b>TD50</b> = dose toxic in 50% of population", BULLET_STYLE),
        Paragraph("• <b>ED50</b> = dose effective in 50% of population", BULLET_STYLE),
        Paragraph("• <b>Higher TI = safer drug</b>", BULLET_STYLE),
        Paragraph("• <b>Narrow TI</b> = small margin between therapeutic & toxic dose", BULLET_STYLE),
    ]
    ti_col2 = [
        Paragraph("<b>Narrow Therapeutic Index Drugs (Must Know!):</b>",
                  make_style("NTI", fontSize=9.5, textColor=RED_DARK, fontName="Helvetica-Bold")),
        Spacer(1, 5),
    ]
    nti_drugs = [
        ("Digoxin", "Cardiac glycoside", "Nausea, arrhythmias, yellow vision"),
        ("Lithium", "Mood stabiliser", "Tremor, nephrotoxicity, seizures"),
        ("Warfarin", "Anticoagulant", "Bleeding"),
        ("Phenytoin", "Antiepileptic", "Nystagmus, ataxia, gingival hyperplasia"),
        ("Aminoglycosides", "Antibiotics", "Nephrotoxicity, ototoxicity"),
        ("Theophylline", "Bronchodilator", "Arrhythmias, seizures"),
        ("Methotrexate", "Anticancer / DMARD", "Bone marrow suppression, hepatotoxicity"),
    ]
    nti_data = [[Paragraph("<b>Drug</b>", TH_STYLE), Paragraph("<b>Class</b>", TH_STYLE), Paragraph("<b>Toxic Effect</b>", TH_STYLE)]]
    for d, c, t in nti_drugs:
        nti_data.append([Paragraph(d, make_style("NTId", fontSize=8.5, fontName="Helvetica-Bold", textColor=RED_DARK)),
                         Paragraph(c, TD_STYLE), Paragraph(t, TD_LEFT)])
    nti_tbl = Table(nti_data, colWidths=[3.0*cm, 2.5*cm, 4.5*cm],
                    style=TableStyle([
                        ("BACKGROUND", (0, 0), (-1, 0), RED_DARK),
                        ("ROWBACKGROUNDS", (0, 1), (-1, -1), [WHITE, PALE_RED]),
                        ("GRID", (0, 0), (-1, -1), 0.3, colors.HexColor("#E74C3C")),
                        ("TOPPADDING", (0, 0), (-1, -1), 4),
                        ("BOTTOMPADDING", (0, 0), (-1, -1), 4),
                        ("LEFTPADDING", (0, 0), (-1, -1), 5),
                    ]))
    ti_col2.append(nti_tbl)

    ti_table = Table([[ti_col1, ti_col2]], colWidths=[W*0.38, W*0.62],
                     style=TableStyle([
                         ("VALIGN", (0, 0), (-1, -1), "TOP"),
                         ("LEFTPADDING", (0, 0), (-1, -1), 8),
                         ("RIGHTPADDING", (0, 0), (-1, -1), 8),
                         ("TOPPADDING", (0, 0), (-1, -1), 8),
                         ("BOTTOMPADDING", (0, 0), (-1, -1), 8),
                         ("BOX", (0, 0), (0, 0), 0.5, NAVY),
                         ("BOX", (1, 0), (1, 0), 0.5, RED_DARK),
                         ("BACKGROUND", (0, 0), (0, 0), LIGHT_BG),
                         ("BACKGROUND", (1, 0), (1, 0), PALE_RED),
                     ]))
    story.append(ti_table)
    story.append(Spacer(1, 10))

    # ── SECTION 7: Quick Exam Summary ────────────────────────────────────────
    story.append(SectionHeader("6.  QUICK EXAM SUMMARY CARD", bg=colors.HexColor("#6C3483"), width=W))
    story.append(Spacer(1, 6))

    summary_lines = [
        ("Full Agonist", "IA = 1", "Max response (e.g. Morphine, Adrenaline)"),
        ("Partial Agonist", "0 < IA < 1", "Submaximal; also blocks full agonist (e.g. Buprenorphine)"),
        ("Competitive Antagonist", "IA = 0", "Reversible; right-shifts curve; Emax unchanged (e.g. Atropine)"),
        ("Non-competitive Antagonist", "IA = 0", "Irreversible; reduces Emax (e.g. Phenoxybenzamine)"),
        ("Inverse Agonist", "IA < 0", "Opposes constitutive receptor activity"),
        ("Potency (EC50)", "↓ EC50 = ↑ potency", "How MUCH drug is needed"),
        ("Efficacy (Emax)", "Higher Emax = better", "How STRONG the max response is (clinically > potency)"),
        ("Therapeutic Index", "TD50 / ED50", "Higher = safer; Narrow TI drugs need monitoring"),
    ]
    summ_data = [[Paragraph("<b>Concept</b>", TH_STYLE), Paragraph("<b>Key Value</b>", TH_STYLE), Paragraph("<b>What to Remember</b>", TH_STYLE)]]
    for row in summary_lines:
        summ_data.append([Paragraph(row[0], make_style("SRow", fontSize=8.5, fontName="Helvetica-Bold", textColor=NAVY)),
                          Paragraph(row[1], make_style("SVal", fontSize=8.5, fontName="Courier", textColor=TEAL, alignment=TA_CENTER)),
                          Paragraph(row[2], TD_LEFT)])
    summ_tbl = Table(summ_data, colWidths=[3.8*cm, 3.2*cm, W - 7.0*cm - 16],
                     style=TableStyle([
                         ("BACKGROUND", (0, 0), (-1, 0), colors.HexColor("#6C3483")),
                         ("ROWBACKGROUNDS", (0, 1), (-1, -1), [WHITE, colors.HexColor("#F5EEF8")]),
                         ("GRID", (0, 0), (-1, -1), 0.3, colors.HexColor("#D2B4DE")),
                         ("TOPPADDING", (0, 0), (-1, -1), 5),
                         ("BOTTOMPADDING", (0, 0), (-1, -1), 5),
                         ("LEFTPADDING", (0, 0), (-1, -1), 6),
                     ]))
    story.append(summ_tbl)
    story.append(Spacer(1, 8))

    # ── SECTION 8: How to Answer ──────────────────────────────────────────────
    story.append(SectionHeader("7.  HOW TO STRUCTURE A 5-MARK SHORT NOTE", bg=TEAL, width=W))
    story.append(Spacer(1, 6))

    answer_steps = [
        ("Step 1 - Define receptor", "1-2 lines defining a receptor and drug-receptor complex"),
        ("Step 2 - List receptor families", "Table or labelled list: 4 families with examples (4-5 lines)"),
        ("Step 3 - Agonist types", "Full / partial / inverse agonist with intrinsic activity value"),
        ("Step 4 - Antagonist types", "Competitive vs. non-competitive with curve changes"),
        ("Step 5 - Dose-response curve", "Draw the sigmoid curve; label EC50, Emax; compare potency/efficacy"),
        ("Step 6 - Therapeutic Index", "Formula + narrow TI drugs list (2-3 examples)"),
    ]
    for step, desc in answer_steps:
        story.append(Paragraph(f"<b>{step}:</b> {desc}", BULLET_STYLE))
    story.append(Spacer(1, 4))
    tip_final = ColorBox(
        Paragraph("✅ <b>Pro tip:</b> Always draw at least ONE graph (dose-response curve) even in a short note. "
                  "Examiners award marks specifically for diagrams. Label axes: Y = % maximal effect, "
                  "X = log[Drug concentration].",
                  BOX_STYLE),
        bg=colors.HexColor("#EAFAF1"), stripe=GREEN, width=W)
    story.append(tip_final)
    story.append(Spacer(1, 6))

    # ── FOOTER NOTE ───────────────────────────────────────────────────────────
    story.append(HRFlowable(width=W, thickness=0.5, color=MID_GRAY))
    story.append(Spacer(1, 4))
    story.append(Paragraph(
        "Source: Lippincott Illustrated Reviews: Pharmacology, Goodman &amp; Gilman's Pharmacological Basis of Therapeutics, "
        "Katzung's Basic and Clinical Pharmacology  |  Generated by Orris Medical AI",
        SMALL_STYLE))

    # ── BUILD ──────────────────────────────────────────────────────────────────
    doc.build(story, onFirstPage=on_page, onLaterPages=on_page)
    print(f"PDF created: {OUTPUT}")


if __name__ == "__main__":
    build()
Running Command

cd /home/daytona/workspace/pharma-study-guide && python generate_pdf.py 2>&1

Running Command

ls -lh /home/daytona/workspace/pharma-study-guide/

Your study guide PDF is ready! Download it here:

Drug Receptor Pharmacology StudyGuide

PDF Document · PDF


What's inside the PDF:
SectionContent
Title BannerColour-coded header with exam tag
Why This TopicExam question types + marks breakdown
Drug-Receptor ComplexCore definitions + MCQ trap (non-receptor drugs)
4 Receptor FamiliesFull table: mechanism, onset speed, clinical examples
Types of LigandsFull/partial/competitive/non-competitive/inverse agonist table with intrinsic activity values
Dose-Response CurvesPotency vs. efficacy side-by-side, competitive vs. non-competitive antagonism comparison
Therapeutic IndexFormula, explanation, and 7 narrow-TI drugs with toxic effects
Quick Summary CardSingle-glance revision table of all key concepts
How to AnswerStep-by-step structure for a 5-mark short note
The PDF uses colour-coded boxes (amber for exam tips, red for MCQ traps, teal for memory aids) and is formatted for clean A4 printing or screen reading. Good luck with your prof exam!

Give guide pdf for all topics of general pharmacology

Finding Sources
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Reading File
Finding Sources
Reading File
Reading File
Writing File

~/pharma-study-guide/gen_pharmacology_complete.py

"""
MBBS 2nd Year General Pharmacology - Complete Quick Reference Study Guide
All 8 major topics covered
"""

from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm, mm
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    HRFlowable, PageBreak, KeepTogether
)
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY, TA_RIGHT
from reportlab.platypus import Flowable

OUTPUT = "/home/daytona/workspace/pharma-study-guide/General_Pharmacology_Complete_StudyGuide.pdf"
W_PAGE = A4[0] - 2.5 * cm

# ─── COLOUR PALETTE ───────────────────────────────────────────────────────────
NAVY      = colors.HexColor("#1A3A5C")
TEAL      = colors.HexColor("#0D7377")
AMBER     = colors.HexColor("#E67E22")
GREEN     = colors.HexColor("#1A6B3C")
PURPLE    = colors.HexColor("#6C3483")
RED_D     = colors.HexColor("#922B21")
BLUE_MID  = colors.HexColor("#1F618D")
SLATE     = colors.HexColor("#2E4057")
WHITE     = colors.white
DARK      = colors.HexColor("#2C3E50")
MID_GRAY  = colors.HexColor("#5D6D7E")
LIGHT_GR  = colors.HexColor("#F2F3F4")
PAL_BLUE  = colors.HexColor("#EBF5FB")
PAL_GREEN = colors.HexColor("#EAFAF1")
PAL_AMB   = colors.HexColor("#FEF9E7")
PAL_RED   = colors.HexColor("#FDEDEC")
PAL_PURP  = colors.HexColor("#F5EEF8")

# Topic accent colours (one per chapter)
TOPIC_COLORS = [TEAL, NAVY, GREEN, PURPLE, AMBER, RED_D, BLUE_MID, SLATE]

# ─── STYLES ───────────────────────────────────────────────────────────────────
styles = getSampleStyleSheet()

def S(name, **kw):
    return ParagraphStyle(name, parent=styles.get("Normal", styles["Normal"]), **kw)

BODY  = S("Body",  fontSize=9,   leading=13, textColor=DARK, spaceAfter=2, alignment=TA_JUSTIFY)
BULL  = S("Bull",  fontSize=9,   leading=13, textColor=DARK, leftIndent=12, spaceAfter=1)
HEAD2 = S("H2",    fontSize=10,  leading=13, textColor=NAVY, fontName="Helvetica-Bold", spaceBefore=6, spaceAfter=3)
HEAD3 = S("H3",    fontSize=9.5, leading=12, textColor=TEAL, fontName="Helvetica-Bold", spaceBefore=4, spaceAfter=2)
MONO  = S("Mono",  fontSize=8.5, leading=12, textColor=DARK, fontName="Courier", leftIndent=8)
SMALL = S("Sm",    fontSize=7.5, leading=10, textColor=MID_GRAY, alignment=TA_CENTER)
TH    = S("TH",    fontSize=8.5, leading=11, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER)
TD    = S("TD",    fontSize=8.5, leading=11, textColor=DARK, alignment=TA_CENTER)
TDL   = S("TDL",   fontSize=8.5, leading=11, textColor=DARK, alignment=TA_LEFT)
BOX_S = S("Box",   fontSize=8.5, leading=12, textColor=DARK)
WARN  = S("Warn",  fontSize=8.5, leading=12, textColor=RED_D, fontName="Helvetica-Bold")
TIP   = S("Tip",   fontSize=8.5, leading=12, textColor=colors.HexColor("#1A5276"), fontName="Helvetica-Bold")

# ─── HELPER FLOWABLES ─────────────────────────────────────────────────────────
class SecBanner(Flowable):
    """Full-width coloured section banner with chapter number pill."""
    def __init__(self, num, title, color, width=None):
        super().__init__()
        self.num = num
        self.title = title
        self.color = color
        self._w = width or W_PAGE
        self.height = 26

    def draw(self):
        c = self.canv
        c.setFillColor(self.color)
        c.roundRect(0, 0, self._w, self.height, 5, fill=1, stroke=0)
        # Pill
        c.setFillColor(WHITE)
        c.roundRect(6, 4, 22, 18, 4, fill=1, stroke=0)
        c.setFillColor(self.color)
        c.setFont("Helvetica-Bold", 9)
        c.drawCentredString(17, 11, str(self.num))
        # Title
        c.setFillColor(WHITE)
        c.setFont("Helvetica-Bold", 12)
        c.drawString(36, 8, self.title)

    def wrap(self, aw, ah):
        return self._w, self.height


class SubBanner(Flowable):
    """Lighter sub-section banner."""
    def __init__(self, text, color, width=None):
        super().__init__()
        self.text = text
        self.color = color
        self._w = width or W_PAGE
        self.height = 19

    def draw(self):
        c = self.canv
        # Light tinted background
        r, g, b = self.color.red, self.color.green, self.color.blue
        light = colors.Color(r * 0.2 + 0.8, g * 0.2 + 0.8, b * 0.2 + 0.8)
        c.setFillColor(light)
        c.roundRect(0, 0, self._w, self.height, 3, fill=1, stroke=0)
        c.setFillColor(self.color)
        c.rect(0, 0, 4, self.height, fill=1, stroke=0)
        c.setFillColor(self.color)
        c.setFont("Helvetica-Bold", 9.5)
        c.drawString(10, 5, self.text)

    def wrap(self, aw, ah):
        return self._w, self.height


class TitlePage(Flowable):
    def __init__(self, width=None):
        super().__init__()
        self._w = width or W_PAGE
        self.height = 200

    def draw(self):
        c = self.canv
        w, h = self._w, self.height
        # Deep background
        c.setFillColor(NAVY)
        c.roundRect(0, 0, w, h, 10, fill=1, stroke=0)
        # Accent strips
        for i, col in enumerate([TEAL, GREEN, PURPLE, AMBER, RED_D]):
            c.setFillColor(col)
            c.rect(w * i / 5, 0, w / 5, 6, fill=1, stroke=0)
        # Rx symbol area
        c.setFillColor(TEAL)
        c.roundRect(w - 70, h - 65, 55, 55, 8, fill=1, stroke=0)
        c.setFillColor(WHITE)
        c.setFont("Helvetica-Bold", 28)
        c.drawCentredString(w - 42, h - 42, "Rx")
        # Main title
        c.setFillColor(WHITE)
        c.setFont("Helvetica-Bold", 22)
        c.drawString(16, h - 46, "General Pharmacology")
        c.setFont("Helvetica-Bold", 14)
        c.setFillColor(colors.HexColor("#AED6F1"))
        c.drawString(16, h - 66, "Complete Quick Reference Study Guide")
        # Subtitle line
        c.setStrokeColor(AMBER)
        c.setLineWidth(2)
        c.line(16, h - 76, w - 16, h - 76)
        # Tags
        tags = ["MBBS 2nd Year", "Prof Exam Ready", "All 8 Topics", "Tables & Mnemonics"]
        x = 16
        for tag in tags:
            c.setFillColor(TEAL)
            tw = len(tag) * 5.5 + 12
            c.roundRect(x, h - 104, tw, 16, 3, fill=1, stroke=0)
            c.setFillColor(WHITE)
            c.setFont("Helvetica-Bold", 7.5)
            c.drawString(x + 6, h - 96, tag)
            x += tw + 6
        # Topics list
        topics = [
            "1. Pharmacokinetics (ADME)",
            "2. Pharmacodynamics",
            "3. Drug-Receptor Interactions",
            "4. Drug Metabolism & Excretion",
            "5. Adverse Drug Reactions",
            "6. Drug Interactions",
            "7. Pharmacogenomics",
            "8. Rational Pharmacotherapy",
        ]
        c.setFillColor(WHITE)
        c.setFont("Helvetica", 8.5)
        col_h = h - 118
        for i, t in enumerate(topics):
            col = 0 if i < 4 else w / 2 + 8
            row = col_h - (i % 4) * 16
            dot_col = TOPIC_COLORS[i]
            c.setFillColor(dot_col)
            c.circle(col + 10, row + 3, 3, fill=1, stroke=0)
            c.setFillColor(WHITE)
            c.drawString(col + 18, row, t)
        # Footer
        c.setFillColor(colors.HexColor("#AED6F1"))
        c.setFont("Helvetica", 7.5)
        c.drawString(16, 10, "Source: Lippincott's Pharmacology | Goodman & Gilman | Katzung's Pharmacology")

    def wrap(self, aw, ah):
        return self._w, self.height


class InfoBox(Flowable):
    """Coloured alert box with left stripe."""
    def __init__(self, label, text, bg, stripe, width=None):
        super().__init__()
        self.label = label
        self.text_str = text
        self.bg = bg
        self.stripe = stripe
        self._w = width or W_PAGE
        para = Paragraph(f"<b>{label}</b> {text}", BOX_S)
        _, self._ph = para.wrap(self._w - 18, 2000)
        self._para = para
        self._h = self._ph + 14

    def draw(self):
        c = self.canv
        c.setFillColor(self.bg)
        c.roundRect(0, 0, self._w, self._h, 3, fill=1, stroke=0)
        c.setFillColor(self.stripe)
        c.rect(0, 0, 4, self._h, fill=1, stroke=0)
        self._para.drawOn(c, 10, 7)

    def wrap(self, aw, ah):
        return self._w, self._h


# ─── TABLE BUILDER ────────────────────────────────────────────────────────────
def tbl(headers, rows, widths, hbg=NAVY):
    data = [[Paragraph(h, TH) for h in headers]]
    for row in rows:
        data.append([Paragraph(str(c), TDL if i == 0 else TD) for i, c in enumerate(row)])
    st = TableStyle([
        ("BACKGROUND",   (0, 0), (-1, 0), hbg),
        ("ROWBACKGROUNDS",(0, 1), (-1,-1), [WHITE, LIGHT_GR]),
        ("GRID",         (0, 0), (-1,-1), 0.3, colors.HexColor("#BFC9CA")),
        ("LEFTPADDING",  (0, 0), (-1,-1), 5),
        ("RIGHTPADDING", (0, 0), (-1,-1), 5),
        ("TOPPADDING",   (0, 0), (-1,-1), 4),
        ("BOTTOMPADDING",(0, 0), (-1,-1), 4),
        ("VALIGN",       (0, 0), (-1,-1), "MIDDLE"),
    ])
    return Table(data, colWidths=widths, style=st, repeatRows=1)


def sp(n=4): return Spacer(1, n)
def hr(): return HRFlowable(width=W_PAGE, thickness=0.4, color=MID_GRAY)


# ─── PAGE TEMPLATE ────────────────────────────────────────────────────────────
def on_page(canvas, doc):
    canvas.saveState()
    w, h = A4
    canvas.setFillColor(NAVY)
    canvas.rect(0, 0, w, 18, fill=1, stroke=0)
    canvas.setFillColor(WHITE)
    canvas.setFont("Helvetica", 7)
    canvas.drawString(14, 5, "General Pharmacology Complete Guide  |  MBBS 2nd Year Prof Exam")
    canvas.drawRightString(w - 14, 5, f"Page {doc.page}")
    canvas.setFillColor(TEAL)
    canvas.rect(0, h - 4, w, 4, fill=1, stroke=0)
    canvas.restoreStore()

def on_page_safe(canvas, doc):
    canvas.saveState()
    w, h = A4
    canvas.setFillColor(NAVY)
    canvas.rect(0, 0, w, 18, fill=1, stroke=0)
    canvas.setFillColor(WHITE)
    canvas.setFont("Helvetica", 7)
    canvas.drawString(14, 5, "General Pharmacology Complete Guide  |  MBBS 2nd Year Prof Exam")
    canvas.drawRightString(w - 14, 5, f"Page {doc.page}")
    canvas.setFillColor(TEAL)
    canvas.rect(0, h - 4, w, 4, fill=1, stroke=0)
    canvas.restoreState()


# ═══════════════════════════════════════════════════════════════════════════════
# CONTENT BUILDERS
# ═══════════════════════════════════════════════════════════════════════════════

def topic1_pharmacokinetics(story, W):
    story.append(SecBanner(1, "PHARMACOKINETICS  —  What the Body Does to the Drug", TEAL, W))
    story.append(sp(6))
    story.append(InfoBox("Definition:", "Pharmacokinetics describes the time course of drug ADME — Absorption, Distribution, Metabolism, Elimination.", PAL_BLUE, TEAL, W))
    story.append(sp(6))

    # Routes of Administration
    story.append(SubBanner("A.  Routes of Drug Administration", TEAL, W))
    story.append(sp(4))
    routes_headers = ["Route", "Key Feature", "Onset", "Bioavailability", "Examples / Notes"]
    routes_rows = [
        ["Oral (PO)", "Most common, convenient", "30-60 min", "Variable (10-100%)", "Tablets, capsules; affected by food, pH, first-pass"],
        ["Sublingual (SL)", "Under tongue; avoids first-pass", "2-5 min", "High", "GTN (nitroglycerin) for angina"],
        ["Buccal", "Between cheek & gum", "5-10 min", "High", "Buprenorphine strips"],
        ["Intravenous (IV)", "100% bioavailability, fastest", "Immediate", "100%", "Emergency drugs; irreversible"],
        ["Intramuscular (IM)", "Aqueous → rapid; depot → slow", "10-30 min", "75-100%", "Vaccines, depot antipsychotics"],
        ["Subcutaneous (SC)", "Slower than IM", "15-30 min", "~75-100%", "Insulin, heparin"],
        ["Transdermal", "Slow, sustained; avoids first-pass", "Hours", "Variable", "GTN patch, fentanyl patch, nicotine patch"],
        ["Inhalation", "Rapid; large surface area", "Seconds-min", "High locally", "Salbutamol inhaler, anaesthetic gases"],
        ["Rectal (PR)", "Bypasses ~50% first-pass", "10-30 min", "30-70%", "Diazepam suppository, ondansetron"],
    ]
    story.append(tbl(routes_headers, routes_rows, [2.8*cm, 3.2*cm, 2.0*cm, 2.4*cm, W-10.4*cm], TEAL))
    story.append(sp(5))
    story.append(InfoBox("MCQ Trap:", "Bioavailability of IV = 100% always. Oral bioavailability is reduced by first-pass metabolism. GTN is given SL not orally because oral route destroys ~90% by first-pass.", PAL_AMB, AMBER, W))
    story.append(sp(8))

    # Absorption
    story.append(SubBanner("B.  Absorption", TEAL, W))
    story.append(sp(4))
    story.append(Paragraph("<b>First-pass metabolism (presystemic metabolism):</b> Oral drugs absorbed from GI tract pass through the portal vein to the liver BEFORE reaching systemic circulation. Extensive first-pass drugs have very low oral bioavailability.", BODY))
    story.append(sp(3))
    story.append(Paragraph("<b>Bioavailability (F) = AUC oral / AUC IV × 100%</b>", S("FA", fontSize=10, textColor=NAVY, fontName="Helvetica-Bold", alignment=TA_CENTER)))
    story.append(sp(4))
    fp_headers = ["Factors Affecting Absorption", "Increases Absorption", "Decreases Absorption"]
    fp_rows = [
        ["Ionization (pH/pKa)", "Unionised form crosses membrane", "Ionised form trapped (ion trapping)"],
        ["Lipid solubility", "Higher lipid solubility → faster", "Highly polar drugs absorbed poorly"],
        ["Blood flow", "High flow (intestine > stomach)", "Shock → poor SC/IM absorption"],
        ["Surface area", "Small intestine (1000x stomach)", "Bowel resection"],
        ["P-glycoprotein", "Inhibited by verapamil", "Overexpressed → multidrug resistance"],
        ["Food", "Fat-rich food → lipid drugs", "Most drugs delayed by food"],
    ]
    story.append(tbl(fp_headers, fp_rows, [3.8*cm, W/2 - 2.9*cm, W/2 - 2.9*cm], TEAL))
    story.append(sp(5))
    story.append(InfoBox("Henderson-Hasselbalch / Ion Trapping:", "Weak acid (e.g. aspirin, pKa 3.5) → unionised in acidic stomach → absorbed. In alkaline intestine → ionised → stays. Weak base (e.g. morphine) → ionised in acid → trapped. Urine alkalinisation used in aspirin OD to trap drug in urine and increase excretion.", PAL_BLUE, TEAL, W))
    story.append(sp(8))

    # Distribution
    story.append(SubBanner("C.  Distribution", TEAL, W))
    story.append(sp(4))
    dist_headers = ["Parameter", "Definition / Formula", "Clinical Significance"]
    dist_rows = [
        ["Volume of Distribution (Vd)", "Vd = Dose / Plasma concentration\n(apparent volume)", "Large Vd = drug in tissues (lipid soluble)\nSmall Vd = drug stays in plasma"],
        ["Plasma protein binding", "Albumin binds acidic drugs\nα1-AGP binds basic drugs", "Only FREE drug is active & eliminated.\nDisplacement interactions possible"],
        ["Blood-brain barrier (BBB)", "Tight junctions + P-glycoprotein", "Only lipid-soluble, unionised drugs cross\n(e.g. diazepam); penicillin excluded normally"],
        ["Placental barrier", "NOT a true barrier", "Most drugs cross; teratogenicity risk\nCategory A-X / newer A-D, X system"],
        ["Redistribution", "Drug moves from target to fat/muscle", "Thiopental: rapid sleep then awakening\ndue to redistribution to fat"],
    ]
    story.append(tbl(dist_headers, dist_rows, [3.2*cm, 5.0*cm, W-8.2*cm], TEAL))
    story.append(sp(8))

    # Zero vs First Order Kinetics
    story.append(SubBanner("D.  Drug Clearance & Kinetics", TEAL, W))
    story.append(sp(4))
    kin_headers = ["Parameter", "First-Order Kinetics", "Zero-Order Kinetics"]
    kin_rows = [
        ["Definition", "Constant FRACTION eliminated per unit time", "Constant AMOUNT eliminated per unit time"],
        ["Elimination rate", "Proportional to plasma concentration", "Independent of plasma concentration"],
        ["Half-life (t½)", "Constant (independent of dose)", "Variable (increases with dose)"],
        ["Graph (log scale)", "Straight line", "Curved / non-linear"],
        ["Examples", "Most drugs (penicillin, paracetamol at low dose)", "Ethanol, phenytoin, aspirin at high dose (SATURATION)"],
        ["Clinical risk", "Predictable", "DANGEROUS — small dose increase → huge plasma level rise"],
    ]
    story.append(tbl(kin_headers, kin_rows, [3.0*cm, W/2 - 2.0*cm, W/2 - 2.0*cm], TEAL))
    story.append(sp(5))

    half_life_data = [
        [Paragraph("<b>Half-Life (t½)</b>", S("HLH", fontSize=9, fontName="Helvetica-Bold", textColor=WHITE, alignment=TA_CENTER)),
         Paragraph("<b>Steady State</b>", S("SSH", fontSize=9, fontName="Helvetica-Bold", textColor=WHITE, alignment=TA_CENTER))],
        [Paragraph("t½ = 0.693 × Vd / CL\n\nTime to halve plasma concentration\n\nDrug reaches steady state in 4-5 half-lives\n\nUseful for dosing interval selection", MONO),
         Paragraph("Steady state = when rate of drug IN = rate of drug OUT\n\nAchieved after 4-5 t½\n\nIndependent of dose (only time to reach it)\n\nLoading dose bypasses the wait:\nLD = Vd × Target concentration / F", MONO)],
    ]
    hl_tbl = Table(half_life_data, colWidths=[W/2 - 4, W/2 - 4], style=TableStyle([
        ("BACKGROUND", (0, 0), (0, 0), TEAL),
        ("BACKGROUND", (1, 0), (1, 0), GREEN),
        ("BACKGROUND", (0, 1), (0, 1), PAL_BLUE),
        ("BACKGROUND", (1, 1), (1, 1), PAL_GREEN),
        ("GRID", (0, 0), (-1,-1), 0.3, colors.HexColor("#BFC9CA")),
        ("TOPPADDING", (0,0),(-1,-1), 6),
        ("BOTTOMPADDING", (0,0),(-1,-1), 6),
        ("LEFTPADDING", (0,0),(-1,-1), 8),
        ("VALIGN", (0,0),(-1,-1), "TOP"),
    ]))
    story.append(hl_tbl)
    story.append(sp(8))


def topic2_pharmacodynamics(story, W):
    story.append(SecBanner(2, "PHARMACODYNAMICS  —  What the Drug Does to the Body", NAVY, W))
    story.append(sp(6))
    story.append(InfoBox("Definition:", "Pharmacodynamics studies the biochemical and physiological effects of drugs and their mechanisms of action, including dose-response relationships.", PAL_BLUE, NAVY, W))
    story.append(sp(6))

    # Receptor families
    story.append(SubBanner("A.  The 4 Receptor Families", NAVY, W))
    story.append(sp(4))
    rf_headers = ["Type", "Mechanism", "Onset", "2nd Messenger", "Examples"]
    rf_rows = [
        ["I — Ligand-gated\nion channels", "Drug opens ion channel directly", "Milliseconds\n(FASTEST)", "None\n(direct)", "Nicotinic ACh\nGABA-A\nGlutamate NMDA"],
        ["II — G protein\ncoupled (GPCR)", "Gs→↑cAMP | Gi→↓cAMP\nGq→↑IP3/DAG/Ca2+", "Seconds", "cAMP, IP3,\nDAG, Ca2+", "α, β adrenoceptors\nMuscarinic\nOpioid receptors"],
        ["III — Enzyme-\nlinked (RTK)", "Receptor dimerises → auto-\nphosphorylates tyrosine", "Minutes", "Phosphorylated\nproteins", "Insulin receptor\nEGF, PDGF, GH"],
        ["IV — Intracellular\n(Nuclear)", "Lipid ligand enters nucleus\n→ alters gene transcription", "Hours\n(SLOWEST)", "mRNA, protein\nsynthesis", "Glucocorticoids\nSex hormones\nThyroid hormone"],
    ]
    story.append(tbl(rf_headers, rf_rows, [2.8*cm, 3.6*cm, 2.0*cm, 2.4*cm, W-10.8*cm], NAVY))
    story.append(sp(5))
    story.append(InfoBox("Memory:", "Fastest to slowest: Ion channels → G proteins → Enzyme-linked → Intracellular (mnemonic: I Got Every Item)", PAL_BLUE, NAVY, W))
    story.append(sp(8))

    # Agonist/Antagonist
    story.append(SubBanner("B.  Types of Ligands", NAVY, W))
    story.append(sp(4))
    lig_headers = ["Type", "Intrinsic Activity (IA)", "Effect", "Drug Examples"]
    lig_rows = [
        ["Full Agonist", "IA = 1", "Maximal activation of receptor (Emax)", "Morphine, adrenaline, salbutamol, ACh"],
        ["Partial Agonist", "0 < IA < 1", "Submaximal; blocks full agonist when present (dual role)", "Buprenorphine, pindolol, aripiprazole, buspirone"],
        ["Competitive Antagonist", "IA = 0", "Reversible block; right-shifts DRC; Emax unchanged", "Atropine, naloxone, propranolol, cetirizine"],
        ["Non-competitive Antagonist", "IA = 0", "Irreversible/allosteric; Emax reduced; insurmountable", "Phenoxybenzamine, aspirin (COX), organophosphates"],
        ["Inverse Agonist", "IA < 0", "Stabilises inactive receptor; opposes constitutive activity", "Beta-carbolines; some H1 antihistamines"],
        ["Chemical Antagonist", "N/A", "Drug binds directly to the agonist chemically", "Protamine + heparin; EDTA + heavy metals"],
        ["Physiological Antagonist", "N/A", "Two drugs produce OPPOSITE effects at DIFFERENT receptors", "Histamine (vasodilation) vs. adrenaline (vasoconstriction)"],
    ]
    story.append(tbl(lig_headers, lig_rows, [3.0*cm, 2.4*cm, 4.0*cm, W-9.4*cm], NAVY))
    story.append(sp(8))

    # Dose-response
    story.append(SubBanner("C.  Dose-Response Relationships", NAVY, W))
    story.append(sp(4))
    drc_headers = ["Concept", "Definition", "Formula/Value", "Clinical Importance"]
    drc_rows = [
        ["Potency", "Amount of drug needed for 50% effect", "EC50 (lower = more potent)", "Determines therapeutic dose range"],
        ["Efficacy", "Maximum response a drug can produce", "Emax (higher = more efficacious)", "Clinically MORE important than potency"],
        ["Affinity", "Strength of drug-receptor binding", "KD (dissociation constant)", "High affinity = strong binding"],
        ["Graded DRC", "Continuous response vs. log dose", "Sigmoid S-shaped curve", "Individual drug-receptor relationships"],
        ["Quantal DRC", "% population responding vs. log dose", "Cumulative frequency curve", "Population-level responses; TI calculation"],
        ["Therapeutic Index", "Safety margin of drug", "TI = TD50 / ED50", "Higher TI = safer; narrow TI = monitor!"],
        ["Ceiling Effect", "Maximum effect regardless of dose increase", "Emax reached", "Paracetamol ceiling; increasing dose only increases toxicity"],
    ]
    story.append(tbl(drc_headers, drc_rows, [2.5*cm, 3.5*cm, 2.5*cm, W-8.5*cm], NAVY))
    story.append(sp(5))

    # Competitive vs non-competitive table
    story.append(SubBanner("D.  Antagonism & Dose-Response Curve Changes", NAVY, W))
    story.append(sp(4))
    antagn = [
        ["Competitive (reversible)", "Parallel RIGHT shift", "UNCHANGED", "Increased", "Surmountable (overcome by more agonist)"],
        ["Non-competitive (irreversible)", "Downward compression", "DECREASED", "Unchanged / ↑", "Insurmountable (cannot overcome)"],
        ["Partial agonist in presence of full agonist", "Reduces response", "DECREASED to partial Emax", "—", "Displaces full agonist; acts as partial blocker"],
    ]
    story.append(tbl(["Antagonism Type", "Curve Change", "Emax", "EC50", "Key Feature"],
                     antagn, [3.5*cm, 2.8*cm, 2.2*cm, 1.8*cm, W-10.3*cm], NAVY))
    story.append(sp(8))


def topic3_drug_metabolism(story, W):
    story.append(SecBanner(3, "DRUG METABOLISM & EXCRETION", GREEN, W))
    story.append(sp(6))
    story.append(InfoBox("Purpose:", "Drug metabolism (biotransformation) converts lipid-soluble drugs into polar, water-soluble metabolites for excretion. The liver is the primary site. Most metabolites are INACTIVE, but some are active (prodrugs).", PAL_GREEN, GREEN, W))
    story.append(sp(6))

    story.append(SubBanner("A.  Phases of Metabolism", GREEN, W))
    story.append(sp(4))
    phase_headers = ["Phase", "Reaction Type", "Enzyme System", "Result", "Examples"]
    phase_rows = [
        ["Phase I\n(Functionalization)", "Oxidation (most common)\nReduction, Hydrolysis", "Cytochrome P450\n(CYP enzymes)\nin liver ER", "Adds/exposes functional group\n(-OH, -NH2, -SH)\nMay produce active/toxic metabolite", "CYP3A4 → midazolam\nCYP2D6 → codeine → morphine\nCYP2C9 → warfarin"],
        ["Phase II\n(Conjugation)", "Glucuronidation (most common)\nSulfation, Acetylation\nMethylation, Glutathione", "UDP-glucuronosyl\ntransferase (UGT)\nSulfotransferases, etc.", "Makes drug MORE polar\n→ water soluble\nUsually INACTIVE", "Paracetamol → glucuronide\nIsoniazid → acetylation\nMorphine-6-glucuronide (active!)"],
    ]
    story.append(tbl(phase_headers, phase_rows, [2.2*cm, 3.0*cm, 3.0*cm, 3.5*cm, W-11.7*cm], GREEN))
    story.append(sp(5))

    story.append(SubBanner("B.  Cytochrome P450 Enzymes — High Yield for Exams", GREEN, W))
    story.append(sp(4))
    cyp_headers = ["CYP Enzyme", "Important Substrates", "Inducers (↑ metabolism)", "Inhibitors (↓ metabolism)"]
    cyp_rows = [
        ["CYP3A4\n(most abundant ~50%)", "Midazolam, cyclosporin\nStatins, HIV drugs, Ca-blockers", "Rifampicin, carbamazepine\nPhenytoin, phenobarbitone\nSt. John's Wort", "Erythromycin, azole antifungals\nGrapefruit juice, HIV PIs"],
        ["CYP2D6\n(genetic polymorphism)", "Codeine → morphine\nTricyclic antidepressants\nβ-blockers (metoprolol)", "—", "Fluoxetine, paroxetine\nHaloperidol, quinidine"],
        ["CYP2C9", "Warfarin (S-), phenytoin\nNSAIDs (ibuprofen)", "Rifampicin", "Fluconazole, amiodarone\nValproic acid"],
        ["CYP2C19", "Omeprazole, diazepam\nClopidogrel (prodrug!)", "Rifampicin", "Omeprazole, fluvoxamine"],
        ["CYP1A2", "Theophylline, caffeine\nClozapine, olanzapine", "Smoking, chargrilled food\nOmeprazole", "Ciprofloxacin, fluvoxamine"],
    ]
    story.append(tbl(cyp_headers, cyp_rows, [2.4*cm, 3.5*cm, 3.5*cm, W-9.4*cm], GREEN))
    story.append(sp(5))
    story.append(InfoBox("Induction vs Inhibition:", "Enzyme INDUCERS increase drug metabolism → reduce drug effect (take days to work, e.g. rifampicin reduces OCP efficacy). Enzyme INHIBITORS decrease metabolism → drug toxicity (fast onset, e.g. erythromycin + warfarin = bleeding risk).", PAL_AMB, AMBER, W))
    story.append(sp(6))

    story.append(SubBanner("C.  First-Pass Metabolism & Prodrugs", GREEN, W))
    story.append(sp(4))
    prodrug_headers = ["Concept", "Detail", "Examples"]
    prodrug_rows = [
        ["High first-pass drugs\n(low oral bioavailability)", "Extensive hepatic extraction after oral absorption\nAlternative routes preferred", "GTN (SL), lidocaine (IV), morphine (large oral dose)\nPropranolol, verapamil, labetalol"],
        ["Prodrugs\n(inactive → active)", "Require metabolism to become active\nUseful to improve absorption/stability", "Codeine → morphine (CYP2D6)\nEnalapril → enalaprilat\nClopidogrel → active thiol (CYP2C19)\nAciclovir → aciclovir triphosphate\nLevodopa → dopamine"],
        ["Active metabolites", "Parent drug metabolised to active compound", "Diazepam → desmethyldiazepam\nMorphine → morphine-6-glucuronide (M6G)"],
    ]
    story.append(tbl(prodrug_headers, prodrug_rows, [3.0*cm, 5.0*cm, W-8.0*cm], GREEN))
    story.append(sp(6))

    story.append(SubBanner("D.  Drug Excretion", GREEN, W))
    story.append(sp(4))
    excr_headers = ["Route", "Mechanism", "Factors", "Clinical Notes"]
    excr_rows = [
        ["Renal (main route)", "Glomerular filtration\nTubular secretion (active)\nTubular reabsorption (passive)", "pKa, urine pH, protein binding\nRenal function (GFR)", "Acidify urine → trap basic drugs\nAlkalinise urine → trap acidic drugs\n(Used in salicylate / amphetamine OD)"],
        ["Biliary / Faecal", "Liver secretes drug into bile\n→ intestine → faeces", "Molecular weight >300 Da\nGlucuronides", "Enterohepatic circulation prolongs drug action\n(ethinyl estradiol, morphine)"],
        ["Pulmonary", "Volatile/gaseous drugs exhaled", "Lipid solubility, blood:gas partition", "Anaesthetic gases; ethanol (breath test)"],
        ["Milk", "Passive diffusion; lipid-soluble\nweak bases concentrate in milk", "Drug lipophilicity, ionization, MW", "Codeine in breastfeeding mothers caused neonatal deaths"],
        ["Other", "Saliva, sweat, tears\n(minor routes)", "Drug physicochemical properties", "Rifampicin colours urine/sweat orange"],
    ]
    story.append(tbl(excr_headers, excr_rows, [2.4*cm, 3.4*cm, 3.0*cm, W-8.8*cm], GREEN))
    story.append(sp(8))


def topic4_ADR(story, W):
    story.append(SecBanner(4, "ADVERSE DRUG REACTIONS  (ADRs)", PURPLE, W))
    story.append(sp(6))
    story.append(InfoBox("Definition (WHO):", "An ADR is any noxious, unintended response to a drug occurring at doses normally used for prophylaxis, diagnosis or therapy.", PAL_PURP, PURPLE, W))
    story.append(sp(6))

    story.append(SubBanner("A.  Classification of ADRs (ABCDE System)", PURPLE, W))
    story.append(sp(4))
    adr_headers = ["Type", "Name", "Features", "Examples"]
    adr_rows = [
        ["Type A\n(Augmented)", "Dose-dependent\n(most common ~80%)", "Predictable, dose-related\nExtension of pharmacological effect\nLow mortality", "Bleeding with warfarin\nHypoglycaemia with insulin\nBradycardia with β-blockers"],
        ["Type B\n(Bizarre)", "Idiosyncratic\n~10-15%", "Unpredictable, NOT dose-related\nImmunological or pharmacogenetic\nHigh mortality", "Anaphylaxis with penicillin\nMalignant hyperthermia (suxamethonium)\nSJS/TEN (carbamazepine, allopurinol)"],
        ["Type C\n(Chronic)", "Continuous use", "Related to cumulative dose / long-term use", "Adrenal suppression (steroids)\nOsteoporosis (steroids)\nTardive dyskinesia (antipsychotics)"],
        ["Type D\n(Delayed)", "Delayed onset", "Years after treatment", "Carcinogenesis (alkylating agents)\nTeratogenicity (thalidomide)\nTardive dyskinesia"],
        ["Type E\n(End of use)", "Withdrawal", "On stopping drug abruptly", "Opioid withdrawal\nBenzodiazepine withdrawal\nCorticosteroid withdrawal"],
    ]
    story.append(tbl(adr_headers, adr_rows, [1.8*cm, 2.4*cm, 3.5*cm, W-7.7*cm], PURPLE))
    story.append(sp(6))

    story.append(SubBanner("B.  Important Specific ADRs to Know", PURPLE, W))
    story.append(sp(4))
    specific_headers = ["Drug / Drug Class", "Important ADR", "Mechanism / Notes"]
    specific_rows = [
        ["Aminoglycosides\n(gentamicin, amikacin)", "Nephrotoxicity\nOtotoxicity (irreversible!)", "Accumulation in proximal tubule and cochlear hair cells\nMonitor levels; avoid in renal failure"],
        ["Aspirin", "GI bleed, Reye syndrome (children)\nSalicylism (tinnitus, deafness)", "COX-1 inhibition → ↓ mucosal protection\nAvoid in children with viral illness"],
        ["Corticosteroids\n(long-term)", "Cushing's, osteoporosis, immunosuppression\nAdrenal suppression, hyperglycaemia", "HPA axis suppression with long-term use\nNever stop abruptly"],
        ["Chloramphenicol", "Grey baby syndrome (neonates)\nAplastic anaemia (rare, idiosyncratic)", "Immature glucuronidation in neonates → drug accumulates"],
        ["Methotrexate", "Bone marrow suppression, hepatotoxicity\nMucositis", "Folinic acid (leucovorin) used as rescue"],
        ["ACE inhibitors\n(enalapril, ramipril)", "Dry cough (~15%), hyperkalaemia\nAngioedema (rare but serious)", "↑ Bradykinin (cough, angioedema)\nSwitch to ARB if cough intolerable"],
        ["Statins", "Myopathy, rhabdomyolysis (rare)\n↑ liver enzymes", "Risk ↑ with CYP3A4 inhibitors\nCheck CK if muscle pain"],
        ["Thalidomide", "Teratogenicity (phocomelia)", "Given to pregnant women in 1960s\nStrictly contraindicated in pregnancy"],
        ["Quinolones\n(ciprofloxacin)", "Tendinopathy/tendon rupture\nQT prolongation, phototoxicity", "Avoid in children (cartilage damage)\nBlack box warning for tendons"],
        ["Clozapine", "Agranulocytosis (life-threatening!)\nWeight gain, seizures, hypersalivation", "Mandatory WBC monitoring weekly → monthly"],
    ]
    story.append(tbl(specific_headers, specific_rows, [3.2*cm, 3.5*cm, W-6.7*cm], PURPLE))
    story.append(sp(6))

    story.append(SubBanner("C.  Pharmacovigilance", PURPLE, W))
    story.append(sp(4))
    story.append(Paragraph("<b>Yellow Card Scheme (UK) / Suspected ADR reporting:</b> Healthcare professionals and patients report suspected ADRs to regulatory bodies (e.g. CDSCO in India). Reports contribute to post-marketing surveillance.", BODY))
    story.append(sp(3))
    naranjo_data = [
        [Paragraph("<b>Causality Assessment — Naranjo Scale</b>", TH)],
        [Paragraph("1 — Definite: >9 points | 2 — Probable: 5-8 | 3 — Possible: 1-4 | 4 — Doubtful: ≤0\nKey questions: Previous conclusive report? After drug given? Improved on withdrawal? Reappeared on rechallenge? Alternative cause? Placebo reaction? Drug level detected? Dose-response?", MONO)],
    ]
    story.append(Table(naranjo_data, colWidths=[W], style=TableStyle([
        ("BACKGROUND", (0,0), (-1,0), PURPLE),
        ("BACKGROUND", (0,1), (-1,1), PAL_PURP),
        ("GRID", (0,0),(-1,-1), 0.3, colors.HexColor("#D2B4DE")),
        ("TOPPADDING",(0,0),(-1,-1), 6), ("BOTTOMPADDING",(0,0),(-1,-1),6),
        ("LEFTPADDING",(0,0),(-1,-1), 8),
    ])))
    story.append(sp(8))


def topic5_drug_interactions(story, W):
    story.append(SecBanner(5, "DRUG INTERACTIONS", AMBER, W))
    story.append(sp(6))
    story.append(InfoBox("Definition:", "A drug interaction occurs when the pharmacological effect of one drug is altered by the co-administration of another drug, food, or substance.", PAL_AMB, AMBER, W))
    story.append(sp(6))

    story.append(SubBanner("A.  Types of Drug Interactions", AMBER, W))
    story.append(sp(4))
    di_headers = ["Type", "Mechanism", "Clinical Examples"]
    di_rows = [
        ["Pharmaceutical\n(in vitro)", "Chemical incompatibility outside body\n(in IV line, syringe)", "Heparin + aminoglycoside precipitate in IV line\nDiazepam precipitates in saline"],
        ["Pharmacokinetic\n(ADME altered)", "One drug alters ADME of another\n(See subtypes below)", "Rifampicin + OCP → OCP failure\nErythromycin + warfarin → bleeding"],
        ["Pharmacodynamic\n(at receptor / effector)", "Additive, synergistic or antagonistic effects\nat same or different receptors", "Aspirin + warfarin → ↑↑ bleeding (additive)\nβ-agonist + β-blocker → antagonism\nAlcohol + benzodiazepine → ↑ CNS depression"],
    ]
    story.append(tbl(di_headers, di_rows, [2.6*cm, 4.2*cm, W-6.8*cm], AMBER))
    story.append(sp(6))

    story.append(SubBanner("B.  Pharmacokinetic Drug Interactions (ADME)", AMBER, W))
    story.append(sp(4))
    pk_di_headers = ["Stage", "Interaction Example", "Result"]
    pk_di_rows = [
        ["Absorption", "Antacids + tetracycline/fluoroquinolone → chelation\nMetoclopramide ↑ absorption by ↑ gastric emptying", "↓ antibiotic efficacy\nAltered drug levels"],
        ["Distribution\n(Protein binding)", "Aspirin displaces warfarin from albumin\n(less significant clinically now)", "Transient ↑ free warfarin"],
        ["Metabolism\n(CYP induction)", "Rifampicin + warfarin → ↑ warfarin metabolism\nRifampicin + OCP → contraceptive failure", "↓ drug effect; need dose increase"],
        ["Metabolism\n(CYP inhibition)", "Erythromycin + simvastatin → ↑ statin levels → myopathy\nFluconazole + warfarin → ↑↑ bleeding\nGrapefruit + statins/amlodipine", "↑ drug toxicity"],
        ["Excretion\n(renal)", "Probenecid blocks tubular secretion of penicillin\nNSAIDs ↓ renal blood flow → ↑ lithium levels", "Prolonged penicillin effect\nLithium toxicity"],
    ]
    story.append(tbl(pk_di_headers, pk_di_rows, [2.8*cm, 5.2*cm, W-8.0*cm], AMBER))
    story.append(sp(6))

    story.append(SubBanner("C.  Pharmacodynamic Interactions", AMBER, W))
    story.append(sp(4))
    pd_di_headers = ["Type", "Definition", "Example"]
    pd_di_rows = [
        ["Additive", "Effect = sum of individual effects (1+1=2)", "Aspirin + warfarin (bleeding)\nTwo antihypertensives"],
        ["Synergism", "Effect > sum of individual effects (1+1>2)", "Trimethoprim + sulphamethoxazole (co-trimoxazole)\nβ-lactam + aminoglycoside (bactericidal)"],
        ["Potentiation", "One drug enhances effect of another (0+1=3)", "Probenecid + penicillin (prolongs action)\nNeostigmine + suxamethonium"],
        ["Antagonism\n(Physiological)", "Drugs act at DIFFERENT receptors, opposite effects", "Adrenaline reverses histamine in anaphylaxis\nNaloxone reverses opioids"],
        ["Antagonism\n(Pharmacological)", "Competitive or non-competitive at SAME receptor", "Atropine + pilocarpine\nFlumazenil + benzodiazepine"],
    ]
    story.append(tbl(pd_di_headers, pd_di_rows, [2.6*cm, 3.8*cm, W-6.4*cm], AMBER))
    story.append(sp(6))

    story.append(InfoBox("High-Risk Combinations to Memorise:", "MAOIs + SSRIs → Serotonin syndrome (FATAL) | MAOIs + pethidine → Serotonin syndrome | Warfarin + amiodarone → Bleeding | Digoxin + amiodarone → Digoxin toxicity | Methotrexate + NSAIDs → ↓ MTX excretion → bone marrow suppression | Clozapine + carbamazepine → agranulocytosis | Lithium + NSAIDs/thiazides → Lithium toxicity", PAL_RED, RED_D, W))
    story.append(sp(8))


def topic6_pharmacogenomics(story, W):
    story.append(SecBanner(6, "PHARMACOGENOMICS & INDIVIDUAL VARIATION", BLUE_MID, W))
    story.append(sp(6))
    story.append(InfoBox("Definition:", "Pharmacogenomics studies how genetic variation in individuals affects drug response. This determines why the same drug at the same dose produces different effects in different patients.", PAL_BLUE, BLUE_MID, W))
    story.append(sp(6))

    story.append(SubBanner("A.  Genetic Polymorphisms Affecting Drug Metabolism", BLUE_MID, W))
    story.append(sp(4))
    pg_headers = ["Gene / Enzyme", "Phenotypes", "Drug Affected", "Clinical Consequence"]
    pg_rows = [
        ["CYP2D6\n(~7% Caucasians poor metabolisers)", "Poor metaboliser (PM)\nIntermediate (IM)\nExtensive (EM)\nUltra-rapid (UM)", "Codeine, tramadol\nTricyclic ADs, tamoxifen\nβ-blockers", "PM → codeine gives NO analgesia (can't convert to morphine)\nUM → excessive morphine → toxicity (neonatal deaths in breastfed infants)"],
        ["N-acetyltransferase 2\n(NAT2)", "Slow acetylators (~50% Indians)\nFast acetylators", "Isoniazid, hydralazine\nProcainamide, dapsone", "Slow: ↑ isoniazid toxicity (peripheral neuropathy)\nFast: ↓ drug effect, TB treatment failure\nSlow + hydralazine → drug-induced lupus"],
        ["CYP2C19", "PM (~20% Asians)\nEM", "Clopidogrel (prodrug)\nOmeprazole, diazepam", "PM → clopidogrel NOT activated → no antiplatelet effect → stent thrombosis risk"],
        ["TPMT\n(thiopurine methyltransferase)", "Deficient (rare)\nLow activity\nNormal", "Azathioprine\n6-mercaptopurine", "Deficient → cannot metabolise → severe bone marrow suppression\nTest TPMT before giving azathioprine"],
        ["G6PD deficiency\n(X-linked)", "Deficient (common in Africans, Indians)", "Primaquine, dapsone\nNitrofurantoin, sulfonamides", "Haemolytic anaemia with oxidant drugs\nMust screen before antimalarials in endemic areas"],
        ["HLA-B*5701", "Carriers (~5-8% Caucasians)", "Abacavir (antiretroviral)", "Severe hypersensitivity reaction\nScreen ALL patients before abacavir"],
        ["HLA-B*1502", "Carriers (South-East Asians)", "Carbamazepine", "Stevens-Johnson Syndrome (SJS)\nScreen Asians before starting carbamazepine"],
    ]
    story.append(tbl(pg_headers, pg_rows, [2.8*cm, 2.6*cm, 2.4*cm, W-7.8*cm], BLUE_MID))
    story.append(sp(6))

    story.append(SubBanner("B.  Other Sources of Individual Variation", BLUE_MID, W))
    story.append(sp(4))
    var_headers = ["Factor", "Effect on Drug Response", "Example"]
    var_rows = [
        ["Age — Neonates", "Immature enzymes (CYP, UGT)\nLow plasma protein\nHigher Vd (more body water)", "Chloramphenicol → grey baby syndrome\nMorphine → apnoea\nHigher doses/kg for some drugs"],
        ["Age — Elderly", "↓ hepatic blood flow, ↓ GFR\n↓ albumin, ↑ body fat\nAltered receptor sensitivity", "↑ drug levels → toxicity\nBenzodiazepines → confusion/falls\nACE inhibitors → ↑ hyperkalemia risk"],
        ["Pregnancy", "↑ plasma volume, ↑ GFR\n↑ CYP3A4, ↓ CYP1A2\nAltered protein binding", "Drug doses may need adjustment\nAvoid teratogens (category X)\nRifampicin → ↑↑ OCP metabolism"],
        ["Hepatic disease", "↓ first-pass, ↓ CYP activity\n↓ albumin, ↑ portal pressure", "↑ oral bioavailability of high first-pass drugs\nAccumulation of hepatically metabolised drugs"],
        ["Renal disease", "↓ GFR → drug accumulation\n↓ protein binding (uraemia)", "Aminoglycoside toxicity ↑\nAdjust doses using Cockcroft-Gault formula\nAvoid NSAIDs (worsen GFR)"],
        ["Body weight / obesity", "↑ Vd for lipophilic drugs\nAltered CYP activity", "Loading doses based on actual body weight (e.g. amiodarone)\nMaintenance doses sometimes lean body weight"],
    ]
    story.append(tbl(var_headers, var_rows, [2.8*cm, 3.8*cm, W-6.6*cm], BLUE_MID))
    story.append(sp(8))


def topic7_special_populations(story, W):
    story.append(SecBanner(7, "DRUG USE IN SPECIAL POPULATIONS & TERATOLOGY", RED_D, W))
    story.append(sp(6))

    story.append(SubBanner("A.  FDA Pregnancy Categories (Old System — Still Tested)", RED_D, W))
    story.append(sp(4))
    preg_headers = ["Category", "Definition", "Examples"]
    preg_rows = [
        ["A", "Adequate human studies show NO risk in 1st trimester", "Folic acid, thyroxine, iron"],
        ["B", "Animal studies OK; no adequate human studies OR\nanimal harm but human studies reassuring", "Penicillin, paracetamol, metformin\nAmoxicillin, cetirizine"],
        ["C", "Animal studies show adverse effects;\nno adequate human studies; benefit may outweigh risk", "Aspirin, quinolones, fluconazole\nCodeine (3rd trimester)"],
        ["D", "Human evidence of fetal risk; may be acceptable\nif life-threatening situation", "Carbamazepine, valproate\nTetracyclines, lithium\nAminoglycosides"],
        ["X", "CONTRAINDICATED in pregnancy — risks outweigh benefits", "Thalidomide, isotretinoin, warfarin\nMethotrexate, statins, misoprostol\nACE inhibitors (2nd-3rd tri), live vaccines"],
    ]
    story.append(tbl(preg_headers, preg_rows, [1.6*cm, 4.0*cm, W-5.6*cm], RED_D))
    story.append(sp(5))
    story.append(InfoBox("Classic Teratogens:", "WARFARIN → fetal warfarin syndrome (nasal hypoplasia, stippled epiphyses) | THALIDOMIDE → phocomelia (seal limbs) | ISOTRETINOIN → craniofacial defects, cardiac | VALPROATE → neural tube defects, spina bifida | ACE inhibitors (2nd-3rd trimester) → renal agenesis | TETRACYCLINES → yellow teeth, bone growth inhibition | ALCOHOL → fetal alcohol syndrome", PAL_RED, RED_D, W))
    story.append(sp(6))

    story.append(SubBanner("B.  Paediatric Pharmacology", RED_D, W))
    story.append(sp(4))
    story.append(Paragraph("<b>Key Differences in Children vs. Adults:</b>", HEAD3))
    paed_rows = [
        ["Organ system", "Neonates / Infants", "Clinical Impact"],
        ["GI tract", "↑ gastric pH (less acid), slower motility", "Altered absorption of acid-labile and pH-dependent drugs"],
        ["Body composition", "More total body water (70-80%)\nLess body fat", "↑ Vd for water-soluble drugs\nHigher mg/kg doses needed"],
        ["Protein binding", "↓ albumin, ↑ fetal albumin (lower affinity)", "↑ free drug fraction → ↑ effect/toxicity"],
        ["Liver metabolism", "↓ CYP450 activity (matures by 1-2 years)\n↑ glucuronidation by 2-3 years", "Chloramphenicol toxicity\nLonger drug half-lives"],
        ["Renal function", "↓ GFR (matures by 1 year)", "Reduced drug elimination → accumulation"],
        ["BBB", "More permeable", "CNS side effects more pronounced"],
    ]
    story.append(Table([[Paragraph(r[0], TH if i == 0 else TDL),
                        Paragraph(r[1], TH if i == 0 else TD),
                        Paragraph(r[2], TH if i == 0 else TDL)]
                       for i, r in enumerate(paed_rows)],
                      colWidths=[2.5*cm, 4.5*cm, W-7.0*cm],
                      style=TableStyle([
                          ("BACKGROUND",(0,0),(-1,0),RED_D),
                          ("ROWBACKGROUNDS",(0,1),(-1,-1),[WHITE,PAL_RED]),
                          ("GRID",(0,0),(-1,-1),0.3,colors.HexColor("#E74C3C")),
                          ("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4),
                          ("LEFTPADDING",(0,0),(-1,-1),5), ("VALIGN",(0,0),(-1,-1),"TOP"),
                      ])))
    story.append(sp(5))
    story.append(InfoBox("Drugs to AVOID in specific ages:", "ASPIRIN in children < 12 with viral illness → Reye syndrome | TETRACYCLINES < 8 years → teeth/bone | QUINOLONES < 18 → cartilage | CHLORAMPHENICOL in neonates → grey baby | CODEINE in children < 12 (especially CYP2D6 ultra-rapid) | METOCLOPRAMIDE < 1 year → extrapyramidal effects", PAL_AMB, AMBER, W))
    story.append(sp(8))


def topic8_rational_prescribing(story, W):
    story.append(SecBanner(8, "RATIONAL PHARMACOTHERAPY & ESSENTIAL CONCEPTS", SLATE, W))
    story.append(sp(6))

    story.append(SubBanner("A.  Principles of Rational Drug Therapy (WHO STEPS)", SLATE, W))
    story.append(sp(4))
    rational_rows = [
        ["Step 1", "Define the patient's problem"],
        ["Step 2", "Specify the therapeutic objective"],
        ["Step 3", "Make an inventory of effective groups of treatments (P-drugs)"],
        ["Step 4", "Choose your P-treatment: verify suitability"],
        ["Step 5", "Start the treatment"],
        ["Step 6", "Give information, instructions, and warnings"],
        ["Step 7", "Monitor (stop?) the treatment"],
    ]
    story.append(Table([[Paragraph(f"<b>{r[0]}</b>", S("RA", fontSize=9, fontName="Helvetica-Bold", textColor=WHITE, alignment=TA_CENTER)),
                         Paragraph(r[1], TDL)] for r in rational_rows],
                      colWidths=[1.5*cm, W-1.5*cm],
                      style=TableStyle([
                          ("BACKGROUND",(0,0),(-1,-1),[[SLATE,WHITE][i%2] for i in range(7)]),
                          ("BACKGROUND",(0,0),(0,-1),SLATE),
                          ("GRID",(0,0),(-1,-1),0.3,colors.HexColor("#BFC9CA")),
                          ("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(sp(6))

    story.append(SubBanner("B.  Essential Drugs Concept (WHO)", SLATE, W))
    story.append(sp(4))
    story.append(Paragraph("Essential medicines are those that satisfy the priority health care needs of the population. Selected with regard to efficacy, safety, quality, and cost-effectiveness. The <b>WHO Essential Medicines List (EML)</b> is updated every 2 years. India has its <b>National List of Essential Medicines (NLEM)</b>.", BODY))
    story.append(sp(5))

    story.append(SubBanner("C.  Prescribing — Important Concepts", SLATE, W))
    story.append(sp(4))
    presc_headers = ["Concept", "Definition / Formula", "Clinical Application"]
    presc_rows = [
        ["Loading Dose (LD)", "LD = Vd × Target Cp / F\n\nOne-time large dose to rapidly achieve therapeutic levels", "Used when immediate effect needed\n(digoxin loading in AF, IV amiodarone, loading dose vancomycin)\nRisky in renal/hepatic impairment"],
        ["Maintenance Dose (MD)", "MD = CL × Target Cp × τ / F\n\nDose to maintain steady-state level", "Regular dosing to replace drug eliminated\nbetween doses"],
        ["Therapeutic Drug\nMonitoring (TDM)", "Measuring plasma drug levels to guide dosing", "Used for narrow TI drugs:\nDigoxin, lithium, phenytoin, aminoglycosides\nCyclosporin, vancomycin, theophylline"],
        ["Tachyphylaxis", "Rapid decrease in response with\nrepeated doses (minutes-hours)", "GTN (nitrate tolerance)\nEphedrine, indirect sympathomimetics"],
        ["Tolerance", "Gradual decrease in response\n(days-weeks of repeated use)", "Opioids (need dose escalation)\nBenzodiazepines\nAmphetamines"],
        ["Dependence\n(Physical)", "Withdrawal syndrome on stopping drug", "Opioids, benzodiazepines, alcohol\nBeta-blockers (rebound hypertension)"],
        ["Placebo Effect", "Response due to belief, not drug chemistry", "~30% of analgesic effect may be placebo\nImportant in clinical trial design (RCTs blinded)"],
    ]
    story.append(tbl(presc_headers, presc_rows, [2.8*cm, 4.0*cm, W-6.8*cm], SLATE))
    story.append(sp(6))

    story.append(SubBanner("D.  Drug Nomenclature", SLATE, W))
    story.append(sp(4))
    nomen_headers = ["Name Type", "Definition", "Example"]
    nomen_rows = [
        ["Chemical name", "Describes molecular structure\n(IUPAC nomenclature)", "N-(4-hydroxyphenyl)acetamide"],
        ["Generic name\n(INN / non-proprietary)", "International Non-proprietary Name\nGiven by WHO", "Paracetamol / Acetaminophen"],
        ["Brand name\n(Proprietary)", "Manufacturer's trade name\n(capitalised)", "Calpol®, Tylenol®, Metacin®"],
        ["Pharmacopoeial name", "Official name in a pharmacopoeia\n(IP, BP, USP)", "Usually same as generic name"],
    ]
    story.append(tbl(nomen_headers, nomen_rows, [2.8*cm, 3.8*cm, W-6.6*cm], SLATE))
    story.append(sp(6))

    story.append(SubBanner("E.  Clinical Trial Phases (Drug Development)", SLATE, W))
    story.append(sp(4))
    trial_headers = ["Phase", "Subjects", "Primary Aim", "Sample Size"]
    trial_rows = [
        ["Phase 0\n(Exploratory)", "Healthy volunteers (few)", "Microdosing studies; pharmacokinetics", "< 15"],
        ["Phase I", "Healthy volunteers", "Safety, tolerability, PK/PD\nMaximum tolerated dose (MTD)", "20-100"],
        ["Phase II", "Patients with disease", "Efficacy, dose-ranging, side effects", "100-500"],
        ["Phase III", "Large patient population\n(multi-centre, RCT)", "Efficacy vs. placebo or standard treatment\nConfirm safety; regulatory submission", "1000-5000+"],
        ["Phase IV\n(Post-marketing)", "General population", "Long-term safety, rare ADRs\nNew indications, pharmacoeconomics", "Thousands+"],
    ]
    story.append(tbl(trial_headers, trial_rows, [2.2*cm, 3.0*cm, 5.0*cm, W-10.2*cm], SLATE))
    story.append(sp(8))


def quick_revision_card(story, W):
    story.append(SecBanner("★", "QUICK REVISION MNEMONICS & EXAM TIPS", colors.HexColor("#B7950B"), W))
    story.append(sp(6))

    mnemonics = [
        ("ADME", "Absorption → Distribution → Metabolism → Elimination\n(What the BODY does to the drug — Pharmacokinetics)"),
        ("Ion trapping rule", "Weak ACID absorbed in ACID stomach (both are acidic)\nWeak BASE excreted in ACID urine (opposite environments trap them)"),
        ("First-pass drugs (GLMP)", "GTN, Lidocaine, Morphine, Propranolol (also verapamil, labetalol, nifedipine)\n→ All need SL/IV/patch routes due to high first-pass"),
        ("Zero-order drugs (PAE)", "Phenytoin, Aspirin (high dose), Ethanol → saturation kinetics"),
        ("Narrow TI drugs (DWAMP-T)", "Digoxin, Warfarin, Aminoglycosides, Methotrexate\nPhenytoin, Theophylline, Lithium\n→ All require TDM"),
        ("Enzyme inducers (PC BRAS)", "Phenytoin, Carbamazepine, Barbiturates\nRifampicin, Alcohol (chronic), St. John's Wort"),
        ("Enzyme inhibitors (CAGE FASCIA)", "Ciprofloxacin, Azole antifungals, Grapefruit juice, Erythromycin\nFluoxetine, Amiodarone, Sulphonamides, Cimetidine, Isoniazid, Alcohol (acute)"),
        ("Type A ADR", "A = Augmented pharmacological effect\nA = dose-relAted, predictAble, commonest (80%), low mortality"),
        ("Type B ADR", "B = Bizarre / idiosyncratic\nB = not dose related, unpredictaBle, Belongs to immunology/genetics, high mortality"),
        ("Teratogens (WARTIME)", "Warfarin, Aminoglycosides, Retinoids, Thalidomide\nIsotretinoin/Iodine, Methotrexate, Epileptic drugs (valproate, carbamazepine)"),
        ("Clinical trial phases", "0 = microdose | I = healthy, safety | II = patients, efficacy\nIII = large RCT, regulatory | IV = post-market, rare ADRs"),
        ("Receptor families onset (IGEI)", "Ion channels (ms) → G-protein (sec) → Enzyme-linked (min) → Intracellular (hours)\nI Got Every Item"),
    ]

    mnem_data = []
    for key, val in mnemonics:
        mnem_data.append([
            Paragraph(f"<b>{key}</b>", S("MK", fontSize=9, fontName="Helvetica-Bold", textColor=WHITE)),
            Paragraph(val, MONO)
        ])

    mnem_tbl = Table(mnem_data, colWidths=[3.2*cm, W - 3.2*cm],
                     style=TableStyle([
                         ("BACKGROUND", (0,0), (0,-1), colors.HexColor("#B7950B")),
                         ("ROWBACKGROUNDS", (1,0), (1,-1), [WHITE, PAL_AMB]),
                         ("GRID",(0,0),(-1,-1), 0.3, colors.HexColor("#D4AC0D")),
                         ("TOPPADDING",(0,0),(-1,-1),6),
                         ("BOTTOMPADDING",(0,0),(-1,-1),6),
                         ("LEFTPADDING",(0,0),(-1,-1),6),
                         ("VALIGN",(0,0),(-1,-1),"MIDDLE"),
                     ]))
    story.append(mnem_tbl)
    story.append(sp(8))

    # Final exam strategy box
    story.append(SubBanner("HOW TO APPROACH ANY PHARMACOLOGY QUESTION", colors.HexColor("#1A3A5C"), W))
    story.append(sp(4))
    strategies = [
        ("Short note 5 marks", "Definition (1-2 lines) → Classification/types (table) → One diagram → Key examples → One clinical point"),
        ("Long answer 10 marks", "Intro → Classification → Mechanism (detailed) → Pharmacokinetics → Clinical uses → ADRs → Contraindications → Drug interactions → Summary table"),
        ("MCQ strategy", "Eliminate obviously wrong options → Look for absolute words ('always', 'never') → Choose the MOST specific answer → For mechanism questions, think receptor type first"),
        ("Draw a graph", "Always label both axes → Potency = EC50 on X-axis → Efficacy = Emax on Y-axis → Show BOTH competitive (parallel shift) and non-competitive (reduced Emax) antagonism in one figure"),
    ]
    strat_tbl = Table(
        [[Paragraph(f"<b>{k}</b>", S("SK", fontSize=9, fontName="Helvetica-Bold", textColor=NAVY)),
          Paragraph(v, BODY)] for k, v in strategies],
        colWidths=[3.2*cm, W - 3.2*cm],
        style=TableStyle([
            ("ROWBACKGROUNDS", (0,0),(-1,-1), [PAL_BLUE, WHITE]),
            ("GRID",(0,0),(-1,-1),0.3,colors.HexColor("#BFC9CA")),
            ("TOPPADDING",(0,0),(-1,-1),6),
            ("BOTTOMPADDING",(0,0),(-1,-1),6),
            ("LEFTPADDING",(0,0),(-1,-1),6),
            ("VALIGN",(0,0),(-1,-1),"TOP"),
        ]))
    story.append(strat_tbl)


# ─── MAIN BUILD ───────────────────────────────────────────────────────────────
def build():
    doc = SimpleDocTemplate(
        OUTPUT,
        pagesize=A4,
        leftMargin=1.25*cm, rightMargin=1.25*cm,
        topMargin=1.1*cm, bottomMargin=1.2*cm,
        title="General Pharmacology Complete Study Guide — MBBS 2nd Year",
        author="Orris Medical AI",
        subject="General Pharmacology",
    )

    story = []
    W = W_PAGE

    # TITLE PAGE
    story.append(TitlePage(W))
    story.append(sp(10))

    # TABLE OF CONTENTS
    story.append(SubBanner("TABLE OF CONTENTS", DARK, W))
    story.append(sp(5))
    toc_items = [
        ("1", "Pharmacokinetics — ADME, Routes, Half-life, Kinetics", "Page 1"),
        ("2", "Pharmacodynamics — Receptors, Agonists, Antagonists, Dose-Response", "Page 2"),
        ("3", "Drug Metabolism & Excretion — CYP450, Phases, Prodrugs", "Page 3"),
        ("4", "Adverse Drug Reactions — ABCDE Classification, Specific ADRs", "Page 4"),
        ("5", "Drug Interactions — Pharmacokinetic & Pharmacodynamic", "Page 5"),
        ("6", "Pharmacogenomics & Individual Variation", "Page 6"),
        ("7", "Drug Use in Special Populations & Teratology", "Page 7"),
        ("8", "Rational Pharmacotherapy, Prescribing & Drug Development", "Page 8"),
        ("★", "Quick Revision Mnemonics & Exam Tips", "Final"),
    ]
    toc_data = []
    for num, title, pg in toc_items:
        col = TOPIC_COLORS[int(num)-1] if num.isdigit() else colors.HexColor("#B7950B")
        toc_data.append([
            Paragraph(f"<b>{num}</b>", S("TOCN", fontSize=10, fontName="Helvetica-Bold", textColor=WHITE, alignment=TA_CENTER)),
            Paragraph(title, S("TOCT", fontSize=9.5, textColor=DARK)),
            Paragraph(pg, S("TOCP", fontSize=9, textColor=MID_GRAY, alignment=TA_RIGHT)),
        ])
    toc_tbl = Table(toc_data, colWidths=[1.0*cm, W - 3.5*cm, 2.5*cm],
                    style=TableStyle([
                        ("BACKGROUND", (0,0), (0,-1),
                         [TOPIC_COLORS[i] if i < 8 else colors.HexColor("#B7950B") for i in range(9)]),
                        ("ROWBACKGROUNDS", (1,0),(1,-1), [WHITE, LIGHT_GR]),
                        ("ROWBACKGROUNDS", (2,0),(2,-1), [WHITE, LIGHT_GR]),
                        ("GRID",(0,0),(-1,-1),0.3,colors.HexColor("#BFC9CA")),
                        ("TOPPADDING",(0,0),(-1,-1),7),
                        ("BOTTOMPADDING",(0,0),(-1,-1),7),
                        ("LEFTPADDING",(0,0),(-1,-1),6),
                        ("VALIGN",(0,0),(-1,-1),"MIDDLE"),
                    ]))
    story.append(toc_tbl)
    story.append(PageBreak())

    # TOPICS
    topic1_pharmacokinetics(story, W)
    story.append(PageBreak())

    topic2_pharmacodynamics(story, W)
    story.append(PageBreak())

    topic3_drug_metabolism(story, W)
    story.append(PageBreak())

    topic4_ADR(story, W)
    story.append(PageBreak())

    topic5_drug_interactions(story, W)
    story.append(PageBreak())

    topic6_pharmacogenomics(story, W)
    story.append(PageBreak())

    topic7_special_populations(story, W)
    story.append(PageBreak())

    topic8_rational_prescribing(story, W)
    story.append(PageBreak())

    quick_revision_card(story, W)

    # FOOTER CITATION
    story.append(sp(6))
    story.append(hr())
    story.append(sp(4))
    story.append(Paragraph(
        "Sources: Lippincott Illustrated Reviews: Pharmacology | Goodman &amp; Gilman's Pharmacological Basis of Therapeutics | "
        "Katzung's Basic and Clinical Pharmacology 16e | Harrison's Internal Medicine 22e  |  Compiled by Orris Medical AI",
        SMALL))

    doc.build(story, onFirstPage=on_page_safe, onLaterPages=on_page_safe)
    print(f"SUCCESS: {OUTPUT}")


if __name__ == "__main__":
    build()
Running Command

cd /home/daytona/workspace/pharma-study-guide && python gen_pharmacology_complet…

Editing File

~/pharma-study-guide/gen_pharmacology_complete.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/pharma-study-guide/gen_pharmacology_complete.py'
Editing File

~/pharma-study-guide/gen_pharmacology_complete.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/pharma-study-guide/gen_pharmacology_complete.py'
Running Command

cd /home/daytona/workspace/pharma-study-guide && python gen_pharmacology_complet…

Running Command

ls -lh /home/daytona/workspace/pharma-study-guide/

Your complete General Pharmacology study guide PDF (64 KB, multi-page) is ready:

General Pharmacology Complete StudyGuide

PDF Document · PDF


Here's exactly what's inside across all 8 topics + bonus section:
#TopicWhat's Covered
1PharmacokineticsRoutes of administration (table with 9 routes), absorption factors, ion trapping, Vd, protein binding, BBB, first-order vs. zero-order kinetics, half-life, steady state, loading dose formula
2Pharmacodynamics4 receptor families with mechanisms & examples, full/partial/competitive/non-competitive/inverse agonists with IA values, dose-response curves, potency vs. efficacy, TI
3Drug Metabolism & ExcretionPhase I & II reactions, CYP450 enzymes table (3A4, 2D6, 2C9, 2C19, 1A2) with substrates/inducers/inhibitors, prodrugs, first-pass drugs, renal/biliary/pulmonary excretion
4Adverse Drug ReactionsABCDE classification with examples, 10 specific high-yield ADR pairs, Naranjo causality scale
5Drug InteractionsPharmaceutical/pharmacokinetic/pharmacodynamic types, CYP induction vs inhibition interactions, dangerous combinations (MAOIs + SSRIs etc.)
6PharmacogenomicsCYP2D6, NAT2, CYP2C19, TPMT, G6PD, HLA-B5701, HLA-B1502 polymorphisms with clinical consequences, individual variation (age/pregnancy/renal/hepatic)
7Special PopulationsFDA pregnancy categories A-X with examples, classic teratogens, paediatric pharmacology differences table, drugs to avoid by age
8Rational PharmacotherapyWHO rational prescribing steps, essential drugs concept, loading/maintenance dose formulas, TDM drugs, tolerance/tachyphylaxis/dependence, drug nomenclature, clinical trial phases I-IV
Revision Card12 mnemonics (ADME, GLMP, CAGE FASCIA, WARTIME etc.), exam answer structuring guide
This is a shared conversation. Sign in to Orris to start your own chat.