我正在尝试将Holoviews的Pointdraw功能与其示例功能结合在一起(我找不到特定的页面,但在此处http://holoviews.org/gallery/demos/bokeh/mandelbrot_section.html中对此进行了展示)
具体来说,我想有两个具有交互性的子图。左侧的一个显示一个颜色图,右侧的一个显示颜色图的样本(线条)。这是通过.sample
实现的。在这个右图中,我希望可以绘制,移动和删除点,通常使用pointdraw
完成。然后,我还想在完成移动后访问它们的坐标,这可以按照文档中的示例进行操作。
现在,按照上面的示例,我让两个人独立工作。但是,当按照我的方式组合时,这将导致如下图所示: 它具有我要寻找的元素,但不能与这些点交互。这在某种程度上与Holoviews的流有关,但是我不确定如何解决。有人可以帮忙吗?
生成以上代码的代码:
%%opts Points (color='color' size=10) [tools=['hover'] width=400 height=400]
%%opts Layout [shared_datasource=True] Table (editable=True)
import param
import numpy as np
import holoviews as hv
hv.extension('bokeh', 'matplotlib')
from holoviews import streams
def lorentzian(x, x0, gamma):
return 1/np.pi*1/2*gamma/((x-x0)**2+(1/2*gamma)**2)
xs = np.arange(0,4*np.pi,0.05)
ys = np.arange(0,4*np.pi,0.05)
data = hv.OrderedDict({'x': [2., 2., 2.], 'y': [0.5, 0.4, 0.2], 'color': ['red', 'green', 'blue']})
z = lorentzian(xs.reshape(len(xs),1),2*np.sin(ys.reshape(1,len(ys)))+5,1) + lorentzian(xs.reshape(len(xs),1),-2*np.sin(ys.reshape(1,len(ys)))+5,1)
def dispersions(f0):
points = hv.Points(data, vdims=['color']).redim.range(x=(xs[0], xs[-1]), y=(np.min(z), np.max(z)))
point_stream = streams.PointDraw(data=points.columns(), source=points, empty_value='black')
image = hv.Image(z, bounds=(xs[0], ys[0], xs[-1], ys[-1]))
return image* hv.VLine(x=f0) + image.sample(x=f0)*points
dmap = hv.DynamicMap(dispersions, kdims=['f0'])
dmap.redim.range(f0=(0,10)).redim.step(f0=(0.1))
我为我们正在绘制的怪异函数表示歉意,我无法立即提出一个简单的函数。
答案 0 :(得分:3)
根据您的示例,我还不太清楚您将如何处理这些要点,但是我对如何更好地构建代码提出了一些建议。
通常,由多个单独的DynamicMap构成图总是比创建一个可以完成所有功能的单个DynamicMap更好。它不仅更具可组合性,而且还获得了单个对象的句柄,使您可以设置流以侦听每个组件上的更改,最重要的是,它效率更高,仅更新需要更新的图。在您的示例中,我将代码拆分如下:
def lorentzian(x, x0, gamma):
return 1/np.pi*1/2*gamma/((x-x0)**2+(1/2*gamma)**2)
xs = np.arange(0,4*np.pi,0.05)
ys = np.arange(0,4*np.pi,0.05)
data = hv.OrderedDict({'x': [2., 2., 2.], 'y': [0.5, 0.4, 0.2], 'color': ['red', 'green', 'blue']})
points = hv.Points(data, vdims=['color']).redim.range(x=(xs[0], xs[-1]), y=(np.min(z), np.max(z)))
image = hv.Image(z, bounds=(xs[0], ys[0], xs[-1], ys[-1]))
z = lorentzian(xs.reshape(len(xs),1),2*np.sin(ys.reshape(1,len(ys)))+5,1) + lorentzian(xs.reshape(len(xs),1),-2*np.sin(ys.reshape(1,len(ys)))+5,1)
taps = []
def vline(f0):
return hv.VLine(x=f0)
def sample(f0):
return image.sample(x=f0)
dim = hv.Dimension('f0', step=0.1, range=(0,10))
vline_dmap = hv.DynamicMap(vline, kdims=[dim])
sample_dmap = hv.DynamicMap(sample, kdims=[dim])
point_stream = streams.PointDraw(data=points.columns(), source=points, empty_value='black')
(image * vline_dmap + sample_dmap * points)
由于图像和点本身不是动态的,因此没有理由将它们放置在DynamicMap中,并且可以轻松地将VLine和采样曲线分开。 PointDraw流还没有执行任何操作,但是您现在可以将其设置为另一个DynamicMap,可以与其余部分组成。