make a ppt on sarcoidosis for registrars doctors
sarcoidosis chest x-ray bilateral hilar lymphadenopathy staging
sarcoidosis non-caseating granuloma histology

This is a low-magnification brightfield histology image of a tissue section stained with Hematoxylin and Eosin (H&E). The specimen shows granulomatous inflammation with aggregates of epithelioid macrophages forming a rounded granuloma, often with multinucleated giant cells, surrounded by a lymphocytic cuff. The central focus is well circumscribed within native parenchyma, suggesting a chronic, organized immune response to a persistent antigen. Necrosis is not clearly evident at this magnification, though subtle caseation cannot be excluded. Morphology is compatible with tuberculoid or non-caseating granulomas, and infectious versus noninfectious etiologies must be distinguished with ancillary studies. This pattern can occur in lymph nodes or solid organs and prompts a differential that includes tuberculous lymphadenitis, sarcoidosis, fungal granulomatous infections (Histoplasma, Coccidioides), and foreign-body reaction. Clinically, recognition of granulomas guides testing: acid-fast bacilli staining (Ziehl-Neelsen), fungal stains (GMS/PAS), cultures, PCR panels, and radiologic correlation. The image is educational for medical trainees, illustrating granuloma architecture, macrophage differentiation, and the spectrum of chronic inflammatory responses. Educational context.

This is a photomicrograph of a splenic parenchyma section from a splenectomy specimen, prepared for light microscopy and stained with hematoxylin and eosin. The specimen shows multiple subcentimeter nodules within the splenic parenchyma, with well-formed, non-caseating granulomas composed of tightly arranged epithelioid macrophages and multinucleated giant cells surrounded by a lymphocytic rim. The granulomas lack central necrosis, which, along with histiocytic microarchitecture, is highly suggestive of granulomatous inflammation due to Toxoplasma gondii infection. Serologic tests confirmed toxoplasmosis in this patient, correlating with disseminated disease or focal splenic involvement associated with lymphadenopathy and splenomegaly. In the spleen, toxoplasmosis can produce discrete nodules or focal granulomatous lesions that may mimic lymphoma or other granulomatous diseases on imaging or gross examination. Key differential diagnoses include sarcoidosis, fungal infections such as histoplasmosis, mycobacterial infections, and other parasitic infestations; clinical correlation with serology and immune status is essential. This image is relevant for teaching granulomatous splenitis due to toxoplasmosis, assessing granuloma morphology, distinguishing non-caseating from caseating granulomas, and correlating histology with systemic infection. Appropriate clinical scenarios include immunocompromised patients with fever, cytopenias, or organomegaly and routine pathology review in splenectomy specimens. This image exemplifies infectious granulomatous disease companion to serology and morphology in clinical practice.
sarcoidosis treatment guideline
lupus pernio cutaneous sarcoidosis face

This composite clinical photograph displays two distinct dermatologic manifestations of systemic sarcoidosis. Panel (a) illustrates erythema nodosum, an acute inflammatory condition characterized by a large, ill-defined, erythematous patch on the pretibial region of the lower leg. The lesion appears as a warm, tender-looking plaque, which is a common early non-specific sign of sarcoidosis, often associated with Löfgren syndrome. Panel (b) shows lupus pernio, a pathognomonic chronic cutaneous finding. It presents as a violaceous (reddish-purple), indurated, and disfiguring plaque affecting the central face, specifically the bridge, tip, and alae of the nose. The texture is nodular with visible scaling and crusting along the nasal borders. These images contrast the transient, reactive nature of erythema nodosum against the chronic, granulomatous infiltration seen in lupus pernio, providing key diagnostic markers for the clinical evaluation of sarcoidosis in dermatology and internal medicine.

This composite clinical photograph displays the multi-systemic cutaneous and musculoskeletal manifestations of chronic sarcoidosis. Figures (a) and (b) show the patient's face with characteristic lupus pernio, presenting as indurated, violaceous (purplish) plaques and nodules affecting the nose, cheeks, and periorbital regions. Figure (e) illustrates a large, well-demarcated, erythematous to purplish indurated plaque on the medial aspect of the right leg. Figures (c) and (d) demonstrate clinical dactylitis ('sausage digits') of the hands, characterized by diffuse swelling of the fingers involving the proximal interphalangeal (PIP) and distal interphalangeal (DIP) joints. The image serves as an educational resource for identifying the classic visual signs of sarcoidosis, specifically the association between lupus pernio skin lesions and sarcoid dactylitis or inflammatory arthritis. It is intended for medical students and clinicians specializing in dermatology and rheumatology.

