Skip to main content

Metabolic neighborhood visualization for COBRApy genome-scale models

Project description

PyPyrus Map

DOI PyPI

Metabolic neighborhood visualization for COBRApy genome-scale models.

PyPyrus Map lets you instantly visualize the full reaction neighborhood of any metabolite in a COBRApy-compatible genome-scale model — including heterologous and non-native pathways that curated databases like Escher cannot represent. Output is publication-quality vector figures (SVG, PDF) suitable for direct journal submission.


Why PyPyrus Map exists

PyPyrus Map was built out of a concrete research problem during Project Menhed, an in silico metabolic engineering effort to optimize lycopene production across multiple chassis organisms. When working with heterologous carotenoid biosynthesis pathways, standard tools like Escher were limited to pre-drawn maps — they could not show the neighborhood of a non-native intermediate like GGPP or Phytoene, making it difficult to quickly identify overexpression and knockout targets.

The need was simple: given a metabolite of interest, show every reaction that produces or consumes it, who the other substrates and products are, and — when an FBA solution is available — what the flux through each reaction looks like. PyPyrus Map was written to answer that question in one function call.


Installation

Step 1: Install PyPyrus Map:

pip install pypyrus-map

Step 2: Install Graphviz (required for layout="dot"):

# Ubuntu / Debian 
apt-get install graphviz

# macOS
brew install graphviz

# Windows
# Download and run the installer from https://graphviz.org/download/
# During installation, tick "Add Graphviz to system PATH"
# Then restart your terminal

Quick start

import cobra
from pypyrus_map import PyPyrusMap

# Load any COBRApy-compatible genome-scale model
model = cobra.io.load_model("iML1515")
solution = model.optimize()

# Create a session and explore a metabolite neighborhood
session = PyPyrusMap(model, solution=solution)
session.add("ipdp_c")

fig = session.render(title="IPP Neighborhood")
fig.show()

# Export publication-quality vector figures
session.export("ipdp_neighborhood.svg")
session.export("ipdp_neighborhood.pdf")

Chaining metabolites

PyPyrus Map is designed for pathway chains. Call .add() multiple times to build up a connected pathway graph — shared nodes are never duplicated.

session = PyPyrusMap(model, solution=solution)

# Build a carotenoid biosynthesis chain
session.add("ipdp_c")   # IPP neighborhood
session.add("frdp_c")   # FPP neighborhood 

fig = session.render(
    title="Isoprenoid Pathway — IPP → FPP",
)
session.export("isoprenoid_chain.svg")

When you call session.add("frdp_c"), PyPyrus Map queries FPP's full depth-1 neighborhood and merges it into the existing graph. Any node already present is promoted to anchor status rather than duplicated.


Visualization options

fig = session.render(
    layout="dot",              # 'dot' (default) | 'spring' | 'circular'
    orientation="landscape",   # 'landscape' (default) | 'portrait'
    figsize=None,              # auto-sized from node count; override with (width, height)
    title=None,                # auto-generated from anchor IDs if None
    label_mode="id",           # 'id' (default) | 'truncate' | 'full'
    show_flux_labels=False,    # show flux values on edge midpoints
    show_stoichiometry=False,  # show stoichiometric coefficients on edges
    flux_filter="all",         # 'all' (default) | 'active' | 'blocked'
    scale_edge_width=False,    # scale arrow width proportionally to |flux|
    legend_loc="upper left",   # any Matplotlib legend location string
    dpi=110,                   # screen resolution; SVG/PDF always lossless
    font_family="DejaVu Sans", # 'Arial' matches Nature/Cell/Science guidelines
)

Label modes

Mode Shows Best for
"id" BiGG ID (e.g. ggpp_c) Default — compact, unambiguous
"truncate" Human name, max 20 chars Readable without overlap
"full" Full human name Presentations, wide figures

Visual encoding

Element Meaning
Deep blue square Focal metabolite (anchor)
Sky blue square Neighbor metabolite
Amber diamond Reaction
Teal-green arrow Produces (reaction → metabolite)
Magenta-pink arrow Consumes (metabolite → reaction)
Double-headed arrow Reversible reaction
Colored arrow with black outline Edge through a blocked reaction
Thicker arrow Higher flux magnitude (when scale_edge_width=True)

Flux filtering

When a cobra.Solution is attached, you can restrict the rendered graph to only the reactions you care about using flux_filter:

# Default — show all reactions regardless of flux
session.render(flux_filter="all")

# Show only reactions carrying non-zero flux
session.render(flux_filter="active")

# Show only completely blocked reactions (flux ≈ 0)
session.render(flux_filter="blocked")

After filtering, any metabolite nodes that become isolated (no remaining reaction connections) are automatically removed from the canvas.

Note: flux_filter has no effect if no cobra.Solution was passed at session construction. A UserWarning is emitted and all reactions are shown.


Flux overlay

When a cobra.Solution is passed at session construction, flux values are attached to each reaction node. Blocked reactions (flux ≈ 0) are visually distinguished by a thick black border on the reaction diamond and a black outline on their connecting arrows.

solution = model.optimize()
session = PyPyrusMap(model, solution=solution)
session.add("ggpp_c")

# Show flux values on edges
fig = session.render(show_flux_labels=True)

