Module geoengine.colorizer

This module is used to generate geoengine compatible color map definitions as a json string.

Expand source code
"""This module is used to generate geoengine compatible color map definitions as a json string."""

from __future__ import annotations
from abc import abstractmethod
from dataclasses import dataclass
import json
import warnings
from typing import Dict, List, Tuple, Union, cast
import numpy as np
import numpy.typing as npt
from matplotlib.colors import Colormap
from matplotlib.cm import ScalarMappable
import geoengine_openapi_client

Rgba = Tuple[int, int, int, int]


@dataclass
class ColorBreakpoint():
    """This class is used to generate geoengine compatible color breakpoint definitions."""
    value: float
    color: Rgba

    def to_api_dict(self) -> geoengine_openapi_client.Breakpoint:
        """Return the color breakpoint as a dictionary."""
        return geoengine_openapi_client.Breakpoint(value=self.value, color=self.color)

    @staticmethod
    def from_response(response: geoengine_openapi_client.Breakpoint) -> ColorBreakpoint:
        """Parse a http response to a `ColorBreakpoint`."""
        return ColorBreakpoint(cast(float, response.value), cast(Rgba, tuple(cast(List[int], response.color))))


@dataclass
class Colorizer():
    """This class is used to generate geoengine compatible color map definitions as a json string."""

    no_data_color: Rgba

    @staticmethod
    def linear_with_mpl_cmap(
        color_map: Union[str, Colormap],
        min_max: Tuple[float, float],
        n_steps: int = 10,
        over_color: Rgba = (0, 0, 0, 0),
        under_color: Rgba = (0, 0, 0, 0),
        no_data_color: Rgba = (0, 0, 0, 0)
    ) -> LinearGradientColorizer:
        """Initialize the colorizer."""
        # pylint: disable=too-many-arguments

        if n_steps < 2:
            raise ValueError(f"n_steps must be greater than or equal to 2, got {n_steps} instead.")
        if min_max[1] <= min_max[0]:
            raise ValueError(f"min_max[1] must be greater than min_max[0], got {min_max[1]} and {min_max[0]}.")
        if len(over_color) != 4:
            raise ValueError(f"overColor must be a tuple of length 4, got {len(over_color)} instead.")
        if len(under_color) != 4:
            raise ValueError(f"underColor must be a tuple of length 4, got {len(under_color)} instead.")
        if len(no_data_color) != 4:
            raise ValueError(f"noDataColor must be a tuple of length 4, got {len(no_data_color)} instead.")
        if not all(0 <= elem < 256 for elem in no_data_color):
            raise ValueError(f"noDataColor must be a RGBA color specification, got {no_data_color} instead.")
        if not all(0 <= elem < 256 for elem in over_color):
            raise ValueError(f"overColor must be a RGBA color specification, got {over_color} instead.")
        if not all(0 <= elem < 256 for elem in under_color):
            raise ValueError(f"underColor must be a RGBA color specification, got {under_color} instead.")

        # get the map, and transform it to a list of (uint8) rgba values
        list_of_rgba_colors: List[npt.NDArray[np.uint8]] = ScalarMappable(cmap=color_map).to_rgba(
            np.linspace(min_max[0], min_max[1], n_steps), bytes=True)

        # if you want to remap the colors, you can do it here (e.g. cutting of the most extreme colors)
        values_of_breakpoints: List[float] = np.linspace(min_max[0], min_max[1], n_steps).tolist()

        # generate color map steps for geoengine
        breakpoints: List[ColorBreakpoint] = [
            ColorBreakpoint(
                color=(int(color[0]), int(color[1]), int(color[2]), int(color[3])), value=value
            ) for (value, color) in zip(
                values_of_breakpoints, list_of_rgba_colors)
        ]

        return LinearGradientColorizer(
            breakpoints=breakpoints,
            no_data_color=no_data_color,
            over_color=over_color,
            under_color=under_color
        )

    @staticmethod
    def logarithmic_with_mpl_cmap(
        color_map: Union[str, Colormap],
        min_max: Tuple[float, float],
        n_steps: int = 10,
        over_color: Rgba = (0, 0, 0, 0),
        under_color: Rgba = (0, 0, 0, 0),
        no_data_color: Rgba = (0, 0, 0, 0)
    ) -> LogarithmicGradientColorizer:
        """Initialize the colorizer."""
        # pylint: disable=too-many-arguments

        if n_steps < 2:
            raise ValueError(f"n_steps must be greater than or equal to 2, got {n_steps} instead.")
        if min_max[0] <= 0:
            raise ValueError(f"min_max[0] must be greater than 0 for a logarithmic gradient, got {min_max[0]}.")
        if min_max[1] <= min_max[0]:
            raise ValueError(f"min_max[1] must be greater than min_max[0], got {min_max[1]} and {min_max[0]}.")
        if len(over_color) != 4:
            raise ValueError(f"overColor must be a tuple of length 4, got {len(over_color)} instead.")
        if len(under_color) != 4:
            raise ValueError(f"underColor must be a tuple of length 4, got {len(under_color)} instead.")
        if len(no_data_color) != 4:
            raise ValueError(f"noDataColor must be a tuple of length 4, got {len(no_data_color)} instead.")
        if not all(0 <= elem < 256 for elem in no_data_color):
            raise ValueError(f"noDataColor must be a RGBA color specification, got {no_data_color} instead.")
        if not all(0 <= elem < 256 for elem in over_color):
            raise ValueError(f"overColor must be a RGBA color specification, got {over_color} instead.")
        if not all(0 <= elem < 256 for elem in under_color):
            raise ValueError(f"underColor must be a RGBA color specification, got {under_color} instead.")

        # get the map, and transform it to a list of (uint8) rgba values
        list_of_rgba_colors: List[npt.NDArray[np.uint8]] = ScalarMappable(cmap=color_map).to_rgba(
            np.linspace(min_max[0], min_max[1], n_steps), bytes=True)

        # if you want to remap the colors, you can do it here (e.g. cutting of the most extreme colors)
        values_of_breakpoints: List[float] = np.logspace(np.log10(min_max[0]), np.log10(min_max[1]), n_steps).tolist()

        # generate color map steps for geoengine
        breakpoints: List[ColorBreakpoint] = [
            ColorBreakpoint(
                color=(int(color[0]), int(color[1]), int(color[2]), int(color[3])), value=value
            ) for (value, color) in zip(
                values_of_breakpoints, list_of_rgba_colors)
        ]

        return LogarithmicGradientColorizer(
            breakpoints=breakpoints,
            no_data_color=no_data_color,
            over_color=over_color,
            under_color=under_color
        )

    @staticmethod
    def palette(
        color_mapping: Dict[float, Rgba],
        default_color: Rgba = (0, 0, 0, 0),
        no_data_color: Rgba = (0, 0, 0, 0),
    ) -> PaletteColorizer:
        """Initialize the colorizer."""

        if len(no_data_color) != 4:
            raise ValueError(f"noDataColor must be a tuple of length 4, got {len(no_data_color)} instead.")
        if len(default_color) != 4:
            raise ValueError(f"defaultColor must be a tuple of length 4, got {len(default_color)} instead.")
        if not all(0 <= elem < 256 for elem in no_data_color):
            raise ValueError(f"noDataColor must be a RGBA color specification, got {no_data_color} instead.")
        if not all(0 <= elem < 256 for elem in default_color):
            raise ValueError(f"defaultColor must be a RGBA color specification, got {default_color} instead.")

        return PaletteColorizer(
            colors=color_mapping,
            no_data_color=no_data_color,
            default_color=default_color,
        )

    @staticmethod
    def palette_with_colormap(
        values: List[float],
        color_map: Union[str, Colormap],
        default_color: Rgba = (0, 0, 0, 0),
        no_data_color: Rgba = (0, 0, 0, 0),
    ) -> PaletteColorizer:
        """This method generates a palette colorizer from a given list of values.
        A colormap can be given as an object or by name only."""

        if len(no_data_color) != 4:
            raise ValueError(f"noDataColor must be a tuple of length 4, got {len(no_data_color)} instead.")
        if len(default_color) != 4:
            raise ValueError(f"defaultColor must be a tuple of length 4, got {len(default_color)} instead.")
        if not all(0 <= elem < 256 for elem in no_data_color):
            raise ValueError(f"noDataColor must be a RGBA color specification, got {no_data_color} instead.")
        if not all(0 <= elem < 256 for elem in default_color):
            raise ValueError(f"defaultColor must be a RGBA color specification, got {default_color} instead.")

        n_colors_of_cmap: int = ScalarMappable(cmap=color_map).get_cmap().N

        if n_colors_of_cmap < len(values):
            warnings.warn(UserWarning(f"Warning!\nYour colormap does not have enough colors "
                                      "to display all unique values of the palette!"
                                      f"\nNumber of values given: {len(values)} vs. "
                                      f"Number of available colors: {n_colors_of_cmap}"))

        # we only need to generate enough different colors for all values specified in the colors parameter
        list_of_rgba_colors: List[npt.NDArray[np.uint8]] = ScalarMappable(cmap=color_map).to_rgba(
            np.linspace(0, len(values), len(values)), bytes=True)

        # generate the dict with value: color mapping
        color_mapping: Dict[float, Rgba] = dict(zip(
            values,
            [(int(color[0]), int(color[1]), int(color[2]), int(color[3])) for color in list_of_rgba_colors])
        )

        return PaletteColorizer(
            colors=color_mapping,
            no_data_color=no_data_color,
            default_color=default_color,
        )

    @abstractmethod
    def to_api_dict(self) -> geoengine_openapi_client.Colorizer:
        pass

    def to_json(self) -> str:
        """Return the colorizer as a JSON string."""
        return json.dumps(self.to_api_dict())

    @staticmethod
    def from_response(response: geoengine_openapi_client.Colorizer) -> Colorizer:
        """Create a colorizer from a response."""
        inner = response.actual_instance

        if isinstance(inner, geoengine_openapi_client.LinearGradientWithType):
            return LinearGradientColorizer.from_response_linear(inner)
        if isinstance(inner, geoengine_openapi_client.PaletteColorizer):
            return PaletteColorizer.from_response_palette(inner)
        if isinstance(inner, geoengine_openapi_client.LogarithmicGradientWithType):
            return LogarithmicGradientColorizer.from_response_logarithmic(inner)

        raise TypeError(f"Unknown colorizer type: {inner.type}")


