Prepare a journal club presentation for a pathology post graduate residents based on the attached pdf article

Reading File
Running Command

cd /tmp/workspace/attachments/36bd92b2-b42c-4d43-a42e-66cfca836c44/ && ls -la && python3 -c " import pdfplumber with pdfplumber.open('DOC-20260814-WA0028.pdf') as pdf: print('pages:', len(pdf.pages)) for i, page in enumerate(pdf.pages): text = page.extract_text() print('--- PAGE', i+1, '---') print(text) "

Reading File
Reading File
Running Command

mkdir -p /tmp/workspace/endometrial-journal-club/output && ls -la /tmp/workspace/

Now building the presentation script with a helper-function-based layout system.
Writing File

~/endometrial-journal-club/build_deck.py

#!/usr/bin/env python3
"""
Journal Club deck:
Endometrial Carcinoma, Grossing and Processing Issues:
Recommendations of the International Society of Gynecologic Pathologists (ISGyP)
Malpica A, et al. Int J Gynecol Pathol. 2019;38(S1):S9-S24.
"""
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
from pptx.oxml.ns import qn
import copy

# ---------- Palette ----------
NAVY = RGBColor(0x0B, 0x2E, 0x4E)
TEAL = RGBColor(0x0E, 0x6E, 0x7A)
TEAL_LIGHT = RGBColor(0xD9, 0xEE, 0xEF)
GOLD = RGBColor(0xC8, 0x9B, 0x3C)
GREY = RGBColor(0x4A, 0x4A, 0x4A)
LIGHT_GREY = RGBColor(0xF2, 0xF3, 0xF4)
WHITE = RGBColor(0xFF, 0xFF, 0xFF)
RED = RGBColor(0xA8, 0x2A, 0x2A)
DARK_TEXT = RGBColor(0x22, 0x22, 0x22)

FONT = "Calibri"

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 set_bg(slide, color=WHITE):
    bg = slide.background
    bg.fill.solid()
    bg.fill.fore_color.rgb = color


def add_rect(slide, x, y, w, h, color, line=False):
    shp = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, x, y, w, h)
    shp.fill.solid()
    shp.fill.fore_color.rgb = color
    if not line:
        shp.line.fill.background()
    else:
        shp.line.color.rgb = color
    shp.shadow.inherit = False
    return shp


def add_text(slide, x, y, w, h, text, size=18, color=DARK_TEXT, bold=False,
             italic=False, align=PP_ALIGN.LEFT, anchor=MSO_ANCHOR.TOP, font=FONT,
             line_spacing=1.0, wrap=True):
    tb = slide.shapes.add_textbox(x, y, w, h)
    tf = tb.text_frame
    tf.word_wrap = wrap
    tf.vertical_anchor = anchor
    tf.margin_left = 0
    tf.margin_right = 0
    tf.margin_top = 0
    tf.margin_bottom = 0
    lines = text.split("\n")
    for i, ln in enumerate(lines):
        p = tf.paragraphs[0] if i == 0 else tf.add_paragraph()
        p.text = ln
        p.alignment = align
        p.line_spacing = line_spacing
        for r in p.runs:
            r.font.size = Pt(size)
            r.font.color.rgb = color
            r.font.bold = bold
            r.font.italic = italic
            r.font.name = font
    return tb


def add_bullets(slide, x, y, w, h, items, size=16, color=DARK_TEXT, font=FONT,
                 space_after=8, bold_lead=False, bullet_color=TEAL, line_spacing=1.05,
                 anchor=MSO_ANCHOR.TOP):
    """items: list of (level, text) or plain strings (level 0). Use '**lead**' prefix trick optionally."""
    tb = slide.shapes.add_textbox(x, y, w, h)
    tf = tb.text_frame
    tf.word_wrap = True
    tf.vertical_anchor = anchor
    tf.margin_left = 0
    tf.margin_right = 0
    tf.margin_top = 0
    tf.margin_bottom = 0
    first = True
    for item in items:
        if isinstance(item, tuple):
            level, txt = item
        else:
            level, txt = 0, item
        p = tf.paragraphs[0] if first else tf.add_paragraph()
        first = False
        p.space_after = Pt(space_after)
        p.line_spacing = line_spacing
        marker = "•  " if level == 0 else "–  "
        indent = 0 if level == 0 else 0.35
        p.text = ""
        run_marker = p.add_run()
        run_marker.text = marker
        run_marker.font.size = Pt(size - (1 if level else 0))
        run_marker.font.color.rgb = bullet_color
        run_marker.font.bold = True
        run_marker.font.name = font
        run_text = p.add_run()
        run_text.text = txt
        run_text.font.size = Pt(size - (1 if level else 0))
        run_text.font.color.rgb = color
        run_text.font.name = font
        run_text.font.bold = False
        # simulate indent via left margin per paragraph
        pPr = p._pPr
        if pPr is None:
            pPr = p._p.get_or_add_pPr()
        pPr.set('marL', str(Emu(Inches(indent)).emu if False else int(Inches(indent))))
        pPr.set('indent', '0')
    return tb


def slide_header(slide, kicker, title, num=None, total=None, dark=False):
    """Standard header bar for content slides."""
    set_bg(slide, WHITE)
    add_rect(slide, 0, 0, SW, Inches(1.15), NAVY)
    add_rect(slide, 0, Inches(1.15), SW, Pt(3), GOLD)
    add_text(slide, Inches(0.55), Inches(0.14), Inches(10.5), Inches(0.35), kicker.upper(),
              size=12, color=GOLD, bold=True, font=FONT)
    add_text(slide, Inches(0.55), Inches(0.44), Inches(11.8), Inches(0.65), title,
              size=24, color=WHITE, bold=True, font=FONT)
    if num is not None:
        add_text(slide, Inches(12.55), Inches(0.14), Inches(0.6), Inches(0.35), f"{num}",
                  size=12, color=WHITE, bold=True, align=PP_ALIGN.RIGHT)
    # footer
    add_text(slide, Inches(0.55), Inches(7.18), Inches(9), Inches(0.28),
              "ISGyP Endometrial Carcinoma Grossing Recommendations \u2013 Journal Club", size=9,
              color=RGBColor(0x9a,0x9a,0x9a))
    if num is not None and total is not None:
        add_text(slide, Inches(12.3), Inches(7.18), Inches(0.6), Inches(0.28), f"{num}/{total}",
                  size=9, color=RGBColor(0x9a,0x9a,0x9a), align=PP_ALIGN.RIGHT)


