nglviewer/nglview

Change color when clicked

DA-L3 opened this issue · 1 comments

DA-L3 commented
  • Version report
nglview.__version__ = 3.0.3
ipywidgets.__version__ = 7.7.2

Hello,

I would like to customize my widget. I am displaying a protein structure in cif-format. I use the nv.show_biopython function in order to create the widget and display it in a jupyter notebook.
When I click onto one residue, the camera centers around this selection per default. What I now want to do is to color this selection while the other residues get white. In some sense, I want to highlight the selection.
Second, I would like to add lines to the component. Lets say, I have a list of atom indices ([2, 4, 10]) and the selection is the position 24. Then I would like to add lines dynamically from 24 to those indices 2, 4, and 10.
I know that there is the option to click onto a residue, then use view.picked to extract which position was clicked and then color, add shapes and then update the view. However, this would require to steps, first click, then execute an additional update cell --- meaning, the update does not happen immediately at the click event.

From what I can tell, nglview does not support such things out of the box, hence I need to use the _execute_js_code function in order to run JS code. Unfortunately, I don't know how to access access several components, execute function properly etc.

Here an example of code with the default display.

import io
import urllib
import nglview as nv 
from Bio.PDB import MMCIFParser
parser = MMCIFParser(QUIET=True)

resource = urllib.request.urlopen('https://files.rcsb.org/download/7YMR.cif')
content = resource.read().decode('utf8')
handle = io.StringIO(content)

structure = parser.get_structure("7YMR", handle)

view = nv.show_biopython(structure[0], default_representation=False)

view.add_cartoon("protein", color_scheme="chainindex")
view.center()
view

image

If I then click on one residue and execute this code additionally, I would like to get something like this

view.picked

list_of_indices = [83, 106, 108]

if "atom1" in view.picked:
    residue_index = view.picked['atom1']['resno']
    nv.color.ColormakerRegistry.add_selection_scheme(
        "picked", [["white", f"0-{residue_index-1}"], 
                   ['red', f"{residue_index}-{residue_index}"], 
                   ["white", f"{residue_index+1}-10000"]]
    )
    print(residue_index)
    view.clear()
    view.add_cartoon("protein", color_scheme="picked")
    
    for atom_index in list_of_indices:
        view.add_distance(atom_pair=[[f"{residue_index}.CA", f"{atom_index}.CA"]], label_color="black")
view

image

image

First, you can see that not only the residue I click onto was colored but also the residue position in the other chains got red as well (which is suboptimal). Second, here I have just added distances between the residue I clicked onto and the residues of my list (I would change it to other shapes).
However, this displaying does only happen after I picked the residue and then executed that additional cell, otherwise, the widget would not change.

I tried experimenting with this in the _execute_js_code, however, since I don't know how to access the components, etc, I am kinda stuck. Additionally the camera then behaves strangely when I clicked, so this automatic centering onto the selection does not work anymore.

this.stage.signals.clicked.add(function (pickingProxy) {
    if (pickingProxy && (pickingProxy.atom || pickingProxy.bond)){
        var atom = pickingProxy.atom || pickingProxy.closestBondAtom;
        var residue_index = atom.index;

Anyone having an idea how I can tackle this? I have already opened an issue in the ngl repo to ask for JS specifics, however, not sure if they can help me there since I am using the nglview binders.

Thanks a lot in advance!

hainm commented

Dear @CodyLDA,

I don't have a good answer for your question(s). Can you please try to read the Advanced NGLview usage in this link: https://projects.volkamerlab.org/teachopencadd/talktorials/T017_advanced_nglview_usage.html

Also read this source code in nglview: https://github.com/nglviewer/nglview/blob/master/js/src/widget_ngl.ts

Good luck.