# Path: attitude/orientation/reconstructed.py
# class ReconstructedPlane(ErrorShell, BaseOrientation):
#     """
#     This class represents a plane with errors on two axes.
#     This error is presumably the result of some statistical
#     process, and is a single confidence interval or shell
#     derived from this result.
#     """
#     def __init__(self, strike, dip, rake, *angular_errors, **kwargs):
#         _trans_arr = N.array([-1, -1, 1])
#         def vec(latlon):
#             lat, lon = latlon
#             _ = M.sph2cart(lat, lon)
#             val = N.array(_).flatten()
#             val = N.roll(val,-1)
#             return val * _trans_arr
# 
#         normal_error = kwargs.pop('normal_error',1)
# 
#         self.__strike = strike
#         self.__dip = dip
#         self.__angular_errors = angular_errors
#         self.__rake = rake
# 
#         errors = N.radians(angular_errors)/2
#         pole = M.pole(strike, dip)
# 
#         # Uncertain why we have to do this to get a normal vector
#         # but it has something to do with the stereonet coordinate
#         # system relative to the normal
#         self.normal = vec(pole)
#         ll = M.rake(strike, dip, rake)
#         max_angle = vec(ll)
#         min_angle = N.cross(self.normal, max_angle)
# 
#         # These axes have the correct length but need to be
#         # rotated into the correct reference frame.
#         ax = N.vstack((min_angle, max_angle, self.normal))
# 
#         # Apply right-hand rule
#         #ax[0:],ax[1:]
# 
#         #T = N.eye(3)
#         #T[:-1,:-1] = rotate_2D(N.radians(rake))
# 
#         T = transform(ax[0],max_angle)
#         self.axes = ax
#         if self.axes[-1,-1] < 0:
#             self.axes *= -1
# 
#         lengths = normal_error/N.tan(errors[::-1])
#         self.hyperbolic_axes = N.array(list(lengths)+[normal_error])
#         self.covariance_matrix = N.diag(self.hyperbolic_axes)
# 
#     def strike_dip_rake(self):
#         return self.__strike, self.__dip, self.__rake
# 
#     def angular_errors(self):
#         return self.__angular_errors
# 
#     @property
#     def hash(self):
#         return hash_array(self.hyperbolic_axes*self.axes)
# 
# Path: attitude/stereonet.py
# def quaternion(vector, angle):
# def ellipse(n=1000, adaptive=False):
# def sph2cart(lat,lon):
# def scale_errors(cov_axes, confidence_level=0.95):
# def normal_errors(axes, covariance_matrix, **kwargs):
# def test_ellipse():
# def plane_errors(axes, covariance_matrix, sheet='upper',**kwargs):
# def iterative_normal_errors(axes, covariance_matrix, **kwargs):
#     def sdot(a,b):
#     def step_func(a):
# def iterative_plane_errors(axes,covariance_matrix, **kwargs):
#     def sdot(a,b):
#     def step_func(a):
# def error_ellipse(axes, covariance_matrix, **kwargs):
# def error_coords(axes, covariance_matrix, **kwargs):
#     def _(half, level=1):
#     def __(level):
# 
# Path: attitude/error/axes.py
# def sampling_axes(fit, **kw):
#     """
#     Hyperbolic axis lengths based on sample-size
#     normal statistics.
# 
#     Note: legacy method that simply wraps the
#     `statistical_axes` function.
#     """
#     return statistical_axes(fit, method='sampling', **kw)
# 
# Path: attitude/geom/transform.py
# def rotate_2D(angle):
#     """
#     Returns a 2x2 transformation matrix to rotate
#     by an angle in two dimensions
#     """
#     return N.array([[N.cos(angle),-N.sin(angle)],
#                     [N.sin(angle),N.cos(angle)]])


import numpy as N
import mplstereonet.stereonet_math as M
from matplotlib.path import Path
from matplotlib.patches import PathPatch
from ..orientation.reconstructed import ReconstructedPlane
from ..stereonet import plane_errors, ellipse, dot, error_ellipse, normal_errors
from ..error.axes import sampling_axes
from ..geom.transform import rotate_2D
            lonlat = lonlat[::-1]
        vertices += list(lonlat)
        codes.append(Path.MOVETO)
        codes += [Path.LINETO]*(n-1)

    plot_patch(ax, vertices, codes, **kwargs)

def pole_error(ax, fit, **kwargs):
    """
    Plot the error to the pole to a plane on a `mplstereonet`
    axis object.
    """
    ell = normal_errors(fit.axes, fit.covariance_matrix)
    lonlat = N.array(ell)
    lonlat[:,0] *= -1
    n = len(lonlat)
    codes = [Path.MOVETO]
    codes += [Path.LINETO]*(n-1)
    vertices = list(lonlat)
    plot_patch(ax, vertices, codes, **kwargs)

def uncertain_pole(ax, *args, **kwargs):
    """
    Min and max angular errors are symmetrical and
    thus should be doubled.
    """
    fit = ReconstructedPlane(*args)
    return pole_error(ax, fit, **kwargs)

def uncertain_plane(ax, *args, **kwargs):

