Elements ¶
Element
s are the basic building blocks for any HoloViews visualization. These are the objects that can be composed together using the various
Container
types.
Here in this overview, we show an example of how to build each of these
Element
s directly out of Python or Numpy data structures. An even more powerful way to use them is by collecting similar
Element
s into a HoloMap, as described in
Exploring Data
, so that you can explore, select, slice, and animate them flexibly, but here we focus on having small, selfcontained examples. Complete reference material for each type can be accessed using our
documentation system
. This tutorial uses the default matplotlib plotting backend; see the
Bokeh Elements
tutorial for the corresponding bokeh plots.
Element types ¶
This class hierarchy shows each of the
Element
types.
Each type is named for the default or expected way that the underlying data can be visualized. E.g., if your data is wrapped into a
Surface
object, it will display as a 3D surface by default, whereas the same data embedded in an
Image
object will display as a 2D raster image. But please note that the specification and implementation for each
Element
type does not actually include
any
such visualization  the name merely serves as a semantic indication that you ordinarily think of the data as being laid out visually in that way. The actual plotting is done by a separate plotting subsystem, while the objects themselves focus on storing your data and the metadata needed to describe and use it.
This separation of data and visualization is described in detail in the
Options tutorial
, which describes all about how to find out the options available for each
Element
type and change them if necessary, from either Python or IPython Notebook. When using this tutorial interactively in an IPython/Jupyter notebook session, we suggest adding
%output info=True
after the call to
notebook_extension
below, which will pop up a detailed list and explanation of the available options for visualizing each
Element
type, after that notebook cell is executed. Then, to find out all the options for any of these
Element
types, just press
<ShiftEnter>
on the corresponding cell in the live notebook.
The types available:

Element

The base class of all
Elements
.
Charts:
¶

Curve
 A continuous relation between a dependent and an independent variable.

ErrorBars
 A collection of x/ycoordinates with associated error magnitudes.

Spread
 Continuous version of ErrorBars.

Area

Bars
 Data collected and binned into categories.

Histogram
 Data collected and binned in a continuous space using specified bin edges.

BoxWhisker
 Distributions of data varying by 0N key dimensions.

Scatter
 Discontinuous collection of points indexed over a single dimension.

Points
 Discontinuous collection of points indexed over two dimensions.

VectorField
 Cyclic variable (and optional auxiliary data) distributed over twodimensional space.

Spikes
 A collection of horizontal or vertical lines at various locations with fixed height (1D) or variable height (2D).

SideHistogram

Histogram binning data contained by some other
Element
.
Chart3D Elements:
¶

Surface
 Continuous collection of points in a threedimensional space.

Scatter3D
 Discontinuous collection of points in a threedimensional space.

Trisurface
 Continuous but irregular collection of points interpolated into a Surface using Delaunay triangulation.
Raster Elements:
¶

Raster
 The base class of all rasters containing twodimensional arrays.

QuadMesh
 Raster type specifying 2D bins with twodimensional array of values.

HeatMap
 Raster displaying sparse, discontinuous data collected in a twodimensional space.

Image
 Raster containing a twodimensional array covering a continuous space (sliceable).

RGB
 Image with 3 (R,G,B) or 4 (R,G,B,Alpha) color channels.

HSV
 Image with 3 (Hue, Saturation, Value) or 4 channels.
Tabular Elements:
¶

ItemTable
 Ordered collection of keyvalue pairs (ordered dictionary).

Table
 Collection of arbitrary data with arbitrary key and value dimensions.
Annotations:
¶

VLine
 Vertical line annotation.

HLine
 Horizontal line annotation.

Spline
 Bezier spline (arbitrary curves).

Text

Text annotation on an
Element
. 
Arrow

Arrow on an
Element
with optional text label.
Paths:
¶

Path
 Collection of paths.

Contours
 Collection of paths, each with an associated value.

Polygons
 Collection of filled, closed paths with an associated value.

