xarray-plotly 0.0.5__tar.gz → 0.0.6__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 (37) hide show
  1. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/.github/workflows/ci.yml +32 -0
  2. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/.github/workflows/docs.yml +2 -1
  3. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/PKG-INFO +1 -1
  4. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/tests/test_accessor.py +49 -0
  5. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/xarray_plotly/accessor.py +4 -0
  6. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/xarray_plotly/plotting.py +20 -0
  7. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/xarray_plotly.egg-info/PKG-INFO +1 -1
  8. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/.github/dependabot.yml +0 -0
  9. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/.github/workflows/dependabot-auto-merge.yml +0 -0
  10. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/.github/workflows/release.yml +0 -0
  11. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/.gitignore +0 -0
  12. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/.pre-commit-config.yaml +0 -0
  13. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/CONTRIBUTING.md +0 -0
  14. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/LICENSE +0 -0
  15. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/README.md +0 -0
  16. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/docs/api.md +0 -0
  17. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/docs/examples/datasets.ipynb +0 -0
  18. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/docs/examples/dimensions.ipynb +0 -0
  19. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/docs/examples/figure.ipynb +0 -0
  20. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/docs/examples/kwargs.ipynb +0 -0
  21. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/docs/examples/plot-types.ipynb +0 -0
  22. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/docs/getting-started.ipynb +0 -0
  23. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/docs/index.md +0 -0
  24. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/mkdocs.yml +0 -0
  25. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/pyproject.toml +0 -0
  26. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/setup.cfg +0 -0
  27. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/tests/__init__.py +0 -0
  28. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/tests/test_common.py +0 -0
  29. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/tests/test_config.py +0 -0
  30. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/xarray_plotly/__init__.py +0 -0
  31. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/xarray_plotly/common.py +0 -0
  32. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/xarray_plotly/config.py +0 -0
  33. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/xarray_plotly/py.typed +0 -0
  34. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/xarray_plotly.egg-info/SOURCES.txt +0 -0
  35. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/xarray_plotly.egg-info/dependency_links.txt +0 -0
  36. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/xarray_plotly.egg-info/requires.txt +0 -0
  37. {xarray_plotly-0.0.5 → xarray_plotly-0.0.6}/xarray_plotly.egg-info/top_level.txt +0 -0
@@ -40,3 +40,35 @@ jobs:
40
40
  with:
41
41
  token: ${{ secrets.CODECOV_TOKEN }}
42
42
  fail_ci_if_error: false
43
+
44
+ docs:
45
+ runs-on: ubuntu-latest
46
+ steps:
47
+ - uses: actions/checkout@v6
48
+
49
+ - name: Install uv
50
+ uses: astral-sh/setup-uv@v7
51
+
52
+ - name: Install dependencies
53
+ run: uv sync --extra docs
54
+
55
+ - name: Build docs
56
+ run: uv run mkdocs build
57
+
58
+ ci-success:
59
+ name: CI Success
60
+ needs: [test, docs]
61
+ if: always()
62
+ runs-on: ubuntu-latest
63
+ steps:
64
+ - name: Check all jobs passed
65
+ run: |
66
+ if [[ "${{ needs.test.result }}" != "success" ]]; then
67
+ echo "Test job failed or was cancelled"
68
+ exit 1
69
+ fi
70
+ if [[ "${{ needs.docs.result }}" != "success" ]]; then
71
+ echo "Docs job failed or was cancelled"
72
+ exit 1
73
+ fi
74
+ echo "All CI checks passed!"
@@ -1,7 +1,7 @@
1
1
  name: Docs
2
2
 
3
3
  on:
4
- push:
4
+ pull_request:
5
5
  branches: [main]
6
6
  release:
7
7
  types: [published]
@@ -26,6 +26,7 @@ jobs:
26
26
  run: uv run mkdocs build
27
27
 
28
28
  - name: Deploy to GitHub Pages
29
+ if: github.event_name == 'release'
29
30
  uses: peaceiris/actions-gh-pages@v4
30
31
  with:
31
32
  github_token: ${{ secrets.GITHUB_TOKEN }}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xarray_plotly
3
- Version: 0.0.5
3
+ Version: 0.0.6
4
4
  Summary: Interactive Plotly Express plotting accessor for xarray
5
5
  Author: Felix
6
6
  License: MIT
@@ -292,3 +292,52 @@ class TestDatasetPlotlyAccessor:
292
292
  """Test box plot with all variables."""
293
293
  fig = self.ds.plotly.box()
294
294
  assert isinstance(fig, go.Figure)
