Source code for TidalPy.utilities.numpy_helper.array_other

from typing import Dict, TYPE_CHECKING

import numpy as np

from TidalPy.utilities.types import float_eps
from TidalPy.utilities.performance.numba import njit

if TYPE_CHECKING:
    from TidalPy.utilities.types import FloatArray, NumericalType


[docs] def normalize_dict( dict_of_values: Dict[str, 'FloatArray'], pass_negatives: bool = False, new_max: float = 1.0, new_min: float = 0.0 ): """ Normalizes values provided in a name separated dictionary to the specified range. Parameters ---------- dict_of_values : Dict[str, FloatArray] Dictionary of reference keys pointing to the to-be-normalized values. pass_negatives : bool = False If true then any values that are negative will be excluded from the normalization. new_max : float = 1.0 The upper-most of the post-normalized values new_min : float = 0.0 The lower-most of the post-normalized values Returns ------- dict_of_normalized_values : Dict[str, FloatArray] Dictionary of reference keys pointing to the post-normalized values. """ if pass_negatives: max_ = 1.0e-10 else: max_ = -1.0e100 min_ = 1.0e100 for ref_name, value in dict_of_values.items(): if np.max(value) > max_: max_ = np.max(value) if min_ > np.min(value): if pass_negatives and np.min(value) < -float_eps: # Negative values may indicate an integration problem and the user may want to exclude them from the # normalization. if min_ > np.min(value[value >= float_eps]): min_ = np.min(value[value >= float_eps]) else: min_ = np.min(value) if min_ == max_: min_ = 0.9 * max_ new_dict = {ref: np.zeros_like(value) for ref, value in dict_of_values.items()} slope = (new_max - new_min) / (max_ - min_) intercept = new_max - slope * max_ for ref_name, value in dict_of_values.items(): if pass_negatives: new_dict[ref_name][value >= float_eps] = slope * value[value >= float_eps] + intercept new_dict[ref_name][value < -float_eps] = value[value < -float_eps] else: new_dict[ref_name] = slope * value + intercept return new_dict
[docs] @njit(cacheable=True) def find_nearest(array: np.ndarray, value: 'NumericalType'): """ Returns the index of the value closest to a provided value in a numpy array. Parameters ---------- array : np.ndarray Numpy array to search in value : NumericalType Value to search for within array Returns ------- index: int Index of nearest value """ array = np.asarray(array) index = (np.abs(array - value)).argmin() return index
[docs] def value_np_cleanup(value): if type(value) in [float, int]: value = np.asarray(value) return value
[docs] @njit(cacheable=True) def neg_array_for_log_plot(array_with_negatives: np.ndarray): """ Converts one numpy array into two where both new arrays only have positive values. Useful for log-plotting. Parameters ---------- array_with_negatives : np.ndarray Numpy array that may have negatives or zeros Returns ------- array_positive : np.ndarray Numpy array with original array's positives array_negative : np.ndarray Numpy array with original array's negatives set to positive """ # TODO: Numba currently does not support fancy indexing with 2+D arrays. # for now we will flatten and reshape the array. org_shape = array_with_negatives.shape array_positive = array_with_negatives.copy().flatten() array_negative = array_with_negatives.copy().flatten() array_positive[array_positive <= 0.] = np.nan array_negative[array_negative >= 0.] = np.nan array_negative = np.abs(array_negative) # Reshape array_positive = array_positive.reshape(org_shape) array_negative = array_negative.reshape(org_shape) return array_positive, array_negative