import holoviews as hv
%reload_ext holoviews.ipython
hv.Element(None, group='Value', label='Label')

"""
Explanation: Elements are the basic building blocks for any HoloViews visualization. These are the objects that can be composed together using the various Container types. 
Here in this overview, we show an example of how to build each of these Elements directly out of Python or Numpy data structures.  An even more powerful way to use them is by collecting similar Elements into a HoloMap, as described in Exploring Data, so that you can explore, select, slice, and animate them flexibly, but here we focus on having small, self-contained examples.  Complete reference material for each type can be accessed using our documentation system.
Element types
This class hierarchy shows each of the Element types.
Each type is named for the default or expected way that the underlying data can be visualized.  E.g., if your data is wrapped into a Surface object, it will display as a 3D surface by default, whereas an Image object will display as a 2D raster image.  But please note that the specification and implementation for each Element type does not actually include any such visualization -- the name merely serves as a semantic indication that you ordinarily think of the data as being laid out in that way.  The actual plotting is done by a separate plotting subsystem, while the objects themselves focus on storing your data and the metadata needed to describe and use it.  
This separation of data and visualization is described in detail in the Options tutorial, which describes all about how to find out the options available for each Element type and change them if necessary, from either Python or IPython Notebook.  For convenience, in this tutorial we have specified %output info=True, which will pop up a detailed list and explanation of the available options for visualizing each Element type, after that notebook cell is executed.  So, to find out all the options for any of these Element types, just press &lt;Shift-Enter&gt; on the corresponding cell in the live notebook. 
The types available:
<dl class="dl-horizontal">
  <dt>[``Element``](#Element)</dt><dd>The base class of all ``Elements``.</dd>
</dl>

<a id='ChartIndex'></a> Charts:
<dl class="dl-horizontal">
  <dt>[``Curve``](#Curve)</dt><dd>A continuous relation between a dependent and an independent variable.</dd>
  <dt>[``ErrorBars``](#ErrorBars)</dt><dd>A collection of x-/y-coordinates with associated symmetric or asymmetric errors.</dd>
    <dt>[``Spread``](#Spread)</dt><dd>Just like ErrorBars, Spread is a collection of x-/y-coordinates with associated symmetric or asymmetric errors.</dd>
  <dt>[``Bars``](#Bars)</dt><dd>Data collected and binned into categories.</dd>
  <dt>[``Histogram``](#Histogram)</dt><dd>Data collected and binned in a continuous space using specified bin edges.</dd>
  <dt>[``Scatter``](#Scatter)</dt><dd>Discontinuous collection of points indexed over a single dimension.</dd>
  <dt>[``Points``](#Points)</dt><dd>Discontinuous collection of points indexed over two dimensions.</dd>
  <dt>[``VectorField``](#VectorField)</dt><dd>Cyclic variable (and optional auxiliary data) distributed over two-dimensional space.</dd>
  <dt>[``SideHistogram``](#SideHistogram)</dt><dd>Histogram binning data contained by some other ``Element``.</dd>
  </dl>

<a id='Chart3DIndex'></a> Chart3D Elements:
<dl class="dl-horizontal">
  <dt>[``Surface``](#Surface)</dt><dd>Continuous collection of points in a three-dimensional space.</dd>
  <dt>[``Scatter3D``](#Scatter3D)</dt><dd>Discontinuous collection of points in a three-dimensional space.</dd>
  <dt>[``Trisurface``](#Trisurface)</dt><dd>A discontinuous collection of points interpolated into a Surface using Delaunay triangulation.</dd>
</dl>

<a id='RasterIndex'></a>  Rasters:
<dl class="dl-horizontal">
  <dt>[``Raster``](#Raster)</dt><dd>The base class of all rasters containing two-dimensional arrays.</dd>
  <dt>[``QuadMesh``](#QuadMesh)</dt><dd>Raster type specifying 2D bins with two-dimensional array of values.</dd>
  <dt>[``HeatMap``](#HeatMap)</dt><dd>Raster displaying sparse, discontinuous data collected in a two-dimensional space.</dd>
  <dt>[``Image``](#Image)</dt><dd>Raster containing a two-dimensional array covering a continuous space (sliceable).</dd>
  <dt>[``RGB``](#RGB)</dt><dd>Raster of 3 (R,G,B) or 4 (R,G,B,Alpha) color channels.</dd>
  <dt>[``HSV``](#HSV)</dt><dd>Raster of 3 (Hue, Saturation, Value) or 4 channels.</dd>
</dl>

<a id='TabularIndex'></a>  Tabular Elements:
<dl class="dl-horizontal">
  <dt>[``ItemTable``](#ItemTable)</dt><dd>Ordered collection of key-value pairs (ordered dictionary).</dd>
  <dt>[``Table``](#Table)</dt><dd>Collection of arbitrary data with arbitrary key and value dimensions.</dd>
  </dl>

<a id='AnnotationIndex'></a>  Annotations:
<dl class="dl-horizontal">
  <dt>[``VLine``](#VLine)</dt><dd>Vertical line annotation.</dd>
  <dt>[``HLine``](#HLine)</dt><dd>Horizontal line annotation.</dd>
  <dt>[``Spline``](#Spline)</dt><dd>Bezier spline (arbitrary curves).</dd>
  <dt>[``Text``](#Text)</dt><dd>Text annotation on an ``Element``.</dd>
  <dt>[``Arrow``](#Arrow)</dt><dd>Arrow on an ``Element`` with optional text label.</dd>
</dl>

<a id='PathIndex'></a>  Paths:
<dl class="dl-horizontal">
  <dt>[``Path``](#Path)</dt><dd>Collection of paths.</dd>
  <dt>[``Contours``](#Contours)</dt><dd>Collection of paths, each with an associated value.</dd>
  <dt>[``Polygons``](#Polygons)</dt><dd>Collection of filled, closed paths with an associated value.</dd>
  <dt>[``Bounds``](#Bounds)</dt><dd>Box specified by corner positions.</dd>
  <dt>[``Box``](#Bounds)</dt><dd>Box specified by center position, radius, and aspect ratio.</dd>
  <dt>[``Ellipse``](#Ellipse)</dt><dd>Ellipse specified by center position, radius, and aspect ratio.</dd>
</dl>

Element <a id='Element'></a>
The basic or fundamental types of data that can be visualized.
Element is the base class for all the other HoloViews objects shown in this section.
All Element objects accept data as the first argument to define the contents of that element. In addition to its implicit type, each element object has a group string defining its category, and a label naming this particular item, as described in the Introduction.
When rich display is off, or if no visualization has been defined for that type of Element, the Element is presented in {type}.{group}.{label} format:
End of explanation
"""


