From medsci-project
Generates publication-ready medical figures: ROC curves, forest plots, CONSORT/PRISMA flow diagrams, Kaplan-Meier curves, Bland-Altman plots, and visual abstracts. Checks journal specs and PHI before generating.
How this skill is triggered — by the user, by Claude, or both
Slash command
/medsci-project:make-figuresinheritThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
You are helping a medical researcher generate publication-ready figures for medical research
references/critic_rubrics/data_plot.mdreferences/critic_rubrics/flow_diagram.mdreferences/design_principles.mdreferences/exemplar_diagrams/README.mdreferences/exemplar_diagrams/consort/README.mdreferences/exemplar_diagrams/consort/template_input.yamlreferences/exemplar_diagrams/consort/template_output.pdfreferences/exemplar_diagrams/consort/template_output.pngreferences/exemplar_diagrams/consort/template_output_600.pngreferences/exemplar_diagrams/other/other_02.meta.yamlreferences/exemplar_diagrams/other/other_02.pngreferences/exemplar_diagrams/other/other_02_why.mdreferences/exemplar_diagrams/pipeline/README.mdreferences/exemplar_diagrams/pipeline/pipeline_01.meta.yamlreferences/exemplar_diagrams/pipeline/pipeline_01.pngreferences/exemplar_diagrams/pipeline/pipeline_01_why.mdreferences/exemplar_diagrams/pipeline/pipeline_03.meta.yamlreferences/exemplar_diagrams/pipeline/pipeline_03.pngreferences/exemplar_diagrams/pipeline/pipeline_03_why.mdreferences/exemplar_diagrams/pipeline/pipeline_04.meta.yamlYou are helping a medical researcher generate publication-ready figures for medical research manuscripts. Every figure must meet journal specifications for dimensions, resolution, fonts, and color accessibility. Produce clean, data-focused visuals with no chartjunk.
The Critic Loop (Step 4b) in this skill is inspired by PaperBanana (Zhu et al., Automating Academic Illustration for AI Scientists, arXiv:2601.23265, 2025) and by prior self-refinement research — Self-Refine (Madaan et al., 2023), Reflexion (Shinn et al., 2023), and Constitutional AI (Anthropic, 2022). This is a clean-room reconstruction specialized for medical publication figures (STARD / CONSORT / PRISMA, journal-specific specs, Wong colorblind palette). No code, prompts, or configurations are derived from PaperBanana's repository.
Before reading any data file, check whether it might contain Protected Health Information (PHI):
*_deidentified.* files exist in the working directory, use those preferentially.*_deidentified.* counterpart), warn the user (ask in the user's preferred language):
"Does this data contain patient identifiers (names, national ID / RRN, contact details, etc.)? If so, please de-identify it first with the
/deidentifyskill."
${CLAUDE_SKILL_DIR}/references/figure_specs.md${CLAUDE_SKILL_DIR}/../analyze-stats/references/style/figure_style.mplstyle (or project's CLAUDE.md if available)2_Data/Read figure_specs.md before generating any figure to confirm journal-specific requirements.
Synced with the user's global rule
~/.claude/rules/journal-ai-image-policies.md. The table below is the local copy used during autonomous workflow; the global rule is authoritative when conflicts arise.
| Journal family | Policy on AI-generated images | Disclosure required |
|---|---|---|
| JACC family (incl. JACC: Asia, JACC Imaging, JACC EP, JACC BTS) | Prohibited without prior Editor-in-Chief permission (JACC pathway, PMC10167500) | Cover-letter pre-submission inquiry + ICMJE-style declaration |
| NEJM | AI image generation prohibited | N/A |
| Radiology / Radiology AI | Allowed with disclosure | Manuscript disclosure block |
| Nature family | Allowed with disclosure + license check | Methods + figure legend |
| Lancet family | Disclosure required, generation discouraged | Manuscript disclosure |
| Default (target unknown) | Treat as prohibited until confirmed | N/A |
Hard rule: For JACC, NEJM, or any "unknown" target journal, never use Gemini / DALL-E / Midjourney / Stable Diffusion / Nano Banana to create images that will appear in figures, Central Illustrations, or graphical abstracts. AI text-editing of the manuscript prose remains acceptable subject to standard disclosure.
Anatomical icons modified from SMART Servier Medical Art (CC BY 4.0).
scatter / Circle / PathPatch. Keeps the entire pipeline non-AI and reproducible.manuscript/figures/_assets_servier/ # CC BY 4.0 source PNGs
manuscript/figures/_assets_servier/CITATION.md # source URL + download date per asset
manuscript/figures/_assets_data/ # data-driven raster (R / matplotlib heat maps, KM, etc.)
manuscript/figures/_legacy/ # archived prior versions
Composition scripts should load only from _assets_servier/ and _assets_data/. If a script imports from _assets_ai/, treat it as a policy violation for JACC/NEJM/unknown targets.
When a figure is produced by a data-driven .py/.R script (ROC, forest, KM, calibration, heat maps), lint that script before finalizing with the /analyze-stats code-quality gate (check_generated_code.py {script} --strict): it catches a missing plotting seed for any bootstrapped CI band, a hardcoded absolute data path, or a hand-typed data literal that should have been read from the analysis CSV.
Even when AI images are allowed, AI-generated illustrations are immediately recognizable to experienced reviewers (small decorative icons that add no information, overly uniform layouts, generic clip-art style). For high-impact submissions, prefer Servier / BioArt / BioRender + matplotlib overlays over AI.
| Output | Minimum DPI | Notes |
|---|---|---|
| Journal halftone (photos, screenshots) | 300 | Standard for most journals |
| Journal line art (diagrams, graphs) | 600 | Required by Radiology, most Elsevier journals |
| Poster presentation | 150-200 | Lower is acceptable for large-format prints |
| Screen/web only | 72-150 | Not for print submission |
Practical workflow for screen captures:
Many journals now require or strongly encourage visual abstracts. European Radiology made graphical abstracts mandatory for all Original Articles from first revision (Jan 2025). Submitting one voluntarily signals effort and can improve editorial impression.
| Status | Example Journals |
|---|---|
| Mandatory | European Radiology (from 1st revision, all Original Articles) |
| Encouraged | Abdominal Radiology, JCO, Annals of Internal Medicine |
| Voluntary | Most other journals — improves social media visibility |
Check the target journal profile (write-paper/references/journal_profiles/) for specific
visual abstract requirements before starting.
${CLAUDE_SKILL_DIR}/references/visual_abstract_templates/{journal}.pptx.
If no journal-specific template exists, use medsci_default.pptx.${CLAUDE_SKILL_DIR}/references/medical_illustration_sources.md)generate_image.py --style medical (only if GEMINI_API_KEY set)python ${CLAUDE_SKILL_DIR}/scripts/generate_visual_abstract.py \
--template european_radiology \
--title "Article Title" \
--hypothesis "Research question" \
--methods "Method 1|Method 2|Method 3" \
--finding "Main finding statement" \
--citation "Eur Radiol (2026) Author A et al; DOI:..." \
--visual figures/fig1_roc_curve.png \
--badges "N=450|CT chest|Multi-center" \
--output figures/visual_abstract.pptx
soffice --headless --convert-to png).| Template | File | Use When |
|---|---|---|
| European Radiology | european_radiology.pptx | Submitting to Eur Radiol |
| MedSci Default | medsci_default.pptx | Any journal without official template |
| JACC Central Illustration | jacc_central_illustration.pptx | JACC family journals (use --type central-illustration) |
To add a new journal template: see ${CLAUDE_SKILL_DIR}/references/visual_abstract_templates/template_guide.md.
A Central Illustration (CI) is not a Visual Abstract (VA). They serve different purposes and follow different rules. JACC family journals (JACC, JACC: Asia, JACC: Cardiovascular Imaging, JACC: Heart Failure, JACC: CardioOncology, JACC: Clinical Electrophysiology, JACC: Basic to Translational Science) require a Central Illustration with every Original Article. Reference: Fuster V, Mann DL. JACC. 2019;74(22):2816–2820.
| Aspect | Central Illustration | Visual Abstract |
|---|---|---|
| Purpose | Single key finding / take-home message | Methods + Results pictorial summary |
| Where in paper | End of Results / start of Discussion | Beginning of paper |
| Methods content | None | Required |
| Audience | Cardiovascular clinicians + journal-issue readers | Broad including non-specialists / social media |
| Used by | All JACC family + JACC: Asia | Originally JACC: Basic to Translational Science |
| Text density | Minimal (graphical priority) | More allowed (methods labels) |
| Bar graphs | OK if they capture entire message | Avoid — use ↑↓ arrows |
| Default complexity | 1–3 visual zones | Q→M→R three blocks |
Full guidance and validation thresholds: ${CLAUDE_SKILL_DIR}/references/jacc_central_illustration_principles.md.
python ${CLAUDE_SKILL_DIR}/scripts/generate_visual_abstract.py \
--type central-illustration \
--visual figures/central_illustration_v2.png \
--citation "FirstAuthor Last et al. Journal Name 2026; vol(issue):pages." \
--output submission/jacc_asia/central_illustration.pptx \
--ci-zones 3 --ci-label-words 22 --ci-numerical-points 2 \
--ci-raw-text "warranty drops to 3 years in age 45+ with cardiometabolic burden; MASLD HR 1.77"
CI mode validates before rendering and rejects (exit 2) if any of: zones > 3, label words > 30, numerical points > 4, or methodology terms (cohort flow / inclusion / exclusion / study design / enrollment / randomized / sample size / CONSORT / PRISMA / STARD) appear in --ci-raw-text. Override individual rules with --ci-allow {zones|words|numerical|methods} only when you have a defensible reason.
The JACC submission PPTX is a 10×7.5 in slide with 4 placeholders (citation textbox, content picture, footer textbox reserved, JACC logo). The red border + blue "CENTRAL ILLUSTRATION:" header are applied by JACC editorial after acceptance — authors submit only the content figure + citation.
Before specifying figure type, read ${CLAUDE_SKILL_DIR}/references/design_principles.md —
identify (1) the one-sentence key message, (2) audience and reading-time budget, and
(3) whether a figure is the right vehicle (vs a small table or in-line text). The
five strategies in that file shift Step 1 from "which chart fits the data" to
"what should the reader remember 10 seconds later." Skip only when the figure
is mandated by a reporting guideline (e.g., PRISMA / CONSORT flow), and even
then apply the cognitive-load checklist.
For reporting-guideline figures, also load
${CLAUDE_SKILL_DIR}/references/reporting_guideline_figure_map.md — the
14-row table tells you which guideline mandates which figures and whether
this skill ships an official template (✅), generic flow only (⚠️), or
needs manual production (❌). Critical for AI-extension guidelines
(CONSORT-AI, STARD-AI, TRIPOD+AI, CLAIM 2024, DECIDE-AI).
For medical AI / engineering pipeline figures (DICOM workflow,
annotation pipeline, federated learning topology, model architecture),
also load ${CLAUDE_SKILL_DIR}/references/pipeline_concepts_medical_ai.md —
canonical layouts, required annotations, and tool selection per type.
Optional flags:
--study-type <type>: One of: diagnostic-accuracy, ai-validation, meta-analysis, dta-meta-analysis, observational-cohort, rct. When set, auto-generate the full figure set from the Study-Type Figure Sets table below without prompting for individual figure types.--data-dir <path>: Directory containing analysis outputs (CSVs, _analysis_outputs.md). Default: current working directory.Ask the user for:
--study-type is provided--study-type): determines the required figure setIf the user provides enough context, infer missing parameters and confirm before proceeding.
import matplotlib.pyplot as plt
import os
style_path = os.path.join(os.environ.get('CLAUDE_SKILL_DIR', '.'), '../analyze-stats/references/style/figure_style.mplstyle')
if os.path.exists(style_path):
plt.style.use(style_path)
${CLAUDE_SKILL_DIR}/references/figure_specs.md.Create the figure using Python (matplotlib/seaborn as primary, with specialized libraries as needed).
Script structure:
"""
Figure: {description}
Date: {YYYY-MM-DD}
Target: {journal}
Dimensions: {width} x {height} inches @ {DPI} DPI
"""
import numpy as np
import matplotlib.pyplot as plt
import os
style_path = os.path.join(os.environ.get('CLAUDE_SKILL_DIR', '.'), '../analyze-stats/references/style/figure_style.mplstyle')
if os.path.exists(style_path):
plt.style.use(style_path)
# Wong colorblind-safe palette
WONG = ['#000000', '#E69F00', '#56B4E9', '#009E73',
'#F0E442', '#0072B2', '#D55E00', '#CC79A7']
np.random.seed(42)
Present the figure to the user and ask:
Iterate until the user approves.
Before Step 5 Export, run the automated Critic Loop. This is two stages — deterministic quantitative checks via Python, then qualitative review by Claude itself — and the combined output tells us whether to re-render or hand off to the user.
Stage 1: Quantitative checks (critic_figure.py)
python ${CLAUDE_SKILL_DIR}/scripts/critic_figure.py \
figures/fig1_stard.png \
--type stard \
--spec-min-dpi 600 \
--spec-width-in 7.0 \
--source-text figures/fig1_stard.txt \ # optional: expected strings for OCR coverage
--out figures/fig1_stard.critique.json
This produces a JSON report covering:
Stage 2: Qualitative review (Claude session)
${CLAUDE_SKILL_DIR}/references/critic_rubrics/flow_diagram.md
(sections A–G; section G adds cognitive-load and template-fidelity checks)${CLAUDE_SKILL_DIR}/references/critic_rubrics/data_plot.md
(sections A–G; section G adds calibration / fairness / colorblind+redundant /
dataset-flow / decision-curve checks for medical AI papers)${CLAUDE_SKILL_DIR}/references/flow_diagram_lessons.md — five
production lessons covering official-template fidelity, PDF export
fidelity (VML fallback), docx XML escape, sequential placeholder
mapping, and frozen-version sync with the manuscript.${CLAUDE_SKILL_DIR}/references/reporting_guideline_figure_map.md —
the row for the target guideline lists mandatory figures and which
ones this skill cannot template (production path documented per
row).${CLAUDE_SKILL_DIR}/references/pipeline_concepts_medical_ai.md.${CLAUDE_SKILL_DIR}/references/exemplar_diagrams/{type}/,
Read 1–3 of them plus their _why.md notes. For a non-flow data plot (forest, ROC, KM,
calibration), read the matching anatomy model in
${CLAUDE_SKILL_DIR}/references/exemplar_plots/ (e.g., forest_plot.md).Refinement loop
critic_pass: yes.critic_pass: partial and record the residual items in the manifest's
critic_notes field.Record the final state in _figure_manifest.md (see the manifest format
below) so downstream steps (/write-paper Phase 2 embedding and Phase 7
DOCX build) and future critic passes can see the history.
Save final outputs:
Name files descriptively: fig1_roc_curve.pdf, fig2_consort_flow.pdf, etc.
For PPTX outputs (visual abstract, central illustration, or any deck the figure
will live in): run the Mac-compatibility validator before delivery. PowerPoint
Mac silently drops TIFF, renders <a:sp3d> 3-D bevels as red outlines that PDF
export does not show, and refuses to open files whose app.xml slide count
disagrees with the actual slide XML files. This script catches all four classes
of defect codified in ~/.claude/rules/pptx-mac-compatibility.md:
python ${CLAUDE_SKILL_DIR}/scripts/validate_pptx_mac_compat.py \
figures/visual_abstract.pptx \
--json figures/visual_abstract.mac_compat.json \
--strict
Exit code 1 means at least one FAIL — fix per the fix: field in the JSON
report and re-render the PPTX before delivery. Exit code 0 with WARN is
acceptable. Skip this step when the figure is PNG/PDF only (no PPTX).
Before delivering the final figure, verify all items:
When the study type is known (from /write-paper Phase 0 or user specification), auto-detect and generate the complete required figure set without asking for each figure individually.
| Study Type (Guideline) | Required Figures |
|---|---|
| Diagnostic accuracy (STARD) | STARD flow diagram, ROC curve, confusion matrix, calibration plot |
| AI validation (TRIPOD+AI / CLAIM) | Flow diagram, ROC curve, confusion matrix, calibration plot, feature importance or SHAP, Grad-CAM (if imaging) |
| Meta-analysis (PRISMA) | PRISMA flow diagram, forest plot, funnel plot |
| DTA meta-analysis (PRISMA-DTA) | PRISMA flow diagram, paired forest plot (Se + Sp), SROC curve, Deeks funnel plot |
| Observational cohort (STROBE) | Flow diagram, Kaplan-Meier curves (if survival endpoint) |
| RCT (CONSORT) | CONSORT flow diagram, primary endpoint figure |
After generating all figures, create a structured manifest file at figures/_figure_manifest.md:
# Figure Manifest
Generated: {YYYY-MM-DD}
Study type: {study type or "custom"}
| Figure | Path | Type | Tool | Critic | Rounds | Description |
|--------|------|------|------|--------|--------|-------------|
| Figure 1 | figures/fig1_stard_flow.svg | flow-diagram | D2 | yes | 2 | STARD participant flow diagram |
| Figure 2 | figures/fig2_roc.pdf | roc-curve | matplotlib | yes | 1 | ROC curves for Model A vs B |
| Figure 3 | figures/fig3_calibration.pdf | calibration | matplotlib | partial | 3 | Calibration plot; legend still crowded (see notes) |
## Critic notes
- Figure 3: after 3 rounds, legend placement remains crowded at the
double-column width. Candidate remediations documented but not applied
to avoid reducing data-point visibility.
Manifest field definitions:
flow-diagram, roc-curve, forest-plot, funnel-plot, calibration, km-curve, bland-altman, confusion-matrix, box-violin, bar-chart, heatmap, pipeline, visual-abstract, sroc-curve, othermatplotlib, D2, python-pptx, seaborn, etc.)yes (all rubric items PASS) / partial (some PARTIAL after max rounds) / no (never critiqued — avoid for submission figures) / skip (deliberately bypassed, e.g., panel figure assembled externally)A ## Critic notes section at the bottom of the manifest records any
residual PARTIAL items and the rationale for accepting them.
This manifest is consumed by /write-paper Phase 2 (figure embedding) and Phase 7 (DOCX build). It MUST exist after figure generation completes. Verify the file is non-empty before finishing.
Flow diagram generation rule: STARD/CONSORT/PRISMA/STROBE flow diagrams MUST use the standardized R pipeline scripts/generate_flow_diagram.R (DiagrammeR + Graphviz dot + rsvg). This is the single canonical tool for all four reporting-guideline flow diagrams. Do NOT use matplotlib FancyBboxPatch (manual coordinates break when text changes, and patches distort when embedded in DOCX). Do NOT use D2 for new flow diagrams (font control is weak, overlap requires manual post-processing). The legacy D2 recipe remains documented below as a fallback only when R is unavailable.
R flow diagram recipe (mandatory for all flow diagrams):
The pipeline reads a YAML config describing nodes/edges and produces: a true vector PDF (journal submission), a 300 dpi PNG (review copy), and a 600 dpi PNG (RSNA/Eur Radiol line-art). Default style is single-color black outline with white fill in Arial, overriding D2's colored defaults and matplotlib's manual coordinates.
# 1. One-time system dependency:
brew install librsvg
Rscript -e 'install.packages(c("DiagrammeR","DiagrammeRsvg","rsvg","yaml"))'
# 2. Author a YAML config. Templates for each type live at
# references/exemplar_diagrams/{strobe,consort,prisma,stard}/template_input.yaml
# 3. Render:
Rscript ${CLAUDE_SKILL_DIR}/scripts/generate_flow_diagram.R \
--type {strobe|consort|prisma|stard} \
--config path/to/counts.yaml \
--out figures/figure1_flow
# Outputs: figure1_flow.pdf, figure1_flow.png (300 dpi), figure1_flow_600.png
YAML schema highlights:
rankdir: TB (top-down, default) or LR (left-to-right).nodes: list with id, label (use literal \n for line breaks, real Unicode –, ≤, −, •).highlight: true (thicker border), shape: note (side boxes), rank_same_with: <other_id> (place on same horizontal rank).edges: list with from, to, optional style: dashed, arrow: false (no arrowhead), constraint: false (edge ignored by layout engine — use for exclusion side-links).Style is fixed (do not override in the YAML):
color=black, fillcolor=white, fontname="Arial".\l (left-align), never \n (center). Each \l applies to text preceding it.label=<...> with <B>, <I>, •). Plain quoted labels with \l bullets produce tighter, more readable structure than HTML ragged wrapping. Do not reintroduce without explicit approval.#0072B2 for a single highlighted box), edit scripts/generate_flow_diagram.R — do not inline hex colors in YAML.Per-project create_figure1.R pattern (preferred for complex flows):
When the flow has derived counts, stopifnot() reconciliation, multi-rank {rank=same; ... } constraints, or exclusion side-cars that the generic YAML dispatcher cannot express cleanly, write a per-project create_figure1.R directly (same DiagrammeR + DiagrammeRsvg + rsvg stack, sprintf'd dot string). This is the dominant pattern when the generic YAML dispatcher cannot capture the flow:
<project>/manuscript/figures/create_figure1.R<project>/Analysis/figures/create_figure1.R or <project>/figures/v2_monochrome/create_figure1.R<project>/5_Figures/create_figure1.R or <project>/analysis/create_figure1.R<project>/figures/v2_monochrome/create_figure1.RCopy the STYLE_HEADER (graph/node/edge attrs) verbatim from any exemplar; then customise nodes, edges, and {rank=same} blocks. Use read.csv() for cohort counts when possible; if hardcoded, every number must have a source comment referencing manuscript line / CSV cell / screening log row.
Legacy D2 fallback (only when R unavailable):
d2 --layout elk --theme 0 --pad 20 flow.d2 /tmp/raw.png --scale 2
# Resize + 85% vertical compression via Pillow; then render PDF:
d2 --layout elk --theme 0 --pad 20 flow.d2 figures/fig1_flow.pdf
Use font-size: 20-24, stroke: black, fill: white. D2 PDF is vector; D2 PNG needs the resize step to match publication density.
Choose the right tool for each figure type. Using matplotlib for flow diagrams leads to hard-coded coordinates that break when text changes — use auto-layout tools instead.
Best for figures where data drives the layout. This skill handles these directly:
| Type | Use Case | Key Library |
|---|---|---|
| ROC Curve | Diagnostic accuracy | matplotlib, sklearn |
| Forest Plot | Meta-analysis | matplotlib |
| Calibration Plot | Prediction model | matplotlib |
| KM Curve | Survival analysis | lifelines, matplotlib |
| Bland-Altman | Agreement | matplotlib |
| Confusion Matrix | Classification | seaborn |
| Box/Violin Plot | Group comparison | seaborn |
| Bar Chart | Categorical comparison | matplotlib |
| Heatmap | Correlation/agreement | seaborn |
Flow diagrams require auto-layout engines. Do NOT use matplotlib patches with manual coordinates — this causes the "absolute coordinate hell" problem where changing one box breaks all downstream positions.
| Type | Recommended Tool | Why |
|---|---|---|
| STROBE (cohort / cross-sectional) | scripts/generate_flow_diagram.R --type strobe | Single canonical tool; auto-layout; vector PDF + 300/600 dpi PNG |
| CONSORT (RCT) | scripts/generate_flow_diagram.R --type consort | Same pipeline; monochrome Arial default |
| PRISMA 2020 (SR/MA) | scripts/generate_flow_diagram.R --type prisma | Faithfully implements PRISMA 2020 structure; avoids PRISMA2020 R package's webshot-based raster PDF issue |
| STARD (DTA) | scripts/generate_flow_diagram.R --type stard | Same pipeline; supports 2x2 reference-standard split |
| Pipeline Diagram | D2 (legacy) | Until pipeline-diagram support is added to the R script |
R workflow for flow diagrams: See the "R flow diagram recipe" above in the Flow diagram generation rule. Key points: YAML config → Rscript scripts/generate_flow_diagram.R --type <t> --config <yaml> --out <prefix> → PDF + 300/600 dpi PNG. Templates in references/exemplar_diagrams/{strobe,consort,prisma,stard}/template_input.yaml.
templates/official/When a journal requires the canonical, statement-issued template (rather than
the auto-laid-out R version), use the bundled official files in
templates/official/{prisma2020,consort2010,stard2015,spirit2013}/.
| Guideline | What ships | When to use |
|---|---|---|
| PRISMA 2020 | Locally built .pptx (4 variants) + fill_prisma_template.py | Reviewer asks for the official PRISMA 2020 layout, or you want editable PowerPoint instead of an R-rendered PDF. |
| STROBE (cohort) | Parametric .pptx builder build_strobe_template.py (single-script, takes YAML config) | Cohort/case-control study Figure 1 when co-authors want PowerPoint they can hand-edit. Auto-fits text, content-fits slide, dashed-border exclusion side-branches with strictly-horizontal connectors. Optional left-side phase column (omit stages: for the plain STROBE convention; include it for the PRISMA-style Identification/Screening/Inclusion/Analysis column). Pair with generate_flow_diagram.R --type strobe for the vector PDF/TIFF submission file. |
| CONSORT 2025 | Official .docx flow diagram + checklist | RCT submissions to journals that mandate the consort-spirit.org template. |
| STARD 2015 | Official .pdf flow diagram + .docx checklist | Diagnostic accuracy studies; flow diagram is fixed PDF, checklist is editable. |
| SPIRIT 2025 | Official .docx participant timeline + checklist | Trial protocols. |
Refresh / fill workflow:
# Refresh from canonical sources (CC-BY 4.0 / public-statement licenses)
bash ${CLAUDE_SKILL_DIR}/scripts/fetch_official_templates.sh
# Build PRISMA 2020 .pptx (one-time; site blocks programmatic .docx fetch)
python3 ${CLAUDE_SKILL_DIR}/scripts/build_prisma2020_template.py \
--variant new \
--out ${CLAUDE_SKILL_DIR}/templates/official/prisma2020/PRISMA_2020_flow_new_v1.pptx
# Fill counts — positional 10-tuple matching most SR/MA workflows:
# n_db, n_dup, n_screened, n_screen_excluded,
# n_sought, n_assessed, n_excl_r1, n_excl_r2, n_excl_r3, n_studies
python3 ${CLAUDE_SKILL_DIR}/scripts/fill_prisma_template.py \
--template ${CLAUDE_SKILL_DIR}/templates/official/prisma2020/PRISMA_2020_flow_new_v1.pptx \
--counts "315,122,186,7,111,204,102,84,3,15" \
--out fig1_prisma_filled.pptx
# Or use full JSON mapping for studies with non-standard PRISMA splits
python3 ${CLAUDE_SKILL_DIR}/scripts/fill_prisma_template.py \
--template ${CLAUDE_SKILL_DIR}/templates/official/prisma2020/PRISMA_2020_flow_new_v1.pptx \
--counts-file my_counts.json \
--out fig1_prisma_filled.pptx
# STROBE — parametric single-script builder (cohort study; spine structure varies per study).
# YAML schema: stages, spine (id/stage/text), exclusions (after/text). Consecutive same-stage
# rows share one phase label automatically. Stage box fills auto-pick readable text color.
python3 ${CLAUDE_SKILL_DIR}/scripts/build_strobe_template.py \
--config figures/figure1_strobe.yaml \
--out figures/figure1_strobe.pptx
For STROBE the canonical KJR/Radiology/BMJ submission flow is:
Rscript ${CLAUDE_SKILL_DIR}/scripts/generate_flow_diagram.R --type strobe --config figures/figure1_strobe_graphviz.yaml --out figures/figure1build_strobe_template.py so co-authors and senior reviewers can adjust prose/positioning before sign-off.See templates/official/NOTES.md for licenses, attribution, and refresh notes.
| Type | Recommended Tool |
|---|---|
| Visual Abstract (any journal) | generate_visual_abstract.py with PPTX template |
| Visual element illustration | Study's own figures (preferred), or free libraries (Servier/NIAID) |
| Medical Illustration | See ${CLAUDE_SKILL_DIR}/references/medical_illustration_sources.md |
See the Visual Abstract section above for the full workflow.
Data plots: matplotlib/seaborn → PDF + PNG (this skill)
Flow diagrams: generate_flow_diagram.R (DiagrammeR + rsvg) → PDF + 300/600 dpi PNG
Final assembly: pandoc or python-docx (auto-embedded in DOCX)
| Type | Use Case | Key Library | Output |
|---|---|---|---|
| ROC Curve | Diagnostic accuracy | matplotlib, sklearn | Single/multi-model ROC with AUC |
| Forest Plot | Meta-analysis | matplotlib | Effect sizes with CIs, diamond summary |
| Calibration Plot | Prediction model | matplotlib | Observed vs predicted with Hosmer-Lemeshow |
| KM Curve | Survival analysis | lifelines, matplotlib | With risk table, log-rank p |
| Bland-Altman | Agreement | matplotlib | With mean diff, +/-1.96 SD limits |
| Confusion Matrix | Classification | seaborn | Heatmap with percentages |
| Box/Violin Plot | Group comparison | seaborn | With individual data points |
| Pipeline Diagram | Methods figure | D2 (preferred) or matplotlib | Processing/workflow steps |
| Bar Chart | Categorical comparison | matplotlib | With error bars (CI or SD) |
| Heatmap | Correlation/agreement | seaborn | Color-coded matrix |
from sklearn.metrics import roc_curve, auc
fig, ax = plt.subplots(figsize=(3.5, 3.5))
fpr, tpr, _ = roc_curve(y_true, y_score)
roc_auc = auc(fpr, tpr)
ax.plot(fpr, tpr, color=WONG[5], lw=1.5,
label=f'Model (AUC = {roc_auc:.3f})')
ax.plot([0, 1], [0, 1], 'k--', lw=0.8, alpha=0.5)
ax.set(xlabel='1 - Specificity', ylabel='Sensitivity',
xlim=[-0.02, 1.02], ylim=[-0.02, 1.02])
ax.legend(loc='lower right', frameon=False)
Single canonical tool: scripts/generate_flow_diagram.R (see the R flow diagram recipe above). Do not fall back to matplotlib for flow diagrams — manual coordinates break when text changes and patches distort in DOCX. D2 remains a documented legacy fallback only when R is unavailable.
Layout invariants:
shape: note) for exclusion side-boxes."Assessed for eligibility\n(n = 450)").GAP_SMALL = 1.5, GAP_BRANCH = 2.2).D2 approach (recommended):
d2 --layout elk --theme 0 flow.d2 output.svg
# Then: open SVG in Figma → grid-snap → font swap → export PDF
Caption ↔ flow-SSOT reconciliation (before Step 5 Export). The flow-diagram config (the YAML/script that generate_flow_diagram.R consumes) is the single source of truth for participant counts. A hand-written Figure 1 caption drifts from it whenever the cohort is re-locked but the caption is not — the classic "caption says n = 1,284 analytic, diagram box says n = 998" defect, which surfaces only at submission. Re-derive the caption counts from the flow config and reconcile:
python3 ${CLAUDE_SKILL_DIR}/scripts/derive_figure_legend_counts.py \
--flow-config figures/figure1_strobe_graphviz.yaml \
--manuscript manuscript/index.qmd \
--out qc/figure_legend_counts.json --strict
Any n = N in the caption that is not a box count in the flow config is a MISMATCH (stale caption) — update the caption from the config, never the reverse. This pairs with numerical-safety's "re-derive prose counts every revision" rule and with /sync-submission's cross-document N checks. (The reconciler is stdlib-only and parses the config as text, so it works regardless of the flow tool.)
Wong colorblind-safe palette (default):
WONG = ['#000000', '#E69F00', '#56B4E9', '#009E73',
'#F0E442', '#0072B2', '#D55E00', '#CC79A7']
Sequential palettes (for heatmaps):
Blues or Greenscoolwarm or RdBu_rYlOrRdRules:
| Element | Font Size | Weight |
|---|---|---|
| Figure title (if any) | 10 pt | Bold |
| Axis label | 9 pt | Regular |
| Tick label | 8 pt | Regular |
| Legend text | 8 pt | Regular |
| Annotation | 8 pt | Regular |
| Panel label (A, B, C) | 12 pt | Bold |
Default dimensions (override from figure_specs.md if journal-specific):
For composite figures with multiple panels:
fig, axes = plt.subplots(nrows, ncols, figsize=(width, height))
# Label each panel
for ax, label in zip(axes.flat, 'ABCDEFGH'):
ax.text(-0.15, 1.05, label, transform=ax.transAxes,
fontsize=12, fontweight='bold', va='top')
Common layouts:
figsize=(7.0, 3.5), 1 row x 2 colsfigsize=(3.5, 7.0), 2 rows x 1 colfigsize=(7.0, 7.0), 2 rows x 2 colsfigsize=(7.0, 3.0), 1 row x 3 colsUse plt.tight_layout() or fig.subplots_adjust() for spacing.
After generating each figure, draft a caption following these rules:
Example:
Figure 1. Receiver operating characteristic curves comparing the diagnostic performance of the multi-agent pipeline (blue) and single-agent baseline (orange) for identifying incorrect Anki flashcard content. The area under the curve was 0.92 (95% CI: 0.89-0.95) for the multi-agent pipeline and 0.84 (95% CI: 0.80-0.88) for the single-agent baseline (DeLong test, p = 0.003). The dashed diagonal line represents chance performance.
| When | Call | Purpose |
|---|---|---|
| Need statistical values for plot | /analyze-stats | Get computed values (AUC, CI, p-values) |
| Flow diagram for manuscript | /write-paper Phase 2 | Coordinate with Tables & Figures plan |
| Caption review | /write-paper Phase 7 | Final polish pass |
tight_layout(), reduce font size, or adjust spacing.ImageMagick, Ghostscript, FFmpeg are installed and can be used for post-processing:
# Figure DPI/format conversion for journal submission
magick input.png -density 300 -units PixelsPerInch output.tiff
magick input.png -resize 1200x -quality 95 output.jpg
# CMYK conversion (some print journals require this)
magick input.png -colorspace CMYK output.tiff
# Multi-panel figure assembly (A/B/C/D panels)
magick montage panelA.png panelB.png panelC.png panelD.png \
-tile 2x2 -geometry +10+10 -density 300 combined.png
# Animated figure (GIF from frame sequence)
ffmpeg -framerate 2 -i frame_%03d.png -vf "scale=800:-1" output.gif
# Video from figure sequence (for supplementary materials)
ffmpeg -framerate 1 -i slide_%03d.png -c:v libx264 -pix_fmt yuv420p supplementary_video.mp4
AI illustration is a supplementary option, not a requirement. Visual abstracts and figures can be completed without any API key using study figures and free illustration libraries.
If GEMINI_API_KEY is set, the generate_image.py script can generate illustrations:
python ${CLAUDE_SKILL_DIR}/scripts/generate_image.py \
"Clean medical illustration of a CT-guided lung biopsy procedure, \
flat vector style, white background, no text" \
--output output.png --aspect 16:9
Use for: procedural schematics, anatomical illustrations, pipeline diagrams. Always review AI output against the AI-Generated Figure Warning section above.
If GEMINI_API_KEY is not set, guide the user to free illustration resources:
see ${CLAUDE_SKILL_DIR}/references/medical_illustration_sources.md.
/search-lit with confirmed DOI or PMID. Mark unverified references as [UNVERIFIED - NEEDS MANUAL CHECK].[VERIFY] and ask the user.npx claudepluginhub aperivue/medsci-skills --plugin medsci-projectGuides chart type selection by data structure, accessible color palettes like viridis and Okabe-Ito, figure composition, and journal formatting for scientific publications and talks.
Creates publication-ready figures and composite layouts from a senior-researcher perspective. Uses Python (matplotlib/seaborn/plotly/altair), R (ggplot2), MATLAB, TikZ, Graphviz, and more. Applies consistent aesthetics, colorblind-safe palettes, journal-specific sizing, and high-resolution export suitable for direct submission.
Creates publication-ready scientific figures with multi-panel layouts, error bars, significance annotations, and colorblind-safe palettes. Orchestrates matplotlib, seaborn, and plotly for journal submission (Nature, Science, Cell).