Skip to content

Fixes Agg/Cairo antialiased rendering of contourf/pcolor/pcolormesh by using a blend group - #32256

Open
ayshih wants to merge 2 commits into
matplotlib:mainfrom
ayshih:fixes_using_blending
Open

Fixes Agg/Cairo antialiased rendering of contourf/pcolor/pcolormesh by using a blend group#32256
ayshih wants to merge 2 commits into
matplotlib:mainfrom
ayshih:fixes_using_blending

Conversation

@ayshih

@ayshih ayshih commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

PR summary

This PR fixes Agg/Cairo antialiased rendering of contourf/pcolor/pcolormesh by using a blend group (see #31162, where these fixes were separated out of). In the examples below, look at the right-most panel and see how the faint lines between antialiased patches are fixed by this PR. (The other panels are for showing why it is desirable to turn on antialiasing when alpha < 1.)

Since these fixes require #31162, this PR cannot be backported to 3.11.x.

contourf

import matplotlib
#matplotlib.use('TkCairo')

import numpy as np

import matplotlib.pyplot as plt

x = np.arange(1, 6)
y = x.reshape(-1, 1)
data = (x * y).astype(float)
data[2, 2] = np.nan

fig, axs = plt.subplots(1, 3, figsize=(5, 2), layout="constrained")

for i, antialiased in enumerate([None, False, True]):
    kwargs = {'cmap': 'jet', 'alpha': 0.5}
    if antialiased is not None:
        kwargs['antialiased'] = antialiased

    axs[i].contourf(data, levels=np.arange(1, 25, 1), extend="both", **kwargs)

    axs[i].set_aspect("equal")
    axs[i].set_axis_off()
    axs[i].set_title(f"antialiased={antialiased}")

plt.show()

Before this PR

1 before

After this PR

1 after

pcolor/pcolormesh

import matplotlib
#matplotlib.use('TkCairo')

import numpy as np

import matplotlib.pyplot as plt
from matplotlib.transforms import Affine2D

N = 5
data = np.arange(N**2, dtype=float).reshape((N, N))
data[2, 2] = np.nan

x, y = np.meshgrid(np.arange(N + 1), np.arange(N + 1))

rotation = Affine2D().rotate(1)

fig, axs = plt.subplots(2, 3, figsize=(5, 3.5), layout="constrained")

for i, antialiased in enumerate([None, False, True]):
    kwargs = {'cmap': 'jet', 'alpha': 0.5}
    if antialiased is not None:
        kwargs['antialiased'] = antialiased

    axs[0, i].pcolormesh(x, y, data, transform=rotation + axs[0, i].transData,
                         **kwargs)
    axs[1, i].pcolor(x, y, data, transform=rotation + axs[1, i].transData, **kwargs)

    for j in range(2):
        axs[j, i].set_aspect("equal")
        axs[j, i].set_axis_off()
    axs[0, i].set_title(f"antialiased={antialiased}")

plt.show()

Before this PR

2 before

After this PR

2 after

AI Disclosure

No AI was used

PR quality check

  • Use an expressive title, e.g. "Fix title font property precedence"
  • New and changed code is tested
  • [N/A] Plotting related features are demonstrated in an example
  • [N/A] New features and API changes have release notes
  • [N/A] Documentation complies with general and docstring guidelines

@ayshih
ayshih force-pushed the fixes_using_blending branch from 7741f0b to 3c1da25 Compare August 28, 2026 20:14
@ayshih
ayshih marked this pull request as ready for review August 28, 2026 20:35
@QuLogic QuLogic added this to the v3.12.0 milestone Aug 28, 2026
@QuLogic

QuLogic commented Aug 29, 2026

Copy link
Copy Markdown
Member

Would it make sense/work to apply this to all Collections?

@iccir

iccir commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Can you explain what exactly is happening and why it's fixed via a plus blend mode? I think that may have gotten buried in the other PR.

My first reaction was "this makes basic sense, but I need to look up the formula for Plus again."

@iccir iccir left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a comment about why "plus" was chosen, but there are also existing comments in the source base about this + intermediate buffers.

@rcomer

rcomer commented Aug 29, 2026

Copy link
Copy Markdown
Member

The pcolor docstring states

The default *antialiaseds* is False if the default
*edgecolors*\ ="none" is used. This eliminates artificial lines
at patch boundaries, and works regardless of the value of alpha.

Those artificial lines are now gone, so this explanation no longer makes sense. Should we change the default? The default for pcolormesh and contourfis alsoFalse, but I have not found statements about why for those.

@iccir

iccir commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Those artificial lines are now gone, so this explanation no longer makes sense. Should we change the default? The default for pcolormesh and contourfis alsoFalse, but I have not found statements about why for those.

I'm +1 on "default to the more-correct-looking option", unless there are other concerns.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants