Opened 8 years ago

Last modified 8 years ago

#822 assigned enhancement

Improved drawing of symmetry equivalents

Reported by: Tristan Croll Owned by: Tom Goddard
Priority: minor Milestone:
Component: Depiction Version:
Keywords: Cc:
Blocked By: Blocking:
Notify when closed: Platform: all
Project: ChimeraX

Description

At present in the Clipper plugin I handle crystallographic symmetry by creating and caching a new AtomicStructure every time a new symmetry equivalent molecule is found in the vicinity of the current viewing region. This works, but it's clunky and not a good long-term solution. For one thing, for larger structures there's an annoying pause of up to a few seconds each time a new molecule is created (which admittedly could be reduced with some more clever re-use of cached copies). For another, things will get complicated/ugly when structure editing comes in to play. Not just for adding/removing atoms - a bunch of callbacks will be needed for every action that affects appearance. More philosophically, the whole point of crystallography is that all the symmetry equivalents are effectively identical, so it makes much more sense for them to be graphical ghosts of the main molecule.

What I would like to suggest is a small enabling amendment to Structure.update_graphics(), to add as optional arguments a specific list of atoms to restrict this pass to, a target drawing (which would be added as a child to self._drawing), and a color multiplier. I'm already using find_close_points_sets() in Clipper, so with this amendment I could subclass AtomicStructure to have update_graphics_if_needed() loop over update_graphics(), creating one Drawing for each symmetry operator. The color multiplier (actually, probably better as a gamma term unless it's restricted to the range 0:1) would allow me to differentiate the symmetry equivalents from the main molecule without affecting the stored colors.

Change History (22)

in reply to:  1 ; comment:1 by goddard@…, 8 years ago

Sounds like you want to be able to create a Drawing for part of a symmetry copy of an atomic structure.  Could be done, maybe for atom and bond depictions but probably not ribbons. There is a similar capability using the Drawing.positions to specify multiple instances.  Your request differs in that you could show only some of the atoms in your copy, and you could change the colors of the atoms in your copy.  But a rather huge drawback is mouse over won’t tell you the name of atoms in your Drawing copy, and you won’t be able to select them.  Also any commands that effect the original “real” molecule won’t effect your copies (maybe a feature).  But basically you have a “dead” molecule copy — just a graphical object where you can’t even identify the residue names.  That doesn’t sound too useful.  The user will see some live atoms from the original copy and some dead ones from copies — of course they want all of them to be live.  Maybe that can be achieved using the current instancing with some enhancement to modulate colors (as you already are requesting), plus maybe graphical clipping to only show the atoms within some radius of the center (as is done for meshes)?

in reply to:  2 ; comment:2 by tic20@…, 8 years ago

What I had in mind would be redrawn on any changes just as it is now, so the copies would be "live" in that sense - but you're right, I hadn't considered picking/mouseover. Hmm.

 
 
Tristan Croll
Research Fellow
Cambridge Institute for Medical Research
University of Cambridge CB2 0XY
 

 

comment:3 by Tristan Croll, 8 years ago

Hover/single-atom picking looks like it could be handled quite straightforwardly with a simple override of first_intercept() in the subclass. planes_pick() looks somewhat more tricky. I might have a play with it and see how far I get - if I can get it to work well the payoff would be worth the effort.

in reply to:  4 ; comment:4 by goddard@…, 8 years ago

I don’t understand why you want complex new mechanisms instead of using the existing instancing capability.  I’m sure there are reasons but I’d have to know them to evaluate things.

in reply to:  5 ; comment:5 by tic20@…, 8 years ago

Well, I was hoping it wouldn't be *too* complex - but I can see it would be more involved than I'd hoped.

Why do it this way? I suppose it could be done with instancing and clipping planes as you say: display all the relevant atoms wherever they are, apply all the relevant positions to the master drawing then use eight clipping planes to cut the result down to a cube around the region of interest. But clipping planes are slow, they'd have to be limited to only this structure, and I lose the ability to differentiate the symmetry copies from the master.

Why not continue to use separate molecules for the symmetry copies as I'm doing now? Because while it works fine for a static molecule that I'm not manipulating in any way other than navigating around it, the complexity grows enormously once other manipulations come into play. I'd need callbacks for every single possible manipulation to the master to propagate the changes to the children, and I'd have to suppress a lot of global-level actions (color, atom show/hide, etc.) from acting on the children since they should be dictated by the state of the master. Would lead to a horrible mess.

