{"metadata":{"kernelspec":{"name":"python3","display_name":"Python 3","language":"python"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":41875,"databundleVersionId":5521661,"isSourceIdPinned":false,"sourceType":"competition"},{"sourceId":116062,"databundleVersionId":14875579,"isSourceIdPinned":false,"sourceType":"competition"}],"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# An Exploratory Analysis of Gene Ontology (GO)","metadata":{}},{"cell_type":"markdown","source":"<strong>What's this about:</strong>\n<div style=\"line-height:24px; font-size:16px\">\n    <ul style=\"list-style:circle\">\n        <li>Briefly describe the basics of Gene Ontology\n        <li>Visualize top-level GO terms for each of the three ontologies (BP, MF, CC)\n        <li>Examine GO changes over time (CAFA5 vs CAFA6)\n        <li>Examine GO terms in the CAFA6 training set\n        <li>Provide a way to track GO terms in the GO DAG\n    </ul>\n    <div style=\"margin-top:20px;\">\n     <a href= \"https://www.kaggle.com/code/antoninadolgorukova/gene-ontology-explorer\">Origin notebook in R</a>\n    </div> \n</div>","metadata":{"execution":{"iopub.execute_input":"2025-12-18T19:21:24.808453Z","iopub.status.busy":"2025-12-18T19:21:24.807869Z","iopub.status.idle":"2025-12-18T19:21:24.861535Z","shell.execute_reply":"2025-12-18T19:21:24.859149Z","shell.execute_reply.started":"2025-12-18T19:21:24.808397Z"}}},{"cell_type":"markdown","source":"**Load packages**","metadata":{}},{"cell_type":"code","source":"!pip install goatools\n!pip install pyvis","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2025-12-27T22:28:00.778888Z","iopub.execute_input":"2025-12-27T22:28:00.779225Z","iopub.status.idle":"2025-12-27T22:28:09.303222Z","shell.execute_reply.started":"2025-12-27T22:28:00.779201Z","shell.execute_reply":"2025-12-27T22:28:09.301687Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!python -V","metadata":{"execution":{"iopub.status.busy":"2025-12-27T22:28:09.305345Z","iopub.execute_input":"2025-12-27T22:28:09.30631Z","iopub.status.idle":"2025-12-27T22:28:09.438848Z","shell.execute_reply.started":"2025-12-27T22:28:09.30627Z","shell.execute_reply":"2025-12-27T22:28:09.437722Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport networkx as nx\nimport textwrap\n\nfrom collections import deque, defaultdict\nfrom IPython.display import IFrame, display\nfrom pyvis.network import Network\nfrom pathlib import Path\nfrom textwrap import fill\nfrom goatools.obo_parser import GODag","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2025-12-27T22:28:09.440345Z","iopub.execute_input":"2025-12-27T22:28:09.440769Z","iopub.status.idle":"2025-12-27T22:28:09.447722Z","shell.execute_reply.started":"2025-12-27T22:28:09.440731Z","shell.execute_reply":"2025-12-27T22:28:09.44651Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"CAFA6_DIR = \"/kaggle/input/cafa-6-protein-function-prediction\"\nobo_path = Path(CAFA6_DIR, \"Train/go-basic.obo\")\ngo_dag = GODag(str(obo_path), optional_attrs={\"relationship\"})","metadata":{"execution":{"iopub.status.busy":"2025-12-27T22:28:09.449852Z","iopub.execute_input":"2025-12-27T22:28:09.450208Z","iopub.status.idle":"2025-12-27T22:28:11.254941Z","shell.execute_reply.started":"2025-12-27T22:28:09.450183Z","shell.execute_reply":"2025-12-27T22:28:11.254082Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Basics of Gene Ontology","metadata":{}},{"cell_type":"markdown","source":"GO (Gene Ontology) is a structured terminology that categorizes gene functions into three distinct domains:\n- molecular function (MF), \n- cellular component (CC), \n- and biological process (BP)  \n\nIt encompasses over 43,000 terms and 130,000 parent-child relationships.","metadata":{}},{"cell_type":"code","source":"type(go_dag)","metadata":{"execution":{"iopub.status.busy":"2025-12-27T22:28:11.255767Z","iopub.execute_input":"2025-12-27T22:28:11.255998Z","iopub.status.idle":"2025-12-27T22:28:11.262848Z","shell.execute_reply.started":"2025-12-27T22:28:11.255979Z","shell.execute_reply":"2025-12-27T22:28:11.26191Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"go-basic.obo (loaded above as `go_dag`) is an instance of goatools.obo_parser.GODag. It represents the Gene Ontology as a Python mapping where keys are GO term identifiers (e.g. GO:0008150) and values are objects describing individual GO terms. Each term object stores its name, ontology domain (BP, MF, CC), parent-child relationships, and additional semantic relationships defined in the ontology.","metadata":{}},{"cell_type":"code","source":"list(go_dag.keys())[:5]","metadata":{"execution":{"iopub.status.busy":"2025-12-27T22:28:11.263865Z","iopub.execute_input":"2025-12-27T22:28:11.264181Z","iopub.status.idle":"2025-12-27T22:28:11.282963Z","shell.execute_reply.started":"2025-12-27T22:28:11.264152Z","shell.execute_reply":"2025-12-27T22:28:11.281911Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"term = go_dag[\"GO:0008150\"]\nterm","metadata":{"execution":{"iopub.status.busy":"2025-12-27T22:28:11.283953Z","iopub.execute_input":"2025-12-27T22:28:11.284179Z","iopub.status.idle":"2025-12-27T22:28:11.30014Z","shell.execute_reply.started":"2025-12-27T22:28:11.28416Z","shell.execute_reply":"2025-12-27T22:28:11.299057Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"GO has a **hierarchical structure organized as a directed acyclic graph (DAG)**, which means that the GO terms are interdependent. The relationship between terms follows a parent-child model, where **parent terms are broader and less specific than their child terms**. The mapping between terms can be one-to-many in both directions, allowing a child to have multiple parents and a parent to have multiple children. There is a single root node for all ontologies, along with separate root nodes for each of the three ontologies mentioned earlier (Molecular Function, Cellular Component, and Biological Process).\n\n- GO:0003673 is the global GO root (a technical top node that connects all three GO domains)\n- GO:0003674 is the MF root \n- GO:0005575 is the CC root \n- GO:0008150 is the BP root\n\nLet's find them in our obo file:","metadata":{}},{"cell_type":"code","source":"unique_terms = list({term.id: term for term in go_dag.values()}.values())\nnon_obsolete_terms = [t for t in unique_terms if not getattr(t, \"is_obsolete\", False)]\n\nroots_all = sorted(\n    [t for t in non_obsolete_terms if len(getattr(t, \"parents\", [])) == 0],\n    key=lambda term: term.id,\n)\n\nroots_df = pd.DataFrame(\n    [{\"go_id\": t.id, \"namespace\": t.namespace} for t in roots_all]\n)\nroots_df","metadata":{"execution":{"iopub.status.busy":"2025-12-27T22:28:11.301183Z","iopub.execute_input":"2025-12-27T22:28:11.302482Z","iopub.status.idle":"2025-12-27T22:28:11.370376Z","shell.execute_reply.started":"2025-12-27T22:28:11.302453Z","shell.execute_reply":"2025-12-27T22:28:11.369365Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"There are also 3 placeholder terms indicating that the corresponding function, process, or localization is unknown:\n- GO:0000004 - biological process unknown \n- GO:0005554 - molecular function unknown \n- GO:0008372 - cellular component unknown ","metadata":{}},{"cell_type":"markdown","source":"💡 Note: some terms can be marked as obsolete in the Gene Ontology. These are terms that have been retired by the Gene Ontology maintainers; they are kept for traceability but should not be treated as valid, current functional labels. When parsing GO with goatools.GODag, obsolete terms are excluded by default (load_obsolete=False).","metadata":{}},{"cell_type":"markdown","source":"**Number of terms in each domain:**","metadata":{}},{"cell_type":"code","source":"namespace_map = {\n    \"molecular_function\": \"MF\",\n    \"cellular_component\": \"CC\",\n    \"biological_process\": \"BP\",\n}\ndomain_order = [\"BP\", \"MF\", \"CC\"]\ncolors = [\"#4C78A8\", \"#F58518\", \"#54A24B\"]\n\nterms = {term.id: term for term in go_dag.values()}.values()\ndomains = [\n    namespace_map.get(term.namespace)\n    for term in terms\n    if not getattr(term, \"is_obsolete\", False)\n]\ncounts = (\n    pd.Series(domains, name=\"domain\")\n    .value_counts().reindex(domain_order)\n)\n\nax = counts.plot(kind=\"bar\", color=colors, figsize=(6, 4), width=0.65)\nax.set_xlabel(\"\")\nax.set_ylabel(\"Number of non-obsolete GO terms\")\nax.set_title(\"GO term counts by domain (from go-basic.obo)\")\nax.tick_params(axis=\"x\", labelrotation=0)\n\ny_max = counts.max()\nax.set_ylim(0, int(y_max * 1.12))\n\nfor bar in ax.patches:\n    height = bar.get_height()\n    ax.text(\n        bar.get_x() + bar.get_width() / 2,\n        height + 0.02 * y_max,\n        f\"{int(height):,}\",\n        ha=\"center\",\n        va=\"bottom\",\n        fontsize=11,\n    )","metadata":{"execution":{"iopub.status.busy":"2025-12-27T22:28:11.371263Z","iopub.execute_input":"2025-12-27T22:28:11.371557Z","iopub.status.idle":"2025-12-27T22:28:11.766536Z","shell.execute_reply.started":"2025-12-27T22:28:11.371532Z","shell.execute_reply":"2025-12-27T22:28:11.765714Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"**Сhild-parent relationships**","metadata":{}},{"cell_type":"markdown","source":"The types of child-parent relationships in GO are defined as follows: \n- is-a: the child term is a more specific version of the parent\n- has part: part-whole relationship from the perspective of the parent,\n- part-of: part-whole relationship from the perspective of the child, i.e. the child is a part of the parent, \n- regulates: one process directly affects the manifestation of another process or quality, i.e. the former regulates the latter\n- negatively regulates\n- positively regulates\n\n![image.png](attachment:4c841d38-a03b-4cb5-8fe7-75858ecf4791.png)\n\nMore details are [here](http://geneontology.org/docs/ontology-relations/)","metadata":{},"attachments":{"4c841d38-a03b-4cb5-8fe7-75858ecf4791.png":{"image/png":"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e9GxdlEdig+dHBtlk/Fy/Lcl4+oV84jbERfg7Y7HYxGXiYiI7hWxGqd0Ew2HEXYOIxLUIaqfcVWDxp6YM0GlF9OLr5ovoilA2DWGiM+dmJGI7mfOfj2Gm0zIi6pRro9e0YpF042rczI1uGo+2dTDOvRdNCPkm76rGBn3YvFPxMHxsTF22R4RN68g4urV84k4KuKwjMcyLhMREd0raXOdQrosGvIiMtwM1WgTVK6rzyah6ngf6HgvcUswFwFVv4KoadxFlrUmRDJnQ5U1C+oMkQQR0X2tox24eAGx4wl9437l6x1W4V+3AD3DiQnCEytFW3X1KiQ/W4WKMmButQgf5sTEaSYy1o3oSDPUIo6OP+GWytsDnP9nwCNPIpNQ9jSiZU8lblwWtRYjKuKoOnsWVCKmEhER3QssCulqR/4YOPqdxA0hez7w+M/jQyJKS/XNwOe+FR8qvv2rwB+IRuMM1wFbXo4PFStFTF31R4kbREREqYW7jxIREREREaUxFoVERERERERpjEUhERERERFRGmNRSERERERElMZYFBIREREREaUxFoVERERERERpjEUhERERERFRGmNRSERERERElMZYFBIREREREaUxFoVERERERERpjEUhERERERFRGmNRSERERERElMZYFBIREREREaUxFoVERERERERpjEUhERERERFRGmNRSERERERElMZYFBIREREREaUxFoVERERERERpjEUhERERERFRGmNRSERERERElMZYFBIREREREaUxFoVERERERERpjEUhERERERFRGmNRSDSlogiH/PC5nRgZ7MfA4BCGnC74wxFEEnMQEaWraDSMoN+NMccwBvv70T/swJjXj5C8Lz4LERHdBSwKiaaMTGkicI10o7XuILa/+SreePsDvHvwDDrGPPAx4yGitBZBKODGUGc9Tuzdgnd+8Qv84qM9ONrciTERH8OJuYiIaOqxKCSaKpEg4O7EgT3b8b0fvYq6vjE43UFEnWNwByLw86fCaS/sG8Bo/T/iw49+jn94+zy6HD4mukQK/wgG22vxr//2Y3y0/yR6fSqEnC4EPD64QyKEcsMZEdFdw6KQ0ldUVGUhD/r7h3GheRBjvhBCdzIJCQcQGevA4QMH8ZO3D2DMlIf84hJUZFqgU6sRZcIz7UUCDnja38PRo7vxzoEODLvEMpG4jyjlRQLwu524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vd7rxOd7iMcUElGaYVFIKcN55v/h2K6f4GvvrsYLLz4tkvON0AWDUMtf3DRaebmtccmCKMZEAhIMhsQdIpHWigJQDCPhMMKRSOzag/IC8ZNJMGQ3iMSuayjmFi909WtNJIKweIx4qdjry0td3K3rD14Xi8JJm+qi8NpE2JXJc0Qsd9HEMieW1UktPjJki4UuIoZRsZSqY9fUlH0hipB4Lvk8KbEc0h0VHG3C8N5v4i8/NOCj/k34t7/4FBZUZEErlgWVRhRZ4m9+9Z89glBIxEMRp2LxUCxncpZQSMRMMa7RXH0B+muR8TEqllf5ONWErzVePD7L147KVxExUisedN/8EsiikIjSzGTXB0RTLqwRBaAugHKtCrkiedCI7EGr10Or04okd6IiTSYYGuj1Buh1OjF/POGRiU789uQKQkklE2lRVGq08leaiV5rIjKp0kIn3p8u9rj7Jduhe08sK2LZVYvlRyuWO5ksT3rxkVm1TOZFki+XWbnsxnZVVmtiv1BzOZyeoqoogjo/7LowKkRhZpTxUSwDOhkjNddafkQhptXBYDCIeeRGMxkzVSJm6cSyMvmCUJIbHzQ6ESOv+VrjxeOzfH2dWE518oylXDSJiFIWi0JKGfqSZzHr0b/DH/zxV/DJT8zn2TuJiBLUpmKYF/4PPPfLv4dvf+txVBTaePZOIiK6Y5hzU8rQWwqRW7IQi+fPQGmBjQsnEVGCWmOEObsaM2dXYVF1ISxG3aT3hCAiIroR5t2UMuQuTWaTCXaLESY9t4ETESnk8YBGoxEZZiNsJj13EyYiojuKRSEREREREVEaY1FIRERERESUxlgUEhERERERpTEWhURERERERGmMRSEREREREVEaY1FIRERERESUxlgUEhERERERpTEWhURERERERGmMRSEREREREVEaY1FIRERERESUxlgUEhERERERpTEWhURERERERGmMRSEREREREVEaY1FIRERERESUxlgUEhERERERpTEWhURERERERGmMRSEREREREVEaY1FIRERERESUxlgUEhERERERpTEWhURERERERGmMRSEREREREVEaY1FIRERERESUxlgUEhERERERpTEWhURERERERGmMRSEREREREVEaY1FIRERERESUxlgUEhERERERpTEWhURERERERGmMRSEREREREVEaY1FIRERERESUxlgU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"}}},{"cell_type":"markdown","source":"Let's count the total number of edges for each relationship type present in the go-basic.obo file. In goatools, `is_a` is treated as the primary hierarchical relation and is exposed via the parents attribute of each term. Other relationships are stored explicitly in the relationship field and do not include `is_a`.","metadata":{}},{"cell_type":"code","source":"relationship_counts = {}\nis_a_count = 0\n\nfor term in non_obsolete_terms:\n    is_a_count += len(getattr(term, \"parents\", []))\n    relationships = getattr(term, \"relationship\", None) or {}\n    for rel_type, rel_parents in relationships.items():\n        relationship_counts[rel_type] = relationship_counts.get(rel_type, 0)\n        relationship_counts[rel_type] += len(rel_parents)\n\ncounts_df = (\n    pd.DataFrame(\n        [{\"type\": \"is_a\", \"n_edges\": is_a_count}]\n        + [{\"type\": rel_type, \"n_edges\": count}\n           for rel_type, count in relationship_counts.items()]\n    )\n    .sort_values(\"n_edges\", ascending=False)\n    .reset_index(drop=True)\n)\n\ncounts_df","metadata":{"execution":{"iopub.status.busy":"2025-12-27T22:28:11.769703Z","iopub.execute_input":"2025-12-27T22:28:11.769997Z","iopub.status.idle":"2025-12-27T22:28:11.822128Z","shell.execute_reply.started":"2025-12-27T22:28:11.769976Z","shell.execute_reply":"2025-12-27T22:28:11.821106Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"A child node in GO doesn’t necessarily have to be on the next hierarchical level and can connect to nodes further down the DAG. Depending on the organism and domain (Biological Process, Molecular Function, or Cellular Component), a GO DAG may consist of thousands of nodes.\n\nAlthough the Gene Ontology is intended to be species-independent, the majority of experimentally supported GO annotations originate from a limited set of well-studied model organisms. These include human, mouse, rat, zebrafish, Drosophila melanogaster, Caenorhabditis elegans, Dictyostelium discoideum, Saccharomyces cerevisiae, Schizosaccharomyces pombe, Arabidopsis thaliana, and Escherichia coli. But obo files species-independent and do not contain any information about organisms.\n\nGene Ontology itself defines only terms and their relationships. The biological meaning emerges when annotations are added. An annotation links a gene or gene product (for example, a protein) to a specific GO term. A single gene can be annotated to multiple GO terms at the same time, because genes typically participate in several processes, have multiple functions, or operate in different cellular locations. Because GO is organized as a hierarchical directed acyclic graph, annotations do not remain isolated at the most specific term. Instead, they propagate upward along is_a relationships. This means that if a gene is annotated to a specific term, it is implicitly also associated with all of that term’s ancestors.","metadata":{}},{"cell_type":"markdown","source":"# Structural properties of GO ontologies (BP, MF, CC)","metadata":{}},{"cell_type":"code","source":"def unique_non_obsolete_terms(go_dag):\n    terms = list({term.id: term for term in go_dag.values()}.values())\n    return [t for t in terms if not getattr(t, \"is_obsolete\", False)]\n\ndef build_domain_table(go_dag, domain, terms_subset=None):\n    domain_to_namespace = {v: k for k, v in namespace_map.items()}\n    \n    terms = unique_non_obsolete_terms(go_dag)\n    target_ns = domain_to_namespace[domain]\n    terms = [t for t in terms if t.namespace == target_ns]\n    if terms_subset is not None:\n        terms = [t for t in terms if t.id in terms_subset]\n\n    term_ids = {t.id for t in terms}\n\n    in_all = {term_id: 0 for term_id in term_ids}\n    out_all = {term_id: 0 for term_id in term_ids}\n\n    for term in terms:\n        children = [c.id for c in getattr(term, \"children\", []) if c.id in term_ids]\n        out_all[term.id] += len(children)\n        for child_id in children:\n            in_all[child_id] += 1\n\n        relationships = getattr(term, \"relationship\", None)\n        for rel_type, rel_targets in relationships.items():\n            targets = [x.id for x in rel_targets if x.id in term_ids]\n            out_all[term.id] += len(targets)\n            for target_id in targets:\n                in_all[target_id] += 1\n\n    domain_df = pd.DataFrame({\n        \"go_id\": [t.id for t in terms],\n        \"name\": [t.name for t in terms],\n        \"depth_is_a\": [int(getattr(t, \"depth\", -1)) for t in terms],\n        \"n_parents_is_a\": [len(getattr(t, \"parents\", [])) for t in terms],\n        \"n_children_is_a\": [len(getattr(t, \"children\", [])) for t in terms],\n        \"n_in_all\": [in_all[t.id] for t in terms],\n        \"n_out_all\": [out_all[t.id] for t in terms],\n    })\n    domain_df[\"n_edges_all\"] = domain_df[\"n_in_all\"] + domain_df[\"n_out_all\"]\n    return domain_df\n\ndef summarize_domain_table(domain_df):\n    columns = [\n        \"n_in_all\",\n        \"n_out_all\",\n        \"n_edges_all\",\n        \"n_parents_is_a\",\n        \"n_children_is_a\",\n        \"depth_is_a\",\n    ]\n    return domain_df[columns].describe(percentiles=[0.5]).T\n\ndef plot_edge_hist_log10(domain_dfs, bins=60):\n    fig, axes = plt.subplots(\n        nrows=len(domain_dfs),\n        ncols=1,\n        figsize=(10, 4 * len(domain_dfs)),\n        sharex=True\n    )\n\n    ticks = [0, np.log10(2), np.log10(5), 1, 2]\n    labels = [\"0\", \"1\", \"4\", \"9\", \"99\"]\n\n    for ax, (name, domain_df) in zip(axes, domain_dfs.items()):\n        values = domain_df[\"n_edges_all\"].to_numpy(dtype=float)\n        values_log = np.log10(values + 1.0)\n        median_log = float(np.median(values_log))\n\n        ax.hist(values_log, bins=bins,\n                color=\"steelblue\", edgecolor=\"black\")\n        ax.axvline(median_log, linestyle=\"--\", color=\"red\")\n\n        ax.set_ylabel(\"Count\")\n        ax.set_title(f\"{name} ontology\")\n\n    axes[-1].set_xticks(ticks)\n    axes[-1].set_xticklabels(labels)\n    axes[-1].set_xlabel(\n        \"Number of edges per term (log10 transform)\"\n    )\n\n    plt.tight_layout()\n    return axes\n\ndef build_k_level_graph(go_dag, root_id, max_depth=3):\n    graph = nx.DiGraph()\n    level_by_id = {root_id: 1}\n    queue = deque([root_id])\n    graph.add_node(root_id, level=1)\n\n    while queue:\n        node_id = queue.popleft()\n        node_level = level_by_id[node_id]\n        if node_level >= max_depth:\n            continue\n\n        node = go_dag[node_id]\n        children_by_rel = defaultdict(set)\n\n        for child in getattr(node, \"children\", []) or []:\n            if not getattr(child, \"is_obsolete\", False):\n                children_by_rel[\"is_a\"].add(child)\n\n        rel_rev = getattr(node, \"relationship_rev\", None) or {}\n        for rel_type, rel_terms in rel_rev.items():\n            for child in rel_terms:\n                if not getattr(child, \"is_obsolete\", False):\n                    children_by_rel[rel_type].add(child)\n\n        next_level = node_level + 1\n        for rel_type, children in children_by_rel.items():\n            for child in sorted(children, key=lambda t: t.id):\n                child_id = child.id\n                graph.add_edge(node_id, child_id, rel=rel_type)\n                prev_level = level_by_id.get(child_id)\n                if prev_level is None or next_level < prev_level:\n                    level_by_id[child_id] = next_level\n                    graph.add_node(child_id, level=next_level)\n                    queue.append(child_id)\n\n    node_set = set(graph.nodes())\n    for node_id in list(node_set):\n        node = go_dag[node_id]\n        rel_rev = getattr(node, \"relationship_rev\", None) or {}\n        for rel_type, rel_terms in rel_rev.items():\n            for child in rel_terms:\n                if getattr(child, \"is_obsolete\", False):\n                    continue\n                if child.id in node_set:\n                    graph.add_edge(node_id, child.id, rel=rel_type)\n\n    return graph\n\n\ndef pyvis_render(go_dag, graph, wrap_label=False, title=\"GO DAG\"):\n    net = Network(\n        height=\"750px\", width=\"100%\", directed=True, notebook=True,\n        cdn_resources=\"in_line\",\n    )\n    net.set_options(\"\"\"\n    {\n      \"layout\": {\n        \"hierarchical\": {\n          \"enabled\": true,\n          \"direction\": \"LR\",\n          \"sortMethod\": \"directed\",\n          \"levelSeparation\": 320,\n          \"nodeSpacing\": %d,\n          \"treeSpacing\": 120,\n          \"blockShifting\": true,\n          \"edgeMinimization\": true,\n          \"parentCentralization\": true\n        }\n      },\n      \"physics\": { \"enabled\": false },\n      \"interaction\": {\n        \"hover\": true,\n        \"navigationButtons\": true,\n        \"keyboard\": true\n      },\n      \"nodes\": {\n        \"shape\": \"box\",\n        \"font\": { \"size\": 11, \"multi\": %s, \"face\": \"arial\" },\n        \"margin\": { \"top\": 2, \"right\": 4, \"bottom\": 2, \"left\": 4 }\n      },\n      \"edges\": {\n        \"smooth\": false,\n        \"arrows\": { \"to\": { \"enabled\": true, \"scaleFactor\": 0.5 } }\n      }\n    }\n    \"\"\" % (\n        60 if wrap_label else 30,\n        \"true\" if wrap_label else \"false\"\n    ))\n\n    rel_color = {\n        \"is_a\": \"#1C588C\",\n        \"part_of\": \"black\",\n        \"has_part\": \"gray\",\n        \"regulates\": \"#BF9039\",\n        \"negatively_regulates\": \"#BF5841\",\n        \"positively_regulates\": \"#2D735F\",\n    }\n\n    for node_id, data in graph.nodes(data=True):\n        term = go_dag[node_id]\n        level = int(data.get(\"level\", 1))\n        full_label = f\"{node_id}: {term.name}\"\n        label = (\"\\n\".join(textwrap.wrap(full_label, width=28))\n         if wrap_label else\n         (full_label if len(full_label) <= 80 else full_label[:77] + \"...\"))\n        net.add_node(\n            node_id,\n            label=label,\n            title=f\"{node_id}<br>{term.name}<br>level: {level}\",\n            shape=\"box\",\n            level=level,\n        )\n\n    used_rels = set()\n    for u, v, data in graph.edges(data=True):\n        rel = data.get(\"rel\", \"is_a\")\n        used_rels.add(rel)\n        net.add_edge(u, v, title=rel, color=rel_color.get(rel, \"#999999\"))\n\n    legend = \" &nbsp; \".join(\n        \"<span style='display:inline-block;width:12px;height:12px;\"\n        f\"background:{rel_color.get(r, '#999999')};margin-right:6px;'></span>{r}\"\n        for r in sorted(used_rels)\n    )\n\n    html = net.generate_html()\n    header = (\n        f\"<h3 style='margin:0 0 6px 0;'>{title}</h3>\"\n        f\"<div style='margin:0 0 10px 0;font-size:14px;'>{legend}</div>\"\n    )\n    \n    html = html.replace(\"<body>\", \"<body>\" + header, 1)\n    \n    path = f\"pyvis_graph_{id(graph)}.html\"\n    with open(path, \"w\", encoding=\"utf-8\") as file:\n        file.write(html)\n    \n    return IFrame(path, width=\"100%\", height=800)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2025-12-27T22:28:11.823206Z","iopub.execute_input":"2025-12-27T22:28:11.823461Z","iopub.status.idle":"2025-12-27T22:28:11.856805Z","shell.execute_reply.started":"2025-12-27T22:28:11.823442Z","shell.execute_reply":"2025-12-27T22:28:11.85577Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"The following graph-theoretic quantities are computed for each ontology (BP, MF, CC):  \n`n_in_all` (incoming edges, all types) is the number of edges pointing to a term from other terms, counting both `is_a` and other semantic relations (e.g., `part_of`, `regulates`, etc.).\n\n`n_out_all` (outgoing edges, all types) is the number of edges going out of a term to other terms, again\ncounting all relationship types.\n\n`n_edges_all` - total (`n_in_all` + `n_out_all`) number of edges, all types.\n\n`n_parents_is_a` - number of direct `is_a` parents\n`n_children_is_a` - number of direct `is_a` children\n`depth_is_a` (depth from the BP root using `is_a`) is the distance from the root term (depth 0) along `is_a` edges, using the convention implemented by goatools.","metadata":{}},{"cell_type":"code","source":"bp_df = build_domain_table(go_dag, domain=\"BP\")\nsummarize_domain_table(bp_df)","metadata":{"execution":{"iopub.status.busy":"2025-12-27T22:28:11.858013Z","iopub.execute_input":"2025-12-27T22:28:11.858345Z","iopub.status.idle":"2025-12-27T22:28:12.089453Z","shell.execute_reply.started":"2025-12-27T22:28:11.858317Z","shell.execute_reply":"2025-12-27T22:28:12.088482Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"mf_df = build_domain_table(go_dag, domain=\"MF\")\nsummarize_domain_table(mf_df)","metadata":{"execution":{"iopub.status.busy":"2025-12-27T22:28:12.09056Z","iopub.execute_input":"2025-12-27T22:28:12.090903Z","iopub.status.idle":"2025-12-27T22:28:12.183676Z","shell.execute_reply.started":"2025-12-27T22:28:12.090875Z","shell.execute_reply":"2025-12-27T22:28:12.182715Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"cc_df = build_domain_table(go_dag, domain=\"CC\")\nsummarize_domain_table(cc_df)","metadata":{"execution":{"iopub.status.busy":"2025-12-27T22:28:12.184444Z","iopub.execute_input":"2025-12-27T22:28:12.184697Z","iopub.status.idle":"2025-12-27T22:28:12.253964Z","shell.execute_reply.started":"2025-12-27T22:28:12.184672Z","shell.execute_reply":"2025-12-27T22:28:12.253135Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"💡 Note:\n- Biological Process (BP) is by far the largest ontology (≈26k terms) and deepest (median depth 7, max 16), followed by Molecular Function (≈10k) and Cellular Component (≈4k)\n- BP shows the highest average total degree (n_edges_all ≈ 4.5), MF and CC are sparser (≈2.5 and ≈3.2, respectively); all 3 have heavy-tailed degree distributions\n- In all three ontologies, the median number of incoming and outgoing edges is small (typically 0–2)\n- The majority of GO terms are leaves","metadata":{}},{"cell_type":"markdown","source":"Plot the histogram for the number of edges:","metadata":{}},{"cell_type":"code","source":"plot_edge_hist_log10({\n    \"Biological Process\": bp_df,\n    \"Molecular Function\": mf_df,\n    \"Cellular Component\": cc_df\n})","metadata":{"execution":{"iopub.status.busy":"2025-12-27T22:28:12.255005Z","iopub.execute_input":"2025-12-27T22:28:12.255275Z","iopub.status.idle":"2025-12-27T22:28:13.141665Z","shell.execute_reply.started":"2025-12-27T22:28:12.255254Z","shell.execute_reply":"2025-12-27T22:28:13.140776Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"These plots show the distribution of the total number of edges per GO term, where edges include all relationship types defined in the ontology (`is_a` as well as non-hierarchical relations such as `part_of`, `regulates`, etc.), restricted to the selected ontology domain.","metadata":{}},{"cell_type":"markdown","source":"Plot top 2 levels:","metadata":{}},{"cell_type":"code","source":"graph = build_k_level_graph(go_dag, root_id = \"GO:0008150\", max_depth=2)\ntitle = \"Top-level BP GO terms (edges by relationship type)\"\nHTML_obj = pyvis_render(go_dag, graph, title=title)\ndisplay(HTML_obj)","metadata":{"execution":{"iopub.status.busy":"2025-12-27T22:28:13.142464Z","iopub.execute_input":"2025-12-27T22:28:13.142719Z","iopub.status.idle":"2025-12-27T22:28:13.271322Z","shell.execute_reply.started":"2025-12-27T22:28:13.142699Z","shell.execute_reply":"2025-12-27T22:28:13.270552Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# GO Changes Over Time","metadata":{}},{"cell_type":"markdown","source":"Here I compare the CAFA6 and the CAFA5 GO data.","metadata":{}},{"cell_type":"code","source":"def load_go_df(obo_path, optional_attrs=None):\n    optional_attrs = set(optional_attrs or set()) | {\"relationship\", \"def\"}\n    go_dag = GODag(str(obo_path), optional_attrs=optional_attrs, load_obsolete=True)\n    rows = []\n    for go_id, term in go_dag.items():\n        rows.append(\n            {\n                \"GOID\": go_id,\n                \"name\": getattr(term, \"name\", None),\n                \"definition\": getattr(term, \"defn\", None),\n                \"is_obsolete\": bool(getattr(term, \"is_obsolete\", False)),\n            }\n        )\n    return pd.DataFrame(rows)\n\n\ndef compare_go_obo(old_obo, new_obo):\n    old_df = load_go_df(old_obo)\n    new_df = load_go_df(new_obo)\n\n    old_terms = set(old_df[\"GOID\"])\n    new_terms = set(new_df[\"GOID\"])\n    added_terms = new_terms - old_terms\n    removed_terms = old_terms - new_terms\n\n    obsolete_old = set(old_df.loc[old_df[\"is_obsolete\"], \"GOID\"])\n    obsolete_new = set(new_df.loc[new_df[\"is_obsolete\"], \"GOID\"])\n    new_obsoletes = obsolete_new - obsolete_old\n    added_as_obsolete = added_terms & obsolete_new\n\n    df = old_df.merge(\n        new_df, on=\"GOID\", how=\"outer\", suffixes=(\"_old\", \"_new\"), validate=\"one_to_one\"\n    )\n\n    in_overlap = df[\"name_old\"].notna() & df[\"name_new\"].notna()\n    def_overlap = df[\"definition_old\"].notna() & df[\"definition_new\"].notna()\n    newly_added_defs = in_overlap & df[\"definition_old\"].isna() & df[\"definition_new\"].notna()\n\n    df[\"name_changed\"] = in_overlap & df[\"name_old\"].ne(df[\"name_new\"])\n    df[\"definition_changed\"] = def_overlap & df[\"definition_old\"].ne(\n        df[\"definition_new\"]\n    )\n\n    old_len = df[\"definition_old\"].fillna(\"\").astype(str).str.len()\n    new_len = df[\"definition_new\"].fillna(\"\").astype(str).str.len()\n    changed_def = df[\"definition_changed\"]\n\n    df[\"definition_delta\"] = np.select(\n        [changed_def & (new_len > old_len),\n         changed_def & (new_len < old_len),\n         changed_def & (new_len == old_len)],\n        [\"Extended\", \"Simplified\", \"Same length\"],\n        default=pd.NA,\n    )\n\n    df[\"term_status\"] = np.select(\n        [df[\"GOID\"].isin(added_terms),\n        df[\"GOID\"].isin(removed_terms),\n        df[\"GOID\"].isin(new_obsoletes)],\n        [\"Added term\", \"Removed term\", \"Newly obsolete\"],\n        default=\"Present in both\",\n    )\n\n    metrics = pd.Series(\n        {\n            \"Terms (old)\": len(old_terms),\n            \"Terms (new)\": len(new_terms),\n            \"Obsolete terms (old)\": int(old_df[\"is_obsolete\"].sum()),\n            \"Obsolete terms (new)\": int(new_df[\"is_obsolete\"].sum()),\n            \"Added terms\": len(added_terms),\n            \"Added terms (obsolete)\": len(added_as_obsolete),\n            \"Removed terms\": len(removed_terms),\n            \"Newly obsolete terms\": len(new_obsoletes),\n            \"Newly added definitions\": int(newly_added_defs.sum()),\n            \"Name changed (overlap)\": int(df[\"name_changed\"].sum()),\n            \"Definition changed (overlap)\": int(df[\"definition_changed\"].sum()),\n            \"Definition simplified (overlap)\": int(\n                (df[\"definition_delta\"] == \"Simplified\").sum()\n            ),\n            \"Definition extended (overlap)\": int(\n                (df[\"definition_delta\"] == \"Extended\").sum()\n            ),\n        },\n        name=\"N\",\n    )\n\n    summary_fields = metrics.rename_axis(\"metric\").reset_index()\n\n    return {\"summary_fields\": summary_fields, \"df\": df}\n\n\ndef plot_term_status(df, title):\n    counts = (\n        df[\"term_status\"].value_counts()\n        .rename_axis(\"term_status\")\n        .reset_index(name=\"N\")\n    )\n    ax = counts.plot(\n        kind=\"bar\", x=\"term_status\", y=\"N\", figsize=(5, 3),\n        width=0.65, color=\"steelblue\", legend=False\n    )\n    ax.set_xlabel(\"\")\n    ax.set_ylabel(\"Number of terms\")\n    ax.set_title(title)\n    ax.tick_params(axis=\"x\", labelrotation=0)\n    \n    y_max = counts[\"N\"].max()\n    ax.set_ylim(0, int(y_max * 1.12))\n    \n    for bar in ax.patches:\n        height = bar.get_height()\n        ax.text(bar.get_x() + bar.get_width() / 2, height + 0.02 * y_max,\n                f\"{int(height):,}\", ha=\"center\", va=\"bottom\", fontsize=11)\n    return ax","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2025-12-27T22:28:13.272367Z","iopub.execute_input":"2025-12-27T22:28:13.272727Z","iopub.status.idle":"2025-12-27T22:28:13.291349Z","shell.execute_reply.started":"2025-12-27T22:28:13.2727Z","shell.execute_reply":"2025-12-27T22:28:13.290384Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"CAFA6_DIR = \"/kaggle/input/cafa-6-protein-function-prediction\"\nCAFA5_DIR = \"/kaggle/input/cafa-5-protein-function-prediction\"\nobo_current = Path(CAFA6_DIR, \"Train/go-basic.obo\")\nobo_cafa5 = Path(CAFA5_DIR, \"Train/go-basic.obo\")\n\nres = compare_go_obo(obo_cafa5, obo_current)\ndisplay(res[\"summary_fields\"])","metadata":{"execution":{"iopub.status.busy":"2025-12-27T22:28:13.292264Z","iopub.execute_input":"2025-12-27T22:28:13.292534Z","iopub.status.idle":"2025-12-27T22:28:18.190372Z","shell.execute_reply.started":"2025-12-27T22:28:13.292509Z","shell.execute_reply":"2025-12-27T22:28:18.189581Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"res[\"df\"].loc[\n    res[\"df\"][\"definition_changed\"],\n    [\"GOID\", \"definition_old\", \"definition_new\"]\n]","metadata":{"execution":{"iopub.status.busy":"2025-12-27T22:28:18.191245Z","iopub.execute_input":"2025-12-27T22:28:18.191466Z","iopub.status.idle":"2025-12-27T22:28:18.211265Z","shell.execute_reply.started":"2025-12-27T22:28:18.191448Z","shell.execute_reply":"2025-12-27T22:28:18.210467Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<div style=\"line-height:24px; font-size:16px;border-left: 5px solid silver; padding-left: 26px;\"> \n    💡 Note (changes over 4 years): \n    <ul style=\"list-style:circle\">\n        <li>Number of terms added in the latest version: 684 (20 were added as obsolete)</li>\n        <li>Number of terms removed in the latest version: 0</li>\n        <li>Number of newly obsolete terms: 3,982</li>\n        <li>Number of terms with changed definitions: 7,710, of which:</li>\n            <ul style=\"list-style:disc; margin-left: 20px;\">\n                <li>Simplified definitions: 2,808</li>\n                <li>Extended definitions: 4,797</li>\n            </ul>\n        <li>Newly added definitions: 0</li>\n    </ul>\n</div>","metadata":{}},{"cell_type":"markdown","source":"# CAFA6 training set","metadata":{}},{"cell_type":"markdown","source":"This set contains all proteins with annotated terms that have been validated by experimental or high-throughput evidence, traceable author statement (evidence code TAS), or inferred by the curator (IC).","metadata":{}},{"cell_type":"code","source":"train_path = Path(CAFA6_DIR, \"Train/train_terms.tsv\")\ntrain_set = pd.read_csv(\n    train_path, sep=\"\\t\", dtype={\n        \"EntryID\": \"string\",\n        \"term\": \"string\",\n        \"aspect\": \"string\"}\n    )\n\naspect_map = {\"P\": \"BP\", \"F\": \"MF\", \"C\": \"CC\", \"BPO\": \"BP\", \"MFO\": \"MF\", \"CCO\": \"CC\"}\ntrain_set[\"domain\"] = train_set[\"aspect\"].map(aspect_map).fillna(train_set[\"aspect\"])\n\nprint(f\"The head of the dataset with {len(train_set):,} rows\")\ndisplay(train_set.head())","metadata":{"execution":{"iopub.status.busy":"2025-12-27T22:28:18.212232Z","iopub.execute_input":"2025-12-27T22:28:18.21247Z","iopub.status.idle":"2025-12-27T22:28:18.669317Z","shell.execute_reply.started":"2025-12-27T22:28:18.212451Z","shell.execute_reply":"2025-12-27T22:28:18.668438Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"n_proteins = train_set[\"EntryID\"].nunique()\nn_terms = train_set[\"term\"].nunique()\nprint(f\"Unique proteins: {n_proteins:,}\")\nprint(f\"Unique GO terms: {n_terms:,}\")\n\nper_protein = train_set.groupby(\"EntryID\", sort=False)[\"term\"].nunique()\nn_le_10 = int((per_protein <= 10).sum())\nprint(\"Number of GO terms per protein:\")\nprint(f\"range: {int(per_protein.min())} to {int(per_protein.max())}\")\nprint(f\"mean: {per_protein.mean():.3f}\")\nprint(f\"median: {per_protein.median():.0f}\")\nprint(f\"Number of proteins with 10 or lesser GO terms: {n_le_10:,} \"\n      f\"({n_le_10 / n_proteins:.2%} of proteins)\")\n\nper_term = train_set.groupby(\"term\", sort=False)[\"EntryID\"].nunique()\nn_singletons = int((per_term == 1).sum())\nprint(f\"Number of GO terms assigned to only one protein: {n_singletons:,} \"\n      f\"({n_singletons / n_terms:.2%} of GO terms)\")\n\nby_aspect = train_set.groupby(\"domain\").agg(\n    n_Proteins=(\"EntryID\", \"nunique\"),\n    n_GOterms=(\"term\", \"nunique\"),\n).reset_index()\nprint(\"\\nNumber of unique proteins and GO terms by ontology:\")\ndisplay(by_aspect)","metadata":{"execution":{"iopub.status.busy":"2025-12-27T22:28:18.670326Z","iopub.execute_input":"2025-12-27T22:28:18.670629Z","iopub.status.idle":"2025-12-27T22:28:19.462975Z","shell.execute_reply.started":"2025-12-27T22:28:18.670603Z","shell.execute_reply":"2025-12-27T22:28:19.462121Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"The empirical distribution of the number of GO terms annotated per protein:","metadata":{}},{"cell_type":"code","source":"terms_per_prot = (\n    train_set.groupby([\"EntryID\", \"domain\"], sort=False)[\"term\"]\n    .nunique()\n    .reset_index(name=\"n_terms\")\n)\n\nmedian_by_domain = terms_per_prot.groupby(\"domain\")[\"n_terms\"].median()\n\nfig, axes = plt.subplots(1, 3, figsize=(15, 4), sharey=True)\n\nfor ax, domain in zip(axes, namespace_map.values()):\n    data = terms_per_prot.loc[\n        terms_per_prot[\"domain\"] == domain, \"n_terms\"\n    ]\n    counts = data.value_counts().sort_index()\n    ax.bar(counts.index, counts.values)\n    ax.set_yscale(\"log\")\n    ax.set_title(domain)\n    ax.set_xlabel(\"Number of GO terms per protein\")\n\n    median_val = int(median_by_domain.loc[domain])\n    ax.axvline(median_val, color=\"crimson\", lw=1)\n\n    xticks = list(ax.get_xticks())\n    if median_val not in xticks:\n        xticks.append(median_val)\n        xticks = sorted(xticks)\n        ax.set_xticks(xticks)\n\n    for tick, label in zip(ax.get_xticks(), ax.get_xticklabels()):\n        if tick == median_val:\n            label.set_color(\"crimson\")\n\naxes[0].set_ylabel(\"Number of proteins\")\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-27T22:28:19.463908Z","iopub.execute_input":"2025-12-27T22:28:19.464184Z","iopub.status.idle":"2025-12-27T22:28:21.196354Z","shell.execute_reply.started":"2025-12-27T22:28:19.464158Z","shell.execute_reply":"2025-12-27T22:28:21.195194Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"💡 Note: the number of GO terms per protein is strongly right-skewed across all 3 domains: most proteins have only a small number of GO annotations, while a small minority have very large annotation sets. The upper tail reaches roughly ~35 terms in MF, ~42 in CC, and ~190 in BP. The median number of terms per protein in each ontology is 2.","metadata":{}},{"cell_type":"markdown","source":"In the tables below I select 10 most/least common GO terms in CAFA5 training set from biological processes (BP) ontology and show:\n- `n_proteins` - the number of training set annotation rows (equivalently, proteins) carrying this GO term\n- `level_in_DAG` - the depth of the term in the GO directed acyclic graph (DAG) (larger values = more specific terms)\n- `n_ANCESTORS` - the parents, and all their parents and so on\n- `n_PARENTS` - the number of immediate parent terms\n- `n_OFFSPRINGS` - the children, their children and so on out to the leaves\n- `n_CHILDREN` - the number of immediate child terms","metadata":{}},{"cell_type":"code","source":"def term_table(train_df, domain, k=10, rare=False):\n    subset = train_df.loc[train_df[\"domain\"].eq(domain), [\"term\", \"EntryID\"]]\n    if subset.empty:\n        return pd.DataFrame(\n            {\"GO_id\": pd.Series([], dtype=\"string\"), \"n_proteins\": pd.Series([], dtype=\"int64\")}\n        )\n    counts = subset.groupby(\"term\", sort=False)[\"EntryID\"].size()\n    counts = counts.sort_values(ascending=rare).head(k)\n    return counts.rename(\"n_proteins\").reset_index().rename(columns={\"term\": \"GO_id\"})\n\ndef annotate_go_table(go_dag, df, wrap_width=35):\n    go_ids = df[\"GO_id\"].tolist()\n    df = df.copy()\n    df[\"GO_term\"] = [\n        fill(getattr(go_dag.get(go_id), \"name\", \"\"), width=wrap_width) for go_id in go_ids\n    ]\n    df[\"level_in_DAG\"] = [\n        getattr(go_dag.get(go_id), \"level\", np.nan)\n        for go_id in go_ids\n    ]\n    df[\"n_ANCESTORS\"] = [\n        len(getattr(go_dag.get(go_id), \"get_all_parents\", lambda: set())())\n        for go_id in go_ids\n    ]\n    df[\"n_PARENTS\"] = [\n        len(getattr(go_dag.get(go_id), \"parents\", {}))\n        for go_id in go_ids\n    ]\n    df[\"n_CHILDREN\"] = [\n        len(getattr(go_dag.get(go_id), \"children\", []))\n        for go_id in go_ids\n    ]\n    df[\"n_OFFSPRINGS\"] = [\n        len(getattr(go_dag.get(go_id), \"get_all_children\", lambda: set())())\n        for go_id in go_ids\n    ]\n    return df","metadata":{"execution":{"iopub.status.busy":"2025-12-27T22:28:21.197363Z","iopub.execute_input":"2025-12-27T22:28:21.197673Z","iopub.status.idle":"2025-12-27T22:28:21.208114Z","shell.execute_reply.started":"2025-12-27T22:28:21.197649Z","shell.execute_reply":"2025-12-27T22:28:21.207077Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"bp_common = term_table(train_set, domain=\"BP\", k=10, rare=False)\nbp_common = annotate_go_table(go_dag, bp_common, wrap_width=35)\ndisplay(bp_common)","metadata":{"execution":{"iopub.status.busy":"2025-12-27T22:28:21.209308Z","iopub.execute_input":"2025-12-27T22:28:21.20962Z","iopub.status.idle":"2025-12-27T22:28:21.390181Z","shell.execute_reply.started":"2025-12-27T22:28:21.209572Z","shell.execute_reply":"2025-12-27T22:28:21.389291Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"bp_rare = term_table(train_set, \"BP\", k=10, rare=True)\nbp_rare = annotate_go_table(go_dag, bp_rare, wrap_width=35)\ndisplay(bp_rare)","metadata":{"execution":{"iopub.status.busy":"2025-12-27T22:28:21.391285Z","iopub.execute_input":"2025-12-27T22:28:21.391613Z","iopub.status.idle":"2025-12-27T22:28:21.556507Z","shell.execute_reply.started":"2025-12-27T22:28:21.391561Z","shell.execute_reply":"2025-12-27T22:28:21.555753Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"💡 Note: The most frequent BP terms differ between CAFA5 (see this notebook: https://www.kaggle.com/code/antoninadolgorukova/gene-ontology-explorer) and CAFA6. In CAFA5, the top terms included very general BP nodes (up to the root, e.g., GO:0008150 biological_process), while in CAFA6 the most frequent terms are mid-level processes and no root/near-root BP terms appear among the top counts.","metadata":{}},{"cell_type":"markdown","source":"For each GO term, let's compute how many distinct proteins are annotated with it, and its depth in the GO hierarchy:","metadata":{}},{"cell_type":"code","source":"term_counts = train_set.groupby(\"term\", sort=False)[\"EntryID\"].nunique()\nterm_meta = term_counts.rename(\"n_proteins\").reset_index().rename(\n    columns={\"term\": \"GO_id\"}\n)\nterm_meta[\"GO_term\"] = term_meta[\"GO_id\"].map(\n    lambda go_id: go_dag[go_id].name if go_id in go_dag else pd.NA\n)\nterm_meta[\"depth\"] = term_meta[\"GO_id\"].map(\n    lambda go_id: go_dag[go_id].depth if go_id in go_dag else pd.NA\n)\nterm_meta[\"domain\"] = term_meta[\"GO_id\"].map(\n    lambda go_id: namespace_map.get(go_dag[go_id].namespace, pd.NA)\n    if go_id in go_dag else pd.NA\n)\nterm_meta","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-27T22:28:21.557447Z","iopub.execute_input":"2025-12-27T22:28:21.557775Z","iopub.status.idle":"2025-12-27T22:28:21.867758Z","shell.execute_reply.started":"2025-12-27T22:28:21.557754Z","shell.execute_reply":"2025-12-27T22:28:21.866922Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"fig, ax = plt.subplots(figsize=(14, 5))\n\nax.hist(\n    term_meta[\"n_proteins\"],\n    bins=50,\n    log=True\n)\nax.set_xlabel(\"Number of proteins assigned a GO term\")\nax.set_ylabel(\"Number of GO terms\")\nax.set_title(\"Distribution of proteins per GO term\")\n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-27T22:28:21.86864Z","iopub.execute_input":"2025-12-27T22:28:21.868951Z","iopub.status.idle":"2025-12-27T22:28:22.462014Z","shell.execute_reply.started":"2025-12-27T22:28:21.868922Z","shell.execute_reply":"2025-12-27T22:28:22.460991Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"💡 Note: On the plot, we see that the vast majority of GO terms are assigned to only a small number of proteins, whereas a small number of GO terms are assigned to tens of thousands of proteins.","metadata":{}},{"cell_type":"code","source":"fig, axes = plt.subplots(1, 3, figsize=(15, 4), sharey=True)\n\nfor ax, domain in zip(axes, namespace_map.values()):\n    depth_counts = (\n        term_meta.loc[term_meta[\"domain\"] == domain]\n        .dropna(subset=[\"depth\"])\n        .groupby(\"depth\", sort=True)\n        .size()\n    )\n    ax.bar(depth_counts.index, depth_counts.values)\n    ax.set_title(domain)\n    ax.set_xlabel(\"GO term depth\")\n\naxes[0].set_ylabel(\"Number of GO terms\")\n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-27T22:28:22.466421Z","iopub.execute_input":"2025-12-27T22:28:22.466848Z","iopub.status.idle":"2025-12-27T22:28:22.998765Z","shell.execute_reply.started":"2025-12-27T22:28:22.466817Z","shell.execute_reply":"2025-12-27T22:28:22.997819Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"💡 Note: GO terms are concentrated at intermediate depths in all three ontology graphs, forming unimodal depth distributions (except CC).","metadata":{}},{"cell_type":"markdown","source":"Next, we determine whether GO terms assigned to the same protein tend to lie on the same ancestor–descendant paths in the Gene Ontology graph, or whether they are mostly independent annotations located on different branches of the ontology.","metadata":{}},{"cell_type":"code","source":"from functools import lru_cache\n\n@lru_cache(maxsize=None)\ndef all_parents(go_id: str) -> frozenset[str]:\n    if go_id not in go_dag:\n        return frozenset()\n    return frozenset(go_dag[go_id].get_all_parents())\n\n\ndef protein_go_dependency_stats(annotations: pd.DataFrame) -> pd.DataFrame:\n    protein_to_terms = (\n        annotations.groupby(\"EntryID\", sort=False)[\"term\"]\n        .apply(lambda s: set(s.dropna().unique()))\n    )\n\n    rows = []\n    for entry_id, term_set in protein_to_terms.items():\n        valid_terms = {go_id for go_id in term_set if go_id in go_dag}\n        if not valid_terms:\n            rows.append({\n                \"EntryID\": entry_id,\n                \"n_terms\": 0,\n                \"n_dependent_terms\": 0,\n                \"share_dependent_terms\": 0.0,\n                \"has_any_dependency\": False,\n            })\n            continue\n\n        dependent_terms = set()\n        for go_id in valid_terms:\n            if all_parents(go_id) & valid_terms:\n                dependent_terms.add(go_id)\n\n        n_terms = len(valid_terms)\n        n_dependent = len(dependent_terms)\n\n        rows.append({\n            \"EntryID\": entry_id,\n            \"n_terms\": n_terms,\n            \"n_dependent_terms\": n_dependent,\n            \"share_dependent_terms\": n_dependent / n_terms,\n            \"has_any_dependency\": n_dependent > 0,\n        })\n\n    return pd.DataFrame(rows)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-27T22:28:22.999651Z","iopub.execute_input":"2025-12-27T22:28:23.000197Z","iopub.status.idle":"2025-12-27T22:28:23.009441Z","shell.execute_reply.started":"2025-12-27T22:28:23.000166Z","shell.execute_reply":"2025-12-27T22:28:23.008479Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"protein_stats = protein_go_dependency_stats(train_set)\nprotein_stats.sort_values(\n    [\"n_dependent_terms\", \"share_dependent_terms\"],\n    ascending=False\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-27T22:28:23.010418Z","iopub.execute_input":"2025-12-27T22:28:23.010836Z","iopub.status.idle":"2025-12-27T22:28:47.782037Z","shell.execute_reply.started":"2025-12-27T22:28:23.010806Z","shell.execute_reply":"2025-12-27T22:28:47.780907Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"summary = pd.Series({\n    \"n_proteins\": len(protein_stats),\n    \"share_with_any_dependency\":\n        protein_stats[\"has_any_dependency\"].mean(),\n    \"median_terms_per_protein\":\n        protein_stats[\"n_terms\"].median(),\n    \"median_share_dependent_terms\":\n        protein_stats[\"share_dependent_terms\"].median(),\n})\nsummary","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-27T22:28:47.78301Z","iopub.execute_input":"2025-12-27T22:28:47.783297Z","iopub.status.idle":"2025-12-27T22:28:47.794811Z","shell.execute_reply.started":"2025-12-27T22:28:47.78327Z","shell.execute_reply":"2025-12-27T22:28:47.793754Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"💡 It seems, for the majority of proteins, none of their assigned GO terms stand in an explicit ancestor-descendant relationship with another term assigned to the same protein, but approximately 29% of proteins have at least one GO term that is hierarchically related to another term in their annotation set.","metadata":{}},{"cell_type":"markdown","source":"# GO term tracking in GO GAD","metadata":{}},{"cell_type":"markdown","source":"Now let's track one term of interest in the DAG up to its root.","metadata":{}},{"cell_type":"code","source":"GO_id = \"GO:0006357\"\n\ngo_term = go_dag.get(GO_id)\ngo_term","metadata":{"execution":{"iopub.status.busy":"2025-12-27T22:28:47.79573Z","iopub.execute_input":"2025-12-27T22:28:47.795965Z","iopub.status.idle":"2025-12-27T22:28:47.807964Z","shell.execute_reply.started":"2025-12-27T22:28:47.795946Z","shell.execute_reply":"2025-12-27T22:28:47.80701Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"\\n\\nProteins having this GO term in their annotation\")\ntrain_set.loc[train_set[\"term\"] == GO_id]","metadata":{"_kg_hide-input":false,"execution":{"iopub.status.busy":"2025-12-27T22:28:47.809146Z","iopub.execute_input":"2025-12-27T22:28:47.809411Z","iopub.status.idle":"2025-12-27T22:28:47.877523Z","shell.execute_reply.started":"2025-12-27T22:28:47.80939Z","shell.execute_reply":"2025-12-27T22:28:47.876696Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def build_term_family_graph(go_dag, term_id):\n    graph = nx.DiGraph()\n    term = go_dag[term_id]\n\n    parents_by_rel = defaultdict(set)\n    for parent in getattr(term, \"parents\", []) or []:\n        if not getattr(parent, \"is_obsolete\", False):\n            parents_by_rel[\"is_a\"].add(parent)\n\n    relationships = getattr(term, \"relationship\", None) or {}\n    for rel_type, rel_terms in relationships.items():\n        for parent in rel_terms:\n            if not getattr(parent, \"is_obsolete\", False):\n                parents_by_rel[rel_type].add(parent)\n\n    children_by_rel = defaultdict(set)\n    for child in getattr(term, \"children\", []) or []:\n        if not getattr(child, \"is_obsolete\", False):\n            children_by_rel[\"is_a\"].add(child)\n\n    rel_rev = getattr(term, \"relationship_rev\", None) or {}\n    for rel_type, rel_terms in rel_rev.items():\n        for child in rel_terms:\n            if not getattr(child, \"is_obsolete\", False):\n                children_by_rel[rel_type].add(child)\n\n    graph.add_node(term_id, level=2)\n\n    for rel_type, parents in parents_by_rel.items():\n        for parent in sorted(parents, key=lambda t: t.id):\n            graph.add_node(parent.id, level=1)\n            graph.add_edge(parent.id, term_id, rel=rel_type)\n\n    for rel_type, children in children_by_rel.items():\n        for child in sorted(children, key=lambda t: t.id):\n            graph.add_node(child.id, level=3)\n            graph.add_edge(term_id, child.id, rel=rel_type)\n\n    node_set = set(graph.nodes())\n    for node_id in list(node_set):\n        node = go_dag[node_id]\n        rel_rev = getattr(node, \"relationship_rev\", None) or {}\n        for rel_type, rel_terms in rel_rev.items():\n            for child in rel_terms:\n                if getattr(child, \"is_obsolete\", False):\n                    continue\n                if child.id in node_set:\n                    graph.add_edge(node_id, child.id, rel=rel_type)\n\n    return graph","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2025-12-27T22:28:47.878647Z","iopub.execute_input":"2025-12-27T22:28:47.879151Z","iopub.status.idle":"2025-12-27T22:28:47.890707Z","shell.execute_reply.started":"2025-12-27T22:28:47.879124Z","shell.execute_reply":"2025-12-27T22:28:47.889733Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"graph = build_term_family_graph(go_dag, GO_id)\ntitle = f\"GO term family: {GO_id} ({go_dag[GO_id].name})\"\n\nHTML_obj = pyvis_render(go_dag, graph, wrap_label=True, title=title)\ndisplay(HTML_obj)","metadata":{"execution":{"iopub.status.busy":"2025-12-27T22:28:47.891792Z","iopub.execute_input":"2025-12-27T22:28:47.892535Z","iopub.status.idle":"2025-12-27T22:28:48.030984Z","shell.execute_reply.started":"2025-12-27T22:28:47.892506Z","shell.execute_reply":"2025-12-27T22:28:48.030009Z"},"trusted":true},"outputs":[],"execution_count":null}]}