xarray-plotly 0.0.14__tar.gz → 0.0.17__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/.github/workflows/ci.yml +3 -3
  2. xarray_plotly-0.0.17/.github/workflows/dependabot-auto-merge.yml +39 -0
  3. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/.github/workflows/docs.yml +4 -2
  4. xarray_plotly-0.0.17/.github/workflows/latest-deps.yml +35 -0
  5. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/.github/workflows/pr-title.yml +7 -8
  6. xarray_plotly-0.0.17/.github/workflows/publish.yaml +66 -0
  7. xarray_plotly-0.0.17/.github/workflows/release.yaml +27 -0
  8. xarray_plotly-0.0.17/.readthedocs.yaml +18 -0
  9. xarray_plotly-0.0.17/.release-please-manifest.json +3 -0
  10. xarray_plotly-0.0.17/CHANGELOG.md +37 -0
  11. {xarray_plotly-0.0.14/xarray_plotly.egg-info → xarray_plotly-0.0.17}/PKG-INFO +1 -15
  12. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/docs/examples/combining.ipynb +140 -16
  13. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/docs/examples/dimensions.ipynb +11 -1
  14. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/pyproject.toml +13 -12
  15. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/tests/test_accessor.py +103 -1
  16. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/tests/test_common.py +17 -0
  17. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/tests/test_figures.py +532 -2
  18. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/xarray_plotly/__init__.py +6 -0
  19. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/xarray_plotly/accessor.py +98 -3
  20. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/xarray_plotly/common.py +8 -1
  21. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/xarray_plotly/config.py +1 -1
  22. xarray_plotly-0.0.17/xarray_plotly/figures.py +1050 -0
  23. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/xarray_plotly/plotting.py +105 -12
  24. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17/xarray_plotly.egg-info}/PKG-INFO +1 -15
  25. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/xarray_plotly.egg-info/SOURCES.txt +4 -2
  26. xarray_plotly-0.0.17/xarray_plotly.egg-info/requires.txt +3 -0
  27. xarray_plotly-0.0.14/.github/workflows/dependabot-auto-merge.yml +0 -24
  28. xarray_plotly-0.0.14/.github/workflows/release-please.yml +0 -42
  29. xarray_plotly-0.0.14/.github/workflows/release.yml +0 -28
  30. xarray_plotly-0.0.14/.release-please-manifest.json +0 -3
  31. xarray_plotly-0.0.14/CHANGELOG.md +0 -15
  32. xarray_plotly-0.0.14/xarray_plotly/figures.py +0 -467
  33. xarray_plotly-0.0.14/xarray_plotly.egg-info/requires.txt +0 -19
  34. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/.github/dependabot.yml +0 -0
  35. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/.gitignore +0 -0
  36. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/.pre-commit-config.yaml +0 -0
  37. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/.release-please-config.json +0 -0
  38. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/CONTRIBUTING.md +0 -0
  39. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/LICENSE +0 -0
  40. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/README.md +0 -0
  41. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/docs/api.md +0 -0
  42. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/docs/examples/datasets.ipynb +0 -0
  43. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/docs/examples/fast_bar.ipynb +0 -0
  44. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/docs/examples/figure.ipynb +0 -0
  45. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/docs/examples/kwargs.ipynb +0 -0
  46. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/docs/examples/manipulation.ipynb +0 -0
  47. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/docs/examples/plot-types.ipynb +0 -0
  48. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/docs/getting-started.ipynb +0 -0
  49. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/docs/index.md +0 -0
  50. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/mkdocs.yml +0 -0
  51. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/setup.cfg +0 -0
  52. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/tests/__init__.py +0 -0
  53. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/tests/test_config.py +0 -0
  54. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/xarray_plotly/py.typed +0 -0
  55. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/xarray_plotly.egg-info/dependency_links.txt +0 -0
  56. {xarray_plotly-0.0.14 → xarray_plotly-0.0.17}/xarray_plotly.egg-info/top_level.txt +0 -0
@@ -23,7 +23,7 @@ jobs:
23
23
  run: uv python install ${{ matrix.python-version }}
24
24
 
25
25
  - name: Install dependencies
26
- run: uv sync --extra dev
26
+ run: uv sync --group dev
27
27
 
28
28
  - name: Lint
29
29
  run: uv run ruff check .
@@ -38,7 +38,7 @@ jobs:
38
38
  run: uv run pytest --cov=xarray_plotly --cov-report=xml
