madman.utilities
Utilities.
1r"""Utilities.""" 2 3import os 4import sys 5from collections.abc import Sequence 6from contextlib import contextmanager 7from math import ceil 8from numbers import Real 9from typing import Optional 10 11import numpy as np 12from ase.parallel import paropen 13 14 15def process_path(path: Optional[str]) -> Optional[str]: 16 r"""Process path, creating tree if needed. 17 18 Args: 19 path: Path to process. 20 21 Returns: 22 Processed path. 23 """ 24 if path is None: 25 return None 26 path = str(path) 27 pathd = os.path.dirname(path) 28 if pathd != "": 29 os.makedirs(pathd, exist_ok=True) 30 return path 31 32 33@contextmanager 34def redirect_to(prefix: Optional[str], *, mode: str = "w") -> None: 35 r"""Redirect standard output/error to file. 36 37 Args: 38 prefix: Prefix for output and error files. 39 mode: Writing mode. 40 """ 41 stdout_old = sys.stdout 42 stderr_old = sys.stderr 43 44 prefix = process_path(prefix) 45 if prefix is not None: 46 sys.stdout = paropen(f"{prefix}.out", mode) 47 sys.stderr = paropen(f"{prefix}.err", mode) 48 49 try: 50 yield 51 52 finally: 53 sys.stdout = stdout_old 54 sys.stderr = stderr_old 55 56 57def gen_regular_grid(xa: Real, xb: Real, dx: Real) -> np.ndarray[float]: 58 """Generate regular grid. 59 60 Args: 61 xa: Minimum value. 62 xb: Maximum value. 63 dx: Target increment. 64 65 Returns: 66 Regular grid. 67 """ 68 ndx = (xb - xa) / dx 69 nx = ceil(ndx) + (1 if ndx % 1 == 0.0 else 0) 70 return np.linspace(xa, xb, nx) 71 72 73def correlate1d( 74 x: Sequence[Real, ...], 75 y1: Sequence[Real, ...], 76 y2: Sequence[Real, ...], 77) -> np.ndarray[float]: 78 r"""Correlate two 1d signals. 79 80 Args: 81 x: Independent variable values. 82 y1: First signal dependent variable values. 83 y2: Second signal dependent variable values. 84 85 Returns: 86 Correlation independent and dependent variable values. 87 88 Raises: 89 ValueError: If independent variable is not equally spaced. 90 ValueError: If independent variable has duplicate values. 91 """ 92 x = np.asarray(x, dtype=float).flatten() 93 y1 = np.asarray(y1, dtype=float).flatten() 94 y2 = np.asarray(y2, dtype=float).flatten() 95 96 i = np.argsort(x) 97 x = x[i] 98 y1 = y1[i] 99 y2 = y2[i] 100 101 if not np.array_equal(x, np.unique(x)): 102 raise ValueError("Duplicate independent variable values!") 103 104 dx = np.diff(x) 105 xn = len(dx) 106 dxm = np.mean(dx) 107 if not np.all(np.isclose(dx, dxm)): 108 raise ValueError("Independent variable not equally spaced!") 109 110 x = dxm * np.arange(-xn, xn + 1) 111 z = dxm * np.correlate(y2, y1, mode="full") 112 return x, z
def
process_path(path: Optional[str]) -> Optional[str]:
16def process_path(path: Optional[str]) -> Optional[str]: 17 r"""Process path, creating tree if needed. 18 19 Args: 20 path: Path to process. 21 22 Returns: 23 Processed path. 24 """ 25 if path is None: 26 return None 27 path = str(path) 28 pathd = os.path.dirname(path) 29 if pathd != "": 30 os.makedirs(pathd, exist_ok=True) 31 return path
Process path, creating tree if needed.
Arguments:
- path: Path to process.
Returns:
Processed path.
@contextmanager
def
redirect_to(prefix: Optional[str], *, mode: str = 'w') -> None:
34@contextmanager 35def redirect_to(prefix: Optional[str], *, mode: str = "w") -> None: 36 r"""Redirect standard output/error to file. 37 38 Args: 39 prefix: Prefix for output and error files. 40 mode: Writing mode. 41 """ 42 stdout_old = sys.stdout 43 stderr_old = sys.stderr 44 45 prefix = process_path(prefix) 46 if prefix is not None: 47 sys.stdout = paropen(f"{prefix}.out", mode) 48 sys.stderr = paropen(f"{prefix}.err", mode) 49 50 try: 51 yield 52 53 finally: 54 sys.stdout = stdout_old 55 sys.stderr = stderr_old
Redirect standard output/error to file.
Arguments:
- prefix: Prefix for output and error files.
- mode: Writing mode.
def
gen_regular_grid( xa: numbers.Real, xb: numbers.Real, dx: numbers.Real) -> numpy.ndarray[float]:
58def gen_regular_grid(xa: Real, xb: Real, dx: Real) -> np.ndarray[float]: 59 """Generate regular grid. 60 61 Args: 62 xa: Minimum value. 63 xb: Maximum value. 64 dx: Target increment. 65 66 Returns: 67 Regular grid. 68 """ 69 ndx = (xb - xa) / dx 70 nx = ceil(ndx) + (1 if ndx % 1 == 0.0 else 0) 71 return np.linspace(xa, xb, nx)
Generate regular grid.
Arguments:
- xa: Minimum value.
- xb: Maximum value.
- dx: Target increment.
Returns:
Regular grid.
def
correlate1d( x: collections.abc.Sequence[numbers.Real, ...], y1: collections.abc.Sequence[numbers.Real, ...], y2: collections.abc.Sequence[numbers.Real, ...]) -> numpy.ndarray[float]:
74def correlate1d( 75 x: Sequence[Real, ...], 76 y1: Sequence[Real, ...], 77 y2: Sequence[Real, ...], 78) -> np.ndarray[float]: 79 r"""Correlate two 1d signals. 80 81 Args: 82 x: Independent variable values. 83 y1: First signal dependent variable values. 84 y2: Second signal dependent variable values. 85 86 Returns: 87 Correlation independent and dependent variable values. 88 89 Raises: 90 ValueError: If independent variable is not equally spaced. 91 ValueError: If independent variable has duplicate values. 92 """ 93 x = np.asarray(x, dtype=float).flatten() 94 y1 = np.asarray(y1, dtype=float).flatten() 95 y2 = np.asarray(y2, dtype=float).flatten() 96 97 i = np.argsort(x) 98 x = x[i] 99 y1 = y1[i] 100 y2 = y2[i] 101 102 if not np.array_equal(x, np.unique(x)): 103 raise ValueError("Duplicate independent variable values!") 104 105 dx = np.diff(x) 106 xn = len(dx) 107 dxm = np.mean(dx) 108 if not np.all(np.isclose(dx, dxm)): 109 raise ValueError("Independent variable not equally spaced!") 110 111 x = dxm * np.arange(-xn, xn + 1) 112 z = dxm * np.correlate(y2, y1, mode="full") 113 return x, z
Correlate two 1d signals.
Arguments:
- x: Independent variable values.
- y1: First signal dependent variable values.
- y2: Second signal dependent variable values.
Returns:
Correlation independent and dependent variable values.
Raises:
- ValueError: If independent variable is not equally spaced.
- ValueError: If independent variable has duplicate values.