diff --git a/VERSION b/VERSION index f72217dce..ba869259d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.0.0-alpha7-86-g72408f389 +3.0.0-alpha7-94-g5d656d9c7 diff --git a/python/damask/_colormap.py b/python/damask/_colormap.py index 688070529..cdcbd8939 100644 --- a/python/damask/_colormap.py +++ b/python/damask/_colormap.py @@ -248,7 +248,7 @@ class Colormap(mpl.colors.ListedColormap): Parameters ---------- - fraction : float or sequence of float + fraction : (sequence of) float Fractional coordinate(s) to evaluate Colormap at. Returns diff --git a/python/damask/_grid.py b/python/damask/_grid.py index feff001f3..9197c1c5f 100644 --- a/python/damask/_grid.py +++ b/python/damask/_grid.py @@ -50,7 +50,7 @@ class Grid: Coordinates of grid origin in meter. Defaults to [0.0,0.0,0.0]. initial_conditions : dictionary, optional Labels and values of the inital conditions at each material point. - comments : str or sequence of str, optional + comments : (sequence of) str, optional Additional, human-readable information, e.g. history of operations. """ @@ -427,7 +427,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 sequence of str + labels : (sequence of) str Label(s) of the columns containing the material definition. Each unique combination of values results in one material ID. @@ -972,15 +972,16 @@ class Grid: # materials: 1 """ - options = ('nearest',False,None) orig = tuple(map(np.linspace,self.origin + self.size/self.cells*.5, self.origin + self.size - self.size/self.cells*.5,self.cells)) + interpolator = partial(interpolate.RegularGridInterpolator, + points=orig,method='nearest',bounds_error=False,fill_value=None) new = grid_filters.coordinates0_point(cells,self.size,self.origin) - return Grid(material = interpolate.RegularGridInterpolator(orig,self.material,*options)(new).astype(int), + return Grid(material = interpolator(values=self.material)(new).astype(int), size = self.size, origin = self.origin, - initial_conditions = {k: interpolate.RegularGridInterpolator(orig,v,*options)(new) + initial_conditions = {k: interpolator(values=v)(new) for k,v in self.initial_conditions.items()}, comments = self.comments+[util.execution_stamp('Grid','scale')], ) @@ -1043,9 +1044,9 @@ class Grid: Parameters ---------- - from_material : int or sequence of int + from_material : (sequence of) int Material indices to be substituted. - to_material : int or sequence of int + to_material : (sequence of) int New material indices. Returns @@ -1104,7 +1105,7 @@ class Grid: distance : float, optional Voxel distance checked for presence of other materials. Defaults to sqrt(3). - selection : int or collection of int, optional + selection : (collection of) int, optional Material IDs to consider. Defaults to all. invert_selection : bool, optional Consider all material IDs except those in selection. Defaults to False. @@ -1179,7 +1180,7 @@ class Grid: 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) + exponent : (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) @@ -1271,7 +1272,7 @@ class Grid: offset : int, optional Offset (positive or negative) to tag material IDs. Defaults to material.max()+1. - selection : int or collection of int, optional + selection : (collection of) int, optional Material IDs that trigger an offset. Defaults to any other than own material ID. invert_selection : bool, optional diff --git a/python/damask/_rotation.py b/python/damask/_rotation.py index e87bcf936..2f9677c89 100644 --- a/python/damask/_rotation.py +++ b/python/damask/_rotation.py @@ -468,7 +468,7 @@ class Rotation: Parameters ---------- - shape : int or sequence of ints + shape : (sequence of) int New shape, number of elements needs to match the original shape. If an integer is supplied, then the result will be a 1-D array of that length. order : {'C', 'F', 'A'}, optional @@ -496,7 +496,7 @@ class Rotation: Parameters ---------- - shape : int or sequence of ints + shape : (sequence of) int Shape of broadcasted array, needs to be compatible with the original shape. mode : str, optional Where to preferentially locate missing dimensions. @@ -1028,7 +1028,7 @@ class Rotation: Parameters ---------- - shape : int or sequence of ints, optional + shape : (sequence of) int, optional Shape of the returned array. Defaults to None, which gives a scalar. rng_seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional A seed to initialize the BitGenerator. @@ -1064,7 +1064,7 @@ class Rotation: Texture intensity values (probability density or volume fraction) at Euler space grid points. phi : numpy.ndarray, shape (n,3) Grid coordinates in Euler space at which weights are defined. - shape : int or sequence of ints, optional + shape : (sequence of) int, optional Shape of the returned array. Defaults to None, which gives a scalar. degrees : bool, optional Euler space grid coordinates are in degrees. Defaults to True. @@ -1116,7 +1116,7 @@ class Rotation: Central rotation. sigma : float Standard deviation of (Gaussian) misorientation distribution. - shape : int or sequence of ints, optional + shape : (sequence of) int, optional Shape of the returned array. Defaults to None, which gives a scalar. degrees : bool, optional sigma is given in degrees. Defaults to False. @@ -1174,7 +1174,7 @@ class Rotation: sigma : float, optional Standard deviation of (Gaussian) misorientation distribution. Defaults to 0. - shape : int or sequence of ints, optional + shape : (sequence of) int, optional Shape of the returned array. Defaults to None, which gives a scalar. degrees : bool, optional sigma and polar coordinates are given in degrees. Defaults to False. diff --git a/python/damask/_table.py b/python/damask/_table.py index 356e73730..990568364 100644 --- a/python/damask/_table.py +++ b/python/damask/_table.py @@ -25,7 +25,7 @@ class Table: For instance, 'F':(3,3) for a deformation gradient, or 'r':(1,) for a scalar. data : numpy.ndarray or pandas.DataFrame, optional Data. Existing column labels of a pandas.DataFrame will be replaced. - comments : str or iterable of str, optional + comments : (iterable of) str, optional Additional, human-readable information. """ @@ -464,9 +464,9 @@ class Table: Parameters ---------- - label_old : str or iterable of str + label_old : (iterable of) str Old column label(s). - label_new : str or iterable of str + label_new : (iterable of) str New column label(s). Returns diff --git a/python/damask/_vtk.py b/python/damask/_vtk.py index 46d779023..dede9f374 100644 --- a/python/damask/_vtk.py +++ b/python/damask/_vtk.py @@ -110,7 +110,7 @@ class VTK: Parameters ---------- - comments : str or sequence of str + comments : (sequence of) str Comments. """ diff --git a/python/damask/seeds.py b/python/damask/seeds.py index 11be5cc93..89d9bf935 100644 --- a/python/damask/seeds.py +++ b/python/damask/seeds.py @@ -118,7 +118,7 @@ def from_grid(grid, ---------- grid : damask.Grid Grid from which the material IDs are used as seeds. - selection : int or collection of int, optional + selection : (collection of) int, optional Material IDs to consider. invert_selection : bool, optional Consider all material IDs except those in selection. Defaults to False. diff --git a/python/damask/util.py b/python/damask/util.py index ec42dede0..04e448422 100644 --- a/python/damask/util.py +++ b/python/damask/util.py @@ -46,7 +46,7 @@ def srepr(msg, Parameters ---------- - msg : object with __repr__ or sequence of objects with __repr__ + msg : (sequence of) object with __repr__ Items to join. glue : str, optional Glue used for joining operation. Defaults to '\n'. @@ -71,7 +71,7 @@ def emph(msg) -> str: Parameters ---------- - msg : object with __repr__ or sequence of objects with __repr__ + msg : (sequence of) object with __repr__ Message to format. Returns @@ -88,7 +88,7 @@ def deemph(msg) -> str: Parameters ---------- - msg : object with __repr__ or sequence of objects with __repr__ + msg : (sequence of) object with __repr__ Message to format. Returns @@ -105,7 +105,7 @@ def warn(msg) -> str: Parameters ---------- - msg : object with __repr__ or sequence of objects with __repr__ + msg : (sequence of) object with __repr__ Message to format. Returns @@ -122,7 +122,7 @@ def strikeout(msg) -> str: Parameters ---------- - msg : object with __repr__ or iterable of objects with __repr__ + msg : (iterable of) object with __repr__ Message to format. Returns @@ -738,7 +738,7 @@ def tail_repack(extended: _Union[str, _Sequence[str]], Parameters ---------- - extended : str or list of str + extended : (list of) str Extended string list with potentially autosplitted tailing string relative to `existing`. existing : list of str Base string list. @@ -767,7 +767,7 @@ def aslist(arg: _Union[_IntCollection, int, None]) -> _List: Parameters ---------- - arg : int or collection of int or None + arg : (collection of) int or None Entity to transform into list. Returns diff --git a/python/tests/test_Rotation.py b/python/tests/test_Rotation.py index d39e20f93..98ee92d39 100644 --- a/python/tests/test_Rotation.py +++ b/python/tests/test_Rotation.py @@ -708,6 +708,7 @@ class TestRotation: @pytest.mark.parametrize('degrees',[True,False]) def test_axis_angle(self,set_of_rotations,degrees,normalize,P): c = np.array([P*-1,P*-1,P*-1,1.]) + c[:3] *= 0.9 if normalize else 1.0 for rot in set_of_rotations: m = rot.as_Euler_angles() o = Rotation.from_axis_angle(rot.as_axis_angle(degrees)*c,degrees,normalize,P).as_Euler_angles() @@ -730,16 +731,30 @@ class TestRotation: assert ok and np.isclose(np.linalg.norm(o[:3]),1.0) \ and o[3]<=np.pi+1.e-9, f'{m},{o},{rot.as_quaternion()}' + def test_parallel(self,set_of_rotations): + a = np.array([[1.0,0.0,0.0], + [0.0,1.0,0.0]]) + for rot in set_of_rotations: + assert rot.allclose(Rotation.from_parallel(a,rot.broadcast_to((2,))@a)) + @pytest.mark.parametrize('P',[1,-1]) @pytest.mark.parametrize('normalize',[True,False]) def test_Rodrigues(self,set_of_rotations,normalize,P): c = np.array([P*-1,P*-1,P*-1,1.]) + c[:3] *= 0.9 if normalize else 1.0 for rot in set_of_rotations: m = rot.as_matrix() o = Rotation.from_Rodrigues_vector(rot.as_Rodrigues_vector()*c,normalize,P).as_matrix() ok = np.allclose(m,o,atol=atol) assert ok and np.isclose(np.linalg.det(o),1.0), f'{m},{o}' + def test_Rodrigues_compact(self,set_of_rotations): + for rot in set_of_rotations: + c = rot.as_Rodrigues_vector(compact=True) + r = rot.as_Rodrigues_vector(compact=False) + assert np.allclose(r[:3]*r[3], c, equal_nan=True) + + @pytest.mark.parametrize('P',[1,-1]) def test_homochoric(self,set_of_rotations,P): cutoff = np.tan(np.pi*.5*(1.-1e-4)) @@ -890,6 +905,15 @@ class TestRotation: with pytest.raises(ValueError): fr(eval(f'R.{to}()'),P=-30) + + def test_invalid_multiplication(self): + rot = Rotation.from_random() + with pytest.raises(TypeError): + rot@Rotation.from_random() + with pytest.raises(TypeError): + rot@[1,2,3,4] + + @pytest.mark.parametrize('shape',[None,(3,),(4,2)]) def test_broadcast(self,shape): rot = Rotation.from_random(shape) @@ -900,7 +924,7 @@ class TestRotation: assert np.allclose(rot_broadcast.quaternion[...,i,:], rot.quaternion) - @pytest.mark.parametrize('function,invalid',[(Rotation.from_quaternion, np.array([-1,0,0,0])), + @pytest.mark.parametrize('function,invalid',[(Rotation.from_quaternion, np.array([-1,0,0,0])), (Rotation.from_quaternion, np.array([1,1,1,0])), (Rotation.from_Euler_angles, np.array([1,4,0])), (Rotation.from_axis_angle, np.array([1,0,0,4])),