@dataclass
class LinearGradientColorizer(Colorizer):
    '''A linear gradient colorizer.'''
    breakpoints: List[ColorBreakpoint]
    over_color: Rgba
    under_color: Rgba

    @staticmethod
    def from_response_linear(response: geoengine_openapi_client.LinearGradientWithType) -> LinearGradientColorizer:
        """Create a colorizer from a response."""
        breakpoints = [ColorBreakpoint.from_response(breakpoint) for breakpoint in response.breakpoints]
        return LinearGradientColorizer(
            no_data_color=response.no_data_color,
            breakpoints=breakpoints,
            over_color=response.over_color,
            under_color=response.under_color,
        )

    def to_api_dict(self) -> geoengine_openapi_client.Colorizer:
        """Return the colorizer as a dictionary."""
        return geoengine_openapi_client.Colorizer(geoengine_openapi_client.LinearGradientWithType(
            type='linearGradient',
            breakpoints=[breakpoint.to_api_dict() for breakpoint in self.breakpoints],
            no_data_color=self.no_data_color,
            over_color=self.over_color,
            under_color=self.under_color
        ))


@dataclass
class LogarithmicGradientColorizer(Colorizer):
    '''A logarithmic gradient colorizer.'''
    breakpoints: List[ColorBreakpoint]
    over_color: Rgba
    under_color: Rgba

    @staticmethod
    def from_response_logarithmic(
            response: geoengine_openapi_client.LogarithmicGradientWithType) -> LogarithmicGradientColorizer:
        """Create a colorizer from a response."""
        breakpoints = [ColorBreakpoint.from_response(breakpoint) for breakpoint in response.breakpoints]
        return LogarithmicGradientColorizer(
            breakpoints=breakpoints,
            no_data_color=response.no_data_color,
            over_color=response.over_color,
            under_color=response.under_color,
        )

    def to_api_dict(self) -> geoengine_openapi_client.Colorizer:
        """Return the colorizer as a dictionary."""
        return geoengine_openapi_client.Colorizer(geoengine_openapi_client.LogarithmicGradientWithType(
            type='logarithmicGradient',
            breakpoints=[breakpoint.to_api_dict() for breakpoint in self.breakpoints],
            no_data_color=self.no_data_color,
            over_color=self.over_color,
            under_color=self.under_color,
        ))


