我正在使用 pyviz 生态系统组合一个交互式仪表板。仪表板的一项功能是基础数据可能会根据小部件选择器而更改。下面是一个示例代码,显示了我在显示时间小部件滑块时遇到的问题:
包版本:
面板:0.5.1
参数:1.9.0
全息视图:1.12.3
地理视图:1.6.2
示例:
import xarray as xr
import panel as pn
import numpy as np
import param as pm
import holoviews as hv
import geoviews as gv
from matplotlib import cm
import geoviews.tile_sources as gts
from holoviews.operation.datashader import rasterize
from collections import OrderedDict as odict
from holoviews import opts
renderer = hv.renderer('bokeh')
pn.extension()
dset = xr.DataArray(np.random.random((100,100,100)),coords={'X':np.arange(100),'Y':np.arange(100),'T':np.arange(100)},dims=['X','Y','T']).to_dataset(name='test')
dset = gv.Dataset(dset, ['X', 'Y', 'T'], 'test').to(gv.QuadMesh, groupby='T').opts(cmap='viridis', colorbar=True, show_frame=False)
fields = odict([('test','test')])#odict([(v.get('label',k),k) for k,v in source.metadata['fields'].items()])
aggfns = odict([(f.capitalize(),f) for f in ['mean','std','min','max','Pixel Level']])#'count','sum','min','max','mean','var','std']])#,'None (Pixel Level)']])
cmaps = odict([(n,cm.get_cmap(n)) for n in ['viridis','seismic','cool','PiYG']])
maps = ['EsriImagery','EsriNatGeo', 'EsriTerrain', 'OSM']
bases = odict([(name, gts.tile_sources[name].relabel(name)) for name in maps])
gopts = hv.opts.WMTS(responsive=True, xaxis=None, yaxis=None, bgcolor='black', show_grid=False)
class Explorer_Test(pm.Parameterized):
field = pm.Selector(fields)
cmap = pm.Selector(cmaps)
basemap = pm.Selector(bases)
data_opacity = pm.Magnitude(1.00)
map_opacity = pm.Magnitude(1.00)
agg_fn_ = pm.Selector(aggfns,label='Aggregation**',default='mean')
@pm.depends('field', 'agg_fn_')
def aggregator(self):
field = None if self.field == "counts" else self.field
return self.agg_fn(field)
@pm.depends('map_opacity', 'basemap')
def tiles(self):
return self.basemap.opts(gopts).opts(alpha=self.map_opacity)
def viewable(self,**kwargs):
rasterized = rasterize(dset, precompute=True).opts(colorbar=True, height=800, show_frame=False).apply.opts(cmap=self.param.cmap,alpha=self.param.data_opacity)
return hv.DynamicMap(self.tiles)*rasterized
explorer_test = Explorer_Test(name="")
当我显示如下图时:
panel = pn.Row(pn.Param(explorer_test.param, expand_button=False),explorer_test.viewable())
panel.servable()
然而:
panel = pn.Row(pn.Param(explorer_test.param, expand_button=False),explorer_test.viewable)
panel.servable()
在第一个示例中,如果我选择了一个替代数据集(基于 param.Selector 小部件 - 本示例中未显示),它不会重绘图像。但是,在第二个示例中,图像被重绘,但我缺少时间滑块。
更新 - 解决方案
这是根据詹姆斯的解决方案的解决方法(谢谢!)。此示例包括更改数据集和变量(在每个数据集中)以及时间参数。
import xarray as xr
import panel as pn
import numpy as np
import param as pm
import holoviews as hv
import geoviews as gv
from holoviews.operation.datashader import rasterize
from collections import OrderedDict as odict
renderer = hv.renderer('bokeh')
pn.extension()
#Define Example Datasets
dset1 = xr.merge([xr.DataArray(np.random.random((50,50,50)),coords={'X':np.arange(50),'Y':np.arange(50),'T':np.arange(50)},dims=['X','Y','T']).to_dataset(name='var1'),
xr.DataArray(np.random.random((50,50,10))*.1,coords={'X':np.arange(50),'Y':np.arange(50),'T':np.arange(10)},dims=['X','Y','T']).to_dataset(name='var2')])
dset2 = xr.DataArray(np.random.random((50,50,20))*10,coords={'X':np.arange(50)/2.,'Y':np.arange(50)/3.,'T':np.arange(20)},dims=['X','Y','T']).to_dataset(name='var1')
data_dict = {'dset1':dset1,'dset2':dset2}
#Plot Datasets
class sel_dset_var():
def dset1_var1():
return rasterize(gv.Dataset(dset1.var1, ['X', 'Y', 'T'], 'test1').to(gv.QuadMesh, groupby='T')()).opts(cmap='viridis',colorbar=True, height=200, show_frame=False)
def dset1_var2():
return rasterize(gv.Dataset(dset1.var2, ['X', 'Y', 'T'], 'test1').to(gv.QuadMesh, groupby='T')()).opts(cmap='viridis',colorbar=True, height=200, show_frame=False)
def dset2_var1():
return rasterize(gv.Dataset(dset2.var1, ['X', 'Y', 'T'], 'test1').to(gv.QuadMesh, groupby='T')()).opts(cmap='viridis',colorbar=True, height=200, show_frame=False)
#Dashboard
class Explorer_Test(pm.Parameterized):
dset = pm.Selector(odict([('Dataset1','dset1'),('Dataset2','dset2')]),default='dset1')
varss = pm.Selector(list(dset1.data_vars),default=list(dset1.data_vars)[0])
time1 = pm.Selector(dset1.var1.coords['T'].values,default=dset1.var1.coords['T'].values[0])
@pm.depends('dset',watch=True)
def update_var(self):
self.param['varss'].objects = list(data_dict[self.dset].data_vars)
self.param.set_param(varss=list(data_dict[self.dset].data_vars)[0])
@pm.depends('dset',watch=True)
def update_var(self):
self.param['varss'].objects = list(data_dict[self.dset].data_vars)
self.param.set_param(varss=list(data_dict[self.dset].data_vars)[0])
def elem(self):
return getattr(sel_dset_var,self.dset+'_'+self.varss)()
@pm.depends('varss','dset',watch=True)
def update_time(self):
self.param['time1'].objects =data_dict[self.dset][self.varss].dropna(dim='T').coords['T'].values
self.param.set_param(time1=data_dict[self.dset][self.varss].dropna(dim='T').coords['T'].values[0])
def elem_yr(self):
return getattr(self.elem(),'select')(T=self.time1)
def viewable(self,**kwargs):
return self.elem_yr
explorer_test = Explorer_Test(name="")
panel = pn.Row(pn.Param(explorer_test.param, expand_button=False),explorer_test.viewable())
panel.servable()
干杯!