Explain the practical of estimation of total bilirubin in serum, estimation of direct bilirubin in serum and estimation of indirect bilirubin in serum along with clinicals

Reading File
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Reading File
Reading File
Reading File
Reading File
Reading File
Reading File
Finding Sources
Reading File
Reading File
Loading Image
I now have all the information needed for a comprehensive, well-sourced answer. Let me compose it.

Estimation of Bilirubin in Serum - Complete Practical Guide


Background: What is Bilirubin?

Bilirubin is an orange-yellow pigment derived from heme, primarily a product of red blood cell (RBC) turnover. It is extracted and biotransformed in the liver and excreted in bile and urine. It exists in two main forms:
  • Unconjugated bilirubin (UCB) / Indirect bilirubin: Lipid-soluble, tightly bound to albumin in plasma. Cannot be filtered by kidneys. Stabilized by six intramolecular hydrogen bonds in a "ridge-tile" configuration that makes it water-insoluble.
  • Conjugated bilirubin (CB) / Direct bilirubin: Water-soluble, formed in the liver by conjugation with glucuronic acid (mono- or di-glucuronide). Can appear in urine when elevated.
  • Delta bilirubin (δ-bilirubin): Conjugated bilirubin covalently bound to albumin; accumulates in prolonged cholestasis.

Principle of the Assay: The Diazo Reaction (Van den Bergh Reaction)

