Skip to content

Adding an equals method to colormaps #20227

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions lib/matplotlib/colors.py
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,17 @@ def __copy__(self):
cmapobject._global = False
return cmapobject

def __eq__(self, other):
if (not isinstance(other, Colormap) or self.name != other.name or
self.colorbar_extend != other.colorbar_extend):
return False
# To compare lookup tables the Colormaps have to be initialized
if not self._isinit:
self._init()
if not other._isinit:
other._init()
return np.array_equal(self._lut, other._lut)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

colormaps know their own name, is that something we want to also check?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, IMHO we should. As we use it now, the name is an integral part of the colormap. Otherwise you can get funny behavior, e.g. with the new colormap registry

cmap in colormaps.values()  # True
cmap.name in colormaps.keys()  # False

And similar.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a strong opinion either way. I was viewing the == to mean "will these colormaps look the same". If cmocean defines a "Blues1" colormap and it looks suspiciously similar to MPL's "Blues", I may want to check for that equality and not name equality. I do see TIm's point though, so I am fine adding it if that is what is wanted.

I suppose we should also add colorbar_extends too in case someone changed that.

Copy link
Member

@timhoffm timhoffm May 14, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see the point in "will these colormaps look the same", but as long as we have Colormap.name I think it has to be taken into account for __eq__. You could introduce a Colormap.is_equivalent() for "look the same". OTOH I don't think there is a strong reason a colormap has to know its name, but removing that is hard to justify as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I added in the comparisons for name and colorbar_extend. Also added tests for those two situations.


def get_bad(self):
"""Get the color for masked values."""
if not self._isinit:
Expand Down
23 changes: 23 additions & 0 deletions lib/matplotlib/tests/test_colors.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,29 @@ def test_colormap_copy():
assert_array_equal(ret1, ret2)


def test_colormap_equals():
cmap = plt.get_cmap("plasma")
cm_copy = cmap.copy()
# different object id's
assert cm_copy is not cmap
# But the same data should be equal
assert cm_copy == cmap
# Change the copy
cm_copy.set_bad('y')
assert cm_copy != cmap
# Make sure we can compare different sizes without failure
cm_copy._lut = cm_copy._lut[:10, :]
assert cm_copy != cmap
# Test different names are not equal
cm_copy = cmap.copy()
cm_copy.name = "Test"
assert cm_copy != cmap
# Test colorbar extends
cm_copy = cmap.copy()
cm_copy.colorbar_extend = not cmap.colorbar_extend
assert cm_copy != cmap


def test_colormap_endian():
"""
GitHub issue #1005: a bug in putmask caused erroneous
Expand Down