From a4bbdd5ecb3a118b36c1d8ae88442b948d8bdafc Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 4 Mar 2016 18:50:13 +0100 Subject: [PATCH] further commenting, removing not used variables and code (marc2vtk) --- lib/damask/__init__.py | 22 ++--- lib/damask/asciitable.py | 128 +++++++++++----------------- lib/damask/config/__init__.py | 2 +- lib/damask/config/material.py | 3 +- lib/damask/orientation.py | 148 ++++++++++++++++++-------------- lib/damask/result.py | 9 +- lib/damask/result/marc2vtk.py | 153 ++++++++++------------------------ lib/damask/test/__init__.py | 2 +- 8 files changed, 194 insertions(+), 273 deletions(-) diff --git a/lib/damask/__init__.py b/lib/damask/__init__.py index 6b980b750..1b6ec409d 100644 --- a/lib/damask/__init__.py +++ b/lib/damask/__init__.py @@ -1,27 +1,27 @@ # -*- coding: UTF-8 no BOM -*- -# $Id$ +"""Main aggregator""" import sys, os with open(os.path.join(os.path.dirname(__file__),'../../VERSION')) as f: version = f.readline()[:-1] -from .environment import Environment # only one class -from .asciitable import ASCIItable # only one class -from .config import Material # will be extended to debug and numerics -from .colormaps import Colormap, Color -from .orientation import Quaternion, Rodrigues, Symmetry, Orientation +from .environment import Environment # noqa +from .asciitable import ASCIItable # noqa +from .config import Material # noqa +from .colormaps import Colormap, Color # noqa +from .orientation import Quaternion, Rodrigues, Symmetry, Orientation # noqa # try: # from .corientation import Quaternion, Rodrigues, Symmetry, Orientation # print "Import Cython version of Orientation module" # except: # from .orientation import Quaternion, Rodrigues, Symmetry, Orientation #from .block import Block # only one class -from .result import Result # only one class -from .geometry import Geometry # one class with subclasses -from .solver import Solver # one class with subclasses -from .test import Test -from .util import extendableOption +from .result import Result # noqa +from .geometry import Geometry # noqa +from .solver import Solver # noqa +from .test import Test # noqa +from .util import extendableOption # noqa try: from . import core diff --git a/lib/damask/asciitable.py b/lib/damask/asciitable.py index 448c790ef..4abe4297d 100644 --- a/lib/damask/asciitable.py +++ b/lib/damask/asciitable.py @@ -4,12 +4,9 @@ import os,sys import numpy as np -import util class ASCIItable(): - ''' - There should be a doc string here :) - ''' + """Read and write to ASCII tables""" __slots__ = ['__IO__', 'info', @@ -58,8 +55,8 @@ class ASCIItable(): self.data = [] self.line = '' - if self.__IO__['in'] == None \ - or self.__IO__['out'] == None: raise IOError # complain if any required file access not possible + if self.__IO__['in'] is None \ + or self.__IO__['out'] is None: raise IOError # complain if any required file access not possible # ------------------------------------------------------------------ def _transliterateToFloat(self, @@ -86,9 +83,7 @@ class ASCIItable(): # ------------------------------------------------------------------ def output_write(self, what): - ''' - aggregate a single row (string) or list of (possibly containing further lists of) rows into output - ''' + """aggregate a single row (string) or list of (possibly containing further lists of) rows into output""" if not isinstance(what, (str, unicode)): try: for item in what: self.output_write(item) @@ -104,7 +99,7 @@ class ASCIItable(): clear = True): try: self.__IO__['output'] == [] or self.__IO__['out'].write('\n'.join(self.__IO__['output']) + '\n') - except IOError as e: + except IOError: return False if clear: self.output_clear() return True @@ -127,11 +122,12 @@ class ASCIItable(): # ------------------------------------------------------------------ def head_read(self): - ''' - get column labels by either reading - the first row or, if keyword "head[*]" is present, - the last line of the header - ''' + """ + get column labels by either reading + + the first row or, if keyword "head[*]" is present, + the last line of the header + """ import re try: @@ -180,10 +176,7 @@ class ASCIItable(): # ------------------------------------------------------------------ def head_write(self, header = True): - ''' - write current header information (info + labels) - ''' - + """write current header information (info + labels)""" head = ['{}\theader'.format(len(self.info)+self.__IO__['labeled'])] if header else [] head.append(self.info) if self.__IO__['labeled']: head.append('\t'.join(self.labels)) @@ -192,9 +185,7 @@ class ASCIItable(): # ------------------------------------------------------------------ def head_getGeom(self): - ''' - interpret geom header - ''' + """interpret geom header""" identifiers = { 'grid': ['a','b','c'], 'size': ['x','y','z'], @@ -234,9 +225,7 @@ class ASCIItable(): # ------------------------------------------------------------------ def head_putGeom(self,info): - ''' - translate geometry description to header - ''' + """translate geometry description to header""" self.info_append([ "grid\ta {}\tb {}\tc {}".format(*info['grid']), "size\tx {}\ty {}\tz {}".format(*info['size']), @@ -249,9 +238,7 @@ class ASCIItable(): def labels_append(self, what, reset = False): - ''' - add item or list to existing set of labels (and switch on labeling) - ''' + """add item or list to existing set of labels (and switch on labeling)""" if not isinstance(what, (str, unicode)): try: for item in what: self.labels_append(item) @@ -265,26 +252,25 @@ class ASCIItable(): # ------------------------------------------------------------------ def labels_clear(self): - ''' - delete existing labels and switch to no labeling - ''' + """delete existing labels and switch to no labeling""" self.labels = [] self.__IO__['labeled'] = False # ------------------------------------------------------------------ def label_index(self, labels): - ''' - tell index of column label(s). - return numpy array if asked for list of labels. - transparently deals with label positions implicitly given as numbers or their headings given as strings. - ''' + """ + tell index of column label(s). + + return numpy array if asked for list of labels. + transparently deals with label positions implicitly given as numbers or their headings given as strings. + """ from collections import Iterable if isinstance(labels, Iterable) and not isinstance(labels, str): # check whether list of labels is requested idx = [] for label in labels: - if label != None: + if label is not None: try: idx.append(int(label)) # column given as integer number? except ValueError: @@ -305,25 +291,25 @@ class ASCIItable(): try: idx = self.labels.index('1_'+labels) # locate '1_'+string in label list except ValueError: - idx = None if labels == None else -1 + idx = None if labels is None else -1 return np.array(idx) if isinstance(idx,list) else idx # ------------------------------------------------------------------ def label_dimension(self, labels): - ''' - tell dimension (length) of column label(s). - return numpy array if asked for list of labels. - transparently deals with label positions implicitly given as numbers or their headings given as strings. - ''' + """ + tell dimension (length) of column label(s). + return numpy array if asked for list of labels. + transparently deals with label positions implicitly given as numbers or their headings given as strings. + """ from collections import Iterable if isinstance(labels, Iterable) and not isinstance(labels, str): # check whether list of labels is requested dim = [] for label in labels: - if label != None: + if label is not None: myDim = -1 try: # column given as number? idx = int(label) @@ -364,12 +350,12 @@ class ASCIItable(): # ------------------------------------------------------------------ def label_indexrange(self, labels): - ''' - tell index range for given label(s). - return numpy array if asked for list of labels. - transparently deals with label positions implicitly given as numbers or their headings given as strings. - ''' + """ + tell index range for given label(s). + return numpy array if asked for list of labels. + transparently deals with label positions implicitly given as numbers or their headings given as strings. + """ from collections import Iterable start = self.label_index(labels) @@ -381,9 +367,7 @@ class ASCIItable(): # ------------------------------------------------------------------ def info_append(self, what): - ''' - add item or list to existing set of infos - ''' + """add item or list to existing set of infos""" if not isinstance(what, (str, unicode)): try: for item in what: self.info_append(item) @@ -394,9 +378,7 @@ class ASCIItable(): # ------------------------------------------------------------------ def info_clear(self): - ''' - delete any info block - ''' + """delete any info block""" self.info = [] # ------------------------------------------------------------------ @@ -409,9 +391,7 @@ class ASCIItable(): # ------------------------------------------------------------------ def data_skipLines(self, count): - ''' - wind forward by count number of lines - ''' + """wind forward by count number of lines""" for i in xrange(count): alive = self.data_read() @@ -421,9 +401,7 @@ class ASCIItable(): def data_read(self, advance = True, respectLabels = True): - ''' - read next line (possibly buffered) and parse it into data array - ''' + """read next line (possibly buffered) and parse it into data array""" self.line = self.__IO__['readBuffer'].pop(0) if len(self.__IO__['readBuffer']) > 0 \ else self.__IO__['in'].readline().strip() # take buffered content or get next data row from file @@ -434,7 +412,7 @@ class ASCIItable(): if self.__IO__['labeled'] and respectLabels: # if table has labels items = self.line.split()[:len(self.__IO__['labels'])] # use up to label count (from original file info) - self.data = items if len(items) == len(self.__IO__['labels']) else [] # take entries if correct number, i.e. not too few compared to label count + self.data = items if len(items) == len(self.__IO__['labels']) else [] # take entries if label count matches else: self.data = self.line.split() # otherwise take all @@ -443,9 +421,7 @@ class ASCIItable(): # ------------------------------------------------------------------ def data_readArray(self, labels = []): - ''' - read whole data of all (given) labels as numpy array - ''' + """read whole data of all (given) labels as numpy array""" from collections import Iterable try: @@ -453,7 +429,7 @@ class ASCIItable(): except: pass # assume/hope we are at data start already... - if labels == None or labels == []: + if labels is None or labels == []: use = None # use all columns (and keep labels intact) labels_missing = [] else: @@ -467,9 +443,10 @@ class ASCIItable(): columns = [] for i,(c,d) in enumerate(zip(indices[present],dimensions[present])): # for all valid labels ... + # ... transparently add all components unless column referenced by number or with explicit dimension columns += range(c,c + \ (d if str(c) != str(labels[present[i]]) else \ - 1)) # ... transparently add all components unless column referenced by number or with explicit dimension + 1)) use = np.array(columns) self.labels = list(np.array(self.labels)[use]) # update labels with valid subset @@ -481,9 +458,7 @@ class ASCIItable(): # ------------------------------------------------------------------ def data_write(self, delimiter = '\t'): - ''' - write current data array and report alive output back - ''' + """write current data array and report alive output back""" if len(self.data) == 0: return True if isinstance(self.data[0],list): @@ -495,9 +470,7 @@ class ASCIItable(): def data_writeArray(self, fmt = None, delimiter = '\t'): - ''' - write whole numpy array data - ''' + """write whole numpy array data""" for row in self.data: try: output = [fmt % value for value in row] if fmt else map(repr,row) @@ -520,9 +493,7 @@ class ASCIItable(): # ------------------------------------------------------------------ def data_set(self, what, where): - ''' - update data entry in column "where". grows data array if needed. - ''' + """update data entry in column "where". grows data array if needed.""" idx = -1 try: idx = self.label_index(where) @@ -547,10 +518,7 @@ class ASCIItable(): # ------------------------------------------------------------------ def microstructure_read(self, grid): - ''' - read microstructure data (from .geom format) - ''' - + """read microstructure data (from .geom format)""" N = grid.prod() # expected number of microstructure indices in data microstructure = np.zeros(N,'i') # initialize as flat array diff --git a/lib/damask/config/__init__.py b/lib/damask/config/__init__.py index ba31241d0..f3635d2a9 100644 --- a/lib/damask/config/__init__.py +++ b/lib/damask/config/__init__.py @@ -2,4 +2,4 @@ """Aggregator for configuration file handling""" -from .material import Material #noqa +from .material import Material # noqa diff --git a/lib/damask/config/material.py b/lib/damask/config/material.py index 4c228e312..bca005e0e 100644 --- a/lib/damask/config/material.py +++ b/lib/damask/config/material.py @@ -243,7 +243,8 @@ class Material(): except AttributeError: pass - for (phase,texture,fraction,crystallite) in zip(components['phase'],components['texture'],components['fraction'],components['crystallite']): + for (phase,texture,fraction,crystallite) in zip(components['phase'],components['texture'], + components['fraction'],components['crystallite']): microstructure.add_multiKey('constituent','phase %i\ttexture %i\tfraction %g\ncrystallite %i'%( self.data['phase']['__order__'].index(phase)+1, self.data['texture']['__order__'].index(texture)+1, diff --git a/lib/damask/orientation.py b/lib/damask/orientation.py index c3f54dffa..886cd5a36 100644 --- a/lib/damask/orientation.py +++ b/lib/damask/orientation.py @@ -9,7 +9,6 @@ import numpy as np # ****************************************************************************************** class Rodrigues: -# ****************************************************************************************** def __init__(self, vector = np.zeros(3)): self.vector = vector @@ -28,20 +27,22 @@ class Rodrigues: # ****************************************************************************************** class Quaternion: -# ****************************************************************************************** - # All methods and naming conventions based off - # http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions + """ + Orientation represented as unit quaternion + + All methods and naming conventions based on http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions - # w is the real part, (x, y, z) are the imaginary parts - - # Representation of rotation is in ACTIVE form! - # (derived directly or through angleAxis, Euler angles, or active matrix) - # vector "a" (defined in coordinate system "A") is actively rotated to new coordinates "b" - # b = Q * a - # b = np.dot(Q.asMatrix(),a) + w is the real part, (x, y, z) are the imaginary parts + Representation of rotation is in ACTIVE form! + (derived directly or through angleAxis, Euler angles, or active matrix) + vector "a" (defined in coordinate system "A") is actively rotated to new coordinates "b" + b = Q * a + b = np.dot(Q.asMatrix(),a) + """ def __init__(self, quatArray = [1.0,0.0,0.0,0.0]): + """initializes to identity if not given""" self.w, \ self.x, \ self.y, \ @@ -49,19 +50,23 @@ class Quaternion: self.homomorph() def __iter__(self): + """components""" return iter([self.w,self.x,self.y,self.z]) def __copy__(self): + """create copy""" Q = Quaternion([self.w,self.x,self.y,self.z]) return Q copy = __copy__ def __repr__(self): + """readbable string""" return 'Quaternion(real=%+.6f, imag=<%+.6f, %+.6f, %+.6f>)' % \ (self.w, self.x, self.y, self.z) def __pow__(self, exponent): + """power""" omega = math.acos(self.w) vRescale = math.sin(exponent*omega)/math.sin(omega) Q = Quaternion() @@ -72,6 +77,7 @@ class Quaternion: return Q def __ipow__(self, exponent): + """in place power""" omega = math.acos(self.w) vRescale = math.sin(exponent*omega)/math.sin(omega) self.w = np.cos(exponent*omega) @@ -81,6 +87,7 @@ class Quaternion: return self def __mul__(self, other): + """multiplication""" try: # quaternion Aw = self.w Ax = self.x @@ -128,6 +135,7 @@ class Quaternion: return self.copy() def __imul__(self, other): + """in place multiplication""" try: # Quaternion Ax = self.x Ay = self.y @@ -145,6 +153,7 @@ class Quaternion: return self def __div__(self, other): + """division""" if isinstance(other, (int,float,long)): w = self.w / other x = self.x / other @@ -155,6 +164,7 @@ class Quaternion: return NotImplemented def __idiv__(self, other): + """in place division""" if isinstance(other, (int,float,long)): self.w /= other self.x /= other @@ -163,6 +173,7 @@ class Quaternion: return self def __add__(self, other): + """addition""" if isinstance(other, Quaternion): w = self.w + other.w x = self.x + other.x @@ -173,6 +184,7 @@ class Quaternion: return NotImplemented def __iadd__(self, other): + """in place division""" if isinstance(other, Quaternion): self.w += other.w self.x += other.x @@ -181,6 +193,7 @@ class Quaternion: return self def __sub__(self, other): + """subtraction""" if isinstance(other, Quaternion): Q = self.copy() Q.w -= other.w @@ -192,6 +205,7 @@ class Quaternion: return self.copy() def __isub__(self, other): + """in place subtraction""" if isinstance(other, Quaternion): self.w -= other.w self.x -= other.x @@ -200,6 +214,7 @@ class Quaternion: return self def __neg__(self): + """additive inverse""" self.w = -self.w self.x = -self.x self.y = -self.y @@ -207,6 +222,7 @@ class Quaternion: return self def __abs__(self): + """norm""" return math.sqrt(self.w ** 2 + \ self.x ** 2 + \ self.y ** 2 + \ @@ -215,6 +231,7 @@ class Quaternion: magnitude = __abs__ def __eq__(self,other): + """equal at e-8 precision""" return (abs(self.w-other.w) < 1e-8 and \ abs(self.x-other.x) < 1e-8 and \ abs(self.y-other.y) < 1e-8 and \ @@ -226,9 +243,11 @@ class Quaternion: abs(-self.z-other.z) < 1e-8) def __ne__(self,other): + """not equal at e-8 precision""" return not self.__eq__(self,other) def __cmp__(self,other): + """linear ordering""" return cmp(self.Rodrigues(),other.Rodrigues()) def magnitude_squared(self): @@ -290,9 +309,10 @@ class Quaternion: return np.outer([i for i in self],[i for i in self]) def asMatrix(self): - return np.array([[1.0-2.0*(self.y*self.y+self.z*self.z), 2.0*(self.x*self.y-self.z*self.w), 2.0*(self.x*self.z+self.y*self.w)], - [ 2.0*(self.x*self.y+self.z*self.w), 1.0-2.0*(self.x*self.x+self.z*self.z), 2.0*(self.y*self.z-self.x*self.w)], - [ 2.0*(self.x*self.z-self.y*self.w), 2.0*(self.x*self.w+self.y*self.z), 1.0-2.0*(self.x*self.x+self.y*self.y)]]) + return np.array( + [[1.0-2.0*(self.y*self.y+self.z*self.z), 2.0*(self.x*self.y-self.z*self.w), 2.0*(self.x*self.z+self.y*self.w)], + [ 2.0*(self.x*self.y+self.z*self.w), 1.0-2.0*(self.x*self.x+self.z*self.z), 2.0*(self.y*self.z-self.x*self.w)], + [ 2.0*(self.x*self.z-self.y*self.w), 2.0*(self.x*self.w+self.y*self.z), 1.0-2.0*(self.x*self.x+self.y*self.y)]]) def asAngleAxis(self, degrees = False): @@ -315,15 +335,17 @@ class Quaternion: return np.inf*np.ones(3) if self.w == 0.0 else np.array([self.x, self.y, self.z])/self.w def asEulers(self, - type = 'bunge', + type = "bunge", degrees = False, standardRange = False): - ''' + u""" + Orientation as Bunge-Euler angles + conversion of ACTIVE rotation to Euler angles taken from: Melcher, A.; Unser, A.; Reichhardt, M.; Nestler, B.; Pötschke, M.; Selzer, M. Conversion of EBSD data by a quaternion based algorithm to be used for grain structure simulations Technische Mechanik 30 (2010) pp 401--413 - ''' + """ angles = [0.0,0.0,0.0] if type.lower() == 'bunge' or type.lower() == 'zxz': @@ -369,7 +391,7 @@ class Quaternion: @classmethod def fromRandom(cls,randomSeed = None): - if randomSeed == None: + if randomSeed is None: randomSeed = int(os.urandom(4).encode('hex'), 16) np.random.seed(randomSeed) r = np.random.random(3) @@ -420,7 +442,6 @@ class Quaternion: y = - c1 * s2 * s3 + s1 * s2 * c3 z = c1 * c2 * s3 + s1 * c2 * c3 else: -# print 'unknown Euler convention' w = c1 * c2 * c3 - s1 * s2 * s3 x = s1 * s2 * c3 + c1 * c2 * s3 y = s1 * c2 * c3 + c1 * s2 * s3 @@ -428,7 +449,8 @@ class Quaternion: return cls([w,x,y,z]) -## Modified Method to calculate Quaternion from Orientation Matrix, Source: http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/ +# Modified Method to calculate Quaternion from Orientation Matrix, +# Source: http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/ @classmethod def fromMatrix(cls, m): @@ -482,8 +504,12 @@ class Quaternion: @classmethod def new_interpolate(cls, q1, q2, t): -# see http://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/20070017872_2007014421.pdf for (another?) way to interpolate quaternions - + """ + interpolation + + see http://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/20070017872_2007014421.pdf + for (another?) way to interpolate quaternions + """ assert isinstance(q1, Quaternion) and isinstance(q2, Quaternion) Q = cls() @@ -522,11 +548,11 @@ class Quaternion: # ****************************************************************************************** class Symmetry: -# ****************************************************************************************** lattices = [None,'orthorhombic','tetragonal','hexagonal','cubic',] def __init__(self, symmetry = None): + """lattice with given symmetry, defaults to None""" if isinstance(symmetry, basestring) and symmetry.lower() in Symmetry.lattices: self.lattice = symmetry.lower() else: @@ -534,29 +560,31 @@ class Symmetry: def __copy__(self): + """copy""" return self.__class__(self.lattice) copy = __copy__ def __repr__(self): + """readbable string""" return '%s' % (self.lattice) def __eq__(self, other): + """equal""" return self.lattice == other.lattice - def __neq__(self, other): + """not equal""" return not self.__eq__(other) def __cmp__(self,other): + """linear ordering""" return cmp(Symmetry.lattices.index(self.lattice),Symmetry.lattices.index(other.lattice)) def symmetryQuats(self,who = []): - ''' - List of symmetry operations as quaternions. - ''' + """List of symmetry operations as quaternions.""" if self.lattice == 'cubic': symQuats = [ [ 1.0, 0.0, 0.0, 0.0 ], @@ -629,18 +657,15 @@ class Symmetry: def equivalentQuaternions(self, quaternion, who = []): - ''' - List of symmetrically equivalent quaternions based on own symmetry. - ''' + """List of symmetrically equivalent quaternions based on own symmetry.""" return [quaternion*q for q in self.symmetryQuats(who)] def inFZ(self,R): - ''' - Check whether given Rodrigues vector falls into fundamental zone of own symmetry. - ''' + """Check whether given Rodrigues vector falls into fundamental zone of own symmetry.""" if isinstance(R, Quaternion): R = R.asRodrigues() # translate accidentially passed quaternion - R = abs(R) # fundamental zone in Rodrigues space is point symmetric around origin +# fundamental zone in Rodrigues space is point symmetric around origin + R = abs(R) if self.lattice == 'cubic': return math.sqrt(2.0)-1.0 >= R[0] \ and math.sqrt(2.0)-1.0 >= R[1] \ @@ -662,12 +687,13 @@ class Symmetry: def inDisorientationSST(self,R): - ''' + """ Check whether given Rodrigues vector (of misorientation) falls into standard stereographic triangle of own symmetry. + Determination of disorientations follow the work of A. Heinz and P. Neumann: Representation of Orientation and Disorientation Data for Cubic, Hexagonal, Tetragonal and Orthorhombic Crystals Acta Cryst. (1991). A47, 780-789 - ''' + """ if isinstance(R, Quaternion): R = R.asRodrigues() # translate accidentially passed quaternion epsilon = 0.0 @@ -691,11 +717,12 @@ class Symmetry: vector, proper = False, color = False): - ''' + """ Check whether given vector falls into standard stereographic triangle of own symmetry. + proper considers only vectors with z >= 0, hence uses two neighboring SSTs. Return inverse pole figure color if requested. - ''' + """ # basis = {'cubic' : np.linalg.inv(np.array([[0.,0.,1.], # direction of red # [1.,0.,1.]/np.sqrt(2.), # direction of green # [1.,1.,1.]/np.sqrt(3.)]).transpose()), # direction of blue @@ -752,15 +779,15 @@ class Symmetry: inSST = np.all(theComponents >= 0.0) else: v = np.array(vector,dtype = float) - if proper: # check both improper ... + if proper: # check both improper ... theComponents = np.dot(basis['improper'],v) inSST = np.all(theComponents >= 0.0) if not inSST: # ... and proper SST theComponents = np.dot(basis['proper'],v) inSST = np.all(theComponents >= 0.0) else: - v[2] = abs(v[2]) # z component projects identical for positive and negative values - theComponents = np.dot(basis['improper'],v) + v[2] = abs(v[2]) # z component projects identical + theComponents = np.dot(basis['improper'],v) # for positive and negative values inSST = np.all(theComponents >= 0.0) if color: # have to return color array @@ -781,7 +808,6 @@ class Symmetry: # ****************************************************************************************** class Orientation: -# ****************************************************************************************** __slots__ = ['quaternion','symmetry'] @@ -791,7 +817,7 @@ class Orientation: angleAxis = None, matrix = None, Eulers = None, - random = False, # put any integer to have a fixed seed or True for real random + random = False, # integer to have a fixed seed or True for real random symmetry = None, ): if random: # produce random orientation @@ -815,12 +841,14 @@ class Orientation: self.symmetry = Symmetry(symmetry) def __copy__(self): + """copy""" return self.__class__(quaternion=self.quaternion,symmetry=self.symmetry.lattice) copy = __copy__ def __repr__(self): + """value as all implemented representations""" return 'Symmetry: %s\n' % (self.symmetry) + \ 'Quaternion: %s\n' % (self.quaternion) + \ 'Matrix:\n%s\n' % ( '\n'.join(['\t'.join(map(str,self.asMatrix()[i,:])) for i in range(3)]) ) + \ @@ -863,10 +891,7 @@ class Orientation: self.equivalentQuaternions(who)) def reduced(self): - ''' - Transform orientation to fall into fundamental zone according to symmetry - ''' - + """Transform orientation to fall into fundamental zone according to symmetry""" for me in self.symmetry.equivalentQuaternions(self.quaternion): if self.symmetry.inFZ(me.asRodrigues()): break @@ -876,13 +901,13 @@ class Orientation: def disorientation(self, other, SST = True): - ''' + """ Disorientation between myself and given other orientation. + Rotation axis falls into SST if SST == True. (Currently requires same symmetry for both orientations. Look into A. Heinz and P. Neumann 1991 for cases with differing sym.) - ''' - + """ if self.symmetry != other.symmetry: raise TypeError('disorientation between different symmetry classes not supported yet.') misQ = self.quaternion.conjugated()*other.quaternion @@ -900,32 +925,27 @@ class Orientation: if breaker: break if breaker: break +# disorientation, own sym, other sym, self-->other: True, self<--other: False return (Orientation(quaternion = theQ,symmetry = self.symmetry.lattice), - i,j,k == 1) # disorientation, own sym, other sym, self-->other: True, self<--other: False + i,j,k == 1) def inversePole(self, axis, proper = False, SST = True): - ''' - axis rotated according to orientation (using crystal symmetry to ensure location falls into SST) - ''' - + """axis rotated according to orientation (using crystal symmetry to ensure location falls into SST)""" if SST: # pole requested to be within SST for i,q in enumerate(self.symmetry.equivalentQuaternions(self.quaternion)): # test all symmetric equivalent quaternions pole = q.conjugated()*axis # align crystal direction to axis - if self.symmetry.inSST(pole,proper): break # found SST version + if self.symmetry.inSST(pole,proper): break # found SST version else: pole = self.quaternion.conjugated()*axis # align crystal direction to axis return (pole,i if SST else 0) def IPFcolor(self,axis): - ''' - TSL color of inverse pole figure for given axis - ''' - + """TSL color of inverse pole figure for given axis""" color = np.zeros(3,'d') for q in self.symmetry.equivalentQuaternions(self.quaternion): @@ -939,7 +959,9 @@ class Orientation: def average(cls, orientations, multiplicity = []): - """RETURN THE AVERAGE ORIENTATION + """ + average orientation + ref: F. Landis Markley, Yang Cheng, John Lucas Crassidis, and Yaakov Oshman. Averaging Quaternions, Journal of Guidance, Control, and Dynamics, Vol. 30, No. 4 (2007), pp. 1193-1197. @@ -949,7 +971,6 @@ class Orientation: b = Orientation(Eulers=np.radians([20, 0, 0]), symmetry='hexagonal') avg = Orientation.average([a,b]) """ - if not all(isinstance(item, Orientation) for item in orientations): raise TypeError("Only instances of Orientation can be averaged.") @@ -960,8 +981,7 @@ class Orientation: reference = orientations[0] # take first as reference for i,(o,n) in enumerate(zip(orientations,multiplicity)): closest = o.equivalentOrientations(reference.disorientation(o,SST = False)[2])[0] # select sym orientation with lowest misorientation - M = closest.quaternion.asM() * n if i == 0 else M + closest.quaternion.asM() * n # add (multiples) of this orientation to average - + M = closest.quaternion.asM() * n if i == 0 else M + closest.quaternion.asM() * n # noqa add (multiples) of this orientation to average noqa eig, vec = np.linalg.eig(M/N) return Orientation(quaternion = Quaternion(quatArray = np.real(vec.T[eig.argmax()])), diff --git a/lib/damask/result.py b/lib/damask/result.py index e65fa2afe..36e4ba81b 100644 --- a/lib/damask/result.py +++ b/lib/damask/result.py @@ -11,10 +11,11 @@ except (ImportError) as e: sys.stderr.write('\nREMARK: h5py module not available \n\n') class Result(): - ''' - General class for result parsing. - Needs h5py to be installed - ''' + """ + General class for result parsing. + + Needs h5py to be installed + """ def __init__(self,resultsFile): self.data=h5py.File(resultsFile,"r") diff --git a/lib/damask/result/marc2vtk.py b/lib/damask/result/marc2vtk.py index 84c2a6313..a04c710d7 100644 --- a/lib/damask/result/marc2vtk.py +++ b/lib/damask/result/marc2vtk.py @@ -1,6 +1,5 @@ # -*- coding: UTF-8 no BOM -*- -# $Id$ # This tool converts a msc.marc result file into the vtk format that # can be viewed by Paraview software (Kitware), or MayaVi (needs xml-vtk, or ... # @@ -8,13 +7,8 @@ # Some example vtk files: http://people.sc.fsu.edu/~jburkardt/data/vtk/vtk.html # www.paraview.org -import os,sys,math,time,re -# python external -try: - import numpy as N - import numpy -except: - print('Could not import numpy.') +import os,sys,re +import numpy as np import py_post # MSC closed source module to access marc result files @@ -27,7 +21,7 @@ class MARC_POST(): self.fpath=os.path.join(self.projdir,self.postname) print('Trying to open ',self.fpath,' ...') self.p=py_post.post_open(self.fpath) - if self.p==None: + if self.p is None: print('Could not open %s.'%self.postname); #return 'err'#; sys.exit(1) raise Exception('Could not open t16') print('Postfile %s%s is open ...'%(self.projdir,self.postname)) @@ -105,7 +99,6 @@ class MARC_POST(): def writeNodes2VTK(self, fobj): self.points=[] self.VTKcnt=200 # number of values per line in vtk file - ndCnt=1 fobj.write('POINTS %i'%self.p.nodes()+' float\n') self.nodes_dict={} # store the node IDs in case of holes in the numbering for iNd in self.nodes: @@ -126,8 +119,6 @@ class MARC_POST(): el=self.p.element(iEl) cell_nodes=[] # for pyvtk ndlist=el.items - #for k in [0, 1, 3, 2, 4, 5, 7, 6]: # FOR CELL TPYE VTK_VOXEL - #for k in [0, 4, 3, 1, 5, 7, 6, 2]: for k in [0, 1, 2, 3, 4, 5, 6, 7]: # FOR CELL TYPE VTK_HEXAHEDRON node=ndlist[k]-1 cell_nodes.append(self.nodes_dict[node]) @@ -147,7 +138,6 @@ class MARC_POST(): fobj.write('\n');cnt=0 fobj.write('\n') print('Elements written to VTK: %i'%self.p.elements()) - #print('Nr of nodes: ',self.nodes) def writeElScalars2NodesVTK(self,fobj): fobj.write('\nPOINT_DATA %i\n'%self.p.nodes()) @@ -157,7 +147,6 @@ class MARC_POST(): fobj.write('LOOKUP_TABLE default\n') idxScal=self.nscal_list.index('Displacement Z') for iNd in self.nodes: - #fobj.write('%f %f '%(self.p.node_scalar(iNd,idxScal), N.random.rand())) fobj.write('%f '%(self.p.node_scalar(iNd,idxScal))) for iEl in range(0,self.nel): el=self.p.element(iEl) @@ -173,8 +162,6 @@ class MARC_POST(): def writeNodeScalars2VTK(self,fobj): fobj.write('\nPOINT_DATA %i\n'%self.p.nodes()) - nNdDat=self.nscals - nComponents=1+nNdDat self.pointDataScalars=[] for idxNdScal in range(-3,self.nscals): #now include node x,y,z if idxNdScal>=0: @@ -209,8 +196,6 @@ class MARC_POST(): idx_sig_vMises=self.getLabelNr('Equivalent Von Mises Stress') idx_sig33=self.getLabelNr('Comp 33 of Cauchy Stress') fobj.write('\nCELL_DATA %i\n'%self.p.elements()) - nElDat=self.elscals - nComponents=1+nElDat for idxElScal in range(0,self.elscals): datalabel=self.elscal_list[idxElScal] datalabel=re.sub("\s",'_',datalabel) @@ -250,19 +235,16 @@ class MARC_POST(): result.append(avgScal) return result - def writeUniaxiality2VTK(self,fobj): - #fobj.write('\nCELL_DATA %i\n'%self.p.elements()) + def writeUniaxiality2VTK(self,fobj): datalabel='uniaxiality_sig_vMises_durch_sig33' fobj.write('SCALARS %s float %i\n'%(datalabel,1)) fobj.write('LOOKUP_TABLE default\n') cnt=0 for iEl in range(0,self.nel): cnt=cnt+1 - #if abs(self.sig33[iEl])<1e-5: if abs(self.sig_vMises[iEl])<1e-5: datum=0. else: - #datum=self.sig_vMises[iEl]/self.sig33[iEl] datum=self.sig33[iEl]/self.sig_vMises[iEl] fobj.write('%E '%(datum)) if cnt>self.VTKcnt: @@ -283,8 +265,8 @@ class MARC_POST(): self.mean_stress.append(self.meanStress(sig)) def triaxiality_per_element(self): - # classical triaxiality - # 1/3 : uniax tension + # classical triaxiality + # 1/3 : uniax tension self.triaxiality=[] for iEl in range(0,self.nel): t=self.mean_stress[iEl]/self.sig_vMises[iEl] @@ -303,10 +285,6 @@ class MARC_POST(): fobj.write('\n') def calc_lode_parameter(self): - # [-1 ... +1] see e.g. Wippler & Boehlke triaxiality measures doi:10.1002/pamm.201010061 - # +1 : uniax tensile? - # 0 : shear - # -1 : uniax compr ? self.lode=[] try: self.stress @@ -328,10 +306,11 @@ class MARC_POST(): def princStress(self, stress): """ Function to compute 3D principal stresses and sort them. + from: http://geodynamics.org/svn/cig/short/3D/PyLith/trunk/playpen/postproc/vtkcff.py """ - stressMat=N.array(stress) - (princStress, princAxes) = numpy.linalg.eigh(stressMat) + stressMat=np.array(stress) + (princStress, princAxes) = np.linalg.eigh(stressMat) idx = princStress.argsort() princStressOrdered = princStress[idx] princAxesOrdered = princAxes[:,idx] @@ -339,36 +318,28 @@ class MARC_POST(): def avg_elten(self, idxElTen, mat=0, elID=None): - tensum=N.zeros((3,3)); - T=N.zeros((3,3)); + tensum=np.zeros((3,3)); + T=np.zeros((3,3)); pts=0; - avg=N.zeros((3,3)); - #print 'Element Scalars' - #print self.p.element_scalar_label(elscal2) - if elID==None: + avg=np.zeros((3,3)); + + if elID is None: averaged_elements=range(0,self.nel) else: averaged_elements=[elID] - #for i in range (0,self.nel): for i in averaged_elements: if mat==0 or int(self.p.element_scalar(i,4)[0].value)==mat: - eldata=self.p.element(i) T=self.p.element_tensor(i,idxElTen) for k in range (0,8): tensum[0][0] = tensum[0][0] + T[k].t11 tensum[0][1] = tensum[0][1] + T[k].t12 tensum[0][2] = tensum[0][2] + T[k].t13 - #tensum1[1][0] = tensum1[1][0] + T1[k].t21 tensum[1][1] = tensum[1][1] + T[k].t22 tensum[1][2] = tensum[1][2] + T[k].t23 - #tensum1[2][0] = tensum1[2][0] + T1[k].t31 - #tensum1[2][1] = tensum1[2][1] + T1[k].t32 tensum[2][2] = tensum[2][2] + T[k].t33 pts=pts+1 avg=tensum/pts - #print avg avg=self.fillComponents(avg) - #print avg del [T] return (avg,tensum,pts) @@ -384,7 +355,7 @@ class MARC_POST(): t=tensor33 s=(t[0,0]-t[1,1])**2+(t[1,1]-t[2,2])**2+(t[0,0]-t[2,2])**2+\ 6*(t[0,1]**2+t[1,2]**2+t[2,0]**2) - vM=N.sqrt(s/2.) + vM=np.sqrt(s/2.) return vM def meanStress(self,tensor33): @@ -397,8 +368,7 @@ class MARC_POST(): t=tensor33 I1=t[0,0]+t[1,1]+t[2,2] I2=t[0,0]*t[1,1]+t[1,1]*t[2,2]+t[0,0]*t[2,2]-\ - t[0,1]**2-t[1,2]**2-t[0,2]**2 - # I3 = det(t) + t[0,1]**2-t[1,2]**2-t[0,2]**2 I3=t[0,0]*t[1,1]*t[2,2]+\ 2*t[0,1]*t[1,2]*t[2,0]-\ t[2,2]*t[0,1]**2-t[0,0]*t[1,2]**2-t[1,1]*t[0,2]**2 @@ -406,17 +376,18 @@ class MARC_POST(): class VTK_WRITER(): - ''' - The resulting vtk-file can be imported in Paraview 3.12 - Then use Filters: Cell Data to Point Data + Contour - to plot semi-transparent iso-surfaces. - ''' + """ + The resulting vtk-file can be imported in Paraview 3.12 + + Then use Filters: Cell Data to Point Data + Contour + to plot semi-transparent iso-surfaces. + """ + import re def __init__(self): self.p=MARC_POST() # self.p def openFile(self, filename='test.vtp'): - #if not self.f:#==None: self.f=open(filename,'w+') self.fname=filename @@ -427,7 +398,7 @@ class VTK_WRITER(): dformat='ASCII', # BINARY | [ASCII] dtype='UNSTRUCTURED_GRID' # UNSTRUCTURED GRID ): - if vtkFile==None: + if vtkFile is None: vtkFile=self.f # First Line contains Data format version self.versionVTK=version @@ -440,7 +411,6 @@ class VTK_WRITER(): def marc2vtkBatch(self): for iori in range(1,63): - #self.p=msc_post.MSC_POST() self.p.postname='indent_fric0.3_R2.70_cA146.0_h0.320_ori%03i_OST_h19d.t16'%(iori) if os.path.exists(self.p.postname): self.marc2vtk(mode='fast', batchMode=1) @@ -496,14 +466,14 @@ class VTK_WRITER(): def scaleBar(self, length=1.0, posXYZ=[0., 0., 0.]): self.fsb=open('micronbar_l%.1f.vtp'%length,'w+') self.writeFirstLines(self.fsb, comment='micronbar') - pts=N.array([]) + pts=np.array([]) width=length*1. height=length*1. - wVec=N.array([0., width, 0.]) - lVec=N.array([length,0.,0.]) - hVec=N.array([0.,0.,height]) + wVec=np.array([0., width, 0.]) + lVec=np.array([length,0.,0.]) + hVec=np.array([0.,0.,height]) posXYZ=posXYZ-0.5*wVec-0.5*lVec#-0.5*hVec # CENTERING Y/N - posXYZ=N.array(posXYZ) + posXYZ=np.array(posXYZ) pts=[posXYZ, posXYZ+lVec, posXYZ+wVec, posXYZ+wVec+lVec] @@ -514,34 +484,22 @@ class VTK_WRITER(): self.fsb.write('%f %f %f\n'%(pts[npts][0], pts[npts][1], pts[npts][2])) if 1: #Triad nCells=3 - #nCells=1 #One Line ptsPerCell=2 # Lines (Type=3) - #ptsPerCell=4 # Quads (Type=9) - #ptsPerCell=8 # Hexahedron (Type=12) cellSize=(ptsPerCell+1)*nCells self.fsb.write('CELLS %i %i\n'%(nCells,cellSize)) self.fsb.write('2 0 1\n') #X-Line self.fsb.write('2 0 2\n') #Y-Line self.fsb.write('2 0 4\n') #Z-Line - #self.fsb.write('4 0 1 3 2\n') #Quad - #self.fsb.write('%i 0 1 3 2 4 5 7 6\n'%ptsPerCell) #Hexahedron self.fsb.write('CELL_TYPES %i\n'%(nCells)) self.fsb.write('3\n3\n3\n')#Line - #self.fsb.write('12\n')#Hexahedron else: # Cube, change posXYZ nCells=1 ptsPerCell=2 # Lines (Type=3) - #ptsPerCell=4 # Quads (Type=9) - #ptsPerCell=8 # Hexahedron (Type=12) cellSize=(ptsPerCell+1)*nCells self.fsb.write('CELLS %i %i\n'%(nCells,cellSize)) self.fsb.write('2 0 1\n') #Line - #self.fsb.write('4 0 1 3 2\n') #Quad - #self.fsb.write('%i 0 1 3 2 4 5 7 6\n'%ptsPerCell) #Hexahedron self.fsb.write('CELL_TYPES %i\n'%(nCells)) self.fsb.write('3\n')#Line - #self.fsb.write('12\n')#Hexahedron - self.fsb.write('\n') self.fsb.close() @@ -549,8 +507,7 @@ class VTK_WRITER(): def example_unstructured(self): self.openFile(filename='example_unstructured_grid.vtk') - #self.writeFirstLines() - self.f.write(''' + self.f.write(""" # vtk DataFile Version 2.0 example_unstruct_grid ASCII @@ -590,61 +547,40 @@ LOOKUP_TABLE default 1.02 1.50 0.00 -3 5 6 23423423423423423423.23423423''') +3 5 6 23423423423423423423.23423423""") self.f.close() def writeNodes2VTK(self, fobj): self.VTKcnt=200 # how many numbers per line in vtk file - #self.VTKcnt=6 - ndCnt=1 - #self.nodes=range(0,10) fobj.write('POINTS %i'%self.p.nodes()+' float\n') for iNd in self.nodes: nd=self.p.node(iNd) disp=self.p.node_displacement(iNd) - #contact=self.p.node_scalar(iNd,contactNr) - #ndCnt=ndCnt+1 fobj.write('%f %f %f \n'% - #(nd.x, nd.y, nd.z)) (nd.x+disp[0], nd.y+disp[1], nd.z+disp[2])) - - #if ndCnt>6: - # fobj.write('\n') - # ndCnt=1 fobj.write('\n') print('Nodes written to VTK: %i'%self.p.nodes()) - #print('Nr of nodes: ',self.nodes) def writeElements2VTK(self, fobj): fobj.write('\nCELLS %i %i'%(self.p.elements(),self.p.elements()*9)+'\n') for iEl in range(0,self.nel): el=self.p.element(iEl) - #disp=self.p.node_displacement(iNd) - #contact=self.p.node_scalar(iNd,contactNr) - #ndCnt=ndCnt+1 fobj.write('8 ') ndlist=el.items - #for k in [0, 1, 3, 2, 4, 5, 7, 6]: # FOR CELL TPYE VTK_VOXEL - #for k in [0, 4, 3, 1, 5, 7, 6, 2]: for k in [0, 1, 2, 3, 4, 5, 6, 7]: # FOR CELL TYPE VTK_HEXAHEDRON fobj.write('%6i '%(ndlist[k]-1)) fobj.write('\n') - #if ndCnt>6: - # fobj.write('\n') - # ndCnt=1 fobj.write('\nCELL_TYPES %i'%self.p.elements()+'\n') cnt=0 for iEl in range(0,self.nel): cnt=cnt+1 - #fobj.write('11\n') #VTK_VOXEL fobj.write('12 ') #VTK_HEXAHEDRON if cnt>self.VTKcnt: fobj.write('\n');cnt=0 fobj.write('\n') print('Elements written to VTK: %i'%self.p.elements()) - #print('Nr of nodes: ',self.nodes) def writeElScalars2NodesVTK(self,fobj): fobj.write('\nPOINT_DATA %i\n'%self.p.nodes()) @@ -668,10 +604,7 @@ LOOKUP_TABLE default fobj.write('\n') def writeNodeScalars2VTK(self,fobj): - #print('writeElementData2VTK') fobj.write('\nPOINT_DATA %i\n'%self.p.nodes()) - nNdDat=self.nscals - nComponents=1+nNdDat for idxNdScal in range(-3,self.nscals): # include node x,y,z if idxNdScal>=0: datalabel=self.nscal_list[idxNdScal] @@ -700,10 +633,7 @@ LOOKUP_TABLE default fobj.write('\n') def writeElementData2VTK(self,fobj): - #print('writeElementData2VTK') fobj.write('\nCELL_DATA %i\n'%self.p.elements()) - nElDat=self.elscals - nComponents=1+nElDat for idxElScal in range(0,self.elscals): datalabel=self.elscal_list[idxElScal] datalabel=re.sub("\s",'_',datalabel) @@ -730,7 +660,7 @@ LOOKUP_TABLE default def example1(self): self.openFile() self.writeFirstLines() - self.f.write('''DATASET POLYDATA + self.f.write("""DATASET POLYDATA POINTS 8 float 0.0 0.0 0.0 1.0 0.0 0.0 @@ -789,18 +719,20 @@ LOOKUP_TABLE my_table 8 0.0 0.0 1.0 1.0 1.0 0.0 1.0 1.0 0.0 1.0 1.0 1.0 -1.0 1.0 1.0 1.0''') +1.0 1.0 1.0 1.0""") self.f.close() import pyvtk class marc_to_vtk(): - ''' - Anybody wants to implement it with pyvtk? - The advantage would be that pyvtk can also wirte the - -VTK format and binary. - These can be plotted with mayavi. - ''' + """ + Anybody wants to implement it with pyvtk? + + The advantage would be that pyvtk can also wirte the + -VTK format and binary. + These can be plotted with mayavi. + """ + def __init__(self): self.p=[]#MARC_POST() # self.p @@ -810,5 +742,4 @@ class marc_to_vtk(): hexahedron=self.p.cells), 'm2v output') vtk.tofile('m2v_file') - #vtk.tofile('example3b','binary') - #VtkData('example3') \ No newline at end of file + diff --git a/lib/damask/test/__init__.py b/lib/damask/test/__init__.py index 264ec7eb7..c81d9eecb 100644 --- a/lib/damask/test/__init__.py +++ b/lib/damask/test/__init__.py @@ -2,4 +2,4 @@ """Test functionality""" -from .test import Test "noqa +from .test import Test #noqa