Describe screening for urine inborn error and describe use of paper chromatography

Reading File
Finding Sources
Finding Sources
Finding Sources
Reading File
Reading File
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Reading File
Finding Sources
Loading Image
Finding Sources
Reading File
Reading File
I now have comprehensive information from multiple authoritative textbooks. Let me compile the full answer.

Screening for Urine Inborn Errors of Metabolism

Overview and Purpose

Many inborn errors of metabolism (IEM) cause severe mental retardation, seizures, or organ damage if treatment is delayed. Early detection - ideally in the neonatal period - allows dietary or pharmacological intervention before irreversible harm occurs. Screening targets conditions where an effective treatment exists and early intervention changes outcomes.
  • Park's Textbook of Preventive and Social Medicine
  • Harper's Illustrated Biochemistry, 32nd Ed.

Neonatal Blood Spot Screening (Guthrie Test)

The cornerstone of IEM screening in neonates is a heel-prick blood sample taken 6-10 days after birth (when affected enzymes have reached full expression). Three to four drops are blotted onto thick absorbent filter paper - these are called Guthrie cards or dried blood spots (DBS).
The Guthrie Bacterial Inhibition Test (the first IEM screening test):
  • A disc from the DBS paper is placed on an agar plate seeded with a phenylalanine-requiring strain of Bacillus subtilis, along with a competitive inhibitor (beta-thienylalanine) calibrated to block bacterial growth at normal blood phenylalanine levels.
  • If phenylalanine is elevated (as in phenylketonuria), it overcomes the inhibitor and bacteria form visible colonies.
  • The same DBS method can test for PKU, galactosaemia, and maple syrup urine disease (MSUD).
In most modern centres, the bacterial inhibition test has been superseded by chromatographic and tandem mass spectrometry (TMS/MS-MS) techniques that permit simultaneous detection of dozens of metabolites and a wide range of IEM.
  • Harper's Illustrated Biochemistry, 32nd Ed., p. 585
  • Park's Textbook of Preventive and Social Medicine

Urine Chemical Spot Tests

Before tandem mass spectrometry, a series of urine chemical spot (colorimetric) tests provided rapid, inexpensive first-line screening. These detect abnormal metabolites in urine and are still used in resource-limited settings or as adjuncts.
DiseaseFerric ChlorideDNPHBenedict ReactionNitroprusside
PhenylketonuriaGreen+--
Maple syrup urine diseaseNavy blue+--
TyrosinemiaPale green (transient)+-+
HistidinemiaGreen-brown±--
Propionic acidemiaPurple+--
Methylmalonic aciduriaPurple+--
Homocystinuria---+
Cystinuria---+
Galactosemia--+-
  • Ferric chloride test: Detects phenylpyruvic acid (PKU) and other keto acids; colour varies by metabolite.
  • DNPH (2,4-dinitrophenylhydrazine) test: Detects keto acids (positive in PKU, MSUD, tyrosinemia, organic acidaemias).
  • Benedict's reaction: Detects reducing sugars in urine (galactose in galactosaemia, fructose in fructosuria, glucose).
  • Nitroprusside reaction: Detects sulfhydryl groups - positive in homocystinuria and cystinuria.
  • Adams and Victor's Principles of Neurology, 12th Ed.

Conditions Commonly Screened

ConditionIncidence (per 100,000 births)
Phenylketonuria (PKU)6.6
Biotinidase deficiency5.4
Very long-chain acyl-CoA dehydrogenase deficiency3.3
Galactosemia1.5
Cobalamin (B12) deficiency1.3
Argininosuccinic aciduria1.0
Homocystinuria0.4
Maple syrup urine disease0.4
Data from New England Newborn Screening Program (tandem mass spectrometry of dried blood spot)
  • Adams and Victor's Principles of Neurology, 12th Ed.

Paper Chromatography for Urine IEM Screening

Principle

Paper chromatography is a type of planar (partition) chromatography in which the stationary phase is water held in cellulose fibres of filter paper, and the mobile phase is an organic solvent or solvent mixture. Compounds migrate at different rates depending on their relative solubility in the stationary vs. mobile phase.

The Retardation Factor (Rf)

The key measurement in paper chromatography is the Rf value:
Rf = Ds / Df
Where:
  • Ds = distance traveled by the compound from the point of application
  • Df = distance traveled by the solvent front in the same time
Rf values always fall between 0 and 1. A compound strongly retained by the stationary phase has a low Rf; one with little retention approaches 1.
Planar chromatography Rf diagram
Separation in planar chromatography: compound B is more retained (lower Rf) than compound A. Df = distance of solvent front; Ds = distance of analyte.
  • Tietz Textbook of Laboratory Medicine, 7th Ed.

Application to Urine Sugars and Metabolites

For urine sugar identification:
  • Urine is applied as a spot and subjected to ascending or descending chromatography on paper.
  • After migration, the paper is developed with dinitrosalicylic acid (or other reagents like ninhydrin for amino acids) to produce coloured bands.
  • Each sugar (glucose, galactose, fructose, lactose, etc.) has a characteristic Rf value in a given solvent system.
  • Presumptive identification is made by comparing the unknown's Rf to known reference compounds run simultaneously on the same sheet.
  • If Rf values match, detection properties (colour of bands, response to reagent) are compared for further confirmation.
  • When paper chromatography is performed infrequently, it is simple, adequate, and requires little actual working time. When frequent separations are needed, thin-layer chromatography (TLC) is preferred for its shorter run time.
  • One common setup uses a 6 x 18-inch Pyrex jar with a tightly fitting cover.
For amino acids (aminoacidurias):
  • Ninhydrin reagent is used to detect amino acids, producing characteristic purple/yellow spots.
  • Two-dimensional paper chromatography (running the chromatogram in two directions with two different solvents) improves resolution when many amino acids are present.
  • Abnormal patterns of amino acid spots indicate specific conditions (e.g., elevated phenylalanine in PKU, elevated leucine/isoleucine/valine in MSUD).
  • Tietz Textbook of Laboratory Medicine, 7th Ed.

Paper vs. Thin-Layer Chromatography

FeaturePaper ChromatographyThin-Layer Chromatography (TLC)
Stationary phaseCellulose paper (water-impregnated)Silica gel / alumina on glass or plastic
Time requiredLongerShorter
EquipmentSimple (jar with cover)Slightly more involved
Best useInfrequent separationsFrequent or high-throughput separations
ResolutionAdequate for most IEM screeningHigher

Modern Supersession

While paper chromatography and spot tests remain useful teaching tools and are used in resource-limited settings, they have been largely replaced by:
  • Tandem mass spectrometry (MS-MS): Simultaneously screens dozens of metabolites from a single DBS in minutes, detecting amino acidopathies, organic acidaemias, and fatty acid oxidation disorders.
  • HPLC amino acid analysis: Provides quantitative amino acid profiles.
  • Enzymatic assays: Specific for individual enzyme deficiencies (e.g., galactose-1-phosphate uridyltransferase for galactosaemia).
  • Harper's Illustrated Biochemistry, 32nd Ed.; Thompson & Thompson Genetics and Genomics in Medicine, 9th Ed.

Well elaborated, well described screening of urine for inborn error and describe use of paper chromatography for mbbs 1st year Biochemistry students lectures

Finding Sources
Finding Sources
Finding Sources
Finding Sources
Reading File
Reading File
Finding Sources
Finding Sources
Finding Sources
Reading File
Finding Sources
Reading File
Reading File
Loading Image
Loading Image

Well elaborated, well described pdf on lecture topic screening of urine for inborn error and describe use of paper chromatography for mbbs 1st year Biochemistry students lectures

Reading File
Reading File
Finding Sources
Finding Sources
Reading File
Reading File
Reading File
Finding Sources
Running Command

mkdir -p /home/daytona/workspace/iem-lecture && ls /home/daytona/workspace/iem-lecture/

Writing File

~/iem-lecture/build_lecture.py

"""
MBBS 1st Year Biochemistry Lecture PDF
Topic: Screening of Urine for Inborn Errors of Metabolism
        & Use of Paper Chromatography
"""

import json, subprocess, base64, os
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm, mm
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    PageBreak, HRFlowable, KeepTogether, Image
)
from reportlab.pdfgen import canvas
from reportlab.graphics.shapes import Drawing, Rect, String, Line, Circle, Polygon
from reportlab.graphics import renderPDF
from io import BytesIO

# ── colours ────────────────────────────────────────────────────────────────
DARK_BLUE   = colors.HexColor("#0D2B5E")
MED_BLUE    = colors.HexColor("#1565C0")
LIGHT_BLUE  = colors.HexColor("#E3F2FD")
ACCENT      = colors.HexColor("#FF6F00")
TEAL        = colors.HexColor("#00695C")
LIGHT_TEAL  = colors.HexColor("#E0F2F1")
GOLD        = colors.HexColor("#F9A825")
LIGHT_GOLD  = colors.HexColor("#FFFDE7")
RED         = colors.HexColor("#C62828")
LIGHT_RED   = colors.HexColor("#FFEBEE")
PURPLE      = colors.HexColor("#6A1B9A")
LIGHT_GREY  = colors.HexColor("#F5F5F5")
MID_GREY    = colors.HexColor("#BDBDBD")
WHITE       = colors.white
BLACK       = colors.black