This is a high‑resolution clinical photograph of a single violaceous cutaneous plaque on the malar/cheek region. Imaging modality: clinical photography of the skin, near-frontal view of the zygomatic area under white light, without dermoscopic enhancement. Anatomical localization: integumentary system, facial skin; cheek. Visual features: a well‑circumscribed, indurated plaque with a purple‑violaceous hue, smooth to slightly glossy surface, mild surrounding erythema, and subtle texturing. The lesion geometry is oval to irregular, with a slightly lighter center suggesting mild central atrophy or edema. Medical impression: the violaceous, persistent plaque on the face is highly suggestive of cutaneous sarcoidosis presenting as lupus pernio, a prototypical cutaneous manifestation linked to systemic sarcoidosis. Alternative considerations include granulomatous rosacea, chronic infectious granulomas (mycobacterial or fungal), and other granulomatous dermatitis. Diagnostic significance: if lupus pernio is suspected, correlate with chest imaging, serum ACE levels, and biopsy showing noncaseating granulomas for confirmation. Clinical relevance: this morphology warrants multidisciplinary evaluation for systemic involvement, and consideration of dermatology, pulmonology, and rheumatology follow‑up. Potential clinical use: educational reference for dermatology training, sarcoidosis recognition, and differential diagnosis practice with facial violaceous plaques. In documentation, annotate lesion margins, color, and texture changes over time to assist monitoring and therapeutic response assessment and prognosis.
mkdir -p /tmp/workspace/sarcoidosis-ppt/assets && ls -la /tmp/workspace/
cd /tmp/workspace/sarcoidosis-ppt/assets && python /tmp/skills/shared/scripts/fetch_images.py \ "https://cdn.orris.care/cdss_images/Pathology_1760048329169_df3d34c0-c544-4c0a-9b0d-fba71fc9eedd.jpg" \ "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_4b430e1931ac5a9b8ed2d0e524fd53b482f329af25bf5f2cff3bf3779f5f219b.jpg" \ "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_089203e7da26e81d7fc77353100f0b5b41f6eb0527c81500483b1bafa9280df0.jpg" \ > images.json && python -c " import json,base64 data=json.load(open('images.json')) names=['granuloma.jpg','skin_lesions1.jpg','skin_lesions2.jpg'] for img,name in zip(data,names): if img.get('base64'): b64=img['base64'].split(',',1)[1] if ',' in img['base64'] else img['base64'] with open(name,'wb') as f: f.write(base64.b64decode(b64)) print('saved',name) else: print('failed', img.get('url'), img.get('error')) "
~/sarcoidosis-ppt/build_ppt.py
from pptx import Presentation
from pptx.util import Inches, Pt, Emu
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.enum.shapes import MSO_SHAPE
import os
ASSETS = "/tmp/workspace/sarcoidosis-ppt/assets"
# Color palette (clinical navy / teal)
NAVY = RGBColor(0x0B, 0x2E, 0x4E)
TEAL = RGBColor(0x0E, 0x7C, 0x86)
LIGHT_TEAL = RGBColor(0xE6, 0xF3, 0xF3)
DARK = RGBColor(0x27, 0x2B, 0x30)
GREY = RGBColor(0x5A, 0x63, 0x6B)
WHITE = RGBColor(0xFF, 0xFF, 0xFF)
ACCENT = RGBColor(0xC0, 0x6A, 0x2E) # amber accent for emphasis
prs = Presentation()
prs.slide_width = Inches(13.333)
prs.slide_height = Inches(7.5)
BLANK = prs.slide_layouts[6]
SW, SH = prs.slide_width, prs.slide_height
def add_slide():
return prs.slides.add_slide(BLANK)
def add_bg(slide, color=WHITE):
rect = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, 0, 0, SW, SH)
rect.fill.solid()
rect.fill.fore_color.rgb = color
rect.line.fill.background()
rect.shadow.inherit = False
slide.shapes._spTree.remove(rect._element)
slide.shapes._spTree.insert(2, rect._element)
return rect
def add_textbox(slide, l, t, w, h, text, size=18, color=DARK, bold=False,
align=PP_ALIGN.LEFT, font="Calibri", anchor=None, italic=False):
tb = slide.shapes.add_textbox(l, t, w, h)
tf = tb.text_frame
tf.word_wrap = True
if anchor:
tf.vertical_anchor = anchor
p = tf.paragraphs[0]
p.text = text
p.alignment = align
r = p.runs[0]
r.font.size = Pt(size)
r.font.bold = bold
r.font.italic = italic
r.font.color.rgb = color
r.font.name = font
return tb
def add_bullets(slide, l, t, w, h, items, size=15, color=DARK, font="Calibri",
line_spacing=1.15, space_after=8):
tb = slide.shapes.add_textbox(l, t, w, h)
tf = tb.text_frame
tf.word_wrap = True
first = True
for item in items:
if isinstance(item, tuple):
text, level, kwargs = item[0], item[1], (item[2] if len(item) > 2 else {})
else:
text, level, kwargs = item, 0, {}
p = tf.paragraphs[0] if first else tf.add_paragraph()
first = False
bullet_char = "\u25AA " if level == 0 else "\u2013 "
indent = "" if level == 0 else " "
p.text = indent + bullet_char + text
p.level = 0
p.space_after = Pt(space_after)
p.line_spacing = line_spacing
r = p.runs[0]
r.font.size = Pt(size - (2 if level else 0))
r.font.color.rgb = kwargs.get("color", color)
r.font.bold = kwargs.get("bold", False)
r.font.name = font
return tb
def header(slide, kicker, title, num, total):
add_bg(slide, WHITE)
bar = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, 0, 0, SW, Inches(1.15))
bar.fill.solid()
bar.fill.fore_color.rgb = NAVY
bar.line.fill.background()
bar.shadow.inherit = False
add_textbox(slide, Inches(0.55), Inches(0.10), Inches(11), Inches(0.35),
kicker.upper(), size=12, color=RGBColor(0xB9, 0xD6, 0xDC), bold=True, font="Calibri")
add_textbox(slide, Inches(0.55), Inches(0.40), Inches(11.5), Inches(0.7),
title, size=26, color=WHITE, bold=True, font="Calibri")
accent = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, Inches(0.55), Inches(1.15), Inches(1.3), Pt(4))
accent.fill.solid()
accent.fill.fore_color.rgb = ACCENT
accent.line.fill.background()
accent.shadow.inherit = False
# footer
add_textbox(slide, Inches(0.55), Inches(7.12), Inches(6), Inches(0.3),
"Sarcoidosis \u2014 Registrar Teaching Session", size=9, color=GREY)
add_textbox(slide, Inches(11.6), Inches(7.12), Inches(1.2), Inches(0.3),
f"{num} / {total}", size=9, color=GREY, align=PP_ALIGN.RIGHT)
TOTAL = 17
# ---------- SLIDE 1: TITLE ----------
s = add_slide()
add_bg(s, NAVY)
band = s.shapes.add_shape(MSO_SHAPE.RECTANGLE, 0, Inches(4.9), SW, Inches(2.6))
band.fill.solid(); band.fill.fore_color.rgb = RGBColor(0x08, 0x22, 0x38); band.line.fill.background(); band.shadow.inherit = False
line = s.shapes.add_shape(MSO_SHAPE.RECTANGLE, Inches(0.7), Inches(3.55), Inches(1.6), Pt(5))
line.fill.solid(); line.fill.fore_color.rgb = ACCENT; line.line.fill.background(); line.shadow.inherit = False
add_textbox(s, Inches(0.7), Inches(2.5), Inches(11.5), Inches(1.0), "SARCOIDOSIS", size=54, color=WHITE, bold=True)
add_textbox(s, Inches(0.7), Inches(3.7), Inches(11), Inches(0.6),
"A Multisystem Granulomatous Disease: Recognition, Work-up & Management", size=20, color=RGBColor(0xCF, 0xE3, 0xE7))
add_textbox(s, Inches(0.7), Inches(5.25), Inches(10), Inches(0.5), "Teaching Session for Medical Registrars", size=18, color=RGBColor(0xB9, 0xD6, 0xDC), bold=True)
add_textbox(s, Inches(0.7), Inches(5.75), Inches(10), Inches(0.5), "Internal Medicine / Respiratory Rotation", size=14, color=GREY)
# ---------- SLIDE 2: OBJECTIVES ----------
s = add_slide(); header(s, "Introduction", "Learning Objectives", 2, TOTAL)
add_bullets(s, Inches(0.7), Inches(1.6), Inches(11.8), Inches(5),
["Define sarcoidosis and summarise its epidemiology and proposed pathogenesis",
"Recognise the pulmonary and key extrapulmonary presentations, including sight- and life-threatening forms",
"Apply a structured diagnostic approach: compatible clinical picture + non-caseating granulomas + exclusion of alternatives",
"Interpret radiographic (Scadding) staging and relevant investigations (bloods, HRCT, BAL, biopsy)",
"Formulate an evidence-based management plan, including when to observe vs. treat, and escalation pathways",
"Identify red flags requiring urgent specialist referral (cardiac, neuro, ocular sarcoidosis)"],
size=17, space_after=14)
# ---------- SLIDE 3: DEFINITION & EPIDEMIOLOGY ----------
s = add_slide(); header(s, "Background", "Definition & Epidemiology", 3, TOTAL)
add_textbox(s, Inches(0.7), Inches(1.5), Inches(5.9), Inches(0.4), "What is it?", size=16, color=TEAL, bold=True)
add_bullets(s, Inches(0.7), Inches(1.95), Inches(5.9), Inches(2.2),
["Multisystem disease of unknown cause characterised by non-caseating granulomatous inflammation",
"Most commonly affects the lungs and mediastinal/hilar lymph nodes, but can involve any organ",
"Diagnosis of exclusion \u2014 no single confirmatory test"], size=14, space_after=10)
add_textbox(s, Inches(6.9), Inches(1.5), Inches(5.7), Inches(0.4), "Epidemiology", size=16, color=TEAL, bold=True)
add_bullets(s, Inches(6.9), Inches(1.95), Inches(5.7), Inches(4.5),
["Highest incidence: African Americans (~35.5/100,000) and Northern Europeans (~24/100,000)",
"Female predominance (up to 2:1 in most cohorts); US Black Women's Health Study: incidence 71/100,000, prevalence ~2%",
"Peak age 35\u201345 years; a significant proportion present after age 55",
"Risk factors: certain occupational/environmental exposures, raised BMI; smoking is associated with reduced incidence",
"Seasonal clustering \u2014 more diagnoses in spring",
"Black and female patients tend to have more severe / extrapulmonary disease; higher mortality reported in women and African Americans (pulmonary fibrosis is the leading cause of death)"],
size=13.5, space_after=9)
add_textbox(s, Inches(0.7), Inches(4.4), Inches(5.9), Inches(2.4), "", size=10)
box = s.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, Inches(0.7), Inches(4.4), Inches(5.9), Inches(2.3))
box.fill.solid(); box.fill.fore_color.rgb = LIGHT_TEAL; box.line.color.rgb = TEAL; box.line.width = Pt(0.75); box.shadow.inherit = False
tf = box.text_frame; tf.word_wrap = True; tf.margin_left = Inches(0.2); tf.margin_top = Inches(0.15)
p = tf.paragraphs[0]; p.text = "Population variation in phenotype"; p.runs[0].font.bold = True; p.runs[0].font.size = Pt(14); p.runs[0].font.color.rgb = NAVY
for line_txt in ["Japanese patients: more cardiac & ocular involvement",
"Europeans: more erythema nodosum (uncommon in Black/Japanese patients)",
"Japan: lower overall mortality, but cardiac sarcoidosis is the leading cause of death there"]:
pp = tf.add_paragraph(); pp.text = "\u25AA " + line_txt; pp.space_before = Pt(6)
pp.runs[0].font.size = Pt(12.5); pp.runs[0].font.color.rgb = DARK
# ---------- SLIDE 4: PATHOGENESIS ----------
s = add_slide(); header(s, "Background", "Aetiology & Pathogenesis", 4, TOTAL)
add_bullets(s, Inches(0.7), Inches(1.6), Inches(11.8), Inches(3.2),
["Cause remains unknown \u2014 leading model: exaggerated / dysregulated host immune (Th1-driven) response to an unidentified environmental antigen in a genetically susceptible host",
"Historic evidence for a transmissible antigen: the Kveim-Siltzbach test (splenic homogenate from sarcoidosis patients) induced granulomas when injected into early-disease patients; sarcoid-like reactions reported after solid organ transplant from a donor with sarcoidosis",
"Candidate antigens studied because they produce similar granulomatous histology: beryllium, mycobacteria, and fungi",
"Mycobacterial proteins (mKatG, ESAT-6, superoxide dismutase A, antigen 85A, heat-shock proteins) are disproportionately represented in sarcoid granulomas, but no organism has been proven causal",
"End result: activated macrophages/CD4+ T-cells aggregate and organise into non-caseating granulomas, which may resolve spontaneously or progress to fibrosis"],
size=15.5, space_after=12)
box = s.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, Inches(0.7), Inches(5.3), Inches(11.8), Inches(1.35))
box.fill.solid(); box.fill.fore_color.rgb = RGBColor(0xFB, 0xF0, 0xE3); box.line.color.rgb = ACCENT; box.line.width = Pt(0.75); box.shadow.inherit = False
tf = box.text_frame; tf.word_wrap = True; tf.margin_left = Inches(0.25); tf.margin_top = Inches(0.12); tf.vertical_anchor = MSO_ANCHOR.MIDDLE
p = tf.paragraphs[0]; p.text = "Registrar pearl: think of sarcoidosis as a diagnosis of pattern + exclusion \u2014 always rule out TB, fungal infection, berylliosis and lymphoma before committing to the label."
p.runs[0].font.size = Pt(14); p.runs[0].font.italic = True; p.runs[0].font.color.rgb = NAVY; p.runs[0].font.bold = True
# ---------- SLIDE 5: CLINICAL - PULMONARY ----------
s = add_slide(); header(s, "Clinical Features", "Pulmonary Manifestations", 5, TOTAL)
add_bullets(s, Inches(0.7), Inches(1.55), Inches(11.8), Inches(3.2),
["Present in ~90% of patients; accounts for most morbidity and mortality",
"Symptoms: dry cough, dyspnoea, chest discomfort \u2014 often insidious; up to a third are asymptomatic and detected incidentally",
"Bilateral hilar and/or mediastinal lymphadenopathy \u00b1 parenchymal infiltrates on imaging",
"Chronic disease may progress to pulmonary fibrosis, traction bronchiectasis, and honeycombing (advanced Stage IV)",
"Pulmonary function tests: may be normal, or show a restrictive pattern with reduced DLCO; obstruction can occur from airway granulomas/distortion",
"Complications: pulmonary hypertension, mycetoma within fibrotic cavities, respiratory failure"],
size=15.5, space_after=11)
box = s.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, Inches(0.7), Inches(5.15), Inches(11.8), Inches(1.55))
box.fill.solid(); box.fill.fore_color.rgb = LIGHT_TEAL; box.line.color.rgb = TEAL; box.line.width = Pt(0.75); box.shadow.inherit = False
tf = box.text_frame; tf.word_wrap = True; tf.margin_left = Inches(0.25); tf.margin_top = Inches(0.12)
p = tf.paragraphs[0]; p.text = "Lofgren syndrome (acute presentation, good prognosis)"; p.runs[0].font.bold = True; p.runs[0].font.size = Pt(14.5); p.runs[0].font.color.rgb = NAVY
pp = tf.add_paragraph(); pp.text = "Bilateral hilar lymphadenopathy + erythema nodosum + polyarthralgia (ankles) \u00b1 fever \u2014 often self-limiting, resolves within 2 years in >80%"
pp.runs[0].font.size = Pt(13.5); pp.runs[0].font.color.rgb = DARK; pp.space_before = Pt(6)
# ---------- SLIDE 6: CLINICAL - EXTRAPULMONARY ----------
s = add_slide(); header(s, "Clinical Features", "Extrapulmonary Manifestations", 6, TOTAL)
cols = [
("Skin (~25%)", ["Erythema nodosum", "Lupus pernio (chronic, disfiguring, associated with pulmonary fibrosis)", "Scar infiltration, plaques, subcutaneous nodules"]),
("Eye (~20-30%)", ["Anterior/posterior uveitis", "Keratoconjunctivitis sicca", "Can cause blindness if untreated \u2014 needs prompt ophthalmology review"]),
("Cardiac (~5% clinical, higher on imaging)", ["Conduction block, ventricular arrhythmia", "Cardiomyopathy, sudden cardiac death", "Higher prevalence & mortality impact in Japanese cohorts"]),
("Neurological (~5-10%)", ["Cranial neuropathy (esp. facial nerve palsy)", "Basal meningitis, hypothalamic-pituitary involvement", "Peripheral neuropathy, myelopathy"]),
("Musculoskeletal / Renal / Other", ["Arthralgia, dactylitis, myopathy", "Hypercalcaemia / hypercalciuria \u2192 nephrocalcinosis, nephrolithiasis", "Hepatosplenomegaly; peripheral lymphadenopathy; parotid/lacrimal gland enlargement"]),
]
x_positions = [Inches(0.55), Inches(4.75), Inches(8.95)]
y_positions = [Inches(1.45), Inches(4.1)]
positions = [(x_positions[0], y_positions[0]), (x_positions[1], y_positions[0]), (x_positions[2], y_positions[0]),
(x_positions[0], y_positions[1]), (x_positions[1], y_positions[1])]
box_w, box_h = Inches(4.0), Inches(2.5)
for (title, items), (x, y) in zip(cols, positions):
card = s.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, x, y, box_w, box_h)
card.fill.solid(); card.fill.fore_color.rgb = WHITE
card.line.color.rgb = RGBColor(0xD8, 0xDE, 0xE2); card.line.width = Pt(1); card.shadow.inherit = False
hd = s.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, x, y, box_w, Inches(0.5))
hd.fill.solid(); hd.fill.fore_color.rgb = NAVY; hd.line.fill.background(); hd.shadow.inherit = False
tf = hd.text_frame; tf.word_wrap = True; tf.vertical_anchor = MSO_ANCHOR.MIDDLE
p = tf.paragraphs[0]; p.text = title; p.alignment = PP_ALIGN.CENTER
p.runs[0].font.size = Pt(13); p.runs[0].font.bold = True; p.runs[0].font.color.rgb = WHITE
tb = s.shapes.add_textbox(x + Inches(0.15), y + Inches(0.58), box_w - Inches(0.3), box_h - Inches(0.68))
tf2 = tb.text_frame; tf2.word_wrap = True
first = True
for it in items:
p2 = tf2.paragraphs[0] if first else tf2.add_paragraph(); first = False
p2.text = "\u25AA " + it
p2.space_after = Pt(5); p2.line_spacing = 1.05
p2.runs[0].font.size = Pt(11); p2.runs[0].font.color.rgb = DARK
# ---------- SLIDE 7: IMAGE - CUTANEOUS SARCOIDOSIS ----------
s = add_slide(); header(s, "Clinical Features", "Cutaneous Sarcoidosis \u2014 Visual Recognition", 7, TOTAL)
img1 = os.path.join(ASSETS, "skin_lesions1.jpg")
img2 = os.path.join(ASSETS, "skin_lesions2.jpg")
if os.path.exists(img1):
s.shapes.add_picture(img1, Inches(0.6), Inches(1.55), height=Inches(3.7))
if os.path.exists(img2):
s.shapes.add_picture(img2, Inches(6.6), Inches(1.55), height=Inches(3.7))
add_textbox(s, Inches(0.6), Inches(5.35), Inches(5.6), Inches(0.9),
"Left: Erythema nodosum (pretibial, acute, non-specific) and lupus pernio (violaceous nasal plaque, chronic).",
size=12.5, color=GREY, italic=True)
add_textbox(s, Inches(6.6), Inches(5.35), Inches(5.9), Inches(0.9),
"Right: Lupus pernio with facial/periorbital plaques and sarcoid dactylitis (\u2018sausage digits\u2019) of the hands.",
size=12.5, color=GREY, italic=True)
box = s.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, Inches(0.6), Inches(6.35), Inches(11.9), Inches(0.65))
box.fill.solid(); box.fill.fore_color.rgb = RGBColor(0xFB, 0xF0, 0xE3); box.line.color.rgb = ACCENT; box.line.width = Pt(0.75); box.shadow.inherit = False
tf = box.text_frame; tf.word_wrap = True; tf.vertical_anchor = MSO_ANCHOR.MIDDLE; tf.margin_left = Inches(0.2)
p = tf.paragraphs[0]; p.text = "Lupus pernio is strongly associated with chronic fibrotic pulmonary disease \u2014 a visual cue to look harder at the chest."
p.runs[0].font.size = Pt(13); p.runs[0].font.bold = True; p.runs[0].font.color.rgb = NAVY
# ---------- SLIDE 8: DIAGNOSTIC APPROACH ----------
s = add_slide(); header(s, "Diagnosis", "Diagnostic Approach", 8, TOTAL)
box = s.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, Inches(0.7), Inches(1.5), Inches(11.8), Inches(1.1))
box.fill.solid(); box.fill.fore_color.rgb = NAVY; box.line.fill.background(); box.shadow.inherit = False
tf = box.text_frame; tf.word_wrap = True; tf.vertical_anchor = MSO_ANCHOR.MIDDLE; tf.margin_left = Inches(0.3); tf.margin_right = Inches(0.3)
p = tf.paragraphs[0]; p.alignment = PP_ALIGN.CENTER
p.text = "Diagnosis requires ALL three: (1) a compatible clinical & radiological picture, (2) histological demonstration of non-caseating granulomas, and (3) exclusion of alternative causes of granulomatous disease"
p.runs[0].font.size = Pt(16); p.runs[0].font.bold = True; p.runs[0].font.color.rgb = WHITE
add_bullets(s, Inches(0.7), Inches(2.9), Inches(11.8), Inches(3.8),
["No single test is diagnostic \u2014 sarcoidosis is a pattern-recognition + exclusion diagnosis",
"Tissue is usually required except in classic Lofgren syndrome, where a confident clinical diagnosis is often accepted without biopsy",
"Key differentials to exclude before labelling as sarcoidosis:", ], size=16, space_after=10)
add_bullets(s, Inches(1.1), Inches(4.15), Inches(11.2), Inches(1.0),
[("Tuberculosis and other mycobacterial infection", 1),
("Fungal infection (histoplasmosis, coccidioidomycosis)", 1),
("Chronic beryllium disease (identical histology \u2014 needs occupational history \u00b1 beryllium lymphocyte proliferation test)", 1),
("Lymphoma, other malignancy; hypersensitivity pneumonitis; granulomatosis with polyangiitis", 1)],
size=13.5, space_after=6)
add_textbox(s, Inches(0.7), Inches(5.7), Inches(11.8), Inches(1.0),
"Biopsy site chosen by accessibility/yield: skin lesion, peripheral/mediastinal lymph node, conjunctiva, or minor salivary gland; endobronchial ultrasound-guided TBNA of mediastinal nodes is now a preferred first-line tissue route.",
size=13.5, color=GREY, italic=True)
# ---------- SLIDE 9: INVESTIGATIONS ----------
s = add_slide(); header(s, "Diagnosis", "Investigations & Work-up", 9, TOTAL)
left_items = ["FBC (anaemia/lymphopenia), U&E, LFTs, corrected calcium (hypercalcaemia)",
"Serum ACE \u2014 supportive but neither sensitive nor specific; not for screening alone",
"24h urinary calcium (hypercalciuria)",
"ECG in every patient \u2014 screen for conduction disease; further cardiac MRI/PET if abnormal or symptomatic",
"Ophthalmology review (slit-lamp) even if asymptomatic",
"Pulmonary function tests (spirometry + DLCO)"]
right_items = ["HRCT chest: bilateral hilar/mediastinal lymphadenopathy, perilymphatic nodules, upper-lobe predominant fibrosis in advanced disease",
"Bronchoscopy with BAL and biopsy (endobronchial + transbronchial) \u00b1 EBUS-TBNA of mediastinal nodes",
"BAL lymphocytosis with CD4:CD8 ratio > 3.5 supports the diagnosis (not fully specific)",
"Tissue biopsy: non-caseating (\u2018naked\u2019) granulomas with epithelioid histiocytes and multinucleated giant cells; stains (AFB, fungal) and cultures to exclude infection",
"Tuberculin skin test / IGRA to help exclude TB before immunosuppression"]
add_textbox(s, Inches(0.65), Inches(1.45), Inches(5.9), Inches(0.4), "Bloods & Screening", size=15.5, color=TEAL, bold=True)
add_bullets(s, Inches(0.65), Inches(1.9), Inches(5.9), Inches(4.8), left_items, size=13.5, space_after=9)
add_textbox(s, Inches(6.85), Inches(1.45), Inches(5.9), Inches(0.4), "Imaging, Endoscopy & Histology", size=15.5, color=TEAL, bold=True)
add_bullets(s, Inches(6.85), Inches(1.9), Inches(5.9), Inches(4.8), right_items, size=13.5, space_after=9)
# ---------- SLIDE 10: HISTOLOGY IMAGE ----------
s = add_slide(); header(s, "Diagnosis", "Histopathology \u2014 Non-caseating Granuloma", 10, TOTAL)
imgh = os.path.join(ASSETS, "granuloma.jpg")
if os.path.exists(imgh):
s.shapes.add_picture(imgh, Inches(0.8), Inches(1.5), height=Inches(4.6))
add_textbox(s, Inches(7.1), Inches(1.6), Inches(5.4), Inches(0.4), "Key features", size=16, color=TEAL, bold=True)
add_bullets(s, Inches(7.1), Inches(2.1), Inches(5.4), Inches(3.2),
["Well-circumscribed, compact ('naked') granulomas of epithelioid histiocytes \u00b1 multinucleated giant cells",
"Tight lymphocytic cuff, minimal surrounding inflammation",
"No central caseating necrosis (unlike TB) \u2014 subtle fibrinoid necrosis can occasionally occur",
"Occasional inclusions: Schaumann bodies, asteroid bodies (not specific)",
"Always correlate with AFB/fungal stains and cultures to exclude infectious granulomas before confirming sarcoidosis"],
size=14, space_after=10)
add_textbox(s, Inches(0.8), Inches(6.25), Inches(6.5), Inches(0.6),
"H&E, low power: discrete non-caseating granuloma with epithelioid macrophages and a lymphocytic rim.",
size=11.5, color=GREY, italic=True)
# ---------- SLIDE 11: RADIOGRAPHIC STAGING ----------
s = add_slide(); header(s, "Diagnosis", "Radiographic (Scadding) Staging \u2014 Chest X-ray", 11, TOTAL)
stages = [
("Stage 0", "Normal chest radiograph", "~10-15%"),
("Stage I", "Bilateral hilar \u00b1 paratracheal lymphadenopathy alone", "~30-50%"),
("Stage II", "Lymphadenopathy + parenchymal infiltrates", "~40-60%"),
("Stage III", "Parenchymal infiltrates without lymphadenopathy", "~10-15%"),
("Stage IV", "Pulmonary fibrosis (honeycombing, traction bronchiectasis, hilar retraction)", "~5-10%"),
]
y = Inches(1.55)
colors = [RGBColor(0x1B, 0x5E, 0x77), RGBColor(0x15, 0x74, 0x7A), RGBColor(0x0E, 0x7C, 0x86), RGBColor(0xB0, 0x7A, 0x2E), RGBColor(0x9C, 0x3B, 0x2E)]
for (stage, desc, freq), col in zip(stages, colors):
row = s.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, Inches(0.7), y, Inches(11.8), Inches(0.85))
row.fill.solid(); row.fill.fore_color.rgb = WHITE; row.line.color.rgb = RGBColor(0xD8,0xDE,0xE2); row.line.width = Pt(1); row.shadow.inherit = False
tag = s.shapes.add_shape(MSO_SHAPE.RECTANGLE, Inches(0.7), y, Inches(1.7), Inches(0.85))
tag.fill.solid(); tag.fill.fore_color.rgb = col; tag.line.fill.background(); tag.shadow.inherit = False
tf = tag.text_frame; tf.vertical_anchor = MSO_ANCHOR.MIDDLE
p = tf.paragraphs[0]; p.alignment = PP_ALIGN.CENTER; p.text = stage
p.runs[0].font.size = Pt(15); p.runs[0].font.bold = True; p.runs[0].font.color.rgb = WHITE
tb = s.shapes.add_textbox(Inches(2.55), y, Inches(7.7), Inches(0.85))
tf2 = tb.text_frame; tf2.vertical_anchor = MSO_ANCHOR.MIDDLE; tf2.word_wrap = True
p2 = tf2.paragraphs[0]; p2.text = desc; p2.runs[0].font.size = Pt(14.5); p2.runs[0].font.color.rgb = DARK
tb2 = s.shapes.add_textbox(Inches(10.4), y, Inches(2.0), Inches(0.85))
tf3 = tb2.text_frame; tf3.vertical_anchor = MSO_ANCHOR.MIDDLE
p3 = tf3.paragraphs[0]; p3.alignment = PP_ALIGN.CENTER; p3.text = freq
p3.runs[0].font.size = Pt(13); p3.runs[0].font.italic = True; p3.runs[0].font.color.rgb = GREY
y += Inches(0.98)
add_textbox(s, Inches(0.7), Inches(6.55), Inches(11.8), Inches(0.5),
"Higher stage broadly correlates with lower spontaneous remission and worse prognosis, but does not replace clinical/physiological assessment.",
size=12.5, color=GREY, italic=True)
# ---------- SLIDE 12: DIFFERENTIAL DIAGNOSIS ----------
s = add_slide(); header(s, "Diagnosis", "Key Differential Diagnoses", 12, TOTAL)
diffs = [
("Infectious", "TB & atypical mycobacteria, histoplasmosis, coccidioidomycosis, cat-scratch disease"),
("Occupational", "Chronic beryllium disease (histologically identical \u2014 needs exposure history & BeLPT)"),
("Malignancy", "Lymphoma, metastatic carcinoma with granulomatous reaction"),
("Autoimmune / Vasculitic", "Granulomatosis with polyangiitis, hypersensitivity pneumonitis, Crohn's disease"),
("Drug-induced", "Interferon-alpha, immune checkpoint inhibitors, anti-TNF therapy (paradoxical sarcoid-like reactions)"),
]
y = Inches(1.55)
for name, desc in diffs:
row = s.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, Inches(0.7), y, Inches(11.8), Inches(0.92))
row.fill.solid(); row.fill.fore_color.rgb = LIGHT_TEAL if diffs.index((name,desc)) % 2 == 0 else WHITE
row.line.color.rgb = RGBColor(0xD8,0xDE,0xE2); row.line.width = Pt(0.75); row.shadow.inherit = False
tb = s.shapes.add_textbox(Inches(0.95), y, Inches(2.6), Inches(0.92))
tf = tb.text_frame; tf.vertical_anchor = MSO_ANCHOR.MIDDLE
p = tf.paragraphs[0]; p.text = name; p.runs[0].font.bold = True; p.runs[0].font.size = Pt(15); p.runs[0].font.color.rgb = NAVY
tb2 = s.shapes.add_textbox(Inches(3.65), y, Inches(8.65), Inches(0.92))
tf2 = tb2.text_frame; tf2.word_wrap = True; tf2.vertical_anchor = MSO_ANCHOR.MIDDLE
p2 = tf2.paragraphs[0]; p2.text = desc; p2.runs[0].font.size = Pt(14); p2.runs[0].font.color.rgb = DARK
y += Inches(1.02)
# ---------- SLIDE 13: WHEN TO TREAT ----------
s = add_slide(); header(s, "Management", "When to Treat vs. Observe", 13, TOTAL)
add_textbox(s, Inches(0.7), Inches(1.45), Inches(11.8), Inches(0.6),
"Not every patient with sarcoidosis needs treatment \u2014 many cases (especially Stage I / Lofgren syndrome) remit spontaneously.",
size=15.5, color=NAVY, bold=True)
add_textbox(s, Inches(0.7), Inches(2.15), Inches(5.7), Inches(0.4), "Observe / no treatment", size=15.5, color=TEAL, bold=True)
add_bullets(s, Inches(0.7), Inches(2.6), Inches(5.7), Inches(3.6),
["Asymptomatic Stage 0-I disease with normal/stable lung function",
"Lofgren syndrome \u2014 usually self-limiting; NSAIDs for symptomatic arthralgia",
"Isolated asymptomatic skin or lymph node disease",
"Plan: clinical, radiographic and PFT surveillance (e.g. every 3-6 months initially)"],
size=14, space_after=10)
add_textbox(s, Inches(6.9), Inches(2.15), Inches(5.7), Inches(0.4), "Treat", size=15.5, color=ACCENT, bold=True)
add_bullets(s, Inches(6.9), Inches(2.6), Inches(5.7), Inches(4.0),
["Progressive or symptomatic pulmonary disease with declining PFTs",
"Cardiac involvement (arrhythmia, conduction disease, cardiomyopathy)",
"Neurosarcoidosis (CNS/PNS involvement)",
"Ocular disease not controlled with topical therapy",
"Hypercalcaemia / hypercalciuria with renal impairment",
"Disfiguring or functionally limiting cutaneous disease (e.g. lupus pernio)",
"Significant constitutional symptoms / disabling fatigue"],
size=14, space_after=8, color=DARK)
# ---------- SLIDE 14: PHARMACOTHERAPY ----------
s = add_slide(); header(s, "Management", "Pharmacological Management", 14, TOTAL)
tiers = [
("1st line", "Oral corticosteroids", "Prednisone/prednisolone (typically ~20-40 mg/day, tapered over months) remain first-line for organ-threatening or progressive disease. Topical/inhaled steroids for isolated skin or airway disease.", NAVY),
("2nd line", "Steroid-sparing agents", "Methotrexate is the most widely used; azathioprine, mycophenolate, leflunomide, and hydroxychloroquine (especially cutaneous disease) are alternatives, used for steroid-refractory disease, relapse, or to limit cumulative steroid toxicity.", TEAL),
("3rd line", "Biologic therapy", "Anti-TNF agents (infliximab has the best evidence; adalimumab also used) for refractory, severe, or multi-organ disease unresponsive to steroids and steroid-sparing agents. Etanercept has NOT shown efficacy.", ACCENT),
]
y = Inches(1.5)
for tag, name, desc, col in tiers:
card = s.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, Inches(0.7), y, Inches(11.8), Inches(1.55))
card.fill.solid(); card.fill.fore_color.rgb = WHITE; card.line.color.rgb = RGBColor(0xD8,0xDE,0xE2); card.line.width = Pt(1); card.shadow.inherit = False
tagbox = s.shapes.add_shape(MSO_SHAPE.RECTANGLE, Inches(0.7), y, Inches(1.5), Inches(1.55))
tagbox.fill.solid(); tagbox.fill.fore_color.rgb = col; tagbox.line.fill.background(); tagbox.shadow.inherit = False
tf = tagbox.text_frame; tf.vertical_anchor = MSO_ANCHOR.MIDDLE; tf.word_wrap = True
p = tf.paragraphs[0]; p.alignment = PP_ALIGN.CENTER; p.text = tag
p.runs[0].font.size = Pt(14); p.runs[0].font.bold = True; p.runs[0].font.color.rgb = WHITE
tb = s.shapes.add_textbox(Inches(2.35), y + Inches(0.08), Inches(10.0), Inches(1.4))
tf2 = tb.text_frame; tf2.word_wrap = True
p2 = tf2.paragraphs[0]; p2.text = name; p2.runs[0].font.size = Pt(15.5); p2.runs[0].font.bold = True; p2.runs[0].font.color.rgb = NAVY
p3 = tf2.add_paragraph(); p3.text = desc; p3.space_before = Pt(3); p3.runs[0].font.size = Pt(12.5); p3.runs[0].font.color.rgb = DARK
y += Inches(1.7)
add_textbox(s, Inches(0.7), Inches(6.65), Inches(11.8), Inches(0.5),
"Recent systematic review/meta-analysis (Thorax, 2025, PMID 40393718) supports biologic/targeted synthetic therapy efficacy in refractory sarcoidosis \u2014 check current evidence before escalation.",
size=11.5, color=GREY, italic=True)
# ---------- SLIDE 15: COMPLICATIONS & PROGNOSIS ----------
s = add_slide(); header(s, "Outcomes", "Complications & Prognosis", 15, TOTAL)
add_textbox(s, Inches(0.7), Inches(1.5), Inches(5.9), Inches(0.4), "Prognosis", size=16, color=TEAL, bold=True)
add_bullets(s, Inches(0.7), Inches(1.95), Inches(5.9), Inches(3.6),
["~60-70% of patients (especially Stage 0-I) undergo spontaneous remission within 2-5 years",
"Chronic/progressive disease more likely with Stage III-IV, Black race, and multi-organ involvement",
"Overall mortality is low (~1-5%) but higher in advanced pulmonary fibrosis, and in Black patients and women",
"Cardiac and neurosarcoidosis carry disproportionate morbidity/mortality risk"], size=14.5, space_after=11)
add_textbox(s, Inches(6.9), Inches(1.5), Inches(5.7), Inches(0.4), "Key complications", size=16, color=TEAL, bold=True)
add_bullets(s, Inches(6.9), Inches(1.95), Inches(5.7), Inches(4.0),
["Pulmonary fibrosis, pulmonary hypertension, mycetoma", "Fatal arrhythmia / sudden cardiac death",
"Blindness from untreated uveitis", "Nephrocalcinosis / renal impairment from hypercalcaemia",
"Hypothalamic-pituitary dysfunction (rare)", "Chronic corticosteroid toxicity from prolonged treatment"],
size=14.5, space_after=10)
# ---------- SLIDE 16: TAKE-HOME / RED FLAGS ----------
s = add_slide(); header(s, "Summary", "Key Take-Home Points for Registrars", 16, TOTAL)
add_bullets(s, Inches(0.7), Inches(1.5), Inches(11.8), Inches(2.6),
["Sarcoidosis is a clinicopathologic diagnosis of exclusion \u2014 always exclude infection, malignancy and beryllium exposure",
"Screen every patient for cardiac (ECG), ocular (slit-lamp) and hypercalcaemic complications regardless of pulmonary status",
"Treatment is reserved for organ-threatening, progressive or significantly symptomatic disease \u2014 many patients need only surveillance",
"Corticosteroids remain first-line; escalate to methotrexate or anti-TNF biologics (infliximab) for refractory disease"],
size=16.5, space_after=12)
box = s.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, Inches(0.7), Inches(4.5), Inches(11.8), Inches(2.1))
box.fill.solid(); box.fill.fore_color.rgb = RGBColor(0x8B, 0x1E, 0x1E); box.line.fill.background(); box.shadow.inherit = False
tf = box.text_frame; tf.word_wrap = True; tf.margin_left = Inches(0.3); tf.margin_top = Inches(0.15); tf.margin_right = Inches(0.3)
p = tf.paragraphs[0]; p.text = "\u26A0 Red flags \u2014 urgent specialist referral"; p.runs[0].font.bold = True; p.runs[0].font.size = Pt(17); p.runs[0].font.color.rgb = WHITE
for t in ["New arrhythmia, syncope, or heart block \u2192 urgent cardiology (risk of sudden death)",
"Visual loss, floaters, painful red eye \u2192 same-day ophthalmology",
"Focal neurology, cranial nerve palsy, or altered consciousness \u2192 neurology / neuroimaging",
"Severe hypercalcaemia or acute kidney injury \u2192 urgent medical admission"]:
pp = tf.add_paragraph(); pp.text = "\u25AA " + t; pp.space_before = Pt(6)
pp.runs[0].font.size = Pt(14); pp.runs[0].font.color.rgb = WHITE
# ---------- SLIDE 17: REFERENCES ----------
s = add_slide(); header(s, "Appendix", "References", 17, TOTAL)
refs = [
"Harrison's Principles of Internal Medicine, 22nd Edition (2025) \u2014 Sarcoidosis chapter",
"Fitzpatrick's Dermatology, 9th Edition \u2014 Sarcoidosis / cutaneous manifestations",
"Murray & Nadel's Textbook of Respiratory Medicine, 7th Edition \u2014 Sarcoidosis diagnosis & treatment",
"Firestein & Kelley's Textbook of Rheumatology \u2014 Musculoskeletal sarcoidosis, diagnostic tests",
"Andrews' Diseases of the Skin, 13th Edition \u2014 Systemic & cutaneous sarcoidosis, staging & treatment",
"Fishman's Pulmonary Diseases and Disorders \u2014 Chest imaging & staging, BAL findings",
"Grainger & Allison's Diagnostic Radiology \u2014 Scadding staging system",
"Bechman K, Biddle K, Miracle A, et al. Systematic review and meta-analysis of the efficacy of biologic and targeted synthetic therapies in sarcoidosis. Thorax. 2025. PMID: 40393718",
"Bouadi N, Rijal H, Sood S, et al. Use of Biologics for Cutaneous Sarcoidosis: A Systematic Review. J Cutan Med Surg. 2024. PMID: 38404164",
]
add_bullets(s, Inches(0.7), Inches(1.5), Inches(11.8), Inches(5.3), refs, size=13.5, space_after=12)
prs.save("/tmp/workspace/sarcoidosis-ppt/Sarcoidosis_Registrar_Teaching.pptx")
print("Saved.")
print("Slides:", len(prs.slides.__iter__.__self__._sldIdLst))
cd /tmp/workspace/sarcoidosis-ppt && python build_ppt.py
~/sarcoidosis-ppt/build_ppt.py
Successfully replaced 1 instance(s) of the string in '/tmp/workspace/sarcoidosis-ppt/build_ppt.py'
cd /tmp/workspace/sarcoidosis-ppt && python build_ppt.py
cd /tmp/workspace/sarcoidosis-ppt/assets && python -c " from PIL import Image import os for f in ['granuloma.jpg','skin_lesions1.jpg','skin_lesions2.jpg']: im = Image.open(f) print(f, im.format, im.mode) rgb = im.convert('RGB') newname = f.rsplit('.',1)[0] + '_fixed.jpg' rgb.save(newname, 'JPEG', quality=90) print('saved', newname) " ls -la /tmp/workspace/sarcoidosis-ppt/assets
~/sarcoidosis-ppt/build_ppt.py
Successfully replaced 1 instance(s) of the string in '/tmp/workspace/sarcoidosis-ppt/build_ppt.py'
~/sarcoidosis-ppt/build_ppt.py
Successfully replaced 1 instance(s) of the string in '/tmp/workspace/sarcoidosis-ppt/build_ppt.py'
cd /tmp/workspace/sarcoidosis-ppt && python build_ppt.py
ls -la /tmp/workspace/sarcoidosis-ppt/*.pptx
Sarcoidosis Registrar Teaching
Presentation · PPTX
add newer drugs for treatment and clinical trials
efzofitimod sarcoidosis
sarcoidosis JAK inhibitor
pulmonary sarcoidosis novel therapeutics trial
sarcoidosis new drug clinical trial 2025 2026 efzofitimod phase 3
sarcoidosis emerging therapies pipeline 2026
~/sarcoidosis-ppt/build_ppt.py
Successfully replaced 1 instance(s) of the string in '/tmp/workspace/sarcoidosis-ppt/build_ppt.py'
~/sarcoidosis-ppt/build_ppt.py
Successfully replaced 1 instance(s) of the string in '/tmp/workspace/sarcoidosis-ppt/build_ppt.py'
~/sarcoidosis-ppt/build_ppt.py
Successfully replaced 1 instance(s) of the string in '/tmp/workspace/sarcoidosis-ppt/build_ppt.py'
~/sarcoidosis-ppt/build_ppt.py
Successfully replaced 1 instance(s) of the string in '/tmp/workspace/sarcoidosis-ppt/build_ppt.py'
cd /tmp/workspace/sarcoidosis-ppt && python build_ppt.py && ls -la *.pptx
Sarcoidosis Registrar Teaching
Presentation · PPTX