Search code examples
pythonmatplotlibplotcurve

How to deal with the "pixelization" of overlapping curves in Matplotlib


I have the following problem: when I plot two or more curves (of the same linewidth) they look "pixelized" at the regions where they overlap. Here's an example:

x = np.linspace(0, np.pi, 100)
y1 = np.sin(x)
y2 = np.zeros(x.shape) 
y2[:51] = np.sin(x[:51])
y2[51:] = 2 - np.sin(x[51:])

fig, ax = plt.subplots(1, 1, figsize=(3,3))
ax.plot(x, y1, lw=4, color='k')
ax.plot(x, y2, lw=4, color='yellow')
plt.show()

enter image description here

To my understanding, this is happening because the pixels at the curve edges have some level of transparency which makes them more smooth-looking. However, there is this side effect in the case of overlapping curves: the edge-pixels of the first curve are visible through the edge-pixels of the second curve.

How to deal with this side effect? One idea is to increase the width of the last curve, however this solution is not ideal for me because I would like the curves to have exactly the same width at the regions where they do not overlap.


Solution

  • The effect you describe is called antialiasing. It's usually wanted to obtain smoother images. You can turn antialiasing off on a per artist basis. (However, not all artists really obey to the setting in every backend.)

    For the plot this could look like

    import numpy as np
    import matplotlib.pyplot as plt
    
    x = np.linspace(0, np.pi, 100)
    y1 = np.sin(x)
    y2 = np.zeros(x.shape) 
    y2[:51] = np.sin(x[:51])
    y2[51:] = 2 - np.sin(x[51:])
    
    fig, axes = plt.subplots(1,2, figsize=(6,3))
    for aa, ax in zip([True, False], axes.flat):
        ax.plot(x, y1, lw=4, color='k', antialiased=aa)
        ax.plot(x, y2, lw=4, color='yellow', antialiased=aa)
    plt.show()
    

    enter image description here

    As consequence when antialiasing is turned off, a pixel is either occupied by the respective color of the line, or not.