def test_1Dakima(self): # Test 1D-akima vs general equivalent. p = np.linspace(0, 100, 25) f_p = np.cos(p * np.pi * 0.5) x = np.linspace(-1, 101, 33) interp = InterpND(points=p, values=f_p, method='1D-akima', extrapolate=True) f, df_dx = interp.interpolate(x, compute_derivative=True) interp_base = InterpND(points=p, values=f_p, method='akima', extrapolate=True) f_base, df_dx_base = interp_base.interpolate(x, compute_derivative=True) assert_near_equal(f, f_base, 1e-13) assert_near_equal(df_dx, df_dx_base.ravel(), 1e-13) # Test non-vectorized. for j, x_i in enumerate(x): interp = InterpND(points=p, values=f_p, method='1D-akima', extrapolate=True) f, df_dx = interp.interpolate(x_i, compute_derivative=True) assert_near_equal(f, f_base[j], 1e-13) # Compare abs error since deriv is near zero in some spots. abs_err = np.abs(df_dx[0] - df_dx_base[j]) assert_near_equal(abs_err, 0.0, 1e-13)
def test_derivative_hysteresis_bug(self): alt = np.array([-1000, 0, 1000], dtype=float) rho = np.array([0.00244752, 0.00237717, 0.00230839]) rho_interp = InterpND(method='slinear', points=alt, values=rho, extrapolate=True) x = 0.0 _, dval1 = rho_interp.interpolate([x], compute_derivative=True) x = 0.5 _, dval2 = rho_interp.interpolate([x], compute_derivative=True) x = 0.0 _, dval3 = rho_interp.interpolate([x], compute_derivative=True) x = -0.5 _, dval4 = rho_interp.interpolate([x], compute_derivative=True) x = 0.0 _, dval5 = rho_interp.interpolate([x], compute_derivative=True) assert_near_equal(dval3 - dval1, np.array([[0.0]])) assert_near_equal(dval5 - dval1, np.array([[0.0]]))
def test_NaN_exception(self): np.random.seed(1234) x = np.linspace(0, 2, 5) y = np.linspace(0, 1, 7) values = np.random.rand(5, 7) interp = InterpND((x, y), values) with self.assertRaises(OutOfBoundsError) as cm: interp.interpolate(np.array([1, np.nan])) err = cm.exception self.assertEqual(str(err), 'One of the requested xi contains a NaN') self.assertEqual(err.idx, 1) self.assertTrue(np.isnan(err.value)) self.assertEqual(err.lower, 0) self.assertEqual(err.upper, 1)
def test_trilinear(self): # Test trilinear vs 3d slinear. p1 = np.linspace(0, 100, 25) p2 = np.linspace(-10, 10, 15) p3 = np.linspace(0, 1, 12) # can use meshgrid to create a 3D array of test data P1, P2, P3 = np.meshgrid(p1, p2, p3, indexing='ij') f_p = np.sqrt(P1) + P2 * P3 x1 = np.linspace(-2, 101, 5) x2 = np.linspace(-10.5, 11, 5) x3 = np.linspace(-0.2, 1.1, 5) X1, X2, X3 = np.meshgrid(x1, x2, x3, indexing='ij') x = np.zeros((125, 3)) x[:, 0] = X1.ravel() x[:, 1] = X2.ravel() x[:, 2] = X3.ravel() interp = InterpND(points=(p1, p2, p3), values=f_p, method='trilinear', extrapolate=True) f, df_dx = interp.interpolate(x, compute_derivative=True) interp_base = InterpND(points=(p1, p2, p3), values=f_p, method='slinear', extrapolate=True) f_base, df_dx_base = interp_base.interpolate(x, compute_derivative=True) assert_near_equal(f, f_base, 1e-11) assert_near_equal(df_dx, df_dx_base, 1e-11) # Test non-vectorized. for j, x_i in enumerate(x): interp = InterpND(points=(p1, p2, p3), values=f_p, method='trilinear', extrapolate=True) f, df_dx = interp.interpolate(x_i, compute_derivative=True) assert_near_equal(f, f_base[j], 1e-11) assert_near_equal(df_dx[0], df_dx_base[j, :], 1e-11)
def test_interp_1Dflat_list_x(self): x = np.array([0., 1., 2., 3., 4.]) y = x**2 f = InterpND(points=x, values=y) computed = f.interpolate([np.array([2.5]), np.array([3.5])]) assert_equal_arrays(computed, np.array([6.5, 12.5]))
def test_spline_xi3d(self): points, values, func, df = self._get_sample_2d() np.random.seed(1) test_pt = np.random.uniform(0, 3, 6).reshape(3, 2) actual = func(*test_pt.T) for method in self.valid_methods: interp = InterpND(points, values, method) computed = interp.interpolate(test_pt) r_err = rel_error(actual, computed) assert r_err < self.tol[method]
def test_spline_single_dim(self): # test interpolated values points, values, func, df = self._get_sample_1d() test_pt = np.array([[0.76], [.33]]) actual = func(test_pt).flatten() for method in self.interp_methods: interp = InterpND(method=method, points=points, values=values) computed = interp.interpolate(test_pt) r_err = rel_error(actual, computed) assert r_err < self.tol[method]
def test_spline_xi3d_akima_delta_x(self): points, values, func, df = self. _get_sample_2d() np.random.seed(1) test_pt = np.random.uniform(0, 3, 6).reshape(3, 2) actual = func(*test_pt.T) interp = InterpND(method='akima', points=points, values=values, delta_x=0.01) computed = interp.interpolate(test_pt) r_err = rel_error(actual, computed) #print('akima', computed, actual, r_err) assert r_err < self.tol['akima']
def test_spline_xi1d(self): # test interpolated values points, values, func, df = self._get_sample_2d() np.random.seed(1) test_pt = np.random.uniform(0, 3, 2) actual = func(*test_pt) for method in self.interp_methods: interp = InterpND(method=method, points=points, values=values) computed = interp.interpolate(test_pt) r_err = rel_error(actual, computed) assert r_err < self.tol[method]
def test_cs_across_interp(self): # The standalone interpolator is used inside of components, so the imaginary part must # be carried through all operations to the outputs. xcp = np.array([1.0, 2.0, 4.0, 6.0, 10.0, 12.0]) ycp = np.array([5.0, 12.0, 14.0, 16.0, 21.0, 29.0]) n = 50 x = np.linspace(1.0, 12.0, n) ycp = np.array([[5.0 + 1j, 12.0, 14.0, 16.0, 21.0, 29.0], [5.0, 12.0 + 1j, 14.0, 16.0, 21.0, 29.0]]) for method in SPLINE_METHODS: # complex step not supported on scipy methods if method.startswith('scipy'): continue interp = InterpND(method=method, points=xcp, x_interp=x) y, dy = interp.evaluate_spline(ycp, compute_derivative=True) self.assertTrue(y.dtype == complex) if method in ['akima']: # Derivs depend on values only for akima. self.assertTrue(dy.dtype == complex) p1 = np.linspace(0, 100, 25) p2 = np.linspace(-10, 10, 5) p3 = np.linspace(0, 1, 10) # can use meshgrid to create a 3D array of test data P1, P2, P3 = np.meshgrid(p1, p2, p3, indexing='ij') f = np.sqrt(P1) + P2 * P3 x = np.array([[55.12 + 1j, -2.14, 0.323], [55.12, -2.14 + 1j, 0.323], [55.12, -2.14, 0.323 + 1j]]) for method in TABLE_METHODS: # complex step not supported on scipy methods if method.startswith('scipy'): continue if method in ['1D-akima', 'akima1D']: # These methods are for fixed grids other than 3d. continue interp = InterpND(method=method, points=(p1, p2, p3), values=f) y, dy = interp.interpolate(x, compute_derivative=True) self.assertTrue(y.dtype == complex) self.assertTrue(dy.dtype == complex)
def test_auto_reduce_spline_order(self): # if a spline method is used and spline_dim_error=False and a dimension # does not have enough points, the spline order for that dimension # should be automatically reduced np.random.seed(314) # x dimension is too small for cubic, should fall back to linear x = [0, 1] y = np.linspace(-10, 4, 10) z = np.linspace(1000, 2000, 20) points = [x, y, z] values = np.random.randn(2, 10, 20) interp = InterpND(points, values, interp_method='scipy_cubic') # first dimension (x) should be reduced to k=1 (linear) self.assertEqual(interp.table._ki[0], 1) # should operate as normal x = np.array([0.5, 0, 1001]) result = interp.interpolate(x) assert_almost_equal(result, -0.046325695741704434, decimal=5) interp = InterpND(points, values, interp_method='scipy_slinear') value1 = interp.interpolate(x) # cycle through different methods that require order reduction # in the first dimension interp = InterpND(points, values, interp_method='scipy_quintic') value2 = interp.interpolate(x) interp.gradient(x) interp = InterpND(points, values, interp_method='scipy_cubic') value3 = interp.interpolate(x) interp.gradient(x) # values from different methods should be different self.assertTrue(value1[0] != value2[0]) self.assertTrue(value2[0] != value3[0])
def test_spline_out_of_bounds_extrap(self): points, values, func, df = self._get_sample_2d() np.random.seed(5) test_pt = np.random.uniform(3, 3.1, 2) actual = func(*test_pt) gradient = np.array(df(*test_pt)) for method in self.valid_methods: k = self.interp_configs[method] interp = InterpND(points, values, method, bounds_error=False) computed = interp.interpolate(test_pt) computed_grad = interp.gradient(test_pt) r_err = rel_error(actual, computed) assert r_err < 1e3 * self.tol[method] r_err = rel_error(gradient, computed_grad) # extrapolated gradients are even trickier, but usable still assert r_err < 2e3 * self.tol[method]
def test_table_interp(self): # create input param training data, of sizes 25, 5, and 10 points resp. p1 = np.linspace(0, 100, 25) p2 = np.linspace(-10, 10, 5) p3 = np.linspace(0, 1, 10) # can use meshgrid to create a 3D array of test data P1, P2, P3 = np.meshgrid(p1, p2, p3, indexing='ij') f = np.sqrt(P1) + P2 * P3 interp = InterpND(method='lagrange3', points=(p1, p2, p3), values=f) x = np.array([55.12, -2.14, 0.323]) f, df_dx = interp.interpolate(x, compute_derivative=True) actual = np.array([6.73306794]) deriv_actual = np.array([[0.06734927, 0.323, -2.14]]) assert_near_equal(f, actual, tolerance=1e-7) assert_near_equal(df_dx, deriv_actual, tolerance=1e-7)
def test_spline_out_of_bounds_extrap(self): points, values, func, df = self. _get_sample_2d() np.random.seed(5) test_pt = np.random.uniform(3, 3.1, 2) actual = func(*test_pt) gradient = np.array(df(*test_pt)) tol = 1e-1 for method in self.interp_methods: k = self.interp_configs[method] if method == 'slinear': tol = 2 interp = InterpND(method=method, points=points, values=values, extrapolate=True) computed, computed_grad = interp.interpolate(test_pt, compute_derivative=True) computed_grad = interp.gradient(test_pt) r_err = rel_error(actual, computed) assert r_err < tol r_err = rel_error(gradient, computed_grad) # extrapolated gradients are even trickier, but usable still assert r_err < 2 * tol