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, Audioimport numpy as npAs 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>"display(HTML(dynamite))d1 = display(HTML(dynamite), display_id=True)d2 = display(HTML(dynamite), display_id=True)sample_rate=44100noise = np.random.normal(0, 1, size=sample_rate)display(Audio(noise, rate=sample_rate))'✅ last return will also be shown as last result'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 timetime.sleep(0.5)d2.update(HTML("<h1>💥</h1>"))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>'            else:                table += '<td style="border-color: white;"></td>'        table += '</tr>\n'    table += '</table>'    return tableWe will also need functions to evolve and advance the cells based on their neighbours:
import timedef 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        h.update(HTML(board2html(current)))        time.sleep(0.5)from scipy.signal import convolve# used for counting the number of living neighbors each cell hasFILTER = 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)] = 1And finally, let’s call evolve to draw the evolution:
evolve(30, 20)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!