示例#1
0
def bezier(icolors,
           ncol=255,
           correctlightness=True,
           reverse=False,
           cmap=None,
           lch=False):
    """
    interpolates between a set of colors using a bezier spline
    """
    # Bezier interpolation functions
    int2 = lambda c0, c1, t: (1. - t) * c0 + t * c1
    int3 = lambda c0, c1, c2, t: (1. - t) * (1. - t) * c0 + 2. * (
        1. - t) * t * c1 + t * t * c2
    int4 = lambda c0, c1, c2, c3, t: (1. - t) * (1. - t) * (
        1. - t) * c0 + 3. * (1. - t) * (1. - t) * t * c1 + 3. * (
            1. - t) * t * t * c2 + t * t * t * c3

    # Check
    assert ncol > 1, 'Number of interpolated colours must be > 1'

    # Convert colours to L*a*b
    if lch:
        colors = [rgb2lch(*col2rgb(i)) for i in icolors]  # in lab
    else:
        colors = [rgb2lab(*col2rgb(i)) for i in icolors]  # in lab

    # Check - 2
    icol = len(colors)
    if (icol > 5):
        raise ValueError('number of input colors > 5 not supported.')

    # Check sequential or diverging colours, i.e. check for increasing/decreasing lightness
    if (icol > 1):
        lights = np.array([i[0] for i in colors])
        dlight = np.diff(lights)
        if np.all(dlight < 0.) or np.all(dlight >= 0.):
            idiverge = False
            # if icol > 4:
            #     raise ValueError('only diverging colours supported in case of 5 input colours.')
        else:
            idiverge = True
            if icol == 4:
                print('ll', lights)
                raise ValueError(
                    'colours must have increasing or decreasing lightness in case of even number of colors: '
                    + ',' + ','.join([str(i) for i in lights]))

    # Interpolate colours
    if icol == 1:
        lab = [colors[0] for i in range(ncol)]
    elif icol == 2:
        lab0 = colors[0]
        lab1 = colors[1]
        # linear interpolation
        lab = list()
        for it in range(ncol):
            t = float(it) / float(ncol - 1)
            if correctlightness:
                t = correct_lightness(int2, lab0[0], lab1[0], t)
            lab.append(tuple([int2(lab0[i], lab1[i], t) for i in range(3)]))
    elif icol == 3:
        if idiverge:
            assert (
                ncol % 2
            ) == 1, 'number of colors has to be odd for bezier interpolation with 3 diverging colors.'
            ncol2 = ncol // 2 + 1
            # two separate interpolations
            col1 = bezier(icolors[:2], ncol2)
            col2 = bezier(icolors[1:], ncol2)
            col1.extend(col2[1:])
            if lch:
                lab = [rgb2lch(*rgb012rgb(*i)) for i in col1]
            else:
                lab = [rgb2lab(*rgb012rgb(*i)) for i in col1]
        else:
            lab0 = colors[0]
            lab1 = colors[1]
            lab2 = colors[2]
            # quadratic bezier interpolation
            lab = list()
            for it in range(ncol):
                t = float(it) / float(ncol - 1)
                if correctlightness:
                    t = correct_lightness(int3, lab0[0], lab1[0], lab2[0], t)
                lab.append(
                    tuple([
                        int3(lab0[i], lab1[i], lab2[i], t) for i in range(3)
                    ]))
    elif icol == 4:
        lab0 = colors[0]
        lab1 = colors[1]
        lab2 = colors[2]
        lab3 = colors[3]
        # cubic bezier interpolation
        lab = list()
        for it in range(ncol):
            t = float(it) / float(ncol - 1)
            if correctlightness:
                t = correct_lightness(int4, lab0[0], lab1[0], lab2[0], lab3[0],
                                      t)
            lab.append(
                tuple([
                    int4(lab0[i], lab1[i], lab2[i], lab3[i], t)
                    for i in range(3)
                ]))
    elif icol == 5:
        assert (
            ncol % 2
        ) == 1, 'number of colors has to be odd for bezier interpolation with 5 colors.'
        ncol2 = ncol // 2 + 1
        col1 = bezier(icolors[:3], ncol2)
        col2 = bezier(icolors[2:], ncol2)
        col1.extend(col2[1:])
        if lch:
            lab = [rgb2lch(*rgb012rgb(*i)) for i in col1]
        else:
            lab = [rgb2lab(*rgb012rgb(*i)) for i in col1]
    else:
        raise ValueError('number of input colors > 5 not supported.')

    # Reverse colours
    if reverse:
        lab = lab[::-1]

    # rgb [0-1]
    if lch:
        cout = [rgb2rgb01(*lch2rgb(*i)) for i in lab]
    else:
        cout = [rgb2rgb01(*lab2rgb(*i)) for i in lab]

    # Register colour map with matplotlib
    if cmap is not None:
        from matplotlib.colors import ListedColormap
        from matplotlib.cm import register_cmap
        iscmap = ListedColormap(cout, name=cmap, N=ncol)
        register_cmap(name=cmap, cmap=iscmap)

    return cout
