diff --git a/python/damask/_colormap.py b/python/damask/_colormap.py index 6b8da4909..97330baf3 100644 --- a/python/damask/_colormap.py +++ b/python/damask/_colormap.py @@ -193,25 +193,39 @@ class Colormap(mpl.colors.ListedColormap): def at(self, - fraction : float) -> np.ndarray: + fraction : Union[float,Sequence[float]], + with_alpha : bool = False, + as_string : bool = False) -> np.ndarray: """ Interpolate color at fraction. Parameters ---------- - fraction : float - Fractional coordinate to evaluate Colormap at. + fraction : float or sequence of float + Fractional coordinate(s) to evaluate Colormap at. + with_alpha : bool + Provide opacity as fourth value. + as_string : bool + Encode color as 'rgb(r,g,b)' or 'rgba(r,g,b,a)'. Returns ------- - color : np.ndarray, shape(3) - RGB values of interpolated color. + color : np.ndarray, shape(3 or 4), or string + RGB(A) values of interpolated color. """ - return interp.interp1d(np.linspace(0,1,self.N), - self.colors, - axis=0, - assume_sorted=True)(fraction) + def _stringify(color): + d = color.shape[-1] + c = np.array([f'rgba({c[0]},{c[1]},{c[2]},{c[3]})' if d==4 + else f'rgb({c[0]},{c[1]},{c[2]})' for c in np.atleast_2d(color)]) + return c if len(c)>1 else c[0] + + + color = interp.interp1d(np.linspace(0,1,self.N), + self.colors, + axis=0, + assume_sorted=True)(fraction)[...,:4 if with_alpha else 3] + return _stringify(color) if as_string else color def shade(self, diff --git a/python/tests/test_Colormap.py b/python/tests/test_Colormap.py index 2c2c78560..d411ca39d 100644 --- a/python/tests/test_Colormap.py +++ b/python/tests/test_Colormap.py @@ -139,12 +139,23 @@ class TestColormap: c += c assert (np.allclose(c.colors[:len(c.colors)//2],c.colors[len(c.colors)//2:])) - @pytest.mark.parametrize('N,cmap',[ - (8,'gray'), - (17,'gray'), - ]) - def test_at(self, N, cmap): - assert np.allclose(Colormap.from_predefined(cmap,N=N).at(0.5)[:3],0.5,rtol=0.005) + @pytest.mark.parametrize('N,cmap,at,with_alpha,result',[ + (8,'gray',0.5,False,[0.5,0.5,0.5]), + (17,'gray',0.5,False,[0.5,0.5,0.5]), + (17,'gray',[0.5,0.75],False,[[0.5,0.5,0.5],[0.75,0.75,0.75]]), + ]) + def test_at_value(self, N, cmap, at, with_alpha, result): + assert np.allclose(Colormap.from_predefined(cmap,N=N).at(at,with_alpha=with_alpha), + result, + rtol=0.005) + + @pytest.mark.parametrize('N,cmap,at,with_alpha,result',[ + (8,'gray',0.5,False,'rgb(0.5,0.5,0.5)'), + (8,'gray',0.5,True,'rgba(0.5,0.5,0.5,1.0)'), + (8,'gray',[0.5,0.25],True,['rgba(0.5,0.5,0.5,1.0)','rgba(0.25,0.25,0.25,1.0)']), + ]) + def test_at_string(self, N, cmap, at, with_alpha, result): + assert np.all(Colormap.from_predefined(cmap,N=N).at(at,with_alpha=with_alpha,as_string=True) == result) @pytest.mark.parametrize('bounds',[None,[2,10]]) def test_shade(self,ref_path,update,bounds):