photonviz 0.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.
- photonviz-0.5.0/.gitignore +24 -0
- photonviz-0.5.0/PKG-INFO +212 -0
- photonviz-0.5.0/README.md +185 -0
- photonviz-0.5.0/pyproject.toml +49 -0
- photonviz-0.5.0/src/photonviz/__init__.py +123 -0
- photonviz-0.5.0/src/photonviz/_arrays.py +169 -0
- photonviz-0.5.0/src/photonviz/_widget.py +86 -0
- photonviz-0.5.0/src/photonviz/charts.py +269 -0
- photonviz-0.5.0/src/photonviz/models.py +300 -0
- photonviz-0.5.0/src/photonviz/static/widget.js +828 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
node_modules/
|
|
2
|
+
dist/
|
|
3
|
+
*.tsbuildinfo
|
|
4
|
+
.DS_Store
|
|
5
|
+
.turbo/
|
|
6
|
+
coverage/
|
|
7
|
+
|
|
8
|
+
# Local agent guidance (not published)
|
|
9
|
+
CLAUDE.md
|
|
10
|
+
|
|
11
|
+
# Python bridge
|
|
12
|
+
python/.venv/
|
|
13
|
+
python/dist/
|
|
14
|
+
python/build/
|
|
15
|
+
python/src/*.egg-info/
|
|
16
|
+
python/src/photonviz/static/widget.js
|
|
17
|
+
__pycache__/
|
|
18
|
+
*.py[cod]
|
|
19
|
+
.pytest_cache/
|
|
20
|
+
|
|
21
|
+
# Docs site (VitePress cache + TypeDoc output)
|
|
22
|
+
docs/.vitepress/cache/
|
|
23
|
+
docs/.vitepress/dist/
|
|
24
|
+
docs/api/
|
photonviz-0.5.0/PKG-INFO
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: photonviz
|
|
3
|
+
Version: 0.5.0
|
|
4
|
+
Summary: GPU-accelerated (WebGL2) charts for Jupyter, JupyterLab and Google Colab
|
|
5
|
+
Project-URL: Homepage, https://github.com/coredumpdev/photon
|
|
6
|
+
Project-URL: Documentation, https://coredumpdev.github.io/photon/
|
|
7
|
+
Project-URL: Source, https://github.com/coredumpdev/photon/tree/master/python
|
|
8
|
+
Project-URL: Issues, https://github.com/coredumpdev/photon/issues
|
|
9
|
+
Author-email: Muzaffer Tolga Yakar <muzaffertolgayakar@gmail.com>
|
|
10
|
+
License: MIT
|
|
11
|
+
Keywords: charts,colab,jupyter,notebook,plotting,pytorch,visualization,webgl
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Framework :: Jupyter
|
|
14
|
+
Classifier: Framework :: Jupyter :: JupyterLab :: 4
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
19
|
+
Requires-Python: >=3.9
|
|
20
|
+
Requires-Dist: anywidget>=0.9.0
|
|
21
|
+
Requires-Dist: numpy>=1.21
|
|
22
|
+
Provides-Extra: dev
|
|
23
|
+
Requires-Dist: jupyterlab>=4; extra == 'dev'
|
|
24
|
+
Requires-Dist: pytest>=7; extra == 'dev'
|
|
25
|
+
Requires-Dist: watchfiles; extra == 'dev'
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
|
|
28
|
+
<p align="center">
|
|
29
|
+
<img src="https://raw.githubusercontent.com/coredumpdev/photon/master/assets/banner.png" alt="Photon" width="100%" />
|
|
30
|
+
</p>
|
|
31
|
+
|
|
32
|
+
# photonviz
|
|
33
|
+
|
|
34
|
+
**GPU-accelerated (WebGL2) charts for Jupyter, JupyterLab and Google Colab.**
|
|
35
|
+
|
|
36
|
+
<p>
|
|
37
|
+
<a href="https://pypi.org/project/photonviz/"><img src="https://img.shields.io/pypi/v/photonviz?color=3775a9&logo=pypi&logoColor=white" alt="PyPI"/></a>
|
|
38
|
+
<a href="https://pypi.org/project/photonviz/"><img src="https://img.shields.io/pypi/dm/photonviz?color=3775a9" alt="downloads"/></a>
|
|
39
|
+
<a href="https://pypi.org/project/photonviz/"><img src="https://img.shields.io/pypi/pyversions/photonviz?color=3775a9" alt="Python versions"/></a>
|
|
40
|
+
<img src="https://img.shields.io/badge/WebGL2-required-8b5cf6" alt="WebGL2"/>
|
|
41
|
+
<img src="https://img.shields.io/badge/Jupyter%20%C2%B7%20Lab%20%C2%B7%20Colab-supported-f37626?logo=jupyter&logoColor=white" alt="Jupyter · Lab · Colab"/>
|
|
42
|
+
<a href="https://github.com/coredumpdev/photon/blob/master/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue" alt="MIT"/></a>
|
|
43
|
+
· <a href="https://coredumpdev.github.io/photon/docs/python/">📖 Docs</a>
|
|
44
|
+
· <a href="https://coredumpdev.github.io/photon/">▶ Live demo</a>
|
|
45
|
+
</p>
|
|
46
|
+
|
|
47
|
+
The Python bridge to [Photon](https://github.com/coredumpdev/photon). NumPy
|
|
48
|
+
arrays and torch tensors cross to the browser as **binary buffers**, so a million
|
|
49
|
+
points still pan and zoom at 60fps inside a notebook cell — no image round-trip,
|
|
50
|
+
no JSON blow-up.
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pip install photonviz
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Nothing else to install: the widget ships one self-contained ESM bundle, so there
|
|
57
|
+
is no CDN fetch, no `jupyter labextension install`, and no separate JS package.
|
|
58
|
+
|
|
59
|
+
<p align="center">
|
|
60
|
+
<img src="https://raw.githubusercontent.com/coredumpdev/photon/master/assets/jupyter-hero.png" alt="A 200,000-point line chart rendered by photonviz in JupyterLab" width="100%" />
|
|
61
|
+
</p>
|
|
62
|
+
|
|
63
|
+
<sub>Real capture from JupyterLab — 200k points, interactive: wheel to zoom, drag to pan, hover for a tooltip.</sub>
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Quick start
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
import numpy as np
|
|
71
|
+
import photonviz as pv
|
|
72
|
+
|
|
73
|
+
x = np.linspace(0, 10, 200_000)
|
|
74
|
+
pv.line(x, np.sin(x) + 0.3 * np.sin(x * 7), name="signal", plot={"theme": "dark", "legend": True})
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Charts chain, and the last expression in a cell renders itself:
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
(pv.Plot(theme="dark", title="Two series", legend=True)
|
|
81
|
+
.line(x, np.sin(x), name="sin", color="#60a5fa")
|
|
82
|
+
.line(x, np.cos(x), name="cos", color="#f472b6", dash=[6, 4])
|
|
83
|
+
.hline(0, color="#64748b"))
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Every keyword maps 1:1 onto the [TypeScript options](https://coredumpdev.github.io/photon/llms-full.txt),
|
|
87
|
+
so the JS reference applies verbatim — `color`, `width`, `step`, `colorBy`,
|
|
88
|
+
`yAxis`, `renderType`, and so on.
|
|
89
|
+
|
|
90
|
+
### Google Colab
|
|
91
|
+
|
|
92
|
+
Run once per session, then use `photonviz` normally:
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
from google.colab import output
|
|
96
|
+
output.enable_custom_widget_manager()
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## What you can draw
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
pv.scatter(x, y, sizes=area, colors=hex_list) # bubble chart
|
|
105
|
+
pv.histogram(samples, bins=40)
|
|
106
|
+
pv.heatmap(z, cols, rows, extent={"x": [0, 1], "y": [0, 1]}, colormap="magma")
|
|
107
|
+
pv.candlestick(t, o, h, l, c) # + heikin_ashi, bollinger, drawdown…
|
|
108
|
+
pv.regression(x, y, band=2) # OLS + confidence band (or method="loess")
|
|
109
|
+
pv.corr_matrix([a, b, c], names=["a", "b", "c"]) # diverging, locked to ±1
|
|
110
|
+
pv.psd(signal, sampleRate=1000) # Welch spectrum
|
|
111
|
+
pv.confusion_matrix(y_true, y_pred) # + roc_curve, pr_curve, calibration, embedding…
|
|
112
|
+
pv.surface(z, cols, rows) # 3D — orbit with the mouse
|
|
113
|
+
pv.polar_line(theta, r)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
`Plot`, `Plot3D` and `Polar` are the full objects; the module-level names are
|
|
117
|
+
one-line shortcuts. Pass `plot={...}` to a shortcut to configure the plot itself:
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
pv.scatter(x, y, size=4, plot={"theme": "dark", "pick": "xy", "colorbar": False})
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Model architecture
|
|
126
|
+
|
|
127
|
+
Hand a **PyTorch**, **Keras**, **scikit-learn** or **ONNX** model straight to
|
|
128
|
+
`model_graph` — the export happens in Python, the layout in the browser.
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
import torch, torchvision, photonviz as pv
|
|
132
|
+
|
|
133
|
+
model = torchvision.models.resnet18()
|
|
134
|
+
|
|
135
|
+
# 2D — a Netron-style DAG, with residual connections routed around the trunk.
|
|
136
|
+
pv.model_graph(model, example_input=torch.randn(1, 3, 224, 224), direction="horizontal")
|
|
137
|
+
|
|
138
|
+
# 3D — one cuboid per layer, sized from its output tensor: feature maps shrink
|
|
139
|
+
# while channel depth grows.
|
|
140
|
+
pv.model_graph_3d(
|
|
141
|
+
model,
|
|
142
|
+
example_input=torch.randn(1, 3, 224, 224),
|
|
143
|
+
labels="full",
|
|
144
|
+
plot={"aspectMode": "data", "projection": "orthographic", "showAxes": False},
|
|
145
|
+
)
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
| Framework | How it is read | Notes |
|
|
149
|
+
| --- | --- | --- |
|
|
150
|
+
| PyTorch | `torch.fx` symbolic trace | Branches and skip connections survive. Pass `example_input=` to record shapes. Untraceable models fall back to a flat chain of leaf modules. |
|
|
151
|
+
| Keras / TF | `model.to_json()` + per-layer shapes | Sequential and functional, Keras 2 and 3. |
|
|
152
|
+
| scikit-learn | `Pipeline` / `ColumnTransformer` / `FeatureUnion` walk | Parallel branches fan out and back in. An `MLPClassifier` expands into its real dense stack. |
|
|
153
|
+
| ONNX | `MessageToDict` + shape inference | The framework-neutral path. |
|
|
154
|
+
|
|
155
|
+
<p align="center">
|
|
156
|
+
<img src="https://raw.githubusercontent.com/coredumpdev/photon/master/assets/jupyter-model3d.png" alt="A CNN drawn as tensor-shaped 3D blocks inside a notebook" width="100%" />
|
|
157
|
+
</p>
|
|
158
|
+
|
|
159
|
+
<sub>Each cuboid is one layer: the visible face is its feature map, the thickness its channel count. Drag to orbit.</sub>
|
|
160
|
+
|
|
161
|
+
The exporters are usable on their own — `pv.from_torch(model)`, `pv.from_keras`,
|
|
162
|
+
`pv.from_sklearn`, `pv.from_onnx` — and a hand-written
|
|
163
|
+
`{"nodes": [...], "edges": [...]}` graph works too.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Example notebooks
|
|
168
|
+
|
|
169
|
+
Runnable, in the repo — [`examples/notebooks/`](https://github.com/coredumpdev/photon/tree/master/examples/notebooks):
|
|
170
|
+
|
|
171
|
+
| Notebook | What it covers |
|
|
172
|
+
| --- | --- |
|
|
173
|
+
| [`quickstart.ipynb`](https://github.com/coredumpdev/photon/blob/master/examples/notebooks/quickstart.ipynb) | The five-minute tour: a 200k-point line, a bubble chart with an OLS fit, a confusion matrix, a 3D model graph, a 3D surface. |
|
|
174
|
+
| [`gallery.ipynb`](https://github.com/coredumpdev/photon/blob/master/examples/notebooks/gallery.ipynb) | The full spread — distributions, fields, custom colours, finance, signal processing, ML metrics, model architecture, and 3D. |
|
|
175
|
+
|
|
176
|
+
<p align="center">
|
|
177
|
+
<img src="https://raw.githubusercontent.com/coredumpdev/photon/master/assets/jupyter-bubble.png" alt="Bubble chart with a least-squares fit and confidence band" width="49%" />
|
|
178
|
+
<img src="https://raw.githubusercontent.com/coredumpdev/photon/master/assets/jupyter-surface.png" alt="A lit 3D surface rendered in a notebook cell" width="49%" />
|
|
179
|
+
</p>
|
|
180
|
+
|
|
181
|
+
## How it works
|
|
182
|
+
|
|
183
|
+
`photonviz` is an [anywidget](https://anywidget.dev), which is why the same
|
|
184
|
+
object renders in Jupyter Notebook 7, JupyterLab 4, VS Code and Colab with no
|
|
185
|
+
per-frontend code.
|
|
186
|
+
|
|
187
|
+
Chart calls build a plain dict. On sync, every array-like is swapped for a
|
|
188
|
+
`{"$buffer": i}` marker and its raw bytes are appended to a buffer list;
|
|
189
|
+
ipywidgets ships those as binary. The browser rebuilds typed-array views over
|
|
190
|
+
them and hands them to `@photonviz/core`, which uploads straight to GPU buffers.
|
|
191
|
+
Colours, names, extents and other structural values stay JSON.
|
|
192
|
+
|
|
193
|
+
All plots on a page share **one** WebGL2 context, so a notebook with dozens of
|
|
194
|
+
charts will not exhaust the browser's context limit.
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Development
|
|
199
|
+
|
|
200
|
+
From a checkout of the [monorepo](https://github.com/coredumpdev/photon):
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
pnpm install
|
|
204
|
+
pnpm build:python # bundles the widget into src/photonviz/static/widget.js
|
|
205
|
+
cd python
|
|
206
|
+
pip install -e ".[dev]"
|
|
207
|
+
pytest
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## License
|
|
211
|
+
|
|
212
|
+
MIT
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/coredumpdev/photon/master/assets/banner.png" alt="Photon" width="100%" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
# photonviz
|
|
6
|
+
|
|
7
|
+
**GPU-accelerated (WebGL2) charts for Jupyter, JupyterLab and Google Colab.**
|
|
8
|
+
|
|
9
|
+
<p>
|
|
10
|
+
<a href="https://pypi.org/project/photonviz/"><img src="https://img.shields.io/pypi/v/photonviz?color=3775a9&logo=pypi&logoColor=white" alt="PyPI"/></a>
|
|
11
|
+
<a href="https://pypi.org/project/photonviz/"><img src="https://img.shields.io/pypi/dm/photonviz?color=3775a9" alt="downloads"/></a>
|
|
12
|
+
<a href="https://pypi.org/project/photonviz/"><img src="https://img.shields.io/pypi/pyversions/photonviz?color=3775a9" alt="Python versions"/></a>
|
|
13
|
+
<img src="https://img.shields.io/badge/WebGL2-required-8b5cf6" alt="WebGL2"/>
|
|
14
|
+
<img src="https://img.shields.io/badge/Jupyter%20%C2%B7%20Lab%20%C2%B7%20Colab-supported-f37626?logo=jupyter&logoColor=white" alt="Jupyter · Lab · Colab"/>
|
|
15
|
+
<a href="https://github.com/coredumpdev/photon/blob/master/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue" alt="MIT"/></a>
|
|
16
|
+
· <a href="https://coredumpdev.github.io/photon/docs/python/">📖 Docs</a>
|
|
17
|
+
· <a href="https://coredumpdev.github.io/photon/">▶ Live demo</a>
|
|
18
|
+
</p>
|
|
19
|
+
|
|
20
|
+
The Python bridge to [Photon](https://github.com/coredumpdev/photon). NumPy
|
|
21
|
+
arrays and torch tensors cross to the browser as **binary buffers**, so a million
|
|
22
|
+
points still pan and zoom at 60fps inside a notebook cell — no image round-trip,
|
|
23
|
+
no JSON blow-up.
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pip install photonviz
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Nothing else to install: the widget ships one self-contained ESM bundle, so there
|
|
30
|
+
is no CDN fetch, no `jupyter labextension install`, and no separate JS package.
|
|
31
|
+
|
|
32
|
+
<p align="center">
|
|
33
|
+
<img src="https://raw.githubusercontent.com/coredumpdev/photon/master/assets/jupyter-hero.png" alt="A 200,000-point line chart rendered by photonviz in JupyterLab" width="100%" />
|
|
34
|
+
</p>
|
|
35
|
+
|
|
36
|
+
<sub>Real capture from JupyterLab — 200k points, interactive: wheel to zoom, drag to pan, hover for a tooltip.</sub>
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Quick start
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
import numpy as np
|
|
44
|
+
import photonviz as pv
|
|
45
|
+
|
|
46
|
+
x = np.linspace(0, 10, 200_000)
|
|
47
|
+
pv.line(x, np.sin(x) + 0.3 * np.sin(x * 7), name="signal", plot={"theme": "dark", "legend": True})
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Charts chain, and the last expression in a cell renders itself:
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
(pv.Plot(theme="dark", title="Two series", legend=True)
|
|
54
|
+
.line(x, np.sin(x), name="sin", color="#60a5fa")
|
|
55
|
+
.line(x, np.cos(x), name="cos", color="#f472b6", dash=[6, 4])
|
|
56
|
+
.hline(0, color="#64748b"))
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Every keyword maps 1:1 onto the [TypeScript options](https://coredumpdev.github.io/photon/llms-full.txt),
|
|
60
|
+
so the JS reference applies verbatim — `color`, `width`, `step`, `colorBy`,
|
|
61
|
+
`yAxis`, `renderType`, and so on.
|
|
62
|
+
|
|
63
|
+
### Google Colab
|
|
64
|
+
|
|
65
|
+
Run once per session, then use `photonviz` normally:
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
from google.colab import output
|
|
69
|
+
output.enable_custom_widget_manager()
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## What you can draw
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
pv.scatter(x, y, sizes=area, colors=hex_list) # bubble chart
|
|
78
|
+
pv.histogram(samples, bins=40)
|
|
79
|
+
pv.heatmap(z, cols, rows, extent={"x": [0, 1], "y": [0, 1]}, colormap="magma")
|
|
80
|
+
pv.candlestick(t, o, h, l, c) # + heikin_ashi, bollinger, drawdown…
|
|
81
|
+
pv.regression(x, y, band=2) # OLS + confidence band (or method="loess")
|
|
82
|
+
pv.corr_matrix([a, b, c], names=["a", "b", "c"]) # diverging, locked to ±1
|
|
83
|
+
pv.psd(signal, sampleRate=1000) # Welch spectrum
|
|
84
|
+
pv.confusion_matrix(y_true, y_pred) # + roc_curve, pr_curve, calibration, embedding…
|
|
85
|
+
pv.surface(z, cols, rows) # 3D — orbit with the mouse
|
|
86
|
+
pv.polar_line(theta, r)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
`Plot`, `Plot3D` and `Polar` are the full objects; the module-level names are
|
|
90
|
+
one-line shortcuts. Pass `plot={...}` to a shortcut to configure the plot itself:
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
pv.scatter(x, y, size=4, plot={"theme": "dark", "pick": "xy", "colorbar": False})
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Model architecture
|
|
99
|
+
|
|
100
|
+
Hand a **PyTorch**, **Keras**, **scikit-learn** or **ONNX** model straight to
|
|
101
|
+
`model_graph` — the export happens in Python, the layout in the browser.
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
import torch, torchvision, photonviz as pv
|
|
105
|
+
|
|
106
|
+
model = torchvision.models.resnet18()
|
|
107
|
+
|
|
108
|
+
# 2D — a Netron-style DAG, with residual connections routed around the trunk.
|
|
109
|
+
pv.model_graph(model, example_input=torch.randn(1, 3, 224, 224), direction="horizontal")
|
|
110
|
+
|
|
111
|
+
# 3D — one cuboid per layer, sized from its output tensor: feature maps shrink
|
|
112
|
+
# while channel depth grows.
|
|
113
|
+
pv.model_graph_3d(
|
|
114
|
+
model,
|
|
115
|
+
example_input=torch.randn(1, 3, 224, 224),
|
|
116
|
+
labels="full",
|
|
117
|
+
plot={"aspectMode": "data", "projection": "orthographic", "showAxes": False},
|
|
118
|
+
)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
| Framework | How it is read | Notes |
|
|
122
|
+
| --- | --- | --- |
|
|
123
|
+
| PyTorch | `torch.fx` symbolic trace | Branches and skip connections survive. Pass `example_input=` to record shapes. Untraceable models fall back to a flat chain of leaf modules. |
|
|
124
|
+
| Keras / TF | `model.to_json()` + per-layer shapes | Sequential and functional, Keras 2 and 3. |
|
|
125
|
+
| scikit-learn | `Pipeline` / `ColumnTransformer` / `FeatureUnion` walk | Parallel branches fan out and back in. An `MLPClassifier` expands into its real dense stack. |
|
|
126
|
+
| ONNX | `MessageToDict` + shape inference | The framework-neutral path. |
|
|
127
|
+
|
|
128
|
+
<p align="center">
|
|
129
|
+
<img src="https://raw.githubusercontent.com/coredumpdev/photon/master/assets/jupyter-model3d.png" alt="A CNN drawn as tensor-shaped 3D blocks inside a notebook" width="100%" />
|
|
130
|
+
</p>
|
|
131
|
+
|
|
132
|
+
<sub>Each cuboid is one layer: the visible face is its feature map, the thickness its channel count. Drag to orbit.</sub>
|
|
133
|
+
|
|
134
|
+
The exporters are usable on their own — `pv.from_torch(model)`, `pv.from_keras`,
|
|
135
|
+
`pv.from_sklearn`, `pv.from_onnx` — and a hand-written
|
|
136
|
+
`{"nodes": [...], "edges": [...]}` graph works too.
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Example notebooks
|
|
141
|
+
|
|
142
|
+
Runnable, in the repo — [`examples/notebooks/`](https://github.com/coredumpdev/photon/tree/master/examples/notebooks):
|
|
143
|
+
|
|
144
|
+
| Notebook | What it covers |
|
|
145
|
+
| --- | --- |
|
|
146
|
+
| [`quickstart.ipynb`](https://github.com/coredumpdev/photon/blob/master/examples/notebooks/quickstart.ipynb) | The five-minute tour: a 200k-point line, a bubble chart with an OLS fit, a confusion matrix, a 3D model graph, a 3D surface. |
|
|
147
|
+
| [`gallery.ipynb`](https://github.com/coredumpdev/photon/blob/master/examples/notebooks/gallery.ipynb) | The full spread — distributions, fields, custom colours, finance, signal processing, ML metrics, model architecture, and 3D. |
|
|
148
|
+
|
|
149
|
+
<p align="center">
|
|
150
|
+
<img src="https://raw.githubusercontent.com/coredumpdev/photon/master/assets/jupyter-bubble.png" alt="Bubble chart with a least-squares fit and confidence band" width="49%" />
|
|
151
|
+
<img src="https://raw.githubusercontent.com/coredumpdev/photon/master/assets/jupyter-surface.png" alt="A lit 3D surface rendered in a notebook cell" width="49%" />
|
|
152
|
+
</p>
|
|
153
|
+
|
|
154
|
+
## How it works
|
|
155
|
+
|
|
156
|
+
`photonviz` is an [anywidget](https://anywidget.dev), which is why the same
|
|
157
|
+
object renders in Jupyter Notebook 7, JupyterLab 4, VS Code and Colab with no
|
|
158
|
+
per-frontend code.
|
|
159
|
+
|
|
160
|
+
Chart calls build a plain dict. On sync, every array-like is swapped for a
|
|
161
|
+
`{"$buffer": i}` marker and its raw bytes are appended to a buffer list;
|
|
162
|
+
ipywidgets ships those as binary. The browser rebuilds typed-array views over
|
|
163
|
+
them and hands them to `@photonviz/core`, which uploads straight to GPU buffers.
|
|
164
|
+
Colours, names, extents and other structural values stay JSON.
|
|
165
|
+
|
|
166
|
+
All plots on a page share **one** WebGL2 context, so a notebook with dozens of
|
|
167
|
+
charts will not exhaust the browser's context limit.
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Development
|
|
172
|
+
|
|
173
|
+
From a checkout of the [monorepo](https://github.com/coredumpdev/photon):
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
pnpm install
|
|
177
|
+
pnpm build:python # bundles the widget into src/photonviz/static/widget.js
|
|
178
|
+
cd python
|
|
179
|
+
pip install -e ".[dev]"
|
|
180
|
+
pytest
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## License
|
|
184
|
+
|
|
185
|
+
MIT
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "photonviz"
|
|
7
|
+
version = "0.5.0"
|
|
8
|
+
description = "GPU-accelerated (WebGL2) charts for Jupyter, JupyterLab and Google Colab"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "Muzaffer Tolga Yakar", email = "muzaffertolgayakar@gmail.com" }]
|
|
13
|
+
keywords = ["plotting", "charts", "webgl", "jupyter", "notebook", "colab", "visualization", "pytorch"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Framework :: Jupyter",
|
|
17
|
+
"Framework :: Jupyter :: JupyterLab :: 4",
|
|
18
|
+
"Intended Audience :: Science/Research",
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Topic :: Scientific/Engineering :: Visualization",
|
|
22
|
+
]
|
|
23
|
+
dependencies = [
|
|
24
|
+
"anywidget>=0.9.0",
|
|
25
|
+
"numpy>=1.21",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
[project.optional-dependencies]
|
|
29
|
+
dev = ["pytest>=7", "watchfiles", "jupyterlab>=4"]
|
|
30
|
+
|
|
31
|
+
[project.urls]
|
|
32
|
+
Homepage = "https://github.com/coredumpdev/photon"
|
|
33
|
+
Documentation = "https://coredumpdev.github.io/photon/"
|
|
34
|
+
Source = "https://github.com/coredumpdev/photon/tree/master/python"
|
|
35
|
+
Issues = "https://github.com/coredumpdev/photon/issues"
|
|
36
|
+
|
|
37
|
+
[tool.hatch.build.targets.wheel]
|
|
38
|
+
packages = ["src/photonviz"]
|
|
39
|
+
|
|
40
|
+
[tool.hatch.build.targets.sdist]
|
|
41
|
+
include = ["src/photonviz", "README.md", "pyproject.toml"]
|
|
42
|
+
|
|
43
|
+
# The bundled widget JS is generated by `pnpm build:python` — it must ship in the
|
|
44
|
+
# wheel, and its absence should fail the build rather than produce a dud package.
|
|
45
|
+
[tool.hatch.build.targets.wheel.force-include]
|
|
46
|
+
"src/photonviz/static/widget.js" = "photonviz/static/widget.js"
|
|
47
|
+
|
|
48
|
+
[tool.pytest.ini_options]
|
|
49
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"""
|
|
2
|
+
photonviz — GPU-accelerated (WebGL2) charts for Jupyter, JupyterLab and Colab.
|
|
3
|
+
|
|
4
|
+
A thin Python bridge over `@photonviz/core <https://github.com/coredumpdev/photon>`_.
|
|
5
|
+
NumPy arrays and torch tensors cross to the browser as binary buffers, so a
|
|
6
|
+
million points still render at 60fps inside a notebook cell.
|
|
7
|
+
|
|
8
|
+
import numpy as np, photonviz as pv
|
|
9
|
+
|
|
10
|
+
x = np.linspace(0, 10, 100_000)
|
|
11
|
+
pv.line(x, np.sin(x), name="sin", plot={"theme": "dark", "legend": True})
|
|
12
|
+
|
|
13
|
+
Charts chain, and the last expression in a cell renders itself::
|
|
14
|
+
|
|
15
|
+
pv.Plot(theme="dark", title="Two series").line(x, y1, name="a").line(x, y2, name="b")
|
|
16
|
+
|
|
17
|
+
Model architectures come straight from the framework object::
|
|
18
|
+
|
|
19
|
+
pv.model_graph(torch_model, example_input=torch.randn(1, 3, 224, 224))
|
|
20
|
+
pv.model_graph_3d(keras_model)
|
|
21
|
+
|
|
22
|
+
In Google Colab, enable the widget manager once per session::
|
|
23
|
+
|
|
24
|
+
from google.colab import output; output.enable_custom_widget_manager()
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
from __future__ import annotations
|
|
28
|
+
|
|
29
|
+
from typing import Any
|
|
30
|
+
|
|
31
|
+
from ._widget import ChartWidget
|
|
32
|
+
from .charts import Plot, Plot3D, Polar, _shortcut
|
|
33
|
+
from .models import from_keras, from_layers, from_onnx, from_sklearn, from_torch, to_source
|
|
34
|
+
|
|
35
|
+
__version__ = "0.5.0"
|
|
36
|
+
|
|
37
|
+
# -- One-liners: pv.line(x, y) == pv.Plot().line(x, y) ------------------------
|
|
38
|
+
line = _shortcut(Plot, "line")
|
|
39
|
+
scatter = _shortcut(Plot, "scatter")
|
|
40
|
+
bar = _shortcut(Plot, "bar")
|
|
41
|
+
area = _shortcut(Plot, "area")
|
|
42
|
+
step = _shortcut(Plot, "step")
|
|
43
|
+
histogram = _shortcut(Plot, "histogram")
|
|
44
|
+
box = _shortcut(Plot, "box")
|
|
45
|
+
heatmap = _shortcut(Plot, "heatmap")
|
|
46
|
+
contour = _shortcut(Plot, "contour")
|
|
47
|
+
hexbin = _shortcut(Plot, "hexbin")
|
|
48
|
+
errorbar = _shortcut(Plot, "errorbar")
|
|
49
|
+
stem = _shortcut(Plot, "stem")
|
|
50
|
+
quiver = _shortcut(Plot, "quiver")
|
|
51
|
+
pie = _shortcut(Plot, "pie")
|
|
52
|
+
|
|
53
|
+
candlestick = _shortcut(Plot, "candlestick")
|
|
54
|
+
ohlc = _shortcut(Plot, "ohlc")
|
|
55
|
+
heikin_ashi = _shortcut(Plot, "heikin_ashi")
|
|
56
|
+
bollinger = _shortcut(Plot, "bollinger")
|
|
57
|
+
volume_profile = _shortcut(Plot, "volume_profile")
|
|
58
|
+
drawdown = _shortcut(Plot, "drawdown")
|
|
59
|
+
|
|
60
|
+
regression = _shortcut(Plot, "regression")
|
|
61
|
+
ecdf = _shortcut(Plot, "ecdf")
|
|
62
|
+
corr_matrix = _shortcut(Plot, "corr_matrix")
|
|
63
|
+
psd = _shortcut(Plot, "psd")
|
|
64
|
+
|
|
65
|
+
confusion_matrix = _shortcut(Plot, "confusion_matrix")
|
|
66
|
+
roc_curve = _shortcut(Plot, "roc_curve")
|
|
67
|
+
pr_curve = _shortcut(Plot, "pr_curve")
|
|
68
|
+
calibration = _shortcut(Plot, "calibration")
|
|
69
|
+
embedding = _shortcut(Plot, "embedding")
|
|
70
|
+
feature_importance = _shortcut(Plot, "feature_importance")
|
|
71
|
+
training_curves = _shortcut(Plot, "training_curves")
|
|
72
|
+
model_graph = _shortcut(Plot, "model_graph")
|
|
73
|
+
|
|
74
|
+
surface = _shortcut(Plot3D, "surface")
|
|
75
|
+
scatter3d = _shortcut(Plot3D, "scatter3d")
|
|
76
|
+
line3d = _shortcut(Plot3D, "line3d")
|
|
77
|
+
bar3d = _shortcut(Plot3D, "bar3d")
|
|
78
|
+
isosurface = _shortcut(Plot3D, "isosurface")
|
|
79
|
+
volume = _shortcut(Plot3D, "volume")
|
|
80
|
+
model_graph_3d = _shortcut(Plot3D, "model_graph")
|
|
81
|
+
|
|
82
|
+
polar_line = _shortcut(Polar, "line")
|
|
83
|
+
polar_scatter = _shortcut(Polar, "scatter")
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def show(chart: Any) -> Any:
|
|
87
|
+
"""Explicitly display a chart (notebooks render the last expression anyway)."""
|
|
88
|
+
from IPython.display import display # noqa: PLC0415 - optional at import time
|
|
89
|
+
|
|
90
|
+
display(chart)
|
|
91
|
+
return chart
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
__all__ = [
|
|
95
|
+
"Plot",
|
|
96
|
+
"Plot3D",
|
|
97
|
+
"Polar",
|
|
98
|
+
"ChartWidget",
|
|
99
|
+
"show",
|
|
100
|
+
"__version__",
|
|
101
|
+
# model export
|
|
102
|
+
"model_graph",
|
|
103
|
+
"model_graph_3d",
|
|
104
|
+
"to_source",
|
|
105
|
+
"from_torch",
|
|
106
|
+
"from_keras",
|
|
107
|
+
"from_sklearn",
|
|
108
|
+
"from_onnx",
|
|
109
|
+
"from_layers",
|
|
110
|
+
# 2D one-liners
|
|
111
|
+
"line", "scatter", "bar", "area", "step", "histogram", "box", "heatmap",
|
|
112
|
+
"contour", "hexbin", "errorbar", "stem", "quiver", "pie",
|
|
113
|
+
# finance
|
|
114
|
+
"candlestick", "ohlc", "heikin_ashi", "bollinger", "volume_profile", "drawdown",
|
|
115
|
+
# statistics
|
|
116
|
+
"regression", "ecdf", "corr_matrix", "psd",
|
|
117
|
+
# machine learning
|
|
118
|
+
"confusion_matrix", "roc_curve", "pr_curve", "calibration", "embedding",
|
|
119
|
+
"feature_importance", "training_curves",
|
|
120
|
+
# 3D + polar
|
|
121
|
+
"surface", "scatter3d", "line3d", "bar3d", "isosurface", "volume",
|
|
122
|
+
"polar_line", "polar_scatter",
|
|
123
|
+
]
|