@dataclass
class PaletteColorizer(Colorizer):
    '''A palette colorizer.'''
    colors: Dict[float, Rgba]
    default_color: Rgba

    @staticmethod
    def from_response_palette(response: geoengine_openapi_client.PaletteColorizer) -> PaletteColorizer:
        """Create a colorizer from a response."""

        return PaletteColorizer(
            colors={float(k): v for k, v in response.colors.items()},
            no_data_color=response.no_data_color,
            default_color=response.default_color,
        )

    def to_api_dict(self) -> geoengine_openapi_client.Colorizer:
        """Return the colorizer as a dictionary."""
        return geoengine_openapi_client.Colorizer(geoengine_openapi_client.PaletteColorizer(
            type='palette',
            colors=self.colors,
            default_color=self.default_color,
            no_data_color=self.no_data_color,
        ))

Classes

class ColorBreakpoint (value: float, color: Rgba)

This class is used to generate geoengine compatible color breakpoint definitions.

Expand source code
@dataclass
class ColorBreakpoint():
    """This class is used to generate geoengine compatible color breakpoint definitions."""
    value: float
    color: Rgba

    def to_api_dict(self) -> geoengine_openapi_client.Breakpoint:
        """Return the color breakpoint as a dictionary."""
        return geoengine_openapi_client.Breakpoint(value=self.value, color=self.color)

    @staticmethod
    def from_response(response: geoengine_openapi_client.Breakpoint) -> ColorBreakpoint:
        """Parse a http response to a `ColorBreakpoint`."""
        return ColorBreakpoint(cast(float, response.value), cast(Rgba, tuple(cast(List[int], response.color))))

Class variables

var color : Tuple[int, int, int, int]
var value : float

Static methods

def from_response(response: geoengine_openapi_client.Breakpoint) ‑> ColorBreakpoint

Parse a http response to a ColorBreakpoint.

Expand source code
@staticmethod
def from_response(response: geoengine_openapi_client.Breakpoint) -> ColorBreakpoint:
    """Parse a http response to a `ColorBreakpoint`."""
    return ColorBreakpoint(cast(float, response.value), cast(Rgba, tuple(cast(List[int], response.color))))

Methods

def to_api_dict(self) ‑> geoengine_openapi_client.models.breakpoint.Breakpoint

Return the color breakpoint as a dictionary.

Expand source code
def to_api_dict(self) -> geoengine_openapi_client.Breakpoint:
    """Return the color breakpoint as a dictionary."""
    return geoengine_openapi_client.Breakpoint(value=self.value, color=self.color)
class Colorizer (no_data_color: Rgba)

This class is used to generate geoengine compatible color map definitions as a json string.

