Make a handwritten notes on the given source ..in a very easy and understandable format covering each and every points
mkdir -p /tmp/workspace/cholinergic-notes && ls /tmp/workspace/
~/cholinergic-notes/make_notes.py
from PIL import Image, ImageDraw, ImageFont
import textwrap
import os
# Page size: A4 at 150 DPI
W, H = 1240, 1754
MARGIN = 70
LINE_H = 38
pages = []
# Colors
BG = (255, 252, 230) # cream/yellowed paper
LINE_COLOR = (180, 200, 220) # faint blue lines
TITLE_COLOR = (30, 80, 160) # deep blue for headings
TEXT_COLOR = (20, 20, 60) # dark navy for body
ACCENT = (190, 50, 50) # red for important/box
HIGHLIGHT = (255, 180, 0) # yellow highlight color
BOX_BG = (220, 235, 255) # light blue box bg
ARROW_COLOR = (80, 120, 60) # green for arrows
# Try to load a handwriting-like font, fallback to default
def get_font(size, bold=False):
font_paths = [
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
"/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf",
"/usr/share/fonts/truetype/ubuntu/Ubuntu-R.ttf",
]
bold_paths = [
"/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf",
"/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf",
"/usr/share/fonts/truetype/ubuntu/Ubuntu-B.ttf",
]
paths = bold_paths if bold else font_paths
for p in paths:
if os.path.exists(p):
try:
return ImageFont.truetype(p, size)
except:
pass
return ImageFont.load_default()
def new_page():
img = Image.new("RGB", (W, H), BG)
draw = ImageDraw.Draw(img)
# Draw ruled lines
for y in range(120, H - 40, LINE_H):
draw.line([(MARGIN - 10, y), (W - MARGIN + 10, y)], fill=LINE_COLOR, width=1)
# Red margin line
draw.line([(MARGIN - 30, 0), (MARGIN - 30, H)], fill=(220, 100, 100), width=2)
return img, draw
def draw_title_box(draw, text, y, font_size=28):
font = get_font(font_size, bold=True)
bbox = draw.textbbox((0, 0), text, font=font)
tw = bbox[2] - bbox[0]
x = MARGIN
draw.rectangle([x - 8, y - 6, x + tw + 14, y + font_size + 8], fill=(30, 80, 160), outline=(10, 40, 100), width=2)
draw.text((x, y), text, fill="white", font=font)
return y + font_size + 20
def draw_section(draw, text, y, font_size=22):
font = get_font(font_size, bold=True)
bbox = draw.textbbox((0, 0), text, font=font)
tw = bbox[2] - bbox[0]
draw.rectangle([MARGIN - 6, y - 4, MARGIN + tw + 10, y + font_size + 4], fill=(255, 230, 100), outline=(200, 160, 0), width=1)
draw.text((MARGIN, y), text, fill=ACCENT, font=font)
return y + font_size + 14
def draw_text(draw, text, y, font_size=17, color=TEXT_COLOR, indent=0, bold=False):
font = get_font(font_size, bold=bold)
x = MARGIN + indent
max_w = W - x - MARGIN
lines = textwrap.wrap(text, width=int(max_w / (font_size * 0.55)))
for line in lines:
if y > H - 80:
return y # overflow guard
draw.text((x, y), line, fill=color, font=font)
y += font_size + 8
return y
def draw_bullet(draw, text, y, font_size=16, color=TEXT_COLOR, indent=0, symbol="•"):
font = get_font(font_size)
sym_font = get_font(font_size, bold=True)
x = MARGIN + 20 + indent
bullet_x = MARGIN + indent
draw.text((bullet_x, y), symbol, fill=ACCENT, font=sym_font)
max_w = W - x - MARGIN
lines = textwrap.wrap(text, width=int(max_w / (font_size * 0.55)))
for i, line in enumerate(lines):
if y > H - 80:
return y
draw.text((x if i == 0 else x + 10, y), line, fill=color, font=font)
y += font_size + 7
return y
def draw_box(draw, lines, y, bg=BOX_BG, border=ACCENT, font_size=15):
font = get_font(font_size)
pad = 10
all_text = "\n".join(lines)
heights = []
wrapped = []
for l in lines:
wl = textwrap.wrap(l, width=int((W - 2*MARGIN - 2*pad) / (font_size * 0.55)))
if not wl:
wl = [""]
wrapped.append(wl)
heights.append(len(wl) * (font_size + 7))
total_h = sum(heights) + 2 * pad
draw.rectangle([MARGIN, y, W - MARGIN, y + total_h], fill=bg, outline=border, width=2)
cy = y + pad
for wl in wrapped:
for wline in wl:
draw.text((MARGIN + pad + 10, cy), wline, fill=TEXT_COLOR, font=font)
cy += font_size + 7
return y + total_h + 14
def draw_arrow_flow(draw, items, y, font_size=15):
font = get_font(font_size)
arrow_font = get_font(20, bold=True)
x = MARGIN
for i, item in enumerate(items):
bbox = draw.textbbox((0,0), item, font=font)
tw = bbox[2] - bbox[0]
th = bbox[3] - bbox[1]
draw.rectangle([x - 4, y - 3, x + tw + 8, y + th + 5], fill=(220, 255, 220), outline=ARROW_COLOR, width=1)
draw.text((x, y), item, fill=TEXT_COLOR, font=font)
x += tw + 14
if i < len(items) - 1:
draw.text((x, y - 2), "→", fill=ARROW_COLOR, font=arrow_font)
x += 22
if x > W - MARGIN - 80:
x = MARGIN + 40
y += font_size + 22
return y + font_size + 24
def draw_table(draw, headers, rows, y, col_widths=None, font_size=14):
if col_widths is None:
n = len(headers)
col_widths = [(W - 2*MARGIN) // n] * n
font_h = get_font(font_size, bold=True)
font_b = get_font(font_size)
pad = 6
row_h = font_size + pad * 2 + 6
# Header row
x = MARGIN
draw.rectangle([MARGIN, y, W - MARGIN, y + row_h], fill=(30, 80, 160))
for i, h in enumerate(headers):
wlines = textwrap.wrap(h, width=int(col_widths[i]/(font_size*0.6)))
draw.text((x + pad, y + pad), wlines[0] if wlines else h, fill="white", font=font_h)
x += col_widths[i]
y += row_h
for ri, row in enumerate(rows):
# Compute row height (multiline)
max_lines = 1
wrapped_cells = []
for ci, cell in enumerate(row):
wl = textwrap.wrap(cell, width=max(1, int(col_widths[ci]/(font_size*0.58))))
if not wl:
wl = [""]
wrapped_cells.append(wl)
max_lines = max(max_lines, len(wl))
rh = max_lines * (font_size + 5) + pad * 2
bg_color = (240, 245, 255) if ri % 2 == 0 else (255, 255, 255)
draw.rectangle([MARGIN, y, W - MARGIN, y + rh], fill=bg_color, outline=LINE_COLOR, width=1)
x = MARGIN
for ci, wl in enumerate(wrapped_cells):
cy2 = y + pad
for wline in wl:
draw.text((x + pad, cy2), wline, fill=TEXT_COLOR, font=font_b)
cy2 += font_size + 5
x += col_widths[ci]
# vertical lines
x2 = MARGIN
for w2 in col_widths:
draw.line([(x2, y), (x2, y + rh)], fill=LINE_COLOR, width=1)
x2 += w2
draw.line([(W - MARGIN, y), (W - MARGIN, y + rh)], fill=LINE_COLOR, width=1)
y += rh
return y + 16
# ─────────────────────────────────────────────────────────────────
# PAGE 1: Cholinergic System Overview + ANS vs SNS
# ─────────────────────────────────────────────────────────────────
img, draw = new_page()
y = 30
y = draw_title_box(draw, " CHOLINERGIC SYSTEM — Pharmacology Notes ", y, 30)
y += 4
# Subheading
y = draw_section(draw, "1. What is Cholinergic Transmission?", y, 20)
y = draw_text(draw, "ACh (Acetylcholine) = neurotransmitter of the cholinergic system.", y, 16, TEXT_COLOR)
y = draw_text(draw, "Neurons that synthesize, store & release ACh → called CHOLINERGIC NEURONS.", y, 16, ACCENT)
y += 6
y = draw_section(draw, "2. ANS vs Somatic Nervous System", y, 20)
headers = ["Feature", "ANS (Autonomic)", "Somatic NS"]
rows = [
["Control", "INVOLUNTARY — maintains homeostasis", "VOLUNTARY — under conscious control"],
["Neuron chain", "2 neurons in series (pre + post ganglionic)", "Single motor neuron (CNS → skeletal muscle)"],
["Junction", "Neuroeffector junction (smooth muscle/gland)", "NMJ — Neuromuscular junction"],
["Innervates", "Heart, smooth muscles, exocrine glands", "Skeletal muscles only"],
["Controls", "Circulation, digestion, excretion", "Skeletal muscle tone"],
]
col_w = [200, 440, 400]
y = draw_table(draw, headers, rows, y, col_w, 13)
y = draw_section(draw, "3. Sites of ACh & NA Release (Fig. 2.1)", y, 20)
items_para = [
"Preganglionic fibres (both sympathetic & parasympathetic)",
"Release: ACh",
]
y = draw_bullet(draw, "Postganglionic — PARASYMPATHETIC → releases ACh at effector cell", y, 15)
y = draw_bullet(draw, "Postganglionic — SYMPATHETIC (most) → releases NA (noradrenaline) at blood vessel", y, 15)
y = draw_bullet(draw, "Sympathetic → SWEAT GLANDS → releases ACh (exception!)", y, 15)
y = draw_bullet(draw, "Nerve to adrenal medulla (preganglionic) → ACh → releases adrenaline + NA", y, 15)
y = draw_bullet(draw, "Somatic motor nerve → ACh → skeletal muscle (NMJ)", y, 15)
y += 6
y = draw_section(draw, "4. Effects of ANS on Organs (Fig. 2.2)", y, 20)
headers2 = ["Organ", "Sympathetic (Fight/Flight)", "Parasympathetic (Rest/Digest)"]
rows2 = [
["Heart (HR & FOC)", "↑ HR, ↑ FOC", "↓ HR, ↓ FOC"],
["Pupil", "Mydriasis (dilates)", "Miosis (constricts)"],
["Bronchi", "Bronchodilatation", "Bronchospasm"],
["GIT (gut)", "↓ motility, ↑ sphincter tone", "↑ motility, sphincters relax"],
]
col_w2 = [200, 470, 370]
y = draw_table(draw, headers2, rows2, y, col_w2, 13)
draw.text((MARGIN, H - 50), "Page 1", fill=(150,150,150), font=get_font(14))
pages.append(img)
# ─────────────────────────────────────────────────────────────────
# PAGE 2: Synthesis, Cholinesterases, Receptors
# ─────────────────────────────────────────────────────────────────
img, draw = new_page()
y = 30
y = draw_title_box(draw, " ACh SYNTHESIS, CHOLINESTERASES & RECEPTORS ", y, 28)
y += 4
y = draw_section(draw, "5. Synthesis of ACh (Fig. 2.3)", y, 20)
steps = ["Choline (enters neuron)", "Reacts with Acetyl-CoA", "ChAT enzyme", "ACh formed", "Stored in vesicles", "Action potential", "Released into synapse", "Activates receptors", "Hydrolysed by AChE"]
y = draw_arrow_flow(draw, steps, y, 14)
y = draw_bullet(draw, "ChAT = Choline AcetylTransferase (enzyme that MAKES ACh)", y, 15, ACCENT)
y = draw_bullet(draw, "AChE = AcetylCholinEsterase (enzyme that BREAKS ACh)", y, 15, ACCENT)
y += 6
y = draw_section(draw, "6. Types of Cholinesterases", y, 20)
headers3 = ["Type", "Location", "Action", "Hydrolyses"]
rows3 = [
["True ChE (AChE)", "Neurons, ganglia, RBCs, NMJ", "Rapidly hydrolyses ACh", "ACh & Methacholine"],
["Pseudocholinesterase\n(Butyrylcholinesterase)", "Plasma, liver, glial cells", "Slow hydrolysis", "Wide variety of esters (NOT methacholine)"],
]
col_w3 = [230, 280, 280, 250]
y = draw_table(draw, headers3, rows3, y, col_w3, 13)
y = draw_section(draw, "7. Cholinergic Receptors", y, 20)
y = draw_text(draw, "Two main types: MUSCARINIC (M) and NICOTINIC (N)", y, 16, TITLE_COLOR, bold=True)
y += 4
y = draw_text(draw, "MUSCARINIC RECEPTORS — G-protein coupled (regulate 2nd messengers)", y, 15, ACCENT, bold=True)
headers4 = ["Subtype", "Location", "Intracellular Effect", "Response"]
rows4 = [
["M1", "Gastric glands, Autonomic ganglia, CNS", "↑ IP3 & DAG", "↑ Learning/memory, gland secretion, SM contraction"],
["M2", "HEART", "↓ cAMP, opens K+ channels", "Hyperpolarization → ↓ SA node, ↓ AV node, ↓ contraction"],
["M3", "Smooth muscle, Exocrine glands, Endothelium", "↑ IP3 & DAG", "Glandular secretion, SM contraction"],
["M4 & M5", "CNS only", "G-protein mediated", "CNS functions"],
]
col_w4 = [90, 260, 250, 440]
y = draw_table(draw, headers4, rows4, y, col_w4, 12)
y += 2
y = draw_text(draw, "NICOTINIC RECEPTORS — Directly opens Na+/K+ ion channels → DEPOLARIZATION", y, 15, ACCENT, bold=True)
headers5 = ["Subtype", "Location", "Effect"]
rows5 = [
["NN (Nn)", "Autonomic ganglia, Adrenal medulla, CNS", "Depolarization → release of Adrenaline + NA from adrenal medulla"],
["NM (Nm)", "NMJ — Neuromuscular Junction", "Depolarization → Skeletal muscle CONTRACTION"],
]
col_w5 = [110, 380, 550]
y = draw_table(draw, headers5, rows5, y, col_w5, 13)
y = draw_box(draw, [
"🧠 MEMORY TIP:",
"M1 = gastric/ganglia (1 = stomach acid) | M2 = Heart (2 chambers pump) | M3 = Smooth muscle/glands (3 = secretion)",
"NN = Ganglia & adrenal | NM = NMJ (M = Muscle)",
], y, bg=(255, 245, 200), border=(180, 140, 0), font_size=13)
draw.text((MARGIN, H - 50), "Page 2", fill=(150,150,150), font=get_font(14))
pages.append(img)
# ─────────────────────────────────────────────────────────────────
# PAGE 3: Classification of Cholinergic Agonists + Choline Esters
# ─────────────────────────────────────────────────────────────────
img, draw = new_page()
y = 30
y = draw_title_box(draw, " CHOLINERGIC AGONISTS — Classification & Choline Esters ", y, 26)
y += 4
y = draw_section(draw, "8. Classification of Cholinergic Agonists", y, 20)
y = draw_box(draw, [
"CHOLINERGIC AGONISTS (Cholinomimetics / Parasympathomimetics)",
"",
"A) DIRECTLY ACTING:",
" i) Choline Esters: Acetylcholine (ACh) | Bethanechol | Carbachol",
" ii) Alkaloids: Pilocarpine | Muscarine | Arecoline",
"",
"B) INDIRECTLY ACTING (Anticholinesterases):",
" i) REVERSIBLE:",
" • Carbamates: Physostigmine, Neostigmine, Pyridostigmine, Rivastigmine",
" • Alcohol: Edrophonium",
" • Others: Donepezil, Galantamine, Tacrine",
" ii) IRREVERSIBLE:",
" • Organophosphates (OP): Parathion, Malathion, Sarin, Soman, Tabun, Dyflos, Echothiophate",
" • Carbamates: Propoxur, Carbaryl",
], y, bg=(240, 250, 255), border=TITLE_COLOR, font_size=13)
y = draw_section(draw, "9. Comparison of Choline Esters", y, 20)
headers6 = ["Property", "Acetylcholine", "Carbachol", "Bethanechol"]
rows6 = [
["Metabolized by", "True + Pseudocholinesterase", "Resistant to BOTH", "Resistant to BOTH"],
["Muscarinic actions", "+ (Yes)", "+ (Yes)", "+ (Yes)"],
["Nicotinic actions", "+ (Yes)", "+ (Yes)", "- (No)"],
["Effect of Atropine", "Completely blocks muscarinic", "NOT completely blocked", "Completely blocks muscarinic"],
["Therapeutic use", "No clinical use (too short action)", "Glaucoma", "Post-op urinary retention & paralytic ileus"],
]
col_w6 = [210, 280, 280, 270]
y = draw_table(draw, headers6, rows6, y, col_w6, 12)
y = draw_section(draw, "10. Actions of ACh on Various Organs", y, 20)
y = draw_text(draw, "HEART (via M2 receptor):", y, 15, TITLE_COLOR, bold=True)
y = draw_bullet(draw, "↓↓ HR (negative chronotropic) — opens K+ channels → hyperpolarization → slows SA node", y, 14)
y = draw_bullet(draw, "↓↓ FOC (negative inotropic) — less force of contraction", y, 14)
y = draw_bullet(draw, "↓↓ A-V conduction (negative dromotropic)", y, 14)
y += 4
y = draw_text(draw, "BLOOD VESSELS (via M3 on endothelium):", y, 15, TITLE_COLOR, bold=True)
y = draw_bullet(draw, "ACh → M3 → releases NO (EDRF) → vasodilatation → ↓↓ BP", y, 14)
y += 4
y = draw_text(draw, "GIT (via M3):", y, 15, TITLE_COLOR, bold=True)
y = draw_bullet(draw, "↑ Tone of gut + ↑ Peristalsis + ↑ GI secretions + Relaxes sphincters (may cause defecation)", y, 14)
y += 4
y = draw_text(draw, "URINARY BLADDER (via M3):", y, 15, TITLE_COLOR, bold=True)
y = draw_bullet(draw, "Contracts detrusor muscle → Relaxes trigone & sphincter → URINATION", y, 14)
y += 4
y = draw_text(draw, "BRONCHI (via M3):", y, 15, TITLE_COLOR, bold=True)
y = draw_bullet(draw, "Bronchospasm + ↑ tracheobronchial secretion → CONTRAINDICATED IN ASTHMA!", y, 14, ACCENT)
y += 4
y = draw_text(draw, "EXOCRINE GLANDS:", y, 15, TITLE_COLOR, bold=True)
y = draw_bullet(draw, "↑ Salivary, lacrimal, sweat, bronchial, gastric & GI secretions", y, 14)
draw.text((MARGIN, H - 50), "Page 3", fill=(150,150,150), font=get_font(14))
pages.append(img)
# ─────────────────────────────────────────────────────────────────
# PAGE 4: Eye effects, Nicotinic actions, Alkaloids
# ─────────────────────────────────────────────────────────────────
img, draw = new_page()
y = 30
y = draw_title_box(draw, " ACh ON EYE | NICOTINIC ACTIONS | ALKALOIDS ", y, 28)
y += 4
y = draw_section(draw, "11. Actions on Eye (M3 receptors)", y, 20)
y = draw_text(draw, "ACh (i.v.), Pilocarpine, Physostigmine act on M3 receptors of eye:", y, 15)
y = draw_box(draw, [
"M3 receptors in eye activated",
" ↓ ↓",
"Contract sphincter pupillae Contract ciliary muscle",
"→ MIOSIS (pupil constricts) → Spasm of accommodation",
" ↓",
"Opens trabecular meshwork around canal of Schlemm",
" ↓",
"Facilitates aqueous humour drainage → ↓ IOP (used in GLAUCOMA!)",
" ↓",
"Ciliary muscle contracts → suspensory ligament relaxes → lens bulges",
" ↓",
"Vision fixed for NEAR distance (Accommodation for near)",
], y, bg=(230, 255, 230), border=ARROW_COLOR, font_size=13)
y = draw_text(draw, "Note: Topical ACh has NO effect on eye because it CANNOT penetrate tissue.", y, 14, ACCENT)
y += 6
y = draw_section(draw, "12. Nicotinic Actions of ACh (higher doses needed)", y, 20)
y = draw_bullet(draw, "Autonomic ganglia: stimulates both sympathetic & parasympathetic ganglia → tachycardia & ↑ BP (atropine must be given first to block dangerous muscarinic effects)", y, 14)
y = draw_bullet(draw, "Skeletal muscles (NMJ): twitching → fasciculations → prolonged depolarization → PARALYSIS", y, 14)
y = draw_bullet(draw, "CNS: NO central effects (ACh does not cross BBB)", y, 14)
y += 6
y = draw_section(draw, "13. Bethanechol", y, 20)
y = draw_bullet(draw, "Selective muscarinic actions on GIT and urinary bladder", y, 14)
y = draw_bullet(draw, "Preferred in: Post-operative urinary retention & Paralytic ileus", y, 14, ACCENT)
y += 6
y = draw_section(draw, "14. Pilocarpine (Cholinomimetic Alkaloid)", y, 20)
y = draw_text(draw, "Source: Pilocarpus plant | Tertiary amine | Direct-acting | Muscarinic + Nicotinic effects", y, 14)
y = draw_text(draw, "USES:", y, 15, TITLE_COLOR, bold=True)
y = draw_bullet(draw, "Open-angle glaucoma & Acute congestive glaucoma (0.5-4% topical solution)", y, 14)
y = draw_bullet(draw, "Break adhesions between iris & lens (used with mydriatics)", y, 14)
y = draw_bullet(draw, "Reverse pupillary dilatation after refraction testing", y, 14)
y = draw_bullet(draw, "Sialogogue (to stimulate salivation)", y, 14)
y = draw_text(draw, "Adverse effects: Salivation, sweating, bradycardia, diarrhoea, bronchospasm, pulmonary oedema", y, 14, ACCENT)
y += 6
y = draw_section(draw, "15. Muscarine & Mushroom Poisoning", y, 20)
headers7 = ["Type", "Mushroom", "Toxin", "Features", "Treatment"]
rows7 = [
["Rapid onset", "Inocybe spp.", "Muscarine", "Excessive muscarinic effects: vomiting, diarrhoea, bradycardia, salivation, sweating, bronchospasm, hypotension", "IV Atropine"],
["Hallucinogen type", "Amanita muscaria, Psilocybe", "Muscimol", "Mainly CENTRAL effects (hallucinations). No specific antidote. Atropine CONTRAINDICATED", "Supportive care"],
["Delayed onset", "Amanita phalloides", "Amatoxin", "Delayed gastroenteritis, hepatic & renal damage. Does NOT respond to atropine", "Thioctic acid + supportive"],
]
col_w7 = [130, 180, 120, 420, 190]
y = draw_table(draw, headers7, rows7, y, col_w7, 11)
draw.text((MARGIN, H - 50), "Page 4", fill=(150,150,150), font=get_font(14))
pages.append(img)
# ─────────────────────────────────────────────────────────────────
# PAGE 5: Anticholinesterases (Reversible) + Individual drugs
# ─────────────────────────────────────────────────────────────────
img, draw = new_page()
y = 30
y = draw_title_box(draw, " ANTICHOLINESTERASES — Reversible Drugs ", y, 28)
y += 4
y = draw_section(draw, "16. How Anticholinesterases Work", y, 20)
y = draw_text(draw, "They INHIBIT cholinesterase enzyme → ACh NOT broken down → ACCUMULATES at muscarinic & nicotinic sites → Cholinergic effects", y, 15)
y = draw_box(draw, [
"Normal: ACh → binds anionic + esteratic site of ChE → acetylated enzyme → rapid hydrolysis → free enzyme",
"",
"Carbamates (e.g. Neostigmine): bind both sites → carbamoylated enzyme → SLOW hydrolysis (reversible)",
"",
"Organophosphates: bind COVALENTLY to esteratic site → IRREVERSIBLE inhibition (phosphorylated enzyme doesn't hydrolyse)",
"",
"Edrophonium: binds only anionic site → weak H-bond → diffuses away in 8-10 min (very short action)",
], y, bg=(255, 240, 220), border=(200, 100, 0), font_size=13)
y = draw_section(draw, "17. Physostigmine vs Neostigmine", y, 20)
headers8 = ["Feature", "Physostigmine (Eserine)", "Neostigmine"]
rows8 = [
["Source", "Natural alkaloid (Physostigma venenosum)", "Synthetic"],
["Chemistry", "Tertiary amine → CROSSES BBB", "Quaternary ammonium → does NOT cross BBB"],
["Penetration", "Good tissue penetration → topically effective", "Poor penetration → topically NOT effective"],
["CNS effects", "YES — both central & peripheral effects", "NO central effects"],
["Uses", "Atropine poisoning, Glaucoma", "Post-op urinary retention, Paralytic ileus, Myasthenia gravis, Curare poisoning"],
]
col_w8 = [180, 430, 430]
y = draw_table(draw, headers8, rows8, y, col_w8, 12)
y = draw_section(draw, "18. Individual Drugs", y, 20)
y = draw_text(draw, "PHYSOSTIGMINE:", y, 15, TITLE_COLOR, bold=True)
y = draw_bullet(draw, "Glaucoma: reduces IOP by producing miosis (BUT causes cataract on chronic use → rarely used now)", y, 14)
y = draw_bullet(draw, "Atropine poisoning: IV physostigmine — reverses BOTH central & peripheral effects (preferred over neostigmine)", y, 14)
y += 4
y = draw_text(draw, "NEOSTIGMINE:", y, 15, TITLE_COLOR, bold=True)
y = draw_bullet(draw, "Indirect action: inhibits ChE → ↑ ACh at NMJ", y, 14)
y = draw_bullet(draw, "Direct action: also directly stimulates NM receptors (structural similarity to ACh)", y, 14)
y = draw_bullet(draw, "Preferred over physostigmine in myasthenia gravis (no CNS side effects)", y, 14, ACCENT)
y = draw_bullet(draw, "Available: oral, SC, IV, IM", y, 14)
y += 4
y = draw_text(draw, "PYRIDOSTIGMINE:", y, 15, TITLE_COLOR, bold=True)
y = draw_bullet(draw, "Same as neostigmine BUT longer duration of action (twice daily sustained release)", y, 14)
y = draw_bullet(draw, "Less potent but BETTER TOLERATED → PREFERRED in myasthenia gravis", y, 14, ACCENT)
y += 4
y = draw_text(draw, "EDROPHONIUM:", y, 15, TITLE_COLOR, bold=True)
y = draw_bullet(draw, "Quaternary ammonium | IV → rapid onset, SHORT action (8-10 min)", y, 14)
y = draw_bullet(draw, "USES: (1) Diagnosis of myasthenia gravis (2) Differentiate myasthenic vs cholinergic crisis (3) Curare poisoning (preferred for rapid onset)", y, 14, ACCENT)
y += 4
y = draw_text(draw, "GALANTAMINE, RIVASTIGMINE, DONEPEZIL:", y, 15, TITLE_COLOR, bold=True)
y = draw_bullet(draw, "Cerebroselective anticholinesterases → increase cerebral ACh levels", y, 14)
y = draw_bullet(draw, "Used in ALZHEIMER'S DISEASE", y, 14, ACCENT)
y += 4
y = draw_section(draw, "19. Adverse Effects of Anticholinesterases", y, 20)
y = draw_box(draw, [
"Due to overstimulation of BOTH muscarinic & nicotinic receptors:",
"↑ Sweating | ↑ Salivation | Nausea | Vomiting | Abdominal cramps | Bradycardia | Diarrhoea | Tremors | Hypotension",
], y, bg=(255, 220, 220), border=ACCENT, font_size=13)
draw.text((MARGIN, H - 50), "Page 5", fill=(150,150,150), font=get_font(14))
pages.append(img)
# ─────────────────────────────────────────────────────────────────
# PAGE 6: Therapeutic Uses of Anticholinesterases + OP Poisoning + Glaucoma
# ─────────────────────────────────────────────────────────────────
img, draw = new_page()
y = 30
y = draw_title_box(draw, " THERAPEUTIC USES | OP POISONING | GLAUCOMA ", y, 26)
y += 4
y = draw_section(draw, "20. Therapeutic Uses of Reversible Anticholinesterases", y, 20)
uses = [
("Eye", ["Glaucoma", "Reverse pupillary dilatation after refraction testing", "Break adhesions between iris & lens (with mydriatics)"]),
("Myasthenia gravis", ["Neostigmine (IV/IM), Pyridostigmine (oral, preferred)"]),
("Postoperative", ["Urinary retention & Paralytic ileus → Neostigmine"]),
("Poisoning reversal", ["Curare (non-depolarizing NMJ block) → Neostigmine/Edrophonium", "Belladonna poisoning → Physostigmine"]),
("Alzheimer's disease", ["Donepezil, Galantamine, Rivastigmine"]),
]
for label, bullets in uses:
y = draw_text(draw, f"• {label}:", y, 15, TITLE_COLOR, bold=True)
for b in bullets:
y = draw_bullet(draw, b, y, 14, indent=20)
y += 2
y += 4
y = draw_section(draw, "21. Irreversible Anticholinesterases — OP Poisoning", y, 20)
y = draw_text(draw, "All OP compounds (except echothiophate) have ONLY toxicological importance.", y, 15, ACCENT)
y = draw_text(draw, "Common OPs: Parathion, Malathion, Dyflos, Sarin, Soman, Tabun (nerve gases)", y, 14)
y += 4
y = draw_text(draw, "SIGNS & SYMPTOMS:", y, 15, TITLE_COLOR, bold=True)
y = draw_bullet(draw, "Muscarinic effects: Profuse sweating, salivation, lacrimation, ↑ tracheobronchial secretions, bronchospasm, vomiting, diarrhoea, abdominal cramps, miosis, bradycardia, hypotension, involuntary urination/defecation (SLUDGE + DUMBELS)", y, 14)
y = draw_bullet(draw, "Nicotinic effects: Twitchings, fasciculations, muscle weakness, PARALYSIS (due to prolonged depolarization)", y, 14)
y = draw_bullet(draw, "Central effects: Headache, restlessness, confusion, convulsions, coma, DEATH (respiratory failure)", y, 14)
y += 4
y = draw_text(draw, "DIAGNOSIS of OP poisoning:", y, 15, TITLE_COLOR, bold=True)
y = draw_bullet(draw, "History of exposure", y, 14)
y = draw_bullet(draw, "Characteristic signs & symptoms", y, 14)
y = draw_bullet(draw, "Decreased cholinesterase activity in blood", y, 14)
y += 4
y = draw_section(draw, "22. Glaucoma — Overview & Drugs", y, 20)
y = draw_text(draw, "Glaucoma = optic nerve damage with ↑ IOP (normal IOP: 10-20 mmHg)", y, 15)
y = draw_text(draw, "Aqueous humour formed by ciliary body → drains via trabecular meshwork (canal of Schlemm) & uveoscleral outflow", y, 14)
y += 4
headers9 = ["Drug Class", "Acute Congestive (Narrow-angle)", "Chronic Simple (Wide-angle)"]
rows9 = [
["Osmotic agents", "Mannitol 20% IV, Glycerol 50% oral", "Not used"],
["Carbonic anhydrase inhibitors", "Acetazolamide IV/oral", "Dorzolamide 2% topical, Brinzolamide, Acetazolamide oral"],
["β-Blockers (topical)", "Timolol 0.5%", "Timolol 0.25%, Betaxolol 0.25%, Carteolol 1%"],
["Prostaglandins (topical)", "Latanoprost 0.005%", "Latanoprost 0.005%, Travoprost, Bimatoprost (DRUG OF CHOICE in open-angle)"],
["Miotics (topical)", "Pilocarpine 2%", "Pilocarpine 0.5%"],
["α-Adrenergic agonists", "Not used", "Apraclonidine, Dipivefrin 0.1%"],
]
col_w9 = [260, 370, 410]
y = draw_table(draw, headers9, rows9, y, col_w9, 12)
y = draw_box(draw, [
"NOTES on Glaucoma drugs:",
"• Propranolol NOT used (membrane-stabilizing effect anesthetizes cornea)",
"• Betaxolol = selective β1-blocker (protective to retinal neurons)",
"• Levobunolol = long acting β-blocker (use cautiously in asthma/heart failure)",
"• Timolol: no local anesthetic, no miosis, no accommodation changes, long duration",
"• Apraclonidine: α2-agonist → ↓ aqueous formation → ↓ IOP (does NOT cross BBB → no hypotension like clonidine)",
"• Dipivefrin = prodrug of adrenaline → penetrates cornea → converted to adrenaline by esterases",
], y, bg=(240, 245, 255), border=TITLE_COLOR, font_size=12)
draw.text((MARGIN, H - 50), "Page 6", fill=(150,150,150), font=get_font(14))
pages.append(img)
# ─────────────────────────────────────────────────────────────────
# PAGE 7: Myasthenia Gravis + Cholinergic Crisis
# ─────────────────────────────────────────────────────────────────
img, draw = new_page()
y = 30
y = draw_title_box(draw, " MYASTHENIA GRAVIS & CHOLINERGIC CRISIS ", y, 28)
y += 4
y = draw_section(draw, "23. Myasthenia Gravis — Key Points", y, 20)
y = draw_text(draw, "Autoimmune disorder: antibodies against NM (Nicotinic-Muscle) receptors at NMJ → ↓ number of NM receptors", y, 15)
y = draw_bullet(draw, "Increased incidence with THYMOMA (thymus is removed → thymectomy can induce remission)", y, 14)
y = draw_bullet(draw, "Features: Marked muscular weakness, varying degree at different times, easy fatigability", y, 14)
y += 4
y = draw_text(draw, "DIAGNOSIS:", y, 15, TITLE_COLOR, bold=True)
y = draw_bullet(draw, "Tensilon test (Edrophonium test): 2-10 mg IV slow → dramatic improvement in MG (but NOT in other dystrophies)", y, 14, ACCENT)
y = draw_bullet(draw, "Also used to differentiate myasthenic crisis from cholinergic crisis", y, 14)
y = draw_bullet(draw, "Circulating antibodies to NM receptors (serology)", y, 14)
y += 4
y = draw_text(draw, "TREATMENT:", y, 15, TITLE_COLOR, bold=True)
y = draw_bullet(draw, "Anticholinesterases (symptomatic): Neostigmine, Pyridostigmine (preferred), Ambenonium", y, 14)
y = draw_bullet(draw, "Corticosteroids + Immunosuppressants (azathioprine / cyclophosphamide) — for induction and maintenance of remission", y, 14)
y = draw_bullet(draw, "Plasmapheresis & immune therapy — resistant cases", y, 14)
y += 4
y = draw_box(draw, [
"DRUGS CONTRAINDICATED in Myasthenia Gravis (they WORSEN it):",
"Aminoglycoside antibiotics | d-Tubocurarine (d-TC) | β-blockers | Ether | Phenytoin | etc.",
], y, bg=(255, 220, 220), border=ACCENT, font_size=13)
y += 4
y = draw_section(draw, "24. Myasthenic Crisis vs Cholinergic Crisis", y, 20)
headers10 = ["Feature", "Myasthenic Crisis", "Cholinergic Crisis"]
rows10 = [
["Cause", "Under-treatment / exacerbation of MG (↓ ACh at NMJ)", "Overdose of anticholinesterases (↑ ACh → prolonged depolarization)"],
["Weakness", "Severe weakness (↓ NMJ activity)", "Severe weakness + NMJ paralysis"],
["Other signs", "No cholinergic signs", "SLUDGE signs: salivation, lacrimation, diarrhoea, GI cramps, bradycardia"],
["Edrophonium test", "Improvement (crisis is myasthenic)", "Worsening / no improvement (crisis is cholinergic)"],
["Treatment", "Give more anticholinesterase", "STOP anticholinesterase, give ATROPINE"],
]
col_w10 = [200, 400, 440]
y = draw_table(draw, headers10, rows10, y, col_w10, 12)
y = draw_box(draw, [
"⚠️ IMPORTANT: Keep ATROPINE ready before injecting Edrophonium in MG diagnosis",
" — if muscular weakness deteriorates (cholinergic crisis), edrophonium will aggravate it!",
" Ventilator should be kept ready.",
], y, bg=(255, 240, 200), border=(180,130,0), font_size=13)
y += 6
y = draw_section(draw, "25. Summary — Quick Recall Table", y, 20)
headers11 = ["Drug", "Type", "Key Use", "Crosses BBB?"]
rows11 = [
["Physostigmine", "Reversible anticholinesterase", "Atropine poisoning, Glaucoma", "YES"],
["Neostigmine", "Reversible anticholinesterase", "MG, Post-op urinary retention, Curare reversal", "NO"],
["Pyridostigmine", "Reversible anticholinesterase", "MG (preferred — better tolerated, longer duration)", "NO"],
["Edrophonium", "Reversible anticholinesterase", "Diagnosis of MG, Curare poisoning", "NO"],
["Donepezil/Galantamine/Rivastigmine", "Cerebroselective AChE inhibitor", "Alzheimer's disease", "YES"],
["Pilocarpine", "Direct muscarinic agonist (alkaloid)", "Glaucoma, Sialogogue", "—"],
["Bethanechol", "Direct muscarinic agonist (choline ester)", "Post-op urinary retention, Paralytic ileus", "—"],
["Carbachol", "Direct muscarinic agonist (choline ester)", "Glaucoma", "—"],
]
col_w11 = [280, 230, 380, 150]
y = draw_table(draw, headers11, rows11, y, col_w11, 11)
draw.text((MARGIN, H - 50), "Page 7", fill=(150,150,150), font=get_font(14))
pages.append(img)
# ─────────────────────────────────────────────────────────────────
# SAVE as multi-page PDF
# ─────────────────────────────────────────────────────────────────
output_path = "/tmp/workspace/cholinergic-notes/Cholinergic_System_Notes.pdf"
pages[0].save(output_path, save_all=True, append_images=pages[1:], format="PDF")
print(f"Saved: {output_path}")
print(f"Pages: {len(pages)}")
cd /tmp/workspace/cholinergic-notes && python make_notes.py 2>&1
Cholinergic System Notes
PDF Document · PDF
Make a beautiful notes and a detailed version notes covering all the heading in detail with proper explanation and diagrams
ls /tmp/workspace/cholinergic-notes/
~/cholinergic-notes/beautiful_notes.py
from PIL import Image, ImageDraw, ImageFont
import textwrap, os, math
# ── Canvas ──────────────────────────────────────────────────────
W, H = 1400, 1980 # A4-ish at ~167 DPI
MARGIN_L, MARGIN_R = 70, 70
CONTENT_W = W - MARGIN_L - MARGIN_R
# ── Palette ─────────────────────────────────────────────────────
BG_CREAM = (255, 253, 240)
RULE_BLUE = (190, 210, 235)
MARGIN_RED = (220, 80, 80)
C_NAVY = (15, 40, 100)
C_TEAL = (0, 130, 140)
C_RUST = (185, 55, 30)
C_GREEN = (30, 120, 60)
C_PURPLE = (120, 40, 160)
C_GOLD = (180, 130, 0)
C_DARK = (25, 25, 50)
C_GRAY = (100, 100, 120)
BAND_NAVY = (15, 40, 100)
BAND_TEAL = (0, 115, 125)
BAND_RUST = (175, 50, 25)
BAND_GREEN = (25, 110, 55)
BAND_PURPLE = (110, 35, 150)
BAND_GOLD = (165, 120, 0)
BOX_YELLOW = (255, 250, 200)
BOX_BLUE = (230, 242, 255)
BOX_GREEN = (225, 248, 230)
BOX_RED = (255, 232, 230)
BOX_PURPLE = (242, 230, 255)
BOX_TEAL = (220, 248, 248)
# ── Font helpers ────────────────────────────────────────────────
def gf(size, bold=False, italic=False):
candidates = {
(False, False): [
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
"/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf",
],
(True, False): [
"/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf",
"/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf",
],
(False, True): [
"/usr/share/fonts/truetype/dejavu/DejaVuSans-Oblique.ttf",
"/usr/share/fonts/truetype/liberation/LiberationSans-Italic.ttf",
],
(True, True): [
"/usr/share/fonts/truetype/dejavu/DejaVuSans-BoldOblique.ttf",
"/usr/share/fonts/truetype/liberation/LiberationSans-BoldItalic.ttf",
],
}
for p in candidates.get((bold, italic), candidates[(False,False)]):
if os.path.exists(p):
try:
return ImageFont.truetype(p, size)
except:
pass
return ImageFont.load_default()
def tw(draw, text, font):
bb = draw.textbbox((0,0), text, font=font)
return bb[2]-bb[0], bb[3]-bb[1]
# ── Page factory ────────────────────────────────────────────────
def new_page():
img = Image.new("RGB", (W, H), BG_CREAM)
d = ImageDraw.Draw(img)
for yy in range(130, H-30, 36):
d.line([(MARGIN_L-15, yy), (W-MARGIN_R+15, yy)], fill=RULE_BLUE, width=1)
d.line([(MARGIN_L-28, 0), (MARGIN_L-28, H)], fill=MARGIN_RED, width=2)
return img, d
# ════════════════════════════════════════════════════════════════
# DRAWING PRIMITIVES
# ════════════════════════════════════════════════════════════════
def page_header(d, title, subtitle, y=18):
"""Full-width gradient banner."""
font1 = gf(34, bold=True)
font2 = gf(17, italic=True)
d.rectangle([0, y, W, y+70], fill=BAND_NAVY)
d.text((MARGIN_L, y+8), title, fill="white", font=font1)
d.text((MARGIN_L, y+48), subtitle, fill=(200,220,255), font=font2)
return y + 82
def section_banner(d, text, y, color=BAND_TEAL, num=""):
"""Coloured section strip with optional number badge."""
font = gf(22, bold=True)
d.rectangle([MARGIN_L-10, y, W-MARGIN_R+10, y+40], fill=color)
label = f" {num} {text}" if num else f" {text}"
d.text((MARGIN_L, y+8), label, fill="white", font=font)
return y + 52
def sub_heading(d, text, y, color=C_NAVY):
font = gf(18, bold=True)
w2, _ = tw(d, text, font)
d.line([(MARGIN_L, y+22), (MARGIN_L+w2+8, y+22)], fill=color, width=2)
d.text((MARGIN_L, y+2), text, fill=color, font=font)
return y + 32
def body(d, text, y, size=16, color=C_DARK, indent=0, bold=False, italic=False, max_w=None):
font = gf(size, bold=bold, italic=italic)
mw = (max_w or CONTENT_W) - indent
chars_per_line = max(10, int(mw / (size * 0.56)))
lines = textwrap.wrap(text, width=chars_per_line)
x = MARGIN_L + indent
for ln in lines:
if y > H - 60:
return y
d.text((x, y), ln, fill=color, font=font)
y += size + 9
return y
def bullet(d, text, y, size=15, color=C_DARK, indent=0, dot_color=None, symbol="●"):
dot_color = dot_color or C_TEAL
fx = MARGIN_L + indent
bx = fx + 22
mw = CONTENT_W - indent - 26
font = gf(size)
sym_f= gf(size, bold=True)
d.text((fx, y+1), symbol, fill=dot_color, font=sym_f)
chars = max(10, int(mw/(size*0.56)))
lines = textwrap.wrap(text, width=chars)
for i, ln in enumerate(lines):
if y > H - 60: return y
d.text((bx if i==0 else bx+10, y), ln, fill=color, font=font)
y += size + 7
return y
def sub_bullet(d, text, y, size=14, color=C_GRAY):
return bullet(d, text, y, size=size, color=color, indent=30, dot_color=C_GOLD, symbol="–")
# ── Coloured info box ────────────────────────────────────────────
def info_box(d, lines, y, bg=BOX_BLUE, border=C_NAVY, title=None, font_size=14):
pad = 12
font = gf(font_size)
font_t= gf(font_size, bold=True)
wrapped_all = []
for ln in lines:
wl = textwrap.wrap(ln, width=max(10, int((CONTENT_W-2*pad)/(font_size*0.56))))
wrapped_all.append(wl if wl else [""])
total_h = sum(len(wl)*(font_size+7) for wl in wrapped_all) + 2*pad
if title:
total_h += font_size + 10
d.rectangle([MARGIN_L, y, W-MARGIN_R, y+total_h], fill=bg, outline=border, width=2)
cy = y + pad
if title:
d.text((MARGIN_L+pad, cy), title, fill=border, font=font_t)
cy += font_size + 10
for wl in wrapped_all:
for piece in wl:
d.text((MARGIN_L+pad+6, cy), piece, fill=C_DARK, font=font)
cy += font_size + 7
return y + total_h + 14
# ── Table ────────────────────────────────────────────────────────
def table(d, headers, rows, y, col_w=None, fs=13, header_color=BAND_NAVY):
if col_w is None:
n = len(headers)
col_w = [CONTENT_W//n]*n
fh = gf(fs, bold=True)
fb = gf(fs)
pad= 6
# Header
x = MARGIN_L
rh = fs + pad*2 + 4
d.rectangle([MARGIN_L, y, W-MARGIN_R, y+rh], fill=header_color)
for i,h in enumerate(headers):
d.text((x+pad, y+pad), h, fill="white", font=fh)
x += col_w[i]
y += rh
for ri, row in enumerate(rows):
wc = []
mlines = 1
for ci, cell in enumerate(row):
wl = textwrap.wrap(str(cell), width=max(5, int((col_w[ci]-2*pad)/(fs*0.58))))
if not wl: wl = [""]
wc.append(wl)
mlines = max(mlines, len(wl))
rh2 = mlines*(fs+6)+pad*2
bg2 = (240,248,255) if ri%2==0 else (252,252,255)
d.rectangle([MARGIN_L, y, W-MARGIN_R, y+rh2], fill=bg2, outline=RULE_BLUE, width=1)
x = MARGIN_L
for ci, wl in enumerate(wc):
cy2 = y+pad
for piece in wl:
d.text((x+pad, cy2), piece, fill=C_DARK, font=fb)
cy2 += fs+6
d.line([(x, y),(x, y+rh2)], fill=RULE_BLUE, width=1)
x += col_w[ci]
d.line([(W-MARGIN_R, y),(W-MARGIN_R, y+rh2)], fill=RULE_BLUE, width=1)
y += rh2
return y + 12
# ── Flow diagram (horizontal boxes + arrows) ─────────────────────
def flow_h(d, items, y, box_color=BOX_TEAL, border=C_TEAL, fs=13):
font = gf(fs)
arrow_font = gf(18, bold=True)
pad = 8
# compute box sizes
boxes = []
for item in items:
wlines = textwrap.wrap(item, width=14)
w2 = max(tw(d, ln, font)[0] for ln in wlines) + 2*pad
h2 = len(wlines)*(fs+5) + 2*pad
boxes.append((wlines, w2, h2))
max_h = max(b[2] for b in boxes)
total_w = sum(b[1] for b in boxes) + 20*(len(boxes)-1)
x = MARGIN_L + max(0, (CONTENT_W - total_w)//2)
by = y
for i,(wlines, bw, bh) in enumerate(boxes):
bx = x
d.rectangle([bx, by, bx+bw, by+max_h], fill=box_color, outline=border, width=2)
cy2 = by + (max_h - bh)//2 + pad
for ln in wlines:
d.text((bx+pad, cy2), ln, fill=C_DARK, font=font)
cy2 += fs+5
x += bw
if i < len(boxes)-1:
d.text((x+2, by+(max_h-18)//2), "→", fill=border, font=arrow_font)
x += 20
return y + max_h + 14
# ── Vertical flow diagram ────────────────────────────────────────
def flow_v(d, items, y, box_color=BOX_GREEN, border=C_GREEN, fs=13, x_offset=0):
font = gf(fs)
arrow_font = gf(20, bold=True)
pad = 8
bw = CONTENT_W - 2*x_offset - 80
cx = MARGIN_L + x_offset + 40
for i, item in enumerate(items):
wlines = textwrap.wrap(item, width=max(10, int(bw/(fs*0.56))))
bh = len(wlines)*(fs+6) + 2*pad
d.rectangle([cx, y, cx+bw, y+bh], fill=box_color, outline=border, width=2)
cy2 = y+pad
for ln in wlines:
lw, _ = tw(d, ln, font)
d.text((cx+(bw-lw)//2, cy2), ln, fill=C_DARK, font=font)
cy2 += fs+6
y += bh
if i < len(items)-1:
mx = cx + bw//2
d.line([(mx, y),(mx, y+16)], fill=border, width=2)
# arrow head
d.polygon([(mx-6, y+10),(mx+6, y+10),(mx, y+18)], fill=border)
y += 18
return y + 10
# ── Two-column flow (splits left / right) ────────────────────────
def flow_split(d, root_text, left_items, right_items, y,
root_color=BOX_YELLOW, left_color=BOX_GREEN, right_color=BOX_BLUE,
root_border=C_GOLD, left_border=C_GREEN, right_border=C_TEAL, fs=13):
font = gf(fs)
fontB = gf(fs, bold=True)
pad = 8
col_w = (CONTENT_W - 40) // 2
root_font = gf(fs+2, bold=True)
rw, rh = tw(d, root_text, root_font)
rbox_w = rw + 2*pad + 20
rx = MARGIN_L + (CONTENT_W - rbox_w)//2
d.rectangle([rx, y, rx+rbox_w, y+rh+2*pad], fill=root_color, outline=root_border, width=2)
d.text((rx+pad+10, y+pad), root_text, fill=root_border, font=root_font)
root_bottom = y + rh + 2*pad
y2 = root_bottom + 22
# branch lines
mid_x = rx + rbox_w//2
left_mid = MARGIN_L + col_w//2
right_mid = MARGIN_L + col_w + 40 + col_w//2
d.line([(mid_x, root_bottom),(mid_x, root_bottom+12)], fill=C_GOLD, width=2)
d.line([(left_mid, root_bottom+12),(right_mid, root_bottom+12)], fill=C_GOLD, width=2)
d.line([(left_mid, root_bottom+12),(left_mid, y2)], fill=left_border, width=2)
d.line([(right_mid, root_bottom+12),(right_mid, y2)], fill=right_border, width=2)
# Left column
lx = MARGIN_L
ly = y2
for item in left_items:
wl = textwrap.wrap(item, width=max(5, int((col_w-2*pad)/(fs*0.57))))
bh = len(wl)*(fs+6)+2*pad
d.rectangle([lx, ly, lx+col_w, ly+bh], fill=left_color, outline=left_border, width=1)
cy2 = ly+pad
for piece in wl:
d.text((lx+pad, cy2), piece, fill=C_DARK, font=font)
cy2 += fs+6
ly += bh+6
# Right column
rx2 = MARGIN_L + col_w + 40
ry2 = y2
for item in right_items:
wl = textwrap.wrap(item, width=max(5, int((col_w-2*pad)/(fs*0.57))))
bh = len(wl)*(fs+6)+2*pad
d.rectangle([rx2, ry2, rx2+col_w, ry2+bh], fill=right_color, outline=right_border, width=1)
cy2 = ry2+pad
for piece in wl:
d.text((rx2+pad, cy2), piece, fill=C_DARK, font=font)
cy2 += fs+6
ry2 += bh+6
return max(ly, ry2) + 14
# ── Organ effects diagram (icon + effects) ───────────────────────
def organ_diagram(d, organ, symp_effects, para_effects, y, icon="♥"):
font_icon = gf(28, bold=True)
font_h = gf(14, bold=True)
font_b = gf(13)
col = (CONTENT_W - 100) // 2
# Header row
d.rectangle([MARGIN_L, y, MARGIN_L+col, y+28], fill=BAND_RUST)
d.text((MARGIN_L+8, y+4), "SYMPATHETIC (Fight/Flight)", fill="white", font=font_h)
cx = MARGIN_L + col + 10
d.text((cx+4, y+2), f"{icon} {organ}", fill=C_NAVY, font=font_h)
d.rectangle([MARGIN_L+col+90, y, W-MARGIN_R, y+28], fill=BAND_TEAL)
d.text((MARGIN_L+col+96, y+4), "PARASYMPATHETIC (Rest/Digest)", fill="white", font=font_h)
y += 34
# Effects
max_rows = max(len(symp_effects), len(para_effects))
for i in range(max_rows):
se = symp_effects[i] if i < len(symp_effects) else ""
pe = para_effects[i] if i < len(para_effects) else ""
d.text((MARGIN_L+8, y+2), f"→ {se}", fill=C_RUST, font=font_b)
d.text((MARGIN_L+col+96, y+2), f"→ {pe}", fill=C_TEAL, font=font_b)
y += 20
return y + 10
# ── Receptor card ────────────────────────────────────────────────
def receptor_card(d, subtype, location, mechanism, response, y,
bg=BOX_TEAL, border=C_TEAL):
font_h = gf(15, bold=True)
font_b = gf(13)
pad = 10
tag_w = 60
# Tag
d.rectangle([MARGIN_L, y, MARGIN_L+tag_w, y+80], fill=border)
tw2, _ = tw(d, subtype, font_h)
d.text((MARGIN_L+(tag_w-tw2)//2, y+28), subtype, fill="white", font=font_h)
# Content box
d.rectangle([MARGIN_L+tag_w, y, W-MARGIN_R, y+80], fill=bg, outline=border, width=1)
d.text((MARGIN_L+tag_w+pad, y+5), f"📍 {location}", fill=C_NAVY, font=font_b)
d.text((MARGIN_L+tag_w+pad, y+24), f"⚙ {mechanism}", fill=C_PURPLE, font=font_b)
d.text((MARGIN_L+tag_w+pad, y+43), f"➜ {response}", fill=C_GREEN, font=font_b)
return y + 88
def spacer(y, n=10): return y + n
pages = []
# ════════════════════════════════════════════════════════════════
# PAGE 1 — TITLE + INTRO + ANS vs SNS
# ════════════════════════════════════════════════════════════════
img, d = new_page()
y = 10
y = page_header(d, "CHOLINERGIC SYSTEM", "Shanbhag Pharmacology | Chapter 2 — Autonomic Pharmacology", y)
# Intro box
y = info_box(d, [
"Acetylcholine (ACh) is the neurotransmitter of the cholinergic system.",
"Neurons that SYNTHESIZE, STORE & RELEASE ACh are called CHOLINERGIC NEURONS.",
"ACh acts at: (1) Parasympathetic post-ganglionic endings (2) All autonomic ganglia",
" (3) Sympathetic fibres to sweat glands (4) NMJ (neuromuscular junction)",
" (5) Some CNS synapses",
], y, bg=BOX_BLUE, border=C_NAVY, title="What is the Cholinergic System?", font_size=15)
y = section_banner(d, "ANS vs SOMATIC NERVOUS SYSTEM", y, BAND_NAVY, "1")
y = table(d,
["Feature", "Autonomic NS (ANS)", "Somatic NS"],
[
["Control", "INVOLUNTARY — maintains homeostasis", "VOLUNTARY — under conscious control"],
["Fibre chain", "2 neurons: Pre-ganglionic + Post-ganglionic (in series)", "Single motor neuron: CNS → skeletal muscle directly"],
["Synapse", "Neuroeffector junction (smooth muscle / gland / heart)", "NMJ — Neuromuscular Junction (skeletal muscle)"],
["Innervates", "Heart, smooth muscles, exocrine glands", "Skeletal muscles ONLY"],
["Controls", "Circulation, digestion, excretion (visceral)", "Skeletal muscle tone (movement)"],
["Transmitter", "ACh (pre-ganglionic) + ACh/NA (post-ganglionic)", "ACh at NMJ"],
],
y, col_w=[200, 510, 550], fs=13, header_color=BAND_NAVY)
y = section_banner(d, "SITES OF ACh & NA RELEASE (Fig 2.1)", y, BAND_TEAL, "2")
# Annotated site diagram
items_site = [
"Pre-ganglionic fibre\n(BOTH Symp + Para)\nReleases: ACh",
"Para Post-ganglionic\nReleases: ACh\n→ Effector cell",
"Symp Post-ganglionic\n(most)\nReleases: NA\n→ Blood vessel",
"Symp → Sweat gland\n(exception!)\nReleases: ACh",
"Pre-ganglionic\n→ Adrenal medulla\nReleases: ACh\n→ Adrenaline + NA",
"Somatic motor\n→ NMJ\nReleases: ACh\n→ Skeletal muscle",
]
font_site = gf(12)
pad_s = 8
bw_s = (CONTENT_W - 5*12) // 6
x_s = MARGIN_L
max_bh = 0
for item in items_site:
wl = item.split("\n")
bh = len(wl)*(12+5)+2*pad_s
max_bh = max(max_bh, bh)
boxes_data = []
x_s2 = MARGIN_L
colors_site = [BOX_YELLOW, BOX_GREEN, BOX_TEAL, BOX_BLUE, BOX_RED, BOX_PURPLE]
borders_site = [C_GOLD, C_GREEN, C_TEAL, C_NAVY, C_RUST, C_PURPLE]
for i, item in enumerate(items_site):
wl = item.split("\n")
bh = len(wl)*(12+5)+2*pad_s
d.rectangle([x_s2, y, x_s2+bw_s, y+max_bh], fill=colors_site[i], outline=borders_site[i], width=2)
cy2 = y+pad_s
for piece in wl:
lw, _ = tw(d, piece, font_site)
d.text((x_s2+(bw_s-lw)//2, cy2), piece, fill=C_DARK, font=font_site)
cy2 += 12+5
boxes_data.append((x_s2, bw_s))
x_s2 += bw_s + 12
if i < len(items_site)-1:
aff = gf(14, bold=True)
d.text((x_s2-10, y+max_bh//2-8), "↔", fill=C_GRAY, font=aff)
y = y + max_bh + 14
y = section_banner(d, "SYMPATHETIC vs PARASYMPATHETIC — Organ Effects (Fig 2.2)", y, BAND_RUST, "3")
y = table(d,
["Organ", "Sympathetic Effect (Adrenergic)", "Parasympathetic Effect (Cholinergic)"],
[
["Heart (Rate)", "↑ HR (positive chronotropic)", "↓ HR (negative chronotropic)"],
["Heart (Force)", "↑ FOC (positive inotropic)", "↓ FOC (negative inotropic)"],
["Pupil", "Mydriasis — dilator pupillae contracts (α1)", "Miosis — sphincter pupillae contracts (M3)"],
["Bronchi", "Broncho-DILATATION (β2)", "Broncho-SPASM + ↑ secretions (M3)"],
["GIT motility", "↓ Motility, ↑ sphincter tone (α1)", "↑ Motility, sphincters relax (M3)"],
["Urinary bladder", "Detrusor relaxes, sphincter contracts (retention)", "Detrusor contracts, sphincter relaxes (urination)"],
["Blood vessels", "Vasoconstriction (α1) / Vasodilatation (β2)", "Vasodilatation via NO release (M3 on endothelium)"],
["Salivary glands", "Thick viscid secretion (α1)", "Profuse watery secretion (M3)"],
["Sweat glands", "↑ Sweating (cholinergic! — ACh, not NA)", "—"],
],
y, col_w=[210, 480, 570], fs=12, header_color=BAND_RUST)
d.text((MARGIN_L, H-44), "Page 1 of 10 | Cholinergic System — Detailed Notes", fill=C_GRAY, font=gf(13, italic=True))
d.text((W-MARGIN_R-60, H-44), "1", fill=C_NAVY, font=gf(16, bold=True))
pages.append(img)
# ════════════════════════════════════════════════════════════════
# PAGE 2 — ACh SYNTHESIS + CHOLINESTERASES
# ════════════════════════════════════════════════════════════════
img, d = new_page()
y = 10
y = page_header(d, "ACh SYNTHESIS, STORAGE & BREAKDOWN", "Cholinergic Neurotransmission — Detailed Mechanism", y)
y = section_banner(d, "SYNTHESIS OF ACETYLCHOLINE (Fig 2.3)", y, BAND_TEAL, "4")
# Synthesis flow
y = flow_v(d, [
"STEP 1 — Choline enters the cholinergic neuron via CARRIER-MEDIATED TRANSPORT",
"STEP 2 — Choline + Acetyl-CoA (from mitochondria) ── ChAT enzyme ──► ACh formed",
"STEP 3 — ACh stored in STORAGE VESICLES near nerve terminal",
"STEP 4 — ACTION POTENTIAL arrives → Ca²⁺ influx → vesicles fuse → ACh released into synaptic cleft",
"STEP 5 — ACh interacts with CHOLINERGIC RECEPTORS on effector cell → response",
"STEP 6 — ACh rapidly hydrolysed by AChE enzyme → Choline + Acetic acid (choline recycled!)",
], y, box_color=BOX_TEAL, border=C_TEAL, fs=14)
y = info_box(d, [
"ChAT = Choline AcetylTransferase → enzyme that MAKES ACh",
"AChE = AcetylCholinEsterase → enzyme that BREAKS ACh (in the synapse)",
"Choline is recycled back into the nerve terminal after hydrolysis (high-affinity choline uptake)",
"Hemicholinium blocks choline uptake — depletes ACh stores",
"Vesamicol blocks ACh transport into vesicles",
"Botulinum toxin blocks ACh release from nerve terminals",
], y, bg=BOX_YELLOW, border=C_GOLD, title="Key Points — ACh Synthesis", font_size=14)
y = section_banner(d, "CHOLINESTERASES — Types & Properties", y, BAND_PURPLE, "5")
y = table(d,
["Type", "Also Called", "Location", "Hydrolyses", "Key Feature"],
[
["True ChE", "AChE — Acetylcholinesterase", "Cholinergic neurons, Ganglia, RBCs, NMJ", "ACh + Methacholine (rapidly)", "HIGH specificity; the MAIN enzyme for ACh breakdown"],
["Pseudo-ChE","Butyrylcholinesterase (BuChE)", "Plasma, Liver, Glial cells", "ACh + wide variety of esters (slowly); NOT methacholine", "LOW specificity; destroyed a lot of IV ACh before it reaches target"],
],
y, col_w=[120, 230, 280, 340, 290], fs=12, header_color=BAND_PURPLE)
y = info_box(d, [
"Clinical importance of Pseudocholinesterase:",
"→ Suxamethonium (succinylcholine) is hydrolysed by pseudocholinesterase",
"→ Pseudocholinesterase deficiency (genetic) → prolonged apnoea after suxamethonium administration",
"→ OP poisoning inhibits BOTH true and pseudocholinesterase",
"→ ACh has NO therapeutic use because pseudocholinesterase in blood destroys it before reaching organs",
], y, bg=BOX_RED, border=C_RUST, title="Clinical Note — Why ACh has no therapeutic use", font_size=13)
y = section_banner(d, "FATE OF ACh IN THE SYNAPSE", y, BAND_GREEN, "6")
y = flow_h(d,
["ACh released", "Binds receptor\n(muscarinic/\nnicotinic)", "Receptor\nactivation\n→ Response", "AChE cleaves\nACh quickly", "Choline\nrecycled\nback", "Acetic acid\ndiffuses away"],
y, box_color=BOX_GREEN, border=C_GREEN, fs=13)
y = info_box(d, [
"The synapse is cleared of ACh within MILLISECONDS — ensuring precision of nerve signalling",
"Anticholinesterases slow this breakdown → ACh accumulates → prolonged/enhanced cholinergic effect",
"This is the basis of: Neostigmine (MG), Physostigmine (atropine poisoning), OP insecticides (toxicity)",
], y, bg=BOX_BLUE, border=C_NAVY, font_size=14)
d.text((MARGIN_L, H-44), "Page 2 of 10 | Cholinergic System — Detailed Notes", fill=C_GRAY, font=gf(13, italic=True))
d.text((W-MARGIN_R-60, H-44), "2", fill=C_NAVY, font=gf(16, bold=True))
pages.append(img)
# ════════════════════════════════════════════════════════════════
# PAGE 3 — CHOLINERGIC RECEPTORS (Detailed)
# ════════════════════════════════════════════════════════════════
img, d = new_page()
y = 10
y = page_header(d, "CHOLINERGIC RECEPTORS", "Muscarinic & Nicotinic — Subtypes, Locations & Mechanisms", y)
y = section_banner(d, "OVERVIEW — Two Main Receptor Types", y, BAND_NAVY, "7")
y = table(d,
["Property", "MUSCARINIC Receptors", "NICOTINIC Receptors"],
[
["Coupling", "G-protein coupled (GPCR) → 2nd messenger", "Ligand-gated ION CHANNELS → direct depolarization"],
["Speed", "Slow (seconds) — via 2nd messengers", "Fast (milliseconds) — direct ion flow"],
["Subtypes", "M1, M2, M3, M4, M5", "NN (neuronal), NM (muscular)"],
["Blocker", "Atropine, Hyoscine, Ipratropium", "Tubocurarine (NM), Hexamethonium (NN)"],
["Agonist", "ACh, Muscarine, Pilocarpine, Bethanechol", "ACh, Nicotine, Suxamethonium"],
["Location", "Heart, smooth muscle, glands, CNS, endothelium", "Autonomic ganglia, NMJ, adrenal medulla"],
],
y, col_w=[200, 530, 530], fs=13, header_color=BAND_NAVY)
y = section_banner(d, "MUSCARINIC RECEPTOR SUBTYPES — Detailed Cards", y, BAND_TEAL, "8")
y = body(d, "All muscarinic receptors are G-protein coupled and regulate intracellular second messengers:", y, 15)
y = receptor_card(d, "M1",
"Gastric glands | Autonomic ganglia | CNS",
"Gq → ↑ IP3 + ↑ DAG → ↑ intracellular Ca²⁺",
"↑ Learning & memory | ↑ Gastric acid secretion | ↑ Smooth muscle contraction",
y, bg=BOX_YELLOW, border=C_GOLD)
y = receptor_card(d, "M2",
"HEART (SA node, AV node, atria, ventricles)",
"Gi → ↓ cAMP + opens K⁺ channels → HYPERPOLARIZATION",
"↓ HR (negative chronotropic) | ↓ A-V conduction (dromotropic) | ↓ Atrial contraction (inotropic)",
y, bg=BOX_RED, border=C_RUST)
y = receptor_card(d, "M3",
"Smooth muscles | Exocrine glands | Vascular endothelial cells",
"Gq → ↑ IP3 + ↑ DAG → ↑ Ca²⁺ → smooth muscle contraction",
"Glandular secretion | Smooth muscle contraction | Endothelium releases NO → vasodilatation",
y, bg=BOX_GREEN, border=C_GREEN)
y = receptor_card(d, "M4 & M5",
"CNS only (striatum, hippocampus, brainstem)",
"G-protein mediated — CNS modulation",
"M4: modulates dopamine release | M5: cerebrovascular effects | Both involved in CNS diseases",
y, bg=BOX_PURPLE, border=C_PURPLE)
y = section_banner(d, "NICOTINIC RECEPTOR SUBTYPES — Detailed Cards", y, BAND_GREEN, "9")
y = body(d, "Nicotinic receptors are LIGAND-GATED ION CHANNELS — opening Na⁺/K⁺ channels → rapid depolarization:", y, 15)
y = receptor_card(d, "NN",
"Autonomic ganglia (all) | Adrenal medulla | Some CNS",
"Direct opening of Na⁺/K⁺ ion channels → MEMBRANE DEPOLARIZATION",
"Ganglionic transmission (sympathetic + parasympathetic) | Adrenaline + NA release from adrenal medulla",
y, bg=BOX_TEAL, border=C_TEAL)
y = receptor_card(d, "NM",
"Neuromuscular Junction (NMJ) — skeletal muscle",
"Direct opening of Na⁺/K⁺ ion channels → END-PLATE POTENTIAL → muscle action potential",
"SKELETAL MUSCLE CONTRACTION | Target of suxamethonium (depolarising block) & tubocurarine (competitive block)",
y, bg=BOX_BLUE, border=C_NAVY)
y = info_box(d, [
"MEMORY TRICK for receptor locations:",
"M1 = Gastric (1 = 1st letter G like Gastric) + Ganglia + CNS",
"M2 = Heart ONLY (2 chambers pump blood — remember the 2)",
"M3 = 3 smooth organs: Smooth muscle + Secretory glands + endothelial cells",
"NN = Neuronal nicotinic (Ganglia + CNS + adrenal) — everywhere EXCEPT muscle",
"NM = Muscle nicotinic (NMJ only) — the one that contracts SKELETAL muscle",
], y, bg=BOX_YELLOW, border=C_GOLD, title="Memory Tips", font_size=14)
d.text((MARGIN_L, H-44), "Page 3 of 10 | Cholinergic System — Detailed Notes", fill=C_GRAY, font=gf(13, italic=True))
d.text((W-MARGIN_R-60, H-44), "3", fill=C_NAVY, font=gf(16, bold=True))
pages.append(img)
# ════════════════════════════════════════════════════════════════
# PAGE 4 — CLASSIFICATION + ACh ACTIONS
# ════════════════════════════════════════════════════════════════
img, d = new_page()
y = 10
y = page_header(d, "CHOLINERGIC AGONISTS — Classification", "Cholinomimetics / Parasympathomimetics | Direct & Indirect Acting", y)
y = section_banner(d, "CLASSIFICATION TREE", y, BAND_NAVY, "10")
# Big classification box
y = info_box(d, [
"CHOLINERGIC AGONISTS",
"",
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━",
"A) DIRECTLY ACTING (mimic ACh by binding receptors directly)",
"",
" 1. Choline Esters — have ester bond:",
" • Acetylcholine (ACh) — natural, no clinical use (destroyed rapidly)",
" • Carbachol — resistant to hydrolysis; muscarinic + nicotinic; used in glaucoma",
" • Bethanechol — selective muscarinic; used in post-op urinary retention & paralytic ileus",
"",
" 2. Alkaloids — plant-derived, tertiary amines:",
" • Pilocarpine — from Pilocarpus plant; used in glaucoma, sialogogue",
" • Muscarine — from Amanita muscaria mushroom; only M receptors",
" • Arecoline — from areca nut; both M + N actions",
"",
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━",
"B) INDIRECTLY ACTING — ANTICHOLINESTERASES (inhibit AChE → ↑ ACh accumulation)",
"",
" i. REVERSIBLE:",
" Carbamates: Physostigmine | Neostigmine | Pyridostigmine | Rivastigmine",
" Alcohol: Edrophonium (very short acting: 8–10 min)",
" Others: Donepezil | Galantamine | Tacrine",
"",
" ii. IRREVERSIBLE (covalent bond — phosphorylation of esteratic site):",
" Organophosphates (OPs): Parathion | Malathion | Echothiophate | Dyflos",
" Nerve gases: Sarin, Soman, Tabun, Novichok",
" Carbamates (irreversible): Propoxur | Carbaryl (insecticides)",
], y, bg=BOX_BLUE, border=C_NAVY, font_size=13)
y = section_banner(d, "ACTIONS OF ACh — Muscarinic Effects", y, BAND_TEAL, "11")
y = body(d, "ACh produces muscarinic effects at M1/M2/M3 receptors on target organs. Recall: ACh itself has no therapeutic use due to rapid hydrolysis by both true + pseudocholinesterases. Actions studied by IV injection.", y, 14)
y = table(d,
["Organ", "Receptor", "Mechanism", "Effect"],
[
["Heart — SA node / AV node", "M2", "↑ K⁺ conductance → hyperpolarization", "↓ HR, ↓ AV conduction, ↓ FOC (vagal mimicry)"],
["Blood vessels (endothelium)", "M3", "→ releases NO (EDRF) → SMC relaxation", "VASODILATION → ↓ Blood Pressure"],
["GIT (smooth muscle)", "M3", "↑ IP3/DAG → ↑ Ca²⁺ → contraction", "↑ Tone, ↑ Peristalsis, ↑ secretions, relax sphincters"],
["Urinary bladder", "M3", "Contracts DETRUSOR muscle", "Contracts detrusor + relaxes trigone/sphincter → URINATION"],
["Bronchi", "M3", "Bronchial smooth muscle contracts", "BRONCHOSPASM + ↑ tracheobronchial secretions (CI in asthma!)"],
["Exocrine glands", "M3", "↑ glandular secretion", "↑ Saliva, tears, sweat, gastric acid, bronchial mucus"],
["Eye (iris)", "M3", "Sphincter pupillae contracts", "MIOSIS (pupil constriction)"],
["Eye (ciliary muscle)", "M3", "Ciliary muscle contracts", "Accommodation for near vision; ↓ IOP (opens trabecular meshwork)"],
],
y, col_w=[230, 90, 340, 600], fs=12, header_color=BAND_TEAL)
y = info_box(d,[
"Why ACh is contraindicated in ASTHMA:",
"→ ACh activates M3 receptors in bronchi → bronchospasm + ↑ mucus secretion → can be fatal",
"→ Therefore ALL cholinergic/parasympathomimetic drugs are contraindicated in asthma patients",
], y, bg=BOX_RED, border=C_RUST, font_size=13)
d.text((MARGIN_L, H-44), "Page 4 of 10 | Cholinergic System — Detailed Notes", fill=C_GRAY, font=gf(13, italic=True))
d.text((W-MARGIN_R-60, H-44), "4", fill=C_NAVY, font=gf(16, bold=True))
pages.append(img)
# ════════════════════════════════════════════════════════════════
# PAGE 5 — EYE + NICOTINIC ACTIONS + CHOLINE ESTER COMPARISON
# ════════════════════════════════════════════════════════════════
img, d = new_page()
y = 10
y = page_header(d, "ACh ON EYE | NICOTINIC ACTIONS | CHOLINE ESTERS", "Muscarinic Eye Effects • Nicotinic Actions • Drug Comparison Table", y)
y = section_banner(d, "EFFECT OF ACh ON THE EYE (Fig 2.9) — Muscarinic Actions", y, BAND_TEAL, "12")
# Eye anatomy description
y = body(d, "The eye has TWO muscular systems controlled by the autonomic nervous system:", y, 15)
y = bullet(d, "IRIS — contains sphincter pupillae (parasympathetic, M3 → MIOSIS) and dilator pupillae (sympathetic, α1 → MYDRIASIS)", y)
y = bullet(d, "CILIARY MUSCLE — contracts under parasympathetic stimulation (M3) → relaxes suspensory ligaments → lens becomes MORE CONVEX (bulges) → near vision", y)
y = bullet(d, "Canal of SCHLEMM — aqueous humour drains through trabecular meshwork into this canal (key in glaucoma)", y)
y = spacer(y, 8)
# Full eye flow diagram
y = section_banner(d, "Muscarinic Agonist Action on Eye — Step by Step", y, BAND_GREEN, "")
y = flow_v(d, [
"ACh (IV) / Pilocarpine / Physostigmine activate M3 receptors in the eye",
"TWO parallel effects occur simultaneously ↓",
"LEFT: Contract SPHINCTER PUPILLAE → MIOSIS (pupil constricts)",
"RIGHT: Contract CILIARY MUSCLE → Spasm of accommodation (lens bulges for near vision)",
"Miosis opens TRABECULAR MESHWORK around the canal of Schlemm",
"Facilitates DRAINAGE of aqueous humour",
"↓ Intraocular Pressure (IOP) → USEFUL IN GLAUCOMA",
"Note: Topical ACh has NO effect on eye (cannot penetrate corneal epithelium)",
], y, box_color=BOX_TEAL, border=C_TEAL, fs=14)
y = section_banner(d, "NICOTINIC ACTIONS OF ACh (larger doses required)", y, BAND_RUST, "13")
y = body(d, "To study nicotinic effects, ATROPINE must be given first to block muscarinic effects.", y, 14, C_RUST, bold=True)
y = table(d,
["Site", "Receptor", "Effect at Low Dose", "Effect at High Dose"],
[
["Autonomic ganglia (all)", "NN", "Stimulates both sympathetic + para ganglia → tachycardia, ↑ BP", "Ganglionic BLOCK (depolarization block) → paradoxical effects"],
["Skeletal muscle (NMJ)", "NM", "Twitchings, fasciculations", "Prolonged depolarization → PARALYSIS of all skeletal muscles"],
["Adrenal medulla", "NN", "Adrenaline + NA release", "Excessive catecholamine release → hypertension"],
["CNS", "NN (central)", "NONE — ACh does NOT cross BBB (IV administration)", "No central effects observed from peripheral ACh"],
],
y, col_w=[210, 90, 450, 510], fs=12, header_color=BAND_RUST)
y = section_banner(d, "CHOLINE ESTERS — Comparison Table", y, BAND_PURPLE, "14")
y = table(d,
["Property", "Acetylcholine (ACh)", "Carbachol", "Bethanechol"],
[
["Chemical", "Choline ester (quaternary)", "Carbamylcholine (quaternary)", "Carbamyl-β-methyl choline (quaternary)"],
["Metabolized by", "True + Pseudo ChE (rapidly hydrolysed)", "RESISTANT to both cholinesterases", "RESISTANT to both cholinesterases"],
["Muscarinic actions", "++ (YES — strong)", "+ (YES)", "+ (YES)"],
["Nicotinic actions", "+ (YES)", "+ (YES)", "— (NO — purely muscarinic)"],
["Effect of Atropine", "Completely blocks muscarinic actions", "NOT completely blocked by atropine", "Completely blocks muscarinic actions"],
["Selectivity", "Non-selective (M + N)", "Mixed (M + N)", "Selective for M3 on bladder + GIT"],
["Therapeutic use", "NONE (too short acting — destroyed in blood)", "Glaucoma (ophthalmic drops)", "Post-op urinary retention, Paralytic ileus"],
["Route of admin", "IV only (to study pharmacology)", "Topical (eye)", "Oral / SC (not IV — severe hypotension risk)"],
],
y, col_w=[210, 320, 310, 420], fs=12, header_color=BAND_PURPLE)
d.text((MARGIN_L, H-44), "Page 5 of 10 | Cholinergic System — Detailed Notes", fill=C_GRAY, font=gf(13, italic=True))
d.text((W-MARGIN_R-60, H-44), "5", fill=C_NAVY, font=gf(16, bold=True))
pages.append(img)
# ════════════════════════════════════════════════════════════════
# PAGE 6 — PILOCARPINE + MUSCARINE + GLAUCOMA
# ════════════════════════════════════════════════════════════════
img, d = new_page()
y = 10
y = page_header(d, "PILOCARPINE | MUSCARINE | GLAUCOMA", "Cholinomimetic Alkaloids & Glaucoma Pharmacology in Detail", y)
y = section_banner(d, "PILOCARPINE — Cholinomimetic Alkaloid", y, BAND_TEAL, "15")
y = table(d,
["Property", "Details"],
[
["Source", "Obtained from PILOCARPUS plant (P. jaborandi)"],
["Chemistry", "TERTIARY AMINE → good tissue penetration; crosses BBB; effective topically"],
["Mechanism", "Directly acts on muscarinic (M3 predominant) AND nicotinic receptors"],
["Predominant effect", "Muscarinic — especially on SECRETORY activity (most potent sialogogue)"],
],
y, col_w=[200, 1060], fs=13, header_color=BAND_TEAL)
y = sub_heading(d, "USES of Pilocarpine:", y)
y = bullet(d, "GLAUCOMA (0.5%–4% topical drops): Increases ciliary muscle tone → miosis → opens trabecular meshwork → ↓ IOP. Both open-angle and acute congestive (narrow-angle) glaucoma. Also available as Pilocarpine Ocusert (sustained release over 7 days)", y, 14)
y = bullet(d, "BREAK ADHESIONS between iris and lens (posterior synechiae) — used alternately with mydriatics", y, 14)
y = bullet(d, "REVERSE PUPILLARY DILATATION after refraction testing", y, 14)
y = bullet(d, "SIALOGOGUE — stimulates salivation; used in xerostomia (dry mouth), Sjögren's syndrome", y, 14)
y = bullet(d, "Pilocarpine is the drug of choice for ACUTE CONGESTIVE GLAUCOMA (emergency)", y, 14, color=C_RUST)
y = info_box(d, [
"Adverse Effects of Pilocarpine: Salivation | Sweating | Bradycardia | Diarrhoea | Bronchospasm",
"Pulmonary oedema can occur following systemic therapy",
"Contraindicated in: Asthma, COPD, heart block",
], y, bg=BOX_RED, border=C_RUST, font_size=13)
y = section_banner(d, "MUSCARINE & MUSHROOM POISONING", y, BAND_RUST, "16")
y = body(d, "Muscarine is the active toxin in Inocybe and Amanita muscaria mushrooms. Three distinct types of mushroom poisoning exist:", y, 14)
y = table(d,
["Type", "Mushroom Species", "Toxin", "Onset", "Clinical Features", "Treatment"],
[
["Rapid onset\n(Muscarine type)", "Inocybe spp.", "MUSCARINE", "< 30 min", "SLUDGE signs: Salivation, Lacrimation, Urination, Defecation, GI cramps, Emesis. Also: bradycardia, bronchospasm, sweating, hypotension", "IV ATROPINE (reverses muscarinic)"],
["Hallucinogen type", "A. muscaria, Psilocybe spp.", "MUSCIMOL (ibotenic acid)", "30 min – 2 h", "Mainly CENTRAL effects: hallucinations, disorientation, euphoria, tachycardia. Muscarinic features minimal", "Supportive ONLY. Atropine CONTRAINDICATED"],
["Delayed onset\n(Deadly type)", "Amanita phalloides (Death Cap)", "AMATOXIN (amatoxin)", "6–24 h", "Delayed gastroenteritis (6–24h), then hepatic + renal failure (day 3–5). Does NOT respond to atropine", "Thioctic acid (alpha-lipoic acid) + Supportive. No antidote"],
],
y, col_w=[150, 180, 160, 100, 480, 190], fs=11, header_color=BAND_RUST)
y = section_banner(d, "GLAUCOMA — Pathophysiology & Drug Overview", y, BAND_NAVY, "17")
y = body(d, "Glaucoma = Optic nerve damage with loss of visual function associated with raised IOP (>21 mmHg). Aqueous humour is continuously produced by the ciliary body and drained via trabecular meshwork (Canal of Schlemm) + uveoscleral outflow.", y, 14)
y = table(d,
["Drug Class", "Acute Congestive (Narrow-angle)", "Chronic Simple (Wide-angle / Open-angle)"],
[
["Osmotic agents", "Mannitol 20% IV (1.5g/kg), Glycerol 50% oral — draw fluid from eye osmotically", "NOT used"],
["Carbonic Anhydrase Inhibitors", "Acetazolamide IV/oral — reduces aqueous formation by inhibiting CA enzyme in ciliary epithelium", "Dorzolamide 2% topical, Brinzolamide topical, Acetazolamide oral"],
["β-Blockers (topical)", "Timolol 0.5% topical — blocks β2 on ciliary epithelium → ↓ aqueous formation", "Timolol 0.25%, Betaxolol 0.25% (β1-selective, safe in asthma), Carteolol 1%, Levobunolol (long-acting)"],
["Prostaglandins (topical)", "Latanoprost 0.005%", "DRUG OF CHOICE in open-angle: Latanoprost, Travoprost, Bimatoprost (PGF2α analogues, once daily, ↑ uveoscleral outflow)"],
["Miotics (Cholinergic)", "Pilocarpine 2% topical", "Pilocarpine 0.5% topical"],
["α-Adrenergic agonists", "NOT first-line", "Apraclonidine (α2-agonist, ↓ aqueous), Dipivefrin (prodrug of adrenaline — penetrates cornea via esterases)"],
],
y, col_w=[250, 430, 580], fs=11, header_color=BAND_NAVY)
y = info_box(d, [
"Key facts on glaucoma drugs:",
"• Propranolol NOT used in glaucoma — membrane-stabilizing effect anesthetizes cornea",
"• Betaxolol is β1-selective → SAFE in patients with asthma/COPD (does not cause bronchospasm)",
"• Prostaglandins (latanoprost): once daily dosing, high efficacy, ↓ systemic toxicity → DRUG OF CHOICE open-angle glaucoma",
"• Apraclonidine: α2-agonist on ciliary epithelium → ↓ aqueous formation; does NOT cross BBB (no hypotension)",
"• Dipivefrin = prodrug of adrenaline → penetrates cornea → converted by esterases inside the eye",
], y, bg=BOX_YELLOW, border=C_GOLD, font_size=13)
d.text((MARGIN_L, H-44), "Page 6 of 10 | Cholinergic System — Detailed Notes", fill=C_GRAY, font=gf(13, italic=True))
d.text((W-MARGIN_R-60, H-44), "6", fill=C_NAVY, font=gf(16, bold=True))
pages.append(img)
# ════════════════════════════════════════════════════════════════
# PAGE 7 — ANTICHOLINESTERASES MECHANISM + REVERSIBLE DRUGS
# ════════════════════════════════════════════════════════════════
img, d = new_page()
y = 10
y = page_header(d, "ANTICHOLINESTERASES — Mechanism & Reversible Drugs", "Physostigmine | Neostigmine | Pyridostigmine | Edrophonium | Alzheimer's drugs", y)
y = section_banner(d, "MECHANISM OF ANTICHOLINESTERASES (Fig 2.11)", y, BAND_NAVY, "18")
y = body(d, "Anticholinesterases inhibit the enzyme AChE → ACh NOT broken down → ACCUMULATES at muscarinic AND nicotinic sites → Prolonged/enhanced cholinergic effects. They are called INDIRECTLY ACTING cholinergic drugs.", y, 14)
y = table(d,
["Drug Type", "Binding Site", "Bond Type", "Duration", "Hydrolysis of enzyme", "Example"],
[
["ACh (normal)", "Anionic + Esteratic", "Non-covalent (transient)", "Milliseconds", "Rapid — acetylated enzyme hydrolyses quickly", "Normal physiological process"],
["Edrophonium", "Anionic site ONLY", "Weak hydrogen bond", "8–10 minutes", "Diffuses away spontaneously", "Diagnosis of MG"],
["Carbamates\n(Neostigmine etc.)", "Anionic + Esteratic", "Carbamoylation (covalent but hydrolysable)", "30 min – 6 hours", "SLOW hydrolysis → reversible", "Neostigmine, Physostigmine"],
["Organophosphates (OPs)", "Esteratic site ONLY", "COVALENT PHOSPHORYLATION (irreversible)", "Days–weeks ('aging')", "NO spontaneous hydrolysis → permanent unless treated with PAM", "Sarin, Malathion, Echothiophate"],
],
y, col_w=[180, 170, 250, 170, 370, 120], fs=11, header_color=BAND_NAVY)
y = info_box(d, [
"'AGING' of organophosphate-AChE complex:",
"After OP binds esteratic site → if not treated promptly → the bond STRENGTHENS (dealkylation)",
"→ Enzyme becomes PERMANENTLY inactivated even by oximes (PAM)",
"→ Therefore, treatment must be given EARLY in OP poisoning",
"Echothiophate: binds BOTH anionic and esteratic sites — even stronger irreversible inhibition",
], y, bg=BOX_RED, border=C_RUST, font_size=13)
y = section_banner(d, "REVERSIBLE ANTICHOLINESTERASES — Individual Drugs", y, BAND_TEAL, "19")
y = table(d,
["Drug", "Chemistry", "Crosses BBB?", "Key Actions", "Uses", "Notes"],
[
["Physostigmine\n(Eserine)", "Natural alkaloid\n(Physostigma venenosum)\nTertiary amine", "YES — central + peripheral effects", "Inhibits true + pseudo ChE reversibly. Good tissue penetration → effective topically", "1. Atropine & antimuscarinic poisoning (IV)\n2. Glaucoma (now rarely used)", "Causes cataract on chronic use in glaucoma. Give SLOWLY IV (causes bradycardia)"],
["Neostigmine", "Synthetic\nQuaternary ammonium\n(structural similarity to ACh)", "NO — peripheral effects only", "Indirect: inhibits ChE → ↑ ACh at NMJ\nDirect: directly stimulates NM receptors", "1. Myasthenia gravis\n2. Post-op urinary retention\n3. Paralytic ileus\n4. Reverse non-depolarizing block\n5. Curare poisoning", "Give atropine simultaneously (block muscarinic side-effects)"],
["Pyridostigmine", "Synthetic\nQuaternary ammonium", "NO — peripheral only", "Same as neostigmine. Longer duration", "PREFERRED in myasthenia gravis (better tolerated, can give twice daily sustained release)", "Less potent than neostigmine but BETTER TOLERATED; preferred in MG"],
["Edrophonium", "Synthetic\nQuaternary ammonium", "NO", "Binds anionic site only → weak reversible inhibition", "1. DIAGNOSIS of myasthenia gravis (Tensilon test)\n2. Differentiate myasthenic vs cholinergic crisis\n3. Curare poisoning", "Very rapid onset, VERY SHORT duration (8–10 min). Keep atropine ready!"],
["Galantamine\nRivastigmine\nDonepezil", "Synthetic (cerebroselective)", "YES — cross BBB selectively", "Preferentially inhibit brain AChE → ↑ cerebral ACh", "ALZHEIMER'S DISEASE — improves cognition in mild-moderate disease", "Do not cross BBB as much as physostigmine — fewer peripheral side effects"],
],
y, col_w=[155, 175, 120, 295, 340, 175], fs=11, header_color=BAND_TEAL)
y = info_box(d, [
"KEY COMPARISON — Physostigmine vs Neostigmine at a glance:",
"Physostigmine = TERTIARY amine = crosses BBB → used when CENTRAL effects needed (atropine poisoning)",
"Neostigmine = QUATERNARY ammonium = NO CNS = peripheral only → used in MG (no CNS side effects)",
"",
"Pyridostigmine is PREFERRED over neostigmine in MYASTHENIA GRAVIS because:",
"→ Longer duration of action (can be given twice daily in SR form)",
"→ Better tolerated (fewer side effects) even though it is less potent",
], y, bg=BOX_YELLOW, border=C_GOLD, title="Must-Know Comparison", font_size=13)
d.text((MARGIN_L, H-44), "Page 7 of 10 | Cholinergic System — Detailed Notes", fill=C_GRAY, font=gf(13, italic=True))
d.text((W-MARGIN_R-60, H-44), "7", fill=C_NAVY, font=gf(16, bold=True))
pages.append(img)
# ════════════════════════════════════════════════════════════════
# PAGE 8 — MYASTHENIA GRAVIS
# ════════════════════════════════════════════════════════════════
img, d = new_page()
y = 10
y = page_header(d, "MYASTHENIA GRAVIS", "Pathophysiology | Diagnosis | Treatment | Crisis Management", y)
y = section_banner(d, "WHAT IS MYASTHENIA GRAVIS?", y, BAND_NAVY, "20")
y = body(d, "Myasthenia Gravis (MG) is an AUTOIMMUNE NEUROMUSCULAR DISEASE in which the immune system produces antibodies against NM (nicotinic-muscle) receptors at the NMJ → decreased number of functional NM receptors → impaired neuromuscular transmission → muscle weakness.", y, 14)
y = info_box(d, [
"Pathophysiology in steps:",
"1. Thymus produces abnormal T-cells → stimulate B-cells",
"2. B-cells produce IgG antibodies against NM receptors at NMJ",
"3. Antibodies bind NM receptors → complement-mediated destruction",
"4. ↓ Functional NM receptors at NMJ → reduced end-plate potentials",
"5. Muscle WEAKNESS — worse with activity, better with rest",
"6. Thymoma (thymic tumour) present in ~15% of MG patients — thymectomy can induce remission",
], y, bg=BOX_BLUE, border=C_NAVY, font_size=13)
y = sub_heading(d, "Clinical Features:", y)
y = bullet(d, "Marked MUSCULAR WEAKNESS varying in degree at different times of day (worse in evening)", y, 14)
y = bullet(d, "EASY FATIGABILITY — weakness increases with repetitive activity", y, 14)
y = bullet(d, "Typically involves: ocular muscles (ptosis, diplopia), facial muscles, bulbar muscles (dysphagia, dysarthria), limb muscles, respiratory muscles", y, 14)
y = section_banner(d, "DIAGNOSIS OF MYASTHENIA GRAVIS", y, BAND_GREEN, "21")
y = table(d,
["Diagnostic Test", "Method", "Result in MG", "Interpretation"],
[
["Tensilon Test\n(Edrophonium test)", "IV Edrophonium 2–10 mg (given slowly)", "DRAMATIC improvement in muscle weakness within 30–60 seconds", "Positive = MG. Improvement is transient (8–10 min). Keep ATROPINE ready (may cause bradycardia)"],
["Anti-NM receptor antibodies", "Blood test for circulating antibodies against NM receptors", "POSITIVE in ~85% of MG patients", "Confirmatory test. Negative does not exclude MG (seronegative MG)"],
["EMG (Repetitive nerve stimulation)", "Electrical stimulation of nerve at 3 Hz", "DECREMENTAL response in compound muscle action potential (CMAP)", "Indicates progressive failure of NMJ transmission"],
["Chest CT/MRI", "Imaging of anterior mediastinum", "Thymoma or thymic hyperplasia in 75% of MG patients", "Indicates need for thymectomy"],
],
y, col_w=[200, 270, 350, 440], fs=12, header_color=BAND_GREEN)
y = section_banner(d, "TREATMENT OF MYASTHENIA GRAVIS", y, BAND_TEAL, "22")
y = table(d,
["Treatment", "Drug/Method", "Mechanism", "Notes"],
[
["Symptomatic\n(anticholinesterases)", "Pyridostigmine (PREFERRED)\nNeostigmine\nAmbenonium", "Inhibit AChE → ↑ ACh at NMJ → better NMJ transmission", "Do NOT cure MG — only symptomatic relief. Atropine given alongside for muscarinic SE"],
["Immunosuppression\n(disease modifying)", "Corticosteroids (Prednisolone)\nAzathioprine\nCyclophosphamide\nMycophenolate", "Suppress abnormal immune response → ↓ antibody production", "Corticosteroids: initial worsening then sustained improvement. Azathioprine: for maintenance"],
["Thymectomy", "Surgical removal of thymus", "Removes source of abnormal T-cell stimulation", "Recommended in all MG patients < 60 years, especially if thymoma present"],
["Plasmapheresis", "Plasma exchange (removes antibodies)", "Removes circulating anti-NM antibodies", "Short-term benefit (days–weeks). Used in myasthenic crisis or pre-surgery"],
["IV Immunoglobulin (IVIG)", "High-dose IV IgG", "Modulates immune response; Fc receptor blockade", "Alternative to plasmapheresis in crisis. Effect lasts 3–6 weeks"],
],
y, col_w=[200, 280, 330, 450], fs=11, header_color=BAND_TEAL)
y = info_box(d, [
"DRUGS CONTRAINDICATED in Myasthenia Gravis (they WORSEN neuromuscular block):",
"• Aminoglycoside antibiotics (Gentamicin, Streptomycin) — inhibit Ca²⁺ at NMJ",
"• d-Tubocurarine (d-TC) and other non-depolarizing NMJ blockers",
"• β-Blockers (reduce end-plate sensitivity)",
"• Ether (anaesthetic)",
"• Phenytoin (membrane stabilizer)",
"• Magnesium (inhibits ACh release)",
], y, bg=BOX_RED, border=C_RUST, title="DANGER — Contraindicated Drugs in MG", font_size=13)
d.text((MARGIN_L, H-44), "Page 8 of 10 | Cholinergic System — Detailed Notes", fill=C_GRAY, font=gf(13, italic=True))
d.text((W-MARGIN_R-60, H-44), "8", fill=C_NAVY, font=gf(16, bold=True))
pages.append(img)
# ════════════════════════════════════════════════════════════════
# PAGE 9 — MYASTHENIC CRISIS + OP POISONING
# ════════════════════════════════════════════════════════════════
img, d = new_page()
y = 10
y = page_header(d, "MYASTHENIC CRISIS | OP POISONING | THERAPEUTIC USES", "Crisis Management | Organophosphate Toxicology | Clinical Applications", y)
y = section_banner(d, "MYASTHENIC CRISIS vs CHOLINERGIC CRISIS", y, BAND_RUST, "23")
y = table(d,
["Feature", "Myasthenic Crisis", "Cholinergic Crisis"],
[
["Definition", "Sudden severe exacerbation of MG weakness (under-treatment or stress)", "Overdose of anticholinesterase drugs → ↑ ACh → prolonged depolarization block"],
["Cause", "Too LITTLE ACh effect at NMJ (under-treatment, infection, surgery, stress)", "Too MUCH ACh effect (anticholinesterase overdose)"],
["Muscle weakness", "Severe — due to failure of NMJ transmission", "Severe — due to depolarization block (excess ACh paralyses)"],
["Cholinergic signs\n(SLUDGE)", "ABSENT (no excess ACh)", "PRESENT: Salivation, Lacrimation, Urination, Defecation, GI cramps, Emesis + Bradycardia, Bronchospasm, Sweating"],
["Pupils", "Normal or slightly dilated", "MIOSIS (constricted)"],
["Edrophonium test", "IMPROVEMENT → confirms myasthenic crisis", "WORSENING or no improvement → confirms cholinergic crisis"],
["Treatment", "Give MORE anticholinesterase (Neostigmine/Pyridostigmine) + mechanical ventilation if needed", "STOP anticholinesterase immediately + Give ATROPINE + Ventilator support"],
],
y, col_w=[190, 470, 600], fs=12, header_color=BAND_RUST)
y = info_box(d, [
"IMPORTANT PROTOCOL: Before giving Edrophonium for Tensilon test:",
"→ Keep ATROPINE ready (0.6 mg IV) — if cholinergic crisis worsens, atropine reverses muscarinic effects",
"→ Keep VENTILATOR on standby (respiratory muscle paralysis can occur)",
"→ Give Edrophonium SLOWLY IV (2 mg test dose first, then 8 mg if no adverse reaction)",
], y, bg=BOX_YELLOW, border=C_GOLD, font_size=13)
y = section_banner(d, "ORGANOPHOSPHATE (OP) POISONING — Irreversible Anticholinesterases", y, BAND_PURPLE, "24")
y = body(d, "OP compounds irreversibly phosphorylate the esteratic site of AChE → ACh accumulates at ALL cholinergic sites. Most common poisoning worldwide. Common agents: Parathion, Malathion, Dyflos. Nerve agents: Sarin, Soman, Tabun.", y, 14)
y = sub_heading(d, "SIGNS & SYMPTOMS — The SLUDGE + DUMBELS Mnemonic:", y)
y = table(d,
["Type", "Features", "Mnemonic"],
[
["MUSCARINIC effects\n(M receptors)", "Salivation, Lacrimation, Urination, Defecation (involuntary)\nGI cramps, Emesis, Bradycardia, Hypotension\nMiosis, Bronchospasm, ↑ Bronchial secretions, Sweating", "SLUDGE:\nSalivation Lacrimation Urination\nDefecation GI-cramps Emesis\n\nDUMBELS:\nDiarrhoea Urination Miosis Bradycardia\nEmesis Lacrimation Salivation"],
["NICOTINIC effects\n(N receptors)", "Twitchings, Fasciculations\nMuscle weakness → PARALYSIS\n(Prolonged depolarization of NMJ)", "The 'Killer' — respiratory muscle paralysis causes DEATH"],
["CENTRAL effects\n(CNS)", "Headache, Restlessness, Anxiety\nConfusion, Convulsions\nComa → DEATH (respiratory failure)", "CNS signs = SEVERE poisoning"],
],
y, col_w=[200, 580, 480], fs=12, header_color=BAND_PURPLE)
y = sub_heading(d, "DIAGNOSIS of OP poisoning:", y)
y = bullet(d, "History of exposure (agricultural, industrial, intentional)", y, 14)
y = bullet(d, "Characteristic clinical signs (miosis + bradycardia + bronchospasm = classic triad)", y, 14)
y = bullet(d, "Decreased plasma/RBC cholinesterase activity (blood test — specific biomarker)", y, 14)
y = spacer(y, 6)
y = sub_heading(d, "TREATMENT of OP poisoning:", y)
y = bullet(d, "ATROPINE — HIGH DOSE IV (2–4 mg every 5–10 min until secretions dry up): Blocks MUSCARINIC effects only. Does NOT reverse paralysis (nicotinic). Give until 'atropinisation' achieved (dry mouth, ↑ HR, ↑ BP)", y, 14, color=C_RUST)
y = bullet(d, "PRALIDOXIME (PAM / 2-PAM) — IV infusion: Reactivates phosphorylated AChE IF given EARLY (before aging). Reverses BOTH muscarinic + nicotinic effects. Must be given within 24–48 hours (before aging)", y, 14, color=C_RUST)
y = bullet(d, "DIAZEPAM — IV: Prevents/treats convulsions (seizures from CNS ACh excess)", y, 14)
y = bullet(d, "Remove contaminated clothing, wash skin thoroughly", y, 14)
y = bullet(d, "Mechanical ventilation if respiratory muscle paralysis", y, 14)
y = info_box(d, [
"Why ATROPINE works but cannot fully save in OP poisoning:",
"→ Atropine blocks M receptors only → dries secretions, reverses bradycardia + bronchospasm",
"→ Atropine has NO effect on NICOTINIC sites → cannot reverse muscle paralysis",
"→ PRALIDOXIME (PAM) reactivates AChE → reduces ACh at BOTH M and N sites",
"→ BUT PAM must be given EARLY before 'aging' of phosphorylated AChE complex (usually < 24–48h)",
], y, bg=BOX_RED, border=C_RUST, title="Critical Point — OP Poisoning Treatment", font_size=13)
d.text((MARGIN_L, H-44), "Page 9 of 10 | Cholinergic System — Detailed Notes", fill=C_GRAY, font=gf(13, italic=True))
d.text((W-MARGIN_R-60, H-44), "9", fill=C_NAVY, font=gf(16, bold=True))
pages.append(img)
# ════════════════════════════════════════════════════════════════
# PAGE 10 — THERAPEUTIC USES + MASTER SUMMARY
# ════════════════════════════════════════════════════════════════
img, d = new_page()
y = 10
y = page_header(d, "THERAPEUTIC USES & MASTER SUMMARY", "All Clinical Applications | Quick Revision Table | High-Yield Points", y)
y = section_banner(d, "THERAPEUTIC USES OF REVERSIBLE ANTICHOLINESTERASES", y, BAND_GREEN, "25")
y = table(d,
["Indication", "Drug of Choice", "Why / Mechanism"],
[
["Myasthenia Gravis\n(symptomatic)", "Pyridostigmine (1st choice)\nNeostigmine (alt)", "Inhibit AChE → ↑ ACh at NMJ → improves neuromuscular transmission"],
["Diagnosis of MG\n(Tensilon test)", "Edrophonium IV", "Rapid onset (30 sec); dramatic improvement in MG; differentiates myasthenic vs cholinergic crisis"],
["Glaucoma", "Physostigmine (now rarely)\nPilocarpine (miotics)", "↓ IOP by miosis → opens trabecular meshwork → ↑ aqueous drainage"],
["Post-operative urinary\nretention & paralytic ileus", "Neostigmine\nBethanechol (alt)", "↑ detrusor tone + ↑ GIT motility; bethanechol more selective for bladder + GIT"],
["Reverse non-depolarizing\nNMJ block (curare reversal)", "Neostigmine + Atropine\nEdrophonium (if rapid)", "↑ ACh competes with curare at NM receptors; atropine prevents bradycardia"],
["Belladonna / Atropine\npoisoning", "Physostigmine IV\n(not neostigmine)", "ONLY physostigmine crosses BBB → reverses BOTH central + peripheral atropine effects"],
["Alzheimer's disease", "Donepezil (1st line)\nRivastigmine\nGalantamine", "Cerebroselective AChE inhibition → ↑ cerebral ACh → improved cognition in mild-moderate AD"],
["Sialogogue\n(dry mouth / xerostomia)", "Pilocarpine (oral)", "Direct M3 agonist → stimulates salivary glands"],
["Break iris-lens adhesions\n(posterior synechiae)", "Pilocarpine (alternated\nwith mydriatics)", "Repeated contraction/relaxation of iris breaks adhesions"],
],
y, col_w=[250, 250, 760], fs=12, header_color=BAND_GREEN)
y = section_banner(d, "MASTER DRUG SUMMARY TABLE", y, BAND_NAVY, "26")
y = table(d,
["Drug", "Class", "BBB?", "Key Clinical Use", "Major Adverse Effect"],
[
["Acetylcholine", "Choline ester (direct M+N)", "No", "Research only (no clinical use)", "No clinical use"],
["Bethanechol", "Choline ester (direct M)", "No", "Post-op urinary retention, Paralytic ileus", "Bronchospasm (CI in asthma)"],
["Carbachol", "Choline ester (direct M+N)", "No", "Glaucoma (topical)", "Miosis, bronchospasm"],
["Pilocarpine", "Alkaloid (direct M>N)", "Yes (tertiary)", "Glaucoma, Sialogogue, Break iris adhesions", "Salivation, sweating, bradycardia"],
["Physostigmine", "Reversible AChE inhibitor", "YES", "Atropine poisoning, Glaucoma (rarely)", "Bradycardia, bronchospasm, cataract (chronic)"],
["Neostigmine", "Reversible AChE inhibitor", "NO", "MG, Post-op urinary retention, Curare reversal", "SLUDGE signs (give atropine)"],
["Pyridostigmine", "Reversible AChE inhibitor", "NO", "MG (preferred — better tolerated, longer acting)", "SLUDGE signs (milder than neostigmine)"],
["Edrophonium", "Reversible AChE inhibitor", "NO", "Diagnosis of MG, Crisis differentiation", "Bradycardia, bronchospasm — KEEP ATROPINE READY"],
["Donepezil", "Cerebroselective AChE inhib", "YES", "Alzheimer's disease (1st line)", "GI upset (nausea, diarrhoea)"],
["Galantamine", "Cerebroselective AChE inhib", "YES", "Alzheimer's disease", "GI upset, dizziness"],
["Rivastigmine", "Cerebroselective AChE inhib", "YES", "Alzheimer's + Parkinson's dementia", "GI upset (patch formulation reduces this)"],
["Parathion/Malathion", "Irreversible OP (toxic)", "YES", "Insecticides (NO therapeutic use)", "Severe OP toxidrome → death"],
["Echothiophate", "Irreversible OP", "Minimal", "Glaucoma (rarely — resistant cases)", "Prolonged miosis, cataract"],
["Sarin/Soman/Tabun", "Irreversible OP (nerve agents)", "YES", "None — only toxicological (bioweapons)", "Rapid death if untreated"],
],
y, col_w=[195, 220, 70, 420, 355], fs=11, header_color=BAND_NAVY)
y = section_banner(d, "HIGH-YIELD EXAM POINTS", y, BAND_RUST, "27")
points = [
"Bethanechol = selective M3 agonist, NO nicotinic effects, NOT blocked fully by atropine in carbachol (carbachol is not completely blocked) ",
"Pilocarpine = TERTIARY amine → penetrates cornea → effective TOPICALLY for glaucoma",
"Neostigmine/Pyridostigmine = QUATERNARY → cannot cross BBB → safe in MG (no CNS effects)",
"Physostigmine = crosses BBB → used for ATROPINE POISONING (reverses central effects neostigmine cannot)",
"Edrophonium = 8–10 min duration → DIAGNOSIS only (Tensilon test) — not treatment",
"PAM (Pralidoxime) = MUST be given EARLY in OP poisoning (before aging of enzyme at 24–48h)",
"Atropine in OP poisoning = reverses MUSCARINIC effects only; PAM reverses BOTH M + N",
"Prostaglandins (Latanoprost) = DRUG OF CHOICE in open-angle glaucoma (once daily, ↑ uveoscleral outflow)",
"Propranolol is NOT used in glaucoma (membrane stabilising effect anesthetises cornea)",
"Betaxolol = β1-selective blocker for glaucoma → SAFE in asthma (unlike timolol which is non-selective)",
"ACh has NO therapeutic use — destroyed by pseudocholinesterase in blood even if given IV",
"All cholinergic drugs CONTRAINDICATED in ASTHMA (bronchospasm risk)",
"Pyridostigmine > Neostigmine in MG: longer duration, better tolerated, twice daily SR dosing",
]
for pt in points:
y = bullet(d, pt, y, 13, C_DARK, symbol="★", dot_color=C_GOLD)
d.text((MARGIN_L, H-44), "Page 10 of 10 | Cholinergic System — Detailed Notes", fill=C_GRAY, font=gf(13, italic=True))
d.text((W-MARGIN_R-60, H-44), "10", fill=C_NAVY, font=gf(16, bold=True))
pages.append(img)
# ════════════════════════════════════════════════════════════════
# SAVE
# ════════════════════════════════════════════════════════════════
output = "/tmp/workspace/cholinergic-notes/Cholinergic_Detailed_Beautiful_Notes.pdf"
pages[0].save(output, save_all=True, append_images=pages[1:], format="PDF")
print(f"Saved: {output}")
print(f"Total pages: {len(pages)}")
cd /tmp/workspace/cholinergic-notes && python beautiful_notes.py 2>&1
Cholinergic Detailed Beautiful Notes
PDF Document · PDF
| Page | Topic | What's Covered |
|---|---|---|
| 1 | Overview + ANS vs SNS | Cholinergic system intro, ANS vs Somatic NS comparison table, Sites of ACh/NA release, Sympathetic vs Parasympathetic organ effects |
| 2 | ACh Synthesis & Cholinesterases | Step-by-step synthesis flow diagram, ChAT/AChE explained, True vs Pseudocholinesterase table, fate of ACh in synapse, clinical importance |
| 3 | Cholinergic Receptors | Muscarinic vs Nicotinic comparison, receptor cards for M1/M2/M3/M4-5/NN/NM — each with location, mechanism & response, memory tips |
| 4 | Classification + ACh Muscarinic Actions | Full classification tree (all drugs), detailed table of ACh effects on every organ with receptor + mechanism |
| 5 | Eye Effects + Nicotinic + Choline Esters | Complete eye flowchart with steps, nicotinic actions at ganglia/NMJ/CNS, full ACh/Carbachol/Bethanechol comparison table |
| 6 | Pilocarpine + Muscarine + Glaucoma | Pilocarpine uses in detail, mushroom poisoning 3-type table, glaucoma pathophysiology, drugs table for acute vs chronic glaucoma |
| 7 | Anticholinesterase Mechanism + Drugs | Mechanism table (ACh vs Edrophonium vs Carbamates vs OPs), full drug cards for Physostigmine/Neostigmine/Pyridostigmine/Edrophonium/Alzheimer's drugs |
| 8 | Myasthenia Gravis | Pathophysiology, diagnosis tests table, full treatment table (symptomatic + immunosuppression + thymectomy + IVIG), contraindicated drugs |
| 9 | Crises + OP Poisoning | Myasthenic vs Cholinergic crisis comparison, OP poisoning SLUDGE/DUMBELS signs, diagnosis, treatment with Atropine + PAM explained |
| 10 | Therapeutic Uses + Master Summary | All indications with drug of choice table, 14-drug master summary table, 13 high-yield exam points starred |