Skip to main content

Minimal Matplotlib visualizations for TensorKrowch, TensorNetwork, Quimb, TeNPy, and traced PyTorch/NumPy einsum tensor networks.

Project description

Tensor-Network-Visualization

CI PyPI version Python versions License: MIT

Minimal Matplotlib visualizations for TensorKrowch, TensorNetwork, Quimb, TeNPy, and traced PyTorch/NumPy einsum tensor networks.

Repository: https://github.com/DOKOS-TAYOS/Tensor-Network-Visualization

What This Library Does

Tensor-network libraries expose very different Python objects, but this package gives them aligned inspection and export entry points:

fig, ax = show_tensor_network(...)
fig, ax = show_tensor_elements(...)
fig, ax = show_tensor_comparison(...)
graph = normalize_tensor_network(...)
snapshot = export_tensor_network_snapshot(...)

Internally, the library:

  1. normalizes backend objects into one graph model,
  2. computes a layout,
  3. draws the graph in 2D or 3D with Matplotlib,
  4. optionally adds figure controls for view/label/scheme toggles.

The goal is to keep the public API small while still being useful for notebooks, papers, debugging, saved figures, and external tooling that wants the backend-normalized graph model.

Install

PyPI package name: tensor-network-visualization
Import package: tensor_network_viz

Requires Python 3.11 or newer.

Base install

python -m pip install tensor-network-visualization

Base dependencies are only numpy, matplotlib, and networkx.

Documentation Map

  • Start here for installation and the public API overview.
  • Use docs/guide.md for workflow-oriented explanations.
  • Use docs/backends.md for backend-specific copy-paste examples.
  • Use examples/README.md when you want to run the local demos from this repository.

Errors and Logging

Public entry points now raise package-specific exceptions while remaining compatible with the built-in exception families they refine:

  • VisualizationInputError: unsupported or ambiguous network input.
  • AxisConfigurationError: incompatible ax / view combinations.
  • UnsupportedEngineError: unknown engine or backend name.
  • TensorDataError: unsupported or missing tensor data for show_tensor_elements(...).
  • MissingOptionalDependencyError: missing optional backend dependency.

All of them inherit from TensorNetworkVizError.

The package logger name is tensor_network_viz. It installs a logging.NullHandler() by default, so importing the library does not change your application's logging configuration.

import logging

logging.basicConfig(level=logging.DEBUG)
logging.getLogger("tensor_network_viz").setLevel(logging.DEBUG)

Optional extras

Need Install
TensorKrowch support python -m pip install "tensor-network-visualization[tensorkrowch]"
TensorNetwork support python -m pip install "tensor-network-visualization[tensornetwork]"
Quimb support python -m pip install "tensor-network-visualization[quimb]"
TeNPy support python -m pip install "tensor-network-visualization[tenpy]"
Traced einsum(...) support python -m pip install "tensor-network-visualization[einsum]"
Interactive Jupyter widgets python -m pip install "tensor-network-visualization[jupyter]"

Windows and Linux quick start

Windows (PowerShell):

python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install -U pip
python -m pip install "tensor-network-visualization[quimb]"

Linux / macOS:

python3 -m venv .venv
source .venv/bin/activate
python -m pip install -U pip
python -m pip install "tensor-network-visualization[quimb]"

Once the virtual environment is active, the python ... commands shown in the rest of this README work the same way on Windows and Linux.

The API in One Minute

show_controls and show are independent:

  • show_controls=False disables the embedded Matplotlib widgets and slider.
  • show=False skips automatic display and only returns (fig, ax).

show_tensor_network

Use show_tensor_network for figure lifecycle:

show_tensor_network(
    network,
    *,
    engine=None,
    view=None,
    config=None,
    ax=None,
    show_controls=True,
    show=True,
)
  • engine: optional backend override. If omitted, the library auto-detects it.
  • view: "2d" or "3d". If omitted, it starts in "2d".
  • config: all visual behavior lives here.
  • ax: render into an existing Matplotlib axis.
  • show_controls: if False, render a static figure without the embedded control panel.
  • show: if False, nothing is displayed automatically.

show_tensor_elements

Use show_tensor_elements to inspect tensor values:

show_tensor_elements(
    data,
    *,
    engine=None,
    config=None,
    ax=None,
    show_controls=True,
    show=True,
)