Expand source code
@dataclass
class Colorizer():
    """This class is used to generate geoengine compatible color map definitions as a json string."""

    no_data_color: Rgba

    @staticmethod
    def linear_with_mpl_cmap(
        color_map: Union[str, Colormap],
        min_max: Tuple[float, float],
        n_steps: int = 10,
        over_color: Rgba = (0, 0, 0, 0),
        under_color: Rgba = (0, 0, 0, 0),
        no_data_color: Rgba = (0, 0, 0, 0)
    ) -> LinearGradientColorizer:
        """Initialize the colorizer."""
        # pylint: disable=too-many-arguments

        if n_steps < 2:
            raise ValueError(f"n_steps must be greater than or equal to 2, got {n_steps} instead.")
        if min_max[1] <= min_max[0]:
            raise ValueError(f"min_max[1] must be greater than min_max[0], got {min_max[1]} and {min_max[0]}.")
        if len(over_color) != 4:
            raise ValueError(f"overColor must be a tuple of length 4, got {len(over_color)} instead.")
        if len(under_color) != 4:
            raise ValueError(f"underColor must be a tuple of length 4, got {len(under_color)} instead.")
        if len(no_data_color) != 4:
            raise ValueError(f"noDataColor must be a tuple of length 4, got {len(no_data_color)} instead.")
        if not all(0 <= elem < 256 for elem in no_data_color):
            raise ValueError(f"noDataColor must be a RGBA color specification, got {no_data_color} instead.")
        if not all(0 <= elem < 256 for elem in over_color):
            raise ValueError(f"overColor must be a RGBA color specification, got {over_color} instead.")
        if not all(0 <= elem < 256 for elem in under_color):
            raise ValueError(f"underColor must be a RGBA color specification, got {under_color} instead.")

        # get the map, and transform it to a list of (uint8) rgba values
        list_of_rgba_colors: List[npt.NDArray[np.uint8]] = ScalarMappable(cmap=color_map).to_rgba(
            np.linspace(min_max[0], min_max[1], n_steps), bytes=True)

        # if you want to remap the colors, you can do it here (e.g. cutting of the most extreme colors)
        values_of_breakpoints: List[float] = np.linspace(min_max[0], min_max[1], n_steps).tolist()

        # generate color map steps for geoengine
        breakpoints: List[ColorBreakpoint] = [
            ColorBreakpoint(
                color=(int(color[0]), int(color[1]), int(color[2]), int(color[3])), value=value
            ) for (value, color) in zip(
                values_of_breakpoints, list_of_rgba_colors)
        ]

        return LinearGradientColorizer(
            breakpoints=breakpoints,
            no_data_color=no_data_color,
            over_color=over_color,
            under_color=under_color
        )

    @staticmethod
    def logarithmic_with_mpl_cmap(
        color_map: Union[str, Colormap],
        min_max: Tuple[float, float],
        n_steps: int = 10,
        over_color: Rgba = (0, 0, 0, 0),
        under_color: Rgba = (0, 0, 0, 0),
        no_data_color: Rgba = (0, 0, 0, 0)
    ) -> LogarithmicGradientColorizer:
        """Initialize the colorizer."""
        # pylint: disable=too-many-arguments

        if n_steps < 2:
            raise ValueError(f"n_steps must be greater than or equal to 2, got {n_steps} instead.")
        if min_max[0] <= 0:
            raise ValueError(f"min_max[0] must be greater than 0 for a logarithmic gradient, got {min_max[0]}.")
        if min_max[1] <= min_max[0]:
            raise ValueError(f"min_max[1] must be greater than min_max[0], got {min_max[1]} and {min_max[0]}.")
        if len(over_color) != 4:
            raise ValueError(f"overColor must be a tuple of length 4, got {len(over_color)} instead.")
        if len(under_color) != 4:
            raise ValueError(f"underColor must be a tuple of length 4, got {len(under_color)} instead.")
        if len(no_data_color) != 4:
            raise ValueError(f"noDataColor must be a tuple of length 4, got {len(no_data_color)} instead.")
        if not all(0 <= elem < 256 for elem in no_data_color):
            raise ValueError(f"noDataColor must be a RGBA color specification, got {no_data_color} instead.")
        if not all(0 <= elem < 256 for elem in over_color):
            raise ValueError(f"overColor must be a RGBA color specification, got {over_color} instead.")
        if not all(0 <= elem < 256 for elem in under_color):
            raise ValueError(f"underColor must be a RGBA color specification, got {under_color} instead.")

        # get the map, and transform it to a list of (uint8) rgba values
        list_of_rgba_colors: List[npt.NDArray[np.uint8]] = ScalarMappable(cmap=color_map).to_rgba(
            np.linspace(min_max[0], min_max[1], n_steps), bytes=True)

        # if you want to remap the colors, you can do it here (e.g. cutting of the most extreme colors)
        values_of_breakpoints: List[float] = np.logspace(np.log10(min_max[0]), np.log10(min_max[1]), n_steps).tolist()

        # generate color map steps for geoengine
        breakpoints: List[ColorBreakpoint] = [
            ColorBreakpoint(
                color=(int(color[0]), int(color[1]), int(color[2]), int(color[3])), value=value
            ) for (value, color) in zip(
                values_of_breakpoints, list_of_rgba_colors)
        ]

        return LogarithmicGradientColorizer(
            breakpoints=breakpoints,
            no_data_color=no_data_color,
            over_color=over_color,
            under_color=under_color
        )

    @staticmethod
    def palette(
        color_mapping: Dict[float, Rgba],
        default_color: Rgba = (0, 0, 0, 0),
        no_data_color: Rgba = (0, 0, 0, 0),
    ) -> PaletteColorizer:
        """Initialize the colorizer."""

        if len(no_data_color) != 4:
            raise ValueError(f"noDataColor must be a tuple of length 4, got {len(no_data_color)} instead.")
        if len(default_color) != 4:
            raise ValueError(f"defaultColor must be a tuple of length 4, got {len(default_color)} instead.")
        if not all(0 <= elem < 256 for elem in no_data_color):
            raise ValueError(f"noDataColor must be a RGBA color specification, got {no_data_color} instead.")
        if not all(0 <= elem < 256 for elem in default_color):
            raise ValueError(f"defaultColor must be a RGBA color specification, got {default_color} instead.")

        return PaletteColorizer(
            colors=color_mapping,
            no_data_color=no_data_color,
            default_color=default_color,
        )

    @staticmethod
    def palette_with_colormap(
        values: List[float],
        color_map: Union[str, Colormap],
        default_color: Rgba = (0, 0, 0, 0),
        no_data_color: Rgba = (0, 0, 0, 0),
    ) -> PaletteColorizer:
        """This method generates a palette colorizer from a given list of values.
        A colormap can be given as an object or by name only."""

        if len(no_data_color) != 4:
            raise ValueError(f"noDataColor must be a tuple of length 4, got {len(no_data_color)} instead.")
        if len(default_color) != 4:
            raise ValueError(f"defaultColor must be a tuple of length 4, got {len(default_color)} instead.")
        if not all(0 <= elem < 256 for elem in no_data_color):
            raise ValueError(f"noDataColor must be a RGBA color specification, got {no_data_color} instead.")
        if not all(0 <= elem < 256 for elem in default_color):
            raise ValueError(f"defaultColor must be a RGBA color specification, got {default_color} instead.")

        n_colors_of_cmap: int = ScalarMappable(cmap=color_map).get_cmap().N

        if n_colors_of_cmap < len(values):
            warnings.warn(UserWarning(f"Warning!\nYour colormap does not have enough colors "
                                      "to display all unique values of the palette!"
                                      f"\nNumber of values given: {len(values)} vs. "
                                      f"Number of available colors: {n_colors_of_cmap}"))

        # we only need to generate enough different colors for all values specified in the colors parameter
        list_of_rgba_colors: List[npt.NDArray[np.uint8]] = ScalarMappable(cmap=color_map).to_rgba(
            np.linspace(0, len(values), len(values)), bytes=True)

        # generate the dict with value: color mapping
        color_mapping: Dict[float, Rgba] = dict(zip(
            values,
            [(int(color[0]), int(color[1]), int(color[2]), int(color[3])) for color in list_of_rgba_colors])
        )

        return PaletteColorizer(
            colors=color_mapping,
            no_data_color=no_data_color,
            default_color=default_color,
        )

    @abstractmethod
    def to_api_dict(self) -> geoengine_openapi_client.Colorizer:
        pass

    def to_json(self) -> str:
        """Return the colorizer as a JSON string."""
        return json.dumps(self.to_api_dict())

    @staticmethod
    def from_response(response: geoengine_openapi_client.Colorizer) -> Colorizer:
        """Create a colorizer from a response."""
        inner = response.actual_instance

        if isinstance(inner, geoengine_openapi_client.LinearGradientWithType):
            return LinearGradientColorizer.from_response_linear(inner)
        if isinstance(inner, geoengine_openapi_client.PaletteColorizer):
            return PaletteColorizer.from_response_palette(inner)
        if isinstance(inner, geoengine_openapi_client.LogarithmicGradientWithType):
            return LogarithmicGradientColorizer.from_response_logarithmic(inner)

        raise TypeError(f"Unknown colorizer type: {inner.type}")

