Source code for figrecipe._wrappers._panel_labels

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Panel label utilities for multi-panel figures."""

import string
from typing import TYPE_CHECKING, Any, List, Optional, Tuple

if TYPE_CHECKING:
    from ._axes import RecordingAxes


def add_panel_labels(
    all_axes: List["RecordingAxes"],
    labels: Optional[List[str]],
    loc: str,
    offset: Tuple[float, float],
    fontsize: float,
    fontweight: str,
    text_color: str,
    record_callback: Any,
    **kwargs,
) -> List[Any]:
    """Add panel labels (A, B, C, D, etc.) to axes.

    Parameters
    ----------
    all_axes : list of RecordingAxes
        Flattened list of all axes.
    labels : list of str or None
        Custom labels. If None, uses uppercase letters.
    loc : str
        Location hint: 'upper left', 'upper right', 'lower left', 'lower right'.
    offset : tuple of float
        (x, y) offset in axes coordinates.
    fontsize : float
        Font size in points.
    fontweight : str
        Font weight.
    text_color : str
        Text color.
    record_callback : callable
        Callback to record panel labels info.
    **kwargs
        Additional arguments passed to ax.text().

    Returns
    -------
    list of Text
        The matplotlib Text objects created.
    """
    n_axes = len(all_axes)

    # Generate default labels if not provided
    if labels is None:
        labels = list(string.ascii_uppercase[:n_axes])
    elif len(labels) < n_axes:
        # Extend with letters if not enough labels provided
        labels = list(labels) + list(string.ascii_uppercase[len(labels) : n_axes])

    # Calculate position based on loc
    x, y, ha, va = _calculate_position(loc, offset)

    # Record panel labels
    record_callback(
        {
            "labels": labels[:n_axes],
            "loc": loc,
            "offset": offset,
            "fontsize": fontsize,
            "fontweight": fontweight,
            "color": text_color,
            "kwargs": kwargs,
        }
    )

    # Add labels to each axes
    text_objects = []
    for ax, label in zip(all_axes, labels[:n_axes]):
        text = ax.ax.text(
            x,
            y,
            label,
            transform=ax.ax.transAxes,
            fontsize=fontsize,
            fontweight=fontweight,
            color=text_color,
            ha=ha,
            va=va,
            **kwargs,
        )
        text_objects.append(text)

    return text_objects


def _calculate_position(
    loc: str, offset: Tuple[float, float]
) -> Tuple[float, float, str, str]:
    """Calculate text position and alignment based on location.

    Returns
    -------
    tuple
        (x, y, ha, va) where ha/va are horizontal/vertical alignment.
    """
    if loc == "upper left":
        x, y = offset
        ha, va = "right", "bottom"
    elif loc == "upper right":
        x, y = offset
        ha, va = "left", "bottom"
    elif loc == "lower left":
        x, y = offset[0], -offset[1] + 1.0
        ha, va = "right", "top"
    elif loc == "lower right":
        x, y = offset
        ha, va = "left", "top"
    else:
        x, y = offset
        ha, va = "right", "bottom"

    return x, y, ha, va


__all__ = ["add_panel_labels", "panel_label"]


[docs] def panel_label( ax: Any, label: str, loc: str = "upper left", offset: Tuple[float, float] = (-0.1, 1.05), fontsize: float = 10, fontweight: str = "bold", text_color: str = "black", **kwargs, ) -> Any: """Place a single panel label (A, B, C, etc.) on one axes. Parameters ---------- ax : matplotlib.axes.Axes The axes to annotate. label : str The panel label text (e.g. 'A', 'B', '(1)'). loc : str Location hint: 'upper left' (default), 'upper right', 'lower left', 'lower right'. offset : tuple of float (x, y) offset in axes coordinates. Default (-0.1, 1.05). fontsize : float Font size in points (default 10). fontweight : str Font weight (default 'bold'). text_color : str Text color (default 'black'). **kwargs Additional arguments passed to ``ax.text()``. Returns ------- matplotlib.text.Text The created text annotation. """ x, y, ha, va = _calculate_position(loc, offset) return ax.ax.text( x, y, label, transform=ax.ax.transAxes, fontsize=fontsize, fontweight=fontweight, color=text_color, ha=ha, va=va, **kwargs, )
# EOF