Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 912ea58

Browse files
committed
Merge pull request #660 from efiring/colormap_alpha
Colormap alpha
2 parents 80d6bfd + 95e6fcd commit 912ea58

File tree

4 files changed

+96
-35
lines changed

4 files changed

+96
-35
lines changed

examples/pylab_examples/custom_cmap.py

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,16 @@
103103
(1.0, 0.0, 0.0))
104104
}
105105

106+
# Make a modified version of cdict3 with some transparency
107+
# in the middle of the range.
108+
cdict4 = cdict3.copy()
109+
cdict4['alpha'] = ((0.0, 1.0, 1.0),
110+
# (0.25,1.0, 1.0),
111+
(0.5, 0.3, 0.3),
112+
# (0.75,1.0, 1.0),
113+
(1.0, 1.0, 1.0))
114+
115+
106116
# Now we will use this example to illustrate 3 ways of
107117
# handling custom colormaps.
108118
# First, the most direct and explicit:
@@ -121,20 +131,27 @@
121131
# leave everything to register_cmap:
122132

123133
plt.register_cmap(name='BlueRed3', data=cdict3) # optional lut kwarg
134+
plt.register_cmap(name='BlueRedAlpha', data=cdict4)
135+
136+
# Make some illustrative fake data:
124137

125138
x = np.arange(0, np.pi, 0.1)
126139
y = np.arange(0, 2*np.pi, 0.1)
127140
X, Y = np.meshgrid(x,y)
128-
Z = np.cos(X) * np.sin(Y)
141+
Z = np.cos(X) * np.sin(Y) * 10
142+
143+
# Make the figure:
129144

130-
plt.figure(figsize=(10,4))
131-
plt.subplots_adjust(wspace=0.3)
145+
plt.figure(figsize=(6,9))
146+
plt.subplots_adjust(left=0.02, bottom=0.06, right=0.95, top=0.94, wspace=0.05)
132147

133-
plt.subplot(1,3,1)
148+
# Make 4 subplots:
149+
150+
plt.subplot(2,2,1)
134151
plt.imshow(Z, interpolation='nearest', cmap=blue_red1)
135152
plt.colorbar()
136153

137-
plt.subplot(1,3,2)
154+
plt.subplot(2,2,2)
138155
cmap = plt.get_cmap('BlueRed2')
139156
plt.imshow(Z, interpolation='nearest', cmap=cmap)
140157
plt.colorbar()
@@ -145,24 +162,32 @@
145162

146163
plt.rcParams['image.cmap'] = 'BlueRed3'
147164

148-
# Also see below for an alternative, particularly for
149-
# interactive use.
150-
151-
plt.subplot(1,3,3)
165+
plt.subplot(2,2,3)
152166
plt.imshow(Z, interpolation='nearest')
153167
plt.colorbar()
168+
plt.title("Alpha = 1")
154169

155-
# Or as yet another variation, we could replace the rcParams
170+
# Or as yet another variation, we can replace the rcParams
156171
# specification *before* the imshow with the following *after*
157-
# imshow:
158-
#
159-
# plt.set_cmap('BlueRed3')
160-
#
172+
# imshow.
161173
# This sets the new default *and* sets the colormap of the last
162174
# image-like item plotted via pyplot, if any.
175+
#
163176

177+
plt.subplot(2,2,4)
178+
# Draw a line with low zorder so it will be behind the image.
179+
plt.plot([0, 10*np.pi], [0, 20*np.pi], color='c', lw=20, zorder=-1)
180+
181+
plt.imshow(Z, interpolation='nearest')
182+
plt.colorbar()
183+
184+
# Here it is: changing the colormap for the current image and its
185+
# colorbar after they have been plotted.
186+
plt.set_cmap('BlueRedAlpha')
187+
plt.title("Varying alpha")
188+
#
164189

165-
plt.suptitle('Custom Blue-Red colormaps')
190+
plt.suptitle('Custom Blue-Red colormaps', fontsize=16)
166191

167192
plt.show()
168193

lib/matplotlib/cm.py

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -183,33 +183,59 @@ def set_colorbar(self, im, ax):
183183
self.colorbar = im, ax
184184