import numpy as np
points = [(0.1*i, np.sin(0.1*i)) for i in range(100)]
hv.Curve(points)

"""
Explanation: In addition, Element has key dimensions (kdims), value dimensions (vdims), and constant dimensions (cdims) to describe the semantics of indexing within the Element, the semantics of the underlying data contained by the Element, and any constant parameters associated with the object, respectively.
Dimensions are described in the Introduction.
The remaining Element types each have a rich, graphical display as shown below.
Chart Elements <a id='Chart Elements'></a>
Visualization of a dependent variable against an independent variable
The first large class of Elements is the Chart elements. These objects are by default indexable and sliceable along the x-axis, but not the y-axis, because they are intended for data values y measured for a given x value. However two key dimensions may be supplied to allow 2D indexing on these types. By default the data is expected to be laid out on a single key dimension x, with the data values ranging over a single value dimension y.
The data itself maybe supplied in one of three formats, however internally the data will always be held as a numpy array of shape (N, D), where N is the number of samples and D the number of dimensions. The accepted formats are:
1) As a numpy array of shape (N, D).
2) As a list of length N containing tuples of length D.
3) As a tuple of length D containing iterables of length N.

Curve <a id='Curve'></a>
End of explanation
"""


np.random.seed(7)
points = [(0.1*i, np.sin(0.1*i)) for i in range(100)]
errors = [(0.1*i, np.sin(0.1*i), np.random.rand()/2) for i in np.linspace(0, 100, 11)]
hv.Curve(points) * hv.ErrorBars(errors)

"""
Explanation: A Curve is a set of values provided for some set of keys from a continuously indexable 1D coordinate system.
ErrorBars <a id='ErrorBars'></a>
End of explanation
"""


%%opts ErrorBars (capthick=3)
points = [(0.1*i, np.sin(0.1*i)) for i in range(100)]
errors = [(0.1*i, np.sin(0.1*i), np.random.rand()/2, np.random.rand()/4) for i in np.linspace(0, 100, 11)]
hv.Curve(points) * hv.ErrorBars(errors, vdims=['y', 'yerrneg', 'yerrpos'])