def content_slide(kicker, title, items, num, total, size=17, two_col=False, extra_note=None,
                   bullet_color=TEAL):
    slide = add_slide()
    slide_header(slide, kicker, title, num, total)
    top = Inches(1.55)
    if two_col:
        half = items
        left_items, right_items = half
        add_bullets(slide, Inches(0.6), top, Inches(5.9), Inches(5.3), left_items, size=size,
                    bullet_color=bullet_color)
        add_bullets(slide, Inches(6.75), top, Inches(5.9), Inches(5.3), right_items, size=size,
                    bullet_color=bullet_color)
    else:
        add_bullets(slide, Inches(0.7), top, Inches(11.9), Inches(5.3), items, size=size,
                    bullet_color=bullet_color)
    if extra_note:
        box = add_rect(slide, Inches(0.6), Inches(6.55), Inches(12.1), Inches(0.55), TEAL_LIGHT)
        add_text(slide, Inches(0.8), Inches(6.6), Inches(11.7), Inches(0.45), extra_note,
                  size=13, color=NAVY, bold=True, anchor=MSO_ANCHOR.MIDDLE, italic=True)
    return slide


def recommendation_slide(kicker, question, rec_text, rationale_items, num, total):
    slide = add_slide()
    slide_header(slide, kicker, question, num, total)
    # Recommendation box
    box = add_rect(slide, Inches(0.6), Inches(1.45), Inches(12.1), Inches(1.25), NAVY)
    add_text(slide, Inches(0.9), Inches(1.53), Inches(1.6), Inches(0.4), "RECOMMENDATION",
              size=13, color=GOLD, bold=True)
    add_text(slide, Inches(0.9), Inches(1.9), Inches(11.5), Inches(0.75), rec_text,
              size=16, color=WHITE, bold=True, line_spacing=1.05)
    add_text(slide, Inches(0.7), Inches(2.95), Inches(4), Inches(0.35), "Rationale / Evidence",
              size=15, color=TEAL, bold=True)
    add_bullets(slide, Inches(0.7), Inches(3.35), Inches(11.9), Inches(3.6), rationale_items,
                size=16, bullet_color=TEAL)
    return slide


def section_slide(section_no, title, subtitle, num, total):
    slide = add_slide()
    set_bg(slide, NAVY)
    add_rect(slide, 0, Inches(3.35), SW, Pt(3), GOLD)
    add_text(slide, Inches(1.0), Inches(2.2), Inches(3), Inches(1), f"{section_no:02d}",
              size=64, color=GOLD, bold=True)
    add_text(slide, Inches(1.0), Inches(3.55), Inches(11), Inches(0.9), title,
              size=34, color=WHITE, bold=True)
    add_text(slide, Inches(1.0), Inches(4.35), Inches(11), Inches(0.6), subtitle,
              size=18, color=RGBColor(0xCF,0xE3,0xE6), italic=True)
    add_text(slide, Inches(12.3), Inches(7.1), Inches(0.6), Inches(0.28), f"{num}/{total}",
              size=9, color=RGBColor(0x9a,0x9a,0x9a), align=PP_ALIGN.RIGHT)
    return slide


def add_table(slide, x, y, w, h, data, col_widths=None, header_bg=NAVY, header_color=WHITE,
              body_size=13, header_size=13, row_h=None):
    rows = len(data)
    cols = len(data[0])
    gtable = slide.shapes.add_table(rows, cols, x, y, w, h).table
    if col_widths:
        for i, cw in enumerate(col_widths):
            gtable.columns[i].width = cw
    for ci in range(cols):
        cell = gtable.cell(0, ci)
        cell.text = data[0][ci]
        cell.fill.solid()
        cell.fill.fore_color.rgb = header_bg
        for p in cell.text_frame.paragraphs:
            p.alignment = PP_ALIGN.CENTER
            for r in p.runs:
                r.font.bold = True
                r.font.size = Pt(header_size)
                r.font.color.rgb = header_color
                r.font.name = FONT
        cell.vertical_anchor = MSO_ANCHOR.MIDDLE
    for ri in range(1, rows):
        for ci in range(cols):
            cell = gtable.cell(ri, ci)
            cell.text = data[ri][ci]
            cell.fill.solid()
            cell.fill.fore_color.rgb = LIGHT_GREY if ri % 2 == 0 else WHITE
            for p in cell.text_frame.paragraphs:
                p.alignment = PP_ALIGN.LEFT if ci == 0 else PP_ALIGN.LEFT
                for r in p.runs:
                    r.font.size = Pt(body_size)
                    r.font.color.rgb = DARK_TEXT
                    r.font.name = FONT
            cell.vertical_anchor = MSO_ANCHOR.MIDDLE
            cell.margin_left = Inches(0.08)
            cell.margin_right = Inches(0.08)
    return gtable


TOTAL = 30

# ============================================================ SLIDE 1: TITLE
s = add_slide()
set_bg(s, NAVY)
add_rect(s, 0, Inches(6.55), SW, Inches(0.95), TEAL)
add_text(s, Inches(0.9), Inches(1.6), Inches(11.5), Inches(0.5), "JOURNAL CLUB \u2014 DEPARTMENT OF PATHOLOGY",
          size=16, color=GOLD, bold=True)
add_text(s, Inches(0.9), Inches(2.15), Inches(11.6), Inches(2.0),
          "Endometrial Carcinoma, Grossing and Processing Issues:\nRecommendations of the International Society of\nGynecological Pathologists (ISGyP)",
          size=32, color=WHITE, bold=True, line_spacing=1.1)
add_rect(s, Inches(0.9), Inches(4.35), Inches(2.2), Pt(4), GOLD)
add_text(s, Inches(0.9), Inches(4.55), Inches(11), Inches(0.5),
          "Malpica A, Euscher ED, Hecht JL, et al.", size=18, color=RGBColor(0xE3,0xEE,0xEF), italic=True)
add_text(s, Inches(0.9), Inches(5.0), Inches(11), Inches(0.5),
          "Int J Gynecol Pathol. 2019;38(Suppl 1):S9\u2013S24. doi:10.1097/PGP.0000000000000552",
          size=15, color=RGBColor(0xB9,0xCE,0xD1))
