fix(str): take the marker range from the majority value shape - #25
Merged
Conversation
DYS413 was reported as `23 / 23 / 23` with 25 distinct observed values — a contradiction on the face of the report. The marker has 866 copy-vector calls (23-23, 21-23, …) and exactly one bare `23` from a kit that collapsed the pair. The range picked whichever shape was non-null, with the scalar winning, so that single observation replaced the entire copy-vector range: the page presented one sample's value as the corpus range for 867 observations. The mirror case was equally broken — a mostly-simple marker with one stray vector would have shown a one-sample vector range. The range now comes from whichever shape the majority of observations use, and the other shape's statistics are nulled out so a row can no longer carry both. DYS413 reads 14-24 / 23-23 / 25-25, all real observations. The minority count is kept rather than silently dropped, and shown in the report's notes cell — the same reasoning as null_alleles and complex_count, and it explains why `distinct` can exceed what the displayed range accounts for. Fixed in the aggregation rather than the template so the JSON API is correct too. Regression test covers both directions. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Reported from the live report: DYS413 showed as multi-copy but with a single reported value.
min = modal = max = 23alongside 25 distinct values is self-contradictory.Cause
DYS413 has 866 copy-vector calls (
23-23,21-23,23-25, …) and exactly one bare23— a kit that collapsed the pair into a single count. The range picked whichever shape was non-null, with the scalar winning ties:So one observation out of 867 replaced the entire copy-vector range, and the page presented a single sample's value as the corpus range. The mirror case was equally broken: a mostly-simple marker with one stray vector would have shown a one-sample vector range.
Fix
The range now comes from whichever shape the majority of observations use, and the other shape's statistics are nulled out, so a row can no longer carry both. DYS413 now reads:
14-2423-2325-25All three are real observations (
14-24×1,23-23×545,25-25×1), and23-23is the genuine mode.The minority observation is counted rather than silently dropped, and surfaced in the notes cell — same reasoning as
null_allelesandcomplex_count, and it explains whydistinctcan exceed what the displayed range accounts for.Fixed in the aggregation rather than the template, so
/api/v1/reports/str-markersis correct too — it had the same bug.Notes
mixed_shape_count. Existing rows keep the old values until the nextdu-jobs run-once str-marker-stats, which the deploy should run anyway.Verification
cargo clippy --workspace --locked -- -D warningsclean🤖 Generated with Claude Code