History of ogbl_biokg
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/ogbl_biokg/__init__.py b/entries/ogbl_biokg/__init__.py
index 9e2291a..6cb7e57 100644
--- a/entries/ogbl_biokg/__init__.py
+++ b/entries/ogbl_biokg/__init__.py
@@ -39,7 +39,7 @@ url = ['https://ogb.stanford.edu/docs/linkprop/#ogbl-biokg',
'https://snap.stanford.edu/ogb/data/']
citation = [('W. Hu, M. Fey, M. Zitnik, Y. Dong, H. Ren, B. Liu, M. Catasta, J. Leskovec, "Open Graph Benchmark: Datasets for Machine Learning on Graphs." Advances in Neural Information Processing Systems 33, 22118-22133 (2020)', 'https://doi.org/10.48550/arXiv.2005.00687'),
('B. Walsh, S. K. Mohamed, V. Nováček, "BioKG: A Knowledge Graph for Relational Learning On Biological Data." Proceedings of the 29th ACM International Conference on Information & Knowledge Management (CIKM), 3173-3180 (2020)', 'https://doi.org/10.1145/3340531.3412776')]
-icon_hash = None
+date_added = '2026-10-31'
upstream_license = ('CC0 1.0', 'https://creativecommons.org/publicdomain/zero/1.0/')
upstream_prefix = 'https://snap.stanford.edu/ogb/data'
z = 'linkproppred/biokg.zip:biokg'
[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/ogbl_biokg/__init__.py b/entries/ogbl_biokg/__init__.py
index f7d2a5a..9e2291a 100644
--- a/entries/ogbl_biokg/__init__.py
+++ b/entries/ogbl_biokg/__init__.py
@@ -30,10 +30,10 @@ The triples are split at random into the training (4,762,678), validation (162,8
The network has the following properties:
-- `kind`: the type of the entity: `disease`, `protein`, `drug`, `sideeffect` or `function`.
-- `entity_id`: the identifier of the entity: a UMLS concept identifier for diseases and side effects, an NCBI Gene (Entrez) identifier for proteins, a STITCH compound identifier for drugs, a Gene Ontology identifier for functions.
-- Edge `relation`: the relation of the triple, e.g. `drug-protein`, `protein-protein_binding`.
-- Edge `split`: the set of the triple in the benchmark: `train`, `valid` or `test`."""
+- (Node) `kind`: the type of the entity: `disease`, `protein`, `drug`, `sideeffect` or `function`.
+- (Node) `entity_id`: the identifier of the entity: a UMLS concept identifier for diseases and side effects, an NCBI Gene (Entrez) identifier for proteins, a STITCH compound identifier for drugs, a Gene Ontology identifier for functions.
+- (Edge) `relation`: the relation of the triple, e.g. `drug-protein`, `protein-protein_binding`.
+- (Edge) `split`: the set of the triple in the benchmark: `train`, `valid` or `test`."""
tags = ['Biological', 'Informational', 'Drug interactions', 'Protein interactions', 'Unweighted', 'Multigraph', 'Metadata']
url = ['https://ogb.stanford.edu/docs/linkprop/#ogbl-biokg',
'https://snap.stanford.edu/ogb/data/']
[entries] New entry: ogbl_biokg 6c282b8
diff --git a/entries/ogbl_biokg/__init__.py b/entries/ogbl_biokg/__init__.py
new file mode 100644
index 0000000..f7d2a5a
--- /dev/null
+++ b/entries/ogbl_biokg/__init__.py
@@ -0,0 +1,146 @@
+#! /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 codecs
+import pickle
+
+import pandas
+
+from .. import *
+
+title = "Biomedical knowledge graph BioKG (ogbl-biokg, 2020)"
+description = """A heterogeneous biomedical knowledge graph, from the `ogbl-biokg` dataset of the Open Graph Benchmark (OGB), a benchmark for link prediction (version 1, of 2020), built from BioKG, which integrates data of biomedical databases (e.g. UniProt, Reactome, KEGG, DrugBank, SIDER, the Gene Ontology, CTD, ...). The nodes are entities of five types: diseases (10,687), proteins (17,499), drugs (10,533), side effects (9,969) and protein functions (45,085), and each directed edge is a triple (head, relation, tail) with one of 51 relations, e.g. drug-protein interactions, protein-protein interactions of several kinds (activation, binding, catalysis, expression, inhibition, post-translational modification, reaction), drug-side effect associations, drug-drug interactions labeled by the class of diseases on which the interaction has an effect (e.g. `drug-drug_cancer`), and the hierarchy of protein functions. Two entities can be joined by several edges with different relations.
+
+The triples are split at random into the training (4,762,678), validation (162,886) and test (162,870) sets of the benchmark; the network contains all 5,088,434 triples, with their set as edge property `split`. The training triples are read from the plain files of the relations, the validation and test triples from the PyTorch files of the split (`split/random/valid.pt`, `test.pt`, of a legacy format, read without PyTorch). The negative samples of the validation and test triples (500 random heads and 500 random tails of the same type for each triple, against which the true triple is ranked in the benchmark: about 163 million non-edges) are left out.
+
+The network has the following properties:
+
+- `kind`: the type of the entity: `disease`, `protein`, `drug`, `sideeffect` or `function`.
+- `entity_id`: the identifier of the entity: a UMLS concept identifier for diseases and side effects, an NCBI Gene (Entrez) identifier for proteins, a STITCH compound identifier for drugs, a Gene Ontology identifier for functions.
+- Edge `relation`: the relation of the triple, e.g. `drug-protein`, `protein-protein_binding`.
+- Edge `split`: the set of the triple in the benchmark: `train`, `valid` or `test`."""
+tags = ['Biological', 'Informational', 'Drug interactions', 'Protein interactions', 'Unweighted', 'Multigraph', 'Metadata']
+url = ['https://ogb.stanford.edu/docs/linkprop/#ogbl-biokg',
+ 'https://snap.stanford.edu/ogb/data/']
+citation = [('W. Hu, M. Fey, M. Zitnik, Y. Dong, H. Ren, B. Liu, M. Catasta, J. Leskovec, "Open Graph Benchmark: Datasets for Machine Learning on Graphs." Advances in Neural Information Processing Systems 33, 22118-22133 (2020)', 'https://doi.org/10.48550/arXiv.2005.00687'),
+ ('B. Walsh, S. K. Mohamed, V. Nováček, "BioKG: A Knowledge Graph for Relational Learning On Biological Data." Proceedings of the 29th ACM International Conference on Information & Knowledge Management (CIKM), 3173-3180 (2020)', 'https://doi.org/10.1145/3340531.3412776')]
+icon_hash = None
+upstream_license = ('CC0 1.0', 'https://creativecommons.org/publicdomain/zero/1.0/')
+upstream_prefix = 'https://snap.stanford.edu/ogb/data'
+z = 'linkproppred/biokg.zip:biokg'
+KINDS = ["disease", "protein", "drug", "sideeffect", "function"]
+RELATIONS = ['disease___disease-protein___protein', 'drug___drug-disease___disease', 'drug___drug-drug_acquired_metabolic_disease___drug', 'drug___drug-drug_bacterial_infectious_disease___drug', 'drug___drug-drug_benign_neoplasm___drug', 'drug___drug-drug_cancer___drug', 'drug___drug-drug_cardiovascular_system_disease___drug', 'drug___drug-drug_chromosomal_disease___drug', 'drug___drug-drug_cognitive_disorder___drug', 'drug___drug-drug_cryptorchidism___drug', 'drug___drug-drug_developmental_disorder_of_mental_health___drug', 'drug___drug-drug_endocrine_system_disease___drug', 'drug___drug-drug_fungal_infectious_disease___drug', 'drug___drug-drug_gastrointestinal_system_disease___drug', 'drug___drug-drug_hematopoietic_system_disease___drug', 'drug___drug-drug_hematopoietic_system_diseases___drug', 'drug___drug-drug_hypospadias___drug', 'drug___drug-drug_immune_system_disease___drug', 'drug___drug-drug_inherited_metabolic_disorder___drug', 'drug___drug-drug_integumentary_system_disease___drug', 'drug___drug-drug_irritable_bowel_syndrome___drug', 'drug___drug-drug_monogenic_disease___drug', 'drug___drug-drug_musculoskeletal_system_disease___drug', 'drug___drug-drug_nervous_system_disease___drug', 'drug___drug-drug_orofacial_cleft___drug', 'drug___drug-drug_parasitic_infectious_disease___drug', 'drug___drug-drug_personality_disorder___drug', 'drug___drug-drug_polycystic_ovary_syndrome___drug', 'drug___drug-drug_pre-malignant_neoplasm___drug', 'drug___drug-drug_psoriatic_arthritis___drug', 'drug___drug-drug_reproductive_system_disease___drug', 'drug___drug-drug_respiratory_system_disease___drug', 'drug___drug-drug_sexual_disorder___drug', 'drug___drug-drug_sleep_disorder___drug', 'drug___drug-drug_somatoform_disorder___drug', 'drug___drug-drug_struct_sim___drug', 'drug___drug-drug_substance-related_disorder___drug', 'drug___drug-drug_thoracic_disease___drug', 'drug___drug-drug_urinary_system_disease___drug', 'drug___drug-drug_viral_infectious_disease___drug', 'drug___drug-protein___protein', 'drug___drug-sideeffect___sideeffect', 'function___function-function___function', 'protein___protein-function___function', 'protein___protein-protein_activation___protein', 'protein___protein-protein_binding___protein', 'protein___protein-protein_catalysis___protein', 'protein___protein-protein_expression___protein', 'protein___protein-protein_inhibition___protein', 'protein___protein-protein_ptmod___protein', 'protein___protein-protein_reaction___protein']
+files = [(tuple(f'{z}/mapping/{k}_entidx2name.csv.gz' for k in KINDS) +
+ tuple(f'{z}/raw/relations/{r}/edge.csv.gz' for r in RELATIONS) +
+ (f'{z}/mapping/relidx2relname.csv.gz',
+ f'{z}/split/random/valid.pt', f'{z}/split/random/test.pt'),
+ None, None)]
+
+def fetch_upstream(force=False):
+ return fetch_upstream_files(__name__.split(".")[-1], upstream_prefix, files,
+ force)
+
+def read_csv_gz(name, fname, **kwargs):
+ with open_upstream_file(name, fname, "rb") as f:
+ return pandas.read_csv(f, compression="gzip", **kwargs)
+
+# The split files of the validation and test triples are PyTorch files of the
+# legacy (non-zip) format: a sequence of pickles (magic number, protocol
+# version, system information, the object, the keys of the tensor storages,
+# then the storages). Here the object is a dict of plain numpy arrays (head,
+# relation, tail, head_neg, tail_neg) and lists (head_type, tail_type), with
+# no tensors, so it is read with a restricted unpickler that only rebuilds
+# numpy arrays (and refuses anything else).
+_np_core = getattr(numpy, "_core", None) or numpy.core
+PICKLE_CLASSES = {
+ ("numpy.core.multiarray", "_reconstruct"): _np_core.multiarray._reconstruct,
+ ("numpy._core.multiarray", "_reconstruct"): _np_core.multiarray._reconstruct,
+ ("numpy", "ndarray"): numpy.ndarray,
+ ("numpy", "dtype"): numpy.dtype,
+ ("_codecs", "encode"): codecs.encode}
+
+class SplitUnpickler(pickle.Unpickler):
+ def find_class(self, module, name):
+ try:
+ return PICKLE_CLASSES[(module, name)]
+ except KeyError:
+ raise pickle.UnpicklingError(f"refused class {module}.{name}")
+
+ def persistent_load(self, pid):
+ raise pickle.UnpicklingError(f"unexpected tensor storage {pid!r}")
+
+def read_legacy_pt(f):
+ "Read the object of a legacy PyTorch file of numpy arrays."
+ magic = pickle.load(f)
+ assert magic == 0x1950a86a20f9469cfc6c, magic
+ pickle.load(f) # protocol version
+ pickle.load(f) # system information
+ obj = SplitUnpickler(f).load()
+ assert pickle.load(f) == [] # no tensor storages
+ return obj
+
+# for checks: stop after this many edges per relation file and split (None:
+# all)
+_check_rows = None
+
+@cache_network()
+@coerce_props()
+@annotate()
+def parse(alts=None):
+ name = __name__.split(".")[-1]
+ offset = {}
+ kinds, ids = [], []
+ for k in KINDS:
+ # "ent idx,ent name"
+ t = read_csv_gz(name, f'{z}/mapping/{k}_entidx2name.csv.gz', dtype=str)
+ assert (t["ent idx"].astype(int).values == numpy.arange(len(t))).all()
+ offset[k] = len(ids)
+ ids.extend(t["ent name"].tolist())
+ kinds.extend([k] * len(t))
+ g = Graph(directed=True)
+ g.add_vertex(len(ids))
+ rels = []
+ for r in RELATIONS:
+ h, rel, t = r.split("___")
+ e = read_csv_gz(name, f'{z}/raw/relations/{r}/edge.csv.gz', header=None,
+ nrows=_check_rows).values
+ g.add_edge_list(numpy.column_stack([e[:, 0] + offset[h],
+ e[:, 1] + offset[t]]))
+ rels.extend([rel] * len(e))
+ splits = ["train"] * len(rels)
+ t = read_csv_gz(name, f'{z}/mapping/relidx2relname.csv.gz')
+ relnames = dict(zip(t["rel idx"], t["rel name"]))
+ for split in ["valid", "test"]:
+ with open_upstream_file(name, f'{z}/split/random/{split}.pt', "rb") as f:
+ d = read_legacy_pt(f)
+ # (the negative samples, head_neg and tail_neg, are left out)
+ del d["head_neg"], d["tail_neg"]
+ n = len(d["head"]) if _check_rows is None else _check_rows
+ heads = numpy.array([x + offset[k] for x, k in zip(d["head"][:n], d["head_type"][:n])],
+ dtype="int64")
+ tails = numpy.array([x + offset[k] for x, k in zip(d["tail"][:n], d["tail_type"][:n])],
+ dtype="int64")
+ g.add_edge_list(numpy.column_stack([heads, tails]))
+ rels.extend(relnames[x] for x in d["relation"][:n])
+ splits.extend([split] * len(heads))
+ del d
+ g.vp.kind = g.new_vp("string", vals=kinds)
+ g.vp.entity_id = g.new_vp("string", vals=ids)
+ g.ep.relation = g.new_ep("string", vals=rels)
+ g.ep.split = g.new_ep("string", vals=splits)
+ yield None, g