示例#2
0
def sron_colors(cmap='palette1', ncol=9, cname=None, rgb=False, rgb256=False, reverse=False):
    """
        Distinct colour palettes of Paul Tol at SRON - Netherlands Institute for Space Research


        Definition
        ----------
        def sron_colors(cmap='palette1', ncol=9, cname=None, rgb=False, rgb256=False, reverse=False):


        Input
        -----
        None

        
        Optional Input
        --------------
        cmap       Colour palette name
                   palette1:        1-12 colours; orignal palette is ncol=9
                   palette2:        more regular hue and saturation (21 colours)
                   palette2-light:  7 light colours of palette2
                   palette2-medium: 7 medium colours of palette2
                   palette2-dark:   7 darker colours of palette2
                   gray / grey:     4 colours optimized for printing in grey scale
                   ylorbr           3-9 colours from sron_maps('ylorbr')
                   buylrd           3-11 colours from sron_maps('buylrd')
                   rainbow          4-12 colours from sron_maps('rainbow')
                   banded-rainbow   14, 15, 18, 21 banded rainbow schemes 
        ncol       number of desired colors if palette1 (1-12)
        cname      if given, name of registered colormap
        rgb        if True, return RGB value tuple between 0 and 1
        rgb256     if True, return RGB value tuple between 0 and 255
        reverse    if True, reverse colormap


        Output
        ------
        matplotlip listed colormap of ncol colours


        Restrictions
        ------------
        None
        

        Examples
        --------
        >>> print(sron_colors('palette1', 3, rgb256=True))
        [(68, 119, 170), (221, 204, 119), (204, 102, 119)]

        >>> print(sron_colors('palette2-light', rgb256=True)[0])
        (119, 170, 221)

        >>> print(sron_colors('ylorbr', 4, rgb256=True, reverse=True)[0])
        (204, 76, 2)


        License
        -------
        This file is part of the JAMS Python package, distributed under the MIT
        License. The JAMS Python package originates from the former UFZ Python library,
        Department of Computational Hydrosystems, Helmholtz Centre for Environmental
        Research - UFZ, Leipzig, Germany.

        Copyright (c) 2016 Matthias Cuntz - mc (at) macu (dot) de

        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:

        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.

        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.


        History
        -------
        Written,  MC, May 2016
    """
    from jams.color import hex2rgb01
    
    if cmap.lower() == 'palette1':
        assert (ncol>0) and (ncol<13), 'palette1 has 1-12 colours.'
        cols = []
        for i in palette1[ncol-1]:
            cols.append(tuple(hex2rgb01(i)))
    elif cmap.lower() == 'palette2':
        cols = []
        for i in range(7):
            cols.append(tuple(hex2rgb01(palette2_light[i])))
            cols.append(tuple(hex2rgb01(palette2_medium[i])))
            cols.append(tuple(hex2rgb01(palette2_dark[i])))
    elif cmap.lower() == 'palette2-light':
        cols = []
        for i in palette2_light:
            cols.append(tuple(hex2rgb01(i)))
    elif cmap.lower() == 'palette2-medium':
        cols = []
        for i in palette2_medium:
            cols.append(tuple(hex2rgb01(i)))
    elif cmap.lower() == 'palette2-dark':
        cols = []
        for i in palette2_dark:
            cols.append(tuple(hex2rgb01(i)))
    elif cmap.lower() == 'grey' or cmap.lower() == 'gray':
        cols = []
        for i in greysafe:
            cols.append(tuple(hex2rgb01(i)))
    elif cmap.lower() == 'ylorbr':
        assert (ncol>2) and (ncol<10), 'ylorbr has 3-9 colours.'
        cols = []
        for i in palette_ylorbr[ncol-3]:
            cols.append(tuple(hex2rgb01(i)))
    elif cmap.lower() == 'buylrd':
        assert (ncol>2) and (ncol<12), 'buylrd has 3-11 colours.'
        cols = []
        for i in palette_buylrd[ncol-3]:
            cols.append(tuple(hex2rgb01(i)))
    elif cmap.lower() == 'rainbow':
        assert (ncol>3) and (ncol<13), 'rainbow has 4-12 colours.'
        cols = []
        for i in palette_rainbow[ncol-4]:
            cols.append(tuple(hex2rgb01(i)))
    elif cmap.lower() == 'banded-rainbow':
        if ncol==14:
            psel = palette_rainbow_band[0]
        elif ncol==15:
            psel = palette_rainbow_band[1]
        elif ncol==18:
            psel = palette_rainbow_band[2]
        elif ncol==21:
            psel = palette_rainbow_band[3]
        else:
            raise ValueError('banded-rainbow palette has 14, 15, 18, or 21 colours.')
        cols = []
        for i in psel:
            cols.append(tuple(hex2rgb01(i)))
    else:
        raise ValueError('Colour palette not known: '+cmap)
            
    if reverse: cols = cols[::-1]
        
    if (not rgb) and (not rgb256):
        from matplotlib.colors import ListedColormap
        ccmap = ListedColormap(cols)
        if cname:
            from matplotlib.cm import register_cmap, get_cmap
            register_cmap(cname, ccmap)
            return get_cmap(cname)
        else:
            return ccmap
    else:
        if rgb256:
            from jams.color import rgb012rgb
            return [ rgb012rgb(*i) for i in cols ]
        else:
            return cols
