Source code for currentscape.legends

"""Legends related functions."""

# Copyright 2023 Blue Brain Project / EPFL

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

#     http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# pylint: disable=wrong-import-position

import matplotlib

from matplotlib.legend_handler import HandlerTuple

from currentscape.mapper import map_colors
from currentscape.plotting import get_colors_hatches_lines_lists, select_color


[docs] def base_legend( ax, curr_names, bg_color, ypos, idx_names=None, handlelength=None, lines=False ): """Returns a legend with all current names. Args: ax (matplotlib.axes): currentscape axis curr_names (list of str): legend labels / current names bg_color (color): background color for legend box ypos (float): y-axis position of legend box. 1 is top of axis. idx_names (ndarray of ints): indexes to new name order (new_names = names[idx_names]) handlelength (float): size of the handles. Takes default value if None. No handles displayed if 0. lines (bool): if True, get lines as handles. if False, get patches as handles. """ if idx_names is None: idx_names = range(len(curr_names)) # create a patch (proxy artist) or a line for every current if lines: handles = [ matplotlib.lines.Line2D([], [], label=curr_names[i]) for i in idx_names ] else: handles = [matplotlib.patches.Patch(label=curr_names[i]) for i in idx_names] # put those patched as legend-handles into the legend leg = ax.legend( handles=handles, bbox_to_anchor=(1.01, ypos), loc=2, borderaxespad=0.0, facecolor=bg_color, edgecolor="black", fancybox=False, # disable round edges handlelength=handlelength, ) leg.get_frame().set_linewidth(0.5) # set border thickness return leg
[docs] def set_legend(ax, cmap, curr_names, bg_color, ypos, idx_names=None, handlelength=0): """Set each current name color-coded in legend. Args: ax (matplotlib.axes): currentscape axis cmap (matplotlib.colors.Colormap): colormap curr_names (list of str): legend labels / current names bg_color (color): background color for legend box ypos (float): y-axis position of legend box. 1 is top of axis. idx_names (ndarray of ints): indexes to new name order (new_names = names[idx_names]) handlelength (float): size of the handles. Takes default value if None. No handles displayed if 0. """ leg = base_legend(ax, curr_names, bg_color, ypos, idx_names, handlelength) # set legend label color & boldness for i_color, text in enumerate(leg.texts): # + 2 because there is black and white at the end of cmap text.set_color(select_color(cmap, i_color, len(curr_names))) text.set_weight("bold")
[docs] def set_legend_with_hatches(ax, cmap, mapper, c, idx_names): """Create legend and color each current name, and set handles color and pattern. Args: ax (matplotlib.axes): currentscape axis cmap (matplotlib.colors.Colormap): colormap mapper (int): number used to mix color and patterns c (dict): config idx_names (ndarray of ints): indexes to new name order (new_names = names[idx_names]) """ curr_names = c["current"]["names"] bg_color = c["legend"]["bgcolor"] ypos = c["legend"]["ypos"] leg = base_legend(ax, curr_names, bg_color, ypos, idx_names) # set legend label color & boldness, and handles color&pattern for i_color, (text, handle) in enumerate(zip(leg.texts, leg.legendHandles)): color, hatch, _ = get_colors_hatches_lines_lists(c, i_color, cmap, mapper) text.set_color(color) text.set_weight("bold") handle.set_facecolor(color) handle.set_hatch(hatch)
[docs] def set_legend_with_lines(ax, cmap, mapper, c, idx_names, names): """Create legend and color each current name, and set handles color and pattern. Args: ax (matplotlib.axes): currentscape axis cmap (matplotlib.colors.Colormap): colormap mapper (int): number used to mix color and patterns c (dict): config idx_names (ndarray of ints): indexes to new name order (new_names = names[idx_names]) names (list of str): legend labels """ bg_color = c["legend"]["bgcolor"] ypos = c["legend"]["ypos"] leg = base_legend(ax, names, bg_color, ypos, idx_names, lines=True) # set legend label color & boldness, and handles color&pattern lw = c["lw"] for i_color, (text, handle) in enumerate(zip(leg.texts, leg.legendHandles)): color, _, line = get_colors_hatches_lines_lists(c, i_color, cmap, mapper) text.set_color(color) text.set_weight("bold") handle.set_color(color) handle.set_linestyle(line) handle.set_linewidth(lw)
[docs] def get_handles_with_hatches_and_linestyles(c, cmap, mapper, N_curr): """Return handles as a list of tuples (patch, line). With patch showing color and hatch and line showing the linestyle. Args: c (dict): config cmap (matplotlib.colors.Colormap): colormap mapper (int): number used to mix color and patterns N_curr (int): number of currents """ lw = c["lw"] # create a patch (proxy artist) for every current handles = [] for i in range(N_curr): color, hatch, line = get_colors_hatches_lines_lists(c, i, cmap, mapper) handles.append( ( matplotlib.patches.Patch(facecolor=color, hatch=hatch), matplotlib.lines.Line2D([], [], color=color, ls=line, lw=lw), ) ) return handles
[docs] def set_legend_with_hatches_and_linestyles(ax, cmap, mapper, c, idx_names): """Create legend and color each current name, and set handles color and pattern. Args: ax (matplotlib.axes): currentscape axis cmap (matplotlib.colors.Colormap): colormap mapper (int): number used to mix color and patterns c (dict): config idx_names (ndarray of ints): indexes to new name order (new_names = names[idx_names]) """ bg_color = c["legend"]["bgcolor"] ypos = c["legend"]["ypos"] curr_names = c["current"]["names"] n_col = c["colormap"]["n_colors"] handlelength = c["legend"]["handlelength"] handles = get_handles_with_hatches_and_linestyles(c, cmap, mapper, len(idx_names)) # put those patched as legend-handles into the legend leg = ax.legend( handles=handles, labels=[curr_names[i] for i in idx_names], bbox_to_anchor=(1.01, ypos), loc=2, borderaxespad=0.0, facecolor=bg_color, edgecolor="black", fancybox=False, # disable round edges handler_map={tuple: HandlerTuple(ndivide=None, pad=0.2)}, handlelength=2 * handlelength, ) leg.get_frame().set_linewidth(0.5) # set border thickness # set legend label color & boldness, and handles color&pattern for i_color, text in enumerate(leg.texts): text.set_color(cmap(map_colors(i_color, n_col, mapper))) text.set_weight("bold")