Skip to content

Commit cb161a1

Browse files
Zac-HDshoyer
authored andcommitted
Plot nans (#1782)
* Fix formatting * Cross-reference matplotlib docs for plot methods * Handle all-NaN data in plot.imshow * Handle array dim with size one in plt.imshow * Add whats-new entry
1 parent f882a58 commit cb161a1

File tree

5 files changed

+41
-15
lines changed

5 files changed

+41
-15
lines changed

doc/conf.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,4 +323,5 @@
323323
'iris': ('http://scitools.org.uk/iris/docs/latest/', None),
324324
'numpy': ('https://docs.scipy.org/doc/numpy/', None),
325325
'numba': ('https://numba.pydata.org/numba-doc/latest/', None),
326+
'matplotlib': ('https://matplotlib.org/', None),
326327
}

doc/whats-new.rst

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,25 +32,29 @@ Enhancements
3232
By `Ryan Abernathey <https://github.com/rabernat>`_.
3333
- Experimental support for parsing ENVI metadata to coordinates and attributes
3434
in :py:func:`xarray.open_rasterio`.
35-
By `Matti Eskelinen <https://github.com/maaleske>`
35+
By `Matti Eskelinen <https://github.com/maaleske>`_.
3636

3737
.. _Zarr: http://zarr.readthedocs.io/
3838

3939

4040
Bug fixes
4141
~~~~~~~~~
4242

43-
- Bug fix in vectorized assignment (:issue:`1743`, `1744`).
44-
Now item assignment to :py:meth:`~DataArray.__setitem__` checks
43+
- Bug fix in vectorized assignment (:issue:`1743`, :issue:`1744`).
44+
Now item assignment to :py:meth:`DataArray.__setitem__` checks
4545
coordinates of target, destination and keys. If there are any conflict among
4646
these coordinates, ``IndexError`` will be raised.
4747
By `Keisuke Fujii <https://github.com/fujiisoup>`_.
48+
- Properly point :py:meth:`DataArray.__dask_scheduler__` to
49+
``dask.threaded.get``. By `Matthew Rocklin <https://github.com/mrocklin>`_.
50+
- Bug fixes in :py:meth:`DataArray.plot.imshow`: all-NaN arrays and arrays
51+
with size one in some dimension can now be plotted, which is good for
52+
exploring satellite imagery. (:issue:`1780`)
53+
By `Zac Hatfield-Dodds <https://github.com/Zac-HD>`_.
4854

4955

5056
.. _whats-new.0.10.0:
5157

52-
- Properly point DataArray.__dask_scheduler__ to dask.threaded.get
53-
5458
v0.10.0 (20 November 2017)
5559
--------------------------
5660

