Source code for objscale._utils

from __future__ import annotations

import numpy as np
from numpy.typing import NDArray
from warnings import warn
import numba

__all__ = ['linear_regression', 'encase_in_value', 'set_num_threads']


[docs] def set_num_threads(n: int) -> None: """ Set the number of threads used for parallel computations. Controls the number of threads Numba uses for parallel operations such as correlation integral calculation and structure property analysis. Parameters ---------- n : int Number of threads to use. Must be between 1 and the number of logical CPU cores available. Raises ------ ValueError If n is less than 1 or greater than the available CPU count. """ numba.set_num_threads(n)
[docs] def linear_regression( x: NDArray[np.floating], y: NDArray[np.floating] ) -> tuple[tuple[float, float], tuple[float, float]]: """ Perform linear regression and return coefficients with 95% confidence errors. Parameters ---------- x : np.ndarray Independent variable values. y : np.ndarray Dependent variable values. Returns ------- coefficients : tuple of float (slope, y-intercept) from linear regression. errors : tuple of float (error_slope, error_y_intercept) for 95% confidence. Raises ------ TypeError If x or y are not numpy arrays. """ if not isinstance(x, np.ndarray) or not isinstance(y, np.ndarray): raise TypeError('x, y, must be of type np.ndarray') index = np.isfinite(x) & np.isfinite(y) if len(x[index]) < 3: # "the number of data points must exceed order to scale the covariance matrix" warn('Less than 3 points (x,y) are good (not nan), returning nans') return (np.nan, np.nan), (np.nan, np.nan) try: coefficients, cov = np.polyfit(x[index], y[index], 1, cov=True) error = np.sqrt(np.diag(cov)) except (np.linalg.LinAlgError, ValueError, FloatingPointError) as e: warn(f'Linear regression failed: {e!s}') return (np.nan, np.nan), (np.nan, np.nan) return tuple(coefficients), tuple(2 * error) # 95% conf interval is 2 times standard error
[docs] def encase_in_value( array: NDArray, value: float = np.nan, dtype: np.dtype = np.float32, n_deep: int = 1 ) -> NDArray: """ Add a border of specified value around a 2-D array. Parameters ---------- array : np.ndarray 2-D input array. value : scalar, default=np.nan Value to append on the edge. dtype : np.dtype, default=np.float32 Data type of the resulting array. n_deep : int, default=1 Number of layers deep to add around the edge. Returns ------- np.ndarray Same as input but with a layer 'n_deep' of 'value' all around the edge. """ out_dtype = np.result_type(dtype, array.dtype) h, w = array.shape result = np.full((h + 2 * n_deep, w + 2 * n_deep), value, dtype=out_dtype) result[n_deep:n_deep + h, n_deep:n_deep + w] = array return result