Я собираю интерактивную панель, используя экосистему pyviz.Одной из особенностей панели инструментов является то, что базовые данные могут изменяться в зависимости от селектора виджета.Ниже приведен пример кода, показывающий проблему, с которой я столкнулся, когда появился ползунок виджета времени:
Версии пакета :
панель: 0.5.1
параметр: 1.9.0
holoviews: 1.12.3
geoviews: 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()
Приветствия!