Skip to content

Commit

Permalink
Fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
AntonOresten committed Jul 22, 2024
1 parent c873d0a commit b19875e
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 15 deletions.
26 changes: 13 additions & 13 deletions src/frames.jl
Original file line number Diff line number Diff line change
Expand Up @@ -59,18 +59,18 @@ Backbone(frames::Frames, ideal_coords::AbstractMatrix{<:Real}) = Backbone(frames
### Quaternion support

# takes a batch of unit quaternions in a 4xN matrix and returns a batch of rotation matrices in a 3x3xN array
function quaternions_to_rotation_matrices(q::AbstractArray{<:Real,2})
size(q, 1) == 4 || throw(ArgumentError("Quaternion batch must have shape 4xN"))

sx = 2q[1, :] .* q[2, :]
sy = 2q[1, :] .* q[3, :]
sz = 2q[1, :] .* q[4, :]
xx = 2q[2, :] .^ 2
xy = 2q[2, :] .* q[3, :]
xz = 2q[2, :] .* q[4, :]
yy = 2q[3, :] .^ 2
yz = 2q[3, :] .* q[4, :]
zz = 2q[4, :] .^ 2
function quaternions_to_rotation_matrices(Q::AbstractArray{<:Real,2})
size(Q, 1) == 4 || throw(ArgumentError("Quaternion batch must have shape 4xN"))

sx = 2Q[1, :] .* Q[2, :]
sy = 2Q[1, :] .* Q[3, :]
sz = 2Q[1, :] .* Q[4, :]
xx = 2Q[2, :] .^ 2
xy = 2Q[2, :] .* Q[3, :]
xz = 2Q[2, :] .* Q[4, :]
yy = 2Q[3, :] .^ 2
yz = 2Q[3, :] .* Q[4, :]
zz = 2Q[4, :] .^ 2

r1 = 1 .- (yy + zz)
r2 = xy - sz
Expand All @@ -89,7 +89,7 @@ Frames(rotations::AbstractArray{<:Real,2}, translations::AbstractArray{<:Real,2}

# takes a batch of rotation matrices in a 3x3xN array and returns a batch of unit quaternions in a 4xN matrix
function rotation_matrices_to_quaternions(R::AbstractArray{<:Real,3})
size(q)[1:2] == (3,3) || throw(ArgumentError("Rotation matrix batch must have shape 3x3xN"))
size(R)[1:2] == (3,3) || throw(ArgumentError("Rotation matrix batch must have shape 3x3xN"))
# 1x1xN
r11, r12, r13 = R[1:1, 1:1, :], R[1:1, 2:2, :], R[1:1, 3:3, :]
r21, r22, r23 = R[2:2, 1:1, :], R[2:2, 2:2, :], R[2:2, 3:3, :]
Expand Down
2 changes: 2 additions & 0 deletions src/protein/chain.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using Backboner: get_atom_distances

"""
Chain <: AbstractVector{Residue}
Expand Down
51 changes: 49 additions & 2 deletions test/frames.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
using Backboner: quaternions_to_rotation_matrices, rotation_matrices_to_quaternions
using LinearAlgebra

@testset "frames.jl" begin

@testset "Frames" begin
Expand Down Expand Up @@ -29,14 +32,58 @@
end

@testset "Quaternion conversion" begin

# Helper functions
function quaternion_multiply(q1, q2)
w1, x1, y1, z1 = q1
w2, x2, y2, z2 = q2
return [
w1*w2 - x1*x2 - y1*y2 - z1*z2,
w1*x2 + x1*w2 + y1*z2 - z1*y2,
w1*y2 - x1*z2 + y1*w2 + z1*x2,
w1*z2 + x1*y2 - y1*x2 + z1*w2
]
end

quaternion_conjugate(q) = [q[1], -q[2], -q[3], -q[4]]

N = 10
_Q = randn(4, N)
Q = _Q ./ sqrt.(sum(abs2, _Q, dims=1))
R = quaternions_to_rotation_matrices(Q)
Q2 = rotation_matrices_to_quaternions(R)
R2 = quaternions_to_rotation_matrices(Q2)
@test R R2
@test all((Q .≈ Q2) .| (Q .≈ -Q2))

@testset "Conversion Consistency" begin
@test R R2
@test all((Q .≈ Q2) .| (Q .≈ -Q2))
end

@testset "Rotation Matrix Properties" begin
for i in 1:N
# Test orthogonality
@test R[:,:,i] * R[:,:,i]' I
# Test proper rotation (determinant should be 1)
@test det(R[:,:,i]) 1
# Test that it actually rotates a vector
v = randn(3)
@test norm(R[:,:,i] * v) norm(v)
@test R[:,:,i] * v v # not approximately equal
end
end

@testset "Quaternion Properties" begin
for i in 1:N
# Test unit norm
@test norm(Q[:,i]) 1
# Test rotation property
v = randn(3)
qv = [0; v]
rotated_v = quaternion_multiply(quaternion_multiply(Q[:,i], qv), quaternion_conjugate(Q[:,i]))[2:4]
@test norm(rotated_v) norm(v)
@test rotated_v v # not approximately equal
end
end
end

end

2 comments on commit b19875e

@AntonOresten
Copy link
Member Author

Choose a reason for hiding this comment

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

@JuliaRegistrator register

Release notes:

  • Add quaternions_to_rotation_matrices and rotation_matrices_to_quaternions utility functions.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

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

Registration pull request created: JuliaRegistries/General/111527

Tagging

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.11.1 -m "<description of version>" b19875ef2584e3e2fb19f475e8ab1c143c3a43d8
git push origin v0.11.1

Please sign in to comment.