Save plot to image file instead of displaying it
Asked Answered
H

26

1735

This displays the figure in a GUI:

import matplotlib.pyplot as plt
plt.plot([1, 2, 3], [1, 4, 9])
plt.show()

But how do I instead save the figure to a file (e.g. foo.png)?

Hui answered 8/3, 2012 at 17:38 Comment(1)
Many of the answers lower down the page mention plt.close(fig) which is especially important in big loops. Otherwise the figures remain open and waiting in memory and all open figures will be shown upon executing plt.show()Bulger
B
2209

When using matplotlib.pyplot.savefig, the file format can be specified by the extension:

from matplotlib import pyplot as plt

plt.savefig('foo.png')
plt.savefig('foo.pdf')

That gives a rasterized or vectorized output respectively. In addition, there is sometimes undesirable whitespace around the image, which can be removed with:

plt.savefig('foo.png', bbox_inches='tight')

Note that if showing the plot, plt.show() should follow plt.savefig(); otherwise, the file image will be blank.

Bencion answered 27/3, 2012 at 13:35 Comment(4)
Can someone explain why showing before saving will result in a saved blank image?Ketty
@Ketty calling show() clears the plot. You have to save it before but there are other options too for this.Labradorite
For Jupyter Notebook the plt.plot(data) and plt.savefig('foo.png') have to be in the same cell. If not you will see a blank file.Putrefaction
it is better to plt.close(fig) after savefig()Deprecate
U
311

As others have said, plt.savefig() or fig1.savefig() is indeed the way to save an image.

However I've found that in certain cases the figure is always shown. (eg. with Spyder having plt.ion(): interactive mode = On.) I work around this by forcing the the figure window to close with:

plt.close(figure_object)

(see documentation). This way I don't have a million open figures during a large loop. Example usage:

import matplotlib.pyplot as plt
fig, ax = plt.subplots( nrows=1, ncols=1 )  # create figure & 1 axis
ax.plot([0,1,2], [10,20,3])
fig.savefig('path/to/save/image/to.png')   # save the figure to file
plt.close(fig)    # close the figure window