Subclasses

Class variables

var no_data_color : Tuple[int, int, int, int]

Static methods

def from_response(response: geoengine_openapi_client.Colorizer) ‑> Colorizer

Create a colorizer from a response.

Expand source code
@staticmethod
def from_response(response: geoengine_openapi_client.Colorizer) -> Colorizer:
    """Create a colorizer from a response."""
    inner = response.actual_instance

    if isinstance(inner, geoengine_openapi_client.LinearGradientWithType):
        return LinearGradientColorizer.from_response_linear(inner)
    if isinstance(inner, geoengine_openapi_client.PaletteColorizer):
        return PaletteColorizer.from_response_palette(inner)
    if isinstance(inner, geoengine_openapi_client.LogarithmicGradientWithType):
        return LogarithmicGradientColorizer.from_response_logarithmic(inner)

    raise TypeError(f"Unknown colorizer type: {inner.type}")
def linear_with_mpl_cmap(color_map: Union[str, Colormap], min_max: Tuple[float, float], n_steps: int = 10, over_color: Rgba = (0, 0, 0, 0), under_color: Rgba = (0, 0, 0, 0), no_data_color: Rgba = (0, 0, 0, 0)) ‑> LinearGradientColorizer

Initialize the colorizer.

Expand source code
@staticmethod
def linear_with_mpl_cmap(
    color_map: Union[str, Colormap],
    min_max: Tuple[float, float],
    n_steps: int = 10,
    over_color: Rgba = (0, 0, 0, 0),
    under_color: Rgba = (0, 0, 0, 0),
    no_data_color: Rgba = (0, 0, 0, 0)
) -> LinearGradientColorizer:
    """Initialize the colorizer."""
    # pylint: disable=too-many-arguments

    if n_steps < 2:
        raise ValueError(f"n_steps must be greater than or equal to 2, got {n_steps} instead.")
    if min_max[1] <= min_max[0]:
        raise ValueError(f"min_max[1] must be greater than min_max[0], got {min_max[1]} and {min_max[0]}.")
    if len(over_color) != 4:
        raise ValueError(f"overColor must be a tuple of length 4, got {len(over_color)} instead.")
    if len(under_color) != 4:
        raise ValueError(f"underColor must be a tuple of length 4, got {len(under_color)} instead.")
    if len(no_data_color) != 4:
        raise ValueError(f"noDataColor must be a tuple of length 4, got {len(no_data_color)} instead.")
    if not all(0 <= elem < 256 for elem in no_data_color):
        raise ValueError(f"noDataColor must be a RGBA color specification, got {no_data_color} instead.")
    if not all(0 <= elem < 256 for elem in over_color):
        raise ValueError(f"overColor must be a RGBA color specification, got {over_color} instead.")
    if not all(0 <= elem < 256 for elem in under_color):
        raise ValueError(f"underColor must be a RGBA color specification, got {under_color} instead.")

    # get the map, and transform it to a list of (uint8) rgba values
    list_of_rgba_colors: List[npt.NDArray[np.uint8]] = ScalarMappable(cmap=color_map).to_rgba(
        np.linspace(min_max[0], min_max[1], n_steps), bytes=True)

    # if you want to remap the colors, you can do it here (e.g. cutting of the most extreme colors)
    values_of_breakpoints: List[float] = np.linspace(min_max[0], min_max[1], n_steps).tolist()

    # generate color map steps for geoengine
    breakpoints: List[ColorBreakpoint] = [
        ColorBreakpoint(
            color=(int(color[0]), int(color[1]), int(color[2]), int(color[3])), value=value
        ) for (value, color) in zip(
            values_of_breakpoints, list_of_rgba_colors)
    ]

    return LinearGradientColorizer(
        breakpoints=breakpoints,
        no_data_color=no_data_color,
        over_color=over_color,
        under_color=under_color
    )