"""
Explanation: ErrorBars is a set of x-/y-coordinates with associated error values, which may be either symmetric or asymmetric and thus can be supplied as an Nx3 or Nx4 array or any of the alternative constructors Chart Elements allow.
End of explanation
"""


np.random.seed(42)
xs = np.linspace(0, np.pi*2, 20)
err = 0.2+np.random.rand(len(xs))
hv.Spread((xs, np.sin(xs), err))

"""
Explanation: Spread <a id='Spread'></a>
Spread elements have the same data format as the ErrorBars element, name x- and y-values with associated symmetric or assymetric errors.
Symmetric
End of explanation
"""


%%opts Spread (facecolor='indianred' alpha=1)
xs = np.linspace(0, np.pi*2, 20)
hv.Spread((xs, np.sin(xs), 0.1+np.random.rand(len(xs)), 0.1+np.random.rand(len(xs))),
          vdims=['y', 'yerrneg', 'yerrpos'])

"""
Explanation: Asymmetric
End of explanation
"""


data = [('one',8),('two', 10), ('three', 16), ('four', 8), ('five', 4), ('six', 1)]
bars = hv.Bars(data, kdims=[hv.Dimension('Car occupants', values='initial')], vdims=['Count'])
bars + bars['one':'four']

"""
Explanation: Bars <a id='Bars'></a>
End of explanation
"""


%%opts Bars [color_by=['category', 'stack'] legend_position='top']
from itertools import product
np.random.seed(1)
groups, categories, stacks = ['A', 'B'], ['a', 'b'], ['I', 'II']
keys = product(groups, categories, stacks)
hv.Bars([(k, np.random.rand()*100) for k in keys],
         kdims=['Group', 'Category', 'Stack'],
        vdims=['Count'])

"""
Explanation: Bars is an NdElement type so by default it is sorted. To inherit the initial ordering specify the Dimension with values set to 'initial', alternatively you can supply an explicit list of valid dimension keys.
Bars support up to three key dimensions which can be laid by 'group', 'category' and 'stack' dimensions, by default these are mapped onto the first second and third Dimension of the Bars object but this behavior can be overridden via the group_index, category_index and stack_index options. Additionally you may style each bar the way you want by creating style groups for any combination of the three dimensions. Here we color_by 'category' and 'stack'.
End of explanation
"""


np.random.seed(1)
data = [np.random.normal() for i in range(10000)]
frequencies, edges = np.histogram(data, 20)
hv.Histogram(frequencies, edges)

"""
Explanation: Histogram <a id='Histogram'></a>
End of explanation
"""


%%opts Histogram [projection='polar' show_grid=True]
data = [np.random.rand()*np.pi*2 for i in range(100)]
frequencies, edges = np.histogram(data, 20)
hv.Histogram(frequencies, edges, kdims=['Angle'])

"""
Explanation: Almost all Element types may be projected onto a polar axis by supplying projection='polar' as a plot option.
End of explanation
"""


%%opts Scatter (color='k', marker='s', s=50)
np.random.seed(42)
points = [(i, np.random.random()) for i in range(20)]
hv.Scatter(points) + hv.Scatter(points)[12:20]

"""
Explanation: Scatter <a id='Scatter'></a>
End of explanation
"""


np.random.seed(12)
points = np.random.rand(50,2)
hv.Points(points) + hv.Points(points)[0.6:0.8,0.2:0.5]

"""
Explanation: The marker shape specified above can be any supported by matplotlib, e.g. s, d, or o; the other options select the color and size of the marker.
Points <a id='Points'></a>
End of explanation
"""


for o in [hv.Points(points,name="Points "), hv.Scatter(points,name="Scatter")]:
    for d in ['key','value']:
        print("%s %s_dimensions: %s " % (o.name, d, o.dimensions(d,label=True)))

"""
Explanation: As you can see, Points is very similar to Scatter, but it is sliceable in both x and $y$, not just x, and so the right-hand plots are different for these two Elements.  Even though they can take the same input data, the Points object treats both x and y as key_dimensions, while Scatter has a single key_dimension x and a single value_dimension y:
End of explanation
"""


%%opts Points [color_index=2 size_index=3 scaling_factor=50]
np.random.seed(10)
data = np.random.rand(100,4)

