Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
313 views
in Technique[技术] by (71.8m points)

python - get aspect ratio of axes

Is there an easy and reliable way to determine the current aspect ratio of an axes when its aspect is set to 'auto'?

The obvious thing to check is ax.get_aspect(), but that just returns 'auto'. I can set it to an arbitrary constant value by ax.set_aspect(aspect), after which that same constant is returned by ax.get_aspect(). By default (and very usefully) we have aspect = 'auto', in which case the aspect ratio is automatically calculated and adjusted to match the data limits and axes size.
How can I get the numeric aspect ratio that was automatically selected?

To clarify, this is neither the aspect ratio of the data limits returned by ax.get_data_ratio(), nor the aspect ratio of the display size of the figure or subplot returned by fig.get_figheight() / fig.get_figwidth() (for the figure). It's a bit subtle, as it depends on both the display size and the data limits. (Which can lead to confusing the different ratios and the reason I find it important to have it easily accessible.)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

From the docs, the aspect ratio is the ratio of data-to-display scaling units in the x- and y-axes. i.e., if there are 10 data units per display in the y-direction and 1 data unit per display unit in the x-direction, the ratio would be 1/10. The circle would be 10 times wider than it is tall. This corresponds to the statement that an aspect of num does the following:

a circle will be stretched such that the height is num times the width. aspect=1 is the same as aspect=’equal’.

Based on the same original piece of code that you looked at (matplotlib.axes._base.adjust_aspect, starting around line 1405), I think we can come up with a simplified formula as long as you only need this ratio for linear Cartesian axes. Things get complicated with polar and logarithmic axes, so I will ignore them.

To reiterate the formula:

(x_data_unit / x_display_unit) / (y_data_unit / y_display_unit)

This happens to be the same as

(y_display_unit / x_display_unit) / (y_data_unit / x_data_unit)

This last formulation is just the ratio of the display sizes in the two directions divided by the ratio of the x and y limits. Note that ax.get_data_ratio does NOT apply here because that returns the results for the actual data bounds, not the axis limits at all:

from operator import sub
def get_aspect(ax):
    # Total figure size
    figW, figH = ax.get_figure().get_size_inches()
    # Axis size on figure
    _, _, w, h = ax.get_position().bounds
    # Ratio of display units
    disp_ratio = (figH * h) / (figW * w)
    # Ratio of data units
    # Negative over negative because of the order of subtraction
    data_ratio = sub(*ax.get_ylim()) / sub(*ax.get_xlim())

    return disp_ratio / data_ratio

Now let's test it:

from matplotlib import pyplot as plt
fig, ax = plt.subplots()
ax.set_aspect('equal')
print('{} == {}'.format(ax.get_aspect(), get_aspect(ax)))
ax.set_aspect(10)
print('{} == {}'.format(ax.get_aspect(), get_aspect(ax)))

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...