Skip to content

fix: error on unequal-length sequences in calc_seq_pwm / extract_pwm - #39

Merged
aviezerl merged 1 commit into
masterfrom
fix/calc-seq-pwm-unequal-lengths
Jul 20, 2026
Merged

fix: error on unequal-length sequences in calc_seq_pwm / extract_pwm#39
aviezerl merged 1 commit into
masterfrom
fix/calc-seq-pwm-unequal-lengths

Conversation

@aviezerl

Copy link
Copy Markdown
Contributor

Problem

Follow-up to the compute_pwm variable-length fix (#38). Auditing the rest of the PWM family for the same class of bug turned up a second one in the MotifDB scoring path.

calc_seq_pwm() (and extract_pwm(), which wraps it) build a single rectangular one-hot matrix via do.call(rbind, ...) in seqs_to_onehot. With sequences of different lengths, rbind recycles the shorter rows up to the longest length, so the shorter sequences get wrong, batch-dependent scores - and it surfaces only as an easy-to-miss rbind warning ("number of columns of result is not a multiple of vector length"), not an error:

# shorter sequence scored in a batch with a longer one vs. alone
SHORT seq in batch: -11.16   |   alone: -14.59   ->  wrong

Fix

These functions are inherently equal-length (one rectangular matrix multiply against all motifs), and compute_pwm() already handles variable lengths correctly. So fail loudly instead of returning garbage:

if (length(unique(nchar(sequences))) > 1) {
    cli_abort("All sequences must have the same length for extract_pwm(). For sequences of different lengths, use compute_pwm().")
}

Mirrors the existing guard in compute_local_pwm() (which already errors when return_list = FALSE and lengths differ).

Not changed

compute_pwm (fixed in #38), compute_local_pwm, screen_local_pwm, mask_sequences_by_pwm, and gextract.local_pwm were all verified to be batch-independent on variable-length input. The misha package was also audited and is immune to this bug class (its scan range is always a per-PSSM constant clamped to each target's own length).

Test

Added a test asserting calc_seq_pwm errors on unequal lengths and still works on equal lengths.

https://claude.ai/code/session_01PK3qefBGDoBwd9w5226FEq

calc_seq_pwm() (and extract_pwm(), which wraps it) built a single
rectangular one-hot matrix via do.call(rbind, ...). With sequences of
different lengths rbind recycled the shorter rows up to the longest
length, so the shorter sequences got wrong, batch-dependent scores -
surfaced only as an easy-to-miss rbind warning.

Fail loudly with a clear message pointing to compute_pwm() (which handles
variable lengths correctly) instead of returning garbage.

Claude-Session: https://claude.ai/code/session_01PK3qefBGDoBwd9w5226FEq
@aviezerl
aviezerl merged commit 3072a8e into master Jul 20, 2026
6 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.

1 participant