countmut 0.0.2__tar.gz → 0.0.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {countmut-0.0.2 → countmut-0.0.3}/PKG-INFO +59 -42
- countmut-0.0.3/README.md +117 -0
- {countmut-0.0.2 → countmut-0.0.3}/countmut/cli.py +10 -9
- {countmut-0.0.2 → countmut-0.0.3}/countmut/core.py +40 -28
- {countmut-0.0.2 → countmut-0.0.3}/countmut.egg-info/PKG-INFO +59 -42
- {countmut-0.0.2 → countmut-0.0.3}/pyproject.toml +1 -1
- countmut-0.0.2/README.md +0 -100
- {countmut-0.0.2 → countmut-0.0.3}/LICENSE +0 -0
- {countmut-0.0.2 → countmut-0.0.3}/countmut/__init__.py +0 -0
- {countmut-0.0.2 → countmut-0.0.3}/countmut/utils.py +0 -0
- {countmut-0.0.2 → countmut-0.0.3}/countmut.egg-info/SOURCES.txt +0 -0
- {countmut-0.0.2 → countmut-0.0.3}/countmut.egg-info/dependency_links.txt +0 -0
- {countmut-0.0.2 → countmut-0.0.3}/countmut.egg-info/entry_points.txt +0 -0
- {countmut-0.0.2 → countmut-0.0.3}/countmut.egg-info/requires.txt +0 -0
- {countmut-0.0.2 → countmut-0.0.3}/countmut.egg-info/top_level.txt +0 -0
- {countmut-0.0.2 → countmut-0.0.3}/setup.cfg +0 -0
- {countmut-0.0.2 → countmut-0.0.3}/tests/test_cli.py +0 -0
- {countmut-0.0.2 → countmut-0.0.3}/tests/test_core.py +0 -0
- {countmut-0.0.2 → countmut-0.0.3}/tests/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: countmut
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.3
|
|
4
4
|
Summary: Ultra-fast strand-aware mutation counter
|
|
5
5
|
Author-email: Ye Chang <yech1990@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -41,13 +41,13 @@ Dynamic: license-file
|
|
|
41
41
|
[](https://pepy.tech/project/countmut)
|
|
42
42
|
[](https://github.com/y9c/countmut)
|
|
43
43
|
|
|
44
|
-
**Ultra-fast strand-aware mutation counter**
|
|
44
|
+
> **Ultra-fast strand-aware mutation counter for bisulfite sequencing analysis**
|
|
45
45
|
|
|
46
|
-
CountMut
|
|
46
|
+
CountMut is a high-performance tool for counting mutations from bisulfite sequencing BAM files (BS-seq, CAM-seq, GLORI-seq, eTAM-seq). It features parallel processing, quality-based mate overlap deduplication, and optimized file I/O for maximum speed.
|
|
47
47
|
|
|
48
48
|
## Features
|
|
49
49
|
|
|
50
|
-
- 🚀 **Ultra-Fast**:
|
|
50
|
+
- 🚀 **Ultra-Fast**: Call mutation without pileup reads
|
|
51
51
|
- 🧬 **Bisulfite Support**: NS, Zf, Yf tag filtering for conversion analysis
|
|
52
52
|
- 🎯 **Accurate**: Quality-based mate overlap deduplication prevents double-counting
|
|
53
53
|
- ⚡ **Parallel**: Multi-threaded genomic window processing
|
|
@@ -72,51 +72,68 @@ countmut -i input.bam -r reference.fa -o mutations.tsv --ref-base T --mut-base C
|
|
|
72
72
|
countmut -i input.bam -r reference.fa -o mutations.tsv -t 8 --max-unc 5 --min-con 2
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
-
##
|
|
75
|
+
## Options
|
|
76
76
|
|
|
77
|
+
**Input/Output**
|
|
77
78
|
```bash
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
Output:
|
|
83
|
-
-o, --output PATH Output TSV file (default: stdout)
|
|
84
|
-
|
|
85
|
-
Mutation:
|
|
86
|
-
--ref-base TEXT Reference base [default: A]
|
|
87
|
-
--mut-base TEXT Mutation base [default: G]
|
|
88
|
-
--strand [both|forward|reverse] Strand processing [default: both]
|
|
89
|
-
--region TEXT Specific region (e.g., 'chr1:1000000-2000000')
|
|
90
|
-
|
|
91
|
-
Performance:
|
|
92
|
-
-t, --threads INTEGER Number of threads [default: auto]
|
|
93
|
-
-b, --bin-size INTEGER Genomic bin size [default: 10000]
|
|
94
|
-
|
|
95
|
-
Filtering (Bisulfite):
|
|
96
|
-
--pad INTEGER Motif window padding [default: 15]
|
|
97
|
-
--trim-start INTEGER Trim 5' bases [default: 2]
|
|
98
|
-
--trim-end INTEGER Trim 3' bases [default: 2]
|
|
99
|
-
--max-unc INTEGER Max unconverted (Zf) [default: 3]
|
|
100
|
-
--min-con INTEGER Min converted (Yf) [default: 1]
|
|
101
|
-
--max-sub INTEGER Max substitutions (NS) [default: 1]
|
|
102
|
-
--min-baseq INTEGER Min base quality (Phred) [default: 20]
|
|
103
|
-
--min-mapq INTEGER Min mapping quality (MAPQ) [default: 0]
|
|
79
|
+
-i, --input PATH Input BAM file (coordinate-sorted) [required]
|
|
80
|
+
-r, --reference PATH Reference FASTA file [required]
|
|
81
|
+
-o, --output PATH Output TSV file (default: stdout)
|
|
82
|
+
-f, --force Overwrite output without prompting
|
|
104
83
|
```
|
|
105
84
|
|
|
106
|
-
**
|
|
85
|
+
**Mutation Analysis**
|
|
86
|
+
```bash
|
|
87
|
+
--ref-base TEXT Reference base to count from [default: A]
|
|
88
|
+
--mut-base TEXT Mutation base to count [default: G]
|
|
89
|
+
--strand TEXT Strand: both/forward/reverse [default: both]
|
|
90
|
+
--region TEXT Genomic region (e.g., 'chr1:1000000-2000000')
|
|
91
|
+
```
|
|
107
92
|
|
|
108
|
-
|
|
93
|
+
**Performance**
|
|
94
|
+
```bash
|
|
95
|
+
-t, --threads INTEGER Number of parallel threads [default: auto]
|
|
96
|
+
-b, --bin-size INTEGER Genomic bin size in bp [default: 10000]
|
|
97
|
+
```
|
|
109
98
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
-
|
|
113
|
-
-
|
|
114
|
-
-
|
|
99
|
+
**Quality Filters**
|
|
100
|
+
```bash
|
|
101
|
+
--min-baseq INTEGER Min base quality (Phred score) [default: 20]
|
|
102
|
+
--min-mapq INTEGER Min mapping quality (MAPQ) [default: 0]
|
|
103
|
+
--max-sub INTEGER Max substitutions (NS tag) [default: 1]
|
|
104
|
+
--trim-start INTEGER Trim 5' bases from reads [default: 2]
|
|
105
|
+
--trim-end INTEGER Trim 3' bases from reads [default: 2]
|
|
106
|
+
--max-unc INTEGER Max unconverted (Zf tag) [default: 3]
|
|
107
|
+
--min-con INTEGER Min converted (Yf tag) [default: 1]
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**Output Records**
|
|
111
|
+
```bash
|
|
112
|
+
-p, --pad INTEGER Motif window half-size [default: 15]
|
|
113
|
+
-s, --save-rest Include other bases (o0, o1, o2 columns)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
> **Note**: BAM files must have **NS**, **Zf**, and **Yf** tags (essential for bisulfite analysis).
|
|
117
|
+
> Indices (.bai, .fai) are created automatically if missing.
|
|
118
|
+
|
|
119
|
+
## Output Format
|
|
115
120
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
121
|
+
TSV file with the following columns:
|
|
122
|
+
|
|
123
|
+
| Column | Description |
|
|
124
|
+
|--------|-------------|
|
|
125
|
+
| `chrom` | Chromosome name |
|
|
126
|
+
| `pos` | Genomic position (1-based) |
|
|
127
|
+
| `strand` | Strand (+ or -) |
|
|
128
|
+
| `motif` | Sequence context (2×pad+1 bp window) |
|
|
129
|
+
| `u0`, `u1`, `u2` | **Unconverted** (reference base) counts |
|
|
130
|
+
| `m0`, `m1`, `m2` | **Mutation** (mutation base only) counts |
|
|
131
|
+
| `o0`, `o1`, `o2` | **Other bases** counts (with `--save-rest`) |
|
|
132
|
+
|
|
133
|
+
**Count categories** (x0, x1, x2):
|
|
134
|
+
- **x0 (low quality)**: Bases failing quality filters (trim region, max-sub, min-mapq, min-baseq)
|
|
135
|
+
- **x1 (high conversion)**: Bases from reads with high conversion efficiency (low Zf and high Yf)
|
|
136
|
+
- **x2 (insufficient conversion)**: Bases from reads with insufficient conversion efficiency (high Zf or low Yf)
|
|
120
137
|
|
|
121
138
|
|
|
122
139
|
|
countmut-0.0.3/README.md
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# CountMut
|
|
2
|
+
|
|
3
|
+
[](https://pypi.python.org/pypi/countmut)
|
|
4
|
+
[](https://pepy.tech/project/countmut)
|
|
5
|
+
[](https://github.com/y9c/countmut)
|
|
6
|
+
|
|
7
|
+
> **Ultra-fast strand-aware mutation counter for bisulfite sequencing analysis**
|
|
8
|
+
|
|
9
|
+
CountMut is a high-performance tool for counting mutations from bisulfite sequencing BAM files (BS-seq, CAM-seq, GLORI-seq, eTAM-seq). It features parallel processing, quality-based mate overlap deduplication, and optimized file I/O for maximum speed.
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- 🚀 **Ultra-Fast**: Call mutation without pileup reads
|
|
14
|
+
- 🧬 **Bisulfite Support**: NS, Zf, Yf tag filtering for conversion analysis
|
|
15
|
+
- 🎯 **Accurate**: Quality-based mate overlap deduplication prevents double-counting
|
|
16
|
+
- ⚡ **Parallel**: Multi-threaded genomic window processing
|
|
17
|
+
- 🔧 **Flexible**: Configurable filtering, strand-specific processing, auto-indexing
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pip install countmut
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Quick Start
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# Basic usage - auto-creates indices if needed
|
|
29
|
+
countmut -i input.bam -r reference.fa -o mutations.tsv
|
|
30
|
+
|
|
31
|
+
# Count T→C mutations (common in bisulfite sequencing)
|
|
32
|
+
countmut -i input.bam -r reference.fa -o mutations.tsv --ref-base T --mut-base C
|
|
33
|
+
|
|
34
|
+
# With custom threads and filtering
|
|
35
|
+
countmut -i input.bam -r reference.fa -o mutations.tsv -t 8 --max-unc 5 --min-con 2
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Options
|
|
39
|
+
|
|
40
|
+
**Input/Output**
|
|
41
|
+
```bash
|
|
42
|
+
-i, --input PATH Input BAM file (coordinate-sorted) [required]
|
|
43
|
+
-r, --reference PATH Reference FASTA file [required]
|
|
44
|
+
-o, --output PATH Output TSV file (default: stdout)
|
|
45
|
+
-f, --force Overwrite output without prompting
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**Mutation Analysis**
|
|
49
|
+
```bash
|
|
50
|
+
--ref-base TEXT Reference base to count from [default: A]
|
|
51
|
+
--mut-base TEXT Mutation base to count [default: G]
|
|
52
|
+
--strand TEXT Strand: both/forward/reverse [default: both]
|
|
53
|
+
--region TEXT Genomic region (e.g., 'chr1:1000000-2000000')
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**Performance**
|
|
57
|
+
```bash
|
|
58
|
+
-t, --threads INTEGER Number of parallel threads [default: auto]
|
|
59
|
+
-b, --bin-size INTEGER Genomic bin size in bp [default: 10000]
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Quality Filters**
|
|
63
|
+
```bash
|
|
64
|
+
--min-baseq INTEGER Min base quality (Phred score) [default: 20]
|
|
65
|
+
--min-mapq INTEGER Min mapping quality (MAPQ) [default: 0]
|
|
66
|
+
--max-sub INTEGER Max substitutions (NS tag) [default: 1]
|
|
67
|
+
--trim-start INTEGER Trim 5' bases from reads [default: 2]
|
|
68
|
+
--trim-end INTEGER Trim 3' bases from reads [default: 2]
|
|
69
|
+
--max-unc INTEGER Max unconverted (Zf tag) [default: 3]
|
|
70
|
+
--min-con INTEGER Min converted (Yf tag) [default: 1]
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Output Records**
|
|
74
|
+
```bash
|
|
75
|
+
-p, --pad INTEGER Motif window half-size [default: 15]
|
|
76
|
+
-s, --save-rest Include other bases (o0, o1, o2 columns)
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
> **Note**: BAM files must have **NS**, **Zf**, and **Yf** tags (essential for bisulfite analysis).
|
|
80
|
+
> Indices (.bai, .fai) are created automatically if missing.
|
|
81
|
+
|
|
82
|
+
## Output Format
|
|
83
|
+
|
|
84
|
+
TSV file with the following columns:
|
|
85
|
+
|
|
86
|
+
| Column | Description |
|
|
87
|
+
|--------|-------------|
|
|
88
|
+
| `chrom` | Chromosome name |
|
|
89
|
+
| `pos` | Genomic position (1-based) |
|
|
90
|
+
| `strand` | Strand (+ or -) |
|
|
91
|
+
| `motif` | Sequence context (2×pad+1 bp window) |
|
|
92
|
+
| `u0`, `u1`, `u2` | **Unconverted** (reference base) counts |
|
|
93
|
+
| `m0`, `m1`, `m2` | **Mutation** (mutation base only) counts |
|
|
94
|
+
| `o0`, `o1`, `o2` | **Other bases** counts (with `--save-rest`) |
|
|
95
|
+
|
|
96
|
+
**Count categories** (x0, x1, x2):
|
|
97
|
+
- **x0 (low quality)**: Bases failing quality filters (trim region, max-sub, min-mapq, min-baseq)
|
|
98
|
+
- **x1 (high conversion)**: Bases from reads with high conversion efficiency (low Zf and high Yf)
|
|
99
|
+
- **x2 (insufficient conversion)**: Bases from reads with insufficient conversion efficiency (high Zf or low Yf)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
<p align="center">
|
|
105
|
+
<img
|
|
106
|
+
src="https://raw.githubusercontent.com/y9c/y9c/master/resource/footer_line.svg?sanitize=true"
|
|
107
|
+
/>
|
|
108
|
+
</p>
|
|
109
|
+
<p align="center">
|
|
110
|
+
Copyright © 2025-present
|
|
111
|
+
<a href="https://github.com/y9c" target="_blank">Chang Y</a>
|
|
112
|
+
</p>
|
|
113
|
+
<p align="center">
|
|
114
|
+
<a href="https://github.com/y9c/countmut/blob/main/LICENSE">
|
|
115
|
+
<img src="https://img.shields.io/static/v1.svg?style=for-the-badge&label=License&message=MIT&logoColor=d9e0ee&colorA=282a36&colorB=c678dd" />
|
|
116
|
+
</a>
|
|
117
|
+
</p>
|
|
@@ -40,12 +40,8 @@ click.rich_click.TEXT_EMOJIS = True
|
|
|
40
40
|
click.rich_click.OPTION_GROUPS = {
|
|
41
41
|
"countmut": [
|
|
42
42
|
{
|
|
43
|
-
"name": "
|
|
44
|
-
"options": ["--input", "--reference"],
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
"name": "Output Options",
|
|
48
|
-
"options": ["--output", "--save-rest", "--force"],
|
|
43
|
+
"name": "Input/Output Options",
|
|
44
|
+
"options": ["--input", "--reference", "--output", "--force"],
|
|
49
45
|
},
|
|
50
46
|
{
|
|
51
47
|
"name": "Mutation Analysis",
|
|
@@ -64,8 +60,12 @@ click.rich_click.OPTION_GROUPS = {
|
|
|
64
60
|
],
|
|
65
61
|
},
|
|
66
62
|
{
|
|
67
|
-
"name": "
|
|
68
|
-
"options": ["--pad"],
|
|
63
|
+
"name": "Output Records",
|
|
64
|
+
"options": ["--pad", "--save-rest"],
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"name": "Performance Options",
|
|
68
|
+
"options": ["--threads", "--bin-size"],
|
|
69
69
|
},
|
|
70
70
|
{
|
|
71
71
|
"name": "Help & Version",
|
|
@@ -181,7 +181,7 @@ countmut -i input.bam -r reference.fa --region chr1:1000000-2000000
|
|
|
181
181
|
"-s",
|
|
182
182
|
"--save-rest",
|
|
183
183
|
is_flag=True,
|
|
184
|
-
help="[bold]Save
|
|
184
|
+
help="[bold]Save other bases[/bold] statistics (o0, o1, o2 columns)",
|
|
185
185
|
)
|
|
186
186
|
@click.option(
|
|
187
187
|
"--region",
|
|
@@ -202,6 +202,7 @@ countmut -i input.bam -r reference.fa --region chr1:1000000-2000000
|
|
|
202
202
|
help="[bold]Strand processing[/bold]: 'both' (default), 'forward' (+ only), or 'reverse' (- only)",
|
|
203
203
|
)
|
|
204
204
|
@click.option(
|
|
205
|
+
"-p",
|
|
205
206
|
"--pad",
|
|
206
207
|
type=int,
|
|
207
208
|
default=15,
|
|
@@ -255,14 +255,14 @@ def parse_region_worker(args: tuple) -> dict[str, Any]:
|
|
|
255
255
|
for pos in target_sites_list:
|
|
256
256
|
position_data[pos] = {
|
|
257
257
|
"+": {
|
|
258
|
-
"
|
|
259
|
-
"
|
|
260
|
-
"
|
|
258
|
+
"high_conversion_count": Counter(),
|
|
259
|
+
"insufficient_conversion_count": Counter(),
|
|
260
|
+
"low_quality_count": Counter(),
|
|
261
261
|
},
|
|
262
262
|
"-": {
|
|
263
|
-
"
|
|
264
|
-
"
|
|
265
|
-
"
|
|
263
|
+
"high_conversion_count": Counter(),
|
|
264
|
+
"insufficient_conversion_count": Counter(),
|
|
265
|
+
"low_quality_count": Counter(),
|
|
266
266
|
},
|
|
267
267
|
}
|
|
268
268
|
|
|
@@ -310,10 +310,10 @@ def parse_region_worker(args: tuple) -> dict[str, Any]:
|
|
|
310
310
|
ns = read.get_tag("NS")
|
|
311
311
|
passes_mismatch_filter = ns <= max_sub
|
|
312
312
|
|
|
313
|
-
# Check conversion
|
|
313
|
+
# Check conversion filter (reads passing are sufficiently converted)
|
|
314
314
|
zf = read.get_tag("Zf")
|
|
315
315
|
yf = read.get_tag("Yf")
|
|
316
|
-
|
|
316
|
+
passes_conversion_filter = (zf <= max_unc) and (yf >= min_con)
|
|
317
317
|
|
|
318
318
|
# Process each position in the read
|
|
319
319
|
query_sequence = read.query_sequence
|
|
@@ -363,7 +363,7 @@ def parse_region_worker(args: tuple) -> dict[str, Any]:
|
|
|
363
363
|
bool(passes_mismatch_filter),
|
|
364
364
|
bool(passes_mapq_filter),
|
|
365
365
|
bool(passes_baseq_filter),
|
|
366
|
-
bool(
|
|
366
|
+
bool(passes_conversion_filter),
|
|
367
367
|
)
|
|
368
368
|
|
|
369
369
|
except (KeyError, AttributeError) as e:
|
|
@@ -380,28 +380,34 @@ def parse_region_worker(args: tuple) -> dict[str, Any]:
|
|
|
380
380
|
passes_mismatch_filter,
|
|
381
381
|
passes_mapq_filter,
|
|
382
382
|
passes_baseq_filter,
|
|
383
|
-
|
|
383
|
+
passes_conversion_filter,
|
|
384
384
|
) in best_obs.items():
|
|
385
385
|
# Skip positions that are not in our target sites (safety)
|
|
386
386
|
if ref_pos not in position_data:
|
|
387
387
|
continue
|
|
388
388
|
|
|
389
|
-
# Count in
|
|
389
|
+
# Count in low_quality if ANY quality filter fails
|
|
390
390
|
if not (
|
|
391
391
|
is_internal
|
|
392
392
|
and passes_mismatch_filter
|
|
393
393
|
and passes_mapq_filter
|
|
394
394
|
and passes_baseq_filter
|
|
395
395
|
):
|
|
396
|
-
position_data[ref_pos][strand_symbol]["
|
|
397
|
-
|
|
396
|
+
position_data[ref_pos][strand_symbol]["low_quality_count"][
|
|
397
|
+
query_base
|
|
398
|
+
] += 1
|
|
399
|
+
# Count in high_conversion/insufficient_conversion only if ALL quality filters pass
|
|
398
400
|
else:
|
|
399
|
-
if
|
|
400
|
-
|
|
401
|
+
if passes_conversion_filter:
|
|
402
|
+
# High conversion efficiency (pass quality + conversion filters)
|
|
403
|
+
position_data[ref_pos][strand_symbol]["high_conversion_count"][
|
|
401
404
|
query_base
|
|
402
405
|
] += 1
|
|
403
406
|
else:
|
|
404
|
-
|
|
407
|
+
# Insufficient conversion efficiency (pass quality but fail conversion)
|
|
408
|
+
position_data[ref_pos][strand_symbol][
|
|
409
|
+
"insufficient_conversion_count"
|
|
410
|
+
][query_base] += 1
|
|
405
411
|
|
|
406
412
|
# Calculate total skipped
|
|
407
413
|
total_skipped = (
|
|
@@ -433,9 +439,15 @@ def parse_region_worker(args: tuple) -> dict[str, Any]:
|
|
|
433
439
|
if process_reverse_only and strand_symbol != "-":
|
|
434
440
|
continue
|
|
435
441
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
442
|
+
high_conversion_count = position_data[pos][strand_symbol][
|
|
443
|
+
"high_conversion_count"
|
|
444
|
+
]
|
|
445
|
+
insufficient_conversion_count = position_data[pos][strand_symbol][
|
|
446
|
+
"insufficient_conversion_count"
|
|
447
|
+
]
|
|
448
|
+
low_quality_count = position_data[pos][strand_symbol][
|
|
449
|
+
"low_quality_count"
|
|
450
|
+
]
|
|
439
451
|
|
|
440
452
|
# Get motif
|
|
441
453
|
motif = extended_target_seq[
|
|
@@ -448,15 +460,15 @@ def parse_region_worker(args: tuple) -> dict[str, Any]:
|
|
|
448
460
|
|
|
449
461
|
# Calculate counts
|
|
450
462
|
# u = unconverted (reference base), m = mutation (mutation base only), o = others
|
|
451
|
-
u0 =
|
|
452
|
-
m0 =
|
|
453
|
-
o0 =
|
|
454
|
-
u1 =
|
|
455
|
-
m1 =
|
|
456
|
-
o1 =
|
|
457
|
-
u2 =
|
|
458
|
-
m2 =
|
|
459
|
-
o2 =
|
|
463
|
+
u0 = low_quality_count[ref_base]
|
|
464
|
+
m0 = low_quality_count[mut_base]
|
|
465
|
+
o0 = low_quality_count.total() - u0 - m0
|
|
466
|
+
u1 = high_conversion_count[ref_base]
|
|
467
|
+
m1 = high_conversion_count[mut_base]
|
|
468
|
+
o1 = high_conversion_count.total() - u1 - m1
|
|
469
|
+
u2 = insufficient_conversion_count[ref_base]
|
|
470
|
+
m2 = insufficient_conversion_count[mut_base]
|
|
471
|
+
o2 = insufficient_conversion_count.total() - u2 - m2
|
|
460
472
|
|
|
461
473
|
if u1 + m1 + u2 + m2 > 0:
|
|
462
474
|
site_info = [region_chrom, pos + 1, strand_symbol, motif]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: countmut
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.3
|
|
4
4
|
Summary: Ultra-fast strand-aware mutation counter
|
|
5
5
|
Author-email: Ye Chang <yech1990@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -41,13 +41,13 @@ Dynamic: license-file
|
|
|
41
41
|
[](https://pepy.tech/project/countmut)
|
|
42
42
|
[](https://github.com/y9c/countmut)
|
|
43
43
|
|
|
44
|
-
**Ultra-fast strand-aware mutation counter**
|
|
44
|
+
> **Ultra-fast strand-aware mutation counter for bisulfite sequencing analysis**
|
|
45
45
|
|
|
46
|
-
CountMut
|
|
46
|
+
CountMut is a high-performance tool for counting mutations from bisulfite sequencing BAM files (BS-seq, CAM-seq, GLORI-seq, eTAM-seq). It features parallel processing, quality-based mate overlap deduplication, and optimized file I/O for maximum speed.
|
|
47
47
|
|
|
48
48
|
## Features
|
|
49
49
|
|
|
50
|
-
- 🚀 **Ultra-Fast**:
|
|
50
|
+
- 🚀 **Ultra-Fast**: Call mutation without pileup reads
|
|
51
51
|
- 🧬 **Bisulfite Support**: NS, Zf, Yf tag filtering for conversion analysis
|
|
52
52
|
- 🎯 **Accurate**: Quality-based mate overlap deduplication prevents double-counting
|
|
53
53
|
- ⚡ **Parallel**: Multi-threaded genomic window processing
|
|
@@ -72,51 +72,68 @@ countmut -i input.bam -r reference.fa -o mutations.tsv --ref-base T --mut-base C
|
|
|
72
72
|
countmut -i input.bam -r reference.fa -o mutations.tsv -t 8 --max-unc 5 --min-con 2
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
-
##
|
|
75
|
+
## Options
|
|
76
76
|
|
|
77
|
+
**Input/Output**
|
|
77
78
|
```bash
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
Output:
|
|
83
|
-
-o, --output PATH Output TSV file (default: stdout)
|
|
84
|
-
|
|
85
|
-
Mutation:
|
|
86
|
-
--ref-base TEXT Reference base [default: A]
|
|
87
|
-
--mut-base TEXT Mutation base [default: G]
|
|
88
|
-
--strand [both|forward|reverse] Strand processing [default: both]
|
|
89
|
-
--region TEXT Specific region (e.g., 'chr1:1000000-2000000')
|
|
90
|
-
|
|
91
|
-
Performance:
|
|
92
|
-
-t, --threads INTEGER Number of threads [default: auto]
|
|
93
|
-
-b, --bin-size INTEGER Genomic bin size [default: 10000]
|
|
94
|
-
|
|
95
|
-
Filtering (Bisulfite):
|
|
96
|
-
--pad INTEGER Motif window padding [default: 15]
|
|
97
|
-
--trim-start INTEGER Trim 5' bases [default: 2]
|
|
98
|
-
--trim-end INTEGER Trim 3' bases [default: 2]
|
|
99
|
-
--max-unc INTEGER Max unconverted (Zf) [default: 3]
|
|
100
|
-
--min-con INTEGER Min converted (Yf) [default: 1]
|
|
101
|
-
--max-sub INTEGER Max substitutions (NS) [default: 1]
|
|
102
|
-
--min-baseq INTEGER Min base quality (Phred) [default: 20]
|
|
103
|
-
--min-mapq INTEGER Min mapping quality (MAPQ) [default: 0]
|
|
79
|
+
-i, --input PATH Input BAM file (coordinate-sorted) [required]
|
|
80
|
+
-r, --reference PATH Reference FASTA file [required]
|
|
81
|
+
-o, --output PATH Output TSV file (default: stdout)
|
|
82
|
+
-f, --force Overwrite output without prompting
|
|
104
83
|
```
|
|
105
84
|
|
|
106
|
-
**
|
|
85
|
+
**Mutation Analysis**
|
|
86
|
+
```bash
|
|
87
|
+
--ref-base TEXT Reference base to count from [default: A]
|
|
88
|
+
--mut-base TEXT Mutation base to count [default: G]
|
|
89
|
+
--strand TEXT Strand: both/forward/reverse [default: both]
|
|
90
|
+
--region TEXT Genomic region (e.g., 'chr1:1000000-2000000')
|
|
91
|
+
```
|
|
107
92
|
|
|
108
|
-
|
|
93
|
+
**Performance**
|
|
94
|
+
```bash
|
|
95
|
+
-t, --threads INTEGER Number of parallel threads [default: auto]
|
|
96
|
+
-b, --bin-size INTEGER Genomic bin size in bp [default: 10000]
|
|
97
|
+
```
|
|
109
98
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
-
|
|
113
|
-
-
|
|
114
|
-
-
|
|
99
|
+
**Quality Filters**
|
|
100
|
+
```bash
|
|
101
|
+
--min-baseq INTEGER Min base quality (Phred score) [default: 20]
|
|
102
|
+
--min-mapq INTEGER Min mapping quality (MAPQ) [default: 0]
|
|
103
|
+
--max-sub INTEGER Max substitutions (NS tag) [default: 1]
|
|
104
|
+
--trim-start INTEGER Trim 5' bases from reads [default: 2]
|
|
105
|
+
--trim-end INTEGER Trim 3' bases from reads [default: 2]
|
|
106
|
+
--max-unc INTEGER Max unconverted (Zf tag) [default: 3]
|
|
107
|
+
--min-con INTEGER Min converted (Yf tag) [default: 1]
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**Output Records**
|
|
111
|
+
```bash
|
|
112
|
+
-p, --pad INTEGER Motif window half-size [default: 15]
|
|
113
|
+
-s, --save-rest Include other bases (o0, o1, o2 columns)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
> **Note**: BAM files must have **NS**, **Zf**, and **Yf** tags (essential for bisulfite analysis).
|
|
117
|
+
> Indices (.bai, .fai) are created automatically if missing.
|
|
118
|
+
|
|
119
|
+
## Output Format
|
|
115
120
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
121
|
+
TSV file with the following columns:
|
|
122
|
+
|
|
123
|
+
| Column | Description |
|
|
124
|
+
|--------|-------------|
|
|
125
|
+
| `chrom` | Chromosome name |
|
|
126
|
+
| `pos` | Genomic position (1-based) |
|
|
127
|
+
| `strand` | Strand (+ or -) |
|
|
128
|
+
| `motif` | Sequence context (2×pad+1 bp window) |
|
|
129
|
+
| `u0`, `u1`, `u2` | **Unconverted** (reference base) counts |
|
|
130
|
+
| `m0`, `m1`, `m2` | **Mutation** (mutation base only) counts |
|
|
131
|
+
| `o0`, `o1`, `o2` | **Other bases** counts (with `--save-rest`) |
|
|
132
|
+
|
|
133
|
+
**Count categories** (x0, x1, x2):
|
|
134
|
+
- **x0 (low quality)**: Bases failing quality filters (trim region, max-sub, min-mapq, min-baseq)
|
|
135
|
+
- **x1 (high conversion)**: Bases from reads with high conversion efficiency (low Zf and high Yf)
|
|
136
|
+
- **x2 (insufficient conversion)**: Bases from reads with insufficient conversion efficiency (high Zf or low Yf)
|
|
120
137
|
|
|
121
138
|
|
|
122
139
|
|
countmut-0.0.2/README.md
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
# CountMut
|
|
2
|
-
|
|
3
|
-
[](https://pypi.python.org/pypi/countmut)
|
|
4
|
-
[](https://pepy.tech/project/countmut)
|
|
5
|
-
[](https://github.com/y9c/countmut)
|
|
6
|
-
|
|
7
|
-
**Ultra-fast strand-aware mutation counter**
|
|
8
|
-
|
|
9
|
-
CountMut counts mutations from bisulfite sequencing / CAM-seq / GLORI-seq / eTAM-seq BAM files with parallel processing, quality-based mate overlap deduplication, and optimized file I/O.
|
|
10
|
-
|
|
11
|
-
## Features
|
|
12
|
-
|
|
13
|
-
- 🚀 **Ultra-Fast**: Direct FASTA index reading, shared file handles, BGZF multi-threading
|
|
14
|
-
- 🧬 **Bisulfite Support**: NS, Zf, Yf tag filtering for conversion analysis
|
|
15
|
-
- 🎯 **Accurate**: Quality-based mate overlap deduplication prevents double-counting
|
|
16
|
-
- ⚡ **Parallel**: Multi-threaded genomic window processing
|
|
17
|
-
- 🔧 **Flexible**: Configurable filtering, strand-specific processing, auto-indexing
|
|
18
|
-
|
|
19
|
-
## Installation
|
|
20
|
-
|
|
21
|
-
```bash
|
|
22
|
-
pip install countmut
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
## Quick Start
|
|
26
|
-
|
|
27
|
-
```bash
|
|
28
|
-
# Basic usage - auto-creates indices if needed
|
|
29
|
-
countmut -i input.bam -r reference.fa -o mutations.tsv
|
|
30
|
-
|
|
31
|
-
# Count T→C mutations (common in bisulfite sequencing)
|
|
32
|
-
countmut -i input.bam -r reference.fa -o mutations.tsv --ref-base T --mut-base C
|
|
33
|
-
|
|
34
|
-
# With custom threads and filtering
|
|
35
|
-
countmut -i input.bam -r reference.fa -o mutations.tsv -t 8 --max-unc 5 --min-con 2
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
## Key Options
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
Required:
|
|
42
|
-
-i, --input PATH Input BAM file
|
|
43
|
-
-r, --reference PATH Reference FASTA file
|
|
44
|
-
|
|
45
|
-
Output:
|
|
46
|
-
-o, --output PATH Output TSV file (default: stdout)
|
|
47
|
-
|
|
48
|
-
Mutation:
|
|
49
|
-
--ref-base TEXT Reference base [default: A]
|
|
50
|
-
--mut-base TEXT Mutation base [default: G]
|
|
51
|
-
--strand [both|forward|reverse] Strand processing [default: both]
|
|
52
|
-
--region TEXT Specific region (e.g., 'chr1:1000000-2000000')
|
|
53
|
-
|
|
54
|
-
Performance:
|
|
55
|
-
-t, --threads INTEGER Number of threads [default: auto]
|
|
56
|
-
-b, --bin-size INTEGER Genomic bin size [default: 10000]
|
|
57
|
-
|
|
58
|
-
Filtering (Bisulfite):
|
|
59
|
-
--pad INTEGER Motif window padding [default: 15]
|
|
60
|
-
--trim-start INTEGER Trim 5' bases [default: 2]
|
|
61
|
-
--trim-end INTEGER Trim 3' bases [default: 2]
|
|
62
|
-
--max-unc INTEGER Max unconverted (Zf) [default: 3]
|
|
63
|
-
--min-con INTEGER Min converted (Yf) [default: 1]
|
|
64
|
-
--max-sub INTEGER Max substitutions (NS) [default: 1]
|
|
65
|
-
--min-baseq INTEGER Min base quality (Phred) [default: 20]
|
|
66
|
-
--min-mapq INTEGER Min mapping quality (MAPQ) [default: 0]
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
**Note**: BAM must have NS, Zf, and Yf tags for bisulfite analysis.
|
|
70
|
-
|
|
71
|
-
## Output Format
|
|
72
|
-
|
|
73
|
-
TSV file with columns:
|
|
74
|
-
- `chrom`, `pos`, `strand`, `motif` - Position and sequence context
|
|
75
|
-
- `u0`, `u1`, `u2` - Unconverted (reference base) counts [drop, clean, unconverted]
|
|
76
|
-
- `m0`, `m1`, `m2` - Mutation (mutation base only) counts [drop, clean, unconverted]
|
|
77
|
-
- `o0`, `o1`, `o2` - Other bases counts [drop, clean, unconverted] (only with `--save-rest`)
|
|
78
|
-
|
|
79
|
-
Where:
|
|
80
|
-
- **drop** (x0): Bases failing quality filters (internal position, mismatch, mapq, baseq)
|
|
81
|
-
- **clean** (x1): High-quality bases passing all filters
|
|
82
|
-
- **unconverted** (x2): Bases in unconverted reads (high Zf or low Yf)
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
<p align="center">
|
|
88
|
-
<img
|
|
89
|
-
src="https://raw.githubusercontent.com/y9c/y9c/master/resource/footer_line.svg?sanitize=true"
|
|
90
|
-
/>
|
|
91
|
-
</p>
|
|
92
|
-
<p align="center">
|
|
93
|
-
Copyright © 2025-present
|
|
94
|
-
<a href="https://github.com/y9c" target="_blank">Chang Y</a>
|
|
95
|
-
</p>
|
|
96
|
-
<p align="center">
|
|
97
|
-
<a href="https://github.com/y9c/countmut/blob/main/LICENSE">
|
|
98
|
-
<img src="https://img.shields.io/static/v1.svg?style=for-the-badge&label=License&message=MIT&logoColor=d9e0ee&colorA=282a36&colorB=c678dd" />
|
|
99
|
-
</a>
|
|
100
|
-
</p>
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|