When several tensors are present, the figure keeps one tensor active at a time and uses a slider to switch between them. The interactive controls are grouped: basic (elements, magnitude, log_magnitude, distribution, data), complex (real, imag, phase), and diagnostic (sign, signed_value, sparsity, nan_inf, singular_values, eigen_real, eigen_imag), plus analysis (slice, reduce, profiles).

  • data: direct numeric tensor input (for example a NumPy array), direct iterables of tensors preserving order and duplicates, supported backend-native tensor collections, or an EinsumTrace with live tensor values.
  • engine: optional backend override. If omitted, the library auto-detects it.
  • config: tensor-inspection behavior lives here.
  • data mode includes global stats, per-axis summaries, and top-k coordinates by magnitude.
  • singular_values renders the singular-value spectrum for the same matrixized tensor used by the heatmap views and is hidden automatically when the active tensor contains NaN or Inf.
  • eigen_real and eigen_imag render the real and imaginary parts of the eigenvalues for the same matrixized tensor, ordered by eigenvalue magnitude. They appear only when the active analysis matrix is finite and square.
  • ax: render a single tensor into an existing Matplotlib axis.
  • show_controls: if True, add compact Matplotlib group + mode controls and, when needed, a tensor slider.
  • show: if False, nothing is displayed automatically.

show_tensor_comparison

Use show_tensor_comparison to compare one tensor against one reference tensor:

show_tensor_comparison(
    data,
    reference,
    *,
    engine=None,
    config=None,
    comparison_config=None,
    ax=None,
    show_controls=True,
    show=True,
)
  • config: still uses TensorElementsConfig(...) for matrixization and rendering style.
  • comparison_config: uses TensorComparisonConfig(...) for comparison-specific behavior.
  • comparison modes are reference, abs_diff, relative_diff, ratio, sign_change, phase_change, and topk_changes.

Normalized snapshots

Use the snapshot helpers when you want the backend-normalized graph and layout without touching any backend adapter internals:

graph = normalize_tensor_network(network, engine=None)
snapshot = export_tensor_network_snapshot(
    network,
    engine=None,
    view="2d",
    config=PlotConfig(),
    seed=0,
)

Both snapshot objects are immutable and expose .to_dict() for serialization.

PlotConfig

Use PlotConfig for visual behavior:

from tensor_network_viz import (
    PlotConfig,
    TensorNetworkDiagnosticsConfig,
    TensorNetworkFocus,
)

config = PlotConfig(
    show_nodes=True,
    show_tensor_labels=True,
    show_index_labels=False,
    hover_labels=True,
    show_contraction_scheme=False,
    contraction_scheme_cost_hover=False,
    contraction_tensor_inspector=False,
    diagnostics=TensorNetworkDiagnosticsConfig(
        show_overlay=False,
        include_hover=True,
    ),
    focus=TensorNetworkFocus(
        kind="neighborhood",
        center="A",
        radius=1,
    ),
    tensor_label_refinement="auto",
    tensor_label_fontsize=None,
    edge_label_fontsize=None,
)

This is where you configure:

  • labels,
  • hover tooltips,
  • diagnostics overlays and enriched hover payloads (shape, dtype, bond dimension, memory),
  • reproducible subnetwork focus (neighborhood radius 1/2 or shortest path by tensor name),
  • contraction-scheme overlays,
  • optional tensor/edge label font-size overrides,
  • styling,
  • layout iterations,
  • custom positions,
  • label-refinement policy,
  • static/export-oriented rendering choices.

TensorElementsConfig

Use TensorElementsConfig for tensor inspection behavior:

from tensor_network_viz import TensorAnalysisConfig, TensorElementsConfig

config = TensorElementsConfig(
    mode="auto",
    row_axes=None,
    col_axes=None,
    analysis=TensorAnalysisConfig(
        slice_axis="phys",
        slice_index=0,
        reduce_axes=("bond",),
        reduce_method="mean",
        profile_axis="phys",
        profile_method="norm",
    ),
    figsize=(7.2, 6.4),
    max_matrix_shape=(256, 256),
    shared_color_scale=False,
    robust_percentiles=(1.0, 99.0),
    highlight_outliers=False,
    outlier_zscore=3.5,
    zero_threshold=1e-12,
    log_magnitude_floor=1e-12,
    histogram_bins=40,
    histogram_max_samples=100_000,
    topk_count=8,
)

This is where you configure:

  • the active inspection mode,
  • row/column axis grouping for rank > 2 tensors,
  • analysis selectors for slice, reduce, and profiles,
  • heatmap downsampling limits,
  • histogram sampling and bin count,
  • data-summary depth (topk_count),
  • heatmap/spectral reduction via max_matrix_shape,
  • optional robust/shared scaling and outlier overlays,
  • singular-value display floor and zero handling.

If you want to start in a specific grouped view, pass mode="real", mode="imag", mode="phase", mode="log_magnitude", mode="sparsity", mode="nan_inf", mode="sign", mode="signed_value", mode="singular_values", mode="eigen_real", mode="eigen_imag", mode="slice", mode="reduce", or mode="profiles" directly in TensorElementsConfig(...).

