xarray-plotly 0.0.12__tar.gz → 0.0.14__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.
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/.github/dependabot.yml +4 -0
- xarray_plotly-0.0.14/.github/workflows/pr-title.yml +33 -0
- xarray_plotly-0.0.14/.github/workflows/release-please.yml +42 -0
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/.github/workflows/release.yml +8 -11
- xarray_plotly-0.0.14/.release-please-config.json +13 -0
- xarray_plotly-0.0.14/.release-please-manifest.json +3 -0
- xarray_plotly-0.0.14/CHANGELOG.md +15 -0
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/CONTRIBUTING.md +4 -7
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/PKG-INFO +24 -5
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/README.md +19 -0
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/pyproject.toml +4 -4
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/tests/test_figures.py +2 -2
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/xarray_plotly/common.py +28 -2
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/xarray_plotly/figures.py +23 -8
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/xarray_plotly/plotting.py +5 -5
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/xarray_plotly.egg-info/PKG-INFO +24 -5
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/xarray_plotly.egg-info/SOURCES.txt +5 -0
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/xarray_plotly.egg-info/requires.txt +4 -4
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/.github/workflows/ci.yml +0 -0
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/.github/workflows/dependabot-auto-merge.yml +0 -0
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/.github/workflows/docs.yml +0 -0
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/.gitignore +0 -0
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/.pre-commit-config.yaml +0 -0
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/LICENSE +0 -0
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/docs/api.md +0 -0
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/docs/examples/combining.ipynb +0 -0
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/docs/examples/datasets.ipynb +0 -0
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/docs/examples/dimensions.ipynb +0 -0
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/docs/examples/fast_bar.ipynb +0 -0
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/docs/examples/figure.ipynb +0 -0
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/docs/examples/kwargs.ipynb +0 -0
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/docs/examples/manipulation.ipynb +0 -0
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/docs/examples/plot-types.ipynb +0 -0
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/docs/getting-started.ipynb +0 -0
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/docs/index.md +0 -0
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/mkdocs.yml +0 -0
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/setup.cfg +0 -0
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/tests/__init__.py +0 -0
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/tests/test_accessor.py +0 -0
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/tests/test_common.py +0 -0
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/tests/test_config.py +0 -0
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/xarray_plotly/__init__.py +0 -0
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/xarray_plotly/accessor.py +0 -0
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/xarray_plotly/config.py +0 -0
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/xarray_plotly/py.typed +0 -0
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/xarray_plotly.egg-info/dependency_links.txt +0 -0
- {xarray_plotly-0.0.12 → xarray_plotly-0.0.14}/xarray_plotly.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
name: PR Title Check
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
types: [opened, edited, synchronize, reopened]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
validate:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
steps:
|
|
11
|
+
- uses: amannn/action-semantic-pull-request@v6
|
|
12
|
+
env:
|
|
13
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
14
|
+
with:
|
|
15
|
+
# Require conventional commit format: type(scope): description
|
|
16
|
+
# Types allowed (default set)
|
|
17
|
+
types: |
|
|
18
|
+
feat
|
|
19
|
+
fix
|
|
20
|
+
docs
|
|
21
|
+
style
|
|
22
|
+
refactor
|
|
23
|
+
perf
|
|
24
|
+
test
|
|
25
|
+
build
|
|
26
|
+
ci
|
|
27
|
+
chore
|
|
28
|
+
revert
|
|
29
|
+
# Scope is optional
|
|
30
|
+
requireScope: false
|
|
31
|
+
# Subject (description) requirements
|
|
32
|
+
subjectPattern: ^.+$
|
|
33
|
+
subjectPatternError: "PR title must have a description after the type"
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
name: Release Please
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: write
|
|
10
|
+
pull-requests: write
|
|
11
|
+
id-token: write # for PyPI trusted publishing
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
release-please:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
outputs:
|
|
17
|
+
release_created: ${{ steps.release.outputs.release_created }}
|
|
18
|
+
tag_name: ${{ steps.release.outputs.tag_name }}
|
|
19
|
+
steps:
|
|
20
|
+
- uses: googleapis/release-please-action@v4
|
|
21
|
+
id: release
|
|
22
|
+
with:
|
|
23
|
+
config-file: .release-please-config.json
|
|
24
|
+
manifest-file: .release-please-manifest.json
|
|
25
|
+
|
|
26
|
+
publish:
|
|
27
|
+
needs: release-please
|
|
28
|
+
if: ${{ needs.release-please.outputs.release_created }}
|
|
29
|
+
runs-on: ubuntu-latest
|
|
30
|
+
permissions:
|
|
31
|
+
id-token: write
|
|
32
|
+
steps:
|
|
33
|
+
- uses: actions/checkout@v6
|
|
34
|
+
|
|
35
|
+
- name: Install uv
|
|
36
|
+
uses: astral-sh/setup-uv@v7
|
|
37
|
+
|
|
38
|
+
- name: Build package
|
|
39
|
+
run: uv build
|
|
40
|
+
|
|
41
|
+
- name: Publish to PyPI
|
|
42
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -1,19 +1,22 @@
|
|
|
1
|
-
name: Release
|
|
1
|
+
name: Release (Manual)
|
|
2
2
|
|
|
3
3
|
on:
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
tag:
|
|
7
|
+
description: 'Tag to release (e.g., v0.0.13)'
|
|
8
|
+
required: true
|
|
7
9
|
|
|
8
10
|
jobs:
|
|
9
11
|
release:
|
|
10
12
|
runs-on: ubuntu-latest
|
|
11
13
|
permissions:
|
|
12
14
|
id-token: write # for trusted publishing
|
|
13
|
-
contents: write # for creating GitHub release
|
|
14
15
|
|
|
15
16
|
steps:
|
|
16
17
|
- uses: actions/checkout@v6
|
|
18
|
+
with:
|
|
19
|
+
ref: ${{ inputs.tag }}
|
|
17
20
|
|
|
18
21
|
- name: Install uv
|
|
19
22
|
uses: astral-sh/setup-uv@v7
|
|
@@ -23,9 +26,3 @@ jobs:
|
|
|
23
26
|
|
|
24
27
|
- name: Publish to PyPI
|
|
25
28
|
uses: pypa/gh-action-pypi-publish@release/v1
|
|
26
|
-
|
|
27
|
-
- name: Create GitHub Release
|
|
28
|
-
uses: softprops/action-gh-release@v2
|
|
29
|
-
with:
|
|
30
|
-
generate_release_notes: true
|
|
31
|
-
files: dist/*
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json",
|
|
3
|
+
"bootstrap-sha": "3c1b9d991a58c2369fe4817ad2f3d555aaab969e",
|
|
4
|
+
"include-component-in-tag": false,
|
|
5
|
+
"packages": {
|
|
6
|
+
".": {
|
|
7
|
+
"release-type": "simple",
|
|
8
|
+
"package-name": "xarray_plotly",
|
|
9
|
+
"bump-patch-for-minor-pre-major": true,
|
|
10
|
+
"changelog-path": "CHANGELOG.md"
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [0.0.14](https://github.com/FBumann/xarray_plotly/compare/v0.0.13...v0.0.14) (2026-03-09)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* 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))
|
|
9
|
+
|
|
10
|
+
## [0.0.13](https://github.com/FBumann/xarray_plotly/compare/v0.0.12...v0.0.13) (2026-01-28)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* 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))
|
|
@@ -42,11 +42,8 @@ uv run ruff format .
|
|
|
42
42
|
|
|
43
43
|
## Releases
|
|
44
44
|
|
|
45
|
-
Releases are automated via
|
|
45
|
+
Releases are fully automated via [Release Please](https://github.com/googleapis/release-please).
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
2. Push: `git push && git push --tags`
|
|
51
|
-
|
|
52
|
-
The CI will automatically publish to PyPI and deploy updated docs.
|
|
47
|
+
1. Merge PRs to `main` using [conventional commit](https://www.conventionalcommits.org/) prefixes (`feat:`, `fix:`, etc.)
|
|
48
|
+
2. Release Please automatically creates/updates a release PR with changelog and version bump
|
|
49
|
+
3. Merge the release PR to publish to PyPI and deploy updated docs
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: xarray_plotly
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.14
|
|
4
4
|
Summary: Interactive Plotly Express plotting accessor for xarray
|
|
5
5
|
Author: Felix
|
|
6
6
|
License: MIT
|
|
@@ -28,13 +28,13 @@ Provides-Extra: dev
|
|
|
28
28
|
Requires-Dist: pytest==9.0.2; extra == "dev"
|
|
29
29
|
Requires-Dist: pytest-cov==7.0.0; extra == "dev"
|
|
30
30
|
Requires-Dist: mypy==1.19.1; extra == "dev"
|
|
31
|
-
Requires-Dist: ruff==0.
|
|
31
|
+
Requires-Dist: ruff==0.15.5; extra == "dev"
|
|
32
32
|
Requires-Dist: pre-commit==4.5.1; extra == "dev"
|
|
33
|
-
Requires-Dist: nbstripout==0.9.
|
|
33
|
+
Requires-Dist: nbstripout==0.9.1; extra == "dev"
|
|
34
34
|
Provides-Extra: docs
|
|
35
35
|
Requires-Dist: mkdocs==1.6.1; extra == "docs"
|
|
36
|
-
Requires-Dist: mkdocs-material==9.7.
|
|
37
|
-
Requires-Dist: mkdocstrings[python]==1.0.
|
|
36
|
+
Requires-Dist: mkdocs-material==9.7.4; extra == "docs"
|
|
37
|
+
Requires-Dist: mkdocstrings[python]==1.0.3; extra == "docs"
|
|
38
38
|
Requires-Dist: mkdocs-jupyter==0.25.1; extra == "docs"
|
|
39
39
|
Requires-Dist: mkdocs-plotly-plugin==0.1.3; extra == "docs"
|
|
40
40
|
Requires-Dist: jupyter==1.1.1; extra == "docs"
|
|
@@ -84,6 +84,25 @@ fig = xpx(da).line()
|
|
|
84
84
|
|
|
85
85
|
Full documentation: [https://fbumann.github.io/xarray_plotly](https://fbumann.github.io/xarray_plotly)
|
|
86
86
|
|
|
87
|
+
## Roadmap
|
|
88
|
+
|
|
89
|
+
Planned additions (contributions welcome):
|
|
90
|
+
|
|
91
|
+
**New plot types**
|
|
92
|
+
- `histogram()` — distribution of DataArray values
|
|
93
|
+
- `violin()` — richer distribution visualization than box plots
|
|
94
|
+
- `density_heatmap()` — 2D histograms (x and y as dimensions)
|
|
95
|
+
- `density_contour()` — 2D density contours (x and y as dimensions)
|
|
96
|
+
|
|
97
|
+
**Enhancements**
|
|
98
|
+
- WebGL rendering option for `line()` and `scatter()` (large datasets)
|
|
99
|
+
|
|
100
|
+
**Figure utilities** (facet/animation-aware)
|
|
101
|
+
- `fill_between()` — fill area between two traces (uncertainty bands)
|
|
102
|
+
- `sync_axes()` — consistent axis ranges across facets and animation frames
|
|
103
|
+
- `add_secondary_x()` — secondary x-axis (like `add_secondary_y()`)
|
|
104
|
+
- `stack()` — vertically stack separate figures into subplots
|
|
105
|
+
|
|
87
106
|
## License
|
|
88
107
|
|
|
89
108
|
MIT
|
|
@@ -42,6 +42,25 @@ fig = xpx(da).line()
|
|
|
42
42
|
|
|
43
43
|
Full documentation: [https://fbumann.github.io/xarray_plotly](https://fbumann.github.io/xarray_plotly)
|
|
44
44
|
|
|
45
|
+
## Roadmap
|
|
46
|
+
|
|
47
|
+
Planned additions (contributions welcome):
|
|
48
|
+
|
|
49
|
+
**New plot types**
|
|
50
|
+
- `histogram()` — distribution of DataArray values
|
|
51
|
+
- `violin()` — richer distribution visualization than box plots
|
|
52
|
+
- `density_heatmap()` — 2D histograms (x and y as dimensions)
|
|
53
|
+
- `density_contour()` — 2D density contours (x and y as dimensions)
|
|
54
|
+
|
|
55
|
+
**Enhancements**
|
|
56
|
+
- WebGL rendering option for `line()` and `scatter()` (large datasets)
|
|
57
|
+
|
|
58
|
+
**Figure utilities** (facet/animation-aware)
|
|
59
|
+
- `fill_between()` — fill area between two traces (uncertainty bands)
|
|
60
|
+
- `sync_axes()` — consistent axis ranges across facets and animation frames
|
|
61
|
+
- `add_secondary_x()` — secondary x-axis (like `add_secondary_y()`)
|
|
62
|
+
- `stack()` — vertically stack separate figures into subplots
|
|
63
|
+
|
|
45
64
|
## License
|
|
46
65
|
|
|
47
66
|
MIT
|
|
@@ -35,14 +35,14 @@ dev = [
|
|
|
35
35
|
"pytest==9.0.2",
|
|
36
36
|
"pytest-cov==7.0.0",
|
|
37
37
|
"mypy==1.19.1",
|
|
38
|
-
"ruff==0.
|
|
38
|
+
"ruff==0.15.5",
|
|
39
39
|
"pre-commit==4.5.1",
|
|
40
|
-
"nbstripout==0.9.
|
|
40
|
+
"nbstripout==0.9.1",
|
|
41
41
|
]
|
|
42
42
|
docs = [
|
|
43
43
|
"mkdocs==1.6.1",
|
|
44
|
-
"mkdocs-material==9.7.
|
|
45
|
-
"mkdocstrings[python]==1.0.
|
|
44
|
+
"mkdocs-material==9.7.4",
|
|
45
|
+
"mkdocstrings[python]==1.0.3",
|
|
46
46
|
"mkdocs-jupyter==0.25.1",
|
|
47
47
|
"mkdocs-plotly-plugin==0.1.3",
|
|
48
48
|
"jupyter==1.1.1",
|
|
@@ -505,8 +505,8 @@ class TestAddSecondaryYFacets:
|
|
|
505
505
|
|
|
506
506
|
combined = add_secondary_y(base, secondary, secondary_y_title="Custom Title")
|
|
507
507
|
|
|
508
|
-
# Title should be on the
|
|
509
|
-
assert combined.layout.
|
|
508
|
+
# Title should be on the rightmost secondary axis (yaxis6 for 3 facets)
|
|
509
|
+
assert combined.layout.yaxis6.title.text == "Custom Title"
|
|
510
510
|
|
|
511
511
|
|
|
512
512
|
class TestAddSecondaryYAnimation:
|
|
@@ -13,7 +13,7 @@ from xarray_plotly.config import DEFAULT_SLOT_ORDERS, _options
|
|
|
13
13
|
|
|
14
14
|
if TYPE_CHECKING:
|
|
15
15
|
import pandas as pd
|
|
16
|
-
from xarray import DataArray
|
|
16
|
+
from xarray import DataArray, Dataset
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class _AUTO:
|
|
@@ -251,7 +251,21 @@ def _get_qualitative_scale_names() -> frozenset[str]:
|
|
|
251
251
|
)
|
|
252
252
|
|
|
253
253
|
|
|
254
|
-
def
|
|
254
|
+
def _sample_colorscale(name: str, n: int) -> list[str]:
|
|
255
|
+
"""Sample *n* evenly-spaced colors from a named Plotly colorscale."""
|
|
256
|
+
scale = px.colors.get_colorscale(name)
|
|
257
|
+
samplepoints = [i / max(n - 1, 1) for i in range(n)]
|
|
258
|
+
result: list[str] = px.colors.sample_colorscale(scale, samplepoints)
|
|
259
|
+
return result
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def resolve_colors(
|
|
263
|
+
colors: Colors,
|
|
264
|
+
px_kwargs: dict[str, Any],
|
|
265
|
+
*,
|
|
266
|
+
color_dim: Hashable | None = None,
|
|
267
|
+
darray: DataArray | Dataset | None = None,
|
|
268
|
+
) -> dict[str, Any]:
|
|
255
269
|
"""Map unified `colors` parameter to appropriate Plotly px_kwargs.
|
|
256
270
|
|
|
257
271
|
Direct color_* kwargs take precedence and trigger a warning if
|
|
@@ -260,6 +274,14 @@ def resolve_colors(colors: Colors, px_kwargs: dict[str, Any]) -> dict[str, Any]:
|
|
|
260
274
|
Args:
|
|
261
275
|
colors: Unified color specification (str, list, dict, or None).
|
|
262
276
|
px_kwargs: Existing kwargs to pass to Plotly Express.
|
|
277
|
+
color_dim: Dimension name used for discrete color grouping.
|
|
278
|
+
When provided together with *darray*, a continuous colorscale
|
|
279
|
+
string is sampled into a discrete sequence whose length
|
|
280
|
+
matches the number of coordinates along this dimension.
|
|
281
|
+
Use for chart types that only accept discrete color
|
|
282
|
+
parameters (line, area, box, pie).
|
|
283
|
+
darray: Source DataArray or Dataset; used with *color_dim* to
|
|
284
|
+
determine the number of discrete colors to sample.
|
|
263
285
|
|
|
264
286
|
Returns:
|
|
265
287
|
Updated px_kwargs with color parameters injected.
|
|
@@ -284,6 +306,10 @@ def resolve_colors(colors: Colors, px_kwargs: dict[str, Any]) -> dict[str, Any]:
|
|
|
284
306
|
# Check if it's a qualitative (discrete) palette name
|
|
285
307
|
if colors in _get_qualitative_scale_names():
|
|
286
308
|
px_kwargs["color_discrete_sequence"] = getattr(px.colors.qualitative, colors)
|
|
309
|
+
elif color_dim is not None and darray is not None:
|
|
310
|
+
# Sample from continuous scale into a discrete sequence
|
|
311
|
+
n = darray.sizes[color_dim]
|
|
312
|
+
px_kwargs["color_discrete_sequence"] = _sample_colorscale(colors, n)
|
|
287
313
|
else:
|
|
288
314
|
# Assume continuous scale
|
|
289
315
|
px_kwargs["color_continuous_scale"] = colors
|
|
@@ -308,6 +308,13 @@ def add_secondary_y(
|
|
|
308
308
|
# Build mapping from primary y-axes to secondary y-axes
|
|
309
309
|
y_mapping = _build_secondary_y_mapping(base_axes)
|
|
310
310
|
|
|
311
|
+
# Build x-y correspondence from base_axes (which x-axis pairs with which y-axis)
|
|
312
|
+
x_for_y = {yaxis: xaxis for xaxis, yaxis in base_axes}
|
|
313
|
+
|
|
314
|
+
# Find the rightmost x-axis (highest number) to determine which secondary axis shows ticks
|
|
315
|
+
rightmost_x = max(x_for_y.values(), key=lambda x: int(x[1:]) if x != "x" else 1)
|
|
316
|
+
rightmost_primary_y = next(y for y, x in x_for_y.items() if x == rightmost_x)
|
|
317
|
+
|
|
311
318
|
# Create new figure with base's layout
|
|
312
319
|
combined = go.Figure(layout=copy.deepcopy(base.layout))
|
|
313
320
|
|
|
@@ -322,24 +329,32 @@ def add_secondary_y(
|
|
|
322
329
|
trace_copy.yaxis = y_mapping[original_yaxis]
|
|
323
330
|
combined.add_trace(trace_copy)
|
|
324
331
|
|
|
332
|
+
# Get the rightmost secondary y-axis name for linking
|
|
333
|
+
rightmost_secondary_y = y_mapping[rightmost_primary_y]
|
|
334
|
+
|
|
325
335
|
# Configure secondary y-axes
|
|
326
336
|
for primary_yaxis, secondary_yaxis in y_mapping.items():
|
|
327
|
-
|
|
337
|
+
is_rightmost = primary_yaxis == rightmost_primary_y
|
|
338
|
+
|
|
339
|
+
# Get title - only set on rightmost secondary axis
|
|
328
340
|
title = None
|
|
329
|
-
if
|
|
330
|
-
|
|
331
|
-
if primary_yaxis == "y":
|
|
341
|
+
if is_rightmost:
|
|
342
|
+
if secondary_y_title is not None:
|
|
332
343
|
title = secondary_y_title
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
title = secondary.layout.yaxis.title.text
|
|
344
|
+
elif secondary.layout.yaxis and secondary.layout.yaxis.title:
|
|
345
|
+
title = secondary.layout.yaxis.title.text
|
|
336
346
|
|
|
337
347
|
# Configure the secondary axis
|
|
348
|
+
# Anchor to the corresponding x-axis so it appears on the right side of its subplot
|
|
338
349
|
axis_config = {
|
|
339
350
|
"title": title,
|
|
340
351
|
"overlaying": primary_yaxis,
|
|
341
352
|
"side": "right",
|
|
342
|
-
"anchor":
|
|
353
|
+
"anchor": x_for_y[primary_yaxis],
|
|
354
|
+
# Only show ticks on the rightmost secondary axis
|
|
355
|
+
"showticklabels": is_rightmost,
|
|
356
|
+
# Link non-rightmost axes to the rightmost for consistent scaling
|
|
357
|
+
"matches": None if is_rightmost else rightmost_secondary_y,
|
|
343
358
|
}
|
|
344
359
|
# Remove None values
|
|
345
360
|
axis_config = {k: v for k, v in axis_config.items() if v is not None}
|
|
@@ -82,7 +82,6 @@ def line(
|
|
|
82
82
|
-------
|
|
83
83
|
plotly.graph_objects.Figure
|
|
84
84
|
"""
|
|
85
|
-
px_kwargs = resolve_colors(colors, px_kwargs)
|
|
86
85
|
slots = assign_slots(
|
|
87
86
|
list(darray.dims),
|
|
88
87
|
"line",
|
|
@@ -94,6 +93,7 @@ def line(
|
|
|
94
93
|
facet_row=facet_row,
|
|
95
94
|
animation_frame=animation_frame,
|
|
96
95
|
)
|
|
96
|
+
px_kwargs = resolve_colors(colors, px_kwargs, color_dim=slots.get("color"), darray=darray)
|
|
97
97
|
|
|
98
98
|
df = to_dataframe(darray)
|
|
99
99
|
value_col = get_value_col(darray)
|
|
@@ -329,7 +329,6 @@ def fast_bar(
|
|
|
329
329
|
-------
|
|
330
330
|
plotly.graph_objects.Figure
|
|
331
331
|
"""
|
|
332
|
-
px_kwargs = resolve_colors(colors, px_kwargs)
|
|
333
332
|
slots = assign_slots(
|
|
334
333
|
list(darray.dims),
|
|
335
334
|
"fast_bar",
|
|
@@ -339,6 +338,7 @@ def fast_bar(
|
|
|
339
338
|
facet_row=facet_row,
|
|
340
339
|
animation_frame=animation_frame,
|
|
341
340
|
)
|
|
341
|
+
px_kwargs = resolve_colors(colors, px_kwargs, color_dim=slots.get("color"), darray=darray)
|
|
342
342
|
|
|
343
343
|
df = to_dataframe(darray)
|
|
344
344
|
value_col = get_value_col(darray)
|
|
@@ -410,7 +410,6 @@ def area(
|
|
|
410
410
|
-------
|
|
411
411
|
plotly.graph_objects.Figure
|
|
412
412
|
"""
|
|
413
|
-
px_kwargs = resolve_colors(colors, px_kwargs)
|
|
414
413
|
slots = assign_slots(
|
|
415
414
|
list(darray.dims),
|
|
416
415
|
"area",
|
|
@@ -421,6 +420,7 @@ def area(
|
|
|
421
420
|
facet_row=facet_row,
|
|
422
421
|
animation_frame=animation_frame,
|
|
423
422
|
)
|
|
423
|
+
px_kwargs = resolve_colors(colors, px_kwargs, color_dim=slots.get("color"), darray=darray)
|
|
424
424
|
|
|
425
425
|
df = to_dataframe(darray)
|
|
426
426
|
value_col = get_value_col(darray)
|
|
@@ -487,7 +487,6 @@ def box(
|
|
|
487
487
|
-------
|
|
488
488
|
plotly.graph_objects.Figure
|
|
489
489
|
"""
|
|
490
|
-
px_kwargs = resolve_colors(colors, px_kwargs)
|
|
491
490
|
slots = assign_slots(
|
|
492
491
|
list(darray.dims),
|
|
493
492
|
"box",
|
|
@@ -498,6 +497,7 @@ def box(
|
|
|
498
497
|
facet_row=facet_row,
|
|
499
498
|
animation_frame=animation_frame,
|
|
500
499
|
)
|
|
500
|
+
px_kwargs = resolve_colors(colors, px_kwargs, color_dim=slots.get("color"), darray=darray)
|
|
501
501
|
|
|
502
502
|
df = to_dataframe(darray)
|
|
503
503
|
value_col = get_value_col(darray)
|
|
@@ -746,7 +746,6 @@ def pie(
|
|
|
746
746
|
-------
|
|
747
747
|
plotly.graph_objects.Figure
|
|
748
748
|
"""
|
|
749
|
-
px_kwargs = resolve_colors(colors, px_kwargs)
|
|
750
749
|
slots = assign_slots(
|
|
751
750
|
list(darray.dims),
|
|
752
751
|
"pie",
|
|
@@ -754,6 +753,7 @@ def pie(
|
|
|
754
753
|
facet_col=facet_col,
|
|
755
754
|
facet_row=facet_row,
|
|
756
755
|
)
|
|
756
|
+
px_kwargs = resolve_colors(colors, px_kwargs, color_dim=slots.get("names"), darray=darray)
|
|
757
757
|
|
|
758
758
|
df = to_dataframe(darray)
|
|
759
759
|
value_col = get_value_col(darray)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: xarray_plotly
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.14
|
|
4
4
|
Summary: Interactive Plotly Express plotting accessor for xarray
|
|
5
5
|
Author: Felix
|
|
6
6
|
License: MIT
|
|
@@ -28,13 +28,13 @@ Provides-Extra: dev
|
|
|
28
28
|
Requires-Dist: pytest==9.0.2; extra == "dev"
|
|
29
29
|
Requires-Dist: pytest-cov==7.0.0; extra == "dev"
|
|
30
30
|
Requires-Dist: mypy==1.19.1; extra == "dev"
|
|
31
|
-
Requires-Dist: ruff==0.
|
|
31
|
+
Requires-Dist: ruff==0.15.5; extra == "dev"
|
|
32
32
|
Requires-Dist: pre-commit==4.5.1; extra == "dev"
|
|
33
|
-
Requires-Dist: nbstripout==0.9.
|
|
33
|
+
Requires-Dist: nbstripout==0.9.1; extra == "dev"
|
|
34
34
|
Provides-Extra: docs
|
|
35
35
|
Requires-Dist: mkdocs==1.6.1; extra == "docs"
|
|
36
|
-
Requires-Dist: mkdocs-material==9.7.
|
|
37
|
-
Requires-Dist: mkdocstrings[python]==1.0.
|
|
36
|
+
Requires-Dist: mkdocs-material==9.7.4; extra == "docs"
|
|
37
|
+
Requires-Dist: mkdocstrings[python]==1.0.3; extra == "docs"
|
|
38
38
|
Requires-Dist: mkdocs-jupyter==0.25.1; extra == "docs"
|
|
39
39
|
Requires-Dist: mkdocs-plotly-plugin==0.1.3; extra == "docs"
|
|
40
40
|
Requires-Dist: jupyter==1.1.1; extra == "docs"
|
|
@@ -84,6 +84,25 @@ fig = xpx(da).line()
|
|
|
84
84
|
|
|
85
85
|
Full documentation: [https://fbumann.github.io/xarray_plotly](https://fbumann.github.io/xarray_plotly)
|
|
86
86
|
|
|
87
|
+
## Roadmap
|
|
88
|
+
|
|
89
|
+
Planned additions (contributions welcome):
|
|
90
|
+
|
|
91
|
+
**New plot types**
|
|
92
|
+
- `histogram()` — distribution of DataArray values
|
|
93
|
+
- `violin()` — richer distribution visualization than box plots
|
|
94
|
+
- `density_heatmap()` — 2D histograms (x and y as dimensions)
|
|
95
|
+
- `density_contour()` — 2D density contours (x and y as dimensions)
|
|
96
|
+
|
|
97
|
+
**Enhancements**
|
|
98
|
+
- WebGL rendering option for `line()` and `scatter()` (large datasets)
|
|
99
|
+
|
|
100
|
+
**Figure utilities** (facet/animation-aware)
|
|
101
|
+
- `fill_between()` — fill area between two traces (uncertainty bands)
|
|
102
|
+
- `sync_axes()` — consistent axis ranges across facets and animation frames
|
|
103
|
+
- `add_secondary_x()` — secondary x-axis (like `add_secondary_y()`)
|
|
104
|
+
- `stack()` — vertically stack separate figures into subplots
|
|
105
|
+
|
|
87
106
|
## License
|
|
88
107
|
|
|
89
108
|
MIT
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
.gitignore
|
|
2
2
|
.pre-commit-config.yaml
|
|
3
|
+
.release-please-config.json
|
|
4
|
+
.release-please-manifest.json
|
|
5
|
+
CHANGELOG.md
|
|
3
6
|
CONTRIBUTING.md
|
|
4
7
|
LICENSE
|
|
5
8
|
README.md
|
|
@@ -9,6 +12,8 @@ pyproject.toml
|
|
|
9
12
|
.github/workflows/ci.yml
|
|
10
13
|
.github/workflows/dependabot-auto-merge.yml
|
|
11
14
|
.github/workflows/docs.yml
|
|
15
|
+
.github/workflows/pr-title.yml
|
|
16
|
+
.github/workflows/release-please.yml
|
|
12
17
|
.github/workflows/release.yml
|
|
13
18
|
docs/api.md
|
|
14
19
|
docs/getting-started.ipynb
|
|
@@ -6,14 +6,14 @@ pandas>=1.5.0
|
|
|
6
6
|
pytest==9.0.2
|
|
7
7
|
pytest-cov==7.0.0
|
|
8
8
|
mypy==1.19.1
|
|
9
|
-
ruff==0.
|
|
9
|
+
ruff==0.15.5
|
|
10
10
|
pre-commit==4.5.1
|
|
11
|
-
nbstripout==0.9.
|
|
11
|
+
nbstripout==0.9.1
|
|
12
12
|
|
|
13
13
|
[docs]
|
|
14
14
|
mkdocs==1.6.1
|
|
15
|
-
mkdocs-material==9.7.
|
|
16
|
-
mkdocstrings[python]==1.0.
|
|
15
|
+
mkdocs-material==9.7.4
|
|
16
|
+
mkdocstrings[python]==1.0.3
|
|
17
17
|
mkdocs-jupyter==0.25.1
|
|
18
18
|
mkdocs-plotly-plugin==0.1.3
|
|
19
19
|
jupyter==1.1.1
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|