W, H = A4   # 595 x 842 pt

# ── page template ──────────────────────────────────────────────────────────
def on_page(c, doc):
    c.saveState()
    # header bar
    c.setFillColor(DARK_BLUE)
    c.rect(0, H - 28, W, 28, fill=1, stroke=0)
    c.setFillColor(WHITE)
    c.setFont("Helvetica-Bold", 8)
    c.drawString(15, H - 18, "MBBS 1st Year Biochemistry  |  Inborn Errors & Paper Chromatography")
    c.setFont("Helvetica", 8)
    c.drawRightString(W - 15, H - 18, f"Page {doc.page}")
    # footer bar
    c.setFillColor(DARK_BLUE)
    c.rect(0, 0, W, 22, fill=1, stroke=0)
    c.setFillColor(GOLD)
    c.setFont("Helvetica-Bold", 7)
    c.drawCentredString(W / 2, 7, "Harper's Biochemistry 32e  |  Tietz Laboratory Medicine 7e  |  Adams & Victor Neurology 12e")
    c.restoreState()

def on_first_page(c, doc):
    pass   # cover draws itself

# ── styles ─────────────────────────────────────────────────────────────────
base = getSampleStyleSheet()

def S(name, **kw):
    return ParagraphStyle(name, **kw)

sTitle = S("sTitle", fontName="Helvetica-Bold", fontSize=26,
           textColor=WHITE, alignment=TA_CENTER, leading=32)
sSubTitle = S("sSubTitle", fontName="Helvetica", fontSize=14,
              textColor=GOLD, alignment=TA_CENTER, leading=20)
sInst = S("sInst", fontName="Helvetica-Oblique", fontSize=11,
          textColor=WHITE, alignment=TA_CENTER, leading=16)

sH1 = S("sH1", fontName="Helvetica-Bold", fontSize=15,
        textColor=WHITE, backColor=DARK_BLUE,
        borderPad=(6, 8, 6, 8), leading=20,
        spaceAfter=6, spaceBefore=14)
sH2 = S("sH2", fontName="Helvetica-Bold", fontSize=12,
        textColor=DARK_BLUE, borderPad=2, leading=16,
        spaceAfter=4, spaceBefore=10,
        borderWidth=0, borderColor=DARK_BLUE,
        leftIndent=0)
sH3 = S("sH3", fontName="Helvetica-Bold", fontSize=10,
        textColor=TEAL, leading=14,
        spaceAfter=3, spaceBefore=8)
sBody = S("sBody", fontName="Helvetica", fontSize=10,
          leading=15, spaceAfter=4, alignment=TA_JUSTIFY)
sBullet = S("sBullet", fontName="Helvetica", fontSize=10,
            leading=14, leftIndent=14, firstLineIndent=-10,
            spaceAfter=2)
sNote = S("sNote", fontName="Helvetica-Oblique", fontSize=9,
          textColor=colors.HexColor("#5D4037"), leading=13,
          backColor=LIGHT_GOLD, borderPad=4, spaceAfter=4)
sMnemonic = S("sMnemonic", fontName="Helvetica-Bold", fontSize=11,
              textColor=PURPLE, alignment=TA_CENTER, leading=16,
              backColor=colors.HexColor("#F3E5F5"), borderPad=6,
              spaceAfter=6)
sKeyPoint = S("sKeyPoint", fontName="Helvetica-Bold", fontSize=10,
              textColor=RED, leading=14, leftIndent=14, firstLineIndent=-10,
              spaceAfter=2)
sCite = S("sCite", fontName="Helvetica-Oblique", fontSize=8,
          textColor=MID_GREY, leading=11, spaceAfter=2)

def bullet(text, style=sBullet):
    return Paragraph(f"•   {text}", style)

def key(text):
    return Paragraph(f"✔   {text}", sKeyPoint)

def h1(text):
    return Paragraph(f"  {text}", sH1)

def h2(text):
    return Paragraph(text, sH2)

def h3(text):
    return Paragraph(text, sH3)

def body(text):
    return Paragraph(text, sBody)

def note(text):
    return Paragraph(f"<b>Note:</b> {text}", sNote)

def cite(text):
    return Paragraph(f"<i>{text}</i>", sCite)

def sp(n=6):
    return Spacer(1, n)

def hr():
    return HRFlowable(width="100%", thickness=0.5, color=MID_GREY, spaceAfter=4, spaceBefore=4)

# ── cover page (canvas-drawn) ───────────────────────────────────────────────
def draw_cover(c, doc):
    c.saveState()
    # background gradient (two rects)
    c.setFillColor(DARK_BLUE)
    c.rect(0, 0, W, H, fill=1, stroke=0)
    c.setFillColor(MED_BLUE)
    c.rect(0, H * 0.35, W, H * 0.65, fill=1, stroke=0)

    # decorative circles
    c.setFillColor(colors.HexColor("#1A3A7A"))
    c.circle(W - 60, H - 60, 100, fill=1, stroke=0)
    c.setFillColor(colors.HexColor("#0A1F4A"))
    c.circle(60, 80, 80, fill=1, stroke=0)

    # accent stripe
    c.setFillColor(GOLD)
    c.rect(0, H * 0.35 - 4, W, 8, fill=1, stroke=0)

    # title block
    c.setFillColor(WHITE)
    c.setFont("Helvetica-Bold", 9)
    c.drawCentredString(W / 2, H - 55, "MBBS 1st YEAR  |  BIOCHEMISTRY")
    c.setFont("Helvetica-Bold", 11)
    c.setFillColor(GOLD)
    c.drawCentredString(W / 2, H - 72, "LECTURE NOTES")

    # main title
    c.setFillColor(WHITE)
    c.setFont("Helvetica-Bold", 22)
    c.drawCentredString(W / 2, H * 0.72, "Screening of Urine for")
    c.drawCentredString(W / 2, H * 0.72 - 30, "Inborn Errors of Metabolism")
    c.setFillColor(GOLD)
    c.setFont("Helvetica-Bold", 15)
    c.drawCentredString(W / 2, H * 0.72 - 62, "& Paper Chromatography")

    # divider
    c.setStrokeColor(GOLD)
    c.setLineWidth(1.5)
    c.line(60, H * 0.53, W - 60, H * 0.53)

    # subtitle info boxes
    info = [
        ("SUBJECT", "Biochemistry"),
        ("YEAR", "MBBS 1st Year"),
        ("TOPIC", "IEM Screening + Chromatography"),
    ]
    bw = (W - 80) / 3
    by = H * 0.40
    for i, (label, val) in enumerate(info):
        bx = 40 + i * bw
        c.setFillColor(colors.HexColor("#102D6B"))
        c.roundRect(bx, by, bw - 8, 50, 6, fill=1, stroke=0)
        c.setFillColor(GOLD)
        c.setFont("Helvetica-Bold", 7)
        c.drawCentredString(bx + (bw - 8) / 2, by + 35, label)
        c.setFillColor(WHITE)
        c.setFont("Helvetica-Bold", 9)
        c.drawCentredString(bx + (bw - 8) / 2, by + 18, val)

    # bottom reference text
    c.setFillColor(WHITE)
    c.setFont("Helvetica", 8)
    c.drawCentredString(W / 2, 60, "Sources: Harper's Illustrated Biochemistry 32e  |  Tietz Laboratory Medicine 7e")
    c.drawCentredString(W / 2, 48, "Adams & Victor's Principles of Neurology 12e  |  Park's Preventive Medicine")
    c.setFillColor(GOLD)
    c.setFont("Helvetica-Bold", 8)
    c.drawCentredString(W / 2, 30, "orris.care  |  Medical Knowledge Platform")
    c.restoreStore = c.restoreState
    c.restoreState()


# ── diagram helpers ─────────────────────────────────────────────────────────

