Source code for tessif.frused.themes

# tessif/frused/themes.py
"""Tessif's themes designed to be used for visualization.

:mod:`~tessif.frused.themes` is a :mod:`tessif` subpackage grouping color and
hatch themes to :`tessif.frused.namedtuples.NodeColorGroupings` for convenient
and automated access.
"""
import collections
from itertools import cycle

import matplotlib.colors as mcolors
import matplotlib.pyplot as plt

import tessif.frused.spellings as spellings

#
from tessif.frused.namedtuples import NodeColorGroupings, Uid

colors = NodeColorGroupings(
    component=collections.OrderedDict(
        [
            ("bus", "#9999ff"),  # websafe very light blue
            ("sink", "#9999ff"),  # websafe very light blue
            ("storage", "#9999ff"),  # websafe very light blue
            ("source", "#9999ff"),  # websafe very light blue
            ("transformer", "#9999ff"),  # websafe very light blue
            ("connector", "#9999ff"),  # websafe very light blue
        ]
    ),
    name=collections.OrderedDict(
        [
            ("renewables", "#00ff00"),  # websafe mostly pure lime green
            ("photovoltaic", "#ff9900"),  # websafe mostly pure orange
            ("solarthermal", "#ff0099"),  # websafe mostly pure pink
            ("onshore", "#99ccff"),  # websafe very light blue
            ("offshore", "#00ccff"),  # websafe mosty pure cyan
            ("hydro_electric", "#000099"),  # websafe dark blue
            ("combined_heat_power", "#9933cc"),  # websafe strong violet
            ("power_plant", "#ff6600"),  # websafe mostly pure orange
            ("heat_plant", "#b30000"),  # strong red
            ("electrical_line", "#ffcc00"),  # websafe mostly pure yellow
            ("gas_station", "#6633cc"),
            ("gas_pipeline", "#336666"),  # websafe very dark desaturated cyan
            ("gas_delivery", "#006666"),  # websafe very dark cyan
            ("oil_pipeline", "#666666"),  # websafe very dark grey
            ("oil_delivery", "#333333"),  # websafe even verier dark grey
            ("hydro_electrical_storage", "#0000cc"),  # websafe strong blue
            # websafe mostly pure yellow
            ("electro_chemical_storage", "#ccff00"),
            ("electro_mechanical_storage", "#999900"),  # websafe dark yellow
            ("thermal_energy_storage", "#cc0033"),  # websafe strong red
            ("power2x", "#669999"),  # websafe mostly desaturated dark cyan
            ("power2heat", "#b30000"),  # strong red
            ("imported", "#ff6600"),  # websafe orange
            ("backup", "#990099"),  # websafe dark magenta
            ("demand", "#330099"),  # websafe dark violet
            ("export", "#006600"),  # websafe dark green
            ("excess", "#cc0000"),  # websafe pure red
            ("connector", "#669999"),  # websafe mostly desaturated dark cyan
        ]
    ),
    carrier=collections.OrderedDict(
        [
            ("solar", "#ff9900"),  # websafe mostly pure orange
            ("wind", "#00ccff"),  # websafe mosty pure cyan
            ("water", "#000099"),  # websafe dark blue
            ("biomass", "#009900"),  # websafe dark lime green
            ("gas", "#336666"),  # websafe very dark desaturated cyan
            ("oil", "#666666"),  # websafe very dark gray
            ("lignite", "#993300"),  # websafe dark orange
            ("hardcoal", "#000000"),  # websafe black
            ("nuclear", "#cccc00"),  # websafe strong yellow
            ("electricity", "#FFD700"),  # websafe pure yellow
            ("steam", "#cc0033"),  # websafe crimson
            ("hot_water", "#ff3300"),  # websafe mostly pure red
        ]
    ),
    sector=collections.OrderedDict(
        [
            ("power", "#ffff33"),  # websafe vivid yellow
            ("heat", "#FF0000"),  # websafe red
            ("mobility", "#669999"),  # websafe mostly desaturated dard cyan
            ("coupled", "#6633cc"),  # websafe strong violet
        ]
    ),
)
""" Tessif color themes.  Stored inside a
:attr:`~tessif.frused.namedtuples.NodeColorGroupings`
:class:`~typing.NamedTuple`. Assembled using `colorhexa
<https://www.colorhexa.com/>`_
Categorized by :attr:`~tessif.frused.namedtuples.NodeColorGroupings`

For each category there is a mapping of identifiers to colors

**Component Grouped Colors:**

.. csv-table:: internal representation
    :file: docs/source/csvs/themes/component.csv

.. image:: ../../images/themes/component_colors.png
    :align: center
    :alt: Image showing the supported component colors

|

**Named Grouped Colors:**

.. csv-table:: internal representation
    :file: docs/source/csvs/themes/name.csv
    :stub-columns: 1

.. image:: ../../images/themes/name_colors.png
    :align: center
    :alt: Image showing the supported name colors

|

**Carrier Grouped Colors:**

.. csv-table:: internal representation
    :file: docs/source/csvs/themes/carrier.csv
    :stub-columns: 1

.. image:: ../../images/themes/carrier_colors.png
    :align: center
    :alt: Image showing the supported carrier colors

|

**Sector Grouped Colors:**

.. csv-table:: internal representation
    :file: docs/source/csvs/themes/sector.csv
    :stub-columns: 1

.. image:: ../../images/themes/sector_colors.png
    :align: center
    :alt: Image showing the supported sector colors
"""


