# encoding: utf-8
"""Event loop integration for the ZeroMQ-based kernels.
"""

#-----------------------------------------------------------------------------
#  Copyright (C) 2011  The IPython Development Team

#  Distributed under the terms of the BSD License.  The full license is in
#  the file COPYING, distributed as part of this software.
#-----------------------------------------------------------------------------

#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------

import os
import sys

# System library imports
import zmq

# Local imports
from IPython.config.application import Application
from IPython.utils import io

#------------------------------------------------------------------------------
# Eventloops for integrating the Kernel into different GUIs
#------------------------------------------------------------------------------

def _on_os_x_10_9():
    import platform
    from distutils.version import LooseVersion as V
    return sys.platform == 'darwin' and V(platform.mac_ver()[0]) >= V('10.9')

def _notify_stream_qt(kernel, stream):

    from IPython.external.qt_for_kernel import QtCore

    if _on_os_x_10_9() and kernel._darwin_app_nap:
        from IPython.external.appnope import nope_scope as context
    else:
        from IPython.core.interactiveshell import NoOpContext as context

    def process_stream_events():
        while stream.getsockopt(zmq.EVENTS) & zmq.POLLIN:
            with context():
                kernel.do_one_iteration()

    fd = stream.getsockopt(zmq.FD)
    notifier = QtCore.QSocketNotifier(fd, QtCore.QSocketNotifier.Read, kernel.app)
    notifier.activated.connect(process_stream_events)

def loop_qt4(kernel):
    """Start a kernel with PyQt4 event loop integration."""

    from IPython.lib.guisupport import get_app_qt4, start_event_loop_qt4

    kernel.app = get_app_qt4([" "])
    kernel.app.setQuitOnLastWindowClosed(False)

    for s in kernel.shell_streams:
        _notify_stream_qt(kernel, s)

    start_event_loop_qt4(kernel.app)

def loop_qt5(kernel):
    """Start a kernel with PyQt5 event loop integration"""
    os.environ['QT_API'] = 'pyqt5'
    return loop_qt4(kernel)

def loop_wx(kernel):
    """Start a kernel with wx event loop support."""

    import wx
    from IPython.lib.guisupport import start_event_loop_wx

    if _on_os_x_10_9() and kernel._darwin_app_nap:
        # we don't hook up App Nap contexts for Wx,
        # just disable it outright.
        from IPython.external.appnope import nope
        nope()

    doi = kernel.do_one_iteration
     # Wx uses milliseconds
    poll_interval = int(1000*kernel._poll_interval)

    # We have to put the wx.Timer in a wx.Frame for it to fire properly.
    # We make the Frame hidden when we create it in the main app below.
    class TimerFrame(wx.Frame):
        def __init__(self, func):
            wx.Frame.__init__(self, None, -1)
            self.timer = wx.Timer(self)
            # Units for the timer are in milliseconds
            self.timer.Start(poll_interval)
            self.Bind(wx.EVT_TIMER, self.on_timer)
            self.func = func

        def on_timer(self, event):
            self.func()

    # We need a custom wx.App to create our Frame subclass that has the
    # wx.Timer to drive the ZMQ event loop.
    class IPWxApp(wx.App):
        def OnInit(self):
            self.frame = TimerFrame(doi)
            self.frame.Show(False)
            return True

    # The redirect=False here makes sure that wx doesn't replace
    # sys.stdout/stderr with its own classes.
    kernel.app = IPWxApp(redirect=False)

    # The import of wx on Linux sets the handler for signal.SIGINT
    # to 0.  This is a bug in wx or gtk.  We fix by just setting it
    # back to the Python default.
    import signal
    if not callable(signal.getsignal(signal.SIGINT)):
        signal.signal(signal.SIGINT, signal.default_int_handler)

    start_event_loop_wx(kernel.app)

def loop_tk(kernel):
    """Start a kernel with the Tk event loop."""

    try:
        from tkinter import Tk  # Py 3
    except ImportError:
        from Tkinter import Tk  # Py 2
    doi = kernel.do_one_iteration
    # Tk uses milliseconds
    poll_interval = int(1000*kernel._poll_interval)
    # For Tkinter, we create a Tk object and call its withdraw method.
    class Timer(object):
        def __init__(self, func):
            self.app = Tk()
            self.app.withdraw()
            self.func = func

        def on_timer(self):
            self.func()
            self.app.after(poll_interval, self.on_timer)

        def start(self):
            self.on_timer()  # Call it once to get things going.
            self.app.mainloop()

    kernel.timer = Timer(doi)
    kernel.timer.start()

def loop_gtk(kernel):
    """Start the kernel, coordinating with the GTK event loop"""
    from .gui.gtkembed import GTKEmbed

    gtk_kernel = GTKEmbed(kernel)
    gtk_kernel.start()

def loop_cocoa(kernel):
    """Start the kernel, coordinating with the Cocoa CFRunLoop event loop
    via the matplotlib MacOSX backend.
    """
    import matplotlib
    if matplotlib.__version__ < '1.1.0':
        kernel.log.warn(
        "MacOSX backend in matplotlib %s doesn't have a Timer, "
        "falling back on Tk for CFRunLoop integration.  Note that "
        "even this won't work if Tk is linked against X11 instead of "
        "Cocoa (e.g. EPD).  To use the MacOSX backend in the kernel, "
        "you must use matplotlib >= 1.1.0, or a native libtk."
        )
        return loop_tk(kernel)

    from matplotlib.backends.backend_macosx import TimerMac, show

    # scale interval for sec->ms
    poll_interval = int(1000*kernel._poll_interval)

    real_excepthook = sys.excepthook
    def handle_int(etype, value, tb):
        """don't let KeyboardInterrupts look like crashes"""
        if etype is KeyboardInterrupt:
            io.raw_print("KeyboardInterrupt caught in CFRunLoop")
        else:
            real_excepthook(etype, value, tb)

    # add doi() as a Timer to the CFRunLoop
    def doi():
        # restore excepthook during IPython code
        sys.excepthook = real_excepthook
        kernel.do_one_iteration()
        # and back:
        sys.excepthook = handle_int

    t = TimerMac(poll_interval)
    t.add_callback(doi)
    t.start()

    # but still need a Poller for when there are no active windows,
    # during which time mainloop() returns immediately
    poller = zmq.Poller()
    if kernel.control_stream:
        poller.register(kernel.control_stream.socket, zmq.POLLIN)
    for stream in kernel.shell_streams:
        poller.register(stream.socket, zmq.POLLIN)

    while True:
        try:
            # double nested try/except, to properly catch KeyboardInterrupt
            # due to pyzmq Issue #130
            try:
                # don't let interrupts during mainloop invoke crash_handler:
                sys.excepthook = handle_int
                show.mainloop()
                sys.excepthook = real_excepthook
                # use poller if mainloop returned (no windows)
                # scale by extra factor of 10, since it's a real poll
                poller.poll(10*poll_interval)
                kernel.do_one_iteration()
            except:
                raise
        except KeyboardInterrupt:
            # Ctrl-C shouldn't crash the kernel
            io.raw_print("KeyboardInterrupt caught in kernel")
        finally:
            # ensure excepthook is restored
            sys.excepthook = real_excepthook

# mapping of keys to loop functions
loop_map = {
    'qt' : loop_qt4,
    'qt4': loop_qt4,
    'qt5': loop_qt5,
    'inline': None,
    'nbagg': None,
    'osx': loop_cocoa,
    'wx' : loop_wx,
    'tk' : loop_tk,
    'gtk': loop_gtk,
    None : None,
}

def enable_gui(gui, kernel=None):
    """Enable integration with a given GUI"""
    if gui not in loop_map:
        e = "Invalid GUI request %r, valid ones are:%s" % (gui, loop_map.keys())
        raise ValueError(e)
    if kernel is None:
        if Application.initialized():
            kernel = getattr(Application.instance(), 'kernel', None)
        if kernel is None:
            raise RuntimeError("You didn't specify a kernel,"
                " and no IPython Application with a kernel appears to be running."
            )
    loop = loop_map[gui]
    if loop and kernel.eventloop is not None and kernel.eventloop is not loop:
        raise RuntimeError("Cannot activate multiple GUI eventloops")
    kernel.eventloop = loop


# -*- coding: utf-8 -*-
from collections import defaultdict, Counter
import math
import random
from simpleai.search.utils import argmax
import pickle
try:
    import matplotlib.pyplot as plt
    import numpy
except:
    plt = None  # lint:ok
    numpy = None  # lint:ok

def make_at_least_n_times(optimistic_reward, min_n):
    def at_least_n_times_exploration(actions, utilities, temperature, action_counter):
        utilities = [utilities[x] for x in actions]
        for i, utility in enumerate(utilities):
            if action_counter[actions[i]] < min_n:
                utilities[i] = optimistic_reward
        d = dict(zip(actions, utilities))
        uf = lambda action: d[action]
        return argmax(actions, uf)

    return at_least_n_times_exploration

def boltzmann_exploration(actions, utilities, temperature, action_counter):
    '''returns an action with a probability depending on utilities and temperature'''
    utilities = [utilities[x] for x in actions]
    temperature = max(temperature, 0.01)
    _max = max(utilities)
    _min = min(utilities)
    if _max == _min:
        return random.choice(actions)

    utilities = [math.exp(((u - _min) / (_max - _min)) / temperature) for u in utilities]
    probs = [u / sum(utilities) for u in utilities]
    i = 0
    tot = probs[i]
    r = random.random()
    while i < len(actions) and r >= tot:
        i += 1
        tot += probs[i]
    return actions[i]

def make_exponential_temperature(initial_temperature, alpha):
    '''returns a function like initial / exp(n * alpha)'''
    def _function(n):
        try:
            return initial_temperature / math.exp(n * alpha)
        except OverflowError:
            return 0.01
    return _function

