stacking colormaps

后端 未结 2 1283
Happy的楠姐
Happy的楠姐 2020-12-04 03:11

Is there a simple way to form a new colormap by stacking together two existing ones?

What I\'m trying to achieve is to make yet another color-coded scatter plot, wh

相关标签:
2条回答
  • 2020-12-04 03:20

    This isn't tested, but as a first pass I would try making a simple sub-class of colors.Colormap.

    class split_cmap(colors.Colormap):
        def __init__(self, cmap_a, cmap_b, split=.5):
            '''Makes a split color map cmap_a is the low range, 
               cmap_b is the high range
               split is where to break the range
            '''
            self.cmap_a, self.cmap_b = cmap_a, cmap_b
            self.split = split
    
        def __call__(self, v):
            if v < self.split:
                return self.cmap_a(v) 
                # or you might want to use v / self.split
            else:
                return self.cmap_b(v) 
                # or you might want to use (v - self.split) / (1 - self.split)
    
        def set_bad(self,*args, **kwargs):
            self.cmap_a.set_bad(*args, **kwargs)
            self.cmap_b.set_bad(*args, **kwargs)
    
        def set_over(self, *args, **kwargs):
            self.cmap_a.set_over(*args, **kwargs) # not really needed
            self.cmap_b.set_over(*args, **kwargs)
    
        def set_under(self, *args, **kwargs):
            self.cmap_a.set_under(*args, **kwargs)
            self.cmap_b.set_under(*args, **kwargs) # not really needed
    
        def is_gray(self):
            return False
    

    colors.Colormap class definition.

    You are going to need to dig into the Normalize classes as well. The color maps only know about [0, 1], so you will have to make sure that your norm maps to .5 where you want the change over to happen.

    You could probably generalize this to take a list of maps and split points and have as many color maps as you want. This also needs all manner of sanity checks.

    If you re-normalize the input, you could also use this to make a periodic version of any existing color map by passing it the color map and it's reversed partner.

    0 讨论(0)
  • 2020-12-04 03:39

    I think it is simpler to make the colormap yourself, especially when so few colors are involved. This one is orange-white-blue.

    cdict = {'red':   [ (0.0,   0.0, 0.0),
                        (0.475, 1.0, 1.0),
                        (0.525, 1.0, 1.0),
                        (1.0,   1.0, 1.0)
                      ],
             'green': [ (0.0,   0.0, 0.0),
                        (0.475, 1.0, 1.0),
                        (0.525, 1.0, 1.0),
                        (1.0,   0.65, 0.0)
                      ],
             'blue':  [ (0.0,   1.0, 1.0),
                        (0.475, 1.0, 1.0),
                        (0.525, 1.0, 1.0),
                        (1.0,   0.0, 0.0)
                      ]
    }
    rwb_cmap = matplotlib.colors.LinearSegmentedColormap(name = 'rwb_colormap', colors = cdict, N = 256)
    

    A colormap is a dictionary for the RGB values. For each color, a list of tupples gives the different segments. Each segment is a point along the z-axis, ranging from 0 to 1. The colors for the levels is interpolated from these segments.

    segment z-axis  end      start
    i       z[i]    v0[i]    v1[i]
    i+1     z[i+1]  v0[i+1]  v1[i+1]   
    i+2     z[i+2]  v0[i+2]  v1[i+2]   
    

    Levels between z[i] and z[i+1] will have colors between v1[i] and v0[i+1] etc. This makes it possible to 'jump' colors. v0[0] and v1[-1] are not used. You can use as many segments as you want. (adapted from here: http://matplotlib.org/api/colors_api.html#matplotlib.colors.LinearSegmentedColormap)

    N is the number of quantization levels. So for N = 256 it will interpolate the map for 256 levels. I use 256 out of laziness. I guess you have to be careful when you set N = 6 and you make 4 contours.

    The 0.475 and 0.525 are to ensure that the middle contour is truly white. For the levels [-1.5, -0.5, 0.5, 1.5] the fill is now orange-white-blue. If I had used 0.5 instead the middle level would be an interpolation of blue-ish and orange-ish.

    The RGB code for orange is 255-165-0 or 1-0.65-0 if the scale is 0-1.

    0 讨论(0)
提交回复
热议问题