homocystinuria
homocystinuria[MeSH Terms]


| Category | Defect | Effect on Methionine |
|---|---|---|
| Trans-sulfuration | CBS deficiency (classic) | Methionine ELEVATED |
| Re-methylation - folate | MTHFR deficiency | Methionine low/normal |
| Re-methylation - cobalamin | Methylcobalamin defects (cblC, D, E, G) | Methionine low/normal |
| Feature | Homocystinuria | Marfan Syndrome |
|---|---|---|
| Inheritance | Autosomal recessive | Autosomal dominant |
| Lens dislocation | Downward (inferior) | Upward (superior) |
| Joints | Stiff | Hypermobile |
| Osteoporosis | Present | Absent |
| Intellectual disability | Common | Absent |
| Vascular | Thrombosis | Aortic dissection/dilation |
| Gene | CBS | FBN1 (fibrillin-1) |
| Approach | Detail |
|---|---|
| Pyridoxine (Vit B6) - B6-responsive patients | 50-500 mg/day; acts as CBS coenzyme; milder phenotype, later onset |
| Low-methionine diet | Restricts substrate for homocysteine production |
| Cystine supplementation | Cysteine becomes essential; also replenishes glutathione |
| Betaine | Alternative methyl donor; promotes remethylation of homocysteine → methionine via betaine:homocysteine methyltransferase |
| Folate + Vitamin B12 | Enhance remethylation; particularly useful in MTHFR and cobalamin defects |
| Anticoagulation | If vascular lesions have occurred, prevents further thrombosis |
Generate the pdf
ls /home/daytona/workspace/ 2>/dev/null && mkdir -p /home/daytona/workspace/homo…
~/homocystinuria/generate_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, Image as RLImage
)
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY
from reportlab.platypus import PageBreak
from reportlab.pdfgen import canvas
from reportlab.lib.utils import ImageReader
import urllib.request
import io
import os
OUTPUT = "/home/daytona/workspace/homocystinuria/Homocystinuria.pdf"
# ── Colour palette ──────────────────────────────────────────────────────────
NAVY = colors.HexColor("#1a3a5c")
TEAL = colors.HexColor("#1d7a8a")
LIGHT = colors.HexColor("#e8f4f8")
ACCENT = colors.HexColor("#e84545")
GOLD = colors.HexColor("#e6a817")
LGREY = colors.HexColor("#f5f5f5")
DGREY = colors.HexColor("#444444")
WHITE = colors.white
BLACK = colors.black
# ── Page template with header/footer ────────────────────────────────────────
class MyPage:
def __init__(self, title):
self.title = title
def on_page(self, canv, doc):
canv.saveState()
w, h = A4
# Header bar
canv.setFillColor(NAVY)
canv.rect(0, h - 40, w, 40, fill=1, stroke=0)
canv.setFillColor(WHITE)
canv.setFont("Helvetica-Bold", 13)
canv.drawString(20, h - 26, self.title)
# Footer
canv.setFillColor(TEAL)
canv.rect(0, 0, w, 22, fill=1, stroke=0)
canv.setFillColor(WHITE)
canv.setFont("Helvetica", 8)
canv.drawString(20, 7, "Sources: Tietz Lab Medicine | Lippincott Biochemistry | Adams & Victor Neurology | Goldman-Cecil Medicine | Emery's Genetics")
canv.drawRightString(w - 20, 7, f"Page {doc.page}")
canv.restoreState()
def build_styles():
styles = getSampleStyleSheet()
s = {}
s["h1"] = ParagraphStyle("h1", fontName="Helvetica-Bold", fontSize=22,
textColor=WHITE, leading=28, spaceAfter=4)
s["h2"] = ParagraphStyle("h2", fontName="Helvetica-Bold", fontSize=13,
textColor=WHITE, leading=17, spaceAfter=2)
s["h3"] = ParagraphStyle("h3", fontName="Helvetica-Bold", fontSize=11,
textColor=NAVY, leading=15, spaceBefore=8, spaceAfter=3)
s["body"] = ParagraphStyle("body", fontName="Helvetica", fontSize=9.5,
textColor=DGREY, leading=14, spaceAfter=5,
alignment=TA_JUSTIFY)
s["bullet"] = ParagraphStyle("bullet", fontName="Helvetica", fontSize=9.5,
textColor=DGREY, leading=13, leftIndent=14,
bulletIndent=4, spaceAfter=2)
s["caption"] = ParagraphStyle("caption", fontName="Helvetica-Oblique",
fontSize=8, textColor=colors.HexColor("#666666"),
leading=11, alignment=TA_CENTER, spaceAfter=6)
s["label"] = ParagraphStyle("label", fontName="Helvetica-Bold", fontSize=9,
textColor=TEAL, leading=12, spaceAfter=1)
s["sources"] = ParagraphStyle("sources", fontName="Helvetica-Oblique",
fontSize=7.5, textColor=colors.HexColor("#888888"),
leading=10)
return s
def section_header(text, styles):
"""Coloured section header bar."""
data = [[Paragraph(text, styles["h2"])]]
t = Table(data, colWidths=[17.5*cm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), TEAL),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("ROWBACKGROUNDS", (0,0), (-1,-1), [TEAL]),
]))
return t
def download_image(url, max_w, max_h):
try:
req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"})
data = urllib.request.urlopen(req, timeout=10).read()
img = RLImage(io.BytesIO(data))
iw, ih = img.imageWidth, img.imageHeight
ratio = min(max_w/iw, max_h/ih)
img.drawWidth = iw * ratio
img.drawHeight = ih * ratio
return img
except Exception as e:
print(f" [img skip] {e}")
return None
def build():
sty = build_styles()
pg = MyPage("Homocystinuria — Clinical Reference")
doc = SimpleDocTemplate(
OUTPUT, pagesize=A4,
leftMargin=1.8*cm, rightMargin=1.8*cm,
topMargin=1.8*cm, bottomMargin=1.5*cm,
title="Homocystinuria", author="Orris Medical"
)
story = []
W = 17.5*cm # usable width
# ── TITLE BLOCK ──────────────────────────────────────────────────────────
title_data = [[Paragraph("Homocystinuria", sty["h1"])],
[Paragraph("Inborn Error of Sulfur Amino Acid Metabolism — Complete Clinical Reference", sty["body"])]]
title_tbl = Table(title_data, colWidths=[W])
title_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), NAVY),
("LEFTPADDING", (0,0), (-1,-1), 14),
("RIGHTPADDING", (0,0), (-1,-1), 14),
("TOPPADDING", (0,0), (-1, 0), 14),
("BOTTOMPADDING",(0,-1),(-1,-1), 14),
("TEXTCOLOR", (0,1),(-1,1), colors.HexColor("#ccddee")),
]))
story.append(title_tbl)
story.append(Spacer(1, 10))
# ── OVERVIEW ─────────────────────────────────────────────────────────────
story.append(section_header("Overview", sty))
story.append(Spacer(1, 5))
story.append(Paragraph(
"Homocystinuria is a group of autosomal recessive inborn errors of metabolism "
"characterized by elevated homocysteine in blood and urine. The most common form "
"— <b>classic homocystinuria</b> — results from deficiency of "
"<b>cystathionine β-synthase (CBS)</b>, a pyridoxal phosphate (PLP/B6)-dependent "
"enzyme in the trans-sulfuration pathway. At least 7 distinct genetic disorders can "
"cause homocystinuria. Worldwide incidence of CBS deficiency is ~1:300,000 live births "
"(up to 1:1,800 in Qatar). Normal plasma total homocysteine is <b><15 µM</b>; "
"levels >50 µM suggest an inherited metabolic disorder.", sty["body"]))
story.append(Spacer(1, 6))
# ── METABOLIC PATHWAY ────────────────────────────────────────────────────
story.append(section_header("Metabolic Pathway", sty))
story.append(Spacer(1, 5))
img1_url = "https://cdn.orris.care/cdss_images/ee87c95e62add7dbc0dcad974256abd1fabb2d00bf2daaf4a7fdebac3dd6a04d.png"
img1 = download_image(img1_url, W, 9*cm)
if img1:
story.append(img1)
story.append(Paragraph(
"Sulfur amino acid metabolism. Methionine transfers a methyl group during conversion "
"to homocysteine. CBS (trans-sulfuration) deficiency raises methionine; remethylation "
"defects (MTHFR, cobalamin pathway) cause low/normal methionine. "
"— Tietz Textbook of Laboratory Medicine, 7th ed.", sty["caption"]))
story.append(Spacer(1, 4))
img2_url = "https://cdn.orris.care/cdss_images/76897b41e995b771cd6163d45eb6b4d85c250f311e415adaea63091e2e3c9f01.png"
img2 = download_image(img2_url, 6*cm, 7*cm)
if img2:
story.append(img2)
story.append(Paragraph(
"CBS reaction: Homocysteine + L-Serine → Cystathionine (requires PLP). "
"— Lippincott Biochemistry, 8th ed.", sty["caption"]))
story.append(Spacer(1, 6))
# ── CAUSES / CLASSIFICATION ───────────────────────────────────────────────
story.append(section_header("Causes / Classification", sty))
story.append(Spacer(1, 5))
cause_data = [
[Paragraph("<b>Category</b>", sty["label"]),
Paragraph("<b>Defect</b>", sty["label"]),
Paragraph("<b>Methionine Level</b>", sty["label"])],
[Paragraph("Trans-sulfuration", sty["body"]),
Paragraph("CBS deficiency (classic)", sty["body"]),
Paragraph("ELEVATED", sty["body"])],
[Paragraph("Re-methylation (folate)", sty["body"]),
Paragraph("MTHFR deficiency", sty["body"]),
Paragraph("Low / Normal", sty["body"])],
[Paragraph("Re-methylation (cobalamin)", sty["body"]),
Paragraph("Methylcobalamin defects (cblC, D, E, G)", sty["body"]),
Paragraph("Low / Normal", sty["body"])],
]
cause_tbl = Table(cause_data, colWidths=[4.5*cm, 8*cm, 5*cm])
cause_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), NAVY),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("BACKGROUND", (0,1), (-1,1), LIGHT),
("BACKGROUND", (0,2), (-1,2), LGREY),
("BACKGROUND", (0,3), (-1,3), LIGHT),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#cccccc")),
("LEFTPADDING", (0,0), (-1,-1), 7),
("RIGHTPADDING", (0,0), (-1,-1), 7),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING",(0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
]))
story.append(cause_tbl)
story.append(Spacer(1, 8))
# ── PATHOPHYSIOLOGY ───────────────────────────────────────────────────────
story.append(section_header("Pathophysiology (CBS Deficiency)", sty))
story.append(Spacer(1, 5))
path_bullets = [
"CBS normally condenses homocysteine + serine → cystathionine (trans-sulfuration pathway).",
"CBS deficiency causes homocysteine accumulation, methionine rise, and <b>cysteine deficiency</b> (cysteine becomes conditionally essential).",
"Excess homocysteine damages vascular endothelium, activates platelets, and promotes thrombosis.",
"Homocysteine interferes with collagen cross-linking → skeletal and connective tissue abnormalities.",
"Reduced cysteine lowers glutathione → increased oxidative stress.",
"Cystathionine (normally present in brain) is absent → may explain developmental delay.",
]
for b in path_bullets:
story.append(Paragraph(f"• {b}", sty["bullet"]))
story.append(Spacer(1, 6))
# ── CLINICAL FEATURES ─────────────────────────────────────────────────────
story.append(section_header("Clinical Features — Classic CBS Deficiency", sty))
story.append(Spacer(1, 5))
features = [
("Ocular",
["Downward ectopia lentis (inferiorly dislocated lens) — pathognomonic",
"Myopia, iridodonesis (tremulous iris)",
"CONTRAST with Marfan syndrome: lens dislocates superiorly in Marfan"]),
("Skeletal (Marfanoid Habitus)",
["Tall, slender build with long limbs; arachnodactyly",
"Scoliosis, kyphosis, pectus excavatum",
"Osteoporosis (not seen in Marfan syndrome)",
"Knock-knees, highly arched feet",
"STIFF joints (contrast: Marfan has hypermobile joints)"]),
("Vascular",
["Thromboembolic episodes — major cause of morbidity and mortality",
"Affects both arteries and veins; can occur even in children",
"Thickening/fibrosis of coronary, cerebral, renal arteries",
"Risk of stroke, MI (some die of coronary occlusion in adolescence)"]),
("Neurological / Psychiatric",
["Intellectual disability (mild-moderate) — key differentiator from Marfan",
"Seizures",
"Psychiatric disturbances, developmental delay"]),
("Dermatological",
["Sparse, brittle, blond hair",
"Malar flush",
"Livedo reticularis"]),
]
for sys_name, bullets in features:
story.append(Paragraph(sys_name, sty["h3"]))
for b in bullets:
story.append(Paragraph(f"• {b}", sty["bullet"]))
story.append(Spacer(1, 3))
story.append(Spacer(1, 4))
# ── VS MARFAN ─────────────────────────────────────────────────────────────
story.append(section_header("Homocystinuria vs. Marfan Syndrome", sty))
story.append(Spacer(1, 5))
marfan_data = [
[Paragraph("<b>Feature</b>", sty["label"]),
Paragraph("<b>Homocystinuria</b>", sty["label"]),
Paragraph("<b>Marfan Syndrome</b>", sty["label"])],
["Inheritance", "Autosomal recessive", "Autosomal dominant"],
["Lens dislocation", "Downward (inferior)", "Upward (superior)"],
["Joints", "Stiff", "Hypermobile"],
["Osteoporosis", "Present", "Absent"],
["Intellectual disability", "Common", "Absent"],
["Vascular complication", "Thrombosis", "Aortic dissection/dilation"],
["Gene", "CBS (cystathionine β-synthase)", "FBN1 (fibrillin-1)"],
]
marfan_data_fmt = []
for i, row in enumerate(marfan_data):
if i == 0:
marfan_data_fmt.append(row)
else:
marfan_data_fmt.append([Paragraph(str(c), sty["body"]) for c in row])
marfan_tbl = Table(marfan_data_fmt, colWidths=[4.5*cm, 6.5*cm, 6.5*cm])
marfan_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), NAVY),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
*[("BACKGROUND", (0,i), (-1,i), LIGHT if i%2==1 else LGREY) for i in range(1,8)],
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#cccccc")),
("LEFTPADDING", (0,0), (-1,-1), 7),
("RIGHTPADDING", (0,0), (-1,-1), 7),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING",(0,0), (-1,-1), 4),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
]))
story.append(marfan_tbl)
story.append(Spacer(1, 8))
# ── DIAGNOSIS ─────────────────────────────────────────────────────────────
story.append(section_header("Diagnosis", sty))
story.append(Spacer(1, 5))
diag_data = [
[Paragraph("<b>Test</b>", sty["label"]),
Paragraph("<b>Finding</b>", sty["label"]),
Paragraph("<b>Notes</b>", sty["label"])],
["Cyanide-nitroprusside test (urine)",
"Purple colour = positive",
"Screening; detects elevated urinary homocysteine"],
["Plasma amino acids",
"↑ Methionine + ↑ Homocysteine",
"Classic CBS; low/normal Met in remethylation defects"],
["Total plasma homocysteine",
">50 µM (normal <15 µM)",
"By immunoassay, HPLC, or MS/MS"],
["Newborn screening (MS/MS)",
"Elevated methionine",
"Detects CBS deficiency early"],
["CBS gene analysis",
"CBS mutation",
"Confirms diagnosis; determines B6-responsiveness"],
]
diag_fmt = []
for i, row in enumerate(diag_data):
if i == 0:
diag_fmt.append(row)
else:
diag_fmt.append([Paragraph(str(c), sty["body"]) for c in row])
diag_tbl = Table(diag_fmt, colWidths=[4.5*cm, 6*cm, 7*cm])
diag_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), NAVY),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
*[("BACKGROUND", (0,i), (-1,i), LIGHT if i%2==1 else LGREY) for i in range(1,6)],
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#cccccc")),
("LEFTPADDING", (0,0), (-1,-1), 7),
("RIGHTPADDING", (0,0), (-1,-1), 7),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING",(0,0), (-1,-1), 4),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
]))
story.append(diag_tbl)
story.append(Spacer(1, 8))
# ── TREATMENT ─────────────────────────────────────────────────────────────
story.append(section_header("Treatment", sty))
story.append(Spacer(1, 5))
story.append(Paragraph(
"Treatment depends on whether the patient is <b>B6-responsive</b> (~50% of CBS-deficient patients). "
"B6-non-responsive patients require stricter dietary management and typically have earlier, more severe disease.",
sty["body"]))
story.append(Spacer(1, 4))
tx_data = [
[Paragraph("<b>Approach</b>", sty["label"]),
Paragraph("<b>Details</b>", sty["label"])],
["Pyridoxine (Vit B6) — B6-responsive patients",
"50-500 mg/day; acts as CBS coenzyme; milder phenotype with later onset"],
["Low-methionine diet",
"Restricts substrate for homocysteine production"],
["Cystine supplementation",
"Cysteine becomes essential; replenishes glutathione and reduces oxidative stress"],
["Betaine",
"Alternative methyl donor; promotes remethylation of Hcy → methionine via betaine:homocysteine methyltransferase"],
["Folate + Vitamin B12",
"Enhance remethylation; particularly useful in MTHFR and cobalamin defects"],
["Anticoagulation",
"If vascular lesions have occurred; prevents further thrombotic events"],
]
tx_fmt = []
for i, row in enumerate(tx_data):
if i == 0:
tx_fmt.append(row)
else:
tx_fmt.append([Paragraph(str(c), sty["body"]) for c in row])
tx_tbl = Table(tx_fmt, colWidths=[6.5*cm, 11*cm])
tx_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), NAVY),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
*[("BACKGROUND", (0,i), (-1,i), LIGHT if i%2==1 else LGREY) for i in range(1,7)],
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#cccccc")),
("LEFTPADDING", (0,0), (-1,-1), 7),
("RIGHTPADDING", (0,0), (-1,-1), 7),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING",(0,0), (-1,-1), 4),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
]))
story.append(tx_tbl)
story.append(Spacer(1, 8))
# ── OTHER CAUSES ──────────────────────────────────────────────────────────
story.append(section_header("Other Causes of Homocystinuria / Hyperhomocysteinemia", sty))
story.append(Spacer(1, 5))
other = [
"<b>MTHFR deficiency:</b> Stroke, dementia, epilepsy, polyneuropathy; methionine low/normal.",
"<b>Methylcobalamin pathway defects (cblC, D, E, G):</b> Also cause megaloblastic anemia, developmental delay.",
"<b>Nutritional (acquired):</b> Severe vitamin B12 or folate deficiency.",
"<b>Mild hyperhomocysteinemia</b> (>15 µM) in otherwise normal individuals: independent cardiovascular risk factor for coronary artery disease and stroke.",
]
for b in other:
story.append(Paragraph(f"• {b}", sty["bullet"]))
story.append(Spacer(1, 6))
# ── KEY SUMMARY BOX ──────────────────────────────────────────────────────
summary_items = [
"Classic homocystinuria = CBS deficiency (autosomal recessive)",
"Biochemistry: high homocysteine + high methionine in plasma and urine",
"Clinical tetrad: ectopia lentis (inferior) + marfanoid habitus + thromboembolism + intellectual disability",
"Thrombosis is the leading cause of death",
"~50% of CBS cases respond to pyridoxine (B6)",
"Differentiate from Marfan by: lens direction (down vs up), osteoporosis, intellectual disability, joint stiffness",
"Screen with cyanide-nitroprusside test; confirm with plasma homocysteine + CBS gene analysis",
]
summary_content = [Paragraph("Key Summary Points", sty["h2"])]
for item in summary_items:
summary_content.append(Paragraph(f"✓ {item}", sty["bullet"]))
sum_data = [[c] for c in summary_content]
sum_tbl = Table([[c] for c in [
Paragraph("Key Summary Points", sty["h2"]),
*[Paragraph(f" ✓ {item}", sty["bullet"]) for item in summary_items]
]], colWidths=[W])
sum_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), GOLD),
("BACKGROUND", (0,1), (-1,-1), colors.HexColor("#fffbe6")),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING", (0,0), (-1,-1), 10),
("TOPPADDING", (0,0), (-1, 0), 7),
("TOPPADDING", (0,1), (-1,-1), 3),
("BOTTOMPADDING",(0,0), (-1, 0), 7),
("BOTTOMPADDING",(0,-1),(-1,-1), 8),
("BOX", (0,0), (-1,-1), 0.8, GOLD),
]))
story.append(sum_tbl)
story.append(Spacer(1, 10))
# ── SOURCES ───────────────────────────────────────────────────────────────
story.append(HRFlowable(width=W, thickness=0.5, color=colors.HexColor("#cccccc")))
story.append(Spacer(1, 4))
story.append(Paragraph(
"Sources: Tietz Textbook of Laboratory Medicine (7th ed.) | Lippincott Illustrated Reviews: Biochemistry (8th ed.) | "
"Adams and Victor's Principles of Neurology (12th ed.) | Goldman-Cecil Medicine | "
"Emery's Elements of Medical Genetics and Genomics | Miller's Review of Orthopaedics (9th ed.) | "
"Recent reviews: PMID 40495464, PMID 41235668.",
sty["sources"]))
doc.build(story, onFirstPage=pg.on_page, onLaterPages=pg.on_page)
print(f"PDF written to {OUTPUT}")
build()
cd /home/daytona/workspace/homocystinuria && python generate_pdf.py 2>&1
ls -lh /home/daytona/workspace/homocystinuria/Homocystinuria.pdf
Homocystinuria
PDF Document · PDF