For the analytical views, keep this mental model:

  • slice fixes one axis at one index and removes that axis from the result.
  • reduce collapses the checked axes with mean or norm, so you see the axes that were not checked.
  • profiles keeps one axis as a 1D curve and reduces the other surviving axes.

Most Common Workflows

Interactive figure with controls

from tensor_network_viz import (
    PlotConfig,
    TensorNetworkDiagnosticsConfig,
    TensorNetworkFocus,
    show_tensor_network,
)

fig, ax = show_tensor_network(
    network,
    config=PlotConfig(
        show_tensor_labels=False,
        show_index_labels=False,
        hover_labels=True,
        diagnostics=TensorNetworkDiagnosticsConfig(show_overlay=True),
        focus=TensorNetworkFocus(kind="neighborhood", center="A", radius=1),
    ),
)

When the network exposes inspectable tensor values, clicking a visible tensor node opens the shared auxiliary inspector directly. In playback-enabled traces, the same inspector can still follow the current contraction result or stay pinned to a manually selected node until you click empty space to clear the manual selection.

Clean export with no embedded controls

from tensor_network_viz import PlotConfig, show_tensor_network

fig, ax = show_tensor_network(
    network,
    config=PlotConfig(
        show_tensor_labels=True,
        show_index_labels=False,
    ),
    show_controls=False,
    show=False,
)
fig.savefig("network.png", bbox_inches="tight")

Inspect tensor values

from tensor_network_viz import TensorAnalysisConfig, TensorElementsConfig, show_tensor_elements

fig, ax = show_tensor_elements(
    trace,
    config=TensorElementsConfig(
        mode="profiles",
        analysis=TensorAnalysisConfig(profile_axis="phys", profile_method="norm"),
    ),
    show=False,
)
fig.savefig("tensor-elements.png", bbox_inches="tight")

Export a focused snapshot with diagnostics

from tensor_network_viz import (
    PlotConfig,
    TensorNetworkDiagnosticsConfig,
    TensorNetworkFocus,
    export_tensor_network_snapshot,
)

snapshot = export_tensor_network_snapshot(
    network,
    config=PlotConfig(
        diagnostics=TensorNetworkDiagnosticsConfig(include_hover=True),
        focus=TensorNetworkFocus(kind="path", endpoints=("A", "C")),
    ),
)
payload = snapshot.to_dict()

Compare tensors

from tensor_network_viz import (
    TensorComparisonConfig,
    TensorElementsConfig,
    show_tensor_comparison,
)

fig, ax = show_tensor_comparison(
    current_tensor,
    reference_tensor,
    config=TensorElementsConfig(mode="elements"),
    comparison_config=TensorComparisonConfig(mode="abs_diff"),
    show=False,
)
fig.savefig("tensor-comparison.png", bbox_inches="tight")

Export a normalized snapshot

from tensor_network_viz import PlotConfig, export_tensor_network_snapshot

snapshot = export_tensor_network_snapshot(
    network,
    config=PlotConfig(),
    view="2d",
)
payload = snapshot.to_dict()

Faster render for large graphs

config = PlotConfig(
    tensor_label_refinement="never",
    layout_iterations=120,
)

Copy-Paste Examples by Backend

The library supports auto-detection, but using engine=... in examples is often clearer.

TensorKrowch

import tensorkrowch as tk
from tensor_network_viz import PlotConfig, show_tensor_network

network = tk.TensorNetwork(name="demo")
left = tk.Node(shape=(2, 2), axes_names=("a", "b"), name="L", network=network)
right = tk.Node(shape=(2, 2), axes_names=("b", "c"), name="R", network=network)
left["b"] ^ right["b"]

fig, ax = show_tensor_network(
    network,
    engine="tensorkrowch",
    config=PlotConfig(show_tensor_labels=True),
)

TensorNetwork

import numpy as np
import tensornetwork as tn
from tensor_network_viz import PlotConfig, show_tensor_network

left = tn.Node(np.ones((2, 2)), name="L", axis_names=("a", "b"))
right = tn.Node(np.ones((2, 2)), name="R", axis_names=("b", "c"))
left["b"] ^ right["b"]

fig, ax = show_tensor_network(
    [left, right],
    engine="tensornetwork",
    config=PlotConfig(show_tensor_labels=True),
)

Quimb

import numpy as np
import quimb.tensor as qtn
from tensor_network_viz import PlotConfig, show_tensor_network

tensors = [
    qtn.Tensor(np.ones((2, 3)), inds=("i0", "b0"), tags={"T0"}),
    qtn.Tensor(np.ones((3, 2)), inds=("b0", "i1"), tags={"T1"}),
]
network = qtn.TensorNetwork(tensors)

fig, ax = show_tensor_network(
    network,
    engine="quimb",
    config=PlotConfig(show_tensor_labels=True),
)

TeNPy

