Skip to content

Add comprehensive statistical tests value set - #77

Merged
cmungall merged 3 commits into
mainfrom
claude/stato-statistical-tests-etfpwf
Aug 1, 2026
Merged

Add comprehensive statistical tests value set#77
cmungall merged 3 commits into
mainfrom
claude/stato-statistical-tests-etfpwf

Conversation

@cmungall

@cmungall cmungall commented Aug 1, 2026

Copy link
Copy Markdown
Member

Summary

Adds a comprehensive value set for statistical hypothesis tests and related statistical concepts, and registers STATO with the repository's ontology validator so those mappings are actually checked.

Key Changes

New schema file: src/valuesets/schema/statistics/statistical_tests.yaml — 10 enums:

Enum Contents
StatisticalTestEnum ~60 tests from the descendants of statistical hypothesis test (OBI:0000673) in STATO — t/z tests, ANOVA, rank-based non-parametrics, categorical and contingency tests, goodness of fit, variance/sphericity, post-hoc, outlier detection, model comparison, survival/genetics, correlation
TTestTypeEnum one-sample, paired, two-sample equal/unequal variance, Yuen trimmed means
NormalityTestEnum Shapiro-Wilk, Kolmogorov-Smirnov, Anderson-Darling
HomoscedasticityTestEnum Levene's, Bartlett's, Brown-Forsythe, Breusch-Pagan
PostHocTestEnum Tukey HSD, Newman-Keuls, Scheffe, LSD, Dunn's, Conover-Iman
MultipleTestingCorrectionEnum Bonferroni, Holm-Bonferroni, Benjamini-Hochberg, Benjamini-Yekutieli, FWER/FDR, alpha spending/investing
CorrelationCoefficientEnum Pearson, Spearman, Kendall
TestTailednessEnum one-tailed vs two-tailed
DistributionalAssumptionEnum parametric vs non-parametric
ComparisonObjectiveEnum superiority, non-inferiority, equivalence

Validator change: registered STATO: sqlite:obo:stato in src/valuesets/validators/oak_config.yaml. STATO was previously unlisted, so its CURIEs were never strictly validated or cached — despite supplying most of the mappings in this file and appearing in three existing modules. cache/stato/terms.csv (87 terms) is the resulting machine-checked evidence.

Retroactive fix: enabling STATO surfaced two label mismatches on pre-existing mappings in bio/expression_units.yaml (FPKM, RPKM). Both CURIEs were correct; STATO's verbatim labels are added as aliases. That file goes from 14 to 12 errors — the remaining 12 are pre-existing UO/NCIT mismatches unrelated to this branch. data_science/binary_classification.yaml and medical/neuroimaging.yaml already validated clean.

Schema integration: added the statistics/statistical_tests import to valuesets.yaml.

Cache updates: ncit (+4), obi (+9), and the new stato (87) — limited to terms this branch uses.

Verification

  • All 127 CURIEs resolved against OLS; every meaning: target's ontology label matches its permissible value key, title, or an alias.
  • All 12 non-meaning: mappings (close_mappings / related_mappings) hand-verified against their owning permissible values — the evaluator only reads pv.meaning, so nothing in the repo checks these automatically.
  • just test: 63 passed, 1 skipped. just gen-project clean. statistical_tests.yaml validates clean under strict STATO mode.

Notes

  • Mappings prefer STATO, falling back to OBI and NCIT where STATO has no term.
  • Several titles reproduce upstream label typos verbatim (Barlett's test, Yate's corrected Chi-Squared test, Least significance different test) because strict validation matches on the ontology label; corrected spellings are provided as aliases.
  • Grouping classes are retained alongside concrete tests as deliberate coarse-annotation fallbacks; this is stated in the enum descriptions.
  • Derived artifacts are not committed — regen-derived.yaml regenerates them on merge to main.

Known follow-ups (out of scope)

  • just validate is not wired into CI, so the term caches are point-in-time and label drift won't be caught. main currently has 138 pre-existing errors across other modules, so this would need a baseline allowlist first.
  • enum_evaluator.py validates only pv.meaning, not close_mappings / related_mappings / exact_mappings.

https://claude.ai/code/session_01Rchj9PETEATt5FtzG9rMzd

Adds src/valuesets/schema/statistics/statistical_tests.yaml with ten
enums covering statistical hypothesis testing:

