Spaces:
Sleeping
Sleeping
CSS = """ | |
/* HTML: <div class="loader"></div> */ | |
.loader { | |
width: 60px; | |
aspect-ratio: 1.154; | |
color: #25b09b; | |
display: grid; | |
animation: l38-0 6s infinite linear; | |
} | |
.loader:before, | |
.loader:after { | |
content: ""; | |
grid-area: 1/1; | |
} | |
.loader:before { | |
clip-path: polygon(25% 0,75% 0,100% 50%,75% 100%,25% 100%,0 50%); | |
background: conic-gradient(from -30deg,#0000 60deg,currentColor 0); | |
} | |
.loader:after { | |
background: conic-gradient(from -30deg,currentColor 60deg,#0000 0); | |
animation: l38 0.5s infinite alternate; | |
} | |
@keyframes l38-0 { | |
0%,16.66% {transform: rotate(0deg)} | |
16.67%,33.33% {transform: rotate(60deg)} | |
33.34%,50% {transform: rotate(120deg)} | |
50.1%,66.66% {transform: rotate(180deg)} | |
66.67%,83.33% {transform: rotate(240deg)} | |
83.34%,100% {transform: rotate(300deg)} | |
} | |
@keyframes l38 { | |
100% {transform: translateY(-20px)} | |
} | |
.help-tip { | |
position: absolute; | |
display: inline-block; | |
top: 16px; | |
right: 0px; | |
text-align: center; | |
border-radius: 40%; | |
/* border: 2px solid darkred; background-color: #8B0000;*/ | |
width: 24px; | |
height: 24px; | |
font-size: 16px; | |
line-height: 26px; | |
cursor: default; | |
transition: all 0.5s cubic-bezier(0.55, 0, 0.1, 1); | |
z-index: 100 !important; | |
} | |
.help-tip:hover { | |
cursor: pointer; | |
/*background-color: #ccc;*/ | |
} | |
.help-tip:before { | |
content: '?'; | |
font-weight: 700; | |
color: #8B0000; | |
z-index: 100 !important; | |
} | |
.help-tip p { | |
visibility: hidden; | |
opacity: 0; | |
text-align: left; | |
background-color: #EFDDE3; | |
padding: 20px; | |
width: 300px; | |
position: absolute; | |
border-radius: 4px; | |
right: -4px; | |
color: #494F5A; | |
font-size: 13px; | |
line-height: normal; | |
transform: scale(0.7); | |
transform-origin: 100% 0%; | |
transition: all 0.5s cubic-bezier(0.55, 0, 0.1, 1); | |
z-index: 100; | |
} | |
.help-tip:hover p { | |
cursor: default; | |
visibility: visible; | |
opacity: 1; | |
transform: scale(1.0); | |
} | |
.help-tip p:before { | |
position: absolute; | |
content: ''; | |
width: 0; | |
height: 0; | |
border: 6px solid transparent; | |
border-bottom-color: #EFDDE3; | |
right: 10px; | |
top: -12px; | |
} | |
.help-tip p:after { | |
width: 100%; | |
height: 40px; | |
content: ''; | |
position: absolute; | |
top: -5px; | |
left: 0; | |
z-index: 101; | |
} | |
.upload_button { | |
background-color: #008000; | |
} | |
.absolute { | |
position: absolute; | |
} | |
.example { | |
padding: 0; | |
background: none; | |
border: none; | |
text-decoration: underline; | |
box-shadow: none; | |
text-align: left !important; | |
display: inline-block !important; | |
} | |
footer { | |
visibility: hidden | |
} | |
.html-container { | |
padding: 0px; | |
} | |
.block .table-wrap { | |
width: 100% !important; | |
aspect-ratio: 1.618 / 1 !important; | |
height: auto !important; | |
} | |
.mol-container { | |
width: 100%; | |
aspect-ratio: 1.618 / 1; | |
position: relative; | |
box-sizing: border-box; | |
} | |
""" | |
IFRAME_TEMPLATE = """ | |
<iframe style="width: 100%; aspect-ratio: 1.618 / 1;" name="result" allow="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='{html}'></iframe> | |
""" | |
PROTEIN_VIEW_IFRAME = IFRAME_TEMPLATE.format(html=""" | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta http-equiv="content-type" content="text/html; charset=UTF-8" /> | |
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script> | |
<script src="https://3Dmol.org/build/3Dmol.js"></script> | |
<style> | |
html, body { | |
height: 100%; | |
margin: 0; | |
overflow: hidden; | |
} | |
.mol-container { | |
width: 100%; | |
height: 100%; | |
position: relative; | |
box-sizing: border-box; | |
} | |
.mol-container select { | |
background-image: none; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="container" class="mol-container"></div> | |
<script> | |
var viewer = null; | |
$(document).ready(function() { | |
let element = $("#container"); | |
let config = { backgroundColor: "white" }; | |
viewer = $3Dmol.createViewer(element, config); | |
let ligandStyle = { stick: { colorscheme: "greenCarbon" } }; | |
let proteinStyle = { cartoon: { colorscheme: "Jmol" } }; | |
let pocketStyle = { sphere: { colorscheme: "blueCarbon", opacity: 0.618 } }; | |
}); | |
</script> | |
</body> | |
</html> | |
""") | |
COMPLEX_RENDERING_TEMPLATE = """ | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta http-equiv="content-type" content="text/html; charset=UTF-8" /> | |
<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.org/build/3Dmol.js"></script> | |
<style> | |
html, body {{ | |
height: 100%; | |
margin: 0; | |
overflow: hidden; | |
}} | |
.mol-container {{ | |
width: 100%; | |
height: 100%; | |
position: relative; | |
box-sizing: border-box; | |
}} | |
.mol-container select {{ | |
background-image: none; | |
}} | |
</style> | |
</head> | |
<body> | |
<div id="container" class="mol-container"></div> | |
<script> | |
var viewer = null; | |
$(document).ready(function() {{ | |
let element = $("#container"); | |
let config = {{ backgroundColor: "white" }}; | |
let viewer = $3Dmol.createViewer(element, config); | |
let ligandStyle = {{ stick: {{ colorscheme: "greenCarbon" }} }}; | |
let proteinStyle = {{ cartoon: {{ colorscheme: "Jmol" }} }}; | |
let pocketStyle = {{ sphere: {{ colorscheme: "blueCarbon", opacity: 0.618 }} }}; | |
{viewer_models} | |
viewer.zoomTo({{ "model": 0 }}); | |
viewer.render(); | |
}}); | |
</script> | |
</body> | |
</html> | |
""" | |
FRAGMENTS_RENDERING_TEMPLATE = """<!DOCTYPE html> | |
<html> | |
<head> | |
<meta http-equiv="content-type" content="text/html; charset=UTF-8" /> | |
<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.org/build/3Dmol.js"></script> | |
<style> | |
html, body {{ | |
height: 100%; | |
margin: 0; | |
overflow: hidden; | |
}} | |
.mol-container {{ | |
width: 100%; | |
height: 100%; | |
position: relative; | |
box-sizing: border-box; | |
}} | |
.mol-container select{{ | |
background-image:None; | |
}} | |
</style> | |
</head> | |
<body> | |
<div id="container" class="mol-container"></div> | |
<script> | |
$(document).ready(function() {{ | |
let element = $("#container"); | |
let config = {{ backgroundColor: "white" }}; | |
let viewer = $3Dmol.createViewer(element, config); | |
let defaultStyle = {{ stick: {{ colorscheme: "greenCarbon" }} }}; | |
viewer.addModel(`{molecule}`, "{fmt}"); | |
viewer.getModel(0).setStyle(defaultStyle); | |
viewer.getModel(0).setClickable( | |
{{}}, | |
true, | |
function (_atom, _viewer, _event, _container) {{ | |
if (!_atom.isClicked) {{ | |
_atom.isClicked = true; | |
_viewer.addStyle( | |
{{"serial": _atom.serial, "model": 0}}, | |
{{"sphere": {{"color": "magenta", "radius": 0.4}} }} | |
); | |
window.parent.postMessage({{ | |
name: "atom_selection", | |
data: {{"atom": _atom.serial, "add": true}} | |
}}, "*"); | |
}} else {{ | |
delete _atom.isClicked; | |
_viewer.setStyle({{"serial": _atom.serial, "model": 0}}, defaultStyle); | |
window.parent.postMessage({{ | |
name: "atom_selection", | |
data: {{"atom": _atom.serial, "add": false}} | |
}}, "*"); | |
}} | |
_viewer.render(); | |
}} | |
); | |
viewer.zoomTo({{ "model": 0 }}); | |
viewer.zoom(0.7); | |
viewer.render(); | |
}}); | |
</script> | |
</body> | |
</html> | |
""" | |
TARGET_RENDERING_TEMPLATE = """<!DOCTYPE html> | |
<html> | |
<head> | |
<meta http-equiv="content-type" content="text/html; charset=UTF-8" /> | |
<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.org/build/3Dmol.js"></script> | |
<style> | |
html, body {{ | |
height: 100%; | |
margin: 0; | |
overflow: hidden; | |
}} | |
.mol-container {{ | |
width: 100%; | |
height: 100%; | |
position: relative; | |
box-sizing: border-box; | |
}} | |
.mol-container select {{ | |
background-image: none; | |
}} | |
</style> | |
</head> | |
<body> | |
<div id="container" class="mol-container"></div> | |
<script> | |
$(document).ready(function() {{ | |
let element = $("#container"); | |
let config = {{ backgroundColor: "white" }}; | |
let viewer = $3Dmol.createViewer(element, config); | |
let proteinStyle = {{ cartoon: {{ colorscheme: "ssPyMOL" }} }}; | |
viewer.addModel(`{molecule}`, "{fmt}"); | |
viewer.getModel(0).setStyle(proteinStyle); | |
viewer.zoomTo({{ "model": 0 }}); | |
viewer.zoom(0.7); | |
viewer.render(); | |
}}); | |
</script> | |
</body> | |
</html> | |
""" | |
COMPLEX_RENDERING_TEMPLATE_OLD = """<!DOCTYPE html> | |
<html> | |
<head> | |
<meta http-equiv="content-type" content="text/html; charset=UTF-8" /> | |
<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.org/build/3Dmol.js"></script> | |
<style> | |
html, body {{ | |
height: 100%; | |
margin: 0; | |
overflow: hidden; | |
}} | |
.mol-container {{ | |
width: 100%; | |
height: 100%; | |
position: relative; | |
box-sizing: border-box; | |
}} | |
.mol-container select {{ | |
background-image: none; | |
}} | |
</style> | |
</head> | |
<body> | |
<div id="container" class="mol-container"></div> | |
<script> | |
$(document).ready(function() {{ | |
let element = $("#container"); | |
let config = {{ backgroundColor: "white" }}; | |
let viewer = $3Dmol.createViewer(element, config); | |
let ligandStyle = {{ stick: {{ colorscheme: "greenCarbon" }} }}; | |
let proteinStyle = {{ cartoon: {{ colorscheme: "Jmol" }} }}; | |
let defaultStyle = {{ stick: {{ colorscheme: "greenCarbon" }} }}; // Store default style | |
let selectedLigand = null; // Keep track of currently selected ligand | |
viewer.setStyle({{ hetflag: false }}, proteinStyle); | |
viewer.setStyle({{ hetflag: true }}, ligandStyle); | |
viewer.addModel(`{complex}`, "{fmt}"); | |
viewer.getModel(0).setClickable( | |
{{ hetflag: true, byres: true }}, | |
true, | |
function (_atom, _viewer, _event, _container) {{ | |
let currentLigand = {{ resn: _atom.resn, chain: _atom.chain, resi: _atom.resi }}; | |
if (selectedLigand === currentLigand) {{ | |
// Deselect ligand | |
selectedLigand = null; | |
_viewer.setStyle({{ resn: _atom.resn, chain: _atom.chain, resi: _atom.resi }}, defaultStyle); | |
console.log("Deselected Residue:", currentLigand); | |
window.parent.postMessage({{ | |
name: "ligand_selection", | |
data: {{ residue: currentLigand, add: false }} | |
}}, "*"); | |
}} else {{ | |
// Select ligand and deselect previous | |
if (selectedLigand) {{ | |
_viewer.setStyle({{ resn: selectedLigand.resn, chain: selectedLigand.chain, resi: selectedLigand.resi }}, defaultStyle); | |
}} | |
selectedLigand = currentLigand; | |
_viewer.setStyle({{ resn: _atom.resn, chain: _atom.chain, resi: _atom.resi }}, {{ stick: {{ color: "red", radius: 0.4}} }}); | |
console.log("Selected Residue:", currentLigand); | |
window.parent.postMessage({{ | |
name: "ligand_selection", | |
data: {{ residue: currentLigand, add: true }} | |
}}, "*"); | |
}} | |
_viewer.render(); | |
}} | |
); | |
viewer.render(); | |
}}); | |
</script> | |
</body> | |
</html> | |
""" | |
COMPLEX_WITH_POCKETS_RENDERING_TEMPLATE = """<!DOCTYPE html> | |
<html> | |
<head> | |
<meta http-equiv="content-type" content="text/html; charset=UTF-8" /> | |
<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.org/build/3Dmol.js"></script> | |
<style> | |
html, body {{ | |
height: 100%; | |
margin: 0; | |
overflow: hidden; | |
}} | |
.mol-container {{ | |
width: 100%; | |
height: 100%; | |
position: relative; | |
box-sizing: border-box; | |
}} | |
.mol-container select {{ | |
background-image: none; | |
}} | |
</style> | |
</head> | |
<body> | |
<div id="container" class="mol-container"></div> | |
<script> | |
$(document).ready(function() {{ | |
let element = $("#container"); | |
let config = {{ backgroundColor: "white" }}; | |
let viewer = $3Dmol.createViewer(element, config); | |
let ligandStyle = {{ stick: {{ colorscheme: "greenCarbon" }} }}; | |
let proteinStyle = {{ cartoon: {{ colorscheme: "Jmol" }} }}; | |
let defaultStyle = {{ stick: {{ colorscheme: "greenCarbon" }} }}; // Store default style | |
let selectedLigand = null; // Keep track of currently selected ligand | |
viewer.addModel(`{complex}`, "{fmt}"); | |
viewer.setStyle({{ hetflag: false }}, proteinStyle); | |
viewer.setStyle({{ hetflag: true }}, ligandStyle); | |
viewer.getModel(0).setClickable( | |
{{ hetflag: true, byres: true }}, | |
true, | |
function (_atom, _viewer, _event, _container) {{ | |
let currentLigand = {{ resn: _atom.resn, chain: _atom.chain, resi: _atom.resi }}; | |
if (selectedLigand === currentLigand) {{ | |
// Deselect ligand | |
selectedLigand = null; | |
_viewer.setStyle({{ resn: _atom.resn, chain: _atom.chain, resi: _atom.resi }}, defaultStyle); | |
console.log("Deselected Residue:", currentLigand); | |
window.parent.postMessage({{ | |
name: "ligand_selection", | |
data: {{ residue: currentLigand, add: false }} | |
}}, "*"); | |
}} else {{ | |
// Select ligand and deselect previous | |
if (selectedLigand) {{ | |
_viewer.setStyle({{ resn: selectedLigand.resn, chain: selectedLigand.chain, resi: selectedLigand.resi }}, defaultStyle); | |
}} | |
selectedLigand = currentLigand; | |
_viewer.setStyle({{ resn: _atom.resn, chain: _atom.chain, resi: _atom.resi }}, {{ stick: {{ color: "red", radius: 0.4}} }}); | |
console.log("Selected Residue:", currentLigand); | |
window.parent.postMessage({{ | |
name: "ligand_selection", | |
data: {{ residue: currentLigand, add: true }} | |
}}, "*"); | |
}} | |
_viewer.render(); | |
}} | |
); | |
// Add pockets | |
viewer.addModel | |
viewer.zoomTo({{ "model": 0 }}); | |
viewer.zoom(0.7); | |
viewer.render(); | |
}}); | |
</script> | |
</body> | |
</html> | |
""" | |
FRAGMENTS_AND_TARGET_RENDERING_TEMPLATE = """ | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta http-equiv="content-type" content="text/html; charset=UTF-8" /> | |
<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.org/build/3Dmol.js"></script> | |
<style> | |
html, body {{ | |
height: 100%; | |
margin: 0; | |
overflow: hidden; | |
}} | |
.mol-container {{ | |
width: 100%; | |
height: 100%; | |
position: relative; | |
box-sizing: border-box; | |
}} | |
.mol-container select{{ | |
background-image:None; | |
}} | |
</style> | |
</head> | |
<body> | |
<div id="container" class="mol-container"></div> | |
<script> | |
$(document).ready(function() {{ | |
let element = $("#container"); | |
let config = {{ backgroundColor: "white" }}; | |
let viewer = $3Dmol.createViewer(element, config); | |
let defaultStyle = {{ stick: {{ colorscheme: "greenCarbon" }} }}; | |
let proteinStyle = {{ cartoon: {{ colorscheme: "ssPyMOL" }} }}; | |
viewer.addModel(`{molecule}`, "{fmt}"); | |
viewer.getModel(0).setStyle(defaultStyle); | |
viewer.getModel(0).setClickable( | |
{{}}, | |
true, | |
function (_atom, _viewer, _event, _container) {{ | |
if (!_atom.isClicked) {{ | |
_atom.isClicked = true; | |
_viewer.addStyle( | |
{{"serial": _atom.serial, "model": 0}}, | |
{{"sphere": {{"color": "magenta", "radius": 0.4}} }} | |
); | |
window.parent.postMessage({{ | |
name: "atom_selection", | |
data: {{"atom": _atom.serial, "add": true}} | |
}}, "*"); | |
}} else {{ | |
delete _atom.isClicked; | |
_viewer.setStyle({{"serial": _atom.serial, "model": 0}}, defaultStyle); | |
window.parent.postMessage({{ | |
name: "atom_selection", | |
data: {{"atom": _atom.serial, "add": false}} | |
}}, "*"); | |
}} | |
_viewer.render(); | |
}} | |
); | |
viewer.addModel(`{target}`, "{target_fmt}"); | |
viewer.getModel(1).setStyle(proteinStyle); | |
viewer.zoomTo({{ "model": 0 }}); | |
viewer.zoom(0.7); | |
viewer.render(); | |
}}); | |
</script> | |
</body> | |
</html> | |
""" | |
SAMPLES_RENDERING_TEMPLATE = """<!DOCTYPE html> | |
<html> | |
<head> | |
<meta http-equiv="content-type" content="text/html; charset=UTF-8" /> | |
<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.org/build/3Dmol.js"></script> | |
<style> | |
html, body {{ | |
height: 100%; | |
margin: 0; | |
overflow: hidden; | |
}} | |
.mol-container {{ | |
width: 100%; | |
height: 100%; | |
position: relative; | |
box-sizing: border-box; | |
}} | |
.mol-container select{{ | |
background-image:None; | |
}} | |
</style> | |
</head> | |
<body> | |
<div id="container" class="mol-container"></div> | |
<br> | |
<button id="fragments">Input Fragments</button> | |
<button id="molecule">Output Molecule</button> | |
<script> | |
let element = $("#container"); | |
let config = {{ backgroundColor: "white" }}; | |
let viewer = $3Dmol.createViewer( element, config ); | |
$(document).ready(function() {{ | |
viewer.addModel(`{fragments}`, "{fragments_fmt}") | |
viewer.getModel().setStyle({{ stick: {{ colorscheme:"greenCarbon" }} }}) | |
viewer.getModel().hide(); | |
viewer.addModel(`{molecule}`, "{molecule_fmt}") | |
viewer.getModel().setStyle({{ stick: {{ colorscheme:"greenCarbon" }} }}) | |
viewer.zoomTo({{ "model": 0 }}); | |
viewer.zoom(0.7); | |
viewer.render(); | |
}}); | |
$("#fragments").click(function() {{ | |
viewer.getModel(0).show(); | |
viewer.getModel(1).hide(); | |
viewer.render(); | |
}}); | |
$("#molecule").click(function() {{ | |
viewer.getModel(1).show(); | |
viewer.getModel(0).hide(); | |
viewer.render(); | |
}}); | |
</script> | |
</body> | |
</html> | |
""" | |
SAMPLES_WITH_TARGET_RENDERING_TEMPLATE = """ | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta http-equiv="content-type" content="text/html; charset=UTF-8" /> | |
<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.org/build/3Dmol.js"></script> | |
<style> | |
html, body {{ | |
height: 100%; | |
margin: 0; | |
overflow: hidden; | |
}} | |
.mol-container {{ | |
width: 100%; | |
height: 100%; | |
position: relative; | |
box-sizing: border-box; | |
}} | |
.mol-container select{{ | |
background-image:None; | |
}} | |
</style> | |
</head> | |
<body> | |
<div id="container" class="mol-container"></div> | |
<br> | |
<button id="fragments">Input Fragments</button> | |
<button id="molecule">Output Molecule</button> | |
<button id="show-target">Show Target</button> | |
<button id="hide-target">Hide Target</button> | |
<script> | |
let element = $("#container"); | |
let config = {{ backgroundColor: "white" }}; | |
let viewer = $3Dmol.createViewer( element, config ); | |
$(document).ready(function() {{ | |
viewer.addModel(`{fragments}`, "{fragments_fmt}") | |
viewer.getModel(0).setStyle({{ stick: {{ colorscheme:"greenCarbon" }} }}) | |
viewer.getModel(0).hide(); | |
viewer.addModel(`{molecule}`, "{molecule_fmt}") | |
viewer.getModel(1).setStyle({{ stick: {{ colorscheme:"greenCarbon" }} }}) | |
viewer.addModel(`{target}`, "{target_fmt}") | |
viewer.getModel(2).setStyle({{ cartoon: {{ colorscheme: "ssPyMOL" }} }}) | |
viewer.zoomTo({{ "model": 0 }}); | |
viewer.zoom(0.7); | |
viewer.render(); | |
}}); | |
$("#fragments").click(function() {{ | |
viewer.getModel(0).show(); | |
viewer.getModel(1).hide(); | |
viewer.render(); | |
}}); | |
$("#molecule").click(function() {{ | |
viewer.getModel(1).show(); | |
viewer.getModel(0).hide(); | |
viewer.render(); | |
}}); | |
$("#show-target").click(function() {{ | |
viewer.getModel(2).show(); | |
viewer.render(); | |
}}); | |
$("#hide-target").click(function() {{ | |
viewer.getModel(2).hide(); | |
viewer.render(); | |
}}); | |
</script> | |
</body> | |
</html> | |
""" | |
INVALID_FORMAT_MSG = """ | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta http-equiv="content-type" content="text/html; charset=UTF-8" /> | |
<style> | |
body{{ | |
font-family:sans-serif | |
}} | |
</style> | |
</head> | |
<body> | |
<h3>Invalid file format: {extension}</h3> | |
Allowed formats for the fragments file: | |
<ul> | |
<li>.pdb</li> | |
<li>.sdf</li> | |
<li>.mol</li> | |
<li>.mol2</li> | |
</ul> | |
Allowed formats for the optional protein file: | |
<ul> | |
<li>.pdb</li> | |
</ul> | |
</body> | |
</html> | |
""" | |
ERROR_FORMAT_MSG = """ | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta http-equiv="content-type" content="text/html; charset=UTF-8" /> | |
<style> | |
body{{ | |
font-family:sans-serif | |
}} | |
</style> | |
</head> | |
<body> | |
<h3>Error:</h3> | |
{message} | |
</body> | |
</html> | |
""" | |
SETUP_JS = """ | |
() => { | |
const scripts = [ | |
"https://code.jquery.com/jquery-3.7.1.min.js", | |
"https://3dmol.org/build/3Dmol.js" | |
]; | |
scripts.forEach((script) => { | |
const scriptElement = document.createElement("script"); | |
scriptElement.src = script; | |
scriptElement.async = true; | |
document.head.appendChild(scriptElement); | |
}); | |
viewerConfig = { backgroundColor: "white" }; | |
ligandStyle = { stick: { colorscheme: "greenCarbon" } }; | |
proteinStyle = { cartoon: { colorscheme: "Jmol" } }; | |
pocketStyle = { clicksphere: { radius: 1.5 } }; | |
pocketSurfaceStyle = { opacity: 0.854, color: "aquamarine" }; | |
selectedElements = { | |
"atoms": [], | |
"ligand": {name: null, resn: null, chain: null, resi: null}, | |
"pocket": {name: null, id: null} | |
} | |
} | |
""" | |
# function handleMessage(event) { | |
# if (event.data.name == "atom_selection") { | |
# console.log("New message: ", event.data) | |
# let atom = event.data.data["atom"]; | |
# let add = event.data.data["add"]; | |
# console.log("add: ", add, " atom: ", atom); | |
# window.selected_elements["atom_selection"][atom] = add; | |
# } | |
# if (event.data.name == "ligand_selection") { | |
# console.log("New message: ", event.data) | |
# let residue_info = event.data.data["residue"]; | |
# let add = event.data.data["add"]; | |
# residue = residue_info.resi + ":" + residue_info.resn + ":" + residue_info.chain; | |
# console.log("add: ", add, " residue: ", residue); | |
# window.selected_elements["ligand_selection"][residue] = add; | |
# } | |
# if (event.data.name == "pocket_selection") { | |
# let pocket = event.data.data["pocket"]; | |
# console.log("add: ", add, " pocket: ", pocket); | |
# window.selected_elements["pocket_selection"][pocket] = add; | |
# } | |
# } | |
# | |
# window.addEventListener("message", handleMessage); | |
# console.log("Listener Added"); | |
# console.log(window.selected_elements); | |
RETURN_LIGAND_SELECTION_JS = """ | |
(prot_file, selected_ligand) => { | |
const selectedElements = window.selected_elements || {}; // Handle potential undefined | |
if ("ligand_selection" in selectedElements) { | |
ligandElements = selectedElements["ligand_selection"]; | |
for (const [residue, add] of Object.entries(ligandElements)) { | |
if (add) { | |
selectedLigand = residue | |
console.log("Selecting ligand ", selectedLigand); | |
} | |
} | |
} | |
console.log("Finished parsing selection."); | |
window.selected_elements["ligand_selection"] = {} | |
return [prot_file, selectedLigand]; | |
} | |
""" | |
RETURN_SELECTION = """ | |
(selected_ligand, selected_pocket) => { | |
selectedAtoms = selectedElements.atoms; | |
selectedLigand = selectedElements.ligand.name; | |
console.log("Selected Ligand:", selectedLigand); | |
selectedPocket = selectedElements.pocket.name; | |
console.log("Selected Pocket:", selectedPocket); | |
return [selectedLigand, selectedPocket]; | |
} | |
""" | |
RETURN_POCKET_SELECTION_JS = """ | |
(prot_file, selected_pocket) => { | |
const selectedElements = window.selected_elements || {}; // Handle potential undefined | |
if ("pocket_selection" in selectedElements) { | |
pocketElements = selectedElements["pocket_selection"]; | |
for (const [pocket, add] of Object.entries(pocketElements)) { | |
if (add) { | |
console.log("Selecting pocket ", pocket); | |
selected_pocket = pocket; | |
} | |
} | |
} | |
console.log("Finished parsing selection."); | |
window.selected_elements["pocket_selection"] = {} | |
return [prot_file, selected_pocket]; | |
} | |
""" | |
RETURN_ATOM_SELECTION_JS = """ | |
(input_file, selected_atoms) => { | |
let selectedAtoms = []; | |
if ("atom_selection" in selectedElements) { | |
atomElements = selectedElements["atom_selection"]; | |
for (const [atom, add] of Object.entries(atomElements)) { | |
if (add) { | |
console.log("Adding atom ", atom); | |
selectedAtoms.push(String(atom)); | |
} | |
} | |
} | |
const selectedAtomsString = selectedAtoms.join(","); | |
console.log("Finished parsing selection."); | |
window.selected_elements["atom_selection"] = {} | |
return [input_file, selectedAtomsString]; | |
} | |
""" | |
CREATE_MOL_VIEW = """ | |
(mol_file, view_html) => { | |
try { | |
let viewer; | |
// Get element id of the view_html string with error handling | |
const idMatch = view_html.match(/id="(\w+)"/); | |
if (!idMatch || !idMatch[1]) { | |
console.error("Invalid view_html: No ID found."); | |
return; // Exit the function if no ID is found | |
} | |
const element_id = idMatch[1]; | |
const element = document.getElementById(element_id); | |
// Get the file format | |
fmt = mol_file.path.split('.').pop(); | |
$.get(mol_file.url, function(molContent) { | |
if (!element.querySelector('canvas')) { | |
viewer = $3Dmol.createViewer(element, viewerConfig); | |
} else { | |
viewer = element.querySelector('canvas')._3dmol_viewer; | |
viewer.clear(); | |
selectedElements = { | |
"atoms": [], | |
"ligand": {name: null, resn: null, chain: null, resi: null}, | |
"pocket": {name: null, id: null} | |
} | |
} | |
model = viewer.addModel(molContent, fmt); | |
model.setStyle({ hetflag: false }, proteinStyle); | |
model.setStyle({ hetflag: true }, ligandStyle); | |
selectedLigand = selectedElements.ligand.name; | |
model.setClickable( | |
{ hetflag: true, byres: true }, | |
true, | |
function (_atom, _viewer, _event, _container) { | |
let selectedLigand = selectedElements.ligand; | |
let currentLigand = { resn: _atom.resn, chain: _atom.chain, resi: _atom.resi }; | |
currentLigand.name = currentLigand.resi + ":" + currentLigand.resn + ":" + currentLigand.chain; | |
if (selectedLigand.name == currentLigand.name) { | |
// Deselect ligand | |
_viewer.setStyle( | |
{ resn: currentLigand.resn, chain: currentLigand.chain, resi: currentLigand.resi }, | |
ligandStyle | |
); | |
console.log("Deselected Ligand:", currentLigand); | |
selectedElements.ligand = {name: null, resn: null, chain: null, resi: null}; | |
} else { | |
// Select ligand and deselect previous | |
if (selectedLigand.name) { | |
_viewer.setStyle( | |
{ resn: selectedLigand.resn, chain: selectedLigand.chain, resi: selectedLigand.resi }, | |
ligandStyle | |
); | |
} | |
selectedElements.ligand = currentLigand; | |
_viewer.setStyle( | |
{ resn: currentLigand.resn, chain: currentLigand.chain, resi: currentLigand.resi }, | |
{ stick: { color: "red", radius: "0.4"} } | |
); | |
console.log("Selected Ligand:", currentLigand); | |
} | |
_viewer.render(); | |
} | |
); | |
viewer.zoomTo(); | |
viewer.render(); | |
}).fail(function(error) { | |
console.error("Error loading molecule:", error); | |
}); | |
} catch (error) { | |
console.error("An error occurred:", error); | |
} | |
} | |
""" | |
UPDATE_PROT_VIEW = """ | |
(mol_files, view_html) => { | |
try { | |
let viewer; | |
// Get element id of the view_html string with error handling | |
const idMatch = view_html.match(/id="(\w+)"/); | |
if (!idMatch || !idMatch[1]) { | |
console.error("Invalid view_html: No ID found."); | |
return; // Exit the function if no ID is found | |
} | |
const element_id = idMatch[1]; | |
const element = document.getElementById(element_id); | |
if (element.querySelector('canvas')) { | |
viewer = element.querySelector('canvas')._3dmol_viewer; | |
for (let i = 1; i < viewer.models.length; i++) { | |
viewer.removeModel(i); | |
} | |
viewer.removeAllSurfaces(); | |
} else { | |
console.error("Invalid view_html: No canvas found."); | |
return; | |
} | |
for (var mol_file of mol_files) { | |
// Get the file format | |
const fmt = mol_file.orig_name.split('.').pop(); | |
const filename = mol_file.orig_name; | |
console.log("File:", mol_file.orig_name, "Format:", fmt); // Check values | |
$.get(mol_file.url, function(molContent) { | |
model = viewer.addModel(molContent, fmt); | |
if (fmt == "pqr") { | |
model.setStyle(pocketStyle); | |
surface = viewer.addSurface('VDW', pocketSurfaceStyle, {model: model}, {model: model}); | |
const surface_id = surface.surfid; | |
const pocket_name = filename.replace("_vert.pqr", ""); | |
model.setClickable( | |
{ byres: true }, | |
true, | |
function (_atom, _viewer, _event, _container) { | |
let selectedPocket = selectedElements.pocket; | |
let currentPocket = { name: pocket_name, id: _atom.model, surface: surface_id }; | |
if (currentPocket.name == selectedPocket.name) { | |
// Deselect pocket | |
// _viewer.setStyle({model: currentPocket.id}, pocketStyle); | |
_viewer.setSurfaceMaterialStyle(currentPocket.surface, pocketSurfaceStyle); | |
console.log("Deselected Pocket:", currentPocket); | |
selectedElements.pocket = {name: null, id: null}; | |
} else { | |
// Select pocket and deselect previous | |
if (selectedPocket.name) { | |
console.log("Deselected Pocket:", selectedPocket); | |
//_viewer.setStyle({model: selectedPocket.id}, pocketStyle); | |
_viewer.setSurfaceMaterialStyle(selectedPocket.surface, pocketSurfaceStyle); | |
} | |
selectedElements.pocket = currentPocket; | |
//_viewer.setStyle({model: currentPocket.id}, {sphere: {color: "red", opacity: 0.944} }); | |
_viewer.setSurfaceMaterialStyle(currentPocket.surface, { opacity: 0.944, color: "red" }); | |
console.log("Selected Pocket:", currentPocket); | |
} | |
_viewer.render(); | |
} | |
); | |
} else { | |
model.setStyle({ hetflag: false }, proteinStyle); | |
model.setStyle({ hetflag: true }, ligandStyle); | |
} | |
viewer.render(); | |
}).fail(function(error) { | |
console.error("Error loading molecule:", error); | |
}) | |
} | |
console.log("Rendering protein view."); | |
viewer.zoomTo(); | |
viewer.render(); | |
selectedElements = { | |
"atoms": [], | |
"ligand": {name: null, resn: null, chain: null, resi: null}, | |
"pocket": {name: null, id: null} | |
} | |
} catch (error) { | |
console.error("An error occurred:", error); | |
} | |
} | |
""" | |