{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"contentcontainer med left\" style=\"margin-left: -50px;\">\n",
    "<dl class=\"dl-horizontal\">\n",
    "  <dt>Title</dt> <dd> Graph Element</dd>\n",
    "  <dt>Dependencies</dt> <dd>Matplotlib</dd>\n",
    "  <dt>Backends</dt> \n",
    "    <dd><a href='./Chord.ipynb'>Matplotlib</a></dd>\n",
    "    <dd><a href='../bokeh/Chord.ipynb'>Bokeh</a></dd>\n",
    "</dl>\n",
    "</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import holoviews as hv\n",
    "\n",
    "from holoviews import dim, opts\n",
    "from bokeh.sampledata.les_mis import data\n",
    "\n",
    "hv.extension('matplotlib')\n",
    "hv.output(fig='svg', size=200)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The ``Chord`` element allows representing the inter-relationships between data points in a graph. The nodes are arranged radially around a circle with the relationships between the data points drawn as arcs (or chords) connecting the nodes. The number of chords is scaled by a weight declared as a value dimension on the ``Chord`` element.\n",
    "\n",
    "If the weight values are integers, they define the number of chords to be drawn between the source and target nodes directly. If the weights are floating point values, they are normalized to a default of 500 chords, which are divided up among the edges. Any non-zero weight will be assigned at least one chord.\n",
    "\n",
    "The ``Chord`` element is a type of ``Graph`` element and shares the same constructor. The most basic constructor accepts a columnar dataset of the source and target nodes and an optional value. Here we supply a dataframe containing the number of dialogues between characters of the *Les Misérables* musical. The data contains ``source`` and ``target`` node indices and an associated ``value`` column:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "links = pd.DataFrame(data['links'])\n",
    "print(links.head(3))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In the simplest case we can construct the ``Chord`` by passing it just the edges:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "hv.Chord(links)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To add node labels and other information we can construct a ``Dataset`` with a key dimension of node indices."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "nodes = hv.Dataset(pd.DataFrame(data['nodes']), 'index')\n",
    "nodes.data.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Additionally we can now color the nodes and edges by their index and add some labels. The ``labels``, ``node_color`` and ``edge_color`` options allow us to reference dimension values by name."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "hv.Chord((links, nodes)).select(value=(5, None)).opts(\n",
    "    opts.Chord(cmap='Category20', edge_color=dim('source').astype(str), labels='name', node_color=dim('index').astype(str)))"
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python",
   "pygments_lexer": "ipython3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
