util.extend_docstring: proper layout for extended class (incl. current return type)
This commit is contained in:
parent
dff8a5a7f9
commit
5017aabcea
|
@ -94,7 +94,7 @@ class Orientation(Rotation,Crystal):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@util.extend_docstring(_parameter_doc)
|
@util.extend_docstring(extra_parameters=_parameter_doc)
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
rotation: Union[FloatSequence, Rotation] = np.array([1.,0.,0.,0.]),
|
rotation: Union[FloatSequence, Rotation] = np.array([1.,0.,0.,0.]),
|
||||||
*,
|
*,
|
||||||
|
@ -300,84 +300,95 @@ class Orientation(Rotation,Crystal):
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@util.extended_docstring(Rotation.from_random, _parameter_doc)
|
@util.extend_docstring(Rotation.from_random,
|
||||||
|
extra_parameters=_parameter_doc)
|
||||||
def from_random(cls, **kwargs) -> 'Orientation':
|
def from_random(cls, **kwargs) -> 'Orientation':
|
||||||
kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_random)
|
kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_random)
|
||||||
return cls(rotation=Rotation.from_random(**kwargs_rot),**kwargs_ori)
|
return cls(rotation=Rotation.from_random(**kwargs_rot),**kwargs_ori)
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@util.extended_docstring(Rotation.from_quaternion,_parameter_doc)
|
@util.extend_docstring(Rotation.from_quaternion,
|
||||||
|
extra_parameters=_parameter_doc)
|
||||||
def from_quaternion(cls, **kwargs) -> 'Orientation':
|
def from_quaternion(cls, **kwargs) -> 'Orientation':
|
||||||
kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_quaternion)
|
kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_quaternion)
|
||||||
return cls(rotation=Rotation.from_quaternion(**kwargs_rot),**kwargs_ori)
|
return cls(rotation=Rotation.from_quaternion(**kwargs_rot),**kwargs_ori)
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@util.extended_docstring(Rotation.from_Euler_angles,_parameter_doc)
|
@util.extend_docstring(Rotation.from_Euler_angles,
|
||||||
|
extra_parameters=_parameter_doc)
|
||||||
def from_Euler_angles(cls, **kwargs) -> 'Orientation':
|
def from_Euler_angles(cls, **kwargs) -> 'Orientation':
|
||||||
kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_Euler_angles)
|
kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_Euler_angles)
|
||||||
return cls(rotation=Rotation.from_Euler_angles(**kwargs_rot),**kwargs_ori)
|
return cls(rotation=Rotation.from_Euler_angles(**kwargs_rot),**kwargs_ori)
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@util.extended_docstring(Rotation.from_axis_angle,_parameter_doc)
|
@util.extend_docstring(Rotation.from_axis_angle,
|
||||||
|
extra_parameters=_parameter_doc)
|
||||||
def from_axis_angle(cls, **kwargs) -> 'Orientation':
|
def from_axis_angle(cls, **kwargs) -> 'Orientation':
|
||||||
kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_axis_angle)
|
kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_axis_angle)
|
||||||
return cls(rotation=Rotation.from_axis_angle(**kwargs_rot),**kwargs_ori)
|
return cls(rotation=Rotation.from_axis_angle(**kwargs_rot),**kwargs_ori)
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@util.extended_docstring(Rotation.from_basis,_parameter_doc)
|
@util.extend_docstring(Rotation.from_basis,
|
||||||
|
extra_parameters=_parameter_doc)
|
||||||
def from_basis(cls, **kwargs) -> 'Orientation':
|
def from_basis(cls, **kwargs) -> 'Orientation':
|
||||||
kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_basis)
|
kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_basis)
|
||||||
return cls(rotation=Rotation.from_basis(**kwargs_rot),**kwargs_ori)
|
return cls(rotation=Rotation.from_basis(**kwargs_rot),**kwargs_ori)
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@util.extended_docstring(Rotation.from_matrix,_parameter_doc)
|
@util.extend_docstring(Rotation.from_matrix,
|
||||||
|
extra_parameters=_parameter_doc)
|
||||||
def from_matrix(cls, **kwargs) -> 'Orientation':
|
def from_matrix(cls, **kwargs) -> 'Orientation':
|
||||||
kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_matrix)
|
kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_matrix)
|
||||||
return cls(rotation=Rotation.from_matrix(**kwargs_rot),**kwargs_ori)
|
return cls(rotation=Rotation.from_matrix(**kwargs_rot),**kwargs_ori)
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@util.extended_docstring(Rotation.from_Rodrigues_vector,_parameter_doc)
|
@util.extend_docstring(Rotation.from_Rodrigues_vector,
|
||||||
|
extra_parameters=_parameter_doc)
|
||||||
def from_Rodrigues_vector(cls, **kwargs) -> 'Orientation':
|
def from_Rodrigues_vector(cls, **kwargs) -> 'Orientation':
|
||||||
kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_Rodrigues_vector)
|
kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_Rodrigues_vector)
|
||||||
return cls(rotation=Rotation.from_Rodrigues_vector(**kwargs_rot),**kwargs_ori)
|
return cls(rotation=Rotation.from_Rodrigues_vector(**kwargs_rot),**kwargs_ori)
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@util.extended_docstring(Rotation.from_homochoric,_parameter_doc)
|
@util.extend_docstring(Rotation.from_homochoric,
|
||||||
|
extra_parameters=_parameter_doc)
|
||||||
def from_homochoric(cls, **kwargs) -> 'Orientation':
|
def from_homochoric(cls, **kwargs) -> 'Orientation':
|
||||||
kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_homochoric)
|
kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_homochoric)
|
||||||
return cls(rotation=Rotation.from_homochoric(**kwargs_rot),**kwargs_ori)
|
return cls(rotation=Rotation.from_homochoric(**kwargs_rot),**kwargs_ori)
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@util.extended_docstring(Rotation.from_cubochoric,_parameter_doc)
|
@util.extend_docstring(Rotation.from_cubochoric,
|
||||||
|
extra_parameters=_parameter_doc)
|
||||||
def from_cubochoric(cls, **kwargs) -> 'Orientation':
|
def from_cubochoric(cls, **kwargs) -> 'Orientation':
|
||||||
kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_cubochoric)
|
kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_cubochoric)
|
||||||
return cls(rotation=Rotation.from_cubochoric(**kwargs_rot),**kwargs_ori)
|
return cls(rotation=Rotation.from_cubochoric(**kwargs_rot),**kwargs_ori)
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@util.extended_docstring(Rotation.from_spherical_component,_parameter_doc)
|
@util.extend_docstring(Rotation.from_spherical_component,
|
||||||
|
extra_parameters=_parameter_doc)
|
||||||
def from_spherical_component(cls, **kwargs) -> 'Orientation':
|
def from_spherical_component(cls, **kwargs) -> 'Orientation':
|
||||||
kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_spherical_component)
|
kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_spherical_component)
|
||||||
return cls(rotation=Rotation.from_spherical_component(**kwargs_rot),**kwargs_ori)
|
return cls(rotation=Rotation.from_spherical_component(**kwargs_rot),**kwargs_ori)
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@util.extended_docstring(Rotation.from_fiber_component,_parameter_doc)
|
@util.extend_docstring(Rotation.from_fiber_component,
|
||||||
|
extra_parameters=_parameter_doc)
|
||||||
def from_fiber_component(cls, **kwargs) -> 'Orientation':
|
def from_fiber_component(cls, **kwargs) -> 'Orientation':
|
||||||
kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_fiber_component)
|
kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_fiber_component)
|
||||||
return cls(rotation=Rotation.from_fiber_component(**kwargs_rot),**kwargs_ori)
|
return cls(rotation=Rotation.from_fiber_component(**kwargs_rot),**kwargs_ori)
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@util.extend_docstring(_parameter_doc)
|
@util.extend_docstring(extra_parameters=_parameter_doc)
|
||||||
def from_directions(cls,
|
def from_directions(cls,
|
||||||
uvw: FloatSequence,
|
uvw: FloatSequence,
|
||||||
hkl: FloatSequence,
|
hkl: FloatSequence,
|
||||||
|
@ -392,6 +403,10 @@ class Orientation(Rotation,Crystal):
|
||||||
hkl : numpy.ndarray, shape (...,3)
|
hkl : numpy.ndarray, shape (...,3)
|
||||||
Lattice plane normal aligned with lab frame z-direction.
|
Lattice plane normal aligned with lab frame z-direction.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
new : damask.Orientation
|
||||||
|
|
||||||
"""
|
"""
|
||||||
o = cls(**kwargs)
|
o = cls(**kwargs)
|
||||||
x = o.to_frame(uvw=uvw)
|
x = o.to_frame(uvw=uvw)
|
||||||
|
@ -538,8 +553,7 @@ class Orientation(Rotation,Crystal):
|
||||||
|
|
||||||
Notes
|
Notes
|
||||||
-----
|
-----
|
||||||
Currently requires same crystal family for both orientations.
|
Requires same crystal family for both orientations.
|
||||||
For extension to cases with differing symmetry see A. Heinz and P. Neumann 1991 and 10.1107/S0021889808016373.
|
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
--------
|
--------
|
||||||
|
@ -569,6 +583,8 @@ class Orientation(Rotation,Crystal):
|
||||||
>>> plt.show()
|
>>> plt.show()
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
# For extension to cases with differing symmetry see
|
||||||
|
# https://doi.org/10.1107/S0021889808016373 and https://doi.org/10.1107/S0108767391006864
|
||||||
if self.family != other.family:
|
if self.family != other.family:
|
||||||
raise NotImplementedError('disorientation between different crystal families')
|
raise NotImplementedError('disorientation between different crystal families')
|
||||||
|
|
||||||
|
|
|
@ -732,7 +732,7 @@ class Rotation:
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
x : numpy.ndarray, shape (...,3)
|
x : numpy.ndarray, shape (...,3)
|
||||||
Cubochoric vector (x_1, x_2, x_3) with max(x_i) < 1/2*π^(2/3).
|
Cubochoric vector (x_1, x_2, x_3) with max(x_i) < 1/2*π^(2/3).
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
--------
|
--------
|
||||||
|
@ -768,6 +768,10 @@ class Rotation:
|
||||||
P : int ∈ {-1,1}, optional
|
P : int ∈ {-1,1}, optional
|
||||||
Sign convention. Defaults to -1.
|
Sign convention. Defaults to -1.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
new : damask.Rotation
|
||||||
|
|
||||||
"""
|
"""
|
||||||
qu = np.array(q,dtype=float)
|
qu = np.array(q,dtype=float)
|
||||||
if qu.shape[:-2:-1] != (4,): raise ValueError('invalid shape')
|
if qu.shape[:-2:-1] != (4,): raise ValueError('invalid shape')
|
||||||
|
@ -800,6 +804,10 @@ class Rotation:
|
||||||
degrees : bool, optional
|
degrees : bool, optional
|
||||||
Euler angles are given in degrees. Defaults to False.
|
Euler angles are given in degrees. Defaults to False.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
new : damask.Rotation
|
||||||
|
|
||||||
Notes
|
Notes
|
||||||
-----
|
-----
|
||||||
Bunge Euler angles correspond to a rotation axis sequence of z–x'–z''.
|
Bunge Euler angles correspond to a rotation axis sequence of z–x'–z''.
|
||||||
|
@ -834,6 +842,10 @@ class Rotation:
|
||||||
P : int ∈ {-1,1}, optional
|
P : int ∈ {-1,1}, optional
|
||||||
Sign convention. Defaults to -1.
|
Sign convention. Defaults to -1.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
new : damask.Rotation
|
||||||
|
|
||||||
"""
|
"""
|
||||||
ax = np.array(axis_angle,dtype=float)
|
ax = np.array(axis_angle,dtype=float)
|
||||||
if ax.shape[:-2:-1] != (4,): raise ValueError('invalid shape')
|
if ax.shape[:-2:-1] != (4,): raise ValueError('invalid shape')
|
||||||
|
@ -898,6 +910,10 @@ class Rotation:
|
||||||
R : numpy.ndarray, shape (...,3,3)
|
R : numpy.ndarray, shape (...,3,3)
|
||||||
Rotation matrix with det(R) = 1 and R.T ∙ R = I.
|
Rotation matrix with det(R) = 1 and R.T ∙ R = I.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
new : damask.Rotation
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return Rotation.from_basis(R)
|
return Rotation.from_basis(R)
|
||||||
|
|
||||||
|
@ -914,6 +930,10 @@ class Rotation:
|
||||||
b : numpy.ndarray, shape (...,2,3)
|
b : numpy.ndarray, shape (...,2,3)
|
||||||
Corresponding three-dimensional vectors of second basis.
|
Corresponding three-dimensional vectors of second basis.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
new : damask.Rotation
|
||||||
|
|
||||||
"""
|
"""
|
||||||
a_ = np.array(a,dtype=float)
|
a_ = np.array(a,dtype=float)
|
||||||
b_ = np.array(b,dtype=float)
|
b_ = np.array(b,dtype=float)
|
||||||
|
@ -946,6 +966,10 @@ class Rotation:
|
||||||
P : int ∈ {-1,1}, optional
|
P : int ∈ {-1,1}, optional
|
||||||
Sign convention. Defaults to -1.
|
Sign convention. Defaults to -1.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
new : damask.Rotation
|
||||||
|
|
||||||
"""
|
"""
|
||||||
ro = np.array(rho,dtype=float)
|
ro = np.array(rho,dtype=float)
|
||||||
if ro.shape[:-2:-1] != (4,): raise ValueError('invalid shape')
|
if ro.shape[:-2:-1] != (4,): raise ValueError('invalid shape')
|
||||||
|
@ -974,6 +998,10 @@ class Rotation:
|
||||||
P : int ∈ {-1,1}, optional
|
P : int ∈ {-1,1}, optional
|
||||||
Sign convention. Defaults to -1.
|
Sign convention. Defaults to -1.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
new : damask.Rotation
|
||||||
|
|
||||||
"""
|
"""
|
||||||
ho = np.array(h,dtype=float)
|
ho = np.array(h,dtype=float)
|
||||||
if ho.shape[:-2:-1] != (3,): raise ValueError('invalid shape')
|
if ho.shape[:-2:-1] != (3,): raise ValueError('invalid shape')
|
||||||
|
@ -999,6 +1027,10 @@ class Rotation:
|
||||||
P : int ∈ {-1,1}, optional
|
P : int ∈ {-1,1}, optional
|
||||||
Sign convention. Defaults to -1.
|
Sign convention. Defaults to -1.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
new : damask.Rotation
|
||||||
|
|
||||||
"""
|
"""
|
||||||
cu = np.array(x,dtype=float)
|
cu = np.array(x,dtype=float)
|
||||||
if cu.shape[:-2:-1] != (3,): raise ValueError('invalid shape')
|
if cu.shape[:-2:-1] != (3,): raise ValueError('invalid shape')
|
||||||
|
@ -1025,6 +1057,10 @@ class Rotation:
|
||||||
A seed to initialize the BitGenerator.
|
A seed to initialize the BitGenerator.
|
||||||
Defaults to None, i.e. unpredictable entropy will be pulled from the OS.
|
Defaults to None, i.e. unpredictable entropy will be pulled from the OS.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
new : damask.Rotation
|
||||||
|
|
||||||
"""
|
"""
|
||||||
rng = np.random.default_rng(rng_seed)
|
rng = np.random.default_rng(rng_seed)
|
||||||
r = rng.random(3 if shape is None else tuple(shape)+(3,) if hasattr(shape, '__iter__') else (shape,3)) # type: ignore
|
r = rng.random(3 if shape is None else tuple(shape)+(3,) if hasattr(shape, '__iter__') else (shape,3)) # type: ignore
|
||||||
|
@ -1066,6 +1102,10 @@ class Rotation:
|
||||||
A seed to initialize the BitGenerator.
|
A seed to initialize the BitGenerator.
|
||||||
Defaults to None, i.e. unpredictable entropy will be pulled from the OS.
|
Defaults to None, i.e. unpredictable entropy will be pulled from the OS.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
new : damask.Rotation
|
||||||
|
|
||||||
Notes
|
Notes
|
||||||
-----
|
-----
|
||||||
Due to the distortion of Euler space in the vicinity of ϕ = 0, probability densities, p, defined on
|
Due to the distortion of Euler space in the vicinity of ϕ = 0, probability densities, p, defined on
|
||||||
|
@ -1150,7 +1190,7 @@ class Rotation:
|
||||||
sigma: float = 0.,
|
sigma: float = 0.,
|
||||||
shape: Union[int, IntSequence] = None,
|
shape: Union[int, IntSequence] = None,
|
||||||
degrees: bool = False,
|
degrees: bool = False,
|
||||||
rng_seed: NumpyRngSeed = None):
|
rng_seed: NumpyRngSeed = None) -> 'Rotation':
|
||||||
"""
|
"""
|
||||||
Initialize with samples from a Gaussian distribution around a given direction.
|
Initialize with samples from a Gaussian distribution around a given direction.
|
||||||
|
|
||||||
|
@ -1173,6 +1213,10 @@ class Rotation:
|
||||||
A seed to initialize the BitGenerator.
|
A seed to initialize the BitGenerator.
|
||||||
Defaults to None, i.e. unpredictable entropy will be pulled from the OS.
|
Defaults to None, i.e. unpredictable entropy will be pulled from the OS.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
new : damask.Rotation
|
||||||
|
|
||||||
Notes
|
Notes
|
||||||
-----
|
-----
|
||||||
The crystal direction for (θ=0,φ=0) is [0 0 1],
|
The crystal direction for (θ=0,φ=0) is [0 0 1],
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
"""Functionality for generation of seed points for Voronoi or Laguerre tessellation."""
|
"""Functionality for generation of seed points for Voronoi or Laguerre tessellation."""
|
||||||
|
|
||||||
from typing import Tuple as _Tuple
|
from typing import Tuple as _Tuple
|
||||||
|
|
|
@ -210,6 +210,14 @@ def open_text(fname: _FileHandle,
|
||||||
open(_Path(fname).expanduser(),mode,newline=('\n' if mode == 'w' else None))
|
open(_Path(fname).expanduser(),mode,newline=('\n' if mode == 'w' else None))
|
||||||
|
|
||||||
|
|
||||||
|
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 natural_sort(key: str) -> _List[_Union[int, str]]:
|
def natural_sort(key: str) -> _List[_Union[int, str]]:
|
||||||
"""
|
"""
|
||||||
Natural sort.
|
Natural sort.
|
||||||
|
@ -403,13 +411,6 @@ 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])]),
|
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]
|
-shift if keepdims else 0,axis=-1)[...,:3 if keepdims else 2]
|
||||||
|
|
||||||
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,
|
def hybrid_IA(dist: _np.ndarray,
|
||||||
N: int,
|
N: int,
|
||||||
|
@ -486,18 +487,18 @@ def shapeshifter(fro: _Tuple[int, ...],
|
||||||
final_shape: _List[int] = []
|
final_shape: _List[int] = []
|
||||||
index = 0
|
index = 0
|
||||||
for i,item in enumerate(_to):
|
for i,item in enumerate(_to):
|
||||||
if item==_fro[index]:
|
if item == _fro[index]:
|
||||||
final_shape.append(item)
|
final_shape.append(item)
|
||||||
index+=1
|
index+=1
|
||||||
else:
|
else:
|
||||||
final_shape.append(1)
|
final_shape.append(1)
|
||||||
if _fro[index]==1 and not keep_ones:
|
if _fro[index] == 1 and not keep_ones:
|
||||||
index+=1
|
index+=1
|
||||||
if index==len(_fro):
|
if index == len(_fro):
|
||||||
final_shape = final_shape+[1]*(len(_to)-i-1)
|
final_shape = final_shape+[1]*(len(_to)-i-1)
|
||||||
break
|
break
|
||||||
if index!=len(_fro): raise ValueError(f'shapes cannot be shifted {fro} --> {to}')
|
if index != len(_fro): raise ValueError(f'shapes cannot be shifted {fro} --> {to}')
|
||||||
return tuple(final_shape[::-1] if mode=='left' else final_shape)
|
return tuple(final_shape[::-1] if mode == 'left' else final_shape)
|
||||||
|
|
||||||
def shapeblender(a: _Tuple[int, ...],
|
def shapeblender(a: _Tuple[int, ...],
|
||||||
b: _Tuple[int, ...]) -> _Tuple[int, ...]:
|
b: _Tuple[int, ...]) -> _Tuple[int, ...]:
|
||||||
|
@ -528,37 +529,82 @@ def shapeblender(a: _Tuple[int, ...],
|
||||||
return a + b[i:]
|
return a + b[i:]
|
||||||
|
|
||||||
|
|
||||||
def extend_docstring(extra_docstring: str) -> _Callable:
|
def _docstringer(docstring: _Union[str, _Callable],
|
||||||
|
extra_parameters: str = None,
|
||||||
|
# extra_examples: str = None,
|
||||||
|
# extra_notes: str = None,
|
||||||
|
return_type: _Union[str, _Callable] = None) -> str:
|
||||||
"""
|
"""
|
||||||
Decorator: Append to function's docstring.
|
Extend a docstring.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
extra_docstring : str
|
docstring : str or callable, optional
|
||||||
Docstring to append.
|
Docstring (of callable) to extend.
|
||||||
|
extra_parameters : str, optional
|
||||||
|
Additional information to append to Parameters section.
|
||||||
|
return_type : str or callable, optional
|
||||||
|
Type of return variable.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def _decorator(func):
|
docstring_ = str( docstring if isinstance(docstring,str)
|
||||||
func.__doc__ += extra_docstring
|
else docstring.__doc__ if hasattr(docstring,'__doc__')
|
||||||
return func
|
else '')
|
||||||
return _decorator
|
d = dict(Parameters=extra_parameters,
|
||||||
|
# Examples=extra_examples,
|
||||||
|
# Notes=extra_notes,
|
||||||
|
)
|
||||||
|
for key,extra in [(k,v) for (k,v) in d.items() if v is not None]:
|
||||||
|
if not (heading := _re.search(fr'^([ ]*){key}\s*\n\1{"-"*len(key)}',
|
||||||
|
docstring_,flags=_re.MULTILINE)):
|
||||||
|
raise RuntimeError(f"Docstring {docstring_} lacks a correctly formatted {key} section to insert values into")
|
||||||
|
content = [line for line in extra.split('\n') if line.strip()]
|
||||||
|
indent = len(heading.group(1))
|
||||||
|
shift = min([len(line)-len(line.lstrip(' '))-indent for line in content])
|
||||||
|
extra = '\n'.join([(line[shift:] if shift > 0 else
|
||||||
|
f'{" "*-shift}{line}') for line in content])
|
||||||
|
docstring_ = _re.sub(fr'(^([ ]*){key}\s*\n\2{"-"*len(key)}[\n ]*[A-Za-z0-9 ]*: ([^\n]+\n)*)',
|
||||||
|
fr'\1{extra}\n',
|
||||||
|
docstring_,flags=_re.MULTILINE)
|
||||||
|
|
||||||
|
if return_type is None:
|
||||||
|
return docstring_
|
||||||
|
else:
|
||||||
|
if isinstance(return_type,str):
|
||||||
|
return_type_ = return_type
|
||||||
|
else:
|
||||||
|
return_class = return_type.__annotations__.get('return','')
|
||||||
|
return_type_ = (_sys.modules[return_type.__module__].__name__.split('.')[0]
|
||||||
|
+'.'
|
||||||
|
+(return_class.__name__ if not isinstance(return_class,str) else return_class)
|
||||||
|
)
|
||||||
|
|
||||||
def extended_docstring(f: _Callable,
|
return _re.sub(r'(^([ ]*)Returns\s*\n\2-------\s*\n[ ]*[A-Za-z0-9 ]*: )(.*)\n',
|
||||||
extra_docstring: str) -> _Callable:
|
fr'\1{return_type_}\n',
|
||||||
|
docstring_,flags=_re.MULTILINE)
|
||||||
|
|
||||||
|
def extend_docstring(docstring: _Union[str, _Callable] = None,
|
||||||
|
extra_parameters: str = None) -> _Callable:
|
||||||
"""
|
"""
|
||||||
Decorator: Combine another function's docstring with a given docstring.
|
Decorator: Extend the function's docstring.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
f : function
|
docstring : str or callable, optional
|
||||||
Function of which the docstring is taken.
|
Docstring to extend. Defaults to that of decorated function.
|
||||||
extra_docstring : str
|
extra_parameters : str, optional
|
||||||
Docstring to append.
|
Additional information to append to Parameters section.
|
||||||
|
|
||||||
|
Notes
|
||||||
|
-----
|
||||||
|
Return type will become own type if docstring is callable.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def _decorator(func):
|
def _decorator(func):
|
||||||
func.__doc__ = f.__doc__ + extra_docstring
|
func.__doc__ = _docstringer(func.__doc__ if docstring is None else docstring,
|
||||||
|
extra_parameters,
|
||||||
|
func if isinstance(docstring,_Callable) else None,
|
||||||
|
)
|
||||||
return func
|
return func
|
||||||
return _decorator
|
return _decorator
|
||||||
|
|
||||||
|
@ -649,7 +695,6 @@ def Bravais_to_Miller(*,
|
||||||
[0,0,0,1]]))
|
[0,0,0,1]]))
|
||||||
return _np.einsum('il,...l',basis,axis)
|
return _np.einsum('il,...l',basis,axis)
|
||||||
|
|
||||||
|
|
||||||
def Miller_to_Bravais(*,
|
def Miller_to_Bravais(*,
|
||||||
uvw: _np.ndarray = None,
|
uvw: _np.ndarray = None,
|
||||||
hkl: _np.ndarray = None) -> _np.ndarray:
|
hkl: _np.ndarray = None) -> _np.ndarray:
|
||||||
|
@ -706,7 +751,6 @@ def dict_prune(d: _Dict) -> _Dict:
|
||||||
|
|
||||||
return new
|
return new
|
||||||
|
|
||||||
|
|
||||||
def dict_flatten(d: _Dict) -> _Dict:
|
def dict_flatten(d: _Dict) -> _Dict:
|
||||||
"""
|
"""
|
||||||
Recursively remove keys of single-entry dictionaries.
|
Recursively remove keys of single-entry dictionaries.
|
||||||
|
|
|
@ -8,7 +8,6 @@ import h5py
|
||||||
|
|
||||||
from damask import util
|
from damask import util
|
||||||
|
|
||||||
|
|
||||||
class TestUtil:
|
class TestUtil:
|
||||||
|
|
||||||
@pytest.mark.xfail(sys.platform == 'win32', reason='echo is not a Windows command')
|
@pytest.mark.xfail(sys.platform == 'win32', reason='echo is not a Windows command')
|
||||||
|
@ -208,3 +207,128 @@ class TestUtil:
|
||||||
@pytest.mark.parametrize('kw_Miller,kw_Bravais',[('uvw','uvtw'),('hkl','hkil')])
|
@pytest.mark.parametrize('kw_Miller,kw_Bravais',[('uvw','uvtw'),('hkl','hkil')])
|
||||||
def test_Bravais_Miller_Bravais(self,vector,kw_Miller,kw_Bravais):
|
def test_Bravais_Miller_Bravais(self,vector,kw_Miller,kw_Bravais):
|
||||||
assert np.all(vector == util.Miller_to_Bravais(**{kw_Miller:util.Bravais_to_Miller(**{kw_Bravais:vector})}))
|
assert np.all(vector == util.Miller_to_Bravais(**{kw_Miller:util.Bravais_to_Miller(**{kw_Bravais:vector})}))
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('extra_parameters',["""
|
||||||
|
p2 : str, optional
|
||||||
|
p2 description 1
|
||||||
|
p2 description 2
|
||||||
|
""",
|
||||||
|
"""
|
||||||
|
|
||||||
|
p2 : str, optional
|
||||||
|
p2 description 1
|
||||||
|
p2 description 2
|
||||||
|
|
||||||
|
""",
|
||||||
|
"""
|
||||||
|
p2 : str, optional
|
||||||
|
p2 description 1
|
||||||
|
p2 description 2
|
||||||
|
"""])
|
||||||
|
@pytest.mark.parametrize('invalid_docstring',["""
|
||||||
|
Function description
|
||||||
|
|
||||||
|
Parameters ----------
|
||||||
|
p0 : numpy.ndarray, shape (...,4)
|
||||||
|
p0 description 1
|
||||||
|
p0 description 2
|
||||||
|
p1 : int, optional
|
||||||
|
p1 description
|
||||||
|
|
||||||
|
Remaining description
|
||||||
|
""",
|
||||||
|
"""
|
||||||
|
Function description
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
p0 : numpy.ndarray, shape (...,4)
|
||||||
|
p0 description 1
|
||||||
|
p0 description 2
|
||||||
|
p1 : int, optional
|
||||||
|
p1 description
|
||||||
|
|
||||||
|
Remaining description
|
||||||
|
""",])
|
||||||
|
def test_extend_docstring_parameters(self,extra_parameters,invalid_docstring):
|
||||||
|
test_docstring = """
|
||||||
|
Function description
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
p0 : numpy.ndarray, shape (...,4)
|
||||||
|
p0 description 1
|
||||||
|
p0 description 2
|
||||||
|
p1 : int, optional
|
||||||
|
p1 description
|
||||||
|
|
||||||
|
Remaining description
|
||||||
|
"""
|
||||||
|
invalid_docstring = """
|
||||||
|
Function description
|
||||||
|
|
||||||
|
Parameters ----------
|
||||||
|
p0 : numpy.ndarray, shape (...,4)
|
||||||
|
p0 description 1
|
||||||
|
p0 description 2
|
||||||
|
p1 : int, optional
|
||||||
|
p1 description
|
||||||
|
|
||||||
|
Remaining description
|
||||||
|
"""
|
||||||
|
expected = """
|
||||||
|
Function description
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
p0 : numpy.ndarray, shape (...,4)
|
||||||
|
p0 description 1
|
||||||
|
p0 description 2
|
||||||
|
p1 : int, optional
|
||||||
|
p1 description
|
||||||
|
p2 : str, optional
|
||||||
|
p2 description 1
|
||||||
|
p2 description 2
|
||||||
|
|
||||||
|
Remaining description
|
||||||
|
""".split("\n")
|
||||||
|
assert expected == util._docstringer(test_docstring,extra_parameters).split('\n')
|
||||||
|
with pytest.raises(RuntimeError):
|
||||||
|
util._docstringer(invalid_docstring,extra_parameters)
|
||||||
|
|
||||||
|
def test_replace_docstring_return_type(self):
|
||||||
|
class TestClassOriginal:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def original_func() -> TestClassOriginal:
|
||||||
|
pass
|
||||||
|
|
||||||
|
class TestClassDecorated:
|
||||||
|
def decorated_func_bound(self) -> 'TestClassDecorated':
|
||||||
|
pass
|
||||||
|
|
||||||
|
def decorated_func() -> TestClassDecorated:
|
||||||
|
pass
|
||||||
|
|
||||||
|
original_func.__doc__ = """
|
||||||
|
Function description/Parameters
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
Return value : test_util.TestClassOriginal
|
||||||
|
|
||||||
|
Remaining description
|
||||||
|
"""
|
||||||
|
|
||||||
|
expected = """
|
||||||
|
Function description/Parameters
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
Return value : test_util.TestClassDecorated
|
||||||
|
|
||||||
|
Remaining description
|
||||||
|
"""
|
||||||
|
assert expected == util._docstringer(original_func,return_type=decorated_func)
|
||||||
|
assert expected == util._docstringer(original_func,return_type=TestClassDecorated.decorated_func_bound)
|
||||||
|
|
Loading…
Reference in New Issue