class PerformanceCounter(object):

    def __init__(self, learners, names=None):
        self.learners = learners
        for i, learner in enumerate(learners):
            self.update_set_reward(learner)
            learner.accumulated_rewards = []
            learner.known_states = []
            learner.temperatures = []
            if names is None:
                learner.name = 'Learner %d' % i
            else:
                learner.name = names[i]

    def update_set_reward(self, learner):
        def set_reward(reward, terminal=False):
            if terminal:
                if len(learner.accumulated_rewards) > 0:
                    learner.accumulated_rewards.append(learner.accumulated_rewards[-1] + reward)
                else:
                    learner.accumulated_rewards.append(reward)
                learner.known_states.append(len(learner.Q))
                learner.temperatures.append(learner.temperature_function(learner.trials))
            learner.old_set_reward(reward, terminal)
        learner.old_set_reward = learner.set_reward
        learner.set_reward = set_reward

    def _make_plot(self, ax, data_name):
        for learner in self.learners:
            data = numpy.array(getattr(learner, data_name))
            ax.plot(numpy.arange(len(data)), data, label=learner.name)
        nice_name = data_name.replace('_', ' ').capitalize()
        ax.set_title(nice_name)
        ax.legend()

    def show_statistics(self):
        f, (ax1, ax2, ax3) = plt.subplots(3, 1, sharex=True)
        self._make_plot(ax1, 'accumulated_rewards')
        self._make_plot(ax2, 'known_states')
        self._make_plot(ax3, 'temperatures')
        plt.show()

class RLProblem(object):

    def actions(self, state):
        '''Returns the actions available to perform from `state`.
           The returned value is an iterable over actions.
        '''
        raise NotImplementedError()

    def update_state(self, percept, agent):
        'Override this method if you need to clean perception to a given agent'
        return percept

def inverse(n):
    if n == 0:
        return 1
    return 1.0 / n

def state_default():
    return defaultdict(int)

class QLearner(object):

    def __init__(self, problem, temperature_function=inverse,
                 discount_factor=1,
                 exploration_function=boltzmann_exploration,
                 learning_rate=inverse):

        self.Q = defaultdict(state_default)
        self.problem = problem
        self.discount_factor = discount_factor
        self.temperature_function = temperature_function
        self.exploration_function = exploration_function
        self.learning_rate = learning_rate

        self.last_state = None
        self.last_action = None
        self.last_reward = None
        self.counter = defaultdict(Counter)
        self.trials = 0

    def set_reward(self, reward, terminal=False):
        self.last_reward = reward
        if terminal:
            self.trials += 1
            self.Q[self.last_state][self.last_action] = reward

    def program(self, percept):
        s = self.last_state
        a = self.last_action

        state = self.problem.update_state(percept, self)
        actions = self.problem.actions(state)

        if len(actions) > 0:
            current_action = self.exploration_function(actions, self.Q[state],
                                                       self.temperature_function(self.trials),
                                                       self.counter[state])
        else:
            current_action = None

        if s is not None and current_action:
            self.counter[s][a] += 1
            self.update_rule(s, a, self.last_reward, state, current_action)

        self.last_state = state
        self.last_action = current_action
        return current_action

    def update_rule(self, s, a, r, cs, ca):
        raise NotImplementedError

    def dump(self, path):
        self.temperature_function = inverse
        with open(path, 'wb') as f:
            pickle.dump(self, f)

    @classmethod
    def load(self, path):
        with open(path, 'rb') as f:
            return pickle.load(f)

class TDQLearner(QLearner):

    def update_rule(self, s, a, r, cs, ca):
        lr = self.learning_rate(self.counter[s][a])
        self.Q[s][a] += lr * (r + self.discount_factor * max(self.Q[cs].values()) - self.Q[s][a])

class SARSALearner(QLearner):

    def update_rule(self, s, a, r, cs, ca):
        lr = self.learning_rate(self.counter[s][a])
        self.Q[s][a] += lr * (r + self.discount_factor * self.Q[cs][ca] - self.Q[s][a])


#!/usr/bin/env python
"""A simple viewer for Jones patterns for dual-polarized representations.
"""
import argparse
import numpy
import matplotlib.pyplot as plt

from antpat.reps.sphgridfun.pntsonsphere import ZenHemisphGrid
from antpat.dualpolelem import DualPolElem, jones2gIXR, IXRJ2IXRM
from antpat.reps.hamaker import convLOFARcc2DPE
import antpat.io.filetypes as antfiles

def plotJonesCanonical(theta, phi, jones, dpelemname):
    normalize = True
    dbscale = True
    polarplt = True
    IXRTYPE = 'IXR_J'  # Can be IXR_J or IXR_M

    g, IXRJ = jones2gIXR(jones)
    IXRM = IXRJ2IXRM(IXRJ)
    if IXRTYPE == 'IXR_J':
        IXR = IXRJ
    elif IXRTYPE == 'IXR_J':
        IXR = IXRM
    else:
        raise RuntimeError("""Error: IXR type {} unknown.
                           Known types are IXR_J, IXR_M.""".format(IXRTYPE))

    fig = plt.figure()
    fig.suptitle(dpelemname)
    plt.subplot(121, polar=polarplt)
    if normalize:
        g_max = numpy.max(g)
        g = g/g_max
    if dbscale:
        g = 20*numpy.log10(g)
        # nrlvls = 5
        # g_lvls = numpy.max(g) - 3.0*numpy.arange(nrlvls)
    plt.pcolormesh(phi, numpy.rad2deg(theta), g)
    # plt.contour( phi, numpy.rad2deg(theta), g_dress, levels = g_lvls)
    plt.colorbar()
    plt.title('Amp gain')
    plt.subplot(122, polar=polarplt)
    plt.pcolormesh(phi, numpy.rad2deg(theta), 10*numpy.log10(IXR))
    plt.colorbar()
    plt.title('IXR_J')
    plt.show()

def plotFFpat():
    from antpat.reps.sphgridfun import tvecfun
    for polchan in [0, 1]:
        E_th = jones[:, :, polchan, 0].squeeze()
        E_ph = jones[:, :, polchan, 1].squeeze()
        tvecfun.plotvfonsph(THETA, PHI, E_th, E_ph, args.freq,
                            vcoordlist=['Ludwig3'], projection='orthographic')

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("freq", type=float,
                        help="Frequency in Hertz")
    parser.add_argument("filename", help="""
        Filename of dual-polarization FF, Hamaker-Arts format,
        or a single-polarization FF (p-channel)""")
    parser.add_argument("filename_q", nargs='?',
                        help="""
                        Filename of second (q-channel) single-polarization FF.
                        """)
    args = parser.parse_args()

    if args.filename.endswith(antfiles.HamArtsuffix):
        hp = convLOFARcc2DPE(args.filename, [args.freq])
    elif args.filename.endswith(antfiles.FEKOsuffix):
        hp = DualPolElem()
        hp.load_ffes(args.filename, args.filename_q)
    else:
        raise RuntimeError("dual-pol pattern file type not known")
    THETA, PHI = ZenHemisphGrid()
    jones = hp.getJonesAlong([args.freq], (THETA, PHI))
    plotFFpat()
    # plotJonesCanonical(THETA, PHI, jones, os.path.basename(args.filename)
    #                    + ' (' + str(args.freq/1e6) + ' MHz)')


"""
This module contains all the 2D line class which can draw with a
variety of line styles, markers and colors.
"""

# TODO: expose cap and join style attrs
from __future__ import division

import numpy as np
from numpy import ma
from matplotlib import verbose
import artist
from artist import Artist
from cbook import iterable, is_string_like, is_numlike, ls_mapper, dedent,\
flatten
from colors import colorConverter
from path import Path
from transforms import Affine2D, Bbox, TransformedPath, IdentityTransform

from matplotlib import rcParams
# special-purpose marker identifiers:
(TICKLEFT, TICKRIGHT, TICKUP, TICKDOWN,
    CARETLEFT, CARETRIGHT, CARETUP, CARETDOWN) = range(8)

# COVERAGE NOTE: Never called internally or from examples
def unmasked_index_ranges(mask, compressed = True):
    warnings.warn("Import this directly from matplotlib.cbook",
                   DeprecationWarning)
    # Warning added 2008/07/22
    from matplotlib.cbook import unmasked_index_ranges as _unmasked_index_ranges
    return _unmasked_index_ranges(mask, compressed=compressed)

def segment_hits(cx, cy, x, y, radius):
    """
    Determine if any line segments are within radius of a
    point. Returns the list of line segments that are within that
    radius.
    """
    # Process single points specially
    if len(x) < 2:
        res, = np.nonzero( (cx - x)**2 + (cy - y)**2 <= radius**2 )
        return res

    # We need to lop the last element off a lot.
    xr,yr = x[:-1],y[:-1]

    # Only look at line segments whose nearest point to C on the line
    # lies within the segment.
    dx,dy = x[1:]-xr, y[1:]-yr
    Lnorm_sq = dx**2+dy**2    # Possibly want to eliminate Lnorm==0
    u = ( (cx-xr)*dx + (cy-yr)*dy )/Lnorm_sq
    candidates = (u>=0) & (u<=1)
    #if any(candidates): print "candidates",xr[candidates]

    # Note that there is a little area near one side of each point
    # which will be near neither segment, and another which will
    # be near both, depending on the angle of the lines.  The
    # following radius test eliminates these ambiguities.
    point_hits = (cx - x)**2 + (cy - y)**2 <= radius**2
    #if any(point_hits): print "points",xr[candidates]
    candidates = candidates & ~(point_hits[:-1] | point_hits[1:])

    # For those candidates which remain, determine how far they lie away
    # from the line.
    px,py = xr+u*dx,yr+u*dy
    line_hits = (cx-px)**2 + (cy-py)**2 <= radius**2
    #if any(line_hits): print "lines",xr[candidates]
    line_hits = line_hits & candidates
    points, = point_hits.ravel().nonzero()
    lines, = line_hits.ravel().nonzero()
    #print points,lines
    return np.concatenate((points,lines))

