【问题标题】:Update Holoviews Image interactively with Panel widget使用面板小部件以交互方式更新 Holoviews 图像
【发布时间】:2020-06-18 00:52:45
【问题描述】:

我有一组灰度图像(2D numpy 数组),并希望根据 holoviews.MultiSelect 小部件的状态同时显示其中的几个,但在 MultiSelect 中进行选择时无法更新图像小部件。这是一个最小的工作示例:

pn.extension()

import numpy as np
import holoviews as hv
from holoviews import opts
hv.extension('bokeh')

# Make grayscale test images
images = []
xmax, ymax = 2560, 1600
for i in range(5):
    # Gray background
    image = np.ones(shape=(ymax, xmax), dtype=np.uint8) * 200
    # Make each image unique with different position for a black square
    # with interior white square
    image[200*i:200*i + 400,200*i:200*i + 400] = 0
    image[200*i+175:200*i+175 + 50,200*i+175:200*i+175 + 50] = 255
    images.append(image)

# Make hv.Images objects
scale_factor = 8
bounds=(0, 0, xmax, ymax)   # Coordinate system: (left, bottom, right, top)
img_0 = hv.Image(images[0], bounds=bounds)
img_1 = hv.Image(images[1], bounds=bounds)
options = [
    opts.Image(cmap='gray',
               aspect='equal',
               frame_width=int(xmax/scale_factor),
               frame_height=int(ymax/scale_factor),
              )
]
img_0.opts(*options)
img_1.opts(*options)

# Set up selector object
image_selector = pn.widgets.MultiSelect(name="Choose image index", 
                                 options=[i for i in range(len(images))],
                                 size=6,
                                 width=120
                                )

# Define interactivity
@pn.depends(image_selector, watch=True)
def change_image_shown(image_selector):
    index = image_selector[0]
    img_0.data = images[index]
    if index != len(images) - 1:
        img_1.data = images[index + 1]
    else:
        img_1.data = images[index]

# Create panel layout
layout = pn.Row(image_selector, pn.Column(img_0, img_1))
layout

初始面板布局符合预期,但是当我在 MultiSelect 中选择索引时,图像不会更新。检查 MultiSelect 对象的值,

image_selector.value[0]

我得到了选定的索引,所以问题必须出在装饰的 change_image_shown 函数中,但我没有尝试过任何工作。我错过了什么?

【问题讨论】:

    标签: image panel dashboard holoviews python-interactive


    【解决方案1】:

    所以你似乎有点误解了更新 HoloViews 图的模型。 HoloViews 元素不应就地修改,而是设置一个回调,返回给定一组依赖项的更新绘图。然后将其包装在 DynamicMap 中,当触发事件时将动态重新呈现。

    import numpy as np
    import holoviews as hv
    
    from holoviews import opts
    
    hv.extension('bokeh')
    
    # Make grayscale test images
    images = []
    xmax, ymax = 2560, 1600
    for i in range(5):
        # Gray background
        image = np.ones(shape=(ymax, xmax), dtype=np.uint8) * 200
        # Make each image unique with different position for a black square
        # with interior white square
        image[200*i:200*i + 400,200*i:200*i + 400] = 0
        image[200*i+175:200*i+175 + 50,200*i+175:200*i+175 + 50] = 255
        images.append(image)
    
    # Make hv.Images objects
    scale_factor = 8
    bounds=(0, 0, xmax, ymax)   # Coordinate system: (left, bottom, right, top)
    options = [
        opts.Image(cmap='gray',
                   aspect='equal',
                   frame_width=int(xmax/scale_factor),
                   frame_height=int(ymax/scale_factor),
                  )
    ]
    
    # Set up selector object
    image_selector = pn.widgets.MultiSelect(
        name="Choose image index", 
        options=[i for i in range(len(images))],
        size=6,
        width=120,
        value=[0, 1]
    )
    
    # Define interactivity
    @pn.depends(indexes=image_selector)
    def img0(indexes):
        index = indexes[0]
        return hv.Image(images[index], bounds=bounds).opts(*options)
    
    @pn.depends(indexes=image_selector)
    def img1(indexes):
        index = indexes[0]
        if index != len(images) - 1:
            data = images[index + 1]
        else:
            data = images[index]
        return hv.Image(images[index], bounds=bounds).opts(*options)
    
    
    # Create panel layout
    layout = pn.Row(
        image_selector,
        pn.Column(
            hv.DynamicMap(img0),
            hv.DynamicMap(img1)
        )
    )
    layout
    

    以上是使用模型重写的代码。那就是说我对你的回调还是有点困惑。如果您只使用第一个选定的值,为什么还要使用 MultiSelect 小部件?你想要简单的Select 小部件吗?

    【讨论】:

    • 你说得对——我不了解更新 HoloViews 绘图的模型。在浏览了几乎所有的文档之后,我错过了。我还认为 DynamicMap 仅适用于您想要连续改变一个或多个参数时,这是我在文档中看到的。我非常感谢您帮助我理清了我的误解。上面的代码非常有用。
    • MultiSelect 元素的原因如下:我将有 200-400 张图像可供选择,我对 Select 小部件的理解是它会创建一个下拉菜单,其中包含这么多项目会很笨拙从中选择。我认为滚动浏览可能性会更容易,这就是 MultiSelect 所支持的。它允许多个同时选择的能力与我需要的无关,所以我只取它返回的第一项。
    • 我已经浏览了更多代码以确保我理解它是如何工作的。我非常感谢你在这方面的帮助!
    • 很高兴你学到了一些东西。如果您错过了这一点,我们显然在文档上做得不好,因此欢迎提出任何改进建议。
    • 你也说得很好,有一个像 MultiSelect 这样的小部件会很好,它只允许选择一个项目,而 iirc 在 Panel 中有一个问题,所以希望我或其他人会有是时候尽快解决这个问题了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-31
    • 1970-01-01
    相关资源
    最近更新 更多