Skip to content

[Bug]: stackplot creates artifacts when height of input is zero #22393

Closed as not planned

Description

@tlkaufmann

Bug summary

In some cases, when a given input for stackplot has zero value entries, thin lines are drawn.

Code for reproduction

import numpy as np
import matplotlib.pyplot as plt

np.random.seed(42)
x = np.arange(10)
y0 = np.linspace(0, 1, 10)
y1 = np.linspace(0, 1, 10)
y2 = [0, 0, 0.25, 0, 0, 0, 0.25, 0, 0, 0]
y3 = np.linspace(0, 1, 10)


colors=['grey', 'blue', 'red', 'blue']

y = np.stack([y0, y1, y2, y3])
im = plt.stackplot(x, y, colors=colors, lw=0)

Actual outcome

image

One can see thin grey lines where the red object hast zero height.

Expected outcome

image

The thin lines are gone

Additional information

This only happens when the color above and below the empty data has the same color, but there are some use-cases where this is needed (see e.g. fish plots for evolutionary relationships).

Fix

The individual calls to fill_between need to have the following parameters:
where=(stack[i, :] != stack[i+1, :]), interpolate=True and edgecolor=color.

These are the changes made to matplotlib/lib/matplotlib/stackplot.py

    # Color between x = 0 and the first array.
    color = ax._get_lines.get_next_color()
    coll = ax.fill_between(x, 0, stack[0, :],
                                      where=(stack[0, :] != 0), interpolate=True, edgecolor=color,
                                     facecolor=color, label=next(labels, None), **kwargs)
    coll.sticky_edges.y[:] = [0]
    r = [coll]

    # Color between array i-1 and array i
    for i in range(len(y) - 1):
        color = ax._get_lines.get_next_color()
        r.append(ax.fill_between(x, stack[i, :], stack[i+1, :],  
                                               where=(stack[i, :] != stack[i+1, :]), interpolate=True, edgecolor=color,
                                               facecolor=color, label=next(labels, None), **kwargs))

These changes get rid of the lines but as far as I tested it do not have side effects for other plots. Probably one should check whether edgecolor is set in **kwargs as well.

Operating system

No response

Matplotlib Version

3.4.3

Matplotlib Backend

No response

Python version

No response

Jupyter version

No response

Installation

conda

Activity

  1. jklymak commented on Feb 4, 2022

    @jklymak
    Member

    I guess its a question of whether you want the zero-width stack to show up at all or not. I understand why you want to remove it, but I'm not sure if that is what folks who do stackplots want in general? (BTW< I'm sure the line is there even if both sides aren't blue, it just may not be as noticeable).

  2. tlkaufmann commented on Feb 4, 2022

    @tlkaufmann
    Author

    Good point. I also don't know what the standard stackplot user would want. Would be easy to make a parameter like show_empty for stackplot? If it defaults to False, it won't break any current use-cases.

    Either way, I don't think the current behavior is intended because the thin line prevails even if I set linewidth = 0. So we are not seeing the outline of the polygon but an artifact of the anti-aliasing. This can be shown as the thin line disappears when setting aa=False.

  3. jklymak commented on Feb 4, 2022

    @jklymak
    Member

    I agree its an anti aliasing artifact. I guess I'm mildly in favour of your change as fixing a display bug, unless there is some reason to fear it will be a lot slower. Did you want to open a PR?

  4. added a commit that references this issue on Feb 7, 2022
  5. tlkaufmann commented on Feb 7, 2022

    @tlkaufmann
    Author

    I opened a PR for this issue incorporating the fix detailed above: #22424

    Thanks for your help @jklymak

  6. reopened this on Feb 7, 2022
  7. jklymak commented on Feb 7, 2022

    @jklymak
    Member

    Let's leave open until the pr is in. Thanks.

  8. added a commit that references this issue on Feb 8, 2022
  9. added 2 commits that reference this issue on Apr 30, 2022
    67e3753
    f47d057
  10. github-actions commented on Nov 24, 2025

    @github-actions

    This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!

  11. timhoffm commented on Dec 7, 2025

    @timhoffm
    Member

    Carification of root cause: The underlying problem here is not drawing of a 0-range. You can test by hiding the red area in the above example (im[2].set_visible(False)), which does not change the plot.

    Instead it is that we have two filled regions (the blue ones in the exmaple) with adjacent edges, and since these polygons are rendered individually there can be antialiasing effects on the edge so that there may be a visual border even though the edges are perfectly aligned.

    I'm going to close this as won't fixt for the following reasons:

    • This is a fundamental rendering limitation that cannot be handled on our side. - It's the general problem of individual antialiased rendering two polygons that share an edge.
    • This will only be visible in stackplots if stack elements i and i+2 have the same color and element i has a 0-region. That should be quite an edge case.
    • With Consolidate style parameter handling for plotting methods that call other plotting methods #30808 it will be possible to draw finite edges with selected colors. Since edges of adjacent polygons are drawn on top of each other, this will fill any possible gaps in the rendering. So the workaround will be that you define finite edges for the blue areas.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    status: inactiveMarked by the “Stale” Github Action

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions