On 05/02/07, John Hunter <[EMAIL PROTECTED]> wrote:
On 2/5/07, Michael Lerner <[EMAIL PROTECTED]> wrote:
> Hi,
>
> I have some data where I'd like almost all of it to be plotted with a
> LinearSegmentedColormap that I've made, but I have a few special
> values that I'd like to set to specific colors (white, in this case).
> So, I made a LinearSegmentedColormap that works pretty well, but I'm
> having trouble with the rest.  I found a nice-looking example at
>
> http://www.scipy.org/Cookbook/Matplotlib/Plotting_Images_with_Special_Values
>
> But, it doesn't work for me.  In particular, it complains a lot about
> _lut.  I'm using matplotlib 0.87.7 on an intel Mac running OS X and
> python 2.4.

On a very quick read, it appears that the sentinel map in that example
forgot to initialize the baseclass.  Eg, you need

 class SentinelMap(Colormap):
         def __init__(self, cmap, sentinels={}):
             Colormap.__init__(self)  # init the base class
             # boilerplate stuff - rest of init function here

See if that helps, and let us know.  If you get it working, please fix
the wiki (you may have to sign up) and post your example along with
it.

Otherwise, please post a complete code example and we'll see what we can do.

JDH


>
> Can someone show me how to make a sentinel'd version of a
> LinearSegmentedColormap?
>
> Thank you,
>
> -Michael Lerner

I had the same problem that you did with the sentinels.py.

I modified the code so that it did work, and attach it here. you can
test it by running it.  It only works with numpy, because it uses
fancy indexing. I'm pretty sure it's not done the fastest  way.

You first make up the colormap instance for the real data, without any
sentinels.
then use the colormap instance as an argument to the sentinel
colormap. This is why it
doesn't do a  Colormap.__init__(self). Not sure that's really best,
but i just followed the original method.

HTH. George Nurser.
from matplotlib.colors import Colormap, normalize
import matplotlib.numerix as nx
from matplotlib.numerix import alltrue,ma
from types import IntType, FloatType, ListType

class SentinelMap(Colormap):
    def __init__(self, cmap, sentinels={}):
        # boilerplate stuff
        self.N = cmap.N
        self.name = 'SentinelMap'
        self.cmap = cmap
        self.sentinels = sentinels

        for rgb in sentinels.values():
            if len(rgb)!=3:
                raise ValueError('sentinel color must be RGB')


    def __call__(self, scaledImageData, alpha=1):
        # assumes the data is already normalized (ignoring sentinels)
        # clip to be on the safe side
        rgbaValues = self.cmap(nx.clip(scaledImageData, 0.,1.))
        for sentinel,rgb in self.sentinels.items():
            r,g,b = rgb
            if (scaledImageData==sentinel).max():
                rgbaValues[...,0] =  nx.where(scaledImageData==sentinel, r, rgbaValues[...,0])
                rgbaValues[...,1] =  nx.where(scaledImageData==sentinel, g, rgbaValues[...,1])
                rgbaValues[...,2] =  nx.where(scaledImageData==sentinel, b, rgbaValues[...,2])
                rgbaValues[...,3] =  nx.where(scaledImageData==sentinel, alpha, rgbaValues[...,3])
        return rgbaValues

