Notebook Magics

In [1]:
import pandas as pd
import numpy as np
import holoviews as hv
from holoviews import opts
hv.extension('bokeh', 'matplotlib')

The Applying Customizations user guide describes the currently recommended way to customize your visualizations in HoloViews. Those mechanisms use standard Python syntax but they are not the only way to apply options as there is a much older approach for working with HoloViews that is specific to notebooks.

From the start, HoloViews aimed to enable rapid exploration of data in Jupyter Notebooks. For this reason, when you load the HoloViews extension in a notebook, you also get a set of IPython magics. IPython magics use a syntax that is not standard Python and the HoloViews magics only apply in the notebook environment (and not the IPython terminal for instance).

The advantages of the notebook magics are:

  • They allow tab-completion in the notebook environment (but so do the more recent option builders and hv.output mechanisms).
  • They allow very concise expression of options and settings.

Unfortunately, they also have some serious disadvantages:

  • They are not Python syntax which makes it difficult to use code written with magics in notebooks anywhere else. For instance, it makes it harder to use such code with bokeh server or panel.
  • They have their own special syntax which is very concise but also rather mysterious.

These disadvantages means the magics can be bewildering to anyone unfamiliar with the IPython specific syntax and HoloViews itself, and are no longer recommended for these reasons. This user guide documents these magics to allow people to understand older notebooks using HoloViews and to help people update these old notebooks to use the recommended Python API.

Line and cell magics

There are two types of magic supported in Jupyter notebooks called line magics and cell magics respectively. Both typically appear at the top of code cells prefixed by % (line magics) or %% (cell magics).

  • line magics: These can appear anywhere in a code cell and effect global changes to the current notebook session. HoloViews has the %opts and %output line magics.
  • cell magics: These have to appear at the top of the cell and are used to modify how that cell is executed. HoloViews has the %%opts and %%ouput cell magics.

The %opts and %%opts magics

These two magics are now served by opts.defaults and the .opts method respectively, as described in the Applying Customizations user guide.

  • The %opts line magic: IPython specific syntax applied globally [string format]
  • The %%opts cell magic: IPython specific syntax applies to displayed object [string format]

These magics have their own syntax that separates between style, plot and norm options described towards the end of the Applying Customizations user guide. The definition of the syntax is as follows:

[[spec] [normalization] [plotting options] [style options]]+

spec:             A dotted type.group.label specification
                  (e.g. Curve,Sinusoid.Squared)

normalization:    List of normalization options delimited by braces.
                  One of | -axiswise | -framewise | +axiswise | +framewise |
                  E.g. { +axiswise +framewise }

plotting options: List of plotting option keywords delimited by
                  square brackets. E.g. [show_title=False]

style options:    List of style option keywords delimited by
                  parentheses. E.g. (lw=10 marker='+')

In other words, you have a list of spec strings (for instance Curve or Curve.Sinusoid) followed by keywords in either parentheses, square brackets or braces to represent the style, plot and normalization options respectively.

Example %%opts cell magic

Here is the example from the Customization section of the 'Getting Started' customized using the %%opts cell magic:

In [2]:
%%opts Curve  [height=200 width=900 xaxis=None tools=['hover']]
%%opts Curve (color='red' line_width=1.5)
%%opts Spikes [height=150 width=900 yaxis=None] (color='grey' line_width=0.25)

spike_train = pd.read_csv('../assets/spike_train.csv.gz')
curve  = hv.Curve( spike_train, 'milliseconds', vdims='Hertz')
spikes = hv.Spikes(spike_train, 'milliseconds', vdims=[])
layout = (curve+spikes).cols(1)
layout
Out[2]:

This layout object is now customized in a way that will persist, just like it would using the recommended .opts method together with option builders. It is worth noting that instead of just using element names, you can specify the group and label (e.g Curve.Sinusoid.Squared) to condition on that metadata, just the way you can using the option builders.

Example %opts line magic

Here is how you could use the %opts line magic instead of opts.default as detailed in the Applying Customizations user guide:

In [3]:
%opts HeatMap (cmap='Summer') [colorbar=True, toolbar='above']

Now all HeatMap elements will use the 'Summer' colormap, showing a colorbar with the Bokeh toolbar at the top:

In [4]:
data = [(chr(65+i), chr(97+j),  i*j) for i in range(5) for j in range(5) if i!=j]
hv.HeatMap(data).sort()
Out[4]:

The %output line magic

The %output line magic has been fairly directly replaced by the hv.output utility. Here is an example of the %output line magic:

In [5]:
%output backend='matplotlib', fig='svg'

This ensures the following Path (and all subsequent Path objects) are rendered as SVG with matplotlib:

In [6]:
lin = np.linspace(0, np.pi*2, 200)

def lissajous(t, a, b, delta):
    return (np.sin(a * t + delta), np.sin(b * t), t)

path = hv.Path([lissajous(lin, 3, 5, np.pi/2)])
path.opts(opts.Path(linewidth=2, color='red', linestyle='dotted'))
Out[6]:

For the purposes of this notebook, let us switch the plotting extension back to bokeh:

In [7]:
%output backend='bokeh'

Note that the %output magic accepts the same set of output settings as the hv.output utility.

The %%output cell magic

If we want to temporarily switch to matplotlib with some custom output settings, we can use the %%output cell magic in an example combines the %%output and %%opts cell magics in the same cell:

In [8]:
%%output backend='matplotlib' fig='svg' size=50
%%opts Path (linewidth=3 color='blue')
lin = np.linspace(0, np.pi*2, 200)

def lissajous(t, a, b, delta):
    return (np.sin(a * t + delta), np.sin(b * t), t)

hv.Path([lissajous(lin, 3, 5, np.pi/2)])
Out[8]:

The recommended approach would now be to pass the path object to the hv.output utility as detailed in the Applying Customizations user guide. The magic processes the same set of output settings as the hv.output utility.