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

Stddev calculations #5

Merged
merged 16 commits into from
Nov 29, 2017
Merged

Stddev calculations #5

merged 16 commits into from
Nov 29, 2017

Conversation

enritoomey
Copy link
Contributor

No description provided.

@enritoomey
Copy link
Contributor Author

@Juanlu001 @gilgamezh como arreglo esto?

@matiasg
Copy link
Collaborator

matiasg commented Nov 8, 2017

@enritoomey , creo que hay que mergear primero el PR de @gilgamezh para que travis sepa de qué se trata el proyecto.

@gilgamezh
Copy link
Contributor

@henry-aocs please merge master to this branch to get the tests working

@coveralls
Copy link

coveralls commented Nov 9, 2017

Coverage Status

Coverage decreased (-5.0%) to 85.185% when pulling 9896d78 on stddev_calculations into 28dba2a on master.

3 similar comments
@coveralls
Copy link

Coverage Status

Coverage decreased (-5.0%) to 85.185% when pulling 9896d78 on stddev_calculations into 28dba2a on master.

@coveralls
Copy link

Coverage Status

Coverage decreased (-5.0%) to 85.185% when pulling 9896d78 on stddev_calculations into 28dba2a on master.

@coveralls
Copy link

Coverage Status

Coverage decreased (-5.0%) to 85.185% when pulling 9896d78 on stddev_calculations into 28dba2a on master.

@enritoomey
Copy link
Contributor Author

el covarage da bajo porque agregue una funcion que no testeo.... en el proximo commit le agrego el test y saco el wip

@enritoomey enritoomey changed the title [WIP] Stddev calculations Stddev calculations Nov 9, 2017
@coveralls
Copy link

coveralls commented Nov 9, 2017

Coverage Status

Coverage increased (+1.8%) to 91.981% when pulling c85723c on stddev_calculations into 28dba2a on master.

@enritoomey
Copy link
Contributor Author

@gilgamezh @matiasg estoy esperando su +1

@enritoomey
Copy link
Contributor Author

@Juanlu001, queres darle una mirada a este MR?

Copy link
Contributor

@astrojuanlu astrojuanlu left a comment

Choose a reason for hiding this comment

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

Despite some minor comments and typos this looks good to me, however bear in mind that I didn't review the math in depth. There are lots of tests against MATLAB though, which is very nice.

@@ -1,7 +1,7 @@
import functools
import numpy as np
from collections import Iterable

from quaternions.utils import (covariance_matrix_from_angles, sigma_lerner, orthogonal_matrix)
Copy link
Contributor

Choose a reason for hiding this comment

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

No need to have parentheses here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes, but i was @matiasg style to put then anyway

Copy link
Collaborator

Choose a reason for hiding this comment

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

parentheses there are needed when you need to split into multiple lines. Otherwise, they are not.
I'm not saying that I always go by this rule, but it's the best rule I can produce ;-)

'''
Return the quaternion such that its matrix minimizes the square distance
to the matrices of the quaternions in the argument list.

See Averaging Quaternions, by Markley, Cheng, Crassidis, Oschman.
'''
B = np.array([q.coordinates for q in quaternions])
if not weights:
if not any(True for _ in weights):
Copy link
Contributor

Choose a reason for hiding this comment

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

Why this instead of the empty list/tuple?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll change it to: use None as default value for weights, and then check if weights is None.

Naive implementation of std. dev. calculation, assuming small angles between quaternions
and average. Returns average quaternion and stddev of input quaternion list in deg
"""
if not any(True for _ in weights):
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as above

weights = np.ones(len(quaternions))
q_average = Quaternion.average(*quaternions, weights=weights)
diffs = np.array([q_average.distance(quat) for quat in quaternions])
# TODO: check that this way of taking into account weights in stddev calculation is ok
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd say it's ok!

called sigma lerner. This covariance matriz is the one asociated with the rotation angles of
each input quaternion agains the average one. Returns the average quaternion anf the sigma lerner
in deg.
:param quaternions: lista de objetos Quaternion
Copy link
Contributor

Choose a reason for hiding this comment

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

Se escapó un comentario en español :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yo no hablar español... jajja, ahora lo corrigo

@staticmethod
def average_and_std_lerner(*quaternions, weights=()):
"""
Calculates the std. dev. as 1.87 of the root of the maximum eigenvalue of the covariance matrix,
Copy link
Contributor

Choose a reason for hiding this comment

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

I am not an expert on quaternions, but Google didn't show any relevant results on "quaternions" "sigma lerner" and variations. Perhaps it's coming from some article by Gerald M. Lerner? Is there a chance we can document this a bit more?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

certainly, i have to track down the paper from which this way of condensing a correlation matrix to a single value was taken...