cmaps = NodeColorGroupings(
    component=collections.OrderedDict(
        [
            (
                "bus",
                [
                    "#4d4dff",
                    "#6666ff",
                    "#8080ff",
                    "#9999ff",
                    "#b3b3ff",
                    "#ccccff",
                    "#e6e6ff",
                ],
            ),  # very light blue
            (
                "sink",
                [
                    "#4d4dff",
                    "#6666ff",
                    "#8080ff",
                    "#9999ff",
                    "#b3b3ff",
                    "#ccccff",
                    "#e6e6ff",
                ],
            ),  # very light blue
            (
                "storage",
                [
                    "#4d4dff",
                    "#6666ff",
                    "#8080ff",
                    "#9999ff",
                    "#b3b3ff",
                    "#ccccff",
                    "#e6e6ff",
                ],
            ),  # very light blue
            (
                "source",
                [
                    "#4d4dff",
                    "#6666ff",
                    "#8080ff",
                    "#9999ff",
                    "#b3b3ff",
                    "#ccccff",
                    "#e6e6ff",
                ],
            ),  # very light blue
            (
                "transformer",
                [
                    "#4d4dff",
                    "#6666ff",
                    "#8080ff",
                    "#9999ff",
                    "#b3b3ff",
                    "#ccccff",
                    "#e6e6ff",
                ],
            ),  # very light blue
            (
                "connector",
                [
                    "#4d4dff",
                    "#6666ff",
                    "#8080ff",
                    "#9999ff",
                    "#b3b3ff",
                    "#ccccff",
                    "#e6e6ff",
                ],
            ),  # very light blue
        ]
    ),
    carrier=collections.OrderedDict(
        [
            (
                "solar",
                [
                    "#ff5900",
                    "#ff6f00",
                    "#ff8400",
                    "#ff9900",
                    "#ffae00",
                    "#ffc400",
                    "#ffd900",
                ],
            ),  # orange
            (
                "wind",
                [
                    "#002aff",
                    "#008cff",
                    "#00b7ff",
                    "#00ccff",
                    "#00e1ff",
                    "#00f7ff",
                    "#00fff2",
                ],
            ),  # cyan
            (
                "water",
                [
                    "#00004d",
                    "#190099",
                    "#0d0099",
                    "#000099",
                    "#000d99",
                    "#001a99",
                    "#002699",
                ],
            ),  # dark blue
            (
                "biomass",
                [
                    "#004d00",
                    "#006600",
                    "#008000",
                    "#009900",
                    "#00b300",
                    "#00cc00",
                    "#00e600",
                ],
            ),  # dark lime
            (
                "gas",
                [
                    "#1a3333",
                    "#224444",
                    "#2b5555",
                    "#336666",
                    "#3c7777",
                    "#448888",
                    "#4d9999",
                ],
            ),  # dark desaturated cyan
            (
                "oil",
                [
                    "#404040",
                    "#4d4d4d",
                    "#595959",
                    "#666666",
                    "#737373",
                    "#808080",
                    "#8c8c8c",
                ],
            ),  # very dark grey
            (
                "lignite",
                [
                    "#4d1a00",
                    "#662200",
                    "#802b00",
                    "#993300",
                    "#b33c00",
                    "#cc4400",
                    "#e64d00",
                ],
            ),  # dark brown
            (
                "hardcoal",
                [
                    "#000000",
                    "#0d0d0d",
                    "#191919",
                    "#262626",
                    "#333333",
                    "#404040",
                    "#4c4c4c",
                ],
            ),  # black
            (
                "nuclear",
                [
                    "#808000",
                    "#999900",
                    "#b3b300",
                    "#cccc00",
                    "#e6e600",
                    "#ffff00",
                    "#ffff1a",
                ],
            ),  # strong yellow
            (
                "electricity",
                [
                    "#b39700",
                    "#ccac00",
                    "#e6c200",
                    "#ffd700",
                    "#ffdb1a",
                    "#ffdf33",
                    "#ffe34d",
                ],
            ),  # pure yellow
            (
                "steam",
                [
                    "#800020",
                    "#990026",
                    "#b3002a",
                    "#cc0033",
                    "#e60039",
                    "#ff0040",
                    "#ff1a53",
                ],
            ),  # crimson
            (
                "hot_water",
                [
                    "#b32400",
                    "#cc2900",
                    "#e62e00",
                    "#ff3300",
                    "#ff471a",
                    "#ff5c33",
                    "#ff704d",
                ],
            ),  # pure red
        ]
    ),
    sector=collections.OrderedDict(
        [
            (
                "power",
                [
                    "#ff5900",
                    "#ff6f00",
                    "#ff8400",
                    "#ff9900",
                    "#ffae00",
                    "#ffc400",
                    "#ffd900",
                ],
            ),  # vivid yellow
            (
                "heat",
                [
                    "#b30000",
                    "#cc0000",
                    "#e60000",
                    "#ff0000",
                    "#ff1a1a",
                    "#ff3333",
                    "#ff4d4d",
                ],
            ),  # red
            (
                "mobility",
                [
                    "#476b6b",
                    "#527a7a",
                    "#5c8a8a",
                    "#669999",
                    "#75a3a3",
                    "#85adad",
                    "#94b8b8",
                ],
            ),  # desaturated dark cyan
            (
                "coupled",
                [
                    "#47248f",
                    "#5229a3",
                    "#5c2eb8",
                    "#6633cc",
                    "#7547d1",
                    "#855cd6",
                    "#9470db",
                ],
            ),  # strong violet
        ]
    ),
    name=collections.OrderedDict(
        [
            (
                "renewables",
                [
                    "#00b300",
                    "#00cc00",
                    "#00e600",
                    "#00ff00",
                    "#1aff1a",
                    "#33ff33",
                    "#4dff4d",
                ],
            ),  # lime green
            (
                "photovoltaic",
                [
                    "#b37400",
                    "#cc8400",
                    "#e69500",
                    "#ffa500",
                    "#ffae1a",
                    "#ffb733",
                    "#ffc04d",
                ],
            ),  # pure orange
            (
                "solarthermal",
                [
                    "#b300b6",
                    "#cc007a",
                    "#e6008a",
                    "#ff0099",
                    "#ff1aa3",
                    "#ff33ad",
                    "#ff4db8",
                ],
            ),  # pure pink
            (
                "offshore",
                [
                    "#4da6ff",
                    "#66b3ff",
                    "#80bfff",
                    "#99ccff",
                    "#b3d9ff",
                    "#cce6ff",
                    "#e6f2ff",
                ],
            ),  # pure cyan
            (
                "onshore",
                [
                    "#002aff",
                    "#008cff",
                    "#00b7ff",
                    "#00ccff",
                    "#00e1ff",
                    "#00f7ff",
                    "#00fff2",
                ],
            ),  # very light blue
            (
                "hydro_electric",
                [
                    "#00004d",
                    "#190099",
                    "#0d0099",
                    "#000099",
                    "#000d99",
                    "#001a99",
                    "#002699",
                ],
            ),  # dark blue
            (
                "combined_heat_power",
                [
                    "#6b248f",
                    "#7a29a3",
                    "#8a2eb8",
                    "#9933cc",
                    "#a347d1",
                    "#ad5cd6",
                    "#b870db",
                ],
            ),  # violet
            (
                "power_plant",
                [
                    "#b34700",
                    "#cc5200",
                    "#c65c00",
                    "#ff6600",
                    "#ff751a",
                    "#ff8533",
                    "#ff944d",
                ],
            ),  # pure orange
            (
                "heat_plant",
                [
                    "#670000",
                    "#800000",
                    "#9a0000",
                    "#b30000",
                    "#cd0000",
                    "#e60000",
                    "#ff0000",
                ],
            ),  # strong red
            (
                "electrical_line",
                [
                    "#b38f00",
                    "#cca300",
                    "#e6b800",
                    "#ffcc00",
                    "#ffd11a",
                    "#ffd633",
                    "#ffdb4d",
                ],
            ),  # pure yellow
            (
                "gas_pipeline",
                [
                    "#1a3333",
                    "#224444",
                    "#2b5555",
                    "#336666",
                    "#3c7777",
                    "#448888",
                    "#4d9999",
                ],
            ),  # v. dark d. cyan
            (
                "gas_delivery",
                [
                    "#003434",
                    "#004d4d",
                    "#006767",
                    "#008080",
                    "#009a9a",
                    "#00b3b3",
                    "#00cdcd",
                ],
            ),  # very dark cyan
            (
                "oil_pipeline",
                [
                    "#404040",
                    "#4d4d4d",
                    "#595959",
                    "#666666",
                    "#737373",
                    "#808080",
                    "#8c8c8c",
                ],
            ),  # very dark grey
            (
                "oil_delivery",
                [
                    "#0d0d0d",
                    "#1a1a1a",
                    "#262626",
                    "#333333",
                    "#404040",
                    "#4d4d4d",
                    "#595959",
                ],
            ),  # darker grey
            (
                "hydro_electrical_storage",
                [
                    "#000080",
                    "#000099",
                    "#0000b3",
                    "#0000cc",
                    "#0000c6",
                    "#0000ff",
                    "#1a1aff",
                ],
            ),  # strong blue
            (
                "electro_chemical_storage",
                [
                    "#8fb300",
                    "#a3cc00",
                    "#b8e600",
                    "#ccff00",
                    "#d1ff1a",
                    "#d6ff33",
                    "#dbff4d",
                ],
            ),  # pure yellow
            (
                "electro_mechanical_storage",
                [
                    "#343400",
                    "#4d4d00",
                    "#676700",
                    "#808000",
                    "#9a9a00",
                    "#b3b300",
                    "#cdcd00",
                ],
            ),  # dark yellow
            (
                "thermal_energy_storage",
                [
                    "#800020",
                    "#990026",
                    "#b3002a",
                    "#cc0033",
                    "#e60039",
                    "#ff0040",
                    "#ff1a53",
                ],
            ),  # strong red
            (
                "power2x",
                [
                    "#476b6b",
                    "#527a7a",
                    "#5c8a8a",
                    "#669999",
                    "#75a3a3",
                    "#85adad",
                    "#94b8b8",
                ],
            ),  # desaturat. dark cyan
            (
                "power2heat",
                [
                    "#670000",
                    "#800000",
                    "#9a0000",
                    "#b30000",
                    "#cd0000",
                    "#e60000",
                    "#ff0000",
                ],
            ),  # strong red
            (
                "imported",
                [
                    "#b33500",
                    "#cc3d00",
                    "#e64400",
                    "#ff4c00",
                    "#ff5e1a",
                    "#ff7033",
                    "#ff824d",
                ],
            ),  # orange
            (
                "backup",
                [
                    "#340034",
                    "#4d004d",
                    "#670067",
                    "#800080",
                    "#9a009a",
                    "#b300b3",
                    "#cd00cd",
                ],
            ),  # dark magenta
            (
                "demand",
                [
                    "#1a004d",
                    "#220066",
                    "#2b0080",
                    "#330099",
                    "#3b00b3",
                    "#4400cc",
                    "#4c00e6",
                ],
            ),  # dark violet
            (
                "export",
                [
                    "#001800",
                    "#003100",
                    "#004b00",
                    "#006400",
                    "#007e00",
                    "#009700",
                    "#00b100",
                ],
            ),  # dark green
            (
                "excess",
                [
                    "#800000",
                    "#990000",
                    "#b30000",
                    "#cc0000",
                    "#e60000",
                    "#ff0000",
                    "#ff1a1a",
                ],
            ),  # pure red
        ]
    ),
)
""" Tessif colormap themes. Stored inside a
:attr:`~tessif.frused.namedtuples.NodeColorGroupings`
:class:`~typing.NamedTuple`. Assembled using `colorhexa
<https://www.colorhexa.com/>`_
Categorized by :attr:`~tessif.frused.namedtuples.NodeColorGroupings`

For each category there is a mapping of identifiers to colors

|

**Component Grouped Colormaps:**

.. csv-table:: internal representation
    :file: docs/source/csvs/themes/component_colormaps.csv

.. image:: ../../images/themes/component_colormaps.png
    :align: center
    :alt: Image showing the supported component colormaps

|

**Name Grouped Colormaps:**

.. csv-table:: internal representation
    :file: docs/source/csvs/themes/name_colormaps.csv
    :stub-columns: 1

.. image:: ../../images/themes/name_colormaps.png
    :align: center
    :alt: Image showing the supported name colormaps

|

**Carrier Grouped Colormaps:**

.. csv-table:: internal representation
    :file: docs/source/csvs/themes/carrier_colormaps.csv
    :stub-columns: 1

.. image:: ../../images/themes/carrier_colormaps.png
    :align: center
    :alt: Image showing the supported carrier colormaps

|

**Sector Grouped Colormaps:**

.. csv-table:: internal representation
    :file: docs/source/csvs/themes/sector_colormaps.csv
    :stub-columns: 1

.. image:: ../../images/themes/sector_colormaps.png
    :align: center
    :alt: Image showing the supported sector colormap
"""

