NetworkX-backed, Rust-accelerated graphs over genotype-phenotype maps.
Project description
gpgraph-v2
NetworkX-backed, Rust-accelerated graphs over genotype-phenotype maps.
gpgraph-v2 lifts a gpmap-v2 GenotypePhenotypeMap into a
NetworkX DiGraph. Nodes carry the row attributes from the map; edges connect neighbors under
a chosen distance metric (Hamming or codon). Fixation models (SSWM, ratio, Moran, McCandlish)
populate an edge prob attribute for evolutionary trajectory analysis.
This is a clean-break rewrite of harmslab/gpgraph. Hot paths live in Rust via PyO3 + rayon; fixation models stay in vectorized numpy.
Why v2
- Fast. Neighbor detection runs in Rust with rayon parallelism. Biallelic cutoff-1 and
cutoff-2 hit a bit-flip fast path:
O(N * L^cutoff)instead ofO(N^2 * L). - Typed. Full type hints,
mypy --strictin CI. - Modern tooling.
uv+maturin+pyproject.toml. Releases viapython-semantic-release. OIDC-based PyPI publishing. - Consumes gpmap-v2. Speaks the locked
SCHEMA.mdcontract; readsbinary_packed,n_mutations, andphenotypes(not the removed v1fitnesses). - No Cython, no
setup.py, no.cblobs.
Install
pip install gpgraph-v2
Or with uv:
uv add gpgraph-v2
Plotting support is optional. For matplotlib:
pip install "gpgraph-v2[plot]"
Python 3.11+. Prebuilt wheels ship for Linux (x86_64, aarch64), macOS (x86_64, aarch64), and Windows (x64).
Quick start
from gpmap import GenotypePhenotypeMap
from gpgraph import GenotypePhenotypeGraph
gpm = GenotypePhenotypeMap(
wildtype="AAA",
genotypes=["AAA", "AAT", "ATA", "TAA", "ATT", "TAT", "TTA", "TTT"],
phenotypes=[0.1, 0.2, 0.2, 0.6, 0.4, 0.6, 1.0, 1.1],
stdeviations=[0.05] * 8,
)
G = GenotypePhenotypeGraph.from_gpm(gpm)
G.number_of_nodes() # 8
G.number_of_edges() # 24 directed (12 undirected pairs)
G.add_model(column="phenotypes", model="sswm")
G.edges[(0, 1)]["prob"] # SSWM fixation probability from AAA -> AAT
Available fixation models: "sswm", "ratio", "moran", "mcclandish". Pass
population_size=N as a keyword for the last two. Pass any f(fi, fj, **kw) -> float
for a custom model.
Forward paths and flux
from gpgraph.paths import forward_paths_prob, paths_prob_to_edges_flux
G.add_model(column="phenotypes", model="sswm")
paths = forward_paths_prob(G, source=0, target=7)
flux = paths_prob_to_edges_flux(paths)
Plotting
from gpgraph.pyplot import draw_gpgraph, draw_paths
fig, ax = draw_gpgraph(G) # Hamming-weight vertical layout
draw_paths(G, source=0, target=7) # paths flux overlay
Benchmarks
Rust kernels vs a pure-Python pairwise reference. Windows 11, Ryzen, release build.
Run via uv run pytest tests/benchmarks/ --benchmark-only.
| problem | bit-flip (Rust) | pairwise (Rust) | pairwise (Python) |
|---|---|---|---|
| N=256, L=6, cutoff=1 | 77 us | 284 us | 29.3 ms |
| N=1024, L=8, cutoff=1 | 167 us | 1.2 ms | (skipped, minutes) |
At L=6 the Rust bit-flip path is ~380x faster than a naive Python loop. Past N = 1000 on biallelic data the bit-flip specialization pulls away from the rayon-parallel pairwise version by another ~7x.
Dispatch policy (neighbor kernels)
gpgraph.neighbors.get_neighbors chooses the fastest available implementation:
| problem shape | kernel |
|---|---|
user-supplied f(g1, g2, cutoff=...) -> bool |
pure Python O(N^2) |
Hamming, biallelic binary_packed, cutoff <= 2 |
Rust bit-flip (O(N * C(L, cutoff))) |
Hamming, biallelic binary_packed, larger cutoff |
Rust rayon-parallel packed pairwise |
| Hamming, non-binary alphabet | Rust rayon-parallel string pairwise |
| codon | Rust rayon-parallel codon pairwise |
See SCHEMA.md for the full node/edge contract.
Development
git clone https://github.com/lperezmo/gpgraph-v2
cd gpgraph-v2
uv sync
uv run maturin develop --release
uv run pytest
uv run ruff check python/gpgraph tests
After editing Rust:
uv run maturin develop --release && uv run pytest
Consuming from another local project
During co-development with gpmap-v2, point at the local source:
[tool.uv.sources]
gpgraph-v2 = { path = "/absolute/path/to/gpgraph-v2", editable = true }
[project]
dependencies = ["gpgraph-v2"]
Imports remain from gpgraph import GenotypePhenotypeGraph.
Migration from v1 (harmslab/gpgraph)
gpgraph-v2 is not wire-compatible with v1. Key differences:
- Distribution name is
gpgraph-v2on PyPI; import path is stillgpgraph. - Construction: use
GenotypePhenotypeGraph.from_gpm(gpm, ...). The v1 two-stepG = GenotypePhenotypeGraph(); G.add_gpm(gpm)is removed. - Reads gpmap-v2 columns: node attribute is
phenotypes, notfitnesses. __repr__no longer renders a matplotlib figure as a side effect.- Matplotlib is an optional extra (
gpgraph-v2[plot]); the core install is headless. - The
_nx_wrapperintrospection shim inpyplot/primitives.pyis gone. NetworkX is version-pinned to>=3.6. gpgraph.neighbor_functionsis renamedgpgraph.neighborsand the pairwiseget_neighborsreturns a NumPy(E, 2) int64array instead of a list of tuples.- Python 3.11+.
Releases
Releases are driven by python-semantic-release
on merge to main. Commits follow Conventional Commits:
fix: ...-> patchfeat: ...-> minorfeat!: ...or aBREAKING CHANGE:footer -> major
CHANGELOG.md, version bumps, Git tags, GitHub Releases, wheel builds, and PyPI uploads
all happen automatically.
License
MIT. See LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gpgraph_v2-1.0.0.tar.gz.
File metadata
- Download URL: gpgraph_v2-1.0.0.tar.gz
- Upload date:
- Size: 23.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8ea62349974b82792b22f7ae963d134c019d84b9e2c387739b40de8a810a7d39
|
|
| MD5 |
9291680e51bfa12d396b0a524c6306df
|
|
| BLAKE2b-256 |
bb500ba9a32ab335c4dedef0e1b4dbf8431699aebb85f45ef70f74477979832e
|
File details
Details for the file gpgraph_v2-1.0.0-cp311-abi3-win_amd64.whl.
File metadata
- Download URL: gpgraph_v2-1.0.0-cp311-abi3-win_amd64.whl
- Upload date:
- Size: 225.9 kB
- Tags: CPython 3.11+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c442fbdac8556b474bd812bebb89337b23a528db90718a122f07b8feda07291f
|
|
| MD5 |
5a1434750f9103913212c06e82352145
|
|
| BLAKE2b-256 |
71f868dcc86f5d2ea0c9bdaed6225378233730a1cd3727916283ce29b0aae153
|
File details
Details for the file gpgraph_v2-1.0.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: gpgraph_v2-1.0.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 396.8 kB
- Tags: CPython 3.11+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a1b16bdefb54614a5a90d23c01d411ee4e3857f38fea0b490776b3d7f2354aa8
|
|
| MD5 |
5a77562f387c88e634ec444e8726e2a0
|
|
| BLAKE2b-256 |
ec9710bfc64404747bcbef9714b9a615d508d8b46f5c856475bd1fe8b19f94ec
|
File details
Details for the file gpgraph_v2-1.0.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: gpgraph_v2-1.0.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 390.1 kB
- Tags: CPython 3.11+, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e4ee3a83739b99c9ea31d50beb4538890f66456a2f9f766c5fef287cfeb8ce48
|
|
| MD5 |
27d7b3e4005243a1b8eb6a6f83af4014
|
|
| BLAKE2b-256 |
d420a0898a42a6000a6a70b63186876bb8410e532760a74ac944955fc84d09c1
|
File details
Details for the file gpgraph_v2-1.0.0-cp311-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: gpgraph_v2-1.0.0-cp311-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 344.7 kB
- Tags: CPython 3.11+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ac71ab31372dd4cb7585bf8d4d3898993d9e4c54a8e6044ed09ba7ff34fbc674
|
|
| MD5 |
6e525dcaf3359d7ec17035d2cc03407a
|
|
| BLAKE2b-256 |
db8fbda1d8b0d993a94cefc72c6383024cc5d6473895ddcfa7ba91112016cc3b
|
File details
Details for the file gpgraph_v2-1.0.0-cp311-abi3-macosx_10_12_x86_64.whl.
File metadata
- Download URL: gpgraph_v2-1.0.0-cp311-abi3-macosx_10_12_x86_64.whl
- Upload date:
- Size: 353.6 kB
- Tags: CPython 3.11+, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8c2bb6f977bb9cb394f56d902e8f7f8985f17c6f29e73638cc05c9da7b3a8548
|
|
| MD5 |
9f6c61945c47a189c4dbac6ed107f75e
|
|
| BLAKE2b-256 |
856d25a40026e8ea9a18e2a1a5a2c13bfa86729480bcf0a50596b000739f149b
|