Source code for latents.plotting.hinton
"""Hinton diagram visualization."""
from __future__ import annotations
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.axes import Axes
[docs]
def hinton_diagram(
matrix: np.ndarray,
max_weight: float | None = None,
ax: Axes | None = None,
) -> None:
"""Draw a Hinton diagram of a matrix.
The color of each square reflects the sign of the corresponding matrix
element, and the size of each square reflects the magnitude of the
corresponding element.
Code adapted from `here
<https://matplotlib.org/stable/gallery/specialty_plots/hinton_demo.html>`_.
Parameters
----------
matrix : ndarray of shape (M, N)
Matrix to visualize.
max_weight : float or None, default None
Maximum absolute value of matrix elements.
ax : Axes or None, default None
Axes on which to draw the diagram. If None, gets an existing axis
or creates a new one.
Examples
--------
>>> import numpy as np
>>> from latents.plotting import hinton_diagram
>>> C = np.random.normal(size=(10, 5))
>>> hinton_diagram(C)
"""
# If no axis is provided, then get an existing one or create a new one
ax = ax if ax is not None else plt.gca()
# Set the default maximum weight if not provided
if not max_weight:
max_weight = 2 ** np.ceil(np.log2(np.abs(matrix).max()))
# Set up the figure background
ax.patch.set_facecolor("white")
ax.set_aspect("equal", "box")
ax.xaxis.set_major_locator(plt.NullLocator())
ax.yaxis.set_major_locator(plt.NullLocator())
# Draw each element of the matrix
if matrix.ndim == 1:
# For 1D arrays, add a second dimension to create a column vector
matrix = matrix[:, np.newaxis]
for (y, x), w in np.ndenumerate(matrix):
# Color code for positive and negative values
rect_color = "red" if w > 0 else "blue"
# Size of each rectangle. Scale down slightly to ensure that there's
# always some white space between elements.
rect_size = 0.9 * np.sqrt(np.abs(w) / max_weight)
# Plot each rectangle
rect = plt.Rectangle(
(x - rect_size / 2, y - rect_size / 2),
rect_size,
rect_size,
facecolor=rect_color,
edgecolor=None,
)
ax.add_patch(rect)
# Make sure we can see all elements of the matrix
ax.autoscale_view()
# The matrix will be plotted upside down by default, so flip it
ax.invert_yaxis()