In [1]:
from IPython.display import display, Image, HTML
from talktools import website, nbviewer
Data exploration is an iterative process that involves repeated passes at visualization, interaction and computation:
In [2]:
Image('images/VizInteractCompute.png')
Out[2]:
Right now this cycle is still really painful:
Jupyter and IPython include an architecture that allows kernels and JavaScript to communicate seamlessly and in real time.
The Python kernel that ships with IPython 2.0 offers an interact function and decorator for interactive exploration. This is the highest-level API in our interactive JavaScript architecture. Other language kernels will also be able to implement these APIs.
In this example, we will perform some basic image processing using scikit-image.
In [3]:
from IPython.html.widgets import *
In [4]:
import skimage
from skimage import data, filter, io
In [5]:
i = data.coffee()
io.Image(i)
Out[5]:
Here is a function that can applies a Gaussian blur and adjusts the RGB channels:
In [6]:
def edit_image(image, sigma=0.1, r=1.0, g=1.0, b=1.0):
new_image = filter.gaussian_filter(image, sigma=sigma, multichannel=True)
new_image[:,:,0] = r*new_image[:,:,0]
new_image[:,:,1] = g*new_image[:,:,1]
new_image[:,:,2] = b*new_image[:,:,2]
new_image = io.Image(new_image)
display(new_image)
return new_image
Calling the function once, displays and returns the edited image:
In [9]:
new_i = edit_image(i, 0.1, r=0.5, b=0.7);
We can use interact to explore the parameter space of the processed image:
In [10]:
lims = (0.0,1.0,0.01)
interact(edit_image, image=fixed(i), sigma=(0.0,10.0,0.1), r=lims, g=lims, b=lims);
We can quickly interate through the visualize, interact, compute cycle.
The interact function and the widget objects underneath it are completely generic and work with any type of Python code or output.
Here is an example from symbolic mathematics using the sympy library:
In [11]:
from sympy import Symbol, Eq, factor, init_printing
init_printing(use_latex='mathjax')
In [12]:
x = Symbol('x')
In [13]:
def factorit(n):
display(Eq(x**n-1, factor(x**n-1)))
In [15]:
factorit(15)
In [16]:
interact(factorit, n=(2,40));
Let's explore a 2d normal distribution:
$$ f_{\mathbf x}(x_1,\ldots,x_k) = \frac{1}{\sqrt{(2\pi)^k|\boldsymbol\Sigma|}} \exp\left(-\frac{1}{2}({\mathbf x}-{\boldsymbol\mu})^T{\boldsymbol\Sigma}^{-1}({\mathbf x}-{\boldsymbol\mu}) \right) $$$$ \boldsymbol\mu = \begin{pmatrix} \mu_x \\ \mu_y \end{pmatrix}, \quad \boldsymbol\Sigma = \begin{pmatrix} \sigma_x^2 & \rho \sigma_x \sigma_y \\ \rho \sigma_x \sigma_y & \sigma_y^2 \end{pmatrix} $$
In [17]:
%matplotlib inline
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import seaborn as sns
In [18]:
def normal_2d(n, mux, muy, sigmax, sigmay, corr):
mean = [mux, muy]
cov = [[sigmax**2, corr*sigmax*sigmay],[corr*sigmax*sigmay,sigmay**2]]
d = np.random.multivariate_normal(mean, cov, n)
return d[:,0], d[:,1]
In [19]:
x, y = normal_2d(100, 0.0, 0.0, 3.0, 2.0, 0.8)
In [20]:
plt.scatter(x, y, s=100, alpha=0.6);
In [21]:
def plot_normal_2d(n, mux, muy, sigmax, sigmay, corr):
x, y = normal_2d(n, mux, muy, sigmax, sigmay, corr)
plt.scatter(x, y, s=100, alpha=0.6)
plt.axis([-10.0,10.0,-10.0,10.0])
In [22]:
interact(plot_normal_2d, n=(10,100,10), mux=(-5.0,5.0,0.1), muy=(-5.0,5.0,0.1),
sigmax=(0.01,5.0,0.01), sigmay=(0.01,5.0,0.01), corr=(-0.99,0.99,0.01));
interact are "widget abbreviations"Widget instancesWidget objects are Python objects that are automatically synchronized with JavaScript MVC objects running in the browserinteract simply calls its callable each time any widget changes state
In [ ]:
def f(x):
print x
In [ ]:
interact(f, x=True);
In [ ]:
interact(f, x=(0,10,2));
In [ ]:
interact(f, x='Hi!');
In [ ]:
interact(f, x=dict(this=list, that=tuple, other=str));
The widget architecture in Jupyter and IPython has a layered design with each layer working independently of the others.
In [ ]:
Image('images/WidgetArch.png')
This entire architecture is language agnostic. Other language kernels (Julia, R, Scala, etc.) will be able to implement the kernel side of the architecture. This will allow all kernels to re-use the JavaScript/HTML/CSS side of the Widgets while having their own language specific APIs for interact/Widgets in the kernels.