from tenpy.networks.mps import MPS
from tenpy.networks.site import SpinHalfSite
from tensor_network_viz import PlotConfig, show_tensor_network

sites = [SpinHalfSite() for _ in range(4)]
mps = MPS.from_product_state(sites, ["up", "up", "up", "up"], bc="finite")

fig, ax = show_tensor_network(
    mps,
    engine="tenpy",
    config=PlotConfig(show_tensor_labels=True),
    show_controls=False,
    show=False,
)

einsum

from tensor_network_viz import PlotConfig, pair_tensor, show_tensor_network

trace = [
    pair_tensor("A0", "x0", "r0", "pa,p->a"),
    pair_tensor("r0", "A1", "r1", "a,apb->pb"),
]

fig, ax = show_tensor_network(
    trace,
    engine="einsum",
    config=PlotConfig(show_contraction_scheme=True),
)

For fuller backend examples, see docs/backends.md.

PlotConfig Fields You Will Actually Use Often

Field Why it matters
show_tensor_labels Draw tensor names on nodes.
show_index_labels Draw index labels on bonds and dangling legs.
hover_labels Enable hover tooltips in interactive sessions.
show_contraction_scheme Enable the dynamic contraction slider with real node shape/color changes.
contraction_scheme_cost_hover Show contraction details in the slider panel.
contraction_tensor_inspector Enable the auxiliary tensor inspector with direct node selection and comparison controls.
tensor_label_refinement "auto", "always", or "never" for the expensive label-fit pass.
layout_iterations Force-layout effort.
positions Supply custom node coordinates.
figsize Matplotlib figure size when the figure is created internally.

Example Launcher

The repository ships a typed demo launcher:

python examples/run_demo.py <engine> <example> [options]

Useful examples:

python examples/run_demo.py quimb hyper --view 2d
python examples/run_demo.py tenpy chain --view 2d --save tenpy_chain.png --no-show
python examples/run_demo.py einsum ellipsis --view 3d --scheme

More details, including an exhaustive copy-paste command list for every CLI example: examples/README.md

There is also a minimal inspection example that only uses base dependencies:

python examples/tensor_elements_demo.py

Troubleshooting

Symptom What to try
Saved figure includes buttons/sliders Use show_controls=False.
Hover tooltips do nothing Use an interactive Matplotlib backend; hover is not useful for PNG-only runs.
Big graphs are slow Set tensor_label_refinement="never", reduce layout_iterations, or pass positions.
Unsupported tensor network engine Install the matching extra or pass the correct backend object.
AxisConfigurationError when passing ax Use a 2D axis for view="2d", a 3D axis for view="3d", and only pass ax to show_tensor_elements(...) for a single tensor.
show_tensor_elements(...) fails on TensorKrowch nodes Materialize the node tensors first; shape-only nodes do not expose element values.
show_tensor_elements(...) fails on manual pair_tensor(...) lists Use an EinsumTrace with live tensors instead; manual trace steps only describe contractions.
Blank / duplicate Jupyter figure Assign fig, ax = show_tensor_network(...) instead of leaving the tuple as the last line.

Documentation Map

Development

Create and use a local virtual environment:

python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install -r requirements.dev.txt

Run the project checks:

.\.venv\Scripts\python scripts\verify.py

Useful slices:

.\.venv\Scripts\python scripts\verify.py quality
.\.venv\Scripts\python scripts\verify.py tests
.\.venv\Scripts\python scripts\verify.py smoke
.\.venv\Scripts\python scripts\verify.py package

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tensor_network_visualization-1.5.4.tar.gz (275.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tensor_network_visualization-1.5.4-py3-none-any.whl (232.8 kB view details)

Uploaded Python 3

File details

Details for the file tensor_network_visualization-1.5.4.tar.gz.

File metadata

File hashes

Hashes for tensor_network_visualization-1.5.4.tar.gz
Algorithm Hash digest
SHA256 e754f728b504e58a1e0b3933e59938b09a2881dc5563838b5067a2579ef4d170
MD5 e3189c1b4e3cbd2c76115df0f2c62bf1
BLAKE2b-256 9d3af807e381bf8b59f5c0f5f5687569d05f3de8ce51f9f0eb0bf4d64d925516

See more details on using hashes here.

File details

Details for the file tensor_network_visualization-1.5.4-py3-none-any.whl.

File metadata

File hashes

Hashes for tensor_network_visualization-1.5.4-py3-none-any.whl
Algorithm Hash digest
SHA256 ee90939ec1702faeb691bf026374e055f922a2c592d661f97f7b05162ccd5a9f
MD5 603a1ed3ae6710bf1d528fb306b28a69
BLAKE2b-256 9b64b6a3e62377722d033635e45a30004457a2b2f3ca79a7d9122b684506dcb1

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page