tensor-network-visualization 1.4.2__tar.gz → 1.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. {tensor_network_visualization-1.4.2/src/tensor_network_visualization.egg-info → tensor_network_visualization-1.5.0}/PKG-INFO +87 -47
  2. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/README.md +80 -42
  3. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/pyproject.toml +20 -7
  4. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0/src/tensor_network_visualization.egg-info}/PKG-INFO +87 -47
  5. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_visualization.egg-info/SOURCES.txt +24 -1
  6. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_visualization.egg-info/requires.txt +1 -1
  7. tensor_network_visualization-1.5.0/src/tensor_network_viz/__init__.py +59 -0
  8. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/axis_directions.py +10 -0
  9. tensor_network_visualization-1.5.0/src/tensor_network_viz/_core/draw/contraction_edges.py +149 -0
  10. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/draw/contraction_scheme.py +87 -58
  11. tensor_network_visualization-1.5.0/src/tensor_network_viz/_core/draw/dangling_self_edges.py +445 -0
  12. tensor_network_visualization-1.5.0/src/tensor_network_viz/_core/draw/edge_labels.py +139 -0
  13. tensor_network_visualization-1.5.0/src/tensor_network_viz/_core/draw/edge_orchestration.py +214 -0
  14. tensor_network_visualization-1.5.0/src/tensor_network_viz/_core/draw/edges.py +16 -0
  15. tensor_network_visualization-1.5.0/src/tensor_network_viz/_core/draw/graph_pipeline.py +275 -0
  16. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/draw/hover.py +412 -250
  17. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/draw/plotter.py +21 -2
  18. tensor_network_visualization-1.5.0/src/tensor_network_viz/_core/draw/render_prep.py +410 -0
  19. tensor_network_visualization-1.5.0/src/tensor_network_viz/_core/draw/scene_state.py +51 -0
  20. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/draw/tensors.py +199 -198
  21. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/draw/viewport_geometry.py +700 -693
  22. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/graph.py +13 -0
  23. tensor_network_visualization-1.5.0/src/tensor_network_viz/_core/layout/body.py +150 -0
  24. tensor_network_visualization-1.5.0/src/tensor_network_viz/_core/layout/direction_common.py +477 -0
  25. tensor_network_visualization-1.5.0/src/tensor_network_viz/_core/layout/free_directions_2d.py +493 -0
  26. tensor_network_visualization-1.5.0/src/tensor_network_viz/_core/layout/free_directions_3d.py +250 -0
  27. tensor_network_visualization-1.5.0/src/tensor_network_viz/_core/layout/geometry.py +382 -0
  28. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/layout/parameters.py +12 -0
  29. tensor_network_visualization-1.5.0/src/tensor_network_viz/_core/layout/positions.py +802 -0
  30. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/layout_structure.py +510 -506
  31. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/renderer.py +497 -444
  32. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_registry.py +6 -0
  33. tensor_network_visualization-1.5.0/src/tensor_network_viz/_typing.py +25 -0
  34. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/config.py +29 -10
  35. tensor_network_visualization-1.5.0/src/tensor_network_viz/contraction_viewer.py +1007 -0
  36. tensor_network_visualization-1.5.0/src/tensor_network_viz/einsum_module/__init__.py +46 -0
  37. tensor_network_visualization-1.5.0/src/tensor_network_viz/einsum_module/contraction_cost.py +79 -0
  38. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/einsum_module/graph.py +11 -0
  39. tensor_network_visualization-1.5.0/src/tensor_network_viz/interactive_viewer.py +595 -0
  40. tensor_network_visualization-1.5.0/src/tensor_network_viz/quimb/__init__.py +32 -0
  41. tensor_network_visualization-1.5.0/src/tensor_network_viz/tenpy/__init__.py +37 -0
  42. tensor_network_visualization-1.5.0/src/tensor_network_viz/tensorkrowch/__init__.py +32 -0
  43. tensor_network_visualization-1.5.0/src/tensor_network_viz/tensornetwork/__init__.py +32 -0
  44. tensor_network_visualization-1.5.0/src/tensor_network_viz/viewer.py +224 -0
  45. tensor_network_visualization-1.5.0/tests/test_ci_workflow.py +26 -0
  46. tensor_network_visualization-1.5.0/tests/test_contraction_cost.py +111 -0
  47. tensor_network_visualization-1.5.0/tests/test_contraction_viewer.py +567 -0
  48. tensor_network_visualization-1.5.0/tests/test_demo_cli_scheme.py +270 -0
  49. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/tests/test_einsum_backend.py +136 -3
  50. tensor_network_visualization-1.5.0/tests/test_engine_detection.py +123 -0
  51. tensor_network_visualization-1.5.0/tests/test_engineering_baseline.py +138 -0
  52. tensor_network_visualization-1.5.0/tests/test_examples.py +331 -0
  53. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/tests/test_layout_core.py +455 -0
  54. tensor_network_visualization-1.5.0/tests/test_lazy_imports.py +40 -0
  55. tensor_network_visualization-1.5.0/tests/test_packaging_metadata.py +29 -0
  56. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/tests/test_plotting.py +504 -3
  57. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/tests/test_public_api.py +205 -183
  58. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/tests/test_quimb_backend.py +16 -6
  59. tensor_network_visualization-1.5.0/tests/test_render_performance_controls.py +162 -0
  60. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/tests/test_tenpy_backend.py +10 -3
  61. tensor_network_visualization-1.5.0/tests/test_verify_script.py +24 -0
  62. tensor_network_visualization-1.4.2/src/tensor_network_viz/__init__.py +0 -30
  63. tensor_network_visualization-1.4.2/src/tensor_network_viz/_core/draw/edges.py +0 -728
  64. tensor_network_visualization-1.4.2/src/tensor_network_viz/_core/draw/graph_pipeline.py +0 -267
  65. tensor_network_visualization-1.4.2/src/tensor_network_viz/_core/layout/body.py +0 -1251
  66. tensor_network_visualization-1.4.2/src/tensor_network_viz/einsum_module/__init__.py +0 -14
  67. tensor_network_visualization-1.4.2/src/tensor_network_viz/quimb/__init__.py +0 -9
  68. tensor_network_visualization-1.4.2/src/tensor_network_viz/tenpy/__init__.py +0 -12
  69. tensor_network_visualization-1.4.2/src/tensor_network_viz/tensorkrowch/__init__.py +0 -9
  70. tensor_network_visualization-1.4.2/src/tensor_network_viz/tensornetwork/__init__.py +0 -9
  71. tensor_network_visualization-1.4.2/src/tensor_network_viz/viewer.py +0 -93
  72. tensor_network_visualization-1.4.2/tests/test_demo_cli_scheme.py +0 -45
  73. tensor_network_visualization-1.4.2/tests/test_examples.py +0 -455
  74. tensor_network_visualization-1.4.2/tests/test_packaging_metadata.py +0 -17
  75. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/LICENSE +0 -0
  76. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/setup.cfg +0 -0
  77. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_visualization.egg-info/dependency_links.txt +0 -0
  78. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_visualization.egg-info/top_level.txt +0 -0
  79. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/__init__.py +0 -0
  80. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/_draw_common.py +0 -0
  81. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/_label_format.py +0 -0
  82. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/_nodes_edges_common.py +0 -0
  83. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/contractions.py +0 -0
  84. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/curves.py +0 -0
  85. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/draw/__init__.py +0 -0
  86. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/draw/constants.py +0 -0
  87. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/draw/disk_metrics.py +0 -0
  88. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/draw/fonts_and_scale.py +0 -0
  89. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/draw/labels_misc.py +0 -0
  90. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/draw/pick_distance.py +0 -0
  91. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/draw/vectors.py +0 -0
  92. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/graph_cache.py +0 -0
  93. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/graph_utils.py +0 -0
  94. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/layout/__init__.py +0 -0
  95. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/layout/force_directed.py +0 -0
  96. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/layout/types.py +0 -0
  97. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_engine_specs.py +0 -0
  98. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/einsum_module/_backend.py +0 -0
  99. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/einsum_module/_equation.py +0 -0
  100. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/einsum_module/_trace_state.py +0 -0
  101. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/einsum_module/_trace_types.py +0 -0
  102. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/einsum_module/renderer.py +0 -0
  103. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/einsum_module/trace.py +0 -0
  104. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/py.typed +0 -0
  105. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/quimb/graph.py +0 -0
  106. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/quimb/renderer.py +0 -0
  107. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/tenpy/explicit.py +0 -0
  108. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/tenpy/graph.py +0 -0
  109. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/tenpy/renderer.py +0 -0
  110. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/tensorkrowch/graph.py +0 -0
  111. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/tensorkrowch/renderer.py +0 -0
  112. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/tensornetwork/graph.py +0 -0
  113. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/tensornetwork/renderer.py +0 -0
  114. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/tests/test_contraction_groups_once.py +0 -0
  115. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/tests/test_contraction_scheme.py +0 -0
  116. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/tests/test_draw_performance.py +0 -0
  117. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/tests/test_edge_index_label_2d.py +0 -0
  118. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/tests/test_edge_index_label_3d.py +0 -0
  119. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/tests/test_einsum_autotrace.py +0 -0
  120. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/tests/test_examples_structure.py +0 -0
  121. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/tests/test_graph_cache.py +0 -0
  122. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/tests/test_integration_einsum.py +0 -0
  123. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/tests/test_integration_tensorkrowch.py +0 -0
  124. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/tests/test_integration_tensornetwork.py +0 -0
  125. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/tests/test_label_draw_metrics_perf.py +0 -0
  126. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/tests/test_label_format.py +0 -0
  127. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/tests/test_node_degrees_perf.py +0 -0
  128. {tensor_network_visualization-1.4.2 → tensor_network_visualization-1.5.0}/tests/test_show_tensor_network_throughput.py +0 -0
