Face bone

Reading File
Finding Sources
Finding Sources
Reading File
Reading File
Loading Image
Loading Image
Finding Sources
Here is a complete overview of the bones of the face (the facial skeleton / viscerocranium), drawn from Rosen's Emergency Medicine and Langman's Medical Embryology.

Bones of the Face

Bones of the facial skeleton - lateral view
Fig. 34.1 - Rosen's Emergency Medicine: Bones of the facial skeleton

Skeletal structures of the head and face showing neural crest vs mesoderm origins
Fig. 10.4 - Langman's Medical Embryology: Skeletal structures of the head and face (blue = neural crest origin, red = paraxial mesoderm)

The 14 Facial Bones

The skull has 22 bones total: 8 cranial (neurocranium) + 14 facial (viscerocranium).
#BoneCountKey Features
1Mandible1Only movable skull bone; lower jaw; has condyle, coronoid process, and angle
2Maxilla2 (paired)Upper jaw; forms anterior hard palate, floor of orbit, lateral nasal wall; bears upper teeth
3Zygomatic (Zygoma / Cheekbone)2 (paired)Forms cheek prominence, lateral orbital wall and floor; articulates with temporal bone via zygomatic arch
4Nasal2 (paired)Bridge of the nose
5Lacrimal2 (paired)Smallest facial bones; medial orbital wall; contains lacrimal fossa for tear drainage
6Palatine2 (paired)Posterior hard palate; contributes to floor of orbit and lateral nasal wall
7Inferior nasal concha2 (paired)Scroll-shaped; project into nasal cavity as turbinates (increase surface area for air conditioning)
8Vomer1Flat bone forming the lower/posterior nasal septum

Deeper Bones That Support the Face

These lie deeper but are integral to facial structure (they are technically cranial bones that contribute to facial support):
  • Frontal bone - forms the forehead and roof of the orbits; considered part of the anterior facial skeleton
  • Ethmoid - forms the roof of the nasal cavity (cribriform plate), part of the medial orbital wall, and the upper nasal septum (perpendicular plate)
  • Sphenoid - forms the lateral orbital wall (greater wing) and provides muscular attachment points
  • Temporal bone - contributes to the zygomatic arch; houses the ear structures

The Bony Orbit (composed of 7 bones)

The eye socket is a good example of how multiple bones collaborate:
WallBone(s)
RoofFrontal bone
Lateral wall + lateral floorZygomatic bone
Medial floor + anteromedial wallMaxilla
Medial wallLacrimal + Ethmoid (most fragile - "blowout" fractures occur here)

Key Clinical Points

  • Mandible - the only mobile facial bone; moves at the temporomandibular joint (TMJ)
  • "Blow-out" fracture - occurs at the medial orbital wall (ethmoid/lacrimal) or orbital floor (maxilla), the weakest areas
  • LeFort fractures - classic patterns of midface fracture involving the maxilla, zygomatic, and nasal bones:
    • LeFort I: horizontal fracture through maxilla (floating palate)
    • LeFort II: pyramidal fracture separating midface
    • LeFort III: craniofacial disjunction - separates entire face from skull base
  • Nasal bones - most commonly fractured facial bones
  • Embryologically, facial bones are derived mostly from neural crest cells (shown in blue in Fig. 10.4 above)

Sources: Rosen's Emergency Medicine, Bones section; Langman's Medical Embryology, SKULL chapter

Tumours osteosarcoma seminar

Asking for Preferences
Reading File
Finding Sources
Reading File
Reading File
Reading File
Reading File
Reading File
Reading File
Loading Image
Loading Image
Loading Image
Reading File
Running Command

mkdir -p /tmp/workspace/osteosarcoma-seminar && ls /tmp/workspace/osteosarcoma-seminar/

Writing File

~/osteosarcoma-seminar/build_pptx.py

import json, subprocess, base64, sys
from io import BytesIO
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.oxml.ns import qn
from lxml import etree

# ── Colours ──────────────────────────────────────────────────────────────
DARK_BLUE   = RGBColor(0x1A, 0x37, 0x6C)   # deep navy
MID_BLUE    = RGBColor(0x2E, 0x6D, 0xB4)   # accent blue
LIGHT_BLUE  = RGBColor(0xD6, 0xE8, 0xF7)   # slide background tint
RED_ACCENT  = RGBColor(0xC0, 0x39, 0x2B)   # highlight
WHITE       = RGBColor(0xFF, 0xFF, 0xFF)
DARK_GREY   = RGBColor(0x2C, 0x2C, 0x2C)
MID_GREY    = RGBColor(0x55, 0x55, 0x55)
LIGHT_GREY  = RGBColor(0xF2, 0xF4, 0xF7)

# ── Helper utilities ──────────────────────────────────────────────────────
def add_rect(slide, l, t, w, h, fill_rgb=None, line_rgb=None, line_width_pt=0):
    shape = slide.shapes.add_shape(1, Inches(l), Inches(t), Inches(w), Inches(h))
    shape.line.fill.background()
    if fill_rgb:
        shape.fill.solid()
        shape.fill.fore_color.rgb = fill_rgb
    else:
        shape.fill.background()
    if line_rgb and line_width_pt:
        shape.line.color.rgb = line_rgb
        shape.line.width = Pt(line_width_pt)
    else:
        shape.line.fill.background()
    return shape

def add_tb(slide, l, t, w, h, text, size, bold=False, color=DARK_GREY,
           align=PP_ALIGN.LEFT, wrap=True, italic=False, font="Calibri"):
    tb = slide.shapes.add_textbox(Inches(l), Inches(t), Inches(w), Inches(h))
    tf = tb.text_frame
    tf.word_wrap = wrap
    tf.margin_left = 0; tf.margin_right = 0
    tf.margin_top = 0;  tf.margin_bottom = 0
    p = tf.paragraphs[0]
    p.alignment = align
    run = p.add_run()
    run.text = text
    run.font.name = font
    run.font.size = Pt(size)
    run.font.bold = bold
    run.font.italic = italic
    run.font.color.rgb = color
    return tf