39
39
 
40
40
  - name: Upload coverage
41
- uses: codecov/codecov-action@v5
41
+ uses: codecov/codecov-action@v6
42
42
  if: matrix.python-version == '3.12'
43
43
  with:
44
44
  token: ${{ secrets.CODECOV_TOKEN }}
@@ -53,7 +53,7 @@ jobs:
53
53
  uses: astral-sh/setup-uv@v7
54
54
 
55
55
  - name: Install dependencies
56
- run: uv sync --extra docs
56
+ run: uv sync --group docs
57
57
 
58
58
  - name: Build docs
59
59
  run: uv run mkdocs build
@@ -0,0 +1,39 @@
1
+ name: Dependabot auto-merge
2
+
3
+ on:
4
+ pull_request:
5
+
6
+ permissions:
7
+ contents: write
8
+ pull-requests: write
9
+
10
+ jobs:
11
+ auto-merge:
12
+ name: Auto-merge patch
13
+ if: github.actor == 'dependabot[bot]'
14
+ runs-on: ubuntu-24.04
15
+ steps:
16
+ - uses: dependabot/fetch-metadata@v3
17
+ id: metadata
18
+
19
+ - name: Generate app token
20
+ if: steps.metadata.outputs.update-type == 'version-update:semver-patch'
21
+ id: app-token
22
+ uses: actions/create-github-app-token@v3
23
+ with:
24
+ app-id: ${{ secrets.APP_ID }}
25
+ private-key: ${{ secrets.APP_PRIVATE_KEY }}
26
+
27
+ - name: Approve PR
28
+ if: steps.metadata.outputs.update-type == 'version-update:semver-patch'
29
+ run: gh pr review "$PR" --approve
30
+ env:
31
+ PR: ${{ github.event.pull_request.html_url }}
32
+ GH_TOKEN: ${{ steps.app-token.outputs.token }}
33
+
34
+ - name: Enable auto-merge
35
+ if: steps.metadata.outputs.update-type == 'version-update:semver-patch'
36
+ run: gh pr merge "$PR" --auto --squash
37
+ env:
38
+ PR: ${{ github.event.pull_request.html_url }}
39
+ GH_TOKEN: ${{ github.token }}
@@ -1,11 +1,13 @@
1
1
  name: Docs
2
2
 
3
3
  on:
4
+ push:
5
+ branches: [main]
4
6
  pull_request:
5
7
  branches: [main]
6
8
  workflow_dispatch: # Manual trigger
7
9
  workflow_run:
8
- workflows: ["Release"]
10
+ workflows: ["Publish"]
9
11
  types: [completed]
10
12
 
11
13
  permissions:
@@ -30,7 +32,7 @@ jobs:
30
32
  uses: astral-sh/setup-uv@v7
31
33
 
32
34
  - name: Install dependencies
33
- run: uv sync --extra docs
35
+ run: uv sync --group docs
34
36
 
35
37
  - name: Build docs
36
38
  run: uv run mkdocs build
@@ -0,0 +1,35 @@
1
+ name: Test Latest Dependencies
2
+
3
+ on:
4
+ schedule:
5
+ # Every Monday at 07:00 UTC
6
+ - cron: "0 7 * * 1"
7
+ workflow_dispatch:
8
+
9
+ jobs:
10
+ test-latest:
11
+ runs-on: ubuntu-latest
12
+ timeout-minutes: 30
13
+ strategy:
14
+ fail-fast: false
15
+ matrix:
16
+ python-version: ["3.10", "3.13"]
17
+
18
+ steps:
19
+ - uses: actions/checkout@v6
20
+
21
+ - name: Install uv
22
+ uses: astral-sh/setup-uv@v7
23
+
24
+ - name: Set up Python ${{ matrix.python-version }}
25
+ run: uv python install ${{ matrix.python-version }}
26
+
27
+ - name: Install with latest dependencies
28
+ run: uv sync --group dev --upgrade
29
+
30
+ - name: Test
31
+ run: uv run pytest --cov=xarray_plotly
32
+
33
+ - name: Print dependency versions
34
+ if: always()
35
+ run: uv pip list | grep -iE "xarray|plotly|pandas" || true
@@ -2,7 +2,9 @@ name: PR Title Check
2
2
 
3
3
  on:
4
4
  pull_request:
5
- types: [opened, edited, synchronize, reopened]
5
+ types: [opened, edited, reopened]
6
+ push:
7
+ branches: ['release-please--**']
6
8
 
