python - 在 Holoviews 中结合 Pointdraw 和 Sample
问题描述
我正在尝试将 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))
对于我们正在绘制的奇怪函数,我深表歉意,我无法立即想出一个简单的函数。
解决方案
根据您的示例,我还不太清楚您将如何处理这些点,但我确实有一些关于更好地构建代码的建议。
一般来说,从几个单独的 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,您可以将其与其余部分组合。
推荐阅读
- python - Python np.busday_count 与 datetime64[ns] 作为输入
- python - Python Tkinter - 一段时间后或点击后销毁窗口
- python - 密码更改所需的 Django 2.0 测试登录失败并出现语法错误
- android - 在后台获取数据并在 UI 中显示
- reactjs - 复选框切换无法正常工作
- octobercms - 分页影响 octobercms 导航中的 URL
- javascript - 如何在打字稿中以 mm-dd-yyy hh-mm-ss 获取日期和时间?
- php - Laravel CRON 工匠错误
- javascript - 如何在 Zapier 中创建重拍触发器?
- spring - Spring Cloud Gateway 2.0.0.RELEASE:找不到名称为 Hystrix 的 GatewayFilterFactory