Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trajectory operators #16

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions src/beignet/center_of_mass.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import torch


def compute_center_of_mass(traj):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

center_of_mass

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add type annotations, e.g.,

center_of_mass(input: Tensor) -> Tensor.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename traj to input to match PyTorch style.

"""Compute the center of mass for each frame.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add the raw string prefix (r).


Parameters
----------
traj : Trajectory
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trajectory is not a type.

Trajectory to compute center of mass for

Returns
-------
com : torch.Tensor, shape=(n_frames, 3)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename com to output to match PyTorch style.

Coordinates of the center of mass for each frame
"""

com = torch.empty((traj.n_frames, 3))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be zeros. empty is random.


masses = torch.tensor([a.element.mass for a in traj.top.atoms])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are a.element.mass and traj.top.atoms?

masses /= masses.sum()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not use assignment ops.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not use methods.


xyz = traj.xyz

for i, x in enumerate(xyz):
com[i, :] = torch.tensordot(masses, x.double().t(), dims=0)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tensordot?


return com
55 changes: 55 additions & 0 deletions src/beignet/gyration_tensor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import torch


def _compute_center_of_geometry(traj):
"""Compute the center of geometry for each frame.

Parameters
----------
traj : Trajectory
Trajectory to compute center of geometry for.

Returns
-------
centers : torch.Tensor, shape=(n_frames, 3)
Coordinates of the center of geometry for each frame.

"""

centers = torch.zeros((traj.n_frames, 3))

for i, x in enumerate(traj.xyz):
centers[i, :] = torch.mean(x.double().t(), dim=1)

return centers


def gyration_tensor(traj):
"""Compute the gyration tensor of a trajectory.

For every frame,

.. math::

S_{xy} = \sum_{i_atoms} r^{i}_x r^{i}_y

Parameters
----------
traj : Trajectory
Trajectory to compute gyration tensor of.

Returns
-------
S_xy: torch.Tensor, shape=(traj.n_frames, 3, 3), dtype=float64
Gyration tensors for each frame.

References
----------
.. [1] https://isg.nist.gov/deepzoomweb/measurement3Ddata_help#shape-metrics-formulas

"""
center_of_geom = torch.unsqueeze(_compute_center_of_geometry(traj), dim=1)

xyz = traj.xyz - center_of_geom

return torch.einsum('...ji,...jk->...ik', xyz, xyz) / traj.n_atoms
60 changes: 60 additions & 0 deletions src/beignet/rmsd.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import torch
from scipy.spatial.transform import Rotation as R
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use one of our rotation operators.



# TODO (isaacsoh) parallelize and speed up, eliminate 3-D requirement
def _rmsd(traj1, traj2):
"""

Parameters
----------
traj1 : Trajectory
For each conformation in this trajectory, compute the RMSD to
a particular 'reference' conformation in another trajectory.
traj2 : Trajectory
The reference conformation to measure distances
to.

Returns
-------
rmsd_result : torch.Tensor
The rmsd calculation of two trajectories.
"""

assert traj1.shape == traj2.shape, "Input tensors must have the same shape"
assert traj1.dim() == 3, "Input tensors must be 3-D (num_frames, num_atoms, 3)"

num_frames = traj1.shape[0] # Number of frames

# Center the trajectories
traj1 = traj1 - traj1.mean(dim=1, keepdim=True)
traj2 = traj2 - traj2.mean(dim=1, keepdim=True)

# Initialization of the resulting RMSD tensor
rmsd_result = torch.zeros(num_frames).double()

for i in range(num_frames):
# For each configuration compute the rotation matrix minimizing RMSD using SVD
u, s, v = torch.svd(torch.mm(traj1[i].t(), traj2[i]))

# Determinat of u * v
d = (u * v).det().item() < 0.0

if d:
s[-1] = s[-1] * (-1)
u[:, -1] = u[:, -1] * (-1)

# Optimal rotation matrix
rot_matrix = torch.mm(v, u.t())

test = (R.from_matrix(rot_matrix)).as_matrix()

assert torch.allclose(torch.from_numpy(test), rot_matrix, rtol=1e-03, atol=1e-04)

# Calculate RMSD and append to resulting tensor
traj2[i] = torch.mm(traj2[i], rot_matrix)

rmsd_result[i] = torch.sqrt(
torch.sum((traj1[i] - traj2[i]) ** 2) / traj1.shape[1])

return rmsd_result
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add newline

Loading