7
9
  jobs:
8
10
  validate:
@@ -17,15 +19,12 @@ jobs:
17
19
  types: |
18
20
  feat
19
21
  fix
20
- docs
21
- style
22
- refactor
23
- perf
22
+ refac
24
23
  test
25
- build
26
- ci
24
+ docs
27
25
  chore
28
- revert
26
+ ci
27
+ perf
29
28
  # Scope is optional
30
29
  requireScope: false
31
30
  # Subject (description) requirements
@@ -0,0 +1,66 @@
1
+ name: Publish
2
+
3
+ on:
4
+ push:
5
+ tags: ["v*"]
6
+
7
+ concurrency:
8
+ group: publish-${{ github.ref_name }}
9
+ cancel-in-progress: false
10
+
11
+ permissions:
12
+ contents: write
13
+ id-token: write
14
+ attestations: write
15
+
16
+ jobs:
17
+ publish:
18
+ name: Build & publish to PyPI
19
+ runs-on: ubuntu-24.04
20
+ timeout-minutes: 10
21
+ environment:
22
+ name: pypi
23
+ url: https://pypi.org/project/xarray_plotly
24
+ steps:
25
+ - uses: actions/checkout@v6
26
+ with:
27
+ ref: ${{ github.ref_name }}
28
+ fetch-depth: 0
29
+
30
+ - uses: astral-sh/setup-uv@v7
31
+ with:
32
+ enable-cache: true
33
+
34
+ - uses: actions/setup-python@v6
35
+ with:
36
+ python-version: "3.12"
37
+
38
+ - name: Build
39
+ run: uv build
40
+
41
+ - uses: pypa/gh-action-pypi-publish@release/v1
42
+
43
+ github-release:
44
+ name: Create GitHub Release
45
+ needs: [publish]
46
+ if: github.event_name == 'push' && needs.publish.result == 'success'
47
+ runs-on: ubuntu-24.04
48
+ steps:
49
+ - uses: actions/checkout@v6
50
+ with:
51
+ ref: ${{ github.ref_name }}
52
+
53
+ - name: Create GitHub Release
54
+ run: |
55
+ if gh release view "$TAG" &>/dev/null; then
56
+ echo "Release $TAG already exists, skipping."
57
+ exit 0
58
+ fi
59
+ if [[ "$TAG" == *-* ]]; then
60
+ gh release create "$TAG" --generate-notes --prerelease
61
+ else
62
+ gh release create "$TAG" --generate-notes
63
+ fi
64
+ env:
65
+ GH_TOKEN: ${{ github.token }}
66
+ TAG: ${{ github.ref_name }}
@@ -0,0 +1,27 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+
7
+ permissions:
8
+ contents: write
9
+ pull-requests: write
10
+
11
+ jobs:
12
+ release-please:
13
+ name: Release Please
14
+ runs-on: ubuntu-24.04
15
+ steps:
16
+ - uses: actions/create-github-app-token@v3
17
+ id: app-token
18
+ with:
19
+ app-id: ${{ secrets.APP_ID }}
20
+ private-key: ${{ secrets.APP_PRIVATE_KEY }}
21
+
22
+ - uses: googleapis/release-please-action@v5
23
+ id: release
24
+ with:
25
+ token: ${{ steps.app-token.outputs.token }}
26
+ config-file: .release-please-config.json
27
+ manifest-file: .release-please-manifest.json
@@ -0,0 +1,18 @@
1
+ version: 2
2
+
3
+ mkdocs:
4
+ configuration: mkdocs.yml
5
+
6
+ build:
7
+ os: ubuntu-24.04
8
+ tools:
9
+ python: "3.13"
10
+ jobs:
11
+ pre_create_environment:
12
+ - asdf plugin add uv
13
+ - asdf install uv latest
14
+ - asdf global uv latest
15
+ create_environment:
16
+ - uv venv "${READTHEDOCS_VIRTUALENV_PATH}"
17
+ install:
18
+ - UV_PROJECT_ENVIRONMENT="${READTHEDOCS_VIRTUALENV_PATH}" uv sync --group docs
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "0.0.17"
3
+ }
@@ -0,0 +1,37 @@
1
+ # Changelog
2
+
3
+ ## [0.0.17](https://github.com/FBumann/xarray_plotly/compare/v0.0.16...v0.0.17) (2026-06-03)
4
+
5
+
6
+ ### Features
7
+
8
+ * **plotting:** shared axis labels for faceted plots ([#84](https://github.com/FBumann/xarray_plotly/issues/84)) ([5a3bef8](https://github.com/FBumann/xarray_plotly/commit/5a3bef863ce07dd1a1f69d79ece116c059782025))
9
+
10
+ ## [0.0.16](https://github.com/FBumann/xarray_plotly/compare/v0.0.15...v0.0.16) (2026-06-03)
11
+
12
+
13
+ ### Features
14
+
15
+ * **imshow:** support facet_row for subplot rows (plotly>=6.7) ([#82](https://github.com/FBumann/xarray_plotly/issues/82)) ([55b503b](https://github.com/FBumann/xarray_plotly/commit/55b503b37d598c845631c7b35adcea3a8f1e3ed9))
16
+ * **plotting:** add facet_titles kwarg to strip dim= prefix ([#77](https://github.com/FBumann/xarray_plotly/issues/77)) ([1433a95](https://github.com/FBumann/xarray_plotly/commit/1433a95c45cacb5f49c35e6f63794d668f6278ab))
17
+
18
+ ## [0.0.15](https://github.com/FBumann/xarray_plotly/compare/v0.0.14...v0.0.15) (2026-03-23)
19
+
20
+
21
+ ### Bug Fixes
22
+
23
+ * legend, style persistence, and axis ranges in combined figures ([#53](https://github.com/FBumann/xarray_plotly/issues/53)) ([28fccc3](https://github.com/FBumann/xarray_plotly/commit/28fccc3d32da334625e626096bfcbf78e3c65de6))
24
+
25
+ ## [0.0.14](https://github.com/FBumann/xarray_plotly/compare/v0.0.13...v0.0.14) (2026-03-09)
26
+
27
+
28
+ ### Bug Fixes
29
+
30
+ * continuous colorscale strings with discrete-only chart types ([#46](https://github.com/FBumann/xarray_plotly/issues/46)) ([cc865b5](https://github.com/FBumann/xarray_plotly/commit/cc865b5c1d2f7a2921b8e27c23546a883a974279))
31
+
32
+ ## [0.0.13](https://github.com/FBumann/xarray_plotly/compare/v0.0.12...v0.0.13) (2026-01-28)
33
+
34
+
35
+ ### Bug Fixes
36
+
37
+ * secondary y axis match and visibility when faceted ([#32](https://github.com/FBumann/xarray_plotly/issues/32)) ([10da229](https://github.com/FBumann/xarray_plotly/commit/10da229282377a229054321e8ff98e3fd6825939))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xarray_plotly
3
- Version: 0.0.14
3
+ Version: 0.0.17
4
4
  Summary: Interactive Plotly Express plotting accessor for xarray
5
5
  Author: Felix
6
6
  License: MIT
@@ -24,20 +24,6 @@ License-File: LICENSE
24
24
  Requires-Dist: xarray>=2023.1.0
25
25
  Requires-Dist: plotly>=5.0.0
26
26
  Requires-Dist: pandas>=1.5.0
27
- Provides-Extra: dev
28
- Requires-Dist: pytest==9.0.2; extra == "dev"
29
- Requires-Dist: pytest-cov==7.0.0; extra == "dev"
30
- Requires-Dist: mypy==1.19.1; extra == "dev"
31
- Requires-Dist: ruff==0.15.5; extra == "dev"
32
- Requires-Dist: pre-commit==4.5.1; extra == "dev"
33
- Requires-Dist: nbstripout==0.9.1; extra == "dev"
34
- Provides-Extra: docs
35
- Requires-Dist: mkdocs==1.6.1; extra == "docs"
36
- Requires-Dist: mkdocs-material==9.7.4; extra == "docs"
37
- Requires-Dist: mkdocstrings[python]==1.0.3; extra == "docs"
38
- Requires-Dist: mkdocs-jupyter==0.25.1; extra == "docs"
39
- Requires-Dist: mkdocs-plotly-plugin==0.1.3; extra == "docs"
40
- Requires-Dist: jupyter==1.1.1; extra == "docs"
41
27
  Dynamic: license-file
42
28
 
43
29
  # xarray_plotly
@@ -10,7 +10,8 @@
10
10
  "xarray-plotly provides helper functions to combine multiple figures:\n",
11
11
  "\n",
12
12
  "- **`overlay`**: Overlay traces on the same axes\n",
13
- "- **`add_secondary_y`**: Plot with two independent y-axes"
13
+ "- **`add_secondary_y`**: Plot with two independent y-axes\n",
14
+ "- **`subplots`**: Arrange independent figures in a grid"
14
15
  ]
15
16
  },
16
17
  {
@@ -23,7 +24,7 @@
23
24
  "import plotly.express as px\n",
24
25
  "import xarray as xr\n",
25
26
  "\n",
26
- "from xarray_plotly import add_secondary_y, config, overlay, xpx\n",
27
+ "from xarray_plotly import add_secondary_y, config, overlay, subplots, xpx\n",
27
28
  "\n",
28
29
  "config.notebook()"
29
30
  ]
@@ -440,6 +441,128 @@
440
441
  "cell_type": "markdown",
441
442
  "id": "27",
442
443
  "metadata": {},
444
+ "source": [
445
+ "## subplots\n",
446
+ "\n",
447
+ "Arrange independent figures side-by-side in a grid. Each figure gets its own\n",
448
+ "subplot cell with axes and title automatically derived from the source figure."
449
+ ]
450
+ },
451
+ {
452
+ "cell_type": "markdown",
453
+ "id": "28",
454
+ "metadata": {},
455
+ "source": [
456
+ "### Different Variables Side by Side"
457
+ ]
458
+ },
459
+ {
460
+ "cell_type": "code",
461
+ "execution_count": null,
462
+ "id": "29",
463
+ "metadata": {},
464
+ "outputs": [],
465
+ "source": [
466
+ "# One figure per variable, arranged in a row\n",
467
+ "us_pop = population.sel(country=\"United States\")\n",
468
+ "us_gdp = gdp_per_capita.sel(country=\"United States\")\n",
469
+ "us_life = life_expectancy.sel(country=\"United States\")\n",
470
+ "\n",
471
+ "pop_fig = xpx(us_pop).bar(title=\"Population\")\n",
472
+ "gdp_fig = xpx(us_gdp).line(title=\"GDP per Capita\")\n",
473
+ "life_fig = xpx(us_life).line(title=\"Life Expectancy\")\n",
474
+ "\n",
475
+ "grid = subplots(pop_fig, gdp_fig, life_fig, cols=3)\n",
476
+ "grid.update_layout(title=\"United States Overview\", height=350, showlegend=False)\n",
477
+ "grid"
478
+ ]
479
+ },
480
+ {
481
+ "cell_type": "markdown",
482
+ "id": "30",
483
+ "metadata": {},
484
+ "source": [
485
+ "### 2x2 Grid\n",
486
+ "\n",
487
+ "Use `cols=2` and pass four figures for a 2x2 layout."
488
+ ]
489
+ },
490
+ {
491
+ "cell_type": "code",
492
+ "execution_count": null,
493
+ "id": "31",
494
+ "metadata": {},
495
+ "outputs": [],
496
+ "source": [
497
+ "# One subplot per country\n",
498
+ "fig_us = xpx(population.sel(country=\"United States\")).bar(title=\"United States\")\n",
499
+ "fig_cn = xpx(population.sel(country=\"China\")).bar(title=\"China\")\n",
500
+ "fig_de = xpx(population.sel(country=\"Germany\")).bar(title=\"Germany\")\n",
501
+ "fig_br = xpx(population.sel(country=\"Brazil\")).bar(title=\"Brazil\")\n",
502
+ "\n",
503
+ "grid = subplots(fig_us, fig_cn, fig_de, fig_br, cols=2)\n",
504
+ "grid.update_layout(height=500, showlegend=False)\n",
505
+ "grid"
506
+ ]
507
+ },
508
+ {
509
+ "cell_type": "markdown",
510
+ "id": "32",
511
+ "metadata": {},
512
+ "source": [
513
+ "### Mixed Chart Types\n",
514
+ "\n",
515
+ "Each cell can use a different chart type. Subplot titles fall back to the\n",
516
+ "y-axis label when no explicit title is set."
517
+ ]
518
+ },
519
+ {
520
+ "cell_type": "code",
521
+ "execution_count": null,
522
+ "id": "33",
523
+ "metadata": {},
524
+ "outputs": [],
525
+ "source": [
526
+ "# No explicit title — subplot titles come from the y-axis label (DataArray name)\n",
527
+ "pop_bar = xpx(us_pop).bar()\n",
528
+ "gdp_line = xpx(us_gdp).line()\n",
529
+ "life_scatter = xpx(us_life).scatter()\n",
530
+ "\n",
531
+ "grid = subplots(pop_bar, gdp_line, life_scatter, cols=3)\n",
532
+ "grid.update_layout(height=350, showlegend=False)\n",
533
+ "grid"
534
+ ]
535
+ },
536
+ {
537
+ "cell_type": "markdown",
538
+ "id": "34",
539
+ "metadata": {},
540
+ "source": [
541
+ "### With Facets\n",
542
+ "\n",
543
+ "Faceted figures can be composed — each figure's internal subplots are remapped into the grid cell."
544
+ ]
545
+ },
546
+ {
547
+ "cell_type": "code",
548
+ "execution_count": null,
549
+ "id": "35",
550
+ "metadata": {},
551
+ "outputs": [],
552
+ "source": [
553
+ "# Faceted bar on top, faceted line below\n",
554
+ "pop_faceted = xpx(population).bar(facet_col=\"country\")\n",
555
+ "gdp_faceted = xpx(gdp_per_capita).line(facet_col=\"country\")\n",
556
+ "\n",
557
+ "grid = subplots(pop_faceted, gdp_faceted, cols=1)\n",
558
+ "grid.update_layout(height=600, showlegend=False)\n",
559
+ "grid"
560
+ ]
561
+ },
562
+ {
563
+ "cell_type": "markdown",
564
+ "id": "36",
565
+ "metadata": {},
443
566
  "source": [
444
567
  "---\n",
445
568
  "\n",
@@ -450,7 +573,7 @@
450
573
  },
451
574
  {
452
575
  "cell_type": "markdown",
453
- "id": "28",
576
+ "id": "37",
454
577
  "metadata": {},
455
578
  "source": [
456
579
  "### overlay: Mismatched Facet Structure\n",
@@ -461,7 +584,7 @@
461
584
  {
462
585
  "cell_type": "code",
463
586
  "execution_count": null,
464
- "id": "29",
587
+ "id": "38",
465
588
  "metadata": {},
466
589
  "outputs": [],
467
590
  "source": [
@@ -479,7 +602,7 @@
479
602
  },
480
603
  {
481
604
  "cell_type": "markdown",
482
- "id": "30",
605
+ "id": "39",
483
606
  "metadata": {},
484
607
  "source": [
485
608
  "### overlay: Animated Overlay on Static Base\n",
@@ -490,7 +613,7 @@
490
613
  {
491
614
  "cell_type": "code",
492
615
  "execution_count": null,
493
- "id": "31",
616
+ "id": "40",
494
617
  "metadata": {},
495
618
  "outputs": [],
496
619
  "source": [
@@ -508,7 +631,7 @@
508
631
  },
509
632
  {
510
633
  "cell_type": "markdown",
511
- "id": "32",
634
+ "id": "41",
512
635
  "metadata": {},
513
636
  "source": [
514
637
  "### overlay: Mismatched Animation Frames\n",
@@ -519,7 +642,7 @@
519
642
  {
520
643
  "cell_type": "code",
521
644
  "execution_count": null,
522
- "id": "33",
645
+ "id": "42",
523
646
  "metadata": {},
524
647
  "outputs": [],
525
648
  "source": [
@@ -535,7 +658,7 @@
535
658
  },
536
659
  {
537
660
  "cell_type": "markdown",
538
- "id": "34",
661
+ "id": "43",
539
662
  "metadata": {},
540
663
  "source": [
541
664
  "### add_secondary_y: Mismatched Facet Structure\n",
@@ -546,7 +669,7 @@
546
669
  {
547
670
  "cell_type": "code",
548
671
  "execution_count": null,
549
- "id": "35",
672
+ "id": "44",
550
673
  "metadata": {},
551
674
  "outputs": [],
552
675
  "source": [
@@ -564,7 +687,7 @@
564
687
  },
565
688
  {
566
689
  "cell_type": "markdown",
567
- "id": "36",
690
+ "id": "45",
568
691
  "metadata": {},
569
692
  "source": [
570
693
  "### add_secondary_y: Animated Secondary on Static Base\n",
@@ -575,7 +698,7 @@
575
698
  {
576
699
  "cell_type": "code",
577
700
  "execution_count": null,
578
- "id": "37",
701
+ "id": "46",
579
702
  "metadata": {},
580
703
  "outputs": [],
581
704
  "source": [
@@ -593,7 +716,7 @@
593
716
  },
594
717
  {
595
718
  "cell_type": "markdown",
596
- "id": "38",
719
+ "id": "47",
597
720
  "metadata": {},
598
721
  "source": [
599
722
  "### add_secondary_y: Mismatched Animation Frames"
@@ -602,7 +725,7 @@
602
725
  {
603
726
  "cell_type": "code",
604
727
  "execution_count": null,
605
- "id": "39",
728
+ "id": "48",
606
729
  "metadata": {},
607
730
  "outputs": [],
608
731
  "source": [
@@ -618,7 +741,7 @@
618
741
  },
619
742
  {
620
743
  "cell_type": "markdown",
621
- "id": "40",
744
+ "id": "49",
622
745
  "metadata": {},
623
746
  "source": [
624
747
  "## Summary\n",
@@ -626,7 +749,8 @@
626
749
  "| Function | Facets | Animation | Static + Animated |\n",
627
750
  "|----------|--------|-----------|-------------------|\n",
628
751
  "| `overlay` | Yes (must match) | Yes (frames must match) | Static overlay on animated base OK |\n",
629
- "| `add_secondary_y` | Yes (must match) | Yes (frames must match) | Static secondary on animated base OK |"
752
+ "| `add_secondary_y` | Yes (must match) | Yes (frames must match) | Static secondary on animated base OK |\n",
753
+ "| `subplots` | Yes (remapped into cells) | No | N/A |"
630
754
  ]
631
755
  }
632
756
  ],
@@ -134,7 +134,7 @@
134
134
  "| line | x, color, line_dash, facet_col, facet_row, animation_frame |\n",
135
135
  "| scatter | x, color, symbol, facet_col, facet_row, animation_frame |\n",
136
136
  "| bar | x, color, facet_col, facet_row, animation_frame |\n",
137
- "| imshow | x, y, facet_col, facet_row, animation_frame |"
137
+ "| imshow | y, x, facet_col, facet_row, animation_frame |"
138
138
  ]
139
139
  },
140
140
  {
@@ -186,6 +186,16 @@
186
186
  "xpx(data_3d).line(x=\"year\", facet_col=\"metric\", facet_row=\"country\")"
187
187
  ]
188
188
  },
189
+ {
190
+ "cell_type": "code",
191
+ "execution_count": null,
192
+ "metadata": {},
193
+ "outputs": [],
194
+ "source": [
195
+ "# Heatmap grids: imshow supports facet_col and facet_row (requires plotly>=6.7)\n",
196
+ "xpx(data_3d).imshow(facet_row=\"metric\")"
197
+ ]
198
+ },
189
199
  {
190
200
  "cell_type": "markdown",
191
201
  "metadata": {},
@@ -30,23 +30,24 @@ Homepage = "https://github.com/FBumann/xarray_plotly"
30
30
  Documentation = "https://fbumann.github.io/xarray_plotly"
31
31
  Repository = "https://github.com/FBumann/xarray_plotly"
32
32
 
33
- [project.optional-dependencies]
34
- dev = [
35
- "pytest==9.0.2",
36
- "pytest-cov==7.0.0",
37
- "mypy==1.19.1",
38
- "ruff==0.15.5",
39
- "pre-commit==4.5.1",
40
- "nbstripout==0.9.1",
41
- ]
33
+ [dependency-groups]
42
34
  docs = [
43
35
  "mkdocs==1.6.1",
44
- "mkdocs-material==9.7.4",
45
- "mkdocstrings[python]==1.0.3",
46
- "mkdocs-jupyter==0.25.1",
36
+ "mkdocs-material==9.7.6",
37
+ "mkdocstrings[python]==1.0.4",
38
+ "mkdocs-jupyter==0.26.2",
47
39
  "mkdocs-plotly-plugin==0.1.3",
48
40
  "jupyter==1.1.1",
49
41
  ]
42
+ dev = [
43
+ {include-group = "docs"},
44
+ "pytest==9.0.3",
45
+ "pytest-cov==7.1.0",
46
+ "mypy==2.0.0",
47
+ "ruff==0.15.12",
48
+ "pre-commit==4.6.0",
49
+ "nbstripout==0.9.1",
50
+ ]
50
51
 
51
52
  [project.entry-points."xarray.backends"]
52
53
  # Entry point for xarray to auto-register the accessor (xarray >= 2024.01)