Reduce left and right margins in matplotlib plot - python

I'm struggling to deal with my plot margins in matplotlib. I've used the code below to produce my chart:
plt.imshow(g)
c = plt.colorbar()
c.set_label("Number of Slabs")
plt.savefig("OutputToUse.png")
However, I get an output figure with lots of white space on either side of the plot. I've searched google and read the matplotlib documentation, but I can't seem to find how to reduce this.

One way to automatically do this is the bbox_inches='tight' kwarg to plt.savefig.
E.g.
import matplotlib.pyplot as plt
import numpy as np
data = np.arange(3000).reshape((100,30))
plt.imshow(data)
plt.savefig('test.png', bbox_inches='tight')
Another way is to use fig.tight_layout()
import matplotlib.pyplot as plt
import numpy as np
xs = np.linspace(0, 1, 20); ys = np.sin(xs)
fig = plt.figure()
axes = fig.add_subplot(1,1,1)
axes.plot(xs, ys)
# This should be called after all axes have been added
fig.tight_layout()
fig.savefig('test.png')

You can adjust the spacing around matplotlib figures using the subplots_adjust() function:
import matplotlib.pyplot as plt
plt.plot(whatever)
plt.subplots_adjust(left=0.1, right=0.9, top=0.9, bottom=0.1)
This will work for both the figure on screen and saved to a file, and it is the right function to call even if you don't have multiple plots on the one figure.
The numbers are fractions of the figure dimensions, and will need to be adjusted to allow for the figure labels.

All you need is
plt.tight_layout()
before your output.
In addition to cutting down the margins, this also tightly groups the space between any subplots:
x = [1,2,3]
y = [1,4,9]
import matplotlib.pyplot as plt
fig = plt.figure()
subplot1 = fig.add_subplot(121)
subplot1.plot(x,y)
subplot2 = fig.add_subplot(122)
subplot2.plot(y,x)
fig.tight_layout()
plt.show()

Sometimes, the plt.tight_layout() doesn't give me the best view or the view I want. Then why don't plot with arbitrary margin first and do fixing the margin after plot?
Since we got nice WYSIWYG from there.
import matplotlib.pyplot as plt
fig,ax = plt.subplots(figsize=(8,8))
plt.plot([2,5,7,8,5,3,5,7,])
plt.show()
Then paste settings into margin function to make it permanent:
fig,ax = plt.subplots(figsize=(8,8))
plt.plot([2,5,7,8,5,3,5,7,])
fig.subplots_adjust(
top=0.981,
bottom=0.049,
left=0.042,
right=0.981,
hspace=0.2,
wspace=0.2
)
plt.show()

In case anybody wonders how how to get rid of the rest of the white margin after applying plt.tight_layout() or fig.tight_layout(): With the parameter pad (which is 1.08 by default), you're able to make it even tighter:
"Padding between the figure edge and the edges of subplots, as a fraction of the font size."
So for example
plt.tight_layout(pad=0.05)
will reduce it to a very small margin. Putting 0 doesn't work for me, as it makes the box of the subplot be cut off a little, too.

Just use ax = fig.add_axes([left, bottom, width, height])
if you want exact control of the figure layout. eg.
left = 0.05
bottom = 0.05
width = 0.9
height = 0.9
ax = fig.add_axes([left, bottom, width, height])

plt.savefig("circle.png", bbox_inches='tight',pad_inches=-1)

inspired by Sammys answer above:
margins = { # vvv margin in inches
"left" : 1.5 / figsize[0],
"bottom" : 0.8 / figsize[1],
"right" : 1 - 0.3 / figsize[0],
"top" : 1 - 1 / figsize[1]
}
fig.subplots_adjust(**margins)
Where figsize is the tuple that you used in fig = pyplot.figure(figsize=...)

With recent matplotlib versions you might want to try Constrained Layout:
constrained_layout automatically adjusts subplots and decorations like
legends and colorbars so that they fit in the figure window while
still preserving, as best they can, the logical layout requested by
the user.
constrained_layout is similar to tight_layout, but uses a constraint
solver to determine the size of axes that allows them to fit.
constrained_layout needs to be activated before any axes are added to
a figure.
Too bad pandas does not handle it well...