def add_bullet_tf(slide, l, t, w, h, items, size=13, color=DARK_GREY,
                  bold_first=False, font="Calibri", line_space=1.15):
    tb = slide.shapes.add_textbox(Inches(l), Inches(t), Inches(w), Inches(h))
    tf = tb.text_frame
    tf.word_wrap = True
    tf.margin_left = 0; tf.margin_right = 0
    tf.margin_top = 0;  tf.margin_bottom = 0
    from pptx.oxml.ns import qn
    from lxml import etree
    for i, item in enumerate(items):
        if i == 0:
            p = tf.paragraphs[0]
        else:
            p = tf.add_paragraph()
        # line spacing
        pPr = p._pPr
        if pPr is None:
            pPr = p._p.get_or_add_pPr()
        lnSpc = etree.SubElement(pPr, qn('a:lnSpc'))
        spcPct = etree.SubElement(lnSpc, qn('a:spcPct'))
        spcPct.set('val', str(int(line_space * 100000)))
        spcBef = etree.SubElement(pPr, qn('a:spcBef'))
        spcPts = etree.SubElement(spcBef, qn('a:spcPts'))
        spcPts.set('val', '800')

        run = p.add_run()
        if isinstance(item, tuple):
            bullet, text = item
        else:
            bullet, text = "•  ", item
        run.text = bullet + text
        run.font.name = font
        run.font.size = Pt(size)
        run.font.color.rgb = color
        run.font.bold = (i == 0 and bold_first)
    return tf

def fetch_images(urls):
    result = json.loads(subprocess.check_output(
        ["python", "/tmp/skills/shared/scripts/fetch_images.py"] + urls
    ))
    return result

def add_image_from_b64(slide, b64_str, l, t, w, h=None):
    raw = base64.b64decode(b64_str.split(',')[1] if ',' in b64_str else b64_str)
    buf = BytesIO(raw)
    if h:
        slide.shapes.add_picture(buf, Inches(l), Inches(t), Inches(w), Inches(h))
    else:
        slide.shapes.add_picture(buf, Inches(l), Inches(t), Inches(w))

# ── Fetch all images ──────────────────────────────────────────────────────
IMAGE_URLS = [
    "https://cdn.orris.care/cdss_images/393983627f910dbe2890e4171c6754c66b496a5b5bb49f34427b6303fced4c9a.png",   # 0 X-ray Codman triangle
    "https://cdn.orris.care/cdss_images/67d666f1c3d7c28aaef14dc5976c9abb955d31bb18ec7afbac8b996a2f8e8fc6.png",   # 1 gross specimen
    "https://cdn.orris.care/cdss_images/825ac63da1176854cfe0feab96138b8c8893240b7088f04166856fa60ded9702.png",   # 2 histology
    "https://cdn.orris.care/cdss_images/6f23f9305fb931f4bfc24c17ee2e15f3095932325f0d0c8655f7628ab82b2ad5.png",   # 3 lytic/sclerotic X-rays
]
print("Fetching images...")
imgs = fetch_images(IMAGE_URLS)
print("Images fetched:", [bool(i["base64"]) for i in imgs])

# ── Presentation setup ────────────────────────────────────────────────────
prs = Presentation()
prs.slide_width  = Inches(13.333)
prs.slide_height = Inches(7.5)
blank = prs.slide_layouts[6]

# ═══════════════════════════════════════════════════════════════════════════
# SLIDE 1 – Title Slide
# ═══════════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
add_rect(s, 0, 0, 13.333, 7.5, DARK_BLUE)            # full bg
add_rect(s, 0, 5.5, 13.333, 2.0, MID_BLUE)            # lower bar
add_rect(s, 0.55, 1.6, 0.07, 3.5, RED_ACCENT)         # vertical accent line

add_tb(s, 0.9, 1.4, 11.5, 1.1, "OSTEOSARCOMA", 54, bold=True,
       color=WHITE, align=PP_ALIGN.LEFT, font="Calibri")
add_tb(s, 0.9, 2.55, 11, 0.7, "Primary Malignant Bone Tumour — A Seminar", 22,
       color=RGBColor(0xAD, 0xD4, 0xF0), align=PP_ALIGN.LEFT, italic=True)

add_tb(s, 0.9, 5.7, 9, 0.5, "Department of Orthopaedics / Pathology", 15,
       color=WHITE, align=PP_ALIGN.LEFT)
add_tb(s, 0.9, 6.15, 9, 0.4, "Undergraduate MBBS Seminar  |  July 2026", 13,
       color=RGBColor(0xAD, 0xD4, 0xF0), align=PP_ALIGN.LEFT)

# ═══════════════════════════════════════════════════════════════════════════
# SLIDE 2 – Overview / Contents
# ═══════════════════════════════════════════════════════════════════════════
def slide_header(slide, title, subtitle=""):
    add_rect(slide, 0, 0, 13.333, 1.15, DARK_BLUE)
    add_rect(slide, 0, 1.15, 13.333, 0.06, MID_BLUE)
    add_tb(slide, 0.45, 0.17, 12, 0.75, title, 28, bold=True,
           color=WHITE, align=PP_ALIGN.LEFT)
    if subtitle:
        add_tb(slide, 0.45, 0.82, 12, 0.38, subtitle, 13,
               color=RGBColor(0xAD, 0xD4, 0xF0), align=PP_ALIGN.LEFT, italic=True)

s = prs.slides.add_slide(blank)
add_rect(s, 0, 0, 13.333, 7.5, LIGHT_GREY)
slide_header(s, "Outline of Seminar")

topics = [
    ("01", "Definition & Introduction"),
    ("02", "Epidemiology & Risk Factors"),
    ("03", "Classification (WHO 2013)"),
    ("04", "Pathogenesis & Molecular Genetics"),
    ("05", "Clinical Features"),
    ("06", "Radiological Features"),
    ("07", "Pathology (Gross & Histology)"),
    ("08", "Diagnosis & Staging"),
    ("09", "Treatment"),
    ("10", "Prognosis & Complications"),
]
col1 = topics[:5]
col2 = topics[5:]

