Skip to content

Saving as a pdf ignores set_clip_path when there is more than one of them. #18499

Closed

Description

@FlorentinJ

I am trying to plot some curves with variable width and opacity. To do this I first plot a background image with the correct color, which I then clip using patches.

It works perfectlty, except when I try to export the result as a PDF, where all clipping information is lost if I try to draw more than one curve. There is no problem when exporting to PNG or with the inline viewer.

Code for reproduction

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import PathPatch

fig, ax = plt.subplots()
X = np.linspace(0, 1, 100)

# green curve, rgba = (0, 1, 0, x)
im1 = ax.imshow([np.array((np.zeros_like(X), np.ones_like(X), np.zeros_like(X), X)).transpose()],
                 aspect=0.5, extent=[0, 1, 0, 1.5])
paths1 = ax.fill_between(X, X**2, X**2+0.5, facecolor='none', lw=2)
patch1 = PathPatch(paths1._paths[0], visible=False)
ax.add_patch(patch1)
im1.set_clip_path(patch1)

# red curve, rgba = (1, 0, 0, x)
im2 = ax.imshow([np.array((np.ones_like(X), np.zeros_like(X), np.zeros_like(X), X)).transpose()],
                 aspect=0.5, extent=[0, 1, 0, 1.5])
paths2 = ax.fill_between(X, 1.5-X**2, 1-X**2, facecolor='none', lw=2)
patch2 = PathPatch(paths2._paths[0], visible=False)
ax.add_patch(patch2)
im2.set_clip_path(patch2)

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

PNG output
image

PDF output
image

If I only try to plot a single curve, then everything works as expected.

Is this linked to a known issue?
Does anyone have a workaround?

Many thanks.

Matplotlib version

  • Operating system: Windows 10 or Cygwin (first discovered on a SageMath install, but reproduced in a pure python environment)
  • Matplotlib version: 3.3.1 and 2.2.4
  • Matplotlib backend: module://ipykernel.pylab.backend_inline
  • Python version: 3.8.5 and 3.7.3
  • Jupyter version (if applicable): jupyterlab 2.2.6 and 2.2.0

Activity

  1. added this to the v3.4.0 milestone on Sep 16, 2020
  2. jklymak commented on Sep 16, 2020

    @jklymak
    Member

    I agree this is a bug, at least on Preview as well. Someone would have to dig into the pdf spec and figure out why this breaks. BTW, its worth noting that this works fine with just one curve, so Artist clipping works for PDF, but two clips are not allowed.

  3. anntzer commented on Sep 16, 2020

    @anntzer
    Contributor

    This actually affects all vector backends, and comes from image._draw_list_compositing_images, which completely fails to take image clipping into account (it only accounts for clipping of the parent axes/figure). My guess is that the simple solution is to just disable precompositing whenever custom clips are sets on the images, something along the lines of not_composite = ... or any(artist.get_clip_rectangle() is not None or artist.get_clip_path() is not None for artist in artists).

  4. modified the milestones: v3.4.0, v3.5.0 on Jan 27, 2021
  5. Jhsmit commented on Feb 3, 2021

    @Jhsmit

    After a few futile attempt to install matplotlib from source to try the PR I found a stackoverflow post with a solution for my issue:

    plt.rcParams["image.composite_image"] = False
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions