Save plot to image file instead of displaying it using Matplotlib - python
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)?
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.
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).
The solution is:
pylab.savefig('foo.png')
Just found this link on the MatPlotLib documentation addressing exactly this issue:
http://matplotlib.org/faq/howto_faq.html#generate-images-without-having-a-window-appear
They 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')
I still 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
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)
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()
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
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.
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()
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()
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')
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()
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
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
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.
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'
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.
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!
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.
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):
You can do it like this:
def plotAFig():
plt.figure()
plt.plot(x,y,'b-')
plt.savefig("figurename.png")
plt.close()
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))
Hope that helps somebody.
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:)
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)
Related
plt.show() does nothing when used for the second time
I am just starting to learn data science using python on Data Camp and I noticed something while using the functions in matplotlib.pyplot import matplotlib.pyplot as plt year = [1500, 1600, 1700, 1800, 1900, 2000] pop = [458, 580, 682, 1000, 1650, 6,127] plt.plot(year, pop) plt.show() # Here a window opens up and shows the figure for the first time but when I try to show it again it doesn't.. plt.show() # for the second time.. nothing happens And I have to retype the line above the show() to be able to show a figure again Is this the normal thing or a problem? Note: I am using the REPL
Answer Yes, this is normal expected behavior for matplotlib figures. Explanation When you run plt.plot(...) you create on the one hand the lines instance of the actual plot: >>> print( plt.plot(year, pop) ) [<matplotlib.lines.Line2D object at 0x000000000D8FDB00>] ...and on the other hand a Figure instance, which is set as the 'current figure' and accessible through plt.gcf() (short for "get current figure"): >>> print( plt.gcf() ) Figure(432x288) The lines (as well as other plot elements you might add) are all placed in the current figure. When plt.show() is called, the current figure is displayed and then emptied (!), which is why a second call of plt.show() doesn't plot anything. Standard Workaround One way of solving this is to explicitly keep hold of the current Figure instance and then show it directly with fig.show(), like this: plt.plot(year, pop) fig = plt.gcf() # Grabs the current figure plt.show() # Shows plot plt.show() # Does nothing fig.show() # Shows plot again fig.show() # Shows plot again... A more commonly used alternative is to initialize the current figure explicitly in the beginning, prior to any plotting commands. fig = plt.figure() # Initializes current figure plt.plot(year, pop) # Adds to current figure plt.show() # Shows plot fig.show() # Shows plot again This is often combined with the specification of some additional parameters for the figure, for example: fig = plt.figure(figsize=(8,8)) For Jupyter Notebook Users The fig.show() approach may not work in the context of Jupyter Notebooks and may instead produce the following warning and not show the plot: C:\redacted\path\lib\site-packages\matplotlib\figure.py:459: UserWarning: matplotlib is currently using a non-GUI backend, so cannot show the figure Fortunately, simply writing fig at the end of a code cell (instead of fig.show()) will push the figure to the cell's output and display it anyway. If you need to display it multiple times from within the same code cell, you can achieve the same effect using the display function: fig = plt.figure() # Initializes current figure plt.plot(year, pop) # Adds to current figure plt.show() # Shows plot plt.show() # Does nothing from IPython.display import display display(fig) # Shows plot again display(fig) # Shows plot again... Making Use of Functions One reason for wanting to show a figure multiple times is to make a variety of different modifications each time. This can be done using the fig approach discussed above but for more extensive plot definitions it is often easier to simply wrap the base figure in a function and call it repeatedly. Example: def my_plot(year, pop): plt.plot(year, pop) plt.xlabel("year") plt.ylabel("population") my_plot(year, pop) plt.show() # Shows plot my_plot(year, pop) plt.show() # Shows plot again my_plot(year, pop) plt.title("demographics plot") plt.show() # Shows plot again, this time with title
Using command: %matplotlib in ipython3 help me to use separate window with plot
Start ipython3 and issue the commands: import matplotlib.pyplot as plt %matplotlib #plot in separate window fig, ax = plt.subplots() #Appear empty Tcl window for image ax.plot([1, 2, 3, 4], [5, 6, 7, 8]) #Appear graph in window
In some version of matplotlib, fig.show() does not block the window for showing plot multiple times. so, Quick fixes using self.fig.waitforbuttonpress() it waits user to press the button for next plot visualisation. self.fig.show() plt.pause(0.1) self.fig.waitforbuttonpress()
Python plt: close or clear figure does not work
I generate a lots of figures with a script which I do not display but store to harddrive. After a while I get the message /usr/lib/pymodules/python2.7/matplotlib/pyplot.py:412: RuntimeWarning: More than 20 figures have been opened. Figures created through the pyplot interface (matplotlib.pyplot.figure) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam figure.max_num_figures). max_open_warning, RuntimeWarning) Thus, I tried to close or clear the figures after storing. So far, I tried all of the followings but no one works. I still get the message from above. plt.figure().clf() plt.figure().clear() plt.clf() plt.close() plt.close('all') plt.close(plt.figure()) And furthermore I tried to restrict the number of open figures by plt.rcParams.update({'figure.max_num_figures':1}) Here follows a piece of sample code that behaves like described above. I added the different options I tried as comments at the places I tried them. from pandas import DataFrame from numpy import random df = DataFrame(random.randint(0,10,40)) import matplotlib.pyplot as plt plt.ioff() #plt.rcParams.update({'figure.max_num_figures':1}) for i in range(0,30): fig, ax = plt.subplots() ax.hist([df]) plt.savefig("/home/userXYZ/Development/pic_test.png") #plt.figure().clf() #plt.figure().clear() #plt.clf() #plt.close() # results in an error #plt.close('all') # also error #plt.close(plt.figure()) # also error To be complete, that is the error I get when using plt.close: can't invoke "event" command: application has been destroyed while executing "event generate $w <>" (procedure "ttk::ThemeChanged" line 6) invoked from within "ttk::ThemeChanged"
The correct way to close your figures would be to use plt.close(fig), as can be seen in the below edit of the code you originally posted. from pandas import DataFrame from numpy import random df = DataFrame(random.randint(0,10,40)) import matplotlib.pyplot as plt plt.ioff() for i in range(0,30): fig, ax = plt.subplots() ax.hist(df) name = 'fig'+str(i)+'.png' # Note that the name should change dynamically plt.savefig(name) plt.close(fig) # <-- use this line The error that you describe at the end of your question suggests to me that your problem is not with matplotlib, but rather with another part of your code (such as ttk).
plt.show() is a blocking function, so in the above code, plt.close() will not execute until the fig windows are closed. You can use plt.ion() at the beginning of your code to make it non-blocking. Even though this has some other implications the fig will be closed.
I was still having the same issue on Python 3.9.7, matplotlib 3.5.1, and VS Code (the issue that no combination of plt.close() closes the figure). I have three loops which the most inner loop plots more than 20 figures. The solution that is working for me is using agg as backend and del someFig after plt.close(someFig). Subsequently, the order of code would be something like: import matplotlib matplotlib.use('agg') import matplotlib.pyplot as plt someFig = plt.figure() . . . someFig.savefig('OUTPUT_PATH') plt.close(someFig) # --> (Note 1) del someFig . . . NOTE 1: If this line is removed, the output figures may not be plotted correctly! Especially when the number of elements to be rendered in the figure is high. NOTE 2: I don't know whether this solution could backfire or not, but at least it is working and not hugging RAM or preventing plotting figures!
import tensorflow as tf from matplotlib import pyplot as plt sample_image = tf.io.read_file(str(PATH / 'Path to your file')) sample_image = tf.io.decode_jpeg(sample_image) print(sample_image.shape) plt.figure("1 - Sample Image ") plt.title(label="Sample Image", fontsize=12, color="red") plt.imshow(sample_image) plt.show(block=False) plt.pause(3) plt.close() plt.show(block=False) plt.pause(interval) do the trick
This does not really solve my problem, but it is a work-around to handle the high memory consumption I faced and I do not get any of the error messages as before: from pandas import DataFrame from numpy import random df = DataFrame(random.randint(0,10,40)) import matplotlib.pyplot as plt plt.ioff() for i in range(0,30): plt.close('all') fig, ax = plt.subplots() ax.hist([df]) plt.savefig("/home/userXYZ/Development/pic_test.png")
Python: Saving one or multiple plots in one png or pdf [duplicate]
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)?
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.
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).
The solution is: pylab.savefig('foo.png')
Just found this link on the MatPlotLib documentation addressing exactly this issue: http://matplotlib.org/faq/howto_faq.html#generate-images-without-having-a-window-appear They 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') I still 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
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)
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()
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
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.
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()
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()
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')
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()
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
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
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.
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'
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.
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!
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.
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):
You can do it like this: def plotAFig(): plt.figure() plt.plot(x,y,'b-') plt.savefig("figurename.png") plt.close()
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)) Hope that helps somebody.
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:)
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)
Matplotlib reuse figure created by another script
I am using Matplotlib on MacOS with Sulime Text. I use Python 3.5 and Matplotlib 2.0. When I work on a figure, I usually have a script that plot the data, and save the figure in a .pdf file with plt.savefig(). Then I use Skim (a pdf viewer) in order to refresh the file each time I modify and run the script. This allows me to set my working layout as clean as: there is one window for the script, and one window for the figure which is automatically refreshing. I would like to do keep the same layout, but using the Matplotlib figures (because they are interactive). I am looking for a way to use plt.show() but always in the same figure that has been created the first time I've run the script. For instance: 1. First run import matplotlib.pyplot as plt import numpy as np fig, ax = plt.figure() noise = np.random.rand(1, 100) ax(noise) plt.show() 2. Following runs import matplotlib.pyplot as plt import numpy as np # This is the super command I am looking for fig = plt.get_previous_run_figure() ax = fig.axes noise = np.random.rand(1, 100) ax.plot(noise) plt.draw() In that case of course, I would have to do a first-run script separately from the main script. Does anyone know if it is possible ?
You want to have multiple consecutive python sessions share a common Matplotlib window. I see no way to share this windows from separate processes, especially when the original owner may terminate at any point in time. However, you could do something similar to your current workflow in which you have an external pdf viewer to view a output file which you update from multiple python instances. See this question/answer on how to pickle a matplotlib figure: Store and reload matplotlib.pyplot object In every script, output your matplotlib figure as a pickled object, rather than calling plt.show(): import matplotlib.pyplot as plt import numpy as np import pickle ax = plt.subplot(111) x = np.linspace(0, 10) y = np.exp(x) plt.plot(x, y) pickle.dump(ax, file('myplot.pickle', 'w')) Then, start a dedicated python session which loads this pickled object and calls plt.show(). Have this script run in a loop, checking for updates of the pickled file on disk, and reloading when necessary: import matplotlib.pyplot as plt import pickle while True: ax = pickle.load(file('myplot.pickle')) plt.show() Alternative Instead of having separate python sessions, I usually have a single Ipython session in which I run different script. By selecting the same figure windows, I end up with a mostly similar setup as you describe, in which the same figure window is reused throughout the day. import matplotlib.pyplot as plt fig = plt.figure(0) fig.clf() plt.show()
In principle establishing a connection between two different scripts could be done using a system-wide clipboard. (As far as I know the clipboard in windows and macos are system-wide.) So the idea can be to set up an application using tk or pyqt, and implement a generic FigureCanvas. This application could have an event listener for changes in the clipboard. The other main workflow script would then call some function that wraps the current figure into a pickle object and sends it to the clipboard, from where it gets caught by the GUI application, is unpickled and shown in the canvas. This sounds like a little bit of work, but should meet the very restrictive requirements from the question.
The alternative from Daan worked for me. Here's a bit more code. I used this in a Tkinter interactive GUI for reusing/updating a matplotlib figure window: fig1 = None if fig1: #if exists, clear figure 1 plt.figure(1).clf() plt.suptitle("New Fig Title", fontsize=18, fontweight='bold') #reuse window of figure 1 for new figure fig1 = plt.scatter(points.T[0], points.T[1], color='red', **plot_kwds) else: #initialize fig1 = plt.figure(num=1,figsize=(7, int(7*imgRatio)), dpi=80) plt.tick_params(axis='both', which='major', labelsize=14) plt.tick_params(axis='both', which='minor', labelsize=14) plt.suptitle("Title", fontsize=18, fontweight='bold') fig1 = plt.scatter(points.T[0], points.T[1], color='red', **plot_kwds) The figure is reusing the (interactive) plt window. For this to work, I had to set interactive : True in the matplotlibrc file (see my comment here)
Combining mayavi and matplotlib in the same figure
I will be making animations. In each frame I want to contain both a mayavi plot obtained with mlab.pipeline.iso_surface(source, some other superfluous args) and a matplotlib plot obtained using simply pylab.plot(args) I have scripts to do both separately, but have no idea how to go about combining them into one figure. I want the end product to be one script which contains the code from both the scripts that I currently have.
AFAIK, there is no direct way because the backends used are so different. It does not seem possible to add matplotlib axes to mayavi.figure or vice versa. However, there is a "kind of a way" by using the the mlab.screenshot. import mayavi.mlab as mlab import matplotlib.pyplot as plt # create and capture a mlab object mlab.test_plot3d() img = mlab.screenshot() mlab.close() # create a pyplot fig = plt.figure() ax1 = fig.add_subplot(121) ax1.plot([0,1], [1,0], 'r') # add the screen capture ax2 = fig.add_subplot(122) ax2.imshow(img) ax2.set_axis_off() This is not necessarily the nicest possible way of doing things, and you may bump into resolution problems, as well (check the size of the mayavi window). However, it gets the job done in most cases.
Adding to the answer by DrV which helped me a great deal, you can work with the mlab figure to set resolution before screenshot such as with batch plotting: mfig = mlab.figure(size=(1024, 1024)) src = mlab.pipeline.scalar_field(field_3d_numpy_array) mlab.pipeline.iso_surface(src) iso_surface_plot = mlab.screenshot(figure=mfig, mode='rgba', antialiased=True) mlab.clf(mfig) mlab.close() # Then later in a matplotlib fig: plt.imshow(iso_surface_plot)