diff --git a/ippisite/ippidb/serializer.py b/ippisite/ippidb/serializer.py index e81cd57c40cc324205f00c7fc5940f1b5458da2e..11a35ad8df24bd86e769effb03719fce9f616492 100644 --- a/ippisite/ippidb/serializer.py +++ b/ippisite/ippidb/serializer.py @@ -124,6 +124,7 @@ class ChainSerializer(serializers.ModelSerializer): "default_isolevel", "interactfile_set", ) + ordering = ["pdb_chain_id"] class LigandSerializer(serializers.ModelSerializer): diff --git a/ippisite/ippidb/static/css/targetcentric.css b/ippisite/ippidb/static/css/targetcentric.css index 4412f683c36ee230e3f52e67f1ce486c0421770e..635ff9b4adc064f0727b5a6d907d41d4ec7cee15 100644 --- a/ippisite/ippidb/static/css/targetcentric.css +++ b/ippisite/ippidb/static/css/targetcentric.css @@ -134,7 +134,10 @@ Description: IPPI-DB targetcentric Theme .dropbtn { font-size: 14px; - color: #007bff + color: #2D96FA; + border-radius: 5px; + border-color: #97ADB5; + background-color: #eff3f5; } .dropdown { @@ -145,12 +148,16 @@ Description: IPPI-DB targetcentric Theme .dropdown-content { display: none; position: absolute; - bottom: 24px; - left: 14px; - background-color: #f1f1f1; + bottom: 22px; + left: 12px; + background-color: #eff3f5; min-width: 100px; - box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); + box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.4); z-index: 3; + border-radius: 5px; + border-color: #97adb5 !important; + border: 2px; + border-style: solid; } .dropdown-content a { @@ -161,11 +168,18 @@ Description: IPPI-DB targetcentric Theme display: block; } -.dropdown-content a:hover {background-color: #ddd;} +.dropdown-content a:hover { + background-color: #d3dee2; + color: black; + border-radius: 5px; +} .dropdown:hover .dropdown-content {display: block;} -.dropdown:hover .dropbtn {background-color: #ddd;} +.dropdown:hover .dropbtn { + background-color: #d3dee2; + color: black; +} .infobulle span{ position:absolute; diff --git a/ippisite/ippidb/static/js/targetcentric.js b/ippisite/ippidb/static/js/targetcentric.js index 83a0968dc97602c6afd7989e7ce8b4ab021199c6..fc0c93d2104991b30f0875d0d1dad708af75e86a 100644 --- a/ippisite/ippidb/static/js/targetcentric.js +++ b/ippisite/ippidb/static/js/targetcentric.js @@ -378,14 +378,14 @@ function loadNGL(url, callback){ divflex.appendChild(divmultiButtonleft); var divslider = createElement("div", {}, {}, 'infobulle form-group border border-info rounded p-2'); var spaninfodrug = createElement("span", {}, {}, ''); - spaninfodrug.innerHTML = "Druggability has been determined by our Deep Learning tool InDeep and are represented as isolevel probabilities, which you can adjust with the slider (0,1)." + spaninfodrug.innerHTML = "Druggability has been determined by our Deep Learning tool InDeep learning on protein/ligand complexes/interactions. They are represented as isolevel probabilities, which you can adjust with the slider (0,1)." divslider.appendChild(spaninfodrug); titledruggable = createElement("strong", {}, {}, ''); - titledruggable.innerHTML = "Predicted druggablility"; + titledruggable.innerHTML = "Predicted druggability"; divslider.appendChild(titledruggable); var divsliderinteractibility = createElement("div", {}, {}, 'infobulle form-group border border-info rounded p-2 mr-2'); var spaninfoint = createElement("span", {}, {"right":"50%"}, ''); - spaninfoint.innerHTML = "Interactability has been determined by our Deep Learning tool InDeep and are represented as isolevel probabilities, which you can adjust with the slider (0,1)." + spaninfoint.innerHTML = "Interactability has been determined by our Deep Learning tool InDeep learning on heterodimers complexes/interactions. They are represented as isolevel probabilities, which you can adjust with the slider (0,1)." divsliderinteractibility.appendChild(spaninfoint); titleinteractible = createElement("strong", {}, {}, ''); titleinteractible.innerHTML = "Predicted Interactability"; @@ -428,7 +428,7 @@ function loadNGL(url, callback){ "data-toggle":"dropdown", "aria-haspopup":"true", "aria-expanded":"false"}); - buttondorpdowninterac.append("Select interactibility model, chain ".concat(chain.pdb_chain_id )); + buttondorpdowninterac.append("Select interactability model, chain ".concat(chain.pdb_chain_id )); divdropdowninterac.appendChild(buttondorpdowninterac); var dropdowninteracmenu = createElement("div",{},{},"dropdown-menu",{'aria-labelledby': componentname + "_interact"}); divdropdowninterac.appendChild(dropdowninteracmenu); @@ -624,7 +624,7 @@ function loadNGL(url, callback){ }; if (hasinteract == 0) { var labelsliderinteractibility = createElement("label", {}, {}, "", {}); - labelsliderinteractibility.innerHTML = 'No interactible surface predict'; + labelsliderinteractibility.innerHTML = 'No interactable surface predict'; divsliderinteractibility.appendChild(labelsliderinteractibility); }; pdb.ligand_set.forEach(function(ligand){ diff --git a/ippisite/ippidb/static/js/targetcentrict_networks.js b/ippisite/ippidb/static/js/targetcentrict_networks.js index 522d719b38cd650d2a5bccfd18675643fd374c9e..635980a3a84fcc5e07c818cec5a7095b0061f04b 100644 --- a/ippisite/ippidb/static/js/targetcentrict_networks.js +++ b/ippisite/ippidb/static/js/targetcentrict_networks.js @@ -127,18 +127,32 @@ $.ajax({ color: 'DarkSlateGrey'}, opacity: opacity[1]}}; Plotly.restyle('myDiv', update_PL, 0); Plotly.restyle('myDiv', update_HD, 1); - - }); + + var queryString = window.location.search; + var urlParams = new URLSearchParams(queryString); + var cavity = urlParams.get('search'); + if (cavity) { + if (cavity in nodes_coords) { + console.log(cavity); + currentlayout = ippidb_plot.layout; + currentlayout.xaxis['autorange'] = false; + currentlayout.yaxis['autorange'] = false; + currentlayout.xaxis['range'] = [nodes_coords[cavity][0]-0.01, nodes_coords[cavity][0]+0.01]; + currentlayout.yaxis['range'] = [nodes_coords[cavity][1]-0.01, nodes_coords[cavity][1]+0.01]; + Plotly.relayout('myDiv', currentlayout); + }; + } $('.search-button').click(function() { var cavity = $("#id_search").val(); - currentlayout = ippidb_plot.layout; + window.open(window.location.pathname+"?search="+cavity, '_self'); + /*currentlayout = ippidb_plot.layout; currentlayout.xaxis['autorange'] = false; currentlayout.yaxis['autorange'] = false; currentlayout.xaxis['range'] = [nodes_coords[cavity][0]-0.01, nodes_coords[cavity][0]+0.01]; currentlayout.yaxis['range'] = [nodes_coords[cavity][1]-0.01, nodes_coords[cavity][1]+0.01]; - Plotly.relayout('myDiv', currentlayout); + Plotly.relayout('myDiv', currentlayout);*/ }); autocomplete(document.getElementById("id_search"), Object.keys(nodes_coords)); diff --git a/ippisite/ippidb/templates/index.html b/ippisite/ippidb/templates/index.html index 32e5f3fcf0c6a3f889d0f161da3b13cdb11c365e..c5d07d234d4711e29099ff71213a8f59c90699f1 100644 --- a/ippisite/ippidb/templates/index.html +++ b/ippisite/ippidb/templates/index.html @@ -303,7 +303,7 @@ Navigate the PPI pocketome </div> <div class="choices_description">Explore the iPPI-DB - heterodimer pocketome by navigating + pocketome by navigating within an interactive network. </div> </div> diff --git a/ippisite/ippidb/templates/targetcentric.html b/ippisite/ippidb/templates/targetcentric.html index 2323223f061bd95a3a1ef0ee2d4f64c4e7f901c7..9f3a7ff0c1ebc1971417037047f2443c902eb7f2 100644 --- a/ippisite/ippidb/templates/targetcentric.html +++ b/ippisite/ippidb/templates/targetcentric.html @@ -95,7 +95,7 @@ </div> <div class="row form-group"> <div class="col"> - <input id="id_ligandcode" name="ligandcode" class="form-control" type="text" placeholder="3 letter code ligands"> + <input id="id_ligandcode" name="ligandcode" class="form-control" type="text" placeholder="3 characters code ligands"> </div> <div class="col"> <input id="id_organism" name="organism" class="form-control" type="text" placeholder="Organism name"> @@ -129,7 +129,7 @@ </div> <div class="card-body text-nowrap"> {% for chain in pdb.chain_set.all reversed %} - {% if forloop.counter > 1 %}With {% else %}On {% endif %}Chain {{ chain.pdb_chain_id }} <a class="submithref" href="{% url 'cavities' %}?uniprotid={{ chain.protein.uniprot_id }}">{{ chain.protein.uniprot_id }}</a> + Chain {{ chain.pdb_chain_id }} <a class="submithref" href="{% url 'cavities' %}?uniprotid={{ chain.protein.uniprot_id }}">{{ chain.protein.uniprot_id }}</a> <a class="submithref" href="{% url 'cavities' %}?organism={{ chain.protein.organism.name }}">{{ chain.protein.organism.name }}</a> </br> {% endfor %} @@ -177,6 +177,8 @@ PSI is given when you mouseover a pocket name. </p> <p>Table of descriptors for each pocket, detected by Volsite (Desaphy et al., 2012). Click on <i class="far fa-plus-square"></i> icon to see closest pockets, based on the Pocket Similarity Index. + Pocket name is built with : pdb id / pocket's chain id / pocket number -- + (PL for a protein ligand complex or HD for a heterodimer / partner ligand id or chain id) </p> </div> <div class="col-4"> @@ -198,7 +200,7 @@ <table id="cavitiestable" class="table table-hover shadow table-responsive table-sm zui-table table-header-rotated"> <thead class="thead-light"> <tr> - <th class="zui-sticky-col" title="PDB / Chain / Partner / Pocket" scope="col"><div><span>Pockets</span></div></th> + <th class="zui-sticky-col" title="PDB ID / Chain ID / Pocket -- (Type / Partner ID)" scope="col"><div><span>Pockets</span></div></th> <th class="rotate-45" title="Volume in Aˆ3" scope="col"><div><span>Volume</span></div></th> <th class="rotate-45" title="Normalized Moment of Inertia PMX/PMZ" scope="col"><div><span>NPR1</span></div></th> <th class="rotate-45" title="Normalized Moment of Inertia PMY/PMZ" scope="col"><div><span>NPR2</span></div></th> @@ -239,15 +241,25 @@ / <span class="dropdown"> <button class="dropbtn btn-outline-secondary" data-toggle="dropdown" title="uniprot: {{ cavity.chain.protein.uniprot_id }}"> - {{ cavity.chain.pdb_chain_id }} / {{ cavity.chain.protein.short_name }} + {{ cavity.chain.pdb_chain_id }}<!-- / {{ cavity.chain.protein.short_name }} --> </button> <div class="dropdown-content"> <a target="_blank" rel="noopener noreferrer" href="{% url 'cavities' %}?uniprotid={{ cavity.chain.protein.uniprot_id }}">Query UniprotID in pockets</a> <a target="_blank" rel="noopener noreferrer" href="{% url 'compound_list' %}?uniprot_id={{ cavity.chain.protein.uniprot_id }}">Query UniprotID as iPPI-DB target</a> </div> </span> - {% if cavity.partner.ligand %} / + <span class="dropdown"> + <button class="dropbtn btn-outline-secondary" data-toggle="dropdown"> + {{ cavity.cavity_number }} + </button> + <div class="dropdown-content"> + <a target="_blank" rel="noopener noreferrer" href="{% url 'networks' %}?search={{ cavity|build_name }}"> Query pocket in pocketome</a> + </div> + </span> + -- + {% if cavity.partner.ligand %} + (PL / <span class="dropdown"> <button class="dropbtn btn-outline-secondary" data-toggle="dropdown" title="smiles: {{ cavity.partner.ligand.canonical_smile }}"> {{ cavity.partner.ligand.pdb_ligand_id }}_{{ cavity.partner.ligand.supplementary_id }} @@ -256,9 +268,9 @@ <a target="_blank" rel="noopener noreferrer" href="{% url 'cavities' %}?ligandcode={{ cavity.partner.ligand.pdb_ligand_id }}">Query ligand ID in pockets</a> <a target="_blank" rel="noopener noreferrer" href="{% url 'compound_list' %}?similar_to=ECFP4:{{ cavity.partner.ligand.canonical_smile|urlencode }}">Query SMILES in iPPI-DB compounds</a> </div> - </span> + </span>) {% else %} - / + (HD / <span class="dropdown"> <button class="dropbtn btn-outline-secondary" data-toggle="dropdown" title="uniprot: {{ cavity.partner.chain.protein.uniprot_id }}"> {{ cavity.partner.chain.pdb_chain_id }} @@ -267,9 +279,8 @@ <a target="_blank" rel="noopener noreferrer" href="{% url 'cavities' %}?uniprotid={{ cavity.partner.chain.protein.uniprot_id }}">Query UniprotID in pockets</a> <a target="_blank" rel="noopener noreferrer" href="{% url 'compound_list' %}?uniprot_id={{ cavity.partner.chain.protein.uniprot_id }}">Query UniprotID as iPPI-DB target</a> </div> - </span> + </span>) {% endif %} - / {{ cavity.cavity_number }} </th> <td>{{ cavity.volume|floatformat:0 }}</td> <td>{{ cavity.npr1|floatformat:2 }}</td> @@ -306,15 +317,25 @@ / <span class="dropdown"> <button class="dropbtn btn-outline-secondary" data-toggle="dropdown" title="uniprot: {{ distance.cavity2.chain.protein.uniprot_id }}"> - {{ distance.cavity2.chain.pdb_chain_id }} / {{ distance.cavity2.chain.protein.short_name }} + {{ distance.cavity2.chain.pdb_chain_id }}<!-- / {{ distance.cavity2.chain.protein.short_name }} --> </button> <div class="dropdown-content"> <a target="_blank" rel="noopener noreferrer" href="{% url 'cavities' %}?uniprotid={{ distance.cavity2.chain.protein.uniprot_id }}">Query UniprotID in pockets</a> <a target="_blank" rel="noopener noreferrer" href="{% url 'compound_list' %}?uniprot_id={{ distance.cavity2.chain.protein.uniprot_id }}">Query UniprotID as iPPI-DB target</a> </div> </span> - {% if distance.cavity2.partner.ligand %} - / + / + <span class="dropdown"> + <button class="dropbtn btn-outline-secondary" data-toggle="dropdown"> + {{ distance.cavity2.cavity_number }} + </button> + <div class="dropdown-content"> + <a target="_blank" rel="noopener noreferrer" href="{% url 'networks' %}?search={{ distance.cavity2|build_name }}"> Query pocket in pocketome</a> + </div> + </span> + -- + {% if distance.cavity2.partner.ligand %} + (PL / <span class="dropdown"> <button class="dropbtn btn-outline-secondary" data-toggle="dropdown" title="smiles: {{ distance.cavity2.partner.ligand.canonical_smile }}"> {{ distance.cavity2.partner.ligand.pdb_ligand_id }}_{{ distance.cavity2.partner.ligand.supplementary_id }} @@ -323,9 +344,9 @@ <a target="_blank" rel="noopener noreferrer" href="{% url 'cavities' %}?ligandcode={{ distance.cavity2.partner.ligand.pdb_ligand_id }}">Query ligand ID in pockets</a> <a target="_blank" rel="noopener noreferrer" href="{% url 'compound_list' %}?similar_to=ECFP4:{{ distance.cavity2.partner.ligand.canonical_smile|urlencode }}">Query SMILES in iPPI-DB compounds</a> </div> - </span> + </span>) {% else %} - / + (HD / <span class="dropdown"> <button class="dropbtn btn-outline-secondary" data-toggle="dropdown" title="uniprot: {{ distance.cavity2.partner.chain.protein.uniprot_id }}"> {{ distance.cavity2.partner.chain.pdb_chain_id }} @@ -334,9 +355,8 @@ <a target="_blank" rel="noopener noreferrer" href="{% url 'cavities' %}?uniprotid={{ distance.cavity2.partner.chain.protein.uniprot_id }}">Query UniprotID in pockets</a> <a target="_blank" rel="noopener noreferrer" href="{% url 'compound_list' %}?uniprot_id={{ distance.cavity2.partner.chain.protein.uniprot_id }}">Query UniprotID as iPPI-DB target</a> </div> - </span> + </span>) {% endif %} - / {{ distance.cavity2.cavity_number }} </th> <td>{{ distance.cavity2.volume|floatformat:0 }}</td> <td>{{ distance.cavity2.npr1|floatformat:2 }}</td> @@ -371,26 +391,36 @@ / <span class="dropdown"> <button class="dropbtn btn-outline-secondary" data-toggle="dropdown" title="uniprot: {{ distance.cavity1.chain.protein.uniprot_id }}"> - {{ distance.cavity1.chain.pdb_chain_id }} / {{ distance.cavity1.chain.protein.short_name }} + {{ distance.cavity1.chain.pdb_chain_id }}<!-- / {{ distance.cavity1.chain.protein.short_name }} --> </button> <div class="dropdown-content"> <a target="_blank" rel="noopener noreferrer" href="{% url 'cavities' %}?uniprotid={{ distance.cavity1.chain.protein.uniprot_id }}">Query UniprotID in pockets</a> <a target="_blank" rel="noopener noreferrer" href="{% url 'cavities' %}?uniprot_id={{ distance.cavity1.chain.protein.uniprot_id }}">Query UniprotID as iPPI-DB target</a> </div> </span> - {% if distance.cavity1.partner.ligand %} / + <span class="dropdown"> + <button class="dropbtn btn-outline-secondary" data-toggle="dropdown"> + {{ distance.cavity1.cavity_number }} + </button> + <div class="dropdown-content"> + <a target="_blank" rel="noopener noreferrer" href="{% url 'networks' %}?search={{ distance.cavity1|build_name }}"> Query pocket in pocketome</a> + </div> + </span> + -- + {% if distance.cavity1.partner.ligand %} + (PL / <span class="dropdown"> <button class="dropbtn btn-outline-secondary" data-toggle="dropdown" title="smiles: {{ distance.cavity1.partner.ligand.canonical_smile }}"> - {{ distance.cavity1.partner.ligand.pdb_ligand_id }}_{{ distance.cavity1.partner.ligand.supplementary_id }} + {{ distance.cavity1.partner.ligand.pdb_ligand_id }}_{{ distance.cavity1.partner.ligand.supplementary_id }}) </button> <div class="dropdown-content"> <a target="_blank" rel="noopener noreferrer" href="{% url 'cavities' %}?ligandcode={{ distance.cavity1.partner.ligand.pdb_ligand_id }}">Query ligand ID in pockets</a> <a target="_blank" rel="noopener noreferrer" href="{% url 'compound_list' %}?similar_to=ECFP4:{{ distance.cavity1.partner.ligand.canonical_smile|urlencode }}">Query SMILES in iPPI-DB compounds</a> </div> - </span> + </span>) {% else %} - / + (HD / <span class="dropdown"> <button class="dropbtn btn-outline-secondary" data-toggle="dropdown" title="uniprot: {{ distance.cavity1.partner.chain.protein.uniprot_id }}"> {{ distance.cavity1.partner.chain.pdb_chain_id }} @@ -399,9 +429,8 @@ <a target="_blank" rel="noopener noreferrer" href="{% url 'cavities' %}?uniprotid={{ distance.cavity1.partner.chain.protein.uniprot_id }}">Query UniprotID in pockets</a> <a target="_blank" rel="noopener noreferrer" href="{% url 'compound_list' %}?uniprot_id={{ distance.cavity1.partner.chain.protein.uniprot_id }}">Query UniprotID as iPPI-DB target</a> </div> - </span> + </span>) {% endif %} - / {{ distance.cavity1.cavity_number }} </th> <td>{{ distance.cavity1.volume|floatformat:0 }}</td> <td>{{ distance.cavity1.npr1|floatformat:2 }}</td> diff --git a/ippisite/ippidb/templatetags/customtags.py b/ippisite/ippidb/templatetags/customtags.py index 17704056415b995f79b6c38606ffc87df961b9fd..24f4f97950ec98e8944679e3a61d144d46fe90a9 100644 --- a/ippisite/ippidb/templatetags/customtags.py +++ b/ippisite/ippidb/templatetags/customtags.py @@ -282,3 +282,32 @@ def get_color(ratio): def make_list(avg_std): step = 1 / 25 return np.arange(0, 1 + step, step) + + +@register.filter +def to_minus(value): + return value.replace("_", "-") + + +@register.filter +def build_name(cavity): + if cavity.partner.is_ligand: + return "{}-{}-{}-{}-{}-within{}_CAVITY_N{}".format( + cavity.chain.pdb.code, + cavity.chain.pdb_chain_id, + cavity.chain.protein.uniprot_id, + cavity.partner.ligand.pdb_ligand_id, + cavity.partner.ligand.supplementary_id, + cavity.chain.pdb_chain_id, + cavity.cavity_number, + ) + else: + return "{}-{}{}-{}-{}-within{}_CAVITY_N{}".format( + cavity.chain.pdb.code, + cavity.chain.pdb_chain_id, + cavity.partner.chain.pdb_chain_id, + cavity.chain.protein.uniprot_id, + cavity.partner.chain.protein.uniprot_id, + cavity.chain.pdb_chain_id, + cavity.cavity_number, + ) \ No newline at end of file