72

I am using pylab in matplotlib to create a plot and save the plot to an image file. However, when I save the image using pylab.savefig( image_name ), I find that the SIZE image saved is the same as the image that is shown when I use pylab.show().

As it happens, I have a lot of data in the plot and when I am using pylab.show(), I have to maximize the window before I can see all of the plot correctly, and the xlabel tickers don't superimpose on each other.

Is there anyway that I can programmatically 'maximize' the window before saving the image to file? - at the moment, I am only getting the 'default' window size image, which results in the x axis labels being superimposed on one another.

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
Homunculus Reticulli
  • 65,167
  • 81
  • 216
  • 341

9 Answers9

66

There are two major options in matplotlib (pylab) to control the image size:

  1. You can set the size of the resulting image in inches
  2. You can define the DPI (dots per inch) for output file (basically, it is a resolution)

Normally, you would like to do both, because this way you will have full control over the resulting image size in pixels. For example, if you want to render exactly 800x600 image, you can use DPI=100, and set the size as 8 x 6 in inches:

import matplotlib.pyplot as plt
# plot whatever you need...
# now, before saving to file:
figure = plt.gcf() # get current figure
figure.set_size_inches(8, 6)
# when saving, specify the DPI
plt.savefig("myplot.png", dpi = 100)

One can use any DPI. In fact, you might want to play with various DPI and size values to get the result you like the most. Beware, however, that using very small DPI is not a good idea, because matplotlib may not find a good font to render legend and other text. For example, you cannot set the DPI=1, because there are no fonts with characters rendered with 1 pixel :)

From other comments I understood that other issue you have is proper text rendering. For this, you can also change the font size. For example, you may use 6 pixels per character, instead of 12 pixels per character used by default (effectively, making all text twice smaller).

import matplotlib
#...
matplotlib.rc('font', size=6)

Finally, some references to the original documentation: http://matplotlib.sourceforge.net/api/pyplot_api.html#matplotlib.pyplot.savefig, http://matplotlib.sourceforge.net/api/pyplot_api.html#matplotlib.pyplot.gcf, http://matplotlib.sourceforge.net/api/figure_api.html#matplotlib.figure.Figure.set_size_inches, http://matplotlib.sourceforge.net/users/customizing.html#dynamic-rc-settings

P.S. Sorry, I didn't use pylab, but as far as I'm aware, all the code above will work same way in pylab - just replace plt in my code with the pylab (or whatever name you assigned when importing pylab). Same for matplotlib - use pylab instead.

Tim
  • 12,318
  • 7
  • 50
  • 72
  • just tried to use this. Something still reduces my pixels. I have a stacked numpy image array of 800 x 4000 pixel and i want to save it without any loss, so that my saved image as exactly 800x4000 pixel. Used figure(figsize=(8,40)) and savefig(fname, dpi=100) and received 576x2880 pixel PDF? – K.-Michael Aye Oct 02 '12 at 02:50
  • i just confirmed that this is an issue of the PDF engine. A png comes out correctly. – K.-Michael Aye Oct 02 '12 at 03:02
32

You set the size on initialization:

fig2 = matplotlib.pyplot.figure(figsize=(8.0, 5.0)) # in inches!

Edit:

If the problem is with x-axis ticks - You can set them "manually":

fig2.add_subplot(111).set_xticks(arange(1,3,0.5)) # You can actually compute the interval You need - and substitute here

And so on with other aspects of Your plot. You can configure it all. Here's an example:

from numpy import arange
import matplotlib
# import matplotlib as mpl
import matplotlib.pyplot
# import matplotlib.pyplot as plt

x1 = [1,2,3]
y1 = [4,5,6]
x2 = [1,2,3]
y2 = [5,5,5]

# initialization
fig2 = matplotlib.pyplot.figure(figsize=(8.0, 5.0)) # The size of the figure is specified as (width, height) in inches

# lines:
l1 = fig2.add_subplot(111).plot(x1,y1, label=r"Text $formula$", "r-", lw=2)
l2 = fig2.add_subplot(111).plot(x2,y2, label=r"$legend2$" ,"g--", lw=3)
fig2.add_subplot(111).legend((l1,l2), loc=0)