points = hv.Points(data, vdims=['z', 'alpha'])
points + points[0.3:0.7, 0.3:0.7].hist()

"""
Explanation: Thus the Scatter object expresses a dependent relationship between x and y, making it useful for combining with other similar Chart types, while the Points object expresses the relationship of two independent keys x and y with optional vdims (zero in this case), which makes Points objects meaningful to combine with the Raster types below.
Of course, the vdims need not be empty for Points; here is an example with two additional quantities for each point, as value_dimensions z and &alpha; visualized as the color and size of the dots, respectively:
End of explanation
"""


x,y  = np.mgrid[-10:10,-10:10] * 0.25
sine_rings  = np.sin(x**2+y**2)*np.pi+np.pi
exp_falloff = 1/np.exp((x**2+y**2)/8)

vector_data = [x,y,sine_rings, exp_falloff]
hv.VectorField(vector_data)

"""
Explanation: VectorField <a id='VectorField'></a>
End of explanation
"""


%%opts VectorField.A [color_dim='angle'] VectorField.M [color_dim='magnitude']
hv.VectorField(vector_data, group='A')

"""
Explanation: As you can see above, the x and y positions are in a regular grid. The arrow angles follow a sinsoidal ring pattern and the arrow lengths fall off exponentially from the center, so this plot has four dimensions of data (direction and length for each x,y position).
Using the IPython %%opts cell-magic (described in the Options tutorial, along with the Python equivalent), we can also use color as a redundant indicator to the direction or magnitude:
End of explanation
"""


import numpy as np
np.random.seed(42)
points = [(i, np.random.normal()) for i in range(800)]
hv.Scatter(points).hist()

"""
Explanation: SideHistogram <a id='SideHistogram'></a>
The .hist method conveniently adjoins a histogram to the side of any Chart, Surface, or Raster component, as well as many of the container types (though it would be reporting data from one of these underlying Element types).  For a Raster using color or grayscale to show values (below), the side histogram doubles as a color bar or key.
End of explanation
"""


%%opts Surface (cmap='jet' rstride=20, cstride=2)
hv.Surface(np.sin(np.linspace(0,100*np.pi*2,10000)).reshape(100,100))

"""
Explanation: Chart3D Elements <a id='Chart3D Elements'></a>
Surface <a id='Surface'></a>
End of explanation
"""


%%opts Scatter3D [azimuth=40 elevation=20]
x,y = np.mgrid[-5:5, -5:5] * 0.1
heights = np.sin(x**2+y**2)
hv.Scatter3D(zip(x.flat,y.flat,heights.flat))

"""
Explanation: Scatter3D <a id='Scatter3D'></a>
End of explanation
"""


%%opts Trisurface [fig_size=200] (cmap='hot_r')
hv.Trisurface((x.flat,y.flat,heights.flat))

"""
Explanation: Trisurface <a id='Trisurface'></a>
The Trisurface Element renders any collection of 3D points as a Surface by applying Delaunay triangulation.
End of explanation
"""


x,y = np.mgrid[-50:51, -50:51] * 0.1
hv.Raster(np.sin(x**2+y**2))

"""
Explanation: Raster Elements <a id='Raster Elements'></a>
A collection of raster image types
The second large class of Elements is the raster elements. Like Points and unlike the other  Chart elements, Raster Elements live in a two-dimensional space. For the Image, RGB, and HSV elements, the coordinates of this two-dimensional space are defined in a continuously indexable coordinate system.
Raster <a id='Raster'></a>
A Raster is the base class for image-like Elements, but may be used directly to visualize 2D arrays using a color map. The coordinate system of a Raster is the raw indexes of the underlying array, with integer values always starting from (0,0) in the top left, with default extents corresponding to the shape of the array.  The Image subclass visualizes similarly, but using a continuous Cartesian coordinate system suitable for an array that represents some underlying continuous region.
End of explanation
"""


n = 21
xs = np.logspace(1, 3, n)
ys = np.linspace(1, 10, n)
X,Y = np.meshgrid(xs[:-1], ys[:-1]);
Z = np.sqrt(X**2 + Y**2)
hv.QuadMesh((xs, ys, np.random.rand(n-1, n-1)))

