python - 查看与可查看并显示小部件

标签 python panel holoviews geoviews pyviz

我正在使用 pyviz 生态系统构建一个交互式仪表板。仪表板的一项功能是基础数据可能会根据小部件选择器而改变。下面是一个示例代码,显示了我在显示时间小部件 slider 时遇到的问题:

软件包版本:
面板:0.5.1
参数:1.9.0
全息 View :1.12.3
地理 View :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()

时间小部件出现: enter image description here

鉴于:

panel = pn.Row(pn.Param(explorer_test.param, expand_button=False),explorer_test.viewable)
panel.servable()

enter image description here

在第一个示例中,如果我选择替代数据集(基于 param.Selector 小部件 - 本示例中未显示),它不会重绘图像。但是,在第二个示例中,图像被重新绘制,但我缺少时间 slider 。

更新 - 解决方案

这是根据 James 的解决方案的解决方法(谢谢!)。此示例包括更改数据集和变量(每个数据集中)以及时间参数。

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()

enter image description here

干杯!

最佳答案

这段代码看起来像是源 self 的 http://datashader.org/dashboard.html例子。在我的示例中,viewable() 的输出方法已经是完全动态的,并且不需要重新生成,已经在内部链接到影响其显示方式的所有小部件和控件。而如果你通过viewable作为 Panel 的方法名称(而不是调用该方法的结果),您要求 Panel 调用 viewable()每当它确定初始调用的结果变得过时时,都会为您提供帮助。这种简单的重新运行方法方法适用于非常简单的全有或全无计算的情况,但当对象本身已经是动态的并且特定控件与绘图的特定方面相关联时,在这里并不真正有用。 (为什么在这种情况下你也没有得到时间小部件,我不确定;这不是推荐的用法,但我认为它仍然应该为你提供一个小部件。)

无论如何,我认为您不应该尝试让上面的第二种情况起作用,而只应该尝试第一种情况。问题不在于缺少 slider ,听起来像是您试图让绘图响应数据源的变化。幸运的是,http://datashader.org/dashboard.html 中的示例已经说明了这种情况。 ;有rasterize动态包装一个返回要显示的数据的适当列的方法。您应该能够调整该方法,使其动态反射(reflect)允许用户选择数据集的其他某个小部件的状态。

关于python - 查看与可查看并显示小部件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56530513/

相关文章:

python - Pandas 从数据框中提取不存在于另一个数据框中的列

python - 在 HoloViews 中为 Datashader 着色点和选择聚合方法

python - 为什么 Holoviews 在 Spyder 中不显示直方图?

python - Intellij 不断重新排序我的 `import os`

python字节(some_string, 'UTF-8')和str(some_string, 'UTF-8')

r - 在多面板 ggplot2 中标记各个面板

javascript - 如何在 ExtJS 中将停靠项目彼此相邻放置

python - Holoviews 重新排序 x 轴刻度

python - Networkx:pagerank、pagerank_numpy 和 pagerank_scipy 之间的区别?

javascript - 面板中的搜索过滤器