Correct combined and dynamic pileup count slots - #656
Open
SuhasSrinivasan wants to merge 7 commits into
Open
Conversation
SuhasSrinivasan
marked this pull request as ready for review
August 6, 2026 06:59
This was referenced Aug 6, 2026
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.
Fixes #655.
Summary
Severity
Severity: High — scientific correctness
Rationale: The affected commands can exit successfully while omitting passing modification classes, losing selected bases, splitting one requested category into contradictory rows, or undercounting failure and ancillary categories. These errors change reported coverage and modification percentages.
Root cause
The related failures arise from five narrow assumptions in the combined/dynamic count path:
mandhas modified and assigns the filtered-C counter to itself.--modified-basesvalues reach preset and writer construction as separate categories.Implementation
N_failwith saturation.(canonical base, modification code), and use explicit canonical/other-mod offsets instead of enum arithmetic.dynamic_anchor_rposhelper for all dynamic call categories and max-depth lookup.(canonical base, modification code)selection before preset and writer construction, warning for ignored duplicates while preserving the same raw code on different canonical bases.The seven commits keep each root cause and its regression independently reviewable.
Preserved behavior
A:mandC:mremain distinct even though they share a raw modification code.Non-goals
Behavior before and after
m+h+f+ ChEBI 19228 + one filtered callN_valid=3,N_mod=2,N_canonical=1,N_fail=0N_valid=5,N_mod=4,N_canonical=1,N_fail=1--combine-mods, normal versus high-depthA:m C:mon one modified and one canonical ACT read(base, code), each with coverage 2GATC 1 --combine-strandsancillary categoriesC:m C:min dynamic/high-depth modeC:mTesting
Test environment
b060d18d35adc761f318e34353ce0b7f9bf00adb72c6ee8d08e6212dd1983c03d8a437772d9b4678; clean5cecc3fb3a9336068d9e3c68d5c08d678153dd2cCargo.lockSHA-25649c08c4c51b6f4320726551146d971fa9ef2183d40c3f6c631b2005965e242c0; one resolvedhts-sys 2.2.0; the lockfile is not in this diff3/2/1/0instead of5/4/1/1; empty C high-depth output; split same-code C rows; omitted reverse ancillary categories; duplicate dynamic/high-depth rows; and the debug overlap paniccargo test -p mod_kit pileup::pileup_processor::tests -- --test-threads=1cargo test -p modkit --test test_pileup -- --test-threads=1cargo test --workspace --all-targets -- --test-threads=1in an isolated worktree/targetmodkitversustarget/debug/modkit8647e2cda884d195ec63dcb0939050d11f0f25353f05f2c713db6b8b870897c5to86bfdef58f08f83ccaae3e462afa2d7281a7f46de6f9f22156f86425056b4dd8; C high-depth corrected from empty SHA-256e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855to normal-output SHA-2569e7c314f6914d756c77fb5a179394649427252c12a75656418a3574ba09592a8; reverse ancillary output corrected frome924d95e2dcc26dc2baca6e212c2eceb68df515e148c21570d296bc257c870f4to502c15d03c4b58806ae716cb33213eeddd8bffa050f0dbc2053e2381dd50ac86A:m C:m; forward and reverse strands; phased ancillary unit partitions; non-CpGGATC 1; CpG overlaprustfmt --edition 2021 --check modkit-core/src/pileup/pileup_processor.rs modkit-core/src/pileup/subcommand.rs modkit/tests/test_pileup.rs;git diff --check upstream/master...HEAD; clean-worktree checkTests not performed
cargo clippywas not run.cargo fmt --all -- --checkreports unrelated pre-existing formatting drift inmodkit/tests/test_bedmethyl_util.rs,modkit-core/src/adjust.rs, andmodkit-core/src/entropy/mod.rs; all three changed files pass directrustfmt --check.Scientific validation
N_failonce and remain outside valid coverage.Output and compatibility
Reviewer guide
modkit-core/src/pileup/pileup_processor.rsand their exact conservation oracles.dynamic_anchor_rposcall sites in the same file.modkit-core/src/pileup/subcommand.rsand the five new CLI regressions inmodkit/tests/test_pileup.rs.cargo test -p mod_kit pileup::pileup_processor::tests -- --test-threads=1andcargo test -p modkit --test test_pileup test_pileup_explicit_same_code_slots_are_keyed_by_base -- --exact.Checklist