Why do it at all? Because those symmetry contacts are important, and are often handled poorly (or not at all) in model building because they're currently difficult to work with. I want to get it right, and make working with symmetry contacts feel as natural as working with any other part of the structure.

 
 
Tristan Croll
Research Fellow
Cambridge Institute for Medical Research
University of Cambridge CB2 0XY
 

 

in reply to:  6 ; comment:6 by goddard@…, 8 years ago

That all makes sense except the critique of instancing.  First I would not expect clip planes to be slow.  It is certainly faster than displaying full symmetry copies.  It does not have to be 8 clip planes, the GPU shader can simply hide everything outside some radius, or use any rules it wants for what not to display.  That the clipping has to be limited to one model is not difficult, although it is not in ChimeraX yet, Elaine has been asking for this for the last 6 months.  Making colors of different instances different is again not hard, as easy as for the separate Drawing approach that you want where some special capability needs to allow modulating all colors of a model.  So my view is that your original proposal is a hard and complex way to do what can be done with enhancements to instancing.  So enhancements to instancing are a better direction I think.

We are fighting with a problem that ChimeraX is too complex given the limited number of programmers developing it.  From our UCSF perspective we need to keep it as simple as possible.  But from your perspective a better course would be to specialize it to your needs, which makes it more complex in ways that help you but that hurt other applications of the program don't need these special features.  


in reply to:  7 ; comment:7 by tic20@…, 8 years ago

Trust me - I'm very thankful for the simplicity of the ChimeraX API design, and I'm doing my best to learn from it! Compared to certain other packages I've had to work with, it's a dream. I also try to do as much as I can with subclasses to keep added complexity contained within my own plugins, but some things just become impractical that way.

OK, if you say instancing/clipping is the way to go, I'll take your word for it. I hope I'm not being too painful if I ask if the clipping could be implemented at the Drawing level? What I find works well with the Clipper plugin is having atom/bond display restricted to a sphere around the focal point, but the full ribbon shown for all symmetry copies that project into the sphere. Keeps everything in context without being overpowering.

 
 
Tristan Croll
Research Fellow
Cambridge Institute for Medical Research
University of Cambridge CB2 0XY
 

 

in reply to:  8 ; comment:8 by goddard@…, 8 years ago

Yeah, radial clip could be done at the Drawing level.  It will be implemented at that level since it will be an OpenGL shader capabilities and the shader capabilities used are specified by each drawing.

comment:9 by Tristan Croll, 8 years ago

I found some time to play around with this, and came up with a fairly straightforward approach that I think I'm happy with. I wrote a little C++ module for the Clipper plugin that takes an Atoms array, a set of symmetry operators, a centre coordinate and a cutoff radius, and returns a tuple containing:

  • pointers to all atoms found within the search radius (including symmetry copies)
  • a matched array of coordinates for the atoms (after applying the symmetry transforms)
  • an array of indices giving which symmetry group each atom belongs to
  • pointers to all bonds between atoms in the symmetry groups
  • matching halfbond cylinder transforms
  • an array of symmetry indices matching the bonds

So, just about everything necessary for the drawing (just need to convert the atom positions to xyzr and add colours), and all the information necessary to implement symmetry-aware picking. The full loop (getting the set of symmetry operators mapping to the desired volume from Clipper through to returning the tuple) takes about 5.5ms for a 20 Angstrom radius on my test case (5f4y).

in reply to:  10 ; comment:10 by goddard@…, 8 years ago

I understand what your routine does but I don’t understand what you intend to do to draw that and integrate together with ChimeraX atomic structure capabilities.

in reply to:  11 ; comment:11 by tic20@…, 8 years ago

Well, there are two ways that could be done:

1. I subclass AtomicStructure and replace _update_atoms_drawing, _update_bonds_drawing and the picking methods with symmetry-aware equivalents. Possible, but probably a bit fragile.

2. If I make sure to exclude the identity matrix from consideration then I get *just* the symmetry atoms, so I can more straightforwardly make my own class to draw them and handle picking/updating.

The core point is to provide a greatly improved version of the “scrolling sphere” style of navigation through a model/map combination. It’s more-or-less an industry standard for getting around high-resolution maps - particularly for crystallography, but also for EM maps with strict symmetry. Done properly, it’ll allow the user to work on, say, an icosahedral viral capsid or helical reconstruction while only having to manipulate a single asymmetric unit. My existing implementation (making real copies of the main molecule) is unworkably clunky for further development. This approach (with a little more work) should give me symmetry atoms that behave like they should - updating live, selectable, providing their symmetry info in the mouse over text, etc. - while still being just graphical instances of the real atoms underneath.

 
 
