def _distance_factory( self, x: np.ndarray, y: np.ndarray, window: float = None, itakura_max_slope: float = None, bounding_matrix: np.ndarray = None, **kwargs: Any ) -> DistanceCallable: """Create a no_python compiled dtw distance callable. Series should be shape (d, m), where d is the number of dimensions, m the series length. Series can be different lengths. Parameters ---------- x: np.ndarray (2d array of shape (d,m1)). First time series. y: np.ndarray (2d array of shape (d,m2)). Second time series. window: Float, defaults = None Float that is the radius of the sakoe chiba window (if using Sakoe-Chiba lower bounding). Must be between 0 and 1. itakura_max_slope: float, defaults = None Gradient of the slope for itakura parallelogram (if using Itakura Parallelogram lower bounding). Must be between 0 and 1. bounding_matrix: np.ndarray (2d array of shape (m1,m2)), defaults = None Custom bounding matrix to use. If defined then other lower_bounding params are ignored. The matrix should be structure so that indexes considered in bound should be the value 0. and indexes outside the bounding matrix should be infinity. kwargs: any extra kwargs. Returns ------- Callable[[np.ndarray, np.ndarray], float] No_python compiled Dtw distance callable. Raises ------ ValueError If the input time series are not numpy array. If the input time series do not have exactly 2 dimensions. If the sakoe_chiba_window_radius is not an integer. If the itakura_max_slope is not a float or int. """ _bounding_matrix = resolve_bounding_matrix( x, y, window, itakura_max_slope, bounding_matrix ) @njit(cache=True) def numba_dtw_distance( _x: np.ndarray, _y: np.ndarray, ) -> float: cost_matrix = _cost_matrix(_x, _y, _bounding_matrix) return cost_matrix[-1, -1] return numba_dtw_distance
def _distance_factory( self, x: np.ndarray, y: np.ndarray, c: float = 0.0, window: float = None, itakura_max_slope: float = None, bounding_matrix: np.ndarray = None, **kwargs: dict, ) -> DistanceCallable: """Create a no_python compiled MSM distance callable. Series should be shape (1, m), where m is the series length. Series can be different lengths. Parameters ---------- x: np.ndarray (2d array of shape (1,m1)). First time series. y: np.ndarray (2d array of shape (1,m2)). Second time series. c: float parameter used in MSM (update later!) Returns ------- Callable[[np.ndarray, np.ndarray], float] No_python compiled MSM distance callable. Raises ------ ValueError If the input time series have more than one dimension (shape[0] > 1) If the input time series is not a numpy array. If the input time series doesn't have exactly 2 dimensions. If the sakoe_chiba_window_radius is not an integer. If the itakura_max_slope is not a float or int. If epsilon is not a float. """ if x.shape[0] > 1 or y.shape[0] > 1: raise ValueError( f"ERROR, MSM distance currently only works with " f"univariate series, passed seris shape {x.shape[0]} and" f"shape {y.shape[0]}") _bounding_matrix = resolve_bounding_matrix(x, y, window, itakura_max_slope, bounding_matrix) @njit(cache=True) def numba_msm_distance( _x: np.ndarray, _y: np.ndarray, ) -> float: cost_matrix = _cost_matrix(_x, _y, c, _bounding_matrix) return cost_matrix[-1, -1] return numba_msm_distance
def _distance_alignment_path_factory( self, x: np.ndarray, y: np.ndarray, return_cost_matrix: bool = False, window: int = None, itakura_max_slope: float = None, bounding_matrix: np.ndarray = None, g: float = 0.05, **kwargs: Any, ) -> DistanceAlignmentPathCallable: """Create a no_python compiled wdtw distance alignment path callable. Series should be shape (d, m), where d is the number of dimensions, m the series length. Series can be different lengths. Parameters ---------- x: np.ndarray (2d array of shape (d,m1)). First time series. y: np.ndarray (2d array of shape (d,m2)). Second time series. return_cost_matrix: bool, defaults = False Boolean that when true will also return the cost matrix. window: Float, defaults = None Float that is the radius of the sakoe chiba window (if using Sakoe-Chiba lower bounding). Must be between 0 and 1. itakura_max_slope: float, defaults = None Gradient of the slope for itakura parallelogram (if using Itakura Parallelogram lower bounding). Must be between 0 and 1. bounding_matrix: np.ndarray (2d array of shape (m1,m2)), defaults = None Custom bounding matrix to use. If defined then other lower_bounding params are ignored. The matrix should be structure so that indexes considered in bound should be the value 0. and indexes outside the bounding matrix should be infinity. g: float, defaults = 0. Constant that controls the curvature (slope) of the function; that is, g controls the level of penalisation for the points with larger phase difference. kwargs: any extra kwargs. Returns ------- Callable[[np.ndarray, np.ndarray], tuple[np.ndarray, float]] No_python compiled wdtw distance path callable. Raises ------ ValueError If the input time series are not numpy array. If the input time series do not have exactly 2 dimensions. If the sakoe_chiba_window_radius is not an integer. If the itakura_max_slope is not a float or int. If the value of g is not a float """ _bounding_matrix = resolve_bounding_matrix( x, y, window, itakura_max_slope, bounding_matrix ) if not isinstance(g, float): raise ValueError( f"The value of g must be a float. The current value is {g}" ) _bounding_matrix = resolve_bounding_matrix( x, y, window, itakura_max_slope, bounding_matrix ) if return_cost_matrix is True: @njit(cache=True) def numba_wdtw_distance_alignment_path( _x: np.ndarray, _y: np.ndarray, ) -> Tuple[List, float, np.ndarray]: cost_matrix = _weighted_cost_matrix(_x, _y, _bounding_matrix, g) path = compute_min_return_path(cost_matrix, _bounding_matrix) return path, cost_matrix[-1, -1], cost_matrix else: @njit(cache=True) def numba_wdtw_distance_alignment_path( _x: np.ndarray, _y: np.ndarray, ) -> Tuple[List, float]: cost_matrix = _weighted_cost_matrix(_x, _y, _bounding_matrix, g) path = compute_min_return_path(cost_matrix, _bounding_matrix) return path, cost_matrix[-1, -1] return numba_wdtw_distance_alignment_path
def _distance_factory( self, x: np.ndarray, y: np.ndarray, window: int = None, itakura_max_slope: float = None, bounding_matrix: np.ndarray = None, g: float = 0.05, **kwargs: Any, ) -> DistanceCallable: """Create a no_python compiled wdtw distance callable. Parameters ---------- x: np.ndarray (2d array of shape (d,m1)). First time series. y: np.ndarray (2d array of shape (d,m2)). Second time series. window: float, defaults = None Integer that is the radius of the sakoe chiba window (if using Sakoe-Chiba lower bounding). Must be between 0 and 1. itakura_max_slope: float, defaults = None Gradient of the slope for itakura parallelogram (if using Itakura Parallelogram lower bounding). Must be between 0 and 1. bounding_matrix: np.ndarray (2d array of shape (m1,m2)), defaults = None Custom bounding matrix to use. If defined then other lower_bounding params are ignored. The matrix should be structure so that indexes considered in bound should be the value 0. and indexes outside the bounding matrix should be infinity. g: float, defaults = 0. Constant that controls the curvature (slope) of the function; that is, g controls the level of penalisation for the points with larger phase difference. kwargs: Any Extra kwargs. Returns ------- Callable[[np.ndarray, np.ndarray], float] No_python compiled wdtw distance callable. Raises ------ ValueError If the input time series are not numpy array. If the input time series do not have exactly 2 dimensions. If the sakoe_chiba_window_radius is not an integer. If the itakura_max_slope is not a float or int. If the value of g is not a float """ _bounding_matrix = resolve_bounding_matrix( x, y, window, itakura_max_slope, bounding_matrix ) if not isinstance(g, float): raise ValueError( f"The value of g must be a float. The current value is {g}" ) @njit(cache=True) def numba_wdtw_distance( _x: np.ndarray, _y: np.ndarray, ) -> float: cost_matrix = _weighted_cost_matrix(_x, _y, _bounding_matrix, g) return cost_matrix[-1, -1] return numba_wdtw_distance
def _distance_factory(self, x: np.ndarray, y: np.ndarray, window: float = None, itakura_max_slope: float = None, bounding_matrix: np.ndarray = None, epsilon: float = None, **kwargs: Any) -> DistanceCallable: """Create a no_python compiled edr distance callable. Parameters ---------- x: np.ndarray (2d array) First timeseries. y: np.ndarray (2d array) Second timeseries. window: float, defaults = None Float that is the radius of the sakoe chiba window (if using Sakoe-Chiba lower bounding). Must be between 0 and 1. itakura_max_slope: float, defaults = None Gradient of the slope for itakura parallelogram (if using Itakura Parallelogram lower bounding). Must be between 0 and 1. bounding_matrix: np.ndarray (2d of size mxn where m is len(x) and n is len(y)), defaults = None Custom bounding matrix to use. If defined then other lower_bounding params are ignored. The matrix should be structure so that indexes considered in bound should be the value 0. and indexes outside the bounding matrix should be infinity. epsilon : float, defaults = None Matching threshold to determine if two subsequences are considered close enough to be considered 'common'. If not specified as per the original paper epsilon is set to a quarter of the maximum standard deviation. kwargs: Any Extra kwargs. Returns ------- Callable[[np.ndarray, np.ndarray], float] No_python compiled edr distance callable. Raises ------ ValueError If the input timeseries is not a numpy array. If the input timeseries doesn't have exactly 2 dimensions. If the sakoe_chiba_window_radius is not an integer. If the itakura_max_slope is not a float or int. If epsilon is not a float. """ _bounding_matrix = resolve_bounding_matrix(x, y, window, itakura_max_slope, bounding_matrix) if epsilon is not None and not isinstance(epsilon, float): raise ValueError("The value of epsilon must be a float.") @njit(cache=True) def numba_edr_distance(_x: np.ndarray, _y: np.ndarray) -> float: if np.array_equal(_x, _y): return 0.0 if epsilon is None: _epsilon = max(np.std(x), np.std(y)) / 4 else: _epsilon = epsilon cost_matrix = _edr_cost_matrix(x, y, _bounding_matrix, _epsilon) return float(cost_matrix[-1, -1] / max(x.shape[0], y.shape[0])) return numba_edr_distance
def _distance_alignment_path_factory( self, x: np.ndarray, y: np.ndarray, return_cost_matrix: bool = False, window: float = None, itakura_max_slope: float = None, bounding_matrix: np.ndarray = None, compute_derivative: DerivativeCallable = average_of_slope, **kwargs: Any, ) -> DistanceAlignmentPathCallable: """Create a no_python compiled ddtw distance alignment path callable. Series should be shape (d, m), where d is the number of dimensions, m the series length. Series can be different lengths. Parameters ---------- x: np.ndarray (2d array of shape (d,m1)). First time series. y: np.ndarray (2d array of shape (d,m2)). Second time series. return_cost_matrix: bool, defaults = False Boolean that when true will also return the cost matrix. window: float, defaults = None Float that is the radius of the Sakoe-Chiba window (if using Sakoe-Chiba lower bounding). Must be between 0 and 1. itakura_max_slope: float, defaults = None Gradient of the slope for Itakura parallelogram (if using Itakura Parallelogram lower bounding). Must be between 0 and 1. bounding_matrix: np.ndarray (2d array of shape (m1,m2)), defaults = None Custom bounding matrix to use. If defined then other lower_bounding params are ignored. The matrix should be structure so that indexes considered in bound should be the value 0. and indexes outside the bounding matrix should be infinity. compute_derivative: Callable[[np.ndarray], np.ndarray], defaults = average slope difference Callable that computes the derivative. If none is provided the average of the slope between two points used. kwargs: any extra kwargs. Returns ------- Callable[[np.ndarray, np.ndarray], tuple[np.ndarray, float]] No_python compiled wdtw distance path callable. Raises ------ ValueError If the input time series is not a numpy array. If the input time series doesn't have exactly 2 dimensions. If the sakoe_chiba_window_radius is not an integer. If the itakura_max_slope is not a float or int. If the compute derivative callable is not no_python compiled. """ _bounding_matrix = resolve_bounding_matrix(x, y, window, itakura_max_slope, bounding_matrix) if not is_no_python_compiled_callable(compute_derivative): raise ( f"The derivative callable must be no_python compiled. The name" f"of the callable that must be compiled is " f"{compute_derivative.__name__}") if return_cost_matrix is True: @njit(cache=True) def numba_ddtw_distance_alignment_path( _x: np.ndarray, _y: np.ndarray, ) -> Tuple[List, float, np.ndarray]: _x = compute_derivative(_x) _y = compute_derivative(_y) cost_matrix = _cost_matrix(_x, _y, _bounding_matrix) path = compute_min_return_path(cost_matrix, _bounding_matrix) return path, cost_matrix[-1, -1], cost_matrix else: @njit(cache=True) def numba_ddtw_distance_alignment_path( _x: np.ndarray, _y: np.ndarray, ) -> Tuple[List, float]: _x = compute_derivative(_x) _y = compute_derivative(_y) cost_matrix = _cost_matrix(_x, _y, _bounding_matrix) path = compute_min_return_path(cost_matrix, _bounding_matrix) return path, cost_matrix[-1, -1] return numba_ddtw_distance_alignment_path
def _distance_factory( self, x: np.ndarray, y: np.ndarray, epsilon: float = 1.0, window: float = None, itakura_max_slope: float = None, bounding_matrix: np.ndarray = None, **kwargs: Any, ) -> DistanceCallable: """Create a no_python compiled lcss distance callable. Parameters ---------- x: np.ndarray (2d array), First time series. y: np.ndarray (2d array), Second time series. epsilon : float, default = 1. Matching threshold to determine if two subsequences are considered close enough to be considered 'common'. window: float, default = None, radius of the bounding window (if using Sakoe-Chiba lower bounding). Must be between 0 and 1. itakura_max_slope: float, defaults = None, gradient of the slope for bounding parallelogram (if using Itakura parallelogram lower bounding). Must be between 0 and 1. bounding_matrix: np.ndarray (2d of size mxn where m is len(x) and n is len( y)), defaults = None, Custom bounding matrix to use. If defined then other lower_bounding params are ignored. The matrix should be structure so that indexes considered in bound should be the value 0. and indexes outside the bounding matrix should be infinity. kwargs: Any Extra kwargs. Returns ------- Callable[[np.ndarray, np.ndarray], float] No_python compiled lcss distance callable. Raises ------ ValueError If the input time series is not a numpy array. If the input time series doesn't have exactly 2 dimensions. If the sakoe_chiba_window_radius is not an integer. If the itakura_max_slope is not a float or int. If epsilon is not a float. """ _bounding_matrix = resolve_bounding_matrix( x, y, window, itakura_max_slope, bounding_matrix ) if not isinstance(epsilon, float): raise ValueError("The value of epsilon must be a float.") @njit(cache=True) def numba_lcss_distance( _x: np.ndarray, _y: np.ndarray, ) -> float: x_size = _x.shape[0] y_size = _y.shape[0] cost_matrix = _sequence_cost_matrix(_x, _y, _bounding_matrix, epsilon) return 1 - float(cost_matrix[x_size, y_size] / min(x_size, y_size)) return numba_lcss_distance
def _distance_factory( self, x: np.ndarray, y: np.ndarray, window: float = None, itakura_max_slope: float = None, bounding_matrix: np.ndarray = None, compute_derivative: DerivativeCallable = _average_of_slope, **kwargs: Any, ) -> DistanceCallable: """Create a no_python compiled ddtw distance callable. Parameters ---------- x: np.ndarray (2d array) First timeseries. y: np.ndarray (2d array) Second timeseries. window: float, defaults = None Float that is the radius of the sakoe chiba window (if using Sakoe-Chiba lower bounding). Must be between 0 and 1. itakura_max_slope: float, defaults = None Gradient of the slope for itakura parallelogram (if using Itakura Parallelogram lower bounding). Must be between 0 and 1. bounding_matrix: np.ndarray (2d of size mxn where m is len(x) and n is len(y)), defaults = None Custom bounding matrix to use. If defined then other lower_bounding params are ignored. The matrix should be structure so that indexes considered in bound should be the value 0. and indexes outside the bounding matrix should be infinity. compute_derivative: Callable[[np.ndarray], np.ndarray], defaults = average slope difference Callable that computes the derivative. If none is provided the average of the slope between two points used. kwargs: any extra kwargs. Returns ------- Callable[[np.ndarray, np.ndarray], float] No_python compiled ddtw distance callable. Raises ------ ValueError If the input timeseries is not a numpy array. If the input timeseries doesn't have exactly 2 dimensions. If the sakoe_chiba_window_radius is not an integer. If the itakura_max_slope is not a float or int. If the compute derivative callable is not no_python compiled. """ _bounding_matrix = resolve_bounding_matrix( x, y, window, itakura_max_slope, bounding_matrix ) if not is_no_python_compiled_callable(compute_derivative): raise ( f"The derivative callable must be no_python compiled. The name" f"of the callable that must be compiled is " f"{compute_derivative.__name__}" ) @njit(cache=True) def numba_ddtw_distance( _x: np.ndarray, _y: np.ndarray, ) -> float: _x = compute_derivative(_x) _y = compute_derivative(_y) cost_matrix = _cost_matrix(_x, _y, _bounding_matrix) return cost_matrix[-1, -1] return numba_ddtw_distance
def _distance_alignment_path_factory( self, x: np.ndarray, y: np.ndarray, return_cost_matrix: bool = False, window: float = None, itakura_max_slope: float = None, bounding_matrix: np.ndarray = None, epsilon: float = None, **kwargs: Any) -> DistanceAlignmentPathCallable: """Create a no_python compiled edr alignment path distance callable. Series should be shape (d, m), where d is the number of dimensions, m the series length. Series can be different lengths. Parameters ---------- x: np.ndarray (2d array of shape (d,m1)). First time series. y: np.ndarray (2d array of shape (d,m2)). Second time series. return_cost_matrix: bool, defaults = False Boolean that when true will also return the cost matrix. window: float, defaults = None Float that is the radius of the sakoe chiba window (if using Sakoe-Chiba lower bounding). Must be between 0 and 1. itakura_max_slope: float, defaults = None Gradient of the slope for itakura parallelogram (if using Itakura Parallelogram lower bounding). Must be between 0 and 1. bounding_matrix: np.ndarray (2d array of shape (m1,m2)), defaults = None Custom bounding matrix to use. If defined then other lower_bounding params are ignored. The matrix should be structure so that indexes considered in bound should be the value 0. and indexes outside the bounding matrix should be infinity. epsilon : float, defaults = None Matching threshold to determine if two subsequences are considered close enough to be considered 'common'. If not specified as per the original paper epsilon is set to a quarter of the maximum standard deviation. kwargs: Any Extra kwargs. Returns ------- Callable[[np.ndarray, np.ndarray], tuple[np.ndarray, float]] No_python compiled edr distance path callable. Raises ------ ValueError If the input time series are not numpy array. If the input time series do not have exactly 2 dimensions. If the sakoe_chiba_window_radius is not an integer. If the itakura_max_slope is not a float or int. If epsilon is not a float. """ _bounding_matrix = resolve_bounding_matrix(x, y, window, itakura_max_slope, bounding_matrix) if epsilon is not None and not isinstance(epsilon, float): raise ValueError("The value of epsilon must be a float.") if return_cost_matrix is True: @njit(cache=True) def numba_edr_distance_alignment_path( _x: np.ndarray, _y: np.ndarray) -> Tuple[List, float, np.ndarray]: if epsilon is None: _epsilon = max(np.std(_x), np.std(_y)) / 4 else: _epsilon = epsilon cost_matrix = _edr_cost_matrix(_x, _y, _bounding_matrix, _epsilon) path = compute_min_return_path(cost_matrix, _bounding_matrix) distance = float(cost_matrix[-1, -1] / max(_x.shape[1], _y.shape[1])) return path, distance, cost_matrix else: @njit(cache=True) def numba_edr_distance_alignment_path( _x: np.ndarray, _y: np.ndarray) -> Tuple[List, float]: if epsilon is None: _epsilon = max(np.std(_x), np.std(_y)) / 4 else: _epsilon = epsilon cost_matrix = _edr_cost_matrix(_x, _y, _bounding_matrix, _epsilon) path = compute_min_return_path(cost_matrix, _bounding_matrix) distance = float(cost_matrix[-1, -1] / max(_x.shape[1], _y.shape[1])) return path, distance return numba_edr_distance_alignment_path
def _distance_factory( self, x: np.ndarray, y: np.ndarray, window: float = None, itakura_max_slope: float = None, bounding_matrix: np.ndarray = None, g: float = 0.0, **kwargs: Any ) -> DistanceCallable: """Create a no_python compiled erp distance callable. Parameters ---------- x: np.ndarray (2d array) First timeseries. y: np.ndarray (2d array) Second timeseries. window: float, defaults = None Float that is the radius of the sakoe chiba window (if using Sakoe-Chiba lower bounding). Must be between 0 and 1. itakura_max_slope: float, defaults = None Gradient of the slope for itakura parallelogram (if using Itakura Parallelogram lower bounding). Must be between 0 and 1. bounding_matrix: np.ndarray (2d of size mxn where m is len(x) and n is len(y)), defaults = None Custom bounding matrix to use. If defined then other lower_bounding params are ignored. The matrix should be structure so that indexes considered in bound should be the value 0. and indexes outside the bounding matrix should be infinity. g: float, defaults = 0. The reference value to penalise gaps. kwargs: Any Extra kwargs. Returns ------- Callable[[np.ndarray, np.ndarray], float] No_python compiled erp distance callable. Raises ------ ValueError If the input timeseries is not a numpy array. If the input timeseries doesn't have exactly 2 dimensions. If the sakoe_chiba_window_radius is not an integer. If the itakura_max_slope is not a float or int. If g is not a float. """ _bounding_matrix = resolve_bounding_matrix( x, y, window, itakura_max_slope, bounding_matrix ) if not isinstance(g, float): raise ValueError("The value of g must be a float.") @njit(cache=True) def numba_erp_distance(_x: np.ndarray, _y: np.ndarray) -> float: cost_matrix = _erp_cost_matrix(x, y, _bounding_matrix, g) return cost_matrix[-1, -1] return numba_erp_distance
def _distance_alignment_path_factory( self, x: np.ndarray, y: np.ndarray, return_cost_matrix: bool = False, epsilon: float = 1.0, window: float = None, itakura_max_slope: float = None, bounding_matrix: np.ndarray = None, **kwargs: Any, ) -> DistanceAlignmentPathCallable: """Create a no_python compiled lcss distance alignment path callable. Series should be shape (d, m), where d is the number of dimensions, m the series length. Series can be different lengths. Parameters ---------- x: np.ndarray (2d array of shape (d,m1)). First time series. y: np.ndarray (2d array of shape (d,m2)). Second time series. return_cost_matrix: bool, defaults = False Boolean that when true will also return the cost matrix. epsilon : float, default = 1. Matching threshold to determine if two subsequences are considered close enough to be considered 'common'. window: float, default = None, radius of the bounding window (if using Sakoe-Chiba lower bounding). Must be between 0 and 1. itakura_max_slope: float, defaults = None, gradient of the slope for bounding parallelogram (if using Itakura parallelogram lower bounding). Must be between 0 and 1. bounding_matrix: np.ndarray (2d array of shape (m1,m2)), defaults = None Custom bounding matrix to use. If defined then other lower_bounding params are ignored. The matrix should be structure so that indexes considered in bound should be the value 0. and indexes outside the bounding matrix should be infinity. kwargs: Any Extra kwargs. Returns ------- Callable[[np.ndarray, np.ndarray], tuple[np.ndarray, float]] No_python compiled wdtw distance path callable. Raises ------ ValueError If the input time series is not a numpy array. If the input time series doesn't have exactly 2 dimensions. If the sakoe_chiba_window_radius is not an integer. If the itakura_max_slope is not a float or int. If epsilon is not a float. """ _bounding_matrix = resolve_bounding_matrix(x, y, window, itakura_max_slope, bounding_matrix) if not isinstance(epsilon, float): raise ValueError("The value of epsilon must be a float.") if return_cost_matrix is True: @njit(cache=True) def numba_lcss_distance_alignment_path( _x: np.ndarray, _y: np.ndarray, ) -> Tuple[List, float, np.ndarray]: x_size = _x.shape[1] y_size = _y.shape[1] cost_matrix = _sequence_cost_matrix(_x, _y, _bounding_matrix, epsilon) distance = 1 - float( cost_matrix[x_size, y_size] / min(x_size, y_size)) path = compute_lcss_return_path( _x, _y, epsilon=epsilon, bounding_matrix=_bounding_matrix, cost_matrix=cost_matrix, ) return path, distance, cost_matrix else: @njit(cache=True) def numba_lcss_distance_alignment_path( _x: np.ndarray, _y: np.ndarray, ) -> Tuple[List, float]: x_size = _x.shape[1] y_size = _y.shape[1] cost_matrix = _sequence_cost_matrix(_x, _y, _bounding_matrix, epsilon) distance = 1 - float( cost_matrix[x_size, y_size] / min(x_size, y_size)) path = compute_lcss_return_path( _x, _y, epsilon=epsilon, bounding_matrix=_bounding_matrix, cost_matrix=cost_matrix, ) return path, distance return numba_lcss_distance_alignment_path