for i, (num, topic) in enumerate(col1):
    y = 1.5 + i * 0.98
    add_rect(s, 0.5, y, 0.55, 0.62, MID_BLUE)
    add_tb(s, 0.5, y+0.08, 0.55, 0.5, num, 18, bold=True, color=WHITE, align=PP_ALIGN.CENTER)
    add_rect(s, 1.15, y, 5.5, 0.62, WHITE)
    add_tb(s, 1.3, y+0.1, 5.2, 0.45, topic, 14, color=DARK_BLUE)

for i, (num, topic) in enumerate(col2):
    y = 1.5 + i * 0.98
    add_rect(s, 7.0, y, 0.55, 0.62, MID_BLUE)
    add_tb(s, 7.0, y+0.08, 0.55, 0.5, num, 18, bold=True, color=WHITE, align=PP_ALIGN.CENTER)
    add_rect(s, 7.65, y, 5.3, 0.62, WHITE)
    add_tb(s, 7.8, y+0.1, 5.1, 0.45, topic, 14, color=DARK_BLUE)

# ═══════════════════════════════════════════════════════════════════════════
# SLIDE 3 – Definition & Introduction
# ═══════════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
add_rect(s, 0, 0, 13.333, 7.5, LIGHT_GREY)
slide_header(s, "Definition & Introduction")

add_rect(s, 0.45, 1.45, 12.4, 1.5, WHITE)
add_tb(s, 0.65, 1.6, 12, 1.2,
       "Osteosarcoma is a malignant tumour of bone in which the tumour cells form neoplastic "
       "osteoid, bone, or both. It is the most common primary malignant bone tumour, excluding "
       "haematopoietic tumours (e.g. multiple myeloma).",
       14, color=DARK_GREY, wrap=True)

bullets = [
    "Most common non-haematological primary bone malignancy",
    "Tumour cells directly produce osteoid / bone matrix — the diagnostic hallmark",
    "High-grade intramedullary lesion in 75% of all cases (conventional type)",
    "All osteosarcomas are assumed to have occult micrometastases at time of diagnosis",
    "5-year survival ~70% (no metastasis) with modern chemotherapy + surgery",
]
add_bullet_tf(s, 0.65, 3.15, 12, 3.8, bullets, size=13.5, color=DARK_GREY)

# ═══════════════════════════════════════════════════════════════════════════
# SLIDE 4 – Epidemiology
# ═══════════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
add_rect(s, 0, 0, 13.333, 7.5, LIGHT_GREY)
slide_header(s, "Epidemiology & Risk Factors")

# Left panel - Epidemiology
add_rect(s, 0.45, 1.4, 5.9, 5.6, WHITE)
add_tb(s, 0.65, 1.55, 5.6, 0.5, "Epidemiology", 16, bold=True, color=DARK_BLUE)
epi_bullets = [
    "Incidence: ~4 per million population/year",
    "Bimodal age distribution:",
    "   Peak 1 — Adolescents 10–20 yrs (75% of cases)",
    "   Peak 2 — Older adults (secondary OSA)",
    "Male > Female (ratio 1.35–1.6 : 1)",
    "Peak coincides with adolescent growth spurt",
    "Almost 50%–75% occur near the knee",
    "   (distal femur or proximal tibia)",
]
add_bullet_tf(s, 0.65, 2.1, 5.6, 4.7, epi_bullets, size=12.5, color=DARK_GREY)

# Right panel - Risk factors
add_rect(s, 6.9, 1.4, 6.0, 5.6, WHITE)
add_tb(s, 7.1, 1.55, 5.7, 0.5, "Risk Factors / Associations", 16, bold=True, color=DARK_BLUE)
rf_bullets = [
    ("⚑  ", "Paget disease of bone"),
    ("⚑  ", "Previous radiation therapy"),
    ("⚑  ", "Bone infarcts"),
    ("⚑  ", "Li-Fraumeni syndrome (TP53 germline)"),
    ("⚑  ", "Familial retinoblastoma (RB1 germline)"),
    ("⚑  ", "Rothmund-Thomson syndrome"),
    ("⚑  ", "Fibrous dysplasia"),
    ("⚑  ", "Bone infarction / osteonecrosis"),
    ("⚑  ", "Prior low-grade sarcoma dedifferentiation"),
]
add_bullet_tf(s, 7.1, 2.1, 5.7, 4.7, rf_bullets, size=12.5, color=DARK_GREY)

# ═══════════════════════════════════════════════════════════════════════════
# SLIDE 5 – WHO Classification
# ═══════════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
add_rect(s, 0, 0, 13.333, 7.5, LIGHT_GREY)
slide_header(s, "Classification of Osteosarcoma", "WHO 2013 — Seven Categories")

types = [
    ("1", "Conventional Osteosarcoma", "75% of all cases. High-grade intramedullary. Osteoblastic, chondroblastic or fibroblastic subtypes.", MID_BLUE),
    ("2", "Telangiectatic Osteosarcoma", "Blood-filled cavities. May mimic ABC on X-ray. High-grade.", DARK_BLUE),
    ("3", "Low-Grade Central OSA", "Resembles fibrous dysplasia. Well-differentiated. Better prognosis.", RGBColor(0x27, 0xAE, 0x60)),
    ("4", "Small Cell Osteosarcoma", "Resembles Ewing sarcoma. Small round blue cells + osteoid.", RED_ACCENT),
    ("5", "Parosteal Osteosarcoma", "Surface lesion, posterior distal femur. Low-grade. Best prognosis.", RGBColor(0x84, 0x44, 0xAD)),
    ("6", "Periosteal Osteosarcoma", "Surface, intermediate grade. Chondroblastic variant.", RGBColor(0x16, 0xA0, 0x85)),
    ("7", "High-Grade Surface OSA", "Rare. Surface location but high-grade histology.", RGBColor(0xD3, 0x5A, 0x00)),
]

