Related
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)
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)
I would like to use matplotlib.pyplot to display many images in my jupyter notebook. However, when I try to display more than 20, a runtime warning appears, since images are kept in memory if not closed:
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_open_warning).
I am using %matplotlib inline
If I close the plot plt.close(), the plots are not displayed. How can I can close the plot and still look at the plot in jupyter, I need to look at many images simultanously: I am using a loop where crop and value are two images.
plt.figure()
f, axarr = plt.subplots(1,2)
plt.title('Image: ' + str(key))
plt.gray()
axarr[0].imshow(crop)
axarr[1].imshow(value)
plt.close()
I think you would want to use plt.show() at the end of your loop.
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
for i in range(25):
fig, ax_arr = plt.subplots(1,2)
ax_arr[0].imshow(np.random.randn(10,10))
ax_arr[1].imshow(np.random.randn(10,10))
plt.show()
There is then no need to close anything.
I am using ipython-notebook a lot at the moment for numerical analysis and plotting of data. In the process of preparing publication quality plots there is a lot of tweaking to get the layout just right, however I can't get ipython/matplotlib to show me what I will be saving in the browser. Making the process more painful than it should be because I have to keep opening the new output file to check it.
Is there a way to get the image that is displayed inline to be the same as the image that is saved?
Example as follows, facecolor='gray' for clarity:
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
fig = plt.figure(figsize=(6,4),facecolor='gray')
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])
x = np.linspace(0,2*np.pi,1000)
y = np.sin(x)
ax.plot(x,y,label=r'$\sin(x)$')
ax.set_xlim(0,2*np.pi)
ax.set_ylim(-1.2,1.2)
ax.set_xlabel(r'$x$')
ax.set_ylabel(r'$y$')
ax.legend(loc='upper right', frameon=False)
fig.savefig('mypath.png',dpi=300, facecolor='gray')
plt.show()
Note here I have explicity chosen my axes dimensions so that they are equidistant from the two sides of the resulting image. This is respected in the saved image, but ignored in the image shown in the notebook:
Notebook displayed image:
Savefig image:
As noted by #andrew, the ipython magics are enforcing bbox_inches='tight' by default. This can be overridden using other magics as explained in the ipython documentation:
%matplotlib inline
%config InlineBackend.print_figure_kwargs = {'bbox_inches':None}
produces an inline image identical to that produced by savefig.
The behavior is due to the fact that the magic %matplotlib inline defaults to using the
bbox_inches='tight' when rendering inline.
I know you asked about changing the behavior of plt.show(), but alternatively, you could change the behavior of savefig() to use the same settings as the notbeook.
fig.savefig('mypath.png',dpi=300, facecolor='gray', bbox_inches='tight')
New 'savefig' image:
I would like to view matplotlib plots inside Spyders IPython console in one size and save figures to a multipage PDF in a different size.
Currently I set the figure size as follows:
plt.rc('axes', grid=True)
plt.rc('figure', figsize=(12, 8))
plt.rc('legend', fancybox=True, framealpha=1)
Then I plot some figures and save them to a list for saving a PDF later on. This works just fine when used alone. The plots are approriately sized for viewing in Spyder IPython console.
At the end of my script I have a loop to go through each of the figures I want to save. In here I want to set the layout and figure size exactly for better printing on an A3 paper.
with PdfPages('multi.pdf') as pdf:
for fig in figs:
fig.tight_layout()
fig.set_size_inches(420/25.4, 297/25.4)
pdf.savefig(figure=fig)
The output PDF is just like I want it to be, but the problem is with the plots shown inside Spyder. Changing the figure size while saving also affects the plots viewed inside Spyder. And using the size of an A3 makes the plots way too big.
So the question is: How do I change the size of saved PDF figures without changing the size of figures shown inside Spyder?
As suggested by #ImportanceOfBeingErnest, changing the figure size back after saving should work and may probably solved you problem.
But, depending on your specific problem, it is possible that you are going to face scaling issues since the size of the figures saved in the pdf is much bigger than the size of those displayed in the IPython console. If you scale everything to look great on the pdf, then it is possible that everything is going to look too big in IPython as shown in the example below:
If you don't need the plot to be interactive in IPython, a solution may be to generate your figures to look good for the pdf and display a scaled bitmap version of them in the IPython console as shown in the code below:
import matplotlib.pyplot as plt
from matplotlib.backends.backend_pdf import PdfPages
import numpy as np
from IPython.display import Image, display
try: # Python 2
from cStringIO import StringIO as BytesIO
except ImportError: # Python 3
from io import BytesIO
# Generate a matplotlib figures that looks good on A3 format :
fig, ax = plt.subplots()
ax.plot(np.random.rand(150), np.random.rand(150), 'o', color='0.35', ms=25,
alpha=0.85)
ax.set_ylabel('ylabel', fontsize=46, labelpad=25)
ax.set_xlabel('xlabel', fontsize=46, labelpad=25)
ax.tick_params(axis='both', which='major', labelsize=30, pad=15,
direction='out', top=False, right=False, width=3, length=10)
for loc in ax.spines:
ax.spines[loc].set_linewidth(3)
# Save figure to pdf in A3 format:
w, h = 420/25.4, 297/25.4
with PdfPages('multi.pdf') as pdf:
fig.set_size_inches(w, h)
fig.tight_layout()
pdf.savefig(figure=fig)
plt.close(fig)
# Display in Ipython a sclaled bitmap using a buffer to save the png :
buf = BytesIO()
fig.savefig(buf, format='png', dpi=90)
display(Image(data=buf.getvalue(), format='png', width=450, height=450*h/w,
unconfined=True))
which shows in the IPython console as:
Thank you #ImportanceOfBeingErnest for pointing out the solution.
I went with a solution that allows me to set plt.rc in the beginning to my taste and then revert to the set values after exporting the figures to a PDF.
First I set the values I use:
plt.rc('axes', grid=True)
plt.rc('figure', figsize=(12, 8))
plt.rc('legend', fancybox=True, framealpha=1)
With these I can plot what I need with just the default values. Then I create the PDF with:
with PdfPages('multi.pdf') as pdf:
for fig in figs:
fig.set_size_inches(420/25.4, 297/25.4)
pdf.savefig(figure=fig, bbox_inches='tight')
fig.set_size_inches(plt.rcParams.get('figure.figsize'))
With this I can get the fig.tight_layout() only on the exported figure and restore the figure size to the default value set earlier.