def make_guthrie_diagram():
    """Simple schematic of the Guthrie test."""
    d = Drawing(440, 120)
    # agar plate
    d.add(Circle(80, 60, 55, fillColor=colors.HexColor("#FFF9C4"), strokeColor=colors.HexColor("#827717"), strokeWidth=1.5))
    d.add(String(80, 118, "Agar Plate", textAnchor="middle", fontSize=8, fillColor=DARK_BLUE, fontName="Helvetica-Bold"))
    d.add(String(80, 40, "B. subtilis", textAnchor="middle", fontSize=7, fillColor=TEAL, fontName="Helvetica-Oblique"))
    d.add(String(80, 28, "+ β-thienylalanine", textAnchor="middle", fontSize=7, fillColor=RED, fontName="Helvetica"))

    # DBS disk
    d.add(Circle(80, 60, 12, fillColor=colors.HexColor("#FFCDD2"), strokeColor=RED, strokeWidth=1))
    d.add(String(80, 62, "DBS", textAnchor="middle", fontSize=6, fillColor=RED, fontName="Helvetica-Bold"))

    # arrow
    d.add(Line(150, 60, 200, 60, strokeColor=DARK_BLUE, strokeWidth=1.5))
    d.add(Polygon([200, 60, 194, 55, 194, 65], fillColor=DARK_BLUE, strokeColor=DARK_BLUE))
    d.add(String(175, 65, "Result?", textAnchor="middle", fontSize=7, fillColor=DARK_BLUE, fontName="Helvetica-Bold"))

    # normal result
    d.add(Circle(250, 60, 45, fillColor=colors.HexColor("#E8F5E9"), strokeColor=TEAL, strokeWidth=1.5))
    d.add(String(250, 100, "NORMAL", textAnchor="middle", fontSize=8, fillColor=TEAL, fontName="Helvetica-Bold"))
    d.add(String(250, 60, "No bacterial", textAnchor="middle", fontSize=7, fillColor=TEAL, fontName="Helvetica"))
    d.add(String(250, 48, "growth", textAnchor="middle", fontSize=7, fillColor=TEAL, fontName="Helvetica"))
    d.add(String(250, 28, "Phe = normal", textAnchor="middle", fontSize=7, fillColor=TEAL, fontName="Helvetica"))

    # OR arrow
    d.add(String(320, 63, "OR", textAnchor="middle", fontSize=9, fillColor=DARK_BLUE, fontName="Helvetica-Bold"))

    # PKU result
    d.add(Circle(390, 60, 45, fillColor=colors.HexColor("#FFEBEE"), strokeColor=RED, strokeWidth=1.5))
    d.add(String(390, 100, "PKU +ve", textAnchor="middle", fontSize=8, fillColor=RED, fontName="Helvetica-Bold"))
    # bacterial colonies
    for cx, cy in [(378,65),(395,72),(388,55),(400,60),(375,52)]:
        d.add(Circle(cx, cy, 4, fillColor=RED, strokeColor=colors.HexColor("#B71C1C"), strokeWidth=0.5))
    d.add(String(390, 28, "Phe > normal", textAnchor="middle", fontSize=7, fillColor=RED, fontName="Helvetica"))

    return d


def make_paper_chrom_diagram():
    """Ascending paper chromatography schematic."""
    d = Drawing(440, 160)
    # tank outline
    d.add(Rect(30, 10, 180, 140, fillColor=colors.HexColor("#E3F2FD"),
               strokeColor=DARK_BLUE, strokeWidth=1.5))
    d.add(String(120, 155, "Chromatography Tank (closed)", textAnchor="middle",
                 fontSize=8, fillColor=DARK_BLUE, fontName="Helvetica-Bold"))
    # solvent pool
    d.add(Rect(30, 10, 180, 20, fillColor=colors.HexColor("#B3E5FC"),
               strokeColor=MED_BLUE, strokeWidth=0.5))
    d.add(String(120, 18, "Solvent (mobile phase)", textAnchor="middle",
                 fontSize=7, fillColor=MED_BLUE, fontName="Helvetica-Bold"))
    # paper strip
    d.add(Rect(90, 10, 60, 135, fillColor=colors.HexColor("#FFFDE7"),
               strokeColor=colors.HexColor("#827717"), strokeWidth=1))
    # sample spots at baseline
    d.add(Circle(110, 32, 5, fillColor=colors.HexColor("#6A1B9A"), strokeColor=PURPLE, strokeWidth=0.5))
    d.add(Circle(130, 32, 5, fillColor=colors.HexColor("#6A1B9A"), strokeColor=PURPLE, strokeWidth=0.5))
    d.add(String(120, 22, "Samples", textAnchor="middle", fontSize=6, fillColor=PURPLE, fontName="Helvetica-Bold"))
    # separated spots - compound A (high Rf)
    d.add(Circle(110, 100, 6, fillColor=colors.HexColor("#1565C0"), strokeColor=MED_BLUE, strokeWidth=0.5))
    d.add(String(77, 102, "A", textAnchor="middle", fontSize=7, fillColor=MED_BLUE, fontName="Helvetica-Bold"))
    # separated spots - compound B (low Rf)
    d.add(Circle(130, 72, 6, fillColor=colors.HexColor("#C62828"), strokeColor=RED, strokeWidth=0.5))
    d.add(String(163, 74, "B", textAnchor="middle", fontSize=7, fillColor=RED, fontName="Helvetica-Bold"))
    # solvent front
    d.add(Line(90, 125, 150, 125, strokeColor=TEAL, strokeWidth=1.5, strokeDashArray=[3,2]))
    d.add(String(163, 127, "Solvent front (Df)", fontSize=7, fillColor=TEAL, fontName="Helvetica-Oblique"))
    # Ds arrow for A
    d.add(Line(70, 32, 70, 100, strokeColor=MED_BLUE, strokeWidth=1))
    d.add(Polygon([70,100,66,92,74,92], fillColor=MED_BLUE, strokeColor=MED_BLUE))
    d.add(String(58, 66, "Ds(A)", textAnchor="middle", fontSize=6, fillColor=MED_BLUE, fontName="Helvetica-Bold"))

    # Rf formula box
    d.add(Rect(240, 70, 175, 70, fillColor=LIGHT_BLUE, strokeColor=MED_BLUE, strokeWidth=1, rx=6, ry=6))
    d.add(String(327, 133, "Retardation Factor (Rf)", textAnchor="middle",
                 fontSize=9, fillColor=DARK_BLUE, fontName="Helvetica-Bold"))
    d.add(Line(255, 125, 400, 125, strokeColor=MID_GREY, strokeWidth=0.5))
    d.add(String(327, 108, "Rf  =  Ds / Df", textAnchor="middle",
                 fontSize=13, fillColor=RED, fontName="Helvetica-Bold"))
    d.add(String(327, 92, "Ds = distance of compound", textAnchor="middle",
                 fontSize=7, fillColor=DARK_BLUE, fontName="Helvetica"))
    d.add(String(327, 80, "Df = distance of solvent front", textAnchor="middle",
                 fontSize=7, fillColor=DARK_BLUE, fontName="Helvetica"))

    # Rf values box
    d.add(Rect(240, 10, 175, 55, fillColor=LIGHT_TEAL, strokeColor=TEAL, strokeWidth=1, rx=6, ry=6))
    d.add(String(327, 58, "Rf is always 0 to 1", textAnchor="middle",
                 fontSize=8, fillColor=TEAL, fontName="Helvetica-Bold"))
    d.add(String(327, 45, "High Rf = moves far = less retained", textAnchor="middle",
                 fontSize=7, fillColor=TEAL, fontName="Helvetica"))
    d.add(String(327, 33, "Low Rf = moves little = more retained", textAnchor="middle",
                 fontSize=7, fillColor=TEAL, fontName="Helvetica"))
    d.add(String(327, 18, "Each compound has a FIXED Rf in given solvent", textAnchor="middle",
                 fontSize=7, fillColor=TEAL, fontName="Helvetica"))

    return d


def make_workflow_diagram():
    """Urine IEM screening workflow flowchart."""
    d = Drawing(440, 200)
    boxes = [
        (10,  165, "Newborn (Day 6-10)",         DARK_BLUE, WHITE),
        (10,  115, "Heel-Prick Blood Sample",    MED_BLUE,  WHITE),
        (10,   65, "Dried Blood Spot (DBS)\non Guthrie Card", TEAL, WHITE),
        (10,   15, "Laboratory Analysis",        TEAL, WHITE),
    ]
    bw, bh = 190, 40
    for (bx, by, txt, bg, fg) in boxes:
        d.add(Rect(bx, by, bw, bh, fillColor=bg, strokeColor=WHITE, strokeWidth=0.5, rx=5, ry=5))
        lines = txt.split("\n")
        if len(lines) == 1:
            d.add(String(bx + bw/2, by + bh/2 - 4, txt, textAnchor="middle",
                         fontSize=9, fillColor=fg, fontName="Helvetica-Bold"))
        else:
            d.add(String(bx + bw/2, by + bh/2 + 3, lines[0], textAnchor="middle",
                         fontSize=8, fillColor=fg, fontName="Helvetica-Bold"))
            d.add(String(bx + bw/2, by + bh/2 - 8, lines[1], textAnchor="middle",
                         fontSize=8, fillColor=fg, fontName="Helvetica-Bold"))
    # arrows
    for y in [155, 105, 55]:
        d.add(Line(105, y, 105, y - 8, strokeColor=GOLD, strokeWidth=2))
        d.add(Polygon([105, y-8, 100, y], fillColor=GOLD, strokeColor=GOLD))

    # methods box on right
    d.add(Rect(220, 10, 210, 185, fillColor=LIGHT_GOLD, strokeColor=GOLD, strokeWidth=1.2, rx=6, ry=6))
    d.add(String(325, 192, "Screening Methods", textAnchor="middle",
                 fontSize=10, fillColor=DARK_BLUE, fontName="Helvetica-Bold"))
    methods = [
        ("1.", "Guthrie Bacterial Inhibition Test",    "First test ever developed"),
        ("2.", "Urine Chemical Spot Tests",            "FeCl3, DNPH, Benedict, Nitroprusside"),
        ("3.", "Paper Chromatography",                 "Amino acids & sugars in urine"),
        ("4.", "Tandem Mass Spectrometry (TMS)",       "Gold standard - 50+ disorders"),
    ]
    y = 165
    for num, title, sub in methods:
        d.add(String(228, y, num, fontSize=8, fillColor=DARK_BLUE, fontName="Helvetica-Bold"))
        d.add(String(240, y, title, fontSize=8, fillColor=DARK_BLUE, fontName="Helvetica-Bold"))
        d.add(String(240, y - 11, sub, fontSize=7, fillColor=TEAL, fontName="Helvetica-Oblique"))
        y -= 38

    return d


