Search code examples
pythonjupyter-notebookjupyterjupyter-labbqplot

Change plot limits with aspect ratio = 1 in bqplot


I hope you all are fine

I'm trying to make plots with aspect_ratio=1 (same scale for both axis), but this always gives a squared layout, with no matters what are the real limits of the elements that i'm plotting

from bqplot import pyplot as plt
from bqplot import LinearScale, Axis, Lines, Figure
from ipywidgets import HTML
import pandas as pd

sc = LinearScale()

axis=[Axis(scale=sc,grid_lines='dashed'),
      Axis(scale=sc,grid_lines='dashed', orientation='vertical')]

data = {
    "X": [[0,2,5],[0,2,0]],
    "Y": [[0,2,0],[0,2,2]],
    "ID": ["1","2"],
    "Material": ["clay","sand"],
    "stress": [123, 234],
    "strain": [0.123, 0.234],
    "color": ['skyblue','pink']
}
df = pd.DataFrame(data)

def show_data(chart, d):
    idx = d["data"]["index"]
    df2=df.drop(columns=['X', 'Y','ID'])
    table=pd.DataFrame(df2.iloc[idx])
    elems.tooltip = HTML(table.to_html())

fig = plt.figure(axes=axis,min_aspect_ratio=1,max_aspect_ratio=1)

elems=plt.plot(x=df["X"].tolist(),          
         y=df["Y"].tolist(),
         fill_colors=df["color"].tolist(),
         fill='inside',
         stroke_width=1,
         close_path=True,
         scales={'x': sc, 'y': sc})
elems.on_hover(show_data)

fig.layout.height = '720px'
# plt.ylim(0,2)
plt.show()

Is this a bqplot limitation? Below I show a capture of what I have and what I want

Illustrated problem


Solution

  • There is not a simple way to do this in Bqplot. You have to calculate figure size after you specify the max (and min if not zero) of the scales. See your modified example below.

    from bqplot import pyplot as plt
    from bqplot import LinearScale, Axis, Lines, Figure
    from ipywidgets import HTML
    import pandas as pd
    
    # ---------------------------
    maxy= 3
    maxx = 6
    heightpx = 520
    # ---------------------------
    
    sc_y = LinearScale(max=maxy)
    sc_x = LinearScale(max = maxx)
    
    axis=[Axis(scale=sc_x,grid_lines='dashed'),
          Axis(scale=sc_y,grid_lines='dashed', orientation='vertical')]
    
    data = {
        "X": [[0,2,5],[0,2,0]],
        "Y": [[0,2,0],[0,2,2]],
        "ID": ["1","2"],
        "Material": ["clay","sand"],
        "stress": [123, 234],
        "strain": [0.123, 0.234],
        "color": ['skyblue','pink']
    }
    df = pd.DataFrame(data)
    
    def show_data(chart, d):
        idx = d["data"]["index"]
        df2=df.drop(columns=['X', 'Y','ID'])
        table=pd.DataFrame(df2.iloc[idx])
        elems.tooltip = HTML(table.to_html())
    
    fig = plt.figure(axes=axis)
    
    elems=plt.plot(x=df["X"].tolist(),          
             y=df["Y"].tolist(),
             fill_colors=df["color"].tolist(),
             fill='inside',
             stroke_width=1,
             close_path=True,
             scales={'x': sc_x, 'y': sc_y})
    elems.on_hover(show_data)
    
    fig.layout.height = f'{heightpx}px'
    
    width = (heightpx - fig.fig_margin['top'] - fig.fig_margin['bottom']) * (maxx/maxy) + \
                fig.fig_margin['left'] + fig.fig_margin['right']
    
    fig.layout.width = f'{width}px'
    plt.show()