year-vs-climatology / hvplot_docs /02-Composing_Elements.md
ahuang11's picture
Upload 5 files
067c884 verified
|
raw
history blame
9.55 kB
# Composing Objects
```python
import numpy as np
import holoviews as hv
hv.extension('bokeh')
```
Instantly viewable HoloViews objects include elements (discussed already) and containers (collections of elements or other containers). Here we'll introduce two types of containers for collecting viewable objects, each typically created from the existing objects using a convenient operator syntax:
1. ** [``Layout``](../reference/containers/bokeh/Layout.ipynb) (``+``):** A collection of any HoloViews objects to be displayed side by side.
2. **[``Overlay``](../reference/containers/bokeh/Overlay.ipynb) (``*``):** A collection of HoloViews objects to be displayed overlaid on one another with the same axes.
The Layout and Overlay containers allow you to mix types in any combination, and have an ordering but no numerical or categorical key dimension with which to index the objects. In contrast, the [Dimensioned containers](./05-Dimensioned_Containers.ipynb) discussed later, such as [``HoloMap``](../reference/containers/bokeh/HoloMap.ipynb) , [``GridSpace``](../reference/containers/bokeh/GridSpace.ipynb), [``NdOverlay``](../reference/containers/bokeh/NdOverlay.ipynb), and [``NdLayout``](../reference/containers/bokeh/NdLayout.ipynb), do not allow mixed types, and each item has an associated numerical or categorical index (key).
Because you can compose a mix of any HoloViews elements into layouts and overlays, these types of container are very common, which is why they have dedicated composition operators. This user guide describes how you can build and organize your data using these two types of composition.
To show how layouts and overlays work with heterogeneous types, we will use these two elements throughout this notebook:
```python
xs = [0.1* i for i in range(100)]
curve = hv.Curve((xs, [np.sin(x) for x in xs]))
scatter = hv.Scatter((xs[::5], np.linspace(0,1,20)))
```
## 1. ``Layout``
A ``Layout`` can contain any HoloViews object except an ``NdLayout``. (See [Building Composite Objects](06-Building_Composite_Objects.ipynb) for the full details about the ways containers can be composed.)
You can build a ``Layout`` from two or more HoloViews objects of any type by using the ``+`` operator:
```python
curve + scatter
```
In this example, we have a ``Layout`` composed of a ``Curve`` element and a ``Scatter`` element, and they happen to share the same ``x`` and ``y`` dimensions.
### Building a ``Layout`` from a list
If the ``+`` syntax is not convenient, you can also build a ``Layout`` using its constructor directly, which is useful if you want to create a ``Layout`` of an arbitrary length:
```python
curve_list = [hv.Curve((xs, [np.sin(f*x) for x in xs])) for f in [0.5, 0.75]]
scatter_list = [hv.Scatter((xs[::5], f*np.linspace(0,1,20))) for f in [-0.5, 0.5]]
layout = hv.Layout(curve_list + scatter_list).cols(2)
layout
```
Note the use of the ``.cols`` method to specify the number of columns, wrapping to the next row in scanline order (left to right, then top to bottom).
### A ``Layout`` has two-level attribute access
``Layout`` and ``Overlay`` are tree-based data structures that can hold arbitrarily heterogeneous collections of HoloViews objects, and are quite different from the dictionary-like dimensioned containers (which will be described in later guides).
As mentioned previously in [Annotating Data](01-Annotating_Data.ipynb), HoloViews objects have string ``group`` and ``label`` parameters, which can be used to select objects in the ``Layout`` using two-level attribute access. First let us see how to index the above example, where the ``group`` and ``label`` parameters were left unspecified on creation:
```python
print(layout)
```
As you can see, the ``layout`` object consists of four different elements, each mapping from ``x`` to ``y``. You can use the "dot" syntax shown in the repr to select individual elements from the layout:
```python
layout2 = layout.Curve.I + layout.Scatter.II
layout2
```
Here we create a second layout by indexing two elements from our earlier ``layout`` object and using ``+`` between them. We see that the first level of indexing is the ``group`` string (which defaults to the element class name) followed by the label, which wasn't set and is therefore mapped to an automatically generated Roman numeral (I,II,III,IV, etc.).
As group and label were again not specified, our new ``Layout`` will also use ``Curve.I`` for the curve, but as there is only one scatter element, it will have ``Scatter.I`` to index the scatter:
```python
layout2.Scatter.I
```
### Using ``group`` and ``label`` with ``Layout``
Now let's return to the first simple layout example, this time setting a group and label as introduced in the [Annotating Data](./01-Annotating_Data.ipynb) guide:
```python
xs = [0.1* i for i in range(100)]
low_freq = hv.Curve((xs, [np.sin(x) for x in xs]), group='Sinusoid', label='Low Frequency')
linpoints = hv.Scatter((xs[::5], np.linspace(0,1,20)), group='Linear Points', label='Demo')
labelled = low_freq + linpoints
labelled
```
As you can see, the group and label are used for titling the plots. They also determine how the objects are accessed:
```python
labelled.Linear_Points.Demo + labelled.Sinusoid.Low_Frequency
```
You are encouraged to use the group and label names as appropriate for organizing your own data. They should let you easily refer to groups of data that are meaningful to your domain, e.g. for [Applying Customizations](./03-Applying_Customizations.ipynb).
## 2. ``Overlay``
An ``Overlay`` can contain any HoloViews elements, but the only container type it can contain is ``NdOverlay``. [Building Composite Objects](06-Building_Composite_Objects.ipynb) provides the full details on how containers can be composed.
Other than being composed with ``*`` and displaying elements together in the same space, ``Overlay`` shares many of the same concepts as layout. The rest of this section will show the overlay equivalents of the manipulations shown above for layout.
First, composition with ``*`` instead of ``+`` results in a single overlaid plot, rather than side-by-side plots:
```python
curve * scatter
```
### Building ``Overlay`` from a list
An ``Overlay`` can be built explicitly from a list, just like a ``Layout``:
```python
curve_list = [hv.Curve((xs, [np.sin(f*x) for x in xs])) for f in [0.5, 0.75]]
scatter_list = [hv.Scatter((xs[::5], f*np.linspace(0,1,20))) for f in [-0.5, 0.5]]
overlay = hv.Overlay(curve_list + scatter_list)
overlay
```
As you can see, a special feature of ``Overlay`` compared to ``Layout`` is that overlays use *color cycles* to help keep the overlaid plots distinguishable, which you can learn about in [Applying Customization](./03-Applying_Customization.ipynb).
### ``Overlay`` also has two-level attribute access
Like ``Layout``, ``Overlay`` is fundamentally a tree structure holding arbitrarily heterogeneous HoloViews objects, unlike the dimensioned containers. ``Overlay`` objects also make use of the ``group`` and ``label`` parameters, introduced in [Annotating Data](01-Annotating_Data.ipynb), for two-level attribute access.
Once again, let us see how to index the above example where the ``group`` and ``label`` parameters were left unspecified:
```python
print(overlay)
```
```python
overlay.Curve.I * overlay.Scatter.II
```
Here we create a second overlay by indexing two elements from our earlier ``overlay`` object and using ``*`` between them. We see that the first level is the ``group`` string (which defaults to the element class name) followed by the label, which wasn't set and is therefore mapped to a Roman numeral.
### Using ``group`` and ``label`` with ``Overlay``
Now let's return to the first simple overlay example, this time setting ``group`` and ``label`` as introduced in the [Annotating Data](./01-Annotating_Data.ipynb) guide:
```python
high_freq = hv.Curve((xs, [np.sin(2*x) for x in xs]), group='Sinusoid', label='High Frequency')
labelled = low_freq * high_freq * linpoints
labelled
```
Once again, this example follows the corresponding ``Layout`` example, although this time we added a high-frequency curve to demonstrate how ``group`` and ``label`` are now used to generate the legend (as opposed to the title, as it was for ``Layout``).
The following example shows how ``group`` and ``label`` affect access:
```python
labelled.Linear_Points.Demo * labelled.Sinusoid.High_Frequency * labelled.Sinusoid.Low_Frequency
```
This new re-ordered ``Overlay`` switches the z-ordering as well as the legend color of the two sinusoidal curves. The colors and other plot options can be set for specific groups and labels as described in
[Applying Customizations](./03-Applying_Customizations.ipynb).
## Layouts of overlays
Of course, layouts work with both elements and overlays:
```python
overlay + labelled + labelled.Sinusoid.Low_Frequency
```
## Tab completion
Both ``Layout`` and ``Overlay`` are designed to be easy to explore and inspect with tab completion. Try running:
```python
overlay.[tab]
```
or
```python
layout.[tab]
```
In a code cell and you should see the first levels of indexing (``Curve`` and ``Scatter``) conveniently listed at the top. If this is not the case, you may need to enable improved tab-completion as described in [Configuring HoloViews](./Installing_and_Configuring.ipynb).
Having seen how to compose viewable objects, the next section shows how to [apply customizations](./03-Applying_Customizations.ipynb).