# ── colour-coded urine test table ────────────────────────────────────────────

def make_spot_test_table():
    col_widths = [115, 65, 50, 70, 85]
    header = ["Disease", "FeCl3 Test", "DNPH", "Benedict's", "Nitroprusside"]
    rows = [
        ["Phenylketonuria (PKU)",     "Green",              "+",  "−", "−"],
        ["Maple Syrup Urine Disease", "Navy Blue",          "+",  "−", "−"],
        ["Tyrosinemia",               "Pale Green (trans)", "+",  "−", "+"],
        ["Histidinemia",              "Green-Brown",        "±",  "−", "−"],
        ["Propionic Acidemia",        "Purple",             "+",  "−", "−"],
        ["Methylmalonic Aciduria",    "Purple",             "+",  "−", "−"],
        ["Homocystinuria",            "−",                  "−",  "−", "+"],
        ["Cystinuria",                "−",                  "−",  "−", "+"],
        ["Galactosemia",              "−",                  "−",  "+", "−"],
        ["Alkaptonuria",              "Dark Brown/Black",   "−",  "−", "−"],
    ]
    data = [header] + rows
    # colour FeCl3 cells
    fecl3_colours = {
        "Green":              colors.HexColor("#A5D6A7"),
        "Navy Blue":          colors.HexColor("#90CAF9"),
        "Pale Green (trans)": colors.HexColor("#C8E6C9"),
        "Green-Brown":        colors.HexColor("#A5D6A7"),
        "Purple":             colors.HexColor("#CE93D8"),
        "Dark Brown/Black":   colors.HexColor("#BCAAA4"),
        "−":                  colors.HexColor("#EEEEEE"),
    }
    t = Table(data, colWidths=col_widths)
    style = TableStyle([
        ("BACKGROUND",   (0, 0), (-1, 0),  DARK_BLUE),
        ("TEXTCOLOR",    (0, 0), (-1, 0),  WHITE),
        ("FONTNAME",     (0, 0), (-1, 0),  "Helvetica-Bold"),
        ("FONTSIZE",     (0, 0), (-1, 0),  9),
        ("ALIGN",        (0, 0), (-1, 0),  "CENTER"),
        ("FONTNAME",     (0, 1), (-1, -1), "Helvetica"),
        ("FONTSIZE",     (0, 1), (-1, -1), 8),
        ("ALIGN",        (1, 1), (-1, -1), "CENTER"),
        ("GRID",         (0, 0), (-1, -1), 0.4, colors.HexColor("#BDBDBD")),
        ("ROWBACKGROUNDS", (0, 1), (-1, -1), [WHITE, LIGHT_GREY]),
        ("TOPPADDING",   (0, 0), (-1, -1), 4),
        ("BOTTOMPADDING",(0, 0), (-1, -1), 4),
        ("LEFTPADDING",  (0, 0), (-1, -1), 4),
    ])
    # colour individual FeCl3 cells
    for i, row in enumerate(rows, start=1):
        colour = fecl3_colours.get(row[1], WHITE)
        style.add("BACKGROUND", (1, i), (1, i), colour)
    t.setStyle(style)
    return t


def make_disorder_freq_table():
    col_widths = [230, 150]
    header = ["Disorder", "Frequency (per 100,000 births)"]
    rows = [
        ["Phenylketonuria (PKU)",                       "6.6"],
        ["Biotinidase Deficiency",                      "5.4"],
        ["Very Long-Chain Acyl-CoA Dehydrogenase Def.", "3.3"],
        ["Galactosemia",                                "1.5"],
        ["Cobalamin Deficiency",                        "1.3"],
        ["Argininosuccinic Aciduria",                   "1.0"],
        ["Isovaleric Acidemia",                         "0.8"],
        ["Long-chain Hydroxyacyl-CoA Dehydrogenase",    "0.8"],
        ["Methylmalonic Aciduria",                      "0.5"],
        ["Maple Syrup Urine Disease (MSUD)",            "0.4"],
        ["Homocystinuria",                              "0.4"],
        ["Glutaric Aciduria Type I",                    "0.4"],
    ]
    data = [header] + rows
    t = Table(data, colWidths=col_widths)
    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, 0),  9),
        ("ALIGN",         (1, 0), (1, -1),  "CENTER"),
        ("FONTNAME",      (0, 1), (-1, -1), "Helvetica"),
        ("FONTSIZE",      (0, 1), (-1, -1), 8),
        ("GRID",          (0, 0), (-1, -1), 0.4, MID_GREY),
        ("ROWBACKGROUNDS",(0, 1), (-1, -1), [WHITE, LIGHT_TEAL]),
        ("TOPPADDING",    (0, 0), (-1, -1), 4),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 4),
        ("LEFTPADDING",   (0, 0), (-1, -1), 4),
    ]))
    return t


def make_pc_vs_tlc_table():
    col_widths = [120, 155, 155]
    header = ["Feature", "Paper Chromatography", "Thin-Layer Chromatography (TLC)"]
    rows = [
        ["Stationary Phase", "Water on cellulose paper", "Silica/alumina on glass/plastic"],
        ["Mobile Phase",     "Organic solvent mixture",  "Organic solvent mixture"],
        ["Time Required",    "Longer (hours)",            "Shorter (30-60 min)"],
        ["Equipment",        "Simple - jar + lid",        "TLC tank + plates"],
        ["Resolution",       "Adequate for most IEM",     "Higher resolution"],
        ["Cost",             "Very inexpensive",          "Slightly more expensive"],
        ["Best Use",         "Infrequent testing",        "Frequent / high-throughput"],
        ["Detection",        "Ninhydrin / dinitrosalicylic acid", "Same reagents"],
    ]
    data = [header] + rows
    t = Table(data, colWidths=col_widths)
    t.setStyle(TableStyle([
        ("BACKGROUND",    (0, 0), (-1, 0),  PURPLE),
        ("TEXTCOLOR",     (0, 0), (-1, 0),  WHITE),
        ("FONTNAME",      (0, 0), (-1, 0),  "Helvetica-Bold"),
        ("FONTSIZE",      (0, 0), (-1, 0),  9),
        ("FONTNAME",      (0, 1), (-1, -1), "Helvetica"),
        ("FONTSIZE",      (0, 1), (-1, -1), 8),
        ("FONTNAME",      (0, 1), (0, -1),  "Helvetica-Bold"),
        ("GRID",          (0, 0), (-1, -1), 0.4, MID_GREY),
        ("ROWBACKGROUNDS",(0, 1), (-1, -1), [WHITE, colors.HexColor("#F3E5F5")]),
        ("TOPPADDING",    (0, 0), (-1, -1), 4),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 4),
        ("LEFTPADDING",   (0, 0), (-1, -1), 4),
    ]))
    return t


def make_criteria_table():
    col_widths = [80, 310]
    header = ["Criterion", "Requirement"]
    rows = [
        ["Disease",     "Common enough to justify mass screening"],
        ["Test",        "Simple, reliable, cheap, high sensitivity & specificity"],
        ["Treatment",   "Effective treatment must be available"],
        ["Timing",      "Early treatment must prevent disease consequences"],
        ["Screening",   "Acceptable to population being screened"],
    ]
    data = [header] + rows
    t = Table(data, colWidths=col_widths)
    t.setStyle(TableStyle([
        ("BACKGROUND",    (0, 0), (-1, 0),  ACCENT),
        ("TEXTCOLOR",     (0, 0), (-1, 0),  WHITE),
        ("FONTNAME",      (0, 0), (-1, 0),  "Helvetica-Bold"),
        ("FONTSIZE",      (0, 0), (-1, 0),  9),
        ("FONTNAME",      (0, 1), (-1, -1), "Helvetica"),
        ("FONTSIZE",      (0, 1), (-1, -1), 9),
        ("FONTNAME",      (0, 1), (0, -1),  "Helvetica-Bold"),
        ("GRID",          (0, 0), (-1, -1), 0.4, MID_GREY),
        ("ROWBACKGROUNDS",(0, 1), (-1, -1), [WHITE, LIGHT_GOLD]),
        ("TOPPADDING",    (0, 0), (-1, -1), 5),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 5),
        ("LEFTPADDING",   (0, 0), (-1, -1), 5),
    ]))
    return t


