Discussion:
[Matplotlib-users] IPython's matplotlib inline magic is really magic? Actually it might resets axes bounds...
Ryan Nelson
2015-03-13 18:59:29 UTC
Permalink
I'm constructing a multi-plot figure using an IPython notebook (v3) and
matplotlib (v1.4.3) inline magic. I was manually setting the axes bounds,
and I ended up with something like the following:

########
import matplotlib.pyplot as plt
%matplotlib inline

bottom = 0.12
top = 0.9
left = 0.12
axwidth = (1-(left*2))/3

fig = plt.figure(figsize=(10,4))

ax1 = fig.add_axes((left, bottom, axwidth, top))
ax1.set_title('Title')
#ax1.tick_params(labelleft=False)

ax2 = fig.add_axes((left+axwidth, bottom, axwidth, top),
sharex=ax1, sharey=ax1)
ax2.tick_params(labelleft=False)

ax3 = fig.add_axes((left+axwidth*2, bottom, axwidth, top),
sharex=ax1, sharey=ax1)
ax3.tick_params(labelleft=False)

fig.savefig('junk.pdf', format='pdf')
fig.savefig('junk2.png')
#######

Obviously, the bottom+top that I've selected is >1, so the axes should go
off the top of the figure. (Stupid, I know...) The axes in both the PDF and
PNG formatted files are clipped by the top of the figure as you would
expect; however, the figure that is displayed in the Notebook looks just
fine. In addition, if you add a title to one of the axes, the figure in
IPython suddenly creates more space for the text. Maybe it is rearranging
the axes information behind the scenes?

I'm curious why this design decision was made. I would say this is a bug.
Now that I know about this behavior, I can easily fix it. But new users
will be baffled when their saved figure looks nothing like the displayed
figure in the notebook.

Ryan
Thomas Caswell
2015-03-13 20:03:20 UTC
Permalink
This is due to the fact that by default the inline backend saves the pngs
using `boundingbox_inches='tight'`. The design goal on the mpl side of
this kwargs was to trim off extra whitespace, but the way it is implemented
works just as effectively to expand to fit artists that fall outside of the
figure. I assume the choice to make this the default in inline was to
waste as little space as possible.

