Skip to content

Weight decomposition

This page documents 3 public symbols. Each entry includes its purpose, import path, full API docstring, and the maintained example that exercises it.

Conceptual guide

plot_weight_decomposition

Map stored spatial, temporal, similarity, and combined weights.

Property Value
Type function
Import from pygwrx.plotting import plot_weight_decomposition
Signature plot_weight_decomposition(model, focus: 'int', *, components: 'Optional[Sequence[str]]' = None, theme: 'str' = 'default', figsize: 'Optional[Tuple[float, float]]' = None, title: 'Optional[str]' = None)
Maintained example examples/plotting/05_temporal_and_weights.py

plot_weight_decomposition

plot_weight_decomposition(
    model,
    focus: int,
    *,
    components: Optional[Sequence[str]] = None,
    theme: str = "default",
    figsize: Optional[Tuple[float, float]] = None,
    title: Optional[str] = None
)

Map stored spatial, temporal, similarity, and combined weights.

Source code in src/pygwrx/plotting/decomposition.py
def plot_weight_decomposition(
    model,
    focus: int,
    *,
    components: Optional[Sequence[str]] = None,
    theme: str = "default",
    figsize: Optional[Tuple[float, float]] = None,
    title: Optional[str] = None,
):
    """Map stored spatial, temporal, similarity, and combined weights."""
    rows = focus_weight_components(model, focus)
    selected = list(rows) if components is None else [str(name) for name in components]
    unknown = [name for name in selected if name not in rows]
    if unknown:
        raise ValueError(f"Unknown weight components: {unknown}.")
    cols = min(3, len(selected))
    n_rows = int(math.ceil(len(selected) / cols))
    n_columns = len(rows[selected[0]])
    source_coords = _source_coords(model, n_columns)
    with plotting_theme(theme):
        fig, axes = plt.subplots(
            n_rows, cols, figsize=figsize or (4.2 * cols, 3.8 * n_rows), squeeze=False
        )
        for axis, name in zip(axes.flat, selected):
            values = rows[name]
            cmap, norm = resolve_color_scale(values, center_zero=False, vmin=0.0)
            artist = render_spatial_values(
                axis, values, coords=source_coords, cmap=cmap, norm=norm
            )
            add_colorbar(fig, axis, artist, f"{name} weight")
            axis.set_title(name.replace("_", " ").title())
        for axis in axes.flat[len(selected) :]:
            axis.axis("off")
        fig.suptitle(title or f"{model.__class__.__name__}: weights for focus {focus}")
        fig.tight_layout()
        return fig, axes

plot_weight_profiles

Compare sorted one-dimensional profiles of stored weight components.

Property Value
Type function
Import from pygwrx.plotting import plot_weight_profiles
Signature plot_weight_profiles(model, focus: 'int', *, components: 'Optional[Sequence[str]]' = None, sort_by: 'Optional[str]' = None, theme: 'str' = 'default', ax: 'Optional[plt.Axes]' = None, figsize: 'Optional[Tuple[float, float]]' = None, title: 'Optional[str]' = None)
Maintained example examples/plotting/05_temporal_and_weights.py

plot_weight_profiles

plot_weight_profiles(
    model,
    focus: int,
    *,
    components: Optional[Sequence[str]] = None,
    sort_by: Optional[str] = None,
    theme: str = "default",
    ax: Optional[Axes] = None,
    figsize: Optional[Tuple[float, float]] = None,
    title: Optional[str] = None
)

Compare sorted one-dimensional profiles of stored weight components.

Source code in src/pygwrx/plotting/decomposition.py
def plot_weight_profiles(
    model,
    focus: int,
    *,
    components: Optional[Sequence[str]] = None,
    sort_by: Optional[str] = None,
    theme: str = "default",
    ax: Optional[plt.Axes] = None,
    figsize: Optional[Tuple[float, float]] = None,
    title: Optional[str] = None,
):
    """Compare sorted one-dimensional profiles of stored weight components."""
    rows = focus_weight_components(model, focus)
    selected = list(rows) if components is None else list(components)
    unknown = [name for name in selected if name not in rows]
    if unknown:
        raise ValueError(f"Unknown weight components: {unknown}.")
    key = sort_by or ("combined" if "combined" in rows else selected[0])
    if key not in rows:
        raise ValueError(f"sort_by={key!r} is not a stored component.")
    order = np.argsort(rows[key])[::-1]
    with plotting_theme(theme):
        if ax is None:
            fig, axis = plt.subplots(figsize=figsize or (8.0, 4.5))
        else:
            fig, axis = ax.figure, ax
        for name in selected:
            axis.plot(
                np.arange(order.size), rows[name][order], label=name.replace("_", " ")
            )
        axis.set_xlabel(f"Source observations sorted by {key} weight")
        axis.set_ylabel("Weight")
        axis.set_title(title or f"{model.__class__.__name__}: weight profiles")
        axis.legend(loc="best")
        axis.grid(True, alpha=0.22)
        fig.tight_layout()
        return fig, axis