for i, (num, name, desc, col) in enumerate(types):
    row = i % 4
    col_idx = i // 4
    x = 0.45 + col_idx * 6.55
    y = 1.5 + row * 1.45
    add_rect(s, x, y, 6.1, 1.3, WHITE)
    add_rect(s, x, y, 0.45, 1.3, col)
    add_tb(s, x+0.02, y+0.3, 0.45, 0.7, num, 18, bold=True, color=WHITE, align=PP_ALIGN.CENTER)
    add_tb(s, x+0.6, y+0.07, 5.3, 0.45, name, 13, bold=True, color=col)
    add_tb(s, x+0.6, y+0.52, 5.3, 0.72, desc, 11, color=DARK_GREY, wrap=True)

# ═══════════════════════════════════════════════════════════════════════════
# SLIDE 6 – Pathogenesis & Molecular Genetics
# ═══════════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
add_rect(s, 0, 0, 13.333, 7.5, LIGHT_GREY)
slide_header(s, "Pathogenesis & Molecular Genetics")

add_tb(s, 0.5, 1.35, 12.5, 0.4,
       "Peak incidence during adolescent growth spurt — rapidly proliferating metaphyseal cells prone to mutations",
       13, italic=True, color=MID_GREY)

genes = [
    ("RB1", "Retinoblastoma gene", "Mutated in up to 70% of sporadic OSA\nGermline RB1 mutations increase risk 1000-fold", MID_BLUE),
    ("TP53", "Tumour suppressor", "Mutated in Li-Fraumeni syndrome\nCommon in sporadic tumours", RED_ACCENT),
    ("MDM2/CDK4", "Oncogenes", "Overexpressed in low-grade OSA\nInhibit p53 and RB function respectively", RGBColor(0x27, 0xAE, 0x60)),
    ("CDKN2A", "INK4a locus", "Encodes p16 and p14 tumour suppressors\nInactivated in many OSA", RGBColor(0xD3, 0x5A, 0x00)),
    ("MYC", "Proto-oncogene", "Amplified in up to 50% of cases\nAssociated with particularly poor prognosis", RGBColor(0x84, 0x44, 0xAD)),
]

for i, (gene, role, detail, col) in enumerate(genes):
    x = 0.45 + i * 2.55
    add_rect(s, x, 1.95, 2.3, 4.9, WHITE)
    add_rect(s, x, 1.95, 2.3, 0.65, col)
    add_tb(s, x+0.1, 2.02, 2.1, 0.5, gene, 16, bold=True, color=WHITE)
    add_tb(s, x+0.1, 2.72, 2.1, 0.45, role, 11, bold=True, color=col)
    add_tb(s, x+0.1, 3.2, 2.1, 3.5, detail, 11, color=DARK_GREY, wrap=True)

add_tb(s, 0.5, 7.0, 12.5, 0.38,
       "Note: Complex karyotypes with numerous chromosomal aberrations characterise osteosarcoma",
       12, italic=True, color=MID_GREY)

# ═══════════════════════════════════════════════════════════════════════════
# SLIDE 7 – Clinical Features
# ═══════════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
add_rect(s, 0, 0, 13.333, 7.5, LIGHT_GREY)
slide_header(s, "Clinical Features")

# Symptoms
add_rect(s, 0.45, 1.4, 5.9, 2.75, WHITE)
add_tb(s, 0.65, 1.52, 5.6, 0.42, "Symptoms", 15, bold=True, color=DARK_BLUE)
syms = [
    "Pain — most common presenting complaint",
    "Progressively enlarging painful mass",
    "Night pain (characteristic)",
    "Pathological fracture (first presentation in some)",
    "Neurological symptoms (70% in spinal OSA)",
]
add_bullet_tf(s, 0.65, 2.0, 5.6, 2.0, syms, size=12.5)

# Sites
add_rect(s, 0.45, 4.3, 5.9, 2.75, WHITE)
add_tb(s, 0.65, 4.42, 5.6, 0.42, "Common Sites", 15, bold=True, color=DARK_BLUE)
sites = [
    "Distal femur (most common, ~30%)",
    "Proximal tibia (~25%)",
    "Proximal humerus (~15%)",
    "50%–75% occur near the knee",
    "Rare: ilium, ribs, scapula, jaw, spine",
]
add_bullet_tf(s, 0.65, 4.85, 5.6, 2.0, sites, size=12.5)

# Signs
add_rect(s, 6.9, 1.4, 6.0, 2.75, WHITE)
add_tb(s, 7.1, 1.52, 5.7, 0.42, "Signs on Examination", 15, bold=True, color=DARK_BLUE)
signs = [
    "Hard, tender, fixed mass over metaphysis",
    "Overlying skin warm and erythematous",
    "Dilated superficial veins",
    "Limited adjacent joint movement",
    "Muscle wasting distal to tumour",
    "Lymphadenopathy (uncommon)",
]
add_bullet_tf(s, 7.1, 1.95, 5.7, 2.0, signs, size=12.5)

# Red flags
add_rect(s, 6.9, 4.3, 6.0, 2.75, WHITE)
add_rect(s, 6.9, 4.3, 6.0, 0.5, RED_ACCENT)
add_tb(s, 7.0, 4.37, 5.7, 0.42, "🚩  Red Flag Features", 15, bold=True, color=WHITE)
flags = [
    "Age 10–20 with bone pain + swelling",
    "Pain worse at rest / night",
    "Rapid progression",
    "Raised ALP and LDH (markers of activity)",
]
add_bullet_tf(s, 7.1, 4.9, 5.7, 2.0, flags, size=12.5, color=RED_ACCENT)

# ═══════════════════════════════════════════════════════════════════════════
# SLIDE 8 – Radiological Features
# ═══════════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
add_rect(s, 0, 0, 13.333, 7.5, LIGHT_GREY)
slide_header(s, "Radiological Features")

