Jupyter Display Playground

Nextjournal’s Jupyter runtimes now fully support all of Jupyter’s display kernel messages. Remix this notebook to try them out yourself.

This notebook already uses a Python Jupyter runtime. You can select a runtime’s type (e.g. Jupyter or Nextjournal) via the runtime settings menu (available from the sidebar or from the runtimes section listed at the bottom of this document).

Showing multiple results

Let’s start by running this cell to import IPython.display and also numpy for some of the following examples:

from IPython.display import display, HTML, Audio
import numpy as np

As you run the next cell, you will see that calling display multiple times (each time passing a rich media/MIME bundle object) will stack corresponding results below the cell:

dynamite = "<h1>🧨</h1>"
d1 = display(HTML(dynamite), display_id=True)
d2 = display(HTML(dynamite), display_id=True)
noise = np.random.normal(0, 1, size=sample_rate)
display(Audio(noise, rate=sample_rate))
'✅ last return will also be shown as last result'
Shift+Enter to run

Updating results

In addition to that, we also support changing display objects in place by calling update on the display handle. Note that, when running the following cell, the last 🧨 from the above cell’s results will turn into a 💥.

import time

To demonstrate a more elaborate version of this, let’s implement Conway's Game of Life based on code by @gvwilson & @jiffyclub.

First, let’s set up a function that draws the cells:

def board2html(board):
    nx, ny = board.shape
    table = '<table style="border-color: black; border-width: 3px; border-bottom: 3px !important;">\n'
    for y in range(ny-1, -1, -1):
        table += '<tr>'
        for x in range(0, nx):
            if board[x, y]:
                table += '<td style="background: black; border-color: white;"></td>'
                table += '<td style="border-color: white;"></td>'
        table += '</tr>\n'
    table += '</table>'
    return table

We will also need functions to evolve and advance the cells based on their neighbours:

import time
def evolve(length, generations):
    current = np.random.randint(2, size=(length, length))
    next = np.empty_like(current)
    h = display(HTML(board2html(current)), display_id=True)
    for _ in range(generations):
        advance(current, next)
        current, next = next, current
from scipy.signal import convolve
# used for counting the number of living neighbors each cell has
FILTER = np.array([[1, 1, 1],
                   [1, 100, 1],
                   [1, 1, 1]], dtype=np.uint8)
def advance(current, next):
    assert current.shape[0] == current.shape[1], 'Expected square universe'
    next[:] = 0
    count = convolve(current, FILTER, mode='same')
    next[(count == 3) | (count == 102) | (count == 103)] = 1

And finally, let’s call evolve to draw the evolution:

evolve(30, 20)
Shift+Enter to run

That’s it for now. You can read up on Jupyter’s kernel display messages in the Project Jupyter Docs and if you have feedback for us, please get in touch!

Runtimes (1)