add_text(s, Inches(0.9), Inches(6.72), Inches(8), Inches(0.55), "Presented for Pathology Postgraduate Residents",
          size=16, color=WHITE, bold=True, anchor=MSO_ANCHOR.MIDDLE)
add_text(s, Inches(9.5), Inches(6.72), Inches(3.0), Inches(0.55), "August 2026",
          size=14, color=WHITE, align=PP_ALIGN.RIGHT, anchor=MSO_ANCHOR.MIDDLE)

# ============================================================ SLIDE 2: OUTLINE
s = add_slide()
slide_header(s, "Session Roadmap", "What We Will Cover Today", 2, TOTAL)
outline = [
    "Background & significance of endometrial cancer, and why grossing standardization matters",
    "Study aims, methodology, and the ISGyP task force approach",
    "Recommendations for hysterectomy specimen handling (orientation, fixation, inking, tumor measurement)",
    "Uterine sectioning, tumor sampling, and myometrial invasion assessment",
    "Special situations: Lynch syndrome, adenomyosis, morcellated specimens",
    "Adnexal structures \u2014 fallopian tube (SEE-FIM), ovary, and omentum sampling",
    "Lymph node & sentinel lymph node (SLN) handling and ultrastaging protocols",
    "Margin reporting and intraoperative (frozen section) assessment",
    "Key take-home points and discussion questions",
]
add_bullets(s, Inches(0.7), Inches(1.55), Inches(11.9), Inches(5.3), outline, size=18, space_after=14)

# ============================================================ SLIDE 3: BACKGROUND
s = add_slide()
slide_header(s, "Background", "Why This Article Matters", 3, TOTAL)
left = [
    "Endometrial cancer (EC) is the 6th most common malignancy in women worldwide, and the most common gynecologic malignancy in developed countries.",
    "USA, 2018 estimate: ~63,230 new cases and 11,350 deaths (American Cancer Society).",
    "Accurate gross examination directly determines diagnosis, FIGO staging, treatment planning, and prognostication.",
]
right = [
    "Prior to this article, no updated universal grossing guideline existed \u2014 practice varied widely between institutions (CAP, RCPath, ICCR datasets addressed reporting, not detailed grossing).",
    "The ISGyP Endometrial Cancer Task Force reviewed the literature and grossing manuals from >20 major institutions to build consensus recommendations.",
]
add_text(s, Inches(0.7), Inches(1.5), Inches(3), Inches(0.35), "The Problem", size=16, bold=True, color=TEAL)
add_bullets(s, Inches(0.7), Inches(1.9), Inches(5.8), Inches(4.6), left, size=16)
add_text(s, Inches(6.9), Inches(1.5), Inches(3), Inches(0.35), "The Gap", size=16, bold=True, color=TEAL)
add_bullets(s, Inches(6.9), Inches(1.9), Inches(5.7), Inches(4.6), right, size=16)

# ============================================================ SLIDE 4: OBJECTIVE / METHODS
s = add_slide()
slide_header(s, "Aim & Methodology", "Objective of the Guideline", 4, TOTAL)
items = [
    "Objective: standardize gross processing of specimens from surgical management of endometrial cancer to improve pathology reporting and understanding of the disease.",
    "Specimens covered: hysterectomy (incl. prophylactic), salpingo-oophorectomy, omentectomy, and lymph nodes (sentinel and non-sentinel).",
    "Basis of recommendations:",
    (1, "Comprehensive literature review"),
    (1, "Review of grossing manuals from >20 academic institutions across North America, Europe, and elsewhere"),
    (1, "Collaborative consensus by a subgroup of the ISGyP Endometrial Cancer Task Force"),
    "Also addresses intraoperative (frozen section) assessment of these specimens.",
]
add_bullets(s, Inches(0.7), Inches(1.55), Inches(11.9), Inches(5.3), items, size=17)

# ============================================================ SECTION 1
section_slide(1, "Hysterectomy Specimen \u2014 General Handling", "Orientation, fixation, inking, and weight reporting", 5, TOTAL)

# ============================================================ SLIDE 6: GENERAL RULE + ORIENTATION
s = add_slide()
slide_header(s, "General Principles", "Block Key & Specimen Orientation", 6, TOTAL)
items = [
    "All pathology reports should include a detailed block/section key documenting the origin of every tissue block.",
    (1, "Essential for internal/external review, IHC or molecular re-testing, and research/clinical trials."),
    "Orient every hysterectomy specimen using anatomic landmarks before sectioning:",
    (1, "Peritoneal reflection is higher anteriorly, lower posteriorly."),
    (1, "Adnexal sequence differs: anteriorly \u2013 round ligament, tube, ovary; posteriorly \u2013 ovary, tube, round ligament."),
    "Document all organs/structures received with measurements and gross appearance.",
]
add_bullets(s, Inches(0.7), Inches(1.55), Inches(7.0), Inches(5.3), items, size=16)
img = search_placeholder = None

# ============================================================ SLIDE 7: TIMING OF OPENING/FIXATION
recommendation_slide(
    "Pre-analytics",
    "When Should the Uterus Be Opened?",
    "Open the uterus immediately upon receipt in the lab and place in formalin within 1 hour whenever possible.",
    [
        "Prevents autolysis, which is very common in hysterectomy specimens.",
        "Avoids preanalytical artifacts that compromise immunohistochemistry and molecular studies.",
        "Some institutional manuals specify documenting the cold ischemic interval and time to formalin fixation.",
        "Fresh tissue for banking/research protocols should be procured as soon as possible \u2014 ideally managed by pathology laboratory personnel \u2014 without compromising diagnostic evaluation; a pathologist should be consulted in questionable cases.",
    ], 7, TOTAL)

# ============================================================ SLIDE 8: INKING
recommendation_slide(
    "Gross Technique",
    "Should Peritoneal/Non-Peritoneal Surfaces Be Inked?",
    "Inking is recommended for hysterectomy specimens and mandatory for radical hysterectomy specimens with parametrium and vaginal cuff.",
    [
        "Aids orientation and confirms tumor at the uterine serosal surface.",
        "Extending ink to the ectocervical/vaginal cuff margin helps measure depth of cervical stromal invasion relative to full cervical wall thickness, and assess margin status.",
        "Blot inked surfaces immediately after application to prevent ink displacement and misinterpretation.",
    ], 8, TOTAL)

