History of monarch_kg
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/monarch_kg/__init__.py b/entries/monarch_kg/__init__.py
index c920821..b95a4ab 100644
--- a/entries/monarch_kg/__init__.py
+++ b/entries/monarch_kg/__init__.py
@@ -56,7 +56,7 @@ url = ['https://monarchinitiative.org/',
'https://data.monarchinitiative.org/monarch-kg/']
citation = [('T. A. Putman et al., "The Monarch Initiative in 2024: an analytic platform integrating phenotypes, genes and diseases across species." Nucleic Acids Research 52, D938-D949 (2024)',
'https://doi.org/10.1093/nar/gkad1082')]
-icon_hash = None
+date_added = '2026-10-28'
upstream_license = ("CC BY 4.0 (the integrated sources keep their own licenses)",
"https://creativecommons.org/licenses/by/4.0/")
upstream_prefix = 'https://data.monarchinitiative.org/monarch-kg'
[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/monarch_kg/__init__.py b/entries/monarch_kg/__init__.py
index 62363db..c920821 100644
--- a/entries/monarch_kg/__init__.py
+++ b/entries/monarch_kg/__init__.py
@@ -37,20 +37,20 @@ Left out are the qualifiers of the edges (e.g. the frequency, onset or sex of a
The networks have the following properties:
-- `id`: the identifier of the entity, as a compact URI, e.g. `HGNC:11998` (the human gene TP53), `MONDO:0007254` (breast cancer), `HP:0001250` (seizure).
-- `category`: the Biolink category of the entity, e.g. `biolink:Gene`, `biolink:Disease`, `biolink:PhenotypicFeature`.
-- `name`: the name of the entity (empty if none).
-- `symbol`: the symbol of the gene (empty for other entities and if none).
-- `taxon`: the NCBI taxonomy identifier of the species of the entity, e.g. `NCBITaxon:9606` (empty if none).
-- `taxon_label`: the name of the species, e.g. `Homo sapiens` (empty if none).
-- Edge `predicate`: the Biolink predicate of the association, e.g. `biolink:has_phenotype`, `biolink:causes`, `biolink:interacts_with`.
-- Edge `category`: the Biolink category of the association, e.g. `biolink:GeneToPhenotypicFeatureAssociation`.
-- Edge `primary_knowledge_source`: the original source of the association, e.g. `infores:omim`, `infores:string`.
-- Edge `knowledge_level`: e.g. `knowledge_assertion`, `predicated` or `not_provided` (empty in releases without it).
-- Edge `agent_type`: the kind of agent that made the assertion, e.g. `manual_agent`, `automated_agent` (empty in releases without it).
-- Edge `negated`: whether the association is negated (e.g. a gene that does *not* have a phenotype).
-- `release` (graph): the date of the release.
-- `dangling_nodes` (graph): the number of nodes that appear in edges but not in the list of nodes of the release (they have only an `id`)."""
+- (Node) `id`: the identifier of the entity, as a compact URI, e.g. `HGNC:11998` (the human gene TP53), `MONDO:0007254` (breast cancer), `HP:0001250` (seizure).
+- (Node) `category`: the Biolink category of the entity, e.g. `biolink:Gene`, `biolink:Disease`, `biolink:PhenotypicFeature`.
+- (Node) `name`: the name of the entity (empty if none).
+- (Node) `symbol`: the symbol of the gene (empty for other entities and if none).
+- (Node) `taxon`: the NCBI taxonomy identifier of the species of the entity, e.g. `NCBITaxon:9606` (empty if none).
+- (Node) `taxon_label`: the name of the species, e.g. `Homo sapiens` (empty if none).
+- (Edge) `predicate`: the Biolink predicate of the association, e.g. `biolink:has_phenotype`, `biolink:causes`, `biolink:interacts_with`.
+- (Edge) `category`: the Biolink category of the association, e.g. `biolink:GeneToPhenotypicFeatureAssociation`.
+- (Edge) `primary_knowledge_source`: the original source of the association, e.g. `infores:omim`, `infores:string`.
+- (Edge) `knowledge_level`: e.g. `knowledge_assertion`, `predicated` or `not_provided` (empty in releases without it).
+- (Edge) `agent_type`: the kind of agent that made the assertion, e.g. `manual_agent`, `automated_agent` (empty in releases without it).
+- (Edge) `negated`: whether the association is negated (e.g. a gene that does *not* have a phenotype).
+- (Node) `release` (graph): the date of the release.
+- (Node) `dangling_nodes` (graph): the number of nodes that appear in edges but not in the list of nodes of the release (they have only an `id`)."""
tags = ['Biological', 'Informational', 'Unweighted', 'Multigraph', 'Metadata']
url = ['https://monarchinitiative.org/',
'https://data.monarchinitiative.org/monarch-kg/']
[entries] Remove unneeded code from the entries 2c69f19
Unneeded "global files" statements, unused imports and variables, f-strings without placeholders, duplicate keys in foodweb_little_rock (keeping the order and the values used), and the second definition of get_lines() in twitter_higgs. Nothing changes in the networks or descriptions. Changed: none
diff --git a/entries/monarch_kg/__init__.py b/entries/monarch_kg/__init__.py
index aae1730..62363db 100644
--- a/entries/monarch_kg/__init__.py
+++ b/entries/monarch_kg/__init__.py
@@ -147,7 +147,7 @@ def parse(alts=None):
g.add_vertex(len(allids))
g.add_edge_list(numpy.column_stack([s, t]))
del s, t
- N, D = len(ids), len(dangling)
+ D = len(dangling)
g.vp.id = g.new_vp("string", vals=allids.to_pylist())
del allids, ids
for k, c in (("category", "category"), ("name", "name"),
[entries] New entry: monarch_kg bc61951
diff --git a/entries/monarch_kg/__init__.py b/entries/monarch_kg/__init__.py
new file mode 100644
index 0000000..aae1730
--- /dev/null
+++ b/entries/monarch_kg/__init__.py
@@ -0,0 +1,170 @@
+#! /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/>.
+
+import pyarrow
+import pyarrow.csv
+import pyarrow.compute as pc
+
+from .. import *
+
+title = "Monarch Initiative knowledge graph (2023-2026)"
+description = r"""The knowledge graph of the Monarch Initiative, which integrates data on genes, diseases and phenotypes across species, for the study of genetic diseases and model organisms. Nodes are biological entities of many kinds, given by their Biolink Model category, e.g. genes (of human and of model organisms such as mouse, rat, zebrafish, fruit fly, *C. elegans*, yeast), diseases (Mondo Disease Ontology), phenotypes (Human Phenotype Ontology and the phenotype ontologies of other species), genotypes, variants, anatomical entities, cell types, biological processes, molecular functions and cellular components (Gene Ontology), pathways (Reactome), chemicals and publications. A directed edge is an association between two entities with a Biolink predicate, e.g. a gene `has_phenotype` a phenotype, a gene `causes` a disease, a gene is `orthologous_to` another, a gene `interacts_with` another (STRING, BioGRID and other interaction databases), a gene `expressed_in` an anatomical entity, a term `subclass_of` a more general term of an ontology. The data are integrated from dozens of sources (e.g. the Alliance of Genome Resources, OMIM, Orphanet, ClinVar, ClinGen, HPO annotations, Gene Ontology annotations, PANTHER, Reactome, STRING, BioGRID, the PHENIO ontology), and both nodes and edges are normalized to common identifiers.
+
+The Monarch knowledge graph is released monthly. One release per year is included, the first of each year (from the first release in the current format, of September 2023), and the latest one:
+
+- `2023-09-28`: 830,288 nodes and 8,076,791 edges (according to its statistics),
+- `2024-01-13`,
+- `2025-01-15`,
+- `2026-01-11`,
+- `2026-10-07`: 1,670,861 nodes and 16,433,147 edges.
+
+Left out are the qualifiers of the edges (e.g. the frequency, onset or sex of a phenotype in a disease, the species or disease context), their supporting publications and evidence codes, and the synonyms, cross-references and descriptions of the nodes.
+
+The networks have the following properties:
+
+- `id`: the identifier of the entity, as a compact URI, e.g. `HGNC:11998` (the human gene TP53), `MONDO:0007254` (breast cancer), `HP:0001250` (seizure).
+- `category`: the Biolink category of the entity, e.g. `biolink:Gene`, `biolink:Disease`, `biolink:PhenotypicFeature`.
+- `name`: the name of the entity (empty if none).
+- `symbol`: the symbol of the gene (empty for other entities and if none).
+- `taxon`: the NCBI taxonomy identifier of the species of the entity, e.g. `NCBITaxon:9606` (empty if none).
+- `taxon_label`: the name of the species, e.g. `Homo sapiens` (empty if none).
+- Edge `predicate`: the Biolink predicate of the association, e.g. `biolink:has_phenotype`, `biolink:causes`, `biolink:interacts_with`.
+- Edge `category`: the Biolink category of the association, e.g. `biolink:GeneToPhenotypicFeatureAssociation`.
+- Edge `primary_knowledge_source`: the original source of the association, e.g. `infores:omim`, `infores:string`.
+- Edge `knowledge_level`: e.g. `knowledge_assertion`, `predicated` or `not_provided` (empty in releases without it).
+- Edge `agent_type`: the kind of agent that made the assertion, e.g. `manual_agent`, `automated_agent` (empty in releases without it).
+- Edge `negated`: whether the association is negated (e.g. a gene that does *not* have a phenotype).
+- `release` (graph): the date of the release.
+- `dangling_nodes` (graph): the number of nodes that appear in edges but not in the list of nodes of the release (they have only an `id`)."""
+tags = ['Biological', 'Informational', 'Unweighted', 'Multigraph', 'Metadata']
+url = ['https://monarchinitiative.org/',
+ 'https://data.monarchinitiative.org/monarch-kg/']
+citation = [('T. A. Putman et al., "The Monarch Initiative in 2024: an analytic platform integrating phenotypes, genes and diseases across species." Nucleic Acids Research 52, D938-D949 (2024)',
+ 'https://doi.org/10.1093/nar/gkad1082')]
+icon_hash = None
+upstream_license = ("CC BY 4.0 (the integrated sources keep their own licenses)",
+ "https://creativecommons.org/licenses/by/4.0/")
+upstream_prefix = 'https://data.monarchinitiative.org/monarch-kg'
+# Dated release directories (published once); one release per year and the
+# latest one at the time of writing
+RELEASES = ["2023-09-28", "2024-01-13", "2025-01-15", "2026-01-11", "2026-10-07"]
+files = [((f"{r}/monarch-kg.tar.gz:monarch-kg_nodes.tsv",
+ f"{r}/monarch-kg.tar.gz:monarch-kg_edges.tsv"), r, None)
+ for r in RELEASES]
+
+def fetch_upstream(force=False):
+ return fetch_upstream_files(__name__.split(".")[-1], upstream_prefix, files,
+ force)
+
+# For checks only: if set, only (about) this many edges are read
+_check_rows = None
+
+def read_tsv(f, cols, max_rows=None):
+ """The columns `cols` of the KGX TSV file `f` (missing columns are empty),
+ or of its first `max_rows` rows (about)."""
+ bad = [0]
+ def skip(row):
+ bad[0] += 1
+ return "skip"
+ read = pyarrow.csv.read_csv if max_rows is None else pyarrow.csv.open_csv
+ t = read(
+ f,
+ read_options=pyarrow.csv.ReadOptions(block_size=1 << 26),
+ parse_options=pyarrow.csv.ParseOptions(delimiter="\t", quote_char=False,
+ double_quote=False,
+ invalid_row_handler=skip),
+ convert_options=pyarrow.csv.ConvertOptions(
+ include_columns=cols, include_missing_columns=True,
+ column_types={c: pyarrow.string() for c in cols},
+ strings_can_be_null=False))
+ if max_rows is not None:
+ batches, n = [], 0
+ for b in t:
+ batches.append(b)
+ n += b.num_rows
+ if n >= max_rows:
+ break
+ t = pyarrow.Table.from_batches(batches)
+ return t, bad[0]
+
+def categorical_ep(g, values, name):
+ """Store the string column `values` as the string edge property `name`,
+ converted from integer codes (one Python string per distinct value)."""
+ d = values.fill_null("").combine_chunks().dictionary_encode()
+ codes = g.new_ep("int", vals=d.indices.to_numpy())
+ labels = d.dictionary.to_pylist()
+ p = g.new_ep("string")
+ map_property_values(codes, p, lambda i: labels[i])
+ g.ep[name] = p
+
+@cache_network()
+@coerce_props()
+@annotate()
+def parse(alts=None):
+ name = __name__.split(".")[-1]
+ for fnames, alt, fmt in files:
+ if alts is not None and alt not in alts:
+ continue
+ ncols = ["id", "category", "name", "symbol", "in_taxon", "in_taxon_label"]
+ with open_upstream_file(name, fnames[0], "rb") as f:
+ nodes, nbad = read_tsv(f, ncols)
+ assert nbad == 0, nbad
+ ecols = ["subject", "predicate", "object", "category",
+ "primary_knowledge_source", "knowledge_level", "agent_type",
+ "negated"]
+ with open_upstream_file(name, fnames[1], "rb") as f:
+ edges, ebad = read_tsv(f, ecols, _check_rows)
+ assert ebad == 0, ebad
+
+ ids = nodes.column("id").combine_chunks()
+ assert len(pc.unique(ids)) == len(ids)
+ # the columns are freed as they are used
+ edges = {c: edges.column(c) for c in ecols}
+ ends = pyarrow.chunked_array(edges["subject"].chunks +
+ edges["object"].chunks)
+ dangling = pc.unique(pc.filter(ends, pc.invert(pc.is_in(ends, value_set=ids))))
+ del ends
+ allids = pyarrow.concat_arrays([ids, dangling.cast(ids.type)])
+ s = pc.index_in(edges.pop("subject"), value_set=allids).to_numpy()
+ t = pc.index_in(edges.pop("object"), value_set=allids).to_numpy()
+
+ g = Graph(directed=True)
+ g.add_vertex(len(allids))
+ g.add_edge_list(numpy.column_stack([s, t]))
+ del s, t
+ N, D = len(ids), len(dangling)
+ g.vp.id = g.new_vp("string", vals=allids.to_pylist())
+ del allids, ids
+ for k, c in (("category", "category"), ("name", "name"),
+ ("symbol", "symbol"), ("taxon", "in_taxon"),
+ ("taxon_label", "in_taxon_label")):
+ g.vp[k] = g.new_vp("string",
+ vals=nodes.column(c).fill_null("").to_pylist() + [""] * D)
+ del nodes
+ neg = pc.is_in(pc.utf8_lower(edges.pop("negated").fill_null("")),
+ value_set=pyarrow.array(["true", "t", "1"]))
+ g.ep.negated = g.new_ep("bool", vals=neg.to_numpy(zero_copy_only=False))
+ del neg
+ for k in ("predicate", "category", "primary_knowledge_source",
+ "knowledge_level", "agent_type"):
+ categorical_ep(g, edges.pop(k), k)
+ pyarrow.default_memory_pool().release_unused()
+ del edges
+ g.gp.release = g.new_gp("string", val=alt)
+ g.gp.dangling_nodes = g.new_gp("int64_t", val=D)
+ yield alt, g