Coverage for pesummary/utils/interpolate.py: 61.1%
54 statements
« prev ^ index » next coverage.py v7.4.4, created at 2025-11-05 13:38 +0000
« prev ^ index » next coverage.py v7.4.4, created at 2025-11-05 13:38 +0000
1# Licensed under an MIT style license -- see LICENSE.md
3from scipy.interpolate import interp1d, RectBivariateSpline as _RectBivariateSpline
4import numpy as np
6__author__ = [
7 "Charlie Hoy <charlie.hoy@ligo.org>",
8]
11class BoundedInterp1d(object):
12 """Return a bounded 1-D interpolant. Interpolating outside of the bounded
13 domain simply returns 0.
15 Parameters
16 ----------
17 x: np.array
18 A 1-D array of real values.
19 y: np.array
20 A N-D array of real values. The length of y along the interpolation axis
21 must be equal to the length of x.
22 xlow: float, optional
23 the lower bound of the bounded domain
24 xhigh: float, optional
25 the upper bound of the bounded domain
26 **kwargs: dict, optional
27 all kwargs passed to scipy.interpolate.interp1d
28 """
29 def __init__(self, x, y, xlow=-np.inf, xhigh=np.inf, **kwargs):
30 if xlow > np.min(x):
31 self._xlow = xlow
32 else:
33 self._xlow = np.min(x)
34 if xhigh < np.max(x):
35 self._xhigh = xhigh
36 else:
37 self._xhigh = np.max(x)
38 self._complex = np.iscomplexobj(y)
39 self._interp_real = interp1d(x, np.real(y), **kwargs)
40 if self._complex:
41 self._interp_imaginary = interp1d(x, np.imag(y), **kwargs)
43 @property
44 def xlow(self):
45 return self._xlow
47 @property
48 def xhigh(self):
49 return self._xhigh
51 def __call__(self, pts):
52 pts = np.atleast_1d(pts)
53 result = np.zeros_like(pts)
54 within_bounds = np.ones_like(pts, dtype='bool')
55 within_bounds[(pts < self.xlow) | (pts > self.xhigh)] = False
56 result[within_bounds] = self._interp_real(pts[within_bounds])
57 if self._complex:
58 result[within_bounds] += 1j * self._interp_imaginary(
59 pts[within_bounds]
60 )
61 return result
64class RectBivariateSpline(_RectBivariateSpline):
65 """A modified version of scipy.interpolant.RectBivariateSpline to add
66 kwargs that were previously available in the deprecated
67 scipy.interpolant.interp2d.
69 Parameters
70 ----------
71 x: np.ndarray
72 data points in the x direction
73 y: np.ndarray
74 data points in the y direction
75 z: np.ndarray
76 2d array of data points with shape (x.size, y.size)
77 bounds_error: bool, optional
78 If True, a ValueError is raised when interpolated values outside of
79 the range [min(x), max(x)] and [min(y), max(y)] are requested. If False,
80 fill_value is used when fill_value is not None. Default False
81 fill_value: float, optional
82 the value to use when interpolated values outside of the range
83 [min(x), max(x)] and [min(y), max(y)] are requested. Default None
84 """
85 def __init__(self, x, y, z, bounds_error=False, fill_value=None, **kwargs):
86 self.x_min = np.min(x)
87 self.x_max = np.max(x)
88 self.y_min = np.min(y)
89 self.y_max = np.max(y)
90 self.bounds_error = bounds_error
91 self.fill_value = fill_value
92 super(RectBivariateSpline, self).__init__(x=x, y=y, z=z, **kwargs)
94 def __call__(self, x, y, *args, **kwargs):
95 result = super(RectBivariateSpline, self).__call__(x=x, y=y, *args, **kwargs)
96 if self.bounds_error or self.fill_value is not None:
97 out_of_bounds_x = (x < self.x_min) | (x > self.x_max)
98 out_of_bounds_y = (y < self.y_min) | (y > self.y_max)
99 any_out_of_bounds_x = np.any(out_of_bounds_x)
100 any_out_of_bounds_y = np.any(out_of_bounds_y)
101 if self.bounds_error and (any_out_of_bounds_x or any_out_of_bounds_y):
102 raise ValueError(
103 "x and y are out of range. Please ensure that x is in range "
104 "[{}, {}] and y is in range [{}, {}]".format(
105 self.x_min, self.x_max, self.y_min, self.y_max
106 )
107 )
108 if self.fill_value is not None:
109 if any_out_of_bounds_x:
110 result[out_of_bounds_x, :] = self.fill_value
111 if any_out_of_bounds_y:
112 result[:, out_of_bounds_y] = self.fill_value
113 return result