From e8c39077df2c0cdda72987756ea712224b6b69aa Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 26 Jan 2022 06:26:37 +0100 Subject: [PATCH 01/16] optional is usually not needed --- python/damask/_table.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python/damask/_table.py b/python/damask/_table.py index fed309439..d20372d2e 100644 --- a/python/damask/_table.py +++ b/python/damask/_table.py @@ -1,7 +1,7 @@ import re import copy from pathlib import Path -from typing import Union, Optional, Tuple, List +from typing import Union, Tuple, List import pandas as pd import numpy as np @@ -12,7 +12,7 @@ from . import util class Table: """Manipulate multi-dimensional spreadsheet-like data.""" - def __init__(self, data: np.ndarray, shapes: dict, comments: Optional[Union[str, list]] = None): + def __init__(self, data: np.ndarray, shapes: dict, comments: Union[str, list] = None): """ New spreadsheet. @@ -147,7 +147,7 @@ class Table: self.data.columns = self._label(self.shapes,how) #type: ignore - def _add_comment(self, label: str, shape: Tuple[int, ...], info: Optional[str]): + def _add_comment(self, label: str, shape: Tuple[int, ...], info: str = None): if info is not None: specific = f'{label}{" "+str(shape) if np.prod(shape,dtype=int) > 1 else ""}: {info}' general = util.execution_stamp('Table') From 0c21b6a8e0aa7a221e29908560be4590f4ffe5f3 Mon Sep 17 00:00:00 2001 From: Daniel Otto de Mentock Date: Wed, 26 Jan 2022 16:25:27 +0100 Subject: [PATCH 02/16] [skip ci] changed almost all function definition lines to multiline for colormap, grid, table, vtk and util modules --- python/damask/_colormap.py | 3 ++- python/damask/_grid.py | 47 +++++++++++++++++++++++++---------- python/damask/_table.py | 51 ++++++++++++++++++++++++++++---------- python/damask/_vtk.py | 34 ++++++++++++++++++------- python/damask/util.py | 37 +++++++++++++++++++-------- 5 files changed, 126 insertions(+), 46 deletions(-) diff --git a/python/damask/_colormap.py b/python/damask/_colormap.py index 93bd83cdc..30ae2677e 100644 --- a/python/damask/_colormap.py +++ b/python/damask/_colormap.py @@ -161,7 +161,8 @@ class Colormap(mpl.colors.ListedColormap): @staticmethod - def from_predefined(name: str, N: int = 256) -> 'Colormap': + def from_predefined(name: str, + N: int = 256) -> 'Colormap': """ Select from a set of predefined colormaps. diff --git a/python/damask/_grid.py b/python/damask/_grid.py index 94f7eefd0..c62d00cbb 100644 --- a/python/damask/_grid.py +++ b/python/damask/_grid.py @@ -101,7 +101,8 @@ class Grid: return self._material @material.setter - def material(self, material: np.ndarray): + def material(self, + material: np.ndarray): if len(material.shape) != 3: raise ValueError(f'invalid material shape {material.shape}') elif material.dtype not in np.sctypes['float'] and material.dtype not in np.sctypes['int']: @@ -120,7 +121,8 @@ class Grid: return self._size @size.setter - def size(self, size: FloatSequence): + def size(self, + size: FloatSequence): if len(size) != 3 or any(np.array(size) < 0): raise ValueError(f'invalid size {size}') else: @@ -132,7 +134,8 @@ class Grid: return self._origin @origin.setter - def origin(self, origin: FloatSequence): + def origin(self, + origin: FloatSequence): if len(origin) != 3: raise ValueError(f'invalid origin {origin}') else: @@ -144,7 +147,8 @@ class Grid: return self._comments @comments.setter - def comments(self, comments: Union[str, Sequence[str]]): + def comments(self, + comments: Union[str, Sequence[str]]): self._comments = [str(c) for c in comments] if isinstance(comments,list) else [str(comments)] @@ -387,7 +391,9 @@ class Grid: @staticmethod - def _find_closest_seed(seeds: np.ndarray, weights: np.ndarray, point: np.ndarray) -> np.integer: + def _find_closest_seed(seeds: np.ndarray, + weights: np.ndarray, + point: np.ndarray) -> np.integer: return np.argmin(np.sum((np.broadcast_to(point,(len(seeds),3))-seeds)**2,axis=1) - weights) @staticmethod @@ -624,7 +630,9 @@ class Grid: ) - def save(self, fname: Union[str, Path], compress: bool = True): + def save(self, + fname: Union[str, Path], + compress: bool = True): """ Save as VTK image data file. @@ -643,7 +651,8 @@ class Grid: v.save(fname,parallel=False,compress=compress) - def save_ASCII(self, fname: Union[str, TextIO]): + def save_ASCII(self, + fname: Union[str, TextIO]): """ Save as geom file. @@ -770,7 +779,9 @@ class Grid: ) - def mirror(self, directions: Sequence[str], reflect: bool = False) -> 'Grid': + def mirror(self, + directions: Sequence[str], + reflect: bool = False) -> 'Grid': """ Mirror grid along given directions. @@ -822,7 +833,9 @@ class Grid: ) - def flip(self, directions: Union[Literal['x', 'y', 'z'], Sequence[Literal['x', 'y', 'z']]]) -> 'Grid': + def flip(self, + directions: Union[Literal['x', 'y', 'z'], + Sequence[Literal['x', 'y', 'z']]]) -> 'Grid': """ Flip grid along given directions. @@ -852,7 +865,9 @@ class Grid: ) - def scale(self, cells: IntSequence, periodic: bool = True) -> 'Grid': + def scale(self, + cells: IntSequence, + periodic: bool = True) -> 'Grid': """ Scale grid to new cells. @@ -958,7 +973,9 @@ class Grid: ) - def rotate(self, R: Rotation, fill: int = None) -> 'Grid': + def rotate(self, + R: Rotation, + fill: int = None) -> 'Grid': """ Rotate grid (pad if required). @@ -1049,7 +1066,9 @@ class Grid: ) - def substitute(self, from_material: IntSequence, to_material: IntSequence) -> 'Grid': + def substitute(self, + from_material: IntSequence, + to_material: IntSequence) -> 'Grid': """ Substitute material indices. @@ -1150,7 +1169,9 @@ class Grid: ) - def get_grain_boundaries(self, periodic: bool = True, directions: Sequence[str] = 'xyz'): + def get_grain_boundaries(self, + periodic: bool = True, + directions: Sequence[str] = 'xyz'): """ Create VTK unstructured grid containing grain boundaries. diff --git a/python/damask/_table.py b/python/damask/_table.py index d20372d2e..16779b83d 100644 --- a/python/damask/_table.py +++ b/python/damask/_table.py @@ -12,7 +12,10 @@ from . import util class Table: """Manipulate multi-dimensional spreadsheet-like data.""" - def __init__(self, data: np.ndarray, shapes: dict, comments: Union[str, list] = None): + def __init__(self, + data: np.ndarray, + shapes: dict, + comments: Union[str, list] = None): """ New spreadsheet. @@ -41,7 +44,8 @@ class Table: return '\n'.join(['# '+c for c in self.comments])+'\n'+data_repr - def __getitem__(self, item: Union[slice, Tuple[slice, ...]]) -> 'Table': + def __getitem__(self, + item: Union[slice, Tuple[slice, ...]]) -> 'Table': """ Slice the Table according to item. @@ -100,7 +104,9 @@ class Table: copy = __copy__ - def _label(self, what: Union[str, List[str]], how: str) -> List[str]: + def _label(self, + what: Union[str, List[str]], + how: str) -> List[str]: """ Expand labels according to data shape. @@ -147,7 +153,10 @@ class Table: self.data.columns = self._label(self.shapes,how) #type: ignore - def _add_comment(self, label: str, shape: Tuple[int, ...], info: str = None): + def _add_comment(self, + label: str, + shape: Tuple[int, ...], + info: str = None): if info is not None: specific = f'{label}{" "+str(shape) if np.prod(shape,dtype=int) > 1 else ""}: {info}' general = util.execution_stamp('Table') @@ -321,7 +330,8 @@ class Table: return list(self.shapes) - def get(self, label: str) -> np.ndarray: + def get(self, + label: str) -> np.ndarray: """ Get column data. @@ -341,7 +351,10 @@ class Table: return data.astype(type(data.flatten()[0])) - def set(self, label: str, data: np.ndarray, info: str = None) -> 'Table': + def set(self, + label: str, + data: np.ndarray, + info: str = None) -> 'Table': """ Set column data. @@ -374,7 +387,10 @@ class Table: return dup - def add(self, label: str, data: np.ndarray, info: str = None) -> 'Table': + def add(self, + label: str, + data: np.ndarray, + info: str = None) -> 'Table': """ Add column data. @@ -406,7 +422,8 @@ class Table: return dup - def delete(self, label: str) -> 'Table': + def delete(self, + label: str) -> 'Table': """ Delete column data. @@ -427,7 +444,10 @@ class Table: return dup - def rename(self, old: Union[str, List[str]], new: Union[str, List[str]], info: str = None) -> 'Table': + def rename(self, + old: Union[str, List[str]], + new: Union[str, List[str]], + info: str = None) -> 'Table': """ Rename column data. @@ -453,7 +473,9 @@ class Table: return dup - def sort_by(self, labels: Union[str, List[str]], ascending: Union[bool, List[bool]] = True) -> 'Table': + def sort_by(self, + labels: Union[str, List[str]], + ascending: Union[bool, List[bool]] = True) -> 'Table': """ Sort table by values of given labels. @@ -486,7 +508,8 @@ class Table: return dup - def append(self, other: 'Table') -> 'Table': + def append(self, + other: 'Table') -> 'Table': """ Append other table vertically (similar to numpy.vstack). @@ -511,7 +534,8 @@ class Table: return dup - def join(self, other: 'Table') -> 'Table': + def join(self, + other: 'Table') -> 'Table': """ Append other table horizontally (similar to numpy.hstack). @@ -538,7 +562,8 @@ class Table: return dup - def save(self, fname: FileHandle): + def save(self, + fname: FileHandle): """ Save as plain text file. diff --git a/python/damask/_vtk.py b/python/damask/_vtk.py index 4e3f27e0e..601608520 100644 --- a/python/damask/_vtk.py +++ b/python/damask/_vtk.py @@ -22,7 +22,8 @@ class VTK: High-level interface to VTK. """ - def __init__(self, vtk_data: vtk.vtkDataSet): + def __init__(self, + vtk_data: vtk.vtkDataSet): """ New spatial visualization. @@ -38,7 +39,9 @@ class VTK: @staticmethod - def from_image_data(cells: IntSequence, size: FloatSequence, origin: FloatSequence = np.zeros(3)) -> 'VTK': + def from_image_data(cells: IntSequence, + size: FloatSequence, + origin: FloatSequence = np.zeros(3)) -> 'VTK': """ Create VTK of type vtk.vtkImageData. @@ -68,7 +71,9 @@ class VTK: @staticmethod - def from_rectilinear_grid(grid: np.ndarray, size: FloatSequence, origin: FloatSequence = np.zeros(3)) -> 'VTK': + def from_rectilinear_grid(grid: np.ndarray, + size: FloatSequence, + origin: FloatSequence = np.zeros(3)) -> 'VTK': """ Create VTK of type vtk.vtkRectilinearGrid. @@ -100,7 +105,9 @@ class VTK: @staticmethod - def from_unstructured_grid(nodes: np.ndarray, connectivity: np.ndarray, cell_type: str) -> 'VTK': + def from_unstructured_grid(nodes: np.ndarray, + connectivity: np.ndarray, + cell_type: str) -> 'VTK': """ Create VTK of type vtk.vtkUnstructuredGrid. @@ -238,7 +245,11 @@ class VTK: def _write(writer): """Wrapper for parallel writing.""" writer.Write() - def save(self, fname: Union[str, Path], parallel: bool = True, compress: bool = True): + + def save(self, + fname: Union[str, Path], + parallel: bool = True, + compress: bool = True): """ Save as VTK file. @@ -284,7 +295,9 @@ class VTK: # Check https://blog.kitware.com/ghost-and-blanking-visibility-changes/ for missing data # Needs support for damask.Table - def add(self, data: Union[np.ndarray, np.ma.MaskedArray], label: str = None): + def add(self, + data: Union[np.ndarray, np.ma.MaskedArray], + label: str = None): """ Add data to either cells or points. @@ -331,7 +344,8 @@ class VTK: raise TypeError - def get(self, label: str) -> np.ndarray: + def get(self, + label: str) -> np.ndarray: """ Get either cell or point data. @@ -383,7 +397,8 @@ class VTK: return [] - def set_comments(self, comments: Union[str, List[str]]): + def set_comments(self, + comments: Union[str, List[str]]): """ Set comments. @@ -400,7 +415,8 @@ class VTK: self.vtk_data.GetFieldData().AddArray(s) - def add_comments(self, comments: Union[str, List[str]]): + def add_comments(self, + comments: Union[str, List[str]]): """ Add comments. diff --git a/python/damask/util.py b/python/damask/util.py index 2872762b9..7c1803e80 100644 --- a/python/damask/util.py +++ b/python/damask/util.py @@ -54,7 +54,8 @@ _colors = { #################################################################################################### # Functions #################################################################################################### -def srepr(msg, glue: str = '\n') -> str: +def srepr(msg, + glue: str = '\n') -> str: r""" Join items with glue string. @@ -148,7 +149,10 @@ def strikeout(msg) -> str: return _colors['crossout']+srepr(msg)+_colors['end_color'] -def run(cmd: str, wd: str = './', env: Dict[str, str] = None, timeout: int = None) -> Tuple[str, str]: +def run(cmd: str, + wd: str = './', + env: Dict[str, str] = None, + timeout: int = None) -> Tuple[str, str]: """ Run a command. @@ -373,14 +377,17 @@ def project_equal_area(vector: np.ndarray, return np.roll(np.block([v[...,:2]/np.sqrt(1.0+np.abs(v[...,2:3])),np.zeros_like(v[...,2:3])]), -shift if keepdims else 0,axis=-1)[...,:3 if keepdims else 2] -def execution_stamp(class_name: str, function_name: str = None) -> str: +def execution_stamp(class_name: str, + function_name: str = None) -> str: """Timestamp the execution of a (function within a) class.""" now = datetime.datetime.now().astimezone().strftime('%Y-%m-%d %H:%M:%S%z') _function_name = '' if function_name is None else f'.{function_name}' return f'damask.{class_name}{_function_name} v{version} ({now})' -def hybrid_IA(dist: np.ndarray, N: int, rng_seed = None) -> np.ndarray: +def hybrid_IA(dist: np.ndarray, + N: int, + rng_seed = None) -> np.ndarray: """ Hybrid integer approximation. @@ -473,7 +480,8 @@ def shapeshifter(fro: Tuple[int, ...], return fill[:-1] -def shapeblender(a: Tuple[int, ...], b: Tuple[int, ...]) -> Tuple[int, ...]: +def shapeblender(a: Tuple[int, ...], + b: Tuple[int, ...]) -> Tuple[int, ...]: """ Return a shape that overlaps the rightmost entries of 'a' with the leftmost of 'b'. @@ -517,7 +525,8 @@ def extend_docstring(extra_docstring: str) -> Callable: return _decorator -def extended_docstring(f: Callable, extra_docstring: str) -> Callable: +def extended_docstring(f: Callable, + extra_docstring: str) -> Callable: """ Decorator: Combine another function's docstring with a given docstring. @@ -593,7 +602,9 @@ def DREAM3D_cell_data_group(fname: Union[str, Path]) -> str: return cell_data_group -def Bravais_to_Miller(*, uvtw: np.ndarray = None, hkil: np.ndarray = None) -> np.ndarray: +def Bravais_to_Miller(*, + uvtw: np.ndarray = None, + hkil: np.ndarray = None) -> np.ndarray: """ Transform 4 Miller–Bravais indices to 3 Miller indices of crystal direction [uvw] or plane normal (hkl). @@ -620,7 +631,9 @@ def Bravais_to_Miller(*, uvtw: np.ndarray = None, hkil: np.ndarray = None) -> np return np.einsum('il,...l',basis,axis) -def Miller_to_Bravais(*, uvw: np.ndarray = None, hkl: np.ndarray = None) -> np.ndarray: +def Miller_to_Bravais(*, + uvw: np.ndarray = None, + hkl: np.ndarray = None) -> np.ndarray: """ Transform 3 Miller indices to 4 Miller–Bravais indices of crystal direction [uvtw] or plane normal (hkil). @@ -710,7 +723,10 @@ class ProgressBar: Works for 0-based loops, ETA is estimated by linear extrapolation. """ - def __init__(self, total: int, prefix: str, bar_length: int): + def __init__(self, + total: int, + prefix: str, + bar_length: int): """ Set current time as basis for ETA estimation. @@ -733,7 +749,8 @@ class ProgressBar: sys.stderr.write(f"{self.prefix} {'░'*self.bar_length} 0% ETA n/a") sys.stderr.flush() - def update(self, iteration: int) -> None: + def update(self, + iteration: int) -> None: fraction = (iteration+1) / self.total filled_length = int(self.bar_length * fraction) From 8e514bf6f42dae2b012ba2cad432d28bbbd10dde Mon Sep 17 00:00:00 2001 From: Daniel Otto de Mentock Date: Wed, 26 Jan 2022 16:36:26 +0100 Subject: [PATCH 03/16] added missing utils typehint --- python/damask/util.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/damask/util.py b/python/damask/util.py index 7c1803e80..e1db35007 100644 --- a/python/damask/util.py +++ b/python/damask/util.py @@ -16,7 +16,7 @@ import numpy as np import h5py from . import version -from ._typehints import FloatSequence +from ._typehints import IntSequence, FloatSequence # limit visibility __all__=[ @@ -387,7 +387,7 @@ def execution_stamp(class_name: str, def hybrid_IA(dist: np.ndarray, N: int, - rng_seed = None) -> np.ndarray: + rng_seed: Union[int, IntSequence] = None) -> np.ndarray: """ Hybrid integer approximation. From bc667888ce196586f6b9588e7d50a186af0a5c1b Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 26 Jan 2022 23:37:07 +0100 Subject: [PATCH 04/16] consistent style --- python/damask/_colormap.py | 33 ++++++++++++++++++++++----------- python/damask/_grid.py | 3 ++- python/damask/_table.py | 3 ++- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/python/damask/_colormap.py b/python/damask/_colormap.py index 30ae2677e..5c77cf61e 100644 --- a/python/damask/_colormap.py +++ b/python/damask/_colormap.py @@ -47,27 +47,32 @@ class Colormap(mpl.colors.ListedColormap): """ - def __eq__(self, other: object) -> bool: + def __eq__(self, + other: object) -> bool: """Test equality of colormaps.""" if not isinstance(other, Colormap): return NotImplemented return len(self.colors) == len(other.colors) \ and bool(np.all(self.colors == other.colors)) - def __add__(self, other: 'Colormap') -> 'Colormap': + def __add__(self, + other: 'Colormap') -> 'Colormap': """Concatenate.""" return Colormap(np.vstack((self.colors,other.colors)), f'{self.name}+{other.name}') - def __iadd__(self, other: 'Colormap') -> 'Colormap': + def __iadd__(self, + other: 'Colormap') -> 'Colormap': """Concatenate (in-place).""" return self.__add__(other) - def __mul__(self, factor: int) -> 'Colormap': + def __mul__(self, + factor: int) -> 'Colormap': """Repeat.""" return Colormap(np.vstack([self.colors]*factor),f'{self.name}*{factor}') - def __imul__(self, factor: int) -> 'Colormap': + def __imul__(self, + factor: int) -> 'Colormap': """Repeat (in-place).""" return self.__mul__(factor) @@ -276,7 +281,8 @@ class Colormap(mpl.colors.ListedColormap): mode='RGBA') - def reversed(self, name: str = None) -> 'Colormap': + def reversed(self, + name: str = None) -> 'Colormap': """ Reverse. @@ -329,7 +335,8 @@ class Colormap(mpl.colors.ListedColormap): return fname - def save_paraview(self, fname: FileHandle = None): + def save_paraview(self, + fname: FileHandle = None): """ Save as JSON file for use in Paraview. @@ -356,7 +363,8 @@ class Colormap(mpl.colors.ListedColormap): fhandle.write('\n') - def save_ASCII(self, fname: FileHandle = None): + def save_ASCII(self, + fname: FileHandle = None): """ Save as ASCII file. @@ -391,7 +399,8 @@ class Colormap(mpl.colors.ListedColormap): self._get_file_handle(fname,'.legend').write(GOM_str) - def save_gmsh(self, fname: FileHandle = None): + def save_gmsh(self, + fname: FileHandle = None): """ Save as ASCII file for use in gmsh. @@ -622,7 +631,8 @@ class Colormap(mpl.colors.ListedColormap): @staticmethod - def _lab2xyz(lab: np.ndarray, ref_white: np.ndarray = _REF_WHITE) -> np.ndarray: + def _lab2xyz(lab: np.ndarray, + ref_white: np.ndarray = _REF_WHITE) -> np.ndarray: """ CIE Lab to CIE Xyz. @@ -653,7 +663,8 @@ class Colormap(mpl.colors.ListedColormap): ])*ref_white @staticmethod - def _xyz2lab(xyz: np.ndarray, ref_white: np.ndarray = _REF_WHITE) -> np.ndarray: + def _xyz2lab(xyz: np.ndarray, + ref_white: np.ndarray = _REF_WHITE) -> np.ndarray: """ CIE Xyz to CIE Lab. diff --git a/python/damask/_grid.py b/python/damask/_grid.py index c62d00cbb..b188873a4 100644 --- a/python/damask/_grid.py +++ b/python/damask/_grid.py @@ -77,7 +77,8 @@ class Grid: copy = __copy__ - def __eq__(self, other: object) -> bool: + def __eq__(self, + other: object) -> bool: """ Test equality of other. diff --git a/python/damask/_table.py b/python/damask/_table.py index 16779b83d..44a04b40a 100644 --- a/python/damask/_table.py +++ b/python/damask/_table.py @@ -137,7 +137,8 @@ class Table: return labels - def _relabel(self, how: str): + def _relabel(self, + how: str): """ Modify labeling of data in-place. From 4ca501c73f221924729d695cd0e73dae004e200e Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Thu, 27 Jan 2022 08:53:27 +0100 Subject: [PATCH 05/16] small changes in logic for type hints --- python/damask/_crystal.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/python/damask/_crystal.py b/python/damask/_crystal.py index 7a21f9245..a8b2ccf79 100644 --- a/python/damask/_crystal.py +++ b/python/damask/_crystal.py @@ -33,9 +33,9 @@ class Crystal(): def __init__(self,*, family = None, lattice = None, - a = None,b = None,c = None, - alpha = None,beta = None,gamma = None, - degrees = False): + a: float = None, b: float = None, c: float = None, + alpha: float = None, beta: float = None, gamma: float = None, + degrees: bool = False): """ Representation of crystal in terms of crystal family or Bravais lattice. @@ -62,7 +62,7 @@ class Crystal(): Angles are given in degrees. Defaults to False. """ - if family not in [None] + list(lattice_symmetries.values()): + if family is not None and family not in list(lattice_symmetries.values()): raise KeyError(f'invalid crystal family "{family}"') if lattice is not None and family is not None and family != lattice_symmetries[lattice]: raise KeyError(f'incompatible family "{family}" for lattice "{lattice}"') @@ -107,9 +107,6 @@ class Crystal(): if np.any([np.roll([self.alpha,self.beta,self.gamma],r)[0] >= np.sum(np.roll([self.alpha,self.beta,self.gamma],r)[1:]) for r in range(3)]): raise ValueError ('each lattice angle must be less than sum of others') - else: - self.a = self.b = self.c = None - self.alpha = self.beta = self.gamma = None def __repr__(self): @@ -139,8 +136,7 @@ class Crystal(): @property def parameters(self): """Return lattice parameters a, b, c, alpha, beta, gamma.""" - return (self.a,self.b,self.c,self.alpha,self.beta,self.gamma) - + if hasattr(self,'a'): return (self.a,self.b,self.c,self.alpha,self.beta,self.gamma) @property def immutable(self): @@ -269,7 +265,7 @@ class Crystal(): https://doi.org/10.1063/1.1661333 """ - if None in self.parameters: + if self.parameters is None: raise KeyError('missing crystal lattice parameters') return np.array([ [1,0,0], From a12135fe7786b2ca0ca90a9bf2c7cb48a801f1c0 Mon Sep 17 00:00:00 2001 From: Daniel Otto de Mentock Date: Thu, 27 Jan 2022 10:45:14 +0100 Subject: [PATCH 06/16] [skip ci] changed function definition to multiline layout for crystal, seeds and tensor module --- python/damask/_crystal.py | 15 +++++++++++---- python/damask/seeds.py | 19 ++++++++++++++----- python/damask/tensor.py | 6 ++++-- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/python/damask/_crystal.py b/python/damask/_crystal.py index a8b2ccf79..c97f75d01 100644 --- a/python/damask/_crystal.py +++ b/python/damask/_crystal.py @@ -311,7 +311,9 @@ class Crystal(): + _lattice_points.get(self.lattice if self.lattice == 'hP' else \ self.lattice[-1],None),dtype=float) - def to_lattice(self, *, direction: np.ndarray = None, plane: np.ndarray = None) -> np.ndarray: + def to_lattice(self, + *, direction: np.ndarray = None, + plane: np.ndarray = None) -> np.ndarray: """ Calculate lattice vector corresponding to crystal frame direction or plane normal. @@ -335,7 +337,10 @@ class Crystal(): return np.einsum('il,...l',basis,axis) - def to_frame(self, *, uvw: np.ndarray = None, hkl: np.ndarray = None) -> np.ndarray: + def to_frame(self, + *, + uvw: np.ndarray = None, + hkl: np.ndarray = None) -> np.ndarray: """ Calculate crystal frame vector along lattice direction [uvw] or plane normal (hkl). @@ -358,7 +363,8 @@ class Crystal(): return np.einsum('il,...l',basis,axis) - def kinematics(self, mode: str) -> Dict[str, List[np.ndarray]]: + def kinematics(self, + mode: str) -> Dict[str, List[np.ndarray]]: """ Return crystal kinematics systems. @@ -617,7 +623,8 @@ class Crystal(): 'plane': [m[:,3:6] for m in master]} - def relation_operations(self, model: str) -> Tuple[str, Rotation]: + def relation_operations(self, + model: str) -> Tuple[str, Rotation]: """ Crystallographic orientation relationships for phase transformations. diff --git a/python/damask/seeds.py b/python/damask/seeds.py index e6d1f9613..1a3af7a64 100644 --- a/python/damask/seeds.py +++ b/python/damask/seeds.py @@ -10,7 +10,9 @@ from . import util as _util from . import grid_filters as _grid_filters -def from_random(size: _FloatSequence, N_seeds: int, cells: _IntSequence = None, +def from_random(size: _FloatSequence, + N_seeds: int, + cells: _IntSequence = None, rng_seed=None) -> _np.ndarray: """ Place seeds randomly in space. @@ -46,8 +48,12 @@ def from_random(size: _FloatSequence, N_seeds: int, cells: _IntSequence = None, return coords -def from_Poisson_disc(size: _FloatSequence, N_seeds: int, N_candidates: int, distance: float, - periodic: bool = True, rng_seed=None) -> _np.ndarray: +def from_Poisson_disc(size: _FloatSequence, + N_seeds: int, + N_candidates: int, + distance: float, + periodic: bool = True, + rng_seed=None) -> _np.ndarray: """ Place seeds according to a Poisson disc distribution. @@ -99,8 +105,11 @@ def from_Poisson_disc(size: _FloatSequence, N_seeds: int, N_candidates: int, dis return coords -def from_grid(grid, selection: _IntSequence = None, invert_selection: bool = False, - average: bool = False, periodic: bool = True) -> _Tuple[_np.ndarray, _np.ndarray]: +def from_grid(grid, + selection: _IntSequence = None, + invert_selection: bool = False, + average: bool = False, + periodic: bool = True) -> _Tuple[_np.ndarray, _np.ndarray]: """ Create seeds from grid description. diff --git a/python/damask/tensor.py b/python/damask/tensor.py index 4f6cb36ea..73cdd7400 100644 --- a/python/damask/tensor.py +++ b/python/damask/tensor.py @@ -45,7 +45,8 @@ def eigenvalues(T_sym: _np.ndarray) -> _np.ndarray: return _np.linalg.eigvalsh(symmetric(T_sym)) -def eigenvectors(T_sym: _np.ndarray, RHS: bool = False) -> _np.ndarray: +def eigenvectors(T_sym: _np.ndarray, + RHS: bool = False) -> _np.ndarray: """ Eigenvectors of a symmetric tensor. @@ -70,7 +71,8 @@ def eigenvectors(T_sym: _np.ndarray, RHS: bool = False) -> _np.ndarray: return v -def spherical(T: _np.ndarray, tensor: bool = True) -> _np.ndarray: +def spherical(T: _np.ndarray, + tensor: bool = True) -> _np.ndarray: """ Calculate spherical part of a tensor. From 19a73bbf3b50a61ca866c8a9d3d805eb6df36bf5 Mon Sep 17 00:00:00 2001 From: Daniel Otto de Mentock Date: Thu, 27 Jan 2022 12:14:54 +0100 Subject: [PATCH 07/16] [skip ci] adjusted function argument alignment with asterisk --- python/damask/_crystal.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/python/damask/_crystal.py b/python/damask/_crystal.py index c97f75d01..e42622210 100644 --- a/python/damask/_crystal.py +++ b/python/damask/_crystal.py @@ -311,8 +311,8 @@ class Crystal(): + _lattice_points.get(self.lattice if self.lattice == 'hP' else \ self.lattice[-1],None),dtype=float) - def to_lattice(self, - *, direction: np.ndarray = None, + def to_lattice(self, *, + direction: np.ndarray = None, plane: np.ndarray = None) -> np.ndarray: """ Calculate lattice vector corresponding to crystal frame direction or plane normal. @@ -337,8 +337,7 @@ class Crystal(): return np.einsum('il,...l',basis,axis) - def to_frame(self, - *, + def to_frame(self, *, uvw: np.ndarray = None, hkl: np.ndarray = None) -> np.ndarray: """ From e2437ee9b556b72fbed947b9f908a5b38f4164a0 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Thu, 27 Jan 2022 15:29:33 +0100 Subject: [PATCH 08/16] adjusting style + documentation --- python/damask/_crystal.py | 5 ++++- python/damask/mechanics.py | 18 ++++++++++++------ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/python/damask/_crystal.py b/python/damask/_crystal.py index e42622210..0b1c00458 100644 --- a/python/damask/_crystal.py +++ b/python/damask/_crystal.py @@ -119,7 +119,8 @@ class Crystal(): 'α={:.5g}°, β={:.5g}°, γ={:.5g}°'.format(*np.degrees(self.parameters[3:]))]) - def __eq__(self,other): + def __eq__(self, + other: object) -> bool: """ Equal to other. @@ -129,6 +130,8 @@ class Crystal(): Crystal to check for equality. """ + if not isinstance(other, Crystal): + return NotImplemented return self.lattice == other.lattice and \ self.parameters == other.parameters and \ self.family == other.family diff --git a/python/damask/mechanics.py b/python/damask/mechanics.py index 7c1af6c5f..65ec1ef3b 100644 --- a/python/damask/mechanics.py +++ b/python/damask/mechanics.py @@ -122,7 +122,9 @@ def rotation(T: _np.ndarray) -> _rotation.Rotation: return _rotation.Rotation.from_matrix(_polar_decomposition(T,'R')[0]) -def strain(F: _np.ndarray, t: str, m: float) -> _np.ndarray: +def strain(F: _np.ndarray, + t: str, + m: float) -> _np.ndarray: """ Calculate strain tensor (Seth–Hill family). @@ -162,7 +164,8 @@ def strain(F: _np.ndarray, t: str, m: float) -> _np.ndarray: return eps -def stress_Cauchy(P: _np.ndarray, F: _np.ndarray) -> _np.ndarray: +def stress_Cauchy(P: _np.ndarray, + F: _np.ndarray) -> _np.ndarray: """ Calculate the Cauchy stress (true stress). @@ -184,7 +187,8 @@ def stress_Cauchy(P: _np.ndarray, F: _np.ndarray) -> _np.ndarray: return _tensor.symmetric(_np.einsum('...,...ij,...kj',1.0/_np.linalg.det(F),P,F)) -def stress_second_Piola_Kirchhoff(P: _np.ndarray, F: _np.ndarray) -> _np.ndarray: +def stress_second_Piola_Kirchhoff(P: _np.ndarray, + F: _np.ndarray) -> _np.ndarray: """ Calculate the second Piola-Kirchhoff stress. @@ -243,7 +247,8 @@ def stretch_right(T: _np.ndarray) -> _np.ndarray: return _polar_decomposition(T,'U')[0] -def _polar_decomposition(T: _np.ndarray, requested: _Sequence[str]) -> tuple: +def _polar_decomposition(T: _np.ndarray, + requested: _Sequence[str]) -> tuple: """ Perform singular value decomposition. @@ -251,7 +256,7 @@ def _polar_decomposition(T: _np.ndarray, requested: _Sequence[str]) -> tuple: ---------- T : numpy.ndarray, shape (...,3,3) Tensor of which the singular values are computed. - requested : iterable of str + requested : sequence of {'R', 'U', 'V'} Requested outputs: ‘R’ for the rotation tensor, ‘V’ for left stretch tensor and ‘U’ for right stretch tensor. @@ -273,7 +278,8 @@ def _polar_decomposition(T: _np.ndarray, requested: _Sequence[str]) -> tuple: return tuple(output) -def _equivalent_Mises(T_sym: _np.ndarray, s: float) -> _np.ndarray: +def _equivalent_Mises(T_sym: _np.ndarray, + s: float) -> _np.ndarray: """ Base equation for Mises equivalent of a stress or strain tensor. From 609f13c590ea29c0ce835e023d468767be94b8cb Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 29 Jan 2022 18:16:19 +0100 Subject: [PATCH 09/16] Python 3.8 magic: The walrus operator ":=" --- python/damask/_colormap.py | 4 +--- python/damask/_grid.py | 15 +++++---------- python/damask/_table.py | 9 +++------ python/damask/_vtk.py | 5 ++--- python/damask/seeds.py | 5 ++--- python/damask/tensor.py | 3 +-- python/damask/util.py | 3 +-- 7 files changed, 15 insertions(+), 29 deletions(-) diff --git a/python/damask/_colormap.py b/python/damask/_colormap.py index 5c77cf61e..e7982ec52 100644 --- a/python/damask/_colormap.py +++ b/python/damask/_colormap.py @@ -266,9 +266,7 @@ class Colormap(mpl.colors.ListedColormap): l,r = (field[mask].min(),field[mask].max()) if bounds is None else \ (bounds[0],bounds[1]) - delta,avg = r-l,0.5*abs(r+l) - - if abs(delta) * 1e8 <= avg: # delta is similar to numerical noise + if abs(delta := r-l) * 1e8 <= (avg := 0.5*abs(r+l)): # delta is similar to numerical noise l,r = l-0.5*avg*np.sign(delta),r+0.5*avg*np.sign(delta), # extend range to have actual data centered within return Image.fromarray( diff --git a/python/damask/_grid.py b/python/damask/_grid.py index b188873a4..639b4e91f 100644 --- a/python/damask/_grid.py +++ b/python/damask/_grid.py @@ -234,8 +234,7 @@ class Grid: content = f.readlines() for i,line in enumerate(content[:header_length]): items = line.split('#')[0].lower().strip().split() - key = items[0] if items else '' - if key == 'grid': + if (key := items[0] if items else '') == 'grid': cells = np.array([ int(dict(zip(items[1::2],items[2::2]))[i]) for i in ['a','b','c']]) elif key == 'size': size = np.array([float(dict(zip(items[1::2],items[2::2]))[i]) for i in ['x','y','z']]) @@ -247,8 +246,7 @@ class Grid: material = np.empty(int(cells.prod())) # initialize as flat array i = 0 for line in content[header_length:]: - items = line.split('#')[0].split() - if len(items) == 3: + if len(items := line.split('#')[0].split()) == 3: if items[1].lower() == 'of': material_entry = np.ones(int(items[0]))*float(items[2]) elif items[1].lower() == 'to': @@ -813,8 +811,7 @@ class Grid: # materials: 1 """ - valid = ['x','y','z'] - if not set(directions).issubset(valid): + if not set(directions).issubset(valid := ['x', 'y', 'z']): raise ValueError(f'invalid direction {set(directions).difference(valid)} specified') limits: Sequence[Optional[int]] = [None,None] if reflect else [-2,0] @@ -852,8 +849,7 @@ class Grid: Updated grid-based geometry. """ - valid = ['x','y','z'] - if not set(directions).issubset(valid): + if not set(directions).issubset(valid := ['x', 'y', 'z']): raise ValueError(f'invalid direction {set(directions).difference(valid)} specified') @@ -1190,8 +1186,7 @@ class Grid: VTK-based geometry of grain boundary network. """ - valid = ['x','y','z'] - if not set(directions).issubset(valid): + if not set(directions).issubset(valid := ['x', 'y', 'z']): raise ValueError(f'invalid direction {set(directions).difference(valid)} specified') o = [[0, self.cells[0]+1, np.prod(self.cells[:2]+1)+self.cells[0]+1, np.prod(self.cells[:2]+1)], diff --git a/python/damask/_table.py b/python/damask/_table.py index 44a04b40a..bd82dc134 100644 --- a/python/damask/_table.py +++ b/python/damask/_table.py @@ -319,8 +319,7 @@ class Table: data = np.loadtxt(content) shapes = {'eu':3, 'pos':2, 'IQ':1, 'CI':1, 'ID':1, 'intensity':1, 'fit':1} - remainder = data.shape[1]-sum(shapes.values()) - if remainder > 0: # 3.8 can do: if (remainder := data.shape[1]-sum(shapes.values())) > 0 + if (remainder := data.shape[1]-sum(shapes.values())) > 0: shapes['unknown'] = remainder return Table(data,shapes,comments) @@ -376,8 +375,7 @@ class Table: """ dup = self.copy() dup._add_comment(label, data.shape[1:], info) - m = re.match(r'(.*)\[((\d+,)*(\d+))\]',label) - if m: + if m := re.match(r'(.*)\[((\d+,)*(\d+))\]',label): key = m.group(1) idx = np.ravel_multi_index(tuple(map(int,m.group(2).split(","))), self.shapes[key]) @@ -495,8 +493,7 @@ class Table: """ labels_ = [labels] if isinstance(labels,str) else labels.copy() for i,l in enumerate(labels_): - m = re.match(r'(.*)\[((\d+,)*(\d+))\]',l) - if m: + if m := re.match(r'(.*)\[((\d+,)*(\d+))\]',l): idx = np.ravel_multi_index(tuple(map(int,m.group(2).split(','))), self.shapes[m.group(1)]) labels_[i] = f'{1+idx}_{m.group(1)}' diff --git a/python/damask/_vtk.py b/python/damask/_vtk.py index 601608520..8247bb6c8 100644 --- a/python/damask/_vtk.py +++ b/python/damask/_vtk.py @@ -22,7 +22,7 @@ class VTK: High-level interface to VTK. """ - def __init__(self, + def __init__(self, vtk_data: vtk.vtkDataSet): """ New spatial visualization. @@ -202,8 +202,7 @@ class VTK: """ if not os.path.isfile(fname): # vtk has a strange error handling raise FileNotFoundError(f'No such file: {fname}') - ext = Path(fname).suffix - if ext == '.vtk' or dataset_type is not None: + if (ext := Path(fname).suffix) == '.vtk' or dataset_type is not None: reader = vtk.vtkGenericDataObjectReader() reader.SetFileName(str(fname)) if dataset_type is None: diff --git a/python/damask/seeds.py b/python/damask/seeds.py index 1a3af7a64..47e34d871 100644 --- a/python/damask/seeds.py +++ b/python/damask/seeds.py @@ -92,10 +92,9 @@ def from_Poisson_disc(size: _FloatSequence, tree = _spatial.cKDTree(coords[:s],boxsize=size) if periodic else \ _spatial.cKDTree(coords[:s]) distances = tree.query(candidates)[0] - best = distances.argmax() - if distances[best] > distance: # require minimum separation + if distances.max() > distance: # require minimum separation i = 0 - coords[s] = candidates[best] # maximum separation to existing point cloud + coords[s] = candidates[distances.argmax()] # maximum separation to existing point cloud s += 1 progress.update(s) diff --git a/python/damask/tensor.py b/python/damask/tensor.py index 73cdd7400..0e2118002 100644 --- a/python/damask/tensor.py +++ b/python/damask/tensor.py @@ -66,8 +66,7 @@ def eigenvectors(T_sym: _np.ndarray, """ (u,v) = _np.linalg.eigh(symmetric(T_sym)) - if RHS: - v[_np.linalg.det(v) < 0.0,:,2] *= -1.0 + if RHS: v[_np.linalg.det(v) < 0.0,:,2] *= -1.0 return v diff --git a/python/damask/util.py b/python/damask/util.py index e1db35007..c042e4dd4 100644 --- a/python/damask/util.py +++ b/python/damask/util.py @@ -753,9 +753,8 @@ class ProgressBar: iteration: int) -> None: fraction = (iteration+1) / self.total - filled_length = int(self.bar_length * fraction) - if filled_length > int(self.bar_length * self.fraction_last) or \ + if filled_length := int(self.bar_length * fraction) > int(self.bar_length * self.fraction_last) or \ datetime.datetime.now() - self.time_last_update > datetime.timedelta(seconds=10): self.time_last_update = datetime.datetime.now() bar = '█' * filled_length + '░' * (self.bar_length - filled_length) From 03b0decfcfe6d0fa35f7b1222d77ba202af4d402 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 29 Jan 2022 18:32:04 +0100 Subject: [PATCH 10/16] starting to configure mypy --- python/mypy.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python/mypy.ini b/python/mypy.ini index 01001daa6..5ef04daee 100644 --- a/python/mypy.ini +++ b/python/mypy.ini @@ -1,3 +1,5 @@ +[mypy] +warn_redundant_casts = True [mypy-scipy.*] ignore_missing_imports = True [mypy-h5py.*] From ce4591fa29f4066451d6b3e3cde4e5a5ff1c28a3 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 29 Jan 2022 19:10:12 +0100 Subject: [PATCH 11/16] silence prospector on Python 3.9 --- python/damask/_colormap.py | 2 +- python/damask/_vtk.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/damask/_colormap.py b/python/damask/_colormap.py index e7982ec52..9d9776821 100644 --- a/python/damask/_colormap.py +++ b/python/damask/_colormap.py @@ -484,7 +484,7 @@ class Colormap(mpl.colors.ListedColormap): 'gnuplot', 'gnuplot2', 'CMRmap', 'cubehelix', 'brg', 'gist_rainbow', 'rainbow', 'jet', 'nipy_spectral', 'gist_ncar']} - _predefined_DAMASK = {'orientation': {'low': [0.933334,0.878432,0.878431], + _predefined_DAMASK = {'orientation': {'low': [0.933334,0.878432,0.878431], # noqa 'high': [0.250980,0.007843,0.000000]}, 'strain': {'low': [0.941177,0.941177,0.870588], 'high': [0.266667,0.266667,0.000000]}, diff --git a/python/damask/_vtk.py b/python/damask/_vtk.py index 8247bb6c8..3d9e5011c 100644 --- a/python/damask/_vtk.py +++ b/python/damask/_vtk.py @@ -455,7 +455,7 @@ class VTK: width = tk.winfo_screenwidth() height = tk.winfo_screenheight() tk.destroy() - except Exception as e: + except Exception: width = 1024 height = 768 From df96110733c85da52615c8f1b05794c0ac95e2cc Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 29 Jan 2022 22:38:17 +0100 Subject: [PATCH 12/16] some suggestions from prospector/pylint --- python/damask/_colormap.py | 18 +++++++++--------- python/damask/_grid.py | 24 ++++++++++++------------ python/damask/_table.py | 22 +++++++++++----------- python/damask/tensor.py | 2 +- python/damask/util.py | 26 +++++++++++++------------- 5 files changed, 46 insertions(+), 46 deletions(-) diff --git a/python/damask/_colormap.py b/python/damask/_colormap.py index 9d9776821..005cf80d6 100644 --- a/python/damask/_colormap.py +++ b/python/damask/_colormap.py @@ -267,7 +267,7 @@ class Colormap(mpl.colors.ListedColormap): (bounds[0],bounds[1]) if abs(delta := r-l) * 1e8 <= (avg := 0.5*abs(r+l)): # delta is similar to numerical noise - l,r = l-0.5*avg*np.sign(delta),r+0.5*avg*np.sign(delta), # extend range to have actual data centered within + l,r = (l-0.5*avg*np.sign(delta),r+0.5*avg*np.sign(delta)) # extend range to have actual data centered within return Image.fromarray( (np.dstack(( @@ -301,7 +301,7 @@ class Colormap(mpl.colors.ListedColormap): >>> damask.Colormap.from_predefined('stress').reversed() """ - rev = super(Colormap,self).reversed(name) + rev = super().reversed(name) return Colormap(np.array(rev.colors),rev.name[:-4] if rev.name.endswith('_r_r') else rev.name) @@ -436,11 +436,11 @@ class Colormap(mpl.colors.ListedColormap): 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 + return msh_sat[2] + + 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) @@ -453,9 +453,9 @@ class Colormap(mpl.colors.ListedColormap): 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: + if lo[1] < 0.05 < hi[1]: lo[2] = adjust_hue(hi,lo) - elif lo[1] > 0.05 and hi[1] < 0.05: + elif hi[1] < 0.05 < lo[1]: hi[2] = adjust_hue(lo,hi) return (1.0 - frac) * lo + frac * hi diff --git a/python/damask/_grid.py b/python/damask/_grid.py index 639b4e91f..0b3a067e2 100644 --- a/python/damask/_grid.py +++ b/python/damask/_grid.py @@ -33,7 +33,7 @@ class Grid: material: np.ndarray, size: FloatSequence, origin: FloatSequence = np.zeros(3), - comments: Union[str, Sequence[str]] = []): + comments: Union[str, Sequence[str]] = None): """ New geometry definition for grid solvers. @@ -53,7 +53,7 @@ class Grid: self.material = material self.size = size # type: ignore self.origin = origin # type: ignore - self.comments = comments # type: ignore + self.comments = [] if comments is None else comments # type: ignore def __repr__(self) -> str: @@ -106,14 +106,14 @@ class Grid: material: np.ndarray): if len(material.shape) != 3: raise ValueError(f'invalid material shape {material.shape}') - elif material.dtype not in np.sctypes['float'] and material.dtype not in np.sctypes['int']: + if material.dtype not in np.sctypes['float'] and material.dtype not in np.sctypes['int']: raise TypeError(f'invalid material data type {material.dtype}') - else: - self._material = np.copy(material) - if self.material.dtype in np.sctypes['float'] and \ - np.all(self.material == self.material.astype(int).astype(float)): - self._material = self.material.astype(int) + self._material = np.copy(material) + + if self.material.dtype in np.sctypes['float'] and \ + np.all(self.material == self.material.astype(int).astype(float)): + self._material = self.material.astype(int) @property @@ -126,8 +126,8 @@ class Grid: size: FloatSequence): if len(size) != 3 or any(np.array(size) < 0): raise ValueError(f'invalid size {size}') - else: - self._size = np.array(size) + + self._size = np.array(size) @property def origin(self) -> np.ndarray: @@ -139,8 +139,8 @@ class Grid: origin: FloatSequence): if len(origin) != 3: raise ValueError(f'invalid origin {origin}') - else: - self._origin = np.array(origin) + + self._origin = np.array(origin) @property def comments(self) -> List[str]: diff --git a/python/damask/_table.py b/python/damask/_table.py index bd82dc134..1572c4f76 100644 --- a/python/damask/_table.py +++ b/python/damask/_table.py @@ -14,7 +14,7 @@ class Table: def __init__(self, data: np.ndarray, - shapes: dict, + shapes: dict, comments: Union[str, list] = None): """ New spreadsheet. @@ -526,10 +526,10 @@ class Table: """ if self.shapes != other.shapes or not self.data.columns.equals(other.data.columns): raise KeyError('Labels or shapes or order do not match') - else: - dup = self.copy() - dup.data = dup.data.append(other.data,ignore_index=True) - return dup + + dup = self.copy() + dup.data = dup.data.append(other.data,ignore_index=True) + return dup def join(self, @@ -552,12 +552,12 @@ class Table: """ if set(self.shapes) & set(other.shapes) or self.data.shape[0] != other.data.shape[0]: raise KeyError('Duplicated keys or row count mismatch') - else: - dup = self.copy() - dup.data = dup.data.join(other.data) - for key in other.shapes: - dup.shapes[key] = other.shapes[key] - return dup + + dup = self.copy() + dup.data = dup.data.join(other.data) + for key in other.shapes: + dup.shapes[key] = other.shapes[key] + return dup def save(self, diff --git a/python/damask/tensor.py b/python/damask/tensor.py index 0e2118002..63eb15b99 100644 --- a/python/damask/tensor.py +++ b/python/damask/tensor.py @@ -64,7 +64,7 @@ def eigenvectors(T_sym: _np.ndarray, associated eigenvalues. """ - (u,v) = _np.linalg.eigh(symmetric(T_sym)) + _,v = _np.linalg.eigh(symmetric(T_sym)) if RHS: v[_np.linalg.det(v) < 0.0,:,2] *= -1.0 return v diff --git a/python/damask/util.py b/python/damask/util.py index c042e4dd4..0cf6606fb 100644 --- a/python/damask/util.py +++ b/python/damask/util.py @@ -7,7 +7,7 @@ import subprocess import shlex import re import fractions -import collections.abc as abc +from collections import abc from functools import reduce from typing import Union, Tuple, Iterable, Callable, Dict, List, Any, Literal, Optional from pathlib import Path @@ -77,7 +77,7 @@ def srepr(msg, hasattr(msg, '__iter__'))): return glue.join(str(x) for x in msg) else: - return msg if isinstance(msg,str) else repr(msg) + return msg if isinstance(msg,str) else repr(msg) def emph(msg) -> str: @@ -230,15 +230,15 @@ def show_progress(iterable: Iterable, """ if isinstance(iterable,abc.Sequence): - if N_iter is None: - N = len(iterable) - else: - raise ValueError('N_iter given for sequence') + if N_iter is None: + N = len(iterable) + else: + raise ValueError('N_iter given for sequence') else: - if N_iter is None: - raise ValueError('N_iter not given') - else: - N = N_iter + if N_iter is None: + raise ValueError('N_iter not given') + + N = N_iter if N <= 1: for item in iterable: @@ -454,7 +454,7 @@ def shapeshifter(fro: Tuple[int, ...], """ - if not len(fro) and not len(to): return () + if len(fro) == 0 and len(to) == 0: return () beg = dict(left ='(^.*\\b)', right='(^.*?\\b)') @@ -462,8 +462,8 @@ def shapeshifter(fro: Tuple[int, ...], right='(.*?\\b)') end = dict(left ='(.*?$)', right='(.*$)') - fro = (1,) if not len(fro) else fro - to = (1,) if not len(to) else to + fro = (1,) if len(fro) == 0 else fro + to = (1,) if len(to) == 0 else to try: match = re.match(beg[mode] +f',{sep[mode]}'.join(map(lambda x: f'{x}' From 9ce4573b12660fcbcb7be092df4fe829ccfff3b8 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sat, 29 Jan 2022 23:16:57 +0100 Subject: [PATCH 13/16] docstring polishing --- python/damask/_grid.py | 13 +++++-------- python/damask/util.py | 25 +++++++++++++++++-------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/python/damask/_grid.py b/python/damask/_grid.py index 0b3a067e2..b08f99757 100644 --- a/python/damask/_grid.py +++ b/python/damask/_grid.py @@ -786,9 +786,8 @@ class Grid: Parameters ---------- - directions : (sequence of) str + directions : (sequence of) {'x', 'y', 'z'} Direction(s) along which the grid is mirrored. - Valid entries are 'x', 'y', 'z'. reflect : bool, optional Reflect (include) outermost layers. Defaults to False. @@ -832,16 +831,14 @@ class Grid: def flip(self, - directions: Union[Literal['x', 'y', 'z'], - Sequence[Literal['x', 'y', 'z']]]) -> 'Grid': + directions: Sequence[str]) -> 'Grid': """ Flip grid along given directions. Parameters ---------- - directions : (sequence of) str + directions : (sequence of) {'x', 'y', 'z'} Direction(s) along which the grid is flipped. - Valid entries are 'x', 'y', 'z'. Returns ------- @@ -1176,9 +1173,9 @@ class Grid: ---------- periodic : bool, optional Assume grid to be periodic. Defaults to True. - directions : (sequence of) string, optional + directions : (sequence of) {'x', 'y', 'z'}, optional Direction(s) along which the boundaries are determined. - Valid entries are 'x', 'y', 'z'. Defaults to 'xyz'. + Defaults to 'xyz'. Returns ------- diff --git a/python/damask/util.py b/python/damask/util.py index 0cf6606fb..0bbc1e7b5 100644 --- a/python/damask/util.py +++ b/python/damask/util.py @@ -305,16 +305,20 @@ def project_equal_angle(vector: np.ndarray, normalize : bool Ensure unit length of input vector. Defaults to True. keepdims : bool - Maintain three-dimensional output coordinates. Defaults to False. - Two-dimensional output uses right-handed frame spanned by - the next and next-next axis relative to the projection direction, - e.g. x-y when projecting along z and z-x when projecting along y. + Maintain three-dimensional output coordinates. + Defaults to False. Returns ------- coordinates : numpy.ndarray, shape (...,2 | 3) Projected coordinates. + Notes + ----- + Two-dimensional output uses right-handed frame spanned by + the next and next-next axis relative to the projection direction, + e.g. x-y when projecting along z and z-x when projecting along y. + Examples -------- >>> import damask @@ -349,16 +353,21 @@ def project_equal_area(vector: np.ndarray, normalize : bool Ensure unit length of input vector. Defaults to True. keepdims : bool - Maintain three-dimensional output coordinates. Defaults to False. - Two-dimensional output uses right-handed frame spanned by - the next and next-next axis relative to the projection direction, - e.g. x-y when projecting along z and z-x when projecting along y. + Maintain three-dimensional output coordinates. + Defaults to False. Returns ------- coordinates : numpy.ndarray, shape (...,2 | 3) Projected coordinates. + Notes + ----- + Two-dimensional output uses right-handed frame spanned by + the next and next-next axis relative to the projection direction, + e.g. x-y when projecting along z and z-x when projecting along y. + + Examples -------- >>> import damask From a479c2971478325b2677c2000f40e6d7a30f5c5b Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 30 Jan 2022 15:46:26 +0100 Subject: [PATCH 14/16] not used --- python/damask/_grid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/damask/_grid.py b/python/damask/_grid.py index b08f99757..f5c06df1b 100644 --- a/python/damask/_grid.py +++ b/python/damask/_grid.py @@ -4,7 +4,7 @@ import warnings import multiprocessing as mp from functools import partial import typing -from typing import Union, Optional, TextIO, List, Sequence, Literal +from typing import Union, Optional, TextIO, List, Sequence from pathlib import Path import numpy as np From 26cd8a46c2e10e6416705713a4ea273a4fd0eb30 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Sun, 30 Jan 2022 22:36:30 +0100 Subject: [PATCH 15/16] consistent style --- python/damask/grid_filters.py | 43 ++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/python/damask/grid_filters.py b/python/damask/grid_filters.py index d9d658d0b..e2178a4b6 100644 --- a/python/damask/grid_filters.py +++ b/python/damask/grid_filters.py @@ -20,7 +20,9 @@ import numpy as _np from ._typehints import FloatSequence as _FloatSequence, IntSequence as _IntSequence -def _ks(size: _FloatSequence, cells: _IntSequence, first_order: bool = False) -> _np.ndarray: +def _ks(size: _FloatSequence, + cells: _IntSequence, + first_order: bool = False) -> _np.ndarray: """ Get wave numbers operator. @@ -47,7 +49,8 @@ def _ks(size: _FloatSequence, cells: _IntSequence, first_order: bool = False) -> return _np.stack(_np.meshgrid(k_sk,k_sj,k_si,indexing = 'ij'), axis=-1) -def curl(size: _FloatSequence, f: _np.ndarray) -> _np.ndarray: +def curl(size: _FloatSequence, + f: _np.ndarray) -> _np.ndarray: u""" Calculate curl of a vector or tensor field in Fourier space. @@ -78,7 +81,8 @@ def curl(size: _FloatSequence, f: _np.ndarray) -> _np.ndarray: return _np.fft.irfftn(curl_,axes=(0,1,2),s=f.shape[:3]) -def divergence(size: _FloatSequence, f: _np.ndarray) -> _np.ndarray: +def divergence(size: _FloatSequence, + f: _np.ndarray) -> _np.ndarray: u""" Calculate divergence of a vector or tensor field in Fourier space. @@ -105,7 +109,8 @@ def divergence(size: _FloatSequence, f: _np.ndarray) -> _np.ndarray: return _np.fft.irfftn(div_,axes=(0,1,2),s=f.shape[:3]) -def gradient(size: _FloatSequence, f: _np.ndarray) -> _np.ndarray: +def gradient(size: _FloatSequence, + f: _np.ndarray) -> _np.ndarray: u""" Calculate gradient of a scalar or vector field in Fourier space. @@ -163,7 +168,8 @@ def coordinates0_point(cells: _IntSequence, axis = -1) -def displacement_fluct_point(size: _FloatSequence, F: _np.ndarray) -> _np.ndarray: +def displacement_fluct_point(size: _FloatSequence, + F: _np.ndarray) -> _np.ndarray: """ Cell center displacement field from fluctuation part of the deformation gradient field. @@ -195,7 +201,8 @@ def displacement_fluct_point(size: _FloatSequence, F: _np.ndarray) -> _np.ndarra return _np.fft.irfftn(displacement,axes=(0,1,2),s=F.shape[:3]) -def displacement_avg_point(size: _FloatSequence, F: _np.ndarray) -> _np.ndarray: +def displacement_avg_point(size: _FloatSequence, + F: _np.ndarray) -> _np.ndarray: """ Cell center displacement field from average part of the deformation gradient field. @@ -216,7 +223,8 @@ def displacement_avg_point(size: _FloatSequence, F: _np.ndarray) -> _np.ndarray: return _np.einsum('ml,ijkl->ijkm',F_avg - _np.eye(3),coordinates0_point(F.shape[:3],size)) -def displacement_point(size: _FloatSequence, F: _np.ndarray) -> _np.ndarray: +def displacement_point(size: _FloatSequence, + F: _np.ndarray) -> _np.ndarray: """ Cell center displacement field from deformation gradient field. @@ -236,7 +244,9 @@ def displacement_point(size: _FloatSequence, F: _np.ndarray) -> _np.ndarray: return displacement_avg_point(size,F) + displacement_fluct_point(size,F) -def coordinates_point(size: _FloatSequence, F: _np.ndarray, origin: _FloatSequence = _np.zeros(3)) -> _np.ndarray: +def coordinates_point(size: _FloatSequence, + F: _np.ndarray, + origin: _FloatSequence = _np.zeros(3)) -> _np.ndarray: """ Cell center positions. @@ -335,7 +345,8 @@ def coordinates0_node(cells: _IntSequence, axis = -1) -def displacement_fluct_node(size: _FloatSequence, F: _np.ndarray) -> _np.ndarray: +def displacement_fluct_node(size: _FloatSequence, + F: _np.ndarray) -> _np.ndarray: """ Nodal displacement field from fluctuation part of the deformation gradient field. @@ -355,7 +366,8 @@ def displacement_fluct_node(size: _FloatSequence, F: _np.ndarray) -> _np.ndarray return point_to_node(displacement_fluct_point(size,F)) -def displacement_avg_node(size: _FloatSequence, F: _np.ndarray) -> _np.ndarray: +def displacement_avg_node(size: _FloatSequence, + F: _np.ndarray) -> _np.ndarray: """ Nodal displacement field from average part of the deformation gradient field. @@ -376,7 +388,8 @@ def displacement_avg_node(size: _FloatSequence, F: _np.ndarray) -> _np.ndarray: return _np.einsum('ml,ijkl->ijkm',F_avg - _np.eye(3),coordinates0_node(F.shape[:3],size)) -def displacement_node(size: _FloatSequence, F: _np.ndarray) -> _np.ndarray: +def displacement_node(size: _FloatSequence, + F: _np.ndarray) -> _np.ndarray: """ Nodal displacement field from deformation gradient field. @@ -396,7 +409,9 @@ def displacement_node(size: _FloatSequence, F: _np.ndarray) -> _np.ndarray: return displacement_avg_node(size,F) + displacement_fluct_node(size,F) -def coordinates_node(size: _FloatSequence, F: _np.ndarray, origin: _FloatSequence = _np.zeros(3)) -> _np.ndarray: +def coordinates_node(size: _FloatSequence, + F: _np.ndarray, + origin: _FloatSequence = _np.zeros(3)) -> _np.ndarray: """ Nodal positions. @@ -526,7 +541,9 @@ def coordinates0_valid(coordinates0: _np.ndarray) -> bool: return False -def regrid(size: _FloatSequence, F: _np.ndarray, cells: _IntSequence) -> _np.ndarray: +def regrid(size: _FloatSequence, + F: _np.ndarray, + cells: _IntSequence) -> _np.ndarray: """ Return mapping from coordinates in deformed configuration to a regular grid. From 3105b2c978548eb0965a8cd4b814c2927ddca1ec Mon Sep 17 00:00:00 2001 From: Daniel Otto de Mentock Date: Mon, 31 Jan 2022 12:40:29 +0100 Subject: [PATCH 16/16] added missing return type to grid.get_grain_boundaries function --- python/damask/_grid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/damask/_grid.py b/python/damask/_grid.py index f5c06df1b..8a9a4bbd9 100644 --- a/python/damask/_grid.py +++ b/python/damask/_grid.py @@ -1165,7 +1165,7 @@ class Grid: def get_grain_boundaries(self, periodic: bool = True, - directions: Sequence[str] = 'xyz'): + directions: Sequence[str] = 'xyz') -> VTK: """ Create VTK unstructured grid containing grain boundaries.