From ef0a74cb7fb76929947f021431479cbb2857ae69 Mon Sep 17 00:00:00 2001 From: Silas Oettinghaus Date: Mon, 13 Jul 2026 15:25:45 +0200 Subject: [PATCH] work on MPI --- Classes/00_signals/Signal.m | 6 +- Classes/04_DSP/Equalizer/FFE.m | 422 +++++++++--- Functions/EQ_recipes/mpi_recipe.m | 404 +++++++++++ Functions/EQ_recipes/mpi_recipe_dev.m | 625 +++++++++++++----- Functions/EQ_visuals/exportLevelScatterTikz.m | 320 +++++++++ Tests/04_DSP/Equalizer/FFE_test.m | 119 ++++ before_eq_-1.png | Bin 0 -> 256089 bytes .../MPI_revisit/algorithms/PLOT_ber_vs_sir.m | 237 +++++++ .../algorithms/recombine_warehouses.m | 539 +++++++++++++++ .../MPI_revisit/investigate_mpi_algorithms.m | 139 ++-- .../RUN_parallel_analysis.m | 73 ++ .../parallelization_pam4.fig | Bin 0 -> 12500 bytes .../plot_parallelization_vs_sir_pam4.m | 360 ++++++++++ .../Diss/MPI_revisit/plot_mpi_timesignal.m | 310 +-------- .../plots_from_database/plot_mpi_trial.m | 45 +- workerError.mat | Bin 1255 -> 1328 bytes 16 files changed, 2894 insertions(+), 705 deletions(-) create mode 100644 Functions/EQ_recipes/mpi_recipe.m create mode 100644 Functions/EQ_visuals/exportLevelScatterTikz.m create mode 100644 before_eq_-1.png create mode 100644 projects/Diss/MPI_revisit/algorithms/PLOT_ber_vs_sir.m create mode 100644 projects/Diss/MPI_revisit/algorithms/recombine_warehouses.m create mode 100644 projects/Diss/MPI_revisit/parallelization_analysis/RUN_parallel_analysis.m create mode 100644 projects/Diss/MPI_revisit/parallelization_analysis/parallelization_pam4.fig create mode 100644 projects/Diss/MPI_revisit/parallelization_analysis/plot_parallelization_vs_sir_pam4.m diff --git a/Classes/00_signals/Signal.m b/Classes/00_signals/Signal.m index 613b7a0..229bce9 100644 --- a/Classes/00_signals/Signal.m +++ b/Classes/00_signals/Signal.m @@ -24,9 +24,9 @@ classdef Signal obj.signal = signal; obj.signal = obj.signal; obj.fs = options.fs; - - [~,obj.gitSHA] = system('git rev-parse HEAD'); - [~,obj.gitStatus] = system('git status --porcelain'); + % + % [~,obj.gitSHA] = system('git rev-parse HEAD'); + % [~,obj.gitStatus] = system('git status --porcelain'); % [~,obj.gitPatch] = system('git diff'); %%% Stuff for Logbook %%% diff --git a/Classes/04_DSP/Equalizer/FFE.m b/Classes/04_DSP/Equalizer/FFE.m index e624137..0ae09ff 100644 --- a/Classes/04_DSP/Equalizer/FFE.m +++ b/Classes/04_DSP/Equalizer/FFE.m @@ -35,16 +35,19 @@ classdef FFE < handle % A1 moving-average input suppression dc_avg_bufferlength_a1 + dc_avg_update_blocklength_a1 dc_smoothing_a1 % A2 level-dependent residual suppression dc_level_avg_bufferlength_a2 + dc_level_update_blocklength_a2 dc_smoothing_a2 dc_level_weights_a2 % Adaptive DC-tracking loop dc_tracking_mu dc_tracking_adaptive_enabled + dc_tracking_persistence_gain dc_tracking_power_exponent dc_tracking_buffer_len @@ -110,14 +113,17 @@ classdef FFE < handle options.dd_len_fraction = 1; options.dc_avg_bufferlength_a1 = 0; + options.dc_avg_update_blocklength_a1 = 0; options.dc_smoothing_a1 = 0; options.dc_level_avg_bufferlength_a2 = 0; + options.dc_level_update_blocklength_a2 = 0; options.dc_smoothing_a2 = 0; options.dc_level_weights_a2 = 0; options.dc_tracking_mu = 0; options.dc_tracking_adaptive_enabled = false; + options.dc_tracking_persistence_gain = 0; options.dc_tracking_power_exponent = 2; options.dc_tracking_buffer_len = 1; @@ -150,15 +156,19 @@ classdef FFE < handle assert(obj.dc_tracking_buffer_len >= 0); assert(obj.ffe_update_buffer_len >= 0); assert(obj.dc_avg_bufferlength_a1 >= 0); + assert(obj.dc_avg_update_blocklength_a1 >= 0); assert(obj.dc_level_avg_bufferlength_a2 >= 0); + assert(obj.dc_level_update_blocklength_a2 >= 0); obj.e = zeros(obj.order,1); obj.e_dc = 0; obj.error = 0; obj.a2_level_weight_initial_stats = struct(); obj.dc_avg_bufferlength_a1 = floor(obj.dc_avg_bufferlength_a1); + obj.dc_avg_update_blocklength_a1 = floor(obj.dc_avg_update_blocklength_a1); obj.dc_smoothing_a1 = min(max(obj.dc_smoothing_a1,0),1); obj.dc_level_avg_bufferlength_a2 = floor(obj.dc_level_avg_bufferlength_a2); + obj.dc_level_update_blocklength_a2 = floor(obj.dc_level_update_blocklength_a2); obj.dc_smoothing_a2 = min(max(obj.dc_smoothing_a2,0),1); obj.dc_tracking_buffer_len = floor(obj.dc_tracking_buffer_len); obj.ffe_update_buffer_len = floor(obj.ffe_update_buffer_len); @@ -260,6 +270,24 @@ classdef FFE < handle x = [zeros(floor(obj.order/2),1); x; zeros(obj.order,1)]; lambda = mu; + n_symbols = ceil(N / obj.sps); + y = zeros(n_symbols,1); + d_hat = zeros(n_symbols,1); + err = zeros(n_symbols,1); + true_err = zeros(n_symbols,1); + constellation = obj.constellation; + + if obj.adaption_technique == adaption_method.nlms + adaption_code = 1; + elseif obj.adaption_technique == adaption_method.lms + adaption_code = 2; + elseif obj.adaption_technique == adaption_method.rls + adaption_code = 3; + else + builtin("error","FFE:InvalidAdaptionTechnique", ... + "Unsupported FFE adaption technique."); + end + adaption_is_rls = adaption_code == 3; if training mask = ones(obj.order,1); @@ -280,21 +308,31 @@ classdef FFE < handle epochs = 1; end - P_err = 0; - err_prev = 0; - dc_tracking_alpha = obj.dc_tracking_alpha; - dc_tracking_gamma = obj.dc_tracking_gamma; dc_tracking_mu_min = obj.dc_tracking_mu_min; dc_tracking_mu_max = obj.dc_tracking_mu_max; dc_tracking_mu_eff_min = obj.dc_tracking_mu_eff_min; dc_tracking_mu_eff_max = obj.dc_tracking_mu_eff_max; - dc_tracking_power_exponent = obj.dc_tracking_power_exponent; - dc_buffer_enabled = obj.dc_tracking_mu ~= 0 && obj.dc_tracking_buffer_len > 1; + dc_tracking_persistence_gain = 0; + if obj.dc_tracking_adaptive_enabled + dc_tracking_persistence_gain = obj.dc_tracking_persistence_gain; + end + dc_tracking_enabled = obj.dc_tracking_mu ~= 0; + if dc_tracking_enabled + obj.dc_tracking_mu = min(max(obj.dc_tracking_mu,dc_tracking_mu_min),dc_tracking_mu_max); + end + dc_tracking_mu = obj.dc_tracking_mu; + dc_tracking_use_persistence = dc_tracking_persistence_gain > 0; + dc_tracking_base_mu_eff = min(max(dc_tracking_mu,dc_tracking_mu_eff_min),dc_tracking_mu_eff_max); + dc_buffer_enabled = dc_tracking_enabled && obj.dc_tracking_buffer_len > 1; if dc_buffer_enabled - e_dc_buffer = NaN(obj.dc_tracking_buffer_len,1); + dc_tracking_err_buffer = NaN(obj.dc_tracking_buffer_len,1); + dc_tracking_err_buffer_pos = 0; + dc_tracking_err_sum = 0; + dc_tracking_abs_err_sum = 0; + dc_tracking_valid_count = 0; end - ffe_buffer_enabled = obj.ffe_update_buffer_len > 1 && obj.adaption_technique ~= adaption_method.rls; + ffe_buffer_enabled = obj.ffe_update_buffer_len > 1 && ~adaption_is_rls; if ffe_buffer_enabled ffe_update_buffer = NaN(obj.order,obj.ffe_update_buffer_len); end @@ -303,7 +341,10 @@ classdef FFE < handle if dc_avg_enabled dc_avg_buffer_a1 = NaN(obj.dc_avg_bufferlength_a1,1); dc_avg_est_a1 = 0; - dc_avg_update_blocklength_a1 = obj.dc_avg_bufferlength_a1; + dc_avg_update_blocklength_a1 = obj.dc_avg_update_blocklength_a1; + if dc_avg_update_blocklength_a1 <= 0 + dc_avg_update_blocklength_a1 = obj.dc_avg_bufferlength_a1; + end dc_avg_update_blocklength_a1 = max(1,floor(dc_avg_update_blocklength_a1)); dc_avg_input_offset_a1 = floor(obj.order/2); % Hardware-like A1 is causal; dc_smoothing_a1 is reserved for offline variants. @@ -311,12 +352,12 @@ classdef FFE < handle dc_level_enabled = obj.dc_level_avg_bufferlength_a2 > 1 && any(obj.dc_level_weights_a2(:) ~= 0); if dc_level_enabled - if isempty(obj.constellation) + if isempty(constellation) builtin("error","FFE:MissingConstellation", ... "A2 level-dependent MPI suppression requires obj.constellation to be set."); end - n_levels = numel(obj.constellation); + n_levels = numel(constellation); if isscalar(obj.dc_level_weights_a2) dc_level_weight_by_level = repmat(obj.dc_level_weights_a2,n_levels,1); elseif numel(obj.dc_level_weights_a2) == n_levels @@ -325,17 +366,24 @@ classdef FFE < handle builtin("error","FFE:InvalidDCLevelWeights", ... "dc_level_weights_a2 must be scalar or have one entry per constellation level."); end - dc_level_err_buffer = NaN(n_levels,obj.dc_level_avg_bufferlength_a2); + dc_level_buffer_len_a2 = obj.dc_level_avg_bufferlength_a2; + dc_level_err_buffer = NaN(n_levels,dc_level_buffer_len_a2); + dc_level_err_buffer_pos_by_level = zeros(n_levels,1); + dc_level_err_sum_by_level = zeros(n_levels,1); + dc_level_buffer_valid_count_by_level = zeros(n_levels,1); dc_level_mpi_est_by_level = zeros(n_levels,1); dc_level_valid_count_by_level = zeros(n_levels,1); - dc_level_update_blocklength_a2 = obj.dc_level_avg_bufferlength_a2; + dc_level_update_blocklength_a2 = obj.dc_level_update_blocklength_a2; + if dc_level_update_blocklength_a2 <= 0 + dc_level_update_blocklength_a2 = dc_level_buffer_len_a2; + end dc_level_update_blocklength_a2 = max(1,floor(dc_level_update_blocklength_a2)); dc_level_window_future_fraction = obj.dc_smoothing_a2; %#ok % reserved for delayed/offline A2 variants end debug_enabled = obj.save_debug; if debug_enabled - n_symbols_debug = ceil(N / obj.sps); + n_symbols_debug = n_symbols; obj.debug_struct.error = NaN(1,n_symbols_debug); obj.debug_struct.error_first_epoch = NaN(1,n_symbols_debug); obj.debug_struct.main_cursor = NaN(1,n_symbols_debug); @@ -392,15 +440,15 @@ classdef FFE < handle if training d_hat(symbol,1) = d(symbol); - if isempty(obj.constellation) + if isempty(constellation) symbol_idx = NaN; else - [~,symbol_idx] = min(abs(d_hat(symbol) - obj.constellation)); + [~,symbol_idx] = min(abs(d_hat(symbol) - constellation)); end else if ~always_ideal_decision - [~,symbol_idx] = min(abs(y(symbol) - obj.constellation)); % decision for closest constellation point - d_hat(symbol,1) = obj.constellation(symbol_idx); + [~,symbol_idx] = min(abs(y(symbol) - constellation)); % decision for closest constellation point + d_hat(symbol,1) = constellation(symbol_idx); else d_hat(symbol,1) = d(symbol); end @@ -412,26 +460,63 @@ classdef FFE < handle dc_level_mpi_est = dc_level_mpi_est_by_level(symbol_idx); dc_level_valid_count = dc_level_valid_count_by_level(symbol_idx); dc_level_weight = dc_level_weight_by_level(symbol_idx) * ... - min(dc_level_valid_count / obj.dc_level_avg_bufferlength_a2,1); + min(dc_level_valid_count / dc_level_buffer_len_a2,1); y(symbol,1) = y_raw - dc_level_weight * dc_level_mpi_est; if training d_hat(symbol,1) = d(symbol); else if ~always_ideal_decision - [~,symbol_idx] = min(abs(y(symbol) - obj.constellation)); - d_hat(symbol,1) = obj.constellation(symbol_idx); + [~,symbol_idx] = min(abs(y(symbol) - constellation)); + d_hat(symbol,1) = constellation(symbol_idx); else d_hat(symbol,1) = d(symbol); end end - dc_level_err_buffer(dc_level_symbol_idx,:) = circshift(dc_level_err_buffer(dc_level_symbol_idx,:),1,2); - dc_level_err_buffer(dc_level_symbol_idx,1) = mpi_err; + dc_level_err_buffer_pos = dc_level_err_buffer_pos_by_level(dc_level_symbol_idx) + 1; + if dc_level_err_buffer_pos > dc_level_buffer_len_a2 + dc_level_err_buffer_pos = 1; + end + dc_level_err_buffer_pos_by_level(dc_level_symbol_idx) = dc_level_err_buffer_pos; + + dc_level_old_err = dc_level_err_buffer(dc_level_symbol_idx,dc_level_err_buffer_pos); + if isfinite(dc_level_old_err) + dc_level_err_sum_by_level(dc_level_symbol_idx) = ... + dc_level_err_sum_by_level(dc_level_symbol_idx) - dc_level_old_err; + dc_level_buffer_valid_count_by_level(dc_level_symbol_idx) = ... + dc_level_buffer_valid_count_by_level(dc_level_symbol_idx) - 1; + end + + if isfinite(mpi_err) + dc_level_err_buffer(dc_level_symbol_idx,dc_level_err_buffer_pos) = mpi_err; + dc_level_err_sum_by_level(dc_level_symbol_idx) = ... + dc_level_err_sum_by_level(dc_level_symbol_idx) + mpi_err; + dc_level_buffer_valid_count_by_level(dc_level_symbol_idx) = ... + dc_level_buffer_valid_count_by_level(dc_level_symbol_idx) + 1; + else + dc_level_err_buffer(dc_level_symbol_idx,dc_level_err_buffer_pos) = NaN; + end + if mod(symbol,dc_level_update_blocklength_a2) == 0 - dc_level_valid_count_by_level = sum(isfinite(dc_level_err_buffer),2); - dc_level_mpi_est_by_level = mean(dc_level_err_buffer,2,"omitnan"); - dc_level_mpi_est_by_level(dc_level_valid_count_by_level == 0) = 0; + if dc_level_update_blocklength_a2 == 1 + dc_level_valid_count_by_level(dc_level_symbol_idx) = ... + dc_level_buffer_valid_count_by_level(dc_level_symbol_idx); + if dc_level_valid_count_by_level(dc_level_symbol_idx) == 0 + dc_level_mpi_est_by_level(dc_level_symbol_idx) = 0; + else + dc_level_mpi_est_by_level(dc_level_symbol_idx) = ... + dc_level_err_sum_by_level(dc_level_symbol_idx) / ... + dc_level_valid_count_by_level(dc_level_symbol_idx); + end + else + dc_level_valid_count_by_level = dc_level_buffer_valid_count_by_level; + dc_level_has_valid = dc_level_valid_count_by_level > 0; + dc_level_mpi_est_by_level(:) = 0; + dc_level_mpi_est_by_level(dc_level_has_valid) = ... + dc_level_err_sum_by_level(dc_level_has_valid) ./ ... + dc_level_valid_count_by_level(dc_level_has_valid); + end end end @@ -440,10 +525,10 @@ classdef FFE < handle true_err(symbol) = y(symbol) - d(symbol); % Instantaneous error - if training || obj.dd_mode - switch obj.adaption_technique + if 1 %training || obj.dd_mode + switch adaption_code - case adaption_method.nlms + case 1 % mu used as update weight (suggestion: 0.01-0.05; bit higher during tr) normU = ((U.'*U)) + eps; @@ -452,7 +537,7 @@ classdef FFE < handle update = grad * weight; - case adaption_method.lms + case 2 % mu used as update weight (suggestion: 0.001) weight = mu; @@ -461,7 +546,7 @@ classdef FFE < handle - case adaption_method.rls + case 3 % RLS‐Gain: @@ -486,30 +571,87 @@ classdef FFE < handle obj.e = obj.e + update; end - if obj.adaption_technique == adaption_method.rls + if adaption_is_rls obj.P = (1/lambda) * (obj.P - k * (U.' * obj.P)); end - if obj.dc_tracking_mu ~= 0 - if obj.dc_tracking_adaptive_enabled - delta_mu = dc_tracking_gamma * err(symbol) * err_prev * (U.'*U); - obj.dc_tracking_mu = min(max(obj.dc_tracking_mu + delta_mu,dc_tracking_mu_min),dc_tracking_mu_max); - err_prev = err(symbol); - P_err = dc_tracking_alpha*P_err + (1-dc_tracking_alpha)*err(symbol)^2; - dc_tracking_mu_eff = obj.dc_tracking_mu / ((P_err + eps)^dc_tracking_power_exponent); - else - dc_tracking_mu_eff = obj.dc_tracking_mu; - end - - dc_tracking_mu_eff = min(max(dc_tracking_mu_eff,dc_tracking_mu_eff_min),dc_tracking_mu_eff_max); + if dc_tracking_enabled if dc_buffer_enabled - e_dc_buffer(1) = obj.e_dc + dc_tracking_mu_eff * err(symbol); - e_dc_buffer = circshift(e_dc_buffer,1); + dc_tracking_err_buffer_pos = dc_tracking_err_buffer_pos + 1; + if dc_tracking_err_buffer_pos > obj.dc_tracking_buffer_len + dc_tracking_err_buffer_pos = 1; + end + + dc_tracking_old_err = dc_tracking_err_buffer(dc_tracking_err_buffer_pos); + if isfinite(dc_tracking_old_err) + dc_tracking_err_sum = dc_tracking_err_sum - dc_tracking_old_err; + dc_tracking_valid_count = dc_tracking_valid_count - 1; + if dc_tracking_use_persistence + dc_tracking_abs_err_sum = dc_tracking_abs_err_sum - abs(dc_tracking_old_err); + end + end + + dc_tracking_new_err = err(symbol); + if isfinite(dc_tracking_new_err) + dc_tracking_err_buffer(dc_tracking_err_buffer_pos) = dc_tracking_new_err; + dc_tracking_err_sum = dc_tracking_err_sum + dc_tracking_new_err; + dc_tracking_valid_count = dc_tracking_valid_count + 1; + if dc_tracking_use_persistence + dc_tracking_abs_err_sum = dc_tracking_abs_err_sum + abs(dc_tracking_new_err); + end + else + dc_tracking_err_buffer(dc_tracking_err_buffer_pos) = NaN; + end + if mod(symbol,obj.dc_tracking_buffer_len) == 0 - obj.e_dc = mean(e_dc_buffer,"omitnan"); + if dc_tracking_valid_count == 0 + dc_tracking_err_mean = 0; + if dc_tracking_use_persistence + dc_tracking_err_abs_mean = 0; + end + else + dc_tracking_err_mean = dc_tracking_err_sum / dc_tracking_valid_count; + if dc_tracking_use_persistence + dc_tracking_err_abs_mean = dc_tracking_abs_err_sum / dc_tracking_valid_count; + end + end + + if dc_tracking_use_persistence + dc_tracking_persistence_scale = abs(dc_tracking_err_mean) / (dc_tracking_err_abs_mean + eps); + dc_tracking_persistence_scale = min(max(dc_tracking_persistence_scale,0),1); + dc_tracking_mu_eff = dc_tracking_mu * ... + (1 + dc_tracking_persistence_gain * dc_tracking_persistence_scale); + dc_tracking_mu_eff = min(max(dc_tracking_mu_eff,dc_tracking_mu_eff_min),dc_tracking_mu_eff_max); + else + dc_tracking_mu_eff = dc_tracking_base_mu_eff; + end + obj.e_dc = obj.e_dc + dc_tracking_mu_eff * dc_tracking_err_mean; end else - obj.e_dc = obj.e_dc + dc_tracking_mu_eff * err(symbol); + dc_tracking_err_mean = err(symbol); + if isfinite(dc_tracking_err_mean) + if dc_tracking_use_persistence + dc_tracking_err_abs_mean = abs(dc_tracking_err_mean); + dc_tracking_persistence_scale = abs(dc_tracking_err_mean) / ... + (dc_tracking_err_abs_mean + eps); + else + dc_tracking_mu_eff = dc_tracking_base_mu_eff; + end + else + dc_tracking_err_mean = 0; + if dc_tracking_use_persistence + dc_tracking_persistence_scale = 0; + else + dc_tracking_mu_eff = dc_tracking_base_mu_eff; + end + end + if dc_tracking_use_persistence + dc_tracking_persistence_scale = min(max(dc_tracking_persistence_scale,0),1); + dc_tracking_mu_eff = dc_tracking_mu * ... + (1 + dc_tracking_persistence_gain * dc_tracking_persistence_scale); + dc_tracking_mu_eff = min(max(dc_tracking_mu_eff,dc_tracking_mu_eff_min),dc_tracking_mu_eff_max); + end + obj.e_dc = obj.e_dc + dc_tracking_mu_eff * dc_tracking_err_mean; end end end @@ -521,7 +663,7 @@ classdef FFE < handle if debug_enabled && epoch == epochs error_power = err(symbol) * err(symbol)'; - update_power = update.'*update ./ (rms(obj.e) + eps); + update_power = update.'*update ./ (sqrt((obj.e.'*obj.e) / obj.order) + eps); obj.debug_struct.error(1,symbol) = error_power; obj.debug_struct.main_cursor(1,symbol) = abs(obj.e(maincursor_pos)); obj.debug_struct.mu_nlms(1,symbol) = weight; @@ -611,9 +753,7 @@ classdef FFE < handle vars = optimizableVariable("dc_tracking_mu",[1e-5,1e-1],"Transform","log"); if obj.dc_tracking_adaptive_enabled vars = [vars, ... - optimizableVariable("dc_tracking_alpha",[0.85,0.995]), ... - optimizableVariable("dc_tracking_gamma",[1e-7,3e-5],"Transform","log"), ... - optimizableVariable("dc_tracking_power_exponent",[0,2]), ... + optimizableVariable("dc_tracking_persistence_gain",[0,2]), ... optimizableVariable("dc_tracking_mu_eff_max",[1e-3,3e-1],"Transform","log")]; end @@ -630,12 +770,10 @@ classdef FFE < handle best = obj.dc_tracking_optimization.XAtMinObjective; obj.dc_tracking_mu = best.dc_tracking_mu; if obj.dc_tracking_adaptive_enabled - obj.dc_tracking_alpha = best.dc_tracking_alpha; - obj.dc_tracking_gamma = best.dc_tracking_gamma; - obj.dc_tracking_power_exponent = best.dc_tracking_power_exponent; + obj.dc_tracking_persistence_gain = best.dc_tracking_persistence_gain; obj.dc_tracking_mu_eff_max = best.dc_tracking_mu_eff_max; - fprintf("\nFFE DC opt done: dc_tracking_mu=%9.3e, alpha=%6.3f, gamma=%9.3e, p=%5.2f, mu_eff_max=%9.3e, objective=%9.3e\n", ... - obj.dc_tracking_mu,obj.dc_tracking_alpha,obj.dc_tracking_gamma,obj.dc_tracking_power_exponent,obj.dc_tracking_mu_eff_max,obj.dc_tracking_optimization.MinObjective); + fprintf("\nFFE DC opt done: dc_tracking_mu=%9.3e, persistence_gain=%6.3f, mu_eff_max=%9.3e, objective=%9.3e\n", ... + obj.dc_tracking_mu,obj.dc_tracking_persistence_gain,obj.dc_tracking_mu_eff_max,obj.dc_tracking_optimization.MinObjective); else fprintf("\nFFE DC opt done: dc_tracking_mu=%9.3e, objective=%9.3e\n", ... obj.dc_tracking_mu,obj.dc_tracking_optimization.MinObjective); @@ -668,34 +806,52 @@ classdef FFE < handle [initial_weights,stats] = obj.a2LevelWeightInitialGuess(x_opt,d_opt); current_weights = obj.expandA2LevelWeights(n_levels); - initial_matrix = initial_weights(:).'; + initial_matrix = [zeros(1,n_levels); initial_weights(:).']; if any(current_weights ~= 0) initial_matrix = [initial_matrix; current_weights(:).']; end initial_matrix = min(max(initial_matrix,0),obj.a2_level_weight_max); initial_matrix = unique(initial_matrix,"rows","stable"); initial_x = array2table(initial_matrix,"VariableNames",cellstr(var_names)); + [baseline_ber,baseline_errors] = obj.a2LevelWeightBer(initial_x(1,:),x_opt,d_opt); + [x_val,d_val,N_val] = obj.a2ValidationSignals(x,d,N_opt); + stats.baseline_ber = baseline_ber; + stats.baseline_errors = baseline_errors; obj.a2_level_weight_initial_stats = stats; obj.a2_level_weight_optimization_iter = 0; max_evals = max(obj.a2_level_weight_optimization_max_evals,height(initial_x)); fprintf("FFE A2 opt uses fixed mu_tr=%9.3e, mu_dd=%9.3e on %d samples / %d symbols\n", ... obj.mu_tr,obj.mu_dd,N_opt,numel(d_opt)); - fprintf("FFE A2 opt init: var_slope=%9.3e, weights=%s\n", ... - stats.variance_slope,mat2str(initial_weights(:).',3)); + fprintf("FFE A2 opt validation uses %d samples / %d symbols\n",N_val,numel(d_val)); + fprintf("FFE A2 opt init: baseline BER=%9.3e (%d errors), var_slope=%9.3e, weights=%s\n", ... + baseline_ber,baseline_errors,stats.variance_slope,mat2str(initial_weights(:).',3)); - obj.a2_level_weight_optimization = bayesopt(@(p)obj.a2LevelWeightObjective(p,x_opt,d_opt),vars, ... + old_rng = rng; + cleanup_rng = onCleanup(@()rng(old_rng)); + rng(42,"twister"); + obj.a2_level_weight_optimization = bayesopt(@(p)obj.a2LevelWeightObjective(p,x_opt,d_opt,baseline_ber),vars, ... "MaxObjectiveEvaluations",max_evals, ... "InitialX",initial_x, ... "AcquisitionFunctionName","expected-improvement-plus", ... - "IsObjectiveDeterministic",false, ... + "IsObjectiveDeterministic",true, ... "Verbose",0, ... "PlotFcn",[]); + clear cleanup_rng - best = obj.a2_level_weight_optimization.XAtMinObjective; + [best,best_validation_ber,best_validation_errors] = obj.selectA2LevelWeightsByValidation( ... + obj.a2_level_weight_optimization.XTrace, ... + obj.a2_level_weight_optimization.ObjectiveTrace, ... + x_val,d_val,initial_x); + best_opt = obj.a2_level_weight_optimization.XAtMinObjective; + best_opt_weights = obj.a2LevelWeightsFromParams(best_opt); obj.dc_level_weights_a2 = obj.a2LevelWeightsFromParams(best); - fprintf("\nFFE A2 opt done: weights=%s, BER=%9.3e\n", ... - mat2str(obj.dc_level_weights_a2(:).',3),obj.a2_level_weight_optimization.MinObjective); + obj.a2_level_weight_initial_stats.validation_ber = best_validation_ber; + obj.a2_level_weight_initial_stats.validation_errors = best_validation_errors; + obj.a2_level_weight_initial_stats.validation_weights = obj.dc_level_weights_a2; + fprintf("\nFFE A2 opt done: opt_weights=%s, opt_obj=%9.3e, validation_weights=%s, validation_BER=%9.3e (%d errors)\n", ... + mat2str(best_opt_weights(:).',3),obj.a2_level_weight_optimization.MinObjective, ... + mat2str(obj.dc_level_weights_a2(:).',3),best_validation_ber,best_validation_errors); end function [x_opt,d_opt,N_opt] = optimizationSignals(obj,x,d,opt_len) @@ -719,6 +875,47 @@ classdef FFE < handle d_opt = d(1:n_symbols); end + function [x_val,d_val,N_val] = a2ValidationSignals(obj,x,d,N_opt) + N_available = min(numel(x),numel(d) * obj.sps); + N_val = min(N_opt,N_available); + if N_available <= N_opt + [x_val,d_val,N_val] = obj.optimizationSignals(x,d,N_opt); + return + end + + start_symbol = floor((N_available - N_val) / obj.sps) + 1; + start_sample = (start_symbol - 1) * obj.sps + 1; + N_val = obj.sps * floor((N_available - start_sample + 1) / obj.sps); + N_val = max(obj.sps,N_val); + n_symbols = N_val / obj.sps; + x_val = x(start_sample:start_sample+N_val-1); + d_val = d(start_symbol:start_symbol+n_symbols-1); + end + + function [best_params,best_ber,best_errors] = selectA2LevelWeightsByValidation(obj,x_trace,objective_trace,x_val,d_val,initial_x) + objective_trace = objective_trace(:); + objective_trace(~isfinite(objective_trace)) = inf; + [~,sort_idx] = sort(objective_trace,"ascend"); + n_trace_candidates = min(8,numel(sort_idx)); + candidate_x = x_trace(sort_idx(1:n_trace_candidates),:); + candidate_x = [initial_x; candidate_x]; + candidate_x = unique(candidate_x,"rows","stable"); + + n_candidates = height(candidate_x); + validation_ber = inf(n_candidates,1); + validation_errors = nan(n_candidates,1); + for candidate_idx = 1:n_candidates + [validation_ber(candidate_idx),validation_errors(candidate_idx)] = ... + obj.a2LevelWeightBer(candidate_x(candidate_idx,:),x_val,d_val); + end + + [best_ber,best_idx] = min(validation_ber); + best_errors = validation_errors(best_idx); + best_params = candidate_x(best_idx,:); + fprintf("FFE A2 validation: checked %d candidates, best weights=%s, BER=%9.3e, errors=%d\n", ... + n_candidates,mat2str(obj.a2LevelWeightsFromParams(best_params).',3),best_ber,best_errors); + end + function objective = muObjective(obj,params,x,d) old_debug = obj.save_debug; old_dc_tracking_mu = obj.dc_tracking_mu; @@ -762,7 +959,27 @@ classdef FFE < handle obj.dc_tracking_mu = old_dc_tracking_mu; end - function objective = a2LevelWeightObjective(obj,params,x,d) + function objective = a2LevelWeightObjective(obj,params,x,d,baseline_ber) + if nargin < 5 || ~isfinite(baseline_ber) + baseline_ber = inf; + end + + [ber,errors] = obj.a2LevelWeightBer(params,x,d); + objective = ber; + if isfinite(baseline_ber) + objective = objective + max(0,ber - baseline_ber); + end + if ~isfinite(objective) + objective = inf; + end + + obj.a2_level_weight_optimization_iter = obj.a2_level_weight_optimization_iter + 1; + weights = obj.a2LevelWeightsFromParams(params); + fprintf("\rFFE A2 opt %02d: weights=%s, BER=%9.3e, obj=%9.3e, errors=%d", ... + obj.a2_level_weight_optimization_iter,mat2str(weights(:).',3),ber,objective,errors); + end + + function [ber,errors] = a2LevelWeightBer(obj,params,x,d) state = obj.captureObjectiveState(); cleanup = onCleanup(@()obj.restoreObjectiveState(state)); @@ -782,14 +999,6 @@ classdef FFE < handle end [ber,errors] = obj.berObjective(signal,d); - objective = ber; - if ~isfinite(objective) - objective = inf; - end - - obj.a2_level_weight_optimization_iter = obj.a2_level_weight_optimization_iter + 1; - fprintf("\rFFE A2 opt %02d: weights=%s, BER=%9.3e, errors=%d", ... - obj.a2_level_weight_optimization_iter,mat2str(obj.dc_level_weights_a2(:).',3),ber,errors); end function objective = dcTrackingObjective(obj,params,x,d) @@ -821,8 +1030,8 @@ classdef FFE < handle obj.dc_tracking_optimization_iter = obj.dc_tracking_optimization_iter + 1; if obj.dc_tracking_adaptive_enabled - fprintf("\rFFE DC opt %02d: dc_tracking_mu=%9.3e, alpha=%6.3f, gamma=%9.3e, p=%5.2f, mu_eff_max=%9.3e, BER=%9.3e, delay=%7.0f, corr=%6.3f, obj=%9.3e, errors=%d", ... - obj.dc_tracking_optimization_iter,params.dc_tracking_mu,params.dc_tracking_alpha,params.dc_tracking_gamma,params.dc_tracking_power_exponent,params.dc_tracking_mu_eff_max, ... + fprintf("\rFFE DC opt %02d: dc_tracking_mu=%9.3e, persistence_gain=%6.3f, mu_eff_max=%9.3e, BER=%9.3e, delay=%7.0f, corr=%6.3f, obj=%9.3e, errors=%d", ... + obj.dc_tracking_optimization_iter,params.dc_tracking_mu,params.dc_tracking_persistence_gain,params.dc_tracking_mu_eff_max, ... ber,delay_symbols,delay_corr,objective,errors); else fprintf("\rFFE DC opt %02d: dc_tracking_mu=%9.3e, BER=%9.3e, delay=%7.0f, corr=%6.3f, obj=%9.3e, errors=%d", ... @@ -835,14 +1044,8 @@ classdef FFE < handle if any(var_names == "dc_tracking_mu") obj.dc_tracking_mu = params.dc_tracking_mu; end - if any(var_names == "dc_tracking_alpha") - obj.dc_tracking_alpha = params.dc_tracking_alpha; - end - if any(var_names == "dc_tracking_gamma") - obj.dc_tracking_gamma = params.dc_tracking_gamma; - end - if any(var_names == "dc_tracking_power_exponent") - obj.dc_tracking_power_exponent = params.dc_tracking_power_exponent; + if any(var_names == "dc_tracking_persistence_gain") + obj.dc_tracking_persistence_gain = params.dc_tracking_persistence_gain; end if any(var_names == "dc_tracking_mu_eff_max") obj.dc_tracking_mu_eff_max = params.dc_tracking_mu_eff_max; @@ -950,6 +1153,51 @@ classdef FFE < handle "initial_weights",weights); end + function [e_dc_next,stats] = dcTrackingBlockUpdate(obj,e_dc_current,err_block,options) + arguments + obj + e_dc_current (1,1) double + err_block (:,1) double + options.mu_dc (1,1) double = NaN + options.persistence_gain (1,1) double = 0 + options.mu_eff_min (1,1) double = NaN + options.mu_eff_max (1,1) double = NaN + end + + if isnan(options.mu_dc) + options.mu_dc = obj.dc_tracking_mu; + end + if isnan(options.mu_eff_min) + options.mu_eff_min = obj.dc_tracking_mu_eff_min; + end + if isnan(options.mu_eff_max) + options.mu_eff_max = obj.dc_tracking_mu_eff_max; + end + + valid_err = err_block(isfinite(err_block)); + if isempty(valid_err) + err_mean = 0; + err_abs_mean = 0; + else + err_mean = mean(valid_err,"omitnan"); + err_abs_mean = mean(abs(valid_err),"omitnan"); + end + + persistence_scale = abs(err_mean) / (err_abs_mean + eps); + persistence_scale = min(max(persistence_scale,0),1); + mu_eff = options.mu_dc * (1 + max(options.persistence_gain,0) * persistence_scale); + mu_eff = min(max(mu_eff,options.mu_eff_min),options.mu_eff_max); + update = mu_eff * err_mean; + e_dc_next = e_dc_current + update; + + stats = struct( ... + "err_mean",err_mean, ... + "err_abs_mean",err_abs_mean, ... + "persistence_scale",persistence_scale, ... + "mu_eff",mu_eff, ... + "update",update); + end + function state = captureObjectiveState(obj) state.e = obj.e; state.e_dc = obj.e_dc; @@ -959,6 +1207,7 @@ classdef FFE < handle state.dc_tracking_mu = obj.dc_tracking_mu; state.dc_tracking_alpha = obj.dc_tracking_alpha; state.dc_tracking_gamma = obj.dc_tracking_gamma; + state.dc_tracking_persistence_gain = obj.dc_tracking_persistence_gain; state.dc_tracking_power_exponent = obj.dc_tracking_power_exponent; state.dc_tracking_mu_eff_max = obj.dc_tracking_mu_eff_max; state.dc_level_weights_a2 = obj.dc_level_weights_a2; @@ -974,6 +1223,7 @@ classdef FFE < handle obj.dc_tracking_mu = state.dc_tracking_mu; obj.dc_tracking_alpha = state.dc_tracking_alpha; obj.dc_tracking_gamma = state.dc_tracking_gamma; + obj.dc_tracking_persistence_gain = state.dc_tracking_persistence_gain; obj.dc_tracking_power_exponent = state.dc_tracking_power_exponent; obj.dc_tracking_mu_eff_max = state.dc_tracking_mu_eff_max; obj.dc_level_weights_a2 = state.dc_level_weights_a2; @@ -989,8 +1239,8 @@ classdef FFE < handle rx_bits = mapper.demap(eq_signal_hd); tx_bits = mapper.demap(tx_symbols); [~,errors,ber,~] = calc_ber(rx_bits.signal,tx_bits.signal, ... - "skip_front",10, ... - "skip_end",10, ... + "skip_front",1000, ... + "skip_end",0, ... "returnErrorLocation",1); end diff --git a/Functions/EQ_recipes/mpi_recipe.m b/Functions/EQ_recipes/mpi_recipe.m new file mode 100644 index 0000000..cb542a2 --- /dev/null +++ b/Functions/EQ_recipes/mpi_recipe.m @@ -0,0 +1,404 @@ +function output = mpi_recipe_dev(Scpe_sig_raw, Symbols, Tx_bits, options) +%mpi_recipe_dev Minimal example recipe for the DSP job framework. +% This recipe intentionally performs only light preprocessing and records +% summary values. It demonstrates the recipe interface without running a +% full equalizer chain. + +arguments + Scpe_sig_raw + Symbols + Tx_bits + options.fsym + options.M + options.duob_mode + options.dataTable table + options.userParameters struct = struct() + options.debug_plots (1,1) logical = false +end + +Scpe_sig = preprocessSignal(Scpe_sig_raw, Symbols, options.fsym, ... + "mode", "auto", ... + "debug_plots", options.debug_plots); +output = struct(); + +%% conventional FFE +eq_core_settings = { ... + "sps", 2, ... + "order", 25, ... + "decide", 0, ... + "adaption_technique", "nlms"}; + +eq_training_settings = { ... + "len_tr", 4096, ... + "epochs_tr", 5, ... + "mu_tr", 0.04}; + +eq_dd_settings = { ... + "dd_mode", 1, ... + "epochs_dd", 3, ... + "mu_dd", 0.012}; + +eq_a1_settings = { ... + "dc_smoothing_a1", 0, ... + "dc_avg_bufferlength_a1", 0, ... + "dc_avg_update_blocklength_a1", 1}; + +eq_a2_settings = { ... + "dc_smoothing_a2", 0, ... + "dc_level_avg_bufferlength_a2", 0, ... + "dc_level_update_blocklength_a2", 0, ... + "dc_level_weights_a2", [0.6 0.6 0.6 0.6]}; + +eq_dc_tracking_settings = { ... + "dc_tracking_mu", 0, ... + "dc_tracking_adaptive_enabled", 0, ... + "dc_tracking_persistence_gain", 0, ... + "dc_tracking_buffer_len", 0}; + +eq_ffe_update_settings = { ... + "ffe_update_buffer_len", 1}; + +eq_optimizer_settings = { ... + "optmize_mus", 0, ... + "plot_mu_optimization", options.debug_plots, ... + "optimize_dc_tracking_params", 0, ... + "optimize_a2_level_weights", 0, ... + "a2_level_weight_optimization_len", 2^15, ... + "a2_level_weight_optimization_max_evals", 30, ... + "a2_level_weight_max", 1}; + +eq_debug_settings = { ... + "save_debug", false}; + +eq_settings = [ ... + eq_core_settings, ... + eq_training_settings, ... + eq_dd_settings, ... + eq_a1_settings, ... + eq_a2_settings, ... + eq_dc_tracking_settings, ... + eq_ffe_update_settings, ... + eq_optimizer_settings, ... + eq_debug_settings]; + +eq_ffe = FFE(eq_settings{:}); + +if 1 + + [ffe_results,equalized_signal] = ffe(eq_ffe, options.M, Scpe_sig, Symbols, Tx_bits, ... + "precode_mode", options.duob_mode, ... + 'showAnalysis', options.debug_plots, ... + "postFFE", [], ... + "eth_style_symbol_mapping", 0); + + ffe_results.metrics.print("description",sprintf('Immediate A2; SIR %d dB',options.dataTable.sir)); + output.conventional_ffe = ffe_results; + +end + +if options.debug_plots + showLevelScatter(Scpe_sig_raw, Symbols, ... + "fsym", options.fsym, ... + "fignum", 400, ... + "normalize", true); + + [~, avg_for_lvl] = showLevelScatter(equalized_signal, Symbols, ... + "fsym", options.fsym, ... + "fignum", 401, ... + "normalize", true); + +end + + +%% A2 +eq_core_settings = { ... + "sps", 2, ... + "order", 25, ... + "decide", 0, ... + "adaption_technique", "nlms"}; + +eq_training_settings = { ... + "len_tr", 4096, ... + "epochs_tr", 5, ... + "mu_tr", 0.04}; + +eq_dd_settings = { ... + "dd_mode", 1, ... + "epochs_dd", 3, ... + "mu_dd", 0.012}; + +eq_a1_settings = { ... + "dc_smoothing_a1", 0, ... + "dc_avg_bufferlength_a1", 0, ... + "dc_avg_update_blocklength_a1", 1}; + +eq_a2_settings = { ... + "dc_smoothing_a2", 1, ... + "dc_level_avg_bufferlength_a2", 256, ... + "dc_level_update_blocklength_a2", options.userParameters.block_update, ... + "dc_level_weights_a2", [0.6 0.6 0.6 0.6]}; + +eq_dc_tracking_settings = { ... + "dc_tracking_mu", 0, ... + "dc_tracking_adaptive_enabled", 0, ... + "dc_tracking_persistence_gain", 0, ... + "dc_tracking_buffer_len", 0}; + +eq_ffe_update_settings = { ... + "ffe_update_buffer_len", 1}; + +eq_optimizer_settings = { ... + "optmize_mus", 0, ... + "plot_mu_optimization", options.debug_plots, ... + "optimize_dc_tracking_params", 0, ... + "optimize_a2_level_weights", 1, ... + "a2_level_weight_optimization_len", 2^15, ... + "a2_level_weight_optimization_max_evals", 30, ... + "a2_level_weight_max", 1}; + +eq_debug_settings = { ... + "save_debug", false}; + +eq_settings = [ ... + eq_core_settings, ... + eq_training_settings, ... + eq_dd_settings, ... + eq_a1_settings, ... + eq_a2_settings, ... + eq_dc_tracking_settings, ... + eq_ffe_update_settings, ... + eq_optimizer_settings, ... + eq_debug_settings]; + +eq_ffe = FFE(eq_settings{:}); + +if 1 + + [ffe_results,equalized_signal] = ffe(eq_ffe, options.M, Scpe_sig, Symbols, Tx_bits, ... + "precode_mode", options.duob_mode, ... + 'showAnalysis', options.debug_plots, ... + "postFFE", [], ... + "eth_style_symbol_mapping", 0); + + ffe_results.metrics.print("description",sprintf('Immediate A2; SIR %d dB',options.dataTable.sir)); + output.a2_immediate_updates = ffe_results; + +end + +if options.debug_plots + showLevelScatter(Scpe_sig_raw, Symbols, ... + "fsym", options.fsym, ... + "fignum", 400, ... + "normalize", true); + + [~, avg_for_lvl] = showLevelScatter(equalized_signal, Symbols, ... + "fsym", options.fsym, ... + "fignum", 401, ... + "normalize", true); + +end + +%% A1 + +eq_a1_settings = { ... + "dc_smoothing_a1", 1 ... + "dc_avg_bufferlength_a1", 2048, ... + "dc_avg_update_blocklength_a1", options.userParameters.block_update}; + +eq_a2_settings = { ... + "dc_smoothing_a2", 0, ... + "dc_level_avg_bufferlength_a2", 0, ... + "dc_level_update_blocklength_a2", 0, ... + "dc_level_weights_a2", [0.6 0.6 0.6 0.6]}; + +eq_optimizer_settings = { ... + "optmize_mus", 0, ... + "plot_mu_optimization", options.debug_plots, ... + "optimize_dc_tracking_params", 0, ... + "optimize_a2_level_weights", 0, ... + "a2_level_weight_optimization_len", 2^15, ... + "a2_level_weight_optimization_max_evals", 30, ... + "a2_level_weight_max", 1}; + +eq_debug_settings = { ... + "save_debug", false}; + +eq_settings = [ ... + eq_core_settings, ... + eq_training_settings, ... + eq_dd_settings, ... + eq_a1_settings, ... + eq_a2_settings, ... + eq_dc_tracking_settings, ... + eq_ffe_update_settings, ... + eq_optimizer_settings, ... + eq_debug_settings]; + +eq_ffe = FFE(eq_settings{:}); + +if 1 + + [ffe_results,equalized_signal] = ffe(eq_ffe, options.M, Scpe_sig, Symbols, Tx_bits, ... + "precode_mode", options.duob_mode, ... + 'showAnalysis', options.debug_plots, ... + "postFFE", [], ... + "eth_style_symbol_mapping", 0); + + ffe_results.metrics.print("description",sprintf('Immediate A1; SIR %d dB',options.dataTable.sir)); + output.a1_immediate_updates = ffe_results; + +end + +%% Tracking + +eq_core_settings = { ... + "sps", 2, ... + "order", 25, ... + "decide", 0, ... + "adaption_technique", "nlms"}; + +eq_training_settings = { ... + "len_tr", 4096, ... + "epochs_tr", 5, ... + "mu_tr", 0.04}; + +eq_dd_settings = { ... + "dd_mode", 1, ... + "epochs_dd", 3, ... + "mu_dd", 0.012}; + +eq_a1_settings = { ... + "dc_smoothing_a1", 0, ... + "dc_avg_bufferlength_a1", 0, ... + "dc_avg_update_blocklength_a1", 1}; + +eq_a2_settings = { ... + "dc_smoothing_a2", 0, ... + "dc_level_avg_bufferlength_a2", 0, ... + "dc_level_update_blocklength_a2", 0, ... + "dc_level_weights_a2", [0.6 0.6 0.6 0.6]}; + +eq_dc_tracking_settings = { ... + "dc_tracking_mu", 0.002, ... + "dc_tracking_adaptive_enabled", 0, ... + "dc_tracking_persistence_gain", 0, ... + "dc_tracking_buffer_len", options.userParameters.block_update}; + +eq_ffe_update_settings = { ... + "ffe_update_buffer_len", 1}; + +eq_optimizer_settings = { ... + "optmize_mus", 0, ... + "plot_mu_optimization", options.debug_plots, ... + "optimize_dc_tracking_params", 1, ... + "optimize_a2_level_weights", 0, ... + "a2_level_weight_optimization_len", 2^15, ... + "a2_level_weight_optimization_max_evals", 30, ... + "a2_level_weight_max", 1}; + +eq_debug_settings = { ... + "save_debug", false}; + +eq_settings = [ ... + eq_core_settings, ... + eq_training_settings, ... + eq_dd_settings, ... + eq_a1_settings, ... + eq_a2_settings, ... + eq_dc_tracking_settings, ... + eq_ffe_update_settings, ... + eq_optimizer_settings, ... + eq_debug_settings]; + +eq_ffe = FFE(eq_settings{:}); + +if 1 + + [ffe_results,equalized_signal] = ffe(eq_ffe, options.M, Scpe_sig, Symbols, Tx_bits, ... + "precode_mode", options.duob_mode, ... + 'showAnalysis', options.debug_plots, ... + "postFFE", [], ... + "eth_style_symbol_mapping", 0); + + ffe_results.metrics.print("description",sprintf('Immediate A2; SIR %d dB',options.dataTable.sir)); + output.tracking_fixmu_immediate_updates = ffe_results; + +end + +%% Tracking Adaptive + +eq_core_settings = { ... + "sps", 2, ... + "order", 25, ... + "decide", 0, ... + "adaption_technique", "nlms"}; + +eq_training_settings = { ... + "len_tr", 4096, ... + "epochs_tr", 5, ... + "mu_tr", 0.04}; + +eq_dd_settings = { ... + "dd_mode", 1, ... + "epochs_dd", 3, ... + "mu_dd", 0.012}; + +eq_a1_settings = { ... + "dc_smoothing_a1", 0, ... + "dc_avg_bufferlength_a1", 0, ... + "dc_avg_update_blocklength_a1", 1}; + +eq_a2_settings = { ... + "dc_smoothing_a2", 0, ... + "dc_level_avg_bufferlength_a2", 0, ... + "dc_level_update_blocklength_a2", 0, ... + "dc_level_weights_a2", [0.6 0.6 0.6 0.6]}; + +eq_dc_tracking_settings = { ... + "dc_tracking_mu", 0.002, ... + "dc_tracking_adaptive_enabled", 1, ... + "dc_tracking_persistence_gain", 0, ... + "dc_tracking_buffer_len", options.userParameters.block_update}; + +eq_ffe_update_settings = { ... + "ffe_update_buffer_len", 1}; + +eq_optimizer_settings = { ... + "optmize_mus", 0, ... + "plot_mu_optimization", options.debug_plots, ... + "optimize_dc_tracking_params", 1, ... + "optimize_a2_level_weights", 0, ... + "a2_level_weight_optimization_len", 2^15, ... + "a2_level_weight_optimization_max_evals", 30, ... + "a2_level_weight_max", 1}; + +eq_debug_settings = { ... + "save_debug", false}; + +eq_settings = [ ... + eq_core_settings, ... + eq_training_settings, ... + eq_dd_settings, ... + eq_a1_settings, ... + eq_a2_settings, ... + eq_dc_tracking_settings, ... + eq_ffe_update_settings, ... + eq_optimizer_settings, ... + eq_debug_settings]; + +eq_ffe = FFE(eq_settings{:}); + +if 1 + + [ffe_results,equalized_signal] = ffe(eq_ffe, options.M, Scpe_sig, Symbols, Tx_bits, ... + "precode_mode", options.duob_mode, ... + 'showAnalysis', options.debug_plots, ... + "postFFE", [], ... + "eth_style_symbol_mapping", 0); + + ffe_results.metrics.print("description",sprintf('Immediate A2; SIR %d dB',options.dataTable.sir)); + output.tracking_adaptive_immediate_updates = ffe_results; + +end + +end diff --git a/Functions/EQ_recipes/mpi_recipe_dev.m b/Functions/EQ_recipes/mpi_recipe_dev.m index bb0fc13..bf50562 100644 --- a/Functions/EQ_recipes/mpi_recipe_dev.m +++ b/Functions/EQ_recipes/mpi_recipe_dev.m @@ -4,202 +4,469 @@ function output = mpi_recipe_dev(Scpe_sig_raw, Symbols, Tx_bits, options) % summary values. It demonstrates the recipe interface without running a % full equalizer chain. - arguments - Scpe_sig_raw - Symbols - Tx_bits - options.fsym - options.M - options.duob_mode - options.dataTable table - options.userParameters struct = struct() - options.debug_plots (1,1) logical = false - end +arguments + Scpe_sig_raw + Symbols + Tx_bits + options.fsym + options.M + options.duob_mode + options.dataTable table + options.userParameters struct = struct() + options.debug_plots (1,1) logical = false +end - Scpe_sig = preprocessSignal(Scpe_sig_raw, Symbols, options.fsym, ... - "mode", "auto", ... - "debug_plots", options.debug_plots); - output = struct(); +Scpe_sig = preprocessSignal(Scpe_sig_raw, Symbols, options.fsym, ... + "mode", "auto", ... + "debug_plots", options.debug_plots); +output = struct(); + +%% conventional FFE +eq_core_settings = { ... + "sps", 2, ... + "order", 50, ... + "decide", 0, ... + "adaption_technique", "nlms"}; + +eq_training_settings = { ... + "len_tr", 4096, ... + "epochs_tr", 5, ... + "mu_tr", 0.04}; + +eq_dd_settings = { ... + "dd_mode", 1, ... + "epochs_dd", 3, ... + "mu_dd", 0.012}; + +eq_a1_settings = { ... + "dc_smoothing_a1", 0, ... + "dc_avg_bufferlength_a1", 0, ... + "dc_avg_update_blocklength_a1", 1}; + +eq_a2_settings = { ... + "dc_smoothing_a2", 0, ... + "dc_level_avg_bufferlength_a2", 0, ... + "dc_level_update_blocklength_a2", 0, ... + "dc_level_weights_a2", [0.6 0.6 0.6 0.6]}; + +eq_dc_tracking_settings = { ... + "dc_tracking_mu", 0, ... + "dc_tracking_adaptive_enabled", 0, ... + "dc_tracking_persistence_gain", 0, ... + "dc_tracking_buffer_len", 1}; + +eq_ffe_update_settings = { ... + "ffe_update_buffer_len", 0}; + +eq_optimizer_settings = { ... + "optmize_mus", 0, ... + "plot_mu_optimization", options.debug_plots, ... + "optimize_dc_tracking_params", 0, ... + "optimize_a2_level_weights", 0, ... + "a2_level_weight_optimization_len", 2^15, ... + "a2_level_weight_optimization_max_evals", 30, ... + "a2_level_weight_max", 1}; + +eq_debug_settings = { ... + "save_debug", false}; + +eq_settings = [ ... + eq_core_settings, ... + eq_training_settings, ... + eq_dd_settings, ... + eq_a1_settings, ... + eq_a2_settings, ... + eq_dc_tracking_settings, ... + eq_ffe_update_settings, ... + eq_optimizer_settings, ... + eq_debug_settings]; + +eq_ffe = FFE(eq_settings{:}); + +% ffe_order_ffe = [50, 0, 0]; +% mu_ffe = [0.0001, 0.0008, 0.001]; +% mu_dfe = 0.0004; +% mu_ffe = [0, 0,0]; +% mu_dfe = 0.0004; +% mu_dc = 0.005; +% eq_ffe = EQ("Ne",ffe_order_ffe,"Nb",[0,0,0],"training_length",4096,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.00,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",0); + + +if 1 + + [ffe_results,equalized_signal] = ffe(eq_ffe, options.M, Scpe_sig, Symbols, Tx_bits, ... + "precode_mode", options.duob_mode, ... + 'showAnalysis', options.debug_plots, ... + "postFFE", [], ... + "eth_style_symbol_mapping", 0); + + ffe_results.metrics.print("description",sprintf('Immediate A2; SIR %d dB',options.dataTable.sir)); + output.conventional_ffe = ffe_results; + +end + +if 1 - eq_core_settings = { ... - "sps", 2, ... - "order", 25, ... - "decide", 0, ... - "adaption_technique", "nlms"}; + showLevelScatter(Scpe_sig_raw, Symbols, ... + "fsym", options.fsym, ... + "fignum", 400, ... + "normalize", true, ... + "debug_plots", false, ... + "showPlot", true, ... + "showStdAnnotations", true, ... + "yLimits", [-2.5 2.5], ... + "xLimits",[0 2.3],... + "scatterAlpha", 0.25, ... + "scatterSize", 1, ... + "avgLineMaxPoints", 500, ... + "avgLineSmoothWindow", 5); - eq_training_settings = { ... - "len_tr", 4096, ... - "epochs_tr", 5, ... - "mu_tr", 0.04}; - eq_dd_settings = { ... - "dd_mode", 1, ... - "epochs_dd", 5, ... - "mu_dd", 0.012}; + exportName = "before_eq"; + exportDir = "C:/Users/Silas/Documents/6971e0b65b380ca6d71c837f/04_Experimental_Evaluation/tikz/mpi"; + pngFile = fullfile(exportDir, exportName + "_img.png"); % absolute filesystem output + tikzFile = fullfile(exportDir, exportName + ".tikz"); % absolute filesystem output + pngTikzPath = "04_Experimental_Evaluation/tikz/mpi/" + exportName + "_img.png"; % path written into TikZ + figure(400); + exportLevelScatterTikz(gca, pngFile, tikzFile, pngTikzPath, ... + "resolutionDpi", 150, ... + "generatedBy", "mpi_recipe_dev.m"); - eq_a1_settings = { ... - "dc_smoothing_a1", 0, ... - "dc_avg_bufferlength_a1", 0}; + showLevelScatter(equalized_signal.*-1, Symbols, ... + "fsym", options.fsym, ... + "fignum", 401, ... + "normalize", true, ... + "debug_plots", false, ... + "showPlot", true, ... + "showStdAnnotations", true, ... + "yLimits", [-2.5 2.5], ... + "xLimits",[0 2.3],... + "scatterAlpha", 0.25, ... + "scatterSize", 1, ... + "avgLineMaxPoints", 500, ... + "avgLineSmoothWindow", 5); - eq_a2_settings = { ... - "dc_smoothing_a2", 0, ... - "dc_level_avg_bufferlength_a2", 0, ... - "dc_level_weights_a2", [0.692 0.979 0.98 0.138]}; + exportName = "after_ffe_eq"; + pngFile = fullfile(exportDir, exportName + "_img.png"); % absolute filesystem output + tikzFile = fullfile(exportDir, exportName + ".tikz"); % absolute filesystem output + pngTikzPath = "04_Experimental_Evaluation/tikz/mpi/" + exportName + "_img.png"; % path written into TikZ + figure(401); + exportLevelScatterTikz(gca, pngFile, tikzFile, pngTikzPath, ... + "resolutionDpi", 150, ... + "generatedBy", "mpi_recipe_dev.m"); - eq_dc_tracking_settings = { ... - "dc_tracking_mu", 0.05, ... - "dc_tracking_adaptive_enabled", 0, ... - "dc_tracking_buffer_len", 1024}; +end - eq_ffe_update_settings = { ... - "ffe_update_buffer_len", 1}; - eq_optimizer_settings = { ... - "optmize_mus", 0, ... - "plot_mu_optimization", options.debug_plots, ... - "optimize_dc_tracking_params", 1, ... - "optimize_a2_level_weights", 0, ... - "a2_level_weight_optimization_len", 2^15, ... - "a2_level_weight_optimization_max_evals", 30, ... - "a2_level_weight_max", 1}; +%% A2 +eq_core_settings = { ... + "sps", 2, ... + "order", 50, ... + "decide", 0, ... + "adaption_technique", "nlms"}; - eq_debug_settings = { ... - "save_debug", true}; +eq_training_settings = { ... + "len_tr", 4096, ... + "epochs_tr", 5, ... + "mu_tr", 0.04}; - eq_settings = [ ... - eq_core_settings, ... - eq_training_settings, ... - eq_dd_settings, ... - eq_a1_settings, ... - eq_a2_settings, ... - eq_dc_tracking_settings, ... - eq_ffe_update_settings, ... - eq_optimizer_settings, ... - eq_debug_settings]; +eq_dd_settings = { ... + "dd_mode", 1, ... + "epochs_dd", 3, ... + "mu_dd", 0.012}; - eq_ffe = FFE(eq_settings{:}); +eq_a1_settings = { ... + "dc_smoothing_a1", 0, ... + "dc_avg_bufferlength_a1", 0, ... + "dc_avg_update_blocklength_a1", 1}; + +eq_a2_settings = { ... + "dc_smoothing_a2", 1, ... + "dc_level_avg_bufferlength_a2", 256, ... + "dc_level_update_blocklength_a2", options.userParameters.block_update, ... + "dc_level_weights_a2", [0.6]}; + +eq_dc_tracking_settings = { ... + "dc_tracking_mu", 0, ... + "dc_tracking_adaptive_enabled", 0, ... + "dc_tracking_persistence_gain", 0, ... + "dc_tracking_buffer_len", 0}; + +eq_ffe_update_settings = { ... + "ffe_update_buffer_len", 1}; + +eq_optimizer_settings = { ... + "optmize_mus", 0, ... + "plot_mu_optimization", options.debug_plots, ... + "optimize_dc_tracking_params", 0, ... + "optimize_a2_level_weights", 1, ... + "a2_level_weight_optimization_len", 2^15, ... + "a2_level_weight_optimization_max_evals", 30, ... + "a2_level_weight_max", 1}; + +eq_debug_settings = { ... + "save_debug", false}; + +eq_settings = [ ... + eq_core_settings, ... + eq_training_settings, ... + eq_dd_settings, ... + eq_a1_settings, ... + eq_a2_settings, ... + eq_dc_tracking_settings, ... + eq_ffe_update_settings, ... + eq_optimizer_settings, ... + eq_debug_settings]; + +eq_ffe = FFE(eq_settings{:}); + +if 0 + + [ffe_results,equalized_signal] = ffe(eq_ffe, options.M, Scpe_sig, Symbols, Tx_bits, ... + "precode_mode", options.duob_mode, ... + 'showAnalysis', options.debug_plots, ... + "postFFE", [], ... + "eth_style_symbol_mapping", 0); + ffe_results.metrics.print("description",sprintf('Immediate A2; SIR %d dB',options.dataTable.sir)); + output.a2_immediate_updates = ffe_results; + +end + +if options.debug_plots showLevelScatter(Scpe_sig_raw, Symbols, ... "fsym", options.fsym, ... "fignum", 400, ... "normalize", true); + [~, avg_for_lvl] = showLevelScatter(equalized_signal, Symbols, ... + "fsym", options.fsym, ... + "fignum", 401, ... + "normalize", true); + +end + +%% A1 + +eq_a1_settings = { ... + "dc_smoothing_a1", 1 ... + "dc_avg_bufferlength_a1", 2048, ... + "dc_avg_update_blocklength_a1", options.userParameters.block_update}; + +eq_a2_settings = { ... + "dc_smoothing_a2", 0, ... + "dc_level_avg_bufferlength_a2", 0, ... + "dc_level_update_blocklength_a2", 0, ... + "dc_level_weights_a2", [0.6 0.6 0.6 0.6]}; + +eq_optimizer_settings = { ... + "optmize_mus", 0, ... + "plot_mu_optimization", options.debug_plots, ... + "optimize_dc_tracking_params", 0, ... + "optimize_a2_level_weights", 0, ... + "a2_level_weight_optimization_len", 2^15, ... + "a2_level_weight_optimization_max_evals", 30, ... + "a2_level_weight_max", 1}; + +eq_debug_settings = { ... + "save_debug", false}; + +eq_settings = [ ... + eq_core_settings, ... + eq_training_settings, ... + eq_dd_settings, ... + eq_a1_settings, ... + eq_a2_settings, ... + eq_dc_tracking_settings, ... + eq_ffe_update_settings, ... + eq_optimizer_settings, ... + eq_debug_settings]; + +eq_ffe = FFE(eq_settings{:}); + +if 0 + + [ffe_results,equalized_signal] = ffe(eq_ffe, options.M, Scpe_sig, Symbols, Tx_bits, ... + "precode_mode", options.duob_mode, ... + 'showAnalysis', options.debug_plots, ... + "postFFE", [], ... + "eth_style_symbol_mapping", 0); + + ffe_results.metrics.print("description",sprintf('Immediate A1; SIR %d dB',options.dataTable.sir)); + output.a1_immediate_updates = ffe_results; + + showLevelScatter(Scpe_sig_raw, Symbols, ... + "fsym", options.fsym, ... + "fignum", 400, ... + "normalize", true); + + [~, avg_for_lvl] = showLevelScatter(equalized_signal, Symbols, ... + "fsym", options.fsym, ... + "fignum", 401, ... + "normalize", true); +end + +%% Tracking fixed + +eq_core_settings = { ... + "sps", 2, ... + "order", 50, ... + "decide", 0, ... + "adaption_technique", "nlms"}; + +eq_training_settings = { ... + "len_tr", 4096, ... + "epochs_tr", 5, ... + "mu_tr", 0.04}; + +eq_dd_settings = { ... + "dd_mode", 1, ... + "epochs_dd", 3, ... + "mu_dd", 0.012}; + +eq_a1_settings = { ... + "dc_smoothing_a1", 0, ... + "dc_avg_bufferlength_a1", 0, ... + "dc_avg_update_blocklength_a1", 1}; + +eq_a2_settings = { ... + "dc_smoothing_a2", 0, ... + "dc_level_avg_bufferlength_a2", 0, ... + "dc_level_update_blocklength_a2", 0, ... + "dc_level_weights_a2", [0.6 0.6 0.6 0.6]}; + +eq_dc_tracking_settings = { ... + "dc_tracking_mu", 0.002, ... + "dc_tracking_adaptive_enabled", 0, ... + "dc_tracking_persistence_gain", 0, ... + "dc_tracking_buffer_len", options.userParameters.block_update}; + +eq_ffe_update_settings = { ... + "ffe_update_buffer_len", 1}; + +eq_optimizer_settings = { ... + "optmize_mus", 0, ... + "plot_mu_optimization", options.debug_plots, ... + "optimize_dc_tracking_params", 1, ... + "optimize_a2_level_weights", 0, ... + "a2_level_weight_optimization_len", 2^15, ... + "a2_level_weight_optimization_max_evals", 30, ... + "a2_level_weight_max", 1}; + +eq_debug_settings = { ... + "save_debug", false}; + +eq_settings = [ ... + eq_core_settings, ... + eq_training_settings, ... + eq_dd_settings, ... + eq_a1_settings, ... + eq_a2_settings, ... + eq_dc_tracking_settings, ... + eq_ffe_update_settings, ... + eq_optimizer_settings, ... + eq_debug_settings]; + +eq_ffe = FFE(eq_settings{:}); + +if 1 + + [ffe_results,equalized_signal] = ffe(eq_ffe, options.M, Scpe_sig, Symbols, Tx_bits, ... + "precode_mode", options.duob_mode, ... + 'showAnalysis', options.debug_plots, ... + "postFFE", [], ... + "eth_style_symbol_mapping", 0); + + ffe_results.metrics.print("description",sprintf('Immediate A2; SIR %d dB',options.dataTable.sir)); + output.tracking_fixmu_immediate_updates = ffe_results; + +end + +%% Tracking Adaptive + +eq_core_settings = { ... + "sps", 2, ... + "order", 50, ... + "decide", 0, ... + "adaption_technique", "nlms"}; + +eq_training_settings = { ... + "len_tr", 4096, ... + "epochs_tr", 5, ... + "mu_tr", 0.04}; + +eq_dd_settings = { ... + "dd_mode", 1, ... + "epochs_dd", 3, ... + "mu_dd", 0.012}; + +eq_a1_settings = { ... + "dc_smoothing_a1", 0, ... + "dc_avg_bufferlength_a1", 0, ... + "dc_avg_update_blocklength_a1", 1}; + +eq_a2_settings = { ... + "dc_smoothing_a2", 0, ... + "dc_level_avg_bufferlength_a2", 0, ... + "dc_level_update_blocklength_a2", 0, ... + "dc_level_weights_a2", [0.6 0.6 0.6 0.6]}; + +eq_dc_tracking_settings = { ... + "dc_tracking_mu", 0.002, ... + "dc_tracking_adaptive_enabled", 1, ... + "dc_tracking_persistence_gain", 0, ... + "dc_tracking_buffer_len", options.userParameters.block_update}; + +eq_ffe_update_settings = { ... + "ffe_update_buffer_len", 1}; + +eq_optimizer_settings = { ... + "optmize_mus", 0, ... + "plot_mu_optimization", options.debug_plots, ... + "optimize_dc_tracking_params", 1, ... + "optimize_a2_level_weights", 0, ... + "a2_level_weight_optimization_len", 2^15, ... + "a2_level_weight_optimization_max_evals", 30, ... + "a2_level_weight_max", 1}; + +eq_debug_settings = { ... + "save_debug", false}; + +eq_settings = [ ... + eq_core_settings, ... + eq_training_settings, ... + eq_dd_settings, ... + eq_a1_settings, ... + eq_a2_settings, ... + eq_dc_tracking_settings, ... + eq_ffe_update_settings, ... + eq_optimizer_settings, ... + eq_debug_settings]; + +eq_ffe = FFE(eq_settings{:}); + +if 1 + + [ffe_results,equalized_signal] = ffe(eq_ffe, options.M, Scpe_sig, Symbols, Tx_bits, ... + "precode_mode", options.duob_mode, ... + 'showAnalysis', options.debug_plots, ... + "postFFE", [], ... + "eth_style_symbol_mapping", 0); + + ffe_results.metrics.print("description",sprintf('Immediate A2; SIR %d dB',options.dataTable.sir)); + output.tracking_adaptive_immediate_updates = ffe_results; + + showLevelScatter(Scpe_sig_raw, Symbols, ... + "fsym", options.fsym, ... + "fignum", 400, ... + "normalize", true); + + [~, avg_for_lvl] = showLevelScatter(equalized_signal, Symbols, ... + "fsym", options.fsym, ... + "fignum", 401, ... + "normalize", true); + + +end - %% NORMAL FFE - if 1 - - [ffe_results,equalized_signal] = ffe(eq_ffe, options.M, Scpe_sig, Symbols, Tx_bits, ... - "precode_mode", options.duob_mode, ... - 'showAnalysis', options.debug_plots, ... - "postFFE", [], ... - "eth_style_symbol_mapping", 0); - - ffe_results.metrics.print("description",sprintf('Normal FFE; SIR %d dB',options.dataTable.sir)); - output.ffe_package = ffe_results; - - [~, avg_for_lvl] = showLevelScatter(equalized_signal, Symbols, ... - "fsym", options.fsym, ... - "fignum", 401, ... - "normalize", true); - - output.ffe_debug = struct(); - dbg = eq_ffe.debug_struct; - - - - smooth_len = 501; - output.ffe_debug.smoothing_window = smooth_len; - error_first_s = movmean(dbg.error_first_epoch(:),smooth_len,"omitnan"); - error_last_s = movmean(dbg.error(:),smooth_len,"omitnan"); - dc_tracking_mu_eff_s = movmean(dbg.dc_tracking_mu_eff(:),smooth_len,"omitnan"); - dc_tracking_est_s = movmean(dbg.dc_tracking_est(:),smooth_len,"omitnan"); - - figure(460); clf; - tiledlayout(2,1,"TileSpacing","compact","Padding","compact"); - - nexttile; - semilogy(error_first_s + eps,"DisplayName","first epoch"); - hold on; - semilogy(error_last_s + eps,"DisplayName","last epoch"); - grid on; - ylabel("error"); - title("FFE debug error"); - legend("Location","best"); - - nexttile;hold on - % plot(eq_sig_mov,"DisplayName","err dc eff"); - plot(dc_tracking_mu_eff_s,"DisplayName","mu DC - either fixed or adaptive"); - e_dc_scale = max(abs(dc_tracking_est_s),[],"omitnan") + eps; - plot(-1.*dc_tracking_est_s./e_dc_scale,"DisplayName","Inverted DC-tracking; Value that is subtracted during EQ"); - avg_lvl_dc=mean(avg_for_lvl,1,"omitnan"); - plot(avg_lvl_dc./0.01,"DisplayName","Smoothed EQ output signal; calc'd by showLevelScatter"); - grid on; - xlabel("Symbol"); - ylabel("mu dc eff"); - title("Effective adaptive DC step"); - legend - - inv_dc_track = -dc_tracking_est_s(:); - avg_lvl_dc = avg_lvl_dc(:); - xcorr_len = min(numel(inv_dc_track),numel(avg_lvl_dc)); - inv_dc_xcorr = inv_dc_track(1:xcorr_len); - avg_lvl_xcorr = avg_lvl_dc(1:xcorr_len); - inv_dc_xcorr = fillmissing(inv_dc_xcorr,"linear","EndValues","nearest"); - avg_lvl_xcorr = fillmissing(avg_lvl_xcorr,"linear","EndValues","nearest"); - inv_dc_xcorr = inv_dc_xcorr - mean(inv_dc_xcorr,"omitnan"); - avg_lvl_xcorr = avg_lvl_xcorr - mean(avg_lvl_xcorr,"omitnan"); - [dc_level_xcorr,dc_level_lags] = xcorr(inv_dc_xcorr,avg_lvl_xcorr,"coeff"); - [dc_level_corr,dc_level_idx] = max(dc_level_xcorr); - dc_level_delay_symbols = dc_level_lags(dc_level_idx); - output.ffe_debug.dc_level_delay_symbols = dc_level_delay_symbols; - output.ffe_debug.dc_level_delay_corr = dc_level_corr; - output.ffe_debug.dc_level_lags = dc_level_lags; - output.ffe_debug.dc_level_xcorr = dc_level_xcorr; - fprintf("FFE debug: xcorr(inv DC tracking, avg level) delay=%d symbols, corr=%6.3f\n", ... - dc_level_delay_symbols,dc_level_corr); - - figure(461); clf; - plot(dc_level_lags,dc_level_xcorr,"DisplayName","xcorr"); - hold on; - plot(dc_level_delay_symbols,dc_level_corr,"ro","DisplayName","max"); - grid on; - xlabel("Lag in symbols"); - ylabel("Correlation coefficient"); - title(sprintf("Delay estimate: %d symbols (corr %.3f)",dc_level_delay_symbols,dc_level_corr)); - legend("Location","best"); - - - end - - - - % - % - % %% MPI Reduction - % if 1 - % - % % dc_buffer_len = 0; - % % ffe_buffer_len = 0; - % % smoothing_buffer_length = options.userParameters.smoothing_length; - % % smoothing_buffer_update = 1; - % - % % eq_ffe_dcr = FFE_DCremoval_adaptive_mu(eq_settings{:}, ... - % % "dc_buffer_len",dc_buffer_len, ... - % % "ffe_buffer_len",ffe_buffer_len,... - % % "smoothing_buffer_length",smoothing_buffer_length,... - % % "smoothing_buffer_update",smoothing_buffer_update); - % - % eq_ = FFE_DCremoval("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",1); - % - % ffe_results_dcr = ffe(eq_, options.M, Scpe_sig, Symbols, Tx_bits, ... - % "precode_mode", options.duob_mode, ... - % 'showAnalysis', options.debug_plots, ... - % "postFFE", [], ... - % "eth_style_symbol_mapping", 0); - % - % ffe_results_dcr.metrics.print("description",'FFE DCR'); - % output.ffe_dcr_package = ffe_results_dcr; - % end end diff --git a/Functions/EQ_visuals/exportLevelScatterTikz.m b/Functions/EQ_visuals/exportLevelScatterTikz.m new file mode 100644 index 0000000..be0424f --- /dev/null +++ b/Functions/EQ_visuals/exportLevelScatterTikz.m @@ -0,0 +1,320 @@ +function exportLevelScatterTikz(sourceAx, pngFile, tikzFile, pngTikzPath, options) +%EXPORTLEVELSCATTERTIKZ Export showLevelScatter axes as PNG-backed TikZ. +% Rasterizes scatter objects into a PNG layer and writes average lines plus +% text annotations as PGFPlots objects. + +arguments + sourceAx + pngFile (1,1) string + tikzFile (1,1) string + pngTikzPath (1,1) string + options.resolutionDpi (1,1) double {mustBePositive, mustBeInteger} = 150 + options.xLabel (1,1) string = "Time in $\mu$s" + options.yLabel (1,1) string = "Normalized Amplitude" + options.generatedBy (1,1) string = "exportLevelScatterTikz.m" +end + +outputDir = fileparts(pngFile); +if ~exist(outputDir, "dir") + mkdir(outputDir); +end + +exportScatterLayerPng(sourceAx, pngFile, options.resolutionDpi); + +linePlots = collectTikzLinePlots(sourceAx); +textAnnotations = collectTikzTextAnnotations(sourceAx); +writeTikzPngAxis(tikzFile, pngTikzPath, sourceAx, linePlots, textAnnotations, options); +end + +function exportScatterLayerPng(sourceAx, pngFile, resolutionDpi) +sourceFig = ancestor(sourceAx, "figure"); +xLimits = sourceAx.XLim; +yLimits = sourceAx.YLim; +scatterHandles = findGraphicsObjectsByType(sourceAx, "scatter"); + +exportFig = figure( ... + "Visible", "off", ... + "Color", "white", ... + "Units", sourceFig.Units, ... + "Position", sourceFig.Position); +cleanupFigure = onCleanup(@() close(exportFig)); + +exportAx = copyobj(sourceAx, exportFig); +exportAx.Units = "normalized"; +exportAx.Position = [0 0 1 1]; +exportAx.XLim = xLimits; +exportAx.YLim = yLimits; +exportAx.XLimMode = "manual"; +exportAx.YLimMode = "manual"; +stripAxesToScatterOnly(exportAx); +hideAxesInkForRasterExport(exportAx); + +fprintf("Exporting scatter PNG with XLim=[%g %g], YLim=[%g %g], scatter objects=%d: %s\n", ... + xLimits(1), xLimits(2), yLimits(1), yLimits(2), numel(scatterHandles), pngFile); +drawnow; +exportFig.PaperPositionMode = "auto"; +print(exportFig, char(pngFile), "-dpng", sprintf("-r%d", resolutionDpi)); +end + +function stripAxesToScatterOnly(ax) +plotObjects = findall(ax); +for objIdx = 1:numel(plotObjects) + obj = plotObjects(objIdx); + if obj == ax || ~isvalid(obj) + continue + end + + objType = string(get(obj, "Type")); + if lower(objType) ~= "scatter" + delete(obj); + end +end +end + +function hideAxesInkForRasterExport(ax) +ax.Visible = "on"; +ax.Color = "white"; +ax.Box = "off"; +ax.XGrid = "off"; +ax.YGrid = "off"; +ax.XMinorGrid = "off"; +ax.YMinorGrid = "off"; +ax.XTick = []; +ax.YTick = []; +ax.XColor = "white"; +ax.YColor = "white"; +ax.Title.String = ""; +ax.XLabel.String = ""; +ax.YLabel.String = ""; +end + +function handles = findGraphicsObjectsByType(parentHandle, objectType) +allHandles = findall(parentHandle); +matches = false(size(allHandles)); +for handleIdx = 1:numel(allHandles) + currentHandle = allHandles(handleIdx); + if ~isvalid(currentHandle) + continue + end + + matches(handleIdx) = lower(string(get(currentHandle, "Type"))) == lower(string(objectType)); +end + +handles = allHandles(matches); +end + +function linePlots = collectTikzLinePlots(sourceAx) +lineHandles = findGraphicsObjectsByType(sourceAx, "line"); +lineHandles = flipud(lineHandles(:)); + +linePlots = repmat(struct( ... + "xData", [], ... + "yData", [], ... + "color", [], ... + "lineWidth", []), numel(lineHandles), 1); +validLineCount = 0; + +for lineIdx = 1:numel(lineHandles) + lineHandle = lineHandles(lineIdx); + xData = lineHandle.XData(:); + yData = lineHandle.YData(:); + validSamples = isfinite(xData) & isfinite(yData); + + if ~any(validSamples) + continue + end + + validLineCount = validLineCount + 1; + linePlots(validLineCount).xData = xData(validSamples); + linePlots(validLineCount).yData = yData(validSamples); + linePlots(validLineCount).color = lineHandle.Color; + linePlots(validLineCount).lineWidth = lineHandle.LineWidth; +end + +linePlots = linePlots(1:validLineCount); +end + +function textAnnotations = collectTikzTextAnnotations(sourceAx) +textHandles = findGraphicsObjectsByType(sourceAx, "text"); +textHandles = flipud(textHandles(:)); +xLimits = sourceAx.XLim; +yLimits = sourceAx.YLim; + +textAnnotations = repmat(struct( ... + "x", [], ... + "y", [], ... + "text", "", ... + "anchor", "center"), numel(textHandles), 1); +validTextCount = 0; + +for textIdx = 1:numel(textHandles) + textHandle = textHandles(textIdx); + labelText = string(textHandle.String); + if strlength(strtrim(labelText)) == 0 + continue + end + + textPosition = textHandle.Position; + if textPosition(1) < xLimits(1) || textPosition(1) > xLimits(2) || ... + textPosition(2) < yLimits(1) || textPosition(2) > yLimits(2) + continue + end + + validTextCount = validTextCount + 1; + textAnnotations(validTextCount).x = textPosition(1); + textAnnotations(validTextCount).y = textPosition(2); + textAnnotations(validTextCount).text = labelText; + textAnnotations(validTextCount).anchor = matlabTextAlignmentToTikzAnchor( ... + textHandle.HorizontalAlignment, textHandle.VerticalAlignment); +end + +textAnnotations = textAnnotations(1:validTextCount); +end + +function writeTikzPngAxis(tikzFile, pngTikzPath, sourceAx, linePlots, textAnnotations, options) +outputDir = fileparts(tikzFile); +if ~exist(outputDir, "dir") + mkdir(outputDir); +end + +xLimits = sourceAx.XLim; +yLimits = sourceAx.YLim; +fid = fopen(tikzFile, "w"); +if fid < 0 + error("exportLevelScatterTikz:TikzOpenFailed", ... + "Could not open TikZ export file: %s", tikzFile); +end +cleanupFile = onCleanup(@() fclose(fid)); + +axisOptions = { + " every axis/.append style={font=\scriptsize}," + "width=\fwidth," + "height=\fheight," + "at={(0\fwidth,0\fheight)}," + "scale only axis," + "axis on top," + "xmin=" + formatPgfNumber(xLimits(1)) + "," + "xmax=" + formatPgfNumber(xLimits(2)) + "," + "xlabel style={font=\color{white!15!black}\small}," + "xlabel={" + options.xLabel + "}," + "ymin=" + formatPgfNumber(yLimits(1)) + "," + "ymax=" + formatPgfNumber(yLimits(2)) + "," + "ylabel style={font=\color{white!15!black}\small}," + "ylabel={" + options.yLabel + "}," + "axis background/.style={fill=white}," + "xmajorgrids," + "ymajorgrids," + "grid style={line width=0.4pt, dotted, color=black!20}," + "scaled ticks=false," + "tick label style={/pgf/number format/fixed, /pgf/number format/1000 sep={}}," + "legend columns=1" + }; + +fprintf(fid, "%% This file was generated by %s.\n", options.generatedBy); +fprintf(fid, "%%\n"); +for lineIdx = 1:numel(linePlots) + fprintf(fid, "%s\n", formatTikzColorDefinition(lineIdx, linePlots(lineIdx).color)); +end +if ~isempty(linePlots) + fprintf(fid, "%%\n"); +end +fprintf(fid, "%s\n\n", "\begin{tikzpicture}"); +fprintf(fid, "%s\n", "\begin{axis}[%"); +for optionIdx = 1:numel(axisOptions) + fprintf(fid, "%s\n", axisOptions{optionIdx}); +end +fprintf(fid, "%s\n", "]"); + +graphicsLine = sprintf( ... + "\\addplot [forget plot] graphics [xmin=%s, xmax=%s, ymin=%s, ymax=%s] {%s};", ... + formatPgfNumber(xLimits(1)), ... + formatPgfNumber(xLimits(2)), ... + formatPgfNumber(yLimits(1)), ... + formatPgfNumber(yLimits(2)), ... + char(strrep(pngTikzPath, "\", "/"))); +fprintf(fid, "%s\n\n", graphicsLine); +writeTikzLinePlots(fid, linePlots); +writeTikzTextAnnotations(fid, textAnnotations); +fprintf(fid, "%s\n\n", "\end{axis}"); +fprintf(fid, "%s", "\end{tikzpicture}%"); +end + +function valueText = formatPgfNumber(value) +valueText = string(sprintf("%.15g", value)); +end + +function colorDefinition = formatTikzColorDefinition(colorIdx, rgbColor) +colorDefinition = sprintf( ... + "\\definecolor{mycolor%d}{rgb}{%.5f,%.5f,%.5f}%%", ... + colorIdx, rgbColor(1), rgbColor(2), rgbColor(3)); +end + +function writeTikzLinePlots(fid, linePlots) +for lineIdx = 1:numel(linePlots) + fprintf(fid, "\\addplot [color=mycolor%d, line width=%.1fpt, forget plot]\n", ... + lineIdx, linePlots(lineIdx).lineWidth); + fprintf(fid, " table[row sep=crcr]{%%\n"); + + for sampleIdx = 1:numel(linePlots(lineIdx).xData) + fprintf(fid, "%s\t%s\\\\\n", ... + formatPgfNumber(linePlots(lineIdx).xData(sampleIdx)), ... + formatPgfNumber(linePlots(lineIdx).yData(sampleIdx))); + end + + fprintf(fid, "};\n\n"); +end +end + +function writeTikzTextAnnotations(fid, textAnnotations) +for textIdx = 1:numel(textAnnotations) + fprintf(fid, "\\node[font=\\scriptsize, anchor=%s, fill=white, draw=black!40, rounded corners=2pt, inner sep=2pt]\n", ... + textAnnotations(textIdx).anchor); + fprintf(fid, " at (axis cs:%s,%s) {%s};\n\n", ... + formatPgfNumber(textAnnotations(textIdx).x), ... + formatPgfNumber(textAnnotations(textIdx).y), ... + escapeTikzText(textAnnotations(textIdx).text)); +end +end + +function anchor = matlabTextAlignmentToTikzAnchor(horizontalAlignment, verticalAlignment) +horizontalAlignment = string(horizontalAlignment); +verticalAlignment = string(verticalAlignment); + +if horizontalAlignment == "left" + horizontalAnchor = "west"; +elseif horizontalAlignment == "right" + horizontalAnchor = "east"; +else + horizontalAnchor = ""; +end + +if verticalAlignment == "top" + verticalAnchor = "north"; +elseif verticalAlignment == "bottom" + verticalAnchor = "south"; +else + verticalAnchor = ""; +end + +if strlength(horizontalAnchor) > 0 && strlength(verticalAnchor) > 0 + anchor = verticalAnchor + " " + horizontalAnchor; +elseif strlength(horizontalAnchor) > 0 + anchor = horizontalAnchor; +elseif strlength(verticalAnchor) > 0 + anchor = verticalAnchor; +else + anchor = "center"; +end +end + +function textOut = escapeTikzText(textIn) +textOut = char(textIn); +% textOut = strrep(textOut, "\", "\textbackslash{}"); +textOut = strrep(textOut, "{", "\{"); +textOut = strrep(textOut, "}", "\}"); +textOut = strrep(textOut, "%", "\%"); +textOut = strrep(textOut, "&", "\&"); +textOut = strrep(textOut, "#", "\#"); +textOut = strrep(textOut, "_", "\_"); +% textOut = strrep(textOut, "$", "\$"); +end diff --git a/Tests/04_DSP/Equalizer/FFE_test.m b/Tests/04_DSP/Equalizer/FFE_test.m index 3d9896d..7bdfc6f 100644 --- a/Tests/04_DSP/Equalizer/FFE_test.m +++ b/Tests/04_DSP/Equalizer/FFE_test.m @@ -14,10 +14,13 @@ classdef FFE_test < IMDDTestCase testCase.verifyEqual(ffe.epochs_dd, 5); testCase.verifyFalse(logical(ffe.optimize_dc_tracking_params)); testCase.verifyEqual(ffe.dc_tracking_optimization_delay_weight, 1e-3); + testCase.verifyEqual(ffe.dc_tracking_persistence_gain, 0); testCase.verifyEqual(ffe.dc_tracking_power_exponent, 2); testCase.verifyEqual(ffe.dc_avg_bufferlength_a1, 0); + testCase.verifyEqual(ffe.dc_avg_update_blocklength_a1, 0); testCase.verifyEqual(ffe.dc_smoothing_a1, 0); testCase.verifyEqual(ffe.dc_level_avg_bufferlength_a2, 0); + testCase.verifyEqual(ffe.dc_level_update_blocklength_a2, 0); testCase.verifyEqual(ffe.dc_smoothing_a2, 0); testCase.verifyEqual(ffe.dc_level_weights_a2, 0); testCase.verifyEqual(ffe.dc_tracking_buffer_len, 1); @@ -101,6 +104,76 @@ classdef FFE_test < IMDDTestCase testCase.verifyEqual(ffe.e_dc, 0.19, "AbsTol", 1e-12); end + function dcTrackingUnbufferedPathUpdatesEverySymbol(testCase) + x = zeros(4, 1); + d = ones(4, 1); + + ffe = FFE( ... + "sps", 1, ... + "order", 1, ... + "dc_tracking_mu", 0.1, ... + "dc_tracking_buffer_len", 1, ... + "dd_mode", 0, ... + "adaption_technique", adaption_method.lms); + + ffe.constellation = unique(d); + ffe.equalize(x, d, 0, 1, numel(x), true, false); + + testCase.verifyEqual(ffe.e_dc, 1 - 0.9^4, "AbsTol", 1e-12); + end + + function dcTrackingBlockUpdateUsesMeanBlockError(testCase) + ffe = FFE("dc_tracking_mu", 0.1); + + [e_dc_next,stats] = ffe.dcTrackingBlockUpdate(0.5, [1; 2; 3]); + + testCase.verifyEqual(e_dc_next, 0.7, "AbsTol", 1e-12); + testCase.verifyEqual(stats.err_mean, 2, "AbsTol", 1e-12); + testCase.verifyEqual(stats.mu_eff, 0.1, "AbsTol", 1e-12); + testCase.verifyEqual(stats.update, 0.2, "AbsTol", 1e-12); + end + + function dcTrackingBlockUpdateDoesNotSuppressLargeErrorPower(testCase) + ffe = FFE("dc_tracking_mu", 0.1); + + [e_dc_next,stats] = ffe.dcTrackingBlockUpdate(0, [10; 10]); + + testCase.verifyEqual(e_dc_next, 1, "AbsTol", 1e-12); + testCase.verifyEqual(stats.err_mean, 10, "AbsTol", 1e-12); + testCase.verifyEqual(stats.mu_eff, 0.1, "AbsTol", 1e-12); + end + + function dcTrackingBlockUpdateCanBoostPersistentMean(testCase) + ffe = FFE("dc_tracking_mu", 0.1); + + [e_dc_next,stats] = ffe.dcTrackingBlockUpdate(0, [2; 2; 2], ... + "persistence_gain", 1); + + testCase.verifyEqual(e_dc_next, 0.4, "AbsTol", 1e-12); + testCase.verifyEqual(stats.persistence_scale, 1, "AbsTol", 1e-12); + testCase.verifyEqual(stats.mu_eff, 0.2, "AbsTol", 1e-12); + end + + function dcTrackingLoopUsesBlockPersistenceGain(testCase) + x = zeros(4, 1); + d = ones(4, 1); + + ffe = FFE( ... + "sps", 1, ... + "order", 1, ... + "dc_tracking_mu", 0.1, ... + "dc_tracking_adaptive_enabled", true, ... + "dc_tracking_persistence_gain", 1, ... + "dc_tracking_buffer_len", 2, ... + "dd_mode", 0, ... + "adaption_technique", adaption_method.lms); + + ffe.constellation = unique(d); + ffe.equalize(x, d, 0, 1, numel(x), true, false); + + testCase.verifyEqual(ffe.e_dc, 0.36, "AbsTol", 1e-12); + end + function ffeBufferDelaysTapUpdateUntilBlockBoundary(testCase) x = ones(4, 1); d = ones(4, 1); @@ -181,6 +254,28 @@ classdef FFE_test < IMDDTestCase testCase.verifyEqual(ffe.debug_struct.dc_avg_offset, expected_offset, "AbsTol", 1e-12); end + function dcAvgA1UpdateBlocklengthOneRefreshesEverySymbol(testCase) + x = (1:4).'; + d = zeros(4, 1); + expected_offset = [0, 1, 1.5, 2]; + expected_y = [1; 1; 1.5; 2]; + + ffe = FFE( ... + "sps", 1, ... + "order", 1, ... + "dc_avg_bufferlength_a1", 3, ... + "dc_avg_update_blocklength_a1", 1, ... + "save_debug", true, ... + "dd_mode", 0, ... + "adaption_technique", adaption_method.lms); + ffe.e = 1; + + [y,~] = ffe.equalize(x, d, 0, 1, numel(x), true, false); + + testCase.verifyEqual(y, expected_y, "AbsTol", 1e-12); + testCase.verifyEqual(ffe.debug_struct.dc_avg_offset, expected_offset, "AbsTol", 1e-12); + end + function dcAvgA1WarnsWhenCombinedWithDcTracking(testCase) testCase.verifyWarning(@() FFE( ... "dc_avg_bufferlength_a1", 3, ... @@ -211,6 +306,30 @@ classdef FFE_test < IMDDTestCase testCase.verifyEqual(ffe.debug_struct.dc_level_valid_count, [0, 0, 2, 2]); end + function dcLevelAvgA2UpdateBlocklengthOneRefreshesEverySymbol(testCase) + x = (1:4).'; + d = zeros(4, 1); + + ffe = FFE( ... + "sps", 1, ... + "order", 1, ... + "dc_level_avg_bufferlength_a2", 2, ... + "dc_level_update_blocklength_a2", 1, ... + "dc_level_weights_a2", 1, ... + "save_debug", true, ... + "dd_mode", 0, ... + "adaption_technique", adaption_method.lms); + ffe.e = 1; + ffe.constellation = 0; + + [y,~] = ffe.equalize(x, d, 0, 1, numel(x), true, false); + + testCase.verifyEqual(y, [1; 1.5; 1.5; 1.5], "AbsTol", 1e-12); + testCase.verifyEqual(ffe.debug_struct.dc_level_mpi_est, [0, 1, 1.5, 2.5], "AbsTol", 1e-12); + testCase.verifyEqual(ffe.debug_struct.dc_level_weight, [0, 0.5, 1, 1], "AbsTol", 1e-12); + testCase.verifyEqual(ffe.debug_struct.dc_level_valid_count, [0, 1, 2, 2]); + end + function dcLevelAvgA2UsesVectorWeightsInConstellationOrder(testCase) x = [1; 3; 1; 4]; d = [0; 2; 0; 2]; diff --git a/before_eq_-1.png b/before_eq_-1.png new file mode 100644 index 0000000000000000000000000000000000000000..5b0ec624fc23ea695eaf9127b453aa5700590373 GIT binary patch literal 256089 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

