Skip to content

bdgdiff: do not truncate region scores to integers (fixes #715) - #739

Merged
taoliu merged 1 commit into
macs3-project:mainfrom
cindykrafft:fix/issue-715-bdgdiff-score-truncation
Sep 18, 2026
Merged

taoliu merged 1 commit into
macs3-project:mainfrom
cindykrafft:fix/issue-715-bdgdiff-score-truncation

Conversation

@cindykrafft

Copy link
Copy Markdown

Fixes #715.

Describe the bug

macs3 bdgdiff writes, as the score of every region in the cond1, cond2 and common BED files, the length-weighted mean of the log10 likelihood ratios of the intervals inside the region (as documented). Since the pure-Python-mode conversion, TwoConditionScores.mean_from_peakcontent in MACS3/Signal/ScoreTrack.py declares the per-interval score tmp_v and the accumulator sum_v as cython.long, so each log10LR is cut to its integer part before it is summed. In MACS2 2.2.9.1 and MACS3 3.0.0 both were float64_t ("for better precision"); 3.0.1 through current main have cython.long.

Consequences, exactly as reported in #715: with a cutoff below 1 (the reporter used -C 0.2) every score in common.bed becomes 0, and cond1/cond2 scores can be below the cutoff; with the default -C 3 every score is biased low by up to 1 (e.g. 24.9521 instead of 25.5431).

To Reproduce

Four one-interval-per-region bedGraphs where the cond1 intervals have log10LR(t1 vs t2) = 0.3271 and 6.1784 (see repro.py in the link below):

macs3 bdgdiff --t1 t1.bdg --c1 c1.bdg --t2 t2.bdg --c2 c2.bdg --d1 1 --d2 1 -C 0.2 -l 200 -g 100 --o-prefix syn

main: syn_c0.2_cond1.bed score 3.0 (= (0 + 6) / 2). Fixed: 3.25276 (= (0.3271 + 6.1784) / 2).

The project's own test/cmdlinetest step 10 (bdgdiff on the CTCF chr22 50k test data) shows the same: on main, 638 of 638 cond1 scores differ from test/standard_results_bdgdiff/run_bdgdiff_prefix_c3.0_cond1.bed (first three: 24.9521 / 36.903 / 48.8178 vs 25.5431 / 37.3104 / 49.3307). The reference files were evidently produced by a float-correct build; cmdlinetest does not catch this because BED files that differ are accepted when their Jaccard index is > 0.99, which ignores the score column.

The fix

Declare tmp_v and sum_v as cython.double again (two lines). With the fix, the bdgdiff output on the test data matches test/standard_results_bdgdiff exactly (0 of 638 scores differ), so no reference file needs regenerating.

Tests

  • test/test_ScoreTrack.py::Test_TwoConditionScores::test_call_peaks_score_is_mean_logLR (new): fails on main with AssertionError: 3.0 != 3.2527 within 3 places, passes with the fix.
  • The Test_TwoConditionScores.setUp fixture called bedGraphTrackI.safe_add_loc, which no longer exists; it now uses add_loc so the class can hold tests again.
  • pytest test/test_ScoreTrack.py test/test_BedGraph.py test/test_PeakIO.py: 8 passed before, 9 passed after.
  • Full pytest --runxfail (excluding test_online.py, which needs network): 102 passed, 4 skipped on main; same plus the new test with the fix.
  • ruff check / flake8 report no findings on the changed lines (the files' pre-existing findings are unchanged).

Found while working through open issues in Mytochondria, a volunteer project that verifies fixes for the software behind published results (methods and harnesses: https://github.com/cindykrafft/mytochondria/tree/main/audits/macs2)


Generated by Claude Code

TwoConditionScores.mean_from_peakcontent declared the per-interval
score and its accumulator as `cython.long` after the pure-Python-mode
conversion (they were `float64_t` in MACS2 2.2.9.1 and MACS3 3.0.0), so
every log10 likelihood ratio was cut to its integer part before the
length-weighted mean was taken. With a cutoff below 1 every score in
the common file became 0 and cond1/cond2 scores could fall below the
cutoff (macs3-project#715); with the default cutoff every score was biased low by
up to 1. Declare both as `cython.double` again. Restores the exact
scores in test/standard_results_bdgdiff.

Also fix the Test_TwoConditionScores fixture, which called the removed
bedGraphTrackI.safe_add_loc, and add a regression test.

Fixes macs3-project#715

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TaHntBDKuZJpMAAMenkC44
@taoliu
taoliu self-requested a review September 18, 2026 06:57
@taoliu taoliu self-assigned this Sep 18, 2026

@taoliu taoliu left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fixes!

@taoliu
taoliu merged commit 26f6709 into macs3-project:main Sep 18, 2026
7 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.

Bug: macs3 bdgdiff produces scores less than -C cutoff in cond1/2 bed file, and scores of all zeroes in common bed file

2 participants