Skip to content

Disable --pairguide auto and validate extraction windows up front - #33

Merged
davidliwei merged 1 commit into
mainfrom
fix/drop-pairguide-auto
Aug 22, 2026
Merged

Disable --pairguide auto and validate extraction windows up front#33
davidliwei merged 1 commit into
mainfrom
fix/drop-pairguide-auto

Conversation

@davidliwei

Copy link
Copy Markdown
Owner

Disables --pairguide auto, which has never produced a correct result, and closes the silent-failure paths that removing it exposes.

Why auto goes

It reused mageckcount_search_variable_region, which walks read columns and stops at the first one whose most common base exceeds 60%. That finds a UMI — a uniformly random run. A second guide is drawn from a fixed library, whose per-column base composition is lumpy by construction, so the search is structurally wrong for guides: no threshold makes a library column look uniform.

Measured before this change, with explicit windows as the control:

Layout auto explicit --pg-start*
R1 = guide1+guide2, 8-guide library window 0-4, 0 rows 8 rows
R1 = guide1+constant, R2 = guide2 window 0-4, 0 rows 8 rows
same, 200-guide library window 0--1, 0 rows 200 rows
R2 = guide2, nothing after guide1 on R1 uncaught ValueError 4 rows

Each failure exited 0 with a header-only pg_count.txt — the confusion reported in #15. Any pipeline pinned to auto today is already producing empty output, so rejecting the choice turns a silent wrong answer into a loud one. #32 tracks reimplementing it on mageckcount_trim5_auto, which already locates guide 1 by counting library matches and exits non-zero when almost nothing matches.

The path it leaves behind was also unguarded

An explicit window is now the only option, so omitting one has to fail cleanly. It did not:

--pairguide secondpair, no --pg-start-2/--pg-end-2   before: rc=0, 0 rows, one ERROR per read
                                                      after: rc=255, one ERROR naming both options

The check lived inside the per-read loop — one log line per read on a real FASTQ — and then sliced an empty string and finished successfully. It now runs once in mageckcount_check_extraction_window, before any FASTQ is opened, and covers --umi too, which shares the code path and the bug.

Also fixed in the shared search, still used by --umi auto

  • A failed search was accepted as success. The second-read result was taken when either bound was set (>= 0 or >= 0; the first-read test at the line above correctly uses and). The failure value (0, -1) then sliced each read as [0:-1] — the whole read but its last base — so every read yielded a distinct "UMI". A run with an 8bp UMI on read 1 filled umi_count.txt with 2,000 rows built from unrelated read-2 sequence. This is the worst of the group: nothing about the output looks wrong.
  • max() over an empty column table raised an uncaught ValueError when nothing follows the guide on read 1 — the normal layout for --pairguide secondpair.
  • An unreachable --pairguide branch in mageckcount_processonefile: args.umi is assigned from args.pairguide before it runs, so the preceding test always won. Had it run, it set args.umi='none' and disabled pair extraction entirely — its being dead is the only reason auto got as far as it did.

Tests

Six new, each written failing first. 38 pass total.

test_pairguide_auto_is_rejected · test_pairguide_secondpair_requires_its_window · test_pairguide_firstpair_requires_its_window · test_umi_secondpair_requires_its_window · test_umi_auto_fails_loudly_when_no_variable_region_is_found · test_umi_auto_reports_reads_with_nothing_after_the_guide

The window tests assert the error appears once, not once per read.

Not covered here

--umi auto still fails to find a UMI that runs to the end of the sequence: var_end is never assigned in that case and the search returns (start, -1). This PR makes that fail loudly instead of silently; actually finding the region is filed separately. The remaining --pairguide test coverage and the ctab_umi[None] accumulation stay in #29.

Refs #29, #32.

--pairguide auto reused the UMI variable-region search, which walks read
columns and stops at the first one whose most common base exceeds 60%. That
finds a uniformly random UMI; a second guide comes from a fixed library whose
per-column composition is lumpy, so the window came back truncated (0-4) or
never closed (0--1). Every layout tested produced a header-only pg_count.txt
with exit 0 -- the silent failure reported in #15. Remove the choice rather
than keep a mode that cannot succeed; #32 tracks reimplementing it on
mageckcount_trim5_auto, which already locates guide 1 by library matching.

That makes an explicit window the only path, and the path was unguarded: the
window was checked inside the per-read loop, logging one error per read on a
real FASTQ, then slicing an empty string and exiting 0 anyway. Check it once,
before any FASTQ is opened, for --pairguide and --umi alike.

Also on the shared search, which --umi auto still uses:

- a second-read search that set only one bound was accepted as success, so the
  failure value (0, -1) sliced every read as [0:-1] and each one yielded a
  distinct "UMI". umi_count.txt filled with plausible rows built from unrelated
  sequence -- the worst of these failures, since nothing looks wrong.
- max() over an empty column table raised an uncaught ValueError when nothing
  followed the guide on read 1.
- the --pairguide branch in mageckcount_processonefile was unreachable, since
  args.umi is assigned from args.pairguide before it runs. Had it run it set
  args.umi='none', disabling pair extraction outright.

Refs #29, #32.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@davidliwei

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. You're on a roll.

Reviewed commit: 7e21c73eb2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@davidliwei
davidliwei merged commit ac5a530 into main Aug 22, 2026
6 checks passed
@davidliwei
davidliwei deleted the fix/drop-pairguide-auto branch August 22, 2026 04:31
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.

1 participant