"""
Explanation: QuadMesh <a id='QuadMesh'></a>
The basic QuadMesh is a 2D grid of bins specified as x-/y-values specifying a regular sampling or edges, with arbitrary sampling and an associated 2D array containing the bin values. The coordinate system of a QuadMesh is defined by the bin edges, therefore any index falling into a binned region will return the appropriate value. Unlike Image objects slices must be inclusive of the bin edges.
End of explanation
"""


coords = np.linspace(-1.5,1.5,n)
X,Y = np.meshgrid(coords, coords);
Qx = np.cos(Y) - np.cos(X)
Qz = np.sin(Y) + np.sin(X)
Z = np.sqrt(X**2 + Y**2)
hv.QuadMesh((Qx, Qz, Z))

"""
Explanation: QuadMesh may also be used to represent an arbitrary mesh of quadrilaterals by supplying three separate 2D arrays representing the coordinates of each quadrilateral in a 2D space. Note that when using QuadMesh in this mode slicing and indexing semantics and most operations will currently not work.
End of explanation
"""


data = {(chr(65+i),chr(97+j)):i*j for i in range(5) for j in range(5) if i!=j}
hv.HeatMap(data)

"""
Explanation: HeatMap <a id='HeatMap'></a>
A HeatMap displays like a typical raster image, but the input is a dictionary indexed with two-dimensional keys, not a Numpy array. As many rows and columns as required will be created to display the values in an appropriate grid format.  Values unspecified are left blank, and the keys can be any Python datatype (not necessarily numeric).  One typical usage is to show values from a set of experiments, such as a parameter space exploration, and many other such visualizations are shown in the Containers and Exploring Data tutorials. Each value in a HeatMap is labeled explicitly , and so this component is not meant for very large numbers of samples.  With the default color map, high values (in the upper half of the range present) are colored orange and red, while low values (in the lower half of the range present) are colored shades of blue.
End of explanation
"""


x,y = np.mgrid[-50:51, -50:51] * 0.1
bounds=(-1,-1,1,1)   # Coordinate system: (left, bottom, top, right)

(hv.Image(np.sin(x**2+y**2),   bounds=bounds) 
 + hv.Image(np.sin(x**2+y**2), bounds=bounds)[-0.5:0.5, -0.5:0.5])

"""
Explanation: Image <a id='Image'></a>
Like Raster, a HoloViews Image allows you to view 2D arrays using an arbitrary color map. Unlike Raster, an Image is associated with a 2D coordinate system in continuous space, which is appropriate for values sampled from some underlying continuous distribution (as in a photograph or other measurements from locations in real space).  Slicing, sampling, etc. on an Image all use this continuous space, whereas the corresponding operations on a Raster work on the raw array coordinates.
End of explanation
"""


x,y = np.mgrid[-50:51, -50:51] * 0.1

r = 0.5*np.sin(np.pi  +3*x**2+y**2)+0.5
g = 0.5*np.sin(x**2+2*y**2)+0.5
b = 0.5*np.sin(np.pi/2+x**2+y**2)+0.5

hv.RGB(np.dstack([r,g,b]))

"""
Explanation: Notice how, because our declared coordinate system is continuous, we can slice with any floating-point value we choose. The appropriate range of the samples in the input numpy array will always be displayed, whether or not there are samples at those specific floating-point values.
It is also worth noting that the name Image can clash with other common libraries, which is one reason to avoid unqualified imports like the from holoviews import * statement that we use in these tutorials for brevity. For instance, the Python Imaging Libray provides an Image module, and IPython itself supplies an Image class in IPython.display.  Python namespaces allow you to avoid such problems, e.g. using from PIL import Image as PILImage or using import holoviews as hv and then hv.Image().
RGB <a id='RGB'></a>
The RGB element is an Image that supports red, green, blue channels:
End of explanation
"""


%%opts Image (cmap='gray')
hv.Image(r,label="R") + hv.Image(g,label="G") + hv.Image(b,label="B")

"""
Explanation: You can see how the RGB object is created from the original channels:
End of explanation
"""


%%opts Image (cmap='gray')
mask = 0.5*np.sin(0.2*(x**2+y**2))+0.5
rgba = hv.RGB(np.dstack([r,g,b,mask]))

bg = hv.Image(0.5*np.cos(x*3)+0.5, label="Background") * hv.VLine(x=0,label="Background")

overlay = bg*rgba
overlay.label="RGBA Overlay"

