Skip to main content

NetworkX-backed, Rust-accelerated graphs over genotype-phenotype maps.

Project description

gpgraph-v2

CI PyPI Python License Open in Streamlit

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 of O(N^2 * L).
  • Typed. Full type hints, mypy --strict in CI.
  • Modern tooling. uv + maturin + pyproject.toml. Releases via python-semantic-release. OIDC-based PyPI publishing.
  • Consumes gpmap-v2. Speaks the locked SCHEMA.md contract; reads binary_packed, n_mutations, and phenotypes (not the removed v1 fitnesses).
  • No Cython, no setup.py, no .c blobs.

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-v2 on PyPI; import path is still gpgraph.
  • Construction: use GenotypePhenotypeGraph.from_gpm(gpm, ...). The v1 two-step G = GenotypePhenotypeGraph(); G.add_gpm(gpm) is removed.
  • Reads gpmap-v2 columns: node attribute is phenotypes, not fitnesses.
  • __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_wrapper introspection shim in pyplot/primitives.py is gone. NetworkX is version-pinned to >=3.6.
  • gpgraph.neighbor_functions is renamed gpgraph.neighbors and the pairwise get_neighbors returns a NumPy (E, 2) int64 array 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: ... -> patch
  • feat: ... -> minor
  • feat!: ... or a BREAKING 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gpgraph_v2-1.0.0.tar.gz (23.9 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

gpgraph_v2-1.0.0-cp311-abi3-win_amd64.whl (225.9 kB view details)

Uploaded CPython 3.11+Windows x86-64

gpgraph_v2-1.0.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (396.8 kB view details)

Uploaded CPython 3.11+manylinux: glibc 2.17+ x86-64

gpgraph_v2-1.0.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (390.1 kB view details)

Uploaded CPython 3.11+manylinux: glibc 2.17+ ARM64

gpgraph_v2-1.0.0-cp311-abi3-macosx_11_0_arm64.whl (344.7 kB view details)

Uploaded CPython 3.11+macOS 11.0+ ARM64

gpgraph_v2-1.0.0-cp311-abi3-macosx_10_12_x86_64.whl (353.6 kB view details)

Uploaded CPython 3.11+macOS 10.12+ x86-64

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

Hashes for gpgraph_v2-1.0.0.tar.gz
Algorithm Hash digest
SHA256 8ea62349974b82792b22f7ae963d134c019d84b9e2c387739b40de8a810a7d39
MD5 9291680e51bfa12d396b0a524c6306df
BLAKE2b-256 bb500ba9a32ab335c4dedef0e1b4dbf8431699aebb85f45ef70f74477979832e

See more details on using hashes here.

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

Hashes for gpgraph_v2-1.0.0-cp311-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 c442fbdac8556b474bd812bebb89337b23a528db90718a122f07b8feda07291f
MD5 5a1434750f9103913212c06e82352145
BLAKE2b-256 71f868dcc86f5d2ea0c9bdaed6225378233730a1cd3727916283ce29b0aae153

See more details on using hashes here.

File details

Details for the file gpgraph_v2-1.0.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for gpgraph_v2-1.0.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 a1b16bdefb54614a5a90d23c01d411ee4e3857f38fea0b490776b3d7f2354aa8
MD5 5a77562f387c88e634ec444e8726e2a0
BLAKE2b-256 ec9710bfc64404747bcbef9714b9a615d508d8b46f5c856475bd1fe8b19f94ec

See more details on using hashes here.

File details

Details for the file gpgraph_v2-1.0.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for gpgraph_v2-1.0.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 e4ee3a83739b99c9ea31d50beb4538890f66456a2f9f766c5fef287cfeb8ce48
MD5 27d7b3e4005243a1b8eb6a6f83af4014
BLAKE2b-256 d420a0898a42a6000a6a70b63186876bb8410e532760a74ac944955fc84d09c1

See more details on using hashes here.

File details

Details for the file gpgraph_v2-1.0.0-cp311-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for gpgraph_v2-1.0.0-cp311-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 ac71ab31372dd4cb7585bf8d4d3898993d9e4c54a8e6044ed09ba7ff34fbc674
MD5 6e525dcaf3359d7ec17035d2cc03407a
BLAKE2b-256 db8fbda1d8b0d993a94cefc72c6383024cc5d6473895ddcfa7ba91112016cc3b

See more details on using hashes here.

File details

Details for the file gpgraph_v2-1.0.0-cp311-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for gpgraph_v2-1.0.0-cp311-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 8c2bb6f977bb9cb394f56d902e8f7f8985f17c6f29e73638cc05c9da7b3a8548
MD5 9f6c61945c47a189c4dbac6ed107f75e
BLAKE2b-256 856d25a40026e8ea9a18e2a1a5a2c13bfa86729480bcf0a50596b000739f149b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page