class SentinelNorm(normalize):
    """
    Leave the sentinel unchanged
    """
    def __init__(self, ignore=[], vmin=None, vmax=None, clip = True):
        self.vmin=vmin
        self.vmax=vmax
        self.clip = clip
        print 'in init vmax=',vmax,'vmin=',vmin
        
        if type(ignore) in [IntType, FloatType]:
            self.ignore = [ignore]
        else:
            self.ignore = list(ignore)
        self.ignore_mask=None
        
    def __call__(self, value, clip=None):
        
        if clip is None:
            clip = self.clip

        # ensure that we have a masked array val to work with
        if isinstance(value, (int, float)):
            vtype = 'scalar'
            val = ma.array([value])
        else:
            vtype = 'array'
            if ma.isMA(value):
                val = value
            else:
                val = ma.asarray(value)

        # create ignore_mask, val=sentinel1 | val= sentinel2..
        if self.ignore is not None:
            self.get_ignore_mask(val)
            
        # find min and max over points not masked by ignore_mask or by original mask of val
        self.autoscale(val)

        # now do scaling
        vmin, vmax = self.vmin, self.vmax
        if vmin > vmax:
            if False in val.mask:
                raise ValueError("minvalue must be less than or equal to maxvalue")
            else:
                # array is completely masked. doesn't matter what values are for plot
                return 0.*value
        elif vmin==vmax:
            return 0.*value
        else:
            # scale points not masked by ignore_mask or by original mask of val
            scale = 1./(vmax-vmin)
            result = (val-vmin)*scale
            if clip:
                result = nx.clip(result,0.,1.)
            # set result over sentinel points to sentinel values 
            if self.ignore is not None:
                result[self.ignore_mask]=val.data[self.ignore_mask]
                
        if vtype == 'scalar':
            result = result[0]
        return result
    
    def get_ignore_mask(self, A):
        if ma.isMA(A):
            A=A.data
        if self.ignore is not None:
            self.ignore_mask = False
            for ignore in self.ignore:
                self.ignore_mask |= A==ignore


    def autoscale(self, A):
        # self.scaled is method in base class Normalize [colors.py], is True if self.vmin,vmax already defined
        if not self.scaled():
            if self.ignore is not None:
                if self.ignore_mask is None:
                    self.get_ignore_mask(A)
                A = ma.masked_where(self.ignore_mask,A)

            if self.vmin is None: self.vmin = A.min()
            if self.vmax is None: self.vmax = A.max()
            
    def inverse(self, value):
        if not self.scaled():
            raise ValueError("Not invertible until scaled")
        vmin, vmax = self.vmin, self.vmax

        if isinstance(value, (int, float)):
            return vmin + value * (vmax - vmin)
        else:
            val = ma.asarray(value)
            result = vmin + val * (vmax - vmin)
            if self.ignore is not None:
                if self.ignore_mask is None:
                    self.get_ignore_mask(value)
                result[self.ignore_mask]=val.data[self.ignore_mask]
            return result

if __name__=="__main__":
    import pylab
    import matplotlib.colors
    n=5

    # create a random array
    X = nx.mlab.rand(n,n)
    xmin = X.min();xmax=X.max()
    print 'xmin= ',xmin,'xmax= ',xmax
    print 'X before any masking\n ',X
    
    # set color map to be overloaded
    cmBase = pylab.cm.jet

    # plot original array with pcolor
    pylab.figure(1)
    pylab.pcolor(X, cmap=cmBase, shading='flat')
    pylab.colorbar()

    # define the sentinels
    sentinel1 = -10.0
    sentinel2 = 10.0
    print 'sentinel1= ',sentinel1,'sentinel2= ', sentinel2
    print '\n'

    # replace some data with sentinels
    X[int(.1*n):int(.2*n), int(.5*n):int(.7*n)]  = sentinel1
    X[int(.6*n):int(.9*n), int(.2*n):int(.5*n)]  = sentinel2
    print 'X after sentinels inserted\n ',X

    # define the colormap and norm
    rgb1 = (0.,0.,0.)
    rgb2 = (.3,0.3,0.3)
    cmap = SentinelMap(cmBase, sentinels={sentinel1:rgb1,sentinel2:rgb2,})
    norm = SentinelNorm(ignore=[sentinel1,sentinel2])

    # plot with the sentinels
    pylab.figure(2)
    pylab.pcolor(X, cmap = cmap, norm=norm,  shading='flat')
    pylab.colorbar()
    
    # make mask
    mask = nx.mlab.rand(n,n) >0.5
    print 'mask\n ',mask

    
    # now mask X
    X= ma.masked_where(mask,X)
    print 'masked X after sentinels inserted\n ',X
    print 'doubly masked X after sentinels inserted\n ',ma.asarray(X)

    # define the colormap and norm
    cmap = SentinelMap(cmBase, sentinels={sentinel1:rgb1,sentinel2:rgb2,})
    norm = SentinelNorm(ignore=[sentinel1,sentinel2])

    # plot with the sentinels AND mask
    pylab.figure(3)
    pylab.pcolor(X, cmap = cmap, norm=norm,  shading='flat')
    pylab.colorbar()

    pylab.show()
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier.
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

Reply via email to