Боке График с равными осями

Боке График с равными осями

Я создал Plot с библиотекой Python Bokeh (см. код).

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

Как я могу представить квадраты (прямоугольник с одинаковой шириной и высотой) с одинаковыми осями, как в matplotlib, с помощью команды axis('equal')?

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

Я вижу возможность изменить ширину и высоту графика или определить диапазон осей, чтобы решить эту проблему, но я думаю, что должна быть более разумная альтернатива.

ПРИМЕЧАНИЕ. Я использую Python v.2.7.8 и Bokeh v.0.6.1.


person Spirou    schedule 31.10.2014    source источник
comment
Это открытый вопрос: github.com/bokeh/bokeh/issues/474   -  person bigreddot    schedule 04.11.2014
comment
Спасибо за ссылку. Я с нетерпением жду возможности использовать решение.   -  person Spirou    schedule 07.11.2014
comment
Обратите внимание на новый ответ @DuCorey ниже относительно match_aspect в 0.12.7.   -  person bigreddot    schedule 30.08.2017


Ответы (2)


Начиная с Bokeh 0.12.7, эта функция реализована. Графики теперь могут принимать два новых свойства. match_aspect, который, если установлено значение true, будет соответствовать аспекту пространства данных пиксельному пространству графика. Например, квадраты, нарисованные в единицах данных, теперь также будут идеальными квадратами в единицах пикселей.

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

Боке соответствует аспекту = True

aspect_scale позволяет дополнительно контролировать соотношение сторон, указывая множитель поверх коррекции соотношения сторон, сделанной match_aspect.

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

Шкала соотношения сторон боке = 2

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

Шкала соотношения сторон боке = 0,5

person DuCorey    schedule 30.08.2017
comment
Было бы поучительно, если бы вы добавили код, используемый для создания этих цифр. - person jorgeh; 17.10.2017
comment
@jorgeh Спасибо за комментарий. Я добавил код, который использовался для создания фигур. - person DuCorey; 19.10.2017

К сожалению, кажется, что два года спустя эта функция все еще отсутствует. В качестве обходного пути я написал функцию, которая устанавливает свойства x_range и y_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)
person Martin Wiebusch    schedule 23.04.2016
comment
К вашему сведению, масштабирование окна теперь можно настроить (начиная с 0.12 сборок для разработчиков) с учетом существующего аспекта сюжета. - person bigreddot; 26.04.2016
comment
Что касается временных рамок, то для библиотеки, генерирующей статические изображения, управление аспектами было бы тривиальной функцией. К сожалению, Bokeh встраивает графики в более широкий контекст макета браузера, и попытка согласовать фиксированный аспект с веб-отзывчивостью (также постоянно запрашиваемая функция) становится очень сложной проблемой. Мы работаем над этим настолько хорошо и быстро, насколько позволяют наши ограниченные ресурсы. - person bigreddot; 26.04.2016
comment
Это отличное решение. Однако при реализации его для работы на сервере 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 - person DuCorey; 07.07.2017
comment
Обратите внимание на новый ответ @DuCorey ниже о match_aspect в 0.12.7. - person bigreddot; 30.08.2017