def test_MC(visualizeOutput=False): # run method y, Uy = MC(x, sigma_noise, b1, [1.0], Ub, runs=runs, blow=b2) assert len(y) == len(x) assert Uy.shape == (x.size, x.size) if visualizeOutput: # visualize input and mean of system response plt.plot(time, x) plt.plot(time, y) # visualize uncertainty of output plt.plot(time, y - np.sqrt(np.diag(Uy)), linestyle="--", linewidth=1, color="red") plt.plot(time, y + np.sqrt(np.diag(Uy)), linestyle="--", linewidth=1, color="red") plt.show()
def test_fir_filter_MC_comparison(): N_signal = np.random.randint(20, 25) x = random_array(N_signal) Ux = random_covariance_matrix(N_signal) N_theta = np.random.randint(2, 5) # scipy.linalg.companion requires N >= 2 theta = random_array(N_theta) # scipy.signal.firwin(N_theta, 0.1) Utheta = random_covariance_matrix(N_theta) # run method y_fir, Uy_fir = _fir_filter(x, theta, Ux, Utheta, initial_conditions="zero") # run FIR with MC and extract diagonal of returned covariance y_mc, Uy_mc = MC(x, Ux, theta, np.ones(1), Utheta, blow=None, runs=10000) # HACK: for visualization during debugging # from PyDynamic.misc.tools import plot_vectors_and_covariances_comparison # plot_vectors_and_covariances_comparison( # vector_1=y_fir, # vector_2=y_mc, # covariance_1=Uy_fir, # covariance_2=Uy_mc, # label_1="fir", # label_2="mc", # title=f"filter: {len(theta)}, signal: {len(x)}", # ) # /HACK assert_allclose(y_fir, y_mc, atol=1e-1, rtol=1e-1) assert_allclose(Uy_fir, Uy_mc, atol=1e-1, rtol=1e-1)
def _conduct_FIRuncFilter_and_MonteCarlo(Ub, b1, blow, kind, runs, sigma_noise, x): y, Uy = FIRuncFilter(x, sigma_noise, b1, Ub, blow=blow, kind=kind) # apply uncertain FIR filter (GUM formula) yMC, UyMC = MC(x, sigma_noise, b1, np.ones(1), Ub, runs=runs, blow=blow) # apply uncertain FIR filter (Monte Carlo) return Uy, UyMC, y, yMC
def test_FIRuncFilter_MC_uncertainty_comparison(filters, signals, lowpasses): # Check output for thinkable permutations of input parameters against a Monte Carlo approach. # run method y_fir, Uy_fir = FIRuncFilter(**filters, **signals, **lowpasses, return_full_covariance=True) # run Monte Carlo simulation of an FIR ## adjust input to match conventions of MC x = signals["y"] ux = signals["sigma_noise"] b = filters["theta"] a = [1.0] if isinstance(filters["Utheta"], np.ndarray): Uab = filters["Utheta"] else: # Utheta == None Uab = np.zeros( (len(b), len(b))) # MC-method cant deal with Utheta = None blow = lowpasses["blow"] if isinstance(blow, np.ndarray): n_blow = len(blow) else: n_blow = 0 ## run FIR with MC and extract diagonal of returned covariance y_mc, Uy_mc = MC(x, ux, b, a, Uab, blow=blow, runs=2000) # HACK for visualization during debugging # import matplotlib.pyplot as plt # fig, ax = plt.subplots(nrows=1, ncols=3) # ax[0].plot(y_fir, label="fir") # ax[0].plot(y_mc, label="mc") # ax[0].set_title("filter: {0}, signal: {1}".format(len(b), len(x))) # ax[0].legend() # ax[1].imshow(Uy_fir) # ax[1].set_title("FIR") # ax[2].imshow(Uy_mc) # ax[2].set_title("MC") # plt.show() # /HACK # check basic properties assert np.all(np.diag(Uy_fir) >= 0) assert np.all(np.diag(Uy_mc) >= 0) assert Uy_fir.shape == Uy_mc.shape # approximative comparison after swing-in of MC-result # (which is after the combined length of blow and b) assert np.allclose( Uy_fir[len(b) + n_blow:, len(b) + n_blow:], Uy_mc[len(b) + n_blow:, len(b) + n_blow:], atol=2e-1 * Uy_fir.max(), # very broad check, increase runs for better fit rtol=1e-1, )
def test_compare_MC_UMC(): np.random.seed(12345) y_MC, Uy_MC = MC(x,sigma_noise,b1,[1.0],Ub,runs=2*runs,blow=b2) y_UMC, Uy_UMC, _, _, _ = UMC(x, b1, [1.0], Ub, blow=b2, sigma=sigma_noise, runs=2*runs, runs_init=10) # both methods should yield roughly the same results assert np.allclose(y_MC, y_UMC, atol=5e-4) assert np.allclose(Uy_MC, Uy_UMC, atol=5e-4)
def apply_filter(self, b, a=1, filter_uncertainty=None, MonteCarloRuns=None): """Apply digital filter (b,a) to the signal values and propagate the uncertainty associated with the signal Parameters ---------- b: np.ndarray filter numerator coefficients a: np.ndarray filter denominator coefficients, use a=1 for FIR-type filter filter_uncertainty: np.ndarray covariance matrix associated with filter coefficients, Uab=None if no uncertainty associated with filter MonteCarloRuns: int number of Monte Carlo runs, if `None` then GUM linearization will be used Returns ------- no return variables """ if isinstance(a, list): a = np.array(a) if not (isinstance(a, np.ndarray)): # FIR type filter if len(self.uncertainty.shape) == 1: if not isinstance(MonteCarloRuns, int): self.values, self.uncertainty = \ FIRuncFilter(self.values, self.uncertainty, b, Utheta = filter_uncertainty) else: self.values, self.uncertainty = \ MC(self.values, self.uncertainty, b, a, filter_uncertainty, runs=MonteCarloRuns) else: if not isinstance(MonteCarloRuns, int): MonteCarloRuns = 10000 self.values, self.uncertainty = \ MC(self.values, self.uncertainty, b, a, filter_uncertainty, runs=MonteCarloRuns) else: # IIR-type filter if not isinstance(MonteCarloRuns, int): MonteCarloRuns = 10000 self.values, self.uncertainty = \ MC(self.values, self.uncertainty, b, a, filter_uncertainty, runs=MonteCarloRuns)
def test_fir_filter_MC_comparison(): N_signal = np.random.randint(20, 25) x = random_array(N_signal) Ux = random_covariance_matrix(N_signal) N_theta = np.random.randint(2, 5) # scipy.linalg.companion requires N >= 2 theta = random_array(N_theta) # scipy.signal.firwin(N_theta, 0.1) Utheta = random_covariance_matrix(N_theta) # run method y_fir, Uy_fir = _fir_filter(x, theta, Ux, Utheta, initial_conditions="zero") ## run FIR with MC and extract diagonal of returned covariance y_mc, Uy_mc = MC(x, Ux, theta, [1.0], Utheta, blow=None, runs=10000) # HACK: for visualization during debugging # import matplotlib.pyplot as plt # fig, ax = plt.subplots(nrows=1, ncols=3) # ax[0].plot(y_fir, label="fir") # ax[0].plot(y_mc, label="mc") # ax[0].set_title("filter: {0}, signal: {1}".format(len(theta), len(x))) # ax[0].legend() # ax[1].imshow(Uy_fir) # ax[1].set_title("FIR") # ax[2].imshow(Uy_mc) # ax[2].set_title("MC") # plt.show() # /HACK # approximate comparison assert np.all(np.diag(Uy_fir) >= 0) assert np.all(np.diag(Uy_mc) >= 0) assert Uy_fir.shape == Uy_mc.shape assert np.allclose(Uy_fir, Uy_mc, atol=1e-1, rtol=1e-1)
FC = fcut + (2 * np.random.rand(runs) - 1) * 0.5e3 B = np.zeros((runs, L + 1)) for k in range(runs): # Monte Carlo for filter coefficients of low-pass filter B[k, :] = kaiser_lowpass(L, FC[k], Fs)[0] Ub = make_semiposdef(np.cov(B, rowvar=False)) # covariance matrix of MC result # simulate input and output signals time = np.arange(0, 499 * Ts, Ts) # time values noise = 1e-5 # std of white noise x = rect(time, 100 * Ts, 250 * Ts, 1.0, noise=noise) # input signal y, Uy = FIRuncFilter(x, noise, b, Ub, blow=b) # apply uncertain FIR filter (GUM formula) yMC, UyMC = MC(x, noise, b, np.ones(1), Ub, runs=1000, blow=b) # apply uncertain FIR filter (Monte Carlo) plt.figure(1) plt.cla() plt.plot(time, x, label="input") plt.plot(time, y, label="output") plt.xlabel("time / au") plt.ylabel("signal amplitude / au") plt.legend() plt.figure(2) plt.cla() plt.plot(time, Uy, label="FIR formula") plt.plot(time, np.sqrt(np.diag(UyMC)), label="Monte Carlo") plt.xlabel("time / au") plt.ylabel("signal uncertainty/ au")
for kind in ["float", "corr", "diag"]: for blow in [None, b2]: print(kind, type(blow)) if kind == "float": # input signal + run methods x = rect(time, 100 * Ts, 250 * Ts, 1.0, noise=sigma_noise) y, Uy = FIRuncFilter( x, sigma_noise, b1, Ub, blow=blow, kind=kind) # apply uncertain FIR filter (GUM formula) yMC, UyMC = MC( x, sigma_noise, b1, [1.0], Ub, runs=runs, blow=blow) # apply uncertain FIR filter (Monte Carlo) elif kind == "corr": # get an instance of noise, the covariance and the covariance-matrix with the specified color color = "red" noise = power_law_noise(N=nTime, color_value=color, std=sigma_noise) Ux = power_law_acf(nTime, color_value=color, std=sigma_noise) # input signal x = rect(time, 100 * Ts, 250 * Ts, 1.0, noise=noise)
def conduct_validation_of_FIRuncFilter(): # parameters of simulated measurement Fs = 100e3 # sampling frequency (in Hz) Ts = 1 / Fs # sampling interval length (in s) # nominal system parameters fcut = 20e3 # low-pass filter cut-off frequency (6 dB) L = 100 # filter order b1 = kaiser_lowpass(L, fcut, Fs)[0] b2 = kaiser_lowpass(L - 20, fcut, Fs)[0] # uncertain knowledge: cutoff between 19.5kHz and 20.5kHz runs = 1000 FC = fcut + (2 * np.random.rand(runs) - 1) * 0.5e3 B = np.zeros((runs, L + 1)) for k in range( runs): # Monte Carlo for filter coefficients of low-pass filter B[k, :] = kaiser_lowpass(L, FC[k], Fs)[0] Ub = make_semiposdef(np.cov( B, rowvar=False)) # covariance matrix of MC result # simulate input and output signals nTime = 500 time = np.arange(nTime) * Ts # time values # different cases sigma_noise = 1e-2 # 1e-5 for kind in ["float", "corr", "diag"]: for blow in [None, b2]: print(kind, type(blow)) if kind == "float": # input signal + run methods x = rect(time, 100 * Ts, 250 * Ts, 1.0, noise=sigma_noise) Uy, UyMC, y, yMC = _conduct_FIRuncFilter_and_MonteCarlo( Ub, b1, blow, kind, runs, sigma_noise, x) elif kind == "corr": # get an instance of noise, the covariance and the covariance-matrix # with # the specified color color = "red" noise = power_law_noise(N=nTime, color_value=color, std=sigma_noise) Ux = power_law_acf(nTime, color_value=color, std=sigma_noise) # input signal x = rect(time, 100 * Ts, 250 * Ts, 1.0, noise=noise) # build Ux_matrix from autocorrelation Ux Ux_matrix = toeplitz(trimOrPad(Ux, nTime)) # run methods y, Uy = FIRuncFilter( x, Ux, b1, Ub, blow=blow, kind=kind) # apply uncertain FIR filter (GUM formula) yMC, UyMC = MC( x, Ux_matrix, b1, np.ones(1), Ub, runs=runs, blow=blow) # apply uncertain FIR filter (Monte Carlo) elif kind == "diag": sigma_diag = sigma_noise * ( 1 + np.heaviside(np.arange(len(time)) - len(time) // 2.5, 0) ) # std doubles after half of the time noise = sigma_diag * white_gaussian(len(time)) # input signal + run methods x = rect(time, 100 * Ts, 250 * Ts, 1.0, noise=noise) Uy, UyMC, y, yMC = _conduct_FIRuncFilter_and_MonteCarlo( Ub, b1, blow, kind, runs, sigma_diag, x) # compare FIR and MC results plt.figure(1) plt.cla() plt.plot(time, x, label="input") plt.plot(time, y, label="output FIR direct") plt.plot(time, yMC, label="output FIR MC") plt.xlabel("time [s]") plt.ylabel("signal amplitude [1]") plt.legend() plt.figure(2) plt.cla() plt.plot(time, Uy, label="FIR formula") plt.plot(time, np.sqrt(np.diag(UyMC)), label="Monte Carlo") plt.xlabel("time [s]") plt.ylabel("signal uncertainty [1]") plt.legend() plt.show()