@@ -1,31 +1,33 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tensor-network-visualization
3
- Version: 1.4.2
3
+ Version: 1.5.0
4
4
  Summary: Minimal Matplotlib visualizations for TensorKrowch, TensorNetwork, Quimb, TeNPy, and traced PyTorch/NumPy einsum tensor networks.
5
5
  Author: Alejandro Mata Ali
6
- License: MIT
6
+ License-Expression: MIT
7
7
  Project-URL: Homepage, https://github.com/DOKOS-TAYOS/Tensor-Network-Visualization
8
8
  Project-URL: Documentation, https://github.com/DOKOS-TAYOS/Tensor-Network-Visualization/blob/main/docs/guide.md
9
9
  Project-URL: Changelog, https://github.com/DOKOS-TAYOS/Tensor-Network-Visualization/blob/main/CHANGELOG.md
10
10
  Project-URL: Repository, https://github.com/DOKOS-TAYOS/Tensor-Network-Visualization
11
11
  Project-URL: Issues, https://github.com/DOKOS-TAYOS/Tensor-Network-Visualization/issues
12
12
  Keywords: tensor-network,visualization,pytorch,numpy,tensorkrowch,tensornetwork,quimb,tenpy,einsum,quantum-inspired,matplotlib
13
- Classifier: License :: OSI Approved :: MIT License
14
13
  Classifier: Programming Language :: Python :: 3
15
14
  Classifier: Programming Language :: Python :: 3 :: Only
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
16
18
  Classifier: Topic :: Scientific/Engineering :: Visualization
17
- Requires-Python: >=3.10
19
+ Requires-Python: >=3.11
18
20
  Description-Content-Type: text/markdown
19
21
  License-File: LICENSE
20
22
  Requires-Dist: matplotlib>=3.7
21
23
  Requires-Dist: networkx>=3.0
22
24
  Requires-Dist: numpy
23
25
  Provides-Extra: dev
26
+ Requires-Dist: build; extra == "dev"
24
27
  Requires-Dist: pytest; extra == "dev"
25
28
  Requires-Dist: ruff; extra == "dev"
26
29
  Requires-Dist: pyright; extra == "dev"
27
30
  Requires-Dist: ipython; extra == "dev"
28
- Requires-Dist: tomli>=2.0.1; extra == "dev"
29
31
  Requires-Dist: tensorkrowch; extra == "dev"
30
32
  Requires-Dist: tensornetwork; extra == "dev"
31
33
  Requires-Dist: quimb; extra == "dev"
@@ -64,8 +66,9 @@ PyTorch/NumPy `einsum` tensor networks.
64
66
  Tensor network libraries use different object models and rarely share a single visualization path.
65
67
  This package **normalizes** each backend into one graph description, **lays out** nodes (chains,
66
68
  grids, trees, planar embeddings, or force-directed fallback), and **draws** with Matplotlib in
67
- **2D** (filled disks) or **3D** (lightweight octahedra). There is no custom GUI: you get standard
68
- `Figure` and `Axes` objects for saving, composing subplots, and further styling.
69
+ **2D** (filled disks) or **3D** (lightweight octahedra). The interactive layer stays inside
70
+ standard Matplotlib figures: `show_tensor_network` can add a small control panel, while the return
71
+ value is still a normal `Figure` plus `Axes` object that you can save, embed, or restyle.
69
72
 
70
73
  **Audience:** Researchers who work with tensor networks and want consistent, publication-friendly
