~/vet-biochem-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, Image,
Table, TableStyle, PageBreak, HRFlowable,
KeepTogether)
from reportlab.platypus.flowables import BalancedColumns
from reportlab.pdfgen import canvas
from reportlab.lib.colors import HexColor
import os
IMG_DIR = "/home/daytona/workspace/vet-biochem-pdf/images"
OUT_PATH = "/home/daytona/workspace/vet-biochem-pdf/Vet_Biochemistry_Diagrams_Clinical.pdf"
W, H = A4
# ── Colour palette ────────────────────────────────────────────────
DARK_BLUE = HexColor("#1a3a5c")
MED_BLUE = HexColor("#2e6da4")
LIGHT_BLUE = HexColor("#dce8f5")
ACCENT_GOLD = HexColor("#c8860a")
VET_GREEN = HexColor("#2d6a2d")
LIGHT_GREEN = HexColor("#e6f4e6")
WARN_RED = HexColor("#b22222")
LIGHT_RED = HexColor("#fde8e8")
LIGHT_GRAY = HexColor("#f5f5f5")
MID_GRAY = HexColor("#888888")
styles = getSampleStyleSheet()
def S(name, **kw):
"""Create a ParagraphStyle inheriting from base."""
base = styles.get(name, styles["Normal"])
return ParagraphStyle(name + "_custom_" + str(id(kw)), parent=base, **kw)
# Custom styles
TITLE_STYLE = S("Title", fontSize=26, textColor=DARK_BLUE, spaceAfter=4,
alignment=TA_CENTER, fontName="Helvetica-Bold")
SUBTITLE_STYLE = S("Normal", fontSize=13, textColor=MED_BLUE, spaceAfter=2,
alignment=TA_CENTER, fontName="Helvetica")
DATE_STYLE = S("Normal", fontSize=9, textColor=MID_GRAY, spaceAfter=0,
alignment=TA_CENTER, fontName="Helvetica-Oblique")
SECTION_STYLE = S("Heading1", fontSize=14, textColor=colors.white,
spaceBefore=6, spaceAfter=4,
fontName="Helvetica-Bold", leading=18)
SUBSEC_STYLE = S("Heading2", fontSize=11, textColor=DARK_BLUE,
spaceBefore=4, spaceAfter=3,
fontName="Helvetica-Bold", leading=14)
BODY_STYLE = S("Normal", fontSize=9, textColor=colors.black,
spaceBefore=2, spaceAfter=2, leading=13,
fontName="Helvetica", alignment=TA_JUSTIFY)
BULLET_STYLE = S("Normal", fontSize=9, textColor=colors.black,
spaceBefore=1, spaceAfter=1, leading=12,
leftIndent=12, bulletIndent=0,
fontName="Helvetica")
CAPTION_STYLE = S("Normal", fontSize=8, textColor=MID_GRAY,
alignment=TA_CENTER, fontName="Helvetica-Oblique",
spaceBefore=2, spaceAfter=6)
VET_BOX_STYLE = S("Normal", fontSize=9, textColor=VET_GREEN,
leading=13, fontName="Helvetica", alignment=TA_JUSTIFY)
WARN_BOX_STYLE = S("Normal", fontSize=9, textColor=WARN_RED,
leading=13, fontName="Helvetica", alignment=TA_JUSTIFY)
TABLE_HEADER = S("Normal", fontSize=8, textColor=colors.white,
fontName="Helvetica-Bold", alignment=TA_CENTER)
TABLE_CELL = S("Normal", fontSize=8, textColor=colors.black,
fontName="Helvetica", alignment=TA_LEFT, leading=11)
def img(filename, width_cm=14, height_cm=None):
path = os.path.join(IMG_DIR, filename)
if not os.path.exists(path):
return Paragraph(f"[Image not found: {filename}]", BODY_STYLE)
w = width_cm * cm
from PIL import Image as PILImage
pil = PILImage.open(path)
iw, ih = pil.size
ratio = ih / iw
h = height_cm * cm if height_cm else w * ratio
# clamp height
max_h = 17 * cm
if h > max_h:
h = max_h
w = h / ratio
return Image(path, width=w, height=h, hAlign="CENTER")
def section_header(text, color=DARK_BLUE):
"""Returns a coloured banner paragraph."""
tbl = Table([[Paragraph(text, SECTION_STYLE)]], colWidths=[W - 4*cm])
tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), color),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 10),
("ROUNDEDCORNERS", [4]),
]))
return tbl
def vet_box(title, *lines, color=LIGHT_GREEN, border=VET_GREEN, title_color=VET_GREEN):
content = [Paragraph(f"<b>{title}</b>", S("Normal", fontSize=9,
textColor=title_color, fontName="Helvetica-Bold", leading=13))]
for line in lines:
content.append(Paragraph(f"• {line}", VET_BOX_STYLE))
tbl = Table([[content]], colWidths=[W - 4*cm])
tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), color),
("BOX", (0,0), (-1,-1), 1.5, border),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
]))
return tbl
def warn_box(title, *lines):
return vet_box(title, *lines, color=LIGHT_RED, border=WARN_RED, title_color=WARN_RED)
def key_table(headers, rows):
data = [[Paragraph(h, TABLE_HEADER) for h in headers]]
for row in rows:
data.append([Paragraph(str(c), TABLE_CELL) for c in row])
col_w = (W - 4*cm) / len(headers)
tbl = Table(data, colWidths=[col_w]*len(headers), repeatRows=1)
style = [
("BACKGROUND", (0,0), (-1,0), MED_BLUE),
("ROWBACKGROUNDS",(0,1), (-1,-1), [colors.white, LIGHT_BLUE]),
("GRID", (0,0), (-1,-1), 0.5, HexColor("#aaaaaa")),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "TOP"),
]
tbl.setStyle(TableStyle(style))
return tbl
def divider():
return HRFlowable(width="100%", thickness=0.5, color=LIGHT_BLUE, spaceAfter=4, spaceBefore=4)
# ── Page numbering canvas ─────────────────────────────────────────
class NumberedCanvas(canvas.Canvas):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._saved_page_states = []
def showPage(self):
self._saved_page_states.append(dict(self.__dict__))
self._startPage()
def save(self):
num_pages = len(self._saved_page_states)
for state in self._saved_page_states:
self.__dict__.update(state)
self.draw_page_number(num_pages)
canvas.Canvas.showPage(self)
canvas.Canvas.save(self)
def draw_page_number(self, page_count):
page_num = self._saved_page_states.index(
{k: v for k, v in self.__dict__.items()
if k in self._saved_page_states[0]}) + 1
self.setFont("Helvetica", 8)
self.setFillColor(MID_GRAY)
self.drawRightString(W - 2*cm, 1.2*cm,
f"Page {page_num} of {page_count}")
self.drawString(2*cm, 1.2*cm, "Vet Biochemistry — Diagrams & Clinical Applications")
self.setStrokeColor(LIGHT_BLUE)
self.setLineWidth(0.5)
self.line(2*cm, 1.5*cm, W - 2*cm, 1.5*cm)
# ── Build story ───────────────────────────────────────────────────
story = []
# ── COVER PAGE ───────────────────────────────────────────────────
story.append(Spacer(1, 3*cm))
story.append(Paragraph("VET BIOCHEMISTRY", TITLE_STYLE))
story.append(Paragraph("Diagrams & Clinical Applications", SUBTITLE_STYLE))
story.append(Spacer(1, 0.5*cm))
story.append(HRFlowable(width="60%", thickness=2, color=ACCENT_GOLD,
hAlign="CENTER", spaceBefore=4, spaceAfter=4))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph("Complete Illustrated Reference for Exam Preparation", SUBTITLE_STYLE))
story.append(Spacer(1, 0.5*cm))
# topic list on cover
topics = [
("Q.6", "Short Notes"),
("1.", "Cori Cycle"),
("2.", "Deamination Reactions of Amino Acids"),
("3.", "Effects of Temperature & pH on Enzyme Activity"),
("Q.7", "Brief Descriptions"),
("4.", "Beta-Oxidation of Fatty Acids"),
("5.", "TCA (Krebs) Cycle — Energy Production"),
("6.", "Glycogenolysis"),
("7.", "Enzyme-Substrate Complex Formation"),
("Bonus", "Oxidative Phosphorylation"),
]
cover_data = [[Paragraph(f"<b>{n}</b>", S("Normal", fontSize=10,
textColor=MED_BLUE, fontName="Helvetica-Bold")),
Paragraph(t, S("Normal", fontSize=10, fontName="Helvetica"))]
for n, t in topics]
cover_tbl = Table(cover_data, colWidths=[2.5*cm, 12*cm])
cover_tbl.setStyle(TableStyle([
("ROWBACKGROUNDS", (0,0), (-1,-1), [colors.white, LIGHT_BLUE]),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 8),
("BOX", (0,0), (-1,-1), 1, MED_BLUE),
("LINEBELOW", (0,0), (-1,-2), 0.3, LIGHT_BLUE),
]))
story.append(cover_tbl)
story.append(Spacer(1, 1*cm))
story.append(Paragraph("Sources: Lippincott Illustrated Reviews Biochemistry 8e • Harper's Illustrated Biochemistry 32e •<br/>Basic Medical Biochemistry 6e • Guyton & Hall Medical Physiology • Harper's 32e", DATE_STYLE))
story.append(PageBreak())
# ════════════════════════════════════════════════════════════════
# SECTION 1 — CORI CYCLE
# ════════════════════════════════════════════════════════════════
story.append(section_header("Q.6 — SHORT NOTES", DARK_BLUE))
story.append(Spacer(1, 0.3*cm))
story.append(section_header("1. Cori Cycle (Lactic Acid Cycle)", MED_BLUE))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph(
"<b>Definition:</b> The Cori cycle is the metabolic pathway by which lactate "
"produced by anaerobic glycolysis in peripheral tissues (muscle, RBCs) is "
"transported to the liver, reconverted to glucose via gluconeogenesis, and "
"returned to blood for re-use.", BODY_STYLE))
story.append(Spacer(1, 0.2*cm))
story.append(img("cori_cycle.png", width_cm=14))
story.append(Paragraph(
"Fig 1. Cori Cycle — Basic Medical Biochemistry 6e, Fig. 22.12",
CAPTION_STYLE))
story.append(key_table(
["Feature", "Detail"],
[
["Tissues involved", "Muscle, RBCs (anaerobic) → Liver (aerobic)"],
["Key enzymes - Muscle", "LDH: Pyruvate → Lactate (uses NADH)"],
["Key enzymes - Liver", "LDH + Gluconeogenic enzymes (PCK, FBPase, G6Pase)"],
["ATP balance", "Muscle gains 2 ATP; Liver spends 6 ATP → Net loss of 4 ATP"],
["Function", "Recycles lactate carbon; prevents lactic acidosis; maintains blood glucose"],
]
))
story.append(Spacer(1, 0.3*cm))
story.append(vet_box(
"Veterinary Clinical Applications",
"Racing horses / greyhounds: Massive lactate production during sprint exercise; "
"Cori cycle keeps blood glucose from crashing post-race",
"Capture myopathy (wild deer, zebra, kangaroo): Extreme exertion → lactic acidosis when "
"Cori cycle is overwhelmed → pH drops → muscle necrosis → death if untreated",
"Cattle with dystocia (prolonged difficult birth): Calf undergoes anaerobic glycolysis "
"→ elevated blood lactate at birth; correction with IV glucose + bicarbonate",
"Exertional rhabdomyolysis ('tying-up') in horses: Pyruvate/lactate accumulation → "
"muscle damage; serum CK and AST markedly elevated",
))
story.append(PageBreak())
# ════════════════════════════════════════════════════════════════
# SECTION 2 — DEAMINATION
# ════════════════════════════════════════════════════════════════
story.append(section_header("2. Deamination Reactions of Amino Acids", MED_BLUE))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph(
"<b>Definition:</b> Deamination is the removal of the amino (−NH₂) group from "
"an amino acid, yielding an α-keto acid and releasing nitrogen. There are "
"three main types: transamination, oxidative deamination, and non-oxidative "
"deamination.", BODY_STYLE))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph("<b>Step 1 — Transamination (ALT & AST):</b>", SUBSEC_STYLE))
story.append(img("transamination.png", width_cm=9))
story.append(Paragraph(
"Fig 2a. Transamination reactions — ALT (top) and AST (bottom). "
"Both require PLP (Vitamin B6). — Lippincott Biochemistry 8e, Fig. 19.8",
CAPTION_STYLE))
story.append(Paragraph("<b>Step 2 — Oxidative Deamination (Glutamate Dehydrogenase):</b>", SUBSEC_STYLE))
story.append(img("oxidative_deamination.png", width_cm=9))
story.append(Paragraph(
"Fig 2b. Panel A: Disposal of amino acids via transamination + oxidative "
"deamination → free NH₃. Panel B: Reductive amination (synthesis). "
"— Lippincott Biochemistry 8e, Fig. 19.12",
CAPTION_STYLE))
story.append(key_table(
["Type", "Enzyme", "Coenzyme", "Product"],
[
["Transamination", "ALT (GPT), AST (GOT)", "PLP (Vit B6)", "α-Keto acid + Glutamate"],
["Oxidative Deamination", "Glutamate Dehydrogenase (GDH)", "NAD⁺ (catabolism)", "α-KG + NH₃ + NADH"],
["Non-oxidative Deamination", "Serine dehydratase", "PLP", "Pyruvate + NH₃"],
["D-amino acid oxidase", "DAO (peroxisomal)", "FAD", "α-Keto acid + NH₃ + H₂O₂"],
]
))
story.append(Spacer(1, 0.2*cm))
story.append(vet_box(
"Veterinary Clinical Applications",
"ALT (SGPT): Liver-specific in dogs & cats. Elevated in hepatitis, hepatic lipidosis "
"(fatty liver in obese cats), toxin ingestion (xylitol, aflatoxin). Normal dog ALT: 10-100 U/L",
"AST (SGOT): Elevated in both liver AND muscle disease in horses and ruminants. "
"Must interpret with CK to differentiate; if CK normal → liver origin",
"GDH: Liver-specific in cattle and sheep. Best single enzyme marker of "
"hepatocellular necrosis in ruminants (e.g., ragwort toxicity, aflatoxicosis)",
"Ammonia toxicity: When GDH is impaired (liver failure) → NH₃ accumulates → "
"hepatic encephalopathy in dogs, horses (head pressing, ataxia, seizures)",
"Thiamin (B6) deficiency → PLP deficiency → transamination impaired → "
"polioencephalomalacia in cattle/sheep (cerebrocortical necrosis)",
))
story.append(PageBreak())
# ════════════════════════════════════════════════════════════════
# SECTION 3 — TEMP & pH
# ════════════════════════════════════════════════════════════════
story.append(section_header("3. Effects of Temperature & pH on Enzyme Activity", MED_BLUE))
story.append(Spacer(1, 0.2*cm))
story.append(img("temp_ph.png", width_cm=15))
story.append(Paragraph(
"Fig 3. Left: Bell-curve effect of temperature (optimum 37-40°C for mammalian enzymes; "
"denaturation above). Right: pH optima vary per enzyme — Pepsin (pH 2), "
"Salivary amylase (pH 6.8), Trypsin (pH 7.5-8).",
CAPTION_STYLE))
story.append(key_table(
["Enzyme", "Optimum pH", "Location / Species Relevance"],
[
["Pepsin", "~2.0", "Stomach (monogastrics — dog, cat, pig, horse)"],
["Salivary amylase", "6.8–7.0", "Oral cavity (absent in cats; present in dogs, horses)"],
["Trypsin / Chymotrypsin", "7.5–8.0", "Pancreas → small intestine (all species)"],
["Alkaline Phosphatase (ALP)", "9–10", "Bone, liver, intestine — elevated in cholestasis"],
["Arginase", "~9.5", "Liver (urea cycle) — ruminants, dogs"],
["Acid Phosphatase", "~5.0", "Lysosomes, prostate"],
["Rumen microbial enzymes", "6.2–6.8", "Rumen — optimal for cellulolytic bacteria"],
]
))
story.append(Spacer(1, 0.2*cm))
story.append(vet_box(
"Veterinary Clinical Applications — Temperature",
"Fever (pyrexia) in animals: Moderate fever (39-40°C) initially enhances immune enzyme "
"reactions. Hyperthermia >42°C (heat stroke in brachycephalic dogs, horses) denatures "
"enzymes → multi-organ failure",
"Hypothermia in neonates: Newborn lambs, piglets, foals in cold environments → "
"metabolic enzyme rates halved per 10°C drop (Q10 effect) → hypoglycemia, bradycardia",
"Thermostable enzymes: Rumen microbes have enzymes stable over wider temperature ranges; "
"important in tropical veterinary nutrition",
"Cold storage of blood/serum samples: Enzyme activity preserved at 4°C for clinical assays",
))
story.append(vet_box(
"Veterinary Clinical Applications — pH",
"Rumen acidosis (grain overload) in cattle/sheep: Rumen pH drops to 4.5-5.5 → "
"inhibits cellulolytic bacteria enzymes → fermentation stops → D-lactic acidosis → "
"ataxia ('drunken cow syndrome'), recumbency, death",
"Abomasal displacement / volvulus in cows: Disrupts HCl production → enzyme pH disrupted",
"Pancreatitis in dogs/cats: Trypsin activated prematurely within pancreas at wrong pH "
"→ autodigestion of pancreatic tissue",
"Alkalosis in milk fever (hypocalcaemia, parturient paresis): Systemic pH shift affects "
"enzyme function; IV calcium gluconate treatment",
"Clinical enzyme assays (ALT, ALP, CK): Must be run at controlled pH (phosphate "
"buffer) and temperature (37°C) for accurate results",
))
story.append(PageBreak())
# ════════════════════════════════════════════════════════════════
# SECTION 4 — BETA OXIDATION
# ════════════════════════════════════════════════════════════════
story.append(section_header("Q.7 — BRIEF DESCRIPTIONS", DARK_BLUE))
story.append(Spacer(1, 0.3*cm))
story.append(section_header("4. β-Oxidation of Fatty Acids", MED_BLUE))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph(
"<b>Definition:</b> β-Oxidation is the stepwise degradation of fatty acids in the "
"<b>mitochondrial matrix</b> by sequential removal of 2-carbon (acetyl-CoA) units, "
"producing NADH and FADH₂ per cycle.", BODY_STYLE))
story.append(Paragraph("<b>Full Pathway (activation + transport + 4 steps):</b>", SUBSEC_STYLE))
story.append(img("beta_oxidation_pathway.png", width_cm=9))
story.append(Paragraph(
"Fig 4a. Complete β-oxidation pathway: activation → carnitine transport across "
"inner mitochondrial membrane → 4-step repeating cycle → Acetyl-CoA → TCA cycle. "
"— Harper's Illustrated Biochemistry 32e, Fig. 22-3",
CAPTION_STYLE))
story.append(Paragraph("<b>Chemical equations for each step:</b>", SUBSEC_STYLE))
story.append(img("beta_oxidation_equations.png", width_cm=15))
story.append(Paragraph(
"Fig 4b. β-oxidation reactions: (1) Activation by Thiokinase; (2) FAD-oxidation "
"by Acyl dehydrogenase → FADH₂; (3) Hydration by Enoyl hydrase → β-OH-acyl-CoA; "
"(4) NAD⁺-oxidation by β-Hydroxyacyl DH → NADH; (5) Thiolysis by Thiolase → "
"Acetyl-CoA + shortened acyl-CoA. — Guyton & Hall Physiology",
CAPTION_STYLE))
story.append(key_table(
["Step", "Enzyme", "Cofactor", "Product"],
[
["0a. Activation", "Acyl-CoA synthetase (Thiokinase)", "ATP, CoA", "Fatty acyl-CoA + AMP + PPi (−2 ATP)"],
["0b. Transport", "CPT-I, CACT, CPT-II (Carnitine shuttle)", "Carnitine", "Acyl-CoA in mitochondrial matrix"],
["1. Oxidation", "Acyl-CoA dehydrogenase", "FAD", "trans-Δ²-Enoyl-CoA + FADH₂"],
["2. Hydration", "Enoyl-CoA hydratase", "H₂O", "L-3-Hydroxyacyl-CoA"],
["3. Oxidation", "L-3-Hydroxyacyl-CoA DH", "NAD⁺", "3-Ketoacyl-CoA + NADH"],
["4. Thiolysis", "β-Ketothiolase (Thiolase)", "CoA", "Acetyl-CoA + (n−2) Acyl-CoA"],
]
))
story.append(Spacer(1, 0.2*cm))
story.append(key_table(
["Palmitate (C16) Energy", "Cycles/Moles", "ATP/unit", "Total ATP"],
[
["Activation cost", "—", "−2", "−2"],
["β-Oxidation FADH₂", "7", "×1.5", "+10.5"],
["β-Oxidation NADH", "7", "×2.5", "+17.5"],
["TCA (8 Acetyl-CoA)", "8", "×10", "+80"],
["NET TOTAL", "", "", "106 ATP"],
]
))
story.append(Spacer(1, 0.2*cm))
story.append(vet_box(
"Veterinary Clinical Applications",
"Ketosis / Acetonaemia in dairy cows (early lactation negative energy balance): "
"Excess β-oxidation → Acetyl-CoA cannot enter TCA (OAA depleted) → ketone bodies "
"(BOHB, acetoacetate, acetone). Blood BOHB >3 mmol/L = clinical ketosis. "
"Treatment: IV glucose, propylene glycol, glucocorticoids",
"Pregnancy toxaemia in ewes (twin-lamb disease): Same mechanism — twin fetuses "
"consume glucose → ewe mobilises fat → ketosis. High mortality if untreated",
"Feline hepatic lipidosis: Obese cats on starvation diet → massive fat mobilisation "
"→ overwhelms hepatic β-oxidation → fat accumulates in liver → jaundice, liver failure",
"CPT-I deficiency (dogs): Carnitine shuttle impaired → long-chain fatty acids cannot "
"enter mitochondria → lipid myopathy, cardiomyopathy (seen in Boxers, Dobermans)",
"L-carnitine supplementation: Used in dogs with dilated cardiomyopathy to improve "
"fatty acid transport into cardiac mitochondria",
))
story.append(warn_box(
"Exam Alert",
"Remember: Activation uses 2 high-energy phosphates (ATP → AMP + PPi, equivalent to −2 ATP)",
"FADH₂ from β-oxidation feeds directly into Complex II of ETC (bypasses Complex I) → 1.5 ATP each",
"Odd-chain fatty acids (propionyl-CoA → succinyl-CoA via Vit B12) — glucogenic, "
"important in ruminants (propionate from rumen)",
))
story.append(PageBreak())
# ════════════════════════════════════════════════════════════════
# SECTION 5 — TCA CYCLE
# ════════════════════════════════════════════════════════════════
story.append(section_header("5. TCA (Krebs / Citric Acid) Cycle", MED_BLUE))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph(
"<b>Definition:</b> The TCA cycle is a series of 8 enzyme-catalysed reactions in "
"the <b>mitochondrial matrix</b> that completely oxidise <b>Acetyl-CoA</b> to CO₂, "
"capturing energy as NADH, FADH₂, and GTP.", BODY_STYLE))
story.append(Spacer(1, 0.2*cm))
story.append(img("tca_cycle.png", width_cm=13))
story.append(Paragraph(
"Fig 5. Complete TCA (Krebs) Cycle showing all 8 steps, enzymes, cofactors, and "
"inhibitors (red lines: Fluoroacetate blocks Aconitase; Arsenite blocks α-KG DH; "
"Malonate blocks Succinate DH). — Harper's Illustrated Biochemistry 32e, Fig. 16-3",
CAPTION_STYLE))
story.append(key_table(
["Step", "Reaction", "Enzyme", "Energy"],
[
["1", "OAA (4C) + Acetyl-CoA (2C) → Citrate (6C)", "Citrate synthase", "—"],
["2", "Citrate → cis-Aconitate → Isocitrate", "Aconitase (Fe²⁺)", "—"],
["3", "Isocitrate → Oxalosuccinate → α-KG + CO₂", "Isocitrate DH (Mn²⁺)", "1 NADH"],
["4", "α-KG (5C) → Succinyl-CoA (4C) + CO₂", "α-KG DH complex (TPP, Lipoate, FAD)", "1 NADH"],
["5", "Succinyl-CoA → Succinate", "Succinyl-CoA synthetase (Mg²⁺)", "1 GTP"],
["6", "Succinate → Fumarate", "Succinate DH (Complex II of ETC)", "1 FADH₂"],
["7", "Fumarate + H₂O → L-Malate", "Fumarase", "—"],
["8", "L-Malate → OAA", "Malate dehydrogenase", "1 NADH"],
]
))
story.append(Spacer(1, 0.2*cm))
story.append(key_table(
["Product per turn", "Number", "ATP equivalent", "Cumulative"],
[
["NADH (Steps 3,4,8)", "3", "× 2.5 = 7.5 ATP", "7.5"],
["FADH₂ (Step 6)", "1", "× 1.5 = 1.5 ATP", "9.0"],
["GTP (Step 5)", "1", "= 1 ATP", "10.0"],
["TOTAL per turn", "", "", "~10 ATP"],
["CO₂ released", "2", "—", "Metabolic waste"],
]
))
story.append(Spacer(1, 0.2*cm))
story.append(vet_box(
"Veterinary Clinical Applications",
"Acetonaemia/ketosis in dairy cattle: Negative energy balance → OAA diverted to "
"gluconeogenesis → TCA cycle slows → Acetyl-CoA accumulates → ketogenesis. "
"Blood glucose <2.2 mmol/L + BOHB >3 mmol/L = diagnosis",
"Fluoroacetate (compound 1080) poisoning: Used as rodenticide; highly toxic to dogs, "
"cats, foxes, livestock. Fluoroacetate → fluorocitrate → irreversibly blocks Aconitase "
"→ citrate accumulates → TCA stops → cardiac arrest. No antidote; supportive care only",
"Arsenite toxicity (arsenic poisoning in livestock from dipping vats, pasture): "
"Inhibits α-KG dehydrogenase → TCA blocked → energy failure in heart and nervous system",
"Thiamin (Vit B1) deficiency: α-KG DH complex requires TPP (thiamin pyrophosphate). "
"Deficiency in ruminants (polioencephalomalacia) and horses (bracken fern toxicity) "
"→ TCA impaired → brain energy failure. Treatment: IV thiamin",
"Succinate dehydrogenase is Complex II of ETC — important junction between TCA and OXPHOS",
))
story.append(PageBreak())
# ════════════════════════════════════════════════════════════════
# SECTION 6 — GLYCOGENOLYSIS
# ════════════════════════════════════════════════════════════════
story.append(section_header("6. Glycogenolysis", MED_BLUE))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph(
"<b>Definition:</b> Glycogenolysis is the enzymatic <b>degradation of stored glycogen</b> "
"to yield glucose (liver) or glucose-6-phosphate (muscle). It is NOT the reverse of "
"glycogen synthesis — it uses entirely different enzymes.", BODY_STYLE))
story.append(Spacer(1, 0.2*cm))
story.append(img("glycogenolysis.png", width_cm=13))
story.append(Paragraph(
"Fig 6. Steps in Glycogenolysis: Phosphorylase cleaves α-1,4 bonds → Glucan transferase "
"moves trisaccharide to expose branch → Debranching enzyme cleaves α-1,6 bond releasing "
"free glucose. Blue = α-1,4 linked glucose; Orange = branch glucose; "
"Branch point = α-1,6 bond. — Harper's Illustrated Biochemistry 32e, Fig. 18-4",
CAPTION_STYLE))
story.append(key_table(
["Step", "Enzyme", "Bond cleaved", "Product"],
[
["1. Chain shortening", "Glycogen phosphorylase (needs PLP)", "α-1,4 (phosphorolysis)", "Glucose-1-phosphate"],
["2. Branch transfer", "Glucan transferase (part of debranching enzyme)", "Transfers 3 units", "Exposed α-1,6 branch"],
["3. Branch removal", "α-1,6-Glucosidase (debranching enzyme)", "α-1,6 (hydrolysis)", "Free glucose (unphosphorylated!)"],
["4. Isomerisation", "Phosphoglucomutase", "—", "Glucose-6-phosphate"],
["5. Liver only", "Glucose-6-phosphatase (ER membrane)", "—", "Free glucose → blood"],
]
))
story.append(Spacer(1, 0.2*cm))
story.append(key_table(
["Hormone/Signal", "Mechanism", "Tissue", "Effect"],
[
["Glucagon (low blood glucose)", "↑cAMP → PKA → Phosphorylase kinase → Phosphorylase b→a", "Liver", "↑ Glycogenolysis; glucose released to blood"],
["Epinephrine (stress/exercise)", "Same cAMP cascade + Ca²⁺", "Liver + Muscle", "↑ Glycogenolysis for fight-or-flight"],
["Ca²⁺ (muscle contraction)", "Directly activates phosphorylase kinase", "Muscle", "↑ Glycogenolysis during exercise"],
["AMP (low ATP)", "Allosteric activation of phosphorylase b", "Muscle", "↑ Glycogenolysis when energy low"],
["Insulin (fed state)", "Activates phosphatase → dephosphorylates phosphorylase", "Both", "↓ Glycogenolysis; ↑ Glycogen synthesis"],
]
))
story.append(Spacer(1, 0.2*cm))
story.append(vet_box(
"Veterinary Clinical Applications",
"Neonatal hypoglycaemia (piglets, lambs, foals): At birth, umbilical cord clamped → "
"maternal glucose supply cut → epinephrine + glucagon activate glycogenolysis to restore "
"blood glucose. Neonates with limited glycogen stores → fatal hypoglycaemia within hours. "
"Rx: Oral or IV glucose",
"Glycogen Storage Diseases (GSD) — Pompe disease (GSD Type II) in Brahman cattle: "
"Acid maltase (lysosomal α-glucosidase) deficiency → glycogen accumulates in muscle "
"and heart → cardiomyopathy, muscle weakness, respiratory failure",
"GSD Type III (Debranching enzyme deficiency): Reported in German Shepherds → "
"cannot debranch → glycogen accumulates → hypoglycaemia + hepatomegaly",
"Capture myopathy in wild animals: Epinephrine surge → rapid glycogenolysis → "
"glucose used for intense muscle work → lactate + glycogen depletion → muscle necrosis",
"Hypoglycaemia in toy breed dogs (Chihuahuas, Yorkshire Terriers): "
"Limited hepatic glycogen stores; stress → rapid glycogen depletion → seizures",
"Diabetes mellitus in dogs/cats: Glucagon dominance → unregulated glycogenolysis "
"→ persistent hyperglycaemia despite glucose excess",
))
story.append(PageBreak())
# ════════════════════════════════════════════════════════════════
# SECTION 7 — ENZYME-SUBSTRATE COMPLEX
# ════════════════════════════════════════════════════════════════
story.append(section_header("7. Enzyme-Substrate Complex Formation", MED_BLUE))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph(
"<b>Definition:</b> The enzyme-substrate (ES) complex is the transient molecular "
"association formed when a substrate binds to the <b>active site</b> of an enzyme, "
"preceding catalysis: <b>E + S ⇌ ES → E + P</b>", BODY_STYLE))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph("<b>Active site hydrogen bonding (basis of specificity):</b>", SUBSEC_STYLE))
story.append(img("es_hbonds.png", width_cm=11))
story.append(Paragraph(
"Fig 7a. Glucose binding site in glucokinase — each -OH of glucose (red) is held by "
"specific H-bonds (dashed) to Asp-205, Asn-204, Asn-231, Glu-256, Glu-290, Gly-229. "
"Panel B: Galactose (differs by one -OH) is NOT phosphorylated → explains enzyme "
"specificity. — Basic Medical Biochemistry 6e, Fig. 8.5",
CAPTION_STYLE))
story.append(Paragraph("<b>Induced Fit Model — Before and After substrate binding:</b>", SUBSEC_STYLE))
# side by side images
before_img = img("es_before.png", width_cm=7)
after_img = img("es_after.png", width_cm=7)
side_tbl = Table([[before_img, after_img]], colWidths=[8*cm, 8*cm])
side_tbl.setStyle(TableStyle([
("ALIGN", (0,0), (-1,-1), "CENTER"),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("LEFTPADDING", (0,0), (-1,-1), 4),
("RIGHTPADDING", (0,0), (-1,-1), 4),
]))
story.append(side_tbl)
story.append(Paragraph(
"Fig 7b (left): Glucokinase BEFORE binding — open cleft, substrate approaching. "
"Fig 7c (right): AFTER binding — cleft closes around glucose (red sphere) "
"= Induced Fit. — Basic Medical Biochemistry 6e, Fig. 8.6",
CAPTION_STYLE))
story.append(key_table(
["Model", "Proposed by", "Concept", "Status"],
[
["Lock and Key", "Emil Fischer, 1894",
"Enzyme has rigid pre-formed active site; substrate fits exactly like key in lock",
"Outdated — does not explain enzyme flexibility"],
["Induced Fit", "Daniel Koshland, 1958",
"Substrate binding induces conformational change in enzyme; cleft closes, "
"improving catalysis, improving co-substrate binding, excluding water",
"Currently accepted model"],
]
))
story.append(Spacer(1, 0.2*cm))
story.append(key_table(
["Stabilising Force", "Example in Glucokinase ES complex"],
[
["Hydrogen bonds", "Each -OH of glucose H-bonds to Asp, Asn, Glu, Gly residues"],
["Electrostatic interactions", "Charged Asp/Glu attract polar glucose -OH groups"],
["Hydrophobic interactions", "Non-polar regions of substrate near hydrophobic pockets"],
["Van der Waals forces", "Short-range attractive forces at close contact"],
["Transient covalent bonds", "Serine proteases (trypsin) — acyl-enzyme intermediate"],
]
))
story.append(Spacer(1, 0.2*cm))
story.append(vet_box(
"Veterinary Clinical Applications",
"Organophosphate (OP) poisoning (cattle, dogs, sheep from pesticide/dip tank exposure): "
"OP covalently binds Serine in active site of acetylcholinesterase (AChE) → ES complex "
"permanently blocked → ACh accumulates at synapses → SLUD signs "
"(Salivation, Lacrimation, Urination, Defaecation) + bradycardia, miosis, seizures. "
"Treatment: Atropine (competitive blocker) + Pralidoxime/2-PAM (reactivates AChE if given early)",
"Competitive enzyme inhibitors: Many drugs work by mimicking substrate to occupy active "
"site — e.g., allopurinol (xanthine oxidase inhibitor) used in Dalmatians for urate urolithiasis",
"Substrate specificity explained by ES complex: Glucokinase phosphorylates glucose but "
"NOT galactose (differs by one -OH) → explains galactosaemia pathology in calves",
"Km and Vmax: Derived from ES complex kinetics. High Km = weak substrate binding. "
"Low Km = tight binding = high affinity. Clinically, enzyme Km determines drug dosing "
"interactions in liver metabolism",
))
story.append(PageBreak())
# ════════════════════════════════════════════════════════════════
# BONUS — OXIDATIVE PHOSPHORYLATION
# ════════════════════════════════════════════════════════════════
story.append(section_header("BONUS: Oxidative Phosphorylation (OXPHOS)", HexColor("#5a1e82")))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph(
"<b>Definition:</b> Oxidative phosphorylation is the process by which ATP is synthesised "
"from ADP + Pi, driven by the energy of electron flow through the mitochondrial electron "
"transport chain (ETC) coupled to the proton-motive force (Mitchell's chemiosmotic theory).",
BODY_STYLE))
story.append(Spacer(1, 0.2*cm))
story.append(img("oxphos.png", width_cm=15))
story.append(Paragraph(
"Fig 8. Complete Oxidative Phosphorylation concept map and ETC diagram. "
"TCA + β-oxidation → NADH/FADH₂ → ETC (Complexes I-IV) → H⁺ pumped out → "
"gradient drives ATP synthase (Complex V). — Lippincott Biochemistry 8e, Fig. 6.18",
CAPTION_STYLE))
story.append(key_table(
["Complex", "Name", "Electron carrier", "H⁺ pumped", "Inhibitor"],
[
["I", "NADH-CoQ reductase", "NADH → FMN → Fe-S → CoQ", "4 H⁺", "Rotenone (insecticide); Amytal"],
["II", "Succinate-CoQ reductase", "FADH₂ → Fe-S → CoQ", "0 H⁺", "Malonate (competitive)"],
["III", "CoQ-Cyt c reductase", "CoQ → Cyt b → Fe-S → Cyt c₁ → Cyt c", "4 H⁺", "Antimycin A"],
["IV", "Cytochrome c oxidase", "Cyt c → CuA → Haem a → CuB/Haem a3 → O₂", "2 H⁺", "Cyanide, CO, Azide"],
["V", "ATP synthase (F₀F₁)", "H⁺ flows back in", "—", "Oligomycin (blocks F₀)"],
["Uncouplers", "Dissipate gradient without ATP", "DNP, Thermogenin (UCP1)", "—", "Heat produced instead of ATP"],
]
))
story.append(Spacer(1, 0.2*cm))
story.append(vet_box(
"Veterinary Clinical Applications — Oxidative Phosphorylation",
"Cyanide toxicity (cattle from sorghum/sudangrass/wild cherry leaves; dogs from "
"smoke inhalation): CN⁻ binds Complex IV (cytochrome oxidase) → blocks O₂ reduction "
"→ OXPHOS stops → histotoxic hypoxia → bright red venous blood (oxyHb not used). "
"Treatment: Sodium nitrite + sodium thiosulphate (cattle); hydroxocobalamin (dogs)",
"Carbon monoxide (CO) poisoning (animals in barn fires, faulty heaters): CO blocks "
"Complex IV + binds Hb → double impairment of O₂ delivery and utilisation",
"Rotenone: Natural insecticide/piscicide, inhibits Complex I. Toxic to fish and "
"insects; used in aquaculture. Toxic to dogs and cats if ingested",
"Thermogenin (UCP1) in brown adipose tissue: Present in neonatal lambs, piglets, "
"foals, calves — uncouples OXPHOS to generate heat instead of ATP. "
"Critical for thermoregulation at birth in cold environments",
"Mitochondrial myopathies in horses and dogs: Defects in ETC complexes → exercise "
"intolerance, lactic acidosis, muscle weakness",
"ATP yield summary: NADH=2.5 ATP, FADH₂=1.5 ATP; 1 glucose → ~30-32 ATP total",
))
story.append(PageBreak())
# ════════════════════════════════════════════════════════════════
# QUICK REVISION TABLE (last page)
# ════════════════════════════════════════════════════════════════
story.append(section_header("QUICK REVISION — Complete Summary Table", DARK_BLUE))
story.append(Spacer(1, 0.3*cm))
story.append(key_table(
["Topic", "Key Enzyme(s)", "Key Product(s)", "ATP Yield", "Vet Relevance"],
[
["Cori Cycle",
"LDH, Glucokinase, G6Pase",
"Glucose ↔ Lactate",
"Net −4 ATP",
"Exercise lactate; capture myopathy; neonatal asphyxia"],
["Transamination",
"ALT (GPT), AST (GOT)",
"Glutamate + α-keto acid",
"—",
"ALT elevated in dog/cat liver disease; AST in horse muscle/liver"],
["Oxidative Deamination",
"GDH (mitochondrial)",
"α-KG + NH₃ + NADH",
"+1 NADH",
"GDH elevated in ruminant hepatocellular necrosis; hepatic encephalopathy"],
["Temp/pH effects",
"All enzymes",
"Optimum bell curve",
"—",
"Rumen acidosis; heat stroke; pancreatitis in dogs"],
["β-Oxidation",
"Acyl-CoA DH, Enoyl hydratase, HADH, Thiolase",
"Acetyl-CoA + NADH + FADH₂",
"106 ATP (palmitate)",
"Ketosis (cows/ewes); feline hepatic lipidosis; carnitine deficiency"],
["TCA Cycle",
"Citrate synthase, Isocitrate DH, α-KG DH, Succinate DH, Malate DH",
"3NADH + 1FADH₂ + 1GTP + 2CO₂",
"~10 ATP/turn",
"Ketosis; fluoroacetate poisoning; thiamin deficiency; arsenic toxicity"],
["Glycogenolysis",
"Glycogen phosphorylase, Debranching enzyme, G6Pase",
"Glucose (liver) / G-6-P (muscle)",
"No ATP cost",
"Neonatal hypoglycaemia; GSD in Brahman cattle; diabetes mellitus"],
["ES Complex",
"Enzyme-specific",
"Transition state complex",
"—",
"OP poisoning (AChE inhibition); allopurinol in Dalmatians; drug interactions"],
["Oxidative Phosphorylation",
"Complexes I-IV + ATP Synthase (V)",
"ATP + H₂O",
"~30-32 ATP/glucose",
"Cyanide poisoning; CO toxicity; thermogenin in neonates; mitochondrial myopathy"],
]
))
story.append(Spacer(1, 0.5*cm))
story.append(Paragraph(
"<b>Sources:</b> Lippincott Illustrated Reviews Biochemistry 8e • "
"Harper's Illustrated Biochemistry 32e • Basic Medical Biochemistry 6e • "
"Guyton & Hall Textbook of Medical Physiology • Goldman-Cecil Medicine",
DATE_STYLE))
# ── BUILD ─────────────────────────────────────────────────────────
doc = SimpleDocTemplate(
OUT_PATH,
pagesize=A4,
leftMargin=2*cm, rightMargin=2*cm,
topMargin=2*cm, bottomMargin=2.5*cm,
title="Vet Biochemistry — Diagrams & Clinical Applications",
author="Orris AI",
subject="Veterinary Biochemistry Exam Reference",
)
doc.build(story, canvasmaker=NumberedCanvas)
print(f"PDF created: {OUT_PATH}")