logo Netzschleuder network catalog, repository, and centrifuge

History of tflink

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] New entry: tflink by Tiago de Paula Peixoto 137fe62
diff --git a/entries/tflink/__init__.py b/entries/tflink/__init__.py
new file mode 100644
index 0000000..e21897c
--- /dev/null
+++ b/entries/tflink/__init__.py
@@ -0,0 +1,132 @@
+#! /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 = "TFLink transcription factor-target gene interactions (2022)"
+description = r"""Directed networks of the regulation of genes by transcription factors (TFs) in seven model organisms, from TFLink, which integrates the TF-target gene interactions of about 10 databases (e.g. ORegAnno, TRRUST, ReMap, GTRD, ChIP-Atlas, HTRIdb, PAZAR, TFe, Yeastract, modERN, REDfly, ...), from small-scale experiments (e.g. reporter assays, electrophoretic mobility shift assays, curated from the literature) and large-scale experiments (mostly ChIP-seq). An edge goes from a TF to a target gene whose expression it regulates, or to whose regulatory region it binds. The data are those of version 1.0 (April 2022) of TFLink.
+
+There is one network per organism, with all its interactions (small and large scale): `human` (*Homo sapiens*), `mouse` (*Mus musculus*), `rat` (*Rattus norvegicus*), `zebrafish` (*Danio rerio*), `fly` (*Drosophila melanogaster*), `worm` (*Caenorhabditis elegans*) and `yeast` (*Saccharomyces cerevisiae*). The small-scale and large-scale subsets that TFLink also provides are those of the edges with `small_scale` true or false. The binding sites of the TFs are not included.
+
+The networks have the following properties:
+
+- `uniprot`: the UniProt accession of the TF or target gene product.
+- `gene_id`: the NCBI Gene identifier of the gene (-1 if not given).
+- `name`: the name of the gene.
+- `tflink_orthologs`: the UniProt accessions of the orthologs of the node in the other organisms of TFLink, prefixed by the organism (e.g. `Hs:Q15049`), separated by `;` (empty if none).
+- `other_orthologs`: the same, for the orthologs that are not in TFLink.
+- Edge `detection_method`: the methods of detection of the interaction, separated by `;`.
+- Edge `pubmed_ids`: the PubMed identifiers of the publications of the interaction, separated by `;`.
+- Edge `source_databases`: the databases from which the interaction comes, separated by `;`.
+- Edge `small_scale`: whether the interaction is supported by small-scale experiments."""
+tags = ['Biological', 'Gene regulation', 'Unweighted', 'Metadata']
+url = ['https://tflink.net/', 'https://tflink.net/download/']
+citation = [('O. Liska, B. Bohár, A. Hidas, T. Korcsmáros, B. Papp, D. Fazekas, E. Ari, "TFLink: an integrated gateway to access transcription factor-target gene interactions for multiple species." Database 2022, baac083 (2022)',
+             'https://doi.org/10.1093/database/baac083')]
+icon_hash = None
+# No license is stated for the data (the article is under CC BY-NC 4.0)
+upstream_license = None
+upstream_prefix = 'https://cdn.netbiol.org/tflink/download_files'
+organisms = {"human": "Homo_sapiens_interactions_All_simpleFormat_v1.0.tsv.gz",
+             "mouse": "Mus_musculus_interactions_All_simpleFormat_v1.0.tsv.gz",
+             "rat": "Rattus_norvegicus_interactions_All_simpleFormat_v1.0.tsv",
+             "zebrafish": "Danio_rerio_interactions_All_simpleFormat_v1.0.tsv",
+             "fly": "Drosophila_melanogaster_interactions_All_simpleFormat_v1.0.tsv",
+             "worm": "Caenorhabditis_elegans_interactions_All_simpleFormat_v1.0.tsv",
+             "yeast": "Saccharomyces_cerevisiae_interactions_All_simpleFormat_v1.0.tsv"}
+files = [(f"TFLink_{fname}", alt, None) for alt, fname in organisms.items()]
+
+def fetch_upstream(force=False):
+    return fetch_upstream_files(__name__.split(".")[-1], upstream_prefix, files,
+                                force)
+
+COLUMNS = ["UniprotID.TF", "UniprotID.Target", "NCBI.GeneID.TF",
+           "NCBI.GeneID.Target", "Name.TF", "Name.Target", "Detection.method",
+           "PubmedID", "Organism", "Source.database", "Small-scale.evidence",
+           "TF.TFLink.ortho", "TF.nonTFLink.ortho", "Target.TFLink.ortho",
+           "Target.nonTFLink.ortho"]
+
+def string_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.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
+
+def dash(x):
+    return "" if x == "-" else x
+
+@cache_network()
+@coerce_props(eforce={"pubmed_ids": "string"})
+@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
+        with open_upstream_file(name, fnames, "rb") as f:
+            t = pyarrow.csv.read_csv(
+                f,
+                parse_options=pyarrow.csv.ParseOptions(delimiter="\t",
+                                                       quote_char=False),
+                convert_options=pyarrow.csv.ConvertOptions(
+                    column_types={c: pyarrow.string() for c in COLUMNS},
+                    strings_can_be_null=False))
+        assert t.column_names == COLUMNS, t.column_names
+        ids = pc.unique(pyarrow.chunked_array(t.column("UniprotID.TF").chunks +
+                                              t.column("UniprotID.Target").chunks))
+        g = Graph(directed=True)
+        g.add_vertex(len(ids))
+        g.add_edge_list(numpy.column_stack(
+            [pc.index_in(t.column("UniprotID.TF"), value_set=ids).to_numpy(),
+             pc.index_in(t.column("UniprotID.Target"), value_set=ids).to_numpy()]))
+        # node attributes, from the first row in which each node appears
+        vals = {k: [""] * len(ids) for k in ("gene_id", "name", "tflink_orthologs",
+                                             "other_orthologs")}
+        for end in ("Target", "TF"):
+            idx = pc.index_in(ids, value_set=t.column(f"UniprotID.{end}"))
+            mask = pc.is_valid(idx).to_numpy(zero_copy_only=False)
+            rows = pc.drop_null(idx)
+            pos = numpy.nonzero(mask)[0]
+            for k, c in (("gene_id", f"NCBI.GeneID.{end}"), ("name", f"Name.{end}"),
+                         ("tflink_orthologs", f"{end}.TFLink.ortho"),
+                         ("other_orthologs", f"{end}.nonTFLink.ortho")):
+                col = t.column(c).take(rows).to_pylist()
+                for i, x in zip(pos, col):
+                    vals[k][i] = x
+        g.vp.uniprot = g.new_vp("string", vals=ids.to_pylist())
+        g.vp.gene_id = g.new_vp("int64_t", vals=[int(x) if x.isdigit() else -1
+                                                for x in vals["gene_id"]])
+        g.vp.name = g.new_vp("string", vals=[dash(x) for x in vals["name"]])
+        g.vp.tflink_orthologs = g.new_vp("string", vals=[dash(x) for x in vals["tflink_orthologs"]])
+        g.vp.other_orthologs = g.new_vp("string", vals=[dash(x) for x in vals["other_orthologs"]])
+        string_ep(g, t.column("Detection.method"), "detection_method")
+        string_ep(g, t.column("PubmedID"), "pubmed_ids")
+        string_ep(g, t.column("Source.database"), "source_databases")
+        ss = t.column("Small-scale.evidence")
+        assert set(pc.unique(ss).to_pylist()) <= {"Yes", "No"}
+        g.ep.small_scale = g.new_ep("bool", vals=pc.equal(ss, "Yes").to_numpy(zero_copy_only=False))
+        del t
+        yield alt, g