71
74
  diagrams across Quimb, TeNPy, TensorNetwork, TensorKrowch, or traced `einsum` contraction graphs.
@@ -74,6 +77,8 @@ diagrams across Quimb, TeNPy, TensorNetwork, TensorKrowch, or traced `einsum` co
74
77
 
75
78
  PyPI package name: `tensor-network-visualization`. Import module: `tensor_network_viz`.
76
79
 
80
+ **Requires Python 3.11 or newer.**
81
+
77
82
  ### Base install
78
83
 
79
84
  ```bash
@@ -148,13 +153,19 @@ Everything below maps to real parameters—there are no hidden mode switches.
148
153
 
149
154
  | Concept | Where | Meaning |
150
155
  |--------|--------|---------|
151
- | **View mode** | `show_tensor_network(..., view=...)` | `"2d"` — disk nodes; `"3d"` octahedra. Same normalized graph. |
152
- | **Engine mode** | `engine=...` | Adapter: `"tensorkrowch"`, `"tensornetwork"`, `"quimb"`, `"tenpy"`, `"einsum"`. Invalid `ValueError`. |
156
+ | **View mode** | `show_tensor_network(..., view=...)` | Default is `"2d"`; `"3d"` is available from the same figure controls when widgets are enabled. |
157
+ | **Engine mode** | `engine=...` | Optional override. When omitted, `show_tensor_network` auto-detects `"tensorkrowch"`, `"tensornetwork"`, `"quimb"`, `"tenpy"`, or `"einsum"` from the input. Invalid explicit values still raise `ValueError`. |
153
158
  | **Display mode** | `show=True` / `False` | If `True`: Jupyter **kernel** uses `IPython.display.display(fig)`; otherwise `plt.show()`. If `False`: neither runs—use for `savefig` / batch. |
154
- | **Label policy** | `PlotConfig` + overrides | Defaults: `show_tensor_labels`, `show_index_labels`. Per-call: `show_tensor_network(..., show_tensor_labels=..., show_index_labels=...)`. |
155
- | **Hover labels** | `PlotConfig(hover_labels=True)` | Tensor names and bond labels appear on pointer hover (2D axes hit-test; 3D screen-space distance). Needs an **interactive** Matplotlib window. |
156
- | **Contraction scheme** | `PlotConfig(show_contraction_scheme=True)` | **Einsum:** cumulative per-step highlights from the trace. **Other engines:** set **`contraction_scheme_by_name`**. **2D:** rounded boxes (AABB + pad); colored borders (no fill by default). **3D:** wireframe box. See **`docs/guide.md`**. |
157
- | **Einsum workflow** | `engine="einsum"` | **Auto:** `EinsumTrace` + `einsum` (binary `pair_tensor`, unary/ternary+ `einsum_trace_step`; implicit `->`, `out=`). **Manual:** `pair_tensor` / `einsum_trace_step` (ellipsis needs `metadata` shapes). See **`examples/einsum_general.py`**. |
159
+ | **Interactive controls** | `interactive_controls=True` | Figure-level Matplotlib widgets for view/hover/label toggles. Set `False` for clean static exports or headless batch rendering. |
160
+ | **Label policy** | `PlotConfig` + overrides | Defaults: `show_tensor_labels=False`, `show_index_labels=False`. Per-call: `show_tensor_network(..., show_tensor_labels=..., show_index_labels=...)`. |
161
+ | **Hover labels** | `PlotConfig(hover_labels=True)` | Default is `True`. Hover tooltips are independent from static labels, so both can stay enabled together in an interactive Matplotlib window. |
162
+ | **Contraction scheme** | `PlotConfig(show_contraction_scheme=True)` | **Einsum:** cumulative per-step highlights from the trace. **Other engines:** set **`contraction_scheme_by_name`**. Compatible figures now add Matplotlib toggles for **Scheme**, **Playback**, and **Cost hover**; if you start with those flags off, the scheme bundle is computed lazily on first use. **2D:** rounded boxes (AABB + pad); colored borders (no fill by default). **3D:** wireframe box. See **`docs/guide.md`**. |
163
+ | **Einsum workflow** | `engine="einsum"` | **Auto:** `EinsumTrace` + `einsum` (binary `pair_tensor`, unary/ternary+ `einsum_trace_step`; implicit `->`, `out=`). **Manual:** ordered `pair_tensor` / `einsum_trace_step` lists when you want a fully explicit trace. See **`examples/run_demo.py`** and **`examples/einsum_demo.py`**. |
164
+
165
+ `show_tensor_network` now creates figure-level Matplotlib widgets by default: a `2d/3d` selector on
166
+ figures it creates itself, plus `Hover`, `Tensor labels`, and `Edge labels` checkboxes. If you
167
+ pass an external `ax`, the same-view checkboxes stay available but the `2d/3d` selector is hidden.
168
+ The default widget state is `Hover=True`, `Tensor labels=False`, `Edge labels=False`.
158
169
 
159
170
  ## Minimal examples
160
171
 
@@ -177,13 +188,16 @@ network = qtn.TensorNetwork(tensors)
177
188
  fig, ax = show_tensor_network(
178
189
  network,
179
190
  engine="quimb",
180
- view="2d",
181
191
  config=PlotConfig(figsize=(8, 6)),
192
+ interactive_controls=False,
182
193
  show=False,
183
194
  )
184
195
  fig.savefig("network.png", bbox_inches="tight")
185
196
  ```
186
197
 
198
+ Use `interactive_controls=False` when you want the saved figure without the Matplotlib control
199
+ panel.
200
+
187
201
  ### Quimb 3D, hide index labels on this call only
188
202
 
189
203
  ```python
@@ -203,12 +217,12 @@ fig, ax = show_tensor_network(
203
217
  fig, ax = show_tensor_network(
204
218
  network,
205
219
  engine="quimb",
206
- view="2d",
207
220
  config=PlotConfig(figsize=(8, 6), hover_labels=True),
208
221
  )
209
222
  ```
210
223
 
211
- No effect for headless `show=False` without a GUI event loop; pair with an interactive backend
224
+ Hover is independent from static labels, so you can also enable tensor or edge labels from the
225
+ figure checkboxes without losing the hover tooltips. This still needs an interactive backend
212
226
  (e.g. `%matplotlib widget` in Jupyter).
213
227
 
214
228
  ### TeNPy finite MPS (sketch)
@@ -222,7 +236,6 @@ from tensor_network_viz import show_tensor_network, PlotConfig
222
236
  fig, ax = show_tensor_network(
223
237
  mps,
224
238
  engine="tenpy",
225
- view="2d",
226
239
  config=PlotConfig(figsize=(8, 6)),
227
240
  show=False,
228
241
  )
