05 Typehints config configmaterial
This commit is contained in:
parent
98381bff2a
commit
086ff42be5
|
@ -2,25 +2,34 @@ import copy
|
|||
from io import StringIO
|
||||
from collections.abc import Iterable
|
||||
import abc
|
||||
from pathlib import Path
|
||||
from typing import Union, Dict, Any, Type, TypeVar
|
||||
|
||||
import numpy as np
|
||||
import yaml
|
||||
|
||||
from ._typehints import FileHandle
|
||||
from . import Rotation
|
||||
|
||||
MyType = TypeVar('MyType', bound='Config')
|
||||
|
||||
class NiceDumper(yaml.SafeDumper):
|
||||
"""Make YAML readable for humans."""
|
||||
|
||||
def write_line_break(self, data=None):
|
||||
def write_line_break(self,
|
||||
data: str = None):
|
||||
super().write_line_break(data)
|
||||
|
||||
if len(self.indents) == 1:
|
||||
super().write_line_break()
|
||||
|
||||
def increase_indent(self, flow=False, indentless=False):
|
||||
def increase_indent(self,
|
||||
flow: bool = False,
|
||||
indentless: bool = False):
|
||||
return super().increase_indent(flow, False)
|
||||
|
||||
def represent_data(self, data):
|
||||
def represent_data(self,
|
||||
data: Any):
|
||||
"""Cast Config objects and its subclasses to dict."""
|
||||
if isinstance(data, dict) and type(data) != dict:
|
||||
return self.represent_data(dict(data))
|
||||
|
@ -31,14 +40,17 @@ class NiceDumper(yaml.SafeDumper):
|
|||
else:
|
||||
return super().represent_data(data)
|
||||
|
||||
def ignore_aliases(self, data):
|
||||
def ignore_aliases(self,
|
||||
data: Any) -> bool:
|
||||
"""Do not use references to existing objects."""
|
||||
return True
|
||||
|
||||
class Config(dict):
|
||||
"""YAML-based configuration."""
|
||||
|
||||
def __init__(self,yml=None,**kwargs):
|
||||
def __init__(self,
|
||||
yml: Union[str, Dict[str, Any]] = None,
|
||||
**kwargs):
|
||||
"""Initialize from YAML, dict, or key=value pairs."""
|
||||
if isinstance(yml,str):
|
||||
kwargs.update(yaml.safe_load(yml))
|
||||
|
@ -47,7 +59,7 @@ class Config(dict):
|
|||
|
||||
super().__init__(**kwargs)
|
||||
|
||||
def __repr__(self):
|
||||
def __repr__(self) -> str:
|
||||
"""Show as in file."""
|
||||
output = StringIO()
|
||||
self.save(output)
|
||||
|
@ -55,14 +67,15 @@ class Config(dict):
|
|||
return ''.join(output.readlines())
|
||||
|
||||
|
||||
def __copy__(self):
|
||||
def __copy__(self: MyType) -> MyType:
|
||||
"""Create deep copy."""
|
||||
return copy.deepcopy(self)
|
||||
|
||||
copy = __copy__
|
||||
|
||||
|
||||
def __or__(self,other):
|
||||
def __or__(self: MyType,
|
||||
other) -> MyType:
|
||||
"""
|
||||
Update configuration with contents of other.
|
||||
|
||||
|
@ -76,18 +89,24 @@ class Config(dict):
|
|||
updated : damask.Config
|
||||
Updated configuration.
|
||||
|
||||
Note
|
||||
----
|
||||
This functionality is a backport for Python 3.8
|
||||
|
||||
"""
|
||||
duplicate = self.copy()
|
||||
duplicate.update(other)
|
||||
return duplicate
|
||||
|
||||
|
||||
def __ior__(self,other):
|
||||
def __ior__(self: MyType,
|
||||
other) -> MyType:
|
||||
"""Update configuration with contents of other."""
|
||||
return self.__or__(other)
|
||||
|
||||
|
||||
def delete(self,keys):
|
||||
def delete(self: MyType,
|
||||
keys: Union[Iterable, str]) -> MyType:
|
||||
"""
|
||||
Remove configuration keys.
|
||||
|
||||
|
@ -109,7 +128,8 @@ class Config(dict):
|
|||
|
||||
|
||||
@classmethod
|
||||
def load(cls,fname):
|
||||
def load(cls: Type[MyType],
|
||||
fname: FileHandle) -> MyType:
|
||||
"""
|
||||
Load from yaml file.
|
||||
|
||||
|
@ -124,14 +144,15 @@ class Config(dict):
|
|||
Configuration from file.
|
||||
|
||||
"""
|
||||
try:
|
||||
if isinstance(fname, (str, Path)):
|
||||
fhandle = open(fname)
|
||||
except TypeError:
|
||||
else:
|
||||
fhandle = fname
|
||||
return cls(yaml.safe_load(fhandle))
|
||||
|
||||
|
||||
def save(self,fname,**kwargs):
|
||||
def save(self,
|
||||
fname: FileHandle,
|
||||
**kwargs):
|
||||
"""
|
||||
Save to yaml file.
|
||||
|
||||
|
@ -143,9 +164,9 @@ class Config(dict):
|
|||
Keyword arguments parsed to yaml.dump.
|
||||
|
||||
"""
|
||||
try:
|
||||
if isinstance(fname, (str, Path)):
|
||||
fhandle = open(fname,'w',newline='\n')
|
||||
except TypeError:
|
||||
else:
|
||||
fhandle = fname
|
||||
|
||||
if 'width' not in kwargs:
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
import numpy as np
|
||||
import h5py
|
||||
from typing import Sequence, Dict, Any, Collection
|
||||
|
||||
from ._typehints import FileHandle
|
||||
from . import Config
|
||||
from . import Rotation
|
||||
from . import Orientation
|
||||
from . import util
|
||||
from . import Table
|
||||
|
||||
|
||||
class ConfigMaterial(Config):
|
||||
"""
|
||||
|
@ -17,7 +21,9 @@ class ConfigMaterial(Config):
|
|||
|
||||
"""
|
||||
|
||||
def __init__(self,d=None,**kwargs):
|
||||
def __init__(self,
|
||||
d: Dict[str, Any] = None,
|
||||
**kwargs):
|
||||
"""
|
||||
New material configuration.
|
||||
|
||||
|
@ -30,6 +36,7 @@ class ConfigMaterial(Config):
|
|||
Initial content specified as pairs of key=value.
|
||||
|
||||
"""
|
||||
default: Collection
|
||||
if d is None:
|
||||
for section, default in {'material':[],'homogenization':{},'phase':{}}.items():
|
||||
if section not in kwargs: kwargs.update({section:default})
|
||||
|
@ -37,7 +44,9 @@ class ConfigMaterial(Config):
|
|||
super().__init__(d,**kwargs)
|
||||
|
||||
|
||||
def save(self,fname='material.yaml',**kwargs):
|
||||
def save(self,
|
||||
fname: FileHandle = 'material.yaml',
|
||||
**kwargs):
|
||||
"""
|
||||
Save to yaml file.
|
||||
|
||||
|
@ -53,7 +62,8 @@ class ConfigMaterial(Config):
|
|||
|
||||
|
||||
@classmethod
|
||||
def load(cls,fname='material.yaml'):
|
||||
def load(cls,
|
||||
fname: FileHandle = 'material.yaml') -> 'ConfigMaterial':
|
||||
"""
|
||||
Load from yaml file.
|
||||
|
||||
|
@ -72,10 +82,14 @@ class ConfigMaterial(Config):
|
|||
|
||||
|
||||
@staticmethod
|
||||
def load_DREAM3D(fname,
|
||||
grain_data=None,cell_data=None,cell_ensemble_data='CellEnsembleData',
|
||||
phases='Phases',Euler_angles='EulerAngles',phase_names='PhaseName',
|
||||
base_group=None):
|
||||
def load_DREAM3D(fname: str,
|
||||
grain_data: str = None,
|
||||
cell_data: str = None,
|
||||
cell_ensemble_data: str = 'CellEnsembleData',
|
||||
phases: str = 'Phases',
|
||||
Euler_angles: str = 'EulerAngles',
|
||||
phase_names: str = 'PhaseName',
|
||||
base_group: str = None) -> 'ConfigMaterial':
|
||||
"""
|
||||
Load DREAM.3D (HDF5) file.
|
||||
|
||||
|
@ -154,7 +168,8 @@ class ConfigMaterial(Config):
|
|||
|
||||
|
||||
@staticmethod
|
||||
def from_table(table,**kwargs):
|
||||
def from_table(table: Table,
|
||||
**kwargs) -> 'ConfigMaterial':
|
||||
"""
|
||||
Generate from an ASCII table.
|
||||
|
||||
|
@ -207,7 +222,7 @@ class ConfigMaterial(Config):
|
|||
|
||||
|
||||
@property
|
||||
def is_complete(self):
|
||||
def is_complete(self) -> bool:
|
||||
"""
|
||||
Check for completeness.
|
||||
|
||||
|
@ -267,12 +282,11 @@ class ConfigMaterial(Config):
|
|||
if homogenization - set(self['homogenization']):
|
||||
print(f'Homogenization(s) {homogenization-set(self["homogenization"])} missing')
|
||||
ok = False
|
||||
|
||||
return ok
|
||||
|
||||
|
||||
@property
|
||||
def is_valid(self):
|
||||
def is_valid(self) -> bool:
|
||||
"""
|
||||
Check for valid content.
|
||||
|
||||
|
@ -316,7 +330,10 @@ class ConfigMaterial(Config):
|
|||
return ok
|
||||
|
||||
|
||||
def material_rename_phase(self,mapping,ID=None,constituent=None):
|
||||
def material_rename_phase(self,
|
||||
mapping: Dict[str, str],
|
||||
ID: Sequence[int] = None,
|
||||
constituent: Sequence[int] = None) -> 'ConfigMaterial':
|
||||
"""
|
||||
Change phase name in material.
|
||||
|
||||
|
@ -347,7 +364,9 @@ class ConfigMaterial(Config):
|
|||
return dup
|
||||
|
||||
|
||||
def material_rename_homogenization(self,mapping,ID=None):
|
||||
def material_rename_homogenization(self,
|
||||
mapping: Dict[str, str],
|
||||
ID: Sequence[int] = None) -> 'ConfigMaterial':
|
||||
"""
|
||||
Change homogenization name in material.
|
||||
|
||||
|
@ -374,7 +393,8 @@ class ConfigMaterial(Config):
|
|||
return dup
|
||||
|
||||
|
||||
def material_add(self,**kwargs):
|
||||
def material_add(self,
|
||||
**kwargs: Any) -> 'ConfigMaterial':
|
||||
"""
|
||||
Add material entries.
|
||||
|
||||
|
@ -453,7 +473,7 @@ class ConfigMaterial(Config):
|
|||
N = max(N,s[0]) if len(s)>0 else N
|
||||
n = max(n,s[1]) if len(s)>1 else n
|
||||
|
||||
mat = [{'constituents':[{} for _ in range(n)]} for _ in range(N)]
|
||||
mat: Sequence[dict] = [{'constituents':[{} for _ in range(n)]} for _ in range(N)]
|
||||
|
||||
if 'v' not in kwargs:
|
||||
shaped['v'] = np.broadcast_to(1/n,(N,n))
|
||||
|
|
|
@ -9,7 +9,7 @@ import re
|
|||
import fractions
|
||||
from collections import abc
|
||||
from functools import reduce
|
||||
from typing import Union, Tuple, Iterable, Callable, Dict, List, Any, Literal, Optional
|
||||
from typing import Union, Tuple, Iterable, Callable, Dict, List, Any, Literal, SupportsIndex, Sequence
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
|
@ -427,7 +427,7 @@ def hybrid_IA(dist: np.ndarray,
|
|||
def shapeshifter(fro: Tuple[int, ...],
|
||||
to: Tuple[int, ...],
|
||||
mode: Literal['left','right'] = 'left',
|
||||
keep_ones: bool = False) -> Tuple[Optional[int], ...]:
|
||||
keep_ones: bool = False) -> Sequence[SupportsIndex]:
|
||||
"""
|
||||
Return dimensions that reshape 'fro' to become broadcastable to 'to'.
|
||||
|
||||
|
@ -483,14 +483,14 @@ def shapeshifter(fro: Tuple[int, ...],
|
|||
grp = match.groups()
|
||||
except AssertionError:
|
||||
raise ValueError(f'Shapes can not be shifted {fro} --> {to}')
|
||||
fill: Tuple[Optional[int], ...] = ()
|
||||
fill: Any = ()
|
||||
for g,d in zip(grp,fro+(None,)):
|
||||
fill += (1,)*g.count(',')+(d,)
|
||||
return fill[:-1]
|
||||
|
||||
|
||||
def shapeblender(a: Tuple[int, ...],
|
||||
b: Tuple[int, ...]) -> Tuple[int, ...]:
|
||||
b: Tuple[int, ...]) -> Sequence[SupportsIndex]:
|
||||
"""
|
||||
Return a shape that overlaps the rightmost entries of 'a' with the leftmost of 'b'.
|
||||
|
||||
|
|
Loading…
Reference in New Issue