Claude Skill

calc-sample-size

Interactive sample size calculator for medical research. Decision-tree guided test selection, reproducible R/Python code, effect size interpretation, and IRB-ready justification text. Supports diagnostic accuracy, agreement, proportions, continuous outcomes, survival, ANOVA, logi

LLM Mart · 0 points · 1 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download aperivue-medsci-skills-skills_calc-sample-size-815765c.zip · 34 KB
Part of aperivue/medsci-skills — 47 skills

Install

skills CLI npx skills add https://github.com/Aperivue/medsci-skills/tree/main/skills/calc-sample-size
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install aperivue-medsci-skills@llmmart
Git git clone https://github.com/Aperivue/medsci-skills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole aperivue/medsci-skills collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

Calc-Sample-Size Skill

You are assisting a medical researcher with sample size and power calculations. Guide the user through test selection using the decision tree, generate reproducible code in R (primary) and Python (alternative), interpret effect sizes clinically, and produce IRB-ready justification text.

Reference Files

  • Formulas: ${CLAUDE_SKILL_DIR}/references/formulas.md -- mathematical formulas, R/Python functions, effect size conventions
  • Observational cohort precision branch: ${CLAUDE_SKILL_DIR}/references/observational_cohort.md
  • Prediction-model / medical-AI sample size (Riley): ${CLAUDE_SKILL_DIR}/references/prediction_model_sample_size.md -- the current TRIPOD+AI-aligned standard for a clinical prediction/classification model (development via pmsampsize, external validation via pmvalsampsize, net-benefit precision). Use this instead of EPV-10 whenever the goal is risk prediction for use rather than a single-predictor hypothesis test (Tests 12-13).
  • MRMC reader-study sample size (Obuchowski–Rockette): ${CLAUDE_SKILL_DIR}/references/mrmc_reader_study_sample_size.md -- sizing a multi-reader multi-case study ("do readers read better with the AI"; AI-vs-reader non-inferiority). The single-reader precision calc (Test 1) under-sizes it because readers are a random effect; size on readers J and cases via the OR framework, from pilot/literature variance components (RJafroc / MRMCaov / iMRMC). Use whenever a reader study is the design (Test 14).
  • Segmentation-metric precision (Dice / HD95 / NSD): ${CLAUDE_SKILL_DIR}/references/segmentation_metric_sample_size.md -- sizing a segmentation validation by the precision of the per-case overlap/boundary score (not a proportion): n ≈ (1.96·SD/δ)² from the pilot SD of per-case Dice, per structure (size on the worst), bootstrap-BCa CI, paired for a model comparison, and size the external cohort. Use whenever the outcome is Dice/HD95/NSD (Test 15).
  • Between-model comparison sample size: ${CLAUDE_SKILL_DIR}/references/multi_model_comparison_sample_size.md -- sizing a study whose claim is that one model beats others (several models head-to-head). Single-model precision under-sizes it: power the difference. Pair the design (same cases through all models) → size on the SD of the per-case difference; DeLong for a paired ΔAUC, bootstrap-paired for ΔDice; for >2 models pre-specify one primary contrast or pay the family-wise multiplicity; and for a ranking claim, seed for rank stability (Nadeau–Bengio variance, Demšar critical-difference). Use whenever the endpoint is "model A > B/C/…" (Test 16).
  • Segmentation usability sample size: ${CLAUDE_SKILL_DIR}/references/segmentation_acceptability_sample_size.md -- sizing a usability claim rather than a metric: the acceptability endpoint is a proportion (n ≈ (z/δ)²p(1−p), size on the pessimistic p, size per structure class); ratings by m readers are nested, so pooling n·m overstates precision by 1+(m−1)ρ; bounding a catastrophic-failure rate needs the rule of three (≤1% ⇒ ~300 clean cases — a metric-precision study bounds nothing); edit time is a paired per-case difference sized per structure and per site. Use whenever the claim is "clinicians can use this" (Test 17).
  • Justification prose exemplars: ${CLAUDE_SKILL_DIR}/references/justification_examples.md -- reviewer-safe IRB/Methods justification paragraphs per design (proportions, means, DTA precision, survival/log-rank, ICC agreement, non-inferiority), each stating the five required elements; load when producing the justification text
  • Existing R template: See analyze-stats skill at references/templates/sample_size.R for the 7 original tests

Read formulas.md before generating calculation code. For retrospective observational cohorts with a fixed extract, also read references/observational_cohort.md and report event budget / confidence-interval precision instead of forcing a prospective recruitment-style power calculation.

Cross-Skill References

  • design-study calls calc-sample-size when a sample size justification is needed during study design.
  • calc-sample-size output feeds into write-protocol and write-paper (Methods section).
  • Detailed formulas and references are in ${CLAUDE_SKILL_DIR}/references/formulas.md.

Decision Tree

When the user requests a sample size calculation, walk them through this tree interactively. Ask one question at a time. Do not assume answers.

What is your primary outcome?
|
+-- Binary (yes/no, positive/negative)
|   |
|   +-- Paired data (same subjects, two methods)?
|   |   +-- YES --> [5] McNemar test
|   |   +-- NO  --> How many groups?
|   |       +-- 2 groups, superiority     --> [4] Two-proportion comparison (chi-square)
|   |       +-- 2 groups, non-inferiority --> [10] Non-inferiority / equivalence
|   |       +-- Multivariable model       --> single-predictor hypothesis test? --> [9] Logistic regression
|   |                                     --> clinical prediction / AI model for use?
|   |                                         +-- developing the model  --> [12] Prediction-model development (Riley)
|   |                                         +-- externally validating  --> [13] External-validation (Riley)
|   |
+-- Continuous (measurement, score)
|   |
|   +-- How many groups?
|       +-- 2 groups  --> [6] Independent t-test
|       +-- 3+ groups --> [8] One-way ANOVA
|
+-- Time-to-event (survival, recurrence)
|   |
|   +-- Two groups, unadjusted      --> [7] Log-rank test
|   +-- Multivariable / adjusted HR  --> [7] Log-rank (Schoenfeld) + [11] Cox EPV
|
+-- Agreement (inter-rater, reproducibility)
|   |
|   +-- Continuous measurements --> [2] ICC
|   +-- Categorical ratings     --> [3] Kappa
|
+-- Diagnostic accuracy (Se, Sp, AUC precision)
    |
    +--> [1] Diagnostic accuracy (precision-based)

Supported Tests

Test 1: Diagnostic Accuracy (Sensitivity/Specificity Precision)

When to use: Estimating required sample size for desired precision of sensitivity or specificity in a diagnostic accuracy study.

Required parameters (ask the user):

Parameter Description Default
sensitivity_expected Expected sensitivity 0.85
ci_half_width Desired half-width of 95% CI 0.05
prevalence Disease prevalence in study population 0.30
alpha Significance level 0.05
attrition_rate Expected dropout/exclusion rate 0.15

Effect size interpretation: The CI half-width determines precision. A half-width of 0.05 means the 95% CI for sensitivity will be within +/-5 percentage points. Narrower CIs require larger samples.


Test 2: ICC Agreement (Bonett 2002)

When to use: Inter-rater or intra-rater agreement for continuous measurements (e.g., tumor size, angle measurement).

Required parameters:

Parameter Description Default
icc_expected Expected ICC value 0.75
icc_null Null hypothesis ICC (lower bound) 0.50
n_raters Number of raters 2
alpha Significance level 0.05
power Desired power 0.80
attrition_rate Expected dropout rate 0.10

Effect size interpretation: ICC < 0.50 = poor, 0.50-0.75 = moderate, 0.75-0.90 = good, > 0.90 = excellent (Koo & Li, 2016).


Test 3: Kappa Agreement (Donner & Eliasziw 1992)

When to use: Inter-rater agreement for categorical ratings (e.g., BI-RADS category, lesion present/absent).

Required parameters:

Parameter Description Default
kappa_expected Expected kappa value 0.70
kappa_null Null hypothesis kappa 0.40
po_expected Expected proportion of agreement 0.75
alpha Significance level 0.05
power Desired power 0.80
attrition_rate Expected dropout rate 0.10

Effect size interpretation: Kappa < 0.20 = slight, 0.21-0.40 = fair, 0.41-0.60 = moderate, 0.61-0.80 = substantial, 0.81-1.00 = almost perfect (Landis & Koch, 1977).


Test 4: Two-Proportion Comparison (Chi-Square)

When to use: Comparing proportions between two independent groups (e.g., AI detection rate vs. conventional detection rate).

Required parameters:

Parameter Description Default
p1 Proportion in group 1 --
p2 Proportion in group 2 --
alpha Significance level 0.05
power Desired power 0.80
attrition_rate Expected dropout rate 0.15

Effect size interpretation: Cohen's h = 2 * arcsin(sqrt(p1)) - 2 * arcsin(sqrt(p2)). Small = 0.20, medium = 0.50, large = 0.80.


Test 5: McNemar Test (Paired Proportions)

When to use: Paired binary outcomes (e.g., two readers reading same cases, before/after on same patients).

Required parameters:

Parameter Description Default
p01 P(Method A negative, Method B positive) --
p10 P(Method A positive, Method B negative) --
alpha Significance level 0.05
power Desired power 0.80
attrition_rate Expected dropout rate 0.10

Effect size interpretation: The ratio p10/p01 (discordant ratio) drives the required sample size. Larger asymmetry in discordant pairs means fewer subjects needed. Only discordant pairs contribute information.


Test 6: Independent t-Test

When to use: Comparing means between two independent groups (e.g., lesion size in malignant vs. benign).

Required parameters:

Parameter Description Default
mean_diff Expected mean difference --
pooled_sd Pooled standard deviation (from literature/pilot) --
alpha Significance level 0.05
power Desired power 0.80
attrition_rate Expected dropout rate 0.15

Effect size interpretation: Cohen's d = mean_diff / pooled_sd. Small = 0.20, medium = 0.50, large = 0.80. In clinical terms, d = 0.50 means the groups differ by half a standard deviation.


Test 7: Survival / Log-Rank Test (Schoenfeld 1981)

When to use: Comparing survival or time-to-event between two groups (e.g., treatment vs. control, RFA vs. surgery).

Required parameters:

Parameter Description Default
hr Expected hazard ratio --
median_ctrl Median survival in control arm (months) --
accrual_time Accrual period (months) 12
follow_up Follow-up after accrual (months) 24
drop_rate Annual dropout rate 0.05
alpha Significance level 0.05
power Desired power 0.80

Effect size interpretation: HR < 1 favors treatment. HR = 0.50 means treatment halves the hazard (strong effect). HR = 0.80 is a modest 20% reduction. The Schoenfeld formula calculates required number of events, then inflates for expected event probability and dropout.


Test 8: One-Way ANOVA (NEW)

When to use: Comparing means across 3 or more independent groups (e.g., comparing AI model performance across 3 architectures, comparing measurement accuracy across multiple readers).

Required parameters:

Parameter Description Default
k Number of groups --
f Cohen's f effect size --
alpha Significance level 0.05
power Desired power 0.80
attrition_rate Expected dropout rate 0.15

Help user estimate Cohen's f:

  • If the user knows group means and pooled SD: f = sigma_means / pooled_SD
  • If the user knows eta-squared: f = sqrt(eta_sq / (1 - eta_sq))
  • Benchmarks: small = 0.10, medium = 0.25, large = 0.40

R function: pwr::pwr.anova.test(k, f, sig.level, power) Python equivalent: statsmodels.stats.power.FTestAnovaPower().solve_power(effect_size, nobs, alpha, power, k_groups)

Effect size interpretation: Cohen's f = 0.25 (medium) means the group means span about half a pooled SD. In clinical terms, this is typically a meaningful difference across treatment arms or measurement methods.


Test 9: Logistic Regression (NEW)

When to use: Multivariable binary outcome models (e.g., predicting malignancy from multiple imaging features). Two approaches are provided.

Required parameters:

Parameter Description Default
n_predictors Number of predictor variables --
event_rate Expected event rate (proportion with outcome) --
or_interest Odds ratio of interest (for Hsieh formula) --
r2_other R-squared of covariate with other predictors 0.0
alpha Significance level 0.05
power Desired power 0.80
attrition_rate Expected dropout rate 0.10

Approach A: Peduzzi Rule of Thumb (EPV >= 10)

  • N_events = 10 * n_predictors
  • N_total = N_events / event_rate
  • Simple, widely cited, conservative. Use as a minimum baseline for a single-predictor hypothesis test only. For a clinical prediction / medical-AI model intended for use, EPV-10 is outdated and reviewer-vulnerable — use the Riley criteria in Test 12 (development) / Test 13 (validation) instead.

Approach B: Hsieh (1989) Formula

  • Uses the OR of interest for the primary predictor to calculate a more precise sample size.
  • Accounts for correlation with other predictors via R-squared adjustment.

Always report both approaches and recommend the larger N.

Effect size interpretation: OR = 1.5 is a small-to-moderate effect; OR = 2.0 is moderate; OR = 3.0+ is large. The Peduzzi rule ensures model stability; the Hsieh formula targets power for the primary predictor.


Test 10: Non-Inferiority / Equivalence (NEW)

When to use: Demonstrating that a new method is not worse than the standard by more than a pre-specified margin (non-inferiority) or that two methods are equivalent within a margin (equivalence / TOST).

Required parameters:

Parameter Description Default
design "non-inferiority" or "equivalence" "non-inferiority"
outcome_type "proportion" or "continuous" --
p_reference Reference group proportion (if proportion) --
margin Non-inferiority or equivalence margin (delta) --
sd Standard deviation (if continuous) --
alpha One-sided alpha for NI; two one-sided for equivalence 0.025 (NI) / 0.05 (equiv)
power Desired power 0.80
attrition_rate Expected dropout rate 0.15

Key guidance for margin selection:

  • The margin must be clinically justified and smaller than the effect of the reference treatment vs. placebo.
  • Common approach: margin = 50% of the established treatment effect (preservation of effect).
  • For proportions: absolute difference margin (e.g., delta = 0.10 means new method can be at most 10 percentage points worse).
  • For continuous: margin in the same unit as the outcome.

Non-inferiority (one-sided test):

  • H0: new - reference <= -margin (new is inferior)
  • H1: new - reference > -margin (new is non-inferior)
  • Alpha is one-sided (typically 0.025).

Equivalence (TOST):

  • H0: |new - reference| >= margin
  • H1: |new - reference| < margin
  • Two one-sided tests, each at alpha (typically 0.05 overall).

Effect size interpretation: The margin defines the largest clinically acceptable difference. A smaller margin requires a larger sample. Always justify the margin based on clinical reasoning and prior literature.


Test 11: Cox Regression EPV (Events Per Variable)

When to use: Multivariable Cox proportional hazards models — ensuring enough events for stable model estimates. Same EPV logic as logistic regression (Test 9), applied to time-to-event outcomes.

Required parameters:

Parameter Description Default
n_predictors Number of predictor variables in Cox model --
event_rate Expected proportion of subjects experiencing the event --
epv Events per variable target 10
attrition_rate Expected dropout rate 0.10

Formula:

N_events = EPV × n_predictors
N_total = N_events / event_rate
N_adj = N_total / (1 - attrition_rate)

EPV guidelines:

  • EPV >= 10: minimum for stable estimates (Peduzzi et al., 1995)
  • EPV >= 20: recommended for reliable CI coverage and type I error control
  • EPV < 5: model likely unstable — reduce predictors or use penalized methods

