From 727c3d93641ecf2d4c28ce56cd8ba28db4ab0e7c Mon Sep 17 00:00:00 2001 From: Silas Oettinghaus Date: Fri, 25 Apr 2025 10:31:43 +0200 Subject: [PATCH] auswertungsfiles und algos for ECOC 2025 rush... --- Classes/00_signals/Signal.m | 2 +- Classes/04_DSP/Equalizer/FFE_DCremoval.m | 19 +- .../Equalizer/FFE_DCremoval_adaptive_mu.m | 272 ++++++++++++++++++ .../04_DSP/Equalizer/FFE_DCremoval_level.m | 240 ++++++++++++++++ Classes/DataBaseHandler/DBHandler.m | 2 +- Functions/EQ_structures/vnle.m | 269 ++++++++++------- .../EQ_structures/vnle_postfilter_mlse.m | 7 +- Functions/EQ_visuals/showLevelScatter.m | 10 +- Functions/Metrics/count_error_bursts.m | 29 ++ projects/ECOC_2025/dsp_loop_id.m | 63 ++++ projects/ECOC_2025/dsp_run_id.m | 63 ++-- projects/ECOC_2025/dsp_standalone.m | 92 +++++- .../ECOC_2025/dsp_test/hyperparam_tuning.m | 58 ++++ projects/ECOC_2025/load_signal_standalone.m | 66 +++-- .../plots_from_database/plot_mpi_trial.m | 173 +++++++---- projects/ECOC_2025/submit_dsp.m | 7 +- .../auswertung MPI/dsp_mpi_database.m | 11 +- .../auswertung MPI/dsp_run_id.m | 2 +- 18 files changed, 1152 insertions(+), 233 deletions(-) create mode 100644 Classes/04_DSP/Equalizer/FFE_DCremoval_adaptive_mu.m create mode 100644 Classes/04_DSP/Equalizer/FFE_DCremoval_level.m create mode 100644 Functions/Metrics/count_error_bursts.m create mode 100644 projects/ECOC_2025/dsp_loop_id.m create mode 100644 projects/ECOC_2025/dsp_test/hyperparam_tuning.m diff --git a/Classes/00_signals/Signal.m b/Classes/00_signals/Signal.m index ff6e05b..dd4cf9e 100644 --- a/Classes/00_signals/Signal.m +++ b/Classes/00_signals/Signal.m @@ -141,7 +141,7 @@ classdef Signal arguments obj - options.fignum + options.fignum = [] options.displayname = []; options.timeframe = 0; options.clear = 0; diff --git a/Classes/04_DSP/Equalizer/FFE_DCremoval.m b/Classes/04_DSP/Equalizer/FFE_DCremoval.m index dafe65c..06d50c6 100644 --- a/Classes/04_DSP/Equalizer/FFE_DCremoval.m +++ b/Classes/04_DSP/Equalizer/FFE_DCremoval.m @@ -57,6 +57,8 @@ classdef FFE_DCremoval < handle obj.e = zeros(obj.order,1); obj.error = 0; + obj.dc_buffer_len = floor(obj.dc_buffer_len); + end function [X,Noi] = process(obj, X, D) @@ -155,16 +157,15 @@ classdef FFE_DCremoval < handle end end - if ~training - figure(1122) - hold on - scatter(1:numel(e_dc_save),e_dc_save,1,'.'); - scatter(1:numel(y),y,1,'.'); - - end + % if ~training + % figure(1122) + % hold on + % scatter(1:numel(e_dc_save),e_dc_save,1,'.'); + % % scatter(1:numel(y),y,1,'.'); + % + % end end end -end - +end \ No newline at end of file diff --git a/Classes/04_DSP/Equalizer/FFE_DCremoval_adaptive_mu.m b/Classes/04_DSP/Equalizer/FFE_DCremoval_adaptive_mu.m new file mode 100644 index 0000000..c6b1a43 --- /dev/null +++ b/Classes/04_DSP/Equalizer/FFE_DCremoval_adaptive_mu.m @@ -0,0 +1,272 @@ +classdef FFE_DCremoval_adaptive_mu < handle + % Implementation of plain and simple FFE. + % 1) Training mode (stable performance when you use NLMS) + % 2) Decision directed mode + + % Eq = FFE("epochs_tr",5,"epochs_dd",5,"len_tr",4096*2,"mu_dd",1e-4,"mu_tr",0,"order",25,"sps",2,"decide",0); + + properties + sps % usually 2 + order + e + error + + len_tr + mu_tr + epochs_tr + + mu_dd + epochs_dd + + mu_dc + dc_buffer_len + + ffe_buffer_len + + smoothing_buffer_length + smoothing_buffer_update + + constellation + + decide + end + + methods + function obj = FFE_DCremoval_adaptive_mu(options) + arguments(Input) + + options.sps = 2; + options.order = 15; + + options.len_tr = 4096; + options.mu_tr = 0; + options.epochs_tr = 5; + + options.mu_dd = 1e-5; + options.epochs_dd = 5; + + options.mu_dc = 0.05; + options.dc_buffer_len = 1; + + options.ffe_buffer_len = 1; + + options.smoothing_buffer_length = 0; + options.smoothing_buffer_update = 0; + options.decide = false; + + end + + assert(options.dc_buffer_len>0); + + fn = fieldnames(options); + for n = 1:numel(fn) + obj.(fn{n}) = options.(fn{n}); + end + + obj.e = zeros(obj.order,1); + obj.error = 0; + + obj.dc_buffer_len = floor(obj.dc_buffer_len); + + end + + function [X,Noi] = process(obj, X, D) + + % actual processing of the signal (steps 1. - 3.) + % 1 normalize RMS + X = X.normalize("mode","rms"); + + obj.constellation = unique(D.signal); + + % if obj.smoothing_buffer_length > 0 + % % Apply A1 filter smoothing + % % Calculate the moving sum with the window size N1 + % moving_sum = movsum(X.signal, [obj.smoothing_buffer_length,0]); + % + % % Initialize the output smoothed signal + % X.signal = X.signal - (1 / obj.smoothing_buffer_length) * moving_sum; + % end + + % Training Mode + training = 1; + obj.equalize(X.signal, D.signal,obj.mu_tr,obj.epochs_tr,obj.len_tr,training); + + % Decision Directed Mode + N = X.length; + training = 0; + [signal,decision]=obj.equalize(X.signal, D.signal,obj.mu_dd,obj.epochs_dd,N,training); + + % Output Signal + if obj.decide + X.signal = decision; + else + X.signal = signal; + end + X.fs = D.fs; %change sampling frequency of outgoing signal from fdac e.g. 2 sps to symbol spaced = fsym + lbdesc = [num2str(obj.order),' tap FFE']; + X = X.logbookentry(lbdesc); % append to logbook + + Noi = X - D; + + end + + function [y,d_hat] = equalize(obj, x, d, mu_lms, epochs, N, training) + % Equalize with adaptive DC-removal, VSS, and parallel-buffered DC updates + % Added: FFE gradient buffering in DD mode (error buffer) with update every obj.dc_buffer_len symbols + + arguments + obj + x + d + mu_lms % LMS step-size (or 0 for NLMS) + epochs % number of training/DD epochs + N % number of samples to process + training % boolean flag: true->training mode, false->DD mode + end + + % Zero-padding for filter memory + x = [zeros(floor(obj.order/2),1); x; zeros(obj.order,1)]; + + % Initialize storage + numSymbols = ceil(N/obj.sps); + y = zeros(numSymbols,1); + d_hat = zeros(numSymbols,1); + err = NaN(numSymbols,numel(obj.constellation)); + e_dc_save= zeros(numSymbols,1); + + % DC-adaptation parameters + P_err = 0; % running error power + alpha = 0.98; % forgetting factor for error power + err_prev = 0; % previous error sample for VSS correlation + gamma_dc = 1e-6; % meta step-size for DC VSS + mu_min = 1e-6; % lower bound for mu_dc + mu_max = 1e-1; % upper bound for mu_dc + + % DC removal buffer + L = obj.dc_buffer_len; % buffer length + e_dc_buf = NaN(L,1); + e_dc_est = 0; + + % FFE gradient buffer (DD mode only) + L_grad = obj.ffe_buffer_len; % buffer length + if ~training + % each column holds one past gradient of length obj.order + grad_buf = NaN(obj.order, L_grad); + + end + + smth_buffer = zeros(1, obj.smoothing_buffer_length); + smth_mean = 0; + % Main loop + for epoch = 1:epochs + s = 0; + for sample = 1:obj.sps:N + s = s + 1; + + if obj.smoothing_buffer_length > 0 + smth_buffer = circshift(smth_buffer,1,2); + smth_buffer(1) = x(sample); + if mod(s, obj.smoothing_buffer_update) == 0 + smth_mean = mean(smth_buffer); + end + x(sample:sample+obj.sps-1) = x(sample:sample+obj.sps-1)-smth_mean; + end + + U = x(obj.order+sample-1:-1:sample); + + %-- 1) filter output with DC correction + y(s) = e_dc_est + obj.e.'*U; + + %-- 2) decision + if training + [~, idx] = min(abs(d(s) - obj.constellation)); + else + [~, idx] = min(abs(y(s) - obj.constellation)); + end + d_hat(s) = obj.constellation(idx); + + %-- 3) error + e_val = y(s) - d_hat(s); + err(s,idx) = e_val; + + %-- 4) tap-weight update: training immediate, DD buffered + if training + % immediate update (LMS or NLMS) + if mu_lms ~= 0 + obj.e = obj.e - mu_lms * e_val * U; + else + normU = (U.'*U) + eps; + obj.e = obj.e - e_val * U / normU; + end + else + if 1 + % buffer gradient + if mu_lms ~= 0 + grad = e_val * U; + else + normU = (U.'*U) + eps; + grad = e_val * U / normU; + end + % shift and insert + grad_buf = circshift(grad_buf, 1, 2); + grad_buf(:,1) = grad; + % update once every L symbols + if mod(s, L_grad) == 0 + avg_grad = mean(grad_buf, 2, 'omitnan'); + if mu_lms ~= 0 + obj.e = obj.e - mu_lms * avg_grad; + else + obj.e = obj.e - avg_grad; + end + end + end + end + + + %-- 5) DC adaptation + if obj.mu_dc ~= 0 + + % VSS for mu_dc + delta_mu = gamma_dc * e_val * err_prev * (U.'*U); + obj.mu_dc = min(max(obj.mu_dc + delta_mu, mu_min), mu_max); + err_prev = e_val; + + % DC buffer update & periodic estimate + P_err = alpha*P_err + (1-alpha)*e_val^2; + mu_dc_norm = obj.mu_dc / (P_err + eps); + e_dc_buf = circshift(e_dc_buf, 1); + e_dc_buf(1) = e_dc_est - mu_dc_norm * e_val; + + if mod(s, L) == 0 + e_dc_est = median(e_dc_buf, 'omitnan'); + end + + e_dc_save(s) = e_dc_est; + end + + % store instantaneous squared error + obj.error(epoch, s) = e_val^2; + end + end + + % Optional plotting in DD mode (uncomment if needed) + if ~training + figure(342);clf + hold on + scatter(1:numSymbols, err + obj.constellation', '.', 'SizeData', 1); + + yline(obj.constellation); + + end + end + + + function mu = update_mu() + + + + end + + end +end + diff --git a/Classes/04_DSP/Equalizer/FFE_DCremoval_level.m b/Classes/04_DSP/Equalizer/FFE_DCremoval_level.m new file mode 100644 index 0000000..3539d2c --- /dev/null +++ b/Classes/04_DSP/Equalizer/FFE_DCremoval_level.m @@ -0,0 +1,240 @@ +classdef FFE_DCremoval_level < handle + % Implementation of plain and simple FFE. + % 1) Training mode (stable performance when you use NLMS) + % 2) Decision directed mode + + % Eq = FFE("epochs_tr",5,"epochs_dd",5,"len_tr",4096*2,"mu_dd",1e-4,"mu_tr",0,"order",25,"sps",2,"decide",0); + + properties + sps % usually 2 + order + e + error + + len_tr + mu_tr + epochs_tr + + mu_dd + epochs_dd + + mu_dc + dc_buffer_len + + constellation + + decide + + KF_meas_noise = 0; + KF_process_noise = 0; + KF_state_cov = 0; + end + + methods + function obj = FFE_DCremoval_level(options) + arguments(Input) + + options.sps = 2; + options.order = 15; + + options.len_tr = 4096; + options.mu_tr = 0; + options.epochs_tr = 5; + + options.mu_dd = 1e-5; + options.epochs_dd = 5; + + options.mu_dc = 0.05; + options.dc_buffer_len = 1; + + options.decide = false; + + end + + assert(options.dc_buffer_len>0); + + fn = fieldnames(options); + for n = 1:numel(fn) + obj.(fn{n}) = options.(fn{n}); + end + + obj.e = zeros(obj.order,1); + obj.error = 0; + + obj.dc_buffer_len = floor(obj.dc_buffer_len); + + end + + function [X,Noi] = process(obj, X, D) + + % actual processing of the signal (steps 1. - 3.) + % 1 normalize RMS + X = X.normalize("mode","rms"); + + obj.constellation = unique(D.signal); + + % Training Mode + training = 1; + obj.equalize(X.signal, D.signal,obj.mu_tr,obj.epochs_tr,obj.len_tr,training); + + % Decision Directed Mode + N = X.length; + training = 0; + [signal,decision]=obj.equalize(X.signal, D.signal,obj.mu_dd,obj.epochs_dd,N,training); + + % Output Signal + if obj.decide + X.signal = decision; + else + X.signal = signal; + end + X.fs = D.fs; %change sampling frequency of outgoing signal from fdac e.g. 2 sps to symbol spaced = fsym + lbdesc = [num2str(obj.order),' tap FFE']; + X = X.logbookentry(lbdesc); % append to logbook + + Noi = X - D; + + end + function [y, d_hat, logs] = equalize(obj, x, d, mu_lms, epochs, N, training) + % Equalize with Kalman-based DC removal; training epochs estimate KF noise parameters + + arguments + obj + x + d + mu_lms % LMS step-size (or 0 for NLMS) + epochs % number of training or DD epochs + N % number of samples to process + training % true => training mode (tap-training + noise estimation) + end + + % Zero-pad for filter memory + x = [zeros(floor(obj.order/2),1); x; zeros(obj.order,1)]; + numSym = ceil(N/obj.sps); + + % Pre-allocate outputs + y = zeros(numSym,1); + d_hat = zeros(numSym,1); + + % --- Training: estimate noise stats and train taps --- + if training + % Pre-allocate error accumulator + totalTrain = epochs * numSym; + trainErrs = zeros(totalTrain,1); + te_idx = 0; + + for ep = 1:epochs + s = 0; + for n = 1:obj.sps:N + s = s + 1; + U = x(obj.order + n - 1 : -1 : n); + + % Equalizer output (no DC correction yet) + y(s) = obj.e.' * U; + + % Decision based on known symbol + [~, idx] = min(abs(d(s) - obj.constellation)); + d_hat(s) = obj.constellation(idx); + + % Instantaneous error + e_n = y(s) - d_hat(s); + + % Collect error for noise estimation + te_idx = te_idx + 1; + trainErrs(te_idx) = e_n; + + % Tap-weight update (LMS or NLMS) + if mu_lms ~= 0 + obj.e = obj.e - mu_lms * e_n * U; + else + normU = (U.'*U) + eps; + obj.e = obj.e - e_n * U / normU; + end + end + end + + % Estimate measurement noise R and process noise Q + R_est = var(trainErrs(1:te_idx)); + Q_est = 1e-3 * R_est; % Q/R ratio = 1e-3 (tune as needed) + + % Store into object for DD pass + obj.KF_meas_noise = R_est; + obj.KF_process_noise = Q_est; + obj.KF_state_cov = 5*R_est; % or 5*R_est for a more “eager” start + + % No Kalman in training; return + logs = struct(); + return; + end + + % --- Decision-Directed with Kalman DC tracking --- + % Initialize Kalman state + x_est = 0; + P = obj.KF_state_cov; % initial P (tune in obj; e.g. 1) + + % Logging containers + logs.y_raw = zeros(numSym,1); + logs.y_corr = zeros(numSym,1); + logs.err = zeros(numSym,1); + logs.K_gain = zeros(numSym,1); + logs.x_est = zeros(numSym,1); + logs.P = zeros(numSym,1); + logs.normU = zeros(numSym,1); + logs.tap_norm = zeros(numSym,1); + + for ep = 1:epochs + s = 0; + for n = 1:obj.sps:N + s = s + 1; + U = x(obj.order + n - 1 : -1 : n); + + % 1) Kalman prediction + P = P + obj.KF_process_noise; + x_prior = x_est; + + % 2) raw equalizer output + y_raw = obj.e.' * U; + logs.y_raw(s) = y_raw; + + % 3) DC-corrected output + y_corr = y_raw + x_prior; + y(s) = y_corr; + logs.y_corr(s) = y_corr; + + % 4) decision-directed symbol + [~, idx] = min(abs(y_corr - obj.constellation)); + d_hat(s) = obj.constellation(idx); + + % 5) error + e_n = y_corr - d_hat(s); + logs.err(s) = e_n; + + % 6) tap-weight update (LMS/NLMS) + if mu_lms ~= 0 + obj.e = obj.e - mu_lms * e_n * U; + else + normU = U.' * U + eps; + logs.normU(s) = normU; + obj.e = obj.e - e_n * U / normU; + end + + logs.tap_norm(s) = norm(obj.e); + + % 7) Kalman update + K_gain = P / (P + obj.KF_meas_noise); + x_est = x_prior + K_gain * (e_n - x_prior); + P = (1 - K_gain) * P; + + % 8) log Kalman state + logs.K_gain(s) = K_gain; + logs.x_est(s) = x_est; + logs.P(s) = P; + end + end + end + + + + end +end + diff --git a/Classes/DataBaseHandler/DBHandler.m b/Classes/DataBaseHandler/DBHandler.m index 5e8333e..6a77aec 100644 --- a/Classes/DataBaseHandler/DBHandler.m +++ b/Classes/DataBaseHandler/DBHandler.m @@ -70,7 +70,7 @@ classdef DBHandler < handle % Get table names and the first rows of each table to understand the structure obj.getTableNames(); obj.getTables(); - obj.getDistinctValues(); + % obj.getDistinctValues(); end function obj = getTableNames(obj) diff --git a/Functions/EQ_structures/vnle.m b/Functions/EQ_structures/vnle.m index 1447351..f143452 100644 --- a/Functions/EQ_structures/vnle.m +++ b/Functions/EQ_structures/vnle.m @@ -1,129 +1,192 @@ function [eq_package] = vnle(eq_,M,rx_signal,tx_symbols,tx_bits,options) - %VNLE Apply an equalization algorithm to the received signal and calculate BER - % This function takes an equalizer object, a received signal, and the - % transmitted symbols to apply equalization, map the received signal back to bits, - % and compute the bit error rate (BER). - % - % Inputs: - % EQ - Equalizer object that provides the equalization method - % rx_signal - Received signal that needs to be equalized - % tx_symbols - Transmitted symbols used as a reference for BER calculation - % - % Outputs: - % eq_signal - Equalized version of the received signal - % ber - Bit error rate after equalization - % numErrors - Number of bit errors detected - arguments - eq_ - M - rx_signal - tx_symbols - tx_bits - options.precode_mode db_mode - options.showAnalysis = 0 - options.eth_style = 0; - options.postFFE = []; - end +arguments + eq_ + M + rx_signal + tx_symbols + tx_bits + options.precode_mode db_mode + options.showAnalysis = 0; + options.eth_style_symbol_mapping = 0; + options.postFFE = []; + options.database = []; +end - %FFE or VNLE - if length(rx_signal)/2 == length(tx_symbols)+0.5 - rx_signal.signal = rx_signal.signal(1:end-1); - elseif length(rx_signal)/2 == length(tx_symbols)-1 - end - [eq_signal_sd,eq_noise] = eq_.process(rx_signal,tx_symbols); +mudc_given = eq_.mu_dc; - if ~isempty(options.postFFE) - [eq_signal_sd,eq_noise] = options.postFFE.process(eq_signal_sd,tx_symbols); - end +%FFE or VNLE +[eq_signal_sd,eq_noise] = eq_.process(rx_signal,tx_symbols); - eq_signal_hd = PAMmapper(M,0).quantize(eq_signal_sd); +if ~isempty(options.postFFE) + tic + [eq_signal_sd,eq_noise] = options.postFFE.process(eq_signal_sd,tx_symbols); + toc +end - % precoding to mitigate error propagation, most prominently used in - % combination with duobinary signaling to avoid catastrophic error - % behavior (see J.W.M. Bergmans, Digital Baseband Transmission and Recording -> partial response signaling) +eq_signal_hd = PAMmapper(M,0).quantize(eq_signal_sd); - % takes: - % -> eq_signal_hd: hard decision signal after eq - % -> tx_symbols: that where used as reference for eq +% precoding to mitigate error propagation, most prominently used in +% combination with duobinary signaling to avoid catastrophic error +% behavior (see J.W.M. Bergmans, Digital Baseband Transmission and Recording -> partial response signaling) - switch options.precode_mode - case db_mode.db_emulate - % re - eq_signal_hd = Duobinary().encode(eq_signal_hd,"M",M); - eq_signal_hd = Duobinary().decode(eq_signal_hd,"M",M); +switch options.precode_mode + + case db_mode.no_db + % TX Data is not precoded: + + % A) Emulate diff precoding + eq_signal_hd_precoded = Duobinary().encode(eq_signal_hd,"M",M); + eq_signal_hd_precoded = Duobinary().decode(eq_signal_hd_precoded,"M",M); tx_symbols_precoded = Duobinary().encode(tx_symbols); tx_symbols_precoded = Duobinary().decode(tx_symbols_precoded); - tx_bits = PAMmapper(M,0,"eth_style",options.eth_style).demap(tx_symbols_precoded); + tx_bits_precoded = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(tx_symbols_precoded); - case db_mode.db_discard + rx_bits_vnle = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(eq_signal_hd_precoded); + [~,errors_vnle_diff_precoded,ber_vnle_diff_precoded,~] = calc_ber(rx_bits_vnle.signal,tx_bits_precoded.signal,"skip_front",30000,"skip_end",150,"returnErrorLocation",1); - % normal dsp for precoded sequence == discard/omit/ignore precode - tx_bits = PAMmapper(M,0).demap(tx_symbols); + %B) Just determine BER + rx_bits_vnle = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(eq_signal_hd); + [bits_vnle,errors_vnle,ber_vnle,error_pos_vnle] = calc_ber(rx_bits_vnle.signal,tx_bits.signal,"skip_front",30000,"skip_end",150,"returnErrorLocation",1); - case db_mode.db_encoded + max_burst_length = 10; + burst_count = count_error_bursts(error_pos_vnle, max_burst_length); - % normal DB encoded data (only for 10KM) + case db_mode.db_precoded - case db_mode.db_precoded + % Daten SIND TATSÄCHLICH precoded auf TX Seite: - eq_signal_hd = Duobinary().encode(eq_signal_hd,"M",M); - eq_signal_hd = Duobinary().decode(eq_signal_hd,"M",M); + % A) Decode at Rx if no DB targeting was applied (we are in VNLE or MLSE EQ structure here! + eq_signal_hd_decoded = Duobinary().encode(eq_signal_hd,"M",M); + eq_signal_hd_decoded = Duobinary().decode(eq_signal_hd_decoded,"M",M); + rx_bits_vnle_decoded = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(eq_signal_hd_decoded); + [~,errors_vnle_diff_precoded,ber_vnle_diff_precoded,~] = calc_ber(rx_bits_vnle_decoded.signal,tx_bits.signal,"skip_front",30000,"skip_end",150,"returnErrorLocation",1); + % B) Omit the Coding by comparing with demapped TX symbol sequence + + tx_bits = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(tx_symbols); + rx_bits_vnle = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(eq_signal_hd); + [bits_vnle,errors_vnle,ber_vnle,~] = calc_ber(rx_bits_vnle.signal,tx_bits.signal,"skip_front",30000,"skip_end",150,"returnErrorLocation",1); + + +end + +% METRICS OF VNLE SD Signal: +[snr_vnle,snr_vnle_lvl] = calc_snr(tx_symbols.signal,eq_noise.signal); +[gmi_vnle] = calc_air(eq_signal_sd,tx_symbols,"skip_front",10000,"skip_end",10000); +air_vnle = tx_symbols.fs .* floor(log2(double(M))*10)/10 .* gmi_vnle ./ log2(double(M)); +[evm_vnle_total,evm_vnle_lvl] = calc_evm(eq_signal_sd,tx_symbols); +[std_vnle_total,std_vnle_lvl] = calc_std(eq_signal_sd,tx_symbols); +[std_rxraw_total,std_rxraw_lvl] = calc_std(rx_signal.resample("fs_out",tx_symbols.fs),tx_symbols); + +eq_package.ber_vnle = ber_vnle; +eq_package.evm_vnle_total = evm_vnle_total; +eq_package.evm_vnle_lvl = evm_vnle_lvl; +eq_package.gmi = gmi_vnle; + +eq_package.eq = eq_; + +resultsVNLE = struct( ... + 'result_id', NaN, ... % + 'run_id', NaN, ... % Beispielhafte Run-ID + 'eqParam_id', NaN, ... % Beispielhafter Fremdschlüssel zur EqualizerParameters-Tabelle + 'date_of_processing', datetime('now'), ... % Aktuelles Datum und Uhrzeit + 'BER', ber_vnle, ... % BER = 120 / 1.000.000 + 'numBits', bits_vnle, ... % Beispiel: 1.000.000 Bits + 'numBitErr', errors_vnle, ... % Beispiel: 120 Bitfehler + 'BER_precoded', ber_vnle_diff_precoded, ... % BER = 120 / 1.000.000 + 'numBitErr_precoded', errors_vnle_diff_precoded, ... % Beispiel: 120 Bitfehler + 'SNR', snr_vnle, ... % Beispielhafte SNR + 'SNR_level', jsonencode(snr_vnle_lvl), ... % SNR-Level als JSON-codiertes Array + 'STD', std_vnle_total, ... + 'STD_level', jsonencode(std_vnle_lvl),... + 'STDrx' , std_rxraw_total, ... + 'STDrx_level', jsonencode(std_rxraw_lvl),... + 'GMI', gmi_vnle, ... % Beispielhafter GMI-Wert + 'AIR', air_vnle, ... % Beispielhafter AIR-Wert + 'EVM', evm_vnle_total, ... % Beispielhafte EVM + 'EVM_level', jsonencode(evm_vnle_lvl), ... % EVM-Level als JSON-codiertes Array + 'Alpha', [] ... % Beispielhafter Alpha-Wert + ); + +if ~isempty(options.postFFE) + npostFFE = options.postFFE.order; +else + npostFFE = 0; +end + +equalizerConfigVNLE = struct( ... + 'eq_id', NaN, ... % Auto-Inkrement, wird in der DB gesetzt + 'equalizer_structure', int32(equalizer_structure.vnle), ... % Beispiel: 1 (z.B. für vnle) + 'M', M, ... % Ordnung der PAM-Konstellation + 'target_constellation', jsonencode(round(unique(tx_symbols.signal),5)), ... % Beispielhafter Target-String + 'db_target', 0, ... % 0 oder 1 + 'diff_precode', int32(options.precode_mode), ... % 0 oder 1 + 'postFFE', int32(~isempty(options.postFFE)), ... % Beispielwert + 'NpostFFE', npostFFE, ... % Beispielwert + 'Ne1', eq_.order, ... % Feedforward Koeffizienten 1. Ordnung + 'K', eq_.sps, ... % Samples pro Symbol + 'DCmu', mudc_given, ... % Anpassungsrate für DC-Tap + 'training_length', eq_.len_tr, ... % Anzahl Trainingssymbole + 'training_loops', eq_.epochs_tr, ... % Anzahl Trainingsdurchläufe + 'TRmu1', eq_.mu_tr, ... % mu für DD-Modus (1. Ordnung) + 'dd_loops', eq_.epochs_dd, ... % Anzahl Durchläufe im DD-Modus + 'DDmu1', eq_.mu_dd, ... % mu für DD-Modus (1. Ordnung) + 'comment', 'function: ffe dc removal', ... % Zusätzliche Kommentare + 'ffe_buffer_len', eq_.ffe_buffer_len, ... + 'smoothing_buffer_len', eq_.smoothing_buffer_length, ... + 'smoothing_buffer_update', eq_.smoothing_buffer_update, ... + 'dc_buffer_len', eq_.dc_buffer_len, ... + 'config_hash', NaN ... + ); + +eq_package.resultsVNLE = resultsVNLE; +eq_package.equalizerConfigVNLE = equalizerConfigVNLE; + + +% eq_package.vnle_out = eq_signal_sd; +if options.showAnalysis + + + % fprintf(['VNLE EVM lvl: ',repmat('%.3f ',1,numel(evm_lvl)),' \n'],evm_lvl); + + % fprintf('VNLE BER: %.2e \n',ber_vnle); + % + % fprintf('MLSE BER: %.2e \n',ber_mlse); + + figure(336); + showEQNoisePSD(eq_noise,"fignum",336,"displayname",'Residual Noise after VNLE'); + + % figure(337);clf; + % rx_signal.spectrum("normalizeTo0dB",1,"fignum",337,"displayname",'Rx Signal'); + + % figure(338);clf; + % showEQcoefficients('n1',eq_.e,'n2',eq_.e2,'n3',eq_.e3,"displayname",'Coefficients','fignum',338); + + if ~isempty(options.postFFE) + showEQcoefficients('n1',options.postFFE.e,"displayname",'Coefficients','fignum',338); end - rx_bits = PAMmapper(M,0,"eth_style",options.eth_style).demap(eq_signal_hd); + showEQfilter(eq_.e,eq_signal_sd.fs.*2); - [~,numErrors,ber,~] = calc_ber(rx_bits.signal,tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1); - [evm_total,evm_lvl] = calc_evm(eq_signal_sd,tx_symbols); - [inf_rate] = calc_air(eq_signal_sd,tx_symbols,"skip_front",10000,"skip_end",10000); + % figure(340);clf; + % eq_signal_sd.eye(eq_signal_sd.fs,M,"fignum",340); + + figure(341);clf; + showLevelHistogram(eq_signal_sd,tx_symbols,"fignum",341); + + figure(400);clf; + warning off + showLevelScatter(eq_signal_sd,tx_symbols,"fignum",400); + + showLevelScatter(rx_signal.resample("fs_out",tx_symbols.fs),tx_symbols,"fignum",400); + warning on + % autoArrangeFigures(3,3,2) - eq_package.ber_vnle = ber; - eq_package.evm_total = evm_total; - eq_package.evm_lvl = evm_lvl; - eq_package.inf_rate_vnle = inf_rate; - eq_package.snr = snr(eq_signal_sd.signal,eq_noise.signal); +end - eq_package.signal = eq_signal_sd; +end - - if options.showAnalysis - - fprintf('SNR: %d dB \n',snr(eq_signal_sd.signal,eq_noise.signal)); - - if M == 6 - logm = 2.5; - else - logm = log2(M); - end - - fprintf('NGMI: %.4f \n', inf_rate/logm); - - fprintf(['VNLE EVM lvl: ',repmat('%.3f ',1,numel(evm_lvl)),' \n'],evm_lvl); - - fprintf('VNLE BER: %.2e \n',ber); - - disp("%%%%%%%%%%%%%%%%%%%%%") - - % showEQcoefficients('n1',eq_.e,'n2',eq_.e2,'n3',eq_.e3,"displayname",'Coefficients'); - % - % if ~isempty(options.postFFE) - % showEQcoefficients('n1',options.postFFE.e,"displayname",'Coefficients'); - % end - % - % showEQNoisePSD(eq_noise); - % - % showEQfilter(eq_.e,eq_signal_sd.fs.*2) - - % noiselessness(tx_symbols,eq_noise,"displayname",'SNR after VNLE','fignum',301); - - % showLevelHistogram(eq_signal_sd,tx_symbols,"fignum",302); - - - - end - -end \ No newline at end of file diff --git a/Functions/EQ_structures/vnle_postfilter_mlse.m b/Functions/EQ_structures/vnle_postfilter_mlse.m index d125ca6..85a17e1 100644 --- a/Functions/EQ_structures/vnle_postfilter_mlse.m +++ b/Functions/EQ_structures/vnle_postfilter_mlse.m @@ -100,7 +100,7 @@ end air_vnle = tx_symbols.fs .* floor(log2(double(M))*10)/10 .* gmi_vnle ./ log2(double(M)); [evm_vnle_total,evm_vnle_lvl] = calc_evm(eq_signal_sd,tx_symbols); [std_vnle_total,std_vnle_lvl] = calc_std(eq_signal_sd,tx_symbols); -[std_rxraw_total,std_rxraw_lvl] = calc_std(rx_signal.resample("fs_out",tx_symbols.fs),tx_symbols); +[std_rxraw_total,std_rxraw_lvl] = calc_std(rx_signal.resample("fs_out",tx_symbols.fs),tx_symbols); % METRICS OF MLSE (HD-VITERBI) pf_.ncoeff = 1; @@ -252,7 +252,7 @@ if options.showAnalysis % % fprintf('MLSE BER: %.2e \n',ber_mlse); - figure(336);clf; + figure(336); showEQNoisePSD(eq_noise,"fignum",336,"displayname",'Residual Noise after VNLE','postfilter_taps',pf_.coefficients); % figure(337);clf; @@ -273,9 +273,12 @@ if options.showAnalysis figure(341);clf; showLevelHistogram(eq_signal_sd,tx_symbols,"fignum",341); + warning off showLevelScatter(eq_signal_sd,tx_symbols,"fignum",400); showLevelScatter(rx_signal.resample("fs_out",tx_symbols.fs),tx_symbols,"fignum",401); + warning on + drawnow; % autoArrangeFigures(3,3,2) diff --git a/Functions/EQ_visuals/showLevelScatter.m b/Functions/EQ_visuals/showLevelScatter.m index b7cab41..1bc7e33 100644 --- a/Functions/EQ_visuals/showLevelScatter.m +++ b/Functions/EQ_visuals/showLevelScatter.m @@ -20,7 +20,6 @@ if isnan(options.fignum) fig = figure; % Create a new figure and get its handle else fig = figure(options.fignum); % Use the specified figure number - clf; end assert(~isempty(options.f_sym),'No fsym given'); @@ -40,7 +39,7 @@ ende = length(correct_symbols); % start = 30000; % ende = 40000; -for l = 1:4 +for l = 1:numel(levels) ccnt = ccnt+2; level_amplitude = levels(l); @@ -50,23 +49,24 @@ for l = 1:4 std_lvl(l) = std(symbols_for_lvl,'omitnan'); xax_in_sec = ((1:length(correct_symbols)) / f_sym) * 1e6; % xax_in_sec = 1:length(correct_symbols); - +if 0 scatter(xax_in_sec(start:ende),symbols_for_lvl(start:ende),10,'.','MarkerFaceAlpha',0.5,'MarkerEdgeAlpha',0.5,'MarkerEdgeColor',col(ccnt,:)); hold on; end +end std_lvl = round(std_lvl,2); ccnt = 0; % Add the windowed/ smoothed curves -for l = 1:4 +for l = 1:numel(levels) ccnt = ccnt+2; level_amplitude = levels(l); symbols_for_lvl = NaN(1,length(correct_symbols)); - movmean = 1/250 .* movsum(rx_symbols(correct_symbols==level_amplitude),[250/2,250/2]); + movmean = 1/250 .* movsum(rx_symbols(correct_symbols==level_amplitude),[250/2,250/2], 'Endpoints', 'fill'); symbols_for_lvl(correct_symbols==level_amplitude) = movmean; diff --git a/Functions/Metrics/count_error_bursts.m b/Functions/Metrics/count_error_bursts.m new file mode 100644 index 0000000..fdc5fc1 --- /dev/null +++ b/Functions/Metrics/count_error_bursts.m @@ -0,0 +1,29 @@ +function burst_count = count_error_bursts(err_pos, max_burst_length) + % err_pos: Vector of error positions + % max_burst_length: Maximum length for which bursts are counted (e.g., 10) + + % Sort the error positions to ensure they're in increasing order + err_pos = sort(err_pos); + + % Initialize burst_count array to hold the counts for each burst length + burst_count = zeros(1, max_burst_length); + + % Find the differences between consecutive error positions + diffs = diff(err_pos); + + % Find the start of the bursts (where the difference is greater than 1) + burst_starts = [1, find(diffs > 1) + 1]; % Starts at index 1 and after gaps + burst_ends = [find(diffs > 1), length(err_pos)]; % Ends where gaps are + + % Loop over the bursts + for b = 1:length(burst_starts) + burst_length = burst_ends(b) - burst_starts(b) + 1; + + % Check if the burst length exceeds any of the thresholds + for i = 1:max_burst_length + if burst_length > i + burst_count(i) = burst_count(i) + 1; + end + end + end +end diff --git a/projects/ECOC_2025/dsp_loop_id.m b/projects/ECOC_2025/dsp_loop_id.m new file mode 100644 index 0000000..2d9ab8f --- /dev/null +++ b/projects/ECOC_2025/dsp_loop_id.m @@ -0,0 +1,63 @@ + + + +savePath = 'Z:\2025\ECOC Silas\ecoc_2025\'; +databasePath = 'C:\Users\Silas\Documents\MATLAB\imdd_simulation\projects\ECOC_2025\'; +database_name = 'ecoc2025_loops.db'; +db = DBHandler("type","mysql"); +% db = DBHandler("pathToDB", [databasePath, database_name],"type","sqlite"); + +filterParams = db.tables; +% filterParams.Configurations = struct('run_id', run_id); +filterParams.Configurations = struct( ... + 'symbolrate', 112e9, ... %[224,336,360,390,420,448] + 'fiber_length', 0, ... + 'db_mode', '"no_db"', ... + 'interference_attenuation', [], ... + 'interference_path_length', 10, ... + 'is_mpi', 1, ... + 'pam_level', 4, ... + 'wavelength', 1310, ... + 'precomp_amp', [], ... + 'signal_attenuation', [], ... + 'v_awg', [], ... + 'v_bias', 2.65 ... + ); + +selectedFields = {'Runs.run_id','Runs.loop_id','Runs.tx_bits_path','Runs.tx_signal_path','Runs.tx_symbols_path','Runs.rx_sync_path','Runs.rx_raw_path',... + 'Configurations.db_mode','Configurations.pam_level','Configurations.bitrate','Configurations.symbolrate','Configurations.fiber_length','Configurations.wavelength','Configurations.precomp_amp','Measurements.power_rop','Configurations.v_bias',... + 'Configurations.interference_attenuation', 'Configurations.interference_path_length'}; + +[dataTable,sql_query] = db.queryDB(filterParams, selectedFields); + +dataTable(dataTable.loop_id~=217,:) = []; + +num_occ = 10; +run_par = true; +run_id = dataTable.run_id; + +params.dc_buffer_len = 224; +params.ffe_buffer_len = 1; +params.smoothing_buffer_length = 0; +params.smoothing_buffer_update = 0; +params.mu_dc = 0.005; + +futures_list = parallel.FevalFuture.empty(); +for id = 1:length(dataTable.run_id) + run_id = dataTable.run_id(id); + [out, futures_list(id)] = submit_dsp(run_id, databasePath, database_name, savePath,"parallel",run_par,'max_occurences',num_occ,'paramstruct',params); +end + +% Extract all ber_mlse values from the vnle_pf_package using cellfun +ber_mlse = cellfun(@(pkg) pkg.ber_mlse, future.OutputArguments{1,1}.vnle_pf_package); +ber_vnle = cellfun(@(pkg) pkg.ber_vnle, future.OutputArguments{1,1}.vnle_pf_package); + +figure(101) +hold on; +scatter(1:num_occ,ber_mlse,15,'Marker','*'); +scatter(1:num_occ,ber_vnle,15,'Marker','*'); +legend('Interpreter', 'latex'); +xlabel('Occurences'); +ylabel('BER'); +grid on; +beautifyBERplot; diff --git a/projects/ECOC_2025/dsp_run_id.m b/projects/ECOC_2025/dsp_run_id.m index 2b57c8e..5ef32d3 100644 --- a/projects/ECOC_2025/dsp_run_id.m +++ b/projects/ECOC_2025/dsp_run_id.m @@ -48,15 +48,14 @@ mu_ffe3 = 0.001; mu_dfe = 0.0004; mu_dc = 0.00; -% mu_ffe1 = 0; -% mu_ffe2 = 0; -% mu_ffe3 = 0; -% mu_dfe =0; -% mu_dc = 0.00; - mu_ffe = [mu_ffe1 mu_ffe2 mu_ffe3]; vnle_order=[vnle_order1,vnle_order2,vnle_order3]; +dc_buffer_len = 224; +ffe_buffer_len = 1; +smoothing_buffer_length = 4096; +smoothing_buffer_update = 224; + % Overwrite default parameters if given in options.parameters paramStruct = options.parameters; if ~isempty(paramStruct) @@ -78,7 +77,7 @@ eq_post = FFE("epochs_tr",5,"epochs_dd",5,"len_tr",4096*2,"mu_dd",1e-4,"mu_tr",0 output = struct(); vnle_pf_package = {}; -vnle_dfe_package = {}; +vnle_package = {}; dbtgt_package = {}; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -121,7 +120,7 @@ if ~found_sync end record_realizations = min(options.max_occurences,length(Scpe_cell)); -for occ = 1:record_realizations +for occ = 4:record_realizations Scpe_sig = Scpe_cell{occ}; @@ -137,16 +136,27 @@ for occ = 1:record_realizations if duob_mode ~= db_mode.db_encoded - vnle_pf = 1; + vnle_pf = 0; dbtgt = 0; % %%%%% VNLE + DFE %%%% - if 0 + if 1 - eq_vnle_dfe = EQ("Ne",vnle_order,"Nb",[0,0,0],"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",0); - eq_post = FFE("epochs_tr",5,"epochs_dd",5,"len_tr",4096*2,"mu_dd",1e-4,"mu_tr",0,"order",2001,"sps",1,"decide",0); + eq_ = FFE_DCremoval_adaptive_mu("epochs_tr",5,"epochs_dd",3,"len_tr",4096*2,"mu_dd",... + 0.0002,"mu_tr",0,"order",25,"sps",2,"decide",0,... + "mu_dc",mu_dc,... + "dc_buffer_len",dc_buffer_len, ... + "ffe_buffer_len",ffe_buffer_len,... + "smoothing_buffer_length",smoothing_buffer_length,... + "smoothing_buffer_update",smoothing_buffer_update); - [result] = vnle(eq_vnle_dfe,M,Scpe_sig,Symbols,Tx_bits,"precode_mode",duob_mode,"showAnalysis",1,"postFFE",[]); - vnle_dfe_package{occ} = result; + result = vnle(eq_,M,Scpe_sig,Symbols,Tx_bits,"precode_mode",duob_mode,'showAnalysis',1,"postFFE",[],"eth_style_symbol_mapping",0); + vnle_package{occ} = result; + fprintf("FFE Results: %.2e\n", result.ber_vnle); + + + if options.append_to_db + database.addProcessingResult(run_id, result.resultsVNLE, result.equalizerConfigVNLE); + end end @@ -176,32 +186,32 @@ for occ = 1:record_realizations % % fprintf("BER VNLE: %.2e | %.2e; BER MLSE: %.2e | %.2e \n",vnle_pf_package{occ}.resultsVNLE.BER,vnle_pf_package{occ}.resultsVNLE.BER_precoded ,vnle_pf_package{occ}.resultsMLSE.BER,vnle_pf_package{occ}.resultsMLSE.BER_precoded); if vnle_pf - occ = 1; % or whatever your loop index is + % occ = 1; % or whatever your loop index is % Extract VNLE results for readability - vnle = vnle_pf_package{occ}.resultsVNLE; - mlse = vnle_pf_package{occ}.resultsMLSE; + vnle_result = vnle_pf_package{occ}.resultsVNLE; + mlse_result = vnle_pf_package{occ}.resultsMLSE; % Print header fprintf("==== EQUALIZATION RUN-ID %d | PAM-%d | %.2f GBd ====\n\n", run_id, M, Symbols.fs.*1e-9); - +s % VNLE Results fprintf(">> VNLE Results:\n"); - fprintf(" BER %.2e\n", vnle.BER); - fprintf(" BER (pre-code) %.2e\n", vnle.BER_precoded); - fprintf(" SNR: %.2f dB\n", vnle.SNR); - fprintf(" GMI: %.4f\n", vnle.GMI); + fprintf(" BER %.2e\n", vnle_result.BER); + fprintf(" BER (pre-code) %.2e\n", vnle_result.BER_precoded); + fprintf(" SNR: %.2f dB\n", vnle_result.SNR); + fprintf(" GMI: %.4f\n", vnle_result.GMI); fprintf(" Linerate: %.2f Gbps\n", Symbols.fs .* floor(log2(M)*10)/10 .*1e-9); - fprintf(" AIR: %.2f Gbps\n", vnle.AIR.*1e-9); + fprintf(" AIR: %.2f Gbps\n", vnle_result.AIR.*1e-9); fprintf("\n"); % MLSE Results fprintf(">> MLSE Results:\n"); - fprintf(" BER : %.2e\n", mlse.BER); - fprintf(" BER (pre-code): %.2e\n", mlse.BER_precoded); - fprintf(" Channel Alpha : %.2f\n", mlse.Alpha); + fprintf(" BER : %.2e\n", mlse_result.BER); + fprintf(" BER (pre-code): %.2e\n", mlse_result.BER_precoded); + fprintf(" Channel Alpha : %.2f\n", mlse_result.Alpha); fprintf("\n"); end @@ -244,6 +254,7 @@ end output.dataTable = dataTable; output.vnle_pf_package = vnle_pf_package; +output.vnle_package = vnle_package; output.dbtgt_package = dbtgt_package; end \ No newline at end of file diff --git a/projects/ECOC_2025/dsp_standalone.m b/projects/ECOC_2025/dsp_standalone.m index 56ba875..b28e6ff 100644 --- a/projects/ECOC_2025/dsp_standalone.m +++ b/projects/ECOC_2025/dsp_standalone.m @@ -4,9 +4,89 @@ savePath = 'Z:\2025\ECOC Silas\ecoc_2025\'; databasePath = 'C:\Users\Silas\Documents\MATLAB\imdd_simulation\projects\ECOC_2025\'; database_name = 'ecoc2025_loops.db'; -db = DBHandler("pathToDB", [databasePath, database_name],"type","mysql"); -% db = DBHandler("type","mysql"); -num_occ = 5; -run_par = false; -run_id = 1958; -[out, future] = submit_dsp(run_id, databasePath, database_name, savePath,"parallel",run_par,'max_occurences',num_occ); +db = DBHandler("type","mysql"); +% db = DBHandler("pathToDB", [databasePath, database_name],"type","sqlite"); + +filterParams = db.tables; +% filterParams.Configurations = struct('run_id', 4001); +filterParams.Configurations = struct( ... + 'symbolrate', 112e9, ... %[224,336,360,390,420,448] + 'fiber_length', 0, ... + 'db_mode', '"no_db"', ... + 'interference_attenuation', [], ... + 'interference_path_length', [], ... + 'is_mpi', 1, ... + 'pam_level', 4, ... + 'wavelength', 1310, ... + 'precomp_amp', [], ... + 'signal_attenuation', [], ... + 'v_awg', [], ... + 'v_bias', 2.65 ... + ); + +selectedFields = {'Runs.run_id','Runs.loop_id','Runs.tx_bits_path','Runs.tx_signal_path','Runs.tx_symbols_path','Runs.rx_sync_path','Runs.rx_raw_path',... + 'Configurations.db_mode','Configurations.pam_level','Configurations.bitrate','Configurations.symbolrate','Configurations.fiber_length','Configurations.wavelength','Configurations.precomp_amp','Measurements.power_rop','Configurations.v_bias',... + 'Configurations.interference_attenuation', 'Configurations.interference_path_length'}; + +[dataTable,sql_query] = db.queryDB(filterParams, selectedFields); + +% dataTable(dataTable.loop_id<200,:) = []; + +num_occ = 15; +run_par = true; +run_id = dataTable.run_id; +params = struct(); + +% slow DC tracking +params.dc_buffer_len = 224; +params.ffe_buffer_len = 1; +params.smoothing_buffer_length = 0; +params.smoothing_buffer_update = 0; +params.mu_dc = 0.005; + +futures_list = parallel.FevalFuture.empty(); +for id = 1:length(dataTable.run_id) + run_id = dataTable.run_id(id); + [out, futures_list(id)] = submit_dsp(run_id, databasePath, database_name, savePath,"parallel",run_par,'max_occurences',num_occ,'paramstruct',params); +end + +% ideal DC tracking +params.dc_buffer_len = 1; +params.ffe_buffer_len = 1; +params.smoothing_buffer_length = 0; +params.smoothing_buffer_update = 0; +params.mu_dc = 0.005; + +futures_list = parallel.FevalFuture.empty(); +for id = 1:length(dataTable.run_id) + run_id = dataTable.run_id(id); + [out, futures_list(id)] = submit_dsp(run_id, databasePath, database_name, savePath,"parallel",run_par,'max_occurences',num_occ,'paramstruct',params); +end + +% DC smoothing +params.dc_buffer_len = 1; +params.ffe_buffer_len = 1; +params.smoothing_buffer_length = 4096; +params.smoothing_buffer_update = 224; +params.mu_dc = 0.00; + +futures_list = parallel.FevalFuture.empty(); +for id = 1:length(dataTable.run_id) + run_id = dataTable.run_id(id); + [out, futures_list(id)] = submit_dsp(run_id, databasePath, database_name, savePath,"parallel",run_par,'max_occurences',num_occ,'paramstruct',params); +end + +% only FFE +params.dc_buffer_len = 1; +params.ffe_buffer_len = 1; +params.smoothing_buffer_length = 0; +params.smoothing_buffer_update = 0; +params.mu_dc = 0.00; + +futures_list = parallel.FevalFuture.empty(); +for id = 1:length(dataTable.run_id) + run_id = dataTable.run_id(id); + [out, futures_list(id)] = submit_dsp(run_id, databasePath, database_name, savePath,"parallel",run_par,'max_occurences',num_occ,'paramstruct',params); +end + + diff --git a/projects/ECOC_2025/dsp_test/hyperparam_tuning.m b/projects/ECOC_2025/dsp_test/hyperparam_tuning.m new file mode 100644 index 0000000..75f415e --- /dev/null +++ b/projects/ECOC_2025/dsp_test/hyperparam_tuning.m @@ -0,0 +1,58 @@ + + +Scpe_sig = load("imdd_simulation\projects\ECOC_2025\dsp_test\pam4_scopesignal.mat");Scpe_sig = Scpe_sig.Scpe_sig; +Tx_bits = load("imdd_simulation\projects\ECOC_2025\dsp_test\pam4_bits.mat");Tx_bits = Tx_bits.Tx_bits; +Symbols = load("imdd_simulation\projects\ECOC_2025\dsp_test\pam4_symbols.mat");Symbols = Symbols.Symbols; + +eq_ = FFE_DCremoval("epochs_tr",5,"epochs_dd",3,"len_tr",4096*2,"mu_dd",1e-5,"mu_tr",0,"order",50,"sps",2,"decide",0,"mu_dc",0.005,"dc_buffer_len",1); + +savePath = 'Z:\2025\ECOC Silas\ecoc_2025\'; +databasePath = 'C:\Users\Silas\Documents\MATLAB\imdd_simulation\projects\ECOC_2025\'; +database_name = 'ecoc2025_loops.db'; +db = DBHandler("type","mysql"); + +params = (logspace(-6,-2,20)); +params = floor((logspace(2,3,20))); +params = 224; + +for i = 1:length(params) + + eq_ = FFE_DCremoval_adaptive_mu("epochs_tr",5,"epochs_dd",3,"len_tr",4096*2,"mu_dd",... + 0.0002,"mu_tr",0,"order",25,"sps",2,"decide",0,... + "mu_dc",0.005,"dc_buffer_len",224, ... + "ffe_buffer_len",1,... + "smoothing_buffer_length",0,... + "smoothing_buffer_update",224); + + result = vnle(eq_,4,Scpe_sig,Symbols,Tx_bits,"precode_mode",db_mode.no_db,'showAnalysis',1,"postFFE",[],"eth_style_symbol_mapping",0); + ber_ffe(i) = result.ber_vnle; + fprintf(" FFE Results: %.2e\n", ber_ffe(i)); + + db.addProcessingResult(run_id, result.resultsVNLE, result.equalizerConfigVNLE); + + % eq_ = FFE_adaptive_decision("epochs_tr",5,"epochs_dd",3,"len_tr",4096*2,"mu_dd",... + % 0.0003,"mu_tr",0,"order",50,"sps",2,"decide",1,"buffer_length",params(i)); + % + % result = vnle(eq_,4,Scpe_sig,Symbols,Tx_bits,"precode_mode",db_mode.no_db,'showAnalysis',1,"postFFE",[],"eth_style_symbol_mapping",0); + % ber_dc(i) = result.ber_vnle; + % + % fprintf(" FFE+dc tr. Results: %.2e\n", ber_dc(i)); + +end + +figure(103435) +hold on; +% scatter(params,ber_dc,15,'Marker','o','LineWidth',1,'DisplayName','DC tracking'); +% [a,b]=min(ber_dc); +% scatter(params(b),a,45,'Marker','x','MarkerEdgeColor','r','LineWidth',1); + +scatter(params,ber_ffe,15,'Marker','square','LineWidth',1); +[a,b]=min(ber_ffe); +scatter(params(b),a,45,'Marker','x','MarkerEdgeColor','r','LineWidth',1,'DisplayName','FFE'); + +legend('Interpreter', 'latex'); +xlabel('Occurences'); +ylabel('BER'); +grid on; +beautifyBERplot; +ylim([1e-4,0.1 ]) \ No newline at end of file diff --git a/projects/ECOC_2025/load_signal_standalone.m b/projects/ECOC_2025/load_signal_standalone.m index 51ae8bd..cb27584 100644 --- a/projects/ECOC_2025/load_signal_standalone.m +++ b/projects/ECOC_2025/load_signal_standalone.m @@ -1,6 +1,6 @@ -run_id = 231; +run_id = 3966; savePath = 'Z:\2025\ECOC Silas\ecoc_2025\'; databasePath = 'C:\Users\Silas\Documents\MATLAB\imdd_simulation\projects\ECOC_2025\'; @@ -9,7 +9,22 @@ db = DBHandler("type","mysql"); % db = DBHandler("pathToDB", [databasePath, database_name],"type","sqlite"); filterParams = db.tables; -filterParams.Configurations = struct('run_id', run_id); +% filterParams.Configurations = struct('run_id', run_id); +filterParams.Configurations = struct( ... + 'symbolrate', [], ... %[224,336,360,390,420,448] + 'fiber_length', 0, ... + 'db_mode', '"no_db"', ... + 'interference_attenuation', 4, ... + 'interference_path_length', 10, ... + 'is_mpi', 1, ... + 'pam_level', [], ... + 'wavelength', 1310, ... + 'precomp_amp', [], ... + 'signal_attenuation', [], ... + 'v_awg', [], ... + 'v_bias', 2.65 ... + ); + selectedFields = {'Runs.run_id','Runs.tx_bits_path','Runs.tx_signal_path','Runs.tx_symbols_path','Runs.rx_sync_path','Runs.rx_raw_path',... 'Configurations.db_mode','Configurations.pam_level','Configurations.bitrate','Configurations.symbolrate','Configurations.fiber_length','Configurations.wavelength','Configurations.precomp_amp','Measurements.power_rop','Configurations.v_bias',... @@ -18,29 +33,36 @@ selectedFields = {'Runs.run_id','Runs.tx_bits_path','Runs.tx_signal_path','Runs. [dataTable,sql_query] = db.queryDB(filterParams, selectedFields); [~, uniqueIdx] = unique(dataTable.run_id); % Get unique run_id indices -dataTable = dataTable(uniqueIdx,:); % Extract unique configurations for each run_id -fsym = dataTable.symbolrate; -M = double(dataTable.pam_level); -duob_mode = db_mode.(strrep(char(dataTable.db_mode),'"','')); -Tx_signal = load([savePath, char(dataTable.tx_signal_path)]); -Tx_signal = Tx_signal.Digi_sig; +for i = 1:4%size(dataTable,1) + dataTable_ = dataTable(i,:); % Extract unique configurations for each run_id + + fsym = dataTable_.symbolrate; + M = double(dataTable_.pam_level); + duob_mode = db_mode.(strrep(char(dataTable_.db_mode),'"','')); + + Tx_signal = load([savePath, char(dataTable_.tx_signal_path)]); + Tx_signal = Tx_signal.Digi_sig; -Tx_bits = load([savePath, char(dataTable.tx_bits_path)]); -Tx_bits = Tx_bits.Bits; -Symbols_mapped = PAMmapper(M,0).map(Tx_bits); -Symbols_mapped.fs = dataTable.symbolrate; + Tx_bits = load([savePath, char(dataTable_.tx_bits_path)]); + Tx_bits = Tx_bits.Bits; + Symbols_mapped = PAMmapper(M,0).map(Tx_bits); + Symbols_mapped.fs = dataTable_.symbolrate; -Symbols = load([savePath, char(dataTable.tx_symbols_path)]); -Symbols = Symbols.Symbols; + Symbols = load([savePath, char(dataTable_.tx_symbols_path)]); + Symbols = Symbols.Symbols; + + Scpe_sig_raw = load([savePath, char(dataTable_.rx_raw_path(1))]); + Scpe_sig_raw = Scpe_sig_raw.Scpe_sig_raw; + Scpe_sig_raw.plot("displayname",['Scope Signal (Run ID: ',num2str(dataTable_.run_id)],"fignum",dataTable_.run_id,"clear",0); -Scpe_sig_raw = load([savePath, char(dataTable.rx_raw_path(1))]); -Scpe_sig_raw = Scpe_sig_raw.Scpe_sig_raw; -Scpe_sig_resampled = Scpe_sig_raw.resample("fs_in",Scpe_sig_raw.fs,"fs_out",2*fsym); -[~,Scpe_cell,found_sync,~,shifts] = Scpe_sig_resampled.tsynch("reference",Symbols,"fs_ref",dataTable.symbolrate,"debug_plots",1); -shifts_mus = shifts./Scpe_sig_resampled.fs .*1e6; -Scpe_sig_raw.plot("displayname",['Scope Signal (Run ID: ',num2str(run_id)],"fignum",2024,"clear",1); -hold on; -xline(shifts_mus,'HandleVisibility','off'); \ No newline at end of file + Scpe_sig_resampled = Scpe_sig_raw.resample("fs_in",Scpe_sig_raw.fs,"fs_out",2*fsym); + [~,Scpe_cell,found_sync,~,shifts] = Scpe_sig_resampled.tsynch("reference",Symbols,"fs_ref",dataTable_.symbolrate,"debug_plots",1); + + shifts_mus = shifts./Scpe_sig_resampled.fs .*1e6; + Scpe_sig_raw.plot("displayname",['Scope Signal (Run ID: ',num2str(dataTable_.run_id)],"fignum",dataTable_.run_id,"clear",0); + hold on; + xline(shifts_mus,'HandleVisibility','off'); +end \ No newline at end of file diff --git a/projects/ECOC_2025/plots_from_database/plot_mpi_trial.m b/projects/ECOC_2025/plots_from_database/plot_mpi_trial.m index 26a85c6..eadb53c 100644 --- a/projects/ECOC_2025/plots_from_database/plot_mpi_trial.m +++ b/projects/ECOC_2025/plots_from_database/plot_mpi_trial.m @@ -1,67 +1,129 @@ -local = 1; - -if local - databasePath = 'C:\Users\sioe\Documents\MATLAB\imdd_simulation\projects\ECOC_2025\'; -else - databasePath = '\\ntserver.tf.uni-kiel.de\scratch\sioe\ECOC_2025\'; -end - -database_name = 'ecoc2025_loops.db'; -database = DBHandler("pathToDB", [databasePath, database_name]); - -figure(); -plotBoundaries = 1; -plotRealizations = 1; -cols = linspecer(3); % Ensure color count matches -% cols = cols(8,:); +basePath = 'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\'; +% database = DBHandler("pathToDB",[basePath,'silas_labor.db']); +database = DBHandler("type",'mysql'); filterParams = database.tables; +%filterParams.Runs.loop_id = 209; filterParams.Configurations = struct( ... 'symbolrate', 112e9, ... %[224,336,360,390,420,448] 'fiber_length', 0, ... 'db_mode', '"no_db"', ... 'interference_attenuation', [], ... - 'interference_path_length', 10, ... + 'interference_path_length', [], ... 'is_mpi', 1, ... 'pam_level', 4, ... 'wavelength', 1310, ... 'precomp_amp', [], ... 'signal_attenuation', [], ... - 'v_awg', 0.95, ... - 'v_bias', 2.5 ... + 'v_awg', [], ... + 'v_bias', [] ... ); -% filterParams.EqualizerParameters.diff_precode = int32(db_mode.db_encoded); -% filterParams.EqualizerParameters.equalizer_structure = int32(equalizer_structure.vnle); + +% if 1 +% % filterParams.EqualizerParameters.dc_buffer_len = 1; +% filterParams.EqualizerParameters.ffe_buffer_len = 1; +% filterParams.EqualizerParameters.smoothing_buffer_len = 4096; +% filterParams.EqualizerParameters.smoothing_buffer_update = 224; +% filterParams.EqualizerParameters.DCmu = 0; +% end selectedFields = {'Configurations.run_id' 'Runs.loop_id' 'Runs.date_of_run' 'Runs.rx_raw_path' 'Configurations.bitrate' 'Configurations.v_bias' 'Configurations.v_awg' 'Configurations.precomp_amp' 'Configurations.symbolrate' 'Configurations.pam_level'... 'Configurations.db_mode' 'Configurations.rop_attenuation' 'Configurations.is_mpi' 'Configurations.interference_attenuation' 'Configurations.interference_path_length' 'Configurations.signal_attenuation' ... - 'EqualizerParameters.equalizer_structure' 'EqualizerParameters.diff_precode' 'EqualizerParameters.eq_id' 'Measurements.power_pd_in' ... - 'Measurements.power_mpi_interference' 'Measurements.power_mpi_signal' 'Results.BER' 'Results.BER_precoded' 'Results.SNR' 'Results.GMI' 'Results.Alpha' 'Results.date_of_processing'}; + 'EqualizerParameters.equalizer_structure' 'EqualizerParameters.diff_precode' 'EqualizerParameters.eq_id' 'EqualizerParameters.dc_buffer_len' 'EqualizerParameters.ffe_buffer_len' 'EqualizerParameters.smoothing_buffer_len' 'EqualizerParameters.smoothing_buffer_update' 'EqualizerParameters.DCmu' 'Measurements.power_pd_in' ... + 'Measurements.power_mpi_interference' 'Measurements.power_mpi_signal' 'Results.BER' 'Results.BER_precoded' 'Results.EVM' 'Results.SNR' 'Results.GMI' 'Results.Alpha' 'Results.date_of_processing'}; -[dataTable,sql_query] = database.queryDB(filterParams, selectedFields); -dataTable.SIR = round(-6 - dataTable.power_mpi_interference); -dataTable = cleanUpTable(dataTable); +% [dataTable_raw,sql_query] = database.queryDB(filterParams, selectedFields); + +%% + + + + +dataTable_clean = dataTable_raw; +dataTable_clean.SIR = round(-7.5 - dataTable_clean.power_mpi_interference); +dataTable_clean.NGMI = dataTable_clean.GMI ./ log2(dataTable_clean.pam_level); +dataTable_clean = cleanUpTable(dataTable_clean); + +%% + +dataTable = dataTable_clean; + +figure(26); +plotBoundaries = 1; +plotRealizations = 0; +cols = linspecer(8); % Ensure color count matches + +% ideal DC tracking +if 0 + dataTable = dataTable(dataTable.dc_buffer_len == 1, :); + dataTable = dataTable(dataTable.ffe_buffer_len == 1, :); + dataTable = dataTable(dataTable.smoothing_buffer_len == 0, :); + dataTable = dataTable(dataTable.smoothing_buffer_update == 0, :); + dataTable = dataTable(dataTable.DCmu == 0.005, :); + cols = cols(1:1+1,:); + method = 'ideal dc tracking'; + % slow DC tracking +elseif 1 + + dataTable = dataTable(dataTable.dc_buffer_len == 224, :); + dataTable = dataTable(dataTable.ffe_buffer_len == 1, :); + dataTable = dataTable(dataTable.smoothing_buffer_len == 0, :); + dataTable = dataTable(dataTable.smoothing_buffer_update == 0, :); + dataTable = dataTable(dataTable.DCmu == 0.005, :); + cols = cols(2:2+1,:); + method = 'parallelized dc tracking'; + % slow DC smoothing +elseif 0 + + dataTable = dataTable(dataTable.dc_buffer_len == 1, :); + dataTable = dataTable(dataTable.ffe_buffer_len == 1, :); + dataTable = dataTable(dataTable.smoothing_buffer_len == 4096, :); + dataTable = dataTable(dataTable.smoothing_buffer_update == 224, :); + dataTable = dataTable(dataTable.DCmu == 0, :); + cols = cols(3:3+1,:); + method = 'dc smoothing'; +elseif 0 + % No compensation method + dataTable = dataTable(dataTable.dc_buffer_len == 1, :); + dataTable = dataTable(dataTable.ffe_buffer_len == 1, :); + dataTable = dataTable(dataTable.smoothing_buffer_len == 0, :); + dataTable = dataTable(dataTable.smoothing_buffer_update == 0, :); + dataTable = dataTable(dataTable.DCmu == 0, :); + cols = cols(4:4+1,:); + method = 'ffe only'; +end dataTable(dataTable.eq_id==0,:) = []; +dataTable(dataTable.equalizer_structure~=1,:) = []; + +% dataTable.interference_path_length(dataTable.interference_path_length < 20, :) = 20; + +dataTable = dataTable(dataTable.interference_path_length == 1000, :); + +% dataTable(dataTable.interference_path_length ~= 50, :) = []; +% dataTable = dataTable(dataTable.interference_path_length < 51, :); + +% dataTable(dataTable.loop_id<200,:) = []; % Filter by time filter_by_time = 0; if filter_by_time - startTime = datetime('2025-04-14 13:00:00', 'InputFormat', 'yyyy-MM-dd HH:mm:ss'); - stopTime = datetime('2025-04-14 19:30:00', 'InputFormat', 'yyyy-MM-dd HH:mm:ss'); + startTime = datetime('2025-04-20 18:00:00', 'InputFormat', 'yyyy-MM-dd HH:mm:ss'); + stopTime = datetime('2025-04-30 19:30:00', 'InputFormat', 'yyyy-MM-dd HH:mm:ss'); dataTable.date_of_run = datetime(dataTable.date_of_run, 'InputFormat', 'yyyy-MM-dd HH:mm:ss.SSSSSS'); dataTable.date_of_processing = datetime(dataTable.date_of_processing, 'InputFormat', 'yyyy-MM-dd HH:mm:ss.SSSSSS'); dataTable = dataTable(dataTable.date_of_processing > startTime, :); dataTable = dataTable(dataTable.date_of_processing < stopTime, :); end + % Group by smth y_var = 'BER'; x_var = 'SIR'; -loop_var = 'eq_id'; -fixedVars = {'eq_id',x_var}; +loop_var = 'interference_path_length'; +fixedVars = {'equalizer_structure','interference_path_length',x_var}; [dataTable, outliersTable] = removeGroupOutliers(dataTable, fixedVars, y_var); @@ -69,14 +131,13 @@ dataTableGrpd_mean = groupIt(fixedVars, dataTable, @mean); dataTableGrpd_min = groupIt(fixedVars, dataTable, @min); dataTableGrpd_max = groupIt(fixedVars, dataTable, @max); - % Create a new figure mkr = '.'; hold on unique_loop_var = unique(dataTable.(loop_var)); -for i = 1%:numel(unique_loop_var) +for i = 1:numel(unique_loop_var) % Prepare filtered data for this loop variable loopValue = unique_loop_var(i); @@ -98,32 +159,43 @@ for i = 1%:numel(unique_loop_var) y_bounds = [y_lower, y_upper]; % Display name (optional) - idx = find(dataTable.(loop_var) == loopValue, 1, 'first'); - dispname = equalizer_structure(dataTable.equalizer_structure(idx)); - dispname = [char(dispname),'; ',num2str(unique(dataTable.interference_path_length)),' m']; + try + idx = find(dataTable.(loop_var) == loopValue, 1, 'first'); + % dispname = char(equalizer_structure(dataTable.equalizer_structure(idx))); + dispname = [method]; + dispname = [dispname, '/ ',num2str(unique_loop_var(i)) ,' m']; + % dispname = [dispname,'; ',num2str(unique(dataTable.interference_path_length)),' m']; + dispname = [dispname, '/ PAM ', num2str(filterParams.Configurations.pam_level)]; + dispname = [dispname, '/ ', num2str(filterParams.Configurations.symbolrate.*1e-9),' GBd']; + end if plotBoundaries % Plot bounded line [hl, hp] = boundedline(x_values, y_mean, y_bounds, ... - 'alpha', 'transparency', 0.2, ... + 'alpha', 'transparency', 0.1, ... 'cmap', cols(i,:), ... 'nan', 'fill', ... 'orientation', 'vert'); - % Style the main line: thinnest, dotted, no marker + % % Style the main line: thinnest, dotted, no marker set(hl, 'LineWidth', 1, 'LineStyle', '-', 'Marker', 'none', ... 'Color', cols(i,:), 'DisplayName', string(dispname)); + + plt = errorbar(x_values,y_mean,y_lower,y_upper,'LineWidth', 0.1, 'LineStyle', 'none', 'Marker', 'none','Color', cols(i,:), 'DisplayName', string(dispname),'HandleVisibility','off'); % Hide patch (shaded area) from legend set(hp, 'HandleVisibility', 'off','LineStyle',':','LineWidth',0.5,'Marker','none'); - % Add invisible scatter for DataTips - plt = scatter(x_values, y_mean, ... - 'Marker', 'o', 'MarkerEdgeColor', 'none', 'MarkerFaceColor', 'none', ... - 'HandleVisibility', 'off', 'PickableParts', 'all'); + % % Add invisible scatter for DataTips + % plt = scatter(x_values, y_mean, ... + % 'Marker', 'o', 'MarkerEdgeColor', 'none', 'MarkerFaceColor', 'none', ... + % 'HandleVisibility', 'off', 'PickableParts', 'all'); else + plt= plot(x_values,y_mean,'LineWidth', 1, 'LineStyle', '-', 'Marker', 'none', ... - 'Color', cols(i,:), 'DisplayName', string(dispname)); + 'Color', cols(i,:), 'DisplayName', string(dispname)); + % plt= errorbar(x_values,y_mean,y_lower,y_upper,'LineWidth', 1, 'LineStyle', '-', 'Marker', 'none','Color', cols(i,:), 'DisplayName', string(dispname)); + end % Add data tips to the invisible scatter pair_one = {'Run ID', dataTableGrpd_mean.run_id(loopFiltGrpd, :)}; @@ -146,7 +218,7 @@ for i = 1%:numel(unique_loop_var) y_single = double(dataTable.(y_var)(loopFiltSingle, :)); sc = scatter(x_single, y_single, 'Marker', mkr, 'MarkerEdgeColor', cols(i, :), ... - 'LineWidth', 0.5, 'HandleVisibility', 'on', 'DisplayName', string(dispname)); + 'LineWidth', 0.5, 'HandleVisibility', 'off', 'DisplayName', string(dispname)); pair_one = {'Run ID', dataTable.run_id(loopFiltSingle, :)}; pair_two = {'Rate', dataTable.bitrate(loopFiltSingle, :) * 1e-9}; @@ -161,12 +233,14 @@ xlabel(x_var); ylabel(y_var); title([x_var, ' vs. ', y_var]); -if y_var == 'BER' +if string(y_var) == "BER" yline(4e-4, 'LineWidth', 1, 'LineStyle', '--', 'HandleVisibility', 'off'); + yline(3.8e-3, 'LineWidth', 1, 'LineStyle', '--', 'HandleVisibility', 'off'); + yline(2e-2, 'LineWidth', 1, 'LineStyle', '--', 'HandleVisibility', 'off'); ylim([1e-5, 0.1]); end -xlim([15,50]); +xlim([13,35]); % Enable grid and beautify grid on; @@ -243,7 +317,6 @@ resultTable.nRows = groupCount; end - function addDatatips(sc, varargin) % addDatatips Adds custom data tip rows to a scatter plot. % @@ -283,7 +356,6 @@ end end - function cleanedTable = cleanUpTable(inputTable) % cleanUpTable Cleans a MATLAB table where numbers and NaNs are stored as strings or structs. % @@ -335,7 +407,7 @@ for i = 1:numel(varNames) else % Try convert to datetime try - cleanedTable.(varNames{i}) = datetime(col, 'InputFormat', 'yyyy-MM-dd HH:mm:ss.SSSSSS'); + cleanedTable.(varNames{i}) = datetime(col, 'InputFormat', 'yyyy-MM-dd HH:mm:ss'); catch % Leave as string end @@ -391,8 +463,9 @@ for groupIdx = 1:height(groupKeys) continue; end - % Detect outliers - outlierMask = isoutlier(y_values, 'quartiles'); + % Detect outliers in log space + y_log = log10(y_values); + outlierMask = isoutlier(y_log, 'quartiles'); % or 'median', 'grubbs', etc. % If any outliers found, collect their data if any(outlierMask) diff --git a/projects/ECOC_2025/submit_dsp.m b/projects/ECOC_2025/submit_dsp.m index 019056d..183ce2b 100644 --- a/projects/ECOC_2025/submit_dsp.m +++ b/projects/ECOC_2025/submit_dsp.m @@ -12,6 +12,7 @@ arguments savePath options.parallel (1,1) logical = true options.max_occurences = 1; + options.paramstruct = struct(); end if options.parallel @@ -29,7 +30,8 @@ if options.parallel "database_name", database_name, ... 'storage_path', savePath, ... 'append_to_db', 1, ... - 'max_occurences', options.max_occurences ... + 'max_occurences', options.max_occurences, ... + 'parameters', options.paramstruct ... ); output = []; @@ -46,7 +48,8 @@ else "database_name", database_name, ... 'storage_path', savePath, ... 'append_to_db', 1, ... - 'max_occurences', options.max_occurences ... + 'max_occurences', options.max_occurences,... + 'parameters', options.paramstruct ... ); future = []; % No future since it's synchronous diff --git a/projects/HighSpeedExperiment_2024/auswertung MPI/dsp_mpi_database.m b/projects/HighSpeedExperiment_2024/auswertung MPI/dsp_mpi_database.m index c34aa7d..f991d79 100644 --- a/projects/HighSpeedExperiment_2024/auswertung MPI/dsp_mpi_database.m +++ b/projects/HighSpeedExperiment_2024/auswertung MPI/dsp_mpi_database.m @@ -2,17 +2,18 @@ % 1) Find RUN ID's basePath = 'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\'; -database = DBHandler("pathToDB",[basePath,'silas_labor.db']); +% database = DBHandler("pathToDB",[basePath,'silas_labor.db']); +database = DBHandler("type",'mysql'); filterParams = database.tables; filterParams.Configurations = struct( ... - 'bitrate', [], ... %[224,336,360,390,420,448] + 'bitrate', 112e9, ... %[224,336,360,390,420,448] 'db_mode', [], ... 'fiber_length', [], ... 'interference_attenuation',[], ... - 'is_mpi', 0, ... - 'pam_level', [], ... - 'rop_attenuation', 0 ... + 'interference_path_length',300, ... + 'is_mpi', 1, ... + 'pam_level', 4 ... ); selectedFields = {'Runs.run_id',... diff --git a/projects/HighSpeedExperiment_2024/auswertung MPI/dsp_run_id.m b/projects/HighSpeedExperiment_2024/auswertung MPI/dsp_run_id.m index ebb7dfc..816505d 100644 --- a/projects/HighSpeedExperiment_2024/auswertung MPI/dsp_run_id.m +++ b/projects/HighSpeedExperiment_2024/auswertung MPI/dsp_run_id.m @@ -124,7 +124,7 @@ for occ = 1:proc_occ % %%%%% VNLE + DFE %%%% if 0 - eq_vnle_dfe = EQ("Ne",vnle_order,"Nb",[0,0,0],"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",0); + eq_vnle_dfe = EQ("Ne",vnle_order,"Nb",[0,0,0],"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.001,"FFEmu",0,"plotfinal",0,"ideal_dfe",0); eq_post = FFE("epochs_tr",5,"epochs_dd",5,"len_tr",4096*2,"mu_dd",1e-4,"mu_tr",0,"order",2001,"sps",1,"decide",0); [result] = vnle(eq_vnle_dfe,M,Scpe_sig,Symbols,Tx_bits,"precode_mode",duob_mode,"showAnalysis",1,"postFFE",[]);