ccycles = NodeColorGroupings(
    *[
        collections.OrderedDict(
            [
                (catgry, cycle(color_list))
                for catgry, color_list in cmaps._asdict()[key].items()
            ]
        )
        for key in cmaps._asdict().keys()
    ]
)
"""
:mod:`~tessif` cycled colormaps. Stored inside a
:attr:`~tessif.frused.namedtuples.NodeColorGroupings`
:class:`~typing.NamedTuple`.
"""

hatches = NodeColorGroupings(
    component=collections.OrderedDict(
        [
            ("bus", "/"),
            ("sink", "\\"),
            ("source", "."),
            ("storage", "|"),
            ("transformer", "-"),
            ("connector", "x"),
        ]
    ),
    carrier=collections.OrderedDict(
        [
            ("solar", "/"),
            ("wind", "\\"),
            ("water", "."),
            ("biomass", "|"),
            ("gas", "-"),
            ("oil", "+/"),
            ("lignite", "o"),
            ("hardcoal", "."),
            ("nuclear", "*"),
            ("electricity", "//"),
            ("steam", "\\\\"),
            ("hot_water", "||"),
        ]
    ),
    sector=collections.OrderedDict(
        [
            ("power", "/"),
            ("heat", "\\"),
            ("mobility", "|"),
            ("coupled", "x"),
        ]
    ),
    name=collections.OrderedDict(
        [
            ("photovoltaic", "/"),
            ("solarthermal", "//"),
            ("onshore", "\\"),
            ("offshore", "\\\\"),
            ("hydro_electric", "o"),
            ("combined_heat_power", "+"),
            ("power_plant", "|"),
            ("heat_plant", "-"),
            ("electrical_line", "++"),
            ("gas_pipeline", "--"),
            ("gas_delivery", "---"),
            ("oil_pipeline", "+/"),
            ("oil_delivery", "+/+/"),
            ("bus", "."),
            ("hydro_electrical_storage", "oo"),
            ("electro_chemical_storage", "xx"),
            ("electro_mechanical_storage", "||"),
            ("thermal_energy_storage", "--"),
            ("power2x", "xxx"),
        ]
    ),
)
"""
:mod:`~tessif` hatch themes. Stored inside a
:attr:`~tessif.frused.namedtuples.NodeColorGroupings`
:class:`~typing.NamedTuple`.

For each category there is a mapping of identifiers to hatches

|

**Component Grouped Hatches:**

.. csv-table:: internal representation
    :file: docs/source/csvs/themes/component_hatches.csv
    :stub-columns: 1

.. image:: ../../images/themes/component_hatches.png
    :align: center
    :alt: Image showing the supported name hatches

|

**Name Grouped Hatches:**

.. csv-table:: internal representation
    :file: docs/source/csvs/themes/name_hatches.csv
    :stub-columns: 1

.. image:: ../../images/themes/name_hatches.png
    :align: center
    :alt: Image showing the supported name hatches

|

**Carrier Grouped Hatches:**

.. csv-table:: internal representation
    :file: docs/source/csvs/themes/carrier_hatches.csv
    :stub-columns: 1

.. image:: ../../images/themes/carrier_hatches.png
    :align: center
    :alt: Image showing the supported carrier hatches

|

**Sector Grouped Hatches:**

.. csv-table:: internal representation
    :file: docs/source/csvs/themes/sector_hatches.csv
    :stub-columns: 1

.. image:: ../../images/themes/sector_hatches.png
    :align: center
    :alt: Image showing the supported sector hatches
"""


