Basic needs: plot a map, and update accoding to variable. Challenges:
import holoviews as hv, datashader as ds, geoviews as gv, geoviews.tile_sources as gvts
from holoviews.operation.datashader import datashade, rasterize, dynspread
import panel as pn
hv.extension('bokeh')
opts = dict(width=700, height=500, tools=['hover'],
colorbar=True,symmetric=True,clim=(-5,5),
cmap='Spectral')
tiles = gvts.OSM.options(alpha=0.6)
def load_dh(var=None):
points = gv.Points(df, kdims=['longitude','latitude'])
return rasterize(points, x_sampling=0.01, y_sampling=0.01, aggregator=ds.mean(var)).options(**opts)* tiles
def on_var_select(event):
var = event.obj.value
col[-1] = load_dh(var=var)
var_select = pn.widgets.Select(name='var:', options=['dh_after_dtm10', '2', '3'])
var_select.param.watch(on_var_select, parameter_names=['value'])
col = pn.Column(var_select, load_dh(var_select.value))
col
The plot did show, but not update with changing variables:
I also try DynamicMap, which is not compataible with rasterize](Panel/Hvplot interaction when variable is changing):
Exception: Nesting a DynamicMap inside a DynamicMap is not supported.
The original code isn't runnable (try to show a fully reproducible example!), but when I made it runnable and removed GeoViews (not in my current envt), it seems to work:
import holoviews as hv, datashader as ds, panel as pn, pandas as pd
from holoviews.operation.datashader import datashade, rasterize, dynspread
df = pd.DataFrame(dict(longitude=[70,80,90,100], latitude=[10,30,20,5],
c1=[1,0,9,7], c2=[5,2,0,1], c3=[3,1,3,8]))
hv.extension('bokeh')
opts = dict(width=700, height=500, tools=['hover'],
colorbar=True,symmetric=True,clim=(-5,5),
cmap='Spectral')
def load_dh(var=None):
points = hv.Points(df, kdims=['longitude','latitude'])
return dynspread(rasterize(points, x_sampling=0.01, y_sampling=0.01, aggregator=ds.mean(var))).options(**opts)
def on_var_select(event):
var = event.obj.value
col[-1] = load_dh(var=var)
var_select = pn.widgets.Select(name='var:', options=['c1', 'c2', 'c3'])
var_select.param.watch(on_var_select, parameter_names=['value'])
col = pn.Column(var_select, load_dh(var_select.value))
col
That said, it seems like an overly complex solution, when pn.bind can be used very straightforwardly for this:
import holoviews as hv, datashader as ds, panel as pn, pandas as pd
from holoviews.operation.datashader import datashade, rasterize, dynspread
df = pd.DataFrame(dict(longitude=[70,80,90,100], latitude=[10,30,20,5],
c1=[1,0,9,7], c2=[5,2,0,1], c3=[3,1,3,8]))
hv.extension('bokeh')
opts = dict(width=700, height=500, tools=['hover'],
colorbar=True,symmetric=True,clim=(-5,5),
cmap='Spectral')
def load_dh(var=None):
points = hv.Points(df, kdims=['longitude','latitude'])
return dynspread(rasterize(points, x_sampling=0.01, y_sampling=0.01, aggregator=ds.mean(var))).options(**opts)
var_select = pn.widgets.Select(name='var:', options=['c1', 'c2', 'c3'])
col = pn.Column(var_select, pn.bind(load_dh, var=var_select))
col
Also, it's not so much that DynamicMap doesn't support rasterize
as that the result of rasterize
is already a DynamicMap, and only a single level of DynamicMap-ping is supported. It's always possible to make a single-level DynamicMap that does what you want, but because HoloViews operations (unlike DynamicMaps) do accept a DynamicMap as an argument, all you usually need to do is to call rasterize
on your DynamicMap. So if you want to make a DynamicMap, just do so, then rasterize
it.