# Path: attitude/display/hyperbola.py
# class HyperbolicErrors(object):
#     """
#     A class to simplify plotting and animation of hyperbolic error
#     areas that are orthogonal to the fitted plane.
#     `ax.fill_between` cannot be used for these (unless
#     the plane is flat), because the coordinate system
#     is rotated.
#     """
#     def __init__(self, *args, **kwargs):
#         """Wraps `hyperbolic_errors` function."""
#         if len(args):
#             self.data = hyperbolic_errors(*args,**kwargs)
#         else:
#             self.data = None
# 
#     def __setup_hyperbola(self, *args,**kwargs):
#         self.args = args
#         self.kwargs = kwargs
# 
# 
#     def __construct_errors(self):
#         pass
# 
# 
#     def plot(self, ax,**kw):
#         _ec = kw.get("color","black")
#         _ec = kw.get("fc",_ec)
#         _ec = kw.get("facecolor",_ec)
#         _ec = kw.pop("ec",_ec)
#         kw['edgecolor'] = kw.pop("edgecolor",_ec)
#         #self.n, = ax.plot([],[], '-', **kw)
#         patch = Polygon([[0,0]], **kw)
#         self.poly = ax.add_patch(patch)
#         if self.data is not None:
#             self.__set_plot_data(self.data)
# 
#     def plot_nominal(self, ax, *args, **kw):
#         ax.plot(*self.data[0],*args, **kw)
# 
#     def update_data(self, *args, **kwargs):
#         self.data = hyperbolic_errors(*args,**kwargs)
#         self.__set_plot_data(self.data)
# 
#     def __set_plot_data(self,n):
#         coords = N.concatenate((n[1],n[2]),axis=1).T
#         self.poly.set_xy(coords)
# 
# 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)
# 
# def noise_axes(fit, **kw):
#     """
#     Hyperbolic axis lengths based on noise statistics.
# 
#     Note: legacy method that simply wraps the
#     `statistical_axes` function.
#     """
#     return statistical_axes(fit, method='noise', **kw)
# 
# Path: attitude/geom/util.py
# def vector(*args):
#     """
#     A single vector in any coordinate basis,
#     as a numpy array.
#     """
#     return N.array(args)
# 
# def plane(normal,offset=0):
#     # This only works in Hessian-Normal form
#     return N.append(normal,offset).view(Plane)


from mplstereonet.stereonet_math import line, pole
from matplotlib.patches import Polygon
from matplotlib.gridspec import GridSpec
from matplotlib.ticker import FuncFormatter
from matplotlib.pyplot import subplots
from ..display.hyperbola import HyperbolicErrors
from ..error.axes import sampling_axes, noise_axes
from ..geom.util import vector,plane
import logging
import numpy as N

    hyp = sampling_axes(pca)
    vertical = vector(0,0,1)

    for i, (title,ax,(a,b),ylabel) in enumerate(
            zip(titles,axes, [(0,1),(0,2),(1,2)],ylabels)):

        kw = dict(linewidth=2, alpha=0.5)
        bounds = minmax[a]

        if b != 2:
            ax.plot(bounds,(0,0), c=colors[a], **kw)
            ax.plot((0,0),minmax[b], c=colors[b], **kw)
        else:
            ax.plot(bounds, (0,0), c=colors[a], **kw)
            v0 = N.zeros(3)
            v0[a] = 1
            axes = N.array([v0,vertical])

            ax_ = (axes@N.diag(hyp)@axes.T).T
            ax_ = N.sqrt(ax_)
            l1 = N.linalg.norm(ax_[:-1])
            l2 = N.linalg.norm(ax_[-1])
            ang_error = 2*N.degrees(N.arctan2(l2,l1))

            title += ": {:2f} m, angular error (95% CI): {:.2f}º".format(lengths[a], ang_error)

            bounds = minmax[0]
            x_ = N.linspace(bounds[0]*1.2,bounds[1]*1.2,100)


