Particles can only be drawn with spheres because the particles have no orientations.
closes #40
Solution
Particles with geometrically-constrained edges (e.g. in ReaDDy data) can be mapped to structural data (e.g. from PDB files) to back-calculate orientations that allow geometry generated from that structural data to be drawn with reasonable accuracy.
This solution breaks the problem into multiple cases:
Independent orientations - particles with two neighbors have fully determined orientations. To calculate them, use the vectors from the particle to each of its neighbors to form a basis.
Random orientation - if a particle has no neighbors, it's orientation is fully undetermined, and the only thing to do is create a random orientation (Note: maybe a future PR should make the random rotation be an offset from the previous time step, for now it is independently random each time. However this might be roughly accurate given these timesteps are very large relative to molecular time).
Dependent orientation - particles with one neighbor may have fully or partially determined orientations:
If their one neighbor has other neighbors, their orientation is fully determined by an offset from their neighbor's orientation
If their one neighbor has no other neighbors, both of these particles have to orient correctly relative to each other, but have a degree of freedom around the axis defined by their edge. (This case also applies to colinear neighbors but I've left that out for now)
For all of these cases, the orientations calculated from neighbor positions are meaningless on their own. In order to use them to orient geometry, we need to calculate the difference between the current orientation and the orientation of the particles used to generate the geometry (which I'm calling "zero orientations").
Type of change
New feature (non-breaking change which adds functionality)
This change requires a documentation update
This change requires updated or new tests
Change summary:
implement orientations for two neighbors (independent)
implement orientations for one neighbor (dependent)
use orientations in ReaDDy converter
verify rotations look reasonable in the viewer
add tests
Keyfiles:
simulariumio/orientations/particle_rotation_calculator.py - ParticleRotationCalculator is the main particle orientation class, which contains all the data needed to calculate orientation for one particle at one time step. In __init__() it calculates independent and random orientations since they don't depend on neighbor orientations already being calculated. It also has calculate_dependent_rotation() which can be used after ParticleRotationCalculators are created for all the particle's neighbors. There's also get_euler_angles() to get the final orientation as an XYZ rotation for the simularium viewer.
simulariumio/readdy/readdy_converter.py and simulariumio/readdy/readdy_data.py - add orientation calculation for ReaDDy particles.
simulariumio/orientations/orientation_data.py and simulariumio/orientations/neighbor_data.py - data classes with some related methods.
simulariumio/orientations/rotation_utility.py - helpers for calculating rotations, everything that uses scipy for linear algebra and rotations
Problem
Particles can only be drawn with spheres because the particles have no orientations. closes #40
Solution
Particles with geometrically-constrained edges (e.g. in ReaDDy data) can be mapped to structural data (e.g. from PDB files) to back-calculate orientations that allow geometry generated from that structural data to be drawn with reasonable accuracy.
This solution breaks the problem into multiple cases:
For all of these cases, the orientations calculated from neighbor positions are meaningless on their own. In order to use them to orient geometry, we need to calculate the difference between the current orientation and the orientation of the particles used to generate the geometry (which I'm calling "zero orientations").
Type of change
Change summary:
Keyfiles:
ParticleRotationCalculator
is the main particle orientation class, which contains all the data needed to calculate orientation for one particle at one time step. In__init__()
it calculates independent and random orientations since they don't depend on neighbor orientations already being calculated. It also hascalculate_dependent_rotation()
which can be used afterParticleRotationCalculator
s are created for all the particle's neighbors. There's alsoget_euler_angles()
to get the final orientation as an XYZ rotation for the simularium viewer.