From 3e1a6dcab730570f41174cca6972fb97e256ab38 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Tue, 23 Nov 2021 17:20:07 -0500 Subject: [PATCH] polished help; streamlined from_range() --- python/damask/_colormap.py | 114 ++++++++++++++++++------------------- 1 file changed, 54 insertions(+), 60 deletions(-) diff --git a/python/damask/_colormap.py b/python/damask/_colormap.py index 5032d6b18..d975aecd4 100644 --- a/python/damask/_colormap.py +++ b/python/damask/_colormap.py @@ -81,20 +81,20 @@ class Colormap(mpl.colors.ListedColormap): Parameters ---------- - low : numpy.ndarray of shape (3) + low : iterable of float (3) Color definition for minimum value. - high : numpy.ndarray of shape (3) + high : iterable of float (3) Color definition for maximum value. - N : int, optional - The number of color quantization levels. Defaults to 256. name : str, optional - The name of the colormap. Defaults to `DAMASK colormap`. + Name of the colormap. Defaults to `DAMASK colormap`. + N : int, optional + Number of color quantization levels. Defaults to 256. model : {'rgb', 'hsv', 'hsl', 'xyz', 'lab', 'msh'} Colormodel used for input color definitions. Defaults to `rgb`. The available color models are: - - 'rgb': R(ed) G(green) B(lue). - - 'hsv': H(ue) S(aturation) V(alue). - - 'hsl': H(ue) S(aturation) L(uminance). + - 'rgb': Red Green Blue. + - 'hsv': Hue Saturation Value. + - 'hsl': Hue Saturation Luminance. - 'xyz': CIE Xyz. - 'lab': CIE Lab. - 'msh': Msh (for perceptual uniform interpolation). @@ -110,41 +110,34 @@ class Colormap(mpl.colors.ListedColormap): >>> damask.Colormap.from_range((0,0,1),(0,0,0),'blue_to_black') """ - low_high = np.vstack((low,high)) - if model.lower() == 'rgb': - if np.any(low_high<0) or np.any(low_high>1): - raise ValueError(f'RGB color {low} | {high} are out of range.') + toMsh = dict( + rgb=Colormap._rgb2msh, + hsv=Colormap._hsv2msh, + hsl=Colormap._hsl2msh, + xyz=Colormap._xyz2msh, + lab=Colormap._lab2msh, + msh=lambda x:x, + ) - low_,high_ = map(Colormap._rgb2msh,low_high) - - elif model.lower() == 'hsv': - if np.any(low_high<0) or np.any(low_high>[360,1,1]): - raise ValueError(f'HSV color {low} | {high} are out of range.') - - low_,high_ = map(Colormap._hsv2msh,low_high) - - elif model.lower() == 'hsl': - if np.any(low_high<0) or np.any(low_high>[360,1,1]): - raise ValueError(f'HSL color {low} | {high} are out of range.') - - low_,high_ = map(Colormap._hsl2msh,low_high) - - elif model.lower() == 'xyz': - - low_,high_ = map(Colormap._xyz2msh,low_high) - - elif model.lower() == 'lab': - if np.any(low_high[:,0]<0): - raise ValueError(f'CIE Lab color {low} | {high} are out of range.') - - low_,high_ = map(Colormap._lab2msh,low_high) - - elif model.lower() == 'msh': - low_,high_ = low_high[0],low_high[1] - - else: + if model.lower() not in toMsh: raise ValueError(f'Invalid color model: {model}.') + low_high = np.vstack((low,high)) + outofbounds = np.bool_(False) + + if model.lower() == 'rgb': + outofbounds = np.any(low_high<0) or np.any(low_high>1) + elif model.lower() == 'hsv': + outofbounds = np.any(low_high<0) or np.any(low_high>[360,1,1]) + elif model.lower() == 'hsl': + outofbounds = np.any(low_high<0) or np.any(low_high>[360,1,1]) + elif model.lower() == 'lab': + outofbounds = np.any(low_high[:,0]<0) + + if outofbounds: + raise ValueError(f'{model.upper()} colors {low} | {high} are out of bounds.') + + low_,high_ = map(toMsh[model.lower()],low_high) msh = map(functools.partial(Colormap._interpolate_msh,low=low_,high=high_),np.linspace(0,1,N)) rgb = np.array(list(map(Colormap._msh2rgb,msh))) @@ -162,9 +155,9 @@ class Colormap(mpl.colors.ListedColormap): Parameters ---------- name : str - The name of the colormap. + Name of the colormap. N : int, optional - The number of color quantization levels. Defaults to 256. + Number of color quantization levels. Defaults to 256. This parameter is not used for matplotlib colormaps that are of type `ListedColormap`. @@ -179,8 +172,8 @@ class Colormap(mpl.colors.ListedColormap): >>> damask.Colormap.from_predefined('strain') """ - # matplotlib presets try: + # matplotlib presets colormap = cm.__dict__[name] return Colormap(np.array(list(map(colormap,np.linspace(0,1,N))) if isinstance(colormap,mpl.colors.LinearSegmentedColormap) else @@ -203,8 +196,8 @@ class Colormap(mpl.colors.ListedColormap): ---------- field : numpy.array of shape (:,:) Data to be shaded. - bounds : iterable of len (2), optional - Colormap value range (low,high). + bounds : iterable of float (2), optional + Value range (low,high) to shade with colormap. gap : field.dtype, optional Transparent value. NaN will always be rendered transparent. @@ -243,13 +236,13 @@ class Colormap(mpl.colors.ListedColormap): Parameters ---------- name : str, optional - The name for the reversed colormap. + Name for the reversed colormap. A name of None will be replaced by the name of the parent colormap + "_r". Returns ------- damask.Colormap - The reversed colormap. + Reversed colormap. Examples -------- @@ -268,7 +261,8 @@ class Colormap(mpl.colors.ListedColormap): Parameters ---------- fname : file, str, pathlib.Path, or None - Filename or filehandle, will be name of the colormap+extension if None. + Filename or filehandle. + If None, built from colormap name and ext. ext: str Extension of the filename. @@ -279,7 +273,7 @@ class Colormap(mpl.colors.ListedColormap): """ if fname is None: - return open(self.name.replace(' ','_')+'.'+ext, 'w', newline='\n') + return open(self.name.replace(' ','_')+(ext if ext.startswith('.') else '.'+ext), 'w', newline='\n') elif isinstance(fname, (str, Path)): return open(fname, 'w', newline='\n') else: @@ -294,7 +288,7 @@ class Colormap(mpl.colors.ListedColormap): ---------- fname : file, str, or pathlib.Path, optional Filename to store results. If not given, the filename will - consist of the name of the colormap and extension '.json'. + consist of the name of the colormap with extension '.json'. """ colors: List = [] @@ -320,7 +314,7 @@ class Colormap(mpl.colors.ListedColormap): ---------- fname : file, str, or pathlib.Path, optional Filename to store results. If not given, the filename will - consist of the name of the colormap and extension '.txt'. + consist of the name of the colormap with extension '.txt'. """ labels = {'RGBA':4} if self.colors.shape[1] == 4 else {'RGB': 3} @@ -336,7 +330,7 @@ class Colormap(mpl.colors.ListedColormap): ---------- fname : file, str, or pathlib.Path, optional Filename to store results. If not given, the filename will - consist of the name of the colormap and extension '.legend'. + consist of the name of the colormap with extension '.legend'. """ # ToDo: test in GOM @@ -357,7 +351,7 @@ class Colormap(mpl.colors.ListedColormap): ---------- fname : file, str, or pathlib.Path, optional Filename to store results. If not given, the filename will - consist of the name of the colormap and extension '.msh'. + consist of the name of the colormap with extension '.msh'. """ # ToDo: test in gmsh @@ -368,7 +362,7 @@ class Colormap(mpl.colors.ListedColormap): @staticmethod - def _interpolate_msh(frac, + def _interpolate_msh(frac: Union[float,int], low: np.ndarray, high: np.ndarray) -> np.ndarray: """ @@ -448,24 +442,24 @@ class Colormap(mpl.colors.ListedColormap): @staticmethod def _hsv2rgb(hsv: np.ndarray) -> np.ndarray: - """H(ue) S(aturation) V(alue) to R(red) G(reen) B(lue).""" + """Hue Saturation Value to Red Green Blue.""" return np.array(colorsys.hsv_to_rgb(hsv[0]/360.,hsv[1],hsv[2])) @staticmethod def _rgb2hsv(rgb: np.ndarray) -> np.ndarray: - """R(ed) G(reen) B(lue) to H(ue) S(aturation) V(alue).""" + """Red Green Blue to Hue Saturation Value.""" h,s,v = colorsys.rgb_to_hsv(rgb[0],rgb[1],rgb[2]) return np.array([h*360,s,v]) @staticmethod def _hsl2rgb(hsl: np.ndarray) -> np.ndarray: - """H(ue) S(aturation) L(uminance) to R(red) G(reen) B(lue).""" + """Hue Saturation Luminance to Red Green Blue.""" return np.array(colorsys.hls_to_rgb(hsl[0]/360.,hsl[2],hsl[1])) @staticmethod def _rgb2hsl(rgb: np.ndarray) -> np.ndarray: - """R(ed) G(reen) B(lue) to H(ue) S(aturation) L(uminance).""" + """Red Green Blue to Hue Saturation Luminance.""" h,l,s = colorsys.rgb_to_hls(rgb[0],rgb[1],rgb[2]) return np.array([h*360,s,l]) @@ -473,7 +467,7 @@ class Colormap(mpl.colors.ListedColormap): @staticmethod def _xyz2rgb(xyz: np.ndarray) -> np.ndarray: """ - CIE Xyz to R(ed) G(reen) B(lue). + CIE Xyz to Red Green Blue. References ---------- @@ -493,7 +487,7 @@ class Colormap(mpl.colors.ListedColormap): @staticmethod def _rgb2xyz(rgb: np.ndarray) -> np.ndarray: """ - R(ed) G(reen) B(lue) to CIE Xyz. + Red Green Blue to CIE Xyz. References ----------