Preprocessing and QC¶
Fragment matrices, peak calling and the qc namespace of quality-control functions.
rustscenic.preproc ¶
scATAC fragment preprocessing.
Public API: rustscenic.preproc.fragments_to_matrix(fragments_path, peaks_path) -> AnnData rustscenic.preproc.call_peaks(fragments_path, cluster_per_barcode, ...) -> pd.DataFrame rustscenic.preproc.qc.insert_size_stats(fragments_path) -> pd.DataFrame rustscenic.preproc.qc.frip(fragments_path, peaks_path) -> pd.Series rustscenic.preproc.qc.tss_enrichment(fragments_path, tss_df) -> pd.Series
All of these are Rust-native and require no extra Python dependencies beyond the four rustscenic ships with (numpy, pandas, pyarrow, scipy).
Together they replace pycisTopic's fragment parsing, iterative peak calling, and per-cell QC - the MACS2-free, Java-free, Python 3.10–3.13 path through rustscenic's ATAC preprocessing surface.
See docs/atac-preprocessing-scope.md for scope + validation plan.
qc ¶
Per-barcode cell QC metrics.
Invocable as a namespace class so users see the grouping in IDE auto-complete and the module docstring lists them at the top. Each method reads the fragments file once and returns a pandas object indexed by barcode.
insert_size_stats
staticmethod
¶
insert_size_stats(fragments_path: str | Path) -> pd.DataFrame
Per-barcode insert-size summary.
Returns DataFrame indexed by barcode with columns:
- mean (float) - mean fragment length
- median (float) - median fragment length
- n_fragments (uint32) - count used in the stats
- sub_nucleosomal (uint32) - fragments < 150 bp
- mono_nucleosomal (uint32) - 150–299 bp
- di_nucleosomal (uint32) - 300–449 bp
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fragments_path
|
str | Path
|
Path to the 10x fragments file used for the per-barcode summaries. |
required |
frip
staticmethod
¶
frip(fragments_path: str | Path, peaks_path: str | Path) -> pd.Series
Per-barcode fraction of reads in peaks.
Returns a pandas Series indexed by barcode. UCSC vs Ensembl chrom conventions are normalised at join time.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fragments_path
|
str | Path
|
Path to the 10x fragments file. |
required |
peaks_path
|
str | Path
|
BED-file path defining the peak intervals used for overlap counts. |
required |
tss_enrichment
staticmethod
¶
tss_enrichment(fragments_path: str | Path, tss: DataFrame) -> pd.Series
Per-barcode TSS enrichment (signal-over-background).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fragments_path
|
str | Path
|
10x fragments file. |
required |
tss
|
DataFrame
|
DataFrame with columns |
required |
Returns:
| Type | Description |
|---|---|
pd.Series indexed by barcode with TSS enrichment scores (0.0 if
|
|
no fragments overlap any TSS window).
|
|
fragments_to_matrix ¶
fragments_to_matrix(
fragments_path: str | Path,
peaks_path: str | Path,
*,
cell_barcodes: list[str] | None = None,
)
Build a cells × peaks AnnData from fragments + peaks.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fragments_path
|
str or Path
|
10x cellranger |
required |
peaks_path
|
str or Path
|
Consensus peak BED (plain or .gz). Uses the first three columns;
column 4 (if present) is stored as |
required |
cell_barcodes
|
list[str] | None
|
Optional cell-called barcode whitelist. When supplied, the Rust parser emits matrix rows only for matching barcodes, avoiding a large all-observed-barcode matrix from raw 10x fragments. |
None
|
Returns:
| Type | Description |
|---|---|
AnnData
|
|
Notes
UCSC (chr1) and Ensembl (1) chrom conventions are matched via
normalise_chrom - a peak BED in either convention joins to
fragments in either convention. Peaks on chroms actually absent
from the fragments file are silently dropped.
call_peaks ¶
call_peaks(
fragments_path: str | Path,
cluster_per_barcode: Series | ndarray | list[int],
*,
n_clusters: int | None = None,
window_size: int = 50,
min_fragments_per_window: int = 3,
quantile_threshold: float = 0.95,
max_gap: int = 250,
peak_half_width: int = 250,
output_bed: str | Path | None = None,
) -> pd.DataFrame
Call iterative consensus peaks from pseudobulked fragments.
Corces-2018-style density-window peak calling: per cluster, tile the genome, threshold at the top-quantile of the cluster's per-window count distribution, merge adjacent significant windows, then union cluster peaks into a consensus set via greedy iterative overlap rejection. No MACS2, no external binaries.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fragments_path
|
str | Path
|
10x cellranger |
required |
cluster_per_barcode
|
Series | ndarray | list[int]
|
Cluster id per barcode (0-indexed). Same length as the fragments'
unique-barcode set - i.e. as what |
required |
n_clusters
|
int | None
|
Number of distinct cluster ids. Defaults to deriving
|
None
|
window_size
|
int
|
See |
50
|
min_fragments_per_window
|
int
|
See |
50
|
quantile_threshold
|
int
|
See |
50
|
max_gap
|
int
|
See |
50
|
peak_half_width
|
int
|
See |
50
|
output_bed
|
str | Path | None
|
If set, write the called peaks as a 4-column BED (chrom, start, end, name) to this path. |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
One row per consensus peak with columns
|