The main idea of the first approach is that you have to implement special display methods when you define your class, one for each representation you want to use. Here is a list of the names of the special methods and the values they must return:

_repr_html_: return raw HTML as a string

_repr_json_: return a JSONable dict

_repr_jpeg_: return raw JPEG data

_repr_png_: return raw PNG data

_repr_svg_: return raw SVG data as a string

_repr_latex_: return LaTeX commands in a string surrounded by "$".

As an illustration, we build a class that holds data generated by sampling a Gaussian distribution with given mean and standard deviation. Here is the definition of the Gaussian class, which has a custom PNG and LaTeX representation.

In [3]:

fromIPython.core.pylabtoolsimportprint_figurefromIPython.displayimportImage,SVG,MathclassGaussian(object):"""A simple object holding data sampled from a Gaussian distribution. """def__init__(self,mean=0.0,std=1,size=1000):self.data=np.random.normal(mean,std,size)self.mean=meanself.std=stdself.size=size# For caching plots that may be expensive to computeself._png_data=Nonedef_figure_data(self,format):fig,ax=plt.subplots()ax.hist(self.data,bins=50)ax.set_title(self._repr_latex_())ax.set_xlim(-10.0,10.0)data=print_figure(fig,format)# We MUST close the figure, otherwise IPython's display machinery# will pick it up and send it as output, resulting in a double displayplt.close(fig)returndatadef_repr_png_(self):ifself._png_dataisNone:self._png_data=self._figure_data('png')returnself._png_datadef_repr_latex_(self):returnr'$\mathcal{N}(\mu=%.2g, \sigma=%.2g),\ N=%d$'%(self.mean,self.std,self.size)

Create an instance of the Gaussian distribution and return it to display the default representation:

In [4]:

x=Gaussian(2.0,1.0)x

Out[4]:

$\mathcal{N}(\mu=2, \sigma=1),\ N=1000$

You can also pass the object to the display function to display the default representation:

In [5]:

display(x)

$\mathcal{N}(\mu=2, \sigma=1),\ N=1000$

Use display_png to view the PNG representation:

In [6]:

display_png(x)

It is important to note a subtle different between display and display_png. The former computes all representations of the object, and lets the notebook UI decide which to display. The later only computes the PNG representation.

Create a new Gaussian with different parameters:

In [7]:

x2=Gaussian(0,2,2000)x2

Out[7]:

$\mathcal{N}(\mu=0, \sigma=2),\ N=2000$

You can then compare the two Gaussians by displaying their histograms:

In [8]:

display_png(x)display_png(x2)

Note that like print, you can call any of the display functions multiple times in a cell.

When you are directly writing your own classes, you can adapt them for display in IPython by following the above approach. But in practice, you often need to work with existing classes that you can't easily modify. We now illustrate how to add rich output capabilities to existing objects. We will use the NumPy polynomials and change their default representation to be a formatted LaTeX expression.

First, consider how a NumPy polynomial object renders by default:

In [9]:

p=np.polynomial.Polynomial([1,2,3],[-10,10])p

Out[9]:

Polynomial([ 1., 2., 3.], [-10., 10.], [-1, 1])

Next, define a function that pretty-prints a polynomial as a LaTeX string:

However, you can configure IPython to do this automatically by registering the Polynomial class and the plot_to_latex function with an IPython display formatter. Let's look at the default formatters provided by IPython:

The formatters attribute is a dictionary keyed by MIME types. To define a custom LaTeX display function, you want a handle on the text/latex formatter:

In [14]:

ip=get_ipython()latex_f=ip.display_formatter.formatters['text/latex']

The formatter object has a couple of methods for registering custom display functions for existing types.

In [15]:

help(latex_f.for_type)

Help on method for_type in module IPython.core.formatters:
for_type(typ, func=None) method of IPython.core.formatters.LatexFormatter instance
Add a format function for a given type.
Parameters
-----------
typ : type or '__module__.__name__' string for a type
The class of the object that will be formatted using `func`.
func : callable
A callable for computing the format data.
`func` will be called with the object to be formatted,
and will return the raw data in this formatter's format.
Subclasses may use a different call signature for the
`func` argument.
If `func` is None or not specified, there will be no change,
only returning the current value.
Returns
-------
oldfunc : callable
The currently registered callable.
If you are registering a new formatter,
this will be the previous value (to enable restoring later).

In [16]:

help(latex_f.for_type_by_name)

Help on method for_type_by_name in module IPython.core.formatters:
for_type_by_name(type_module, type_name, func=None) method of IPython.core.formatters.LatexFormatter instance
Add a format function for a type specified by the full dotted
module and name of the type, rather than the type of the object.
Parameters
----------
type_module : str
The full dotted name of the module the type is defined in, like
``numpy``.
type_name : str
The name of the type (the class name), like ``dtype``
func : callable
A callable for computing the format data.
`func` will be called with the object to be formatted,
and will return the raw data in this formatter's format.
Subclasses may use a different call signature for the
`func` argument.
If `func` is None or unspecified, there will be no change,
only returning the current value.
Returns
-------
oldfunc : callable
The currently registered callable.
If you are registering a new formatter,
this will be the previous value (to enable restoring later).

In this case, we will use for_type_by_name to register poly_to_latex as the display function for the Polynomial type:

Rich output special methods and functions can only display one object or MIME type at a time. Sometimes this is not enough if you want to display multiple objects or MIME types at once. An example of this would be to use an HTML representation to put some HTML elements in the DOM and then use a JavaScript representation to add events to those elements.

IPython 2.0 recognizes another display method, _ipython_display_, which allows your objects to take complete control of displaying themselves. If this method is defined, IPython will call it, and make no effort to display the object using the above described _repr_*_ methods for custom display functions. It's a way for you to say "Back off, IPython, I can display this myself." Most importantly, your _ipython_display_ method can make multiple calls to the top-level display functions to accomplish its goals.

Here is an object that uses display_html and display_javascript to make a plot using the Flot JavaScript plotting library: