Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I have the following problem, I want to create my own colormap (red-mix-violet-mix-blue) that maps to values between -2 and +2 and want to use it to color points in my plot. The plot should then have the colorscale to the right.

That is how I create the map so far. But I am not really sure if it mixes the colors.

cmap = matplotlib.colors.ListedColormap(["red","violet","blue"], name='from_list', N=None)
m = cm.ScalarMappable(norm=norm, cmap=cmap)


That way I map the colors to the values.

colors = itertools.cycle([m.to_rgba(1.22), ..])


Then I plot it:

for i in range(0, len(array_dg)):
  plt.plot(array_dg[i], markers.next(),alpha=alpha[i], c=colors.next())


My problems are:
1. I can't plot the color scale.
2. I am not completely sure if my scale is creating a continues (smooth) colorscale.

share|improve this question
    
Could you clarify your question a bit? For example, c= specifies the line color, while you are talking about points. You can only specify one markerfacecolor, scatter might be a better option if you really want points. And indeed ListedColormap is listed, not continuous, see LinearSegmentedColormap. –  Rutger Kassies May 30 '13 at 11:44
    
That is strange, it is supposed to be points and it looks like points. –  Trollbrot May 30 '13 at 11:47
    
You can off course, but thats what you should clarify. We cant see what plot style you are using. If you use plt.plot(values, 'o'), you will plot only markers and no line, but the markers will have one fixed color which doesnt (and cant) vary by the value. –  Rutger Kassies May 30 '13 at 12:25

1 Answer 1

up vote 16 down vote accepted

There is an illustrative example of how to create custom colormaps here. The docstring is essential for understanding the meaning of cdict. Once you get that under your belt, you might use a cdict like this:

cdict = {'red':   ((0.0, 1.0, 1.0), 
                   (0.1, 1.0, 1.0),  # red 
                   (0.4, 1.0, 1.0),  # violet
                   (1.0, 0.0, 0.0)), # blue

         'green': ((0.0, 0.0, 0.0),
                   (1.0, 0.0, 0.0)),

         'blue':  ((0.0, 0.0, 0.0),
                   (0.1, 0.0, 0.0),  # red
                   (0.4, 1.0, 1.0),  # violet
                   (1.0, 1.0, 0.0))  # blue
          }

Although the cdict format gives you a lot of flexibility, I find for simple gradients its format is rather unintuitive. Here is a utility function to help generate simple LinearSegmentedColormaps:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors


def make_colormap(seq):
    """Return a LinearSegmentedColormap
    seq: a sequence of floats and RGB-tuples. The floats should be increasing
    and in the interval (0,1).
    """
    seq = [(None,) * 3, 0.0] + list(seq) + [1.0, (None,) * 3]
    cdict = {'red': [], 'green': [], 'blue': []}
    for i, item in enumerate(seq):
        if isinstance(item, float):
            r1, g1, b1 = seq[i - 1]
            r2, g2, b2 = seq[i + 1]
            cdict['red'].append([item, r1, r2])
            cdict['green'].append([item, g1, g2])
            cdict['blue'].append([item, b1, b2])
    return mcolors.LinearSegmentedColormap('CustomMap', cdict)


c = mcolors.ColorConverter().to_rgb
rvb = make_colormap(
    [c('red'), c('violet'), 0.33, c('violet'), c('blue'), 0.66, c('blue')])
N = 1000
array_dg = np.random.uniform(0, 10, size=(N, 2))
colors = np.random.uniform(-2, 2, size=(N,))
plt.scatter(array_dg[:, 0], array_dg[:, 1], c=colors, cmap=rvb)
plt.colorbar()
plt.show()

enter image description here


By the way, the for-loop

for i in range(0, len(array_dg)):
  plt.plot(array_dg[i], markers.next(),alpha=alpha[i], c=colors.next())

plots one point for every call to plt.plot. This will work for a small number of points, but will become extremely slow for many points. plt.plot can only draw in one color, but plt.scatter can assign a different color to each dot. Thus, plt.scatter is the way to go.

share|improve this answer
    
Thanks! That is pretty much what I wanted to do. These edicts confused me a lot. –  Trollbrot Jun 1 '13 at 16:39
    
Now I got a problem. I also would like to get a different marker symbol according to the color (I have 13 different colors). But the scatter plot allows only one marker per plot, or do I miss something? –  Trollbrot Jun 3 '13 at 14:41
    
In that case you will need to call plt.scatter (or plt.plot) once for each color/marker combination. –  unutbu Jun 3 '13 at 16:34
2  
@Ilya: First register the colormap: plt.register_cmap(name=rvb.name, cmap=rvb) and then call plt.set_cmap(rvb). –  unutbu Jan 25 at 11:00
1  
@As3adTintin: rvb above is a full-fledge Colormap, just like plt.cm.cool. So they are fungible: color = rvb(x/y). –  unutbu Oct 3 at 17:51

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.