class Line2D(Artist):
    """
    A line - the line can have both a solid linestyle connecting all
    the vertices, and a marker at each vertex.  Additionally, the
    drawing of the solid line is influenced by the drawstyle, eg one
    can create "stepped" lines in various styles.

    """
    lineStyles = _lineStyles =  { # hidden names deprecated
        '-'          : '_draw_solid',
        '--'         : '_draw_dashed',
        '-.'         : '_draw_dash_dot',
        ':'          : '_draw_dotted',
        'None'       : '_draw_nothing',
        ' '          : '_draw_nothing',
        ''           : '_draw_nothing',
    }

    _drawStyles_l = {
        'default'    : '_draw_lines',
        'steps-mid'  : '_draw_steps_mid',
        'steps-pre'  : '_draw_steps_pre',
        'steps-post' : '_draw_steps_post',
    }

    _drawStyles_s = {
        'steps'      : '_draw_steps_pre',
    }
    drawStyles = {}
    drawStyles.update(_drawStyles_l)
    drawStyles.update(_drawStyles_s)

    markers = _markers =  {  # hidden names deprecated
        '.'  : '_draw_point',
        ','  : '_draw_pixel',
        'o'  : '_draw_circle',
        'v'  : '_draw_triangle_down',
        '^'  : '_draw_triangle_up',
        '<'  : '_draw_triangle_left',
        '>'  : '_draw_triangle_right',
        '1'  : '_draw_tri_down',
        '2'  : '_draw_tri_up',
        '3'  : '_draw_tri_left',
        '4'  : '_draw_tri_right',
        's'  : '_draw_square',
        'p'  : '_draw_pentagon',
        '*'  : '_draw_star',
        'h'  : '_draw_hexagon1',
        'H'  : '_draw_hexagon2',
        '+'  : '_draw_plus',
        'x'  : '_draw_x',
        'D'  : '_draw_diamond',
        'd'  : '_draw_thin_diamond',
        '|'  : '_draw_vline',
        '_'  : '_draw_hline',
        TICKLEFT    : '_draw_tickleft',
        TICKRIGHT   : '_draw_tickright',
        TICKUP      : '_draw_tickup',
        TICKDOWN    : '_draw_tickdown',
        CARETLEFT   : '_draw_caretleft',
        CARETRIGHT  : '_draw_caretright',
        CARETUP     : '_draw_caretup',
        CARETDOWN   : '_draw_caretdown',
        'None' : '_draw_nothing',
        ' ' : '_draw_nothing',
        '' : '_draw_nothing',
    }

    filled_markers = ('o', '^', 'v', '<', '>',
                        's', 'd', 'D', 'h', 'H', 'p', '*')

    zorder = 2
    validCap = ('butt', 'round', 'projecting')
    validJoin =   ('miter', 'round', 'bevel')

    def __str__(self):
        if self._label != "":
            return "Line2D(%s)"%(self._label)
        elif hasattr(self, '_x') and len(self._x) > 3:
            return "Line2D((%g,%g),(%g,%g),...,(%g,%g))"\
                %(self._x[0],self._y[0],self._x[0],self._y[0],self._x[-1],self._y[-1])
        elif hasattr(self, '_x'):
            return "Line2D(%s)"\
                %(",".join(["(%g,%g)"%(x,y) for x,y in zip(self._x,self._y)]))
        else:
            return "Line2D()"

    def __init__(self, xdata, ydata,
                 linewidth       = None, # all Nones default to rc
                 linestyle       = None,
                 color           = None,
                 marker          = None,
                 markersize      = None,
                 markeredgewidth = None,
                 markeredgecolor = None,
                 markerfacecolor = None,
                 antialiased     = None,
                 dash_capstyle   = None,
                 solid_capstyle  = None,
                 dash_joinstyle  = None,
                 solid_joinstyle = None,
                 pickradius      = 5,
                 drawstyle       = None,
                 **kwargs
                 ):
        """
        Create a :class:`~matplotlib.lines.Line2D` instance with *x*
        and *y* data in sequences *xdata*, *ydata*.

        The kwargs are :class:`~matplotlib.lines.Line2D` properties:

        %(Line2D)s

        See :meth:`set_linestyle` for a decription of the line styles,
        :meth:`set_marker` for a description of the markers, and
        :meth:`set_drawstyle` for a description of the draw styles.

        """
        Artist.__init__(self)

        #convert sequences to numpy arrays
        if not iterable(xdata):
            raise RuntimeError('xdata must be a sequence')
        if not iterable(ydata):
            raise RuntimeError('ydata must be a sequence')

        if linewidth is None   : linewidth=rcParams['lines.linewidth']

        if linestyle is None   : linestyle=rcParams['lines.linestyle']
        if marker is None      : marker=rcParams['lines.marker']
        if color is None       : color=rcParams['lines.color']

        if markersize is None  : markersize=rcParams['lines.markersize']
        if antialiased is None : antialiased=rcParams['lines.antialiased']
        if dash_capstyle is None : dash_capstyle=rcParams['lines.dash_capstyle']
        if dash_joinstyle is None : dash_joinstyle=rcParams['lines.dash_joinstyle']
        if solid_capstyle is None : solid_capstyle=rcParams['lines.solid_capstyle']
        if solid_joinstyle is None : solid_joinstyle=rcParams['lines.solid_joinstyle']

        if drawstyle is None : drawstyle='default'

        self.set_dash_capstyle(dash_capstyle)
        self.set_dash_joinstyle(dash_joinstyle)
        self.set_solid_capstyle(solid_capstyle)
        self.set_solid_joinstyle(solid_joinstyle)

        self.set_linestyle(linestyle)
        self.set_drawstyle(drawstyle)
        self.set_linewidth(linewidth)
        self.set_color(color)
        self.set_marker(marker)
        self.set_antialiased(antialiased)
        self.set_markersize(markersize)
        self._dashSeq = None

        self.set_markerfacecolor(markerfacecolor)
        self.set_markeredgecolor(markeredgecolor)
        self.set_markeredgewidth(markeredgewidth)
        self._point_size_reduction = 0.5

        self.verticalOffset = None

        # update kwargs before updating data to give the caller a
        # chance to init axes (and hence unit support)
        self.update(kwargs)
        self.pickradius = pickradius
        if is_numlike(self._picker):
            self.pickradius = self._picker

        self._xorig = np.asarray([])
        self._yorig = np.asarray([])
        self._invalid = True
        self.set_data(xdata, ydata)

    def contains(self, mouseevent):
        """
        Test whether the mouse event occurred on the line.  The pick
        radius determines the precision of the location test (usually
        within five points of the value).  Use
        :meth:`~matplotlib.lines.Line2D.get_pickradius` or
        :meth:`~matplotlib.lines.Line2D.set_pickradius` to view or
        modify it.

        Returns *True* if any values are within the radius along with
        ``{'ind': pointlist}``, where *pointlist* is the set of points
        within the radius.

        TODO: sort returned indices by distance
        """
        if callable(self._contains): return self._contains(self,mouseevent)

        if not is_numlike(self.pickradius):
            raise ValueError,"pick radius should be a distance"

        # Make sure we have data to plot
        if self._invalid:
            self.recache()
        if len(self._xy)==0: return False,{}

        # Convert points to pixels
        path, affine = self._transformed_path.get_transformed_path_and_affine()
        path = affine.transform_path(path)
        xy = path.vertices
        xt = xy[:, 0]
        yt = xy[:, 1]

        # Convert pick radius from points to pixels
        if self.figure == None:
            warning.warn('no figure set when check if mouse is on line')
            pixels = self.pickradius
        else:
            pixels = self.figure.dpi/72. * self.pickradius

        # Check for collision
        if self._linestyle in ['None',None]:
            # If no line, return the nearby point(s)
            d = (xt-mouseevent.x)**2 + (yt-mouseevent.y)**2
            ind, = np.nonzero(np.less_equal(d, pixels**2))
        else:
            # If line, return the nearby segment(s)
            ind = segment_hits(mouseevent.x,mouseevent.y,xt,yt,pixels)

        # Debugging message
        if False and self._label != u'':
            print "Checking line",self._label,"at",mouseevent.x,mouseevent.y
            print 'xt', xt
            print 'yt', yt
            #print 'dx,dy', (xt-mouseevent.x)**2., (yt-mouseevent.y)**2.
            print 'ind',ind

        # Return the point(s) within radius
        return len(ind)>0,dict(ind=ind)

    def get_pickradius(self):
        'return the pick radius used for containment tests'
        return self.pickradius

    def setpickradius(self,d):
        """Sets the pick radius used for containment tests

        ACCEPTS: float distance in points
        """
        self.pickradius = d

    def set_picker(self,p):
        """Sets the event picker details for the line.

        ACCEPTS: float distance in points or callable pick function
        ``fn(artist, event)``
        """
        if callable(p):
            self._contains = p
        else:
            self.pickradius = p
        self._picker = p

    def get_window_extent(self, renderer):
        bbox = Bbox.unit()
        bbox.update_from_data_xy(self.get_transform().transform(self.get_xydata()),
                                 ignore=True)
        # correct for marker size, if any
        if self._marker is not None:
            ms = (self._markersize / 72.0 * self.figure.dpi) * 0.5
            bbox = bbox.padded(ms)
        return bbox

    def set_axes(self, ax):
        Artist.set_axes(self, ax)
        if ax.xaxis is not None:
            self._xcid = ax.xaxis.callbacks.connect('units', self.recache)
        if ax.yaxis is not None:
            self._ycid = ax.yaxis.callbacks.connect('units', self.recache)
    set_axes.__doc__ = Artist.set_axes.__doc__

    def set_data(self, *args):
        """
        Set the x and y data

        ACCEPTS: 2D array
        """
        if len(args)==1:
            x, y = args[0]
        else:
            x, y = args

        not_masked = 0
        if not ma.isMaskedArray(x):
            x = np.asarray(x)
            not_masked += 1
        if not ma.isMaskedArray(y):
            y = np.asarray(y)
            not_masked += 1

        if (not_masked < 2 or
            (x is not self._xorig and
             (x.shape != self._xorig.shape or np.any(x != self._xorig))) or
            (y is not self._yorig and
              (y.shape != self._yorig.shape or np.any(y != self._yorig)))):
            self._xorig = x
            self._yorig = y
            self._invalid = True

    def recache(self):
        #if self.axes is None: print 'recache no axes'
        #else: print 'recache units', self.axes.xaxis.units, self.axes.yaxis.units
        if ma.isMaskedArray(self._xorig) or ma.isMaskedArray(self._yorig):
            x = ma.asarray(self.convert_xunits(self._xorig), float)
            y = ma.asarray(self.convert_yunits(self._yorig), float)
            x = ma.ravel(x)
            y = ma.ravel(y)
        else:
            x = np.asarray(self.convert_xunits(self._xorig), float)
            y = np.asarray(self.convert_yunits(self._yorig), float)
            x = np.ravel(x)
            y = np.ravel(y)

        if len(x)==1 and len(y)>1:
            x = x * np.ones(y.shape, float)
        if len(y)==1 and len(x)>1:
            y = y * np.ones(x.shape, float)

        if len(x) != len(y):
            raise RuntimeError('xdata and ydata must be the same length')

        x = x.reshape((len(x), 1))
        y = y.reshape((len(y), 1))

        if ma.isMaskedArray(x) or ma.isMaskedArray(y):
            self._xy = ma.concatenate((x, y), 1)
        else:
            self._xy = np.concatenate((x, y), 1)
        self._x = self._xy[:, 0] # just a view
        self._y = self._xy[:, 1] # just a view

        # Masked arrays are now handled by the Path class itself
        self._path = Path(self._xy)
        self._transformed_path = TransformedPath(self._path, self.get_transform())

        self._invalid = False

    def set_transform(self, t):
        """
        set the Transformation instance used by this artist

        ACCEPTS: a :class:`matplotlib.transforms.Transform` instance
        """
        Artist.set_transform(self, t)
        self._invalid = True
        # self._transformed_path = TransformedPath(self._path, self.get_transform())

    def _is_sorted(self, x):
        "return true if x is sorted"
        if len(x)<2: return 1
        return np.alltrue(x[1:]-x[0:-1]>=0)

    def draw(self, renderer):
        if self._invalid:
            self.recache()

        renderer.open_group('line2d')

        if not self._visible: return
        gc = renderer.new_gc()
        self._set_gc_clip(gc)

        gc.set_foreground(self._color)
        gc.set_antialiased(self._antialiased)
        gc.set_linewidth(self._linewidth)
        gc.set_alpha(self._alpha)
        if self.is_dashed():
            cap = self._dashcapstyle
            join = self._dashjoinstyle
        else:
            cap = self._solidcapstyle
            join = self._solidjoinstyle
        gc.set_joinstyle(join)
        gc.set_capstyle(cap)
        gc.set_snap(self.get_snap())

        funcname = self._lineStyles.get(self._linestyle, '_draw_nothing')
        if funcname != '_draw_nothing':
            tpath, affine = self._transformed_path.get_transformed_path_and_affine()
            self._lineFunc = getattr(self, funcname)
            funcname = self.drawStyles.get(self._drawstyle, '_draw_lines')
            drawFunc = getattr(self, funcname)
            drawFunc(renderer, gc, tpath, affine.frozen())

        if self._marker is not None:
            gc = renderer.new_gc()
            self._set_gc_clip(gc)
            gc.set_foreground(self.get_markeredgecolor())
            gc.set_linewidth(self._markeredgewidth)
            gc.set_alpha(self._alpha)
            funcname = self._markers.get(self._marker, '_draw_nothing')
            if funcname != '_draw_nothing':
                tpath, affine = self._transformed_path.get_transformed_points_and_affine()
                markerFunc = getattr(self, funcname)
                markerFunc(renderer, gc, tpath, affine.frozen())

        renderer.close_group('line2d')

    def get_antialiased(self): return self._antialiased
    def get_color(self): return self._color
    def get_drawstyle(self): return self._drawstyle
    def get_linestyle(self): return self._linestyle

    def get_linewidth(self): return self._linewidth
    def get_marker(self): return self._marker

    def get_markeredgecolor(self):
        if (is_string_like(self._markeredgecolor) and
            self._markeredgecolor == 'auto'):
            if self._marker in self.filled_markers:
                return 'k'
            else:
                return self._color
        else:
            return self._markeredgecolor

        return self._markeredgecolor
    def get_markeredgewidth(self): return self._markeredgewidth

    def get_markerfacecolor(self):
        if (self._markerfacecolor is None or
            (is_string_like(self._markerfacecolor) and
             self._markerfacecolor.lower()=='none') ):
            return self._markerfacecolor
        elif (is_string_like(self._markerfacecolor) and
              self._markerfacecolor.lower() == 'auto'):
            return self._color
        else:
            return self._markerfacecolor

    def get_markersize(self): return self._markersize

    def get_data(self, orig=True):
        """
        Return the xdata, ydata.

        If *orig* is *True*, return the original data
        """
        return self.get_xdata(orig=orig), self.get_ydata(orig=orig)

    def get_xdata(self, orig=True):
        """
        Return the xdata.

        If *orig* is *True*, return the original data, else the
        processed data.
        """
        if orig:
            return self._xorig
        if self._invalid:
            self.recache()
        return self._x

    def get_ydata(self, orig=True):
        """
        Return the ydata.

        If *orig* is *True*, return the original data, else the
        processed data.
        """
        if orig:
            return self._yorig
        if self._invalid:
            self.recache()
        return self._y

    def get_path(self):
        """
        Return the :class:`~matplotlib.path.Path` object associated
        with this line.
        """
        if self._invalid:
            self.recache()
        return self._path

    def get_xydata(self):
        """
        Return the *xy* data as a Nx2 numpy array.
        """
        if self._invalid:
            self.recache()
        return self._xy

    def set_antialiased(self, b):
        """
        True if line should be drawin with antialiased rendering

        ACCEPTS: [True | False]
        """
        self._antialiased = b

    def set_color(self, color):
        """
        Set the color of the line

        ACCEPTS: any matplotlib color
        """
        self._color = color

    def set_drawstyle(self, drawstyle):
        """
        Set the drawstyle of the plot

        'default' connects the points with lines. The steps variants
        produce step-plots. 'steps' is equivalent to 'steps-pre' and
        is maintained for backward-compatibility.

        ACCEPTS: [ 'default' | 'steps' | 'steps-pre' | 'steps-mid' | 'steps-post' ]
        """
        self._drawstyle = drawstyle

    def set_linewidth(self, w):
        """
        Set the line width in points

        ACCEPTS: float value in points
        """
        self._linewidth = w

    def set_linestyle(self, linestyle):
        """
        Set the linestyle of the line (also accepts drawstyles)

        ================    =================
        linestyle           description
        ================    =================
        '-'                 solid
        '--'                dashed
        '-.'                dash_dot
        ':'                 dotted
        'None'              draw nothing
        ' '                 draw nothing
        ''                  draw nothing
        ================    =================

        'steps' is equivalent to 'steps-pre' and is maintained for
        backward-compatibility.

        .. seealso::
            :meth:`set_drawstyle`

        ACCEPTS: [ '-' | '--' | '-.' | ':' | 'None' | ' ' | '' ] and
        any drawstyle in combination with a linestyle, e.g. 'steps--'.
        """

        # handle long drawstyle names before short ones !
        for ds in flatten([k.keys() for k in (self._drawStyles_l,
                self._drawStyles_s)], is_string_like):
            if linestyle.startswith(ds):
                self.set_drawstyle(ds)
                if len(linestyle) > len(ds):
                    linestyle = linestyle[len(ds):]
                else:
                    linestyle = '-'

        if linestyle not in self._lineStyles:
            if linestyle in ls_mapper:
                linestyle = ls_mapper[linestyle]
            else:
                verbose.report('Unrecognized line style %s, %s' %
                                            (linestyle, type(linestyle)))
        if linestyle in [' ','']:
            linestyle = 'None'
        self._linestyle = linestyle

    def set_marker(self, marker):
        """
        Set the line marker

        ========== ==========================
        marker     description
        ========== ==========================
        '.'        point
        ','        pixel
        'o'        circle
        'v'        triangle_down
        '^'        triangle_up
        '<'        triangle_left
        '>'        triangle_right
        '1'        tri_down
        '2'        tri_up
        '3'        tri_left
        '4'        tri_right
        's'        square
        'p'        pentagon
        '*'        star
        'h'        hexagon1
        'H'        hexagon2
        '+'        plus
        'x'        x
        'D'        diamond
        'd'        thin_diamond
        '|'        vline
        '_'        hline
        TICKLEFT   tickleft
        TICKRIGHT  tickright
        TICKUP     tickup
        TICKDOWN   tickdown
        CARETLEFT  caretleft
        CARETRIGHT caretright
        CARETUP    caretup
        CARETDOWN  caretdown
        'None'     nothing
        ' '        nothing
        ''         nothing
        ========== ==========================

        ACCEPTS: [ '+' | '*' | ',' | '.' | '1' | '2' | '3' | '4'
                 | '<' | '>' | 'D' | 'H' | '^' | '_' | 'd'
                 | 'h' | 'o' | 'p' | 's' | 'v' | 'x' | '|'
                 | TICKUP | TICKDOWN | TICKLEFT | TICKRIGHT
                 | 'None' | ' ' | '' ]

        """
        if marker not in self._markers:
            verbose.report('Unrecognized marker style %s, %s' %
                                            (marker, type(marker)))
        if marker in [' ','']:
            marker = 'None'
        self._marker = marker
        self._markerFunc = self._markers[marker]

    def set_markeredgecolor(self, ec):
        """
        Set the marker edge color

        ACCEPTS: any matplotlib color
        """
        if ec is None :
            ec = 'auto'
        self._markeredgecolor = ec

    def set_markeredgewidth(self, ew):
        """
        Set the marker edge width in points

        ACCEPTS: float value in points
        """
        if ew is None :
            ew = rcParams['lines.markeredgewidth']
        self._markeredgewidth = ew

    def set_markerfacecolor(self, fc):
        """
        Set the marker face color

        ACCEPTS: any matplotlib color
        """
        if fc is None :
            fc = 'auto'
        self._markerfacecolor = fc

    def set_markersize(self, sz):
        """
        Set the marker size in points

        ACCEPTS: float
        """
        self._markersize = sz

    def set_xdata(self, x):
        """
        Set the data np.array for x

        ACCEPTS: 1D array
        """
        x = np.asarray(x)
        self.set_data(x, self._yorig)

    def set_ydata(self, y):
        """
        Set the data np.array for y

        ACCEPTS: 1D array
        """
        y = np.asarray(y)
        self.set_data(self._xorig, y)

    def set_dashes(self, seq):
        """
        Set the dash sequence, sequence of dashes with on off ink in
        points.  If seq is empty or if seq = (None, None), the
        linestyle will be set to solid.

        ACCEPTS: sequence of on/off ink in points
        """
        if seq == (None, None) or len(seq)==0:
            self.set_linestyle('-')
        else:
            self.set_linestyle('--')
        self._dashSeq = seq  # TODO: offset ignored for now

    def _draw_lines(self, renderer, gc, path, trans):
        self._lineFunc(renderer, gc, path, trans)

    def _draw_steps_pre(self, renderer, gc, path, trans):
        vertices = self._xy
        steps = ma.zeros((2*len(vertices)-1, 2), np.float_)

        steps[0::2, 0], steps[1::2, 0] = vertices[:, 0], vertices[:-1, 0]
        steps[0::2, 1], steps[1:-1:2, 1] = vertices[:, 1], vertices[1:, 1]

        path = Path(steps)
        path = path.transformed(self.get_transform())
        self._lineFunc(renderer, gc, path, IdentityTransform())

    def _draw_steps_post(self, renderer, gc, path, trans):
        vertices = self._xy
        steps = ma.zeros((2*len(vertices)-1, 2), np.float_)

        steps[::2, 0], steps[1:-1:2, 0] = vertices[:, 0], vertices[1:, 0]
        steps[0::2, 1], steps[1::2, 1] = vertices[:, 1], vertices[:-1, 1]

        path = Path(steps)
        path = path.transformed(self.get_transform())
        self._lineFunc(renderer, gc, path, IdentityTransform())

    def _draw_steps_mid(self, renderer, gc, path, trans):
        vertices = self._xy
        steps = ma.zeros((2*len(vertices), 2), np.float_)

        steps[1:-1:2, 0] = 0.5 * (vertices[:-1, 0] + vertices[1:, 0])
        steps[2::2, 0] = 0.5 * (vertices[:-1, 0] + vertices[1:, 0])
        steps[0, 0] = vertices[0, 0]
        steps[-1, 0] = vertices[-1, 0]
        steps[0::2, 1], steps[1::2, 1] = vertices[:, 1], vertices[:, 1]

        path = Path(steps)
        path = path.transformed(self.get_transform())
        self._lineFunc(renderer, gc, path, IdentityTransform())

    def _draw_nothing(self, *args, **kwargs):
        pass

    def _draw_solid(self, renderer, gc, path, trans):
        gc.set_linestyle('solid')
        renderer.draw_path(gc, path, trans)

    def _draw_dashed(self, renderer, gc, path, trans):
        gc.set_linestyle('dashed')
        if self._dashSeq is not None:
            gc.set_dashes(0, self._dashSeq)

        renderer.draw_path(gc, path, trans)

    def _draw_dash_dot(self, renderer, gc, path, trans):
        gc.set_linestyle('dashdot')
        renderer.draw_path(gc, path, trans)

    def _draw_dotted(self, renderer, gc, path, trans):
        gc.set_linestyle('dotted')
        renderer.draw_path(gc, path, trans)

    def _draw_point(self, renderer, gc, path, path_trans):
        w = renderer.points_to_pixels(self._markersize) * \
            self._point_size_reduction * 0.5
        gc.set_snap(renderer.points_to_pixels(self._markersize) > 3.0)
        rgbFace = self._get_rgb_face()
        transform = Affine2D().scale(w)
        renderer.draw_markers(
            gc, Path.unit_circle(), transform, path, path_trans,
            rgbFace)

    _draw_pixel_transform = Affine2D().translate(-0.5, -0.5)
    def _draw_pixel(self, renderer, gc, path, path_trans):
        rgbFace = self._get_rgb_face()
        gc.set_snap(False)
        renderer.draw_markers(gc, Path.unit_rectangle(),
                              self._draw_pixel_transform,
                              path, path_trans, rgbFace)

    def _draw_circle(self, renderer, gc, path, path_trans):
        w = renderer.points_to_pixels(self._markersize) * 0.5
        gc.set_snap(renderer.points_to_pixels(self._markersize) > 3.0)
        rgbFace = self._get_rgb_face()
        transform = Affine2D().scale(w, w)
        renderer.draw_markers(
            gc, Path.unit_circle(), transform, path, path_trans,
            rgbFace)

    _triangle_path = Path([[0.0, 1.0], [-1.0, -1.0], [1.0, -1.0], [0.0, 1.0]])
    def _draw_triangle_up(self, renderer, gc, path, path_trans):
        gc.set_snap(renderer.points_to_pixels(self._markersize) >= 5.0)
        offset = 0.5*renderer.points_to_pixels(self._markersize)
        transform = Affine2D().scale(offset, offset)
        rgbFace = self._get_rgb_face()
        renderer.draw_markers(gc, self._triangle_path, transform,
                              path, path_trans, rgbFace)

    def _draw_triangle_down(self, renderer, gc, path, path_trans):
        gc.set_snap(renderer.points_to_pixels(self._markersize) >= 5.0)
        offset = 0.5*renderer.points_to_pixels(self._markersize)
        transform = Affine2D().scale(offset, -offset)
        rgbFace = self._get_rgb_face()
        renderer.draw_markers(gc, self._triangle_path, transform,
                              path, path_trans, rgbFace)

    def _draw_triangle_left(self, renderer, gc, path, path_trans):
        gc.set_snap(renderer.points_to_pixels(self._markersize) >= 5.0)
        offset = 0.5*renderer.points_to_pixels(self._markersize)
        transform = Affine2D().scale(offset, offset).rotate_deg(90)
        rgbFace = self._get_rgb_face()
        renderer.draw_markers(gc, self._triangle_path, transform,
                              path, path_trans, rgbFace)

    def _draw_triangle_right(self, renderer, gc, path, path_trans):
        gc.set_snap(renderer.points_to_pixels(self._markersize) >= 5.0)
        offset = 0.5*renderer.points_to_pixels(self._markersize)
        transform = Affine2D().scale(offset, offset).rotate_deg(-90)
        rgbFace = self._get_rgb_face()
        renderer.draw_markers(gc, self._triangle_path, transform,
                              path, path_trans, rgbFace)

    def _draw_square(self, renderer, gc, path, path_trans):
        gc.set_snap(renderer.points_to_pixels(self._markersize) >= 2.0)
        side = renderer.points_to_pixels(self._markersize)
        transform = Affine2D().translate(-0.5, -0.5).scale(side)
        rgbFace = self._get_rgb_face()
        renderer.draw_markers(gc, Path.unit_rectangle(), transform,
                              path, path_trans, rgbFace)

    def _draw_diamond(self, renderer, gc, path, path_trans):
        gc.set_snap(renderer.points_to_pixels(self._markersize) >= 5.0)
        side = renderer.points_to_pixels(self._markersize)
        transform = Affine2D().translate(-0.5, -0.5).rotate_deg(45).scale(side)
        rgbFace = self._get_rgb_face()
        renderer.draw_markers(gc, Path.unit_rectangle(), transform,
                              path, path_trans, rgbFace)

    def _draw_thin_diamond(self, renderer, gc, path, path_trans):
        gc.set_snap(renderer.points_to_pixels(self._markersize) >= 3.0)
        offset = renderer.points_to_pixels(self._markersize)
        transform = Affine2D().translate(-0.5, -0.5) \
            .rotate_deg(45).scale(offset * 0.6, offset)
        rgbFace = self._get_rgb_face()
        renderer.draw_markers(gc, Path.unit_rectangle(), transform,
                              path, path_trans, rgbFace)

    def _draw_pentagon(self, renderer, gc, path, path_trans):
        gc.set_snap(renderer.points_to_pixels(self._markersize) >= 5.0)
        offset = 0.5 * renderer.points_to_pixels(self._markersize)
        transform = Affine2D().scale(offset)
        rgbFace = self._get_rgb_face()
        renderer.draw_markers(gc, Path.unit_regular_polygon(5), transform,
                              path, path_trans, rgbFace)

    def _draw_star(self, renderer, gc, path, path_trans):
        gc.set_snap(renderer.points_to_pixels(self._markersize) >= 5.0)
        offset = 0.5 * renderer.points_to_pixels(self._markersize)
        transform = Affine2D().scale(offset)
        rgbFace = self._get_rgb_face()
        _starpath = Path.unit_regular_star(5, innerCircle=0.381966)
        renderer.draw_markers(gc, _starpath, transform,
                              path, path_trans, rgbFace)

    def _draw_hexagon1(self, renderer, gc, path, path_trans):
        gc.set_snap(renderer.points_to_pixels(self._markersize) >= 5.0)
        offset = 0.5 * renderer.points_to_pixels(self._markersize)
        transform = Affine2D().scale(offset)
        rgbFace = self._get_rgb_face()
        renderer.draw_markers(gc, Path.unit_regular_polygon(6), transform,
                              path, path_trans, rgbFace)

    def _draw_hexagon2(self, renderer, gc, path, path_trans):
        gc.set_snap(renderer.points_to_pixels(self._markersize) >= 5.0)
        offset = 0.5 * renderer.points_to_pixels(self._markersize)
        transform = Affine2D().scale(offset).rotate_deg(30)
        rgbFace = self._get_rgb_face()
        renderer.draw_markers(gc, Path.unit_regular_polygon(6), transform,
                              path, path_trans, rgbFace)

    _line_marker_path = Path([[0.0, -1.0], [0.0, 1.0]])
    def _draw_vline(self, renderer, gc, path, path_trans):
        gc.set_snap(renderer.points_to_pixels(self._markersize) >= 1.0)
        offset = 0.5*renderer.points_to_pixels(self._markersize)
        transform = Affine2D().scale(offset)
        renderer.draw_markers(gc, self._line_marker_path, transform,
                              path, path_trans)

    def _draw_hline(self, renderer, gc, path, path_trans):
        gc.set_snap(renderer.points_to_pixels(self._markersize) >= 1.0)
        offset = 0.5*renderer.points_to_pixels(self._markersize)
        transform = Affine2D().scale(offset).rotate_deg(90)
        renderer.draw_markers(gc, self._line_marker_path, transform,
                              path, path_trans)

    _tickhoriz_path = Path([[0.0, 0.0], [1.0, 0.0]])
    def _draw_tickleft(self, renderer, gc, path, path_trans):
        gc.set_snap(renderer.points_to_pixels(self._markersize) >= 1.0)
        offset = renderer.points_to_pixels(self._markersize)
        marker_transform = Affine2D().scale(-offset, 1.0)
        renderer.draw_markers(gc, self._tickhoriz_path, marker_transform,
                              path, path_trans)

    def _draw_tickright(self, renderer, gc, path, path_trans):
        gc.set_snap(renderer.points_to_pixels(self._markersize) >= 1.0)
        offset = renderer.points_to_pixels(self._markersize)
        marker_transform = Affine2D().scale(offset, 1.0)
        renderer.draw_markers(gc, self._tickhoriz_path, marker_transform,
                              path, path_trans)

    _tickvert_path = Path([[-0.0, 0.0], [-0.0, 1.0]])
    def _draw_tickup(self, renderer, gc, path, path_trans):
        gc.set_snap(renderer.points_to_pixels(self._markersize) >= 1.0)
        offset = renderer.points_to_pixels(self._markersize)
        marker_transform = Affine2D().scale(1.0, offset)
        renderer.draw_markers(gc, self._tickvert_path, marker_transform,
                              path, path_trans)

    def _draw_tickdown(self, renderer, gc, path, path_trans):
        gc.set_snap(renderer.points_to_pixels(self._markersize) >= 1.0)
        offset = renderer.points_to_pixels(self._markersize)
        marker_transform = Affine2D().scale(1.0, -offset)
        renderer.draw_markers(gc, self._tickvert_path, marker_transform,
                              path, path_trans)

    _plus_path = Path([[-1.0, 0.0], [1.0, 0.0],
                       [0.0, -1.0], [0.0, 1.0]],
                      [Path.MOVETO, Path.LINETO,
                       Path.MOVETO, Path.LINETO])
    def _draw_plus(self, renderer, gc, path, path_trans):
        gc.set_snap(renderer.points_to_pixels(self._markersize) >= 3.0)
        offset = 0.5*renderer.points_to_pixels(self._markersize)
        transform = Affine2D().scale(offset)
        renderer.draw_markers(gc, self._plus_path, transform,
                              path, path_trans)

    _tri_path = Path([[0.0, 0.0], [0.0, -1.0],
                      [0.0, 0.0], [0.8, 0.5],
                      [0.0, 0.0], [-0.8, 0.5]],
                     [Path.MOVETO, Path.LINETO,
                      Path.MOVETO, Path.LINETO,
                      Path.MOVETO, Path.LINETO])
    def _draw_tri_down(self, renderer, gc, path, path_trans):
        gc.set_snap(renderer.points_to_pixels(self._markersize) >= 5.0)
        offset = 0.5*renderer.points_to_pixels(self._markersize)
        transform = Affine2D().scale(offset)
        renderer.draw_markers(gc, self._tri_path, transform,
                              path, path_trans)

    def _draw_tri_up(self, renderer, gc, path, path_trans):
        gc.set_snap(renderer.points_to_pixels(self._markersize) >= 5.0)
        offset = 0.5*renderer.points_to_pixels(self._markersize)
        transform = Affine2D().scale(offset).rotate_deg(180)
        renderer.draw_markers(gc, self._tri_path, transform,
                              path, path_trans)

    def _draw_tri_left(self, renderer, gc, path, path_trans):
        gc.set_snap(renderer.points_to_pixels(self._markersize) >= 5.0)
        offset = 0.5*renderer.points_to_pixels(self._markersize)
        transform = Affine2D().scale(offset).rotate_deg(90)
        renderer.draw_markers(gc, self._tri_path, transform,
                              path, path_trans)

    def _draw_tri_right(self, renderer, gc, path, path_trans):
        gc.set_snap(renderer.points_to_pixels(self._markersize) >= 5.0)
        offset = 0.5*renderer.points_to_pixels(self._markersize)
        transform = Affine2D().scale(offset).rotate_deg(270)
        renderer.draw_markers(gc, self._tri_path, transform,
                              path, path_trans)

    _caret_path = Path([[-1.0, 1.5], [0.0, 0.0], [1.0, 1.5]])
    def _draw_caretdown(self, renderer, gc, path, path_trans):
        gc.set_snap(renderer.points_to_pixels(self._markersize) >= 3.0)
        offset = 0.5*renderer.points_to_pixels(self._markersize)
        transform = Affine2D().scale(offset)
        renderer.draw_markers(gc, self._caret_path, transform,
                              path, path_trans)

    def _draw_caretup(self, renderer, gc, path, path_trans):
        gc.set_snap(renderer.points_to_pixels(self._markersize) >= 3.0)
        offset = 0.5*renderer.points_to_pixels(self._markersize)
        transform = Affine2D().scale(offset).rotate_deg(180)
        renderer.draw_markers(gc, self._caret_path, transform,
                              path, path_trans)

    def _draw_caretleft(self, renderer, gc, path, path_trans):
        gc.set_snap(renderer.points_to_pixels(self._markersize) >= 3.0)
        offset = 0.5*renderer.points_to_pixels(self._markersize)
        transform = Affine2D().scale(offset).rotate_deg(270)
        renderer.draw_markers(gc, self._caret_path, transform,
                              path, path_trans)

    def _draw_caretright(self, renderer, gc, path, path_trans):
        gc.set_snap(renderer.points_to_pixels(self._markersize) >= 3.0)
        offset = 0.5*renderer.points_to_pixels(self._markersize)
        transform = Affine2D().scale(offset).rotate_deg(90)
        renderer.draw_markers(gc, self._caret_path, transform,
                              path, path_trans)

    _x_path = Path([[-1.0, -1.0], [1.0, 1.0],
                    [-1.0, 1.0], [1.0, -1.0]],
                   [Path.MOVETO, Path.LINETO,
                    Path.MOVETO, Path.LINETO])
    def _draw_x(self, renderer, gc, path, path_trans):
        gc.set_snap(renderer.points_to_pixels(self._markersize) >= 3.0)
        offset = 0.5*renderer.points_to_pixels(self._markersize)
        transform = Affine2D().scale(offset)
        renderer.draw_markers(gc, self._x_path, transform,
                              path, path_trans)

    def update_from(self, other):
        'copy properties from other to self'
        Artist.update_from(self, other)
        self._linestyle = other._linestyle
        self._linewidth = other._linewidth
        self._color = other._color
        self._markersize = other._markersize
        self._markerfacecolor = other._markerfacecolor
        self._markeredgecolor = other._markeredgecolor
        self._markeredgewidth = other._markeredgewidth
        self._dashSeq = other._dashSeq
        self._dashcapstyle = other._dashcapstyle
        self._dashjoinstyle = other._dashjoinstyle
        self._solidcapstyle = other._solidcapstyle
        self._solidjoinstyle = other._solidjoinstyle

        self._linestyle = other._linestyle
        self._marker = other._marker
        self._drawstyle = other._drawstyle

    def _get_rgb_face(self):
        facecolor = self.get_markerfacecolor()
        if is_string_like(facecolor) and facecolor.lower()=='none':
            rgbFace = None
        else:
            rgbFace = colorConverter.to_rgb(facecolor)
        return rgbFace

    # some aliases....
    def set_aa(self, val):
        'alias for set_antialiased'
        self.set_antialiased(val)

    def set_c(self, val):
        'alias for set_color'
        self.set_color(val)

    def set_ls(self, val):
        'alias for set_linestyle'
        self.set_linestyle(val)

    def set_lw(self, val):
        'alias for set_linewidth'
        self.set_linewidth(val)

    def set_mec(self, val):
        'alias for set_markeredgecolor'
        self.set_markeredgecolor(val)

    def set_mew(self, val):
        'alias for set_markeredgewidth'
        self.set_markeredgewidth(val)

    def set_mfc(self, val):
        'alias for set_markerfacecolor'
        self.set_markerfacecolor(val)

    def set_ms(self, val):
        'alias for set_markersize'
        self.set_markersize(val)

    def get_aa(self):
        'alias for get_antialiased'
        return self.get_antialiased()

    def get_c(self):
        'alias for get_color'
        return self.get_color()

    def get_ls(self):
        'alias for get_linestyle'
        return self.get_linestyle()

    def get_lw(self):
        'alias for get_linewidth'
        return self.get_linewidth()

    def get_mec(self):
        'alias for get_markeredgecolor'
        return self.get_markeredgecolor()

    def get_mew(self):
        'alias for get_markeredgewidth'
        return self.get_markeredgewidth()

    def get_mfc(self):
        'alias for get_markerfacecolor'
        return self.get_markerfacecolor()

    def get_ms(self):
        'alias for get_markersize'
        return self.get_markersize()

    def set_dash_joinstyle(self, s):
        """
        Set the join style for dashed linestyles
        ACCEPTS: ['miter' | 'round' | 'bevel']
        """
        s = s.lower()
        if s not in self.validJoin:
            raise ValueError('set_dash_joinstyle passed "%s";\n' % (s,)
                  + 'valid joinstyles are %s' % (self.validJoin,))
        self._dashjoinstyle = s

    def set_solid_joinstyle(self, s):
        """
        Set the join style for solid linestyles
        ACCEPTS: ['miter' | 'round' | 'bevel']
        """
        s = s.lower()
        if s not in self.validJoin:
            raise ValueError('set_solid_joinstyle passed "%s";\n' % (s,)
                  + 'valid joinstyles are %s' % (self.validJoin,))
        self._solidjoinstyle = s

    def get_dash_joinstyle(self):
        """
        Get the join style for dashed linestyles
        """
        return self._dashjoinstyle

    def get_solid_joinstyle(self):
        """
        Get the join style for solid linestyles
        """
        return self._solidjoinstyle

    def set_dash_capstyle(self, s):
        """
        Set the cap style for dashed linestyles

        ACCEPTS: ['butt' | 'round' | 'projecting']
        """
        s = s.lower()
        if s not in self.validCap:
            raise ValueError('set_dash_capstyle passed "%s";\n' % (s,)
                  + 'valid capstyles are %s' % (self.validCap,))

        self._dashcapstyle = s

    def set_solid_capstyle(self, s):
        """
        Set the cap style for solid linestyles

        ACCEPTS: ['butt' | 'round' |  'projecting']
        """
        s = s.lower()
        if s not in self.validCap:
            raise ValueError('set_solid_capstyle passed "%s";\n' % (s,)
                  + 'valid capstyles are %s' % (self.validCap,))

        self._solidcapstyle = s

    def get_dash_capstyle(self):
        """
        Get the cap style for dashed linestyles
        """
        return self._dashcapstyle

    def get_solid_capstyle(self):
        """
        Get the cap style for solid linestyles
        """
        return self._solidcapstyle

    def is_dashed(self):
        'return True if line is dashstyle'
        return self._linestyle in ('--', '-.', ':')