# X-ray image (Codman triangle)
if imgs[0]["base64"]:
    add_image_from_b64(s, imgs[0]["base64"], 0.45, 1.35, 4.0, 5.8)
add_tb(s, 0.45, 7.1, 4.1, 0.35,
       "X-ray: Distal femur OSA with Codman triangle (arrow)", 10, italic=True, color=MID_GREY)

# Radiology bullet points
add_rect(s, 4.9, 1.35, 8.0, 5.8, WHITE)
add_tb(s, 5.1, 1.5, 7.7, 0.45, "Plain Radiograph Findings", 16, bold=True, color=DARK_BLUE)
rad_bullets = [
    "Metaphyseal location (long bones)",
    "Mixed lytic + sclerotic pattern (most common)",
    "Entirely lytic in 13% of cases",
    "Entirely sclerotic (ivory-like) in some",
    "Cortical destruction with eccentric soft-tissue mass",
    "Periosteal reactions (pathognomonic patterns):",
    "   • Codman triangle — reactive subperiosteal bone",
    "   • Sunburst / spiculated pattern",
    "   • Onion-skin (lamellated) pattern",
    "   • Any combination may be present",
    "",
    "MRI (mandatory for staging):",
    "   • Defines tumour extent in bone & soft tissue",
    "   • Identifies skip metastases",
    "   • Neurovascular involvement",
    "   • Joint involvement",
]
add_bullet_tf(s, 5.1, 2.05, 7.7, 5.0, rad_bullets, size=12)

# ═══════════════════════════════════════════════════════════════════════════
# SLIDE 9 – Gross & Histopathology
# ═══════════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
add_rect(s, 0, 0, 13.333, 7.5, LIGHT_GREY)
slide_header(s, "Pathology — Gross & Histology")

# Gross image
if imgs[1]["base64"]:
    add_image_from_b64(s, imgs[1]["base64"], 0.45, 1.35, 3.8, 4.5)
add_tb(s, 0.45, 5.9, 3.9, 0.5,
       "Gross: Distal femur OSA — cortical disruption,\nhaemorrhage, confined to metaphysis", 10, italic=True, color=MID_GREY, wrap=True)

# Histology image
if imgs[2]["base64"]:
    add_image_from_b64(s, imgs[2]["base64"], 4.55, 1.35, 3.8, 4.5)
add_tb(s, 4.55, 5.9, 3.9, 0.5,
       "Histology: Lancelike osteoid by pleomorphic cells;\nabnormal mitotic figure (arrow)", 10, italic=True, color=MID_GREY, wrap=True)

# Text panel
add_rect(s, 8.75, 1.35, 4.15, 5.75, WHITE)
add_tb(s, 8.95, 1.5, 3.9, 0.42, "Key Pathological Features", 14, bold=True, color=DARK_BLUE)
path_bullets = [
    "Bulky, gritty, tan-white tumour",
    "Areas of haemorrhage and necrosis",
    "Intramedullary spread — replaces marrow",
    "Cortical destruction into soft tissue",
    "Rarely enters adjacent joint",
    "",
    "Histology:",
    "• Cell pleomorphism + hyperchromatic nuclei",
    "• Bizarre tumour giant cells",
    "• Abundant mitoses (incl. abnormal bipolar)",
    "• Fine lacelike or sheet-like osteoid — ESSENTIAL for Dx",
    "• Intravascular invasion common",
]
add_bullet_tf(s, 8.95, 2.0, 3.9, 5.0, path_bullets, size=11.5, color=DARK_GREY)

# ═══════════════════════════════════════════════════════════════════════════
# SLIDE 10 – Diagnosis & Staging
# ═══════════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
add_rect(s, 0, 0, 13.333, 7.5, LIGHT_GREY)
slide_header(s, "Diagnosis & Staging")

# Left
add_rect(s, 0.45, 1.4, 5.9, 5.65, WHITE)
add_tb(s, 0.65, 1.55, 5.6, 0.45, "Investigations", 15, bold=True, color=DARK_BLUE)
inv = [
    ("Lab:", "ALP ↑, LDH ↑ (activity markers); FBC; renal/liver function"),
    ("X-ray:", "First-line; classic periosteal patterns"),
    ("MRI:", "MANDATORY for local staging — whole bone"),
    ("CT chest:", "Screen for pulmonary metastases (commonest site)"),
    ("Bone scan:", "Identify skip metastases, bone metastases"),
    ("PET-CT:", "More sensitive than bone scan in paediatric sarcoma"),
    ("Biopsy:", "DEFINITIVE diagnosis — open or core needle\n(in specialist centre, along tumour axis)"),
]
y = 2.05
for label, text in inv:
    tb = s.shapes.add_textbox(Inches(0.65), Inches(y), Inches(5.6), Inches(0.7))
    tf = tb.text_frame; tf.word_wrap = True
    tf.margin_left=0; tf.margin_right=0; tf.margin_top=0; tf.margin_bottom=0
    p = tf.paragraphs[0]
    r1 = p.add_run(); r1.text = label + " "; r1.font.bold = True
    r1.font.size = Pt(12); r1.font.color.rgb = DARK_BLUE; r1.font.name = "Calibri"
    r2 = p.add_run(); r2.text = text
    r2.font.size = Pt(12); r2.font.color.rgb = DARK_GREY; r2.font.name = "Calibri"
    y += 0.72

