From 9ceb6b91ab4530e2da0015860124e712eae6aeaa Mon Sep 17 00:00:00 2001 From: Kjartan Myrdal Date: Wed, 23 Mar 2016 16:06:00 +0100 Subject: [PATCH 1/3] A method added to Colormap classes to reverse the colormap * method added to both ListedColormap and LinearSegmentedColormap * The parent class Colormap raises NotImplementedError * A test was added to test_colors.py --- lib/matplotlib/colors.py | 79 +++++++++++++++++++++++++++++ lib/matplotlib/tests/test_colors.py | 11 ++++ 2 files changed, 90 insertions(+) diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index 043a7986571c..ba0d5fbc396a 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -665,6 +665,30 @@ def _resample(self, lutsize): """ raise NotImplementedError() + def reversed(self, name=None): + """ + Make a reversed instance of the Colormap. + + NOTE: Function not implemented for base class. + + Parameters + ---------- + name : str, optional + The name for the reversed colormap. If it's None the + name will be the name of the parent colormap + "_r". + + Raises + ------ + NotImplementedError + Function not implemented for base class. + + Notes + ----- + See :meth:`LinearSegmentedColormap.reversed` and + :meth:`ListedColormap.reversed` + """ + raise NotImplementedError() + class LinearSegmentedColormap(Colormap): """Colormap objects based on lookup tables using linear segments. @@ -784,6 +808,40 @@ def _resample(self, lutsize): """ return LinearSegmentedColormap(self.name, self._segmentdata, lutsize) + def reversed(self, name=None): + """ + Make a reversed instance of the Colormap. + + Parameters + ---------- + name : str, optional + The name for the reversed colormap. If it's None the + name will be the name of the parent colormap + "_r". + + Returns + ------- + LinearSegmentedColormap + The reversed colormap. + """ + if name is None: + name = self.name + "_r" + + # Function factory needed to deal with 'late binding' issue. + def factory(dat): + def func_r(x): + return dat(1.0 - x) + return func_r + + data_r = dict() + for key, data in six.iteritems(self._segmentdata): + if six.callable(data): + data_r[key] = factory(data) + else: + new_data = [(1.0 - x, y1, y0) for x, y0, y1 in reversed(data)] + data_r[key] = new_data + + return LinearSegmentedColormap(name, data_r, self.N, self._gamma) + class ListedColormap(Colormap): """Colormap object generated from a list of colors. @@ -856,6 +914,27 @@ def _resample(self, lutsize): colors = self(np.linspace(0, 1, lutsize)) return ListedColormap(colors, name=self.name) + def reversed(self, name=None): + """ + Make a reversed instance of the Colormap. + + Parameters + ---------- + name : str, optional + The name for the reversed colormap. If it's None the + name will be the name of the parent colormap + "_r". + + Returns + ------- + ListedColormap + A reversed instance of the colormap. + """ + if name is None: + name = self.name + "_r" + + colors_r = list(reversed(self.colors)) + return ListedColormap(colors_r, name=name, N=self.N) + class Normalize(object): """ diff --git a/lib/matplotlib/tests/test_colors.py b/lib/matplotlib/tests/test_colors.py index de0200ebeaf5..0b2e21820ff1 100644 --- a/lib/matplotlib/tests/test_colors.py +++ b/lib/matplotlib/tests/test_colors.py @@ -587,6 +587,17 @@ def test_pandas_iterable(): cm2 = mcolors.ListedColormap(s, N=5) assert_sequence_equal(cm1.colors, cm2.colors) +def test_colormap_reversing(): + """Check the generated _lut data of a colormap and corresponding + reversed colormap if they are almost the same.""" + for name in six.iterkeys(cm.cmap_d): + cmap = plt.get_cmap(name) + cmap_r = cmap.reversed() + if not cmap_r._isinit: + cmap._init() + cmap_r._init() + assert_array_almost_equal(cmap._lut[:-3], cmap_r._lut[-4::-1]) + if __name__ == '__main__': import nose From 9f0aa6ea62b814b24227ec6072cf86bee8f4b54b Mon Sep 17 00:00:00 2001 From: Kjartan Myrdal Date: Wed, 23 Mar 2016 18:57:03 +0100 Subject: [PATCH 2/3] Blank line added in test_colors.py for pep8 consistency. --- lib/matplotlib/tests/test_colors.py | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/matplotlib/tests/test_colors.py b/lib/matplotlib/tests/test_colors.py index 0b2e21820ff1..12942edaa78e 100644 --- a/lib/matplotlib/tests/test_colors.py +++ b/lib/matplotlib/tests/test_colors.py @@ -587,6 +587,7 @@ def test_pandas_iterable(): cm2 = mcolors.ListedColormap(s, N=5) assert_sequence_equal(cm1.colors, cm2.colors) + def test_colormap_reversing(): """Check the generated _lut data of a colormap and corresponding reversed colormap if they are almost the same.""" From d2d997156f5003367fd066e4751470bc20b70dde Mon Sep 17 00:00:00 2001 From: Kjartan Myrdal Date: Sat, 26 Mar 2016 15:49:36 +0100 Subject: [PATCH 3/3] Docstring changes made based on comments: * NOTE: cnaged to .. note :: * Raises section removed Colormap.reversed docstring * methods mentioned in a new file under whats_new --- doc/users/whats_new/reversed_colormap.rst | 7 +++++++ lib/matplotlib/colors.py | 7 +------ 2 files changed, 8 insertions(+), 6 deletions(-) create mode 100644 doc/users/whats_new/reversed_colormap.rst diff --git a/doc/users/whats_new/reversed_colormap.rst b/doc/users/whats_new/reversed_colormap.rst new file mode 100644 index 000000000000..fb42757a7e5c --- /dev/null +++ b/doc/users/whats_new/reversed_colormap.rst @@ -0,0 +1,7 @@ +Colormap reversed method +------------------------ + +The methods :meth:`~matplotlib.colors.LinearSegmentedColormap.reversed` and +:meth:`~matplotlib.colors.ListedColormap.reversed` return a reversed +instance of the Colormap. This implements a way for any Colormap to be +reversed. \ No newline at end of file diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index ba0d5fbc396a..cf5869e8f5a5 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -669,7 +669,7 @@ def reversed(self, name=None): """ Make a reversed instance of the Colormap. - NOTE: Function not implemented for base class. + .. note :: Function not implemented for base class. Parameters ---------- @@ -677,11 +677,6 @@ def reversed(self, name=None): The name for the reversed colormap. If it's None the name will be the name of the parent colormap + "_r". - Raises - ------ - NotImplementedError - Function not implemented for base class. - Notes ----- See :meth:`LinearSegmentedColormap.reversed` and