- StatisticalTestEnum: ~60 tests drawn from the descendants of
  'statistical hypothesis test' (OBI:0000673) in STATO, grouped by
  t-tests/z-tests, ANOVA, rank-based non-parametric tests, categorical
  and contingency table tests, goodness of fit, variance/sphericity,
  odds ratio homogeneity, post-hoc procedures, outlier detection,
  model comparison, survival/genetics, and correlation
- TTestTypeEnum, NormalityTestEnum, HomoscedasticityTestEnum,
  PostHocTestEnum: focused subsets for common slot ranges
- MultipleTestingCorrectionEnum: Bonferroni, Holm-Bonferroni,
  Benjamini-Hochberg, Benjamini-Yekutieli, FWER/FDR, alpha
  spending/investing
- CorrelationCoefficientEnum: Pearson, Spearman, Kendall
- TestTailednessEnum, DistributionalAssumptionEnum,
  ComparisonObjectiveEnum (superiority/non-inferiority/equivalence)

All 127 CURIEs were resolved and label-checked against OLS; every
'meaning:' target's ontology label matches the permissible value key,
title, or an alias. Mappings prefer STATO, falling back to OBI and
NCIT where STATO has no term.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rchj9PETEATt5FtzG9rMzd
@claude

claude Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Claude encountered an error after 2s —— View job


I'll analyze this and get back to you.

The claude-review job on PR #77 failed at SDK startup (1 turn, 1.7s,
zero cost) because the OAuth token was invalid. No content changes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rchj9PETEATt5FtzG9rMzd
@claude

claude Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Claude finished @cmungall's task in 5m 10s —— View job


Code Review: Statistical tests value set

  • Gather context (diff, CLAUDE.md, repo conventions)
  • Review statistical_tests.yaml
  • Check ontology mapping/validation tooling
  • Check CI status — Build and test passed
  • Post review

Overall this is a well-organized, high-value addition. Structure matches the sibling statistics/prediction_outcomes.yaml exactly (slots block, status: DRAFT, contributors, instantiates: valuesets_meta:ValueSetEnumDefinition), license: MIT matches the repo majority, the import is correctly placed in valuesets.yaml, and there are no enum-name collisions with the other ~150 modules. The annotations: note: fallback on NONE (L822-823) follows the existing convention in data_science/binary_classification.yaml.

The issues below are mostly about mapping verifiability and value-set design, not schema validity.


🔴 Main concern: ~85 STATO CURIEs are unvalidated by the repo's tooling

STATO is not listed in src/valuesets/validators/oak_config.yaml. Per enum_evaluator.py:275-290, only prefixes configured there get strict validation and a persisted cache/<prefix>/terms.csv; everything else falls into the dynamic sqlite:obo:<prefix> branch, which is silently downgraded to a warning on failure (enum_evaluator.py:330-341) and never cached.

The diff corroborates this: it adds 9 OBI and 4 NCIT cache rows but zero STATO rows, and there is no cache/stato/ directory at all — even though STATO supplies ~85 of the ~100 mappings here. So the file's dominant mapping source has no machine-checked evidence in the PR, which is exactly what CLAUDE.md's "ALWAYS check IDs, NEVER guess them" is meant to prevent.

This isn't specific to this PR — medical/neuroimaging.yaml, data_science/binary_classification.yaml, and bio/expression_units.yaml already use STATO under the same gap. Suggested fix, which would both validate this PR and retroactively cover those:

# src/valuesets/validators/oak_config.yaml
  OBI: sqlite:obo:obi
  STATO: sqlite:obo:stato   # <-- add

then re-run just validate and commit the resulting cache/stato/terms.csv as reviewable evidence.

I could not verify the CURIEs myself — this runner has no outbound network and uv run is not permitted, so just validate / OLS lookups both failed. Everything below is from static analysis only; the STATO IDs remain unverified. Fix this →


🟠 Correctness / usability

1. FDR alias collides with a sibling permissible valuestatistical_tests.yaml:767 puts FDR as an alias on BENJAMINI_HOCHBERG, but FALSE_DISCOVERY_RATE (L792, OBI:0200163 "false discovery rate correction method") is its own value in the same enum. Any alias-based lookup for "FDR" silently resolves to BH rather than the generic term. Suggest dropping the bare FDR alias (keep BH) or narrowing it to BH-FDR. Fix this →

