Skip to content

Implemented __copy__ in Colormap #8314

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

Closed
wants to merge 9 commits into from
Closed
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Fixed __copy__ indentation
  • Loading branch information
vidursatija authored Mar 17, 2017
commit 82cccd003e1a9eff6fcca7de9f24fcd44a2b4657
17 changes: 8 additions & 9 deletions lib/matplotlib/colors.py
Original file line number Diff line number Diff line change
Expand Up @@ -532,15 +532,14 @@ def __call__(self, X, alpha=None, bytes=False):

def __copy__(self):
"""Create new object with the same class and update attributes
If object is initialized, copy the elements of _lut list
"""
cls = self.__class__
newCMapObj = cls.__new__(cls)
newCMapObj.__dict__.update(self.__dict__)
if self._isinit:
newCMapObj._lut = np.copy(self._lut)
return newCMapObj

If object is initialized, copy the elements of _lut list
"""
cls = self.__class__
Copy link
Member

Choose a reason for hiding this comment

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

Is this really the best way to do this? It seems to be dropping down to a low layer of python.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The low layer of python is presumably faster than the normal python code. Another way of doing this would be creating a normal Colormap object and manually copying each attribute.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

How should I implement a test?

Copy link
Member

Choose a reason for hiding this comment

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

Get a color map, use it (cm([-1, 0, .5, 1, np.nan, np.inf]), copy it, use set_bad, set_over, set_under on one or both of them, use them both and check that the colors come back as expected.

Copy link
Member

Choose a reason for hiding this comment

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

I would not expect this to be much faster. If you think it is can you bench mark it?

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 will bench mark it and implement the tests. I'll post the results soon.

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 have bench marked the 2 functions.
The following code is used:

import matplotlib.pyplot as plt
import time

cm = plt.cm.Reds

start = time.time()
cm2 = cm.copy_1()     #Using low level python
end1 = time.time()
cm3 = cm.copy_2()     #Copying the attributes manually
end2 = time.time()
print("Method 1 :" + str(end1-start))
print("Method 2 :" + str(end2-end1))

I get the following output:
Method 1 :1.8358230590820312e-05
Method 2 :2.6941299438476562e-05

I can definitely say that using low level python functions would lead to a simpler, faster code, which might be a little difficult to understand by seeing it.

Test

I've used the copy_1 function to copy the object.

import numpy as np
import matplotlib.pyplot as plt

cm = plt.cm.Reds
cm([-1, 0, .5, np.nan, np.inf])

cm.set_bad('y')
cm2 = cm.copy_1()
cm2.set_bad('b')
print(cm._rgba_bad)
print(cm2._rgba_bad)

cm.set_under('y')
cm2.set_under('r')
print(cm._rgba_under)
print(cm2._rgba_under)

cm.set_over('c')
cm2.set_over('m')
print(cm._rgba_over)
print(cm2._rgba_over)

Output is as follows:
(0.75, 0.75, 0.0, 1)
(0.0, 0.0, 1.0, 1)
(0.75, 0.75, 0.0, 1)
(1.0, 0.0, 0.0, 1)
(0.0, 0.75, 0.75, 1)
(0.75, 0.0, 0.75, 1)

As we can see, using the function on both Colormaps doesn't change the other

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My last commit (3ece4cb) has used lower level python to implement copy. The code has also used spaces instead of tabs

newCMapObj = cls.__new__(cls)
newCMapObj.__dict__.update(self.__dict__)
if self._isinit:
newCMapObj._lut = np.copy(self._lut)
Copy link
Member

Choose a reason for hiding this comment

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

Please use spaces instead of tabs

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'll update it

return newCMapObj

def set_bad(self, color='k', alpha=None):
"""Set color to be used for masked values.
Expand Down