| name | scientific-statistics |
| description | Use for statistical analysis of scientific experimental data, especially materials/MOF experiments. Inspect experimental units and pseudo-replication before inference, validate hierarchy and batch/treatment confounding, fit linear mixed-effects models, analyze repeated measures, and perform reproducible descriptive/comparison/correlation/regression/reliability/agreement analyses. Report effect sizes and confidence intervals, and refuse statistically invalid shortcuts. Trigger when users provide CSV/Excel/JSON experimental data, ask which statistical test to use, ask whether groups differ, ask for correlation/regression, mixed-effects modeling, repeated measures, ICC/CV/Bland-Altman, or need a defensible statistical report. Do not use as a substitute for domain-specific kinetic, PXRD, BET-isotherm, DOE/RSM, Bayesian optimization, raw image-analysis, or other methods outside v0.2 scope. |
Scientific Statistics Skill v0.2
Use this skill as a statistical copilot for experimental scientists. The primary goal is not maximum method coverage; it is to prevent common invalid analyses while providing a reproducible path for defensible inference.
Non-negotiable principles
- Determine the experimental unit before inferential statistics.
- Never infer independence from the number of spreadsheet rows.
- Distinguish independent synthesis replicates from technical/measurement replicates.
- Never silently delete failed experiments, missing values, or outliers.
- Never choose a test solely from a Shapiro-Wilk p-value.
- Prefer Welch's t-test over equal-variance Student's t-test unless equal variance is scientifically justified.
- For three or more groups, do not replace omnibus testing with many uncorrected t-tests.
- Report effect size and uncertainty alongside p-values whenever the implemented method supports them.
- Correlation is not causation.
- If the data structure needed for a valid analysis is unknown, stop inferential analysis and ask only the missing high-impact questions.
- Statistical evidence must constrain the strength of the scientific claim — never let interpretation outrun the data.
Read references/00-principles.md and references/01-experimental-unit.md whenever independence, replication, or data hierarchy is uncertain.
Read references/18-claim-calibration.md before writing any scientific interpretation. It defines the Claim Ladder (descriptive → inferential → adjusted → causal → validation/decision) and the hard wording rules below.
v0.2 scope
Supported deterministic calculations:
- dataset inspection and quality flags;
- experimental hierarchy validation (hierarchy module) — experimental units, technical replicates, repeated measures, independence status;
- batch/treatment confounding diagnostics (batch-check) — complete-confounding blocking, identifiability, consistency within units;
- descriptive statistics;
- independent two-group comparison: Welch t, Student t, Mann-Whitney U;
- paired two-group comparison: paired t, Wilcoxon signed-rank;
- independent multi-group comparison: classical one-way ANOVA, Welch ANOVA, Kruskal-Wallis;
- post-hoc: Tukey HSD after classical ANOVA; pairwise Welch or Mann-Whitney with multiplicity correction;
- Pearson and Spearman correlation;
- ordinary least-squares regression with basic residual/influence diagnostics;
- linear mixed-effects models (random intercept, random slope, nested fixed-effect comparison via ML LRT, convergence/singularity diagnostics);
- repeated measures: structure inspection, paired occasions, one-way RM-ANOVA with Mauchly/GG/HF sphericity, Friedman, repeated LMM, deterministic method recommendation;
- reproducibility / reliability / agreement: variance decomposition, VC-ICC, six classical ICC variants (McGraw & Wong 1996) with CIs, CV, Bland–Altman with CIs, deterministic method recommendation;
- Hedges g, Cohen dz, rank-biserial effects, eta-squared/epsilon-squared where implemented;
- mean-difference confidence intervals where implemented;
- Holm or other statsmodels-supported p-value corrections;
- raw-data group plots and scatter/regression-line plots.
Explicitly outside v0.2 (see docs/KNOWN_LIMITATIONS_V0.2.md):
- factorial DOE and response-surface optimization;
- GLMM / non-linear mixed models / crossed random-effects frameworks;
- multivariate PCA/PLS;
- dedicated PXRD-pattern, BET-isotherm, SEM-image or adsorption-kinetics analysis;
- Bayesian optimization and next-experiment recommendation;
- multiple imputation;
- equivalence/non-inferiority;
- SPC/Gage R&R;
- automated causal inference.
When a requested analysis is outside scope, explain the limitation and route to the roadmap rather than improvising an unvalidated method.
Workflow
Step 1 — Read and inspect the data
For CSV/XLSX/JSON, use the deterministic inspector first:
python scripts/scistat.py inspect DATA_FILE --output inspection.json
Review:
- dimensions and column types;
- missingness;
- duplicated rows;
- identifier-like fields;
- batch-like fields;
- repeated sample/synthesis identifiers;
- potential pseudo-replication warnings;
- possible outliers as review flags, not deletion instructions.
For data conventions, read references/02-data-contract.md.
Step 2 — Resolve the experimental unit
Before any p-value, determine what one independent observation represents.
Hierarchy module — Run the deterministic hierarchy validator first:
python scripts/scistat.py hierarchy DATA_FILE --output hierarchy.json
This produces:
experimental_unit_count and experimental_unit_level
observation_role_distribution (experimental_unit, technical_replicate, repeated_measure, sub_observation, unknown)
independence_status (confirmed, assumed, needs_confirmation)
- warnings such as
TECHNICAL_REPLICATES_NOT_INDEPENDENT, NEEDS_INDEPENDENCE_CONFIRMATION
Key semantic: observation count ≠ independent sample size.
2 synthesis batches × 3 BET measurements = 2 experimental units + 6 technical replicates.
Explicit experimental-unit override: when treatment is assigned below
the synthesis level (e.g. at sample level), declare it explicitly:
python scripts/scistat.py hierarchy DATA_FILE \
--synthesis-column synthesis_batch --sample-column sample_id \
--experimental-unit-column sample_id --output hierarchy.json
The override makes Python use the declared column structurally
(experimental_unit_count = unique declared units; the synthesis batch is
kept as upper-level container metadata, not independent n). Structural
identification is not proof of scientific independence: units are
reported as assumed unless provenance confirms them. Do not silently
equate a finer grouping column with a confirmed independent unit.
For MOF/materials data, explicitly determine whether rows represent:
- independent synthesis batches;
- aliquots from one synthesis;
- repeated instrument measurements;
- SEM particles nested in images and synthesis batches;
- time points from the same specimen;
- other nested/repeated observations.
If unclear, ask questions such as:
- How many independently prepared synthesis batches produced these rows?
- Are repeated measurements from the same physical sample?
- Is there a batch/operator/instrument/date variable?
- For paired data, what column identifies the same unit across conditions?
Do not proceed with inferential statistics until the answer is sufficiently clear.
Step 2b — Diagnose batch / treatment confounding
After resolving the experimental unit, check whether the treatment effect
can be distinguished from batch effects:
python scripts/scistat.py batch-check data.csv \
--treatment treatment --batch batch_id --synthesis synthesis_id
This produces:
confounding_classification: NO_APPARENT, PARTIAL, COMPLETE, or SINGLE_BATCH
identifiability.treatment_effect_identifiable: whether the design supports separating treatment from batch
cross_tab: treatment × batch experimental-unit counts
empty_cells: factor-nuisance combinations with zero experimental units
balance_summary: per-cell experimental unit counts and imbalance ratio
issues with severity levels (blocking, critical, warning)
Also supports operator and instrument diagnostics:
python scripts/scistat.py batch-check data.csv \
--treatment treatment --synthesis synthesis_id \
--operator operator --instrument instrument
Hard rule: COMPLETE_TREATMENT_BATCH_CONFOUNDING blocks inferential
claims about treatment effects. Batch correction cannot rescue a completely
confounded design.
Key principle: Batch diagnostics operate on experimental units, not
technical measurements. 2 syntheses × 10 measurements = 2 units in the
cross-tab.
Invalid experimental unit stops diagnostics: when
INCONSISTENT_FACTOR_WITHIN_EXPERIMENTAL_UNIT or
INCONSISTENT_NUISANCE_WITHIN_EXPERIMENTAL_UNIT is reported, the proposed
unit is incompatible with the factor/nuisance assignment. The output is
diagnostic_evaluable: false with confounding_classification: null —
no representative-row deduplication, no cross-tab, no COMPLETE/PARTIAL/
NO_APPARENT verdict, regardless of row order. Resolve the scientific
experimental unit before interpreting confounding (the unit may be too
coarse — a sample/specimen-level unit may be appropriate, but Python never
decides that automatically).
Propagate independence status from hierarchy:
python scripts/scistat.py batch-check data.csv \
--treatment treatment --batch batch_id --synthesis synthesis_id \
--independence-status needs_confirmation
Diagnostic vs model observation tables: The diagnostic experimental-unit
table is for confounding detection only. For mixed-effects fitting, use
build_model_observation_table() which preserves all observation rows with
experimental-unit grouping intact.
Step 3 — State the scientific question
Map the request to one of the supported question types:
- describe a variable or group;
- compare two independent groups;
- compare two paired conditions;
- compare three or more independent groups;
- quantify association between two variables;
- fit an OLS relationship between a response and predictors.
Read references/03-decision-tree.md before selecting a method.
Step 4 — Build an analysis plan before calculation
Write a compact plan containing:
- experimental unit;
- response variable;
- predictor/group variable(s);
- independent vs paired structure;
- requested scientific estimand: mean difference, distributional difference, association, regression coefficient, etc.;
- chosen method and reason;
- multiplicity plan if needed;
- exclusions, missing-data handling, and outlier policy;
- expected effect size and CI output.
Use schemas/analysis-plan.schema.json when a machine-readable plan is useful.
Step 5 — Execute deterministic calculations
Examples:
python scripts/scistat.py hierarchy data.csv --output hierarchy.json
python scripts/scistat.py hierarchy data.csv --synthesis-column synth_id --time-column day --cycle-column adsorption_cycle
python scripts/scistat.py batch-check data.csv --treatment treatment --batch batch_id --synthesis synthesis_id
python scripts/scistat.py batch-check data.csv --treatment treatment --synthesis synthesis_id --operator operator --instrument instrument
python scripts/scistat.py batch-check data.csv --factor temperature --nuisance reagent_lot
python scripts/scistat.py describe data.xlsx --columns BET yield --group treatment
python scripts/scistat.py compare data.xlsx --response BET --group treatment --levels Treatment Control --method welch
python scripts/scistat.py compare data.csv --response uptake --group condition --pair-id synthesis_id --method paired_t
python scripts/scistat.py compare data.csv --response BET --group temperature --method welch_anova
python scripts/scistat.py correlate data.csv --x modulator_eq --y BET --method spearman
python scripts/scistat.py regress data.csv --formula 'BET ~ temperature + modulator_eq'
Never fabricate numeric output if scripts cannot run. Report the execution failure and provide the analysis plan instead.
Step 6 — Check assumptions and fragility
Use graphical and substantive checks before mechanical normality-test routing. Review:
- distribution shape and extreme observations;
- sample sizes;
- group imbalance;
- pairing completeness;
- independence and nesting;
- variance differences;
- regression residual pattern, heteroskedasticity, and influential points.
Read references/04-data-quality.md and method-specific references.
Step 7 — Visualize raw observations
Prefer plots that expose raw measurements:
python scripts/scistat.py plot-group data.csv --response BET --group treatment --output bet_groups.png
python scripts/scistat.py plot-scatter data.csv --x temperature --y BET --output temp_bet.png
Do not default to a bar chart of mean ± SEM when raw observations can be shown.
Step 8 — Report in scientist-readable form
Use templates/analysis-report.md and references/12-reporting.md.
Every inferential report should state:
- scientific question;
- experimental unit and sample sizes;
- data-quality/replication caveats;
- method and why it was selected;
- point estimate and effect size when available;
- confidence interval when available;
- p-value without binary "proved/not proved" language;
- post-hoc correction if used;
- practical/scientific interpretation;
- limitations and next statistical step.
Claim calibration — before finalizing, check every major interpretation
against references/18-claim-calibration.md:
locate the result on the Claim Ladder (L1 descriptive → L5 validation/decision)
and explicitly separate what the data support from what the data do not
establish. Prohibited shortcuts:
p > 0.05 is not evidence of equivalence;
- a statistical outlier flag is not evidence of measurement error — and a
structured time/group pattern does not prove the reverse either: without
external QC or provenance, the analysis cannot establish whether
measurement error is absent, so structured outliers are retained/reviewed,
not declared "real variation" or "measurement error";
baseline p > 0.05 + balanced groups + treatment represented within
batches do not alone reach a causal (L4) claim — without documented
assignment/randomization provenance, default to adjusted/conditional (L3)
inference;
- an adjusted association is not causal proof;
- an in-sample fit is not validation.
Step 9 — Fit linear mixed-effects models
When data has a hierarchical/nested structure (multiple observations per
experimental unit), fit a linear mixed-effects model to account for
within-unit correlation:
python scripts/scistat.py mixed data.csv --response BET \
--fixed-effects treatment --random-effects 1 \
--validate-only
python scripts/scistat.py mixed data.csv --response BET \
--fixed-effects treatment --random-effects 1 \
--synthesis synthesis_id
python scripts/scistat.py mixed data.csv --response BET \
--fixed-effects treatment temperature --random-effects 1 temperature \
--random-slope temperature
python scripts/scistat.py mixed data.csv --response BET \
--fixed-effects treatment temperature --random-effects 1 \
--compare --reduced-fixed-effects treatment
python scripts/scistat.py mixed data.csv --response BET \
--formula 'BET ~ treatment * storage_day' \
--reduced-formula 'BET ~ treatment + storage_day' \
--random-effects 1 --grouping sample_id --compare
python scripts/scistat.py mixed data.csv --response BET \
--fixed-effects treatment --random-effects 1 \
--experimental-unit sample_id --synthesis synthesis_id
python scripts/scistat.py mixed data.csv --response BET \
--fixed-effects treatment --random-effects 1 --no-reml
python scripts/scistat.py mixed data.csv --response BET \
--fixed-effects treatment --random-effects 1 \
--status-column synthesis_status
python scripts/scistat.py mixed data.csv --response BET \
--fixed-effects treatment --random-effects 1 --confidence-level 0.99
This produces:
validation: pre-fit gates (response, grouping, fixed effects, independence, status-based exclusion classification)
fit_meta: optimizer used, REML/ML, likelihood type, design matrix rank, confidence level
fixed_effects: estimates, SE, z-statistics (asymptotic normal, not t), p-values, confidence intervals (ci_lower/ci_upper), categorical reference provenance for each term
random_effects: variance components, BLUPs, covariance matrix
fit_summary: log-likelihood, AIC/BIC (null under REML with status "not_applicable_under_reml"), n obs, n groups
convergence: converged/singular/boundary diagnostics (unit-invariant: correlation matrix eigenvalues for structural singularity, standardized variance contributions q_j = SD(b_j) × scale(Z_j) / SD(residual) for boundary variance, |ρ| from correlation matrix for boundary correlation; raw covariance eigenvalues saved as descriptive-only metadata)
issues: warnings and errors
Hard rules for mixed models:
independence_status = "needs_confirmation" blocks fitting. Independence
must be confirmed or assumed before a mixed model is fit.
- Model comparison uses ML, not REML — REML likelihoods are not comparable
across models with different fixed effects.
- Failed experiments must be explicitly listed via
excluded_synthesis_ids,
never silently dropped. Exclusion reasons are classified: FAILED, NO_PRODUCT,
AMORPHOUS, WRONG_PHASE.
- Random-effect variance estimates must be positive; zero or near-zero
variance components indicate over-parameterisation.
- Singular-fit warnings require model simplification (e.g., removing
random-slope terms). Three distinct boundary diagnostics are reported:
near-zero variance component (standardized contribution q_j below threshold),
near-perfect random-effect correlation (|ρ| > 0.999 from correlation matrix),
and singular covariance structure (correlation matrix eigenvalue ratio below
threshold). All three use unit-invariant measures — correlation matrix
eigenvalues, standardized contributions, and |ρ| — not raw covariance
eigenvalues.
- Design matrix rank is checked on the actual expanded design matrix (after
categorical encoding and intercept construction) via SVD with relative
tolerance. Rank-deficient designs block fitting. Pairwise correlation is
a separate heuristic warning only.
- Fixed-effect inference uses asymptotic normal (z) approximation, not
finite-sample t-distribution. CIs are symmetric: estimate ± z_crit × SE.
- AIC/BIC from REML fits are
null in JSON output. Only ML-based fits
produce valid information criteria.
- All numerical outputs are JSON-strict: NaN and Infinity are replaced
with
null throughout the output contract.
- The formula LHS must equal the
--response argument (plain column
names only; transformed responses are not supported in v0.2). A
mismatch blocks fitting/comparison with FORMULA_RESPONSE_MISMATCH.
Explicitly outside scope: GLMM and non-linear mixed models, multiple
crossed random effects, compound-symmetry / autoregressive residual
covariance structures, Gage R&R / full measurement-system analysis,
multi-lab ISO reproducibility, Bayesian hierarchical reliability, CCC,
DOE/RSM, SPC, Bayesian optimization, and repeated-measures Bland–Altman.
See docs/KNOWN_LIMITATIONS_V0.2.md.
Step 10 — Analyze repeated measures
When data has repeated observations across occasions on the same experimental
units, use the repeated-measures decision and analysis layer:
python scripts/scistat.py repeated data.csv --response BET --occasion time \
--experimental-unit synthesis_id --method inspect
python scripts/scistat.py repeated data.csv --response BET --occasion time \
--experimental-unit synthesis_id --method recommend
python scripts/scistat.py repeated data.csv --response BET --occasion time \
--method paired_t --aggregation mean
python scripts/scistat.py repeated data.csv --response BET --occasion time \
--method rm_anova
python scripts/scistat.py repeated data.csv --response BET --occasion time \
--method friedman
python scripts/scistat.py repeated data.csv --response BET --occasion time \
--method lmm --occasion-numeric --random-slope time
python scripts/scistat.py repeated data.csv --response BET --occasion time \
--treatment condition --method lmm
This produces:
structure_summary: experimental units, occasions, completeness, balance, technical replicates
decision (via recommend): candidate methods, preferred method, blocked methods, reasoning codes, assumptions to confirm
paired (via paired_t/wilcoxon): n_pairs, mean/median difference, CI, effect size, direction
anova (via rm_anova): F-value, p (uncorrected + GG/HF corrected), partial eta squared, sphericity diagnostics (Mauchly's W, GG epsilon, HF epsilon)
friedman: statistic, p-value, n blocks, Kendall's W
lmm: full mixed-model output with repeated-measures provenance
Hard rules for repeated measures:
- Technical replicates must be explicitly aggregated (mean/median) before
classical paired/RM-ANOVA/Friedman analysis. LMM can model at measurement
level but must acknowledge nested structure.
- Per-timepoint separate t-tests are NOT a valid primary analysis for
treatment × time designs. Use treatment × time interaction models.
- Sphericity-violated RM-ANOVA must report Greenhouse-Geisser corrected
p-values as the primary result, not uncorrected.
- Missing occasions must be explicitly reported; incomplete units must not
be silently dropped. LMM is preferred when missingness is substantial.
- Method selection must NOT be based on mechanical normality-test routing
(Shapiro → paired-t else Wilcoxon; Shapiro → RM-ANOVA else Friedman).
Selection is based on experimental structure, measurement scale, and
scientific estimand.
- Time representation (categorical vs numeric) must be explicitly chosen;
Python never decides automatically.
- All inferential analyses are blocked when independence_status is
needs_confirmation.
- Classical paired/RM/Friedman methods are blocked when technical replicates
exist and no aggregation is specified.
Read references/15-repeated-measures.md for the full repeated-measures decision model.
Step 11 — Analyze reproducibility, reliability & agreement
When the question is about measurement precision, rater reliability, or
method agreement, use the reproducibility analysis layer:
python scripts/scistat.py reproducibility data.csv --response BET \
--experimental-unit batch_id --method inspect
python scripts/scistat.py reproducibility data.csv --response BET \
--experimental-unit batch_id --measurement measurement_id \
--session run_day --repro-status-column status --method inspect
python scripts/scistat.py reproducibility data.csv --response BET \
--experimental-unit batch_id --target sample_id \
--method-column method --method recommend
python scripts/scistat.py reproducibility data.csv --response BET \
--experimental-unit batch_id --method variance_decomposition
python scripts/scistat.py reproducibility data.csv --response BET \
--experimental-unit batch_id --method vc_icc
python scripts/scistat.py reproducibility data.csv --response Scores \
--target Wine --rater Judge --method classical_icc --nan-policy raise
python scripts/scistat.py reproducibility data.csv --response BET \
--experimental-unit batch_id --method cv --scale-type ratio
python scripts/scistat.py reproducibility data.csv --response BET \
--target sample_id --method-column method \
--method-a old_BET --method-b new_BET --method bland_altman \
--aggregation mean --acceptable-lower -20 --acceptable-upper 20
This produces:
inspect: n_observations, n_experimental_units, has_technical_replicates, balanced, complete, missing_cells, methods, instruments, nesting summary
variance_decomposition: between_unit_variance, within_unit_variance, total_variance, variance fractions
vc_icc: variance-component ICC from two-level random intercept
classical_icc: all six ICC variants (ICC(1,1), ICC(A,1), ICC(C,1), ICC(1,k), ICC(A,k), ICC(C,k)) with CI, F, p, rater means, systematic bias flag
cv: overall CV%, per-unit CV%, pooled within-unit CV%, between-unit CV%
bland_altman: bias, SD of differences, LoA, CI for bias and both LoA bounds, heteroscedasticity check, Pearson r with explicit non-agreement caveat
Hard rules for reproducibility:
- Correlation is not agreement. High Pearson r or high ICC(C,1) does not mean two methods are interchangeable. Bland–Altman is the primary tool for method agreement.
- ICC variant must be chosen, not auto-selected. All six variants are returned. Python never selects ICC(1,1) vs ICC(A,1) vs ICC(C,1) automatically. The user/Agent must decide based on the scientific question.
- No "poor/good/excellent" classification. ICC values are reported as estimates with CIs. No automatic reliability classification is applied.
- Classical ICC requires complete, balanced target × rater design. Missing cells or unbalanced measurements block classical ICC. Use VC-ICC or
nan_policy="omit" as alternatives.
- More than one measurement in a target × rater cell is BLOCKED, not averaged.
compute_icc() validates the raw rows before pivoting and returns UNBALANCED_OR_DUPLICATED_TARGET_RATER_MEASUREMENTS. No silent mean/median/first aggregation is applied — resolve replicates explicitly, or model them with variance components.
- Bland–Altman requires one independent pair per target. Repeated measurements must be explicitly aggregated (mean/median) before Bland–Altman. Blocked otherwise.
- CV requires ratio-scale measurements (meaningful zero, all values > 0). Non-positive or near-zero means block CV computation.
- Systematic rater bias is flagged when detected (rater means differ substantially). ICC(A,1) and ICC(C,1) can differ dramatically — report both.
- t-test for zero bias does NOT prove agreement. "p > 0.05" for bias ≠ "methods agree". Absence of significant bias is not sufficient for acceptable agreement.
- Independence must be confirmed before any inferential reproducibility analysis.
- Do not conflate repeatability, reproducibility, reliability, and agreement. They are distinct questions requiring distinct tools.
- Failed syntheses are not "just another NA". Pass
--repro-status-column / status_column= so failed, no-product, amorphous, and wrong-phase units are excluded from the numeric model but retained in the reported experimental universe via exclusion_provenance. Continuous reproducibility estimates are conditional on successful numeric outcomes — never quietly rewrite the denominator to only the successful batches.
Read references/16-reproducibility-agreement.md for the full reproducibility/reliability/agreement model.
MOF/materials profile
Read references/13-mof-profile.md whenever the experiment involves MOFs, porous materials, synthesis optimization, BET, PXRD, adsorption, SEM morphology, yield, stability, or related characterization.
Hard MOF rules:
- independent synthesis batch is usually the relevant replication level for synthesis claims;
- repeated BET measurements do not create independent synthesis replicates;
- many SEM particles from one batch do not create many independent synthesis replicates;
- PXRD peaks/points are not independent samples;
- failed synthesis is an experimental outcome, not automatically missing data;
- preserve batch/date/operator/reagent-lot/instrument metadata whenever available.
Completion checks
Before finalizing any analysis, verify:
Development and extension
For implementation architecture, test requirements, cross-agent installation, and the v0.2-v1.0 plan, read: