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>"
display(HTML(dynamite))
d1 = display(HTML(dynamite), display_id=True)
d2 = display(HTML(dynamite), display_id=True)
sample_rate=44100
noise = 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 time
time.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 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
h.update(HTML(board2html(current)))
time.sleep(0.5)
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)
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!