def iris_isochron_fig(a, border=1., phase_offset=0., l = default_lambda):
    # set up the model parameters for this figure
    l_cw = -l
    l_ccw = 1
    X = Y = 1.

    # calculate the isochrons
    mesh_points = 400
    XX, YY = np.meshgrid(
            np.linspace(-(2*X + a/2), (2*X + a/2), mesh_points),
            np.linspace(-(2*Y + a/2), (2*Y + a/2), mesh_points),
            )
    isochrons = iris.iris_isochron(XX, YY, a=a, l_ccw=l_ccw,
            l_cw=l_cw, X=X, Y=Y)

    # create a new figure
    fig = plt.figure(figsize=(6,6))
    axes = fig.add_axes([0.1, 0.1, 0.8, 0.8])

    indexes = np.array([[i, j] for i in range(-2,3) for j in range(-2,3)])
    offsets = np.array([[i*2*X - a*j, j*2*Y + i*a] for i,j in indexes])

    for i in range(len(offsets)):
        if indexes[i].sum() % 2 == 0:
            iris.draw_fancy_iris(axes, a, l_ccw, l_cw, X, Y, x0=np.nan,
                    offset = offsets[i,:2])

    contours = phase_offset + np.linspace(
            -3*math.pi, 14*math.pi, 128, endpoint=False)
    cool_colors = [(0, 0.6 + 0.3*math.sin(c), 0.7 + 0.3*math.cos(c))
                for c in contours]
    hot_colors = [(0.6 + 0.3*math.cos(c), 0., 0.7 + 0.3*math.sin(c))
                for c in contours]

    # draw the other limit cycles
    for i in range(len(offsets)):
        if indexes[i].sum() % 2 == 0:
            axes.contour(XX + offsets[i, 0], YY + offsets[i, 1], isochrons,
                    contours,
                    colors=(cool_colors, hot_colors)[indexes[i, 0] % 2])

    # add lines at the edge of the squares to hide the contour discontinuity
    # where the phase wraps from 2 \pi to zero
    for i in range(len(offsets)):
        axes.plot([ a/2,  a/2] + offsets[i, 0],
                [-a/2, -(2*Y+a/2)] + offsets[i, 1], 'k')
        axes.plot([-a/2, -(2*X+a/2)] + offsets[i, 0],
                [-a/2, -a/2] + offsets[i, 1], 'k')

    # center the plot and clean up the scale bars
    axes.set_xlim(-3*X-border, 3*X+border)
    axes.set_ylim(-3*Y-border, 3*Y+border)
    axes.set_xticks([])
    axes.set_yticks([])
    axes.set_frame_on(False)
    return fig
def iris_timeplot_fig(a_vals = sample_a_vals, border = 0.3):
    # set up the model parameters for this figure
    l_cw = -default_lambda
    l_ccw = 1
    X = Y = 1.
    n_phis = np.linspace(0, 2*math.pi, 20*4 + 1)
    a_phis = np.linspace(0, 2*math.pi, 100*4 + 1)
    dx = 1e-4
    dy = 0.
    mag = math.sqrt(dx**2 + dy**2)
    phasescale = 4 / (2 * math.pi) # convert from (0,2 \pi) to (0,4)

    # create a new figure
    fig = plt.figure(figsize=(6,6))

    width = 1./len(a_vals)
    padding = 0.2*width

    for i in range(len(a_vals)):
        a = a_vals[i]

        axes = plt.axes((2*padding, 1-(i+1) * width+padding,
            1 - width - 2*padding, width - 1.5*padding))

        # draw the trajectory components vs. time
        r0 = iris.iris_fixedpoint(a, l_ccw, l_cw, X, Y, guess=1e-6*X)
        T = 4 * iris.dwell_time(r0, l_ccw, l_cw, X, Y)
        ts = np.linspace(0, 3*T, 1000);
        vals = integrate.odeint(iris.iris,
                [-a/2, -a/2 - Y + r0],
                ts,
                args=(a, l_ccw, l_cw, X, Y))
        axes.plot(ts, vals[:,1], '-', color='0.8', lw=2)
        axes.plot(ts, vals[:,0], 'k-', lw=2)

        axes.set_xlim(0, 3*T)

        # make the y-axis symmetric around zero
        #ymaxabs = np.max(np.abs(axes.get_ylim()))
        ymaxabs = 1.2
        axes.set_ylim(-ymaxabs, ymaxabs)


        # draw the phase plot for reference
        axes = plt.axes((1-width, 1-(i+1) * width, width, width))
        iris.draw_fancy_iris(axes, a, l_ccw, l_cw, X, Y,
                scale=3.0, x0=np.nan)

        # center the plot and clean up the scale bars
        axes.set_xlim(-2*X-border, 2*X+border)
        axes.set_ylim(-2*Y-border, 2*Y+border)
        axes.set_xticks([])
        axes.set_yticks([])
        axes.set_frame_on(False)

    return fig