# Right
add_rect(s, 6.9, 1.4, 6.0, 5.65, WHITE)
add_tb(s, 7.1, 1.55, 5.7, 0.45, "Staging — Enneking / MSTS System", 15, bold=True, color=DARK_BLUE)
staging = [
    ("Stage IA:", "Low-grade, intracompartmental (T1)"),
    ("Stage IB:", "Low-grade, extracompartmental (T2)"),
    ("Stage IIA:", "High-grade, intracompartmental (T1)"),
    ("Stage IIB:", "High-grade, extracompartmental (T2) — MOST OSA"),
    ("Stage III:", "Any grade with regional or distant metastasis"),
]
y2 = 2.05
for label, text in staging:
    tb = s.shapes.add_textbox(Inches(7.1), Inches(y2), Inches(5.7), Inches(0.6))
    tf = tb.text_frame; tf.word_wrap = True
    tf.margin_left=0; tf.margin_right=0; tf.margin_top=0; tf.margin_bottom=0
    p = tf.paragraphs[0]
    r1 = p.add_run(); r1.text = label + " "
    r1.font.bold = True; r1.font.size = Pt(12); r1.font.color.rgb = MID_BLUE; r1.font.name = "Calibri"
    r2 = p.add_run(); r2.text = text
    r2.font.size = Pt(12); r2.font.color.rgb = DARK_GREY; r2.font.name = "Calibri"
    y2 += 0.68

add_rect(s, 6.9, 5.4, 6.0, 1.65, LIGHT_BLUE)
add_tb(s, 7.1, 5.5, 5.7, 1.4,
       "Biopsy is the gold standard for diagnosis.\n"
       "Biopsy tract must be excised en bloc with the tumour.\n"
       "Always perform in a specialist sarcoma centre.",
       12, color=DARK_BLUE, wrap=True, italic=True)

# ═══════════════════════════════════════════════════════════════════════════
# SLIDE 11 – Treatment
# ═══════════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
add_rect(s, 0, 0, 13.333, 7.5, LIGHT_GREY)
slide_header(s, "Treatment")

# Timeline bar
steps = [
    ("1\nNeoadjuvant\nChemo", MID_BLUE, "MAP protocol\n(Methotrexate,\nAdriaymcin, Cisplatin)\n8–12 weeks"),
    ("2\nSurgery", DARK_BLUE, "Limb-salvage surgery\n(preferred) or\namputation if\nneurovascular involved"),
    ("3\nHistological\nResponse", RGBColor(0x27, 0xAE, 0x60), "Assess tumour necrosis\n≥90% necrosis = good\nresponse (favourable)"),
    ("4\nAdjuvant\nChemo", MID_BLUE, "Continue MAP\n(± ifosfamide if\npoor responder)\n~12–18 weeks"),
]

for i, (step, col, detail) in enumerate(steps):
    x = 0.45 + i * 3.2
    add_rect(s, x, 1.4, 2.9, 1.0, col)
    add_tb(s, x, 1.4, 2.9, 1.0, step, 13, bold=True, color=WHITE, align=PP_ALIGN.CENTER, wrap=True)
    add_rect(s, x, 2.5, 2.9, 2.2, WHITE)
    add_tb(s, x+0.15, 2.6, 2.6, 2.0, detail, 12, color=DARK_GREY, wrap=True)
    if i < 3:
        add_tb(s, x+2.95, 1.75, 0.25, 0.5, "→", 22, bold=True, color=DARK_BLUE, align=PP_ALIGN.CENTER)

# Surgery details
add_rect(s, 0.45, 4.9, 12.45, 2.3, WHITE)
add_tb(s, 0.65, 5.05, 12, 0.4, "Surgical Principles", 15, bold=True, color=DARK_BLUE)
surg = [
    "Limb-salvage surgery (LSS) is now possible in ~85–90% of cases due to effective neoadjuvant chemotherapy",
    "Wide margin excision (en bloc) with reconstruction: endoprosthesis, allograft, or rotationplasty",
    "Amputation: reserved for unresectable cases or where LSS compromises oncological outcome",
    "Radiation therapy: limited role (OSA is relatively radio-resistant); used for unresectable spinal or pelvic lesions",
]
add_bullet_tf(s, 0.65, 5.5, 12, 1.6, surg, size=12)

# ═══════════════════════════════════════════════════════════════════════════
# SLIDE 12 – Prognosis & Complications
# ═══════════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
add_rect(s, 0, 0, 13.333, 7.5, LIGHT_GREY)
slide_header(s, "Prognosis & Complications")

# Prognosis boxes
prog_data = [
    ("~70%", "5-year survival\n(no metastasis)", MID_BLUE),
    ("<30%", "5-year survival\n(with metastasis)", RED_ACCENT),
    ("≥90%", "Tumour necrosis\n= good response", RGBColor(0x27, 0xAE, 0x60)),
    ("~20%", "5-year survival\nspinal OSA", RGBColor(0xD3, 0x5A, 0x00)),
]
for i, (val, label, col) in enumerate(prog_data):
    x = 0.45 + i * 3.22
    add_rect(s, x, 1.4, 2.9, 1.5, col)
    add_tb(s, x, 1.55, 2.9, 0.85, val, 38, bold=True, color=WHITE, align=PP_ALIGN.CENTER)
    add_tb(s, x, 2.3, 2.9, 0.6, label, 12, color=WHITE, align=PP_ALIGN.CENTER, wrap=True)

# Prognostic factors
add_rect(s, 0.45, 3.1, 5.9, 4.05, WHITE)
add_tb(s, 0.65, 3.25, 5.6, 0.42, "Favourable Prognostic Factors", 14, bold=True, color=RGBColor(0x27, 0xAE, 0x60))
fav = [
    "Age < 40 years",
    "Distal extremity location",
    "No metastasis at diagnosis",
    "≥90% histological necrosis post-chemo",
    "Complete surgical resection (wide margins)",
    "Low ALP at diagnosis",
]
add_bullet_tf(s, 0.65, 3.75, 5.6, 3.2, fav, size=12.5, color=DARK_GREY)

add_rect(s, 6.9, 3.1, 6.0, 4.05, WHITE)
add_tb(s, 7.1, 3.25, 5.7, 0.42, "Complications & Metastases", 14, bold=True, color=RED_ACCENT)
comp = [
    "Haematogenous spread — lungs (most common)",
    "Bone metastases, brain, other sites",
    "Skip metastases (same bone, across joint)",
    "Pathological fracture",
    "Local recurrence after surgery",
    "Chemotherapy toxicity (cardiotoxicity, nephrotoxicity)",
    "Prosthesis failure / aseptic loosening",
    "Poor prognosis if clinically evident metastasis at Dx",
]
add_bullet_tf(s, 7.1, 3.75, 5.7, 3.2, comp, size=12.5, color=DARK_GREY)