# axes:
fig2.add_subplot(111).grid(True)
fig2.add_subplot(111).set_xticks(arange(1,3,0.5))
fig2.add_subplot(111).axis(xmin=3, xmax=6) # there're also ymin, ymax
fig2.add_subplot(111).axis([0,4,3,6]) # all!
fig2.add_subplot(111).set_xlim([0,4])
fig2.add_subplot(111).set_ylim([3,6])

# labels:
fig2.add_subplot(111).set_xlabel(r"x $2^2$", fontsize=15, color = "r")
fig2.add_subplot(111).set_ylabel(r"y $2^2$")
fig2.add_subplot(111).set_title(r"title $6^4$")
fig2.add_subplot(111).text(2, 5.5, r"an equation: $E=mc^2$", fontsize=15, color = "y")
fig2.add_subplot(111).text(3, 2, unicode('f\374r', 'latin-1'))

# saving:
fig2.savefig("fig2.png")

So - what exactly do You want to be configured?

Adobe
  • 12,967
  • 10
  • 85
  • 126
  • 4
    Thanks for the prompt response. However, this does not solve the problem. The image saved to file is the image that is displayed when one calls `pylab.show()`. For the data I am plotting, I need to (manually) maximize the window in order to provide enough spacing between the labels. It almost seems that behind the scene, `pylab.savefig()` is doing a `pylab.show()`, then taking a screen capture of the **DEFAULT** size window and saving that to file. I need to save the image displayed when the window is **MAXIMIZED** – Homunculus Reticulli Apr 06 '12 at 10:07
  • Why don't You customize it all the non-GUI way? I never heard that it is possible to make python aware of You've done in pylab.show(). – Adobe Apr 06 '12 at 10:27
  • I'm not sure I understand your last comment. What I meant (in case you misunderstood my comment), is that the solution you suggested, still results in an image being saved to disk which still has all the X axis labels 'crumpled together' and ineligible. I was merely pointing out that the image saved to file is EXACTLY the same as that created when `pylab.show()` is invoked. It is only when I maximize the GUI window, that I can read all the X axis labels correctly. In my script, I am generating hundreds of images, so it is not practical for me to manually maximize each window and save. – Homunculus Reticulli Apr 06 '12 at 10:46
  • 5
    Continued ... I am merely trying to find a way to 'programatically' maximize the 'window'/canvas (or at least specify a specific size) before the image is saved to file. – Homunculus Reticulli Apr 06 '12 at 10:48
  • +1, this is the way to do it (set `figsize`). The answer was given 5 minutes after the question. no bounty necessary. – bmu Apr 19 '12 at 20:55
  • 5
    The answer doesnt actually answer the question. It may solve the questioner's problem, but the question is clearly how to save the maximized figure - and that is not anyway clear from this answer. – ImportanceOfBeingErnest Aug 24 '17 at 16:58
  • 2
    @HomunculusReticulli did you managed to find a way for that? I have the same issue and all the solution suggested didnt solve the saving problem at all. – SacreD Sep 04 '17 at 15:23
  • @SacreD I asked this question a few years ago; I don't think I got the answer I was after, judging by my comments. Sorry I can't be of more help – Homunculus Reticulli Sep 04 '17 at 16:34
12

I think you need to specify a different resolution when saving the figure to a file:

fig = matplotlib.pyplot.figure()
# generate your plot
fig.savefig("myfig.png",dpi=600)

Specifying a large dpi value should have a similar effect as maximizing the GUI window.

silvado
  • 17,202
  • 2
  • 30
  • 46
  • 1
    Actually the effect is quite different. Increasing the DPI only increase the resolution of the image, while changing the size of the figure changes the spacing between subplots, titles...etc without changing the font size. So you need to set the figure size first to get the right font size, then to set the DPI to get the desired resolution. – milembar Mar 19 '21 at 20:57
4

Check this: How to maximize a plt.show() window using Python

The command is different depending on which backend you use. I find that this is the best way to make sure the saved pictures have the same scaling as what I view on my screen.

Since I use Canopy with the QT backend:

pylab.get_current_fig_manager().window.showMaximized()

I then call savefig() as required with an increased DPI per silvado's answer.

Community
  • 1
  • 1
