7

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:

Notebook displayed image

Savefig image:

enter image description here

Thomas K
  • 39,200
  • 7
  • 84
  • 86
PTooley
  • 383
  • 3
  • 11
  • okay, so having written this it strikes me that I can use `IPython.display.Image` as a workaround to save and then display. However, I would be interested to know if there is an answer that lets me actually control the behaviour of `plot.show()` – PTooley Jun 16 '16 at 16:42

2 Answers2

10

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.

PTooley
  • 383
  • 3
  • 11
4

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:

enter image description here

andrew
  • 3,929
  • 1
  • 25
  • 38
  • Thanks for pointing out that it is the ipython magics setting `bbox_inches='tight'`. Unfortunately doing the same for my output figure is not an option as it means my output is not guaranteed to be the size I want, but it does lead the the answer in the ipython docs. – PTooley Jun 17 '16 at 10:31
  • I tried changing the `rcParams` back to default after running the inline magic, but it still renders with the tight layout. If you find a solution please post it here. This seems to be an open problem. – andrew Jun 17 '16 at 17:54
  • Yes, it seems that the inline display magic has some of its own defaults and doesn't necessarily defer to the rcparams. (Presumably caching values for all the plt.savefig args and hence overriding whatever is in rcparams at each call.)I posted an answer with link to the relevant ipython docs. – PTooley Jun 20 '16 at 14:56