# ═══════════════════════════════════════════════════════════════════════════
# SLIDE 13 – Differential Diagnosis
# ═══════════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
add_rect(s, 0, 0, 13.333, 7.5, LIGHT_GREY)
slide_header(s, "Differential Diagnosis")

diffs = [
    ("Ewing Sarcoma", "Age 10–20; diaphysis; 'onion skin' periosteal reaction;\nsmall round blue cells on histology; no osteoid", MID_BLUE),
    ("Chondrosarcoma", "Adults >40; lytic with rings & arcs calcification;\ncartilage matrix; low to intermediate grade", DARK_BLUE),
    ("Giant Cell Tumour", "Age 20–40; epiphysis; soap-bubble lytic lesion;\nno matrix; osteoclast-like giant cells", RGBColor(0x27, 0xAE, 0x60)),
    ("Osteoid Osteoma", "Age 10–30; diaphysis; nocturnal pain relieved by aspirin;\nnidus <2 cm; reactive sclerosis; benign", RGBColor(0xD3, 0x5A, 0x00)),
    ("Metastatic Bone Disease", "Adults >40; multiple lesions; known primary elsewhere;\nlytic (most) or sclerotic (prostate, breast)", RED_ACCENT),
    ("Aneurysmal Bone Cyst", "Any age; expansile lytic; fluid-fluid levels on MRI;\ncan mimic telangiectatic OSA; benign", RGBColor(0x84, 0x44, 0xAD)),
]

for i, (name, desc, col) in enumerate(diffs):
    row = i % 3
    ci = i // 3
    x = 0.45 + ci * 6.55
    y = 1.4 + row * 1.9
    add_rect(s, x, y, 6.1, 1.75, WHITE)
    add_rect(s, x, y, 0.1, 1.75, col)
    add_tb(s, x+0.25, y+0.12, 5.7, 0.45, name, 14, bold=True, color=col)
    add_tb(s, x+0.25, y+0.57, 5.7, 1.1, desc, 12, color=DARK_GREY, wrap=True)

# ═══════════════════════════════════════════════════════════════════════════
# SLIDE 14 – Summary
# ═══════════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
add_rect(s, 0, 0, 13.333, 7.5, DARK_BLUE)
add_rect(s, 0, 5.5, 13.333, 2.0, MID_BLUE)
add_rect(s, 0.55, 1.6, 0.07, 3.5, RED_ACCENT)

add_tb(s, 0.9, 1.35, 11.5, 0.8, "Key Take-Home Points", 30, bold=True,
       color=WHITE, align=PP_ALIGN.LEFT)

summary = [
    "Most common primary malignant bone tumour (excl. haematological)",
    "Bimodal age: adolescent peak (10–20 yrs) + older adults (secondary OSA)",
    "Metaphysis of long bones around the knee in 50–75% of cases",
    "Diagnostic hallmark: malignant cells producing osteoid / bone matrix",
    "Classic X-ray: mixed lytic-sclerotic, Codman triangle, sunburst periosteal reaction",
    "Treatment: Neoadjuvant chemo → Limb-salvage surgery → Adjuvant chemo (MAP)",
    "5-year survival ~70% without metastasis; <30% with metastasis",
    "Lungs are the most common site of distant metastasis",
]
for i, point in enumerate(summary):
    add_tb(s, 1.05, 2.35 + i * 0.59, 11.5, 0.55,
           f"  ✓  {point}", 13, color=WHITE if i % 2 == 0 else RGBColor(0xAD, 0xD4, 0xF0),
           wrap=True)

add_tb(s, 0.9, 5.7, 9, 0.5, "Sources: Robbins & Kumar Basic Pathology | Grainger & Allison Diagnostic Radiology | Campbell's Operative Orthopaedics 2026", 11,
       color=WHITE, align=PP_ALIGN.LEFT, italic=True)

# ── Save ──────────────────────────────────────────────────────────────────
out = "/tmp/workspace/osteosarcoma-seminar/Osteosarcoma_Seminar_MBBS.pptx"
prs.save(out)
print(f"Saved: {out}")
Running Command

cd /tmp/workspace/osteosarcoma-seminar && python build_pptx.py 2>&1

Running Command

find /tmp/skills -name "fetch_images.py" 2>/dev/null; ls /tmp/skills/

Editing File

~/osteosarcoma-seminar/build_pptx.py

Successfully replaced 1 instance(s) of the string in '/tmp/workspace/osteosarcoma-seminar/build_pptx.py'
Editing File

~/osteosarcoma-seminar/build_pptx.py

Successfully replaced 1 instance(s) of the string in '/tmp/workspace/osteosarcoma-seminar/build_pptx.py'
Running Command

cd /tmp/workspace/osteosarcoma-seminar && python build_pptx.py 2>&1

Running Command

ls -lh /tmp/workspace/osteosarcoma-seminar/Osteosarcoma_Seminar_MBBS.pptx

Your Osteosarcoma seminar presentation is ready (1.3 MB, 14 slides):

Osteosarcoma Seminar MBBS

Presentation · PPTX


What's Inside — 14 Slides

SlideContent
1Title slide — navy/blue professional design
2Seminar outline — 10 topics with numbered boxes
3Definition & Introduction — what is osteosarcoma, key facts
4Epidemiology & Risk Factors — incidence, bimodal age, associations (Paget, radiation, Li-Fraumeni, RB)
5WHO 2013 Classification — all 7 types with descriptions (conventional to high-grade surface)
6Pathogenesis & Molecular Genetics — RB1, TP53, MDM2, CDK4, CDKN2A, MYC in colour-coded gene cards
7Clinical Features — symptoms, signs, common sites, red flags
8Radiological Features — X-ray showing Codman triangle (real textbook image), periosteal patterns, MRI role
9Gross & Histopathology — real gross specimen photo + H&E histology image with key features
10Diagnosis & Staging — investigations (ALP, MRI, CT chest, biopsy) + Enneking staging
11Treatment — MAP chemotherapy → limb salvage surgery → adjuvant chemo timeline
12Prognosis & Complications — survival statistics, prognostic factors, metastasis
13Differential Diagnosis — Ewing sarcoma, chondrosarcoma, GCT, OO, metastases, ABC
14Summary — 8 take-home points
Sources: Robbins & Kumar Basic Pathology, Grainger & Allison Diagnostic Radiology, Campbell's Operative Orthopaedics 15th Ed (2026)

