Search code examples
pythonplotcolorscolormap

Creating a colormap in Python with a specific transition between two regions


I am trying to create a colormap in Python for coloring a map of the world. As such, I want there to be a distinct difference in color between ocean and land, and I am trying to create a colormap for this, but I and stuck on how to make the transition between the two work correctly.

My code is something like this:

vmin1 = -12000
vmax1 = 9000

vmax2 = int(np.round(256/(np.abs(vmin1)/np.abs(vmax1)+1)))
vmin2 = int(np.round((256-vmax2)))

cmap = cm.ocean.copy()
colors1 = cmap(np.linspace(0.25, 0.85, vmin2))
cmap = ListedColormap(colors1)
colors = ['yellowgreen', 'goldenrod', 'maroon', 'white']
nodes = [0.0, 0.05, 0.3, 1.0]
cmap = LinearSegmentedColormap.from_list('cm', list(zip(nodes,     colors)))
colors2 = cmap(np.linspace(0, 1, vmax2))
cmap = ListedColormap(np.concatenate((colors1, colors2)))

This creates a nice colormap which looks like this:

cmap

This combines two different colorschemes, the built-in 'ocean' colormap and the ['yellowgreen', 'goldenrod', 'maroon', 'white'] scheme that will be used for land. The problem is that this colormap is not centered on a depth of zero, meaning that a lot of shallow ocean is colored as if it was land. Is there a way to make a colormap be centered on a specific value so that everything above zero is colored with one part of the colormap and everything below zero is colored with another? Thanks for any help!


Solution

  • I might not have understood your question correctly, but your way of building the colormap is good, as long as you specify vmin and vmax when creating the colormap.

    After having built the colormap, you can use it with

    import matplotlib.pyplot as plt
    
    data = np.random.rand(20, 3) * (vmax1 - vmin1) + vmin1 
    plt.figure()
    plt.scatter(data[:, 0], data[:, 1], c=data[:, 2], 
                cmap=cmap, 
                vmin = vmin1, 
                vmax = vmax1
                )
    plt.colorbar(orientation="horizontal")
    plt.show()
    

    which results in Toy example with colorbar

    and you will have all the points with negative X coordinate (arbitrary choice of mine) in ocean color and the points with positive X coordinate in land colors.

    I do not get if this is the (non) answer to the question, or if you are looking for the ocean-to-yellow transition to be at the center of the colormap and also to correspond to a value of 0 in the data.