bg + hv.Image(mask,label="Mask") + overlay

"""
Explanation: RGB also supports an optional alpha channel, which will be used as a mask revealing or hiding any Elements it is overlaid on top of:
End of explanation
"""


x,y = np.mgrid[-50:51, -50:51] * 0.1
h = 0.5 + np.sin(0.2*(x**2+y**2)) / 2.0
s = 0.5*np.cos(y*3)+0.5
v = 0.5*np.cos(x*3)+0.5

hv.HSV(np.dstack([h, s, v]))

"""
Explanation: HSV <a id='HSV'></a>
HoloViews makes it trivial to  work in any color space that can be converted to RGB by making a simple subclass of RGB as appropriate. For instance, we also provide the  HSV (hue, saturation, value) color space, which is useful for plotting cyclic data (as the Hue) along with two additional dimensions (controlling the saturation and value of the color, respectively):
End of explanation
"""


%%opts Image (cmap='gray')
hv.Image(h, label="H") + hv.Image(s, label="S") + hv.Image(v, label="V")

"""
Explanation: You can see how this is created from the original channels:
End of explanation
"""


hv.ItemTable([('Age', 10), ('Weight',15), ('Height','0.8 meters')])

"""
Explanation: Tabular Elements <a id='Tabular Elements'></a>
General data structures for holding arbitrary information
ItemTable <a id='ItemTable'></a>
An ItemTable is an ordered collection of key, value pairs. It can be used to directly visualize items in a tabular format where the items may be supplied as an OrderedDict or a list of (key,value) pairs. A standard Python dictionary can be easily visualized using a call to the .items() method, though the entries in such a dictionary are not kept in any particular order, and so you may wish to sort them before display.  One typical usage for an ItemTable is to list parameter values or measurements associated with an adjacent Element.
End of explanation
"""


keys =   [('M',10), ('M',16), ('F',12)]
values = [(15, 0.8), (18, 0.6), (10, 0.8)]
table = hv.Table(zip(keys,values), 
                 kdims = ['Gender', 'Age'], 
                 vdims=['Weight', 'Height'])
table

"""
Explanation: Table <a id='Table'></a>
A table is more general than an ItemTable, as it allows multi-dimensional keys and multidimensional values.
End of explanation
"""


table.select(Gender='M') + table.select(Gender='M', Age=10)

"""
Explanation: Note that you can use select using tables, and once you select using a full, multidimensional key, you get an ItemTable (shown on the right):
End of explanation
"""


table.select(Gender='M').to.curve(kdims=["Age"], vdims=["Weight"])

"""
Explanation: The Table is used as a common data structure that may be converted to any other HoloViews data structure using the TableConversion class. A similar principle holds when converting data from Pandas DataFrames to HoloViews objects using the optional Pandas support.
The functionality of the TableConversion class may be conveniently accessed using the .to property, which should have its own tutorial someday, but hopefully this will get the idea across:
End of explanation
"""


scene = hv.RGB.load_image('../assets/penguins.png')

"""
Explanation: Annotation Elements <a id='Annotation Elements'></a>
Useful information that can be overlaid onto other components
Annotations are components designed to be overlaid on top of other Element objects. To demonstrate annotation and paths, we will be drawing many of our elements on top of an RGB Image:
End of explanation
"""


scene * hv.VLine(-0.05) + scene * hv.HLine(-0.05)

"""
Explanation: VLine and HLine  <a id='VLine'></a><a id='HLine'></a>
End of explanation
"""


points = [(-0.3, -0.3), (0,0), (0.25, -0.25), (0.3, 0.3)]
codes = [1,4,4,4]
scene * hv.Spline((points,codes)) * hv.Curve(points)

"""
Explanation: Spline  <a id='Spline'></a>
The Spline annotation is used to draw Bezier splines using the same semantics as matplotlib splines. In the overlay below, the spline is in dark blue and the control points are in light blue.
End of explanation
"""


scene * hv.Text(0, 0.2, 'Adult\npenguins') + scene * hv.Arrow(0,-0.1, 'Baby penguin', 'v')

"""
Explanation: Text and Arrow  <a id='Text'></a><a id='Arrow'></a>
End of explanation
"""


angle = np.linspace(0, 2*np.pi, 100)
baby = list(zip(0.15*np.sin(angle),  0.2*np.cos(angle)-0.2))