Face muscle

Finding Sources
Finding Sources
Reading File
Reading File
Reading File
Loading Image
Loading Image
Reading File
Excellent - I have rich content and two great anatomical diagrams. Here is the full breakdown:

Muscles of the Face

The face has two major functional groups of muscles:
  1. Muscles of Facial Expression - innervated by CN VII (Facial nerve); arise from the 2nd branchial arch; insert into skin
  2. Muscles of Mastication - innervated by CN V3 (Mandibular division of Trigeminal nerve)

Anterior View

Muscles of Facial Expression - Anterior View (Netter's Atlas)
Netter's Atlas of Human Anatomy - Muscles of Facial Expression, Anterior View

Lateral View

Muscles of Facial Expression - Lateral View (Netter's Atlas)
Netter's Atlas of Human Anatomy - Muscles of Facial Expression, Lateral View

Group 1: Muscles of Facial Expression (CN VII)

All arise from the 2nd branchial arch, are innervated by CN VII, and insert into skin (not bone). They are arranged around the orifices of the face and coordinated through the SMAS (Superficial MusculoAponeurotic System).

Forehead & Scalp Region

MuscleCN VII BranchActionClinical Effect if Lost
Frontalis (part of epicranius)TemporalRaises eyebrows; horizontal forehead linesCannot raise brow; forehead lines flatten
Corrugator superciliiTemporalDraws brows medially & downward ("scowl")Difficulty frowning/scowling
ProcerusZygomaticShortens nose; "bunny lines" with nasalisLoss of bunny lines on nose bridge

Eye Region (Periorbital)

MuscleCN VII BranchActionClinical Effect if Lost
Orbicularis oculi (orbital part)TemporalTight voluntary eye closureInability to close eye tightly - risk of corneal damage
Orbicularis oculi (palpebral part)Temporal/ZygomaticGentle closure, blinking, tear drainageLagophthalmos, ectropion
Auricularis anterior & superiorTemporalDraws temporal skin backMinimal functional loss
Auricularis posteriorPosterior auricularDraws temporal skin backMinimal functional loss

Nose Region

MuscleCN VII BranchAction
Nasalis (transverse part)ZygomaticCompresses nostrils
Nasalis (alar part)ZygomaticFlares nostrils
Depressor septi nasiBuccalPulls columella toward lip; depresses nasal tip

Mouth & Cheek Region (most complex group)

MuscleCN VII BranchActionClinical Effect if Lost
Orbicularis orisBuccal & Marginal mandibularCloses & purses lips; sphincter of mouthCannot close lips; difficulty speaking, eating
Zygomaticus majorZygomatic & BuccalElevates & retracts mouth corners (smile)Difficulty smiling
Zygomaticus minorBuccalElevates upper lipAltered smile
Levator labii superiorisBuccalElevates upper lipLoss of nasolabial fold
Levator labii superioris alaeque nasiBuccalElevates lip + flares nostril-
Levator anguli orisZygomatic & BuccalElevates angle of mouthDrooping of mouth angle
BuccinatorBuccalCompresses cheek against teeth; prevents food pocketing; aids whistlingFood collects in cheek; cannot whistle
RisoriusBuccal / Marginal mandibularRetracts angle of mouth (grin)Asymmetric smile
Depressor anguli orisMarginal mandibularDepresses angle of mouthLip droops upward
Depressor labii inferiorisMarginal mandibularDepresses & everts lower lipLower lip held too high
MentalisMarginal mandibularElevates & protrudes lower lip; wrinkles chin skin"Witches chin" deformity
PlatysmaCervical branchDepresses mandible; tightens neck skinLoss of neck skin tension

Group 2: Muscles of Mastication (CN V3)

These move the mandible and are used for chewing. They arise from the 1st branchial arch.
MuscleActionNotes
MasseterElevation + protrusion of mandibleMost powerful jaw closer; palpable on biting
TemporalisElevation + retraction of mandibleFan-shaped; fills temporal fossa
Medial pterygoidElevation of mandibleWorks with masseter to form a "sling"
Lateral pterygoid (superior head)Elevation + protrusionOnly masticatory muscle active during closing
Lateral pterygoid (inferior head)Depression + lateral displacement of mandibleOpens jaw; protrudes chin
Digastric (anterior belly)Depression + retraction of mandibleAlso a suprahyoid muscle
MylohyoidDepression of mandibleForms floor of mouth
GeniohyoidDepression of mandibleInnervated by C1 via CN XII (not CN V3)

Key Clinical Pearls

PointDetail
SMAS layerConnects facial muscles into a coordinated unit; key landmark in facelifts and parotid surgery
Bell's palsyLMN CN VII palsy - all ipsilateral muscles paralysed (forehead + lower face); brow cannot be raised
UMN facial palsy (stroke)Spares the upper face (forehead) because frontalis has bilateral cortical representation
Wrinkle linesPerpendicular to muscle fiber direction - useful for elliptical incision planning
BuccinatorUnique - it is a muscle of facial expression but also functions in mastication (keeps food between teeth)
Parotid glandLies superficial to masseter; facial nerve branches fan out through it to reach expression muscles

Sources: Netter's Atlas of Human Anatomy; Dermatology 5th ed (Dermatology 2-Volume Set); Cummings Otolaryngology Head and Neck Surgery
This is a shared conversation. Sign in to Orris to start your own chat.