def logarithmic_with_mpl_cmap(color_map: Union[str, Colormap], min_max: Tuple[float, float], n_steps: int = 10, over_color: Rgba = (0, 0, 0, 0), under_color: Rgba = (0, 0, 0, 0), no_data_color: Rgba = (0, 0, 0, 0)) ‑> LogarithmicGradientColorizer

Initialize the colorizer.

Expand source code
@staticmethod
def logarithmic_with_mpl_cmap(
    color_map: Union[str, Colormap],
    min_max: Tuple[float, float],
    n_steps: int = 10,
    over_color: Rgba = (0, 0, 0, 0),
    under_color: Rgba = (0, 0, 0, 0),
    no_data_color: Rgba = (0, 0, 0, 0)
) -> LogarithmicGradientColorizer:
    """Initialize the colorizer."""
    # pylint: disable=too-many-arguments

    if n_steps < 2:
        raise ValueError(f"n_steps must be greater than or equal to 2, got {n_steps} instead.")
    if min_max[0] <= 0:
        raise ValueError(f"min_max[0] must be greater than 0 for a logarithmic gradient, got {min_max[0]}.")
    if min_max[1] <= min_max[0]:
        raise ValueError(f"min_max[1] must be greater than min_max[0], got {min_max[1]} and {min_max[0]}.")
    if len(over_color) != 4:
        raise ValueError(f"overColor must be a tuple of length 4, got {len(over_color)} instead.")
    if len(under_color) != 4:
        raise ValueError(f"underColor must be a tuple of length 4, got {len(under_color)} instead.")
    if len(no_data_color) != 4:
        raise ValueError(f"noDataColor must be a tuple of length 4, got {len(no_data_color)} instead.")
    if not all(0 <= elem < 256 for elem in no_data_color):
        raise ValueError(f"noDataColor must be a RGBA color specification, got {no_data_color} instead.")
    if not all(0 <= elem < 256 for elem in over_color):
        raise ValueError(f"overColor must be a RGBA color specification, got {over_color} instead.")
    if not all(0 <= elem < 256 for elem in under_color):
        raise ValueError(f"underColor must be a RGBA color specification, got {under_color} instead.")

    # get the map, and transform it to a list of (uint8) rgba values
    list_of_rgba_colors: List[npt.NDArray[np.uint8]] = ScalarMappable(cmap=color_map).to_rgba(
        np.linspace(min_max[0], min_max[1], n_steps), bytes=True)

    # if you want to remap the colors, you can do it here (e.g. cutting of the most extreme colors)
    values_of_breakpoints: List[float] = np.logspace(np.log10(min_max[0]), np.log10(min_max[1]), n_steps).tolist()

    # generate color map steps for geoengine
    breakpoints: List[ColorBreakpoint] = [
        ColorBreakpoint(
            color=(int(color[0]), int(color[1]), int(color[2]), int(color[3])), value=value
        ) for (value, color) in zip(
            values_of_breakpoints, list_of_rgba_colors)
    ]

    return LogarithmicGradientColorizer(
        breakpoints=breakpoints,
        no_data_color=no_data_color,
        over_color=over_color,
        under_color=under_color
    )
def palette(color_mapping: Dict[float, Rgba], default_color: Rgba = (0, 0, 0, 0), no_data_color: Rgba = (0, 0, 0, 0)) ‑> PaletteColorizer

Initialize the colorizer.

Expand source code
@staticmethod
def palette(
    color_mapping: Dict[float, Rgba],
    default_color: Rgba = (0, 0, 0, 0),
    no_data_color: Rgba = (0, 0, 0, 0),
) -> PaletteColorizer:
    """Initialize the colorizer."""

    if len(no_data_color) != 4:
        raise ValueError(f"noDataColor must be a tuple of length 4, got {len(no_data_color)} instead.")
    if len(default_color) != 4:
        raise ValueError(f"defaultColor must be a tuple of length 4, got {len(default_color)} instead.")
    if not all(0 <= elem < 256 for elem in no_data_color):
        raise ValueError(f"noDataColor must be a RGBA color specification, got {no_data_color} instead.")
    if not all(0 <= elem < 256 for elem in default_color):
        raise ValueError(f"defaultColor must be a RGBA color specification, got {default_color} instead.")

    return PaletteColorizer(
        colors=color_mapping,
        no_data_color=no_data_color,
        default_color=default_color,
    )
