diff --git "a/output_helpers.py" "b/output_helpers.py" new file mode 100644--- /dev/null +++ "b/output_helpers.py" @@ -0,0 +1,1566 @@ + +import json +import os + +local_url = "http://localhost:8888/frontend/" +remote_url = "https://cdn.jsdelivr.net/gh/duerrsimon/vue_3dmol_gradio@latest/" + + +if os.environ.get("GRADIO_LOCAL") is not None: + url = local_url +else: + url = remote_url + +def viewer_html(path_to_file, name="input", selectionStyle={"color": "greenCarbon", + "representation": "cartoon", + "multiple": True}, representations={}): + + ext = path_to_file.split(".")[-1] + with open(path_to_file, "r") as f: + data = f.read() + moldata = {"moldata": [{"data": data, "name": name, "selectionStyle": selectionStyle,"format": ext, + "selectable": True, + "asFrames":False, + "clickable": False}] + } + # dict to json + moldata = json.dumps(moldata) + representations = json.dumps(representations) + + return """ +<!DOCTYPE html> +<html lang="en"> + +<head> + + <script src=\""""+url+ """vue.js\"></script> + <script src="https://unpkg.com/dragselect@latest/dist/ds.min.js"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/3Dmol/2.0.3/3Dmol.min.js"></script> + <script src="https://cdn.tailwindcss.com"></script> + <title>Molecule View</title> + + <style> + .item { + width: 50px; + height: 50px; + color: red; + border: 0; + } + + .item:focus { + border: 1px solid rbg(0, 155, 255); + } + + .selectable, + .item-selectable, .model-selectable { + -webkit-user-select: none; + /* Safari */ + -ms-user-select: none; + /* IE 10 and IE 11 */ + user-select: none; + /* Standard syntax */ + } + + .ds-selected { + /* outline: 3px solid black; */ + /* outline-offset: 3px; */ + /* color: black; */ + font-weight: 600; + background-color: rgb(187 247 208) + } + + .sequence_container { + overflow-wrap: anywhere; + counter-reset: sequence; + } + + .sequence_container .sequence__chunk { + display: inline-block; + margin: 1rem 0 1rem 1rem; + /* width: 10ch; */ + position: relative; + white-space: nowrap; + } + + .sequence_container .sequence__chunk:not(:last-child):before, + .sequence_container .sequence__chunk--display-last:before { + content: counter(sequence); + counter-increment: sequence 10; + position: absolute; + top: -0.8em; + right: 0; + opacity: .5; + font-weight: bold; + } + + .sequence-container .sequence__chunk::after { + content: ""; + position: absolute; + bottom: 0; + left: 0; + right: 0; + transform-origin: left; + transform: scaleX(0.1); + box-shadow: var(--box-shadow); + } + + .sequence__chunk span { + padding: 0 0.05rem; + } + + .tooltip .tooltip-text { + display: none; + } + + .tooltip:hover .tooltip-text { + display: block; + } + </style> +</head> + +<body> + <div id="app" class="h-full bg-white"> + <div class="bg-white px-6 pt-3 pb-1 text-sm flex items-center"> + <span v-if="selectedAtoms.length==0">Resampling the whole PDB file, <span + class="bg-green-100 text-green-800 text-xs font-medium px-1 py-0.5 rounded dark:bg-green-900 dark:text-green-300">select</span> + residues in the + sequence view to resample only parts + of the structure</span> + <span v-else>Resampling the <span + class="bg-green-100 text-green-800 text-xs font-medium px-1 py-0.5 rounded dark:bg-green-900 dark:text-green-300">selected</span> + residues </span> + <svg fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24" + xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="w-4 h-4 pl-1 mt-3"> + <polyline points="10 15 15 20 20 15"></polyline> + <path d="M4 4h7a4 4 0 0 1 4 4v12"></path> + </svg> + </div> + <div class="flex"> + <!-- <div class="w-1/3"> + <div class=" px-4 border border-gray-200 shadow border-gray-200 rounded-xl mt-10" id="selectable"> + <div class="flex items-center justify-between border-b dark:border-gray-600"> + + <div class="flex flex-wrap items-center divide-gray-200 sm:divide-x dark:divide-gray-600"> + <div class="flex items-center space-x-1 "> + <button type="button" + class="p-2 text-gray-500 rounded cursor-pointer hover:text-gray-900 hover:bg-gray-100 dark:text-gray-400 dark:hover:text-white dark:hover:bg-gray-600 flex space-x-1 items-center" + :class="selectionMode=='single'?'bg-gray-100 dark:bg-gray-600':''" + @click="selectionMode='single'"> + <svg aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.5" + class="w-5 h-5" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> + <path + d="M15.042 21.672L13.684 16.6m0 0l-2.51 2.225.569-9.47 5.227 7.917-3.286-.672zM12 2.25V4.5m5.834.166l-1.591 1.591M20.25 10.5H18M7.757 14.743l-1.59 1.59M6 10.5H3.75m4.007-4.243l-1.59-1.59" + stroke-linecap="round" stroke-linejoin="round"></path> + </svg> + <span class="text-xs">Residue</span> + </button> + <button type="button" + class="p-2 text-gray-500 rounded cursor-pointer hover:text-gray-900 hover:bg-gray-100 dark:text-gray-400 dark:hover:text-white dark:hover:bg-gray-600 flex space-x-1 items-center" + @click="selectionMode='chain'"> + <svg aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.5" + class="w-5 h-5" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> + <path + d="M15.042 21.672L13.684 16.6m0 0l-2.51 2.225.569-9.47 5.227 7.917-3.286-.672zM12 2.25V4.5m5.834.166l-1.591 1.591M20.25 10.5H18M7.757 14.743l-1.59 1.59M6 10.5H3.75m4.007-4.243l-1.59-1.59" + stroke-linecap="round" stroke-linejoin="round"></path> + </svg> + <span class="text-xs">Chain</span> + </button> + </div> + <div class="flex flex-wrap items-center space-x-1 sm"> + <button type="button" + class="p-2 text-gray-500 rounded cursor-pointer hover:text-gray-900 hover:bg-gray-100 dark:text-gray-400 dark:hover:text-white dark:hover:bg-gray-600 flex space-x-1 items-center"> + <svg aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.5" + viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="w-5 h-5"> + <path + d="M13.5 16.875h3.375m0 0h3.375m-3.375 0V13.5m0 3.375v3.375M6 10.5h2.25a2.25 2.25 0 002.25-2.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v2.25A2.25 2.25 0 006 10.5zm0 9.75h2.25A2.25 2.25 0 0010.5 18v-2.25a2.25 2.25 0 00-2.25-2.25H6a2.25 2.25 0 00-2.25 2.25V18A2.25 2.25 0 006 20.25zm9.75-9.75H18a2.25 2.25 0 002.25-2.25V6A2.25 2.25 0 0018 3.75h-2.25A2.25 2.25 0 0013.5 6v2.25a2.25 2.25 0 002.25 2.25z" + stroke-linecap="round" stroke-linejoin="round"></path> + </svg> + <span class="text-xs">Insert segment</span> + </button> + </div> + <div class="flex flex-wrap items-center space-x-1 "> + <button type="button" + class="p-2 text-gray-500 rounded cursor-pointer hover:text-gray-900 hover:bg-gray-100 dark:text-gray-400 dark:hover:text-white dark:hover:bg-gray-600 flex space-x-1 items-center"> + <svg aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.5" + viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="w-5 h-5"> + <path + d="M12 9.75L14.25 12m0 0l2.25 2.25M14.25 12l2.25-2.25M14.25 12L12 14.25m-2.58 4.92l-6.375-6.375a1.125 1.125 0 010-1.59L9.42 4.83c.211-.211.498-.33.796-.33H19.5a2.25 2.25 0 012.25 2.25v10.5a2.25 2.25 0 01-2.25 2.25h-9.284c-.298 0-.585-.119-.796-.33z" + stroke-linecap="round" stroke-linejoin="round"></path> + </svg> + <span class="text-xs leading-tight">Delete residues</span> + </button> + </div> + <div class="flex flex-wrap items-center space-x-1 "> + <button type="button" + class="p-2 text-gray-500 rounded cursor-pointer hover:text-gray-900 hover:bg-gray-100 dark:text-gray-400 dark:hover:text-white dark:hover:bg-gray-600 flex space-x-1 items-center"> + <svg aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.5" + viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="w-5 h-5"> + <path + d="M12 9.75L14.25 12m0 0l2.25 2.25M14.25 12l2.25-2.25M14.25 12L12 14.25m-2.58 4.92l-6.375-6.375a1.125 1.125 0 010-1.59L9.42 4.83c.211-.211.498-.33.796-.33H19.5a2.25 2.25 0 012.25 2.25v10.5a2.25 2.25 0 01-2.25 2.25h-9.284c-.298 0-.585-.119-.796-.33z" + stroke-linecap="round" stroke-linejoin="round"></path> + </svg> + <span class="text-xs leading-tight">Delete residues</span> + </button> + </div> + </div> + + </div> + + <div class="w-full overflow-x-scroll p-2 "> + + + <div class="w-[780px] my-5 flex " v-for="chain in Object.keys(sequence)" :key="chain"> + + <div class="w-[60px] h-full"> + <div class="mt-[24px] font-medium text-sm py-1"> + chain {{chain}} + </div> + + </div> + <div class="w-[720px] flex flex-col relative"> + <div class="w-full h-[24px] whitespace-nowrap flex font-mono text-gray-400"> + <div class="ml-2 block">1</div> + <div class="ml-[1095px] block">100</div> + </div> + <div class="flex w-full bg-gray-100 text-sm group h-[24px]"> + <div class="w-[24px] h-[24px] dark:border-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white border border-gray-300 bg-white px-2 py-1 flex items-center justify-center item-selectable cursor-pointer" + :class="selectionMode==='chain'? 'group-hover:bg-gray-100 group:hover:text-gray-700' : 'hover:bg-gray-100 hover:text-gray-700'" + v-for="(aa,i) in sequence[chain]" :key="chain + aa + i" :data-chain="chain" + :data-index="i"> + <a href="#" class=" leading-tight text-gray-500 ">{{aa}}</a> + </div> + + + + + + </div> + </div> + </div> + + + </div> + + <div class="py-2"> + <h1 class="py-1 font-medium">Selections</h1> + <div class="flex flex-col text-sm"> + + <div class="bg-gray-50 p-2"> + Sele1 + </div> + </div> + </div> + </div> + </div> --> + + + <div class="w-full"> + + <div class="bg-white p-5 w-full" :class="hover ? 'cursor-pointer':''"> + <div class="w-full gr-form overflow-hidden flex border-solid border gap-px rounded-lg flex-wrap"> + <div class="gr-block gr-box relative w-full overflow-hidden border-dashed border border-gray-300 border-gray-200" + style="height:800px"> + <!-- <div + class="absolute z-50 top-0 left-0 bg-white rounded-br border-b border-r border-gray-200 p-1"> + <span class=" flex items-center space-x-1 text-xs text-gray-500"><svg + xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" + viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" + stroke-linecap="round" stroke-linejoin="round" + class="feather feather-file h-3 w-3"> + <path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z" /> + <polyline points="13 2 13 9 20 9" /> + </svg> <span>Molecule3D</span> + </span> + </div> --> + + <div + class="absolute z-50 top-0 right-0 mr-2 flex flex-col divide-y border border-gray-200 mt-2 rounded items-center justify-center bg-white"> + <button class="p-2" title="Reset View" @click="resetZoom"> + <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" + stroke-width="1.5" stroke="currentColor" + class="w-4 h-4 text-gray-500 hover:text-orange-600 cursor-pointer"> + <path stroke-linecap="round" stroke-linejoin="round" + d="M9 9V4.5M9 9H4.5M9 9L3.75 3.75M9 15v4.5M9 15H4.5M9 15l-5.25 5.25M15 9h4.5M15 9V4.5M15 9l5.25-5.25M15 15h4.5M15 15v4.5m0-4.5l5.25 5.25" /> + </svg> + </button> + <button class="p-2" title="Settings" @click="showOffCanvas =!showOffCanvas"> + <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" + stroke-width="1.5" stroke="currentColor" + class="w-5 h-5 text-gray-500 hover:text-orange-600 cursor-pointer"> + <path stroke-linecap="round" stroke-linejoin="round" + d="M10.5 6h9.75M10.5 6a1.5 1.5 0 11-3 0m3 0a1.5 1.5 0 10-3 0M3.75 6H7.5m3 12h9.75m-9.75 0a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m-3.75 0H7.5m9-6h3.75m-3.75 0a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m-9.75 0h9.75" /> + </svg> + </button> + + <button class="p-2" title="Representations" + @click="showOffCanvasReps =!showOffCanvasReps"> + <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" + stroke-width="1.5" stroke="currentColor" + class="w-5 h-5 text-gray-500 hover:text-orange-600 cursor-pointer"> + <path stroke-linecap="round" stroke-linejoin="round" + d="M21.75 6.75a4.5 4.5 0 01-4.884 4.484c-1.076-.091-2.264.071-2.95.904l-7.152 8.684a2.548 2.548 0 11-3.586-3.586l8.684-7.152c.833-.686.995-1.874.904-2.95a4.5 4.5 0 016.336-4.486l-3.276 3.276a3.004 3.004 0 002.25 2.25l3.276-3.276c.256.565.398 1.192.398 1.852z" /> + <path stroke-linecap="round" stroke-linejoin="round" + d="M4.867 19.125h.008v.008h-.008v-.008z" /> + </svg> + </button> + + <!-- <button class="p-2" title="Download files" @click="downloadFiles"> + <svg aria-hidden="true" fill="currentColor" viewBox="0 0 20 20" + xmlns="http://www.w3.org/2000/svg" + class="w-5 h-5 text-gray-500 hover:text-orange-600 cursor-pointer"> + <path + d="M10.75 2.75a.75.75 0 00-1.5 0v8.614L6.295 8.235a.75.75 0 10-1.09 1.03l4.25 4.5a.75.75 0 001.09 0l4.25-4.5a.75.75 0 00-1.09-1.03l-2.955 3.129V2.75z" /> + <path + d="M3.5 12.75a.75.75 0 00-1.5 0v2.5A2.75 2.75 0 004.75 18h10.5A2.75 2.75 0 0018 15.25v-2.5a.75.75 0 00-1.5 0v2.5c0 .69-.56 1.25-1.25 1.25H4.75c-.69 0-1.25-.56-1.25-1.25v-2.5z" /> + </svg> + </button> --> + </div> + + + <div class="absolute bottom-0 left-0 z-50 p-2" v-if="anyColorAlphaFold"> + <div class="flex text-xs items-center space-x-2"> + <div class="flex space-x-1 py-1 items-center"> + <span class="w-4 h-4" + style="background-color: rgb(0, 83, 214);"> </span><span + class="legendlabel">Very high ({{confidenceLabel}} > 90)</span> + </div> + <div class="flex space-x-1 py-1 items-center"> + <span class="w-4 h-4" + style="background-color: rgb(101, 203, 243);"> </span><span + class="legendlabel">Confident (90 > {{confidenceLabel}} > 70)</span> + </div> + <div class="flex space-x-1 py-1 items-center"> + <span class="w-4 h-4" + style="background-color: rgb(255, 219, 19);"> </span><span + class="legendlabel">Low (70 > {{confidenceLabel}} > 50)</span> + </div> + <div class="flex space-x-1 py-1 items-center"> + <span class="w-4 h-4" + style="background-color: rgb(255, 125, 69);"> </span><span + class="legendlabel">Very low ({{confidenceLabel}} < 50)</span> + </div> + </div> + </div> + + + + <div v-if="hasFrames" + class="absolute z-50 bottom-0 right-0 mr-2 flex divide-x border border-gray-200 mb-2 rounded items-center justify-center"> + + <button class="p-2" title="Play" @click="toggleAnimation" v-if="isAnimated"> + <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" + stroke-width="2" stroke="currentColor" + class="w-4 h-4 text-gray-500 hover:text-orange-600 cursor-pointer"> + <path stroke-linecap="round" stroke-linejoin="round" + d="M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.348a1.125 1.125 0 010 1.971l-11.54 6.347a1.125 1.125 0 01-1.667-.985V5.653z" /> + </svg> + </button> + + <button class="p-2" title="Pause" @click="toggleAnimation" v-else> + <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" + stroke-width="2" stroke="currentColor" + class="w-4 h-4 text-gray-500 hover:text-orange-600 cursor-pointer"> + <path stroke-linecap="round" stroke-linejoin="round" + d="M5.25 7.5A2.25 2.25 0 017.5 5.25h9a2.25 2.25 0 012.25 2.25v9a2.25 2.25 0 01-2.25 2.25h-9a2.25 2.25 0 01-2.25-2.25v-9z" /> + </svg> + + <!-- <svg + xmlns="http://www.w3.org/2000/svg" + fill="none" + viewBox="0 0 24 24" + stroke-width="2" + stroke="currentColor" + class="w-4 h-4 text-gray-500 hover:text-orange-600 cursor-pointer" + > + <path + stroke-linecap="round" + stroke-linejoin="round" + d="M15.75 5.25v13.5m-7.5-13.5v13.5" + /> + </svg> --> + </button> + + </div> + + <div class="absolute top-0 h-28 z-20 flex flex-col w-full font-mono text-xs"> + <div class="bg-gray-100 pt-2 px-2 h-5/6 border-b overflow-y-scroll" v-show="showSequence" + ref="selectableArea"> + <div class="sequence_container text-sm"> + <div class="sequence__chunk" v-for="(tenAA,index) in sequence" + :key="'tenAA'+index"> + <span + class="p-0.1 text-center w-full inline hover:font-bold cursor-pointer item-selectable" + :class="isSelected(currentModel, currentChain, aa.resi) ? 'bg-green-200' : ''" + v-for="(aa, i) in tenAA" :data-currentmodel="currentModel" + :data-currentchain="currentChain" :data-currentresi="aa.resi"> + <!-- @click="selectAtom(currentModel, currentChain, aa.resi)" --> + <div class="inline-block p-0.5"> + {{aa.resn}} + </div> + + + </span> + </div> + </div> + </div> + <div class="h-1/6 mt-2 font-sans flex justify-between"> + <button class="bg-white p-2 flex space-x-2 rounded ml-2 border h-8"> + <div @click="showSequence = !showSequence" class="flex space-x-1 border-r pr-2"> + <svg v-if="showSequence" fill="none" stroke="currentColor" + stroke-width="1.5" viewBox="0 0 24 24" + xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="h-4 w-4"> + <path stroke-linecap="round" stroke-linejoin="round" + d="M3.98 8.223A10.477 10.477 0 001.934 12C3.226 16.338 7.244 19.5 12 19.5c.993 0 1.953-.138 2.863-.395M6.228 6.228A10.45 10.45 0 0112 4.5c4.756 0 8.773 3.162 10.065 7.498a10.523 10.523 0 01-4.293 5.774M6.228 6.228L3 3m3.228 3.228l3.65 3.65m7.894 7.894L21 21m-3.228-3.228l-3.65-3.65m0 0a3 3 0 10-4.243-4.243m4.242 4.242L9.88 9.88"> + </path> + </svg> + <svg v-else fill="none" stroke="currentColor" stroke-width="1.5" + viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" + aria-hidden="true" class="h-4 w-4"> + <path stroke-linecap="round" stroke-linejoin="round" + d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z"> + </path> + <path stroke-linecap="round" stroke-linejoin="round" + d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path> + </svg> + <span><span v-if="showSequence">Hide</span><span v-else>Show</span> + sequence</span> + + </div> + <div> + <span>Model</span> + <select v-model="currentModel" class="bg-white"> + <option v-for="(moldata, index) in moldata" :key="'model'+index" + :value="index">{{index}}</option> + </select> + </div> + <div> + + <select v-model="currentChain" class="bg-white"> + <option v-for="chain in modelChains" :key="'chains'+chain" + :value="chain">{{chain}}</option> + </select> + </div> + + </button> + + + + </div> + + </div> + + <div class="viewer w-full h-full z-10 mt-20 relative" ref="viewer"></div> + + + + <div id="settings-drawer" + class="absolute top-0 right-0 z-50 h-full overflow-y-auto transition-transform bg-gray-100 w-80 dark:bg-gray-800 border-l border-gray-100" + tabindex="-1" aria-labelledby="settings-drawer-label" v-if="showOffCanvas"> + <div class="p-4"> + <h5 id="settings-drawer-label" + class="inline-flex items-center mb-4 text-base font-semibold text-gray-500 dark:text-gray-400"> + Settings + </h5> + <button type="button" data-drawer-hide="drawer-example" + aria-controls="drawer-example" + class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 absolute top-2.5 right-2.5 inline-flex items-center dark:hover:bg-gray-600 dark:hover:text-white" + @click="showOffCanvas = !showOffCanvas"> + <svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" + xmlns="http://www.w3.org/2000/svg"> + <path fill-rule="evenodd" + d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" + clip-rule="evenodd" /> + </svg> + <span class="sr-only">Close menu</span> + </button> + </div> + + <div class="flex flex-col mb-4 divide-y" v-for="setting in Object.keys(settings)" + :key="setting"> + <div + class="flex items-center border-t border-b border-gray-200 bg-white px-4 py-2 space-x-2"> + + + + + <label :for="setting" + class="text-sm font-medium text-gray-600 dark:text-gray-400 w-1/2"> + {{setting}} + </label> + + + + + <label v-if="settings[setting].type == 'toggle'" + class="relative inline-flex items-center mr-5 cursor-pointer text-center justify-center"> + <input type="checkbox" value="" class="sr-only peer" + v-model="config[setting]" /> + <div + class="w-11 h-6 bg-gray-200 rounded-full peer dark:bg-gray-700 peer-focus:ring-4 peer-focus:ring-orange-300 dark:peer-focus:ring-orange-800 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-orange-400"> + </div> + </label> + + + <div class="flex items-center" v-if="settings[setting].type == 'range'"> + <input id="medium-range" type="range" :min="settings[setting].min" + :max="settings[setting].max" :step="settings[setting].step" + v-model="config[setting]" + class="w-2/3 h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700" /> + <span + class="w-1/3 text-center text-sm font-medium text-gray-600 dark:text-gray-400">{{config[setting]}}</span> + </div> + + <select v-if="settings[setting].type == 'select'" + class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" + v-model="config[setting]"> + + <option v-for="option in settings[setting].options" :value="option" + :selected="option == + config[setting]"> + {{option}} + </option> + + </select> + + + </div> + </div> + + <div class="bg-white"> + <div + class="flex items-center border-t border-b border-gray-200 bg-white px-4 py-2 space-x-2"> + <label class="text-sm font-medium text-gray-600 dark:text-gray-400 w-1/2"> + Label atoms on hover + </label> + <label + class="relative inline-flex items-center mr-5 cursor-pointer text-center justify-center"> + <input type="checkbox" class="sr-only peer" v-model="labelHover" /> + <div + class="w-11 h-6 bg-gray-200 rounded-full peer dark:bg-gray-700 peer-focus:ring-4 peer-focus:ring-orange-300 dark:peer-focus:ring-orange-800 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-orange-400"> + </div> + </label> + </div> + </div> + </div> + + + + <div id="off-canvas-reps" + class="absolute top-0 right-0 z-50 h-full overflow-y-auto transition-transform bg-gray-100 w-80 dark:bg-gray-800 border-l border-gray-100" + tabindex="-1" aria-labelledby="off-canvas-reps-label" v-if="showOffCanvasReps"> + <div class="p-4"> + <h5 id="off-canvas-reps-label" + class="inline-flex items-center mb-4 text-base font-semibold text-gray-500 dark:text-gray-400"> + Representations + </h5> + <button type="button" data-drawer-hide="off-canvas-reps" + aria-controls="off-canvas-reps" + class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 absolute top-2.5 right-2.5 inline-flex items-center dark:hover:bg-gray-600 dark:hover:text-white" + @click="showOffCanvasReps =!showOffCanvasReps"> + <svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" + xmlns="http://www.w3.org/2000/svg"> + <path fill-rule="evenodd" + d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" + clip-rule="evenodd" /> + </svg> + <span class="sr-only">Close menu</span> + </button> + </div> + + + <div v-for="(rep, index) in representations " + class="bg-white border-b border-t border-gray-200 py-4 px-2"> + + <div class=""> + <div class="flex space-x-2 items-center cursor-pointer p-1"> + <button @click="rep.visible = !rep.visible" + class="flex items-center space-x-2"> + <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" + stroke-width="1.5" stroke="currentColor" :class="rep.visible + ? 'transform rotate-90 w-5 h-5' + : 'w-5 h-5'"> + <path stroke-linecap="round" stroke-linejoin="round" + d="M8.25 4.5l7.5 7.5-7.5 7.5" /> + </svg> + <span>Representation #{{index}}</span> + </button> + <button @click="deleteRep(index)"> + <!----> + <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" + stroke-width="1.5" stroke="currentColor" class="w-5 h-5"> + <path stroke-linecap="round" stroke-linejoin="round" + d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0" /> + </svg> + </button> + <button title="zoom to selection" @click="resetZoom(rep)"> + <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" + stroke-width="1.5" stroke="currentColor" + class="w-4 h-4 text-gray-500 hover:text-orange-600 cursor-pointer"> + <path stroke-linecap="round" stroke-linejoin="round" + d="M9 9V4.5M9 9H4.5M9 9L3.75 3.75M9 15v4.5M9 15H4.5M9 15l-5.25 5.25M15 9h4.5M15 9V4.5M15 9l5.25-5.25M15 15h4.5M15 15v4.5m0-4.5l5.25 5.25" /> + </svg> + </button> + </div> + + <div v-if="rep.visible"> + <div class="p-1 flex space-x-1"> + <select id="style" + class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" + v-model="rep.model"> + <option v-for="(mol,i) in moldata" :value="i" :key="'model'+i"> + {{mol.name}} #{{i}}</option> + + </select> + <input type="text" id="chain" + class="w-1/2 bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" + placeholder="Chain" v-model="rep.chain" /> + </div> + <div class="p-1 flex space-x-1"> + <input type="text" id="chain" + class="w-1/2 bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" + placeholder="Resname" v-model="rep.resname" /> + <input type="text" id="residue_range" + class="w-full bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" + placeholder="Residue range" v-model="rep.residue_range" /> + </div> + <div class="p-1 flex space-x-1 items-center"> + <label :for="'style_rep'+index" + class="block mb-2 text-sm w-1/3 font-medium text-gray-600 dark:text-white">Select + style</label> + <select :id="'style_rep'+index" + class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" + v-model="rep.style"> + <option value="stick">Stick</option> + <option value="cartoon">Cartoon</option> + <!-- <option value="surface">Surface</option> --> + <option value="sphere">Sphere</option> + </select> + </div> + <div class="flex p-1 items-center text-gray-700 space-x-1 text-sm"> + <div class="">Expand selection</div> + <input id="around" type="range" min="0" max="10" step="0.5" + v-model="rep.around" + class="h-2 w-1/3 bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700" /> + <input type="text" v-model="rep.around" class="w-8" /> + <div>Å</div> + </div> + + <div class="flex p-1 items-center text-gray-700 text-sm"> + <div class="flex space-x-1 w-1/2 pr-2"> + <span class="whitespace-nowrap">Full residue</span> + <label + class="relative inline-flex items-center mr-5 cursor-pointer text-center h-6"> + <input type="checkbox" value="" class="sr-only peer" + v-model="rep.byres" /> + <div + class="w-11 h-6 bg-gray-200 rounded-full peer dark:bg-gray-700 peer-focus:ring-4 peer-focus:ring-orange-300 dark:peer-focus:ring-orange-800 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-orange-400"> + </div> + </label> + </div> + <div class="flex space-x-1 w-1/2"> + <span class="whitespace-nowrap ">Only sidechain</span> + <label + class="relative inline-flex items-center mr-5 cursor-pointer text-center h-6"> + <input type="checkbox" value="" class="sr-only peer" + v-model="rep.sidechain" /> + <div + class="w-11 h-6 bg-gray-200 rounded-full peer dark:bg-gray-700 peer-focus:ring-4 peer-focus:ring-orange-300 dark:peer-focus:ring-orange-800 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-orange-400"> + </div> + </label> + </div> + </div> + + </div> + </div> + <div class="flex space-x-2 mt-2 w-full p-2"> + <button + :class="rep.color === + 'orangeCarbon' + ?'bg-orange-600 rounded-full w-8 h-8 border-4 border-gray-300 cursor-pointer' + : 'bg-orange-600 rounded-full w-8 h-8 border-4 border-white cursor-pointer'" + @click="rep.color ='orangeCarbon'"> </button> + <button + :class="rep.color === + 'redCarbon' + ?'bg-red-600 rounded-full w-8 h-8 border-4 border-gray-300 cursor-pointer' + : 'bg-red-600 rounded-full w-8 h-8 border-4 border-white cursor-pointer'" + @click="rep.color ='redCarbon'"> </button> + <button + :class="rep.color === + 'greenCarbon' + ?'bg-green-600 rounded-full w-8 h-8 border-4 border-gray-300 cursor-pointer' + : 'bg-green-600 rounded-full w-8 h-8 border-4 border-white cursor-pointer'" + @click="rep.color ='greenCarbon'"></button> + <button + :class="rep.color === + 'blueCarbon' + ?'bg-blue-600 rounded-full w-8 h-8 border-4 border-gray-300 cursor-pointer' + : 'bg-blue-600 rounded-full w-8 h-8 border-4 border-white cursor-pointer'" + @click="rep.color ='blueCarbon'"></button> + </div> + <div class="py-2 text-sm group:m-1"> + <button + :class="rep.color === + 'alphafold' + ?'rounded-lg p-1 border border-gray-400 cursor-pointer bg-gray-200' + : 'rounded-lg p-1 border border-gray-200 cursor-pointer bg-white'" + @click="rep.color ='alphafold'">AlphaFold</button> + <button + :class="rep.color === + 'default' + ?'rounded-lg p-1 border border-gray-400 cursor-pointer bg-gray-200' + : 'rounded-lg p-1 border border-gray-200 cursor-pointer bg-white'" + @click="rep.color ='default'">PyMol</button> + + <button + :class="rep.color === + 'jmol' + ?'rounded-lg p-1 border border-gray-400 cursor-pointer bg-gray-200' + : 'rounded-lg p-1 border border-gray-200 cursor-pointer bg-white'" + @click="rep.color ='jmol'">JMol</button> + + <button + :class="rep.color === + 'chain' + ?'rounded-lg p-1 border border-gray-400 cursor-pointer bg-gray-200' + : 'rounded-lg p-1 border border-gray-200 cursor-pointer bg-white'" + @click="rep.color ='chain'">chain</button> + <button + :class="rep.color === + 'spectrum' + ?'rounded-lg p-1 border border-gray-400 cursor-pointer bg-gray-200' + : 'rounded-lg p-1 border border-gray-200 cursor-pointer bg-white'" + @click="rep.color ='spectrum'">Spectrum</button> + + + </div> + </div> + + <button + class="w-full flex text-orange-600 justify-center my-2 text-sm space-x-2 items-center hover:text-gray-600 cursor-pointer" + @click="insertRep"> + <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" + stroke-width="2" stroke="currentColor" class="w-4 h-4"> + <path stroke-linecap="round" stroke-linejoin="round" + d="M12 9v6m3-3H9m12 0a9 9 0 11-18 0 9 9 0 0118 0z" /> + </svg> + + <div>Add representation</div> + </button> + </div> + + + + + + + </div> + + + + </div> + </div> + </div> + + </div> + + <textarea id="moldata" style="display:none">"""+moldata+""" + </textarea> + + <textarea id="representations" style="display:none">"""+representations+"""</textarea> + </div> + <script src=\""""+url+ """script.js\"></script> +</body> +</html> +""" +import os +import subprocess +import shlex + +def get_color(i): + colors= ["orange", "cyan", "blue", "yellow", "magenta"] + return colors[i % len(colors)]+"Carbon" + + +def output_html(path_to_file,path_to_designs,metrics, resample_idx="",mode="unconditional", selectionStyle={"color": "greenCarbon", + "representation": "cartoon", + "multiple": True}): + + if mode=="conditional": + ext = path_to_file.split(".")[-1] + with open(path_to_file, "r") as f: + data = f.read() + moldata = [{"data": data, "name": os.path.basename(path_to_file), + "selectionStyle": selectionStyle, + "format": ext, + "selectable": True, + "asFrames":False, + "clickable": False}] + representations = [{ + "model": 0, + "chain": "", + "resname": "", + "style": "cartoon", + "color": "whiteCarbon", + "residue_range": "", + "around": 0, + "byres": False, + "visible": False, + }] + if resample_idx!="": + representations.append({ + "model": 0, + "chain": "", + "resname": "", + "style": "cartoon", + "color": "greenCarbon", + "residue_range": resample_idx[1:-1], #remove leading and trailing quotes + "around": 0, + "byres": False, + "visible": False, + }) + # move file from temp to save dir + subprocess.run(shlex.split(f"cp {path_to_file} {os.path.dirname(path_to_designs[0])}/template.pdb")) + path_to_file = f"{os.path.dirname(path_to_designs[0])}/template.pdb" + designs = [{ + "model":0, + "name":"template.pdb", + "fullpath": path_to_file, + "len":76, + "metric":{ + "resample idx": resample_idx[1:-1], + }, + "visible":True, + "color":"gray" + }] + add_index = 1 + else: + designs = [] + moldata = [] + representations = [] + add_index = 0 + + for i,d in enumerate(path_to_designs): + ext = d.split(".")[-1] + with open(d, "r") as f: + data = f.read() + moldata.append({"data": data, "name": os.path.basename(d), + "selectionStyle": selectionStyle, + "format": ext, + "selectable": True, + "asFrames":False, + "clickable": False}) + representations.append({ + "model": i+add_index, + "chain": "", + "resname": "", + "style": "cartoon", + "color": get_color(i), + "residue_range": "", + "around": 0, + "byres": False, + "visible": False, + }) + designs.append({ + "model":i+add_index, + "fullpath": d, + "name":os.path.basename(d), + "metric":metrics[i], + "visible":True, + "color":"" + }) + # dict to json + moldata = json.dumps(moldata) + representations = json.dumps(representations) + designs = json.dumps(designs) + return """<!DOCTYPE html> +<html lang="en"> + +<head> + <script src=\""""+url+ """vue.js\"></script> + <script src="https://unpkg.com/dragselect@latest/dist/ds.min.js"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/3Dmol/2.0.3/3Dmol.min.js"></script> + <script src="https://cdn.tailwindcss.com"></script> + <title>Molecule View</title> + <style> + .item { + width: 50px; + height: 50px; + color: red; + border: 0; + } + + .item:focus { + border: 1px solid rbg(0, 155, 255); + } + + .selectable, + .item-selectable, .model-selectable { + -webkit-user-select: none; + /* Safari */ + -ms-user-select: none; + /* IE 10 and IE 11 */ + user-select: none; + /* Standard syntax */ + } + + .ds-selected { + /* outline: 3px solid black; */ + /* outline-offset: 3px; */ + /* color: black; */ + font-weight: 600; + background-color: rgb(187 247 208) + } + + .sequence_container { + overflow-wrap: anywhere; + counter-reset: sequence; + } + + .sequence_container .sequence__chunk { + display: inline-block; + margin: 0.6rem 0 0.6rem 0.6rem; + /* width: 10ch; */ + position: relative; + white-space: nowrap; + } + + .sequence_container .sequence__chunk:not(:last-child):before, + .sequence_container .sequence__chunk--display-last:before { + content: counter(sequence); + counter-increment: sequence 10; + position: absolute; + top: -0.8em; + right: 0; + opacity: .5; + font-weight: bold; + } + + .sequence-container .sequence__chunk::after { + content: ""; + position: absolute; + bottom: 0; + left: 0; + right: 0; + transform-origin: left; + transform: scaleX(0.1); + box-shadow: var(--box-shadow); + } + + .sequence__chunk span { + padding: 0 0.05rem; + } + + .tooltip .tooltip-text { + display: none; + } + + .tooltip:hover .tooltip-text { + display: block; + } + </style> +</head> + +<body> + <div id="app"> + <div class="flex"> + <div class="w-2/3"> + <div class="bg-white p-5 h-screen w-full" :class="hover ? 'cursor-pointer':''"> + <div class="w-full gr-form overflow-hidden flex border-solid border gap-px rounded-lg flex-wrap"> + <div class="gr-block gr-box relative w-full overflow-hidden border-dashed border border-gray-300 border-gray-200" + style="height:800px"> + <!-- <div + class="absolute z-50 top-0 left-0 bg-white rounded-br border-b border-r border-gray-200 p-1"> + <span class=" flex items-center space-x-1 text-xs text-gray-500"><svg + xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" + viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" + stroke-linecap="round" stroke-linejoin="round" + class="feather feather-file h-3 w-3"> + <path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z" /> + <polyline points="13 2 13 9 20 9" /> + </svg> <span>Molecule3D</span> + </span> + </div> --> + + <div + class="absolute z-50 top-0 right-0 mr-2 flex flex-col divide-y border border-gray-200 mt-2 rounded items-center justify-center bg-white"> + <button class="p-2" title="Reset View" @click="resetZoom"> + <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" + stroke-width="1.5" stroke="currentColor" + class="w-4 h-4 text-gray-500 hover:text-orange-600 cursor-pointer"> + <path stroke-linecap="round" stroke-linejoin="round" + d="M9 9V4.5M9 9H4.5M9 9L3.75 3.75M9 15v4.5M9 15H4.5M9 15l-5.25 5.25M15 9h4.5M15 9V4.5M15 9l5.25-5.25M15 15h4.5M15 15v4.5m0-4.5l5.25 5.25" /> + </svg> + </button> + <button class="p-2" title="Settings" @click="showOffCanvas =!showOffCanvas"> + <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" + stroke-width="1.5" stroke="currentColor" + class="w-5 h-5 text-gray-500 hover:text-orange-600 cursor-pointer"> + <path stroke-linecap="round" stroke-linejoin="round" + d="M10.5 6h9.75M10.5 6a1.5 1.5 0 11-3 0m3 0a1.5 1.5 0 10-3 0M3.75 6H7.5m3 12h9.75m-9.75 0a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m-3.75 0H7.5m9-6h3.75m-3.75 0a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m-9.75 0h9.75" /> + </svg> + </button> + + <button class="p-2" title="Representations" + @click="showOffCanvasReps =!showOffCanvasReps"> + <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" + stroke-width="1.5" stroke="currentColor" + class="w-5 h-5 text-gray-500 hover:text-orange-600 cursor-pointer"> + <path stroke-linecap="round" stroke-linejoin="round" + d="M21.75 6.75a4.5 4.5 0 01-4.884 4.484c-1.076-.091-2.264.071-2.95.904l-7.152 8.684a2.548 2.548 0 11-3.586-3.586l8.684-7.152c.833-.686.995-1.874.904-2.95a4.5 4.5 0 016.336-4.486l-3.276 3.276a3.004 3.004 0 002.25 2.25l3.276-3.276c.256.565.398 1.192.398 1.852z" /> + <path stroke-linecap="round" stroke-linejoin="round" + d="M4.867 19.125h.008v.008h-.008v-.008z" /> + </svg> + </button> + + <!-- <button class="p-2" title="Download files" @click="downloadFiles"> + <svg aria-hidden="true" fill="currentColor" viewBox="0 0 20 20" + xmlns="http://www.w3.org/2000/svg" + class="w-5 h-5 text-gray-500 hover:text-orange-600 cursor-pointer"> + <path + d="M10.75 2.75a.75.75 0 00-1.5 0v8.614L6.295 8.235a.75.75 0 10-1.09 1.03l4.25 4.5a.75.75 0 001.09 0l4.25-4.5a.75.75 0 00-1.09-1.03l-2.955 3.129V2.75z" /> + <path + d="M3.5 12.75a.75.75 0 00-1.5 0v2.5A2.75 2.75 0 004.75 18h10.5A2.75 2.75 0 0018 15.25v-2.5a.75.75 0 00-1.5 0v2.5c0 .69-.56 1.25-1.25 1.25H4.75c-.69 0-1.25-.56-1.25-1.25v-2.5z" /> + </svg> + </button> --> + </div> + + + <div class="absolute bottom-0 left-0 z-50 p-2" v-if="anyColorAlphaFold"> + <div class="flex text-xs items-center space-x-2"> + <div class="flex space-x-1 py-1 items-center"> + <span class="w-4 h-4" + style="background-color: rgb(0, 83, 214);"> </span><span + class="legendlabel">Very high ({{confidenceLabel}} > 90)</span> + </div> + <div class="flex space-x-1 py-1 items-center"> + <span class="w-4 h-4" + style="background-color: rgb(101, 203, 243);"> </span><span + class="legendlabel">Confident (90 > {{confidenceLabel}} > 70)</span> + </div> + <div class="flex space-x-1 py-1 items-center"> + <span class="w-4 h-4" + style="background-color: rgb(255, 219, 19);"> </span><span + class="legendlabel">Low (70 > {{confidenceLabel}} > 50)</span> + </div> + <div class="flex space-x-1 py-1 items-center"> + <span class="w-4 h-4" + style="background-color: rgb(255, 125, 69);"> </span><span + class="legendlabel">Very low ({{confidenceLabel}} < 50)</span> + </div> + </div> + </div> + + + + <div v-if="hasFrames" + class="absolute z-50 bottom-0 right-0 mr-2 flex divide-x border border-gray-200 mb-2 rounded items-center justify-center"> + + <button class="p-2" title="Play" @click="toggleAnimation" v-if="isAnimated"> + <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" + stroke-width="2" stroke="currentColor" + class="w-4 h-4 text-gray-500 hover:text-orange-600 cursor-pointer"> + <path stroke-linecap="round" stroke-linejoin="round" + d="M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.348a1.125 1.125 0 010 1.971l-11.54 6.347a1.125 1.125 0 01-1.667-.985V5.653z" /> + </svg> + </button> + + <button class="p-2" title="Pause" @click="toggleAnimation" v-else> + <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" + stroke-width="2" stroke="currentColor" + class="w-4 h-4 text-gray-500 hover:text-orange-600 cursor-pointer"> + <path stroke-linecap="round" stroke-linejoin="round" + d="M5.25 7.5A2.25 2.25 0 017.5 5.25h9a2.25 2.25 0 012.25 2.25v9a2.25 2.25 0 01-2.25 2.25h-9a2.25 2.25 0 01-2.25-2.25v-9z" /> + </svg> + + <!-- <svg + xmlns="http://www.w3.org/2000/svg" + fill="none" + viewBox="0 0 24 24" + stroke-width="2" + stroke="currentColor" + class="w-4 h-4 text-gray-500 hover:text-orange-600 cursor-pointer" + > + <path + stroke-linecap="round" + stroke-linejoin="round" + d="M15.75 5.25v13.5m-7.5-13.5v13.5" + /> + </svg> --> + </button> + + </div> + + <div class="absolute top-0 h-28 z-20 flex flex-col w-full font-mono text-xs"> + <div class="bg-gray-100 pt-2 px-2 h-5/6 border-b overflow-y-scroll" + v-show="showSequence" ref="selectableArea"> + <div class="sequence_container text-sm"> + <div class="sequence__chunk" v-for="(tenAA,index) in sequence" + :key="'tenAA'+index"> + <span + class="p-0.1 text-center w-full inline hover:font-bold cursor-pointer item-selectable" + :class="isSelected(currentModel, currentChain, aa.resi) ? 'bg-green-200' : ''" + v-for="(aa, i) in tenAA" :data-currentmodel="currentModel" + :data-currentchain="currentChain" :data-currentresi="aa.resi"> + <!-- @click="selectAtom(currentModel, currentChain, aa.resi)" --> + <div class="inline-block p-0.5"> + {{aa.resn}} + </div> + + + </span> + </div> + </div> + </div> + <div class="h-1/6 mt-2 font-sans flex justify-between"> + <button class="bg-white p-2 flex space-x-2 rounded ml-2 border h-8"> + <div @click="showSequence = !showSequence" class="flex space-x-1 border-r pr-2"> + <svg v-if="showSequence" fill="none" stroke="currentColor" + stroke-width="1.5" viewBox="0 0 24 24" + xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="h-4 w-4"> + <path stroke-linecap="round" stroke-linejoin="round" + d="M3.98 8.223A10.477 10.477 0 001.934 12C3.226 16.338 7.244 19.5 12 19.5c.993 0 1.953-.138 2.863-.395M6.228 6.228A10.45 10.45 0 0112 4.5c4.756 0 8.773 3.162 10.065 7.498a10.523 10.523 0 01-4.293 5.774M6.228 6.228L3 3m3.228 3.228l3.65 3.65m7.894 7.894L21 21m-3.228-3.228l-3.65-3.65m0 0a3 3 0 10-4.243-4.243m4.242 4.242L9.88 9.88"> + </path> + </svg> + <svg v-else fill="none" stroke="currentColor" stroke-width="1.5" + viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" + aria-hidden="true" class="h-4 w-4"> + <path stroke-linecap="round" stroke-linejoin="round" + d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z"> + </path> + <path stroke-linecap="round" stroke-linejoin="round" + d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path> + </svg> + <span><span v-if="showSequence">Hide</span><span v-else>Show</span> + sequence</span> + + </div> + <div> + <span>Model</span> + <select v-model="currentModel" class="bg-white"> + <option v-for="(moldata, index) in moldata" + :key="'model'+index" :value="index">{{index}}</option> + </select> + </div> + <div> + <select v-model="currentChain" class="bg-white"> + <option v-for="chain in modelChains" :key="'chains'+chain" + :value="chain">{{chain}}</option> + </select> + </div> + + </button> + + + + </div> + + </div> + + <div class="viewer w-full h-full z-10 mt-20 relative" ref="viewer"></div> + + + + <div id="settings-drawer" + class="absolute top-0 right-0 z-50 h-full overflow-y-auto transition-transform bg-gray-100 w-80 dark:bg-gray-800 border-l border-gray-100" + tabindex="-1" aria-labelledby="settings-drawer-label" v-if="showOffCanvas"> + <div class="p-4"> + <h5 id="settings-drawer-label" + class="inline-flex items-center mb-4 text-base font-semibold text-gray-500 dark:text-gray-400"> + Settings + </h5> + <button type="button" data-drawer-hide="drawer-example" + aria-controls="drawer-example" + class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 absolute top-2.5 right-2.5 inline-flex items-center dark:hover:bg-gray-600 dark:hover:text-white" + @click="showOffCanvas = !showOffCanvas"> + <svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" + xmlns="http://www.w3.org/2000/svg"> + <path fill-rule="evenodd" + d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" + clip-rule="evenodd" /> + </svg> + <span class="sr-only">Close menu</span> + </button> + </div> + + <div class="flex flex-col mb-4 divide-y" v-for="setting in Object.keys(settings)" + :key="setting"> + <div + class="flex items-center border-t border-b border-gray-200 bg-white px-4 py-2 space-x-2"> + + + + + <label :for="setting" + class="text-sm font-medium text-gray-600 dark:text-gray-400 w-1/2"> + {{setting}} + </label> + + + + + <label v-if="settings[setting].type == 'toggle'" + class="relative inline-flex items-center mr-5 cursor-pointer text-center justify-center"> + <input type="checkbox" value="" class="sr-only peer" + v-model="config[setting]" /> + <div + class="w-11 h-6 bg-gray-200 rounded-full peer dark:bg-gray-700 peer-focus:ring-4 peer-focus:ring-orange-300 dark:peer-focus:ring-orange-800 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-orange-400"> + </div> + </label> + + + <div class="flex items-center" + v-if="settings[setting].type == 'range'"> + <input id="medium-range" type="range" :min="settings[setting].min" + :max="settings[setting].max" :step="settings[setting].step" + v-model="config[setting]" + class="w-2/3 h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700" /> + <span + class="w-1/3 text-center text-sm font-medium text-gray-600 dark:text-gray-400">{{config[setting]}}</span> + </div> + + <select v-if="settings[setting].type == 'select'" + class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" + v-model="config[setting]"> + + <option v-for="option in settings[setting].options" :value="option" + :selected="option == + config[setting]"> + {{option}} + </option> + + </select> + + + </div> + </div> + + <div class="bg-white"> + <div + class="flex items-center border-t border-b border-gray-200 bg-white px-4 py-2 space-x-2"> + <label class="text-sm font-medium text-gray-600 dark:text-gray-400 w-1/2"> + Label atoms on hover + </label> + <label + class="relative inline-flex items-center mr-5 cursor-pointer text-center justify-center"> + <input type="checkbox" class="sr-only peer" v-model="labelHover" /> + <div + class="w-11 h-6 bg-gray-200 rounded-full peer dark:bg-gray-700 peer-focus:ring-4 peer-focus:ring-orange-300 dark:peer-focus:ring-orange-800 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-orange-400"> + </div> + </label> + </div> + </div> + </div> + + + + <div id="off-canvas-reps" + class="absolute top-0 right-0 z-50 h-full overflow-y-auto transition-transform bg-gray-100 w-80 dark:bg-gray-800 border-l border-gray-100" + tabindex="-1" aria-labelledby="off-canvas-reps-label" v-if="showOffCanvasReps"> + <div class="p-4"> + <h5 id="off-canvas-reps-label" + class="inline-flex items-center mb-4 text-base font-semibold text-gray-500 dark:text-gray-400"> + Representations + </h5> + <button type="button" data-drawer-hide="off-canvas-reps" + aria-controls="off-canvas-reps" + class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 absolute top-2.5 right-2.5 inline-flex items-center dark:hover:bg-gray-600 dark:hover:text-white" + @click="showOffCanvasReps =!showOffCanvasReps"> + <svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" + xmlns="http://www.w3.org/2000/svg"> + <path fill-rule="evenodd" + d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" + clip-rule="evenodd" /> + </svg> + <span class="sr-only">Close menu</span> + </button> + </div> + + + <div v-for="(rep, index) in representations " + class="bg-white border-b border-t border-gray-200 py-4 px-2" v-if="isModelVisible(rep.model)"> + + <div class=""> + <div class="flex space-x-2 items-center cursor-pointer p-1"> + <button @click="rep.visible = !rep.visible" + class="flex items-center space-x-2"> + <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" + stroke-width="1.5" stroke="currentColor" :class="rep.visible + ? 'transform rotate-90 w-5 h-5' + : 'w-5 h-5'"> + <path stroke-linecap="round" stroke-linejoin="round" + d="M8.25 4.5l7.5 7.5-7.5 7.5" /> + </svg> + <span>Representation #{{index}}</span> + </button> + <button @click="deleteRep(index)"> + <!----> + <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" + stroke-width="1.5" stroke="currentColor" class="w-5 h-5"> + <path stroke-linecap="round" stroke-linejoin="round" + d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0" /> + </svg> + </button> + <button title="zoom to selection" @click="resetZoom(rep)"> + <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" + stroke-width="1.5" stroke="currentColor" + class="w-4 h-4 text-gray-500 hover:text-orange-600 cursor-pointer"> + <path stroke-linecap="round" stroke-linejoin="round" + d="M9 9V4.5M9 9H4.5M9 9L3.75 3.75M9 15v4.5M9 15H4.5M9 15l-5.25 5.25M15 9h4.5M15 9V4.5M15 9l5.25-5.25M15 15h4.5M15 15v4.5m0-4.5l5.25 5.25" /> + </svg> + </button> + </div> + + <div v-if="rep.visible"> + <div class="p-1 flex space-x-1"> + <select id="style" + class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" + v-model="rep.model"> + <option v-for="(mol,i) in moldata" :value="i" + :key="'model'+i"> + {{mol.name}} #{{i}}</option> + + </select> + <input type="text" id="chain" + class="w-1/2 bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" + placeholder="Chain" v-model="rep.chain" /> + </div> + <div class="p-1 flex space-x-1"> + <input type="text" id="chain" + class="w-1/2 bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" + placeholder="Resname" v-model="rep.resname" /> + <input type="text" id="residue_range" + class="w-full bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" + placeholder="Residue range" v-model="rep.residue_range" /> + </div> + <div class="p-1 flex space-x-1 items-center"> + <label :for="'style_rep'+index" + class="block mb-2 text-sm w-1/3 font-medium text-gray-600 dark:text-white">Select + style</label> + <select :id="'style_rep'+index" + class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" + v-model="rep.style"> + <option value="stick">Stick</option> + <option value="cartoon">Cartoon</option> + <!-- <option value="surface">Surface</option> --> + <option value="sphere">Sphere</option> + </select> + </div> + <div class="flex p-1 items-center text-gray-700 space-x-1 text-sm"> + <div class="">Expand selection</div> + <input id="around" type="range" min="0" max="10" step="0.5" + v-model="rep.around" + class="h-2 w-1/3 bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700" /> + <input type="text" v-model="rep.around" class="w-8" /> + <div>Å</div> + </div> + + <div class="flex p-1 items-center text-gray-700 text-sm"> + <div class="flex space-x-1 w-1/2 pr-2"> + <span class="whitespace-nowrap">Full residue</span> + <label + class="relative inline-flex items-center mr-5 cursor-pointer text-center h-6"> + <input type="checkbox" value="" class="sr-only peer" + v-model="rep.byres" /> + <div + class="w-11 h-6 bg-gray-200 rounded-full peer dark:bg-gray-700 peer-focus:ring-4 peer-focus:ring-orange-300 dark:peer-focus:ring-orange-800 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-orange-400"> + </div> + </label> + </div> + <div class="flex space-x-1 w-1/2"> + <span class="whitespace-nowrap ">Only sidechain</span> + <label + class="relative inline-flex items-center mr-5 cursor-pointer text-center h-6"> + <input type="checkbox" value="" class="sr-only peer" + v-model="rep.sidechain" /> + <div + class="w-11 h-6 bg-gray-200 rounded-full peer dark:bg-gray-700 peer-focus:ring-4 peer-focus:ring-orange-300 dark:peer-focus:ring-orange-800 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-orange-400"> + </div> + </label> + </div> + </div> + + </div> + </div> + <div class="flex space-x-2 mt-2 w-full p-2"> + <button + :class="rep.color === + 'orangeCarbon' + ?'bg-orange-600 rounded-full w-8 h-8 border-4 border-gray-300 cursor-pointer' + : 'bg-orange-600 rounded-full w-8 h-8 border-4 border-white cursor-pointer'" + @click="rep.color ='orangeCarbon'"> </button> + <button + :class="rep.color === + 'redCarbon' + ?'bg-red-600 rounded-full w-8 h-8 border-4 border-gray-300 cursor-pointer' + : 'bg-red-600 rounded-full w-8 h-8 border-4 border-white cursor-pointer'" + @click="rep.color ='redCarbon'"> </button> + <button + :class="rep.color === + 'greenCarbon' + ?'bg-green-600 rounded-full w-8 h-8 border-4 border-gray-300 cursor-pointer' + : 'bg-green-600 rounded-full w-8 h-8 border-4 border-white cursor-pointer'" + @click="rep.color ='greenCarbon'"></button> + <button + :class="rep.color === + 'blueCarbon' + ?'bg-blue-600 rounded-full w-8 h-8 border-4 border-gray-300 cursor-pointer' + : 'bg-blue-600 rounded-full w-8 h-8 border-4 border-white cursor-pointer'" + @click="rep.color ='blueCarbon'"></button> + </div> + <div class="py-2 text-sm group:m-1"> + <button + :class="rep.color === + 'alphafold' + ?'rounded-lg p-1 border border-gray-400 cursor-pointer bg-gray-200' + : 'rounded-lg p-1 border border-gray-200 cursor-pointer bg-white'" + @click="rep.color ='alphafold'">AlphaFold</button> + <button + :class="rep.color === + 'default' + ?'rounded-lg p-1 border border-gray-400 cursor-pointer bg-gray-200' + : 'rounded-lg p-1 border border-gray-200 cursor-pointer bg-white'" + @click="rep.color ='default'">PyMol</button> + + <button + :class="rep.color === + 'jmol' + ?'rounded-lg p-1 border border-gray-400 cursor-pointer bg-gray-200' + : 'rounded-lg p-1 border border-gray-200 cursor-pointer bg-white'" + @click="rep.color ='jmol'">JMol</button> + + <button + :class="rep.color === + 'chain' + ?'rounded-lg p-1 border border-gray-400 cursor-pointer bg-gray-200' + : 'rounded-lg p-1 border border-gray-200 cursor-pointer bg-white'" + @click="rep.color ='chain'">chain</button> + <button + :class="rep.color === + 'spectrum' + ?'rounded-lg p-1 border border-gray-400 cursor-pointer bg-gray-200' + : 'rounded-lg p-1 border border-gray-200 cursor-pointer bg-white'" + @click="rep.color ='spectrum'">Spectrum</button> + + + </div> + </div> + + <button + class="w-full flex text-orange-600 justify-center my-2 text-sm space-x-2 items-center hover:text-gray-600 cursor-pointer" + @click="insertRep"> + <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" + stroke-width="2" stroke="currentColor" class="w-4 h-4"> + <path stroke-linecap="round" stroke-linejoin="round" + d="M12 9v6m3-3H9m12 0a9 9 0 11-18 0 9 9 0 0118 0z" /> + </svg> + + <div>Add representation</div> + </button> + </div> + + + + + + + </div> + + + + </div> + </div> + </div> + <div class="w-1/3 py-5 px-1 overflow-y-scroll" style="height:880px" ref="modelSelectableArea"> + <div + class="gr-block gr-box relative w-full border-dashed border border-gray-300 border-gray-200 px-3 py-2 rounded"> + + <div class="my-5 overflow-y-auto"> + + + <div v-for="(d, i) in designs" :key="'design'+i" + class="model-selectable flex justify-between items-center border-b py-3 px-2 border-l-4 border-l-slate-300 transition ease-linear duration-150" + :class="d.visible ? designActiveClass(i,d.color) : ''" :data-currentmodel="i"> + + <div class="inline-flex items-center space-x-2 cursor-pointer" + > + <div> + <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" + stroke-width="1.5" stroke="currentColor" class=" text-slate-500 w-6 h-6" + v-if="!d.visible"> + <path stroke-linecap="round" stroke-linejoin="round" + d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z" /> + <path stroke-linecap="round" stroke-linejoin="round" + d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" /> + </svg> + + <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" + stroke-width="1.5" stroke="currentColor" class="text-slate-500 w-6 h-6" v-else> + <path stroke-linecap="round" stroke-linejoin="round" + d="M3.98 8.223A10.477 10.477 0 001.934 12C3.226 16.338 7.244 19.5 12 19.5c.993 0 1.953-.138 2.863-.395M6.228 6.228A10.45 10.45 0 0112 4.5c4.756 0 8.773 3.162 10.065 7.498a10.523 10.523 0 01-4.293 5.774M6.228 6.228L3 3m3.228 3.228l3.65 3.65m7.894 7.894L21 21m-3.228-3.228l-3.65-3.65m0 0a3 3 0 10-4.243-4.243m4.242 4.242L9.88 9.88" /> + </svg> + + </div> + <div><span class="text-sm font-medium px-2">{{d.model}}</span>{{d.name}} <span class="text-xs"> <span v-for="(v,k) in d.metric">{{k}}: {{v}}</span></span></div> + + </div> + <div> + <a :href="'/file='+d.fullpath"> + <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" + stroke-width="1.5" stroke="currentColor" + class=" text-slate-500 hover:text-slate-700 w-4 h-4 cursor-pointer"> + <path stroke-linecap="round" stroke-linejoin="round" + d="M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5M16.5 12L12 16.5m0 0L7.5 12m4.5 4.5V3" /> + </svg> + </a> + </div> + </div> + + </div> + </div> + </div> + </div> + </div> + <textarea id="moldata" + style="display:none">""" + moldata + """</textarea> + + <textarea id="representations" + style="display:none">""" + representations + """</textarea> + <textarea id="designs" style="display:none">""" + designs + """</textarea> + <script src=\""""+url+ """script_output.js\"></script> +</body> +</html>""" + +load_js = """ + +async () => { + // create empty textarea with id selectedAtoms that is hidden + // and append it to the body + var selectedAtoms = document.createElement("textarea"); + selectedAtoms.id = "selectedAtoms"; + selectedAtoms.style.display = "none"; + document.body.appendChild(selectedAtoms); + +window.onmessage = function(e) { +selectedAtoms.value = JSON.stringify(e.data); +}; +} +""" + +get_js = """ +async (resample_idxs) => { + + var selectedAtoms = document.getElementById("selectedAtoms"); + var selectedAtomsValue = selectedAtoms.value; + + var hasNumber = /\d/; + + + if (hasNumber.test(selectedAtomsValue)==false) { + selectedAtomsValue = resample_idxs.replace(/.$/,' "') + + } + return selectedAtomsValue; + +} +"""