Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 1a3d16b

Browse filesBrowse files
committed
Bivariate works with imshow, pcolor, pcolormesh, pcolorfast
1 parent 90eae1f commit 1a3d16b
Copy full SHA for 1a3d16b

File tree

2 files changed

+170
-10
lines changed
Filter options

2 files changed

+170
-10
lines changed

‎lib/matplotlib/axes/_axes.py

Copy file name to clipboardExpand all lines: lib/matplotlib/axes/_axes.py
+86-10Lines changed: 86 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5081,12 +5081,30 @@ def imshow(self, X, cmap=None, norm=None, aspect=None,
50815081
if not self._hold:
50825082
self.cla()
50835083

5084-
if norm is not None and not isinstance(norm, mcolors.Normalize):
5085-
msg = "'norm' must be an instance of 'mcolors.Normalize'"
5084+
isNorm = isinstance(norm, (mcolors.Normalize, mcolors.BivariateNorm))
5085+
if norm is not None and not isNorm:
5086+
msg = "'norm' must be an instance of 'mcolors.Normalize' " \
5087+
"or 'mcolors.BivariateNorm'"
50865088
raise ValueError(msg)
5089+
50875090
if aspect is None:
50885091
aspect = rcParams['image.aspect']
50895092
self.set_aspect(aspect)
5093+
5094+
temp = np.asarray(X)
5095+
if (temp.ndim == 3 and isinstance(norm, mcolors.BivariateNorm) or
5096+
isinstance(cmap, mcolors.BivariateColormap)):
5097+
if cmap is None:
5098+
cmap = mcolors.BivariateColormap()
5099+
if norm is None:
5100+
norm = mcolors.BivariateNorm()
5101+
temp = norm(temp)
5102+
temp[0] = temp[0] * (cmap.N-1)
5103+
temp[1] = temp[1] * (cmap.N-1)
5104+
temp = temp.astype(int)
5105+
X = temp[0] + cmap.N * temp[1]
5106+
norm = mcolors.NoNorm()
5107+
50905108
im = mimage.AxesImage(self, cmap, norm, interpolation, origin, extent,
50915109
filternorm=filternorm, filterrad=filterrad,
50925110
resample=resample, **kwargs)
@@ -5113,7 +5131,6 @@ def imshow(self, X, cmap=None, norm=None, aspect=None,
51135131

51145132
@staticmethod
51155133
def _pcolorargs(funcname, *args, **kw):
5116-
# This takes one kwarg, allmatch.
51175134
# If allmatch is True, then the incoming X, Y, C must
51185135
# have matching dimensions, taking into account that
51195136
# X and Y can be 1-D rather than 2-D. This perfect
@@ -5126,9 +5143,25 @@ def _pcolorargs(funcname, *args, **kw):
51265143
# is False.
51275144

51285145
allmatch = kw.pop("allmatch", False)
5146+
norm = kw.pop("norm", None)
5147+
cmap = kw.pop("cmap", None)
51295148

51305149
if len(args) == 1:
51315150
C = np.asanyarray(args[0])
5151+
5152+
if (C.ndim == 3 and isinstance(norm, mcolors.BivariateNorm) or
5153+
isinstance(cmap, mcolors.BivariateColormap)):
5154+
if cmap is None:
5155+
cmap = mcolors.BivariateColormap()
5156+
if norm is None:
5157+
norm = mcolors.BivariateNorm()
5158+
C = norm(C)
5159+
C[0] = C[0] * (cmap.N-1)
5160+
C[1] = C[1] * (cmap.N-1)
5161+
C = C.astype(int)
5162+
C = C[0] + cmap.N * C[1]
5163+
C = np.array(C)
5164+
51325165
numRows, numCols = C.shape
51335166
if allmatch:
51345167
X, Y = np.meshgrid(np.arange(numCols), np.arange(numRows))
@@ -5140,6 +5173,18 @@ def _pcolorargs(funcname, *args, **kw):
51405173

51415174
if len(args) == 3:
51425175
X, Y, C = [np.asanyarray(a) for a in args]
5176+
if (C.ndim == 3 and isinstance(norm, mcolors.BivariateNorm) or
5177+
isinstance(cmap, mcolors.BivariateColormap)):
5178+
if cmap is None:
5179+
cmap = mcolors.BivariateColormap()
5180+
if norm is None:
5181+
norm = mcolors.BivariateNorm()
5182+
C = norm(C)
5183+
C[0] = C[0] * (cmap.N-1)
5184+
C[1] = C[1] * (cmap.N-1)
5185+
C = C.astype(int)
5186+
C = C[0] + cmap.N * C[1]
5187+
C = np.array(C)
51435188
numRows, numCols = C.shape
51445189
else:
51455190
raise TypeError(
@@ -5325,9 +5370,14 @@ def pcolor(self, *args, **kwargs):
53255370
vmin = kwargs.pop('vmin', None)
53265371
vmax = kwargs.pop('vmax', None)
53275372

5328-
X, Y, C = self._pcolorargs('pcolor', *args, allmatch=False)
5373+
kw = {'norm': norm, 'cmap': cmap, 'allmatch': False}
5374+
X, Y, C = self._pcolorargs('pcolor', *args, **kw)
53295375
Ny, Nx = X.shape
53305376

5377+
if (isinstance(norm, mcolors.BivariateNorm) or
5378+
isinstance(cmap, mcolors.BivariateColormap)):
5379+
norm = mcolors.NoNorm()
5380+
53315381
# unit conversion allows e.g. datetime objects as axis values
53325382
self._process_unit_info(xdata=X, ydata=Y, kwargs=kwargs)
53335383
X = self.convert_xunits(X)
@@ -5393,9 +5443,13 @@ def pcolor(self, *args, **kwargs):
53935443

53945444
collection.set_alpha(alpha)
53955445
collection.set_array(C)
5396-
if norm is not None and not isinstance(norm, mcolors.Normalize):
5397-
msg = "'norm' must be an instance of 'mcolors.Normalize'"
5446+
5447+
isNorm = isinstance(norm, (mcolors.Normalize, mcolors.BivariateNorm))
5448+
if norm is not None and not isNorm:
5449+
msg = "'norm' must be an instance of 'mcolors.Normalize' " \
5450+
"or 'mcolors.BivariateNorm'"
53985451
raise ValueError(msg)
5452+
53995453
collection.set_cmap(cmap)
54005454
collection.set_norm(norm)
54015455
collection.set_clim(vmin, vmax)
@@ -5525,9 +5579,14 @@ def pcolormesh(self, *args, **kwargs):
55255579

55265580
allmatch = (shading == 'gouraud')
55275581

5528-
X, Y, C = self._pcolorargs('pcolormesh', *args, allmatch=allmatch)
5582+
kw = {'norm': norm, 'cmap': cmap, 'allmatch': allmatch}
5583+
X, Y, C = self._pcolorargs('pcolormesh', *args, **kw)
55295584
Ny, Nx = X.shape
55305585

5586+
if (isinstance(norm, mcolors.BivariateNorm) or
5587+
isinstance(cmap, mcolors.BivariateColormap)):
5588+
norm = mcolors.NoNorm()
5589+
55315590
# unit conversion allows e.g. datetime objects as axis values
55325591
self._process_unit_info(xdata=X, ydata=Y, kwargs=kwargs)
55335592
X = self.convert_xunits(X)
@@ -5666,11 +5725,28 @@ def pcolorfast(self, *args, **kwargs):
56665725
cmap = kwargs.pop('cmap', None)
56675726
vmin = kwargs.pop('vmin', None)
56685727
vmax = kwargs.pop('vmax', None)
5669-
if norm is not None and not isinstance(norm, mcolors.Normalize):
5670-
msg = "'norm' must be an instance of 'mcolors.Normalize'"
5728+
isNorm = isinstance(norm, (mcolors.Normalize, mcolors.BivariateNorm))
5729+
if norm is not None and not isNorm:
5730+
msg = "'norm' must be an instance of 'mcolors.Normalize' " \
5731+
"or 'mcolors.BivariateNorm'"
56715732
raise ValueError(msg)
56725733

5673-
C = args[-1]
5734+
C = np.asarray(args[-1])
5735+
5736+
if (C.ndim == 3 and isinstance(norm, mcolors.BivariateNorm) or
5737+
isinstance(cmap, mcolors.BivariateColormap)):
5738+
if cmap is None:
5739+
cmap = mcolors.BivariateColormap()
5740+
if norm is None:
5741+
norm = mcolors.BivariateNorm()
5742+
C = norm(C)
5743+
C[0] = C[0] * (cmap.N-1)
5744+
C[1] = C[1] * (cmap.N-1)
5745+
C = C.astype(int)
5746+
C = C[0] + cmap.N * C[1]
5747+
C = np.array(C)
5748+
norm = mcolors.NoNorm()
5749+
56745750
nr, nc = C.shape
56755751
if len(args) == 1:
56765752
style = "image"

‎lib/matplotlib/colors.py

Copy file name to clipboardExpand all lines: lib/matplotlib/colors.py
+84Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -855,6 +855,32 @@ def reversed(self, name=None):
855855
return ListedColormap(colors_r, name=name, N=self.N)
856856

857857

858+
class BivariateColormap(Colormap):
859+
def __init__(self, name, N=256):
860+
Colormap.__init__(self, name, N)
861+
862+
def _init(self):
863+
red = np.linspace(0, 1, self.N)
864+
green = np.linspace(0, 1, self.N)
865+
red_mesh, green_mesh = np.meshgrid(red, green)
866+
blue_mesh = np.zeros_like(red_mesh)
867+
alpha_mesh = np.ones_like(red_mesh)
868+
bivariate_cmap = np.dstack((red_mesh, green_mesh, blue_mesh, alpha_mesh))
869+
self._lut = np.vstack(bivariate_cmap)
870+
self._isinit = True
871+
self.N = self.N * self.N
872+
self._set_extremes()
873+
874+
def _resample(self, lutsize):
875+
"""
876+
Return a new color map with *lutsize x lutsize* entries.
877+
"""
878+
return BivariateColormap(self.name, lutsize)
879+
880+
def reversed(self, name=None):
881+
raise NotImplementedError()
882+
883+
858884
class Normalize(object):
859885
"""
860886
A class which, when called, can normalize data into
@@ -1403,6 +1429,64 @@ def inverse(self, values):
14031429
"""
14041430
return [self.norm1.inverse(values[0]), self.norm.inverse(values[1])]
14051431

1432+
class BivariateNorm:
1433+
"""
1434+
Normalize a list of two values corresponding to two 1D normalizers
1435+
"""
1436+
def __init__(self, norm1=None, norm2=None):
1437+
"""
1438+
Parameters
1439+
----------
1440+
norm1 :
1441+
An instance of 1D normalizers
1442+
norm2 :
1443+
An instance of 1D normalizers
1444+
"""
1445+
if norm1 is None:
1446+
self.norm1 = Normalize()
1447+
else:
1448+
self.norm1 = norm1
1449+
if norm2 is None:
1450+
self.norm2 = Normalize()
1451+
else:
1452+
self.norm2 = norm2
1453+
1454+
def __call__(self, values, clip=None):
1455+
"""
1456+
Parameters
1457+
----------
1458+
values : array-like
1459+
A list of two values to be normalized
1460+
clip : list of bools, None, optional
1461+
A list of two bools corresponding to value in values.
1462+
If clip is None then clip is set according to corresponding
1463+
normalizers.
1464+
1465+
Returns
1466+
-------
1467+
A list of two normalized values according to corresponding 1D
1468+
normalizers.
1469+
"""
1470+
if clip is None:
1471+
clip = [self.norm1.clip, self.norm2.clip]
1472+
1473+
return np.array([self.norm1(values[0], clip=clip[0]),
1474+
self.norm2(values[1], clip=clip[1])])
1475+
1476+
def inverse(self, values):
1477+
"""
1478+
Parameters
1479+
----------
1480+
values : array-like
1481+
A list of two values to be inverted
1482+
1483+
Returns
1484+
-------
1485+
A list of two unnormalized values
1486+
"""
1487+
return [self.norm1.inverse(values[0]), self.norm.inverse(values[1])]
1488+
1489+
14061490
def rgb_to_hsv(arr):
14071491
"""
14081492
convert float rgb values (in the range [0, 1]), in a numpy array to hsv

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.