# ── box helper ──────────────────────────────────────────────────────────────
def coloured_box(content_list, bg=LIGHT_BLUE, border=MED_BLUE, padding=8):
    """Wrap a list of flowables in a single-cell table to simulate a coloured box."""
    inner = Table([[c] for c in content_list], colWidths=[440])
    inner.setStyle(TableStyle([
        ("BACKGROUND",    (0, 0), (-1, -1), bg),
        ("BOX",           (0, 0), (-1, -1), 1.2, border),
        ("LEFTPADDING",   (0, 0), (-1, -1), padding),
        ("RIGHTPADDING",  (0, 0), (-1, -1), padding),
        ("TOPPADDING",    (0, 0), (0,  0),  padding),
        ("BOTTOMPADDING", (0,-1), (-1,-1),  padding),
    ]))
    return inner


# ── build story ─────────────────────────────────────────────────────────────
def build_story():
    story = []

    # ── PAGE 1: Cover (blank - drawn by on_first_page via canvas) ──────────
    # We add a blank page for the cover, drawn separately
    story.append(Spacer(1, H))  # placeholder - actual drawing in on_first_page

    # ── PAGE 2: Learning Objectives & Overview ──────────────────────────────
    story.append(PageBreak())
    story.append(h1("LEARNING OBJECTIVES"))
    story.append(sp(8))
    story.append(body(
        "By the end of this lecture, the MBBS 1st year student should be able to:"
    ))
    story.append(sp(4))
    objectives = [
        "Define inborn errors of metabolism (IEM) and explain why early screening is essential.",
        "Describe the Guthrie bacterial inhibition test - its principle, procedure, and significance.",
        "List the common urine chemical spot tests (FeCl3, DNPH, Benedict's, Nitroprusside) and interpret their results for major IEM diseases.",
        "Explain the principle of paper chromatography including the concept of Rf value.",
        "Describe the step-by-step procedure of ascending paper chromatography for urine amino acids and sugars.",
        "Compare paper chromatography with thin-layer chromatography (TLC).",
        "Recognise the role of modern techniques (tandem mass spectrometry) in replacing older screening methods.",
    ]
    for i, obj in enumerate(objectives, 1):
        story.append(Paragraph(f"<b>{i}.</b>&nbsp; {obj}", sBullet))
    story.append(sp(10))

    story.append(h1("SECTION 1: INBORN ERRORS OF METABOLISM - AN OVERVIEW"))
    story.append(sp(8))
    story.append(h2("1.1 Definition"))
    story.append(body(
        "<b>Inborn errors of metabolism (IEM)</b> are a large group of inherited (usually autosomal recessive) "
        "biochemical disorders in which a specific enzyme deficiency disrupts a normal metabolic pathway. "
        "The result is either: (a) accumulation of a toxic substrate, (b) deficiency of an essential product, "
        "or (c) diversion into an abnormal pathway, each causing characteristic clinical features."
    ))
    story.append(sp(4))
    story.append(h2("1.2 Why Screen?"))
    story.append(body(
        "Many IEM cause <b>irreversible brain damage, mental retardation, and death</b> if undetected. "
        "For conditions like Phenylketonuria (PKU) and Maple Syrup Urine Disease (MSUD), a simple "
        "<b>dietary restriction</b> started within days of birth is all that is needed to prevent "
        "catastrophic neurological damage. Screening allows intervention BEFORE symptoms appear."
    ))
    story.append(sp(6))
    story.append(h2("1.3 Wilson's Criteria for a Screening Programme"))
    story.append(sp(4))
    story.append(make_criteria_table())
    story.append(sp(4))
    story.append(cite("Source: Park's Textbook of Preventive and Social Medicine"))
    story.append(sp(8))

    story.append(h2("1.4 Timing of Sample Collection"))
    story.append(body(
        "Blood is usually collected at <b>6-10 days of age</b> by heel prick. "
        "This delay is deliberate: the affected enzymes must have reached full expression "
        "so that metabolite levels are detectably elevated. Collecting too early (e.g., day 1-2) "
        "may give false negatives. A capillary blood sample is blotted onto <b>thick absorbent "
        "filter paper (Guthrie card)</b> and sent to the laboratory."
    ))
    story.append(sp(6))
    story.append(note(
        "The Guthrie card (dried blood spot / DBS) is the universal sample type for neonatal IEM screening. "
        "The same card can be used for PKU, galactosaemia, MSUD, congenital hypothyroidism, and more."
    ))

    # ── PAGE 3: Guthrie Test & Chemical Tests ──────────────────────────────
    story.append(PageBreak())
    story.append(h1("SECTION 2: SCREENING TESTS FOR URINE / BLOOD IEM"))
    story.append(sp(8))
    story.append(h2("2.1 The Guthrie Bacterial Inhibition Test"))
    story.append(sp(4))
    story.append(body(
        "Developed by Robert Guthrie in 1963, this was the <b>first mass screening test</b> for an inborn "
        "error of metabolism. It screens for <b>Phenylketonuria (PKU)</b>."
    ))
    story.append(sp(6))
    story.append(h3("Principle:"))
    story.append(body(
        "A strain of <i>Bacillus subtilis</i> that <b>requires phenylalanine (Phe)</b> to grow is seeded onto "
        "agar. A competitive inhibitor of Phe uptake, <b>beta-thienylalanine</b>, is added at a concentration "
        "that prevents bacterial growth at normal blood Phe levels."
    ))
    story.append(sp(4))
    story.append(h3("Procedure:"))
    steps = [
        "Heel-prick blood is blotted onto filter paper (DBS card).",
        "A small disc is punched from the DBS card and placed on the inhibitor-seeded agar plate.",
        "The plate is incubated at 37°C overnight.",
        "Results are read the next day.",
    ]
    for s in steps:
        story.append(bullet(s))
    story.append(sp(6))
    story.append(h3("Interpretation:"))
    story.append(bullet("<b>No bacterial growth</b> around disc = Normal Phe level = Negative (screen negative)"))
    story.append(bullet("<b>Visible bacterial colonies</b> around disc = Elevated Phe = Positive (screen positive for PKU)"))
    story.append(sp(8))

    # Guthrie diagram
    story.append(KeepTogether([
        h3("Diagrammatic Representation of Guthrie Test:"),
        sp(6),
        renderPDF.GraphicsFlowable(make_guthrie_diagram()),
        sp(4),
        cite("Adapted from Harper's Illustrated Biochemistry 32e, p. 585"),
    ]))
    story.append(sp(8))

    story.append(h3("Limitations of the Guthrie Test:"))
    story.append(bullet("Detects only PKU; cannot screen for other IEM."))
    story.append(bullet("Qualitative, not quantitative."))
    story.append(bullet("Has been superseded by chromatographic and mass spectrometric methods in most modern centres."))
    story.append(sp(6))
    story.append(note(
        "The same DBS cards can be used to simultaneously screen for PKU, galactosaemia, and MSUD "
        "by testing different aliquots of the same card."
    ))

    # ── PAGE 4: Chemical Spot Tests ─────────────────────────────────────────
    story.append(PageBreak())
    story.append(h2("2.2 Urine Chemical Spot Tests"))
    story.append(sp(4))
    story.append(body(
        "These colorimetric tests are performed on a fresh urine sample. They are rapid, inexpensive, "
        "and require no special equipment. They serve as <b>first-line screening</b> in resource-limited "
        "settings or as confirmatory adjuncts. Each test detects a class of abnormal metabolites."
    ))
    story.append(sp(8))

    tests = [
        ("Ferric Chloride (FeCl3) Test",
         "A few drops of 10% ferric chloride are added to fresh urine. Phenylpyruvic acid "
         "(from PKU) gives an immediate deep-green colour. Different metabolites give different colours.",
         LIGHT_BLUE, MED_BLUE),
        ("DNPH Test (2,4-Dinitrophenylhydrazine)",
         "Detects alpha-keto acids in urine. Positive (yellow-orange precipitate) in PKU, MSUD, "
         "tyrosinemia, organic acidaemias. Principle: DNPH reacts with the keto group.",
         LIGHT_GOLD, GOLD),
        ("Benedict's Reaction",
         "Detects reducing sugars in urine (glucose, galactose, fructose, lactose). Positive "
         "(brick-red precipitate) in galactosaemia, fructosuria, and glucosuria. "
         "Principle: Cu2+ reduced to Cu2O by reducing sugars.",
         LIGHT_TEAL, TEAL),
        ("Nitroprusside (Legal's) Reaction",
         "Detects sulfhydryl (-SH) groups. Positive (magenta/purple colour) in homocystinuria "
         "and cystinuria. Also detects ketone bodies (acetonuria).",
         LIGHT_RED, RED),
    ]
    for test_name, test_desc, bg, border in tests:
        story.append(KeepTogether([
            h3(f"• {test_name}"),
            body(test_desc),
            sp(4),
        ]))

    story.append(sp(6))
    story.append(h2("2.3 Summary Table: Chemical Spot Tests in IEM"))
    story.append(sp(4))
    story.append(make_spot_test_table())
    story.append(sp(4))
    story.append(cite("Source: Adams and Victor's Principles of Neurology 12e, Table 36-2"))
    story.append(sp(4))
    story.append(note(
        "Tandem mass spectrometry (TMS) has largely replaced these traditional tests for newborn "
        "screening in developed countries. However, chemical spot tests remain valuable in "
        "resource-limited settings and as teaching tools."
    ))

    # ── PAGE 5: Common IEM & Frequency ─────────────────────────────────────
    story.append(PageBreak())
    story.append(h2("2.4 Common IEM Detected by Neonatal Screening"))
    story.append(sp(4))
    story.append(body(
        "The following table shows disorders detected by tandem mass spectrometry of dried blood spots "
        "from the New England Newborn Screening Program:"
    ))
    story.append(sp(6))
    story.append(make_disorder_freq_table())
    story.append(sp(4))
    story.append(cite("Source: Adams and Victor's Principles of Neurology 12e, Table 36-1 (Dr. Inderneel Sahai, New England Newborn Screening Program)"))
    story.append(sp(8))

    story.append(h2("2.5 Key Individual Disorders"))
    story.append(sp(4))

    disorders = [
        ("Phenylketonuria (PKU)",
         "Deficiency: Phenylalanine hydroxylase (PAH)\n"
         "Accumulates: Phenylalanine → Phenylpyruvic acid in urine\n"
         "Features: Fair skin/hair, musty odour, seizures, severe mental retardation\n"
         "Screening: Guthrie test → FeCl3 green colour → HPLC\n"
         "Treatment: Low phenylalanine diet (life-long)",
         LIGHT_BLUE, MED_BLUE),
        ("Maple Syrup Urine Disease (MSUD)",
         "Deficiency: Branched-chain alpha-keto acid dehydrogenase\n"
         "Accumulates: Leucine, Isoleucine, Valine + their keto acids\n"
         "Features: Sweet/maple syrup smell of urine, encephalopathy, death if untreated\n"
         "Screening: FeCl3 navy blue, DNPH positive\n"
         "Treatment: Diet free of branched-chain amino acids",
         LIGHT_TEAL, TEAL),
        ("Galactosemia",
         "Deficiency: Galactose-1-phosphate uridylyltransferase (GALT gene)\n"
         "Accumulates: Galactose-1-phosphate (toxic to liver, brain, lens)\n"
         "Features: Jaundice, cataracts, liver failure, E. coli sepsis in neonates\n"
         "Screening: Benedict's test positive (galactosuria)\n"
         "Treatment: Lactose-free diet (no breast milk or cow milk)",
         LIGHT_GOLD, GOLD),
        ("Homocystinuria",
         "Deficiency: Cystathionine beta-synthase\n"
         "Accumulates: Homocysteine (and homocystine in urine)\n"
         "Features: Marfan-like habitus, ectopia lentis, thromboembolism, mental retardation\n"
         "Screening: Nitroprusside test positive\n"
         "Treatment: Vitamin B6 (pyridoxine), low methionine diet, betaine",
         LIGHT_RED, RED),
    ]
    for name, content, bg, border in disorders:
        lines = content.split("\n")
        story.append(KeepTogether([
            h3(f"▶ {name}"),
            *[bullet(line) for line in lines if line.strip()],
            sp(4),
        ]))

    # ── PAGE 6: Screening Workflow ──────────────────────────────────────────
    story.append(PageBreak())
    story.append(h2("2.6 Neonatal Screening Workflow"))
    story.append(sp(6))
    story.append(renderPDF.GraphicsFlowable(make_workflow_diagram()))
    story.append(sp(4))
    story.append(cite("Sources: Harper's Illustrated Biochemistry 32e; Park's Preventive Medicine; Thompson & Thompson Genetics 9e"))
    story.append(sp(8))

    story.append(h2("2.7 Modern Screening: Tandem Mass Spectrometry (TMS / MS-MS)"))
    story.append(body(
        "Today, most developed countries use <b>tandem mass spectrometry (TMS)</b> as the primary "
        "screening tool. A single dried blood spot is analysed and <b>50+ metabolic disorders</b> can "
        "be detected simultaneously within minutes. TMS measures acylcarnitines (for fatty acid "
        "oxidation disorders) and amino acid profiles (for amino acidopathies and urea cycle disorders)."
    ))
    story.append(sp(4))
    story.append(bullet("<b>Amino acidopathies</b>: PKU, MSUD, homocystinuria, tyrosinemia, citrullinemia"))
    story.append(bullet("<b>Organic acidaemias</b>: Propionic acidemia, methylmalonic acidemia, isovaleric acidemia"))
    story.append(bullet("<b>Fatty acid oxidation disorders</b>: VLCAD deficiency, LCAD deficiency, MCAD deficiency"))
    story.append(bullet("<b>Urea cycle disorders</b>: Argininosuccinic aciduria, OTC deficiency"))
    story.append(sp(4))
    story.append(note(
        "Although TMS has replaced older methods in many centres, paper chromatography and chemical "
        "spot tests are still valuable in low-resource settings and form the conceptual foundation "
        "of IEM biochemistry that every MBBS student must understand."
    ))

    # ── PAGE 7-8: Paper Chromatography ─────────────────────────────────────
    story.append(PageBreak())
    story.append(h1("SECTION 3: PAPER CHROMATOGRAPHY"))
    story.append(sp(8))

    story.append(h2("3.1 Definition and Principle"))
    story.append(body(
        "<b>Paper chromatography</b> is a type of <b>planar (partition) chromatography</b> in which "
        "compounds are separated based on their differential solubility between two phases:"
    ))
    story.append(sp(4))
    story.append(bullet(
        "<b>Stationary phase</b>: Water (or a polar solvent) adsorbed onto the cellulose fibres of filter paper."
    ))
    story.append(bullet(
        "<b>Mobile phase</b>: An organic solvent or solvent mixture (e.g., butanol:acetic acid:water, phenol:water) "
        "that moves across the paper by capillary action."
    ))
    story.append(sp(4))
    story.append(body(
        "As the solvent front moves, each compound partitions between the two phases according to its relative "
        "solubility. Compounds more soluble in the mobile phase travel <b>further</b>; those more soluble in "
        "the stationary phase travel <b>less far</b>."
    ))
    story.append(sp(8))

    story.append(h2("3.2 The Retardation Factor (Rf)"))
    story.append(sp(4))
    story.append(body(
        "The key measurable parameter in paper chromatography is the <b>Rf (retardation factor)</b>:"
    ))
    story.append(sp(6))
    story.append(Paragraph(
        "<b>Rf = Distance traveled by compound (Ds) / Distance traveled by solvent front (Df)</b>",
        ParagraphStyle("formula", fontName="Helvetica-Bold", fontSize=12,
                       textColor=RED, alignment=TA_CENTER,
                       backColor=LIGHT_RED, borderPad=10,
                       spaceAfter=6, spaceBefore=6)
    ))
    story.append(sp(6))
    story.append(bullet("<b>Rf is always between 0 and 1.</b>"))
    story.append(bullet("High Rf (close to 1) = compound moves with solvent = low affinity for stationary phase."))
    story.append(bullet("Low Rf (close to 0) = compound barely moves = high affinity for stationary phase."))
    story.append(bullet("Each compound has a <b>fixed, characteristic Rf</b> for a given solvent system and paper type."))
    story.append(bullet("Rf values are used for <b>presumptive identification</b> by comparison with known standards."))
    story.append(sp(8))

    story.append(h2("3.3 Diagrams"))
    story.append(sp(4))
    story.append(renderPDF.GraphicsFlowable(make_paper_chrom_diagram()))
    story.append(sp(4))
    story.append(cite("Source: Tietz Textbook of Laboratory Medicine 7e, Fig. 19.15 & 19.16"))
    story.append(sp(8))

    # ── PAGE 9: Procedure ───────────────────────────────────────────────────
    story.append(PageBreak())
    story.append(h2("3.4 Types of Paper Chromatography"))
    story.append(sp(4))

    types_data = [
        ["Type", "Direction", "How Solvent Moves", "Best For"],
        ["Ascending", "Bottom → Top", "Capillary action draws solvent upward", "Most routine separations"],
        ["Descending", "Top → Bottom", "Gravity + capillary flow", "Longer runs, better resolution"],
        ["Radial / Circular", "Centre → Edge", "Radially outward from centre spot", "Quick screening, spot detection"],
        ["2D (Two-Dimensional)", "Both axes", "First run, rotate 90°, second run", "Complex amino acid mixtures"],
    ]
    t = Table(types_data, colWidths=[90, 90, 150, 115])
    t.setStyle(TableStyle([
        ("BACKGROUND",    (0, 0), (-1, 0),  DARK_BLUE),
        ("TEXTCOLOR",     (0, 0), (-1, 0),  WHITE),
        ("FONTNAME",      (0, 0), (-1, 0),  "Helvetica-Bold"),
        ("FONTSIZE",      (0, 0), (-1, -1), 8),
        ("FONTNAME",      (0, 1), (-1, -1), "Helvetica"),
        ("GRID",          (0, 0), (-1, -1), 0.4, MID_GREY),
        ("ROWBACKGROUNDS",(0, 1), (-1, -1), [WHITE, LIGHT_BLUE]),
        ("ALIGN",         (0, 0), (-1, -1), "LEFT"),
        ("TOPPADDING",    (0, 0), (-1, -1), 4),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 4),
        ("LEFTPADDING",   (0, 0), (-1, -1), 5),
    ]))
    story.append(t)
    story.append(sp(6))
    story.append(note(
        "For urine amino acid profiling in IEM, <b>two-dimensional (2D) paper chromatography</b> gives the best "
        "separation, using two different solvent systems at 90 degrees to each other."
    ))
    story.append(sp(8))

    story.append(h2("3.5 Step-by-Step Procedure: Ascending Paper Chromatography for Urine Amino Acids"))
    story.append(sp(4))

    procedure_steps = [
        ("Step 1: Prepare the Paper",
         "Cut a strip of Whatman No. 1 filter paper. Draw a pencil baseline about 2 cm from the bottom. "
         "Mark spots lightly in pencil (do NOT use pen - ink may run)."),
        ("Step 2: Apply Samples",
         "Using a micropipette or capillary tube, apply small spots (1-2 mm diameter) of: (a) Patient's urine "
         "concentrate, (b) Known amino acid standards. Allow each spot to DRY completely before applying the next layer. "
         "Apply 2-3 times to concentrate the sample."),
        ("Step 3: Prepare the Solvent",
         "Pour solvent (e.g., n-butanol:glacial acetic acid:water in 4:1:5 ratio) into a 6 x 18-inch Pyrex jar "
         "with a tightly fitting lid. Allow 30 min for solvent equilibration (to saturate the atmosphere in the jar)."),
        ("Step 4: Develop the Chromatogram",
         "Suspend the paper vertically in the jar so that the bottom edge dips into the solvent BUT "
         "the sample spots are ABOVE the solvent level. Seal the jar. Allow solvent to ascend for 18-24 hours."),
        ("Step 5: Mark Solvent Front",
         "Remove paper from jar. IMMEDIATELY mark the solvent front with a pencil before it evaporates. "
         "Allow paper to dry in a fume hood."),
        ("Step 6: Detect / Visualize Spots",
         "Spray paper with <b>ninhydrin solution</b> (0.1% in acetone). "
         "Heat in oven at 90°C for 5-10 minutes. "
         "Amino acids appear as <b>purple/violet spots</b> (proline gives yellow). "
         "For sugars: use dinitrosalicylic acid or aniline-diphenylamine reagent."),
        ("Step 7: Calculate Rf Values",
         "Measure: Ds (centre of spot to baseline) and Df (solvent front to baseline). "
         "Calculate Rf = Ds / Df for each spot. "
         "Compare with Rf values of known amino acid standards run simultaneously."),
        ("Step 8: Interpret Results",
         "Normal urine: only trace amino acids. "
         "Abnormal patterns indicate specific IEM. "
         "Confirm positive screening results with quantitative HPLC or TMS."),
    ]

    for step_title, step_desc in procedure_steps:
        story.append(KeepTogether([
            h3(step_title),
            body(step_desc),
            sp(4),
        ]))

    # ── PAGE 10: Detection & Applications ──────────────────────────────────
    story.append(PageBreak())
    story.append(h2("3.6 Detection Reagents in Paper Chromatography"))
    story.append(sp(4))

    det_data = [
        ["Reagent", "Compounds Detected", "Colour", "Application"],
        ["Ninhydrin", "Amino acids", "Purple/violet (yellow for proline)", "Aminoaciduria screening"],
        ["Dinitrosalicylic acid", "Reducing sugars", "Orange-red", "Sugar disorders (galactosemia)"],
        ["Aniline-diphenylamine", "Reducing sugars", "Various colours per sugar", "Specific sugar identification"],
        ["Ferricyanide / Ehrlich", "Indoles (tryptophan)", "Blue-green", "Hartnup disease"],
        ["UV fluorescence (254nm)", "Purines, pyrimidines", "Dark spots on bright background", "Nucleotide disorders"],
    ]
    t = Table(det_data, colWidths=[95, 125, 105, 120])
    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),
        ("FONTNAME",      (0, 1), (-1, -1), "Helvetica"),
        ("GRID",          (0, 0), (-1, -1), 0.4, MID_GREY),
        ("ROWBACKGROUNDS",(0, 1), (-1, -1), [WHITE, LIGHT_TEAL]),
        ("TOPPADDING",    (0, 0), (-1, -1), 4),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 4),
        ("LEFTPADDING",   (0, 0), (-1, -1), 5),
    ]))
    story.append(t)
    story.append(sp(8))

    story.append(h2("3.7 Clinical Applications of Paper Chromatography in IEM Screening"))
    story.append(sp(4))
    apps = [
        ("<b>Aminoaciduria</b>: Detects excess amino acids in urine - important for PKU (phenylalanine), "
         "MSUD (leucine, isoleucine, valine), cystinuria (cystine, lysine, arginine, ornithine), "
         "Hartnup disease (neutral amino acids)."),
        ("<b>Organic aciduria</b>: Two-dimensional chromatography or combined with chemical spot tests "
         "helps identify propionic acid, methylmalonic acid, isovaleric acid."),
        ("<b>Urine sugar identification</b>: Ascending or descending chromatography with dinitrosalicylic "
         "acid developer distinguishes galactose, glucose, fructose, lactose - key in galactosaemia "
         "and fructose intolerance."),
        ("<b>Quality control / teaching tool</b>: Even where TMS is available, paper chromatography "
         "remains the cornerstone of biochemistry practical teaching at the undergraduate level."),
    ]
    for app in apps:
        story.append(bullet(app))
    story.append(sp(8))

    story.append(h2("3.8 Factors Affecting Rf Value"))
    story.append(sp(4))
    factors = [
        "Type and composition of solvent (mobile phase)",
        "Type of paper (Whatman No.1 vs No. 3, acetylated paper, etc.)",
        "Temperature during development",
        "Time of development (run time)",
        "pH of the solvent system",
        "Sample concentration and spot size (large spots give poor resolution)",
        "Direction (ascending vs descending gives slightly different Rf)",
    ]
    for f in factors:
        story.append(bullet(f))
    story.append(sp(4))
    story.append(note(
        "Always run known amino acid standards alongside the patient sample on the SAME sheet "
        "to ensure valid Rf comparisons. Rf values from different runs cannot be directly compared."
    ))

    # ── PAGE 11: PC vs TLC + Mnemonics ──────────────────────────────────────
    story.append(PageBreak())
    story.append(h2("3.9 Comparison: Paper Chromatography vs Thin-Layer Chromatography (TLC)"))
    story.append(sp(4))
    story.append(make_pc_vs_tlc_table())
    story.append(sp(4))
    story.append(cite("Source: Tietz Textbook of Laboratory Medicine 7e"))
    story.append(sp(8))

    story.append(h2("3.10 Abnormal Amino Acid Patterns in Common IEM"))
    story.append(sp(4))
    pattern_data = [
        ["Disease", "Amino Acids Elevated in Urine / Blood", "Other Urine Finding"],
        ["PKU", "Phenylalanine (blood), Phenylpyruvate (urine)", "FeCl3 green, DNPH +ve, mousy odour"],
        ["MSUD", "Leucine, Isoleucine, Valine + keto acids", "FeCl3 navy blue, maple syrup smell"],
        ["Homocystinuria", "Homocystine (urine)", "Nitroprusside +ve, lens dislocation"],
        ["Cystinuria", "Cystine, Lysine, Arginine, Ornithine", "Nitroprusside +ve, kidney stones"],
        ["Hartnup Disease", "Neutral amino acids (all)", "Pellagra-like rash, cerebellar ataxia"],
        ["Tyrosinemia I", "Tyrosine (blood), succinylacetone (urine)", "FeCl3 pale green, liver failure"],
    ]
    t = Table(pattern_data, colWidths=[90, 185, 170])
    t.setStyle(TableStyle([
        ("BACKGROUND",    (0, 0), (-1, 0),  PURPLE),
        ("TEXTCOLOR",     (0, 0), (-1, 0),  WHITE),
        ("FONTNAME",      (0, 0), (-1, 0),  "Helvetica-Bold"),
        ("FONTSIZE",      (0, 0), (-1, -1), 8),
        ("FONTNAME",      (0, 1), (-1, -1), "Helvetica"),
        ("GRID",          (0, 0), (-1, -1), 0.4, MID_GREY),
        ("ROWBACKGROUNDS",(0, 1), (-1, -1), [WHITE, colors.HexColor("#F3E5F5")]),
        ("TOPPADDING",    (0, 0), (-1, -1), 4),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 4),
        ("LEFTPADDING",   (0, 0), (-1, -1), 5),
        ("VALIGN",        (0, 0), (-1, -1), "TOP"),
    ]))
    story.append(t)
    story.append(sp(8))

    # Mnemonics
    story.append(h1("SECTION 4: MNEMONICS & EXAM KEY POINTS"))
    story.append(sp(8))

    story.append(Paragraph(
        "<b>Mnemonic 1: FeCl3 Colours</b><br/>"
        '"<font color=#C62828>G</font>reen <font color=#1565C0>N</font>avy '
        '<font color=#00695C>P</font>ale <font color=#6A1B9A>G</font>reen <font color=#6A1B9A>P</font>urple"<br/>'
        "G = PKU (Green) | N = MSUD (Navy blue) | P = Tyrosinemia (Pale green) | G = Histidinemia (Green-brown) | P = Organic acidaemias (Purple)",
        sMnemonic
    ))
    story.append(sp(6))

    story.append(Paragraph(
        "<b>Mnemonic 2: Tests That Are Positive in PKU</b><br/>"
        '"<font color=#C62828>F</font>irst <font color=#C62828>D</font>iagnose - <font color=#C62828>G</font>ive <font color=#C62828>N</font>ormal <font color=#C62828>P</font>he"<br/>'
        "FeCl3 = Green | DNPH = Positive | Guthrie = Positive | No Benedict | No nitroprusside",
        sMnemonic
    ))
    story.append(sp(6))

    story.append(Paragraph(
        "<b>Mnemonic 3: Rf Value Rule</b><br/>"
        '"<font color=#C62828>H</font>igh Rf = <font color=#C62828>H</font>appy traveller (moves far from home)"<br/>'
        "High Rf = Moves far = More soluble in mobile phase = Less retained<br/>"
        "Low Rf = Stays near baseline = More retained by stationary phase",
        sMnemonic
    ))
    story.append(sp(6))

    story.append(Paragraph(
        "<b>Mnemonic 4: Guthrie Test Mechanism</b><br/>"
        '"<b>BIAB</b> = Bacteria Inhibited At Baseline Phe → NO growth = Normal"<br/>'
        "When Phe is <b>HIGH</b> → Overcomes inhibitor → Bacteria GROW → PKU POSITIVE",
        sMnemonic
    ))
    story.append(sp(8))

    story.append(h2("4.1 Key Exam Points (Frequently Asked in MBBS)"))
    story.append(sp(4))
    exam_points = [
        "The Guthrie test uses beta-thienylalanine as a competitive inhibitor of phenylalanine.",
        "Blood for neonatal IEM screening is collected at Day 6-10 by heel prick.",
        "Rf = Ds / Df. Always between 0 and 1. Higher Rf = more soluble in mobile phase.",
        "Ninhydrin spray gives purple spots for amino acids (yellow for proline).",
        "PKU: FeCl3 → Green. MSUD: FeCl3 → Navy blue. Homocystinuria: Nitroprusside +ve.",
        "Two-dimensional paper chromatography is best for resolving complex amino acid mixtures.",
        "Paper chromatography uses cellulose paper (water as stationary phase). TLC uses silica/alumina.",
        "TMS (tandem mass spectrometry) is the modern gold-standard, detecting 50+ IEM from a single DBS.",
        "Benedict's test detects reducing sugars - important in galactosaemia screening.",
        "In PKU: restrict phenylalanine; in MSUD: restrict branched-chain amino acids (Leu, Ile, Val).",
    ]
    for pt in exam_points:
        story.append(key(pt))
    story.append(sp(8))

    # ── PAGE 12: References & Summary ──────────────────────────────────────
    story.append(PageBreak())
    story.append(h1("SECTION 5: SUMMARY & REFERENCES"))
    story.append(sp(8))

    story.append(h2("5.1 Summary"))
    summary_items = [
        "Inborn errors of metabolism are inherited enzyme deficiencies causing accumulation of toxic metabolites.",
        "Neonatal screening aims to detect IEM before irreversible damage occurs. Sample: heel-prick DBS card at Day 6-10.",
        "The Guthrie test (bacterial inhibition assay) was the first mass screening test, detecting PKU by elevated phenylalanine.",
        "Urine chemical spot tests (FeCl3, DNPH, Benedict's, Nitroprusside) provide rapid, cheap first-line screening for IEM.",
        "Paper chromatography separates compounds by partition between stationary (water on paper) and mobile (organic solvent) phases.",
        "The Rf value (= Ds/Df) characterises each compound and allows presumptive identification against known standards.",
        "Ascending paper chromatography with ninhydrin staining detects aminoacidurias; dinitrosalicylic acid detects urine sugars.",
        "Two-dimensional paper chromatography provides the best resolution for complex amino acid mixtures.",
        "TLC is preferred over paper chromatography when frequent/high-throughput separations are required.",
        "Modern IEM screening uses tandem mass spectrometry (TMS) to simultaneously detect 50+ disorders from a single DBS.",
    ]
    for i, item in enumerate(summary_items, 1):
        story.append(Paragraph(f"<b>{i}.</b>&nbsp; {item}", sBullet))
    story.append(sp(10))

    story.append(h2("5.2 References / Sources"))
    story.append(sp(4))
    refs = [
        "Harper HA, Rodwell VW, Mayes PA. <i>Harper's Illustrated Biochemistry</i>, 32nd Ed. McGraw-Hill, 2023. Chapter 48 (Clinical Biochemistry), p. 585.",
        "Tietz NW. <i>Tietz Textbook of Laboratory Medicine</i>, 7th Ed. Elsevier, 2023. Chapter 19 (Chromatography), Chapter 35 (Carbohydrate Disorders).",
        "Ropper AH, Samuels MA, Klein JP. <i>Adams and Victor's Principles of Neurology</i>, 12th Ed. McGraw-Hill, 2023. Chapter 36 (Neonatal Metabolic Diseases), Tables 36-1 and 36-2.",
        "Park K. <i>Park's Textbook of Preventive and Social Medicine</i>, 26th Ed. Bhanot Publishers, 2021. Chapter on Neonatal Screening.",
        "Thompson MW, McInnes RR, Willard HF. <i>Thompson & Thompson Genetics and Genomics in Medicine</i>, 9th Ed. Elsevier, 2023. Chapter 19 (Newborn Screening, Tandem Mass Spectrometry).",
    ]
    for ref in refs:
        story.append(Paragraph(ref, sCite))
        story.append(sp(4))
    story.append(sp(8))

    story.append(hr())
    story.append(Paragraph(
        "<b>End of Lecture Notes</b> | MBBS 1st Year Biochemistry | Screening of Urine for Inborn Errors of Metabolism & Paper Chromatography",
        ParagraphStyle("footer_note", fontName="Helvetica-Oblique", fontSize=8,
                       textColor=MID_GREY, alignment=TA_CENTER)
    ))

    return story


