Alexander Kurganskiy
Alexander Kurganskiy

Reputation: 51

Python matplotlib manual colormap

I have 2-d fields to plot in python using matplotlib basemap. The values of the fields varies from 0 to more than 1000. Is it possible to create manual colormap with fixed gradations and colours? It should looks like :

for values - set colour

I am a new in python. So, any suggestions are welcome.

Upvotes: 5

Views: 4740

Answers (2)

will
will

Reputation: 10650

Something like this should work:

from matplotlib import pyplot
from matplotlib.colors import LinearSegmentedColormap

def create_cmap(data, colours, stops=None):
    min_x = min(data)
    max_x = max(data)
    
    if stops is not None:
        min_x = min(min_x, min(stops))
        max_x = max(max_x, max(stops))
    
    if stops is None:
        d_x = (max_x - min_x)/(len(colours)-1)
        stops = [min_x + i*d_x for i in range(len(colours))]
    
    if min_x < min(stops):
        stops = [min_x] + stops
        colours = [colours[0]] + colours
        
    if max_x > max(stops):
        stops = stops + [max_x]
        colours = colours + [colours[-1]]
    
    stops = [(s-min_x)/(max_x-min_x) for s in stops]
    
    cmap_data = list(zip(stops, colours))
    cmap = LinearSegmentedColormap.from_list('continuous_map', cmap_data)
    
    def cmap_wrapper(x):
        x = max(min_x, min(x, max_x))
        x_n = (x-min_x)/(max_x-min_x)
        return cmap(x_n)
    
    return cmap_wrapper



colours = ['xkcd:white', 'xkcd:darkgreen', 'xkcd:lightgreen', 'xkcd:yellow', 'xkcd:brown', 'xkcd:orange', 'xkcd:coral', 'xkcd:crimson', 'xkcd:purple']
stops = [0, 1, 5, 10, 25, 50, 100, 500, 1000]

cmap = create_cmap(stops, colours, stops=stops)

fig = pyplot.figure(figsize=(10,10))
ax = fig.add_subplot(1,1,1)

for y in range(1000):
    ax.plot([0,1],[y,y],c=cmap(y))
    
pyplot.show()

enter image description here

Upvotes: 0

will
will

Reputation: 10650

This is exactly what you want.

The way you have to input it is a little confusing though, so this might be more helpful.

To get the greater than 1000 bit though, you'll need to mask the values above 1000, and have the rest of the scale go from 0-1000.

from matplotlib.colors import LinearSegmentedColormap
cMap = []
for value, colour in zip([0,1,5,10,25,50,100,500,1000],["White", "DarkGreen", "LightGreen", "Yellow", "Brown", "Orange", "IndianRed", "DarkRed", "Purple"]):
    cMap.append((value/1000.0, colour))

customColourMap = LinearSegmentedColormap.from_list("custom", cMap)

That is all you need to create your custom colormap. To use it just pass it into the plot function (whichever one you're using) as the named argument cmap

Here's what it looks like.enter image description here

Upvotes: 7

Related Questions