From ab2072bf2f5195389bd76d3bc9138d8532e57328 Mon Sep 17 00:00:00 2001 From: Daniel Otto de Mentock Date: Wed, 8 Jun 2022 15:50:35 +0200 Subject: [PATCH 01/13] apply_DAMASK_modifications script needs to be independent from damask installation (except solver variables) --- .../MarcMentat/apply_DAMASK_modifications.py | 48 +++++++++++++++---- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/install/MarcMentat/apply_DAMASK_modifications.py b/install/MarcMentat/apply_DAMASK_modifications.py index a17120895..473d26da7 100755 --- a/install/MarcMentat/apply_DAMASK_modifications.py +++ b/install/MarcMentat/apply_DAMASK_modifications.py @@ -1,20 +1,51 @@ #!/usr/bin/env python3 - import os import sys import glob import argparse import shutil from pathlib import Path +import importlib.machinery +import signal +import subprocess +import shlex +from functools import partial + +solver = importlib.machinery.SourceFileLoader( + 'damask',f'{str(Path(__file__).parent.absolute().parents[1])}/python/damask/solver/_marc.py').load_module() + +def run(cmd, wd='./', env=None, timeout=None): + def pass_signal(sig,_,proc,default): + proc.send_signal(sig) + signal.signal(sig,default) + signal.raise_signal(sig) + signals = [signal.SIGINT,signal.SIGTERM] + print(f"running '{cmd}' in '{wd}'") + process = subprocess.Popen(shlex.split(cmd), + stdout = subprocess.PIPE, + stderr = subprocess.PIPE, + env = os.environ if env is None else env, + cwd = wd, + encoding = 'utf-8') + sig_states = [signal.signal(sig,partial(pass_signal,proc=process,default=signal.getsignal(sig))) for sig in signals] + try: + stdout,stderr = process.communicate(timeout=timeout) + finally: + for sig,state in zip(signals,sig_states): + signal.signal(sig,state) + if process.returncode != 0: + print(stdout) + print(stderr) + raise RuntimeError(f"'{cmd}' failed with returncode {process.returncode}") + return stdout, stderr -import damask def copy_and_patch(patch,orig,editor): try: shutil.copyfile(orig,orig.parent/patch.stem) except shutil.SameFileError: pass - damask.util.run(f'patch {orig.parent/patch.stem} {patch} --backup --forward') + run(f'patch {orig.parent/patch.stem} {patch} --backup --forward') with open(orig.parent/patch.stem) as f_in: content = f_in.read() with open(orig.parent/patch.stem,'w') as f_out: @@ -28,15 +59,16 @@ parser = argparse.ArgumentParser( parser.add_argument('--editor', dest='editor', metavar='string', default='vi', help='Name of the editor (executable) used by Marc Mentat') parser.add_argument('--marc-root', dest='marc_root', metavar='string', - default=damask.solver._marc._marc_root, + default=solver._marc_root, help='Marc root directory') parser.add_argument('--marc-version', dest='marc_version', metavar='string', - default=damask.solver._marc._marc_version, + default=solver._marc_version, help='Marc version') parser.add_argument('--damask-root', dest='damask_root', metavar = 'string', - default=damask.solver._marc._damask_root, + default=solver._damask_root, help='DAMASK root directory') + args = parser.parse_args() marc_root = Path(args.marc_root).expanduser() damask_root = Path(args.damask_root).expanduser() @@ -52,7 +84,7 @@ matches = {'Marc_tools': [['comp_user','comp_damask_*mp'], for cmd in ['patch','xvfb-run']: try: - damask.util.run(f'{cmd} --help') + run(f'{cmd} --help') except FileNotFoundError: print(f'"{cmd}" not found, please install') sys.exit() @@ -71,7 +103,7 @@ print('compiling Mentat menu binaries...') executable = marc_root/f'mentat{marc_version}/bin/mentat' menu_file = marc_root/f'mentat{marc_version}/menus/linux64/main.msb' -damask.util.run(f'xvfb-run -a {executable} -compile {menu_file}') +run(f'xvfb-run -a {executable} -compile {menu_file}') print('setting file access rights...') From 1ed7bbabefdc6bdb735c27080956649c9d15fc84 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Thu, 9 Jun 2022 00:12:19 +0200 Subject: [PATCH 02/13] signal handling etc. not needed here --- .../MarcMentat/apply_DAMASK_modifications.py | 34 ++----------------- 1 file changed, 3 insertions(+), 31 deletions(-) diff --git a/install/MarcMentat/apply_DAMASK_modifications.py b/install/MarcMentat/apply_DAMASK_modifications.py index 473d26da7..208abdd6f 100755 --- a/install/MarcMentat/apply_DAMASK_modifications.py +++ b/install/MarcMentat/apply_DAMASK_modifications.py @@ -6,46 +6,18 @@ import argparse import shutil from pathlib import Path import importlib.machinery -import signal import subprocess import shlex -from functools import partial solver = importlib.machinery.SourceFileLoader( 'damask',f'{str(Path(__file__).parent.absolute().parents[1])}/python/damask/solver/_marc.py').load_module() -def run(cmd, wd='./', env=None, timeout=None): - def pass_signal(sig,_,proc,default): - proc.send_signal(sig) - signal.signal(sig,default) - signal.raise_signal(sig) - signals = [signal.SIGINT,signal.SIGTERM] - print(f"running '{cmd}' in '{wd}'") - process = subprocess.Popen(shlex.split(cmd), - stdout = subprocess.PIPE, - stderr = subprocess.PIPE, - env = os.environ if env is None else env, - cwd = wd, - encoding = 'utf-8') - sig_states = [signal.signal(sig,partial(pass_signal,proc=process,default=signal.getsignal(sig))) for sig in signals] - try: - stdout,stderr = process.communicate(timeout=timeout) - finally: - for sig,state in zip(signals,sig_states): - signal.signal(sig,state) - if process.returncode != 0: - print(stdout) - print(stderr) - raise RuntimeError(f"'{cmd}' failed with returncode {process.returncode}") - return stdout, stderr - - def copy_and_patch(patch,orig,editor): try: shutil.copyfile(orig,orig.parent/patch.stem) except shutil.SameFileError: pass - run(f'patch {orig.parent/patch.stem} {patch} --backup --forward') + subprocess.run(shlex.split(f'patch {orig.parent/patch.stem} {patch} --backup --forward')) with open(orig.parent/patch.stem) as f_in: content = f_in.read() with open(orig.parent/patch.stem,'w') as f_out: @@ -84,7 +56,7 @@ matches = {'Marc_tools': [['comp_user','comp_damask_*mp'], for cmd in ['patch','xvfb-run']: try: - run(f'{cmd} --help') + subprocess.run(shlex.split(f'{cmd} --help')) except FileNotFoundError: print(f'"{cmd}" not found, please install') sys.exit() @@ -103,7 +75,7 @@ print('compiling Mentat menu binaries...') executable = marc_root/f'mentat{marc_version}/bin/mentat' menu_file = marc_root/f'mentat{marc_version}/menus/linux64/main.msb' -run(f'xvfb-run -a {executable} -compile {menu_file}') +subprocess.run(shlex.split(f'xvfb-run -a {executable} -compile {menu_file}')) print('setting file access rights...') From ea6199b9085d6ba5310a6ef866fc2395866ad1c2 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Thu, 9 Jun 2022 00:22:04 +0200 Subject: [PATCH 03/13] simplified --- install/MarcMentat/apply_DAMASK_modifications.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/install/MarcMentat/apply_DAMASK_modifications.py b/install/MarcMentat/apply_DAMASK_modifications.py index 208abdd6f..353df955e 100755 --- a/install/MarcMentat/apply_DAMASK_modifications.py +++ b/install/MarcMentat/apply_DAMASK_modifications.py @@ -1,16 +1,16 @@ #!/usr/bin/env python3 + import os import sys import glob import argparse import shutil from pathlib import Path -import importlib.machinery import subprocess import shlex -solver = importlib.machinery.SourceFileLoader( - 'damask',f'{str(Path(__file__).parent.absolute().parents[1])}/python/damask/solver/_marc.py').load_module() +sys.path.append(str(Path(__file__).parents[2]/'python/damask')) +import solver def copy_and_patch(patch,orig,editor): try: @@ -31,13 +31,13 @@ parser = argparse.ArgumentParser( parser.add_argument('--editor', dest='editor', metavar='string', default='vi', help='Name of the editor (executable) used by Marc Mentat') parser.add_argument('--marc-root', dest='marc_root', metavar='string', - default=solver._marc_root, + default=solver._marc._marc_root, help='Marc root directory') parser.add_argument('--marc-version', dest='marc_version', metavar='string', - default=solver._marc_version, + default=solver._marc._marc_version, help='Marc version') parser.add_argument('--damask-root', dest='damask_root', metavar = 'string', - default=solver._damask_root, + default=solver._marc._damask_root, help='DAMASK root directory') From b3b14e91047e205fecd129e26642287d9cd2628a Mon Sep 17 00:00:00 2001 From: Test User Date: Thu, 9 Jun 2022 17:47:00 +0200 Subject: [PATCH 04/13] [skip ci] updated version information after successful test of v3.0.0-alpha6-447-g42ee6310b --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 6c99f4893..896507f8b 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.0.0-alpha6-442-g49e40923e +3.0.0-alpha6-447-g42ee6310b From 8fefc46f388acc97589b9139dca021c65e5c5dbd Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Thu, 9 Jun 2022 16:38:13 -0400 Subject: [PATCH 05/13] fixed FZ conditions and tightened tolerance to accommodate higher precision "tfit" --- python/damask/_orientation.py | 7 +++++-- python/damask/_rotation.py | 25 +++++++++++++++---------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/python/damask/_orientation.py b/python/damask/_orientation.py index dcc139b7c..7d6dee3ff 100644 --- a/python/damask/_orientation.py +++ b/python/damask/_orientation.py @@ -448,9 +448,12 @@ class Orientation(Rotation,Crystal): elif self.family == 'orthorhombic': return (np.prod(1. >= rho_abs,axis=-1)).astype(bool) elif self.family == 'monoclinic': - return (1. >= rho_abs[...,1]).astype(bool) + return np.logical_or( 1. >= rho_abs[...,1], + np.isnan(rho_abs[...,1])) + elif self.family == 'triclinic': + return np.ones(rho_abs.shape[:-1]).astype(bool) else: - return np.all(np.isfinite(rho_abs),axis=-1) + raise(TypeError, f'unknown symmetry "{self.family}"') @property diff --git a/python/damask/_rotation.py b/python/damask/_rotation.py index 61529eb46..06f87abc5 100644 --- a/python/damask/_rotation.py +++ b/python/damask/_rotation.py @@ -1372,7 +1372,7 @@ class Rotation: w[np.isclose(w[...,0],1.0+0.0j),1:] = 0. w[np.isclose(w[...,1],1.0+0.0j),2:] = 0. vr = np.swapaxes(vr,-1,-2) - ax = np.where(np.abs(diag_delta)<1e-12, + ax = np.where(np.abs(diag_delta)<1e-13, np.real(vr[np.isclose(w,1.0+0.0j)]).reshape(om.shape[:-2]+(3,)), np.abs(np.real(vr[np.isclose(w,1.0+0.0j)]).reshape(om.shape[:-2]+(3,))) \ *np.sign(diag_delta)) @@ -1581,14 +1581,19 @@ class Rotation: @staticmethod def _ho2ax(ho: np.ndarray) -> np.ndarray: """Homochoric vector to axis–angle pair.""" - tfit = np.array([+1.0000000000018852, -0.5000000002194847, - -0.024999992127593126, -0.003928701544781374, - -0.0008152701535450438, -0.0002009500426119712, - -0.00002397986776071756, -0.00008202868926605841, - +0.00012448715042090092, -0.0001749114214822577, - +0.0001703481934140054, -0.00012062065004116828, - +0.000059719705868660826, -0.00001980756723965647, - +0.000003953714684212874, -0.00000036555001439719544]) + tfit = np.array([ + 0.9999999999999968E0, -0.49999999999986866E0, + -0.025000000000632055E0, -0.003928571496460683E0, + -0.0008164666077062752E0, -0.00019411896443261646E0, + -0.00004985822229871769E0, -0.000014164962366386031E0, + -1.9000248160936107E-6, -5.72184549898506E-6, + 7.772149920658778E-6, -0.00001053483452909705E0, + 9.528014229335313E-6, -5.660288876265125E-6, + 1.2844901692764126E-6, 1.1255185726258763E-6, + -1.3834391419956455E-6, 7.513691751164847E-7, + -2.401996891720091E-7, 4.386887017466388E-8, + -3.5917775353564864E-9, + ]) hmag_squared = np.sum(ho**2.,axis=-1,keepdims=True) s = np.sum(tfit*hmag_squared**np.arange(len(tfit)),axis=-1,keepdims=True) with np.errstate(invalid='ignore'): @@ -1679,7 +1684,7 @@ class Rotation: """ with np.errstate(invalid='ignore',divide='ignore'): - # get pyramide and scale by grid parameter ratio + # get pyramid and scale by grid parameter ratio XYZ = np.take_along_axis(cu,Rotation._get_pyramid_order(cu,'forward'),-1) * _sc order = np.abs(XYZ[...,1:2]) <= np.abs(XYZ[...,0:1]) q = np.pi/12.0 * np.where(order,XYZ[...,1:2],XYZ[...,0:1]) \ From d10516e0b6489f7dfdb743bedc07dd7cf857a519 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Thu, 9 Jun 2022 17:23:16 -0400 Subject: [PATCH 06/13] fixed typo --- python/damask/_orientation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/damask/_orientation.py b/python/damask/_orientation.py index 7d6dee3ff..4721143da 100644 --- a/python/damask/_orientation.py +++ b/python/damask/_orientation.py @@ -453,7 +453,7 @@ class Orientation(Rotation,Crystal): elif self.family == 'triclinic': return np.ones(rho_abs.shape[:-1]).astype(bool) else: - raise(TypeError, f'unknown symmetry "{self.family}"') + raise TypeError(f'unknown symmetry "{self.family}"') @property From cdd3b44519e327439d5e7737dfead55f41e1a88e Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Thu, 9 Jun 2022 23:16:02 +0200 Subject: [PATCH 07/13] using more precise coefficients also in test changes in _rotation.py are just cosmetic --- python/damask/_rotation.py | 20 +++++++------------- python/tests/test_Rotation.py | 15 +++++++-------- 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/python/damask/_rotation.py b/python/damask/_rotation.py index 06f87abc5..f93b3b012 100644 --- a/python/damask/_rotation.py +++ b/python/damask/_rotation.py @@ -1581,19 +1581,13 @@ class Rotation: @staticmethod def _ho2ax(ho: np.ndarray) -> np.ndarray: """Homochoric vector to axis–angle pair.""" - tfit = np.array([ - 0.9999999999999968E0, -0.49999999999986866E0, - -0.025000000000632055E0, -0.003928571496460683E0, - -0.0008164666077062752E0, -0.00019411896443261646E0, - -0.00004985822229871769E0, -0.000014164962366386031E0, - -1.9000248160936107E-6, -5.72184549898506E-6, - 7.772149920658778E-6, -0.00001053483452909705E0, - 9.528014229335313E-6, -5.660288876265125E-6, - 1.2844901692764126E-6, 1.1255185726258763E-6, - -1.3834391419956455E-6, 7.513691751164847E-7, - -2.401996891720091E-7, 4.386887017466388E-8, - -3.5917775353564864E-9, - ]) + tfit = np.array([+0.9999999999999968, -0.49999999999986866, -0.025000000000632055, + -0.003928571496460683, -0.0008164666077062752, -0.00019411896443261646, + -0.00004985822229871769, -0.000014164962366386031, -1.9000248160936107e-6, + -5.72184549898506e-6, +7.772149920658778e-6, -0.00001053483452909705, + +9.528014229335313e-6, -5.660288876265125e-6, +1.2844901692764126e-6, + +1.1255185726258763e-6, -1.3834391419956455e-6, +7.513691751164847e-7, + -2.401996891720091e-7, +4.386887017466388e-8, -3.5917775353564864e-9]) hmag_squared = np.sum(ho**2.,axis=-1,keepdims=True) s = np.sum(tfit*hmag_squared**np.arange(len(tfit)),axis=-1,keepdims=True) with np.errstate(invalid='ignore'): diff --git a/python/tests/test_Rotation.py b/python/tests/test_Rotation.py index c9dfc68b8..8b1bd0de8 100644 --- a/python/tests/test_Rotation.py +++ b/python/tests/test_Rotation.py @@ -301,14 +301,13 @@ def ro2ho(ro): #---------- Homochoric vector---------- def ho2ax(ho): """Homochoric vector to axis angle pair.""" - tfit = np.array([+1.0000000000018852, -0.5000000002194847, - -0.024999992127593126, -0.003928701544781374, - -0.0008152701535450438, -0.0002009500426119712, - -0.00002397986776071756, -0.00008202868926605841, - +0.00012448715042090092, -0.0001749114214822577, - +0.0001703481934140054, -0.00012062065004116828, - +0.000059719705868660826, -0.00001980756723965647, - +0.000003953714684212874, -0.00000036555001439719544]) + tfit = np.array([+0.9999999999999968, -0.49999999999986866, -0.025000000000632055, + -0.003928571496460683, -0.0008164666077062752, -0.00019411896443261646, + -0.00004985822229871769, -0.000014164962366386031, -1.9000248160936107e-6, + -5.72184549898506e-6, +7.772149920658778e-6, -0.00001053483452909705, + +9.528014229335313e-6, -5.660288876265125e-6, +1.2844901692764126e-6, + +1.1255185726258763e-6, -1.3834391419956455e-6, +7.513691751164847e-7, + -2.401996891720091e-7, +4.386887017466388e-8, -3.5917775353564864e-9]) # normalize h and store the magnitude hmag_squared = np.sum(ho**2.) if iszero(hmag_squared): From bcd3d00960511dd140cfac3b92a3eede7b24d947 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Thu, 9 Jun 2022 23:28:04 +0200 Subject: [PATCH 08/13] fixed test this tests should ensure that each Orientation has exactly one symmetrically equivalent representation. It was not fully correct before and works as expected after 8fefc46f388acc97589b9139dca021c65e5c5dbd --- python/tests/test_Orientation.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/tests/test_Orientation.py b/python/tests/test_Orientation.py index 5f9b83e70..2cb97d252 100644 --- a/python/tests/test_Orientation.py +++ b/python/tests/test_Orientation.py @@ -224,11 +224,11 @@ class TestOrientation: @pytest.mark.parametrize('family',crystal_families) def test_reduced_corner_cases(self,family): - # test whether there is always a sym-eq rotation that falls into the FZ + # test whether there is always exactly one sym-eq rotation that falls into the FZ N = np.random.randint(10,40) size = np.ones(3)*np.pi**(2./3.) grid = grid_filters.coordinates0_node([N+1,N+1,N+1],size,-size*.5) - evenly_distributed = Orientation.from_cubochoric(x=grid[:-2,:-2,:-2],family=family) + evenly_distributed = Orientation.from_cubochoric(x=grid,family=family) assert evenly_distributed.shape == evenly_distributed.reduced.shape @pytest.mark.parametrize('family',crystal_families) From afbafd1d981479d8d4584909c87ce20401f7791f Mon Sep 17 00:00:00 2001 From: "d.mentock" Date: Fri, 10 Jun 2022 12:00:54 +0200 Subject: [PATCH 09/13] util imports need prefix instead of __all__ definition to prevent namespace pollution --- python/damask/util.py | 238 +++++++++++++++++++----------------------- 1 file changed, 110 insertions(+), 128 deletions(-) diff --git a/python/damask/util.py b/python/damask/util.py index ab3789bf5..468ac49ec 100644 --- a/python/damask/util.py +++ b/python/damask/util.py @@ -1,43 +1,25 @@ """Miscellaneous helper functionality.""" -import sys -import datetime -import os -import subprocess -import shlex -import re -import signal -import fractions -from collections import abc -from functools import reduce, partial -from typing import Callable, Union, Iterable, Sequence, Dict, List, Tuple, Literal, Any, Collection, TextIO -from pathlib import Path +import sys as _sys +import datetime as _datetime +import os as _os +import subprocess as _subprocess +import shlex as _shlex +import re as _re +import signal as _signal +import fractions as _fractions +from collections import abc as _abc +from functools import reduce as _reduce, partial as _partial +from typing import Callable as _Callable, Union as _Union, Iterable as _Iterable, Sequence as _Sequence, Dict as _Dict, \ + List as _List, Tuple as _Tuple, Literal as _Literal, Any as _Any, Collection as _Collection, TextIO as _TextIO +from pathlib import Path as _Path -import numpy as np -import h5py +import numpy as _np +import h5py as _h5py -from . import version -from ._typehints import FloatSequence, NumpyRngSeed, IntCollection, FileHandle - -# limit visibility -__all__=[ - 'srepr', - 'emph', 'deemph', 'warn', 'strikeout', - 'run', - 'open_text', - 'natural_sort', - 'show_progress', - 'scale_to_coprime', - 'project_equal_angle', 'project_equal_area', - 'hybrid_IA', - 'execution_stamp', - 'shapeshifter', 'shapeblender', - 'extend_docstring', 'extended_docstring', - 'Bravais_to_Miller', 'Miller_to_Bravais', - 'DREAM3D_base_group', 'DREAM3D_cell_data_group', - 'dict_prune', 'dict_flatten', - 'tail_repack', - ] +from . import version as _version +from ._typehints import FloatSequence as _FloatSequence, NumpyRngSeed as _NumpyRngSeed, IntCollection as _IntCollection, \ + FileHandle as _FileHandle # https://svn.blender.org/svnroot/bf-blender/trunk/blender/build_files/scons/tools/bcolors.py # https://stackoverflow.com/questions/287871 @@ -154,8 +136,8 @@ def strikeout(msg) -> str: def run(cmd: str, wd: str = './', - env: Dict[str, str] = None, - timeout: int = None) -> Tuple[str, str]: + env: _Dict[str, str] = None, + timeout: int = None) -> _Tuple[str, str]: """ Run a command. @@ -178,26 +160,26 @@ def run(cmd: str, """ def pass_signal(sig,_,proc,default): proc.send_signal(sig) - signal.signal(sig,default) - signal.raise_signal(sig) + _signal.signal(sig,default) + _signal.raise_signal(sig) - signals = [signal.SIGINT,signal.SIGTERM] + signals = [_signal.SIGINT,_signal.SIGTERM] print(f"running '{cmd}' in '{wd}'") - process = subprocess.Popen(shlex.split(cmd), - stdout = subprocess.PIPE, - stderr = subprocess.PIPE, - env = os.environ if env is None else env, + process = _subprocess.Popen(_shlex.split(cmd), + stdout = _subprocess.PIPE, + stderr = _subprocess.PIPE, + env = _os.environ if env is None else env, cwd = wd, encoding = 'utf-8') # ensure that process is terminated (https://stackoverflow.com/questions/22916783) - sig_states = [signal.signal(sig,partial(pass_signal,proc=process,default=signal.getsignal(sig))) for sig in signals] + sig_states = [_signal.signal(sig,_partial(pass_signal,proc=process,default=_signal.getsignal(sig))) for sig in signals] try: stdout,stderr = process.communicate(timeout=timeout) finally: for sig,state in zip(signals,sig_states): - signal.signal(sig,state) + _signal.signal(sig,state) if process.returncode != 0: print(stdout) @@ -207,8 +189,8 @@ def run(cmd: str, return stdout, stderr -def open_text(fname: FileHandle, - mode: Literal['r','w'] = 'r') -> TextIO: +def open_text(fname: _FileHandle, + mode: _Literal['r','w'] = 'r') -> _TextIO: """ Open a text file. @@ -224,11 +206,11 @@ def open_text(fname: FileHandle, f : file handle """ - return fname if not isinstance(fname, (str,Path)) else \ - open(Path(fname).expanduser(),mode,newline=('\n' if mode == 'w' else None)) + return fname if not isinstance(fname, (str,_Path)) else \ + open(_Path(fname).expanduser(),mode,newline=('\n' if mode == 'w' else None)) -def natural_sort(key: str) -> List[Union[int, str]]: +def natural_sort(key: str) -> _List[_Union[int, str]]: """ Natural sort. @@ -240,13 +222,13 @@ def natural_sort(key: str) -> List[Union[int, str]]: """ convert = lambda text: int(text) if text.isdigit() else text - return [ convert(c) for c in re.split('([0-9]+)', key) ] + return [ convert(c) for c in _re.split('([0-9]+)', key) ] -def show_progress(iterable: Iterable, +def show_progress(iterable: _Iterable, N_iter: int = None, prefix: str = '', - bar_length: int = 50) -> Any: + bar_length: int = 50) -> _Any: """ Decorate a loop with a progress bar. @@ -264,7 +246,7 @@ def show_progress(iterable: Iterable, Length of progress bar in characters. Defaults to 50. """ - if isinstance(iterable,abc.Sequence): + if isinstance(iterable,_abc.Sequence): if N_iter is None: N = len(iterable) else: @@ -285,7 +267,7 @@ def show_progress(iterable: Iterable, status.update(i) -def scale_to_coprime(v: FloatSequence) -> np.ndarray: +def scale_to_coprime(v: _FloatSequence) -> _np.ndarray: """ Scale vector to co-prime (relatively prime) integers. @@ -304,30 +286,30 @@ def scale_to_coprime(v: FloatSequence) -> np.ndarray: def get_square_denominator(x): """Denominator of the square of a number.""" - return fractions.Fraction(x ** 2).limit_denominator(MAX_DENOMINATOR).denominator + return _fractions.Fraction(x ** 2).limit_denominator(MAX_DENOMINATOR).denominator def lcm(a,b): """Least common multiple.""" try: - return np.lcm(a,b) # numpy > 1.18 + return _np.lcm(a,b) # numpy > 1.18 except AttributeError: - return a * b // np.gcd(a, b) + return a * b // _np.gcd(a, b) - v_ = np.array(v) - m = (v_ * reduce(lcm, map(lambda x: int(get_square_denominator(x)),v_))**0.5).astype(np.int64) - m = m//reduce(np.gcd,m) + v_ = _np.array(v) + m = (v_ * _reduce(lcm, map(lambda x: int(get_square_denominator(x)),v_))**0.5).astype(_np.int64) + m = m//_reduce(_np.gcd,m) - with np.errstate(invalid='ignore'): - if not np.allclose(np.ma.masked_invalid(v_/m),v_[np.argmax(abs(v_))]/m[np.argmax(abs(v_))]): + with _np.errstate(invalid='ignore'): + if not _np.allclose(_np.ma.masked_invalid(v_/m),v_[_np.argmax(abs(v_))]/m[_np.argmax(abs(v_))]): raise ValueError(f'invalid result "{m}" for input "{v_}"') return m -def project_equal_angle(vector: np.ndarray, - direction: Literal['x', 'y', 'z'] = 'z', +def project_equal_angle(vector: _np.ndarray, + direction: _Literal['x', 'y', 'z'] = 'z', normalize: bool = True, - keepdims: bool = False) -> np.ndarray: + keepdims: bool = False) -> _np.ndarray: """ Apply equal-angle projection to vector. @@ -367,15 +349,15 @@ def project_equal_angle(vector: np.ndarray, """ shift = 'zyx'.index(direction) - v = np.roll(vector/np.linalg.norm(vector,axis=-1,keepdims=True) if normalize else vector, + v = _np.roll(vector/_np.linalg.norm(vector,axis=-1,keepdims=True) if normalize else vector, shift,axis=-1) - return np.roll(np.block([v[...,:2]/(1.0+np.abs(v[...,2:3])),np.zeros_like(v[...,2:3])]), + return _np.roll(_np.block([v[...,:2]/(1.0+_np.abs(v[...,2:3])),_np.zeros_like(v[...,2:3])]), -shift if keepdims else 0,axis=-1)[...,:3 if keepdims else 2] -def project_equal_area(vector: np.ndarray, - direction: Literal['x', 'y', 'z'] = 'z', +def project_equal_area(vector: _np.ndarray, + direction: _Literal['x', 'y', 'z'] = 'z', normalize: bool = True, - keepdims: bool = False) -> np.ndarray: + keepdims: bool = False) -> _np.ndarray: """ Apply equal-area projection to vector. @@ -416,22 +398,22 @@ def project_equal_area(vector: np.ndarray, """ shift = 'zyx'.index(direction) - v = np.roll(vector/np.linalg.norm(vector,axis=-1,keepdims=True) if normalize else vector, + v = _np.roll(vector/_np.linalg.norm(vector,axis=-1,keepdims=True) if normalize else vector, shift,axis=-1) - 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] 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') + 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})' + return f'damask.{class_name}{_function_name} v{_version} ({now})' -def hybrid_IA(dist: np.ndarray, +def hybrid_IA(dist: _np.ndarray, N: int, - rng_seed: NumpyRngSeed = None) -> np.ndarray: + rng_seed: _NumpyRngSeed = None) -> _np.ndarray: """ Hybrid integer approximation. @@ -446,23 +428,23 @@ def hybrid_IA(dist: np.ndarray, If None, then fresh, unpredictable entropy will be pulled from the OS. """ - N_opt_samples,N_inv_samples = (max(np.count_nonzero(dist),N),0) # random subsampling if too little samples requested + N_opt_samples,N_inv_samples = (max(_np.count_nonzero(dist),N),0) # random subsampling if too little samples requested scale_,scale,inc_factor = (0.0,float(N_opt_samples),1.0) - while (not np.isclose(scale, scale_)) and (N_inv_samples != N_opt_samples): - repeats = np.rint(scale*dist).astype(np.int64) - N_inv_samples = np.sum(repeats) + while (not _np.isclose(scale, scale_)) and (N_inv_samples != N_opt_samples): + repeats = _np.rint(scale*dist).astype(_np.int64) + N_inv_samples = _np.sum(repeats) scale_,scale,inc_factor = (scale,scale+inc_factor*0.5*(scale - scale_), inc_factor*2.0) \ if N_inv_samples < N_opt_samples else \ (scale_,0.5*(scale_ + scale), 1.0) - return np.repeat(np.arange(len(dist)),repeats)[np.random.default_rng(rng_seed).permutation(N_inv_samples)[:N]] + return _np.repeat(_np.arange(len(dist)),repeats)[_np.random.default_rng(rng_seed).permutation(N_inv_samples)[:N]] -def shapeshifter(fro: Tuple[int, ...], - to: Tuple[int, ...], - mode: Literal['left','right'] = 'left', - keep_ones: bool = False) -> Tuple[int, ...]: +def shapeshifter(fro: _Tuple[int, ...], + to: _Tuple[int, ...], + mode: _Literal['left','right'] = 'left', + keep_ones: bool = False) -> _Tuple[int, ...]: """ Return dimensions that reshape 'fro' to become broadcastable to 'to'. @@ -509,7 +491,7 @@ def shapeshifter(fro: Tuple[int, ...], fro = (1,) if len(fro) == 0 else fro to = (1,) if len(to) == 0 else to try: - match = re.match(beg[mode] + match = _re.match(beg[mode] +f',{sep[mode]}'.join(map(lambda x: f'{x}' if x>1 or (keep_ones and len(fro)>1) else '\\d+',fro)) @@ -518,14 +500,14 @@ def shapeshifter(fro: Tuple[int, ...], grp = match.groups() except AssertionError: raise ValueError(f'shapes cannot be shifted {fro} --> {to}') - fill: Any = () + 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, ...]: +def shapeblender(a: _Tuple[int, ...], + b: _Tuple[int, ...]) -> _Tuple[int, ...]: """ Return a shape that overlaps the rightmost entries of 'a' with the leftmost of 'b'. @@ -553,7 +535,7 @@ def shapeblender(a: Tuple[int, ...], return a + b[i:] -def extend_docstring(extra_docstring: str) -> Callable: +def extend_docstring(extra_docstring: str) -> _Callable: """ Decorator: Append to function's docstring. @@ -569,8 +551,8 @@ def extend_docstring(extra_docstring: str) -> Callable: return _decorator -def extended_docstring(f: Callable, - extra_docstring: str) -> Callable: +def extended_docstring(f: _Callable, + extra_docstring: str) -> _Callable: """ Decorator: Combine another function's docstring with a given docstring. @@ -588,7 +570,7 @@ def extended_docstring(f: Callable, return _decorator -def DREAM3D_base_group(fname: Union[str, Path]) -> str: +def DREAM3D_base_group(fname: _Union[str, _Path]) -> str: """ Determine the base group of a DREAM.3D file. @@ -606,7 +588,7 @@ def DREAM3D_base_group(fname: Union[str, Path]) -> str: Path to the base group. """ - with h5py.File(Path(fname).expanduser(),'r') as f: + with _h5py.File(_Path(fname).expanduser(),'r') as f: base_group = f.visit(lambda path: path.rsplit('/',2)[0] if '_SIMPL_GEOMETRY/SPACING' in path else None) if base_group is None: @@ -614,7 +596,7 @@ def DREAM3D_base_group(fname: Union[str, Path]) -> str: return base_group -def DREAM3D_cell_data_group(fname: Union[str, Path]) -> str: +def DREAM3D_cell_data_group(fname: _Union[str, _Path]) -> str: """ Determine the cell data group of a DREAM.3D file. @@ -634,10 +616,10 @@ def DREAM3D_cell_data_group(fname: Union[str, Path]) -> str: """ base_group = DREAM3D_base_group(fname) - with h5py.File(Path(fname).expanduser(),'r') as f: + with _h5py.File(_Path(fname).expanduser(),'r') as f: cells = tuple(f['/'.join([base_group,'_SIMPL_GEOMETRY','DIMENSIONS'])][()][::-1]) cell_data_group = f[base_group].visititems(lambda path,obj: path.split('/')[0] \ - if isinstance(obj,h5py._hl.dataset.Dataset) and np.shape(obj)[:-1] == cells \ + if isinstance(obj,_h5py._hl.dataset.Dataset) and _np.shape(obj)[:-1] == cells \ else None) if cell_data_group is None: @@ -647,8 +629,8 @@ def DREAM3D_cell_data_group(fname: Union[str, Path]) -> str: def Bravais_to_Miller(*, - uvtw: np.ndarray = None, - hkil: np.ndarray = None) -> np.ndarray: + uvtw: _np.ndarray = None, + hkil: _np.ndarray = None) -> _np.ndarray: """ Transform 4 Miller–Bravais indices to 3 Miller indices of crystal direction [uvw] or plane normal (hkl). @@ -665,19 +647,19 @@ def Bravais_to_Miller(*, """ if (uvtw is not None) ^ (hkil is None): raise KeyError('specify either "uvtw" or "hkil"') - axis,basis = (np.array(uvtw),np.array([[1,0,-1,0], + axis,basis = (_np.array(uvtw),_np.array([[1,0,-1,0], [0,1,-1,0], [0,0, 0,1]])) \ if hkil is None else \ - (np.array(hkil),np.array([[1,0,0,0], + (_np.array(hkil),_np.array([[1,0,0,0], [0,1,0,0], [0,0,0,1]])) - return np.einsum('il,...l',basis,axis) + return _np.einsum('il,...l',basis,axis) def Miller_to_Bravais(*, - uvw: np.ndarray = None, - hkl: np.ndarray = None) -> np.ndarray: + uvw: _np.ndarray = None, + hkl: _np.ndarray = None) -> _np.ndarray: """ Transform 3 Miller indices to 4 Miller–Bravais indices of crystal direction [uvtw] or plane normal (hkil). @@ -694,19 +676,19 @@ def Miller_to_Bravais(*, """ if (uvw is not None) ^ (hkl is None): raise KeyError('specify either "uvw" or "hkl"') - axis,basis = (np.array(uvw),np.array([[ 2,-1, 0], + axis,basis = (_np.array(uvw),_np.array([[ 2,-1, 0], [-1, 2, 0], [-1,-1, 0], [ 0, 0, 3]])/3) \ if hkl is None else \ - (np.array(hkl),np.array([[ 1, 0, 0], + (_np.array(hkl),_np.array([[ 1, 0, 0], [ 0, 1, 0], [-1,-1, 0], [ 0, 0, 1]])) - return np.einsum('il,...l',basis,axis) + return _np.einsum('il,...l',basis,axis) -def dict_prune(d: Dict) -> Dict: +def dict_prune(d: _Dict) -> _Dict: """ Recursively remove empty dictionaries. @@ -732,7 +714,7 @@ def dict_prune(d: Dict) -> Dict: return new -def dict_flatten(d: Dict) -> Dict: +def dict_flatten(d: _Dict) -> _Dict: """ Recursively remove keys of single-entry dictionaries. @@ -756,8 +738,8 @@ def dict_flatten(d: Dict) -> Dict: return new -def tail_repack(extended: Union[str, Sequence[str]], - existing: List[str] = []) -> List[str]: +def tail_repack(extended: _Union[str, _Sequence[str]], + existing: _List[str] = []) -> _List[str]: """ Repack tailing characters into single string if all are new. @@ -782,11 +764,11 @@ def tail_repack(extended: Union[str, Sequence[str]], """ return [extended] if isinstance(extended,str) else existing + \ - ([''.join(extended[len(existing):])] if np.prod([len(i) for i in extended[len(existing):]]) == 1 else + ([''.join(extended[len(existing):])] if _np.prod([len(i) for i in extended[len(existing):]]) == 1 else list(extended[len(existing):])) -def aslist(arg: Union[IntCollection,int,None]) -> List: +def aslist(arg: _Union[_IntCollection, int, None]) -> _List: """ Transform argument to list. @@ -801,7 +783,7 @@ def aslist(arg: Union[IntCollection,int,None]) -> List: Entity transformed into list. """ - return [] if arg is None else list(arg) if isinstance(arg,(np.ndarray,Collection)) else [arg] + return [] if arg is None else list(arg) if isinstance(arg,(_np.ndarray,_Collection)) else [arg] #################################################################################################### @@ -834,11 +816,11 @@ class ProgressBar: self.total = total self.prefix = prefix self.bar_length = bar_length - self.time_start = self.time_last_update = datetime.datetime.now() + self.time_start = self.time_last_update = _datetime.datetime.now() self.fraction_last = 0.0 - sys.stderr.write(f"{self.prefix} {'░'*self.bar_length} 0% ETA n/a") - sys.stderr.flush() + _sys.stderr.write(f"{self.prefix} {'░'*self.bar_length} 0% ETA n/a") + _sys.stderr.flush() def update(self, iteration: int) -> None: @@ -846,17 +828,17 @@ class ProgressBar: fraction = (iteration+1) / self.total if (filled_length := int(self.bar_length * fraction)) > int(self.bar_length * self.fraction_last) or \ - datetime.datetime.now() - self.time_last_update > datetime.timedelta(seconds=10): - self.time_last_update = datetime.datetime.now() + _datetime.datetime.now() - self.time_last_update > _datetime.timedelta(seconds=10): + self.time_last_update = _datetime.datetime.now() bar = '█' * filled_length + '░' * (self.bar_length - filled_length) - remaining_time = (datetime.datetime.now() - self.time_start) \ + remaining_time = (_datetime.datetime.now() - self.time_start) \ * (self.total - (iteration+1)) / (iteration+1) - remaining_time -= datetime.timedelta(microseconds=remaining_time.microseconds) # remove μs - sys.stderr.write(f'\r{self.prefix} {bar} {fraction:>4.0%} ETA {remaining_time}') - sys.stderr.flush() + remaining_time -= _datetime.timedelta(microseconds=remaining_time.microseconds) # remove μs + _sys.stderr.write(f'\r{self.prefix} {bar} {fraction:>4.0%} ETA {remaining_time}') + _sys.stderr.flush() self.fraction_last = fraction if iteration == self.total - 1: - sys.stderr.write('\n') - sys.stderr.flush() + _sys.stderr.write('\n') + _sys.stderr.flush() From d88a139a41b0b47d9c0c242d181a1c0d5c3c6e39 Mon Sep 17 00:00:00 2001 From: "d.mentock" Date: Fri, 10 Jun 2022 12:03:50 +0200 Subject: [PATCH 10/13] pyflakes bug causes error without comment --- python/damask/util.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/python/damask/util.py b/python/damask/util.py index 468ac49ec..5e003bb7e 100644 --- a/python/damask/util.py +++ b/python/damask/util.py @@ -190,7 +190,7 @@ def run(cmd: str, def open_text(fname: _FileHandle, - mode: _Literal['r','w'] = 'r') -> _TextIO: + mode: _Literal['r','w'] = 'r') -> _TextIO: # noqa """ Open a text file. @@ -307,7 +307,7 @@ def scale_to_coprime(v: _FloatSequence) -> _np.ndarray: def project_equal_angle(vector: _np.ndarray, - direction: _Literal['x', 'y', 'z'] = 'z', + direction: _Literal['x', 'y', 'z'] = 'z', # noqa normalize: bool = True, keepdims: bool = False) -> _np.ndarray: """ @@ -355,7 +355,7 @@ def project_equal_angle(vector: _np.ndarray, -shift if keepdims else 0,axis=-1)[...,:3 if keepdims else 2] def project_equal_area(vector: _np.ndarray, - direction: _Literal['x', 'y', 'z'] = 'z', + direction: _Literal['x', 'y', 'z'] = 'z', # noqa normalize: bool = True, keepdims: bool = False) -> _np.ndarray: """ @@ -443,7 +443,7 @@ def hybrid_IA(dist: _np.ndarray, def shapeshifter(fro: _Tuple[int, ...], to: _Tuple[int, ...], - mode: _Literal['left','right'] = 'left', + mode: _Literal['left','right'] = 'left', # noqa keep_ones: bool = False) -> _Tuple[int, ...]: """ Return dimensions that reshape 'fro' to become broadcastable to 'to'. From 1a44b6e692b363ce4ae479ef6a68b849ec308525 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Fri, 10 Jun 2022 14:03:43 +0200 Subject: [PATCH 11/13] white space adjustments --- python/damask/util.py | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/python/damask/util.py b/python/damask/util.py index 5e003bb7e..f6d67fb37 100644 --- a/python/damask/util.py +++ b/python/damask/util.py @@ -167,11 +167,11 @@ def run(cmd: str, print(f"running '{cmd}' in '{wd}'") process = _subprocess.Popen(_shlex.split(cmd), - stdout = _subprocess.PIPE, - stderr = _subprocess.PIPE, - env = _os.environ if env is None else env, - cwd = wd, - encoding = 'utf-8') + stdout = _subprocess.PIPE, + stderr = _subprocess.PIPE, + env = _os.environ if env is None else env, + cwd = wd, + encoding = 'utf-8') # ensure that process is terminated (https://stackoverflow.com/questions/22916783) sig_states = [_signal.signal(sig,_partial(pass_signal,proc=process,default=_signal.getsignal(sig))) for sig in signals] @@ -350,9 +350,9 @@ def project_equal_angle(vector: _np.ndarray, """ shift = 'zyx'.index(direction) v = _np.roll(vector/_np.linalg.norm(vector,axis=-1,keepdims=True) if normalize else vector, - shift,axis=-1) + shift,axis=-1) return _np.roll(_np.block([v[...,:2]/(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 project_equal_area(vector: _np.ndarray, direction: _Literal['x', 'y', 'z'] = 'z', # noqa @@ -399,9 +399,9 @@ def project_equal_area(vector: _np.ndarray, """ shift = 'zyx'.index(direction) v = _np.roll(vector/_np.linalg.norm(vector,axis=-1,keepdims=True) if normalize else vector, - shift,axis=-1) + shift,axis=-1) 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: @@ -648,12 +648,12 @@ def Bravais_to_Miller(*, if (uvtw is not None) ^ (hkil is None): raise KeyError('specify either "uvtw" or "hkil"') axis,basis = (_np.array(uvtw),_np.array([[1,0,-1,0], - [0,1,-1,0], - [0,0, 0,1]])) \ + [0,1,-1,0], + [0,0, 0,1]])) \ if hkil is None else \ (_np.array(hkil),_np.array([[1,0,0,0], - [0,1,0,0], - [0,0,0,1]])) + [0,1,0,0], + [0,0,0,1]])) return _np.einsum('il,...l',basis,axis) @@ -677,14 +677,14 @@ def Miller_to_Bravais(*, if (uvw is not None) ^ (hkl is None): raise KeyError('specify either "uvw" or "hkl"') axis,basis = (_np.array(uvw),_np.array([[ 2,-1, 0], - [-1, 2, 0], - [-1,-1, 0], - [ 0, 0, 3]])/3) \ + [-1, 2, 0], + [-1,-1, 0], + [ 0, 0, 3]])/3) \ if hkl is None else \ (_np.array(hkl),_np.array([[ 1, 0, 0], - [ 0, 1, 0], - [-1,-1, 0], - [ 0, 0, 1]])) + [ 0, 1, 0], + [-1,-1, 0], + [ 0, 0, 1]])) return _np.einsum('il,...l',basis,axis) From bbd4f01fb782d55cd8914dd2da89a66a0a4c5aaa Mon Sep 17 00:00:00 2001 From: Test User Date: Sat, 11 Jun 2022 03:24:31 +0200 Subject: [PATCH 12/13] [skip ci] updated version information after successful test of v3.0.0-alpha6-453-g98b307f0c --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 896507f8b..104caef74 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.0.0-alpha6-447-g42ee6310b +3.0.0-alpha6-453-g98b307f0c From 655103d39edc5c0213d15d1e6a70e8d72ee9b226 Mon Sep 17 00:00:00 2001 From: Test User Date: Mon, 13 Jun 2022 19:35:37 +0200 Subject: [PATCH 13/13] [skip ci] updated version information after successful test of v3.0.0-alpha6-458-g132823519 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 104caef74..09973b4ed 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.0.0-alpha6-453-g98b307f0c +3.0.0-alpha6-458-g132823519