xarray-plotly 0.0.11__tar.gz → 0.0.13__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.11 → xarray_plotly-0.0.13}/.github/workflows/ci.yml +3 -0
- xarray_plotly-0.0.13/.github/workflows/pr-title.yml +33 -0
- xarray_plotly-0.0.13/.github/workflows/release-please.yml +19 -0
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/.github/workflows/release.yml +0 -7
- xarray_plotly-0.0.13/.release-please-config.json +13 -0
- xarray_plotly-0.0.13/.release-please-manifest.json +3 -0
- xarray_plotly-0.0.13/CHANGELOG.md +8 -0
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/PKG-INFO +20 -1
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/README.md +19 -0
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/docs/examples/kwargs.ipynb +65 -0
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/tests/test_accessor.py +125 -0
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/tests/test_figures.py +2 -2
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/xarray_plotly/__init__.py +4 -3
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/xarray_plotly/accessor.py +46 -1
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/xarray_plotly/common.py +73 -4
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/xarray_plotly/config.py +7 -7
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/xarray_plotly/figures.py +30 -13
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/xarray_plotly/plotting.py +73 -1
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/xarray_plotly.egg-info/PKG-INFO +20 -1
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/xarray_plotly.egg-info/SOURCES.txt +5 -0
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/.github/dependabot.yml +0 -0
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/.github/workflows/dependabot-auto-merge.yml +0 -0
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/.github/workflows/docs.yml +0 -0
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/.gitignore +0 -0
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/.pre-commit-config.yaml +0 -0
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/CONTRIBUTING.md +0 -0
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/LICENSE +0 -0
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/docs/api.md +0 -0
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/docs/examples/combining.ipynb +0 -0
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/docs/examples/datasets.ipynb +0 -0
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/docs/examples/dimensions.ipynb +0 -0
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/docs/examples/fast_bar.ipynb +0 -0
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/docs/examples/figure.ipynb +0 -0
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/docs/examples/manipulation.ipynb +0 -0
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/docs/examples/plot-types.ipynb +0 -0
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/docs/getting-started.ipynb +0 -0
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/docs/index.md +0 -0
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/mkdocs.yml +0 -0
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/pyproject.toml +0 -0
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/setup.cfg +0 -0
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/tests/__init__.py +0 -0
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/tests/test_common.py +0 -0
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/tests/test_config.py +0 -0
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/xarray_plotly/py.typed +0 -0
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/xarray_plotly.egg-info/dependency_links.txt +0 -0
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/xarray_plotly.egg-info/requires.txt +0 -0
- {xarray_plotly-0.0.11 → xarray_plotly-0.0.13}/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@v5
|
|
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,19 @@
|
|
|
1
|
+
name: Release Please
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: write
|
|
10
|
+
pull-requests: write
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
release-please:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: googleapis/release-please-action@v4
|
|
17
|
+
with:
|
|
18
|
+
config-file: .release-please-config.json
|
|
19
|
+
manifest-file: .release-please-manifest.json
|
|
@@ -10,7 +10,6 @@ jobs:
|
|
|
10
10
|
runs-on: ubuntu-latest
|
|
11
11
|
permissions:
|
|
12
12
|
id-token: write # for trusted publishing
|
|
13
|
-
contents: write # for creating GitHub release
|
|
14
13
|
|
|
15
14
|
steps:
|
|
16
15
|
- uses: actions/checkout@v6
|
|
@@ -23,9 +22,3 @@ jobs:
|
|
|
23
22
|
|
|
24
23
|
- name: Publish to PyPI
|
|
25
24
|
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,8 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [0.0.13](https://github.com/FBumann/xarray_plotly/compare/v0.0.12...v0.0.13) (2026-01-28)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* 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.
|
|
3
|
+
Version: 0.0.13
|
|
4
4
|
Summary: Interactive Plotly Express plotting accessor for xarray
|
|
5
5
|
Author: Felix
|
|
6
6
|
License: MIT
|
|
@@ -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
|
|
@@ -159,6 +159,71 @@
|
|
|
159
159
|
"xpx(change).imshow(color_continuous_scale=\"RdBu_r\", color_continuous_midpoint=0)"
|
|
160
160
|
]
|
|
161
161
|
},
|
|
162
|
+
{
|
|
163
|
+
"cell_type": "markdown",
|
|
164
|
+
"metadata": {},
|
|
165
|
+
"source": [
|
|
166
|
+
"## colors (unified parameter)\n",
|
|
167
|
+
"\n",
|
|
168
|
+
"The `colors` parameter provides a simpler way to set colors without remembering the exact Plotly parameter name. It automatically maps to the correct parameter based on the input type:\n",
|
|
169
|
+
"\n",
|
|
170
|
+
"| Input | Maps To |\n",
|
|
171
|
+
"|-------|---------|\n",
|
|
172
|
+
"| `\"Viridis\"` (continuous scale name) | `color_continuous_scale` |\n",
|
|
173
|
+
"| `\"D3\"` (qualitative palette name) | `color_discrete_sequence` |\n",
|
|
174
|
+
"| `[\"red\", \"blue\"]` (list) | `color_discrete_sequence` |\n",
|
|
175
|
+
"| `{\"A\": \"red\"}` (dict) | `color_discrete_map` |"
|
|
176
|
+
]
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
"cell_type": "code",
|
|
180
|
+
"execution_count": null,
|
|
181
|
+
"metadata": {},
|
|
182
|
+
"outputs": [],
|
|
183
|
+
"source": [
|
|
184
|
+
"# Named qualitative palette\n",
|
|
185
|
+
"xpx(stocks).line(colors=\"D3\")"
|
|
186
|
+
]
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
"cell_type": "code",
|
|
190
|
+
"execution_count": null,
|
|
191
|
+
"metadata": {},
|
|
192
|
+
"outputs": [],
|
|
193
|
+
"source": [
|
|
194
|
+
"# List of custom colors\n",
|
|
195
|
+
"xpx(stocks).line(colors=[\"#E63946\", \"#457B9D\", \"#2A9D8F\", \"#E9C46A\", \"#F4A261\"])"
|
|
196
|
+
]
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
"cell_type": "code",
|
|
200
|
+
"execution_count": null,
|
|
201
|
+
"metadata": {},
|
|
202
|
+
"outputs": [],
|
|
203
|
+
"source": [
|
|
204
|
+
"# Dict for explicit mapping\n",
|
|
205
|
+
"xpx(stocks).line(\n",
|
|
206
|
+
" colors={\n",
|
|
207
|
+
" \"GOOG\": \"red\",\n",
|
|
208
|
+
" \"AAPL\": \"blue\",\n",
|
|
209
|
+
" \"AMZN\": \"green\",\n",
|
|
210
|
+
" \"FB\": \"purple\",\n",
|
|
211
|
+
" \"NFLX\": \"orange\",\n",
|
|
212
|
+
" \"MSFT\": \"brown\",\n",
|
|
213
|
+
" }\n",
|
|
214
|
+
")"
|
|
215
|
+
]
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
"cell_type": "code",
|
|
219
|
+
"execution_count": null,
|
|
220
|
+
"metadata": {},
|
|
221
|
+
"outputs": [],
|
|
222
|
+
"source": [
|
|
223
|
+
"# Continuous scale for heatmaps\n",
|
|
224
|
+
"xpx(stocks).imshow(colors=\"Plasma\")"
|
|
225
|
+
]
|
|
226
|
+
},
|
|
162
227
|
{
|
|
163
228
|
"cell_type": "markdown",
|
|
164
229
|
"metadata": {},
|
|
@@ -401,3 +401,128 @@ class TestImshowBounds:
|
|
|
401
401
|
coloraxis = fig.layout.coloraxis
|
|
402
402
|
assert coloraxis.cmin == 0.0
|
|
403
403
|
assert coloraxis.cmax == 70.0
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
class TestColorsParameter:
|
|
407
|
+
"""Tests for the unified colors parameter."""
|
|
408
|
+
|
|
409
|
+
@pytest.fixture(autouse=True)
|
|
410
|
+
def setup(self) -> None:
|
|
411
|
+
"""Create test DataArrays."""
|
|
412
|
+
self.da = xr.DataArray(
|
|
413
|
+
np.random.rand(10, 3),
|
|
414
|
+
dims=["time", "city"],
|
|
415
|
+
coords={"city": ["A", "B", "C"]},
|
|
416
|
+
)
|
|
417
|
+
|
|
418
|
+
def test_colors_list_sets_discrete_sequence(self) -> None:
|
|
419
|
+
"""Test that a list of colors sets color_discrete_sequence."""
|
|
420
|
+
fig = self.da.plotly.line(colors=["red", "blue", "green"])
|
|
421
|
+
# Check that traces have the expected colors
|
|
422
|
+
assert len(fig.data) == 3
|
|
423
|
+
assert fig.data[0].line.color == "red"
|
|
424
|
+
assert fig.data[1].line.color == "blue"
|
|
425
|
+
assert fig.data[2].line.color == "green"
|
|
426
|
+
|
|
427
|
+
def test_colors_dict_sets_discrete_map(self) -> None:
|
|
428
|
+
"""Test that a dict sets color_discrete_map."""
|
|
429
|
+
fig = self.da.plotly.line(colors={"A": "red", "B": "blue", "C": "green"})
|
|
430
|
+
# Traces should be colored according to the mapping
|
|
431
|
+
assert len(fig.data) == 3
|
|
432
|
+
# Find traces by name and check their color
|
|
433
|
+
colors_by_name = {trace.name: trace.line.color for trace in fig.data}
|
|
434
|
+
assert colors_by_name["A"] == "red"
|
|
435
|
+
assert colors_by_name["B"] == "blue"
|
|
436
|
+
assert colors_by_name["C"] == "green"
|
|
437
|
+
|
|
438
|
+
def test_colors_continuous_scale_string(self) -> None:
|
|
439
|
+
"""Test that a continuous scale name sets color_continuous_scale."""
|
|
440
|
+
da = xr.DataArray(
|
|
441
|
+
np.random.rand(50, 2),
|
|
442
|
+
dims=["point", "coord"],
|
|
443
|
+
coords={"coord": ["x", "y"]},
|
|
444
|
+
)
|
|
445
|
+
fig = da.plotly.scatter(y="coord", x="point", color="value", colors="Viridis")
|
|
446
|
+
# Plotly Express uses coloraxis in the layout for continuous scales
|
|
447
|
+
# Check that the colorscale was applied to the coloraxis
|
|
448
|
+
assert fig.layout.coloraxis.colorscale is not None
|
|
449
|
+
colorscale = fig.layout.coloraxis.colorscale
|
|
450
|
+
# Viridis should be in the colorscale definition
|
|
451
|
+
assert any("viridis" in str(c).lower() for c in colorscale) or len(colorscale) > 0
|
|
452
|
+
|
|
453
|
+
def test_colors_qualitative_palette_string(self) -> None:
|
|
454
|
+
"""Test that a qualitative palette name sets color_discrete_sequence."""
|
|
455
|
+
import plotly.express as px
|
|
456
|
+
|
|
457
|
+
fig = self.da.plotly.line(colors="D3")
|
|
458
|
+
# D3 palette should be applied - check first trace color is from D3
|
|
459
|
+
d3_colors = px.colors.qualitative.D3
|
|
460
|
+
assert fig.data[0].line.color in d3_colors
|
|
461
|
+
|
|
462
|
+
def test_colors_ignored_with_warning_when_px_kwargs_present(self) -> None:
|
|
463
|
+
"""Test that colors is ignored with warning when color_* kwargs are present."""
|
|
464
|
+
import warnings
|
|
465
|
+
|
|
466
|
+
with warnings.catch_warnings(record=True) as w:
|
|
467
|
+
warnings.simplefilter("always")
|
|
468
|
+
fig = self.da.plotly.line(
|
|
469
|
+
colors="D3", color_discrete_sequence=["orange", "purple", "cyan"]
|
|
470
|
+
)
|
|
471
|
+
# Should have raised a warning about colors being ignored
|
|
472
|
+
assert any(
|
|
473
|
+
"colors" in str(m.message).lower() and "ignored" in str(m.message).lower()
|
|
474
|
+
for m in w
|
|
475
|
+
), "Expected warning about 'colors' being 'ignored' not found"
|
|
476
|
+
# The explicit px_kwargs should take precedence
|
|
477
|
+
assert fig.data[0].line.color == "orange"
|
|
478
|
+
|
|
479
|
+
def test_colors_none_uses_defaults(self) -> None:
|
|
480
|
+
"""Test that colors=None uses Plotly defaults."""
|
|
481
|
+
fig1 = self.da.plotly.line(colors=None)
|
|
482
|
+
fig2 = self.da.plotly.line()
|
|
483
|
+
# Both should produce the same result
|
|
484
|
+
assert fig1.data[0].line.color == fig2.data[0].line.color
|
|
485
|
+
|
|
486
|
+
def test_colors_works_with_bar(self) -> None:
|
|
487
|
+
"""Test colors parameter with bar chart."""
|
|
488
|
+
fig = self.da.plotly.bar(colors=["#e41a1c", "#377eb8", "#4daf4a"])
|
|
489
|
+
assert fig.data[0].marker.color == "#e41a1c"
|
|
490
|
+
|
|
491
|
+
def test_colors_works_with_area(self) -> None:
|
|
492
|
+
"""Test colors parameter with area chart."""
|
|
493
|
+
fig = self.da.plotly.area(colors=["red", "green", "blue"])
|
|
494
|
+
assert len(fig.data) == 3
|
|
495
|
+
|
|
496
|
+
def test_colors_works_with_scatter(self) -> None:
|
|
497
|
+
"""Test colors parameter with scatter plot."""
|
|
498
|
+
fig = self.da.plotly.scatter(colors=["red", "green", "blue"])
|
|
499
|
+
assert len(fig.data) == 3
|
|
500
|
+
|
|
501
|
+
def test_colors_works_with_imshow(self) -> None:
|
|
502
|
+
"""Test colors parameter with imshow (continuous scale)."""
|
|
503
|
+
da = xr.DataArray(np.random.rand(10, 10), dims=["y", "x"])
|
|
504
|
+
fig = da.plotly.imshow(colors="RdBu")
|
|
505
|
+
# Plotly Express uses coloraxis in the layout for continuous scales
|
|
506
|
+
assert fig.layout.coloraxis.colorscale is not None
|
|
507
|
+
colorscale = fig.layout.coloraxis.colorscale
|
|
508
|
+
# RdBu should be in the colorscale definition
|
|
509
|
+
assert any("rdbu" in str(c).lower() for c in colorscale) or len(colorscale) > 0
|
|
510
|
+
|
|
511
|
+
def test_colors_works_with_pie(self) -> None:
|
|
512
|
+
"""Test colors parameter with pie chart."""
|
|
513
|
+
da = xr.DataArray([30, 40, 30], dims=["category"], coords={"category": ["A", "B", "C"]})
|
|
514
|
+
fig = da.plotly.pie(colors={"A": "red", "B": "blue", "C": "green"})
|
|
515
|
+
assert isinstance(fig, go.Figure)
|
|
516
|
+
|
|
517
|
+
def test_colors_works_with_dataset(self) -> None:
|
|
518
|
+
"""Test colors parameter works with Dataset accessor."""
|
|
519
|
+
ds = xr.Dataset(
|
|
520
|
+
{
|
|
521
|
+
"temp": (["time"], np.random.rand(10)),
|
|
522
|
+
"precip": (["time"], np.random.rand(10)),
|
|
523
|
+
}
|
|
524
|
+
)
|
|
525
|
+
fig = ds.plotly.line(colors=["red", "blue"])
|
|
526
|
+
assert len(fig.data) == 2
|
|
527
|
+
assert fig.data[0].line.color == "red"
|
|
528
|
+
assert fig.data[1].line.color == "blue"
|
|
@@ -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:
|
|
@@ -52,7 +52,7 @@ from xarray import DataArray, Dataset, register_dataarray_accessor, register_dat
|
|
|
52
52
|
|
|
53
53
|
from xarray_plotly import config
|
|
54
54
|
from xarray_plotly.accessor import DataArrayPlotlyAccessor, DatasetPlotlyAccessor
|
|
55
|
-
from xarray_plotly.common import SLOT_ORDERS, auto
|
|
55
|
+
from xarray_plotly.common import SLOT_ORDERS, Colors, auto
|
|
56
56
|
from xarray_plotly.figures import (
|
|
57
57
|
add_secondary_y,
|
|
58
58
|
overlay,
|
|
@@ -61,6 +61,7 @@ from xarray_plotly.figures import (
|
|
|
61
61
|
|
|
62
62
|
__all__ = [
|
|
63
63
|
"SLOT_ORDERS",
|
|
64
|
+
"Colors",
|
|
64
65
|
"add_secondary_y",
|
|
65
66
|
"auto",
|
|
66
67
|
"config",
|
|
@@ -110,5 +111,5 @@ def xpx(data: DataArray | Dataset) -> DataArrayPlotlyAccessor | DatasetPlotlyAcc
|
|
|
110
111
|
__version__ = version("xarray_plotly")
|
|
111
112
|
|
|
112
113
|
# Register the accessors
|
|
113
|
-
register_dataarray_accessor("plotly")(DataArrayPlotlyAccessor)
|
|
114
|
-
register_dataset_accessor("plotly")(DatasetPlotlyAccessor)
|
|
114
|
+
register_dataarray_accessor("plotly")(DataArrayPlotlyAccessor) # type: ignore[no-untyped-call]
|
|
115
|
+
register_dataset_accessor("plotly")(DatasetPlotlyAccessor) # type: ignore[no-untyped-call]
|