nglviewer / nglview

Jupyter widget to interactively view molecular structures and trajectories
http://nglviewer.org/nglview/latest/
Other
820 stars 134 forks source link

Usage questions about nglview: Please ask here first [2] #901

Closed hainm closed 3 years ago

hainm commented 4 years ago

For any questions relating to how/why/ ... Or anything you don't know where to ask. For bug, suggestion or anything you want to ask separately, please open seperate issue

PS:

dprada commented 4 years ago

Hi! Is there a way to work with the residue indices (0-th based), not the ids, in a selection? I have a homodimer, and thereby two set of residues in the input pdb with the same ids, and a list of scalar values to color all residues with a new '_ColorScheme'. Is there a way to play with the position index of the scalar value being equal to the residue index, in order to avoid the chain and residue ids?

Thanks in advance!!

hainm commented 4 years ago

hi @dprada, I don't know yet on top of my head. Let me think a bit.

mjw99 commented 4 years ago

Hello, thank you for all your work on this great tool.

I am trying to calculate and visualize a molecular electrostatic potential, on a specific electron density isosurface, kind of similar to this example with ngl (live example), but using PySCF and nglview, within a Jupyter notebook:

from pyscf import gto
from pyscf import dft
from pyscf.geomopt import berny_solver
from pyscf import __config__
from pyscf.tools import cubegen

import nglview as nv

# Default of 3.0 is too small for 6-31G*
setattr(__config__, 'cubegen_box_margin', 4.0)

h2o = gto.M(atom='      O 0.00000000,  0.000000,  0.119748;\
                        H 0.00000000,  0.761561, -0.478993;\
                        H 0.00000000, -0.761561, -0.478993',\
                        basis='6-31G*')

h2o.build()
h2o.verbose = 0

method = dft.RKS(h2o)
method.grids.prune = dft.gen_grid.treutler_prune
method.grids.atom_grid = {"H": (50, 194), "O": (50, 194)}
method.xc = 'b3lypg'
method.scf()

opt_mol = berny_solver.optimize(method)

cubegen.density(opt_mol, 'water_den.cube', method.make_rdm1(), resolution=(1/6))
cubegen.mep(opt_mol, 'water_pot.cube', method.make_rdm1(), resolution=(1/6))

view = nv.NGLWidget()

view.add_component('water_den.cube', color="red")
view.component_0.add_surface(isolevelType="value", isolevel=0.002)

view.add_component('water_pot.cube')
view.component_1.add_surface(color='red')

view

I think I am close to getting this to work, but I am not sure how to use data from the two components together.

dprada commented 4 years ago

Dont' worry @hainm, it is something that can be done combining the chain and residues ids. I was wondering if there was a simpler way. But many thanks for your kind reply (as always).

hainm commented 4 years ago

I am trying to calculate and visualize a molecular electrostatic potential, on a specific electron density isosurface, kind of similar to this example with ngl (live example), but using PySCF and nglview, within a Jupyter notebook:

hi @mjw99 Is this what you're looking for? https://github.com/arose/nglview/pull/804

mjw99 commented 4 years ago

Dear Hai, Thank you for the example; with a slightly modified form, and the example data files I can get your example to work:

import nglview as nv

v = nv.NGLWidget()

c0 = v.add_component('esp.mol')
c1 = v.add_component('esp.dx')

c1.clear()

c0.add_surface(
    color_scheme='volume',
      color_volume=c1,      
      colorScale='rwb',
      colorDomain=[ -0.05, 0.05 ],             
      opacity=0.5
)

v

However, with my initial example, a similar approach is still not working:

view = nv.NGLWidget()

c0 = view.add_component('water_den.cube')
c1 = view.add_component('water_pot.cube')
c0.clear()

c0.add_surface(color_scheme='volume', 
      color_volume=c1,
      colorScale='rwb',
      colorDomain=[ -0.05, 0.05 ],      
      opacity=0.5
)

