checked with prospector, adopted mainly docstrings

This commit is contained in:
Martin Diehl 2016-03-04 17:53:55 +01:00
parent f13ba71f6e
commit 24391b5398
4 changed files with 169 additions and 175 deletions

View File

@ -5,11 +5,12 @@ import math,numpy as np
### --- COLOR CLASS -------------------------------------------------- ### --- COLOR CLASS --------------------------------------------------
class Color(): class Color():
''' """Conversion of colors between different color-spaces.
Conversion of colors between different color-spaces. Colors should be given in the form
Colors should be given in the form
Color('model',[vector]).To convert and copy color from one space to other, use the methods Color('model',[vector]).To convert and copy color from one space to other, use the methods
convertTo('model') and expressAs('model')spectively convertTo('model') and expressAs('model')spectively
''' """
__slots__ = [ __slots__ = [
'model', 'model',
@ -17,7 +18,7 @@ class Color():
] ]
# ------------------------------------------------------------------ # ------------------------------------------------------------------
def __init__(self, def __init__(self,
model = 'RGB', model = 'RGB',
color = np.zeros(3,'d')): color = np.zeros(3,'d')):
@ -45,17 +46,19 @@ class Color():
self.color = np.array(color,'d') self.color = np.array(color,'d')
# ------------------------------------------------------------------ # ------------------------------------------------------------------
def __repr__(self): def __repr__(self):
"""Color model and values"""
return 'Model: %s Color: %s'%(self.model,str(self.color)) return 'Model: %s Color: %s'%(self.model,str(self.color))
# ------------------------------------------------------------------ # ------------------------------------------------------------------
def __str__(self): def __str__(self):
"""Color model and values"""
return self.__repr__() return self.__repr__()
# ------------------------------------------------------------------ # ------------------------------------------------------------------
def convertTo(self,toModel = 'RGB'): def convertTo(self,toModel = 'RGB'):
toModel = toModel.upper() toModel = toModel.upper()
if toModel not in self.__transforms__.keys(): return if toModel not in self.__transforms__.keys(): return
@ -73,17 +76,19 @@ class Color():
return self return self
# ------------------------------------------------------------------ # ------------------------------------------------------------------
def expressAs(self,asModel = 'RGB'): def expressAs(self,asModel = 'RGB'):
return self.__class__(self.model,self.color).convertTo(asModel) return self.__class__(self.model,self.color).convertTo(asModel)
# ------------------------------------------------------------------
# convert H(ue) S(aturation) L(uminance) to R(red) G(reen) B(lue)
# with S,L,H,R,G,B running from 0 to 1
# from http://en.wikipedia.org/wiki/HSL_and_HSV
def _HSL2RGB(self):
def _HSL2RGB(self):
"""
convert H(ue) S(aturation) L(uminance) to R(red) G(reen) B(lue)
with S,L,H,R,G,B running from 0 to 1
from http://en.wikipedia.org/wiki/HSL_and_HSV
"""
if self.model != 'HSL': return if self.model != 'HSL': return
sextant = self.color[0]*6.0 sextant = self.color[0]*6.0
@ -103,12 +108,13 @@ class Color():
self.color = converted.color self.color = converted.color
# ------------------------------------------------------------------
# convert R(ed) G(reen) B(lue) to H(ue) S(aturation) L(uminance)
# with S,L,H,R,G,B running from 0 to 1
# from http://130.113.54.154/~monger/hsl-rgb.html
def _RGB2HSL(self): def _RGB2HSL(self):
"""
convert R(ed) G(reen) B(lue) to H(ue) S(aturation) L(uminance)
with S,L,H,R,G,B running from 0 to 1
from http://130.113.54.154/~monger/hsl-rgb.html
"""
if self.model != 'RGB': return if self.model != 'RGB': return
HSL = np.zeros(3,'d') HSL = np.zeros(3,'d')
@ -129,7 +135,7 @@ class Color():
HSL[0] = 2.0 + (self.color[2] - self.color[0])/(maxcolor - mincolor) HSL[0] = 2.0 + (self.color[2] - self.color[0])/(maxcolor - mincolor)
elif (maxcolor == self.color[2]): elif (maxcolor == self.color[2]):
HSL[0] = 4.0 + (self.color[0] - self.color[1])/(maxcolor - mincolor) HSL[0] = 4.0 + (self.color[0] - self.color[1])/(maxcolor - mincolor)
HSL[0] = HSL[0]*60.0 # is it necessary to scale to 360 hue values? might be dangerous for small values <1..! HSL[0] = HSL[0]*60.0 # scaling to 360 might be dangerous for small values
if (HSL[0] < 0.0): if (HSL[0] < 0.0):
HSL[0] = HSL[0] + 360.0 HSL[0] = HSL[0] + 360.0
for i in xrange(2): for i in xrange(2):
@ -141,12 +147,14 @@ class Color():
self.color = converted.color self.color = converted.color
# ------------------------------------------------------------------
# convert R(ed) G(reen) B(lue) to CIE XYZ
# with all values in the range of 0 to 1
# from http://www.cs.rit.edu/~ncs/color/t_convert.html
def _RGB2XYZ(self):
def _RGB2XYZ(self):
"""
convert R(ed) G(reen) B(lue) to CIE XYZ
with all values in the range of 0 to 1
from http://www.cs.rit.edu/~ncs/color/t_convert.html
"""
if self.model != 'RGB': return if self.model != 'RGB': return
XYZ = np.zeros(3,'d') XYZ = np.zeros(3,'d')
@ -168,12 +176,14 @@ class Color():
self.color = converted.color self.color = converted.color
# ------------------------------------------------------------------
# convert CIE XYZ to R(ed) G(reen) B(lue)
# with all values in the range of 0 to 1
# from http://www.cs.rit.edu/~ncs/color/t_convert.html
def _XYZ2RGB(self):
def _XYZ2RGB(self):
"""
convert CIE XYZ to R(ed) G(reen) B(lue)
with all values in the range of 0 to 1
from http://www.cs.rit.edu/~ncs/color/t_convert.html
"""
if self.model != 'XYZ': return if self.model != 'XYZ': return
convert = np.array([[ 3.240479,-1.537150,-0.498535], convert = np.array([[ 3.240479,-1.537150,-0.498535],
@ -197,12 +207,14 @@ class Color():
self.color = converted.color self.color = converted.color
# ------------------------------------------------------------------
# convert CIE Lab to CIE XYZ
# with XYZ in the range of 0 to 1
# from http://www.easyrgb.com/index.php?X=MATH&H=07#text7
def _CIELAB2XYZ(self):
def _CIELAB2XYZ(self):
"""
convert CIE Lab to CIE XYZ
with XYZ in the range of 0 to 1
from http://www.easyrgb.com/index.php?X=MATH&H=07#text7
"""
if self.model != 'CIELAB': return if self.model != 'CIELAB': return
ref_white = np.array([.95047, 1.00000, 1.08883],'d') # Observer = 2, Illuminant = D65 ref_white = np.array([.95047, 1.00000, 1.08883],'d') # Observer = 2, Illuminant = D65
@ -220,13 +232,13 @@ class Color():
self.model = converted.model self.model = converted.model
self.color = converted.color self.color = converted.color
# ------------------------------------------------------------------
# convert CIE XYZ to CIE Lab
# with XYZ in the range of 0 to 1
# from http://en.wikipedia.org/wiki/Lab_color_space, http://www.cs.rit.edu/~ncs/color/t_convert.html
def _XYZ2CIELAB(self): def _XYZ2CIELAB(self):
"""
convert CIE XYZ to CIE Lab
with XYZ in the range of 0 to 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 if self.model != 'XYZ': return
ref_white = np.array([.95047, 1.00000, 1.08883],'d') # Observer = 2, Illuminant = D65 ref_white = np.array([.95047, 1.00000, 1.08883],'d') # Observer = 2, Illuminant = D65
@ -243,11 +255,12 @@ class Color():
self.color = converted.color self.color = converted.color
# ------------------------------------------------------------------
# convert CIE Lab to Msh colorspace
# from http://www.cs.unm.edu/~kmorel/documents/ColorMaps/DivergingColorMapWorkshop.xls
def _CIELAB2MSH(self): 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 if self.model != 'CIELAB': return
Msh = np.zeros(3,'d') Msh = np.zeros(3,'d')
@ -262,12 +275,13 @@ class Color():
self.color = converted.color self.color = converted.color
# ------------------------------------------------------------------
# convert Msh colorspace to CIE Lab
# s,h in radians
# from http://www.cs.unm.edu/~kmorel/documents/ColorMaps/DivergingColorMapWorkshop.xls
def _MSH2CIELAB(self): def _MSH2CIELAB(self):
"""
convert Msh colorspace to CIE Lab
s,h in radians
from http://www.cs.unm.edu/~kmorel/documents/ColorMaps/DivergingColorMapWorkshop.xls
"""
if self.model != 'MSH': return if self.model != 'MSH': return
Lab = np.zeros(3,'d') Lab = np.zeros(3,'d')
@ -280,13 +294,8 @@ class Color():
self.color = converted.color self.color = converted.color
### --- COLORMAP CLASS -----------------------------------------------
class Colormap(): class Colormap():
''' """perceptually uniform diverging or sequential colormaps."""
perceptually uniform diverging or sequential colormaps.
'''
__slots__ = [ __slots__ = [
'left', 'left',
@ -294,20 +303,40 @@ class Colormap():
'interpolate', 'interpolate',
] ]
__predefined__ = { __predefined__ = {
'gray': {'left': Color('HSL',[0,1,1]), 'right': Color('HSL',[0,0,0.15]), 'interpolate': 'perceptualuniform'}, 'gray': {'left': Color('HSL',[0,1,1]),
'grey': {'left': Color('HSL',[0,1,1]), 'right': Color('HSL',[0,0,0.15]), 'interpolate': 'perceptualuniform'}, 'right': Color('HSL',[0,0,0.15]),
'red': {'left': Color('HSL',[0,1,0.14]), 'right': Color('HSL',[0,0.35,0.91]), 'interpolate': 'perceptualuniform'}, 'interpolate': 'perceptualuniform'},
'green': {'left': Color('HSL',[0.33333,1,0.14]), 'right': Color('HSL',[0.33333,0.35,0.91]), 'interpolate': 'perceptualuniform'}, 'grey': {'left': Color('HSL',[0,1,1]),
'blue': {'left': Color('HSL',[0.66,1,0.14]), 'right': Color('HSL',[0.66,0.35,0.91]), 'interpolate': 'perceptualuniform'}, 'right': Color('HSL',[0,0,0.15]),
'seaweed': {'left': Color('HSL',[0.78,1.0,0.1]), 'right': Color('HSL',[0.40000,0.1,0.9]), 'interpolate': 'perceptualuniform'}, 'interpolate': 'perceptualuniform'},
'bluebrown': {'left': Color('HSL',[0.65,0.53,0.49]), 'right': Color('HSL',[0.11,0.75,0.38]), 'interpolate': 'perceptualuniform'}, 'red': {'left': Color('HSL',[0,1,0.14]),
'redgreen': {'left': Color('HSL',[0.97,0.96,0.36]), 'right': Color('HSL',[0.33333,1.0,0.14]), 'interpolate': 'perceptualuniform'}, 'right': Color('HSL',[0,0.35,0.91]),
'bluered': {'left': Color('HSL',[0.65,0.53,0.49]), 'right': Color('HSL',[0.97,0.96,0.36]), 'interpolate': 'perceptualuniform'}, 'interpolate': 'perceptualuniform'},
'blueredrainbow':{'left': Color('HSL',[2.0/3.0,1,0.5]), 'right': Color('HSL',[0,1,0.5]), 'interpolate': 'linear' }, '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' },
} }
# ------------------------------------------------------------------ # ------------------------------------------------------------------
def __init__(self, def __init__(self,
left = Color('RGB',[1,1,1]), left = Color('RGB',[1,1,1]),
right = Color('RGB',[0,0,0]), right = Color('RGB',[0,0,0]),
@ -330,26 +359,27 @@ class Colormap():
self.interpolate = interpolate self.interpolate = interpolate
# ------------------------------------------------------------------ # ------------------------------------------------------------------
def __repr__(self): def __repr__(self):
"""left and right value of colormap"""
return 'Left: %s Right: %s'%(self.left,self.right) return 'Left: %s Right: %s'%(self.left,self.right)
# ------------------------------------------------------------------ # ------------------------------------------------------------------
def invert(self): def invert(self):
(self.left, self.right) = (self.right, self.left) (self.left, self.right) = (self.right, self.left)
return self return self
# ------------------------------------------------------------------ # ------------------------------------------------------------------
def color(self,fraction = 0.5): def color(self,fraction = 0.5):
def interpolate_Msh(lo, hi, frac): def interpolate_Msh(lo, hi, frac):
def rad_diff(a,b): def rad_diff(a,b):
return abs(a[2]-b[2]) return abs(a[2]-b[2])
# if saturation of one of the two colors is too less than the other, hue of the less
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 def adjust_hue(Msh_sat, Msh_unsat):
if Msh_sat[0] >= Msh_unsat[0]: if Msh_sat[0] >= Msh_unsat[0]:
return Msh_sat[2] return Msh_sat[2]
else: else:
@ -375,10 +405,11 @@ class Colormap():
return Color('MSH',Msh) return Color('MSH',Msh)
def interpolate_linear(lo, hi, frac): def interpolate_linear(lo, hi, frac):
''' """
linearly interpolate color at given fraction between lower and higher color in model of lower color linearly interpolate color at given fraction between lower and
'''
higher color in model of lower color
"""
interpolation = (1.0 - frac) * np.array(lo.color[:]) \ interpolation = (1.0 - frac) * np.array(lo.color[:]) \
+ frac * np.array(hi.expressAs(lo.model).color[:]) + frac * np.array(hi.expressAs(lo.model).color[:])
@ -393,21 +424,21 @@ class Colormap():
else: else:
raise NameError('unknown color interpolation method') raise NameError('unknown color interpolation method')
# ------------------------------------------------------------------ # ------------------------------------------------------------------
def export(self,name = 'uniformPerceptualColorMap',\ def export(self,name = 'uniformPerceptualColorMap',\
format = 'paraview',\ format = 'paraview',\
steps = 2,\ steps = 2,\
crop = [-1.0,1.0], crop = [-1.0,1.0],
model = 'RGB'): model = 'RGB'):
''' """
[RGB] colormap for use in paraview or gmsh, or as raw string, or array. [RGB] colormap for use in paraview or gmsh, or as raw string, or array.
arguments: name, format, steps, crop. arguments: name, format, steps, crop.
format is one of (paraview, gmsh, raw, list). format is one of (paraview, gmsh, raw, list).
crop selects a (sub)range in [-1.0,1.0]. crop selects a (sub)range in [-1.0,1.0].
generates sequential map if one limiting color is either white or black, generates sequential map if one limiting color is either white or black,
diverging map otherwise. diverging map otherwise.
''' """
format = format.lower() # consistent comparison basis format = format.lower() # consistent comparison basis
frac = 0.5*(np.array(crop) + 1.0) # rescale crop range to fractions 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]).expressAs(model).color for i in xrange(steps)] colors = [self.color(float(i)/(steps-1)*(frac[1]-frac[0])+frac[0]).expressAs(model).color for i in xrange(steps)]

View File

@ -2,7 +2,7 @@
# $Id$ # $Id$
import os,sys,string,re,subprocess,shlex import os,subprocess,shlex
class Environment(): class Environment():
__slots__ = [ \ __slots__ = [ \

View File

@ -1,5 +1,5 @@
# -*- coding: UTF-8 no BOM -*- # -*- coding: UTF-8 no BOM -*-
# $Id$ """Test functionality"""
from .test import Test from .test import Test "noqa

View File

@ -2,17 +2,19 @@
# $Id$ # $Id$
import os, sys, shlex, inspect import os,sys,shutil
import subprocess,shutil,string import logging,logging.config
import logging, logging.config
import damask import damask
import numpy as np
from collections import Iterable
from optparse import OptionParser from optparse import OptionParser
class Test(): class Test():
''' """
General class for testing. General class for testing.
Is sub-classed by the individual tests. Is sub-classed by the individual tests.
''' """
variants = [] variants = []
@ -52,9 +54,7 @@ class Test():
accept=False) accept=False)
def execute(self): def execute(self):
''' """Run all variants and report first failure."""
Run all variants and report first failure.
'''
if self.options.debug: if self.options.debug:
for variant in xrange(len(self.variants)): for variant in xrange(len(self.variants)):
try: try:
@ -84,15 +84,11 @@ class Test():
return 0 return 0
def testPossible(self): def testPossible(self):
''' """Check if test is possible or not (e.g. no license available)."""
Check if test is possible or not (e.g. no license available).
'''
return True return True
def clean(self): def clean(self):
''' """Delete directory tree containing current results."""
Delete directory tree containing current results.
'''
status = True status = True
try: try:
@ -110,103 +106,77 @@ class Test():
return status return status
def prepareAll(self): def prepareAll(self):
''' """Do all necessary preparations for the whole test"""
Do all necessary preparations for the whole test
'''
return True return True
def prepare(self,variant): def prepare(self,variant):
''' """Do all necessary preparations for the run of each test variant"""
Do all necessary preparations for the run of each test variant
'''
return True return True
def run(self,variant): def run(self,variant):
''' """Execute the requested test variant."""
Execute the requested test variant.
'''
return True return True
def postprocess(self,variant): def postprocess(self,variant):
''' """Perform post-processing of generated results for this test variant."""
Perform post-processing of generated results for this test variant.
'''
return True return True
def compare(self,variant): def compare(self,variant):
''' """Compare reference to current results."""
Compare reference to current results.
'''
return True return True
def update(self,variant): def update(self,variant):
''' """Update reference with current results."""
Update reference with current results.
'''
logging.debug('Update not necessary') logging.debug('Update not necessary')
return True return True
def dirReference(self): def dirReference(self):
''' """Directory containing reference results of the test."""
Directory containing reference results of the test.
'''
return os.path.normpath(os.path.join(self.dirBase,'reference/')) return os.path.normpath(os.path.join(self.dirBase,'reference/'))
def dirCurrent(self): def dirCurrent(self):
''' """Directory containing current results of the test."""
Directory containing current results of the test.
'''
return os.path.normpath(os.path.join(self.dirBase,'current/')) return os.path.normpath(os.path.join(self.dirBase,'current/'))
def dirProof(self): def dirProof(self):
''' """Directory containing human readable proof of correctness for the test."""
Directory containing human readable proof of correctness for the test.
'''
return os.path.normpath(os.path.join(self.dirBase,'proof/')) return os.path.normpath(os.path.join(self.dirBase,'proof/'))
def fileInRoot(self,dir,file): def fileInRoot(self,dir,file):
''' """Path to a file in the root directory of DAMASK."""
Path to a file in the root directory of DAMASK.
'''
return os.path.join(damask.Environment().rootDir(),dir,file) return os.path.join(damask.Environment().rootDir(),dir,file)
def fileInReference(self,file): def fileInReference(self,file):
''' """Path to a file in the refrence directory for the test."""
Path to a file in the refrence directory for the test.
'''
return os.path.join(self.dirReference(),file) return os.path.join(self.dirReference(),file)
def fileInCurrent(self,file): def fileInCurrent(self,file):
''' """Path to a file in the current results directory for the test."""
Path to a file in the current results directory for the test.
'''
return os.path.join(self.dirCurrent(),file) return os.path.join(self.dirCurrent(),file)
def fileInProof(self,file): def fileInProof(self,file):
''' """Path to a file in the proof directory for the test."""
Path to a file in the proof directory for the test.
'''
return os.path.join(self.dirProof(),file) return os.path.join(self.dirProof(),file)
def copy(self, mapA, mapB, def copy(self, mapA, mapB,
A = [], B = []): A = [], B = []):
''' """
copy list of files from (mapped) source to target. copy list of files from (mapped) source to target.
mapA/B is one of self.fileInX.
'''
mapA/B is one of self.fileInX.
"""
if not B or len(B) == 0: B = A if not B or len(B) == 0: B = A
for source,target in zip(map(mapA,A),map(mapB,B)): for source,target in zip(map(mapA,A),map(mapB,B)):
@ -328,7 +298,8 @@ class Test():
logging.info('comparing ASCII Tables\n %s \n %s'%(file0,file1)) logging.info('comparing ASCII Tables\n %s \n %s'%(file0,file1))
if normHeadings == '': normHeadings = headings0 if normHeadings == '': normHeadings = headings0
if len(headings0) == len(headings1) == len(normHeadings): #check if comparison is possible and determine lenght of columns # check if comparison is possible and determine lenght of columns
if len(headings0) == len(headings1) == len(normHeadings):
dataLength = len(headings0) dataLength = len(headings0)
length = [1 for i in xrange(dataLength)] length = [1 for i in xrange(dataLength)]
shape = [[] for i in xrange(dataLength)] shape = [[] for i in xrange(dataLength)]
@ -431,15 +402,11 @@ class Test():
meanTol = 1.0e-4, meanTol = 1.0e-4,
stdTol = 1.0e-6, stdTol = 1.0e-6,
preFilter = 1.0e-9): preFilter = 1.0e-9):
"""
'''
calculate statistics of tables calculate statistics of tables
threshold can be used to ignore small values (a negative number disables this feature) threshold can be used to ignore small values (a negative number disables this feature)
''' """
import numpy as np
from collections import Iterable
if not (isinstance(files, Iterable) and not isinstance(files, str)): # check whether list of files is requested if not (isinstance(files, Iterable) and not isinstance(files, str)): # check whether list of files is requested
files = [str(files)] files = [str(files)]
@ -491,15 +458,11 @@ class Test():
preFilter = -1.0, preFilter = -1.0,
postFilter = -1.0, postFilter = -1.0,
debug = False): debug = False):
"""
'''
compare tables with np.allclose compare tables with np.allclose
threshold can be used to ignore small values (a negative number disables this feature) threshold can be used to ignore small values (a negative number disables this feature)
''' """
import numpy as np
from collections import Iterable
if not (isinstance(files, Iterable) and not isinstance(files, str)): # check whether list of files is requested if not (isinstance(files, Iterable) and not isinstance(files, str)): # check whether list of files is requested
files = [str(files)] files = [str(files)]