Maximus
  • 1,244
  • 10
  • 12
3

You can look in a saved figure it's size, like 1920x983 px (size when i saved a maximized window), then I set the dpi as 100 and the size as 19.20x9.83 and it worked fine. Saved exactly equal to the maximized figure.

import numpy as np
import matplotlib.pyplot as plt
x, y = np.genfromtxt('fname.dat', usecols=(0,1), unpack=True)
a = plt.figure(figsize=(19.20,9.83))
a = plt.plot(x, y, '-')
plt.savefig('file.png',format='png',dpi=100)
Dom_Aron
  • 31
  • 1
3

I had this exact problem and this worked:

plt.savefig(output_dir + '/xyz.png', bbox_inches='tight')

Here is the documentation:

[https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.savefig.html][1]

RestitutorOrbis
  • 189
  • 1
  • 2
  • 13
2

Old question but to anyone in need, Here's what had worked for me a while ago:

You have to have a general idea of the aspect ratio that would maximise your plot fitting. This will take some trial and error to get right, but generally 1920x1080 would be a good aspect ratio for most modern monitors. I would still suggest playing around with the aspect ratios to best suit your plot.

Steps:

  1. Before initiating the plot, set the size for the plot, use:
 plt.figure(19.20, 10.80)

**notice how I have multiplied my aspect ratio by '0.01'.

  1. At the end of the plot, when using plt.savefig, save it as follows:
plt.savefig('name.jpg', bbox_inches='tight', dpi=1000)
lemon
  • 14,875
  • 6
  • 18
  • 38
New_Noob
  • 21
  • 2
1

I did the same search time ago, it seems that he exact solution depends on the backend.

I have read a bunch of sources and probably the most useful was the answer by Pythonio here How to maximize a plt.show() window using Python I adjusted the code and ended up with the function below. It works decently for me on windows, I mostly use Qt, where I use it quite often, while it is minimally tested with other backends.

Basically it consists in identifying the backend and calling the appropriate function. Note that I added a pause afterwards because I was having issues with some windows getting maximized and others not, it seems this solved for me.

def maximize(backend=None,fullscreen=False):
    """Maximize window independently on backend.
    Fullscreen sets fullscreen mode, that is same as maximized, but it doesn't have title bar (press key F to toggle full screen mode)."""
    if backend is None:
        backend=matplotlib.get_backend()
    mng = plt.get_current_fig_manager()

    if fullscreen:
        mng.full_screen_toggle()
    else:
        if backend == 'wxAgg':
            mng.frame.Maximize(True)
        elif backend == 'Qt4Agg' or backend == 'Qt5Agg':
            mng.window.showMaximized()
        elif backend == 'TkAgg':
            mng.window.state('zoomed') #works fine on Windows!
        else:
            print ("Unrecognized backend: ",backend) #not tested on different backends (only Qt)
    plt.show()

    plt.pause(0.1) #this is needed to make sure following processing gets applied (e.g. tight_layout)
Vincenzooo
  • 2,013
  • 1
  • 19
  • 33
  • for TkAgg on ubuntu you could try:
    `mng = plt.get_current_fig_manager()
    mng.resize(*mng.window.maxsize())`
    Taken from https://stackoverflow.com/questions/12439588/how-to-maximize-a-plt-show-window-using-python/14537262
    – Patricio Astudillo Feb 25 '19 at 10:51
-1

If I understand correctly what you want to do, you can create your figure and set the size of the window. Afterwards, you can save your graph with the matplotlib toolbox button. Here an example:

from pylab import get_current_fig_manager,show,plt,imshow

plt.Figure()
thismanager = get_current_fig_manager()
thismanager.window.wm_geometry("500x500+0+0") 
#in this case 500 is the size (in pixel) of the figure window. In your case you want to maximise to the size of your screen or whatever

imshow(your_data)
show()
maupertius
  • 1,518
  • 4
  • 17
  • 30
  • 7
    "you can save your graph with the matplotlib toolbox button" - this is **EXACTLY** what I'm trying to avoid. I want an automated (i.e. programmable) solution, not a manual one, since I will be generating several hundred images in a script. – Homunculus Reticulli Apr 19 '12 at 08:30