Source code for attitude.display.test_hyperbolic_errors
"""
Test module to make sure that simple representations of
hyperbolic errors are equivalent to more generalized
expressions.
"""
import numpy as N
from scipy.stats import chi2
from .plot.cov_types.regressions import hyperbola
from ..orientation.test_pca import random_pca
from ..geom.util import dot, augment_tensor, plane
from ..error.axes import sampling_axes
from ..geom.conics import conic
[docs]def simple_hyperbola(cov, xvals, n=1, level=1):
"""
Simple hyperbolic error bounds for 2d errors
using quadratic formulation.
Returns tuple of
( distance from center of distribution,
width of error bar)
in unrotated coordinate space
"""
assert len(cov) == 2
a = cov[0]
# Plot hyperbola
b = N.sqrt(cov[-1])
def y(x):
return level*b*N.sqrt(x**2/(a*n)+1/n)
# Top values of error bar only
t = N.array([xvals,y(xvals)])
return t
[docs]def hyperbola_from_axes(cov, xvals, n=1, level=1):
# Plot hyperbola
cov[-1] = level*N.sqrt(cov[-1]/n)
def y(x):
return cov[-1]*N.sqrt(x**2/cov[1]+1)
# Top values of error bar only
t = N.array([xvals,y(xvals)])
return t
[docs]def test_sampling_covariance():
"""
Test the creation of hyperbolic errors
along direction of maximum angular variability
"""
fit = random_pca()
sv = fit.singular_values
n = len(fit.arr)
cov = sv**2/(n-1)
xvals = N.linspace(-100,100,100)
level = chi2.ppf(0.95,n-3)
# use only direction of maximum angular
# variation
cov2d = cov[1:]
res1 = simple_hyperbola(cov2d,xvals, n, N.sqrt(level))
res2 = hyperbola(
cov2d,
N.identity(2), # rotation
N.array([0,0]), # mean
xvals,
n=n,
level=N.sqrt(level))
# Get only top values
res2 = (res2[0],res2[-1])
for a,b in zip(res1,res2):
assert N.allclose(a,b)
# Scale axes before sending to plotting function
cov[-1] = level*cov[-1]/n
res3 = simple_hyperbola(cov[1:],xvals)
for a,b in zip(res1,res3):
assert N.allclose(a,b)
[docs]def test_dual_conic():
fit = random_pca()
angle = N.pi/8
# Hyperbolic axes
hyp_axes = N.array([100,10,0.02])#sampling_axes(fit)
arr = augment_tensor(N.diag(hyp_axes))
# Transform ellipsoid to dual hyperboloid
hyp = conic(arr).dual()
axes = N.array([[N.cos(angle),N.sin(angle),0],[0,0,1]])
n_ = N.cross(axes[0],axes[1])
# Create a plane containing the two axes specified
# in the function call
p = plane(n_) # no offset (goes through origin)
h1 = hyp.slice(p, axes=axes)[0]
# Major axes of the conic sliced in the requested viewing
# geometry
H = N.sqrt(h1.semiaxes())
## Simple methods
h = N.sqrt(1/hyp_axes)
v = [h[0]*N.cos(angle),
h[1]*N.sin(angle),
h[2]]
a = 1/N.linalg.norm([v[0],v[1]])
b = 1/N.abs(v[2])
H1 = [a,b]
assert N.allclose(H,H1)