/ concept-collection / jupyterlite-numbl-kernel
Sign in
concept-collection / jupyterlite-numbl-kernel
jupyterlite-numbl-kernel / README.md
154 lines · 6.8 KBCodeBlameHistory
41c072cjupyterlite-numbl-kernel: MATLAB-syntax kernel for JupyterLiteJeremy Magland 1# jupyterlite-numbl-kernel
77bc6b7Soften rebrand: keep MATLAB syntax visible alongside numblJeremy Magland 3Run [**numbl**](https://github.com/flatironinstitute/numbl) — numerical
4computing with **MATLAB syntax** — in
5[JupyterLite](https://jupyterlite.readthedocs.io/) notebooks, **entirely in
f44f6a3Rebrand numbl-first: this runs numbl (which uses MATLAB syntax)Jeremy Magland 6the browser**, with no server, no kernel process, and nothing for the reader
7to install.
f44f6a3Rebrand numbl-first: this runs numbl (which uses MATLAB syntax)Jeremy Magland 9numbl is an open-source numerical-computing engine, written in TypeScript,
10that uses MATLAB syntax — so `.m` code runs unchanged. This kernel runs a
41c072cjupyterlite-numbl-kernel: MATLAB-syntax kernel for JupyterLiteJeremy Magland 11numbl session in a Web Worker in the page: variables persist across cells,
f44f6a3Rebrand numbl-first: this runs numbl (which uses MATLAB syntax)Jeremy Magland 12console output streams into the running cell, plots render as figures in cell
13outputs (including interactive 3-D), the `mip` package manager can install
14numbl packages from GitHub, and `.m` files next to the notebook are part of
15the workspace (named functions, called from cells) — all client-side.
17**Demo site:**
18<https://concept-collection.github.io/jupyterlite-numbl-kernel/> (deployed
19from this repo via GitHub Pages — see `.github/workflows/deploy.yml`)
21## Why
f44f6a3Rebrand numbl-first: this runs numbl (which uses MATLAB syntax)Jeremy Magland 23This kernel is a proof of concept that a numbl notebook can be a static web
24page: hostable on GitHub Pages, shareable as a link, and executable by anyone
25with a browser. Because numbl uses MATLAB syntax and needs no MATLAB/Octave
26install (or any server process), the same `.m` code that would otherwise
27require a licensed product behind a server just runs in the tab.
29## How it works
31Three small pieces, all in this repo:
33- **Kernel** (`src/kernel.ts`) — implements JupyterLite's `BaseKernel` from
6b31a9aSync .m workspace files from the notebook directory into the sessionJeremy Magland 34 `@jupyterlite/services`. Before each `execute_request`, `.m` files in the
35 notebook's directory (read via the JupyterLite contents manager) are
36 synced into the numbl session; the cell source then runs against the
37 session's persistent workspace (`createNumblSession` /
38 `session.execute` from `numbl/browser`, a Web Worker that numbl manages).
39 Output streams back as `stream` messages; the run's plot instructions are
40 published as `display_data` with the mime type
41 `application/vnd.numbl.figure+json`.
41c072cjupyterlite-numbl-kernel: MATLAB-syntax kernel for JupyterLiteJeremy Magland 42- **Figure renderer** (`src/mime.tsx`) — a JupyterLab mime renderer for that
43 mime type: it replays the instructions through numbl's figures reducer and
44 mounts numbl's React `FigureView` (from `numbl/graphics`). Outputs are
45 plain JSON, so saved notebooks re-render wherever the extension is
46 installed.
47- **Kernel registration** (`src/index.ts`) — registers the kernelspec with
48 JupyterLite's `IKernelSpecs`.
50## Build a site with it
52```bash
53pip install jupyterlite-core jupyterlite-numbl-kernel
54jupyter lite build --contents my-notebooks --output-dir dist
55# dist/ is a static site — serve it anywhere
56```
58The `demo/` directory in this repo contains the demo site sources
59(notebooks + requirements); `.github/workflows/deploy.yml` builds and
60deploys it to GitHub Pages.
8befa62Demo: use in-memory JupyterLite storage so reloads show fresh contentJeremy Magland 62### Always-fresh content (demo choice)
0fd7818Demo: disable the JupyterLite service worker so redeploys show on reloadJeremy Magland 64JupyterLite caches content in two layers that both defeat redeploys:
661. It copies notebooks into the browser's IndexedDB on first visit, and that
67 local copy then wins over the deployed files **even after a redeploy**.
682. Its **service worker** is an offline caching proxy for the app itself and
69 for content files, so it can keep serving the old app and old notebooks
70 after a redeploy until it happens to update.
72Since this is a demo, `demo/jupyter-lite.json` neutralizes both: it uses
73JupyterLite's in-memory storage (so every reload re-seeds the latest
74deployed notebooks) and disables the service-worker plugin (which the numbl
75kernel doesn't need — it reads content on the main thread, not via the
76service worker's kernel drive):
78```json
80 "jupyter-config-data": {
81 "enableMemoryStorage": true,
82 "contentsStorageDrivers": ["memoryStorageDriver"],
83 "settingsStorageDrivers": ["memoryStorageDriver"],
0fd7818Demo: disable the JupyterLite service worker so redeploys show on reloadJeremy Magland 84 "workspacesStorageDrivers": ["memoryStorageDriver"],
85 "disabledExtensions": [
86 "@jupyterlite/application-extension:service-worker-manager"
87 ]
90```
92The trade-off is that a visitor's edits live only for the session and are
0fd7818Demo: disable the JupyterLite service worker so redeploys show on reloadJeremy Magland 93discarded on reload. A visitor who loaded the site **before** the service
94worker was disabled still has it registered and must clear browser data
95(or `Help > Clear Browser Data`) once to get past it. For a real deployment where users should keep their
8befa62Demo: use in-memory JupyterLite storage so reloads show fresh contentJeremy Magland 96work, omit these keys (the default persistent storage) and bump
97`contentsStorageName` when you want to force-refresh shipped content.
98numbl's own package cache (installed via `mip`) lives in a separate
99IndexedDB store and is unaffected, so `mip`-installed packages still
100persist across reloads.
41c072cjupyterlite-numbl-kernel: MATLAB-syntax kernel for JupyterLiteJeremy Magland 102## Limitations (proof of concept)
104- **No interrupt**: a runaway cell can only be stopped by restarting the
105 kernel (restart works and gives a fresh workspace). Cooperative
106 cancellation exists in numbl but needs `SharedArrayBuffer`, i.e.
107 cross-origin isolation headers, which plain GitHub Pages doesn't set.
108- **No `input()`** (stdin), for the same reason.
109- **Figures are per-cell** (like inline matplotlib): each cell renders the
110 figures its own commands produce; `hold on` does not span cells.
111- **Named function definitions are not supported inside cells** (a numbl
112 REPL limitation) — anonymous functions work; named functions belong in
6b31a9aSync .m workspace files from the notebook directory into the sessionJeremy Magland 113 `.m` files next to the notebook (see `demo/content/statsutils.m`), which
114 this kernel syncs into the session automatically.
115- The `.m`-file sync is **one-way**: deleting a `.m` file from the file
116 browser leaves its function defined until the kernel restarts, and files
117 written by cell code (e.g. via `fopen`) don't appear back in the file
118 browser.
41c072cjupyterlite-numbl-kernel: MATLAB-syntax kernel for JupyterLiteJeremy Magland 119- **uihtml** components render display-only; the MATLAB↔HTML event bridge
120 is not wired into outputs yet.
121- numbl itself is not MATLAB: it covers a large, tested subset of the
122 language and toolbox surface. See the
123 [numbl repo](https://github.com/flatironinstitute/numbl) for scope.
125## Development
127Requires Python ≥ 3.9 and NodeJS ≥ 20, and `numbl >= 0.4.14` on npm (the
128first release with the incremental `session.execute` browser API). To
129develop against an unreleased numbl checkout, run `npm pack` there and
130point the `numbl` dependency at the tarball.
132```bash
133python -m venv .venv && source .venv/bin/activate
134pip install "jupyterlab~=4.6.0" "jupyterlite-core==0.8.1"
136jlpm install
137jlpm build # tsc + labextension (dev)
138pip install -e . # editable install, registers the labextension
140# Build and serve the demo site locally
141pip install -r demo/requirements.txt
142jupyter lite build --lite-dir demo --contents content --output-dir demo/_output
143python -m http.server -d demo/_output 8000
144```
146`jlpm watch` rebuilds on change during development.
148## License
150Apache-2.0. Built on [numbl](https://github.com/flatironinstitute/numbl) and
151the [JupyterLite](https://github.com/jupyterlite/jupyterlite) kernel API;
152scaffolding follows the
153[jupyterlite/echo-kernel](https://github.com/jupyterlite/echo-kernel)
154template.
moveopenescclose