Answer
cd /home/daytona/workspace/attachments/db94bb3a-46e4-44a6-b74e-eb0efabdbd13 && p…
| Type | Also Called | Direction | Example |
|---|---|---|---|
| Cotransport | Symport | Both solutes move in the SAME direction | Na+-glucose (SGLT1), Na+-amino acid |
| Countertransport | Antiport/Exchange | Solutes move in OPPOSITE directions | Na+-H+ exchanger, Na+-Ca2+ exchanger |
| Ion | Intracellular | Extracellular | Equilibrium Potential | Resting Permeability |
|---|---|---|---|---|
| K+ | 140 mEq/L | 4 mEq/L | -94 mV | HIGH |
| Na+ | 14 mEq/L | 140 mEq/L | +66 mV | LOW |
| Cl- | 4 mEq/L | 114 mEq/L | -90 mV | Moderate |
| Ca2+ | 0.0001 mEq/L | 2.5 mEq/L | +132 mV | Very LOW |
| Factor | Effect on Diffusion |
|---|---|
| Concentration gradient (CA - CB) | ↑ gradient → ↑ diffusion |
| Partition coefficient (K) | ↑ lipid solubility → ↑ diffusion |
| Diffusion coefficient (D) | ↑ in small molecules, low viscosity |
| Membrane thickness (Δx) | ↑ thickness → ↓ diffusion |
| Surface area (A) | ↑ area → ↑ diffusion |
| Feature | Explanation |
|---|---|
| Saturation | Rate increases with concentration but plateaus (Vmax) when all carriers are occupied - unlike simple diffusion which increases linearly |
| Stereospecificity | Carrier recognizes specific molecular shape (e.g., GLUT4 transports D-glucose but NOT L-glucose) |
| Competition | Structurally similar molecules compete for same carrier (e.g., D-galactose competes with D-glucose for the glucose transporter) |
| No energy required | Moves solute only DOWN electrochemical gradient |
| Feature | Simple Diffusion | Facilitated Diffusion |
|---|---|---|
| Carrier protein | No | Yes |
| Energy (ATP) | No | No |
| Saturation | No | Yes (Vmax) |
| Stereospecificity | No | Yes |
| Competition | No | Yes |
| Rate at low concentration | Slower | Faster |
| Rate at high concentration | Continues to rise | Plateaus at Vmax |
| Type | Feature |
|---|---|
| Apoptosis | Caspase-dependent, membrane intact, no inflammation |
| Anoikis | Apoptosis triggered by lack of cell-to-ECM contact |
| Necroptosis | Programmed, caspase-independent, membrane rupture |
| Autophagy | Cell "self-eating" - degradation of own organelles |
| Pyroptosis | Inflammatory cell death (caspase-1 dependent) |
| Topic | Key Point |
|---|---|
| Secondary Active Transport | Uses Na+ gradient (maintained by Na-K-ATPase); Cotransport (symport) vs Countertransport (antiport) |
| RMP | -70 to -80 mV; driven by high K+ permeability; Na-K-ATPase maintains gradient |
| Cell Junctions | Tight (seal), Adherens (actin-based), Desmosome (intermediate filaments), Hemidesmosome (basal lamina), Gap (communication) |
| Na+-K+-ATPase | 3Na+ out : 2K+ in per ATP; α+β subunits; inhibited by ouabain/digitalis |
| Simple Diffusion | Passive; no carrier; rate = P×A×(CA-CB); governed by partition & diffusion coefficients |
| Facilitated Diffusion | Passive with carrier; saturable, stereospecific, competitive; GLUT4 is classic example |
| Apoptosis | Programmed cell death; caspase-dependent; intrinsic (mitochondrial) or extrinsic (death receptor) pathway |
Generate a summary PDF with diagrams and key equations
mkdir -p /home/daytona/workspace/gen-physiology-pdf && ls /home/daytona/workspac…
~/gen-physiology-pdf/build_pdf.py
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import cm, mm
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, PageBreak, KeepTogether
)
from reportlab.platypus.flowables import Flowable
from reportlab.graphics.shapes import Drawing, Rect, String, Line, Arrow, Circle, Polygon
from reportlab.graphics import renderPDF
from reportlab.graphics.shapes import Group
import math
# ── Output path ──────────────────────────────────────────────────────────────
OUTPUT = "/home/daytona/workspace/gen-physiology-pdf/General_Physiology_Summary.pdf"
# ── Colour palette ────────────────────────────────────────────────────────────
BLUE_DARK = colors.HexColor("#1A3A5C")
BLUE_MID = colors.HexColor("#2E6DA4")
BLUE_LIGHT = colors.HexColor("#D6E8FA")
TEAL = colors.HexColor("#0B7285")
TEAL_LIGHT = colors.HexColor("#C8EEF2")
GREEN_DARK = colors.HexColor("#1B5E20")
GREEN_LIGHT = colors.HexColor("#E8F5E9")
ORANGE_DARK = colors.HexColor("#E65100")
ORANGE_LIGHT= colors.HexColor("#FFF3E0")
RED_DARK = colors.HexColor("#B71C1C")
RED_LIGHT = colors.HexColor("#FFEBEE")
PURPLE_DARK = colors.HexColor("#4A148C")
PURPLE_LIGHT= colors.HexColor("#F3E5F5")
YELLOW = colors.HexColor("#FFF9C4")
GRAY_LIGHT = colors.HexColor("#F5F5F5")
GRAY_MID = colors.HexColor("#BDBDBD")
WHITE = colors.white
BLACK = colors.black
# ── Styles ────────────────────────────────────────────────────────────────────
styles = getSampleStyleSheet()
def S(name, **kw):
return ParagraphStyle(name, **kw)
COVER_TITLE = S("CoverTitle", fontSize=28, leading=36, textColor=WHITE,
fontName="Helvetica-Bold", alignment=TA_CENTER)
COVER_SUB = S("CoverSub", fontSize=14, leading=20, textColor=BLUE_LIGHT,
fontName="Helvetica", alignment=TA_CENTER)
H1 = S("H1", fontSize=16, leading=22, textColor=WHITE,
fontName="Helvetica-Bold", alignment=TA_CENTER, spaceAfter=6)
H2 = S("H2", fontSize=13, leading=18, textColor=BLUE_DARK,
fontName="Helvetica-Bold", spaceBefore=10, spaceAfter=4)
H3 = S("H3", fontSize=11, leading=15, textColor=TEAL,
fontName="Helvetica-Bold", spaceBefore=6, spaceAfter=3)
BODY = S("Body", fontSize=9, leading=13, textColor=BLACK,
fontName="Helvetica", spaceAfter=4, alignment=TA_JUSTIFY)
BULLET = S("Bullet", fontSize=9, leading=13, textColor=BLACK,
fontName="Helvetica", leftIndent=14, firstLineIndent=-10,
spaceAfter=3)
EQUATION = S("Equation", fontSize=10, leading=16, textColor=BLUE_DARK,
fontName="Helvetica-Bold", alignment=TA_CENTER,
spaceBefore=4, spaceAfter=4,
backColor=BLUE_LIGHT, borderPad=6)
KEY_BOX = S("KeyBox", fontSize=9, leading=13, textColor=GREEN_DARK,
fontName="Helvetica-Bold", alignment=TA_CENTER,
backColor=GREEN_LIGHT, borderPad=5)
NOTE = S("Note", fontSize=8, leading=12, textColor=ORANGE_DARK,
fontName="Helvetica-Oblique", spaceAfter=3)
# ── Helper: Section header banner ─────────────────────────────────────────────
class ColorBanner(Flowable):
def __init__(self, text, bg=BLUE_DARK, fg=WHITE, height=28, fontsize=13):
super().__init__()
self.text = text
self.bg = bg
self.fg = fg
self.height = height
self.fontsize = fontsize
self.width = 0 # set by wrap
def wrap(self, availW, availH):
self.width = availW
return (availW, self.height)
def draw(self):
c = self.canv
c.setFillColor(self.bg)
c.roundRect(0, 0, self.width, self.height, 5, stroke=0, fill=1)
c.setFillColor(self.fg)
c.setFont("Helvetica-Bold", self.fontsize)
c.drawCentredString(self.width / 2, (self.height - self.fontsize) / 2 + 2, self.text)
# ── Helper: Diagram flowable base ─────────────────────────────────────────────
class DiagramFlowable(Flowable):
def __init__(self, width, height, draw_fn):
super().__init__()
self._w = width
self._h = height
self._draw_fn = draw_fn
def wrap(self, availW, availH):
return (self._w, self._h)
def draw(self):
self._draw_fn(self.canv, self._w, self._h)
# ─────────────────────────────────────────────────────────────────────────────
# DIAGRAM FUNCTIONS
# ─────────────────────────────────────────────────────────────────────────────
def draw_secondary_active_transport(c, W, H):
"""Diagram: Secondary active transport - cotransport and countertransport."""
# Background
c.setFillColor(BLUE_LIGHT)
c.roundRect(0, 0, W, H, 8, stroke=0, fill=1)
mid = W / 2
# Cell membrane bar
memb_y = H / 2
c.setFillColor(colors.HexColor("#7B9ABF"))
c.rect(20, memb_y - 8, W - 40, 16, stroke=0, fill=1)
c.setFillColor(BLACK)
c.setFont("Helvetica-Bold", 7)
c.drawCentredString(mid, memb_y + 20, "CELL MEMBRANE")
c.drawCentredString(mid * 0.5, memb_y + 28, "ECF (High Na+)")
c.drawCentredString(mid * 0.5, memb_y - 28, "ICF (Low Na+)")
# === LEFT SIDE: Cotransport (Symport) ===
cx = mid * 0.48
# Carrier box
c.setFillColor(TEAL)
c.roundRect(cx - 22, memb_y - 18, 44, 36, 4, stroke=0, fill=1)
c.setFillColor(WHITE)
c.setFont("Helvetica-Bold", 7)
c.drawCentredString(cx, memb_y + 2, "SGLT1")
c.drawCentredString(cx, memb_y - 8, "Cotransport")
# Arrows pointing DOWN (into cell) for both Na+ and Glucose
c.setStrokeColor(BLUE_DARK)
c.setLineWidth(1.8)
c.line(cx - 10, memb_y + 38, cx - 10, memb_y + 22)
_arrowhead(c, cx - 10, memb_y + 22, "down", BLUE_DARK)
c.setFillColor(BLUE_DARK)
c.setFont("Helvetica-Bold", 8)
c.drawString(cx - 26, memb_y + 42, "Na+")
c.setStrokeColor(GREEN_DARK)
c.line(cx + 10, memb_y + 38, cx + 10, memb_y + 22)
_arrowhead(c, cx + 10, memb_y + 22, "down", GREEN_DARK)
c.setFillColor(GREEN_DARK)
c.drawString(cx + 12, memb_y + 42, "Gluc")
# Both exit arrow downward from carrier
c.setStrokeColor(BLUE_DARK)
c.line(cx - 10, memb_y - 18, cx - 10, memb_y - 36)
_arrowhead(c, cx - 10, memb_y - 36, "down", BLUE_DARK)
c.setStrokeColor(GREEN_DARK)
c.line(cx + 10, memb_y - 18, cx + 10, memb_y - 36)
_arrowhead(c, cx + 10, memb_y - 36, "down", GREEN_DARK)
# Label
c.setFillColor(TEAL)
c.setFont("Helvetica-Bold", 8)
c.drawCentredString(cx, 14, "SYMPORT (same direction)")
# === RIGHT SIDE: Countertransport (Antiport) ===
cx2 = mid + mid * 0.52
c.setFillColor(ORANGE_DARK)
c.roundRect(cx2 - 22, memb_y - 18, 44, 36, 4, stroke=0, fill=1)
c.setFillColor(WHITE)
c.setFont("Helvetica-Bold", 7)
c.drawCentredString(cx2, memb_y + 2, "NHE1")
c.drawCentredString(cx2, memb_y - 8, "Antiport")
# Na+ moves DOWN (in), H+ moves UP (out)
c.setStrokeColor(BLUE_DARK)
c.line(cx2 - 10, memb_y + 38, cx2 - 10, memb_y + 22)
_arrowhead(c, cx2 - 10, memb_y + 22, "down", BLUE_DARK)
c.setFillColor(BLUE_DARK)
c.setFont("Helvetica-Bold", 8)
c.drawString(cx2 - 26, memb_y + 42, "Na+")
c.setStrokeColor(RED_DARK)
c.line(cx2 + 10, memb_y - 18, cx2 + 10, memb_y - 36)
_arrowhead(c, cx2 + 10, memb_y - 36, "up", RED_DARK)
c.setFillColor(RED_DARK)
c.drawString(cx2 + 12, memb_y - 40, "H+")
c.line(cx2 - 10, memb_y - 18, cx2 - 10, memb_y - 36)
_arrowhead(c, cx2 - 10, memb_y - 36, "down", BLUE_DARK)
c.setStrokeColor(RED_DARK)
c.line(cx2 + 10, memb_y + 38, cx2 + 10, memb_y + 22)
_arrowhead(c, cx2 + 10, memb_y + 22, "up", RED_DARK)
c.setFillColor(RED_DARK)
c.drawString(cx2 + 12, memb_y + 42, "H+")
c.setFillColor(ORANGE_DARK)
c.setFont("Helvetica-Bold", 8)
c.drawCentredString(cx2, 14, "ANTIPORT (opposite directions)")
# Divider
c.setStrokeColor(GRAY_MID)
c.setLineWidth(1)
c.line(mid, 10, mid, H - 10)
def _arrowhead(c, x, y, direction, color):
c.setFillColor(color)
size = 5
if direction == "down":
path = c.beginPath()
path.moveTo(x, y)
path.lineTo(x - size, y + size * 1.6)
path.lineTo(x + size, y + size * 1.6)
path.close()
c.drawPath(path, fill=1, stroke=0)
elif direction == "up":
path = c.beginPath()
path.moveTo(x, y)
path.lineTo(x - size, y - size * 1.6)
path.lineTo(x + size, y - size * 1.6)
path.close()
c.drawPath(path, fill=1, stroke=0)
elif direction == "right":
path = c.beginPath()
path.moveTo(x, y)
path.lineTo(x - size * 1.6, y + size)
path.lineTo(x - size * 1.6, y - size)
path.close()
c.drawPath(path, fill=1, stroke=0)
elif direction == "left":
path = c.beginPath()
path.moveTo(x, y)
path.lineTo(x + size * 1.6, y + size)
path.lineTo(x + size * 1.6, y - size)
path.close()
c.drawPath(path, fill=1, stroke=0)
def draw_rmp_diagram(c, W, H):
"""Ionic basis of RMP - bar chart of equilibrium potentials."""
c.setFillColor(YELLOW)
c.roundRect(0, 0, W, H, 8, stroke=0, fill=1)
# Title
c.setFillColor(BLUE_DARK)
c.setFont("Helvetica-Bold", 9)
c.drawCentredString(W / 2, H - 14, "IONIC BASIS OF RESTING MEMBRANE POTENTIAL")
# Axes
origin_x = 60
origin_y = 35
axis_w = W - origin_x - 20
axis_h = H - 60
# Zero line (0 mV)
zero_y = origin_y + axis_h * 0.62 # ~60% up for 0 mV (range -100 to +140)
range_mv = 240 # from -100 to +140
scale = axis_h / range_mv
def mv_to_y(mv):
return origin_y + (mv + 100) * scale
# Draw y-axis
c.setStrokeColor(BLACK)
c.setLineWidth(1.2)
c.line(origin_x, origin_y, origin_x, origin_y + axis_h)
# Y gridlines and labels
c.setFont("Helvetica", 7)
c.setFillColor(BLACK)
for mv in [-100, -70, -50, 0, +50, +100, +132]:
y = mv_to_y(mv)
c.setStrokeColor(GRAY_MID)
c.setLineWidth(0.5)
c.line(origin_x, y, origin_x + axis_w, y)
c.setFillColor(BLACK)
c.drawRightString(origin_x - 3, y - 3, f"{mv:+d}")
# Zero mV label
c.setFillColor(RED_DARK)
c.setFont("Helvetica-Bold", 7)
c.drawRightString(origin_x - 3, mv_to_y(0) - 3, " 0")
# Bars
bar_data = [
("K+", -94, BLUE_MID, "HIGH perm."),
("Na+", +66, RED_DARK, "LOW perm."),
("Cl-", -90, TEAL, "HIGH perm."),
("Ca2+", +132, ORANGE_DARK, "LOW perm."),
]
bar_w = axis_w / (len(bar_data) * 2.2)
spacing = axis_w / len(bar_data)
for i, (ion, eq_pot, col, perm) in enumerate(bar_data):
bx = origin_x + i * spacing + spacing * 0.2
by_zero = mv_to_y(0)
by_eq = mv_to_y(eq_pot)
bh = by_eq - by_zero
c.setFillColor(col)
c.setStrokeColor(col)
if bh >= 0:
c.rect(bx, by_zero, bar_w, bh, stroke=0, fill=1)
else:
c.rect(bx, by_zero + bh, bar_w, -bh, stroke=0, fill=1)
# Ion label
c.setFillColor(col)
c.setFont("Helvetica-Bold", 8)
c.drawCentredString(bx + bar_w / 2, origin_y - 18, ion)
c.setFont("Helvetica", 6)
c.setFillColor(BLACK)
c.drawCentredString(bx + bar_w / 2, origin_y - 28, perm)
# Value label on bar
c.setFillColor(WHITE)
c.setFont("Helvetica-Bold", 7)
label_y = by_eq + (5 if eq_pot < 0 else -12)
c.drawCentredString(bx + bar_w / 2, label_y, f"{eq_pot:+d}mV")
# RMP line
rmp_y = mv_to_y(-75)
c.setStrokeColor(BLUE_DARK)
c.setLineWidth(2)
c.setDash([4, 3])
c.line(origin_x + 5, rmp_y, origin_x + axis_w, rmp_y)
c.setDash()
c.setFillColor(BLUE_DARK)
c.setFont("Helvetica-Bold", 8)
c.drawString(origin_x + axis_w + 2, rmp_y - 3, "RMP\n-75mV")
# Y-axis label
c.saveState()
c.setFillColor(BLACK)
c.setFont("Helvetica-Bold", 8)
c.translate(12, origin_y + axis_h / 2)
c.rotate(90)
c.drawCentredString(0, 0, "Equilibrium Potential (mV)")
c.restoreState()
def draw_nak_atpase(c, W, H):
"""Na-K-ATPase pump diagram."""
c.setFillColor(PURPLE_LIGHT)
c.roundRect(0, 0, W, H, 8, stroke=0, fill=1)
# Title
c.setFillColor(PURPLE_DARK)
c.setFont("Helvetica-Bold", 10)
c.drawCentredString(W / 2, H - 14, "Na⁺-K⁺-ATPase PUMP")
# Cell membrane
mid_y = H / 2 + 5
c.setFillColor(colors.HexColor("#9E9E9E"))
c.rect(30, mid_y - 10, W - 60, 20, stroke=0, fill=1)
# Labels
c.setFillColor(BLUE_DARK)
c.setFont("Helvetica-Bold", 9)
c.drawString(35, mid_y + 18, "ECF")
c.drawString(35, mid_y - 28, "ICF")
# Pump protein
pump_cx = W / 2
c.setFillColor(PURPLE_DARK)
c.roundRect(pump_cx - 28, mid_y - 28, 56, 56, 8, stroke=0, fill=1)
c.setFillColor(WHITE)
c.setFont("Helvetica-Bold", 8)
c.drawCentredString(pump_cx, mid_y + 10, "α subunit")
c.drawCentredString(pump_cx, mid_y - 2, "Na⁺-K⁺")
c.drawCentredString(pump_cx, mid_y - 14, "ATPase")
# 3 Na+ arrows going OUT (up, ECF side)
for i, dx in enumerate([-18, 0, 18]):
x = pump_cx + dx
c.setStrokeColor(RED_DARK)
c.setLineWidth(1.8)
c.line(x, mid_y + 28, x, mid_y + 52)
_arrowhead(c, x, mid_y + 52, "up", RED_DARK)
c.setFillColor(RED_DARK)
c.setFont("Helvetica-Bold", 9)
c.drawCentredString(pump_cx, mid_y + 60, "3 Na⁺ OUT")
# 2 K+ arrows coming IN (down, from ECF)
for dx in [-10, 10]:
x = pump_cx + dx + 50
c.setStrokeColor(BLUE_MID)
c.setLineWidth(1.8)
c.line(x, mid_y + 52, x, mid_y + 28)
_arrowhead(c, x, mid_y + 28, "down", BLUE_MID)
c.setFillColor(BLUE_MID)
c.setFont("Helvetica-Bold", 9)
c.drawCentredString(pump_cx + 50, mid_y + 60, "2 K⁺ IN")
# ATP → ADP at bottom
c.setFillColor(ORANGE_DARK)
c.setFont("Helvetica-Bold", 9)
c.drawCentredString(pump_cx, mid_y - 42, "ATP → ADP + Pi")
# Ouabain binding label
c.setFillColor(RED_DARK)
c.setFont("Helvetica", 7)
c.drawCentredString(pump_cx, 14, "Inhibited by: Ouabain / Digitalis glycosides")
# Stoichiometry box
c.setFillColor(ORANGE_LIGHT)
c.roundRect(W - 100, H - 55, 90, 40, 4, stroke=1, fill=1)
c.setStrokeColor(ORANGE_DARK)
c.setLineWidth(0.8)
c.roundRect(W - 100, H - 55, 90, 40, 4, stroke=1, fill=0)
c.setFillColor(ORANGE_DARK)
c.setFont("Helvetica-Bold", 8)
c.drawCentredString(W - 55, H - 32, "Coupling Ratio")
c.drawCentredString(W - 55, H - 46, "3 Na⁺ : 2 K⁺ : 1 ATP")
def draw_diffusion_comparison(c, W, H):
"""Simple vs Facilitated Diffusion side-by-side."""
c.setFillColor(GREEN_LIGHT)
c.roundRect(0, 0, W, H, 8, stroke=0, fill=1)
c.setFillColor(GREEN_DARK)
c.setFont("Helvetica-Bold", 9)
c.drawCentredString(W / 2, H - 14, "SIMPLE vs FACILITATED DIFFUSION")
mid = W / 2
# Divider
c.setStrokeColor(GRAY_MID)
c.setLineWidth(1)
c.line(mid, 10, mid, H - 25)
# ── LEFT: Simple Diffusion ──
lx = mid * 0.5
c.setFillColor(BLUE_DARK)
c.setFont("Helvetica-Bold", 9)
c.drawCentredString(lx, H - 30, "SIMPLE DIFFUSION")
# Membrane
memb_y = H * 0.55
c.setFillColor(colors.HexColor("#7B9ABF"))
c.rect(20, memb_y - 5, mid - 30, 10, stroke=0, fill=1)
# Molecules (circles) high side
c.setFillColor(BLUE_MID)
for i, (x, y) in enumerate([(35, memb_y + 25), (55, memb_y + 40), (75, memb_y + 20),
(45, memb_y + 55), (65, memb_y + 50)]):
c.circle(x, y, 7, stroke=0, fill=1)
c.setFont("Helvetica", 7)
c.setFillColor(BLACK)
c.drawCentredString(lx, H - 45, "High [conc] side")
# Molecules (fewer) low side
c.setFillColor(BLUE_LIGHT)
for x, y in [(40, memb_y - 30), (70, memb_y - 25)]:
c.circle(x, y, 7, stroke=0, fill=1)
c.drawCentredString(lx, memb_y - 55, "Low [conc] side")
c.setFillColor(BLACK)
# Net flux arrow
c.setStrokeColor(BLUE_DARK)
c.setLineWidth(2)
c.line(lx, memb_y + 15, lx, memb_y - 15)
_arrowhead(c, lx, memb_y - 15, "down", BLUE_DARK)
c.setFillColor(BLUE_DARK)
c.setFont("Helvetica-Bold", 7)
c.drawCentredString(lx, memb_y - 60, "No carrier needed")
# Features
feats = ["✓ No carrier protein", "✓ Not saturable", "✓ No stereospecificity",
"✓ Linear rate ∝ gradient"]
c.setFont("Helvetica", 7)
c.setFillColor(GREEN_DARK)
for i, f in enumerate(feats):
c.drawString(22, 75 - i * 12, f)
# ── RIGHT: Facilitated Diffusion ──
rx = mid + mid * 0.5
c.setFillColor(TEAL)
c.setFont("Helvetica-Bold", 9)
c.drawCentredString(rx, H - 30, "FACILITATED DIFFUSION")
c.setFillColor(colors.HexColor("#7B9ABF"))
c.rect(mid + 10, memb_y - 5, mid - 30, 10, stroke=0, fill=1)
# Carrier protein in membrane
c.setFillColor(TEAL)
c.roundRect(rx - 15, memb_y - 20, 30, 40, 5, stroke=0, fill=1)
c.setFillColor(WHITE)
c.setFont("Helvetica-Bold", 7)
c.drawCentredString(rx, memb_y + 5, "GLUT4")
c.drawCentredString(rx, memb_y - 7, "Carrier")
# Molecules high side
c.setFillColor(GREEN_DARK)
for i, (x, y) in enumerate([(mid + 25, memb_y + 30), (mid + 45, memb_y + 45),
(mid + 65, memb_y + 25), (mid + 55, memb_y + 55)]):
c.circle(x, y, 7, stroke=0, fill=1)
c.setFillColor(BLACK)
c.setFont("Helvetica", 7)
c.drawCentredString(rx, H - 45, "High [conc] side (D-glucose)")
# Arrow through carrier
c.setStrokeColor(TEAL)
c.setLineWidth(2)
c.line(rx, memb_y + 18, rx, memb_y - 18)
_arrowhead(c, rx, memb_y - 18, "down", TEAL)
c.setFillColor(GREEN_DARK)
c.setFont("Helvetica-BoldOblique", 7)
c.drawCentredString(rx, memb_y - 55, "Requires specific carrier")
feats2 = ["✓ Carrier protein (GLUT4)", "✓ Saturable (Vmax)", "✓ Stereospecific",
"✓ Competition between solutes"]
c.setFont("Helvetica", 7)
c.setFillColor(TEAL)
for i, f in enumerate(feats2):
c.drawString(mid + 18, 75 - i * 12, f)
def draw_apoptosis_pathway(c, W, H):
"""Apoptosis pathways diagram."""
c.setFillColor(RED_LIGHT)
c.roundRect(0, 0, W, H, 8, stroke=0, fill=1)
c.setFillColor(RED_DARK)
c.setFont("Helvetica-Bold", 10)
c.drawCentredString(W / 2, H - 14, "APOPTOSIS PATHWAYS")
mid = W / 2
def box(cx, y, w, h, label, sublabel, bg, fg=WHITE, fontsize=8):
c.setFillColor(bg)
c.roundRect(cx - w/2, y - h/2, w, h, 5, stroke=0, fill=1)
c.setFillColor(fg)
c.setFont("Helvetica-Bold", fontsize)
c.drawCentredString(cx, y + h/4 - 2, label)
if sublabel:
c.setFont("Helvetica", fontsize - 1)
c.drawCentredString(cx, y - h/4, sublabel)
def arrow_down(cx, y_top, y_bot, col=BLACK):
c.setStrokeColor(col)
c.setLineWidth(1.5)
c.line(cx, y_top, cx, y_bot + 8)
_arrowhead(c, cx, y_bot + 8, "down", col)
def arrow_right(x_l, x_r, y, col=BLACK):
c.setStrokeColor(col)
c.setLineWidth(1.5)
c.line(x_l, y, x_r - 8, y)
_arrowhead(c, x_r - 8, y, "right", col)
# Intrinsic pathway (left column)
lx = mid * 0.38
# Trigger
box(lx, H - 38, 100, 22, "DNA Damage /", "Oxidative Stress", BLUE_DARK)
arrow_down(lx, H - 49, H - 65, BLUE_DARK)
box(lx, H - 78, 100, 22, "Proapoptotic", "BAX, BAK, BIM↑", RED_DARK)
arrow_down(lx, H - 89, H - 105, RED_DARK)
box(lx, H - 118, 100, 22, "Mitochondria", "Cytochrome c release", ORANGE_DARK)
arrow_down(lx, H - 129, H - 145, ORANGE_DARK)
box(lx, H - 158, 100, 22, "Apoptosome", "Cyt c + Apaf-1", PURPLE_DARK)
arrow_down(lx, H - 169, H - 185, PURPLE_DARK)
box(lx, H - 198, 100, 22, "Caspase-9", "(Initiator)", PURPLE_DARK)
c.setFillColor(BLUE_DARK)
c.setFont("Helvetica-Bold", 8)
c.drawCentredString(lx, H - 25, "INTRINSIC PATHWAY")
# Extrinsic pathway (right column)
rx = mid + mid * 0.62
box(rx, H - 38, 100, 22, "Death Receptor", "Fas / TNFR", BLUE_DARK)
arrow_down(rx, H - 49, H - 65, BLUE_DARK)
box(rx, H - 78, 100, 22, "FasL binding", "DISC formation", RED_DARK)
arrow_down(rx, H - 89, H - 145, RED_DARK)
box(rx, H - 158, 100, 22, "Caspase-8", "(Initiator)", TEAL)
c.setFillColor(RED_DARK)
c.setFont("Helvetica-Bold", 8)
c.drawCentredString(rx, H - 25, "EXTRINSIC PATHWAY")
# Both converge → Caspase 3/6/7
exec_y = H - 235
# Arrows from caspase 9 and 8 converging
arrow_down(lx, H - 209, exec_y + 12, PURPLE_DARK)
arrow_down(rx, H - 169, exec_y + 12, TEAL)
# Lines from both columns to center
conv_y = exec_y + 16
c.setStrokeColor(GRAY_MID)
c.setLineWidth(1)
c.line(lx, conv_y, mid, conv_y)
c.line(rx, conv_y, mid, conv_y)
c.line(mid, conv_y, mid, exec_y + 12)
box(mid, exec_y, 130, 24, "EXECUTIONER CASPASES", "3, 6, 7", RED_DARK, WHITE, 9)
arrow_down(mid, exec_y - 12, exec_y - 35, RED_DARK)
box(mid, exec_y - 48, 140, 22, "CELL DISMANTLING", "Protein degradation → Apoptotic bodies", colors.HexColor("#880E4F"), WHITE, 7)
# Features box
c.setFillColor(YELLOW)
c.roundRect(4, 4, W - 8, 36, 4, stroke=0, fill=1)
c.setFillColor(BLUE_DARK)
c.setFont("Helvetica-Bold", 7)
c.drawString(10, 30, "Key features: Caspase-dependent | Cell membrane INTACT | No inflammation | Apoptotic bodies phagocytosed")
def draw_cell_junctions(c, W, H):
"""Cell junctions diagram."""
c.setFillColor(TEAL_LIGHT)
c.roundRect(0, 0, W, H, 8, stroke=0, fill=1)
c.setFillColor(TEAL)
c.setFont("Helvetica-Bold", 10)
c.drawCentredString(W / 2, H - 14, "TYPES OF CELL JUNCTIONS")
# Two cell columns
cell_w = 50
gap = 20
lx = W / 2 - gap / 2 - cell_w
rx = W / 2 + gap / 2
cell_h = H - 70
c.setFillColor(colors.HexColor("#BBDEFB"))
c.rect(lx, 30, cell_w, cell_h, stroke=1, fill=1)
c.setFillColor(colors.HexColor("#C8E6C9"))
c.rect(rx, 30, cell_w, cell_h, stroke=1, fill=1)
c.setFillColor(BLACK)
c.setFont("Helvetica-Bold", 7)
c.drawCentredString(lx + cell_w / 2, 22, "Cell A")
c.drawCentredString(rx + cell_w / 2, 22, "Cell B")
# Junction data: (y_fraction, name, color, description)
junctions = [
(0.85, "Tight Jn\n(Zonula Occludens)", BLUE_DARK, "Occludin, Claudins\nSeals paracellular space"),
(0.70, "Adherens Jn\n(Zonula Adherens)", GREEN_DARK, "Cadherins + Actin\nMechanical link"),
(0.55, "Desmosome\n(Macula Adherens)", ORANGE_DARK, "Cadherins + Intermediate\nfilaments - resists shear"),
(0.38, "Gap Junction\n(Nexus)", PURPLE_DARK, "Connexins (<1000 Da)\nElectric coupling"),
(0.22, "Hemidesmosome", TEAL, "Integrins\nAnchor to basal lamina"),
]
for frac, name, col, desc in junctions:
jy = 30 + cell_h * frac
# Junction block between cells
c.setFillColor(col)
c.rect(lx + cell_w - 5, jy - 8, gap + 10, 16, stroke=0, fill=1)
# Labels on left
c.setFillColor(col)
c.setFont("Helvetica-Bold", 7)
lines = name.split("\n")
for k, line in enumerate(lines):
c.drawRightString(lx - 5, jy + 5 - k * 10, line)
# Description on right
c.setFillColor(BLACK)
c.setFont("Helvetica", 6)
desc_lines = desc.split("\n")
for k, dl in enumerate(desc_lines):
c.drawString(rx + cell_w + 5, jy + 4 - k * 9, dl)
# ─────────────────────────────────────────────────────────────────────────────
# BUILD DOCUMENT
# ─────────────────────────────────────────────────────────────────────────────
def build():
doc = SimpleDocTemplate(
OUTPUT, pagesize=A4,
leftMargin=1.8*cm, rightMargin=1.8*cm,
topMargin=1.5*cm, bottomMargin=1.5*cm
)
W = A4[0] - 3.6*cm # usable width
story = []
# ── COVER PAGE ─────────────────────────────────────────────────────────────
class CoverBg(Flowable):
def wrap(self, aw, ah): return (aw, 280)
def draw(self):
c = self.canv
cw, _ = self.wrap(0, 0)
# gradient-ish block
c.setFillColor(BLUE_DARK)
c.roundRect(0, 0, cw, 280, 10, stroke=0, fill=1)
c.setFillColor(BLUE_MID)
c.roundRect(0, 0, cw, 200, 10, stroke=0, fill=1)
c.setFillColor(BLUE_DARK)
c.roundRect(0, 0, cw, 60, 0, stroke=0, fill=1)
c.setFillColor(WHITE)
c.setFont("Helvetica-Bold", 26)
c.drawCentredString(cw / 2, 200, "GENERAL PHYSIOLOGY")
c.setFont("Helvetica-Bold", 16)
c.drawCentredString(cw / 2, 168, "Summary with Diagrams & Key Equations")
c.setFillColor(BLUE_LIGHT)
c.setFont("Helvetica", 11)
c.drawCentredString(cw / 2, 140, "SRM Medical College — Must Know Revision")
c.drawCentredString(cw / 2, 122, "Topics: Secondary Active Transport | RMP | Cell Junctions")
c.drawCentredString(cw / 2, 106, "Na⁺-K⁺-ATPase | Simple Diffusion | Facilitated Diffusion | Apoptosis")
c.setFillColor(YELLOW)
c.setFont("Helvetica-BoldOblique", 9)
c.drawCentredString(cw / 2, 72, "Based on: Costanzo Physiology 7e | Ganong's Review 26e | Guyton & Hall")
# decorative line
c.setStrokeColor(YELLOW)
c.setLineWidth(2)
c.line(cw * 0.15, 88, cw * 0.85, 88)
story.append(CoverBg())
story.append(Spacer(1, 0.5*cm))
# Table of contents box
toc_data = [
["#", "Topic", "Type"],
["1", "Secondary Active Transport", "Essay"],
["2", "Resting Membrane Potential (RMP)", "Essay"],
["3", "Structure & Functions of Cell Junctions", "Essay"],
["4", "Na⁺-K⁺-ATPase System", "Essay"],
["5", "Simple Diffusion", "Essay"],
["6", "Facilitated Diffusion", "Essay"],
["7", "Apoptosis", "Essay"],
]
toc_style = TableStyle([
("BACKGROUND", (0,0), (-1,0), BLUE_DARK),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,0), 10),
("BACKGROUND", (0,1), (-1,-1), BLUE_LIGHT),
("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, BLUE_LIGHT]),
("FONTNAME", (0,1), (-1,-1), "Helvetica"),
("FONTSIZE", (0,1), (-1,-1), 9),
("ALIGN", (0,0), (-1,-1), "CENTER"),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("GRID", (0,0), (-1,-1), 0.5, GRAY_MID),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING",(0,0), (-1,-1), 5),
("ROUNDEDCORNERS", (0,0), (-1,-1), [4, 4, 4, 4]),
])
toc_table = Table(toc_data, colWidths=[W*0.08, W*0.65, W*0.2])
toc_table.setStyle(toc_style)
story.append(toc_table)
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════════════
# 1. SECONDARY ACTIVE TRANSPORT
# ═══════════════════════════════════════════════════════════════════════════
story.append(ColorBanner("1. SECONDARY ACTIVE TRANSPORT", bg=TEAL))
story.append(Spacer(1, 4))
story.append(Paragraph(
"<b>Definition:</b> Transport of two or more solutes where one solute (Na⁺) moves "
"<i>down</i> its electrochemical gradient, providing energy for the other solute to move "
"<i>against</i> its gradient. ATP is <b>not used directly</b> - energy comes indirectly from the Na⁺ gradient maintained by Na⁺-K⁺-ATPase.",
BODY))
# Key equation box
story.append(Paragraph("Energy Source: Na⁺ gradient (maintained by Na⁺-K⁺-ATPase using ATP)", EQUATION))
story.append(Spacer(1, 4))
story.append(Paragraph("<b>Two Types:</b>", H3))
type_data = [
["Type", "Synonym", "Solute Direction", "Classic Example"],
["Cotransport", "Symport", "Both in SAME direction", "Na⁺-Glucose (SGLT1)\nNa⁺-Amino Acid"],
["Countertransport", "Antiport", "OPPOSITE directions", "Na⁺-H⁺ exchanger (NHE)\nNa⁺-Ca²⁺ exchanger"],
]
ts = TableStyle([
("BACKGROUND", (0,0),(-1,0), TEAL),
("TEXTCOLOR", (0,0),(-1,0), WHITE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0),(-1,-1), 8),
("ROWBACKGROUNDS",(0,1),(-1,-1),[TEAL_LIGHT, WHITE]),
("GRID", (0,0),(-1,-1), 0.5, GRAY_MID),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
("ALIGN", (0,0),(-1,-1), "CENTER"),
("TOPPADDING", (0,0),(-1,-1), 5),
("BOTTOMPADDING",(0,0),(-1,-1), 5),
])
t = Table(type_data, colWidths=[W*0.22, W*0.18, W*0.3, W*0.28])
t.setStyle(ts)
story.append(t)
story.append(Spacer(1, 6))
# Diagram
story.append(DiagramFlowable(W, 155, draw_secondary_active_transport))
story.append(Spacer(1, 6))
story.append(Paragraph(
"<b>Effect of Ouabain (Na⁺-K⁺-ATPase inhibitor):</b> "
"Intracellular Na⁺ rises → Na⁺ gradient decreases → ALL secondary active transport is impaired indirectly.",
NOTE))
story.append(Paragraph("<b>Key Examples:</b>", H3))
examples = [
("SGLT1", "Na⁺-Glucose cotransport", "Luminal membrane — small intestine & proximal renal tubule"),
("NKCC2", "Na⁺-K⁺-2Cl⁻ cotransport", "Thick ascending limb of loop of Henle"),
("NHE1", "Na⁺-H⁺ exchanger", "Proximal tubule — Na⁺ in, H⁺ out"),
("NCX", "Na⁺-Ca²⁺ exchanger", "Cardiac & smooth muscle — Ca²⁺ homeostasis"),
]
ex_data = [["Transporter", "Process", "Location"]] + [[e[0], e[1], e[2]] for e in examples]
ex_t = Table(ex_data, colWidths=[W*0.12, W*0.38, W*0.48])
ex_t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), TEAL),
("TEXTCOLOR", (0,0),(-1,0), WHITE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0),(-1,-1), 8),
("ROWBACKGROUNDS",(0,1),(-1,-1),[TEAL_LIGHT, WHITE]),
("GRID", (0,0),(-1,-1), 0.5, GRAY_MID),
("TOPPADDING", (0,0),(-1,-1), 4),
("BOTTOMPADDING",(0,0),(-1,-1), 4),
]))
story.append(ex_t)
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════════════
# 2. RESTING MEMBRANE POTENTIAL
# ═══════════════════════════════════════════════════════════════════════════
story.append(ColorBanner("2. RESTING MEMBRANE POTENTIAL (RMP)", bg=BLUE_DARK))
story.append(Spacer(1, 4))
story.append(Paragraph(
"<b>Definition:</b> The electrical potential difference across the membrane of excitable cells "
"(nerve, muscle) at rest. Expressed as intracellular potential relative to extracellular potential.",
BODY))
story.append(Paragraph("RMP = −70 to −80 mV (intracellular negative)", EQUATION))
story.append(Paragraph("<b>Ionic Concentrations & Equilibrium Potentials (Nernst Equation):</b>", H3))
ion_data = [
["Ion", "Intracellular", "Extracellular", "Equilibrium Pot.", "Resting Perm.", "Contribution"],
["K⁺", "140 mEq/L", "4 mEq/L", "−94 mV", "HIGH ✓", "MAJOR"],
["Na⁺", "14 mEq/L", "140 mEq/L", "+66 mV", "LOW", "Minor"],
["Cl⁻", "4 mEq/L", "114 mEq/L", "−90 mV", "Moderate ✓", "Moderate"],
["Ca²⁺", "0.0001", "2.5 mEq/L", "+132 mV", "Very LOW", "Negligible"],
]
ion_ts = TableStyle([
("BACKGROUND", (0,0),(-1,0), BLUE_DARK),
("TEXTCOLOR", (0,0),(-1,0), WHITE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0),(-1,-1), 8),
("ROWBACKGROUNDS",(0,1),(-1,-1),[BLUE_LIGHT, WHITE]),
("BACKGROUND", (0,1),(-1,1), colors.HexColor("#BBDEFB")),
("BACKGROUND", (0,3),(-1,3), colors.HexColor("#E0F7FA")),
("GRID", (0,0),(-1,-1), 0.5, GRAY_MID),
("ALIGN", (0,0),(-1,-1), "CENTER"),
("TOPPADDING", (0,0),(-1,-1), 4),
("BOTTOMPADDING",(0,0),(-1,-1), 4),
])
ion_t = Table(ion_data, colWidths=[W*0.08, W*0.18, W*0.18, W*0.17, W*0.18, W*0.18])
ion_t.setStyle(ion_ts)
story.append(ion_t)
story.append(Spacer(1, 6))
story.append(Paragraph("<b>Key Equations:</b>", H3))
story.append(Paragraph(
"Nernst Equation: E_ion = (RT/zF) × ln([ion]_out / [ion]_in) = 61/z × log([ion]_out / [ion]_in)",
EQUATION))
story.append(Paragraph(
"Chord Conductance: Em = (gK/gT)·EK + (gNa/gT)·ENa + (gCl/gT)·ECl + (gCa/gT)·ECa",
EQUATION))
story.append(DiagramFlowable(W, 200, draw_rmp_diagram))
story.append(Spacer(1, 4))
story.append(Paragraph("<b>Role of Na⁺-K⁺-ATPase in RMP:</b>", H3))
role_data = [
["Contribution", "Mechanism", "Importance"],
["Direct (electrogenic)", "Pumps 3 Na⁺ out : 2 K⁺ in → net negative charge inside", "Small"],
["Indirect (major)", "Maintains K⁺ gradient → K⁺ diffusion potential → RMP", "LARGE"],
]
role_t = Table(role_data, colWidths=[W*0.28, W*0.48, W*0.2])
role_t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), BLUE_DARK),
("TEXTCOLOR", (0,0),(-1,0), WHITE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0),(-1,-1), 8),
("ROWBACKGROUNDS",(0,1),(-1,-1),[BLUE_LIGHT, WHITE]),
("GRID", (0,0),(-1,-1), 0.5, GRAY_MID),
("TOPPADDING", (0,0),(-1,-1), 4),
("BOTTOMPADDING",(0,0),(-1,-1), 4),
]))
story.append(role_t)
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════════════
# 3. CELL JUNCTIONS
# ═══════════════════════════════════════════════════════════════════════════
story.append(ColorBanner("3. STRUCTURE & FUNCTIONS OF CELL JUNCTIONS", bg=TEAL))
story.append(Spacer(1, 4))
story.append(Paragraph(
"Cell junctions are specialised membrane structures that <b>mechanically link cells</b>, "
"<b>regulate paracellular permeability</b>, and enable <b>direct cell-to-cell communication</b>.",
BODY))
story.append(Spacer(1, 4))
jn_data = [
["Junction", "Also Called", "Proteins", "Location", "Function"],
["Tight Junction", "Zonula Occludens", "Occludin, Claudins, JAMs", "Apical epithelium", "Seals paracellular space; cell polarity"],
["Adherens Junction", "Zonula Adherens", "Cadherins + Actin", "Just basal to TJ", "Mechanical link; morphogenesis"],
["Desmosome", "Macula Adherens", "Cadherins + Intermediate filaments","Skin, cardiac muscle", "Resists shearing forces"],
["Hemidesmosome", "—", "Integrins + Intermediate filaments","Basal epithelium", "Anchors cell to basal lamina"],
["Focal Adhesion", "—", "Integrins + Actin", "Basal surface", "ECM attachment; cell signaling"],
["Gap Junction", "Nexus", "Connexins (connexons)", "Heart, smooth muscle, glia", "Ion/molecule transfer <1000 Da; electrical coupling"],
]
jn_ts = TableStyle([
("BACKGROUND", (0,0),(-1,0), TEAL),
("TEXTCOLOR", (0,0),(-1,0), WHITE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0),(-1,-1), 7.5),
("ROWBACKGROUNDS",(0,1),(-1,-1),[TEAL_LIGHT, WHITE]),
("GRID", (0,0),(-1,-1), 0.5, GRAY_MID),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
("TOPPADDING", (0,0),(-1,-1), 4),
("BOTTOMPADDING",(0,0),(-1,-1), 4),
])
jn_t = Table(jn_data, colWidths=[W*0.16, W*0.16, W*0.22, W*0.2, W*0.26])
jn_t.setStyle(jn_ts)
story.append(jn_t)
story.append(Spacer(1, 6))
story.append(DiagramFlowable(W, 210, draw_cell_junctions))
story.append(Spacer(1, 4))
story.append(Paragraph(
"<b>Note:</b> Desmosomes and hemidesmosomes use <b>intermediate filaments</b>; "
"adherens junctions and focal adhesions use <b>actin filaments</b>. "
"Tight junctions are the most apical; the junctional complex (zonula occludens + adherens + desmosome) forms the <i>terminal bar</i>.",
NOTE))
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════════════
# 4. Na+-K+-ATPase
# ═══════════════════════════════════════════════════════════════════════════
story.append(ColorBanner("4. Na⁺-K⁺-ATPase SYSTEM", bg=PURPLE_DARK))
story.append(Spacer(1, 4))
story.append(Paragraph(
"The Na⁺-K⁺-ATPase is a <b>primary active transport</b> pump present in ALL cell membranes. "
"It directly uses ATP to transport ions against their electrochemical gradients.",
BODY))
story.append(Paragraph("3 Na⁺ OUT : 2 K⁺ IN : 1 ATP hydrolysed → Coupling ratio 3:2", EQUATION))
story.append(Paragraph("<b>Structural Components:</b>", H3))
struct_data = [
["Subunit", "MW", "Membrane Spans", "Key Binding Sites"],
["α subunit", "~100,000 Da", "~10 transmembrane domains",
"Intracellular: Na⁺ site, ATP site, phosphorylation site\nExtracellular: K⁺ site, ouabain site"],
["β subunit (glycoprotein)", "~55,000 Da", "1 transmembrane domain",
"3 extracellular glycosylation sites (1/3 of MW is carbohydrate)\nRequired for activity — separation destroys function"],
]
struct_ts = TableStyle([
("BACKGROUND", (0,0),(-1,0), PURPLE_DARK),
("TEXTCOLOR", (0,0),(-1,0), WHITE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0),(-1,-1), 8),
("ROWBACKGROUNDS",(0,1),(-1,-1),[PURPLE_LIGHT, WHITE]),
("GRID", (0,0),(-1,-1), 0.5, GRAY_MID),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
("TOPPADDING", (0,0),(-1,-1), 5),
("BOTTOMPADDING",(0,0),(-1,-1), 5),
])
struct_t = Table(struct_data, colWidths=[W*0.22, W*0.15, W*0.25, W*0.38])
struct_t.setStyle(struct_ts)
story.append(struct_t)
story.append(Spacer(1, 6))
story.append(DiagramFlowable(W, 180, draw_nak_atpase))
story.append(Spacer(1, 6))
story.append(Paragraph("<b>Functions of Na⁺-K⁺-ATPase:</b>", H3))
funcs = [
"Maintains low intracellular Na⁺ and high intracellular K⁺.",
"Creates the Na⁺ gradient used for ALL secondary active transport (glucose, amino acids, H⁺).",
"Contributes to RMP: electrogenic effect (direct) + maintains K⁺ gradient (indirect, major).",
"Regulates cell volume — controls intracellular osmolarity.",
"Maintains excitability of nerve and muscle cells.",
]
for f in funcs:
story.append(Paragraph(f"• {f}", BULLET))
story.append(Paragraph(
"<b>Inhibitors:</b> Ouabain and digitalis glycosides (digoxin) bind the extracellular α subunit site → "
"↑ intracellular Na⁺ → ↑ intracellular Ca²⁺ (via NCX) → ↑ cardiac contractility. "
"Used clinically in heart failure.",
NOTE))
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════════════
# 5. SIMPLE DIFFUSION
# ═══════════════════════════════════════════════════════════════════════════
story.append(ColorBanner("5. SIMPLE DIFFUSION", bg=GREEN_DARK))
story.append(Spacer(1, 4))
story.append(Paragraph(
"Simple diffusion is the <b>passive movement</b> of a solute across a membrane from high to low "
"concentration, driven by the concentration (or electrochemical) gradient. "
"<b>No carrier protein or ATP is required.</b>",
BODY))
story.append(Paragraph("Fick's Law: J = P × A × (C_A − C_B)", EQUATION))
story.append(Spacer(1, 2))
story.append(Paragraph("Diffusion Coefficient (Stokes-Einstein): D = kT / (6πηr)", EQUATION))
story.append(Spacer(1, 2))
story.append(Paragraph("Permeability: P = K × D / Δx (K = partition coefficient, Δx = membrane thickness)", EQUATION))
story.append(Spacer(1, 4))
story.append(Paragraph("<b>Factors Affecting Rate of Simple Diffusion:</b>", H3))
factor_data = [
["Factor", "Symbol", "Relationship", "Reason"],
["Concentration gradient", "C_A − C_B", "↑ gradient → ↑ diffusion", "Driving force"],
["Partition coefficient", "K", "↑ K → ↑ diffusion", "Lipid solubility → membrane penetration"],
["Diffusion coefficient", "D", "↑ D → ↑ diffusion", "Smaller molecule, lower viscosity"],
["Membrane thickness", "Δx", "↑ Δx → ↓ diffusion", "Greater distance to traverse"],
["Surface area", "A", "↑ A → ↑ diffusion", "More membrane available"],
]
fd_ts = TableStyle([
("BACKGROUND", (0,0),(-1,0), GREEN_DARK),
("TEXTCOLOR", (0,0),(-1,0), WHITE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0),(-1,-1), 8),
("ROWBACKGROUNDS",(0,1),(-1,-1),[GREEN_LIGHT, WHITE]),
("GRID", (0,0),(-1,-1), 0.5, GRAY_MID),
("ALIGN", (0,0),(-1,-1), "CENTER"),
("TOPPADDING", (0,0),(-1,-1), 4),
("BOTTOMPADDING",(0,0),(-1,-1), 4),
])
fd_t = Table(factor_data, colWidths=[W*0.25, W*0.12, W*0.28, W*0.32])
fd_t.setStyle(fd_ts)
story.append(fd_t)
story.append(Spacer(1, 6))
story.append(Paragraph("<b>Characteristics vs Carrier-Mediated Transport:</b>", H3))
char_data = [
["Characteristic", "Simple Diffusion", "Carrier-Mediated"],
["Carrier protein", "NOT needed", "Required"],
["Energy (ATP)", "Not required", "Not required (facilitated)\nRequired (active)"],
["Saturation", "No — linear", "Yes — plateaus at Vmax"],
["Stereospecificity", "None", "Yes (D vs L isomers)"],
["Competition", "None", "Yes (structurally similar solutes)"],
["Examples", "O₂, CO₂, urea,\nethanol, steroids", "Glucose (GLUT4),\nNa⁺-Glucose (SGLT1)"],
]
char_ts = TableStyle([
("BACKGROUND", (0,0),(-1,0), GREEN_DARK),
("TEXTCOLOR", (0,0),(-1,0), WHITE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0),(-1,-1), 8),
("ROWBACKGROUNDS",(0,1),(-1,-1),[GREEN_LIGHT, WHITE]),
("GRID", (0,0),(-1,-1), 0.5, GRAY_MID),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
("TOPPADDING", (0,0),(-1,-1), 4),
("BOTTOMPADDING",(0,0),(-1,-1), 4),
])
char_t = Table(char_data, colWidths=[W*0.3, W*0.35, W*0.33])
char_t.setStyle(char_ts)
story.append(char_t)
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════════════
# 6. FACILITATED DIFFUSION
# ═══════════════════════════════════════════════════════════════════════════
story.append(ColorBanner("6. FACILITATED DIFFUSION", bg=TEAL))
story.append(Spacer(1, 4))
story.append(Paragraph(
"Facilitated diffusion is <b>passive transport</b> (no ATP) that uses a <b>specific membrane carrier protein</b>. "
"The solute still moves DOWN its electrochemical gradient but is aided by the carrier. "
"It exhibits all hallmarks of carrier-mediated transport.",
BODY))
story.append(Paragraph(
"Rate ∝ [Solute] at low concentration (faster than simple diffusion)",
EQUATION))
story.append(Paragraph(
"Rate → Vmax at high concentration (saturation — unlike simple diffusion)",
EQUATION))
story.append(Spacer(1, 4))
story.append(DiagramFlowable(W, 155, draw_diffusion_comparison))
story.append(Spacer(1, 6))
story.append(Paragraph("<b>Properties of Carrier-Mediated Transport:</b>", H3))
prop_data = [
["Property", "Explanation", "Clinical Relevance"],
["Saturation (Vmax)", "At high [solute], all carriers are occupied → rate plateaus",
"Tubular maximum (Tm) for glucose reabsorption in kidney"],
["Stereospecificity", "Carrier recognises D-glucose but NOT L-glucose",
"Only natural isomers are transported"],
["Competition", "D-galactose competes with D-glucose for same GLUT transporter",
"Galactosaemia — galactose competes, disrupting glucose transport"],
["Insulin regulation", "Insulin triggers GLUT4 insertion into muscle/adipose membrane",
"Type 2 diabetes — GLUT4 insufficiency → hyperglycaemia"],
]
prop_ts = TableStyle([
("BACKGROUND", (0,0),(-1,0), TEAL),
("TEXTCOLOR", (0,0),(-1,0), WHITE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0),(-1,-1), 8),
("ROWBACKGROUNDS",(0,1),(-1,-1),[TEAL_LIGHT, WHITE]),
("GRID", (0,0),(-1,-1), 0.5, GRAY_MID),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
("TOPPADDING", (0,0),(-1,-1), 4),
("BOTTOMPADDING",(0,0),(-1,-1), 4),
])
prop_t = Table(prop_data, colWidths=[W*0.22, W*0.42, W*0.34])
prop_t.setStyle(prop_ts)
story.append(prop_t)
story.append(Spacer(1, 6))
story.append(Paragraph("<b>GLUT Transporter Family:</b>", H3))
glut_data = [
["Transporter", "Location", "Regulation", "Notes"],
["GLUT1", "RBCs, brain, endothelium", "Constitutive", "High affinity, low Km"],
["GLUT2", "Liver, β-cells, intestine", "Constitutive", "Low affinity, high Km — glucose sensor"],
["GLUT4", "Skeletal muscle, adipose", "Insulin-stimulated","Major route for post-meal glucose uptake"],
["GLUT5", "Small intestine", "Constitutive", "Fructose transport"],
]
glut_ts = TableStyle([
("BACKGROUND", (0,0),(-1,0), TEAL),
("TEXTCOLOR", (0,0),(-1,0), WHITE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0),(-1,-1), 8),
("ROWBACKGROUNDS",(0,1),(-1,-1),[TEAL_LIGHT, WHITE]),
("GRID", (0,0),(-1,-1), 0.5, GRAY_MID),
("TOPPADDING", (0,0),(-1,-1), 4),
("BOTTOMPADDING",(0,0),(-1,-1), 4),
])
glut_t = Table(glut_data, colWidths=[W*0.14, W*0.28, W*0.22, W*0.34])
glut_t.setStyle(glut_ts)
story.append(glut_t)
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════════════
# 7. APOPTOSIS
# ═══════════════════════════════════════════════════════════════════════════
story.append(ColorBanner("7. APOPTOSIS", bg=RED_DARK))
story.append(Spacer(1, 4))
story.append(Paragraph(
"<b>Definition:</b> Apoptosis (Greek: 'falling off') is <b>programmed cell death</b> — a "
"highly regulated, <b>caspase-dependent</b> process in which a cell actively dismantles itself "
"<b>without triggering inflammation</b>. Essential for normal development, immune tolerance, and tissue homeostasis.",
BODY))
story.append(Paragraph("<b>Apoptosis vs Necrosis:</b>", H3))
diff_data = [
["Feature", "APOPTOSIS", "NECROSIS"],
["Cause", "Physiological or programmed", "Pathological (ischaemia, toxins)"],
["Cell membrane", "INTACT throughout", "Ruptures early"],
["Cell size", "Shrinks", "Swells"],
["Inflammation", "ABSENT (no spillage)", "Present (cytoplasmic release)"],
["Caspases", "Required (central)", "Not involved"],
["DNA", "Internucleosomal laddering", "Random degradation"],
["End product", "Apoptotic bodies (phagocytosed)", "Cell debris, inflammation"],
]
diff_ts = TableStyle([
("BACKGROUND", (0,0),(-1,0), RED_DARK),
("TEXTCOLOR", (0,0),(-1,0), WHITE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0),(-1,-1), 8),
("ROWBACKGROUNDS",(0,1),(-1,-1),[RED_LIGHT, WHITE]),
("BACKGROUND", (0,2),(0,-1), colors.HexColor("#FFCDD2")),
("FONTNAME", (0,1),(0,-1), "Helvetica-Bold"),
("GRID", (0,0),(-1,-1), 0.5, GRAY_MID),
("ALIGN", (0,0),(-1,-1), "CENTER"),
("TOPPADDING", (0,0),(-1,-1), 4),
("BOTTOMPADDING",(0,0),(-1,-1), 4),
])
diff_t = Table(diff_data, colWidths=[W*0.22, W*0.39, W*0.39])
diff_t.setStyle(diff_ts)
story.append(diff_t)
story.append(Spacer(1, 6))
story.append(DiagramFlowable(W, 260, draw_apoptosis_pathway))
story.append(Spacer(1, 6))
story.append(Paragraph("<b>Molecular Players:</b>", H3))
mol_data = [
["Molecule", "Role"],
["Bcl-2, Bcl-XL", "Anti-apoptotic — stabilise mitochondrial membrane"],
["BAX, BAK, BIM", "Pro-apoptotic Bcl-2 family — ↑ mitochondrial permeability"],
["Cytochrome c", "Released from mitochondria → activates apoptosome"],
["SMAC/DIABLO", "Released with cytochrome c → inhibits IAPs → enables caspases"],
["Apaf-1", "Binds cytochrome c → forms apoptosome scaffold"],
["Caspase-9", "Initiator caspase (intrinsic pathway)"],
["Caspase-8", "Initiator caspase (extrinsic / death receptor pathway)"],
["Caspases 3, 6, 7", "Executioner caspases — digest cytoplasmic proteins"],
["p53 (tumour suppressor)", "Triggers intrinsic pathway on DNA damage"],
]
mol_ts = TableStyle([
("BACKGROUND", (0,0),(-1,0), RED_DARK),
("TEXTCOLOR", (0,0),(-1,0), WHITE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0),(-1,-1), 8),
("ROWBACKGROUNDS",(0,1),(-1,-1),[RED_LIGHT, WHITE]),
("GRID", (0,0),(-1,-1), 0.5, GRAY_MID),
("TOPPADDING", (0,0),(-1,-1), 4),
("BOTTOMPADDING",(0,0),(-1,-1), 4),
])
mol_t = Table(mol_data, colWidths=[W*0.32, W*0.66])
mol_t.setStyle(mol_ts)
story.append(mol_t)
story.append(Spacer(1, 6))
story.append(Paragraph("<b>Clinical Relevance:</b>", H3))
clin = [
"Cancer: p53 mutation / Bcl-2 overexpression → apoptosis resistance → tumour survival",
"Leukaemia: t(14;18) translocation → Bcl-2 overexpression",
"Neurodegeneration (Parkinson's, Alzheimer's): excessive apoptosis of neurons",
"Autoimmune disease: defective FAS-mediated apoptosis → failure to delete self-reactive T cells (ALPS syndrome)",
"HIV: CD4+ T cell depletion via apoptosis",
"Anoikis: apoptosis triggered by loss of cell-ECM contact — important in cancer metastasis",
]
for item in clin:
story.append(Paragraph(f"• {item}", BULLET))
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════════════
# QUICK REVISION SUMMARY TABLE
# ═══════════════════════════════════════════════════════════════════════════
story.append(ColorBanner("QUICK REVISION SUMMARY", bg=BLUE_DARK))
story.append(Spacer(1, 6))
summary_data = [
["Topic", "Key Equation / Formula", "Must Remember"],
["Secondary Active\nTransport",
"Energy = Na⁺ gradient\n(maintained by Na-K-ATPase)",
"Symport: same direction\nAntiport: opposite\nInhibit NaKATPase → stops all SAT"],
["Resting Membrane\nPotential",
"Em = Σ(gi/gT)·Ei\nNernst: E = 61/z · log([out]/[in])",
"−70 to −80 mV\nK⁺ + Cl⁻ = main determinants\nNa-K-ATPase role = indirect (major)"],
["Cell Junctions",
"No formula",
"TJ: Occludin/Claudin (seal)\nAJ: Cadherin+Actin (link)\nDSM: Cadherin+IF (shear)\nGJ: Connexin <1000Da (comms)"],
["Na⁺-K⁺-ATPase",
"3 Na⁺ out : 2 K⁺ in : 1 ATP\nCoupling = 3:2 (electrogenic)",
"α subunit = functional core\nβ subunit = glycoprotein\nInhibited by Ouabain/Digitalis"],
["Simple Diffusion",
"J = P × A × (CA − CB)\nP = KD/Δx",
"No carrier, no saturation\nDriven by conc gradient\nLipid-soluble substances"],
["Facilitated\nDiffusion",
"Vmax (saturable)\nKm = concentration at ½Vmax",
"Carrier needed, no ATP\nStereospecific, competitive\nGLUT4 (insulin-stimulated)"],
["Apoptosis",
"No formula\nCaspase cascade",
"Intrinsic: Bcl-2/Cyt c/Casp-9\nExtrinsic: Fas/DISC/Casp-8\nExecutioner: Casp 3,6,7\nNO inflammation"],
]
sum_ts = TableStyle([
("BACKGROUND", (0,0),(-1,0), BLUE_DARK),
("TEXTCOLOR", (0,0),(-1,0), WHITE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0),(-1,-1), 8),
("ROWBACKGROUNDS",(0,1),(-1,-1),[BLUE_LIGHT, WHITE]),
("GRID", (0,0),(-1,-1), 0.5, GRAY_MID),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
("TOPPADDING", (0,0),(-1,-1), 5),
("BOTTOMPADDING",(0,0),(-1,-1), 5),
])
sum_t = Table(summary_data, colWidths=[W*0.22, W*0.35, W*0.41])
sum_t.setStyle(sum_ts)
story.append(sum_t)
story.append(Spacer(1, 10))
# Footer note
story.append(HRFlowable(width=W, thickness=1, color=BLUE_DARK))
story.append(Spacer(1, 4))
story.append(Paragraph(
"Sources: Costanzo Physiology 7e | Ganong's Review of Medical Physiology 26e | "
"Guyton & Hall Textbook of Medical Physiology | Histology: A Text and Atlas (Ross & Pawlina)",
S("Footer", fontSize=7, textColor=GRAY_MID, alignment=TA_CENTER)))
doc.build(story)
print(f"PDF generated: {OUTPUT}")
if __name__ == "__main__":
build()
cd /home/daytona/workspace/gen-physiology-pdf && python3 build_pdf.py 2>&1
~/gen-physiology-pdf/build_pdf.py
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/gen-physiology-pdf/build_pdf.py'
cd /home/daytona/workspace/gen-physiology-pdf && python3 build_pdf.py 2>&1
ls -lh /home/daytona/workspace/gen-physiology-pdf/General_Physiology_Summary.pdf
General Physiology Summary
PDF Document · PDF
| Page | Content |
|---|---|
| 1 | Cover page + Table of Contents |
| 2 | Secondary Active Transport - diagram (symport vs antiport), transporter table |
| 3 | Resting Membrane Potential - ion table, Nernst & chord conductance equations, bar chart diagram |
| 4 | Cell Junctions - full comparison table + illustrated diagram of all 6 junction types |
| 5 | Na⁺-K⁺-ATPase - structure table, pump diagram with stoichiometry |
| 6 | Simple Diffusion - Fick's Law, Stokes-Einstein equation, factors table, comparison with carrier transport |
| 7 | Facilitated Diffusion - GLUT family table, saturation kinetics, diagram |
| 8 | Apoptosis - vs Necrosis table, intrinsic/extrinsic pathway diagram, molecular players, clinical correlations |
| Final | Quick Revision Summary Table - all 7 topics with key equations + must-remember points |