# ============================================================ SLIDE 9: UTERINE WEIGHT
recommendation_slide(
    "Reporting",
    "Should Uterine Weight Be Reported?",
    "Uterine weight should be included \u2014 its necessity is geographically dependent, but mandatory in the USA.",
    [
        "In the USA, CPT reimbursement coding depends on a 250g threshold: CPT 58570 (\u2264250g) vs CPT 58572 (>250g).",
        "Also required for ABOG (American Board of Obstetrics & Gynecology) case-list submissions.",
        "Larger uteri may correlate with increased operative duration/surgical complication risk, but the primary driver for reporting is administrative/reimbursement, not oncologic.",
    ], 9, TOTAL)

# ============================================================ SECTION 2
section_slide(2, "Tumor Measurement & Uterine Sectioning", "Opening technique, dimensions, and the Mayo algorithm", 10, TOTAL)

# ============================================================ SLIDE 11: HOW TO OPEN + FIG3
recommendation_slide(
    "Gross Technique",
    "How Should the Uterus Be Opened?",
    "Open along the lateral uterine walls at the 3 and 9 o\u2019clock positions.",
    [
        "Provides maximum exposure of the endometrial surface in a flat plane for optimal visualization and measurement.",
        "Caution: lateral walls contain the cornua \u2014 tumor filling the proximal fallopian tube lumen can mimic myoinvasive carcinoma. Do not misinterpret this as myometrial invasion.",
        "This technique is endorsed by essentially all grossing manuals reviewed.",
    ], 11, TOTAL)

# ============================================================ SLIDE 12: TUMOR MEASUREMENT
s = add_slide()
slide_header(s, "Tumor Measurement", "Should Tumor Always Be Measured in 3 Dimensions?", 12, TOTAL)
box = add_rect(s, Inches(0.6), Inches(1.45), Inches(12.1), Inches(0.95), NAVY)
add_text(s, Inches(0.9), Inches(1.5), Inches(1.6), Inches(0.4), "RECOMMENDATION", size=13, color=GOLD, bold=True)
add_text(s, Inches(0.9), Inches(1.83), Inches(11.5), Inches(0.5),
          "At minimum, report the largest tumor dimension; 3 dimensions are best practice but not mandatory.",
          size=15, color=WHITE, bold=True)
items = [
    "CAP checklist: maximum dimension only \u2014 optional, not required for accreditation.",
    "RCPath (UK) dataset: recommends recording only the maximum tumor dimension.",
    "Tumor size influences intraoperative triage for lymph node dissection (Mayo algorithm \u2014 next slide).",
    "Evidence on tumor size and outcome is conflicting:",
    (1, "Some studies show association between size and nodal metastasis / recurrence (thresholds \u22653.5cm or >5cm), but not always independent of depth of invasion / LVSI."),
    (1, "Other studies show no independent prognostic value once myoinvasion and LVSI are accounted for."),
]
add_bullets(s, Inches(0.7), Inches(2.55), Inches(11.9), Inches(4.3), items, size=16)

# ============================================================ SLIDE 13: MAYO ALGORITHM TABLE
s = add_slide()
slide_header(s, "Risk Stratification", "The \u201cMayo Algorithm\u201d \u2014 Tumor Size & Nodal Risk", 13, TOTAL)
add_text(s, Inches(0.7), Inches(1.45), Inches(11.9), Inches(0.5),
          "Used to triage low-risk endometrioid EC patients for intraoperative lymph node dissection.", size=15, color=GREY, italic=True)
data = [
    ["Criteria", "Low Risk\n(LN dissection spared)", "High Risk\n(pelvic LN dissection performed)"],
    ["Histotype / Grade", "Endometrioid, FIGO grade 1\u20132", "FIGO grade 3, or non-endometrioid histotype"],
    ["Tumor size", "\u2264 2 cm", "> 2 cm"],
    ["Myometrial invasion", "\u2264 50%", "> 50%"],
    ["Risk of pelvic LN metastasis", "< 0.3%", "up to ~10% (if size >2cm, \u226450% invasion)"],
]
add_table(s, Inches(0.7), Inches(2.1), Inches(11.9), Inches(3.4), data,
          col_widths=[Inches(3.1), Inches(4.4), Inches(4.4)], header_size=14, body_size=14)
add_text(s, Inches(0.7), Inches(5.75), Inches(11.9), Inches(1.0),
          "Clinical relevance: tumor size measurement at grossing is not just descriptive \u2014 it can directly change intraoperative surgical management.",
          size=15, color=NAVY, bold=True, italic=True)

# ============================================================ SLIDE 14: SECTIONING ORIENTATION
recommendation_slide(
    "Gross Technique",
    "How Should the Uterus Be Sectioned?",
    "Horizontal/transverse sectioning (left to right) from lower uterine segment to fundus is recommended for the corpus.",
    [
        "Almost all manuals reviewed recommend horizontal/transverse sectioning of the corpus.",
        "Vertical (longitudinal) sectioning is advisable specifically to demonstrate the lower uterine segment together with the upper cervix.",
        "A combined approach (transverse corpus + longitudinal lower segment/cervix) is standard practice.",
    ], 14, TOTAL)

# ============================================================ SECTION 3
section_slide(3, "Tumor & Myometrial Sampling", "How much tissue to submit, and where", 15, TOTAL)

# ============================================================ SLIDE 16: TUMOR SAMPLING
recommendation_slide(
    "Sampling Rule",
    "Should the Tumor Be Submitted Entirely?",
    "Not necessary. Submit one section per centimeter of the largest tumor dimension (as for tumors at other anatomic sites).",
    [
        "Entire tumor submission is only advocated if the tumor measures \u2264 3 cm.",
        "Some manuals recommend a minimum of 4 tumor blocks regardless of size.",
        "Risk of missing a high-grade component (serous/clear cell/undifferentiated/neuroendocrine) admixed with endometrioid carcinoma exists but is uncommon \u2014 no data mandate more extensive sampling.",
    ], 16, TOTAL)

