parapeak 0.3.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.
- parapeak-0.3.3/LICENSE +21 -0
- parapeak-0.3.3/PKG-INFO +490 -0
- parapeak-0.3.3/README.md +458 -0
- parapeak-0.3.3/parapeak/__init__.py +1 -0
- parapeak-0.3.3/parapeak/__main__.py +28 -0
- parapeak-0.3.3/parapeak/bam_reader.py +396 -0
- parapeak-0.3.3/parapeak/blacklist.py +60 -0
- parapeak-0.3.3/parapeak/cli.py +147 -0
- parapeak-0.3.3/parapeak/gc_model.py +120 -0
- parapeak-0.3.3/parapeak/output.py +269 -0
- parapeak-0.3.3/parapeak/peak_caller.py +496 -0
- parapeak-0.3.3/parapeak/stats.py +267 -0
- parapeak-0.3.3/parapeak.egg-info/PKG-INFO +490 -0
- parapeak-0.3.3/parapeak.egg-info/SOURCES.txt +18 -0
- parapeak-0.3.3/parapeak.egg-info/dependency_links.txt +1 -0
- parapeak-0.3.3/parapeak.egg-info/entry_points.txt +2 -0
- parapeak-0.3.3/parapeak.egg-info/requires.txt +11 -0
- parapeak-0.3.3/parapeak.egg-info/top_level.txt +1 -0
- parapeak-0.3.3/pyproject.toml +47 -0
- parapeak-0.3.3/setup.cfg +4 -0
parapeak-0.3.3/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Takaho A. Endo
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
parapeak-0.3.3/PKG-INFO
ADDED
|
@@ -0,0 +1,490 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: parapeak
|
|
3
|
+
Version: 0.3.3
|
|
4
|
+
Summary: NGS peak caller with parallel computation and GC-corrected statistics
|
|
5
|
+
Author-email: "Takaho A. Endo" <ssssrabbit@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/takaho/parapeak
|
|
8
|
+
Project-URL: Repository, https://github.com/takaho/parapeak
|
|
9
|
+
Project-URL: Bug Tracker, https://github.com/takaho/parapeak/issues
|
|
10
|
+
Keywords: bioinformatics,NGS,peak-calling,genomics
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Requires-Python: >=3.9
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Requires-Dist: pysam>=0.21
|
|
23
|
+
Requires-Dist: numpy>=1.24
|
|
24
|
+
Requires-Dist: scipy>=1.11
|
|
25
|
+
Requires-Dist: numba>=0.58
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: pytest; extra == "dev"
|
|
28
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
|
29
|
+
Provides-Extra: bigwig
|
|
30
|
+
Requires-Dist: pyBigWig>=0.3; extra == "bigwig"
|
|
31
|
+
Dynamic: license-file
|
|
32
|
+
|
|
33
|
+
# parapeak
|
|
34
|
+
|
|
35
|
+
An NGS peak caller supporting shallow (MiSeq) to deep coverage across
|
|
36
|
+
ATAC-seq, genome-editing assays (CIRCLE-seq, GUIDE-seq), ChIP-seq, CUT&TAG,
|
|
37
|
+
and similar experiments.
|
|
38
|
+
|
|
39
|
+
**parapeak** is inspired by [MACS3](https://github.com/macs3-project/MACS) but differs in several key aspects:
|
|
40
|
+
|
|
41
|
+
| Feature | MACS3 | parapeak |
|
|
42
|
+
|---|---|---|
|
|
43
|
+
| Parallelism | Single-threaded | Multi-process, per chromosome |
|
|
44
|
+
| Genome size | User-supplied `--gsize` | Inferred from BAM headers |
|
|
45
|
+
| Statistical model | Poisson | Negative binomial **and** GC-corrected Z-score (both required) |
|
|
46
|
+
| GC correction | Separate tool | Built-in (no reference FASTA needed) |
|
|
47
|
+
| Blacklist | Not built-in | Applied at pileup construction time |
|
|
48
|
+
| Low-coverage support | Limited | Signal filters for MiSeq-depth data |
|
|
49
|
+
| Paired-end fragments | Fixed extension | Actual insert size from TLEN field |
|
|
50
|
+
| Unsorted BAM support | Requires sorted + indexed | Single-pass; no sorting or index required |
|
|
51
|
+
| Read QC filters | Basic | MAPQ threshold, QC-fail flag, duplicate/secondary/supplementary |
|
|
52
|
+
| Input | BAM/SAM/BED | BAM/SAM only (broken headers auto-repaired) |
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Installation
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
pip install -r requirements.txt
|
|
60
|
+
pip install -e .
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Dependencies: `pysam`, `numpy`, `scipy`, `numba`
|
|
64
|
+
|
|
65
|
+
> **numba** accelerates the negative-binomial survival function and the
|
|
66
|
+
> Benjamini–Hochberg isotonic step with JIT compilation.
|
|
67
|
+
> If numba is unavailable, parapeak falls back transparently to scipy.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Quick start
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
# Paired-end ATAC-seq, unsorted BAM
|
|
75
|
+
parapeak -t atac.bam --blacklist hg38-blacklist.v2.bed.gz \
|
|
76
|
+
-o results/ -n ATAC -p 8
|
|
77
|
+
|
|
78
|
+
# CIRCLE-seq / genome-editing with NTC control (MiSeq depth)
|
|
79
|
+
parapeak -t treated.bam -c ntc.bam \
|
|
80
|
+
--min-count 3 --min-fold 3.0 --pseudocount 2.0 \
|
|
81
|
+
-o results/ -n edit -p 8
|
|
82
|
+
|
|
83
|
+
# Multiple replicates, stricter MAPQ filter
|
|
84
|
+
parapeak -t rep1.bam rep2.bam --min-mapq 30 -o results/ -p 4
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
BAM files do **not** need to be sorted or indexed. parapeak reads each file
|
|
88
|
+
in a single sequential pass.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Options
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
Input:
|
|
96
|
+
-t, --treated BAM [BAM ...] Treated BAM/SAM files (sorting and indexing not required)
|
|
97
|
+
-c, --control BAM [BAM ...] Control/input BAM/SAM files
|
|
98
|
+
--blacklist BED Blacklist BED file (plain or gzip-compressed)
|
|
99
|
+
|
|
100
|
+
Output:
|
|
101
|
+
-o, --output DIR Output directory (default: parapeak_output)
|
|
102
|
+
-n, --name NAME Output file prefix (default: parapeak)
|
|
103
|
+
--bedgraph-value TYPE Value written to the bedGraph output.
|
|
104
|
+
fold_enrichment (default): (treated + pc) / (scaled control + pc)
|
|
105
|
+
pvalue: -log10 of the minimum NB / Z-score p-value per bin
|
|
106
|
+
pileup: raw treated read count per bin
|
|
107
|
+
|
|
108
|
+
Algorithm parameters:
|
|
109
|
+
--local-window BP Local background window size in bp (default: 1000)
|
|
110
|
+
--fragment-size BP Fallback extension for single-end or discordant
|
|
111
|
+
paired-end reads; estimated from paired-end insert
|
|
112
|
+
sizes if omitted, falls back to 200 bp
|
|
113
|
+
--bin-size BP Pileup bin size in bp (default: 10)
|
|
114
|
+
-q, --qvalue FLOAT Q-value threshold for both methods (default: 0.05)
|
|
115
|
+
--min-length BP Minimum peak length in bp (default: 200)
|
|
116
|
+
--max-gap BP Maximum gap to merge between significant bins (default: 30)
|
|
117
|
+
|
|
118
|
+
Read QC filters:
|
|
119
|
+
--min-mapq INT Minimum mapping quality (MAPQ). Reads below this
|
|
120
|
+
threshold are discarded (default: 20)
|
|
121
|
+
--min-fragment BP Minimum paired-end insert size accepted from TLEN.
|
|
122
|
+
Smaller inserts are treated as single-end (default: 10)
|
|
123
|
+
--max-fragment BP Maximum paired-end insert size accepted from TLEN.
|
|
124
|
+
Larger inserts are treated as single-end (default: 2000)
|
|
125
|
+
|
|
126
|
+
Signal filters:
|
|
127
|
+
--min-count FLOAT Minimum pileup at the peak summit bin (default: 5)
|
|
128
|
+
--min-fold FLOAT Minimum fold enrichment over background (default: 2.0)
|
|
129
|
+
--pseudocount FLOAT Background floor per local window (default: 1.0)
|
|
130
|
+
|
|
131
|
+
-p, --threads INT Number of parallel worker processes (default: 1)
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Read QC filtering
|
|
137
|
+
|
|
138
|
+
The following filters are applied to each read in order before it contributes
|
|
139
|
+
to the pileup. Counts for each filter are reported in the JSON run report.
|
|
140
|
+
|
|
141
|
+
| Filter | SAM flag / field | Default behaviour |
|
|
142
|
+
|---|---|---|
|
|
143
|
+
| Unmapped | `0x4` | Discarded |
|
|
144
|
+
| Duplicate | `0x400` | Discarded |
|
|
145
|
+
| Secondary alignment | `0x100` | Discarded |
|
|
146
|
+
| Supplementary alignment | `0x800` | Discarded |
|
|
147
|
+
| QC fail | `0x200` | Discarded |
|
|
148
|
+
| Low mapping quality | `MAPQ < --min-mapq` | Discarded (default MAPQ < 20) |
|
|
149
|
+
| Read 2 of a pair | `0x80` | Skipped (not a quality filter; avoids double-counting) |
|
|
150
|
+
|
|
151
|
+
Paired-end reads that pass all filters but whose TLEN falls outside
|
|
152
|
+
`[--min-fragment, --max-fragment]` are not discarded; they are treated as
|
|
153
|
+
single-end reads and extended by `--fragment-size`. The count of such reads
|
|
154
|
+
is reported as `insert_size_fallback` in the JSON run report.
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Single-end and paired-end handling
|
|
159
|
+
|
|
160
|
+
### Single-end
|
|
161
|
+
|
|
162
|
+
Each mapped read is extended from its 5′ end by `--fragment-size` bp toward
|
|
163
|
+
the sequenced fragment's expected end. `--fragment-size` is estimated
|
|
164
|
+
automatically as the median insert size if the BAM contains paired reads;
|
|
165
|
+
otherwise it defaults to 200 bp.
|
|
166
|
+
|
|
167
|
+
```
|
|
168
|
+
5'─────read──────3'──────────────extension──────────────►
|
|
169
|
+
|←────────────── fragment_size ────────────────────────→|
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Paired-end
|
|
173
|
+
|
|
174
|
+
Only **R1** is processed; R2 is skipped to avoid double-counting fragments.
|
|
175
|
+
|
|
176
|
+
For **proper pairs** whose TLEN (template length from the SAM field) falls
|
|
177
|
+
within `[--min-fragment, --max-fragment]` (default 10–2000 bp), the actual
|
|
178
|
+
fragment interval is used directly:
|
|
179
|
+
|
|
180
|
+
```
|
|
181
|
+
R1 5'──────────►
|
|
182
|
+
◄──────────5' R2
|
|
183
|
+
|←───────── TLEN (actual insert size) ─────────────────→|
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
This is important for experiments where fragment size varies:
|
|
187
|
+
|
|
188
|
+
- **ATAC-seq**: each pair of Tn5 cut sites defines an accessible region;
|
|
189
|
+
using actual insert sizes correctly captures nucleosome-free regions
|
|
190
|
+
(NFR, < 200 bp) and mono-nucleosomal fragments (∼200 bp).
|
|
191
|
+
- **CIRCLE-seq / GUIDE-seq**: read pairs span the circularised DNA around
|
|
192
|
+
cut sites; TLEN reflects the circle diameter.
|
|
193
|
+
- **ChIP-seq paired-end**: sonication produces a range of fragment sizes;
|
|
194
|
+
actual TLEN avoids over-smoothing short fragments.
|
|
195
|
+
|
|
196
|
+
For **discordant pairs** (TLEN outside `[--min-fragment, --max-fragment]`)
|
|
197
|
+
and **unpaired reads**, the read is treated as single-end and extended by
|
|
198
|
+
`--fragment-size`.
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## Signal filters for low-coverage data
|
|
203
|
+
|
|
204
|
+
At shallow sequencing depth (MiSeq, ~1–5 M reads), stochastic sampling
|
|
205
|
+
means that ~60% of 10 bp bins in the control have zero reads.
|
|
206
|
+
Without a signal floor, NB and Z-score tests can declare bins with only
|
|
207
|
+
1–2 reads significant wherever the control happens to have zero coverage,
|
|
208
|
+
producing thousands of artefactual peaks.
|
|
209
|
+
|
|
210
|
+
Three filters address this, all applied *after* the BH q-value test:
|
|
211
|
+
|
|
212
|
+
### `--pseudocount` (default: 1.0)
|
|
213
|
+
|
|
214
|
+
Adds a pseudocount (in units of reads per `--local-window`) to the scaled
|
|
215
|
+
control pileup before NB background fitting and fold-enrichment calculation.
|
|
216
|
+
Distributing the pseudocount across the local window gives each 10 bp bin
|
|
217
|
+
a minimum background floor of `pseudocount / (local_window / bin_size)`.
|
|
218
|
+
|
|
219
|
+
Fold enrichment is computed as:
|
|
220
|
+
|
|
221
|
+
```
|
|
222
|
+
fold = (mean_treatment + pseudocount) / (mean_scaled_control + pseudocount)
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
This eliminates infinite fold values when the control has zero reads and
|
|
226
|
+
makes the metric interpretable at all coverage depths.
|
|
227
|
+
|
|
228
|
+
### `--min-count` (default: 5.0)
|
|
229
|
+
|
|
230
|
+
Discards peaks whose summit bin has a pileup value below this threshold,
|
|
231
|
+
regardless of the q-value.
|
|
232
|
+
At typical fragment extension (200 bp), a summit pileup of 5 corresponds
|
|
233
|
+
to approximately 2–3 overlapping read fragments; for sparser data where
|
|
234
|
+
even 2–3 reads can be statistically significant against zero control, this
|
|
235
|
+
filter prevents low-signal artefacts.
|
|
236
|
+
|
|
237
|
+
### `--min-fold` (default: 2.0)
|
|
238
|
+
|
|
239
|
+
Discards peaks with fold enrichment (pseudocount-corrected) below this
|
|
240
|
+
value. Combined with `--pseudocount`, a minimum fold of 2.0 ensures that
|
|
241
|
+
the signal is at least twice the effective background, not just twice zero.
|
|
242
|
+
Set to values < 1 to disable.
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## Recommended parameters by experiment
|
|
247
|
+
|
|
248
|
+
| Experiment | SE/PE | Typical depth | `--min-count` | `--min-fold` | `--pseudocount` | `--local-window` | Notes |
|
|
249
|
+
|---|---|---|---|---|---|---|---|
|
|
250
|
+
| ATAC-seq (deep) | PE | > 20 M | 10 | 2.0 | 0.5 | 1000 | Nucleosome-free regions; actual insert sizes used |
|
|
251
|
+
| ATAC-seq (MiSeq) | PE | 2–5 M | 3 | 2.0 | 2.0 | 2000 | Wider local window compensates for sparse control |
|
|
252
|
+
| CIRCLE-seq | PE | 1–5 M | 3 | 3.0 | 2.0 | 1000 | Sparse library; higher fold reduces false positives |
|
|
253
|
+
| GUIDE-seq | PE | 5–20 M | 5 | 2.0 | 1.0 | 1000 | On-target site may need blacklisting |
|
|
254
|
+
| ChIP-seq narrow (deep) | SE/PE | > 10 M | 10 | 2.0 | 0.5 | 1000 | TF binding sites |
|
|
255
|
+
| ChIP-seq narrow (MiSeq) | SE | 1–5 M | 3 | 2.0 | 2.0 | 5000 | Wider local window for stable background |
|
|
256
|
+
| ChIP-seq broad | SE/PE | > 10 M | 5 | 1.5 | 1.0 | 5000 | Histone marks; lower fold threshold |
|
|
257
|
+
| CUT&TAG | PE | 5–20 M | 5 | 2.0 | 1.0 | 500 | High signal-to-noise; narrow local window |
|
|
258
|
+
| FAIRE-seq | SE/PE | > 5 M | 5 | 2.0 | 1.0 | 1000 | Similar to ATAC-seq |
|
|
259
|
+
|
|
260
|
+
### Coverage guide
|
|
261
|
+
|
|
262
|
+
| Sequencer | Typical read pairs | Recommended `--min-count` | Recommended `--pseudocount` |
|
|
263
|
+
|---|---|---|---|
|
|
264
|
+
| NovaSeq / HiSeq (deep) | > 30 M | 10–20 | 0.5 |
|
|
265
|
+
| NextSeq / HiSeq (standard) | 10–30 M | 5–10 | 1.0 |
|
|
266
|
+
| MiSeq (V3 2×300) | 3–10 M | 3–5 | 1.0–2.0 |
|
|
267
|
+
| MiSeq (V2 2×150) | 1–3 M | 3 | 2.0–5.0 |
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## Output files
|
|
272
|
+
|
|
273
|
+
| File | Format | Description |
|
|
274
|
+
|---|---|---|
|
|
275
|
+
| `<name>_peaks.narrowPeak` | ENCODE narrowPeak (BED6+4) | Final peak calls |
|
|
276
|
+
| `<name>_summits.bed` | BED | Single-base summit positions |
|
|
277
|
+
| `<name>_peaks.tsv` | TSV | All score columns for downstream analysis |
|
|
278
|
+
| `<name>.bedGraph` | UCSC bedGraph | Genome-wide signal track (see `--bedgraph-value`) |
|
|
279
|
+
| `<name>_run.json` | JSON | Settings and read QC statistics |
|
|
280
|
+
|
|
281
|
+
The narrowPeak columns follow the
|
|
282
|
+
[ENCODE specification](https://genome.ucsc.edu/FAQ/FAQformat.html#format12):
|
|
283
|
+
|
|
284
|
+
```
|
|
285
|
+
chrom start end name score strand signalValue -log10(p) -log10(q) summit_offset
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
The TSV file includes separate NB and Z-score p-values and q-values for
|
|
289
|
+
inspection of which statistical test is the driver for each peak.
|
|
290
|
+
|
|
291
|
+
### bedGraph signal track
|
|
292
|
+
|
|
293
|
+
The bedGraph file covers the full genome at the same bin resolution as the
|
|
294
|
+
pileup (`--bin-size`). Bins with zero signal and blacklisted bins are
|
|
295
|
+
omitted; consecutive bins with identical values are merged into a single
|
|
296
|
+
record to reduce file size. The default value is **fold enrichment**:
|
|
297
|
+
|
|
298
|
+
```
|
|
299
|
+
fold = (treated_bin + pseudocount) / (scaled_control_bin + pseudocount)
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
Use `--bedgraph-value pvalue` to write −log₁₀(*p*) (minimum of the NB
|
|
303
|
+
and Z-score p-values per bin), or `--bedgraph-value pileup` to write the
|
|
304
|
+
raw treated read count per bin.
|
|
305
|
+
|
|
306
|
+
The track is compatible with IGV, the UCSC Genome Browser, and any tool
|
|
307
|
+
that accepts bedGraph format.
|
|
308
|
+
|
|
309
|
+
### JSON run report
|
|
310
|
+
|
|
311
|
+
The JSON file records all settings and per-file read statistics for
|
|
312
|
+
reproducibility and QC review. Example:
|
|
313
|
+
|
|
314
|
+
```json
|
|
315
|
+
{
|
|
316
|
+
"run": {
|
|
317
|
+
"timestamp": "2026-06-15T10:00:00Z",
|
|
318
|
+
"tool": "parapeak"
|
|
319
|
+
},
|
|
320
|
+
"settings": {
|
|
321
|
+
"treated": ["sample.bam"],
|
|
322
|
+
"control": null,
|
|
323
|
+
"blacklist": null,
|
|
324
|
+
"bin_size": 10,
|
|
325
|
+
"fragment_size": null,
|
|
326
|
+
"min_mapq": 20,
|
|
327
|
+
"min_fragment": 10,
|
|
328
|
+
"max_fragment": 2000,
|
|
329
|
+
"qvalue": 0.05,
|
|
330
|
+
"min_count": 5.0,
|
|
331
|
+
"min_fold": 2.0,
|
|
332
|
+
"pseudocount": 1.0,
|
|
333
|
+
"threads": 8,
|
|
334
|
+
"bedgraph_value": "fold_enrichment"
|
|
335
|
+
},
|
|
336
|
+
"statistics": {
|
|
337
|
+
"fragment_size_used": 185,
|
|
338
|
+
"scale_factor": 1.0,
|
|
339
|
+
"treated": {
|
|
340
|
+
"total_reads": 42000000,
|
|
341
|
+
"filtered_unmapped": 1200000,
|
|
342
|
+
"filtered_duplicate": 3500000,
|
|
343
|
+
"filtered_secondary": 80000,
|
|
344
|
+
"filtered_supplementary": 12000,
|
|
345
|
+
"filtered_qcfail": 45000,
|
|
346
|
+
"filtered_low_mapq": 2100000,
|
|
347
|
+
"skipped_read2": 17500000,
|
|
348
|
+
"insert_size_fallback": 320000,
|
|
349
|
+
"reads_used": 17243000
|
|
350
|
+
},
|
|
351
|
+
"control": null,
|
|
352
|
+
"peaks_called": 48312
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
---
|
|
358
|
+
|
|
359
|
+
## Algorithm
|
|
360
|
+
|
|
361
|
+
### 1. Read pileup (single-pass)
|
|
362
|
+
|
|
363
|
+
Each BAM/SAM file is read in a single sequential pass using
|
|
364
|
+
[pysam](https://pysam.readthedocs.io/), with no region argument.
|
|
365
|
+
BAM files do not need to be sorted or indexed.
|
|
366
|
+
|
|
367
|
+
For each file, numpy arrays (one per chromosome, length = chromosome size /
|
|
368
|
+
bin size) are pre-allocated and held in memory. As each read is consumed from
|
|
369
|
+
the stream, QC filters are applied (see [Read QC filtering](#read-qc-filtering)),
|
|
370
|
+
the fragment interval is determined (see
|
|
371
|
+
[Single-end and paired-end handling](#single-end-and-paired-end-handling)),
|
|
372
|
+
and the corresponding bins are incremented by 1.
|
|
373
|
+
|
|
374
|
+
This approach has O(N_reads) I/O cost regardless of sort order. The previous
|
|
375
|
+
per-chromosome `fetch()` strategy required N_chromosomes scans of an unsorted
|
|
376
|
+
file; on a typical human genome (25 chromosomes) this is a ~25× reduction in
|
|
377
|
+
I/O for unsorted input.
|
|
378
|
+
|
|
379
|
+
Blacklisted bins are zeroed after the pass completes.
|
|
380
|
+
|
|
381
|
+
If pysam rejects a file due to a malformed header (e.g. duplicate `@HD`
|
|
382
|
+
lines produced by some aligners or merge tools), parapeak automatically
|
|
383
|
+
repairs the header: for SAM files the raw text is rewritten with duplicate
|
|
384
|
+
`@HD` lines removed; for BAM files the same repair is applied after dumping
|
|
385
|
+
the file to SAM text via `samtools view`. The fixed content is written to
|
|
386
|
+
a temporary file, read, and then deleted. If repair fails, the file is
|
|
387
|
+
skipped with a warning and the run continues with the remaining inputs.
|
|
388
|
+
|
|
389
|
+
### 2. GC correction model
|
|
390
|
+
|
|
391
|
+
Without requiring a reference genome, parapeak estimates per-bin GC content
|
|
392
|
+
from the sequences of mapped reads (a reliable proxy for reference GC%).
|
|
393
|
+
|
|
394
|
+
The genome is divided into non-overlapping windows (`--local-window`).
|
|
395
|
+
For each window, the mean GC fraction of overlapping reads and the observed
|
|
396
|
+
read depth are recorded. All windows across all chromosomes are pooled,
|
|
397
|
+
binned into 20 equal GC% intervals (0–5%, 5–10%, …, 95–100%), and the
|
|
398
|
+
mean and variance of depth are computed per interval.
|
|
399
|
+
|
|
400
|
+
A piecewise-linear interpolation curve `f(GC%) → (expected_depth, variance)`
|
|
401
|
+
is fitted to these bin statistics. This curve is used in Step 4 to derive
|
|
402
|
+
GC-corrected expected values and their variances for every genomic bin.
|
|
403
|
+
When too few data points are available (sparse libraries), the model falls
|
|
404
|
+
back to the global mean depth.
|
|
405
|
+
|
|
406
|
+
### 3. Negative-binomial p-values
|
|
407
|
+
|
|
408
|
+
The scaled control pileup is floored by adding
|
|
409
|
+
`pseudocount / (local_window / bin_size)` per bin before fitting.
|
|
410
|
+
|
|
411
|
+
For each bin, the background is estimated at two scales:
|
|
412
|
+
|
|
413
|
+
- **Global λ**: genome-wide mean of the pseudocount-adjusted scaled control.
|
|
414
|
+
- **Local λ**: sliding-window mean over `--local-window` bp.
|
|
415
|
+
|
|
416
|
+
The **larger** lambda (more conservative, higher p-value) is used, so
|
|
417
|
+
enrichment is only called when signal exceeds both local and global baselines.
|
|
418
|
+
|
|
419
|
+
A Negative Binomial NB(*r*, *p*) is fitted by the method of moments:
|
|
420
|
+
|
|
421
|
+
```
|
|
422
|
+
r = μ² / (σ² − μ) p = μ / σ²
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
When σ² ≤ μ the distribution degenerates to Poisson (*r* → ∞).
|
|
426
|
+
The survival function is evaluated with a numba-JIT log-PMF recurrence.
|
|
427
|
+
|
|
428
|
+
### 4. GC-corrected Z-score p-values
|
|
429
|
+
|
|
430
|
+
Each bin receives a GC-matched expected depth *E* and variance *V* from
|
|
431
|
+
Step 2. Expected values are scaled to match the total treatment read count.
|
|
432
|
+
|
|
433
|
+
```
|
|
434
|
+
Z = (observed − E) / √V
|
|
435
|
+
p_Z = P(Z_standard > Z) [one-sided upper tail]
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
### 5. Genome-wide Benjamini–Hochberg correction
|
|
439
|
+
|
|
440
|
+
P-values from all chromosomes are pooled and corrected independently for
|
|
441
|
+
each method. Steps 2–5 are parallelised across chromosomes (`-p` workers).
|
|
442
|
+
|
|
443
|
+
```
|
|
444
|
+
q_NB = BH(p_NB) q_Z = BH(p_Z)
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
A bin is **significant** only when **both** q_NB < threshold **and**
|
|
448
|
+
q_Z < threshold.
|
|
449
|
+
|
|
450
|
+
### 6. Peak region assembly and signal filtering
|
|
451
|
+
|
|
452
|
+
Contiguous significant bins are merged across gaps of up to `--max-gap` bp.
|
|
453
|
+
Regions shorter than `--min-length` bp are discarded.
|
|
454
|
+
|
|
455
|
+
Signal filters are then applied in order:
|
|
456
|
+
|
|
457
|
+
1. **`--min-count`**: summit pileup ≥ threshold
|
|
458
|
+
2. **`--min-fold`**: fold enrichment (pseudocount-corrected) ≥ threshold
|
|
459
|
+
|
|
460
|
+
The summit is the bin with the highest treatment pileup.
|
|
461
|
+
The score in the output is −log₁₀ of the minimum q-value across both methods.
|
|
462
|
+
|
|
463
|
+
---
|
|
464
|
+
|
|
465
|
+
## Comparison with MACS3
|
|
466
|
+
|
|
467
|
+
MACS3 uses a linked-list data structure internally, which limits its
|
|
468
|
+
ability to parallelise across chromosomes. parapeak replaces this with
|
|
469
|
+
per-chromosome NumPy arrays and Python `multiprocessing`, with
|
|
470
|
+
inter-process communication only at the genome-wide BH correction step.
|
|
471
|
+
|
|
472
|
+
MACS3 requires sorted and indexed BAM files for random-access region
|
|
473
|
+
queries. parapeak reads each file in a single forward pass, which
|
|
474
|
+
avoids this requirement and is more I/O-efficient for unsorted input.
|
|
475
|
+
|
|
476
|
+
The true runtime bottleneck is BAM decompression (via the C library
|
|
477
|
+
underlying pysam) and gzip decompression of the blacklist. These I/O costs
|
|
478
|
+
dominate over Python-level arithmetic, so there is no need for a compiled
|
|
479
|
+
extension language; numba JIT is sufficient for the compute-intensive
|
|
480
|
+
statistical routines.
|
|
481
|
+
|
|
482
|
+
---
|
|
483
|
+
|
|
484
|
+
## Author
|
|
485
|
+
|
|
486
|
+
Takaho A. Endo
|
|
487
|
+
|
|
488
|
+
## License
|
|
489
|
+
|
|
490
|
+
MIT
|