Zero-shot detection and output filtering
For a complete application recipe with matching null, whitening, scale, and calibration artifacts, start with zero-shot detection. This page covers additional modes and output options.
porefm zero-shot detect scores read positions using a unified canonical
reference model and empirical k-mer calibration. It supports cosine and
whitening scores, with the score family selected from calibration metadata
by default. Supply the matching whitening artifact for whitening detection.
Single-file model bundles
Use --model-path RNA004_zero-shot.pt (or --model_path) to provide all
model artifacts in one file. This overrides --canonical_null_model_path,
--calibration_path, and --whitening_artifact, even if those paths are invalid.
Set input, output, filtering, and device options on the detection command.
Create a bundle once from matching artifacts:
porefm utils bundle-model --kind zero-shot \
--canonical_null_model_path scale/model.best \
--calibration_path calibration.pt \
--whitening_artifact whitening.pt \
--output RNA004_zero-shot.pt
porefm zero-shot detect --model-path RNA004_zero-shot.pt \
--bam_path aligned.signal.bam --ref reference.fa \
--motif 'N 0' --output_dir predictions/aligned
Whitening can be omitted when packaging cosine-only detection. The destination
must not exist. A bundle contains all required inference components; the source
files are not needed on the inference machine. Load it with the detection
command, rather than torch.load. Inference verifies component checksums and
extracts temporary files under TMPDIR (or the system temporary directory).
Allow enough disk space for the complete component set; these temporary files
are cleaned up when inference exits.
Detection always writes paired data/meta Parquets, factoring out
repeated read names, chromosomes, and strands. Read these files and
collapse them to reference loci with porefm.outputs.open_output; see the
shared output API for filters, DuckDB, and streamed site summaries.
Optional deterministic execution
Add --deterministic to porefm zero-shot detect to request repeatable
numerical execution for identical inputs, model artifacts, batching, hardware,
and software versions. Compilation remains enabled unless --disable_compile
is also supplied; autocast and matmul precision follow the command settings.
This option enables PyTorch deterministic algorithms, fixes numerically
sensitive compiler kernel choices, disables cuDNN benchmarking, and defaults
CUBLAS_WORKSPACE_CONFIG to :4096:8 when it is unset. PyTorch raises an error
for operations it identifies as lacking a deterministic implementation. The
requested option and effective numerical settings/software versions are
recorded in run_manifest.json under
arguments.deterministic and arguments.numerical_policy.
Deterministic execution can be slower and can produce different scores and p-values from the default policy. It does not retrain the model, refit whitening, or regenerate calibration. When using an existing calibration, assess p-value behavior on canonical controls before relying on thresholds under the selected policy. The option applies only to detection. Identical results across devices, versions, or batch layouts are not guaranteed.
Aligned, reference-based inference
Omit --chrom to process eligible aligned reads across all reference contigs.
Specify --chrom chr1 chr2 to restrict the run. This mode still requires a
reference FASTA and aligned inputs. Signal-BAM input requires coordinate
sorting and indexing; direct BAM + POD5 uses its read-ID index instead (see
input preparation). Motifs/position labels are
reference-based; --motif "N 0" selects all aligned bases without constructing
a genome-wide label dictionary.
porefm zero-shot detect \
--bam_path aligned.signal.bam \
--canonical_null_model_path scale/model.best \
--calibration_path calibration.pt \
--whitening_artifact whitening.pt \
--ref reference.fa \
--motif "N 0" \
--output_dir predictions/aligned
Unaligned or mixed aligned/unaligned samples
Use --read_based (also spelled --read-based). Without --chrom, this
streams BAM records in file order, including unmapped reads, without requiring
a BAM index or reference FASTA. It selects motifs in the called sequence, not
the reference. --motif "N 0" selects every eligible canonical read base; it is
expanded into A/C/G/T motifs per read, not reference-wide arrays.
porefm zero-shot detect \
--bam_path unaligned.signal.bam \
--canonical_null_model_path scale/model.best \
--calibration_path calibration.pt \
--whitening_artifact whitening.pt \
--read_based --motif "N 0" \
--output_dir predictions/read_based
Sequence type, pore chemistry, and k-mer currents come from checkpoint
metadata. Use matching model, whitening, and calibration artifacts. Raw signal
is required, either in SG tags or supplied with --pod5. Move tables are
preferred; supported chemistries can infer chunks when moves are absent.
Ordinary basecalls alone are not sufficient.
readnameand zero-basedread_posidentify observations. Unmapped reads havechrom="*",position=-1, andstrand=-1. Do not group these rows by reference position as though they were genomic sites.- Supplying
--refin read-based mode retains available reference coordinates for aligned reads. Without it, reference positions are unavailable even for mapped records; the BAM contig name/strand may still be recorded. - An explicit
--chromrestricts read-based mode to aligned records on those contigs and requires--ref(plus a coordinate index for signal-BAM input). Omit it to include unmapped reads. Supplying only--refdoes not impose a chromosome filter. - Read-based mode requires
--motifand cannot use--pos_file. Reference- guided polishing requires--refand suitable aligned reads; it is not an unaligned-read operation. - Flag, read-length, quality, valid-kmer, trimming, and score filters
apply.
--max_batches, if supplied, limits the run. “All reads” removes chromosome restriction; it does not disable these filters.
Read-based mode is explicit rather than auto-enabled when --ref is absent,
so an accidentally omitted reference cannot silently change motif semantics.
P-value filtering and peak output
porefm zero-shot detect supports an inclusive p-value
cutoff and optional peak finding. Add these options to an existing inference
command with its usual model, calibration, input, and output paths:
--motif "N 0" --max_pvalue 0.01 --peak_only --prune_radius 5
--max_pvalue Pwrites only finite p-values <= P, with P in [0, 1]. It replaces the raw-distance filter, so explicitly combining it with--min_metricis an error. This option works independently of peak finding and can be used with motif/position selections.--peak_onlyreports local p-value minima after overlapping chunks have been stitched into a read. It requires all-base selection (--motif "N 0") and no--pos_file. It works in both reference-based and read-based modes.--prune_radius Woptionally suppresses weaker qualifying peaks within +/- W read bases, inclusive. For W=5, retained peaks must be at least 6 bases apart. The default, 0, disables pruning; a positive radius requires--peak_only. Distance usesread_pos, not genomic coordinates, including for reverse-strand, spliced, and unmapped reads.
Peak finding uses the original p-values, before applying the chosen output threshold. Each peak or equal-valued plateau must have valid, strictly higher p-values on both sides. Flat peaks use their midpoint rounded down: positions 100--104 select 102, while 100--103 select 101, not 100. Invalid k-mers, unlabelled bases, nonfinite p-values, and missing positions break the profile; their neighboring segment endpoints are not called as peaks. Gaps are never compressed away. Chunk trimming determines available bases.
After peak detection, the selected p-value or raw-distance cutoff is applied. If distance pruning is enabled, qualifying peaks are considered by increasing p-value, with lower read position breaking ties. Each retained peak suppresses its neighbors; suppressed peaks cannot suppress other peaks. Results are written in read-position order with their original scores and p-values. For example, peaks at 100, 104, and 108 with p-values 0.001, 0.002, and 0.003 and radius 5 retain 100 and 108. A smoothly declining shoulder is not a peak.
These options select output rows after scoring and calibration. Without either
threshold, the default distance > 0.0 filter applies. Without --peak_only, all qualifying bases are emitted.
No smoothing or prominence filter is applied. Small secondary peaks can
survive, and distance pruning can merge distinct nearby modifications.
Wider sequence context
Add --output_context_radius 15 to porefm zero-shot detect
to save 31 bases around each retained position:
--motif "N 0" --max_pvalue 0.01 --peak_only --prune_radius 5 \
--output_context_radius 15
The default radius is 0 (disabled).
A positive radius R adds sequence_context and boolean context_complete.
Context works with either output threshold, with or without peak finding,
and with motif/position selections. It adds context to the selected rows
without rescoring them.
Context follows the model-input sequence, in read orientation, including
on reverse-strand reads. With --use_polished_sequence, this is the polished
sequence and its read coordinates, which can differ from original BAM query
offsets. The alphabet is A/C/G/T/N, including T for RNA, consistent with the
k-mer column. The reported base is at zero-based context index R.
Available neighboring bases are included even if they are unlabelled, trimmed
from scoring, or fail the output filter. Overlapping chunks use the same
midpoint stitching as the scores.
Unavailable read flanks or gaps between loaded chunks are padded with N, and
context_complete is false. An observed N counts as available and does not
by itself make context incomplete. No extra BAM/reference lookup is made to
fill gaps; context cannot recover sequence absent from the loaded chunks.
Compact storage and decoding
The default --output_context_format packed stores lossless binary DNA:
two bits per A/C/G/T base plus an N mask only for contexts containing N.
A 31-base context takes 8 bytes, or 12 bytes with an N mask, before
Parquet overhead and compression. The output reader decodes packed contexts
automatically when the column is selected:
from porefm.outputs import open_output
calls = open_output("outputs/zero-shot")
for table in calls.iter_tables(
columns=["readname", "read_pos", "sequence_context", "context_complete"],
reads_per_batch=32,
):
print(table.to_pandas().head())
Use --output_context_format text to store directly readable DNA strings.
Keep the same format and radius across parts of one dataset. See the
output API for filtering and selecting columns without loading
the whole run into memory.