*Update (13 Jan 2016)*: Added links to the DIY section.

A few days ago I started making my blog posts interactive. It was cool, but required you to surf to a different page for the interactive experience, while the original post was still non-interactive.

Alex pointed out that really you wanted it all in one page. Basically he was:

My blog setup follows Jake Vanderplas' pretty closely. So I created a new `liquid_tags`

plugin
that has its own template for `nbconvert`

which generates HTML that thebe understands.

No downloading, no installing, no browsing to a separate page! Just interactive blog posts! (Scroll down to see it in action if you do not care how it was done.)

## Do it yourself¶

If you have a pelican site take a look at my fork of the `liquid_tags`

plugin. In addition I made a small gist that shows how to convert notebook to interactive HTML with plain `nbconvert`

. The most important part is using the following template with `nbconvert`

:

```
{%- extends 'basic.tpl' -%}
{% block codecell %}
<pre data-executable>
{{ cell.source }}
</pre>
{% endblock codecell %}
{% block markdowncell scoped %}
<div class="cellOOO border-box-sizing text_cell rendered">
{{ self.empty_in_prompt() }}
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
{{ cell.source | markdown2html | strip_files_prefix }}
</div>
</div>
</div>
{%- endblock markdowncell %}
```

It embeds code cells in simple `<pre>`

tags and modifies non-code cells so that they do not
match the selectors used inside the notebook machinery. That is it. Then stick a bit of CSS and JS in the `<head>`

of your web page and you are good to go (use the source of this page for inspiration).

### Credits¶

Compared to my previous post this setup now only relies on thebe, tmpnb, and the kind people at rackspace who sponsor the computing power for `tmpnb`

.

Below, the work of the jupyter development team, licensed under the 3 clause BSD license.

Get in touch on twitter @betatim.

# Exploring the Lorenz System of Differential Equations¶

In this Notebook we explore the Lorenz system of differential equations:

$$ \begin{aligned} \dot{x} & = \sigma(y-x) \\ \dot{y} & = \rho x - y - xz \\ \dot{z} & = -\beta z + xy \end{aligned} $$This is one of the classic systems in non-linear differential equations. It exhibits a range of different behaviors as the parameters ($\sigma$, $\beta$, $\rho$) are varied.

## Imports¶

First, we import the needed things from IPython, NumPy, Matplotlib and SciPy.

%matplotlib inline

Experiment with using `%matplotlib notebook`

for interactive matplotlib figures. Thanks to Thomas Caswell for that tip! If you use this you will have to modify the `interact()`

call below a bit, but I'll leave that as *an exercise for the reader*.

from ipywidgets import interact, interactive from IPython.display import clear_output, display, HTML

import numpy as np from scipy import integrate from matplotlib import pyplot as plt from mpl_toolkits.mplot3d import Axes3D from matplotlib.colors import cnames from matplotlib import animation

## Computing the trajectories and plotting the result¶

We define a function that can integrate the differential equations numerically and then plot the solutions. This function has arguments that control the parameters of the differential equation ($\sigma$, $\beta$, $\rho$), the numerical integration (`N`

, `max_time`

) and the visualization (`angle`

).

def solve_lorenz(N=10, angle=0.0, max_time=4.0, sigma=10.0, beta=8./3, rho=28.0): fig = plt.figure() ax = fig.add_axes([0, 0, 1, 1], projection='3d') ax.axis('off') # prepare the axes limits ax.set_xlim((-25, 25)) ax.set_ylim((-35, 35)) ax.set_zlim((5, 55)) def lorenz_deriv(x_y_z, t0, sigma=sigma, beta=beta, rho=rho): """Compute the time-derivative of a Lorenz system.""" x, y, z = x_y_z return [sigma * (y - x), x * (rho - z) - y, x * y - beta * z] # Choose random starting points, uniformly distributed from -15 to 15 np.random.seed(1) x0 = -15 + 30 * np.random.random((N, 3)) # Solve for the trajectories t = np.linspace(0, max_time, int(250*max_time)) x_t = np.asarray([integrate.odeint(lorenz_deriv, x0i, t) for x0i in x0]) # choose a different color for each trajectory colors = plt.cm.jet(np.linspace(0, 1, N)) for i in range(N): x, y, z = x_t[i,:,:].T lines = ax.plot(x, y, z, '-', c=colors[i]) plt.setp(lines, linewidth=2) ax.view_init(30, angle) plt.show() return t, x_t

Let's call the function once to view the solutions. For this set of parameters, we see the trajectories swirling around two points, called attractors.

t, x_t = solve_lorenz(angle=0, N=10)

Using IPython's `interactive`

function, we can explore how the trajectories behave as we change the various parameters.

w = interactive(solve_lorenz, angle=(0.,360.), N=(0,50), sigma=(0.0,50.0), rho=(0.0,50.0)) display(w)

The object returned by `interactive`

is a `Widget`

object and it has attributes that contain the current result and arguments:

t, x_t = w.result

w.kwargs

After interacting with the system, we can take the result and perform further computations. In this case, we compute the average positions in $x$, $y$ and $z$.

xyz_avg = x_t.mean(axis=1)

xyz_avg.shape

Creating histograms of the average positions (across different trajectories) show that on average the trajectories swirl about the attractors.

plt.hist(xyz_avg[:,0]) plt.title('Average $x(t)$')

plt.hist(xyz_avg[:,1]) plt.title('Average $y(t)$')

This post started life as a jupyter notebook, download it or view it online.