Segments¶
Download this notebook from GitHub (right-click to download).
In [1]:
import numpy as np
import holoviews as hv
from holoviews import dim
hv.extension('bokeh')
Segments
visualizes a collection of line segments, each starting at a position (x0
, y0
) and ending at a position (x1
, y1
). To specify it, we hence need four key dimensions, listed in the order (x0
, y0
, x1
, y1
), and an arbitrary number of value dimensions as attributes to each line segment.
Basic usage¶
Declare mock data:
In [2]:
event = ['A', 'B']
data = dict(
start=[np.datetime64('1999'), np.datetime64('2001')],
end=[np.datetime64('2010'), np.datetime64('2020')],
start_event = event,
end_event = event
)
Define the Segments
:
In [3]:
seg = hv.Segments(data, [hv.Dimension('start', label='Year'),
hv.Dimension('start_event', label='Event'), 'end', 'end_event'])
Display and style the Element:
In [4]:
seg.opts(color='k', line_width=10)
Out[4]:
A fractal tree¶
In [5]:
from functools import reduce
def tree(N):
"""
Generates fractal tree up to branch N.
"""
# x0, y0, x1, y1, level
branches = [(0, 0, 0, 1)]
theta = np.pi/5 # branching angle
r = 0.5 # length ratio between successive branches
# Define function to grow successive branches given previous branch and branching angle
angle = lambda b: np.arctan2(b[3]-b[1], b[2]-b[0])
length = lambda b: np.sqrt((b[3]-b[1])**2 + (b[2]-b[0])**2)
grow = lambda b, ang: (b[2], b[3],
b[2] + r*length(b)*np.cos(angle(b)+ang),
b[3] + r*length(b)*np.sin(angle(b)+ang))
ctr = 1
while ctr<=N:
yield branches
ctr += 1
branches = [[grow(b, theta), grow(b, -theta)] for b in branches]
branches = reduce(lambda i, j: i+j, branches)
t = reduce(lambda i, j: i+j, tree(14))
data = np.array(t[1:])
Declare a Segments
Element and add an additional value dimension c
that we can use for styling:
In [6]:
s = hv.Segments(np.c_[data, np.arange(len(data))], ['x', 'y', 'x1', 'y1'], 'c')
Now, let's style the Element into a digital broccoli painting:
In [7]:
s.opts(xaxis=None, yaxis=None, height=400, width=400,toolbar='above',
color=np.log10(1+dim('c')), cmap='Greens', line_width=15)
Out[7]:
Cantor set¶
In [8]:
def cantor(N):
"""
Generates a Cantor set up to iteration N, cutting out the middle 9th of each interval
at each step.
"""
y = 0
intervals = [(0, 1, y)]
while y<=N:
yield intervals
dx = (intervals[0][1]-intervals[0][0])/9*4
y += 1
intervals = [[(i[0], i[0]+dx, y), (i[1]-dx, i[1], y)] for i in intervals]
intervals = reduce(lambda i, j: i+j, intervals)
cl = reduce(lambda i, j: i+j, cantor(12))
x0, x1, y = zip(*cl)
data = np.array(cl)
In [9]:
s = hv.Segments((x0, y, x1, y, y), vdims=['c'])
s.opts(xaxis=None, yaxis=None, height=160, width=500,
toolbar='above', line_width=8, color=dim('c'), cmap='fire_r')
Out[9]:
Download this notebook from GitHub (right-click to download).