<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 <div class="alert alert-info" role="alert">
    This tutorial contains a lot of bokeh plots, which may take a little while to load and render.
</div>
One of the major design principles of HoloViews is that the declaration of data is completely independent from the plotting implementation. This means that the visualization of HoloViews data structures can be performed by different plotting backends. As part of the 1.4 release of HoloViews, a Bokeh backend was added in addition to the default matplotlib backend. Bokeh provides a powerful platform to generate interactive plots using HTML5 canvas and WebGL, and is ideally suited towards interactive exploration of data.
By combining the ease of generating interactive, high-dimensional visualizations with the interactive widgets and fast rendering provided by Bokeh, HoloViews becomes even more powerful.
This tutorial will cover some basic options on how to style and change various plot attributes and explore some of the more advanced features like interactive tools, linked axes, and brushing.
As usual, the first thing we do is initialize the HoloViews notebook extension, but we now specify the backend specifically.
Step2:  We could instead leave the default backend as 'matplotlib', and then switch only some specific cells to use bokeh using a  cell magic
Step3:  Here's an example of HoloViews Elements using a Bokeh backend, with bokeh's style options
Step4:  Notice that because the first two plots use the same underlying data, they become linked, such that zooming or panning one of the plots makes the corresponding change on the other.
Sizing Elements
Sizing and aspect of Elements in bokeh are always computed in absolute pixels. To change the size or aspect of an Element set the width and height plot options.
Step5:  Controlling axes
Bokeh provides a variety of options to control the axes. Here we provide a quick overview of linked plots for the same data displayed differently by applying log axes, disabling axes, rotating ticks, specifying the number of ticks, and supplying an explicit list of ticks.
Step6:  Datetime axes
Both the matplotlib and the bokeh backends allow plotting datetime data, if you ensure the dates array is of a datetime dtype.
Step7:  Matplotlib/Seaborn conversions
Bokeh also allows converting a subset of existing matplotlib plot types to Bokeh. This allows us to work with some of the Seaborn plot types, including Distribution, Bivariate, and TimeSeries
Step8:  Containers
Tabs
Using bokeh, both (Nd)Overlay and (Nd)Layout types may be displayed inside a tabs widget. This may be enabled via a plot option tabs, and may even be nested inside a Layout.
Step9:  Another reason to use tabs is that some Layout combinations may not be able to be displayed directly using HoloViews. For example, it is not currently possible to display a GridSpace as part of a Layout in any backend, and this combination will automatically switch to a tab representation for the bokeh backend.
Marginals
The Bokeh backend also supports marginal plots to generate adjoined plots. The most convenient way to build an AdjointLayout is with the .hist() method.
Step10:  When the histogram represents a quantity that is mapped to a value dimension with a corresponding colormap, it will automatically share the colormap, making it useful as a colorbar for that dimension as well as a histogram.
Step11:  HoloMaps
HoloMaps work in bokeh just as in other backends.
Step12:  Tools
Step13:  Selection tools
Bokeh provides a number of tools for selecting data points including box_select, lasso_select and poly_select. To distinguish between selected and unselected data points we can also set the unselected_color.  You can try out any of these selection tools and see how the plot is affected
Step14:  Selection widget with shared axes and linked brushing
When dealing with complex multi-variate data it is often useful to explore interactions between variables across plots. HoloViews will automatically link the data sources of plots in a Layout if they draw from the same data, allowing for both linked axes and brushing.
We'll see what this looks like in practice using a small dataset of macro-economic data
Step15:  By creating two Points Elements, which both draw their data from the same pandas DataFrame, the two plots become automatically linked.  This linking behavior can be toggled with the shared_datasource plot option on a Layout or GridSpace.  You can try selecting data in one plot, and see how the corresponding data (those on the same rows of the DataFrame, even if the plots show different data, will be highlighted in each.
Step16:  A gridmatrix is a clear use case for linked plotting.  This operation plots any combination of numeric variables against each other, in a grid, and selecting datapoints in any plot will highlight them in all of them.  Such linking can thus reveal how values in a particular range (e.g. very large outliers along one dimension) relate to each of the other dimensions.
<ASSISTANT_TASK:>
Python Code:
import numpy as np
import pandas as pd
import holoviews as hv
hv.notebook_extension('bokeh')
Explanation: <div class="alert alert-info" role="alert">
    This tutorial contains a lot of bokeh plots, which may take a little while to load and render.
</div>
One of the major design principles of HoloViews is that the declaration of data is completely independent from the plotting implementation. This means that the visualization of HoloViews data structures can be performed by different plotting backends. As part of the 1.4 release of HoloViews, a Bokeh backend was added in addition to the default matplotlib backend. Bokeh provides a powerful platform to generate interactive plots using HTML5 canvas and WebGL, and is ideally suited towards interactive exploration of data.
By combining the ease of generating interactive, high-dimensional visualizations with the interactive widgets and fast rendering provided by Bokeh, HoloViews becomes even more powerful.
This tutorial will cover some basic options on how to style and change various plot attributes and explore some of the more advanced features like interactive tools, linked axes, and brushing.
As usual, the first thing we do is initialize the HoloViews notebook extension, but we now specify the backend specifically.
End of explanation
from holoviews.plotting.bokeh.element import (line_properties, fill_properties,
                                              text_properties)
print(
      Line properties: %s\n
      Fill properties: %s\n
      Text properties: %s
       % (line_properties, fill_properties, text_properties))
Explanation: We could instead leave the default backend as 'matplotlib', and then switch only some specific cells to use bokeh using a  cell magic:
python
%%output backend='bokeh'
obj
Element Style options
Most Bokeh Elements support a mixture of the following fill, line, and text style customization options:
End of explanation
curve_opts = dict(line_width=10, line_color='indianred', line_dash='dotted', line_alpha=0.5)
point_opts = dict(fill_color='#00AA00', fill_alpha=0.5, line_width=1, line_color='black', size=5)
text_opts  = dict(text_align='center', text_baseline='middle', text_color='gray', text_font='Arial')
xs = np.linspace(0, np.pi*4, 100)
data = (xs, np.sin(xs))
(hv.Curve(data)(style=curve_opts) +
 hv.Points(data)(style=point_opts) +
 hv.Text(6, 0, 'Here is some text')(style=text_opts))
Explanation: Here's an example of HoloViews Elements using a Bokeh backend, with bokeh's style options:
End of explanation
%%opts Points.A [width=300 height=300] Points.B [width=600 height=300]
hv.Points(data, group='A') + hv.Points(data, group='B')
Explanation: Notice that because the first two plots use the same underlying data, they become linked, such that zooming or panning one of the plots makes the corresponding change on the other.
Sizing Elements
Sizing and aspect of Elements in bokeh are always computed in absolute pixels. To change the size or aspect of an Element set the width and height plot options.
End of explanation
points = hv.Points(np.exp(xs)) 
axes_opts = [('Plain', {}),
             ('Log', {'logy': True}),
             ('None', {'yaxis': None}),
             ('Rotate', {'xrotation': 90}),
             ('N Ticks', {'xticks': 3}),
             ('List Ticks', {'xticks': [0, 100, 300, 500]})]
hv.Layout([points.relabel(group=group)(plot=opts)
           for group, opts in axes_opts]).cols(3).display('all')
Explanation: Controlling axes
Bokeh provides a variety of options to control the axes. Here we provide a quick overview of linked plots for the same data displayed differently by applying log axes, disabling axes, rotating ticks, specifying the number of ticks, and supplying an explicit list of ticks.
End of explanation
%%opts Overlay [width=600 legend_position='top_left']
try:
    import bokeh.sampledata.stocks
except:
    import bokeh.sampledata
    bokeh.sampledata.download()
from bokeh.sampledata.stocks import GOOG, AAPL
goog_dates = np.array(GOOG['date'], dtype=np.datetime64)
aapl_dates = np.array(AAPL['date'], dtype=np.datetime64)
hv.Curve((goog_dates, GOOG['adj_close']), kdims=['Date'], vdims=['Stock Index'], label='Google') *\
hv.Curve((aapl_dates, AAPL['adj_close']), kdims=['Date'], vdims=['Stock Index'], label='Apple')
Explanation: Datetime axes
Both the matplotlib and the bokeh backends allow plotting datetime data, if you ensure the dates array is of a datetime dtype.
End of explanation
%%opts Distribution (kde_kws=dict(shade=True))
d1 = np.random.randn(500) + 450
d2 = np.random.randn(500) + 540
sines = np.array([np.sin(np.linspace(0, np.pi*2, 100)) + np.random.normal(0, 1, 100) for _ in range(20)])
hv.Distribution(d1) + hv.Bivariate((d1, d2)) + hv.TimeSeries(sines)
Explanation: Matplotlib/Seaborn conversions
Bokeh also allows converting a subset of existing matplotlib plot types to Bokeh. This allows us to work with some of the Seaborn plot types, including Distribution, Bivariate, and TimeSeries:
End of explanation
%%opts Overlay [tabs=True width=600 height=600] RGB [width=600 height=600]
x,y = np.mgrid[-50:51, -50:51] * 0.1
img = hv.Image(np.sin(x**2+y**2), bounds=(-1,-1,1,1))
img.relabel('Low') * img.clone(img.data*2).relabel('High') + img
Explanation: Containers
Tabs
Using bokeh, both (Nd)Overlay and (Nd)Layout types may be displayed inside a tabs widget. This may be enabled via a plot option tabs, and may even be nested inside a Layout.
End of explanation
points = hv.Points(np.random.randn(500,2))
points.hist(num_bins=51, dimension=['x','y'])
Explanation: Another reason to use tabs is that some Layout combinations may not be able to be displayed directly using HoloViews. For example, it is not currently possible to display a GridSpace as part of a Layout in any backend, and this combination will automatically switch to a tab representation for the bokeh backend.
Marginals
The Bokeh backend also supports marginal plots to generate adjoined plots. The most convenient way to build an AdjointLayout is with the .hist() method.
End of explanation
img.hist(num_bins=100, dimension=['x', 'y'], weight_dimension='z', mean_weighted=True) +\
img.hist(dimension='z')
Explanation: When the histogram represents a quantity that is mapped to a value dimension with a corresponding colormap, it will automatically share the colormap, making it useful as a colorbar for that dimension as well as a histogram.
End of explanation
hmap = hv.HoloMap({phase: img.clone(np.sin(x**2+y**2+phase))
                   for phase in np.linspace(0, np.pi*2, 6)}, kdims=['Phase'])
hmap.hist(num_bins=100, dimension=['x', 'y'], weight_dimension='z', mean_weighted=True)
Explanation: HoloMaps
HoloMaps work in bokeh just as in other backends.
End of explanation
%%opts Points [tools=['hover']] (size=5) HeatMap [tools=['hover']] Histogram [tools=['hover']] Layout [shared_axes=False]
error = np.random.rand(100, 3)
heatmap_data = {(chr(65+i),chr(97+j)):i*j for i in range(5) for j in range(5) if i!=j}
data = [np.random.normal() for i in range(10000)]
hist = np.histogram(data, 20)
hv.Points(error) + hv.HeatMap(heatmap_data).sort() + hv.Histogram(hist)
Explanation: Tools: Interactive widgets
Hover tools
Some Elements allow revealing additional data by hovering over the data. To enable the hover tool, simply supply 'hover' as a list to the tools plot option.
End of explanation
%%opts Points [tools=['box_select', 'lasso_select', 'poly_select']] (size=10 unselected_color='red' color='blue')
hv.Points(error)
Explanation: Selection tools
Bokeh provides a number of tools for selecting data points including box_select, lasso_select and poly_select. To distinguish between selected and unselected data points we can also set the unselected_color.  You can try out any of these selection tools and see how the plot is affected:
End of explanation
macro_df = pd.read_csv('http://assets.holoviews.org/macro.csv', '\t')
Explanation: Selection widget with shared axes and linked brushing
When dealing with complex multi-variate data it is often useful to explore interactions between variables across plots. HoloViews will automatically link the data sources of plots in a Layout if they draw from the same data, allowing for both linked axes and brushing.
We'll see what this looks like in practice using a small dataset of macro-economic data:
End of explanation
%%opts Scatter [tools=['box_select', 'lasso_select']] Layout [shared_axes=True shared_datasource=True]
hv.Scatter(macro_df, kdims=['year'], vdims=['gdp']) +\
hv.Scatter(macro_df, kdims=['gdp'], vdims=['unem'])
Explanation: By creating two Points Elements, which both draw their data from the same pandas DataFrame, the two plots become automatically linked.  This linking behavior can be toggled with the shared_datasource plot option on a Layout or GridSpace.  You can try selecting data in one plot, and see how the corresponding data (those on the same rows of the DataFrame, even if the plots show different data, will be highlighted in each.
End of explanation
%%opts Scatter [tools=['box_select', 'lasso_select', 'hover'] border=0] Histogram {+axiswise}
table = hv.Table(macro_df, kdims=['year', 'country'])
matrix = hv.operation.gridmatrix(table.groupby('country'))
matrix.select(country=['West Germany', 'United Kingdom', 'United States'])
Explanation: A gridmatrix is a clear use case for linked plotting.  This operation plots any combination of numeric variables against each other, in a grid, and selecting datapoints in any plot will highlight them in all of them.  Such linking can thus reveal how values in a particular range (e.g. very large outliers along one dimension) relate to each of the other dimensions.
End of explanation
<END_TASK>