A possibly more reliable method to get the same effect is to use
`tight_layout` (see http://matplotlib.org/users/tight_layout_guide.html)

There was talk of replacing that implementation with a linear constraint
solver, but not much progress has been made in that direction (see
https://github.com/matplotlib/matplotlib/issues/1109)

Tom
Post by Ryan Nelson
I'm constructing a multi-plot figure using an IPython notebook (v3) and
matplotlib (v1.4.3) inline magic. I was manually setting the axes bounds,
########
import matplotlib.pyplot as plt
%matplotlib inline
bottom = 0.12
top = 0.9
left = 0.12
axwidth = (1-(left*2))/3
fig = plt.figure(figsize=(10,4))
ax1 = fig.add_axes((left, bottom, axwidth, top))
ax1.set_title('Title')
#ax1.tick_params(labelleft=False)
ax2 = fig.add_axes((left+axwidth, bottom, axwidth, top),
sharex=ax1, sharey=ax1)
ax2.tick_params(labelleft=False)
ax3 = fig.add_axes((left+axwidth*2, bottom, axwidth, top),
sharex=ax1, sharey=ax1)
ax3.tick_params(labelleft=False)
fig.savefig('junk.pdf', format='pdf')
fig.savefig('junk2.png')
#######
Obviously, the bottom+top that I've selected is >1, so the axes should go
off the top of the figure. (Stupid, I know...) The axes in both the PDF and
PNG formatted files are clipped by the top of the figure as you would
expect; however, the figure that is displayed in the Notebook looks just
fine. In addition, if you add a title to one of the axes, the figure in
IPython suddenly creates more space for the text. Maybe it is rearranging
the axes information behind the scenes?
I'm curious why this design decision was made. I would say this is a bug.
Now that I know about this behavior, I can easily fix it. But new users
will be baffled when their saved figure looks nothing like the displayed
figure in the notebook.
Ryan
------------------------------------------------------------
------------------
Dive into the World of Parallel Programming The Go Parallel Website,
sponsored
by Intel and developed in partnership with Slashdot Media, is your hub for
all
things parallel software development, from weekly thought leadership blogs
to
news, videos, case studies, tutorials and more. Take a look and join the
conversation now. http://goparallel.sourceforge.net/
_______________________________________________
Matplotlib-users mailing list
https://lists.sourceforge.net/lists/listinfo/matplotlib-users
Ryan Nelson
2015-03-13 23:00:40 UTC
Permalink
Thanks Tom.

Your hint led me to the following page:
https://github.com/ipython/ipython/blob/aab20bf85126f5b1da857193c446aebe6346acec/docs/source/whatsnew/version2.0.rst#other-changes
So it seems that this change is quite old, and I never noticed it before...
The suggestion on that page requires some incantation of the %config magic.
I tried this:
%config InlineBackend.print_figure_kwargs.bbox_inches = None
Which silently passes, but doesn't change the behavior.

Your rational for IPython's use of this kwarg by default is sound, and I
understand that there are valid use cases for it in some circumstances.
However, I still think this is problematic. I like MPL because you can make
a plot to your exact specifications -- but setting this kind of behavior by
default (without a well documented fix) feels a little "Microsoft
Office"-y... That being said, I really don't care all that much. IPython is
a fantastic tool. I'll just move my plotting code to a separate script and
tweak things there. (But then I won't be able to share the notebook with my
fancy plot embedded except as an external image. Can't have everything.)

I actually don't want any sort of 'tight' layout; however, just for
reference, the `tight_layout` function throws an error in my example.

Ryan
Post by Thomas Caswell
This is due to the fact that by default the inline backend saves the pngs
using `boundingbox_inches='tight'`. The design goal on the mpl side of
this kwargs was to trim off extra whitespace, but the way it is implemented
works just as effectively to expand to fit artists that fall outside of the
figure. I assume the choice to make this the default in inline was to
waste as little space as possible.
A possibly more reliable method to get the same effect is to use
`tight_layout` (see http://matplotlib.org/users/tight_layout_guide.html)
There was talk of replacing that implementation with a linear constraint
solver, but not much progress has been made in that direction (see
https://github.com/matplotlib/matplotlib/issues/1109)
Tom
Post by Ryan Nelson
I'm constructing a multi-plot figure using an IPython notebook (v3) and
matplotlib (v1.4.3) inline magic. I was manually setting the axes bounds,
########
import matplotlib.pyplot as plt
%matplotlib inline
bottom = 0.12
top = 0.9
left = 0.12
axwidth = (1-(left*2))/3
fig = plt.figure(figsize=(10,4))
ax1 = fig.add_axes((left, bottom, axwidth, top))
ax1.set_title('Title')
#ax1.tick_params(labelleft=False)
ax2 = fig.add_axes((left+axwidth, bottom, axwidth, top),
sharex=ax1, sharey=ax1)
ax2.tick_params(labelleft=False)
ax3 = fig.add_axes((left+axwidth*2, bottom, axwidth, top),
sharex=ax1, sharey=ax1)
ax3.tick_params(labelleft=False)
fig.savefig('junk.pdf', format='pdf')
fig.savefig('junk2.png')
#######
Obviously, the bottom+top that I've selected is >1, so the axes should go
off the top of the figure. (Stupid, I know...) The axes in both the PDF and
PNG formatted files are clipped by the top of the figure as you would
expect; however, the figure that is displayed in the Notebook looks just
fine. In addition, if you add a title to one of the axes, the figure in
IPython suddenly creates more space for the text. Maybe it is rearranging
the axes information behind the scenes?
I'm curious why this design decision was made. I would say this is a bug.
Now that I know about this behavior, I can easily fix it. But new users
will be baffled when their saved figure looks nothing like the displayed
figure in the notebook.
Ryan
------------------------------------------------------------
------------------
Dive into the World of Parallel Programming The Go Parallel Website,
sponsored
by Intel and developed in partnership with Slashdot Media, is your hub
for all
things parallel software development, from weekly thought leadership
blogs to
news, videos, case studies, tutorials and more. Take a look and join the
conversation now. http://goparallel.sourceforge.net/
_______________________________________________
Matplotlib-users mailing list
https://lists.sourceforge.net/lists/listinfo/matplotlib-users
Ryan Nelson
2015-03-14 02:52:27 UTC
Permalink
Okay. I figured out the problem. You need to pass a dictionary to the
config magic. Here is the relevant code:

%config InlineBackend.print_figure_kwargs = {'bbox_inches':None}

I created a PR with IPython (https://github.com/ipython/ipython/pull/8051)
to add this information to the %matplotlib documentation, so this doesn't
cause confusion for others.

Thanks to all the IPython and MPL devs for these great tools!
Ryan,
http://wrdrd.github.io/docs/consulting/data-science.html#data-visualization-tools
Post by Ryan Nelson
I'm constructing a multi-plot figure using an IPython notebook (v3) and
matplotlib (v1.4.3) inline magic. I was manually setting the axes bounds,
########
import matplotlib.pyplot as plt
%matplotlib inline
bottom = 0.12
top = 0.9
left = 0.12
axwidth = (1-(left*2))/3
fig = plt.figure(figsize=(10,4))
ax1 = fig.add_axes((left, bottom, axwidth, top))
ax1.set_title('Title')
#ax1.tick_params(labelleft=False)
ax2 = fig.add_axes((left+axwidth, bottom, axwidth, top),
sharex=ax1, sharey=ax1)
ax2.tick_params(labelleft=False)
ax3 = fig.add_axes((left+axwidth*2, bottom, axwidth, top),
sharex=ax1, sharey=ax1)
ax3.tick_params(labelleft=False)
fig.savefig('junk.pdf', format='pdf')
fig.savefig('junk2.png')
#######
Obviously, the bottom+top that I've selected is >1, so the axes should go
off the top of the figure. (Stupid, I know...) The axes in both the PDF and
PNG formatted files are clipped by the top of the figure as you would
expect; however, the figure that is displayed in the Notebook looks just
fine. In addition, if you add a title to one of the axes, the figure in
IPython suddenly creates more space for the text. Maybe it is rearranging
the axes information behind the scenes?
I'm curious why this design decision was made. I would say this is a bug.
Now that I know about this behavior, I can easily fix it. But new users
will be baffled when their saved figure looks nothing like the displayed
figure in the notebook.
Ryan
_______________________________________________
IPython-dev mailing list
http://mail.scipy.org/mailman/listinfo/ipython-dev
_______________________________________________
IPython-dev mailing list
http://mail.scipy.org/mailman/listinfo/ipython-dev
Loading...