I’m trying to create a simple functionality where a user can select image layers (regridded by datashader) to be shown on a tile map by checking checkboxes. Also the images have customizable parameters, not just some opts() but something that specifies their contents.
I can create a customizable colormap for a specific image all right by tiles * hd.regrid(hv.DynamicMap(load_image))
where load_image()
is a function that @pn.depends()
on options coming from widgets. It works like a charm, even when the user is zoomed in, if they change the value of the colormap Select(), the image on the map changes without the whole map resetting.
But of course, I have multiple images all with their own colormap settings and any number of them should be visible. However, I can not figure out how to do this.
Imagine this setup:
tiles = hv.element.tiles.OSM()
pn_layers_all = pn.widgets.CheckBoxGroup(options=['Layer01', 'Layer02'])
pn_image01_cmaps = pn.widgets.Select(options=['inferno', 'viridis'])
pn_image02_cmaps = pn.widgets.Select(options=['inferno', 'viridis'])
pn_image01_ages = pn.widgets.IntSlider(start=0, end=80, step=1)
pn_image02_ages = pn.widgets.IntSlider(start=0, end=80, step=1)
@pn.depends(
pn_layers = pn_layers_all.param.value,
pn_image01_cmap = pn_image01_cmaps.param.value,
pn_image01_age = pn_image01_ages.param.value,
)
def load_image01(pn_layers, pn_image01_cmap, pn_image01_age):
image = bla01(pn_image01_age) # some function that loads and gives back a hv.Image()
image.opts(cmap=pn_image01_cmap)
return image
@pn.depends(
pn_layers = pn_layers_all.param.value,
pn_image02_cmap = pn_image02_cmaps.param.value,
pn_image02_age = pn_image02_ages.param.value,
)
def load_image02(pn_layers, pn_image02_cmap, pn_image02_age):
image = bla02(pn_image02_age) # some function that loads and gives back a hv.Image()
image.opts(cmap=pn_image02_cmap)
return image
So now this works:
dynmap01 = hd.regrid(hv.DynamicMap(load_image01))
combined = tiles * dynmap01
pn.Column(
pn_layers_all, pn_image01_cmaps, pn_image02_cmaps, pn_image01_ages, pn_image02_ages, combined
)
The map shows up, and it reacts to changes in the widgets without resetting even when zoomed in.
The map shows up and reacts to changes in the widgets. combined = tiles * dynmap01 * dynmap02
also works.
However, the only way I could integrate the layer selection is by putting the hd.regrid(hv.DynamicMap())
part into the body of a @pn.depends function and returning tiles * dynmap01 * dynmap02
and of course that resets the whole map every time the layer selection changes, including the zoom level. So it is impossible for example to zoom in on an area of interest and quickly toggle a layer a few times to compare it to a layer below, or just to go through every relevant layer for an area without having to rezoom.
I went through all the relevant HV documentation I could find and I also tried any possible combination I could imagine to reload everything without reloading the tile map itself without any luck. I can not use combined = tiles * load_needed_regridded_images
where the latter is a function because I get “Iteration on Elements is not supported.” error. I can not use combined = tiles * hv.DynamicMap(load_needed_regridded_images)
as by regridding I already had DynamicMaps, so I get a “Nesting a DynamicMap inside a DynamicMap is not supported.” error. Etc etc.
Does anybody have an idea or similar example I could check? Thanks!