nglviewer / ngl

WebGL protein viewer
http://nglviewer.org/ngl/
MIT License
664 stars 169 forks source link

How to draw a line connecting two residues? #928

Closed samuelflores closed 1 year ago

samuelflores commented 2 years ago

Is there some trick that would enable me to draw a line between two nucleic acid residues, or for that matter two atoms ? Let's say I know the chain IDs, residue numbers, and atoms names, but not the atom indices. So I can't get the coordinates directly.

I am thinking maybe a Representation could be hacked for this purpose. How is the covalent bond network determined? Is it based only on distance, or does it come from the CONECT records? How about if I create a selection with just the two atoms, and then use e.g. Licorice rendering, and greatly increase the minimum covalent bond length, or in some other way specify that they are connected? Then the two atoms would appear to be bonded, and I would get the line I want. If that would work, kindly tell me how to do it.

fredludlow commented 2 years ago

Hi @samuelflores, does the solution in #924 help?

samuelflores commented 2 years ago

No, because I would have to know the coordinates. What I know are chain IDs and residue numbers. And atom names of course.

fredludlow commented 2 years ago

Covalent bonds are generated when the file is parsed, I don't think that's going to be an easy way to do it.

The reason I pointed at 924 was the example I'd posted there, copied here: you can go from chain, resno and atom name to selection, and the center of that selection is a coordinate (see how start and end variables are set) then build an arrow (or cylinder or whatever) using them.

stage.loadFile( "rcsb://1crn", { defaultRepresentation: true }).then(function (o) {
  stage.autoView()

  const start = o.structure.getView(new NGL.Selection("22:A.CA")).center
  const end = o.structure.getView(new NGL.Selection("33:A.CA")).center

  const shape = new NGL.Shape("shape")
  shape.addArrow(start, end, [1,0,0], 0.2)  // Or shape.addCylinder(start, end, color, radius)

  var shapeComp = stage.addComponentFromObject( shape );
  shapeComp.addRepresentation( "buffer" );
});
samuelflores commented 2 years ago

Oh this sounds like exactly what I want! However you seem to be using javascript or some such. How would I do this in python? I could find no documentation to help with that.

import nglview view = nglview.NGLWidget() view.clear_representations() pdbId = "1gid" view.add_pdbid(pdbId) for index, row in basePairingDataFrame.iterrows(): atom1String = str(row['nr1']) + "C1'" # here I am just creating an atom selection using residue number and atom name atom2String = str(row['nr2']) + "C1'" view.add_distance(atom_pair=[[atom1String, atom2String]], label_color="black", labelType = "text", labelText = "my text", color = "blue")

fredludlow commented 2 years ago

Ah, sorry, I see we were talking at cross purposes. @hainm: Given the JS recipe above is it possible to execute something like that through nglview?

Also, if you want to show base pairing the base representation type is available, e.g. https://codepen.io/fludlow/pen/bGLwJJM?editors=001&layout=left

hainm commented 2 years ago

Ah, sorry, I see we were talking at cross purposes. @hainm: Given the JS recipe above is it possible to execute something like that through nglview?

ah yeah, user can use view._execute_js_code (or just view._js): e.g: https://projects.volkamerlab.org/teachopencadd/talktorials/T017_advanced_nglview_usage.html