pdstools.utils.plot_utils

Plot utilities for pdstools visualizations.

This module centralizes the small helpers that the plotting modules across pdstools all reach for: a typed Figure alias that survives without plotly installed, an optional-dependency import shim, label abbreviation, facet-title cleanup, dynamic facet sizing, and report-layout adjustments.

Attributes

Functions

get_colorscale(→ list[tuple[float, str]] | list[str])

Get the colorscale for a metric.

abbreviate_label(→ str)

Truncate a label to max_length chars, appending ... when shortened.

abbreviate_label_expr(→ polars.Expr)

Polars expression equivalent of abbreviate_label().

simplify_facet_titles(→ Figure)

Strip the column= prefix from Plotly facet annotations.

fig_update_facet(→ Figure)

Resize a faceted plot proportionally to its row count and clean labels.

update_axes_clean(→ Figure)

Clear or set both axis titles in one call.

apply_report_layout(→ Figure)

Apply Quarto-friendly sizing to a figure.

Module Contents

logger
type Figure = '_Figure'
LIFT_DIRECTION_COLORS: dict[str, str]
COLORSCALES: dict[str, Any]
get_colorscale(metric: str, default: str = 'other') list[tuple[float, str]] | list[str]

Get the colorscale for a metric.

Parameters:
  • metric (str) – The metric name to look up (e.g., “Performance”, “SuccessRate”).

  • default (str, optional) – The default colorscale key to use if metric not found, by default “other”.

Returns:

A Plotly-compatible colorscale (list of (position, color) tuples or list of colors).

Return type:

list[tuple[float, str]] | list[str]

Examples

>>> get_colorscale("Performance")
[(0, '#d91c29'), (0.01, '#F76923'), (0.3, '#20aa50'), (0.8, '#20aa50'), (1, '#0000FF')]
>>> get_colorscale("UnknownMetric")
['#d91c29', '#F76923', '#20aa50']
DEFAULT_LABEL_MAX_LENGTH = 25
abbreviate_label(label: str, max_length: int = DEFAULT_LABEL_MAX_LENGTH, *, from_end: bool = False) str

Truncate a label to max_length chars, appending ... when shortened.

Used for axis tick labels (predictor names, bin symbols, action names) that would otherwise overflow plot containers. Note that truncation is not guaranteed to produce unique labels — callers that require uniqueness must enforce that themselves.

Parameters:
  • label (str) – The original label.

  • max_length (int, optional) – Maximum length before the ellipsis is appended, by default 25.

  • from_end (bool, optional) – If True, keep the trailing max_length characters and prepend ... instead of truncating from the end. Useful for action / treatment names whose distinguishing suffix is more informative than the common prefix. Defaults to False.

Returns:

The original label if it fits, otherwise the truncated label with ... on the truncated side.

Return type:

str

abbreviate_label_expr(column: str | polars.Expr, max_length: int = DEFAULT_LABEL_MAX_LENGTH) polars.Expr

Polars expression equivalent of abbreviate_label().

Parameters:
  • column (str | pl.Expr) – Column name or expression producing string values to abbreviate.

  • max_length (int, optional) – Maximum length before the ellipsis is appended, by default 25.

Returns:

Expression that yields the abbreviated string.

Return type:

pl.Expr

simplify_facet_titles(fig: Figure) Figure

Strip the column= prefix from Plotly facet annotations.

Plotly Express labels facets as "<column_name>=<value>"; in our reports the column name is redundant context. This helper rewrites each facet annotation to show only the value.

Parameters:

fig (Figure) – The faceted Plotly figure to update in place.

Returns:

The same figure (returned for chaining).

Return type:

Figure

fig_update_facet(fig: Figure, n_cols: int = 2, base_height: int = 250, step_height: int = 270) Figure

Resize a faceted plot proportionally to its row count and clean labels.

Combines simplify_facet_titles() with a height calculation that grows the figure as facet rows are added — Plotly Express does not do this on its own, so without this helper faceted plots squash together as more facets are introduced.

Parameters:
  • fig (Figure) – The faceted figure to update.

  • n_cols (int, optional) – Number of facet columns, by default 2.

  • base_height (int, optional) – Height (px) for a single-row layout, by default 250.

  • step_height (int, optional) – Additional height (px) per row of facets, by default 270.

Returns:

The same figure with adjusted height and simplified facet titles.

Return type:

Figure

update_axes_clean(fig: Figure, x_title: str | None = '', y_title: str | None = '') Figure

Clear or set both axis titles in one call.

A surprising number of plots only need to blank one or both axis titles — this helper replaces the repeated fig.update_xaxes(title=...).update_yaxes(title=...) pairs.

Parameters:
  • fig (Figure) – The figure to update.

  • x_title (str | None, optional) – New x-axis title; "" clears it (default), None leaves it.

  • y_title (str | None, optional) – New y-axis title; "" clears it (default), None leaves it.

Returns:

The same figure (returned for chaining).

Return type:

Figure

apply_report_layout(fig: Figure, *, n_facets: int = 1, base_height: int = 400, per_facet_height: int = 200, width: int | None = None) Figure

Apply Quarto-friendly sizing to a figure.

Quarto HTML reports render charts in a fixed-width container, so charts benefit from a consistent width and a height that scales with the number of facets. Use this in report templates instead of repeating update_layout(height=..., width=...) calls in every code chunk.

Parameters:
  • fig (Figure) – The figure to size.

  • n_facets (int, optional) – Number of facets in the figure (1 for non-faceted), by default 1.

  • base_height (int, optional) – Height (px) for a single-facet figure, by default 400.

  • per_facet_height (int, optional) – Additional height (px) per extra facet, by default 200.

  • width (int | None, optional) – Optional fixed width (px). When None the figure stays responsive.

Returns:

The same figure with adjusted height (and width if provided).

Return type:

Figure

HOVER_PERFORMANCE_PCT = 'Performance: %{y:.2%}'
HOVER_SUCCESS_RATE_PCT = 'Success Rate: %{y:.3%}'
HOVER_RESPONSE_COUNT = 'Responses: %{y:,d}'
HOVER_LIFT_PCT = 'Lift: %{x:.2%}'