class VertexSelector:
    """
    Manage the callbacks to maintain a list of selected vertices for
    :class:`matplotlib.lines.Line2D`. Derived classes should override
    :meth:`~matplotlib.lines.VertexSelector.process_selected` to do
    something with the picks.

    Here is an example which highlights the selected verts with red
    circles::

        import numpy as np
        import matplotlib.pyplot as plt
        import matplotlib.lines as lines

        class HighlightSelected(lines.VertexSelector):
            def __init__(self, line, fmt='ro', **kwargs):
                lines.VertexSelector.__init__(self, line)
                self.markers, = self.axes.plot([], [], fmt, **kwargs)

            def process_selected(self, ind, xs, ys):
                self.markers.set_data(xs, ys)
                self.canvas.draw()

        fig = plt.figure()
        ax = fig.add_subplot(111)
        x, y = np.random.rand(2, 30)
        line, = ax.plot(x, y, 'bs-', picker=5)

        selector = HighlightSelected(line)
        plt.show()

    """
    def __init__(self, line):
        """
        Initialize the class with a :class:`matplotlib.lines.Line2D`
        instance.  The line should already be added to some
        :class:`matplotlib.axes.Axes` instance and should have the
        picker property set.
        """
        if not hasattr(line, 'axes'):
            raise RuntimeError('You must first add the line to the Axes')

        if line.get_picker() is None:
            raise RuntimeError('You must first set the picker property of the line')

        self.axes = line.axes
        self.line = line
        self.canvas = self.axes.figure.canvas
        self.cid = self.canvas.mpl_connect('pick_event', self.onpick)

        self.ind = set()

    def process_selected(self, ind, xs, ys):
        """
        Default "do nothing" implementation of the
        :meth:`process_selected` method.

        *ind* are the indices of the selected vertices.  *xs* and *ys*
        are the coordinates of the selected vertices.
        """
        pass

    def onpick(self, event):
        'When the line is picked, update the set of selected indicies.'
        if event.artist is not self.line: return

        for i in event.ind:
            if i in self.ind:
                self.ind.remove(i)
            else:
                self.ind.add(i)

        ind = list(self.ind)
        ind.sort()
        xdata, ydata = self.line.get_data()
        self.process_selected(ind, xdata[ind], ydata[ind])

