code shortening; list_predefined() --> property "predefined"
This commit is contained in:
parent
fd8743af5e
commit
de20e6b35d
|
@ -22,6 +22,16 @@ _ref_white = np.array([.95047, 1.00000, 1.08883])
|
||||||
# - support NaN color (paraview)
|
# - support NaN color (paraview)
|
||||||
|
|
||||||
class Colormap(mpl.colors.ListedColormap):
|
class Colormap(mpl.colors.ListedColormap):
|
||||||
|
"""
|
||||||
|
References
|
||||||
|
----------
|
||||||
|
[1] DAMASK colormap theory
|
||||||
|
https://www.kennethmoreland.com/color-maps/ColorMapsExpanded.pdf
|
||||||
|
[2] DAMASK colormaps first use
|
||||||
|
https://doi.org/10.1016/j.ijplas.2012.09.012
|
||||||
|
[3] Matplotlib colormaps overview
|
||||||
|
https://matplotlib.org/tutorials/colors/colormaps.html
|
||||||
|
"""
|
||||||
|
|
||||||
def __add__(self,other):
|
def __add__(self,other):
|
||||||
"""Concatenate colormaps."""
|
"""Concatenate colormaps."""
|
||||||
|
@ -137,51 +147,27 @@ class Colormap(mpl.colors.ListedColormap):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# matplotlib presets
|
# matplotlib presets
|
||||||
for cat in Colormap._predefined_mpl:
|
try:
|
||||||
for n in cat[1]:
|
|
||||||
if n == name:
|
|
||||||
colormap = cm.__dict__[name]
|
colormap = cm.__dict__[name]
|
||||||
if isinstance(colormap,mpl.colors.LinearSegmentedColormap):
|
return Colormap(np.array(list(map(colormap,np.linspace(0,1,N)))
|
||||||
return Colormap(np.array(list(map(colormap,np.linspace(0,1,N)))),name=name)
|
if isinstance(colormap,mpl.colors.LinearSegmentedColormap) else
|
||||||
else:
|
colormap.colors),
|
||||||
return Colormap(np.array(colormap.colors),name=name)
|
name=name)
|
||||||
|
except:
|
||||||
# DAMASK presets
|
# DAMASK presets
|
||||||
definition = Colormap._predefined_DAMASK[name]
|
definition = Colormap._predefined_DAMASK[name]
|
||||||
return Colormap.from_range(definition['low'],definition['high'],name,N)
|
return Colormap.from_range(definition['low'],definition['high'],name,N)
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def list_predefined():
|
|
||||||
"""
|
|
||||||
List predefined colormaps by category.
|
|
||||||
|
|
||||||
References
|
|
||||||
----------
|
|
||||||
[1] DAMASK colormap theory
|
|
||||||
https://www.kennethmoreland.com/color-maps/ColorMapsExpanded.pdf
|
|
||||||
[2] DAMASK colormaps first use
|
|
||||||
https://doi.org/10.1016/j.ijplas.2012.09.012
|
|
||||||
[3] Matplotlib colormaps overview
|
|
||||||
https://matplotlib.org/tutorials/colors/colormaps.html
|
|
||||||
|
|
||||||
"""
|
|
||||||
print('DAMASK colormaps')
|
|
||||||
print(' '+', '.join(Colormap._predefined_DAMASK.keys()))
|
|
||||||
for cat in Colormap._predefined_mpl:
|
|
||||||
print(f'{cat[0]}')
|
|
||||||
print(' '+', '.join(cat[1]))
|
|
||||||
|
|
||||||
|
|
||||||
def shade(self,field,bounds=None,gap=None):
|
def shade(self,field,bounds=None,gap=None):
|
||||||
"""
|
"""
|
||||||
Generate PIL image of 2D field using colormap.
|
Generate PIL image of 2D field using colormap.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
field : numpy.array of shape(:,:)
|
field : numpy.array of shape (:,:)
|
||||||
Data to be shaded.
|
Data to be shaded.
|
||||||
bounds : iterable of len(2), optional
|
bounds : iterable of len (2), optional
|
||||||
Colormap value range (low,high).
|
Colormap value range (low,high).
|
||||||
gap : field.dtype, optional
|
gap : field.dtype, optional
|
||||||
Transparent value. NaN will always be rendered transparent.
|
Transparent value. NaN will always be rendered transparent.
|
||||||
|
@ -234,7 +220,6 @@ class Colormap(mpl.colors.ListedColormap):
|
||||||
return Colormap(np.array(rev.colors),rev.name[:-4] if rev.name.endswith('_r_r') else rev.name)
|
return Colormap(np.array(rev.colors),rev.name[:-4] if rev.name.endswith('_r_r') else rev.name)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def save_paraview(self,fname=None):
|
def save_paraview(self,fname=None):
|
||||||
"""
|
"""
|
||||||
Write colormap to JSON file for Paraview.
|
Write colormap to JSON file for Paraview.
|
||||||
|
@ -246,13 +231,13 @@ class Colormap(mpl.colors.ListedColormap):
|
||||||
consist of the name of the colormap and extension '.json'.
|
consist of the name of the colormap and extension '.json'.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if fname is not None:
|
if fname is None:
|
||||||
|
fhandle = None
|
||||||
|
else:
|
||||||
try:
|
try:
|
||||||
fhandle = open(fname,'w')
|
fhandle = open(fname,'w')
|
||||||
except TypeError:
|
except TypeError:
|
||||||
fhandle = fname
|
fhandle = fname
|
||||||
else:
|
|
||||||
fhandle = None
|
|
||||||
|
|
||||||
colors = []
|
colors = []
|
||||||
for i,c in enumerate(np.round(self.colors,6).tolist()):
|
for i,c in enumerate(np.round(self.colors,6).tolist()):
|
||||||
|
@ -265,11 +250,9 @@ class Colormap(mpl.colors.ListedColormap):
|
||||||
'DefaultMap':True,
|
'DefaultMap':True,
|
||||||
'RGBPoints':colors
|
'RGBPoints':colors
|
||||||
}]
|
}]
|
||||||
if fhandle is None:
|
|
||||||
with open(self.name.replace(' ','_')+'.json', 'w') as f:
|
with open(self.name.replace(' ','_')+'.json', 'w') if fhandle is None else fhandle as f:
|
||||||
json.dump(out, f,indent=4)
|
json.dump(out, f,indent=4)
|
||||||
else:
|
|
||||||
json.dump(out,fhandle,indent=4)
|
|
||||||
|
|
||||||
|
|
||||||
def save_ASCII(self,fname=None):
|
def save_ASCII(self,fname=None):
|
||||||
|
@ -283,22 +266,19 @@ class Colormap(mpl.colors.ListedColormap):
|
||||||
consist of the name of the colormap and extension '.txt'.
|
consist of the name of the colormap and extension '.txt'.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if fname is not None:
|
if fname is None:
|
||||||
|
fhandle = None
|
||||||
|
else:
|
||||||
try:
|
try:
|
||||||
fhandle = open(fname,'w')
|
fhandle = open(fname,'w')
|
||||||
except TypeError:
|
except TypeError:
|
||||||
fhandle = fname
|
fhandle = fname
|
||||||
else:
|
|
||||||
fhandle = None
|
|
||||||
|
|
||||||
labels = {'RGBA':4} if self.colors.shape[1] == 4 else {'RGB': 3}
|
labels = {'RGBA':4} if self.colors.shape[1] == 4 else {'RGB': 3}
|
||||||
t = Table(self.colors,labels,f'Creator: {util.execution_stamp("Colormap")}')
|
t = Table(self.colors,labels,f'Creator: {util.execution_stamp("Colormap")}')
|
||||||
|
|
||||||
if fhandle is None:
|
with open(self.name.replace(' ','_')+'.txt', 'w') if fhandle is None else fhandle as f:
|
||||||
with open(self.name.replace(' ','_')+'.txt', 'w') as f:
|
|
||||||
t.save(f)
|
t.save(f)
|
||||||
else:
|
|
||||||
t.save(fhandle)
|
|
||||||
|
|
||||||
|
|
||||||
def save_GOM(self,fname=None):
|
def save_GOM(self,fname=None):
|
||||||
|
@ -312,24 +292,21 @@ class Colormap(mpl.colors.ListedColormap):
|
||||||
consist of the name of the colormap and extension '.legend'.
|
consist of the name of the colormap and extension '.legend'.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if fname is not None:
|
if fname is None:
|
||||||
|
fhandle = None
|
||||||
|
else:
|
||||||
try:
|
try:
|
||||||
fhandle = open(fname,'w')
|
fhandle = open(fname,'w')
|
||||||
except TypeError:
|
except TypeError:
|
||||||
fhandle = fname
|
fhandle = fname
|
||||||
else:
|
|
||||||
fhandle = None
|
|
||||||
# ToDo: test in GOM
|
# ToDo: test in GOM
|
||||||
GOM_str = '1 1 {name} 9 {name} '.format(name=self.name.replace(" ","_")) \
|
GOM_str = '1 1 {name} 9 {name} '.format(name=self.name.replace(" ","_")) \
|
||||||
+ '0 1 0 3 0 0 -1 9 \\ 0 0 0 255 255 255 0 0 255 ' \
|
+ '0 1 0 3 0 0 -1 9 \\ 0 0 0 255 255 255 0 0 255 ' \
|
||||||
+ f'30 NO_UNIT 1 1 64 64 64 255 1 0 0 0 0 0 0 3 0 {len(self.colors)}' \
|
+ f'30 NO_UNIT 1 1 64 64 64 255 1 0 0 0 0 0 0 3 0 {len(self.colors)}' \
|
||||||
+ ' '.join([f' 0 {c[0]} {c[1]} {c[2]} 255 1' for c in reversed((self.colors*255).astype(int))]) \
|
+ ' '.join([f' 0 {c[0]} {c[1]} {c[2]} 255 1' for c in reversed((self.colors*255).astype(int))]) \
|
||||||
+ '\n'
|
+ '\n'
|
||||||
if fhandle is None:
|
with open(self.name.replace(' ','_')+'.legend', 'w') if fhandle is None else fhandle as f:
|
||||||
with open(self.name.replace(' ','_')+'.legend', 'w') as f:
|
|
||||||
f.write(GOM_str)
|
f.write(GOM_str)
|
||||||
else:
|
|
||||||
fhandle.write(GOM_str)
|
|
||||||
|
|
||||||
|
|
||||||
def save_gmsh(self,fname=None):
|
def save_gmsh(self,fname=None):
|
||||||
|
@ -343,22 +320,19 @@ class Colormap(mpl.colors.ListedColormap):
|
||||||
consist of the name of the colormap and extension '.msh'.
|
consist of the name of the colormap and extension '.msh'.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if fname is not None:
|
if fname is None:
|
||||||
|
fhandle = None
|
||||||
|
else:
|
||||||
try:
|
try:
|
||||||
fhandle = open(fname,'w')
|
fhandle = open(fname,'w')
|
||||||
except TypeError:
|
except TypeError:
|
||||||
fhandle = fname
|
fhandle = fname
|
||||||
else:
|
|
||||||
fhandle = None
|
|
||||||
# ToDo: test in gmsh
|
# ToDo: test in gmsh
|
||||||
gmsh_str = 'View.ColorTable = {\n' \
|
gmsh_str = 'View.ColorTable = {\n' \
|
||||||
+'\n'.join([f'{c[0]},{c[1]},{c[2]},' for c in self.colors[:,:3]*255]) \
|
+'\n'.join([f'{c[0]},{c[1]},{c[2]},' for c in self.colors[:,:3]*255]) \
|
||||||
+'\n}\n'
|
+'\n}\n'
|
||||||
if fhandle is None:
|
with open(self.name.replace(' ','_')+'.msh', 'w') if fhandle is None else fhandle as f:
|
||||||
with open(self.name.replace(' ','_')+'.msh', 'w') as f:
|
|
||||||
f.write(gmsh_str)
|
f.write(gmsh_str)
|
||||||
else:
|
|
||||||
fhandle.write(gmsh_str)
|
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -386,7 +360,6 @@ class Colormap(mpl.colors.ListedColormap):
|
||||||
if msh_sat[2] < - np.pi/3.0: hSpin *= -1.0
|
if msh_sat[2] < - np.pi/3.0: hSpin *= -1.0
|
||||||
return msh_sat[2] + hSpin
|
return msh_sat[2] + hSpin
|
||||||
|
|
||||||
|
|
||||||
lo = np.array(low)
|
lo = np.array(low)
|
||||||
hi = np.array(high)
|
hi = np.array(high)
|
||||||
|
|
||||||
|
@ -406,28 +379,28 @@ class Colormap(mpl.colors.ListedColormap):
|
||||||
return (1.0 - frac) * lo + frac * hi
|
return (1.0 - frac) * lo + frac * hi
|
||||||
|
|
||||||
|
|
||||||
_predefined_mpl= [('Perceptually Uniform Sequential', [
|
_predefined_mpl= {'Perceptually Uniform Sequential': [
|
||||||
'viridis', 'plasma', 'inferno', 'magma', 'cividis']),
|
'viridis', 'plasma', 'inferno', 'magma', 'cividis'],
|
||||||
('Sequential', [
|
'Sequential': [
|
||||||
'Greys', 'Purples', 'Blues', 'Greens', 'Oranges', 'Reds',
|
'Greys', 'Purples', 'Blues', 'Greens', 'Oranges', 'Reds',
|
||||||
'YlOrBr', 'YlOrRd', 'OrRd', 'PuRd', 'RdPu', 'BuPu',
|
'YlOrBr', 'YlOrRd', 'OrRd', 'PuRd', 'RdPu', 'BuPu',
|
||||||
'GnBu', 'PuBu', 'YlGnBu', 'PuBuGn', 'BuGn', 'YlGn']),
|
'GnBu', 'PuBu', 'YlGnBu', 'PuBuGn', 'BuGn', 'YlGn'],
|
||||||
('Sequential (2)', [
|
'Sequential (2)': [
|
||||||
'binary', 'gist_yarg', 'gist_gray', 'gray', 'bone', 'pink',
|
'binary', 'gist_yarg', 'gist_gray', 'gray', 'bone', 'pink',
|
||||||
'spring', 'summer', 'autumn', 'winter', 'cool', 'Wistia',
|
'spring', 'summer', 'autumn', 'winter', 'cool', 'Wistia',
|
||||||
'hot', 'afmhot', 'gist_heat', 'copper']),
|
'hot', 'afmhot', 'gist_heat', 'copper'],
|
||||||
('Diverging', [
|
'Diverging': [
|
||||||
'PiYG', 'PRGn', 'BrBG', 'PuOr', 'RdGy', 'RdBu',
|
'PiYG', 'PRGn', 'BrBG', 'PuOr', 'RdGy', 'RdBu',
|
||||||
'RdYlBu', 'RdYlGn', 'Spectral', 'coolwarm', 'bwr', 'seismic']),
|
'RdYlBu', 'RdYlGn', 'Spectral', 'coolwarm', 'bwr', 'seismic'],
|
||||||
('Cyclic', ['twilight', 'twilight_shifted', 'hsv']),
|
'Cyclic': ['twilight', 'twilight_shifted', 'hsv'],
|
||||||
('Qualitative', [
|
'Qualitative': [
|
||||||
'Pastel1', 'Pastel2', 'Paired', 'Accent',
|
'Pastel1', 'Pastel2', 'Paired', 'Accent',
|
||||||
'Dark2', 'Set1', 'Set2', 'Set3',
|
'Dark2', 'Set1', 'Set2', 'Set3',
|
||||||
'tab10', 'tab20', 'tab20b', 'tab20c']),
|
'tab10', 'tab20', 'tab20b', 'tab20c'],
|
||||||
('Miscellaneous', [
|
'Miscellaneous': [
|
||||||
'flag', 'prism', 'ocean', 'gist_earth', 'terrain', 'gist_stern',
|
'flag', 'prism', 'ocean', 'gist_earth', 'terrain', 'gist_stern',
|
||||||
'gnuplot', 'gnuplot2', 'CMRmap', 'cubehelix', 'brg',
|
'gnuplot', 'gnuplot2', 'CMRmap', 'cubehelix', 'brg',
|
||||||
'gist_rainbow', 'rainbow', 'jet', 'nipy_spectral', 'gist_ncar'])]
|
'gist_rainbow', 'rainbow', 'jet', 'nipy_spectral', 'gist_ncar']}
|
||||||
|
|
||||||
_predefined_DAMASK = {'orientation': {'low': [0.933334,0.878432,0.878431],
|
_predefined_DAMASK = {'orientation': {'low': [0.933334,0.878432,0.878431],
|
||||||
'high': [0.250980,0.007843,0.000000]},
|
'high': [0.250980,0.007843,0.000000]},
|
||||||
|
@ -436,6 +409,9 @@ class Colormap(mpl.colors.ListedColormap):
|
||||||
'stress': {'low': [0.878432,0.874511,0.949019],
|
'stress': {'low': [0.878432,0.874511,0.949019],
|
||||||
'high': [0.000002,0.000000,0.286275]}}
|
'high': [0.000002,0.000000,0.286275]}}
|
||||||
|
|
||||||
|
predefined = dict(**{'DAMASK':list(_predefined_DAMASK)},**_predefined_mpl)
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _hsv2rgb(hsv):
|
def _hsv2rgb(hsv):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -141,8 +141,8 @@ class TestColormap:
|
||||||
diff = ImageChops.difference(img_reference.convert('RGB'),img_current.convert('RGB'))
|
diff = ImageChops.difference(img_reference.convert('RGB'),img_current.convert('RGB'))
|
||||||
assert not diff.getbbox()
|
assert not diff.getbbox()
|
||||||
|
|
||||||
def test_list(self):
|
def test_predefined(self):
|
||||||
Colormap.list_predefined()
|
assert (isinstance(Colormap.predefined,dict))
|
||||||
|
|
||||||
@pytest.mark.parametrize('format,ext',[('ASCII','.txt'),
|
@pytest.mark.parametrize('format,ext',[('ASCII','.txt'),
|
||||||
('paraview','.json'),
|
('paraview','.json'),
|
||||||
|
|
Loading…
Reference in New Issue