Serum protein electophoresis and all detailed of this including all abnormal findings and how to see the report explain in detail in ppt
serum protein electrophoresis pattern normal abnormal
mkdir -p /tmp/workspace/spep-ppt && ls /tmp/workspace/spep-ppt/
~/spep-ppt/build_spep.py
from pptx import Presentation
from pptx.util import Inches, Pt, Emu
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.util import Inches, Pt
import json, subprocess, base64
from io import BytesIO
prs = Presentation()
prs.slide_width = Inches(13.333)
prs.slide_height = Inches(7.5)
blank = prs.slide_layouts[6]
# ---- COLOR PALETTE ----
DARK_BLUE = RGBColor(0x1A, 0x35, 0x5E) # title bar bg
MID_BLUE = RGBColor(0x1F, 0x6D, 0xA6) # accent / subheading
LIGHT_BLUE = RGBColor(0xD6, 0xEA, 0xF8) # content box bg
WHITE = RGBColor(0xFF, 0xFF, 0xFF)
DARK_GRAY = RGBColor(0x2C, 0x3E, 0x50)
YELLOW_ACC = RGBColor(0xFF, 0xD7, 0x00)
GREEN_ACC = RGBColor(0x27, 0xAE, 0x60)
RED_ACC = RGBColor(0xC0, 0x39, 0x2B)
ORANGE_ACC = RGBColor(0xE6, 0x7E, 0x22)
LIGHT_GREEN = RGBColor(0xD5, 0xF5, 0xE3)
LIGHT_RED = RGBColor(0xFD, 0xED, 0xEC)
LIGHT_ORANGE= RGBColor(0xFE, 0xF9, 0xE7)
LIGHT_GRAY = RGBColor(0xF2, 0xF3, 0xF4)
TEAL = RGBColor(0x11, 0x7A, 0x65)
# ---- HELPER FUNCTIONS ----
def add_rect(slide, x, y, w, h, fill_color=None, line_color=None, line_width=Pt(0)):
from pptx.util import Pt as _Pt
shape = slide.shapes.add_shape(1, Inches(x), Inches(y), Inches(w), Inches(h))
if fill_color:
shape.fill.solid()
shape.fill.fore_color.rgb = fill_color
else:
shape.fill.background()
if line_color:
shape.line.color.rgb = line_color
shape.line.width = line_width
else:
shape.line.fill.background()
return shape
def add_text(slide, text, x, y, w, h, font_size=18, bold=False, color=DARK_GRAY,
align=PP_ALIGN.LEFT, italic=False, word_wrap=True, v_anchor=MSO_ANCHOR.TOP):
tb = slide.shapes.add_textbox(Inches(x), Inches(y), Inches(w), Inches(h))
tf = tb.text_frame
tf.word_wrap = word_wrap
tf.vertical_anchor = v_anchor
tf.margin_left = Inches(0.05)
tf.margin_right = Inches(0.05)
tf.margin_top = Inches(0.03)
tf.margin_bottom = Inches(0.03)
p = tf.paragraphs[0]
p.alignment = align
run = p.add_run()
run.text = text
run.font.size = Pt(font_size)
run.font.bold = bold
run.font.italic = italic
run.font.color.rgb = color
run.font.name = "Calibri"
return tf
def add_multiline_textbox(slide, lines, x, y, w, h, font_size=15, bold_first=False,
color=DARK_GRAY, bullet_char="•", word_wrap=True):
"""lines: list of (text, bold, color, size, indent) tuples or plain strings"""
tb = slide.shapes.add_textbox(Inches(x), Inches(y), Inches(w), Inches(h))
tf = tb.text_frame
tf.word_wrap = word_wrap
tf.margin_left = Inches(0.08)
tf.margin_right = Inches(0.05)
tf.margin_top = Inches(0.05)
tf.margin_bottom = Inches(0.03)
first = True
for line in lines:
if isinstance(line, str):
text = line; b = False; c = color; s = font_size; indent = 0
else:
text, b, c, s, indent = line
if first:
p = tf.paragraphs[0]
first = False
else:
p = tf.add_paragraph()
p.alignment = PP_ALIGN.LEFT
p.level = indent
if indent > 0:
p.space_before = Pt(2)
run = p.add_run()
run.text = text
run.font.size = Pt(s)
run.font.bold = b
run.font.color.rgb = c
run.font.name = "Calibri"
return tf
def add_title_bar(slide, title, subtitle=None):
# Full-width dark blue header bar
add_rect(slide, 0, 0, 13.333, 1.15, fill_color=DARK_BLUE)
add_text(slide, title, 0.3, 0.08, 12.5, 0.65, font_size=30, bold=True, color=WHITE,
align=PP_ALIGN.LEFT)
if subtitle:
add_text(slide, subtitle, 0.3, 0.72, 12.5, 0.4, font_size=16, bold=False,
color=RGBColor(0xAE, 0xCC, 0xEE), align=PP_ALIGN.LEFT)
# Bottom accent line
add_rect(slide, 0, 1.15, 13.333, 0.05, fill_color=YELLOW_ACC)
def add_footer(slide, text="Serum Protein Electrophoresis (SPEP) | Clinical Pathology Reference"):
add_rect(slide, 0, 7.25, 13.333, 0.25, fill_color=DARK_BLUE)
add_text(slide, text, 0.3, 7.26, 12.5, 0.22, font_size=9, color=RGBColor(0xAA, 0xBB, 0xCC),
align=PP_ALIGN.LEFT)
def add_section_box(slide, title, x, y, w, h, bg=LIGHT_BLUE, title_color=DARK_BLUE):
add_rect(slide, x, y, w, 0.38, fill_color=bg, line_color=MID_BLUE, line_width=Pt(1.5))
add_text(slide, title, x+0.08, y+0.03, w-0.16, 0.33, font_size=14, bold=True, color=title_color)
return y + 0.38
def fetch_image_b64(url):
result = json.loads(subprocess.check_output(
["python", "/tmp/skills/shared/scripts/fetch_images.py", url]
))
if result and result[0]["base64"]:
return result[0]["base64"]
return None
def add_image_from_url(slide, url, x, y, w, h=None):
b64 = fetch_image_b64(url)
if b64:
mime, data = b64.split(";base64,", 1)
raw = base64.b64decode(data)
buf = BytesIO(raw)
pic = slide.shapes.add_picture(buf, Inches(x), Inches(y), width=Inches(w))
if h:
pic.height = Inches(h)
return pic
return None
# ============================================================
# SLIDE 1: TITLE SLIDE
# ============================================================
slide = prs.slides.add_slide(blank)
add_rect(slide, 0, 0, 13.333, 7.5, fill_color=DARK_BLUE)
add_rect(slide, 0, 2.8, 13.333, 0.08, fill_color=YELLOW_ACC)
add_rect(slide, 0, 4.5, 13.333, 0.08, fill_color=YELLOW_ACC)
add_text(slide, "Serum Protein Electrophoresis", 0.8, 1.1, 11.8, 1.2,
font_size=44, bold=True, color=WHITE, align=PP_ALIGN.CENTER)
add_text(slide, "(SPEP)", 0.8, 2.25, 11.8, 0.55,
font_size=32, bold=False, color=YELLOW_ACC, align=PP_ALIGN.CENTER)
add_text(slide, "Principles • Methodology • Normal & Abnormal Patterns", 0.8, 3.05, 11.8, 0.55,
font_size=18, bold=False, color=RGBColor(0xAE, 0xCC, 0xEE), align=PP_ALIGN.CENTER)
add_text(slide, "How to Read & Interpret the SPEP Report", 0.8, 3.7, 11.8, 0.45,
font_size=16, bold=True, color=YELLOW_ACC, align=PP_ALIGN.CENTER)
add_text(slide, "Source: Quick Compendium of Clinical Pathology, 5th Edition", 0.8, 4.75, 11.8, 0.4,
font_size=13, color=RGBColor(0x88, 0xAA, 0xCC), align=PP_ALIGN.CENTER)
add_text(slide, "Clinical Pathology | Laboratory Medicine", 0.8, 5.15, 11.8, 0.4,
font_size=14, color=RGBColor(0xCC, 0xDD, 0xEE), align=PP_ALIGN.CENTER)
# ============================================================
# SLIDE 2: WHAT IS SPEP?
# ============================================================
slide = prs.slides.add_slide(blank)
add_rect(slide, 0, 0, 13.333, 7.5, fill_color=WHITE)
add_title_bar(slide, "What is Serum Protein Electrophoresis (SPEP)?")
add_footer(slide)
# Left column
add_rect(slide, 0.3, 1.3, 6.1, 5.7, fill_color=LIGHT_BLUE, line_color=MID_BLUE, line_width=Pt(1))
add_text(slide, "Definition & Principle", 0.4, 1.35, 5.9, 0.4, font_size=14, bold=True, color=DARK_BLUE)
add_multiline_textbox(slide, [
("• SPEP is a laboratory technique that separates serum proteins by size and electrical charge in an electric field", False, DARK_GRAY, 14, 0),
("• Proteins migrate toward the anode (positive electrode) at different speeds depending on their charge and molecular weight", False, DARK_GRAY, 14, 0),
("• Result displayed as densitometric tracing (peaks) or gel electrophoresis bands", False, DARK_GRAY, 14, 0),
("• Identifies and quantifies 6 major protein fractions:", True, DARK_BLUE, 14, 0),
(" 1. Prealbumin (transthyretin)", False, DARK_GRAY, 13, 0),
(" 2. Albumin", False, DARK_GRAY, 13, 0),
(" 3. Alpha-1 (α1) globulins", False, DARK_GRAY, 13, 0),
(" 4. Alpha-2 (α2) globulins", False, DARK_GRAY, 13, 0),
(" 5. Beta (β) globulins", False, DARK_GRAY, 13, 0),
(" 6. Gamma (γ) globulins", False, DARK_GRAY, 13, 0),
], 0.35, 1.78, 6.0, 5.0)
# Right column
add_rect(slide, 6.7, 1.3, 6.3, 2.6, fill_color=LIGHT_GREEN, line_color=GREEN_ACC, line_width=Pt(1))
add_text(slide, "Clinical Indications", 0.1+6.7, 1.35, 6.1, 0.38, font_size=14, bold=True, color=TEAL)
add_multiline_textbox(slide, [
("• Suspected monoclonal gammopathy or myeloma", False, DARK_GRAY, 13, 0),
("• Evaluation of nephrotic syndrome", False, DARK_GRAY, 13, 0),
("• Screening for chronic liver disease / cirrhosis", False, DARK_GRAY, 13, 0),
("• Evaluation of chronic inflammatory states", False, DARK_GRAY, 13, 0),
("• Assessment of nutritional status / hypoalbuminemia", False, DARK_GRAY, 13, 0),
("• Alpha-1 antitrypsin deficiency workup", False, DARK_GRAY, 13, 0),
("• Investigation of immune deficiencies", False, DARK_GRAY, 13, 0),
], 6.8, 1.72, 6.1, 2.15)
add_rect(slide, 6.7, 4.1, 6.3, 2.9, fill_color=LIGHT_ORANGE, line_color=ORANGE_ACC, line_width=Pt(1))
add_text(slide, "Specimen & Method", 0.1+6.7, 4.15, 6.1, 0.38, font_size=14, bold=True, color=ORANGE_ACC)
add_multiline_textbox(slide, [
("• Specimen: Serum (NOT plasma — fibrinogen causes pseudo-band)", False, DARK_GRAY, 13, 0),
("• High-resolution agarose gel electrophoresis (most common)", False, DARK_GRAY, 13, 0),
("• Capillary zone electrophoresis (CZE) — increasingly used", False, DARK_GRAY, 13, 0),
("• Result reported as % and g/dL for each fraction", False, DARK_GRAY, 13, 0),
("• Total protein and albumin/globulin (A/G) ratio calculated", False, DARK_GRAY, 13, 0),
], 6.8, 4.55, 6.1, 2.35)
# ============================================================
# SLIDE 3: MAJOR SERUM PROTEINS TABLE
# ============================================================
slide = prs.slides.add_slide(blank)
add_rect(slide, 0, 0, 13.333, 7.5, fill_color=WHITE)
add_title_bar(slide, "Major Serum Proteins — Electrophoretic Fractions",
subtitle="Each fraction reflects specific proteins with distinct clinical significance")
add_footer(slide)
rows = [
("Fraction", "Key Protein(s)", "Function / Clinical Notes", True),
("Prealbumin\n(Transthyretin)", "Transthyretin, RBP", "Best marker of nutritional status; negative acute phase reactant; short half-life (2 days)", False),
("Albumin", "Albumin", "Most abundant protein; maintains oncotic pressure; binds drugs, hormones, fatty acids; half-life 17 days; negative acute phase reactant", False),
("α1 globulin", "α1-Antitrypsin (AAT)\nα1-Acid glycoprotein\nα1-Fetoprotein", "AAT = main component; protease inhibitor; acute phase reactant; decreased in AAT deficiency", False),
("α2 globulin", "Haptoglobin\nα2-Macroglobulin\nCeruloplasmin", "Haptoglobin binds free Hb (depleted in hemolysis); α2-Macroglobulin: NOT lost in nephrosis (large size) → elevated in nephrotic syndrome", False),
("β globulin\n(β1 & β2)", "Transferrin (β1)\nC3 complement (β2)\nLDL, IgA (β2)", "Transferrin: iron transport, ↑ in iron deficiency; C3 complement in β2; IgA paraprotein may migrate here", False),
("γ globulin", "IgG, IgA, IgM, IgD, IgE\nCRP, fibrinogen (if plasma)", "Site of immunoglobulins; M-spike seen here in myeloma (usually IgG); broad polyclonal rise in chronic infection", False),
]
col_widths = [1.9, 2.5, 7.4]
col_x = [0.25, 2.2, 4.75]
row_h = 0.82
start_y = 1.3
colors_bg = [DARK_BLUE, LIGHT_BLUE, LIGHT_GREEN, LIGHT_ORANGE, LIGHT_RED,
RGBColor(0xF5, 0xEC, 0xFF), LIGHT_GRAY]
text_colors_hdr = WHITE
for ri, (c0, c1, c2, is_header) in enumerate(rows):
y = start_y + ri * row_h
bg = DARK_BLUE if is_header else colors_bg[ri]
tc = WHITE if is_header else DARK_GRAY
for ci, (cx, cw, ct) in enumerate(zip(col_x, col_widths, [c0, c1, c2])):
add_rect(slide, cx, y, cw, row_h - 0.04, fill_color=bg,
line_color=MID_BLUE, line_width=Pt(0.5))
add_multiline_textbox(slide, [
(ct, is_header, tc if is_header else (DARK_BLUE if ci == 0 else DARK_GRAY),
13 if not is_header else 14, 0)
], cx + 0.05, y + 0.05, cw - 0.1, row_h - 0.14)
# ============================================================
# SLIDE 4: NORMAL SPEP PATTERN
# ============================================================
slide = prs.slides.add_slide(blank)
add_rect(slide, 0, 0, 13.333, 7.5, fill_color=WHITE)
add_title_bar(slide, "Normal SPEP Pattern",
subtitle="Understanding the baseline — what to expect in a healthy individual")
add_footer(slide)
# Left: image
add_image_from_url(slide,
"https://cdn.orris.care/cdss_images/765119bd78e9873c8d751f719b5a823eddefcfe0e36efd07b0902eb28257ddec.png",
0.3, 1.3, 5.8)
# Right: description
add_rect(slide, 6.4, 1.3, 6.6, 5.9, fill_color=LIGHT_BLUE, line_color=MID_BLUE, line_width=Pt(1.2))
add_text(slide, "Features of Normal SPEP", 6.55, 1.35, 6.35, 0.42, font_size=15, bold=True, color=DARK_BLUE)
add_multiline_textbox(slide, [
("PREALBUMIN", True, DARK_BLUE, 13, 0),
(" Nearly invisible / very faint band", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 10, 0),
("ALBUMIN", True, DARK_BLUE, 13, 0),
(" Largest, tallest peak — fastest migrating band", False, DARK_GRAY, 13, 0),
(" ~52-66% of total protein | 3.5-5.0 g/dL", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 10, 0),
("α1 BAND", True, DARK_BLUE, 13, 0),
(" Small, sharp peak just after albumin", False, DARK_GRAY, 13, 0),
(" ~3.9-5.8% | 0.2-0.4 g/dL", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 10, 0),
("α2 BAND", True, DARK_BLUE, 13, 0),
(" Somewhat broader peak", False, DARK_GRAY, 13, 0),
(" ~7.5-13.4% | 0.5-0.9 g/dL", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 10, 0),
("β BAND (bi-nodal)", True, DARK_BLUE, 13, 0),
(" Bi-nodal (β1 + β2); moderate height", False, DARK_GRAY, 13, 0),
(" ~8.5-13.7% | 0.6-1.0 g/dL", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 10, 0),
("γ BAND", True, DARK_BLUE, 13, 0),
(" Broad, diffuse, low-level plateau", False, DARK_GRAY, 13, 0),
(" ~8.8-19.2% | 0.6-1.4 g/dL", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 10, 0),
("A/G Ratio: Normal = 1.2-2.5", True, TEAL, 14, 0),
], 6.55, 1.8, 6.3, 5.25)
# ============================================================
# SLIDE 5: HOW TO READ SPEP REPORT
# ============================================================
slide = prs.slides.add_slide(blank)
add_rect(slide, 0, 0, 13.333, 7.5, fill_color=WHITE)
add_title_bar(slide, "How to Read an SPEP Report — Step-by-Step",
subtitle="A systematic approach to interpreting every SPEP result")
add_footer(slide)
steps = [
("STEP 1", "Check Total Protein", "Normal: 6.0-8.0 g/dL. Low = malnutrition / protein loss. High = may suggest paraprotein.", DARK_BLUE, LIGHT_BLUE),
("STEP 2", "Assess Albumin Band", "Largest band. Reduced in liver disease, nephrotic syndrome, malnutrition, acute illness. Half-life: 17 days.", MID_BLUE, RGBColor(0xEB, 0xF5, 0xFB)),
("STEP 3", "Calculate A/G Ratio", "A/G = Albumin / (Total Protein - Albumin). Low ratio (<1.2) → globulin excess or albumin loss. Reversed A/G = important flag.", TEAL, LIGHT_GREEN),
("STEP 4", "Evaluate α1 & α2 Bands", "↑ α1 + α2 = acute phase response (infection, inflammation). ↑ α2 alone with ↓ albumin = nephrotic syndrome. ↓ α1 = AAT deficiency.", ORANGE_ACC, LIGHT_ORANGE),
("STEP 5", "Examine β Band", "β-γ bridging (no gap between β and γ) = cirrhosis hallmark. IgA paraprotein migrates to β. Iron deficiency → ↑ transferrin (↑ β1).", RED_ACC, LIGHT_RED),
("STEP 6", "Inspect γ Band carefully", "Look for: (a) Discrete spike = M protein (monoclonal), (b) Broad ↑ = polyclonal, (c) ↓ γ = immunodeficiency / light chain myeloma.", DARK_BLUE, LIGHT_BLUE),
]
for i, (step, title, desc, title_color, bg_color) in enumerate(steps):
col = i % 3
row = i // 3
x = 0.25 + col * 4.33
y = 1.3 + row * 2.85
add_rect(slide, x, y, 4.1, 2.65, fill_color=bg_color, line_color=title_color, line_width=Pt(1.5))
add_rect(slide, x, y, 4.1, 0.42, fill_color=title_color)
add_text(slide, f"{step}: {title}", x+0.1, y+0.05, 3.9, 0.35,
font_size=13, bold=True, color=WHITE)
add_multiline_textbox(slide, [
(desc, False, DARK_GRAY, 13, 0)
], x+0.1, y+0.48, 3.9, 2.1)
# ============================================================
# SLIDE 6: ACUTE PHASE RESPONSE PATTERN
# ============================================================
slide = prs.slides.add_slide(blank)
add_rect(slide, 0, 0, 13.333, 7.5, fill_color=WHITE)
add_title_bar(slide, "Abnormal Pattern 1: Acute Phase Response",
subtitle="Elevated α1 & α2 bands — seen in acute inflammation, infection, trauma, malignancy")
add_footer(slide)
add_image_from_url(slide,
"https://cdn.orris.care/cdss_images/9c99a74d689c2dcc213cf063c777ce894e4b1a103bfe834a24c4213f3a87f3bc.png",
0.3, 1.3, 5.5)
add_rect(slide, 6.1, 1.3, 6.9, 5.85, fill_color=LIGHT_ORANGE, line_color=ORANGE_ACC, line_width=Pt(1.2))
add_text(slide, "Acute Inflammation Pattern — Key Features", 6.25, 1.35, 6.6, 0.42,
font_size=14, bold=True, color=ORANGE_ACC)
add_multiline_textbox(slide, [
("TYPICAL LAB VALUES (example):", True, DARK_BLUE, 13, 0),
(" Albumin: 38.1% (↓) | 2.5 g/dL", False, DARK_GRAY, 13, 0),
(" α1: 9.9% (↑↑) | 0.6 g/dL (ref: 0.2-0.4)", False, RED_ACC, 13, 0),
(" α2: 25.4% (↑↑) | 1.7 g/dL (ref: 0.5-0.9)", False, RED_ACC, 13, 0),
(" β: 11.6% — Normal", False, DARK_GRAY, 13, 0),
(" γ: 15.0% — Normal to mildly ↑", False, DARK_GRAY, 13, 0),
(" A/G Ratio: 0.62 (reversed / low)", False, RED_ACC, 13, 0),
("", False, DARK_GRAY, 8, 0),
("MECHANISM:", True, DARK_BLUE, 13, 0),
(" Liver produces acute phase reactants", False, DARK_GRAY, 13, 0),
(" ↑ α1-antitrypsin, α1-acid glycoprotein → ↑ α1", False, DARK_GRAY, 13, 0),
(" ↑ Haptoglobin, α2-macroglobulin, ceruloplasmin → ↑ α2", False, DARK_GRAY, 13, 0),
(" Albumin is negative acute phase reactant (↓)", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 8, 0),
("CAUSES:", True, DARK_BLUE, 13, 0),
(" Infection, sepsis, surgery, trauma, MI, burns", False, DARK_GRAY, 13, 0),
(" Autoimmune disease, malignancy", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 8, 0),
("NOTE: Prolonged inflammation → polyclonal ↑ γ", True, ORANGE_ACC, 13, 0),
], 6.25, 1.82, 6.6, 5.3)
# ============================================================
# SLIDE 7: NEPHROTIC SYNDROME PATTERN
# ============================================================
slide = prs.slides.add_slide(blank)
add_rect(slide, 0, 0, 13.333, 7.5, fill_color=WHITE)
add_title_bar(slide, "Abnormal Pattern 2: Nephrotic Syndrome",
subtitle="Massive loss of small proteins → selective hypoalbuminemia with elevated α2")
add_footer(slide)
add_rect(slide, 0.3, 1.3, 12.7, 5.9, fill_color=WHITE)
# Left info box
add_rect(slide, 0.3, 1.3, 6.0, 5.9, fill_color=LIGHT_RED, line_color=RED_ACC, line_width=Pt(1.2))
add_text(slide, "Nephrotic Syndrome Pattern", 0.45, 1.35, 5.7, 0.42, font_size=15, bold=True, color=RED_ACC)
add_multiline_textbox(slide, [
("HALLMARK FINDINGS:", True, DARK_BLUE, 13, 0),
("", False, DARK_GRAY, 8, 0),
("↓↓ Albumin", True, RED_ACC, 14, 0),
(" Massive urinary loss of small proteins", False, DARK_GRAY, 13, 0),
(" Albumin < 3.0 g/dL common", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 8, 0),
("↑↑ α2 band (MOST CHARACTERISTIC)", True, RED_ACC, 14, 0),
(" α2-macroglobulin is LARGE (720 kDa) — NOT lost in urine", False, DARK_GRAY, 13, 0),
(" Compensatory hepatic synthesis of α2-macroglobulin", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 8, 0),
("↓ All other fractions (lost in urine):", True, DARK_BLUE, 13, 0),
(" α1 globulins, transferrin (β), IgG (γ) all reduced", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 8, 0),
("VISUAL PATTERN:", True, DARK_BLUE, 13, 0),
(" Small albumin peak + Tall α2 peak + Flat everything else", False, DARK_GRAY, 13, 0),
(" A/G ratio markedly reversed (very low)", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 8, 0),
("ASSOCIATED: Hyperlipidemia (VLDL/LDL ↑)", True, ORANGE_ACC, 13, 0),
(" ↑ Lipoproteins in β band due to compensatory hepatic synthesis", False, DARK_GRAY, 13, 0),
], 0.45, 1.82, 5.7, 5.3)
# Right: summary table
add_rect(slide, 6.6, 1.3, 6.4, 5.9, fill_color=LIGHT_BLUE, line_color=MID_BLUE, line_width=Pt(1.2))
add_text(slide, "Fraction-by-Fraction Summary", 6.75, 1.35, 6.1, 0.42, font_size=15, bold=True, color=DARK_BLUE)
fractions_ns = [
("Fraction", "Direction", "Reason", True),
("Albumin", "↓↓↓ Markedly Low", "Lost in urine (small size, 66 kDa)", False),
("α1 globulin", "↓ Reduced", "Small proteins lost in urine", False),
("α2 globulin", "↑↑↑ Markedly HIGH", "α2-Macroglobulin too large to be lost (720 kDa)", False),
("β globulin", "↓ / Normal", "Transferrin lost; LDL may ↑", False),
("γ globulin", "↓ Reduced", "IgG lost in urine", False),
("Total Protein", "↓ Reduced", "Net protein loss", False),
("A/G Ratio", "< 1 (Reversed)", "Albumin loss predominates", False),
]
row_h2 = 0.63
for ri, (c0, c1, c2, is_hdr) in enumerate(fractions_ns):
ry = 1.82 + ri * row_h2
bg = DARK_BLUE if is_hdr else (LIGHT_BLUE if ri % 2 == 0 else WHITE)
tc = WHITE if is_hdr else DARK_GRAY
tc1 = WHITE if is_hdr else (RED_ACC if "↓" in c1 or "↑" in c1 else DARK_GRAY)
for ci, (cx, cw, ct, ftc) in enumerate(zip([6.65, 8.55, 9.9], [1.85, 1.3, 3.0], [c0, c1, c2], [tc, tc1, tc])):
add_rect(slide, cx, ry, cw-0.05, row_h2-0.04, fill_color=bg,
line_color=MID_BLUE, line_width=Pt(0.5))
add_multiline_textbox(slide, [
(ct, is_hdr, ftc, 12 if not is_hdr else 12, 0)
], cx+0.05, ry+0.05, cw-0.15, row_h2-0.12)
# ============================================================
# SLIDE 8: CIRRHOSIS / LIVER DISEASE PATTERN
# ============================================================
slide = prs.slides.add_slide(blank)
add_rect(slide, 0, 0, 13.333, 7.5, fill_color=WHITE)
add_title_bar(slide, "Abnormal Pattern 3: Cirrhosis / Chronic Liver Disease",
subtitle="β-γ bridging — the hallmark of cirrhosis on SPEP")
add_footer(slide)
# Left: image
add_rect(slide, 0.3, 1.3, 5.8, 5.9, fill_color=LIGHT_GRAY, line_color=MID_BLUE, line_width=Pt(1))
add_text(slide, "Cirrhosis SPEP Pattern (Schematic)", 0.45, 1.35, 5.5, 0.42,
font_size=14, bold=True, color=DARK_BLUE)
add_multiline_textbox(slide, [
("β-γ BRIDGE:", True, RED_ACC, 22, 0),
("The gap between β and γ peaks disappears.", False, DARK_GRAY, 14, 0),
("This is the HALLMARK of cirrhosis.", True, RED_ACC, 14, 0),
("", False, DARK_GRAY, 8, 0),
("On densitometry tracing, β and γ merge", False, DARK_GRAY, 14, 0),
("into a continuous elevation — no valley", False, DARK_GRAY, 14, 0),
("between them.", False, DARK_GRAY, 14, 0),
("", False, DARK_GRAY, 8, 0),
("Primarily due to: ↑ serum IgA", True, DARK_BLUE, 14, 0),
("IgA migrates in β-γ interface region,", False, DARK_GRAY, 14, 0),
("filling the trough and causing bridging.", False, DARK_GRAY, 14, 0),
], 0.45, 1.82, 5.6, 5.3)
# Right: features
add_rect(slide, 6.4, 1.3, 6.6, 5.9, fill_color=LIGHT_ORANGE, line_color=ORANGE_ACC, line_width=Pt(1.2))
add_text(slide, "Key SPEP Features in Cirrhosis", 6.55, 1.35, 6.35, 0.42,
font_size=15, bold=True, color=ORANGE_ACC)
add_multiline_textbox(slide, [
("1. β-γ BRIDGING (HALLMARK)", True, RED_ACC, 14, 0),
(" Absence of distinct valley between β and γ", False, DARK_GRAY, 13, 0),
(" Due to ↑ serum IgA (produced by gut plasma cells)", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 8, 0),
("2. HYPOALBUMINEMIA", True, DARK_BLUE, 14, 0),
(" ↓ Hepatic albumin synthesis", False, DARK_GRAY, 13, 0),
(" Reflects degree of hepatic synthetic failure", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 8, 0),
("3. BLUNTED α1 & α2 BANDS", True, DARK_BLUE, 14, 0),
(" ↓ Hepatic synthesis of acute phase proteins", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 8, 0),
("4. POLYCLONAL ↑ γ (broad)", True, DARK_BLUE, 14, 0),
(" Chronic immune stimulation from portosystemic shunting", False, DARK_GRAY, 13, 0),
(" Antigens bypass liver → systemic B-cell activation", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 8, 0),
("5. REVERSED A/G RATIO", True, DARK_BLUE, 14, 0),
(" A/G < 1.0 common in advanced cirrhosis", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 8, 0),
("REMEMBER: Plasma (not serum) may show fibrinogen band", True, TEAL, 13, 0),
(" in β region — potential pseudo-M spike source", False, DARK_GRAY, 13, 0),
], 6.55, 1.82, 6.35, 5.3)
# ============================================================
# SLIDE 9: MONOCLONAL GAMMOPATHY / M-SPIKE
# ============================================================
slide = prs.slides.add_slide(blank)
add_rect(slide, 0, 0, 13.333, 7.5, fill_color=WHITE)
add_title_bar(slide, "Abnormal Pattern 4: Monoclonal Gammopathy (M-Spike)",
subtitle="Most important SPEP finding — discrete spike = clonal plasma cell disorder until proven otherwise")
add_footer(slide)
# Textbook image
add_image_from_url(slide,
"https://cdn.orris.care/cdss_images/33f3a80e7caa2460589e39464d7261581e1fc22a422d8a345ed83590cdc36dc0.png",
0.3, 1.3, 4.8)
# Right main
add_rect(slide, 5.4, 1.3, 7.6, 5.9, fill_color=LIGHT_RED, line_color=RED_ACC, line_width=Pt(1.2))
add_text(slide, "Monoclonal Gammopathy — Key Points", 5.55, 1.35, 7.35, 0.42,
font_size=15, bold=True, color=RED_ACC)
add_multiline_textbox(slide, [
("DEFINITION:", True, DARK_BLUE, 13, 0),
(" Homogeneous (clonal) immunoglobulin produced by a single plasma cell clone", False, DARK_GRAY, 13, 0),
(" = Paraprotein / M protein", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 8, 0),
("SPEP APPEARANCE:", True, DARK_BLUE, 13, 0),
(" Prominent, discrete, narrow, DARK band on gel", False, DARK_GRAY, 13, 0),
(" Sharp spike on densitometry tracing (M spike)", False, DARK_GRAY, 13, 0),
(" Usually in γ region; can be in β or α2", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 8, 0),
("MIGRATION BY ISOTYPE:", True, DARK_BLUE, 13, 0),
(" IgG → Usually γ region (most common)", False, DARK_GRAY, 13, 0),
(" IgM → β-γ interface", False, DARK_GRAY, 13, 0),
(" IgA → β region (can be mistaken for β peak)", False, DARK_GRAY, 13, 0),
(" Light chain only → γ or β; often ONLY hypogammaglobulinemia on SPEP!", False, RED_ACC, 13, 0),
("", False, DARK_GRAY, 8, 0),
("M PROTEIN COMPOSITION:", True, DARK_BLUE, 13, 0),
(" Usually: 2 heavy chains + 2 light chains", False, DARK_GRAY, 13, 0),
(" Sometimes: light chain only (Bence Jones protein)", False, DARK_GRAY, 13, 0),
(" Rarely: heavy chain only", False, DARK_GRAY, 13, 0),
(" Biclonal: 3-4% of cases", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 8, 0),
("CAUSES:", True, DARK_BLUE, 13, 0),
(" Multiple Myeloma, MGUS, Waldenström macroglobulinemia", False, DARK_GRAY, 13, 0),
(" Lymphoma (esp. lymphoplasmacytic / CLL/SLL)", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 8, 0),
("NEXT STEP: Immunofixation electrophoresis (IFE)", True, TEAL, 13, 0),
(" to characterize heavy chain + light chain type", False, DARK_GRAY, 13, 0),
], 5.55, 1.82, 7.35, 5.3)
# ============================================================
# SLIDE 10: M SPIKE vs POLYCLONAL + IFE
# ============================================================
slide = prs.slides.add_slide(blank)
add_rect(slide, 0, 0, 13.333, 7.5, fill_color=WHITE)
add_title_bar(slide, "M-Spike: Monoclonal vs Polyclonal Gammopathy",
subtitle="Critical distinction — monoclonal = malignant potential; polyclonal = reactive/benign")
add_footer(slide)
# Monoclonal box
add_rect(slide, 0.3, 1.3, 6.0, 5.9, fill_color=LIGHT_RED, line_color=RED_ACC, line_width=Pt(2))
add_rect(slide, 0.3, 1.3, 6.0, 0.42, fill_color=RED_ACC)
add_text(slide, "MONOCLONAL (M-Spike)", 0.45, 1.33, 5.7, 0.38, font_size=15, bold=True, color=WHITE)
add_multiline_textbox(slide, [
("APPEARANCE ON SPEP:", True, DARK_BLUE, 13, 0),
(" Tall, narrow, sharp, discrete spike", False, DARK_GRAY, 13, 0),
(" Looks like a 'church steeple'", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 8, 0),
("REPRESENTS:", True, DARK_BLUE, 13, 0),
(" Single clone of plasma cells producing identical Ig", False, DARK_GRAY, 13, 0),
(" Pathological — requires further workup", False, RED_ACC, 13, 0),
("", False, DARK_GRAY, 8, 0),
("DISEASES:", True, DARK_BLUE, 13, 0),
(" • Multiple myeloma", False, DARK_GRAY, 13, 0),
(" • MGUS (Monoclonal Gammopathy of Undetermined Significance)", False, DARK_GRAY, 13, 0),
(" • Waldenström macroglobulinemia (IgM)", False, DARK_GRAY, 13, 0),
(" • Primary amyloidosis (AL amyloid)", False, DARK_GRAY, 13, 0),
(" • Lymphoma / CLL / SLL", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 8, 0),
("WORKUP:", True, DARK_BLUE, 13, 0),
(" 1. Immunofixation electrophoresis (IFE) — characterize Ig type", False, DARK_GRAY, 13, 0),
(" 2. 24-hour urine protein electrophoresis (UPEP)", False, DARK_GRAY, 13, 0),
(" 3. Serum free light chains (κ/λ ratio)", False, DARK_GRAY, 13, 0),
(" 4. Bone marrow biopsy if myeloma suspected", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 8, 0),
("⚠ 10% of myeloma → NO M-spike (light chain only)", True, RED_ACC, 13, 0),
(" Only hypogammaglobulinemia seen on SPEP!", False, RED_ACC, 13, 0),
], 0.45, 1.78, 5.7, 5.35)
# Polyclonal box
add_rect(slide, 6.7, 1.3, 6.3, 5.9, fill_color=LIGHT_GREEN, line_color=GREEN_ACC, line_width=Pt(2))
add_rect(slide, 6.7, 1.3, 6.3, 0.42, fill_color=GREEN_ACC)
add_text(slide, "POLYCLONAL (Broad γ elevation)", 6.85, 1.33, 6.0, 0.38, font_size=15, bold=True, color=WHITE)
add_multiline_textbox(slide, [
("APPEARANCE ON SPEP:", True, DARK_BLUE, 13, 0),
(" Broad, diffuse, wide elevation in γ zone", False, DARK_GRAY, 13, 0),
(" No single narrow spike", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 8, 0),
("REPRESENTS:", True, DARK_BLUE, 13, 0),
(" Multiple clones producing varied immunoglobulins", False, DARK_GRAY, 13, 0),
(" Reactive / benign — body's immune response", False, TEAL, 13, 0),
("", False, DARK_GRAY, 8, 0),
("DISEASES:", True, DARK_BLUE, 13, 0),
(" • Chronic infections (HIV, TB, hepatitis, malaria)", False, DARK_GRAY, 13, 0),
(" • Autoimmune diseases (SLE, RA, Sjögren)", False, DARK_GRAY, 13, 0),
(" • Chronic liver disease / cirrhosis", False, DARK_GRAY, 13, 0),
(" • Sarcoidosis", False, DARK_GRAY, 13, 0),
(" • Prolonged inflammation", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 8, 0),
("KEY DISTINCTION FROM MONOCLONAL:", True, DARK_BLUE, 13, 0),
(" • Broad base vs. narrow spike", False, DARK_GRAY, 13, 0),
(" • IFE: multiple heavy + light chains vs. single clone", False, DARK_GRAY, 13, 0),
(" • Usually benign / reactive cause", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 8, 0),
("✓ IFE not required unless doubt about monoclonal component", True, TEAL, 13, 0),
], 6.85, 1.78, 6.0, 5.35)
# ============================================================
# SLIDE 11: α1-ANTITRYPSIN DEFICIENCY + PSEUDO M-SPIKE
# ============================================================
slide = prs.slides.add_slide(blank)
add_rect(slide, 0, 0, 13.333, 7.5, fill_color=WHITE)
add_title_bar(slide, "Other Abnormal Patterns: AAT Deficiency & Pseudo M-Spikes",
subtitle="Pattern recognition pitfalls — knowing when the M-spike is NOT a paraprotein")
add_footer(slide)
add_image_from_url(slide,
"https://cdn.orris.care/cdss_images/78dde153893d992acec78bf0d3e23e7bd23427da83d45793078fe33ee8ca8ea2.png",
0.3, 1.3, 5.2)
add_rect(slide, 5.8, 1.3, 7.2, 2.7, fill_color=LIGHT_ORANGE, line_color=ORANGE_ACC, line_width=Pt(1.2))
add_text(slide, "α1-Antitrypsin (AAT) Deficiency", 5.95, 1.35, 6.95, 0.42, font_size=14, bold=True, color=ORANGE_ACC)
add_multiline_textbox(slide, [
("• Nearly absent α1 band on SPEP (AAT = major component of α1)", False, DARK_GRAY, 13, 0),
("• NOT sensitive or specific alone — confirmatory testing needed", False, DARK_GRAY, 13, 0),
("• AAT is an acute phase reactant — may appear normal in inflammation!", False, RED_ACC, 13, 0),
("• Confirm with quantitative AAT level + phenotyping (PiZZ = severe deficiency)", False, DARK_GRAY, 13, 0),
("• Associated: emphysema (panacinar), liver cirrhosis", False, DARK_GRAY, 13, 0),
], 5.95, 1.82, 6.9, 2.1)
add_rect(slide, 5.8, 4.2, 7.2, 2.95, fill_color=LIGHT_RED, line_color=RED_ACC, line_width=Pt(1.2))
add_text(slide, "⚠ Pseudo M-Spikes (False Paraproteins)", 5.95, 4.25, 6.95, 0.42, font_size=14, bold=True, color=RED_ACC)
add_multiline_textbox(slide, [
("These can MIMIC a monoclonal spike on SPEP:", True, DARK_BLUE, 13, 0),
(" 1. Fibrinogen — from incompletely clotted sample (use serum, NOT plasma)", False, DARK_GRAY, 13, 0),
(" 2. Hemoglobin — from hemolyzed specimen", False, DARK_GRAY, 13, 0),
(" 3. Elevated CRP — migrates in γ region", False, DARK_GRAY, 13, 0),
(" 4. Elevated transferrin — β region", False, DARK_GRAY, 13, 0),
(" 5. Certain antibiotics (e.g., penicillin)", False, DARK_GRAY, 13, 0),
(" 6. Radiocontrast agents", False, DARK_GRAY, 13, 0),
(" 7. Very high tumor markers", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 8, 0),
("Confirm all spikes with IFE before diagnosing paraproteinemia!", True, RED_ACC, 13, 0),
], 5.95, 4.7, 6.9, 2.4)
# ============================================================
# SLIDE 12: HYPOGAMMAGLOBULINEMIA
# ============================================================
slide = prs.slides.add_slide(blank)
add_rect(slide, 0, 0, 13.333, 7.5, fill_color=WHITE)
add_title_bar(slide, "Abnormal Pattern 5: Hypogammaglobulinemia",
subtitle="Reduced or absent γ band — primary or secondary immune deficiency")
add_footer(slide)
add_rect(slide, 0.3, 1.3, 12.7, 5.9, fill_color=WHITE)
cols_data = [
("Primary Hypogammaglobulinemia\n(Immune Deficiency Disorders)", [
("X-linked agammaglobulinemia (Bruton's):", True, DARK_BLUE, 13),
(" No B cells; absent all Ig fractions", False, DARK_GRAY, 13),
("Common Variable Immunodeficiency (CVID):", True, DARK_BLUE, 13),
(" Low IgG ± IgA/IgM; recurrent infections", False, DARK_GRAY, 13),
("Selective IgA deficiency:", True, DARK_BLUE, 13),
(" Most common primary immunodeficiency", False, DARK_GRAY, 13),
(" IgA absent; IgG/IgM normal", False, DARK_GRAY, 13),
("Hyper-IgM syndrome:", True, DARK_BLUE, 13),
(" ↑ IgM; absent IgG, IgA", False, DARK_GRAY, 13),
], LIGHT_GREEN, GREEN_ACC),
("Secondary Hypogammaglobulinemia\n(Acquired Causes)", [
("Protein-losing states:", True, DARK_BLUE, 13),
(" Nephrotic syndrome, protein-losing enteropathy", False, DARK_GRAY, 13),
("Immunosuppression:", True, DARK_BLUE, 13),
(" Corticosteroids, chemotherapy, rituximab", False, DARK_GRAY, 13),
("Hematological malignancies:", True, DARK_BLUE, 13),
(" CLL, light chain myeloma (M-spike absent!)", False, RED_ACC, 13),
(" 10% of myeloma → only hypogammaglobulinemia", False, RED_ACC, 13),
("Splenectomy, HIV/AIDS", True, DARK_BLUE, 13),
(" Secondary immune suppression", False, DARK_GRAY, 13),
], LIGHT_ORANGE, ORANGE_ACC),
("SPEP Appearance &\nNext Steps", [
("SPEP shows:", True, DARK_BLUE, 13),
(" Flat / nearly absent γ region", False, DARK_GRAY, 13),
(" All other bands may be normal", False, DARK_GRAY, 13),
("", False, DARK_GRAY, 8),
("Key pearl: Light chain myeloma", True, RED_ACC, 13),
(" SPEP shows ONLY hypogammaglobulinemia", False, RED_ACC, 13),
(" Light chains (Bence Jones protein) in URINE", False, DARK_GRAY, 13),
(" MUST check UPEP + serum free light chains!", True, RED_ACC, 13),
("", False, DARK_GRAY, 8),
("Always follow up with:", True, DARK_BLUE, 13),
(" Serum IgG, IgA, IgM quantitation", False, DARK_GRAY, 13),
(" Serum free light chains", False, DARK_GRAY, 13),
], LIGHT_RED, RED_ACC),
]
for ci, (title, lines, bg, lc) in enumerate(cols_data):
cx = 0.35 + ci * 4.3
add_rect(slide, cx, 1.3, 4.1, 5.9, fill_color=bg, line_color=lc, line_width=Pt(1.2))
add_rect(slide, cx, 1.3, 4.1, 0.52, fill_color=lc)
add_text(slide, title, cx+0.1, 1.32, 3.9, 0.48, font_size=13, bold=True, color=WHITE)
add_multiline_textbox(slide, [
(t, b, c, s, 0) for t,b,c,s in lines
], cx+0.12, 1.86, 3.85, 5.28)
# ============================================================
# SLIDE 13: URINE PROTEIN ELECTROPHORESIS (UPEP)
# ============================================================
slide = prs.slides.add_slide(blank)
add_rect(slide, 0, 0, 13.333, 7.5, fill_color=WHITE)
add_title_bar(slide, "Urine Protein Electrophoresis (UPEP)",
subtitle="Complements SPEP — essential for detecting light chain (Bence Jones) proteinuria")
add_footer(slide)
add_image_from_url(slide,
"https://cdn.orris.care/cdss_images/5e1b3b4a5838553f80767fae0ac000ce93806a5744e54e41732139a269eb339c.png",
0.3, 1.3, 5.5)
add_rect(slide, 6.1, 1.3, 6.9, 5.9, fill_color=LIGHT_BLUE, line_color=MID_BLUE, line_width=Pt(1.2))
add_text(slide, "UPEP — Patterns & Interpretation", 6.25, 1.35, 6.6, 0.42, font_size=15, bold=True, color=DARK_BLUE)
add_multiline_textbox(slide, [
("PATTERN 1: Normal Urine", True, TEAL, 13, 0),
(" Very little protein — mainly Tamm-Horsfall mucoprotein", False, DARK_GRAY, 13, 0),
(" No significant bands", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 8, 0),
("PATTERN 2a: Glomerular Proteinuria", True, DARK_BLUE, 13, 0),
(" Large proteins pass through damaged glomerular filter", False, DARK_GRAY, 13, 0),
(" Albumin-predominant band in urine", False, DARK_GRAY, 13, 0),
(" Seen in: nephrotic syndrome, glomerulonephritis", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 8, 0),
("PATTERN 2b: Tubular Proteinuria", True, DARK_BLUE, 13, 0),
(" Small proteins not reabsorbed by damaged tubules", False, DARK_GRAY, 13, 0),
(" Pre-albumin, α1, β2-microglobulin bands", False, DARK_GRAY, 13, 0),
(" Seen in: Fanconi syndrome, toxic nephropathy", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 8, 0),
("PATTERN 2c: Overflow Proteinuria", True, RED_ACC, 13, 0),
(" Overproduction overwhelms tubular reabsorption", False, DARK_GRAY, 13, 0),
(" BENCE JONES PROTEIN (free light chains)", True, RED_ACC, 13, 0),
(" Sharp spike — may be κ or λ light chains", False, DARK_GRAY, 13, 0),
(" SPEP may be NORMAL or show only hypogammaglobulinemia!", False, RED_ACC, 13, 0),
(" Diagnose by IFE of urine", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 8, 0),
("KEY POINT:", True, DARK_BLUE, 14, 0),
(" Always order UPEP + IFE alongside SPEP", False, DARK_GRAY, 13, 0),
(" when myeloma / paraprotein is suspected!", False, DARK_GRAY, 13, 0),
], 6.25, 1.82, 6.6, 5.3)
# ============================================================
# SLIDE 14: COMPLETE COMPARISON TABLE
# ============================================================
slide = prs.slides.add_slide(blank)
add_rect(slide, 0, 0, 13.333, 7.5, fill_color=WHITE)
add_title_bar(slide, "SPEP Abnormal Patterns — At a Glance Summary Table",
subtitle="Quick-reference comparison of all major SPEP patterns")
add_footer(slide)
table_data = [
("Pattern", "Albumin", "α1", "α2", "β", "γ", "Key Clue", True),
("Normal", "↑↑ (large)", "Small peak", "Broad", "Bi-nodal", "Broad low", "A/G 1.2–2.5", False),
("Acute Inflammation", "↓ mild", "↑↑", "↑↑", "Normal", "↑ poly (late)", "CRP ↑; α1+α2 both up", False),
("Nephrotic Syndrome", "↓↓↓", "↓", "↑↑↑", "↓/norm", "↓ (IgG lost)", "α2-macroglobulin spared", False),
("Cirrhosis", "↓", "↓", "↓", "Bridge →γ", "↑ broad poly", "β-γ bridging; IgA ↑", False),
("AAT Deficiency", "Normal", "↓↓ (absent)", "Normal", "Normal", "Normal", "α1 nearly absent", False),
("Monoclonal Gammopathy", "↓ (sometimes)", "Norm", "Norm", "Norm/M-spike", "M-SPIKE ↑↑", "Sharp narrow spike; IFE+", False),
("Polyclonal Gammopathy", "↓ (chronic dz)", "Norm/↑", "Norm/↑", "Normal", "↑↑ BROAD", "Wide γ elevation; reactive", False),
("Hypogammaglobulinemia", "Normal", "Normal", "Normal", "Normal", "↓↓ flat", "IgG/IgA/IgM all ↓; check light chains", False),
("Iron Deficiency", "Normal", "Normal", "Normal", "↑ (transferrin)", "Normal", "Isolated β1 ↑; check Fe studies", False),
]
col_widths_t = [2.3, 1.2, 0.8, 0.9, 1.4, 1.5, 2.0, 2.8]
col_x_t = [0.15]
for cw in col_widths_t[:-1]:
col_x_t.append(col_x_t[-1] + cw + 0.02)
row_h_t = 0.53
start_y_t = 1.28
alt_colors = [LIGHT_BLUE, WHITE]
for ri, row_data in enumerate(table_data):
*cells, is_hdr = row_data
y = start_y_t + ri * row_h_t
bg = DARK_BLUE if is_hdr else alt_colors[ri % 2]
for ci, (ct, cx, cw) in enumerate(zip(cells, col_x_t, col_widths_t)):
cell_bg = bg
tc = WHITE if is_hdr else DARK_GRAY
if not is_hdr:
if "↑↑↑" in ct or "↓↓↓" in ct or "M-SPIKE" in ct:
tc = RED_ACC
elif "↓" in ct and ct not in ("Normal", "Norm"):
tc = RED_ACC
elif "↑" in ct and ci > 0:
tc = TEAL
add_rect(slide, cx, y, cw-0.02, row_h_t-0.03, fill_color=cell_bg,
line_color=MID_BLUE, line_width=Pt(0.3))
add_multiline_textbox(slide, [
(ct, is_hdr, tc, 11 if not is_hdr else 12, 0)
], cx+0.04, y+0.04, cw-0.1, row_h_t-0.1)
# ============================================================
# SLIDE 15: IMMUNOFIXATION ELECTROPHORESIS (IFE)
# ============================================================
slide = prs.slides.add_slide(blank)
add_rect(slide, 0, 0, 13.333, 7.5, fill_color=WHITE)
add_title_bar(slide, "Immunofixation Electrophoresis (IFE)",
subtitle="Gold standard for confirming and characterizing an M protein detected on SPEP")
add_footer(slide)
# IgG image
add_image_from_url(slide,
"https://cdn.orris.care/cdss_images/607cee6948ede4518033703db584873d1830b7122e0dde6a40f33224ebba81b5.png",
0.3, 1.3, 5.5)
add_rect(slide, 6.1, 1.3, 6.9, 5.9, fill_color=LIGHT_BLUE, line_color=MID_BLUE, line_width=Pt(1.2))
add_text(slide, "IFE — Principles & Interpretation", 6.25, 1.35, 6.65, 0.42,
font_size=15, bold=True, color=DARK_BLUE)
add_multiline_textbox(slide, [
("PRINCIPLE:", True, DARK_BLUE, 13, 0),
(" After electrophoresis, separate antisera applied to lanes:", False, DARK_GRAY, 13, 0),
(" Anti-IgG, Anti-IgA, Anti-IgM, Anti-κ, Anti-λ", False, DARK_GRAY, 13, 0),
(" Precipitin reaction identifies the M protein type", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 8, 0),
("HOW TO READ IFE:", True, DARK_BLUE, 13, 0),
(" A band in ONE heavy chain lane (e.g., IgG)", False, DARK_GRAY, 13, 0),
(" AND ONE light chain lane (e.g., κ or λ)", False, DARK_GRAY, 13, 0),
(" = Monoclonal IgG κ (or IgG λ)", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 8, 0),
("MIGRATION PATTERNS BY ISOTYPE:", True, DARK_BLUE, 13, 0),
(" IgG κ/λ → γ region (most common, ~70%)", False, DARK_GRAY, 13, 0),
(" IgA κ/λ → β region (appears as β peak on SPEP)", False, DARK_GRAY, 13, 0),
(" IgM κ/λ → β-γ interface (Waldenström)", False, DARK_GRAY, 13, 0),
(" Light chain only → κ or λ in any region", False, RED_ACC, 13, 0),
("", False, DARK_GRAY, 8, 0),
("BICLONAL GAMMOPATHY:", True, DARK_BLUE, 13, 0),
(" Two separate M proteins (3-4% of cases)", False, DARK_GRAY, 13, 0),
(" Apparent IgA biclonality may be IgA dimer", False, DARK_GRAY, 13, 0),
(" → pretreat with β-mercaptoethanol to distinguish", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 8, 0),
("IFE vs SPEP sensitivity:", True, DARK_BLUE, 13, 0),
(" IFE detects M proteins < 0.2 g/dL (SPEP misses these)", False, DARK_GRAY, 13, 0),
(" IFE is mandatory for M protein characterization", False, DARK_GRAY, 13, 0),
], 6.25, 1.82, 6.65, 5.3)
# ============================================================
# SLIDE 16: MGUS vs MYELOMA DIFFERENTIATION
# ============================================================
slide = prs.slides.add_slide(blank)
add_rect(slide, 0, 0, 13.333, 7.5, fill_color=WHITE)
add_title_bar(slide, "MGUS vs Multiple Myeloma — Clinical Differentiation",
subtitle="Both show M-spike on SPEP — key lab & clinical features distinguish them")
add_footer(slide)
add_rect(slide, 0.3, 1.3, 6.0, 5.9, fill_color=LIGHT_GREEN, line_color=GREEN_ACC, line_width=Pt(2))
add_rect(slide, 0.3, 1.3, 6.0, 0.42, fill_color=GREEN_ACC)
add_text(slide, "MGUS (Monoclonal Gammopathy of Undetermined Significance)", 0.45, 1.33, 5.7, 0.38, font_size=12, bold=True, color=WHITE)
add_multiline_textbox(slide, [
("SPEP / Lab Criteria:", True, DARK_BLUE, 13, 0),
(" • M protein < 3 g/dL", False, DARK_GRAY, 13, 0),
(" • Bone marrow plasma cells < 10%", False, DARK_GRAY, 13, 0),
(" • No end-organ damage (CRAB absent)", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 8, 0),
("CRAB Criteria (absent in MGUS):", True, DARK_BLUE, 13, 0),
(" C = hyperCalcemia", False, DARK_GRAY, 13, 0),
(" R = Renal impairment", False, DARK_GRAY, 13, 0),
(" A = Anemia", False, DARK_GRAY, 13, 0),
(" B = Bone lesions", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 8, 0),
("Risk of progression to myeloma:", True, DARK_BLUE, 13, 0),
(" ~1% per year", False, DARK_GRAY, 13, 0),
(" Requires regular monitoring (SPEP every 6-12 months)", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 8, 0),
("MOST COMMON cause of M-spike in general population", True, TEAL, 13, 0),
(" Prevalence ~3% in persons >50 years old", False, DARK_GRAY, 13, 0),
], 0.45, 1.78, 5.7, 5.35)
add_rect(slide, 6.7, 1.3, 6.3, 5.9, fill_color=LIGHT_RED, line_color=RED_ACC, line_width=Pt(2))
add_rect(slide, 6.7, 1.3, 6.3, 0.42, fill_color=RED_ACC)
add_text(slide, "Multiple Myeloma", 6.85, 1.33, 6.0, 0.38, font_size=15, bold=True, color=WHITE)
add_multiline_textbox(slide, [
("SPEP / Lab Criteria:", True, DARK_BLUE, 13, 0),
(" • M protein ≥ 3 g/dL OR", False, RED_ACC, 13, 0),
(" • Bone marrow plasma cells ≥ 10% PLUS", False, RED_ACC, 13, 0),
(" • End-organ damage (CRAB) OR biomarkers:", False, RED_ACC, 13, 0),
(" - Plasma cells ≥ 60%", False, DARK_GRAY, 13, 0),
(" - Free light chain ratio ≥ 100", False, DARK_GRAY, 13, 0),
(" - >1 focal MRI lesion", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 8, 0),
("SPEP Findings in Myeloma:", True, DARK_BLUE, 13, 0),
(" • Large M-spike (usually IgG > IgA > IgD/IgE)", False, DARK_GRAY, 13, 0),
(" • ↓ normal Ig (immune paresis)", False, DARK_GRAY, 13, 0),
(" • Hypogammaglobulinemia only in 10%", False, RED_ACC, 13, 0),
(" (light chain myeloma — no serum M-spike!)", False, RED_ACC, 13, 0),
("", False, DARK_GRAY, 8, 0),
("Other SPEP findings:", True, DARK_BLUE, 13, 0),
(" • Anemia pattern (normochromic normocytic)", False, DARK_GRAY, 13, 0),
(" • Possible high ESR (rouleaux)", False, DARK_GRAY, 13, 0),
("", False, DARK_GRAY, 8, 0),
("Always correlate SPEP with:", True, DARK_BLUE, 13, 0),
(" IFE, UPEP + IFE, serum free light chains", False, DARK_GRAY, 13, 0),
(" CBC, creatinine, calcium, LDH, β2-microglobulin", False, DARK_GRAY, 13, 0),
], 6.85, 1.78, 6.0, 5.35)
# ============================================================
# SLIDE 17: SUMMARY / KEY TAKEAWAYS
# ============================================================
slide = prs.slides.add_slide(blank)
add_rect(slide, 0, 0, 13.333, 7.5, fill_color=DARK_BLUE)
add_rect(slide, 0, 1.0, 13.333, 0.06, fill_color=YELLOW_ACC)
add_rect(slide, 0, 6.85, 13.333, 0.06, fill_color=YELLOW_ACC)
add_text(slide, "KEY TAKEAWAYS — SPEP Interpretation", 0.4, 0.22, 12.5, 0.75,
font_size=28, bold=True, color=WHITE, align=PP_ALIGN.CENTER)
takeaways = [
("1", "Albumin = largest peak. Any reduction = significant (liver, kidney, nutrition).", YELLOW_ACC),
("2", "α1 ↓ → think AAT deficiency; α1+α2 ↑ → think acute phase response.", RGBColor(0x7D, 0xBF, 0xFF)),
("3", "α2 ↑↑ with ↓ albumin (other fractions ↓) = NEPHROTIC SYNDROME pattern.", RGBColor(0xFF, 0x99, 0x66)),
("4", "β-γ bridging = CIRRHOSIS hallmark (IgA fills the trough).", RGBColor(0x99, 0xFF, 0xCC)),
("5", "M-spike = monoclonal protein → always confirm with IFE. Check UPEP too.", RGBColor(0xFF, 0x77, 0x77)),
("6", "10% of myeloma has NO M-spike — only hypogammaglobulinemia. Order free light chains!", YELLOW_ACC),
("7", "Pseudo M-spikes: fibrinogen, hemoglobin, CRP, transferrin, antibiotics, contrast.", RGBColor(0xCC, 0xFF, 0xCC)),
("8", "Always read: Total protein → Albumin → A/G ratio → α1/α2 → β → γ (systematic approach)", RGBColor(0xAE, 0xCC, 0xEE)),
]
for i, (num, text, col) in enumerate(takeaways):
row = i // 2
col_n = i % 2
x = 0.3 + col_n * 6.5
y = 1.2 + row * 1.38
add_rect(slide, x, y, 6.1, 1.25, fill_color=RGBColor(0x22, 0x44, 0x6E),
line_color=col, line_width=Pt(1.5))
add_rect(slide, x, y, 0.5, 1.25, fill_color=col)
add_text(slide, num, x+0.05, y+0.35, 0.4, 0.55, font_size=18, bold=True,
color=DARK_BLUE, align=PP_ALIGN.CENTER)
add_multiline_textbox(slide, [
(text, False, WHITE, 13, 0)
], x+0.6, y+0.18, 5.4, 0.95)
add_text(slide, "Source: Quick Compendium of Clinical Pathology, 5th Ed. | Orris Medical Library",
0.3, 7.05, 12.5, 0.35, font_size=10, color=RGBColor(0x88, 0xAA, 0xCC), align=PP_ALIGN.CENTER)
# ---- SAVE ----
out_path = "/tmp/workspace/spep-ppt/SPEP_Complete_Guide.pptx"
prs.save(out_path)
print(f"Saved: {out_path}")
cd /tmp/workspace/spep-ppt && python build_spep.py 2>&1
**/*.py in /tmp/skills
~/spep-ppt/build_spep.py
Successfully replaced 1 instance(s) of the string in '/tmp/workspace/spep-ppt/build_spep.py'
~/spep-ppt/build_spep.py
Successfully replaced 1 instance(s) of the string in '/tmp/workspace/spep-ppt/build_spep.py'
cd /tmp/workspace/spep-ppt && python build_spep.py 2>&1
ls -lh /tmp/workspace/spep-ppt/SPEP_Complete_Guide.pptx
Plz do it
Please if not than elaborate here