def test_compare_returnc_interp1d_unc(interp_inputs): # Compare the uncertainties computed from the sensitivities inside the # interpolation range and directly. uy_new_with_sensitivities = interp1d_unc(**interp_inputs)[2] interp_inputs["returnC"] = False uy_new_without_sensitivities = interp1d_unc(**interp_inputs)[2] # Check that extrapolation results match up to machine epsilon. assert_allclose(uy_new_with_sensitivities, uy_new_without_sensitivities, rtol=9e-15)
def interpolate_hyd(hyd_data, f): # Interpolation and extrapolation of calibration data hyd_interpolated = {"frequency": f} N = len(f) // 2 # interpolate real part in selected frequency range ( hyd_interpolated["frequency"], hyd_interpolated["real"], hyd_interpolated["varreal"], Creal, ) = interp1d_unc( f[:N], hyd_data["frequency"], hyd_data["real"], hyd_data["varreal"], bounds_error=False, fill_value="extrapolate", fill_unc="extrapolate", returnC=True, ) # interpolate imag part in selected frequency range hyd_interpolated["imag"] = np.zeros((N, )) hyd_interpolated["varimag"] = np.zeros((N, )) ( hyd_interpolated["frequency"], hyd_interpolated["imag"], hyd_interpolated["varimag"], Cimag, ) = interp1d_unc( f[:N], hyd_data["frequency"], hyd_data["imag"], hyd_data["varimag"], bounds_error=False, fill_value="extrapolate", fill_unc="extrapolate", returnC=True, ) # adjustment of end points hyd_interpolated["imag"][0] = 0 # Must be 0 by definition hyd_interpolated["imag"][-1] = 0 hyd_interpolated["varimag"][0] = 0 # Must be 0 by definition hyd_interpolated["varimag"][-1] = 0 ## Use pseudo-interpolation for the covariances between real and imaginary parts hyd_interpolated["cov"] = (Creal.dot(np.diag(hyd_data["cov"]))).dot( Cimag.T) return hyd_interpolated
def test_extrapolate_above_with_fill_value_interp1d_unc(interp_inputs): # Deal with those cases where at least one of t_new is above the maximum of t and # fill_value is a float, which means constant extrapolation with this value. y_new = interp1d_unc(**interp_inputs)[1] # Check that extrapolation works. assert np.all(y_new[interp_inputs["t_new"] > np.max(interp_inputs["t"])] == interp_inputs["fill_value"])
def test_extrapolate_below_with_fill_uncs_interp1d_unc(interp_inputs): # Deal with those cases where at least one of t_new is below the minimum of t and # fill_unc is a tuple, which means constant extrapolation with its first element. uy_new = interp1d_unc(**interp_inputs)[2] # Check that extrapolation works. assert np.all(uy_new[interp_inputs["t_new"] < np.min(interp_inputs["t"])] == interp_inputs["fill_unc"][0])
def test_returnc_with_extrapolation_check_c_interp1d_unc(interp_inputs, ): # Check if sensitivity computation parallel to linear interpolation and # extrapolation with constant values works as expected regarding the shape and # content of the sensitivity matrix. C = interp1d_unc(**interp_inputs)[3] # Check that C has the right shape. assert C.shape == (len(interp_inputs["t_new"]), len(interp_inputs["t"])) # Find interpolation range because we reuse it. interp_range = (interp_inputs["t_new"] >= np.min(interp_inputs["t"])) | ( interp_inputs["t_new"] <= np.max(interp_inputs["t"])) # Check if each row corresponding to an extrapolated value contains exactly one # non-zero sensitivity. assert np.all(np.count_nonzero(C[np.where(~interp_range)], 1) == 1) # Check if each row corresponding to an interpolated value contains either exactly # one or exactly two non-zero sensitivities, which are the two possible cases # when performing Lagrangian linear interpolation. assert np.all( np.any( ( np.count_nonzero(C[np.where(interp_range)], 1) == 2, np.count_nonzero(C[np.where(interp_range)], 1) == 1, ), 0, )) # Check if each row of sensitivities sum to one, which should hold for the # Lagrangians and proves equality with one for extrapolation sensitivities. assert_allclose(np.sum(C, 1), np.ones_like(interp_inputs["t_new"]))
def test_extrapolate_below_with_fill_unc_interp1d_unc(interp_inputs): # Deal with those cases where at least one of x_new is below the minimum of x and # fill_unc is a float, which means constant extrapolation with this value. uy_new = interp1d_unc(**interp_inputs)[2] # Check that extrapolation works. assert np.all(uy_new[interp_inputs["x_new"] < np.min(interp_inputs["x"])] == interp_inputs["fill_unc"])
def test_extrapolate_above_with_fill_uncs_interp1d_unc(interp_inputs): # Deal with those cases where at least one of t_new is above the maximum of t and # fill_unc is a tuple, which means constant extrapolation with its second element. uy_new = interp1d_unc(**interp_inputs)[2] # Check that extrapolation works. assert np.all(uy_new[interp_inputs["t_new"] > np.max(interp_inputs["t"])] == interp_inputs["fill_unc"][1])
def test_extrapolate_below_without_fill_value_interp1d_unc(interp_inputs): # Deal with those cases where at least one of t_new is below the minimum of t and # fill_value=="extrapolate", which means constant extrapolation from the boundaries. y_new = interp1d_unc(**interp_inputs)[1] # Check that extrapolation works, meaning in the present case, that the boundary # value of y is taken for all t_new below the original bound. assert np.all(y_new[interp_inputs["t_new"] < np.min(interp_inputs["t"])] == interp_inputs["y"][0])
def test_extrapolate_above_without_fill_unc_interp1d_unc(interp_inputs): # Deal with those cases where at least one of t_new is above the maximum of t and # fill_unc=="extrapolate", which means constant extrapolation from the boundaries. uy_new = interp1d_unc(**interp_inputs)[2] # Check that extrapolation works, meaning in the present case, that the boundary # value of y is taken for all t_new above the original bound. assert np.all(uy_new[interp_inputs["t_new"] > np.max(interp_inputs["t"])] == interp_inputs["uy"][-1])
def test_returnc_with_extrapolation_check_below_bound_interp1d_unc( interp_inputs): # Check if extrapolation with constant values outside interpolation range and # returning sensitivities work as expected regarding extrapolation values # below original bound. uy_new, C = interp1d_unc(**interp_inputs)[2:] assert np.all(uy_new[interp_inputs["t_new"] < np.min(interp_inputs["t"])] == interp_inputs["uy"][0])
def test_returnc_with_extrapolation_check_uy_new_above_bound_interp1d_unc( interp_inputs, ): # Check if extrapolation with constant values outside interpolation range and # returning sensitivities work as expected regarding extrapolation values # above original bound. uy_new = interp1d_unc(**interp_inputs)[2] assert np.all(uy_new[interp_inputs["t_new"] > np.max(interp_inputs["t"])] == interp_inputs["uy"][-1])
def test_extrapolate_below_with_fill_values_interp1d_unc(interp_inputs): # Deal with those cases where at least one of x_new is below the minimum of x and # fill_value is a tuple, which means constant extrapolation with its first # element. y_new = interp1d_unc(**interp_inputs)[1] # Check that extrapolation works. assert np.all(y_new[interp_inputs["x_new"] < np.min(interp_inputs["x"])] == interp_inputs["fill_value"][0])
def test_linear_uy_in_interp1d_unc(n, ): # Check for given input, if interpolated uncertainties equal 1 and # :math:`sqrt(2) / 2`. dt_unit = 2 dt_half = dt_unit / 2 t_new = np.arange(0, n, dt_half) t_unit = np.arange(0, n + dt_half, dt_unit) y = uy_unit = np.ones_like(t_unit) uy_new = interp1d_unc(t_new, t_unit, y, uy_unit, "linear")[2] assert np.all(uy_new[0:n:dt_unit] == 1) and np.all( uy_new[1:n:dt_unit] == np.sqrt(2) / 2)
def test_wrong_input_lengths_call_interp1d(interp_inputs): # Check erroneous calls with unequally long inputs. with raises(ValueError): interp_inputs["uy"] = np.tile(interp_inputs["uy"], 2) interp1d_unc(**interp_inputs)
def test_value_error_for_returnc_interp1d_unc(interp_inputs): # Check erroneous calls with returnC and wrong kind. with raises(NotImplementedError): interp1d_unc(**interp_inputs)
def test_usual_call_interp1d_unc(interp_inputs): t_new, y_new, uy_new = interp1d_unc(**interp_inputs)[:] # Check the equal dimensions of the minimum calls output. assert len(t_new) == len(y_new) == len(uy_new)
def test_returnc_with_extrapolation_interp1d_unc(interp_inputs): # Check if extrapolation with constant values outside interpolation range and # returning of sensitivities is callable. assert interp1d_unc(**interp_inputs)
def test_failing_returnc_with_extrapolation_interp1d_unc(interp_inputs): # Since we have not implemented these cases, for now we # check for exception being thrown. assume(not isinstance(interp_inputs["fill_unc"], str)) with raises(NotImplementedError): interp1d_unc(**interp_inputs)
def test_trivial_in_interp1d_unc(interp_inputs): y_new, uy_new = interp1d_unc(**interp_inputs)[1:3] # Check if all 'interpolated' values are present in the actual values. assert np.all(np.isin(y_new, interp_inputs["y"])) assert np.all(np.isin(uy_new, interp_inputs["uy"]))
def test_raise_not_implemented_yet_interp1d(interp_inputs): # Check that not implemented versions raise exceptions. with raises(NotImplementedError): interp1d_unc(**interp_inputs)
def test_linear_in_interp1d_unc(interp_inputs): y_new, uy_new = interp1d_unc(**interp_inputs)[1:3] # Check if all interpolated values lie in the range of the original values. assert np.all(np.min(interp_inputs["y"]) <= y_new) assert np.all(np.max(interp_inputs["y"]) >= y_new)
def test_extrapolate_interp1d_unc(interp_inputs): # Check that extrapolation is executable in general. assert interp1d_unc(**interp_inputs)
def test_raise_value_error_interp1d_unc(interp_inputs): # Check that interpolation with points outside the original domain raises # exception if requested. interp_inputs["bounds_error"] = True with raises(ValueError): interp1d_unc(**interp_inputs)
import matplotlib.pyplot as plt import numpy as np from PyDynamic.uncertainty.interpolate import interp1d_unc from scipy.interpolate import interp1d # base signal N = 10 t = np.cumsum(0.5 * (1 + np.random.random(N))) x = np.sin(t) # + 0.01*np.random.randn(N) # ut = np.full_like(t, 0.05) ux = np.full_like(x, 0.2) # interpolate with PyDynamic ti = np.linspace(np.min(t), np.max(t), 60) # uti = np.full_like(ti, 0.05) ti, xi, uxi = interp1d_unc(ti, t, x, ux, kind="cubic") # interpolate with Monte Carlo X_mc = [] for i in range(2000): interp_x = interp1d(t, x + ux * np.random.randn(len(x)), kind="cubic") xm = interp_x(ti) X_mc.append(xm) x_mc = np.mean(X_mc, axis=0) ux_mc = np.std(X_mc, axis=0) # visualize # interpolated signal plt.plot(ti, xi, "-or", label="interpolation PyDynamic") plt.fill_between(ti, xi + uxi, xi - uxi, color="r", alpha=0.3) # interpolated signal