2014-10-31 14 views
7

Bokeh Grundstück mit gleichen Achsen

habe ich ein Grundstück mit der Python Bibliothek Bokeh (siehe Code).Bokeh Grundstück mit gleichen Achsen

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

Wie kann ich die Quadrate (Rechteck mit der gleichen Breite und Höhe) mit gleichen Achsen wie in matplotlib mit dem Befehl axis('equal') darstellen?

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

Ich sehe die Möglichkeit, die Breite und die Höhe des Grundstücks zu ändern oder der Achsenbereich zu definieren, dieses Problem zu lösen, aber ich denke, es sollte eine intelligentere Alternative sein.

HINWEIS: Ich verwende und Bokeh v.0.6.1.

+0

Dies ist eine offene Frage: https://github.com/bokeh/bokeh/issues/474 – bigreddot

+0

Danke für den Link. Ich freue mich auf eine Lösung. – Spirou

+1

Bitte beachten Sie die neue Antwort von @DuCorey unten in Bezug auf 'match_aspect' in 0.12.7 – bigreddot

Antwort

2

Leider scheint dieses Feature zwei Jahre später noch zu fehlen. Als Workaround habe ich eine Funktion geschrieben, die die Eigenschaften einer Figur x_range und y_range passend einstellt, um Ihre Daten mit einem gegebenen Seitenverhältnis anzuzeigen. Dies funktioniert gut, solange Sie keine Werkzeuge wie Boxzoom zulassen, mit denen der Benutzer das Seitenverhältnis ändern kann.

__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 Box Zoom kann jetzt (ab' 0.12' dev builds) so konfiguriert werden, dass der bestehende Aspekt des Plots berücksichtigt wird. – bigreddot

+0

In Bezug auf den Zeitrahmen wäre die Aspektsteuerung für eine Bibliothek, die statische Bilder erzeugt, ein triviales Merkmal. Unglücklicherweise bettet Bokeh Plots in einen größeren Browser-Layout-Kontext ein und versucht, einen festen Aspekt mit einer "Web-Reaktionsfähigkeit" (auch eine kontinuierlich angeforderte Funktion) in Einklang zu bringen, wird ein sehr heikles Problem. Wir arbeiten daran, so gut und so schnell, wie es unsere begrenzten Ressourcen erlauben. – bigreddot

+0

Diese Lösung ist großartig. Bei der Implementierung für die Ausführung auf einem 0.12.5-Server musste ich stattdessen die Start- und Endeigenschaften des Bereichs direkt ändern, damit es funktioniert. 'fig.x_range.start = xcenter - 0,5 * Breite fig.x_range.end = xcenter + 0,5 * Breite fig.y_range.start = ycenter - 0,5 * Höhe fig.y_range.end = ycenter + 0,5 * height' – DuCorey

5

Ab Bokeh 0.12.7 wurde diese Funktion implementiert. Plots können jetzt zwei neue Eigenschaften akzeptieren. match_aspect, die, wenn sie auf "true" gesetzt sind, den Aspekt des Datenraums mit dem Pixelraum des Diagramms abgleichen. Zum Beispiel sind Quadrate, die in Dateneinheiten gezeichnet werden, jetzt ebenfalls perfekte Quadrate in Pixeleinheiten.

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

Bokeh match aspect = True

aspect_scale ermöglicht weiter das Verhältnis Aspekt Steuerung durch einen Multiplizierer auf der Oberseite der Seiten Korrektur durch match_aspect angibt.

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

Es wäre lehrreich, wenn Sie den Code hinzufügen, mit dem diese Zahlen erzeugt werden. – jorgeh

+1

@jorgeh Danke für den Kommentar. Ich habe den Code hinzugefügt, mit dem die Figuren generiert wurden. – DuCorey