lineStyles = Line2D._lineStyles
lineMarkers = Line2D._markers
drawStyles = Line2D.drawStyles

artist.kwdocd['Line2D'] = artist.kwdoc(Line2D)

# You can not set the docstring of an instancemethod,
# but you can on the underlying function.  Go figure.
Line2D.__init__.im_func.__doc__ = dedent(Line2D.__init__.__doc__) % artist.kwdocd


""" This is the Bokeh charts testing interface.

"""
#-----------------------------------------------------------------------------
# Copyright (c) 2012 - 2014, Continuum Analytics, Inc. All rights reserved.
#
# Powered by the Bokeh Development Team.
#
# The full license is in the file LICENSE.txt, distributed with this software.
#-----------------------------------------------------------------------------

#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
from __future__ import absolute_import

from collections import OrderedDict
import unittest
from mock import patch

import numpy as np
from numpy.testing import assert_array_equal, assert_array_almost_equal
import pandas as pd

from bokeh._legacy_charts import Histogram

from ._utils import create_chart

#-----------------------------------------------------------------------------
# Classes and functions
#-----------------------------------------------------------------------------

class TestHistogram(unittest.TestCase):
    def test_supported_input(self):
        normal = [1, 2, 3, 1]
        lognormal = [5, 4, 4, 1]
        xyvalues = OrderedDict(normal=normal, lognormal=lognormal)

        xyvaluesdf = pd.DataFrame(xyvalues)

        exptected = dict(
            leftnormal=[1., 1.4, 1.8, 2.2, 2.6],
            rightnormal=[1.4, 1.8, 2.2, 2.6, 3.],
            lognormal=[5, 4, 4, 1],
            edgeslognormal=[1., 1.8, 2.6, 3.4, 4.2, 5.],
            bottomlognormal=[0, 0, 0, 0, 0],
            bottomnormal=[0, 0, 0, 0, 0],
            edgesnormal=[1., 1.4, 1.8, 2.2, 2.6, 3.],
            histlognormal=[0.3125, 0., 0., 0.625, 0.3125],
            leftlognormal=[1., 1.8, 2.6, 3.4, 4.2],
            normal=[1, 2, 3, 1],
            rightlognormal=[1.8, 2.6, 3.4, 4.2, 5.],
            histnormal=[1.25, 0., 0.625, 0., 0.625],
        )

        for i, _xy in enumerate([xyvalues, xyvaluesdf]):
            hm = create_chart(Histogram, _xy, bins=5)
            builder = hm._builders[0]
            self.assertEqual(sorted(builder._groups), sorted(list(xyvalues.keys())))
            for key, expected_v in exptected.items():
                assert_array_almost_equal(builder._data[key], expected_v, decimal=2)

        lvalues = [[1, 2, 3, 1], [5, 4, 4, 1]]
        for i, _xy in enumerate([lvalues, np.array(lvalues)]):
            hm = create_chart(Histogram, _xy, bins=5)
            builder = hm._builders[0]
            self.assertEqual(builder._groups, ['0', '1'])
            for key, expected_v in exptected.items():
                # replace the keys because we have 0, 1 instead of normal and lognormal
                key = key.replace('lognormal', '1').replace('normal', '0')
                assert_array_almost_equal(builder._data[key], expected_v, decimal=2)

    @patch('bokeh._legacy_charts.builder.histogram_builder.np.histogram', return_value=([1, 3, 4], [2.4, 4]))
    def test_histogram_params(self, histogram_mock):
        inputs = [[5, 0, 0.5, True], [3, 1, 0, False]]
        normal = [1, 2, 3, 1]
        lognormal = [5, 4, 4, 1]
        xyvalues = OrderedDict()
        xyvalues['normal'] = normal
        xyvalues['lognormal'] = lognormal

        for (bins, mu, sigma, dens) in inputs:
            histogram_mock.reset_mock()
            kws = dict(bins=bins, mu=mu, sigma=sigma, density=dens)
            hm = create_chart(Histogram, xyvalues, compute_values=False, **kws)
            builder = hm._builders[0]
            # ensure all class attributes have been correctly set
            for key, value in kws.items():
                self.assertEqual(getattr(builder, key), value)

            builder._process_data()
            # ensure we are calling numpy.histogram with the right args
            calls = histogram_mock.call_args_list
            assert_array_equal(calls[0][0][0], np.array([1, 2, 3, 1]))
            assert_array_equal(calls[1][0][0], np.array([5, 4, 4, 1]))
            self.assertEqual(calls[0][1]['bins'], bins)
            self.assertEqual(calls[1][1]['bins'], bins)
            self.assertEqual(calls[0][1]['density'], dens)
            self.assertEqual(calls[1][1]['density'], dens)


