我在 Django 应用程序中使用 bokeh 1.0.1 版本,我想将微观表面图像显示为具有颜色编码高度和颜色条的可缩放图像图。原则上这是可行的,但我在获取具有正确纵横比的绘图时遇到问题,仅显示图像而周围没有空间。
这是我想要实现的示例:结果图应该
- 显示宽度为的随机数据图像
sx=10
和高度sy=5
在数据空间中(图像size)
- 轴限制为
(0,sx)
and (0,sy)
,初步看来
以及缩放时
- 屏幕上的正方形应该与数据空间中的正方形匹配,至少在初始视图中
对于图像,我只使用随机数据nx=100
x 方向上的点和ny=100
点在 y 方向。
这是我的第一个方法:
尝试1
from bokeh.models.ranges import Range1d
from bokeh.plotting import figure, show
from bokeh.models import LinearColorMapper, ColorBar
import numpy as np
sx = 10
sy = 5
nx = 100
ny = 100
arr = np.random.rand(nx, ny)
x_range = Range1d(start=0, end=sx, bounds=(0,sx))
y_range = Range1d(start=0, end=sy, bounds=(0,sy))
# Attempt 1
plot = figure(x_range=x_range, y_range=y_range, match_aspect=True)
# Attempt 2
# plot = figure(match_aspect=True)
# Attempt 3
# pw = 400
# ph = int(400/sx*sy)
# plot = figure(plot_width=pw, plot_height=ph,
# x_range=x_range, y_range=y_range, match_aspect=True)
color_mapper = LinearColorMapper(palette="Viridis256",
low=arr.min(), high=arr.max())
colorbar = ColorBar(color_mapper=color_mapper, location=(0,0))
plot.image([arr], x=[0], y=[0], dw=[sx], dh=[sy],
color_mapper=color_mapper)
plot.rect(x=[0,sx,sx,0,sx/2], y=[0,0,sy,sy,sy/2],
height=1, width=1, color='blue')
plot.add_layout(colorbar, 'right')
show(plot)
我还在图中添加了蓝色方块,以便查看何时
纵横比要求失败。
不幸的是,在结果图片 https://i.stack.imgur.com/omQL1.png,正方形不再是正方形了,它的高是宽的两倍。缩放和平移按预期工作。
尝试2
当使用省略范围时
plot = figure(match_aspect=True)
我去拿这张照片 https://i.stack.imgur.com/Wcxux.png。正方形是屏幕上的一个正方形,
这很好,但是轴范围改变了,所以有
现在它周围的空间。我只想只覆盖数据区域
图像。
尝试3
或者,当提供plot_height
and plot_width
到图中,
具有预定义的纵横比,例如经过
pw = 800 # plot width
ph = int(pw/sx*sy)
plot = figure(plot_width=pw, plot_height=ph,
x_range=x_range, y_range=y_range,
match_aspect=True)
我去拿这张照片 https://i.stack.imgur.com/r2WPV.png。广场也不再是广场了。几乎可以完成,但是很难,因为plot_width还包括颜色条和工具栏。
我读了这个相应的博客文章 https://stackoverflow.com/questions/26674779/bokeh-plot-with-equal-axes以及相应的散景文档 https://bokeh.pydata.org/en/latest/docs/reference/models/plots.html#bokeh.models.plots.Plot,但我无法让它工作。
有谁知道如何实现我想要的或者是否不可能?
响应行为也很好,但我们现在可以忽略这一点。
感谢您的任何提示。
Update
与 Bokeh 开发人员交谈后Gitter https://gitter.im/bokeh/bokeh?at=5c08ea695e40952503228d58(谢谢布莱恩!)看来我想要的几乎是不可能的。
原因是,如何match_aspect=True
工作原理是为了使数据空间中的正方形看起来像像素空间中的正方形:给定画布大小,这可能是由于应用不同的画布大小而产生的sizing_mode
设置响应行为,然后更改数据范围以获得匹配的宽高比。因此,没有其他方法可以使像素长宽比与数据长宽比匹配,而无需在图像周围添加额外的空间,即将轴延伸到给定的边界上。另请参阅此评论issue https://github.com/bokeh/bokeh/issues/8486.
可以在没有响应行为的情况下根据纵横比预先固定画布大小,但目前并不完美,因为内部绘图框架周围的所有其他元素也占用空间。有一个PR https://github.com/bokeh/bokeh/pull/8085这可能允许直接控制内部框架尺寸,但我不知道该怎么做。
好吧,如果我放弃紧轴目标怎么办?
这是在上面的“尝试 2”中完成的,但图像周围有太多空白空间,与图像绘图占用的空间相同。
我尝试过使用各种range_padding*
属性,例如
x_range = DataRange1d(range_padding=10, range_padding_units='percent')
y_range = DataRange1d(range_padding=10, range_padding_units='percent')
但它并没有减少地块周围的空间量,而只是增加了它。以百分比为单位的填充应相对于由下式给出的图像尺寸dh
and dw
.
有谁知道如何使用range_padding
参数具有较小的轴范围或另一种方式在上面的示例中在图像图周围具有较小的填充(使用match_aspect=True
)?
我已经打开了另一个问题 https://stackoverflow.com/questions/55225823/smaller-range-padding-for-image-plot-with-bokeh关于这一点。