{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "#### **Title**: Segments Element\n", "\n", "**Dependencies** Bokeh\n", "\n", "**Backends** [Bokeh](./Segments.ipynb), [Matplotlib](../matplotlib/Segments.ipynb)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import holoviews as hv\n", "from holoviews import dim\n", "hv.extension('bokeh')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`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." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### Basic usage" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Declare mock data:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "event = ['A', 'B']\n", "data = dict(\n", " start=[np.datetime64('1999'), np.datetime64('2001')],\n", " end=[np.datetime64('2010'), np.datetime64('2020')],\n", " start_event = event,\n", " end_event = event\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Define the `Segments`:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "seg = hv.Segments(data, [hv.Dimension('start', label='Year'), \n", " hv.Dimension('start_event', label='Event'), 'end', 'end_event'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Display and style the Element:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "seg.opts(color='k', line_width=10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### A fractal tree" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from functools import reduce\n", "def tree(N):\n", " \"\"\"\n", " Generates fractal tree up to branch N.\n", " \"\"\"\n", " # x0, y0, x1, y1, level\n", " branches = [(0, 0, 0, 1)]\n", " theta = np.pi/5 # branching angle\n", " r = 0.5 # length ratio between successive branches\n", " \n", " # Define function to grow successive branches given previous branch and branching angle\n", " angle = lambda b: np.arctan2(b[3]-b[1], b[2]-b[0])\n", " length = lambda b: np.sqrt((b[3]-b[1])**2 + (b[2]-b[0])**2)\n", " grow = lambda b, ang: (b[2], b[3], \n", " b[2] + r*length(b)*np.cos(angle(b)+ang), \n", " b[3] + r*length(b)*np.sin(angle(b)+ang))\n", " ctr = 1\n", " while ctr<=N:\n", " yield branches\n", " ctr += 1\n", " branches = [[grow(b, theta), grow(b, -theta)] for b in branches]\n", " branches = reduce(lambda i, j: i+j, branches)\n", " \n", "t = reduce(lambda i, j: i+j, tree(14))\n", "data = np.array(t[1:])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Declare a `Segments` Element and add an additional value dimension `c` that we can use for styling:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "s = hv.Segments(np.c_[data, np.arange(len(data))], ['x', 'y', 'x1', 'y1'], 'c')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, let's style the Element into a digital broccoli painting:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "s.opts(xaxis=None, yaxis=None, height=400, width=400,toolbar='above',\n", " color=np.log10(1+dim('c')), cmap='Greens', line_width=15)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### Cantor set" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def cantor(N):\n", " \"\"\"\n", " Generates a Cantor set up to iteration N, cutting out the middle 9th of each interval\n", " at each step.\n", " \"\"\"\n", " y = 0\n", " intervals = [(0, 1, y)]\n", " while y<=N:\n", " yield intervals\n", " dx = (intervals[0][1]-intervals[0][0])/9*4\n", " y += 1\n", " intervals = [[(i[0], i[0]+dx, y), (i[1]-dx, i[1], y)] for i in intervals]\n", " intervals = reduce(lambda i, j: i+j, intervals)\n", "\n", "cl = reduce(lambda i, j: i+j, cantor(12))\n", "\n", "x0, x1, y = zip(*cl)\n", "data = np.array(cl)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "s = hv.Segments((x0, y, x1, y, y), vdims=['c'])\n", "s.opts(xaxis=None, yaxis=None, height=160, width=500, \n", " toolbar='above', line_width=8, color=dim('c'), cmap='fire_r')" ] } ], "metadata": { "language_info": { "name": "python", "pygments_lexer": "ipython3" } }, "nbformat": 4, "nbformat_minor": 4 }