def run_reconstruction(self): t = np.linspace(0, (self.size - 1) * self.sampling_period, self.size) recon_time_start = time.time() self.eta2 = np.ones(self.M * self.N) * self.eta2_magnitude self.reconstruction_options = { 'eta2': self.eta2, 'sigmaU2': [1.] * self.L, 'noise': [{ 'std': self.sigma2_reconst, 'steeringVector': self.beta * np.eye(self.N * self.M)[:, i], 'name': 'noise_{}'.format(i) } for i in range(self.N * self.M)] } self.reconstruction = reconstruction.WienerFilter( t, self.sys, self.input_signals, self.reconstruction_options) tmp_estimates, recon_log = self.reconstruction.filter(self.ctrl) self.input_estimates = tmp_estimates[self.border:-self.border] self.recon_run_time = time.time() - recon_time_start self.log(recon_log) self.log("Reconstruction run time: {:.2f} seconds".format( self.recon_run_time)) self.finished_reconstruction = True
def test_for_constant_signal(): size = 1000 Ts = 0.1 coef = np.ones(size) * 0.7 vector = np.array([1., 0, 0]) inp = system.Input(Ts, coefficients=coef, steeringVector=vector) A = np.eye(3, k=-1) c = np.eye(3) sys = system.System(A, c) mixingMatrix = -1e1 * np.eye(3) ctrl = system.Control(mixingMatrix, size) sim = simulator.Simulator(sys, ctrl) t = np.linspace(0., 99., size) res = sim.simulate(t, (inp, )) plt.figure() plt.plot(res['t'], res['output']) plt.legend(["%s" % x for x in range(3)]) recon = reconstruction.WienerFilter(t, sys, (inp, )) u_hat, log = recon.filter(ctrl) plt.figure() plt.plot(t, coef, label="u") plt.plot(t, u_hat, label="u_hat") plt.legend()
def test_lowering_order(): size = 1000 order = 8 Ts = 0.1 amplitude = 0.35 frequency = 1e-2 phase = np.pi * 7. / 8. vector = np.zeros(order) vector[0] = 1. inp = system.Sin(Ts, amplitude=amplitude, frequency=frequency, phase=phase, steeringVector=vector) A = np.eye(order, k=-1) c = np.eye(order) sys = system.System(A, c) mixingMatrix = -1e0 * np.eye(order) ctrl = system.Control(mixingMatrix, size) sim = simulator.Simulator(sys, ctrl) t = np.linspace(0., 99., size) res = sim.simulate(t, (inp, )) plt.figure() plt.plot(res['t'], res['output']) plt.legend(["%s" % x for x in range(order)]) u_hats = [] for index in range(1, order + 1): newSystem, newControl, newInput = system.LowerOrderSystem( sys, ctrl, inp, index) recon = reconstruction.WienerFilter(t, newSystem, (newInput, )) u_hat, log = recon.filter(newControl) u_hats.append(u_hat) plt.figure() plt.plot(t, inp.scalarFunction(t), label="u") for index in range(order): plt.plot(t, u_hats[index], label="u_hat_%i" % (index + 1)) plt.legend()
def test_evaluate_PlotTransferFunctions(): size = 10000 order = 7 Ts = 0.1 beta = 5. coef = np.random.rand(size) * 2. - 1. vector = np.zeros(order) vector[0] = 2. inp = system.FirstOrderHold(Ts, coefficients=coef, steeringVector=vector) T = 40 t = 10 ** (T/10.) rho = np.power(t, 1./order)/beta * np.sqrt(2) A = beta * np.eye(order, k=-1) - rho * np.eye(order, k=0) c = np.eye(order) sys = system.System(A, c) mixingMatrix = - 1e1 * np.eye(order) ctrl = system.Control(mixingMatrix, size) sim = simulator.Simulator(sys, ctrl) t = np.linspace(0., 99., size) res = sim.simulate(t, (inp,)) plt.figure() plt.plot(res['t'], res['output']) plt.legend(["%s" % x for x in range(order)]) recon = reconstruction.WienerFilter(t, sys, (inp,)) u_hat, log = recon.filter(ctrl) ev = evaluation.Evaluation(sys, u_hat, (inp,)) freqsLim = [1e-2, 1e2] figure1 = ev.PlotTransferFunctions(freqsLim) figure2 = ev.PlotPowerSpectralDensity(t)
def test_for_sinusodial_signal(): size = 1000 order = 8 Ts = 0.1 amplitude = 0.35 frequency = 1e-2 phase = np.pi * 7. / 8. vector = np.zeros(order) vector[0] = 1. inp = system.Sin(Ts, amplitude=amplitude, frequency=frequency, phase=phase, steeringVector=vector) A = np.eye(order, k=-1) c = np.eye(order) sys = system.System(A, c) mixingMatrix = -1e0 * np.eye(order) ctrl = system.Control(mixingMatrix, size) sim = simulator.Simulator(sys, ctrl) t = np.linspace(0., 99., size) res = sim.simulate(t, (inp, )) plt.figure() plt.plot(res['t'], res['output']) plt.legend(["%s" % x for x in range(order)]) recon = reconstruction.WienerFilter(t, sys, (inp, )) u_hat, log = recon.filter(ctrl) plt.figure() plt.plot(t, inp.scalarFunction(t), label="u") plt.plot(t, u_hat, label="u_hat") plt.legend()
def test_for_first_order_filter_signal(): size = 10000 order = 7 Ts = 0.1 coef = np.random.rand(size) * 2. - 1. vector = np.zeros(order) vector[0] = 1. inp = system.FirstOrderHold(Ts, coefficients=coef, steeringVector=vector) A = np.eye(order, k=-1) c = np.eye(order) sys = system.System(A, c) mixingMatrix = -1e1 * np.eye(order) ctrl = system.Control(mixingMatrix, size) sim = simulator.Simulator(sys, ctrl) t = np.linspace(0., 99., size) res = sim.simulate(t, (inp, )) plt.figure() plt.plot(res['t'], res['output']) plt.legend(["%s" % x for x in range(order)]) recon = reconstruction.WienerFilter(t, sys, (inp, )) reconP = reconstruction.ParallelWienerFilter(t, sys, (inp, )) u_hat, log = recon.filter(ctrl) u_hatP = reconP.filter(ctrl) plt.figure() plt.plot(t, coef, label="coef") plt.plot(t, inp.scalarFunction(t), label="u") plt.plot(t, u_hat, label="u_hat") plt.plot(t, u_hatP, label="u_hatP") plt.legend()
def test_for_noise_simulation(): size = 1000 order = 8 Ts = 0.1 amplitude = 0.35 frequency = 1e-2 phase = np.pi * 7. / 8. vector = np.zeros(order) vector[0] = 1. inp = system.Sin(Ts, amplitude=amplitude, frequency=frequency, phase=phase, steeringVector=vector) A = np.eye(order, k=-1) c = np.eye(order) sys = system.System(A, c) mixingMatrix = -1e0 * np.eye(order) ctrl = system.Control(mixingMatrix, size) noiseVariance = np.ones(order) * 1e-4 noiseSources = [] for index in range(order): if noiseVariance[index] > 0: vector = np.zeros(order) vector[index] = 1 noiseSources.append({ "std": np.sqrt(noiseVariance[index]), "steeringVector": vector, "name": "Noise Source %s" % index }) options = {'noise': noiseSources} sim = simulator.Simulator(sys, ctrl, options=options) t = np.linspace(0., 99., size) res = sim.simulate(t, [inp]) plt.figure() plt.plot(res['t'], res['output']) plt.legend(["%s" % x for x in range(order)]) recon = reconstruction.WienerFilter(t, sys, (inp, )) recon_with_noise = reconstruction.WienerFilter(t, sys, [inp], options=options) recon_with_noise_Parallel = reconstruction.ParallelWienerFilter( t, sys, [inp], options=options) u_hat, log = recon.filter(ctrl) u_hat_with_noise, log_with_noise = recon_with_noise.filter(ctrl) u_hat_with_noise_Parallel = recon_with_noise_Parallel.filter(ctrl) plt.figure() plt.plot(t, inp.scalarFunction(t), label="u") plt.plot(t, u_hat, label="u_hat") plt.plot(t, u_hat_with_noise, label="u_hat_with_noise") plt.plot(t, u_hat_with_noise_Parallel, label="u_hat_with_noise_Parallel") plt.legend()
def piBlockSystem1(): start_time = time.time() size = 20000 # Number of samples in the simulation M = (1 << 0) # Number of parallel controlnverters N = 2 # Number of PI mixing submatrices Ts = 8e-5 # Sampling period num_inputs = 1 t = np.linspace(0, (size - 1) * Ts, size) # Time grid for control updates beta = 6250 kappa = 1 stability = Ts * beta * (1 / np.sqrt(M) + kappa) <= 1 print("Stability margin: {}".format(1. - Ts * beta * (1 / np.sqrt(M) + kappa))) print("Stability criterion: {}".format(stability)) H = hadamardMatrix(M) L = 1 A = np.zeros(((N + 1) * M, (N + 1) * M)) MixingPi = np.empty((N, M, M)) for k in range(N): MixingPi[k] = beta * np.outer(H[:, 0], H[:, 0]) # (beta)*(0.2*np.outer(H[:,0],H[:,0]) # + 0.1*np.outer(H[:,1],H[:,1]) # + 0.3*np.outer(H[:,2],H[:,2]) # + 0.4*np.outer(H[:,3],H[:,3])) # Index set = {0,0} A[(k + 1) * M:(k + 2) * M, (k) * M:(k + 1) * M] = MixingPi[k] nperseg = (1 << 16) selected_FFT_bin = 250. input_signals = [] frequencies = [] # sins = np.empty((M,size)) for i in range(num_inputs): amplitude = 1 frequency = (i + 1) * (selected_FFT_bin / (nperseg * Ts)) print("{} Hz".format(frequency)) # size = frequencies.append(frequency) phase = 0 vector = np.zeros((N + 1) * M) vector[0:M] = beta * (H[:, i]) input_signals.append( system.Sin(Ts, amplitude=amplitude, frequency=frequency, phase=phase, steeringVector=vector)) input_signals = tuple(input_signals) print("A = \n%s\nb = \n%s" % (A, vector)) checkCovarianceMatrixConvergence(A, vector) checkCovarianceMatrixConvergence(-A, vector) c = np.eye((N + 1) * M) sys = system.System(A, c) mixingMatrix = -kappa * beta * np.eye((N + 1) * M) ctrl = system.Control(mixingMatrix, size) sim = simulator.Simulator(sys, ctrl, options={ 'stateBound': (Ts * beta * kappa) / (1. - Ts * beta) + 1., 'noise': [{ 'std': 1e-6, 'steeringVector': beta * np.eye((N + 1) * M)[:, i], 'name': 'Bastard' } for i in range((N + 1) * M)] }) res = sim.simulate(t, input_signals) # plt.figure() # plt.plot(res['t'], res['output']) # plt.legend(["%s" % x for x in range(res['output'].shape[0])]) # plt.show() eta2 = np.ones((N + 1) * M) * 1e5 options = { 'eta2': eta2, 'sigmaU2': [1.], 'noise': [{ 'std': 1e-6, 'steeringVector': beta * np.eye((N + 1) * M)[:, i], 'name': 'Bastard' } for i in range((N + 1) * M)] } recon = reconstruction.WienerFilter(t, sys, input_signals, options) input_estimates, recon_log = recon.filter(ctrl) print("Run Time: {} seconds".format(time.time() - start_time)) nfft = (1 << 16) spectrums = np.empty((num_inputs, nfft // 2 + 1)) for i in range(num_inputs): freq, spec = signal.welch(input_estimates[:, i], 1. / Ts, axis=0, nperseg=nperseg, nfft=nfft, scaling='density') spectrums[i, :] = spec plt.figure() [ plt.semilogx(freq, 10 * np.log10(np.abs(spec)), label="") for spec in spectrums ] plt.grid() plt.title("Block diagonal Pi System")
def test_evaluate_PlotTransferFunctions_For_PostFiltering(): size = 10000 order = 2 postFilterOrder = 2 Ts = 0.1 eta2 = 1e-6 filterEta2 = 1e-0 amplitude = 1. frequency = 1e-1 phase = np.pi * 7. / 8. vector = np.zeros(order) vector[0] = 1. inp = system.Sin(Ts, amplitude=amplitude, frequency=frequency, phase=phase, steeringVector=vector) # coef = np.random.rand(size) * 2. - 1. # vector = np.zeros(order) # vector[0] = 2. # inp = system.FirstOrderHold(Ts, coefficients=coef, steeringVector=vector) A = 2 * np.eye(order, k=-1, dtype=np.float) # make causal filter A += 0. * np.eye(order, k=0) c = np.eye(order, dtype=np.float) sys = system.System(A, c) mixingMatrix = - 1e1 * np.eye(order) ctrl = system.Control(mixingMatrix, size) sim = simulator.Simulator(sys, ctrl) t = np.linspace(0., 99., size) res = sim.simulate(t, (inp,)) plt.figure() plt.plot(res['t'], res['output']) plt.legend(["%s" % x for x in range(order)]) # System 1 recon = reconstruction.WienerFilter(t, sys, (inp,), {"eta2":eta2*np.ones(order)}) u_hat, log = recon.filter(ctrl) ev = evaluation.Evaluation(sys, u_hat, (inp,)) # Post Filtering bandwith = 2 * np.pi * 1e-1 print("Bandwith = %s" % bandwith) postFilterTF = filters.TransferFunction() postFilterTF.butterWorth(postFilterOrder, (bandwith)) postFilterElliptic = filters.TransferFunction() postFilterElliptic.iirFilter(postFilterOrder, (bandwith,), 'ellip') postFilterCheby1 = filters.TransferFunction() postFilterCheby1.iirFilter(postFilterOrder, (bandwith,), 'cheby1') postFilterCheby2 = filters.TransferFunction() postFilterCheby2.iirFilter(postFilterOrder, (bandwith,), 'cheby2') postFilterBessel = filters.TransferFunction() postFilterBessel.iirFilter(postFilterOrder, (bandwith,), 'bessel') plt.figure() w1, h1 = postFilterTF.frequencyResponse() w2, h2 = postFilterElliptic.frequencyResponse() w3, h3 = postFilterCheby1.frequencyResponse() w4, h4 = postFilterCheby2.frequencyResponse() w5, h5 = postFilterBessel.frequencyResponse() plt.semilogx(w1/np.pi/2., 20 * np.log10(abs(h1)), label="Butterworth") plt.semilogx(w2/np.pi/2., 20 * np.log10(abs(h2)), label="Elliptic") plt.semilogx(w3/np.pi/2., 20 * np.log10(abs(h3)), label="Cheby 1") plt.semilogx(w4/np.pi/2., 20 * np.log10(abs(h4)), label="Cheby 2") plt.semilogx(w5/np.pi/2., 20 * np.log10(abs(h5)), label="Bessel") plt.legend() plt.xlabel('Frequency [Hz]') plt.ylabel('Amplitude response [dB]') plt.grid() # plt.show() # print(postFilterTF.a, postFilterTF.b) postFilter1 = filters.Filter() postFilter2 = filters.Filter() postFilter3 = filters.Filter() postFilter4 = filters.Filter() postFilter5 = filters.Filter() postFilter1.tf2lssObservableForm(postFilterTF.b, postFilterTF.a) postFilter2.tf2lssObservableForm(postFilterElliptic.b, postFilterElliptic.a) postFilter3.tf2lssObservableForm(postFilterCheby1.b, postFilterCheby1.a) postFilter4.tf2lssObservableForm(postFilterCheby2.b, postFilterCheby2.a) postFilter5.tf2lssObservableForm(postFilterBessel.b, postFilterBessel.a) # eta2PostFilter = np.concatenate((eta2 * np.ones(order), filterEta2 * np.ones(postFilter.c.shape[1]))) eta2PostFilter = eta2 * np.ones(order) reconstructionFiltered1 = reconstruction.WienerFilterWithPostFiltering(t, sys, (inp,), postFilter1, {"eta2":eta2PostFilter}) reconstructionFiltered2 = reconstruction.WienerFilterWithPostFiltering(t, sys, (inp,), postFilter2, {"eta2":eta2PostFilter}) reconstructionFiltered3 = reconstruction.WienerFilterWithPostFiltering(t, sys, (inp,), postFilter3, {"eta2":eta2PostFilter}) reconstructionFiltered4 = reconstruction.WienerFilterWithPostFiltering(t, sys, (inp,), postFilter4, {"eta2":eta2PostFilter}) reconstructionFiltered5 = reconstruction.WienerFilterWithPostFiltering(t, sys, (inp,), postFilter5, {"eta2":eta2PostFilter}) print(ctrl.mixingMatrix) u_hatP_1, log_1 = reconstructionFiltered1.filter(ctrl) print(ctrl.mixingMatrix) print(postFilter2) u_hatP_2, log_2 = reconstructionFiltered2.filter(ctrl) u_hatP_3, log_3 = reconstructionFiltered3.filter(ctrl) u_hatP_4, log_4 = reconstructionFiltered4.filter(ctrl) u_hatP_5, log_5 = reconstructionFiltered5.filter(ctrl) evP1 = evaluation.Evaluation(sys, u_hatP_1, (inp,)) evP2 = evaluation.Evaluation(sys, u_hatP_2, (inp,)) evP3 = evaluation.Evaluation(sys, u_hatP_3, (inp,)) evP4 = evaluation.Evaluation(sys, u_hatP_4, (inp,)) evP5 = evaluation.Evaluation(sys, u_hatP_5, (inp,)) freqsLim = [1e-2, 1e2] # figure1 = ev.PlotTransferFunctions(freqsLim) figure2 = ev.PlotPowerSpectralDensity(t) # figure3 = ev2.PlotTransferFunctions(freqsLim) figure4 = evP1.PlotPowerSpectralDensity(t) figure5 = evP2.PlotPowerSpectralDensity(t) figure6 = evP3.PlotPowerSpectralDensity(t) figure7 = evP4.PlotPowerSpectralDensity(t) figure8 = evP5.PlotPowerSpectralDensity(t) plt.figure() plt.plot(u_hat, label="u_hat") # plt.plot(u_hatP_1, label="Butter") # plt.plot(u_hatP_2, label="Elliptic") plt.plot(u_hatP_3, label="Chebyshev 1") # plt.plot(u_hatP_4, label="Chebychev 2") plt.plot(u_hatP_5, label="Bessel") # plt.plot(u_hat - u_hat2, label="diff") plt.legend()
def test_evaluate_WithNoise(): size = 10000 order = 5 Ts = 0.0001 eta2 = 1e-4 beta = 1000. noiseVariance = np.ones(order) * 1e-12 noiseSources = [] for index in range(order): if noiseVariance[index]>0: vector = np.zeros(order) vector[index] = beta noiseSources.append( { "std": np.sqrt(noiseVariance[index]), "steeringVector": vector, "name": "Noise Source %s" % index } ) options = { 'noise': noiseSources, 'eta2': eta2 * np.ones(order) } # options = {} # options2 = { # # 'noise': {"standardDeviation": np.sqrt(noiseVariance) * np.array([1./(order - x)**3 for x in range(order)])}, # 'noise': {"standardDeviation": 1e-4 * np.array([1. for x in range(order)])}, # 'eta2': eta2 * np.ones(order) # } # options['noise']['standardDeviation'][5] = 1e-1 amplitude = 1. * 1e-6 frequency = 1e2 / (2. * np.pi) phase = np.pi * 7. / 8. vector = np.ones(order) * beta / 2. # vector = np.zeros(order) vector[0] = beta inp = system.Sin(Ts, amplitude=amplitude, frequency=frequency, phase=phase, steeringVector=vector) # coef = np.random.rand(size) * 2. - 1. # vector = np.zeros(order) # vector[0] = beta # inp = system.FirstOrderHold(Ts, coefficients=coef, steeringVector=vector) # T = 120 # t = 10 ** (T/10.) # rho = np.power(t, 1./order)/beta * np.sqrt(2) rho = 0. A = beta/2. * np.eye(order, k=-1) - rho * np.eye(order, k=0) # A[0, :] =-np.ones(order) * beta/2. print(A) # A = 1e-2 * np.eye(order, k=-1) - rho * np.eye(order, k=0) # A = np.zeros((order, order)) # A = np.random.randn(order, order) # A = np.dot(A, np.linalg.inv(np.diag(np.sum(np.abs(A), axis=1)))) # print(A) # A = 9. * np.eye(order, k=-1, dtype=np.float) # make causal filter # A += 0. * np.eye(order, k=0) c0 = np.zeros(order, dtype=np.float).reshape((order,1)) c0[-1] = 1. c = np.eye(order, dtype=np.float) sys0 = system.System(A, c0) sys = system.System(A, c) mixingMatrix = - 10.5 * np.eye(order) ctrl = system.Control(mixingMatrix, size) ctrl0 = system.Control(mixingMatrix, size) sim0 = simulator.Simulator(sys0, ctrl0, options=options) sim = simulator.Simulator(sys, ctrl, options=options) t = np.linspace(0., Ts * (size - 1) , size) u = inp.scalarFunction(t) # res2 = sim0.simulate(t, (inp,)) res = sim.simulate(t, (inp,)) plt.figure() plt.plot(res['t'], res['output']) plt.legend(["%s" % x for x in range(order)]) # System 1 reconSISO = reconstruction.WienerFilter(t, sys0, (inp,), {"eta2":np.array(eta2)}) reconSIMO = reconstruction.WienerFilter(t, sys, (inp,), {"eta2":eta2 * np.ones(order)}) reconMIMO = reconstruction.WienerFilter(t, sys, [inp], options) u_hatSISO, log_SISO = reconSISO.filter(ctrl) u_hatSIMO, log_SIMO = reconSIMO.filter(ctrl) u_hatMIMO, log_MIMO = reconMIMO.filter(ctrl) print(reconSISO) ev_SISO = evaluation.Evaluation(sys, u_hatSISO, (inp,)) ev_SIMO = evaluation.Evaluation(sys, u_hatSIMO, (inp,)) ev_MIMO = evaluation.Evaluation(sys, u_hatMIMO, (inp,)) freqsLim = [1e-2, 1e2] freq, SISOSPECTRUM, SIGNALSPECTRUM = ev_SISO.PowerSpectralDensity(t) _, SIMOSPECTRUM, _ = ev_SIMO.PowerSpectralDensity(t) _, MIMOSPECTRUM, _ = ev_MIMO.PowerSpectralDensity(t) plt.figure() plt.semilogx(freq, 10 * np.log10(np.abs(SIGNALSPECTRUM[0].flatten())), label="u_hatSISO") plt.semilogx(freq, 10 * np.log10(np.abs(SISOSPECTRUM.flatten())), label="u_hatSISO") plt.semilogx(freq, 10 * np.log10(np.abs(SIMOSPECTRUM.flatten())), label="u_hatSIMO") plt.semilogx(freq, 10 * np.log10(np.abs(MIMOSPECTRUM[:, 0].flatten())), label="u_hatMIMO") plt.legend() plt.figure() plt.plot(u, label="u") plt.plot(u_hatSISO, label="u_hatSISO") plt.plot(u_hatSIMO, label="u_hatSIMO") plt.plot(u_hatMIMO, label="u_hatMIMO") plt.legend() plt.figure() plt.plot(u_hatSISO.flatten() - u.flatten(), label="u_hatSISO") plt.plot(u_hatSIMO.flatten() - u.flatten(), label="u_hatSIMO") plt.plot(u_hatMIMO[:,0] - u.flatten(), label="u_hatMIMO") plt.legend() plt.figure() freq, u_hatSISOSP = signal.welch(u_hatSISO.flatten() - u.flatten(), 1./Ts) _, u_hatSIMOSP = signal.welch(u_hatSIMO.flatten() - u.flatten(), 1./Ts) _, u_hatMIMOSP = signal.welch(u_hatMIMO[:,0] - u.flatten(), 1./Ts) plt.semilogx(freq, 10 * np.log10(np.abs(u_hatSISOSP)), label="u_hatSISO") plt.semilogx(freq, 10 * np.log10(np.abs(u_hatSIMOSP)), label="u_hatSIMO") plt.semilogx(freq, 10 * np.log10(np.abs(u_hatMIMOSP)), label="u_hatMIMO") plt.legend() figure1 = ev_SISO.PlotTransferFunctions(freqsLim)
res = sim.simulate(t, (input_signal, )) reconstructionOptions = { 'eta2': eta2, 'sigmaU2': sigmaU2, 'noise': [{ 'std': sigma2_reconst, 'steeringVector': beta * np.eye(order)[:, i], 'name': f'Bastard_{i}' } for i in range(order)] } print(f'Reconstructing using: {RECONSTRUCTION_METHOD}') recon = reconstruction.WienerFilter(t, sys, tuple(all_inputs), reconstructionOptions) input_estimates, _ = recon.filter(ctrl) snrVsAmplitude = evaluation.SNRvsAmplitude( system=sys, estimates=[input_estimates[:, 0]], OSR=osr) freq, spec = snrVsAmplitude.estimates[0][ 'performance'].freq, snrVsAmplitude.estimates[0][ 'performance'].spec snrVsAmplitude.ToTextFile( data_dir / f'{RECONSTRUCTION_METHOD}_{sigma2_jitter}_SNR.csv', delimiter=' ') f = lambda x: 10 * np.log10(x) df = pd.DataFrame({'freq': freq, 'spec': spec}) fIndex = df.idxmax().spec df = df.apply(f)