Source code for plaid.utils.interpolation

"""Interpolation utilities for working with ordered lists and vectors."""

# -*- coding: utf-8 -*-
#
# This file is subject to the terms and conditions defined in
# file 'LICENSE.txt', which is part of this source code package.
#
#

# %% Imports

import bisect
from typing import Union

import numpy as np

# %% Functions






[docs] def binary_search_vectorized( ordered_list: Union[list, np.ndarray], items: Union[list, np.ndarray] ) -> np.ndarray: """Vectorized binary search for multiple items in a sorted list (items is now a list or one-dimensional np.ndarray). Args: ordered_list (Union[list, np.ndarray]): The data sorted in increasing order. items (Union[list, np.ndarray]): The items for which ranks are searched. Returns: np.ndarray: An array containing the ranks of the largest elements smaller or equal to each item. """ return np.fromiter( map(lambda item: binary_search(ordered_list, item), items), dtype=int )
[docs] def piece_wise_linear_interpolation( item: float, item_indices: np.ndarray, vectors: Union[np.ndarray, dict], tolerance: float = 1e-4, ) -> np.ndarray: """Computes a item interpolation for temporal vectors defined either by item_indices and vectors at these indices. Args: item (float): The input item at which the interpolation is required. item_indices (np.ndarray): The items where the available data is defined, of size (numberOfTimeIndices). vectors (Union[np.ndarray, dict]): The available data, of size (numberOfVectors, numberOfDofs). tolerance (float): Tolerance for deciding when using the closest timestep value instead of carrying out the linear interpolation, default to 1e-4. Returns: np.ndarray: Interpolated vector, of size (numberOfDofs). """ if item <= item_indices[0]: return vectors[0] if item >= item_indices[-1]: return vectors[-1] prev = binary_search(item_indices, item) coef = (item - item_indices[prev]) / (item_indices[prev + 1] - item_indices[prev]) if 0.5 - abs(coef - 0.5) < tolerance: coef = round(coef) return coef * vectors[prev + 1] + (1 - coef) * vectors[prev]
[docs] def piece_wise_linear_interpolation_with_map( item: float, item_indices: np.ndarray, vectors: Union[np.ndarray, dict], vectors_map: list = None, tolerance: float = 1e-4, ) -> np.ndarray: """Computes a item interpolation for temporal vectors defined either by item_indices, some tags at these item indices (vectors_map), and vectors at those tags. Args: item (float): The input item at which the interpolation is required. item_indices (np.ndarray): The items where the available data is defined, of size (numberOfTimeIndices). vectors (Union[np.ndarray, dict]): The available data, of size (numberOfVectors, numberOfDofs). vectors_map (list, optional): List containing the mapping from the numberOfTimeIndices items indices to the numberOfVectors vectors, of size (numberOfTimeIndices,). Defaults to None. tolerance (float, optional): Tolerance for deciding when using the closest timestep value instead of carrying out the linear interpolation, default to 1e-4. Returns: np.ndarray: Interpolated vector, of size (numberOfDofs). """ # TODO What if vectorsMap = None ??? it will crash if item <= item_indices[0]: return vectors[vectors_map[0]] if item >= item_indices[-1]: return vectors[vectors_map[-1]] prev = binary_search(item_indices, item) coef = (item - item_indices[prev]) / (item_indices[prev + 1] - item_indices[prev]) if 0.5 - abs(coef - 0.5) < tolerance: coef = round(coef) return ( coef * vectors[vectors_map[prev + 1]] + (1 - coef) * vectors[vectors_map[prev]] )
[docs] def piece_wise_linear_interpolation_vectorized( items: list[float], item_indices: np.ndarray, vectors: Union[np.ndarray, str] ) -> list[np.ndarray]: """piece_wise_linear_interpolation for more than one call (items is now a list or one-dimensional np.ndarray). Args: items (list[float]): The input items at which interpolations are required. item_indices (np.ndarray): The items where the available data is defined, of size (numberOfTimeIndices). vectors (np.ndarray or dict): The available data, of size (numberOfVectors, numberOfDofs). Returns: list[np.ndarray]: List of interpolated vectors, each of size (numberOfDofs). """ return [ piece_wise_linear_interpolation(item, item_indices, vectors) for item in items ]
# return np.fromiter(map(lambda item: piece_wise_linear_interpolation(item, # item_indices, vectors), items), dtype = type(vectors[0]))
[docs] def piece_wise_linear_interpolation_vectorized_with_map( items: list[float], item_indices: np.ndarray, vectors: Union[np.ndarray, dict], vectors_map: list = None, ) -> list[np.ndarray]: """piece_wise_linear_interpolation_with_map for more than one call (items is now a list or one-dimensional np.ndarray). Args: items (list[float]): The input items at which interpolations are required. item_indices (np.ndarray): The items where the available data is defined, of size (numberOfTimeIndices). vectors (np.ndarray or dict): The available data, of size (numberOfVectors, numberOfDofs). vectors_map (list): List containing the mapping from the numberOfTimeIndices items indices to the numberOfVectors vectors, of size (numberOfTimeIndices,). Default is None, in which case numberOfVectors = numberOfTimeIndices. Returns: list[np.ndarray]: List of interpolated vectors, each of size (numberOfDofs). """ return [ piece_wise_linear_interpolation_with_map( item, item_indices, vectors, vectors_map ) for item in items ]
# return np.fromiter(map(lambda item: # piece_wise_linear_interpolation_with_map(item, item_indices, vectors, # vectors_map), items), dtype = np.float)