From 5558c301fa1cb940fd26f2c1d1004cf69a599c83 Mon Sep 17 00:00:00 2001 From: Daniel Otto de Mentock Date: Mon, 6 Dec 2021 14:22:52 +0100 Subject: [PATCH 1/6] added fist typehints for _grid module --- python/damask/_grid.py | 158 ++++++++++++++++++++-------------- python/damask/grid_filters.py | 12 +-- 2 files changed, 101 insertions(+), 69 deletions(-) diff --git a/python/damask/_grid.py b/python/damask/_grid.py index 135cc6b66..99991a534 100644 --- a/python/damask/_grid.py +++ b/python/damask/_grid.py @@ -3,6 +3,8 @@ import copy import warnings import multiprocessing as mp from functools import partial +from typing import Union, Optional, TextIO, List, Sequence +from pathlib import Path import numpy as np import pandas as pd @@ -13,7 +15,7 @@ from . import VTK from . import util from . import grid_filters from . import Rotation - +from . import Table class Grid: """ @@ -25,7 +27,11 @@ class Grid: the physical size. """ - def __init__(self,material,size,origin=[0.0,0.0,0.0],comments=[]): + def __init__(self, + material: np.ndarray, + size, + origin = [0.0,0.0,0.0], + comments = []): """ New geometry definition for grid solvers. @@ -43,12 +49,12 @@ class Grid: """ self.material = material - self.size = size - self.origin = origin + self._size = size + self._origin = origin self.comments = comments - def __repr__(self): + def __repr__(self) -> str: """Basic information on grid definition.""" mat_min = np.nanmin(self.material) mat_max = np.nanmax(self.material) @@ -62,14 +68,14 @@ class Grid: ]) - def __copy__(self): + def __copy__(self) -> "Grid": """Create deep copy.""" return copy.deepcopy(self) copy = __copy__ - def __eq__(self,other): + def __eq__(self, other): """ Test equality of other. @@ -79,6 +85,8 @@ class Grid: Grid to compare self against. """ + if not isinstance(other, Grid): + raise TypeError return (np.allclose(other.size,self.size) and np.allclose(other.origin,self.origin) and np.all(other.cells == self.cells) @@ -86,15 +94,15 @@ class Grid: @property - def material(self): + def material(self) -> np.ndarray: """Material indices.""" return self._material @material.setter - def material(self,material): + 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'] + np.sctypes['int']: + elif 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) @@ -105,53 +113,53 @@ class Grid: @property - def size(self): + def size(self) -> np.ndarray: """Physical size of grid in meter.""" return self._size @size.setter - def size(self,size): + def size(self, size: Union[Sequence[float], np.ndarray]): if len(size) != 3 or any(np.array(size) < 0): raise ValueError(f'invalid size {size}') else: self._size = np.array(size) @property - def origin(self): + def origin(self) -> Union[Sequence[float], np.ndarray]: """Coordinates of grid origin in meter.""" return self._origin @origin.setter - def origin(self,origin): + def origin(self, origin: np.ndarray): if len(origin) != 3: raise ValueError(f'invalid origin {origin}') else: self._origin = np.array(origin) @property - def comments(self): + def comments(self) -> List[str]: """Comments, e.g. history of operations.""" return self._comments @comments.setter - def comments(self,comments): + def comments(self, comments: Union[str, Sequence[str]]): self._comments = [str(c) for c in comments] if isinstance(comments,list) else [str(comments)] @property - def cells(self): + def cells(self) -> np.ndarray: """Number of cells in x,y,z direction.""" return np.asarray(self.material.shape) @property - def N_materials(self): + def N_materials(self) -> int: """Number of (unique) material indices within grid.""" return np.unique(self.material).size @staticmethod - def load(fname): + def load(fname: Union[str, Path]) -> "Grid": """ Load from VTK image data file. @@ -198,15 +206,17 @@ class Grid: """ warnings.warn('Support for ASCII-based geom format will be removed in DAMASK 3.1.0', DeprecationWarning,2) - try: + if isinstance(fname, (str, Path)): f = open(fname) - except TypeError: + elif isinstance(fname, TextIO): f = fname + else: + raise TypeError f.seek(0) try: - header_length,keyword = f.readline().split()[:2] - header_length = int(header_length) + header_length_,keyword = f.readline().split()[:2] + header_length = int(header_length_) except ValueError: header_length,keyword = (-1, 'invalid') if not keyword.startswith('head') or header_length < 3: @@ -215,10 +225,10 @@ class Grid: comments = [] content = f.readlines() for i,line in enumerate(content[:header_length]): - items = line.split('#')[0].lower().strip().split() + items: List[str] = line.split('#')[0].lower().strip().split() key = items[0] if items else '' if key == 'grid': - cells = np.array([ int(dict(zip(items[1::2],items[2::2]))[i]) for i in ['a','b','c']]) + 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']]) elif key == 'origin': @@ -226,19 +236,19 @@ class Grid: else: comments.append(line.strip()) - material = np.empty(cells.prod()) # initialize as flat array + 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 items[1].lower() == 'of': - items = np.ones(int(items[0]))*float(items[2]) + if items[1].lower() == 'of': + material_entry = np.ones(int(items[0]))*float(items[2]) elif items[1].lower() == 'to': - items = np.linspace(int(items[0]),int(items[2]), + material_entry = np.linspace(int(items[0]),int(items[2]), abs(int(items[2])-int(items[0]))+1,dtype=float) - else: items = list(map(float,items)) - else: items = list(map(float,items)) - material[i:i+len(items)] = items + else: material_entry = list(map(float, items)) + else: material_entry = list(map(float, items)) + material[i:i+len(material_entry)] = material_entry i += len(items) if i != cells.prod(): @@ -251,7 +261,7 @@ class Grid: @staticmethod - def load_Neper(fname): + def load_Neper(fname: Union[str, Path]) -> "Grid": """ Load from Neper VTK file. @@ -276,10 +286,10 @@ class Grid: @staticmethod - def load_DREAM3D(fname, - feature_IDs=None,cell_data=None, - phases='Phases',Euler_angles='EulerAngles', - base_group=None): + def load_DREAM3D(fname: str, + feature_IDs: str = None, cell_data: str = None, + phases: str = 'Phases', Euler_angles: str = 'EulerAngles', + base_group: str = None) -> "Grid": """ Load DREAM.3D (HDF5) file. @@ -339,7 +349,7 @@ class Grid: @staticmethod - def from_table(table,coordinates,labels): + def from_table(table: Table, coordinates: str, labels: Union[str, Sequence[str]]) -> "Grid": """ Create grid from ASCII table. @@ -372,11 +382,16 @@ class Grid: @staticmethod - def _find_closest_seed(seeds, weights, point): + 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 - def from_Laguerre_tessellation(cells,size,seeds,weights,material=None,periodic=True): + def from_Laguerre_tessellation(cells, + size, + seeds, + weights, + material = None, + periodic = True): """ Create grid from Laguerre tessellation. @@ -412,7 +427,6 @@ class Grid: seeds_p = seeds coords = grid_filters.coordinates0_point(cells,size).reshape(-1,3) - pool = mp.Pool(int(os.environ.get('OMP_NUM_THREADS',4))) result = pool.map_async(partial(Grid._find_closest_seed,seeds_p,weights_p), coords) pool.close() @@ -428,7 +442,11 @@ class Grid: @staticmethod - def from_Voronoi_tessellation(cells,size,seeds,material=None,periodic=True): + def from_Voronoi_tessellation(cells: np.ndarray, + size: Union[Sequence[float], np.ndarray], + seeds: np.ndarray, + material: np.ndarray = None, + periodic: bool = True) -> "Grid": """ Create grid from Voronoi tessellation. @@ -509,7 +527,12 @@ class Grid: @staticmethod - def from_minimal_surface(cells,size,surface,threshold=0.0,periods=1,materials=(0,1)): + def from_minimal_surface(cells: np.ndarray, + size: Union[Sequence[float], np.ndarray], + surface: str, + threshold: float = 0.0, + periods: int = 1, + materials: tuple = (0,1)) -> "Grid": """ Create grid from definition of triply periodic minimal surface. @@ -595,7 +618,7 @@ class Grid: ) - def save(self,fname,compress=True): + def save(self, fname: Union[str, Path], compress: bool = True): """ Save as VTK image data file. @@ -614,7 +637,7 @@ class Grid: v.save(fname if str(fname).endswith('.vti') else str(fname)+'.vti',parallel=False,compress=compress) - def save_ASCII(self,fname): + def save_ASCII(self, fname: Union[str, TextIO]): """ Save as geom file. @@ -649,8 +672,14 @@ class Grid: VTK.from_rectilinear_grid(self.cells,self.size,self.origin).show() - def add_primitive(self,dimension,center,exponent, - fill=None,R=Rotation(),inverse=False,periodic=True): + def add_primitive(self, + dimension: np.ndarray, + center: np.ndarray, + exponent: Union[np.ndarray, float], + fill: int = None, + R: Rotation = Rotation(), + inverse: bool = False, + periodic: bool = True) -> "Grid": """ Insert a primitive geometric object at a given position. @@ -734,7 +763,7 @@ class Grid: ) - def mirror(self,directions,reflect=False): + def mirror(self, directions: Sequence[str], reflect: bool = False) -> "Grid": """ Mirror grid along given directions. @@ -769,7 +798,7 @@ class Grid: if not set(directions).issubset(valid): raise ValueError(f'invalid direction {set(directions).difference(valid)} specified') - limits = [None,None] if reflect else [-2,0] + limits: Sequence[Optional[int]] = [None,None] if reflect else [-2,0] mat = self.material.copy() if 'x' in directions: @@ -786,7 +815,7 @@ class Grid: ) - def flip(self,directions): + def flip(self, directions: Sequence[str]) -> "Grid": """ Flip grid along given directions. @@ -815,7 +844,7 @@ class Grid: ) - def scale(self,cells,periodic=True): + def scale(self, cells: np.ndarray, periodic: bool = True) -> "Grid": """ Scale grid to new cells. @@ -859,7 +888,7 @@ class Grid: ) - def clean(self,stencil=3,selection=None,periodic=True): + def clean(self, stencil: int = 3, selection: Sequence[float] = None, periodic: bool = True) -> "Grid": """ Smooth grid by selecting most frequent material index within given stencil at each location. @@ -878,7 +907,7 @@ class Grid: Updated grid-based geometry. """ - def mostFrequent(arr,selection=None): + def mostFrequent(arr, selection = None): me = arr[arr.size//2] if selection is None or me in selection: unique, inverse = np.unique(arr, return_inverse=True) @@ -899,7 +928,7 @@ class Grid: ) - def renumber(self): + def renumber(self) -> "Grid": """ Renumber sorted material indices as 0,...,N-1. @@ -918,7 +947,7 @@ class Grid: ) - def rotate(self,R,fill=None): + def rotate(self, R: Rotation, fill: Union[int, float] = None) -> "Grid": """ Rotate grid (pad if required). @@ -956,7 +985,7 @@ class Grid: ) - def canvas(self,cells=None,offset=None,fill=None): + def canvas(self, cells = None, offset = None, fill = None): """ Crop or enlarge/pad grid. @@ -1008,7 +1037,7 @@ class Grid: ) - def substitute(self,from_material,to_material): + def substitute(self, from_material: np.ndarray, to_material: np.ndarray) -> "Grid": """ Substitute material indices. @@ -1025,7 +1054,7 @@ class Grid: Updated grid-based geometry. """ - def mp(entry,mapper): + def mp(entry, mapper): return mapper[entry] if entry in mapper else entry mp = np.vectorize(mp) @@ -1038,7 +1067,7 @@ class Grid: ) - def sort(self): + def sort(self) -> "Grid": """ Sort material indices such that min(material) is located at (0,0,0). @@ -1060,7 +1089,11 @@ class Grid: ) - def vicinity_offset(self,vicinity=1,offset=None,trigger=[],periodic=True): + def vicinity_offset(self, + vicinity: int = 1, + offset: int = None, + trigger: Sequence[int] = [], + periodic: bool = True) -> "Grid": """ Offset material index of points in the vicinity of xxx. @@ -1088,8 +1121,7 @@ class Grid: Updated grid-based geometry. """ - def tainted_neighborhood(stencil,trigger): - + def tainted_neighborhood(stencil, trigger): me = stencil[stencil.shape[0]//2] return np.any(stencil != me if len(trigger) == 0 else np.in1d(stencil,np.array(list(set(trigger) - {me})))) @@ -1108,7 +1140,7 @@ class Grid: ) - def get_grain_boundaries(self,periodic=True,directions='xyz'): + def get_grain_boundaries(self, periodic = True, directions = 'xyz'): """ Create VTK unstructured grid containing grain boundaries. diff --git a/python/damask/grid_filters.py b/python/damask/grid_filters.py index 42b5a16c4..1b83e99f8 100644 --- a/python/damask/grid_filters.py +++ b/python/damask/grid_filters.py @@ -130,9 +130,9 @@ def gradient(size: _np.ndarray, f: _np.ndarray) -> _np.ndarray: return _np.fft.irfftn(grad_,axes=(0,1,2),s=f.shape[:3]) -def coordinates0_point(cells: Union[ _np.ndarray,Sequence[int]], - size: _np.ndarray, - origin: _np.ndarray = _np.zeros(3)) -> _np.ndarray: +def coordinates0_point(cells: Union[_np.ndarray, Sequence[int]], + size: Union[_np.ndarray, Sequence[float]], + origin: Union[_np.ndarray, Sequence[float]] = _np.zeros(3)) -> _np.ndarray: """ Cell center positions (undeformed). @@ -305,9 +305,9 @@ def cellsSizeOrigin_coordinates0_point(coordinates0: _np.ndarray, return (cells,size,origin) -def coordinates0_node(cells: Union[_np.ndarray,Sequence[int]], - size: _np.ndarray, - origin: _np.ndarray = _np.zeros(3)) -> _np.ndarray: +def coordinates0_node(cells: Union[_np.ndarray, Sequence[int]], + size: Union[_np.ndarray, Sequence[int]], + origin: Union[_np.ndarray, Sequence[int]] = _np.zeros(3)) -> _np.ndarray: """ Nodal positions (undeformed). From 1de12bb40289c2a2c8845559145c0d283f501df5 Mon Sep 17 00:00:00 2001 From: Daniel Otto de Mentock Date: Mon, 6 Dec 2021 15:48:19 +0100 Subject: [PATCH 2/6] removed direct attribute assignments for size and origin --- python/damask/_grid.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/damask/_grid.py b/python/damask/_grid.py index 99991a534..1bda19d4e 100644 --- a/python/damask/_grid.py +++ b/python/damask/_grid.py @@ -49,8 +49,8 @@ class Grid: """ self.material = material - self._size = size - self._origin = origin + self.size = size + self.origin = origin self.comments = comments From 7c7c3926b783201c6f2464efad553137cf6a1437 Mon Sep 17 00:00:00 2001 From: Daniel Otto de Mentock Date: Mon, 6 Dec 2021 15:48:57 +0100 Subject: [PATCH 3/6] added array conversion to ambiguous types in grid_filters.coordinates0_point function --- python/damask/grid_filters.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/damask/grid_filters.py b/python/damask/grid_filters.py index 1b83e99f8..9d0e055c8 100644 --- a/python/damask/grid_filters.py +++ b/python/damask/grid_filters.py @@ -151,8 +151,8 @@ def coordinates0_point(cells: Union[_np.ndarray, Sequence[int]], Undeformed cell center coordinates. """ - start = origin + size/_np.array(cells)*.5 - end = origin + size - size/_np.array(cells)*.5 + start = _np.array(origin) + size/_np.array(cells)*.5 + end = _np.array(origin) + _np.array(size) - size/_np.array(cells)*.5 return _np.stack(_np.meshgrid(_np.linspace(start[0],end[0],cells[0]), _np.linspace(start[1],end[1],cells[1]), From e60d41d5e4d0674342334579bb42b98502313285 Mon Sep 17 00:00:00 2001 From: Daniel Otto de Mentock Date: Wed, 5 Jan 2022 14:06:06 +0100 Subject: [PATCH 4/6] merge with current development branch --- python/damask/_grid.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/damask/_grid.py b/python/damask/_grid.py index 1bda19d4e..a6340ce9b 100644 --- a/python/damask/_grid.py +++ b/python/damask/_grid.py @@ -205,7 +205,7 @@ class Grid: Grid-based geometry from file. """ - warnings.warn('Support for ASCII-based geom format will be removed in DAMASK 3.1.0', DeprecationWarning,2) + warnings.warn('Support for ASCII-based geom format will be removed in DAMASK 3.0.0', DeprecationWarning,2) if isinstance(fname, (str, Path)): f = open(fname) elif isinstance(fname, TextIO): @@ -652,7 +652,7 @@ class Grid: Compress geometry with 'x of y' and 'a to b'. """ - warnings.warn('Support for ASCII-based geom format will be removed in DAMASK 3.1.0', DeprecationWarning,2) + warnings.warn('Support for ASCII-based geom format will be removed in DAMASK 3.0.0', DeprecationWarning,2) header = [f'{len(self.comments)+4} header'] + self.comments \ + ['grid a {} b {} c {}'.format(*self.cells), 'size x {} y {} z {}'.format(*self.size), From 2c1231a806bfcefa8f8a09102fb9eda531545398 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 12 Jan 2022 20:34:29 +0100 Subject: [PATCH 5/6] using best practices from grid_filters --- python/damask/_grid.py | 255 ++++++++++++++++++++------------------ python/damask/_vtk.py | 2 +- python/tests/test_Grid.py | 21 +++- 3 files changed, 153 insertions(+), 125 deletions(-) diff --git a/python/damask/_grid.py b/python/damask/_grid.py index a6340ce9b..a65f4eb30 100644 --- a/python/damask/_grid.py +++ b/python/damask/_grid.py @@ -3,6 +3,7 @@ import copy import warnings import multiprocessing as mp from functools import partial +import typing from typing import Union, Optional, TextIO, List, Sequence from pathlib import Path @@ -16,6 +17,7 @@ from . import util from . import grid_filters from . import Rotation from . import Table +from ._typehints import FloatSequence, IntSequence class Grid: """ @@ -29,9 +31,9 @@ class Grid: def __init__(self, material: np.ndarray, - size, - origin = [0.0,0.0,0.0], - comments = []): + size: FloatSequence, + origin: FloatSequence = np.zeros(3), + comments: Union[str, Sequence[str]] = []): """ New geometry definition for grid solvers. @@ -40,18 +42,18 @@ class Grid: material : numpy.ndarray of shape (:,:,:) Material indices. The shape of the material array defines the number of cells. - size : list or numpy.ndarray of shape (3) + size : sequence of float, len (3) Physical size of grid in meter. - origin : list or numpy.ndarray of shape (3), optional - Coordinates of grid origin in meter. - comments : list of str, optional + origin : sequence of float, len (3), optional + Coordinates of grid origin in meter. Defaults to [0.0,0.0,0.0]. + comments : (list of) str, optional Comments, e.g. history of operations. """ self.material = material - self.size = size - self.origin = origin - self.comments = comments + self.size = size # type: ignore + self.origin = origin # type: ignore + self.comments = comments # type: ignore def __repr__(self) -> str: @@ -75,7 +77,7 @@ class Grid: copy = __copy__ - def __eq__(self, other): + def __eq__(self, other: object) -> bool: """ Test equality of other. @@ -86,8 +88,8 @@ class Grid: """ if not isinstance(other, Grid): - raise TypeError - return (np.allclose(other.size,self.size) + return NotImplemented + return bool(np.allclose(other.size,self.size) and np.allclose(other.origin,self.origin) and np.all(other.cells == self.cells) and np.all(other.material == self.material)) @@ -118,19 +120,19 @@ class Grid: return self._size @size.setter - def size(self, size: Union[Sequence[float], np.ndarray]): + def size(self, size: FloatSequence): if len(size) != 3 or any(np.array(size) < 0): raise ValueError(f'invalid size {size}') else: self._size = np.array(size) @property - def origin(self) -> Union[Sequence[float], np.ndarray]: + def origin(self) -> np.ndarray: """Coordinates of grid origin in meter.""" return self._origin @origin.setter - def origin(self, origin: np.ndarray): + def origin(self, origin: FloatSequence): if len(origin) != 3: raise ValueError(f'invalid origin {origin}') else: @@ -165,7 +167,7 @@ class Grid: Parameters ---------- - fname : str or or pathlib.Path + fname : str or pathlib.Path Grid file to read. Valid extension is .vti, which will be appended if not given. @@ -186,8 +188,9 @@ class Grid: comments=comments) + @typing. no_type_check @staticmethod - def load_ASCII(fname): + def load_ASCII(fname)-> "Grid": """ Load from geom file. @@ -225,10 +228,10 @@ class Grid: comments = [] content = f.readlines() for i,line in enumerate(content[:header_length]): - items: List[str] = line.split('#')[0].lower().strip().split() + items = line.split('#')[0].lower().strip().split() key = items[0] if items else '' if key == 'grid': - cells = np.array([int(dict(zip(items[1::2],items[2::2]))[i]) for i in ['a','b','c']]) + 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']]) elif key == 'origin': @@ -236,7 +239,7 @@ class Grid: else: comments.append(line.strip()) - material = np.empty(int(cells.prod())) # initialize as flat array + material = np.empty(int(cells.prod())) # initialize as flat array i = 0 for line in content[header_length:]: items = line.split('#')[0].split() @@ -267,7 +270,7 @@ class Grid: Parameters ---------- - fname : str, pathlib.Path, or file handle + fname : str or pathlib.Path Geometry file to read. Returns @@ -286,7 +289,7 @@ class Grid: @staticmethod - def load_DREAM3D(fname: str, + def load_DREAM3D(fname: Union[str, Path], feature_IDs: str = None, cell_data: str = None, phases: str = 'Phases', Euler_angles: str = 'EulerAngles', base_group: str = None) -> "Grid": @@ -300,24 +303,24 @@ class Grid: Parameters ---------- - fname : str + fname : str or or pathlib.Path Filename of the DREAM.3D (HDF5) file. - feature_IDs : str + feature_IDs : str, optional Name of the dataset containing the mapping between cells and grain-wise data. Defaults to 'None', in which case cell-wise data is used. - cell_data : str + cell_data : str, optional Name of the group (folder) containing cell-wise data. Defaults to None in wich case it is automatically detected. - phases : str + phases : str, optional Name of the dataset containing the phase ID. It is not used for grain-wise data, i.e. when feature_IDs is not None. Defaults to 'Phases'. - Euler_angles : str + Euler_angles : str, optional Name of the dataset containing the crystallographic orientation as Euler angles in radians It is not used for grain-wise data, i.e. when feature_IDs is not None. Defaults to 'EulerAngles'. - base_group : str + base_group : str, optional Path to the group (folder) that contains geometry (_SIMPL_GEOMETRY), and grain- or cell-wise data. Defaults to None, in which case it is set as the path that contains _SIMPL_GEOMETRY/SPACING. @@ -349,7 +352,9 @@ class Grid: @staticmethod - def from_table(table: Table, coordinates: str, labels: Union[str, Sequence[str]]) -> "Grid": + def from_table(table: Table, + coordinates: str, + labels: Union[str, Sequence[str]]) -> "Grid": """ Create grid from ASCII table. @@ -360,7 +365,7 @@ class Grid: coordinates : str Label of the vector column containing the spatial coordinates. Need to be ordered (1./x fast, 3./z slow). - labels : str or list of str + labels : (list of) str Label(s) of the columns containing the material definition. Each unique combination of values results in one material ID. @@ -386,26 +391,26 @@ class Grid: return np.argmin(np.sum((np.broadcast_to(point,(len(seeds),3))-seeds)**2,axis=1) - weights) @staticmethod - def from_Laguerre_tessellation(cells, - size, - seeds, - weights, - material = None, - periodic = True): + def from_Laguerre_tessellation(cells: IntSequence, + size: FloatSequence, + seeds: np.ndarray, + weights: FloatSequence, + material: IntSequence = None, + periodic: bool = True): """ Create grid from Laguerre tessellation. Parameters ---------- - cells : int numpy.ndarray of shape (3) + cells : sequence of int, len (3) Number of cells in x,y,z direction. - size : list or numpy.ndarray of shape (3) + size : sequence of float, len (3) Physical size of the grid in meter. seeds : numpy.ndarray of shape (:,3) Position of the seed points in meter. All points need to lay within the box. - weights : numpy.ndarray of shape (seeds.shape[0]) + weights : sequence of float, len (seeds.shape[0]) Weights of the seeds. Setting all weights to 1.0 gives a standard Voronoi tessellation. - material : numpy.ndarray of shape (seeds.shape[0]), optional + material : sequence of int, len (seeds.shape[0]), optional Material ID of the seeds. Defaults to None, in which case materials are consecutively numbered. periodic : Boolean, optional @@ -427,6 +432,7 @@ class Grid: seeds_p = seeds coords = grid_filters.coordinates0_point(cells,size).reshape(-1,3) + pool = mp.Pool(int(os.environ.get('OMP_NUM_THREADS',4))) result = pool.map_async(partial(Grid._find_closest_seed,seeds_p,weights_p), coords) pool.close() @@ -435,30 +441,30 @@ class Grid: if periodic: material_ %= len(weights) - return Grid(material = material_ if material is None else material[material_], + return Grid(material = material_ if material is None else np.array(material)[material_], size = size, comments = util.execution_stamp('Grid','from_Laguerre_tessellation'), ) @staticmethod - def from_Voronoi_tessellation(cells: np.ndarray, - size: Union[Sequence[float], np.ndarray], + def from_Voronoi_tessellation(cells: IntSequence, + size: FloatSequence, seeds: np.ndarray, - material: np.ndarray = None, + material: IntSequence = None, periodic: bool = True) -> "Grid": """ Create grid from Voronoi tessellation. Parameters ---------- - cells : int numpy.ndarray of shape (3) + cells : sequence of int, len (3) Number of cells in x,y,z direction. - size : list or numpy.ndarray of shape (3) + size : sequence of float, len (3) Physical size of the grid in meter. seeds : numpy.ndarray of shape (:,3) Position of the seed points in meter. All points need to lay within the box. - material : numpy.ndarray of shape (seeds.shape[0]), optional + material : sequence of int, len (seeds.shape[0]), optional Material ID of the seeds. Defaults to None, in which case materials are consecutively numbered. periodic : Boolean, optional @@ -478,7 +484,7 @@ class Grid: except TypeError: material_ = tree.query(coords, n_jobs = int(os.environ.get('OMP_NUM_THREADS',4)))[1] # scipy <1.6 - return Grid(material = (material_ if material is None else material[material_]).reshape(cells), + return Grid(material = (material_ if material is None else np.array(material)[material_]).reshape(cells), size = size, comments = util.execution_stamp('Grid','from_Voronoi_tessellation'), ) @@ -527,20 +533,20 @@ class Grid: @staticmethod - def from_minimal_surface(cells: np.ndarray, - size: Union[Sequence[float], np.ndarray], + def from_minimal_surface(cells: IntSequence, + size: FloatSequence, surface: str, threshold: float = 0.0, periods: int = 1, - materials: tuple = (0,1)) -> "Grid": + materials: IntSequence = (0,1)) -> "Grid": """ Create grid from definition of triply periodic minimal surface. Parameters ---------- - cells : int numpy.ndarray of shape (3) + cells : sequence of int, len (3) Number of cells in x,y,z direction. - size : list or numpy.ndarray of shape (3) + size : sequence of float, len (3) Physical size of the grid in meter. surface : str Type of the minimal surface. See notes for details. @@ -548,7 +554,7 @@ class Grid: Threshold of the minimal surface. Defaults to 0.0. periods : integer, optional. Number of periods per unit cell. Defaults to 1. - materials : (int, int), optional + materials : sequence of int, len (2) Material IDs. Defaults to (0,1). Returns @@ -589,22 +595,21 @@ class Grid: >>> import numpy as np >>> import damask - >>> damask.Grid.from_minimal_surface(np.array([64]*3,int),np.ones(3), - ... 'Gyroid') - cells a b c: 64 x 64 x 64 - size x y z: 1.0 x 1.0 x 1.0 - origin x y z: 0.0 0.0 0.0 + >>> damask.Grid.from_minimal_surface([64]*3,np.ones(3)*1.e-4,'Gyroid') + cells : 64 x 64 x 64 + size : 0.0001 x 0.0001 x 0.0001 / m³ + origin: 0.0 0.0 0.0 / m # materials: 2 Minimal surface of 'Neovius' type. non-default material IDs. >>> import numpy as np >>> import damask - >>> damask.Grid.from_minimal_surface(np.array([80]*3,int),np.ones(3), + >>> damask.Grid.from_minimal_surface([80]*3,np.ones(3)*5.e-4, ... 'Neovius',materials=(1,5)) - cells a b c: 80 x 80 x 80 - size x y z: 1.0 x 1.0 x 1.0 - origin x y z: 0.0 0.0 0.0 + cells : 80 x 80 x 80 + size : 0.0005 x 0.0005 x 0.0005 / m³ + origin: 0.0 0.0 0.0 / m # materials: 2 (min: 1, max: 5) """ @@ -634,7 +639,7 @@ class Grid: v.add(self.material.flatten(order='F'),'material') v.add_comments(self.comments) - v.save(fname if str(fname).endswith('.vti') else str(fname)+'.vti',parallel=False,compress=compress) + v.save(fname,parallel=False,compress=compress) def save_ASCII(self, fname: Union[str, TextIO]): @@ -667,15 +672,15 @@ class Grid: header='\n'.join(header), fmt=format_string, comments='') - def show(self): + def show(self) -> None: """Show on screen.""" VTK.from_rectilinear_grid(self.cells,self.size,self.origin).show() def add_primitive(self, - dimension: np.ndarray, - center: np.ndarray, - exponent: Union[np.ndarray, float], + dimension: Union[FloatSequence, IntSequence], + center: Union[FloatSequence, IntSequence], + exponent: Union[FloatSequence, float], fill: int = None, R: Rotation = Rotation(), inverse: bool = False, @@ -685,14 +690,15 @@ class Grid: Parameters ---------- - dimension : int or float numpy.ndarray of shape (3) - Dimension (diameter/side length) of the primitive. If given as - integers, cell centers are addressed. - If given as floats, coordinates are addressed. - center : int or float numpy.ndarray of shape (3) - Center of the primitive. If given as integers, cell centers are addressed. - If given as floats, coordinates in space are addressed. - exponent : numpy.ndarray of shape (3) or float + dimension : sequence of int or float, len (3) + Dimension (diameter/side length) of the primitive. + If given as integers, cell centers are addressed. + If given as floats, physical coordinates are addressed. + center : sequence of int or float, len (3) + Center of the primitive. + If given as integers, cell centers are addressed. + If given as floats, physical coordinates are addressed. + exponent : float or sequence of float, len (3) Exponents for the three axes. 0 gives octahedron (ǀxǀ^(2^0) + ǀyǀ^(2^0) + ǀzǀ^(2^0) < 1) 1 gives sphere (ǀxǀ^(2^1) + ǀyǀ^(2^1) + ǀzǀ^(2^1) < 1) @@ -719,9 +725,9 @@ class Grid: >>> import damask >>> g = damask.Grid(np.zeros([64]*3,int), np.ones(3)*1e-4) >>> g.add_primitive(np.ones(3)*5e-5,np.ones(3)*5e-5,1) - cells a b c: 64 x 64 x 64 - size x y z: 0.0001 x 0.0001 x 0.0001 - origin x y z: 0.0 0.0 0.0 + cells : 64 x 64 x 64 + size : 0.0001 x 0.0001 x 0.0001 / m³ + origin: 0.0 0.0 0.0 / m # materials: 2 Add a cube at the origin. @@ -730,9 +736,9 @@ class Grid: >>> import damask >>> g = damask.Grid(np.zeros([64]*3,int), np.ones(3)*1e-4) >>> g.add_primitive(np.ones(3,int)*32,np.zeros(3),np.inf) - cells a b c: 64 x 64 x 64 - size x y z: 0.0001 x 0.0001 x 0.0001 - origin x y z: 0.0 0.0 0.0 + cells : 64 x 64 x 64 + size : 0.0001 x 0.0001 x 0.0001 / m³ + origin: 0.0 0.0 0.0 / m # materials: 2 """ @@ -769,7 +775,7 @@ class Grid: Parameters ---------- - directions : iterable containing str + directions : (sequence of) str Direction(s) along which the grid is mirrored. Valid entries are 'x', 'y', 'z'. reflect : bool, optional @@ -788,9 +794,9 @@ class Grid: >>> import damask >>> g = damask.Grid(np.zeros([32]*3,int), np.ones(3)*1e-4) >>> g.mirror('xy',True) - cells a b c: 64 x 64 x 32 - size x y z: 0.0002 x 0.0002 x 0.0001 - origin x y z: 0.0 0.0 0.0 + cells : 64 x 64 x 32 + size : 0.0002 x 0.0002 x 0.0001 / m³ + origin: 0.0 0.0 0.0 / m # materials: 1 """ @@ -821,7 +827,7 @@ class Grid: Parameters ---------- - directions : iterable containing str + directions : (sequence of) str Direction(s) along which the grid is flipped. Valid entries are 'x', 'y', 'z'. @@ -844,13 +850,13 @@ class Grid: ) - def scale(self, cells: np.ndarray, periodic: bool = True) -> "Grid": + def scale(self, cells: IntSequence, periodic: bool = True) -> "Grid": """ Scale grid to new cells. Parameters ---------- - cells : numpy.ndarray of shape (3) + cells : sequence of int, len (3) Number of cells in x,y,z direction. periodic : Boolean, optional Assume grid to be periodic. Defaults to True. @@ -868,9 +874,9 @@ class Grid: >>> import damask >>> g = damask.Grid(np.zeros([32]*3,int),np.ones(3)*1e-4) >>> g.scale(g.cells*2) - cells a b c: 64 x 64 x 64 - size x y z: 0.0001 x 0.0001 x 0.0001 - origin x y z: 0.0 0.0 0.0 + cells : 64 x 64 x 64 + size : 0.0001 x 0.0001 x 0.0001 / m³ + origin: 0.0 0.0 0.0 / m # materials: 1 """ @@ -888,7 +894,10 @@ class Grid: ) - def clean(self, stencil: int = 3, selection: Sequence[float] = None, periodic: bool = True) -> "Grid": + def clean(self, + stencil: int = 3, + selection: IntSequence = None, + periodic: bool = True) -> "Grid": """ Smooth grid by selecting most frequent material index within given stencil at each location. @@ -896,7 +905,7 @@ class Grid: ---------- stencil : int, optional Size of smoothing stencil. - selection : list, optional + selection : sequence of int, optional Field values that can be altered. Defaults to all. periodic : Boolean, optional Assume grid to be periodic. Defaults to True. @@ -907,7 +916,7 @@ class Grid: Updated grid-based geometry. """ - def mostFrequent(arr, selection = None): + def mostFrequent(arr: np.ndarray, selection = None): me = arr[arr.size//2] if selection is None or me in selection: unique, inverse = np.unique(arr, return_inverse=True) @@ -947,7 +956,7 @@ class Grid: ) - def rotate(self, R: Rotation, fill: Union[int, float] = None) -> "Grid": + def rotate(self, R: Rotation, fill: int = None) -> "Grid": """ Rotate grid (pad if required). @@ -955,7 +964,7 @@ class Grid: ---------- R : damask.Rotation Rotation to apply to the grid. - fill : int or float, optional + fill : int, optional Material index to fill the corners. Defaults to material.max() + 1. Returns @@ -985,17 +994,20 @@ class Grid: ) - def canvas(self, cells = None, offset = None, fill = None): + def canvas(self, + cells: IntSequence = None, + offset: IntSequence = None, + fill: int = None) -> "Grid": """ Crop or enlarge/pad grid. Parameters ---------- - cells : numpy.ndarray of shape (3) + cells : sequence of int, len (3), optional Number of cells x,y,z direction. - offset : numpy.ndarray of shape (3) + offset : sequence of int, len (3), optional Offset (measured in cells) from old to new grid [0,0,0]. - fill : int or float, optional + fill : int, optional Material index to fill the background. Defaults to material.max() + 1. Returns @@ -1010,42 +1022,43 @@ class Grid: >>> import numpy as np >>> import damask >>> g = damask.Grid(np.zeros([32]*3,int),np.ones(3)*1e-4) - >>> g.canvas(np.array([32,32,16],int)) - cells a b c: 33 x 32 x 16 - size x y z: 0.0001 x 0.0001 x 5e-05 - origin x y z: 0.0 0.0 0.0 + >>> g.canvas([32,32,16]) + cells : 33 x 32 x 16 + size : 0.0001 x 0.0001 x 5e-05 / m³ + origin: 0.0 0.0 0.0 / m # materials: 1 """ - if offset is None: offset = 0 + offset_ = np.array(offset,int) if offset is not None else np.zeros(3,int) + cells_ = np.array(cells,int) if cells is not None else self.cells if fill is None: fill = np.nanmax(self.material) + 1 dtype = float if int(fill) != fill or self.material.dtype in np.sctypes['float'] else int - canvas = np.full(self.cells if cells is None else cells,fill,dtype) + canvas = np.full(cells_,fill,dtype) - LL = np.clip( offset, 0,np.minimum(self.cells, cells+offset)) - UR = np.clip( offset+cells, 0,np.minimum(self.cells, cells+offset)) - ll = np.clip(-offset, 0,np.minimum( cells,self.cells-offset)) - ur = np.clip(-offset+self.cells,0,np.minimum( cells,self.cells-offset)) + LL = np.clip( offset_, 0,np.minimum(self.cells, cells_+offset_)) + UR = np.clip( offset_+cells_, 0,np.minimum(self.cells, cells_+offset_)) + ll = np.clip(-offset_, 0,np.minimum( cells_,self.cells-offset_)) + ur = np.clip(-offset_+self.cells,0,np.minimum( cells_,self.cells-offset_)) canvas[ll[0]:ur[0],ll[1]:ur[1],ll[2]:ur[2]] = self.material[LL[0]:UR[0],LL[1]:UR[1],LL[2]:UR[2]] return Grid(material = canvas, size = self.size/self.cells*np.asarray(canvas.shape), - origin = self.origin+offset*self.size/self.cells, + origin = self.origin+offset_*self.size/self.cells, comments = self.comments+[util.execution_stamp('Grid','canvas')], ) - def substitute(self, from_material: np.ndarray, to_material: np.ndarray) -> "Grid": + def substitute(self, from_material: IntSequence, to_material: IntSequence) -> "Grid": """ Substitute material indices. Parameters ---------- - from_material : iterable of ints + from_material : sequence of int Material indices to be substituted. - to_material : iterable of ints + to_material : sequence of int New material indices. Returns @@ -1092,7 +1105,7 @@ class Grid: def vicinity_offset(self, vicinity: int = 1, offset: int = None, - trigger: Sequence[int] = [], + trigger: IntSequence = [], periodic: bool = True) -> "Grid": """ Offset material index of points in the vicinity of xxx. @@ -1109,7 +1122,7 @@ class Grid: offset : int, optional Offset (positive or negative) to tag material indices, defaults to material.max()+1. - trigger : list of ints, optional + trigger : sequence of int, optional List of material indices that trigger a change. Defaults to [], meaning that any different neighbor triggers a change. periodic : Boolean, optional @@ -1121,7 +1134,7 @@ class Grid: Updated grid-based geometry. """ - def tainted_neighborhood(stencil, trigger): + def tainted_neighborhood(stencil: np.ndarray, trigger): me = stencil[stencil.shape[0]//2] return np.any(stencil != me if len(trigger) == 0 else np.in1d(stencil,np.array(list(set(trigger) - {me})))) @@ -1140,7 +1153,7 @@ class Grid: ) - def get_grain_boundaries(self, periodic = True, directions = 'xyz'): + def get_grain_boundaries(self, periodic: bool = True, directions: Sequence[str] = 'xyz'): """ Create VTK unstructured grid containing grain boundaries. @@ -1148,7 +1161,7 @@ class Grid: ---------- periodic : Boolean, optional Assume grid to be periodic. Defaults to True. - directions : iterable containing str, optional + directions : (sequence of) string, optional Direction(s) along which the boundaries are determined. Valid entries are 'x', 'y', 'z'. Defaults to 'xyz'. diff --git a/python/damask/_vtk.py b/python/damask/_vtk.py index cbf70c37a..95cea4542 100644 --- a/python/damask/_vtk.py +++ b/python/damask/_vtk.py @@ -419,7 +419,7 @@ class VTK: return writer.GetOutputString() - def show(self): + def show(self) -> None: """ Render. diff --git a/python/tests/test_Grid.py b/python/tests/test_Grid.py index 3538e3dd8..2b9ca22f4 100644 --- a/python/tests/test_Grid.py +++ b/python/tests/test_Grid.py @@ -237,12 +237,27 @@ class TestGrid: modified) - def test_canvas(self,default): + def test_canvas_extend(self,default): cells = default.cells - grid_add = np.random.randint(0,30,(3)) - modified = default.canvas(cells + grid_add) + cells_add = np.random.randint(0,30,(3)) + modified = default.canvas(cells + cells_add) assert np.all(modified.material[:cells[0],:cells[1],:cells[2]] == default.material) + @pytest.mark.parametrize('sign',[+1,-1]) + @pytest.mark.parametrize('extra_offset',[0,-1]) + def test_canvas_move_out(self,sign,extra_offset): + g = Grid(np.zeros(np.random.randint(3,30,(3)),int),np.ones(3)) + o = sign*np.ones(3)*g.cells.min() +extra_offset*sign + if extra_offset == 0: + assert np.all(g.canvas(offset=o).material == 1) + else: + assert np.all(np.unique(g.canvas(offset=o).material) == (0,1)) + + def test_canvas_cells(self,default): + g = Grid(np.zeros(np.random.randint(3,30,(3)),int),np.ones(3)) + cells = np.random.randint(1,30,(3)) + offset = np.random.randint(-30,30,(3)) + assert np.all(g.canvas(cells,offset).cells == cells) @pytest.mark.parametrize('center1,center2',[(np.random.random(3)*.5,np.random.random()*8), (np.random.randint(4,8,(3)),np.random.randint(9,12,(3)))]) From 3acabcdc7feac3c585e9c1b997e9f56700f3b34f Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 12 Jan 2022 23:13:38 +0100 Subject: [PATCH 6/6] docstring adjustments --- python/damask/_colormap.py | 2 +- python/damask/_grid.py | 22 +++++++++++----------- python/damask/_orientation.py | 12 ++++++------ python/damask/_result.py | 2 +- python/damask/_rotation.py | 22 +++++++++++----------- python/damask/_vtk.py | 6 +++--- python/damask/seeds.py | 14 +++++++------- python/tests/test_seeds.py | 2 +- 8 files changed, 41 insertions(+), 41 deletions(-) diff --git a/python/damask/_colormap.py b/python/damask/_colormap.py index 2da92ae3f..2c7f01d94 100644 --- a/python/damask/_colormap.py +++ b/python/damask/_colormap.py @@ -205,7 +205,7 @@ class Colormap(mpl.colors.ListedColormap): Returns ------- - color : np.ndarray, shape(...,4) + color : numpy.ndarray, shape(...,4) RGBA values of interpolated color(s). Examples diff --git a/python/damask/_grid.py b/python/damask/_grid.py index a65f4eb30..5006e1b40 100644 --- a/python/damask/_grid.py +++ b/python/damask/_grid.py @@ -39,7 +39,7 @@ class Grid: Parameters ---------- - material : numpy.ndarray of shape (:,:,:) + material : numpy.ndarray, shape (:,:,:) Material indices. The shape of the material array defines the number of cells. size : sequence of float, len (3) @@ -406,14 +406,14 @@ class Grid: Number of cells in x,y,z direction. size : sequence of float, len (3) Physical size of the grid in meter. - seeds : numpy.ndarray of shape (:,3) + seeds : numpy.ndarray, shape (:,3) Position of the seed points in meter. All points need to lay within the box. weights : sequence of float, len (seeds.shape[0]) Weights of the seeds. Setting all weights to 1.0 gives a standard Voronoi tessellation. material : sequence of int, len (seeds.shape[0]), optional Material ID of the seeds. Defaults to None, in which case materials are consecutively numbered. - periodic : Boolean, optional + periodic : bool, optional Assume grid to be periodic. Defaults to True. Returns @@ -462,12 +462,12 @@ class Grid: Number of cells in x,y,z direction. size : sequence of float, len (3) Physical size of the grid in meter. - seeds : numpy.ndarray of shape (:,3) + seeds : numpy.ndarray, shape (:,3) Position of the seed points in meter. All points need to lay within the box. material : sequence of int, len (seeds.shape[0]), optional Material ID of the seeds. Defaults to None, in which case materials are consecutively numbered. - periodic : Boolean, optional + periodic : bool, optional Assume grid to be periodic. Defaults to True. Returns @@ -706,10 +706,10 @@ class Grid: Fill value for primitive. Defaults to material.max()+1. R : damask.Rotation, optional Rotation of primitive. Defaults to no rotation. - inverse : Boolean, optional + inverse : bool, optional Retain original materials within primitive and fill outside. Defaults to False. - periodic : Boolean, optional + periodic : bool, optional Assume grid to be periodic. Defaults to True. Returns @@ -858,7 +858,7 @@ class Grid: ---------- cells : sequence of int, len (3) Number of cells in x,y,z direction. - periodic : Boolean, optional + periodic : bool, optional Assume grid to be periodic. Defaults to True. Returns @@ -907,7 +907,7 @@ class Grid: Size of smoothing stencil. selection : sequence of int, optional Field values that can be altered. Defaults to all. - periodic : Boolean, optional + periodic : bool, optional Assume grid to be periodic. Defaults to True. Returns @@ -1125,7 +1125,7 @@ class Grid: trigger : sequence of int, optional List of material indices that trigger a change. Defaults to [], meaning that any different neighbor triggers a change. - periodic : Boolean, optional + periodic : bool, optional Assume grid to be periodic. Defaults to True. Returns @@ -1159,7 +1159,7 @@ class Grid: Parameters ---------- - periodic : Boolean, optional + periodic : bool, optional Assume grid to be periodic. Defaults to True. directions : (sequence of) string, optional Direction(s) along which the boundaries are determined. diff --git a/python/damask/_orientation.py b/python/damask/_orientation.py index 2fc2a7d4a..b7a43e0fb 100644 --- a/python/damask/_orientation.py +++ b/python/damask/_orientation.py @@ -393,8 +393,8 @@ class Orientation(Rotation,Crystal): Returns ------- - in : numpy.ndarray of quaternion.shape - Boolean array indicating whether Rodrigues-Frank vector falls into fundamental zone. + in : numpy.ndarray of bool, quaternion.shape + Whether Rodrigues-Frank vector falls into fundamental zone. Notes ----- @@ -437,8 +437,8 @@ class Orientation(Rotation,Crystal): Returns ------- - in : numpy.ndarray of quaternion.shape - Boolean array indicating whether Rodrigues-Frank vector falls into disorientation FZ. + in : numpy.ndarray of bool, quaternion.shape + Whether Rodrigues-Frank vector falls into disorientation FZ. References ---------- @@ -651,8 +651,8 @@ class Orientation(Rotation,Crystal): Returns ------- - in : numpy.ndarray of shape (...) - Boolean array indicating whether vector falls into SST. + in : numpy.ndarray, shape (...) + Whether vector falls into SST. """ if not isinstance(vector,np.ndarray) or vector.shape[-1] != 3: diff --git a/python/damask/_result.py b/python/damask/_result.py index f47a7da80..c87b51a89 100644 --- a/python/damask/_result.py +++ b/python/damask/_result.py @@ -1817,7 +1817,7 @@ class Result: output : (list of) str, optional Names of the datasets to export to the file. Defaults to '*', in which case all datasets are exported. - overwrite : boolean, optional + overwrite : bool, optional Overwrite existing configuration files. Defaults to False. diff --git a/python/damask/_rotation.py b/python/damask/_rotation.py index ac921d70a..fd19ec31b 100644 --- a/python/damask/_rotation.py +++ b/python/damask/_rotation.py @@ -671,7 +671,7 @@ class Rotation: ---------- q : numpy.ndarray of shape (...,4) Unit quaternion (q_0, q_1, q_2, q_3) in positive real hemisphere, i.e. ǀqǀ = 1, q_0 ≥ 0. - accept_homomorph : boolean, optional + accept_homomorph : bool, optional Allow homomorphic variants, i.e. q_0 < 0 (negative real hemisphere). Defaults to False. P : int ∈ {-1,1}, optional @@ -706,7 +706,7 @@ class Rotation: phi : numpy.ndarray of shape (...,3) Euler angles (φ_1 ∈ [0,2π], ϕ ∈ [0,π], φ_2 ∈ [0,2π]) or (φ_1 ∈ [0,360], ϕ ∈ [0,180], φ_2 ∈ [0,360]) if degrees == True. - degrees : boolean, optional + degrees : bool, optional Euler angles are given in degrees. Defaults to False. Notes @@ -737,9 +737,9 @@ class Rotation: axis_angle : numpy.ndarray of shape (...,4) Axis and angle (n_1, n_2, n_3, ω) with ǀnǀ = 1 and ω ∈ [0,π] or ω ∈ [0,180] if degrees == True. - degrees : boolean, optional + degrees : bool, optional Angle ω is given in degrees. Defaults to False. - normalize: boolean, optional + normalize: bool, optional Allow ǀnǀ ≠ 1. Defaults to False. P : int ∈ {-1,1}, optional Sign convention. Defaults to -1. @@ -773,9 +773,9 @@ class Rotation: ---------- basis : numpy.ndarray of shape (...,3,3) Three three-dimensional lattice basis vectors. - orthonormal : boolean, optional + orthonormal : bool, optional Basis is strictly orthonormal, i.e. is free of stretch components. Defaults to True. - reciprocal : boolean, optional + reciprocal : bool, optional Basis vectors are given in reciprocal (instead of real) space. Defaults to False. """ @@ -851,7 +851,7 @@ class Rotation: ---------- rho : numpy.ndarray of shape (...,4) Rodrigues–Frank vector (n_1, n_2, n_3, tan(ω/2)) with ǀnǀ = 1 and ω ∈ [0,π]. - normalize : boolean, optional + normalize : bool, optional Allow ǀnǀ ≠ 1. Defaults to False. P : int ∈ {-1,1}, optional Sign convention. Defaults to -1. @@ -977,9 +977,9 @@ class Rotation: N : integer, optional Number of discrete orientations to be sampled from the given ODF. Defaults to 500. - degrees : boolean, optional + degrees : bool, optional Euler space grid coordinates are in degrees. Defaults to True. - fractions : boolean, optional + fractions : bool, optional ODF values correspond to volume fractions, not probability densities. Defaults to True. rng_seed: {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional @@ -1033,7 +1033,7 @@ class Rotation: Standard deviation of (Gaussian) misorientation distribution. N : int, optional Number of samples. Defaults to 500. - degrees : boolean, optional + degrees : bool, optional sigma is given in degrees. Defaults to True. rng_seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional A seed to initialize the BitGenerator. @@ -1072,7 +1072,7 @@ class Rotation: Defaults to 0. N : int, optional Number of samples. Defaults to 500. - degrees : boolean, optional + degrees : bool, optional sigma, alpha, and beta are given in degrees. rng_seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional A seed to initialize the BitGenerator. diff --git a/python/damask/_vtk.py b/python/damask/_vtk.py index 95cea4542..dbbfb1b10 100644 --- a/python/damask/_vtk.py +++ b/python/damask/_vtk.py @@ -28,8 +28,8 @@ class VTK: ---------- vtk_data : subclass of vtk.vtkDataSet Description of geometry and topology, optionally with attached data. - Valid types are vtk.vtkRectilinearGrid, vtk.vtkUnstructuredGrid, - or vtk.vtkPolyData. + Valid types are vtk.vtkImageData, vtk.vtkUnstructuredGrid, + vtk.vtkPolyData, and vtk.vtkRectilinearGrid. """ self.vtk_data = vtk_data @@ -242,7 +242,7 @@ class VTK: ---------- fname : str or pathlib.Path Filename for writing. - parallel : boolean, optional + parallel : bool, optional Write data in parallel background process. Defaults to True. compress : bool, optional Compress with zlib algorithm. Defaults to True. diff --git a/python/damask/seeds.py b/python/damask/seeds.py index 7e01a40e6..6ff150df3 100644 --- a/python/damask/seeds.py +++ b/python/damask/seeds.py @@ -61,7 +61,7 @@ def from_Poisson_disc(size: _FloatSequence, N_seeds: int, N_candidates: int, dis Number of candidates to consider for finding best candidate. distance : float Minimum acceptable distance to other seeds. - periodic : boolean, optional + periodic : bool, optional Calculate minimum distance for periodically repeated grid. rng_seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional A seed to initialize the BitGenerator. Defaults to None. @@ -99,8 +99,8 @@ def from_Poisson_disc(size: _FloatSequence, N_seeds: int, N_candidates: int, dis return coords -def from_grid(grid, selection: _IntSequence = None, - invert: 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. @@ -110,11 +110,11 @@ def from_grid(grid, selection: _IntSequence = None, Grid from which the material IDs are used as seeds. selection : sequence of int, optional Material IDs to consider. - invert : boolean, false + invert_selection : bool, optional Consider all material IDs except those in selection. Defaults to False. - average : boolean, optional + average : bool, optional Seed corresponds to center of gravity of material ID cloud. - periodic : boolean, optional + periodic : bool, optional Center of gravity accounts for periodic boundaries. Returns @@ -125,7 +125,7 @@ def from_grid(grid, selection: _IntSequence = None, """ material = grid.material.reshape((-1,1),order='F') mask = _np.full(grid.cells.prod(),True,dtype=bool) if selection is None else \ - _np.isin(material,selection,invert=invert).flatten() + _np.isin(material,selection,invert=invert_selection).flatten() coords = _grid_filters.coordinates0_point(grid.cells,grid.size).reshape(-1,3,order='F') if not average: diff --git a/python/tests/test_seeds.py b/python/tests/test_seeds.py index e68260aa4..ca5cd6f6d 100644 --- a/python/tests/test_seeds.py +++ b/python/tests/test_seeds.py @@ -67,5 +67,5 @@ class TestSeeds: coords = seeds.from_random(size,N_seeds,cells) grid = Grid.from_Voronoi_tessellation(cells,size,coords) selection=np.random.randint(N_seeds)+1 - coords,material = seeds.from_grid(grid,average=average,periodic=periodic,invert=invert,selection=[selection]) + coords,material = seeds.from_grid(grid,average=average,periodic=periodic,invert_selection=invert,selection=[selection]) assert selection not in material if invert else (selection==material).all()