|
| 1 | +# Handoff: `why-an-index` custom-index tutorial |
| 2 | + |
| 3 | +## The task |
| 4 | +Contribute a new "custom indexes" tutorial notebook to the xarray-tutorial repo |
| 5 | +(a Jupyter Book). |
| 6 | + |
| 7 | +1. **Read the notebook end-to-end — actually RUN it**, don't assume: |
| 8 | + `pixi run jupyter nbconvert --to notebook --execute intermediate/indexing/why-an-index.ipynb` |
| 9 | + Report its current state. |
| 10 | +2. **Work on the examples**: tighten them, make them run cleanly, improve the pedagogy. |
| 11 | +3. Where it helps, **base examples on the animations/gifs from earlier tutorial sections** |
| 12 | + for visual continuity. The notebook already reuses `advanced/backends/ocean.gif` |
| 13 | + (the "video time axis" example) — that gif and the animation style of earlier |
| 14 | + sections are the model to follow. |
| 15 | +4. **Confirm the target file with the user before editing.** |
| 16 | + |
| 17 | +## The ONE file we work on |
| 18 | +- `intermediate/indexing/why-an-index.ipynb` ← OUR notebook (67 cells). The entire task. |
| 19 | +- Branch `why-an-index`, off origin/main, baseline commit `d8c4793` already in place. |
| 20 | + |
| 21 | +## DO NOT TOUCH (this derailed a previous session — read this) |
| 22 | +- `intermediate/indexing/build_custom_index_1d.ipynb` and **PR #295 "Custom index tutorial"** |
| 23 | + are Emma Marshall's SEPARATE draft on her fork (`e-marshall/xarray-tutorial`, branch |
| 24 | + `custom_index`). It is **prior art / reference ONLY**. |
| 25 | +- Never edit it, never branch off `custom_index`. It does not exist on `main`; if it shows |
| 26 | + up in the working tree, ignore it. |
| 27 | +- A prior session mistakenly spent effort cleaning up Emma's notebook instead of ours, |
| 28 | + because it anchored on the first PR it found ("the existing branch that adds a start |
| 29 | + here"). Our real work is `why-an-index.ipynb` and was never in Emma's file. |
| 30 | + |
| 31 | +## What the notebook is |
| 32 | +Title: *"Why does xarray need an index? (and when a custom one)"*. Intuition-first narrative: |
| 33 | +coordinate = array of labels → why scanning is bad → alignment → 1-D index in the wild |
| 34 | +(video time axis via `ocean.gif`, `RangeIndex`) → 2-D selection → `NDPointIndex` → |
| 35 | +building your own index (1-D rule → regular grid → nonlinear "fisheye" via |
| 36 | +`CoordinateTransform`) → "which index, when?" summary. |
| 37 | + |
| 38 | +Full section list (23 headers) is visible by scanning the markdown cells; the arc above |
| 39 | +covers it. |
| 40 | + |
| 41 | +## Current xarray API facts (verified against xarray 2025.12, the pinned env) |
| 42 | +Check the notebook's custom-index code against these — they are current-API requirements: |
| 43 | +- `Index.equals` must be `(self, other, *, exclude=None)` — the old 2-arg form raises a `FutureWarning`. |
| 44 | +- `Index.sel` must return an `IndexSelResult`. |
| 45 | +- `Index.reindex_like` is `(self, other)` (no `method`/`tolerance`). |
| 46 | +- Any **intentional-error cell needs a `raises-exception` cell tag**, or the Jupyter Book |
| 47 | + build (`allow_errors: false` in `_config.yml`) fails. |
| 48 | + |
| 49 | +## Reference material (read-only) |
| 50 | +- Custom-index guide: `~/Documents/dev/xarray/doc/internals/how-to-create-custom-index.rst` |
| 51 | +- xarray source in `~/Documents/dev/xarray` for `Index` / `PandasIndex` / |
| 52 | + `CoordinateTransform` / `NDPointIndex` / `RangeIndex`. |
| 53 | +- Earlier tutorial sections for gif/animation examples (e.g. `advanced/backends/ocean.gif`). |
| 54 | + |
| 55 | +## Environment & workflow |
| 56 | +- **pixi** project. Run Python: `pixi run python`. Execute a notebook headless (mirrors the |
| 57 | + book build): `pixi run jupyter nbconvert --to notebook --execute <nb>`. |
| 58 | +- Edit notebooks **IN PLACE** via the Jupyter MCP against the user's live JupyterLab |
| 59 | + (they'll paste a URL+token) or `Edit` the `.ipynb` directly. **NEVER** regenerate a |
| 60 | + `.ipynb` from a builder script. |
| 61 | +- **Jupyter gotcha (bit us hard last time):** if the MCP warns *"collab socket disconnected / |
| 62 | + split-brain,"* your edits may sit in a local buffer and never reach disk, and a stale |
| 63 | + `.jupyter_ystore.db` RTC cache can serve OLD content to the browser even after a save. |
| 64 | + Fix: ensure **ONE** jupyter server per directory, delete `.jupyter_ystore.db` + `.jupyter/`, |
| 65 | + restart the server. Verify disk truth with `grep`/the contents API, not the browser. |
| 66 | + |
| 67 | +## Housekeeping notes |
| 68 | +- Baseline commit `d8c4793` includes the notebook **with outputs** (pre-commit/nbstripout is |
| 69 | + NOT installed in this clone, so outputs weren't stripped). `pre-commit.ci` will strip them |
| 70 | + when this becomes a PR. Fine to keep outputs while developing. |
| 71 | +- `pixi.lock` shows as modified in the working tree — local env state, leave it. |
| 72 | +- Stray untracked clutter safe to ignore: `Untitled.ipynb`, `intermediate/indexing/Untitled.ipynb` |
| 73 | + (empty), `.jupyter/`, `.jupyter_ystore.db`, `.wrangler/`, `uv.lock`. |
| 74 | +- The very first prototype lives at `~/Documents/dev/xarray/.ipynb_checkpoints/why-an-index-checkpoint.ipynb` |
| 75 | + (18 cells, older) — the 67-cell version in this repo supersedes it. |
| 76 | + |
| 77 | +## Suggested opening prompt for the next session |
| 78 | +> Read `notes/handoff-why-an-index.md` and continue. Start by running |
| 79 | +> `intermediate/indexing/why-an-index.ipynb` end-to-end and reporting its state, then let's |
| 80 | +> work on the examples. Confirm you're editing why-an-index.ipynb (NOT Emma's |
| 81 | +> build_custom_index_1d.ipynb) before making changes. |
0 commit comments