2. Aliases attached to the wrong t-test variantL102-104 gives independent samples t-test and unpaired t-test exclusively to TWO_SAMPLE_T_TEST_EQUAL_VARIANCE. Both terms apply equally to Welch's test (TWO_SAMPLE_T_TEST_UNEQUAL_VARIANCE, L105) — in fact Welch's is the default "unpaired t-test" in R and SciPy. As written, someone resolving "unpaired t-test" gets the equal-variance assumption silently baked in. Consider adding the aliases to both, or moving them up to a shared parent value.

3. Correlation tests close-mapped to correlation coefficientsL560-561 and L568-569 attach STATO:0000280 / STATO:0000201 as close_mappings on PEARSON_CORRELATION_TEST / SPEARMAN_CORRELATION_TEST. But this same PR uses those exact IDs as the meaning of CorrelationCoefficientEnum.PEARSON (L840) and .SPEARMAN (L848), i.e. as coefficients (data items), not tests (planned processes). close_mappings asserts near-equivalence across an ontological type boundary; related_mappings would be more defensible.

4. HOLM_BONFERRONI and HOLM_FDR in the same enum — L751 (OBI:0200066, FWER) and L776 (STATO:0000551, "Holm false discovery rate correction"). Holm's procedure controls FWER, not FDR. If STATO:0000551 really carries that label it's STATO's naming, but presenting both to a curator with no note is a genuine foot-gun — worth a description clarifying they are the same underlying step-down procedure, or dropping one.

5. DistributionalAssumptionEnum values point at test classes — the enum describes whether a procedure assumes a parametric form (L887-893), but PARAMETRICNCIT:C53230 "Parametric Test" (L904) and NON_PARAMETRICSTATO:0000198 "non-parametric test" (L908) both denote tests. If a PATO-style quality or an OBI characteristic exists, it would type-check better; otherwise a note annotation explaining the deliberate approximation would help.


🟡 Design: abstraction levels are mixed within enums

StatisticalTestEnum interleaves ~60 concrete tests with grouping/parent classes: TEST_OF_ASSOCIATION_BETWEEN_CATEGORICAL_VARIABLES (L324), GOODNESS_OF_FIT_TEST (L332), HOMOSKEDASTICITY_TEST (L390), HOMOGENEITY_TEST (L396), SPHERICITY_TEST (L402), POST_HOC_ANALYSIS (L440), BETWEEN_GROUP_COMPARISON_TEST (L576), WITHIN_SUBJECT_COMPARISON_TEST (L582), NON_PARAMETRIC_TEST (L588). A curator annotating a paper can legitimately pick either SHAPIRO_WILK_TEST or GOODNESS_OF_FIT_TEST, which makes the resulting data non-comparable. MultipleTestingCorrectionEnum has the same shape — concrete methods (Bonferroni, Holm, BH) alongside method classes (FAMILY_WISE_ERROR_RATE, FALSE_DISCOVERY_RATE, SIMULTANEOUS, SEQUENTIAL).

Options: split the grouping terms into a StatisticalTestCategoryEnum, or keep them and state in the enum description that grouping terms are intentional fallbacks for coarse annotation. Either is fine — the current file just doesn't say which was intended.

Related: ~22 permissible values duplicate a meaning already present in StatisticalTestEnum (all of TTestTypeEnum, NormalityTestEnum, HomoscedasticityTestEnum, PostHocTestEnum). Functionally harmless — from_meaning() is scoped per enum class — but just gen-sssom will emit each CURIE under multiple subjects. Worth a one-line comment noting the redundancy is deliberate.


🔵 Nits

  • Non-ASCII apostrophe, L477 and L721: Dunn’s multiple comparison test uses U+2019. These are the only two non-ASCII characters in the entire src/valuesets/schema/ tree, and the file's own aliases (L483, and Grubbs' test L492, Fisher's exact test L269) use the straight '. Normalize to ' and keep the curly form as an alias if it's the verbatim STATO label. Fix this →
  • Spelling drift within the file: HOMOSKEDASTICITY_TEST (L390, k) vs HomoscedasticityTestEnum (L659, c). Fine if the PV name mirrors the STATO label, but add a comment so it doesn't look like a typo.
  • Ontology-label typos without corrective aliases: Barlett's test (L371) and Cochran-Mantel-Haenzel (L301) correctly carry corrected aliases — but Least significance different test (L469 → "Least significant difference test"), Yate's corrected Chi-Squared test (L256 → "Yates'"), and Scheffe test (L463 → "Scheffé") do not. Adding them would make lookup work for people who spell them correctly.
  • SUPERIORITY description (L928-930) defines superiority as exceeding "a prespecified threshold of meaningful benefit" — that's superiority-by-margin. Conventional superiority testing is just difference ≠ 0. If this is STATO's verbatim definition, fine; otherwise worth softening.

