From f38bfc53ae1553695ee778f331aa463a40ec3de7 Mon Sep 17 00:00:00 2001 From: Fabien Maussion Date: Fri, 3 Jun 2016 19:03:25 +0200 Subject: [PATCH 1/6] fix: contour plot levels --- xarray/plot/plot.py | 12 ++++++++++-- xarray/plot/utils.py | 2 +- xarray/test/test_plot.py | 12 +++++++++--- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/xarray/plot/plot.py b/xarray/plot/plot.py index cad5ee4cac3..b096da38ae9 100644 --- a/xarray/plot/plot.py +++ b/xarray/plot/plot.py @@ -389,8 +389,16 @@ def newplotfunc(darray, x=None, y=None, ax=None, row=None, col=None, _ensure_plottable(xval, yval) - if 'contour' in plotfunc.__name__ and levels is None: - levels = 7 # this is the matplotlib default + if 'contour' in plotfunc.__name__: + if levels is None: + levels = 7 # this is the matplotlib default + # A colorbar with one level is not possible with mpl + try: + if len(levels) < 2: + add_colorbar = False + except TypeError: + if levels < 2: + add_colorbar = False cmap_kwargs = {'plot_data': zval.data, 'vmin': vmin, diff --git a/xarray/plot/utils.py b/xarray/plot/utils.py index 5e4b11a4ab4..e9fb1de98d6 100644 --- a/xarray/plot/utils.py +++ b/xarray/plot/utils.py @@ -41,7 +41,7 @@ def _build_discrete_cmap(cmap, levels, extend, filled): if not filled: # non-filled contour plots - extend = 'neither' + extend = 'max' if extend == 'both': ext_n = 2 diff --git a/xarray/test/test_plot.py b/xarray/test/test_plot.py index 8b0a699b9ed..7fe7b228c94 100644 --- a/xarray/test/test_plot.py +++ b/xarray/test/test_plot.py @@ -414,7 +414,7 @@ def test_build_discrete_cmap(self): if filled: self.assertEqual(ncmap.colorbar_extend, extend) else: - self.assertEqual(ncmap.colorbar_extend, 'neither') + self.assertEqual(ncmap.colorbar_extend, 'max') def test_discrete_colormap_list_of_levels(self): for extend, levels in [('max', [-1, 2, 4, 8, 10]), @@ -429,7 +429,7 @@ def test_discrete_colormap_list_of_levels(self): if kind != 'contour': self.assertEqual(extend, primitive.cmap.colorbar_extend) else: - self.assertEqual('neither', primitive.cmap.colorbar_extend) + self.assertEqual('max', primitive.cmap.colorbar_extend) self.assertEqual(len(levels) - 1, len(primitive.cmap.colors)) def test_discrete_colormap_int_levels(self): @@ -454,7 +454,7 @@ def test_discrete_colormap_int_levels(self): if kind != 'contour': self.assertEqual(extend, primitive.cmap.colorbar_extend) else: - self.assertEqual('neither', primitive.cmap.colorbar_extend) + self.assertEqual('max', primitive.cmap.colorbar_extend) self.assertGreaterEqual(levels, len(primitive.cmap.colors)) def test_discrete_colormap_list_levels_and_vmin_or_vmax(self): @@ -810,6 +810,12 @@ def test_2d_coord_names(self): self.assertEqual('x2d', ax.get_xlabel()) self.assertEqual('y2d', ax.get_ylabel()) + def test_single_level(self): + self.plotmethod(levels=[0.1]) + self.plotmethod(levels=[0.1, 0.2]) + self.plotmethod(levels=1) + + class TestPcolormesh(Common2dMixin, PlotTestCase): From a4bafee86d801b6d40a484e5b2f6f15f3118b158 Mon Sep 17 00:00:00 2001 From: Fabien Maussion Date: Thu, 9 Jun 2016 14:19:44 +0200 Subject: [PATCH 2/6] cleaned up tests --- xarray/test/test_plot.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/xarray/test/test_plot.py b/xarray/test/test_plot.py index 7fe7b228c94..de43f97bd9f 100644 --- a/xarray/test/test_plot.py +++ b/xarray/test/test_plot.py @@ -795,6 +795,19 @@ def _color_as_tuple(c): _color_as_tuple(artist.cmap.colors[1]), (0.0, 0.0, 1.0)) + artist = self.darray.plot.contour(levels=[-0.5, 0., 0.5, 1.], + colors=['k', 'r', 'w', 'b']) + self.assertEqual( + _color_as_tuple(artist.cmap.colors[1]), + (1.0, 0.0, 0.0)) + self.assertEqual( + _color_as_tuple(artist.cmap.colors[2]), + (1.0, 1.0, 1.0)) + # the last color is now under "over" + self.assertEqual( + _color_as_tuple(artist.cmap._rgba_over), + (0.0, 0.0, 1.0)) + def test_cmap_and_color_both(self): with self.assertRaises(ValueError): self.plotmethod(colors='k', cmap='RdBu') @@ -811,8 +824,8 @@ def test_2d_coord_names(self): self.assertEqual('y2d', ax.get_ylabel()) def test_single_level(self): + # this used to raise an error self.plotmethod(levels=[0.1]) - self.plotmethod(levels=[0.1, 0.2]) self.plotmethod(levels=1) From 2b48428172e79df8405bfc032c4a894cde87e229 Mon Sep 17 00:00:00 2001 From: Fabien Maussion Date: Wed, 20 Jul 2016 10:52:13 +0200 Subject: [PATCH 3/6] cbar defaults to None --- xarray/plot/plot.py | 20 +++++++++++--------- xarray/test/test_plot.py | 12 +++++++----- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/xarray/plot/plot.py b/xarray/plot/plot.py index b096da38ae9..c388ae56733 100644 --- a/xarray/plot/plot.py +++ b/xarray/plot/plot.py @@ -339,13 +339,17 @@ def _plot2d(plotfunc): @functools.wraps(plotfunc) def newplotfunc(darray, x=None, y=None, ax=None, row=None, col=None, col_wrap=None, xincrease=True, yincrease=True, - add_colorbar=True, add_labels=True, vmin=None, vmax=None, + add_colorbar=None, add_labels=True, vmin=None, vmax=None, cmap=None, center=None, robust=False, extend=None, levels=None, colors=None, subplot_kws=None, cbar_ax=None, cbar_kwargs=None, **kwargs): # All 2d plots in xarray share this function signature. # Method signature below should be consistent. + # Decide on a default for the colorbar before facetgrids + if add_colorbar is None: + add_colorbar = plotfunc.__name__ != 'contour' + # Handle facetgrids first if row or col: allargs = locals().copy() @@ -392,13 +396,11 @@ def newplotfunc(darray, x=None, y=None, ax=None, row=None, col=None, if 'contour' in plotfunc.__name__: if levels is None: levels = 7 # this is the matplotlib default - # A colorbar with one level is not possible with mpl - try: - if len(levels) < 2: - add_colorbar = False - except TypeError: - if levels < 2: - add_colorbar = False + + # # A colorbar with one level is not possible with mpl + # if add_colorbar: + # if (isinstance(levels, int) and levels < 2) or len(levels) < 2: + # add_colorbar = False cmap_kwargs = {'plot_data': zval.data, 'vmin': vmin, @@ -458,7 +460,7 @@ def newplotfunc(darray, x=None, y=None, ax=None, row=None, col=None, @functools.wraps(newplotfunc) def plotmethod(_PlotMethods_obj, x=None, y=None, ax=None, row=None, col=None, col_wrap=None, xincrease=True, yincrease=True, - add_colorbar=True, add_labels=True, vmin=None, vmax=None, + add_colorbar=None, add_labels=True, vmin=None, vmax=None, cmap=None, colors=None, center=None, robust=False, extend=None, levels=None, subplot_kws=None, cbar_ax=None, cbar_kwargs=None, **kwargs): diff --git a/xarray/test/test_plot.py b/xarray/test/test_plot.py index de43f97bd9f..264e4dbe752 100644 --- a/xarray/test/test_plot.py +++ b/xarray/test/test_plot.py @@ -620,7 +620,7 @@ def test_default_title(self): def test_colorbar_default_label(self): self.darray.name = 'testvar' - self.plotmethod() + self.plotmethod(add_colorbar=True) self.assertIn(self.darray.name, text_in_fig()) def test_no_labels(self): @@ -633,18 +633,19 @@ def test_no_labels(self): def test_colorbar_kwargs(self): # replace label self.darray.name = 'testvar' - self.plotmethod(cbar_kwargs={'label':'MyLabel'}) + self.plotmethod(add_colorbar=True, cbar_kwargs={'label':'MyLabel'}) alltxt = text_in_fig() self.assertIn('MyLabel', alltxt) self.assertNotIn('testvar', alltxt) # you can use mapping types as well - self.plotmethod(cbar_kwargs=(('label', 'MyLabel'),)) + self.plotmethod(add_colorbar=True, cbar_kwargs=(('label', 'MyLabel'),)) alltxt = text_in_fig() self.assertIn('MyLabel', alltxt) self.assertNotIn('testvar', alltxt) # change cbar ax fig, (ax, cax) = plt.subplots(1, 2) - self.plotmethod(ax=ax, cbar_ax=cax, cbar_kwargs={'label':'MyBar'}) + self.plotmethod(ax=ax, cbar_ax=cax, add_colorbar=True, + cbar_kwargs={'label':'MyBar'}) self.assertTrue(ax.has_data()) self.assertTrue(cax.has_data()) alltxt = text_in_fig() @@ -652,7 +653,8 @@ def test_colorbar_kwargs(self): self.assertNotIn('testvar', alltxt) # note that there are two ways to achieve this fig, (ax, cax) = plt.subplots(1, 2) - self.plotmethod(ax=ax, cbar_kwargs={'label':'MyBar', 'cax':cax}) + self.plotmethod(ax=ax, add_colorbar=True, + cbar_kwargs={'label':'MyBar', 'cax':cax}) self.assertTrue(ax.has_data()) self.assertTrue(cax.has_data()) alltxt = text_in_fig() From 400fd748224ec547f21feee99c4d2021eeaa77a4 Mon Sep 17 00:00:00 2001 From: Fabien Maussion Date: Wed, 20 Jul 2016 10:58:25 +0200 Subject: [PATCH 4/6] whats new --- doc/whats-new.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/whats-new.rst b/doc/whats-new.rst index bb10d3e5796..ca462e8e1fd 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -29,6 +29,7 @@ Breaking changes - Indexing on multi-index now drop levels, which is consitent with pandas. It also changes the name of the dimension / coordinate when the multi-index is reduced to a single index. +- Contour plots no longer add a colorbar per default (:issue:`866`). Enhancements ~~~~~~~~~~~~ @@ -100,6 +101,9 @@ Bug fixes - Fixed incorrect test for dask version :issue:`891`. By `Stephan Hoyer `_. +- :py:func:`~xarray.plot.contour` now plots the correct number of contours + (:issue:`866`). By `Fabien Maussion `_. + .. _whats-new.0.7.2: v0.7.2 (13 March 2016) From cd624ee70b7f2d2f5c83d310f2012ac6f3915a2a Mon Sep 17 00:00:00 2001 From: Fabien Maussion Date: Wed, 20 Jul 2016 11:06:28 +0200 Subject: [PATCH 5/6] forgot something --- xarray/plot/plot.py | 5 ----- xarray/test/test_plot.py | 4 ++-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/xarray/plot/plot.py b/xarray/plot/plot.py index c388ae56733..0d10c0ab4ee 100644 --- a/xarray/plot/plot.py +++ b/xarray/plot/plot.py @@ -397,11 +397,6 @@ def newplotfunc(darray, x=None, y=None, ax=None, row=None, col=None, if levels is None: levels = 7 # this is the matplotlib default - # # A colorbar with one level is not possible with mpl - # if add_colorbar: - # if (isinstance(levels, int) and levels < 2) or len(levels) < 2: - # add_colorbar = False - cmap_kwargs = {'plot_data': zval.data, 'vmin': vmin, 'vmax': vmax, diff --git a/xarray/test/test_plot.py b/xarray/test/test_plot.py index 264e4dbe752..4e812d2b602 100644 --- a/xarray/test/test_plot.py +++ b/xarray/test/test_plot.py @@ -826,12 +826,12 @@ def test_2d_coord_names(self): self.assertEqual('y2d', ax.get_ylabel()) def test_single_level(self): - # this used to raise an error + # this used to raise an error, but not anymore since + # add_colorbar defaults to false self.plotmethod(levels=[0.1]) self.plotmethod(levels=1) - class TestPcolormesh(Common2dMixin, PlotTestCase): plotfunc = staticmethod(xplt.pcolormesh) From ff721b6f48ce1d5f35d3f167f766f327d281e223 Mon Sep 17 00:00:00 2001 From: Fabien Maussion Date: Wed, 20 Jul 2016 11:14:12 +0200 Subject: [PATCH 6/6] forgot something again --- xarray/plot/plot.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/xarray/plot/plot.py b/xarray/plot/plot.py index 0d10c0ab4ee..11a32e9f85e 100644 --- a/xarray/plot/plot.py +++ b/xarray/plot/plot.py @@ -393,9 +393,8 @@ def newplotfunc(darray, x=None, y=None, ax=None, row=None, col=None, _ensure_plottable(xval, yval) - if 'contour' in plotfunc.__name__: - if levels is None: - levels = 7 # this is the matplotlib default + if 'contour' in plotfunc.__name__ and levels is None: + levels = 7 # this is the matplotlib default cmap_kwargs = {'plot_data': zval.data, 'vmin': vmin,