dMb
dMb

Reputation: 9367

custom color map for pcolor

I'm following the documentation for creating a custom color map. The map I want looks like this:

enter image description here

Here's the dictionary I came up with:

   cdict = {'red':   ((0.00,  0.0, 0.0),
               (0.25,  1.0, 0.0),
               (0.50,  0.0, 0.0),
               (0.75,  1.0, 0.0),
               (1.00,  1.0, 0.0)),

     'green': ((0.00,  0.0, 0.0),
               (0.25, 1.0, 1.0),
               (0.50, 1.0, 1.0),
               (0.75, 1.0, 1.0),
               (1.00,  0.0, 0.0)),

     'blue':  ((0.00,  1.0, 1.0),
               (0.25,  0.0, 0.0),
               (1.00,  0.0, 0.0))
    }

But it's not giving me the results I want. For example, value 0.5 is rendered using red.

Here's what the rest of code looks like:

cmap = LinearSegmentedColormap('bgr', cdict)
plt.register_cmap(cmap=cmap)

plt.pcolor(dist, cmap='bgr')
plt.yticks(np.arange(0.5, len(dist.index), 1), dist.index)
plt.xticks(np.arange(0.1, len(dist.columns), 1), dist.columns, rotation=40)

for y in range(dist.shape[0]):
    for x in range(dist.shape[1]):
        plt.text(x + 0.5, y + 0.5, dist.iloc[y,x],
                 horizontalalignment='center',
                 verticalalignment='center', rotate=90
                 )
plt.show()

Here's a sample of the rendered heatmap:

enter image description here

What am I missing?

Upvotes: 1

Views: 1580

Answers (2)

Ajean
Ajean

Reputation: 5669

The reason that 0.5 is showing up as red in your plot is likely just because your vmin and vmax are not 0.0 and 1.0. Most matplotlib 2D plotting routines set vmax to the maximum value in the array by default, which looks like it is 0.53 in your case. If you want 0.5 to be green, set vmin=0.0, vmax=1.0 in the call to pcolor.

Your colormap dict is nearly correct, but as you have it now there are hard transitions to yellow/green at the 0.25 and 0.75 points, you should change those lines in 'red' from

           (0.25,  1.0, 0.0),
           (0.50,  0.0, 0.0),
           (0.75,  1.0, 0.0),

to

           (0.25,  1.0, 1.0),
           (0.50,  0.0, 0.0),
           (0.75,  1.0, 1.0),

to get the colorscale you want. This is the result:

corrected colorscale

Upvotes: 1

Bart
Bart

Reputation: 10308

It seems that your color dictionary is wrong. For example, the first entry for the start of the colormap is:

'red':   (0.00,  0.0, 0.0)
'green': (0.00,  0.0, 0.0)
'blue':  (0.00,  1.0, 1.0)

which gives RGB = 001 = blue. Also, I'm not sure how LinearSegmentedColormap is going to behave when some intervals (like index 0.5 in blue) are undefined.

This seems to give the correct results:

import numpy as np
import matplotlib.pyplot as pl
from matplotlib.colors import LinearSegmentedColormap

pl.close('all')

cdict = {
  'red':   ((0.00, 1.0, 1.0),
            (0.25, 1.0, 1.0),
            (0.50, 0.0, 0.0),
            (0.75, 1.0, 1.0),
            (1.00, 0.0, 0.0)),

  'green': ((0.00, 0.0, 0.0),
            (0.25, 1.0, 1.0),
            (0.50, 1.0, 1.0),
            (0.75, 1.0, 1.0),
            (1.00, 0.0, 0.0)),

  'blue':  ((0.00, 0.0, 0.0),
            (0.25, 0.0, 0.0),
            (0.50, 0.0, 0.0),
            (0.75, 0.0, 0.0),
            (1.00, 1.0, 1.0))
}

cm_rgb = LinearSegmentedColormap('bgr', cdict)

pl.figure()
pl.imshow(np.random.random((20,20)), interpolation='nearest', cmap=cm_rgb)
pl.colorbar()

See the matplotlib docs for documentation of LinearSegmentedColormap.

enter image description here

Upvotes: 0

Related Questions