.opts not working when overlaying elements

Hello,

I have a program where i have a scatter plot working on Bokeh Serve,

...
def draw_holoview_xvsy(data):
    return hv.Points([[data[0][i], data[1][i]] for i in range(len(data[0]))])


figure_xvsy_holoview_pipe = Pipe(data=np.array([[-100, 0, 100], [-100, 0, 100]]))
figure_xvsy_holoview_dmap = hv.DynamicMap(draw_holoview_xvsy, streams=[figure_xvsy_holoview_pipe])
figure_xvsy_holoview_dmap = dynspread(datashade(figure_xvsy_holoview_dmap)).opts(width=600, height=600,
                                                                     tools=['xwheel_zoom', 'ywheel_zoom', 'box_zoom', 'pan'],
                                                                     active_tools=['xwheel_zoom', 'pan'],
                                                                     default_tools=['reset', 'save', 'hover'],
                                                                     show_grid=True, title='X vs Y')
figure_xvsy_holoview_hvplot = renderer.get_plot(figure_xvsy_holoview_dmap, curdoc())
figure_xvsy_holoview_hvplot.state.output_backend = "webgl"

... #Changing name and labels programatically
figure_xvsy_holoview_dmap.opts(xlabel=x_label, ylabel=y_label, title=y_label + ' vs ' + x_label)
figure_xvsy_holoview_pipe.send(data=np.array([data2plot.iloc[:, 0], data2plot.iloc[:, 1]]))

This works as expected and correctly as im showing in the following GIF.

But now i want to overlay a curve which represents a linear regression of the scatter plot, im doing it as follows:

...
def draw_holoview_xvsy(data):
    return hv.Points([[data[0][i], data[1][i]] for i in range(len(data[0]))])

def draw_holoview_xvsy_linear(data):
    fit = np.polyfit(data[0][:], data[1][:], 1, full=True)
    minx = np.min(data[0][:])
    maxx = np.max(data[0][:])
    slope = fit[0][0]
    intercept = fit[0][1]
    curvedata = np.array([[minx, maxx], [minx * slope + intercept, maxx * slope + intercept]])

    return hv.Curve(dict(x=curvedata[0], y=curvedata[1]))


figure_xvsy_holoview_pipe = Pipe(data=np.array([[-100, 0, 100], [-100, 0, 100]]))
figure_xvsy_holoview_dmap = hv.DynamicMap(draw_holoview_xvsy, streams=[figure_xvsy_holoview_pipe])
figure_xvsy_holoview_dmap = dynspread(datashade(figure_xvsy_holoview_dmap))

figure_xvsy_linear_holoview_pipe = Pipe(data=np.array([[-100, 0, 100], [-100, 0, 100]]))
figure_xvsy_linear_holoview_dmap = hv.DynamicMap(draw_holoview_xvsy_linear, streams=[figure_xvsy_linear_holoview_pipe])
figure_xvsy_linear_holoview_dmap = dynspread(datashade(figure_xvsy_linear_holoview_dmap, cmap=["red"]))

figure_xvsy_holoview_dmap = (figure_xvsy_holoview_dmap * figure_xvsy_linear_holoview_dmap).opts(width=600, height=600,
                                                                     tools=['xwheel_zoom', 'ywheel_zoom', 'box_zoom', 'pan'],
                                                                     active_tools=['xwheel_zoom', 'pan'],
                                                                     default_tools=['reset', 'save', 'hover'],
                                                                     show_grid=True, title='X vs Y')

figure_xvsy_holoview_hvplot = renderer.get_plot(figure_xvsy_holoview_dmap, curdoc())
figure_xvsy_holoview_hvplot.state.output_backend = "webgl"

... #Changing name and labels programatically
figure_xvsy_holoview_dmap.opts(xlabel=x_label, ylabel=y_label, title=y_label + ' vs ' + x_label)
figure_xvsy_holoview_pipe.send(data=np.array([data2plot.iloc[:, 0], data2plot.iloc[:, 1]]))
figure_xvsy_linear_holoview_pipe.send(data=np.array([data2plot.iloc[:, 0], data2plot.iloc[:, 1]]))

And now the labels dont change and the xwheel, ywheel and hoover tools dont show.

Im wondering why the title, labels and tools are not working properly when overlaying these two plots.

Thank you in advance.

Josu Catalina.

Any idea?

Seem to have missed this issue, sorry about that. So let’s start with some unrelated comments:

figure_xvsy_holoview_hvplot = renderer.get_plot(figure_xvsy_holoview_dmap, curdoc())
figure_xvsy_holoview_hvplot.state.output_backend = "webgl"

This does nothing, you rendering the object, then changing the rendering backend. When it renders it again later it remembers nothing about this option. You can change this option globally with:

hv.renderer('bokeh').webgl = True

Now to your actual issue. I suspect this line isn’t applying properly:

figure_xvsy_holoview_dmap.opts(xlabel=x_label, ylabel=y_label, title=y_label + ' vs ' + x_label)

When applying .opts on a DynamicMap I suspect it ends up making a copy of the object so you may have to be reassign it to the same variable:

figure_xvsy_holoview_dmap = figure_xvsy_holoview_dmap.opts(xlabel=x_label, ylabel=y_label, title=y_label + ' vs ' + x_label)

I can’t quite figure out the issue with the tools yet but maybe just try targeting those options to a specific element:

figure_xvsy_holoview_dmap = (figure_xvsy_holoview_dmap * figure_xvsy_linear_holoview_dmap).opts(
    hv.opts.RGB(width=600, height=600, tools=['xwheel_zoom', 'ywheel_zoom', 'box_zoom', 'pan'],
                active_tools=['xwheel_zoom', 'pan'], default_tools=['reset', 'save', 'hover'],
                show_grid=True, title='X vs Y')
)

I had a similar issue with overlay. Below is a simple case to reproduce.

import numpy as np
import holoviews as hv
hv.notebook_extension('matplotlib')

x=np.linspace(0,9,10)
v=np.random.rand(10,10)
xx,yy=np.meshgrid(x,x)

fig=hv.QuadMesh((xx,yy,v))
fig.opts(fig_bounds=(0.4,0.4,0.6,0.6))

c=hv.Curve((x,x))
c.opts(fig_bounds=(0.4,0.4,0.6,0.6))

#fig
#(fig*c).opts(hv.opts.QuadMesh(fig_bounds=(0.4,0.4,0.6,0.6)),hv.opts.Curve(fig_bounds=(0.4,0.4,0.6,0.6)))

The key tester here is fig_bounds. If you uncomment the 1st line in the end, which shows the QuadMesh itself, the result, as it should b, is a shrunken one.

But uncommenting the 2nd line gives the following

.
The image is by its original bounds, even though I set fig_bounds wherever possible.

Help is much appreciated in directing me in debugging this! Like, what is the workflow to go from an overlay object to the final plot?