Tristan Croll
Research Fellow
Cambridge Institute for Medical Research
University of Cambridge CB2 0XY
 

 


comment:12 by Tristan Croll, 8 years ago

I've put up a plugin source tarball at
https://drive.google.com/open?id=0B6uMjfjuw4k8TFg2aVJKWmpCZDA which should demonstrate what I'm getting at. You should be able to run make app-install on any Linux or Mac machine, then in ChimeraX do:

from chimerax.clipper.tests import test_sym
sym_handler = test_sym.test_clipper_sym(session, radius=50)

... then wander around by dragging with the middle mouse button. I'm really happy with how responsive it is (note: the radius of 50 Angstroms is much bigger than what one would typically use - 15-20A is more normal). Hovering over any atom will give you its symmetry operator. I did implement picking (that is, picking a symmetry copy would pick the original atom), but eventually decided that was counterproductive and turned it off. It *would* be nice to have selected atoms highlight in the symmetry drawing, but I haven't worked out how to do that yet.

comment:13 by Tristan Croll, 8 years ago

Working nicely now - see https://drive.google.com/open?id=1AoN6nk4W9KSKzSFh5_39ST6qqSKVDR7i for a quick video demonstration. It's in what I think I'll call "searchlight mode" - maps masked to within a given radius around the cofr, and atoms masked to a slightly larger radius. It's using the HIDE_ISOLDE bit on the main model to suppress showing of atoms outside the sphere, so it plays nicely with all the standard ChimeraX controls. The symmetry copies are mostly non-interactive "ghosts", except that mouse-hover over a symmetry atom adds the symmetry information to the tooltip.

Right now it's set up to work with the Clipper engine (getting the short-list of local crystallographic symmetry operators and providing the infinitely-scrolling maps), but it would be good to add support for EM structures as well. Working with real-space maps should be fairly straightforward, but as far as I'm aware the treatment of symmetry in EM models (in particular, those with helical or 2D crystallographic symmetry) has yet to be handled really neatly by anyone.

in reply to:  14 ; comment:14 by goddard@…, 8 years ago

That looks nice.  Do you need support for the ghost symmetric molecules in the ChimeraX core, or is it intended to stay in ISOLDE?  Sorry, I have not looked at your ghost implementation yet.

I understand the ghost molecules are to achieve fast rendering.  I am a bit concerned that it means I cannot for instance move to a region of interest and display a distance (pseudobond plus number) between two atoms because one or both of the atoms are part of a ghost.  If speed were not an issue it seems like every symmetry copy being a real molecule would be best.  Ghosts atoms will prevent almost every ChimeraX capability that involves the spatial position of atoms from working -- it is a big sacrifice made for speed.  You may think the cases where real atoms are needed are infrequent, as long as you stay in the ISOLDE world.  But a major strength of ChimeraX is that it works for use cases you did not envision.  So optimizations that prevent the interoperation of diverse ChimeraX tools are unfortunate.


in reply to:  15 ; comment:15 by tic20@…, 8 years ago

Fair point - but it wouldn’t be particularly difficult to “promote” a ghost copy to a bona fide molecule where necessary. Ultimately I plan to do that where I need to simulate a symmetry interface, for example. I could straightforwardly add a method akin to Chimera’s crystal contacts tool. Alternatively, I could give the symmetry coordinates to the PickedSymAtom object (a subclass of PickedAtom), if that could be made to work.

The problems with using multiple real copies really start to blow out when you think about coordinate and display changes, etc. Each copy has to completely redraw itself, which becomes really painful for large models particularly with the cartoon on, and enforcing a colour scheme to differentiate symmetry copies from the central model becomes somewhat frustrating.

I don’t feel I *need* to add it to the core, but I wouldn’t be against it either. It won’t yet work for Windows since I still haven’t gotten around to a Windows build of Clipper-Python (only because I have no experience building for Windows - it’s not particularly challenging to build for Linux and Mac). But on that note, the PHENIX people have put together a “minimal” cctbx build - it might now make sense for me to look into using that instead for crystallographic functions...

 
 
Tristan Croll
Research Fellow
Cambridge Institute for Medical Research
University of Cambridge CB2 0XY
 

 


in reply to:  16 ; comment:16 by tic20@…, 8 years ago

Just playing with ideas - and not something I'd be thinking of 
attempting within at least the next few months, but I wonder if 
something along the lines of the below mock-up might have merit? The 
general idea would be to have a read-only subclass of Atom (so it can 
participate in Bond/Pseudobonds etc.) that mostly just passes through 
the properties of its "master", but returns the symmetry coordinates.


