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.
Related
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)
I am trying to plot an image (using matplotlib.imshow) and a scatter plot within the same figure. When trying this, the image appears smaller than the scatter plot. Small example code is shown below:
import matplotlib.pyplot as plt
import numpy as np
image = np.random.randint(100,200,(200,200))
x = np.arange(0,10,0.1)
y = np.sin(x)
fig, (ax1, ax2) = plt.subplots(1,2)
ax1.imshow(image)
ax2.scatter(x,y)
plt.show()
Which gives the following figure:
How can I get the two sublpots to have the same height? (and width I suppose)
I have tried using gridspec as shown in this answer:
fig=plt.figure()
gs=GridSpec(1,2)
ax1=fig.add_subplot(gs[0,0])
ax2=fig.add_subplot(gs[0,1])
ax1.imshow(image)
ax2.scatter(x,y)
But this gives the same result. I have also tried to adjust the subplot sizes manually by using:
fig = plt.figure()
ax1 = plt.axes([0.05,0.05,0.45,0.9])
ax2 = plt.axes([0.55,0.19,0.45,0.62])
ax1.imshow(image)
ax2.scatter(x,y)
By trial and error I can get the two subplots to the correct size, though any change in the overall figure size will mean that the subplots will no longer be the same size.
Is there a way to make imshow and a scatter plot appear the same size in a figure without manually changing the axes sizes?
I am using Python 2.7 and matplotlib 2.0.0
It's not perfectly clear what your desired outcome is.
You may use automatic aspect on the image
ax.imshow(z, aspect="auto")
Or you may set the aspect of the line plot depending on its axis limits such that it gets the same size as the image (in case the image has equal x and y sizes)
asp = np.diff(ax2.get_xlim())[0] / np.diff(ax2.get_ylim())[0]
ax2.set_aspect(asp)
Complete code:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0,10,20)
y = np.sin(x)
z = np.random.rand(100,100)
fig, (ax, ax2) = plt.subplots(ncols=2)
ax.imshow(z)
ax2.plot(x,y, marker=".")
asp = np.diff(ax2.get_xlim())[0] / np.diff(ax2.get_ylim())[0]
ax2.set_aspect(asp)
plt.show()
If the image does not have equal limits (is not square), one still needs to divide by the aspect of the image:
asp = np.diff(ax2.get_xlim())[0] / np.diff(ax2.get_ylim())[0]
asp /= np.abs(np.diff(ax1.get_xlim())[0] / np.diff(ax1.get_ylim())[0])
ax2.set_aspect(asp)
More sophisticated solutions:
This answer for using the subplot parameters to achieve a certain aspect.
If you want to use mpl_toolkits and make your hands dirty, this answer would be a good read.
I had the same problem and asked a very similar question in SO. The solution proposed by #ImportanceOfBeingErnest worked like a charm for me, but for completeness, I'd like to mention a pretty simple workaround I was suggested to apply (credit to #Yilun Zhang) before my question was marked as an exact duplicate of this one:
The problem is that the plot region height is too large and this is leaving empty place in the image.
If you change your code to:
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6))
then you get the desired outcome:
Here's some code I use:
fig, axis_array = plt.subplots(1, 2, figsize=(chosen_value, 1.05 * chosen_value / 2),
subplot_kw={'aspect': 1})
I'm explicitly selecting that there will be 2 sub plots in my figure, and that the figure will be chosen_value tall and each subplot will be about half that size wide, and that the subplots will have an aspect ratio of 1 (i.e., they will both be square). The figure size is a specific ratio which forces the spacing.
For those sharing the y-axis across both plots, setting constrained_layout to True may help.
I am trying to plot an image (using matplotlib.imshow) and a scatter plot within the same figure. When trying this, the image appears smaller than the scatter plot. Small example code is shown below:
import matplotlib.pyplot as plt
import numpy as np
image = np.random.randint(100,200,(200,200))
x = np.arange(0,10,0.1)
y = np.sin(x)
fig, (ax1, ax2) = plt.subplots(1,2)
ax1.imshow(image)
ax2.scatter(x,y)
plt.show()
Which gives the following figure:
How can I get the two sublpots to have the same height? (and width I suppose)
I have tried using gridspec as shown in this answer:
fig=plt.figure()
gs=GridSpec(1,2)
ax1=fig.add_subplot(gs[0,0])
ax2=fig.add_subplot(gs[0,1])
ax1.imshow(image)
ax2.scatter(x,y)
But this gives the same result. I have also tried to adjust the subplot sizes manually by using:
fig = plt.figure()
ax1 = plt.axes([0.05,0.05,0.45,0.9])
ax2 = plt.axes([0.55,0.19,0.45,0.62])
ax1.imshow(image)
ax2.scatter(x,y)
By trial and error I can get the two subplots to the correct size, though any change in the overall figure size will mean that the subplots will no longer be the same size.
Is there a way to make imshow and a scatter plot appear the same size in a figure without manually changing the axes sizes?
I am using Python 2.7 and matplotlib 2.0.0
It's not perfectly clear what your desired outcome is.
You may use automatic aspect on the image
ax.imshow(z, aspect="auto")
Or you may set the aspect of the line plot depending on its axis limits such that it gets the same size as the image (in case the image has equal x and y sizes)
asp = np.diff(ax2.get_xlim())[0] / np.diff(ax2.get_ylim())[0]
ax2.set_aspect(asp)
Complete code:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0,10,20)
y = np.sin(x)
z = np.random.rand(100,100)
fig, (ax, ax2) = plt.subplots(ncols=2)
ax.imshow(z)
ax2.plot(x,y, marker=".")
asp = np.diff(ax2.get_xlim())[0] / np.diff(ax2.get_ylim())[0]
ax2.set_aspect(asp)
plt.show()
If the image does not have equal limits (is not square), one still needs to divide by the aspect of the image:
asp = np.diff(ax2.get_xlim())[0] / np.diff(ax2.get_ylim())[0]
asp /= np.abs(np.diff(ax1.get_xlim())[0] / np.diff(ax1.get_ylim())[0])
ax2.set_aspect(asp)
More sophisticated solutions:
This answer for using the subplot parameters to achieve a certain aspect.
If you want to use mpl_toolkits and make your hands dirty, this answer would be a good read.
I had the same problem and asked a very similar question in SO. The solution proposed by #ImportanceOfBeingErnest worked like a charm for me, but for completeness, I'd like to mention a pretty simple workaround I was suggested to apply (credit to #Yilun Zhang) before my question was marked as an exact duplicate of this one:
The problem is that the plot region height is too large and this is leaving empty place in the image.
If you change your code to:
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6))
then you get the desired outcome:
Here's some code I use:
fig, axis_array = plt.subplots(1, 2, figsize=(chosen_value, 1.05 * chosen_value / 2),
subplot_kw={'aspect': 1})
I'm explicitly selecting that there will be 2 sub plots in my figure, and that the figure will be chosen_value tall and each subplot will be about half that size wide, and that the subplots will have an aspect ratio of 1 (i.e., they will both be square). The figure size is a specific ratio which forces the spacing.
For those sharing the y-axis across both plots, setting constrained_layout to True may help.
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().
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)