Merge branch 'modernize_colormap' into 'development'

Modernize colormap

See merge request damask/DAMASK!183
This commit is contained in:
Philip Eisenlohr 2020-07-02 19:13:59 +02:00
commit 1a8feab255
14 changed files with 2607 additions and 633 deletions

View File

@ -1,75 +0,0 @@
#!/usr/bin/env python3
import os
import sys
from optparse import OptionParser
import damask
scriptName = os.path.splitext(os.path.basename(__file__))[0]
scriptID = ' '.join([scriptName,damask.version])
# --------------------------------------------------------------------
# MAIN
# --------------------------------------------------------------------
#Borland, D., & Taylor, R. M. (2007). Rainbow Color Map (Still) Considered Harmful. Computer Graphics and Applications, IEEE, 27(2), 14--17.
#Moreland, K. (2009). Diverging Color Maps for Scientific Visualization. In Proc. 5th Int. Symp. Visual Computing (pp. 92--103).
outtypes = ['paraview','gmsh','raw','GOM']
extensions = ['.json','.msh','.txt','.legend']
colormodels = ['RGB','HSL','XYZ','CIELAB','MSH']
parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [file[s]]', description = """
Produces perceptually linear diverging and sequential colormaps in formats suitable for visualization software
or simply as a list of interpolated colors.
""", version = scriptID)
parser.add_option('-N','--steps', dest='N', type='int', nargs=1, metavar='int',
help='number of interpolation steps [%default]')
parser.add_option('-t','--trim', dest='trim', type='float', nargs=2, metavar='float float',
help='relative trim of colormap range [%default]')
parser.add_option('-l','--left', dest='left', type='float', nargs=3, metavar='float float float',
help='left color [%default]')
parser.add_option('-r','--right', dest='right', type='float', nargs=3, metavar='float float float',
help='right color [%default]')
parser.add_option('-c','--colormodel', dest='colormodel', metavar='string',
help='colormodel: '+', '.join(colormodels)+' [%default]')
parser.add_option('-p','--predefined', dest='predefined', metavar='string',
help='predefined colormap')
parser.add_option('-f','--format', dest='format', metavar='string',
help='output format: '+', '.join(outtypes)+' [%default]')
parser.set_defaults(colormodel = 'RGB')
parser.set_defaults(predefined = None)
parser.set_defaults(basename = None)
parser.set_defaults(format = 'paraview')
parser.set_defaults(N = 10)
parser.set_defaults(trim = (-1.0,1.0))
parser.set_defaults(left = (1.0,1.0,1.0))
parser.set_defaults(right = (0.0,0.0,0.0))
(options,filename) = parser.parse_args()
if options.format not in outtypes:
parser.error('invalid format: "{}" (choices: {}).'.format(options.format,', '.join(outtypes)))
if options.N < 2:
parser.error('too few steps (need at least 2).')
if options.trim[0] < -1.0 or \
options.trim[1] > 1.0 or \
options.trim[0] >= options.trim[1]:
parser.error('invalid trim range (-1 +1).')
name = options.format if filename == [] \
else filename[0]
output = sys.stdout if filename == [] \
else open(os.path.basename(filename[0])+extensions[outtypes.index(options.format)],'w')
colorLeft = damask.Color(options.colormodel.upper(), list(options.left))
colorRight = damask.Color(options.colormodel.upper(), list(options.right))
colormap = damask.Colormap(colorLeft, colorRight, predefined=options.predefined)
output.write(colormap.export(name,options.format,options.N,list(options.trim)))
output.close()

View File

@ -10,7 +10,7 @@ with open(_Path(__file__).parent/_Path('VERSION')) as _f:
from ._environment import Environment # noqa
from ._table import Table # noqa
from ._vtk import VTK # noqa
from ._colormaps import Colormap, Color # noqa
from ._colormap import Colormap # noqa
from ._rotation import Rotation # noqa
from ._lattice import Symmetry, Lattice# noqa
from ._orientation import Orientation # noqa

612
python/damask/_colormap.py Normal file
View File

@ -0,0 +1,612 @@
import json
import functools
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib import cm
import damask
from . import Table
_eps = 216./24389.
_kappa = 24389./27.
_ref_white = np.array([.95047, 1.00000, 1.08883]) # Observer = 2, Illuminant = D65
# ToDo (if needed)
# - support alpha channel (paraview/ASCII/input)
# - support NaN color (paraview)
class Colormap(mpl.colors.ListedColormap):
def __add__(self,other):
"""Concatenate colormaps."""
return Colormap(np.vstack((self.colors,other.colors)),
f'{self.name}+{other.name}')
def __iadd__(self,other):
"""Concatenate colormaps."""
return self.__add__(other)
def __invert__(self):
"""Return inverted colormap."""
return self.reversed()
@staticmethod
def from_range(low,high,name='DAMASK colormap',N=256,model='rgb'):
"""
Create a perceptually uniform colormap between given (inclusive) bounds.
Colors are internally stored as R(ed) G(green) B(lue) values.
The colormap can be used in matplotlib/seaborn or exported to
file for external use.
Parameters
----------
low : numpy.ndarray of shape (3)
Color definition for minimum value.
high : numpy.ndarray of shape (3)
Color definition for maximum value.
N : integer, optional
The number of color quantization levels. Defaults to 256.
name : str, optional
The name of the colormap. Defaults to `DAMASK colormap`.
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).
- 'xyz': CIE Xyz.
- 'lab': CIE Lab.
- 'msh': Msh (for perceptual uniform interpolation).
"""
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.')
low_,high_ = map(Colormap._rgb2msh,low_high)
elif model.lower() == 'hsv':
if np.any(low_high<0) or np.any(low_high[:,1:3]>1) or np.any(low_high[:,0]>360):
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[:,1:3]>1) or np.any(low_high[:,0]>360):
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:
raise ValueError(f'Invalid color model: {model}.')
msh = map(functools.partial(Colormap._interpolate_msh,low=low_,high=high_),np.linspace(0,1,N))
rgb = np.array(list(map(Colormap._msh2rgb,msh)))
return Colormap(rgb,name=name)
@staticmethod
def from_predefined(name,N=256):
"""
Select from a set of predefined colormaps.
Predefined colormaps include native matplotlib colormaps
and common DAMASK colormaps.
Parameters
----------
name : str
The name of the colormap.
N : int, optional
The number of color quantization levels. Defaults to 256.
This parameter is not used for matplotlib colormaps
that are of type `ListedColormap`.
"""
# matplotlib presets
for cat in Colormap._predefined_mpl:
for n in cat[1]:
if n == name:
colormap = cm.__dict__[name]
if isinstance(colormap,mpl.colors.LinearSegmentedColormap):
return Colormap(np.array(list(map(colormap,np.linspace(0,1,N)))),name=name)
else:
return Colormap(np.array(colormap.colors),name=name)
# DAMASK presets
definition = Colormap._predefined_DAMASK[name]
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 show(self,aspect=10,vertical=False):
"""Show colormap as matplotlib figure."""
fig = plt.figure(figsize=(5/aspect,5) if vertical else (5,5/aspect))
ax1 = fig.add_axes([0, 0, 1, 1])
ax1.set_axis_off()
ax1.imshow(np.linspace(1 if vertical else 0,
0 if vertical else 1,
self.N).reshape((-1,1) if vertical else (1,-1)),
aspect='auto', cmap=self, interpolation='nearest')
plt.show()
def reversed(self,name=None):
"""
Make a reversed instance of the colormap.
Parameters
----------
name : str, optional
The 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.
"""
rev = super(Colormap,self).reversed(name)
return Colormap(np.array(rev.colors),rev.name[:-4] if rev.name.endswith('_r_r') else rev.name)
def to_file(self,fname=None,format='ParaView'):
"""
Export colormap to file for use in external programs.
Parameters
----------
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 an extension that
depends on the file format.
format : {'ParaView', 'ASCII', 'GOM', 'gmsh'}, optional
File format, defaults to 'ParaView'. Available formats are:
- ParaView: JSON file, extension '.json'.
- ASCII: Plain text file, extension '.txt'.
- GOM: Aramis GOM (DIC), extension '.legend'.
- Gmsh: Gmsh FEM mesh-generator, extension '.msh'.
"""
if fname is not None:
try:
f = open(fname,'w')
except TypeError:
f = fname
else:
f = None
if format.lower() == 'paraview':
Colormap._export_paraview(self,f)
elif format.lower() == 'ascii':
Colormap._export_ASCII(self,f)
elif format.lower() == 'gom':
Colormap._export_GOM(self,f)
elif format.lower() == 'gmsh':
Colormap._export_gmsh(self,f)
else:
raise ValueError('Unknown output format: {format}.')
@staticmethod
def _export_paraview(colormap,fhandle=None):
"""Write colormap to JSON file for Paraview."""
colors = []
for i,c in enumerate(np.round(colormap.colors,6).tolist()):
colors+=[i]+c
out = [{
'Creator':f'damask.Colormap v{damask.version}',
'ColorSpace':'RGB',
'Name':colormap.name,
'DefaultMap':True,
'RGBPoints':colors
}]
if fhandle is None:
with open(colormap.name.replace(' ','_')+'.json', 'w') as f:
json.dump(out, f,indent=4)
else:
json.dump(out,fhandle,indent=4)
@staticmethod
def _export_ASCII(colormap,fhandle=None):
"""Write colormap to ASCII table."""
labels = {'RGBA':4} if colormap.colors.shape[1] == 4 else {'RGB': 3}
t = Table(colormap.colors,labels,f'Creator: damask.Colormap v{damask.version}')
if fhandle is None:
with open(colormap.name.replace(' ','_')+'.txt', 'w') as f:
t.to_ASCII(f,True)
else:
t.to_ASCII(fhandle,True)
@staticmethod
def _export_GOM(colormap,fhandle=None):
"""Write colormap to GOM Aramis compatible format."""
# ToDo: test in GOM
GOM_str = f'1 1 {colormap.name.replace(" ","_")} 9 {colormap.name.replace(" ","_")} ' \
+ '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(colormap.colors)}' \
+ ' '.join([f' 0 {c[0]} {c[1]} {c[2]} 255 1' for c in reversed((colormap.colors*255).astype(int))]) \
+ '\n'
if fhandle is None:
with open(colormap.name.replace(' ','_')+'.legend', 'w') as f:
f.write(GOM_str)
else:
fhandle.write(GOM_str)
@staticmethod
def _export_gmsh(colormap,fhandle=None):
"""Write colormap to Gmsh compatible format."""
# ToDo: test in gmsh
gmsh_str = 'View.ColorTable = {\n' \
+'\n'.join([f'{c[0]},{c[1]},{c[2]},' for c in colormap.colors[:,:3]*255]) \
+'\n}\n'
if fhandle is None:
with open(colormap.name.replace(' ','_')+'.msh', 'w') as f:
f.write(gmsh_str)
else:
fhandle.write(gmsh_str)
@staticmethod
def _interpolate_msh(frac,low,high):
"""
Interpolate in Msh color space.
This interpolation gives a perceptually uniform colormap.
References
----------
https://www.kennethmoreland.com/color-maps/ColorMapsExpanded.pdf
https://www.kennethmoreland.com/color-maps/diverging_map.py
"""
def rad_diff(a,b):
return abs(a[2]-b[2])
def adjust_hue(msh_sat, msh_unsat):
"""If saturation of one of the two colors is much less than the other, hue of the less."""
if msh_sat[0] >= msh_unsat[0]:
return msh_sat[2]
else:
hSpin = msh_sat[1]/np.sin(msh_sat[1])*np.sqrt(msh_unsat[0]**2.0-msh_sat[0]**2)/msh_sat[0]
if msh_sat[2] < - np.pi/3.0: hSpin *= -1.0
return msh_sat[2] + hSpin
lo = np.array(low)
hi = np.array(high)
if (lo[1] > 0.05 and hi[1] > 0.05 and rad_diff(lo,hi) > np.pi/3.0):
M_mid = max(lo[0],hi[0],88.0)
if frac < 0.5:
hi = np.array([M_mid,0.0,0.0])
frac *= 2.0
else:
lo = np.array([M_mid,0.0,0.0])
frac = 2.0*frac - 1.0
if lo[1] < 0.05 and hi[1] > 0.05:
lo[2] = adjust_hue(hi,lo)
elif lo[1] > 0.05 and hi[1] < 0.05:
hi[2] = adjust_hue(lo,hi)
return (1.0 - frac) * lo + frac * hi
_predefined_mpl= [('Perceptually Uniform Sequential', [
'viridis', 'plasma', 'inferno', 'magma', 'cividis']),
('Sequential', [
'Greys', 'Purples', 'Blues', 'Greens', 'Oranges', 'Reds',
'YlOrBr', 'YlOrRd', 'OrRd', 'PuRd', 'RdPu', 'BuPu',
'GnBu', 'PuBu', 'YlGnBu', 'PuBuGn', 'BuGn', 'YlGn']),
('Sequential (2)', [
'binary', 'gist_yarg', 'gist_gray', 'gray', 'bone', 'pink',
'spring', 'summer', 'autumn', 'winter', 'cool', 'Wistia',
'hot', 'afmhot', 'gist_heat', 'copper']),
('Diverging', [
'PiYG', 'PRGn', 'BrBG', 'PuOr', 'RdGy', 'RdBu',
'RdYlBu', 'RdYlGn', 'Spectral', 'coolwarm', 'bwr', 'seismic']),
('Cyclic', ['twilight', 'twilight_shifted', 'hsv']),
('Qualitative', [
'Pastel1', 'Pastel2', 'Paired', 'Accent',
'Dark2', 'Set1', 'Set2', 'Set3',
'tab10', 'tab20', 'tab20b', 'tab20c']),
('Miscellaneous', [
'flag', 'prism', 'ocean', 'gist_earth', 'terrain', 'gist_stern',
'gnuplot', 'gnuplot2', 'CMRmap', 'cubehelix', 'brg',
'gist_rainbow', 'rainbow', 'jet', 'nipy_spectral', 'gist_ncar'])]
_predefined_DAMASK = {'orientation': {'low': [0.933334,0.878432,0.878431],
'high': [0.250980,0.007843,0.000000]},
'strain': {'low': [0.941177,0.941177,0.870588],
'high': [0.266667,0.266667,0.000000]},
'stress': {'low': [0.878432,0.874511,0.949019],
'high': [0.000002,0.000000,0.286275]}}
@staticmethod
def _hsv2rgb(hsv):
"""
H(ue) S(aturation) V(alue) to R(red) G(reen) B(lue).
References
----------
https://www.rapidtables.com/convert/color/hsv-to-rgb.html
"""
sextant = np.clip(int(hsv[0]/60.),0,5)
c = hsv[1]*hsv[2]
x = c*(1.0 - abs((hsv[0]/60.)%2 - 1.))
return np.array([
[c, x, 0],
[x, c, 0],
[0, c, x],
[0, x, c],
[x, 0, c],
[c, 0, x],
])[sextant] + hsv[2] - c
@staticmethod
def _rgb2hsv(rgb):
"""
R(ed) G(reen) B(lue) to H(ue) S(aturation) V(alue).
References
----------
https://www.rapidtables.com/convert/color/rgb-to-hsv.html
"""
C_max = rgb.max()
C_min = rgb.min()
Delta = C_max - C_min
v = C_max
s = 0. if np.isclose(C_max,0.) else Delta/C_max
if np.isclose(Delta,0.):
h = 0.
elif rgb.argmax() == 0:
h = (rgb[1]-rgb[2])/Delta%6
elif rgb.argmax() == 1:
h = (rgb[2]-rgb[0])/Delta + 2.
elif rgb.argmax() == 2:
h = (rgb[0]-rgb[1])/Delta + 4.
h = np.clip(h,0.,6.) * 60.
return np.array([h,s,v])
@staticmethod
def _hsl2rgb(hsl):
"""
H(ue) S(aturation) L(uminance) to R(red) G(reen) B(lue).
References
----------
https://www.rapidtables.com/convert/color/hsl-to-rgb.html
"""
sextant = np.clip(int(hsl[0]/60.),0,5)
c = (1.0 - abs(2.0 * hsl[2] - 1.))*hsl[1]
x = c*(1.0 - abs((hsl[0]/60.)%2 - 1.))
m = hsl[2] - 0.5*c
return np.array([
[c+m, x+m, m],
[x+m, c+m, m],
[m, c+m, x+m],
[m, x+m, c+m],
[x+m, m, c+m],
[c+m, m, x+m],
])[sextant]
@staticmethod
def _rgb2hsl(rgb):
"""
R(ed) G(reen) B(lue) to H(ue) S(aturation) L(uminance).
References
----------
https://www.rapidtables.com/convert/color/rgb-to-hsl.html
"""
C_max = rgb.max()
C_min = rgb.min()
Delta = C_max - C_min
l = np.clip((C_max + C_min)*.5,0.,1.) # noqa
s = 0. if np.isclose(C_max,C_min) else Delta/(1.-np.abs(2*l-1.))
if np.isclose(Delta,0.):
h = 0.
elif rgb.argmax() == 0:
h = (rgb[1]-rgb[2])/Delta%6
elif rgb.argmax() == 1:
h = (rgb[2]-rgb[0])/Delta + 2.
elif rgb.argmax() == 2:
h = (rgb[0]-rgb[1])/Delta + 4.
h = np.clip(h,0.,6.) * 60.
return np.array([h,s,l])
@staticmethod
def _xyz2rgb(xyz):
"""
CIE Xyz to R(ed) G(reen) B(lue).
References
----------
http://www.ryanjuckett.com/programming/rgb-color-space-conversion
"""
rgb_lin = np.dot(np.array([
[ 3.240969942,-1.537383178,-0.498610760],
[-0.969243636, 1.875967502, 0.041555057],
[ 0.055630080,-0.203976959, 1.056971514]
]),xyz)
with np.errstate(invalid='ignore'):
rgb = np.where(rgb_lin>0.0031308,rgb_lin**(1.0/2.4)*1.0555-0.0555,rgb_lin*12.92)
return np.clip(rgb,0.,1.)
@staticmethod
def _rgb2xyz(rgb):
"""
R(ed) G(reen) B(lue) to CIE Xyz.
References
----------
http://www.ryanjuckett.com/programming/rgb-color-space-conversion
"""
rgb_lin = np.where(rgb>0.04045,((rgb+0.0555)/1.0555)**2.4,rgb/12.92)
return np.dot(np.array([
[0.412390799,0.357584339,0.180480788],
[0.212639006,0.715168679,0.072192315],
[0.019330819,0.119194780,0.950532152]
]),rgb_lin)
@staticmethod
def _lab2xyz(lab,ref_white=None):
"""
CIE Lab to CIE Xyz.
References
----------
http://www.brucelindbloom.com/index.html?Eqn_Lab_to_XYZ.html
"""
f_x = (lab[0]+16.)/116. + lab[1]/500.
f_z = (lab[0]+16.)/116. - lab[2]/200.
return np.array([
f_x**3. if f_x**3. > _eps else (116.*f_x-16.)/_kappa,
((lab[0]+16.)/116.)**3 if lab[0]>_kappa*_eps else lab[0]/_kappa,
f_z**3. if f_z**3. > _eps else (116.*f_z-16.)/_kappa
])*(ref_white if ref_white is not None else _ref_white)
@staticmethod
def _xyz2lab(xyz,ref_white=None):
"""
CIE Xyz to CIE Lab.
References
----------
http://www.brucelindbloom.com/index.html?Eqn_Lab_to_XYZ.html
"""
ref_white = ref_white if ref_white is not None else _ref_white
f = np.where(xyz/ref_white > _eps,(xyz/ref_white)**(1./3.),(_kappa*xyz/ref_white+16.)/116.)
return np.array([
116.0 * f[1] - 16.0,
500.0 * (f[0] - f[1]),
200.0 * (f[1] - f[2])
])
@staticmethod
def _lab2msh(lab):
"""
CIE Lab to Msh.
References
----------
https://www.kennethmoreland.com/color-maps/ColorMapsExpanded.pdf
https://www.kennethmoreland.com/color-maps/diverging_map.py
"""
M = np.linalg.norm(lab)
return np.array([
M,
np.arccos(lab[0]/M) if M>1e-8 else 0.,
np.arctan2(lab[2],lab[1]) if M>1e-8 else 0.,
])
@staticmethod
def _msh2lab(msh):
"""
Msh to CIE Lab.
References
----------
https://www.kennethmoreland.com/color-maps/ColorMapsExpanded.pdf
https://www.kennethmoreland.com/color-maps/diverging_map.py
"""
return np.array([
msh[0] * np.cos(msh[1]),
msh[0] * np.sin(msh[1]) * np.cos(msh[2]),
msh[0] * np.sin(msh[1]) * np.sin(msh[2])
])
@staticmethod
def _lab2rgb(lab):
return Colormap._xyz2rgb(Colormap._lab2xyz(lab))
@staticmethod
def _rgb2lab(rgb):
return Colormap._xyz2lab(Colormap._rgb2xyz(rgb))
@staticmethod
def _msh2rgb(msh):
return Colormap._lab2rgb(Colormap._msh2lab(msh))
@staticmethod
def _rgb2msh(rgb):
return Colormap._lab2msh(Colormap._rgb2lab(rgb))
@staticmethod
def _hsv2msh(hsv):
return Colormap._rgb2msh(Colormap._hsv2rgb(hsv))
@staticmethod
def _hsl2msh(hsl):
return Colormap._rgb2msh(Colormap._hsl2rgb(hsl))
@staticmethod
def _xyz2msh(xyz):
return Colormap._lab2msh(Colormap._xyz2lab(xyz))

View File

@ -1,541 +0,0 @@
import numpy as np
from . import util
class Color:
"""Color representation in and conversion between different color-spaces."""
__slots__ = [
'model',
'color',
'__dict__',
]
def __init__(self,
model = 'RGB',
color = np.zeros(3)):
"""
Create a Color object.
Parameters
----------
model : string
color model
color : numpy.ndarray
vector representing the color according to the selected model
"""
self.__transforms__ = \
{'HSV': {'index': 0, 'next': self._HSV2HSL},
'HSL': {'index': 1, 'next': self._HSL2RGB, 'prev': self._HSL2HSV},
'RGB': {'index': 2, 'next': self._RGB2XYZ, 'prev': self._RGB2HSL},
'XYZ': {'index': 3, 'next': self._XYZ2CIELAB, 'prev': self._XYZ2RGB},
'CIELAB': {'index': 4, 'next': self._CIELAB2MSH, 'prev': self._CIELAB2XYZ},
'MSH': {'index': 5, 'prev': self._MSH2CIELAB},
}
model = model.upper()
if model not in list(self.__transforms__.keys()): model = 'RGB'
if model == 'RGB' and max(color) > 1.0: # are we RGB255 ?
for i in range(3):
color[i] /= 255.0 # rescale to RGB
if model == 'HSL': # are we HSL ?
if abs(color[0]) > 1.0: color[0] /= 360.0 # with angular hue?
while color[0] >= 1.0: color[0] -= 1.0 # rewind to proper range
while color[0] < 0.0: color[0] += 1.0 # rewind to proper range
self.model = model
self.color = np.array(color,'d')
def __repr__(self):
"""Color model and values."""
return 'Model: %s Color: %s'%(self.model,str(self.color))
def __str__(self):
"""Color model and values."""
return self.__repr__()
def convert_to(self,toModel = 'RGB'):
"""
Change the color model permanently.
Parameters
----------
toModel : string
color model
"""
toModel = toModel.upper()
if toModel not in list(self.__transforms__.keys()): return
sourcePos = self.__transforms__[self.model]['index']
targetPos = self.__transforms__[toModel]['index']
while sourcePos < targetPos:
self.__transforms__[self.model]['next']()
sourcePos += 1
while sourcePos > targetPos:
self.__transforms__[self.model]['prev']()
sourcePos -= 1
return self
def express_as(self,asModel = 'RGB'):
"""
Return the color in a different model.
Parameters
----------
asModel : string
color model
"""
return self.__class__(self.model,self.color).convert_to(asModel)
def _HSV2HSL(self):
"""
Convert H(ue) S(aturation) V(alue or brightness) to H(ue) S(aturation) L(uminance).
All values are in the range [0,1]
http://codeitdown.com/hsl-hsb-hsv-color
"""
if self.model != 'HSV': return
converted = Color('HSL',np.array([
self.color[0],
1. if self.color[2] == 0.0 or (self.color[1] == 0.0 and self.color[2] == 1.0) \
else self.color[1]*self.color[2]/(1.-abs(self.color[2]*(2.-self.color[1])-1.)),
0.5*self.color[2]*(2.-self.color[1]),
]))
self.model = converted.model
self.color = converted.color
def _HSL2HSV(self):
"""
Convert H(ue) S(aturation) L(uminance) to H(ue) S(aturation) V(alue or brightness).
All values are in the range [0,1]
http://codeitdown.com/hsl-hsb-hsv-color
"""
if self.model != 'HSL': return
h = self.color[0]
b = self.color[2]+0.5*(self.color[1]*(1.-abs(2*self.color[2]-1)))
s = 1.0 if b == 0.0 else 2.*(b-self.color[2])/b
converted = Color('HSV',np.array([h,s,b]))
self.model = converted.model
self.color = converted.color
def _HSL2RGB(self):
"""
Convert H(ue) S(aturation) L(uminance) to R(red) G(reen) B(lue).
All values are in the range [0,1]
from http://en.wikipedia.org/wiki/HSL_and_HSV
"""
if self.model != 'HSL': return
sextant = self.color[0]*6.0
c = (1.0 - abs(2.0 * self.color[2] - 1.0))*self.color[1]
x = c*(1.0 - abs(sextant%2 - 1.0))
m = self.color[2] - 0.5*c
converted = Color('RGB',np.array([
[c+m, x+m, m],
[x+m, c+m, m],
[m, c+m, x+m],
[m, x+m, c+m],
[x+m, m, c+m],
[c+m, m, x+m],
][int(sextant)]))
self.model = converted.model
self.color = converted.color
def _RGB2HSL(self):
"""
Convert R(ed) G(reen) B(lue) to H(ue) S(aturation) L(uminance).
All values are in the range [0,1]
from http://130.113.54.154/~monger/hsl-rgb.html
"""
if self.model != 'RGB': return
HSL = np.zeros(3)
maxcolor = self.color.max()
mincolor = self.color.min()
HSL[2] = (maxcolor + mincolor)/2.0
if(mincolor == maxcolor):
HSL[0] = 0.0
HSL[1] = 0.0
else:
if (HSL[2]<0.5):
HSL[1] = (maxcolor - mincolor)/(maxcolor + mincolor)
else:
HSL[1] = (maxcolor - mincolor)/(2.0 - maxcolor - mincolor)
if (maxcolor == self.color[0]):
HSL[0] = 0.0 + (self.color[1] - self.color[2])/(maxcolor - mincolor)
elif (maxcolor == self.color[1]):
HSL[0] = 2.0 + (self.color[2] - self.color[0])/(maxcolor - mincolor)
elif (maxcolor == self.color[2]):
HSL[0] = 4.0 + (self.color[0] - self.color[1])/(maxcolor - mincolor)
HSL[0] = HSL[0]*60.0 # scaling to 360 might be dangerous for small values
if (HSL[0] < 0.0):
HSL[0] = HSL[0] + 360.0
HSL[1:] = np.clip(HSL[1:],0.0,1.0)
converted = Color('HSL', HSL)
self.model = converted.model
self.color = converted.color
def _RGB2XYZ(self):
"""
Convert R(ed) G(reen) B(lue) to CIE XYZ.
All values are in the range [0,1]
from http://www.cs.rit.edu/~ncs/color/t_convert.html
"""
if self.model != 'RGB': return
XYZ = np.zeros(3)
RGB_lin = np.zeros(3)
convert = np.array([[0.412453,0.357580,0.180423],
[0.212671,0.715160,0.072169],
[0.019334,0.119193,0.950227]])
for i in range(3):
if (self.color[i] > 0.04045): RGB_lin[i] = ((self.color[i]+0.0555)/1.0555)**2.4
else: RGB_lin[i] = self.color[i] /12.92
XYZ = np.dot(convert,RGB_lin)
XYZ = np.clip(XYZ,0.0,None)
converted = Color('XYZ', XYZ)
self.model = converted.model
self.color = converted.color
def _XYZ2RGB(self):
"""
Convert CIE XYZ to R(ed) G(reen) B(lue).
All values are in the range [0,1]
from http://www.cs.rit.edu/~ncs/color/t_convert.html
"""
if self.model != 'XYZ': return
convert = np.array([[ 3.240479,-1.537150,-0.498535],
[-0.969256, 1.875992, 0.041556],
[ 0.055648,-0.204043, 1.057311]])
RGB_lin = np.dot(convert,self.color)
RGB = np.zeros(3)
for i in range(3):
if (RGB_lin[i] > 0.0031308): RGB[i] = ((RGB_lin[i])**(1.0/2.4))*1.0555-0.0555
else: RGB[i] = RGB_lin[i] *12.92
RGB = np.clip(RGB,0.0,1.0)
maxVal = max(RGB) # clipping colors according to the display gamut
if (maxVal > 1.0): RGB /= maxVal
converted = Color('RGB', RGB)
self.model = converted.model
self.color = converted.color
def _CIELAB2XYZ(self):
"""
Convert CIE Lab to CIE XYZ.
All values are in the range [0,1]
from http://www.easyrgb.com/index.php?X=MATH&H=07#text7
"""
if self.model != 'CIELAB': return
ref_white = np.array([.95047, 1.00000, 1.08883]) # Observer = 2, Illuminant = D65
XYZ = np.zeros(3)
XYZ[1] = (self.color[0] + 16.0 ) / 116.0
XYZ[0] = XYZ[1] + self.color[1]/ 500.0
XYZ[2] = XYZ[1] - self.color[2]/ 200.0
for i in range(len(XYZ)):
if (XYZ[i] > 6./29. ): XYZ[i] = XYZ[i]**3.
else: XYZ[i] = 108./841. * (XYZ[i] - 4./29.)
converted = Color('XYZ', XYZ*ref_white)
self.model = converted.model
self.color = converted.color
def _XYZ2CIELAB(self):
"""
Convert CIE XYZ to CIE Lab.
All values are in the range [0,1]
from http://en.wikipedia.org/wiki/Lab_color_space,
http://www.cs.rit.edu/~ncs/color/t_convert.html
"""
if self.model != 'XYZ': return
ref_white = np.array([.95047, 1.00000, 1.08883]) # Observer = 2, Illuminant = D65
XYZ = self.color/ref_white
for i in range(len(XYZ)):
if (XYZ[i] > 216./24389 ): XYZ[i] = XYZ[i]**(1.0/3.0)
else: XYZ[i] = (841./108. * XYZ[i]) + 16.0/116.0
converted = Color('CIELAB', np.array([ 116.0 * XYZ[1] - 16.0,
500.0 * (XYZ[0] - XYZ[1]),
200.0 * (XYZ[1] - XYZ[2]) ]))
self.model = converted.model
self.color = converted.color
def _CIELAB2MSH(self):
"""
Convert CIE Lab to Msh colorspace.
from http://www.cs.unm.edu/~kmorel/documents/ColorMaps/DivergingColorMapWorkshop.xls
"""
if self.model != 'CIELAB': return
Msh = np.zeros(3)
Msh[0] = np.sqrt(np.dot(self.color,self.color))
if (Msh[0] > 0.001):
Msh[1] = np.arccos(self.color[0]/Msh[0])
if (self.color[1] != 0.0):
Msh[2] = np.arctan2(self.color[2],self.color[1])
converted = Color('MSH', Msh)
self.model = converted.model
self.color = converted.color
def _MSH2CIELAB(self):
"""
Convert Msh colorspace to CIE Lab.
with s,h in radians
from http://www.cs.unm.edu/~kmorel/documents/ColorMaps/DivergingColorMapWorkshop.xls
"""
if self.model != 'MSH': return
Lab = np.zeros(3)
Lab[0] = self.color[0] * np.cos(self.color[1])
Lab[1] = self.color[0] * np.sin(self.color[1]) * np.cos(self.color[2])
Lab[2] = self.color[0] * np.sin(self.color[1]) * np.sin(self.color[2])
converted = Color('CIELAB', Lab)
self.model = converted.model
self.color = converted.color
class Colormap:
"""Perceptually uniform diverging or sequential colormap."""
__slots__ = [
'left',
'right',
'interpolate',
]
__predefined__ = {
'gray': {'left': Color('HSL',[0,1,1]),
'right': Color('HSL',[0,0,0.15]),
'interpolate': 'perceptualuniform'},
'grey': {'left': Color('HSL',[0,1,1]),
'right': Color('HSL',[0,0,0.15]),
'interpolate': 'perceptualuniform'},
'red': {'left': Color('HSL',[0,1,0.14]),
'right': Color('HSL',[0,0.35,0.91]),
'interpolate': 'perceptualuniform'},
'green': {'left': Color('HSL',[0.33333,1,0.14]),
'right': Color('HSL',[0.33333,0.35,0.91]),
'interpolate': 'perceptualuniform'},
'blue': {'left': Color('HSL',[0.66,1,0.14]),
'right': Color('HSL',[0.66,0.35,0.91]),
'interpolate': 'perceptualuniform'},
'seaweed': {'left': Color('HSL',[0.78,1.0,0.1]),
'right': Color('HSL',[0.40000,0.1,0.9]),
'interpolate': 'perceptualuniform'},
'bluebrown': {'left': Color('HSL',[0.65,0.53,0.49]),
'right': Color('HSL',[0.11,0.75,0.38]),
'interpolate': 'perceptualuniform'},
'redgreen': {'left': Color('HSL',[0.97,0.96,0.36]),
'right': Color('HSL',[0.33333,1.0,0.14]),
'interpolate': 'perceptualuniform'},
'bluered': {'left': Color('HSL',[0.65,0.53,0.49]),
'right': Color('HSL',[0.97,0.96,0.36]),
'interpolate': 'perceptualuniform'},
'blueredrainbow':{'left': Color('HSL',[2.0/3.0,1,0.5]),
'right': Color('HSL',[0,1,0.5]),
'interpolate': 'linear' },
'orientation': {'left': Color('RGB',[0.933334,0.878432,0.878431]),
'right': Color('RGB',[0.250980,0.007843,0.000000]),
'interpolate': 'perceptualuniform'},
'strain': {'left': Color('RGB',[0.941177,0.941177,0.870588]),
'right': Color('RGB',[0.266667,0.266667,0.000000]),
'interpolate': 'perceptualuniform'},
'stress': {'left': Color('RGB',[0.878432,0.874511,0.949019]),
'right': Color('RGB',[0.000002,0.000000,0.286275]),
'interpolate': 'perceptualuniform'},
}
def __init__(self,
left = Color('RGB',[1,1,1]),
right = Color('RGB',[0,0,0]),
interpolate = 'perceptualuniform',
predefined = None
):
"""
Create a Colormap object.
Parameters
----------
left : Color
left color (minimum value)
right : Color
right color (maximum value)
interpolate : str
interpolation scheme (either 'perceptualuniform' or 'linear')
predefined : bool
ignore other arguments and use predefined definition
"""
if predefined is not None:
left = self.__predefined__[predefined.lower()]['left']
right= self.__predefined__[predefined.lower()]['right']
interpolate = self.__predefined__[predefined.lower()]['interpolate']
if left.__class__.__name__ != 'Color':
left = Color()
if right.__class__.__name__ != 'Color':
right = Color()
self.left = left
self.right = right
self.interpolate = interpolate
def __repr__(self):
"""Left and right value of colormap."""
return 'Left: %s Right: %s'%(self.left,self.right)
def invert(self):
"""Switch left/minimum with right/maximum."""
(self.left, self.right) = (self.right, self.left)
return self
def show_predefined(self):
"""Show the labels of the predefined colormaps."""
print('\n'.join(self.__predefined__.keys()))
def color(self,fraction = 0.5):
def interpolate_Msh(lo, hi, frac):
def rad_diff(a,b):
return abs(a[2]-b[2])
def adjust_hue(Msh_sat, Msh_unsat):
"""If saturation of one of the two colors is too less than the other, hue of the less."""
if Msh_sat[0] >= Msh_unsat[0]:
return Msh_sat[2]
else:
hSpin = Msh_sat[1]/np.sin(Msh_sat[1])*np.sqrt(Msh_unsat[0]**2.0-Msh_sat[0]**2)/Msh_sat[0]
if Msh_sat[2] < - np.pi/3.0: hSpin *= -1.0
return Msh_sat[2] + hSpin
Msh1 = np.array(lo[:])
Msh2 = np.array(hi[:])
if (Msh1[1] > 0.05 and Msh2[1] > 0.05 and rad_diff(Msh1,Msh2) > np.pi/3.0):
M_mid = max(Msh1[0],Msh2[0],88.0)
if frac < 0.5:
Msh2 = np.array([M_mid,0.0,0.0])
frac *= 2.0
else:
Msh1 = np.array([M_mid,0.0,0.0])
frac = 2.0*frac - 1.0
if Msh1[1] < 0.05 and Msh2[1] > 0.05: Msh1[2] = adjust_hue(Msh2,Msh1)
elif Msh1[1] > 0.05 and Msh2[1] < 0.05: Msh2[2] = adjust_hue(Msh1,Msh2)
Msh = (1.0 - frac) * Msh1 + frac * Msh2
return Color('MSH',Msh)
def interpolate_linear(lo, hi, frac):
"""Linear interpolation between lo and hi color at given fraction; output in model of lo color."""
interpolation = (1.0 - frac) * np.array(lo.color[:]) \
+ frac * np.array(hi.express_as(lo.model).color[:])
return Color(lo.model,interpolation)
if self.interpolate == 'perceptualuniform':
return interpolate_Msh(self.left.express_as('MSH').color,
self.right.express_as('MSH').color,fraction)
elif self.interpolate == 'linear':
return interpolate_linear(self.left,self.right,fraction)
else:
raise NameError('unknown color interpolation method')
def export(self,name = 'uniformPerceptualColorMap',\
format = 'paraview',\
steps = 2,\
crop = [-1.0,1.0],
model = 'RGB'):
"""
[RGB] colormap for use in paraview or gmsh, or as raw string, or array.
Arguments: name, format, steps, crop.
Format is one of (paraview, gmsh, gom, raw, list).
Crop selects a (sub)range in [-1.0,1.0].
Generates sequential map if one limiting color is either white or black,
diverging map otherwise.
"""
format = format.lower() # consistent comparison basis
frac = 0.5*(np.array(crop) + 1.0) # rescale crop range to fractions
colors = [self.color(float(i)/(steps-1)*(frac[1]-frac[0])+frac[0]).express_as(model).color for i in range(steps)]
if format == 'paraview':
colormap = [f'[\n {{\n "ColorSpace": "RGB", "Name": "{name}", "DefaultMap": true,\n "RGBPoints" : ['] \
+ [f' {i:4d},{color[0]:8.6f},{color[1]:8.6f},{color[2]:8.6f}{"," if i+1<len(colors) else ""}' \
for i,color in enumerate(colors)] \
+ [' ]\n }\n]']
elif format == 'gmsh':
colormap = ['View.ColorTable = {'] \
+ [',\n'.join([','.join([str(x*255.0) for x in color]) for color in colors])] \
+ ['}']
elif format == 'gom':
colormap = [ f'1 1 {name}'
+ f' 9 {name}'
+ ' 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(colors)}'
+ ' '.join([f' 0 {util.srepr((255*np.array(c)).astype(int)," ")} 255 1' for c in reversed(colors)])]
elif format == 'raw':
colormap = ['\t'.join(map(str,color)) for color in colors]
elif format == 'list':
colormap = colors
else:
raise NameError('unknown color export format')
return '\n'.join(colormap) + '\n' if type(colormap[0]) is str else colormap

View File

@ -1,19 +1,32 @@
import os
from pathlib import Path
import tkinter
class Environment:
# ToDo: Probably, we don't need a class (just a module with a few functions)
def __init__(self):
"""Read and provide values of DAMASK configuration."""
"""Do Nothing."""
pass
@property
def screen_size(self):
width = 1024
height = 768
try:
import wx
_ = wx.App(False) # noqa
width, height = wx.GetDisplaySize()
except ImportError:
try:
import tkinter
tk = tkinter.Tk()
self.screen_width = tk.winfo_screenwidth()
self.screen_height = tk.winfo_screenheight()
width = tk.winfo_screenwidth()
height = tk.winfo_screenheight()
tk.destroy()
except tkinter.TclError:
self.screen_width = 1024
self.screen_height = 768
except Exception as e:
pass
return (width,height)
@property
def options(self):
@ -26,6 +39,7 @@ class Environment:
return options
@property
def root_dir(self):
"""Return DAMASK root path."""

View File

@ -12,6 +12,7 @@ from functools import partial
import h5py
import numpy as np
import damask
from . import VTK
from . import Table
from . import Rotation
@ -20,7 +21,6 @@ from . import Environment
from . import grid_filters
from . import mechanics
from . import util
from . import version
class Result:
@ -1090,7 +1090,7 @@ class Result:
for l,v in result[1]['meta'].items():
dataset.attrs[l]=v.encode()
creator = f"damask.Result.{dataset.attrs['Creator'].decode()} v{version}"
creator = f"damask.Result.{dataset.attrs['Creator'].decode()} v{damask.version}"
dataset.attrs['Creator'] = creator.encode()
except (OSError,RuntimeError) as err:

View File

@ -19,11 +19,12 @@ class Table:
Data. Column labels from a pandas.DataFrame will be replaced.
shapes : dict with str:tuple pairs
Shapes of the columns. Example 'F':(3,3) for a deformation gradient.
comments : iterable of str, optional
comments : str or iterable of str, optional
Additional, human-readable information.
"""
self.comments = [] if comments is None else [c for c in comments]
comments_ = [comments] if isinstance(comments,str) else comments
self.comments = [] if comments_ is None else [c for c in comments_]
self.data = pd.DataFrame(data=data)
self.shapes = { k:(v,) if isinstance(v,(np.int,int)) else v for k,v in shapes.items() }
self._label_condensed()