view

Screenshot from 2020-06-12 11-44-59

As a side point, if I load these same CUBE files into VMD (using a protocol similar to the VMD section here ), they do display fine. Any ideas?

jessevig commented 4 years ago

Thank you for the great tool. Is it possible to set opacity to residues at specific indices or a range of indices? I'm using the cartoon representation. Thanks!

hainm commented 4 years ago

As a side point, if I load these same CUBE files into VMD (using a protocol similar to the VMD section here ), they do display fine. Any ideas?

@mjw99 Can you please try NGL live example first by using your files?

hainm commented 4 years ago

Thank you for the great tool. Is it possible to set opacity to residues at specific indices or a range of indices? I'm using the cartoon representation. Thanks!

hi @jessevig, may be use multiple cartoon representations. Saying you have 5 residues and want to set opacity for some of them.

view.add_cartoon("1,2,5")
view.add_cartoon("3,4", opacity=0.5)
hainm commented 4 years ago

@arose Does NGL support setting opacity for some residues in ONE representation? thanks.

jessevig commented 4 years ago

Is there a simple example for animating a protein structure to rotate? I found this but wasn't sure how to invoke it from the jupyter notebook: https://github.com/arose/ngl/blob/master/src/controls/animation-controls.ts Thanks much!

hainm commented 4 years ago

@jessevig may be use view.control.spin https://github.com/arose/nglview/blob/master/nglview/viewer_control.py#L86

jessevig commented 4 years ago

I thought I tried that one before, but it didn't show an animation associated with spinning, it just changed the viewing angle. Is it supposed to show the animation? Thanks.

hainm commented 4 years ago

@jessevig I see. Please use view._set_spin for now. I thought two methods are the same. :D

jessevig commented 4 years ago

Thanks. Do you know if it's possible to display text sideways, i.e. rotated 90 degrees?

hainm commented 4 years ago

rotated 90 degrees?

I am not sure. May be playing with NGL itself to check. I see your open issue in that repo.

mrjoness commented 4 years ago

Hello,

I've been trying to use ngl to visualize DNA oligos from a .lammpstrj trajectory file and .psf topology. I am able to load the data without any error, but when I visualize a frame I am not able to recover the bonding information contained in the psf file. I believe that some bonds are forming based off proximity (they look like random triangles) but these are not reflective of what I see in vmd for example. Here is the code I am using and the corresponding visualization:

`frame = md.load_frame('../GC-core_321K_vis.lammpstrj', 0, top='../GC-core-ions.psf')

view = nv.show_mdtraj(frame) view.clear_representations()

strand_len = 29 view.add_representation('licorice', selection=[i for i in range(strand_len)], color='red') view.add_representation('licorice', selection=[i+strand_len for i in range(strand_len)], color='blue')

view`

Capture
hainm commented 4 years ago

hi @mrjoness, nglview uses mdtraj's save_pdb method to save the topology to pdb format.

frame[0].save_pdb("test.pdb")

Load test.pdb to VMD, do you still see the bond correctly?

mrjoness commented 4 years ago

When I use test.pdb in vmd I don't see the correct bonds either... I guess there's a problem with the mdtraj method (or my psf file) and not necessarily nglviewer? Is there anything you recommend to fix this?

hainm commented 4 years ago

@mrjoness Either:

luponzo86 commented 4 years ago

Hi, I am trying to draw a distance representation between two components, but it is not clear to me how to select an atom pair between the two components: What is the correct syntax? I tried using the "model" syntax, e.g. ('@1/0', '@99/1'), but it does not work:

view = nv.NGLWidget()

# add components to view
c0 = view.add_component(mol0)
c1 = view.add_component(mol1)

view.add_representation(
    'distance', 
    atomPair=[('@333/0', '@444/1')],  # <- dist, between atom 333 in model (component?) 0 and atom 444 in model 1. Does not work
)