@@ -234,25 +247,30 @@ fig, ax = show_tensor_network(
234
247
  show_tensor_network(
235
248
  network,
236
249
  *,
237
- engine: EngineName,
238
- view: ViewName,
250
+ engine: EngineName | None = None,
251
+ view: ViewName | None = None,
239
252
  config: PlotConfig | None = None,
253
+ ax: Axes | Axes3D | None = None,
240
254
  show_tensor_labels: bool | None = None,
241
255
  show_index_labels: bool | None = None,
256
+ interactive_controls: bool = True,
242
257
  show: bool = True,
243
258
  ) -> tuple[Figure, Axes | Axes3D]
244
259
  ```
245
260
 
246
261
  - **`network`:** Backend-native object or iterable (see [guide — supported inputs](docs/guide.md)).
247
- - **`engine`:** `"tensorkrowch"` \| `"tensornetwork"` \| `"quimb"` \| `"tenpy"` \| `"einsum"`.
248
- - **`view`:** `"2d"` \| `"3d"`.
262
+ - **`engine`:** optional explicit override. If omitted, the backend is inferred from `network`.
263
+ - **`view`:** `"2d"` \| `"3d"`; omitted means `"2d"` unless a 3D `ax` is passed.
249
264
  - **`config`:** Styling and layout; defaults to `PlotConfig()` if omitted.
265
+ - **`ax`:** Optional Matplotlib axes. When present, rendering stays on that axes and the `2d/3d` selector is hidden.
250
266
  - **`show_tensor_labels` / `show_index_labels`:** If `None`, use values from `config`; else override for this call only.
267
+ - **`interactive_controls`:** If `True`, attach the view/hover/label widgets when the figure supports them. Set `False` for a static render.
251
268
  - **`show`:** Whether to push the figure to the current UI (`display`/`show`).
252
269
  - **Returns:** `(fig, ax)` for titles, `savefig`, colorbars, or embedding in a subplot.
253
270
 
254
271
  Backend-specific shortcuts (same renderer core) accept **`ax=`** and **`seed=`** for subplots and
255
- reproducible layout; see the [guide](docs/guide.md).
272
+ reproducible layout; they stay fixed-dimension helpers (`plot_*_network_2d` or `plot_*_network_3d`)
273
+ and do not add the `2d/3d` selector. See the [guide](docs/guide.md).
256
274
 
257
275
  ### `PlotConfig` quick reference
258
276
 
@@ -270,8 +288,8 @@ Numeric fields with **`None`** use the corresponding `DEFAULT_*` on the class (s
270
288
  | `bond_edge_color` | `"#0369A1"` | Contraction edges. |
271
289
  | `dangling_edge_color` | `"#BE123C"` | Dangling (open) legs. |
272
290
  | `figsize` | `(8, 6)` | `inches`; `None` uses Matplotlib fallback `(14, 10)` when the renderer creates a new figure. |
273
- | `show_tensor_labels` | `True` | Draw tensor names on nodes. |
274
- | `show_index_labels` | `True` | Draw axis names on bonds / stubs. |
291
+ | `show_tensor_labels` | `False` | Draw tensor names on nodes. |
292
+ | `show_index_labels` | `False` | Draw axis names on bonds / stubs. |
275
293
  | `node_radius` | `None` | → `0.08` data units (scaled with layout; multiplies geometric radius). |
276
294
  | `stub_length` | `None` | → `0.16` (dangling stub length scale). |
277
295
  | `self_loop_radius` | `None` | → `0.2` (self-contraction loops). |
@@ -281,7 +299,7 @@ Numeric fields with **`None`** use the corresponding `DEFAULT_*` on the class (s
281
299
  | `positions` | `None` | `dict[int, tuple[float, ...]]` — custom positions keyed by **normalized node id** (`id` of adapter node); partial dicts get layout for missing ids. |
282
300
  | `validate_positions` | `False` | If `True`, warn on unknown keys or short coordinates vs `view`. |
283
301
  | `refine_tensor_labels` | `True` | Extra passes to fit tensor names inside the node marker (2D or 3D); set `False` for speed. |
284
- | `hover_labels` | `False` | Hide labels until hover (interactive only). |
302
+ | `hover_labels` | `True` | Enable hover tooltips independently from static labels (interactive only). |
285
303
 
286
304
  Defaults `0.08`, `0.16`, `0.2`, `0.85`, `0.75`, `220` are also available as
287
305
  `PlotConfig.DEFAULT_NODE_RADIUS`, `DEFAULT_STUB_LENGTH`, `DEFAULT_SELF_LOOP_RADIUS`,
@@ -337,23 +355,35 @@ Details, subgraph behavior, and Quimb hyperindex hubs are in **[docs/guide.md](d
337
355
 
338
356
  ## Example scripts
339
357
 
340
- Runnable demos live under **`examples/`**. From the repo root with the right extra installed:
358
+ Runnable demos live under **`examples/`** and now share one public launcher:
359
+
360
+ ```bash
361
+ python examples/run_demo.py <engine> <example> [options]
362
+ ```
341
363
 
342
- | Script | Purpose |
364
+ Main files:
365
+
366
+ | File | Purpose |
343
367
  |--------|---------|
344
- | `demo_cli.py` | Shared helpers (`--hover-labels` `PlotConfig(hover_labels=True)`); imported by demos. |
345
- | `tensorkrowch_demo.py` | MPS, MPO, PEPS, weird, disconnected; `--from-list` subset. |
346
- | `tensornetwork_demo.py` | Same topologies with `tensornetwork.Node`. |
347
- | `mera_tree_demo.py` | Large MERA + binary TTN stress test. |
348
- | `cubic_peps_demo.py` | 3D cubic PEPS lattice. |
349
- | `quimb_demo.py` | Includes hyper-index example; `--from-list`. |
350
- | `tenpy_demo.py` | MPS/MPO, purification, uniform, excitation chain (duck-typed like `MomentumMPS`). |
351
- | `tenpy_explicit_tn_demo.py` | Explicit `TenPyTensorNetwork`: open chain or 3-way hub ([examples/README](examples/README.md)). |
352
- | `einsum_demo.py` | Auto trace vs manual `pair_tensor`. |
353
- | `einsum_general.py` | Ellipsis, batch hubs, multi-step fusion, traces, short MPS, implicit/`out=`, unary, ternary (auto-trace). |
354
- | `tn_tsp.py` | Larger TensorKrowch TSP construction. |
355
-
356
- Catalog and one-liner commands: **[examples/README.md](examples/README.md)**.
368
+ | `run_demo.py` | Public CLI entry point for every engine and example. |
369
+ | `demo_cli.py` | Shared typed helpers for parsing, save paths, plot config, and topology builders. |
370
+ | `tensorkrowch_demo.py` | TensorKrowch registry: MPS/TT, MPO, ladder, PEPS, cubic PEPS, MERA, MERA+TTN, weird, disconnected. |
371
+ | `tensornetwork_demo.py` | TensorNetwork registry with the same structured graph examples. |
372
+ | `quimb_demo.py` | Quimb registry with the same graph family plus a native hypergraph example. |
373
+ | `tenpy_demo.py` | TeNPy registry: native MPS/MPO/iMPS/iMPO/purification/uniform/excitation plus explicit chain/hub/hyper examples. |
374
+ | `einsum_demo.py` | Einsum registry: network-style traces plus `ellipsis`, `batch`, `trace`, `ternary`, `unary`, `nway`, `implicit_out`. |
375
+ | `run_all_examples.py` | Headless batch runner that calls `run_demo.py` and saves PNGs. |
376
+
377
+ Useful launcher examples:
378
+
379
+ ```bash
380
+ python examples/run_demo.py quimb hyper --view 2d
381
+ python examples/run_demo.py tenpy chain --view 2d --save tenpy_chain.png --no-show
382
+ python examples/run_demo.py einsum ellipsis --view 3d --from-list
383
+ python examples/run_demo.py tensornetwork mera_ttn --view 2d --scheme
384
+ ```
385
+
386
+ Catalog and CLI details: **[examples/README.md](examples/README.md)**.
357
387
 
358
388
  ## Backend notes
359
389
 
@@ -374,7 +404,7 @@ Catalog and one-liner commands: **[examples/README.md](examples/README.md)**.
374
404
 
375
405
  ```bash
376
406
  python -m pip install -e ".[quimb]"
377
- python examples/quimb_demo.py mps 2d --save quimb_mps.png --no-show
407
+ python examples/run_demo.py quimb mps --view 2d --save quimb_mps.png --no-show
378
408
  python -m pytest
379
409
  ```
380
410
 
@@ -388,6 +418,7 @@ Expect `quimb_mps.png` and all tests passing.
388
418
  | `ValueError: Unsupported tensor network engine` / `view` | Use only listed `engine` / `view` literals (see above). |
389
419
  | Blank or double figure in Jupyter | Assign `fig, ax = show_tensor_network(...)`; avoid bare tuple as last line; try `%matplotlib widget` or inline. |
390
420
  | Hover labels do nothing | Requires interactive backend and `show` path that runs a GUI or widget event loop; not for `--no-show` PNG only. |
421
+ | Saved figure includes the control panel | Pass `interactive_controls=False` when exporting a static figure from `show_tensor_network`. |
391
422
  | Huge graphs are slow | `PlotConfig(refine_tensor_labels=False)`; lower `layout_iterations` or pass `positions`. Force layout samples repulsion when node count is large (about 72+; see [guide](docs/guide.md#layout-and-draw-scale)). |
392
423
  | Einsum unary trace (`ii->i`) looks odd in 2D | Layout offsets the virtual hub off the tensor in 2D; try `view="3d"` or read [Einsum unary / same-tensor trace in 2D](docs/guide.md#toc-einsum-unary-2d-layout) in the guide. |
393
424
 
@@ -398,7 +429,7 @@ Expect `quimb_mps.png` and all tests passing.
398
429
  - **[docs/guide.md](docs/guide.md)** — Installation, backends, `PlotConfig` recipes, layout/draw
399
430
  behavior, architecture, **extended troubleshooting**.
400
431
  - **[CHANGELOG.md](CHANGELOG.md)** — Release notes by version.
401
- - **[examples/README.md](examples/README.md)** — CLI examples per script.
432
+ - **[examples/README.md](examples/README.md)** — launcher usage, engine/example matrix, and batch examples.
402
433
  - **[THIRD_PARTY_LICENSES.md](THIRD_PARTY_LICENSES.md)**
403
434
 
404
435
  ## Support and contributing
@@ -410,9 +441,18 @@ Expect `quimb_mps.png` and all tests passing.
410
441
  ## Development
411
442
 
412
443
  ```bash
413
- python -m pip install -e ".[dev]"
414
- ruff check .
415
- ruff format .
416
- pyright
417
- pytest
444
+ python -m venv .venv
445
+ python -m pip install -r requirements.dev.txt
446
+ ```
447
+
448
+ Windows:
449
+
450
+ ```powershell
451
+ .\.venv\Scripts\python scripts\verify.py
452
+ ```
453
+
454
+ Linux/macOS (with the venv activated):
455
+
456
+ ```bash
457
+ python scripts/verify.py
418
458
  ```
@@ -15,8 +15,9 @@ PyTorch/NumPy `einsum` tensor networks.
15
15
  Tensor network libraries use different object models and rarely share a single visualization path.
16
16
  This package **normalizes** each backend into one graph description, **lays out** nodes (chains,
17
17
  grids, trees, planar embeddings, or force-directed fallback), and **draws** with Matplotlib in
18
- **2D** (filled disks) or **3D** (lightweight octahedra). There is no custom GUI: you get standard
19
- `Figure` and `Axes` objects for saving, composing subplots, and further styling.
18
+ **2D** (filled disks) or **3D** (lightweight octahedra). The interactive layer stays inside
19
+ standard Matplotlib figures: `show_tensor_network` can add a small control panel, while the return
20
+ value is still a normal `Figure` plus `Axes` object that you can save, embed, or restyle.
20
21
 
21
22
  **Audience:** Researchers who work with tensor networks and want consistent, publication-friendly
22
23
  diagrams across Quimb, TeNPy, TensorNetwork, TensorKrowch, or traced `einsum` contraction graphs.
@@ -25,6 +26,8 @@ diagrams across Quimb, TeNPy, TensorNetwork, TensorKrowch, or traced `einsum` co
25
26
 
26
27
  PyPI package name: `tensor-network-visualization`. Import module: `tensor_network_viz`.
27
28
 
29
+ **Requires Python 3.11 or newer.**
30
+
28
31
  ### Base install
29
32
 
30
33
  ```bash
@@ -99,13 +102,19 @@ Everything below maps to real parameters—there are no hidden mode switches.
99
102
 
100
103
  | Concept | Where | Meaning |
101
104
  |--------|--------|---------|
102
- | **View mode** | `show_tensor_network(..., view=...)` | `"2d"` — disk nodes; `"3d"` octahedra. Same normalized graph. |
103
- | **Engine mode** | `engine=...` | Adapter: `"tensorkrowch"`, `"tensornetwork"`, `"quimb"`, `"tenpy"`, `"einsum"`. Invalid `ValueError`. |
105
+ | **View mode** | `show_tensor_network(..., view=...)` | Default is `"2d"`; `"3d"` is available from the same figure controls when widgets are enabled. |
106
+ | **Engine mode** | `engine=...` | Optional override. When omitted, `show_tensor_network` auto-detects `"tensorkrowch"`, `"tensornetwork"`, `"quimb"`, `"tenpy"`, or `"einsum"` from the input. Invalid explicit values still raise `ValueError`. |
104
107
  | **Display mode** | `show=True` / `False` | If `True`: Jupyter **kernel** uses `IPython.display.display(fig)`; otherwise `plt.show()`. If `False`: neither runs—use for `savefig` / batch. |
105
- | **Label policy** | `PlotConfig` + overrides | Defaults: `show_tensor_labels`, `show_index_labels`. Per-call: `show_tensor_network(..., show_tensor_labels=..., show_index_labels=...)`. |
106
- | **Hover labels** | `PlotConfig(hover_labels=True)` | Tensor names and bond labels appear on pointer hover (2D axes hit-test; 3D screen-space distance). Needs an **interactive** Matplotlib window. |
107
- | **Contraction scheme** | `PlotConfig(show_contraction_scheme=True)` | **Einsum:** cumulative per-step highlights from the trace. **Other engines:** set **`contraction_scheme_by_name`**. **2D:** rounded boxes (AABB + pad); colored borders (no fill by default). **3D:** wireframe box. See **`docs/guide.md`**. |
108
- | **Einsum workflow** | `engine="einsum"` | **Auto:** `EinsumTrace` + `einsum` (binary `pair_tensor`, unary/ternary+ `einsum_trace_step`; implicit `->`, `out=`). **Manual:** `pair_tensor` / `einsum_trace_step` (ellipsis needs `metadata` shapes). See **`examples/einsum_general.py`**. |
108
+ | **Interactive controls** | `interactive_controls=True` | Figure-level Matplotlib widgets for view/hover/label toggles. Set `False` for clean static exports or headless batch rendering. |
109
+ | **Label policy** | `PlotConfig` + overrides | Defaults: `show_tensor_labels=False`, `show_index_labels=False`. Per-call: `show_tensor_network(..., show_tensor_labels=..., show_index_labels=...)`. |
110
+ | **Hover labels** | `PlotConfig(hover_labels=True)` | Default is `True`. Hover tooltips are independent from static labels, so both can stay enabled together in an interactive Matplotlib window. |
111
+ | **Contraction scheme** | `PlotConfig(show_contraction_scheme=True)` | **Einsum:** cumulative per-step highlights from the trace. **Other engines:** set **`contraction_scheme_by_name`**. Compatible figures now add Matplotlib toggles for **Scheme**, **Playback**, and **Cost hover**; if you start with those flags off, the scheme bundle is computed lazily on first use. **2D:** rounded boxes (AABB + pad); colored borders (no fill by default). **3D:** wireframe box. See **`docs/guide.md`**. |
112
+ | **Einsum workflow** | `engine="einsum"` | **Auto:** `EinsumTrace` + `einsum` (binary `pair_tensor`, unary/ternary+ `einsum_trace_step`; implicit `->`, `out=`). **Manual:** ordered `pair_tensor` / `einsum_trace_step` lists when you want a fully explicit trace. See **`examples/run_demo.py`** and **`examples/einsum_demo.py`**. |
113
+
114
+ `show_tensor_network` now creates figure-level Matplotlib widgets by default: a `2d/3d` selector on
115
+ figures it creates itself, plus `Hover`, `Tensor labels`, and `Edge labels` checkboxes. If you
116
+ pass an external `ax`, the same-view checkboxes stay available but the `2d/3d` selector is hidden.
117
+ The default widget state is `Hover=True`, `Tensor labels=False`, `Edge labels=False`.
109
118
 
110
119
  ## Minimal examples
111
120
 
@@ -128,13 +137,16 @@ network = qtn.TensorNetwork(tensors)
128
137
  fig, ax = show_tensor_network(
129
138
  network,
130
139
  engine="quimb",
131
- view="2d",
132
140
  config=PlotConfig(figsize=(8, 6)),
141
+ interactive_controls=False,
133
142
  show=False,
134
143
  )
135
144
  fig.savefig("network.png", bbox_inches="tight")
136
145
  ```
137
146
 
147
+ Use `interactive_controls=False` when you want the saved figure without the Matplotlib control
148
+ panel.
149
+
138
150
  ### Quimb 3D, hide index labels on this call only
139
151
 
140
152
  ```python
@@ -154,12 +166,12 @@ fig, ax = show_tensor_network(
154
166
  fig, ax = show_tensor_network(
155
167
  network,
156
168
  engine="quimb",
157
- view="2d",
158
169
  config=PlotConfig(figsize=(8, 6), hover_labels=True),
159
170
  )
160
171
  ```
161
172
 
162
- No effect for headless `show=False` without a GUI event loop; pair with an interactive backend
173
+ Hover is independent from static labels, so you can also enable tensor or edge labels from the
174
+ figure checkboxes without losing the hover tooltips. This still needs an interactive backend
163
175
  (e.g. `%matplotlib widget` in Jupyter).
164
176
 
165
177
  ### TeNPy finite MPS (sketch)
@@ -173,7 +185,6 @@ from tensor_network_viz import show_tensor_network, PlotConfig
173
185
  fig, ax = show_tensor_network(
174
186
  mps,
175
187
  engine="tenpy",
176
- view="2d",
177
188
  config=PlotConfig(figsize=(8, 6)),
178
189
  show=False,
179
190
  )
@@ -185,25 +196,30 @@ fig, ax = show_tensor_network(
185
196
  show_tensor_network(
186
197
  network,
187
198
  *,
188
- engine: EngineName,
189
- view: ViewName,
199
+ engine: EngineName | None = None,
200
+ view: ViewName | None = None,
190
201
  config: PlotConfig | None = None,
202
+ ax: Axes | Axes3D | None = None,
191
203
  show_tensor_labels: bool | None = None,
192
204
  show_index_labels: bool | None = None,
205
+ interactive_controls: bool = True,
193
206
  show: bool = True,
194
207
  ) -> tuple[Figure, Axes | Axes3D]
195
208
  ```
196
209
 
197
210
  - **`network`:** Backend-native object or iterable (see [guide — supported inputs](docs/guide.md)).
198
- - **`engine`:** `"tensorkrowch"` \| `"tensornetwork"` \| `"quimb"` \| `"tenpy"` \| `"einsum"`.
199
- - **`view`:** `"2d"` \| `"3d"`.
211
+ - **`engine`:** optional explicit override. If omitted, the backend is inferred from `network`.
212
+ - **`view`:** `"2d"` \| `"3d"`; omitted means `"2d"` unless a 3D `ax` is passed.
200
213
  - **`config`:** Styling and layout; defaults to `PlotConfig()` if omitted.
214
+ - **`ax`:** Optional Matplotlib axes. When present, rendering stays on that axes and the `2d/3d` selector is hidden.
201
215
  - **`show_tensor_labels` / `show_index_labels`:** If `None`, use values from `config`; else override for this call only.
216
+ - **`interactive_controls`:** If `True`, attach the view/hover/label widgets when the figure supports them. Set `False` for a static render.
202
217
  - **`show`:** Whether to push the figure to the current UI (`display`/`show`).
203
218
  - **Returns:** `(fig, ax)` for titles, `savefig`, colorbars, or embedding in a subplot.
204
219
 
205
220
  Backend-specific shortcuts (same renderer core) accept **`ax=`** and **`seed=`** for subplots and
206
- reproducible layout; see the [guide](docs/guide.md).
221
+ reproducible layout; they stay fixed-dimension helpers (`plot_*_network_2d` or `plot_*_network_3d`)
222
+ and do not add the `2d/3d` selector. See the [guide](docs/guide.md).
207
223
 
208
224
  ### `PlotConfig` quick reference
209
225
 
@@ -221,8 +237,8 @@ Numeric fields with **`None`** use the corresponding `DEFAULT_*` on the class (s
221
237
  | `bond_edge_color` | `"#0369A1"` | Contraction edges. |
222
238
  | `dangling_edge_color` | `"#BE123C"` | Dangling (open) legs. |
223
239
  | `figsize` | `(8, 6)` | `inches`; `None` uses Matplotlib fallback `(14, 10)` when the renderer creates a new figure. |
224
- | `show_tensor_labels` | `True` | Draw tensor names on nodes. |
225
- | `show_index_labels` | `True` | Draw axis names on bonds / stubs. |
240
+ | `show_tensor_labels` | `False` | Draw tensor names on nodes. |
241
+ | `show_index_labels` | `False` | Draw axis names on bonds / stubs. |
226
242
  | `node_radius` | `None` | → `0.08` data units (scaled with layout; multiplies geometric radius). |
227
243
  | `stub_length` | `None` | → `0.16` (dangling stub length scale). |
228
244
  | `self_loop_radius` | `None` | → `0.2` (self-contraction loops). |
@@ -232,7 +248,7 @@ Numeric fields with **`None`** use the corresponding `DEFAULT_*` on the class (s
232
248
  | `positions` | `None` | `dict[int, tuple[float, ...]]` — custom positions keyed by **normalized node id** (`id` of adapter node); partial dicts get layout for missing ids. |
233
249
  | `validate_positions` | `False` | If `True`, warn on unknown keys or short coordinates vs `view`. |
234
250
  | `refine_tensor_labels` | `True` | Extra passes to fit tensor names inside the node marker (2D or 3D); set `False` for speed. |
235
- | `hover_labels` | `False` | Hide labels until hover (interactive only). |
251
+ | `hover_labels` | `True` | Enable hover tooltips independently from static labels (interactive only). |
236
252
 
237
253
  Defaults `0.08`, `0.16`, `0.2`, `0.85`, `0.75`, `220` are also available as
238
254
  `PlotConfig.DEFAULT_NODE_RADIUS`, `DEFAULT_STUB_LENGTH`, `DEFAULT_SELF_LOOP_RADIUS`,
@@ -288,23 +304,35 @@ Details, subgraph behavior, and Quimb hyperindex hubs are in **[docs/guide.md](d
288
304
 
289
305
  ## Example scripts
290
306
 
291
- Runnable demos live under **`examples/`**. From the repo root with the right extra installed:
307
+ Runnable demos live under **`examples/`** and now share one public launcher:
308
+
309
+ ```bash
310
+ python examples/run_demo.py <engine> <example> [options]
311
+ ```
292
312
 
293
- | Script | Purpose |
313
+ Main files:
314
+
315
+ | File | Purpose |
294
316
  |--------|---------|
295
- | `demo_cli.py` | Shared helpers (`--hover-labels` `PlotConfig(hover_labels=True)`); imported by demos. |
296
- | `tensorkrowch_demo.py` | MPS, MPO, PEPS, weird, disconnected; `--from-list` subset. |
297
- | `tensornetwork_demo.py` | Same topologies with `tensornetwork.Node`. |
298
- | `mera_tree_demo.py` | Large MERA + binary TTN stress test. |
299
- | `cubic_peps_demo.py` | 3D cubic PEPS lattice. |
300
- | `quimb_demo.py` | Includes hyper-index example; `--from-list`. |
301
- | `tenpy_demo.py` | MPS/MPO, purification, uniform, excitation chain (duck-typed like `MomentumMPS`). |
302
- | `tenpy_explicit_tn_demo.py` | Explicit `TenPyTensorNetwork`: open chain or 3-way hub ([examples/README](examples/README.md)). |
303
- | `einsum_demo.py` | Auto trace vs manual `pair_tensor`. |
304
- | `einsum_general.py` | Ellipsis, batch hubs, multi-step fusion, traces, short MPS, implicit/`out=`, unary, ternary (auto-trace). |
305
- | `tn_tsp.py` | Larger TensorKrowch TSP construction. |
306
-
307
- Catalog and one-liner commands: **[examples/README.md](examples/README.md)**.
317
+ | `run_demo.py` | Public CLI entry point for every engine and example. |
318
+ | `demo_cli.py` | Shared typed helpers for parsing, save paths, plot config, and topology builders. |
319
+ | `tensorkrowch_demo.py` | TensorKrowch registry: MPS/TT, MPO, ladder, PEPS, cubic PEPS, MERA, MERA+TTN, weird, disconnected. |
320
+ | `tensornetwork_demo.py` | TensorNetwork registry with the same structured graph examples. |
321
+ | `quimb_demo.py` | Quimb registry with the same graph family plus a native hypergraph example. |
322
+ | `tenpy_demo.py` | TeNPy registry: native MPS/MPO/iMPS/iMPO/purification/uniform/excitation plus explicit chain/hub/hyper examples. |
323
+ | `einsum_demo.py` | Einsum registry: network-style traces plus `ellipsis`, `batch`, `trace`, `ternary`, `unary`, `nway`, `implicit_out`. |
324
+ | `run_all_examples.py` | Headless batch runner that calls `run_demo.py` and saves PNGs. |
325
+
326
+ Useful launcher examples:
327
+
328
+ ```bash
329
+ python examples/run_demo.py quimb hyper --view 2d
330
+ python examples/run_demo.py tenpy chain --view 2d --save tenpy_chain.png --no-show
331
+ python examples/run_demo.py einsum ellipsis --view 3d --from-list
332
+ python examples/run_demo.py tensornetwork mera_ttn --view 2d --scheme
333
+ ```
334
+
335
+ Catalog and CLI details: **[examples/README.md](examples/README.md)**.
308
336
 
309
337
  ## Backend notes
310
338
 
@@ -325,7 +353,7 @@ Catalog and one-liner commands: **[examples/README.md](examples/README.md)**.
325
353
 
326
354
  ```bash
327
355
  python -m pip install -e ".[quimb]"
328
- python examples/quimb_demo.py mps 2d --save quimb_mps.png --no-show
356
+ python examples/run_demo.py quimb mps --view 2d --save quimb_mps.png --no-show
329
357
  python -m pytest
330
358
  ```
331
359
 
@@ -339,6 +367,7 @@ Expect `quimb_mps.png` and all tests passing.
339
367
  | `ValueError: Unsupported tensor network engine` / `view` | Use only listed `engine` / `view` literals (see above). |
340
368
  | Blank or double figure in Jupyter | Assign `fig, ax = show_tensor_network(...)`; avoid bare tuple as last line; try `%matplotlib widget` or inline. |
341
369
  | Hover labels do nothing | Requires interactive backend and `show` path that runs a GUI or widget event loop; not for `--no-show` PNG only. |
370
+ | Saved figure includes the control panel | Pass `interactive_controls=False` when exporting a static figure from `show_tensor_network`. |
342
371
  | Huge graphs are slow | `PlotConfig(refine_tensor_labels=False)`; lower `layout_iterations` or pass `positions`. Force layout samples repulsion when node count is large (about 72+; see [guide](docs/guide.md#layout-and-draw-scale)). |
343
372
  | Einsum unary trace (`ii->i`) looks odd in 2D | Layout offsets the virtual hub off the tensor in 2D; try `view="3d"` or read [Einsum unary / same-tensor trace in 2D](docs/guide.md#toc-einsum-unary-2d-layout) in the guide. |
344
373
 
@@ -349,7 +378,7 @@ Expect `quimb_mps.png` and all tests passing.
349
378
  - **[docs/guide.md](docs/guide.md)** — Installation, backends, `PlotConfig` recipes, layout/draw
350
379
  behavior, architecture, **extended troubleshooting**.
351
380
  - **[CHANGELOG.md](CHANGELOG.md)** — Release notes by version.
352
- - **[examples/README.md](examples/README.md)** — CLI examples per script.
381
+ - **[examples/README.md](examples/README.md)** — launcher usage, engine/example matrix, and batch examples.
353
382
  - **[THIRD_PARTY_LICENSES.md](THIRD_PARTY_LICENSES.md)**
354
383
 
355
384
  ## Support and contributing
@@ -361,9 +390,18 @@ Expect `quimb_mps.png` and all tests passing.
361
390
  ## Development
362
391
 
363
392
  ```bash
364
- python -m pip install -e ".[dev]"
365
- ruff check .
366
- ruff format .
367
- pyright
368
- pytest
393
+ python -m venv .venv
394
+ python -m pip install -r requirements.dev.txt
395
+ ```
396
+
397
+ Windows:
398
+
399
+ ```powershell
400
+ .\.venv\Scripts\python scripts\verify.py
401
+ ```
402
+
403
+ Linux/macOS (with the venv activated):
404
+
405
+ ```bash
406
+ python scripts/verify.py
369
407
  ```
@@ -1,15 +1,16 @@
1
1
  [build-system]
2
- requires = ["setuptools>=68"]
2
+ requires = ["setuptools>=77"]
3
3
  build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "tensor-network-visualization"
7
- version = "1.4.2"
7
+ version = "1.5.0"
8
8
  description = "Minimal Matplotlib visualizations for TensorKrowch, TensorNetwork, Quimb, TeNPy, and traced PyTorch/NumPy einsum tensor networks."
9
9
  authors = [{ name = "Alejandro Mata Ali" }]
10
10
  readme = "README.md"
11
- license = { text = "MIT" }
12
- requires-python = ">=3.10"
11
+ license = "MIT"
12
+ license-files = ["LICENSE"]
13
+ requires-python = ">=3.11"
13
14
  keywords = ["tensor-network", "visualization", "pytorch", "numpy", "tensorkrowch", "tensornetwork", "quimb", "tenpy", "einsum", "quantum-inspired", "matplotlib"]
14
15
  dependencies = [
15
16
  "matplotlib>=3.7",
@@ -17,9 +18,11 @@ dependencies = [
17
18
  "numpy",
18
19
  ]
19
20
  classifiers = [
20
- "License :: OSI Approved :: MIT License",
21
21
  "Programming Language :: Python :: 3",
22
22
  "Programming Language :: Python :: 3 :: Only",
23
+ "Programming Language :: Python :: 3.11",
24
+ "Programming Language :: Python :: 3.12",
25
+ "Programming Language :: Python :: 3.13",
23
26
  "Topic :: Scientific/Engineering :: Visualization",
24
27
  ]
25
28
 
@@ -31,7 +34,17 @@ Repository = "https://github.com/DOKOS-TAYOS/Tensor-Network-Visualization"
31
34
  Issues = "https://github.com/DOKOS-TAYOS/Tensor-Network-Visualization/issues"
32
35
 
33
36
  [project.optional-dependencies]
34
- dev = ["pytest", "ruff", "pyright", "ipython", "tomli>=2.0.1", "tensorkrowch", "tensornetwork", "quimb", "physics-tenpy"]
37
+ dev = [
38
+ "build",
39
+ "pytest",
40
+ "ruff",
41
+ "pyright",
42
+ "ipython",
43
+ "tensorkrowch",
44
+ "tensornetwork",
45
+ "quimb",
46
+ "physics-tenpy",
47
+ ]
35
48
  jupyter = ["ipympl>=0.9.0", "ipywidgets>=8.0", "jupyterlab>=4.0", "notebook>=7.0"]
36
49
  tensorkrowch = ["tensorkrowch"]
37
50
  tensornetwork = ["tensornetwork"]
@@ -52,7 +65,7 @@ pythonpath = ["src"]
52
65
 
53
66
  [tool.ruff]
54
67
  line-length = 100
55
- target-version = "py310"
68
+ target-version = "py311"
56
69
  src = ["src", "tests"]
57
70
  exclude = [".venv", ".tmp", ".tmp_venv_*", ".pip_tmp", ".pytest_cache", ".ruff_cache", "pytest-cache-files-*", "tn_tsp.py"]
58
71