nglviewer / ngl

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

Line representation including waters/metals (and pickable?) #354

Closed fredludlow closed 7 years ago

fredludlow commented 7 years ago

Apologies this is a bit of a "splurge thoughts into a text box" - I'm wondering what the best way to do this is:

I'd like to display a protein in line representation with waters and metals shown (metal-organic bonds might not always be defined - at the moment metals without bonds don't appear at all in line mode). The way pymol and others do this is to draw a cross (pymol draws 3 lines, parallel with the axes, intersecting at the point, AstexViewer draws a 2d cross in plane with the screen).

The Point representation with useTexture and sizeAttenuation true is nearly right, but its size is specified in screen units not Angstroms so the size is fixed as you zoom in and out, which isn't quite what I'm after.

I'd also like to be able to pick atoms from a line representation, which doesn't seem possible at the moment?

Maybe some kind of line+point representation, using a cross as the texture for isolated atoms with size specified in scene units? If the bonded atoms were also shown as 1-pixel point circular representations (in screen units) you'd be able to pick atoms too, which would be a bit of a bonus.

Alternatively, I might be massively over-complicating this and there's already a way to do this...

fredludlow commented 7 years ago

So I played around with it a bit more, and here's a handy workaround in case anyone else wants to display a line representation but also keep atoms pickable: You can add a point representation with the following params:

{sizeAttenusation: false,
 opacity: 0.0,
 pointSize: 15}

Then hovering/picking atoms works as it detects the (transparent) point representation.

Doesn't solve the displaying waters/metals in line representation, but that probably needs its own new representation type.

fredludlow commented 7 years ago

After a few weeks otherwise engaged I made a cross representation: http://fredludlow.com/ngldev/examples/webapp.html?script=representation/cross https://github.com/fredludlow/ngl/tree/cross-representation

This methods draws crosses a bit like pymol - aesthetically this isn't quite as nice as doing them in plane, but I think that would require a custom shader? (One that takes 4 vertices positioned at each atom and nudges them up/down/left/right in the screen plane?).

What I'm aiming for is a "line XOR cross" representation, i.e. every atom is depicted, if possible as the end of a line/bond, if not forming a bond to another displayed atom then as a cross. Actually, what I'm really aiming for is a "pickable line/cross" representation (possibly using a transparent point representation as outlined above?). I'm not sure how best to structure this, so here's what I've come up with, feedback on structure, naming and whether to include at all very welcome!

fredludlow commented 7 years ago

So I've made a 'line+cross' representation roughly as outlined above, which has most of the behaviour I'm after, but looking at it now there's a lot of scope for improvement in how it achieves that! Demo is here: http://fredludlow.com/ngldev/examples/webapp.html?script=representation/line-and-cross

If you load the demo and then type ".CA" or "sidechain" as the selection you can see how every atom is depicted (either with a line to it when there's a visible bond or a cross at it's location)

Code is in the same branch as before https://github.com/fredludlow/ngl/tree/cross-representation

The issues with this are mostly around [ab]using the PointBuffer to fudge pickable lines:

Anyway - to summarise, it sort of does what I want, but probably not in the way it ought to and I'm not quite sure what to do with it... Comments much appreciated!

arose commented 7 years ago

Nice, the demo looks good! Sorry for being so slow to answer.

I made a WideLineBuffer to be able to render wide pixel lines again as this is a feature that was/is dropped from browsers. I suggest to change the CrossRepresentation so it uses the WideLineBuffer, i.e. calculate the lines to form the crosses and pass to the WideLineBuffer. An extra CrossBuffer seems overkill. Same for the combined for the Line+Cross Representation. I think the CrossRepresentation can be part of the LineRepresentation with a flag to toggle it.

Also, the WideLineBuffer supports picking :)

fredludlow commented 7 years ago

Excellent - WideLineBuffer looks like a much better solution, and I'd been hoping that triangle/quad based lines would make an appearance (user-base here is Windows so linewidth with DirectX/Angle has never worked AFAIK) - so many thanks for that!

Agree separate representations/buffers for everything is overkill. With two parameters you could get all permuations of the behaviour within the single LineRepresentation type:

arose commented 7 years ago

How about just cross - true/false. You can get the rest by using selections, I think, unless, see below...

With isolated would you show crosses for atoms that are generally unbounded or for atoms that have no bonds in the current selection?

fredludlow commented 7 years ago

With isolated would you show crosses for atoms that are generally unbounded or for atoms that have > no bonds in the current selection?

The latter; my concern was to not miss out any atoms. A contrived example is line representation with 'sidechain' selection - Alanine sidechains don't appear because there are no intra-sidechain bonds. I used 'isolated' rather than 'nonbonded' so as to distinguish it from the selection language term, though I'm not sure it really makes it clearer...

The following branch does all the cross creation etc in the LineRepresentation class: https://github.com/fredludlow/ngl/tree/line-cross-repr Updated example here (you can type "sidechain" into the selection box and see how it behaves) http://fredludlow.com/ngldev/examples/webapp.html?script=representation/line-and-cross

It still uses two buffers (I couldn't work out a better way to handle both atom and bond picking)

A couple of other issues:

arose commented 7 years ago

Ok, I see the use case.

It still uses two buffers (I couldn't work out a better way to handle both atom and bond picking)

having multiple buffers is fine

That branch has crosses on by default, which would change behaviour for existing code, I guess they probably want to be off by default?

I think having crosses on for isolated atoms is a good default! The term isolated is fine I guess, got me on the right track :) Maybe lone?

I build a copy of the AtomPicker with each array value repeated three times (to cope with the fact that there are three rendered lines per atom) - maybe this would be more elegantly done with some kind of scale factor in the AtomPicker? (i.e. array[pid] becomes array[ 0 | (pid/scale)] ?

copying pickingArray values is fine

fredludlow commented 7 years ago

I think having crosses on for isolated atoms is a good default! The term isolated is fine I guess, got me on the right track :) Maybe lone?

lone works for me and is less typing! I'll make a PR...

fredludlow commented 7 years ago

Closing - thanks again for getting me from vague idea of what I want to something that works!