Repository navigation
3.0: stricter call rules (proper pairs, intact CpG, base quality), reference check, review fixes - #99
Merged
Merged
Conversation
…ference check, review fixes Default output changes, so this is a major version. The output format number stays 2: no release has written format 2 (2.8 writes format 1). Which reads and calls are used - Improper pairs are dropped by default: a paired read without the proper-pair flag (0x2) is skipped. --keep-improper-pairs keeps them. Single-end reads are unaffected. - Intact CpG: a call is kept only if the read shows the CpG's other base present, adjacent and equal to the reference (G after the C for top-strand reads, C before the G for bottom-strand reads). Otherwise the entry is -1. This removes the false "unmethylated" call a CpA/TpG variant molecule produces, and applies identically to the Bismark (XM) and base-decoding paths. A variant on the base that carries the call looks exactly like conversion in a single read and is not caught. - Base quality: the base carrying the call needs Phred >= 20 (--min-base-quality, 0 turns it off; reads without stored qualities are not filtered). Measured on real EM-seq at bases conversion cannot touch: 14.7% wrong below Q20, 0.88% at Q20-29, 0.14% at Q30 and above. - --mask-3prime N (off by default): calls within N bases of the 3' end of the fragment's original strand become -1, to remove end-repair fill-in. The end comes from the mates' own coordinates, not TLEN, because Bismark and bwa define TLEN differently when mates extend past each other. - The EM over-conversion filter ignores -1 entries, so a discarded call can no longer shield a fully unmethylated fragment. - RuntimeWarning when either the proper-pair or the base-quality filter discards more than half of at least 1,000 reads / calls. Reference check - A BAM whose header chromosome lengths differ from the FASTA is refused (ValueError; --allow-length-mismatch turns the check off). - RuntimeWarning when more than 10% of at least 1,000 decoded CpGs mismatch the reference. Real data: 2.1%; a wrong reference of the same length: 78%. Fixes from the methylation review - scipy >= 1.15 is required (scipy.sparse.get_index_dtype). - A CpG cache is no longer reused for a different FASTA with the same size and modification time: the fast path also needs the same resolved path; otherwise the SHA-256 decides. - Two BAMs that would write the same output file are refused up front. - Mates are matched by name and position, so unrelated pairs sharing a query name are not merged. - A chromosome named twice in --expected-chromosomes is an error. - bam2tensor-inspect exits 1 when a file cannot be read. - Rows follow the expected-chromosomes order, like the columns, whatever the FASTA's order. Recorded with every output - metadata.json gains input_bam, aligner, every filter setting (min_mapping_quality, min_base_quality, mask_3prime, keep_improper_pairs) and extraction_stats (reads used and dropped, CpG observations, and how many were discarded for each reason). API - ExtractionResult gains a third field, stats. Code that unpacks two values must change. - extract_methylation_data_from_bam() gains min_base_quality, mask_3prime, keep_improper_pairs and allow_length_mismatch. - New: check_chromosome_lengths(), embedding.chromosome_lengths. On real EM-seq (tests/test.bam against hg38 chr1) the output equals an independent decoder of the same rules with defaults, with masks of 10 and 20, and with two worker processes. Defaults give 11,062 fragments at 0.664 methylation; keeping improper pairs with no quality filter gives 11,638 at 0.660. The Bismark and bwa-meth fixtures still extract to identical matrices, including under the new options. Tests: 492 pass. New hand-built cases for each rule (intact CpG with deletions and insertions, base quality, mask boundaries, TLEN-convention independence, improper pairs, mate matching, statistics, warnings); the simulator now models base qualities, improper pairs and fragment ends.
Coverage reportClick to see where and how coverage changed
This report was generated by python-coverage-comment-action |
||||||||||||||||||||||||||||||||||||||||||||||||
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.
Summary
Version 3.0. Default output changes, so this is a major version: bam2tensor now keeps a methylation call only when the read gives good evidence for it, checks that the BAM matches the reference, and fixes the seven findings from the methylation review.
Merging this publishes 3.0 to PyPI (the release workflow tags a version change on
main).Which reads and calls are used
0x2is skipped--keep-improper-pairs-1-1--min-base-quality N(0= off)-1--mask-3prime NIntact CpG removes the false "unmethylated" call that a CpA/TpG variant molecule produces. It is applied identically to the Bismark (
XM) and base-decoding paths. A variant on the base that carries the call looks exactly like conversion in a single read and is not caught.Base quality is justified by measurement on real EM-seq, at bases conversion cannot touch:
3' end mask removes end-repair fill-in. It is off by default because pipelines often trim for this elsewhere. The end is taken from the mates' own coordinates, not
TLEN: Bismark and bwa defineTLENdifferently when mates extend past each other (70 of the 557 fixture pairs).EM over-conversion filter now ignores
-1entries, so a discarded call can no longer shield a fully unmethylated fragment.Guard warnings: a
RuntimeWarningfires when the proper-pair or base-quality filter discards more than half of at least 1,000 reads / calls, so an aligner that never sets0x2, or placeholder qualities, cannot silently empty the output.Reference check
--allow-length-mismatchturns the check off).RuntimeWarningfires when more than 10% of at least 1,000 decoded CpGs mismatch the reference. Real data sits at 2.1%; a wrong reference of the same length at 78%.Fixes from the methylation review
scipy >= 1.15is required (scipy.sparse.get_index_dtype).--expected-chromosomesis an error.bam2tensor-inspectexits 1 when a file cannot be read.Also: rows follow the
--expected-chromosomesorder, like the columns, whatever the FASTA's order.Recorded with every output
metadata.jsongainsinput_bam,aligner, every filter setting (min_mapping_quality,min_base_quality,mask_3prime,keep_improper_pairs) andextraction_stats: reads used and dropped, CpG observations, and how many were discarded for each reason.bam2tensor-inspectprints the filters.Breaking changes
-1entries (not-intact CpGs, low base quality) than 2.8 for the same BAM.ExtractionResulthas a third field,stats. Code that unpacksmatrix, tlen = ...must change.Verification
Real EM-seq cfDNA (
tests/test.bamagainst hg38 chr1):nox: all 12 sessions pass locally (pre-commit, mypy, tests on 3.11 / 3.12 / 3.13, typeguard, xdoctest, docs-build); 492 tests.Known limits
MDtag, so--filter-non-convertedcannot evaluate its reads. Now documented.tlen) still follows each aligner's ownTLENconvention.