{"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":[{"sourceType":"competition","sourceId":116062,"databundleVersionId":14084779},{"sourceType":"datasetVersion","sourceId":13680623,"datasetId":8699749,"databundleVersionId":14422004},{"sourceType":"datasetVersion","sourceId":13502493,"datasetId":8572953,"databundleVersionId":14224132},{"sourceType":"kernelVersion","sourceId":284705615}],"dockerImageVersionId":31192,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os, gc\nfrom collections import defaultdict\n\nimport pandas as pd\nfrom tqdm.auto import tqdm\nimport numpy as np","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-12-07T07:15:07.996638Z","iopub.execute_input":"2025-12-07T07:15:07.996940Z","iopub.status.idle":"2025-12-07T07:15:10.349977Z","shell.execute_reply.started":"2025-12-07T07:15:07.996912Z","shell.execute_reply":"2025-12-07T07:15:10.347575Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def read_train_terms(path):\n    mapping = defaultdict(list)\n    df = pd.read_csv(path, sep=\"\\t\", header=None, names=[\"protein\",\"go\",\"ont\"], dtype=str)\n    for _, r in tqdm(df.iterrows(), total=len(df)): \n        mapping[r.protein].append(r.go)\n    print(f\"[io] Read training annotations for {len(mapping)} proteins from {path}\")\n    return mapping\n\ndef parse_obo(go_obo_path):\n    parents = defaultdict(set)\n    children = defaultdict(set)\n    \n    if not os.path.exists(go_obo_path): \n        return parents, children\n        \n    with open(go_obo_path,\"r\") as f:\n        cur_id=None\n        for line in f:\n            line=line.strip()\n            if line==\"[Term]\": \n                cur_id=None\n            elif line.startswith(\"id: \"): \n                cur_id=line.split(\"id: \")[1].strip()\n            elif line.startswith(\"is_a: \"):\n                pid=line.split()[1].strip()\n                if cur_id: \n                    parents[cur_id].add(pid)\n                    children[pid].add(cur_id)\n            elif line.startswith(\"relationship: part_of \"):\n                parts=line.split(); \n                if len(parts)>=3:\n                    pid=parts[2].strip()\n                    if cur_id: \n                        parents[cur_id].add(pid)\n                        children[pid].add(cur_id)\n    print(f\"[io] Parsed OBO: {len(parents)} nodes with parents\")\n    return parents, children\n\ndef get_ancestors(go_id, parents):\n    ans=set()\n    stack=[go_id]\n    while stack:\n        cur=stack.pop()\n        for p in parents.get(cur,[]): \n            if p not in ans:\n                ans.add(p)\n                stack.append(p)\n    return ans\n\ndef get_descendants(go_id):\n    desc = set()\n    stack = [go_id]\n    while stack:\n        cur = stack.pop()\n        for child in children_map.get(cur, []):\n            if child not in desc:\n                desc.add(child)\n                stack.append(child)\n    return desc","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-07T07:15:10.352452Z","iopub.execute_input":"2025-12-07T07:15:10.353549Z","iopub.status.idle":"2025-12-07T07:15:10.375638Z","shell.execute_reply.started":"2025-12-07T07:15:10.353517Z","shell.execute_reply":"2025-12-07T07:15:10.374833Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_terms = read_train_terms(\"/kaggle/input/cafa-6-protein-function-prediction/Train/train_terms.tsv\")\nparents_map, children_map = parse_obo(\"/kaggle/input/cafa-6-protein-function-prediction/Train/go-basic.obo\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-07T07:15:10.377403Z","iopub.execute_input":"2025-12-07T07:15:10.377713Z","iopub.status.idle":"2025-12-07T07:15:46.312606Z","shell.execute_reply.started":"2025-12-07T07:15:10.377688Z","shell.execute_reply":"2025-12-07T07:15:46.311441Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"go_annotations = pd.read_csv('/kaggle/input/protein-go-annotations/goa_uniprot_all.csv')\ngo_annotations = go_annotations.drop_duplicates()\nprint(f'[+] Dataset shape: {go_annotations.shape}')\ngo_annotations.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-07T07:15:46.313598Z","iopub.execute_input":"2025-12-07T07:15:46.313999Z","iopub.status.idle":"2025-12-07T07:15:49.471891Z","shell.execute_reply.started":"2025-12-07T07:15:46.313968Z","shell.execute_reply":"2025-12-07T07:15:49.471011Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"go_annotations.qualifier.value_counts()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-07T07:15:49.472746Z","iopub.execute_input":"2025-12-07T07:15:49.473043Z","iopub.status.idle":"2025-12-07T07:15:49.659222Z","shell.execute_reply.started":"2025-12-07T07:15:49.473015Z","shell.execute_reply":"2025-12-07T07:15:49.658466Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(f\"[1/3] Filtering Negative Annotations ..\")\nnegative_annots = go_annotations[go_annotations['qualifier'].str.contains('NOT', na=False)]\nnegative_annots = negative_annots.drop(columns=['qualifier']).drop_duplicates()\n\nprint(f\"[2/3] Propagate Negative Terms ..\")\nnegative_annots = negative_annots.groupby('protein_id')['go_term'].apply(list).to_dict()\n\npropagated={}\nfor p in tqdm(negative_annots.keys()):\n    terms=set(negative_annots[p])\n    extra=set()\n    for t in list(terms): \n        extra |= get_descendants(t)\n    propagated[p] = sorted(terms | extra)\n        \nnegative_annots = propagated\n\nprint(f\"[3/3] Extract Unique Keys ..\")\nrows = [(protein_id, go_term) for protein_id, terms in negative_annots.items() for go_term in terms]\nnegative_df = pd.DataFrame(rows, columns=[\"protein_id\", \"go_term\"])\nnegative_df['pred_key'] = negative_df.protein_id.apply(str) + '_' + negative_df.go_term.apply(str)\nnegative_keys = set(negative_df['pred_key'])\n\ndel negative_df\ngc.collect()\n\nprint(f\"Total unique negative protein-GO pairs: {len(negative_keys)}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-07T07:15:49.660100Z","iopub.execute_input":"2025-12-07T07:15:49.660427Z","iopub.status.idle":"2025-12-07T07:15:51.195091Z","shell.execute_reply.started":"2025-12-07T07:15:49.660397Z","shell.execute_reply":"2025-12-07T07:15:51.194311Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(f\"[1/4] Loading GOA Annotations ..\")\ngo_annotations = pd.read_csv('/kaggle/input/protein-go-annotations/goa_uniprot_all.csv')\n\nprint(f\"[2/4] Removing unwanted annotations ..\")\ngo_annotations = go_annotations[~go_annotations['qualifier'].str.contains('NOT', na=False)]\ngo_annotations.drop(columns=['qualifier'], inplace=True)\ngo_annotations = go_annotations.drop_duplicates()\n\nprint(f\"[3/4] Set Ground-Truth Score ..\")\ngo_annotations['score'] = round(1.0, 3)\n\nprint(f\"[4/4] Setting Key ..\")\ngo_annotations['pred_key'] = go_annotations['protein_id'].astype(str) + '_' + go_annotations['go_term'].astype(str)\ngo_annotations = go_annotations[~go_annotations['pred_key'].isin(negative_keys)]\ngoa_pred_keys = set(go_annotations['pred_key'])\nprint(f\"[+] Total unique ground truth protein-GO pairs: {len(goa_pred_keys)}\")\nprint(f\"[✅] Done.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-07T07:15:51.197094Z","iopub.execute_input":"2025-12-07T07:15:51.197519Z","iopub.status.idle":"2025-12-07T07:15:56.356912Z","shell.execute_reply.started":"2025-12-07T07:15:51.197498Z","shell.execute_reply":"2025-12-07T07:15:56.355806Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def load_submission(path, chunksize=50000, num_rows = None):\n    total = None\n    if num_rows:\n        total = int(num_rows / chunksize) + 1 \n    chunks = []\n    for chunk in tqdm(pd.read_csv(path, sep='\\t', header=None, chunksize=chunksize), total = total):\n        chunk['pred_key'] = chunk[0].astype(str) + '_' + chunk[1].astype(str)\n        chunks.append(chunk)\n    df = pd.concat(chunks, ignore_index=True)\n    df.columns = ['protein_id', 'go_term', 'score', 'pred_key']\n    return df","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-07T07:15:56.357688Z","iopub.execute_input":"2025-12-07T07:15:56.357994Z","iopub.status.idle":"2025-12-07T07:15:56.364544Z","shell.execute_reply.started":"2025-12-07T07:15:56.357963Z","shell.execute_reply":"2025-12-07T07:15:56.363576Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"!wc -l /kaggle/input/cafa6-protbert/submission.tsv","metadata":{"execution":{"iopub.status.busy":"2025-12-08T13:44:13.474944Z","iopub.execute_input":"2025-12-08T13:44:13.475252Z","iopub.status.idle":"2025-12-08T13:44:32.564988Z","shell.execute_reply.started":"2025-12-08T13:44:13.475230Z","shell.execute_reply":"2025-12-08T13:44:32.563723Z"}}},{"cell_type":"code","source":"print(f\"[1/2] Loading 1st submission ..\")\nA = load_submission('/kaggle/input/cafa6-protbert/submission.tsv', num_rows = 112154500)\nA.shape","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(f\"[1/2] Removing Ground-Truth from A ..\")\nA = A[~A.pred_key.isin(goa_pred_keys)]\nprint(f\"[2/2] Removing Negatives from A ..\")\nA = A[~A.pred_key.isin(negative_keys)]","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"A.drop(columns=['pred_key'], inplace=True)\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(f'[⏳] Saving Submission ...')\nA.to_csv('submission.tsv',sep='\\t', index=False, header=None)\nprint(f\"[✅] Done.\")","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}