Opened 8 years ago

Closed 8 years ago

#789 closed enhancement (fixed)

Optimize atom radius lookup

Reported by: Tom Goddard Owned by: pett
Priority: minor Milestone:
Component: Core Version:
Keywords: Cc: tic20@…
Blocked By: Blocking:
Notify when closed: Platform: all
Project: ChimeraX

Description

Looking up atom radii values during graphics updates and when computing molecule bounds is slow because the radius is computed by a function that takes into account element type, bonds, and metal coordination.

In timing the Structure._atom_bounds() routine with 3j3q (2.4 million atoms) it takes about 85 msec to get the atom radii, more than 1/3 of the total time of 210 msec (includes coordinate lookup, and bounds calculation). If a precomputed radius is used instead the lookup reduces to 1 msec.

This problem was encountered in ticket #778, changing coordinates every frame being slow for large structures in ISOLDE.

Change History (11)

comment:1 by Tom Goddard, 8 years ago

Cc: tic20@… added

comment:2 by pett, 8 years ago

Status: assignedaccepted

comment:3 by Tristan Croll, 8 years ago

From what I can see, this can be trivially fixed by adding the line:

self.atoms.radii = self.atoms.default_radii

to Structure.__init__(). The C++ function only resorts to the default calculation every time if the radii are never actually set. After that, the atoms.radii call comes down from 10 to 1.5ms for 184k atoms.

Last edited 8 years ago by Tristan Croll (previous) (diff)

comment:4 by Tristan Croll, 8 years ago

OK, it's been explained to me that I'd misunderstood the way the radii code works, and that simply setting the radii to fixed values would break the ability of atoms to change radii if/when their bonding or identity changes. In that case, I would suggest something along the lines of the following will be necessary, since currently if the user does do atoms.radii = radii there is no way to set them back to the default behaviour later.

void
Atom::reset_radius_to_default()
{

    graphics_container()->set_gc_shape();
    track_change(ChangeTracker::REASON_RADIUS);
    _radius = 0.0f;
}

While perhaps not the best long-term solution, this would also be a minimal-effort solution to provide an easy way to give speed when necessary:

atoms.radii = atoms.default_radii
# Whatever code requires fast framerates
atoms.reset_radii_to_defaults()

comment:5 by pett, 8 years ago

The plan, when I get to it, is to cache the default lookup. The radius computation only depends on a few very specific criteria, so it should be possible to avoid missing places where the caching should be invalidated and isn't. Also, I already have a variable to use for the caching, I just to expand its meaning from "-1 == compute; positive == explicitly set" to "any negative == cached value; positive == explicitly set; zero == need to compute default and cache".

--Eric

comment:6 by pett, 8 years ago

Oh, I also need to implement a call to reset to default value(s), and the "vdwdefine" command for user control of radii.

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

One other idea for optimizing graphics updates while atoms are moving is to have a graphics change bit that indicates atoms moved and don’t update the graphics sphere radii in that case.

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

It turns out that in ISOLDE I've been accidentally "optimizing" radii all along. I've been naively setting them to specific values to differentiate sets of atoms from each other (fixed atoms smaller, mobile atoms intermediate, "special" atoms like C-alphas bigger). Not sure if there's a per-atom radius scaling factor available to do this in a way that doesn't break things?

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

 

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

I tried out the latest official build today, by the way. In a structure that was giving me barely 1-2 frames per second during simulations previously I can now get closer to 10 fps (~35 ms for drawing/rendering, 70 ms for the simulation). If my plan to get the simulation out into its own subprocess works out, that should give me a quite respectable 30+ fps in the GUI regardless of simulation speed.

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

 

comment:10 by pett, 8 years ago

Good to hear that the new speed is close to what you need.

There is no per-atom sphere scaling (other than radius). Once I implement set-back-to-default-radius, you will be at least be able to revert to default radii at the end of your simulation.

--Eric

comment:11 by pett, 8 years ago

Resolution: fixed
Status: acceptedclosed

Atomic radii caching implemented. The ability to revert to default radii (after using explicit radii) is available as Atom.use_default_radius(), Atoms.use_default_radii(), and Structure.use_default_atom_radii()

Note: See TracTickets for help on using tickets.