# Scale arrow width proportionally to |flux| — thicker = more flux
fig = session.render(scale_edge_width=True)

# Power combo: active reactions only, width and labels by flux
fig = session.render(
    flux_filter="active",
    scale_edge_width=True,
    show_flux_labels=True,
)

When scale_edge_width=True, widths are normalised across all reactions in the current graph: the highest-flux reaction always gets the fattest arrow, near-zero reactions get a hairline. This has no effect if no solution is attached.


Currency metabolite suppression

High-connectivity cofactors (ATP, NADH, H₂O, CoA, Pi, etc.) connect nearly every reaction in the model to every other. By default, PyPyrus Map suppresses these from neighbor nodes to keep figures clean. The focal metabolite is always shown regardless.

# Default: currency suppressed
session = PyPyrusMap(model)

# Show everything including currency metabolites
session = PyPyrusMap(model, suppress_currency=False)

# Custom currency list
my_currency = frozenset({"h_c", "h_e", "atp_c", "adp_c"})
session = PyPyrusMap(model, custom_currency_ids=my_currency)

The default currency ID list is available as pypyrus_map.DEFAULT_CURRENCY_IDS and follows the conventions of Huss & Holme (2007) and KEGG RPAIR.


Error handling

PyPyrus Map uses strict BiGG IDs — no fuzzy matching. If an ID is not found, a clear error is raised with prefix-matched candidate suggestions:

from pypyrus_map import MetaboliteNotFoundError

try:
    session.add("ggpp_m")   # wrong compartment
except MetaboliteNotFoundError as e:
    print(e)
# MetaboliteNotFoundError: 'ggpp_m' not found in model.
# Did you mean: ggpp_c?

Session API

PyPyrusMap(model, solution=None, suppress_currency=True, custom_currency_ids=None)

Parameter Type Default Description
model cobra.Model required Any COBRApy-compatible genome-scale model
solution cobra.Solution None FBA solution — enables flux overlay
suppress_currency bool True Suppress high-connectivity cofactors from neighbor nodes
custom_currency_ids frozenset[str] None Replace the default currency list entirely

Session methods

Method Returns Description
session.add(metabolite_id) self Add a metabolite neighborhood. Chainable.
session.remove(metabolite_id) self Remove a metabolite and its orphaned reactions. Chainable.
session.clear() self Reset the session graph entirely.
session.render(**kwargs) Figure Render and return a Matplotlib figure.
session.export(path, dpi=300) Path Save figure to SVG, PDF, PNG, or TIFF.
session.build() PathwayGraph Return the raw graph object for custom processing.
session.summary() str Print a text summary of current session state.

Development

git clone https://github.com/NoureldenRihan/PyPyrus-Map.git
cd PyPyrus-Map
pip install -e ".[dev]"
pytest tests/ -v

Citing PyPyrus Map

If PyPyrus Map contributes to a published work, please cite:

Rihan, N. PyPyrus Map: Metabolic neighborhood visualization for COBRApy genome-scale models. (2026). DOI: 10.5281/zenodo.18870982

@software{rihan_2026_pypyrus_map,
  author    = {Rihan, Nourelden},
  title     = {PyPyrus Map: Metabolic neighborhood visualization for COBRApy genome-scale models},
  year      = {2026},
  publisher = {Zenodo},
  doi       = {10.5281/zenodo.18870982},
  url       = {https://doi.org/10.5281/zenodo.18870982}
}

Acknowledgements

PyPyrus Map was developed with the assistance of Claude (Anthropic), a large language model used for code generation and implementation. All research direction, architectural decisions, feature design, and validation were conceived and directed by the author.

PyPyrus Map was built as part of Project Menhed, an in silico metabolic engineering initiative targeting lycopene biosynthesis optimization.


License

MIT License — Copyright (c) 2026 Nourelden Rihan. See LICENSE for details.

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

pypyrus_map-0.1.3.tar.gz (30.6 kB view details)

Uploaded Source

Built Distribution

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

pypyrus_map-0.1.3-py3-none-any.whl (27.5 kB view details)

Uploaded Python 3

File details

Details for the file pypyrus_map-0.1.3.tar.gz.

File metadata

  • Download URL: pypyrus_map-0.1.3.tar.gz
  • Upload date:
  • Size: 30.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.4

File hashes

Hashes for pypyrus_map-0.1.3.tar.gz
Algorithm Hash digest
SHA256 deb6a55094c9b8548a991a999ff0365c070c0cc5cab86d7a266f95c354ca26f2
MD5 e66ae6f2408e8c3526a971b285368796
BLAKE2b-256 da73c7a22f0d1c48652e4c797397577a12c31e8e08f6780a2d6dee119f4e28cf

See more details on using hashes here.

File details

Details for the file pypyrus_map-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: pypyrus_map-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 27.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.4

File hashes

Hashes for pypyrus_map-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 d5a557286d1b9badd63c0c3d144359a3542c142bfd4dfbd49a97a3355b394c4a
MD5 73d53b68c1c32f88b1e4a6c501b45c47
BLAKE2b-256 df3dd6cc38f8842d7790aa01249293db2a7aec7b99f745b0ecb476e494dcc714

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