⚪ Scope / process

  • Unrelated cache churn: cache/pato/terms.csv (+98) and cache/so/terms.csv (+13) contain nothing statistical — they're colors, shapes, viability, and protein secondary-structure terms picked up by running just validate across the whole schema dir. Harmless, but it triples the reviewable diff and obscures which terms this PR actually validated. Consider reverting those two files here and landing them separately.
  • generated_slots.yaml not updated — the 10 new slots (statistical_test, t_test_type, …) aren't in it. That's a derived artifact handled by regen-derived.yml, so probably fine to leave; just confirm that workflow runs post-merge.
  • Test coverage: no test exercises the new enums, but tests/data/valid/ is empty repo-wide and tests/test_rich_enums.py only covers a couple of representative enums — so this matches the status quo rather than regressing it. Build and test passing confirms the schema compiles and generates cleanly.
  • Security / performance: nothing applicable — this is declarative schema with no executable code. The added enums are ~100 values, negligible for generated-Pydantic size.

Bottom line: structurally sound and CI-green; I'd want item 🔴 (STATO added to oak_config.yaml + just validate re-run with cache/stato/terms.csv committed) resolved before merge, since it's the difference between "mappings are checked" and "mappings look plausible." Items 1-3 are small concrete fixes; the abstraction-level question is a judgement call for you.
· Branch

Main change: register STATO in src/valuesets/validators/oak_config.yaml so
the ~83 STATO CURIEs in statistical_tests.yaml are strictly validated and
cached rather than silently skipped. cache/stato/terms.csv is the resulting
machine-checked evidence. This also retroactively covers the pre-existing
STATO mappings in bio/expression_units.yaml, data_science/binary_classification.yaml
and medical/neuroimaging.yaml; the latter two already validate clean, and the
two label mismatches it surfaced in expression_units.yaml (FPKM/RPKM) are
fixed here by adding STATO's verbatim labels as aliases. Net effect on
expression_units.yaml is 14 -> 12 errors; the remainder are pre-existing
UO/NCIT mismatches unrelated to this branch.

Other review fixes in statistical_tests.yaml:
- BENJAMINI_HOCHBERG alias FDR -> BH-FDR, which collided with the sibling
  FALSE_DISCOVERY_RATE permissible value
- Pearson/Spearman correlation tests: close_mappings -> related_mappings,
  since STATO:0000280 / STATO:0000201 denote coefficients (data items) while
  the permissible values denote tests (planned processes)
- HOLM_FDR: note that Holm's step-down procedure controls FWER, not FDR, and
  that the label is STATO's own
- Two-sample t-tests: note that "unpaired"/"independent samples" are ambiguous
  and that R and SciPy default to the Welch variant
- DistributionalAssumptionEnum: note the deliberate approximation of using
  test classes for what is really a property of a procedure
- StatisticalTestEnum / MultipleTestingCorrectionEnum: state that grouping
  classes are intentional coarse-annotation fallbacks, and that meanings
  repeated in the narrower enums are deliberate
- Corrective aliases for Scheffe test and Least significance different test
- Comment explaining the k/c spelling split on homoskedasticity

Reverted the unrelated cache/pato and cache/so churn picked up by running the
validator over the whole schema directory; cache changes are now limited to
ncit, obi and stato terms this branch actually uses.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rchj9PETEATt5FtzG9rMzd
@claude

claude Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Claude finished @cmungall's task in 2m 42s —— View job


Re-review after a07d416

  • Gather context (new commit, diff vs origin/main)
  • Verify STATO validation is now wired up
  • Re-check previously raised items 1–5 and nits
  • Check CI status
  • Post review

✅ The blocking item is resolved