185185
def to_rgba(self, x, alpha=None, bytes=False):
186-
'''Return a normalized rgba array corresponding to *x*. If *x*
187-
is already an rgb array, insert *alpha*; if it is already
188-
rgba, return it unchanged. If *bytes* is True, return rgba as
189-
4 uint8s instead of 4 floats.
190-
'''
191-
if alpha is None:
192-
_alpha = 1.0
193-
else:
194-
_alpha = alpha
186+
"""
187+
Return a normalized rgba array corresponding to *x*.
188+
189+
In the normal case, *x* is a 1-D or 2-D sequence of scalars, and
190+
the corresponding ndarray of rgba values will be returned,
191+
based on the norm and colormap set for this ScalarMappable.
192+
193+
There is one special case, for handling images that are already
194+
rgb or rgba, such as might have been read from an image file.
195+
If *x* is an ndarray with 3 dimensions,
196+
and the last dimension is either 3 or 4, then it will be
197+
treated as an rgb or rgba array, and no mapping will be done.
198+
If the last dimension is 3, the *alpha* kwarg (defaulting to 1)
199+
will be used to fill in the transparency. If the last dimension
200+
is 4, the *alpha* kwarg is ignored; it does not
201+
replace the pre-existing alpha. A ValueError will be raised
202+
if the third dimension is other than 3 or 4.
203+
204+
In either case, if *bytes* is *False* (default), the rgba
205+
array will be floats in the 0-1 range; if it is *True*,
206+
the returned rgba array will be uint8 in the 0 to 255 range.
207+
208+
Note: this method assumes the input is well-behaved; it does
209+
not check for anomalies such as *x* being a masked rgba
210+
array, or being an integer type other than uint8, or being
211+
a floating point rgba array with values outside the 0-1 range.
212+
"""
213+
# First check for special case, image input:
195214
try:
196215
if x.ndim == 3:
197216
if x.shape[2] == 3:
217+
if alpha is None:
218+
alpha = 1
198219
if x.dtype == np.uint8:
199-
_alpha = np.array(_alpha*255, np.uint8)
220+
alpha = np.uint8(alpha * 255)
200221
m, n = x.shape[:2]
201222
xx = np.empty(shape=(m,n,4), dtype = x.dtype)
202223
xx[:,:,:3] = x
203-
xx[:,:,3] = _alpha
224+
xx[:,:,3] = alpha
204225
elif x.shape[2] == 4:
205226
xx = x
206227
else:
207228
raise ValueError("third dimension must be 3 or 4")
208229
if bytes and xx.dtype != np.uint8:
209230
xx = (xx * 255).astype(np.uint8)
231+
if not bytes and xx.dtype == np.uint8:
232+
xx = xx.astype(float) / 255
210233
return xx
211234
except AttributeError:
235+
# e.g., x is not an ndarray; so try mapping it
212236
pass
237+
238+
# This is the normal case, mapping a scalar array:
213239
x = ma.asarray(x)
214240
x = self.norm(x)
215241
x = self.cmap(x, alpha=alpha, bytes=bytes)

lib/matplotlib/colors.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -624,7 +624,7 @@ def __init__(self, name, segmentdata, N=256, gamma=1.0):
624624
625625
segmentdata argument is a dictionary with a red, green and blue
626626
entries. Each entry should be a list of *x*, *y0*, *y1* tuples,
627-
forming rows in a table.
627+
forming rows in a table. Entries for alpha are optional.
628628
629629
Example: suppose you want red to increase from 0 to 1 over
630630
the bottom half, green to do the same over the middle half,
@@ -680,6 +680,9 @@ def _init(self):
680680
self._segmentdata['green'], self._gamma)
681681
self._lut[:-3, 2] = makeMappingArray(self.N,
682682
self._segmentdata['blue'], self._gamma)
683+
if 'alpha' in self._segmentdata:
684+
self._lut[:-3, 3] = makeMappingArray(self.N,
685+
self._segmentdata['alpha'], 1)
683686
self._isinit = True
684687
self._set_extremes()
685688

@@ -711,12 +714,13 @@ def from_list(name, colors, N=256, gamma=1.0):
711714
else:
712715
vals = np.linspace(0., 1., len(colors))
713716

714-
cdict = dict(red=[], green=[], blue=[])
717+
cdict = dict(red=[], green=[], blue=[], alpha=[])
715718
for val, color in zip(vals, colors):
716-
r,g,b = colorConverter.to_rgb(color)
719+
r,g,b,a = colorConverter.to_rgba(color)
717720
cdict['red'].append((val, r, r))
718721
cdict['green'].append((val, g, g))
719722
cdict['blue'].append((val, b, b))
723+
cdict['alpha'].append((val, a, a))
720724

721725
return LinearSegmentedColormap(name, cdict, N, gamma)
722726

@@ -733,7 +737,8 @@ def __init__(self, colors, name = 'from_list', N = None):
733737
734738
*colors*
735739
a list of matplotlib color specifications,
736-
or an equivalent Nx3 floating point array (*N* rgb values)
740+
or an equivalent Nx3 or Nx4 floating point array
741+
(*N* rgb or rgba values)
737742
*name*
738743
a string to identify the colormap
739744
*N*
@@ -774,11 +779,9 @@ def __init__(self, colors, name = 'from_list', N = None):
774779

775780

776781
def _init(self):
777-
rgb = np.array([colorConverter.to_rgb(c)
778-
for c in self.colors], np.float)
782+
rgba = colorConverter.to_rgba_array(self.colors)
779783
self._lut = np.zeros((self.N + 3, 4), np.float)
780-
self._lut[:-3, :-1] = rgb
781-
self._lut[:-3, -1] = 1
784+
self._lut[:-3] = rgba
782785
self._isinit = True
783786
self._set_extremes()
784787

lib/matplotlib/image.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,14 @@ def _get_unsampled_image(self, A, image_extents, viewlim):
199199
im.is_grayscale = False
200200
else:
201201
if self._rgbacache is None:
202-
x = self.to_rgba(self._A, bytes=True)
202+
x = self.to_rgba(self._A, bytes=False)
203+
# Avoid side effects: to_rgba can return its argument
204+
# unchanged.
205+
if np.may_share_memory(x, self._A):
206+
x = x.copy()
207+
# premultiply the colors
208+
x[...,0:3] *= x[...,3:4]
209+
x = (x * 255).astype(np.uint8)
203210
self._rgbacache = x
204211
else:
205212
x = self._rgbacache

0 commit comments

Comments
 (0)