Axes not updating dynamically in panel histogram plots

I’m trying to generate a histogram plot that responds dynamically to two Select panel widgets that select data from a dataframe: one widget selects a subset of rows (“TROCAS Number”) and the other the column (“Parameter”) to plot. The y and x axes should update dynamically to the selected data’s distribution, but I can’t get this to work without issues. Either the axis ranges don’t update, or they do but the plot is not actually generated, or an extraneous extra plots needs to be present. I’ve tried these two schemes:

  • hist1: hv.Points.hist()
  • hist2: dataframe hvplot.hist()

In a plot with hist1 alone, a change to the TROCAS Number or Parameter does not update the x-axis and y-axis ranges. In the panel with both hist1 and hist2 plots, the hist1 behaves differently: the x axis now updates dynamically and the data are plotted, though the y axis range is still fixed. In that panel, the hist2 plot updates the range on both axes, but the data are not actually plotted when a new Parameter is chosen, nor is it plotted when the original Parameter (“Temp oC”) is selected again. (The behavior of hist2 is identical when plotted in a panel by itself without hist1). In all plots, the x-axis label always updates correctly.

So, the only time I’m successful, with hist1 only, is when I add an extra, unnecessary histogram plot in the same pane. Even then, the y-axis range doesn’t update dynamically.

I’ve created a notebook that demonstrates the problem. It uses panel version 0.8.0, holoviews 1.12.7 and hvplot 0.5.2; I also tested it with panel 0.7.0 and 0.6.2, holoviews 1.12.5, and hvplot 0.4.0. I’m pasted below the code from the notebook. This functionality is part of a larger panel dashboard I’m developing, that you can check out for context on Heroku at https://trocasdata-1.herokuapp.com; click on the Data Browser tab.

I’m still fairly new with the holoviz ecosystem, so I don’t know where the problem is exactly, including whether it has anything to do with panel per se. Any help would be really appreciated!

import pandas as pd
import holoviews as hv
import hvplot.pandas
import panel as pn

hv.extension('bokeh', logo=False)
pn.extension(logo=False)

# Load parquet data and create holoviews Points from dataframe

mbdata_df = pd.read_parquet('./data/merged_1minbinned_df.parq', engine='fastparquet')
mbdata_points = hv.Points(mbdata_df, kdims=['longitude', 'latitude'])

# panel widgets for selecting a "TROCAS" and a parameter

EXOSonde_parameters = ['Temp °C', 'ODO mg/L', 'pH', 'Turbidity FNU', 'Chlorophyll µg/L']

obs_parameter = pn.widgets.Select(
    name='Parameter',
    value=EXOSonde_parameters[0], 
    options=EXOSonde_parameters,
    width=150
)

trocas_nbr = pn.widgets.Select(
    name='TROCAS Number',
    value='5', 
    options=[tr for tr in mbdata_df.TROCAS_nbr.unique()],
    width=100
)

# Data filtering based on widget selections

def mbdata_points_tr(ds, obs_param, TROCAS_nbr=5):
    selected = ds.select(TROCAS_nbr=TROCAS_nbr)
    return selected.to(hv.Points, ['longitude', 'latitude'], [obs_param, 'date_time'], [])

selpoints = mbdata_points.apply(
    mbdata_points_tr, 
    obs_param=obs_parameter.param.value,
    TROCAS_nbr=trocas_nbr.param.value
)

# hist1: hv.Points.hist histogram scheme

hist1 = selpoints.hist(adjoin=False)
pn.Row(
    pn.Column(trocas_nbr, obs_parameter),
    hist1.opts(width=800, height=200, toolbar='above')
)

# hist2: hvplot.hist histogram scheme

def histogram(ds, obs_param):
    return ds.data.hvplot.hist(y=obs_param)

hist2 = selpoints.apply(histogram, obs_param=obs_parameter.param.value)

# Plot the two histogram schemes in a Column panel driven by a common control widget

pn.Column(
    pn.Row(trocas_nbr, obs_parameter),
    hist1.opts(width=800, height=200, toolbar='above'), 
    hist2.opts(width=800, height=200, toolbar='above') 
)
1 Like

I realize my issue is probably tricky and I dumped a fair bit of code here. This is my first time posing a question to the holoviz community. I find it challenging to diagnose problems down to one specific holoviz component – say, panel vs holoviews.

Does anyone recommend I post this question elsewhere, like Stackoverflow or the holoviz gitter chat? I originally was going to post as a github issue on the panel repo, but the guidance there sent me to discourse.

Also, I should add that I experimented with streams=[RangeXY(transient=True)] and opts(normalize=dict(framewise=True)), without success.

Thanks.

@emiliom I see that you tried .opts(normalize=dict(framewise=True)) but that is very old syntax, does it work with .opts(framewise=True)?

.opts(framewise=True) worked! Thank you!!

(Now I’m having problems testing it in my full-blown Panel app due to problems with JupyterLab 2.0 and the newly released jupyterlab_pyviz extension, but that’s a different topic)