Search code examples
holoviews

Linking axis in interactive plot for holoviews layout


I am trying to annotate some time series data with different occurrences in time. To do this I have created an overlay of curves and a holoviews.element.raster.Image (see code below).

As per here and here I know that the axis should have the same units and label for holoviews to automatically link them. I have tried this in the example code below, but the plots are still not linked.

import xarray as xr
import numpy as np

# creaty dummy data
t = np.linspace(-10,10,50)
dates = pd.to_datetime(np.linspace(pd.Timestamp('2017-01-01').value, pd.Timestamp('2018-01-01').value, 200))
data = np.random.rand(50,200)
xrData = xr.DataArray(data, dims=['time','dates'], coords={'time':t, 'dates':dates})

dataplot = xrData.hvplot(width=1000)
# create annotations
line1 = hv.Curve([
    [pd.Timestamp('2017-03-01'), 0],
    [pd.Timestamp('2017-06-01'), 0]], ('x','dates'), label='eventA').opts(line_width=20, color='red')

line2 = hv.Curve([
    [pd.Timestamp('2017-08-01'), 0],
    [pd.Timestamp('2017-10-01'), 0]], ('x','dates'), label='eventA').opts(line_width=20, color='red')

line3 = hv.Curve([
    [pd.Timestamp('2017-11-01'), 0],
    [pd.Timestamp('2017-12-01'), 0]], ('x','dates'), label='eventB').opts(line_width=20, color='blue')

annotations = line1 * line2 * line3

annotations.opts(width=1000,height=150, legend_cols=2, yaxis=None)
annotations = annotations.redim(y=hv.Dimension('y', range=(-0.25, 1)))


annotated_data = (annotations + dataplot).cols(1)

annotated_data

Here is the plot I get in jupyter


Solution

  • Good question! Here you are wondering why the x axes aren't linked between these two plots, even though both are labeled "dates" and thus seem to be the same dimension. But if you inspect the actual dimensions of your plots, you'll see that they are different; one is "x" (but relabeled "dates" for display) and the other is "dates":

    dimensions

    To make them the same, you need not just to make them be labeled the same, but to be declared to be the same dimension, e.g.:

    new dimensions

    (How you label the dimensions onscreen is up to you; HoloViews only cares whether you actually denoted the dimensions as being the same.)

    Here's your code updated with the right imports and simplified y re-ranging along with declaring the dimensions to be shared:

    import xarray as xr, pandas as pd, numpy as np, holoviews as hv, hvplot.xarray
    
    # creaty dummy data
    t = np.linspace(-10,10,50)
    dates = pd.to_datetime(np.linspace(pd.Timestamp('2017-01-01').value, pd.Timestamp('2018-01-01').value, 200))
    data = np.random.rand(50,200)
    xrData = xr.DataArray(data, dims=['time','dates'], coords={'time':t, 'dates':dates})
    
    dataplot = xrData.hvplot(width=1000)
    # create annotations
    line1 = hv.Curve([
        [pd.Timestamp('2017-03-01'), 0],
        [pd.Timestamp('2017-06-01'), 0]], 'dates', label='eventA').opts(line_width=20, color='red')
    
    line2 = hv.Curve([
        [pd.Timestamp('2017-08-01'), 0],
        [pd.Timestamp('2017-10-01'), 0]], 'dates', label='eventA').opts(line_width=20, color='red')
    
    line3 = hv.Curve([
        [pd.Timestamp('2017-11-01'), 0],
        [pd.Timestamp('2017-12-01'), 0]], 'dates', label='eventB').opts(line_width=20, color='blue')
    
    annotations = line1 * line2 * line3
    
    annotations.opts(width=1000,height=150, legend_cols=2, yaxis=None)
    annotations = annotations.redim.range(y=(-0.25, 1))
    
    
    annotated_data = (annotations + dataplot).cols(1)
    
    annotated_data
    

    fixed example