Skip to content

skais_mapper.utils.colors

Color module for more beautiful plots.

Classes:

Name Description
SkaisColorMaps

An assortment of linearly interpolated colormaps based on 4+ colors each.

SkaisColors

An assortment of colors and palettes.

Functions:

Name Description
color_variant

Takes a color in hex code and produces a lighter or darker shift variant.

ReNormColormapAdaptor

ReNormColormapAdaptor(
    base,
    cmap_norm: Normalize,
    orig_norm: Normalize | None = None,
)

Bases: Colormap

Adaptor for re-normalizing color mappable.

Methods:

Name Description
__call__

Re-normalise the values before applying the colormap.

reversed

Abstract dummy method.

Source code in skais_mapper/utils/colors.py
40
41
42
43
44
45
46
47
48
49
50
51
52
53
def __init__(self, base, cmap_norm: Normalize, orig_norm: Normalize | None = None):
    if orig_norm is None:
        if isinstance(base, ScalarMappable):
            orig_norm = base.norm
            base = base.cmap
        else:
            orig_norm = Normalize(0, 1)
    self._base = base
    if isinstance(cmap_norm, type(Normalize)) and issubclass(cmap_norm, Normalize):
        # a class was provided instead of an instance. create an instance
        # with the same limits.
        cmap_norm = cmap_norm(orig_norm.vmin, orig_norm.vmax)
    self._cmap_norm = cmap_norm
    self._orig_norm = orig_norm

__call__

__call__(X, **kwargs)

Re-normalise the values before applying the colormap.

Source code in skais_mapper/utils/colors.py
55
56
57
def __call__(self, X, **kwargs):
    """Re-normalise the values before applying the colormap."""
    return self._base(self._cmap_norm(self._orig_norm.inverse(X)), **kwargs)

reversed

reversed(*args, **kwargs)

Abstract dummy method.

Source code in skais_mapper/utils/colors.py
66
67
def reversed(self, *args, **kwargs):
    """Abstract dummy method."""

SkaisColorMaps

An assortment of linearly interpolated colormaps based on 4+ colors each.

Methods:

Name Description
gen

Generate colormaps.

palette

Return a palette of a colormap with N linearly interpolated color points.

plot_gradients

Plot all color-map gradients.

random

Choose a random color map.

register_all

Register colormaps with matplotlib.

reverse

Reverse the specified colormap.

gen classmethod

gen()

Generate colormaps.

Returns:

Type Description
mpl.colors.LinearSegmentedColormap object

colormap generated from custom list

Source code in skais_mapper/utils/colors.py
271
272
273
274
275
276
277
278
@classmethod
def gen(cls):
    """Generate colormaps.

    Returns:
        (mpl.colors.LinearSegmentedColormap object): colormap generated from custom list
    """
    yield from cls.aslist

palette classmethod

palette(cmap_name: str, N: int)

Return a palette of a colormap with N linearly interpolated color points.

Parameters:

Name Type Description Default
cmap_name str

name of the colormap

required
N int

number of colors in the palette

required
Source code in skais_mapper/utils/colors.py
318
319
320
321
322
323
324
325
326
327
328
329
@classmethod
def palette(cls, cmap_name: str, N: int):
    """Return a palette of a colormap with N linearly interpolated color points.

    Args:
        cmap_name: name of the colormap
        N: number of colors in the palette
    """
    vals = np.linspace(0, 1, N)
    cmap = cls.__dict__[cmap_name]
    rgbas = cmap(vals)
    return [to_hex(rgba, keep_alpha=False) for rgba in rgbas]

plot_gradients classmethod

plot_gradients(savefig: bool = False)

Plot all color-map gradients.

Parameters:

Name Type Description Default
savefig bool

save figure as palettes.png

False
Source code in skais_mapper/utils/colors.py
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
@classmethod
def plot_gradients(cls, savefig: bool = False):
    """Plot all color-map gradients.

    Args:
        savefig (bool): save figure as palettes.png
    """
    gradient = np.linspace(0, 1, 256)
    gradient = np.vstack((gradient, gradient))
    fig, axes = plt.subplots(nrows=SkaisColorMaps.N)
    fig.subplots_adjust(top=0.95, bottom=0.01, left=0.2, right=0.99)
    for ax, cmap in zip(axes, cls.aslist):
        ax.imshow(gradient, aspect="auto", cmap=cmap)
        pos = list(ax.get_position().bounds)
        x_text = pos[0] - 0.01
        y_text = pos[1] + pos[3] / 2.0
        fig.text(x_text, y_text, cmap.name, va="center", ha="right", fontsize=10)
    for ax in axes:
        ax.set_axis_off()
    if savefig:
        plt.savefig("palette.png")

random classmethod

random() -> LinearSegmentedColormap

Choose a random color map.

Returns:

Name Type Description
cmap LinearSegmentedColormap

random colormap from custom list

Source code in skais_mapper/utils/colors.py
262
263
264
265
266
267
268
269
@classmethod
def random(cls) -> LinearSegmentedColormap:
    """Choose a random color map.

    Returns:
        cmap: random colormap from custom list
    """
    return random.choice(cls.aslist)

register_all staticmethod

register_all(verbose: bool = False)

