Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions .github/workflows/demo-notebook.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: demo notebook

# Builds examples/demo.py (a `# %%` cell file) into examples/demo.ipynb with jupytext, so it can be
# opened in Colab. On pushes to main the notebook is force-pushed to the orphan `demo` branch, which
# the README's "Open in Colab" badge points at; on pull requests it is only built, as a check.

on:
push:
branches: [main]
pull_request:
workflow_dispatch:

permissions:
contents: write

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: python -m pip install jupytext nbformat
- name: Convert the cell files to notebooks
run: |
set -e
for f in examples/*.py; do
case "$f" in examples/make_gif.py) continue;; esac
jupytext --to ipynb "$f"
done
ls -la examples/*.ipynb
- name: Publish to the demo branch
if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request'
run: |
set -e
mkdir -p /tmp/demo/examples
cp examples/*.ipynb /tmp/demo/examples/
cp README.md LICENSE /tmp/demo/
cd /tmp/demo
git init -q -b demo
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
cat > README.md <<'EOF'
# liveplot demo notebooks

Generated by CI from `examples/*.py` on `main`; do not edit here.
Open in Colab: https://colab.research.google.com/github/ARENA-education/liveplot/blob/demo/examples/demo.ipynb
EOF
git add -A
git commit -q -m "Build demo notebooks from main ${GITHUB_SHA::7}"
git remote add origin "https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git"
git push -q --force origin demo
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
17 changes: 17 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: tests

on:
push:
branches: [main]
pull_request:

jobs:
pytest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: python -m pip install -e ".[test]" tqdm ipython numpy
- run: python -m pytest -q tests
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

Live training curves in Jupyter, Colab and the VS Code / Cursor interactive window, with a tqdm bar underneath, at (almost) no cost to the training loop.

[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/ARENA-education/liveplot/blob/demo/examples/demo.ipynb) [![tests](https://github.com/ARENA-education/liveplot/actions/workflows/tests.yml/badge.svg)](https://github.com/ARENA-education/liveplot/actions/workflows/tests.yml)

Try it in Colab with the badge above: that notebook is [`examples/demo.py`](examples/demo.py), a cell-by-cell tour of the features, which CI converts with jupytext and publishes to the `demo` branch on every push to `main`.

![training loss every step, eval loss and accuracy every 50 steps, on one panel with two y-axes](docs/demo.gif)

The GIF is cell 2 of [`examples/demo.py`](examples/demo.py), a tour of the features in a cell-separated file: open it in the VS Code / Cursor interactive window and run it cell by cell. That cell trains a tiny numpy classifier, logging the training loss every step and the eval loss and accuracy every 50 steps, laid out as `"loss | eval_loss eval_acc"`. The GIF itself was recorded by the library: `examples/make_gif.py` runs the same loop as a plain script with `record="docs/demo.gif"`.
Expand Down
21 changes: 17 additions & 4 deletions examples/demo.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
# %%
"""
liveplot tour. A cell-separated file: run it cell by cell in the VS Code / Cursor interactive
window (or paste the cells into a notebook) to watch each plot update live. Running it as a plain
script also works, it just prints instead of drawing (except the recording cell, which renders).

pip install git+https://github.com/ARENA-education/liveplot.git
window, open it in Colab (the README has the link: CI turns this file into a notebook on the
`demo` branch), or run it as a plain script, which prints instead of drawing (except the
recording cell, which renders).
"""

# Setup: on Colab, install liveplot; anywhere else it is already installed.
import subprocess
import sys

try:
import google.colab # noqa: F401

IN_COLAB = True
except ImportError:
IN_COLAB = False
if IN_COLAB:
subprocess.run([sys.executable, "-m", "pip", "install", "-q", "git+https://github.com/ARENA-education/liveplot.git"], check=True)

# %%
import math
import random
import time
Expand Down
1 change: 1 addition & 0 deletions tests/test_liveplot.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ def test_interrupt_inside_with_block_is_clean(fake_notebook):
assert len(p.data["loss"][0]) == n_warmup + 31 and fake_notebook.frames, "final frame drawn, data kept"


@pytest.mark.skipif(sys.platform == "win32", reason="os.kill(pid, SIGINT) terminates the process on Windows")
def test_render_child_ignores_sigint(fake_notebook):
"""Jupyter's interrupt goes to the whole process group; the renderer must shrug it off."""
p = LivePlot(refresh_seconds=0.1)
Expand Down
Loading