def test_initialization(chain_of_integrators): digitalControl = DigitalControl(Ts, M) eta2 = 1.0 K1 = 100 K2 = 0 DigitalEstimator(chain_of_integrators['system'], digitalControl, eta2, K1, K2)
def test_batch_iterations(): digitalControl = DigitalControl(Ts, M) eta2 = 100.0 K1 = 25 K2 = 1000 analogSystem = AnalogSystem(A, B, CT, Gamma, Gamma_tildeT) estimator = DigitalEstimator(analogSystem, digitalControl, eta2, K1, K2=K2, stop_after_number_of_iterations=200) estimator(controlSequence()) for est in estimator: print(np.array(est))
def test_estimation_with_circuit_simulator(): eta2 = 1e12 K1 = 1000 K2 = 0 analogSystem = AnalogSystem(A, B, CT, Gamma, Gamma_tildeT) # analogSignals = [Sinusoidal(0.5, 10)] analogSignals = [ConstantSignal(0.25)] digitalControl = DigitalControl(Ts, M) circuitSimulator = StateSpaceSimulator(analogSystem, digitalControl, analogSignals, t_stop=Ts * 1000) estimator = DigitalEstimator(analogSystem, digitalControl, eta2, K1, K2) estimator(circuitSimulator) for est in estimator: print(est)
# analog system with a large analog state order or equivalently for large # number of independent digital controls. # Set the bandwidth of the estimator G_at_omega = np.linalg.norm( analog_system.transfer_function_matrix(np.array([omega_3dB]))) eta2 = G_at_omega**2 print(f"eta2 = {eta2}, {10 * np.log10(eta2)} [dB]") # Set the batch size K1 = 1 << 14 K2 = 1 << 14 # Instantiate the digital estimator (this is where the filter coefficients are # computed). digital_estimator_batch = DigitalEstimator( analog_system, digital_control1, eta2, K1, K2) digital_estimator_batch(simulator1) print(digital_estimator_batch, "\n") ############################################################################### # Visualize Estimator's Transfer Function (Same for Both) # ------------------------------------------------------- # # Logspace frequencies frequencies = np.logspace(-3, 0, 100) omega = 4 * np.pi * beta * frequencies # Compute NTF
def setup(): DigitalEstimator( analogSystem, digitalControl, eta2, K1, K2)
def test_benchmark_digital_estimator_algorithm(benchmark): est = DigitalEstimator( analogSystem, digitalControl, eta2, K1, K2) est(controlSequence()) result = benchmark(iterate_through, est) assert(result == size)
def test_estimation_with_circuit_simulator(): eta2 = 1e12 K1 = 1 << 10 K2 = 1 << 10 size = K2 << 2 window = 1000 size_2 = size // 2 window_2 = window // 2 left_w = size_2 - window_2 right_w = size_2 + window_2 analogSystem = AnalogSystem(A, B, CT, Gamma, Gamma_tildeT) analogSignals = [Sinusodial(amplitude, frequency, phase)] digitalControl1 = DigitalControl(Ts, M) digitalControl2 = DigitalControl(Ts, M) digitalControl3 = DigitalControl(Ts, M) digitalControl4 = DigitalControl(Ts, M) tf_abs = np.abs( analogSystem.transfer_function_matrix(np.array([2 * np.pi * frequency ]))) print(tf_abs, tf_abs.shape) simulator1 = StateSpaceSimulator(analogSystem, digitalControl1, analogSignals) simulator2 = StateSpaceSimulator(analogSystem, digitalControl2, analogSignals) simulator3 = StateSpaceSimulator(analogSystem, digitalControl3, analogSignals) simulator4 = StateSpaceSimulator(analogSystem, digitalControl4, analogSignals) estimator1 = DigitalEstimator(analogSystem, digitalControl1, eta2, K1, K2) estimator2 = ParallelEstimator(analogSystem, digitalControl2, eta2, K1, K2) estimator3 = FIRFilter(analogSystem, digitalControl3, eta2, K1, K2) estimator4 = IIRFilter(analogSystem, digitalControl4, eta2, K2) estimator1(simulator1) estimator2(simulator2) estimator3(simulator3) estimator4(simulator4) tf_1 = estimator1.signal_transfer_function( np.array([2 * np.pi * frequency]))[0] e1_array = np.zeros(size) e2_array = np.zeros(size) e3_array = np.zeros(size) e4_array = np.zeros(size) e1_error = 0 e2_error = 0 e3_error = 0 e4_error = 0 for index in range(size): e1 = estimator1.__next__() e2 = estimator2.__next__() e3 = estimator3.__next__() e4 = estimator4.__next__() e1_array[index] = e1 e2_array[index] = e2 e3_array[index] = e3 e4_array[index] = e4 t = index * Ts u = analogSignals[0].evaluate(t) u_lag = analogSignals[0].evaluate(t - estimator4.filter_lag() * Ts) if (index > left_w and index < right_w): print( f"Time: {t: 0.2f}, Input Signal: {u * tf_1}, e1: {e1}, e2: {e2}, e3: {e3}, e4: {e4}" ) e1_error += np.abs(e1 - u * tf_1)**2 e2_error += np.abs(e2 - u * tf_1)**2 e3_error += np.abs(e3 - u_lag * tf_1)**2 e4_error += np.abs(e4 - u_lag * tf_1)**2 e1_error /= window e2_error /= window e3_error /= window e4_error /= window print(f"""Digital estimator error: {e1_error}, {10 * np.log10(e1_error)} dB""") print(f"""Parallel estimator error: {e2_error}, {10 * np.log10(e2_error)} dB""") print(f"""FIR filter estimator error: {e3_error}, {10 * np.log10(e3_error)} dB""") print(f"""IIR filter estimator error: {e4_error}, {10 * np.log10(e4_error)} dB""") assert (np.allclose(e1_error, 0, rtol=1e-6, atol=1e-6)) assert (np.allclose(e2_error, 0, rtol=1e-6, atol=1e-6)) assert (np.allclose(e3_error, 0, rtol=1e-6, atol=1e-6)) assert (np.allclose(e4_error, 0, rtol=1e-6, atol=1e-6))
np.log10(np.abs(np.array(digital_estimators[-1].h[:, 0, :]))) plt.figure() for index in range(N): plt.plot(np.arange(0, filter_lengths[-1]), impulse_response_dB[filter_lengths[-1]:, index], label=f"$h_{index + 1}[k]$") plt.legend() plt.xlabel("filter tap k") plt.ylabel("$| h_\ell [k]|$ [dB]") plt.xlim((0, filter_lengths[-1])) plt.grid(which='both') digital_estimators_ref = DigitalEstimator( analog_system, digital_control, eta2, stop_after_number_of_iterations >> 2, 1 << 14, stop_after_number_of_iterations=stop_after_number_of_iterations) digital_estimators_ref( byte_stream_2_control_signal( read_byte_stream_from_file( '../a_getting_started/sinusodial_simulation.adc', M), M)) for index, estimate in enumerate(digital_estimators_ref): u_hat[index] = estimate f_ref, psd_ref = compute_power_spectral_density(u_hat) u_hats = [] plt.rcParams['figure.figsize'] = [6.40, 6.40 * 4]
# DigitalEstimator class. However, these computations require us to # specify both the analog system, the digital control and the filter parameters # such as eta2, the batch size K1, and possible the lookahead K2. # Set the bandwidth of the estimator eta2 = 1e7 # Set the batch size K1 = sequence_length # Instantiate the digital estimator (this is where the filter coefficients are # computed). digital_estimator = DigitalEstimator(analog_system, digital_control, eta2, K1) print(digital_estimator, "\n") # Set control signal iterator digital_estimator(control_signal_sequences) ############################################################################### # Producing Estimates # ------------------- # # At this point, we can produce estimates by simply calling the iterator for i in digital_estimator: print(i)
# from the :math:`\ell`-th observation to the final estimate. # Define dummy control and control sequence (not used when computing transfer # functions). However necessary to instantiate the digital estimator T = 1 / (2 * beta) digital_control = DigitalControl(T, N) # Compute eta2 for a given bandwidth. omega_3dB = (4 * np.pi * beta) / 100. eta2 = np.linalg.norm( analog_system.transfer_function_matrix(np.array([omega_3dB])).flatten())**2 # Instantiate estimator. digital_estimator = DigitalEstimator(analog_system, digital_control, eta2, K1=1) # Compute NTF ntf = digital_estimator.noise_transfer_function(omega) ntf_dB = 20 * np.log10(np.abs(ntf)) # Compute STF stf = digital_estimator.signal_transfer_function(omega) stf_dB = 20 * np.log10(np.abs(stf.flatten())) # Plot plt.figure() plt.semilogx(frequencies, stf_dB, label='$STF(\omega)$') for n in range(N): plt.semilogx(frequencies, ntf_dB[0, n, :], label=f"$|NTF_{n+1}(\omega)|$")