# Path: attitude/orientation/reconstructed.py
# class ReconstructedPlane(ErrorShell, BaseOrientation):
#     """
#     This class represents a plane with errors on two axes.
#     This error is presumably the result of some statistical
#     process, and is a single confidence interval or shell
#     derived from this result.
#     """
#     def __init__(self, strike, dip, rake, *angular_errors, **kwargs):
#         _trans_arr = N.array([-1, -1, 1])
#         def vec(latlon):
#             lat, lon = latlon
#             _ = M.sph2cart(lat, lon)
#             val = N.array(_).flatten()
#             val = N.roll(val,-1)
#             return val * _trans_arr
# 
#         normal_error = kwargs.pop('normal_error',1)
# 
#         self.__strike = strike
#         self.__dip = dip
#         self.__angular_errors = angular_errors
#         self.__rake = rake
# 
#         errors = N.radians(angular_errors)/2
#         pole = M.pole(strike, dip)
# 
#         # Uncertain why we have to do this to get a normal vector
#         # but it has something to do with the stereonet coordinate
#         # system relative to the normal
#         self.normal = vec(pole)
#         ll = M.rake(strike, dip, rake)
#         max_angle = vec(ll)
#         min_angle = N.cross(self.normal, max_angle)
# 
#         # These axes have the correct length but need to be
#         # rotated into the correct reference frame.
#         ax = N.vstack((min_angle, max_angle, self.normal))
# 
#         # Apply right-hand rule
#         #ax[0:],ax[1:]
# 
#         #T = N.eye(3)
#         #T[:-1,:-1] = rotate_2D(N.radians(rake))
# 
#         T = transform(ax[0],max_angle)
#         self.axes = ax
#         if self.axes[-1,-1] < 0:
#             self.axes *= -1
# 
#         lengths = normal_error/N.tan(errors[::-1])
#         self.hyperbolic_axes = N.array(list(lengths)+[normal_error])
#         self.covariance_matrix = N.diag(self.hyperbolic_axes)
# 
#     def strike_dip_rake(self):
#         return self.__strike, self.__dip, self.__rake
# 
#     def angular_errors(self):
#         return self.__angular_errors
# 
#     @property
#     def hash(self):
#         return hash_array(self.hyperbolic_axes*self.axes)
# 
# Path: attitude/stereonet.py
# def quaternion(vector, angle):
# def ellipse(n=1000, adaptive=False):
# def sph2cart(lat,lon):
# def scale_errors(cov_axes, confidence_level=0.95):
# def normal_errors(axes, covariance_matrix, **kwargs):
# def test_ellipse():
# def plane_errors(axes, covariance_matrix, sheet='upper',**kwargs):
# def iterative_normal_errors(axes, covariance_matrix, **kwargs):
#     def sdot(a,b):
#     def step_func(a):
# def iterative_plane_errors(axes,covariance_matrix, **kwargs):
#     def sdot(a,b):
#     def step_func(a):
# def error_ellipse(axes, covariance_matrix, **kwargs):
# def error_coords(axes, covariance_matrix, **kwargs):
#     def _(half, level=1):
#     def __(level):
# 
# Path: attitude/error/axes.py
# def sampling_axes(fit, **kw):
#     """
#     Hyperbolic axis lengths based on sample-size
#     normal statistics.
# 
#     Note: legacy method that simply wraps the
#     `statistical_axes` function.
#     """
#     return statistical_axes(fit, method='sampling', **kw)
# 
# Path: attitude/geom/transform.py
# def rotate_2D(angle):
#     """
#     Returns a 2x2 transformation matrix to rotate
#     by an angle in two dimensions
#     """
#     return N.array([[N.cos(angle),-N.sin(angle)],
#                     [N.sin(angle),N.cos(angle)]])


# Path: attitude/display/stereonet.py
import numpy as N
import mplstereonet.stereonet_math as M
from matplotlib.path import Path
from matplotlib.patches import PathPatch
from ..orientation.reconstructed import ReconstructedPlane
from ..stereonet import plane_errors, ellipse, dot, error_ellipse, normal_errors
from ..error.axes import sampling_axes
from ..geom.transform import rotate_2D

            lonlat = lonlat[::-1]
        vertices += list(lonlat)
        codes.append(Path.MOVETO)
        codes += [Path.LINETO]*(n-1)

    plot_patch(ax, vertices, codes, **kwargs)

def pole_error(ax, fit, **kwargs):
    """
    Plot the error to the pole to a plane on a `mplstereonet`
    axis object.
    """
    ell = normal_errors(fit.axes, fit.covariance_matrix)
    lonlat = N.array(ell)
    lonlat[:,0] *= -1
    n = len(lonlat)
    codes = [Path.MOVETO]
    codes += [Path.LINETO]*(n-1)
    vertices = list(lonlat)
    plot_patch(ax, vertices, codes, **kwargs)

def uncertain_pole(ax, *args, **kwargs):
    """
    Min and max angular errors are symmetrical and
    thus should be doubled.
    """
    fit = ReconstructedPlane(*args)
    return pole_error(ax, fit, **kwargs)

def uncertain_plane(ax, *args, **kwargs):

    fit = ReconstructedPlane(*args)