Skip to content

Migrate to ArviZ v1#31

Open
haeussma wants to merge 11 commits into
JR-1991:masterfrom
haeussma:update-arviz
Open

Migrate to ArviZ v1#31
haeussma wants to merge 11 commits into
JR-1991:masterfrom
haeussma:update-arviz

Conversation

@haeussma

Copy link
Copy Markdown
Contributor

Migrate to ArviZ v1

Why

In April 2026, ArviZ released v1.0 (Catalax currently pins v0.x). The
v1 release is a substantial rewrite that splits the package into
arviz-base, arviz-stats, and arviz-plots, and ships breaking changes to
the public API (InferenceDataxarray.DataTree, hdi_probprob /
ci_prob, plot_posteriorplot_dist, plot_ess(kind="evolution")
plot_ess_evolution, and so on). Pinning v0.x is no longer viable: it
prevents Catalax from coexisting in the same environment as other Bayesian
modelling tools that have already migrated (notably Chromhander, which we
routinely use together with Catalax).

This PR migrates Catalax to ArviZ v1 so the library stays current and
installable alongside the wider ArviZ-v1 ecosystem.

Impact for Catalax users

  • The public Catalax API does not change. All MCMC plotting and summary
    entrypoints keep their existing signatures
    (HMCResults.plot_posterior(...), Model.from_samples(..., hdi_prob=...),
    summary(mcmc, hdi_prob=...), etc.). Existing notebooks and downstream
    code continue to work without edits.
  • Minimum Python version is raised from 3.11 → 3.12. ArviZ v1.1 itself
    requires Python ≥ 3.12, so we have no choice here. Bumping the floor is
    necessary to make Catalax installable in the same environment as
    Chromhander and other ArviZ-v1-based tools that are typically used
    together with Catalax in a single venv.

What changed

Dependency / packaging

  • pyproject.toml
    • requires-python = ">=3.12,<3.15" (was >=3.11).
    • arviz>=1.1.0,<2.0 (was >=0.22,<0.30).
    • Added h5netcdf>=1.6.4,<2 and h5py>=3.10,<4: ArviZ v1 writes NetCDF
      via h5netcdf and the latter no longer pulls in h5py automatically.
    • Removed corner>=2.2.2,<3: the corner library is not compatible with
      xarray.DataTree, so the pair plot is now built with
      arviz.plot_pair.
  • README.md: badge, prerequisites and CI section updated to Python 3.12+.
  • .github/workflows/tests.yml: test matrix ['3.12', '3.13'] (dropped
    3.11).
  • .github/workflows/test-publish.yml: build runs on 3.12.

Internal adaptation to ArviZ v1

Public Catalax signatures are unchanged; only the calls Catalax makes into
ArviZ were updated.

  • catalax/model/model.py
    • Type hints samples: az.InferenceDatasamples: xarray.DataTree.
    • All az.hdi(..., hdi_prob=...) calls converted to
      az.hdi(..., prob=...).
    • Model.from_samples now reshapes raw 1-D dict samples to (1, -1)
      before passing to az.hdi, because az.hdi in v1 expects sample
      dimensions to be present. A regression test was added for this path
      (tests/unit/model/test_from_samples.py).
  • catalax/mcmc/plotting.py
    • plot_posterior now calls az.plot_dist (v0 az.plot_posterior was
      removed in v1).
    • plot_ess body simplified to a direct
      az.plot_ess_evolution(...) call (v0
      plot_ess(kind="evolution") was removed in v1).
    • summary uses ci_prob=hdi_prob, ci_kind="hdi" (v0 hdi_prob kwarg
      was renamed).
    • plot_corner was rewritten on top of arviz.plot_pair:
      • KDE marginals on the diagonal with median dot + HDI bar +
        point-estimate text (controlled via stats.ci_kind="hdi",
        stats.ci_prob=hdi_prob, stats.point_estimate="median" scoped via
        az.rc_context so user rcParams are not modified).
      • Lower-triangle joint plots: filled KDE bands (cmap="Blues",
        levels=6) with a thin matching contour line on top to hide soft
        fill transitions, a faint grey scatter underlay so tail samples
        outside the lowest contour remain visible, and divergent transitions
        overlaid by arviz.plot_pair itself.
  • catalax/mcmc/results.py
    • to_netcdf(...) now passes engine="h5netcdf" (the default netcdf4
      engine is no longer bundled with ArviZ v1).
    • Docstring sweep: arviz.plot_posteriorarviz.plot_dist, hdi_prob
      ci_probs, InferenceDataDataTree.
  • catalax/__init__.py, catalax/dataset/__init__.py,
    catalax/mcmc/__init__.py, catalax/model/__init__.py,
    catalax/neural/__init__.py
    • Dropped import arviz as az + az.style.use("arviz-doc") from
      package init modules (the v0 style is gone in v1 and we intentionally
      do not override the user's matplotlib / arviz style).
  • catalax/__init__.py
    • Set matplotlib.rcParams["figure.dpi"] = 300 and savefig.dpi = 300
      so all plots Catalax produces (and saved files) render at 300 dpi.

Tests / examples

  • New regression test tests/unit/model/test_from_samples.py covers the
    reshape path in Model.from_samples that v1 az.hdi forced.
  • Example notebooks (HMC.ipynb, InhomogeneousData.ipynb, etc.) were
    re-executed against ArviZ v1 and the resulting JSON / .eqx artefacts
    refreshed. Notebook code itself only changed where the Catalax API was
    not the entrypoint (e.g. direct ArviZ calls inside the notebook).

Verification

  • uv run ruff check catalax tests — clean.
  • uv run pytest -m "not expensive"62 passed, 2 deselected (= 64
    total, including the new from_samples regression test).
  • examples/HMC.ipynb runs end-to-end on arviz==1.1.0.
  • import catalax produces no FutureWarning / MigrationWarning from
    ArviZ.

Known minor visual differences

  • az.summary column names changed upstream (hdi_2.5%hdi95_lb).
    Visible in the summary DataFrame; unavoidable from the ArviZ side.
  • The corner / pair plot now uses ArviZ + seaborn (KDE bands) instead of
    the corner library, so styling is slightly different. The replacement
    shows the same information (HDI, median, divergences) and additionally
    displays joint KDE density rather than just scatter clouds.

haeussma and others added 11 commits June 10, 2026 10:02
ArviZ v1 removed the "arviz-doc" matplotlib style and requires
Python 3.12+. The style call was happening at import time in five
package __init__.py files; drop it entirely rather than swap to a
v1 style (users can apply their own style if they want one). Add
h5netcdf so InferenceData.to_netcdf works out-of-the-box without
the user installing a backend separately.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The repo's .gitignore excludes specs/. The previous commit (89f83bf)
slipped in specs/update-arviz-v1.md; remove it from tracking. The
file remains on disk locally for reference during the migration.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
az.hdi(...) renamed its credible-interval kwarg from hdi_prob to
prob in ArviZ v1; switch the four internal call sites in
Model.from_samples and Model.from_arviz. The public Catalax kwarg
hdi_prob is preserved — only the inner call changes.

Also retype Model.from_arviz's samples parameter as
xarray.DataTree (the v1 replacement for arviz.InferenceData,
which now just warns and aliases to DataTree).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Keep migration spec drafts and other working notes outside version
control. Spawned from the ArviZ v1 migration work — specs/update-arviz-v1.md
lives there for active reference but isn't repo content.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
az.plot_posterior is gone in ArviZ v1 — replace the internal call
inside catalax's plot_posterior wrapper with az.plot_dist (the v1
distribution-plot replacement). The catalax public function name
stays plot_posterior.