plot_selection_history

Plot AICc/CV values from an SGWR/STWR/SGTWR parameter search.

Property Value
Type function
Import from pygwrx.plotting import plot_selection_history
Signature plot_selection_history(model, *, criterion: 'str' = 'aicc', theme: 'str' = 'default', ax: 'Optional[plt.Axes]' = None, figsize: 'Optional[Tuple[float, float]]' = None, title: 'Optional[str]' = None)
Maintained example examples/plotting/05_temporal_and_weights.py

plot_selection_history

plot_selection_history(
    model,
    *,
    criterion: str = "aicc",
    theme: str = "default",
    ax: Optional[Axes] = None,
    figsize: Optional[Tuple[float, float]] = None,
    title: Optional[str] = None
)

Plot AICc/CV values from an SGWR/STWR/SGTWR parameter search.

Source code in src/pygwrx/plotting/decomposition.py
def plot_selection_history(
    model,
    *,
    criterion: str = "aicc",
    theme: str = "default",
    ax: Optional[plt.Axes] = None,
    figsize: Optional[Tuple[float, float]] = None,
    title: Optional[str] = None,
):
    """Plot AICc/CV values from an SGWR/STWR/SGTWR parameter search."""
    history = getattr(model, "selection_history_", None)
    if not history:
        history = getattr(model, "alpha_search_history_", None)
    if not history:
        history = getattr(model, "lambda_selection_history_", None)
    if not history:
        raise ValueError(
            "The fitted model does not expose a non-empty selection history."
        )
    frame = pd.DataFrame(history)
    token = str(criterion).strip().lower()
    candidate = next((name for name in frame.columns if name.lower() == token), None)
    if candidate is None:
        candidate = next(
            (name for name in frame.columns if name.lower() in {"score", "aicc", "cv"}),
            None,
        )
    if candidate is None:
        raise ValueError("Selection history does not contain a score column.")
    score = pd.to_numeric(frame[candidate], errors="coerce")
    with plotting_theme(theme):
        if ax is None:
            fig, axis = plt.subplots(figsize=figsize or (8.0, 4.5))
        else:
            fig, axis = ax.figure, ax
        axis.plot(np.arange(len(frame)), score, marker="o")
        if np.isfinite(score).any():
            best = int(np.nanargmin(score.to_numpy(float)))
            axis.scatter(
                [best], [score.iloc[best]], marker="*", s=140, label="Selected"
            )
            axis.legend(loc="best")
        axis.set_xlabel("Candidate index")
        axis.set_ylabel(candidate)
        axis.set_title(title or f"{model.__class__.__name__}: parameter search")
        axis.grid(True, alpha=0.22)
        fig.tight_layout()
        return fig, axis

Runnable examples used on this page

examples/plotting/05_temporal_and_weights.py
# SPDX-FileCopyrightText: 2026 Jinghao Hu
# SPDX-License-Identifier: MIT

"""All temporal, multiscale, weight decomposition, and selection-history plots."""

# Allow this script to run directly from any working directory.
import sys
from pathlib import Path

_PROJECT_ROOT = Path(__file__).resolve().parents[2]
_EXAMPLES_ROOT = _PROJECT_ROOT / "examples"
_SRC_ROOT = _PROJECT_ROOT / "src"
for _path in (_SRC_ROOT, _EXAMPLES_ROOT):
    if str(_path) not in sys.path:
        sys.path.insert(0, str(_path))

import matplotlib

matplotlib.use("Agg", force=True)
from _common import save_plot
from _models import temporal_models

from pygwrx.plotting import (
    plot_mgtwr_scales,
    plot_selection_history,
    plot_temporal_bandwidths,
    plot_temporal_coefficient_slices,
    plot_temporal_residuals,
    plot_temporal_trajectory,
    plot_weight_decomposition,
    plot_weight_profiles,
)

X, y, coords, times, gtwr, mgtwr, sgtwr, sgwr, stwr, search_model = temporal_models()
plots = {
    "temporal_slices.png": plot_temporal_coefficient_slices(gtwr, "x1"),
    "temporal_trajectory.png": plot_temporal_trajectory(gtwr, "x1"),
    "temporal_residuals.png": plot_temporal_residuals(gtwr),
    "temporal_bandwidths.png": plot_temporal_bandwidths(sgtwr),
    "mgtwr_scales.png": plot_mgtwr_scales(mgtwr),
    "sgwr_decomposition.png": plot_weight_decomposition(sgwr, 0),
    "sgwr_profiles.png": plot_weight_profiles(sgwr, 0, sort_by="combined"),
    "stwr_decomposition.png": plot_weight_decomposition(stwr, 0),
    "sgtwr_decomposition.png": plot_weight_decomposition(sgtwr, 0),
    "selection_history.png": plot_selection_history(search_model),
}
for name, result in plots.items():
    print(save_plot(result, name))