# Specific cmap

 2 Hello, How would I create a specific cmap, which would have a separate color value for each matrix value? For example, could I make a cmap that specifies 0:'red', 1:'green', 2:'yellow', etc? The linear interpolation cmaps don't work as I want them to because they normalize to the given range of the matrix. Thank you. asked Dec 19 '10 Eviatar Bach 474 ● 2 ● 10 ● 26 kcrisman 6639 ● 13 ● 66 ● 150

 2 I seem to recall once having a slick workaround for this but for the life of me I can't find it now. Anyway, something like this should get the job done: # preamble import matplotlib # choose our preferred colour scheme, where None describes the exceptions cdict = {0: 'red', 1: 'green', 2:'yellow', 3:'orange', 43+2*I: 'brown', None: 'purple'} # choose some fixed order -- doesn't matter what -- for iterating the keys ckeys, cvals = zip(*cdict.items()) # build a mapping function to turn the matrix elements into integers # (would be faster to use a dict for lots of colours) cmap_fn = lambda x: Integer(ckeys.index(x if x in cdict else None)) # generate a colormap with exactly the colours we want, in the right order my_cmap = matplotlib.colors.ListedColormap(cvals) # generate a test matrix m = Matrix(lambda i,j: (i+j) if (i,j) != (6,6) else 43+2*I, nrows=10) # plot it: apply the mapping function to the matrix and feed matrix_plot our colour map matrix_plot(m.apply_map(cmap_fn), cmap=my_cmap)   This should generate one very ugly graph: one red cell, two green cells, three yellow cells, four orange cells, and a brown cell at (6,6) in a purple sea. It's easy to bundle this into a function if you find yourself doing it frequently. [update: modified to make it slightly more general: now you don't need any ordering relation defined on the matrix elements] posted Dec 20 '10 DSM 4802 ● 12 ● 61 ● 103 Will that work even with Sage #s, like $4.3+2*I$? kcrisman (Dec 20 '10) This is exactly what I wanted! Thank you! This should be built in to Sage. Eviatar Bach (Dec 20 '10)@kcrisman: yes, you just have to be careful to make sure that the matrix element still has the same type as [well, no, just 'still compares equal to'] the cdict key, else the cmap_fn will fail to find a match and fall back to the None colour. DSM (Dec 20 '10) I've updated the relevant ticket to put this as an enhancement. DSM may want to put his/her real name on there to get some credit if this ever makes it into Sage, which seems like a good idea. kcrisman (Dec 21 '10)
 2 Well, after writing this, I finally found out that we have this capability, though there are no examples in the matrix_plot doc (though it's mentioned). sage: matrix_plot(matrix([[0,1],[1,2]]),cmap=['red','green','blue'])  This relies on get_cmap, a very nice utility I had forgotten about! Read this: sage: sage.plot.matrix_plot.get_cmap?  Still, I'll put some other interesting resources I found below, in case that is too easy, or you need more direction for how to create good colormaps.. Here is an example of how this might be done in pure Python, and here is a nice way to 'discretize' colormaps. Now, these don't do exactly what you want, because the colormaps seem to mostly operate on the principle of the interval $(0,1)$. If we do sage: import matplotlib sage: matplotlib.colors? A module for converting numbers or color arguments to *RGB* or *RGBA* *RGB* and *RGBA* are sequences of, respectively, 3 or 4 floats in the range 0-1. This module includes functions and classes for color specification conversions, and for mapping numbers to colors in a 1-D array of colors called a colormap. Colormapping typically involves two steps: a data array is first mapped onto the range 0-1 using an instance of Normalize or of a subclass; then this number in the 0-1 range is mapped to a color using an instance of a subclass of Colormap. Two are provided here: LinearSegmentedColormap, which is used to generate all the built-in colormap instances, but is also useful for making custom colormaps, and ListedColormap, which is used for generating a custom colormap from a list of color specifications.  So here is something that might work: sage: import matplotlib sage: M = matplotlib.colors.ListedColormap([(0,1,1),(1,0,1),(1,1,0)],'M') sage: matrix_plot(matrix([[0,1],[1,2]]),cmap=M)  posted Dec 20 '10 kcrisman 6639 ● 13 ● 66 ● 150 See also http://trac.sagemath.org/sage_trac/ticket/10503kcrisman (Dec 20 '10) And I do not believe matplotlib allows one to associate specific numbers with colors, only the range. The type of cmap this provides is discrete, though, so hopefully it should be good enough if you know what values to expect ahead of time. If that is random, you may have to generate the cmap on the fly. The links provided are just some of some great posts and explanations I found on the matplotlib and Scipy websites, so hopefully you'll find what you need if this isn't it. kcrisman (Dec 20 '10) This fits my needs if normalized, but since user input will not necessarily be in order, the other solution works better. Eviatar Bach (Dec 20 '10)
 0 You might check out the norm option to matrix_plot (see the docs), which takes a value argument that does away with scaling before applying a colormap. You can also specify a function that does the colormapping. See also the matplotlib documentation for colormaps and the normalizing functions. posted Dec 22 '10 Jason Grout 3185 ● 7 ● 27 ● 71

[hide preview]

## Stats:

Asked: Dec 19 '10

Seen: 239 times

Last updated: Dec 22 '10