STATO: sqlite:obo:stato is now in src/valuesets/validators/oak_config.yaml:16, and cache/stato/terms.csv (87 terms) is committed. I mechanically cross-checked it: every one of the 84 distinct STATO: CURIEs used as a meaning: in statistical_tests.yaml is present in the cache, and the cached labels match the title: fields (spot-checked ~20, including the awkward ones — Yate's corrected Chi-Squared test, Barlett's test, Cochran-Mantel-Haenzel test for repeated tests of independence, Least significance different test). That's real machine-checked evidence, which is what was missing before. The retroactive coverage of bio/expression_units.yaml (FPKM/RPKM label aliases) is a nice bonus, and the unrelated cache/pato / cache/so churn is reverted.

Items 1–5 and the nits from the last pass are all addressed — the alias collision, the close_mappingsrelated_mappings retype for the correlation coefficients, the HOLM_FDR / FWER note, the Welch-default note on both two-sample variants, the DistributionalAssumptionEnum type-approximation note, the abstraction-level statements on both enums, and the Scheffé / Least significant difference / Yates' / Cochran-Mantel-Haenszel corrective aliases.

One correction to my own last review: the non-ASCII nit was wrong and should not be acted on. STATO:0000490's own label is Dunn’s multiple comparison test with U+2019 (cache/stato/terms.csv:57) — normalizing the title to a straight quote would introduce a title/label mismatch. And the schema tree is not otherwise pure ASCII: geography/geographic_codes.yaml (°), bioprocessing/scale_up.yaml (μ), medical/clinical.yaml () all contain non-ASCII. Leave both lines as they are.


🟠 One new finding: close_mappings are not validated by anything

enum_evaluator.py:429-441 reads pv.meaning and nothing else — close_mappings / related_mappings / exact_mappings never appear in the file. So the 9 distinct NCIT CURIEs used as close_mappings in this PR are unchecked, and I confirmed none of them is in cache/ncit/terms.csv:

CURIE line asserted as
NCIT:C53240 99 ONE_SAMPLE_T_TEST
NCIT:C53232 107 PAIRED_T_TEST
NCIT:C53247 227 MANN_WHITNEY_U_TEST
NCIT:C53246 235 WILCOXON_SIGNED_RANK_TEST
NCIT:C53248 245 KRUSKAL_WALLIS_TEST
NCIT:C53235 267 CHI_SQUARE_TEST
NCIT:C45725 300 FISHERS_EXACT_TEST
NCIT:C53250 376 SHAPIRO_WILK_TEST
NCIT:C53229 626, 965 NON_PARAMETRIC_TEST

The 4 NCIT CURIEs added to the cache this PR (C53244, C53249, C61594, C53230) are exactly the ones used as meaning:, which confirms the split. This is a repo-wide tooling gap rather than something this PR introduced — but since ~10% of this file's mappings live in close_mappings, it's worth either spot-checking those 9 by hand before merge or filing an issue to extend the evaluator. File the tooling gap →

⚪ Process notes (no action needed for this PR)

  • just validate is not in CI. main.yaml:55 runs just test, which is _test-schema (gen-project) + pytest + examples (justfile:88,192). The ontology validation recipe lives in project.justfile:81 and is never invoked by a workflow, so cache/stato/terms.csv is a point-in-time artifact — nothing will catch drift if a STATO label changes. Not a blocker, just worth knowing that the cache's value depends on someone re-running the validator manually.
  • CI is still in progress for a07d416 (Build and test run 30714232947). The previous commit passed, and the new commit only adds comments, notes, aliases and one close_mappingsrelated_mappings rename, so I'd be surprised by a failure — but it isn't green yet as I write this.

Bottom line: the blocking concern from my last pass is properly resolved with verifiable evidence, and the follow-ups are all in. From my side this is ready to merge once Build and test goes green; the unvalidated close_mappings are a pre-existing tooling gap you may prefer to handle separately.
· Branch

cmungall commented Aug 1, 2026

Copy link
Copy Markdown
Member Author

Addressed in a07d416. Thanks — the 🔴 item was the right call and is now fixed properly. Two of the nits don't hold up, details below.

🔴 STATO validation — done

Added STATO: sqlite:obo:stato to oak_config.yaml. statistical_tests.yaml validates clean under strict mode, and cache/stato/terms.csv (83 terms) is committed as the machine-checked evidence.

