|
import gradio as gr |
|
from igfold import IgFoldRunner |
|
import os |
|
import random |
|
import base64 |
|
import socket |
|
import re |
|
|
|
|
|
def read_mol(molpath): |
|
with open(molpath, "r") as fp: |
|
lines = fp.readlines() |
|
mol = "" |
|
for l in lines: |
|
mol += l |
|
return mol |
|
|
|
|
|
def molecule(input_pdb, h_seq, l_seq): |
|
mol = read_mol(input_pdb) |
|
|
|
byte_content = mol.encode('utf-8') |
|
base64_content = base64.b64encode(byte_content).decode('utf-8') |
|
|
|
x = ( |
|
"""<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8" /> |
|
<style> |
|
body{ |
|
font-family:sans-serif |
|
} |
|
.mol-container { |
|
width: 100%; |
|
height: 600px; |
|
position: relative; |
|
} |
|
.mol-container select{ |
|
background-image:None; |
|
} |
|
</style> |
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.3/jquery.min.js" integrity="sha512-STof4xm1wgkfm7heWqFJVn58Hm3EtS31XFaagaa8VMReCXAkQnJZ+jEy8PCC/iT18dFy95WcExNHFTqLyp72eQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> |
|
<script src="https://3Dmol.csb.pitt.edu/build/3Dmol-min.js"></script> |
|
</head> |
|
<body> |
|
<div id="container" class="mol-container"></div> |
|
|
|
<script> |
|
|
|
let h_seq = `""" |
|
+ h_seq |
|
+ """` |
|
|
|
let l_seq = `""" |
|
+ l_seq |
|
+ """` |
|
|
|
let pdb = `""" |
|
+ mol |
|
+ """` |
|
$(document).ready(function () { |
|
let element = $("#container"); |
|
let config = { backgroundColor: "white" }; |
|
let viewer = $3Dmol.createViewer(element, config); |
|
viewer.addModel(pdb, "pdb"); |
|
viewer.getModel(0).setStyle({chain: "H"}, {cartoon:{color:"red"}}); |
|
viewer.getModel(0).setStyle({chain: "L"}, {cartoon:{color:"blue"}}); |
|
viewer.addSurface($3Dmol.SurfaceType.VDW, {opacity: 0.4, color: "lightblue"}); |
|
viewer.zoomTo(); |
|
viewer.render(); |
|
viewer.zoom(0.8, 2000); |
|
}) |
|
</script> |
|
</body></html>""" |
|
) |
|
|
|
return f"""<iframe style="width: 100%; height: 600px" name="result" allow="midi; geolocation; microphone; camera; |
|
display-capture; encrypted-media;" sandbox="allow-modals allow-forms |
|
allow-scripts allow-same-origin allow-popups |
|
allow-top-navigation-by-user-activation allow-downloads" allowfullscreen="" |
|
allowpaymentrequest="" frameborder="0" srcdoc='{x}'></iframe> |
|
<div style="position: absolute; top: 10px; right: 10px; background-color: white; padding: 10px; border: 1px solid black;"> |
|
<div style="width: 20px; height: 20px; background-color: red; display: inline-block;"></div> |
|
<span style="margin-left: 3px;">Heavy chain</span><br> |
|
<div style="width: 20px; height: 20px; background-color: blue; display: inline-block;"></div> |
|
<span style="margin-left: 3px;">Light chain</span> |
|
<div style="display: flex; justify-content: space-between; margin-top: 5px;"> |
|
<a href="data:application/octet-stream;base64,{base64_content}" download="structure.pdb">Download File</a> |
|
</div> |
|
</div> |
|
""" |
|
|
|
def validate(seq): |
|
alphabet = set('ACDEFGHIKLMNPQRSTVWY') |
|
leftover = set(seq.upper()) - alphabet |
|
return not leftover |
|
|
|
def clean_sequence(seq): |
|
return re.sub(r'\s+', '', seq) |
|
|
|
def pred_seq(h_seq, l_seq): |
|
h_seq = clean_sequence(h_seq).upper() |
|
l_seq = clean_sequence(l_seq).upper() |
|
|
|
print("Logs","___"*10) |
|
print(f"Heavy chain: {h_seq}") |
|
print(f"Light chain: {l_seq}") |
|
hostname = socket.gethostname() |
|
ip_address = socket.gethostbyname(hostname) |
|
print(f"Hostname: {hostname}") |
|
print(f"IP Address: {ip_address}") |
|
print("___"*10) |
|
|
|
h_is_valid = validate(h_seq) |
|
l_is_valid = validate(l_seq) |
|
if h_is_valid and l_is_valid: |
|
sequences = { |
|
"H": h_seq, |
|
"L": l_seq |
|
} |
|
|
|
f_name = ''.join([random.choice("ACDEFGHIKLMNPQRSTVWY") for _ in range(15)]) |
|
|
|
pred_pdb = f"{f_name}.pdb" |
|
|
|
igfold = IgFoldRunner(num_models = 1) |
|
igfold.fold( |
|
pred_pdb, |
|
sequences=sequences, |
|
do_refine=False, |
|
do_renum=False |
|
) |
|
|
|
html = molecule(pred_pdb, h_seq, l_seq) |
|
|
|
else: |
|
html = "<p>ERROR! Not valid sequence. Please use only standard amino acid letters (ACDEFGHIKLMNPQRSTVWY)</p>" |
|
return html |
|
|
|
|
|
examples = [ |
|
[ |
|
"QVQLKESGPGLVAPSQSLSITCTVSGFSLSSYGVSWVRQPPGKGLEWLGVIWGDGSTNYHPNLMSRLSISKDISKSQVLFKLNSLQTDDTATYYCVTLDYWGQGTSVTVSS", |
|
"DVVMTQTPLSLPVSLGDQASISCRSSQSLVHRNGNTYLHWYLQKPGQSPKLLIYKVSNRFSGVPDRFSGSGSGTDFTLKISRVEAEDLGLYFCFQTTYVPNTFGGGTKLEIK" |
|
], |
|
[ |
|
"EVQLLESGGGLVQPGGSLRLSCAASGFTFSLYWMGWVRQAPGKGLEWVSSISSSGGVTPYADSVKGRFTISRDNSKNTLYLQMNSLRAEDTAVYYCAKLGELGWFDPWGQGTLVTVSS", |
|
"DIQMTQSPSSLSASVGDRVTITCRASQGISSYLNWYQQKPGKAPKLLIYYASNLQNGVPSRFSGSGSGTDFTLTISSLQPEDFATYYCQQSYSTPLTFGGGTKVEIK" |
|
], |
|
[ |
|
"EVQLVQSGPEVKKPGTSVKVSCKASGFTFMSSAVQWVRQARGQRLEWIGWIVIGSGNTNYAQKFQERVTITRDMSTSTAYMELSSLRSEDTAVYYCAAPYCSSISCNDGFDIWGQGTMVTVS", |
|
"EIVLTQSPATLSLSPGERATLSCRASQSVSSYLAWYQQKPGQAPRLLIYDASNRATGIPARFSGSGSGTDFTLTISSLEPEDFAVYYCQQRSNWPITFGQGTKLEIK" |
|
] |
|
] |
|
|
|
with gr.Blocks() as demo: |
|
gr.Markdown('# Antibody Structure Prediction') |
|
gr.Markdown("## Examples") |
|
|
|
with gr.Row(): |
|
h_text = gr.Textbox(lines=5, label="Heavy chain", |
|
placeholder="Enter heavy chain sequence (e.g. QVQLKESGP...)") |
|
l_text = gr.Textbox(lines=5, label="Light chain", |
|
placeholder="Enter light chain sequence (e.g. DVVMTQTPL...)") |
|
|
|
|
|
gr.Examples( |
|
examples=examples, |
|
inputs=[h_text, l_text], |
|
label="Click on any example to paste it into the input fields", |
|
fn=pred_seq, |
|
outputs=gr.HTML() |
|
) |
|
|
|
btn = gr.Button(value="Submit") |
|
output_html = gr.HTML() |
|
btn.click(pred_seq, inputs=[h_text, l_text], outputs=output_html) |
|
|
|
if __name__ == "__main__": |
|
demo.launch() |