Skip to content

Releases: coredumpdev/photon

v0.7.2

Choose a tag to compare

@coredumpdev coredumpdev released this 27 Jul 10:01

Waterfall

addWaterfall(plot, opts) — a spectrogram that streams. Each pushed column becomes the newest row at the top and the history slides one row down, while the y axis reads as elapsed time.

const wf = addWaterfall(plot, {
  extent: [0, 160_000],      // the band one row spans
  cols: 512, rows: 400,      // cells across × rows of history
  rowSeconds: 0.08,          // seconds per row → 32s on screen
  domain: [-68, -6],         // fix it, or the colours breathe every push
  colormap: "plasma", name: "power (dB)",
  timeFormat: "hh:mm:ss",    // or "mm:ss.mmm", or (s) => your own label
  timeTitle: "time",
});

wf.push(psdInDb);                          // one column per step
wf.setTimeAxis({ format: "mm:ss.mmm" });   // relabel live

Two things a hand-rolled version keeps getting wrong are handled inside: ticks are handed over as a fresh array on every push (an axis caches its resolved ticks while the domain and config hold still, and a waterfall's domain never moves — so a generator gets called once and the labels sit there while the image scrolls under them), and the clock starts one row negative so the first push lands on startTime exactly instead of leaving the top edge of the empty history a row above its own tick.

A column longer than cols is reduced by block maximum, so a peak two bins wide survives fitting a 200k-bin spectrum into a few hundred cells. history opens on a pre-computed grid instead of an empty one. Clock labels are wider than plain numbers and the left margin is not measured from them — pass margin: { left: 72 }.

Pure and unit tested: waterfallTimeTicks, formatDuration, niceTimeStep, blockMax.

Wrappers: a Waterfall component (react/vue/solid) and a waterfall series (svelte/gea/wc). Live streaming still goes through the handle on a core Plot, as with every other streaming layer.

Gallery

examples/vanilla gains a Signal tab — a 409.6 kHz receiver as a 204 800-point live spectrum over the waterfall, both full width on a shared frequency axis, with start/stop frequency boxes and a time-label picker. Its streaming updaters are now grouped per tab, so switching away from Dynamic no longer leaves those 50 panels running behind it.

v0.7.1

Choose a tag to compare

@coredumpdev coredumpdev released this 26 Jul 23:13

A bug-fix release. Every item here was a chart that drew nothing at all, with no error — the failure mode that is hardest to notice and hardest to report.

Python bridge

  • attention_map works with a 2-D matrix again. A numpy array was ravelled into one buffer so its shape never reached the browser, and a list of lists arrived as an Array of Float64Array, which the shape inference (Array.isArray(weights[0])) rejected. Both forms now render identically to the flat form.
  • annotate("band", …) is reachable from Python. from is a Python keyword, so the field is spelled from_ and translated on the way out — previously there was no way to pass it.
  • Wrong field names raise instead of drawing nothing. A 3D box is sized with w/h/d (not width/height/depth); a line/ray annotation runs x0,y0 → x1,y1 (not x1,y1 → x2,y2); fib takes x0,x1,high,low. Each now reports which fields the type takes, and the Python docstrings list them.

Core

  • A polar series added after the first frame is drawn. PolarPlot.addLine/addScatter refit but never scheduled a render, so the series stayed invisible until something resized the container.
  • toDataURL() on a hidden or detached container returns the chart, not a 1×1 blank PNG.
  • A chart that scrolls back into view is current, not stale. With offscreenCulling on, a redraw is now unconditional on re-entry: an app that also skips its own data generation never called render() while away, so the catch-up never triggered.

Examples

  • The svelte gallery's two linked-finance panels build from a use: action rather than onMount — Rollup was deleting the whole onMount(...) call from the production bundle, leaving both panels empty with no error.

Housekeeping

  • plot.ts no longer contains literal NUL bytes, which made file(1) classify it as binary and grep silently report no matches on the largest source file in the repo.

v0.7.0

Choose a tag to compare

@coredumpdev coredumpdev released this 26 Jul 17:09

Closes the two gaps left open at 0.6.0.

Triangulations — matplotlib's tri* family

For samples that are scattered rather than gridded.

Photon matplotlib
addTriplot / pv.triplot triplot
addTripcolor / pv.tripcolor tripcolor
addTricontour / pv.tricontour tricontour
addTricontourf / pv.tricontourf tricontourf
pv.tripcolor(x, y, z, edges=True)       # flat-shaded triangles + the mesh
pv.tricontourf(x, y, z, levels=12)      # filled bands over the triangulation

Backing them is a new delaunay(x, y): incremental insertion with Lawson edge flipping over a half-edge mesh. Points go in along a spatial order and each one is located by walking from the last triangle touched, so location stays near O(1) amortised instead of the O(n) scan a naive Bowyer–Watson does — 4000 points triangulate in tens of milliseconds. Zero-area slivers and exact duplicates are dropped rather than emitted, since a degenerate triangle divides by zero in every interpolation downstream.

Pass your own triangles when the connectivity is part of the data — a finite-element result, say — and no triangulation runs.

Binding parity — 32 builders, all six wrappers

The statistics pack (Regression, Ecdf, CorrMatrix, Psd), the ML pack (16, from ConfusionMatrix to LearningCurve), the diagram pack (Treemap through ParallelCoordinates), Drawdown, and the new tri* four existed in core but in no wrapper. All are now:

  • components in React, Vue and Solid
  • type: entries in the Svelte, Gea and Web Component series specs
  • methods and one-liners in Python

Core exports collectLayers(handle) to make that safe: it finds the layers in whatever shape a builder returns — a bare layer, { upper, middle, lower }, { lines: Layer[], arrows? } — mixed in with computed data like auc or layout. Naming each handle's fields by hand across 96 call sites is how one gets forgotten.

Fixes

Six Python methods were written against guessed option names and rendered an error box rather than a chart. The browser pass caught all six; there is now a test pinning the key names the layers actually read (yTrue/yPred, pd, weights).

Verification

68 gallery panels and 32 Python chart types all draw with non-zero ink under headless Chromium. 217 TS tests — 13 new for the triangulator, including that no vertex falls inside any circumcircle and that the triangle count matches Euler's formula — and 43 Python tests.

Install

npm i @photonviz/core     # or @photonviz/react, vue, svelte, solid, gea, wc
pip install photonviz

Full changelog: v0.6.0...v0.7.0

v0.6.0

Choose a tag to compare

@coredumpdev coredumpdev released this 26 Jul 16:49

matplotlib ergonomics for the Python API

figsize is matplotlib's (width, height) in inches at dpi (100 by default), and works on any chart — not just a figure.

fig, axes = pv.subplots(2, 2, figsize=(12, 7), sharex=True, theme="dark")
axes[0, 0].line(t, loss).title("Loss")
axes[0, 1].roc_curve(scores, labels)
axes[1, 0].confusion_matrix(y_true, y_pred)
axes[1, 1].histogram(residuals)
fig

subplots returns (figure, axes) with matplotlib's squeeze rules, so axes[i, j], axes[i] and axes.flat all behave. sharex / sharey link the panels' views. For layouts that aren't a uniform grid, pv.figure() + add_subplot(row, col, rowspan, colspan, kind) covers spans and mixed 2D / polar / 3D panels.

The grid is one widget, not one per panel: the drawing API moved onto plain Axes / Axes3D / PolarAxes spec objects, so a 2×2 figure ships a single copy of the ~280 KB bundled engine instead of four.

New chart types — matplotlib's field and raster gallery

Photon matplotlib
addContourFilled / pv.contourf contourf
addPcolormesh / pv.pcolormesh pcolormesh
addStreamplot / pv.streamplot streamplot
addBarbs / pv.barbs barbs
addHist2d / pv.hist2d hist2d
addEventPlot / pv.eventplot eventplot

Filled bands are real polygons, not a quantised image: every cell is split into four triangles around its centre before clipping, which removes the saddle ambiguity plain marching squares has. Streamlines are RK4-traced with matplotlib's occupancy trick, so they stay evenly spaced instead of bunching on attractors. The pure halves — isobands, streamlines, hist2d — are exported too.

PlotGrid for JavaScript

const grid = new PlotGrid(el, { rows: 2, cols: 2, gap: 14, title: "Sensors", linkX: true });
grid.addPlot().addLine({ x, y: a });
grid.addPlot({ colSpan: 2 }).addLine({ x, y: total });
grid.addPolar({ row: 1, col: 1 }).addLine({ theta, r });

Cells all draw through the one shared WebGL context, so a 4×4 figure costs no more GPU contexts than a single chart. linkY joins linkX as the y-view counterpart.

Fixes

  • pv.box drew nothing. It documented groups as {"x": …, "values": …} but the layer reads position, so every vertex was NaN — the gallery notebook's "Violin + Tukey box" cell rendered empty axes. Python accepts either key now, and BoxLayer throws on a non-finite position instead of drawing nothing.
  • addRenko without brickSize produced zero bricks; it throws now.
  • Series-spec wrappers leaked layers. addSeries returned a single layer, so a multi-layer builder left the rest behind on rebuild (a model graph leaked its connectors). It returns Layer[] now.
  • addContourFilled returns { bands, lines? } so its optional stroke layer is removable.

Python API gaps closed

Nine chart types reachable from JS had no Python method: grouped_bars, stacked_bars, stacked_area, patches, graph, renko, depth, shap_beeswarm, and contour3d. training_curves also accepts "values" alongside the layer's "y".

Wrappers

<ContourFilled>, <Pcolormesh>, <Hist2d>, <EventPlot>, <Streamplot> and <Barbs> in React / Vue / Solid; matching type: entries in the Svelte / Gea / Web Component series specs. PlotGrid and linkY re-exported from all six.

Install

npm i @photonviz/core     # or @photonviz/react, vue, svelte, solid, gea, wc
pip install photonviz

Full changelog: v0.5.0...v0.6.0

v0.5.0

Choose a tag to compare

@coredumpdev coredumpdev released this 25 Jul 19:53

GPU charts that can now draw the model that produced the data — plus a Python
bridge, readable colour, and a documentation site.

Model architecture graphs

Draw a real model's layers, straight from PyTorch, Keras, scikit-learn or ONNX.

  • addModelGraph(plot, { graph }) — a flat Netron-style DAG. Boxes are coloured
    by layer family, and a residual edge that skips ranks routes around the
    trunk instead of cutting through it.
  • addModelGraph3D(plot3d, { graph }) — one cuboid per layer, sized from its
    output tensor: the visible face is H×W, the thickness is the channel count, so
    a CNN reads as feature maps shrinking while depth grows.

Six pure adapters (modelGraphFromTorchFx, modelGraphFromKeras,
modelGraphFromSklearn, modelGraphFromOnnx, sequentialModel, mlpModel)
feed one shared layout — modelLayout is exported if you would rather draw it
yourself.

New: Boxes3DLayer (instanced lit cuboids), and on Plot3DaspectMode: "data", projection: "orthographic", showAxes, and addLabel3D for outlined
text pinned in data space.

Python — pip install photonviz

An anywidget bridge for Jupyter Notebook, JupyterLab,
VS Code and Google Colab
. NumPy arrays and torch tensors cross to the browser
as binary buffers, so a million points stay interactive in a cell.

```python
import numpy as np, photonviz as pv

pv.line(x, np.sin(x), name="signal", plot={"theme": "dark", "legend": True})
pv.model_graph_3d(torch_model, example_input=torch.randn(1, 3, 224, 224))
```

Two runnable notebooks under `examples/notebooks/`.

Colorbars, and colour worth trusting

  • Colorbars are on by default. Any layer that maps values to colours —
    heatmap, hexbin, contour, choropleth patches, `colorBy` scatter/quiver —
    reports a scale, and the plot draws a bar for it.
  • 4 colormaps become 12 across sequential / diverging / cyclic, plus 4
    categorical palettes
    (including the colour-vision-safe `okabe-ito`).
  • Bring your own: `registerColormap` / `registerPalette`, or pass inline
    colours anywhere a name is accepted.
  • `symmetricDomain` centres a diverging scale so its neutral colour lands on
    zero instead of drifting with the data.

Marks and interaction

  • Bubble charts — per-point `sizes` and `colors` on scatter.
  • Dashed lines — `dash: [6, 4]` for guides and forecasts.
  • Interactive legend — click an entry to hide a series; the auto axes re-fit
    to what is left. Keyboard-accessible, with `onVisibilityChange`.

Finance, ML, signal and statistics

  • Finance: `cci`, `mfi`, `williamsR`, `aroon`, `donchian`, `parabolicSar`,
    `pivotPoints`, `resampleOhlc`, `drawdown` + `addDrawdown`.
  • ML: `r2`, `rmse`, `mae`, `logLoss`, `brierScore`, `classificationReport`,
    `liftCurve`, `rocCurveOvR` + `addPredVsActual`, `addResiduals`,
    `addLiftCurve`, `addLearningCurve`.
  • Signal + statistics (new modules): window functions, Welch PSD,
    Savitzky-Golay, cross-correlation, OLS/LOESS fits, ECDF, z-score,
    correlation matrix + `addRegression`, `addEcdf`, `addCorrMatrix`, `addPsd`.

Documentation

A full site at https://coredumpdev.github.io/photon/docs/ — guides, the
chart catalog with live demos, and a TypeDoc API reference. Every demo is a
real module loaded twice, imported to run and read raw to display, so the code
on the page is what produced the chart above it.

Also

All six framework wrappers expose the new charts, dash and sizes/colors.
190 TypeScript tests and 22 Python tests.

v0.4.1

Choose a tag to compare

@coredumpdev coredumpdev released this 24 Jul 10:58

Docs: add a Docs for AI agents link (→ llms-full.txt) to every package README so it shows on the npm package pages, alongside the live-demo link. No code changes.

v0.4.0

Choose a tag to compare

@coredumpdev coredumpdev released this 24 Jul 10:54

✨ ML / deep-learning chart pack (@photonviz/core)

Classification metrics (confusion matrix, ROC + AUC, precision–recall + AP,
calibration + ECE), a PCA reducer + embedding projector, explainability
(feature importance, SHAP beeswarm, partial dependence, attention maps), and
training-monitoring charts (EMA-smoothed training curves, ridgeline). All
composed addX(plot, opts) builders; the pure metrics are unit-tested and the
whole pack is re-exported from every framework wrapper. New examples/ml app +
an ML tab in every gallery + playground presets.

⚠️ Breaking — maps decoupled, @photonviz/map removed

The @photonviz/map package has been removed. The framework wrappers no longer
depend on it and no longer ship <Map> / <GeoJson> components or map /
geojson series. If you need a basemap, add it imperatively on the core
Plot
(addMap / addGeoJson) via onReady / usePlot / the Web
Components .plot getter.

🩹 Fixes

  • Legend now shows only explicitly named series — auto-id helper layers
    (fills, ICE curves, raw pre-smoothing lines) no longer clutter it.

📚 Docs & discoverability

  • Live demo + playground: https://coredumpdev.github.io/photon/
  • llms.txt / llms-full.txt + AGENTS.md — docs for AI coding agents.
  • npm / downloads / size badges, CODE_OF_CONDUCT, SECURITY, FUNDING.

v0.3.2

Choose a tag to compare

@coredumpdev coredumpdev released this 23 Jul 17:21

Since v0.3.1:

✨ Features

  • Image export — every plot (Plot/Plot3D/PolarPlot) has toDataURL() / toBlob() / downloadImage() / copyToClipboard(), plus a one-click download-PNG button on the toolbar (and next to reset-view on 3D).
  • Interactive drawing toolsnew Plot(el, { drawingTools: true }) adds trendline / horizontal / ray / Fibonacci / rectangle tools. Drawings are editable: drag endpoint handles to reshape, drag the body to move, double-click to label, right-click for a context menu (rename / recolor / delete), Delete to remove.
  • 7 diagram chart typesaddTreemap · addFunnel · addSunburst · addGauge · addSankey · addChord · addParallelCoordinates (pure *Layout fns exported too).
  • 7 more finance indicators — Stochastic, Keltner, OBV, Ichimoku, ADX, SuperTrend, Fibonacci retracements.
  • @photonviz/wc — new framework-agnostic Web Components package: <photon-plot> / <photon-plot3d> / <photon-polar>.
  • Data adaptersparseCSV(text) → a typed Table, and lttb(x, y, threshold) downsampling for long line series.
  • Accessibility — plots render as role="img" with an auto-summarized aria-label (ariaLabel / setAriaLabel() / describe()).
  • Examples — per-chart fullscreen button; a new interactive playground (CodeMirror editor) and a Web Components gallery.

🐛 Fixes

  • Ordinal-time axis gridlines now snap to real calendar dates (month/week/day) and no longer drift when panning.
  • Hover x-readout uses the axis scale's formatter (dates on time/ordinal-time instead of a raw index).

All 8 packages published to npm at 0.3.2.

v0.3.0

Choose a tag to compare

@coredumpdev coredumpdev released this 22 Jul 22:57

GPU-accelerated scientific plotting — a big feature release: a full styling/config system, a much larger 2D + 3D chart catalog, two new framework wrappers, and performance work. All 7 packages published to npm with provenance.

Highlights

Styling & config

  • background/border fills, plot title, DOM legend
  • Per-axis line/tick/label/grid color, font & label rotation
  • Categorical (factor) scale

New 2D charts

  • Scatter marker glyphs (circle/square/triangle/diamond/cross/plus)
  • Grouped / stacked / horizontal bars, stacked area
  • Pie / donut, patches/polygons (earcut, choropleth), graph/network (force layout)
  • Image (RGBA/URL), annotations (span/band/box/label)

Full 3D suite (Plot3D)

  • New layers: line3d, bar3d, quiver3d, contour3d, isosurface (marching cubes), volume (GPU raymarch) + surface wireframe
  • 3D chrome: legend, colorbar, title, hover tooltip + highlight ring, back-wall grid planes, reset-view, auto-rotate; per-point size/label + streaming setData

Wrappers — now five frameworks

  • Added @photonviz/solid and @photonviz/gea; every chart wrapped across React, Vue, Svelte, Solid & Gea

Performance

  • LUT-backed colormaps (~14× faster hot path) + a pnpm bench benchmark suite

Housekeeping

  • LICENSE + author/bugs in every package; new unit tests (earcut, marching cubes, force layout, categorical scale) — 98 total

Packages (all @0.3.0)

@photonviz/core · map · react · vue · svelte · solid · gea

v0.2.1

Choose a tag to compare

@coredumpdev coredumpdev released this 22 Jul 13:12

Per-package READMEs for npm, each with the Photon banner + gallery images (and the vector-map image for @photonviz/map). No API changes since v0.2.0.