Line Plot

bqplot is an interactive plotting library. Attributes of plots can be updated in place without recreating the whole figure and marks. Let's look at idiomatic ways of updating plots in bqplot

import numpy as np
import bqplot.pyplot as plt

# Jupyter Specifics
#
from IPython.display import HTML
from ipywidgets.widgets import interact, IntSlider, FloatSlider, Dropdown, Layout
x = np.linspace(-10, 10, 100)
y = np.sin(x)

fig = plt.figure()
line = plt.plot(x=x, y=y)
fig

Circle

Basic Functions

Once everything is imported and ready to use, several functions must be defined, namely:

  1. A function to calculate the points arround a circle
  2. A function to generate each of the lines
  3. A function to plot the labels and the point in the circle
  4. A function to plot the lines in the circle

The first function is called points_arround_circle and it basically uses polar coordinates to place a given number of points arround a circle of a given radius. Here numpy is needed to make the calculation performant.

def points_arround_circle(number=100, center=(0,0), radius=1):
    theta = np.linspace(0, 2 * np.pi - (2 * np.pi / number), number)
    x = radius * np.cos(theta)
    y = radius * np.sin(theta)
    return (x, y)

Second, in order to generate the lines, the list of points is given and a new line is generated by the function get_lines_from_points.

def get_lines_from_points(x, y, factor, animated=None):
    limit = len(x)
    if animated is not None:
        for i in range(limit):
            x_range = (x[i], x[int(i * factor) % limit])
            y_range = (y[i], y[int(i * factor) % limit])
            yield mlines.Line2D(x_range, y_range)
    else:
        for i in range(limit):
            start = (x[i], y[i])
            index = int((i * factor) % limit)
            end = (x[index], y[index])          
            yield end, start
def plot_circle_points(x, y, ax, labels=None):
    ax.annotate("Points: {}".format(len(x)), (0.8, 0.9))
    ax.plot(x, y, "-ko", markevery=1)
    if not labels is None:
        for i, (x, y) in enumerate(zip(x, y)):
            ax.annotate(i, (x, y))
def plot_lines(x, y, factor, ax, color=None):
    ax.annotate("Factor: {}".format(factor), (0.8, 1))
    lines = list(get_lines_from_points(x, y, factor))
    if color is None:
        line_segments = LineCollection(lines)
    else:
        line_segments = LineCollection(lines, colors=colorsys.hsv_to_rgb(color, 1.0, 0.8))
            
    ax.add_collection(line_segments)
def plot_parametric(Factor=2, Points=100):
    
    # figsize: width|height recalculated from inches to pixels
    my_dpi=96
    plt.figure(figsize=(800/my_dpi, 800/my_dpi), dpi=my_dpi)    
    
    # ax = plt.subplot()
    # plt.axis('off')
    ax = 1
    
    x, y = points_arround_circle(number=Points)
    plot_circle_points(x, y, ax)
    plot_lines(x, y, Factor, ax)
    plt.show()

factors = 2, 3, 4, 5, 8, 10, 16, 20, 21, 25, 26, 34
print("\nTry these Factors with different number of Points:\n", *factors, "\n")
Try these Factors with different number of Points:
 2 3 4 5 8 10 16 20 21 25 26 34 

# nbi:hide_in

interact(plot_parametric, 
        Factor=IntSlider(min=1, max=34, step=1, value=2, layout=Layout(width='90%')),
        Points=IntSlider(min=25, max=200, step=5, value=100, layout=Layout(width='90%')));