'''
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
IMPORTANT!!

It is suggested you run this script with mpu_level2.ino first to see and understand
its operation.
Basically this script EXPECTS:
Arduino is providing space separated gyro readings @ ~5ms intervals (via MPU Interrupt).
* Each serial packet must be ASCII and look like:
		[x_gyro]<space>[y_gyro]<space>[z_gyro]<newline>
+ You need to specify correct Serial port
+ You need to set the Y-limits of the plot axis.
+ You need to use correct value of "dt".
+ You need to set the correct conversion factor for Gyro readings.
  Mode  0		1		2		3
  Range +-250	+-500	+-1000	+-2000
  Conv. 131		65.5	32.75	16.375

AND it DELIVERS:
* 3 axis loss-less Gyro readings plot (almost real time).
* 3D visualisation of current orientation based on gyro vals

If you want to just plot data in ~real time use {oscilloscope.py}.
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
'''
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import serial, time

def rotate(v, axis, theta):
	'''
	Rotates "v" vector about "axis" vector by "theta" radians, returns vector
	'''
	c = np.cos(theta)
	s = np.sin(theta)
	t = 1-c
	mat = np.array([ [c+axis[0]*axis[0]*t, axis[0]*axis[1]*t-axis[2]*s, axis[0]*axis[2]*t+axis[1]*s],
				 	 [axis[0]*axis[1]*t+axis[2]*s, c+axis[1]*axis[1]*t, axis[1]*axis[2]*t-axis[0]*s],
					 [axis[0]*axis[2]*t-axis[1]*s, axis[1]*axis[2]*t+axis[0]*s, c+axis[2]*axis[2]*t] ])
	return mat.dot(v.T)