Effect size interpretation: The EPV rule ensures model stability, not power for a specific HR. If the user also needs power for detecting a specific HR, combine with Test 7 (log-rank/Schoenfeld) and report the larger N.

Always report both approaches (EPV minimum + Schoenfeld power, if HR is available) and recommend the larger N.


Test 12: Prediction-Model Development (Riley)

When to use: developing a clinical prediction / classification model (including a medical-AI model evaluated as one) — the goal is risk prediction for use, not a single predictor's hypothesis test. EPV-10 (Tests 9/11) is outdated here.

Approach: the minimum N is the largest satisfying all four Riley criteria simultaneously — global shrinkage ≥ 0.9, apparent–adjusted R² gap ≤ 0.05, precise overall risk estimate, and (time-to-event) precise baseline survival. Implemented in R pmsampsize.

Required parameters: number of candidate predictor parameters (count dummy/non-linear terms), a conservative expected C-statistic or Cox-Snell R² (with its literature source), and outcome prevalence (binary) or event rate + mean follow-up (time-to-event).

Read ${CLAUDE_SKILL_DIR}/references/prediction_model_sample_size.md for the criteria, the pmsampsize code, and the reporting requirements. Report N + required events + the binding criterion + the assumed C/R² and its source.


Test 13: External-Validation Sample Size (Riley)

When to use: sizing an external validation of an existing prediction/AI model.

Approach: size to estimate the key validation metrics precisely enough to be conclusive — target the CI width of the C-statistic, the calibration slope, the calibration-in-the-large / O:E ratio, and (if a utility claim) net benefit. Implemented in R pmvalsampsize. A floor of ≥ 100 events and ≥ 100 non-events applies, but the precise target is usually larger.

Required parameters: expected prevalence, anticipated C-statistic, and the target CI widths.

Read ${CLAUDE_SKILL_DIR}/references/prediction_model_sample_size.md for the pmvalsampsize code. Report the targeted CI widths and the resulting events / non-events.


Test 14: MRMC Reader Study (Obuchowski–Rockette)

When to use: sizing a multi-reader multi-case (MRMC) reader study — "do readers read better with the AI", or "is the AI non-inferior to readers". The single-reader AUC-precision calculation (Test 1) under-sizes this: readers as well as cases are random, so power must cover the reader-variance term, and a null from an under-sized reader study is inconclusive, not negative.

Approach: invert the OR variance formula over the number of readers J and the case counts N⁺/N⁻; report the J × N power grid (past a modest case count, adding readers usually buys more power than adding cases). Requires variance components from a pilot or literature — the real bottleneck. Implemented in R RJafroc / MRMCaov / FDA iMRMC (integrate; do not hand-roll the OR algebra).

Required parameters: the effect (ΔAUC, or the non-inferiority margin — an AI-vs-reader claim is usually NI), the expected AUC level, the variance components (pilot/literature), the design (fully-crossed vs crossover-with-washout), and power/α.

Read ${CLAUDE_SKILL_DIR}/references/mrmc_reader_study_sample_size.md for the framework, the readers-vs-cases trade-off, software, and reporting. Reader-study design internals live in design-study (reader_elicitation_design.md); an AI-vs-human-expert benchmark routes to /design-ai-benchmarking.


Test 15: Segmentation-metric precision (Dice / HD95 / NSD)

When to use: sizing a segmentation validation — how many cases to estimate the segmentation metric (Dice / HD95 / NSD) precisely enough to be conclusive, or to separate two models. The proportion/events calcs (Tests 1, 12–13) do not apply: the outcome is a bounded, skewed per-case overlap/boundary score, not a proportion.

Approach: precision sizing n ≈ (1.96·SD/δ)² from the pilot/literature SD of per-case Dice (per structure — size on the worst structure you must report, not the average); report the CI by bootstrapping per-case values (BCa) — a t-interval is closed-form but Dice is bounded and non-normal near the ceiling, so its coverage is not the coverage you asked for, and BCa must resample whole patients, not structures. A model comparison on the same cases is paired (size on the SD of the per-case difference, or an NI margin). Size the external cohort too — a precise external estimate is the #1 acceptance lever.

Required parameters: the per-structure SD of per-case Dice (pilot/literature), the target precision δ or NI margin, and the metric.

Read ${CLAUDE_SKILL_DIR}/references/segmentation_metric_sample_size.md for the per-structure and paired-comparison detail. The comparator/ablation the size serves lives in design-study (combine_models_ablation_design.md); metric selection is /model-evaluation.


Test 16: Between-model comparison (is model A really better than B, C, …)

When to use: the claim is that one model outperforms others — several architectures / families compared head-to-head on the same task. Single-model precision (Test 1 AUC, Test 15 Dice) under-sizes it: two models can each have a tight CI and still overlap, so the difference must be powered.

Approach: run all models on the same cases (paired / within-case) and size on the SD of the per-case difference — σ√(2(1−ρ)), below either marginal SD once ρ > 0.5, which shared easy/hard cases usually clear. Use DeLong for a paired ΔAUC (or Obuchowski for the MRMC/clustered case) and a bootstrap of the paired per-case differences for ΔDice; size so the delta CI excludes zero, or so its lower bound clears the NI margin (the whole interval inside ±margin is equivalence, a stricter claim). For >2 models, pre-specify one primary contrast (proposed vs a strong, fairly-tuned baseline) at full α — or, if all pairwise are confirmatory, pay the family-wise correction (higher n per contrast). For a ranking claim, a single-run leaderboard ranks by luck: train over multiple seeds (Nadeau–Bengio corrected variance for repeated-CV differences) and leave models inside the Demšar critical difference unranked — not separated by the test is not a demonstrated tie, and Demšar's N counts independent datasets, not seeds.

Required parameters: the per-case-difference SD of the primary metric (pilot / prior head-to-head; per structure for segmentation), the metric + paired-CI method, the target δ or NI margin on the delta, the number of models + the primary contrast, and (for ranking) the seed-to-seed SD.

Read ${CLAUDE_SKILL_DIR}/references/multi_model_comparison_sample_size.md for the paired-difference, multiplicity, and ranking-stability detail. The fair-comparison design the size serves lives in design-study (multi_model_comparison_design.md); presenting it is make-figures (exemplar_plots/model_comparison_leaderboard.md).


Test 17: Segmentation usability (acceptability rate, failure bound, edit time)

When to use: the claim is that a segmentation model is clinically usable — a share of cases a clinician accepts, a bounded catastrophic-failure rate, a time saving — not that its mean metric is high. Test 15 sizes a mean Dice to a precision and says nothing about any of these.

Approach: an acceptability endpoint is a proportion: n ≈ (z/δ)²·p(1−p) — ≈138 cases at p = 0.90, δ = 0.05, but ≈384 at p = 0.50, so size on the pessimistic p unless a pilot in the same anatomy says otherwise, and size per structure class (use-as-is rates for one pipeline have run from ~40% for target volumes to ~89% for normal tissue). When m readers rate each case the ratings are nested, not independent: pooling n·m overstates precision by DE ≈ 1 + (m−1)ρ (3 readers at ρ = 0.5 halves it) — pre-specify either a case-level consensus rule or a mixed-effects/GEE analysis. To bound a catastrophic-failure rate, zero events in n cases gives an upper bound of ≈ 3/n (rule of three), so ≤1% needs ~300 clean cases; a 40–60-case study bounds nothing below ~5–8%. For an edit-time claim, size the paired per-case time difference (as Test 16) per structure and per site — pooled savings coexist with structures and centres showing none.

Required parameters: the acceptability scale and which level counts as accepted (use-as-is vs after minor edits are different endpoints), the expected p per structure class and target δ or threshold, the readers per case + analysis unit + assumed ρ, the catastrophic bound you must state, and (for work saving) the SD of the per-case time difference.

Read ${CLAUDE_SKILL_DIR}/references/segmentation_acceptability_sample_size.md for the proportion, clustering, rule-of-three and edit-time detail. The usability design the size serves lives in design-study (segmentation_failure_characterization_design.md); presenting it is make-figures (exemplar_plots/segmentation_failure_panel.md).


Scope Limitations

Supported

The 11 tests listed above cover the vast majority of sample size calculations needed in medical imaging research, diagnostic accuracy studies, and clinical trials.

NOT Supported

The following designs require specialized software or biostatistician consultation:

  • Adaptive trials (group-sequential, sample size re-estimation)
  • Cluster-randomized trials (design effect, ICC-based inflation)
  • Bayesian sample size determination
  • Crossover designs
  • Multi-endpoint correction (mention Bonferroni adjustment if asked, but do not compute corrected sample sizes)

If the user requests any of these, respond:

"This design requires specialized tools beyond this skill's scope. Consider using G*Power software (free, https://www.psychologie.hhu.de/gpower), PASS software, or consulting a biostatistician for [specific design]."


Workflow

Phase 1: Understand the Study

  1. Ask the user to describe their study briefly (design, primary outcome, groups).
  2. Walk through the decision tree to identify the appropriate test.
  3. Confirm the selected test with the user before proceeding.

Phase 2: Collect Parameters

  1. Present the parameter table for the selected test.
  2. For each parameter without a user-provided value, explain what it means and offer the default.
  3. Help the user estimate effect sizes from:
    • Prior literature (ask for references)
    • Pilot data
    • Cohen's conventions (as a last resort, with a note that convention-based estimates are less precise)

Phase 2b: Retrospective Study — Experience-Based Sample Size Justification

For retrospective studies, formal power analysis is often impractical because the dataset already exists. In these cases, an experience-based justification is acceptable for IRB and many journals. Offer this path when the user describes a retrospective design.

Two approaches:

Approach A: Institution Volume-Based

Estimate N from the number of examinations performed at the institution during the study period.

Total exams in period × prevalence of target condition × (1 - exclusion rate) = Expected N
  • Ask the user for: annual exam volume for the modality, study period length, estimated prevalence, and expected exclusion rate
  • This gives a realistic upper bound for N

IRB justification template:

Based on approximately [X] [modality] examinations performed annually at [institution], and an estimated prevalence of [condition] of [Y]%, we anticipate identifying approximately [N] eligible patients over the [Z]-year study period. After accounting for an estimated [W]% exclusion rate (due to [reasons]), we expect a final sample of approximately [N_adj] patients for analysis.

Approach B: Prior Study-Based

Use sample sizes from published studies with similar designs as justification.

  • Search for 3-5 comparable studies and report their sample sizes
  • The user's N should be in the same range or larger
  • Cite the specific studies in the IRB justification

IRB justification template:

Previous studies evaluating [similar topic] with [similar design] enrolled [N1] (Author1 et al., Year), [N2] (Author2 et al., Year), and [N3] (Author3 et al., Year) patients. Our anticipated sample of [N] patients is [comparable to / larger than] these prior studies.

When to Use Formal Calculation Instead

Even for retrospective studies, a formal sample size calculation is preferred when:

  • The study is prospective or will prospectively enroll a subset
  • The primary analysis involves hypothesis testing (not just estimation)
  • The journal explicitly requires power analysis (check Instructions for Authors)
  • The IRB requires it for approval

In these cases, proceed to Phase 3 with the appropriate test from the decision tree.


Phase 3: Calculate and Report

  1. Read ${CLAUDE_SKILL_DIR}/references/formulas.md for the exact formula.
  2. Generate the R code (primary) and Python code (alternative).
  3. Run the R code via Bash to produce the actual result.
  4. Present results in the output format below.

Phase 4: Sensitivity Analysis (Optional)

If the user is uncertain about parameters, offer a sensitivity table showing N across a range of plausible values (e.g., varying effect size or power from 0.80 to 0.90).


Output Format

Always structure the final output as follows:

## Sample Size Calculation Report

### Study Design
[1-2 sentence summary of the design and test selected]

### Parameters
| Parameter | Value | Source |
|-----------|-------|--------|
| ... | ... | user / literature / convention |

### Result
- **Required sample size**: N = [value]
- **With [X]% attrition adjustment**: N_adj = [value]