The problem with matplotlibs subplots_adjust is that the values you enter are relative to the x and y figsize of the figure. This example is for correct figuresizing for printing of a pdf:
For that, I recalculate the relative spacing to absolute values like this:
pyplot.subplots_adjust(left = (5/25.4)/figure.xsize, bottom = (4/25.4)/figure.ysize, right = 1 - (1/25.4)/figure.xsize, top = 1 - (3/25.4)/figure.ysize)
for a figure of 'figure.xsize' inches in x-dimension and 'figure.ysize' inches in y-dimension. So the whole figure has a left margin of 5 mm, bottom margin of 4 mm, right of 1 mm and top of 3 mm within the labels are placed. The conversion of (x/25.4) is done because I needed to convert mm to inches.
Note that the pure chart size of x will be "figure.xsize - left margin - right margin" and the pure chart size of y will be "figure.ysize - bottom margin - top margin" in inches
Other sniplets (not sure about these ones, I just wanted to provide the other parameters)
pyplot.figure(figsize = figureSize, dpi = None)
and
pyplot.savefig("outputname.eps", dpi = 100)

For me, the answers above did not work with matplotlib.__version__ = 1.4.3 on Win7. So, if we are only interested in the image itself (i.e., if we don't need annotations, axis, ticks, title, ylabel etc), then it's better to simply save the numpy array as image instead of savefig.
from pylab import *
ax = subplot(111)
ax.imshow(some_image_numpyarray)
imsave('test.tif', some_image_numpyarray)
# or, if the image came from tiff or png etc
RGBbuffer = ax.get_images()[0].get_array()
imsave('test.tif', RGBbuffer)
Also, using opencv drawing functions (cv2.line, cv2.polylines), we can do some drawings directly on the numpy array. http://docs.opencv.org/2.4/modules/core/doc/drawing_functions.html

# import pyplot
import matplotlib.pyplot as plt
# your code to plot the figure
# set tight margins
plt.margins(0.015, tight=True)

Related

Add space around axes so x ticks don't get cut off in seaborn clustermap [duplicate]

I'm struggling to deal with my plot margins in matplotlib. I've used the code below to produce my chart:
plt.imshow(g)
c = plt.colorbar()
c.set_label("Number of Slabs")
plt.savefig("OutputToUse.png")
However, I get an output figure with lots of white space on either side of the plot. I've searched google and read the matplotlib documentation, but I can't seem to find how to reduce this.
One way to automatically do this is the bbox_inches='tight' kwarg to plt.savefig.
E.g.
import matplotlib.pyplot as plt
import numpy as np
data = np.arange(3000).reshape((100,30))
plt.imshow(data)
plt.savefig('test.png', bbox_inches='tight')
Another way is to use fig.tight_layout()
import matplotlib.pyplot as plt
import numpy as np
xs = np.linspace(0, 1, 20); ys = np.sin(xs)
fig = plt.figure()
axes = fig.add_subplot(1,1,1)
axes.plot(xs, ys)
# This should be called after all axes have been added
fig.tight_layout()
fig.savefig('test.png')
You can adjust the spacing around matplotlib figures using the subplots_adjust() function:
import matplotlib.pyplot as plt
plt.plot(whatever)
plt.subplots_adjust(left=0.1, right=0.9, top=0.9, bottom=0.1)
This will work for both the figure on screen and saved to a file, and it is the right function to call even if you don't have multiple plots on the one figure.
The numbers are fractions of the figure dimensions, and will need to be adjusted to allow for the figure labels.
All you need is
plt.tight_layout()
before your output.
In addition to cutting down the margins, this also tightly groups the space between any subplots:
x = [1,2,3]
y = [1,4,9]
import matplotlib.pyplot as plt
fig = plt.figure()
subplot1 = fig.add_subplot(121)
subplot1.plot(x,y)
subplot2 = fig.add_subplot(122)
subplot2.plot(y,x)
fig.tight_layout()
plt.show()
Sometimes, the plt.tight_layout() doesn't give me the best view or the view I want. Then why don't plot with arbitrary margin first and do fixing the margin after plot?
Since we got nice WYSIWYG from there.
import matplotlib.pyplot as plt
fig,ax = plt.subplots(figsize=(8,8))
plt.plot([2,5,7,8,5,3,5,7,])
plt.show()
Then paste settings into margin function to make it permanent:
fig,ax = plt.subplots(figsize=(8,8))
plt.plot([2,5,7,8,5,3,5,7,])
fig.subplots_adjust(
top=0.981,
bottom=0.049,
left=0.042,
right=0.981,
hspace=0.2,
wspace=0.2
)
plt.show()
In case anybody wonders how how to get rid of the rest of the white margin after applying plt.tight_layout() or fig.tight_layout(): With the parameter pad (which is 1.08 by default), you're able to make it even tighter:
"Padding between the figure edge and the edges of subplots, as a fraction of the font size."
So for example
plt.tight_layout(pad=0.05)
will reduce it to a very small margin. Putting 0 doesn't work for me, as it makes the box of the subplot be cut off a little, too.
Just use ax = fig.add_axes([left, bottom, width, height])
if you want exact control of the figure layout. eg.
left = 0.05
bottom = 0.05
width = 0.9
height = 0.9
ax = fig.add_axes([left, bottom, width, height])
plt.savefig("circle.png", bbox_inches='tight',pad_inches=-1)
inspired by Sammys answer above:
margins = { # vvv margin in inches
"left" : 1.5 / figsize[0],
"bottom" : 0.8 / figsize[1],
"right" : 1 - 0.3 / figsize[0],
"top" : 1 - 1 / figsize[1]
}
fig.subplots_adjust(**margins)
Where figsize is the tuple that you used in fig = pyplot.figure(figsize=...)
With recent matplotlib versions you might want to try Constrained Layout:
constrained_layout automatically adjusts subplots and decorations like
legends and colorbars so that they fit in the figure window while
still preserving, as best they can, the logical layout requested by
the user.
constrained_layout is similar to tight_layout, but uses a constraint
solver to determine the size of axes that allows them to fit.
constrained_layout needs to be activated before any axes are added to
a figure.
Too bad pandas does not handle it well...
The problem with matplotlibs subplots_adjust is that the values you enter are relative to the x and y figsize of the figure. This example is for correct figuresizing for printing of a pdf:
For that, I recalculate the relative spacing to absolute values like this:
pyplot.subplots_adjust(left = (5/25.4)/figure.xsize, bottom = (4/25.4)/figure.ysize, right = 1 - (1/25.4)/figure.xsize, top = 1 - (3/25.4)/figure.ysize)
for a figure of 'figure.xsize' inches in x-dimension and 'figure.ysize' inches in y-dimension. So the whole figure has a left margin of 5 mm, bottom margin of 4 mm, right of 1 mm and top of 3 mm within the labels are placed. The conversion of (x/25.4) is done because I needed to convert mm to inches.
Note that the pure chart size of x will be "figure.xsize - left margin - right margin" and the pure chart size of y will be "figure.ysize - bottom margin - top margin" in inches
Other sniplets (not sure about these ones, I just wanted to provide the other parameters)
pyplot.figure(figsize = figureSize, dpi = None)
and
pyplot.savefig("outputname.eps", dpi = 100)
For me, the answers above did not work with matplotlib.__version__ = 1.4.3 on Win7. So, if we are only interested in the image itself (i.e., if we don't need annotations, axis, ticks, title, ylabel etc), then it's better to simply save the numpy array as image instead of savefig.
from pylab import *
ax = subplot(111)
ax.imshow(some_image_numpyarray)
imsave('test.tif', some_image_numpyarray)
# or, if the image came from tiff or png etc
RGBbuffer = ax.get_images()[0].get_array()
imsave('test.tif', RGBbuffer)
Also, using opencv drawing functions (cv2.line, cv2.polylines), we can do some drawings directly on the numpy array. http://docs.opencv.org/2.4/modules/core/doc/drawing_functions.html
# import pyplot
import matplotlib.pyplot as plt
# your code to plot the figure
# set tight margins
plt.margins(0.015, tight=True)

How to create python imshow subplots with same pixel size

I'm trying to create imshow subplots with the same pixel size without having the figure height automatically scaled, but I haven't been able to figure out how.
Ideally, I'm looking for a plot similar to the second picture, without the extra white space (ylim going from -0.5 to 4.5) and maybe centered vertically. My pictures will always have the same width, so maybe if I could fix the subplot width instead of the height that would help. Does anyone have any ideas?
close('all')
f,ax=subplots(1,2)
ax[0].imshow(random.rand(30,4),interpolation='nearest')
ax[1].imshow(random.rand(4,4),interpolation='nearest')
tight_layout()
f,ax=subplots(1,2)
ax[0].imshow(random.rand(30,4),interpolation='nearest')
ax[1].imshow(random.rand(4,4),interpolation='nearest')
ax[1].set_ylim((29.5,-0.5))
tight_layout()
Plot without ylim adjustment:
Plot with ylim adjustment:
In principle you can just make the figure size small enough in width, such that it constrains the widths of the subplots. E.g. figsize=(2,7) would work here.
For an automated solution, you may adjust the subplot parameters, such that the left and right margin constrain the subplot width. This is shown in the code below.
It assumes that there is one row of subplots, and that all images have the same pixel number in horizontal direction.
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots(1,2)
im1 = ax[0].imshow(np.random.rand(30,4))
im2 = ax[1].imshow(np.random.rand(4,4))
def adjustw(images, wspace="auto"):
fig = images[0].axes.figure
if wspace=="auto":
wspace = fig.subplotpars.wspace
top = fig.subplotpars.top
bottom = fig.subplotpars.bottom
shapes = np.array([im.get_array().shape for im in images])
w,h = fig.get_size_inches()
imw = (top-bottom)*h/shapes[:,0].max()*shapes[0,1] #inch
n = len(shapes)
left = -((n+(n-1)*wspace)*imw/w - 1)/2.
right = 1.-left
fig.subplots_adjust(left=left, right=right, wspace=wspace)
adjustw([im1, im2], wspace=1)
plt.show()
If you need to use tight_layout(), do so before calling the function. Also you would then definitely need to set the only free parameter here, wspace to something other than "auto". wspace=1 means to have as much space between the plots as their width.
The result is a figure where the subplots have the same size in width.

Avoid overlapping ticks in matplotlib

I am generating plots like this one:
When using less ticks, the plot fits nicely and the bars are wide enough to see them correctly. Nevertheless, when there are lots of ticks, instead of making the plot larger, it just compress the y axe, resulting in thin bars and overlapping tick text.
This is happening both for plt.show() and plt.save_fig().
Is there any solution so it plots the figure in a scale which guarantees that bars have the specified width, not more (if too few ticks) and not less (too many, overlapping)?
EDIT:
Yes, I'm using barh, and yes, I'm setting height to a fixed value (8):
height = 8
ax.barh(yvalues-width/2, xvalues, height=height, color='blue', align='center')
ax.barh(yvalues+width/2, xvalues, height=height, color='red', align='center')
I don't quite understand your code, it seems you do two plots with the same (only shifted) yvalues, but the image doesn't look so. And are you sure you want to shift by width/2 if you have align=center? Anyways, to changing the image size:
No, I am not sure there is no other way, but I don't see anything in the manual at a glance. To set image size by hand:
fig = plt.figure(figsize=(5, 80))
ax = fig.add_subplot(111)
...your_code
the size is in cm. You can compute it beforehand, try for example
import numpy as np
fig_height = (max(yvalues) - min(yvalues)) / np.diff(yvalue)
this would (approximately) set the minimum distance between ticks to a centimeter, which is too much, but try to adjust it.
I think of two solutions for your case:
If you are trying to plot a histogram, use hist function [1]. This will automatically bin your data. You can even plot multiple overlapping histograms as long as you set alpha value lower than 1. See this post
import matplotlib.pyplot as plt
import numpy as np
x = mu + sigma*np.random.randn(10000)
plt.hist(x, 50, normed=1, facecolor='green',
alpha=0.75, orientation='horizontal')
You can also identify interval of your axis ticks. This will place a tick every 10 items. But I doubt this will solve your problem.
import matplotlib.ticker as ticker
...
ax.yaxis.set_major_locator(ticker.MultipleLocator(10))

Matplotlib adjust figure margin

The following code gives me a plot with significant margins above and below the figure. I don't know how to eliminate the noticeable margins. subplots_adjust does not work as expected.
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(range(10),range(10))
ax.set_aspect('equal')
plt.tight_layout()
tight_layout eliminates some of the margin, but not all of the margins.
What I wanted is actually setting the aspect ratio to any customized value and eliminating the white space at the same time.
Update: as Pierre H. puts it, the key is to change the size of the figure container. So my question is: Could you suggest a way to accommodate the size of the figure to the size of the axes with arbitrary aspect ratio?
In other words, first I create a figure and an axes on it, and then I change the size of the axes (by changing aspect ratio for example), which in general will leave a portion of the figure container empty. At this stage, we need to change the size of the figure accordingly to eliminate the blank space on the figure container.
I just discovered how to eliminate all margins from my figures. I didn't use tight_layout(), instead I used:
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(20,20))
ax = plt.subplot(111,aspect = 'equal')
plt.subplots_adjust(left=0, bottom=0, right=1, top=1, wspace=0, hspace=0)
Hope this helps.
After plotting your chart you can easily manipulate margins this way:
plot_margin = 0.25
x0, x1, y0, y1 = plt.axis()
plt.axis((x0 - plot_margin,
x1 + plot_margin,
y0 - plot_margin,
y1 + plot_margin))
This example could be changed to the aspect ratio you want or change the margins as you really want.
In other stacktoverflow posts many questions related to margins could make use of this simpler approach.
Best regards.
tight_layout(pad=0) will meet your need.
http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.tight_layout
I think what you need is, and it works well for me.
plt.axis('tight')
This command will automatically scale the axis to fit tightly to the data. Also check the answer of Nuno Aniceto for a customized axis. The documents are in https://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.axis.
Be aware that
plt.savefig(filename, bbox_inches='tight')
will help remove white space of all the figure including labels, etc, but not the white space inside the axes.
You should use add_axes if you want exact control of the figure layout. eg.
left = 0.05
bottom = 0.05
width = 0.9
height = 0.9
ax = fig.add_axes([left, bottom, width, height])
I think the subplot_adjust call is irrelevant here since the adjustment is overridden by tight_layout. Anyway, this only change the size of the axes inside the figure.
As tcaswell pointed it, you need to change the size of the figure. Either at creation (my proposition below) or after, using fig.set_size_inches. I'm here creating a figure with a 1:1 aspect ratio using the figsize=(6,6) argument (of course 6 inches is an arbitrary choice):
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure(figsize=(6,6))
ax = fig.add_subplot(111)
ax.plot(range(10),range(10))
ax.set_aspect('equal')
plt.tight_layout()
You can use like:
plt.subplots_adjust(wspace=1,hspace=0.5,left=0.1,top=0.9,right=0.9,bottom=0.1)
And delete the item bbox_inches='tight' in plt.savefig().

How can I set the aspect ratio in matplotlib?

I'm trying to make a square plot (using imshow), i.e. aspect ratio of 1:1, but I can't. None of these work:
import matplotlib.pyplot as plt
ax = fig.add_subplot(111,aspect='equal')
ax = fig.add_subplot(111,aspect=1.0)
ax.set_aspect('equal')
plt.axes().set_aspect('equal')
It seems like the calls are just being ignored (a problem I often seem to have with matplotlib).
Third times the charm. My guess is that this is a bug and Zhenya's answer suggests it's fixed in the latest version. I have version 0.99.1.1 and I've created the following solution:
import matplotlib.pyplot as plt
import numpy as np
def forceAspect(ax,aspect=1):
im = ax.get_images()
extent = im[0].get_extent()
ax.set_aspect(abs((extent[1]-extent[0])/(extent[3]-extent[2]))/aspect)
data = np.random.rand(10,20)
fig = plt.figure()
ax = fig.add_subplot(111)
ax.imshow(data)
ax.set_xlabel('xlabel')
ax.set_aspect(2)
fig.savefig('equal.png')
ax.set_aspect('auto')
fig.savefig('auto.png')
forceAspect(ax,aspect=1)
fig.savefig('force.png')
This is 'force.png':
Below are my unsuccessful, yet hopefully informative attempts.
Second Answer:
My 'original answer' below is overkill, as it does something similar to axes.set_aspect(). I think you want to use axes.set_aspect('auto'). I don't understand why this is the case, but it produces a square image plot for me, for example this script:
import matplotlib.pyplot as plt
import numpy as np
data = np.random.rand(10,20)
fig = plt.figure()
ax = fig.add_subplot(111)
ax.imshow(data)
ax.set_aspect('equal')
fig.savefig('equal.png')
ax.set_aspect('auto')
fig.savefig('auto.png')
Produces an image plot with 'equal' aspect ratio:
and one with 'auto' aspect ratio:
The code provided below in the 'original answer' provides a starting off point for an explicitly controlled aspect ratio, but it seems to be ignored once an imshow is called.
Original Answer:
Here's an example of a routine that will adjust the subplot parameters so that you get the desired aspect ratio:
import matplotlib.pyplot as plt
def adjustFigAspect(fig,aspect=1):
'''
Adjust the subplot parameters so that the figure has the correct
aspect ratio.
'''
xsize,ysize = fig.get_size_inches()
minsize = min(xsize,ysize)
xlim = .4*minsize/xsize
ylim = .4*minsize/ysize
if aspect < 1:
xlim *= aspect
else:
ylim /= aspect
fig.subplots_adjust(left=.5-xlim,
right=.5+xlim,
bottom=.5-ylim,
top=.5+ylim)
fig = plt.figure()
adjustFigAspect(fig,aspect=.5)
ax = fig.add_subplot(111)
ax.plot(range(10),range(10))
fig.savefig('axAspect.png')
This produces a figure like so:
I can imagine if your having multiple subplots within the figure, you would want to include the number of y and x subplots as keyword parameters (defaulting to 1 each) to the routine provided. Then using those numbers and the hspace and wspace keywords, you can make all the subplots have the correct aspect ratio.
A simple option using plt.gca() to get current axes and set aspect
plt.gca().set_aspect('equal')
in place of your last line
What is the matplotlib version you are running? I have recently had to upgrade to 1.1.0, and with it, add_subplot(111,aspect='equal') works for me.
After many years of success with the answers above, I have found this not to work again - but I did find a working solution for subplots at
https://jdhao.github.io/2017/06/03/change-aspect-ratio-in-mpl
With full credit of course to the author above (who can perhaps rather post here), the relevant lines are:
ratio = 1.0
xleft, xright = ax.get_xlim()
ybottom, ytop = ax.get_ylim()
ax.set_aspect(abs((xright-xleft)/(ybottom-ytop))*ratio)
The link also has a crystal clear explanation of the different coordinate systems used by matplotlib.
Thanks for all great answers received - especially #Yann's which will remain the winner.
you should try with figaspect. It works for me. From the docs:
Create a figure with specified aspect ratio. If arg is a number, use that aspect ratio. > If arg is an array, figaspect will
determine the width and height for a figure that would fit array
preserving aspect ratio. The figure width, height in inches are
returned. Be sure to create an axes with equal with and height, eg
Example usage:
# make a figure twice as tall as it is wide
w, h = figaspect(2.)
fig = Figure(figsize=(w,h))
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])
ax.imshow(A, **kwargs)
# make a figure with the proper aspect for an array
A = rand(5,3)
w, h = figaspect(A)
fig = Figure(figsize=(w,h))
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])
ax.imshow(A, **kwargs)
Edit: I am not sure of what you are looking for. The above code changes the canvas (the plot size). If you want to change the size of the matplotlib window, of the figure, then use:
In [68]: f = figure(figsize=(5,1))
this does produce a window of 5x1 (wxh).
This answer is based on Yann's answer. It will set the aspect ratio for linear or log-log plots. I've used additional information from https://stackoverflow.com/a/16290035/2966723 to test if the axes are log-scale.
def forceAspect(ax,aspect=1):
#aspect is width/height
scale_str = ax.get_yaxis().get_scale()
xmin,xmax = ax.get_xlim()
ymin,ymax = ax.get_ylim()
if scale_str=='linear':
asp = abs((xmax-xmin)/(ymax-ymin))/aspect
elif scale_str=='log':
asp = abs((scipy.log(xmax)-scipy.log(xmin))/(scipy.log(ymax)-scipy.log(ymin)))/aspect
ax.set_aspect(asp)
Obviously you can use any version of log you want, I've used scipy, but numpy or math should be fine.
In my case, the following setting works best:
plt.figure(figsize=(16,9))
where (16,9) is your plot aspect ratio.

Categories

Resources