Get the aspect ratio of the axes

Is there a simple and reliable way to determine the current aspect ratio of 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 on ax.set_aspect(aspect) , after which the same constant is returned ax.get_aspect() . By default (and very useful) we have aspect = 'auto' , in which case the proportionality coefficient is automatically calculated and adjusted in accordance with the data size and the size of the axes.
How can I get the numerical aspect ratio that was automatically selected?

To clarify, this is not the aspect ratio of the data limits returned by ax.get_data_ratio() , nor the aspect ratio of the shape display size or subtitle returned by fig.get_figheight() / fig.get_figwidth() (for the picture). This is a little subtle, as it depends on both the screen size and the data limitations. (This can lead to confusion of different ratios and the reason why I think this is easily accessible.)

+3
python matplotlib
source share
3 answers

Of the docs, aspect ratio is the ratio of data scaling units to the display in the x and y axes. that is, if there are 10 data units and 1 unit of data per display unit in the x direction on the display in y units, this ratio will be 1/10. The circle will be 10 times wider than tall. This is consistent with the statement that the num aspect does the following:

the circle will be stretched so that the height is several times larger than the width. aspect = 1 matches aspect = equal.

Based on the same original code snippet you were looking at ( matplotlib.axes._base.adjust_aspect starting at line 1405 ), I think we can come up with a simplified formula if you only need this ratio for linear Cartesian axes. Everything is complicated by polar and logarithmic axes, so I will ignore them.

Repeat formula:

 (x_data_unit / x_display_unit) / (y_data_unit / y_display_unit) 

It happens the same way

 (y_display_unit / x_display_unit) / (y_data_unit / x_data_unit) 

This last statement is simply the ratio of the dimensions of the display in two directions divided by the ratio of the limits x and y. Note that ax.get_data_ratio NOT applied here because it returns results for actual data boundaries, not axis limits:

 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))) 
+2
source share

The best I can find is this:

 def get_aspect(ax=None): if ax is None: ax = plt.gca() fig = ax.figure ll, ur = ax.get_position() * fig.get_size_inches() width, height = ur - ll axes_ratio = height / width aspect = axes_ratio / ax.get_data_ratio() return aspect 

But this is surprisingly complicated, and I'm not sure if it is reliable in transforms, etc., since I don't know anything about bbox and transform objects.

0
source share

What about

 import numpy as np aspect = sum(np.abs(ax.get_xlim())) / sum(np.abs(ax.get_ylim())) 
0
source share

All Articles