### R Code (Reproducible)
```r
# [complete, self-contained R script]
# Dependencies: [list packages]
# Run: Rscript sample_size_calc.R

Python Code (Alternative)

# [complete, self-contained Python script]
# Dependencies: [list packages]
# Run: python sample_size_calc.py

IRB Justification Text

A sample of [N] participants is required to detect [effect description] with [power]% power at a [one/two]-sided significance level of [alpha], assuming [key assumptions]. Accounting for an estimated [X]% attrition rate, we plan to enroll [N_adj] participants. This calculation is based on [formula/method reference].

Effect Size Interpretation

[Cohen's benchmark classification + clinical meaning in the context of this study]


---

## IRB Justification Text Guidelines

The IRB text must:
1. State the required N clearly.
2. Name the statistical test and its formula source.
3. Specify all assumed parameters (effect size, alpha, power).
4. State the attrition adjustment and final enrollment target.
5. Cite the methodological reference (e.g., "Schoenfeld, 1981" for survival).
6. Use formal, third-person language suitable for an ethics board.

---

## Communication Rules

- Communicate with the user in their preferred language.
- Use English for all statistical terminology, effect size names, and test names.
- Be explicit about assumptions and their impact on the result.
- When the user provides vague effect size estimates, flag the uncertainty and suggest a sensitivity analysis.
- Never fabricate references. Cite only verified methodological sources from `formulas.md`.

## Anti-Hallucination

- **Never fabricate file paths, URLs, DOIs, or package names.** Verify existence before recommending.
- **Never invent journal metadata, impact factors, or submission policies** without verification at the journal's website.
- If a tool, package, or resource does not exist or you are unsure, say so explicitly rather than guessing.
Files (medsci-skills)
  • references
    • formulas.md 20 KB
      # Sample Size Formulas Reference
      
      Mathematical formulas, R/Python implementations, and effect size conventions for all 10 supported tests.
      
      ---
      
      ## Test 1: Diagnostic Accuracy (Sensitivity/Specificity Precision)
      
      ### Formula
      For estimating a single proportion p with desired 95% CI half-width w:
      
      ```
      n_positive = ceil( (z_{alpha/2} / w)^2 * p * (1 - p) )
      n_total = ceil( n_positive / prevalence )
      ```
      
      Where:
      - `z_{alpha/2}` = 1.96 for alpha = 0.05
      - `p` = expected sensitivity (or specificity)
      - `w` = desired CI half-width
      - `prevalence` = disease prevalence in the study population
      
      ### R Implementation
      ```r
      z <- qnorm(1 - alpha / 2)
      n_pos <- ceiling((z / ci_half_width)^2 * se_expected * (1 - se_expected))
      n_total <- ceiling(n_pos / prevalence)
      n_adj <- ceiling(n_total / (1 - attrition_rate))
      ```
      
      ### Python Implementation
      ```python
      from scipy.stats import norm
      import math
      
      z = norm.ppf(1 - alpha / 2)
      n_pos = math.ceil((z / ci_half_width)**2 * se_expected * (1 - se_expected))
      n_total = math.ceil(n_pos / prevalence)
      n_adj = math.ceil(n_total / (1 - attrition_rate))
      ```
      
      ### R Package
      Base R (no additional packages needed).
      
      ### Key Reference
      Buderer NMF. Statistical methodology: I. Incorporating the prevalence of disease into the sample size calculation for sensitivity and specificity. Acad Emerg Med. 1996;3(9):895-900.
      
      ---
      
      ## Test 2: ICC Agreement (Bonett 2002)
      
      ### Formula
      Fisher z-transformation approach:
      
      ```
      z_1 = 0.5 * ln((1 + rho_1) / (1 - rho_1))    # expected ICC
      z_0 = 0.5 * ln((1 + rho_0) / (1 - rho_0))    # null ICC
      n = ceil( ((z_{alpha} + z_{beta}) / (z_1 - z_0))^2 + 3 )
      ```
      
      Where:
      - `rho_1` = expected ICC
      - `rho_0` = null hypothesis ICC
      - `z_{alpha}` = qnorm(1 - alpha) for one-sided, qnorm(1 - alpha/2) for two-sided
      - `z_{beta}` = qnorm(power)
      
      ### R Implementation
      ```r
      # Option A: MKpower package (preferred)
      library(MKpower)
      result <- sampleSize.ICC(rho0 = icc_null, rho1 = icc_expected,
                                k = n_raters, alpha = alpha, power = power)
      n <- result$n
      
      # Option B: Manual Fisher z (if MKpower unavailable)
      z_exp  <- 0.5 * log((1 + icc_expected) / (1 - icc_expected))
      z_null <- 0.5 * log((1 + icc_null) / (1 - icc_null))
      n <- ceiling(((qnorm(1 - alpha) + qnorm(power)) / (z_exp - z_null))^2 + 3)
      ```
      
      ### Python Implementation
      ```python
      from scipy.stats import norm
      import math
      import numpy as np
      
      z_exp  = 0.5 * np.log((1 + icc_expected) / (1 - icc_expected))
      z_null = 0.5 * np.log((1 + icc_null) / (1 - icc_null))
      z_alpha = norm.ppf(1 - alpha)
      z_beta  = norm.ppf(power)
      n = math.ceil(((z_alpha + z_beta) / (z_exp - z_null))**2 + 3)
      ```
      
      ### R Package
      `MKpower` (preferred), or base R for manual calculation.
      
      ### Key Reference
      Bonett DG. Sample size requirements for estimating intraclass correlations with desired precision. Stat Med. 2002;21(9):1331-1335.
      
      ---
      
      ## Test 3: Kappa Agreement (Donner & Eliasziw 1992)
      
      ### Formula
      Z-test approximation for testing kappa_1 vs kappa_0:
      
      ```
      n = ceil( ((z_{alpha/2} + z_{beta})^2 * kappa_1 * (1 - kappa_1)) / (kappa_1 - kappa_0)^2 + 1 )
      ```
      
      Where:
      - `kappa_1` = expected kappa
      - `kappa_0` = null hypothesis kappa
      - `pe` = expected chance agreement = (po - kappa) / (1 - kappa)
      
      ### R Implementation
      ```r
      n_kappa <- ceiling(
        ((qnorm(1 - alpha / 2) + qnorm(power))^2 *
           kappa_expected * (1 - kappa_expected)) /
          (kappa_expected - kappa_null)^2 + 1
      )
      ```
      
      ### Python Implementation
      ```python
      from scipy.stats import norm
      import math
      
      z_a = norm.ppf(1 - alpha / 2)
      z_b = norm.ppf(power)
      n = math.ceil(((z_a + z_b)**2 * kappa_exp * (1 - kappa_exp)) /
                    (kappa_exp - kappa_null)**2 + 1)
      ```
      
      ### R Package
      Base R. Also available via `kappaSize` package.
      
      ### Key Reference
      Donner A, Eliasziw M. A goodness-of-fit approach to inference procedures for the kappa statistic: confidence interval construction, significance-testing and sample size estimation. Stat Med. 1992;11(11):1511-1519.
      
      ---
      
      ## Test 4: Two-Proportion Comparison (Chi-Square)
      
      ### Formula
      Based on Cohen's h effect size (arcsine transformation):
      
      ```
      h = 2 * arcsin(sqrt(p1)) - 2 * arcsin(sqrt(p2))
      n_per_group = ceil( ((z_{alpha/2} + z_{beta}) / h)^2 )
      ```
      
      ### R Implementation
      ```r
      library(pwr)
      h <- ES.h(p1, p2)
      result <- pwr.2p.test(h = h, sig.level = alpha, power = power)
      n_per_group <- ceiling(result$n)
      n_total <- n_per_group * 2
      ```
      
      ### Python Implementation
      ```python
      from statsmodels.stats.power import NormalIndPower
      import numpy as np
      import math
      
      h = 2 * np.arcsin(np.sqrt(p1)) - 2 * np.arcsin(np.sqrt(p2))
      analysis = NormalIndPower()
      n_per_group = math.ceil(analysis.solve_power(effect_size=h, alpha=alpha, power=power,
                                                    ratio=1, alternative='two-sided'))
      n_total = n_per_group * 2
      ```
      
      ### R Package
      `pwr`
      
      ### Key Reference
      Cohen J. Statistical Power Analysis for the Behavioral Sciences. 2nd ed. Lawrence Erlbaum Associates; 1988.
      
      ---
      
      ## Test 5: McNemar Test (Paired Proportions)
      
      ### Formula
      ```
      n = ceil(
        (z_{alpha/2} * sqrt(p01 + p10) + z_{beta} * sqrt(p01 + p10 - (p10 - p01)^2))^2
        / (p10 - p01)^2
      )
      ```
      
      Where:
      - `p01` = P(Method A negative, Method B positive)
      - `p10` = P(Method A positive, Method B negative)
      
      ### R Implementation
      ```r
      n_mc <- ceiling(
        (qnorm(1 - alpha / 2) * sqrt(p01 + p10) +
           qnorm(power) * sqrt(p01 + p10 - (p10 - p01)^2))^2 /
          (p10 - p01)^2
      )
      ```
      
      ### Python Implementation
      ```python
      from scipy.stats import norm
      import math
      
      z_a = norm.ppf(1 - alpha / 2)
      z_b = norm.ppf(power)
      disc_sum = p01 + p10
      disc_diff = p10 - p01
      n = math.ceil((z_a * math.sqrt(disc_sum) +
                     z_b * math.sqrt(disc_sum - disc_diff**2))**2 / disc_diff**2)
      ```
      
      ### R Package
      Base R. Also available via `exact2x2` package.
      
      ### Key Reference
      Connor RJ. Sample size for testing differences in proportions for the paired-sample design. Biometrics. 1987;43(1):207-211.
      
      ---
      
      ## Test 6: Independent t-Test
      
      ### Formula
      ```
      d = mean_diff / pooled_sd    (Cohen's d)
      n_per_group = ceil( 2 * ((z_{alpha/2} + z_{beta}) / d)^2 )
      ```
      
      ### R Implementation
      ```r
      library(pwr)
      d <- mean_diff / pooled_sd
      result <- pwr.t.test(d = d, sig.level = alpha, power = power, type = "two.sample")
      n_per_group <- ceiling(result$n)
      n_total <- n_per_group * 2
      ```
      
      ### Python Implementation
      ```python
      from statsmodels.stats.power import TTestIndPower
      import math
      
      d = mean_diff / pooled_sd
      analysis = TTestIndPower()
      n_per_group = math.ceil(analysis.solve_power(effect_size=d, alpha=alpha, power=power,
                                                    ratio=1, alternative='two-sided'))
      n_total = n_per_group * 2
      ```
      
      ### R Package
      `pwr`
      
      ### Key Reference
      Cohen J. Statistical Power Analysis for the Behavioral Sciences. 2nd ed. Lawrence Erlbaum Associates; 1988.
      
      ---
      
      ## Test 7: Survival / Log-Rank Test (Schoenfeld 1981)
      
      ### Formula
      Step 1 -- Required number of events:
      ```
      d = ceil( ((z_{alpha/2} + z_{beta}) / ln(HR))^2 )
      ```
      
      Step 2 -- Total sample size:
      ```
      lambda_ctrl = ln(2) / median_ctrl
      lambda_trt  = lambda_ctrl * HR
      p_event_ctrl = 1 - exp(-lambda_ctrl * follow_up)
      p_event_trt  = 1 - exp(-lambda_trt * follow_up)
      avg_p_event  = (p_event_ctrl + p_event_trt) / 2
      n_total = ceil( d / avg_p_event )
      ```
      
      ### R Implementation
      ```r
      n_events <- ceiling((qnorm(1 - alpha / 2) + qnorm(power))^2 / (log(hr))^2)
      lambda_ctrl <- log(2) / median_ctrl
      lambda_trt  <- lambda_ctrl * hr
      p_event_ctrl <- 1 - exp(-lambda_ctrl * follow_up)
      p_event_trt  <- 1 - exp(-lambda_trt * follow_up)
      avg_p_event  <- (p_event_ctrl + p_event_trt) / 2
      n_total <- ceiling(n_events / avg_p_event)
      n_adj <- ceiling(n_total / (1 - drop_rate))
      ```
      
      ### Python Implementation
      ```python
      from scipy.stats import norm
      import math
      import numpy as np
      
      z_a = norm.ppf(1 - alpha / 2)
      z_b = norm.ppf(power)
      n_events = math.ceil((z_a + z_b)**2 / np.log(hr)**2)
      lambda_ctrl = np.log(2) / median_ctrl
      lambda_trt = lambda_ctrl * hr
      p_event_ctrl = 1 - np.exp(-lambda_ctrl * follow_up)
      p_event_trt = 1 - np.exp(-lambda_trt * follow_up)
      avg_p_event = (p_event_ctrl + p_event_trt) / 2
      n_total = math.ceil(n_events / avg_p_event)
      n_adj = math.ceil(n_total / (1 - drop_rate))
      ```
      
      ### R Package
      Base R. Also available via `gsDesign`, `survival` packages.
      
      ### Key Reference
      Schoenfeld DA. The asymptotic properties of nonparametric tests for comparing survival distributions. Biometrika. 1981;68(1):316-319.
      
      ---
      
      ## Test 8: One-Way ANOVA
      
      ### Formula
      Using Cohen's f effect size:
      
      ```
      f = sigma_between / sigma_within
      ```
      
      Where:
      - `sigma_between` = SD of group means
      - `sigma_within` = pooled within-group SD
      
      From eta-squared: `f = sqrt(eta_sq / (1 - eta_sq))`
      
      The sample size per group is obtained via the F-test power formula (implemented in `pwr`).
      
      ### R Implementation
      ```r
      library(pwr)
      result <- pwr.anova.test(k = k, f = f, sig.level = alpha, power = power)
      n_per_group <- ceiling(result$n)
      n_total <- n_per_group * k
      n_adj <- ceiling(n_total / (1 - attrition_rate))
      ```
      
      ### Python Implementation
      ```python
      from statsmodels.stats.power import FTestAnovaPower
      import math
      
      analysis = FTestAnovaPower()
      n_per_group = math.ceil(analysis.solve_power(effect_size=f, nobs=None, alpha=alpha,
                                                    power=power, k_groups=k))
      n_total = n_per_group * k
      n_adj = math.ceil(n_total / (1 - attrition_rate))
      ```
      
      ### R Package
      `pwr`
      
      ### Key Reference
      Cohen J. Statistical Power Analysis for the Behavioral Sciences. 2nd ed. Lawrence Erlbaum Associates; 1988. (Chapter 8: F tests for ANOVA)
      
      ---
      
      ## Test 9: Logistic Regression
      
      ### Approach A: Peduzzi Rule of Thumb (EPV >= 10)
      
      ```
      N_events = 10 * p   (where p = number of predictor variables)
      N_total = N_events / event_rate
      ```
      
      This ensures at least 10 events per predictor variable (EPV), the widely accepted minimum for stable logistic regression estimates.
      
      ### Approach B: Hsieh (1989) Formula
      
      For detecting a specific odds ratio (OR) for a continuous or binary predictor:
      
      ```
      # For a binary predictor (proportion B exposed):
      n_unadj = ((z_{alpha/2} + z_{beta})^2) / (B * (1-B) * ln(OR)^2)
      
      # Adjusted for correlation with other predictors:
      n_adj = n_unadj / (1 - R^2)
      ```
      
      Where:
      - `OR` = odds ratio of interest
      - `B` = proportion of subjects exposed (for binary predictor) or use p*(1-p) for the outcome
      - `R^2` = multiple correlation of the predictor with other covariates
      
      For a continuous predictor, the formula uses the standard normal density.
      
      ### R Implementation
      ```r
      # Approach A: Peduzzi
      n_events_peduzzi <- 10 * n_predictors
      n_total_peduzzi <- ceiling(n_events_peduzzi / event_rate)
      
      # Approach B: Hsieh (binary predictor)
      z_a <- qnorm(1 - alpha / 2)
      z_b <- qnorm(power)
      n_hsieh <- ceiling((z_a + z_b)^2 /
                           (event_rate * (1 - event_rate) * log(or_interest)^2))
      n_hsieh_adj <- ceiling(n_hsieh / (1 - r2_other))
      
      # Report the larger of the two
      n_final <- max(n_total_peduzzi, n_hsieh_adj)
      ```
      
      ### Python Implementation
      ```python
      from scipy.stats import norm
      import math
      import numpy as np
      
      # Approach A: Peduzzi
      n_events_peduzzi = 10 * n_predictors
      n_total_peduzzi = math.ceil(n_events_peduzzi / event_rate)
      
      # Approach B: Hsieh (binary predictor)
      z_a = norm.ppf(1 - alpha / 2)
      z_b = norm.ppf(power)
      n_hsieh = math.ceil((z_a + z_b)**2 /
                           (event_rate * (1 - event_rate) * np.log(or_interest)**2))
      n_hsieh_adj = math.ceil(n_hsieh / (1 - r2_other))
      
      n_final = max(n_total_peduzzi, n_hsieh_adj)
      ```
      
      ### R Package
      Base R. Also see `powerMediation` package for Hsieh's formula.
      
      ### Key References
      - Peduzzi P, Concato J, Kemper E, Holford TR, Feinstein AR. A simulation study of the number of events per variable in logistic regression analysis. J Clin Epidemiol. 1996;49(12):1373-1379.
      - Hsieh FY. Sample size tables for logistic regression. Stat Med. 1989;8(7):795-802.
      
      ---
      
      ## Test 10: Non-Inferiority / Equivalence
      
      ### Non-Inferiority (Proportions)
      
      ```
      n_per_group = ceil(
        ((z_{1-alpha} + z_{beta})^2 * (p_ref*(1-p_ref) + p_new*(1-p_new))) /
        (margin - |p_new - p_ref|)^2
      )
      ```
      
      When assuming p_new = p_ref (no true difference):
      ```
      n_per_group = ceil( ((z_{1-alpha} + z_{beta})^2 * 2 * p*(1-p)) / margin^2 )
      ```
      
      Note: alpha is one-sided (typically 0.025) for non-inferiority.
      
      ### Non-Inferiority (Continuous)
      
      ```
      n_per_group = ceil( ((z_{1-alpha} + z_{beta})^2 * 2 * sd^2) / margin^2 )
      ```
      
      ### Equivalence / TOST (Proportions)
      
      ```
      n_per_group = ceil(
        ((z_{1-alpha/2} + z_{beta})^2 * 2 * p*(1-p)) / margin^2
      )
      ```
      
      Note: For TOST, each one-sided test uses alpha (e.g., alpha = 0.05 for overall 5% type I error).
      
      ### Equivalence / TOST (Continuous)
      
      ```
      n_per_group = ceil( ((z_{1-alpha} + z_{beta})^2 * 2 * sd^2) / margin^2 )
      ```
      
      ### R Implementation
      ```r
      # Non-inferiority for proportions (assuming no true difference)
      z_a <- qnorm(1 - alpha)  # one-sided, alpha = 0.025
      z_b <- qnorm(power)
      p <- p_reference
      n_per_group <- ceiling(((z_a + z_b)^2 * 2 * p * (1 - p)) / margin^2)
      n_total <- n_per_group * 2
      
      # Non-inferiority for continuous
      n_per_group <- ceiling(((z_a + z_b)^2 * 2 * sd^2) / margin^2)
      n_total <- n_per_group * 2
      
      # Equivalence / TOST for continuous
      n_per_group <- ceiling(((z_a + z_b)^2 * 2 * sd^2) / margin^2)
      n_total <- n_per_group * 2
      
      n_adj <- ceiling(n_total / (1 - attrition_rate))
      ```
      
      ### Python Implementation
      ```python
      from scipy.stats import norm
      import math
      
      # Non-inferiority for proportions (assuming no true difference)
      z_a = norm.ppf(1 - alpha)  # one-sided, alpha = 0.025
      z_b = norm.ppf(power)
      p = p_reference
      n_per_group = math.ceil(((z_a + z_b)**2 * 2 * p * (1 - p)) / margin**2)
      n_total = n_per_group * 2
      
      # Non-inferiority for continuous
      n_per_group = math.ceil(((z_a + z_b)**2 * 2 * sd**2) / margin**2)
      n_total = n_per_group * 2
      
      # Equivalence / TOST for continuous
      # Same formula; the difference is in the hypothesis and alpha interpretation
      n_per_group = math.ceil(((z_a + z_b)**2 * 2 * sd**2) / margin**2)
      n_total = n_per_group * 2
      
      n_adj = math.ceil(n_total / (1 - attrition_rate))
      ```
      
      ### R Package
      Base R. Also see `TrialSize`, `PowerTOST` packages.
      
      ### Key References
      - Julious SA. Sample sizes for clinical trials with normal data. Stat Med. 2004;23(12):1921-1986.
      - Schuirmann DJ. A comparison of the two one-sided tests procedure and the power approach for assessing the equivalence of average bioavailability. J Pharmacokinet Biopharm. 1987;15(6):657-680.
      
      ---
      
      ## Test 11: Cox Regression EPV (Events Per Variable)
      
      ### Formula
      ```
      N_events = EPV × k    (where k = number of predictor variables)
      N_total = ceil( N_events / event_rate )
      N_adj = ceil( N_total / (1 - attrition_rate) )
      ```
      
      Where:
      - `EPV` = events per variable (minimum 10, recommended 20)
      - `k` = number of predictors in the Cox model
      - `event_rate` = proportion of subjects experiencing the event
      
      ### R Implementation
      ```r
      n_events <- epv * n_predictors
      n_total <- ceiling(n_events / event_rate)
      n_adj <- ceiling(n_total / (1 - attrition_rate))
      
      cat(sprintf("EPV = %d, Predictors = %d\n", epv, n_predictors))
      cat(sprintf("Required events = %d\n", n_events))
      cat(sprintf("Total N = %d (event rate = %.0f%%)\n", n_total, event_rate * 100))
      cat(sprintf("Adjusted N = %d (attrition = %.0f%%)\n", n_adj, attrition_rate * 100))
      ```
      
      ### Python Implementation
      ```python
      import math
      
      n_events = epv * n_predictors
      n_total = math.ceil(n_events / event_rate)
      n_adj = math.ceil(n_total / (1 - attrition_rate))
      ```
      
      ### R Package
      Base R (no additional packages needed).
      
      ### Key References
      - Peduzzi P, Concato J, Feinstein AR, Holford TR. Importance of events per independent variable in proportional hazards regression analysis. II. Accuracy and precision of regression estimates. J Clin Epidemiol. 1995;48(12):1503-1510.
      - Vittinghoff E, McCulloch CE. Relaxing the rule of ten events per variable in logistic and Cox regression. Am J Epidemiol. 2007;165(6):710-718.
      
      ---
      
      ## Cohen's Effect Size Conventions
      
      | Measure | Small | Medium | Large | Context |
      |---------|-------|--------|-------|---------|
      | d (t-test) | 0.20 | 0.50 | 0.80 | Difference in means / pooled SD |
      | f (ANOVA) | 0.10 | 0.25 | 0.40 | SD of group means / within-group SD |
      | h (proportions) | 0.20 | 0.50 | 0.80 | Arcsine-transformed proportion difference |
      | w (chi-square) | 0.10 | 0.30 | 0.50 | Chi-square contingency effect |
      | OR (logistic) | 1.5 | 2.0 | 3.0+ | Odds ratio (approximate equivalence) |
      | HR (survival) | 0.80 | 0.65 | 0.50 | Hazard ratio (values < 1 favor treatment) |
      | ICC | 0.50-0.75 | 0.75-0.90 | > 0.90 | Poor/moderate/good/excellent |
      | Kappa | 0.21-0.40 | 0.41-0.60 | 0.61-0.80 | Fair/moderate/substantial |
      
      **Important**: Cohen's conventions are rules of thumb. Always prefer effect sizes estimated from prior literature or pilot data. When conventions are used, explicitly state this limitation in the IRB justification.
      
      ---
      
      ## Common Attrition Rates by Study Type
      
      | Study Type | Typical Attrition | Recommended Adjustment |
      |------------|-------------------|------------------------|
      | Randomized controlled trial (RCT) | 15-20% | 20% |
      | Prospective observational / cohort | 10-15% | 15% |
      | Cross-sectional / survey | 5-10% | 10% |
      | Retrospective chart review | 3-5% | 5% |
      | Diagnostic accuracy (imaging) | 5-10% | 10% |
      | Inter-rater agreement study | 5-10% | 10% |
      | Survival / long follow-up (> 2 yr) | 15-25% | 20% |
      
      **Note**: Attrition rates vary widely by disease, population, and follow-up duration. Use study-specific estimates when available.
      
      ---
      
      ## Key References
      
      1. **Cohen J.** Statistical Power Analysis for the Behavioral Sciences. 2nd ed. Hillsdale, NJ: Lawrence Erlbaum Associates; 1988.
         - Foundation for effect size conventions (d, f, h, w) and power analysis methodology.
      
      2. **Schoenfeld DA.** The asymptotic properties of nonparametric tests for comparing survival distributions. Biometrika. 1981;68(1):316-319.
         - Formula for required number of events in log-rank test.
      
      3. **Bonett DG.** Sample size requirements for estimating intraclass correlations with desired precision. Stat Med. 2002;21(9):1331-1335.
         - ICC-based sample size using Fisher z-transformation.
      
      4. **Hsieh FY.** Sample size tables for logistic regression. Stat Med. 1989;8(7):795-802.
         - Power-based sample size for detecting a specific odds ratio.
      
      5. **Peduzzi P, Concato J, Kemper E, Holford TR, Feinstein AR.** A simulation study of the number of events per variable in logistic regression analysis. J Clin Epidemiol. 1996;49(12):1373-1379.
         - EPV >= 10 rule for logistic regression model stability.
      
      6. **Donner A, Eliasziw M.** A goodness-of-fit approach to inference procedures for the kappa statistic: confidence interval construction, significance-testing and sample size estimation. Stat Med. 1992;11(11):1511-1519.
         - Sample size for testing kappa against a null value.
      
      7. **Buderer NMF.** Statistical methodology: I. Incorporating the prevalence of disease into the sample size calculation for sensitivity and specificity. Acad Emerg Med. 1996;3(9):895-900.
         - Prevalence-adjusted sample size for diagnostic accuracy.
      
      8. **Julious SA.** Sample sizes for clinical trials with normal data. Stat Med. 2004;23(12):1921-1986.
         - Comprehensive non-inferiority and equivalence sample size formulas.
      
      9. **Schuirmann DJ.** A comparison of the two one-sided tests procedure and the power approach for assessing the equivalence of average bioavailability. J Pharmacokinet Biopharm. 1987;15(6):657-680.
         - TOST (two one-sided tests) procedure for equivalence testing.
      
      10. **Koo TK, Li MY.** A guideline of selecting and reporting intraclass correlation coefficients for reliability research. J Chiropr Med. 2016;15(2):155-163.
          - ICC interpretation benchmarks.
      
      11. **Landis JR, Koch GG.** The measurement of observer agreement for categorical data. Biometrics. 1977;33(1):159-174.
          - Kappa interpretation benchmarks.
      
      12. **Connor RJ.** Sample size for testing differences in proportions for the paired-sample design. Biometrics. 1987;43(1):207-211.
          - McNemar test sample size formula.
      
      13. **Peduzzi P, Concato J, Feinstein AR, Holford TR.** Importance of events per independent variable in proportional hazards regression analysis. II. Accuracy and precision of regression estimates. J Clin Epidemiol. 1995;48(12):1503-1510.
          - EPV >= 10 rule for Cox regression model stability.
      
      14. **Vittinghoff E, McCulloch CE.** Relaxing the rule of ten events per variable in logistic and Cox regression. Am J Epidemiol. 2007;165(6):710-718.
          - Evidence that EPV 5-10 may be acceptable with careful validation.
      
    • justification_examples.md 3.6 KB
      # Sample-size justification — worked prose exemplars (IRB / Methods)
      
      Reviewer-safe **justification paragraphs** for the prospective designs this skill computes,
      complementing `formulas.md` (the math) and the retrospective/experience-based templates in
      SKILL.md Phase 2b. Each shows the same five elements a methods reviewer or IRB looks for; fill
      the `[brackets]` from the actual calculation — never invent the inputs. These are synthetic
      teaching models of *standard* justification structure, not copied text.
      
      ## The five elements (every justification states all five)
      1. The **primary outcome** and its effect/precision target (with the **source** of the assumed
         value — prior study, pilot, or a minimal clinically important difference, cited).
      2. **α** (and one- vs two-sided) and **power** (or the target CI half-width for a precision aim).
      3. The **test/method** the calculation matches (it must match the planned primary analysis).
      4. The resulting **n**, including any **inflation** for attrition/clustering/multiplicity.
      5. The **software/approach** used (named, so it is reproducible).
      
      ## Exemplars by design
      
      **Two proportions (superiority).** "Assuming an event rate of `[p1]` in the control arm
      (from `[cited source]`) and a clinically meaningful absolute reduction to `[p2]`, a two-sided
      α = 0.05 and 80% power require `[n/arm]` per arm (two-proportion test). Allowing for `[d]%`
      attrition, we will enrol `[N]`."
      
      **Two means (superiority).** "To detect a between-group difference of `[Δ]` in `[outcome]`
      (SD `[s]`, from `[source]`; standardised effect `[d]`) with two-sided α = 0.05 and 90% power
      requires `[n/arm]` per arm (two-sample t-test)."
      
      **Diagnostic accuracy (precision aim).** "To estimate sensitivity with a 95% CI half-width of
      `[w]`, assuming sensitivity `[Se]` and disease prevalence `[π]`, `[N_total]` participants
      (`[N_diseased]` with the target condition) are needed; the **specificity** target is checked
      separately from the non-diseased count `[N_nondiseased]` and is satisfied at this n. The aim is
      **precision, not power** — no comparison hypothesis is tested." (Cite Hajian-Tilaki / Buderer.)
      
      **Survival (log-rank).** "To detect a hazard ratio of `[HR]` (median `[m1]` vs `[m2]`) with
      two-sided α = 0.05 and 80% power, `[E]` events are required (Schoenfeld); with an accrual of
      `[a]` over `[t]` and follow-up `[f]`, this needs `[N]` participants. The **event count**, not N,
      drives power."
      
      **Agreement / reliability (ICC).** "Assuming a true ICC of `[ρ]` with `[k]` raters per subject,
      `[n]` subjects give a 95% CI half-width of `[w]` (a **precision** aim, Bonett/Walter) —
      *or*, framed as **assurance**, `[n]` subjects so the 95% CI lower bound exceeds the minimally
      acceptable `[ρ0]`. State which of the two aims you used; report the CI target, not power."
      
      **Non-inferiority.** "With a non-inferiority margin of `[m]` (justified clinically and by
      `[regulatory/prior]` precedent), assuming true equivalence and a control rate `[p]`, one-sided
      α = 0.025 and 90% power require `[n/arm]` per arm. The margin and its rationale are pre-specified."
      
      ## Discipline
      - The calculation must match the **planned primary analysis** (do not power for a t-test and
        analyse with a mixed model); state any clustering (design effect) or multiplicity adjustment.
      - For a **precision** aim (DTA, agreement, single-arm), report the **CI half-width**, not power —
        do not invent a comparison hypothesis to manufacture a power statement.
      - Never reverse-engineer the effect size from an achievable n (post-hoc justification); the
        assumed effect comes from a cited source or an MCID. Post-hoc/observed power is uninformative.
      
    • mrmc_reader_study_sample_size.md 5.7 KB
      # MRMC reader-study sample size (multi-reader multi-case)
      
      For a **reader study** — the design that asks "do radiologists read better *with* the AI than
      without", or "is the AI non-inferior to radiologists" — the single-reader AUC-precision
      calculation (Test 1) **under-sizes the study**, often badly. This reference is the design-time
      sizing for that class of study. It is the sizing counterpart to the flagship "clearing move" in
      `design-study/references/venue_accept_recipe.md` (a reader study measuring clinical impact is
      what lifts a study to the flagship tier) — and an under-sized reader study cannot deliver it.
      
      ## Why a single-reader power calculation is the wrong tool
      
      A reader study generalizes to **radiologists in general**, not to the specific readers you hired.
      So **both the readers and the cases are random effects**, and the uncertainty of the
      reader-averaged AUC (or of the AI−reader ΔAUC) carries a **reader-variance** term the single-reader
      calculation omits entirely. Size on case variance alone and the study is powered to detect an
      effect *in your particular readers*, not in the population of readers — which is exactly the claim
      a reviewer reads the paper as making. The practical consequence: studies sized as if readers were
      fixed are routinely **under-powered**, and a null result from an under-sized reader study is
      **inconclusive, not negative**.
      
      ## The framework — Obuchowski–Rockette / Hillis (OR)
      
      The multi-reader multi-case (MRMC) analysis of variance treats the figure of merit (usually AUC,
      or a difference in AUC between modalities/AI-conditions) as an outcome with **reader**, **case**,
      and **reader×case** (plus modality) random components. Sizing inverts the OR variance formula:
      
      - You choose the **number of readers `J`** and the **case counts** (diseased `N⁺`, non-diseased
        `N⁻`), and the OR formula returns the power to detect the target effect.
      - Power depends on the **variance components** — the error variance and the between-reader /
        within-reader covariances (`Cov1`, `Cov2`, `Cov3` in the OR parameterization, or Hillis'
        equivalent `σ²` terms). **You cannot size an MRMC study without these**, and they are the real
        bottleneck: take them from a **pilot** (a handful of readers on a subset) or from **published
        component estimates** for a similar task/modality, and state the source.
      
      ## The inputs to pre-specify (before any data)
      
      1. **The effect**: the ΔAUC to detect (superiority) *or* the non-inferiority margin (an AI-vs-reader
         claim is usually **non-inferiority**, so state the margin, not a difference).
      2. **The expected AUC level** of the reference arm (variance of an AUC estimate depends on where it
         sits).
      3. **The variance components** (pilot or literature — the hard part; §above).
      4. **The design**: **fully-crossed** (every reader reads every case in every condition) is the
         default and the most efficient; a **crossover with washout** (readers read with and without AI,
         separated by a washout so the first read does not cue the second) is the standard AI-assistance
         design.
      5. **Power and α** (commonly 80–90% at two-sided 0.05).
      
      ## Readers vs cases — where the power comes from
      
      Because the **reader-variance term usually dominates** the generalization uncertainty, past a
      modest case count **adding readers often buys more power than adding cases** — yet readers are the
      scarcer, costlier resource. Report the **`J × N` power grid**, not a single number, so the
      reader/case trade-off is an explicit, defensible design choice. A study with many cases but only
      3–4 readers is a common, predictable under-powering.
      
      ## Compute it — integrate, do not reimplement
      
      - **`RJafroc`** (R; Chakraborty) — `SsPowerGivenJK` / sample-size functions for ROC & FROC MRMC.
      - **`MRMCaov`** (R) — OR analysis + power.
      - **`iMRMC`** (Gallas, FDA) — MRMC sizing/analysis, widely accepted by regulators.
      - **OR-DBM / DBM** procedures for the variance-component estimation from a pilot.
      
      Feed the pilot/literature variance components + the target effect into one of these; do not hand-roll
      the OR variance algebra.
      
      ## Grounding exemplars (accepted reader studies)
      
      Realistic `J × N` and design choices from accepted open-access papers:
      - **8-reader MRMC crossover, 500 cases** — PCN CT model, *npj Digital Medicine* 2025
        (`10.1038/s41746-025-01970-y`): readers spanning residents→seniors, accuracy **and** reading-time
        endpoints.
      - **26 physicians × 150 cases × 3 conditions with ≥2-week washout** — pelvic-radiograph AI-support,
        *npj Digital Medicine* 2025 (`10.1038/s41746-025-01923-5`): a crossover across no-AI / alert /
        heatmap, specialty-stratified.
      
      These illustrate the crossover-with-washout design and the reader-count range a flagship reader
      study lands in; they are patterns, not templates.
      
      ## Reporting (what the Methods must state)
      
      The number of readers `J`, the case split `N⁺`/`N⁻`, the **design** (fully-crossed / crossover +
      washout), the **target effect** (ΔAUC or NI margin) and power/α, the **source of the variance
      components** (pilot vs literature), and the **software**. Analysis of the completed study uses the
      matching OR/DBM procedure (see `analyze-stats` `reader_study` table-type + `diagnostic_accuracy`
      guide); the reader-study *design internals* (rubric, blinding, washout, experience mix) are in
      `design-study/references/reader_elicitation_design.md`, and an AI-vs-human-expert benchmark routes
      to `/design-ai-benchmarking`.
      
      ## References (methodology — cite, do not copy)
      
      - Obuchowski NA, Rockette HE. *Commun Stat Simul Comput* 1995 (the OR method).
      - Hillis SL, Berbaum KS, Metz CE. *Acad Radiol* 2008 (OR/DBM equivalence, sizing).
      - Hillis SL. *Stat Med* 2007 (degrees of freedom for MRMC).
      - Chakraborty DP. *Observer Performance Methods for Diagnostic Imaging* (RJafroc).
      
    • multi_model_comparison_sample_size.md 6.1 KB
      # Between-model comparison sample size (is model A really better than B, C, …)
      
      For a study whose claim is that **one model outperforms others** — several architectures / families
      compared head-to-head on the same task — the sizing question is not single-model precision (Test 15
      for Dice, Test 1 for AUC) but **how many cases separate the models**. A study powered only to
      estimate each model's metric can still be too small to tell whether the ranking is real. This is the
      **size** counterpart to the fair-comparison **design** in
      `design-study/references/multi_model_comparison_design.md`; decide it before data collection.
      
      ## Why single-model precision under-sizes a comparison
      
      Sizing each arm to a tight marginal CI does **not** guarantee the *difference* is distinguishable
      from zero — two models can each have a narrow CI and still overlap. The comparison is powered by the
      **difference**, and its precision depends on the **SD of the per-case difference**, which the
      marginal SDs do not give you.
      
      ## Pair the design — it shrinks the required n
      
      Run **all models on the same cases** (a paired / within-case design) and size on the **SD of the
      per-case difference**. With equal marginal SDs σ and between-model correlation ρ,
      `SD_Δ = σ·√(2(1−ρ))` — **smaller than either marginal SD only once ρ > 0.5**, a bar that models
      scored on the *same* cases usually clear by a wide margin (easy cases are easy for every model, hard
      cases are hard for every model). Whatever ρ turns out to be, the paired design also **collects fewer
      cases** than two independent arms at equal power, because one case serves every model — and it is the
      only design that supports the paired statistics below.
      
      ## Metric-specific paired sizing
      
      - **Classification / detection — paired ΔAUC:** use the **DeLong** (1988) variance of the *difference*
        of two correlated AUCs (or Obuchowski for the MRMC / clustered case); size so the **ΔAUC CI excludes
        zero** (superiority) or so its **lower bound clears −δ**, the non-inferiority margin — requiring the
        *whole* interval inside ±δ is the stricter **equivalence** claim, so do not size one and call it the
        other. Sizing on each AUC's marginal CI
        is the wrong tool — the covariance between the two ROC curves is exactly what a paired calc uses.
      - **Segmentation — paired ΔDice / ΔHD95 / ΔNSD:** size on the SD of the **per-case metric difference**
        and report the delta CI by **bootstrapping the paired per-case differences (BCa)** — a t-interval on
        the mean per-case difference is closed-form, but it leans on a normality that a bounded metric
        bunched near ceiling does not deliver, and BCa resamples whole *patients* rather than lesions or
        structures. This extends the A-vs-B section of `segmentation_metric_sample_size.md` beyond
        a single contrast; **size on the worst structure** you must report.
      - Take the **per-case-difference SD from a pilot** (or a prior head-to-head), never from a marginal-SD
        formula that assumes independence.
      
      ## More than two models — multiplicity across contrasts
      
      Comparing **k models** creates up to k(k−1)/2 pairwise contrasts. Decide the estimand **before** the
      data:
      
      - **Primary-contrast design (preferred):** pre-specify **one** primary comparison — the proposed model
        vs the **strong, fairly-tuned reference baseline** (e.g., nnU-Net) — sized at full α; everything else
        is secondary / exploratory and labelled so. This avoids sizing for a multiplicity you do not need.
      - **All-pairs confirmatory:** if every pairwise claim is confirmatory, a **family-wise correction**
        (Bonferroni / Tukey-analog) lowers the per-contrast α, which **inflates the required n per contrast** —
        budget for it. Running k(k−1)/2 unplanned tests and headlining the one that clears p < 0.05 is the
        rejected pattern (`analyze-stats` `analysis_guides/multiplicity.md`).
      
      ## Ranking stability — the trap a difference calc still misses
      
      A **single-run** leaderboard ranks models by *true skill + run-to-run noise* (random seed, data order,
      augmentation draw). Near-tied models can swap rank between seeds, so "our model ranked first" from one
      run is not evidence. Two additions:
      
      - **Report run-to-run variance:** train each model over **multiple seeds** and report the metric's
        seed SD; for the paired difference of repeated cross-validation runs use the **Nadeau–Bengio
        corrected-resampled variance** (a naïve paired t over overlapping CV folds is anticonservative).
      - **Comparing many models across independent datasets:** the **Demšar (2006)** framework — Friedman
        test + Nemenyi **critical-difference** — tells you which rank gaps are real. Its sampling unit is the
        **independent dataset**, so its N is the *number of datasets*: extra seeds and overlapping CV folds do
        not raise it (those buy you the run-to-run spread above), and per-structure scores from one cohort are
        correlated blocks, not substitutes for datasets. Models inside the critical difference are **not
        separated by the test** — leave them unranked, and do not upgrade that to a demonstrated tie
        (failure to reject is not evidence of equality; an equivalence claim needs its own margin).
      
      ## Required parameters
      
      The **per-case-difference SD** of the primary metric (pilot / prior head-to-head; per structure for
      segmentation), the **metric** and its paired-CI method (DeLong for AUC, bootstrap for Dice), the target
      **δ or NI margin on the delta**, the **number of models + which single contrast is primary**, and (for
      a ranking claim) the **seed-to-seed SD**. Report N, the difference-SD source, the primary contrast, and
      the multiplicity handling.
      
      ## Cross-links
      
      The fair-comparison design the size serves → `design-study/references/multi_model_comparison_design.md`;
      the single-metric precision + one A-vs-B Dice contrast → `segmentation_metric_sample_size.md`;
      reader-in-the-loop (AI-vs-reader) sizing → `mrmc_reader_study_sample_size.md` (Test 14); presenting the
      result → `make-figures` `exemplar_plots/model_comparison_leaderboard.md` + `analyze-stats`
      `table-standards/table-types/model_comparison.md`; the multiplicity discipline →
      `analyze-stats` `analysis_guides/multiplicity.md`.
      
    • observational_cohort.md 2.1 KB
      # Observational Cohort Sample Size: Precision Branch
      
      Use this reference when a cohort study is extraction-constrained or when the goal is precision rather than formal power.
      
      ## When To Use
      
      - Retrospective hospital-based cohort with all eligible records included.
      - National database cohort where the sample is fixed by release permissions.
      - Sparse-event outcome where the real question is whether confidence intervals are narrow enough to support a claim.
      
      ## Core Checks
      
      1. Primary estimand: risk difference, odds ratio, hazard ratio, incidence rate, or mean difference.
      2. Event count: total events and events per modeled parameter.
      3. Precision target: acceptable confidence interval half-width or maximum acceptable upper bound.
      4. Model complexity: covariate count relative to events.
      5. Fragility: subgroup and sensitivity analyses with smaller denominators.
      
      ## Rule-of-Thumb Gates
      
      | Situation | Minimum check |
      |---|---|
      | Logistic or Cox model | Events per parameter and shrinkage/penalization consideration |
      | Sparse binary outcome | Exact or profile-likelihood confidence intervals |
      | Incidence rate | Poisson exact CI around event rate |
      | Null association claim | Upper CI bound must exclude clinically meaningful effect |
      | Subgroup analysis | Interaction test plus event count per subgroup |
      
      ## Manuscript Phrase
      
      "The study size was determined by all eligible participants in the released cohort. We therefore evaluated statistical informativeness by the number of outcome events, events per modeled parameter, and the width of the 95% confidence intervals around the primary estimate rather than by a conventional a priori recruitment target."
      
      ## Minimal R Sketch
      
      ```r
      events <- 130
      parameters <- 8
      epv <- events / parameters
      
      rate <- 130 / 250000
      poisson.test(130, T = 250000)$conf.int
      ```
      
      ## Reviewer-Safe Interpretation
      
      - If events are sparse, do not write "no association" without discussing the upper confidence bound.
      - If EPV is below 10, state that estimates are exploratory or use penalized/sparse models.
      - If a subgroup has few events, report it descriptively even when the p-value looks attractive.
      
      
    • prediction_model_sample_size.md 5 KB
      # Prediction-model sample size (Riley) — development & external validation
      
      For a **clinical prediction model** (or a medical-AI model evaluated as one), the
      events-per-variable rule of thumb (EPV ≥ 10) is **outdated and reviewer-vulnerable**. EPV
      does not target the things that determine whether a developed model is trustworthy
      (overfitting, precise risk estimates) or whether a validation is conclusive (precise
      discrimination and calibration). Use the **Riley criteria** instead — they are the current
      TRIPOD+AI-aligned standard, and they are implemented in the R packages `pmsampsize`
      (development) and `pmvalsampsize` (external validation).
      
      Apply this whenever the goal is **risk prediction / classification for use**, not a single
      predictor's hypothesis test. (For a single-predictor association test, the Hsieh/logistic
      power calculation in Test 9 is appropriate.)
      
      ## Development sample size — `pmsampsize` (Riley et al.)
      
      The minimum development sample size is the largest N satisfying four criteria
      simultaneously:
      
      1. **Small overfitting** — global shrinkage factor ≥ 0.9.
      2. **Small optimism in apparent fit** — absolute difference between apparent and adjusted
         Nagelkerke R² ≤ 0.05.
      3. **Precise estimate of overall risk** — margin of error of the mean predicted outcome
         (the intercept) ≤ 0.05.
      4. **(time-to-event)** precise estimate of the baseline survival at a key time point.
      
      Inputs you must specify (and justify from prior literature, not guess):
      - number of **candidate predictor parameters** (count dummy variables and non-linear terms,
        not just variables);
      - the anticipated model performance — a conservative **Cox-Snell R²** (derivable from an
        expected **C-statistic** + outcome prevalence) or expected R²;
      - the **outcome prevalence** (binary) or **event rate + mean follow-up** (time-to-event),
        or outcome mean/SD (continuous).
      
      ```r
      library(pmsampsize)
      # Binary outcome: prevalence 0.20, 30 candidate parameters, expected C ≈ 0.78
      # (convert C to a conservative Cox-Snell R²; pmsampsize accepts csrsquared or cstatistic)
      pmsampsize(type = "b", cstatistic = 0.78, parameters = 30, prevalence = 0.20)
      
      # Time-to-event: rate per person-year, mean follow-up, timepoint of interest
      pmsampsize(type = "s", csrsquared = 0.05, parameters = 30,
                 rate = 0.08, timepoint = 5, meanfup = 4.2)
      ```
      
      Report the **minimum N and the required number of events**, the assumed C-statistic / R²
      and its source, and the binding criterion. A development set below this is a standard
      high-impact-journal rejection.
      
      ## External-validation sample size — `pmvalsampsize` (Riley et al.)
      
      Size the validation set to estimate the key performance metrics **precisely enough to be
      conclusive** — target the confidence-interval width of each:
      
      - **discrimination** — C-statistic (target CI width, e.g. ±0.05);
      - **calibration slope** (target SE / CI width);
      - **calibration-in-the-large / O:E ratio**;
      - **(if reporting clinical utility)** the standardized **net benefit** at the decision
        threshold.
      
      ```r
      library(pmvalsampsize)
      # Validate a model with expected prevalence 0.20, anticipated C ≈ 0.78,
      # targeting a C-statistic CI half-width of 0.05 and a precise calibration slope
      pmvalsampsize(type = "b", prevalence = 0.20, cstatistic = 0.78,
                    cslope = 1, oe = 1, lpnormal = c(-0.5, 0.5),
                    cstatci = 0.10)   # target CI *width* for the C-statistic
      ```
      
      A common **floor** is ≥ 100 events and ≥ 100 non-events (Vergouwe; Collins), but
      `pmvalsampsize` gives the precise target for your metrics and usually requires more.
      
      ## Sample size for net benefit / decision-curve
      
      If the model's value claim rests on **net benefit** (decision-curve analysis), size the
      study to estimate net benefit at the relevant threshold with adequate precision —
      `pmvalsampsize` supports a net-benefit target, and the development criteria should be met
      so the model is not overfit before its utility is judged. Do not claim clinical utility
      from a decision curve estimated on an underpowered validation set.
      
      ## Reporting
      
      - State that sizing followed the **Riley criteria** (cite the originals) — not EPV-10.
      - Report the assumed C-statistic / R² / prevalence and **where they came from**.
      - For development, report N + events + the binding criterion; for validation, report the
        targeted CI widths and the resulting N (events and non-events).
      
      ## References (cite the originals)
      
      - Riley RD, Snell KIE, Ensor J, et al. Minimum sample size for developing a multivariable
        prediction model: PART II — binary and time-to-event outcomes. *Stat Med* 2019.
      - Riley RD, Ensor J, Snell KIE, et al. Calculating the sample size required for developing
        a clinical prediction model. *BMJ* 2020.
      - Riley RD, Debray TPA, Collins GS, et al. Minimum sample size for external validation of a
        clinical prediction model with a binary outcome. *Stat Med* 2021.
      - Collins GS, Ogundimu EO, Altman DG. Sample size considerations for the external
        validation of a multivariable prognostic model. *Stat Med* 2016.
      
    • segmentation_acceptability_sample_size.md 5.7 KB
      # Sizing a segmentation *usability* claim (acceptability rate, failure bound, edit time)
      
      For a study whose claim is that a segmentation model is **clinically usable** — a share of cases a
      clinician accepts, a bounded catastrophic-failure rate, a time saving — the endpoint is **not the
      mean of a per-case metric**. Test 15 sizes a mean Dice to a target precision; that calculation says
      nothing about how many cases you need to state an acceptability *rate*, and a study sized for
      metric precision is routinely far too small to bound a failure rate. This is the **size**
      counterpart to the fair-usability **design** in
      `design-study/references/segmentation_failure_characterization_design.md`; decide it before data
      collection.
      
      ## The endpoint is a proportion, not a mean
      
      An acceptability endpoint (*use-as-is*, *acceptable after minor edits*, *clinically acceptable*) is a
      **binomial proportion**. Size it to a target CI half-width δ:
      
      ```
      n ≈ (z/δ)² · p(1−p)          z = 1.96 for 95%
      ```
      
      At p = 0.90 and δ = 0.05 that is ≈ **138 cases**; at p = 0.50 (the worst case, and the value to use
      when the pilot is thin) it is ≈ **384**. Two consequences follow immediately. A proportion near the
      ceiling is cheap and one near 50% is expensive — and **you do not know which you have until you
      measure**, so size on the pessimistic p unless a pilot in the same anatomy justifies otherwise. And
      the rate is **per structure class**: acceptability is not one number (accepted use-as-is rates for a
      single pipeline have ranged from ~40% for target volumes to ~89% for normal tissue), so size on the
      **structure whose acceptability you must claim**, not on the pooled average.
      
      If the claim is against a threshold ("≥80% of cases acceptable"), size the **one-sided** comparison
      of the observed proportion to that threshold, and state the threshold and its justification before
      the data — a threshold chosen after seeing the rate is not a threshold.
      
      ## Ratings are nested in cases — a rate judged by k readers is not a simple binomial
      
      When m readers rate each of n cases, the total **is not** n·m independent observations. Ratings of
      the same case are correlated (an easy case is easy for every reader) and ratings by the same reader
      are correlated (a lenient reader is lenient throughout). Pooling them as independent overstates
      precision by the **design effect**:
      
      ```
      DE ≈ 1 + (m − 1)·ρ           n_effective ≈ n·m / DE
      ```
      
      With 3 readers per case and ρ = 0.5, DE = 2 — half the apparent sample. Either analyse at the
      **case level** (a pre-specified consensus or majority rule across readers, then a plain binomial on n
      cases) or model the clustering (mixed-effects / GEE with case and reader as random effects) and size
      with the inflation. Pick one at design time; the choice changes n by a factor of two or more.
      
      ## Bounding a catastrophic-failure rate — the rule of three
      
      A usability claim usually carries an implicit safety claim: *catastrophic failures are rare*.
      Rarity has to be sized for, and it is expensive. If **zero** events are observed in n cases, the
      one-sided 95% upper bound on the rate is approximately
      
      ```
      upper bound ≈ 3 / n
      ```
      
      So bounding a catastrophic-failure rate at **≤ 1% requires ~300 clean cases**; at ≤ 0.5%, ~600. This
      is the number that most often breaks a usability claim retrospectively: a study sized to estimate
      mean Dice on 40–60 cases can observe zero catastrophic failures and still only bound the rate at
      ~5–8%, which is not a safety statement. If the design cannot reach n, say what the observed data can
      actually bound rather than reporting "no failures occurred" as though it settled the question.
      
      ## Edit time / correction effort — paired, per structure
      
      If the claim is that the model saves work, the endpoint is a **paired per-case time difference**
      (edit the auto-contour vs contour from scratch, same cases): size on the **SD of the per-case
      difference**, exactly as in Test 16, not on the SDs of the two marginal times. Two design points the
      published record insists on:
      
      - **Size per structure, not on the pooled saving.** A multi-centre evaluation reporting an overall
        46% saving simultaneously found **no significant saving** for five lymph-node levels, and some
        centres were **slower editing than contouring manually**. A study powered only on the pooled
        contrast cannot support or refute any per-structure claim.
      - **Site is a second grouping factor.** If the claim is multi-centre, the per-centre effects differ
        in sign, so size for the centres you intend to claim over (or restrict the claim).
      
      ## Required parameters
      
      The **acceptability definition and scale** and which level counts as "accepted" (*use-as-is* and
      *acceptable-after-minor-edits* are different endpoints with different n); the **expected rate p** per
      structure class (pilot, else 0.5) and the target **δ or threshold**; the **number of readers per
      case** and the analysis unit (consensus vs mixed-effects) with the assumed ρ; the **catastrophic-rate
      bound** you must be able to state; and, for a work-saving claim, the **SD of the per-case time
      difference** per structure. Report n, the assumed p and ρ, the analysis unit, and what
      failure rate the design can bound.
      
      ## Cross-links
      
      The usability design this size serves → `design-study`
      `references/segmentation_failure_characterization_design.md`; the single-metric precision (mean Dice
      per structure) → `segmentation_metric_sample_size.md` (Test 15); the paired between-model delta →
      `multi_model_comparison_sample_size.md` (Test 16); reader-in-the-loop diagnostic sizing →
      `mrmc_reader_study_sample_size.md` (Test 14); presenting the result →
      `make-figures` `exemplar_plots/segmentation_failure_panel.md`; abstention and risk–coverage instead
      of a fixed acceptability rate → `/uncertainty-imaging`.
      
    • segmentation_metric_sample_size.md 3.9 KB
      # Segmentation-metric sample size (Dice / HD95 / NSD precision)
      
      For a **segmentation** validation, the sizing question is not "how many events" but **how many
      cases to estimate the segmentation metric precisely enough to be conclusive** — and, for a
      comparison, precisely enough to separate the models. The diagnostic-accuracy calc (Test 1) and the
      Riley prediction-model calc (Tests 12–13) do not apply: the outcome is a per-case **overlap /
      boundary** score (Dice, HD95, NSD), bounded and often skewed, not a proportion or a risk. This is
      the **design-time** case count for a segmentation study — including the external cohort a genuine
      generalization claim needs (see `design-study/references/combine_models_ablation_design.md` and
      `venue_accept_recipe.md`).
      
      ## Why a proportion/events calculation is the wrong tool
      
      Per-case **Dice is bounded [0,1] and heteroscedastic**: near-ceiling and low-variance for large,
      easy organs, but low and high-variance for **small or hard structures**. Precision therefore depends
      on the **SD of per-case Dice**, which you must take from a **pilot or literature** — not from a
      formula that assumes a proportion. **HD95 / NSD** are even more skewed (a few outlier cases dominate),
      so their precision is worse at the same n.
      
      ## Precision sizing (estimate a mean metric within ±δ)
      
      To estimate the mean metric with a two-sided 95% CI half-width **δ**:
      
          n ≈ ( 1.96 · SD / δ )²
      
      where **SD** is the pilot/literature SD of the **per-case** metric. Because Dice is bounded and
      non-normal, **report the CI by bootstrapping the per-case values (BCa)**, not a naïve normal CI —
      the formula sizes the study, the bootstrap reports it. For near-ceiling Dice consider a variance-
      stabilizing view or report the full distribution, since a symmetric ±δ misleads at the ceiling.
      
      ## Comparison sizing (model A vs B, or internal vs external, or an ablation contrast)
      
      A model comparison on the **same cases** is **paired**: size on the **SD of the per-case
      *difference*** (usually much smaller than the marginal SD, because easy cases are easy for both) or,
      for an "as good as" claim, a **non-inferiority margin** on Dice. This is the calculation behind the
      ablation contrasts in `combine_models_ablation_design.md` (un-adapted base, best single component,
      direct-train-vs-transfer) — each needs enough cases to make its ΔDice CI exclude zero (or the
      margin).
      
      ## Size on the worst structure, and size the external cohort
      
      - **Per-structure, not the average.** Small/hard structures dominate the variance; size on the
        **worst structure you must report**, or the study is under-powered exactly where it matters (the
        batch's honest failures: orbital-lymphoma T1c, medulloblastoma cystic subregions).
      - **The external cohort needs its own n.** The #1 acceptance lever is a *precise* external estimate
        with an honest drop; a 30-case external set gives a wide Dice CI. Size it to the precision the
        generalization claim requires (the G72 batch's external cohorts — AMOS, a 33-patient 3-centre set,
        a 72-CT set — motivate the range).
      
      ## Required parameters + compute
      
      - Pilot/literature **SD of the per-case metric** (per structure), the target **precision δ** or the
        **NI margin**, the metric itself. A t-interval on mean per-case Dice is closed-form, but the metric
        is **bounded and skewed near the ceiling**, so its nominal coverage is not the real one → **bootstrap
        per-case values** (BCa, resampling whole patients rather than structures); use the pilot for SD.
        Report N, the per-structure SD source, and δ / margin.
      
      ## Cross-links
      
      Metric **selection** (Dice + a boundary/agreement metric, per-structure) → `/model-evaluation`;
      validation design + the split-leakage gate → `/model-validation`; the comparator/ablation the size
      serves → `design-study/references/combine_models_ablation_design.md`; presenting the across-cohort
      result → `make-figures` `exemplar_plots/external_validation_comparison.md`.
      
  • SKILL.md 32.7 KB
    ---
    name: calc-sample-size
    description: >
      Interactive sample size calculator for medical research. Decision-tree guided test selection,
      reproducible R/Python code, effect size interpretation, and IRB-ready justification text.
      Supports diagnostic accuracy, agreement, proportions, continuous outcomes, survival,
      ANOVA, logistic regression, and non-inferiority/equivalence designs.
    triggers: sample size, power analysis, power calculation, how many patients, how many subjects, IRB sample size
    tools: Read, Write, Edit, Bash, Grep, Glob
    model: inherit
    ---
    
    # Calc-Sample-Size Skill
    
    You are assisting a medical researcher with sample size and power calculations. Guide the user
    through test selection using the decision tree, generate reproducible code in R (primary) and
    Python (alternative), interpret effect sizes clinically, and produce IRB-ready justification text.
    
    ## Reference Files
    
    - **Formulas**: `${CLAUDE_SKILL_DIR}/references/formulas.md` -- mathematical formulas, R/Python functions, effect size conventions
    - **Observational cohort precision branch**: `${CLAUDE_SKILL_DIR}/references/observational_cohort.md`
    - **Prediction-model / medical-AI sample size (Riley)**: `${CLAUDE_SKILL_DIR}/references/prediction_model_sample_size.md` -- the current TRIPOD+AI-aligned standard for a clinical prediction/classification model (development via `pmsampsize`, external validation via `pmvalsampsize`, net-benefit precision). Use this instead of EPV-10 whenever the goal is risk prediction for use rather than a single-predictor hypothesis test (Tests 12-13).
    - **MRMC reader-study sample size (Obuchowski–Rockette)**: `${CLAUDE_SKILL_DIR}/references/mrmc_reader_study_sample_size.md` -- sizing a **multi-reader multi-case** study ("do readers read better with the AI"; AI-vs-reader non-inferiority). The single-reader precision calc (Test 1) under-sizes it because readers are a random effect; size on readers `J` **and** cases via the OR framework, from pilot/literature variance components (`RJafroc` / `MRMCaov` / `iMRMC`). Use whenever a reader study is the design (Test 14).
    - **Segmentation-metric precision (Dice / HD95 / NSD)**: `${CLAUDE_SKILL_DIR}/references/segmentation_metric_sample_size.md` -- sizing a segmentation validation by the precision of the per-case overlap/boundary score (not a proportion): `n ≈ (1.96·SD/δ)²` from the pilot SD of per-case Dice, per structure (size on the worst), bootstrap-BCa CI, paired for a model comparison, and size the external cohort. Use whenever the outcome is Dice/HD95/NSD (Test 15).
    - **Between-model comparison sample size**: `${CLAUDE_SKILL_DIR}/references/multi_model_comparison_sample_size.md` -- sizing a study whose claim is that **one model beats others** (several models head-to-head). Single-model precision under-sizes it: power the **difference**. Pair the design (same cases through all models) → size on the **SD of the per-case difference**; **DeLong** for a paired ΔAUC, bootstrap-paired for ΔDice; for **>2 models** pre-specify one primary contrast or pay the family-wise multiplicity; and for a ranking claim, seed for **rank stability** (Nadeau–Bengio variance, Demšar critical-difference). Use whenever the endpoint is "model A > B/C/…" (Test 16).
    - **Segmentation usability sample size**: `${CLAUDE_SKILL_DIR}/references/segmentation_acceptability_sample_size.md` -- sizing a **usability** claim rather than a metric: the acceptability endpoint is a **proportion** (`n ≈ (z/δ)²p(1−p)`, size on the pessimistic p, size **per structure class**); ratings by m readers are **nested**, so pooling n·m overstates precision by `1+(m−1)ρ`; bounding a **catastrophic-failure rate** needs the **rule of three** (≤1% ⇒ ~300 clean cases — a metric-precision study bounds nothing); **edit time** is a paired per-case difference sized per structure and per site. Use whenever the claim is "clinicians can use this" (Test 17).
    - **Justification prose exemplars**: `${CLAUDE_SKILL_DIR}/references/justification_examples.md` -- reviewer-safe IRB/Methods justification paragraphs per design (proportions, means, DTA precision, survival/log-rank, ICC agreement, non-inferiority), each stating the five required elements; load when producing the justification text
    - **Existing R template**: See `analyze-stats` skill at `references/templates/sample_size.R` for the 7 original tests
    
    Read `formulas.md` before generating calculation code.
    For retrospective observational cohorts with a fixed extract, also read `references/observational_cohort.md` and report event budget / confidence-interval precision instead of forcing a prospective recruitment-style power calculation.
    
    ## Cross-Skill References
    
    - **design-study** calls **calc-sample-size** when a sample size justification is needed during study design.
    - **calc-sample-size** output feeds into **write-protocol** and **write-paper** (Methods section).
    - Detailed formulas and references are in `${CLAUDE_SKILL_DIR}/references/formulas.md`.
    
    ---
    
    ## Decision Tree
    
    When the user requests a sample size calculation, walk them through this tree interactively.
    Ask one question at a time. Do not assume answers.
    
    ```
    What is your primary outcome?
    |
    +-- Binary (yes/no, positive/negative)
    |   |
    |   +-- Paired data (same subjects, two methods)?
    |   |   +-- YES --> [5] McNemar test
    |   |   +-- NO  --> How many groups?
    |   |       +-- 2 groups, superiority     --> [4] Two-proportion comparison (chi-square)
    |   |       +-- 2 groups, non-inferiority --> [10] Non-inferiority / equivalence
    |   |       +-- Multivariable model       --> single-predictor hypothesis test? --> [9] Logistic regression
    |   |                                     --> clinical prediction / AI model for use?
    |   |                                         +-- developing the model  --> [12] Prediction-model development (Riley)
    |   |                                         +-- externally validating  --> [13] External-validation (Riley)
    |   |
    +-- Continuous (measurement, score)
    |   |
    |   +-- How many groups?
    |       +-- 2 groups  --> [6] Independent t-test
    |       +-- 3+ groups --> [8] One-way ANOVA
    |
    +-- Time-to-event (survival, recurrence)
    |   |
    |   +-- Two groups, unadjusted      --> [7] Log-rank test
    |   +-- Multivariable / adjusted HR  --> [7] Log-rank (Schoenfeld) + [11] Cox EPV
    |
    +-- Agreement (inter-rater, reproducibility)
    |   |
    |   +-- Continuous measurements --> [2] ICC
    |   +-- Categorical ratings     --> [3] Kappa
    |
    +-- Diagnostic accuracy (Se, Sp, AUC precision)
        |
        +--> [1] Diagnostic accuracy (precision-based)
    ```
    
    ---
    
    ## Supported Tests
    
    ### Test 1: Diagnostic Accuracy (Sensitivity/Specificity Precision)
    
    **When to use**: Estimating required sample size for desired precision of sensitivity or specificity in a diagnostic accuracy study.
    
    **Required parameters** (ask the user):
    | Parameter | Description | Default |
    |-----------|-------------|---------|
    | `sensitivity_expected` | Expected sensitivity | 0.85 |
    | `ci_half_width` | Desired half-width of 95% CI | 0.05 |
    | `prevalence` | Disease prevalence in study population | 0.30 |
    | `alpha` | Significance level | 0.05 |
    | `attrition_rate` | Expected dropout/exclusion rate | 0.15 |
    
    **Effect size interpretation**: The CI half-width determines precision. A half-width of 0.05 means the 95% CI for sensitivity will be within +/-5 percentage points. Narrower CIs require larger samples.
    
    ---
    
    ### Test 2: ICC Agreement (Bonett 2002)
    
    **When to use**: Inter-rater or intra-rater agreement for continuous measurements (e.g., tumor size, angle measurement).
    
    **Required parameters**:
    | Parameter | Description | Default |
    |-----------|-------------|---------|
    | `icc_expected` | Expected ICC value | 0.75 |
    | `icc_null` | Null hypothesis ICC (lower bound) | 0.50 |
    | `n_raters` | Number of raters | 2 |
    | `alpha` | Significance level | 0.05 |
    | `power` | Desired power | 0.80 |
    | `attrition_rate` | Expected dropout rate | 0.10 |
    
    **Effect size interpretation**: ICC < 0.50 = poor, 0.50-0.75 = moderate, 0.75-0.90 = good, > 0.90 = excellent (Koo & Li, 2016).
    
    ---
    
    ### Test 3: Kappa Agreement (Donner & Eliasziw 1992)
    
    **When to use**: Inter-rater agreement for categorical ratings (e.g., BI-RADS category, lesion present/absent).
    
    **Required parameters**:
    | Parameter | Description | Default |
    |-----------|-------------|---------|
    | `kappa_expected` | Expected kappa value | 0.70 |
    | `kappa_null` | Null hypothesis kappa | 0.40 |
    | `po_expected` | Expected proportion of agreement | 0.75 |
    | `alpha` | Significance level | 0.05 |
    | `power` | Desired power | 0.80 |
    | `attrition_rate` | Expected dropout rate | 0.10 |
    
    **Effect size interpretation**: Kappa < 0.20 = slight, 0.21-0.40 = fair, 0.41-0.60 = moderate, 0.61-0.80 = substantial, 0.81-1.00 = almost perfect (Landis & Koch, 1977).
    
    ---
    
    ### Test 4: Two-Proportion Comparison (Chi-Square)
    
    **When to use**: Comparing proportions between two independent groups (e.g., AI detection rate vs. conventional detection rate).
    
    **Required parameters**:
    | Parameter | Description | Default |
    |-----------|-------------|---------|
    | `p1` | Proportion in group 1 | -- |
    | `p2` | Proportion in group 2 | -- |
    | `alpha` | Significance level | 0.05 |
    | `power` | Desired power | 0.80 |
    | `attrition_rate` | Expected dropout rate | 0.15 |
    
    **Effect size interpretation**: Cohen's h = 2 * arcsin(sqrt(p1)) - 2 * arcsin(sqrt(p2)). Small = 0.20, medium = 0.50, large = 0.80.
    
    ---
    
    ### Test 5: McNemar Test (Paired Proportions)
    
    **When to use**: Paired binary outcomes (e.g., two readers reading same cases, before/after on same patients).
    
    **Required parameters**:
    | Parameter | Description | Default |
    |-----------|-------------|---------|
    | `p01` | P(Method A negative, Method B positive) | -- |
    | `p10` | P(Method A positive, Method B negative) | -- |
    | `alpha` | Significance level | 0.05 |
    | `power` | Desired power | 0.80 |
    | `attrition_rate` | Expected dropout rate | 0.10 |
    
    **Effect size interpretation**: The ratio p10/p01 (discordant ratio) drives the required sample size. Larger asymmetry in discordant pairs means fewer subjects needed. Only discordant pairs contribute information.
    
    ---
    
    ### Test 6: Independent t-Test
    
    **When to use**: Comparing means between two independent groups (e.g., lesion size in malignant vs. benign).
    
    **Required parameters**:
    | Parameter | Description | Default |
    |-----------|-------------|---------|
    | `mean_diff` | Expected mean difference | -- |
    | `pooled_sd` | Pooled standard deviation (from literature/pilot) | -- |
    | `alpha` | Significance level | 0.05 |
    | `power` | Desired power | 0.80 |
    | `attrition_rate` | Expected dropout rate | 0.15 |
    
    **Effect size interpretation**: Cohen's d = mean_diff / pooled_sd. Small = 0.20, medium = 0.50, large = 0.80. In clinical terms, d = 0.50 means the groups differ by half a standard deviation.
    
    ---
    
    ### Test 7: Survival / Log-Rank Test (Schoenfeld 1981)
    
    **When to use**: Comparing survival or time-to-event between two groups (e.g., treatment vs. control, RFA vs. surgery).
    
    **Required parameters**:
    | Parameter | Description | Default |
    |-----------|-------------|---------|
    | `hr` | Expected hazard ratio | -- |
    | `median_ctrl` | Median survival in control arm (months) | -- |
    | `accrual_time` | Accrual period (months) | 12 |
    | `follow_up` | Follow-up after accrual (months) | 24 |
    | `drop_rate` | Annual dropout rate | 0.05 |
    | `alpha` | Significance level | 0.05 |
    | `power` | Desired power | 0.80 |
    
    **Effect size interpretation**: HR < 1 favors treatment. HR = 0.50 means treatment halves the hazard (strong effect). HR = 0.80 is a modest 20% reduction. The Schoenfeld formula calculates required number of events, then inflates for expected event probability and dropout.
    
    ---
    
    ### Test 8: One-Way ANOVA (NEW)
    
    **When to use**: Comparing means across 3 or more independent groups (e.g., comparing AI model performance across 3 architectures, comparing measurement accuracy across multiple readers).
    
    **Required parameters**:
    | Parameter | Description | Default |
    |-----------|-------------|---------|
    | `k` | Number of groups | -- |
    | `f` | Cohen's f effect size | -- |
    | `alpha` | Significance level | 0.05 |
    | `power` | Desired power | 0.80 |
    | `attrition_rate` | Expected dropout rate | 0.15 |
    
    **Help user estimate Cohen's f**:
    - If the user knows group means and pooled SD: f = sigma_means / pooled_SD
    - If the user knows eta-squared: f = sqrt(eta_sq / (1 - eta_sq))
    - Benchmarks: small = 0.10, medium = 0.25, large = 0.40
    
    **R function**: `pwr::pwr.anova.test(k, f, sig.level, power)`
    **Python equivalent**: `statsmodels.stats.power.FTestAnovaPower().solve_power(effect_size, nobs, alpha, power, k_groups)`
    
    **Effect size interpretation**: Cohen's f = 0.25 (medium) means the group means span about half a pooled SD. In clinical terms, this is typically a meaningful difference across treatment arms or measurement methods.
    
    ---
    
    ### Test 9: Logistic Regression (NEW)
    
    **When to use**: Multivariable binary outcome models (e.g., predicting malignancy from multiple imaging features). Two approaches are provided.
    
    **Required parameters**:
    | Parameter | Description | Default |
    |-----------|-------------|---------|
    | `n_predictors` | Number of predictor variables | -- |
    | `event_rate` | Expected event rate (proportion with outcome) | -- |
    | `or_interest` | Odds ratio of interest (for Hsieh formula) | -- |
    | `r2_other` | R-squared of covariate with other predictors | 0.0 |
    | `alpha` | Significance level | 0.05 |
    | `power` | Desired power | 0.80 |
    | `attrition_rate` | Expected dropout rate | 0.10 |
    
    **Approach A: Peduzzi Rule of Thumb (EPV >= 10)**
    - N_events = 10 * n_predictors
    - N_total = N_events / event_rate
    - Simple, widely cited, conservative. Use as a minimum baseline **for a single-predictor
      hypothesis test only**. For a **clinical prediction / medical-AI model intended for use**,
      EPV-10 is outdated and reviewer-vulnerable — use the Riley criteria in Test 12
      (development) / Test 13 (validation) instead.
    
    **Approach B: Hsieh (1989) Formula**
    - Uses the OR of interest for the primary predictor to calculate a more precise sample size.
    - Accounts for correlation with other predictors via R-squared adjustment.
    
    **Always report both approaches** and recommend the larger N.
    
    **Effect size interpretation**: OR = 1.5 is a small-to-moderate effect; OR = 2.0 is moderate; OR = 3.0+ is large. The Peduzzi rule ensures model stability; the Hsieh formula targets power for the primary predictor.
    
    ---
    
    ### Test 10: Non-Inferiority / Equivalence (NEW)
    
    **When to use**: Demonstrating that a new method is not worse than the standard by more than a pre-specified margin (non-inferiority) or that two methods are equivalent within a margin (equivalence / TOST).
    
    **Required parameters**:
    | Parameter | Description | Default |
    |-----------|-------------|---------|
    | `design` | "non-inferiority" or "equivalence" | "non-inferiority" |
    | `outcome_type` | "proportion" or "continuous" | -- |
    | `p_reference` | Reference group proportion (if proportion) | -- |
    | `margin` | Non-inferiority or equivalence margin (delta) | -- |
    | `sd` | Standard deviation (if continuous) | -- |
    | `alpha` | One-sided alpha for NI; two one-sided for equivalence | 0.025 (NI) / 0.05 (equiv) |
    | `power` | Desired power | 0.80 |
    | `attrition_rate` | Expected dropout rate | 0.15 |
    
    **Key guidance for margin selection**:
    - The margin must be clinically justified and smaller than the effect of the reference treatment vs. placebo.
    - Common approach: margin = 50% of the established treatment effect (preservation of effect).
    - For proportions: absolute difference margin (e.g., delta = 0.10 means new method can be at most 10 percentage points worse).
    - For continuous: margin in the same unit as the outcome.
    
    **Non-inferiority (one-sided test)**:
    - H0: new - reference <= -margin (new is inferior)
    - H1: new - reference > -margin (new is non-inferior)
    - Alpha is one-sided (typically 0.025).
    
    **Equivalence (TOST)**:
    - H0: |new - reference| >= margin
    - H1: |new - reference| < margin
    - Two one-sided tests, each at alpha (typically 0.05 overall).
    
    **Effect size interpretation**: The margin defines the largest clinically acceptable difference. A smaller margin requires a larger sample. Always justify the margin based on clinical reasoning and prior literature.
    
    ---
    
    ### Test 11: Cox Regression EPV (Events Per Variable)
    
    **When to use**: Multivariable Cox proportional hazards models — ensuring enough events for stable model estimates. Same EPV logic as logistic regression (Test 9), applied to time-to-event outcomes.
    
    **Required parameters**:
    | Parameter | Description | Default |
    |-----------|-------------|---------|
    | `n_predictors` | Number of predictor variables in Cox model | -- |
    | `event_rate` | Expected proportion of subjects experiencing the event | -- |
    | `epv` | Events per variable target | 10 |
    | `attrition_rate` | Expected dropout rate | 0.10 |
    
    **Formula**:
    ```
    N_events = EPV × n_predictors
    N_total = N_events / event_rate
    N_adj = N_total / (1 - attrition_rate)
    ```
    
    **EPV guidelines**:
    - EPV >= 10: minimum for stable estimates (Peduzzi et al., 1995)
    - EPV >= 20: recommended for reliable CI coverage and type I error control
    - EPV < 5: model likely unstable — reduce predictors or use penalized methods
    
    **Effect size interpretation**: The EPV rule ensures model stability, not power for a specific HR. If the user also needs power for detecting a specific HR, combine with Test 7 (log-rank/Schoenfeld) and report the larger N.
    
    **Always report both approaches** (EPV minimum + Schoenfeld power, if HR is available) and recommend the larger N.
    
    ---
    
    ### Test 12: Prediction-Model Development (Riley)
    
    **When to use**: developing a clinical prediction / classification model (including a
    medical-AI model evaluated as one) — the goal is risk prediction *for use*, not a single
    predictor's hypothesis test. EPV-10 (Tests 9/11) is outdated here.
    
    **Approach**: the minimum N is the largest satisfying all four Riley criteria
    simultaneously — global shrinkage ≥ 0.9, apparent–adjusted R² gap ≤ 0.05, precise overall
    risk estimate, and (time-to-event) precise baseline survival. Implemented in R `pmsampsize`.
    
    **Required parameters**: number of **candidate predictor parameters** (count dummy/non-linear
    terms), a conservative expected **C-statistic or Cox-Snell R²** (with its literature source),
    and outcome **prevalence** (binary) or **event rate + mean follow-up** (time-to-event).
    
    Read `${CLAUDE_SKILL_DIR}/references/prediction_model_sample_size.md` for the criteria, the
    `pmsampsize` code, and the reporting requirements. Report N + required events + the binding
    criterion + the assumed C/R² and its source.
    
    ---
    
    ### Test 13: External-Validation Sample Size (Riley)
    
    **When to use**: sizing an **external validation** of an existing prediction/AI model.
    
    **Approach**: size to estimate the key validation metrics *precisely enough to be
    conclusive* — target the CI width of the **C-statistic**, the **calibration slope**, the
    **calibration-in-the-large / O:E ratio**, and (if a utility claim) **net benefit**.
    Implemented in R `pmvalsampsize`. A floor of ≥ 100 events and ≥ 100 non-events applies, but
    the precise target is usually larger.
    
    **Required parameters**: expected **prevalence**, anticipated **C-statistic**, and the
    target CI widths.
    
    Read `${CLAUDE_SKILL_DIR}/references/prediction_model_sample_size.md` for the `pmvalsampsize`
    code. Report the targeted CI widths and the resulting events / non-events.
    
    ---
    
    ### Test 14: MRMC Reader Study (Obuchowski–Rockette)
    
    **When to use**: sizing a **multi-reader multi-case (MRMC) reader study** — "do readers read
    better *with* the AI", or "is the AI non-inferior to readers". The single-reader AUC-precision
    calculation (Test 1) **under-sizes** this: readers as well as cases are random, so power must
    cover the **reader-variance** term, and a null from an under-sized reader study is *inconclusive,
    not negative*.
    
    **Approach**: invert the OR variance formula over the number of readers `J` and the case counts
    `N⁺`/`N⁻`; report the **`J × N` power grid** (past a modest case count, adding readers usually
    buys more power than adding cases). Requires **variance components** from a pilot or literature —
    the real bottleneck. Implemented in R `RJafroc` / `MRMCaov` / FDA `iMRMC` (integrate; do not
    hand-roll the OR algebra).
    
    **Required parameters**: the **effect** (ΔAUC, or the **non-inferiority margin** — an AI-vs-reader
    claim is usually NI), the expected AUC level, the **variance components** (pilot/literature), the
    **design** (fully-crossed vs crossover-with-washout), and power/α.
    
    Read `${CLAUDE_SKILL_DIR}/references/mrmc_reader_study_sample_size.md` for the framework, the
    readers-vs-cases trade-off, software, and reporting. Reader-study *design internals* live in
    `design-study` (`reader_elicitation_design.md`); an AI-vs-human-expert benchmark routes to
    `/design-ai-benchmarking`.
    
    ---
    
    ### Test 15: Segmentation-metric precision (Dice / HD95 / NSD)
    
    **When to use**: sizing a **segmentation** validation — how many cases to estimate the segmentation
    metric (Dice / HD95 / NSD) precisely enough to be conclusive, or to separate two models. The
    proportion/events calcs (Tests 1, 12–13) do not apply: the outcome is a bounded, skewed per-case
    overlap/boundary score, not a proportion.
    
    **Approach**: precision sizing `n ≈ (1.96·SD/δ)²` from the **pilot/literature SD of per-case Dice**
    (per structure — size on the **worst** structure you must report, not the average); report the CI by
    **bootstrapping per-case values (BCa)** — a t-interval is closed-form but Dice is bounded and
    non-normal near the ceiling, so its coverage is not the coverage you asked for, and BCa must resample
    whole **patients**, not structures. A model comparison on the same cases is **paired** (size on the SD of the per-case
    *difference*, or an NI margin). **Size the external cohort too** — a precise external estimate is the
    #1 acceptance lever.
    
    **Required parameters**: the **per-structure SD of per-case Dice** (pilot/literature), the target
    **precision δ** or **NI margin**, and the metric.
    
    Read `${CLAUDE_SKILL_DIR}/references/segmentation_metric_sample_size.md` for the per-structure and
    paired-comparison detail. The comparator/ablation the size serves lives in `design-study`
    (`combine_models_ablation_design.md`); metric selection is `/model-evaluation`.
    
    ---
    
    ### Test 16: Between-model comparison (is model A really better than B, C, …)
    
    **When to use**: the claim is that **one model outperforms others** — several architectures / families
    compared head-to-head on the same task. Single-model precision (Test 1 AUC, Test 15 Dice) under-sizes
    it: two models can each have a tight CI and still overlap, so the **difference** must be powered.
    
    **Approach**: run all models on the **same cases** (paired / within-case) and size on the **SD of the
    per-case difference** — `σ√(2(1−ρ))`, below either marginal SD once ρ > 0.5, which shared easy/hard cases
    usually clear. Use **DeLong** for a paired ΔAUC (or Obuchowski for the MRMC/clustered case) and a
    **bootstrap of the paired per-case differences** for ΔDice; size so the delta CI excludes zero, or so its
    lower bound clears the NI margin (the whole interval inside ±margin is *equivalence*, a stricter claim).
    For **>2 models**, pre-specify **one primary contrast** (proposed vs a strong, fairly-tuned baseline) at
    full α — or, if all pairwise are confirmatory, pay the **family-wise** correction (higher n per contrast).
    For a **ranking** claim, a single-run leaderboard ranks by luck: train over **multiple seeds**
    (Nadeau–Bengio corrected variance for repeated-CV differences) and leave models inside the **Demšar
    critical difference** unranked — not separated by the test is not a demonstrated tie, and Demšar's N
    counts independent datasets, not seeds.
    
    **Required parameters**: the **per-case-difference SD** of the primary metric (pilot / prior head-to-head;
    per structure for segmentation), the metric + paired-CI method, the target **δ or NI margin on the delta**,
    the **number of models + the primary contrast**, and (for ranking) the **seed-to-seed SD**.
    
    Read `${CLAUDE_SKILL_DIR}/references/multi_model_comparison_sample_size.md` for the paired-difference,
    multiplicity, and ranking-stability detail. The fair-comparison design the size serves lives in
    `design-study` (`multi_model_comparison_design.md`); presenting it is `make-figures`
    (`exemplar_plots/model_comparison_leaderboard.md`).
    
    ---
    
    ### Test 17: Segmentation usability (acceptability rate, failure bound, edit time)
    
    **When to use**: the claim is that a segmentation model is **clinically usable** — a share of cases a
    clinician accepts, a bounded catastrophic-failure rate, a time saving — not that its mean metric is
    high. Test 15 sizes a mean Dice to a precision and says nothing about any of these.
    
    **Approach**: an acceptability endpoint is a **proportion**: `n ≈ (z/δ)²·p(1−p)` — ≈138 cases at
    p = 0.90, δ = 0.05, but ≈384 at p = 0.50, so size on the pessimistic p unless a pilot in the same
    anatomy says otherwise, and size **per structure class** (use-as-is rates for one pipeline have run
    from ~40% for target volumes to ~89% for normal tissue). When m readers rate each case the ratings
    are **nested**, not independent: pooling n·m overstates precision by `DE ≈ 1 + (m−1)ρ` (3 readers at
    ρ = 0.5 halves it) — pre-specify either a case-level consensus rule or a mixed-effects/GEE analysis.
    To bound a **catastrophic-failure rate**, zero events in n cases gives an upper bound of ≈ `3/n`
    (**rule of three**), so ≤1% needs ~300 clean cases; a 40–60-case study bounds nothing below ~5–8%.
    For an **edit-time** claim, size the paired per-case time difference (as Test 16) **per structure and
    per site** — pooled savings coexist with structures and centres showing none.
    
    **Required parameters**: the acceptability scale and which level counts as accepted (*use-as-is* vs
    *after minor edits* are different endpoints), the expected **p** per structure class and target **δ or
    threshold**, the **readers per case** + analysis unit + assumed **ρ**, the **catastrophic bound** you
    must state, and (for work saving) the **SD of the per-case time difference**.
    
    Read `${CLAUDE_SKILL_DIR}/references/segmentation_acceptability_sample_size.md` for the proportion,
    clustering, rule-of-three and edit-time detail. The usability design the size serves lives in
    `design-study` (`segmentation_failure_characterization_design.md`); presenting it is `make-figures`
    (`exemplar_plots/segmentation_failure_panel.md`).
    
    ---
    
    ## Scope Limitations
    
    ### Supported
    The 11 tests listed above cover the vast majority of sample size calculations needed in medical imaging research, diagnostic accuracy studies, and clinical trials.
    
    ### NOT Supported
    The following designs require specialized software or biostatistician consultation:
    - **Adaptive trials** (group-sequential, sample size re-estimation)
    - **Cluster-randomized trials** (design effect, ICC-based inflation)
    - **Bayesian sample size determination**
    - **Crossover designs**
    - **Multi-endpoint correction** (mention Bonferroni adjustment if asked, but do not compute corrected sample sizes)
    
    If the user requests any of these, respond:
    > "This design requires specialized tools beyond this skill's scope. Consider using G*Power software (free, https://www.psychologie.hhu.de/gpower), PASS software, or consulting a biostatistician for [specific design]."
    
    ---
    
    ## Workflow
    
    ### Phase 1: Understand the Study
    
    1. Ask the user to describe their study briefly (design, primary outcome, groups).
    2. Walk through the decision tree to identify the appropriate test.
    3. Confirm the selected test with the user before proceeding.
    
    ### Phase 2: Collect Parameters
    
    1. Present the parameter table for the selected test.
    2. For each parameter without a user-provided value, explain what it means and offer the default.
    3. Help the user estimate effect sizes from:
       - Prior literature (ask for references)
       - Pilot data
       - Cohen's conventions (as a last resort, with a note that convention-based estimates are less precise)
    
    ### Phase 2b: Retrospective Study — Experience-Based Sample Size Justification
    
    For retrospective studies, formal power analysis is often impractical because the dataset
    already exists. In these cases, an experience-based justification is acceptable for IRB
    and many journals. Offer this path when the user describes a retrospective design.
    
    **Two approaches**:
    
    #### Approach A: Institution Volume-Based
    
    Estimate N from the number of examinations performed at the institution during the study period.
    
    ```
    Total exams in period × prevalence of target condition × (1 - exclusion rate) = Expected N
    ```
    
    - Ask the user for: annual exam volume for the modality, study period length, estimated
      prevalence, and expected exclusion rate
    - This gives a realistic upper bound for N
    
    **IRB justification template**:
    > Based on approximately [X] [modality] examinations performed annually at [institution],
    > and an estimated prevalence of [condition] of [Y]%, we anticipate identifying approximately
    > [N] eligible patients over the [Z]-year study period. After accounting for an estimated
    > [W]% exclusion rate (due to [reasons]), we expect a final sample of approximately [N_adj]
    > patients for analysis.
    
    #### Approach B: Prior Study-Based
    
    Use sample sizes from published studies with similar designs as justification.
    
    - Search for 3-5 comparable studies and report their sample sizes
    - The user's N should be in the same range or larger
    - Cite the specific studies in the IRB justification
    
    **IRB justification template**:
    > Previous studies evaluating [similar topic] with [similar design] enrolled [N1] (Author1
    > et al., Year), [N2] (Author2 et al., Year), and [N3] (Author3 et al., Year) patients.
    > Our anticipated sample of [N] patients is [comparable to / larger than] these prior studies.
    
    #### When to Use Formal Calculation Instead
    
    Even for retrospective studies, a formal sample size calculation is preferred when:
    - The study is prospective or will prospectively enroll a subset
    - The primary analysis involves hypothesis testing (not just estimation)
    - The journal explicitly requires power analysis (check Instructions for Authors)
    - The IRB requires it for approval
    
    In these cases, proceed to Phase 3 with the appropriate test from the decision tree.
    
    ---
    
    ### Phase 3: Calculate and Report
    
    1. Read `${CLAUDE_SKILL_DIR}/references/formulas.md` for the exact formula.
    2. Generate the R code (primary) and Python code (alternative).
    3. Run the R code via Bash to produce the actual result.
    4. Present results in the output format below.
    
    ### Phase 4: Sensitivity Analysis (Optional)
    
    If the user is uncertain about parameters, offer a sensitivity table showing N across a range of plausible values (e.g., varying effect size or power from 0.80 to 0.90).
    
    ---
    
    ## Output Format
    
    Always structure the final output as follows:
    
    ```markdown
    ## Sample Size Calculation Report
    
    ### Study Design
    [1-2 sentence summary of the design and test selected]
    
    ### Parameters
    | Parameter | Value | Source |
    |-----------|-------|--------|
    | ... | ... | user / literature / convention |
    
    ### Result
    - **Required sample size**: N = [value]
    - **With [X]% attrition adjustment**: N_adj = [value]
    
    ### R Code (Reproducible)
    ```r
    # [complete, self-contained R script]
    # Dependencies: [list packages]
    # Run: Rscript sample_size_calc.R
    ```
    
    ### Python Code (Alternative)
    ```python
    # [complete, self-contained Python script]
    # Dependencies: [list packages]
    # Run: python sample_size_calc.py
    ```
    
    ### IRB Justification Text
    > A sample of [N] participants is required to detect [effect description] with [power]% power
    > at a [one/two]-sided significance level of [alpha], assuming [key assumptions].
    > Accounting for an estimated [X]% attrition rate, we plan to enroll [N_adj] participants.
    > This calculation is based on [formula/method reference].
    
    ### Effect Size Interpretation
    [Cohen's benchmark classification + clinical meaning in the context of this study]
    ```
    
    ---
    
    ## IRB Justification Text Guidelines
    
    The IRB text must:
    1. State the required N clearly.
    2. Name the statistical test and its formula source.
    3. Specify all assumed parameters (effect size, alpha, power).
    4. State the attrition adjustment and final enrollment target.
    5. Cite the methodological reference (e.g., "Schoenfeld, 1981" for survival).
    6. Use formal, third-person language suitable for an ethics board.
    
    ---
    
    ## Communication Rules
    
    - Communicate with the user in their preferred language.
    - Use English for all statistical terminology, effect size names, and test names.
    - Be explicit about assumptions and their impact on the result.
    - When the user provides vague effect size estimates, flag the uncertainty and suggest a sensitivity analysis.
    - Never fabricate references. Cite only verified methodological sources from `formulas.md`.
    
    ## Anti-Hallucination
    
    - **Never fabricate file paths, URLs, DOIs, or package names.** Verify existence before recommending.
    - **Never invent journal metadata, impact factors, or submission policies** without verification at the journal's website.
    - If a tool, package, or resource does not exist or you are unsure, say so explicitly rather than guessing.
    
  • skill.yml 2.9 KB
    schema_version: 2
    name: calc-sample-size
    layer: A
    owner_domain: study_design
    maturity: official
    when_to_use:
      - User asks for a sample size, power calculation, or "how many patients/subjects do I need"
      - Drafting an IRB sample size justification before /write-protocol Methods
      - Re-deriving N when a reviewer challenges the original power assumption
      - Estimating events-per-variable (EPV) for survival or logistic regression
    when_NOT_to_use:
      - Statistical analysis of collected data (use /analyze-stats)
      - Choosing the test itself rather than its N (use /design-study)
      - Replicating a prior study's reported N without recomputation (still re-derive)
    inputs:
      - study_design (proportions, continuous, agreement, survival, ANOVA, logistic, NI/equivalence, diagnostic accuracy, repeated measures, Cox EPV)
      - parameters (effect size, alpha, power, attrition rate, etc.)
    outputs:
      - protocol/sample_size_justification.md  # IRB-ready prose, Output Format §"IRB Justification Text"
      - protocol/sample_size_calc.R  # reproducible R script
      - protocol/sample_size_calc.py  # alternative reproducible Python script
    deterministic_scripts:
      - inline R/Python code blocks (skill-emitted, not packaged)
    side_effects:
      - none  # no external API calls; pure computation + literature anchoring
    downstream_consumers:
      - write-protocol  # embeds Output §"IRB Justification Text" verbatim into Methods §Sample Size
      - write-paper  # embeds same text into Methods (post-IRB)
      - design-study  # cross-reference for analysis-unit / cohort-logic alignment
    ssot_boundary:
      - protocol/sample_size_justification.md is the canonical sample size text. write-protocol and write-paper EMBED VERBATIM; do not rephrase numbers.
    quality_gates:
      - parameters_documented: every parameter has a Source column entry (user / literature / convention)
      - effect_size_interpretation: Cohen's benchmark classification present
      - methodological_reference: cited (e.g., "Schoenfeld, 1981" for survival)
      - reproducible_code: both R and Python emitted (skill default), runnable standalone
    forbidden_actions:
      - fabricate_effect_size_from_unverified_assumption
      - omit_attrition_or_loss_to_followup
      - silent_protocol_modification  # changes to N must update both justification.md and protocol Methods
    
    # v2.1 quality card
    purpose: "Compute sample size / power with decision-tree test selection and reproducible R/Python code plus IRB-ready justification."
    safety_boundaries:
      - "Effect-size assumptions are justified and sourced, not fabricated; attrition/loss is accounted for."
      - "Any change to N updates both the justification and the protocol Methods (no silent change)."
    known_limitations:
      - "Emits inline R/Python, not a packaged script; the user runs it."
      - "Output is only as valid as the assumed effect size and design."
    validation_commands:
      - "re-run the emitted power code and confirm N matches the justification"
    evidence_surface: manual_workflow
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related