# ── MAIN BUILD ──────────────────────────────────────────────────────────────
OUTPUT = "/home/daytona/workspace/iem-lecture/IEM_Screening_Paper_Chromatography_MBBS.pdf"

doc = SimpleDocTemplate(
    OUTPUT,
    pagesize=A4,
    leftMargin=1.8*cm, rightMargin=1.8*cm,
    topMargin=1.5*cm, bottomMargin=1.5*cm,
    title="IEM Urine Screening & Paper Chromatography - MBBS Biochemistry Lecture",
    author="Orris Medical Knowledge Platform",
    subject="MBBS 1st Year Biochemistry",
)

story = build_story()

# First page: custom cover canvas; subsequent pages: header/footer
class MyDocTemplate(SimpleDocTemplate):
    def handle_pageBegin(self):
        super().handle_pageBegin()

doc.build(
    story,
    onFirstPage=draw_cover,
    onLaterPages=on_page
)

print(f"PDF created: {OUTPUT}")
Running Command

cd /home/daytona/workspace/iem-lecture && python build_lecture.py 2>&1

Editing File

~/iem-lecture/build_lecture.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/iem-lecture/build_lecture.py'
Editing File

~/iem-lecture/build_lecture.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/iem-lecture/build_lecture.py'
Editing File

~/iem-lecture/build_lecture.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/iem-lecture/build_lecture.py'
Reading File
Running Command

cd /home/daytona/workspace/iem-lecture && python build_lecture.py 2>&1

Reading File
This is a shared conversation. Sign in to Orris to start your own chat.