示例#3
0
def sron_maps(cmap, ncol=256, offset=0, upper=1,
              cname=None, rgb=False, rgb256=False, reverse=False, grey=False, gray=False):
    """
        Colour maps of Paul Tol at SRON - Netherlands Institute for Space Research


        Definition
        ----------
        def sron_maps(cmap, ncol=256, offset=0, upper=1,
                      cname=None, rgb=False, rgb256=False, reverse=False, grey=False, gray=False):


        Input
        -----
        cmap       Colour map name
                   buylrd:  blue-yellow-red diverging
                   rainbow: rainbow
                   ylorbr:  yellow-orange-red sequential
        

        Optional Input
        --------------
        ncol       number of desired colors
        offset     bottom fraction to exclude (0-1)
        upper      upper most fraction included (0-1)
        cname      if given, name of registered colormap
        rgb        if True, return RGB value tuple between 0 and 1
        rgb256     if True, return RGB value tuple between 0 and 255
        reverse    if True, reverse colormap
        grey       if True, return grey equivalent
        gray       same as grey


        Output
        ------
        matplotlip listed colormap of ncol colours


        Restrictions
        ------------
        None
        

        Examples
        --------
        cmap = sron_maps('rainbow', 256)
        
        cc = sron_maps('buylrd', 11, rgb=True)


        License
        -------
        This file is part of the JAMS Python package, distributed under the MIT
        License. The JAMS Python package originates from the former UFZ Python library,
        Department of Computational Hydrosystems, Helmholtz Centre for Environmental
        Research - UFZ, Leipzig, Germany.

        Copyright (c) 2016 Matthias Cuntz - mc (at) macu (dot) de

        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:

        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.

        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.


        History
        -------
        Written,  MC, May 2016
    """
    if cmap == 'ylorbr':
        from scipy.special import erf

    cols = []
    for i in range(ncol):
        x = offset + float(i)/float(ncol-1) * (upper-offset)
        if cmap == 'buylrd':
            cols.append(tuple(buylrd(x)))
        elif cmap == 'rainbow':
            cols.append(tuple(rainbow(x)))
        elif cmap == 'ylorbr':
            cols.append(tuple(ylorbr(x)))
        else:
            raise ValueError('Colour map not known: '+cmap)
            
    if reverse: cols = cols[::-1]

    if grey or gray:
        for i, cc in enumerate(cols):
            isgray = 0.2125*cc[0] + 0.7154*cc[1] + 0.072*cc[2]
            cols[i] = (isgray,isgray,isgray)
        
    if (not rgb) and (not rgb256):
        from matplotlib.colors import ListedColormap
        ccmap = ListedColormap(cols)
        if cname:
            from matplotlib.cm import register_cmap, get_cmap
            register_cmap(cname, ccmap)
            return get_cmap(cname)
        else:
            return ccmap
    else:
        if rgb256:
            from jams.color import rgb012rgb
            return [ rgb012rgb(*i) for i in cols ]
        else:
            return cols
