I am making visualizations to illustrate a regridding problem. I’d like to show two plots next to one another, the left side zoomed out to show the whole grid extent, the right side zoomed in to show a smaller area.
I’m finding that I can do this in two separate notebook cells, but if I try to place the plots side by side they both get the same axis limits. From " Q: Why are my .options(), .relabel(), .redim(), and similar settings not having any effect?" in the FAQ, I expected to see two different versions of the grid1 object plotted.
This is a minimal working example; in the real one the grids are also overlaid over a bunch of polygons representing coastlines and adminstrative boundaries.
# In[1]:
import holoviews as hv
from holoviews import opts
import numpy as np
import bokeh.palettes as bp
hv.extension("bokeh")
def make_grid(n, color):
grid = hv.QuadMesh((np.arange(n), np.arange(n), np.random.rand(n, n))).opts(
line_width=0.2, line_alpha=1.0, fill_alpha=0.0, line_color=color
)
return grid
grid1 = make_grid(20, "red")
# In[2]:
# these both plot with x limits (5, 10)
grid1.opts(xlim=(2, 18)) + grid1.opts(xlim=(5, 10))
# In[3]:
# these both plot with xlimits (2, 18)
grid1.options(xlim=(2, 18)) + grid1.options(xlim=(5, 10))
# In[4]:
# plotting in separate cells works
grid1.opts(xlim=(2, 18))
# In[5]:
grid1.opts(xlim=(5, 10))
Hi!
This is one of the possible solutions to your problem:
(grid1.redim.range(x=(2, 18)) + grid1.redim.range(x=(5, 10))).opts(shared_axes=False)
The FAQ has some useful info on how shared_axes
works. Another approach would have been to apply .opts(axiswise=True)
to each QuadMesh element.
In the examples you tried, I can tell you that .opts
actually modifies in place the element, so grid1.opts(xlim=(2, 18)) + grid1.opts(xlim=(5, 10))
applies .opts
twice to grid1
. So avoid having .opts
modify the element in place, you can call it like .opts(..., clone=True)
. In the solution I gave I use redim
as it doesn’t modify grid1
, but a solution with .opts(xlim=...)
would also have been possible.
That’s right. @Timothy-W-Hilton , we set that up as a trap for you; .options()
clones automatically, while .opts()
only clones when requested. We wrote .options
first, but then found that many more people were surprised by their option settings disappearing than were surprised when the options were shared across uses of the same object. So we added .opts
with the less-surprising behavior and mostly don’t mention .options
any more, apart from that FAQ, but there are certainly cases where you do want clone=True
.
Thanks @maximlt and @jbednar – that helped me a lot. For anyone who finds this in the future, these three calls all work for me:
(grid1.opts(xlim=(2, 18), clone=True) + grid1.opts(xlim=(5, 10), clone=True)).opts(
shared_axes=False
)
(grid1.options(xlim=(2, 18)) + grid1.options(xlim=(5, 10))).opts(shared_axes=False)
(grid1.redim.range(x=(2, 18)) + grid1.redim.range(x=(5, 10))).opts(shared_axes=False)
HoloViz really is a brilliant piece of work. Thanks!
2 Likes
Here’s one more alternative; you can clone your object explicitly if you prefer:
(grid1.opts(xlim=(2, 18)) + grid1.clone().opts(xlim=(5, 10))).opts(shared_axes=False)
And as Maxime noted, it’s not just about cloning, but also about sharing axes, so that bit still needs to be there to make them truly independent.