Worth recording what this turned up repo-wide, since it wasn't what either of us predicted. I had held off on this change because I expected it to surface ~4 new label mismatches on the pre-existing STATO mappings. It surfaced exactly 2, both in expression_units.yaml:

ExpressionUnitEnum.FPKM: expected one of {'FPKM', 'Fragments per kilobase...'},
  got 'FPKM-fragments per kilobase of transcript per million fragments mapped'
ExpressionUnitEnum.RPKM: ... got 'RPKM-reads per kilobase of transcript per million fragments mapped'

Both CURIEs were correct; only the labels were unmatched. Fixed by adding STATO's verbatim labels as aliases. binary_classification.yaml and neuroimaging.yaml already validated clean. Net effect on expression_units.yaml is 14 → 12 errors — the remaining 12 are pre-existing UO/NCIT mismatches (minute/hour/mg per mL etc.) unrelated to this branch.

Note this means those 2 errors were already being reported before my config change — the dynamic sqlite:obo:stato path does label-check once stato.db is present. The config entry buys strictness and the committed cache, not the check itself.

🟠 Fixed

  1. FDR aliasBH-FDR. Agreed, real collision with FALSE_DISCOVERY_RATE.
  2. Correlation close_mappingsrelated_mappings on Pearson/Spearman, with a comment on the coefficient-vs-test type boundary. Good catch.
  3. HOLM_FDR — added a description noting Holm controls FWER, not FDR, that the wording is STATO's own label, and pointing to HOLM_BONFERRONI.
  4. DistributionalAssumptionEnum — added a note on the deliberate approximation. I checked; there's no PATO quality or OBI characteristic for "parametric", so the test classes stay as the closest referent.

2. t-test aliases — addressed, but not by adding the aliases to both. Doing that would recreate exactly the collision from item 1, one enum over. Instead both variants carry a note: the equal-variance one flags that "unpaired"/"independent samples" are ambiguous, and the Welch one records that it's R's and SciPy's default, so an unqualified "unpaired t-test" often means Welch.

🟡 Abstraction levels

Kept the grouping terms and documented the intent in both enum descriptions — they're deliberate fallbacks for sources that report only "a test of normality was applied", with instructions to prefer the most specific value. Also noted that meanings repeated in the narrower range-constraining enums are intentional.

🔵 Nits — two are incorrect

Non-ASCII apostrophe — not changing this, and the premise is wrong. The claim that these are "the only two non-ASCII characters in the entire src/valuesets/schema/ tree" doesn't survive checking:

$ grep -rPo '[^\x00-\x7F]' src/valuesets/schema/ | wc -l
898        # across 24 files

Ångström, μm, °C, β, Ψ, and en-dashes inside aliases used for label matching (liquid–liquid extraction, Karl–Fischer titration). U+2019 specifically appears twice, but the tree is nowhere near pure ASCII.

More to the point, Dunn’s multiple comparison test is STATO's verbatim label for STATO:0000490 — confirmed against OLS. title has to keep the curly form or strict validation fails, which is precisely the check this PR just enabled. The ASCII form is already present as an alias on both DUNNS_TEST and DUNN, so the suggested end state was already in place.

Yate's already has the corrective aliasYates' chi-squared test is on the value at L262. The other two were genuinely missing: added Scheffé test (both enums) and Least significant difference test.

SUPERIORITY — verbatim STATO. STATO:0000718: "…to determine that the absolute value of any difference in effects is larger than a prespecified value representing a meaningful difference." Leaving as-is.

Spelling drift — added a comment explaining the k matches STATO's label while the enum name uses the commoner c.

⚪ Scope

Reverted cache/pato (+98) and cache/so (+13). Cache changes are now only ncit (+4), obi (+9), and the new stato (83) — all terms this branch actually uses.

