smftools.analysis.compute.dimensionality_reduction#

dimensionality_reduction.py — PCA → UMAP → KNN → Leiden pipeline for per-read matrices.

Functions#

coverage_filter Drop low-coverage columns and rows from a reads × positions matrix. make_features_raw NaN → 0.5 imputation for direct use of modification matrix. make_features_acf Per-read ACF features with optional rolling smoothing. umap_from_pca UMAP embedding from a cached PCA-space matrix; returns (X_umap, fitted model). cluster_from_pca KNN graph + Leiden clustering from a cached PCA-space matrix. run_pipeline PCA → UMAP → KNN graph → Leiden clustering (composes the above); returns (X_pca, X_umap, clusters, explained_variance_ratio, fitted PCA model, fitted UMAP model).

Functions

cluster_from_pca(X_pca[, leiden_resolution, ...])

KNN graph + Leiden clustering from a PCA-space matrix.

coverage_filter(mat, positions, obs_names[, ...])

Drop low-coverage positions (columns) then low-coverage reads (rows).

make_features_acf(mat, pos[, window, max_lag])

Per-read ACF with rolling average smoothing; drop degenerate rows.

make_features_raw(mat)

NaN → 0.5 imputation for raw modification matrix.

run_pipeline(feat[, leiden_resolution, ...])

PCA → UMAP → KNN → Leiden clustering.

umap_from_pca(X_pca[, n_neighbors, random_state])

UMAP embedding from a PCA-space matrix.

smftools.analysis.compute.dimensionality_reduction.coverage_filter(mat, positions, obs_names, group_labels=None, min_col_coverage=0.05, min_row_coverage=0.8)#

Drop low-coverage positions (columns) then low-coverage reads (rows).

Returns (mat, positions, obs_names, group_labels) after filtering.

Return type:

tuple[ndarray, ndarray, list[str], list | None]

smftools.analysis.compute.dimensionality_reduction.make_features_raw(mat)#

NaN → 0.5 imputation for raw modification matrix.

Return type:

ndarray

smftools.analysis.compute.dimensionality_reduction.make_features_acf(mat, pos, window=5, max_lag=1000)#

Per-read ACF with rolling average smoothing; drop degenerate rows.

Return type:

tuple[ndarray, ndarray]

Parameters#

mat : (n_reads × n_positions) float array. pos : TSS-centred int coordinates. window : rolling mean window in lags. max_lag: maximum ACF lag to compute.

Returns#

feat : (n_valid × (max_lag+1)) float — smoothed ACF per valid read valid_mask : bool array of length n_reads (pre-filter)

smftools.analysis.compute.dimensionality_reduction.umap_from_pca(X_pca, n_neighbors=15, random_state=42)#

UMAP embedding from a PCA-space matrix.

Split out of run_pipeline() so a cached X_pca (e.g. pca_space.npy) can be re-embedded with different UMAP parameters without recomputing PCA.

Return type:

tuple[ndarray, UMAP]

Returns#

(X_umap, model) : the 2-D embedding and the fitted UMAP transformer. Call model.transform(new_X_pca) to embed additional points into this exact space later without refitting (see smftools.project.embedding_store for the project-layer wrapper that does this by default when a set grows).

smftools.analysis.compute.dimensionality_reduction.cluster_from_pca(X_pca, leiden_resolution=0.5, n_neighbors=15, random_state=42)#

KNN graph + Leiden clustering from a PCA-space matrix.

Split out of run_pipeline() so a cached X_pca (e.g. pca_space.npy) can be re-clustered at a different leiden_resolution (or n_neighbors) without recomputing PCA/UMAP.

Return type:

ndarray

smftools.analysis.compute.dimensionality_reduction.run_pipeline(feat, leiden_resolution=0.5, min_reads=10, n_neighbors=15, random_state=42)#

PCA → UMAP → KNN → Leiden clustering.

Return type:

tuple[ndarray, ndarray, ndarray, ndarray, PCA, UMAP] | None

Parameters#

feat : (n_reads × n_features) float feature matrix. leiden_resolution : resolution parameter for Leiden community detection. min_reads : return None if fewer reads than this. n_neighbors : number of KNN neighbours for graph construction and UMAP. random_state : seed for reproducibility.

Returns#

(X_pca, X_umap, clusters, explained_variance_ratio, pca_model, umap_model) or None if too few reads. X_pca contains all computed PCs (up to 50) -- cache it to re-derive X_umap/clusters via umap_from_pca()/cluster_from_pca() without recomputing PCA. pca_model/umap_model are the fitted transformers: call pca_model.transform(new_feat) then umap_model.transform(new_X_pca) to embed additional reads into this exact space later without refitting (see smftools.project.embedding_store for the project-layer wrapper that does this by default when a set grows). Leiden clustering has no equivalent incremental transform -- assign new points to the nearest existing point's cluster instead (also handled there).