# ============================================================ SLIDE 17: NO GROSS TUMOR SCENARIOS
s = add_slide()
slide_header(s, "Special Scenario", "No Gross Tumor Visible \u2014 What Do You Sample?", 17, TOTAL)
box = add_rect(s, Inches(0.6), Inches(1.45), Inches(12.1), Inches(0.95), NAVY)
add_text(s, Inches(0.9), Inches(1.5), Inches(1.6), Inches(0.4), "RECOMMENDATION", size=13, color=GOLD, bold=True)
add_text(s, Inches(0.9), Inches(1.83), Inches(11.5), Inches(0.55),
          "Submit the ENTIRE endometrium + adjacent inner myometrium when: preoperative biopsy showed malignancy but no gross lesion, OR there is a history of atypical hyperplasia/EIN.",
          size=15, color=WHITE, bold=True)
items = [
    "Same rule applies to hysterectomies removed for other reasons (leiomyoma, adenomyosis) that unexpectedly show carcinoma/AEH on initial sections.",
    "Cornual blocks must be submitted when there is biopsy-proven carcinoma but no gross endometrial tumor.",
    "Residual myometrium: keep in sequential order (folded towel/gauze, in formalin) in case deeper sampling for depth-of-invasion is later required.",
    "Data point: intraoperative full-thickness section of a grossly-unremarkable uterus for known EC found microscopic tumor in only 3/20 (15%) of cases.",
]
add_bullets(s, Inches(0.7), Inches(2.55), Inches(11.9), Inches(4.3), items, size=16)

# ============================================================ SLIDE 18: MYOMETRIAL INVASION
recommendation_slide(
    "Staging-Critical",
    "How Many Full-Thickness Sections for Myometrial Invasion?",
    "At least ONE full-thickness section (including serosa) is required to show the deepest point of invasion; more sections may be needed if gross assessment is uncertain.",
    [
        "In thin-walled uteri, full-thickness sections can be submitted in a single cassette.",
        "Depth of myometrial invasion is an independent predictor of lymph node metastasis and prognosis, and is part of the FIGO staging system.",
        "Take extra full-thickness sections when gross assessment is difficult: adenomyosis involved by carcinoma, unusual invasion patterns (\u201cadenoma malignum-like,\u201d \u201csingle cell,\u201d \u201cMELF\u201d = microcystic, elongated, and fragmented), or a distorting leiomyoma.",
        "In adenomyosis specifically: do NOT alter the number of sections routinely, but take additional sections if myoinvasion assessment is genuinely difficult.",
    ], 18, TOTAL)

# ============================================================ SLIDE 19: INTERFACE + NON-NEOPLASTIC ENDOMETRIUM
s = add_slide()
slide_header(s, "Sampling Detail", "Tumor Interface & Background Endometrium", 19, TOTAL)
left = [
    "Tumor/non-tumor interface: sample whenever possible.",
    (1, "Facilitates measurement of depth of myoinvasion."),
    (1, "Helps identify precursor lesions (e.g., EIN/atypical hyperplasia)."),
]
right = [
    "Non-neoplastic endometrium: at least one representative section required.",
    (1, "Any grossly distinct endometrial lesion separate from the tumor must also be submitted."),
    (1, "No universal rule on number of sections \u2014 some manuals suggest 1\u20132 full-thickness sections of uninvolved endomyometrium."),
]
add_text(s, Inches(0.7), Inches(1.5), Inches(4), Inches(0.35), "Tumor Interface", size=16, bold=True, color=TEAL)
add_bullets(s, Inches(0.7), Inches(1.9), Inches(5.8), Inches(4.6), left, size=16)
add_text(s, Inches(6.9), Inches(1.5), Inches(4), Inches(0.35), "Non-Neoplastic Endometrium", size=16, bold=True, color=TEAL)
add_bullets(s, Inches(6.9), Inches(1.9), Inches(5.7), Inches(4.6), right, size=16)

# ============================================================ SECTION 4
section_slide(4, "Special Clinical Scenarios", "Lynch syndrome, lower uterine segment, cervix, morcellation", 20, TOTAL)

# ============================================================ SLIDE 21: LYNCH SYNDROME
s = add_slide()
slide_header(s, "Hereditary Cancer", "Prophylactic Specimens in Lynch Syndrome", 21, TOTAL)
box = add_rect(s, Inches(0.6), Inches(1.45), Inches(12.1), Inches(0.95), NAVY)
add_text(s, Inches(0.9), Inches(1.5), Inches(1.6), Inches(0.4), "RECOMMENDATION", size=13, color=GOLD, bold=True)
add_text(s, Inches(0.9), Inches(1.83), Inches(11.5), Inches(0.55),
          "Submit ALL gross abnormalities; if no gross lesion, submit the ENTIRE endometrium in toto. Submit unremarkable tubes/ovaries entirely as well.",
          size=15, color=WHITE, bold=True)
items = [
    "Endometrial cancer is the most common extracolonic tumor in Lynch syndrome; cumulative incidence by age 70: MLH1 34%, MSH2 51%, MSH6 49%, PMS2 24%.",
    "Ovarian cancer is the 2nd most common extracolonic tumor (lifetime risk 6\u201314%).",
    "Risk-reducing hysterectomy + BSO is included in NCCN guidelines for postmenopausal/childbearing-complete Lynch patients \u2014 uptake is increasing.",
    "Rationale: small, low-grade, clinically occult carcinomas are found in these prophylactic specimens \u2014 in toto endometrial submission is needed to detect them.",
    "Lower uterine segment: submit in toto with longitudinal sections including the endocervical junction; excess myometrium can be trimmed.",
    "Pathologist must be informed of Lynch syndrome status before grossing.",
]
add_bullets(s, Inches(0.7), Inches(2.55), Inches(11.9), Inches(4.3), items, size=15)

# ============================================================ SLIDE 22: LOWER UTERINE SEGMENT + CERVIX
s = add_slide()
slide_header(s, "Regional Sampling", "Lower Uterine Segment, Parametrium & Cervix", 22, TOTAL)
left = [
    "Lower uterine segment: minimum 2 sections (1 anterior, 1 posterior); longitudinal orientation preferred to show relationship to upper endocervix.",
    "Parametrium: sample BEFORE opening the uterus to avoid carryover contamination. Submit entirely, in sequential slices, after inking the margin.",
    "Cervix left attached to corpus \u2014 never amputate (would compromise assessment of relationship to endocervix).",
]
right = [
    "Cervix grossly normal: \u2265 2 full-thickness sections (1 anterior, 1 posterior).",
    (1, "A more recent study: standard 2 sections missed 24% of cervical involvement in high-risk cohorts (serous, grade 3, carcinosarcoma, LVSI)."),
    "Cervix grossly involved: \u2265 2 representative sections, full thickness, including ectocervical/vaginal cuff margin.",
    (1, "Depth of stromal invasion vs full cervical wall thickness guides adjuvant radiotherapy decisions (e.g., <3mm vs outer 1/3 vs middle 1/3 with LVSI)."),
]
add_text(s, Inches(0.7), Inches(1.5), Inches(3), Inches(0.35), "LUS & Parametrium", size=16, bold=True, color=TEAL)
add_bullets(s, Inches(0.7), Inches(1.9), Inches(5.8), Inches(4.7), left, size=15)
add_text(s, Inches(6.9), Inches(1.5), Inches(3), Inches(0.35), "Cervix", size=16, bold=True, color=TEAL)
add_bullets(s, Inches(6.9), Inches(1.9), Inches(5.7), Inches(4.7), right, size=15)