def iris_fig(a, border=1., label_theta0=True):
    # set up the model parameters for this figure
    l_cw = -default_lambda
    l_ccw = 1
    X = Y = 1.

    # create a new figure
    fig = plt.figure(figsize=(5,5))
    axes = fig.add_axes([0., 0., 1., 1.])

    iris.draw_fancy_iris(axes, a, l_ccw, l_cw, X, Y)

    # add an arrow indicating theta = 0
    if label_theta0:
        r0s = iris.iris_fixedpoint(a, l_ccw, l_cw, X, Y, guess=1e-6*X)
        if r0s != None:
            axes.annotate(r'$\theta = 0$',
                xy=(a/2, -X + r0s - a/2), xycoords='data',
                xytext=(15,15), textcoords='offset points',
                arrowprops=dict(arrowstyle='->',
                    connectionstyle='angle,angleA=180,angleB=240,rad=10')
                )
        r0u = iris.iris_fixedpoint(a, l_ccw, l_cw, X, Y, guess=1*X)
        if a != 0 and r0u != None:
            axes.annotate(r'',
                xy=(-X + r0u - a/2, -a/2), xycoords='data',
                xytext=(-15,15), textcoords='offset points',
                arrowprops=dict(arrowstyle='->', color='r',
                    connectionstyle='angle,angleA=-180,angleB=-45,rad=0')
                )
        if a != 0 and r0u != None:
            x0 = [-a/2, a/2 + Y - (0.9*r0u + 0.1*r0s)]
        elif a == 0:
            x0 = [-a/2, a/2 + Y - 0.9]
        else:
            x0 = [-a/2, 0.9*Y]
        axes.annotate(r'',
            xy=x0, xycoords='data',
            xytext=x0 + np.r_[-1.0e-3, 0.5e-3], textcoords='data',
            arrowprops=dict(arrowstyle='->', color='b',
                connectionstyle='arc3,rad=0')
            )

    # center the plot and clean up the scale bars
    axes.set_xlim(-2*X-border, 2*X+border)
    axes.set_ylim(-2*Y-border, 2*Y+border)
    axes.set_xticks([])
    axes.set_yticks([])
    axes.set_frame_on(False)
    return fig
def iris_prc_fig(a_vals = sample_a_vals, border = 0.3):
    # set up the model parameters for this figure
    l_cw = -default_lambda
    l_ccw = 1
    X = Y = 1.
    n_phis = np.linspace(0, 2*math.pi, 20*4 + 1)
    a_phis = np.linspace(0, 2*math.pi, 100*4 + 1)
    dx = 1e-4
    dy = 0.
    mag = math.sqrt(dx**2 + dy**2)
    phasescale = 4 / (2 * math.pi) # convert from (0,2 \pi) to (0,4)

    # create a new figure
    fig = plt.figure(figsize=(6,6))

    width = 1./len(a_vals)
    padding = 0.2*width

    for i in range(len(a_vals)):
        a = a_vals[i]

        axes = plt.axes((2*padding, 1-(i+1) * width+padding,
            1 - width - 2*padding, width - 1.5*padding))

        # draw the orthogonal prc found analytically
        a_prc_o = np.array([
            iris.analytic_phase_reset(phi, dx=-dy, dy=dx, a=a,
                l_ccw=l_ccw, l_cw=l_cw)
            for phi in a_phis
            ])
        axes.plot(a_phis, a_prc_o/mag*phasescale, color='0.8')

        # draw the orthogonal prc found numerically
        n_prc_o = np.array([
            iris.phase_reset(phi, dx=-dy, dy=dx, a=a, l_ccw=l_ccw, l_cw=l_cw,
                steps_per_cycle=100000)
            for phi in n_phis
            ])
        axes.plot(n_phis, n_prc_o/mag*phasescale, 'o', markersize=3,
                markeredgecolor='0.8', color='0.8')

        # draw the prc found analytically
        a_prc = np.array([
            iris.analytic_phase_reset(phi, dx=dx, dy=dy, a=a,
                l_ccw=l_ccw, l_cw=l_cw)
            for phi in a_phis
            ])
        axes.plot(a_phis, a_prc/mag*phasescale, 'k')

        # draw the prc found numerically
        n_prc = np.array([
            iris.phase_reset(phi, dx=dx, dy=dy, a=a, l_ccw=l_ccw, l_cw=l_cw,
                steps_per_cycle=100000)
            for phi in n_phis
            ])
        axes.plot(n_phis, n_prc/mag*phasescale, 'bo', markersize=3)

        # clean up the axes
        axes.set_xlim(0, 2*math.pi)
        plt.xticks(np.arange(5.)*math.pi/2,
                #['$0$', '$\\pi/2$', '$\\pi$',
                #    '$3\\pi/2$', '$2\\pi$'])
                # phase rescaled from 0 to 4 to match analysis
                ['$0$', '$1$', '$2$', '$3$', '$4$'])

        # make the y-axis symmetric around zero
        ymaxabs = np.max(np.abs(axes.get_ylim()))
        axes.set_ylim(-ymaxabs, ymaxabs)


        # draw the phase plot for reference
        axes = plt.axes((1-width, 1-(i+1) * width, width, width))
        iris.draw_fancy_iris(axes, a, l_ccw, l_cw, X, Y,
                scale=3.0, x0=np.nan)

        # center the plot and clean up the scale bars
        axes.set_xlim(-2*X-border, 2*X+border)
        axes.set_ylim(-2*Y-border, 2*Y+border)
        axes.set_xticks([])
        axes.set_yticks([])
        axes.set_frame_on(False)

    return fig