[EDIT] More in general, what is the syntax for selecting a component and its atoms? I have a small molecule loaded as a separate component and I cannot understand how to find out the identifiers assigned to its atoms

hainm commented 4 years ago

hi @luponzo86, I don't think nglview (NGL under the hood) support distance between two components.

cc @arose

luponzo86 commented 4 years ago

Thanks, @hainm

I then tried to combine the two molecules together with OpenBabel:

mol1 += mol2  # both are OBMol objects
comp = view.add_component(nv.OpenbabelStructure(mol1))

and it works, but then I don't know how to tell the two molecules apart during selection. Is there a way to figure out the identifiers of the two molecules? Is there something like comp.getData() that could help understand how the atoms/chains are named?

Thanks!

hainm commented 4 years ago

@luponzo86

Is there something like comp.getData() that could help understand how the atoms/chains are named?

Can you try nv.OpenbabelStructure(mol1).get_structure_string()?

luponzo86 commented 4 years ago

@hainm

Can you try nv.OpenbabelStructure(mol1).get_structure_string()?

Thanks a lot, very useful!

I was finally able to combine the two molecules (mol1 and mol2) together and draw the distance between two atoms that were originally in the two separate molecules. The only thing to be careful about is to remap the atom indices of the second molecule, since after appending it to the first one its indices are shifted by len(mol1)

hainm commented 4 years ago

@luponzo86 fantastic.

markperri commented 4 years ago

Is there a way to display a view from inside a function in a Jupyter Notebook:

cell 1:

import nglview as nv
import pytraj as pt
import numpy as np

def loadTrajectory(job):
    traj = pt.load(f'{job}.dcd', top=f'{job}.psf')
    print(set(residue.name for residue in traj.top.residues))
    view1 = nv.show_pytraj(traj)
    view1

cell 2: loadTrajectory(182076)

output: {'TIP3'}

The trajectory isn't displayed, but it works fine when I don't use a function. Is there a view1.show() type function I should use instead?

hainm commented 4 years ago

hi @markperri, just return view1 or

from IPython.display import display
display(view1)
markperri commented 4 years ago

@hainm thanks!

JIMonroe commented 4 years ago

Hi all! I'm looking for a way to grab static images generated by nglview and display them however I like (for instance, as subplots with pyplot). The natural way seems to be to grab the _image_data attribute of the NGLWidget object, but of course this returns empty byte strings until you run view.display() and view.render_image() in separate cells. I would really prefer not to have to do this, as I want to generate and compare a lot of configurations side-by-side. In other words, I only want to pull out the image rendering functionality. Is there a good way to do this with nglview, or should I be looking at a different tool? Thanks!

hainm commented 4 years ago

Hi all! I'm looking for a way to grab static images generated by nglview and display them however I like (for instance, as subplots with pyplot). The natural way seems to be to grab the _image_data attribute of the NGLWidget object, but of course this returns empty byte strings until you run view.display() and view.render_image() in separate cells. I would really prefer not to have to do this, as I want to generate and compare a lot of configurations side-by-side. In other words, I only want to pull out the image rendering functionality. Is there a good way to do this with nglview, or should I be looking at a different tool? Thanks!

hi @JIMonroe: you can not avoid displaying view and calling render_image. But you can save the data and process it later.

Please see this example. You can grab the raw value from im0.value.

Screen Shot 2020-09-23 at 3 21 42 PM
JIMonroe commented 4 years ago

Should work for me, thank you!

khoroshyy commented 4 years ago

HI everybody. Can I run nglview without Jupiter in the interactive python session, similar to matplotlib figures? Thanks. Petro.

hainm commented 4 years ago

@khoroshyy No you can not. nglview requires web browser.

rbf22 commented 4 years ago

I could not find a way to change the view to orthoscopic, is there a way to do this? I have checked the wiki, and searched the documentation.

rbf22 commented 4 years ago

