Skip to content

Adding colorbars to row subplots doesn't render the main plots when saving to .eps in 1.5.0 #5814

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
jklaise opened this issue Jan 8, 2016 · 9 comments
Assignees
Milestone

Comments

@jklaise
Copy link

jklaise commented Jan 8, 2016

I upgraded to matplotlib 1.5.0 and ran into a potential bug involving colorbars, subplots and saving to .eps for which the only workaround I found was to downgrade back to 1.4.3 where the problem doesn't exist.

Essentially, the .eps output gets corrupted when multiple subplots in a row array (e.g. 1x2) have colorbars added to them. This results in a blank canvas on the main plots of all heatmaps but the first one in the .eps output, whereas the .pdf output works as intended.

A minimal working example:

import matplotlib.pyplot as plt
import numpy as np

data = np.random.rand(100,100)

fig, ax = plt.subplots(1,2)
p1 = ax[0].pcolormesh(data)
p2 = ax[1].pcolormesh(data)

plt.colorbar(p1,ax=ax[0])
plt.colorbar(p2,ax=ax[1])

fig.savefig('test.pdf')
fig.savefig('test.eps')

These are the outputs (converted to .png, the top line in the .eps output in the second subplot is just an artefact from converting to .png):

.pdf:
alt text

.eps:
alt text

The problem persists when replacing pcolormesh with pcolor or imshow, using cax for colorbar axis instead of ax, changing colormaps, using row arrays of more subplots (for 1xn the last n-1 subplots have empty canvas), using gridspec to define subplots. The only thing that resolved this was to downgrade back to 1.4.3.

@jenshnielsen jenshnielsen added this to the Critical bugfix release (1.5.1) milestone Jan 8, 2016
@jenshnielsen
Copy link
Member

I can reproduce with 1.5.1rc1

By opening the file in inkscape I can see that the issue is the bbox of the colorbar. It extends well beyond the colorbar it self and is plotted on top of the image to the right.

@jenshnielsen
Copy link
Member

I think this is a bug in the rasterising code revealed by #4481

If I disable the rasterization it looks right:

import matplotlib.pyplot as plt
import numpy as np

data = np.random.rand(100,100)

fig, ax = plt.subplots(1,2)
p1 = ax[0].pcolormesh(data)
p2 = ax[1].pcolormesh(data)

cb = plt.colorbar(p1,ax=ax[0])
plt.colorbar(p2,ax=ax[1])

cb.solids.set_rasterized(False)
fig.tight_layout()
fig.canvas
fig.savefig('test.pdf')
fig.savefig('test.eps')

@mdboom
Copy link
Member

mdboom commented Jan 8, 2016

This comes from the fact that the Postscript file format doesn't support alpha blending. So when you have an image with transparent pixels, they come out as white.

I suppose the best thing to do here is to turn off the colorbar rasterization when using the Postscript backend... I'll try to work up a PR shortly.

@WeatherGod
Copy link
Member

but, why is the bounding box for the colorbar not constrained?

On Fri, Jan 8, 2016 at 12:25 PM, Michael Droettboom <
notifications@github.com> wrote:

This comes from the fact that the Postscript file format doesn't support
alpha blending. So when you have an image with transparent pixels, they
come out as white.

I suppose the best thing to do here is to turn off the colorbar
rasterization when using the Postscript backend... I'll try to work up a PR
shortly.


Reply to this email directly or view it on GitHub
#5814 (comment)
.

@mdboom
Copy link
Member

mdboom commented Jan 8, 2016

This is going to be tricky to fix. The code that turns on rasterizing of colorbars is ignorant of the backend in use (and probably should remain so). The Postscript backend should probably be fixed so that when the rasterized layer contains alpha it falls back to not rasterizing. But I don't think it can figure that out before it actually rasterizes, so then it would have to store and play back the backend calls...

I'd really like to deprecate the Postscript backend -- there are fewer and fewer cases where Postscript is required but PDF can't be used instead. But I know there still a few tools and workflows that need Postscript, so that's probably not realistic yet.

@mdboom
Copy link
Member

mdboom commented Jan 8, 2016

but, why is the bounding box for the colorbar not constrained?

I think the code that "minimizes" the image is somehow broken...

@WeatherGod
Copy link
Member

How about we focus on fixing that first to minimize the impact this bug has?

On Fri, Jan 8, 2016 at 12:35 PM, Michael Droettboom <
notifications@github.com> wrote:

but, why is the bounding box for the colorbar not constrained?

I think the code that "minimizes" the image is somehow broken...


Reply to this email directly or view it on GitHub
#5814 (comment)
.

@WeatherGod
Copy link
Member

I winder if this problem exists also for pcolormesh plots, or if it is
specific to colorbar objects?

On Fri, Jan 8, 2016 at 12:41 PM, Benjamin Root ben.v.root@gmail.com wrote:

How about we focus on fixing that first to minimize the impact this bug
has?

On Fri, Jan 8, 2016 at 12:35 PM, Michael Droettboom <
notifications@github.com> wrote:

but, why is the bounding box for the colorbar not constrained?

I think the code that "minimizes" the image is somehow broken...


Reply to this email directly or view it on GitHub
#5814 (comment)
.

@mdboom
Copy link
Member

mdboom commented Jan 8, 2016

It's for anything that's rasterized (in this particular case, just the colorbars). I have a fix that I'll post shortly.

mdboom added a commit to mdboom/matplotlib that referenced this issue Jan 8, 2016
The creation of the bounding box of actual image content is wrong.
@mdboom mdboom self-assigned this Jan 8, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants