Skip to content

multiple imshow in figure are rendered as single image in svg, causing problems when clipping images #7151

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
luca-penasa opened this issue Sep 21, 2016 · 11 comments
Milestone

Comments

@luca-penasa
Copy link

I am on matplotlib 1.5.1 (but i suppose this is not related with this specific version)
This is probably a bug/limit of the svg export engine (maybe known?)

when multiple calls to imshow are made in the same figure and then saved in svg ALL the calls are joined into a single raster instead of having multiple (e.g. grouped) images in the svg file.

This make fail a simple test case like this. We call two times imshow to position two images in the figure, then we clip the two images with two different shapes. The problem is that in the svg the two imshow calls are joined in an unique raster, thus the clips are simply not created at all in the svg. Exporting each imshow() raster as a separated image in the svg, each with their clips, would probably solve the problem.
Is it possible or is a known limit?

if saved as png:
test

and as svg:
test_svg

Code for generating these pictures (for a notebook):

%pylab inline

import matplotlib

pylab.rcParams['figure.figsize'] = (8, 8)

a = np.random.randn(100,100)
b = np.random.randn(100,100)

im1 = imshow(a, extent = [0,1,0,1])
im2 = imshow(b, extent = [1.2,2.2,1.2,2.2])
xlim(0,2.2)
ylim(0,2.2)

from matplotlib.path import Path
verts1 = np.array([[0.5,0.5],[1,0.5],[1,1], [0,0.5], [0.5,0.5]])
path1 = Path(verts1)
path2 = Path(verts1 + np.array([1.1, 1.2]))


import matplotlib.patches as patches
patch1 = patches.PathPatch(path1, facecolor=None, alpha=0)
gca().add_patch(patch1)

patch2 = patches.PathPatch(path2, facecolor=None, alpha=0)
gca().add_patch(patch2)

im1.set_clip_path(patch1)
im2.set_clip_path(patch2)

savefig("test.png")
savefig("test.svg")

many thanks for the wonderful work 👍

Luca

@luca-penasa luca-penasa changed the title multiple imshow in image are rendered as single image in svg, causing problems when clipping images multiple imshow in figure are rendered as single image in svg, causing problems when clipping images Sep 21, 2016
@WeatherGod
Copy link
Member

By default, we composite images for output to vector graphics formats. I
think if you set the rcParam "image.composite_image" to False, you'll get
what you want.

On Wed, Sep 21, 2016 at 5:39 AM, Luca notifications@github.com wrote:

I am on matplotlib 1.5.1 (but i suppose this is not related with this
specific version)
This is probably a bug/limit of the svg export engine (maybe known?)

when multiple calls to imshow are made in the same figure and then saved
in svg ALL the calls are joined into a single raster instead of having
multiple (e.g. grouped) images in the svg file.

This make fail a simple test case like this. We call two times imshow to
position two images in the figure, then we clip the two images with two
different shapes. The problem is that in the svg the two imshow calls are
joined in an unique raster, thus the clips are simply not created at all in
the svg. Exporting each imshow() raster as a separated image in the svg,
each with their clips, would probably solve the problem.
Is it possible or is a known limit?

if saved as png:
[image: test]
https://cloud.githubusercontent.com/assets/2051141/18705379/5899d41a-7fee-11e6-98e2-f23301c3ca99.png

and as svg:
[image: test_svg]
https://cloud.githubusercontent.com/assets/2051141/18705418/7c65874a-7fee-11e6-83ec-46ccd41fb464.png

Code for generating these pictures (for a notebook):

%pylab inline
import matplotlib

pylab.rcParams['figure.figsize'] = (8, 8)

a = np.random.randn(100,100)
b = np.random.randn(100,100)

im1 = imshow(a, extent = [0,1,0,1])
im2 = imshow(b, extent = [1.2,2.2,1.2,2.2])
xlim(0,2.2)
ylim(0,2.2)
from matplotlib.path import Path
verts1 = np.array([[0.5,0.5],[1,0.5],[1,1], [0,0.5], [0.5,0.5]])
path1 = Path(verts1)
path2 = Path(verts1 + np.array([1.1, 1.2]))

