Richard Whitehead
Richard Whitehead

Reputation: 906

hvplot reset axis to range of selected data when using dropdown

When using hvplot, the range of the y axis is calculated from all the data, which means that if you use the "by" keyword to get a dropdown option, the axis does not change. If one variable in your data has a numerically much smaller range than another, then you can't see the values of the variable with the smaller range, it just looks like a horizontal line.

For example, I have time series data as an xarray dataset, where I'm displaying sensor values for multiple sensors on one graph. Each sensor reports a DAC value which is 0 to 3 billion, and a temperature which is 0 to 100. If I use the "by" mechanism to choose either DAC or temperature, the y axis always has a range of 0 to 3 billion, even when the temperature is being displayed, so the temperature look like zero.

I would like to have the y axis range reset whenever the dropdown option is changed.

Upvotes: 0

Views: 25

Answers (1)

Richard Whitehead
Richard Whitehead

Reputation: 906

The solution turned out to be to use a hook. However there are some gotchas:

  • The documentation is terrible so it was very hard to work out how to obtain the dropdown selection.
  • Updating the y axis range affected the next redraw of the graph, not the current redraw; this was solved by calling refresh on the graph, with some logic to prevent an infinite loop since refresh would call the hook again.
  • The padding option did not work in this case so I implemented that too.
current_attribute = ''

def hook(data, plot):
    global current_attribute

    selected_attribute = plot.current_key[0]
    if not isinstance(selected_attribute, str):
        return
    if selected_attribute == current_attribute:
        return
    current_attribute = selected_attribute
    filtered_data = data.sel(attribute=selected_attribute)
    try:
        min_y = float(filtered_data.min().item())
        max_y = float(filtered_data.max().item())
        y_range_extension = (max_y - min_y) * 0.01 if max_y != min_y else 1.0
        limits = (min_y - y_range_extension, max_y + y_range_extension)
    except ValueError:
        limits = (0.0, 1.0)
    plot.ylim = limits
    plot.refresh()


alldata.hvplot.line(by='sensor').opts(hooks=[lambda plot, element: hook(alldata, plot)])

Upvotes: 0

Related Questions