Skip to content

pynem

Neighborhood EM (NEM) — clustering that combines the EM algorithm with a hidden Markov random field. Given a graph whose nodes carry feature vectors, NEM produces a partition that accounts for both the data and the spatial structure of the graph. Scikit-learn-style API; NumPy / SciPy / NetworkX, and optionally Numba.

It also faithfully reproduces the partitioning step of PPanGGOLiN (persistent / shell / cloud pangenome partitioning) and adds two original extensions: per-variable weighting (genome redundancy) and a MAG-aware completeness model (genome incompleteness).

Installation

pip install pynem            # core
pip install "pynem[fast]"    # + Numba JIT (sequential E-step)
pip install "pynem[viz]"     # + matplotlib (plotting)

Quick start

import numpy as np, networkx as nx
from pynem import NEM

G = nx.path_graph(100)
X = np.random.default_rng(0).normal(size=(100, 2))

model = NEM(n_clusters=3, beta=1.0, family="normal")
model.fit(X, graph=G)

model.labels_        # hard classification (N,)
model.membership_    # soft classification (N, K)
model.predict(Xnew)  # classify new feature vectors

Pangenome partitioning

from pynem import partition_pangenome

res = partition_pangenome(presence, graph, K=3, beta=2.5)
res["partition"]     # "P" / "S" / "C" per gene family

# correct genome redundancy (weighting) and/or incompleteness (completeness):
w = pynem.genome_weights(presence, selection="silhouette")
res = partition_pangenome(presence, graph, genome_weights=w, completeness="auto")

See the API reference for the full documentation, and the GitHub repository for examples, the maths notes, and the original C implementation.