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

Improve coverage #18

Merged
merged 7 commits into from
Mar 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 3 additions & 0 deletions quaternions/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
from quaternions.quaternion import Quaternion # NOQA
from quaternions.general_quaternion import GeneralQuaternion, QuaternionError # NOQA
from quaternions.version import __version__ # NOQA

import warnings
warnings.simplefilter('once')
4 changes: 4 additions & 0 deletions quaternions/quaternion.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
GeneralQuaternion, QuaternionError, DEFAULT_TOLERANCE, exp
)

import warnings


class Quaternion(GeneralQuaternion):
''' A class that holds unit quaternions (norm==1, aka versors). It actually holds Q^op, as
Expand Down Expand Up @@ -119,6 +121,7 @@ def average(cls, *quaternions, weights=None):

@property
def basis(self):
warnings.warn('This property will be deprecated. Use matrix instead', DeprecationWarning)
m = self.matrix
return m[0, :], m[1, :], m[2, :]

Expand Down Expand Up @@ -156,6 +159,7 @@ def astrometry_ra_dec_roll(self):
Notice that Tetra gives a different roll angle, so this is not
a fixed standard.
'''
warnings.warn('This method will be deprecated', DeprecationWarning)
twisted = self.OpticalAxisFirst() * self
ra, dec, roll = twisted.ra_dec_roll
return np.array([-ra, dec, roll - 180])
Expand Down
4 changes: 4 additions & 0 deletions tests/test_general_quaternion.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,7 @@ def test_log_identical_both_ways(self, arr):
assume(np.linalg.norm(arr) > DEFAULT_TOLERANCE)
q = GeneralQuaternion(*arr)
assert log(q) == q.log()

def test_repr(self):
gen_quat = GeneralQuaternion(1, 2, 3, 4)
assert repr(gen_quat) == 'GeneralQuaternion(1, 2, 3, 4)'
33 changes: 32 additions & 1 deletion tests/test_quaternion.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,11 +161,29 @@ def test_ra_dec_roll(self, arr):
def test_qmethod(self):
v1, v2 = [2 / 3, 2 / 3, 1 / 3], [2 / 3, -1 / 3, -2 / 3]
w1, w2 = [0.8, 0.6, 0], [-0.6, 0.8, 0]
q = Quaternion.from_qmethod(np.array([v1, v2]).T, np.array([w1, w2]).T, np.ones(2))
q = Quaternion.from_qmethod(np.array([v1, v2]).T, np.array([w1, w2]).T)

np.testing.assert_allclose(q(v1), w1, atol=1e-10)
np.testing.assert_allclose(q(v2), w2, atol=1e-10)

def test_weights_change_in_qmethod(self):
v1, v2 = [1, 0, 0], [0, 1, 0]
w1, w2 = [1, 0, 0], [-1/2, np.sqrt(3) / 2, 0]

previous_cos_1 = np.inf
previous_cos_2 = -np.inf
for second_weight in np.linspace(0.1, 2, 10):
q = Quaternion.from_qmethod(np.array([v1, v2]).T, np.array([w1, w2]).T, [1, second_weight])
current_cos_1 = q(v1).dot(w1)
current_cos_2 = q(v2).dot(w2)

# since first weight is constant and second weight increases, correlation with
# first vector should go down and correlation with second vector should go up
assert current_cos_1 < previous_cos_1
assert current_cos_2 > previous_cos_2

previous_cos_1, previous_cos_2 = current_cos_1, current_cos_2

@given(ANY_ROTATION_VECTOR)
def test_from_qmethod_with_noise(self, r):
assume(np.linalg.norm(r) > Quaternion.tolerance)
Expand Down Expand Up @@ -253,6 +271,19 @@ def test_apply_wrong_type(self):
with pytest.raises(QuaternionError):
q({1, 2, 3})

def test_repr(self):
unit_quat = Quaternion(1, 2, 3, 4)
assert repr(unit_quat).startswith('Quaternion(')
assert eval(repr(unit_quat)) == unit_quat

@given(strategies.integers(min_value=1, max_value=5))
def test_integrate(self, number_of_vectors):
vectors = [np.array([0, 0, i / 10]) for i in range(1, number_of_vectors + 1)]
v = Quaternion.integrate_from_velocity_vectors(vectors)
expected = [0, 0, number_of_vectors * (number_of_vectors + 1) / 20]
np.testing.assert_allclose(expected, v)


class QuaternionStdDevTests(unittest.TestCase):
# tolerance is this big because average_and_std_naive gives slightly different results than matlab implementation
# this may be due to the way weights are taken into account, as in matlab implementation weights were not being used
Expand Down