2014-10-31 6 views
7

Bokeh Участок с равными осями

Я создал Участок с Python библиотеки Bokeh (см код).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.

+0

Это открытый вопрос: https://github.com/bokeh/bokeh/issues/474 – bigreddot

+0

Спасибо за ссылку. Я с нетерпением жду возможности использовать решение. – Spirou

+1

Обратите внимание, что новый ответ by @DuCorey ниже относительно 'match_aspect' в 0.12.7 – bigreddot

ответ

2

К сожалению, через два года эта функция все еще отсутствует. В качестве обходного пути я написал функцию, которая устанавливает свойства и 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) 
+0

Теперь размер окна FYI теперь (по умолчанию' 0.12' dev builds) настроен на уважение существующего аспекта графика. – bigreddot

+0

Что касается временных рамок, для библиотеки, которая генерирует статические изображения, управление аспектами будет тривиальной функцией. К сожалению, Bokeh вкладывает графики в более широкий контекст макета браузера и пытается согласовать фиксированный аспект с «чувствительностью к сети» (также непрерывно запрашиваемой функцией), это становится очень сложной проблемой. Мы работаем над этим, как лучше, так и быстро, как позволяют наши ограниченные ресурсы. – bigreddot

+0

Это решение замечательно. Однако при реализации его для запуска на сервере 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

5

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

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

Bokeh match aspect = True

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

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

Bokeh aspect scale = 2

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

Bokeh aspect scale = 0.5

+0

Было бы поучительно добавить код, используемый для создания этих цифр. – jorgeh

+1

@jorgeh Спасибо за комментарий. Я добавил код, который использовался для создания цифр. – DuCorey

Смежные вопросы