# ============================================================ SLIDE 23: MORCELLATED SPECIMENS
recommendation_slide(
    "Challenging Specimen",
    "Handling an Unexpectedly Malignant Morcellated Specimen",
    "Carefully examine for any endometrial abnormality; if found, submit the entire lesion + adjacent myometrium + any serosal surface present.",
    [
        "If endometrium looks unremarkable but initial sections show AEH/EIN or carcinoma \u2014 careful re-grossing with submission of ALL visible endometrial lining and adjacent myometrium is required.",
        "If cervix is present in the specimen, sample it representatively.",
        "Incidence of unexpected EC in morcellated specimens for presumed-benign disease: 0.07\u20133%.",
        "Depth of myoinvasion and accurate staging may be impossible to assess once tissue architecture is disrupted by morcellation \u2014 an important limitation to communicate in the report.",
        "Preoperative endometrial biopsy is recommended to exclude malignancy before morcellation is undertaken.",
    ], 23, TOTAL)

# ============================================================ SECTION 5
section_slide(5, "Adnexal Structures", "Fallopian tube (SEE-FIM), ovary, and omentum", 24, TOTAL)

# ============================================================ SLIDE 25: FALLOPIAN TUBE - SEE FIM
s = add_slide()
slide_header(s, "Fallopian Tube", "SEE-FIM Protocol", 25, TOTAL)
left = [
    "Any macroscopically abnormal area \u2192 submit for microscopy.",
    "If grossly unremarkable \u2192 entire tube processed using the SEE-FIM protocol, at minimum for serous carcinoma, clear cell carcinoma, and carcinosarcoma.",
    "Practical minimum alternative: at least examine the fimbrial end via SEE-FIM, plus routine representative sections of the rest of the tube.",
]
right_title = "SEE-FIM Steps"
right = [
    "Fix specimen for several hours.",
    "Amputate distal 2cm (infundibulum + fimbria); section parallel to the long axis.",
    "Cross-section the remaining isthmus/ampulla at 2\u20133mm intervals.",
    "Section ovary perpendicular to long axis at 2\u20133mm intervals.",
    "One H&E slide per block.",
]
add_text(s, Inches(0.7), Inches(1.5), Inches(5.5), Inches(0.35), "Recommendation", size=16, bold=True, color=TEAL)
add_bullets(s, Inches(0.7), Inches(1.9), Inches(5.8), Inches(4.7), left, size=16)
add_text(s, Inches(6.9), Inches(1.5), Inches(5.5), Inches(0.35), right_title, size=16, bold=True, color=TEAL)
add_bullets(s, Inches(6.9), Inches(1.9), Inches(5.7), Inches(4.7), right, size=16)

# ============================================================ SLIDE 26: OVARY & OMENTUM
s = add_slide()
slide_header(s, "Adnexa & Omentum", "Ovary and Omentum Sampling", 26, TOTAL)
left = [
    "High-grade histotypes (serous, clear cell, carcinosarcoma): submit ENTIRE ovary, sliced perpendicular to long axis at 2\u20133mm intervals.",
    "Same protocol ideally used for accompanying oophorectomy in other EC histotypes; if not feasible, submit \u2265 2 sections per ovary.",
    "~2.7% of grossly unremarkable ovaries removed for EC harbor microscopic carcinoma.",
]
right = [
    "Omentectomy is part of staging for serous carcinoma, clear cell carcinoma, and carcinosarcoma.",
    "Report gross appearance and measurement; slice at 0.5cm intervals to detect small deposits.",
    "Grossly positive: 1\u20132 representative sections suffice.",
    "Grossly negative: 1 section per 2\u20133cm of maximal dimension, or minimum 4 blocks (RCPath) \u2014 5 blocks give 82% sensitivity, 10 blocks raise sensitivity to 95%.",
]
add_text(s, Inches(0.7), Inches(1.5), Inches(4), Inches(0.35), "Ovary", size=16, bold=True, color=TEAL)
add_bullets(s, Inches(0.7), Inches(1.9), Inches(5.8), Inches(4.7), left, size=16)
add_text(s, Inches(6.9), Inches(1.5), Inches(4), Inches(0.35), "Omentum", size=16, bold=True, color=TEAL)
add_bullets(s, Inches(6.9), Inches(1.9), Inches(5.7), Inches(4.7), right, size=16)

# ============================================================ SECTION 6
section_slide(6, "Lymph Nodes & Sentinel Lymph Nodes", "Handling, slicing, and ultrastaging protocols", 27, TOTAL)

# ============================================================ SLIDE 28: LYMPH NODE HANDLING
s = add_slide()
slide_header(s, "Non-Sentinel Nodes", "General Lymph Node Handling", 28, TOTAL)
items = [
    "Nodes from different anatomical sites: separate, clearly labelled containers; handle and report separately.",
    "Dissect from adipose tissue by visual exam + palpation \u2014 clearing solutions not routinely needed.",
    "Leave a small rim of adipose tissue around larger nodes to allow assessment of extranodal (extracapsular) extension \u2014 an important prognostic factor in stage IIIC disease.",
    "Nodes \u2264 2mm: embed whole. Nodes > 2mm: slice perpendicular to the long axis at 2\u20133mm intervals.",
    "All grossly unremarkable nodal tissue must be submitted for microscopy in properly identified cassettes; record number of nodes per cassette and how submitted (whole vs sectioned).",
    "Grossly positive nodes: representative sections showing the largest tumor deposit and surrounding fat.",
    "Systematic pelvic \u00b1 para-aortic lymphadenectomy carries significant morbidity with no proven survival benefit \u2014 practice varies worldwide, driving interest in SLN mapping.",
]
add_bullets(s, Inches(0.7), Inches(1.55), Inches(11.9), Inches(5.3), items, size=15.5)