hmaps = {
    "sector": collections.OrderedDict(
        [
            ("power", ["/", "\\", "//", "\\\\", "///", "\\\\\\"]),
            ("heat", ["-", "|", "--", "||", "---", "|||"]),
            ("mobility", ["x", "+/", "xx", "+/+/", "xxx", "+/+/+/"]),
        ]
    ),
}
"""
Mapping of :mod:`~tessif` hatchmaps. Usefull when plotting sector grouped
results to distinguish the individual components without coloring.

|

**Sector Grouped Hatchmap:**

.. csv-table:: internal representation
    :file: docs/source/csvs/themes/sector_hatchmaps.csv
    :stub-columns: 1
"""


def _plot_colortable(colors, title, sort_colors=True, emptycols=0):
    """Plot color themes.

    Inspired by matplotlib's `documentation
    <https://matplotlib.org/3.2.2/gallery/color/named_colors.html>`_.
    """
    cell_width = 212
    cell_height = 22
    swatch_width = 48
    margin = 12
    topmargin = 40

    # Sort colors by hue, saturation, value and name.
    if sort_colors is True:
        by_hsv = sorted(
            (tuple(mcolors.rgb_to_hsv(mcolors.to_rgb(color))), name)
            for name, color in colors.items()
        )
        names = [name for hsv, name in by_hsv]
    else:
        names = list(colors)

    n = len(names)
    ncols = 4 - emptycols
    nrows = n // ncols + int(n % ncols > 0)

    width = cell_width * 4 + 2 * margin
    height = cell_height * nrows + margin + topmargin
    dpi = 72

    fig, ax = plt.subplots(figsize=(width / dpi, height / dpi), dpi=dpi)
    fig.subplots_adjust(
        margin / width,
        margin / height,
        (width - margin) / width,
        (height - topmargin) / height,
    )
    ax.set_xlim(0, cell_width * 4)
    ax.set_ylim(cell_height * (nrows - 0.5), -cell_height / 2.0)
    ax.yaxis.set_visible(False)
    ax.xaxis.set_visible(False)
    ax.set_axis_off()
    ax.set_title(title, fontsize=24, loc="left", pad=10)

    for i, name in enumerate(names):
        row = i % nrows
        col = i // nrows
        y = row * cell_height

        swatch_start_x = cell_width * col
        swatch_end_x = cell_width * col + swatch_width
        text_pos_x = cell_width * col + swatch_width + 7

        ax.text(
            text_pos_x,
            y,
            name,
            fontsize=14,
            horizontalalignment="left",
            verticalalignment="center",
        )

        ax.hlines(y, swatch_start_x, swatch_end_x, color=colors[name], linewidth=18)

    return fig


