Source code for plotnine_extra.geoms.geom_bracket

from __future__ import annotations

from typing import TYPE_CHECKING, Any

from plotnine.doctools import document
from plotnine.geoms.geom import geom

if TYPE_CHECKING:
    import pandas as pd
    from matplotlib.axes import Axes
    from matplotlib.offsetbox import DrawingArea
    from plotnine.coords.coord import coord
    from plotnine.iapi import panel_view


def _bracket_draw_legend(
    data: "pd.Series",
    da: "DrawingArea",
    lyr,
) -> "DrawingArea":
    """Brackets carry no useful legend, return an empty area."""
    return da


[docs] @document class geom_bracket(geom): """ Draw significance brackets with labels Draws a U-shaped bracket (two vertical tips connected by a horizontal bar) with a centered text label, typically used for significance annotations. {usage} Parameters ---------- {common_parameters} tip_length : float, default=0.02 Length of the bracket tips as a fraction of the y data range. bracket_nudge_y : float, default=0 Vertical offset for the bracket. label_size : float, default=8 Font size for the label text. vjust : float, default=0 Vertical justification of the label relative to the bracket. bracket : bool, default=True If ``False``, suppress the bracket line and draw only the label. Mirrors the ``bracket`` parameter of ``ggcompare::geom_bracket``. """ _aesthetics_doc = """ {aesthetics_table} """ REQUIRED_AES = {"xmin", "xmax", "y", "label"} DEFAULT_AES = { "color": "black", "alpha": 1, } DEFAULT_PARAMS = { "stat": "identity", "position": "identity", "na_rm": False, "tip_length": 0.02, "bracket_nudge_y": 0, "label_size": 8, "vjust": 0, "bracket": True, } draw_legend = staticmethod(_bracket_draw_legend)
[docs] @staticmethod def draw_group( data: pd.DataFrame, panel_params: panel_view, coord: coord, ax: Axes, params: dict[str, Any], ): import pandas as _pd tip_length = params.get("tip_length", 0.02) bracket_nudge_y = params.get("bracket_nudge_y", 0) label_size = params.get("label_size", 8) vjust = params.get("vjust", 0) draw_bracket = params.get("bracket", True) for _, row in data.iterrows(): xmin = row["xmin"] xmax = row["xmax"] y = row["y"] + bracket_nudge_y label = row.get("label", "") color = row.get("color", "black") alpha = row.get("alpha", 1.0) # Compute tip length in data coordinates y_range = panel_params.y.range tip = tip_length * (y_range[1] - y_range[0]) # Build bracket coordinates and transform x_mid = (xmin + xmax) / 2 y_text = y + tip * 0.3 + vjust bracket_df = _pd.DataFrame( { "x": [ xmin, xmin, xmax, xmax, ], "y": [ y - tip, y, y, y - tip, ], } ) bracket_df = coord.transform(bracket_df, panel_params) label_df = _pd.DataFrame({"x": [x_mid], "y": [y_text]}) label_df = coord.transform(label_df, panel_params) if draw_bracket: ax.plot( bracket_df["x"].to_numpy(), bracket_df["y"].to_numpy(), color=color, alpha=alpha, linewidth=0.75, solid_capstyle="butt", ) if label: ax.text( label_df["x"].iloc[0], label_df["y"].iloc[0], str(label), ha="center", va="bottom", fontsize=label_size, color=color, alpha=alpha, )