Register colormaps with matplotlib.

Parameters:

Name Type Description Default
verbose bool

If True, print information to command line

False
Source code in skais_mapper/utils/colors.py
353
354
355
356
357
358
359
360
361
362
363
364
365
366
@staticmethod
def register_all(verbose: bool = False):
    """Register colormaps with matplotlib.

    Args:
        verbose (bool): If True, print information to command line
    """
    for g in SkaisColorMaps.aslist:
        if verbose:
            print(g.name)
        if g.name not in mpl.colormaps:
            mpl.colormaps.register(name=g.name, cmap=g)
        if f"skais_{g.name}" not in mpl.colormaps:
            mpl.colormaps.register(name=f"skais_{g.name}", cmap=g)

reverse classmethod

reverse(
    cmap: Colormap,
    set_bad: str = None,
    set_under: str = None,
    set_over: str = None,
) -> LinearSegmentedColormap

Reverse the specified colormap.

Parameters:

Name Type Description Default
cmap mpl.colors.LinearSegmentedColormap object

colormap to be reversed

required
set_bad str

set colormaps bad values to a different color

None
set_under str

set colormaps under values to a different color

None
set_over str

set colormaps over values to a different color

None

Returns:

Type Description
mpl.colors.LinearSegmentedColormap object

reversed colormap

Source code in skais_mapper/utils/colors.py
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
@classmethod
def reverse(
    cls, cmap: Colormap, set_bad: str = None, set_under: str = None, set_over: str = None
) -> LinearSegmentedColormap:
    """Reverse the specified colormap.

    Args:
        cmap (mpl.colors.LinearSegmentedColormap object): colormap to be reversed
        set_bad (str): set colormaps bad values to a different color
        set_under (str): set colormaps under values to a different color
        set_over (str): set colormaps over values to a different color

    Returns:
        (mpl.colors.LinearSegmentedColormap object): reversed colormap
    """
    reverse = []
    k = []

    for key in cmap._segmentdata:
        k.append(key)

        channel = cmap._segmentdata[key]
        data = []

        for t in channel:
            data.append((1 - t[0], t[2], t[1]))
        reverse.append(sorted(data))

    linear_l = dict(zip(k, reverse))
    rcmap = LinearSegmentedColormap(f"{cmap.name}_r", linear_l)
    if set_bad is not None:
        rcmap.set_bad(set_bad)
    if set_under is not None:
        rcmap.set_over(set_under)
    if set_over is not None:
        rcmap.set_over(set_over)
    return rcmap

SkaisColors

An assortment of colors and palettes.

Methods:

Name Description
cmap_from_color

Create a colormap from a single color.

cmap_from_color classmethod

cmap_from_color(
    color_str: str, secondary_color: str | None = None
) -> LinearSegmentedColormap

Create a colormap from a single color.

Parameters:

Name Type Description Default
color_str str

color string of the class color

required
secondary_color str | None

color into which the color changes in the colormap

None

Returns:

Type Description
mpl.colors.LinearSegmentedColormap object

reversed colormap

Source code in skais_mapper/utils/colors.py
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
@classmethod
def cmap_from_color(
    cls,
    color_str: str,
    secondary_color: str | None = None,
) -> LinearSegmentedColormap:
    """Create a colormap from a single color.

    Args:
        color_str: color string of the class color
        secondary_color: color into which the color changes in the colormap

    Returns:
        (mpl.colors.LinearSegmentedColormap object): reversed colormap
    """
    if color_str in cls.__dict__:
        color = cls.__dict__[color_str]
    else:
        color = color_str
    if secondary_color in cls.__dict__:
        secondary_color = cls.__dict__[secondary_color]
    elif secondary_color is None:
        secondary_color = color_variant(color, shift=125)
    cmap = LinearSegmentedColormap.from_list("Skais" + color_str, [secondary_color, color])
    return cmap

color_variant

color_variant(hex_color: str, shift: int = 10) -> str

Takes a color in hex code and produces a lighter or darker shift variant.

Parameters:

Name Type Description Default
hex_color str

formatted as '#' + rgb hex string of length 6

required
shift int

decimal shift of the rgb hex string

10

Returns:

Name Type Description
variant str

formatted as '#' + rgb hex string of length 6

Source code in skais_mapper/utils/colors.py
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
def color_variant(hex_color: str, shift: int = 10) -> str:
    """Takes a color in hex code and produces a lighter or darker shift variant.

    Args:
        hex_color (str): formatted as '#' + rgb hex string of length 6
        shift (int): decimal shift of the rgb hex string

    Returns:
        variant (str): formatted as '#' + rgb hex string of length 6
    """
    if len(hex_color) != 7:
        message = "Passed {} to color_variant(), needs to be in hex format."
        raise ValueError(message.format(hex_color))
    rgb_hex = [hex_color[x : x + 2] for x in [1, 3, 5]]
    new_rgb_int = [int(hex_value, 16) + shift for hex_value in rgb_hex]
    # limit to interval 0 and 255
    new_rgb_int = [min([255, max([0, i])]) for i in new_rgb_int]
    # hex() produces "0x88", we want the last two digits
    return "#" + "".join([hex(i)[2:] if i else "00" for i in new_rgb_int])