# Path: attitude/display/hyperbola.py
# class HyperbolicErrors(object):
#     """
#     A class to simplify plotting and animation of hyperbolic error
#     areas that are orthogonal to the fitted plane.
#     `ax.fill_between` cannot be used for these (unless
#     the plane is flat), because the coordinate system
#     is rotated.
#     """
#     def __init__(self, *args, **kwargs):
#         """Wraps `hyperbolic_errors` function."""
#         if len(args):
#             self.data = hyperbolic_errors(*args,**kwargs)
#         else:
#             self.data = None
# 
#     def __setup_hyperbola(self, *args,**kwargs):
#         self.args = args
#         self.kwargs = kwargs
# 
# 
#     def __construct_errors(self):
#         pass
# 
# 
#     def plot(self, ax,**kw):
#         _ec = kw.get("color","black")
#         _ec = kw.get("fc",_ec)
#         _ec = kw.get("facecolor",_ec)
#         _ec = kw.pop("ec",_ec)
#         kw['edgecolor'] = kw.pop("edgecolor",_ec)
#         #self.n, = ax.plot([],[], '-', **kw)
#         patch = Polygon([[0,0]], **kw)
#         self.poly = ax.add_patch(patch)
#         if self.data is not None:
#             self.__set_plot_data(self.data)
# 
#     def plot_nominal(self, ax, *args, **kw):
#         ax.plot(*self.data[0],*args, **kw)
# 
#     def update_data(self, *args, **kwargs):
#         self.data = hyperbolic_errors(*args,**kwargs)
#         self.__set_plot_data(self.data)
# 
#     def __set_plot_data(self,n):
#         coords = N.concatenate((n[1],n[2]),axis=1).T
#         self.poly.set_xy(coords)
# 
# 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)
# 
# def noise_axes(fit, **kw):
#     """
#     Hyperbolic axis lengths based on noise statistics.
# 
#     Note: legacy method that simply wraps the
#     `statistical_axes` function.
#     """
#     return statistical_axes(fit, method='noise', **kw)
# 
# Path: attitude/geom/util.py
# def vector(*args):
#     """
#     A single vector in any coordinate basis,
#     as a numpy array.
#     """
#     return N.array(args)
# 
# def plane(normal,offset=0):
#     # This only works in Hessian-Normal form
#     return N.append(normal,offset).view(Plane)


# Path: attitude/display/pca_aligned.py
from mplstereonet.stereonet_math import line, pole
from matplotlib.patches import Polygon
from matplotlib.gridspec import GridSpec
from matplotlib.ticker import FuncFormatter
from matplotlib.pyplot import subplots
from ..display.hyperbola import HyperbolicErrors
from ..error.axes import sampling_axes, noise_axes
from ..geom.util import vector,plane
import logging
import numpy as N


    hyp = sampling_axes(pca)
    vertical = vector(0,0,1)

    for i, (title,ax,(a,b),ylabel) in enumerate(
            zip(titles,axes, [(0,1),(0,2),(1,2)],ylabels)):

        kw = dict(linewidth=2, alpha=0.5)
        bounds = minmax[a]

        if b != 2:
            ax.plot(bounds,(0,0), c=colors[a], **kw)
            ax.plot((0,0),minmax[b], c=colors[b], **kw)
        else:
            ax.plot(bounds, (0,0), c=colors[a], **kw)
            v0 = N.zeros(3)
            v0[a] = 1
            axes = N.array([v0,vertical])

            ax_ = (axes@N.diag(hyp)@axes.T).T
            ax_ = N.sqrt(ax_)
            l1 = N.linalg.norm(ax_[:-1])
            l2 = N.linalg.norm(ax_[-1])
            ang_error = 2*N.degrees(N.arctan2(l2,l1))

            title += ": {:2f} m, angular error (95% CI): {:.2f}º".format(lengths[a], ang_error)

            bounds = minmax[0]
            x_ = N.linspace(bounds[0]*1.2,bounds[1]*1.2,100)


            err = HyperbolicErrors(hyp,x_,axes=axes)