# ============================================================ SLIDE 29: SLN HANDLING
s = add_slide()
slide_header(s, "Sentinel Lymph Nodes", "SLN Gross Handling & Ultrastaging", 29, TOTAL)
left = [
    "Record measurements, gross appearance, dye presence, and surgeon-provided radioactive tracer reading.",
    "Slice at 2.0mm intervals perpendicular to the long axis; leave a small rim of adipose tissue.",
    "Entire SLN submitted for microscopy in properly identified cassettes.",
    "Routine frozen section of SLNs is NOT advisable \u2014 risk of losing small tumor foci, and low sensitivity for detecting metastases in grossly unremarkable nodes.",
    "2018 NCCN guidelines: SLN mapping may be used even in high-risk histologies (serous, clear cell, carcinosarcoma).",
]
add_text(s, Inches(0.7), Inches(1.5), Inches(6), Inches(0.35), "Gross Handling", size=16, bold=True, color=TEAL)
add_bullets(s, Inches(0.7), Inches(1.9), Inches(5.8), Inches(3.0), left, size=14.5)

data = [
    ["Protocol", "Steps"],
    ["MD Anderson\n(MDACC)", "If initial H&E negative \u2192 3 consecutive sections at 250\u03bcm; 1 for H&E, 1 spare, 1 for pan-keratin IHC if repeat H&E negative."],
    ["Memorial Sloan\nKettering (MSKCC)", "If initial H&E negative AND myoinvasive/LVSI+ \u2192 2 additional levels 50\u03bcm apart, each with an H&E + keratin IHC slide (IHC if H&E negative)."],
]
add_text(s, Inches(6.9), Inches(1.5), Inches(6), Inches(0.35), "Ultrastaging \u2014 No Universal Protocol", size=16, bold=True, color=TEAL)
add_table(s, Inches(6.9), Inches(1.9), Inches(5.7), Inches(2.6), data,
          col_widths=[Inches(1.6), Inches(4.1)], body_size=12.5, header_size=13)
add_text(s, Inches(0.7), Inches(5.15), Inches(11.9), Inches(1.1),
          "Key point: ultrastaging is required to detect low-volume metastases missed by routine H&E, but is NOT yet standardized across institutions. Perpendicular 2mm sectioning alone raises detection odds independent of ultrastaging.",
          size=14.5, color=NAVY, italic=True, line_spacing=1.1)

# ============================================================ SLIDE 30: SLN mapping procedure NCCN/SGO key points (moved into 29 already) -> use for margins + frozen section + summary as new numbering
# Adjust: combine reporting margins + intraop into slide 30, and add summary/discussion afterward -> increase TOTAL accordingly later.

s = add_slide()
slide_header(s, "Reporting & Intraoperative Assessment", "Margins and Frozen Section Evaluation", 30, TOTAL)
left = [
    "Ectocervical margin: report if cervix involved by tumor.",
    "Vaginal cuff & parametrial margins: report when radical hysterectomy performed for cervical/parametrial involvement.",
    "Otherwise, margin reporting is optional (per CAP).",
    "Uterine serosal involvement = FIGO stage IIIA \u2014 must be reported, but serosa is NOT a true margin and should not be labelled as one.",
]
right = [
    "Frozen section: examine uterine serosa, lower uterine segment, cervix, and adnexa.",
    "Identify and measure the lesion; cross-section the uterine wall; submit \u2265 1 section of tumor + adjacent wall for frozen section.",
    "If myoinvasion suspected: submit the lesion + full uterine wall thickness at the deepest invasion point.",
    "Report histotype, grade, and depth of myoinvasion intraoperatively \u2014 needed to apply the Mayo algorithm for LND triage.",
    "Report LUS, cervical, adnexal involvement and LVSI if identified intraoperatively.",
]
add_text(s, Inches(0.7), Inches(1.5), Inches(5.8), Inches(0.35), "Margins", size=16, bold=True, color=TEAL)
add_bullets(s, Inches(0.7), Inches(1.9), Inches(5.8), Inches(4.7), left, size=15.5)
add_text(s, Inches(6.9), Inches(1.5), Inches(5.7), Inches(0.35), "Intraoperative / Frozen Section", size=16, bold=True, color=TEAL)
add_bullets(s, Inches(6.9), Inches(1.9), Inches(5.7), Inches(4.7), right, size=15.5)

TOTAL = 33

# ============================================================ SLIDE 31: SUMMARY TABLE
s = add_slide()
slide_header(s, "Summary", "Quick-Reference Grossing Checklist", 31, TOTAL)
data = [
    ["Step", "Key Recommendation"],
    ["Opening/Fixation", "Open immediately; formalin within 1 hour"],
    ["Inking", "Recommended (mandatory in radical hysterectomy)"],
    ["Uterine weight", "Always report (mandatory in the USA for CPT coding)"],
    ["Opening technique", "3 and 9 o\u2019clock lateral incisions"],
    ["Tumor size", "Report at least the largest dimension"],
    ["Sectioning", "Horizontal/transverse (corpus); longitudinal (LUS/cervix)"],
    ["Tumor sampling", "1 section/cm of largest dimension (entire if \u22643cm)"],
    ["Myoinvasion", "\u2265 1 full-thickness section at deepest point"],
    ["No gross tumor + malignant biopsy", "Submit entire endometrium + inner myometrium"],
    ["Lynch syndrome", "Entire endometrium + entire tubes/ovaries in toto"],
    ["Cervix (grossly normal)", "\u2265 2 full-thickness sections (ant + post)"],
    ["Fallopian tube", "SEE-FIM at minimum for high-grade histotypes"],
    ["Ovary (high-grade histotype)", "Entire ovary, 2\u20133mm sections"],
    ["Omentum (grossly negative)", "1 section/2\u20133cm or \u2265 4 blocks"],
    ["Lymph nodes", "Slice >2mm nodes at 2\u20133mm; submit all tissue"],
    ["SLN", "2.0mm perpendicular slices; entire node submitted; ultrastage"],
]
add_table(s, Inches(0.5), Inches(1.45), Inches(12.3), Inches(5.65), data,
          col_widths=[Inches(3.6), Inches(8.7)], body_size=12.5, header_size=14)