You should be able to re-open the figure later if needed to with fig.show() (didn't test myself).

Ulita answered 28/4, 2015 at 22:35 Comment(3)
Note that the names ax/fig/plt are made up variable names - call them whatever you want. Either way, they contain Objects. You can see what objects subplots returns here: matplotlib.org/3.2.1/api/_as_gen/… , and what the pyplot module is here: matplotlib.org/tutorials/introductory/pyplot.html .Ulita
(The above was an answer to a ghost-comment that has since magically disappeared!)Ulita
I am running fine tunning in cv2, and thank to plt.close(fig), my memory was down from 97% (and out of memory) to 60%. It's foolish for me!Deprecate
C
176

The solution is:

import matplotlib.pyplot as pylab

... # your way of creating the graph
pylab.savefig('foo.png')
Chiachiack answered 27/3, 2012 at 11:36 Comment(2)
pylab is not definedDecoteau
@Decoteau I've just addressed your comment as an edit to this answer.Swetiana
U
126

There was a section on the MatPlotLib documentation addressing exactly this issue, however it has since changed.

It used to say that the easiest way to prevent the figure from popping up is to use a non-interactive backend (eg. Agg), via matplotib.use(<backend>), eg:

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
plt.plot([1,2,3])
plt.savefig('myfig')

New documentation here: https://matplotlib.org/stable/users/faq/howto_faq.html#generate-images-without-having-a-window-appear Says to not call plt.show(). However, Spyder's default settings still causes the figure to show. See this hint for a workaround: https://mcmap.net/q/45106/-save-plot-to-image-file-instead-of-displaying-it

I personally prefer using plt.close( fig ), since then you have the option to hide certain figures (during a loop), but still display figures for post-loop data processing. It is probably slower than choosing a non-interactive backend though - would be interesting if someone tested that.

UPDATE: for Spyder, you usually can't set the backend in this way (Because Spyder usually loads matplotlib early, preventing you from using matplotlib.use()).

Instead, use plt.switch_backend('Agg'), or Turn off "enable support" in the Spyder prefs and run the matplotlib.use('Agg') command yourself.

From these two hints: one, two

Ulita answered 4/1, 2016 at 0:35 Comment(1)
I like the tutorial the matplotlib site has for the description/definition of "backends": matplotlib.org/tutorials/introductory/…Revkah
P
60

If you don't like the concept of the "current" figure, do:

import matplotlib.image as mpimg

img = mpimg.imread("src.png")
mpimg.imsave("out.png", img)
Promycelium answered 30/1, 2014 at 18:30 Comment(4)
Doesn't this just copy src.png to out.png?Seethe
That's just an example, that shows if you have an image object (img), then you can save it into file with .imsave() method.Promycelium
@Promycelium would help to show how to create an image without using the current figure.Houseyhousey
@Houseyhousey You don't always need to create an image, sometimes you try out some code and want a visual output, it is handy in such occasions.Finnic
G
40

I used the following:

import matplotlib.pyplot as plt

p1 = plt.plot(dates, temp, 'r-', label="Temperature (celsius)")  
p2 = plt.plot(dates, psal, 'b-', label="Salinity (psu)")  
plt.legend(loc='upper center', numpoints=1, bbox_to_anchor=(0.5, -0.05),        ncol=2, fancybox=True, shadow=True)

plt.savefig('data.png')  
plt.show() 
plt.close()

I found very important to use plt.show after saving the figure, otherwise it won't work.figure exported in png

Guiana answered 5/4, 2016 at 13:34 Comment(0)
S
39
import datetime
import numpy as np
from matplotlib.backends.backend_pdf import PdfPages
import matplotlib.pyplot as plt

# Create the PdfPages object to which we will save the pages:
# The with statement makes sure that the PdfPages object is closed properly at
# the end of the block, even if an Exception occurs.
with PdfPages('multipage_pdf.pdf') as pdf:
    plt.figure(figsize=(3, 3))
    plt.plot(range(7), [3, 1, 4, 1, 5, 9, 2], 'r-o')
    plt.title('Page One')
    pdf.savefig()  # saves the current figure into a pdf page
    plt.close()

    plt.rc('text', usetex=True)
    plt.figure(figsize=(8, 6))
    x = np.arange(0, 5, 0.1)
    plt.plot(x, np.sin(x), 'b-')
    plt.title('Page Two')
    pdf.savefig()
    plt.close()

    plt.rc('text', usetex=False)
    fig = plt.figure(figsize=(4, 5))
    plt.plot(x, x*x, 'ko')
    plt.title('Page Three')
    pdf.savefig(fig)  # or you can pass a Figure object to pdf.savefig
    plt.close()

    # We can also set the file's metadata via the PdfPages object:
    d = pdf.infodict()
    d['Title'] = 'Multipage PDF Example'
    d['Author'] = u'Jouni K. Sepp\xe4nen'
    d['Subject'] = 'How to create a multipage pdf file and set its metadata'
    d['Keywords'] = 'PdfPages multipage keywords author title subject'
    d['CreationDate'] = datetime.datetime(2009, 11, 13)
    d['ModDate'] = datetime.datetime.today()
Scibert answered 30/6, 2015 at 8:38 Comment(0)
S
35

The other answers are correct. However, I sometimes find that I want to open the figure object later. For example, I might want to change the label sizes, add a grid, or do other processing. In a perfect world, I would simply rerun the code generating the plot, and adapt the settings. Alas, the world is not perfect. Therefore, in addition to saving to PDF or PNG, I add:

with open('some_file.pkl', "wb") as fp:
    pickle.dump(fig, fp, protocol=4)

Like this, I can later load the figure object and manipulate the settings as I please.

I also write out the stack with the source-code and locals() dictionary for each function/method in the stack, so that I can later tell exactly what generated the figure.

NB: Be careful, as sometimes this method generates huge files.

Seethe answered 26/5, 2016 at 11:48 Comment(0)
L
32

After using the plot() and other functions to create the content you want, you could use a clause like this to select between plotting to the screen or to file:

import matplotlib.pyplot as plt

fig = plt.figure(figsize=(4, 5))       # size in inches
# use plot(), etc. to create your plot.

# Pick one of the following lines to uncomment
# save_file = None
# save_file = os.path.join(your_directory, your_file_name)  

if save_file:
    plt.savefig(save_file)
    plt.close(fig)
else:
    plt.show()
Loyola answered 11/10, 2016 at 22:12 Comment(0)
H
17

If, like me, you use Spyder IDE, you have to disable the interactive mode with :

plt.ioff()

(this command is automatically launched with the scientific startup)

If you want to enable it again, use :

plt.ion()

Herzl answered 29/8, 2015 at 14:50 Comment(0)
S
16

You can either do:

plt.show(hold=False)
plt.savefig('name.pdf')

and remember to let savefig finish before closing the GUI plot. This way you can see the image beforehand.

Alternatively, you can look at it with plt.show() Then close the GUI and run the script again, but this time replace plt.show() with plt.savefig().

Alternatively, you can use

fig, ax = plt.figure(nrows=1, ncols=1)
plt.plot(...)
plt.show()
fig.savefig('out.pdf')
Shorthorn answered 23/9, 2017 at 23:20 Comment(0)
R
15

According to question Matplotlib (pyplot) savefig outputs blank image.

One thing should note: if you use plt.show and it should after plt.savefig, or you will give a blank image.

A detailed example:

import numpy as np
import matplotlib.pyplot as plt


def draw_result(lst_iter, lst_loss, lst_acc, title):
    plt.plot(lst_iter, lst_loss, '-b', label='loss')
    plt.plot(lst_iter, lst_acc, '-r', label='accuracy')

    plt.xlabel("n iteration")
    plt.legend(loc='upper left')
    plt.title(title)
    plt.savefig(title+".png")  # should before plt.show method

    plt.show()


def test_draw():
    lst_iter = range(100)
    lst_loss = [0.01 * i + 0.01 * i ** 2 for i in xrange(100)]
    # lst_loss = np.random.randn(1, 100).reshape((100, ))
    lst_acc = [0.01 * i - 0.01 * i ** 2 for i in xrange(100)]
    # lst_acc = np.random.randn(1, 100).reshape((100, ))
    draw_result(lst_iter, lst_loss, lst_acc, "sgd_method")


if __name__ == '__main__':
    test_draw()

enter image description here

Rood answered 20/7, 2018 at 9:38 Comment(0)
D
14

The Solution :

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
matplotlib.style.use('ggplot')
ts = pd.Series(np.random.randn(1000), index=pd.date_range('1/1/2000', periods=1000))
ts = ts.cumsum()
plt.figure()
ts.plot()
plt.savefig("foo.png", bbox_inches='tight')

If you do want to display the image as well as saving the image use:

%matplotlib inline

after import matplotlib

Distinction answered 27/3, 2016 at 8:49 Comment(0)
F
11

When using matplotlib.pyplot, you must first save your plot and then close it using these 2 lines:

fig.savefig('plot.png') # save the plot, place the path you want to save the figure in quotation
plt.close(fig) # close the figure window
Flyspeck answered 11/5, 2020 at 8:24 Comment(0)
P
9
import matplotlib.pyplot as plt
plt.savefig("image.png")

In Jupyter Notebook you have to remove plt.show() and add plt.savefig(), together with the rest of the plt-code in one cell. The image will still show up in your notebook.

Putrefaction answered 17/11, 2018 at 20:1 Comment(0)
B
7

Additionally to those above, I added __file__ for the name so the picture and Python file get the same names. I also added few arguments to make It look better:

# Saves a PNG file of the current graph to the folder and updates it every time
# (nameOfimage, dpi=(sizeOfimage),Keeps_Labels_From_Disappearing)
plt.savefig(__file__+".png",dpi=(250), bbox_inches='tight')
# Hard coded name: './test.png'
Brookins answered 12/7, 2019 at 13:11 Comment(0)
K
6

Just a extra note because I can't comment on posts yet.

If you are using plt.savefig('myfig') or something along these lines make sure to add a plt.clf() after your image is saved. This is because savefig does not close the plot and if you add to the plot after without a plt.clf() you'll be adding to the previous plot.

You may not notice if your plots are similar as it will plot over the previous plot, but if you are in a loop saving your figures the plot will slowly become massive and make your script very slow.

Kristlekristo answered 29/6, 2021 at 15:37 Comment(0)
P
5

Given that today (was not available when this question was made) lots of people use Jupyter Notebook as python console, there is an extremely easy way to save the plots as .png, just call the matplotlib's pylab class from Jupyter Notebook, plot the figure 'inline' jupyter cells, and then drag that figure/image to a local directory. Don't forget %matplotlib inline in the first line!

Pretext answered 14/12, 2018 at 7:20 Comment(0)
G
5

well, I do recommend using wrappers to render or control the plotting. examples can be mpltex (https://github.com/liuyxpp/mpltex) or prettyplotlib (https://github.com/olgabot/prettyplotlib).

import mpltex

@mpltex.acs_decorator
def myplot():
  plt.figure()
  plt.plot(x,y,'b-',lable='xxx')
  plt.tight_layout(pad=0.5)
  plt.savefig('xxxx')  # the figure format was controlled by the decorator, it can be either eps, or pdf or png....
  plt.close()

I basically use this decorator a lot for publishing academic papers in various journals at American Chemical Society, American Physics Society, Opticcal Society American, Elsivier and so on.

An example can be found as following image (https://github.com/MarkMa1990/gradientDescent): an example of gradient descent

Gooding answered 6/8, 2021 at 16:2 Comment(0)
P
4

As suggested before, you can either use:

import matplotlib.pyplot as plt
plt.savefig("myfig.png")

For saving whatever IPhython image that you are displaying. Or on a different note (looking from a different angle), if you ever get to work with open cv, or if you have open cv imported, you can go for:

import cv2

cv2.imwrite("myfig.png",image)

But this is just in case if you need to work with Open CV. Otherwise plt.savefig() should be sufficient.

Pythagoreanism answered 29/1, 2020 at 11:46 Comment(0)
G
2

You can do it like this:

def plotAFig():
  plt.figure()
  plt.plot(x,y,'b-')
  plt.savefig("figurename.png")
  plt.close()
Gooding answered 20/8, 2019 at 14:51 Comment(0)
H
2

Nothing was working for me. The problem is that the saved imaged was very small and I could not find how the hell make it bigger.

This seems to make it bigger, but still not full screen.

https://matplotlib.org/stable/api/figure_api.html#matplotlib.figure.Figure.set_size_inches

fig.set_size_inches((w, h))
Halfcaste answered 22/6, 2021 at 8:37 Comment(0)
L
2

plt.savefig("name.png") is definitely going to be the most direct way to get your visualization saved.

If you're looking for a more comprehensive solution for organizing visualization output, check out teeplot. This library wraps plotting calls to automatically manage matplotlib file output, picking meaningful file names based on semantic plotting variables.

Example

This example shows a call to seaborn's lmplot dispatched through teeplot.tee to save out the plot as teeplots/col=time+hue=sex+viz=lmplot+x=total-bill+y=tip+ext={.pdf,.png}

example plot

To save withoutshow-ing,

>>> # adapted from seaborn.pydata.org/generated/seaborn.FacetGrid.html
>>> import seaborn as sns
>>> from teeplot import teeplot as tp
>>> tp.tee(sns.lmplot,  # plotter, then forwarded args/kwargs
>>>     sns.load_dataset("tips"), col="time", hue="sex", x="total_bill", y="tip"
>>>     teeplot_show=False, teeplot_verbose=True)
teeplots/col=time+hue=sex+viz=lmplot+x=total-bill+y=tip+ext=.pdf
teeplots/col=time+hue=sex+viz=lmplot+x=total-bill+y=tip+ext=.png

The idea is to make the process of saving and cataloging plots more efficient, systematic, and meaningful, taking the hassle out of manual file management.

Further Information

teeplot can be installed as python3 -m pip install teeplot.

teeplot has additional advanced features, as well, including an interface to globally configure visualization output file types (i.e., ".pdf", ".png"), etc. You can read more in the project's usage guide and API listing.

disclaimer: am library author

Laminitis answered 29/12, 2023 at 8:22 Comment(0)
S
1

Just want to point out that if you explicitly define a figure object, then you can technically do plot, show and savefig in that order. This is especially useful if you are using a third-party library that uses matplotlib in the backend that automatically calls show() which causes the savefig() to save a blank image. So instead of plot/show + savefig, use figure + plot/show + savefig.

An example:

fig = plt.figure()                       # <--- define a figure object
plt.plot([1, 2, 3, 1])
plt.show()
fig.savefig('myimage.png', dpi=fig.dpi)  # <--- save the previously defined fig

Some library plotters returns a figure; in which case, save that figure:

from statsmodels.tsa.seasonal import seasonal_decompose
fig = season_decompose(data).plot()
fig.savefig('myimage.png')

One thing to note about plt.close() is that it doesn't delete the figure instance from memory, it merely closes the window showing it; to completely flush it use plt.clf()/fig.clf().

Sophistic answered 4/12, 2023 at 21:47 Comment(0)
M
0

You can save your image with any extension(png, jpg,etc.) and with the resolution you want. Here's a function to save your figure.

import os

def save_fig(fig_id, tight_layout=True, fig_extension="png", resolution=300):
    path = os.path.join(IMAGES_PATH, fig_id + "." + fig_extension)
    print("Saving figure", fig_id)
    if tight_layout:
        plt.tight_layout()
    plt.savefig(path, format=fig_extension, dpi=resolution)

'fig_id' is the name by which you want to save your figure. Hope it helps:)

Morbihan answered 25/6, 2019 at 17:36 Comment(0)
H
0

using 'agg' due to no gui on server. Debugging on ubuntu 21.10 with gui and VSC. In debug, trying to both display a plot and then saving to file for web UI.

Found out that saving before showing is required, otherwise saved plot is blank. I suppose that showing will clear the plot for some reason. Do this:

plt.savefig(imagePath) 
plt.show()
plt.close(fig)

Instead of this:

plt.show()
plt.savefig(imagePath) 
plt.close(fig)
Hoecake answered 4/2, 2022 at 20:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.