Bounds
 Box specified by corner positions.

Box
 Box specified by center position, radius, and aspect ratio.

Ellipse
 Ellipse specified by center position, radius, and aspect ratio.
Element
¶
The basic or fundamental types of data that can be visualized.
Element
is the base class for all the other HoloViews objects shown in this section.
All
Element
objects accept
data
as the first argument to define the contents of that element. In addition to its implicit type, each element object has a
group
string defining its category, and a
label
naming this particular item, as described in the
Introduction
.
When rich display is off, or if no visualization has been defined for that type of
Element
, the
Element
is presented with a default textual representation:
import holoviews as hv
hv.notebook_extension()
hv.Element(None, group='Value', label='Label')
In addition,
Element
has key dimensions (
kdims
), value dimensions (
vdims
), and constant dimensions (
cdims
) to describe the semantics of indexing within the
Element
, the semantics of the underlying data contained by the
Element
, and any constant parameters associated with the object, respectively.
Dimensions are described in the
Introduction
.
The remaining
Element
types each have a rich, graphical display as shown below.
Chart
Elements
¶
Visualization of a dependent variable against an independent variable
The first large class of
Elements
is the
Chart
elements. These objects have at least one fully indexable, sliceable key dimension (typically the
x
axis in a plot), and usually have one or more value dimension(s) (often the
y
axis) that may or may not be indexable depending on the implementation. The key dimensions are normally the parameter settings for which things are measured, and the value dimensions are the data points recorded at those settings.
As described in the Columnar Data tutorial , the data can be stored in several different internal formats, such as a NumPy array of shape (N, D), where N is the number of samples and D the number of dimensions. A somewhat larger list of formats can be accepted, including any of the supported internal formats, or
 As a list of length N containing tuples of length D.
 As a tuple of length D containing iterables of length N.
