Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting the size of the plotting canvas in Matplotlib

Tags:

I would like Matplotlib/Pyplot to generate plots with a consistent canvas size. That is, the figures can well have different sizes to accomodate the axis descriptions, but the plotting area (the rectangle within which the curves are drawn) should always have the same size.

Is there a simple way to achieve that? The option figsize of pyplot.figure() seems to set the overall size of the figure, not that of the canvas, so I get a different canvas size whenever the axis description occupies more or less space.

like image 751
Dario Avatar asked Apr 17 '13 10:04

Dario


People also ask

Which function is used to change the size of the plot in Matplotlib?

figsize() takes two parameters- width and height (in inches). By default the values for width and height are 6.4 and 4.8 respectively. Where, x and y are width and height respectively in inches.

What is the default size in Matplotlib?

If not provided, defaults to rcParams["figure. figsize"] (default: [6.4, 4.8]) = [6.4, 4.8] . dpiinteger, optional, default: None.


2 Answers

This is one of my biggest frustrations with Matplotlib. I often work with raster data where for example i want to add a colormap, legend and some title. Any simple example from the matplotlib gallery doing so will result in a different resolution and therefore resampled data. Especially when doing image analysis you dont want any (unwanted) resampling.

Here is what i usually do, although i would love to know if there are simpler or better ways.

Lets start with loading a picture and outputting it just as it is with the same resolution:

import matplotlib.pyplot as plt
import urllib2

# load the image
img = plt.imread(urllib2.urlopen('http://upload.wikimedia.org/wikipedia/en/thumb/5/56/Matplotlib_logo.svg/500px-Matplotlib_logo.svg.png'))

# get the dimensions
ypixels, xpixels, bands = img.shape

# get the size in inches
dpi = 72.
xinch = xpixels / dpi
yinch = ypixels / dpi

# plot and save in the same size as the original
fig = plt.figure(figsize=(xinch,yinch))

ax = plt.axes([0., 0., 1., 1.], frameon=False, xticks=[],yticks=[])
ax.imshow(img, interpolation='none')

plt.savefig('D:\\mpl_logo.png', dpi=dpi, transparent=True)

Note that i manually defined the axes position so that spans the entire figure.

In a similar way as above you could add some margin around the image to allow for labels or colorbars etc.

This example adds a 20% margin above the image, which is then used for plotting a title:

fig = plt.figure(figsize=(xinch,yinch/.8))

ax = plt.axes([0., 0., 1., .8], frameon=False, xticks=[],yticks=[])
ax.imshow(img, interpolation='none')
ax.set_title('Matplotlib is fun!', size=16, weight='bold')

plt.savefig('D:\\mpl_logo_with_title.png', dpi=dpi)

So the figure y-size (height) is increased and the y-size of the axes is decreased equally. This gives a larger (overall) output image, but the axes area will still be the same size.

It might be nice the have a figure or axes property like .set_scale() to force a true 1-on-x output.

like image 153
Rutger Kassies Avatar answered Sep 22 '22 08:09

Rutger Kassies


You can specify the following settings in Matplotlib rc:

import matplotlib
matplotlib.rcParams['figure.figsize'] = [10, 10] # for square canvas
matplotlib.rcParams['figure.subplot.left'] = 0
matplotlib.rcParams['figure.subplot.bottom'] = 0
matplotlib.rcParams['figure.subplot.right'] = 1
matplotlib.rcParams['figure.subplot.top'] = 1
like image 28
Piotr Jurkiewicz Avatar answered Sep 18 '22 08:09

Piotr Jurkiewicz