ColorMap: keep RGBA values as uint8, clean up docstrings (#1722)
* keep RGBA values as uint8, clean up docstrings * ColorMap docstring correction * enum mapping fix 2
This commit is contained in:
parent
c62e51f4d8
commit
a6f9a2be12
@ -1,9 +1,9 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
from .Qt import QtGui, QtCore
|
from .Qt import QtGui, QtCore
|
||||||
from .python2_3 import basestring
|
|
||||||
from .functions import mkColor, eq
|
from .functions import mkColor, eq
|
||||||
from os import path, listdir
|
from os import path, listdir
|
||||||
from collections.abc import Callable, Sequence
|
from collections.abc import Callable, Sequence
|
||||||
|
import warnings
|
||||||
|
|
||||||
_mapCache = {}
|
_mapCache = {}
|
||||||
|
|
||||||
@ -193,16 +193,11 @@ class ColorMap(object):
|
|||||||
| 1.0 -> white
|
| 1.0 -> white
|
||||||
|
|
||||||
The colors for intermediate values are determined by interpolating between
|
The colors for intermediate values are determined by interpolating between
|
||||||
the two nearest colors in either RGB or HSV color space.
|
the two nearest colors in RGB color space.
|
||||||
|
|
||||||
To provide user-defined color mappings, see :class:`GradientWidget <pyqtgraph.GradientWidget>`.
|
To provide user-defined color mappings, see :class:`GradientWidget <pyqtgraph.GradientWidget>`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
## color interpolation modes
|
|
||||||
RGB = 1
|
|
||||||
HSV_POS = 2
|
|
||||||
HSV_NEG = 3
|
|
||||||
|
|
||||||
## mapping modes
|
## mapping modes
|
||||||
CLIP = 1
|
CLIP = 1
|
||||||
REPEAT = 2
|
REPEAT = 2
|
||||||
@ -215,59 +210,52 @@ class ColorMap(object):
|
|||||||
QCOLOR = 3
|
QCOLOR = 3
|
||||||
|
|
||||||
enumMap = {
|
enumMap = {
|
||||||
'rgb': RGB,
|
'clip': CLIP,
|
||||||
# 'hsv+': HSV_POS,
|
'repeat': REPEAT,
|
||||||
# 'hsv-': HSV_NEG,
|
'mirror': MIRROR,
|
||||||
# 'clip': CLIP,
|
'diverging': DIVERGING,
|
||||||
# 'repeat': REPEAT,
|
|
||||||
'byte': BYTE,
|
'byte': BYTE,
|
||||||
'float': FLOAT,
|
'float': FLOAT,
|
||||||
'qcolor': QCOLOR,
|
'qcolor': QCOLOR,
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, pos, color, mode=None, mapping=None): #, names=None):
|
def __init__(self, pos, color, mapping=CLIP, mode=None): #, names=None):
|
||||||
"""
|
"""
|
||||||
=============== =================================================================
|
=============== =======================================================================
|
||||||
**Arguments:**
|
**Arguments:**
|
||||||
pos Array of positions where each color is defined
|
pos Array of positions where each color is defined
|
||||||
color Array of colors.
|
color Array of colors.
|
||||||
Values are interpreted via
|
Values are interpreted via
|
||||||
:func:`mkColor() <pyqtgraph.mkColor>`.
|
:func:`mkColor() <pyqtgraph.mkColor>`.
|
||||||
mode Array of color modes (ColorMap.RGB, HSV_POS, or HSV_NEG)
|
mapping Mapping mode (ColorMap.CLIP, REPEAT, MIRROR or DIVERGING)
|
||||||
indicating the color space that should be used when
|
controlling mapping of relative index to color. String representations
|
||||||
interpolating between stops. Note that the last mode value is
|
'clip', 'repeat', 'mirror' or 'diverging' are also accepted.
|
||||||
ignored. By default, the mode is entirely RGB.
|
CLIP maps colors to [0.0;1.0] and is the default.
|
||||||
mapping Mapping mode (ColorMap.CLIP, REPEAT, MIRROR, or DIVERGING)
|
|
||||||
controlling mapping of relative index to color.
|
|
||||||
CLIP maps colors to [0.0;1.0]
|
|
||||||
REPEAT maps colors to repeating intervals [0.0;1.0];[1.0-2.0],...
|
REPEAT maps colors to repeating intervals [0.0;1.0];[1.0-2.0],...
|
||||||
MIRROR maps colors to [0.0;-1.0] and [0.0;+1.0] identically
|
MIRROR maps colors to [0.0;-1.0] and [0.0;+1.0] identically
|
||||||
DIVERGING maps colors to [-1.0;+1.0]
|
DIVERGING maps colors to [-1.0;+1.0]
|
||||||
=============== =================================================================
|
=============== =======================================================================
|
||||||
"""
|
"""
|
||||||
|
if mode is not None:
|
||||||
|
warnings.warn(
|
||||||
|
"'mode' argument is deprecated and does nothing.",
|
||||||
|
DeprecationWarning, stacklevel=2
|
||||||
|
)
|
||||||
|
if isinstance(mapping, str):
|
||||||
|
mapping = self.enumMap[mapping.lower()]
|
||||||
|
|
||||||
self.pos = np.array(pos)
|
self.pos = np.array(pos)
|
||||||
order = np.argsort(self.pos)
|
order = np.argsort(self.pos)
|
||||||
self.pos = self.pos[order]
|
self.pos = self.pos[order]
|
||||||
self.color = np.apply_along_axis(
|
self.color = np.apply_along_axis(
|
||||||
func1d = lambda x: mkColor(x).getRgb(),
|
func1d = lambda x: np.uint8( mkColor(x).getRgb() ), # cast RGB integer values to uint8
|
||||||
axis = -1,
|
axis = -1,
|
||||||
arr = color,
|
arr = color,
|
||||||
)[order]
|
)[order]
|
||||||
if mode is None:
|
|
||||||
mode = np.ones(len(pos))
|
|
||||||
self.mode = mode
|
|
||||||
|
|
||||||
if mapping is None:
|
|
||||||
self.mapping_mode = self.CLIP
|
|
||||||
elif mapping == self.REPEAT:
|
|
||||||
self.mapping_mode = self.REPEAT
|
|
||||||
elif mapping == self.DIVERGING:
|
|
||||||
self.mapping_mode = self.DIVERGING
|
|
||||||
elif mapping == self.MIRROR:
|
|
||||||
self.mapping_mode = self.MIRROR
|
|
||||||
else:
|
|
||||||
self.mapping_mode = self.CLIP
|
|
||||||
|
|
||||||
|
self.mapping_mode = self.CLIP # default to CLIP mode
|
||||||
|
if mapping in [self.CLIP, self.REPEAT, self.DIVERGING, self.MIRROR]:
|
||||||
|
self.mapping_mode = mapping # only allow defined values
|
||||||
self.stopsCache = {}
|
self.stopsCache = {}
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
@ -281,7 +269,7 @@ class ColorMap(object):
|
|||||||
except ValueError: pass
|
except ValueError: pass
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def map(self, data, mode='byte'):
|
def map(self, data, mode=BYTE):
|
||||||
"""
|
"""
|
||||||
Return an array of colors corresponding to the values in *data*.
|
Return an array of colors corresponding to the values in *data*.
|
||||||
Data must be either a scalar position or an array (any shape) of positions.
|
Data must be either a scalar position or an array (any shape) of positions.
|
||||||
@ -294,7 +282,7 @@ class ColorMap(object):
|
|||||||
qcolor Values are returned as an array of QColor objects.
|
qcolor Values are returned as an array of QColor objects.
|
||||||
=========== ===============================================================
|
=========== ===============================================================
|
||||||
"""
|
"""
|
||||||
if isinstance(mode, basestring):
|
if isinstance(mode, str):
|
||||||
mode = self.enumMap[mode.lower()]
|
mode = self.enumMap[mode.lower()]
|
||||||
|
|
||||||
if mode == self.QCOLOR:
|
if mode == self.QCOLOR:
|
||||||
@ -302,9 +290,6 @@ class ColorMap(object):
|
|||||||
else:
|
else:
|
||||||
pos, color = self.getStops(mode)
|
pos, color = self.getStops(mode)
|
||||||
|
|
||||||
# Interpolate
|
|
||||||
# TODO: is griddata faster?
|
|
||||||
# interp = scipy.interpolate.griddata(pos, color, data)
|
|
||||||
if np.isscalar(data):
|
if np.isscalar(data):
|
||||||
interp = np.empty((color.shape[1],), dtype=color.dtype)
|
interp = np.empty((color.shape[1],), dtype=color.dtype)
|
||||||
else:
|
else:
|
||||||
@ -364,7 +349,7 @@ class ColorMap(object):
|
|||||||
def getColors(self, mode=None):
|
def getColors(self, mode=None):
|
||||||
"""Return list of all color stops converted to the specified mode.
|
"""Return list of all color stops converted to the specified mode.
|
||||||
If mode is None, then no conversion is done."""
|
If mode is None, then no conversion is done."""
|
||||||
if isinstance(mode, basestring):
|
if isinstance(mode, str):
|
||||||
mode = self.enumMap[mode.lower()]
|
mode = self.enumMap[mode.lower()]
|
||||||
|
|
||||||
color = self.color
|
color = self.color
|
||||||
@ -383,11 +368,9 @@ class ColorMap(object):
|
|||||||
if mode not in self.stopsCache:
|
if mode not in self.stopsCache:
|
||||||
color = self.color
|
color = self.color
|
||||||
if mode == self.BYTE and color.dtype.kind == 'f':
|
if mode == self.BYTE and color.dtype.kind == 'f':
|
||||||
color = (color * 255).astype(np.ubyte)
|
color = (color*255).astype(np.ubyte)
|
||||||
elif mode == self.FLOAT and color.dtype.kind != 'f':
|
elif mode == self.FLOAT and color.dtype.kind != 'f':
|
||||||
color = color.astype(float) / 255.
|
color = color.astype(float) / 255.
|
||||||
|
|
||||||
## to support HSV mode, we need to do a little more work..
|
|
||||||
self.stopsCache[mode] = (self.pos, color)
|
self.stopsCache[mode] = (self.pos, color)
|
||||||
return self.stopsCache[mode]
|
return self.stopsCache[mode]
|
||||||
|
|
||||||
@ -406,7 +389,7 @@ class ColorMap(object):
|
|||||||
See :func:`map() <pyqtgraph.ColorMap.map>`.
|
See :func:`map() <pyqtgraph.ColorMap.map>`.
|
||||||
=============== =============================================================================
|
=============== =============================================================================
|
||||||
"""
|
"""
|
||||||
if isinstance(mode, basestring):
|
if isinstance(mode, str):
|
||||||
mode = self.enumMap[mode.lower()]
|
mode = self.enumMap[mode.lower()]
|
||||||
|
|
||||||
if alpha is None:
|
if alpha is None:
|
||||||
|
@ -93,7 +93,7 @@ def test_NonUniformImage_colormap():
|
|||||||
|
|
||||||
image = NonUniformImage(x, y, Z, border=fn.mkPen('g'))
|
image = NonUniformImage(x, y, Z, border=fn.mkPen('g'))
|
||||||
|
|
||||||
cmap = ColorMap(pos=[0.0, 1.0], color=[(0.0, 0.0, 0.0, 1.0), (1.0, 1.0, 1.0, 1.0)], mode='rgb')
|
cmap = ColorMap(pos=[0.0, 1.0], color=[(0.0, 0.0, 0.0, 1.0), (1.0, 1.0, 1.0, 1.0)])
|
||||||
image.setColorMap(cmap)
|
image.setColorMap(cmap)
|
||||||
|
|
||||||
viewbox.addItem(image)
|
viewbox.addItem(image)
|
||||||
|
Loading…
Reference in New Issue
Block a user