Calling footprints¶
fiberhmm-call runs the whole per-read caller in one process: the HMM,
nucleosome recall and TF recall (see How FiberHMM works).
For DAF input it also marks PCR duplicates and screens for SNPs first, and it
finishes with a bounded QC report.
Every option is listed in the command-line reference.
Inputs¶
| Input | Works | Notes |
|---|---|---|
| Aligned, coordinate-sorted and indexed BAM | yes | the fastest path, with --region-parallel |
| Aligned BAM, unsorted or unindexed | yes | streaming mode |
| Unaligned BAM (uBAM) | yes | streaming mode; reads are called unaligned |
stdin (-i -) |
yes | streaming mode |
Hia5 input needs MM/ML tags with m6A calls (A+a, and T-a on PacBio).
DAF input needs its deaminations as R/Y codes, a usable MD tag, or
--reference (see DAF-seq).
Reads below --min-mapq (0) or --min-read-length (1000 bp), reads with no
usable observations, and records that are skipped for another reason are
written to the output unchanged (without call tags), so the output always
holds every input record.
Two execution strategies¶
Region-parallel (--region-parallel) splits the genome into
--region-size (10 Mb) regions and gives one to each worker. It needs a
coordinate-sorted, indexed input, scales with --cores up to about the number
of regions, and writes a sorted, indexed output. Use it for aligned data.
fiberhmm-call -i sorted.bam -o calls.bam --enzyme hia5 --seq pacbio \
-c 16 --region-parallel --skip-scaffolds
--skip-scaffoldsleaves unplaced contigs,_random/_alt/chrUn_sequences and GenBank/RefSeq scaffolds uncalled (they are still copied to the output). Main chromosomes of human, mouse, fly, yeast (chrI–chrXVI), worm, RefSeqNC_accessions andchrEBVare kept.--chroms chr2L chr3Rcalls only those contigs; the others are copied.- A missing output directory is created.
Streaming (the default without --region-parallel) reads the input once,
in order, with --cores workers each taking --chunk-size (500) reads. It
accepts unsorted, unaligned and stdin input and can write to stdout (-o -,
unsorted, not indexed). A file output is sorted if needed, then indexed.
# Pipe into FIRE (fibertools' ft, installed separately) without an intermediate file
fiberhmm-call -i aligned.bam -o - --enzyme hia5 --seq pacbio -c 8 | ft fire - fire.bam
-c/--cores sets the worker processes (default 4); -c 0 uses every CPU. --io-threads (8) sets the htslib compression threads
per stage. --max-reads N (streaming only) stops after N reads, for a quick
look.
Long runs and resuming¶
A genome-scale --region-parallel run can take many hours. It keeps every
finished region in a work directory, so an interrupted run (Ctrl-C, kill,
a closed laptop lid, a crashed node) continues where it stopped:
fiberhmm-call -i sorted.bam -o calls.bam --enzyme hia5 --seq pacbio \
-c 16 --region-parallel --skip-scaffolds
# ... interrupted after 212 of 318 regions ...
fiberhmm-call -i sorted.bam -o calls.bam --enzyme hia5 --seq pacbio \
-c 16 --region-parallel --skip-scaffolds --resume
- The work directory is
.<output name>.fiberhmm-workbeside the output (.calls.bam.fiberhmm-work/), or--work-dir DIR. It holds each finished region's BAM, aregion_NNNNNN.done.jsonmarker written after the region finished (with the size and SHA-256 of the region's BAM), andmanifest.jsonwith the run identity: the input BAM (path, size, content SHA-256 of the BAM and its index, header SHA-256), every effective parameter including the resolved chemistry and defaults, the content digests of the model, nucleosome profile, SNP mask and reference, the region plan and the FiberHMM version. - Identities compare content, not file dates: a touched input, or a file replaced by an identical copy at the same path, is the same input; a changed one is refused even if its size and date were preserved. The resolved path is part of the identity, so the same data at another path (for example staged to scratch) is a different input. A digest is recomputed unless the file's device, inode, size, modification time and status-change time (which no tool can set back) are all unchanged, so resuming does not rehash unchanged inputs.
--resumereuses every region whose marker and BAM (size and SHA-256) validate, reruns missing, partial or altered regions, then merges and publishes the output atomically, exactly as an uninterrupted run would: the records are identical. The header's@PGkeeps the original command line. Integrated dedup and the DAF SNP screen are recomputed (they are deterministic).- A change to the input BAM or to any parameter is refused, naming the
fields that differ; nothing is mixed.
--coresand--io-threadsmay change. --resumeimplies--region-parallelfor an indexed, aligned BAM. With no work directory it starts a new run, so a runner can always pass it. Streaming runs (stdin, stdout, unsorted or unaligned input) cannot resume.- Without
--resume, an existing work directory is never discarded: the run stops and asks for--resume(or for the directory to be deleted). - A work directory has one owner: a run holds a lock on it (
.lock) from the moment it inspects it until it has published and cleaned up, and a second run on the same work directory is refused while the first is alive. The lock disappears with its process, however it ends, so there is never a stale lock to remove. - The work directory is removed after a successful publish
(
--keep-work-dirkeeps it) and kept when a run fails or is interrupted. It needs about as much space as the output BAM. SIGINT,SIGTERMandSIGHUPstop the run at once (queued regions are cancelled, workers are stopped); a partly written output is never published, and the exit status is 128 + the signal number.
Machine-readable progress¶
--progress-json writes one JSON object per line to stderr, or appends them
to a file with --progress-json FILE. Every line has schema
(fiberhmm.progress.v1), tool, event and time (Unix seconds):
event |
Extra fields |
|---|---|
start |
regions_total, regions_done, regions_reused, work_dir, output |
region |
region ([chrom, start, end]), regions_done, regions_total, regions_reused, reads, reads_with_footprints, reads_per_s, elapsed_s, eta_s |
merge |
regions_total, bams |
done |
output, regions_total, regions_reused, reads, reads_with_footprints, elapsed_s |
stopped |
reason, regions_done, regions_total, work_dir |
{"schema": "fiberhmm.progress.v1", "tool": "fiberhmm-call", "event": "region", "time": 1790733514.5, "region": ["chr2L", 2000000, 4000000], "regions_done": 57, "regions_total": 318, "regions_reused": 40, "reads": 812344, "reads_with_footprints": 790012, "reads_per_s": 1840.2, "elapsed_s": 212.4, "eta_s": 3120.0}
reads_per_s, elapsed_s and eta_s cover only regions processed in this
attempt (reused regions are excluded); eta_s scales the elapsed time by the
remaining called base pairs and is null until the first region finishes.
Region-parallel runs emit every event; streaming runs emit only start and
done. The text progress line shows the same ETA.
Which records are called¶
- Primary and supplementary alignments (default,
--alignments primary-supplementary). A supplementary record is another part of the read (the far side of a structural variant, an insertion's TE copy) and is called on its aligned bases only; its soft clips are the primary record's sequence. Secondary records (alternative placements of the same bases) are written through uncalled.--primarycalls primary records only,--no-primary(--alignments all) every record. - DAF bases without a reference counterpart (insertions, soft clips) and
SNP-masked sites are no evidence: a deamination is a read-versus-reference
mismatch, so these bases can show none. Unaligned stretches of 50 bp or more
get no calls (no nucleosome, MSP or TF; calls running into them are trimmed
at their edge).
--no-daf-mask-unalignedturns this off. Fiber-seq m6A is read-intrinsic: insertions and clips are called normally. - DAF insertions carried by many reads (at least
--daf-insert-min-carriers, default 20, within ±30 bp) are re-encoded against a deamination-aware consensus of the carriers' inserts, so they get real calls (--daf-insert-consensus offkeeps them masked). Each cluster's position, length, carriers per strand, consensus sequence and the fraction of confidently called columns are written toqc/<output>.insert_consensus.json. - Hard-clipped records whose MM/ML cannot match SEQ are always skipped
(
hard_clipped_mmin the skip report). minimap2 hard-clips supplementary alignments unless run with-Y, and theirMM/MLstill describe the full read. - Unmapped reads are called automatically for stdin, unindexed and
unaligned (no
@SQ) input, and passed through for indexed aligned BAMs.--process-unmapped/--no-process-unmappedforce either.
The run ends with a count of processed and skipped records by reason. If more
than 90% of records were skipped as unmapped, the run fails (see
Troubleshooting)
unless you passed --no-process-unmapped.
Model and chemistry¶
--enzyme and --seq choose the bundled models and every chemistry default
(Choosing the chemistry).
| Option | Default | Use |
|---|---|---|
-m/--model |
bundled | a custom HMM model (JSON) |
--recall-model |
the HMM model (DddA: ddda_TF.json) |
a separate table for TF recall |
-k/--context-size |
from the model | validated against the model's table |
--replace-chemistry |
off | re-declare the input's chemistry deliberately |
--prob-threshold |
128; 248 for Hia5 Nanopore | minimum ML for an MM/ML call |
A custom --model on a BAM that declares its chemistry inherits that enzyme
and platform (and their defaults) when the observation mode matches.
TF recall options¶
| Option | Default | Effect |
|---|---|---|
--min-llr |
5.0 (every preset) | per-interval cost λ of the TF decoder |
--min-opps |
3 | minimum informative targets per TF call |
--unify-threshold |
90 | HMM footprints shorter than this are TF candidates |
--emission-uplift |
1.0 | power transform of the emissions (sensitivity experiments only) |
--use-m5c / --no-use-m5c |
on for DddA | CpG-aware calling: CpGs masked in the first-pass HMM and recall (DAF-seq) |
--cpg-mask-policy |
unmethylated-only |
methylated-only masks only ddda_mcg spans (the pre-3.0 behaviour) |
Nucleosome recall options¶
| Option | Default | Effect |
|---|---|---|
--recall-nucs / --no-recall-nucs |
on | nucleosome recall; off gives raw HMM nucleosomes (nuc.Q) |
--split-min-llr |
4.0 | accessible evidence needed to split a footprint |
--split-min-opps |
3 | informative positions needed in a split |
--nuc-min-size |
85 | minimum nucleosome size; also what bounds an MSP |
--msp-min-size |
0 | minimum MSP size |
--ddda-derived-tf-max-edge-gap |
12 | DddA: evidence needed on both sides of TFs exposed by radial recall (-1 off) |
DAF options¶
For --enzyme dddb and --enzyme ddda on a file input, three stages run
automatically; each has its own section in DAF-seq:
- PCR-duplicate marking (
--dedup/--no-dedup,--dedup-collapseand the--dedup-*tuning options); - recurrent-SNP screening after duplicate
marking, when coverage allows (
--daf-call-snps/--no-daf-call-snps,--daf-snp-mask BED); - calling, with the strand-swap chimera filter
(on;
--keep-chimerasturns it off,--chimera-min-seg5 and--chimera-purity0.8 tune it) and adjacent-target thinning (--daf-mask-runs, default 2 with--daf-run-policy keep-onefor DddA, off for DddB).
--reference ref.fa supplies the reference when reads carry neither R/Y
codes nor a usable MD tag. --ddda-mcg was retired; it prints the
replacement workflow.
QC after calling¶
For a file output, fiberhmm-call samples the new BAM and writes a QC report
next to it (<output dir>/qc/<BAM stem>.qc.*), selecting the reference data
set from the resolved enzyme and platform. --no-qc skips it,
--qc-output-prefix moves it, and --qc-sample-reads, --qc-seed,
--qc-min-mapq tune the sample. QC is skipped for stdout output. See
Quality control.
Output¶
| Content | Where |
|---|---|
| Calls | ns/nl, as/al, nq, and MA/AQ (nuc, msp, tf); see Annotations |
| Provenance | @PG with the resolved settings in DS (for example mode=, enzyme=, prob_threshold=, primary_only=, recall_nucs=, dedup=, daf_snp_mask=, daf_run_mask=, cpg_mask=, hmm_cpg_mask=), and @CO fiberhmm:coord=molecular (calls are in the molecular frame; see Coordinates) |
| Chemistry | @CO FIBERHMM-CHEMISTRY:v1: |
| Layer list | @CO MA-TYPES:v1:nuc,msp,tf |
| QC and DAF side outputs | qc/ next to the output BAM |
Tag options:
--no-legacy-tags: write onlyMA/AQ, notns/nl/as/al.--downstream-compat: put TF calls intons/nland write noMA/AQ/AN, for tools that read only legacy tags.--scores(alias--with-scores): with--no-recall-nucs, write the HMM posterior mean of each nucleosome asnq.-r/--circular: circular molecules (Annotations).
Outputs are published atomically. The BAM is written and indexed under a temporary name and renamed with its index only when the run succeeds, so a failed or interrupted run leaves no valid-looking partial BAM, and an earlier output at the same path is kept.
Failures inside workers are not silent. A read that raises an error in a worker is written through uncalled and counted. If more than 1% of processed reads fail (any failure when fewer than 100 reads were processed), the run stops with the first tracebacks and writes no output.
fiberhmm-apply: HMM only¶
fiberhmm-apply runs only the HMM (step 2): nucleosome and MSP calls in
ns/nl/as/al, no TF recall, no MA. It is useful for inspecting the
raw HMM, for a staged workflow, or with fiberhmm-recall-tfs/-recall-nucs
afterwards (Re-calling).
Processed 300 reads -> 300 with footprints
BAM: out/apply/hia5_pacbio_footprints.bam
BAM index: out/apply/hia5_pacbio_footprints.bam.bai
-ois an output directory; the BAM is<input stem>_footprints.bam.-o -writes the BAM to stdout.--streamingprocesses unaligned, unindexed or stdin input in a pipeline;-c 0uses every CPU;-c 1(default) runs in one process.- DAF and DddA options match
fiberhmm-call:--daf-mask-runs,--daf-run-policy,--daf-mask-unaligned, and the first-pass CpG mask (--use-m5c/--no-use-m5c,--cpg-mask-policy; on for DddA). - By default
ns/nllist every HMM footprint, which the recall tools need.--harmonize-legacy-tagswritesns/nlas the nucleosomesMAwould hold (footprints outside MSPs), so the legacy tags tile withas/allikefiberhmm-calloutput; each such read carrieshl:i:1, andfiberhmm-recall-tfs/-recall-nucsrefuse it (Re-calling). --scoreswrites posterior-meannq/aq;--no-mspsomitsas/al/aq;--statssamples reads for summary plots (needsfiberhmm[plots]);--output-posteriors FILEalso exports HMM posteriors;-texcludes the read IDs a model was trained on.fiberhmm-applyrecords the same provenance asfiberhmm-call: an@PGline with its resolved settings and aFIBERHMM-CHEMISTRYdeclaration, so recall, extract and QC read the chemistry from its output.--chroms,--skip-scaffolds,--region-size,--scores-dband-lnever had an effect infiberhmm-applyand are rejected; usefiberhmm-call --region-parallelto select regions.
Performance¶
- Use
--region-parallelwith-cset to the cores you have (-c 0= all) on sorted, indexed input; add--skip-scaffoldson assemblies with many small contigs. - Install
samtools: FiberHMM falls back to pysam for sorting, indexing and concatenation, which is slower. - Pipe
-o -intoft fireorsamtoolsto avoid intermediate files. - Numba compiles the HMM kernels when each worker starts, which takes a few seconds; it is negligible on real data sets.
- For long runs, see Long runs and resuming: the resume bookkeeping costs one extra read of the input BAM when the run starts (its SHA-256, at about 2-3 GB/s) and a digest of each region BAM; a resume does not rehash an unchanged input.