{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# Grab the code and weights -- Shujun saved these in Kaggle 'datasets'\n!rsync -avzL /kaggle/input/rhofold/RhoFold . >/dev/null 2>&1\n!rsync -avzL /kaggle/input/rhofold-pretrained-weights/rhofold_pretrained.pt RhoFold/pretrained/rhofold_pretrained.pt\n# Grab the pre-trained model as the documentation says\n#!wget https://proj.cse.cuhk.edu.hk/aihlab/rhofold/api/download?filename=rhofold_pretrained.pt -O RhoFold/pretrained/rhofold_pretrained.pt\n","metadata":{"execution":{"iopub.status.busy":"2023-10-31T19:33:06.837498Z","iopub.execute_input":"2023-10-31T19:33:06.837851Z","iopub.status.idle":"2023-10-31T19:33:22.037620Z","shell.execute_reply.started":"2023-10-31T19:33:06.837820Z","shell.execute_reply":"2023-10-31T19:33:22.036634Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Setup RhoFold through conda. \nNote that the weights and original code are no longer publicly available, but these files are stored in Kaggle data sets *rhofold* and *rhofold-pretrained-weights*.","metadata":{}},{"cell_type":"code","source":"# If the create command doesn't work, you may have to re-define the provided path\n# For some reason, the notebook couldn't find the file when I typed it the path, \n# but when I tab-completed the path to the file, it worked\n!conda env create -f /kaggle/working/RhoFold/envs/environment_linux.yaml >/dev/null 2>&1","metadata":{"execution":{"iopub.status.busy":"2023-10-31T19:33:22.039698Z","iopub.execute_input":"2023-10-31T19:33:22.040064Z","iopub.status.idle":"2023-10-31T19:42:49.002416Z","shell.execute_reply.started":"2023-10-31T19:33:22.040034Z","shell.execute_reply":"2023-10-31T19:42:49.001251Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Activating the conda environment in the traditional way doesn't work, but one lining\n# the activation and the desired command seems to\n!source /opt/conda/bin/activate rhofold && python RhoFold/setup.py install\n# Test as described in the RhoFold repo\n#!source /opt/conda/bin/activate rhofold && python RhoFold/inference.py --input_fas RhoFold/example/input/3owzA/3owzA.fasta --input_a3m RhoFold/example/input/3owzA/3owzA.a3m  --output_dir ./example/output/3owzA/ --ckpt RhoFold/pretrained/rhofold_pretrained.pt","metadata":{"execution":{"iopub.status.busy":"2023-10-31T19:42:49.003827Z","iopub.execute_input":"2023-10-31T19:42:49.004186Z","iopub.status.idle":"2023-10-31T19:42:50.637971Z","shell.execute_reply.started":"2023-10-31T19:42:49.004157Z","shell.execute_reply":"2023-10-31T19:42:50.636973Z"},"collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Helper functions to wrap RhoFold","metadata":{}},{"cell_type":"code","source":"def get_rhofold_3D(sequence):\n    #sequence='AUGCAUGCAUGC'\n    with open('fasta.fasta','w+') as f:\n        f.write('>test\\n')\n        f.write(sequence)\n\n    ! source /opt/conda/bin/activate rhofold && python RhoFold/inference.py --input_fas fasta.fasta --single_seq_pred True --output_dir ./rhofold_output/ --ckpt ./RhoFold/pretrained/rhofold_pretrained.pt\n    \ndef get_rhofold_3D_GPU(sequence):\n    #sequence='AUGCAUGCAUGC'\n    with open('fasta.fasta','w+') as f:\n        f.write('>test\\n')\n        f.write(sequence)\n\n    ! source /opt/conda/bin/activate rhofold && python RhoFold/inference.py --input_fas fasta.fasta --single_seq_pred True --output_dir ./rhofold_output/ --ckpt ./RhoFold/pretrained/rhofold_pretrained.pt --device cuda:0 #>/dev/null 2>&1\n    ","metadata":{"execution":{"iopub.status.busy":"2023-10-31T19:42:50.639672Z","iopub.execute_input":"2023-10-31T19:42:50.640099Z","iopub.status.idle":"2023-10-31T19:42:50.651215Z","shell.execute_reply.started":"2023-10-31T19:42:50.640062Z","shell.execute_reply":"2023-10-31T19:42:50.650164Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Sequence for AB50\nget_rhofold_3D_GPU('AGCUCGAAAAGGACCAAAACGAGCAAUAACAUAAAUAAAGGUCCAAAUAA')","metadata":{"execution":{"iopub.status.busy":"2023-10-31T19:42:50.653892Z","iopub.execute_input":"2023-10-31T19:42:50.654766Z","iopub.status.idle":"2023-10-31T19:43:00.872701Z","shell.execute_reply.started":"2023-10-31T19:42:50.654731Z","shell.execute_reply":"2023-10-31T19:43:00.871573Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Get py3Dmol installed, load up a PDB.","metadata":{}},{"cell_type":"code","source":"!pip install py3Dmol\n!wget --no-check-certificate 'https://docs.google.com/uc?export=download&id=1us10sgCvCAgqL2XVW_Df2gXX8US_qlyz' -O unrelaxed_model_PymolOUT.pdb\nimport py3Dmol","metadata":{"execution":{"iopub.status.busy":"2023-10-31T19:43:00.874241Z","iopub.execute_input":"2023-10-31T19:43:00.874613Z","iopub.status.idle":"2023-10-31T19:43:15.962681Z","shell.execute_reply.started":"2023-10-31T19:43:00.874577Z","shell.execute_reply":"2023-10-31T19:43:15.961700Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Load in Rhofold model. \nOriginally viewing the model PDB coordinates required downloading the model to my laptop, opening in Pymol, saving again, and then re-uploading via Google Drive! \nThere appears to be an atom ordering issue that is tripping up py3Dmol, which can be fixed with this line editing script.","metadata":{}},{"cell_type":"code","source":"def reorder( resi_lines):\n    '''Do backbone atom reordering for a block of lines corresponding to one residue'''\n    #if len(resi_lines) > 0: print( resi_lines[0][19])  # ACGU\n    #backbone_atoms_for_nt = {'A':['P',\"C5'\",\"O5'\",\"C4'\",\"O4'\",\"C3'\",\"O3'\",\"C2'\",\"O2'\",\"C1'\"]}\n    backbone_atoms = ['P',\"C5'\",\"O5'\",\"C4'\",\"O4'\",\"C3'\",\"O3'\",\"C2'\",\"O2'\",\"C1'\",'OP1','OP2']\n    other_lines = []\n    resi_line_dict = {}\n    for resi_line in resi_lines:\n        if len(resi_line)>25: \n            atom_name = resi_line[11:16].strip()\n            if atom_name in backbone_atoms:\n                resi_line_dict[atom_name] = resi_line\n            else:\n                other_lines.append(resi_line)\n        else: other_lines.append(resi_line)\n    resi_lines_reorder = [resi_line_dict[x] for x in backbone_atoms if x in resi_line_dict]\n    resi_lines_reorder += other_lines\n    return resi_lines_reorder\n    \ndef reorder_atom_numbers( lines ):\n    ''' Atom numbers should go from 1,2,.... '''\n    atom_number = 0\n    lines_new = []\n    for line in lines:\n        line_new = line\n        if len(line) > 11:\n            atom_number += 1\n            line_new = '%s%6d%s' % (line[:5],atom_number,line[11:])\n            assert( len(line_new) == len(line))\n        lines_new.append( line_new )\n    return lines_new\n\ndef sanitize( lines ):\n    ''' sanitize RNA residue lines from RhoFold to be in \"correct\" order expected by py3Dmol.'''\n    lines_is_string = False\n    if isinstance(lines,str): \n        lines = lines.split('\\n')\n        lines_is_string = True\n        \n    lines_reorder = []\n    resi_lines = []\n    chain = ''\n    resi = ''\n    count = 0\n    for (i,line) in enumerate(lines):\n        if len(line)>25 and (line[21] != chain or resi != line[22:26]):\n            #print(len(resi_lines),chain,resi)\n            chain = line[21]\n            resi = line[22:26]\n            resi_lines_reorder = reorder(resi_lines)\n            lines_reorder = lines_reorder + reorder(resi_lines)\n            # get next block ready\n            resi_lines = [line]\n            count += 1\n        else:\n            resi_lines.append(line)\n    lines_reorder = lines_reorder + reorder(resi_lines)\n    lines_reorder = reorder_atom_numbers( lines_reorder )\n    if lines_is_string: lines_reorder = '\\n'.join(lines_reorder)\n    return lines_reorder\n\ndef get_pdb_lines(filename):\n    ''' Currently only reads in ATOM, not HETATM '''\n    lines = ''.join([(line) for line in open(pdb_file_path).readlines() if line.find(\"ATOM\")==0])\n    return sanitize(lines)\n    ","metadata":{"execution":{"iopub.status.busy":"2023-10-31T19:43:15.964021Z","iopub.execute_input":"2023-10-31T19:43:15.964312Z","iopub.status.idle":"2023-10-31T19:43:15.978571Z","shell.execute_reply.started":"2023-10-31T19:43:15.964285Z","shell.execute_reply":"2023-10-31T19:43:15.977570Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# A test sequence ('AB50') from Eterna.\nThis sequence, designed by Eterna player AmyBarish, appears to fold into a pseudoknot, based on experimental chemical mapping data. It also is folded into a pseudoknot by RhoFold.","metadata":{}},{"cell_type":"code","source":"# Sequence for AB50\nget_rhofold_3D_GPU('AGCUCGAAAAGGACCAAAACGAGCAAUAACAUAAAUAAAGGUCCAAAUAA')\npdb_file_path = '/kaggle/working/rhofold_output/unrelaxed_model.pdb';\nview = py3Dmol.view(width=400, height=300)\nview.addModel(get_pdb_lines(pdb_file_path),'pdb')\nview.setStyle( {\"cartoon\": {'color': 'spectrum'}})\nview.zoomTo()\nview.show()","metadata":{"execution":{"iopub.status.busy":"2023-10-31T19:43:15.979800Z","iopub.execute_input":"2023-10-31T19:43:15.980144Z","iopub.status.idle":"2023-10-31T19:43:26.124919Z","shell.execute_reply.started":"2023-10-31T19:43:15.980107Z","shell.execute_reply":"2023-10-31T19:43:26.123695Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# More tests!\n## AB50 but with mutations to disrupt one stem of the pseudoknot","metadata":{}},{"cell_type":"code","source":"# Sequence for AB50\n# get_rhofold_3D('AGCUCGAAAAGGACCAAAACGAGCAAUAACAUAAAUAAAGGUCCAAAUAA')\n# mutate pseudoknot\nget_rhofold_3D_GPU('AGCUCGAAAAGGACCAAAACGAGCAAUAACAUAAAUAAACCAGGAAAUAA')\nview = py3Dmol.view(width=400, height=300)\nview.addModel(get_pdb_lines(pdb_file_path),'pdb')\nview.setStyle( {\"cartoon\": {'color': 'spectrum'}})\nview.zoomTo()\nview.update()","metadata":{"execution":{"iopub.status.busy":"2023-10-31T19:43:26.126294Z","iopub.execute_input":"2023-10-31T19:43:26.126601Z","iopub.status.idle":"2023-10-31T19:43:36.117083Z","shell.execute_reply.started":"2023-10-31T19:43:26.126573Z","shell.execute_reply":"2023-10-31T19:43:36.115843Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# An even more compact wrapper to run rhofold and view...","metadata":{}},{"cell_type":"code","source":"def rhofold_and_view(sequence):\n    get_rhofold_3D_GPU(sequence)\n    view = py3Dmol.view(width=400, height=300)\n    view.addModel(get_pdb_lines(pdb_file_path),'pdb')\n    view.setStyle( {\"cartoon\": {'color': 'spectrum'}})\n    view.zoomTo()\n    view.update()","metadata":{"execution":{"iopub.status.busy":"2023-10-31T19:43:36.118730Z","iopub.execute_input":"2023-10-31T19:43:36.119116Z","iopub.status.idle":"2023-10-31T19:43:36.125829Z","shell.execute_reply.started":"2023-10-31T19:43:36.119082Z","shell.execute_reply":"2023-10-31T19:43:36.124793Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## The IceBolt sequence is also from Eterna, and experimental data supports it's formation of a pseudoknot","metadata":{}},{"cell_type":"code","source":"# IceBolt\nsequence = 'CAUAGUAUACCCUGUUGCAUGUAUACUAUGAUAUACCGUAAUGCAACGGA' \nrhofold_and_view(sequence)","metadata":{"execution":{"iopub.status.busy":"2023-10-31T19:43:36.127324Z","iopub.execute_input":"2023-10-31T19:43:36.127617Z","iopub.status.idle":"2023-10-31T19:43:46.261035Z","shell.execute_reply.started":"2023-10-31T19:43:36.127593Z","shell.execute_reply":"2023-10-31T19:43:46.259770Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## This sequenc from Eterna player IceBolt including the flanking sequences used for chemical mapping.\nThe flanking sequences appear to confuse RhoFold, and we don't see a clean pseudoknot flanked by hairpins.","metadata":{}},{"cell_type":"code","source":"# IceBolt, with flanking sequences:\nsequence = 'GGGAACGACUCGAGUAGAGUCGAAAACAUAGUAUACCCUGUUGCAUGUAUACUAUGAUAUACCGUAAUGCAACGGACGGUGCGUUCGCGCAUCGAAAAGAAACAACAACAACAAC'\nrhofold_and_view(sequence)","metadata":{"execution":{"iopub.status.busy":"2023-10-31T19:43:46.262839Z","iopub.execute_input":"2023-10-31T19:43:46.263255Z","iopub.status.idle":"2023-10-31T19:43:57.892190Z","shell.execute_reply.started":"2023-10-31T19:43:46.263220Z","shell.execute_reply":"2023-10-31T19:43:57.890936Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## This sequence designed by Eterna player *cynwulf* forms two hairpins whose loops 'kiss'\nRhoFold models the kissing hairpins, but does not model a continuous loop connecting them.","metadata":{}},{"cell_type":"code","source":"# cynwulf Kissing hairpins\nsequence = 'GGGAACGACUCGAGUAGAGUCGAAAACGCCGUAGCGCGCAACGGCGUAACGGCAGCAUUAGCGCGCAGCUGCCGACUGAUGUGUUCGCACAUCAAAAAGAAACAACAACAACAAC' \nsequence = 'CGCCGUAGCGCGCAACGGCGUAACGGCAGCAUUAGCGCGCAGCUGCCGACU'\nrhofold_and_view(sequence)","metadata":{"execution":{"iopub.status.busy":"2023-10-31T19:43:57.893985Z","iopub.execute_input":"2023-10-31T19:43:57.894414Z","iopub.status.idle":"2023-10-31T19:44:07.873995Z","shell.execute_reply.started":"2023-10-31T19:43:57.894372Z","shell.execute_reply":"2023-10-31T19:44:07.872803Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Grab a sequence from Ribonanza training data","metadata":{}},{"cell_type":"code","source":"import pandas as pd\ndf = pd.read_csv('/kaggle/input/stanford-ribonanza-rna-folding/train_data_QUICK_START.csv')","metadata":{"execution":{"iopub.status.busy":"2023-10-31T19:44:07.877412Z","iopub.execute_input":"2023-10-31T19:44:07.877725Z","iopub.status.idle":"2023-10-31T19:44:26.947257Z","shell.execute_reply.started":"2023-10-31T19:44:07.877697Z","shell.execute_reply":"2023-10-31T19:44:26.946450Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sequence = df['sequence'][0]\nrhofold_and_view(sequence)","metadata":{"execution":{"iopub.status.busy":"2023-10-31T19:44:26.948302Z","iopub.execute_input":"2023-10-31T19:44:26.948565Z","iopub.status.idle":"2023-10-31T19:44:41.301850Z","shell.execute_reply.started":"2023-10-31T19:44:26.948543Z","shell.execute_reply":"2023-10-31T19:44:41.300660Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}