Skip to content

Horizontal lines in colorbars in PDF #5151

Closed

Description

@astrofrog

If I make a plot with e.g.

import numpy as np
import matplotlib.pyplot as plt

image = np.random.random([256, 256])

fig = plt.figure()
ax = fig.add_axes([0.1, 0.1, 0.4, 0.4])
im = ax.imshow(image, cmap=plt.cm.gist_heat)
fig.colorbar(im)
fig.savefig('test.pdf')

The colorbar can contain white horizontal lines:

screen shot 2015-09-26 at 10 25 28 pm

This actually becomes much more obvious when printing, as this can cause some kind of resonant/ringing pattern (I can send a photo of a printout if needed), and really makes the printed colorbar look bad.

Activity

  1. tacaswell commented on Sep 26, 2015

    @tacaswell
    Member

    This is a known issue with adjacent, but not overlapping rectangles. See http://matplotlib.org/api/pyplot_api.html?highlight=colorbar#matplotlib.pyplot.colorbar down towards the bottom.

  2. efiring commented on Sep 26, 2015

    @efiring
    Member

    Yes, this keeps coming up, but no one has proposed a really good solution; the problem is a function of the particular renderer. A partial solution is in master. Please give that a try and see what you think.

  3. tacaswell commented on Sep 26, 2015

    @tacaswell
    Member

    we have a partial fix in master?

  4. efiring commented on Sep 26, 2015

    @efiring
    Member

    Yes, I think so. If there are more than 50 colors, the colorbar is rasterized. #4481

  5. tacaswell commented on Sep 26, 2015

    @tacaswell
    Member

    Huh, I even reviewed it....

  6. QuLogic commented on Sep 29, 2015

    @QuLogic
    Member

    This is a known issue with adjacent, but not overlapping rectangles.

    How about just making them overlap? Have the lower values just a little bit taller than they should be and the upper values placed above so that the lower values are cropped at the right place. It's probably easier said than done though, or someone might have tried it already.

  7. efiring commented on Sep 29, 2015

    @efiring
    Member

    Workarounds like that tend to be difficult or impossible to get right in general. One of the problems is that they cause artifacts if alpha is less than one.

  8. jkseppan commented on Sep 29, 2015

    @jkseppan
    Member

    The pdf drawing model has gradient fills, so colorbars could be implemented with those instead of adjacent polygons. I guess it would be a nontrivial change, since we'd need to add a new fill type (or a new kind of artist) to matplotlib and implement it for all backends. I guess svg must have gradient fills, but how about agg?

  9. QuLogic commented on Sep 29, 2015

    @QuLogic
    Member

    Ah, I didn't know colorbars would allow transparency like that; it'd probably end up with the inverse problem. Actually, this idea was already mentioned in the colorbar documentation:

    It is known that some vector graphics viewer (svg and pdf) renders white gaps
    between segments of the colorbar. This is due to bugs in the viewers not
    matplotlib. As a workaround the colorbar can be rendered with overlapping
    segments::

        cbar = colorbar()
        cbar.solids.set_edgecolor("face")
        draw()
    

    However this has negative consequences in other circumstances. Particularly
    with semi transparent images (alpha < 1) and colorbar extensions and is not
    enabled by default see (issue #1188).

  10. efiring commented on Sep 29, 2015

    @efiring
    Member

    On 2015/09/28 7:07 PM, Jouni K. Seppänen wrote:

    The pdf drawing model has gradient fills, so colorbars could be
    implemented with those instead of adjacent polygons. I guess it would be
    a nontrivial change, since we'd need to add a new fill type (or a new
    kind of artist) to matplotlib and implement it for all backends. I guess
    svg must have gradient fills, but how about agg?

    A problem with this approach, apart from the added complexity, is that
    it is using a gradient to represent a discrete set of colors.
    Colormapping is done with a lookup table. By default it has 256
    entries, but it can have any number, from one on up. So if you are going
    to use a gradient, you still have to decide at what point to switch from
    the present discrete block representation to the gradient.

    Let's see if the workaround in #4481 is good enough.

  11. jkseppan commented on Sep 29, 2015

    @jkseppan
    Member

    On 29 Sep 2015, at 11:22, Eric Firing notifications@github.com wrote:

    A problem with this approach, apart from the added complexity, is that
    it is using a gradient to represent a discrete set of colors.

    The gradients in pdf are not required to be smooth or continuous. It’s of course another question how it gets rendered by any particular application, but I’m sure we could represent a stepwise colorbar as a pdf gradient. I don’t know enough about svg to say if it’s doable there.

  12. astrofrog commented on Sep 29, 2015

    @astrofrog
    ContributorAuthor

    Just out of curiosity, why not use imshow to plot the colorbar, with an array of dimension Nx1 where N is the number of colors in the colorbar?

  13. tacaswell commented on Sep 29, 2015

    @tacaswell
    Member

    There are also cases where the color regions in the color bar are not evenly spaced.

  14. added this to the milestone on Oct 8, 2015
  15. QuLogic commented on Nov 26, 2015

    @QuLogic
    Member

    Here's an interesting explanation of implementing PDF gradients in LibreOffice. SVG allows gradients that are defined by arbitrary stops, so I'd guess it'd be about the same.

  16. dstansby commented on Feb 21, 2017

    @dstansby
    Member

    This looks good to me on master - feel free to reopen if that's not the case.
    screen shot 2017-02-21 at 20 59 17

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