xarray/plot/plot.py

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ def line(darray, *args, **kwargs):
158158
"""
159159
Line plot of 1 dimensional DataArray index against values
160160
161-
Wraps matplotlib.pyplot.plot
161+
Wraps :func:`matplotlib:matplotlib.pyplot.plot`
162162
163163
Parameters
164164
----------
@@ -220,7 +220,7 @@ def hist(darray, figsize=None, size=None, aspect=None, ax=None, **kwargs):
220220
"""
221221
Histogram of DataArray
222222
223-
Wraps matplotlib.pyplot.hist
223+
Wraps :func:`matplotlib:matplotlib.pyplot.hist`
224224
225225
Plots N dimensional arrays by first flattening the array.
226226
@@ -565,10 +565,9 @@ def imshow(x, y, z, ax, **kwargs):
565565
"""
566566
Image plot of 2d DataArray using matplotlib.pyplot
567567
568-
Wraps matplotlib.pyplot.imshow
569-
570-
..note::
568+
Wraps :func:`matplotlib:matplotlib.pyplot.imshow`
571569
570+
.. note::
572571
This function needs uniformly spaced coordinates to
573572
properly label the axes. Call DataArray.plot() to check.
574573
@@ -581,8 +580,15 @@ def imshow(x, y, z, ax, **kwargs):
581580
'pcolormesh or contour(f)')
582581

583582
# Centering the pixels- Assumes uniform spacing
584-
xstep = (x[1] - x[0]) / 2.0
585-
ystep = (y[1] - y[0]) / 2.0
583+
try:
584+
xstep = (x[1] - x[0]) / 2.0
585+
except IndexError:
586+
# Arbitrary default value, similar to matplotlib behaviour
587+
xstep = .1
588+
try:
589+
ystep = (y[1] - y[0]) / 2.0
590+
except IndexError:
591+
ystep = .1
586592
left, right = x[0] - xstep, x[-1] + xstep
587593
bottom, top = y[-1] + ystep, y[0] - ystep
588594

@@ -608,7 +614,7 @@ def contour(x, y, z, ax, **kwargs):
608614
"""
609615
Contour plot of 2d DataArray
610616
611-
Wraps matplotlib.pyplot.contour
617+
Wraps :func:`matplotlib:matplotlib.pyplot.contour`
612618
"""
613619
primitive = ax.contour(x, y, z, **kwargs)
614620
return primitive
@@ -619,7 +625,7 @@ def contourf(x, y, z, ax, **kwargs):
619625
"""
620626
Filled contour plot of 2d DataArray
621627
622-
Wraps matplotlib.pyplot.contourf
628+
Wraps :func:`matplotlib:matplotlib.pyplot.contourf`
623629
"""
624630
primitive = ax.contourf(x, y, z, **kwargs)
625631
return primitive
@@ -635,6 +641,8 @@ def _infer_interval_breaks(coord, axis=0):
635641
"""
636642
coord = np.asarray(coord)
637643
deltas = 0.5 * np.diff(coord, axis=axis)
644+
if deltas.size == 0:
645+
deltas = np.array(0.0)
638646
first = np.take(coord, [0], axis=axis) - np.take(deltas, [0], axis=axis)
639647
last = np.take(coord, [-1], axis=axis) + np.take(deltas, [-1], axis=axis)
640648
trim_last = tuple(slice(None, -1) if n == axis else slice(None)
@@ -647,7 +655,7 @@ def pcolormesh(x, y, z, ax, infer_intervals=None, **kwargs):
647655
"""
648656
Pseudocolor plot of 2d DataArray
649657
650-
Wraps matplotlib.pyplot.pcolormesh
658+
Wraps :func:`matplotlib:matplotlib.pyplot.pcolormesh`
651659
"""
652660

653661
# decide on a default for infer_intervals (GH781)

xarray/plot/utils.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,11 @@ def _determine_cmap_params(plot_data, vmin=None, vmax=None, cmap=None,
165165

166166
calc_data = np.ravel(plot_data[~pd.isnull(plot_data)])
167167

168+
# Handle all-NaN input data gracefully
169+
if calc_data.size == 0:
170+
# Arbitrary default for when all values are NaN
171+
calc_data = np.array(0.0)
172+
168173
# Setting center=False prevents a divergent cmap
169174
possibly_divergent = center is not False
170175

xarray/tests/test_plot.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,14 @@ def test_plot_nans(self):
624624
clim2 = self.plotfunc(x2).get_clim()
625625
self.assertEqual(clim1, clim2)
626626

627+
def test_can_plot_all_nans(self):
628+
# regression test for issue #1780
629+
self.plotfunc(DataArray(np.full((2, 2), np.nan)))
630+
631+
def test_can_plot_axis_size_one(self):
632+
if self.plotfunc.__name__ not in ('contour', 'contourf'):
633+
self.plotfunc(DataArray(np.ones((1, 1))))
634+
627635
def test_viridis_cmap(self):
628636
cmap_name = self.plotmethod(cmap='viridis').get_cmap().name
629637
self.assertEqual('viridis', cmap_name)

0 commit comments

Comments
 (0)