I could not find a way to change the view to orthoscopic, is there a way to do this? I have checked the wiki, and searched the documentation.

update camera type

view.camera = 'orthographic'

stnrl commented 3 years ago

Hi everybody, I was wondering if it is possible to keep the interactive image of the nglview (or at least the picture of the view) when the ipynb file is exported to html (or pdf). For example, I have this output in the notebook, the viewer of a protein:

image

But once I export the file to html, there is no output: image

is it possible to keep the output image (interactive or not) after the file conversion?

Thanks!

hainm commented 3 years ago

is it possible to keep the output image (interactive or not) after the file conversion?

hi @s73v3nR, it's tricky to do that with nglview. But you can do something similar:

hainm commented 3 years ago

@s73v3nR Another approach: https://github.com/nglviewer/nglview/issues/869

djmaity commented 3 years ago
  1. Is there a way to automatically start a trajectory animation in loop when executing the cell with the code for displaying a PDB file with multiple models in the latest version of nglview in Jupyter notebook?

  2. How can I deselect a picked atom using left click?

rbf22 commented 3 years ago

How can the color of a selection of residues be changed. Is there some way to do this efficiently?

hainm commented 3 years ago
  1. Is there a way to automatically start a trajectory animation in loop when executing the cell with the code for displaying a PDB file with multiple models in the latest version of nglview in Jupyter notebook?

hi @djmaity: sorry for my late reply

You can try this:

import nglview as nv
import pytraj as pt
import time

traj = pt.datafiles.load_tz2()
view = nv.show_pytraj(traj)

def on_displayed(view): 
    def func():
        time.sleep(0.1)
        for frame in range(view.max_frame+1):
            view.frame = frame
            time.sleep(0.1)
    view._run_on_another_thread(func)

view.on_displayed(on_displayed)
view
  1. How can I deselect a picked atom using left click?

You can not.

hainm commented 3 years ago

How can the color of a selection of residues be changed. Is there some way to do this efficiently?

hi @rbf22 I guess you can use view.update_representation(...).

Screen Shot 2020-11-17 at 8 43 17 PM
zacharyrs commented 3 years ago

Hey - I'm having a little difficulty with the GUI (#830).

Using the exact code in the PR gives me a blank GUI on first run, but then succeeds on the second. Peek 2020-12-17 15-23

Console doesn't show any errors. I've indicated 1 and 2 for the 1st and 2nd cell runs. Screenshot from 2020-12-17 15-27-24

hainm commented 3 years ago

hi @zacharyrs: yeah, it happens sometimes and I don't know how to fix. You can try to put the view.gui_style = 'ngl' in 2nd cell.

Keeping track the issue in #939

gmacari commented 3 years ago

Hi guys, I would like to use nglview to draw a box around a protein specifying the box center and the side size. Do you have any advice?

hainm commented 3 years ago

hi @gmacari: sorry for the delay. There is no direct way to do that, however, you can use view.shape.add_cylinder to create the lines: https://github.com/hainm/nglview/blob/1edd80dde2f45bcc72e498a4d3603a5b57542610/nglview/shape.py#L24

jochym commented 3 years ago

I have a problem with the size of the ngl view in the embedded viewer. The _remote_call trick works fine in the notebook but when I save widget to html it always comes in default height. Seems to adopt the width of the surrounding div but not the height. The only way to resize the view is resizing by hand. Is there any example how we can do the equivalent of _remote_call inside the html with embedded widget? I am not an expert in JS - thus it is not easy find the correct object to call the setSize method on. Some minimal example would be great but any lead will help.

hainm commented 3 years ago

@jochym I don't know for now, let me think a bit.

hainm commented 3 years ago

@jochym The best way currently is to wrap the view in an ipywidgets's Box (or GridBox): https://ipywidgets.readthedocs.io/en/stable/examples/Widget%20Styling.html

Screen Shot 2021-02-02 at 12 10 10 PM