Skip to content

Commit 636822f

Browse files
committed
feat: add tensor element viewer
1 parent 5c5cb6c commit 636822f

13 files changed

Lines changed: 2319 additions & 7 deletions

README.md

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,12 @@ PyTorch/NumPy `einsum` tensor networks.
1212

1313
## What This Library Does
1414

15-
Tensor-network libraries expose very different Python objects, but this package gives them one
16-
common plotting entry point:
15+
Tensor-network libraries expose very different Python objects, but this package gives them two
16+
aligned plotting entry points:
1717

1818
```python
1919
fig, ax = show_tensor_network(...)
20+
fig, ax = show_tensor_elements(...)
2021
```
2122

2223
Internally, the library:
@@ -101,6 +102,35 @@ show_tensor_network(
101102
- `show_controls`: if `False`, the figure is saved/rendered without the embedded control panel.
102103
- `show`: if `False`, nothing is displayed automatically.
103104

105+
### `show_tensor_elements`
106+
107+
Use `show_tensor_elements` to inspect tensor values:
108+
109+
```python
110+
show_tensor_elements(
111+
data,
112+
*,
113+
engine=None,
114+
config=None,
115+
ax=None,
116+
show_controls=True,
117+
show=True,
118+
)
119+
```
120+
121+
When several tensors are present, the figure keeps one tensor active at a time and uses a slider
122+
to switch between them. The interactive controls are grouped: `basic` (`elements`, `magnitude`,
123+
`distribution`, `data`), `complex` (`real`, `imag`, `phase`), and `diagnostic` (`sign`,
124+
`signed_value`).
125+
126+
- `data`: single tensor, iterable of tensors, supported backend-native tensor collections, or an
127+
`EinsumTrace` with live tensor values.
128+
- `engine`: optional backend override. If omitted, the library auto-detects it.
129+
- `config`: tensor-inspection behavior lives here.
130+
- `ax`: render a single tensor into an existing Matplotlib axis.
131+
- `show_controls`: if `True`, add compact Matplotlib `group + mode` controls and, when needed, a tensor slider.
132+
- `show`: if `False`, nothing is displayed automatically.
133+
104134
### `PlotConfig`
105135

106136
Use `PlotConfig` for visual behavior:
@@ -128,6 +158,31 @@ This is where you configure:
128158
- label-refinement policy,
129159
- static/export-oriented rendering choices.
130160

161+
### `TensorElementsConfig`
162+
163+
Use `TensorElementsConfig` for tensor inspection behavior:
164+
165+
```python
166+
from tensor_network_viz import TensorElementsConfig
167+
168+
config = TensorElementsConfig(
169+
mode="auto",
170+
max_matrix_shape=(256, 256),
171+
histogram_bins=40,
172+
)
173+
```
174+
175+
This is where you configure:
176+
177+
- the active inspection mode,
178+
- row/column axis grouping for rank > 2 tensors,
179+
- heatmap downsampling limits,
180+
- histogram sampling and bin count.
181+
182+
If you want to start in a specific grouped view, pass `mode="real"`, `mode="imag"`,
183+
`mode="phase"`, `mode="sign"`, or `mode="signed_value"` directly in
184+
`TensorElementsConfig(...)`.
185+
131186
## Most Common Workflows
132187

133188
### Interactive figure with controls
@@ -162,6 +217,19 @@ fig, ax = show_tensor_network(
162217
fig.savefig("network.png", bbox_inches="tight")
163218
```
164219

220+
### Inspect tensor values
221+
222+
```python
223+
from tensor_network_viz import TensorElementsConfig, show_tensor_elements
224+
225+
fig, ax = show_tensor_elements(
226+
trace,
227+
config=TensorElementsConfig(mode="auto"),
228+
show=False,
229+
)
230+
fig.savefig("tensor-elements.png", bbox_inches="tight")
231+
```
232+
165233
### Faster render for large graphs
166234

167235
```python
@@ -302,6 +370,12 @@ python examples/run_demo.py einsum ellipsis --view 3d --scheme
302370

303371
More details: [examples/README.md](examples/README.md)
304372

373+
There is also a minimal inspection example that only uses base dependencies:
374+
375+
```bash
376+
python examples/tensor_elements_demo.py
377+
```
378+
305379
## Troubleshooting
306380

307381
| Symptom | What to try |
@@ -310,13 +384,17 @@ More details: [examples/README.md](examples/README.md)
310384
| Hover tooltips do nothing | Use an interactive Matplotlib backend; hover is not useful for PNG-only runs. |
311385
| Big graphs are slow | Set `tensor_label_refinement="never"`, reduce `layout_iterations`, or pass `positions`. |
312386
| `Unsupported tensor network engine` | Install the matching extra or pass the correct backend object. |
387+
| `show_tensor_elements(...)` fails on TensorKrowch nodes | Materialize the node tensors first; shape-only nodes do not expose element values. |
388+
| `show_tensor_elements(...)` fails on manual `pair_tensor(...)` lists | Use an `EinsumTrace` with live tensors instead; manual trace steps only describe contractions. |
313389
| Blank / duplicate Jupyter figure | Assign `fig, ax = show_tensor_network(...)` instead of leaving the tuple as the last line. |
314390

315391
## Documentation Map
316392

317393
- [docs/guide.md](docs/guide.md): workflow-oriented guide to the public API.
318394
- [docs/backends.md](docs/backends.md): copy-paste backend-specific examples.
319395
- [examples/README.md](examples/README.md): demo launcher and batch-render usage.
396+
- [examples/tensor_elements_demo.py](examples/tensor_elements_demo.py): minimal tensor inspection
397+
example.
320398
- [CHANGELOG.md](CHANGELOG.md): release notes.
321399

322400
## Development

docs/backends.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,29 @@
22

33
This page collects copy-paste examples for each supported backend.
44

5+
## Tensor Inspection
6+
7+
### Base-dependency example with `EinsumTrace`
8+
9+
```python
10+
import numpy as np
11+
from tensor_network_viz import EinsumTrace, TensorElementsConfig, einsum, show_tensor_elements
12+
13+
trace = EinsumTrace()
14+
a = np.arange(6, dtype=float).reshape(2, 3)
15+
x = np.array([1.0, -0.5, 0.25], dtype=float)
16+
trace.bind("A", a)
17+
trace.bind("x", x)
18+
r0 = einsum("ab,b->a", a, x, trace=trace, backend="numpy")
19+
20+
fig, ax = show_tensor_elements(
21+
trace,
22+
config=TensorElementsConfig(mode="auto"),
23+
show=False,
24+
)
25+
fig.savefig("tensor-elements.png", bbox_inches="tight")
26+
```
27+
528
## TensorKrowch
629

730
```python
@@ -144,6 +167,13 @@ fig, ax = show_tensor_network(
144167
## Notes
145168

146169
- You can often omit `engine=...` because `show_tensor_network` auto-detects the backend.
170+
- `show_tensor_elements(...)` auto-detects the same backends, but it needs real tensor values.
147171
- Use `show_controls=False` when you want a clean saved figure with no embedded buttons/sliders.
148172
- Use `PlotConfig(...)` for labels, hover behavior, contraction schemes, and performance-related
149173
rendering choices.
174+
- Use `TensorElementsConfig(...)` for tensor-view mode, matrix grouping, and downsampling choices.
175+
- When multiple tensors are present, `show_tensor_elements(...)` shows one tensor at a time and
176+
adds a slider to move between them. Interactive views are grouped into `basic`, `complex`, and
177+
`diagnostic`, with diagnostic modes `sign` and `signed_value`.
178+
- TensorKrowch shape-only nodes and manual `pair_tensor(...)` lists are intentionally unsupported
179+
for `show_tensor_elements(...)` because they do not expose inspectable tensor values.

docs/guide.md

Lines changed: 94 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,18 @@ This guide is organized around user workflows instead of internal implementation
44

55
## Core Idea
66

7-
The public API is intentionally split into two responsibilities:
7+
The public API is intentionally split into four responsibilities:
88

99
- `show_tensor_network(...)` manages the figure lifecycle.
10-
- `PlotConfig(...)` manages how the network should look and behave.
10+
- `show_tensor_elements(...)` manages tensor element inspection figures.
11+
- `PlotConfig(...)` manages how tensor networks should look and behave.
12+
- `TensorElementsConfig(...)` manages how tensor inspection should look and behave.
1113

1214
If you remember only one thing, remember this:
1315

1416
```python
1517
fig, ax = show_tensor_network(network, config=PlotConfig(...))
18+
fig, ax = show_tensor_elements(data, config=TensorElementsConfig(...))
1619
```
1720

1821
## Public API
@@ -30,6 +33,18 @@ show_tensor_network(
3033
)
3134
```
3235

36+
```python
37+
show_tensor_elements(
38+
data,
39+
*,
40+
engine=None,
41+
config=None,
42+
ax=None,
43+
show_controls=True,
44+
show=True,
45+
)
46+
```
47+
3348
### Parameters
3449

3550
| Parameter | Meaning |
@@ -42,6 +57,15 @@ show_tensor_network(
4257
| `show_controls` | If `True`, add the figure control panel. If `False`, render only the network. |
4358
| `show` | If `True`, display the figure immediately. If `False`, just return `(fig, ax)`. |
4459

60+
| Parameter | Meaning |
61+
| --- | --- |
62+
| `data` | Supported tensor object, tensor collection, backend-native tensor container, or `EinsumTrace` with live tensors. |
63+
| `engine` | Optional explicit backend: `"tensorkrowch"`, `"tensornetwork"`, `"quimb"`, `"tenpy"`, or `"einsum"`. |
64+
| `config` | A `TensorElementsConfig` instance. If omitted, `TensorElementsConfig()` is used. |
65+
| `ax` | Existing Matplotlib axis for single-tensor rendering only. |
66+
| `show_controls` | If `True`, add compact `group + mode` controls and, when several tensors are present, a tensor slider. |
67+
| `show` | If `True`, display the figure immediately. If `False`, just return `(fig, ax)`. |
68+
4569
## `PlotConfig` in Practice
4670

4771
`PlotConfig` is where visual behavior lives.
@@ -98,6 +122,39 @@ config = PlotConfig(
98122
)
99123
```
100124

125+
## `TensorElementsConfig` in Practice
126+
127+
`TensorElementsConfig` is where tensor inspection behavior lives.
128+
129+
### Useful defaults
130+
131+
```python
132+
config = TensorElementsConfig(
133+
mode="auto",
134+
max_matrix_shape=(256, 256),
135+
histogram_bins=40,
136+
)
137+
```
138+
139+
When multiple tensors are present, `show_tensor_elements(...)` keeps one tensor visible at a time.
140+
The slider changes the active tensor. The controls are grouped so you first choose a family of
141+
views and then the concrete mode inside that family:
142+
143+
- `basic`: `elements`, `magnitude`, `distribution`, `data`
144+
- `complex`: `real`, `imag`, `phase`
145+
- `diagnostic`: `sign`, `signed_value`
146+
147+
### Rank > 2 tensors
148+
149+
```python
150+
config = TensorElementsConfig(
151+
row_axes=("left", "phys"),
152+
col_axes=("right",),
153+
)
154+
```
155+
156+
If you omit `row_axes` / `col_axes`, the library chooses a deterministic balanced partition.
157+
101158
## Common Workflows
102159

103160
### 1. Explore interactively
@@ -148,31 +205,50 @@ show_tensor_network(
148205

149206
If you pass `ax`, the plot is rendered into that axis and the figure is not recreated.
150207

208+
### 4. Inspect tensor values
209+
210+
```python
211+
fig, ax = show_tensor_elements(
212+
trace,
213+
config=TensorElementsConfig(mode="auto"),
214+
show=False,
215+
)
216+
fig.savefig("tensor-elements.png", bbox_inches="tight")
217+
```
218+
219+
Use this when you want one tensor at a time, quick switches between grouped views, and a `data`
220+
summary without leaving the same figure.
221+
151222
## Supported Inputs
152223

153224
### TensorKrowch
154225

155226
- `TensorNetwork`
156227
- iterable of TensorKrowch nodes
228+
- single TensorKrowch node with a materialized `tensor`
157229

158230
### TensorNetwork
159231

160232
- iterable of `tensornetwork.Node`
233+
- single `tensornetwork.Node`
161234

162235
### Quimb
163236

164237
- `quimb.tensor.TensorNetwork`
165238
- iterable of `quimb.tensor.Tensor`
239+
- single `quimb.tensor.Tensor`
166240

167241
### TeNPy
168242

169243
- common native MPS/MPO-style objects
170244
- explicit `TenPyTensorNetwork`
245+
- single TeNPy tensor exposing `to_ndarray()` and `get_leg_labels()`
171246

172247
### `einsum`
173248

174249
- `EinsumTrace`
175-
- ordered iterable of `pair_tensor(...)` / `einsum_trace_step(...)`
250+
- manual `pair_tensor(...)` / `einsum_trace_step(...)` lists are only valid for
251+
`show_tensor_network(...)`, not for `show_tensor_elements(...)`
176252

177253
More detailed copy-paste examples: [backends.md](backends.md)
178254

@@ -186,6 +262,11 @@ ax.set_title("My tensor network")
186262
fig.savefig("out.png", bbox_inches="tight")
187263
```
188264

265+
```python
266+
fig, ax = show_tensor_elements(data, show=False)
267+
fig.savefig("tensor-elements.png", bbox_inches="tight")
268+
```
269+
189270
That means you can:
190271

191272
- add titles,
@@ -220,6 +301,16 @@ config = PlotConfig(
220301

221302
Then consider passing `positions` if you already know the layout you want.
222303

304+
### Tensor inspection fails for TensorKrowch shape-only nodes
305+
306+
`show_tensor_elements(...)` needs real tensor values. Nodes with only `shape` metadata are not
307+
enough.
308+
309+
### Tensor inspection fails for manual `pair_tensor(...)` lists
310+
311+
Manual trace steps describe contractions, not tensor values. Use `EinsumTrace` and keep the traced
312+
tensors alive until you render them.
313+
223314
### Jupyter shows duplicate output
224315

225316
Prefer:

docs/tensor_elements_ideas.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Tensor Elements Ideas
2+
3+
This file collects ideas that are intentionally out of scope for the current implementation round.
4+
5+
## Potential Future Views
6+
7+
- `log_magnitude`
8+
- `sparsity`
9+
- `nan_inf`
10+
- `topk`
11+
- `slice`
12+
- `reduce`
13+
- `profiles`
14+
- `spectrum`
15+
16+
## Potential Future Controls
17+
18+
- shared color scale across tensors
19+
- robust scaling by percentiles
20+
- symmetric color scaling around zero
21+
- reference tensor comparison
22+
- outlier highlighting
23+
24+
## Notes
25+
26+
- Prefer additions that fit the current Matplotlib control style.
27+
- Avoid turning `TensorElementsConfig` into a catch-all config object.
28+
- Keep `show_tensor_elements(...)` aligned with the current package API style.

0 commit comments

Comments
 (0)