Matplotlib: Save figure as file from iPython notebook

66,977

Solution 1

Problem solved: add 'bbox_inches='tight' argument to savefig.

import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_axes([1,1,1,1])
plt.plot([1,2])

savefig('test.png', bbox_inches='tight')

I don't understand what's happening here, but the file looks like the iPython notebook inline file now. Yay.

Solution 2

Actually, the savefig is working properly. When you call add_axes, your list specifies a rectangle: [left, bottom, width, height]. Since the figure goes from 0 to 1 on both axes with the origin at the bottom left, you're making a rectangle of width and height 1 starting from the very top-right of the figure. You likely want to be doing ax = fig.add_axes([0,0,1,1]).

I'm not sure why the inline plot doesn't respect where you've placed the axes. If I had to guess, I would say that the inline backend automatically figures out the bounding box and places the inline figure according to that.

Share:
66,977
Martin Preusse
Author by

Martin Preusse

Updated on October 10, 2020

Comments

  • Martin Preusse
    Martin Preusse over 3 years

    I am trying to save a Matplotlib figure as a file from an iPython notebook.

    import matplotlib.pyplot as plt
    
    fig = plt.figure()
    ax = fig.add_axes([1,1,1,1])
    ax.plot([1,2])
    
    fig.savefig('test.png')
    

    The inline view in the iPython notebook looks good:

    Inline view of figure in iPython notebook


    The file 'test.png' is almost empty though. It looks like the plot is shifted to the top right, you can see the tick labels '1.0' and '0.0' in the corner.

    test.png

    How can I produce a file from the iPython notebook that looks like the inline view?

  • Rutger Kassies
    Rutger Kassies over 10 years
    But it shouldn't be happening at all, so it might still be worth finding out whats your issue.
  • Martin Preusse
    Martin Preusse over 10 years
    Good point. Here's what the docs say about 'bbox_inches': "Bbox in inches. Only the given portion of the figure is saved. If ‘tight’, try to figure out the tight bbox of the figure." I kind of don't get it.
  • Rutger Kassies
    Rutger Kassies over 10 years
    Normal behavior often has a very wide white border around the axes, tight tries to minimize that. Its not really related to your issue i think. But only by using tight, the correct "figure area" is determined, but that doesn't tell (me) much on why it is wrong in the first place.
  • Martin Preusse
    Martin Preusse over 10 years
    Me neither :) What I figured out so far is that it works when I only do 'plt.plot([1,2]) plt.savefig('file.png')' and don't define the fig = plt.figure() and ax = fig.add_axes(). So I assume it has something to do with the settings on the figure or axes. It's also not an iPython or notebook issue. Same behavior in iPython console and plain Python script.
  • Martin Preusse
    Martin Preusse over 10 years
    When I do "ax = fig.add_axes([0,0,1,1])" everything outside of the actual axes is cut off. When I move everything up with "ax = fig.add_axes([0.1,0.1,1,1])" the top and right part of the plot are missing. Even if I combine it with a 'figsize' some parts are always cut off. With "bbox_inches='tight'" everything is nicely placed. I don't really understand what number sets what, docs don't help.
  • tbekolay
    tbekolay over 10 years
    In general, you shouldn't be creating your own axes with .make_axes; you should let Matplotlib handle that itself. Your example could be done with plt.plot([1,2]); plt.savefig('test.png'). Adding axes manually is an advanced thing that you would do if you need precise placement of axes; in most cases, however, you should just let Matplotlib do its thing, and use plt.tight_layout() when things go wrong.
  • Martin Preusse
    Martin Preusse over 10 years
    In the real life case I use 'imshow' and all the examples I found use axes. Strange, I think I need to get my head around this plotting logic ;)