Coverage for src / zooc / dsp / surface_nearest_interpolator.py: 0%

40 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2025-12-11 21:45 +0000

1"""2D-surface with interpolation and extrapolation using simple nearest neighbor interpolation.""" 

2import bisect 

3from collections import OrderedDict 

4from functools import cached_property 

5 

6import numpy as np 

7import numpy.typing as npt 

8from typing_extensions import deprecated 

9 

10 

11@deprecated("Not supported") 

12class SurfaceNearestInterpolator: 

13 """Simple Nearest interpolator without numpy dependency. 

14 

15 .. deprecated:: 1.0 

16 This module is obsolete. 

17 

18 For now, the module still uses numpy. 

19 """ 

20 

21 @staticmethod 

22 def nearest[T](dict_v: dict[float, T], key_value: float) -> T: 

23 """Search the dict value of which key is nearest to given key. 

24 

25 When the target key is exactly between the two keys, select the larger one. 

26 

27 :param dict_v: Dict with float keys and any value. Keys must be sorted in ascending order. 

28 :param key_value: Target key value to search. 

29 :return: Value of the nearest key to target. 

30 """ 

31 list_keys = list(dict_v.keys()) 

32 list_keys = sorted(list_keys) 

33 index_nearest_max = bisect.bisect_left(list_keys, key_value) 

34 if index_nearest_max >= len(list_keys): 

35 index_nearest_max -= 1 

36 if index_nearest_max == 0: 

37 return dict_v[list_keys[index_nearest_max]] 

38 

39 key_max = list_keys[index_nearest_max] 

40 key_min = list_keys[index_nearest_max - 1] 

41 if key_value - key_min < key_max - key_value: 

42 return dict_v[key_min] 

43 return dict_v[key_max] 

44 

45 def __init__(self, xy: tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]], z: npt.NDArray[np.float64]) -> None: 

46 """Nearest interpolation without numpy. 

47 

48 :param xy: XY-coordinates as a tuple of two numpy arrays (x, y). 

49 :param z: Z-coordinates as a numpy array. 

50 """ 

51 self.xy = xy 

52 self.z = z 

53 

54 @cached_property 

55 def dict_x(self) -> dict[float, dict[float, float]]: 

56 """Create a dictionary of x-coordinates with z-coordinates as values. 

57 

58 :return: Dictionary with x-coordinates as keys and z-coordinates as values. 

59 """ 

60 dict_x: dict[float, dict[float, float]] = OrderedDict() 

61 for xy, z in zip(self.xy, self.z, strict=True): 

62 dict_e_z = dict_x.setdefault(float(xy[0]), OrderedDict()) 

63 dict_e_z[float(xy[1])] = z 

64 return dict_x 

65 

66 def __call__(self, xx: npt.NDArray[np.float64], yy: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]: 

67 """Solve the nearest interpolation for given x and y coordinates. 

68 

69 :param xx: X coordinates. 

70 :param yy: Y coordinates. 

71 :return: Z values at given x, y coordinates. 

72 """ 

73 output_xx = np.full_like(xx, 0) 

74 for ix, x in np.ndenumerate(xx): 

75 y = float(yy[ix]) 

76 # noinspection PyDeprecation 

77 dict_e_nearest: dict[float, float] = SurfaceNearestInterpolator.nearest(self.dict_x, x) 

78 # noinspection PyDeprecation 

79 value = SurfaceNearestInterpolator.nearest(dict_e_nearest, y) 

80 output_xx[ix] = value 

81 return output_xx