pub struct FeaturePairGraph {
pub feature_names: Vec<Box<str>>,
pub n_features: usize,
pub feature_edges: Vec<(usize, usize)>,
}Fields§
§feature_names: Vec<Box<str>>§n_features: usize§feature_edges: Vec<(usize, usize)>Implementations§
Source§impl FeaturePairGraph
impl FeaturePairGraph
Sourcepub fn from_edge_list(
file_path: &str,
feature_names: Vec<Box<str>>,
allow_prefix: bool,
delimiter: Option<char>,
) -> Result<Self>
pub fn from_edge_list( file_path: &str, feature_names: Vec<Box<str>>, allow_prefix: bool, delimiter: Option<char>, ) -> Result<Self>
Build a feature-pair graph from an external two-column edge list.
Names are matched against feature_names via
GeneIndexResolver (exact → delimiter-stripped → optional prefix).
Self-loops, duplicates, and edges referencing unknown names are
dropped silently. The resulting feature_edges are canonical
(u < v), unique, and sorted.
Sourcepub fn from_edge_list_canon(
file_path: &str,
feature_names: Vec<Box<str>>,
allow_prefix: bool,
delimiter: Option<char>,
canon: &dyn Fn(&str) -> Box<str>,
) -> Result<Self>
pub fn from_edge_list_canon( file_path: &str, feature_names: Vec<Box<str>>, allow_prefix: bool, delimiter: Option<char>, canon: &dyn Fn(&str) -> Box<str>, ) -> Result<Self>
Like Self::from_edge_list but canonicalizes both the feature
axis names and each edge endpoint through canon before matching.
Lets callers reuse a domain canonicalizer (e.g. FeatureNameKind
that normalizes gene symbols and chrX:start-end loci) so an
edge file with raw names resolves against a canonicalized axis.
The stored feature_names remain the originals.
Sourcepub fn filter_edges(&mut self, keep_indices: &[usize])
pub fn filter_edges(&mut self, keep_indices: &[usize])
Keep only edges at the given indices.
pub fn num_edges(&self) -> usize
pub fn num_features(&self) -> usize
Sourcepub fn feature_degrees(&self) -> Vec<usize>
pub fn feature_degrees(&self) -> Vec<usize>
Per-feature undirected degree from the canonical edge list.
Sourcepub fn build_directed_adjacency(&self) -> Vec<Vec<(usize, usize)>>
pub fn build_directed_adjacency(&self) -> Vec<Vec<(usize, usize)>>
Build directed adjacency: adj[g] = [(neighbor, edge_idx)] where
neighbor > g (so each undirected edge appears once).
Common-neighbor count for each (u, v) in pairs, computed in
parallel via sorted-merge on the CSR rows. O(deg(u) + deg(v))
per pair. Self-loops (u == v) yield deg(u) (correct but
usually meaningless).
Sourcepub fn augment_with_snn(&mut self, min_shared: usize)
pub fn augment_with_snn(&mut self, min_shared: usize)
Augment with shared-neighbor edges: any unordered pair (u, v)
with at least min_shared undirected neighbors in common gains a
synthetic edge (unless one is already present). min_shared = 0
is a no-op. Parallel over the outer node id; sorted-merge
intersection avoids the HashSet rebuild that the old serial
implementation paid per call.
QC prune: drop any edge (u, v) whose endpoints share fewer than
min_shared neighbors in the current graph. Standard PPI
denoising — an edge with no corroborating shared interactor is
likely a noisy hit. min_shared = 0 is a no-op.
Sourcepub fn cap_per_node_degree(&mut self, max_degree: usize)
pub fn cap_per_node_degree(&mut self, max_degree: usize)
Per-node hard cap on degree, ranked by shared-neighbor count.
For each node u with deg(u) > max_degree, sort its neighbors
by |N(u) ∩ N(v)| descending (ties broken by neighbor id) and
keep the top max_degree. Symmetric union — an edge survives iff
either endpoint kept it. max_degree = 0 is a no-op. Used to
cap PPI hubs whose degree would otherwise blow up the per-cell
sub-adjacency cache.
Sourcepub fn prune_by_min_degree(&mut self, min_degree: usize)
pub fn prune_by_min_degree(&mut self, min_degree: usize)
Iterative k-core: drop every feature whose current degree is
< min_degree, then recompute degrees and repeat until the
surviving subgraph is (min_degree)-degenerate. The feature axis
itself is kept the same — only edges incident to pruned features
are removed. min_degree = 0 is a no-op.
Second-order edges: unordered pairs (u, v) NOT directly linked
that share at least min_shared neighbours, with the count. Where
Self::augment_with_snn folds such pairs into the graph
unweighted, this returns them on their own so a caller can treat
“co-interactors” as a relation distinct from “interactors”,
weighted by how many partners they share. Each entry is
(u, v, shared, union) so a caller can weight by the raw count or
by the Jaccard overlap shared / union. top_k > 0 keeps, for
every node, only its top_k co-interactors by Jaccard (ties by
count, then id) — the degree-normalised choice, since on a
scale-free graph a raw count is dominated by the hubs every pair
shares by chance — and a pair survives when either endpoint keeps
it, which bounds the result at n · top_k where “every pair
sharing one neighbour” would be quadratic. min_shared = 0 yields
nothing. Canonical u < v, sorted.
Sourcepub fn personalized_pagerank_top_k(
&self,
alpha: f64,
eps: f64,
k: usize,
) -> Vec<Vec<(usize, f32)>>
pub fn personalized_pagerank_top_k( &self, alpha: f64, eps: f64, k: usize, ) -> Vec<Vec<(usize, f32)>>
Personalized PageRank from every node, truncated to its k
strongest targets (self excluded), by the forward-push
approximation (Andersen, Chung & Lang 2006): random walk with
restart probability alpha on the unweighted graph, residual mass
per node pushed until every residual is below eps · degree. Local
and sparse, so the cost per source is O(1/(eps · alpha))
regardless of graph size; sources run in parallel. Scores are the
PPR mass in (0, 1]; the caller decides how to weight them.
Isolated nodes get an empty list.
Sourcepub fn to_adj_list(&self) -> AdjListGraph
pub fn to_adj_list(&self) -> AdjListGraph
Symmetric adjacency-list view implementing
crate::matrix::graph::WeightedGraph (for Leiden, SGC, etc.).
Auto Trait Implementations§
impl Freeze for FeaturePairGraph
impl RefUnwindSafe for FeaturePairGraph
impl Send for FeaturePairGraph
impl Sync for FeaturePairGraph
impl Unpin for FeaturePairGraph
impl UnsafeUnpin for FeaturePairGraph
impl UnwindSafe for FeaturePairGraph
Blanket Implementations§
impl<T> Allocation for T
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
impl<T> ErasedDestructor for Twhere
T: 'static,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> Pointable for T
impl<T> Pointable for T
impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
Source§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.