|
16 | 16 | from datetime import datetime |
17 | 17 |
|
18 | 18 | from .utils import (_determine_cmap_params, _infer_xy_labels, get_axis, |
19 | | - import_matplotlib_pyplot) |
| 19 | + import_matplotlib_pyplot, ROBUST_PERCENTILE) |
20 | 20 | from .facetgrid import FacetGrid |
21 | 21 | from xarray.core.pycompat import basestring |
22 | 22 |
|
@@ -419,14 +419,32 @@ def newplotfunc(darray, x=None, y=None, figsize=None, size=None, |
419 | 419 | # Decide on a default for the colorbar before facetgrids |
420 | 420 | if add_colorbar is None: |
421 | 421 | add_colorbar = plotfunc.__name__ != 'contour' |
422 | | - if plotfunc.__name__ == 'imshow' and \ |
423 | | - darray.ndim == (3 + (row is not None) + (col is not None)): |
| 422 | + imshow_rgb = plotfunc.__name__ == 'imshow' and \ |
| 423 | + darray.ndim == (3 + (row is not None) + (col is not None)) |
| 424 | + if imshow_rgb: |
424 | 425 | # Don't add a colorbar when showing an image with explicit colors |
425 | 426 | add_colorbar = False |
| 427 | + # Manually stretch colors for robust cmap |
| 428 | + if robust: |
| 429 | + flat = darray.values.ravel(order='K') |
| 430 | + flat = flat[~np.isnan(flat)] |
| 431 | + if flat.size == 0: |
| 432 | + # All data will be masked, so skip percentile calculation |
| 433 | + vmin, vmax = 0, 1 |
| 434 | + if vmin is None: |
| 435 | + vmin = np.percentile(flat, ROBUST_PERCENTILE) |
| 436 | + if vmax is None: |
| 437 | + vmax = np.percentile(flat, 100 - ROBUST_PERCENTILE) |
| 438 | + darray = (darray - vmin) / (vmax - vmin) |
| 439 | + robust = False |
| 440 | + del flat |
| 441 | + # Clip range to [0, 1] to avoid visual artefacts |
| 442 | + darray.values[:] = np.clip(darray.values, 0, 1) |
426 | 443 |
|
427 | 444 | # Handle facetgrids first |
428 | 445 | if row or col: |
429 | 446 | allargs = locals().copy() |
| 447 | + allargs.pop('imshow_rgb') |
430 | 448 | allargs.update(allargs.pop('kwargs')) |
431 | 449 |
|
432 | 450 | # Need the decorated plotting function |
@@ -575,6 +593,11 @@ def imshow(x, y, z, ax, **kwargs): |
575 | 593 | While other plot methods require the DataArray to be strictly |
576 | 594 | two-dimensional, ``imshow`` also accepts a 3D array where the third |
577 | 595 | dimension can be interpreted as RGB or RGBA color channels. |
| 596 | + In this case, ``robust=True`` will saturate the image in the |
| 597 | + usual way, consistenly between all bands and facets. |
| 598 | +
|
| 599 | + This method will clip oversaturated pixels to the valid range, |
| 600 | + instead of wrapping around to new colors like matplotlib. |
578 | 601 |
|
579 | 602 | .. note:: |
580 | 603 | This function needs uniformly spaced coordinates to |
|
0 commit comments