generated_slots.yaml: confirmed regen-derived.yaml triggers on push to main for src/valuesets/schema/**, so it regenerates post-merge.

Local: just test 63 passed / 1 skipped, just gen-project clean, and all 127 CURIEs re-verified against OLS after the edits (every meaning: label still matches its key, title, or an alias).


Generated by Claude Code

cmungall commented Aug 1, 2026

Copy link
Copy Markdown
Member Author

CI is green on a07d416 — all five checks pass (test on 3.10/3.11/3.12/3.13, plus claude-review).

🟠 close_mappings — spot-checked, all correct

Took the suggestion to hand-check these rather than defer them. The tooling-gap observation is right: enum_evaluator only reads pv.meaning, so nothing in the repo validates these. I resolved all 12 non-meaning: mappings against OLS, pairing each CURIE with its actual owning permissible value:

CURIE predicate owning PV resolved label
NCIT:C53240 close ONE_SAMPLE_T_TEST One Sample t-Test
NCIT:C53232 close PAIRED_T_TEST Paired t-Test
NCIT:C53247 close MANN_WHITNEY_U_TEST Mann-Whitney Test
NCIT:C53246 close WILCOXON_SIGNED_RANK_TEST Wilcoxon Signed Rank Test
NCIT:C53248 close KRUSKAL_WALLIS_TEST Kruskal-Wallis Test
NCIT:C53235 close CHI_SQUARE_TEST Chi-Square Test
NCIT:C45725 close FISHERS_EXACT_TEST Fisher's Exact Test
NCIT:C53250 close KOLMOGOROV_SMIRNOV_TEST Komogorov-Smirnov Test
NCIT:C53229 close NON_PARAMETRIC_TEST Non-Parametric Test
NCIT:C53229 close NON_PARAMETRIC Non-Parametric Test
STATO:0000280 related PEARSON_CORRELATION_TEST Pearson's correlation coefficient
STATO:0000201 related SPEARMAN_CORRELATION_TEST Spearman's rank correlation coefficient

All 12 resolve and all denote the intended concept. No changes needed.

One correction to the table in the re-review: NCIT:C53250 is attributed to SHAPIRO_WILK_TEST, but it sits on KOLMOGOROV_SMIRNOV_TEST (L369; L376 is the CURIE line inside that value). That distinction matters here — NCIT has no Shapiro-Wilk term at all, so had it actually been on SHAPIRO_WILK_TEST it would have been a genuine wrong-term mapping rather than a correct one. SHAPIRO_WILK_TEST carries only meaning: STATO:0000077, no close_mapping. Worth flagging since the whole point of the check was catching exactly that failure mode.

(NCIT's own label misspells it as "Komogorov" — that's upstream, and it doesn't affect us since close_mappings aren't label-matched.)

Two other small numbers in the re-review: cache/stato/terms.csv holds 83 terms (88 lines — 1 header, and 4 labels contain embedded newlines from STATO definitions), matching the 83 distinct STATO CURIEs used as meaning: in the file, not 87/84.

⚪ On just validate not being in CI

Confirmed and worth acting on separately — main.yaml runs just test, and the ontology validation recipe in project.justfile:81 is never invoked by any workflow. So the cache is point-in-time and label drift wouldn't be caught. Wiring just validate into CI isn't free right now: main currently has 138 pre-existing errors across other modules (UO unit labels, NCIT mismatches), so the job would need to start from a baseline-allowlist rather than a clean zero. That plus extending the evaluator to cover close_mappings/related_mappings is a reasonable follow-up issue — out of scope for this PR, and @cmungall's call whether to file it.


Generated by Claude Code

cmungall commented Aug 1, 2026

Copy link
Copy Markdown
Member Author

Correcting my own previous comment: the cache/stato/terms.csv line-count claim was wrong.

I said the file holds 83 terms and attributed the 88 lines to embedded newlines in STATO definitions. That was wrong on both counts — I inferred it from wc -l instead of parsing. Parsed properly:

cache data rows: 87
labels containing newlines: 0

87 is correct — the re-review's number, not mine. The four entries beyond this file's 83 are the pre-existing STATO mappings elsewhere, picked up when I ran the validator against those files to check the oak_config.yaml change:

CURIE source file
STATO:0000172, STATO:0000206 bio/expression_units.yaml
STATO:0000036 data_science/binary_classification.yaml
STATO:0000046 medical/neuroimaging.yaml

So the cache is 83 + 4, and every STATO CURIE in the repo is now cached — which is the better outcome anyway, since it's what makes the retroactive coverage real rather than notional.

The one number that is off the other way: distinct STATO CURIEs used as meaning: in statistical_tests.yaml is 83, not 84. (There are 85 STATO references in the file total, but STATO:0000280 and STATO:0000201 are related_mappings, not meanings.)

Nothing in the diff changes as a result — this is a correction to my description of the artifact, not to the artifact.


Generated by Claude Code

@cmungall
cmungall merged commit 86eab01 into main Aug 1, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants