{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"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":116062,"databundleVersionId":14084779,"sourceType":"competition"}],"dockerImageVersionId":31192,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-11-30T08:25:22.996194Z","iopub.execute_input":"2025-11-30T08:25:22.996664Z","iopub.status.idle":"2025-11-30T08:25:25.461114Z","shell.execute_reply.started":"2025-11-30T08:25:22.996625Z","shell.execute_reply":"2025-11-30T08:25:25.459986Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"pip install networkx matplotlib","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-30T08:25:25.463126Z","iopub.execute_input":"2025-11-30T08:25:25.463582Z","iopub.status.idle":"2025-11-30T08:25:31.511499Z","shell.execute_reply.started":"2025-11-30T08:25:25.463555Z","shell.execute_reply":"2025-11-30T08:25:31.510240Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import networkx as nx\nimport matplotlib.pyplot as plt\n\ndef parse_obo_file(file_path):\n    graph = nx.DiGraph()\n    with open(file_path, 'r') as f:\n        current_term = None\n        for line in f:\n            line = line.strip()\n            if line == \"[Term]\":\n                current_term = {}\n            elif line == \"\" and current_term:\n                if 'id' in current_term:\n                    node_id = current_term['id']\n                    graph.add_node(node_id, **current_term)\n                    for parent_id in current_term.get('is_a', []):\n                        graph.add_edge(parent_id, node_id) \n                current_term = None\n            elif current_term is not None:\n                if line.startswith(\"id: \"):\n                    current_term['id'] = line[4:]\n                elif line.startswith(\"name: \"):\n                    current_term['name'] = line[6:]\n                elif line.startswith(\"namespace: \"):\n                    current_term['namespace'] = line[11:]\n                elif line.startswith(\"is_a: \"):\n                    parent_id = line[6:].split(' ! ')[0]\n                    if 'is_a' not in current_term:\n                        current_term['is_a'] = []\n                    current_term['is_a'].append(parent_id)\n    print(f\"Tổng số nốt: {graph.number_of_nodes()}\")\n    return graph\n\ndef hierarchy_pos(G, root=None, width=1., vert_gap=0.2, vert_loc=0, xcenter=0.5):\n    if not nx.is_tree(G):\n        if root is None:\n            roots = [n for n, d in G.in_degree() if d == 0]\n            if not roots: return None\n            root = roots[0]\n        G = nx.bfs_tree(G, root)\n\n    def _hierarchy_pos(G, root, width=1., vert_gap=0.2, vert_loc=0, xcenter=0.5, pos=None, parent=None):\n        if pos is None:\n            pos = {root: (xcenter, vert_loc)}\n        else:\n            pos[root] = (xcenter, vert_loc)\n        children = list(G.neighbors(root))\n        if len(children) != 0:\n            dx = width / len(children) \n            nextx = xcenter - width/2 - dx/2\n            for child in children:\n                nextx += dx\n                pos = _hierarchy_pos(G, child, width=dx, vert_gap=vert_gap, \n                                     vert_loc=vert_loc-vert_gap, xcenter=nextx,\n                                     pos=pos, parent=root)\n        return pos\n    return _hierarchy_pos(G, root, width, vert_gap, vert_loc, xcenter)\n\ndef draw_ancestors_tree(G, target_id):\n    if target_id not in G:\n        print(f\"Không tìm thấy ID {target_id}.\")\n        return\n\n    target_name = G.nodes[target_id].get('name', 'Unknown')\n    \n    nodes_to_draw = {target_id}\n    queue = [target_id]\n    while queue:\n        curr = queue.pop(0)\n        parents = list(G.predecessors(curr)) \n        for p in parents:\n            if p not in nodes_to_draw:\n                nodes_to_draw.add(p)\n                queue.append(p)\n    \n    subG = G.subgraph(nodes_to_draw)\n\n    roots = [n for n, d in subG.in_degree() if d == 0]\n    if not roots: return\n    main_root = roots[0]\n    \n    pos = hierarchy_pos(subG, root=main_root)\n    \n    plt.figure(figsize=(14, 10))\n    ax = plt.gca()\n\n    nx.draw_networkx_edges(subG, pos, \n                           edge_color='gray', \n                           arrows=True, \n                           arrowstyle='-|>', \n                           arrowsize=25, \n                           width=1.5,\n                           connectionstyle=\"arc3,rad=0.0\") \n\n    for node, (x, y) in pos.items():\n        name = subG.nodes[node].get('name', 'NA')\n        words = name.split()\n        if len(words) > 4:\n            display_name = '\\n'.join([' '.join(words[i:i+3]) for i in range(0, len(words), 3)])\n        else:\n            display_name = name.replace(\" \", \"\\n\")\n\n        if node == target_id:\n            box_color, edge_color = '#ffcccb', 'red' # Target: Đỏ\n        elif node == main_root:\n            box_color, edge_color = '#90EE90', 'green' # Root: Xanh lá\n        else:\n            box_color, edge_color = '#E0FFFF', '#4682B4' # Khác: Xanh dương nhạt\n\n        ax.text(x, y, f\"{node}\\n\\n{display_name}\", \n                bbox=dict(boxstyle=\"round,pad=0.5\", fc=box_color, ec=edge_color, lw=2),\n                ha='center', va='center', fontsize=9, fontweight='bold')\n\n    plt.title(f\"Cây Gia Phả Gene Ontology: {target_name}\", fontsize=16)\n    plt.axis('off')\n    plt.tight_layout()\n    plt.show()\n\nfile_path = '/kaggle/input/cafa-6-protein-function-prediction/Train/go-basic.obo'\n\ntry:\n    G = parse_obo_file(file_path)\n    draw_ancestors_tree(G, \"GO:0006281\")\nexcept Exception as e:\n    print(f\"Lỗi: {e}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-30T09:31:46.384542Z","iopub.execute_input":"2025-11-30T09:31:46.385687Z","iopub.status.idle":"2025-11-30T09:31:47.597715Z","shell.execute_reply.started":"2025-11-30T09:31:46.385651Z","shell.execute_reply":"2025-11-30T09:31:47.596655Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"evaluation = pd.read_csv(\"/kaggle/input/cafa-6-protein-function-prediction/IA.tsv\", sep='\\t')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-30T08:43:26.989132Z","iopub.execute_input":"2025-11-30T08:43:26.989508Z","iopub.status.idle":"2025-11-30T08:43:27.024246Z","shell.execute_reply.started":"2025-11-30T08:43:26.989481Z","shell.execute_reply":"2025-11-30T08:43:27.023300Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"evaluation.head(10)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-30T08:43:56.078128Z","iopub.execute_input":"2025-11-30T08:43:56.079036Z","iopub.status.idle":"2025-11-30T08:43:56.088297Z","shell.execute_reply.started":"2025-11-30T08:43:56.079003Z","shell.execute_reply":"2025-11-30T08:43:56.087138Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install Bio","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-30T08:50:59.409288Z","iopub.execute_input":"2025-11-30T08:50:59.410198Z","iopub.status.idle":"2025-11-30T08:51:06.052217Z","shell.execute_reply.started":"2025-11-30T08:50:59.410159Z","shell.execute_reply":"2025-11-30T08:51:06.051127Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#nối 2 bảng sequence và tẻm\n\nfrom Bio import SeqIO\nimport pandas as pd\n\ntrain_data = pd.DataFrame()\ndef load_data_demo():\n    sequences = []\n    for record in SeqIO.parse(file_path, \"fasta\"):\n        full_desc = record.description\n        \n        parts = record.id.split(\"|\")\n        protein_id = parts[1] if len(parts) > 1 else record.id\n        entry_name = parts[2] if len(parts) > 2 else None\n        \n        ox_match = re.search(r'OX=(\\d+)', full_desc)\n        taxon_id = int(ox_match.group(1)) if ox_match else None\n        \n        gn_match = re.search(r'GN=([^\\s]+)', full_desc)\n        gene_name = gn_match.group(1) if gn_match else None\n        \n        sequences.append({\n            'EntryID': protein_id,\n            'Entry_Name': entry_name,\n            'Taxon_ID': taxon_id,\n            'Gene_Name': gene_name,\n            'Sequence': str(record.seq)\n        })\n    \n    df_seq = pd.DataFrame(sequences)\n    print(\"bảng sequence\")\n    print(df_seq.head())\n\n    df_terms = pd.read_csv(\"/kaggle/input/cafa-6-protein-function-prediction/Train/train_terms.tsv\", sep=\"\\t\")\n    df_terms = df_terms[['EntryID', 'term', 'aspect']]\n    print(\"bảng term\")\n    print(df_terms.head())\n\n    train_data = pd.merge(df_seq, df_terms, on='EntryID', how='outer')\n    \n    print(\"bảng dữ liệu huấn luyện\")\n    print(train_data.head())\n    return train_data\n\ntrain_data = load_data_demo()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-30T09:44:39.389091Z","iopub.execute_input":"2025-11-30T09:44:39.389386Z","iopub.status.idle":"2025-11-30T09:44:40.988381Z","shell.execute_reply.started":"2025-11-30T09:44:39.389365Z","shell.execute_reply":"2025-11-30T09:44:40.987167Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_data","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-30T09:44:45.310807Z","iopub.execute_input":"2025-11-30T09:44:45.311224Z","iopub.status.idle":"2025-11-30T09:44:45.326142Z","shell.execute_reply.started":"2025-11-30T09:44:45.311197Z","shell.execute_reply":"2025-11-30T09:44:45.324953Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}