def _plot_color_gradients(category, cmap_dct):
    """Plot color gradients.

    Utility for plotting colormap examples. Inspired by
    matplotlib's `documentation
    <https://matplotlib.org/3.1.0/tutorials/colors/colormaps.html>`_.
    """
    import numpy as np

    gradient = np.linspace(0, 1, 256)
    gradient = np.vstack((gradient, gradient))

    fig, axes = plt.subplots(nrows=len(cmap_dct))
    fig.subplots_adjust(top=0.95, bottom=0.01, left=0.2, right=0.99)
    axes[0].set_title(category + " colormaps", fontsize=14)

    for ax, name in zip(axes, cmap_dct):
        ax.imshow(gradient, aspect="auto", cmap=mcolors.ListedColormap(cmap_dct[name]))
        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, name, va="center", ha="right", fontsize=10)

    # Turn off *all* ticks & spines, not just the ones with colormaps.
    for ax in axes:
        ax.set_axis_off()

    return fig


def _plot_hatches(category, hatch_map, sort_colors=True, emptycols=0):
    """Plot hatches.

    Utility for plotting color themes. Inspired by
    matplotlib's `documentation
    <https://matplotlib.org/3.2.2/gallery/color/named_colors.html>`_.

    And a pach hatching example from `so
    <https://stackoverflow.com/a/25185432>`
    """
    import matplotlib.patches as patches
    import matplotlib.pyplot as plt

    cell_width = 212
    cell_height = 22
    swatch_width = 48
    margin = 12
    topmargin = 40

    n = len(hatch_map)
    ncols = 4 - emptycols
    nrows = n // ncols + int(n % ncols > 0)

    width = cell_width * 4 + 2 * margin
    height = cell_height * nrows + margin + topmargin
    dpi = 72

    fig, ax = plt.subplots(figsize=(width / dpi, height / dpi), dpi=dpi)
    fig.subplots_adjust(
        margin / width,
        margin / height,
        (width - margin) / width,
        (height - topmargin) / height,
    )
    ax.set_xlim(0, cell_width * 4)
    ax.set_ylim(cell_height * (nrows - 0.5), -cell_height / 2.0)
    ax.yaxis.set_visible(False)
    ax.xaxis.set_visible(False)
    ax.set_axis_off()
    ax.set_title(category, fontsize=24, loc="left", pad=10)

    for i, name in enumerate(hatch_map):
        row = i % nrows
        col = i // nrows
        y = row * cell_height

        swatch_start_x = cell_width * col
        swatch_end_x = cell_width * col + swatch_width
        text_pos_x = cell_width * col + swatch_width + 7

        ax.text(
            text_pos_x,
            y,
            name,
            fontsize=14,
            horizontalalignment="left",
            verticalalignment="center",
        )

        ax.add_patch(
            patches.Rectangle(
                (swatch_start_x, y - 9),
                swatch_end_x - swatch_start_x,
                18,
                hatch=hatch_map[name],
                fill=False,
                snap=False,
                linewidth=0,
            )
        )

    return fig