295
+
296
+
297
+ class TestImshowBounds:
298
+ """Tests for imshow global bounds and robust mode."""
299
+
300
+ def test_imshow_global_bounds(self) -> None:
301
+ """Test that imshow uses global min/max by default."""
302
+ da = xr.DataArray(
303
+ np.array([[[1, 2], [3, 4]], [[5, 6], [7, 100]]]),
304
+ dims=["time", "y", "x"],
305
+ )
306
+ fig = da.plotly.imshow(animation_frame="time")
307
+ # Check coloraxis for zmin/zmax (plotly stores them there)
308
+ coloraxis = fig.layout.coloraxis
309
+ assert coloraxis.cmin == 1.0
310
+ assert coloraxis.cmax == 100.0
311
+
312
+ def test_imshow_robust_bounds(self) -> None:
313
+ """Test that robust=True uses percentile-based bounds."""
314
+ # Create data with outlier
315
+ data = np.random.rand(10, 20) * 100
316
+ data[0, 0] = 10000 # extreme outlier
317
+ da = xr.DataArray(data, dims=["y", "x"])
318
+
319
+ fig = da.plotly.imshow(robust=True)
320
+ # With robust=True, cmax should be much less than the outlier
321
+ coloraxis = fig.layout.coloraxis
322
+ assert coloraxis.cmax < 10000
323
+ assert coloraxis.cmax < 200 # Should be around 98th percentile (~98)
324
+
325
+ def test_imshow_user_zmin_zmax_override(self) -> None:
326
+ """Test that user-provided zmin/zmax overrides auto bounds."""
327
+ da = xr.DataArray(np.random.rand(10, 20) * 100, dims=["y", "x"])
328
+ fig = da.plotly.imshow(zmin=0, zmax=50)
329
+ coloraxis = fig.layout.coloraxis
330
+ assert coloraxis.cmin == 0
331
+ assert coloraxis.cmax == 50
332
+
333
+ def test_imshow_animation_consistent_bounds(self) -> None:
334
+ """Test that animation frames have consistent color bounds."""
335
+ da = xr.DataArray(
336
+ np.array([[[0, 10], [20, 30]], [[40, 50], [60, 70]]]),
337
+ dims=["time", "y", "x"],
338
+ )
339
+ fig = da.plotly.imshow(animation_frame="time")
340
+ # All frames should use global min (0) and max (70)
341
+ coloraxis = fig.layout.coloraxis
342
+ assert coloraxis.cmin == 0.0
343
+ assert coloraxis.cmax == 70.0
@@ -250,6 +250,7 @@ class DataArrayPlotlyAccessor:
250
250
  y: SlotValue = auto,
251
251
  facet_col: SlotValue = auto,
252
252
  animation_frame: SlotValue = auto,
253
+ robust: bool = False,
253
254
  **px_kwargs: Any,
254
255
  ) -> go.Figure:
255
256
  """Create an interactive heatmap image.
@@ -261,7 +262,9 @@ class DataArrayPlotlyAccessor:
261
262
  y: Dimension for y-axis (rows). Default: first dimension.
262
263
  facet_col: Dimension for subplot columns. Default: third dimension.
263
264
  animation_frame: Dimension for animation. Default: fourth dimension.
265
+ robust: If True, use 2nd/98th percentiles for color bounds (handles outliers).
264
266
  **px_kwargs: Additional arguments passed to `plotly.express.imshow()`.
267
+ Use `zmin` and `zmax` to manually set color scale bounds.
265
268
 
266
269
  Returns:
267
270
  Interactive Plotly Figure.
@@ -272,6 +275,7 @@ class DataArrayPlotlyAccessor:
272
275
  y=y,
273
276
  facet_col=facet_col,
274
277
  animation_frame=animation_frame,
278
+ robust=robust,
275
279
  **px_kwargs,
276
280
  )
277
281
 
@@ -6,6 +6,7 @@ from __future__ import annotations
6
6
 
7
7
  from typing import TYPE_CHECKING, Any
8
8
 
9
+ import numpy as np
9
10
  import plotly.express as px
10
11
 
11
12
  from xarray_plotly.common import (
@@ -398,6 +399,7 @@ def imshow(
398
399
  y: SlotValue = auto,
399
400
  facet_col: SlotValue = auto,
400
401
  animation_frame: SlotValue = auto,
402
+ robust: bool = False,
401
403
  **px_kwargs: Any,
402
404
  ) -> go.Figure:
403
405
  """
@@ -418,8 +420,12 @@ def imshow(
418
420
  Dimension for subplot columns. Default: third dimension.
419
421
  animation_frame
420
422
  Dimension for animation. Default: fourth dimension.
423
+ robust
424
+ If True, compute color bounds using 2nd and 98th percentiles
425
+ for robustness against outliers. Default: False.
421
426
  **px_kwargs
422
427
  Additional arguments passed to `plotly.express.imshow()`.
428
+ Use `zmin` and `zmax` to manually set color scale bounds.
423
429
 
424
430
  Returns
425
431
  -------
@@ -440,6 +446,20 @@ def imshow(
440
446
  ]
441
447
  plot_data = darray.transpose(*transpose_order) if transpose_order else darray
442
448
 
449
+ # Compute global color bounds if not provided
450
+ if "zmin" not in px_kwargs or "zmax" not in px_kwargs:
451
+ values = plot_data.values
452
+ if robust:
453
+ # Use percentiles for outlier robustness
454
+ zmin = float(np.nanpercentile(values, 2))
455
+ zmax = float(np.nanpercentile(values, 98))
456
+ else:
457
+ # Use global min/max across all data
458
+ zmin = float(np.nanmin(values))
459
+ zmax = float(np.nanmax(values))
460
+ px_kwargs.setdefault("zmin", zmin)
461
+ px_kwargs.setdefault("zmax", zmax)
462
+
443
463
  return px.imshow(
444
464
  plot_data,
445
465
  facet_col=slots.get("facet_col"),
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xarray_plotly
3
- Version: 0.0.5
3
+ Version: 0.0.6
4
4
  Summary: Interactive Plotly Express plotting accessor for xarray
5
5
  Author: Felix
6
6
  License: MIT
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes