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)} | |
} | |
.loader.first-frame { | |
animation: none; /* Stop the main animation */ | |
} | |
.loader.first-frame:before { | |
transform: rotate(0deg); /* Explicitly set the rotation to the first frame */ | |
} | |
.loader.first-frame:after { | |
animation: none; /* Stop the after animation */ | |
transform: translateY(0px); /*reset the translate Y*/ | |
} | |
.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: block; | |
} | |
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; | |
} | |
.mol-container > canvas { | |
position: relative ! important; | |
} | |
.gr-btn-grp { | |
display: flex; | |
flex-wrap: wrap; | |
gap: var(--layout-gap); | |
width: var(--size-full); | |
position: relative | |
border-radius: 0 | |
border-radius: var(--container-radius); | |
background: var(--background-fill-secondary); | |
padding: var(--size-2) | |
align-items: stretch | |
} | |
.gr-btn-grp > button { | |
flex: 1 1 0; | |
display: inline-flex; | |
justify-content: center; | |
align-items: center; | |
transition: var(--button-transition); | |
padding: var(--size-0-5) var(--size-2); | |
text-align: center; | |
border: var(--button-border-width) solid var(--button-secondary-border-color); | |
background: var(--button-secondary-background-fill); | |
color: var(--button-secondary-text-color); | |
box-shadow: var(--button-secondary-shadow) | |
border-radius: var(--button-large-radius); | |
padding: calc(var(--button-large-padding) - 1px); | |
font-family: monospace; | |
font-weight: var(--button-large-text-weight); | |
font-size: calc(var(--button-large-text-size) - 1px); | |
} | |
""" | |
IFRAME_TEMPLATE = """ | |
<iframe style="width: 100%; aspect-ratio: {aspect_ratio}; overflow: visible; border: none;" scrolling="no" | |
frameborder="0" 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" srcdoc='{srcdoc}'></iframe> | |
""" | |
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_INPUT_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); | |
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} | |
} | |
} | |
if (mol_file == null) { | |
return; | |
} | |
$.get(mol_file.url, function(molContent) { | |
fmt = mol_file.path.split('.').pop(); | |
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_MOL_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); | |
} | |
} | |
""" | |
CREATE_OUTPUT_MOL_VIEW = """ | |
(mol_file, view_html) => { | |
try { | |
let viewer; | |
const idMatch = view_html.match(/id="(\w+)"/); | |
if (!idMatch || !idMatch[1]) { | |
console.error("Invalid view_html: No ID found."); | |
return; | |
} | |
const element_id = idMatch[1]; | |
const element = document.getElementById(element_id); | |
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(); | |
} | |
model = viewer.addModel(molContent, fmt); | |
model.setStyle({ hetflag: false }, proteinStyle); | |
model.setStyle({ hetflag: true }, ligandStyle); | |
viewer.zoomTo(); | |
viewer.render(); | |
let container = element.parentElement.querySelector(".gr-btn-grp"); | |
if (!container) { | |
container = document.createElement("div"); | |
container.classList.add("gr-btn-grp"); | |
element.parentElement.appendChild(container); | |
} | |
// Molecule Button | |
let toggleMoleculeButton = container.querySelector("#toggleMoleculeButton"); | |
if (!toggleMoleculeButton) { | |
toggleMoleculeButton = document.createElement("button"); | |
toggleMoleculeButton.id = "toggleMoleculeButton"; // Add an ID | |
toggleMoleculeButton.textContent = "Hide Generated Molecule"; | |
let moleculeIsHidden = false; | |
toggleMoleculeButton.onclick = function() { | |
if (viewer.models.length === 2) { | |
moleculeIsHidden = !moleculeIsHidden; | |
viewer.addStyle({model: 1}, {stick: {hidden: moleculeIsHidden} }); | |
toggleMoleculeButton.textContent = moleculeIsHidden ? "Show Generated Molecule" : "Hide Generated Molecule"; | |
viewer.render(); | |
} | |
}; | |
container.appendChild(toggleMoleculeButton); | |
} | |
// Ligand Button | |
const ligandButtonId = "toggleLigandButton"; | |
let toggleLigandButton = container.querySelector("#" + ligandButtonId); | |
// Check for ligands and existing button | |
const hasLigands = viewer.getAtomsFromSel({model: 0, hetflag : true}).length > 0; | |
if (hasLigands && !toggleLigandButton) { | |
// Create button if ligands exist and it doesn't exist yet | |
toggleLigandButton = document.createElement("button"); | |
toggleLigandButton.id = ligandButtonId; | |
toggleLigandButton.textContent = "Hide Co-Crystallized Ligand"; | |
let ligandIsHidden = false; | |
toggleLigandButton.onclick = function() { | |
ligandIsHidden = !ligandIsHidden; | |
viewer.addStyle({model: 0, hetflag: true}, {stick: {hidden: ligandIsHidden} }); | |
toggleLigandButton.textContent = ligandIsHidden ? "Show Co-Crystallized Ligand" : "Hide Co-Crystallized Ligand"; | |
viewer.render(); | |
}; | |
container.appendChild(toggleLigandButton); | |
} else if (!hasLigands && toggleLigandButton) { | |
// Remove button if no ligands exist and it already exists | |
container.removeChild(toggleLigandButton); | |
} | |
// Protein Button | |
let toggleProteinButton = container.querySelector("#toggleProteinButton"); | |
if (!toggleProteinButton) { | |
toggleProteinButton = document.createElement("button"); | |
toggleProteinButton.id = "toggleProteinButton"; | |
toggleProteinButton.textContent = "Hide Target Protein"; | |
let proteinIsHidden = false; | |
toggleProteinButton.onclick = function() { | |
proteinIsHidden = !proteinIsHidden; | |
viewer.addStyle({model: 0, hetflag: false}, {cartoon: {hidden: proteinIsHidden} }); | |
toggleProteinButton.textContent = proteinIsHidden ? "Show Target Protein" : "Hide Target Protein"; | |
viewer.render(); | |
}; | |
container.appendChild(toggleProteinButton); | |
} | |
}).fail(function(error) { | |
console.error("Error loading molecule:", error); | |
}); | |
} catch (error) { | |
console.error("An error occurred:", error); | |
} | |
} | |
""" | |