def average_and_std_lerner(*quaternions, weights=()):
"""
Calculates the std. dev. as 1.87 of the root of the maximum eigenvalue of the covariance matrix,
called sigma lerner. This covariance matriz is the one asociated with the rotation angles of
Copy link
Contributor

Choose a reason for hiding this comment

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

"matriz", "anf"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

orthogonal_matrix_sum += orthogonal_matrix(q).dot(
R_inverse.dot(orthogonal_matrix(q).T))

cov_dev_matrix = np.linalg.inv(orthogonal_matrix(q_average).T.dot(
Copy link
Contributor

Choose a reason for hiding this comment

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

I guess the code is required to run in Python 3.4? Otherwise you could use orthogonal_matrix(q_average).T @ orthogonal_matrix_sum @ orthogonal_matrix(q_average).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yeap, I still fun python 3.4 in my debian8 installation 😳 Do we have a requisite on the python version?

Copy link
Collaborator

Choose a reason for hiding this comment

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

We have travis now, that tests the code from python 3.4 until 3.6.
And 3.4 is needed, sadly.

"""
covariance_matrix = np.zeros((3, 3))
for angles in angles_list:
covariance_matrix += np.outer(angles.T, angles)
Copy link
Contributor

Choose a reason for hiding this comment

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

I guess angles_list is a list of NumPy arrays, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes

* np.sqrt(len(quat_diff_matlab_quats)-1)

assert abs(sigma_lerner_in_deg - sigma_lerner_out_deg ) \
< self.tolerance_deg
Copy link
Contributor

Choose a reason for hiding this comment

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

Missing newline

@coveralls
Copy link

coveralls commented Nov 15, 2017

Coverage Status

Coverage increased (+1.8%) to 91.981% when pulling 5616a6e on stddev_calculations into 28dba2a on master.

Copy link
Contributor

@astrojuanlu astrojuanlu left a comment

Choose a reason for hiding this comment

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

Although it would be nice to know from which Lerner paper does the covariance come, I'm approving these changes.

@astrojuanlu
Copy link
Contributor

...although some tests fail in Python 3.6 :)

Copy link
Collaborator

@matiasg matiasg left a comment

Choose a reason for hiding this comment

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

We should first merge the PR splitting quaternions into two classes and then merge this one. Anyway, there should be almost no changes in this PR for that.
Mostly, I'd like some function names to change.

@@ -0,0 +1,38 @@
import numpy as np
Copy link
Collaborator

Choose a reason for hiding this comment

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

please, add the reference to the paper(s) you are implementing here.
Also, in the methods, there could be a line like equation 2.3 from (1), or any other citation like this one.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Still missing the reference paper to the sigma lerner calculation

[-quaternion.qj, quaternion.qi, 0]])


def orthogonal_matrix(quaternion):
Copy link
Collaborator

Choose a reason for hiding this comment

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

I strongly oppose to this name :-P
This matrix is not square, so it is not an orthogonal matrix.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

return 1.87 * np.sqrt(max(values))


def rotation_matrix(quaternion):
Copy link
Collaborator

Choose a reason for hiding this comment

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

this is not a rotation matrix, but the matrix of a cross product with the vector [qi, qj, qk].
The name cross_product_matrix might be better. It could also have the same name it has in the paper where it comes from.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@coveralls
Copy link

coveralls commented Nov 28, 2017

Coverage Status

Coverage increased (+1.009%) to 96.899% when pulling 881db4f on stddev_calculations into 8f57a95 on master.

@coveralls
Copy link

coveralls commented Nov 28, 2017

Coverage Status

Coverage increased (+1.009%) to 96.899% when pulling 88800e8 on stddev_calculations into 8f57a95 on master.

1 similar comment
@coveralls
Copy link

coveralls commented Nov 28, 2017

Coverage Status

Coverage increased (+1.009%) to 96.899% when pulling 88800e8 on stddev_calculations into 8f57a95 on master.

@coveralls
Copy link

Coverage Status

Coverage increased (+1.009%) to 96.899% when pulling d12da5d on stddev_calculations into 8f57a95 on master.

1 similar comment
@coveralls
Copy link

coveralls commented Nov 29, 2017

Coverage Status

Coverage increased (+1.009%) to 96.899% when pulling d12da5d on stddev_calculations into 8f57a95 on master.

Copy link
Collaborator

@matiasg matiasg left a comment

Choose a reason for hiding this comment

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

Ok for me after a few changes are made.

weights = np.ones(len(quaternions))
q_average = Quaternion.average(*quaternions, weights=weights)
diffs = np.array([q_average.distance(quat) for quat in quaternions])
# TODO: check that this way of taking into account weights in stddev calculation is ok
Copy link
Collaborator

Choose a reason for hiding this comment

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

