{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### **Title**: Segments Element\n",
    "\n",
    "**Dependencies** Matplotlib\n",
    "\n",
    "**Backends** [Bokeh](../bokeh/Segments.ipynb), [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('matplotlib')"
   ]
  },
  {
   "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 = [1, 2]\n",
    "data = dict(\n",
    "    start=[1999, 2001],\n",
    "    end=[2010, 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'), \n",
    "                         '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', linewidth=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, fig_size=150, linewidth=10,\n",
    "       color=np.log10(1+dim('c')), cmap='Greens')"
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python",
   "pygments_lexer": "ipython3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