def palette_with_colormap(values: List[float], color_map: Union[str, Colormap], default_color: Rgba = (0, 0, 0, 0), no_data_color: Rgba = (0, 0, 0, 0)) ‑> PaletteColorizer

This method generates a palette colorizer from a given list of values. A colormap can be given as an object or by name only.

Expand source code
@staticmethod
def palette_with_colormap(
    values: List[float],
    color_map: Union[str, Colormap],
    default_color: Rgba = (0, 0, 0, 0),
    no_data_color: Rgba = (0, 0, 0, 0),
) -> PaletteColorizer:
    """This method generates a palette colorizer from a given list of values.
    A colormap can be given as an object or by name only."""

    if len(no_data_color) != 4:
        raise ValueError(f"noDataColor must be a tuple of length 4, got {len(no_data_color)} instead.")
    if len(default_color) != 4:
        raise ValueError(f"defaultColor must be a tuple of length 4, got {len(default_color)} instead.")
    if not all(0 <= elem < 256 for elem in no_data_color):
        raise ValueError(f"noDataColor must be a RGBA color specification, got {no_data_color} instead.")
    if not all(0 <= elem < 256 for elem in default_color):
        raise ValueError(f"defaultColor must be a RGBA color specification, got {default_color} instead.")

    n_colors_of_cmap: int = ScalarMappable(cmap=color_map).get_cmap().N

    if n_colors_of_cmap < len(values):
        warnings.warn(UserWarning(f"Warning!\nYour colormap does not have enough colors "
                                  "to display all unique values of the palette!"
                                  f"\nNumber of values given: {len(values)} vs. "
                                  f"Number of available colors: {n_colors_of_cmap}"))

    # we only need to generate enough different colors for all values specified in the colors parameter
    list_of_rgba_colors: List[npt.NDArray[np.uint8]] = ScalarMappable(cmap=color_map).to_rgba(
        np.linspace(0, len(values), len(values)), bytes=True)

    # generate the dict with value: color mapping
    color_mapping: Dict[float, Rgba] = dict(zip(
        values,
        [(int(color[0]), int(color[1]), int(color[2]), int(color[3])) for color in list_of_rgba_colors])
    )

    return PaletteColorizer(
        colors=color_mapping,
        no_data_color=no_data_color,
        default_color=default_color,
    )

Methods

def to_api_dict(self) ‑> geoengine_openapi_client.models.colorizer.Colorizer
Expand source code
@abstractmethod
def to_api_dict(self) -> geoengine_openapi_client.Colorizer:
    pass
def to_json(self) ‑> str

Return the colorizer as a JSON string.

Expand source code
def to_json(self) -> str:
    """Return the colorizer as a JSON string."""
    return json.dumps(self.to_api_dict())
class LinearGradientColorizer (no_data_color: Rgba, breakpoints: List[ColorBreakpoint], over_color: Rgba, under_color: Rgba)

A linear gradient colorizer.

Expand source code
@dataclass
class LinearGradientColorizer(Colorizer):
    '''A linear gradient colorizer.'''
    breakpoints: List[ColorBreakpoint]
    over_color: Rgba
    under_color: Rgba

    @staticmethod
    def from_response_linear(response: geoengine_openapi_client.LinearGradientWithType) -> LinearGradientColorizer:
        """Create a colorizer from a response."""
        breakpoints = [ColorBreakpoint.from_response(breakpoint) for breakpoint in response.breakpoints]
        return LinearGradientColorizer(
            no_data_color=response.no_data_color,
            breakpoints=breakpoints,
            over_color=response.over_color,
            under_color=response.under_color,
        )

    def to_api_dict(self) -> geoengine_openapi_client.Colorizer:
        """Return the colorizer as a dictionary."""
        return geoengine_openapi_client.Colorizer(geoengine_openapi_client.LinearGradientWithType(
            type='linearGradient',
            breakpoints=[breakpoint.to_api_dict() for breakpoint in self.breakpoints],
            no_data_color=self.no_data_color,
            over_color=self.over_color,
            under_color=self.under_color
        ))

Ancestors

Class variables

var breakpoints : List[ColorBreakpoint]
var over_color : Tuple[int, int, int, int]
var under_color : Tuple[int, int, int, int]

Static methods

def from_response_linear(response: geoengine_openapi_client.LinearGradientWithType) ‑> LinearGradientColorizer

Create a colorizer from a response.

Expand source code
@staticmethod
def from_response_linear(response: geoengine_openapi_client.LinearGradientWithType) -> LinearGradientColorizer:
    """Create a colorizer from a response."""
    breakpoints = [ColorBreakpoint.from_response(breakpoint) for breakpoint in response.breakpoints]
    return LinearGradientColorizer(
        no_data_color=response.no_data_color,
        breakpoints=breakpoints,
        over_color=response.over_color,
        under_color=response.under_color,
    )

Methods

def to_api_dict(self) ‑> geoengine_openapi_client.models.colorizer.Colorizer

Return the colorizer as a dictionary.

