~/nephrotic-notes/build_notes.py
from docx import Document
from docx.shared import Pt, Inches, RGBColor, Cm
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.table import WD_TABLE_ALIGNMENT, WD_ALIGN_VERTICAL
from docx.oxml.ns import qn
from docx.oxml import OxmlElement
import copy
doc = Document()
# ── Page margins (narrow to fit more content per page) ──────────────────────
from docx.shared import Cm
section = doc.sections[0]
section.page_width = Inches(8.27) # A4
section.page_height = Inches(11.69)
section.left_margin = Cm(1.8)
section.right_margin = Cm(1.8)
section.top_margin = Cm(1.5)
section.bottom_margin = Cm(1.5)
# ── Styles ───────────────────────────────────────────────────────────────────
normal_style = doc.styles["Normal"]
normal_style.font.name = "Calibri"
normal_style.font.size = Pt(9)
def set_heading_style(paragraph, text, level=1, color=None):
paragraph.text = text
run = paragraph.runs[0]
run.font.name = "Calibri"
if level == 0: # Document title
run.font.size = Pt(16)
run.font.bold = True
run.font.color.rgb = RGBColor(0xFF, 0xFF, 0xFF)
elif level == 1:
run.font.size = Pt(12)
run.font.bold = True
run.font.color.rgb = RGBColor(0xFF, 0xFF, 0xFF)
elif level == 2:
run.font.size = Pt(10)
run.font.bold = True
run.font.color.rgb = RGBColor(0x1F, 0x3864, 0x96)
elif level == 3:
run.font.size = Pt(9)
run.font.bold = True
run.font.color.rgb = RGBColor(0x2E, 0x74, 0xB5)
def shade_paragraph(paragraph, fill_hex):
"""Apply shading to a paragraph (for section headers)."""
pPr = paragraph._p.get_or_add_pPr()
shd = OxmlElement('w:shd')
shd.set(qn('w:val'), 'clear')
shd.set(qn('w:color'), 'auto')
shd.set(qn('w:fill'), fill_hex)
pPr.append(shd)
def shade_cell(cell, fill_hex):
tc = cell._tc
tcPr = tc.get_or_add_tcPr()
shd = OxmlElement('w:shd')
shd.set(qn('w:val'), 'clear')
shd.set(qn('w:color'), 'auto')
shd.set(qn('w:fill'), fill_hex)
tcPr.append(shd)
def add_section_header(doc, text, bg='1F3864'):
p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
shade_paragraph(p, bg)
run = p.add_run(f' {text} ')
run.font.name = 'Calibri'
run.font.size = Pt(11)
run.font.bold = True
run.font.color.rgb = RGBColor(0xFF, 0xFF, 0xFF)
p.paragraph_format.space_before = Pt(4)
p.paragraph_format.space_after = Pt(2)
return p
def add_sub_header(doc, text):
p = doc.add_paragraph()
run = p.add_run(text)
run.font.name = 'Calibri'
run.font.size = Pt(10)
run.font.bold = True
run.font.color.rgb = RGBColor(0x1F, 0x38, 0x64)
p.paragraph_format.space_before = Pt(4)
p.paragraph_format.space_after = Pt(1)
return p
def add_body(doc, text, bold_label=None):
p = doc.add_paragraph()
p.paragraph_format.space_before = Pt(1)
p.paragraph_format.space_after = Pt(1)
p.paragraph_format.left_indent = Cm(0.3)
if bold_label:
r1 = p.add_run(bold_label + ' ')
r1.font.bold = True
r1.font.name = 'Calibri'
r1.font.size = Pt(9)
r2 = p.add_run(text)
r2.font.name = 'Calibri'
r2.font.size = Pt(9)
return p
def add_bullet(doc, text, bold_label=None):
p = doc.add_paragraph(style='List Bullet')
p.paragraph_format.space_before = Pt(0)
p.paragraph_format.space_after = Pt(0)
p.paragraph_format.left_indent = Cm(0.5)
if bold_label:
r1 = p.add_run(bold_label + ' ')
r1.font.bold = True
r1.font.name = 'Calibri'
r1.font.size = Pt(9)
r2 = p.add_run(text)
r2.font.name = 'Calibri'
r2.font.size = Pt(9)
return p
def add_table(doc, headers, rows, col_widths=None, header_fill='2E74B5'):
table = doc.add_table(rows=1, cols=len(headers))
table.style = 'Table Grid'
table.alignment = WD_TABLE_ALIGNMENT.CENTER
# Header row
hdr_cells = table.rows[0].cells
for i, h in enumerate(headers):
shade_cell(hdr_cells[i], header_fill)
p = hdr_cells[i].paragraphs[0]
run = p.add_run(h)
run.font.bold = True
run.font.name = 'Calibri'
run.font.size = Pt(8.5)
run.font.color.rgb = RGBColor(0xFF, 0xFF, 0xFF)
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
# Data rows
for ri, row_data in enumerate(rows):
row_cells = table.add_row().cells
fill = 'DEEAF1' if ri % 2 == 0 else 'FFFFFF'
for ci, val in enumerate(row_data):
shade_cell(row_cells[ci], fill)
p = row_cells[ci].paragraphs[0]
if isinstance(val, tuple): # (text, bold)
run = p.add_run(val[0])
run.font.bold = val[1]
else:
run = p.add_run(str(val))
run.font.name = 'Calibri'
run.font.size = Pt(8.5)
# Column widths
if col_widths:
for i, w in enumerate(col_widths):
for row in table.rows:
row.cells[i].width = Cm(w)
doc.add_paragraph().paragraph_format.space_after = Pt(2)
return table
def page_break(doc):
doc.add_page_break()
# ════════════════════════════════════════════════════════════════════════════
# COVER / TITLE BLOCK
# ════════════════════════════════════════════════════════════════════════════
# Big title bar
p_title = doc.add_paragraph()
shade_paragraph(p_title, '1F3864')
p_title.alignment = WD_ALIGN_PARAGRAPH.CENTER
r = p_title.add_run(' CLINICAL CASE NOTES ')
r.font.name = 'Calibri'; r.font.size = Pt(18); r.font.bold = True
r.font.color.rgb = RGBColor(0xFF, 0xFF, 0xFF)
p_sub = doc.add_paragraph()
shade_paragraph(p_sub, '2E74B5')
p_sub.alignment = WD_ALIGN_PARAGRAPH.CENTER
r2 = p_sub.add_run(' NEPHROTIC SYNDROME ')
r2.font.name = 'Calibri'; r2.font.size = Pt(14); r2.font.bold = True
r2.font.color.rgb = RGBColor(0xFF, 0xFF, 0xFF)
doc.add_paragraph().paragraph_format.space_after = Pt(2)
# ────────────────────────────────────────────────────────────────────────────
# PAGE 1: IDENTIFICATION + DIAGNOSIS + CHIEF COMPLAINT + HPI
# ────────────────────────────────────────────────────────────────────────────
add_section_header(doc, 'PAGE 1 — IDENTIFICATION DATA, DIAGNOSIS & CHIEF COMPLAINT')
# Identification table
add_sub_header(doc, '1. Identification Data')
id_headers = ['Field', 'Details']
id_rows = [
('Name', 'Mr. James O. (anonymized)'),
('Age / DOB', '35 years / July 10, 1991'),
('Sex', 'Male'),
('Marital Status', 'Married'),
('Occupation', 'Office Administrator'),
('Religion / Nationality', 'Christian / Nigerian'),
('Address', '14 Lagos Street, Ikeja, Lagos'),
('Date of Admission', 'July 15, 2026'),
('Ward / Unit', 'Nephrology Ward'),
('Informant', 'Patient (reliable historian)'),
]
add_table(doc, id_headers, id_rows, col_widths=[4.5, 10.5])
# Diagnosis
add_sub_header(doc, '2. Diagnosis')
add_body(doc, 'Nephrotic Syndrome (primary/idiopathic — pending renal biopsy confirmation)', bold_label='Primary Diagnosis:')
add_body(doc, '')
add_body(doc, 'Differential Diagnoses:', bold_label='')
diff_dx = [
('Minimal Change Disease (MCD)', '— most common in children; 5-10% of adult idiopathic NS'),
('Focal Segmental Glomerulosclerosis (FSGS)', '— most common primary cause in adults (esp. Black patients)'),
('Membranous Nephropathy', '— most common primary cause in White adults (30%)'),
('Membranoproliferative GN (MPGN)', '— mixed nephrotic/nephritic features'),
('Secondary causes', '— DM nephropathy, SLE, amyloidosis, drugs (NSAIDs, heroin), infections (HBV, HCV, HIV, malaria)'),
]
for dx, detail in diff_dx:
add_bullet(doc, detail, bold_label=dx)
# Chief Complaint
add_sub_header(doc, '3. Chief Complaint')
cc_items = [
'Progressive bilateral leg swelling — 3 weeks',
'Periorbital (facial) puffiness on waking — 3 weeks',
'Foamy / frothy urine — 2 weeks',
'Generalised fatigue and weakness — 2 weeks',
'Abdominal distension — 1 week',
]
for item in cc_items:
add_bullet(doc, item)
page_break(doc)
# ────────────────────────────────────────────────────────────────────────────
# PAGE 2: HISTORY OF PRESENT ILLNESS + PAST HISTORY
# ────────────────────────────────────────────────────────────────────────────
add_section_header(doc, 'PAGE 2 — HISTORY OF PRESENT ILLNESS & PAST HISTORIES')
add_sub_header(doc, '4. History of Present Illness (HPI)')
hpi_text = (
'Mr. James O., a 35-year-old male, was in his usual state of health until ~3 weeks '
'prior to admission when he noticed progressive swelling of both lower limbs starting '
'from the ankles and extending upwards. He also noted periorbital puffiness most '
'prominent on waking in the morning. Two weeks ago, he began noticing foamy/frothy urine. '
'He reports a 5 kg weight gain over this period.\n'
'One week ago, abdominal distension commenced. He now has exertional dyspnoea (likely '
'pleural effusion). No haematuria, no burning on urination, no reduced urine output.\n'
'No preceding sore throat, skin rash, joint pains, recent infections, NSAID or illicit '
'drug use, bee sting, fever or rigors.'
)
p = doc.add_paragraph()
p.paragraph_format.left_indent = Cm(0.3)
p.paragraph_format.space_before = Pt(1)
p.paragraph_format.space_after = Pt(2)
run = p.add_run(hpi_text)
run.font.name = 'Calibri'; run.font.size = Pt(9)
add_sub_header(doc, 'Relevant Positives vs Negatives')
pn_headers = ['Relevant POSITIVES', 'Relevant NEGATIVES']
pn_rows = [
('Progressive pitting bilateral pedal oedema', 'No haematuria / dysuria'),
('Periorbital puffiness (worse on waking)', 'No rash, joint pains, fever'),
('Foamy urine (heavy proteinuria indicator)', 'No recent NSAID / drug use'),
('5 kg weight gain in 3 weeks', 'No prior similar episodes'),
('Abdominal distension (ascites)', 'No family history of renal disease'),
('Exertional dyspnoea (pleural effusion)', 'No preceding throat/skin infection'),
]
add_table(doc, pn_headers, pn_rows, col_widths=[7.5, 7.5])
# Past Medical
add_sub_header(doc, '5. Past Medical History (PMH)')
pmh_headers = ['Condition', 'Details']
pmh_rows = [
('Diabetes Mellitus', 'None (FBG and HbA1c normal)'),
('Hypertension', 'None (first presentation with elevated BP)'),
('Renal Disease', 'No prior kidney disease'),
('Malaria', 'Repeated childhood episodes, all treated'),
('Hepatitis B / C', 'Screening pending — result: negative'),
('HIV', 'Screening pending — result: negative'),
('SLE / Autoimmune', 'None (ANA negative)'),
('Tuberculosis', 'None'),
('Allergies', 'No known drug or food allergies'),
]
add_table(doc, pmh_headers, pmh_rows, col_widths=[5, 10])
# Past Surgical
add_sub_header(doc, '6. Past Surgical History (PSH)')
add_bullet(doc, 'No prior surgeries, invasive procedures, or biopsies')
add_bullet(doc, 'No prior blood transfusions')
# Present Surgical
add_sub_header(doc, '7. Present Surgical History')
add_bullet(doc, 'Renal biopsy — planned / performed on Day 5 of admission')
add_body(doc, 'Required in all adult nephrotic patients to identify the specific glomerular lesion '
'(MCD, FSGS, membranous nephropathy, MPGN) and guide treatment. Specimen sent for '
'light microscopy, immunofluorescence, and electron microscopy.')
# Personal History
add_sub_header(doc, '8. Personal History')
ph_headers = ['Field', 'Details']
ph_rows = [
('Smoking', 'Non-smoker'),
('Alcohol', 'Social (occasional)'),
('Illicit drugs', 'Denies — heroin specifically relevant (can cause FSGS)'),
('Diet', 'Mixed; admits high salt intake'),
('Occupation / Exposure', 'Office work; no nephrotoxin exposure'),
('Exercise', 'Sedentary'),
('Sexual history', 'Monogamous, married'),
('Travel history', 'No recent international travel'),
]
add_table(doc, ph_headers, ph_rows, col_widths=[4.5, 10.5])
page_break(doc)
# ────────────────────────────────────────────────────────────────────────────
# PAGE 3: FAMILY HISTORY + CLINICAL JOURNAL + PHYSICAL EXAM
# ────────────────────────────────────────────────────────────────────────────
add_section_header(doc, 'PAGE 3 — FAMILY HISTORY, CLINICAL JOURNAL & PHYSICAL EXAMINATION')
# Family History
add_sub_header(doc, '9. Family History')
fh_headers = ['Relation', 'Condition']
fh_rows = [
('Father', 'Hypertension; deceased age 65 (stroke)'),
('Mother', 'Alive and well; no known kidney disease'),
('Siblings ×2', 'No kidney disease'),
('Children ×1', 'Healthy'),
('Extended family', 'No known SLE, DM, autoimmune, or NS'),
]
add_table(doc, fh_headers, fh_rows, col_widths=[4.5, 10.5])
add_body(doc, 'Note: FSGS has genetic forms (NPHS2, APOL1 variants) — especially relevant in patients of African descent.')
# Clinical Journal
add_sub_header(doc, '10. Clinical Journal / Progress Notes')
journal_headers = ['Day', 'Date', 'Clinical Events']
journal_rows = [
('Day 1', '15 Jul 2026', 'Admission. Full assessment. Urine dipstick: 3+ protein. Bloods sent (FBC, U&E, albumin, lipids, ANA, complement, HBV/HCV/HIV). 24-hr urine protein started. Fluid balance chart commenced.'),
('Day 2', '16 Jul 2026', 'Results: Serum albumin 18 g/L; 24-hr urine protein 6.8 g/day; cholesterol 8.2 mmol/L. Nephrotic syndrome confirmed. Na restriction, furosemide 40 mg OD + enalapril 5 mg OD started.'),
('Day 3', '17 Jul 2026', 'Renal biopsy scheduled. INR checked (1.1 — normal). Renal ultrasound: kidneys normal size, normal echogenicity, no obstruction.'),
('Day 5', '19 Jul 2026', 'Renal biopsy performed under USS guidance. Post-procedure monitoring uneventful. Specimen for LM/IF/EM sent.'),
('Day 7', '21 Jul 2026', 'Biopsy result awaited. Oedema mildly improved with diuresis. Daily weight chart maintained. Lipid profile confirmed hyperlipidaemia — atorvastatin commenced.'),
]
add_table(doc, journal_headers, journal_rows, col_widths=[1.5, 2.5, 11])
# Physical Exam
add_sub_header(doc, '11. Physical Examination')
# Gen appearance + Antho
add_body(doc, 'Alert, conscious, oriented x3. Appears puffy (periorbital), mildly pale. No jaundice, no lymphadenopathy. Weight 87 kg (+5 kg in 3 wks), Height 175 cm, BMI 28.4 kg/m².',
bold_label='General:')
add_body(doc, 'Bilateral periorbital puffiness; mucous membranes mildly pale; no oral ulcers; JVP mildly elevated; no goitre.',
bold_label='Head & Neck:')
add_body(doc, 'S1 S2 present, no murmurs, no S3/S4. Pulse 88 bpm, regular.',
bold_label='CVS:')
add_body(doc, 'RR 18/min. Reduced air entry right base (pleural effusion). No wheeze. SpO2 97% room air.',
bold_label='Respiratory:')
add_body(doc, 'Distended abdomen. Shifting dullness +ve (ascites). Fluid thrill borderline. No hepatosplenomegaly. No renal angle tenderness. BS present and normal.',
bold_label='Abdomen:')
add_body(doc, 'Bilateral pitting oedema 3+, extending to mid-thigh. Warm peripheries. CRT <2 sec. No clubbing.',
bold_label='Extremities:')
add_body(doc, 'No rash, no purpura, no butterfly rash, no vasculitis signs.',
bold_label='Skin:')
add_body(doc, 'GCS 15/15. No focal deficit.',
bold_label='Neuro:')
page_break(doc)
# ────────────────────────────────────────────────────────────────────────────
# PAGE 4: VITAL SIGNS + INVESTIGATIONS (URINE + BLOOD)
# ────────────────────────────────────────────────────────────────────────────
add_section_header(doc, 'PAGE 4 — VITAL SIGNS & DATA / INVESTIGATIONS CHART')
add_sub_header(doc, '12. Vital Signs')
vs_headers = ['Parameter', 'Value', 'Normal Range', 'Status']
vs_rows = [
('Temperature', '37.1°C', '36.1 - 37.2°C', 'Normal'),
('Blood Pressure', '148/92 mmHg', '<120/80 mmHg', '⚠ ELEVATED'),
('Heart Rate', '88 bpm', '60 - 100 bpm', 'Normal'),
('Respiratory Rate', '18 /min', '12 - 20 /min', 'Normal'),
('SpO2', '97%', '>95%', 'Normal'),
('Weight', '87 kg', 'Baseline + 5 kg', '⚠ Fluid overload'),
('Urine Output', '800 mL/24h', '>0.5 mL/kg/hr (~900)', '⚠ Slightly reduced'),
]
add_table(doc, vs_headers, vs_rows, col_widths=[4, 3.5, 4, 3.5])
add_sub_header(doc, '13a. Urine Investigations')
ur_headers = ['Test', 'Result', 'Normal', 'Interpretation']
ur_rows = [
('Urine dipstick — Protein', '3+', 'Negative', 'Heavy proteinuria'),
('Urine dipstick — Blood', 'Trace', 'Negative', 'Microhaematuria'),
('Urine dipstick — Glucose', 'Negative', 'Negative', 'Normal'),
('24-hr urine protein', '6.8 g/day', '<150 mg/day', 'NEPHROTIC RANGE (>3.5 g/day)'),
('Urine Protein:Creatinine ratio', '0.68', '<0.02', 'Markedly elevated'),
('Urine microscopy', 'Oval fat bodies, fatty casts', 'No casts', 'Lipiduria (hallmark NS)'),
]
add_table(doc, ur_headers, ur_rows, col_widths=[4.5, 3, 3, 4.5])
add_sub_header(doc, '13b. Serum / Blood Investigations')
bl_headers = ['Test', 'Result', 'Normal Range', 'Interpretation']
bl_rows = [
('Serum Albumin', '18 g/L', '35 - 50 g/L', 'HYPOALBUMINAEMIA'),
('Total Protein', '45 g/L', '60 - 80 g/L', 'Low'),
('Serum Sodium', '132 mmol/L', '135 - 145', 'Hyponatraemia'),
('Serum Potassium', '4.0 mmol/L', '3.5 - 5.0', 'Normal'),
('Serum Creatinine', '115 µmol/L', '62 - 106', 'Mildly elevated'),
('Blood Urea', '9.2 mmol/L', '2.5 - 6.4', 'Slightly elevated'),
('eGFR', '62 mL/min/1.73m²', '>60', 'Mildly reduced'),
('Total Cholesterol', '8.2 mmol/L', '<5.2', 'HYPERCHOLESTEROLAEMIA'),
('LDL Cholesterol', '5.1 mmol/L', '<3.0', 'Elevated'),
('HDL Cholesterol', '0.9 mmol/L', '>1.0', 'Low'),
('Triglycerides', '3.8 mmol/L', '<1.7', 'Elevated'),
('Fasting Blood Glucose', '4.9 mmol/L', '3.9 - 5.6', 'Normal (excludes DM)'),
('HbA1c', '5.2%', '<5.7%', 'Normal'),
('ANA', 'Negative', 'Negative', 'Excludes SLE'),
('C3 Complement', '1.1 g/L', '0.9 - 1.8', 'Normal'),
('C4 Complement', '0.22 g/L', '0.1 - 0.4', 'Normal'),
('Hepatitis B sAg', 'Negative', 'Negative', 'Normal'),
('Hepatitis C Ab', 'Negative', 'Negative', 'Normal'),
('HIV 1/2 Ab', 'Negative', 'Negative', 'Normal'),
('ANCA', 'Negative', 'Negative', 'Normal'),
('Anti-GBM Ab', 'Negative', 'Negative', 'Normal'),
('Haemoglobin', '11.8 g/dL', '13.5 - 17.5', 'Mild anaemia'),
('WBC', '7.2 ×10⁹/L', '4 - 11', 'Normal'),
('Platelets', '290 ×10⁹/L', '150 - 400', 'Normal'),
('PT/INR', '1.1', '0.8 - 1.2', 'Normal'),
('Fibrinogen', '5.8 g/L', '2 - 4 g/L', 'Elevated (hypercoagulable)'),
('Antithrombin III', 'Low', 'Normal', 'Urinary loss — thrombosis risk'),
]
add_table(doc, bl_headers, bl_rows, col_widths=[4.5, 2.5, 3.5, 4.5])
page_break(doc)
# ────────────────────────────────────────────────────────────────────────────
# PAGE 5: IMAGING + BIOPSY + MEDICATION CHART
# ────────────────────────────────────────────────────────────────────────────
add_section_header(doc, 'PAGE 5 — IMAGING, BIOPSY & MEDICATION CHART')
add_sub_header(doc, '13c. Imaging Studies')
img_headers = ['Investigation', 'Findings']
img_rows = [
('Renal Ultrasound', 'Both kidneys normal size (L: 11.2 cm, R: 11.0 cm), normal echogenicity, no hydronephrosis, no calculi'),
('Chest X-Ray (PA)', 'Small right-sided pleural effusion; no cardiomegaly; lung fields otherwise clear'),
('Abdominal Ultrasound', 'Free fluid (ascites) in peritoneal cavity; no hepatosplenomegaly; no masses'),
('Renal Doppler USS', 'Pending — to be done if renal vein thrombosis clinically suspected'),
]
add_table(doc, img_headers, img_rows, col_widths=[5, 10])
add_sub_header(doc, '13d. Renal Biopsy (Histopathology)')
bx_headers = ['Modality', 'Finding', 'Purpose']
bx_rows = [
('Light Microscopy', 'Result pending', 'Glomerular structure — proliferation, sclerosis, thickening'),
('Immunofluorescence', 'Result pending', 'Immune deposits — IgG, IgM, IgA, C3, C1q pattern'),
('Electron Microscopy', 'Result pending', 'Podocyte foot process effacement (MCD), subepithelial/subendothelial deposits'),
]
add_table(doc, bx_headers, bx_rows, col_widths=[4, 4, 7])
add_body(doc, 'Adult nephrotic patients require biopsy as the specific lesion cannot be determined clinically. '
'The biopsy identifies the diagnosis, determines prognosis, and directly guides immunosuppressive therapy selection. '
'(Goldman-Cecil Medicine, Brenner & Rector\'s The Kidney)')
# Medication Chart
add_sub_header(doc, '14. Medication Chart')
med_headers = ['Drug', 'Dose', 'Route', 'Frequency', 'Indication']
med_rows = [
('Furosemide', '40 mg', 'PO', 'Once daily (AM)', 'Oedema — loop diuretic'),
('Spironolactone', '25 mg', 'PO', 'Once daily', 'Adjunct diuretic; aldosterone antagonist'),
('Enalapril (ACE-I)', '5 mg', 'PO', 'Once daily', 'Antiproteinuric; reduces proteinuria, improves albumin'),
('Atorvastatin', '20 mg', 'PO', 'Once daily (night)', 'Hyperlipidaemia; HMG-CoA reductase inhibitor'),
('Prednisolone', '1 mg/kg/day', 'PO', 'Once daily', 'Pending biopsy — empirical if MCD / steroid-responsive NS confirmed'),
('Warfarin', 'INR-guided', 'PO', 'Daily', 'Anticoagulation if DVT/RVT/PE complication occurs'),
('Calcium + Vit D', '500 mg + 400 IU', 'PO', 'Once daily', 'Bone protection during steroid therapy'),
('Penicillin V', '250 mg', 'PO', 'Twice daily', 'Prophylaxis — risk of Streptococcal/Pneumococcal infection due to IgG loss'),
]
add_table(doc, med_headers, med_rows, col_widths=[3.5, 2, 1.5, 2.5, 5.5])
add_sub_header(doc, 'Non-Pharmacological Measures')
np_items = [
'Dietary sodium restriction: <2 g (88 mmol) per day',
'Fluid restriction: 1.5 L/day (until oedema resolves)',
'Daily weight monitoring (fluid balance)',
'Strict input/output fluid balance chart',
'Bed rest during acute phase; graduated mobilisation to reduce DVT risk',
'Dietary protein: 0.8 - 1.0 g/kg/day (avoid excess — worsens proteinuria)',
]
for item in np_items:
add_bullet(doc, item)
add_sub_header(doc, 'Monitoring Parameters')
mon_items = [
'BP twice daily',
'Serum electrolytes every 48h (diuretic monitoring)',
'Serum albumin and urine protein:creatinine ratio — weekly',
'INR if anticoagulation commenced',
'Serum creatinine and urine output daily',
'Daily weight and strict fluid balance',
'Blood glucose (if on steroids)',
]
for item in mon_items:
add_bullet(doc, item)
page_break(doc)
# ────────────────────────────────────────────────────────────────────────────
# PAGE 6: PATHOPHYSIOLOGY + COMPLICATIONS + SUMMARY
# ────────────────────────────────────────────────────────────────────────────
add_section_header(doc, 'PAGE 6 — PATHOPHYSIOLOGY, COMPLICATIONS & CLINICAL SUMMARY')
add_sub_header(doc, '15. Pathophysiology of Nephrotic Syndrome')
patho_text = (
'Nephrotic syndrome results from structural or physicochemical injury to the glomerular '
'capillary wall (endothelium + GBM + podocytes), increasing permeability to plasma proteins. '
'This triggers a cascade of secondary metabolic derangements:'
)
p = doc.add_paragraph()
p.paragraph_format.left_indent = Cm(0.3)
p.paragraph_format.space_after = Pt(2)
run = p.add_run(patho_text)
run.font.name = 'Calibri'; run.font.size = Pt(9)
path_steps = [
('1. Massive proteinuria (>3.5 g/day)', '— Primary lesion. Loss of albumin + immunoglobulins + coagulation proteins in urine.'),
('2. Hypoalbuminaemia (albumin <30 g/L)', '— Urinary loss exceeds hepatic synthetic capacity. Renal tubular catabolism also contributes.'),
('3. Generalised oedema', '— Reduced oncotic pressure → fluid shifts from intravascular to interstitium. Compensatory RAAS activation + aldosterone → Na/water retention → worsens oedema.'),
('4. Hyperlipidaemia', '— Reduced oncotic pressure upregulates hepatic lipoprotein synthesis. Decreased lipid catabolism. Raised: cholesterol, TG, VLDL, LDL, Lp(a). Reduced: HDL.'),
('5. Lipiduria', '— Lipoproteins leak across damaged glomerulus. Appear in urine as oval fat bodies and fatty casts.'),
('6. Hypercoagulable state', '— Urinary loss of antithrombin III, protein C, protein S. Increased hepatic synthesis of fibrinogen and clotting factors V, VII. Platelet aggregability increases.'),
('7. Susceptibility to infection', '— Urinary loss of IgG, complement factors. Risk of pneumococcal and staphylococcal infections.'),
]
for step, detail in path_steps:
add_bullet(doc, detail, bold_label=step)
add_sub_header(doc, '16. Causes of Nephrotic Syndrome by Prevalence')
cause_headers = ['Cause', 'Children (%)', 'Adults (%)']
cause_rows = [
('PRIMARY GLOMERULAR DISEASES', '', ''),
('Minimal Change Disease (MCD)', '75', '5-10'),
('Focal Segmental Glomerulosclerosis (FSGS)', '10', '35'),
('Membranous Nephropathy', '3', '30'),
('MPGN / Dense deposit disease', '10', '10'),
('Other proliferative GN (IgA, mesangial)', '2', '17'),
('SYSTEMIC / SECONDARY CAUSES', '', ''),
('Diabetes mellitus', 'Rare', 'Most common secondary'),
('SLE (Lupus nephritis)', 'Uncommon', 'Common'),
('Amyloidosis', 'Rare', 'Important adult cause'),
('Drugs (NSAIDs, heroin, gold, penicillamine)', 'Rare', 'Recognised cause'),
('Infections (HBV, HCV, HIV, malaria, syphilis)', 'Less common', 'Recognised cause'),
('Malignancy (carcinoma, lymphoma)', 'Rare', 'Especially elderly'),
]
add_table(doc, cause_headers, cause_rows, col_widths=[9, 2.5, 3.5])
add_sub_header(doc, '17. Complications to Monitor')
comp_headers = ['Complication', 'Mechanism', 'Monitoring / Action']
comp_rows = [
('Deep vein thrombosis / PE', 'Loss of antithrombin III, protein C, S; increased fibrinogen', 'Doppler USS limbs; D-dimer; anticoagulate if confirmed'),
('Renal vein thrombosis (10-50%)', 'Hypercoagulable state', 'Renal Doppler; haematuria; flank pain'),
('Bacterial infections', 'Loss of IgG + complement in urine', 'Temp chart; prophylactic penicillin; pneumococcal vaccine'),
('Pleural effusion / Ascites', 'Hypoalbuminaemia (low oncotic pressure)', 'CXR; USS abdomen; paracentesis if symptomatic'),
('Accelerated atherosclerosis', 'Persistent hyperlipidaemia + hypercoagulability', 'Statin therapy; cardiovascular risk monitoring'),
('Acute kidney injury (AKI)', 'Volume depletion from aggressive diuresis', 'Serum Cr; urine output; adjust diuretic dose'),
('Steroid complications', 'Long-term corticosteroid therapy', 'BP, glucose, bone density, weight — monitor closely'),
]
add_table(doc, comp_headers, comp_rows, col_widths=[4, 5, 6])
# Summary box
add_sub_header(doc, '18. Diagnostic Criteria Summary')
dc_headers = ['Criterion', 'Threshold', 'This Patient']
dc_rows = [
('Proteinuria', '>3.5 g/day (adult)', '6.8 g/day — MET'),
('Hypoalbuminaemia', 'Albumin <30 g/L', '18 g/L — MET'),
('Generalised oedema', 'Clinical', 'Bilateral oedema + ascites + periorbital — MET'),
('Hyperlipidaemia', 'Elevated cholesterol/TG', 'Total cholesterol 8.2 mmol/L — MET'),
('Lipiduria', 'Oval fat bodies in urine', 'Present — MET'),
]
add_table(doc, dc_headers, dc_rows, col_widths=[5, 4.5, 5.5])
# Footer note
p_footer = doc.add_paragraph()
p_footer.paragraph_format.space_before = Pt(6)
shade_paragraph(p_footer, 'DEEAF1')
r_footer = p_footer.add_run(
' Sources: Brenner & Rector\'s The Kidney | Robbins Pathologic Basis of Disease | '
'Goldman-Cecil Medicine | Tintinalli\'s Emergency Medicine | '
'Comprehensive Clinical Nephrology 7th Ed | Washington Manual of Medical Therapeutics '
)
r_footer.font.name = 'Calibri'
r_footer.font.size = Pt(7.5)
r_footer.font.italic = True
r_footer.font.color.rgb = RGBColor(0x1F, 0x38, 0x64)
# ── Save ─────────────────────────────────────────────────────────────────────
output_path = '/tmp/workspace/nephrotic-notes/Nephrotic_Syndrome_Clinical_Notes.docx'
doc.save(output_path)
print(f'Saved: {output_path}')