示例#4
0
def get_brewer(cname=None,
               names=False,
               rgb=False,
               rgb256=False,
               reverse=False,
               grey=False,
               gray=False):
    """
        Get colour map either as registered handle or as RGB values (0-255 or 0-1).

        Examples
        --------
        >>> import numpy as np
        >>> from jams.autostring import astr
        >>> cc = get_brewer('blues4',rgb=True)
        >>> print(astr(np.array(cc[0]), 4))
        ['0.9373' '0.9529' '1.0000']

        >>> cc = get_brewer('Blues4',rgb256=True)
        >>> print(cc[0])
        (239, 243, 255)

        >>> cc = get_brewer('bLuEs4',rgb256=True,reverse=True)
        >>> print(cc[-1])
        (239, 243, 255)
        >>> print(cc[0])
        (33, 113, 181)

        >>> cc = get_brewer('blues4',rgb256=True,grey=True)
        >>> print(astr(np.array(cc[0]), 4))
        ['242.9897' '242.9897' '242.9897']
    """
    from jams.color import rgb2rgb01, rgb012rgb
    if names:
        if names.lower() == 'sequential':
            return list(brewer_sequential.keys())
        elif names.lower() == 'diverging':
            return list(brewer_diverging.keys())
        elif names.lower() == 'qualitative':
            return list(brewer_qualitative.keys())
        elif names.lower() == 'osu':
            return list(oregon.keys())
        elif names.lower() == 'ncl_large':
            return list(ncl_large.keys())
        elif names.lower() == 'ncl_small':
            return list(ncl_small.keys())
        elif names.lower() == 'ncl_meteo_swiss':
            return list(ncl_meteo_swiss.keys())
        elif names.lower() == 'mma' or names.lower() == 'mathematica':
            return list(mathematica.keys())
        else:
            cmaps = list(all_maps.keys())
            return cmaps
    else:
        cname = capitalise(cname)
        cpool = all_maps[cname][:]
        if (not rgb) and (not rgb256):
            # register colour map with matplotlib
            from matplotlib.cm import get_cmap
            register_brewer(cname, reverse=reverse, grey=grey, gray=gray)
            return get_cmap(cname)
        elif rgb:
            # tuple 0-1
            if cname in all255_maps:
                cpool = [rgb2rgb01(*i) for i in cpool]
        elif rgb256:
            # tuple 0-255
            if cname not in all255_maps:
                cpool = [rgb012rgb(*i) for i in cpool]
        if reverse:
            cpool = cpool[::-1]
        if grey or gray:
            for j in range(len(cpool)):
                isgray = 0.2125 * cpool[j][0] + 0.7154 * cpool[j][
                    1] + 0.072 * cpool[j][2]
                cpool[j] = (isgray, isgray, isgray)
        return cpool