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 , 8 years ago
Cc: | added |
---|
comment:2 by , 8 years ago
Status: | assigned → accepted |
---|
comment:4 by , 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 , 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 , 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.
follow-up: 7 comment:7 by , 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.
follow-up: 8 comment:8 by , 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
follow-up: 9 comment:9 by , 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 , 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 , 8 years ago
Resolution: | → fixed |
---|---|
Status: | accepted → closed |
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()
From what I can see, this can be trivially fixed by adding the line:
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.