import matplotlib.patches as patches
patch1 = patches.PathPatch(path1, facecolor=None, alpha=0)
gca().add_patch(patch1)

patch2 = patches.PathPatch(path2, facecolor=None, alpha=0)
gca().add_patch(patch2)

im1.set_clip_path(patch1)
im2.set_clip_path(patch2)

savefig("test.png")
savefig("test.svg")

many thanks for the wonderful work 👍

Luca


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
#7151, or mute the thread
https://github.com/notifications/unsubscribe-auth/AARy-Fgi73j33fOJka7T32i2BnBygARKks5qsPtrgaJpZM4KCmHm
.

@luca-penasa
Copy link
Author

cool!
This totally solves the problem!
Thank you a lot, maybe it should be the default behaviour given it causes a different output for svg and png?

Many thanks and feel free to close the ticket!

@QuLogic
Copy link
Member

QuLogic commented Sep 21, 2016

Is this really not a bug? Compositing is an optimization, but it shouldn't break things in alternate formats.

@Kojoley
Copy link
Member

Kojoley commented Sep 21, 2016

Is this really not a bug? Compositing is an optimization, but it shouldn't break things in alternate formats.

I was wondering about this too.

And this is true not only for svg (tested pdf and it is affected).

@tacaswell tacaswell reopened this Sep 21, 2016
@tacaswell tacaswell added this to the 2.0.1 (next bug fix release) milestone Sep 21, 2016
@tacaswell
Copy link
Member

probably should detect if the artist have non-trivial clipping and if so, opt them out of the optimization.

The only place the compositing really helps you if you have many overlapping images, in the OPs case it might have been hurting (independent of the clipping bug!).

@tacaswell
Copy link
Member

Which is a long way of saying, flipping this to off by default might be a reasonable thing to do

@mdboom @efiring do you know the history of this?

@QuLogic
Copy link
Member

QuLogic commented Sep 21, 2016

Also of note is that there was a significant image infrastructure rewrite, so we should check what happens with 2.x and/or master.

@efiring
Copy link
Member

efiring commented Sep 21, 2016

I think it goes way back, but I don't remember whether it was put in by JDH or by Mike.

@efiring
Copy link
Member

efiring commented Sep 21, 2016

https://github.com/matplotlib/matplotlib/blame/v0.91.2/lib/matplotlib/axes.py
If you use git blame and look for "composite" you will see that this logic in the draw method is old. It might have been put in because postscript doesn't handle alpha, so if we wanted composited images with alpha, we had to do it ourselves. This is still true, of course. At the time, it would also have been true for some other backends that we no longer support.

@luca-penasa
Copy link
Author

In my opinion, given changing default behaviours is always risky, better documenting this might be a good starting point. My problem wasn't actually the behaviour of the svg compositing engine, but that I was not able to find the right switch to turn for solving the problem. Even if you google "image.composite_image" you see how much is difficult to get what it does. #2517 btw is the same.

An example in the cookbook or similar with the right keywords, pointing to this and other issues, will definitively help. Or even add better info into the doc (?)
Maybe the info are there but I had difficult times finding them...

said that a default option which creates discrepancies between format outputs maybe should be investigated better

Thanks again everybody for this great library 👍

Luca

@QuLogic QuLogic modified the milestones: 2.0.1 (next bug fix release), 2.0.2 (next bug fix release) May 3, 2017
@tacaswell tacaswell modified the milestones: 2.1.1 (next bug fix release), 2.2 (next feature release) Oct 9, 2017
yoda-vid added a commit to sanderslab/magellanmapper that referenced this issue Nov 6, 2020
…ics output

Compositing is turned on by default in Matplotlib, which appears to cause images with multiple layers exported to PDF to merge these layers (see matplotlib/matplotlib#7151). Turn off this setting in the default theme.
@QuLogic
Copy link
Member

QuLogic commented Mar 9, 2023

This was fixed by #19375 in 3.5.0.

@QuLogic QuLogic closed this as completed Mar 9, 2023
@QuLogic QuLogic modified the milestones: future releases, v3.5.0 Mar 9, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants