【问题标题】:Bokeh Plot with equal axes等轴散景图
【发布时间】:2014-12-27 18:43:01
【问题描述】:

等轴散景图

我使用 PythonBokeh 创建了一个 Plot(参见代码)。

from bokeh.plotting import *

figure()
hold()
rect([1,3], [1,1], [1,0.5], [1,0.5])
patch([0,0,4,4], [2,0,0,2], line_color="black", fill_color=None)
show()

如何使用命令axis('equal') 以与 matplotlib 中相同的轴表示正方形(具有相同宽度和高度的矩形)?

http://matplotlib.org/examples/pylab_examples/axis_equal_demo.html

我看到了更改绘图宽度和高度或定义轴范围来解决此问题的选项,但我认为应该有更聪明的选择。

注意:我使用的是 Python v.2.7.8Bokeh v.0.6.1

【问题讨论】:

  • 这是一个未解决的问题:github.com/bokeh/bokeh/issues/474
  • 感谢您的链接。我期待使用解决方案。
  • 请注意下面@DuCorey 关于0.12.7 中match_aspect 的新回答

标签: python axes bokeh


【解决方案1】:

从 Bokeh 0.12.7 开始,此功能已实现。绘图现在可以接受两个新属性。 match_aspect,当设置为 true 时,会将数据空间的方面与绘图的像素空间相匹配。例如,以数据单位绘制的正方形现在也将是像素单位的完美正方形。

p = figure(match_aspect=True)
p.circle([-1, +1, +1, -1], [-1, -1, +1, +1])

aspect_scale 允许您通过在match_aspect 进行的纵横校正之上指定一个乘数来进一步控制纵横比。

p = figure(aspect_scale=2)
p.circle([-1, +1, +1, -1], [-1, -1, +1, +1])

p = figure(aspect_scale=0.5)
p.circle([-1, +1, +1, -1], [-1, -1, +1, +1])

【讨论】:

  • 如果您添加用于生成这些数字的代码会很有指导意义。
  • @jorgeh 感谢您的评论。我已经添加了用于生成数字的代码。
【解决方案2】:

遗憾的是,两年后似乎仍然缺少此功能。作为一种解决方法,我编写了一个函数,它可以适当地设置图形的x_rangey_range 属性,以便以给定的纵横比显示您的数据。只要您不允许使用任何工具(例如让用户修改纵横比的框缩放),此方法就可以正常工作。

__all__ = ['set_aspect']

from bokeh.models import Range1d

def set_aspect(fig, x, y, aspect=1, margin=0.1):
    """Set the plot ranges to achieve a given aspect ratio.

    Args:
      fig (bokeh Figure): The figure object to modify.
      x (iterable): The x-coordinates of the displayed data.
      y (iterable): The y-coordinates of the displayed data.
      aspect (float, optional): The desired aspect ratio. Defaults to 1.
        Values larger than 1 mean the plot is squeezed horizontally.
      margin (float, optional): The margin to add for glyphs (as a fraction
        of the total plot range). Defaults to 0.1
    """
    xmin = min(xi for xi in x)
    xmax = max(xi for xi in x)
    ymin = min(yi for yi in y)
    ymax = max(yi for yi in y)
    width = (xmax - xmin)*(1+2*margin)
    if width <= 0:
        width = 1.0
    height = (ymax - ymin)*(1+2*margin)
    if height <= 0:
        height = 1.0
    xcenter = 0.5*(xmax + xmin)
    ycenter = 0.5*(ymax + ymin)
    r = aspect*(fig.plot_width/fig.plot_height)
    if width < r*height:
        width = r*height
    else:
        height = width/r
    fig.x_range = Range1d(xcenter-0.5*width, xcenter+0.5*width)
    fig.y_range = Range1d(ycenter-0.5*height, ycenter+0.5*height)

if __name__ == '__main__':
    from bokeh.plotting import figure, output_file, show

    x = [-1, +1, +1, -1]
    y = [-1, -1, +1, +1]
    output_file("bokeh_aspect.html")
    p = figure(plot_width=400, plot_height=300, tools='pan,wheel_zoom',
               title="Aspect Demo")
    set_aspect(p, x, y, aspect=2)
    p.circle(x, y, size=10)
    show(p)

【讨论】:

  • 仅供参考,现在可以将框缩放(截至0.12 dev builds)配置为尊重情节的现有方面。
  • 关于时间范围,对于生成静态图像的库,纵横比控制将是一个微不足道的功能。不幸的是,Bokeh 将绘图嵌入到更大的浏览器布局上下文中,并试图将固定方面与“Web 响应性”(也是一个不断请求的功能)相协调,这成为一个非常棘手的问题。我们正在努力,在我们有限的资源允许的范围内尽可能快地进行。
  • 这个解决方案很棒。但是,当实现它以在 0.12.5 服务器上运行时,我不得不直接修改范围开始和结束属性以使其工作。 fig.x_range.start = xcenter - 0.5 * width fig.x_range.end = xcenter + 0.5 * width fig.y_range.start = ycenter - 0.5 * height fig.y_range.end = ycenter + 0.5 * height
  • 请注意下面@DuCorey 关于0.12.7 中match_aspect 的新回答
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-07-30
  • 1970-01-01
  • 2015-08-13
  • 1970-01-01
  • 2017-07-10
  • 2023-03-22
  • 1970-01-01
相关资源
最近更新 更多