Search code examples
pythonmatplotlibscalecontour

How do I change contour color plot to make it more readable?


I want to make a contour plot, with a specific contour line using matplotlib, the important piece of code is the following:

levels = [-5, -3,-2,-1, 0,1, 2,5,10,17.5]
cax = ax1.contourf(X,Y,Z,levels)
#some similar code

In the end, is scale of the contour plot is the on the following picture, however, I don't like that the contour between (-5,0) becomes only variants of dark blue and purple, How can I make the colour scale more varied, without needing to change the scale?

enter image description here


Solution

  • enter image description here

    There are several things that could help you

    1. use a different colormap (e.g., cm.PRGrn)
    2. use ax.contour(...) to draw contour lines across the boundaries of different levels
    3. do not use ax.contourf(...) at all, but a combination of ax.imshow(...) and ax.contour(...), as it's shown in the right subplot; note the differences in the two colorbars.

    This is the code used to produce the figure at the top.
    Matplotlib's example recommends using the exact levels that are recomputed in the filled contour object; note also extend='both' in ax.contourf's parameters.

    The code for ax.imshow is relatively straightforward, note the use of extent to have correct axis limits, origin='lower' to have the y axis going upwards, and the (optional) use of TwoSlopeNorm to have the colormap centered about zero and extending to the data extremes.

    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib.cm import PRGn
    from matplotlib.colors import TwoSlopeNorm
    
    x = y = np.linspace(-2, 2, 81)
    X, Y = np.meshgrid(x, y)
    Z = 5*X + 4*Y + 4 - 2
    
    levels = [-5, -3, -2, -1, 0, 1, 2, 5, 10, 17.5]
    extent = (-2, 2, -2, 2)
    
    fig, (ax0, ax1) = plt.subplots(1, 2, figsize=(10, 4), layout='constrained')
    
    cf0 = ax0.contourf(X, Y, Z, levels=levels, cmap=PRGn, extend='both')
    cc0 = ax0.contour( X, Y, Z, levels=cf0.levels, colors='k')
    cl0 = ax0.clabel(cc0)
    cb0 = fig.colorbar(cf0, ax=ax0)
    ax0.set_aspect(1)
    
    im1 = ax1.imshow(Z, extent=extent, origin='lower', cmap=PRGn, norm=TwoSlopeNorm(0))
    cc1 = ax1.contour(Z, levels, colors='k', origin='lower', extent=extent)
    cl1 = ax1.clabel(cc1)
    cb1 = fig.colorbar(im1, ax=ax1)
    
    plt.show()