# ============================================================ SLIDE 32: WHY IT MATTERS FOR RESIDENTS
s = add_slide()
slide_header(s, "Clinical Relevance", "Why This Matters for Your Daily Bench Work", 32, TOTAL)
items = [
    "Grossing errors are frequently irreversible \u2014 unlike slides, a poorly sampled specimen cannot be re-grossed after tissue is discarded.",
    "Tumor size and myoinvasion depth measured at grossing directly drive FIGO stage, adjuvant therapy, and even intraoperative surgical decisions (Mayo algorithm).",
    "Missing occult carcinoma in Lynch-syndrome or morcellated specimens has direct medico-legal and clinical consequences.",
    "SLN ultrastaging protocols are becoming standard of care \u2014 residents should know at least one institutional protocol in depth.",
    "Standardized block/section keys are essential for quality review, tumor board discussion, and molecular/IHC workup.",
]
add_bullets(s, Inches(0.7), Inches(1.55), Inches(11.9), Inches(5.3), items, size=18, space_after=14)

# ============================================================ SLIDE 33: DISCUSSION QUESTIONS
s = add_slide()
slide_header(s, "Journal Club Discussion", "Questions for the Group", 33, TOTAL)
items = [
    "Does our department's current grossing protocol for endometrial cancer specimens align with these ISGyP recommendations? Where are the gaps?",
    "How do we currently document and communicate uterine weight, tumor size, and myoinvasion depth to referring gynecologic oncologists?",
    "Do we have (or need) a standardized SLN ultrastaging protocol? Which method \u2014 MDACC or MSKCC-style \u2014 fits our IHC/workflow capacity better?",
    "How do we handle morcellated specimens or Lynch-syndrome prophylactic specimens in practice today?",
    "What would it take to implement a formal block/section-code key across our residency training program?",
]
add_bullets(s, Inches(0.7), Inches(1.55), Inches(11.9), Inches(5.0), items, size=18, space_after=16)
box = add_rect(s, Inches(0.6), Inches(6.6), Inches(12.1), Inches(0.5), TEAL_LIGHT)
add_text(s, Inches(0.8), Inches(6.63), Inches(11.7), Inches(0.45),
          "Citation: Malpica A, et al. Int J Gynecol Pathol. 2019;38(Suppl 1):S9\u2013S24.",
          size=12, color=NAVY, bold=True, anchor=MSO_ANCHOR.MIDDLE)

out_path = "/tmp/workspace/endometrial-journal-club/output/Endometrial_Carcinoma_Grossing_JournalClub.pptx"
prs.save(out_path)
print("Saved:", out_path)
print("Total slides:", len(prs.slides.__iter__.__self__._sldIdLst))
Editing File

~/endometrial-journal-club/build_deck.py

Successfully replaced 1 instance(s) of the string in '/tmp/workspace/endometrial-journal-club/build_deck.py'
Editing File

~/endometrial-journal-club/build_deck.py

Successfully replaced 1 instance(s) of the string in '/tmp/workspace/endometrial-journal-club/build_deck.py'
Now remove the duplicate TOTAL = 33 line that appears after slide 30 and run the script.
Searching Content

"TOTAL = 33" in ~/endometrial-journal-club/build_deck.py

Reading File
That's fine, it's redundant but harmless (same value). Now let's run the script.
Running Command

cd /tmp/workspace/endometrial-journal-club && python3 build_deck.py

33 slides generated successfully. Let's verify text doesn't overflow by checking a rendering-free text-length sanity check, and confirm slide content via python-pptx text dump.
Running Command

cd /tmp/workspace/endometrial-journal-club/output && python3 -c " from pptx import Presentation prs = Presentation('Endometrial_Carcinoma_Grossing_JournalClub.pptx') print('slides:', len(prs.slides)) for i, slide in enumerate(prs.slides,1): texts = [] for shp in slide.shapes: if shp.has_text_frame and shp.text_frame.text.strip(): texts.append(shp.text_frame.text.replace(chr(10),' | ')[:60]) print(i, '->', texts[:2]) " ls -la .

All 33 slides generated correctly with the proper structure. The deck is complete.I've built a 33-slide journal club presentation based on the article: Malpica A, et al. "Endometrial Carcinoma, Grossing and Processing Issues: Recommendations of the International Society of Gynecologic Pathologists." Int J Gynecol Pathol. 2019;38(Suppl 1):S9-S24.

Endometrial Carcinoma Grossing JournalClub

Presentation · PPTX

Structure of the deck:
  1. Title + Roadmap (slides 1-2)
  2. Background & Methodology (3-4) — why EC grossing standardization matters, ISGyP task force approach
  3. Section 1 – Hysterectomy General Handling (5-9): block/section key, orientation, timing of opening/fixation, inking rules, uterine weight/CPT coding
  4. Section 2 – Tumor Measurement & Sectioning (10-14): 3 & 9 o'clock opening technique, tumor dimension debate, the Mayo algorithm (with a risk-stratification table), horizontal vs. longitudinal sectioning
  5. Section 3 – Tumor & Myometrial Sampling (15-19): 1 section/cm rule, no-gross-tumor scenarios, full-thickness myoinvasion sampling (incl. adenomyosis/MELF pattern), tumor interface sampling
  6. Section 4 – Special Scenarios (20-23): Lynch syndrome prophylactic specimens, lower uterine segment/parametrium/cervix sampling, morcellated specimen handling
  7. Section 5 – Adnexal Structures (24-26): SEE-FIM protocol for fallopian tube, ovary and omentum sampling rules
  8. Section 6 – Lymph Nodes (27-30): routine node handling, SLN handling with MDACC vs. MSKCC ultrastaging protocol comparison table, margin reporting, intraoperative/frozen section assessment
  9. Wrap-up (31-33): quick-reference checklist table, clinical relevance for residents, and 5 discussion questions to drive journal club conversation
Each recommendation slide follows a consistent "Recommendation box + Rationale/Evidence" format so residents can quickly distinguish what to do from why, and section dividers keep the large volume of content organized. The Mayo algorithm and SLN ultrastaging comparisons are presented as tables since these are the most exam- and practice-relevant elements for residents.
This is a shared conversation. Sign in to Orris to start your own chat.