Source code for knowledgespaces.viz.diagnostics

"""Optional matplotlib diagnostics for complete BLIM response tables."""

from __future__ import annotations

from typing import TYPE_CHECKING, Literal, cast

import numpy as np

from knowledgespaces.viz.hasse import _MATPLOTLIB_IMPORT_ERROR

if TYPE_CHECKING:
    from matplotlib.axes import Axes
    from matplotlib.figure import Figure

    from knowledgespaces.estimation.diagnostics import BLIMResiduals


[docs] def plot_blim_residuals( residuals: BLIMResiduals, *, kind: Literal["deviance", "pearson"] = "deviance", ax: Axes | None = None, figsize: tuple[float, float] = (8, 5), ) -> Figure: """Plot signed residuals against predicted response probabilities. Uses all cells, including zero observed counts. The horizontal zero line is a visual reference, not a significance threshold. A table with infinite residuals is rejected explicitly; inspect impossible observed cells in the numerical result before plotting. Requires the viz extra. """ if kind not in ("deviance", "pearson"): raise ValueError("kind must be 'deviance' or 'pearson'.") values = getattr(residuals, kind) if not np.isfinite(values).all(): raise ValueError("Residuals are nonfinite; inspect model-impossible observed cells.") try: import matplotlib.pyplot as plt except ImportError as error: raise ImportError(_MATPLOTLIB_IMPORT_ERROR) from error if ax is None: fig, ax = plt.subplots(figsize=figsize) else: fig = cast("Figure", ax.get_figure()) ax.scatter(np.exp(residuals.log_probabilities), values, s=18, alpha=0.7) ax.axhline(0, color="0.4", linestyle="--", linewidth=1) ax.set(xlabel="Predicted response probability", ylabel=f"{kind.capitalize()} residual") return fig