Curve
¶
import numpy as np
points = [(0.1*i, np.sin(0.1*i)) for i in range(100)]
hv.Curve(points)
A
Curve
is a set of values provided for some set of keys from a
continuously indexable 1D coordinate system
, where the plotted values will be connected up because they are assumed to be samples from a continuous relation.
ErrorBars
¶
np.random.seed(7)
points = [(0.1*i, np.sin(0.1*i)) for i in range(100)]
errors = [(0.1*i, np.sin(0.1*i), np.random.rand()/2) for i in np.linspace(0, 100, 11)]
hv.Curve(points) * hv.ErrorBars(errors)
ErrorBars
is a set of x/ycoordinates with associated error values. Error values may be either symmetric or asymmetric, and thus can be supplied as an Nx3 or Nx4 array (or any of the alternative constructors Chart Elements allow).
%%opts ErrorBars (capthick=3)
points = [(0.1*i, np.sin(0.1*i)) for i in range(100)]
errors = [(0.1*i, np.sin(0.1*i), np.random.rand()/2, np.random.rand()/4) for i in np.linspace(0, 100, 11)]
hv.Curve(points) * hv.ErrorBars(errors, vdims=['y', 'yerrneg', 'yerrpos'])
Spread
¶
Spread
elements have the same data format as the
ErrorBars
element, namely x and yvalues with associated symmetric or assymetric errors, but are interpreted as samples from a continuous distribution (just as
Curve
is the continuous version of
Scatter
). These are often paired with an overlaid
Curve
to show both the mean (as a curve) and the spread of values; see the
Columnar Data tutorial
for examples.
Symmetric ¶
np.random.seed(42)
xs = np.linspace(0, np.pi*2, 20)
err = 0.2+np.random.rand(len(xs))
hv.Spread((xs, np.sin(xs), err))
Asymmetric ¶
%%opts Spread (facecolor='indianred' alpha=1)
xs = np.linspace(0, np.pi*2, 20)
hv.Spread((xs, np.sin(xs), 0.1+np.random.rand(len(xs)), 0.1+np.random.rand(len(xs))),
vdims=['y', 'yerrneg', 'yerrpos'])
Area
¶
Area under the curve
By default the Area Element draws just the area under the curve, i.e. the region between the curve and the origin.
xs = np.linspace(0, np.pi*4, 40)
hv.Area((xs, np.sin(xs)))
Area between curves
When supplied a second value dimension the area is defined as the area between two curves.
X = np.linspace(0,3,200)
Y = X**2 + 3
Y2 = np.exp(X) + 2
Y3 = np.cos(X)
hv.Area((X, Y, Y2), vdims=['y', 'y2']) * hv.Area((X, Y, Y3), vdims=['y', 'y3'])
Bars
¶
data = [('one',8),('two', 10), ('three', 16), ('four', 8), ('five', 4), ('six', 1)]
bars = hv.Bars(data, kdims=[hv.Dimension('Car occupants', values='initial')], vdims=['Count'])
bars + bars[['one', 'two', 'three']]
Bars
is an
NdElement
type, so by default it is sorted. To preserve the initial ordering specify the
Dimension
with values set to 'initial', or you can supply an explicit list of valid dimension keys.
Bars
support up to three key dimensions which can be laid by
'group'
,
'category'
, and
'stack'
dimensions. By default the key dimensions are mapped onto the first, second, and third
Dimension
of the
Bars
object, but this behavior can be overridden via the
group_index
,
category_index
, and
stack_index
options. You can also style each bar the way you want by creating style groups for any combination of the three dimensions. Here we color_by
'category'
and
'stack'
, so that a given color represents some combination of those two values (according to the key shown).
%%opts Bars [color_by=['category', 'stack'] legend_position='top']
from itertools import product
np.random.seed(1)
groups, categories, stacks = ['A', 'B'], ['a', 'b'], ['I', 'II']
keys = product(groups, categories, stacks)
hv.Bars([(k, np.random.rand()*100) for k in keys],
kdims=['Group', 'Category', 'Stack'], vdims=['Count'])
BoxWhisker
¶
The
BoxWhisker
Element allows representing distributions of data varying by 0N key dimensions. To represent the distribution of a single variable, we can create a BoxWhisker Element with no key dimensions and a single value dimension:
hv.BoxWhisker(np.random.randn(200), kdims=[], vdims=['Value'])
BoxWhisker Elements support any number of dimensions and may also be rotated. To style the boxes and whiskers, supply
boxprops
,
whiskerprops
, and
flierprops
.
%%opts BoxWhisker [fig_size=200 invert_axes=True]
style = dict(boxprops=dict(color='gray', linewidth=1), whiskerprops=dict(color='indianred', linewidth=1))
groups = [chr(65+g) for g in np.random.randint(0, 3, 200)]
hv.BoxWhisker((groups, np.random.randint(0, 5, 200), np.random.randn(200)),
kdims=['Group', 'Category'], vdims=['Value'])(style=style).sort()
BoxWhisker
Elements may also be used to represent a distribution as a marginal plot by adjoining it using
<<
.
points = hv.Points(np.random.randn(500, 2))
points << hv.BoxWhisker(points['y']) << hv.BoxWhisker(points['x'])
Histogram
¶
np.random.seed(1)
data = [np.random.normal() for i in range(10000)]
frequencies, edges = np.histogram(data, 20)
hv.Histogram(frequencies, edges)
Histogram
s partition the
x
axis into discrete (but not necessarily regular) bins, showing counts in each as a bar.
Almost all Element types, including
Histogram
, may be projected onto a polar axis by supplying
projection='polar'
as a plot option.
%%opts Histogram [projection='polar' show_grid=True]
data = [np.random.rand()*np.pi*2 for i in range(100)]
frequencies, edges = np.histogram(data, 20)
hv.Histogram(frequencies, edges, kdims=['Angle'])
Scatter
¶
%%opts Scatter (color='k', marker='s', s=50)
np.random.seed(42)
points = [(i, np.random.random()) for i in range(20)]
hv.Scatter(points) + hv.Scatter(points)[12:20]
Scatter is the discrete equivalent of Curve, showing
y
values for discrete
x
values selected. See
Points
for more information.
The marker shape specified above can be any supported by
matplotlib
, e.g.
s
,
d
, or
o
; the other options select the color and size of the marker. For convenience with the
bokeh backend
, the matplotlib marker options are supported using a compatibility function in HoloViews.
Points
¶
np.random.seed(12)
points = np.random.rand(50,2)
hv.Points(points) + hv.Points(points)[0.6:0.8,0.2:0.5]
As you can see,
Points
is very similar to
Scatter
, and can produce some plots that look identical. However, the two
Element
s are very different semantically. For
Scatter
, the dots each show a dependent variable
y
for some
x
, such as in the
Scatter
example above where we selected regularly spaced values of
x
and then created a random number as the corresponding
y
. I.e., for
Scatter
, the
y
values are the data; the
x
s are just where the data values are located. For
Points
, both
x
and
y
are independent variables, known as
key_dimensions
in HoloViews:
for o in [hv.Points(points,name="Points "), hv.Scatter(points,name="Scatter")]:
for d in ['key','value']:
print("%s %s_dimensions: %s " % (o.name, d, o.dimensions(d,label=True)))
The
Scatter
object expresses a dependent relationship between
x
and
y
, making it useful for combining with other similar
Chart
types, while the
Points
object expresses the relationship of two independent keys
x
and
y
with optional
vdims
(zero in this case), which makes
Points
objects meaningful to combine with the
Raster
types below.
Of course, the
vdims
need not be empty for
Points
; here is an example with two additional quantities for each point, as
value_dimension
s
z
and α visualized as the color and size of the dots, respectively. The point sizes can be tweaked using the option
scaling_factor
, which determines the amount by which each point width or area is scaled, depending on the value of
scaling_method
.
%%opts Points [color_index=2 size_index=3 scaling_method="width" scaling_factor=10]
np.random.seed(10)
data = np.random.rand(100,4)
points = hv.Points(data, vdims=['z', 'alpha'])
points + points[0.3:0.7, 0.3:0.7].hist()
Such a plot wouldn't be meaningful for
Scatter
, but is a valid use for
Points
, where the
x
and
y
locations are independent variables representing coordinates, and the "data" is conveyed by the size and color of the dots.
Spikes
¶
Spikes represent any number of horizontal or vertical line segments with fixed or variable heights. There are a number of disparate uses for this type. First of all, they may be used as a rugplot to give an overview of a onedimensional distribution. They may also be useful in more domainspecific cases, such as visualizing spike trains for neurophysiology or spectrograms in physics and chemistry applications.
In the simplest case, a Spikes object represents coordinates in a 1D distribution:
%%opts Spikes (alpha=0.4)
xs = np.random.rand(50)
ys = np.random.rand(50)
hv.Points((xs, ys)) * hv.Spikes(xs)
When supplying two dimensions to the Spikes object, the second dimension will be mapped onto the line height. Optionally, you may also supply a cmap and color_index to map color onto one of the dimensions. This way we can, for example, plot a mass spectrogram:
%%opts Spikes (cmap='Reds')
hv.Spikes(np.random.rand(20, 2), kdims=['Mass'], vdims=['Intensity'])
Another possibility is to draw a number of spike trains as you would encounter in neuroscience. Here we generate 10 separate random spike trains and distribute them evenly across the space by setting their
position
. By also declaring some
yticks
, each spike train can be labeled individually:
%%opts Spikes NdOverlay [show_legend=False]
hv.NdOverlay({i: hv.Spikes(np.random.randint(0, 100, 10), kdims=['Time'])(plot=dict(position=0.1*i))
for i in range(10)})(plot=dict(yticks=[((i+1)*0.10.05, i) for i in range(10)]))
Finally, we may use
Spikes
to visualize marginal distributions as adjoined plots using the
<<
adjoin operator:
%%opts Spikes (alpha=0.05) [spike_length=1]
points = hv.Points(np.random.randn(500, 2))
points << hv.Spikes(points['y']) << hv.Spikes(points['x'])
VectorField
¶
%%opts VectorField [size_index=3]
y,x = np.mgrid[10:10,10:10] * 0.25
sine_rings = np.sin(x**2+y**2)*np.pi+np.pi
exp_falloff = 1/np.exp((x**2+y**2)/8)
vector_data = [x,y,sine_rings, exp_falloff]
hv.VectorField(vector_data)
As you can see above, here the x and y positions are chosen to make a regular grid. The arrow angles follow a sinsoidal ring pattern, and the arrow lengths fall off exponentially from the center, so this plot has four dimensions of data (direction and length for each x,y position).
Using the IPython
%%opts
cellmagic (described in the
Options tutorial
, along with the Python equivalent), we can also use color as a redundant indicator to the direction or magnitude:
%%opts VectorField [size_index=3] VectorField.A [color_index=2] VectorField.M [color_index=3]
hv.VectorField(vector_data, group='A') + hv.VectorField(vector_data, group='M')
The vector fields above were sampled on a regular grid, but any collection of x,y values is allowed:
n=20
x=np.linspace(1,3,n)
y=np.sin(np.linspace(0,2*np.pi,n))/4
hv.VectorField([x,y,x*5,np.ones(n)]) * hv.VectorField([x,y,x*5,np.ones(n)])
SideHistogram
¶
The
.hist
method conveniently adjoins a histogram to the side of any
Chart
,
Surface
, or
Raster
component, as well as many of the container types (though it would be reporting data from one of these underlying
Element
types). For a
Raster
using color or grayscale to show values (see
Raster
section below), the side histogram doubles as a color bar or key.
import numpy as np
np.random.seed(42)
points = [(i, np.random.normal()) for i in range(800)]
hv.Scatter(points).hist()
Chart3D
Elements
¶
Surface
¶
%%opts Surface (cmap='jet' rstride=20, cstride=2)
hv.Surface(np.sin(np.linspace(0,100*np.pi*2,10000)).reshape(100,100))
Surface is used for a set of gridded points whose associated value dimension represents samples from a continuous surface; it is the equivalent of a
Curve
but with two key dimensions instead of just one.
Scatter3D
¶
%%opts Scatter3D [azimuth=40 elevation=20]
y,x = np.mgrid[5:5, 5:5] * 0.1
heights = np.sin(x**2+y**2)
hv.Scatter3D(zip(x.flat,y.flat,heights.flat))
Scatter3D
is the equivalent of
Scatter
but for two key dimensions, rather than just one.
Trisurface
¶
The
Trisurface
Element renders any collection of 3D points as a Surface by applying Delaunay triangulation. It thus supports arbitrary, nongridded data, but it does not support indexing to find data values, since finding the closest ones would require a search.
%%opts Trisurface [fig_size=200] (cmap='hot_r')
hv.Trisurface((x.flat,y.flat,heights.flat))
Raster
Elements
¶
A collection of raster image types
The second large class of
Elements
is the raster elements. Like
Points
and unlike the other
Chart
elements,
Raster Elements
live in a 2D keydimensions space. For the
Image
,
RGB
, and
HSV
elements, the coordinates of this twodimensional key space are defined in a
continuously indexable coordinate system
. We can use
np.meshgrid
to define the appropriate sampling along the
x
and
y
dimensions:
x,y = np.meshgrid(np.linspace(5,5,101), np.linspace(5,5,101))
Raster
¶
A
Raster
is the base class for imagelike
Elements
, but may be used directly to visualize 2D arrays using a color map. The coordinate system of a
Raster
is the raw indexes of the underlying array, with integer values always starting from (0,0) in the top left, with default extents corresponding to the shape of the array. The
Image
subclass visualizes similarly, but using a continuous Cartesian coordinate system suitable for an array that represents some underlying continuous region.
hv.Raster(np.sin(x**2+y**2))
QuadMesh
¶
The basic
QuadMesh
is a 2D grid of bins specified as x/yvalues specifying a regular sampling or edges, with arbitrary sampling and an associated 2D array containing the bin values. The coordinate system of a
QuadMesh
is defined by the bin edges, therefore any index falling into a binned region will return the appropriate value. Unlike
Image
objects, slices must be inclusive of the bin edges.
n = 21
xs = np.logspace(1, 3, n)
ys = np.linspace(1, 10, n)
hv.QuadMesh((xs, ys, np.random.rand(n1, n1)))
QuadMesh may also be used to represent an arbitrary mesh of quadrilaterals by supplying three separate 2D arrays representing the coordinates of each quadrilateral in a 2D space. Note that when using
QuadMesh
in this mode, slicing and indexing semantics and most operations will currently not work.
coords = np.linspace(1.5,1.5,n)
X,Y = np.meshgrid(coords, coords);
Qx = np.cos(Y)  np.cos(X)
Qz = np.sin(Y) + np.sin(X)
Z = np.sqrt(X**2 + Y**2)
hv.QuadMesh((Qx, Qz, Z))
HeatMap
¶
A
HeatMap
displays like a typical raster image, but the input is a dictionary indexed with twodimensional keys, not a Numpy array or Pandas dataframe. As many rows and columns as required will be created to display the values in an appropriate grid format. Values unspecified are left blank, and the keys can be any Python datatype (not necessarily numeric). One typical usage is to show values from a set of experiments, such as a parameter space exploration, and many other such visualizations are shown in the
Containers
and
Exploring Data
tutorials. Each value in a
HeatMap
is labeled explicitly by default, and so this component is not meant for very large numbers of samples. With the default color map, high values (in the upper half of the range present) are colored orange and red, while low values (in the lower half of the range present) are colored shades of blue.
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()
Image
¶
Like
Raster
, a HoloViews
Image
allows you to view 2D arrays using an arbitrary color map. Unlike
Raster
, an
Image
is associated with a
2D coordinate system in continuous space
, which is appropriate for values sampled from some underlying continuous distribution (as in a photograph or other measurements from locations in real space). Slicing, sampling, etc. on an
Image
all use this continuous space, whereas the corresponding operations on a
Raster
work on the raw array coordinates.
To make the coordinate system clear, we'll define two arrays called
xs
and
ys
with a nonsquare aspect and map them through a simple function that illustrate how these inputs relate to the coordinate system:
bounds=(2,3,5,2) # Coordinate system: (left, bottom, top, right)
xs,ys = np.meshgrid(np.linspace(2,5,50), np.linspace(2,3, 30))
(hv.Image(np.sin(xs)+ys, bounds=bounds)
+ hv.Image(np.sin(xs)+ys, bounds=bounds)[0:3, 2.5:2])
Notice how, because our declared coordinate system is continuous, we can slice with any floatingpoint value we choose. The appropriate range of the samples in the input numpy array will always be displayed, whether or not there are samples at those specific floatingpoint values.
It is also worth noting that the name
Image
can clash with other common libraries, which is one reason to avoid unqualified imports like
from holoviews import *
. For instance, the Python Imaging Libray provides an
Image
module, and IPython itself supplies an
Image
class in
IPython.display
. Python namespaces allow you to avoid such problems, e.g. using
from PIL import Image as PILImage
or using
import holoviews as hv
and then
hv.Image()
, as we do in these tutorials.
RGB
¶
The
RGB
element is an
Image
that supports red, green, blue channels:
r = 0.5*np.sin(np.pi +3*x**2+y**2)+0.5
g = 0.5*np.sin(x**2+2*y**2)+0.5
b = 0.5*np.sin(np.pi/2+x**2+y**2)+0.5
hv.RGB(np.dstack([r,g,b]))