Command line¶
MethylExtractor [options] <input.bam> [output_dir] [ref.fa]
Implemented in src/main.c. The program prints the raw argv to stderr before doing work, including for --help (help is handled after that banner). --help / -h then prints usage and returns 0.
Arguments¶
| Argument | Required | Role |
|---|---|---|
input.bam |
yes | Coordinate-sorted BAM with an index (sam_index_load). A missing index aborts that chromosome |
output_dir |
yes, positional or -o |
Created with mkdir if needed. Its final path component, with the suffix after the last . removed, is sample_id |
ref.fa |
one of this or reference in the map |
Indexed FASTA (fai_load). A positional FASTA overrides the map |
A trailing slash on output_dir makes the final component empty, so the manifest is written as /.extraction_manifest.json under that directory. Pass the directory without a trailing slash.
Options¶
| Option | Default | Accepted values |
|---|---|---|
-t, --threads |
online CPU count, else 16 |
integer ≥ 1 |
-q, --min-mapq |
30 |
integer ≥ 0. Reads with MAPQ less than this are dropped |
-p, --min-phred |
20 |
integer ≥ 0. Bases with Phred less than this are skipped |
-c, --min-cov |
4 |
integer ≥ 0. Sites with mC + uC below this are left out of the output file |
-C, --cap-cov |
0 |
integer ≥ 0. See below |
-G, --CHG |
off | flag |
-H, --CHH |
off | flag |
-m, --chrom-mapping |
<directory of the BAM>/chrom_mapping.json |
path |
-z, --compression |
6 |
integer 0–19 |
-k, --chunk-size |
1000000 |
integer ≥ 1. HDF5 chunk length |
-f, --output-format |
hdf5 |
hdf5, txt, both |
-s, --split |
off | flag |
-o, --output-dir |
unset | path. Wins over the positional output directory: if -o is set, the next positional is the FASTA |
-R, --read-level |
off | flag |
--mhap |
off | flag, long option only |
-T, --tile-size |
4 |
integer 2–8 |
--chrom-parallel |
2 |
integer ≥ 1 |
--max-rss-gb |
32 |
integer ≥ 1 |
-t is the total region-worker budget. Each in-flight chromosome receives max(1, threads / chrom_parallel) workers. There is no CLI flag for BGZF threads; each region samFile uses 2 (DEFAULT_BGZF_THREADS) via hts_set_threads.
Coverage cap¶
--cap-cov 0 stores the counts that were tallied.
Any positive --cap-cov enables rescaling inside flush_buffer. The numeric value is copied into the QC JSON filters.cap_cov and is not compared with site coverage. The writer computes the mean of mC + uC over sites that already pass --min-cov. Each of those sites whose coverage is above that mean is rewritten so the methylated fraction is unchanged and mC + uC equals the mean (mC rounded, uC set to the remainder). Sites at or below the mean are unchanged. sites_capped in the context JSON counts how many sites were rescaled.
Chromosome map¶
load_chrom_mapping in src/bam_processing.c reads a JSON object:
| Field | Role |
|---|---|
reference |
FASTA path, used when no positional FASTA was given |
chromosomes |
array |
chromosomes[].extract |
JSON true required, otherwise the entry is skipped |
chromosomes[].fasta |
contig name passed to faidx_fetch_seq |
chromosomes[].bam |
contig name passed to bam_name2id |
chromosomes[].name |
string used in output file names (up to 63 bytes) |
fasta, bam, and name must all be non-empty. A BAM contig that is missing, or a FASTA contig that cannot be fetched, is skipped with a message on stderr. Chromosomes that do run are ordered longest-first before the worker pool starts.
config/grch38_cpg_manifest.json is a checked-in table of per-chromosome CpG site counts. It is not read by the binary.
Read filters¶
For every alignment returned by the region iterator (src/bam_processing.c):
| Condition | Counter |
|---|---|
BAM_FUNMAP |
reads_dropped_unmapped |
BAM_FSECONDARY |
reads_dropped_secondary |
BAM_FQCFAIL |
reads_dropped_qc_fail |
BAM_FDUP |
reads_dropped_duplicate |
BAM_FSUPPLEMENTARY |
reads_dropped_supplementary |
MAPQ < --min-mapq |
reads_dropped_low_mapq |
NH tag present and NH > 1 |
reads_dropped_multimap |
Reads with no NH tag are kept. Flag masks are fixed; there is no include/exclude flag option. A read that contributes at least one counted base increments reads_used.
Base calls¶
Only reference positions whose base is C or G are candidates. Other reference bases increment bases_skipped_non_cytosine. Bases below --min-phred increment bases_skipped_low_phred.
Strand comes from getRealStrand:
- If the
XGtag isCorG, the strand is the Bismark OT/OB/CTOT/CTOB combination ofXG,BAM_FREVERSE, and read1/read2. Stored codes are1(OT),2(OB),3(CTOT),4(CTOB). - Otherwise a paired read uses flags only: read1 forward →
1, read1 reverse →2, read2 reverse →1, read2 forward →2. - An unpaired read is
2when reverse and1when forward.
If the XM tag is present and has type Z, a base is methylated when the tag character is Z, X, H, or U, and unmethylated when it is z, x, h, or u. Otherwise the sequence is used:
- Reference
Cand strand1or3:Cmethylated,Tunmethylated. - Reference
Gand strand2or4:Gmethylated,Aunmethylated.
Other bases at a candidate position are ignored (they do not increment the counted-base counters).
Contexts¶
Sites are classified in get_context (src/utils.c), in this order:
| Context | Flag | Rule |
|---|---|---|
CG (1) |
always | Reference C followed by G, or reference G preceded by C |
CHG (2) |
-G |
Reference C with G two bases downstream, or reference G with C two bases upstream, and the site was not already CG. The middle base is not inspected |
CHH (3) |
-H |
Any remaining reference C or G |
Plus-strand records are the reference C positions. Minus-strand records are the reference G positions. The two cytosines of one CpG stay in two records; this program does not merge them.
Output positions are 1-based (reference index + 1).
Overlapping mates¶
For a paired read whose mate is mapped on the same contig, the mate with the smaller POS skips reference positions at or after the mate's POS. If both starts are equal, read2 yields and read1 keeps the base. Skipped bases increment bases_skipped_overlap_clip. The decision uses only that alignment's own fields, so it stays the same when the mates fall in different region threads.
Read-level and haplotype sidecars¶
-R builds tiles of --tile-size consecutive sites (default 4, range 2–8). CG tiles are always eligible. CHG and CHH tiles are built only when -s is set and the matching context flag is set. The writer keeps a tile when at least one read called every site in the tile (min_tile_reads is fixed at 1). Files are {name}-{ctx}.patterns.h5.
--mhap records up to 256 CpG calls on each alignment and writes {name}-CG.mhap.h5 when at least one read had a CpG call. It does not require -s.
Layouts are in Output.
Parallelism flags¶
--chrom-parallel defaults to 2 and is clamped to the number of chromosomes that actually start. Before the pool starts, if the estimated RSS of the two largest chromosomes is greater than --max-rss-gb gibibytes, the program logs a line and forces --chrom-parallel to 1. The pool also waits rather than starting another chromosome when the running estimate would pass the same byte budget. The estimate is estimate_chromosome_rss_bytes in src/utils.c (sequence, site buffer, position index, dense count arrays, and read-level maps). It is an estimate, not a measurement of VmRSS.