All routine serum bilirubin measurements are based on the diazo (Van den Bergh) reaction, discovered by Ehrlich in 1883 and applied to serum measurement by Van den Bergh and Muller in 1916.
Chemical Reaction: Diazotized sulfanilic acid (the diazo reagent) reacts with the two central pyrrole rings of bilirubin via electrophilic aromatic substitution. The central methylene carbon is cleaved, producing two phenyl-azo adducts (azodipyroles/azobilirubin) that absorb at 540 nm (reddish-purple at neutral pH, blue at acidic/alkaline pH), measurable colorimetrically.
Bilirubin diazo reaction with diazonized sulfanilic acid producing two phenyl-azo adducts
Reaction of bilirubin with diazonized sulfanilic acid producing two azobilirubin adducts (Henry's Clinical Diagnosis, p. 527)
Why conjugated bilirubin reacts directly: CB is water-soluble and lacks the tight internal hydrogen bonds that shield unconjugated bilirubin. It therefore reacts rapidly with the diazo reagent in aqueous solution without any accelerator.
Why unconjugated bilirubin needs an accelerator: UCB is tightly bound to albumin and protected by six internal hydrogen bonds that block access of the diazo reagent. An accelerator (e.g., caffeine-benzoate, ethanol, methanol) disrupts these bonds and displaces UCB from albumin, allowing it to react.

The Standard Method: Jendrassik-Grof Method (1938, Modified by Doumas)

This is the method of choice for routine clinical laboratory measurement, recognized as reproducible and reliable.
Reagents Required:
  1. Diazo reagent: Freshly prepared diazotized sulfanilic acid (sulfanilic acid + sodium nitrite + HCl)
  2. Accelerator solution: Caffeine-sodium benzoate solution (aqueous; preferred over methanol/ethanol as it avoids protein precipitation and turbidity)
  3. Alkaline tartrate solution: Sodium hydroxide + sodium potassium tartrate (used to shift pH for color development)
  4. Blank reagent: Sodium nitrite replaced with distilled water (controls for background colour of sample)

I. Estimation of TOTAL Bilirubin

Principle

Total bilirubin = conjugated + unconjugated bilirubin. The caffeine-benzoate accelerator displaces UCB from albumin, allowing all bilirubin species to react with the diazo reagent. The product is measured spectrophotometrically.

Procedure

StepAction
1Pipette 0.1 mL serum + 0.5 mL caffeine-benzoate (accelerator) + 0.4 mL diazo reagent into a test tube. Mix well.
2Allow to stand for 10 minutes at room temperature (reaction time for both CB and UCB).
3Add 1.5 mL alkaline tartrate (shifts product to blue color at alkaline pH, increasing sensitivity).
4Read absorbance at 600 nm (blue color) or 540 nm (reddish-purple) within 1 hour.
5Run a blank: serum + caffeine-benzoate + blank reagent (no diazo) - subtract this from the test reading.
6Compare to standard bilirubin calibrator of known concentration.

Calculation

Using the Beer-Lambert law:
Total Bilirubin (mg/dL) = (Absorbance of Test / Absorbance of Standard) × Concentration of Standard

Reference Range

  • Adults: 0.2 - 1.0 mg/dL (3.4 - 17.1 μmol/L)
  • With van den Bergh method: normal mean ~0.5 mg/dL; 95% of normal population 0.2 - 0.9 mg/dL

II. Estimation of DIRECT Bilirubin (Conjugated Bilirubin)

Principle

Direct bilirubin = the fraction that reacts with diazotized sulfanilic acid in aqueous solution, WITHOUT any accelerator. This primarily measures conjugated (water-soluble) bilirubin, which reacts rapidly (within 1 minute).

Procedure

StepAction
1Pipette 0.1 mL serum + 0.9 mL distilled water + 0.4 mL diazo reagent. Mix.
2Allow to react for exactly 1 minute at room temperature (only direct-reacting CB reacts in this short window).
3Read absorbance at 540 nm immediately.
4Run a blank as above (serum + water + blank reagent).
Note: No accelerator is added. The reaction is done in purely aqueous conditions. Conjugated bilirubin reacts rapidly; unconjugated bilirubin reacts slowly but some will react with prolonged incubation - hence the strict 1-minute reaction window.

Reference Range

  • Direct bilirubin: 0.0 - 0.3 mg/dL (< 5.1 μmol/L)
  • In normal plasma, only ~4% of total bilirubin is conjugated (direct-reacting)
  • Clinically: Direct fraction <15% of total serum bilirubin = unconjugated hyperbilirubinemia

III. Estimation of INDIRECT Bilirubin (Unconjugated Bilirubin)

Principle

Indirect bilirubin cannot be measured directly - it is calculated by subtraction:
Indirect Bilirubin = Total Bilirubin - Direct Bilirubin
This reflects mostly unconjugated bilirubin (albumin-bound, slow-reacting fraction). However, this is an approximation - the calculated "indirect" value may slightly underestimate true UCB because a small amount of UCB may react in the direct assay even without accelerator.

Reference Range

  • Indirect bilirubin: 0.1 - 0.8 mg/dL (1.7 - 13.7 μmol/L)

Important Technical Points & Sources of Error

IssueExplanation
HemolysisHemoglobin interferes; no significant interference up to 25 mg/dL Hb on automated analyzers (Beckman AU). Hemolysis can falsely lower bilirubin by oxidation.
LipemiaNo significant interference up to 500 mg/dL Intralipid.
Light exposureBilirubin is photosensitive; samples must be protected from light (covered tubes).
Methanol/ethanol acceleratorsCause protein precipitation and turbidity; caffeine-benzoate is preferred.
Delta bilirubinCovalently albumin-bound conjugated bilirubin. Has a ~18-20 day half-life (albumin's half-life). Not accurately measured by standard diazo methods. Important in prolonged cholestasis.
Direct ≠ ConjugatedDirect and conjugated bilirubin are NOT equivalent. A small amount of UCB may appear in the "direct" fraction; some CB (especially delta bilirubin) may escape. Errors can occur if used to diagnose isolated disorders like Gilbert syndrome.
CalibratorsHuman serum-based calibrators are preferred over bovine serum, which gives incomplete and unpredictable reactions with UCB.

Clinical Significance

Normal Values Summary

FractionNormal Range (mg/dL)Normal Range (μmol/L)
Total bilirubin0.2 - 1.03.4 - 17.1
Direct (conjugated)0.0 - 0.30.0 - 5.1
Indirect (unconjugated)0.1 - 0.81.7 - 13.7
Jaundice becomes clinically visible at total bilirubin >2.5 - 3.0 mg/dL (scleral icterus typically appears first around 2 mg/dL).

Elevated INDIRECT (Unconjugated) Bilirubin - Causes

CategoryExamples
Increased production (overproduction)Hemolysis (intravascular/extravascular), ineffective erythropoiesis, blood transfusion, resorption of large hematomas
Decreased hepatocellular uptakeDrugs (rifampin, cyclosporine)
Decreased conjugationGilbert syndrome (mild UGT1A1 deficiency), Crigler-Najjar syndrome type I and II (severe/absent UGT1A1), neonatal physiologic jaundice (low UGT activity at birth), hypothyroidism
Key point on neonatal jaundice: UCB in excess of albumin's binding capacity (>20-25 mg/dL) can cross the blood-brain barrier and deposit in the basal ganglia causing kernicterus (toxic encephalopathy). Treatment: phototherapy (blue light converts bilirubin Z-Z to more water-soluble E-isomers that can be excreted without conjugation).

Elevated DIRECT (Conjugated) Bilirubin - Causes

CategoryExamples
Hepatocellular diseaseViral hepatitis (A, B, C, E), alcoholic hepatitis, drug-induced liver injury, cirrhosis, liver failure
Intrahepatic cholestasisPrimary biliary cholangitis (PBC), primary sclerosing cholangitis (PSC), intrahepatic cholestasis of pregnancy, drug-induced cholestasis
Extrahepatic (posthepatic) obstructionCholedocholithiasis (bile duct stones), carcinoma of head of pancreas, cholangiocarcinoma, ampullary carcinoma, biliary strictures
Hereditary disordersDubin-Johnson syndrome, Rotor syndrome
Key point: Even limited amounts of true conjugated bilirubin in serum indicate significant hepatobiliary pathology. Conjugated hyperbilirubinemia is always associated with bilirubinuria (bilirubin in urine - "dark urine") EXCEPT when it's in the form of delta bilirubin (albumin-bound), which cannot be filtered by glomeruli due to its large size. A urine dipstick for bilirubin is therefore a helpful confirmatory test.

Differential Diagnosis Summary by Pattern

Bilirubin PatternLikely Diagnosis
↑ Indirect, Normal DirectHemolysis, Gilbert syndrome, Crigler-Najjar, neonatal jaundice
↑ Direct, ↑ IndirectHepatocellular disease (hepatitis, cirrhosis)
↑ Direct predominantlyObstructive jaundice (intrahepatic or extrahepatic cholestasis)
↑ Total, decreasing but jaundice persistsDelta bilirubin accumulation (prolonged cholestasis)

The Delta Bilirubin Enigma

In prolonged cholestasis, patients may show:
  1. Bilirubin in serum but NO bilirubinuria - because delta bilirubin (albumin-bound CB) cannot pass through glomeruli.
  2. Clinical jaundice persisting after biochemical recovery - because delta bilirubin's half-life matches albumin (~18-20 days vs. free bilirubin's ~4 hours), so it clears slowly even after the underlying cause is corrected.

Sources

  • Tietz Textbook of Laboratory Medicine, 7th Edition, pp. 1971-1972 (Jendrassik-Grof method, diazo methods)
  • Henry's Clinical Diagnosis and Management by Laboratory Methods, p. 527 (bilirubin reaction chemistry)
  • Harrison's Principles of Internal Medicine, 22nd Ed., pp. 1650-1655 (measurement, delta bilirubin, clinical interpretation)
  • Sleisenger and Fordtran's Gastrointestinal and Liver Disease, pp. 335-336 (clinical significance, differential diagnosis)
  • Lippincott's Illustrated Reviews: Biochemistry, 8th Ed., p. 805 (van den Bergh reaction, neonatal jaundice)

Create a colorful pdf of that

Reading File
Running Command

ls /home/daytona/workspace/ 2>/dev/null || echo "workspace empty"

Running Command

mkdir -p /home/daytona/workspace/bilirubin-pdf

Writing File

~/bilirubin-pdf/create_pdf.py

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

# ── Color Palette ──────────────────────────────────────────────────────────
TEAL        = colors.HexColor("#0D7C8F")
TEAL_LIGHT  = colors.HexColor("#E0F4F7")
ORANGE      = colors.HexColor("#E8720C")
ORANGE_LIGHT= colors.HexColor("#FEF0E6")
PURPLE      = colors.HexColor("#6B3FA0")
PURPLE_LIGHT= colors.HexColor("#F0EAF9")
GREEN       = colors.HexColor("#1A7A4A")
GREEN_LIGHT = colors.HexColor("#E5F5EC")
RED         = colors.HexColor("#C0392B")
RED_LIGHT   = colors.HexColor("#FDEDEC")
GOLD        = colors.HexColor("#D4A017")
GOLD_LIGHT  = colors.HexColor("#FDF8E1")
DARK        = colors.HexColor("#1A1A2E")
GREY        = colors.HexColor("#5A5A72")
LIGHT_GREY  = colors.HexColor("#F5F5F7")
WHITE       = colors.white

W, H = A4

# ── Page template with header/footer ───────────────────────────────────────
def on_page(canv, doc):
    canv.saveState()
    # Top header bar
    canv.setFillColor(TEAL)
    canv.rect(0, H - 28, W, 28, fill=1, stroke=0)
    canv.setFillColor(WHITE)
    canv.setFont("Helvetica-Bold", 10)
    canv.drawString(18, H - 19, "BILIRUBIN ESTIMATION IN SERUM")
    canv.setFont("Helvetica", 9)
    canv.drawRightString(W - 18, H - 19, f"Page {doc.page}")
    # Bottom footer bar
    canv.setFillColor(TEAL)
    canv.rect(0, 0, W, 20, fill=1, stroke=0)
    canv.setFillColor(WHITE)
    canv.setFont("Helvetica-Oblique", 7.5)
    canv.drawCentredString(W / 2, 6, "Sources: Tietz Lab Medicine 7e · Henry's Clinical Diagnosis · Harrison's 22e · Lippincott Biochemistry 8e")
    canv.restoreState()

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

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

TITLE_STYLE = S("Title",
    fontSize=22, fontName="Helvetica-Bold", textColor=WHITE,
    alignment=TA_CENTER, spaceAfter=4)

SUBTITLE_STYLE = S("Subtitle",
    fontSize=11, fontName="Helvetica-Oblique", textColor=TEAL_LIGHT,
    alignment=TA_CENTER, spaceAfter=8)

H1 = S("H1",
    fontSize=14, fontName="Helvetica-Bold", textColor=WHITE,
    spaceBefore=10, spaceAfter=4, leftIndent=0)

H2 = S("H2",
    fontSize=11, fontName="Helvetica-Bold", textColor=TEAL,
    spaceBefore=8, spaceAfter=3)

BODY = S("Body",
    fontSize=9.5, fontName="Helvetica", textColor=DARK,
    leading=14, spaceBefore=2, spaceAfter=2, alignment=TA_JUSTIFY)

BODY_BOLD = S("BodyBold",
    fontSize=9.5, fontName="Helvetica-Bold", textColor=DARK, leading=14)

BULLET = S("Bullet",
    fontSize=9.5, fontName="Helvetica", textColor=DARK,
    leading=14, leftIndent=14, spaceBefore=1)

NOTE = S("Note",
    fontSize=8.5, fontName="Helvetica-Oblique", textColor=GREY,
    leading=12, spaceBefore=2, leftIndent=10)

FORMULA = S("Formula",
    fontSize=11, fontName="Helvetica-Bold", textColor=PURPLE,
    alignment=TA_CENTER, spaceBefore=6, spaceAfter=6, leading=16)

# ── Helper Flowables ────────────────────────────────────────────────────────
class ColorBanner(Flowable):
    """Full-width colored title banner."""
    def __init__(self, text, subtext="", bg=TEAL, h=56):
        super().__init__()
        self.text = text
        self.subtext = subtext
        self.bg = bg
        self.bh = h
        self.width = W - 2.5*cm
        self.height = h

    def draw(self):
        c = self.canv
        c.setFillColor(self.bg)
        c.roundRect(0, 0, self.width, self.bh, 6, fill=1, stroke=0)
        c.setFillColor(WHITE)
        c.setFont("Helvetica-Bold", 17)
        c.drawCentredString(self.width / 2, self.bh - 26, self.text)
        if self.subtext:
            c.setFont("Helvetica-Oblique", 9)
            c.setFillColor(colors.HexColor("#D0EEF4"))
            c.drawCentredString(self.width / 2, self.bh - 40, self.subtext)

class SectionHeader(Flowable):
    """Colored section header bar."""
    def __init__(self, text, bg=TEAL, width=None):
        super().__init__()
        self.text = text
        self.bg = bg
        self.width = (width or W - 2.5*cm)
        self.height = 24

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

class FormulaBox(Flowable):
    """Highlighted formula/equation box."""
    def __init__(self, text, bg=PURPLE_LIGHT, border=PURPLE, width=None):
        super().__init__()
        self.text = text
        self.bg = bg
        self.border = border
        self.width = width or W - 2.5*cm
        self.height = 38

    def draw(self):
        c = self.canv
        c.setFillColor(self.bg)
        c.roundRect(0, 0, self.width, self.height, 5, fill=1, stroke=0)
        c.setStrokeColor(self.border)
        c.setLineWidth(1.5)
        c.roundRect(0, 0, self.width, self.height, 5, fill=0, stroke=1)
        c.setFillColor(self.border)
        c.setFont("Helvetica-Bold", 11)
        c.drawCentredString(self.width / 2, 12, self.text)

class InfoBox(Flowable):
    """Colored info callout box."""
    def __init__(self, label, text, bg=TEAL_LIGHT, border=TEAL, width=None):
        super().__init__()
        self.label = label
        self.text = text
        self.bg = bg
        self.border = border
        self.width = width or W - 2.5*cm
        self.height = 46

    def draw(self):
        c = self.canv
        # Accent left bar
        c.setFillColor(self.border)
        c.rect(0, 0, 5, self.height, fill=1, stroke=0)
        # Background
        c.setFillColor(self.bg)
        c.rect(5, 0, self.width - 5, self.height, fill=1, stroke=0)
        # Label
        c.setFillColor(self.border)
        c.setFont("Helvetica-Bold", 9)
        c.drawString(14, self.height - 16, self.label)
        # Text
        c.setFillColor(DARK)
        c.setFont("Helvetica", 9)
        # Wrap text manually
        words = self.text.split()
        line, lines = "", []
        for w in words:
            test = (line + " " + w).strip()
            if c.stringWidth(test, "Helvetica", 9) < self.width - 28:
                line = test
            else:
                lines.append(line)
                line = w
        lines.append(line)
        y = self.height - 29
        for l in lines:
            c.drawString(14, y, l)
            y -= 12

# ── Table helpers ────────────────────────────────────────────────────────────
def make_table(data, col_widths, header_bg=TEAL, header_text_color=WHITE,
               alt_row_bg=LIGHT_GREY, border_color=TEAL):
    t = Table(data, colWidths=col_widths)
    style = [
        ('BACKGROUND', (0, 0), (-1, 0), header_bg),
        ('TEXTCOLOR',  (0, 0), (-1, 0), header_text_color),
        ('FONTNAME',   (0, 0), (-1, 0), 'Helvetica-Bold'),
        ('FONTSIZE',   (0, 0), (-1, 0), 9),
        ('ALIGN',      (0, 0), (-1, 0), 'CENTER'),
        ('VALIGN',     (0, 0), (-1, -1), 'MIDDLE'),
        ('FONTNAME',   (0, 1), (-1, -1), 'Helvetica'),
        ('FONTSIZE',   (0, 1), (-1, -1), 9),
        ('ROWBACKGROUNDS', (0, 1), (-1, -1), [WHITE, alt_row_bg]),
        ('GRID', (0, 0), (-1, -1), 0.5, border_color),
        ('TOPPADDING',    (0, 0), (-1, -1), 5),
        ('BOTTOMPADDING', (0, 0), (-1, -1), 5),
        ('LEFTPADDING',   (0, 0), (-1, -1), 7),
        ('RIGHTPADDING',  (0, 0), (-1, -1), 7),
        ('ROUNDEDCORNERS', [4]),
    ]
    t.setStyle(TableStyle(style))
    return t

def para(text, style=BODY):
    return Paragraph(text, style)

# ── Build Document ──────────────────────────────────────────────────────────
doc = SimpleDocTemplate(
    "/home/daytona/workspace/bilirubin-pdf/Bilirubin_Estimation_Serum.pdf",
    pagesize=A4,
    leftMargin=1.25*cm, rightMargin=1.25*cm,
    topMargin=1.5*cm, bottomMargin=1.2*cm,
    title="Bilirubin Estimation in Serum",
    author="Orris Medical"
)

story = []
SP = lambda n=6: Spacer(1, n)

# ════════════════════════════════════════════════════════════════════
# COVER BANNER
# ════════════════════════════════════════════════════════════════════
story.append(SP(10))
story.append(ColorBanner(
    "ESTIMATION OF BILIRUBIN IN SERUM",
    subtext="Total Bilirubin  ·  Direct Bilirubin  ·  Indirect Bilirubin  ·  Clinical Significance",
    bg=TEAL, h=70
))
story.append(SP(10))

# ════════════════════════════════════════════════════════════════════
# SECTION 1 — BACKGROUND
# ════════════════════════════════════════════════════════════════════
story.append(SectionHeader("1.  BACKGROUND: WHAT IS BILIRUBIN?", bg=TEAL))
story.append(SP(6))
story.append(para(
    "Bilirubin is an <b>orange-yellow pigment</b> derived from heme, primarily a product of red blood cell (RBC) "
    "turnover (~80%). It is extracted, biotransformed, and excreted by the liver. Measurement of serum bilirubin "
    "is a key liver function test and is vital in the assessment of jaundice, neonatal hyperbilirubinemia, and "
    "hepatobiliary disorders."
))
story.append(SP(6))

bili_types = [
    ["Form", "Also Known As", "Solubility", "Albumin Bound?", "Appears in Urine?"],
    ["Unconjugated Bilirubin (UCB)", "Indirect Bilirubin", "Lipid-soluble", "Yes (tightly)", "No"],
    ["Conjugated Bilirubin (CB)", "Direct Bilirubin", "Water-soluble", "No", "Yes (when elevated)"],
    ["Delta Bilirubin (δ)", "Albumin-bound CB", "Water-soluble", "Covalently", "No"],
]
story.append(make_table(bili_types,
    [4.5*cm, 3.8*cm, 3*cm, 3*cm, 3*cm],
    header_bg=TEAL))
story.append(SP(5))
story.append(para(
    "<b>Key chemistry:</b> UCB is stabilized by <b>six intramolecular hydrogen bonds</b> in a 'ridge-tile' configuration "
    "(Z,Z conformation) — this makes it water-insoluble and shields it from the diazo reagent. "
    "Phototherapy converts Z,Z → E-isomers, which are water-soluble and can be excreted without conjugation (neonatal jaundice treatment).",
    NOTE
))
story.append(SP(10))

# ════════════════════════════════════════════════════════════════════
# SECTION 2 — PRINCIPLE
# ════════════════════════════════════════════════════════════════════
story.append(SectionHeader("2.  PRINCIPLE: THE DIAZO (VAN DEN BERGH) REACTION", bg=ORANGE))
story.append(SP(6))
story.append(para(
    "All routine serum bilirubin measurements are based on the <b>Diazo Reaction</b>, "
    "discovered by Ehrlich (1883) and applied to serum by <b>Van den Bergh and Muller (1916)</b>. "
    "The current standard method is the <b>Jendrassik-Grof method (1938)</b>, modified by Doumas — the method of choice."
))
story.append(SP(5))
story.append(InfoBox(
    "CHEMICAL REACTION",
    "Diazotized sulfanilic acid reacts with the two central pyrrole rings of bilirubin by electrophilic aromatic "
    "substitution. The central methylene carbon is cleaved, producing two PHENYL-AZO ADDUCTS (azodipyroles / azobilirubin) "
    "that absorb at 540 nm (reddish-purple at neutral pH) or 600 nm (blue at alkaline pH).",
    bg=ORANGE_LIGHT, border=ORANGE
))
story.append(SP(7))

story.append(para("<b>Why the two-step approach?</b>", BODY_BOLD))
react_data = [
    ["Bilirubin Type", "Condition", "Reaction Speed", "Reason"],
    ["Conjugated (Direct)", "Aqueous, NO accelerator", "RAPID (< 1 min)", "Water-soluble; no internal H-bonds blocking diazo access"],
    ["Unconjugated (Indirect)", "Aqueous, NO accelerator", "Very slow", "Albumin-bound; internal H-bonds block diazo reagent"],
    ["Unconjugated (Indirect)", "With accelerator (caffeine-benzoate)", "Rapid", "Accelerator displaces UCB from albumin, breaks H-bonds"],
]
story.append(SP(5))
story.append(make_table(react_data,
    [4*cm, 5*cm, 3.5*cm, 5.8*cm],
    header_bg=ORANGE, alt_row_bg=ORANGE_LIGHT, border_color=ORANGE))
story.append(SP(5))
story.append(para(
    "<b>Preferred accelerator:</b> Caffeine-sodium benzoate (aqueous). <i>NOT</i> methanol or ethanol — "
    "those cause protein precipitation, turbidity, and matrix interference.",
    NOTE
))
story.append(SP(10))

# ════════════════════════════════════════════════════════════════════
# SECTION 3 — REAGENTS
# ════════════════════════════════════════════════════════════════════
story.append(SectionHeader("3.  REAGENTS REQUIRED", bg=PURPLE))
story.append(SP(6))
reagent_data = [
    ["Reagent", "Composition", "Purpose"],
    ["Diazo Reagent", "Sulfanilic acid + NaNO₂ + HCl (freshly prepared)", "Couples with bilirubin to form colored azobilirubin"],
    ["Accelerator", "Caffeine + Sodium benzoate (aqueous solution)", "Displaces UCB from albumin; breaks H-bonds"],
    ["Alkaline Tartrate", "NaOH + Sodium potassium tartrate", "Shifts pH → blue color at 600 nm; increases sensitivity"],
    ["Blank Reagent", "Same as diazo but NaNO₂ replaced by distilled water", "Controls for background color/turbidity of serum"],
    ["Standard", "Known bilirubin concentration in human serum base", "Calibrates the colorimetric reading"],
]
story.append(make_table(reagent_data,
    [3.5*cm, 6.5*cm, 7.3*cm],
    header_bg=PURPLE, alt_row_bg=PURPLE_LIGHT, border_color=PURPLE))
story.append(SP(10))

# ════════════════════════════════════════════════════════════════════
# SECTION 4 — TOTAL BILIRUBIN
# ════════════════════════════════════════════════════════════════════
story.append(SectionHeader("4.  ESTIMATION OF TOTAL BILIRUBIN", bg=TEAL))
story.append(SP(6))
story.append(InfoBox(
    "PRINCIPLE",
    "Total bilirubin = Conjugated + Unconjugated bilirubin. Caffeine-benzoate accelerator displaces ALL bilirubin "
    "from albumin. Both fractions react with diazo reagent. Measured at 600 nm after addition of alkaline tartrate.",
    bg=TEAL_LIGHT, border=TEAL
))
story.append(SP(7))
story.append(para("<b>Procedure:</b>", BODY_BOLD))
total_proc = [
    ["Step", "Action", "Volume/Detail"],
    ["1", "Add serum to test tube", "0.1 mL serum"],
    ["2", "Add caffeine-benzoate accelerator", "0.5 mL — mix well"],
    ["3", "Add diazo reagent", "0.4 mL — mix immediately"],
    ["4", "Incubate at room temperature", "10 minutes (allows full reaction of all bilirubin)"],
    ["5", "Add alkaline tartrate solution", "1.5 mL — shifts to blue color"],
    ["6", "Read absorbance", "At 600 nm (or 540 nm) within 1 hour"],
    ["7", "Run blank simultaneously", "Serum + accelerator + blank reagent (no diazo) — subtract"],
    ["8", "Calculate concentration", "Use calibration curve or standard comparison"],
]
story.append(make_table(total_proc,
    [1.2*cm, 8.5*cm, 7.6*cm],
    header_bg=TEAL, alt_row_bg=TEAL_LIGHT, border_color=TEAL))
story.append(SP(7))
story.append(FormulaBox(
    "Total Bilirubin (mg/dL)  =  (Absorbance of Test ÷ Absorbance of Standard)  ×  Concentration of Standard",
    bg=TEAL_LIGHT, border=TEAL
))
story.append(SP(5))
story.append(para(
    "<b>Normal Range:</b> <b>0.2 – 1.0 mg/dL</b> (3.4 – 17.1 μmol/L)  |  "
    "Jaundice becomes clinically visible at >2.5–3.0 mg/dL (scleral icterus at ~2 mg/dL)."
))
story.append(SP(10))

# ════════════════════════════════════════════════════════════════════
# SECTION 5 — DIRECT BILIRUBIN
# ════════════════════════════════════════════════════════════════════
story.append(SectionHeader("5.  ESTIMATION OF DIRECT (CONJUGATED) BILIRUBIN", bg=GREEN))
story.append(SP(6))
story.append(InfoBox(
    "PRINCIPLE",
    "Direct bilirubin = fraction reacting with diazo reagent in AQUEOUS solution WITHOUT any accelerator. "
    "Only conjugated (water-soluble) bilirubin reacts rapidly. Strict 1-minute reaction window prevents "
    "unconjugated bilirubin from contributing.",
    bg=GREEN_LIGHT, border=GREEN
))
story.append(SP(7))
story.append(para("<b>Procedure:</b>", BODY_BOLD))
direct_proc = [
    ["Step", "Action", "Volume/Detail"],
    ["1", "Add serum to test tube", "0.1 mL serum"],
    ["2", "Add distilled water", "0.9 mL — NO accelerator added"],
    ["3", "Add diazo reagent", "0.4 mL — mix immediately"],
    ["4", "Incubate at room temperature", "EXACTLY 1 minute only"],
    ["5", "Read absorbance immediately", "At 540 nm — do not delay"],
    ["6", "Run blank simultaneously", "Serum + water + blank reagent — subtract"],
]
story.append(make_table(direct_proc,
    [1.2*cm, 8.5*cm, 7.6*cm],
    header_bg=GREEN, alt_row_bg=GREEN_LIGHT, border_color=GREEN))
story.append(SP(7))
story.append(para(
    "<b>Normal Range:</b> <b>0.0 – 0.3 mg/dL</b> (< 5.1 μmol/L)"
))
story.append(para(
    "In normal plasma, only ~<b>4%</b> of total bilirubin is conjugated (direct-reacting). "
    "If direct fraction is <b><15% of total bilirubin</b>, this indicates unconjugated hyperbilirubinemia.",
    NOTE
))
story.append(SP(10))

# ════════════════════════════════════════════════════════════════════
# SECTION 6 — INDIRECT BILIRUBIN
# ════════════════════════════════════════════════════════════════════
story.append(SectionHeader("6.  ESTIMATION OF INDIRECT (UNCONJUGATED) BILIRUBIN", bg=ORANGE))
story.append(SP(6))
story.append(InfoBox(
    "PRINCIPLE",
    "Indirect bilirubin CANNOT be measured directly. It is calculated by subtracting the Direct Bilirubin "
    "from Total Bilirubin. Represents mostly albumin-bound unconjugated bilirubin (slow-reacting fraction).",
    bg=ORANGE_LIGHT, border=ORANGE
))
story.append(SP(7))
story.append(FormulaBox(
    "Indirect Bilirubin  =  Total Bilirubin  –  Direct Bilirubin",
    bg=ORANGE_LIGHT, border=ORANGE
))
story.append(SP(6))
story.append(para(
    "<b>Normal Range:</b> <b>0.1 – 0.8 mg/dL</b> (1.7 – 13.7 μmol/L)"
))
story.append(para(
    "<b>Note:</b> The calculated indirect value may slightly <i>underestimate</i> true unconjugated bilirubin "
    "because a small amount of UCB may react in the direct assay even without accelerator. "
    "Direct and indirect values are not strictly equivalent to conjugated and unconjugated concentrations.",
    NOTE
))
story.append(SP(10))

# ════════════════════════════════════════════════════════════════════
# SECTION 7 — REFERENCE RANGES SUMMARY
# ════════════════════════════════════════════════════════════════════
story.append(SectionHeader("7.  REFERENCE RANGES SUMMARY", bg=PURPLE))
story.append(SP(6))
ref_data = [
    ["Fraction", "Normal Range (mg/dL)", "Normal Range (μmol/L)", "Represents"],
    ["Total Bilirubin", "0.2 – 1.0", "3.4 – 17.1", "All bilirubin species combined"],
    ["Direct (Conjugated)", "0.0 – 0.3", "0.0 – 5.1", "~4% of total in normal plasma"],
    ["Indirect (Unconjugated)", "0.1 – 0.8", "1.7 – 13.7", "~96% of total in normal plasma"],
]
story.append(make_table(ref_data,
    [4.5*cm, 4.2*cm, 4.2*cm, 4.4*cm],
    header_bg=PURPLE, alt_row_bg=PURPLE_LIGHT, border_color=PURPLE))
story.append(SP(10))

# ════════════════════════════════════════════════════════════════════
# SECTION 8 — SOURCES OF ERROR
# ════════════════════════════════════════════════════════════════════
story.append(SectionHeader("8.  IMPORTANT TECHNICAL POINTS & SOURCES OF ERROR", bg=RED))
story.append(SP(6))
error_data = [
    ["Issue", "Explanation / Impact"],
    ["Hemolysis", "Hemoglobin competes with bilirubin; no significant interference up to 25 mg/dL Hb (Beckman AU analyzers). Hemolysis can falsely LOWER bilirubin by oxidation."],
    ["Lipemia", "No significant interference up to 500 mg/dL Intralipid."],
    ["Light exposure", "Bilirubin is photosensitive — samples must be protected from light (amber/covered tubes). Even minutes of exposure can degrade bilirubin significantly."],
    ["Methanol/Ethanol accelerators", "Cause protein precipitation and increased turbidity. Caffeine-benzoate preferred. Malloy-Evelyn method (methanol) is now largely abandoned."],
    ["Delta bilirubin", "Covalently albumin-bound CB. Has ~18–20 day half-life (albumin). NOT accurately measured by standard diazo methods. Important in prolonged cholestasis."],
    ["Direct ≠ Conjugated exactly", "Some UCB appears in 'direct' fraction; some CB (especially delta bilirubin) escapes. Can cause errors in diagnosing isolated disorders like Gilbert syndrome."],
    ["Bovine serum calibrators", "Give incomplete/unpredictable reactions with UCB. Human serum-based calibrators must be used (especially for neonatal bilirubin accuracy)."],
    ["Delayed measurement", "Total bilirubin assay should be read within 1 hour of adding alkaline tartrate. Direct bilirubin must be read immediately after 1-minute reaction."],
]
story.append(make_table(error_data,
    [4.5*cm, 12.8*cm],
    header_bg=RED, alt_row_bg=RED_LIGHT, border_color=RED))
story.append(SP(10))

# ════════════════════════════════════════════════════════════════════
# PAGE BREAK — CLINICAL SECTION
# ════════════════════════════════════════════════════════════════════
story.append(PageBreak())

# ════════════════════════════════════════════════════════════════════
# SECTION 9 — CLINICAL SIGNIFICANCE
# ════════════════════════════════════════════════════════════════════
story.append(SP(8))
story.append(SectionHeader("9.  CLINICAL SIGNIFICANCE", bg=TEAL))
story.append(SP(6))
story.append(para(
    "Bilirubin fractionation allows classification of jaundice and guides the differential diagnosis. "
    "The pattern of elevation (total, direct, indirect) combined with other liver function tests and clinical features "
    "determines whether jaundice is <b>pre-hepatic, hepatic, or post-hepatic</b> in origin."
))
story.append(SP(8))

# 9A — Elevated Indirect
story.append(SectionHeader("9A.  ELEVATED INDIRECT (UNCONJUGATED) BILIRUBIN — Causes", bg=ORANGE, width=W-2.5*cm))
story.append(SP(5))
indirect_causes = [
    ["Category", "Examples"],
    ["↑ Production (overproduction)", "Hemolysis (intravascular/extravascular), ineffective erythropoiesis, blood transfusion, resorption of large hematomas"],
    ["↓ Hepatocellular uptake", "Drugs: rifampin, cyclosporine"],
    ["↓ Conjugation (UGT1A1 deficiency)", "Gilbert syndrome (mild), Crigler-Najjar type I (absent UGT) and type II (reduced UGT), neonatal physiologic jaundice, hypothyroidism"],
]
story.append(make_table(indirect_causes,
    [5.5*cm, 11.8*cm],
    header_bg=ORANGE, alt_row_bg=ORANGE_LIGHT, border_color=ORANGE))
story.append(SP(5))
story.append(InfoBox(
    "NEONATAL JAUNDICE WARNING",
    "UCB > 20–25 mg/dL exceeds albumin binding capacity → crosses blood-brain barrier → "
    "deposits in basal ganglia → KERNICTERUS (toxic encephalopathy). Treatment: Blue-light phototherapy "
    "(450 nm) converts Z,Z bilirubin to water-soluble E-isomers → excreted in bile without conjugation.",
    bg=ORANGE_LIGHT, border=ORANGE
))
story.append(SP(10))

# 9B — Elevated Direct
story.append(SectionHeader("9B.  ELEVATED DIRECT (CONJUGATED) BILIRUBIN — Causes", bg=GREEN, width=W-2.5*cm))
story.append(SP(5))
direct_causes = [
    ["Category", "Examples"],
    ["Hepatocellular disease", "Viral hepatitis (A, B, C, E), alcoholic hepatitis, drug-induced liver injury, cirrhosis, acute liver failure"],
    ["Intrahepatic cholestasis", "Primary biliary cholangitis (PBC), primary sclerosing cholangitis (PSC), intrahepatic cholestasis of pregnancy, drug-induced cholestasis"],
    ["Extrahepatic (post-hepatic) obstruction", "Choledocholithiasis, carcinoma of head of pancreas, cholangiocarcinoma, ampullary carcinoma, biliary strictures"],
    ["Hereditary / Benign", "Dubin-Johnson syndrome, Rotor syndrome"],
]
story.append(make_table(direct_causes,
    [5.5*cm, 11.8*cm],
    header_bg=GREEN, alt_row_bg=GREEN_LIGHT, border_color=GREEN))
story.append(SP(5))
story.append(InfoBox(
    "KEY CLINICAL POINT",
    "Even limited amounts of true conjugated bilirubin in serum indicate significant hepatobiliary pathology. "
    "Conjugated hyperbilirubinemia is ALWAYS associated with bilirubinuria (dark urine / bilirubin on dipstick) "
    "— EXCEPT when it is delta bilirubin (albumin-bound), which cannot be filtered by glomeruli.",
    bg=GREEN_LIGHT, border=GREEN
))
story.append(SP(10))

# 9C — Pattern Diagnosis
story.append(SectionHeader("9C.  DIFFERENTIAL DIAGNOSIS BY BILIRUBIN PATTERN", bg=PURPLE, width=W-2.5*cm))
story.append(SP(5))
pattern_data = [
    ["Bilirubin Pattern", "Likely Diagnosis / Condition"],
    ["↑ Indirect only, Normal Direct", "Hemolysis, Gilbert syndrome, Crigler-Najjar syndrome, neonatal physiologic jaundice"],
    ["↑ Direct predominantly", "Obstructive jaundice (cholestasis: intrahepatic or extrahepatic)"],
    ["↑ Both Direct + Indirect", "Hepatocellular disease (hepatitis, cirrhosis) — mixed pattern"],
    ["↑ Total serum, jaundice persists but Direct falling", "Delta bilirubin accumulation in prolonged cholestasis — 'post-recovery jaundice'"],
    ["Conjugated hyperbilirubinemia WITHOUT bilirubinuria", "Delta bilirubin fraction (albumin-bound; cannot pass glomerulus)"],
]
story.append(make_table(pattern_data,
    [6.5*cm, 10.8*cm],
    header_bg=PURPLE, alt_row_bg=PURPLE_LIGHT, border_color=PURPLE))
story.append(SP(10))

# ════════════════════════════════════════════════════════════════════
# SECTION 10 — DELTA BILIRUBIN
# ════════════════════════════════════════════════════════════════════
story.append(SectionHeader("10.  THE DELTA BILIRUBIN ENIGMA", bg=GOLD))
story.append(SP(6))
story.append(InfoBox(
    "WHAT IS DELTA BILIRUBIN?",
    "Delta bilirubin is conjugated bilirubin COVALENTLY bound to albumin. It forms when hepatic excretion "
    "of bilirubin glucuronides is impaired and glucuronides accumulate in serum. Its half-life mirrors albumin "
    "(18–20 days) rather than free bilirubin (only ~4 hours).",
    bg=GOLD_LIGHT, border=GOLD
))
story.append(SP(6))
delta_data = [
    ["Clinical Enigma", "Explanation"],
    ["Bilirubinuria absent despite conjugated hyperbilirubinemia", "Delta bilirubin (albumin-bound) cannot be filtered by glomeruli due to large molecular size"],
    ["Jaundice persists after apparent biochemical recovery", "Delta bilirubin has 18–20 day half-life matching albumin; clears slowly even after underlying cause resolves"],
    ["Underestimated by standard assays", "Diazo methods and some automated spectroscopic assays fail to accurately detect delta bilirubin"],
]
story.append(make_table(delta_data,
    [6.5*cm, 10.8*cm],
    header_bg=GOLD, alt_row_bg=GOLD_LIGHT, border_color=GOLD))
story.append(SP(10))

# ════════════════════════════════════════════════════════════════════
# SECTION 11 — METHODS COMPARISON
# ════════════════════════════════════════════════════════════════════
story.append(SectionHeader("11.  METHODS FOR BILIRUBIN MEASUREMENT — COMPARISON", bg=TEAL))
story.append(SP(6))
methods_data = [
    ["Method", "Principle", "Status / Use"],
    ["Jendrassik-Grof (modified by Doumas)", "Diazo + caffeine-benzoate accelerator; alkaline tartrate for color development", "METHOD OF CHOICE — reproducible, reliable, transferable"],
    ["Malloy-Evelyn", "Diazo + methanol accelerator", "ABANDONED — protein precipitation, matrix effects, Hb interference"],
    ["Direct spectrophotometry", "Absorbance measurement at two wavelengths; solves two-component equations", "Used in neonates (only UCB present); requires Hb correction"],
    ["HPLC", "Chromatographic separation of α (UCB), β (monoglucuronide), γ (diglucuronide), δ (albumin-bound) fractions", "Research/reference method — not routine clinical use"],
    ["Transcutaneous bilirubinometry", "Non-invasive skin reflectance measurement", "Screening only — NOT a substitute for quantitative serum assay"],
]
story.append(make_table(methods_data,
    [4.5*cm, 6.5*cm, 6.3*cm],
    header_bg=TEAL, alt_row_bg=TEAL_LIGHT, border_color=TEAL))
story.append(SP(10))

# ════════════════════════════════════════════════════════════════════
# SOURCES
# ════════════════════════════════════════════════════════════════════
story.append(HRFlowable(color=TEAL, thickness=1.5, width="100%"))
story.append(SP(5))
story.append(para("<b>Sources:</b>", BODY_BOLD))
sources = [
    "Tietz Textbook of Laboratory Medicine, 7th Edition, pp. 1971–1972",
    "Henry's Clinical Diagnosis and Management by Laboratory Methods, p. 527",
    "Harrison's Principles of Internal Medicine, 22nd Ed., pp. 1650–1655",
    "Sleisenger and Fordtran's Gastrointestinal and Liver Disease, pp. 335–336",
    "Lippincott's Illustrated Reviews: Biochemistry, 8th Ed., p. 805",
]
for s in sources:
    story.append(para(f"• {s}", NOTE))

# ── Build PDF ────────────────────────────────────────────────────────────────
doc.build(story, onFirstPage=on_page, onLaterPages=on_page)
print("PDF created successfully.")
Running Command

cd /home/daytona/workspace/bilirubin-pdf && python create_pdf.py 2>&1

Running Command

ls -lh /home/daytona/workspace/bilirubin-pdf/

Your colorful PDF is ready! Here's the download link:

Bilirubin Estimation Serum

PDF Document · PDF

The PDF includes:
  • Color-coded section headers - each major section has its own color (teal, orange, purple, green, red, gold)
  • Teal header/footer bar on every page with title and page numbers
  • All 11 sections fully formatted with colored tables, info boxes, and formula boxes:
    • Background & types of bilirubin
    • Principle (diazo/Van den Bergh reaction) with chemical details
    • Reagents required
    • Total bilirubin estimation procedure (step-by-step table)
    • Direct bilirubin estimation procedure
    • Indirect bilirubin calculation with formula box
    • Reference ranges summary table
    • Sources of error table
    • Clinical significance with causes of elevated direct/indirect
    • Differential diagnosis by bilirubin pattern
    • Delta bilirubin enigma
    • Methods comparison (Jendrassik-Grof, HPLC, etc.)
  • Alternating row colors in all tables for easy reading
  • Source citations at the bottom
This is a shared conversation. Sign in to Orris to start your own chat.