Rich Output


Rich Output

In Python, objects can declare their textual representation using the __repr__ method. IPython expands on this idea and allows objects to declare other, rich representations including:

  • HTML
  • JSON
  • PNG
  • JPEG
  • SVG
  • LaTeX

A single object can declare some or all of these representations; all are handled by IPython's display system. This Notebook shows how you can use this display system to incorporate a broad range of content into your Notebooks.

Basic display imports

The display function is a general purpose tool for displaying different representations of objects. Think of it as print for these rich representations.


In [1]:
from IPython.display import display

A few points:

  • Calling display on an object will send all possible representations to the Notebook.
  • These representations are stored in the Notebook document.
  • In general the Notebook will use the richest available representation.

If you want to display a particular representation, there are specific functions for that:


In [2]:
from IPython.display import (
    display_pretty, display_html, display_jpeg,
    display_png, display_json, display_latex, display_svg
)

Images

To work with images (JPEG, PNG) use the Image class.


In [3]:
from IPython.display import Image

In [4]:
i = Image(filename='images/ipython_logo.png')

Returning an Image object from an expression will automatically display it:


In [5]:
i


Out[5]:

Or you can pass an object with a rich representation to display:


In [6]:
display(i)


An image can also be displayed from raw data or a URL.


In [7]:
Image(url='http://python.org/images/python-logo.gif')


Out[7]:

SVG images are also supported out of the box.


In [8]:
from IPython.display import SVG
SVG(filename='images/python-logo.svg')


Out[8]:
image/svg+xml

HTML

Python objects can declare HTML representations that will be displayed in the Notebook. If you have some HTML you want to display, simply use the HTML class.


In [9]:
from IPython.display import HTML

In [10]:
s = """<table>
<tr>
<th>Header 1</th>
<th>Header 2</th>
</tr>
<tr>
<td>row 1, cell 1</td>
<td>row 1, cell 2</td>
</tr>
<tr>
<td>row 2, cell 1</td>
<td>row 2, cell 2</td>
</tr>
</table>"""

In [11]:
h = HTML(s)

In [12]:
display(h)


Header 1 Header 2
row 1, cell 1 row 1, cell 2
row 2, cell 1 row 2, cell 2

You can also use the %%html cell magic to accomplish the same thing.


In [13]:
%%html
<table>
<tr>
<th>Header 1</th>
<th>Header 2</th>
</tr>
<tr>
<td>row 1, cell 1</td>
<td>row 1, cell 2</td>
</tr>
<tr>
<td>row 2, cell 1</td>
<td>row 2, cell 2</td>
</tr>
</table>


Header 1 Header 2
row 1, cell 1 row 1, cell 2
row 2, cell 1 row 2, cell 2

JavaScript

The Notebook also enables objects to declare a JavaScript representation. At first, this may seem odd as output is inherently visual and JavaScript is a programming language. However, this opens the door for rich output that leverages the full power of JavaScript and associated libraries such as d3.js for output.


In [14]:
from IPython.display import Javascript

Pass a string of JavaScript source code to the JavaScript object and then display it.


In [15]:
js = Javascript('alert("hi")');

In [16]:
display(js)


The same thing can be accomplished using the %%javascript cell magic:


In [17]:
%%javascript

alert("hi");


LaTeX

The IPython display system also has builtin support for the display of mathematical expressions typeset in LaTeX, which is rendered in the browser using MathJax.

You can pass raw LaTeX test as a string to the Math object:


In [22]:
from IPython.display import Math
Math(r'F(k) = \int_{-\infty}^{\infty} f(x) e^{2\pi i k} dx')


Out[22]:
$$F(k) = \int_{-\infty}^{\infty} f(x) e^{2\pi i k} dx$$

With the Latex class, you have to include the delimiters yourself. This allows you to use other LaTeX modes such as eqnarray:


In [23]:
from IPython.display import Latex
Latex(r"""\begin{eqnarray}
\nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} & = \frac{4\pi}{c}\vec{\mathbf{j}} \\
\nabla \cdot \vec{\mathbf{E}} & = 4 \pi \rho \\
\nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} & = \vec{\mathbf{0}} \\
\nabla \cdot \vec{\mathbf{B}} & = 0 
\end{eqnarray}""")


Out[23]:
\begin{eqnarray} \nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} & = \frac{4\pi}{c}\vec{\mathbf{j}} \\ \nabla \cdot \vec{\mathbf{E}} & = 4 \pi \rho \\ \nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} & = \vec{\mathbf{0}} \\ \nabla \cdot \vec{\mathbf{B}} & = 0 \end{eqnarray}

Or you can enter LaTeX directly with the %%latex cell magic:


In [24]:
%%latex
\begin{align}
\nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} & = \frac{4\pi}{c}\vec{\mathbf{j}} \\
\nabla \cdot \vec{\mathbf{E}} & = 4 \pi \rho \\
\nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} & = \vec{\mathbf{0}} \\
\nabla \cdot \vec{\mathbf{B}} & = 0
\end{align}


\begin{align} \nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} & = \frac{4\pi}{c}\vec{\mathbf{j}} \\ \nabla \cdot \vec{\mathbf{E}} & = 4 \pi \rho \\ \nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} & = \vec{\mathbf{0}} \\ \nabla \cdot \vec{\mathbf{B}} & = 0 \end{align}

Audio

IPython makes it easy to work with sounds interactively. The Audio display class allows you to create an audio control that is embedded in the Notebook. The interface is analogous to the interface of the Image display class. All audio formats supported by the browser can be used. Note that no single format is presently supported in all browsers.


In [25]:
from IPython.display import Audio
Audio(url="http://www.nch.com.au/acm/8k16bitpcm.wav")


Out[25]:

A NumPy array can be auralized automatically. The Audio class normalizes and encodes the data and embeds the resulting audio in the Notebook.

For instance, when two sine waves with almost the same frequency are superimposed a phenomena known as beats occur. This can be auralised as follows:


In [26]:
import numpy as np
max_time = 3
f1 = 220.0
f2 = 224.0
rate = 8000.0
L = 3
times = np.linspace(0,L,rate*L)
signal = np.sin(2*np.pi*f1*times) + np.sin(2*np.pi*f2*times)

Audio(data=signal, rate=rate)


Out[26]:

Video

More exotic objects can also be displayed, as long as their representation supports the IPython display protocol. For example, videos hosted externally on YouTube are easy to load:


In [27]:
from IPython.display import YouTubeVideo
YouTubeVideo('sjfsUzECqK0')


Out[27]:

Using the nascent video capabilities of modern browsers, you may also be able to display local videos. At the moment this doesn't work very well in all browsers, so it may or may not work for you; we will continue testing this and looking for ways to make it more robust.

The following cell loads a local file called animation.m4v, encodes the raw video as base64 for http transport, and uses the HTML5 video tag to load it. On Chrome 15 it works correctly, displaying a control bar at the bottom with a play/pause button and a location slider.


In [28]:
from IPython.display import HTML
from base64 import b64encode
video = open("images/animation.m4v", "rb").read()
video_encoded = b64encode(video).decode('ascii')
video_tag = '<video controls alt="test" src="data:video/x-m4v;base64,{0}">'.format(video_encoded)
HTML(data=video_tag)


Out[28]:

External sites

You can even embed an entire page from another site in an iframe; for example this is today's Wikipedia page for mobile users:


In [29]:
from IPython.display import IFrame
IFrame('http://ipython.org', width='100%', height=350)


Out[29]: