From 569e72a1fe50dc2c3d264140728ee3e05841d151 Mon Sep 17 00:00:00 2001 From: Silas Oettinghaus Date: Mon, 15 Dec 2025 15:04:15 +0100 Subject: [PATCH] Add new minimal example (+ a ton of other, not so important, changes) --- Classes/00_signals/Signal.m | 19 +- Classes/01_transmit/ChannelFreqResp.m | 8 + Classes/04_DSP/Equalizer/ML_MLSE.m | 4 +- Classes/DataBaseHandler/Metricstruct.m | 10 +- .../fwm_plots/automate_JLT_plots.m | 10 +- Functions/EQ_structures/dsp_runid.m | 10 +- Functions/EQ_structures/duobinary_target.m | 4 + Functions/EQ_visuals/showEQNoisePSD.m | 1 - Functions/EQ_visuals/showLevelHistogram.m | 2 + Functions/Job_Processing/preprocessSignal.m | 14 +- Functions/Theory/dispersion_10km.m | 103 ++--- Functions/beautifyBERplot.m | 13 +- Libs/wesanderson_colors/WesPalette.m | 133 ++++++ Libs/wesanderson_colors/hex2rgb.m | 20 + .../minimal_example_wespalette.m | 64 +++ Libs/wesanderson_colors/wes_palettes.m | 79 ++++ .../Auswertung_JLT/final/Copy_of_FIGURE_ROP.m | 146 ++++++ .../final/Copy_of_FIGURE_WAVELENGTH.m | 272 +++++++++++ .../Auswertung_JLT/final/FIGURE_BER_3x4.m | 132 ++++++ .../Auswertung_JLT/final/FIGURE_EYES.m | 257 +++++++++++ .../Auswertung_JLT/final/FIGURE_NGMI.m | 221 +++++++++ .../Auswertung_JLT/final/FIGURE_NGMI_v2.m | 180 ++++++++ .../Auswertung_JLT/final/FIGURE_ROP.m | 153 ++++++ .../Auswertung_JLT/final/FIGURE_Spectra.m | 182 ++++++++ .../Auswertung_JLT/final/FIGURE_WAVELENGTH.m | 124 +++++ .../final/FIGURE_WAVELENGTH_VS_BAUDRATE.m | 160 +++++++ .../final/FIGURE_introduction.m | 88 ++++ .../final/HighSpeedExperiments.xlsx | Bin 0 -> 26210 bytes .../final/analyze_measurements_gpt.m | 334 ++++++++++++++ .../final/compare_ber_best_results.m | 21 +- .../final/compare_ber_complete_results.m | 170 ------- .../Auswertung_JLT/final/example_usage.m | 92 ++++ .../final/generate_spectrum_plots.m | 15 +- .../final/plot_measurements_gpt.m | 358 +++----------- .../final/plot_measurements_gpt_old.m | 436 ++++++++++++++++++ .../Auswertung_JLT/final/plot_rates.m | 34 -- .../Auswertung_JLT/run_dsp_from_db.m | 23 +- .../a_minimal_example.m | 118 +++++ .../auswertung/only_show_precomp.m | 171 ++++--- .../bias_evaluation.m | 2 +- projects/IMDD_base_system/simulation_bwl_2.m | 80 +++- projects/ML_based_MLSE/experimental_data.m | 3 +- projects/WDM/WDM_model.m | 2 +- 43 files changed, 3594 insertions(+), 674 deletions(-) create mode 100644 Libs/wesanderson_colors/WesPalette.m create mode 100644 Libs/wesanderson_colors/hex2rgb.m create mode 100644 Libs/wesanderson_colors/minimal_example_wespalette.m create mode 100644 Libs/wesanderson_colors/wes_palettes.m create mode 100644 projects/HighSpeedExperiment_2024/Auswertung_JLT/final/Copy_of_FIGURE_ROP.m create mode 100644 projects/HighSpeedExperiment_2024/Auswertung_JLT/final/Copy_of_FIGURE_WAVELENGTH.m create mode 100644 projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_BER_3x4.m create mode 100644 projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_EYES.m create mode 100644 projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_NGMI.m create mode 100644 projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_NGMI_v2.m create mode 100644 projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_ROP.m create mode 100644 projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_Spectra.m create mode 100644 projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_WAVELENGTH.m create mode 100644 projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_WAVELENGTH_VS_BAUDRATE.m create mode 100644 projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_introduction.m create mode 100644 projects/HighSpeedExperiment_2024/Auswertung_JLT/final/HighSpeedExperiments.xlsx create mode 100644 projects/HighSpeedExperiment_2024/Auswertung_JLT/final/analyze_measurements_gpt.m delete mode 100644 projects/HighSpeedExperiment_2024/Auswertung_JLT/final/compare_ber_complete_results.m create mode 100644 projects/HighSpeedExperiment_2024/Auswertung_JLT/final/example_usage.m create mode 100644 projects/HighSpeedExperiment_2024/Auswertung_JLT/final/plot_measurements_gpt_old.m delete mode 100644 projects/HighSpeedExperiment_2024/Auswertung_JLT/final/plot_rates.m create mode 100644 projects/HighSpeedExperiment_2024/a_minimal_example.m diff --git a/Classes/00_signals/Signal.m b/Classes/00_signals/Signal.m index 7eaa1c0..a21e71c 100644 --- a/Classes/00_signals/Signal.m +++ b/Classes/00_signals/Signal.m @@ -347,8 +347,10 @@ classdef Signal options.fignum = 2025 options.displayname = ""; options.color = []; + options.linestyle = '-'; options.normalizeToNyquist = 0; options.addDCoffset = 0; + options.normalizeToDC = 0; options.normalizeTo0dB = 0; options.max_num_lines = []; % Leave empty or omit to disable line rotation options.fft_length = []; @@ -361,6 +363,8 @@ classdef Signal options.fft_length = 2^(nextpow2(length(obj.signal))-9); end + + if options.normalizeToNyquist == 0 [p_lin,f_Hz] = pwelch(obj.signal, hanning(options.fft_length), ... options.fft_length/2, options.fft_length, ... @@ -374,6 +378,8 @@ classdef Signal % We'll keep f_rad for the x-axis in that mode. end + % p_lin = movmean(p_lin,4); + if options.normalizeTo0dB p_lin = p_lin ./ max(p_lin); p_dbm = 10*log10(p_lin); % normalized to 0 dB @@ -418,11 +424,18 @@ classdef Signal p_dbm = p_dbm+options.addDCoffset; + if options.normalizeToDC + [~,min_idx]=min(abs(f_GHz)); + pow_at_dc = p_dbm(min_idx); + p_dbm = p_dbm-pow_at_dc; + end + % p_dbm = movmean(p_dbm,10); + for s = 1:min(size(p_dbm)) if isempty(options.color) plot(x_vec, p_dbm(:,s), 'DisplayName', options.displayname, 'LineWidth', 1); else - plot(x_vec, p_dbm(:,s), 'DisplayName', options.displayname, 'LineWidth', 1, 'Color', options.color); + plot(x_vec, p_dbm(:,s), 'DisplayName', options.displayname, 'LineWidth', 1, 'Color', options.color,'LineStyle',options.linestyle); end end @@ -968,8 +981,8 @@ classdef Signal maxA = max(sig(100:end-100))*1.3; minA = min(sig(100:end-100))*1.3; - % maxA = 0.0025; - % minA = 0; + maxA = 0.12; + minA = -0.08; difference= maxA-minA; diff --git a/Classes/01_transmit/ChannelFreqResp.m b/Classes/01_transmit/ChannelFreqResp.m index cfffe17..e6c8a2a 100644 --- a/Classes/01_transmit/ChannelFreqResp.m +++ b/Classes/01_transmit/ChannelFreqResp.m @@ -139,6 +139,8 @@ classdef ChannelFreqResp < handle fnew = linspace(0,fstarget/2,length(Target)/2+1); fnew = fnew(2:end-1); + + % Old frequency axis (should be much coarser) idx_old = find((obj.faxis > 0) .* (obj.faxis < fstarget/2)); %positions of all Frequencies smaller than fs/2 int_fold = obj.faxis(idx_old); %old frequencies from 0 to fs/2 @@ -149,6 +151,10 @@ classdef ChannelFreqResp < handle % interpolate the frequency response that had a coarse frequency resolution (e.g. 256 bins) to the current frequency resolution (e.g. 21843 bins) iH = interp1(int_fold, real(H_inv(idx_old)) ,fnew, 'linear') + 1i*interp1(int_fold, imag(H_inv(idx_old)) ,fnew, 'linear'); + if 0 + figure(7);hold on;plot(fnew,20*log10(abs(iH))) + end + % set all NaN values to the fist/ last non-NaN value nH = find(~isnan(iH),1,'first'); iH(1:nH)=iH(nH); @@ -171,6 +177,8 @@ classdef ChannelFreqResp < handle % five frequencies -> should be the vaue at f=0=DC component? iH = iH./mean(abs(iH)); %why 1:5?? + dc = 20*log10(abs(mean(abs(iH(1:5))))); + % set maximum amplification % set als values higher than hmax to hmax and keep the % phase information by multiplication with respective diff --git a/Classes/04_DSP/Equalizer/ML_MLSE.m b/Classes/04_DSP/Equalizer/ML_MLSE.m index 239c2d8..3f584c3 100644 --- a/Classes/04_DSP/Equalizer/ML_MLSE.m +++ b/Classes/04_DSP/Equalizer/ML_MLSE.m @@ -164,8 +164,8 @@ classdef ML_MLSE < handle % EQUALIZE % ============================================================== function [y,y_ref] = equalize(obj,x,d,mu,epochs,N,training) - debug = 1; - showPlots = 1; + debug = 0; + showPlots = 0; y = zeros(N,1); nSymbols = ceil(N/obj.sps); diff --git a/Classes/DataBaseHandler/Metricstruct.m b/Classes/DataBaseHandler/Metricstruct.m index f95311c..ef00675 100644 --- a/Classes/DataBaseHandler/Metricstruct.m +++ b/Classes/DataBaseHandler/Metricstruct.m @@ -71,16 +71,22 @@ classdef Metricstruct end end - function print(obj) + function print(obj,options) % Print method to display key metrics in a formatted way + arguments + obj + options.description = ''; + end + % Define the width for formatting nameWidth = 15; % Width for parameter names valueWidth = 12; % Width for values % Print header + fprintf('\n%s\n', repmat('=', 1, nameWidth + valueWidth)); - fprintf(' Results \n'); + fprintf([char(options.description),' Results \n']); fprintf('%s\n', repmat('=', 1, nameWidth + valueWidth)); % Function to format numbers with appropriate precision diff --git a/Classes/Warehouse_class/functions/phase_predist_plots/fwm_plots/automate_JLT_plots.m b/Classes/Warehouse_class/functions/phase_predist_plots/fwm_plots/automate_JLT_plots.m index 801c0e8..c29a009 100644 --- a/Classes/Warehouse_class/functions/phase_predist_plots/fwm_plots/automate_JLT_plots.m +++ b/Classes/Warehouse_class/functions/phase_predist_plots/fwm_plots/automate_JLT_plots.m @@ -21,7 +21,7 @@ height = 200; plotJob.Position = [100 100 width 100+height]; cols = cbrewer2("paired",12); plotJob.color = cols(1,:); -plotJob.l = 2; +plotJob.l = 10; plotJob.ch = 16; plotJob.d = 0; plotJob.sgm = 0; @@ -30,7 +30,7 @@ plotJob.p_in = 3; plotJob.gamma = 0.0023; plotJob.pmd = 0.1; plotJob.channelspacing = 400e9; -plotJob.randzdw = 0; +plotJob.randzdw = 1; plotJob.plot_ber_curve = 0; @@ -52,7 +52,7 @@ plotJob.yAxisLabel = 'BER'; % createbercurves(wh,plotJob) - P = [3,6]; + P = [3]; for i = 1:2 plotJob.p_in = P(i); createviolinplots(wh,plotJob); @@ -234,8 +234,8 @@ Title = ["Co Pol.","Link Segmentation","Paired Pol. Interl.","Alternating Pol. I D = [0,3,0,0]; Sgm = [0,1,0,0]; -colidx = [3]; -Len = [10]; +colidx = [4]; +Len = plotJob.l; fig = findall(groot, 'Type', 'figure', 'Name', plotJob.figName); if isvalid(fig) diff --git a/Functions/EQ_structures/dsp_runid.m b/Functions/EQ_structures/dsp_runid.m index 210728a..4d207bd 100644 --- a/Functions/EQ_structures/dsp_runid.m +++ b/Functions/EQ_structures/dsp_runid.m @@ -95,11 +95,11 @@ try adaption= 1; use_dd_mode = 1; - use_ffe = 1; - use_dfe = 1; - use_vnle_mlse = 1; - use_dbtgt = 1; - use_dbenc = 1; + use_ffe = 0; + use_dfe = 0; + use_vnle_mlse = 0; + use_dbtgt = 0; + use_dbenc = 0; use_ml_mlse = 1; addProcessingResultToDatabase = 0; diff --git a/Functions/EQ_structures/duobinary_target.m b/Functions/EQ_structures/duobinary_target.m index 3a1389f..36150dd 100644 --- a/Functions/EQ_structures/duobinary_target.m +++ b/Functions/EQ_structures/duobinary_target.m @@ -130,6 +130,10 @@ db_results.config.equalizer_structure = int32(equalizer_structure.vnle_db_mlse); db_results.config.comment = 'function: Duobinary tgt. (VNLE -> MLSE)'; if options.showAnalysis + + eq_signal.eye(eq_signal.fs,M,"fignum",249); + + eq_noise = eq_noise - mean(eq_noise.signal); rx_signal.spectrum("normalizeTo0dB",1,"fignum",250,"displayname","Rx Spectrum"); diff --git a/Functions/EQ_visuals/showEQNoisePSD.m b/Functions/EQ_visuals/showEQNoisePSD.m index 8eeed21..ed7b440 100644 --- a/Functions/EQ_visuals/showEQNoisePSD.m +++ b/Functions/EQ_visuals/showEQNoisePSD.m @@ -22,7 +22,6 @@ end % Ensure the figure is ready before calling spectrum eq_noise.spectrum("displayname", options.displayname, "fignum", fig.Number, "normalizeTo0dB", 1,"color",options.color); - title('EEN') if ~isnan(options.postfilter_taps) % Hold on to the figure for further plotting diff --git a/Functions/EQ_visuals/showLevelHistogram.m b/Functions/EQ_visuals/showLevelHistogram.m index ef88791..e6e7156 100644 --- a/Functions/EQ_visuals/showLevelHistogram.m +++ b/Functions/EQ_visuals/showLevelHistogram.m @@ -52,6 +52,8 @@ end legend grid on + % view([90 -90]); + end diff --git a/Functions/Job_Processing/preprocessSignal.m b/Functions/Job_Processing/preprocessSignal.m index ed40a6c..6932697 100644 --- a/Functions/Job_Processing/preprocessSignal.m +++ b/Functions/Job_Processing/preprocessSignal.m @@ -16,13 +16,17 @@ Scpe_sig = Scpe_sig.resample("fs_out", 2*fsym); [Scpe_sig, ~] = Scpe_sig.tsynch("reference", Symbols, "fs_ref", fsym, "debug_plots", 0); % Apply Gaussian filter -if 1 -Scpe_sig = Filter('filtdegree', 8, "f_cutoff", Symbols.fs.*0.52, ... - "fs", Scpe_sig.fs, "filterType", filtertypes.gaussian, ... - "active", true).process(Scpe_sig); +if 1 + Scpe_sig = Filter('filtdegree', 8, "f_cutoff", Symbols.fs.*0.52, ... + "fs", Scpe_sig.fs, "filterType", filtertypes.gaussian, ... + "active", true).process(Scpe_sig); +else + Scpe_sig = Filter('filtdegree', 4, "f_cutoff", Symbols.fs.*0.6, ... + "fs", Scpe_sig.fs, "filterType", filtertypes.gaussian, ... + "active", true).process(Scpe_sig); end -% Remove DC offset +%Remove DC offset Scpe_sig = Scpe_sig - mean(Scpe_sig.signal); end \ No newline at end of file diff --git a/Functions/Theory/dispersion_10km.m b/Functions/Theory/dispersion_10km.m index 87a17a8..83fcf29 100644 --- a/Functions/Theory/dispersion_10km.m +++ b/Functions/Theory/dispersion_10km.m @@ -2,11 +2,11 @@ % IM/DD Fading Notch – λ_null vs. Bandwidth (Fixed 10 km) % ============================================================ - +clear; clc; %% Fiber and dispersion parameters -lambda0 = 1315e-9; % Zero-dispersion wavelength [m] -S0 = 0.08; % Dispersion slope at ZDW [ps/(nm²·km)] +lambda0 = 1310e-9; % Zero-dispersion wavelength [m] +S0 = 0.09; % Dispersion slope at ZDW [ps/(nm²·km)] L = 10e3; % Fiber length [m] c = physconst('lightspeed'); @@ -17,74 +17,73 @@ f_GHz = f_targets / 1e9; %% Compute wavelength λ_null for each target f_null [lambda_vec, Dacc_vec] = lambda_for_first_null_full(f_targets, L, lambda0, S0); lambda_nm = lambda_vec * 1e9; % Convert to nm +Dacc = Dacc_vec; % [ps/nm] %% ------------------------------------------------------------ % Plot λ_null vs. f_null for 10 km fiber % ------------------------------------------------------------ -% figure('Color','w'); -% plot(lambda_nm,f_GHz, 'LineWidth', 2); -% grid on; box on; - cols = cbrewer2('Paired',10); -figure('Color','w');hold on +figure('Color','w'); hold on; -plot(lambda_nm, f_GHz, 'LineWidth',2,'DisplayName',sprintf('%d km',L),'Color',cols(2,:)); +hLine = plot(lambda_nm, f_GHz, ... + 'LineWidth', 2, ... + 'DisplayName', sprintf('L = %.1f km', L/1000), ... + 'Color', cols(2,:)); -yticks([56,75,90,112]) - -f_GHz = [56,75,90,112] * 1e9; -[lambda_vec, Dacc_vec] = lambda_for_first_null_full(f_GHz, L, lambda0, S0); -lambda_nm = lambda_vec * 1e9; % Convert to nm - -xticks(round(lambda_nm)) - -xlabel('$\Delta \lambda$ from ZDW [nm]'); -ylabel('$F_{null}$ [GHz]'); +xlabel('Wavelength λ [nm]'); +ylabel('First fading notch f_{null} [GHz]'); +title('IM/DD Fading Notch Position vs. Wavelength'); grid on; box on; -lim=(lambda0.*1e9)-[8,40]; + +lim = (lambda0.*1e9) - [8, 40]; xlim([lim(2) lim(1)]); -% ylim([40,130]) +yticks([56,75,90,112]); + +%% ------------------------------------------------------------ +% Custom DataTip Template +% ------------------------------------------------------------ +% Add accumulated dispersion value to the DataTip +hLine.DataTipTemplate.DataTipRows(1).Label = 'λ [nm]'; +hLine.DataTipTemplate.DataTipRows(2).Label = 'f_{null} [GHz]'; + +% Create a new row for Dacc +dRow = dataTipTextRow('D_{acc} [ps/nm]', Dacc); +hLine.DataTipTemplate.DataTipRows(end+1) = dRow; %% ------------------------------------------------------------ % Helper function: lambda_for_first_null_full -% Stable, single-branch, clamped to O-band % ------------------------------------------------------------ function [lambda_vec, Dacc_vec] = lambda_for_first_null_full(f_target, L, lambda0, S0) -c = physconst('lightspeed'); -S0_si = S0 * 1e3; % ps/(nm²·km) -> s/(m³) + c = physconst('lightspeed'); + S0_si = S0 * 1e3; % ps/(nm²·km) -> s/(m³) -% Define O-band boundaries [m] -lambda_min = 1260e-9; -lambda_max = 1360e-9; + lambda_min = 1260e-9; + lambda_max = 1360e-9; -f_target = f_target(:); -N = numel(f_target); + f_target = f_target(:); + N = numel(f_target); -lambda_vec = zeros(N,1); -Dacc_vec = zeros(N,1); + lambda_vec = zeros(N,1); + Dacc_vec = zeros(N,1); -for k = 1:N - RHS = c * 0.5 / (f_target(k)^2 * L); + for k = 1:N + RHS = c * 0.5 / (f_target(k)^2 * L); - % Normal-dispersion branch (λ < λ0) - fun = @(lambda) -(S0_si/4).*(lambda - (lambda0^4)./(lambda.^3)).*lambda.^2 - RHS; + fun = @(lambda) -(S0_si/4).*(lambda - (lambda0^4)./(lambda.^3)).*lambda.^2 - RHS; - % Solve within normal-dispersion range - try - lambda_sol = fzero(fun, [lambda_min, lambda0 * 0.999]); - catch - lambda_sol = lambda_min; + try + lambda_sol = fzero(fun, [lambda_min, lambda0 * 0.999]); + catch + lambda_sol = lambda_min; + end + + lambda_sol = min(max(lambda_sol, lambda_min), lambda_max); + lambda_vec(k) = lambda_sol; + + D_lambda = (S0_si/4) * (lambda_sol - (lambda0^4)/(lambda_sol^3)) / 1e-6; % ps/(nm·km) + Dacc_val = D_lambda * (L/1000); % ps/nm + Dacc_val = min(max(Dacc_val, -100), 100); + + Dacc_vec(k) = Dacc_val; end - - % Clamp to O-band - lambda_sol = min(max(lambda_sol, lambda_min), lambda_max); - lambda_vec(k) = lambda_sol; - - % Compute D(lambda) and accumulated dispersion - D_lambda = (S0_si/4) * (lambda_sol - (lambda0^4)/(lambda_sol^3)) / 1e-6; % ps/(nm·km) - Dacc_val = D_lambda * (L/1000); % ps/nm - Dacc_val = min(max(Dacc_val, -100), 100); - - Dacc_vec(k) = Dacc_val; -end end diff --git a/Functions/beautifyBERplot.m b/Functions/beautifyBERplot.m index 0697abc..9bc5d0a 100644 --- a/Functions/beautifyBERplot.m +++ b/Functions/beautifyBERplot.m @@ -11,6 +11,7 @@ function beautifyBERplot(options) arguments options.logscale (1,1) logical = 1 + options.setmarkers (1,1) logical = 1; options.polyfit (1,1) logical = 0 options.polyorder (1,1) double = 2 options.fitmethod (1,1) string = "polyfit" % choose fit type @@ -23,13 +24,15 @@ num_markers = length(markers); % --- style all lines consistently for i = 1:length(lines) - lines(i).LineWidth = 1; + lines(i).LineWidth = 1.2; % lines(i).LineStyle = '-'; - if string(lines(i).Marker) == "none" - lines(i).Marker = markers{mod(i-1, num_markers) + 1}; + if options.setmarkers == 1 + if string(lines(i).Marker) == "none" + lines(i).Marker = markers{mod(i-1, num_markers) + 1}; + end + lines(i).MarkerSize = 4; + lines(i).MarkerFaceColor = lines(i).Color; end - lines(i).MarkerSize = 4; - lines(i).MarkerFaceColor = lines(i).Color; end % --- optional smoothing/fitting overlay diff --git a/Libs/wesanderson_colors/WesPalette.m b/Libs/wesanderson_colors/WesPalette.m new file mode 100644 index 0000000..7cd1dcb --- /dev/null +++ b/Libs/wesanderson_colors/WesPalette.m @@ -0,0 +1,133 @@ +classdef WesPalette + % WESPALETTE Wes Anderson color palettes with auto-completion + % Usage: + % cmap = WesPalette.Zissou1.rgb() + % cmap = WesPalette.Zissou1.rgb(3) + + % https://github.com/karthik/wesanderson?tab=readme-ov-file + + enumeration + BottleRocket1 + BottleRocket2 + Rushmore1 + Rushmore + Royal1 + Royal2 + Zissou1 + Zissou1Continuous + Darjeeling1 + Darjeeling2 + Chevalier1 + FantasticFox1 + Moonrise1 + Moonrise2 + Moonrise3 + Cavalcanti1 + GrandBudapest1 + GrandBudapest2 + IsleofDogs1 + IsleofDogs2 + FrenchDispatch + AsteroidCity1 + AsteroidCity2 + AsteroidCity3 + end + + methods + function cmap = rgb(obj, n) + % Return palette as Nx3 RGB colormap [0–1] + + hex = obj.hex(); + + rgb = hex2rgb(hex); + + if nargin == 2 + if n > size(rgb,1) + error('Requested %d colors, but only %d available.', ... + n, size(rgb,1)) + end + cmap = rgb(1:n,:); + else + cmap = rgb; + end + end + end + + methods (Access = private) + function hex = hex(obj) + % Internal HEX storage + + switch obj + case WesPalette.BottleRocket1 + hex = {'#A42820','#5F5647','#9B110E','#3F5151','#4E2A1E','#550307','#0C1707'}; + + case WesPalette.BottleRocket2 + hex = {'#FAD510','#CB2314','#273046','#354823','#1E1E1E'}; + + case {WesPalette.Rushmore1, WesPalette.Rushmore} + hex = {'#E1BD6D','#EABE94','#0B775E','#35274A','#F2300F'}; + + case WesPalette.Royal1 + hex = {'#899DA4','#C93312','#FAEFD1','#DC863B'}; + + case WesPalette.Royal2 + hex = {'#9A8822','#F5CDB4','#F8AFA8','#FDDDA0','#74A089'}; + + case WesPalette.Zissou1 + hex = {'#3B9AB2','#78B7C5','#EBCC2A','#E1AF00','#F21A00'}; + + case WesPalette.Zissou1Continuous + hex = {'#3A9AB2','#6FB2C1','#91BAB6','#A5C2A3','#BDC881', ... + '#DCCB4E','#E3B710','#E79805','#EC7A05','#EF5703','#F11B00'}; + + case WesPalette.Darjeeling1 + hex = {'#FF0000','#00A08A','#F2AD00','#F98400','#5BBCD6'}; + + case WesPalette.Darjeeling2 + hex = {'#ECCBAE','#046C9A','#D69C4E','#ABDDDE','#000000'}; + + case WesPalette.Chevalier1 + hex = {'#446455','#FDD262','#D3DDDC','#C7B19C'}; + + case WesPalette.FantasticFox1 + hex = {'#DD8D29','#E2D200','#46ACC8','#E58601','#B40F20'}; + + case WesPalette.Moonrise1 + hex = {'#F3DF6C','#CEAB07','#D5D5D3','#24281A'}; + + case WesPalette.Moonrise2 + hex = {'#798E87','#C27D38','#CCC591','#29211F'}; + + case WesPalette.Moonrise3 + hex = {'#85D4E3','#F4B5BD','#9C964A','#CDC08C','#FAD77B'}; + + case WesPalette.Cavalcanti1 + hex = {'#D8B70A','#02401B','#A2A475','#81A88D','#972D15'}; + + case WesPalette.GrandBudapest1 + hex = {'#F1BB7B','#FD6467','#5B1A18','#D67236'}; + + case WesPalette.GrandBudapest2 + hex = {'#E6A0C4','#C6CDF7','#D8A499','#7294D4'}; + + case WesPalette.IsleofDogs1 + hex = {'#9986A5','#79402E','#CCBA72','#0F0D0E','#D9D0D3','#8D8680'}; + + case WesPalette.IsleofDogs2 + hex = {'#EAD3BF','#AA9486','#B6854D','#39312F','#1C1718'}; + + case WesPalette.FrenchDispatch + hex = {'#90D4CC','#BD3027','#B0AFA2','#7FC0C6','#9D9C85'}; + + case WesPalette.AsteroidCity1 + hex = {'#0A9F9D','#CEB175','#E54E21','#6C8645','#C18748'}; + + case WesPalette.AsteroidCity2 + hex = {'#C52E19','#AC9765','#54D8B1','#B67C3B','#175149','#AF4E24'}; + + case WesPalette.AsteroidCity3 + hex = {'#FBA72A','#D3D4D8','#CB7A5C','#5785C1'}; + end + end + end +end diff --git a/Libs/wesanderson_colors/hex2rgb.m b/Libs/wesanderson_colors/hex2rgb.m new file mode 100644 index 0000000..b193e8d --- /dev/null +++ b/Libs/wesanderson_colors/hex2rgb.m @@ -0,0 +1,20 @@ +function rgb = hex2rgb(hex) +% HEX2RGB Convert HEX color codes to RGB [0–1] + +if ischar(hex) + hex = {hex}; +end + +n = numel(hex); +rgb = zeros(n,3); + +for k = 1:n + h = hex{k}; + h = strrep(h,'#',''); + rgb(k,1) = hex2dec(h(1:2)); + rgb(k,2) = hex2dec(h(3:4)); + rgb(k,3) = hex2dec(h(5:6)); +end + +rgb = rgb / 255; +end diff --git a/Libs/wesanderson_colors/minimal_example_wespalette.m b/Libs/wesanderson_colors/minimal_example_wespalette.m new file mode 100644 index 0000000..f55d2ad --- /dev/null +++ b/Libs/wesanderson_colors/minimal_example_wespalette.m @@ -0,0 +1,64 @@ +x = -10:2:25; % Input power [dBm] + +y1 = 1e-5 * 10.^(0.12*x); % Dispersion-only +y2 = 1e0 ./ (1 + exp(-0.4*(x-12))); % NLPN +y3 = 1e-6 * 10.^(0.45*x); % RP on gamma +y4 = 1e-2 * 10.^(0.18*(x-8)); % RP on beta2 + +cmap = WesPalette.AsteroidCity1.rgb(4); +cmap = linspecer(4); +figure1=figure(202998);clf;hold on +lw = 0.8; ms = 4; +plot(x,y1,'LineWidth',lw,'Color',cmap(1,:),'Marker','o','MarkerEdgeColor',cmap(1,:),'MarkerFaceColor',[1,1,1],'MarkerSize',ms); +plot(x,y2,'LineWidth',lw,'Color',cmap(2,:),'Marker','square','MarkerEdgeColor',cmap(2,:),'MarkerFaceColor',[1,1,1],'MarkerSize',ms); +plot(x,y3,'LineWidth',lw,'Color',cmap(3,:),'Marker','o','MarkerEdgeColor',cmap(3,:),'MarkerFaceColor',[1,1,1],'MarkerSize',ms); +plot(x,y4,'LineWidth',lw,'Color',cmap(4,:),'Marker','o','MarkerEdgeColor',cmap(4,:),'MarkerFaceColor',[1,1,1],'MarkerSize',ms); +yline(3.8e-3) + +grid on +xlabel('Input power [dBm]') +ylabel('NSD ($\%$)') +legend({'Dispersion','NLPN','RP','RP on $\beta_2$'}, ... + 'Location','best') + +grid off +set(gca,'MinorGridLineWidth',0.5); +set(gca,'GridLineWidth',0.5,'GridLineStyle','--','GridColor',[0.9,0.9,0.9]); + +set(gca,'FontSize',12,'YScale','log'); +ylim([1e-6 1e3]) +xlim([-10 23]) + +% % Create textarrow +% annotation(figure1,'textarrow',[0.564444444444444 0.548148148148148],... +% [0.768523809523809 0.63047619047619],'String',{'(A)'}); +% +% % Create doublearrow +% annotation(figure1,'doublearrow',[0.724444444444444 0.699259259259259],... +% [0.854238095238095 0.723809523809524]); +% +% % Create line +% annotation(figure1,'line',[0.700740740740741 0.699259259259259],... +% [0.554285714285714 0.405714285714286]); +% +% % Create textbox +% annotation(figure1,'textbox',... +% [0.578777777777778 0.194285714285714 0.104185185185185 0.0685714285714286],... +% 'String',{'BOX'},... +% 'FitBoxToText','off'); + +% +fig_path = 'C:\Users\Silas\Documents\Dissertation\00_Examples\tikz\textfig.tikz'; +matlab2tikz(fig_path, ... + 'width','\fwidth', ... + 'height','\fheight', ... + 'showInfo',false, ... + 'extraAxisOptions',{ ... + 'legend style={font=\footnotesize}', ... + 'xlabel style={font=\color{white!15!black},font=\small},',... + 'ylabel style={font=\color{white!15!black},font=\small},',... + 'legend columns=1', ... + 'every axis/.append style={font=\scriptsize}',... + 'legend columns=2',... + 'legend style={at={(0.02,0.98)},font=\footnotesize,draw=black!60,rounded corners=2pt,inner sep=1pt,fill=white,column sep=6pt,anchor= north west}',... + }); \ No newline at end of file diff --git a/Libs/wesanderson_colors/wes_palettes.m b/Libs/wesanderson_colors/wes_palettes.m new file mode 100644 index 0000000..df744b5 --- /dev/null +++ b/Libs/wesanderson_colors/wes_palettes.m @@ -0,0 +1,79 @@ +function palettes = wes_palettes() +% WES_PALETTES Full Wes Anderson color palette collection for MATLAB +% Colors are stored as HEX and converted to RGB on demand. + +palettes = struct(); + +palettes.BottleRocket1 = { ... + '#A42820', '#5F5647', '#9B110E', '#3F5151', '#4E2A1E', '#550307', '#0C1707'}; + +palettes.BottleRocket2 = { ... + '#FAD510', '#CB2314', '#273046', '#354823', '#1E1E1E'}; + +palettes.Rushmore1 = { ... + '#E1BD6D', '#EABE94', '#0B775E', '#35274A', '#F2300F'}; + +palettes.Rushmore = palettes.Rushmore1; + +palettes.Royal1 = { ... + '#899DA4', '#C93312', '#FAEFD1', '#DC863B'}; + +palettes.Royal2 = { ... + '#9A8822', '#F5CDB4', '#F8AFA8', '#FDDDA0', '#74A089'}; + +palettes.Zissou1 = { ... + '#3B9AB2', '#78B7C5', '#EBCC2A', '#E1AF00', '#F21A00'}; + +palettes.Zissou1Continuous = { ... + '#3A9AB2', '#6FB2C1', '#91BAB6', '#A5C2A3', '#BDC881', ... + '#DCCB4E', '#E3B710', '#E79805', '#EC7A05', '#EF5703', '#F11B00'}; + +palettes.Darjeeling1 = { ... + '#FF0000', '#00A08A', '#F2AD00', '#F98400', '#5BBCD6'}; + +palettes.Darjeeling2 = { ... + '#ECCBAE', '#046C9A', '#D69C4E', '#ABDDDE', '#000000'}; + +palettes.Chevalier1 = { ... + '#446455', '#FDD262', '#D3DDDC', '#C7B19C'}; + +palettes.FantasticFox1 = { ... + '#DD8D29', '#E2D200', '#46ACC8', '#E58601', '#B40F20'}; + +palettes.Moonrise1 = { ... + '#F3DF6C', '#CEAB07', '#D5D5D3', '#24281A'}; + +palettes.Moonrise2 = { ... + '#798E87', '#C27D38', '#CCC591', '#29211F'}; + +palettes.Moonrise3 = { ... + '#85D4E3', '#F4B5BD', '#9C964A', '#CDC08C', '#FAD77B'}; + +palettes.Cavalcanti1 = { ... + '#D8B70A', '#02401B', '#A2A475', '#81A88D', '#972D15'}; + +palettes.GrandBudapest1 = { ... + '#F1BB7B', '#FD6467', '#5B1A18', '#D67236'}; + +palettes.GrandBudapest2 = { ... + '#E6A0C4', '#C6CDF7', '#D8A499', '#7294D4'}; + +palettes.IsleofDogs1 = { ... + '#9986A5', '#79402E', '#CCBA72', '#0F0D0E', '#D9D0D3', '#8D8680'}; + +palettes.IsleofDogs2 = { ... + '#EAD3BF', '#AA9486', '#B6854D', '#39312F', '#1C1718'}; + +palettes.FrenchDispatch = { ... + '#90D4CC', '#BD3027', '#B0AFA2', '#7FC0C6', '#9D9C85'}; + +palettes.AsteroidCity1 = { ... + '#0A9F9D', '#CEB175', '#E54E21', '#6C8645', '#C18748'}; + +palettes.AsteroidCity2 = { ... + '#C52E19', '#AC9765', '#54D8B1', '#B67C3B', '#175149', '#AF4E24'}; + +palettes.AsteroidCity3 = { ... + '#FBA72A', '#D3D4D8', '#CB7A5C', '#5785C1'}; + +end diff --git a/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/Copy_of_FIGURE_ROP.m b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/Copy_of_FIGURE_ROP.m new file mode 100644 index 0000000..d42b76d --- /dev/null +++ b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/Copy_of_FIGURE_ROP.m @@ -0,0 +1,146 @@ +%% ============================================================ +% SETTINGS +% ============================================================ +database_type = 'mysql'; +db = DBHandler("dataBase", "labor_highspeed", "type", database_type); + +fiberL = 1; % km +wlen = 1310; % nm +bit = 300e9; % example (adjust if needed) +max_pd = 7; % ROP limit (same as before) + +PAM_list = [4 6 8]; % formats to compare + +% Colors for PAM formats +colors = {clr.Paired.red, clr.Paired.green, clr.Paired.blue}; + +% Best DSP selection: +bestDSP = struct; +bestDSP = struct; +bestDSP.P4 = equalizer_structure.vnle_db_mlse; % PAM-4 +bestDSP.P6 = equalizer_structure.vnle; % PAM-6 +bestDSP.P8 = equalizer_structure.vnle; % PAM-8 + + + +%% ============================================================ +% LOOP over PAM formats — extract data +% ============================================================ +results = struct; + +for pi = 1:numel(PAM_list) + M = PAM_list(pi); + eq = bestDSP.(sprintf('P%d', M)); + + % ---- DB FILTER ---- + fp = QueryFilter(); + fp.where('Runs','pam_level','EQUALS',M); + fp.where('Runs','fiber_length','EQUALS',fiberL); + fp.where('Runs','wavelength','EQUALS',wlen); + fp.where('Runs','bitrate','EQUALS',bit); + fp.where('Runs','power_pd_in','LESS_THAN',max_pd); + + fields = [ + db.getTableFieldNames('power_state_info'); + db.getTableFieldNames('dashboard_ungrouped_alltime') + ]; + [T,~] = db.queryDB(fp, fields); + + % ---- DSP OPTIONS ---- + pre_emph = decide_preemph(M, eq); + precoded = decide_precoded(M, eq); + + cfg = struct; + cfg.x_axis = 'power_mzm'; + cfg.y_axis = 'BER'; + cfg.agg = 'min'; + cfg.outlier = 'none'; + cfg.show_raw = false; + + cfg.filters = struct( ... + 'pam_level', M, ... + 'fiber_length', fiberL, ... + 'wavelength', wlen, ... + 'bitrate', bit, ... + 'is_mpi', 0, ... + 'equalizer_structure', eq, ... + 'pre_emph', pre_emph); + + A = analyze_measurements_gpt(T, cfg); + + results(pi).M = M; + results(pi).x = A.group{1}.x; + results(pi).color = colors{pi}; + + if precoded + results(pi).ber = A.group{1}.y_precoded; + else + results(pi).ber = A.group{1}.y; + end +end + + +%% ============================================================ +% PLOT — all PAM formats in one ROP plot +% ============================================================ +fig = figure(91); hold on; + +lw = 2.2; ms = 7; + +for pi = 1:numel(results) + plot(results(pi).x, results(pi).ber, ... + '-o', ... + 'LineWidth', lw, ... + 'MarkerSize', ms, ... + 'MarkerFaceColor', results(pi).color, ... + 'Color', results(pi).color, ... + 'DisplayName', sprintf('PAM-%d', results(pi).M)); +end + +set(gca,'YScale','log'); +grid minor; + +xlabel('ROP / Power (MZM) [dBm]'); +ylabel('BER'); + +ylim([1e-4 2e-1]); + +legend('Location','best'); +title(sprintf('BER vs ROP — Best DSP (4,6,8) at %.0f GBd, λ=%d nm, %.0f km', ... + bit*1e-9, wlen, fiberL)); + +beautifyBERplot(); + +set(fig,'Position',1e3*[0.35 0.45 1.0 0.45]); + +%% ============================================================ +% DECISION LOGIC (INLINE FUNCTIONS) +% ============================================================ + +function pe = decide_preemph(M, eq) + % PRE-EMPH RULES: + switch M + case 4 + if eq == equalizer_structure.vnle + pe = 1; % PAM4: VNLE → pre-emph on + else + pe = 0; % PAM4: all others → off + end + case {6,8} + pe = 1; % PAM6/8: all → pre-emph on + otherwise + pe = 0; + end +end + + +function flag = decide_precoded(M, eq) + % PRE-CODE RULES: + if eq == equalizer_structure.vnle_db_mlse + flag = 1; % Always for DB-target + elseif eq == equalizer_structure.ml_mlse && M == 4 + flag = 1; % PAM4: ML-based → precoded + else + flag = 0; + end +end \ No newline at end of file diff --git a/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/Copy_of_FIGURE_WAVELENGTH.m b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/Copy_of_FIGURE_WAVELENGTH.m new file mode 100644 index 0000000..21f881f --- /dev/null +++ b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/Copy_of_FIGURE_WAVELENGTH.m @@ -0,0 +1,272 @@ +%% ============================================================ +% LOAD DATA FOR PAM = 4,6,8 +% ============================================================ +database_type = 'mysql'; +db = DBHandler("dataBase", "labor_highspeed", "type", database_type); + +pam_levels = [4, 6, 8]; % three tiles +bitrate_set = 360e9; +fiberL = 10; + +fields = [ + db.getTableFieldNames('power_state_info'); + db.getTableFieldNames('dashboard_ungrouped_alltime') +]; + +%% ============================================================ +% DEFINE DSP SCHEMES +% ============================================================ +curves = struct; + +curves(1).name = 'VNLE'; +curves(1).eq = equalizer_structure.vnle; +curves(1).color = clr.Paired.red; + +curves(2).name = 'PF + MLSE'; +curves(2).eq = equalizer_structure.vnle_pf_mlse; +curves(2).color = clr.Paired.green; + +curves(3).name = 'DB-target + MLSE'; +curves(3).eq = equalizer_structure.vnle_db_mlse; +curves(3).color = clr.Paired.blue; + +curves(4).name = 'ML-based MLSE'; +curves(4).eq = equalizer_structure.ml_mlse; +curves(4).color = clr.Paired.purple; + +%% ============================================================ +% ANALYSIS — NO PLOTTING +% results(p, k) → p: PAM index, k: DSP index +% ============================================================ +results = struct; + +for p = 1:length(pam_levels) + M = pam_levels(p); + + % --- Load DB rows for this PAM --- + fp = QueryFilter(); + fp.where('Runs','pam_level','EQUALS', M); + fp.where('Runs','fiber_length','EQUALS', fiberL); + fp.where('Runs','bitrate','EQUALS', bitrate_set); + fp.where('Runs','is_mpi','EQUALS', 0); + + [dataTable, ~] = db.queryDB(fp, fields); + + for k = 1:numel(curves) + + %% ===================================================== + % DECIDE PRE-EMPHASIS AND PRECoded BER + % ====================================================== + pre_emph = decide_preemph(M, curves(k).eq); + use_precoded = decide_precoded(M, curves(k).eq); + + %% ---- base config ---- + cfg = struct; + cfg.x_axis = 'wavelength'; + cfg.y_axis = 'BER'; + cfg.agg = 'min'; + cfg.outlier = 'none'; + % cfg.group_by = {'wavelength'}; + cfg.show_raw = false; + + cfg.filters = struct( ... + 'pam_level', M, ... + 'is_mpi', 0, ... + 'bitrate', bitrate_set, ... + 'fiber_length', fiberL, ... + 'equalizer_structure', curves(k).eq, ... + 'pre_emph', pre_emph); + + %% ---- Run analysis ---- + A = analyze_measurements_gpt(dataTable, cfg); + + results(p,k).wavelength = A.group{1}.x; + + %% ---- store BER variant ---- + if use_precoded + results(p,k).ber = A.group{1}.y_precoded; + else + results(p,k).ber = A.group{1}.y; + end + + end +end + + +%% ============================================================ +% PLOT — 1×3 (PAM-4, PAM-6, PAM-8) +% ============================================================ +fig = figure(9110); clf; +tiledlayout(1,3,'TileSpacing','compact','Padding','compact'); + +lw = 1.8; +ms = 6; + +for p = 1:length(pam_levels) + nexttile; hold on; + + for k = 1:numel(curves) + plot(results(p,k).wavelength, results(p,k).ber, ... + '-o', ... + 'Color', curves(k).color, ... + 'MarkerFaceColor', curves(k).color, ... + 'MarkerSize', ms, ... + 'LineWidth', lw, ... + 'DisplayName', curves(k).name); + end + + set(gca,'YScale','log'); + grid on; + if p == 1 + ylabel('BER'); + else +ylabel(''); + end + xlabel('wavelength'); + + ylim([4e-4, 0.1]); + + beautifyBERplot(); + + yline([2.2e-4 4.85e-3 2e-2], ... + 'LineWidth',1.1, 'Color',[0.2 0.2 0.2], ... + 'LineStyle',':','HandleVisibility','off'); + + + if p == 1 + + x1 = 1290; + x2 = 1297; + x3 = 1300; + x4 = 1323; + x5 = 1325; + x6 = 1330; + + elseif p == 2 + + x1 = 1290; + x2 = 1295; + x3 = 1300; + x4 = 1323.5; + x5 = 1325; + x6 = 1330; + + elseif p == 3 + + x1 = 1290; + x2 = 1292; + x3 = 1298; + x4 = 1323; + x5 = 1327.5; + x6 = 1330; + end + + % --- Get current y-limits --- + yl = ylim; + + % --- LEFT AREA BELOW KP4 FEC --- + patch([x1 x2 x2 x1], [yl(1) yl(1) yl(2) yl(2)], ... + clr.Set1.red, ... % RGB = red + 'FaceAlpha', 0.1, ... % transparency 0.1 + 'EdgeColor', 'none'); % no border + + % --- RIGHT AREA BELOW KP4 FEC --- + patch([x2 x3 x3 x2], [yl(1) yl(1) yl(2) yl(2)], ... + clr.Set1.blue, ... % RGB = red + 'FaceAlpha', 0.10, ... % transparency 0.1 + 'EdgeColor', 'none'); % no border + + % --- LEFT AREA BELOW O-FEC --- + patch([x4 x5 x5 x4], [yl(1) yl(1) yl(2) yl(2)], ... + clr.Set1.blue, ... % RGB = red + 'FaceAlpha', 0.10, ... % transparency 0.1 + 'EdgeColor', 'none'); % no border + + % --- RIGHT AREA BELOW O-FEC --- + patch([x5 x6 x6 x5], [yl(1) yl(1) yl(2) yl(2)], ... + clr.Set1.red, ... % RGB = red + 'FaceAlpha', 0.10, ... % transparency 0.1 + 'EdgeColor', 'none'); % no border + + uistack(findobj(gca,'Type','patch'),'bottom'); % send the patch behind curves + + +% ax = gca; +% axpos = ax.Position; % [x y w h] normalized +% xl = xlim; +% yl = ylim; +% +% % Convert axis coords → normalized figure coords +% toNorm = @(x,y) [ ... +% axpos(1) + (x - xl(1)) / (xl(2)-xl(1)) * axpos(3), ... +% axpos(2) + (y - yl(1)) / (yl(2)-yl(1)) * axpos(4) ... +% ]; +% +% % Choose vertical placement (10% above bottom of axis) +% y_arrow = yl(1) * (yl(2)/yl(1))^0.10; % works with log-scale axes +% +% % === Arrow 1: x3 <-> x4 ====================================== +% p1 = toNorm(x3, y_arrow); +% p2 = toNorm(x4, y_arrow); +% +% annotation('doublearrow', ... +% [p1(1) p2(1)], [p1(2) p2(2)], ... +% 'Color', [0 0 0], 'LineWidth', 1.4); +% +% % === Arrow 2: x2 <-> x5 ====================================== +% p3 = toNorm(x2, y_arrow); +% p4 = toNorm(x5, y_arrow); +% +% annotation('doublearrow', ... +% [p3(1) p4(1)], [p3(2) p4(2)], ... +% 'Color', [0 0 0], 'LineWidth', 1.4); + +end + +pos = 1e3.*[2.7770 1.2017 1.4000 0.3200]; +set(fig, 'Position', pos); + +%% === EXPORT === +outfile = 'C:\Users\Silas\Documents\latex\JLT_400G copy\media\matlab2tikz\wavelength_analysis.tikz'; +matlab2tikz(outfile, ... + 'width','\fwidth', ... + 'height','\fheight', ... + 'showInfo',false, ... + 'extraAxisOptions',{ ... + 'legend style={font=\footnotesize}', ... + 'legend columns=1' ... + }); + + + +%% ============================================================ +% DECISION LOGIC (INLINE FUNCTIONS) +% ============================================================ + +function pe = decide_preemph(M, eq) + % PRE-EMPH RULES: + switch M + case 4 + if eq == equalizer_structure.vnle + pe = 1; % PAM4: VNLE → pre-emph on + else + pe = 0; % PAM4: all others → off + end + case {6,8} + pe = 1; % PAM6/8: all → pre-emph on + otherwise + pe = 0; + end +end + + +function flag = decide_precoded(M, eq) + % PRE-CODE RULES: + if eq == equalizer_structure.vnle_db_mlse + flag = 1; % Always for DB-target + elseif eq == equalizer_structure.ml_mlse && M == 4 + flag = 1; % PAM4: ML-based → precoded + else + flag = 0; + end +end diff --git a/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_BER_3x4.m b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_BER_3x4.m new file mode 100644 index 0000000..5bd84b7 --- /dev/null +++ b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_BER_3x4.m @@ -0,0 +1,132 @@ +database_type = 'mysql'; +dataBase = 'labor_highspeed'; +db = DBHandler("dataBase", dataBase, "type", database_type); + +%% FILTER QUERY +fp = QueryFilter(); +fp.where('Runs', 'fiber_length','EQUALS', 2); +fp.where('Runs', 'wavelength','EQUALS', 1310); +fp.where('Runs', 'rop_attenuation','EQUALS', 0); + +fields = db.getTableFieldNames('power_state_info'); +fields = [fields; db.getTableFieldNames('dashboard_ungrouped_alltime')]; + +[dataTable,~] = db.queryDB(fp, fields); + +%% ---- CONFIG ---- +cfg = struct; +cfg.x_axis = 'grossrate'; +cfg.y_axis = 'BER'; +cfg.y_scale = 'log'; +cfg.outlier = 'mad'; +cfg.show_raw = false; +cfg.show_spread = 'none'; +cfg.agg = 'min'; +cfg.show_precoded = 1; +cfg.fec_lines = []; + +cfg.plot = struct; +cfg.plot.use_cbrewer2 = false; +cfg.plot.lineWidth = 2.0; +cfg.plot.errWidth = 1.2; +cfg.plot.scatterAlpha = 0.35; +cfg.plot.legendLocation = 'best'; +cfg.plot.fecLineWidth = 2.4; +cfg.plot.custom_colors_scatter = []; % disabled + +%% ---- DSP DEFINITIONS ---- +DSP(1).name = 'VNLE'; +DSP(1).eq = equalizer_structure.vnle; +DSP(1).color = clr.Paired.red; +DSP(1).lightcolor = clr.Paired.lightred; + +DSP(2).name = 'VNLE PF MLSE'; +DSP(2).eq = equalizer_structure.vnle_pf_mlse; +DSP(2).color = clr.Paired.green; +DSP(2).lightcolor = clr.Paired.lightgreen; + +DSP(3).name = 'VNLE DB MLSE'; +DSP(3).eq = equalizer_structure.vnle_db_mlse; +DSP(3).color = clr.Paired.blue; +DSP(3).lightcolor = clr.Paired.lightblue; + +DSP(4).name = 'ML MLSE'; +DSP(4).eq = equalizer_structure.ml_mlse; +DSP(4).color = clr.Paired.purple; +DSP(4).lightcolor = clr.Paired.lightpurple; + +%% ---- GRID CONFIG ---- +rows = 3; % PAM 4,6,8 +cols = 4; % DSP schemes +pam = [4 6 8]; + +cfg.figure_number = 46; +fig = figure(cfg.figure_number); clf; + +t = tiledlayout(rows, cols, ... + 'TileSpacing','compact', ... + 'Padding','compact'); + +cfg.group_by = {'equalizer_structure','pre_emph'}; +cfg.plot.use_cbrewer2 = false; + +%% ==== MAIN PLOT LOOP ===== +for r = 1:rows + Mlev = pam(r); + + for c = 1:cols + ax = nexttile(t, (r-1)*cols + c); + cfg.ax = ax; + + % ---- PRE-EMPH = 1 ---- + cfg.filters = struct('is_mpi',0,'pam_level',Mlev, ... + 'equalizer_structure',DSP(c).eq, ... + 'pre_emph',1); + cfg.plot.custom_colors = DSP(c).lightcolor; + cfg.plot.custom_linetypes = {'-'}; + [~, M1] = plot_measurements_gpt(dataTable, cfg); + + % ---- PRE-EMPH = 0 ---- + cfg.filters.pre_emph = 0; + cfg.plot.custom_colors = DSP(c).color; + cfg.plot.custom_linetypes = {'-'}; + [~, M0] = plot_measurements_gpt(dataTable, cfg); + + % Axis limits + if Mlev == 4 + ylim([1e-5 0.3]); + elseif Mlev == 6 + ylim([6e-4 0.1]); + elseif Mlev == 8 + ylim([9e-4 0.1]); + end + + % ---- FEC lines ---- + yline([2.2e-4 4.85e-3 2e-2], ... + 'LineWidth',1.1, 'Color',[0.2 0.2 0.2], ... + 'LineStyle',':','HandleVisibility','off'); + + beautifyBERplot; + + % ---- Remove redundant labels ---- + if c > 1, ax.YLabel = []; end + if r < rows, ax.XLabel = []; end + + grid(ax,'on'); box(ax,'on'); + end +end + +%% ---- FIXED FIGURE SIZE ---- +pos = 1e3.*[0.1070 0.5497 1.4113 0.6847]; +set(fig, 'Position', pos); + +% %% === EXPORT === +% outfile = 'C:\Users\Silas\Documents\latex\JLT_400G copy\media\matlab2tikz\compare_pre_emphasis.tikz'; +% matlab2tikz(outfile, ... +% 'width','\fwidth', ... +% 'height','\fheight', ... +% 'showInfo',false, ... +% 'extraAxisOptions',{ ... +% 'legend style={font=\footnotesize}', ... +% 'legend columns=1' ... +% }); diff --git a/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_EYES.m b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_EYES.m new file mode 100644 index 0000000..c22e90f --- /dev/null +++ b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_EYES.m @@ -0,0 +1,257 @@ +dsp_options.storage_path = 'Z:\2024\sioe_labor\'; +dsp_options.max_occurences = 1; +database = DBHandler("dataBase", 'labor_highspeed', "type", 'mysql' ); + +rate = [300e9]; +cols = cbrewer2('BuPu',25); +cols = [cols(end-10:2:end,:)]; +cols = cbrewer2('Set1',6); + +fignum = 200; +fig=figure(fignum);clf; + +dbmode = 0; + + +% 1 - PAM 4 with preemphasis +fp = QueryFilter(); +M = 6; +fp.where('Runs', 'pam_level','EQUALS', M); +fp.where('Runs', 'bitrate','EQUALS', rate);%360,390 +fp.where('Runs', 'fiber_length','EQUALS', 2); +fp.where('Runs', 'wavelength','EQUALS', 1310); +fp.where('Runs', 'db_mode','EQUALS', dbmode); +fp.where('Runs', 'rop_attenuation','EQUAL', 0); + +[dataTable,~] = db.queryDB(fp, database.getTableFieldNames('Runs')); + +dataTable = queryRunid(dataTable.run_id, database); +fsym = dataTable.symbolrate; +M = double(dataTable.pam_level); +duob_mode = db_mode(strrep(dataTable.db_mode,'"','')); + +% Load and Sync signal data from DB +[Tx_bits, Symbols, Scpe_cell, ~] = loadAndSyncSignalDataFromDb(dataTable, dsp_options); + +% Preprocess signal +Scpe_sig = preprocessSignal(Scpe_cell{1}, Symbols, fsym); + +Scpe_sig.eye(fsym,M,"fignum",M*10); + +%% === EXPORT TO TIKZ === +% outfile = ['C:\Users\Silas\Documents\latex\JLT_400G copy\media\matlab2tikz\eye_pam_',num2str(M),'.tikz']; +% outfile = ['C:\Users\Silas\Documents\latex\JLT_400G copy\media\matlab2tikz\vnle_optimization.tikz']; +% matlab2tikz(outfile, ... +% 'width','\fwidth', ... +% 'height','\fheight', ... +% 'showInfo',false, ... +% 'extraAxisOptions',{ ... +% 'legend style={font=\footnotesize}', ... +% 'legend columns=1' ... +% } ); + +%% + +if duob_mode == db_mode.no_db && M == 6 %only for PAM-6 and no duobinary precoding, otherwise leads to false sequence estimation + trellexlusion = 1; +else + trellexlusion = 0; +end +mlse_db_ = MLSE("DIR",[1,1],"duobinary_output",0,"M",M,"trellis_states",PAMmapper(M,0).levels,'scale_mode',2,'trellis_exclusion',trellexlusion,'trellis_state_mode',3); +len_tr = 4096*2; + +ffe_order = [50, 5, 5]; +dfe_order = [0, 0, 0]; +pf_ncoeffs = 1; +mu_ffe = [0.0001, 0.0008, 0.001]; +mu_dfe = 0.0004; +mu_dc = 0.005; +dc_buffer_len = 1; + +mu_tr = 0; +mu_dd = 0.05; +adaption= 1; +use_dd_mode = 1; +ffe_order = [50, 5, 5]; +eq_ = EQ("Ne",ffe_order,"Nb",dfe_order,"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1); + +dbt_results = duobinary_target(eq_, mlse_db_, M, Scpe_sig, Symbols, Tx_bits, ... + "precode_mode", duob_mode, ... + 'showAnalysis', 1,... + "postFFE", []); + +%% === FINAL FIGURE SIZE === + +% Existing figure numbers +figEye = 249; +figConst = 341; + +% Find axes in the source figures +srcAxEye = findobj(figEye, 'Type', 'axes'); +srcAxConst = findobj(figConst, 'Type', 'axes'); + +% Create new combined figure +figCombined = figure; +t = tiledlayout(figCombined, 1, 2); +t.TileSpacing = 'compact'; +t.Padding = 'compact'; + +% ------------------------------------------------------------ +% LEFT TILE: EYE DIAGRAM +% ------------------------------------------------------------ +ax1 = nexttile(t, 1); +hold(ax1, 'on') + +% Copy children (images, lines, patches, hist objects, etc.) +copyobj(srcAxEye.Children, ax1); + +% Copy labels and title +ax1.XLabel.String = srcAxEye.XLabel.String; +ax1.YLabel.String = srcAxEye.YLabel.String; +ax1.Title.String = srcAxEye.Title.String; + +% Copy axis limits +ax1.XLim = srcAxEye.XLim; +ax1.YLim = srcAxEye.YLim; +ax1.YDir = srcAxEye.YDir; + +% Copy ticks + labels EXACTLY (including remapped/scaled ones) +ax1.XTick = srcAxEye.XTick; +ax1.XTickLabel = srcAxEye.XTickLabel; +ax1.YTick = srcAxEye.YTick; +ax1.YTickLabel = srcAxEye.YTickLabel; + +% Copy colormap + clim (important for density eye) +colormap(ax1, colormap(srcAxEye.Parent)); +ax1.CLim = srcAxEye.CLim; + +% Copy any style props that matter +ax1.TickDir = srcAxEye.TickDir; +ax1.TickLength = srcAxEye.TickLength; +ax1.FontSize = srcAxEye.FontSize; +ax1.Box = srcAxEye.Box; + +grid(ax1,'on'); + + +% ------------------------------------------------------------ +% RIGHT TILE: CONSTELLATION HISTOGRAM +% ------------------------------------------------------------ +ax2 = nexttile(t, 2); +hold(ax2, 'on') + +copyobj(srcAxConst.Children, ax2); + +% Copy labels and title +ax2.XLabel.String = srcAxConst.XLabel.String; +ax2.YLabel.String = srcAxConst.YLabel.String; +ax2.Title.String = srcAxConst.Title.String; + +% The histogram uses the same y-axis as the eye +% Extract mapping from eye +rawTicks = ax1.YTick; +rawLabelsCell = ax1.YTickLabel; +trueVoltages = str2double(rawLabelsCell); + +% Apply true voltages to the histogram axis +ax2.XTick = flip(trueVoltages); +ax2.XTickLabel = flip(rawLabelsCell); + +% Set histogram y-limits to match the actual voltages +ax2.XLim = [min(trueVoltages) max(trueVoltages)]; + +% Ensure eye diagram prints the same (we *do not* touch ax1.YLim) +ax1.XTickLabel = rawLabelsCell; + + +% Copy colormap (your histogram uses same palette) +colormap(ax2, colormap(srcAxConst.Parent)); + +% Style properties +ax2.TickDir = srcAxConst.TickDir; +ax2.TickLength = srcAxConst.TickLength; +ax2.FontSize = srcAxConst.FontSize; +ax2.Box = srcAxConst.Box; + +grid(ax2,'on'); + +% ============================================================ +% remove right y-axis completely +% ============================================================ +ax2.XAxis.Visible = 'off'; % hides ticks + labels + axis line + +% BUT we still keep the YTick positions internally for alignment: +% ax2.YTick = ; + + +% ============================================================ +% minimize distance between the two plots +% ============================================================ +t.TileSpacing = 'none'; % no space between tiles +t.Padding = 'none'; % no outer padding + +% Also reduce internal padding for each axis +ax1.Position(3) = ax1.Position(3) + 0.02; % widen eye a bit +ax2.Position(1) = ax2.Position(1) - 0.02; % pull histogram closer + + +% Keep left axis grid visible +ax2.YGrid = 'off'; + +% +% ===================================================================== +% FINAL POLISHING: unified visual style +% ======================================================================= + +% --- unified font size --- +FS = 12; +set([ax1 ax2], 'FontSize', FS); + +% --- unified axis line width (outline stroke thickness) --- +LW = 1.0; +set([ax1 ax2], 'LineWidth', LW); + +% --- unified tick length --- +TL = [.015 .015]; +set([ax1 ax2], 'TickLength', TL); + +% --- unified grid style --- +set([ax1 ax2], 'XGrid', 'on', 'YGrid', 'on'); +set([ax1 ax2], 'GridLineStyle', '--'); +set([ax1 ax2], 'GridAlpha', 0.2); + +% --- remove right y-axis ticks and labels --- +ax2.YAxis.Visible = 'off'; + +% --- copy colormap + CLim from the eye to histogram (synchronize look) --- +colormap(ax1, colormap(srcAxEye.Parent)); +colormap(ax2, colormap(srcAxEye.Parent)); +ax2.CLim = ax1.CLim; + +% --- minimal spacing between tiles --- +t.TileSpacing = 'none'; +t.Padding = 'none'; + + +% --- pull the panels together (touching boundary effect) --- +pos1 = ax1.Position; +pos2 = ax2.Position; + +% Shift histogram left until the outlines touch +pos2(1) = pos1(1) + pos1(3) - 0.002; % 0.002 = fine overlap control +ax2.Position = pos2; + +% Expand histogram slightly, remove white band +pos2 = ax2.Position; +pos2(3) = pos2(3) + 0.01; +ax2.Position = pos2; + +% Ensure the left plot stays correct after the move +ax1.Position = pos1; + +% --- enforce same visible outline --- +% For ax2, create a fake left spine (since YAxis is hidden) +ax2.Box = 'on'; % keep outline but no ticks on the right +ax1.Box = 'on'; + +ax2.View = [90 -90]; \ No newline at end of file diff --git a/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_NGMI.m b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_NGMI.m new file mode 100644 index 0000000..cf3e317 --- /dev/null +++ b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_NGMI.m @@ -0,0 +1,221 @@ +%% ============================================================ +% GRID: NGMI, AIR, HD-NetRate, SD-NetRate (1 × 4) +% ============================================================ + +db = DBHandler("dataBase","labor_highspeed","type","mysql"); + +%% --- Base DB Filters (shared across all curves) +fp = QueryFilter(); +fp.where('Runs','fiber_length','EQUALS', 2); +fp.where('Runs','wavelength','EQUALS', 1310); +fp.where('Runs','rop_attenuation','EQUALS', 0); +fp.where('Runs','is_mpi','EQUALS', 0); + +fields = db.getTableFieldNames('dashboard_ungrouped_alltime'); +[dataTable,~] = db.queryDB(fp, fields); + + +%% === Curve Definitions ======================================= +curves = struct; + +% PAM-8 — VNLE PF MLSE — no_emph = 1 — RED +curves(1).pam = 8; +curves(1).eq = equalizer_structure.vnle_pf_mlse; +curves(1).pre = 0; +curves(1).color = clr.Paired.red; +curves(1).mkr = 'o'; + +% PAM-6 — VNLE PF MLSE — no_emph = 1 — BLUE +curves(2).pam = 6; +curves(2).eq = equalizer_structure.vnle_pf_mlse; +curves(2).pre = 1; +curves(2).color = clr.Paired.blue; +curves(2).mkr = 'square'; + +% PAM-4 — VNLE DB MLSE — pre_emph = 0 — GREEN +curves(3).pam = 4; +curves(3).eq = equalizer_structure.vnle_db_mlse; +curves(3).pre = 0; +curves(3).color = clr.Paired.green; +curves(3).mkr = 'diamond'; + +%% === Prepare Analysis Config ================================== +base = struct; +base.group_by = {'equalizer_structure','pre_emph'}; +base.x_axis = 'symbolrate'; +base.outlier = 'none'; +base.show_raw = false; +base.filters = struct; % will be filled per curve + + +%% === Precompute All Curves ==================================== +results = struct; + +for k = 1:numel(curves) + + % --- BER --- + cfg = base; + cfg.y_axis = 'BER'; + cfg.agg = 'min'; + cfg.filters = struct('pam_level', curves(k).pam, ... + 'equalizer_structure', curves(k).eq, ... + 'pre_emph', curves(k).pre); + + A = analyze_measurements_gpt(dataTable, cfg); + cfg.x_axis = 'grossrate'; + B = analyze_measurements_gpt(dataTable, cfg); + + results(k).baudr = A.group{1}.x; + results(k).gross = B.group{1}.x; + + if curves(k).pam == 4 + results(k).ber = A.group{1}.y_precoded; + else + results(k).ber = A.group{1}.y; + end + + % --- NGMI --- + cfg.y_axis = 'NGMI'; + cfg.agg = 'max'; + A = analyze_measurements_gpt(dataTable, cfg); + results(k).ngmi = A.group{1}.y; + + + + % --- AIR --- + cfg.y_axis = 'AIR'; + cfg.agg = 'max'; + A = analyze_measurements_gpt(dataTable, cfg); + results(k).air = A.group{1}.y; + results(k).air = results(k).ngmi .* results(k).gross; + + % --- Net Rates --- + tp = TransmissionPerformance; + results(k).ndr = tp.calculateNetRate(results(k).gross, ... + 'NGMI', results(k).ngmi, ... + 'BER', results(k).ber); +end + + +%% ============================================================ +% FIGURE: 1 × 4 GRID +% ============================================================ +fig = figure(71); clf; +t = tiledlayout(1,4, 'TileSpacing','compact', 'Padding','compact'); + +lw = 1.0; + +% === NGMI vs Grossrate === +ax = nexttile(t,1); +hold on; +for k = 1:3 + plot(results(k).baudr, results(k).ngmi, ... + 'LineWidth', lw, ... + 'Color', curves(k).color, ... + 'MarkerSize', 1, ... + 'MarkerFaceColor', curves(k).color,... + 'Marker',curves(k).mkr); +end +ylabel('NGMI'); +xlabel('Baud rate [GBd]'); +xlim([100 210]); +xticks(100:15:225); +ylim([0.9, 1]); +grid minor; box on; +beautifyBERplot("logscale",0,"setmarkers",0); + + +% === AIR vs Grossrate === +ax = nexttile(t,2); +hold on; +for k = 1:3 + plot(results(k).baudr, results(k).air, ... + '-', 'LineWidth', lw, ... + 'Color', curves(k).color, ... + 'MarkerSize', 2, ... + 'MarkerFaceColor', curves(k).color,'Marker',curves(k).mkr); +end +ylabel('AIR [Gb/s]'); +xlabel('Baud rate [GBd]'); +ylim([280 430]); +yticks(280:30:440) +xlim([100 210]); +xticks(100:15:225); +grid minor; box on; +beautifyBERplot("logscale",0,"setmarkers",0); +yline(400,'LineStyle','--'); + +% === SD-FEC Net Rate === +ax = nexttile(t,3); +hold on; +for k = 1:3 + plot(results(k).baudr, results(k).ndr.SDHD.NetRate, ... + 'LineWidth', lw, ... + 'Color', curves(k).color, ... + 'MarkerSize', 2, ... + 'MarkerFaceColor', curves(k).color,... + 'Marker',curves(k).mkr); +end +ylabel('NDR [Gb/s]'); +xlabel('Baud rate [GBd]'); +ylim([280 430]); +yticks(280:30:440) +xlim([100 210]); +xticks(100:15:225); +grid minor; box on; +beautifyBERplot("logscale",0,"setmarkers",0); +yline(400,'LineStyle','--'); + +% === HD-FEC Net Rate === +ax = nexttile(t,4); +hold on; +for k = 1:3 + % plot(results(k).baudr, results(k).ndr.STAIR.NetRate, ... + % '-', 'LineWidth', lw, ... + % 'Color', curves(k).color, ... + % 'MarkerSize', 4,'Marker','+', ... + % 'MarkerFaceColor', curves(k).color); + + plot(results(k).baudr, results(k).ndr.O_FEC.NetRate, ... + ':', 'LineWidth', lw, ... + 'Color', curves(k).color, ... + 'MarkerSize', 2,... + 'MarkerFaceColor', curves(k).color,... + 'Marker',curves(k).mkr); + + plot(results(k).baudr, results(k).ndr.KP4_hamming.NetRate, ... + '--', 'LineWidth', lw, ... + 'Color', curves(k).color, ... + 'MarkerSize', 2,'Marker','diamond', ... + 'MarkerFaceColor', curves(k).color,... + 'Marker',curves(k).mkr); +end + +yline(400,'LineStyle','--'); +ylabel(''); +xlabel('Baud rate [GBd]'); +ylim([280 430]); +yticks(280:30:440) +xlim([100 210]); +xticks(100:15:225); +grid minor; box on; +beautifyBERplot("logscale",0,"setmarkers",0); + +% === FINAL FIGURE SIZE === +pos = 1e3.*[0.7950 1.1150 1.4113 0.1900]; +set(fig, 'Position', pos); + +% % % %% === EXPORT === +outfile = 'C:\Users\Silas\Documents\latex\JLT_400G copy\media\matlab2tikz\compare_ndr_v3.tikz'; +matlab2tikz(outfile, ... + 'width','\fwidth', ... + 'height','\fheight', ... + 'showInfo',false, ... + 'extraAxisOptions',{ ... + 'legend style={font=\footnotesize}', ... + 'legend columns=1' ... + 'every axis/.append style={font=\scriptsize}',... + 'minor grid style={line width=0.2pt, solid, color=black!10}',... + 'grid style={line width=0.4pt, solid, color=black!20}',... + 'grid style={dashed}',... + }); diff --git a/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_NGMI_v2.m b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_NGMI_v2.m new file mode 100644 index 0000000..a690207 --- /dev/null +++ b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_NGMI_v2.m @@ -0,0 +1,180 @@ +%% ============================================================ +% GRID (1 × 4): +% 1) NGMI overview (PAM4+PAM6+PAM8 superimposed) +% 2) PAM-4 tile (AIR + SD-NDR + HD-NDR) +% 3) PAM-6 tile +% 4) PAM-8 tile +% ============================================================ + +db = DBHandler("dataBase","labor_highspeed","type","mysql"); + +%% --- Base DB Filters (shared across all curves) +fp = QueryFilter(); +fp.where('Runs','fiber_length','EQUALS', 2); +fp.where('Runs','wavelength','EQUALS', 1310); +fp.where('Runs','rop_attenuation','EQUALS', 0); +fp.where('Runs','is_mpi','EQUALS', 0); + +fields = db.getTableFieldNames('dashboard_ungrouped_alltime'); +[dataTable,~] = db.queryDB(fp, fields); + +%% === CURVE DEFINITIONS ================================================= +curves = struct; + +curves(1).pam = 8; +curves(1).eq = equalizer_structure.vnle_pf_mlse; +curves(1).pre = 0; +curves(1).color = clr.Paired.red; + +curves(2).pam = 6; +curves(2).eq = equalizer_structure.vnle_pf_mlse; +curves(2).pre = 1; +curves(2).color = clr.Paired.blue; + +curves(3).pam = 4; +curves(3).eq = equalizer_structure.vnle_db_mlse; +curves(3).pre = 0; +curves(3).color = clr.Paired.green; + +% === ANALYSIS ENGINE (extract BER/NGMI/AIR/netrates) =================== +base = struct; +base.group_by = {'equalizer_structure','pre_emph'}; +base.x_axis = 'grossrate'; +base.outlier = 'none'; +base.show_raw = false; + +results = struct; + +for k = 1:numel(curves) + + % ========== BER ========== + cfg = base; + cfg.y_axis = 'BER'; + cfg.agg = 'min'; + + cfg.filters = struct('pam_level', curves(k).pam, ... + 'equalizer_structure', curves(k).eq, ... + 'pre_emph', curves(k).pre); + A = analyze_measurements_gpt(dataTable, cfg); + + results(k).gross = A.group{1}.x; + if curves(k).pam == 4 + results(k).ber = A.group{1}.y_precoded; + else + results(k).ber = A.group{1}.y; + end + + % ========== NGMI ========== + cfg.y_axis = 'NGMI'; cfg.agg = 'max'; + A = analyze_measurements_gpt(dataTable, cfg); + results(k).ngmi = A.group{1}.y; + + % ========== AIR ========== + cfg.y_axis = 'AIR'; cfg.agg = 'max'; + A = analyze_measurements_gpt(dataTable, cfg); + results(k).air = A.group{1}.y; + + % ========== NET RATES ========== + tp = TransmissionPerformance; + results(k).ndr = tp.calculateNetRate(results(k).gross, ... + 'NGMI', results(k).ngmi, ... + 'BER', results(k).ber); +end + + +% ============================================================ +% FIGURE +% ============================================================ +fig = figure(3); +t = tiledlayout(1,4,'TileSpacing','compact','Padding','compact'); + +lw = 1.7; + +% ======================================================================= +% (1) NGMI OVERVIEW TILE (all 3 curves) +% ======================================================================= +ax = nexttile(t,1); hold on; + +for k = 1:3 + plot(results(k).gross, results(k).ngmi, ... + '-o', 'Color', curves(k).color, ... + 'LineWidth',lw,'MarkerSize',5, ... + 'MarkerFaceColor',curves(k).color); +end + +ylabel('NGMI'); +xlabel('Grossrate [Gb/s]'); +ylim([0.9 1]); % your chosen limits +xlim([300 480]); +xticks(300:30:480) +grid minor; box on; +beautifyBERplot; + +% ======================================================================= +% (2–4) PAM-SPECIFIC TILES: AIR, SD-NDR, HD-NDR +% ======================================================================= + +pam_order = [4 6 8]; % left → right + +for ti = 1:3 + pam_target = pam_order(ti); + ax = nexttile(t, 1+ti); hold on; + + % find matching curve + for k = 1:3 + if curves(k).pam ~= pam_target, continue; end + + col = curves(k).color; + + % AIR + plot(results(k).gross, results(k).air, ... + '-','Color',col,'LineWidth',lw,'Marker','*', ... + 'MarkerSize',5,'MarkerFaceColor',col,'DisplayName','AIR'); + + % SD-based net rate + plot(results(k).gross, results(k).ndr.SDHD.NetRate, ... + '--','Color',col,'LineWidth',lw,'Marker','v', ... + 'MarkerSize',5,'MarkerFaceColor',col,'DisplayName','SD+HD'); + + % HD-based net rate + plot(results(k).gross, results(k).ndr.STAIR.NetRate, ... + ':','Color',col,'LineWidth',lw,'Marker','x', ... + 'MarkerSize',5,'MarkerFaceColor',col,'DisplayName','HD-FEC (Staircase)'); + + % HD-based net rate + plot(results(k).gross, results(k).ndr.O_FEC.NetRate, ... + 'LineStyle','-.','Color',col,'LineWidth',lw,'Marker','+', ... + 'MarkerSize',5,'MarkerFaceColor',col,'DisplayName','O-FEC'); + + % HD-based net rate + plot(results(k).gross, results(k).ndr.KP4_hamming.NetRate, ... + 'LineStyle','-','Color',col,'LineWidth',lw,'Marker','x', ... + 'MarkerSize',5,'MarkerFaceColor',col,'DisplayName','KP4+Hamming'); + end + + ylabel('NDR [Gb/s]'); + xlabel('Grossrate [Gb/s]'); + ylim([300 440]); % your chosen limits + yticks(300:20:480) + xlim([300 480]); + xticks(300:30:480) + grid minor; box on; + beautifyBERplot; + yline(400,'HandleVisibility','off'); +end + +% === FIX FIGURE SIZE FOR TIKZ ========================================== +if 0 +pos = 1e3.*[0.3643 0.9943 1.4113 0.2120]; +set(fig,'Position',pos); + +% outfile = 'C:\Users\Silas\Documents\latex\JLT_400G copy\media\matlab2tikz\compare_ndr.tikz'; +% matlab2tikz(outfile, ... +% 'width','\fwidth', ... +% 'height','\fheight', ... +% 'showInfo',false, ... +% 'extraAxisOptions',{ ... +% 'legend style={font=\footnotesize}', ... +% 'legend columns=1' ... +% }); +end \ No newline at end of file diff --git a/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_ROP.m b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_ROP.m new file mode 100644 index 0000000..5a3c530 --- /dev/null +++ b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_ROP.m @@ -0,0 +1,153 @@ +%% ============================================================ +% LOAD DATA (PAM-4, sweep over ROP) +% ============================================================ +database_type = 'mysql'; +db = DBHandler("dataBase", "labor_highspeed", "type", database_type); + +pam_level = 4; +fiberL = 1; % 1 km +wlen = 1310; +baudrate = 360e9; + +fp = QueryFilter(); +fp.where('Runs','pam_level','EQUALS', pam_level); +fp.where('Runs','fiber_length','EQUALS', fiberL); +fp.where('Runs','wavelength','EQUALS', wlen); +fp.where('Runs','bitrate','EQUALS', baudrate); +fp.where('Runs','power_pd_in','LESS_THAN', 7); + +fields = [ + db.getTableFieldNames('power_state_info'); + db.getTableFieldNames('dashboard_ungrouped_alltime') +]; + +[dataTable,~] = db.queryDB(fp, fields); + + +%% ============================================================ +% DSP SCHEMES (Best combinations only) +% ============================================================ +curves = struct; + +curves(1).name = 'VNLE'; +curves(1).eq = equalizer_structure.vnle; +curves(1).color = clr.Paired.red; + +curves(2).name = 'PF + MLSE'; +curves(2).eq = equalizer_structure.vnle_pf_mlse; +curves(2).color = clr.Paired.green; + +curves(3).name = 'DB-target + MLSE'; +curves(3).eq = equalizer_structure.vnle_db_mlse; +curves(3).color = clr.Paired.blue; + +curves(4).name = 'ML-based MLSE'; +curves(4).eq = equalizer_structure.ml_mlse; +curves(4).color = clr.Paired.purple; + + + + +%% ============================================================ +% ANALYSIS ENGINE (No plotting) +% ============================================================ +results = struct; + +for k = 1:numel(curves) + + pre_emph = decide_preemph(pam_level,curves(k).eq); + precoded = decide_precoded(pam_level,curves(k).eq); + + cfg = struct; + cfg.x_axis = 'power_mzm'; % ROP axis + cfg.y_axis = 'BER'; + cfg.agg = 'min'; + cfg.outlier = 'none'; + cfg.show_raw = false; + + cfg.filters = struct( ... + 'pam_level', pam_level, ... + 'fiber_length', fiberL, ... + 'wavelength', wlen, ... + 'bitrate', baudrate, ... + 'is_mpi', 0, ... + 'equalizer_structure', curves(k).eq, ... + 'pre_emph', pre_emph); + + A = analyze_measurements_gpt(dataTable, cfg); + + results(k).x = A.group{1}.x; + if precoded + results(k).ber = A.group{1}.y_precoded; + else + results(k).ber = A.group{1}.y; + end +end + + +%% ============================================================ +% PLOT — BER vs ROP (Single Axis) +% ============================================================ +fig = figure(); clf; hold on; + +lw = 2.0; +ms = 7; + +for k = 1:numel(curves) + plot(results(k).x, results(k).ber, ... + '-o', ... + 'Color', curves(k).color, ... + 'MarkerFaceColor', curves(k).color, ... + 'MarkerSize', ms, ... + 'LineWidth', lw, ... + 'DisplayName', curves(k).name); +end + +set(gca,'YScale','log'); +grid on; + +xlabel('ROP / Power (MZM) [dBm]'); +ylabel('BER'); + +ylim([1e-4 2e-1]); + +title(sprintf('BER vs ROP — PAM-%d, %.0f km, %.0f GBd, %.0f nm', ... + pam_level, fiberL, baudrate*1e-9, wlen)); + +legend('Location','best'); +beautifyBERplot(); + +pos = 1e3.*[0.2 0.6 1.3 0.4]; +set(fig, 'Position', pos); + +%% ============================================================ +% DECISION LOGIC (INLINE FUNCTIONS) +% ============================================================ + +function pe = decide_preemph(M, eq) + % PRE-EMPH RULES: + switch M + case 4 + if eq == equalizer_structure.vnle + pe = 1; % PAM4: VNLE → pre-emph on + else + pe = 0; % PAM4: all others → off + end + case {6,8} + pe = 1; % PAM6/8: all → pre-emph on + otherwise + pe = 0; + end +end + + +function flag = decide_precoded(M, eq) + % PRE-CODE RULES: + if eq == equalizer_structure.vnle_db_mlse + flag = 1; % Always for DB-target + elseif eq == equalizer_structure.ml_mlse && M == 4 + flag = 1; % PAM4: ML-based → precoded + else + flag = 0; + end +end diff --git a/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_Spectra.m b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_Spectra.m new file mode 100644 index 0000000..97dc7a9 --- /dev/null +++ b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_Spectra.m @@ -0,0 +1,182 @@ +dsp_options.storage_path = 'Z:\2024\sioe_labor\'; +dsp_options.max_occurences = 1; +database = DBHandler("dataBase", 'labor_highspeed', "type", 'mysql' ); + +rates = [300e9]; +cols = cbrewer2('BuPu',25); +cols = [cols(end-10:2:end,:)]; +cols = cbrewer2('Set1',6); + +fignum = 200; +fig=figure(fignum);clf; + +for dbmode = 0:1%length(rates) + + + if 0 + rcalpha = 0.05; + fsym = rates/2; + pulsef = 1; + Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rrc","pulselength",16,"alpha",rcalpha); + + Pamsource = PAMsource(... + "fsym",fsym,"M",4,"order",18,"useprbs",0,... + "fs_out",fdac,... + "applyclipping",0,"clipfactor",1.2,... + "applypulseform",pulsef,"pulseformer",Pform,... + "randkey",20,... + "db_precode",dbmode,"db_encode",0,... + "mrds_code",0,"mrds_blocklength",512); + + [Digi_sig,Symbols,Bits] = Pamsource.process(); + + Digi_sig = Digi_sig.normalize("mode","rms"); + + %%% 1) PLOT FULL RESPONSE SIGNAL + Digi_sig.spectrum("displayname","Full Response","fignum",fignum+dbmode,"normalizeToNyquist",0,"normalizeTo0dB",0,"color",[0.2,0.2,0.2],"linestyle",'-','addDCoffset',0,'normalizeToDC',1); + + + %%% 2) PLOT PREEMPH. TX SIGNAL + if dbmode == 0 + maxamp = -37; + precomp_est = ChannelFreqResp("Nacq",2048,"Navg",100,"Ncp",63,'f_ref',Digi_sig.fs); + + precomp_path = "C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\precomp"; + precomp_fn = "lab_high_speed"; + Digi_sig_pre = precomp_est.precomp(Digi_sig,'maxampdb',maxamp,'loadPath',precomp_path,'fileName',precomp_fn); + + Digi_sig_pre = Digi_sig_pre.resample("fs_out",fdac); + + Digi_sig_pre= Digi_sig_pre.normalize("mode","rms"); + + Digi_sig_pre.spectrum("displayname","Strong Precomp","fignum",fignum+dbmode,"normalizeToNyquist",0,"normalizeTo0dB",0,"color",[0,0,0],"linestyle",'-.','addDCoffset',0,'normalizeToDC',1); + end + + end + + % 1 - PAM 4 with preemphasis + fp = QueryFilter(); + M = 4; + fp.where('Runs', 'pam_level','EQUALS', M); + fp.where('Runs', 'bitrate','EQUALS', rates);%360,390 + fp.where('Runs', 'fiber_length','EQUALS', 10); + fp.where('Runs', 'wavelength','EQUALS', 1322.7); %1327.4 + fp.where('Runs', 'db_mode','EQUALS', dbmode); + fp.where('Runs', 'rop_attenuation','EQUAL', 0); + + [dataTable,~] = database.queryDB(fp, database.getTableFieldNames('Runs')); + + dataTable = queryRunid(dataTable.run_id, database); + fsym = dataTable.symbolrate; + M = double(dataTable.pam_level); + + % Load and Sync signal data from DB + [Tx_bits, Symbols, Scpe_cell, ~] = loadAndSyncSignalDataFromDb(dataTable, dsp_options); + + % Preprocess signal + Scpe_sig = preprocessSignal(Scpe_cell{1}, Symbols, fsym); + Scpe_sig = Scpe_cell{1}; + + %%% 3) PLOT DB Tgt. SIGNAL + if 1 + DB_Symbols = Duobinary().encode(Symbols); + DB_Symbols.spectrum("fignum",fignum+dbmode,"normalizeTo0dB",1,"displayname",'DB-Response','addDCoffset',0,'color',clr.Set1.blue,'normalizeToNyquist',0,'linestyle','--'); + end + + %%% 4) Plot RX Signal + Scpe_sig.spectrum("fignum",fignum+dbmode,"normalizeTo0dB",1,"displayname",'Rx','addDCoffset',1,'color',[0,0,0],'normalizeToNyquist',0,'linestyle',':'); +Scpe_sig.eye(fsym,M,"fignum",47,"displayname",' Eye of AVG Signal'); + % xline(Symbols.fs/2.*1e-9,'Color',cols(r,:),'HandleVisibility','off'); + + average_signals = 1; + if average_signals + Scpe_sig_avg = Scpe_sig; + scope_mean = zeros(size(Scpe_cell{1}.signal)); + for n=1:numel(Scpe_cell) + scope_mean = scope_mean + Scpe_cell{n}.signal; + end + scope_mean = scope_mean ./ n; + Scpe_sig_avg.signal = scope_mean; + + Scpe_sig_avg.spectrum("displayname","Scope PSD","fignum",20,"normalizeTo0dB",1); + Scpe_sig_avg.plot("displayname","Scope raw signal","fignum",27,"clear",1); + Scpe_sig_avg.eye(fsym,M,"fignum",48,"displayname",' Eye of AVG Signal'); + end + + + fig = figure(fignum+dbmode); + if dbmode == 0 + ylim([-22,12]); + else + ylim([-22,2]); + end + xlim([0,105]); + xticks(-100:20:100); + yticks(-20:10:10); + + beautifyBERplot("logscale",0,"setmarkers",0) + pos = [100.3333 991.6667 358.0000 192.6667]; + set(fig, 'Position', pos); + + %%%%%%%%%%%% + drawnow; + + % Do EQ and find alpha's + len_tr = 4096*2; + + ffe_order = [50, 5, 5]; + dfe_order = [0, 0, 0]; + pf_ncoeffs = 1; + mu_ffe = [0.0001, 0.0008, 0.001]; + mu_dfe = 0.0004; + mu_dc = 0.005; + + %%% FULL RESP TARGET + eq_ = EQ("Ne",ffe_order,"Nb",dfe_order,"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",0); + pf_1 = Postfilter("ncoeff",1,"useBurg",1); + + [eq_signal_sd, eq_noise] = eq_.process(Scpe_sig, Symbols); + + % eq_noise.signal = eq_noise.signal - mean(eq_noise.signal); + % eq_noise = eq_noise.normalize("mode","rms"); + + [mlse_sig_sd,whitened_noise] = pf_1.process(eq_signal_sd, eq_noise); + + fig = figure(fignum+dbmode+10); hold on + + [h, w] = freqz(1, pf_1.coefficients, length(eq_noise), "whole", eq_noise.fs); + h = h / max(abs(h)); % Normalize the filter response + w_ = (w - eq_noise.fs / 2); + + %%% DB TARGET + db_ref_sequence = Duobinary().encode(Symbols); + eq_ = EQ("Ne",ffe_order,"Nb",dfe_order,"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",0); + [eq_signal, db_noise] = eq_.process(Scpe_sig,db_ref_sequence); + + % db_noise.signal = db_noise.signal - mean(db_noise.signal); + % db_noise = db_noise.normalize("mode","rms"); + + %%% 1-3) Plot EQ Noise EEN + figure(fignum+dbmode+10) + eq_noise.spectrum("displayname", 'Noise', "fignum", fignum+dbmode+10, "normalizeTo0dB", 0,"color",clr.Set1.green,"normalizeToDC",0,"addDCoffset",0); + if dbmode == 1 + offset = 27.7; + else + offset = 29.8; + end + plot(w_ * 1e-9, 20 * log10(fftshift(abs(h)))-offset, 'DisplayName', ['Burg Coeffs: ', num2str(round(pf_1.coefficients, 2)), ' '], 'LineWidth', 1,'Color',clr.Set1.green,'LineStyle','--'); + db_noise.spectrum("displayname", 'DBt. Noise', "fignum", fignum+dbmode+10, "normalizeTo0dB", 0,"color",clr.Set1.blue,"normalizeToDC",0,"addDCoffset",0); + + ylim([-54,-25]); + xlim([0,105]); + xticks(0:20:110); + yticks(-50:10:10); + + beautifyBERplot("logscale",0,"setmarkers",0) + pos = [100.3333 991.6667 358.0000 192.6667]; + set(fig, 'Position', pos); + +end + + +% === FINAL FIGURE SIZE === diff --git a/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_WAVELENGTH.m b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_WAVELENGTH.m new file mode 100644 index 0000000..ffac5d2 --- /dev/null +++ b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_WAVELENGTH.m @@ -0,0 +1,124 @@ +%% ============================================================ +% LOAD DATA +% ============================================================ +database_type = 'mysql'; +db = DBHandler("dataBase", "labor_highspeed", "type", database_type); + +M = 4; % PAM level for this analysis + +fp = QueryFilter(); +fp.where('Runs', 'pam_level', 'EQUALS', M); +fp.where('Runs', 'fiber_length', 'EQUALS', 10); +fp.where('Runs', 'bitrate', 'EQUALS', 360e9); +fp.where('Runs', 'is_mpi', 'EQUALS', 0); + +fields = [ + db.getTableFieldNames('power_state_info'); + db.getTableFieldNames('dashboard_ungrouped_alltime') +]; + +[dataTable, ~] = db.queryDB(fp, fields); + + +%% ============================================================ +% COMMON CONFIGURATION FOR ALL SUBPLOTS +% ============================================================ +%% ============================================================ +% DEFINE DSP ALGORITHMS FOR THE 4 SUBPLOTS +% ============================================================ +curves = struct; + +curves(1).name = 'VNLE'; +curves(1).eq = equalizer_structure.vnle; +curves(1).pre = 0; +curves(1).color = clr.Paired.red; + +curves(2).name = 'PF + MLSE'; +curves(2).eq = equalizer_structure.vnle_pf_mlse; +curves(2).pre = 0; +curves(2).color = clr.Paired.green; + +curves(3).name = 'DB-target + MLSE'; +curves(3).eq = equalizer_structure.vnle_db_mlse; +curves(3).pre = 0; +curves(3).color = clr.Paired.blue; + +curves(4).name = 'ML-based MLSE'; +curves(4).eq = equalizer_structure.ml_mlse; +if M == 4 +curves(4).pre = 0; +else +curves(4).pre = 1; +end +curves(4).color = clr.Paired.purple; + + +%% ============================================================ +% ANALYSIS ENGINE — NO PLOTTING +% ============================================================ +results = struct; + +for k = 1:numel(curves) + + %% ---- BASE CONFIG ---- + cfg = struct; + cfg.x_axis = 'wavelength'; + cfg.y_axis = 'BER'; + cfg.agg = 'min'; + cfg.outlier = 'none'; + % cfg.group_by = {'wavelength'}; + cfg.show_raw = false; + + cfg.filters = struct( ... + 'pam_level', M, ... + 'is_mpi', 0, ... + 'bitrate', 360e9, ... + 'fiber_length', 10, ... + 'equalizer_structure', curves(k).eq, ... + 'pre_emph', curves(k).pre); + + %% ---- GET BER ---- + cfg.y_axis = 'BER'; + A = analyze_measurements_gpt(dataTable, cfg); + + results(k).wavelength = A.group{1}.x; + + if curves(k).eq == equalizer_structure.vnle_db_mlse || ... + curves(k).eq == equalizer_structure.ml_mlse + % DB and ML-based need precoded BER + results(k).ber = A.group{1}.y_precoded; + else + results(k).ber = A.group{1}.y; + end + +end + +%% ============================================================ +% 1×4 TILED BER-vs-WAVELENGTH FIGURE +% ============================================================ +fig=figure(901); +tiledlayout(1,4,'TileSpacing','compact','Padding','compact'); + +lw = 1.8; % line width +ms = 6; % marker size + +for k = 1:numel(curves) + nexttile; hold on; + + plot(results(k).wavelength, results(k).ber, ... + '-o', ... + 'Color', curves(k).color, ... + 'MarkerFaceColor', curves(k).color, ... + 'MarkerSize', ms, ... + 'LineWidth', lw); + + set(gca,'YScale','log'); + grid on; + xlabel('wavelength'); + ylabel('BER'); + title(curves(k).name); + ylim([1e-4, 0.1]) + beautifyBERplot(); +end +pos = 1e3.*[0.1070 0.5497 1.4113 0.3253]; +set(fig, 'Position', pos); \ No newline at end of file diff --git a/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_WAVELENGTH_VS_BAUDRATE.m b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_WAVELENGTH_VS_BAUDRATE.m new file mode 100644 index 0000000..d987359 --- /dev/null +++ b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_WAVELENGTH_VS_BAUDRATE.m @@ -0,0 +1,160 @@ +%% ============================================================ +% PARAMETERS +% ============================================================ +database_type = 'mysql'; +db = DBHandler("dataBase", "labor_highspeed", "type", database_type); + +pam_level = 4; % FIXED for this figure +baudrates = [300e9 330e9 360e9 390e9]; +fiberL = 10; + +fields = [ + db.getTableFieldNames('power_state_info'); + db.getTableFieldNames('dashboard_ungrouped_alltime') +]; + +%% ============================================================ +% DEFINE DSP SCHEMES +% ============================================================ +curves = struct; + +curves(1).name = 'VNLE'; +curves(1).eq = equalizer_structure.vnle; +curves(1).color = clr.Paired.red; + +curves(2).name = 'PF + MLSE'; +curves(2).eq = equalizer_structure.vnle_pf_mlse; +curves(2).color = clr.Paired.green; + +curves(3).name = 'DB-target + MLSE'; +curves(3).eq = equalizer_structure.vnle_db_mlse; +curves(3).color = clr.Paired.blue; + +curves(4).name = 'ML-based MLSE'; +curves(4).eq = equalizer_structure.ml_mlse; +curves(4).color = clr.Paired.purple; + + +%% ============================================================ +% ANALYSIS — results(b, k): b = baudrate index, k = DSP scheme index +% ============================================================ +results = struct; + +for b = 1:length(baudrates) + + Rb = baudrates(b); + + % --- query matching runs --- + fp = QueryFilter(); + fp.where('Runs','pam_level','EQUALS', pam_level); + fp.where('Runs','fiber_length','EQUALS', fiberL); + fp.where('Runs','bitrate','EQUALS', Rb); + fp.where('Runs','is_mpi','EQUALS', 0); + + [dataTable, ~] = db.queryDB(fp, fields); + + for k = 1:numel(curves) + + %% ---- DECIDE PRE-EMPH & PRECoded RULES for PAM-4 ---- + pre_emph = decide_preemph(pam_level, curves(k).eq); + use_precoded = decide_precoded(pam_level, curves(k).eq); + + %% ---- SETUP ANALYSIS CONFIG ---- + cfg = struct; + cfg.x_axis = 'wavelength'; + cfg.y_axis = 'BER'; + cfg.agg = 'min'; + cfg.outlier = 'none'; + % cfg.group_by = {'wavelength'}; + cfg.show_raw = false; + + cfg.filters = struct( ... + 'pam_level', pam_level, ... + 'is_mpi', 0, ... + 'bitrate', Rb, ... + 'fiber_length', fiberL, ... + 'equalizer_structure', curves(k).eq, ... + 'pre_emph', pre_emph); + + %% ---- RUN ANALYSIS ---- + A = analyze_measurements_gpt(dataTable, cfg); + + results(b,k).wavelength = A.group{1}.x; + + if use_precoded + results(b,k).ber = A.group{1}.y_precoded; + else + results(b,k).ber = A.group{1}.y; + end + end +end + + +%% ============================================================ +% PLOT — 1×4 (one tile per baudrate) +% ============================================================ +fig = figure(); clf; +tiledlayout(1,4,'TileSpacing','compact','Padding','compact'); + +lw = 1.8; +ms = 6; + +for b = 1:length(baudrates) + nexttile; hold on; + + for k = 1:numel(curves) + plot(results(b,k).wavelength, results(b,k).ber, ... + '-o', ... + 'Color', curves(k).color, ... + 'MarkerFaceColor', curves(k).color, ... + 'MarkerSize', ms, ... + 'LineWidth', lw, ... + 'DisplayName', curves(k).name); + end + + set(gca,'YScale','log'); + grid on; + xlabel('Wavelength [nm]'); + ylabel('BER'); + ylim([1e-4 0.1]); + title(sprintf('PAM-%d @ %.0f GBd',pam_level, baudrates(b)/1e9)); + legend('Location','best'); + beautifyBERplot(); +end + +% Optional figure size +pos = 1e3.*[0.1 0.55 1.4 0.32]; +set(fig, 'Position', pos); + + +%% ============================================================ +% DECISION LOGIC (INLINE FUNCTIONS) +% ============================================================ + +function pe = decide_preemph(M, eq) + % PRE-EMPH RULES: + switch M + case 4 + if eq == equalizer_structure.vnle + pe = 1; % PAM4: VNLE → pre-emph on + else + pe = 0; % PAM4: all others → off + end + case {6,8} + pe = 1; % PAM6/8: all → pre-emph on + otherwise + pe = 0; + end +end + + +function flag = decide_precoded(M, eq) + % PRE-CODE RULES: + if eq == equalizer_structure.vnle_db_mlse + flag = 1; % Always for DB-target + elseif eq == equalizer_structure.ml_mlse && M == 4 + flag = 1; % PAM4: ML-based → precoded + else + flag = 0; + end +end diff --git a/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_introduction.m b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_introduction.m new file mode 100644 index 0000000..2213c8a --- /dev/null +++ b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_introduction.m @@ -0,0 +1,88 @@ +%% ============================================================ +% PLOT +% ============================================================ +figure; hold on; +ms = 32; % scatter size +lw = 0.8; % line width + +for k = 1:4 % PAM-2/4/6/8 + + M = pam_list(k); + idxPam = (Mvals == M); + + % Extract for this PAM + x = baud(idxPam); + y = netrate(idxPam); + n = names(idxPam); + + % Get color for this PAM format + col = colors(k,:); + + % ----- LEGEND FLAG (only add one entry per PAM) ----- + firstLegend = true; + + % ---- PLOT ALL POINTS (marker based on publication) ---- + for i = 1:sum(idxPam) + + % marker selection by publication + pubIdx = find(pub_list == n(i), 1); + marker = markerlist{mod(pubIdx-1, nMarkers) + 1}; + + if firstLegend + h = scatter(x(i), y(i), ms, ... + 'Marker', marker, ... + 'MarkerEdgeColor', col, ... + 'MarkerFaceColor', col, ... + 'DisplayName', sprintf('PAM-%d', M)); + firstLegend = false; + else + h = scatter(x(i), y(i), ms, ... + 'Marker', marker, ... + 'MarkerEdgeColor', col, ... + 'MarkerFaceColor', col, ... + 'HandleVisibility','off'); + end + + % ====== CUSTOM DATATIP CONTENT ====== + dt = h.DataTipTemplate; + dt.DataTipRows(1).Label = 'Baud rate'; + dt.DataTipRows(2).Label = 'Net rate'; + + % Add publication name + dt.DataTipRows(end+1) = dataTipTextRow('Publication', n(i)); + + + end + + % ---- Fit (PAM-specific) ---- + valid = ~isnan(x) & ~isnan(y); + if sum(valid) >= 3 + p = polyfit(x(valid), y(valid), 2); + xfit = linspace(min(x(valid)), max(x(valid)), 200); + yfit = polyval(p, xfit); + + plot(xfit, yfit, ':', ... + 'LineWidth', lw, ... + 'Color', col, ... + 'HandleVisibility', 'off'); % do NOT add to legend + end +end + +grid on; +xlabel('Baud rate [GBd]'); +ylabel('Net rate [Gb/s]'); + +legend('Location','northwest'); +set(gca,'FontSize',11); + + +%% === EXPORT === +outfile = 'C:\Users\Silas\Documents\latex\JLT_400G copy\media\matlab2tikz\highspeedresults.tikz'; +matlab2tikz(outfile, ... + 'width','\fwidth', ... + 'height','\fheight', ... + 'showInfo',false, ... + 'extraAxisOptions',{ ... + 'legend style={font=\footnotesize}', ... + 'legend columns=1' ... + }); diff --git a/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/HighSpeedExperiments.xlsx b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/HighSpeedExperiments.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..59d1ab509026f1099bc19cd39d470e6bd700e11e GIT binary patch literal 26210 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 literal 0 HcmV?d00001 diff --git a/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/analyze_measurements_gpt.m b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/analyze_measurements_gpt.m new file mode 100644 index 0000000..9ab6e85 --- /dev/null +++ b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/analyze_measurements_gpt.m @@ -0,0 +1,334 @@ +function [M, cfg] = analyze_measurements_gpt(T, cfg) +% ANALYZE_MEASUREMENTS_GPT +% Filter, compute X/Y, group and aggregate measurements from table T. +% No plotting here. +% +% Usage: +% [M, cfg] = analyze_measurements_gpt(dataTable, cfg); +% +% Typical result (single group): +% M.x -> aggregated x-values (e.g., grossrate) +% M.y -> aggregated y-values (e.g., BER or NGMI) +% M.y_precoded -> aggregated precoded BER (if available) +% +% For multiple groups: +% M.group(g).x, M.group(g).y, M.group(g).label, ... + +%% ---- Defaults (non-plot) ---- +if nargin < 2, cfg = struct; end +defaults = struct( ... + 'x_axis' , 'symbolrate', ... + 'y_axis' , 'BER', ... + 'y_scale' , 'auto', ... + 'group_by' , {{'equalizer_structure','pre_emph'}}, ... + 'filters' , struct, ... + 'agg' , 'mean', ... + 'outlier' , 'auto', ... + 'mad_z' , 4, ... + 'pct_limits' , [2.5 97.5], ... + 'min_pts_x' , 3, ... + 'show_raw' , true, ... + 'show_precoded', [], ... + 'show_spread' , 'none', ... + 'fec_lines' , [], ... + 'plot' , struct() ... % plot settings handled in plot function +); +cfg = filldefaults(cfg, defaults); + +%% ---- Derived/prep columns ---- +if ~ismember('pre_emph', T.Properties.VariableNames) + if ~ismember('db_mode', T.Properties.VariableNames) + error('Missing column "db_mode" for pre_emph derivation.'); + end + T.pre_emph = T.db_mode == 0; +end + +if ~ismember(cfg.y_axis, T.Properties.VariableNames) + error('y_axis "%s" not found in table.', cfg.y_axis); +end + +isBER = startsWith(cfg.y_axis, "BER", 'IgnoreCase', true); +M.isBER = isBER; + +if strcmpi(cfg.y_scale,'auto') + cfg.y_scale = tern(isBER, 'log', 'linear'); +end +if strcmpi(cfg.outlier,'auto') + cfg.outlier = tern(isBER, 'mad', 'none'); +end +if isempty(cfg.show_precoded) + cfg.show_precoded = isBER && ismember('BER_precoded', T.Properties.VariableNames); +end + +%% ---- Filters & core X/Y extraction ---- +T = applyFilters(T, cfg.filters); + +[x_raw, x_label] = computeX(T, cfg.x_axis); +y_raw = T.(cfg.y_axis); + +validXY = isfinite(x_raw) & isfinite(y_raw); +T = T(validXY, :); +x_raw = x_raw(validXY); +y_raw = y_raw(validXY); + +% Degiga if needed +if mean(abs(y_raw)) > 1e8 + y_raw = y_raw .* 1e-9; +end + +if cfg.show_precoded && ismember('BER_precoded', T.Properties.VariableNames) + y_raw_p = T.BER_precoded(validXY); +else + y_raw_p = []; +end + +%% ---- Grouping ---- +group_by = cfg.group_by; +if ~all(ismember(group_by, T.Properties.VariableNames)) + error('Some group_by columns are missing in table.'); +end +[G, grpTbl] = findgroups(T(:, group_by)); +nG = max(G); + +%% ---- Aggregation per group ---- +M = struct; +M.cfg = cfg; +M.x_label = x_label; +M.y_axis = cfg.y_axis; +M.x_axis = cfg.x_axis; +M.nGroups = nG; + +% raw (filtered) data +M.raw = struct; +M.raw.x = x_raw; +M.raw.y = y_raw; +M.raw.y_precoded = y_raw_p; +M.raw.T = T; + +M.group = cell(nG,1); + +useLog = strcmpi(cfg.y_scale,'log'); +for gi = 1:nG + idx = (G == gi); + Ti = T(idx,:); + xi = x_raw(idx); + yi = y_raw(idx); + + [xu, ~, iu] = unique(xi); + yu = nan(size(xu)); + ylo = nan(size(xu)); + yhi = nan(size(xu)); + + for k = 1:numel(xu) + bin = (iu==k); + yy = yi(bin); + yy = yy(isfinite(yy)); + if isempty(yy), continue; end + + km = outlierMask(yy, cfg, useLog); + if nnz(km) < cfg.min_pts_x, km = true(size(yy)); end + yy = yy(km); + + switch lower(cfg.agg) + case 'median' + yu(k) = median(yy,'omitnan'); + case 'mean' + yu(k) = mean(yy,'omitnan'); + case 'min' + yu(k) = min(yy); + case 'max' + yu(k) = max(yy); + otherwise + error('Unknown agg mode "%s".', cfg.agg); + end + + if strcmpi(cfg.show_spread,'iqr') + q = prctile(yy,[25 75]); + ylo(k) = max(yu(k)-q(1), eps); + yhi(k) = max(q(2)-yu(k), eps); + elseif strcmpi(cfg.show_spread,'minmax') + ylo(k) = min(yy); + yhi(k) = max(yy); + end + end + + % sort by x + [xu, ord] = sort(xu); + yu = yu(ord); + ylo = ylo(ord); + yhi = yhi(ord); + + g = struct; + g.label = buildLabel(grpTbl(gi,:), group_by); + g.idx = find(G==gi); + g.T = Ti; + g.x_raw = xi; + g.y_raw = yi; + g.x = xu; + g.y = yu; + g.y_lo = ylo; + g.y_hi = yhi; + g.y_precoded = []; + g.y_precoded_lo = []; + g.y_precoded_hi = []; + + % Precoded aggregation (if requested & available) + if cfg.show_precoded && ~isempty(y_raw_p) && strcmpi(cfg.y_axis,'BER') + ypi = y_raw_p(idx); + ypu = nan(size(xu)); + + for k = 1:numel(xu) + bin = (iu==k); + yy = ypi(bin); + yy = yy(isfinite(yy)); + if isempty(yy), continue; end + + km = outlierMask(yy, cfg, true); + if nnz(km) < cfg.min_pts_x, km = true(size(yy)); end + yy = yy(km); + + switch lower(cfg.agg) + case 'median' + ypu(k) = median(yy,'omitnan'); + case 'mean' + ypu(k) = mean(yy,'omitnan'); + case 'min' + ypu(k) = min(yy); + case 'max' + ypu(k) = max(yy); + end + end + + g.y_precoded = ypu(ord); + end + + M.group{gi} = g; +end + +% Convenience flatten for single-group case +if nG == 1 + g = M.group{1}; + M.x = g.x; + M.y = g.y; + M.y_precoded = g.y_precoded; +end + +end % ===== main ===== + + +%% ===================== Helpers ===================== + +function cfg = filldefaults(cfg, defs) +fn = fieldnames(defs); +for i = 1:numel(fn) + f = fn{i}; + if ~isfield(cfg, f) || isempty(cfg.(f)) + cfg.(f) = defs.(f); + elseif isstruct(defs.(f)) && isstruct(cfg.(f)) + cfg.(f) = filldefaults(cfg.(f), defs.(f)); % recursive + end +end +end + +function out = tern(cond, a, b) +if cond + out = a; +else + out = b; +end +end + +function T2 = applyFilters(T, filters) +if isempty(filters), T2 = T; return; end +keep = true(height(T),1); +fns = fieldnames(filters); +for i = 1:numel(fns) + name = fns{i}; + if ~ismember(name, T.Properties.VariableNames) + warning('Filter column "%s" not found. Ignored.', name); + continue + end + val = filters.(name); + col = T.(name); + if isa(val,'function_handle') + m = val(col); + if ~islogical(m) || ~isequal(size(m), size(col)) + error('Filter for %s must return logical mask of same size.', name); + end + keep = keep & m; + else + keep = keep & ismember(col, val); + end +end +T2 = T(keep,:); +end + +function [x, label] = computeX(T, whichX) +switch lower(whichX) + case {'symbolrate','baudrate'} + x = T.symbolrate * 1e-9; + label = 'Symbol rate [GBd]'; + case 'bitrate' + if ~ismember('pam_level', T.Properties.VariableNames) + error('bitrate requires "pam_level" column.'); + end + bits = floor(log2(double(T.pam_level))*10)/10; + x = (T.symbolrate .* bits) * 1e-9; + label = 'Grossrate [Gb/s]'; + case 'grossrate' + x = T.grossrate * 1e-9; + label = 'Grossrate [Gb/s]'; + otherwise + if ~ismember(whichX, T.Properties.VariableNames) + error('x_axis "%s" not found in table.', whichX); + end + x = T.(whichX); + label = whichX; +end +x = double(x(:)); +end + +function keep = outlierMask(y, cfg, useLog) +if isempty(y), keep = false(size(y)); return; end +y = y(:); +switch lower(cfg.outlier) + case 'none' + keep = true(size(y)); return + case 'mad' + z = tern(useLog, log10(y), y); + med = median(z,'omitnan'); + madv = median(abs(z-med),'omitnan'); + if ~(isfinite(madv) && madv>0) + keep = true(size(y)); return + end + sigma = 1.4826*madv; + zz = tern(useLog, log10(y), y); + keep = abs(zz - med) <= cfg.mad_z*sigma; + case 'pctl' + pr = prctile(y, cfg.pct_limits); + keep = (y >= pr(1)) & (y <= pr(2)); + otherwise + error('Unknown outlier mode "%s".', cfg.outlier); +end +end + +function s = buildLabel(grpRow, group_by) +parts = strings(1, numel(group_by)); +for i = 1:numel(group_by) + key = group_by{i}; + val = grpRow.(key); + if iscell(val), val = val{1}; end + if islogical(val), val = tern(val,'w/','w/o'); end + if key == "equalizer_structure" + key = ''; + val = upper(val); + val = strrep(val,'_',' '); + end + if key == "pre_emph" + val = [val, ' pre-emph.']; + key = ''; + end + parts(i) = sprintf('%s %s', key, string(val)); +end +s = strjoin(parts, ', '); +end diff --git a/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/compare_ber_best_results.m b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/compare_ber_best_results.m index b38a814..5b2e245 100644 --- a/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/compare_ber_best_results.m +++ b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/compare_ber_best_results.m @@ -86,8 +86,9 @@ cfg.filters = struct('is_mpi',0,'pam_level',4, ... cfg.show_precoded = 1; a = plot_measurements_gpt(dataTable, cfg); ngmi_pam4 = a.lines(1).YData; +grossrates = a.lines(1).XData; tp = TransmissionPerformance; -netrates_vnle = tp.calculateNetRate(baudrate.* m, ... +netrates_vnle = tp.calculateNetRate(grossrates, ... 'NGMI', ngmi_pam4, ... 'BER', BER_VNLE); @@ -151,10 +152,26 @@ cfg.fec_lines = []; cfg.agg = 'max'; cfg.figure_number = 47; -% fig = figure(cfg.figure_number); lambda = 1310; +% cfg = struct; +cfg.filters = struct('is_mpi',0,'pam_level',4, ... + 'equalizer_structure',equalizer_structure.vnle_db_mlse, ... + 'pre_emph',0,'wavelength',lambda); +cfg.x_axis = 'grossrate'; +cfg.y_axis = 'NGMI'; % or 'NGMI', etc. +cfg.show_precoded = 1; + +[M, cfg] = analyze_measurements_gpt(dataTable, cfg); + +grossrates = M.x; % aggregated X +ber = M.y; % aggregated Y (BER or NGMI) +ber_prec = M.y_precoded; % precoded BER (if available) + +[h, M] = plot_measurements_gpt(dataTable, cfg); + + % PAM 4 cfg.plot.custom_colors = clr.Paired.red; cfg.plot.custom_linetypes = {'-'}; diff --git a/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/compare_ber_complete_results.m b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/compare_ber_complete_results.m deleted file mode 100644 index 5cd72da..0000000 --- a/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/compare_ber_complete_results.m +++ /dev/null @@ -1,170 +0,0 @@ -database_type = 'mysql'; -dataBase = 'labor_highspeed'; -db = DBHandler("dataBase", [dataBase], "type", database_type); - - -% M = 4; -fp = QueryFilter(); -% fp.where('Runs', 'pam_level','EQUALS', M); -fp.where('Runs', 'fiber_length','EQUALS', 2); -fp.where('Runs', 'wavelength','EQUALS', 1310); -% fp.where('Runs', 'db_mode','EQUALS', 1); % 0 == high preemphasis // 1 == low preemphasis -fp.where('Runs', 'rop_attenuation','EQUALS', 0); - -fields = db.getTableFieldNames('power_state_info'); -fields = [fields; db.getTableFieldNames('dashboard_ungrouped_alltime')]; %dashboard_ungrouped_after_nov_2025 dashboard_ungrouped_aug_nov_2025 -[dataTable,~] = db.queryDB(fp, fields); - -%% -cfg = struct; -cfg.x_axis = 'grossrate'; % 'symbol rate' | 'bitrate' | 'wavelength' grossrate -cfg.y_axis = 'BER'; % 'BER' | 'GMI' | 'AIR' | ... - -cfg.y_scale = 'auto'; % auto -> log for BER*, linear otherwise -cfg.outlier = 'mad'; % simple, robust; 'none' or 'pctl' also available -cfg.show_raw = false; -cfg.show_spread = 'none'; % 'none' or 'iqr' or minmax -cfg.agg = 'min'; % or 'median' -cfg.show_precoded = 0; - -% cfg.fec_lines = [2.2e-4 4.85e-3 2e-2]; % optional -cfg.fec_lines = []; -cfg.plot.custom_colors = [ - clr.Paired.red; - clr.Paired.blue; - clr.Paired.green; - clr.Paired.orange; - clr.Paired.purple -]; - -cfg.plot.custom_colors_scatter = [ - clr.Paired.lightred; - clr.Paired.lightblue; - clr.Paired.lightgreen; - clr.Paired.lightorange; - clr.Paired.lightpurple -]; - - -% New styling knobs -cfg.plot.use_cbrewer2 = true; -cfg.plot.colormap = 'Paired'; -cfg.plot.paired_dark_first = false; % dark for lines, light for scatter -cfg.plot.lineWidth = 2.0; -cfg.plot.errWidth = 1.2; -cfg.plot.scatterAlpha = 0.35; -cfg.plot.legendLocation = 'best'; -cfg.plot.fecLineWidth = 2.4; % thicker FEC limits -cfg.plot.lineStyle_pre_emph_on = '-'; -cfg.plot.lineStyle_pre_emph_off = '-'; - - -%% Grid configuration -rows = 3; % PAM 4,6,8 -cols = 4; % DSP schemes -pam = [4 6 8]; - -cfg.figure_number = 46; -fig = figure(cfg.figure_number); clf; - -% Create extremely compact tile layout -t = tiledlayout(rows, cols, ... - 'TileSpacing','compact', ... - 'Padding','compact'); - -% Common cfg -cfg.show_precoded = 1; -cfg.group_by = {'equalizer_structure','pre_emph'}; -cfg.x_axis = 'grossrate'; -cfg.y_axis = 'BER'; -cfg.y_scale = 'log'; -cfg.plot.custom_colors_scatter = []; -cfg.plot.use_cbrewer2 = false; -cfg.fec_lines = []; -% DSP scheme definitions --------------------------------------------- -DSP(1).name = 'vnle'; -DSP(1).eq = equalizer_structure.vnle; -DSP(1).color = clr.Paired.red; -DSP(1).lightcolor = clr.Paired.lightred; - -DSP(2).name = 'VNLE PF MLSE'; -DSP(2).eq = equalizer_structure.vnle_pf_mlse; -DSP(2).color = clr.Paired.green; -DSP(2).lightcolor = clr.Paired.lightgreen; - -DSP(3).name = 'VNLE DB MLSE'; -DSP(3).eq = equalizer_structure.vnle_db_mlse; -DSP(3).color = clr.Paired.blue; -DSP(3).lightcolor = clr.Paired.lightblue; - -DSP(4).name = 'ML MLSE'; -DSP(4).eq = equalizer_structure.ml_mlse; -DSP(4).color = clr.Paired.purple; -DSP(4).lightcolor = clr.Paired.lightpurple; - - -% === Main nested loop: rows = PAM format, columns = DSP scheme === -for r = 1:rows - M = pam(r); - - for c = 1:cols - ax = nexttile(t, (r-1)*cols + c); - cfg.ax = ax; - - % ---- pre-emph = 1 (solid) ---- - cfg.plot.custom_colors = DSP(c).lightcolor; - cfg.plot.custom_linetypes = {'-'}; - cfg.filters = struct('is_mpi',0,'pam_level',M, ... - 'equalizer_structure',DSP(c).eq, ... - 'pre_emph',1); - plot_measurements_gpt(dataTable, cfg); - - % ---- pre-emph = 0 (dashed) ---- - cfg.plot.custom_colors = DSP(c).color; - cfg.plot.custom_linetypes = {'-'}; - cfg.filters.pre_emph = 0; - plot_measurements_gpt(dataTable, cfg); - - if M == 4 - ylim([1e-5 0.2]); - else - ylim([6e-4 0.2]); - end - - % % FEC limits - yline([2.2e-4 4.85e-3 2e-2],'LineWidth',1.1,'Color',[0.2 0.2 0.2], ... - 'LineStyle',':','HandleVisibility','off'); - - % Axes prettification - beautifyBERplot; - - % ===== Remove redundant labels ===== - if c > 1 - ax.YLabel = []; - end - if r < rows - ax.XLabel = []; - end - - grid(ax,'on'); box(ax,'on'); - end -end - -%this is just a ranom size but fits and is fixed now! -pos = 1e3.*[0.0983 0.6110 1.4113 0.4733]; -set(fig, 'Position', pos) - - - - -%% === EXPORT TO TIKZ === -outfile = 'C:\Users\Silas\Documents\latex\JLT_400G copy\media\matlab2tikz\compare_pre_emphasis.tikz'; - -matlab2tikz(outfile, ... - 'width','\fwidth', ... - 'height','\fheight', ... - 'showInfo',false, ... - 'extraAxisOptions',{ ... - 'legend style={font=\footnotesize}', ... - 'legend columns=1' ... - } ); \ No newline at end of file diff --git a/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/example_usage.m b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/example_usage.m new file mode 100644 index 0000000..bf3d4bf --- /dev/null +++ b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/example_usage.m @@ -0,0 +1,92 @@ +% ============================================================ +% MINIMAL EXAMPLE: Query → Analyze → Plot → Extract X/Y data +% ============================================================ + +%% === Load from database === +db = DBHandler("dataBase","labor_highspeed","type","mysql"); + +fp = QueryFilter(); +fp.where('Runs','fiber_length','EQUALS',2); +% fp.where('Runs','pam_level','EQUALS',6); % PAM-4 +% fp.where('Runs','db_mode','EQUALS',0); % w/o pre-emph + +fields = db.getTableFieldNames('dashboard_ungrouped_alltime'); +[dataTable,~] = db.queryDB(fp, fields); + + + + + +%% === Define config === + +for m = [4,6,8] + + cfg = struct; + cfg.x_axis = 'symbolrate'; + cfg.y_axis = 'Alpha'; + cfg.group_by = {'equalizer_structure','pre_emph'}; + cfg.filters = struct('is_mpi',0,'pam_level',m, ... + 'equalizer_structure',equalizer_structure.vnle_pf_mlse, ... + 'pre_emph',0); + cfg.agg = 'max'; + cfg.outlier = 'mad'; + cfg.show_raw = false; + cfg.show_precoded = 0; + + % Plot cosmetics (minimal) + cfg.plot = struct; + cfg.plot.custom_colors = linspecer(8); + cfg.plot.custom_linetypes = {'-'}; + cfg.plot.lineWidth = 2; + + + % ============================================================ + % === ANALYSIS ONLY (no plotting) ============================= + % ============================================================ + A = analyze_measurements_gpt(dataTable, cfg); + + % Now you have: + % A.raw.x = raw x-values + % A.raw.y = raw BER values + % A.group{1}.x = unique sorted x-values + % A.group{1}.y = aggregated BER for each x + + x_values = A.group{1}.x; + y_values = A.group{1}.y; + + + % ============================================================ + % === PLOT ==================================================== + % ============================================================ + + figure(10);hold on + cfg.ax = gca; % optional: plot into existing axes + plot(x_values,y_values,... + 'LineWidth', 2, ... + 'Color', clr.Set1.red, ... + 'MarkerSize', 5, ... + 'MarkerFaceColor', clr.Set1.red,... + 'Marker','o'); + % [h, ~] = plot_measurements_gpt(dataTable, cfg); + + title('Minimal VNLE BER Example') + xlabel('Grossrate [Gb/s]') + ylabel('BER') + xticks(100:30:220) + xlim([100,220]); + ylim([0,1]); + +end +% outfile = 'C:\Users\Silas\Documents\latex\JLT_400G copy\media\matlab2tikz\alphas.tikz'; +% matlab2tikz(outfile, ... +% 'width','\fwidth', ... +% 'height','\fheight', ... +% 'showInfo',false, ... +% 'extraAxisOptions',{ ... +% 'legend style={font=\footnotesize}', ... +% 'legend columns=1' ... +% 'every axis/.append style={font=\scriptsize}',... +% 'minor grid style={line width=0.2pt, solid, color=black!10}',... +% 'grid style={line width=0.4pt, solid, color=black!20}',... +% 'grid style={dashed}',... +% }); diff --git a/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/generate_spectrum_plots.m b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/generate_spectrum_plots.m index 29ec0c4..f90cf1a 100644 --- a/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/generate_spectrum_plots.m +++ b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/generate_spectrum_plots.m @@ -65,7 +65,7 @@ Scpe_sig.spectrum("fignum",201,"normalizeTo0dB",0,"displayname",'Rx'); -if 0 +if 1 %% show freuqncy response of filter measure = 1; @@ -74,7 +74,7 @@ if 0 % Digi_sig = freqresp.buildOFDM(); - Digi_sig.spectrum("fignum",1112,"displayname",['maxamp:',num2str(maxamp)]); + % Digi_sig.spectrum("fignum",1112,"displayname",['maxamp:',num2str(maxamp)]); Digi_sig = Filter('filtdegree',3,"f_cutoff",70e9,"fs",256e9,"filterType",filtertypes.butterworth,"active",true).process(Digi_sig); @@ -97,4 +97,15 @@ if 0 fprintf('Plotting: %s\n', precomp_filename); freqresp.plot(); + + outfile = 'C:\Users\Silas\Documents\latex\JLT_400G copy\media\matlab2tikz\spectrum_2.tikz'; +matlab2tikz(outfile, ... + 'width','\fwidth', ... + 'height','\fheight', ... + 'showInfo',false, ... + 'extraAxisOptions',{ ... + 'legend style={font=\footnotesize}', ... + 'legend columns=1' ... + }); + end \ No newline at end of file diff --git a/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/plot_measurements_gpt.m b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/plot_measurements_gpt.m index fc88501..a31fab0 100644 --- a/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/plot_measurements_gpt.m +++ b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/plot_measurements_gpt.m @@ -1,111 +1,51 @@ -function h = plot_measurements_gpt(T, cfg) -% Versatile plotting from your DB table (with cbrewer2 'Paired' palette). +function [h, M, cfg] = plot_measurements_gpt(T, cfg) +% PLOT_MEASUREMENTS_GPT +% Plot measurements, using analyze_measurements_gpt for data handling. % % Usage: -% h = plot_measurements_flex(dataTable, cfg) +% h = plot_measurements_gpt(dataTable, cfg); +% [h, M] = plot_measurements_gpt(dataTable, cfg); +% +% For values only, without plotting, call: +% [M, cfg] = analyze_measurements_gpt(dataTable, cfg); -%% ---- Defaults if nargin < 2, cfg = struct; end -defaults = struct( ... - 'x_axis' , 'symbolrate', ... - 'y_axis' , 'BER', ... - 'y_scale' , 'auto', ... - 'group_by' , {{'equalizer_structure','pre_emph'}}, ... - 'filters' , struct, ... - 'agg' , 'mean', ... - 'outlier' , 'auto', ... - 'mad_z' , 4, ... - 'pct_limits' , [2.5 97.5], ... - 'min_pts_x' , 3, ... - 'show_raw' , true, ... - 'show_precoded', [], ... - 'show_spread' , 'none', ... - 'fec_lines' , [], ... - 'plot', struct() ... -); -cfg = filldefaults(cfg, defaults); -% ---- Plot defaults (new) +% --- First: run analysis (filtering, grouping, aggregation) --- +[M, cfg] = analyze_measurements_gpt(T, cfg); + +nG = M.nGroups; + +%% ---- Plot defaults ---- plotdefs = struct( ... 'use_cbrewer2' , true, ... - 'colormap' , 'Paired', ... % ColorBrewer 'Paired' - 'paired_dark_first' , true, ... % dark for lines, light for scatter + 'colormap' , 'Paired', ... + 'paired_dark_first' , true, ... 'lineWidth' , 1.8, ... 'errWidth' , 1.0, ... 'scatterSize' , 14, ... 'scatterAlpha' , 0.35, ... 'marker' , 'o', ... 'marker_precoded' , 's', ... - 'lineStyle_pre_emph_on' , '--', ... - 'lineStyle_pre_emph_off', '-', ... 'legendLocation' , 'best', ... - 'fecLineWidth' , 2.2, ... % thicker FEC limits + 'fecLineWidth' , 2.2, ... 'fecColor' , [0.25 0.25 0.25], ... 'capSize' , 6, ... - 'lineStyle_default' , '-', ... - 'use_pre_emph_styling' , true ... + 'lineStyle_default' , '-', ... + 'custom_colors' , [], ... + 'custom_colors_scatter' , [] ... ); +if ~isfield(cfg,'plot') || isempty(cfg.plot) + cfg.plot = struct; +end cfg.plot = filldefaults(cfg.plot, plotdefs); -%% ---- Derived/prep columns -if ~ismember('pre_emph', T.Properties.VariableNames) - if ~ismember('db_mode', T.Properties.VariableNames) - error('Missing column "db_mode" for pre_emph derivation.'); - end - T.pre_emph = T.db_mode == 0; -end -if ~ismember(cfg.y_axis, T.Properties.VariableNames) - error('y_axis "%s" not found in table.', cfg.y_axis); -end - -isBER = startsWith(cfg.y_axis, "BER", 'IgnoreCase', true); -if strcmpi(cfg.y_scale,'auto'), cfg.y_scale = tern(isBER, 'log', 'linear'); end -if strcmpi(cfg.outlier,'auto'), cfg.outlier = tern(isBER, 'mad', 'none'); end -if isempty(cfg.show_precoded) - cfg.show_precoded = isBER && ismember('BER_precoded', T.Properties.VariableNames); -end - -%% ---- Filters -T = applyFilters(T, cfg.filters); -[x_raw, x_label] = computeX(T, cfg.x_axis); -y_raw = T.(cfg.y_axis); - -validXY = isfinite(x_raw) & isfinite(y_raw); -T = T(validXY, :); -x_raw = x_raw(validXY); -y_raw = y_raw(validXY); - -if mean(abs(y_raw)) > 1e8 - %giga values - y_raw = y_raw.*1e-9; -end - -if cfg.show_precoded && ismember('BER_precoded', T.Properties.VariableNames) - y_raw_p = T.BER_precoded(validXY); -else - y_raw_p = []; -end - -%% ---- Grouping -group_by = cfg.group_by; -if ~all(ismember(group_by, T.Properties.VariableNames)) - error('Some group_by columns are missing in table.'); -end -[G, grpTbl] = findgroups(T(:, group_by)); -nG = max(G); - -% ==== Colors (cbrewer2 'Paired' with dark/ light pairs) ==== +%% ---- Colors ---- [cols_line, cols_scatter] = buildGroupColors(nG, cfg.plot); -%% ---- Axes / Figure handling (new unified logic) - -% Priority: -% 1) cfg.ax → use existing axes (subplots/tiles) -% 2) cfg.figure_number → select/create figure -% 3) fallback: create new figure - +%% ---- Axes / Figure handling ---- if isfield(cfg,'ax') && ~isempty(cfg.ax) && isgraphics(cfg.ax,'axes') - ax = cfg.ax; % use caller-provided axes + ax = cfg.ax; set(gcf,'CurrentAxes',ax); else if isfield(cfg,'figure_number') && ~isempty(cfg.figure_number) @@ -113,143 +53,97 @@ else else figure; end - ax = gca; % active axes + ax = gca; end - hold(ax,'on'); grid(ax,'on'); - h.lines = gobjects(nG,1); h.err = gobjects(nG,1); h.scat = gobjects(nG,1); h.lines_p = gobjects(nG,1); +%% ---- Plot each group ---- for gi = 1:nG - idx = (G==gi); - Ti = T(idx,:); - xi = x_raw(idx); - yi = y_raw(idx); + g = M.group{gi}; + xu = g.x; + yu = g.y; + ylo = g.y_lo; + yhi = g.y_hi; - % Aggregate per unique x - [xu, ia, iu] = unique(xi); - yu = nan(size(xu)); - ylo = nan(size(xu)); - yhi = nan(size(xu)); - - for k = 1:numel(xu) - bin = (iu==k); - yy = yi(bin); - yy = yy(isfinite(yy)); - if isempty(yy), continue; end - km = outlierMask(yy, cfg, strcmpi(cfg.y_scale,'log')); - if nnz(km) < cfg.min_pts_x, km = true(size(yy)); end - yy = yy(km); - - if strcmpi(cfg.agg,'median'), yu(k)=median(yy,'omitnan'); elseif strcmpi(cfg.agg,'mean'), yu(k)=mean(yy,'omitnan'); elseif strcmpi(cfg.agg,'min'), yu(k)=min(yy); elseif strcmpi(cfg.agg,'max'), yu(k)=max(yy); end - if strcmpi(cfg.show_spread,'iqr') - q = prctile(yy,[25 75]); - ylo(k) = max(yu(k)-q(1), eps); - yhi(k) = max(q(2)-yu(k), eps); - elseif strcmpi(cfg.show_spread,'minmax') - ylo(k) = min(yy); - yhi(k) = max(yy); - end - end - - % sort - [xu, ord] = sort(xu); - yu = yu(ord); - ylo = ylo(ord); - yhi = yhi(ord); - - % Styles - % Decide if we style by pre_emph - % --- LINE TYPE SELECTION (no pre-emphasis logic) --- + % --- Linestyle selection --- ls = cfg.plot.lineStyle_default; - - % User-defined override (cycled) if isfield(cfg.plot,'custom_linetypes') && ~isempty(cfg.plot.custom_linetypes) L = cfg.plot.custom_linetypes; ls = L{ mod(gi-1, numel(L)) + 1 }; end - lbl = buildLabel(grpTbl(gi,:), group_by); - - % Main line (dark) colL = cols_line(gi,:); - h.lines(gi) = plot(xu, yu, ... + lbl = g.label; + + % Main line + h.lines(gi) = plot(ax, xu, yu, ... 'LineWidth', cfg.plot.lineWidth, ... 'Marker', cfg.plot.marker, 'MarkerSize', 3, ... 'Color', colL, 'LineStyle', ls, ... 'DisplayName', char(lbl)); - % Spread (IQR) in line color + % Spread if any(isfinite(ylo)) && any(isfinite(yhi)) - h.err(gi) = errorbar(xu, yu, ylo, yhi, 'LineStyle','none', ... + h.err(gi) = errorbar(ax, xu, yu, ylo, yhi, 'LineStyle','none', ... 'Color', colL, 'CapSize', cfg.plot.capSize, 'HandleVisibility','off'); h.err(gi).LineWidth = cfg.plot.errWidth; end - % Raw kept scatter (light) + % Raw scatter if cfg.show_raw - keep_all = false(size(yi)); - for k = 1:numel(xu) - bin = (iu==k); - yy = yi(bin); - km = outlierMask(yy, cfg, strcmpi(cfg.y_scale,'log')); - if nnz(km) < cfg.min_pts_x, km = true(size(yy)); end - keep_all(bin) = km; - end + % reuse stored raw data (no extra filtering) + xi = g.x_raw; + yi = g.y_raw; colS = cols_scatter(gi,:); - scatter(xi(keep_all), yi(keep_all), cfg.plot.scatterSize, colS, 'filled', ... - 'MarkerFaceAlpha', cfg.plot.scatterAlpha, 'MarkerEdgeAlpha', cfg.plot.scatterAlpha, ... + scatter(ax, xi, yi, cfg.plot.scatterSize, colS, 'filled', ... + 'MarkerFaceAlpha', cfg.plot.scatterAlpha, ... + 'MarkerEdgeAlpha', cfg.plot.scatterAlpha, ... 'HandleVisibility','off'); end - % Precoded overlay (dotted, squares), in line color - if cfg.show_precoded && ~isempty(y_raw_p) && strcmpi(cfg.y_axis,'BER') - ypi = y_raw_p(idx); - ypu = nan(size(xu)); - for k = 1:numel(xu) - bin = (iu==k); - yy = ypi(bin); - yy = yy(isfinite(yy)); - if isempty(yy), continue; end - km = outlierMask(yy, cfg, true); - if nnz(km) < cfg.min_pts_x, km = true(size(yy)); end - yy = yy(km); - if strcmpi(cfg.agg,'median'), ypu(k)=median(yy,'omitnan'); elseif strcmpi(cfg.agg,'mean'), ypu(k)=mean(yy,'omitnan'); elseif strcmpi(cfg.agg,'min'), ypu(k)=min(yy); elseif strcmpi(cfg.agg,'max'), ypu(k)=max(yy); end - end - h.lines_p(gi) = plot(xu, ypu, ... + % Precoded overlay + if cfg.show_precoded && ~isempty(g.y_precoded) && strcmpi(M.y_axis,'BER') + ypu = g.y_precoded; + h.lines_p(gi) = plot(ax, xu, ypu, ... 'LineWidth', max(1.2, cfg.plot.lineWidth-0.2), ... 'Marker', cfg.plot.marker_precoded, 'MarkerSize', 3, ... 'Color', colL, 'LineStyle', ':', ... 'DisplayName', [char(lbl) ' (precoded)']); end - - end -%% ---- Axes / Labels / FEC -ylabel(cfg.y_axis, 'Interpreter','none'); -xlabel(x_label, 'Interpreter','none'); -set(gca, 'YScale', cfg.y_scale, 'FontSize', 11); -% legend('Location', cfg.plot.legendLocation); box on; +%% ---- Axes / Labels / FEC ---- +ylabel(ax, M.y_axis, 'Interpreter','none'); +xlabel(ax, M.x_label, 'Interpreter','none'); +set(ax, 'YScale', cfg.y_scale, 'FontSize', 11); -xticks(floor(xu)); -xlim([min(xu), max(xu)]) +% X ticks/limits using all group x-values +allX = cellfun(@(g) g.x(:), M.group, 'UniformOutput', false); +allX = unique(vertcat(allX{:})); +if ~isempty(allX) + xticks(ax, allX); + xticklabels(cellstr(num2str(round(allX,1), '%.4f'))) + xlim(ax, [min(allX), max(allX)]); +end -if startsWith(cfg.y_axis,"BER",'IgnoreCase',true) +if startsWith(M.y_axis,"BER",'IgnoreCase',true) for v = cfg.fec_lines - yline(v, '--', 'Color', cfg.plot.fecColor, ... + yline(ax, v, '--', 'Color', cfg.plot.fecColor, ... 'LineWidth', cfg.plot.fecLineWidth, 'HandleVisibility','off'); end - ylim([1e-5, 0.5]); - yticks([1e-5, 1e-4, 1e-3, 1e-2, 1e-1]); + ylim(ax, [1e-5, 0.5]); + yticks(ax, [1e-5, 1e-4, 1e-3, 1e-2, 1e-1]); end +% legend(ax, 'Location', cfg.plot.legendLocation); % if you want legends +box(ax,'on'); end % ===== main ===== @@ -263,120 +157,14 @@ for i = 1:numel(fn) if ~isfield(cfg, f) || isempty(cfg.(f)) cfg.(f) = defs.(f); elseif isstruct(defs.(f)) && isstruct(cfg.(f)) - cfg.(f) = filldefaults(cfg.(f), defs.(f)); % recursive for structs + cfg.(f) = filldefaults(cfg.(f), defs.(f)); end end end -function out = tern(cond, a, b) - if cond - out = a; - else - out = b; - end -end - -function T2 = applyFilters(T, filters) -if isempty(filters), T2 = T; return; end -keep = true(height(T),1); -fns = fieldnames(filters); -for i = 1:numel(fns) - name = fns{i}; - if ~ismember(name, T.Properties.VariableNames) - warning('Filter column "%s" not found. Ignored.', name); %#ok<*WNTAG> - continue - end - val = filters.(name); - col = T.(name); - if isa(val,'function_handle') - m = val(col); - if ~islogical(m) || ~isequal(size(m), size(col)) - error('Filter for %s must return logical mask of same size.', name); - end - keep = keep & m; - else - keep = keep & ismember(col, val); - end -end -T2 = T(keep,:); -end - -function [x, label] = computeX(T, whichX) -switch lower(whichX) - case {'symbolrate','baudrate'} - x = T.symbolrate * 1e-9; - label = 'Symbol rate [GBd]'; - case 'bitrate' - if ~ismember('pam_level', T.Properties.VariableNames) - error('bitrate requires "pam_level" column.'); - end - bits = floor(log2(double(T.pam_level))*10)/10; - x = (T.symbolrate .* bits) * 1e-9; - label = 'Grossrate [Gb/s]'; - case 'grossrate' - x = (T.grossrate) * 1e-9; - label = 'Grossrate [Gb/s]'; - otherwise - if ~ismember(whichX, T.Properties.VariableNames) - error('x_axis "%s" not found in table.', whichX); - end - x = T.(whichX); - label = whichX; -end -x = double(x(:)); -end - -function keep = outlierMask(y, cfg, useLog) -if isempty(y), keep = false(size(y)); return; end -y = y(:); -switch lower(cfg.outlier) - case 'none' - keep = true(size(y)); return - case 'mad' - z = tern(useLog, log10(y), y); - med = median(z,'omitnan'); - madv = median(abs(z-med),'omitnan'); - if ~(isfinite(madv) && madv>0) - keep = true(size(y)); return - end - sigma = 1.4826*madv; - zz = tern(useLog, log10(y), y); - keep = abs(zz - med) <= cfg.mad_z*sigma; - case 'pctl' - pr = prctile(y, cfg.pct_limits); - keep = (y >= pr(1)) & (y <= pr(2)); - otherwise - error('Unknown outlier mode "%s".', cfg.outlier); -end -end - -function s = buildLabel(grpRow, group_by) -parts = strings(1, numel(group_by)); -for i = 1:numel(group_by) - key = group_by{i}; - val = grpRow.(key); - if iscell(val), val = val{1}; end - if islogical(val), val = tern(val,'w/','w/o'); end - if key == "equalizer_structure" - key = ''; - val = upper(val); - val = strrep(val,'_',' '); - end - - if key == "pre_emph" - % key = strrep(key,'_','-'); - val = [val, ' pre-emph.']; - key = ''; - end - - parts(i) = sprintf('%s %s', key, string(val)); -end -s = strjoin(parts, ', '); -end - function [cols_line, cols_scatter] = buildGroupColors(nG, plotcfg) -% --- 1) User-provided custom colors ------------------------------- +% 1) User-provided custom colors if isfield(plotcfg,'custom_colors') && ~isempty(plotcfg.custom_colors) C = plotcfg.custom_colors; if size(C,1) < nG @@ -384,7 +172,6 @@ if isfield(plotcfg,'custom_colors') && ~isempty(plotcfg.custom_colors) end cols_line = C(1:nG, :); - % Scatter colors: either user-provided or lightened if isfield(plotcfg,'custom_colors_scatter') && ~isempty(plotcfg.custom_colors_scatter) Cs = plotcfg.custom_colors_scatter; if size(Cs,1) < nG @@ -392,7 +179,6 @@ if isfield(plotcfg,'custom_colors') && ~isempty(plotcfg.custom_colors) end cols_scatter = Cs(1:nG, :); else - % auto-lighten scatter colors cols_scatter = zeros(nG,3); for i = 1:nG cols_scatter(i,:) = lightenColor(cols_line(i,:), 0.40); @@ -401,7 +187,7 @@ if isfield(plotcfg,'custom_colors') && ~isempty(plotcfg.custom_colors) return; end -% --- 2) Standard behavior (using cbrewer2 or fallback) ------------ +% 2) Standard behavior useBrewer = plotcfg.use_cbrewer2 && exist('cbrewer2','file')==2; if useBrewer N = max(2*nG, 12); diff --git a/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/plot_measurements_gpt_old.m b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/plot_measurements_gpt_old.m new file mode 100644 index 0000000..207b4d1 --- /dev/null +++ b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/plot_measurements_gpt_old.m @@ -0,0 +1,436 @@ +function h = plot_measurements_gpt_old(T, cfg) +% Versatile plotting from your DB table (with cbrewer2 'Paired' palette). +% +% Usage: +% h = plot_measurements_flex(dataTable, cfg) + +%% ---- Defaults +if nargin < 2, cfg = struct; end +defaults = struct( ... + 'x_axis' , 'symbolrate', ... + 'y_axis' , 'BER', ... + 'y_scale' , 'auto', ... + 'group_by' , {{'equalizer_structure','pre_emph'}}, ... + 'filters' , struct, ... + 'agg' , 'mean', ... + 'outlier' , 'auto', ... + 'mad_z' , 4, ... + 'pct_limits' , [2.5 97.5], ... + 'min_pts_x' , 3, ... + 'show_raw' , true, ... + 'show_precoded', [], ... + 'show_spread' , 'none', ... + 'fec_lines' , [], ... + 'plot', struct() ... +); +cfg = filldefaults(cfg, defaults); + +% ---- Plot defaults (new) +plotdefs = struct( ... + 'use_cbrewer2' , true, ... + 'colormap' , 'Paired', ... % ColorBrewer 'Paired' + 'paired_dark_first' , true, ... % dark for lines, light for scatter + 'lineWidth' , 1.8, ... + 'errWidth' , 1.0, ... + 'scatterSize' , 14, ... + 'scatterAlpha' , 0.35, ... + 'marker' , 'o', ... + 'marker_precoded' , 's', ... + 'lineStyle_pre_emph_on' , '--', ... + 'lineStyle_pre_emph_off', '-', ... + 'legendLocation' , 'best', ... + 'fecLineWidth' , 2.2, ... % thicker FEC limits + 'fecColor' , [0.25 0.25 0.25], ... + 'capSize' , 6, ... + 'lineStyle_default' , '-', ... + 'use_pre_emph_styling' , true ... +); +cfg.plot = filldefaults(cfg.plot, plotdefs); + +%% ---- Derived/prep columns +if ~ismember('pre_emph', T.Properties.VariableNames) + if ~ismember('db_mode', T.Properties.VariableNames) + error('Missing column "db_mode" for pre_emph derivation.'); + end + T.pre_emph = T.db_mode == 0; +end +if ~ismember(cfg.y_axis, T.Properties.VariableNames) + error('y_axis "%s" not found in table.', cfg.y_axis); +end + +isBER = startsWith(cfg.y_axis, "BER", 'IgnoreCase', true); +if strcmpi(cfg.y_scale,'auto'), cfg.y_scale = tern(isBER, 'log', 'linear'); end +if strcmpi(cfg.outlier,'auto'), cfg.outlier = tern(isBER, 'mad', 'none'); end +if isempty(cfg.show_precoded) + cfg.show_precoded = isBER && ismember('BER_precoded', T.Properties.VariableNames); +end + +%% ---- Filters +T = applyFilters(T, cfg.filters); +[x_raw, x_label] = computeX(T, cfg.x_axis); +y_raw = T.(cfg.y_axis); + +validXY = isfinite(x_raw) & isfinite(y_raw); +T = T(validXY, :); +x_raw = x_raw(validXY); +y_raw = y_raw(validXY); + +if mean(abs(y_raw)) > 1e8 + %giga values + y_raw = y_raw.*1e-9; +end + +if cfg.show_precoded && ismember('BER_precoded', T.Properties.VariableNames) + y_raw_p = T.BER_precoded(validXY); +else + y_raw_p = []; +end + +%% ---- Grouping +group_by = cfg.group_by; +if ~all(ismember(group_by, T.Properties.VariableNames)) + error('Some group_by columns are missing in table.'); +end +[G, grpTbl] = findgroups(T(:, group_by)); +nG = max(G); + +% ==== Colors (cbrewer2 'Paired' with dark/ light pairs) ==== +[cols_line, cols_scatter] = buildGroupColors(nG, cfg.plot); + +%% ---- Axes / Figure handling (new unified logic) + +% Priority: +% 1) cfg.ax → use existing axes (subplots/tiles) +% 2) cfg.figure_number → select/create figure +% 3) fallback: create new figure + +if isfield(cfg,'ax') && ~isempty(cfg.ax) && isgraphics(cfg.ax,'axes') + ax = cfg.ax; % use caller-provided axes + set(gcf,'CurrentAxes',ax); +else + if isfield(cfg,'figure_number') && ~isempty(cfg.figure_number) + figure(cfg.figure_number); + else + figure; + end + ax = gca; % active axes +end + +hold(ax,'on'); +grid(ax,'on'); + + +h.lines = gobjects(nG,1); +h.err = gobjects(nG,1); +h.scat = gobjects(nG,1); +h.lines_p = gobjects(nG,1); + +for gi = 1:nG + idx = (G==gi); + Ti = T(idx,:); + xi = x_raw(idx); + yi = y_raw(idx); + + % Aggregate per unique x + [xu, ia, iu] = unique(xi); + yu = nan(size(xu)); + ylo = nan(size(xu)); + yhi = nan(size(xu)); + + for k = 1:numel(xu) + bin = (iu==k); + yy = yi(bin); + yy = yy(isfinite(yy)); + if isempty(yy), continue; end + km = outlierMask(yy, cfg, strcmpi(cfg.y_scale,'log')); + if nnz(km) < cfg.min_pts_x, km = true(size(yy)); end + yy = yy(km); + + if strcmpi(cfg.agg,'median'), yu(k)=median(yy,'omitnan'); elseif strcmpi(cfg.agg,'mean'), yu(k)=mean(yy,'omitnan'); elseif strcmpi(cfg.agg,'min'), yu(k)=min(yy); elseif strcmpi(cfg.agg,'max'), yu(k)=max(yy); end + if strcmpi(cfg.show_spread,'iqr') + q = prctile(yy,[25 75]); + ylo(k) = max(yu(k)-q(1), eps); + yhi(k) = max(q(2)-yu(k), eps); + elseif strcmpi(cfg.show_spread,'minmax') + ylo(k) = min(yy); + yhi(k) = max(yy); + end + end + + % sort + [xu, ord] = sort(xu); + yu = yu(ord); + ylo = ylo(ord); + yhi = yhi(ord); + + % Styles + % Decide if we style by pre_emph + % --- LINE TYPE SELECTION (no pre-emphasis logic) --- + ls = cfg.plot.lineStyle_default; + + % User-defined override (cycled) + if isfield(cfg.plot,'custom_linetypes') && ~isempty(cfg.plot.custom_linetypes) + L = cfg.plot.custom_linetypes; + ls = L{ mod(gi-1, numel(L)) + 1 }; + end + + lbl = buildLabel(grpTbl(gi,:), group_by); + + % Main line (dark) + colL = cols_line(gi,:); + h.lines(gi) = plot(xu, yu, ... + 'LineWidth', cfg.plot.lineWidth, ... + 'Marker', cfg.plot.marker, 'MarkerSize', 3, ... + 'Color', colL, 'LineStyle', ls, ... + 'DisplayName', char(lbl)); + + % Spread (IQR) in line color + if any(isfinite(ylo)) && any(isfinite(yhi)) + h.err(gi) = errorbar(xu, yu, ylo, yhi, 'LineStyle','none', ... + 'Color', colL, 'CapSize', cfg.plot.capSize, 'HandleVisibility','off'); + h.err(gi).LineWidth = cfg.plot.errWidth; + end + + % Raw kept scatter (light) + if cfg.show_raw + keep_all = false(size(yi)); + for k = 1:numel(xu) + bin = (iu==k); + yy = yi(bin); + km = outlierMask(yy, cfg, strcmpi(cfg.y_scale,'log')); + if nnz(km) < cfg.min_pts_x, km = true(size(yy)); end + keep_all(bin) = km; + end + colS = cols_scatter(gi,:); + scatter(xi(keep_all), yi(keep_all), cfg.plot.scatterSize, colS, 'filled', ... + 'MarkerFaceAlpha', cfg.plot.scatterAlpha, 'MarkerEdgeAlpha', cfg.plot.scatterAlpha, ... + 'HandleVisibility','off'); + end + + % Precoded overlay (dotted, squares), in line color + if cfg.show_precoded && ~isempty(y_raw_p) && strcmpi(cfg.y_axis,'BER') + ypi = y_raw_p(idx); + ypu = nan(size(xu)); + for k = 1:numel(xu) + bin = (iu==k); + yy = ypi(bin); + yy = yy(isfinite(yy)); + if isempty(yy), continue; end + km = outlierMask(yy, cfg, true); + if nnz(km) < cfg.min_pts_x, km = true(size(yy)); end + yy = yy(km); + if strcmpi(cfg.agg,'median'), ypu(k)=median(yy,'omitnan'); elseif strcmpi(cfg.agg,'mean'), ypu(k)=mean(yy,'omitnan'); elseif strcmpi(cfg.agg,'min'), ypu(k)=min(yy); elseif strcmpi(cfg.agg,'max'), ypu(k)=max(yy); end + end + h.lines_p(gi) = plot(xu, ypu, ... + 'LineWidth', max(1.2, cfg.plot.lineWidth-0.2), ... + 'Marker', cfg.plot.marker_precoded, 'MarkerSize', 3, ... + 'Color', colL, 'LineStyle', ':', ... + 'DisplayName', [char(lbl) ' (precoded)']); + end + + +end + +%% ---- Axes / Labels / FEC +ylabel(cfg.y_axis, 'Interpreter','none'); +xlabel(x_label, 'Interpreter','none'); +set(gca, 'YScale', cfg.y_scale, 'FontSize', 11); +% legend('Location', cfg.plot.legendLocation); box on; + +xticks(floor(xu)); +xlim([min(xu), max(xu)]) + +if startsWith(cfg.y_axis,"BER",'IgnoreCase',true) + for v = cfg.fec_lines + yline(v, '--', 'Color', cfg.plot.fecColor, ... + 'LineWidth', cfg.plot.fecLineWidth, 'HandleVisibility','off'); + end + ylim([1e-5, 0.5]); + yticks([1e-5, 1e-4, 1e-3, 1e-2, 1e-1]); +end + + + +end % ===== main ===== + + +%% ===================== Helpers ===================== + +function cfg = filldefaults(cfg, defs) +fn = fieldnames(defs); +for i = 1:numel(fn) + f = fn{i}; + if ~isfield(cfg, f) || isempty(cfg.(f)) + cfg.(f) = defs.(f); + elseif isstruct(defs.(f)) && isstruct(cfg.(f)) + cfg.(f) = filldefaults(cfg.(f), defs.(f)); % recursive for structs + end +end +end + +function out = tern(cond, a, b) + if cond + out = a; + else + out = b; + end +end + +function T2 = applyFilters(T, filters) +if isempty(filters), T2 = T; return; end +keep = true(height(T),1); +fns = fieldnames(filters); +for i = 1:numel(fns) + name = fns{i}; + if ~ismember(name, T.Properties.VariableNames) + warning('Filter column "%s" not found. Ignored.', name); %#ok<*WNTAG> + continue + end + val = filters.(name); + col = T.(name); + if isa(val,'function_handle') + m = val(col); + if ~islogical(m) || ~isequal(size(m), size(col)) + error('Filter for %s must return logical mask of same size.', name); + end + keep = keep & m; + else + keep = keep & ismember(col, val); + end +end +T2 = T(keep,:); +end + +function [x, label] = computeX(T, whichX) +switch lower(whichX) + case {'symbolrate','baudrate'} + x = T.symbolrate * 1e-9; + label = 'Symbol rate [GBd]'; + case 'bitrate' + if ~ismember('pam_level', T.Properties.VariableNames) + error('bitrate requires "pam_level" column.'); + end + bits = floor(log2(double(T.pam_level))*10)/10; + x = (T.symbolrate .* bits) * 1e-9; + label = 'Grossrate [Gb/s]'; + case 'grossrate' + x = (T.grossrate) * 1e-9; + label = 'Grossrate [Gb/s]'; + otherwise + if ~ismember(whichX, T.Properties.VariableNames) + error('x_axis "%s" not found in table.', whichX); + end + x = T.(whichX); + label = whichX; +end +x = double(x(:)); +end + +function keep = outlierMask(y, cfg, useLog) +if isempty(y), keep = false(size(y)); return; end +y = y(:); +switch lower(cfg.outlier) + case 'none' + keep = true(size(y)); return + case 'mad' + z = tern(useLog, log10(y), y); + med = median(z,'omitnan'); + madv = median(abs(z-med),'omitnan'); + if ~(isfinite(madv) && madv>0) + keep = true(size(y)); return + end + sigma = 1.4826*madv; + zz = tern(useLog, log10(y), y); + keep = abs(zz - med) <= cfg.mad_z*sigma; + case 'pctl' + pr = prctile(y, cfg.pct_limits); + keep = (y >= pr(1)) & (y <= pr(2)); + otherwise + error('Unknown outlier mode "%s".', cfg.outlier); +end +end + +function s = buildLabel(grpRow, group_by) +parts = strings(1, numel(group_by)); +for i = 1:numel(group_by) + key = group_by{i}; + val = grpRow.(key); + if iscell(val), val = val{1}; end + if islogical(val), val = tern(val,'w/','w/o'); end + if key == "equalizer_structure" + key = ''; + val = upper(val); + val = strrep(val,'_',' '); + end + + if key == "pre_emph" + % key = strrep(key,'_','-'); + val = [val, ' pre-emph.']; + key = ''; + end + + parts(i) = sprintf('%s %s', key, string(val)); +end +s = strjoin(parts, ', '); +end + +function [cols_line, cols_scatter] = buildGroupColors(nG, plotcfg) + +% --- 1) User-provided custom colors ------------------------------- +if isfield(plotcfg,'custom_colors') && ~isempty(plotcfg.custom_colors) + C = plotcfg.custom_colors; + if size(C,1) < nG + error('custom_colors must have at least nG=%d rows.', nG); + end + cols_line = C(1:nG, :); + + % Scatter colors: either user-provided or lightened + if isfield(plotcfg,'custom_colors_scatter') && ~isempty(plotcfg.custom_colors_scatter) + Cs = plotcfg.custom_colors_scatter; + if size(Cs,1) < nG + error('custom_colors_scatter must have at least nG=%d rows.', nG); + end + cols_scatter = Cs(1:nG, :); + else + % auto-lighten scatter colors + cols_scatter = zeros(nG,3); + for i = 1:nG + cols_scatter(i,:) = lightenColor(cols_line(i,:), 0.40); + end + end + return; +end + +% --- 2) Standard behavior (using cbrewer2 or fallback) ------------ +useBrewer = plotcfg.use_cbrewer2 && exist('cbrewer2','file')==2; +if useBrewer + N = max(2*nG, 12); + C = cbrewer2(plotcfg.colormap, N); + cols_line = zeros(nG,3); + cols_scatter = zeros(nG,3); + for i = 1:nG + if plotcfg.paired_dark_first + dark = C(2*i-1, :); + light = C(2*i, :); + else + light = C(2*i-1, :); + dark = C(2*i, :); + end + cols_line(i,:) = dark; + cols_scatter(i,:) = light; + end +else + C = lines(max(nG,7)); + cols_line = C(1:nG,:); + cols_scatter = zeros(nG,3); + for i = 1:nG + cols_scatter(i,:) = lightenColor(cols_line(i,:), 0.50); + end +end + +end + +function c2 = lightenColor(c, fracTowardWhite) +c = c(:).'; +c2 = (1-fracTowardWhite)*c + fracTowardWhite*1; +end diff --git a/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/plot_rates.m b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/plot_rates.m deleted file mode 100644 index 29b09b5..0000000 --- a/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/plot_rates.m +++ /dev/null @@ -1,34 +0,0 @@ - -path = "C:\Users\Silas\Documents\MATLAB\imdd_simulation\projects\HighSpeedExperiment_2024\Auswertung_JLT\final\rates.csv"; - -%% === Read CSV into a table === -T = readtable(path, 'Delimiter', ';', 'DecimalSeparator', ','); - -%% === Column definitions === -x = T.X_Werte; -pam_cols = {'PAM_2','PAM_4','PAM_6','PAM_8','PAM_12'}; -titles = {'PAM-2','PAM-4','PAM-6','PAM-8','PAM-12'}; - -% === Create subplots === -figure;hold on -c = linspecer(6); -for k = 1:numel(pam_cols) - - y = T.(pam_cols{k}); - valid = ~isnan(y); - - - % Scatter plot - s = scatter(x(valid), y(valid), 25, 'filled','MarkerEdgeColor',c(k,:),'MarkerFaceColor',c(k,:),'DisplayName',titles{k}); - - % Fit (2nd-order polynomial) - p = polyfit(x(valid), y(valid), 2); - xfit = linspace(min(x(valid)), max(x(valid)), 200); - yfit = polyval(p, xfit); - - % Plot fit curve - plot(xfit, yfit, 'LineWidth', 1,'linestyle',':','Color',c(k,:),'HandleVisibility','off'); - - xlabel('baud rate [GBd]'); - ylabel('net rate [Gb/s]'); -end \ No newline at end of file diff --git a/projects/HighSpeedExperiment_2024/Auswertung_JLT/run_dsp_from_db.m b/projects/HighSpeedExperiment_2024/Auswertung_JLT/run_dsp_from_db.m index b5fdd4a..8f96ba2 100644 --- a/projects/HighSpeedExperiment_2024/Auswertung_JLT/run_dsp_from_db.m +++ b/projects/HighSpeedExperiment_2024/Auswertung_JLT/run_dsp_from_db.m @@ -1,6 +1,6 @@ % === SETTINGS === -dsp_options.append_to_db = 0; -dsp_options.max_occurences = 5; +dsp_options.append_to_db = 1; +dsp_options.max_occurences = 1; experiment = "highspeed_2024"; dsp_options.mode = "load_run_id"; % 'simulate' & 'load_files' @@ -40,25 +40,25 @@ end fp = QueryFilter(); % fp.where('Runs', 'run_id','EQUALS', 2776); -M = 4; +M = 6; fp.where('Runs', 'pam_level','EQUALS', M); -fp.where('Runs', 'bitrate','EQUALS', 390e9);%360,390 +% fp.where('Runs', 'bitrate','EQUALS', 390e9);%360,390 % fp.where('Runs', 'symbolrate','EQUALS', 195e9); -fp.where('Runs', 'fiber_length','EQUALS', 2); -% fp.where('Runs', 'is_mpi','EQUALS', 0); +fp.where('Runs', 'fiber_length','EQUALS', 10); +fp.where('Runs', 'is_mpi','EQUALS', 0); % fp.where('Runs', 'interference_path_length','EQUALS', 1000); % fp.where('Runs', 'loop_id','GREATER_THAN', 11); % fp.where('Runs', 'sir','EQUALS',18); -fp.where('Runs', 'wavelength','EQUALS', 1310); +% fp.where('Runs', 'wavelength','EQUALS', 1310); fp.where('Runs', 'db_mode','EQUALS', 0); fp.where('Runs', 'rop_attenuation','EQUAL', 0); -% fp.where('Runs', 'power_pd_in','GREATER_THAN', 7); +% fp.where('Runs', 'power_pd_in','LESS_THAN', 7); [dataTable,~] = db.queryDB(fp, db.getTableFieldNames('Runs')); % === Set LOOPS & Initialize DataStorage === dsp_options.parameters = struct(); -% dsp_options.parameters.pf_ncoeffs = [1,2];%[0,logspace(-4,0,10)]; +% dsp_options.parameters.pf_ncoeffs = [1,2];%s[0,logspace(-4,0,10)]; wh = DataStorage(dsp_options.parameters); wh.addStorage("ffe_package"); @@ -70,10 +70,7 @@ wh.addStorage("mlmlse_package"); %% === RUN IT === -[results,wh] = submitJobs(dataTable.run_id(:), dsp_options, "serial", 'wh', wh, 'waitbar', true); - - - +[results,wh] = submitJobs(dataTable.run_id(:), dsp_options, "parallel", 'wh', wh, 'waitbar', true); diff --git a/projects/HighSpeedExperiment_2024/a_minimal_example.m b/projects/HighSpeedExperiment_2024/a_minimal_example.m new file mode 100644 index 0000000..de85571 --- /dev/null +++ b/projects/HighSpeedExperiment_2024/a_minimal_example.m @@ -0,0 +1,118 @@ + + +dsp_options.storage_path = 'Z:\2024\sioe_labor\'; +dsp_options.max_occurences = 1; +db = DBHandler("dataBase", 'labor_highspeed', "type", 'mysql' ); + +fp = QueryFilter(); + +fp.where('Runs','fiber_length','EQUALS', 2); +fp.where('Runs','wavelength','EQUALS', 1310); +fp.where('Runs','bitrate','EQUALS', 300e9); +fp.where('Runs','pam_level','EQUALS', 4); +fp.where('Runs','rop_attenuation','EQUALS', 0); +fp.where('Runs','is_mpi','EQUALS', 0); +fp.where('Runs', 'db_mode','EQUALS', 0); +fields = db.getTableFieldNames('Runs'); +[dataTable,~] = db.queryDB(fp, fields); + + +fsym = dataTable.symbolrate; +M = double(dataTable.pam_level); +duob_mode = db_mode(strrep(dataTable.db_mode,'"','')); + + +% Load and Sync signal data from DB +[Tx_bits, Symbols, Scpe_cell, ~] = loadAndSyncSignalDataFromDb(dataTable, dsp_options); + +% Preprocess signal +Scpe_sig = preprocessSignal(Scpe_cell{1}, Symbols, fsym); + +% Show spectrum +Scpe_sig.spectrum("fignum",1,"displayname",'Rx') + + + + + + +%% simple FFE + +mu_ffe = [0.0001, 0.0008, 0.001]; +mu_dfe = 0.0004; +ffe_order = [50, 0, 0]; +eq_dfe = EQ("Ne",ffe_order,"Nb",[0,0,0],"training_length",4096,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.005,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",0); + +ffe_results = ffe(eq_dfe,M,Scpe_sig,Symbols,Tx_bits,... + "precode_mode",duob_mode,... + 'showAnalysis',0,... + "postFFE",[],... + "eth_style_symbol_mapping",0); + + +ffe_results.metrics.print("description",'FFE'); +ffe_results.config.equalizer_structure = "ffe"; + +%% a) VNLE // b) concatenated VNLE + MLSE + +pf_ncoeffs = 1; +ffe_order = [50, 5, 5]; +dfe_order = [0,0,0]; +eq_ = EQ("Ne",ffe_order,"Nb",dfe_order,"training_length",4096,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.005,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",0); +pf_ = Postfilter("ncoeff",pf_ncoeffs,"useBurg",1); + + + +if duob_mode == db_mode.no_db && M == 6 %only for PAM-6 and no duobinary precoding, otherwise leads to false sequence estimation + trellexlusion = 1; +else + trellexlusion = 0; +end + +%state_mode 3 -> stat lvl; state_mode 2 -> use target lvls +%scale_mode 2 -> mmse adaption + +mlse_ = MLSE("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels,'scale_mode',2,'trellis_exclusion',trellexlusion,'trellis_state_mode',2); + +[vnle_results, mlse_results] = vnle_postfilter_mlse(eq_, pf_, mlse_, M, Scpe_sig, Symbols, Tx_bits, ... + "precode_mode", duob_mode,... + 'showAnalysis', 0, ... + "postFFE", [],... + "eth_style_symbol_mapping", 0); + +vnle_results.metrics.print("description",'VNLE'); +mlse_results.metrics.print("description",'VNLE + PF + MLSE'); + + +%% Duobinary Equalization + + +if duob_mode == db_mode.no_db && M == 6 %only for PAM-6 and no duobinary precoding, otherwise leads to false sequence estimation + trellexlusion = 1; +else + trellexlusion = 0; +end +mlse_db_ = MLSE("DIR",[1,1],"duobinary_output",0,"M",M,"trellis_states",PAMmapper(M,0).levels,'scale_mode',2,'trellis_exclusion',trellexlusion,'trellis_state_mode',3); + +ffe_order = [50, 5, 5]; +dfe_order = [0,0,0]; +eq_ = EQ("Ne",ffe_order,"Nb",dfe_order,"training_length",4096,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.005,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1); + +dbt_results = duobinary_target(eq_, mlse_db_, M, Scpe_sig, Symbols, Tx_bits, ... + "precode_mode", duob_mode, ... + 'showAnalysis', 0,... + "postFFE", []); + +dbt_results.metrics.print("description",'Duobinary EQ'); + +%% Ml based Viterbi + +%ML-based MLSE (L=2) +mu_ml = 0.01; training_epochs = 100; +ml_mlse_equalizer = ML_MLSE("epochs_tr",training_epochs,"epochs_dd",1, ... + "len_tr",length(Scpe_sig),"mu_dd",mu_ml,"mu_tr",mu_ml,"order",11,"sps",2, ... + "traceback_depth",128,"L",1,"delta",4,"adaptive_mu",0); + +[ml_mlse_results] = ml_mlse(ml_mlse_equalizer, M, Scpe_sig, Symbols, Tx_bits,"precode_mode",duob_mode); + +ml_mlse_results.metrics.print("description",'ML pre Eq. + Viterbi') \ No newline at end of file diff --git a/projects/HighSpeedExperiment_2024/auswertung/only_show_precomp.m b/projects/HighSpeedExperiment_2024/auswertung/only_show_precomp.m index db72ac3..7fe1e7d 100644 --- a/projects/HighSpeedExperiment_2024/auswertung/only_show_precomp.m +++ b/projects/HighSpeedExperiment_2024/auswertung/only_show_precomp.m @@ -8,84 +8,115 @@ db_coding_approach = 0; fsym = 160e9; fdac = 256e9; random_key = 0; -M = 4; +pams = [4]; -if (db_precode==1)&&(db_coding_approach==0) +cols = cbrewer2('Paired',6); +for i = 1:length(pams) + M = pams(i); + if (db_precode==1)&&(db_coding_approach==0) - if M == 4 - pulsef=1; - precomp_amp_max = -50; - elseif M == 6 - pulsef=0; - precomp_amp_max = -50; - elseif M == 8 - pulsef=0; - precomp_amp_max = -50; + if M == 4 + pulsef=1; + precomp_amp_max = -50; + fsym = 196e9; + elseif M == 6 + pulsef=0; + precomp_amp_max = -50; + fsym = 180e9; + elseif M == 8 + pulsef=0; + precomp_amp_max = -50; + fsym = 160e9; + end + + elseif (db_precode==1)&&(db_coding_approach==1) + + if M == 4 + pulsef=1; + precomp_amp_max = -38; + pulsef = 1; + elseif M == 6 + pulsef=0; + precomp_amp_max = -38; + pulsef = 1; + elseif M == 8 + pulsef=0; + precomp_amp_max = -38; + pulsef = 1; + end + + elseif (db_precode==0)&&(db_coding_approach==0) + + if M == 4 + pulsef=1; + precomp_amp_max = -37; + pulsef = 1; + fsym = 196e9; + elseif M == 6 + pulsef=0; + precomp_amp_max = -34; + pulsef = 1; + fsym = 180e9; + elseif M == 8 + pulsef=0; + precomp_amp_max = -34; + pulsef = 0; + fsym = 160e9; + end end -elseif (db_precode==1)&&(db_coding_approach==1) - if M == 4 - pulsef=1; - precomp_amp_max = -38; - pulsef = 1; - elseif M == 6 - pulsef=0; - precomp_amp_max = -38; - pulsef = 1; - elseif M == 8 - pulsef=0; - precomp_amp_max = -38; - pulsef = 1; + rcalpha = 0.05; + Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rrc","pulselength",16,"alpha",rcalpha); + + Pamsource = PAMsource(... + "fsym",fsym,"M",M,"order",19,"useprbs",0,... + "fs_out",fdac,... + "applyclipping",0,"clipfactor",1.2,... + "applypulseform",pulsef,"pulseformer",Pform,... + "randkey",random_key,... + "db_precode",db_precode,"db_encode",db_coding_approach,... + "mrds_code",0,"mrds_blocklength",512); + + [Digi_sig,Symbols,Bits] = Pamsource.process(); + + Digi_sig = Digi_sig.normalize("mode","rms"); + + precomp_est = ChannelFreqResp("Nacq",2048,"Navg",100,"Ncp",63,'f_ref',Digi_sig.fs); + + % maxampdb = [-30:-3:-50,precomp_amp_max]; + maxampdb = precomp_amp_max;%sort(maxampdb); + cols_ = cbrewer2('spectral',15); + + for j = 1:length(maxampdb) + + if maxampdb(j) == precomp_amp_max + color=clr.Set1.green; + else + color=cols_(j,:); + end + + Digi_sig_pre = precomp_est.precomp(Digi_sig,'maxampdb',maxampdb(j),'loadPath',precomp_path,'fileName',precomp_fn); + + % Digi_sig_pre = Digi_sig_pre.normalize("mode","rms"); + + Digi_sig_pre = Digi_sig_pre.resample("fs_out",fdac); + + Digi_sig_pre= Digi_sig_pre.normalize("mode","rms"); + + Digi_sig_pre.spectrum("displayname","Strong Precomp","fignum",2223,"normalizeToNyquist",0,"normalizeTo0dB",0,"color",color,"linestyle",'-','addDCoffset',27); + end -elseif (db_precode==0)&&(db_coding_approach==0) + Digi_sig.spectrum("displayname","No Precomp","fignum",2223,"normalizeToNyquist",0,"normalizeTo0dB",0,"color",cols(2*i,:),"linestyle",'-','addDCoffset',27); - if M == 4 - pulsef=1; - precomp_amp_max = -37; - pulsef = 1; - elseif M == 6 - pulsef=0; - precomp_amp_max = -34; - pulsef = 1; - elseif M == 8 - pulsef=0; - precomp_amp_max = -34; - pulsef = 0; - end end +ylim([-25,10]); +xlim([0,105]); +xticks(0:20:110); +yticks(-30:10:10); -rcalpha = 0.05; -Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rrc","pulselength",16,"alpha",rcalpha); - -Pamsource = PAMsource(... - "fsym",fsym,"M",M,"order",19,"useprbs",0,... - "fs_out",fdac,... - "applyclipping",0,"clipfactor",1.2,... - "applypulseform",pulsef,"pulseformer",Pform,... - "randkey",random_key,... - "db_precode",db_precode,"db_encode",db_coding_approach,... - "mrds_code",0,"mrds_blocklength",512); - -[Digi_sig,Symbols,Bits] = Pamsource.process(); - -Digi_sig = Digi_sig.normalize("mode","rms"); - -Digi_sig.spectrum("displayname","No Precomp","fignum",2223,"normalizeToNyquist",0,"normalizeTo0dB",0); - -precomp_est = ChannelFreqResp("Nacq",2048,"Navg",100,"Ncp",63,'f_ref',Digi_sig.fs); - -Digi_sig = precomp_est.precomp(Digi_sig,'maxampdb',precomp_amp_max,'loadPath',precomp_path,'fileName',precomp_fn); - -Digi_sig = Digi_sig.normalize("mode","rms"); - -Digi_sig = Digi_sig.resample("fs_out",fdac); - -Digi_sig= Digi_sig.normalize("mode","rms"); - -Digi_sig.spectrum("displayname","Strong Precomp","fignum",2223,"normalizeToNyquist",0,"normalizeTo0dB",0); - -ylim([-30,3]); -xlim([-5,100]); \ No newline at end of file +fig = gcf; +pos = [536.3333 879 450 222]; +set(fig, 'Position', pos); \ No newline at end of file diff --git a/projects/HighSpeedExperiment_2024/bias_evaluation.m b/projects/HighSpeedExperiment_2024/bias_evaluation.m index 43e5b7e..c042156 100644 --- a/projects/HighSpeedExperiment_2024/bias_evaluation.m +++ b/projects/HighSpeedExperiment_2024/bias_evaluation.m @@ -30,7 +30,7 @@ for l = 1:numel(lambda_vals) for m = 1:numel(M_vals) ber_ffe = wh.getStoValue('ber_ffe',v_bias_vals,awg_vpp_vals(1),precomp_amp_max_vals(1),rop_atten_vals(1),M_vals(m),lambda_vals(l)); - ber = wh.getStoValue('ber_collect',v_bias_vals,awg_vpp_vals(1),precomp_amp_max_vals(1),rop_atten_vals(1),M_vals(m),lambda_vals(l)); + ber = wh.getStoValue('ber_ffe',v_bias_vals,awg_vpp_vals(1),precomp_amp_max_vals(1),rop_atten_vals(1),M_vals(m),lambda_vals(l)); exfo = wh.getStoValue('exfo',v_bias_vals,awg_vpp_vals(1),precomp_amp_max_vals(1),rop_atten_vals(1),M_vals(m),lambda_vals(l)); lb = wh.getStoValue('exfo',v_bias_vals,awg_vpp_vals(1),precomp_amp_max_vals(1),rop_atten_vals(1),M_vals(m),lambda_vals(l)); diff --git a/projects/IMDD_base_system/simulation_bwl_2.m b/projects/IMDD_base_system/simulation_bwl_2.m index 27a71cb..dec8036 100644 --- a/projects/IMDD_base_system/simulation_bwl_2.m +++ b/projects/IMDD_base_system/simulation_bwl_2.m @@ -18,14 +18,14 @@ u_pi = 2.9; vbias = -vbias_rel*u_pi; laser_wavelength = 1310; laser_linewidth = 0; -tx_bw_nyquist = 0.7; +tx_bw_nyquist = 1; % Channel link_length = 1; % RX -rop = -8; -rx_bw_nyquist = 0.7; +rop = 0; +rx_bw_nyquist = 0.99; vnle_order1 = 50; vnle_order2 = 3; @@ -59,7 +59,7 @@ Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rc","pulselength",1 db_precode = 0; db_encode = 0; -duob_mode = db_mode.no_db; +duob_mode = db_mode.db_precoded; apply_pulsef = 1; [Digi_sig,Symbols,Tx_bits] = PAMsource(... "fsym",fsym,"M",M,"order",18,"useprbs",0,... @@ -67,12 +67,21 @@ apply_pulsef = 1; "applyclipping",0,"clipfactor",1.5,... "applypulseform",apply_pulsef,"pulseformer",Pform,... "randkey",random_key,... - "db_precode",db_precode,"db_encode",db_encode,... "mrds_code",0,"mrds_blocklength",512,"duobinary_mode",duob_mode).process(); Digi_sig.spectrum("displayname",'Digi Spectrum','fignum',10,'normalizeTo0dB',1); +%% proof of concept +Symbols_db = Duobinary().encode(Symbols); +mim_decoded = Duobinary().decode(Symbols_db,"M",M); +rx_bits_mim_decoded = PAMmapper(M,0,"eth_style",0).demap(mim_decoded); +rx_bits_mim_decoded_.signal = circshift(rx_bits_mim_decoded.signal,0); +[~,~,ber_mim_decode,~] = calc_ber(rx_bits_mim_decoded_.signal,Tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1); +fprintf('BER mim: %.2e \n',ber_mim_decode); + +%% + %%%%% AWG % El_sig = M8199A("kover",kover).process(Digi_sig); @@ -127,14 +136,57 @@ pf_ = Postfilter("ncoeff",pf_ncoeffs,"useBurg",1); % mlse_ = MLSE_viterbi("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels); mlse_ = MLSE("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels); -% FFE or VNLE -[eq_signal_sd, eq_noise] = eq_.process(Scpe_cell{1}, Symbols); +if duob_mode == db_mode.no_db -% Hard decision on VNLE output -eq_signal_hd = PAMmapper(M, 0).quantize(eq_signal_sd); + % FFE or VNLE + [eq_signal_sd, eq_noise] = eq_.process(Scpe_cell{1}, Symbols); + + % Hard decision on VNLE output + eq_signal_hd = PAMmapper(M, 0).quantize(eq_signal_sd); + + % Process through postfilter and MLSE + [mlse_sig_sd,whitened_noise] = pf_.process(eq_signal_sd, eq_noise); + mlse_.DIR = pf_.coefficients; + mlse_sig_sd = mlse_.process(mlse_sig_sd,Symbols); + + + % BER + rx_bits = PAMmapper(M,0,"eth_style",0).demap(eq_signal_hd); + [~,tot_err,ber_vnle,a] = calc_ber(rx_bits.signal,Tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1); + + rx_bits = PAMmapper(M,0,"eth_style",0).demap(mlse_sig_sd); + [~,tot_err,ber_mlse,a] = calc_ber(rx_bits.signal,Tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1); -% Process through postfilter and MLSE -[mlse_sig_sd,whitened_noise] = pf_.process(eq_signal_sd, eq_noise); -mlse_.DIR = pf_.coefficients; -mlse_sig_sd = mlse_.process(mlse_sig_sd,Symbols); -mlse_sig_hd = PAMmapper(M, 0, "eth_style", 0).quantize(mlse_sig_sd); +elseif duob_mode == db_mode.db_precoded + + %% + [EQ_sig, Noi] = eq_.process(Scpe_cell{1},Duobinary().encode(Symbols)); + + showLevelHistogram(EQ_sig,Duobinary().encode(Symbols),"displayname",101); + + mim_decoded = Duobinary().decode(EQ_sig,"M",M); + + showLevelHistogram(mim_decoded,Symbols,"displayname",101); + + rx_bits_mim_decoded = PAMmapper(M,0,"eth_style",0).demap(mim_decoded); + + rx_bits_mim_decoded_.signal = circshift(rx_bits_mim_decoded.signal,0); + + [~,~,ber_mim_decode,~] = calc_ber(rx_bits_mim_decoded_.signal,Tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1); + + fprintf('BER mim: %.2e \n',ber_mim_decode); + + %% + mlse_sig_hd = MLSE("DIR",[1,1],"duobinary_output",1,"M",M,"trellis_states",PAMmapper(M,0).levels).process(EQ_sig,Symbols); + + mlse_sig_hd_decoded = Duobinary().encode(mlse_sig_hd,"M",M); + + mlse_sig_hd_decoded = Duobinary().decode(mlse_sig_hd_decoded,"M",M); + + rx_bits_mlse_decoded = PAMmapper(M,0,"eth_style",0).demap(mlse_sig_hd_decoded); + + [~,errors_db_diff_precoded,ber_db_diff_precoded,a] = calc_ber(rx_bits_mlse_decoded.signal,Tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1); + + %% + +end \ No newline at end of file diff --git a/projects/ML_based_MLSE/experimental_data.m b/projects/ML_based_MLSE/experimental_data.m index 6543e9f..a594a92 100644 --- a/projects/ML_based_MLSE/experimental_data.m +++ b/projects/ML_based_MLSE/experimental_data.m @@ -35,8 +35,9 @@ mlse_ = MLSE("DIR",[1,1],"duobinary_output",0,"M",M,"trellis_states",PAMmapper(M db_ref_sequence = Duobinary().encode(Symbols); db_ref_constellation = unique(db_ref_sequence.signal); [eq_signal, eq_noise] = eq_.process(Scpe_sig,db_ref_sequence); + %% -if 0 +if 1 [mlse_sig_sd,LLR,GMI_MLSE] = mlse_.process(eq_signal,Symbols); else % Ml MLSE diff --git a/projects/WDM/WDM_model.m b/projects/WDM/WDM_model.m index c72a985..0d7cbe2 100644 --- a/projects/WDM/WDM_model.m +++ b/projects/WDM/WDM_model.m @@ -142,7 +142,7 @@ for realiz = 1:s.num_realiz Opt_sig_wdm_demux = Optical_Demultiplex("attenuation",0,"B",200e9,"filtype",1,"fs_out",Opt_sig_wdm_rx.fs/upsample_pow,"fs_in",Opt_sig_wdm_rx.fs,"lambda_center",1310).process(Opt_sig_wdm_rx); PD_cell = {}; - parfor l = 1:N + for l = 1:N %%%%%% PD Square Law %%%%%% assert(fdac*kover==Opt_sig_wdm_demux{l}.fs,'Sampling Frequencies do not match! Check previous steps');