Reference#
Glossary#
Python terms#
traitlets — The library that defines typed attributes on Python objects.
Every widget property that syncs to JavaScript is a traitlet.
pos_row = traitlets.Int(0).tag(sync=True)
Common types: Int, Float, Bool, Unicode (string), Bytes (binary),
List, Dict.
.tag(sync=True) — Marks a traitlet for synchronization with JavaScript.
Without this tag, the trait exists only in Python.
.observe(callback, names=[...]) — Registers a function that runs whenever
the named traits change:
self.observe(self._update_frame, names=["pos_row", "pos_col"])
anywidget.AnyWidget — The base class every widget extends. Handles trait
synchronization, binary transport, and widget lifecycle.
@property — Turns a method into a read-only attribute. Used for computed
values like widget.profile_values.
Self return type — Type hint for method chaining (from typing import Self).
.tobytes() — Converts a NumPy array to raw bytes for sending to JS:
self.frame_bytes = frame.astype(np.float32).tobytes()
hasattr (duck typing) — Auto-detect quantem Dataset objects without
importing quantem:
if hasattr(data, "array"):
title = getattr(data, "name", "")
JavaScript / TypeScript terms#
JSX — HTML-like syntax inside JavaScript. <Box sx={{ color: "red" }}>Hello</Box>
compiles to React.createElement(...).
Hooks — Functions that manage state and side effects:
useState(initial)— state variable, triggers re-render on changeuseEffect(() => { ... }, [deps])— runs code when dependencies change (canvas rendering, data processing)useRef(initial)— persistent reference that survives re-renders (canvas elements, drag state)useMemo(() => value, [deps])— cached computed valueuseCallback(() => fn, [deps])— cached function reference
useModelState — The anywidget hook bridging React to Python traitlets:
const [cmap, setCmap] = useModelState<string>("cmap");
The string must exactly match the Python trait name. A typo silently returns
undefined.
DataView → Float32Array — Bytes traitlets arrive as DataView.
Convert with extractFloat32() from format.ts.
Canvas API — getContext("2d"), clearRect, drawImage, save/restore.
Widgets render to offscreen canvas first, then drawImage() with zoom/pan
transforms.
DPR — window.devicePixelRatio. UI canvas uses width={cssW * DPR},
style={{ width: cssW }}, ctx.scale(DPR, DPR) for crisp text on HiDPI.
ref / .current — Persistent DOM references via useRef(). Don’t trigger
re-renders.
MUI (Material UI)#
Box— styled<div>withsxpropStack— flexbox layout (direction="row"for horizontal)Typography— text with consistent stylingsx— inline CSS as JS object (fontSize: 10,mb: "4px",bgcolor: "#fff")Switch— toggle (FFT, log scale);Select— dropdown (colormap);Button— action;Slider— range
Build tools#
esbuild — JS bundler. npm run build (one-shot, ~130ms) or npm run dev (watch mode).
anywidget HMR — Hot Module Replacement. With npm run dev + ANYWIDGET_HMR=1,
JS changes appear without kernel restart.
Troubleshooting#
Trait exists in Python but JS reads undefined — You forgot .tag(sync=True).
Python changes don’t take effect — Restart the kernel. Python code is loaded at import time.
Trait isn’t syncing — Check spelling. useModelState("pos_row") must exactly
match the Python trait name.
Theme colors — Use colors from useTheme() for all UI chrome:
const { colors } = useTheme();
<Box sx={{ bgcolor: colors.bg, color: colors.text, border: `1px solid ${colors.border}` }}>
Available: bg, bgAlt, text, textMuted, border, controlBg, accent.
Colormaps — Applied entirely in JS. Python sends raw float32, JS maps via LUT:
import { COLORMAPS, applyColormap } from "../colormaps";
applyColormap(floatData, rgbaBuffer, COLORMAPS["inferno"], vmin, vmax);
Testing#
Unit tests#
python -m pytest tests/ -v --ignore=tests/test_e2e_smoke.py # all
python -m pytest tests/test_widget_show4dstem.py -v # one widget
End-to-end smoke tests#
Requires Playwright + JupyterLab. Renders widgets in a real browser, captures screenshots (light + dark theme), tests interactions. ~4 minutes:
python -m pytest tests/test_e2e_smoke.py -v # all
python -m pytest tests/test_e2e_smoke.py -v -k show2d # one widget
Screenshot verification#
After modifying widget UI: npm run build → run smoke tests → visually verify
tests/screenshots/smoke/.
File |
Purpose |
|---|---|
|
Unit tests (traits, shapes, data, state, ROI, display) |
|
Screenshot capture scripts (run manually) |
|
Full E2E via Playwright |
Publishing#
Docs#
pip install -e ".[docs]"
# One-shot build
sphinx-build docs docs/_build/html
# Live reload (rebuilds on file change, opens browser)
sphinx-autobuild docs docs/_build/html --open-browser --port 8322
TestPyPI#
Currently published on TestPyPI (not yet on PyPI).
Bump version in
pyproject.tomlTag and push:
git tag vX.Y.Z && git push origin main && git push origin vX.Y.ZCI builds and uploads to TestPyPI. Verify:
./scripts/verify_testpypi.sh X.Y.Z
Install from TestPyPI:
pip install -i https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ quantem-widget