{
 "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> Labels Element</dd>\n",
    "  <dt>Dependencies</dt> <dd>Bokeh</dd>\n",
    "  <dt>Backends</dt> <dd><a href='./Labels.ipynb'>Bokeh</a></dd> <dd><a href='../matplotlib/Labels.ipynb'>Matplotlib</a></dd>\n",
    "</dl>\n",
    "</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import holoviews as hv\n",
    "from holoviews import opts\n",
    "hv.extension('bokeh')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The ``Labels`` element may be used to annotate a plot with a number of labels. Unlike the ``Text`` element, ``Labels`` is vectorized and allows plotting many labels at once. It also supports any [tabular](../../../user_guide/08-Tabular_Datasets.ipynb) or [gridded](../../../user_guide/09-Gridded_Datasets.ipynb) data format. This also means that most other elements may be cast to a ``Labels`` element to annotate or label the values.\n",
    "\n",
    "``Labels`` also support various other options that make it convenient to use as an annotation, e.g. ``xoffset`` and ``yoffset`` options allow adjusting the position of the labels relative to an existing data point:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "np.random.seed(9)\n",
    "data = np.random.rand(10, 2)\n",
    "points = hv.Points(data)\n",
    "labels = hv.Labels({('x', 'y'): data, 'text': [chr(65+i) for i in range(10)]}, ['x', 'y'], 'text')\n",
    "overlay = (points * labels).redim.range(x=(-0.2, 1.2), y=(-.2, 1.2))\n",
    "\n",
    "overlay.opts(\n",
    "    opts.Labels(text_font_size='10pt', xoffset=0.08),\n",
    "    opts.Points(color='black', size=5))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The same concept also works for other types, e.g. here we will overlay ``Labels`` for every second value on top of a ``HeatMap``by casting it to a Labels type:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data = [(chr(65+i), chr(97+j),  i*j) for i in range(8) for j in range(8) if i!=j]\n",
    "heatmap = hv.HeatMap(data) \n",
    "\n",
    "heatmap * hv.Labels(heatmap)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If the value dimension of the data is not already of string type it will be formatted using the applicable entry in ``Dimension.type_formatters`` or an explicit ``value_format`` defined on the Dimension. Additionally the ``text_color`` option allows us to colormap the text by a dimension.\n",
    "\n",
    "Here we will create a 2D array of values, define a Dimension with a formatter and then colormap the text:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "value_dimension = hv.Dimension('Values', value_format=lambda x: '%.1f' % x)\n",
    "xs = ys = np.linspace(-2.5, 2.5, 25)\n",
    "zs = np.sin(xs**2)*np.sin(ys**2)[:, np.newaxis]\n",
    "\n",
    "labels = hv.Labels((xs, ys, zs), vdims=value_dimension)\n",
    "labels.opts(\n",
    "    opts.Labels(bgcolor='black', cmap='magma', text_color='Values', height=400, text_font_size='6pt', width=400))"
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python",
   "pygments_lexer": "ipython3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
