Make notes on systemic amyloidosis from standard dermatology textbooks
| Type | Amyloid Protein | Cause |
|---|---|---|
| Primary (AL) | Immunoglobulin light chains (lambda > kappa) | Plasma cell dyscrasia / multiple myeloma |
| Secondary (AA) | Serum amyloid A protein | Chronic infection / inflammation |
| Dialysis-related | Beta-2 microglobulin | Long-term hemodialysis |
| Senile systemic (ATTRwt) | Wild-type transthyretin | Age-related (>70 years) |
| Familial ATTR | Mutant transthyretin | Hereditary TTR gene mutations |
| ALect2 | Leukocyte chemotactic factor 2 | Sporadic |


| Stain | Result |
|---|---|
| Congo red | Positive - salmon pink/orange color |
| Congo red under polarized light | Apple-green birefringence (pathognomonic) |
| PAS | Weakly positive, diastase resistant |
| Crystal violet | Purple (metachromasia) |
| Thioflavin T | Positive (fluorescence) |
| Cotton dyes (Dylon, Pagoda red, etc.) | Intense bright orange |

| Skin Lesion Type | Differential Diagnoses |
|---|---|
| Waxy papules of AL amyloidosis | Papular mucinosis, nodular amyloidosis, lipoid proteinosis, adnexal tumors (face) |
| Sclerodermoid infiltration | Systemic sclerosis, scleromyxedema, pretibial myxedema |
| Nail dystrophy | Late ungual lichen planus |
| Feature | AL (Primary) | AA (Secondary) | ATTRwt (Senile) |
|---|---|---|---|
| Protein | Ig light chains (lambda) | Serum amyloid A | Wild-type transthyretin |
| Cause | Plasma cell dyscrasia | Chronic infection/inflammation | Aging |
| Age | Middle-aged adults | Any age | >70 years |
| Skin involvement | Yes (25-40%) | Clinically absent | Absent |
| Key skin sign | Pinch purpura, macroglossia, waxy papules | None (perivascular deposits only) | None |
| Key organ | Heart, kidney, nerve | Kidney, liver, spleen | Heart |
| KMnO4 test | Birefringence retained | Birefringence lost | - |
| Prognosis | Poor (median 13 months untreated) | Depends on underlying disease | Slowly progressive |
Make this into a downloadable pdf notes
ls /home/daytona/workspace/ 2>/dev/null && python3 -c "import weasyprint; print('weasyprint ok')" 2>/dev/null || echo "weasyprint not found"
python3 -c "from reportlab.lib.pagesizes import A4; print('reportlab ok')" 2>/dev/null && python3 -c "import markdown; print('markdown ok')" 2>/dev/null; which pandoc 2>/dev/null && pandoc --version | head -1
which xelatex pdflatex 2>/dev/null; python3 -c "import markdown2; print('markdown2 ok')" 2>/dev/null; python3 -c "from xhtml2pdf import pisa; print('xhtml2pdf ok')" 2>/dev/null
python3 -c "from xhtml2pdf import pisa; print('xhtml2pdf ok')" 2>&1; python3 -c "import markdown; print('markdown ok')" 2>&1
mkdir -p /home/daytona/workspace/amyloidosis-notes && echo "dir created"
~/amyloidosis-notes/generate_pdf.py
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm, mm
from reportlab.lib import colors
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether, PageBreak
)
from reportlab.platypus import ListFlowable, ListItem
from reportlab.lib.colors import HexColor
import urllib.request
import os
import tempfile
# Color palette
NAVY = HexColor('#1a2e4a')
TEAL = HexColor('#2e7d8a')
LIGHT_TEAL = HexColor('#e8f4f6')
AMBER = HexColor('#d4820a')
LIGHT_AMBER = HexColor('#fef3e2')
LIGHT_GREY = HexColor('#f5f5f5')
BORDER_GREY = HexColor('#cccccc')
TEXT_DARK = HexColor('#1a1a1a')
TEXT_MID = HexColor('#444444')
WHITE = colors.white
OUTPUT_PATH = '/home/daytona/workspace/amyloidosis-notes/Systemic_Amyloidosis_Dermatology_Notes.pdf'
doc = SimpleDocTemplate(
OUTPUT_PATH,
pagesize=A4,
rightMargin=2*cm,
leftMargin=2*cm,
topMargin=2*cm,
bottomMargin=2*cm,
title='Systemic Amyloidosis - Dermatology Notes',
author='Orris Medical Library',
)
styles = getSampleStyleSheet()
# Custom styles
h1 = ParagraphStyle('H1', parent=styles['Normal'],
fontSize=20, fontName='Helvetica-Bold', textColor=WHITE,
spaceAfter=0, spaceBefore=0, leading=26)
h2 = ParagraphStyle('H2', parent=styles['Normal'],
fontSize=13, fontName='Helvetica-Bold', textColor=WHITE,
spaceAfter=4, spaceBefore=0, leading=17)
h3 = ParagraphStyle('H3', parent=styles['Normal'],
fontSize=11, fontName='Helvetica-Bold', textColor=NAVY,
spaceAfter=4, spaceBefore=8, leading=15)
h4 = ParagraphStyle('H4', parent=styles['Normal'],
fontSize=10, fontName='Helvetica-Bold', textColor=TEAL,
spaceAfter=3, spaceBefore=6, leading=13)
body = ParagraphStyle('Body', parent=styles['Normal'],
fontSize=9.5, fontName='Helvetica', textColor=TEXT_DARK,
spaceAfter=4, spaceBefore=2, leading=14, alignment=TA_JUSTIFY)
bullet = ParagraphStyle('Bullet', parent=styles['Normal'],
fontSize=9.5, fontName='Helvetica', textColor=TEXT_DARK,
spaceAfter=2, spaceBefore=1, leading=13, leftIndent=14,
bulletIndent=4)
sub_bullet = ParagraphStyle('SubBullet', parent=styles['Normal'],
fontSize=9, fontName='Helvetica', textColor=TEXT_MID,
spaceAfter=2, spaceBefore=0, leading=12, leftIndent=28,
bulletIndent=18)
highlight = ParagraphStyle('Highlight', parent=styles['Normal'],
fontSize=9.5, fontName='Helvetica-Bold', textColor=AMBER,
spaceAfter=3, spaceBefore=3, leading=13, leftIndent=10)
caption = ParagraphStyle('Caption', parent=styles['Normal'],
fontSize=8, fontName='Helvetica-Oblique', textColor=TEXT_MID,
spaceAfter=6, spaceBefore=2, leading=11, alignment=TA_CENTER)
source_style = ParagraphStyle('Source', parent=styles['Normal'],
fontSize=8, fontName='Helvetica-Oblique', textColor=TEXT_MID,
spaceAfter=2, spaceBefore=1, leading=11)
def section_header(text, level=2):
"""Creates a colored section header."""
bg = NAVY if level == 2 else TEAL
pad = 8 if level == 2 else 6
style = h2 if level == 2 else ParagraphStyle('H2b', parent=h2,
fontSize=11, fontName='Helvetica-Bold', textColor=WHITE, leading=15)
data = [[Paragraph(text, style)]]
tbl = Table(data, colWidths=[17*cm])
tbl.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,-1), bg),
('TOPPADDING', (0,0), (-1,-1), pad),
('BOTTOMPADDING', (0,0), (-1,-1), pad),
('LEFTPADDING', (0,0), (-1,-1), 10),
('RIGHTPADDING', (0,0), (-1,-1), 10),
('ROUNDEDCORNERS', (0,0), (-1,-1), 3),
]))
return tbl
def callout_box(text, color=LIGHT_TEAL, border=TEAL):
"""Creates a highlighted callout box."""
data = [[Paragraph(text, ParagraphStyle('cb', parent=body, fontSize=9.5,
fontName='Helvetica-Bold', textColor=TEXT_DARK, leading=14))]]
tbl = Table(data, colWidths=[17*cm])
tbl.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,-1), color),
('TOPPADDING', (0,0), (-1,-1), 7),
('BOTTOMPADDING', (0,0), (-1,-1), 7),
('LEFTPADDING', (0,0), (-1,-1), 10),
('RIGHTPADDING', (0,0), (-1,-1), 10),
('LINEBEFORETABLE', (0,0), (0,0), 3, border),
('LINEBEFORE', (0,0), (0,-1), 4, border),
('BOX', (0,0), (-1,-1), 0.5, border),
]))
return tbl
def info_table(data_rows, col_widths, header_row=True):
"""Creates a styled table."""
tbl = Table(data_rows, colWidths=col_widths, repeatRows=1 if header_row else 0)
style = [
('FONTNAME', (0,0), (-1,-1), 'Helvetica'),
('FONTSIZE', (0,0), (-1,-1), 8.5),
('TOPPADDING', (0,0), (-1,-1), 5),
('BOTTOMPADDING', (0,0), (-1,-1), 5),
('LEFTPADDING', (0,0), (-1,-1), 7),
('RIGHTPADDING', (0,0), (-1,-1), 7),
('ROWBACKGROUNDS', (0,1), (-1,-1), [WHITE, LIGHT_GREY]),
('GRID', (0,0), (-1,-1), 0.4, BORDER_GREY),
('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
('ALIGN', (0,0), (-1,-1), 'LEFT'),
]
if header_row:
style += [
('BACKGROUND', (0,0), (-1,0), NAVY),
('TEXTCOLOR', (0,0), (-1,0), WHITE),
('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
('FONTSIZE', (0,0), (-1,0), 9),
]
tbl.setStyle(TableStyle(style))
return tbl
def b(text):
return f'<b>{text}</b>'
def i(text):
return f'<i>{text}</i>'
def red(text):
return f'<font color="#c0392b"><b>{text}</b></font>'
def teal_text(text):
return f'<font color="#2e7d8a"><b>{text}</b></font>'
# ─── Download images ──────────────────────────────────────────────────────────
img_dir = '/home/daytona/workspace/amyloidosis-notes/imgs'
os.makedirs(img_dir, exist_ok=True)
image_urls = {
'periorbital.png': 'https://cdn.orris.care/cdss_images/84c3a421c70dc06838d48aa20a3db9151ecedd5402f4975207d67fc2b530cbaf.png',
'macroglossia.png': 'https://cdn.orris.care/cdss_images/8dd78eaa027e0e19fa5e22304378b5452609c9bb40b9fd4be7aa276521153985.png',
'flowchart.png': 'https://cdn.orris.care/cdss_images/cc024dfbf33594637c4695c0e7c0b7e8836802b6cf1d5645f7a48a2e07a4a39a.png',
'nails.png': 'https://cdn.orris.care/cdss_images/dc2d9dd50f12b235a3aac6b3c85d2b5198d8004ef36b5484e02eb90aa38b3f45.png',
}
downloaded = {}
for name, url in image_urls.items():
path = os.path.join(img_dir, name)
try:
urllib.request.urlretrieve(url, path)
downloaded[name] = path
print(f"Downloaded {name}")
except Exception as e:
print(f"Failed {name}: {e}")
from reportlab.platypus import Image as RLImage
def inline_image(key, width=7*cm, caption_text=''):
items = []
if key in downloaded:
img = RLImage(downloaded[key], width=width)
items.append(img)
if caption_text:
items.append(Paragraph(caption_text, caption))
return items
# ─── Build Story ──────────────────────────────────────────────────────────────
story = []
# ── Cover / Title block ──────────────────────────────────────────────────────
title_data = [[Paragraph('SYSTEMIC AMYLOIDOSIS', ParagraphStyle('Title',
parent=styles['Normal'], fontSize=24, fontName='Helvetica-Bold',
textColor=WHITE, leading=30, alignment=TA_CENTER)),
],[Paragraph('Dermatology Notes | Andrews • Bologna • Fitzpatrick\'s', ParagraphStyle('Sub',
parent=styles['Normal'], fontSize=11, fontName='Helvetica',
textColor=HexColor('#b0d4dc'), leading=16, alignment=TA_CENTER))
]]
title_tbl = Table([[row] for row in [title_data[0][0], title_data[1][0]]],
colWidths=[17*cm])
title_tbl.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,-1), NAVY),
('TOPPADDING', (0,0), (-1,-1), 16),
('BOTTOMPADDING', (0,0), (-1,-1), 16),
('LEFTPADDING', (0,0), (-1,-1), 14),
('RIGHTPADDING', (0,0), (-1,-1), 14),
]))
story.append(title_tbl)
story.append(Spacer(1, 0.4*cm))
# ── Section 1: Definition ────────────────────────────────────────────────────
story.append(section_header('1. DEFINITION AND BASIC CONCEPTS'))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph(
'Amyloid is a material deposited in the skin and other organs that is '
f'{b("eosinophilic, homogeneous, and hyaline")} in appearance. It consists of proteins '
f'arranged in a {b("beta-pleated sheet")} configuration processed by host cells. '
'Over 30 proteins have been associated with amyloidosis.',
body))
story.append(Spacer(1, 0.15*cm))
story.append(Paragraph(b('Three components of all amyloid deposits:'), h4))
for item in [
'Protein-derived amyloid fibers (differ among subtypes)',
'Amyloid P component (~15% of total amyloid)',
'Ground substance',
]:
story.append(Paragraph(f'• {item}', bullet))
story.append(Spacer(1, 0.15*cm))
story.append(Paragraph(
'Excess host protein is metabolized into amyloid precursors that interact with '
'tissue proteoglycans/glycosaminoglycans, forming soluble oligomers. These complex with '
f'{b("serum amyloid P (SAP)")} to form amyloid deposits in affected organs.',
body))
story.append(Spacer(1, 0.3*cm))
# ── Section 2: Classification ────────────────────────────────────────────────
story.append(section_header('2. CLASSIFICATION OF SYSTEMIC AMYLOIDOSIS'))
story.append(Spacer(1, 0.2*cm))
class_data = [
[b('Type'), b('Amyloid Protein'), b('Cause / Association')],
['Primary (AL)', 'Ig light chains (lambda > kappa)', 'Plasma cell dyscrasia / multiple myeloma'],
['Secondary (AA)', 'Serum amyloid A (SAA)', 'Chronic infection / inflammation'],
['Dialysis-related', 'Beta-2 microglobulin', 'Long-term hemodialysis'],
['Senile systemic (ATTRwt)', 'Wild-type transthyretin', 'Aging (>70 years)'],
['Familial ATTR', 'Mutant transthyretin', 'Hereditary TTR gene mutations'],
['ALect2', 'Leukocyte chemotactic factor 2', 'Sporadic; kidney/liver involvement'],
]
class_rows = []
for row in class_data:
class_rows.append([Paragraph(cell, ParagraphStyle('tc', parent=body, fontSize=8.5, leading=12)) for cell in row])
story.append(info_table(class_rows, [4.5*cm, 5.5*cm, 7*cm]))
story.append(Spacer(1, 0.3*cm))
# ── Section 3: AL Amyloidosis ─────────────────────────────────────────────────
story.append(section_header('3. PRIMARY SYSTEMIC AMYLOIDOSIS (AL AMYLOIDOSIS)'))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph('Pathogenesis', h3))
for item in [
f'Extracellular deposition of fibrils from {b("monoclonal immunoglobulin light chains")}, usually {b("lambda (λ) subtype")} (75-80% of cases)',
'Produced by a small plasma cell clone (usually not fulfilling full myeloma criteria)',
f'Amino acid substitutions in variable region of Ig light chain destabilize chains',
f'Germline Ig light-chain V chains {b("6aVλVI")} and {b("3rVλIII")} responsible in 40% of patients',
]:
story.append(Paragraph(f'• {item}', bullet))
story.append(Paragraph('Associated Malignancy', h3))
for item in [
f'{b("Multiple myeloma")} is the most common associated malignancy (~20% of AL amyloidosis patients)',
'~15% of AL amyloidosis will have myeloma; ~15% of myeloma patients will have AL amyloidosis',
'NHL, MALT lymphoma, lymphoplasmacytic lymphoma are rare associations',
'Secondary AA amyloidosis: hepatocellular carcinoma, renal cell carcinoma, Castleman disease, Hodgkin disease',
]:
story.append(Paragraph(f'• {item}', bullet))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph('Cutaneous Manifestations (25-40% of patients)', h3))
story.append(Paragraph(teal_text('A. Waxy Papules and Plaques'), h4))
for item in [
'Shiny, smooth, firm, flat-topped or spherical papules of waxy/translucent color',
'Coalesce to form nodules and plaques',
'Distribution: periorbital, perinasal, perioral, mucocutaneous junctions, anogenital',
'Smooth skin-colored papules on face, neck, scalp',
'Follicular plugging resulting in milia; vulvar lesions may resemble giant condylomata',
'Waxy infiltration of palms and volar aspect of fingertips',
]:
story.append(Paragraph(f'• {item}', bullet))
# Images side by side
if 'periorbital.png' in downloaded and 'macroglossia.png' in downloaded:
img1 = RLImage(downloaded['periorbital.png'], width=7.5*cm)
img2 = RLImage(downloaded['macroglossia.png'], width=6.5*cm)
img_tbl = Table(
[[img1, img2],
[Paragraph('Periorbital waxy papules and hemorrhagic lesions in AL amyloidosis (Andrews Fig. 26.1)', caption),
Paragraph('Macroglossia with amyloid nodules on tongue surface (Andrews Fig. 26.2)', caption)]],
colWidths=[8.5*cm, 8.5*cm]
)
img_tbl.setStyle(TableStyle([
('ALIGN', (0,0), (-1,-1), 'CENTER'),
('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
('TOPPADDING', (0,0), (-1,-1), 4),
('BOTTOMPADDING', (0,0), (-1,-1), 2),
]))
story.append(img_tbl)
story.append(Spacer(1, 0.15*cm))
story.append(Paragraph(teal_text('B. Purpura (Most Common Cutaneous Manifestation, ~15%)'), h4))
story.append(callout_box(
'★ "Pinch purpura" and "Raccoon eyes" (periorbital purpura) are classic signs of AL amyloidosis',
LIGHT_AMBER, AMBER))
story.append(Spacer(1, 0.15*cm))
story.append(Paragraph(b('Mechanisms of purpura:'), ParagraphStyle('bold9', parent=body, fontName='Helvetica-Bold')))
for item in [
'Amyloid infiltration of blood vessel walls causing fragility',
'AL amyloid binding to Factor X, inhibiting its function',
'Amyloid infiltration of the liver reducing fibrinogen and Factor X production',
]:
story.append(Paragraph(f' ○ {item}', sub_bullet))
story.append(Paragraph(b('Precipitants:'), ParagraphStyle('bold9', parent=body, fontName='Helvetica-Bold')))
for item in [
'Coughing, Valsalva maneuver, proctoscopy, removal of adhesive tape',
'Friction / pinching of skin (pinch purpura) - can be reproduced by rubbing a dull instrument',
'Distribution: eyelids, neck, axillae, anogenital region',
]:
story.append(Paragraph(f' ○ {item}', sub_bullet))
story.append(Paragraph(teal_text('C. Macroglossia (≥20% of patients)'), h4))
for item in [
'Greatly enlarged tongue with furrow development; lateral indentations from teeth',
'Hemorrhagic papules or nodules on tongue surface',
'May be an early symptom; can lead to dysphagia',
]:
story.append(Paragraph(f'• {item}', bullet))
story.append(callout_box(
'★ Macroglossia + carpal tunnel syndrome = classic presentation → always investigate for amyloidosis',
LIGHT_AMBER, AMBER))
story.append(Paragraph(teal_text('D. Other Skin Findings'), h4))
skin_other = [
f'{b("Bullous amyloidosis")} - tense hemorrhagic or clear noninflammatory bullae at trauma sites (hands, forearms, feet); heal with scarring and milia; resembles porphyria cutanea tarda or epidermolysis bullosa acquisita',
f'{b("Nail dystrophy")} - atrophy of nail plate, longitudinal ridging, partial anonychia, splitting, crumbling; resembles lichen planus; amyloid deposits around blood vessels in nail bed dermis',
f'{b("Shoulder pad sign")} - prominent deltoid muscles from amyloid deposition in muscles',
f'{b("Sclerodermoid / cutis laxa-like")} appearance (generalized or acral)',
f'{b("Amyloid elastosis")} - amyloid coating elastic fibers; lesions in flexors/lateral neck may resemble pseudoxanthoma elasticum (PXE)',
f'{b("Cutis verticis gyrata-like")} scalp thickening with associated alopecia',
'Cordlike thickening along blood vessels; bilateral stenosis of external auditory canals (rare)',
'Increased risk for skin cancer',
]
for item in skin_other:
story.append(Paragraph(f'• {item}', bullet))
# Nail image
if 'nails.png' in downloaded:
story.append(Spacer(1, 0.1*cm))
nail_img = RLImage(downloaded['nails.png'], width=6*cm)
nail_tbl = Table([[nail_img], [Paragraph('Severely dystrophic nails in systemic amyloidosis (Fitzpatrick\'s Fig. 91-62)', caption)]], colWidths=[17*cm])
nail_tbl.setStyle(TableStyle([('ALIGN', (0,0), (-1,-1), 'CENTER')]))
story.append(nail_tbl)
story.append(Paragraph('Systemic Manifestations', h3))
sys_mani = [
f'{b("Carpal tunnel syndrome")} (classic)',
f'{b("Peripheral neuropathy")} - bilateral, symmetrical, sensory',
f'{b("Autonomic neuropathy")} - postural hypotension, impotence, gastroparesis',
f'{b("Arthropathy")} - RA-like, affecting small joints',
f'{b("Renal")} - nephrotic syndrome (proteinuria, hypoalbuminemia, edema)',
f'{b("Cardiac")} - restrictive cardiomyopathy with preserved EF; right-sided CHF; arrhythmias',
f'{b("Hepatomegaly")} (amyloid infiltration or CHF)',
f'{b("GI bleeding")}; orthostatic hypotension; dyspnea',
f'{b("Elevated cardiac troponins")} - powerful prognostic markers; elevated troponins associated with 6-month survival',
]
for item in sys_mani:
story.append(Paragraph(f'• {item}', bullet))
story.append(Paragraph('Prognosis', h3))
story.append(callout_box(
'Without therapy: median survival ~12-13 months | Neurologic presentation = better prognosis vs. cardiac presentation',
LIGHT_TEAL, TEAL))
story.append(Spacer(1, 0.3*cm))
# ── Section 4: AA Amyloidosis ─────────────────────────────────────────────────
story.append(section_header('4. SECONDARY SYSTEMIC AMYLOIDOSIS (AA AMYLOIDOSIS)'))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph('Pathogenesis', h3))
for item in [
f'Precursor protein: {b("serum amyloid A (SAA)")}, an acute-phase reactant synthesized by the liver',
'Chronic elevation of SAA → converted to AA amyloid protein in affected tissues',
f'Treatment target: maintaining SAA {b("<4 mg/L")} is associated with good outcome',
]:
story.append(Paragraph(f'• {item}', bullet))
story.append(Paragraph('Causes', h3))
cause_data = [
[b('Category'), b('Examples')],
['Infectious (now less common)', 'TB, lepromatous leprosy, osteomyelitis, schistosomiasis, bronchiectasis, pyelonephritis'],
['Inflammatory / Autoimmune', 'RA, JIA, ankylosing spondylitis, adult Still disease, IBD, Behçet disease'],
['Dermatologic triggers', 'Hidradenitis suppurativa, stasis ulcers, psoriatic arthritis, dystrophic EB, pustular psoriasis, systemic sclerosis, dermatomyositis, SLE'],
['Hereditary / Autoinflammatory', 'Familial Mediterranean fever, CAPS, TRAPS, Muckle-Wells syndrome, alkaptonuria'],
['Malignancy-associated', 'HCC, RCC, Castleman disease, Hodgkin disease, adult hairy cell leukemia'],
]
cause_rows = [[Paragraph(cell, ParagraphStyle('tc', parent=body, fontSize=8.5, leading=12)) for cell in row] for row in cause_data]
story.append(info_table(cause_rows, [5*cm, 12*cm]))
story.append(Spacer(1, 0.15*cm))
story.append(Paragraph('Skin Involvement', h3))
story.append(callout_box(
'Skin is NOT clinically involved in AA amyloidosis. However, amyloid can be detected perivascularly in the dermis on biopsy, and within subcutaneous fat aspirates.',
LIGHT_TEAL, TEAL))
story.append(Paragraph('Organ involvement: kidneys, adrenals, liver, spleen, heart', body))
story.append(Spacer(1, 0.3*cm))
# ── Section 5: Other Systemic Types ──────────────────────────────────────────
story.append(section_header('5. OTHER SYSTEMIC AMYLOIDOSIS TYPES'))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph('Dialysis-Associated (Beta-2 Microglobulin) Amyloidosis', h3))
for item in [
'Long-term hemodialysis - beta-2 microglobulin accumulates (not cleared by dialysis membranes)',
'Primarily affects musculoskeletal system: carpal tunnel syndrome, bone cysts, arthropathy',
]:
story.append(Paragraph(f'• {item}', bullet))
story.append(Paragraph('Senile Systemic (ATTRwt) Amyloidosis', h3))
for item in [
f'Caused by deposition of {b("normal (wild-type) transthyretin")} - a transport protein for thyroxine and retinol-binding protein (produced in liver, choroid plexus, eye)',
f'Affects patients {b(">70 years")}; increasingly recognized cause of cardiac disease',
f'{b("Skin lesions are absent")}, but vascular deposition has caused tongue necrosis',
f'{b("Carpal tunnel syndrome")} can occur',
f'Diagnosis in ~75% by {b("deep abdominal fat biopsy")}; cardiac pyrophosphate scan positive',
]:
story.append(Paragraph(f'• {item}', bullet))
story.append(Paragraph('Familial (Hereditary) ATTR Amyloidosis', h3))
for item in [
f'Caused by {b("mutations in the transthyretin (TTR) gene")}; mutations alter protein stability',
f'{b("Familial amyloid polyneuropathy")} (TTR mutations)',
f'{b("Familial amyloid cardiomyopathy/ATTR-CM")} (TTR mutations)',
'Increased risk of non-Hodgkin lymphoma has been described',
]:
story.append(Paragraph(f'• {item}', bullet))
story.append(Spacer(1, 0.3*cm))
# ── Section 6: Histopathology ─────────────────────────────────────────────────
story.append(section_header('6. HISTOPATHOLOGY'))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph('General Features', h3))
for item in [
'Eosinophilic, homogeneous, hyaline material on H&E',
f'Ultrastructure: straight, nonbranching, nonanastomosing filaments {b("60-100 nm in diameter")}',
'Three components: protein-derived fibers + amyloid P component + ground substance',
]:
story.append(Paragraph(f'• {item}', bullet))
story.append(Paragraph('Staining Characteristics', h3))
stain_data = [
[b('Stain'), b('Result'), b('Notes')],
['Congo red', 'Salmon pink / orange', 'Standard diagnostic stain'],
['Congo red + polarized light', 'Apple-green birefringence', red('PATHOGNOMONIC - most important')],
['PAS', 'Weakly positive', 'Diastase resistant'],
['Crystal violet', 'Purple (metachromasia)', ''],
['Thioflavin T', 'Positive (fluorescence)', 'Sensitive screening stain'],
['Cotton dyes (Dylon, Pagoda red)', 'Intense bright orange', ''],
]
stain_rows = [[Paragraph(cell, ParagraphStyle('tc', parent=body, fontSize=8.5, leading=12)) for cell in row] for row in stain_data]
story.append(info_table(stain_rows, [4*cm, 5.5*cm, 7.5*cm]))
story.append(Spacer(1, 0.15*cm))
story.append(callout_box(
'★ KMnO4 (potassium permanganate) test: AA amyloid LOSES Congo red birefringence after KMnO4 treatment. '
'AL (primary) and localized cutaneous amyloid RETAIN birefringence.',
LIGHT_AMBER, AMBER))
story.append(Spacer(1, 0.15*cm))
story.append(Paragraph('Histologic Pattern in AL vs. Cutaneous Amyloidosis', h3))
pattern_data = [
[b('Feature'), b('AL Systemic Amyloidosis'), b('Primary Cutaneous Amyloidosis')],
['Amyloid location', 'Dermis, subcutis, around blood vessel walls, sweat glands', 'Dermal papillae only (no perivascular)'],
['Perivascular deposits', 'YES (key distinguishing feature)', 'Absent'],
['IHC staining', 'Anti-Ig light chain antibodies', 'Anti-keratin (keratin 5) positive'],
['Amyloid P', 'Present (in all forms)', 'Present (in all forms)'],
['DIF', 'May show Ig deposition around vessels', 'IgM in globular pattern (passive absorption)'],
]
pattern_rows = [[Paragraph(cell, ParagraphStyle('tc', parent=body, fontSize=8.5, leading=12)) for cell in row] for row in pattern_data]
story.append(info_table(pattern_rows, [4*cm, 6.5*cm, 6.5*cm]))
story.append(Spacer(1, 0.3*cm))
# ── Section 7: Diagnosis ──────────────────────────────────────────────────────
story.append(section_header('7. DIAGNOSIS'))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph('Biopsy Sites', h3))
biopsy_data = [
['• Abdominal subcutaneous fat aspirate', 'Positive in 80-90% of AL amyloidosis; preferred (avoids bleeding risk)'],
['• Rectal mucosal biopsy', 'Highly sensitive; risk of bleeding'],
['• Gingival / tongue biopsy', 'Useful when clinically involved; less sensitive if not involved'],
['• Bone marrow biopsy', 'Examines for amyloid deposits; determines plasma cell percentage'],
['• Skin biopsy of lesions', 'Direct; useful when specific lesions present'],
]
biopsy_tbl = Table(biopsy_data, colWidths=[7*cm, 10*cm])
biopsy_tbl.setStyle(TableStyle([
('FONTNAME', (0,0), (-1,-1), 'Helvetica'),
('FONTSIZE', (0,0), (-1,-1), 8.5),
('TOPPADDING', (0,0), (-1,-1), 4),
('BOTTOMPADDING', (0,0), (-1,-1), 4),
('LEFTPADDING', (0,0), (-1,-1), 6),
('ROWBACKGROUNDS', (0,0), (-1,-1), [WHITE, LIGHT_GREY]),
('GRID', (0,0), (-1,-1), 0.4, BORDER_GREY),
('FONTNAME', (0,0), (0,-1), 'Helvetica-Bold'),
]))
story.append(biopsy_tbl)
story.append(Paragraph('Laboratory Work-Up (AL Amyloidosis)', h3))
for item in [
f'{b("Serum protein electrophoresis (SPEP) and immunofixation")} - detects monoclonal protein',
f'{b("Serum free light chain assay")} - detects excess K or λ light chain in ~10% not detectable on SPEP/urine',
f'{b("24-hour urine protein electrophoresis and immunofixation")}',
'~90% will have Ig fragment in serum/urine; remaining 10% detected by free light chains',
f'{b("Cardiac troponins and NT-proBNP")} - cardiac involvement assessment and prognosis',
f'Reduction of urine free light chains by {b(">50%")} = substantial benefit from treatment',
]:
story.append(Paragraph(f'• {item}', bullet))
story.append(Paragraph('Imaging and Organ Assessment', h3))
for item in [
'Echocardiogram and cardiac MRI (restrictive cardiomyopathy)',
'Nerve conduction studies (neuropathy)',
f'{b("Cardiac pyrophosphate scan")} - positive in ATTR amyloidosis (not AL)',
f'{b("SAP scintigraphy")} (radio-iodine labeled SAP) - sensitive, non-invasive; primarily used outside the US',
'Renal function tests, LFTs, BUN, creatinine',
]:
story.append(Paragraph(f'• {item}', bullet))
story.append(callout_box(
'★ Mass spectrometry is the preferred method for amyloid typing - critical to distinguish AL from '
'wild-type ATTR and ALect2, especially in elderly patients with coincidental monoclonal gammopathy.',
LIGHT_AMBER, AMBER))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph('Diagnostic Flowchart (Dermatology 5e, Fig. 47.11)', h3))
if 'flowchart.png' in downloaded:
fc_img = RLImage(downloaded['flowchart.png'], width=14*cm)
fc_tbl = Table([[fc_img]], colWidths=[17*cm])
fc_tbl.setStyle(TableStyle([('ALIGN', (0,0), (-1,-1), 'CENTER')]))
story.append(fc_tbl)
story.append(Spacer(1, 0.3*cm))
# ── Section 8: Differential Diagnosis ────────────────────────────────────────
story.append(section_header('8. DIFFERENTIAL DIAGNOSIS'))
story.append(Spacer(1, 0.2*cm))
dd_data = [
[b('Presentation'), b('Differential Diagnoses')],
['Waxy papules (AL amyloidosis)', 'Papular mucinosis, nodular cutaneous amyloidosis, lipoid proteinosis, adnexal tumors (face)'],
['Sclerodermoid infiltration', 'Systemic sclerosis, scleromyxedema, pretibial myxedema'],
['Bullous lesions', 'Porphyria cutanea tarda, epidermolysis bullosa acquisita, lichen planus bullosa'],
['PXE-like lesions', 'True pseudoxanthoma elasticum, perforating calcific elastosis'],
['Nail dystrophy', 'Late ungual lichen planus, onychomycosis'],
['Cutis laxa-like', 'True cutis laxa, acquired cutis laxa, aged skin'],
]
dd_rows = [[Paragraph(cell, ParagraphStyle('tc', parent=body, fontSize=8.5, leading=12)) for cell in row] for row in dd_data]
story.append(info_table(dd_rows, [5.5*cm, 11.5*cm]))
story.append(Spacer(1, 0.3*cm))
# ── Section 9: Treatment ──────────────────────────────────────────────────────
story.append(section_header('9. TREATMENT'))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph('AL Amyloidosis', h3))
story.append(Paragraph(
'Therapy targets reducing production of the amyloid precursor light chain. '
'Supportive care is directed at affected organs.',
body))
for item in [
f'{b("High-dose melphalan + autologous stem cell transplantation (ASCT)")} - standard for eligible patients; improved organ responses and survival',
f'{b("Bortezomib-based combination chemotherapy")} (e.g., bortezomib-cyclophosphamide-dexamethasone) for ineligible patients',
f'{b("Daratumumab-based regimens")} - more recently employed',
f'{b("Lenalidomide-based regimens")}',
f'{b("Supportive:")} diuretics for nephrotic syndrome/CHF; antiarrhythmics; symptomatic treatment of neuropathy and GI involvement',
]:
story.append(Paragraph(f'• {item}', bullet))
story.append(Paragraph('AA Amyloidosis', h3))
for item in [
f'Treat the {b("underlying infectious or inflammatory disease")} to halt progression',
f'{b("Biologic agents")} (e.g., TNF inhibitors in RA/ankylosing spondylitis) have shown significant reduction in acute phase reactants and proteinuria',
f'Goal: maintain SAA {b("<4 mg/L")}',
]:
story.append(Paragraph(f'• {item}', bullet))
story.append(Paragraph('Cutaneous Amyloidosis (Primary Localized)', h3))
story.append(Paragraph('No curative treatment. Directed at breaking the itch-scratch-itch cycle.', body))
tx_data = [
[b('Treatment'), b('Evidence Level')],
['Potent topical corticosteroids ± occlusion ± keratolytics (SA)', '2'],
['Topical calcineurin inhibitors', '3'],
['Intralesional corticosteroids', '3'],
['UVB phototherapy', '2'],
['PUVA phototherapy (marginally better for pruritus)', '2'],
['Systemic retinoids (acitretin, alitretinoin)', '2'],
['Dermabrasion (effects lasting ≥5 years)', '2'],
['CO2 or Er:YAG laser therapy', '2'],
['Dupilumab (lichen amyloidosis)', '3'],
['Low-dose cyclophosphamide (50 mg/day)', '3'],
['Surgical excision / cryotherapy (nodular)', '2 - local recurrence common'],
]
tx_rows = [[Paragraph(cell, ParagraphStyle('tc', parent=body, fontSize=8.5, leading=12)) for cell in row] for row in tx_data]
story.append(info_table(tx_rows, [12.5*cm, 4.5*cm]))
story.append(Spacer(1, 0.3*cm))
# ── Section 10: Summary Table ─────────────────────────────────────────────────
story.append(section_header('10. SUMMARY COMPARISON TABLE'))
story.append(Spacer(1, 0.2*cm))
sum_data = [
[b('Feature'), b('AL (Primary)'), b('AA (Secondary)'), b('ATTRwt (Senile)')],
['Amyloid protein', 'Ig light chains (lambda)', 'Serum amyloid A', 'Wild-type transthyretin'],
['Cause', 'Plasma cell dyscrasia', 'Chronic infection/inflammation', 'Aging (wild-type TTR)'],
['Age group', 'Middle-aged adults', 'Any age', '>70 years'],
['Skin involvement', 'YES (25-40%)', 'Clinically absent', 'Absent'],
['Key skin sign', 'Pinch purpura, macroglossia,\nwaxy papules', 'None (perivascular deposits only)', 'None'],
['Key organs', 'Heart, kidney, nerve', 'Kidney, liver, spleen', 'Heart'],
['KMnO4 test', 'Birefringence retained', 'Birefringence LOST', 'N/A'],
['Fat aspirate', 'Positive (80-90%)', 'Detects AA deposits', 'Positive (~75%)'],
['Prognosis', 'Poor (median 13 months)', 'Depends on underlying disease', 'Slowly progressive'],
]
sum_rows = [[Paragraph(cell, ParagraphStyle('tc', parent=body, fontSize=8.5, leading=12)) for cell in row] for row in sum_data]
story.append(info_table(sum_rows, [3.5*cm, 4.5*cm, 4.5*cm, 4.5*cm]))
story.append(Spacer(1, 0.4*cm))
# ── Sources ───────────────────────────────────────────────────────────────────
story.append(HRFlowable(width='100%', thickness=0.5, color=TEAL))
story.append(Spacer(1, 0.15*cm))
story.append(Paragraph('Sources', h3))
for src in [
'Andrews\' Diseases of the Skin: Clinical Dermatology, 12th ed., Chapter 26, pp. 598-610',
'Dermatology 2-Volume Set, 5th ed. (Bolognia et al.), Chapter 47, pp. 924-932',
'Fitzpatrick\'s Dermatology, 9th ed., Chapter 91 (Nail disorders) and Chapter on Cutaneous Manifestations of Internal Malignancy',
]:
story.append(Paragraph(f'• {src}', source_style))
# ─── Build PDF ────────────────────────────────────────────────────────────────
doc.build(story)
print(f"PDF created: {OUTPUT_PATH}")
cd /home/daytona/workspace/amyloidosis-notes && python3 generate_pdf.py 2>&1
~/amyloidosis-notes/generate_pdf.py
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/amyloidosis-notes/generate_pdf.py'
~/amyloidosis-notes/generate_pdf.py
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/amyloidosis-notes/generate_pdf.py'
~/amyloidosis-notes/generate_pdf.py
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/amyloidosis-notes/generate_pdf.py'
cd /home/daytona/workspace/amyloidosis-notes && python3 generate_pdf.py 2>&1
ls -lh /home/daytona/workspace/amyloidosis-notes/Systemic_Amyloidosis_Dermatology_Notes.pdf
Systemic Amyloidosis Dermatology Notes
PDF Document · PDF