Add new minimal example (+ a ton of other, not so important, changes)
This commit is contained in:
@@ -347,8 +347,10 @@ classdef Signal
|
|||||||
options.fignum = 2025
|
options.fignum = 2025
|
||||||
options.displayname = "";
|
options.displayname = "";
|
||||||
options.color = [];
|
options.color = [];
|
||||||
|
options.linestyle = '-';
|
||||||
options.normalizeToNyquist = 0;
|
options.normalizeToNyquist = 0;
|
||||||
options.addDCoffset = 0;
|
options.addDCoffset = 0;
|
||||||
|
options.normalizeToDC = 0;
|
||||||
options.normalizeTo0dB = 0;
|
options.normalizeTo0dB = 0;
|
||||||
options.max_num_lines = []; % Leave empty or omit to disable line rotation
|
options.max_num_lines = []; % Leave empty or omit to disable line rotation
|
||||||
options.fft_length = [];
|
options.fft_length = [];
|
||||||
@@ -361,6 +363,8 @@ classdef Signal
|
|||||||
options.fft_length = 2^(nextpow2(length(obj.signal))-9);
|
options.fft_length = 2^(nextpow2(length(obj.signal))-9);
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if options.normalizeToNyquist == 0
|
if options.normalizeToNyquist == 0
|
||||||
[p_lin,f_Hz] = pwelch(obj.signal, hanning(options.fft_length), ...
|
[p_lin,f_Hz] = pwelch(obj.signal, hanning(options.fft_length), ...
|
||||||
options.fft_length/2, 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.
|
% We'll keep f_rad for the x-axis in that mode.
|
||||||
end
|
end
|
||||||
|
|
||||||
|
% p_lin = movmean(p_lin,4);
|
||||||
|
|
||||||
if options.normalizeTo0dB
|
if options.normalizeTo0dB
|
||||||
p_lin = p_lin ./ max(p_lin);
|
p_lin = p_lin ./ max(p_lin);
|
||||||
p_dbm = 10*log10(p_lin); % normalized to 0 dB
|
p_dbm = 10*log10(p_lin); % normalized to 0 dB
|
||||||
@@ -418,11 +424,18 @@ classdef Signal
|
|||||||
|
|
||||||
p_dbm = p_dbm+options.addDCoffset;
|
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))
|
for s = 1:min(size(p_dbm))
|
||||||
if isempty(options.color)
|
if isempty(options.color)
|
||||||
plot(x_vec, p_dbm(:,s), 'DisplayName', options.displayname, 'LineWidth', 1);
|
plot(x_vec, p_dbm(:,s), 'DisplayName', options.displayname, 'LineWidth', 1);
|
||||||
else
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -968,8 +981,8 @@ classdef Signal
|
|||||||
maxA = max(sig(100:end-100))*1.3;
|
maxA = max(sig(100:end-100))*1.3;
|
||||||
minA = min(sig(100:end-100))*1.3;
|
minA = min(sig(100:end-100))*1.3;
|
||||||
|
|
||||||
% maxA = 0.0025;
|
maxA = 0.12;
|
||||||
% minA = 0;
|
minA = -0.08;
|
||||||
|
|
||||||
difference= maxA-minA;
|
difference= maxA-minA;
|
||||||
|
|
||||||
|
|||||||
@@ -139,6 +139,8 @@ classdef ChannelFreqResp < handle
|
|||||||
fnew = linspace(0,fstarget/2,length(Target)/2+1);
|
fnew = linspace(0,fstarget/2,length(Target)/2+1);
|
||||||
fnew = fnew(2:end-1);
|
fnew = fnew(2:end-1);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
% Old frequency axis (should be much coarser)
|
% 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
|
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
|
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)
|
% 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');
|
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
|
% set all NaN values to the fist/ last non-NaN value
|
||||||
nH = find(~isnan(iH),1,'first');
|
nH = find(~isnan(iH),1,'first');
|
||||||
iH(1:nH)=iH(nH);
|
iH(1:nH)=iH(nH);
|
||||||
@@ -171,6 +177,8 @@ classdef ChannelFreqResp < handle
|
|||||||
% five frequencies -> should be the vaue at f=0=DC component?
|
% five frequencies -> should be the vaue at f=0=DC component?
|
||||||
iH = iH./mean(abs(iH)); %why 1:5??
|
iH = iH./mean(abs(iH)); %why 1:5??
|
||||||
|
|
||||||
|
dc = 20*log10(abs(mean(abs(iH(1:5)))));
|
||||||
|
|
||||||
% set maximum amplification
|
% set maximum amplification
|
||||||
% set als values higher than hmax to hmax and keep the
|
% set als values higher than hmax to hmax and keep the
|
||||||
% phase information by multiplication with respective
|
% phase information by multiplication with respective
|
||||||
|
|||||||
@@ -164,8 +164,8 @@ classdef ML_MLSE < handle
|
|||||||
% EQUALIZE
|
% EQUALIZE
|
||||||
% ==============================================================
|
% ==============================================================
|
||||||
function [y,y_ref] = equalize(obj,x,d,mu,epochs,N,training)
|
function [y,y_ref] = equalize(obj,x,d,mu,epochs,N,training)
|
||||||
debug = 1;
|
debug = 0;
|
||||||
showPlots = 1;
|
showPlots = 0;
|
||||||
y = zeros(N,1);
|
y = zeros(N,1);
|
||||||
nSymbols = ceil(N/obj.sps);
|
nSymbols = ceil(N/obj.sps);
|
||||||
|
|
||||||
|
|||||||
@@ -71,16 +71,22 @@ classdef Metricstruct
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function print(obj)
|
function print(obj,options)
|
||||||
% Print method to display key metrics in a formatted way
|
% Print method to display key metrics in a formatted way
|
||||||
|
arguments
|
||||||
|
obj
|
||||||
|
options.description = '';
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
% Define the width for formatting
|
% Define the width for formatting
|
||||||
nameWidth = 15; % Width for parameter names
|
nameWidth = 15; % Width for parameter names
|
||||||
valueWidth = 12; % Width for values
|
valueWidth = 12; % Width for values
|
||||||
|
|
||||||
% Print header
|
% Print header
|
||||||
|
|
||||||
fprintf('\n%s\n', repmat('=', 1, nameWidth + valueWidth));
|
fprintf('\n%s\n', repmat('=', 1, nameWidth + valueWidth));
|
||||||
fprintf(' Results \n');
|
fprintf([char(options.description),' Results \n']);
|
||||||
fprintf('%s\n', repmat('=', 1, nameWidth + valueWidth));
|
fprintf('%s\n', repmat('=', 1, nameWidth + valueWidth));
|
||||||
|
|
||||||
% Function to format numbers with appropriate precision
|
% Function to format numbers with appropriate precision
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ height = 200;
|
|||||||
plotJob.Position = [100 100 width 100+height];
|
plotJob.Position = [100 100 width 100+height];
|
||||||
cols = cbrewer2("paired",12);
|
cols = cbrewer2("paired",12);
|
||||||
plotJob.color = cols(1,:);
|
plotJob.color = cols(1,:);
|
||||||
plotJob.l = 2;
|
plotJob.l = 10;
|
||||||
plotJob.ch = 16;
|
plotJob.ch = 16;
|
||||||
plotJob.d = 0;
|
plotJob.d = 0;
|
||||||
plotJob.sgm = 0;
|
plotJob.sgm = 0;
|
||||||
@@ -30,7 +30,7 @@ plotJob.p_in = 3;
|
|||||||
plotJob.gamma = 0.0023;
|
plotJob.gamma = 0.0023;
|
||||||
plotJob.pmd = 0.1;
|
plotJob.pmd = 0.1;
|
||||||
plotJob.channelspacing = 400e9;
|
plotJob.channelspacing = 400e9;
|
||||||
plotJob.randzdw = 0;
|
plotJob.randzdw = 1;
|
||||||
|
|
||||||
|
|
||||||
plotJob.plot_ber_curve = 0;
|
plotJob.plot_ber_curve = 0;
|
||||||
@@ -52,7 +52,7 @@ plotJob.yAxisLabel = 'BER';
|
|||||||
|
|
||||||
% createbercurves(wh,plotJob)
|
% createbercurves(wh,plotJob)
|
||||||
|
|
||||||
P = [3,6];
|
P = [3];
|
||||||
for i = 1:2
|
for i = 1:2
|
||||||
plotJob.p_in = P(i);
|
plotJob.p_in = P(i);
|
||||||
createviolinplots(wh,plotJob);
|
createviolinplots(wh,plotJob);
|
||||||
@@ -234,8 +234,8 @@ Title = ["Co Pol.","Link Segmentation","Paired Pol. Interl.","Alternating Pol. I
|
|||||||
D = [0,3,0,0];
|
D = [0,3,0,0];
|
||||||
Sgm = [0,1,0,0];
|
Sgm = [0,1,0,0];
|
||||||
|
|
||||||
colidx = [3];
|
colidx = [4];
|
||||||
Len = [10];
|
Len = plotJob.l;
|
||||||
|
|
||||||
fig = findall(groot, 'Type', 'figure', 'Name', plotJob.figName);
|
fig = findall(groot, 'Type', 'figure', 'Name', plotJob.figName);
|
||||||
if isvalid(fig)
|
if isvalid(fig)
|
||||||
|
|||||||
@@ -95,11 +95,11 @@ try
|
|||||||
adaption= 1;
|
adaption= 1;
|
||||||
use_dd_mode = 1;
|
use_dd_mode = 1;
|
||||||
|
|
||||||
use_ffe = 1;
|
use_ffe = 0;
|
||||||
use_dfe = 1;
|
use_dfe = 0;
|
||||||
use_vnle_mlse = 1;
|
use_vnle_mlse = 0;
|
||||||
use_dbtgt = 1;
|
use_dbtgt = 0;
|
||||||
use_dbenc = 1;
|
use_dbenc = 0;
|
||||||
use_ml_mlse = 1;
|
use_ml_mlse = 1;
|
||||||
|
|
||||||
addProcessingResultToDatabase = 0;
|
addProcessingResultToDatabase = 0;
|
||||||
|
|||||||
@@ -130,6 +130,10 @@ db_results.config.equalizer_structure = int32(equalizer_structure.vnle_db_mlse);
|
|||||||
db_results.config.comment = 'function: Duobinary tgt. (VNLE -> MLSE)';
|
db_results.config.comment = 'function: Duobinary tgt. (VNLE -> MLSE)';
|
||||||
|
|
||||||
if options.showAnalysis
|
if options.showAnalysis
|
||||||
|
|
||||||
|
eq_signal.eye(eq_signal.fs,M,"fignum",249);
|
||||||
|
|
||||||
|
|
||||||
eq_noise = eq_noise - mean(eq_noise.signal);
|
eq_noise = eq_noise - mean(eq_noise.signal);
|
||||||
|
|
||||||
rx_signal.spectrum("normalizeTo0dB",1,"fignum",250,"displayname","Rx Spectrum");
|
rx_signal.spectrum("normalizeTo0dB",1,"fignum",250,"displayname","Rx Spectrum");
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ end
|
|||||||
|
|
||||||
% Ensure the figure is ready before calling spectrum
|
% Ensure the figure is ready before calling spectrum
|
||||||
eq_noise.spectrum("displayname", options.displayname, "fignum", fig.Number, "normalizeTo0dB", 1,"color",options.color);
|
eq_noise.spectrum("displayname", options.displayname, "fignum", fig.Number, "normalizeTo0dB", 1,"color",options.color);
|
||||||
title('EEN')
|
|
||||||
|
|
||||||
if ~isnan(options.postfilter_taps)
|
if ~isnan(options.postfilter_taps)
|
||||||
% Hold on to the figure for further plotting
|
% Hold on to the figure for further plotting
|
||||||
|
|||||||
@@ -52,6 +52,8 @@ end
|
|||||||
legend
|
legend
|
||||||
grid on
|
grid on
|
||||||
|
|
||||||
|
% view([90 -90]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -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);
|
[Scpe_sig, ~] = Scpe_sig.tsynch("reference", Symbols, "fs_ref", fsym, "debug_plots", 0);
|
||||||
|
|
||||||
% Apply Gaussian filter
|
% Apply Gaussian filter
|
||||||
if 1
|
if 1
|
||||||
Scpe_sig = Filter('filtdegree', 8, "f_cutoff", Symbols.fs.*0.52, ...
|
Scpe_sig = Filter('filtdegree', 8, "f_cutoff", Symbols.fs.*0.52, ...
|
||||||
"fs", Scpe_sig.fs, "filterType", filtertypes.gaussian, ...
|
"fs", Scpe_sig.fs, "filterType", filtertypes.gaussian, ...
|
||||||
"active", true).process(Scpe_sig);
|
"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
|
end
|
||||||
|
|
||||||
% Remove DC offset
|
%Remove DC offset
|
||||||
Scpe_sig = Scpe_sig - mean(Scpe_sig.signal);
|
Scpe_sig = Scpe_sig - mean(Scpe_sig.signal);
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -2,11 +2,11 @@
|
|||||||
% IM/DD Fading Notch – λ_null vs. Bandwidth (Fixed 10 km)
|
% IM/DD Fading Notch – λ_null vs. Bandwidth (Fixed 10 km)
|
||||||
% ============================================================
|
% ============================================================
|
||||||
|
|
||||||
|
clear; clc;
|
||||||
|
|
||||||
%% Fiber and dispersion parameters
|
%% Fiber and dispersion parameters
|
||||||
lambda0 = 1315e-9; % Zero-dispersion wavelength [m]
|
lambda0 = 1310e-9; % Zero-dispersion wavelength [m]
|
||||||
S0 = 0.08; % Dispersion slope at ZDW [ps/(nm²·km)]
|
S0 = 0.09; % Dispersion slope at ZDW [ps/(nm²·km)]
|
||||||
L = 10e3; % Fiber length [m]
|
L = 10e3; % Fiber length [m]
|
||||||
c = physconst('lightspeed');
|
c = physconst('lightspeed');
|
||||||
|
|
||||||
@@ -17,74 +17,73 @@ f_GHz = f_targets / 1e9;
|
|||||||
%% Compute wavelength λ_null for each target f_null
|
%% Compute wavelength λ_null for each target f_null
|
||||||
[lambda_vec, Dacc_vec] = lambda_for_first_null_full(f_targets, L, lambda0, S0);
|
[lambda_vec, Dacc_vec] = lambda_for_first_null_full(f_targets, L, lambda0, S0);
|
||||||
lambda_nm = lambda_vec * 1e9; % Convert to nm
|
lambda_nm = lambda_vec * 1e9; % Convert to nm
|
||||||
|
Dacc = Dacc_vec; % [ps/nm]
|
||||||
|
|
||||||
%% ------------------------------------------------------------
|
%% ------------------------------------------------------------
|
||||||
% Plot λ_null vs. f_null for 10 km fiber
|
% 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);
|
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])
|
xlabel('Wavelength λ [nm]');
|
||||||
|
ylabel('First fading notch f_{null} [GHz]');
|
||||||
f_GHz = [56,75,90,112] * 1e9;
|
title('IM/DD Fading Notch Position vs. Wavelength');
|
||||||
[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]');
|
|
||||||
grid on; box on;
|
grid on; box on;
|
||||||
lim=(lambda0.*1e9)-[8,40];
|
|
||||||
|
lim = (lambda0.*1e9) - [8, 40];
|
||||||
xlim([lim(2) lim(1)]);
|
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
|
% 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)
|
function [lambda_vec, Dacc_vec] = lambda_for_first_null_full(f_target, L, lambda0, S0)
|
||||||
c = physconst('lightspeed');
|
c = physconst('lightspeed');
|
||||||
S0_si = S0 * 1e3; % ps/(nm²·km) -> s/(m³)
|
S0_si = S0 * 1e3; % ps/(nm²·km) -> s/(m³)
|
||||||
|
|
||||||
% Define O-band boundaries [m]
|
lambda_min = 1260e-9;
|
||||||
lambda_min = 1260e-9;
|
lambda_max = 1360e-9;
|
||||||
lambda_max = 1360e-9;
|
|
||||||
|
|
||||||
f_target = f_target(:);
|
f_target = f_target(:);
|
||||||
N = numel(f_target);
|
N = numel(f_target);
|
||||||
|
|
||||||
lambda_vec = zeros(N,1);
|
lambda_vec = zeros(N,1);
|
||||||
Dacc_vec = zeros(N,1);
|
Dacc_vec = zeros(N,1);
|
||||||
|
|
||||||
for k = 1:N
|
for k = 1:N
|
||||||
RHS = c * 0.5 / (f_target(k)^2 * L);
|
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
|
||||||
try
|
lambda_sol = fzero(fun, [lambda_min, lambda0 * 0.999]);
|
||||||
lambda_sol = fzero(fun, [lambda_min, lambda0 * 0.999]);
|
catch
|
||||||
catch
|
lambda_sol = lambda_min;
|
||||||
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
|
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
|
end
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ function beautifyBERplot(options)
|
|||||||
|
|
||||||
arguments
|
arguments
|
||||||
options.logscale (1,1) logical = 1
|
options.logscale (1,1) logical = 1
|
||||||
|
options.setmarkers (1,1) logical = 1;
|
||||||
options.polyfit (1,1) logical = 0
|
options.polyfit (1,1) logical = 0
|
||||||
options.polyorder (1,1) double = 2
|
options.polyorder (1,1) double = 2
|
||||||
options.fitmethod (1,1) string = "polyfit" % choose fit type
|
options.fitmethod (1,1) string = "polyfit" % choose fit type
|
||||||
@@ -23,13 +24,15 @@ num_markers = length(markers);
|
|||||||
|
|
||||||
% --- style all lines consistently
|
% --- style all lines consistently
|
||||||
for i = 1:length(lines)
|
for i = 1:length(lines)
|
||||||
lines(i).LineWidth = 1;
|
lines(i).LineWidth = 1.2;
|
||||||
% lines(i).LineStyle = '-';
|
% lines(i).LineStyle = '-';
|
||||||
if string(lines(i).Marker) == "none"
|
if options.setmarkers == 1
|
||||||
lines(i).Marker = markers{mod(i-1, num_markers) + 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
|
end
|
||||||
lines(i).MarkerSize = 4;
|
|
||||||
lines(i).MarkerFaceColor = lines(i).Color;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
% --- optional smoothing/fitting overlay
|
% --- optional smoothing/fitting overlay
|
||||||
|
|||||||
133
Libs/wesanderson_colors/WesPalette.m
Normal file
133
Libs/wesanderson_colors/WesPalette.m
Normal file
@@ -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
|
||||||
20
Libs/wesanderson_colors/hex2rgb.m
Normal file
20
Libs/wesanderson_colors/hex2rgb.m
Normal file
@@ -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
|
||||||
64
Libs/wesanderson_colors/minimal_example_wespalette.m
Normal file
64
Libs/wesanderson_colors/minimal_example_wespalette.m
Normal file
@@ -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}',...
|
||||||
|
});
|
||||||
79
Libs/wesanderson_colors/wes_palettes.m
Normal file
79
Libs/wesanderson_colors/wes_palettes.m
Normal file
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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' ...
|
||||||
|
% });
|
||||||
@@ -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 = <values already set earlier> ;
|
||||||
|
|
||||||
|
|
||||||
|
% ============================================================
|
||||||
|
% 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];
|
||||||
@@ -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}',...
|
||||||
|
});
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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 ===
|
||||||
@@ -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);
|
||||||
@@ -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
|
||||||
@@ -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' ...
|
||||||
|
});
|
||||||
Binary file not shown.
@@ -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
|
||||||
@@ -86,8 +86,9 @@ cfg.filters = struct('is_mpi',0,'pam_level',4, ...
|
|||||||
cfg.show_precoded = 1;
|
cfg.show_precoded = 1;
|
||||||
a = plot_measurements_gpt(dataTable, cfg);
|
a = plot_measurements_gpt(dataTable, cfg);
|
||||||
ngmi_pam4 = a.lines(1).YData;
|
ngmi_pam4 = a.lines(1).YData;
|
||||||
|
grossrates = a.lines(1).XData;
|
||||||
tp = TransmissionPerformance;
|
tp = TransmissionPerformance;
|
||||||
netrates_vnle = tp.calculateNetRate(baudrate.* m, ...
|
netrates_vnle = tp.calculateNetRate(grossrates, ...
|
||||||
'NGMI', ngmi_pam4, ...
|
'NGMI', ngmi_pam4, ...
|
||||||
'BER', BER_VNLE);
|
'BER', BER_VNLE);
|
||||||
|
|
||||||
@@ -151,10 +152,26 @@ cfg.fec_lines = [];
|
|||||||
cfg.agg = 'max';
|
cfg.agg = 'max';
|
||||||
|
|
||||||
cfg.figure_number = 47;
|
cfg.figure_number = 47;
|
||||||
% fig = figure(cfg.figure_number);
|
|
||||||
|
|
||||||
lambda = 1310;
|
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
|
% PAM 4
|
||||||
cfg.plot.custom_colors = clr.Paired.red;
|
cfg.plot.custom_colors = clr.Paired.red;
|
||||||
cfg.plot.custom_linetypes = {'-'};
|
cfg.plot.custom_linetypes = {'-'};
|
||||||
|
|||||||
@@ -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' ...
|
|
||||||
} );
|
|
||||||
@@ -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}',...
|
||||||
|
% });
|
||||||
@@ -65,7 +65,7 @@ Scpe_sig.spectrum("fignum",201,"normalizeTo0dB",0,"displayname",'Rx');
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
if 0
|
if 1
|
||||||
%% show freuqncy response of filter
|
%% show freuqncy response of filter
|
||||||
|
|
||||||
measure = 1;
|
measure = 1;
|
||||||
@@ -74,7 +74,7 @@ if 0
|
|||||||
%
|
%
|
||||||
Digi_sig = freqresp.buildOFDM();
|
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);
|
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);
|
fprintf('Plotting: %s\n', precomp_filename);
|
||||||
freqresp.plot();
|
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
|
end
|
||||||
@@ -1,111 +1,51 @@
|
|||||||
function h = plot_measurements_gpt(T, cfg)
|
function [h, M, cfg] = plot_measurements_gpt(T, cfg)
|
||||||
% Versatile plotting from your DB table (with cbrewer2 'Paired' palette).
|
% PLOT_MEASUREMENTS_GPT
|
||||||
|
% Plot measurements, using analyze_measurements_gpt for data handling.
|
||||||
%
|
%
|
||||||
% Usage:
|
% 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
|
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( ...
|
plotdefs = struct( ...
|
||||||
'use_cbrewer2' , true, ...
|
'use_cbrewer2' , true, ...
|
||||||
'colormap' , 'Paired', ... % ColorBrewer 'Paired'
|
'colormap' , 'Paired', ...
|
||||||
'paired_dark_first' , true, ... % dark for lines, light for scatter
|
'paired_dark_first' , true, ...
|
||||||
'lineWidth' , 1.8, ...
|
'lineWidth' , 1.8, ...
|
||||||
'errWidth' , 1.0, ...
|
'errWidth' , 1.0, ...
|
||||||
'scatterSize' , 14, ...
|
'scatterSize' , 14, ...
|
||||||
'scatterAlpha' , 0.35, ...
|
'scatterAlpha' , 0.35, ...
|
||||||
'marker' , 'o', ...
|
'marker' , 'o', ...
|
||||||
'marker_precoded' , 's', ...
|
'marker_precoded' , 's', ...
|
||||||
'lineStyle_pre_emph_on' , '--', ...
|
|
||||||
'lineStyle_pre_emph_off', '-', ...
|
|
||||||
'legendLocation' , 'best', ...
|
'legendLocation' , 'best', ...
|
||||||
'fecLineWidth' , 2.2, ... % thicker FEC limits
|
'fecLineWidth' , 2.2, ...
|
||||||
'fecColor' , [0.25 0.25 0.25], ...
|
'fecColor' , [0.25 0.25 0.25], ...
|
||||||
'capSize' , 6, ...
|
'capSize' , 6, ...
|
||||||
'lineStyle_default' , '-', ...
|
'lineStyle_default' , '-', ...
|
||||||
'use_pre_emph_styling' , true ...
|
'custom_colors' , [], ...
|
||||||
|
'custom_colors_scatter' , [] ...
|
||||||
);
|
);
|
||||||
|
if ~isfield(cfg,'plot') || isempty(cfg.plot)
|
||||||
|
cfg.plot = struct;
|
||||||
|
end
|
||||||
cfg.plot = filldefaults(cfg.plot, plotdefs);
|
cfg.plot = filldefaults(cfg.plot, plotdefs);
|
||||||
|
|
||||||
%% ---- Derived/prep columns
|
%% ---- Colors ----
|
||||||
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);
|
[cols_line, cols_scatter] = buildGroupColors(nG, cfg.plot);
|
||||||
|
|
||||||
%% ---- Axes / Figure handling (new unified logic)
|
%% ---- Axes / Figure handling ----
|
||||||
|
|
||||||
% 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')
|
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);
|
set(gcf,'CurrentAxes',ax);
|
||||||
else
|
else
|
||||||
if isfield(cfg,'figure_number') && ~isempty(cfg.figure_number)
|
if isfield(cfg,'figure_number') && ~isempty(cfg.figure_number)
|
||||||
@@ -113,143 +53,97 @@ else
|
|||||||
else
|
else
|
||||||
figure;
|
figure;
|
||||||
end
|
end
|
||||||
ax = gca; % active axes
|
ax = gca;
|
||||||
end
|
end
|
||||||
|
|
||||||
hold(ax,'on');
|
hold(ax,'on');
|
||||||
grid(ax,'on');
|
grid(ax,'on');
|
||||||
|
|
||||||
|
|
||||||
h.lines = gobjects(nG,1);
|
h.lines = gobjects(nG,1);
|
||||||
h.err = gobjects(nG,1);
|
h.err = gobjects(nG,1);
|
||||||
h.scat = gobjects(nG,1);
|
h.scat = gobjects(nG,1);
|
||||||
h.lines_p = gobjects(nG,1);
|
h.lines_p = gobjects(nG,1);
|
||||||
|
|
||||||
|
%% ---- Plot each group ----
|
||||||
for gi = 1:nG
|
for gi = 1:nG
|
||||||
idx = (G==gi);
|
g = M.group{gi};
|
||||||
Ti = T(idx,:);
|
xu = g.x;
|
||||||
xi = x_raw(idx);
|
yu = g.y;
|
||||||
yi = y_raw(idx);
|
ylo = g.y_lo;
|
||||||
|
yhi = g.y_hi;
|
||||||
|
|
||||||
% Aggregate per unique x
|
% --- Linestyle selection ---
|
||||||
[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;
|
ls = cfg.plot.lineStyle_default;
|
||||||
|
|
||||||
% User-defined override (cycled)
|
|
||||||
if isfield(cfg.plot,'custom_linetypes') && ~isempty(cfg.plot.custom_linetypes)
|
if isfield(cfg.plot,'custom_linetypes') && ~isempty(cfg.plot.custom_linetypes)
|
||||||
L = cfg.plot.custom_linetypes;
|
L = cfg.plot.custom_linetypes;
|
||||||
ls = L{ mod(gi-1, numel(L)) + 1 };
|
ls = L{ mod(gi-1, numel(L)) + 1 };
|
||||||
end
|
end
|
||||||
|
|
||||||
lbl = buildLabel(grpTbl(gi,:), group_by);
|
|
||||||
|
|
||||||
% Main line (dark)
|
|
||||||
colL = cols_line(gi,:);
|
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, ...
|
'LineWidth', cfg.plot.lineWidth, ...
|
||||||
'Marker', cfg.plot.marker, 'MarkerSize', 3, ...
|
'Marker', cfg.plot.marker, 'MarkerSize', 3, ...
|
||||||
'Color', colL, 'LineStyle', ls, ...
|
'Color', colL, 'LineStyle', ls, ...
|
||||||
'DisplayName', char(lbl));
|
'DisplayName', char(lbl));
|
||||||
|
|
||||||
% Spread (IQR) in line color
|
% Spread
|
||||||
if any(isfinite(ylo)) && any(isfinite(yhi))
|
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');
|
'Color', colL, 'CapSize', cfg.plot.capSize, 'HandleVisibility','off');
|
||||||
h.err(gi).LineWidth = cfg.plot.errWidth;
|
h.err(gi).LineWidth = cfg.plot.errWidth;
|
||||||
end
|
end
|
||||||
|
|
||||||
% Raw kept scatter (light)
|
% Raw scatter
|
||||||
if cfg.show_raw
|
if cfg.show_raw
|
||||||
keep_all = false(size(yi));
|
% reuse stored raw data (no extra filtering)
|
||||||
for k = 1:numel(xu)
|
xi = g.x_raw;
|
||||||
bin = (iu==k);
|
yi = g.y_raw;
|
||||||
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,:);
|
colS = cols_scatter(gi,:);
|
||||||
scatter(xi(keep_all), yi(keep_all), cfg.plot.scatterSize, colS, 'filled', ...
|
scatter(ax, xi, yi, cfg.plot.scatterSize, colS, 'filled', ...
|
||||||
'MarkerFaceAlpha', cfg.plot.scatterAlpha, 'MarkerEdgeAlpha', cfg.plot.scatterAlpha, ...
|
'MarkerFaceAlpha', cfg.plot.scatterAlpha, ...
|
||||||
|
'MarkerEdgeAlpha', cfg.plot.scatterAlpha, ...
|
||||||
'HandleVisibility','off');
|
'HandleVisibility','off');
|
||||||
end
|
end
|
||||||
|
|
||||||
% Precoded overlay (dotted, squares), in line color
|
% Precoded overlay
|
||||||
if cfg.show_precoded && ~isempty(y_raw_p) && strcmpi(cfg.y_axis,'BER')
|
if cfg.show_precoded && ~isempty(g.y_precoded) && strcmpi(M.y_axis,'BER')
|
||||||
ypi = y_raw_p(idx);
|
ypu = g.y_precoded;
|
||||||
ypu = nan(size(xu));
|
h.lines_p(gi) = plot(ax, xu, ypu, ...
|
||||||
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), ...
|
'LineWidth', max(1.2, cfg.plot.lineWidth-0.2), ...
|
||||||
'Marker', cfg.plot.marker_precoded, 'MarkerSize', 3, ...
|
'Marker', cfg.plot.marker_precoded, 'MarkerSize', 3, ...
|
||||||
'Color', colL, 'LineStyle', ':', ...
|
'Color', colL, 'LineStyle', ':', ...
|
||||||
'DisplayName', [char(lbl) ' (precoded)']);
|
'DisplayName', [char(lbl) ' (precoded)']);
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
%% ---- Axes / Labels / FEC
|
%% ---- Axes / Labels / FEC ----
|
||||||
ylabel(cfg.y_axis, 'Interpreter','none');
|
ylabel(ax, M.y_axis, 'Interpreter','none');
|
||||||
xlabel(x_label, 'Interpreter','none');
|
xlabel(ax, M.x_label, 'Interpreter','none');
|
||||||
set(gca, 'YScale', cfg.y_scale, 'FontSize', 11);
|
set(ax, 'YScale', cfg.y_scale, 'FontSize', 11);
|
||||||
% legend('Location', cfg.plot.legendLocation); box on;
|
|
||||||
|
|
||||||
xticks(floor(xu));
|
% X ticks/limits using all group x-values
|
||||||
xlim([min(xu), max(xu)])
|
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
|
for v = cfg.fec_lines
|
||||||
yline(v, '--', 'Color', cfg.plot.fecColor, ...
|
yline(ax, v, '--', 'Color', cfg.plot.fecColor, ...
|
||||||
'LineWidth', cfg.plot.fecLineWidth, 'HandleVisibility','off');
|
'LineWidth', cfg.plot.fecLineWidth, 'HandleVisibility','off');
|
||||||
end
|
end
|
||||||
ylim([1e-5, 0.5]);
|
ylim(ax, [1e-5, 0.5]);
|
||||||
yticks([1e-5, 1e-4, 1e-3, 1e-2, 1e-1]);
|
yticks(ax, [1e-5, 1e-4, 1e-3, 1e-2, 1e-1]);
|
||||||
end
|
end
|
||||||
|
|
||||||
|
% legend(ax, 'Location', cfg.plot.legendLocation); % if you want legends
|
||||||
|
|
||||||
|
box(ax,'on');
|
||||||
|
|
||||||
end % ===== main =====
|
end % ===== main =====
|
||||||
|
|
||||||
@@ -263,120 +157,14 @@ for i = 1:numel(fn)
|
|||||||
if ~isfield(cfg, f) || isempty(cfg.(f))
|
if ~isfield(cfg, f) || isempty(cfg.(f))
|
||||||
cfg.(f) = defs.(f);
|
cfg.(f) = defs.(f);
|
||||||
elseif isstruct(defs.(f)) && isstruct(cfg.(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
|
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)
|
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)
|
if isfield(plotcfg,'custom_colors') && ~isempty(plotcfg.custom_colors)
|
||||||
C = plotcfg.custom_colors;
|
C = plotcfg.custom_colors;
|
||||||
if size(C,1) < nG
|
if size(C,1) < nG
|
||||||
@@ -384,7 +172,6 @@ if isfield(plotcfg,'custom_colors') && ~isempty(plotcfg.custom_colors)
|
|||||||
end
|
end
|
||||||
cols_line = C(1:nG, :);
|
cols_line = C(1:nG, :);
|
||||||
|
|
||||||
% Scatter colors: either user-provided or lightened
|
|
||||||
if isfield(plotcfg,'custom_colors_scatter') && ~isempty(plotcfg.custom_colors_scatter)
|
if isfield(plotcfg,'custom_colors_scatter') && ~isempty(plotcfg.custom_colors_scatter)
|
||||||
Cs = plotcfg.custom_colors_scatter;
|
Cs = plotcfg.custom_colors_scatter;
|
||||||
if size(Cs,1) < nG
|
if size(Cs,1) < nG
|
||||||
@@ -392,7 +179,6 @@ if isfield(plotcfg,'custom_colors') && ~isempty(plotcfg.custom_colors)
|
|||||||
end
|
end
|
||||||
cols_scatter = Cs(1:nG, :);
|
cols_scatter = Cs(1:nG, :);
|
||||||
else
|
else
|
||||||
% auto-lighten scatter colors
|
|
||||||
cols_scatter = zeros(nG,3);
|
cols_scatter = zeros(nG,3);
|
||||||
for i = 1:nG
|
for i = 1:nG
|
||||||
cols_scatter(i,:) = lightenColor(cols_line(i,:), 0.40);
|
cols_scatter(i,:) = lightenColor(cols_line(i,:), 0.40);
|
||||||
@@ -401,7 +187,7 @@ if isfield(plotcfg,'custom_colors') && ~isempty(plotcfg.custom_colors)
|
|||||||
return;
|
return;
|
||||||
end
|
end
|
||||||
|
|
||||||
% --- 2) Standard behavior (using cbrewer2 or fallback) ------------
|
% 2) Standard behavior
|
||||||
useBrewer = plotcfg.use_cbrewer2 && exist('cbrewer2','file')==2;
|
useBrewer = plotcfg.use_cbrewer2 && exist('cbrewer2','file')==2;
|
||||||
if useBrewer
|
if useBrewer
|
||||||
N = max(2*nG, 12);
|
N = max(2*nG, 12);
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
% === SETTINGS ===
|
% === SETTINGS ===
|
||||||
dsp_options.append_to_db = 0;
|
dsp_options.append_to_db = 1;
|
||||||
dsp_options.max_occurences = 5;
|
dsp_options.max_occurences = 1;
|
||||||
|
|
||||||
experiment = "highspeed_2024";
|
experiment = "highspeed_2024";
|
||||||
dsp_options.mode = "load_run_id"; % 'simulate' & 'load_files'
|
dsp_options.mode = "load_run_id"; % 'simulate' & 'load_files'
|
||||||
@@ -40,25 +40,25 @@ end
|
|||||||
|
|
||||||
fp = QueryFilter();
|
fp = QueryFilter();
|
||||||
% fp.where('Runs', 'run_id','EQUALS', 2776);
|
% fp.where('Runs', 'run_id','EQUALS', 2776);
|
||||||
M = 4;
|
M = 6;
|
||||||
fp.where('Runs', 'pam_level','EQUALS', M);
|
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', 'symbolrate','EQUALS', 195e9);
|
||||||
fp.where('Runs', 'fiber_length','EQUALS', 2);
|
fp.where('Runs', 'fiber_length','EQUALS', 10);
|
||||||
% fp.where('Runs', 'is_mpi','EQUALS', 0);
|
fp.where('Runs', 'is_mpi','EQUALS', 0);
|
||||||
% fp.where('Runs', 'interference_path_length','EQUALS', 1000);
|
% fp.where('Runs', 'interference_path_length','EQUALS', 1000);
|
||||||
% fp.where('Runs', 'loop_id','GREATER_THAN', 11);
|
% fp.where('Runs', 'loop_id','GREATER_THAN', 11);
|
||||||
% fp.where('Runs', 'sir','EQUALS',18);
|
% 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', 'db_mode','EQUALS', 0);
|
||||||
fp.where('Runs', 'rop_attenuation','EQUAL', 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'));
|
[dataTable,~] = db.queryDB(fp, db.getTableFieldNames('Runs'));
|
||||||
|
|
||||||
% === Set LOOPS & Initialize DataStorage ===
|
% === Set LOOPS & Initialize DataStorage ===
|
||||||
dsp_options.parameters = struct();
|
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 = DataStorage(dsp_options.parameters);
|
||||||
wh.addStorage("ffe_package");
|
wh.addStorage("ffe_package");
|
||||||
@@ -70,10 +70,7 @@ wh.addStorage("mlmlse_package");
|
|||||||
|
|
||||||
%% === RUN IT ===
|
%% === 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);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
118
projects/HighSpeedExperiment_2024/a_minimal_example.m
Normal file
118
projects/HighSpeedExperiment_2024/a_minimal_example.m
Normal file
@@ -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')
|
||||||
@@ -8,84 +8,115 @@ db_coding_approach = 0;
|
|||||||
fsym = 160e9;
|
fsym = 160e9;
|
||||||
fdac = 256e9;
|
fdac = 256e9;
|
||||||
random_key = 0;
|
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
|
if M == 4
|
||||||
pulsef=1;
|
pulsef=1;
|
||||||
precomp_amp_max = -50;
|
precomp_amp_max = -50;
|
||||||
elseif M == 6
|
fsym = 196e9;
|
||||||
pulsef=0;
|
elseif M == 6
|
||||||
precomp_amp_max = -50;
|
pulsef=0;
|
||||||
elseif M == 8
|
precomp_amp_max = -50;
|
||||||
pulsef=0;
|
fsym = 180e9;
|
||||||
precomp_amp_max = -50;
|
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
|
end
|
||||||
|
|
||||||
elseif (db_precode==1)&&(db_coding_approach==1)
|
|
||||||
|
|
||||||
if M == 4
|
rcalpha = 0.05;
|
||||||
pulsef=1;
|
Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rrc","pulselength",16,"alpha",rcalpha);
|
||||||
precomp_amp_max = -38;
|
|
||||||
pulsef = 1;
|
Pamsource = PAMsource(...
|
||||||
elseif M == 6
|
"fsym",fsym,"M",M,"order",19,"useprbs",0,...
|
||||||
pulsef=0;
|
"fs_out",fdac,...
|
||||||
precomp_amp_max = -38;
|
"applyclipping",0,"clipfactor",1.2,...
|
||||||
pulsef = 1;
|
"applypulseform",pulsef,"pulseformer",Pform,...
|
||||||
elseif M == 8
|
"randkey",random_key,...
|
||||||
pulsef=0;
|
"db_precode",db_precode,"db_encode",db_coding_approach,...
|
||||||
precomp_amp_max = -38;
|
"mrds_code",0,"mrds_blocklength",512);
|
||||||
pulsef = 1;
|
|
||||||
|
[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
|
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
|
end
|
||||||
|
|
||||||
|
ylim([-25,10]);
|
||||||
|
xlim([0,105]);
|
||||||
|
xticks(0:20:110);
|
||||||
|
yticks(-30:10:10);
|
||||||
|
|
||||||
rcalpha = 0.05;
|
fig = gcf;
|
||||||
Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rrc","pulselength",16,"alpha",rcalpha);
|
pos = [536.3333 879 450 222];
|
||||||
|
set(fig, 'Position', pos);
|
||||||
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]);
|
|
||||||
@@ -30,7 +30,7 @@ for l = 1:numel(lambda_vals)
|
|||||||
for m = 1:numel(M_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_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));
|
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));
|
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));
|
||||||
|
|||||||
@@ -18,14 +18,14 @@ u_pi = 2.9;
|
|||||||
vbias = -vbias_rel*u_pi;
|
vbias = -vbias_rel*u_pi;
|
||||||
laser_wavelength = 1310;
|
laser_wavelength = 1310;
|
||||||
laser_linewidth = 0;
|
laser_linewidth = 0;
|
||||||
tx_bw_nyquist = 0.7;
|
tx_bw_nyquist = 1;
|
||||||
|
|
||||||
% Channel
|
% Channel
|
||||||
link_length = 1;
|
link_length = 1;
|
||||||
|
|
||||||
% RX
|
% RX
|
||||||
rop = -8;
|
rop = 0;
|
||||||
rx_bw_nyquist = 0.7;
|
rx_bw_nyquist = 0.99;
|
||||||
|
|
||||||
vnle_order1 = 50;
|
vnle_order1 = 50;
|
||||||
vnle_order2 = 3;
|
vnle_order2 = 3;
|
||||||
@@ -59,7 +59,7 @@ Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rc","pulselength",1
|
|||||||
|
|
||||||
db_precode = 0;
|
db_precode = 0;
|
||||||
db_encode = 0;
|
db_encode = 0;
|
||||||
duob_mode = db_mode.no_db;
|
duob_mode = db_mode.db_precoded;
|
||||||
apply_pulsef = 1;
|
apply_pulsef = 1;
|
||||||
[Digi_sig,Symbols,Tx_bits] = PAMsource(...
|
[Digi_sig,Symbols,Tx_bits] = PAMsource(...
|
||||||
"fsym",fsym,"M",M,"order",18,"useprbs",0,...
|
"fsym",fsym,"M",M,"order",18,"useprbs",0,...
|
||||||
@@ -67,12 +67,21 @@ apply_pulsef = 1;
|
|||||||
"applyclipping",0,"clipfactor",1.5,...
|
"applyclipping",0,"clipfactor",1.5,...
|
||||||
"applypulseform",apply_pulsef,"pulseformer",Pform,...
|
"applypulseform",apply_pulsef,"pulseformer",Pform,...
|
||||||
"randkey",random_key,...
|
"randkey",random_key,...
|
||||||
"db_precode",db_precode,"db_encode",db_encode,...
|
|
||||||
"mrds_code",0,"mrds_blocklength",512,"duobinary_mode",duob_mode).process();
|
"mrds_code",0,"mrds_blocklength",512,"duobinary_mode",duob_mode).process();
|
||||||
|
|
||||||
Digi_sig.spectrum("displayname",'Digi Spectrum','fignum',10,'normalizeTo0dB',1);
|
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
|
%%%%% AWG
|
||||||
% El_sig = M8199A("kover",kover).process(Digi_sig);
|
% 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_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);
|
mlse_ = MLSE("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels);
|
||||||
|
|
||||||
% FFE or VNLE
|
if duob_mode == db_mode.no_db
|
||||||
[eq_signal_sd, eq_noise] = eq_.process(Scpe_cell{1}, Symbols);
|
|
||||||
|
|
||||||
% Hard decision on VNLE output
|
% FFE or VNLE
|
||||||
eq_signal_hd = PAMmapper(M, 0).quantize(eq_signal_sd);
|
[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
|
elseif duob_mode == db_mode.db_precoded
|
||||||
[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);
|
[EQ_sig, Noi] = eq_.process(Scpe_cell{1},Duobinary().encode(Symbols));
|
||||||
mlse_sig_hd = PAMmapper(M, 0, "eth_style", 0).quantize(mlse_sig_sd);
|
|
||||||
|
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
|
||||||
@@ -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_sequence = Duobinary().encode(Symbols);
|
||||||
db_ref_constellation = unique(db_ref_sequence.signal);
|
db_ref_constellation = unique(db_ref_sequence.signal);
|
||||||
[eq_signal, eq_noise] = eq_.process(Scpe_sig,db_ref_sequence);
|
[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);
|
[mlse_sig_sd,LLR,GMI_MLSE] = mlse_.process(eq_signal,Symbols);
|
||||||
else
|
else
|
||||||
% Ml MLSE
|
% Ml MLSE
|
||||||
|
|||||||
@@ -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);
|
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 = {};
|
PD_cell = {};
|
||||||
parfor l = 1:N
|
for l = 1:N
|
||||||
|
|
||||||
%%%%%% PD Square Law %%%%%%
|
%%%%%% PD Square Law %%%%%%
|
||||||
assert(fdac*kover==Opt_sig_wdm_demux{l}.fs,'Sampling Frequencies do not match! Check previous steps');
|
assert(fdac*kover==Opt_sig_wdm_demux{l}.fs,'Sampling Frequencies do not match! Check previous steps');
|
||||||
|
|||||||
Reference in New Issue
Block a user