Python: Convert an NCL colormap file to a Matplotlib colormap object#

Description

Sometimes you would like to continue using the colormaps from NCL in Python. This function can be used for this purpose, which reads an NCL RGB file and converts it into an Matplotlib colormap object.

For example the NCL colormap name ‘ncl_default’ points to the colormap file $NCARG_ROOT/lib/ncarg/colormaps/ncl_default.rgb

Software requirements

  • Python 3

  • numpy

  • matplotlib

Example script#

conv_cmap_ncl_to_mpl.py

def conv_cmap_ncl_to_mpl(colormap_file, extend='None'):
    '''Read an NCL RGB colormap file and convert it to a Matplotlib colormap object.
    
    For example the NCL colormap name "ncl_default" points to the colormap file 
    $NCARG_ROOT/lib/ncarg/colormaps/ncl_default.rgb
        
    Parameter:
        colormap_file    full path to NCL RGB colormap file
        extend           add one additional color (ncl-like)
    Returns:
        Returns a matplotlib.colors.ListedColormap object.

    2024 Meier-Fleischer, Deutsches Klimarechenzentrum (DKRZ), Germany
    '''
    import matplotlib.colors as colors
    from matplotlib.colors import ListedColormap

    #-- read the NCL colormap RGB file
    with open(colormap_file) as f:
        lines = f.read().splitlines()
        
    #-- skip unknown numer of not needed header lines
    tmp = [ x for x in lines if 'ncolors' not in x ]
    tmp = [ x for x in tmp if '#' not in x ]
    tmp = [ x for x in tmp if ';' not in x ]
    tmp = [ x for x in tmp if x != '']

    #-- get the RGB values
    i = 0
    for l in tmp:
        new_array = np.array(l.split()).astype(float)
        if i == 0:
            color_list = new_array
        else:
            color_list = np.vstack((color_list, new_array))
        i += 1
        
    #-- make sure that the RGB values are within range 0 to 1
    if (color_list > 1.).any(): color_list = color_list / 255

    #-- add alpha-channel
    alpha = np.ones((color_list.shape[0],4))
    alpha[:,:-1] = color_list
    color_list = alpha

    #-- define the under, over, and bad colors
    under = color_list[0,:]
    over  = color_list[-1,:]
    bad   = [0.5, 0.5, 0.5, 1.]

    #-- convert to Colormap object
    if extend == 'ncl':
        cmap = ListedColormap(color_list[1:-1,:])
    else:
        cmap = ListedColormap(color_list)
    cmap.set_extremes(under=color_list[0], bad=bad, over=color_list[-1])

    return cmap