diff --git a/CLAUDE.md b/CLAUDE.md index 98db509..d75b407 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,17 +6,23 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co A Python package that generates responsive static HTML galleries from scientific plot collections (PDFs and HTMLs). It converts PDFs to PNGs via ImageMagick, organizes plots hierarchically, propagates YAML/JSON metadata through directory trees, and renders everything via a Jinja2 template into a static website served from a web directory. +The repo also ships `plotstyle`, a standalone matplotlib styling toolkit (KIT corporate-design theme + building-block functions) for producing the PDF figures that feed into a `gallery` source directory. `gallery` never imports it — the only connection is the PDF files and `metadata.yaml` on disk. **See `plotstyle/CLAUDE.md` for full agent-facing usage docs, the API reference, and the metadata.yaml workflow.** + ## Commands ```bash # Install the package (editable) pip install -e ".[dev]" +# Also install plotstyle's dependency (matplotlib) if working on plot-producing scripts +pip install -e ".[dev,plotting]" # or: uv sync --extra dev --extra plotting + # Run all tests pytest tests/ # Run a single test file pytest tests/test_generate_gallery.py -v +pytest tests/test_plotstyle.py -v # Run a single test by name pytest tests/test_generate_gallery.py::test_needs_update_missing_target -v @@ -75,6 +81,8 @@ generate() [api.py] | `gallery/assets/js/` | Vanilla JS modules loaded as ES modules; `GalleryApp` in `gallery-app.js` orchestrates all managers | | `gallery/assets/css/` | Modular CSS; `main.css` imports all others via `@import` | | `config.yaml` | Local deployment config (paths are machine-specific) | +| `plotstyle/` | Standalone matplotlib styling toolkit for producing plots (see `plotstyle/CLAUDE.md`) — not imported by `gallery/` | +| `examples/plotstyle_showcase.ipynb` | Rendered, runnable tour of every `plotstyle` function | ### Config File Format @@ -104,10 +112,16 @@ When `source_to_update` is passed to `generate()`, only that source's subdirecto `metadata.yaml` (or `.yml`/`.json`) in any source directory is loaded and **merged with parent metadata** (`inherit_from_parent=True` by default). Child directories override parent keys. Per-plot overrides can live in `.yaml` files alongside the plot. +Fields are freeform YAML (no fixed schema); `title`, `description`, `plot_type`, `experiment` get prominent placement in the per-plot metadata popup, everything else still displays under "Additional Information". Text values support inline LaTeX rendered via MathJax client-side. + +### Plot-Producing Companion (`plotstyle`) + +`plotstyle` (top-level package, optional `plotting` extra) is how plots destined for a `gallery` source directory should be produced — a KIT corporate-design matplotlib theme plus building blocks (`new_figure`, `colorbar`, `style_legend`, `panel_label`, `savefig`). It has no code dependency on `gallery`; the two only meet on disk, via the PDFs and `metadata.yaml` files a `plotstyle` script writes into a `gallery` source directory. **Full usage docs, API reference, best practices, and the metadata.yaml workflow live in `plotstyle/CLAUDE.md`** — read that file before writing or reviewing any script that `import plotstyle`. `examples/plotstyle_showcase.ipynb` is a rendered, runnable tour of every function. + ### Frontend (Static JS/CSS) The frontend is vanilla ES modules — no build step. `assets/js/main.js` imports `GalleryApp` from `gallery-app.js`, which instantiates all manager classes (`ThemeManager`, `SearchManager`, `NavigationManager`, etc.). Each manager is self-contained. The template embeds gallery data as JSON in the page; JS reads it at runtime. ### Deployment -The project ships a `Singularity.def` / `web.sif` Apptainer container for HPC environments. CI (`.gitlab-ci.yml`) builds the container and runs pytest inside it. For local development the `.venv` is sufficient. +The project ships a `Dockerfile` plus `docker-compose.yml` (a `generator` service that runs `gallery generate` on an interval, and an `nginx`-based `web` service serving the output — see `deploy/entrypoint.sh` and `deploy/nginx.conf`). CI (`.gitlab-ci.yml`) builds the Docker image and runs pytest inside it. For local development the `.venv` (or `uv`) is sufficient. diff --git a/README.md b/README.md index de6198e..3203292 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,10 @@ - TUI: `gallery tui` - Config file stored under user `$HOME/.config/gallery` +### Producing Plots (`plotstyle`) + +- Companion matplotlib styling toolkit (optional `plotting` extra) for producing figures that look consistent across a thesis and slide deck, ready to drop straight into a gallery source directory — see [Producing Plots with `plotstyle`](#producing-plots-with-plotstyle) + ## Installation @@ -54,6 +58,16 @@ gallery --help - Python packages are installed automatically by pip (Jinja2, PyYAML, PyMuPDF, Textual, argcomplete, platformdirs) - [ImageMagick](https://imagemagick.org/) is **optional** — used as a fallback if `PyMuPDF` is not available +### Optional: `plotstyle` (for producing plots) + +```bash +pip install -e ".[plotting]" +# or +uv sync --extra plotting +``` + +This only installs `matplotlib` — it's kept out of the core dependencies so a plain gallery install stays lightweight. `plotstyle` also requires a local LaTeX toolchain (`latex` + `dvipng`) to be installed separately; see [Producing Plots with `plotstyle`](#producing-plots-with-plotstyle). + ### Shell Completion (optional) Install tab-completion for bash/zsh/fish: @@ -215,6 +229,37 @@ LaTeX formulas are supported in metadata values and rendered with MathJax: formula: "$$E = mc^2$$" ``` +## Producing Plots with `plotstyle` + +`plotstyle` is a companion matplotlib styling toolkit shipped in this repo (the `plotstyle/` package) for producing the plots you'll point a gallery source at — a KIT (Karlsruhe Institute of Technology) corporate-design color palette, consistent spines/ticks/gridlines, LaTeX text in a modern sans font, and a few building-block functions (figure titles with a parameters subtitle, a same-size colorbar helper, an outside-axes legend, panel labels). It has no code dependency on `gallery` — the two only meet on disk, through the PDF files (and optional `metadata.yaml`) a `plotstyle` script writes into a directory that `gallery` then scans. + +Install it with the `plotting` extra (see [Installation](#installation)) and make sure a LaTeX toolchain (`latex` + `dvipng`) is available locally — `plotstyle` always renders text through real LaTeX, there's no fallback. + +```python +import numpy as np +import plotstyle as ps + +ps.use() # once, before creating any figure + +fig, ax = ps.new_figure( + "thesis-single", + title="Measured signal", + params={"N": 512, "seed": 42}, +) +x = np.linspace(0, 10, 200) +ax.plot(x, np.sin(x), label="signal") +ax.set_xlabel("Time (s)") +ax.set_ylabel(r"Amplitude $A(t)$") +ps.style_legend(ax, title="Series") + +# Save straight into a gallery source directory: +ps.savefig(fig, "/path/to/plots/measured_signal", formats=("pdf",)) +``` + +That PDF (plus an optional `metadata.yaml` next to it, as described above) is exactly what `gallery generate --source /path/to/plots` picks up — `gallery` converts the PDF to a thumbnail PNG itself, so `plotstyle` scripts should stick to `formats=("pdf",)` rather than also producing a PNG. + +See `examples/plotstyle_showcase.ipynb` for a fully rendered tour of every function, and `plotstyle/CLAUDE.md` for the full API reference and best practices (aimed at coding agents, but equally useful for humans). + ## Shortcuts | Icon | Button | Function | Shortcut |