Expand source code
def to_api_dict(self) -> geoengine_openapi_client.Colorizer:
    """Return the colorizer as a dictionary."""
    return geoengine_openapi_client.Colorizer(geoengine_openapi_client.LinearGradientWithType(
        type='linearGradient',
        breakpoints=[breakpoint.to_api_dict() for breakpoint in self.breakpoints],
        no_data_color=self.no_data_color,
        over_color=self.over_color,
        under_color=self.under_color
    ))

Inherited members

class LogarithmicGradientColorizer (no_data_color: Rgba, breakpoints: List[ColorBreakpoint], over_color: Rgba, under_color: Rgba)

A logarithmic gradient colorizer.

Expand source code
@dataclass
class LogarithmicGradientColorizer(Colorizer):
    '''A logarithmic gradient colorizer.'''
    breakpoints: List[ColorBreakpoint]
    over_color: Rgba
    under_color: Rgba

    @staticmethod
    def from_response_logarithmic(
            response: geoengine_openapi_client.LogarithmicGradientWithType) -> LogarithmicGradientColorizer:
        """Create a colorizer from a response."""
        breakpoints = [ColorBreakpoint.from_response(breakpoint) for breakpoint in response.breakpoints]
        return LogarithmicGradientColorizer(
            breakpoints=breakpoints,
            no_data_color=response.no_data_color,
            over_color=response.over_color,
            under_color=response.under_color,
        )

    def to_api_dict(self) -> geoengine_openapi_client.Colorizer:
        """Return the colorizer as a dictionary."""
        return geoengine_openapi_client.Colorizer(geoengine_openapi_client.LogarithmicGradientWithType(
            type='logarithmicGradient',
            breakpoints=[breakpoint.to_api_dict() for breakpoint in self.breakpoints],
            no_data_color=self.no_data_color,
            over_color=self.over_color,
            under_color=self.under_color,
        ))

Ancestors

Class variables

var breakpoints : List[ColorBreakpoint]
var over_color : Tuple[int, int, int, int]
var under_color : Tuple[int, int, int, int]

Static methods

def from_response_logarithmic(response: geoengine_openapi_client.LogarithmicGradientWithType) ‑> LogarithmicGradientColorizer

Create a colorizer from a response.

Expand source code
@staticmethod
def from_response_logarithmic(
        response: geoengine_openapi_client.LogarithmicGradientWithType) -> LogarithmicGradientColorizer:
    """Create a colorizer from a response."""
    breakpoints = [ColorBreakpoint.from_response(breakpoint) for breakpoint in response.breakpoints]
    return LogarithmicGradientColorizer(
        breakpoints=breakpoints,
        no_data_color=response.no_data_color,
        over_color=response.over_color,
        under_color=response.under_color,
    )

Methods

def to_api_dict(self) ‑> geoengine_openapi_client.models.colorizer.Colorizer

Return the colorizer as a dictionary.

Expand source code
def to_api_dict(self) -> geoengine_openapi_client.Colorizer:
    """Return the colorizer as a dictionary."""
    return geoengine_openapi_client.Colorizer(geoengine_openapi_client.LogarithmicGradientWithType(
        type='logarithmicGradient',
        breakpoints=[breakpoint.to_api_dict() for breakpoint in self.breakpoints],
        no_data_color=self.no_data_color,
        over_color=self.over_color,
        under_color=self.under_color,
    ))

Inherited members

class PaletteColorizer (no_data_color: Rgba, colors: Dict[float, Rgba], default_color: Rgba)

A palette colorizer.

Expand source code
@dataclass
class PaletteColorizer(Colorizer):
    '''A palette colorizer.'''
    colors: Dict[float, Rgba]
    default_color: Rgba

    @staticmethod
    def from_response_palette(response: geoengine_openapi_client.PaletteColorizer) -> PaletteColorizer:
        """Create a colorizer from a response."""

        return PaletteColorizer(
            colors={float(k): v for k, v in response.colors.items()},
            no_data_color=response.no_data_color,
            default_color=response.default_color,
        )

    def to_api_dict(self) -> geoengine_openapi_client.Colorizer:
        """Return the colorizer as a dictionary."""
        return geoengine_openapi_client.Colorizer(geoengine_openapi_client.PaletteColorizer(
            type='palette',
            colors=self.colors,
            default_color=self.default_color,
            no_data_color=self.no_data_color,
        ))

Ancestors

Class variables

var colors : Dict[float, Tuple[int, int, int, int]]
var default_color : Tuple[int, int, int, int]

Static methods

def from_response_palette(response: geoengine_openapi_client.PaletteColorizer) ‑> PaletteColorizer

Create a colorizer from a response.

Expand source code
@staticmethod
def from_response_palette(response: geoengine_openapi_client.PaletteColorizer) -> PaletteColorizer:
    """Create a colorizer from a response."""

    return PaletteColorizer(
        colors={float(k): v for k, v in response.colors.items()},
        no_data_color=response.no_data_color,
        default_color=response.default_color,
    )

Methods

def to_api_dict(self) ‑> geoengine_openapi_client.models.colorizer.Colorizer

Return the colorizer as a dictionary.

Expand source code
def to_api_dict(self) -> geoengine_openapi_client.Colorizer:
    """Return the colorizer as a dictionary."""
    return geoengine_openapi_client.Colorizer(geoengine_openapi_client.PaletteColorizer(
        type='palette',
        colors=self.colors,
        default_color=self.default_color,
        no_data_color=self.no_data_color,
    ))

Inherited members