4gaHsp|MU2r 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

    Y+`MB>~dUFPVQ=E#%B)_gzQZ`b{~*25Gti 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

    6aWu0b;U70d*tJTEmX3i|hccYWog$bl3 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%0D?zl(sOng2Dk0#clQQUP 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 0; + if nnz(fitMask) >= 2 + fitOrder = min(polyfitOrderMax, nnz(fitMask) - 1); + fitCoeff = polyfit(sirValues(fitMask), log10(meanBer(fitMask)), fitOrder); + xFit = linspace(min(sirValues(fitMask)), max(sirValues(fitMask)), 300); + yFit = 10 .^ polyval(fitCoeff, xFit); + + plot(xFit, yFit, ... + "LineStyle", "--", ... + "LineWidth", 1.1, ... + "Color", algColor, ... + "HandleVisibility", "off"); + end + end + end + + title(sprintf("PAM %.0f, path %.0f m", pamLevel, pathLengthToPlot)); + xlabel("SIR (dB)"); + ylabel("BER"); + set(gca, "YScale", "log"); + xlim([15,45]); + grid on; + box on; + legend("Location", "best", "Interpreter", "none"); +end + +%% Local helpers + +function berTable = buildBerTable(wh, storageName, pathLength) +rows = struct( ... + "pam_level", {}, ... + "symbolrate", {}, ... + "interference_path_length", {}, ... + "sir", {}, ... + "block_update", {}, ... + "run_ids", {}, ... + "n_run_ids", {}, ... + "ber_values", {}, ... + "n_ber_values", {}); + +for linIdx = 1:numel(wh.sto.(storageName)) + storedValue = wh.sto.(storageName){linIdx}; + if isempty(storedValue) + continue + end + + phys = linearIndexToStruct(wh, linIdx); + if phys.interference_path_length ~= pathLength + continue + end + + berValues = extractBerValues(storedValue); + if isempty(berValues) + continue + end + + runIds = wh.sto.run_id{linIdx}; + if isempty(runIds) + runIds = NaN; + end + + row = struct(); + row.pam_level = phys.pam_level; + row.symbolrate = phys.symbolrate; + row.interference_path_length = phys.interference_path_length; + row.sir = phys.sir; + row.block_update = phys.block_update; + row.run_ids = {runIds}; + row.n_run_ids = numel(runIds); + row.ber_values = {berValues}; + row.n_ber_values = numel(berValues); + + rows(end+1) = row; %#ok +end + +if isempty(rows) + berTable = struct2table(rows); +else + berTable = struct2table(rows); + berTable = sortrows(berTable, ["pam_level", "sir", "symbolrate"]); +end +end + +function physStruct = linearIndexToStruct(wh, linIdx) +[physValues, physNames] = wh.getPhysIndicesByLinIndex(linIdx); +physStruct = struct(); + +for paramIdx = 1:numel(physNames) + physStruct.(char(physNames{paramIdx})) = physValues{paramIdx}; +end +end + +function berValues = extractBerValues(value) +berValues = []; + +if isstruct(value) + if isfield(value, "metrics") && hasBer(value.metrics) + berValues(end+1) = value.metrics.BER; + end +elseif iscell(value) + for valueIdx = 1:numel(value) + berValues = [berValues, extractBerValues(value{valueIdx})]; %#ok + end +end +end + +function tf = hasBer(metrics) +tf = (isstruct(metrics) && isfield(metrics, "BER")) || ... + (isobject(metrics) && isprop(metrics, "BER")); +end diff --git a/projects/Diss/MPI_revisit/algorithms/recombine_warehouses.m b/projects/Diss/MPI_revisit/algorithms/recombine_warehouses.m new file mode 100644 index 0000000..85b13b0 --- /dev/null +++ b/projects/Diss/MPI_revisit/algorithms/recombine_warehouses.m @@ -0,0 +1,539 @@ +% === DSP settings === +dsp_options = struct(); +dsp_options.mode = "run_id"; +dsp_options.recipe = @mpi_recipe_dev; +dsp_options.append_to_db = false; +dsp_options.start_occurence = 1; +dsp_options.max_occurences = 15; +dsp_options.debug_plots = false; + +dsp_options.database_type = "mysql"; + +dsp_options.dataBase = "labor"; +dsp_options.storage_path = "W:\labdata\ECOC Silas\ecoc_2025"; + +dsp_options.server = "192.168.178.192"; +dsp_options.port = 3306; +dsp_options.user = "silas"; +dsp_options.password = "silas"; + +db = DBHandler("dataBase", [dsp_options.dataBase], ... + "type", dsp_options.database_type, ... + "server", dsp_options.server, ... + "user", dsp_options.user, "password", dsp_options.password); + +scriptDir = fileparts(mfilename("fullpath")); + +whpam4_loaded = load(fullfile(scriptDir, "pam_4_results.mat")); +whpam6_loaded = load(fullfile(scriptDir, "pam_6_results.mat")); +whpam8_loaded = load(fullfile(scriptDir, "pam_8_results.mat")); + +whpam4 = whpam4_loaded.obj; +whpam6 = whpam6_loaded.obj; +whpam8 = whpam8_loaded.obj; + +whList = {whpam4, whpam6, whpam8}; +algorithmStorageNames = fieldnames(whpam4.sto); + +%% Build a lossless run_id warehouse and cache run metadata + +pamformats = [4, 6, 8]; +baudrates = [112e9, 96e9, 72e9]; +runMetaTable = queryRunMetadata(db, whList, pamformats, baudrates); + +wh_run_id_combined = mergeDataStoragesByUnion(whList); +wh_run_id_combined = addRunMetadataStorages(wh_run_id_combined, runMetaTable); + +runIdSavePath = fullfile(scriptDir, "combined_by_run_id_results.mat"); +save(runIdSavePath, "wh_run_id_combined", "runMetaTable", "algorithmStorageNames", '-v7.3'); + +fprintf("Saved run_id-combined warehouse:\n %s\n", runIdSavePath); +wh_run_id_combined.showInfo; + +%% Build a grouped config warehouse for analysis views + +configFields = ["pam_level", "symbolrate", "interference_path_length", "sir"]; +wh_config_combined = buildConfigWarehouse( ... + wh_run_id_combined, runMetaTable, algorithmStorageNames, configFields); + +configSavePath = fullfile(scriptDir, "combined_by_config_results.mat"); +save(configSavePath, "wh_config_combined", "runMetaTable", "algorithmStorageNames", '-v7.3'); + +fprintf("Saved config-grouped warehouse:\n %s\n", configSavePath); +wh_config_combined.showInfo; + +%% BER over SIR at fixed path length + +plot_options = struct(); +plot_options.path_length = 1000; +plot_options.use_boundedlines = true; +plot_options.boundedline_alpha = 0.10; +plot_options.polyfit_order_max = 3; +plot_options.fec_ber_threshold = 2e-2; +plot_options.figure_base = 7100; +plot_options.xlim = [15 35]; + +plotBerOverSirForPath(wh_config_combined, algorithmStorageNames, plot_options); + +%% Local functions + +function runMetaTable = queryRunMetadata(db, whList, pamformats, baudrates) +metaTables = {}; +metadataFields = db.getTableFieldNames('Runs'); + +for whIdx = 1:numel(whList) + curWh = whList{whIdx}; + curRunIds = curWh.parameter.run_id.values(:); + + fp = QueryFilter(); + fp.where('Runs', 'run_id', 'GREATER_EQUAL', 3153); + fp.where('Runs', 'symbolrate', 'EQUALS', baudrates(whIdx)); + fp.where('Runs', 'fiber_length', 'EQUALS', 0); + fp.where('Runs', 'db_mode', 'EQUALS', '"no_db"'); + fp.where('Runs', 'pam_level', 'EQUALS', pamformats(whIdx)); + + [dataTable, ~] = db.queryDB(fp, metadataFields); + dataTable.run_id = numericColumn(dataTable.run_id); + dataTable = dataTable(ismember(dataTable.run_id, curRunIds), :); + + missingRunIds = setdiff(curRunIds, dataTable.run_id); + if ~isempty(missingRunIds) + warning("recombine_warehouses:MissingMetadata", ... + "%d run_id(s) from PAM %.0f warehouse were not found in the metadata query.", ... + numel(missingRunIds), pamformats(whIdx)); + end + + metaTables{end+1} = dataTable; %#ok +end + +runMetaTable = vertcat(metaTables{:}); +[~, uniqueIdx] = unique(numericColumn(runMetaTable.run_id), "stable"); +runMetaTable = runMetaTable(uniqueIdx, :); + +numericFields = ["run_id", "pam_level", "symbolrate", "interference_path_length", "sir"]; +for fieldIdx = 1:numel(numericFields) + fieldName = numericFields(fieldIdx); + if ismember(fieldName, string(runMetaTable.Properties.VariableNames)) + runMetaTable.(char(fieldName)) = numericColumn(runMetaTable.(char(fieldName))); + end +end + +[~, sortIdx] = sort(runMetaTable.run_id); +runMetaTable = runMetaTable(sortIdx, :); +end + +function x = numericColumn(x) +if isnumeric(x) + x = double(x); +elseif iscell(x) + x = str2double(string(x)); +elseif isstring(x) || ischar(x) || iscategorical(x) + x = str2double(string(x)); +else + x = double(x); +end +x = x(:); +end + +function whMerged = mergeDataStoragesByUnion(whList) +templateWh = whList{1}; +paramNames = cellstr(templateWh.fn); + +for whIdx = 2:numel(whList) + if ~isequal(sort(cellstr(whList{whIdx}.fn)), sort(paramNames)) + error("recombine_warehouses:ParameterMismatch", ... + "All input warehouses must use the same parameter names."); + end +end + +mergedParams = struct(); +for paramIdx = 1:numel(paramNames) + paramName = paramNames{paramIdx}; + values = []; + + for whIdx = 1:numel(whList) + newValues = whList{whIdx}.parameter.(paramName).values(:).'; + values = [values, newValues]; %#ok + end + + values = unique(values, "stable"); + if isnumeric(values) + values = sort(values); + end + mergedParams.(paramName) = values; +end + +whMerged = DataStorage(mergedParams); + +for whIdx = 1:numel(whList) + curWh = whList{whIdx}; + curStorageNames = fieldnames(curWh.sto); + + for storageIdx = 1:numel(curStorageNames) + storageName = curStorageNames{storageIdx}; + if ~isfield(whMerged.sto, storageName) + whMerged.addStorage(storageName); + end + + for linIdx = 1:numel(curWh.sto.(storageName)) + storedValue = curWh.sto.(storageName){linIdx}; + if isempty(storedValue) + continue + end + + targetLinIdx = mapLinearIndex(curWh, whMerged, linIdx); + existingValue = whMerged.sto.(storageName){targetLinIdx}; + whMerged.sto.(storageName){targetLinIdx} = mergeStoredValue(existingValue, storedValue); + end + end +end +end + +function wh = addRunMetadataStorages(wh, runMetaTable) +metadataStorageNames = ["meta_pam_level", "meta_symbolrate", ... + "meta_interference_path_length", "meta_sir"]; +metadataTableFields = ["pam_level", "symbolrate", "interference_path_length", "sir"]; + +for fieldIdx = 1:numel(metadataStorageNames) + if ~isfield(wh.sto, metadataStorageNames(fieldIdx)) + wh.addStorage(char(metadataStorageNames(fieldIdx))); + end +end + +for linIdx = 1:wh.getLastLinIndice() + physStruct = linearIndexToStruct(wh, linIdx); + if ~isfield(physStruct, "run_id") + continue + end + + metaIdx = find(runMetaTable.run_id == physStruct.run_id, 1); + if isempty(metaIdx) + continue + end + + for fieldIdx = 1:numel(metadataStorageNames) + wh.sto.(char(metadataStorageNames(fieldIdx))){linIdx} = ... + runMetaTable.(char(metadataTableFields(fieldIdx)))(metaIdx); + end +end +end + +function whConfig = buildConfigWarehouse(whRun, runMetaTable, algorithmStorageNames, configFields) +runParamNames = cellstr(whRun.fn); +extraParamNames = setdiff(string(runParamNames), "run_id", "stable"); + +configParams = struct(); +for fieldIdx = 1:numel(configFields) + fieldName = configFields(fieldIdx); + values = unique(runMetaTable.(char(fieldName))(:).', "stable"); + if isnumeric(values) + values = sort(values); + end + configParams.(char(fieldName)) = values; +end + +for paramIdx = 1:numel(extraParamNames) + paramName = extraParamNames(paramIdx); + configParams.(char(paramName)) = whRun.parameter.(char(paramName)).values; +end + +whConfig = DataStorage(configParams); +for storageIdx = 1:numel(algorithmStorageNames) + whConfig.addStorage(algorithmStorageNames{storageIdx}); +end +whConfig.addStorage("run_id"); + +for storageIdx = 1:numel(algorithmStorageNames) + storageName = algorithmStorageNames{storageIdx}; + + for linIdx = 1:numel(whRun.sto.(storageName)) + storedValue = whRun.sto.(storageName){linIdx}; + if isempty(storedValue) + continue + end + + sourcePhys = linearIndexToStruct(whRun, linIdx); + metaIdx = find(runMetaTable.run_id == sourcePhys.run_id, 1); + if isempty(metaIdx) + continue + end + + targetArgs = configTargetArgs(whConfig, sourcePhys, runMetaTable, metaIdx, configFields); + targetLinIdx = whConfig.getIndicesByPhys(targetArgs); + + existingValue = whConfig.sto.(storageName){targetLinIdx}; + whConfig.sto.(storageName){targetLinIdx} = mergeStoredValue(existingValue, storedValue); + end +end + +for linIdx = 1:whRun.getLastLinIndice() + sourcePhys = linearIndexToStruct(whRun, linIdx); + metaIdx = find(runMetaTable.run_id == sourcePhys.run_id, 1); + if isempty(metaIdx) + continue + end + + targetArgs = configTargetArgs(whConfig, sourcePhys, runMetaTable, metaIdx, configFields); + targetLinIdx = whConfig.getIndicesByPhys(targetArgs); + whConfig.sto.run_id{targetLinIdx} = mergeUniqueNumeric( ... + whConfig.sto.run_id{targetLinIdx}, sourcePhys.run_id); +end +end + +function targetArgs = configTargetArgs(whConfig, sourcePhys, runMetaTable, metaIdx, configFields) +targetArgs = cell(1, numel(whConfig.fn)); + +for paramIdx = 1:numel(whConfig.fn) + paramName = string(whConfig.fn(paramIdx)); + if any(configFields == paramName) + targetArgs{paramIdx} = runMetaTable.(char(paramName))(metaIdx); + else + targetArgs{paramIdx} = sourcePhys.(char(paramName)); + end +end +end + +function targetLinIdx = mapLinearIndex(sourceWh, targetWh, sourceLinIdx) +sourcePhys = linearIndexToStruct(sourceWh, sourceLinIdx); +targetArgs = cell(1, numel(targetWh.fn)); + +for paramIdx = 1:numel(targetWh.fn) + paramName = char(targetWh.fn(paramIdx)); + targetArgs{paramIdx} = sourcePhys.(paramName); +end + +targetLinIdx = targetWh.getIndicesByPhys(targetArgs); +end + +function physStruct = linearIndexToStruct(wh, linIdx) +[physValues, physNames] = wh.getPhysIndicesByLinIndex(linIdx); +physStruct = struct(); + +for paramIdx = 1:numel(physNames) + physStruct.(char(physNames{paramIdx})) = physValues{paramIdx}; +end +end + +function out = mergeStoredValue(existingValue, newValue) +if isempty(existingValue) + out = newValue; + return +end + +existingPackages = asPackageCell(existingValue); +newPackages = asPackageCell(newValue); +out = [existingPackages(:); newPackages(:)].'; +end + +function packages = asPackageCell(value) +if isempty(value) + packages = {}; +elseif iscell(value) + packages = value(:).'; +else + packages = {value}; +end +end + +function out = mergeUniqueNumeric(existingValue, newValue) +if isempty(existingValue) + out = newValue; +else + out = unique([existingValue(:); newValue(:)].', "stable"); +end +end + +function plotBerOverSirForPath(whConfig, algorithmStorageNames, plotOptions) +paramNames = string(whConfig.fn); + +if ~any(paramNames == "pam_level") || ~any(paramNames == "interference_path_length") || ~any(paramNames == "sir") + error("recombine_warehouses:MissingPlotParameters", ... + "The config warehouse must contain pam_level, interference_path_length, and sir parameters."); +end + +pamLevels = whConfig.parameter.pam_level.values; +hasBlockUpdate = any(paramNames == "block_update"); +if hasBlockUpdate + blockUpdates = whConfig.parameter.block_update.values; +else + blockUpdates = NaN; +end + +if exist("linspecer", "file") + curveColors = linspecer(max(numel(algorithmStorageNames), 1)); +else + curveColors = lines(max(numel(algorithmStorageNames), 1)); +end + +figureIdx = plotOptions.figure_base; +for blockIdx = 1:numel(blockUpdates) + for pamIdx = 1:numel(pamLevels) + pamLevel = pamLevels(pamIdx); + figureIdx = figureIdx + 1; + figure(figureIdx); clf; hold on + + for storageIdx = 1:numel(algorithmStorageNames) + storageName = algorithmStorageNames{storageIdx}; + curveColor = curveColors(storageIdx, :); + + filter = struct(); + filter.pam_level = pamLevel; + filter.interference_path_length = plotOptions.path_length; + if hasBlockUpdate + filter.block_update = blockUpdates(blockIdx); + end + + [sirValues, berGroups] = collectBerBySir(whConfig, storageName, filter); + if isempty(sirValues) + continue + end + + [sirValues, sortIdx] = sort(sirValues); + berGroups = berGroups(sortIdx); + + berAvg = nan(1, numel(sirValues)); + berMin = nan(1, numel(sirValues)); + berMax = nan(1, numel(sirValues)); + + for sirIdx = 1:numel(sirValues) + rawBer = berGroups{sirIdx}; + rawBer = rawBer(isfinite(rawBer)); + if isempty(rawBer) + continue + end + + scatter(repmat(sirValues(sirIdx), size(rawBer)), rawBer, ... + 12, ... + "Marker", ".", ... + "MarkerEdgeColor", curveColor, ... + "MarkerFaceColor", curveColor, ... + "HandleVisibility", "off"); + + berAvg(sirIdx) = mean(rawBer, "omitnan"); + berMin(sirIdx) = min(rawBer); + berMax(sirIdx) = max(rawBer); + end + + validAvg = isfinite(sirValues) & isfinite(berAvg); + if ~any(validAvg) + continue + end + + if plotOptions.use_boundedlines && exist("boundedline", "file") + yLower = max(berAvg - berMin, 0); + yUpper = max(berMax - berAvg, 0); + yBounds = [yLower(:), yUpper(:)]; + + [hl, hp] = boundedline(sirValues(:), berAvg(:), yBounds, ... + "alpha", "transparency", plotOptions.boundedline_alpha, ... + "cmap", curveColor, ... + "nan", "fill", ... + "orientation", "vert"); + set(hl, "LineStyle", "none", "Marker", "none", "HandleVisibility", "off"); + set(hp, "HandleVisibility", "off", "LineStyle", "none"); + end + + scatter(sirValues(validAvg), berAvg(validAvg), ... + 54, ... + "Marker", "o", ... + "MarkerEdgeColor", curveColor, ... + "MarkerFaceColor", "none", ... + "LineWidth", 1.2, ... + "DisplayName", storageName); + + fitMask = validAvg & berAvg > 0; + if nnz(fitMask) >= 2 + fitOrder = min(plotOptions.polyfit_order_max, nnz(fitMask) - 1); + fitCoeff = polyfit(sirValues(fitMask), log10(berAvg(fitMask)), fitOrder); + xFit = linspace(min(sirValues(fitMask)), max(sirValues(fitMask)), 300); + yFit = 10 .^ polyval(fitCoeff, xFit); + + plot(xFit, yFit, ... + "LineWidth", 1.2, ... + "LineStyle", "--", ... + "Marker", "none", ... + "Color", curveColor, ... + "HandleVisibility", "off"); + end + end + + if hasBlockUpdate + title(sprintf("BER over SIR, PAM %.0f, path %.0f m, block update = %g", ... + pamLevel, plotOptions.path_length, blockUpdates(blockIdx))); + else + title(sprintf("BER over SIR, PAM %.0f, path %.0f m", ... + pamLevel, plotOptions.path_length)); + end + xlabel("SIR (dB)"); + ylabel("BER"); + xlim(plotOptions.xlim); + grid on + box on + + if exist("beautifyBERplot", "file") + beautifyBERplot("logscale", true, "setcolors", false, "setmarkers", false); + else + set(gca, "YScale", "log"); + end + legend("Location", "best", "Interpreter", "none"); + end +end +end + +function [sirValues, berGroups] = collectBerBySir(whConfig, storageName, filter) +sirValues = []; +berGroups = {}; + +for linIdx = 1:numel(whConfig.sto.(storageName)) + storedValue = whConfig.sto.(storageName){linIdx}; + if isempty(storedValue) + continue + end + + physStruct = linearIndexToStruct(whConfig, linIdx); + if ~matchesFilter(physStruct, filter) + continue + end + + berValues = extractBerValues(storedValue); + if isempty(berValues) + continue + end + + sirValue = physStruct.sir; + sirIdx = find(sirValues == sirValue, 1); + if isempty(sirIdx) + sirValues(end+1) = sirValue; %#ok + berGroups{end+1} = berValues; %#ok + else + berGroups{sirIdx} = [berGroups{sirIdx}, berValues]; %#ok + end +end +end + +function tf = matchesFilter(physStruct, filter) +tf = true; +filterFields = fieldnames(filter); + +for fieldIdx = 1:numel(filterFields) + fieldName = filterFields{fieldIdx}; + if ~isfield(physStruct, fieldName) || physStruct.(fieldName) ~= filter.(fieldName) + tf = false; + return + end +end +end + +function berValues = extractBerValues(value) +berValues = []; + +if isstruct(value) + if isfield(value, "metrics") && isfield(value.metrics, "BER") + berValues(end+1) = value.metrics.BER; + end +elseif iscell(value) + for valueIdx = 1:numel(value) + berValues = [berValues, extractBerValues(value{valueIdx})]; %#ok + end +end +end diff --git a/projects/Diss/MPI_revisit/investigate_mpi_algorithms.m b/projects/Diss/MPI_revisit/investigate_mpi_algorithms.m index 5eb1a0f..60bc296 100644 --- a/projects/Diss/MPI_revisit/investigate_mpi_algorithms.m +++ b/projects/Diss/MPI_revisit/investigate_mpi_algorithms.m @@ -3,8 +3,8 @@ dsp_options = struct(); dsp_options.mode = "run_id"; dsp_options.recipe = @mpi_recipe_dev; dsp_options.append_to_db = false; -dsp_options.start_occurence = 2; -dsp_options.max_occurences = 1; +dsp_options.start_occurence = 1; +dsp_options.max_occurences = 15; dsp_options.debug_plots = false; dsp_options.database_type = "mysql"; @@ -23,95 +23,58 @@ db = DBHandler("dataBase", [dsp_options.dataBase],... "user", dsp_options.user, "password", dsp_options.password); %% -fp = QueryFilter(); -fp.where('Runs','run_id','GREATER_EQUAL',3153); -fp.where('Runs', 'symbolrate', 'EQUALS', 112e9); -fp.where('Runs', 'fiber_length', 'EQUALS', 0); -fp.where('Runs', 'interference_path_length', 'EQUALS', 1000); -fp.where('Runs', 'sir', 'LESS_EQUAL', 20); -fp.where('Runs', 'db_mode', 'EQUALS', '"no_db"'); -% fp.where('Runs', 'is_mpi', 'EQUALS', 1); -fp.where('Runs', 'pam_level', 'EQUALS', 4); -% fp.where('Runs', 'v_bias', 'EQUALS', 2.65); -[dataTable,~] = db.queryDB(fp, db.getTableFieldNames('Runs')); +pamformats = [4,6,8]; +baudrates = [112e9,96e9,72e9]; -% [~, uniqueSirRows] = unique(dataTable.sir, "stable"); -% dataTable = dataTable(uniqueSirRows, :); +for i = 1:3 + + B = baudrates(i); + M = pamformats(i); + + fp = QueryFilter(); + fp.where('Runs','run_id','GREATER_EQUAL',3153); + fp.where('Runs', 'symbolrate', 'EQUALS', B); % 72 96 112 + fp.where('Runs', 'fiber_length', 'EQUALS', 0); + fp.where('Runs', 'interference_path_length', 'EQUALS', 1000); + fp.where('Runs', 'sir', 'LESS_EQUAL', 20); + fp.where('Runs', 'db_mode', 'EQUALS', '"no_db"'); + % fp.where('Runs', 'is_mpi', 'EQUALS', 1); + fp.where('Runs', 'pam_level', 'EQUALS', M); + % fp.where('Runs', 'v_bias', 'EQUALS', 2.65); + + [dataTable,~] = db.queryDB(fp, db.getTableFieldNames('Runs')); + + [~, sortIdx] = sort(dataTable.sir, 'descend'); + dataTable = dataTable(sortIdx, :); + run_ids = dataTable.run_id; + + %% === Warehouse setup === + dsp_options.userParameters = struct(); + dsp_options.userParameters.block_update = 1;%[1,2,4,8,16,32,64,112,224,448,512,1024,2048,2048*2,2048*4];%%logspace(-3.8,-1,22);%[linspace(2,4096,22)]; + wh = DataStorage(dsp_options.userParameters); + + + %% + n_realizations = (dsp_options.max_occurences - dsp_options.start_occurence + 1); + n_userparams = prod(wh.dim); + n_run_ids = numel(run_ids); + parallel_jobs = n_userparams * n_run_ids; + queried_jobs = n_realizations * n_userparams * n_run_ids; + + fprintf("-> [ %d run_id(s) × %d userParam combination(s) = %d parallel job(s) ] × %d realizations = %d total jobs \n", ... + n_run_ids, n_userparams, parallel_jobs, n_realizations, queried_jobs); + + %% === Run === + % submitJobs returns the raw per-job results and the filled Warehouse. For a + % single run_id and remove_dc = [0, 1], results is a 2-by-1 cell array. + [results, wh] = submitJobs(run_ids, dsp_options, processingMode.serial, ... + "wh", wh, ... + "waitbar", true); + + % savepath = fullfile("C:","Users","Silas","Documents","MATLAB","imdd_simulation","projects","Diss","MPI_revisit","algorithms",sprintf("pam_%d_results.mat",M)); + % save(wh,savepath) -[~, sortIdx] = sort(dataTable.sir, 'descend'); -dataTable = dataTable(sortIdx, :); -dataTable = dataTable(1, :); -run_ids = dataTable.run_id; -if isempty(run_ids) - error("run_minimal_recipe:MissingRunIds", ... - "Set run_ids to one or more known run IDs before running this example."); end -%% === Warehouse setup === -dsp_options.userParameters = struct(); -% dsp_options.userParameters.smoothing_length = [0,linspace(100,1000,10),2500,5000,10000]; -wh = DataStorage(dsp_options.userParameters); - - -%% -n_realizations = (dsp_options.max_occurences - dsp_options.start_occurence + 1); -n_userparams = prod(wh.dim); -n_run_ids = numel(run_ids); -parallel_jobs = n_userparams * n_run_ids; -queried_jobs = n_realizations * n_userparams * n_run_ids; - -fprintf("-> [ %d run_id(s) × %d userParam combination(s) = %d parallel job(s) ] × %d realizations = %d total jobs \n", ... - n_run_ids, n_userparams, parallel_jobs, n_realizations, queried_jobs); - -%% === Run === -% submitJobs returns the raw per-job results and the filled Warehouse. For a -% single run_id and remove_dc = [0, 1], results is a 2-by-1 cell array. -[results, wh] = submitJobs(run_ids, dsp_options, processingMode.serial, ... - "wh", wh, ... - "waitbar", true); - -%% Analyze - -storageNames = fieldnames(wh.sto); -result = wh.sto.(storageNames{1}); -result = result(:).'; - -% Each stored entry is a package cell containing one or more occurrences. -ber_all = cell(1,numel(result)); -for result_idx = 1:numel(result) - packageCell = result{result_idx}; - if isempty(packageCell) - ber_all{result_idx} = NaN; - continue - end - - ber_values = nan(1,numel(packageCell)); - for package_idx = 1:numel(packageCell) - if isstruct(packageCell{package_idx}) && isfield(packageCell{package_idx},"metrics") - ber_values(package_idx) = packageCell{package_idx}.metrics.BER; - end - end - ber_all{result_idx} = ber_values; -end - -maxPackages = max(cellfun(@numel,ber_all)); -ber_mat = nan(maxPackages,numel(ber_all)); -for k = 1:numel(ber_all) - ber_mat(1:numel(ber_all{k}),k) = ber_all{k}; -end -ber = mean(ber_mat,1,"omitnan"); - -x = dataTable.sir(:).'; -if numel(x) ~= numel(ber) - x = 1:numel(ber); -end - -figure(2026); clf; hold on -plot(x,ber); -for k = 1:numel(x) - scatter(repmat(x(k),maxPackages,1),ber_mat(:,k)) -end -beautifyBERplot("logscale",true,"setcolors",false,"setmarkers",true); - diff --git a/projects/Diss/MPI_revisit/parallelization_analysis/RUN_parallel_analysis.m b/projects/Diss/MPI_revisit/parallelization_analysis/RUN_parallel_analysis.m new file mode 100644 index 0000000..f786e4c --- /dev/null +++ b/projects/Diss/MPI_revisit/parallelization_analysis/RUN_parallel_analysis.m @@ -0,0 +1,73 @@ +% === DSP settings === +dsp_options = struct(); +dsp_options.mode = "run_id"; +dsp_options.recipe = @mpi_recipe_dev; +dsp_options.append_to_db = false; +dsp_options.start_occurence = 1; +dsp_options.max_occurences = 15; +dsp_options.debug_plots = false; + +dsp_options.database_type = "mysql"; + +dsp_options.dataBase = "labor"; +dsp_options.storage_path = "W:\labdata\ECOC Silas\ecoc_2025"; + +dsp_options.server = "192.168.178.192"; +dsp_options.port = 3306; +dsp_options.user = "silas"; +dsp_options.password = "silas"; + +db = DBHandler("dataBase", [dsp_options.dataBase],... + "type", dsp_options.database_type,... + "server", dsp_options.server,... + "user", dsp_options.user, "password", dsp_options.password); + +%% +fp = QueryFilter(); +fp.where('Runs','run_id','GREATER_EQUAL',3153); +fp.where('Runs', 'symbolrate', 'EQUALS', 72e9); % 72 96 112 +fp.where('Runs', 'fiber_length', 'EQUALS', 0); +% fp.where('Runs', 'interference_path_length', 'EQUALS', 1000); +% fp.where('Runs', 'sir', 'LESS_EQUAL', 50); +fp.where('Runs', 'db_mode', 'EQUALS', '"no_db"'); +% fp.where('Runs', 'is_mpi', 'EQUALS', 1); +fp.where('Runs', 'pam_level', 'EQUALS', 8); +% fp.where('Runs', 'v_bias', 'EQUALS', 2.65); + +[dataTable,~] = db.queryDB(fp, db.getTableFieldNames('Runs')); + +% [~, uniqueSirRows] = unique(dataTable.sir, "stable"); +% dataTable = dataTable(uniqueSirRows, :); + +[~, sortIdx] = sort(dataTable.sir, 'descend'); +dataTable = dataTable(sortIdx, :); +% dataTable = dataTable(1, :); +run_ids = dataTable.run_id; + +if isempty(run_ids) + error("run_minimal_recipe:MissingRunIds", ... + "Set run_ids to one or more known run IDs before running this example."); +end + +%% === Warehouse setup === +dsp_options.userParameters = struct(); +dsp_options.userParameters.block_update = [1,2,4,8,16,32,64,112,224,448,512,1024,2048,2048*2,2048*4];%%logspace(-3.8,-1,22);%[linspace(2,4096,22)]; +wh = DataStorage(dsp_options.userParameters); + + +%% +n_realizations = (dsp_options.max_occurences - dsp_options.start_occurence + 1); +n_userparams = prod(wh.dim); +n_run_ids = numel(run_ids); +parallel_jobs = n_userparams * n_run_ids; +queried_jobs = n_realizations * n_userparams * n_run_ids; + +fprintf("-> [ %d run_id(s) × %d userParam combination(s) = %d parallel job(s) ] × %d realizations = %d total jobs \n", ... + n_run_ids, n_userparams, parallel_jobs, n_realizations, queried_jobs); + +%% === Run === +% submitJobs returns the raw per-job results and the filled Warehouse. For a +% single run_id and remove_dc = [0, 1], results is a 2-by-1 cell array. +[results, wh] = submitJobs(run_ids, dsp_options, processingMode.parallel, ... + "wh", wh, ... + "waitbar", true); diff --git a/projects/Diss/MPI_revisit/parallelization_analysis/parallelization_pam4.fig b/projects/Diss/MPI_revisit/parallelization_analysis/parallelization_pam4.fig new file mode 100644 index 0000000000000000000000000000000000000000..b2482da3aae9c70db063b8d49c09d62691818abc GIT binary patch literal 12500 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 W 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 literal 0 HcmV?d00001 diff --git a/projects/Diss/MPI_revisit/parallelization_analysis/plot_parallelization_vs_sir_pam4.m b/projects/Diss/MPI_revisit/parallelization_analysis/plot_parallelization_vs_sir_pam4.m new file mode 100644 index 0000000..368a72e --- /dev/null +++ b/projects/Diss/MPI_revisit/parallelization_analysis/plot_parallelization_vs_sir_pam4.m @@ -0,0 +1,360 @@ +%% Analyze +% === DSP settings === +dsp_options = struct(); +dsp_options.mode = "run_id"; +dsp_options.recipe = @mpi_recipe_dev; +dsp_options.append_to_db = false; +dsp_options.start_occurence = 1; +dsp_options.max_occurences = 15; +dsp_options.debug_plots = false; + +dsp_options.database_type = "mysql"; + +dsp_options.dataBase = "labor"; +dsp_options.storage_path = "W:\labdata\ECOC Silas\ecoc_2025"; + +dsp_options.server = "192.168.178.192"; +dsp_options.port = 3306; +dsp_options.user = "silas"; +dsp_options.password = "silas"; + +db = DBHandler("dataBase", [dsp_options.dataBase],... + "type", dsp_options.database_type,... + "server", dsp_options.server,... + "user", dsp_options.user, "password", dsp_options.password); + +%% + +fp = QueryFilter(); +fp.where('Runs','run_id','GREATER_EQUAL',3153); +fp.where('Runs', 'symbolrate', 'EQUALS', 72e9); % 72 96 112 +fp.where('Runs', 'fiber_length', 'EQUALS', 0); +fp.where('Runs', 'interference_path_length', 'EQUALS', 1000); +% fp.where('Runs', 'sir', 'LESS_EQUAL', 50); +fp.where('Runs', 'db_mode', 'EQUALS', '"no_db"'); +% fp.where('Runs', 'is_mpi', 'EQUALS', 1); +fp.where('Runs', 'pam_level', 'EQUALS', 8); +% fp.where('Runs', 'v_bias', 'EQUALS', 2.65); + +[dataTable,~] = db.queryDB(fp, db.getTableFieldNames('Runs')); + +% [~, uniqueSirRows] = unique(dataTable.sir, "stable"); +% dataTable = dataTable(uniqueSirRows, :); + +[~, sortIdx] = sort(dataTable.sir, 'descend'); +dataTable = dataTable(sortIdx, :); +% dataTable = dataTable(1, :); +run_ids = dataTable.run_id; +%% + +wh_ = load("C:\Users\Silas\Documents\MATLAB\imdd_simulation\projects\Diss\MPI_revisit\parallelization_analysis\wh_block_update_pam8_combined.mat"); +wh = wh_.wh; + +% wh_ = load("C:\Users\Silas\Documents\MATLAB\imdd_simulation\projects\Diss\MPI_revisit\parallelization_analysis\wh_block_update_pam4_short_blocks.mat"); +% wh2 = wh_.wh; +% +% wh = mergeDataStorages(wh1,wh2); + +%% + + +storageNames = fieldnames(wh.sto); +ber_by_storage = struct(); +ber_mat_by_storage = struct(); + +sir_values = dataTable.sir(:).'; +block_updates = wh.parameter.block_update.values; +storage_parameter_names = cellstr(wh.fn); +block_axis = find(strcmp(storage_parameter_names,"block_update"),1); + +if exist('linspecer','file') + curve_colors = linspecer(max(numel(storageNames),1)); +else + curve_colors = lines(max(numel(storageNames),1)); +end + +fec_ber_threshold = 2e-2;%3.8e-3; +fit_coeff_by_storage = struct(); +required_sir_fec_by_storage = struct(); +for storage_idx = 1:numel(storageNames) + storageName = storageNames{storage_idx}; + fit_coeff_by_storage.(storageName) = cell(1,numel(block_updates)); + required_sir_fec_by_storage.(storageName) = nan(1,numel(block_updates)); +end + +for block_idx = 1:numel(block_updates) + block_update = block_updates(block_idx); + + figure(3000 + block_idx); clf; hold on + for storage_idx = 1:numel(storageNames) + storageName = storageNames{storage_idx}; + curve_color = curve_colors(storage_idx,:); + result = wh.sto.(storageName); + + if ~isempty(block_axis) && size(result,block_axis) == numel(block_updates) + result_subs = repmat({':'},1,ndims(result)); + result_subs{block_axis} = block_idx; + result_for_block = result(result_subs{:}); + result_for_block = result_for_block(:).'; + else + result_for_block = result(:).'; + end + + % Each stored entry is a package cell containing one or more occurrences. + ber_all = cell(1,numel(result_for_block)); + for result_idx = 1:numel(result_for_block) + packageCell = result_for_block{result_idx}; + if isempty(packageCell) + ber_all{result_idx} = NaN; + continue + end + + ber_values = nan(1,numel(packageCell)); + for package_idx = 1:numel(packageCell) + if isstruct(packageCell{package_idx}) && isfield(packageCell{package_idx},"metrics") + ber_values(package_idx) = packageCell{package_idx}.metrics.BER; + end + end + ber_all{result_idx} = ber_values; + end + + maxPackages = max(cellfun(@numel,ber_all)); + ber_mat = nan(maxPackages,numel(ber_all)); + for k = 1:numel(ber_all) + ber_mat(1:numel(ber_all{k}),k) = ber_all{k}; + end + + % Replace outliers in ber_mat with NaN (operate column-wise). + for col = 1:size(ber_mat,2) + colData = ber_mat(:,col); + if all(isnan(colData)); continue; end + mask = isoutlier(colData); + ber_mat(mask,col) = NaN; + end + + ber = mean(ber_mat,1,"omitnan"); + ber_min = nan(1,numel(ber)); + ber_max = nan(1,numel(ber)); + for k = 1:numel(ber) + ber_here = ber_mat(:,k); + ber_here = ber_here(isfinite(ber_here)); + if isempty(ber_here) + continue + end + ber_min(k) = min(ber_here); + ber_max(k) = max(ber_here); + end + + x = sir_values; + if numel(x) ~= numel(ber) + x = 1:numel(ber); + end + + ber_by_storage.(storageName){block_idx} = ber; + ber_mat_by_storage.(storageName){block_idx} = ber_mat; + + y_lower = max(ber - ber_min,0); + y_upper = max(ber_max - ber,0); + y_bounds = [y_lower(:), y_upper(:)]; + + [hl, hp] = boundedline(x(:),ber(:),y_bounds, ... + 'alpha', 'transparency', 0.1, ... + 'cmap', curve_color, ... + 'nan', 'fill', ... + 'orientation', 'vert'); + set(hl, ... + 'LineWidth',1.4, ... + 'LineStyle','none', ... + 'Marker','o', ... + 'Markersize',5,... + 'Color',curve_color, ... + 'DisplayName',storageName); + set(hp, ... + 'HandleVisibility','off', ... + 'LineStyle','none'); + + for k = 1:numel(x) + scatter(repmat(x(k),maxPackages,1),ber_mat(:,k), ... + 16, ... + 'Marker','.', ... + 'MarkerEdgeColor',curve_color, ... + 'MarkerFaceColor',curve_color, ... + 'HandleVisibility','off'); + end + + fit_mask = isfinite(x) & isfinite(ber) & ber > 0; + if nnz(fit_mask) >= 2 + fit_order = min(3,nnz(fit_mask)-1); + fit_coeff = polyfit(x(fit_mask),log10(ber(fit_mask)),fit_order); + x_fit = linspace(min(x(fit_mask)),max(x(fit_mask)),300); + y_fit = 10.^polyval(fit_coeff,x_fit); + fit_coeff_by_storage.(storageName){block_idx} = fit_coeff; + + sir_req = NaN; + threshold_mask = isfinite(y_fit) & y_fit <= fec_ber_threshold; + if any(threshold_mask) + first_threshold_idx = find(threshold_mask,1,"first"); + if first_threshold_idx == 1 + sir_req = x_fit(first_threshold_idx); + else + x_pair = x_fit(first_threshold_idx-1:first_threshold_idx); + y_pair = log10(y_fit(first_threshold_idx-1:first_threshold_idx)); + if all(isfinite(y_pair)) && diff(y_pair) ~= 0 + sir_req = interp1(y_pair,x_pair,log10(fec_ber_threshold), ... + "linear","extrap"); + else + sir_req = x_fit(first_threshold_idx); + end + end + end + required_sir_fec_by_storage.(storageName)(block_idx) = sir_req; + + plot(x_fit,y_fit, ... + 'LineWidth',1.2, ... + 'LineStyle','--', ... + 'Marker','none', ... + 'Color',curve_color, ... + 'HandleVisibility','off'); + end + end + + title(sprintf("BER over SIR, block update = %g",block_update)); + xlabel("SIR (dB)"); + ylabel("BER"); + xlim([15 35]); + + beautifyBERplot("logscale",true,"setcolors",false,"setmarkers",false); + legend("Location","best","Interpreter","none"); +end + +%% Required SIR to reach FEC over parallelization + +figure(5000); clf; hold on +for storage_idx = 1:numel(storageNames) + storageName = storageNames{storage_idx}; + curve_color = curve_colors(storage_idx,:); + required_sir = required_sir_fec_by_storage.(storageName); + valid = isfinite(block_updates) & isfinite(required_sir); + + if ~any(valid) + continue + end + + plot(block_updates(valid),required_sir(valid), ... + 'LineWidth',1.4, ... + 'LineStyle','-', ... + 'Marker','o', ... + 'MarkerSize',5, ... + 'Color',curve_color, ... + 'DisplayName',storageName); +end + +set(gca,'XScale','log'); +xticks(block_updates); +xticklabels(string(block_updates)); +grid on +box on +xlabel("Parallelization / block update"); +ylabel(sprintf("Required SIR at BER = %.1e (dB)",fec_ber_threshold)); +title("Required SIR to reach FEC over parallelization"); +legend("Location","best","Interpreter","none"); + + +%% + + +function whMerged = mergeDataStorages(varargin) +% mergeDataStorages merges compatible DataStorage objects by physical indices. +% Existing duplicate entries are concatenated when both values are package cells. + +whList = varargin; +templateWh = whList{1}; +paramNames = cellstr(templateWh.fn); + +mergedParams = struct(); +for param_idx = 1:numel(paramNames) + paramName = paramNames{param_idx}; + values = templateWh.parameter.(paramName).values(:).'; + + for wh_idx = 2:numel(whList) + curWh = whList{wh_idx}; + if ~isequal(sort(cellstr(curWh.fn)),sort(paramNames)) + error("mergeDataStorages:ParameterMismatch", ... + "All warehouses must use the same parameter names."); + end + if ~isfield(curWh.parameter,paramName) + error("mergeDataStorages:ParameterMismatch", ... + "Warehouse %d does not contain parameter '%s'.",wh_idx,paramName); + end + + newValues = curWh.parameter.(paramName).values(:).'; + for value_idx = 1:numel(newValues) + if ~ismember(newValues(value_idx),values) + values(end+1) = newValues(value_idx); %#ok + end + end + end + + if strcmp(paramName,"block_update") && isnumeric(values) + values = sort(values); + end + + mergedParams.(paramName) = values; +end + +whMerged = DataStorage(mergedParams); + +for wh_idx = 1:numel(whList) + curWh = whList{wh_idx}; + curStorageNames = fieldnames(curWh.sto); + + for storage_idx = 1:numel(curStorageNames) + storageName = curStorageNames{storage_idx}; + if ~isfield(whMerged.sto,storageName) + whMerged.addStorage(storageName); + end + + for lin_idx = 1:numel(curWh.sto.(storageName)) + storedValue = curWh.sto.(storageName){lin_idx}; + if isempty(storedValue) + continue + end + + [physValues,physNames] = curWh.getPhysIndicesByLinIndex(lin_idx); + physNames = cellfun(@char,physNames,'UniformOutput',false); + targetSubscripts = cell(1,numel(whMerged.fn)); + + for param_idx = 1:numel(whMerged.fn) + paramName = char(whMerged.fn(param_idx)); + sourceParamIdx = find(strcmp(physNames,paramName),1); + if isempty(sourceParamIdx) + error("mergeDataStorages:ParameterMismatch", ... + "Storage entry is missing parameter '%s'.",paramName); + end + targetSubscripts{param_idx} = whMerged.getIndexByPhys(paramName,physValues{sourceParamIdx}); + end + + if isscalar(targetSubscripts) + targetLinIdx = targetSubscripts{1}; + else + targetLinIdx = sub2ind(whMerged.getStorageSize(),targetSubscripts{:}); + end + + existingValue = whMerged.sto.(storageName){targetLinIdx}; + whMerged.sto.(storageName){targetLinIdx} = mergeStoredValue(existingValue,storedValue); + end + end +end +end + +function out = mergeStoredValue(existingValue,newValue) +if isempty(existingValue) + out = newValue; +elseif iscell(existingValue) && iscell(newValue) + out = [existingValue(:); newValue(:)].'; +else + out = newValue; +end +end + + diff --git a/projects/Diss/MPI_revisit/plot_mpi_timesignal.m b/projects/Diss/MPI_revisit/plot_mpi_timesignal.m index ec3462c..dcd4087 100644 --- a/projects/Diss/MPI_revisit/plot_mpi_timesignal.m +++ b/projects/Diss/MPI_revisit/plot_mpi_timesignal.m @@ -127,7 +127,9 @@ for sirval = [20,30,50] pngTikzPath = "04_Experimental_Evaluation/tikz/mpi/" + exportName + "-1.png"; figure(sirval + pathlen); - exportNakedPlotWithTikz(gca, pngFile, tikzFile, pngTikzPath, 150); + exportLevelScatterTikz(gca, pngFile, tikzFile, pngTikzPath, ... + "resolutionDpi", 150, ... + "generatedBy", "plot_mpi_timesignal.m"); end end @@ -145,309 +147,3 @@ end % var_slope = p(1); % var_offset = p(2);c -function exportNakedPlotWithTikz(sourceAx, pngFile, tikzFile, pngTikzPath, resolutionDpi) -outputDir = fileparts(pngFile); -if ~exist(outputDir, "dir") - mkdir(outputDir); -end - -exportScatterLayerPng(sourceAx, pngFile, resolutionDpi); - -linePlots = collectTikzLinePlots(sourceAx); -textAnnotations = collectTikzTextAnnotations(sourceAx); -writeTikzPngAxis(tikzFile, pngTikzPath, sourceAx, linePlots, textAnnotations); -end - -function exportScatterLayerPng(sourceAx, pngFile, resolutionDpi) -sourceFig = ancestor(sourceAx, "figure"); -xLimits = sourceAx.XLim; -yLimits = sourceAx.YLim; -scatterHandles = findGraphicsObjectsByType(sourceAx, "scatter"); - -exportFig = figure( ... - "Visible", "off", ... - "Color", "white", ... - "Units", sourceFig.Units, ... - "Position", sourceFig.Position); -cleanupFigure = onCleanup(@() close(exportFig)); - -exportAx = copyobj(sourceAx, exportFig); -exportAx.Units = "normalized"; -exportAx.Position = [0 0 1 1]; -exportAx.XLim = xLimits; -exportAx.YLim = yLimits; -exportAx.XLimMode = "manual"; -exportAx.YLimMode = "manual"; -stripAxesToScatterOnly(exportAx); -hideAxesInkForRasterExport(exportAx); - -fprintf("Exporting scatter PNG with XLim=[%g %g], YLim=[%g %g], scatter objects=%d: %s\n", ... - xLimits(1), xLimits(2), yLimits(1), yLimits(2), numel(scatterHandles), pngFile); -drawnow; -exportFig.PaperPositionMode = "auto"; -print(exportFig, char(pngFile), "-dpng", sprintf("-r%d", resolutionDpi)); -end - -function stripAxesToScatterOnly(ax) -plotObjects = findall(ax); -for objIdx = 1:numel(plotObjects) - obj = plotObjects(objIdx); - if obj == ax || ~isvalid(obj) - continue - end - - objType = string(get(obj, "Type")); - if lower(objType) ~= "scatter" - delete(obj); - end -end -end - -function hideAxesInkForRasterExport(ax) -ax.Visible = "on"; -ax.Color = "white"; -ax.Box = "off"; -ax.XGrid = "off"; -ax.YGrid = "off"; -ax.XMinorGrid = "off"; -ax.YMinorGrid = "off"; -ax.XTick = []; -ax.YTick = []; -ax.XColor = "white"; -ax.YColor = "white"; -ax.Title.String = ""; -ax.XLabel.String = ""; -ax.YLabel.String = ""; -end - -function handles = findGraphicsObjectsByType(parentHandle, objectType) -allHandles = findall(parentHandle); -matches = false(size(allHandles)); -for handleIdx = 1:numel(allHandles) - currentHandle = allHandles(handleIdx); - if ~isvalid(currentHandle) - continue - end - - matches(handleIdx) = lower(string(get(currentHandle, "Type"))) == lower(string(objectType)); -end - -handles = allHandles(matches); -end - -function linePlots = collectTikzLinePlots(sourceAx) -lineHandles = findGraphicsObjectsByType(sourceAx, "line"); -lineHandles = flipud(lineHandles(:)); - -linePlots = repmat(struct( ... - "xData", [], ... - "yData", [], ... - "color", [], ... - "lineWidth", []), numel(lineHandles), 1); -validLineCount = 0; - -for lineIdx = 1:numel(lineHandles) - lineHandle = lineHandles(lineIdx); - xData = lineHandle.XData(:); - yData = lineHandle.YData(:); - validSamples = isfinite(xData) & isfinite(yData); - - if ~any(validSamples) - continue - end - - validLineCount = validLineCount + 1; - linePlots(validLineCount).xData = xData(validSamples); - linePlots(validLineCount).yData = yData(validSamples); - linePlots(validLineCount).color = lineHandle.Color; - linePlots(validLineCount).lineWidth = lineHandle.LineWidth; -end - -linePlots = linePlots(1:validLineCount); -end - -function textAnnotations = collectTikzTextAnnotations(sourceAx) -textHandles = findGraphicsObjectsByType(sourceAx, "text"); -textHandles = flipud(textHandles(:)); -xLimits = sourceAx.XLim; -yLimits = sourceAx.YLim; - -textAnnotations = repmat(struct( ... - "x", [], ... - "y", [], ... - "text", "", ... - "anchor", "center"), numel(textHandles), 1); -validTextCount = 0; - -for textIdx = 1:numel(textHandles) - textHandle = textHandles(textIdx); - labelText = string(textHandle.String); - if strlength(strtrim(labelText)) == 0 - continue - end - - textPosition = textHandle.Position; - if textPosition(1) < xLimits(1) || textPosition(1) > xLimits(2) || ... - textPosition(2) < yLimits(1) || textPosition(2) > yLimits(2) - continue - end - - validTextCount = validTextCount + 1; - textAnnotations(validTextCount).x = textPosition(1); - textAnnotations(validTextCount).y = textPosition(2); - textAnnotations(validTextCount).text = labelText; - textAnnotations(validTextCount).anchor = matlabTextAlignmentToTikzAnchor( ... - textHandle.HorizontalAlignment, textHandle.VerticalAlignment); -end - -textAnnotations = textAnnotations(1:validTextCount); -end - -function writeTikzPngAxis(tikzFile, pngTikzPath, sourceAx, linePlots, textAnnotations) -outputDir = fileparts(tikzFile); -if ~exist(outputDir, "dir") - mkdir(outputDir); -end - -xLimits = sourceAx.XLim; -yLimits = sourceAx.YLim; -fid = fopen(tikzFile, "w"); -if fid < 0 - error("plot_mpi_timesignal:TikzOpenFailed", ... - "Could not open TikZ export file: %s", tikzFile); -end -cleanupFile = onCleanup(@() fclose(fid)); - -axisOptions = { - " every axis/.append style={font=\scriptsize}," - "width=\fwidth," - "height=\fheight," - "at={(0\fwidth,0\fheight)}," - "scale only axis," - "axis on top," - "xmin=" + formatPgfNumber(xLimits(1)) + "," - "xmax=" + formatPgfNumber(xLimits(2)) + "," - "xlabel style={font=\color{white!15!black}\small}," - "xlabel={Time in $\mu$s}," - "ymin=" + formatPgfNumber(yLimits(1)) + "," - "ymax=" + formatPgfNumber(yLimits(2)) + "," - "ylabel style={font=\color{white!15!black}\small}," - "ylabel={Normalized Amplitude}," - "axis background/.style={fill=white}," - "xmajorgrids," - "ymajorgrids," - "grid style={line width=0.4pt, dotted, color=black!20}," - "scaled ticks=false," - "tick label style={/pgf/number format/fixed, /pgf/number format/1000 sep={}}," - "legend columns=1" - }; - -fprintf(fid, "%% This file was generated by plot_mpi_timesignal.m.\n"); -fprintf(fid, "%%\n"); -for lineIdx = 1:numel(linePlots) - fprintf(fid, "%s\n", formatTikzColorDefinition(lineIdx, linePlots(lineIdx).color)); -end -if ~isempty(linePlots) - fprintf(fid, "%%\n"); -end -fprintf(fid, "%s\n\n", "\begin{tikzpicture}"); -fprintf(fid, "%s\n", "\begin{axis}[%"); -for optionIdx = 1:numel(axisOptions) - fprintf(fid, "%s\n", axisOptions{optionIdx}); -end -fprintf(fid, "%s\n", "]"); - -graphicsLine = sprintf( ... - "\\addplot [forget plot] graphics [xmin=%s, xmax=%s, ymin=%s, ymax=%s] {%s};", ... - formatPgfNumber(xLimits(1)), ... - formatPgfNumber(xLimits(2)), ... - formatPgfNumber(yLimits(1)), ... - formatPgfNumber(yLimits(2)), ... - char(strrep(pngTikzPath, "\", "/"))); -fprintf(fid, "%s\n\n", graphicsLine); -writeTikzLinePlots(fid, linePlots); -writeTikzTextAnnotations(fid, textAnnotations); -fprintf(fid, "%s\n\n", "\end{axis}"); -fprintf(fid, "%s", "\end{tikzpicture}%"); -end - -function valueText = formatPgfNumber(value) -valueText = string(sprintf("%.15g", value)); -end - -function colorDefinition = formatTikzColorDefinition(colorIdx, rgbColor) -colorDefinition = sprintf( ... - "\\definecolor{mycolor%d}{rgb}{%.5f,%.5f,%.5f}%%", ... - colorIdx, rgbColor(1), rgbColor(2), rgbColor(3)); -end - -function writeTikzLinePlots(fid, linePlots) -for lineIdx = 1:numel(linePlots) - fprintf(fid, "\\addplot [color=mycolor%d, line width=%.1fpt, forget plot]\n", ... - lineIdx, linePlots(lineIdx).lineWidth); - fprintf(fid, " table[row sep=crcr]{%%\n"); - - for sampleIdx = 1:numel(linePlots(lineIdx).xData) - fprintf(fid, "%s\t%s\\\\\n", ... - formatPgfNumber(linePlots(lineIdx).xData(sampleIdx)), ... - formatPgfNumber(linePlots(lineIdx).yData(sampleIdx))); - end - - fprintf(fid, "};\n\n"); -end -end - -function writeTikzTextAnnotations(fid, textAnnotations) -for textIdx = 1:numel(textAnnotations) - fprintf(fid, "\\node[font=\\scriptsize, anchor=%s, fill=white, draw=black!40, rounded corners=2pt, inner sep=2pt]\n", ... - textAnnotations(textIdx).anchor); - fprintf(fid, " at (axis cs:%s,%s) {%s};\n\n", ... - formatPgfNumber(textAnnotations(textIdx).x), ... - formatPgfNumber(textAnnotations(textIdx).y), ... - escapeTikzText(textAnnotations(textIdx).text)); -end -end - -function anchor = matlabTextAlignmentToTikzAnchor(horizontalAlignment, verticalAlignment) -horizontalAlignment = string(horizontalAlignment); -verticalAlignment = string(verticalAlignment); - -if horizontalAlignment == "left" - horizontalAnchor = "west"; -elseif horizontalAlignment == "right" - horizontalAnchor = "east"; -else - horizontalAnchor = ""; -end - -if verticalAlignment == "top" - verticalAnchor = "north"; -elseif verticalAlignment == "bottom" - verticalAnchor = "south"; -else - verticalAnchor = ""; -end - -if strlength(horizontalAnchor) > 0 && strlength(verticalAnchor) > 0 - anchor = verticalAnchor + " " + horizontalAnchor; -elseif strlength(horizontalAnchor) > 0 - anchor = horizontalAnchor; -elseif strlength(verticalAnchor) > 0 - anchor = verticalAnchor; -else - anchor = "center"; -end -end - -function textOut = escapeTikzText(textIn) -textOut = char(textIn); -% textOut = strrep(textOut, "\", "\textbackslash{}"); -textOut = strrep(textOut, "{", "\{"); -textOut = strrep(textOut, "}", "\}"); -textOut = strrep(textOut, "%", "\%"); -textOut = strrep(textOut, "&", "\&"); -textOut = strrep(textOut, "#", "\#"); -textOut = strrep(textOut, "_", "\_"); -% textOut = strrep(textOut, "$", "\$"); -end - diff --git a/projects/ECOC_2025_MPI/plots_from_database/plot_mpi_trial.m b/projects/ECOC_2025_MPI/plots_from_database/plot_mpi_trial.m index 0359b37..5c05de5 100644 --- a/projects/ECOC_2025_MPI/plots_from_database/plot_mpi_trial.m +++ b/projects/ECOC_2025_MPI/plots_from_database/plot_mpi_trial.m @@ -1,49 +1,10 @@ -% dsp_options.database_type = 'mysql'; -% dsp_options.dataBase = 'labor'; -% dsp_options.storage_path = 'Z:\2025\ECOC Silas\ecoc_2025\'; -% database = DBHandler("dataBase", [dsp_options.dataBase], "type", dsp_options.database_type); -% 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', 1000, ... -% % 'is_mpi', 1, ... -% % 'pam_level', 4, ... -% % 'wavelength', 1310, ... -% % 'precomp_amp', [], ... -% % 'signal_attenuation', [], ... -% % 'v_awg', [], ... -% % 'v_bias', [] ... -% % ); -% -% % 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 -% a = database.getTableFieldNames('Runs'); -% b = database.getTableFieldNames('Results'); -% c = database.getTableFieldNames('EqualizerParameters'); -% d = [a;b;c]; -% -% [dataTable,~] = database.queryDB(filterParams, d); -% -% selectedFields = {'Configurations.run_id' 'Runs.loop_id' 'Runs.date_of_run' 'Runs.rx_raw_path' 'Runs.bitrate' 'Runs.v_bias' 'Runs.v_awg' 'Runs.precomp_amp' 'Runs.symbolrate' 'Runs.pam_level'... -% 'Runs.db_mode' 'Runs.rop_attenuation' 'Runs.is_mpi' 'Runs.interference_attenuation' 'Runs.interference_path_length' 'Runs.signal_attenuation' ... -% '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'}; - db = DBHandler("type","mysql","dataBase",'labor'); fp = QueryFilter(); % fp.where('mpi_superview', 'loop_id','EQUALS', 209); +% fp.where('mpi_superview','run_id','GREATER_EQUAL',3153); fp.where('mpi_superview', 'symbolrate','EQUALS', 112e9); fp.where('mpi_superview', 'pam_level','EQUALS', 4); fn = [db.getTableFieldNames('mpi_superview')]; @@ -67,7 +28,7 @@ figure() tiledlayout(1, 1, 'TileSpacing', 'compact', 'Padding', 'compact'); y_here = 0; figcnt = 0; -for int_len = 1000%[0,50,300,1000] +for int_len = 1%[0,50,300,1000] figcnt = figcnt+1; % figure(int_len+1); nexttile; @@ -139,7 +100,7 @@ for int_len = 1000%[0,50,300,1000] % Modify values in 'interference_path_length' where the condition is met dataTable.interference_path_length(dataTable.interference_path_length < 101 & dataTable.interference_path_length > 1) = 50; - dataTable.interference_path_length(dataTable.interference_path_length == 1) = 0; + % dataTable.interference_path_length(dataTable.interference_path_length == 1) = 0; dataTable = dataTable(dataTable.interference_path_length == int_len, :); diff --git a/workerError.mat b/workerError.mat index e62af78533bf3e797bb0d8a2f899dd50ec585956..afabc042e105ce166ec5de58dc7dd7ce9e6a6345 100644 GIT binary patch delta 1156 zcmV-~1bh4E39t%~G#FE1bRbG~Y#=c)ATcpIGdMajFd#B8GB%M>BavVQk#uQ)PXqt} zc%1E7PjA~c6sHw8jnm9+uN%<%81xWi#Re3?usU&KEJeLKaIy`B0F9Pui;ezOq=L4m z9CzGtA0fwngnWb^d)!CZamSJpWz(!|DN_C{O9>Ftqxc?w@AvrU39JJEK0X9skv*4K zt%11Q5^{yrlZWw>7fr~ZvfJT*a-H{+^tBZIq{i*l=vzhf>9k(-5<904CU)+N{+02w z8ujJ!SFEt)|4C)G-)}0@{WZ~6WzS_+|77*OsDHEC zW#4`m)nb*t^%1Zj*+R%|!Ej_zfCtE>c!*H|97G5lAuvEg7}}IjXdVK8gI#=h5yw2~kI%Mk=xX?ks#x4@; zH3R?83VtrPHuM960;2b@4T-+(nei&oW5RUo31E1^8%(ZnU)$eP_?;+n#wy^x+V3D#m`SXW&?v!m$9De#w33$H@ObGR8en{68q` zKRafy&nAcCWASc(4A4=;MV@(4SMYFo+Em&7_?KL~>?=6-OY!o|>l@v8W@C4x4~TCB zp^FFc6v@L&O~J$Eu^G``ZoRZ~@zPUp^v;tP=FAp9n#9V%PUwv z3LhlwJD9RYl6(CuD|om(F#}S0J=^-}M7;c!fn%uP7#84vg`EYjSklURV!}FgciAp* zgbAiPc8?IDcmydj`0fDhkr!ZUIV3rMvht;`6?|NtZS@>@JKc+TTdmK|e`<<8&wrA5 z^1Lg`f1(m4K~ae_Azn<+4jq@jvE-j3&McVVKF;9dzmgYRR-ROR{y%GGo##oB{kU#% zxUBrFcpM&oU1%Ks?|ETy{U1v4{v{tx&qs^vw=OguH#H9~9*^%YG#)oC|1KWK<~7=< zu20@yT>slr@%Zw;QS5)?s^WFodd2-bAN{QOf1}{$^6dC8kL|8Xb}Ncql@FCa)ep6Q zP0~A=Gfr|BB99~Um3ChTrtDNNRDUG{uj+rapJ+h;IUtj(2Px8(_5ch!NGV?-^ zmE=w^F4Nb0Q}=|*MWKWf6rXQ3ZN6Wcc)N=I;jDhmi?`bUtn)jMzMOxg-KYNsWL{%g WzEA&Y&iHBbZPtA{FP{LYU^Vg7<5dp; delta 1083 zcmV-B1jPHW3g-!sG#FH9bs$Q0Y#<;xATc*OGBG+aF(5K9GB%M>BavVQk#uQ)1_S^A zc%1E7&2Q5%6nC@Itphf=!8p((7Z4yJ!7g;4ViSc;T>+s;!A+djEMJP9Y20??$dNx` z#~nHHXK>_C;K&g>aaPw$nylTJ_;`}#Jjd_l_de|Bx^n=4YqtQXv3`cNI!Ne};47?s zUr2gRn&3fYqs93-)|v|gc`ZYKK5fZ(HGWqSb6P7e+o_(PHwSvIi}{t~z8cTv{8iT0 zv4dWRFbGg+7()JwBtQ6G!e3Ev@cD<8e7pB6!}B#UR%QJxYoAy<674%{TkPFC(fX{> z4*>#wNR|=uR$$cYQ-CexQEX!r0v8bidk9#_hLJ-Fh2}0mULSfUvJwt|hP}vT0tBr1 zVTeqMeGjzO_DvMTk0y)=0-03L9v-4f1}~4zfRpxXf}fJ!RYk7}-=*(s()(#JhD zRsvrj0h*KgBak2G6pI|^$I|>-#(de%x)@LB$J02!CHZQG{H!E@P4MrD?;+3hEi}Nf zRiNj#qKEUXrJd(X%Zprp-D1ZhQ4shcMb;{$aEGTD*LzT)cSF(3`Hly>4r)-pk)Uk& z-S;fXNW-@qrUMCS*pU|}ox!rwVpAb$Y_?y%xNG~N3n|0UplF}oll=UxmcI|A`H-~_ z%(G^*^$a}dBH&;TfwApcS=2iOg+y;-W`(}$o5?ED6G!UUwJd{wU^j9gH%?y{RuX+} z+vqyJxl450M)zFFuKNWzriO4#0VY3L-hF-535B-&^OtZjlG_3k-!Ke4_ir!l<`Yl!Nd7u zHDY`szZ|TW@=IHP!O=cTzc6E#AvODA<*4>#;h9nJa6VNtS)RPTfc2yJgG5~yQ#MFS zub-?sGEf6D{d&53){6b|xd4Z);IPN=OAz{TJ<(S&VUxBt*ewQw^AqKp!y>v*&pfm4@cll?+|6Yvfs1rxxtX0>bc5aDZs1R zAMZ=r@3r@iHd