python – 具有紧轴和匹配纵横比的散景图像绘图

我在Django应用程序中使用散景1.0.1版本,我想将微观表面图像显示为具有颜色编码高度和颜色条的可缩放图像图.原则上这是有效的,但是我有问题要获得具有正确宽高比的图,仅显示没有空间的图像.

以下是我想要实现的示例:结果图应该是

>在数据空间(图像大小)中显示宽度为sx = 10且sy = 5的高度的随机数据的图像
>在初始视图中将轴限制为(0,sx)和(0,sy)
当缩放时
>屏幕上的正方形应与数据空间中的正方形匹配,至少在初始视图中是这样

对于图像,我只使用随机数据,在x方向上nx = 100个点,在y方向上ny = 100个点.

这是我的第一种方法:

尝试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)

我还在情节中添加了蓝色方块,以便看到
宽高比要求失败.

不幸的是,在resulting picture中,广场不再是正方形,它的宽度是广场的两倍.缩放和平移按预期工作.

尝试2

使用时省略范围

plot = figure(match_aspect=True)

我会得到this picture.广场是屏幕上的正方形,
这很好,但是轴的范围发生了变化,所以有
现在它周围的空间.我想只有数据区域
图片.

尝试3

或者,在为图形提供plot_height和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)

我会得到this picture.广场也不再是正方形.它几乎可以完成,但很难,因为plot_width还包括colorbar和工具栏.

我读过this corresponding blog post
和相应的bokeh documentation,但我不能让它工作.

有人知道如何实现我想要的或者是不可能的吗?
反应行为也会很好,但我们现在可以忽略这一点.
谢谢你的任何提示.

更新

Gitter与Bokeh开发人员交谈后(感谢Bryan!),似乎我想要的几乎不可能.

原因是,match_aspect = True如何工作以使数据空间中的正方形在像素空间中看起来像一个正方形:给定画布大小,这可能是由于对响应行为应用不同的sizing_mode设置,因此数据范围会在为了获得匹配的宽高比.因此,没有其他方法可以使像素长宽比与数据宽高比相匹配,而不会在图像周围添加额外的空间,即在给定的边界上延伸轴.另见issue的评论.

没有响应行为,然后预先相对于纵横比固定画布大小可以完成,但目前不完美,因为内部绘图框架周围的所有其他元素也占用空间.有一个PR可以直接控制内框尺寸,但我不知道该怎么做.

好吧,如果我放弃拥有紧轴的目标怎么办?
这是在上面的“尝试2”中完成的,但图像周围有太多的空白区域,与图像绘图所占的空间相同.

我试过使用各种range_padding *属性,例如

x_range = DataRange1d(range_padding=10, range_padding_units='percent')
y_range = DataRange1d(range_padding=10, range_padding_units='percent')

但它不会减少绘图周围的空间量,但只会增加它.以百分比表示的填充应该与dh和dw给出的图像尺寸相关.

有人知道如何使用range_padding参数来获得较小的轴范围,或者在上面的示例中使用较小的填充来围绕图像绘图(使用match_aspect = True)?
我已经开了another question了.

最佳答案 你能接受这个解决方案(适用于Bokeh v1.0.4)吗?

from bokeh.models.ranges import Range1d
from bokeh.plotting import figure, show
from bokeh.layouts import Row
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))

pw = 400
ph = pw * sy / sx
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())

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')

colorbar_plot = figure(plot_height = ph, plot_width = 69, x_axis_location = None, y_axis_location = None, title = None, tools = '', toolbar_location = None)
colorbar = ColorBar(color_mapper = color_mapper, location = (0, 0))
colorbar_plot.add_layout(colorbar, 'left')

show(Row(plot, colorbar_plot))

结果:

《python – 具有紧轴和匹配纵横比的散景图像绘图》

点赞