def calcPose(omega):
	'''
	Helper function. Finds the "d"-theta, then calls rotate.
	Omega must be in ** degrees per second **
	'''
	theta = omega*dt*np.pi/180 #theta is "d-theta" in radians
	rpy[1] = rotate(rpy[1], rpy[0], theta[0])
	rpy[0] = rotate(rpy[0], rpy[1], theta[1])
	rpy[2] = np.cross(rpy[0], rpy[1])
	rpy[1] = rotate(rpy[1], rpy[2], theta[2])
	rpy[0] = rotate(rpy[0], rpy[2], theta[2])

plt.ion()
# SET CORRECT PORT NUM HERE
arduino = serial.Serial('/dev/ttyACM0', 57600)
# dt is found experimentally. Contact Ananya for details. Basically this the time between
# 2 MPU(gyro) interrupts. The np.pi/180 converts deg/sec to rad/sec.
# SET CORRECT dt HERE. TIME IN SECONDS BETWEEN TWO SENSOR PACKETS AS RECVD. BY ARDUINO.
dt = .005 # 5msec
# rpy is original orientation. These vectors are updated by calcPose()
rpy = np.eye(3)

fig = plt.figure(figsize=(16,6))
axes = fig.add_subplot(121)
a3d = fig.add_subplot(122, projection='3d')
a3d.set_xlim(-1.2,1.2)
a3d.set_ylim(-1.2,1.2)
a3d.set_zlim(-1.2,1.2)
a3d.scatter([0], [0], [0], s=40)
r, = a3d.plot([0,1], [0,0], [0,0], lw=2, c='black')
p, = a3d.plot([0,0], [0,1], [0,0], lw=2, c='red')
a3d.plot([0,2], [0,0], [0,0], c='cyan')
a3d.plot([0,0], [0,2], [0,0], c='brown')
a3d.plot([0,0], [0,0], [0,2], c='green')
a3d.plot([0,-2], [0,0], [0,0], ls='--', c='cyan')
a3d.plot([0,0], [0,-2], [0,0], ls='--', c='brown')
a3d.plot([0,0], [0,0], [0,-2], ls='--', c='green')