az.plot_ess no longer supports kind="evolution" or the v0
color/extra_kwargs styling; swap the internal call inside
catalax's plot_ess wrapper to az.plot_ess_evolution and drop the
v0 styling overrides. v1 styling now flows through visuals= and
is out of scope for this migration.

az.summary renamed hdi_prob → ci_prob and changed its default
ci_kind from "hdi" to "eti"; pass ci_prob=hdi_prob and
ci_kind="hdi" to preserve v0 semantics. With ci_kind="hdi" and
default fmt="wide", the return type narrows to pd.DataFrame —
update annotation and drop the now-unused xarray import.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ArviZ v1's to_netcdf on an xarray.DataTree needs an explicit
engine; pass "h5netcdf" since we already declare it as a dep.
h5netcdf 1.8 stopped pulling in h5py automatically — add h5py
to dependencies so the round-trip works on a fresh install.

Also retire references to "arviz.InferenceData" in HMCResults
docstrings; the v1 successor is xarray.DataTree.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
corner.corner() doesn't know about ArviZ v1's DataTree — it
falls back to expecting a numpy array or DataFrame. v0 worked
because corner had built-in interop with arviz.InferenceData.

Stack the parameter samples into an (N, P) numpy array directly
from mcmc.get_samples() and pass it with labels=. This drops the
divergences=True overlay (no divergence info without a DataTree),
which is an acceptable loss; it can be reintroduced once corner
adds DataTree support upstream.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
az.hdi in ArviZ v1 requires at least a (chain, draw)-shaped input.
mcmc.get_samples() returns a dict of flat 1-D arrays per parameter
(no chain axis), which raises ValueError when handed straight to
az.hdi. Add a leading singleton chain dim before the two az.hdi
calls so the input is shaped (1, N). Downstream indexing
(hdi[name][0], hdi[name][1]) is unchanged because az.hdi still
emits a Dataset with a single ci_bound axis.

Add a unit test that exercises the path with a synthetic 1-D dict
to lock in the behaviour and catch any future regression.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
HMCResults docstrings still mentioned arviz.plot_posterior and
hdi_prob kwargs that no longer exist in ArviZ v1; rewrite them
to reference plot_dist and ci_probs. Narrow summary's return type
to pd.DataFrame to match the wrapped call. Drop the now-unused
xarray and Union imports.

Bound h5py upper at <4 to match the project's pinning style. Bump
README badge, prerequisites, and CI matrix from Python 3.11 to 3.12
since arviz>=1.1 requires 3.12+. Add trailing newline to
.gitignore.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Removed the `corner` dependency from `pyproject.toml`.
- Added `matplotlib` configuration for higher DPI in `catalax/__init__.py`.
- Refactored `plot_corner` in `catalax/mcmc/plotting.py` to use `arviz.plot_pair` for improved visualization of posterior parameters, including KDE marginals and HDI intervals.
- Updated `HMCResults.plot_corner` method to align with the new `plot_corner` signature and functionality.
- Made minor adjustments to Jupyter notebooks to reflect execution count changes and added a new column for 'type' in data tables.

This commit enhances the plotting capabilities and streamlines dependencies in preparation for future updates.
Bump the project version to 0.6.0 to reflect recent changes and improvements. This update ensures consistency across project files.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant