Custom colormaps

Matplotlib color maps are really powerful, much more than the usual possibilities in other softwares. But they are quite difficult to understand, and most of the times, a simple list with intervals and colors is easier to work with:

from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
from osgeo import gdal
from numpy import linspace
from numpy import meshgrid
from matplotlib.colors import LinearSegmentedColormap

cmap1 = LinearSegmentedColormap.from_list("my_colormap", ((0, 0, 0), (1, 1, 1)), N=6, gamma=1.0)

map = Basemap(projection='tmerc', 
              lat_0=0, lon_0=3,
              llcrnrlon=1.819757266426611, 
              llcrnrlat=41.583851612359275, 
              urcrnrlon=1.841589961763497, 
              urcrnrlat=41.598674173123)

ds = gdal.Open("../sample_files/dem.tiff")
data = ds.ReadAsArray()

x = linspace(0, map.urcrnrx, data.shape[1])
y = linspace(0, map.urcrnry, data.shape[0])

xx, yy = meshgrid(x, y)

map.contourf(xx, yy, data, (400, 600, 800, 1000, 1200),cmap=cmap1)

plt.show()
  • The way to create the contourf plot is taken from the contourf example
  • The color map is created using the LinearSegmentedColormap.from_list static method. This method has the following arguments:
    1. The name given to the color map
    2. The color list. This is a list or sequence, each element containing three floats in the range 0 to 1, which are the red, green and blue values of the color
    3. N is the number of color levels to create. If the number is lower than the list of colors length, the list will be truncated If it’s longer, some colors will be repeated
  • In our example, the values will go from black to white, in six levels
  • The contourf is created forcing a level in each of the elements of the sequence
_images/cmap.png

GDAL includes an utility named gdaldem, that classifies a raster using the values defined in a file. The file format is originally used by the GRASS r.colors function. I like the format, since is really easy to understand and can be used from different software. Here’s how to read it and use it with basemap:

from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
from osgeo import gdal
from numpy import linspace
from numpy import meshgrid
from os.path import exists
from matplotlib.colors import LinearSegmentedColormap


def read_color_table(color_file):
    '''
    The method for reading the color file.
    '''
    colors = []
    levels = []
    if exists(color_file) is False:
        raise Exception("Color file " + color_file + " does not exist")
    fp = open(color_file, "r")
    for line in fp:
        if line.find('#') == -1 and line.find('/') == -1:
            entry = line.split()
            levels.append(eval(entry[0]))
            colors.append((int(entry[1])/255.,int(entry[2])/255.,int(entry[3])/255.))
       
    fp.close()

    cmap = LinearSegmentedColormap.from_list("my_colormap",colors, N=len(levels), gamma=1.0)
    
    return levels, cmap

levels, cmap = read_color_table("../sample_files/colorfile.clr")

map = Basemap(projection='tmerc', 
              lat_0=0, lon_0=3,
              llcrnrlon=1.819757266426611, 
              llcrnrlat=41.583851612359275, 
              urcrnrlon=1.841589961763497, 
              urcrnrlat=41.598674173123)

ds = gdal.Open("../sample_files/dem.tiff")
data = ds.ReadAsArray()

x = linspace(0, map.urcrnrx, data.shape[1])
y = linspace(0, map.urcrnry, data.shape[0])
xx, yy = meshgrid(x, y)

map.contourf(xx, yy, data, levels, cmap=cmap)

plt.show()
  • The function read_color_table opens and reads the color file, and returns the levels defined in the file, and a color map that has its color
    • Checks if some line is commented
    • The original values are in the range 0-255, and have to be converted to 0-1
    • The color map is created using the LinearSegmentedColormap.from_list static method
    • The function returns the levels and the color map so they can be used together or separately
  • contourf is used with the values defined in the file
_images/colortable2.png

The result if the levels are passed as an argument. Not all the colors are used, since some of them are defined out of the data range

_images/colortable.png

The result if the levels are not passed as an argument. The contourf method creates as many levels as number of colors of the cmap within the data values range