[docs]def match_theme( strings, theme="colors", grouping="name", ): """ Match a collection of strings to tessf's theme groupings. Parameters ---------- strings: ~collections.abc.Iterable Iterable of strings which are tried to be matched to registerd theme values. theme: str String specifying one of :mod:`tessif's themes <tessif.frused.themes>` like ``colors``, etc. grouping: str String specifying one of the :attr:`~tessif.frused.namedtuples.NodeColorGroupings` the :paramref:`~match_theme.theme` provides Return ------ dict Mapping of the provided strings to the matched theme values Example ------- Create a :class:`tessif energy system <tessif.model.energy_system.AbstractEnergySystem>` and create a color mapping using it's nodes: 1. Create the tessif energy system using the :ref:`Example Hub <Examples>`: >>> import tessif.examples.data.tsf.py_hard as coded_examples >>> tessif_es = coded_examples.create_fpwe() 2. Create a list of node names: >>> node_names = [str(node.uid) for node in tessif_es.nodes] 3. Match the node colors: >>> from tessif.frused.themes import match_theme >>> node_colors = match_theme( ... strings=node_names, theme='colors', grouping='name') >>> import pprint >>> pprint.pprint(node_colors) {'Battery': '#ccff00', 'Demand': '#330099', 'Gas Station': '#6633cc', 'Generator': '#ff6600', 'Pipeline': '#336666', 'Powerline': '#ffcc00', 'Solar Panel': '#ff9900'} """ matched_theme = dict() for string in strings: # get requested theme group of this module theme_group = getattr(globals().get(theme), grouping) # reconstruct the uid from its string representation: uid = Uid.reconstruct(string) # match reconstructed uid groupings attribute to spellings: for registered_key in theme_group: if any( tag == getattr(uid, grouping) for tag in getattr(spellings, registered_key) ): matched_theme[string] = theme_group[registered_key] return matched_theme