this is what you do with any zero-mean random variable to compute its standard deviation:
sqrt( sum ( x ** 2 * p(x) ) )

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ok

@staticmethod
def average_and_std_naive(*quaternions, weights=None):
"""
Naive implementation of std. dev. calculation, assuming small angles between quaternions
Copy link
Collaborator

Choose a reason for hiding this comment

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

why do you need small angles?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I really don't know why I put that docstring.

"""
q_average = Quaternion.average(*quaternions, weights=weights)
diffs = [quat / q_average for quat in quaternions]
angles_list = np.array([[2 * diff.coordinates[i] for i in [1, 2, 3]] for diff in diffs])
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think you can do here

angles_list = [2 * diff.coordinates[1:] for diff in diffs]

You don't need it to be a numpy array, anyway

Copy link
Collaborator

Choose a reason for hiding this comment

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

actually, the RAX paper works with Gibbs vectors, which are

diff.coordinates[1:] / diff.qr

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes, actually there's a factor of two. I'll open an issue

"""
Calculates the std. dev. as 1.87 of the root of the maximum eigenvalue of the covariance matrix,
called sigma lerner. This covariance matrix is the one asociated with the rotation angles of
each input quaternion agains the average one. Returns the average quaternion and the sigma lerner
Copy link
Collaborator

Choose a reason for hiding this comment

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

against

"""
covariance_matrix = np.zeros((3, 3))
for angles in angles_list:
covariance_matrix += np.outer(angles.T, angles)
Copy link
Collaborator

Choose a reason for hiding this comment

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

it seems that these three lines can be

covariance_matrix = sum(np.outer(angles, angles) for angles in angles_list)

or, if you already receive a numpy.array, by

covariance_matrix = angles_list.T.dot(angles_list)

Returns the quaternion such that its matrix minimizes the square distance
to the matrices of the quaternions in the argument list, and the resulting
covariance matrix asociated with that quaternion. Input matrix R (3x3) is
assume to be the same for all input quaternions, and in rads**2
Copy link
Collaborator

Choose a reason for hiding this comment

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

assumed

'''
Returns the quaternion such that its matrix minimizes the square distance
to the matrices of the quaternions in the argument list, and the resulting
covariance matrix asociated with that quaternion. Input matrix R (3x3) is
Copy link
Collaborator

Choose a reason for hiding this comment

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

associated

@coveralls
Copy link

coveralls commented Nov 29, 2017

Coverage Status

Coverage increased (+1.0%) to 96.875% when pulling df4485f on stddev_calculations into 8f57a95 on master.

@coveralls
Copy link

coveralls commented Nov 29, 2017

Coverage Status

Coverage increased (+1.0%) to 96.875% when pulling 5fa4f58 on stddev_calculations into 8f57a95 on master.

3 similar comments
@coveralls
Copy link

Coverage Status

Coverage increased (+1.0%) to 96.875% when pulling 5fa4f58 on stddev_calculations into 8f57a95 on master.

@coveralls
Copy link

Coverage Status

Coverage increased (+1.0%) to 96.875% when pulling 5fa4f58 on stddev_calculations into 8f57a95 on master.

@coveralls
Copy link

Coverage Status

Coverage increased (+1.0%) to 96.875% when pulling 5fa4f58 on stddev_calculations into 8f57a95 on master.

@enritoomey enritoomey merged commit 10a0adc into master Nov 29, 2017
@enritoomey enritoomey deleted the stddev_calculations branch March 19, 2020 23:54
matiasg added a commit that referenced this pull request Jul 27, 2020
# This is the 1st commit message:

pin coveralls version

# This is the commit message #2:

rever change of pytest-coverage. Pin python-coverage

# This is the commit message #3:

just as a test, remove coveralls

# This is the commit message #4:

remove also cov from script 🤦

# This is the commit message #5:

pin pytest version

# This is the commit message #6:

pin hypothesis version

# This is the commit message #7:

pin hypothesis to 3.55.1 now

# This is the commit message #8:

do not install pytest-coverage

# This is the commit message #9:

pin pytest-coverage

# This is the commit message #10:

install pinned coverage, do not install pytest-coverage :'(

# This is the commit message #11:

pin attr

# This is the commit message #12:

attr is attrs

# This is the commit message #13:

travis, please tell me attr version

# This is the commit message #14:

go back to original setup.py

# This is the commit message #15:

exclude coveralls from 3.4 & 3.5. Try 1

# This is the commit message #16:

use [] instead of test

# This is the commit message #17:

install pytest 5.4.3

# This is the commit message #18:

travis tell me something

# This is the commit message #19:

please do tell

# This is the commit message #20:

ooohhh?

# This is the commit message #21:

oh 2

# This is the commit message #22:

oh 3

# This is the commit message #23:

oh 4

# This is the commit message #24:

oh 5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants