History of metanetx_reactions
The changes to the source code of this entry in the repository, newest first, each with the differences it made to the entry's files. They are also listed on GitLab.
[entries] Add the date when each entry was added, and remove icon_hash beff7c9
The dates are those of the commits that first added the entries' files (2020-08-11 for the entries of the initial commit); renamed entries keep the date of their first name. Changed: none
diff --git a/entries/metanetx_reactions/__init__.py b/entries/metanetx_reactions/__init__.py
index ac8aa1a..cf64ab0 100644
--- a/entries/metanetx_reactions/__init__.py
+++ b/entries/metanetx_reactions/__init__.py
@@ -41,7 +41,7 @@ citation = [('S. Moretti, V. D. T. Tran, F. Mehl, M. Ibberson, M. Pagni, "MetaNe
'https://doi.org/10.1093/nar/gkaa992'),
('S. Moretti, O. Martin, T. Van Du Tran, A. Bridge, A. Morgat, M. Pagni, "MetaNetX/MNXref – reconciliation of metabolites and biochemical reactions to bring together genome-scale metabolic networks." Nucleic Acids Research 44, D523-D526 (2016)',
'https://doi.org/10.1093/nar/gkv1117')]
-icon_hash = None
+date_added = '2026-10-31'
# The files of MetaNetX are under CC BY 4.0, but the information taken from
# the external resources (listed in the headers of the files) remains under
# their own terms (e.g. BiGG: educational, research and non-profit use)
[entries] Prefix the properties in the descriptions with (Node), (Edge) or (Graph) bc3dbbd
The lists of properties at the end of the descriptions marked edge properties with "Edge" but left node properties unmarked, or grouped them in "Nodes: `a`, ...; `b`, ..." items, so the kind of a property was often unclear. Every item now starts with (Node), (Edge) or (Graph), followed by the property names, a colon and the explanation, one item per property or group of properties; qualifications (kinds of nodes, networks) follow the names in parentheses. Properties that were only named got a short explanation, and a few items that named the wrong kind of property were corrected.
diff --git a/entries/metanetx_reactions/__init__.py b/entries/metanetx_reactions/__init__.py
index 6346600..ac8aa1a 100644
--- a/entries/metanetx_reactions/__init__.py
+++ b/entries/metanetx_reactions/__init__.py
@@ -25,16 +25,16 @@ There is one network for each release of MNXref, from 1.0 (2013) to 4.5 (2025),
The networks have the following properties:
-- `mnx_id`: the MNXref identifier of the reaction (`MNXR...`) or of the metabolite (`MNXM...`).
-- `is_reaction`: whether the node is a reaction (otherwise it is a metabolite).
-- `name`: the name of the metabolite (empty for reactions, and for metabolites missing from the list of metabolites of the release).
-- `reference`: the source of the identifier, i.e. the first database in which it was found (e.g. `bigg:10FTHF5GLUtl`, `chebi:15378`).
-- `ec`: the EC numbers of the reaction, separated by `;`.
-- `balance`: whether the reaction is balanced (in versions up to 3.2: `true`, `false`, `ambiguous`, `NA` or `redox`; from version 4.0: `B` for balanced, or empty).
-- `is_transport` (versions 4.x): whether the reaction is a transport reaction.
-- `formula`, `charge`, `mass`, `inchikey`: the formula, charge, mass and InChIKey of the metabolite (empty, 0 or NaN if not given; `inchikey` is not given in versions 1.0 and 2.0).
-- Edge `coefficient`: the stoichiometric coefficient of the metabolite, as given (e.g. `1`, `2`, `0.5`, `(n)`, `(n+1)`).
-- Edge `compartment` (versions from 3.0): the generic compartment of the metabolite in the reaction."""
+- (Node) `mnx_id`: the MNXref identifier of the reaction (`MNXR...`) or of the metabolite (`MNXM...`).
+- (Node) `is_reaction`: whether the node is a reaction (otherwise it is a metabolite).
+- (Node) `name`: the name of the metabolite (empty for reactions, and for metabolites missing from the list of metabolites of the release).
+- (Node) `reference`: the source of the identifier, i.e. the first database in which it was found (e.g. `bigg:10FTHF5GLUtl`, `chebi:15378`).
+- (Node) `ec`: the EC numbers of the reaction, separated by `;`.
+- (Node) `balance`: whether the reaction is balanced (in versions up to 3.2: `true`, `false`, `ambiguous`, `NA` or `redox`; from version 4.0: `B` for balanced, or empty).
+- (Node) `is_transport` (versions 4.x): whether the reaction is a transport reaction.
+- (Node) `formula`, `charge`, `mass`, `inchikey`: the formula, charge, mass and InChIKey of the metabolite (empty, 0 or NaN if not given; `inchikey` is not given in versions 1.0 and 2.0).
+- (Edge) `coefficient`: the stoichiometric coefficient of the metabolite, as given (e.g. `1`, `2`, `0.5`, `(n)`, `(n+1)`).
+- (Edge) `compartment` (versions from 3.0): the generic compartment of the metabolite in the reaction."""
tags = ['Biological', 'Metabolic', 'Chemical', 'Unweighted', 'Bipartite', 'Metadata']
url = ['https://www.metanetx.org/', 'https://www.metanetx.org/mnxdoc/mnxref.html']
citation = [('S. Moretti, V. D. T. Tran, F. Mehl, M. Ibberson, M. Pagni, "MetaNetX/MNXref: unified namespace for metabolites and biochemical reactions in the context of metabolic models." Nucleic Acids Research 49, D570-D574 (2021)',
[entries] New entry: metanetx_reactions 9a0b036
diff --git a/entries/metanetx_reactions/__init__.py b/entries/metanetx_reactions/__init__.py
new file mode 100644
index 0000000..6346600
--- /dev/null
+++ b/entries/metanetx_reactions/__init__.py
@@ -0,0 +1,148 @@
+#! /usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2026 Tiago de Paula Peixoto <tiago@skewed.de>
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Affero General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Affero General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+
+from .. import *
+
+title = "MetaNetX/MNXref reconciled metabolic reactions (2013-2025)"
+description = r"""Bipartite networks of metabolic reactions and metabolites from MNXref, the reconciled namespace of metabolites and biochemical reactions of MetaNetX (SIB Swiss Institute of Bioinformatics). MNXref merges the reactions and metabolites of the main metabolic databases and genome-scale models (e.g. BiGG, KEGG, MetaCyc, ModelSEED, Rhea, Reactome, SABIO-RK, ChEBI, HMDB, LipidMaps, SwissLipids), identifying the same metabolites and reactions across them, so that each reaction and each metabolite has a single MNXref identifier (`MNXR...`, `MNXM...`).
+
+There is one network for each release of MNXref, from 1.0 (2013) to 4.5 (2025), named by its version: `1.0`, `2.0`, `3.0`, `3.1`, `3.2`, `4.0`, `4.1`, `4.2`, `4.3`, `4.4` and `4.5`. In each network, an edge goes from each metabolite of the left side of the equation of a reaction, as written by MNXref, to the reaction, and from the reaction to each metabolite of its right side, with the stoichiometric coefficient and, from version 3.0 on, the generic compartment of the metabolite (`MNXD1` and `MNXD2` for the two sides of a membrane in transport reactions, and in versions 3.x also `MNXD3` to `MNXD5`, `MNXDX` and `BOUNDARY`). The direction of the reactions is not given by MNXref (the equations are written with `=`), so the direction of the edges is only that of the written equation. A metabolite that is transported between compartments appears on both sides of a reaction. Pseudo-metabolites of MNXref are kept as nodes, e.g. `BIOMASS`, `WATER` (the solvent, distinct from the water molecule `MNXM2`) and `MNXM01` (a proton that is not balanced). Reactions without participants (e.g. `EMPTY`) are isolated nodes.
+
+The networks have the following properties:
+
+- `mnx_id`: the MNXref identifier of the reaction (`MNXR...`) or of the metabolite (`MNXM...`).
+- `is_reaction`: whether the node is a reaction (otherwise it is a metabolite).
+- `name`: the name of the metabolite (empty for reactions, and for metabolites missing from the list of metabolites of the release).
+- `reference`: the source of the identifier, i.e. the first database in which it was found (e.g. `bigg:10FTHF5GLUtl`, `chebi:15378`).
+- `ec`: the EC numbers of the reaction, separated by `;`.
+- `balance`: whether the reaction is balanced (in versions up to 3.2: `true`, `false`, `ambiguous`, `NA` or `redox`; from version 4.0: `B` for balanced, or empty).
+- `is_transport` (versions 4.x): whether the reaction is a transport reaction.
+- `formula`, `charge`, `mass`, `inchikey`: the formula, charge, mass and InChIKey of the metabolite (empty, 0 or NaN if not given; `inchikey` is not given in versions 1.0 and 2.0).
+- Edge `coefficient`: the stoichiometric coefficient of the metabolite, as given (e.g. `1`, `2`, `0.5`, `(n)`, `(n+1)`).
+- Edge `compartment` (versions from 3.0): the generic compartment of the metabolite in the reaction."""
+tags = ['Biological', 'Metabolic', 'Chemical', 'Unweighted', 'Bipartite', 'Metadata']
+url = ['https://www.metanetx.org/', 'https://www.metanetx.org/mnxdoc/mnxref.html']
+citation = [('S. Moretti, V. D. T. Tran, F. Mehl, M. Ibberson, M. Pagni, "MetaNetX/MNXref: unified namespace for metabolites and biochemical reactions in the context of metabolic models." Nucleic Acids Research 49, D570-D574 (2021)',
+ 'https://doi.org/10.1093/nar/gkaa992'),
+ ('S. Moretti, O. Martin, T. Van Du Tran, A. Bridge, A. Morgat, M. Pagni, "MetaNetX/MNXref – reconciliation of metabolites and biochemical reactions to bring together genome-scale metabolic networks." Nucleic Acids Research 44, D523-D526 (2016)',
+ 'https://doi.org/10.1093/nar/gkv1117')]
+icon_hash = None
+# The files of MetaNetX are under CC BY 4.0, but the information taken from
+# the external resources (listed in the headers of the files) remains under
+# their own terms (e.g. BiGG: educational, research and non-profit use)
+upstream_license = ('Creative Commons Attribution 4.0 International (CC BY 4.0); information from the external resources under their own licenses',
+ 'https://www.metanetx.org/mnxdoc/mnxref.html')
+upstream_prefix = 'https://www.metanetx.org/ftp'
+versions = ["1.0", "2.0", "3.0", "3.1", "3.2", "4.0", "4.1", "4.2", "4.3",
+ "4.4", "4.5"]
+files = [((f"{v}/reac_prop.tsv", f"{v}/chem_prop.tsv"), v, None)
+ for v in versions]
+
+def fetch_upstream(force=False):
+ return fetch_upstream_files(__name__.split(".")[-1], upstream_prefix, files,
+ force)
+
+def rows(f):
+ for l in f:
+ if l.startswith("#"):
+ continue
+ yield l.rstrip("\r\n").split("\t")
+
+@cache_network()
+@coerce_props(eforce={"coefficient": "string"})
+@annotate()
+def parse(alts=None):
+ name = __name__.split(".")[-1]
+ for v in versions:
+ if alts is not None and v not in alts:
+ continue
+ new = v >= "4"
+ vidx = {}
+ rxns = []
+ edges, ecoef, ecomp = [], [], []
+ with open_upstream_file(name, f"{v}/reac_prop.tsv", "r") as f:
+ for r in rows(f):
+ if new:
+ rid, eq, ref, ec, bal, tr = r
+ else:
+ rid, eq, desc, bal, ec, ref = r
+ tr = ""
+ assert rid not in vidx, rid
+ u = vidx[rid] = len(vidx)
+ rxns.append((rid, ref, ec, bal, tr == "T"))
+ left, right = eq.split(" = ") if eq.strip() != "=" else ("", "")
+ for side, terms in enumerate((left, right)):
+ terms = terms.strip()
+ if not terms:
+ continue
+ for t in terms.split(" + "):
+ c, m = t.split(" ")
+ m, _, comp = m.partition("@")
+ assert m and (comp or v < "3"), (rid, t)
+ w = vidx.get(m)
+ if w is None:
+ w = vidx[m] = len(vidx)
+ edges.append((w, u) if side == 0 else (u, w))
+ ecoef.append(c)
+ ecomp.append(comp)
+ mets = {}
+ with open_upstream_file(name, f"{v}/chem_prop.tsv", "r") as f:
+ for r in rows(f):
+ if r[0] not in vidx or r[0] in mets:
+ continue
+ if new:
+ mets[r[0]] = (r[1], r[2], r[3], r[4], r[5], r[7])
+ else:
+ r += [""] * (9 - len(r))
+ mets[r[0]] = (r[1], r[7], r[2], r[3], r[4], r[8])
+
+ g = Graph(directed=True)
+ N = len(vidx)
+ g.add_vertex(N)
+ g.add_edge_list(numpy.array(edges, dtype="int64").reshape(-1, 2))
+ ids = list(vidx.keys())
+ rinfo = {r[0]: r for r in rxns}
+ is_r = [i in rinfo for i in ids]
+ g.vp.mnx_id = g.new_vp("string", vals=ids)
+ g.vp.is_reaction = g.new_vp("bool", vals=is_r)
+ mi = [mets.get(i, ("", "", "", "", "", "")) for i in ids]
+ g.vp.name = g.new_vp("string", vals=[m[0] for m in mi])
+ g.vp.reference = g.new_vp("string", vals=[rinfo[i][1] if r else m[1]
+ for i, r, m in zip(ids, is_r, mi)])
+ g.vp.ec = g.new_vp("string", vals=[rinfo[i][2] if r else ""
+ for i, r in zip(ids, is_r)])
+ g.vp.balance = g.new_vp("string", vals=[rinfo[i][3] if r else ""
+ for i, r in zip(ids, is_r)])
+ if new:
+ g.vp.is_transport = g.new_vp("bool", vals=[rinfo[i][4] if r else False
+ for i, r in zip(ids, is_r)])
+ def num(x, t):
+ try:
+ return t(x)
+ except ValueError:
+ return t("nan") if t is float else 0
+ g.vp.formula = g.new_vp("string", vals=[m[2] for m in mi])
+ g.vp.charge = g.new_vp("int", vals=[num(m[3], int) for m in mi])
+ g.vp.mass = g.new_vp("double", vals=[num(m[4], float) for m in mi])
+ if v >= "3":
+ g.vp.inchikey = g.new_vp("string", vals=[m[5].removeprefix("InChIKey=")
+ for m in mi])
+ g.ep.coefficient = g.new_ep("string", vals=ecoef)
+ if v >= "3":
+ g.ep.compartment = g.new_ep("string", vals=ecomp)
+ yield v, g