pythonmatplotliblabelcontourf

Contour labels in filled contours wrong


In the example below I want to add contour labels to a filled contour. I do the same for regular contours, and the result seems to be correct. For the filled contours, however, the labels are off. Is this a bug or did I misunderstand something?

import matplotlib.pyplot as plt
import numpy

X,Z = numpy.meshgrid(range(5),range(5))
V = numpy.zeros([len(X),len(X[0])])
for kx in range(len(X[0])):
    for kz in range(len(X)):
        V[kz][kx] = X[kx][kz]


fig = plt.figure(figsize=(12,8))

ax1 = fig.add_subplot(121)
CS1 = ax1.contour(X,Z,V,range(5))
ax1.clabel(CS1,fontsize=16,colors='k')
cb1 = fig.colorbar(CS1)

ax2 = fig.add_subplot(122)
CS2 = ax2.contourf(X,Z,V,range(5))
ax2.clabel(CS2,fontsize=16,colors='k')
cb2 = fig.colorbar(CS2)

fig.savefig('contour')

enter image description here


Solution

  • The recent versions of Matplotlib have improved in this aspect. I ran your code on matplotlib 2.0.2, and got the following plots:

    import matplotlib.pyplot as plt
    import numpy
    
    X,Z = numpy.meshgrid(range(5),range(5))
    V = numpy.zeros([len(X),len(X[0])])
    for kx in range(len(X[0])):
        for kz in range(len(X)):
            V[kz][kx] = X[kx][kz]
    
    
    fig = plt.figure(figsize=(12,8))
    
    ax1 = fig.add_subplot(121)
    CS1 = ax1.contour(X,Z,V,range(5))
    ax1.clabel(CS1,fontsize=16,colors='k')
    cb1 = fig.colorbar(CS1)
    
    ax2 = fig.add_subplot(122)
    CS2 = ax2.contourf(X,Z,V,range(5))
    ax2.clabel(CS2,fontsize=16,colors='k')
    cb2 = fig.colorbar(CS2)
    
    fig.savefig('contour')
    

    enter image description here

    This certainly looks better but it doesn't solve the problem completely. We want the labels on the filled contour plot to look like the labels in the contour line plot. Now as tom pointed out, we can't do that easily since clabel is designed to work with contour and not contourf. There is a not-so-neat workaround for this. What we can do is to first create the contour plot, whose labels can be easily manipulated with clabel function and then we fill this plot using contourf.

    import matplotlib.pyplot as plt
    import numpy
    
    X,Z = numpy.meshgrid(range(5),range(5))
    V = numpy.zeros([len(X),len(X[0])])
    for kx in range(len(X[0])):
        for kz in range(len(X)):
            V[kz][kx] = X[kx][kz]
    fig = plt.figure(figsize=(12,8))
    
    ax1 = fig.add_subplot(121)
    CS1 = ax1.contour(X,Z,V,range(5))
    ax1.clabel(CS1,fontsize=16,colors='k')
    cb1 = fig.colorbar(CS1)
    
    ax2 = fig.add_subplot(122)
    CS2 = ax2.contour(X,Z,V,range(5)) # Creating the contour plot
    ax2.clabel(CS2,fontsize=16,colors='k')
    CS3 = ax2.contourf(X,Z,V,range(5)) # Creating another filled contour plot on top
    cb2 = fig.colorbar(CS3) # Display colorbar for filled contour plot
    
    fig.savefig('contour')
    

    enter image description here

    I would still like these labels to be centred in the different regions of the plot, but I couldn't find a way to do that.