使用 Panel 小部件以交互方式更新 Holoviews Image
Update Holoviews Image interactively with Panel widget
我有一组灰度图像(2D numpy 数组),想根据 holoviews.MultiSelect 小部件的状态同时显示其中的几个,但是当 selection 是在 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
初始面板布局符合预期,但是当我 select 在 MultiSelect 中创建索引时,图像不会更新。检查 MultiSelect 对象的值,
image_selector.value[0]
我得到了 selected 索引,所以问题必须出在修饰的 change_image_shown
函数中,但我没有尝试过。我错过了什么?
所以你似乎对更新HoloViews plots的模型有一点误解。不应就地修改 HoloViews 元素,而是设置一个回调 returns 给定一组依赖项更新的绘图。然后将其包装在 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
小部件吗?
我有一组灰度图像(2D numpy 数组),想根据 holoviews.MultiSelect 小部件的状态同时显示其中的几个,但是当 selection 是在 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
初始面板布局符合预期,但是当我 select 在 MultiSelect 中创建索引时,图像不会更新。检查 MultiSelect 对象的值,
image_selector.value[0]
我得到了 selected 索引,所以问题必须出在修饰的 change_image_shown
函数中,但我没有尝试过。我错过了什么?
所以你似乎对更新HoloViews plots的模型有一点误解。不应就地修改 HoloViews 元素,而是设置一个回调 returns 给定一组依赖项更新的绘图。然后将其包装在 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
小部件吗?