num_samples = 0
buff = 0
# "buff" counts till 50. Every time it reaches fifty, plt.draw() is called, since
# plt.draw() is a costly operation. Normal list append and pose calculations are fast.
# So, do those diligently, for every sample, but update display
# rarely (while ensuring smooth animation).
gyro_x = [0]
gyro_y = [0] # gyro data lists. I use them like queues.
gyro_z = [0]
t = [0]
# scopes is a list of 3 matplotlib.Line_2D objects.
scopes = [axes.plot(t, gyro_x, label=r'$\omega_x$')[0], axes.plot(t, gyro_y, label=r'$\omega_y$')[0], axes.plot(t, gyro_z, label=r'$\omega_z$')[0]]
axes.legend(prop=dict(size=14))
plt.legend(bbox_to_anchor=(0., 1.02, 1., .102), loc=3,
           ncol=3, mode="expand", borderaxespad=0.)
axes.set_ylim(-505, 505) # SET CORRECT Y-LIM HERE
conversion = 65.5 #Gyro 500 SET CORRECT CONV FACTOR HERE

# Refer datasheet. Convert ADC result into a Physical measurement.
# If you don't understand this, pls. leave project.
print 'Me Ready'
time.sleep(2)
#Handshake MAY BE REDUNDANT
print arduino.inWaiting()
arduino.flushInput()
arduino.write('e')
print 'Sent Request...'
data = [0]*6
while True:
	try:
		num = arduino.read(12)
		num = [ord(x) for x in num]
	except:
		print 'Serial error!'
		raise RuntimeError
	_ind=0 #this var is connected to for loop below!!
	for i in range(0,12, 2):
		data[_ind] = (num[i]<<8)|num[i+1]
		if data[_ind] & 0x8000:
			data[_ind] = data[_ind] - 0x10000
		_ind += 1
	#print data[3:]
	datas = np.array([float(data[3])/conversion, float(data[4])/conversion, float(data[5])/conversion])
	gyro_x.append(datas[0])
	gyro_y.append(datas[1])
	gyro_z.append(datas[2])
	num_samples += 1
	t.append(num_samples)
	calcPose(datas) #This function updates the global variable: "rpy"
	if num_samples>200:
		del t[0]
		del gyro_x[0]
		del gyro_y[0]
		del gyro_z[0]
	axes.set_xlim(t[0], num_samples)
	scopes[0].set_data(t, gyro_x)
	scopes[1].set_data(t, gyro_y)
	scopes[2].set_data(t, gyro_z)
	# pose matrix is just an easier way of giving input to the .set_data()
	# and .set_3d_properties() methods. You see, line needs 2 (end) points:
	# the rpy entries AND THE ORIGIN. pose matrix does just that: specifies
	# BOTH end points.
	pose = np.array([np.array([np.zeros(3), rpy[0]]).T,	np.array([np.zeros(3), rpy[1]]).T, np.array([np.zeros(3), rpy[2]]).T])
	r.set_data(pose[0][:2])
	r.set_3d_properties(pose[0][2])
	p.set_data(pose[1][:2])
	p.set_3d_properties(pose[1][2])

	if buff>25:
		buff=0
		plt.draw()
	buff += 1

plt.ioff()
plt.show()


from geo import AitoffAxes, HammerAxes, LambertAxes
from polar import PolarAxes
from matplotlib import axes

class ProjectionRegistry(object):
    """
    Manages the set of projections available to the system.
    """
    def __init__(self):
        self._all_projection_types = {}

    def register(self, *projections):
        """
        Register a new set of projection(s).
        """
        for projection in projections:
            name = projection.name
            self._all_projection_types[name] = projection

    def get_projection_class(self, name):
        """
        Get a projection class from its *name*.
        """
        return self._all_projection_types[name]

    def get_projection_names(self):
        """
        Get a list of the names of all projections currently
        registered.
        """
        names = self._all_projection_types.keys()
        names.sort()
        return names
projection_registry = ProjectionRegistry()

projection_registry.register(
    axes.Axes,
    PolarAxes,
    AitoffAxes,
    HammerAxes,
    LambertAxes)

def register_projection(cls):
    projection_registry.register(cls)

def get_projection_class(projection=None):
    """
    Get a projection class from its name.

    If *projection* is None, a standard rectilinear projection is
    returned.
    """
    if projection is None:
        projection = 'rectilinear'

    try:
        return projection_registry.get_projection_class(projection)
    except KeyError:
        raise ValueError("Unknown projection '%s'" % projection)

def projection_factory(projection, figure, rect, **kwargs):
    """
    Get a new projection instance.

    *projection* is a projection name.

    *figure* is a figure to add the axes to.

    *rect* is a :class:`~matplotlib.transforms.Bbox` object specifying
    the location of the axes within the figure.

    Any other kwargs are passed along to the specific projection
    constructor being used.
    """

    return get_projection_class(projection)(figure, rect, **kwargs)

def get_projection_names():
    """
    Get a list of acceptable projection names.
    """
    return projection_registry.get_projection_names()


import numpy as np
from numpy.testing import dec, assert_equal, assert_almost_equal

from statsmodels.graphics.functional import \
            banddepth, fboxplot, rainbowplot

try:
    import matplotlib.pyplot as plt
    import matplotlib
    if matplotlib.__version__ < '1':
        raise
    have_matplotlib = True
except:
    have_matplotlib = False

def test_banddepth_BD2():
    xx = np.arange(500) / 150.
    y1 = 1 + 0.5 * np.sin(xx)
    y2 = 0.3 + np.sin(xx + np.pi/6)
    y3 = -0.5 + np.sin(xx + np.pi/6)
    y4 = -1 + 0.3 * np.cos(xx + np.pi/6)

    data = np.asarray([y1, y2, y3, y4])
    depth = banddepth(data, method='BD2')
    expected_depth = [0.5, 5./6, 5./6, 0.5]
    assert_almost_equal(depth, expected_depth)

    ## Plot to visualize why we expect this output
    #fig = plt.figure()
    #ax = fig.add_subplot(111)
    #for ii, yy in enumerate([y1, y2, y3, y4]):
    #    ax.plot(xx, yy, label="y%s" % ii)

    #ax.legend()
    #plt.show()

def test_banddepth_MBD():
    xx = np.arange(5001) / 5000.
    y1 = np.zeros(xx.shape)
    y2 = 2 * xx - 1
    y3 = np.ones(xx.shape) * 0.5
    y4 = np.ones(xx.shape) * -0.25

    data = np.asarray([y1, y2, y3, y4])
    depth = banddepth(data, method='MBD')
    expected_depth = [5./6, (2*(0.75-3./8)+3)/6, 3.5/6, (2*3./8+3)/6]
    assert_almost_equal(depth, expected_depth, decimal=4)

@dec.skipif(not have_matplotlib)
def test_fboxplot_rainbowplot():
    """Test fboxplot and rainbowplot together, is much faster."""
    def harmfunc(t):
        """Test function, combination of a few harmonic terms."""
        # Constant, 0 with p=0.9, 1 with p=1 - for creating outliers
        ci = int(np.random.random() > 0.9)
        a1i = np.random.random() * 0.05
        a2i = np.random.random() * 0.05
        b1i = (0.15 - 0.1) * np.random.random() + 0.1
        b2i = (0.15 - 0.1) * np.random.random() + 0.1

        func = (1 - ci) * (a1i * np.sin(t) + a2i * np.cos(t)) + \
               ci * (b1i * np.sin(t) + b2i * np.cos(t))

        return func

    np.random.seed(1234567)
    # Some basic test data, Model 6 from Sun and Genton.
    t = np.linspace(0, 2 * np.pi, 250)
    data = []
    for ii in range(20):
        data.append(harmfunc(t))

    # fboxplot test
    fig = plt.figure()
    ax = fig.add_subplot(111)
    _, depth, ix_depth, ix_outliers = fboxplot(data, wfactor=2, ax=ax)

    ix_expected = np.array([13, 4, 15, 19, 8, 6, 3, 16, 9, 7, 1, 5, 2,
                            12, 17, 11, 14, 10, 0, 18])
    assert_equal(ix_depth, ix_expected)
    ix_expected2 = np.array([2, 11, 17, 18])
    assert_equal(ix_outliers, ix_expected2)

    plt.close(fig)

    # rainbowplot test (re-uses depth variable)
    xdata = np.arange(data[0].size)
    fig = rainbowplot(data, xdata=xdata, depth=depth, cmap=plt.cm.rainbow)
    plt.close(fig)