GFR answer include defination machainism regulation and calculation Physiology
python -m markitdown /home/daytona/workspace/attachments/5e8f80b9-819d-478a-92f9-93d3f5f00f73/"renal system 2020.pptx" 2>/dev/null | head -300
python -m markitdown "/home/daytona/workspace/attachments/5e8f80b9-819d-478a-92f9-93d3f5f00f73/renal system 2020.pptx" 2>&1 | grep -i -A 20 "GFR\|filtration\|glomerular" | head -200
python -m markitdown "/home/daytona/workspace/attachments/5e8f80b9-819d-478a-92f9-93d3f5f00f73/renal system 2020.pptx" 2>&1 | head -500
cd /home/daytona/skills/pptx && python scripts/thumbnail.py "/home/daytona/workspace/attachments/5e8f80b9-819d-478a-92f9-93d3f5f00f73/renal system 2020.pptx" 2>&1 | head -50; python3 -c " from pptx import Presentation prs = Presentation('/home/daytona/workspace/attachments/5e8f80b9-819d-478a-92f9-93d3f5f00f73/renal system 2020.pptx') for i, slide in enumerate(prs.slides): texts = [] for shape in slide.shapes: if shape.has_text_frame: for para in shape.text_frame.paragraphs: t = para.text.strip() if t: texts.append(t) if texts: print(f'--- Slide {i+1} ---') for t in texts: print(t) " 2>&1 | head -300
cd /home/daytona/skills/pptx && python3 scripts/office/unpack.py "/home/daytona/workspace/attachments/5e8f80b9-819d-478a-92f9-93d3f5f00f73/renal system 2020.pptx" /tmp/renal_unpacked/ 2>&1 | head -20
ls /tmp/renal_unpacked/ppt/slides/ | head -20; python3 -c " import os, re slide_dir = '/tmp/renal_unpacked/ppt/slides/' files = sorted([f for f in os.listdir(slide_dir) if f.endswith('.xml') and not 'layout' in f and not 'master' in f]) for fn in files[:40]: path = os.path.join(slide_dir, fn) with open(path) as f: content = f.read() # Extract text texts = re.findall(r'<a:t[^>]*>([^<]+)</a:t>', content) if texts: print(f'=== {fn} ===') for t in texts: t = t.strip() if t: print(t) print() " 2>&1 | head -400
python3 -c " import os, re slide_dir = '/tmp/renal_unpacked/ppt/slides/' files = sorted([f for f in os.listdir(slide_dir) if f.endswith('.xml') and not 'layout' in f and not 'master' in f]) for fn in files[40:]: path = os.path.join(slide_dir, fn) with open(path) as f: content = f.read() texts = re.findall(r'<a:t[^>]*>([^<]+)</a:t>', content) if texts: print(f'=== {fn} ===') for t in texts: t = t.strip() if t: print(t) print() " 2>&1 | head -400
SNGFR = Kf × Net Ultrafiltration Pressure
Net Ultrafiltration Pressure = (P_gc - P_bs) - (π_gc - π_bs)
| Force | Value | Direction |
|---|---|---|
| P_gc (glomerular capillary hydrostatic pressure) | ~45 mmHg | Pro-filtration |
| P_bs (Bowman's space hydrostatic pressure) | ~10 mmHg | Opposes filtration |
| π_gc (glomerular capillary oncotic pressure) | ~25 mmHg | Opposes filtration |
| π_bs (Bowman's space oncotic pressure) | ~0 mmHg | (negligible - no protein in filtrate) |
Note on filtration equilibrium: As blood flows along the glomerular capillary, plasma proteins concentrate, raising π_gc progressively. Toward the efferent end, filtration pressure falls. In healthy glomeruli, filtration equilibrium is never fully reached because: (1) efferent arteriolar resistance maintains capillary hydrostatic pressure, and (2) progressive morphologic changes reduce permeability at the efferent end. - Comprehensive Clinical Nephrology, 7th Ed.
| Variable | Effect on P_gc | Effect on GFR |
|---|---|---|
| ↑ Arterial pressure | ↑ P_gc | ↑ GFR (buffered by autoregulation) |
| ↑ Afferent arteriolar resistance | ↓ P_gc | ↓ GFR |
| ↑ Efferent arteriolar resistance | ↑ P_gc (initially) | ↑ GFR at low doses; ↓ GFR at high doses (reduced RBF) |
| Factor | Mechanism | Effect on GFR |
|---|---|---|
| Sympathetic nerves (NE) | Constricts afferent arteriole | ↓ GFR |
| Angiotensin II | Constricts efferent > afferent | ↑ GFR (low dose); ↓ GFR (high dose) |
| ANP (Atrial natriuretic peptide) | Dilates afferent arteriole | ↑ GFR |
| ADH (vasopressin) | Vasoconstriction | ↓ GFR |
| Nitric oxide (NO) | Vasodilation | ↑ GFR |
| Endothelin / Adenosine / ATP | Vasoconstriction | ↓ GFR |
| Prostaglandins (PGE2, PGI2) | Vasodilation (afferent) | Maintain GFR (esp. in low-flow states) |
C_x = (U_x × V) / P_x
GFR = (U_inulin × V) / P_inulin
eGFR = [140 - Age] × Weight × (0.85 if female) / [72 × S_Cr (mg/dL)]
eGFR = 186 × (S_Cr)^-1.154 × (Age)^-0.203 × (0.742 if female) × (1.210 if African-American)
| Marker | Method | Notes |
|---|---|---|
| Inulin | Urinary clearance (IV infusion) | Gold standard |
| Iothalamate (^125I) | Urinary/plasma clearance | May overestimate (tubular secretion) |
| ^99mTc-DTPA | Plasma clearance | May underestimate (protein binding) |
| ^51Cr-EDTA | Plasma clearance | ~10% lower than inulin |
| Iohexol | Plasma clearance | Most practical non-radioactive alternative |
| Marker | Limitation |
|---|---|
| Creatinine | Partially secreted by tubules → overestimates GFR; affected by muscle mass, diet, drugs |
| Cystatin C | Less affected by muscle mass; better in elderly, amputees |
| Urea/BUN | Reabsorbed (~50%) → underestimates GFR |
| Parameter | Value |
|---|---|
| Normal GFR | 125 mL/min (men ~130, women ~120 mL/min/1.73 m²) |
| Net filtration pressure | ~10 mmHg |
| Kf | ~12.5 mL/min/mmHg |
| Glomerular capillary P | ~45 mmHg |
| Bowman's space P | ~10 mmHg |
| Plasma oncotic P | ~25 mmHg |
| Daily filtrate volume | ~180 L/day |
| Urine output | ~1.5 L/day |
| Filtration fraction (FF) | ~20% (GFR/RPF = 125/625) |
GFR INCLUDE - DEFINATION Normal value MECHANISM CALCULATION CONTENT FROM ABOVE PDF Physiology 5 marker
"GFR refers to volume of the glomerular filtrate formed each minute by all the nephrons in both the kidneys."
- Your PPTX Slide 50 (LRM VII.2 BDS Curriculum Physiology)
| Parameter | Value |
|---|---|
| GFR (normal) | 125 mL/min |
| GFR per day | 170-180 L/day |
| Men (indexed) | ~130 mL/min/1.73 m² BSA |
| Women (indexed) | ~120 mL/min/1.73 m² BSA |
| Net filtration pressure | 10 mmHg |
| Filtration coefficient (Kf) | 12.5 mL/min/mmHg |
| Daily urine output | ~1.5 L/day |
| Filtration fraction (FF) | ~20% (GFR/RPF = 125/625) |
Normal GFR in men is ~8% higher than women and declines ~0.75 mL/min/year after age 40. During pregnancy, GFR increases by ~50% in the first trimester.
GFR = Kf × Net Ultrafiltration Pressure
Net EFP = P_gc - P_bs - π_gc + π_bs
| Starling Force | Value | Direction |
|---|---|---|
| P_gc (glomerular capillary hydrostatic pressure) | 45 mmHg | ✅ Pro-filtration |
| P_bs (Bowman's space hydrostatic pressure) | 10 mmHg | ❌ Opposes filtration |
| π_gc (plasma oncotic pressure in glomerulus) | 25 mmHg | ❌ Opposes filtration |
| π_bs (oncotic pressure in Bowman's space) | 0 mmHg | Negligible (no protein) |
EFP = 45 - (10 + 25) = 10 mmHg
GFR = Kf × EFP = 12.5 × 10 = 125 mL/min ✓
Kf = Hydraulic conductivity × Capillary surface area
| Symbol | Meaning |
|---|---|
| C_x | Clearance of substance x (mL/min) |
| U_x | Urinary concentration of x |
| V | Urine flow rate (mL/min) |
| P_x | Plasma concentration of x |
| # | Marker | Clearance vs GFR | Key Facts |
|---|---|---|---|
| 1 | Creatinine | > GFR (overestimates) | Partially secreted by tubules; affected by muscle mass, drugs, diet. Most widely used clinically |
| 2 | Cystatin C | ≈ GFR | Freely filtered; not affected by muscle mass; better in elderly, amputees, extremes of weight |
| 3 | Urea (BUN) | < GFR (underestimates) | ~50% reabsorbed by tubules; affected by protein intake and hydration |
| # | Marker | Method | Key Facts |
|---|---|---|---|
| 4 | Inulin | Urinary clearance (continuous IV infusion) | GOLD STANDARD - freely filtered, not secreted/reabsorbed/metabolized. Reference against which all others are compared |
| 5 | Iohexol | Plasma clearance (IV bolus) | Most practical non-radioactive alternative; assayed by HPLC; used in research |
"The classic method for GFR measurement described by Homer Smith is the urinary clearance of inulin and remains the reference (gold standard) against which other clearance methods and filtration markers are evaluated."
- Comprehensive Clinical Nephrology, 7th Ed.
GLOMERULAR FILTRATION
│
▼
EFP = Pgc - Pbs - πgc + πbs
10 = 45 - 10 - 25 + 0 (mmHg)
│
▼
GFR = Kf × EFP
125 = 12.5 × 10 (mL/min)
│
▼
Measured by CLEARANCE
C = (U × V) / P
│
┌────┴─────┐
│ │
Inulin Creatinine
(gold (clinical
standard) standard)
Generate a pdf on that exactly how I have to write in exam for 5 marker
ls /home/daytona/workspace/ 2>/dev/null && mkdir -p /home/daytona/workspace/gfr-exam
~/gfr-exam/generate_gfr_pdf.py
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm
from reportlab.lib import colors
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether
)
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus import Flowable
# ── Output path ──────────────────────────────────────────────────────────────
OUTPUT = "/home/daytona/workspace/gfr-exam/GFR_5_Marker_Exam_Answer.pdf"
# ── Document ─────────────────────────────────────────────────────────────────
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
leftMargin=2.2*cm, rightMargin=2.2*cm,
topMargin=2*cm, bottomMargin=2*cm,
)
W = A4[0] - 4.4*cm # usable width
# ── Colour palette ────────────────────────────────────────────────────────────
NAVY = colors.HexColor("#1a3a5c")
TEAL = colors.HexColor("#17737a")
GOLD = colors.HexColor("#d4a017")
LGREY = colors.HexColor("#f0f4f8")
MGREY = colors.HexColor("#d0dce8")
WHITE = colors.white
BLACK = colors.black
RED = colors.HexColor("#c0392b")
GREEN = colors.HexColor("#1a6e3c")
# ── Styles ────────────────────────────────────────────────────────────────────
base = getSampleStyleSheet()
def S(name, parent="Normal", **kw):
return ParagraphStyle(name, parent=base[parent], **kw)
sTitle = S("sTitle", fontSize=18, leading=22, textColor=WHITE,
alignment=TA_CENTER, fontName="Helvetica-Bold", spaceAfter=0)
sSubtitle = S("sSubtitle", fontSize=11, leading=14, textColor=MGREY,
alignment=TA_CENTER, fontName="Helvetica", spaceAfter=0)
sQ = S("sQ", fontSize=12, leading=15, textColor=WHITE,
fontName="Helvetica-Bold", spaceAfter=0)
sSection = S("sSection", fontSize=11, leading=14, textColor=NAVY,
fontName="Helvetica-Bold", spaceBefore=8, spaceAfter=4)
sSubSection = S("sSubSection", fontSize=10, leading=13, textColor=TEAL,
fontName="Helvetica-Bold", spaceBefore=5, spaceAfter=2)
sBody = S("sBody", fontSize=9.5, leading=14, textColor=BLACK,
fontName="Helvetica", alignment=TA_JUSTIFY, spaceAfter=3)
sBullet = S("sBullet", fontSize=9.5, leading=13, textColor=BLACK,
fontName="Helvetica", leftIndent=14, spaceAfter=2)
sFormula = S("sFormula", fontSize=10, leading=14, textColor=NAVY,
fontName="Helvetica-Bold", alignment=TA_CENTER,
backColor=LGREY, spaceBefore=4, spaceAfter=4)
sNote = S("sNote", fontSize=8.5, leading=12, textColor=colors.HexColor("#555555"),
fontName="Helvetica-Oblique", leftIndent=10, spaceAfter=3)
sFooter = S("sFooter", fontSize=7.5, leading=10, textColor=colors.HexColor("#888888"),
alignment=TA_CENTER)
sMarkerHead = S("sMarkerHead", fontSize=9.5, leading=12, textColor=WHITE,
fontName="Helvetica-Bold")
sTableCell = S("sTableCell", fontSize=9, leading=12, textColor=BLACK,
fontName="Helvetica")
sTableHead = S("sTableHead", fontSize=9, leading=12, textColor=WHITE,
fontName="Helvetica-Bold")
# ── Helper: coloured box title ────────────────────────────────────────────────
def section_box(text, bg=NAVY):
t = Table([[Paragraph(text, sSection)]],
colWidths=[W])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("TEXTCOLOR", (0,0), (-1,-1), WHITE),
("LEFTPADDING",(0,0), (-1,-1), 8),
("RIGHTPADDING",(0,0),(-1,-1), 8),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING",(0,0),(-1,-1), 5),
("ROUNDEDCORNERS", [3,3,3,3]),
]))
return t
def subsection_label(text):
return Paragraph(f"<font color='#17737a'><b>{text}</b></font>", sSubSection)
def body(text):
return Paragraph(text, sBody)
def bullet(text):
return Paragraph(f"• {text}", sBullet)
def note(text):
return Paragraph(f"<i>{text}</i>", sNote)
def formula(text):
return Paragraph(text, sFormula)
def sp(h=4):
return Spacer(1, h)
def hr(color=MGREY, thickness=0.5):
return HRFlowable(width="100%", thickness=thickness, color=color, spaceAfter=4, spaceBefore=4)
# ── Build story ───────────────────────────────────────────────────────────────
story = []
# ── HEADER BANNER ─────────────────────────────────────────────────────────────
header_data = [[
Paragraph("GLOMERULAR FILTRATION RATE (GFR)", sTitle),
Paragraph("Physiology | BDS / MBBS | 5-Mark Exam Answer", sSubtitle),
]]
header = Table(
[[Paragraph("GLOMERULAR FILTRATION RATE (GFR)", sTitle)],
[Paragraph("Physiology · BDS / MBBS · 5-Mark Exam Answer", sSubtitle)]],
colWidths=[W]
)
header.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), NAVY),
("TOPPADDING", (0,0), (-1,-1), 12),
("BOTTOMPADDING", (0,0), (-1,-1), 12),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING", (0,0), (-1,-1), 10),
]))
story.append(header)
story.append(sp(10))
# ── QUESTION BOX ──────────────────────────────────────────────────────────────
q_box = Table(
[[Paragraph("Q. Write a short note on Glomerular Filtration Rate (GFR). <font color='#ffd700'>[5 marks]</font>", sQ)]],
colWidths=[W]
)
q_box.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), TEAL),
("TOPPADDING", (0,0), (-1,-1), 8),
("BOTTOMPADDING", (0,0), (-1,-1), 8),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING", (0,0), (-1,-1), 10),
]))
story.append(q_box)
story.append(sp(10))
# ══════════════════════════════════════════════════════════════════════════════
# 1. DEFINITION
# ══════════════════════════════════════════════════════════════════════════════
story.append(section_box("1. DEFINITION"))
story.append(sp(5))
story.append(body(
"GFR is defined as the <b>volume of glomerular filtrate formed per minute by all the nephrons "
"in both kidneys combined.</b>"
))
story.append(sp(3))
story.append(body(
"The filtrate produced is an <b>ultrafiltrate of plasma</b> — identical to plasma in osmolarity, "
"pH, electrolytes, and small organic molecules (glucose, urea, creatinine), but "
"<b>practically contains no protein and no cells.</b>"
))
story.append(sp(8))
# ══════════════════════════════════════════════════════════════════════════════
# 2. NORMAL VALUE
# ══════════════════════════════════════════════════════════════════════════════
story.append(section_box("2. NORMAL VALUE", bg=TEAL))
story.append(sp(5))
nv_data = [
[Paragraph("<b>Parameter</b>", sTableHead), Paragraph("<b>Value</b>", sTableHead)],
[Paragraph("GFR (normal)", sTableCell), Paragraph("<b>125 mL/min</b>", sTableCell)],
[Paragraph("GFR per day", sTableCell), Paragraph("170–180 L/day", sTableCell)],
[Paragraph("Men (BSA-indexed)", sTableCell), Paragraph("~130 mL/min / 1.73 m²", sTableCell)],
[Paragraph("Women (BSA-indexed)", sTableCell),Paragraph("~120 mL/min / 1.73 m²", sTableCell)],
[Paragraph("Net filtration pressure", sTableCell), Paragraph("10 mmHg", sTableCell)],
[Paragraph("Filtration coefficient (Kf)", sTableCell), Paragraph("12.5 mL/min/mmHg", sTableCell)],
[Paragraph("Filtration fraction (FF)", sTableCell), Paragraph("~20% (GFR / RPF = 125/625)", sTableCell)],
]
nv_table = Table(nv_data, colWidths=[W*0.52, W*0.48])
nv_table.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), NAVY),
("BACKGROUND", (0,1), (-1,1), LGREY),
("BACKGROUND", (0,2), (-1,2), WHITE),
("BACKGROUND", (0,3), (-1,3), LGREY),
("BACKGROUND", (0,4), (-1,4), WHITE),
("BACKGROUND", (0,5), (-1,5), LGREY),
("BACKGROUND", (0,6), (-1,6), WHITE),
("BACKGROUND", (0,7), (-1,7), LGREY),
("GRID", (0,0), (-1,-1), 0.4, MGREY),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 7),
("RIGHTPADDING", (0,0), (-1,-1), 7),
]))
story.append(nv_table)
story.append(sp(4))
story.append(note("GFR declines ~0.75 mL/min/year after age 40. Increases ~50% during pregnancy (first trimester)."))
story.append(sp(8))
# ══════════════════════════════════════════════════════════════════════════════
# 3. MECHANISM
# ══════════════════════════════════════════════════════════════════════════════
story.append(section_box("3. MECHANISM OF GLOMERULAR FILTRATION"))
story.append(sp(5))
story.append(subsection_label("A. Glomerular Membrane — Three Layers"))
for b in [
"1. <b>Fenestrated capillary endothelium</b> — intracellular pores allow fluid transudation.",
"2. <b>Basement membrane</b> — main size and charge barrier.",
"3. <b>Bowman's epithelium (podocytes)</b> — finger-like processes with filtration slits.",
]:
story.append(bullet(b))
story.append(sp(5))
story.append(subsection_label("B. Starling Forces — The Filtration Equation"))
story.append(body("Filtration is governed by the balance of hydrostatic and oncotic pressures:"))
story.append(sp(3))
story.append(formula("GFR = Kf × Net Effective Filtration Pressure (EFP)"))
story.append(sp(2))
story.append(formula("EFP = P<sub>gc</sub> − P<sub>bs</sub> − π<sub>gc</sub> + π<sub>bs</sub>"))
story.append(sp(4))
forces_data = [
[Paragraph("<b>Force</b>", sTableHead),
Paragraph("<b>Value</b>", sTableHead),
Paragraph("<b>Direction</b>", sTableHead)],
[Paragraph("P<sub>gc</sub> Glomerular capillary hydrostatic pressure", sTableCell),
Paragraph("45 mmHg", sTableCell),
Paragraph("<font color='#1a6e3c'><b>✔ Pro-filtration</b></font>", sTableCell)],
[Paragraph("P<sub>bs</sub> Bowman's space hydrostatic pressure", sTableCell),
Paragraph("10 mmHg", sTableCell),
Paragraph("<font color='#c0392b'>✖ Opposes filtration</font>", sTableCell)],
[Paragraph("π<sub>gc</sub> Plasma oncotic pressure (glomerulus)", sTableCell),
Paragraph("25 mmHg", sTableCell),
Paragraph("<font color='#c0392b'>✖ Opposes filtration</font>", sTableCell)],
[Paragraph("π<sub>bs</sub> Bowman's space oncotic pressure", sTableCell),
Paragraph("0 mmHg", sTableCell),
Paragraph("Negligible (no protein)", sTableCell)],
]
forces_table = Table(forces_data, colWidths=[W*0.52, W*0.18, W*0.30])
forces_table.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), NAVY),
("BACKGROUND", (0,1), (-1,1), colors.HexColor("#eaf7ea")),
("BACKGROUND", (0,2), (-1,2), colors.HexColor("#fdecea")),
("BACKGROUND", (0,3), (-1,3), colors.HexColor("#fdecea")),
("BACKGROUND", (0,4), (-1,4), LGREY),
("GRID", (0,0), (-1,-1), 0.4, MGREY),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 7),
("RIGHTPADDING", (0,0), (-1,-1), 7),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
]))
story.append(forces_table)
story.append(sp(5))
story.append(formula("EFP = 45 − (10 + 25) = <b>10 mmHg</b>"))
story.append(formula("GFR = 12.5 × 10 = <b>125 mL/min ✓</b>"))
story.append(sp(4))
story.append(subsection_label("C. Filtration Coefficient (Kf)"))
story.append(body("<b>Kf = Hydraulic conductivity × Capillary surface area</b>"))
story.append(body("Normal Kf = 12.5 mL/min/mmHg (400× greater than most capillary beds)."))
story.append(body("Diseases that reduce Kf → reduce GFR:"))
for item in ["Chronic hypertension", "Obesity / Diabetes mellitus", "Glomerulonephritis"]:
story.append(bullet(item))
story.append(sp(8))
# ══════════════════════════════════════════════════════════════════════════════
# 4. CALCULATION
# ══════════════════════════════════════════════════════════════════════════════
story.append(section_box("4. CALCULATION OF GFR", bg=colors.HexColor("#2e4057")))
story.append(sp(5))
story.append(body(
"GFR <b>cannot be measured directly</b>. It is calculated from the <b>clearance</b> of "
"filtration markers using the formula:"
))
story.append(sp(3))
story.append(formula("C<sub>x</sub> = ( U<sub>x</sub> × V ) / P<sub>x</sub>"))
story.append(sp(3))
# Clearance symbols table
sym_data = [
[Paragraph("<b>Symbol</b>", sTableHead), Paragraph("<b>Meaning</b>", sTableHead)],
[Paragraph("C<sub>x</sub>", sTableCell), Paragraph("Clearance of substance x (mL/min)", sTableCell)],
[Paragraph("U<sub>x</sub>", sTableCell), Paragraph("Urinary concentration of x", sTableCell)],
[Paragraph("V", sTableCell), Paragraph("Urine flow rate (mL/min)", sTableCell)],
[Paragraph("P<sub>x</sub>", sTableCell), Paragraph("Plasma concentration of x", sTableCell)],
]
sym_table = Table(sym_data, colWidths=[W*0.2, W*0.8])
sym_table.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), NAVY),
("ROWBACKGROUNDS",(0,1), (-1,-1), [LGREY, WHITE]),
("GRID", (0,0), (-1,-1), 0.4, MGREY),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
("ALIGN", (0,0), (0,-1), "CENTER"),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
]))
story.append(sym_table)
story.append(sp(5))
story.append(note(
"A substance is an ideal GFR marker if it is freely filtered and NOT reabsorbed, secreted, "
"synthesized, or metabolized by the kidney → then Cx = GFR exactly."
))
story.append(sp(6))
story.append(subsection_label("Clinical eGFR Equations"))
# Equations
eq_data = [
[Paragraph("<b>Equation</b>", sTableHead), Paragraph("<b>Formula</b>", sTableHead), Paragraph("<b>Use</b>", sTableHead)],
[Paragraph("Cockcroft-Gault", sTableCell),
Paragraph("[140−Age] × Wt × (0.85 if ♀) / 72 × SCr", sTableCell),
Paragraph("Drug dosing", sTableCell)],
[Paragraph("MDRD", sTableCell),
Paragraph("186 × SCr⁻¹·¹⁵⁴ × Age⁻⁰·²⁰³ × (0.742 if ♀) × (1.21 if AA)", sTableCell),
Paragraph("CKD staging", sTableCell)],
[Paragraph("CKD-EPI", sTableCell),
Paragraph("Complex formula; normalized to 1.73 m² BSA", sTableCell),
Paragraph("<b>Most accurate — preferred</b>", sTableCell)],
]
eq_table = Table(eq_data, colWidths=[W*0.22, W*0.52, W*0.26])
eq_table.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), NAVY),
("ROWBACKGROUNDS",(0,1), (-1,-1), [LGREY, WHITE, LGREY]),
("GRID", (0,0), (-1,-1), 0.4, MGREY),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 6),
("RIGHTPADDING", (0,0), (-1,-1), 6),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
]))
story.append(eq_table)
story.append(sp(4))
story.append(note(
"Example (Cockcroft-Gault): Male, 22 yrs, 60 kg, SCr 1.0 mg/dL → "
"eGFR = (140×22×60) / (72×1.0) = 122 mL/min"
))
story.append(sp(8))
# ══════════════════════════════════════════════════════════════════════════════
# 5. FILTRATION MARKERS
# ══════════════════════════════════════════════════════════════════════════════
story.append(section_box("5. FILTRATION MARKERS (5 Key Markers)", bg=colors.HexColor("#1a5276")))
story.append(sp(6))
markers = [
{
"num": "1",
"name": "INULIN",
"tag": "GOLD STANDARD",
"tag_color": GOLD,
"type": "Exogenous",
"clearance": "= GFR (exact)",
"method": "Urinary clearance — continuous IV infusion",
"key": [
"Freely filtered at glomerulus.",
"NOT reabsorbed, secreted, synthesized, or metabolized.",
"Reference standard (Homer Smith's method) against which all others are validated.",
"Cumbersome in practice — not used routinely.",
],
},
{
"num": "2",
"name": "CREATININE",
"tag": "ROUTINE CLINICAL",
"tag_color": TEAL,
"type": "Endogenous",
"clearance": "> GFR (overestimates ~10–20%)",
"method": "24-hr urine collection or serum creatinine eGFR",
"key": [
"Freely filtered + <b>partially secreted</b> by tubules → overestimates GFR.",
"Affected by muscle mass, diet (meat), age, drugs (e.g., trimethoprim).",
"Most widely used clinically — forms basis of MDRD and CKD-EPI equations.",
"Serum creatinine is inversely proportional to GFR.",
],
},
{
"num": "3",
"name": "UREA (BUN)",
"tag": "CRUDE ESTIMATE",
"tag_color": colors.HexColor("#7d6608"),
"type": "Endogenous",
"clearance": "< GFR (underestimates ~40–50%)",
"method": "Blood urea nitrogen (BUN) level",
"key": [
"Freely filtered + <b>~50% reabsorbed</b> by tubules → underestimates GFR.",
"Affected by protein intake, hydration, liver function, catabolic state.",
"BUN : Creatinine ratio >20 suggests pre-renal cause; <10 suggests malnutrition.",
"Used alongside creatinine, not alone.",
],
},
{
"num": "4",
"name": "CYSTATIN C",
"tag": "BETTER ALTERNATIVE",
"tag_color": GREEN,
"type": "Endogenous",
"clearance": "≈ GFR",
"method": "Serum cystatin C level",
"key": [
"Freely filtered; completely reabsorbed and catabolised in proximal tubule (not excreted).",
"<b>Not affected by muscle mass</b> → better in elderly, amputees, extreme body weights.",
"Superior to creatinine in early CKD detection.",
"More expensive; less widely available than creatinine.",
],
},
{
"num": "5",
"name": "IOHEXOL",
"tag": "RESEARCH / REFERENCE",
"tag_color": colors.HexColor("#6c3483"),
"type": "Exogenous",
"clearance": "≈ GFR",
"method": "Plasma clearance after IV bolus injection",
"key": [
"Non-ionic, non-radioactive contrast agent.",
"Most practical alternative to inulin for measured GFR (mGFR).",
"Assayed by HPLC or mass spectrometry.",
"May have minor extrarenal clearance → slight overestimation.",
],
},
]
for m in markers:
# Marker header row
header_row = Table(
[[
Paragraph(f"<b>Marker {m['num']}:</b> {m['name']}", sMarkerHead),
Paragraph(f" [{m['tag']}]", ParagraphStyle(
"tag", fontSize=8, leading=10, textColor=m["tag_color"],
fontName="Helvetica-Bold",
)),
]],
colWidths=[W*0.6, W*0.4],
)
header_row.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), NAVY),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING", (0,0), (-1,-1), 8),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
]))
detail_rows = [
[Paragraph("<b>Type:</b>", sTableCell), Paragraph(m["type"], sTableCell)],
[Paragraph("<b>Clearance:</b>", sTableCell), Paragraph(m["clearance"], sTableCell)],
[Paragraph("<b>Method:</b>", sTableCell), Paragraph(m["method"], sTableCell)],
]
detail_table = Table(detail_rows, colWidths=[W*0.22, W*0.78])
detail_table.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), LGREY),
("GRID", (0,0), (-1,-1), 0.3, MGREY),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
key_paras = [Paragraph(f"• {k}", sBullet) for k in m["key"]]
key_table = Table(
[[Paragraph("<b>Key Points:</b>", sTableCell)]] +
[[p] for p in key_paras],
colWidths=[W]
)
key_table.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), WHITE),
("LEFTPADDING", (0,0), (-1,-1), 12),
("RIGHTPADDING", (0,0), (-1,-1), 8),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LINEBELOW", (0,-1), (-1,-1), 0.6, MGREY),
]))
story.append(KeepTogether([header_row, detail_table, key_table, sp(6)]))
# ══════════════════════════════════════════════════════════════════════════════
# QUICK RECALL BOX
# ══════════════════════════════════════════════════════════════════════════════
story.append(sp(4))
recall_data = [[
Paragraph(
"<b>QUICK RECALL ★</b><br/><br/>"
"GFR = Kf × EFP = 12.5 × 10 = <b>125 mL/min</b><br/><br/>"
"EFP = 45 − 10 − 25 + 0 = <b>10 mmHg</b><br/><br/>"
"Clearance: C = (U × V) / P<br/><br/>"
"<b>Markers:</b> Inulin (gold) · Creatinine (clinical) · Urea (crude) · Cystatin C (best endo.) · Iohexol (practical exo.)",
ParagraphStyle("recall", fontSize=9.5, leading=15, textColor=NAVY,
fontName="Helvetica", alignment=TA_LEFT),
)
]]
recall_box = Table(recall_data, colWidths=[W])
recall_box.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), colors.HexColor("#fef9e7")),
("BOX", (0,0), (-1,-1), 1.5, GOLD),
("TOPPADDING", (0,0), (-1,-1), 12),
("BOTTOMPADDING", (0,0), (-1,-1), 12),
("LEFTPADDING", (0,0), (-1,-1), 14),
("RIGHTPADDING", (0,0), (-1,-1), 14),
]))
story.append(recall_box)
story.append(sp(12))
# ── FOOTER ────────────────────────────────────────────────────────────────────
story.append(hr(MGREY, 0.8))
story.append(Paragraph(
"Sources: Comprehensive Clinical Nephrology 7th Ed. · Guyton & Hall Medical Physiology · "
"Medical Physiology (Boron & Boulpaep) · NKF Primer on Kidney Diseases 8th Ed. · "
"LRM VII.2 BDS Curriculum Physiology MRDC",
sFooter
))
# ── BUILD ─────────────────────────────────────────────────────────────────────
doc.build(story)
print(f"PDF saved → {OUTPUT}")
cd /home/daytona/workspace/gfr-exam && python3 generate_gfr_pdf.py 2>&1
GFR 5 Marker Exam Answer
PDF Document · PDF
| Section | What's included |
|---|---|
| 1. Definition | Clear one-line definition + ultrafiltrate description |
| 2. Normal Value | Table: 125 mL/min, 170-180 L/day, male/female indexed values, Kf, EFP, FF |
| 3. Mechanism | Glomerular membrane layers + Starling forces table + full EFP calculation (45-10-25=10 mmHg → GFR=125) |
| 4. Calculation | Clearance formula (C = U×V/P) + all 3 eGFR equations (Cockcroft-Gault, MDRD, CKD-EPI) with worked example |
| 5. Filtration Markers | All 5 markers with type, clearance vs GFR, method, and key exam points |
| Quick Recall Box | Golden summary box at the end for last-minute revision |
Jog appratus 5 marker Physiology
~/gfr-exam/generate_jga_pdf.py
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm
from reportlab.lib import colors
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether
)
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
import urllib.request, io
OUTPUT = "/home/daytona/workspace/gfr-exam/JGA_5_Marker_Exam_Answer.pdf"
doc = SimpleDocTemplate(
OUTPUT, pagesize=A4,
leftMargin=2.2*cm, rightMargin=2.2*cm,
topMargin=2*cm, bottomMargin=2*cm,
)
W = A4[0] - 4.4*cm
# Colours
NAVY = colors.HexColor("#1a3a5c")
TEAL = colors.HexColor("#17737a")
GOLD = colors.HexColor("#d4a017")
DKRED = colors.HexColor("#922b21")
GREEN = colors.HexColor("#1a6e3c")
PURP = colors.HexColor("#6c3483")
LGREY = colors.HexColor("#f0f4f8")
MGREY = colors.HexColor("#d0dce8")
WHITE = colors.white
BLACK = colors.black
base = getSampleStyleSheet()
def S(name, parent="Normal", **kw):
return ParagraphStyle(name, parent=base[parent], **kw)
sTitle = S("sTitle", fontSize=18, leading=22, textColor=WHITE,
alignment=TA_CENTER, fontName="Helvetica-Bold")
sSub = S("sSub", fontSize=10, leading=13, textColor=MGREY,
alignment=TA_CENTER, fontName="Helvetica")
sQ = S("sQ", fontSize=12, leading=15, textColor=WHITE,
fontName="Helvetica-Bold")
sSection = S("sSection", fontSize=11, leading=14, textColor=WHITE,
fontName="Helvetica-Bold")
sSubSec = S("sSubSec", fontSize=10, leading=13, textColor=TEAL,
fontName="Helvetica-Bold", spaceBefore=5, spaceAfter=2)
sBody = S("sBody", fontSize=9.5, leading=14, textColor=BLACK,
fontName="Helvetica", alignment=TA_JUSTIFY, spaceAfter=3)
sBullet = S("sBullet", fontSize=9.5, leading=13, textColor=BLACK,
fontName="Helvetica", leftIndent=14, spaceAfter=2)
sFormula = S("sFormula", fontSize=10, leading=14, textColor=NAVY,
fontName="Helvetica-Bold", alignment=TA_CENTER,
backColor=LGREY, spaceBefore=4, spaceAfter=4)
sNote = S("sNote", fontSize=8.5, leading=12,
textColor=colors.HexColor("#555555"),
fontName="Helvetica-Oblique", leftIndent=10, spaceAfter=3)
sFooter = S("sFooter", fontSize=7.5, leading=10,
textColor=colors.HexColor("#888888"), alignment=TA_CENTER)
sTH = S("sTH", fontSize=9, leading=12, textColor=WHITE,
fontName="Helvetica-Bold")
sTD = S("sTD", fontSize=9, leading=12, textColor=BLACK,
fontName="Helvetica")
sRecall = S("sRecall", fontSize=9.5, leading=15, textColor=NAVY,
fontName="Helvetica")
def section_box(text, bg=NAVY):
t = Table([[Paragraph(text, sSection)]], colWidths=[W])
t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), bg),
("LEFTPADDING", (0,0),(-1,-1), 8),
("RIGHTPADDING", (0,0),(-1,-1), 8),
("TOPPADDING", (0,0),(-1,-1), 6),
("BOTTOMPADDING", (0,0),(-1,-1), 6),
]))
return t
def subsec(text):
return Paragraph(f"<font color='#17737a'><b>{text}</b></font>", sSubSec)
def body(t): return Paragraph(t, sBody)
def bullet(t): return Paragraph(f"• {t}", sBullet)
def note(t): return Paragraph(f"<i>{t}</i>", sNote)
def formula(t): return Paragraph(t, sFormula)
def sp(h=5): return Spacer(1, h)
def hr(): return HRFlowable(width="100%", thickness=0.5, color=MGREY, spaceAfter=4, spaceBefore=4)
story = []
# ── HEADER ────────────────────────────────────────────────────────────────────
hdr = Table([
[Paragraph("JUXTAGLOMERULAR APPARATUS (JGA)", sTitle)],
[Paragraph("Renal Physiology · BDS / MBBS · 5-Mark Exam Answer", sSub)],
], colWidths=[W])
hdr.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), NAVY),
("TOPPADDING", (0,0),(-1,-1), 12),
("BOTTOMPADDING", (0,0),(-1,-1), 12),
("LEFTPADDING", (0,0),(-1,-1), 10),
]))
story.append(hdr)
story.append(sp(10))
# ── QUESTION BOX ──────────────────────────────────────────────────────────────
qbox = Table([[Paragraph(
"Q. Write a short note on Juxtaglomerular Apparatus (JGA). "
" <font color='#ffd700'>[5 marks]</font>", sQ)]], colWidths=[W])
qbox.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), TEAL),
("TOPPADDING", (0,0),(-1,-1), 8),
("BOTTOMPADDING", (0,0),(-1,-1), 8),
("LEFTPADDING", (0,0),(-1,-1), 10),
]))
story.append(qbox)
story.append(sp(10))
# ══════════════════════════════════════════════════════════════════════════════
# 1. DEFINITION
# ══════════════════════════════════════════════════════════════════════════════
story.append(section_box("1. DEFINITION"))
story.append(sp(5))
story.append(body(
"The <b>Juxtaglomerular Apparatus (JGA)</b> is a specialised microscopic structure "
"located at the vascular pole of the renal corpuscle, where the "
"<b>distal tubule of a nephron comes into close contact with the afferent and efferent "
"arterioles of its own glomerulus.</b>"
))
story.append(sp(3))
story.append(body(
"It is a key regulator of <b>GFR, renal blood flow, sodium balance, extracellular fluid "
"volume, and systemic blood pressure</b> through the renin-angiotensin-aldosterone system "
"(RAAS) and tubuloglomerular feedback (TGF)."
))
story.append(sp(8))
# ══════════════════════════════════════════════════════════════════════════════
# 2. LOCATION
# ══════════════════════════════════════════════════════════════════════════════
story.append(section_box("2. LOCATION", bg=TEAL))
story.append(sp(5))
for b in [
"Situated at the <b>vascular pole</b> of each renal corpuscle (glomerulus).",
"The <b>distal convoluted tubule (DCT)</b> of each nephron loops back and touches "
"the afferent arteriole of its own glomerulus — this contact point forms the JGA.",
"Found in <b>both cortical and juxtamedullary nephrons</b>.",
"Present in <b>all ~1.3 million nephrons</b> per kidney.",
]:
story.append(bullet(b))
story.append(sp(8))
# ══════════════════════════════════════════════════════════════════════════════
# 3. COMPONENTS (STRUCTURE)
# ══════════════════════════════════════════════════════════════════════════════
story.append(section_box("3. COMPONENTS / STRUCTURE"))
story.append(sp(6))
# Diagram image
from reportlab.platypus import Image as RLImage
img_url = "https://cdn.orris.care/cdss_images/0aa4204a84727104da7b7ac6ad9a7b5daa329e3404c07dc119b62ce98f544dca.png"
try:
req = urllib.request.urlopen(img_url, timeout=10)
img_data = io.BytesIO(req.read())
img = RLImage(img_data, width=9*cm, height=6.5*cm)
img_table = Table([[img]], colWidths=[W])
img_table.setStyle(TableStyle([
("ALIGN", (0,0),(-1,-1), "CENTER"),
("TOPPADDING", (0,0),(-1,-1), 4),
("BOTTOMPADDING", (0,0),(-1,-1), 2),
]))
story.append(img_table)
story.append(Paragraph(
"<i>Fig. Structure of the Juxtaglomerular Apparatus — Ganong's Review of Medical Physiology</i>",
sNote
))
story.append(sp(6))
except Exception as e:
story.append(note(f"[Diagram: JGA structure — see textbook Fig. 38-8]"))
story.append(sp(4))
# Component cards
components = [
{
"num": "1",
"name": "JUXTAGLOMERULAR (GRANULAR) CELLS",
"bg": NAVY,
"points": [
"Modified <b>smooth muscle cells</b> in the <b>media of the afferent arteriole</b> "
"(and sometimes efferent arteriole) near the glomerulus.",
"Contain <b>secretory granules</b> storing <b>renin</b> (an aspartyl protease).",
"Also called <b>epithelioid cells</b> or <b>granular cells</b>.",
"Nuclei are <b>spherical</b> (unlike elongated nuclei of normal smooth muscle cells).",
"Densely innervated by <b>sympathetic nerve terminals</b>.",
"Connected to adjacent cells by <b>gap junctions</b>.",
"Under conditions of volume depletion or renal artery stenosis, additional upstream "
"smooth muscle cells <b>transform into granular cells</b> to increase renin output.",
],
"function": "SYNTHESIZE, STORE & RELEASE RENIN → activates RAAS",
},
{
"num": "2",
"name": "MACULA DENSA",
"bg": TEAL,
"points": [
"A plaque of <b>specialised epithelial cells</b> in the wall of the "
"<b>thick ascending limb of the loop of Henle</b> / early DCT.",
"Cells are <b>narrower, taller</b> with <b>large, crowded nuclei</b> — hence the name "
"('dense spot').",
"Contain a <b>Golgi apparatus</b> directed toward the arterioles — secretory function.",
"Rich in <b>neuronal nitric oxide synthase (nNOS)</b> and "
"<b>cyclooxygenase-2 (COX-2)</b>.",
"Cells are joined by <b>tight junctions</b> with low permeability.",
"Sense <b>NaCl concentration</b> in the tubular fluid via the "
"Na⁺/K⁺/2Cl⁻ co-transporter (NKCC2).",
"Lateral intercellular spaces vary with functional state.",
],
"function": "CHEMORECEPTOR — senses NaCl in filtrate → signals granular cells",
},
{
"num": "3",
"name": "EXTRAGLOMERULAR MESANGIAL CELLS (Lacis cells / Polkissen cells)",
"bg": colors.HexColor("#2e4057"),
"points": [
"Located in the <b>angle between the afferent and efferent arterioles</b> at the "
"glomerular hilum.",
"Also called <b>Lacis cells</b> (Goormaghtigh cells / Polkissen cells).",
"Heavily branched cells interconnected by <b>gap junctions</b>.",
"Processes contain <b>prominent microfilament bundles</b> — contractile.",
"Connected to the basement membrane of Bowman's capsule and walls of both arterioles.",
"Act as a <b>structural and functional bridge</b> between macula densa and granular cells.",
"Contain renin (significance unclear) — may facilitate signal transmission.",
],
"function": "INTERCELLULAR COMMUNICATION — bridges macula densa and granular cells",
},
]
for c in components:
# Header
c_hdr = Table(
[[Paragraph(f"Component {c['num']}: {c['name']}", S("ch", fontSize=9.5, leading=13,
textColor=WHITE, fontName="Helvetica-Bold"))]],
colWidths=[W]
)
c_hdr.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), c["bg"]),
("TOPPADDING", (0,0),(-1,-1), 6),
("BOTTOMPADDING", (0,0),(-1,-1), 6),
("LEFTPADDING", (0,0),(-1,-1), 10),
]))
# Points
pt_rows = [[Paragraph(f"• {p}", sBullet)] for p in c["points"]]
pt_table = Table(pt_rows, colWidths=[W])
pt_table.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), LGREY),
("LEFTPADDING", (0,0),(-1,-1), 12),
("TOPPADDING", (0,0),(-1,-1), 3),
("BOTTOMPADDING", (0,0),(-1,-1), 3),
]))
# Function bar
fn_bar = Table(
[[Paragraph(f"<b>Function:</b> {c['function']}",
S("fn", fontSize=9, leading=12, textColor=WHITE, fontName="Helvetica-Bold"))]],
colWidths=[W]
)
fn_bar.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), colors.HexColor("#1a5276")),
("TOPPADDING", (0,0),(-1,-1), 5),
("BOTTOMPADDING", (0,0),(-1,-1), 5),
("LEFTPADDING", (0,0),(-1,-1), 10),
]))
story.append(KeepTogether([c_hdr, pt_table, fn_bar, sp(6)]))
# ══════════════════════════════════════════════════════════════════════════════
# 4. FUNCTIONS
# ══════════════════════════════════════════════════════════════════════════════
story.append(section_box("4. FUNCTIONS OF THE JGA", bg=colors.HexColor("#1a5276")))
story.append(sp(6))
story.append(subsec("A. Renin Secretion → RAAS Activation"))
story.append(body(
"Granular cells release <b>renin</b> by exocytosis into the surrounding interstitium. "
"This is the <b>major source of systemic angiotensin II</b>, controlling extracellular volume "
"and blood pressure."
))
story.append(sp(3))
# RAAS cascade table
raas = [
[Paragraph("<b>Step</b>", sTH), Paragraph("<b>Event</b>", sTH), Paragraph("<b>Site</b>", sTH)],
[Paragraph("1", sTD), Paragraph("Renin released by JG cells", sTD), Paragraph("Kidney", sTD)],
[Paragraph("2", sTD), Paragraph("Renin cleaves Angiotensinogen → <b>Angiotensin I</b> (decapeptide)", sTD), Paragraph("Blood", sTD)],
[Paragraph("3", sTD), Paragraph("ACE converts Ang I → <b>Angiotensin II</b> (octapeptide)", sTD), Paragraph("Lungs", sTD)],
[Paragraph("4", sTD), Paragraph("Ang II → vasoconstriction + <b>Aldosterone</b> release", sTD), Paragraph("Adrenal cortex", sTD)],
[Paragraph("5", sTD), Paragraph("Aldosterone → ↑ Na⁺ reabsorption, ↑ K⁺ excretion → ↑ ECF volume → ↑ BP", sTD), Paragraph("Kidney DCT/CD", sTD)],
]
raas_t = Table(raas, colWidths=[W*0.08, W*0.62, W*0.30])
raas_t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), NAVY),
("ROWBACKGROUNDS",(0,1),(-1,-1), [LGREY, WHITE, LGREY, WHITE, LGREY]),
("GRID", (0,0),(-1,-1), 0.4, MGREY),
("TOPPADDING", (0,0),(-1,-1), 4),
("BOTTOMPADDING", (0,0),(-1,-1), 4),
("LEFTPADDING", (0,0),(-1,-1), 6),
("RIGHTPADDING", (0,0),(-1,-1), 6),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
("ALIGN", (0,0),(0,-1), "CENTER"),
]))
story.append(raas_t)
story.append(sp(6))
story.append(subsec("B. Tubuloglomerular Feedback (TGF) — Autoregulation of GFR"))
story.append(body(
"The TGF mechanism links NaCl concentration at the macula densa to arteriolar resistance, "
"maintaining a constant GFR (autoregulation range: <b>80–180 mmHg</b> mean arterial pressure)."
))
story.append(sp(3))
tgf_data = [
[Paragraph("<b>Stimulus</b>", sTH), Paragraph("<b>Macula Densa Response</b>", sTH), Paragraph("<b>Arteriolar Effect</b>", sTH), Paragraph("<b>Net GFR</b>", sTH)],
[Paragraph("↑ GFR\n(↑ NaCl delivery)", sTD),
Paragraph("NKCC2 activated → ATP → Adenosine released", sTD),
Paragraph("Afferent arteriole <b>constricts</b> → ↓ P_gc", sTD),
Paragraph("<font color='#c0392b'><b>↓ GFR</b></font>\n(returns to normal)", sTD)],
[Paragraph("↓ GFR\n(↓ NaCl delivery)", sTD),
Paragraph("Renin released; NO & PGE2 vasodilate", sTD),
Paragraph("Afferent arteriole <b>dilates</b>; Ang II constricts efferent", sTD),
Paragraph("<font color='#1a6e3c'><b>↑ GFR</b></font>\n(returns to normal)", sTD)],
]
tgf_t = Table(tgf_data, colWidths=[W*0.18, W*0.32, W*0.31, W*0.19])
tgf_t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), TEAL),
("BACKGROUND", (0,1),(-1,1), colors.HexColor("#fdecea")),
("BACKGROUND", (0,2),(-1,2), colors.HexColor("#eaf7ea")),
("GRID", (0,0),(-1,-1), 0.4, MGREY),
("TOPPADDING", (0,0),(-1,-1), 5),
("BOTTOMPADDING", (0,0),(-1,-1), 5),
("LEFTPADDING", (0,0),(-1,-1), 6),
("RIGHTPADDING", (0,0),(-1,-1), 6),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
]))
story.append(tgf_t)
story.append(sp(6))
story.append(subsec("C. Other Functions"))
for b in [
"<b>Erythropoietin secretion</b> — stimulates red blood cell production in the bone marrow.",
"<b>Myogenic autoregulation</b> — afferent arteriole smooth muscle reflexively contracts when "
"stretched by ↑ blood pressure → maintains constant glomerular pressure.",
"<b>Regulation of sodium and water balance</b> — via RAAS and direct tubular effects.",
]:
story.append(bullet(b))
story.append(sp(8))
# ══════════════════════════════════════════════════════════════════════════════
# 5. REGULATION OF RENIN SECRETION
# ══════════════════════════════════════════════════════════════════════════════
story.append(section_box("5. REGULATION OF RENIN SECRETION", bg=DKRED))
story.append(sp(5))
ren_data = [
[Paragraph("<b>STIMULATES Renin Release ↑</b>", S("rh1", fontSize=9, leading=12,
textColor=WHITE, fontName="Helvetica-Bold")),
Paragraph("<b>INHIBITS Renin Release ↓</b>", S("rh2", fontSize=9, leading=12,
textColor=WHITE, fontName="Helvetica-Bold"))],
[Paragraph("↓ Afferent arteriolar pressure (baroreceptor mechanism)", sTD),
Paragraph("↑ Afferent arteriolar pressure / stretch", sTD)],
[Paragraph("↓ NaCl delivery to macula densa (↓ tubular flow)", sTD),
Paragraph("↑ NaCl reabsorption across macula densa", sTD)],
[Paragraph("↑ Sympathetic activity (β₁ receptors on JG cells)", sTD),
Paragraph("Angiotensin II (negative feedback)", sTD)],
[Paragraph("↑ Circulating catecholamines", sTD),
Paragraph("Vasopressin (ADH)", sTD)],
[Paragraph("Prostaglandins (PGE₂, PGI₂)", sTD),
Paragraph("↑ ECF volume / hypervolaemia", sTD)],
[Paragraph("Nitric Oxide (NO)", sTD),
Paragraph("NSAIDs (block PGE₂ → reduce renin)", sTD)],
]
ren_t = Table(ren_data, colWidths=[W*0.50, W*0.50])
ren_t.setStyle(TableStyle([
("BACKGROUND", (0,0),(0,0), colors.HexColor("#1a6e3c")),
("BACKGROUND", (1,0),(1,0), DKRED),
("ROWBACKGROUNDS",(0,1),(-1,-1), [LGREY, WHITE, LGREY, WHITE, LGREY, WHITE]),
("GRID", (0,0),(-1,-1), 0.4, MGREY),
("TOPPADDING", (0,0),(-1,-1), 4),
("BOTTOMPADDING", (0,0),(-1,-1), 4),
("LEFTPADDING", (0,0),(-1,-1), 7),
("RIGHTPADDING", (0,0),(-1,-1), 7),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
]))
story.append(ren_t)
story.append(sp(10))
# ══════════════════════════════════════════════════════════════════════════════
# QUICK RECALL BOX
# ══════════════════════════════════════════════════════════════════════════════
recall = Table([[Paragraph(
"<b>QUICK RECALL ★</b><br/><br/>"
"<b>Components:</b> JG (Granular) cells · Macula Densa · Lacis (Extraglomerular Mesangial) cells<br/><br/>"
"<b>JG cells:</b> in media of afferent arteriole → store & release RENIN<br/>"
"<b>Macula densa:</b> in thick ascending limb / early DCT → senses NaCl → controls renin & GFR<br/>"
"<b>Lacis cells:</b> at junction of arterioles → signal bridge<br/><br/>"
"<b>Two functions:</b> (1) Renin release → RAAS → BP control | "
"(2) TGF → GFR autoregulation (80–180 mmHg)<br/><br/>"
"<b>RAAS chain:</b> Renin → Angiotensinogen → Ang I → (ACE, lungs) → Ang II → Aldosterone → ↑ Na⁺ reabsorption",
sRecall
)]], colWidths=[W])
recall.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), colors.HexColor("#fef9e7")),
("BOX", (0,0),(-1,-1), 1.5, GOLD),
("TOPPADDING", (0,0),(-1,-1), 12),
("BOTTOMPADDING", (0,0),(-1,-1), 12),
("LEFTPADDING", (0,0),(-1,-1), 14),
("RIGHTPADDING", (0,0),(-1,-1), 14),
]))
story.append(recall)
story.append(sp(12))
# ── FOOTER ────────────────────────────────────────────────────────────────────
story.append(HRFlowable(width="100%", thickness=0.8, color=MGREY, spaceAfter=4, spaceBefore=4))
story.append(Paragraph(
"Sources: Comprehensive Clinical Nephrology 7th Ed. · Ganong's Review of Medical Physiology 26th Ed. · "
"Guyton & Hall Medical Physiology · Histology — Text & Atlas (Eroschenko) · "
"NKF Primer on Kidney Diseases 8th Ed.",
sFooter
))
doc.build(story)
print(f"PDF saved → {OUTPUT}")
ls /tmp/workspace/ 2>/dev/null && mkdir -p /tmp/workspace/jga-exam
~/jga-exam/generate_jga_pdf.py
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm
from reportlab.lib import colors
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether
)
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
import urllib.request, io
OUTPUT = "/tmp/workspace/jga-exam/JGA_5_Marker_Exam_Answer.pdf"
doc = SimpleDocTemplate(
OUTPUT, pagesize=A4,
leftMargin=2.2*cm, rightMargin=2.2*cm,
topMargin=2*cm, bottomMargin=2*cm,
)
W = A4[0] - 4.4*cm
NAVY = colors.HexColor("#1a3a5c")
TEAL = colors.HexColor("#17737a")
GOLD = colors.HexColor("#d4a017")
DKRED = colors.HexColor("#922b21")
GREEN = colors.HexColor("#1a6e3c")
LGREY = colors.HexColor("#f0f4f8")
MGREY = colors.HexColor("#d0dce8")
WHITE = colors.white
BLACK = colors.black
base = getSampleStyleSheet()
def S(name, parent="Normal", **kw):
return ParagraphStyle(name, parent=base[parent], **kw)
sTitle = S("sTitle", fontSize=17, leading=21, textColor=WHITE, alignment=TA_CENTER, fontName="Helvetica-Bold")
sSub = S("sSub", fontSize=10, leading=13, textColor=MGREY, alignment=TA_CENTER, fontName="Helvetica")
sQ = S("sQ", fontSize=11, leading=14, textColor=WHITE, fontName="Helvetica-Bold")
sSec = S("sSec", fontSize=11, leading=14, textColor=WHITE, fontName="Helvetica-Bold")
sSubSec = S("sSubSec", fontSize=10, leading=13, textColor=TEAL, fontName="Helvetica-Bold", spaceBefore=5, spaceAfter=2)
sBody = S("sBody", fontSize=9.5, leading=14, textColor=BLACK, fontName="Helvetica", alignment=TA_JUSTIFY, spaceAfter=3)
sBullet = S("sBullet", fontSize=9.5, leading=13, textColor=BLACK, fontName="Helvetica", leftIndent=14, spaceAfter=2)
sNote = S("sNote", fontSize=8.5, leading=12, textColor=colors.HexColor("#555555"), fontName="Helvetica-Oblique", leftIndent=10, spaceAfter=3)
sFooter = S("sFooter", fontSize=7.5, leading=10, textColor=colors.HexColor("#888888"), alignment=TA_CENTER)
sTH = S("sTH", fontSize=9, leading=12, textColor=WHITE, fontName="Helvetica-Bold")
sTD = S("sTD", fontSize=9, leading=12, textColor=BLACK, fontName="Helvetica")
sRecall = S("sRecall", fontSize=9.5, leading=15, textColor=NAVY, fontName="Helvetica")
def secbox(text, bg=NAVY):
t = Table([[Paragraph(text, sSec)]], colWidths=[W])
t.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),bg),("LEFTPADDING",(0,0),(-1,-1),8),
("RIGHTPADDING",(0,0),(-1,-1),8),("TOPPADDING",(0,0),(-1,-1),6),("BOTTOMPADDING",(0,0),(-1,-1),6)]))
return t
def subsec(t): return Paragraph(f"<font color='#17737a'><b>{t}</b></font>", sSubSec)
def body(t): return Paragraph(t, sBody)
def bullet(t): return Paragraph(f"• {t}", sBullet)
def note(t): return Paragraph(f"<i>{t}</i>", sNote)
def sp(h=5): return Spacer(1, h)
story = []
# HEADER
hdr = Table([
[Paragraph("JUXTAGLOMERULAR APPARATUS (JGA)", sTitle)],
[Paragraph("Renal Physiology · BDS / MBBS · 5-Mark Exam Answer", sSub)],
], colWidths=[W])
hdr.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),NAVY),("TOPPADDING",(0,0),(-1,-1),12),
("BOTTOMPADDING",(0,0),(-1,-1),12),("LEFTPADDING",(0,0),(-1,-1),10)]))
story.append(hdr); story.append(sp(10))
qbox = Table([[Paragraph(
"Q. Write a short note on Juxtaglomerular Apparatus (JGA). "
"<font color='#ffd700'>[5 marks]</font>", sQ)]], colWidths=[W])
qbox.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),TEAL),("TOPPADDING",(0,0),(-1,-1),8),
("BOTTOMPADDING",(0,0),(-1,-1),8),("LEFTPADDING",(0,0),(-1,-1),10)]))
story.append(qbox); story.append(sp(10))
# ── 1. DEFINITION ─────────────────────────────────────────────────────────────
story.append(secbox("1. DEFINITION"))
story.append(sp(5))
story.append(body(
"The <b>Juxtaglomerular Apparatus (JGA)</b> is a specialised microscopic structure "
"located at the <b>vascular pole of the renal corpuscle</b>, where the distal tubule "
"of a nephron comes into close contact with the afferent and efferent arterioles of "
"<b>its own glomerulus.</b>"
))
story.append(sp(3))
story.append(body(
"It is central to the regulation of <b>GFR, renal blood flow, sodium balance, "
"extracellular fluid volume, and systemic blood pressure</b> through the "
"Renin-Angiotensin-Aldosterone System (RAAS) and tubuloglomerular feedback (TGF)."
))
story.append(sp(8))
# ── 2. LOCATION ────────────────────────────────────────────────────────────────
story.append(secbox("2. LOCATION", bg=TEAL))
story.append(sp(5))
for b in [
"Situated at the <b>vascular pole</b> of each renal corpuscle (glomerulus).",
"The <b>distal convoluted tubule (DCT)</b> of each nephron loops back and touches "
"the afferent arteriole of its own glomerulus — this is the JGA contact zone.",
"Found in both <b>cortical and juxtamedullary nephrons</b>.",
"Present in all ~<b>1.3 million nephrons</b> per kidney.",
]:
story.append(bullet(b))
story.append(sp(8))
# ── 3. COMPONENTS ──────────────────────────────────────────────────────────────
story.append(secbox("3. COMPONENTS / STRUCTURE"))
story.append(sp(5))
# Try embedding diagram
img_url = "https://cdn.orris.care/cdss_images/0aa4204a84727104da7b7ac6ad9a7b5daa329e3404c07dc119b62ce98f544dca.png"
try:
from reportlab.platypus import Image as RLImage
req = urllib.request.urlopen(img_url, timeout=12)
img_data = io.BytesIO(req.read())
img = RLImage(img_data, width=9*cm, height=6.5*cm)
img_wrap = Table([[img]], colWidths=[W])
img_wrap.setStyle(TableStyle([("ALIGN",(0,0),(-1,-1),"CENTER"),("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),2)]))
story.append(img_wrap)
story.append(note("Fig. Structure of JGA showing Lacis cells, Macula densa, Granular cells, Afferent & Efferent arterioles (Ganong's Review of Medical Physiology 26th Ed.)"))
story.append(sp(6))
except:
story.append(note("[Fig: JGA structure — Ganong's Review of Medical Physiology, Fig. 38-8]"))
story.append(sp(4))
# Component 1 — JG Cells
c1_hdr = Table([[Paragraph("Component 1: JUXTAGLOMERULAR (GRANULAR) CELLS", S("c1h", fontSize=9.5, leading=13, textColor=WHITE, fontName="Helvetica-Bold"))]], colWidths=[W])
c1_hdr.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),NAVY),("LEFTPADDING",(0,0),(-1,-1),10),("TOPPADDING",(0,0),(-1,-1),6),("BOTTOMPADDING",(0,0),(-1,-1),6)]))
c1_pts = [
"Modified <b>smooth muscle cells</b> in the <b>media of the afferent arteriole</b> near the glomerulus.",
"Contain cytoplasmic <b>secretory granules</b> storing <b>renin</b> (an aspartyl protease).",
"Also called <b>epithelioid cells / granular cells</b>; nuclei are <b>spherical</b>.",
"Densely innervated by <b>sympathetic (β₁ adrenergic) nerve terminals</b>.",
"Connected to adjacent cells by <b>gap junctions</b>.",
"Under volume depletion / renal artery stenosis, extra smooth muscle cells "
"<b>transform into granular cells</b> to increase renin output.",
]
c1_rows = [[Paragraph(f"• {p}", sBullet)] for p in c1_pts]
c1_body = Table(c1_rows, colWidths=[W])
c1_body.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),LGREY),("LEFTPADDING",(0,0),(-1,-1),12),("TOPPADDING",(0,0),(-1,-1),3),("BOTTOMPADDING",(0,0),(-1,-1),3)]))
c1_fn = Table([[Paragraph("<b>Function:</b> SYNTHESIZE, STORE & RELEASE RENIN → Activates RAAS → Controls BP", S("fn1", fontSize=9, leading=12, textColor=WHITE, fontName="Helvetica-Bold"))]], colWidths=[W])
c1_fn.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),colors.HexColor("#1a5276")),("LEFTPADDING",(0,0),(-1,-1),10),("TOPPADDING",(0,0),(-1,-1),5),("BOTTOMPADDING",(0,0),(-1,-1),5)]))
story.append(KeepTogether([c1_hdr, c1_body, c1_fn, sp(6)]))
# Component 2 — Macula Densa
c2_hdr = Table([[Paragraph("Component 2: MACULA DENSA", S("c2h", fontSize=9.5, leading=13, textColor=WHITE, fontName="Helvetica-Bold"))]], colWidths=[W])
c2_hdr.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),TEAL),("LEFTPADDING",(0,0),(-1,-1),10),("TOPPADDING",(0,0),(-1,-1),6),("BOTTOMPADDING",(0,0),(-1,-1),6)]))
c2_pts = [
"Specialised plaque of <b>tall, narrow epithelial cells</b> in the wall of the "
"<b>thick ascending limb of Henle / early DCT</b>.",
"Cells have <b>large, crowded nuclei</b> — hence the name 'macula densa' (dense spot).",
"Contain a <b>Golgi apparatus</b> directed toward the arterioles (secretory function).",
"Rich in <b>neuronal nitric oxide synthase (nNOS)</b> and <b>cyclooxygenase-2 (COX-2)</b>.",
"Sense luminal <b>NaCl concentration</b> via the <b>Na⁺/K⁺/2Cl⁻ co-transporter (NKCC2)</b>.",
"Cells joined by <b>tight junctions</b> with low permeability; lateral intercellular spaces "
"vary with functional state.",
]
c2_rows = [[Paragraph(f"• {p}", sBullet)] for p in c2_pts]
c2_body = Table(c2_rows, colWidths=[W])
c2_body.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),LGREY),("LEFTPADDING",(0,0),(-1,-1),12),("TOPPADDING",(0,0),(-1,-1),3),("BOTTOMPADDING",(0,0),(-1,-1),3)]))
c2_fn = Table([[Paragraph("<b>Function:</b> CHEMORECEPTOR — Senses NaCl in filtrate → Signals granular cells → Regulates renin & GFR", S("fn2", fontSize=9, leading=12, textColor=WHITE, fontName="Helvetica-Bold"))]], colWidths=[W])
c2_fn.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),colors.HexColor("#1a5276")),("LEFTPADDING",(0,0),(-1,-1),10),("TOPPADDING",(0,0),(-1,-1),5),("BOTTOMPADDING",(0,0),(-1,-1),5)]))
story.append(KeepTogether([c2_hdr, c2_body, c2_fn, sp(6)]))
# Component 3 — Lacis Cells
c3_hdr = Table([[Paragraph("Component 3: EXTRAGLOMERULAR MESANGIAL CELLS (Lacis cells / Polkissen cells)", S("c3h", fontSize=9.5, leading=13, textColor=WHITE, fontName="Helvetica-Bold"))]], colWidths=[W])
c3_hdr.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),colors.HexColor("#2e4057")),("LEFTPADDING",(0,0),(-1,-1),10),("TOPPADDING",(0,0),(-1,-1),6),("BOTTOMPADDING",(0,0),(-1,-1),6)]))
c3_pts = [
"Located in the <b>angle between the afferent and efferent arterioles</b> at the glomerular hilum.",
"Also called <b>Lacis cells</b> (Goormaghtigh cells / Polkissen / juxtaglomerular interstitial cells).",
"Heavily branched cells interconnected by <b>gap junctions</b> with prominent microfilament bundles.",
"Connected to Bowman's capsule basement membrane and walls of both arterioles.",
"Act as a <b>structural and functional bridge</b> between macula densa and granular cells.",
"Contain some renin (significance unclear); may facilitate intercellular signal transmission.",
]
c3_rows = [[Paragraph(f"• {p}", sBullet)] for p in c3_pts]
c3_body = Table(c3_rows, colWidths=[W])
c3_body.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),LGREY),("LEFTPADDING",(0,0),(-1,-1),12),("TOPPADDING",(0,0),(-1,-1),3),("BOTTOMPADDING",(0,0),(-1,-1),3)]))
c3_fn = Table([[Paragraph("<b>Function:</b> INTERCELLULAR COMMUNICATION — bridges macula densa signals to granular cells", S("fn3", fontSize=9, leading=12, textColor=WHITE, fontName="Helvetica-Bold"))]], colWidths=[W])
c3_fn.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),colors.HexColor("#1a5276")),("LEFTPADDING",(0,0),(-1,-1),10),("TOPPADDING",(0,0),(-1,-1),5),("BOTTOMPADDING",(0,0),(-1,-1),5)]))
story.append(KeepTogether([c3_hdr, c3_body, c3_fn, sp(8)]))
# ── 4. FUNCTIONS ───────────────────────────────────────────────────────────────
story.append(secbox("4. FUNCTIONS OF THE JGA", bg=colors.HexColor("#1a5276")))
story.append(sp(5))
story.append(subsec("A. Renin Secretion → RAAS Activation (Controls Blood Pressure)"))
story.append(body(
"Granular cells release <b>renin</b> by exocytosis — the major source of systemic "
"angiotensin II, controlling extracellular volume and blood pressure:"
))
story.append(sp(3))
raas = [
[Paragraph("<b>Step</b>", sTH), Paragraph("<b>Event</b>", sTH), Paragraph("<b>Site</b>", sTH)],
[Paragraph("1", sTD), Paragraph("JG cells release <b>Renin</b>", sTD), Paragraph("Kidney", sTD)],
[Paragraph("2", sTD), Paragraph("Renin cleaves Angiotensinogen → <b>Angiotensin I</b> (decapeptide)", sTD), Paragraph("Blood/Liver", sTD)],
[Paragraph("3", sTD), Paragraph("ACE converts Ang I → <b>Angiotensin II</b> (octapeptide)", sTD), Paragraph("Lungs", sTD)],
[Paragraph("4", sTD), Paragraph("Ang II → vasoconstriction + stimulates <b>Aldosterone</b>", sTD), Paragraph("Adrenal cortex", sTD)],
[Paragraph("5", sTD), Paragraph("Aldosterone → ↑ Na⁺ reabsorption, ↑ K⁺ excretion → ↑ ECF → ↑ BP", sTD), Paragraph("Kidney DCT/CD", sTD)],
]
raas_t = Table(raas, colWidths=[W*0.08, W*0.62, W*0.30])
raas_t.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,0),NAVY),("ROWBACKGROUNDS",(0,1),(-1,-1),[LGREY,WHITE,LGREY,WHITE,LGREY]),
("GRID",(0,0),(-1,-1),0.4,MGREY),("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4),
("LEFTPADDING",(0,0),(-1,-1),6),("RIGHTPADDING",(0,0),(-1,-1),6),
("VALIGN",(0,0),(-1,-1),"MIDDLE"),("ALIGN",(0,0),(0,-1),"CENTER"),
]))
story.append(raas_t); story.append(sp(6))
story.append(subsec("B. Tubuloglomerular Feedback (TGF) — Autoregulation of GFR"))
story.append(body("Links NaCl concentration at macula densa to arteriolar resistance, maintaining constant GFR (autoregulation range: <b>80–180 mmHg</b>):"))
story.append(sp(3))
tgf = [
[Paragraph("<b>Stimulus</b>", sTH), Paragraph("<b>Signal</b>", sTH), Paragraph("<b>Arteriole Effect</b>", sTH), Paragraph("<b>Net GFR</b>", sTH)],
[Paragraph("↑ GFR (↑ NaCl at MD)", sTD),
Paragraph("NKCC2 activated → ATP → Adenosine", sTD),
Paragraph("Afferent arteriole <b>CONSTRICTS</b> → ↓ P_gc", sTD),
Paragraph("<font color='#c0392b'><b>↓ GFR</b></font> (normalises)", sTD)],
[Paragraph("↓ GFR (↓ NaCl at MD)", sTD),
Paragraph("Renin↑; NO & PGE₂ → vasodilate", sTD),
Paragraph("Afferent <b>DILATES</b>; Ang II → efferent constricts", sTD),
Paragraph("<font color='#1a6e3c'><b>↑ GFR</b></font> (normalises)", sTD)],
]
tgf_t = Table(tgf, colWidths=[W*0.20, W*0.30, W*0.32, W*0.18])
tgf_t.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,0),TEAL),
("BACKGROUND",(0,1),(-1,1),colors.HexColor("#fdecea")),
("BACKGROUND",(0,2),(-1,2),colors.HexColor("#eaf7ea")),
("GRID",(0,0),(-1,-1),0.4,MGREY),("TOPPADDING",(0,0),(-1,-1),5),("BOTTOMPADDING",(0,0),(-1,-1),5),
("LEFTPADDING",(0,0),(-1,-1),6),("RIGHTPADDING",(0,0),(-1,-1),6),("VALIGN",(0,0),(-1,-1),"MIDDLE"),
]))
story.append(tgf_t); story.append(sp(6))
story.append(subsec("C. Other Functions"))
for b in [
"<b>Erythropoietin secretion</b> — stimulates RBC production from bone marrow.",
"<b>Myogenic autoregulation</b> — afferent arteriole smooth muscle reflexively contracts on stretch → maintains constant glomerular pressure.",
"<b>Regulates sodium & water balance</b> — through RAAS and direct tubular effects.",
]:
story.append(bullet(b))
story.append(sp(8))
# ── 5. REGULATION OF RENIN SECRETION ──────────────────────────────────────────
story.append(secbox("5. REGULATION OF RENIN SECRETION", bg=DKRED))
story.append(sp(5))
ren = [
[Paragraph("<b>STIMULATES Renin ↑</b>", S("rh1", fontSize=9, leading=12, textColor=WHITE, fontName="Helvetica-Bold")),
Paragraph("<b>INHIBITS Renin ↓</b>", S("rh2", fontSize=9, leading=12, textColor=WHITE, fontName="Helvetica-Bold"))],
[Paragraph("↓ Afferent arteriolar pressure (baroreceptor mechanism)", sTD), Paragraph("↑ Afferent arteriolar pressure / stretch", sTD)],
[Paragraph("↓ NaCl delivery to macula densa (↓ tubular flow)", sTD), Paragraph("↑ NaCl at macula densa", sTD)],
[Paragraph("↑ Sympathetic activity (β₁ receptors on JG cells)", sTD), Paragraph("Angiotensin II (negative feedback)", sTD)],
[Paragraph("↑ Circulating catecholamines (adrenaline)", sTD), Paragraph("Vasopressin (ADH)", sTD)],
[Paragraph("Prostaglandins (PGE₂, PGI₂)", sTD), Paragraph("↑ ECF volume / hypervolaemia", sTD)],
[Paragraph("Nitric Oxide (NO)", sTD), Paragraph("NSAIDs (block PGE₂ → reduce renin)", sTD)],
]
ren_t = Table(ren, colWidths=[W*0.50, W*0.50])
ren_t.setStyle(TableStyle([
("BACKGROUND",(0,0),(0,0),colors.HexColor("#1a6e3c")),("BACKGROUND",(1,0),(1,0),DKRED),
("ROWBACKGROUNDS",(0,1),(-1,-1),[LGREY,WHITE,LGREY,WHITE,LGREY,WHITE]),
("GRID",(0,0),(-1,-1),0.4,MGREY),("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4),
("LEFTPADDING",(0,0),(-1,-1),7),("RIGHTPADDING",(0,0),(-1,-1),7),("VALIGN",(0,0),(-1,-1),"MIDDLE"),
]))
story.append(ren_t); story.append(sp(10))
# QUICK RECALL BOX
recall = Table([[Paragraph(
"<b>QUICK RECALL ★</b><br/><br/>"
"<b>3 Components:</b> (1) JG / Granular cells [afferent arteriole wall — release RENIN] "
"· (2) Macula Densa [thick ascending limb / DCT — senses NaCl] "
"· (3) Lacis cells [junction — signal bridge]<br/><br/>"
"<b>2 Main Functions:</b><br/>"
" ① Renin release → RAAS → Ang II → Aldosterone → ↑ Na⁺ reabsorption → ↑ BP<br/>"
" ② TGF → GFR autoregulation (80–180 mmHg range)<br/><br/>"
"<b>Renin stimulated by:</b> ↓ BP, ↓ NaCl, ↑ sympathetics, PGE₂, NO<br/>"
"<b>Renin inhibited by:</b> ↑ BP, ↑ NaCl, Ang II, ADH, NSAIDs",
sRecall
)]], colWidths=[W])
recall.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1),colors.HexColor("#fef9e7")),
("BOX",(0,0),(-1,-1),1.5,GOLD),
("TOPPADDING",(0,0),(-1,-1),12),("BOTTOMPADDING",(0,0),(-1,-1),12),
("LEFTPADDING",(0,0),(-1,-1),14),("RIGHTPADDING",(0,0),(-1,-1),14),
]))
story.append(recall); story.append(sp(12))
story.append(HRFlowable(width="100%", thickness=0.8, color=MGREY, spaceAfter=4, spaceBefore=4))
story.append(Paragraph(
"Sources: Comprehensive Clinical Nephrology 7th Ed. · Ganong's Review of Medical Physiology 26th Ed. · "
"Guyton & Hall Medical Physiology · Histology — Text & Atlas (Eroschenko) · NKF Primer on Kidney Diseases 8th Ed.",
sFooter
))
doc.build(story)
print(f"PDF saved → {OUTPUT}")
cd /tmp/workspace/jga-exam && python3 generate_jga_pdf.py 2>&1
JGA 5 Marker Exam Answer
PDF Document · PDF
| Component | Location | Key Feature |
|---|---|---|
| JG (Granular) cells | Media of afferent arteriole | Contain renin granules — modified smooth muscle |
| Macula densa | Thick ascending limb / early DCT | Tall narrow cells with crowded nuclei — sense NaCl via NKCC2 |
| Lacis cells (Extraglomerular mesangial / Polkissen) | Junction of arterioles | Signal bridge — gap junctions to both other components |