Skip to content

Guard _mirrored_baf against all-NaN median to fix 3.11-min CI (gh#407)#1080

Merged
etal merged 1 commit into
masterfrom
fix-mirrored-baf-allnan-median
May 24, 2026
Merged

Guard _mirrored_baf against all-NaN median to fix 3.11-min CI (gh#407)#1080
etal merged 1 commit into
masterfrom
fix-mirrored-baf-allnan-median

Conversation

@etal
Copy link
Copy Markdown
Owner

@etal etal commented May 24, 2026

Summary

master is currently red on the 3.11-min CI job (e.g. the merge of #1077, run 26365341592), and every PR branched off master inherits the failure (#1078, #1079). This fixes the root cause.

Root cause

PR #407 keeps alt_freq as NaN when a VCF lacks allele counts. A bin whose heterozygous SNPs all lack frequencies then hands _mirrored_baf an all-NaN slice, where it calls:

above_half = vals.median() > 0.5   # cnvlib/vary.py

Under the min-pinned (older) numpy, pd.Series.median() on an all-NaN slice routes through np.nanmediannp.nanmean of an empty slice, which emits RuntimeWarning: "Mean of empty slice". Because pyproject.toml sets filterwarnings = ["error"], that warning becomes a test failure. Newer numpy (the regular jobs) doesn't warn, so only 3.11-min fails.

#407 added an all-NaN guard in the outer summarize() (protecting summary_func), but the inner median() in _mirrored_baf runs first and was left unguarded.

Affected tests (both via baf_by_ranges → summarize → _mirrored_baf):

  • test/test_commands.py::CallTests::test_call_filter
  • test/test_io.py::IOTests::test_read_vcf_het_no_alt_count

Fix

Short-circuit _mirrored_baf for an all-NaN slice before calling .median(); the mirrored result is all-NaN regardless of mirroring direction:

if vals.isna().all():
    return shift   # all-NaN
above_half = vals.median() > 0.5

Tests

  • New VATests::test_mirrored_baf_all_nan (test/test_cnvlib.py): under warnings.simplefilter("error"), asserts an all-NaN input mirrors to all-NaN without warning, and that a partially-NaN slice still mirrors correctly (median taken over the real values).
  • Locally (numpy 2.4.3) test_cnvlib.py + test_io.py + test_commands.py = 119 passed; mypy and ruff clean. The warning is numpy-version-dependent, so the warnings-as-error assertion is the guard that bites in the 3.11-min environment.

Clinical-impact note

Behavior is unchanged for VCFs that do carry allele counts (the median() path is untouched there). For the no-allele-count case the BAF was already meant to be NaN (#407); this only stops a spurious warning/crash. No change to .cnr/.cns/.cnn/SEG/VCF numeric output.

Refs #407.

🤖 Generated with Claude Code

PR #407 keeps alt_freq NaN when a VCF lacks allele counts, so a bin whose
het SNPs all lack frequencies hands _mirrored_baf an all-NaN slice. It
then calls vals.median(), which under older (min-pinned) numpy warns
"Mean of empty slice"; with pytest's filterwarnings=["error"] that warning
becomes a failure -- breaking test_call_filter and
test_read_vcf_het_no_alt_count in the 3.11-min job only (newer numpy
doesn't warn). #407 guarded the outer summarize() but missed this inner
median.

Short-circuit _mirrored_baf for an all-NaN slice before calling median;
the mirrored result is all-NaN regardless of direction. Add a unit test
(VATests.test_mirrored_baf_all_nan) asserting no warning under
warnings-as-error plus correct mirroring of a partially-NaN slice.

No change to numeric output for VCFs that do have allele counts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@codecov
Copy link
Copy Markdown

codecov Bot commented May 24, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 67.81%. Comparing base (c479179) to head (9162f9e).

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #1080   +/-   ##
=======================================
  Coverage   67.80%   67.81%           
=======================================
  Files          74       74           
  Lines        7684     7686    +2     
  Branches     1365     1366    +1     
=======================================
+ Hits         5210     5212    +2     
  Misses       2034     2034           
  Partials      440      440           
Flag Coverage Δ
unittests 67.81% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@etal etal merged commit 86bf4da into master May 24, 2026
13 checks passed
@etal etal deleted the fix-mirrored-baf-allnan-median branch May 24, 2026 16:34
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