adultR = [(0.25, 0.45), (0.35,0.35), (0.25, 0.25), (0.15, 0.35), (0.25, 0.45)]
adultL = [(-0.3, 0.4), (-0.3, 0.3), (-0.2, 0.3), (-0.2, 0.4),(-0.3, 0.4)]

scene * hv.Path([adultL, adultR, baby]) * hv.Path([baby])

"""
Explanation: Paths  <a id='Path Elements'></a>
Line-based components that can be overlaid onto other components
Paths are a subclass of annotations that involve drawing line-based components on top of other elements. Internally Path Element types hold a list of Nx2 arrays, specifying the x/y-coordinates along each path. The data may be supplied in a number of ways however
1) A list of Nx2 numpy arrays.
2) A list of lists containing x/y coordinate tuples.
3) A tuple containing an array of length N with the x-values and a
   second array of shape NxP, where P is the number of paths.
4) A list of tuples each containing separate x and y values.

Path  <a id='Path'></a>
A Path object is actually a collection of paths which can be arbitrarily specified. Although there may be multiple unconnected paths in a single Path object, they will all share the same style. Only by overlaying multiple Path objects do you iterate through the defined color cycle (or any other style options that have been defined).
End of explanation
"""


x,y = np.mgrid[-50:51, -50:51] * 0.1

def circle(radius, x=0, y=0):
    angles = np.linspace(0, 2*np.pi, 100)
    return np.array( list(zip(x+radius*np.sin(angles), y+radius*np.cos(angles))))

hv.Image(np.sin(x**2+y**2)) * hv.Contours([circle(0.22)], level=0) * hv.Contours([circle(0.33)], level=1)

"""
Explanation: Contours  <a id='Contours'></a>
A Contours object is similar to Path object except each of the path elements is associated with a numeric value, called the level. Sadly, our penguins are too complicated to give a simple example so instead we will simply mark the first couple of rings of our earlier ring pattern:
End of explanation
"""


%%opts Polygons (cmap='hot' edgecolor='k' linewidth=2)
np.random.seed(35)
hv.Polygons([np.random.rand(4,2)], level=0.5) *\
hv.Polygons([np.random.rand(4,2)], level=1.0) *\
hv.Polygons([np.random.rand(4,2)], level=1.5) *\
hv.Polygons([np.random.rand(4,2)], level=2.0)

"""
Explanation: Polygons <a id='Polygons'></a>
A Polygons object is similar to a Contours object except that each supplied path is closed and filled. Just like Contours, optionally a level may be supplied, the Polygons will then be colored according to the supplied cmap. Non-finite values such as np.NaN or np.inf will default to the supplied facecolor.
Polygons with values can be used as heatmaps with arbitrary shapes.
End of explanation
"""


def rectangle(x=0, y=0, width=1, height=1):
    return np.array([(x,y), (x+width, y), (x+width, y+height), (x, y+height)])

(hv.Polygons([rectangle(width=2), rectangle(x=6, width=2)])(style={'facecolor': '#a50d0d'})
* hv.Polygons([rectangle(x=2, height=2), rectangle(x=5, height=2)])(style={'facecolor': '#ffcc00'})
* hv.Polygons([rectangle(x=3, height=2, width=2)])(style={'facecolor': 'c', 'hatch':'x'}))

"""
Explanation: Polygons without a value are useful as annotation, but also allow us to draw arbitrary shapes.
End of explanation
"""


scene * hv.Bounds(0.2) * hv.Bounds((0.45, 0.45, 0.2, 0.2))

"""
Explanation: Bounds  <a id='Bounds'></a>
A bounds is a rectangular area specified as a tuple in  (left, bottom, right, top) format. It is useful for denoting a region of interest defined by some bounds, whereas Box (below) is useful for drawing a box at a specific location.
End of explanation
"""


scene * hv.Box(    -0.25, 0.3, 0.3, aspect=0.5) * hv.Box(    0, -0.2, 0.1) + \
scene * hv.Ellipse(-0.25, 0.3, 0.3, aspect=0.5) * hv.Ellipse(0, -0.2, 0.1)

"""
Explanation: Box <a id='Box'></a> and Ellipse <a id='Ellipse'></a>
A Box is similar to a Bounds except you specify the box position, width, and aspect ratio instead of the coordinates of the box corners.  An Ellipse is specified just as for Box, but has a round shape.
End of explanation
"""