View File

@ -6,9 +6,9 @@ import vtk
from vtk.util.numpy_support import numpy_to_vtk as np_to_vtk
from vtk.util.numpy_support import numpy_to_vtkIdTypeArray as np_to_vtkIdTypeArray
import damask
from . import Table
from . import Environment
from . import version
class VTK:
@ -216,7 +216,7 @@ class VTK:
def __repr__(self):
"""ASCII representation of the VTK data."""
writer = vtk.vtkDataSetWriter()
writer.SetHeader(f'# DAMASK.VTK v{version}')
writer.SetHeader(f'# damask.VTK v{damask.version}')
writer.WriteToOutputStringOn()
writer.SetInputData(self.geom)
writer.Write()
@ -242,7 +242,7 @@ class VTK:
ren.AddActor(actor)
ren.SetBackground(0.2,0.2,0.2)
window.SetSize(Environment().screen_width,Environment().screen_height)
window.SetSize(Environment().screen_size[0],Environment().screen_size[1])
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(window)

View File

@ -2,6 +2,11 @@ from pathlib import Path
import pytest
# Use to monkeypatch damask.version (for comparsion to reference files that contain version information)
def pytest_configure():
pytest.dummy_version = '99.99.99-9999-pytest'
def pytest_addoption(parser):
parser.addoption("--update",
action="store_true",

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,258 @@
View.ColorTable = {
255.0,255.0,255.0,
254.0,254.0,254.0,
253.0,253.0,253.0,
252.0,252.0,252.0,
251.0,251.0,251.0,
250.0,250.0,250.0,
249.0,249.0,249.0,
248.0,248.0,248.0,
247.0,247.0,247.0,
246.0,246.0,246.0,
245.0,245.0,245.0,
244.0,244.0,244.0,
243.0,243.0,243.0,
242.0,242.0,242.0,
241.0,241.0,241.0,
240.0,240.0,240.0,
239.0,239.0,239.0,
238.0,238.0,238.0,
237.0,237.0,237.0,
236.0,236.0,236.0,
235.00000000000003,235.00000000000003,235.00000000000003,
234.0,234.0,234.0,
233.0,233.0,233.0,
232.0,232.0,232.0,
231.0,231.0,231.0,
230.0,230.0,230.0,
229.0,229.0,229.0,
228.0,228.0,228.0,
227.0,227.0,227.0,
226.0,226.0,226.0,
225.0,225.0,225.0,
224.0,224.0,224.0,
223.0,223.0,223.0,
222.0,222.0,222.0,
221.0,221.0,221.0,
220.0,220.0,220.0,
219.00000000000003,219.00000000000003,219.00000000000003,
218.00000000000003,218.00000000000003,218.00000000000003,
217.0,217.0,217.0,
216.0,216.0,216.0,
215.0,215.0,215.0,
214.0,214.0,214.0,
213.0,213.0,213.0,
211.99999999999997,211.99999999999997,211.99999999999997,
211.0,211.0,211.0,
210.0,210.0,210.0,
209.0,209.0,209.0,
208.0,208.0,208.0,
207.0,207.0,207.0,
206.0,206.0,206.0,
205.0,205.0,205.0,
204.0,204.0,204.0,
203.00000000000003,203.00000000000003,203.00000000000003,
202.00000000000003,202.00000000000003,202.00000000000003,
201.0,201.0,201.0,
200.0,200.0,200.0,
199.0,199.0,199.0,
198.0,198.0,198.0,
197.0,197.0,197.0,
195.99999999999997,195.99999999999997,195.99999999999997,
195.0,195.0,195.0,
194.0,194.0,194.0,
193.0,193.0,193.0,
192.0,192.0,192.0,
191.0,191.0,191.0,
190.0,190.0,190.0,
189.0,189.0,189.0,
188.0,188.0,188.0,
187.00000000000003,187.00000000000003,187.00000000000003,
186.00000000000003,186.00000000000003,186.00000000000003,
185.0,185.0,185.0,
184.0,184.0,184.0,
183.0,183.0,183.0,
182.0,182.0,182.0,
181.0,181.0,181.0,
179.99999999999997,179.99999999999997,179.99999999999997,
179.0,179.0,179.0,
178.0,178.0,178.0,
177.0,177.0,177.0,
176.0,176.0,176.0,
175.0,175.0,175.0,
174.0,174.0,174.0,
173.0,173.0,173.0,
172.0,172.0,172.0,
171.00000000000003,171.00000000000003,171.00000000000003,
170.00000000000003,170.00000000000003,170.00000000000003,
169.0,169.0,169.0,
168.0,168.0,168.0,
167.0,167.0,167.0,
166.0,166.0,166.0,
165.0,165.0,165.0,
163.99999999999997,163.99999999999997,163.99999999999997,
163.0,163.0,163.0,
162.0,162.0,162.0,
161.0,161.0,161.0,
160.0,160.0,160.0,
159.0,159.0,159.0,
158.0,158.0,158.0,
157.0,157.0,157.0,
156.0,156.0,156.0,
155.00000000000003,155.00000000000003,155.00000000000003,
154.00000000000003,154.00000000000003,154.00000000000003,
153.0,153.0,153.0,
152.0,152.0,152.0,
151.0,151.0,151.0,
150.0,150.0,150.0,
149.0,149.0,149.0,
147.99999999999997,147.99999999999997,147.99999999999997,
147.0,147.0,147.0,
146.0,146.0,146.0,
145.0,145.0,145.0,
144.0,144.0,144.0,
143.0,143.0,143.0,
142.0,142.0,142.0,
141.0,141.0,141.0,
140.0,140.0,140.0,
139.00000000000003,139.00000000000003,139.00000000000003,
138.00000000000003,138.00000000000003,138.00000000000003,
137.0,137.0,137.0,
136.0,136.0,136.0,
135.0,135.0,135.0,
134.0,134.0,134.0,
133.0,133.0,133.0,
131.99999999999997,131.99999999999997,131.99999999999997,
131.0,131.0,131.0,
130.0,130.0,130.0,
129.0,129.0,129.0,
128.0,128.0,128.0,
127.0,127.0,127.0,
126.0,126.0,126.0,
125.00000000000001,125.00000000000001,125.00000000000001,
124.00000000000001,124.00000000000001,124.00000000000001,
123.00000000000001,123.00000000000001,123.00000000000001,
121.99999999999999,121.99999999999999,121.99999999999999,
121.0,121.0,121.0,
120.0,120.0,120.0,
119.0,119.0,119.0,
118.0,118.0,118.0,
117.00000000000001,117.00000000000001,117.00000000000001,
116.00000000000001,116.00000000000001,116.00000000000001,
114.99999999999999,114.99999999999999,114.99999999999999,
113.99999999999999,113.99999999999999,113.99999999999999,
113.0,113.0,113.0,
112.0,112.0,112.0,
111.0,111.0,111.0,
110.0,110.0,110.0,
109.00000000000001,109.00000000000001,109.00000000000001,
108.00000000000001,108.00000000000001,108.00000000000001,
107.00000000000001,107.00000000000001,107.00000000000001,
105.99999999999999,105.99999999999999,105.99999999999999,
105.0,105.0,105.0,
104.0,104.0,104.0,
103.0,103.0,103.0,
102.0,102.0,102.0,
101.00000000000001,101.00000000000001,101.00000000000001,
100.00000000000001,100.00000000000001,100.00000000000001,
98.99999999999999,98.99999999999999,98.99999999999999,
97.99999999999999,97.99999999999999,97.99999999999999,
97.0,97.0,97.0,
96.0,96.0,96.0,
95.0,95.0,95.0,
94.0,94.0,94.0,
93.00000000000001,93.00000000000001,93.00000000000001,
92.00000000000001,92.00000000000001,92.00000000000001,
91.00000000000001,91.00000000000001,91.00000000000001,
89.99999999999999,89.99999999999999,89.99999999999999,
89.0,89.0,89.0,
88.0,88.0,88.0,
87.0,87.0,87.0,
86.0,86.0,86.0,
85.00000000000001,85.00000000000001,85.00000000000001,
84.00000000000001,84.00000000000001,84.00000000000001,
82.99999999999999,82.99999999999999,82.99999999999999,
81.99999999999999,81.99999999999999,81.99999999999999,
81.0,81.0,81.0,
80.0,80.0,80.0,
79.0,79.0,79.0,
78.0,78.0,78.0,
77.00000000000001,77.00000000000001,77.00000000000001,
76.00000000000001,76.00000000000001,76.00000000000001,
75.00000000000001,75.00000000000001,75.00000000000001,
73.99999999999999,73.99999999999999,73.99999999999999,
73.0,73.0,73.0,
72.0,72.0,72.0,
71.0,71.0,71.0,
70.0,70.0,70.0,
69.00000000000001,69.00000000000001,69.00000000000001,
68.00000000000001,68.00000000000001,68.00000000000001,
66.99999999999999,66.99999999999999,66.99999999999999,
65.99999999999999,65.99999999999999,65.99999999999999,
65.0,65.0,65.0,
64.0,64.0,64.0,
63.0,63.0,63.0,
62.00000000000001,62.00000000000001,62.00000000000001,
61.00000000000001,61.00000000000001,61.00000000000001,
60.000000000000014,60.000000000000014,60.000000000000014,
59.000000000000014,59.000000000000014,59.000000000000014,
57.99999999999999,57.99999999999999,57.99999999999999,
56.99999999999999,56.99999999999999,56.99999999999999,
56.0,56.0,56.0,
55.0,55.0,55.0,
54.00000000000001,54.00000000000001,54.00000000000001,
53.00000000000001,53.00000000000001,53.00000000000001,
52.000000000000014,52.000000000000014,52.000000000000014,
50.999999999999986,50.999999999999986,50.999999999999986,
49.99999999999999,49.99999999999999,49.99999999999999,
48.99999999999999,48.99999999999999,48.99999999999999,
48.0,48.0,48.0,
47.0,47.0,47.0,
46.00000000000001,46.00000000000001,46.00000000000001,
45.00000000000001,45.00000000000001,45.00000000000001,
44.000000000000014,44.000000000000014,44.000000000000014,
43.000000000000014,43.000000000000014,43.000000000000014,
41.99999999999999,41.99999999999999,41.99999999999999,
40.99999999999999,40.99999999999999,40.99999999999999,
40.0,40.0,40.0,
39.0,39.0,39.0,
38.00000000000001,38.00000000000001,38.00000000000001,
37.00000000000001,37.00000000000001,37.00000000000001,
36.000000000000014,36.000000000000014,36.000000000000014,
34.999999999999986,34.999999999999986,34.999999999999986,
33.99999999999999,33.99999999999999,33.99999999999999,
32.99999999999999,32.99999999999999,32.99999999999999,
32.0,32.0,32.0,
31.000000000000004,31.000000000000004,31.000000000000004,
30.000000000000007,30.000000000000007,30.000000000000007,
29.00000000000001,29.00000000000001,29.00000000000001,
28.000000000000014,28.000000000000014,28.000000000000014,
27.000000000000018,27.000000000000018,27.000000000000018,
25.999999999999993,25.999999999999993,25.999999999999993,
24.999999999999996,24.999999999999996,24.999999999999996,
24.0,24.0,24.0,
23.000000000000004,23.000000000000004,23.000000000000004,
22.000000000000007,22.000000000000007,22.000000000000007,
21.00000000000001,21.00000000000001,21.00000000000001,
20.000000000000014,20.000000000000014,20.000000000000014,
18.99999999999999,18.99999999999999,18.99999999999999,
17.999999999999993,17.999999999999993,17.999999999999993,
16.999999999999996,16.999999999999996,16.999999999999996,
16.0,16.0,16.0,
15.000000000000004,15.000000000000004,15.000000000000004,
14.000000000000007,14.000000000000007,14.000000000000007,
13.00000000000001,13.00000000000001,13.00000000000001,
12.000000000000014,12.000000000000014,12.000000000000014,
11.000000000000018,11.000000000000018,11.000000000000018,
9.999999999999993,9.999999999999993,9.999999999999993,
8.999999999999996,8.999999999999996,8.999999999999996,
8.0,8.0,8.0,
7.0000000000000036,7.0000000000000036,7.0000000000000036,
6.000000000000007,6.000000000000007,6.000000000000007,
5.000000000000011,5.000000000000011,5.000000000000011,
4.000000000000014,4.000000000000014,4.000000000000014,
2.9999999999999893,2.9999999999999893,2.9999999999999893,
1.999999999999993,1.999999999999993,1.999999999999993,
0.9999999999999964,0.9999999999999964,0.9999999999999964,
0.0,0.0,0.0,
}

View File

@ -0,0 +1,258 @@
# Creator: damask.Colormap v99.99.99-9999-pytest
1_RGBA 2_RGBA 3_RGBA 4_RGBA
1.0 1.0 1.0 1.0
0.996078431372549 0.996078431372549 0.996078431372549 1.0
0.9921568627450981 0.9921568627450981 0.9921568627450981 1.0
0.9882352941176471 0.9882352941176471 0.9882352941176471 1.0
0.9843137254901961 0.9843137254901961 0.9843137254901961 1.0
0.9803921568627451 0.9803921568627451 0.9803921568627451 1.0
0.9764705882352941 0.9764705882352941 0.9764705882352941 1.0
0.9725490196078431 0.9725490196078431 0.9725490196078431 1.0
0.9686274509803922 0.9686274509803922 0.9686274509803922 1.0
0.9647058823529412 0.9647058823529412 0.9647058823529412 1.0
0.9607843137254902 0.9607843137254902 0.9607843137254902 1.0
0.9568627450980393 0.9568627450980393 0.9568627450980393 1.0
0.9529411764705882 0.9529411764705882 0.9529411764705882 1.0
0.9490196078431372 0.9490196078431372 0.9490196078431372 1.0
0.9450980392156862 0.9450980392156862 0.9450980392156862 1.0
0.9411764705882353 0.9411764705882353 0.9411764705882353 1.0
0.9372549019607843 0.9372549019607843 0.9372549019607843 1.0
0.9333333333333333 0.9333333333333333 0.9333333333333333 1.0
0.9294117647058824 0.9294117647058824 0.9294117647058824 1.0
0.9254901960784314 0.9254901960784314 0.9254901960784314 1.0
0.9215686274509804 0.9215686274509804 0.9215686274509804 1.0
0.9176470588235294 0.9176470588235294 0.9176470588235294 1.0
0.9137254901960784 0.9137254901960784 0.9137254901960784 1.0
0.9098039215686274 0.9098039215686274 0.9098039215686274 1.0
0.9058823529411765 0.9058823529411765 0.9058823529411765 1.0
0.9019607843137255 0.9019607843137255 0.9019607843137255 1.0
0.8980392156862745 0.8980392156862745 0.8980392156862745 1.0
0.8941176470588236 0.8941176470588236 0.8941176470588236 1.0
0.8901960784313725 0.8901960784313725 0.8901960784313725 1.0
0.8862745098039215 0.8862745098039215 0.8862745098039215 1.0
0.8823529411764706 0.8823529411764706 0.8823529411764706 1.0
0.8784313725490196 0.8784313725490196 0.8784313725490196 1.0
0.8745098039215686 0.8745098039215686 0.8745098039215686 1.0
0.8705882352941177 0.8705882352941177 0.8705882352941177 1.0
0.8666666666666667 0.8666666666666667 0.8666666666666667 1.0
0.8627450980392157 0.8627450980392157 0.8627450980392157 1.0
0.8588235294117648 0.8588235294117648 0.8588235294117648 1.0
0.8549019607843138 0.8549019607843138 0.8549019607843138 1.0
0.8509803921568627 0.8509803921568627 0.8509803921568627 1.0
0.8470588235294118 0.8470588235294118 0.8470588235294118 1.0
0.8431372549019608 0.8431372549019608 0.8431372549019608 1.0
0.8392156862745098 0.8392156862745098 0.8392156862745098 1.0
0.8352941176470589 0.8352941176470589 0.8352941176470589 1.0
0.8313725490196078 0.8313725490196078 0.8313725490196078 1.0
0.8274509803921568 0.8274509803921568 0.8274509803921568 1.0
0.8235294117647058 0.8235294117647058 0.8235294117647058 1.0
0.8196078431372549 0.8196078431372549 0.8196078431372549 1.0
0.8156862745098039 0.8156862745098039 0.8156862745098039 1.0
0.8117647058823529 0.8117647058823529 0.8117647058823529 1.0
0.807843137254902 0.807843137254902 0.807843137254902 1.0
0.803921568627451 0.803921568627451 0.803921568627451 1.0
0.8 0.8 0.8 1.0
0.7960784313725491 0.7960784313725491 0.7960784313725491 1.0
0.7921568627450981 0.7921568627450981 0.7921568627450981 1.0
0.788235294117647 0.788235294117647 0.788235294117647 1.0
0.7843137254901961 0.7843137254901961 0.7843137254901961 1.0
0.7803921568627451 0.7803921568627451 0.7803921568627451 1.0
0.7764705882352941 0.7764705882352941 0.7764705882352941 1.0
0.7725490196078432 0.7725490196078432 0.7725490196078432 1.0
0.7686274509803921 0.7686274509803921 0.7686274509803921 1.0
0.7647058823529411 0.7647058823529411 0.7647058823529411 1.0
0.7607843137254902 0.7607843137254902 0.7607843137254902 1.0
0.7568627450980392 0.7568627450980392 0.7568627450980392 1.0
0.7529411764705882 0.7529411764705882 0.7529411764705882 1.0
0.7490196078431373 0.7490196078431373 0.7490196078431373 1.0
0.7450980392156863 0.7450980392156863 0.7450980392156863 1.0
0.7411764705882353 0.7411764705882353 0.7411764705882353 1.0
0.7372549019607844 0.7372549019607844 0.7372549019607844 1.0
0.7333333333333334 0.7333333333333334 0.7333333333333334 1.0
0.7294117647058824 0.7294117647058824 0.7294117647058824 1.0
0.7254901960784313 0.7254901960784313 0.7254901960784313 1.0
0.7215686274509804 0.7215686274509804 0.7215686274509804 1.0
0.7176470588235294 0.7176470588235294 0.7176470588235294 1.0
0.7137254901960784 0.7137254901960784 0.7137254901960784 1.0
0.7098039215686275 0.7098039215686275 0.7098039215686275 1.0
0.7058823529411764 0.7058823529411764 0.7058823529411764 1.0
0.7019607843137254 0.7019607843137254 0.7019607843137254 1.0
0.6980392156862745 0.6980392156862745 0.6980392156862745 1.0
0.6941176470588235 0.6941176470588235 0.6941176470588235 1.0
0.6901960784313725 0.6901960784313725 0.6901960784313725 1.0
0.6862745098039216 0.6862745098039216 0.6862745098039216 1.0
0.6823529411764706 0.6823529411764706 0.6823529411764706 1.0
0.6784313725490196 0.6784313725490196 0.6784313725490196 1.0
0.6745098039215687 0.6745098039215687 0.6745098039215687 1.0
0.6705882352941177 0.6705882352941177 0.6705882352941177 1.0
0.6666666666666667 0.6666666666666667 0.6666666666666667 1.0
0.6627450980392157 0.6627450980392157 0.6627450980392157 1.0
0.6588235294117647 0.6588235294117647 0.6588235294117647 1.0
0.6549019607843137 0.6549019607843137 0.6549019607843137 1.0
0.6509803921568628 0.6509803921568628 0.6509803921568628 1.0
0.6470588235294118 0.6470588235294118 0.6470588235294118 1.0
0.6431372549019607 0.6431372549019607 0.6431372549019607 1.0
0.6392156862745098 0.6392156862745098 0.6392156862745098 1.0
0.6352941176470588 0.6352941176470588 0.6352941176470588 1.0
0.6313725490196078 0.6313725490196078 0.6313725490196078 1.0
0.6274509803921569 0.6274509803921569 0.6274509803921569 1.0
0.6235294117647059 0.6235294117647059 0.6235294117647059 1.0
0.6196078431372549 0.6196078431372549 0.6196078431372549 1.0
0.615686274509804 0.615686274509804 0.615686274509804 1.0
0.611764705882353 0.611764705882353 0.611764705882353 1.0
0.607843137254902 0.607843137254902 0.607843137254902 1.0
0.603921568627451 0.603921568627451 0.603921568627451 1.0
0.6 0.6 0.6 1.0
0.596078431372549 0.596078431372549 0.596078431372549 1.0
0.592156862745098 0.592156862745098 0.592156862745098 1.0
0.5882352941176471 0.5882352941176471 0.5882352941176471 1.0
0.5843137254901961 0.5843137254901961 0.5843137254901961 1.0
0.580392156862745 0.580392156862745 0.580392156862745 1.0
0.5764705882352941 0.5764705882352941 0.5764705882352941 1.0
0.5725490196078431 0.5725490196078431 0.5725490196078431 1.0
0.5686274509803921 0.5686274509803921 0.5686274509803921 1.0
0.5647058823529412 0.5647058823529412 0.5647058823529412 1.0
0.5607843137254902 0.5607843137254902 0.5607843137254902 1.0
0.5568627450980392 0.5568627450980392 0.5568627450980392 1.0
0.5529411764705883 0.5529411764705883 0.5529411764705883 1.0
0.5490196078431373 0.5490196078431373 0.5490196078431373 1.0
0.5450980392156863 0.5450980392156863 0.5450980392156863 1.0
0.5411764705882354 0.5411764705882354 0.5411764705882354 1.0
0.5372549019607843 0.5372549019607843 0.5372549019607843 1.0
0.5333333333333333 0.5333333333333333 0.5333333333333333 1.0
0.5294117647058824 0.5294117647058824 0.5294117647058824 1.0
0.5254901960784314 0.5254901960784314 0.5254901960784314 1.0
0.5215686274509804 0.5215686274509804 0.5215686274509804 1.0
0.5176470588235293 0.5176470588235293 0.5176470588235293 1.0
0.5137254901960784 0.5137254901960784 0.5137254901960784 1.0
0.5098039215686274 0.5098039215686274 0.5098039215686274 1.0
0.5058823529411764 0.5058823529411764 0.5058823529411764 1.0
0.5019607843137255 0.5019607843137255 0.5019607843137255 1.0
0.4980392156862745 0.4980392156862745 0.4980392156862745 1.0
0.49411764705882355 0.49411764705882355 0.49411764705882355 1.0
0.4901960784313726 0.4901960784313726 0.4901960784313726 1.0
0.4862745098039216 0.4862745098039216 0.4862745098039216 1.0
0.48235294117647065 0.48235294117647065 0.48235294117647065 1.0
0.4784313725490196 0.4784313725490196 0.4784313725490196 1.0
0.4745098039215686 0.4745098039215686 0.4745098039215686 1.0
0.47058823529411764 0.47058823529411764 0.47058823529411764 1.0
0.4666666666666667 0.4666666666666667 0.4666666666666667 1.0
0.4627450980392157 0.4627450980392157 0.4627450980392157 1.0
0.45882352941176474 0.45882352941176474 0.45882352941176474 1.0
0.4549019607843138 0.4549019607843138 0.4549019607843138 1.0
0.4509803921568627 0.4509803921568627 0.4509803921568627 1.0
0.44705882352941173 0.44705882352941173 0.44705882352941173 1.0
0.44313725490196076 0.44313725490196076 0.44313725490196076 1.0
0.4392156862745098 0.4392156862745098 0.4392156862745098 1.0
0.43529411764705883 0.43529411764705883 0.43529411764705883 1.0
0.43137254901960786 0.43137254901960786 0.43137254901960786 1.0
0.4274509803921569 0.4274509803921569 0.4274509803921569 1.0
0.42352941176470593 0.42352941176470593 0.42352941176470593 1.0
0.41960784313725497 0.41960784313725497 0.41960784313725497 1.0
0.4156862745098039 0.4156862745098039 0.4156862745098039 1.0
0.4117647058823529 0.4117647058823529 0.4117647058823529 1.0
0.40784313725490196 0.40784313725490196 0.40784313725490196 1.0
0.403921568627451 0.403921568627451 0.403921568627451 1.0
0.4 0.4 0.4 1.0
0.39607843137254906 0.39607843137254906 0.39607843137254906 1.0
0.3921568627450981 0.3921568627450981 0.3921568627450981 1.0
0.388235294117647 0.388235294117647 0.388235294117647 1.0
0.38431372549019605 0.38431372549019605 0.38431372549019605 1.0
0.3803921568627451 0.3803921568627451 0.3803921568627451 1.0
0.3764705882352941 0.3764705882352941 0.3764705882352941 1.0
0.37254901960784315 0.37254901960784315 0.37254901960784315 1.0
0.3686274509803922 0.3686274509803922 0.3686274509803922 1.0
0.3647058823529412 0.3647058823529412 0.3647058823529412 1.0
0.36078431372549025 0.36078431372549025 0.36078431372549025 1.0
0.3568627450980393 0.3568627450980393 0.3568627450980393 1.0
0.3529411764705882 0.3529411764705882 0.3529411764705882 1.0
0.34901960784313724 0.34901960784313724 0.34901960784313724 1.0
0.34509803921568627 0.34509803921568627 0.34509803921568627 1.0
0.3411764705882353 0.3411764705882353 0.3411764705882353 1.0
0.33725490196078434 0.33725490196078434 0.33725490196078434 1.0
0.33333333333333337 0.33333333333333337 0.33333333333333337 1.0
0.3294117647058824 0.3294117647058824 0.3294117647058824 1.0
0.3254901960784313 0.3254901960784313 0.3254901960784313 1.0
0.32156862745098036 0.32156862745098036 0.32156862745098036 1.0
0.3176470588235294 0.3176470588235294 0.3176470588235294 1.0
0.3137254901960784 0.3137254901960784 0.3137254901960784 1.0
0.30980392156862746 0.30980392156862746 0.30980392156862746 1.0
0.3058823529411765 0.3058823529411765 0.3058823529411765 1.0
0.3019607843137255 0.3019607843137255 0.3019607843137255 1.0
0.29803921568627456 0.29803921568627456 0.29803921568627456 1.0
0.2941176470588236 0.2941176470588236 0.2941176470588236 1.0
0.2901960784313725 0.2901960784313725 0.2901960784313725 1.0
0.28627450980392155 0.28627450980392155 0.28627450980392155 1.0
0.2823529411764706 0.2823529411764706 0.2823529411764706 1.0
0.2784313725490196 0.2784313725490196 0.2784313725490196 1.0
0.27450980392156865 0.27450980392156865 0.27450980392156865 1.0
0.2705882352941177 0.2705882352941177 0.2705882352941177 1.0
0.2666666666666667 0.2666666666666667 0.2666666666666667 1.0
0.26274509803921564 0.26274509803921564 0.26274509803921564 1.0
0.2588235294117647 0.2588235294117647 0.2588235294117647 1.0
0.2549019607843137 0.2549019607843137 0.2549019607843137 1.0
0.25098039215686274 0.25098039215686274 0.25098039215686274 1.0
0.24705882352941178 0.24705882352941178 0.24705882352941178 1.0
0.2431372549019608 0.2431372549019608 0.2431372549019608 1.0
0.23921568627450984 0.23921568627450984 0.23921568627450984 1.0
0.23529411764705888 0.23529411764705888 0.23529411764705888 1.0
0.2313725490196079 0.2313725490196079 0.2313725490196079 1.0
0.22745098039215683 0.22745098039215683 0.22745098039215683 1.0
0.22352941176470587 0.22352941176470587 0.22352941176470587 1.0
0.2196078431372549 0.2196078431372549 0.2196078431372549 1.0
0.21568627450980393 0.21568627450980393 0.21568627450980393 1.0
0.21176470588235297 0.21176470588235297 0.21176470588235297 1.0
0.207843137254902 0.207843137254902 0.207843137254902 1.0
0.20392156862745103 0.20392156862745103 0.20392156862745103 1.0
0.19999999999999996 0.19999999999999996 0.19999999999999996 1.0
0.196078431372549 0.196078431372549 0.196078431372549 1.0
0.19215686274509802 0.19215686274509802 0.19215686274509802 1.0
0.18823529411764706 0.18823529411764706 0.18823529411764706 1.0
0.1843137254901961 0.1843137254901961 0.1843137254901961 1.0
0.18039215686274512 0.18039215686274512 0.18039215686274512 1.0
0.17647058823529416 0.17647058823529416 0.17647058823529416 1.0
0.1725490196078432 0.1725490196078432 0.1725490196078432 1.0
0.16862745098039222 0.16862745098039222 0.16862745098039222 1.0
0.16470588235294115 0.16470588235294115 0.16470588235294115 1.0
0.16078431372549018 0.16078431372549018 0.16078431372549018 1.0
0.1568627450980392 0.1568627450980392 0.1568627450980392 1.0
0.15294117647058825 0.15294117647058825 0.15294117647058825 1.0
0.14901960784313728 0.14901960784313728 0.14901960784313728 1.0
0.14509803921568631 0.14509803921568631 0.14509803921568631 1.0
0.14117647058823535 0.14117647058823535 0.14117647058823535 1.0
0.13725490196078427 0.13725490196078427 0.13725490196078427 1.0
0.1333333333333333 0.1333333333333333 0.1333333333333333 1.0
0.12941176470588234 0.12941176470588234 0.12941176470588234 1.0
0.12549019607843137 0.12549019607843137 0.12549019607843137 1.0
0.1215686274509804 0.1215686274509804 0.1215686274509804 1.0
0.11764705882352944 0.11764705882352944 0.11764705882352944 1.0
0.11372549019607847 0.11372549019607847 0.11372549019607847 1.0
0.1098039215686275 0.1098039215686275 0.1098039215686275 1.0
0.10588235294117654 0.10588235294117654 0.10588235294117654 1.0
0.10196078431372546 0.10196078431372546 0.10196078431372546 1.0
0.0980392156862745 0.0980392156862745 0.0980392156862745 1.0
0.09411764705882353 0.09411764705882353 0.09411764705882353 1.0
0.09019607843137256 0.09019607843137256 0.09019607843137256 1.0
0.0862745098039216 0.0862745098039216 0.0862745098039216 1.0
0.08235294117647063 0.08235294117647063 0.08235294117647063 1.0
0.07843137254901966 0.07843137254901966 0.07843137254901966 1.0
0.07450980392156858 0.07450980392156858 0.07450980392156858 1.0
0.07058823529411762 0.07058823529411762 0.07058823529411762 1.0
0.06666666666666665 0.06666666666666665 0.06666666666666665 1.0
0.06274509803921569 0.06274509803921569 0.06274509803921569 1.0
0.05882352941176472 0.05882352941176472 0.05882352941176472 1.0
0.05490196078431375 0.05490196078431375 0.05490196078431375 1.0
0.050980392156862786 0.050980392156862786 0.050980392156862786 1.0
0.04705882352941182 0.04705882352941182 0.04705882352941182 1.0
0.04313725490196085 0.04313725490196085 0.04313725490196085 1.0
0.039215686274509776 0.039215686274509776 0.039215686274509776 1.0
0.03529411764705881 0.03529411764705881 0.03529411764705881 1.0
0.03137254901960784 0.03137254901960784 0.03137254901960784 1.0
0.027450980392156876 0.027450980392156876 0.027450980392156876 1.0
0.02352941176470591 0.02352941176470591 0.02352941176470591 1.0
0.019607843137254943 0.019607843137254943 0.019607843137254943 1.0
0.015686274509803977 0.015686274509803977 0.015686274509803977 1.0
0.0117647058823529 0.0117647058823529 0.0117647058823529 1.0
0.007843137254901933 0.007843137254901933 0.007843137254901933 1.0
0.0039215686274509665 0.0039215686274509665 0.0039215686274509665 1.0
0.0 0.0 0.0 1.0

View File

@ -0,0 +1,151 @@
import os
import filecmp
import time
import numpy as np
import pytest
import damask
from damask import Colormap
@pytest.fixture
def reference_dir(reference_dir_base):
"""Directory containing reference results."""
return reference_dir_base/'Colormap'
class TestColormap:
def test_conversion(self):
specials = np.array([[0.,0.,0.],
[1.,0.,0.],
[0.,1.,0.],
[0.,0.,1.],
[1.,1.,0.],
[0.,1.,1.],
[1.,0.,1.],
[1.,1.,1.]
])
rgbs = np.vstack((specials,np.random.rand(100,3)))
pass # class not integrated
for rgb in rgbs:
print('rgb',rgb)
# rgb2hsv2rgb
hsv = Colormap._rgb2hsv(rgb)
print('hsv',hsv)
assert np.allclose(Colormap._hsv2rgb(hsv),rgb)
# rgb2hsl2rgb
hsl = Colormap._rgb2hsl(rgb)
print('hsl',hsl)
assert np.allclose(Colormap._hsl2rgb(hsl),rgb)
# rgb2xyz2rgb
xyz = Colormap._rgb2xyz(rgb)
print('xyz',xyz)
assert np.allclose(Colormap._xyz2rgb(xyz),rgb,atol=1.e-6,rtol=0)
# xyz2lab2xyz
lab = Colormap._xyz2lab(xyz)
print('lab',lab)
assert np.allclose(Colormap._lab2xyz(lab),xyz)
# lab2msh2lab
msh = Colormap._lab2msh(lab)
print('msh',msh)
assert np.allclose(Colormap._msh2lab(msh),lab)
# lab2rgb2lab
assert np.allclose(Colormap._rgb2lab(Colormap._lab2rgb(lab)),lab,atol=1.e-6,rtol=0)
# rgb2msh2rgb
assert np.allclose(Colormap._msh2rgb(Colormap._rgb2msh(rgb)),rgb,atol=1.e-6,rtol=0)
# hsv2msh
assert np.allclose(Colormap._hsv2msh(hsv),msh,atol=1.e-6,rtol=0)
# hsl2msh
assert np.allclose(Colormap._hsv2msh(hsv),msh,atol=1.e-6,rtol=0)
# xyz2msh
assert np.allclose(Colormap._xyz2msh(xyz),msh,atol=1.e-6,rtol=0)
@pytest.mark.parametrize('format',['ASCII','paraview','GOM','Gmsh'])
@pytest.mark.parametrize('model',['rgb','hsv','hsl','xyz','lab','msh'])
def test_from_range(self,model,format,tmpdir):
N = np.random.randint(2,256)
c = Colormap.from_range(np.random.rand(3),np.random.rand(3),model=model,N=N)
c.to_file(tmpdir/'color_out',format=format)
@pytest.mark.parametrize('format',['ASCII','paraview','GOM','Gmsh'])
@pytest.mark.parametrize('name',['strain','gnuplot','Greys','PRGn','viridis'])
def test_from_predefined(self,name,format,tmpdir):
N = np.random.randint(2,256)
c = Colormap.from_predefined(name,N)
os.chdir(tmpdir)
c.to_file(format=format)
@pytest.mark.parametrize('format,name',[('ASCII','test.txt'),
('paraview','test.json'),
('GOM','test.legend'),
('Gmsh','test.msh')
])
def test_write_filehandle(self,format,name,tmpdir):
c = Colormap.from_predefined('Dark2')
fname = tmpdir/name
with open(fname,'w') as f:
c.to_file(f,format=format)
for i in range(10):
if fname.exists(): return
time.sleep(.5)
assert False
def test_write_invalid_format(self):
c = Colormap.from_predefined('Dark2')
with pytest.raises(ValueError):
c.to_file(format='invalid')
@pytest.mark.parametrize('model',['rgb','hsv','hsl','lab','invalid'])
def test_invalid_color(self,model):
with pytest.raises(ValueError):
c = Colormap.from_range(-2.+np.random.rand(3),np.random.rand(3),N=10,model=model) # noqa
def test_reversed(self):
c_1 = Colormap.from_predefined('stress')
c_2 = c_1.reversed()
assert (not np.allclose(c_1.colors,c_2.colors)) and \
np.allclose(c_1.colors,c_2.reversed().colors)
def test_invert(self):
c_1 = Colormap.from_predefined('strain')
c_2 = ~c_1
assert (not np.allclose(c_1.colors,c_2.colors)) and \
np.allclose(c_1.colors,(~c_2).colors)
def test_add(self):
c = Colormap.from_predefined('jet')
c += c
assert (np.allclose(c.colors[:len(c.colors)//2],c.colors[len(c.colors)//2:]))
def test_list(self):
Colormap.list_predefined()
@pytest.mark.parametrize('format,ext',[('ASCII','.txt'),
('paraview','.json'),
('GOM','.legend'),
('Gmsh','.msh')
])
def test_compare_reference(self,format,ext,tmpdir,reference_dir,update,monkeypatch):
monkeypatch.setattr(damask, 'version', pytest.dummy_version)
name = 'binary'
c = Colormap.from_predefined(name)
if update:
os.chdir(reference_dir)
c.to_file(format=format)
else:
os.chdir(tmpdir)
c.to_file(format=format)
time.sleep(.5)
assert filecmp.cmp(tmpdir/(name+ext),reference_dir/(name+ext))