class SymAtom: public Atom
{
public:
     SymAtom(Atom* master, double* symop) : _master_atom(master)
     {
         for (size_t i=0; i<12; ++i)
             _symop[i] = symop[i];
     }

     // Pass most getter functions through to _master atom, remove setter 
functions

     const Coord& coord()
     {
         transform_coord(_symop, _coord);
         return _coord;
     }

private:
     Atom* _master_atom;
     double _symop[12];


};

On 2018-03-01 18:20, ChimeraX wrote:

in reply to:  17 ; comment:17 by goddard@…, 8 years ago

I know I harp on this a lot, but here it goes.  All of the performance issues you mention when using real molecules for symmetry copies just reflect a lack of optimization in the real molecule code.

"The problems with using multiple real copies really start to blow out when
you think about coordinate and display changes, etc. Each copy has to
completely redraw itself, which becomes really painful for large models
particularly with the cartoon on, and enforcing a colour scheme to
differentiate symmetry copies from the central model becomes somewhat
frustrating."

Trying to solve that by adding a new and complex and possibly limited scheme of ghost molecules seems like a poor long-term direction.  We don't have the resources to make that work well.  I think a better direction is to optimize real molecules which will benefit all users even when symmetry is not important.  None of the issues you mention should be slower than with ghosts.  The cartoon one is perhaps the trickiest - because you want to take the ribbon computed for one copy and be able to reuse it in other real copies.  Even computing a single copy ribbon is excruciatingly slow in ChimeraX which I think would make it unusable with your interactive MD -- so that is an independent optimization problem.  There are problems you did not mention like creating a real copy in the first place takes time and memory -- again things that should be optimized.  The advantage of optimizations are that they create no extra API complexity and interoperability limitations.

in reply to:  18 ; comment:18 by tic20@…, 8 years ago

I guess my response to that is that with the Clipper engine to find the 
necessary symmetry operators, making real symmetry copies of the 
structure is trivially easy - so when the necessary optimisations are 
done I'm happy to change. I'm taking extra care to make everything 
modular to make that easy - like all my other recent additions to 
ISOLDE, the symmetry handler is a self-contained Model subclass. Add it 
to a structure and you get the live symmetry view (with or without 
maps); close the model and it goes away. Easy to swap in for a different 
implementation later. For that matter, it would be rather easy to modify 
it to allow a choice between this fast-but-limited mode and a 
"real-model" mode. For now, it gives me a sufficiently-fast 
implementation of some functionality I really need sooner rather than 
later.

On 2018-03-02 17:46, ChimeraX wrote:

in reply to:  19 ; comment:19 by goddard@…, 8 years ago

Hi Tristan,

  You are right I was not thinking clearly about your case of building the models where they are constantly changing and your symmetry copies should all be identical.  I know the ChimeraX instancing was inadequate because it did not allow for different colors and display styles.  I’ll let you know if I have any other brilliant ideas!  But ghosts look like they have more life in them than I realized.

  Tom


comment:20 by Tristan Croll, 8 years ago

This should give a clearer idea of what I'm driving at: https://drive.google.com/open?id=1d9QLlc6HcWFGfnbzcFQXW1ztVRNoodjt. It's a short demo video of a live simulation running with the live symmetry view on. OK, the simulated atoms don't feel their symmetry copies (that's a much, much harder problem for a later date), but now all changes are immediately visible in their symmetry context without any need for a complex set of callbacks to keep strict symmetry enforced on multiple separate models.

in reply to:  21 ; comment:21 by goddard@…, 8 years ago

That’s cool.  What you have made is some instanced rendering that allows each instance to separately control which atoms are shown, and what their colors are (although in your video from the previous message the colors are the same, I think you sent me another video where the colors were different for the symmetry copies).


in reply to:  22 ; comment:22 by tic20@…, 8 years ago

At the moment the RGB values of a symmetry atom are just those of the 
parent atom multiplied by a dimming constant. Of course that could be 
made fancier with a little bit of work.

In the symmetry model, instancing is at the atom/bond level - there's 
just one Drawing for each, and all the atom positions and bond 
transforms are fetched in a single call. Ribbon (when present) is just a 
copy of the master ribbon Drawing tree, re-coloured and instanced for 
all symmetry operators that appear at least once in the found symmetry 
atoms. If the display is just cartoons (no atoms shown), it instead uses 
the coordinates of the ribbon tethers to decide which symmetry copies to 
show.

On 2018-03-12 17:43, ChimeraX wrote:
Note: See TracTickets for help on using tickets.