Journal Reading PPTX Conversion
Overview
When a user provides a medical paper and asks for a journal reading presentation (Journal Reading 簡報 / 晨會簡報), use this skill to generate a professional, academic python-pptx presentation. The input can be:
- A single PDF file — the main paper
- A folder containing the main paper PDF plus supplementary files (e.g., supplement PDFs, appendix tables, additional figures downloaded from the journal website)
The slide structure should follow the paper's own organization — not a fixed template — to faithfully represent the study's logic and highlight its academic rigor.
Prerequisites
- The python modules
python-pptx and pymupdf must be installed:pip3 install python-pptx pymupdf
Workflow
0a. Ask for Presenter Information
Before starting any processing, ask the user for presenter information. This ensures the title slide and ending slide display the correct names. Present the question concisely — the user may skip it:
Presenter info: Who is presenting and who is the supervisor? (e.g., "R2 王大明 / VS 李教授") — press Enter to skip.
- If the user provides names → use them on the title slide and ending slide
- If the user skips (empty reply or says "skip" / "略過") → check memory for saved user profile; if none found, leave presenter info blank or use a generic placeholder ("Presenter / Supervisor")
- Only ask once at the beginning — do not re-ask during the workflow
0b. Identify Input & Create Output Folder
Detect input type
The user may provide:
- A single PDF file → treat it as the main paper
- A folder path → scan the folder for all relevant files
import os, re, glob
user_input = "..." # path provided by user
if os.path.isdir(user_input):
# Folder input: find all PDFs, images, and supplementary files
input_dir = user_input
all_pdfs = sorted(glob.glob(os.path.join(input_dir, "*.pdf")))
all_images = sorted(
glob.glob(os.path.join(input_dir, "*.png")) +
glob.glob(os.path.join(input_dir, "*.jpg")) +
glob.glob(os.path.join(input_dir, "*.jpeg")) +
glob.glob(os.path.join(input_dir, "*.tif")) +
glob.glob(os.path.join(input_dir, "*.tiff"))
)
# Identify main paper vs supplements by filename heuristics
# Main paper: usually the largest PDF, or one without "suppl/supplement/appendix" in name
main_pdf = None
supplement_pdfs = []
for pdf in all_pdfs:
basename = os.path.basename(pdf).lower()
if any(kw in basename for kw in ["suppl", "supplement", "appendix", "table_s", "figure_s"]):
supplement_pdfs.append(pdf)
elif main_pdf is None:
main_pdf = pdf
else:
# Multiple non-supplement PDFs: pick the largest as main
if os.path.getsize(pdf) > os.path.getsize(main_pdf):
supplement_pdfs.append(main_pdf)
main_pdf = pdf
else:
supplement_pdfs.append(pdf)
print(f"Main paper: {main_pdf}")
print(f"Supplements: {supplement_pdfs}")
print(f"Standalone images: {all_images}")
else:
# Single file input
main_pdf = user_input
input_dir = os.path.dirname(user_input)
supplement_pdfs = []
all_images = []
Create output folder
Create a dedicated output folder in the same directory as the input:
{ShortTitle}_journal_reading/
├── figures/ ← extracted figures & tables (from main + supplements)
└── presentation.pptx ← final presentation
Naming convention: derive {ShortTitle} from the paper title — use 3-5 key English words in snake_case, e.g.:
- "The Effect of Topical Tranexamic Acid on..." →
topical_TXA_rhinoplasty_journal_reading/
- "A Randomized Trial of Platelet-Rich Plasma..." →
PRP_randomized_trial_journal_reading/
paper_title = "..." # extracted from the paper
short = "_".join(paper_title.split()[:5]).replace("/","_")
short = re.sub(r'[^a-zA-Z0-9_\-]', '', short)
base_dir = input_dir if os.path.isdir(user_input) else os.path.dirname(main_pdf)
output_dir = os.path.join(base_dir, f"{short}_journal_reading")
figures_dir = os.path.join(output_dir, "figures")
os.makedirs(figures_dir, exist_ok=True)
All subsequent outputs must be saved into this output_dir.
1. Read All Source Files
Main paper
Use the Read tool with pages parameter to read the main PDF, or pdftotext for full extraction:
pdftotext "paper.pdf" /tmp/paper_text.txt
Supplement PDFs
Read each supplement PDF as well — these often contain important supplementary tables, figures, methods, and sensitivity analyses:
for pdf in supplement_pdfs:
pdftotext "$pdf" "/tmp/supplement_$(basename $pdf .pdf).txt"
Standalone images
Copy any standalone images (e.g., high-res figures downloaded from the journal website) directly into figures/:
import shutil
for img in all_images:
shutil.copy2(img, os.path.join(figures_dir, os.path.basename(img)))
2. Extract Figures & Tables from All PDFs
Apply the extraction process to both the main paper and all supplement PDFs. Supplement PDFs often contain high-resolution versions of figures, extended data tables, and flow diagrams.
Use a three-tier approach with PyMuPDF (fitz) for maximum quality. Tier 1 MUST be caption-aware (see warning below).
⚠️ CRITICAL — DO NOT use page.get_images() indices to name files.
page.get_images(full=True) returns images in xref order (PDF resource
dictionary order), NOT spatial / reading order. When a page has multiple
figures, naming embedded_p{N}_1, embedded_p{N}_2 produces SWAPPED labels.
Real failure: in the Kappenstein 2026 thyroid paper, page 5 returned FIG 3
(bottom) before FIG 2 (top), and the same happened on page 6 with FIG 4 / 5.
Always use the caption-aware helper below, which sorts by spatial bbox
position and matches each image to its "FIG. N" caption text block.
import fitz
import os
import sys
# Use the caption-aware helper from this skill
SKILL_SCRIPTS = "<absolute path to>/.claude/skills/journal-reading/scripts"
sys.path.insert(0, SKILL_SCRIPTS)
from extract_figures_by_caption import extract_figures_with_captions
pdf_path = "paper.pdf"
# ──────────────────────────────────────────────
# TIER 1: Caption-aware extraction (REQUIRED)
# Maps each embedded image to its FIG N caption by:
# - sorting images by bbox.y0 (true spatial order)
# - finding nearest "FIG. N" / "Figure N" text block below the image
# - naming files as fig1.{ext}, fig2.{ext}, etc.
# Falls back to img_p{N}_pos{M} for images with no caption (logos, etc.)
# ──────────────────────────────────────────────
saved = extract_figures_with_captions(pdf_path, figures_dir)
# saved is a list of dicts with {filename, fig_num, label, page, xref, bbox, size, ext}
doc = fitz.open(pdf_path) # keep doc open for Tier 2 / 3 below
# ──────────────────────────────────────────────
# TIER 2: Block-based detection for precise bounding boxes
# ──────────────────────────────────────────────
PADDING = 8 # points of padding
for page_idx in range(len(doc)):
page = doc[page_idx]
blocks = page.get_text("dict")["blocks"]
img_blocks = [b for b in blocks if b["type"] == 1]
for i, block in enumerate(img_blocks):
bbox = block["bbox"]
print(f" Page {page_idx+1} image block {i+1}: bbox={bbox}")
# ──────────────────────────────────────────────
# TIER 3: Full-page renders + padded crop
# For figures/tables spanning multiple blocks or needing captions.
# ──────────────────────────────────────────────
scale = 2.5
mat = fitz.Matrix(scale, scale)
for i, page in enumerate(doc):
pix = page.get_pixmap(matrix=mat)
pix.save(os.path.join(figures_dir, f"page_{i+1}.png"))
def crop_save(page_idx, rect_tuple, filename, padding=PADDING):
"""Crop a region from a PDF page with padding."""
page = doc[page_idx]
page_rect = page.rect
x0 = max(rect_tuple[0] - padding, page_rect.x0)
y0 = max(rect_tuple[1] - padding, page_rect.y0)
x1 = min(rect_tuple[2] + padding, page_rect.x1)
y1 = min(rect_tuple[3] + padding, page_rect.y1)
clip = fitz.Rect(x0, y0, x1, y1)
pix = page.get_pixmap(matrix=fitz.Matrix(3.0, 3.0), clip=clip)
pix.save(os.path.join(figures_dir, filename))
doc.close()
Precise cropping workflow (CRITICAL)
Academic PDFs pack figures, tables, captions, footnotes, and body text tightly together. Guessing crop coordinates by eye leads to stray text bleeding into the crop (e.g., page headers, adjacent table footnotes, neighboring figure captions). You MUST follow this two-step process:
Step 1 — Block analysis (mandatory before ANY crop):
Run page.get_text("dict")["blocks"] on every page that contains a figure or table you need. Print each block's type (TXT=0, IMG=1) and bbox, plus a text preview for TXT blocks. This gives you the exact pixel boundaries of every element on the page.
for page_idx in pages_with_figures:
page = doc[page_idx]
blocks = page.get_text("dict")["blocks"]
for i, b in enumerate(blocks):
btype = "IMG" if b["type"] == 1 else "TXT"
bbox = [round(x, 1) for x in b["bbox"]]
if btype == "TXT":
text_preview = ""
for line in b.get("lines", []):
for span in line.get("spans", []):
text_preview += span["text"] + " "
text_preview = text_preview.strip()[:80]
print(f" Block {i:2d} [{btype}] bbox={bbox} \"{text_preview}\"")
else:
print(f" Block {i:2d} [{btype}] bbox={bbox}")
Step 2 — Derive crop coordinates from block boundaries:
- For a figure: use the IMG block's bbox as the top boundary, and its caption TXT block's bbox bottom as the lower boundary
- For a table: use the table title TXT block's bbox top as the upper boundary, and the last footnote TXT block's bbox bottom as the lower boundary
- Exclude adjacent elements: page headers (e.g., "Plastic and Reconstructive Surgery • March 2024"), body text paragraphs, other figures' captions, copyright lines
- Use small padding (4–6pt) — just enough for clean edges without capturing neighboring content
# Example: crop Fig 1 using block analysis results
# IMG block bbox = (147.5, 194.2, 435.5, 397.0)
# Caption block bbox = (147.5, 405.9, 437.4, 453.0)
# → crop from (145, 192) to (440, 455) with padding=4
crop_save(page_idx, (145, 192, 440, 455), "fig1.png", padding=4)
Step 3 — Visual verification (mandatory):
After cropping, use the Read tool to view each cropped image and confirm:
- No stray text from adjacent elements (headers, body text, other tables/figures)
- The complete figure/table is captured including title, data, and footnotes
- If any crop is wrong, re-examine block coordinates and re-crop
Figure extraction decision guide
| Scenario |
Method |
Notes |
| Standalone photo/chart as raster image |
Tier 1 (extract_image) |
Best quality — native resolution |
| Need precise crop of a figure region |
Tier 2 (block analysis → crop_save()) |
MUST run block analysis first |
| Complex figure with caption, or table |
Tier 2 (block analysis → crop_save()) |
Use block boundaries, not guesses |
| Vector graphics (PDF-drawn charts) |
Tier 2 block analysis + higher scale (3.5–4.0) |
Won't appear in get_images() |
Key principles:
- NEVER guess crop coordinates — always derive them from
get_text("dict")["blocks"] bounding boxes
- Always use small padding (4–6pt) when cropping — large padding captures neighboring elements
- Tier 1 must be caption-aware — use
extract_figures_with_captions(), never get_images() index
- For tables: include title block through footnote blocks, but NOT adjacent body text or page headers
- For figures: include IMG block through caption block, but NOT adjacent tables or text
- Verify FIG-N mapping AND content: after Tier 1, read each
figN.{ext} with the Read tool and confirm the image content matches what FIG N is described as in the paper (e.g., fig2.jpeg must show whatever the paper's "FIG. 2." caption describes — not just a clean crop). The caption-matching helper is robust on standard journal layouts but can fail on multi-panel figures with sub-captions only ("a)", "b)" without "FIG N"); always cross-check.
- Verify ALL Tier-2/3 crops visually: read each cropped image to confirm no stray content before proceeding — if wrong, re-crop immediately
3. Analyze the Paper Structure
Read the full text carefully. Identify the paper's own sections (e.g., Introduction, Methods, Results, Discussion, Conclusion) and key elements:
- Title, authors, journal, year, DOI
- Study type (RCT, cohort, meta-analysis, case series, systematic review, etc.)
- Level of Evidence (LOE)
- PICO — Population, Intervention, Comparison, Outcome
- Key tables and figures — map extracted images to their original labels (Table 1, Figure 2, etc.)
- Statistical results — p-values, confidence intervals, effect sizes, NNT
- Limitations and strengths
- Clinical implications
3.5. Text Formatting Rules (CRITICAL)
These rules apply to ALL python-pptx text in the generated script. Violating them causes formatting bugs (black text, missing font sizes).
Never use p.text = "..."
Always use set_run() or p.add_run() to add text. The p.text = pattern creates a run but does not guarantee formatting on subsequent lines.
# ❌ WRONG — only first line gets formatted
p.text = "Line 1\nLine 2\nLine 3"
run = p.runs[0]
run.font.size = Pt(22) # Only Line 1 is 22pt!
# ✅ CORRECT — each line is a separate paragraph with its own run
for i, line in enumerate(lines):
p = tf.paragraphs[0] if i == 0 else tf.add_paragraph()
run = p.add_run()
run.text = line
run.font.size = Pt(22)
run.font.color.rgb = DARK_GRAY
run.font.name = "Helvetica"
Never use \n in text strings
Each visual line must be a separate paragraph. Split multi-line content into a list before passing to any helper function.
Every text element must have explicit formatting
Every run must set: font.size, font.color.rgb, font.name. Never rely on defaults.
4. Design Slides Based on the Paper's Structure
Do NOT force a fixed slide count or fixed template. The number of slides should be determined by the content — use as many slides as needed to present the material clearly with comfortable spacing. Prefer more slides with less content each over fewer dense slides. A typical journal reading presentation may range from 15 to 25+ slides depending on the paper's complexity.
Layout density principles (critical):
- Max 4–5 bullet points per slide — each bullet should be one concise line
- Max 1 table + 1–2 figures per slide — if a slide has a table AND figures AND a highlight box, split it
- Two-column layouts: max 4–5 items per column
- Leave breathing room — generous padding, whitespace between elements; do not fill every pixel
- When in doubt, split — it is always better to add a slide than to cram content
- Font sizes must be readable from the back of a conference room — body text ≥ Pt(22), table cells ≥ Pt(16), titles ≥ Pt(32)
Required slides (always present):
- Title slide — Paper title, authors, journal, year, LOE badge, presenter info
- Outline slide (2nd slide) — Numbered table of contents listing all subsequent sections. This serves as a roadmap for the audience and must match the actual slide titles that follow.
- Background / Introduction — Clinical problem, knowledge gap, study rationale (1–2 slides)
- Study Objective & PICO — separate slide for clarity
- Study Design & Methods — split into multiple slides if needed (e.g., design + intervention on one, outcome assessment on another, grading scales/statistics on another)
- Results — one slide per major outcome; add a summary comparison slide if multiple outcomes exist
- Discussion (multiple slides) — This section should be detailed and thorough, with each sub-topic on its own slide: key findings, mechanism of action, comparison with literature, strengths & limitations, clinical implications, and future research directions. Never condense Discussion into fewer than 4 slides. When citing other studies in the Discussion, always include the author name, year, and key finding (e.g., "Ghavimi et al. (2017): IV TA reduced edema at 24 hrs"). These references come from the paper's own Discussion section — faithfully attribute claims to their cited sources rather than presenting them as standalone facts.
- Conclusions — key findings + clinical pearl
- Ending slide (last slide) — "Thank you — Questions?" with presenter info
Adapt to paper type:
| Paper Type |
Structural Emphasis |
| RCT |
CONSORT flow, intervention details, primary/secondary endpoints |
| Meta-analysis |
PRISMA flow, forest plots, heterogeneity, subgroup analyses |
| Cohort / Case-control |
Exposure definition, matching, confounders, adjusted estimates |
| Systematic review |
Search strategy, inclusion criteria, quality assessment |
| Case series / report |
Clinical presentation, timeline, management, outcome |
| Diagnostic study |
Reference standard, sensitivity/specificity, ROC, STARD |
Slide Layout Patterns (16:9, coordinates in Inches)
Use these 5 patterns consistently. Reference them by name in code comments.
| Pattern |
Layout |
Coordinates |
When to use |
| A: Figure + Analysis |
Image left, bullets right |
Image: (0.6, 1.4, w=6.0), Bullets: (7.0, 1.4, w=5.7, h=5.0) |
Single figure with interpretation |
| B: Figure + Analysis (reversed) |
Bullets left, image right |
Bullets: (0.6, 1.4, w=5.7, h=5.0), Image: (6.8, 1.4, w=6.0) |
Alternating visual flow |
| C: Table + Key Takeaway |
Table top, highlight box bottom |
Table: (0.6, 1.4, w=12.0, h=3.5), Box: (0.6, 5.2, w=12.0) |
Results table with headline finding |
| D: Side-by-Side Comparison |
Two images side by side, note below |
Img1: (0.6, 1.4, w=5.8), Img2: (6.8, 1.4, w=5.8), Caption: (0.6, 6.0) |
Comparing groups, before/after |
| E: Pure Content |
Full-width bullets |
Bullets: (0.8, 1.4, w=11.7, h=5.5), max 5 items |
Intro, methods, discussion |
Emphasis Box Policy
Two types of emphasis boxes are available — use the appropriate one based on importance:
| Box Type |
Function |
Background |
Text Color |
When to Use |
add_highlight_box() |
Supporting emphasis |
Warm yellow (HIGHLIGHT_BG) + left gold accent bar |
Dark text |
Exclusion criteria, study rationale, secondary notes |
add_key_point() |
Primary emphasis |
Deep blue (KEY_POINT_BG) |
White text, gold bold prefix |
KEY FINDING, CLINICAL PEARL, most important takeaway |
- Max 1 emphasis box per slide — never stack multiple boxes
add_key_point() is for the single most important finding on a slide (e.g., significant result, clinical pearl)
add_highlight_box() is for supporting context (e.g., exclusion criteria, rationale)
- Position: typically at the bottom of the slide (Pattern C) or below bullets
Image-Text Pairing Rule
- Every figure/table MUST appear on the SAME slide as its interpretation text
- Use Pattern A or B to pair an image with analysis bullets
- NEVER isolate a figure on its own slide without interpretation
- NEVER put interpretation on a separate slide from its figure
Embedding figures in slides:
- Use
slide.shapes.add_picture() to insert extracted figures/tables into relevant slides
- Place figures alongside bullet-point summaries for context
- Maintain original figure/table labels as captions
- Size figures appropriately — typically
Inches(5) width for full-width, Inches(3.5) for side-by-side
from pptx.util import Inches
# Example: add a figure to a slide
img_path = os.path.join(figures_dir, "figure1.png")
slide.shapes.add_picture(img_path, Inches(1), Inches(2), width=Inches(5))
Slide numbers (mandatory):
Every slide must display "X / N" in the bottom-right corner. Call add_slide_numbers(prs) from the helper library as the final step before prs.save(). This automatically adds numbers to all slides.
Academic quality principles:
- Faithfully represent the paper — preserve the authors' logic and data hierarchy
- Show raw data — include exact numbers, p-values, CIs; do not over-simplify
- Use proper statistical reporting — e.g., "OR 2.3 (95% CI 1.4–3.8, p=0.001)"
- Cite figures/tables by original labels — "Table 2", "Figure 3A"
- Include critical appraisal — bias assessment, study limitations, generalizability
- Highlight significant findings — use red/bold for significant p-values
Citation and attribution in Discussion slides:
- When the Discussion references other studies (comparison with literature, mechanism explanations, supporting evidence), always attribute the claim to its source with author name and year
- Format: "Author et al. (Year):" followed by key finding and study detail (e.g., sample size, route, outcome)
- Clearly distinguish between the current study's own findings vs claims from cited literature
- If the paper's Discussion explains a mechanism or makes an interpretive claim, note that it comes from the paper's own discussion (e.g., "The authors suggest..." or present it as the paper's interpretation)
- Do NOT present cited literature findings as if they are the current study's own results
- Example good format:
**Ghavimi et al. (2017):** IV TA in rhinoplasty (n=60) — reduced edema & ecchymosis at 24 hrs. *BUT systemic route*
- Example bad format:
IV TA reduces edema and ecchymosis at 24 hours (no attribution, unclear whose finding this is)
Slide layout and readability:
- Keep bullet points concise — max 4–5 per slide, one line each; split if more content is needed
- Font sizes for projection: body text ≥ Pt(22), titles ≥ Pt(32), table cells ≥ Pt(16), captions ≥ Pt(14)
- Spacious layout — do not pack slides tight; leave ≥ Inches(0.5) margins on all sides
- Figures: use
Inches(5–6) width for full-width; Inches(3–4) for side-by-side; always leave room for caption
- Tables: limit to 4–5 data rows per slide; split large tables across multiple slides if needed
- Widescreen format: use
prs.slide_width = Inches(13.333) and prs.slide_height = Inches(7.5) for 16:9 ratio
5. Generate the PPTX
Write a self-contained Python script to /tmp/create_presentation.py that inlines all helper functions from scripts/generate_aesthetic_pptx.py. Do NOT import from the helper file path — copy the function definitions directly into the script so it runs standalone.
Script structure:
- Inline all helpers at the top:
set_run(), create_presentation(), add_title_slide(), add_content_slide(), add_section_num(), add_outline_slide(), add_ending_slide(), add_bullets(), add_highlight_box(), add_key_point(), add_styled_table(), add_image(), add_caption(), add_slide_numbers(), _set_slide_bg(), _add_shape_with_fill(), _add_card_bg(), and all constants (DEEP_BLUE, MEDIUM_BLUE, DARK_TEXT, ACCENT_RED, SUCCESS_GREEN, WHITE, MUTED_GRAY, LIGHT_BG, CARD_BORDER, HIGHLIGHT_BG, KEY_POINT_BG, TABLE_ALT_ROW, SECTION_NUM_COLOR, font sizes, slide dimensions).
- Build slides using the layout patterns by name in comments (e.g.,
# Pattern A: Figure + Analysis).
- Call
add_slide_numbers(prs) as the final step before prs.save().
Key rules for the generated script:
- Use
add_content_slide(prs, title) for every content slide (creates light-bg slide with title bar + accent line)
- Use
add_section_num(slide, "01 — Methods") to add section number labels below title bar
- Use
add_bullets() for bullet lists — supports plain strings, ("Bold:", "rest") tuples, {"red": "p=0.001"} dicts, and {"green": "positive finding"} dicts
- Bold prefixes in tuples render in
DEEP_BLUE for high contrast; body text uses DARK_TEXT (#1E293B)
- Use
add_key_point() for KEY FINDING or CLINICAL PEARL — deep blue box with white/gold text
- Use
add_highlight_box() for supporting context — warm yellow box with gold accent bar
- Use
add_styled_table() with {"red": val} or {"green": val} dicts for colored cells
- Use
add_image() with existence check — always pair with analysis on the same slide
- Use
_add_card_bg() to create card-like backgrounds with left accent borders when grouping content visually
- Reference layout patterns A–E in comments for every slide
output_path = os.path.join(output_dir, "presentation.pptx")
add_slide_numbers(prs) # MUST be last step before save
prs.save(output_path)
Execute the script:
python3 /tmp/create_presentation.py
6. Deliver
- All output files are saved inside the dedicated output folder:
{ShortTitle}_journal_reading/
├── figures/ ← extracted figures & tables
└── presentation.pptx ← final presentation
- Notify the user:
- The output folder path
- The number of slides generated and their section breakdown
- The number of figures/tables extracted and embedded
- That the file is fully editable in PowerPoint/Keynote
Content Guidelines
- Default language: English — use standard medical/academic terminology
- If the user requests Chinese or bilingual, switch accordingly
- Preserve the paper's own terminology and abbreviations
- Always include LOE and study design on the title slide
- Tables should use the styled format (deep-blue header, clean rows)
- Significant p-values: red bold text
- Non-significant results: still include them — academic honesty matters
- End with clinical relevance — what should the audience take away?
When to Use
This skill applies when a user:
- Provides a medical paper in PDF format
- Requests a "journal reading" / "Journal Reading 簡報" / "晨會簡報"
- Wants a PowerPoint (.pptx) presentation for academic presentation
- Mentions critical appraisal or evidence-based review
1---2name: journal-reading3description: Convert a medical paper (PDF or folder with supplements) into a professional, academic PowerPoint presentation (PPTX) with extracted figures/tables, mirroring the paper's own structure, with clean medical aesthetics.4---56# Journal Reading PPTX Conversion78## Overview910When a user provides a medical paper and asks for a journal reading presentation (Journal Reading 簡報 / 晨會簡報), use this skill to generate a professional, academic `python-pptx` presentation. The input can be:1112- **A single PDF file** — the main paper13- **A folder** containing the main paper PDF plus supplementary files (e.g., supplement PDFs, appendix tables, additional figures downloaded from the journal website)1415The slide structure should **follow the paper's own organization** — not a fixed template — to faithfully represent the study's logic and highlight its academic rigor.1617## Prerequisites18191. The python modules `python-pptx` and `pymupdf` must be installed:20 ```bash21 pip3 install python-pptx pymupdf22 ```2324## Workflow2526### 0a. Ask for Presenter Information2728Before starting any processing, **ask the user** for presenter information. This ensures the title slide and ending slide display the correct names. Present the question concisely — the user may skip it:2930> **Presenter info:** Who is presenting and who is the supervisor? (e.g., "R2 王大明 / VS 李教授") — press Enter to skip.3132- If the user provides names → use them on the title slide and ending slide33- If the user skips (empty reply or says "skip" / "略過") → check memory for saved user profile; if none found, leave presenter info blank or use a generic placeholder ("Presenter / Supervisor")34- Only ask **once** at the beginning — do not re-ask during the workflow3536### 0b. Identify Input & Create Output Folder3738#### Detect input type3940The user may provide:41- **A single PDF file** → treat it as the main paper42- **A folder path** → scan the folder for all relevant files4344```python45import os, re, glob4647user_input = "..." # path provided by user4849if os.path.isdir(user_input):50 # Folder input: find all PDFs, images, and supplementary files51 input_dir = user_input52 all_pdfs = sorted(glob.glob(os.path.join(input_dir, "*.pdf")))53 all_images = sorted(54 glob.glob(os.path.join(input_dir, "*.png")) +55 glob.glob(os.path.join(input_dir, "*.jpg")) +56 glob.glob(os.path.join(input_dir, "*.jpeg")) +57 glob.glob(os.path.join(input_dir, "*.tif")) +58 glob.glob(os.path.join(input_dir, "*.tiff"))59 )60 # Identify main paper vs supplements by filename heuristics61 # Main paper: usually the largest PDF, or one without "suppl/supplement/appendix" in name62 main_pdf = None63 supplement_pdfs = []64 for pdf in all_pdfs:65 basename = os.path.basename(pdf).lower()66 if any(kw in basename for kw in ["suppl", "supplement", "appendix", "table_s", "figure_s"]):67 supplement_pdfs.append(pdf)68 elif main_pdf is None:69 main_pdf = pdf70 else:71 # Multiple non-supplement PDFs: pick the largest as main72 if os.path.getsize(pdf) > os.path.getsize(main_pdf):73 supplement_pdfs.append(main_pdf)74 main_pdf = pdf75 else:76 supplement_pdfs.append(pdf)77 print(f"Main paper: {main_pdf}")78 print(f"Supplements: {supplement_pdfs}")79 print(f"Standalone images: {all_images}")80else:81 # Single file input82 main_pdf = user_input83 input_dir = os.path.dirname(user_input)84 supplement_pdfs = []85 all_images = []86```8788#### Create output folder8990Create a dedicated output folder **in the same directory as the input**:9192```93{ShortTitle}_journal_reading/94├── figures/ ← extracted figures & tables (from main + supplements)95└── presentation.pptx ← final presentation96```9798**Naming convention:** derive `{ShortTitle}` from the paper title — use 3-5 key English words in snake_case, e.g.:99- "The Effect of Topical Tranexamic Acid on..." → `topical_TXA_rhinoplasty_journal_reading/`100- "A Randomized Trial of Platelet-Rich Plasma..." → `PRP_randomized_trial_journal_reading/`101102```python103paper_title = "..." # extracted from the paper104short = "_".join(paper_title.split()[:5]).replace("/","_")105short = re.sub(r'[^a-zA-Z0-9_\-]', '', short)106base_dir = input_dir if os.path.isdir(user_input) else os.path.dirname(main_pdf)107output_dir = os.path.join(base_dir, f"{short}_journal_reading")108figures_dir = os.path.join(output_dir, "figures")109os.makedirs(figures_dir, exist_ok=True)110```111112All subsequent outputs must be saved into this `output_dir`.113114### 1. Read All Source Files115116#### Main paper117Use the `Read` tool with `pages` parameter to read the main PDF, or `pdftotext` for full extraction:118```bash119pdftotext "paper.pdf" /tmp/paper_text.txt120```121122#### Supplement PDFs123Read each supplement PDF as well — these often contain important supplementary tables, figures, methods, and sensitivity analyses:124```bash125for pdf in supplement_pdfs:126 pdftotext "$pdf" "/tmp/supplement_$(basename $pdf .pdf).txt"127```128129#### Standalone images130Copy any standalone images (e.g., high-res figures downloaded from the journal website) directly into `figures/`:131```python132import shutil133for img in all_images:134 shutil.copy2(img, os.path.join(figures_dir, os.path.basename(img)))135```136137### 2. Extract Figures & Tables from All PDFs138139Apply the extraction process to **both the main paper and all supplement PDFs**. Supplement PDFs often contain high-resolution versions of figures, extended data tables, and flow diagrams.140141Use a **three-tier approach** with PyMuPDF (`fitz`) for maximum quality. **Tier 1 MUST be caption-aware** (see warning below).142143> ⚠️ **CRITICAL — DO NOT use `page.get_images()` indices to name files.**144> `page.get_images(full=True)` returns images in **xref order** (PDF resource145> dictionary order), NOT spatial / reading order. When a page has multiple146> figures, naming `embedded_p{N}_1`, `embedded_p{N}_2` produces SWAPPED labels.147> Real failure: in the Kappenstein 2026 thyroid paper, page 5 returned FIG 3148> (bottom) before FIG 2 (top), and the same happened on page 6 with FIG 4 / 5.149> Always use the caption-aware helper below, which sorts by spatial bbox150> position and matches each image to its "FIG. N" caption text block.151152```python153import fitz154import os155import sys156157# Use the caption-aware helper from this skill158SKILL_SCRIPTS = "<absolute path to>/.claude/skills/journal-reading/scripts"159sys.path.insert(0, SKILL_SCRIPTS)160from extract_figures_by_caption import extract_figures_with_captions161162pdf_path = "paper.pdf"163# ──────────────────────────────────────────────164# TIER 1: Caption-aware extraction (REQUIRED)165# Maps each embedded image to its FIG N caption by:166# - sorting images by bbox.y0 (true spatial order)167# - finding nearest "FIG. N" / "Figure N" text block below the image168# - naming files as fig1.{ext}, fig2.{ext}, etc.169# Falls back to img_p{N}_pos{M} for images with no caption (logos, etc.)170# ──────────────────────────────────────────────171saved = extract_figures_with_captions(pdf_path, figures_dir)172# saved is a list of dicts with {filename, fig_num, label, page, xref, bbox, size, ext}173174doc = fitz.open(pdf_path) # keep doc open for Tier 2 / 3 below175176# ──────────────────────────────────────────────177# TIER 2: Block-based detection for precise bounding boxes178# ──────────────────────────────────────────────179PADDING = 8 # points of padding180181for page_idx in range(len(doc)):182 page = doc[page_idx]183 blocks = page.get_text("dict")["blocks"]184 img_blocks = [b for b in blocks if b["type"] == 1]185 for i, block in enumerate(img_blocks):186 bbox = block["bbox"]187 print(f" Page {page_idx+1} image block {i+1}: bbox={bbox}")188189# ──────────────────────────────────────────────190# TIER 3: Full-page renders + padded crop191# For figures/tables spanning multiple blocks or needing captions.192# ──────────────────────────────────────────────193scale = 2.5194mat = fitz.Matrix(scale, scale)195for i, page in enumerate(doc):196 pix = page.get_pixmap(matrix=mat)197 pix.save(os.path.join(figures_dir, f"page_{i+1}.png"))198199def crop_save(page_idx, rect_tuple, filename, padding=PADDING):200 """Crop a region from a PDF page with padding."""201 page = doc[page_idx]202 page_rect = page.rect203 x0 = max(rect_tuple[0] - padding, page_rect.x0)204 y0 = max(rect_tuple[1] - padding, page_rect.y0)205 x1 = min(rect_tuple[2] + padding, page_rect.x1)206 y1 = min(rect_tuple[3] + padding, page_rect.y1)207 clip = fitz.Rect(x0, y0, x1, y1)208 pix = page.get_pixmap(matrix=fitz.Matrix(3.0, 3.0), clip=clip)209 pix.save(os.path.join(figures_dir, filename))210211doc.close()212```213214#### Precise cropping workflow (CRITICAL)215216Academic PDFs pack figures, tables, captions, footnotes, and body text tightly together. **Guessing crop coordinates by eye leads to stray text bleeding into the crop** (e.g., page headers, adjacent table footnotes, neighboring figure captions). You MUST follow this two-step process:217218**Step 1 — Block analysis (mandatory before ANY crop):**219Run `page.get_text("dict")["blocks"]` on every page that contains a figure or table you need. Print each block's `type` (TXT=0, IMG=1) and `bbox`, plus a text preview for TXT blocks. This gives you the exact pixel boundaries of every element on the page.220221```python222for page_idx in pages_with_figures:223 page = doc[page_idx]224 blocks = page.get_text("dict")["blocks"]225 for i, b in enumerate(blocks):226 btype = "IMG" if b["type"] == 1 else "TXT"227 bbox = [round(x, 1) for x in b["bbox"]]228 if btype == "TXT":229 text_preview = ""230 for line in b.get("lines", []):231 for span in line.get("spans", []):232 text_preview += span["text"] + " "233 text_preview = text_preview.strip()[:80]234 print(f" Block {i:2d} [{btype}] bbox={bbox} \"{text_preview}\"")235 else:236 print(f" Block {i:2d} [{btype}] bbox={bbox}")237```238239**Step 2 — Derive crop coordinates from block boundaries:**240- For a **figure**: use the IMG block's bbox as the top boundary, and its caption TXT block's bbox bottom as the lower boundary241- For a **table**: use the table title TXT block's bbox top as the upper boundary, and the last footnote TXT block's bbox bottom as the lower boundary242- **Exclude** adjacent elements: page headers (e.g., "Plastic and Reconstructive Surgery • March 2024"), body text paragraphs, other figures' captions, copyright lines243- Use **small padding (4–6pt)** — just enough for clean edges without capturing neighboring content244245```python246# Example: crop Fig 1 using block analysis results247# IMG block bbox = (147.5, 194.2, 435.5, 397.0)248# Caption block bbox = (147.5, 405.9, 437.4, 453.0)249# → crop from (145, 192) to (440, 455) with padding=4250crop_save(page_idx, (145, 192, 440, 455), "fig1.png", padding=4)251```252253**Step 3 — Visual verification (mandatory):**254After cropping, use the `Read` tool to view each cropped image and confirm:255- No stray text from adjacent elements (headers, body text, other tables/figures)256- The complete figure/table is captured including title, data, and footnotes257- If any crop is wrong, re-examine block coordinates and re-crop258259#### Figure extraction decision guide260261| Scenario | Method | Notes |262|----------|--------|-------|263| Standalone photo/chart as raster image | **Tier 1** (`extract_image`) | Best quality — native resolution |264| Need precise crop of a figure region | **Tier 2** (block analysis → `crop_save()`) | MUST run block analysis first |265| Complex figure with caption, or table | **Tier 2** (block analysis → `crop_save()`) | Use block boundaries, not guesses |266| Vector graphics (PDF-drawn charts) | **Tier 2** block analysis + higher scale (3.5–4.0) | Won't appear in `get_images()` |267268**Key principles:**269- **NEVER guess crop coordinates** — always derive them from `get_text("dict")["blocks"]` bounding boxes270- **Always use small padding (4–6pt)** when cropping — large padding captures neighboring elements271- **Tier 1 must be caption-aware** — use `extract_figures_with_captions()`, never `get_images()` index272- **For tables**: include title block through footnote blocks, but NOT adjacent body text or page headers273- **For figures**: include IMG block through caption block, but NOT adjacent tables or text274- **Verify FIG-N mapping AND content**: after Tier 1, read each `figN.{ext}` with the Read tool and confirm the image content matches what FIG N is described as in the paper (e.g., `fig2.jpeg` must show whatever the paper's "FIG. 2." caption describes — not just a clean crop). The caption-matching helper is robust on standard journal layouts but can fail on multi-panel figures with sub-captions only ("a)", "b)" without "FIG N"); always cross-check.275- **Verify ALL Tier-2/3 crops visually**: read each cropped image to confirm no stray content before proceeding — if wrong, re-crop immediately276277### 3. Analyze the Paper Structure278279Read the full text carefully. Identify the paper's **own sections** (e.g., Introduction, Methods, Results, Discussion, Conclusion) and key elements:280281- **Title, authors, journal, year, DOI**282- **Study type** (RCT, cohort, meta-analysis, case series, systematic review, etc.)283- **Level of Evidence (LOE)**284- **PICO** — Population, Intervention, Comparison, Outcome285- **Key tables and figures** — map extracted images to their original labels (Table 1, Figure 2, etc.)286- **Statistical results** — p-values, confidence intervals, effect sizes, NNT287- **Limitations and strengths**288- **Clinical implications**289290### 3.5. Text Formatting Rules (CRITICAL)291292These rules apply to ALL python-pptx text in the generated script. Violating them causes formatting bugs (black text, missing font sizes).293294#### Never use `p.text = "..."`295Always use `set_run()` or `p.add_run()` to add text. The `p.text =` pattern creates a run but does not guarantee formatting on subsequent lines.296297```python298# ❌ WRONG — only first line gets formatted299p.text = "Line 1\nLine 2\nLine 3"300run = p.runs[0]301run.font.size = Pt(22) # Only Line 1 is 22pt!302303# ✅ CORRECT — each line is a separate paragraph with its own run304for i, line in enumerate(lines):305 p = tf.paragraphs[0] if i == 0 else tf.add_paragraph()306 run = p.add_run()307 run.text = line308 run.font.size = Pt(22)309 run.font.color.rgb = DARK_GRAY310 run.font.name = "Helvetica"311```312313#### Never use `\n` in text strings314Each visual line must be a separate paragraph. Split multi-line content into a list before passing to any helper function.315316#### Every text element must have explicit formatting317Every `run` must set: `font.size`, `font.color.rgb`, `font.name`. Never rely on defaults.318319### 4. Design Slides Based on the Paper's Structure320321**Do NOT force a fixed slide count or fixed template.** The number of slides should be determined by the content — use as many slides as needed to present the material clearly with comfortable spacing. **Prefer more slides with less content each** over fewer dense slides. A typical journal reading presentation may range from 15 to 25+ slides depending on the paper's complexity.322323#### Layout density principles (critical):324- **Max 4–5 bullet points per slide** — each bullet should be one concise line325- **Max 1 table + 1–2 figures per slide** — if a slide has a table AND figures AND a highlight box, split it326- **Two-column layouts:** max 4–5 items per column327- **Leave breathing room** — generous padding, whitespace between elements; do not fill every pixel328- **When in doubt, split** — it is always better to add a slide than to cram content329- **Font sizes must be readable from the back of a conference room** — body text ≥ Pt(22), table cells ≥ Pt(16), titles ≥ Pt(32)330331#### Required slides (always present):332- **Title slide** — Paper title, authors, journal, year, LOE badge, presenter info333- **Outline slide** (2nd slide) — Numbered table of contents listing all subsequent sections. This serves as a roadmap for the audience and must match the actual slide titles that follow.334- **Background / Introduction** — Clinical problem, knowledge gap, study rationale (1–2 slides)335- **Study Objective & PICO** — separate slide for clarity336- **Study Design & Methods** — split into multiple slides if needed (e.g., design + intervention on one, outcome assessment on another, grading scales/statistics on another)337- **Results** — one slide per major outcome; add a summary comparison slide if multiple outcomes exist338- **Discussion** (multiple slides) — This section should be **detailed and thorough**, with each sub-topic on its own slide: key findings, mechanism of action, comparison with literature, strengths & limitations, clinical implications, and future research directions. **Never condense Discussion into fewer than 4 slides.** When citing other studies in the Discussion, always include the **author name, year, and key finding** (e.g., "Ghavimi et al. (2017): IV TA reduced edema at 24 hrs"). These references come from the paper's own Discussion section — faithfully attribute claims to their cited sources rather than presenting them as standalone facts.339- **Conclusions** — key findings + clinical pearl340- **Ending slide** (last slide) — "Thank you — Questions?" with presenter info341342#### Adapt to paper type:343| Paper Type | Structural Emphasis |344|------------|-------------------|345| RCT | CONSORT flow, intervention details, primary/secondary endpoints |346| Meta-analysis | PRISMA flow, forest plots, heterogeneity, subgroup analyses |347| Cohort / Case-control | Exposure definition, matching, confounders, adjusted estimates |348| Systematic review | Search strategy, inclusion criteria, quality assessment |349| Case series / report | Clinical presentation, timeline, management, outcome |350| Diagnostic study | Reference standard, sensitivity/specificity, ROC, STARD |351352#### Slide Layout Patterns (16:9, coordinates in Inches)353354Use these 5 patterns consistently. Reference them by name in code comments.355356| Pattern | Layout | Coordinates | When to use |357|---------|--------|-------------|-------------|358| **A: Figure + Analysis** | Image left, bullets right | Image: (0.6, 1.4, w=6.0), Bullets: (7.0, 1.4, w=5.7, h=5.0) | Single figure with interpretation |359| **B: Figure + Analysis (reversed)** | Bullets left, image right | Bullets: (0.6, 1.4, w=5.7, h=5.0), Image: (6.8, 1.4, w=6.0) | Alternating visual flow |360| **C: Table + Key Takeaway** | Table top, highlight box bottom | Table: (0.6, 1.4, w=12.0, h=3.5), Box: (0.6, 5.2, w=12.0) | Results table with headline finding |361| **D: Side-by-Side Comparison** | Two images side by side, note below | Img1: (0.6, 1.4, w=5.8), Img2: (6.8, 1.4, w=5.8), Caption: (0.6, 6.0) | Comparing groups, before/after |362| **E: Pure Content** | Full-width bullets | Bullets: (0.8, 1.4, w=11.7, h=5.5), max 5 items | Intro, methods, discussion |363364#### Emphasis Box Policy365Two types of emphasis boxes are available — use the appropriate one based on importance:366367| Box Type | Function | Background | Text Color | When to Use |368|----------|----------|------------|------------|-------------|369| `add_highlight_box()` | Supporting emphasis | Warm yellow (`HIGHLIGHT_BG`) + left gold accent bar | Dark text | Exclusion criteria, study rationale, secondary notes |370| `add_key_point()` | **Primary emphasis** | Deep blue (`KEY_POINT_BG`) | White text, gold bold prefix | **KEY FINDING**, **CLINICAL PEARL**, most important takeaway |371372- **Max 1 emphasis box per slide** — never stack multiple boxes373- `add_key_point()` is for the single most important finding on a slide (e.g., significant result, clinical pearl)374- `add_highlight_box()` is for supporting context (e.g., exclusion criteria, rationale)375- Position: typically at the bottom of the slide (Pattern C) or below bullets376377#### Image-Text Pairing Rule378- Every figure/table **MUST** appear on the **SAME slide** as its interpretation text379- Use Pattern A or B to pair an image with analysis bullets380- **NEVER** isolate a figure on its own slide without interpretation381- **NEVER** put interpretation on a separate slide from its figure382383#### Embedding figures in slides:384- Use `slide.shapes.add_picture()` to insert extracted figures/tables into relevant slides385- Place figures alongside bullet-point summaries for context386- Maintain original figure/table labels as captions387- Size figures appropriately — typically `Inches(5)` width for full-width, `Inches(3.5)` for side-by-side388389```python390from pptx.util import Inches391# Example: add a figure to a slide392img_path = os.path.join(figures_dir, "figure1.png")393slide.shapes.add_picture(img_path, Inches(1), Inches(2), width=Inches(5))394```395396#### Slide numbers (mandatory):397Every slide **must** display "X / N" in the bottom-right corner. Call `add_slide_numbers(prs)` from the helper library as the **final step** before `prs.save()`. This automatically adds numbers to all slides.398399#### Academic quality principles:400- **Faithfully represent the paper** — preserve the authors' logic and data hierarchy401- **Show raw data** — include exact numbers, p-values, CIs; do not over-simplify402- **Use proper statistical reporting** — e.g., "OR 2.3 (95% CI 1.4–3.8, p=0.001)"403- **Cite figures/tables by original labels** — "Table 2", "Figure 3A"404- **Include critical appraisal** — bias assessment, study limitations, generalizability405- **Highlight significant findings** — use red/bold for significant p-values406407#### Citation and attribution in Discussion slides:408- When the Discussion references other studies (comparison with literature, mechanism explanations, supporting evidence), **always attribute the claim to its source** with author name and year409- Format: **"Author et al. (Year):"** followed by key finding and study detail (e.g., sample size, route, outcome)410- Clearly distinguish between the current study's own findings vs claims from cited literature411- If the paper's Discussion explains a mechanism or makes an interpretive claim, note that it comes from the paper's own discussion (e.g., "The authors suggest..." or present it as the paper's interpretation)412- Do NOT present cited literature findings as if they are the current study's own results413- Example good format: `**Ghavimi et al. (2017):** IV TA in rhinoplasty (n=60) — reduced edema & ecchymosis at 24 hrs. *BUT systemic route*`414- Example bad format: `IV TA reduces edema and ecchymosis at 24 hours` (no attribution, unclear whose finding this is)415416#### Slide layout and readability:417- **Keep bullet points concise** — max 4–5 per slide, one line each; split if more content is needed418- **Font sizes for projection:** body text ≥ Pt(22), titles ≥ Pt(32), table cells ≥ Pt(16), captions ≥ Pt(14)419- **Spacious layout** — do not pack slides tight; leave ≥ Inches(0.5) margins on all sides420- **Figures:** use `Inches(5–6)` width for full-width; `Inches(3–4)` for side-by-side; always leave room for caption421- **Tables:** limit to 4–5 data rows per slide; split large tables across multiple slides if needed422- **Widescreen format:** use `prs.slide_width = Inches(13.333)` and `prs.slide_height = Inches(7.5)` for 16:9 ratio423424### 5. Generate the PPTX425426Write a **self-contained** Python script to `/tmp/create_presentation.py` that **inlines all helper functions** from `scripts/generate_aesthetic_pptx.py`. Do NOT `import` from the helper file path — copy the function definitions directly into the script so it runs standalone.427428#### Script structure:4291. **Inline all helpers** at the top: `set_run()`, `create_presentation()`, `add_title_slide()`, `add_content_slide()`, `add_section_num()`, `add_outline_slide()`, `add_ending_slide()`, `add_bullets()`, `add_highlight_box()`, `add_key_point()`, `add_styled_table()`, `add_image()`, `add_caption()`, `add_slide_numbers()`, `_set_slide_bg()`, `_add_shape_with_fill()`, `_add_card_bg()`, and all constants (`DEEP_BLUE`, `MEDIUM_BLUE`, `DARK_TEXT`, `ACCENT_RED`, `SUCCESS_GREEN`, `WHITE`, `MUTED_GRAY`, `LIGHT_BG`, `CARD_BORDER`, `HIGHLIGHT_BG`, `KEY_POINT_BG`, `TABLE_ALT_ROW`, `SECTION_NUM_COLOR`, font sizes, slide dimensions).4302. **Build slides** using the layout patterns by name in comments (e.g., `# Pattern A: Figure + Analysis`).4313. **Call `add_slide_numbers(prs)`** as the final step before `prs.save()`.432433#### Key rules for the generated script:434- Use `add_content_slide(prs, title)` for every content slide (creates light-bg slide with title bar + accent line)435- Use `add_section_num(slide, "01 — Methods")` to add section number labels below title bar436- Use `add_bullets()` for bullet lists — supports plain strings, `("Bold:", "rest")` tuples, `{"red": "p=0.001"}` dicts, and `{"green": "positive finding"}` dicts437- Bold prefixes in tuples render in `DEEP_BLUE` for high contrast; body text uses `DARK_TEXT` (#1E293B)438- Use `add_key_point()` for **KEY FINDING** or **CLINICAL PEARL** — deep blue box with white/gold text439- Use `add_highlight_box()` for supporting context — warm yellow box with gold accent bar440- Use `add_styled_table()` with `{"red": val}` or `{"green": val}` dicts for colored cells441- Use `add_image()` with existence check — always pair with analysis on the same slide442- Use `_add_card_bg()` to create card-like backgrounds with left accent borders when grouping content visually443- Reference layout patterns A–E in comments for every slide444445```python446output_path = os.path.join(output_dir, "presentation.pptx")447add_slide_numbers(prs) # MUST be last step before save448prs.save(output_path)449```450451Execute the script:452453```bash454python3 /tmp/create_presentation.py455```456457### 6. Deliver4584591. All output files are saved inside the dedicated output folder:460 ```461 {ShortTitle}_journal_reading/462 ├── figures/ ← extracted figures & tables463 └── presentation.pptx ← final presentation464 ```4652. Notify the user:466 - The output folder path467 - The number of slides generated and their section breakdown468 - The number of figures/tables extracted and embedded469 - That the file is fully editable in PowerPoint/Keynote470471## Content Guidelines472473- **Default language: English** — use standard medical/academic terminology474- If the user requests Chinese or bilingual, switch accordingly475- Preserve the paper's own terminology and abbreviations476- Always include LOE and study design on the title slide477- Tables should use the styled format (deep-blue header, clean rows)478- Significant p-values: red bold text479- Non-significant results: still include them — academic honesty matters480- End with clinical relevance — what should the audience take away?481482## When to Use483484This skill applies when a user:485- Provides a medical paper in PDF format486- Requests a "journal reading" / "Journal Reading 簡報" / "晨會簡報"487- Wants a PowerPoint (.pptx) presentation for academic presentation488- Mentions critical appraisal or evidence-based review