From: Perry G. <pe...@st...> - 2005-01-11 22:35:28
|
On Jan 11, 2005, at 10:25 AM, Eric Emsellem wrote: > HI again, > > I have questions of how to generate new LUTs outside matplotlib. > > 3 main issues: > > 1/ how to create a new lut in the same way that cm.py/colors.py is > doing it > in matplotlib > 2/ how to create a new lut which is given by a set of e.g., 256 > colours levels (R, G, B) > but not as a segmented array as in cm/colors > 3/ How do you rescale a lut without rescaling the array itself? > (so an equivalent to load/itt log for example in Midas for those who > know). > For example I would like to use the jet lut but with a log increase > of the lut so that e.g. displaying the color bar shows it is in > ''log'' > > For 1, I am not so sure what to do, and for 2/ I give below > what I am doing at the moment. To be frank, it looks quite ugly > (mainly because I am a bad programmer and don't know so much about > python/matplotlib). > > I got inspired by cm and colors.py and Midas lut > but really this is probably not the way to go. > In order to change the lut I just then do: > > lut('mylut') > > where 'mylut.lasc' is then the ascii file where the 256 colours are > given in 3 columns > (R G B) of 256 rows > > The problem is that since I do not have the corresponding segmented > array for each > lut (and I don't want it to be that way) I need to define a ''dummy'' > array. > Then each time I use imshow I must reload the lut (otherwise it uses > this dummy segmented > array which is here a gray lut). > > I am not sure this is all clear, but basically what I am trying to do > here is to just > answer questions 1, 2, 3 above and below is an ugly solution for 2 > (but incomplete). > I think it is important to realize that you don't need to base it on the existing colormapping mechanism, you just need to duplicate the interface of colormaps, namely that it has N, and name attributes, and that when the object is called with an array or scalar as an argument, it will return the appropriate array (or tuple) as the result. How you convert the array to rgba values is entirely up to you. But I think there is enough similarity to what LinearSegmentColormap that effectively its __call__ method can be resused without changed. You would only override the __init__ to create the _red_lut, _green_lut, _blue_lut attribute directly from array arguments (if I remember what MIDAS does; it's been nearly 20 years since I've used it!). That is something like this (untested, untried!) class ArrayColormap(LinearSegmentColormap): """ really, it seems that linear should inherit from Array instead!""" def __init__(name, r,g,b): """create color map from supplied r,g,b arrays""" # put checks on r,g,b arrays here... self._red_lut = r self._green_lut = g self._blue_lut = b self.N = len(r) self.name = name This is something we should add but you can try this in the meantime. The second part is how to set the lut to this. You can provide the new colormap instance as a keyword (cmap) argument to imshow or figimage. But I understand you would like a functional way to update an existing display. There doesn't appear to be a function to do this, but a new one is easily defined. Something like this ought to work (again untested, and again, we should supply this in the next version) from def loadcm(cm): """change the default colormap to cm""" rc('image', cmap='yourcmname') im = gci() if im is not None: im.set_cmap(cm) draw_if_interactive() But the problem with this is that default mechanism won't work since this eventually calls cm.get_cmap, which then looks for the named cm in the cm.datad array to construct a LinearSegmentedColormap instance. I think the solution here may need to have some sort of caching mechanism so that user defined colormaps can be used as a default (perhaps John can think of some other mechanism). I agree that it should be simple to define your own on the fly and be able to use these. So we'll see how this is best handled. I'm not sure what you mean by 3. If you are changing the lut (i.e., which colors map to which image intensity levels, the rescaling the image is required when displaying it (in the "old days" when image displays were only 8-bit and had hardware luts, one didn't have to do that). If all you mean is that you already had transformed the data to log format but want to show the lut as though the data were linearly displayed, I suppose one would display a colorbar where the intensities were suitably transformed from a linear ramp. But please elaborate. Perry |