Add new minimal example (+ a ton of other, not so important, changes)
This commit is contained in:
@@ -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;
|
||||
a = plot_measurements_gpt(dataTable, cfg);
|
||||
ngmi_pam4 = a.lines(1).YData;
|
||||
grossrates = a.lines(1).XData;
|
||||
tp = TransmissionPerformance;
|
||||
netrates_vnle = tp.calculateNetRate(baudrate.* m, ...
|
||||
netrates_vnle = tp.calculateNetRate(grossrates, ...
|
||||
'NGMI', ngmi_pam4, ...
|
||||
'BER', BER_VNLE);
|
||||
|
||||
@@ -151,10 +152,26 @@ cfg.fec_lines = [];
|
||||
cfg.agg = 'max';
|
||||
|
||||
cfg.figure_number = 47;
|
||||
% fig = figure(cfg.figure_number);
|
||||
|
||||
lambda = 1310;
|
||||
|
||||
% cfg = struct;
|
||||
cfg.filters = struct('is_mpi',0,'pam_level',4, ...
|
||||
'equalizer_structure',equalizer_structure.vnle_db_mlse, ...
|
||||
'pre_emph',0,'wavelength',lambda);
|
||||
cfg.x_axis = 'grossrate';
|
||||
cfg.y_axis = 'NGMI'; % or 'NGMI', etc.
|
||||
cfg.show_precoded = 1;
|
||||
|
||||
[M, cfg] = analyze_measurements_gpt(dataTable, cfg);
|
||||
|
||||
grossrates = M.x; % aggregated X
|
||||
ber = M.y; % aggregated Y (BER or NGMI)
|
||||
ber_prec = M.y_precoded; % precoded BER (if available)
|
||||
|
||||
[h, M] = plot_measurements_gpt(dataTable, cfg);
|
||||
|
||||
|
||||
% PAM 4
|
||||
cfg.plot.custom_colors = clr.Paired.red;
|
||||
cfg.plot.custom_linetypes = {'-'};
|
||||
|
||||
@@ -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
|
||||
|
||||
measure = 1;
|
||||
@@ -74,7 +74,7 @@ if 0
|
||||
%
|
||||
Digi_sig = freqresp.buildOFDM();
|
||||
|
||||
Digi_sig.spectrum("fignum",1112,"displayname",['maxamp:',num2str(maxamp)]);
|
||||
% Digi_sig.spectrum("fignum",1112,"displayname",['maxamp:',num2str(maxamp)]);
|
||||
|
||||
Digi_sig = Filter('filtdegree',3,"f_cutoff",70e9,"fs",256e9,"filterType",filtertypes.butterworth,"active",true).process(Digi_sig);
|
||||
|
||||
@@ -97,4 +97,15 @@ if 0
|
||||
|
||||
fprintf('Plotting: %s\n', precomp_filename);
|
||||
freqresp.plot();
|
||||
|
||||
outfile = 'C:\Users\Silas\Documents\latex\JLT_400G copy\media\matlab2tikz\spectrum_2.tikz';
|
||||
matlab2tikz(outfile, ...
|
||||
'width','\fwidth', ...
|
||||
'height','\fheight', ...
|
||||
'showInfo',false, ...
|
||||
'extraAxisOptions',{ ...
|
||||
'legend style={font=\footnotesize}', ...
|
||||
'legend columns=1' ...
|
||||
});
|
||||
|
||||
end
|
||||
@@ -1,111 +1,51 @@
|
||||
function h = plot_measurements_gpt(T, cfg)
|
||||
% Versatile plotting from your DB table (with cbrewer2 'Paired' palette).
|
||||
function [h, M, cfg] = plot_measurements_gpt(T, cfg)
|
||||
% PLOT_MEASUREMENTS_GPT
|
||||
% Plot measurements, using analyze_measurements_gpt for data handling.
|
||||
%
|
||||
% Usage:
|
||||
% h = plot_measurements_flex(dataTable, cfg)
|
||||
% h = plot_measurements_gpt(dataTable, cfg);
|
||||
% [h, M] = plot_measurements_gpt(dataTable, cfg);
|
||||
%
|
||||
% For values only, without plotting, call:
|
||||
% [M, cfg] = analyze_measurements_gpt(dataTable, cfg);
|
||||
|
||||
%% ---- Defaults
|
||||
if nargin < 2, cfg = struct; end
|
||||
defaults = struct( ...
|
||||
'x_axis' , 'symbolrate', ...
|
||||
'y_axis' , 'BER', ...
|
||||
'y_scale' , 'auto', ...
|
||||
'group_by' , {{'equalizer_structure','pre_emph'}}, ...
|
||||
'filters' , struct, ...
|
||||
'agg' , 'mean', ...
|
||||
'outlier' , 'auto', ...
|
||||
'mad_z' , 4, ...
|
||||
'pct_limits' , [2.5 97.5], ...
|
||||
'min_pts_x' , 3, ...
|
||||
'show_raw' , true, ...
|
||||
'show_precoded', [], ...
|
||||
'show_spread' , 'none', ...
|
||||
'fec_lines' , [], ...
|
||||
'plot', struct() ...
|
||||
);
|
||||
cfg = filldefaults(cfg, defaults);
|
||||
|
||||
% ---- Plot defaults (new)
|
||||
% --- First: run analysis (filtering, grouping, aggregation) ---
|
||||
[M, cfg] = analyze_measurements_gpt(T, cfg);
|
||||
|
||||
nG = M.nGroups;
|
||||
|
||||
%% ---- Plot defaults ----
|
||||
plotdefs = struct( ...
|
||||
'use_cbrewer2' , true, ...
|
||||
'colormap' , 'Paired', ... % ColorBrewer 'Paired'
|
||||
'paired_dark_first' , true, ... % dark for lines, light for scatter
|
||||
'colormap' , 'Paired', ...
|
||||
'paired_dark_first' , true, ...
|
||||
'lineWidth' , 1.8, ...
|
||||
'errWidth' , 1.0, ...
|
||||
'scatterSize' , 14, ...
|
||||
'scatterAlpha' , 0.35, ...
|
||||
'marker' , 'o', ...
|
||||
'marker_precoded' , 's', ...
|
||||
'lineStyle_pre_emph_on' , '--', ...
|
||||
'lineStyle_pre_emph_off', '-', ...
|
||||
'legendLocation' , 'best', ...
|
||||
'fecLineWidth' , 2.2, ... % thicker FEC limits
|
||||
'fecLineWidth' , 2.2, ...
|
||||
'fecColor' , [0.25 0.25 0.25], ...
|
||||
'capSize' , 6, ...
|
||||
'lineStyle_default' , '-', ...
|
||||
'use_pre_emph_styling' , true ...
|
||||
'lineStyle_default' , '-', ...
|
||||
'custom_colors' , [], ...
|
||||
'custom_colors_scatter' , [] ...
|
||||
);
|
||||
if ~isfield(cfg,'plot') || isempty(cfg.plot)
|
||||
cfg.plot = struct;
|
||||
end
|
||||
cfg.plot = filldefaults(cfg.plot, plotdefs);
|
||||
|
||||
%% ---- Derived/prep columns
|
||||
if ~ismember('pre_emph', T.Properties.VariableNames)
|
||||
if ~ismember('db_mode', T.Properties.VariableNames)
|
||||
error('Missing column "db_mode" for pre_emph derivation.');
|
||||
end
|
||||
T.pre_emph = T.db_mode == 0;
|
||||
end
|
||||
if ~ismember(cfg.y_axis, T.Properties.VariableNames)
|
||||
error('y_axis "%s" not found in table.', cfg.y_axis);
|
||||
end
|
||||
|
||||
isBER = startsWith(cfg.y_axis, "BER", 'IgnoreCase', true);
|
||||
if strcmpi(cfg.y_scale,'auto'), cfg.y_scale = tern(isBER, 'log', 'linear'); end
|
||||
if strcmpi(cfg.outlier,'auto'), cfg.outlier = tern(isBER, 'mad', 'none'); end
|
||||
if isempty(cfg.show_precoded)
|
||||
cfg.show_precoded = isBER && ismember('BER_precoded', T.Properties.VariableNames);
|
||||
end
|
||||
|
||||
%% ---- Filters
|
||||
T = applyFilters(T, cfg.filters);
|
||||
[x_raw, x_label] = computeX(T, cfg.x_axis);
|
||||
y_raw = T.(cfg.y_axis);
|
||||
|
||||
validXY = isfinite(x_raw) & isfinite(y_raw);
|
||||
T = T(validXY, :);
|
||||
x_raw = x_raw(validXY);
|
||||
y_raw = y_raw(validXY);
|
||||
|
||||
if mean(abs(y_raw)) > 1e8
|
||||
%giga values
|
||||
y_raw = y_raw.*1e-9;
|
||||
end
|
||||
|
||||
if cfg.show_precoded && ismember('BER_precoded', T.Properties.VariableNames)
|
||||
y_raw_p = T.BER_precoded(validXY);
|
||||
else
|
||||
y_raw_p = [];
|
||||
end
|
||||
|
||||
%% ---- Grouping
|
||||
group_by = cfg.group_by;
|
||||
if ~all(ismember(group_by, T.Properties.VariableNames))
|
||||
error('Some group_by columns are missing in table.');
|
||||
end
|
||||
[G, grpTbl] = findgroups(T(:, group_by));
|
||||
nG = max(G);
|
||||
|
||||
% ==== Colors (cbrewer2 'Paired' with dark/ light pairs) ====
|
||||
%% ---- Colors ----
|
||||
[cols_line, cols_scatter] = buildGroupColors(nG, cfg.plot);
|
||||
|
||||
%% ---- Axes / Figure handling (new unified logic)
|
||||
|
||||
% Priority:
|
||||
% 1) cfg.ax → use existing axes (subplots/tiles)
|
||||
% 2) cfg.figure_number → select/create figure
|
||||
% 3) fallback: create new figure
|
||||
|
||||
%% ---- Axes / Figure handling ----
|
||||
if isfield(cfg,'ax') && ~isempty(cfg.ax) && isgraphics(cfg.ax,'axes')
|
||||
ax = cfg.ax; % use caller-provided axes
|
||||
ax = cfg.ax;
|
||||
set(gcf,'CurrentAxes',ax);
|
||||
else
|
||||
if isfield(cfg,'figure_number') && ~isempty(cfg.figure_number)
|
||||
@@ -113,143 +53,97 @@ else
|
||||
else
|
||||
figure;
|
||||
end
|
||||
ax = gca; % active axes
|
||||
ax = gca;
|
||||
end
|
||||
|
||||
hold(ax,'on');
|
||||
grid(ax,'on');
|
||||
|
||||
|
||||
h.lines = gobjects(nG,1);
|
||||
h.err = gobjects(nG,1);
|
||||
h.scat = gobjects(nG,1);
|
||||
h.lines_p = gobjects(nG,1);
|
||||
|
||||
%% ---- Plot each group ----
|
||||
for gi = 1:nG
|
||||
idx = (G==gi);
|
||||
Ti = T(idx,:);
|
||||
xi = x_raw(idx);
|
||||
yi = y_raw(idx);
|
||||
g = M.group{gi};
|
||||
xu = g.x;
|
||||
yu = g.y;
|
||||
ylo = g.y_lo;
|
||||
yhi = g.y_hi;
|
||||
|
||||
% Aggregate per unique x
|
||||
[xu, ia, iu] = unique(xi);
|
||||
yu = nan(size(xu));
|
||||
ylo = nan(size(xu));
|
||||
yhi = nan(size(xu));
|
||||
|
||||
for k = 1:numel(xu)
|
||||
bin = (iu==k);
|
||||
yy = yi(bin);
|
||||
yy = yy(isfinite(yy));
|
||||
if isempty(yy), continue; end
|
||||
km = outlierMask(yy, cfg, strcmpi(cfg.y_scale,'log'));
|
||||
if nnz(km) < cfg.min_pts_x, km = true(size(yy)); end
|
||||
yy = yy(km);
|
||||
|
||||
if strcmpi(cfg.agg,'median'), yu(k)=median(yy,'omitnan'); elseif strcmpi(cfg.agg,'mean'), yu(k)=mean(yy,'omitnan'); elseif strcmpi(cfg.agg,'min'), yu(k)=min(yy); elseif strcmpi(cfg.agg,'max'), yu(k)=max(yy); end
|
||||
if strcmpi(cfg.show_spread,'iqr')
|
||||
q = prctile(yy,[25 75]);
|
||||
ylo(k) = max(yu(k)-q(1), eps);
|
||||
yhi(k) = max(q(2)-yu(k), eps);
|
||||
elseif strcmpi(cfg.show_spread,'minmax')
|
||||
ylo(k) = min(yy);
|
||||
yhi(k) = max(yy);
|
||||
end
|
||||
end
|
||||
|
||||
% sort
|
||||
[xu, ord] = sort(xu);
|
||||
yu = yu(ord);
|
||||
ylo = ylo(ord);
|
||||
yhi = yhi(ord);
|
||||
|
||||
% Styles
|
||||
% Decide if we style by pre_emph
|
||||
% --- LINE TYPE SELECTION (no pre-emphasis logic) ---
|
||||
% --- Linestyle selection ---
|
||||
ls = cfg.plot.lineStyle_default;
|
||||
|
||||
% User-defined override (cycled)
|
||||
if isfield(cfg.plot,'custom_linetypes') && ~isempty(cfg.plot.custom_linetypes)
|
||||
L = cfg.plot.custom_linetypes;
|
||||
ls = L{ mod(gi-1, numel(L)) + 1 };
|
||||
end
|
||||
|
||||
lbl = buildLabel(grpTbl(gi,:), group_by);
|
||||
|
||||
% Main line (dark)
|
||||
colL = cols_line(gi,:);
|
||||
h.lines(gi) = plot(xu, yu, ...
|
||||
lbl = g.label;
|
||||
|
||||
% Main line
|
||||
h.lines(gi) = plot(ax, xu, yu, ...
|
||||
'LineWidth', cfg.plot.lineWidth, ...
|
||||
'Marker', cfg.plot.marker, 'MarkerSize', 3, ...
|
||||
'Color', colL, 'LineStyle', ls, ...
|
||||
'DisplayName', char(lbl));
|
||||
|
||||
% Spread (IQR) in line color
|
||||
% Spread
|
||||
if any(isfinite(ylo)) && any(isfinite(yhi))
|
||||
h.err(gi) = errorbar(xu, yu, ylo, yhi, 'LineStyle','none', ...
|
||||
h.err(gi) = errorbar(ax, xu, yu, ylo, yhi, 'LineStyle','none', ...
|
||||
'Color', colL, 'CapSize', cfg.plot.capSize, 'HandleVisibility','off');
|
||||
h.err(gi).LineWidth = cfg.plot.errWidth;
|
||||
end
|
||||
|
||||
% Raw kept scatter (light)
|
||||
% Raw scatter
|
||||
if cfg.show_raw
|
||||
keep_all = false(size(yi));
|
||||
for k = 1:numel(xu)
|
||||
bin = (iu==k);
|
||||
yy = yi(bin);
|
||||
km = outlierMask(yy, cfg, strcmpi(cfg.y_scale,'log'));
|
||||
if nnz(km) < cfg.min_pts_x, km = true(size(yy)); end
|
||||
keep_all(bin) = km;
|
||||
end
|
||||
% reuse stored raw data (no extra filtering)
|
||||
xi = g.x_raw;
|
||||
yi = g.y_raw;
|
||||
colS = cols_scatter(gi,:);
|
||||
scatter(xi(keep_all), yi(keep_all), cfg.plot.scatterSize, colS, 'filled', ...
|
||||
'MarkerFaceAlpha', cfg.plot.scatterAlpha, 'MarkerEdgeAlpha', cfg.plot.scatterAlpha, ...
|
||||
scatter(ax, xi, yi, cfg.plot.scatterSize, colS, 'filled', ...
|
||||
'MarkerFaceAlpha', cfg.plot.scatterAlpha, ...
|
||||
'MarkerEdgeAlpha', cfg.plot.scatterAlpha, ...
|
||||
'HandleVisibility','off');
|
||||
end
|
||||
|
||||
% Precoded overlay (dotted, squares), in line color
|
||||
if cfg.show_precoded && ~isempty(y_raw_p) && strcmpi(cfg.y_axis,'BER')
|
||||
ypi = y_raw_p(idx);
|
||||
ypu = nan(size(xu));
|
||||
for k = 1:numel(xu)
|
||||
bin = (iu==k);
|
||||
yy = ypi(bin);
|
||||
yy = yy(isfinite(yy));
|
||||
if isempty(yy), continue; end
|
||||
km = outlierMask(yy, cfg, true);
|
||||
if nnz(km) < cfg.min_pts_x, km = true(size(yy)); end
|
||||
yy = yy(km);
|
||||
if strcmpi(cfg.agg,'median'), ypu(k)=median(yy,'omitnan'); elseif strcmpi(cfg.agg,'mean'), ypu(k)=mean(yy,'omitnan'); elseif strcmpi(cfg.agg,'min'), ypu(k)=min(yy); elseif strcmpi(cfg.agg,'max'), ypu(k)=max(yy); end
|
||||
end
|
||||
h.lines_p(gi) = plot(xu, ypu, ...
|
||||
% Precoded overlay
|
||||
if cfg.show_precoded && ~isempty(g.y_precoded) && strcmpi(M.y_axis,'BER')
|
||||
ypu = g.y_precoded;
|
||||
h.lines_p(gi) = plot(ax, xu, ypu, ...
|
||||
'LineWidth', max(1.2, cfg.plot.lineWidth-0.2), ...
|
||||
'Marker', cfg.plot.marker_precoded, 'MarkerSize', 3, ...
|
||||
'Color', colL, 'LineStyle', ':', ...
|
||||
'DisplayName', [char(lbl) ' (precoded)']);
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
%% ---- Axes / Labels / FEC
|
||||
ylabel(cfg.y_axis, 'Interpreter','none');
|
||||
xlabel(x_label, 'Interpreter','none');
|
||||
set(gca, 'YScale', cfg.y_scale, 'FontSize', 11);
|
||||
% legend('Location', cfg.plot.legendLocation); box on;
|
||||
%% ---- Axes / Labels / FEC ----
|
||||
ylabel(ax, M.y_axis, 'Interpreter','none');
|
||||
xlabel(ax, M.x_label, 'Interpreter','none');
|
||||
set(ax, 'YScale', cfg.y_scale, 'FontSize', 11);
|
||||
|
||||
xticks(floor(xu));
|
||||
xlim([min(xu), max(xu)])
|
||||
% X ticks/limits using all group x-values
|
||||
allX = cellfun(@(g) g.x(:), M.group, 'UniformOutput', false);
|
||||
allX = unique(vertcat(allX{:}));
|
||||
if ~isempty(allX)
|
||||
xticks(ax, allX);
|
||||
xticklabels(cellstr(num2str(round(allX,1), '%.4f')))
|
||||
xlim(ax, [min(allX), max(allX)]);
|
||||
end
|
||||
|
||||
if startsWith(cfg.y_axis,"BER",'IgnoreCase',true)
|
||||
if startsWith(M.y_axis,"BER",'IgnoreCase',true)
|
||||
for v = cfg.fec_lines
|
||||
yline(v, '--', 'Color', cfg.plot.fecColor, ...
|
||||
yline(ax, v, '--', 'Color', cfg.plot.fecColor, ...
|
||||
'LineWidth', cfg.plot.fecLineWidth, 'HandleVisibility','off');
|
||||
end
|
||||
ylim([1e-5, 0.5]);
|
||||
yticks([1e-5, 1e-4, 1e-3, 1e-2, 1e-1]);
|
||||
ylim(ax, [1e-5, 0.5]);
|
||||
yticks(ax, [1e-5, 1e-4, 1e-3, 1e-2, 1e-1]);
|
||||
end
|
||||
|
||||
% legend(ax, 'Location', cfg.plot.legendLocation); % if you want legends
|
||||
|
||||
box(ax,'on');
|
||||
|
||||
end % ===== main =====
|
||||
|
||||
@@ -263,120 +157,14 @@ for i = 1:numel(fn)
|
||||
if ~isfield(cfg, f) || isempty(cfg.(f))
|
||||
cfg.(f) = defs.(f);
|
||||
elseif isstruct(defs.(f)) && isstruct(cfg.(f))
|
||||
cfg.(f) = filldefaults(cfg.(f), defs.(f)); % recursive for structs
|
||||
cfg.(f) = filldefaults(cfg.(f), defs.(f));
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function out = tern(cond, a, b)
|
||||
if cond
|
||||
out = a;
|
||||
else
|
||||
out = b;
|
||||
end
|
||||
end
|
||||
|
||||
function T2 = applyFilters(T, filters)
|
||||
if isempty(filters), T2 = T; return; end
|
||||
keep = true(height(T),1);
|
||||
fns = fieldnames(filters);
|
||||
for i = 1:numel(fns)
|
||||
name = fns{i};
|
||||
if ~ismember(name, T.Properties.VariableNames)
|
||||
warning('Filter column "%s" not found. Ignored.', name); %#ok<*WNTAG>
|
||||
continue
|
||||
end
|
||||
val = filters.(name);
|
||||
col = T.(name);
|
||||
if isa(val,'function_handle')
|
||||
m = val(col);
|
||||
if ~islogical(m) || ~isequal(size(m), size(col))
|
||||
error('Filter for %s must return logical mask of same size.', name);
|
||||
end
|
||||
keep = keep & m;
|
||||
else
|
||||
keep = keep & ismember(col, val);
|
||||
end
|
||||
end
|
||||
T2 = T(keep,:);
|
||||
end
|
||||
|
||||
function [x, label] = computeX(T, whichX)
|
||||
switch lower(whichX)
|
||||
case {'symbolrate','baudrate'}
|
||||
x = T.symbolrate * 1e-9;
|
||||
label = 'Symbol rate [GBd]';
|
||||
case 'bitrate'
|
||||
if ~ismember('pam_level', T.Properties.VariableNames)
|
||||
error('bitrate requires "pam_level" column.');
|
||||
end
|
||||
bits = floor(log2(double(T.pam_level))*10)/10;
|
||||
x = (T.symbolrate .* bits) * 1e-9;
|
||||
label = 'Grossrate [Gb/s]';
|
||||
case 'grossrate'
|
||||
x = (T.grossrate) * 1e-9;
|
||||
label = 'Grossrate [Gb/s]';
|
||||
otherwise
|
||||
if ~ismember(whichX, T.Properties.VariableNames)
|
||||
error('x_axis "%s" not found in table.', whichX);
|
||||
end
|
||||
x = T.(whichX);
|
||||
label = whichX;
|
||||
end
|
||||
x = double(x(:));
|
||||
end
|
||||
|
||||
function keep = outlierMask(y, cfg, useLog)
|
||||
if isempty(y), keep = false(size(y)); return; end
|
||||
y = y(:);
|
||||
switch lower(cfg.outlier)
|
||||
case 'none'
|
||||
keep = true(size(y)); return
|
||||
case 'mad'
|
||||
z = tern(useLog, log10(y), y);
|
||||
med = median(z,'omitnan');
|
||||
madv = median(abs(z-med),'omitnan');
|
||||
if ~(isfinite(madv) && madv>0)
|
||||
keep = true(size(y)); return
|
||||
end
|
||||
sigma = 1.4826*madv;
|
||||
zz = tern(useLog, log10(y), y);
|
||||
keep = abs(zz - med) <= cfg.mad_z*sigma;
|
||||
case 'pctl'
|
||||
pr = prctile(y, cfg.pct_limits);
|
||||
keep = (y >= pr(1)) & (y <= pr(2));
|
||||
otherwise
|
||||
error('Unknown outlier mode "%s".', cfg.outlier);
|
||||
end
|
||||
end
|
||||
|
||||
function s = buildLabel(grpRow, group_by)
|
||||
parts = strings(1, numel(group_by));
|
||||
for i = 1:numel(group_by)
|
||||
key = group_by{i};
|
||||
val = grpRow.(key);
|
||||
if iscell(val), val = val{1}; end
|
||||
if islogical(val), val = tern(val,'w/','w/o'); end
|
||||
if key == "equalizer_structure"
|
||||
key = '';
|
||||
val = upper(val);
|
||||
val = strrep(val,'_',' ');
|
||||
end
|
||||
|
||||
if key == "pre_emph"
|
||||
% key = strrep(key,'_','-');
|
||||
val = [val, ' pre-emph.'];
|
||||
key = '';
|
||||
end
|
||||
|
||||
parts(i) = sprintf('%s %s', key, string(val));
|
||||
end
|
||||
s = strjoin(parts, ', ');
|
||||
end
|
||||
|
||||
function [cols_line, cols_scatter] = buildGroupColors(nG, plotcfg)
|
||||
|
||||
% --- 1) User-provided custom colors -------------------------------
|
||||
% 1) User-provided custom colors
|
||||
if isfield(plotcfg,'custom_colors') && ~isempty(plotcfg.custom_colors)
|
||||
C = plotcfg.custom_colors;
|
||||
if size(C,1) < nG
|
||||
@@ -384,7 +172,6 @@ if isfield(plotcfg,'custom_colors') && ~isempty(plotcfg.custom_colors)
|
||||
end
|
||||
cols_line = C(1:nG, :);
|
||||
|
||||
% Scatter colors: either user-provided or lightened
|
||||
if isfield(plotcfg,'custom_colors_scatter') && ~isempty(plotcfg.custom_colors_scatter)
|
||||
Cs = plotcfg.custom_colors_scatter;
|
||||
if size(Cs,1) < nG
|
||||
@@ -392,7 +179,6 @@ if isfield(plotcfg,'custom_colors') && ~isempty(plotcfg.custom_colors)
|
||||
end
|
||||
cols_scatter = Cs(1:nG, :);
|
||||
else
|
||||
% auto-lighten scatter colors
|
||||
cols_scatter = zeros(nG,3);
|
||||
for i = 1:nG
|
||||
cols_scatter(i,:) = lightenColor(cols_line(i,:), 0.40);
|
||||
@@ -401,7 +187,7 @@ if isfield(plotcfg,'custom_colors') && ~isempty(plotcfg.custom_colors)
|
||||
return;
|
||||
end
|
||||
|
||||
% --- 2) Standard behavior (using cbrewer2 or fallback) ------------
|
||||
% 2) Standard behavior
|
||||
useBrewer = plotcfg.use_cbrewer2 && exist('cbrewer2','file')==2;
|
||||
if useBrewer
|
||||
N = max(2*nG, 12);
|
||||
|
||||
@@ -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 ===
|
||||
dsp_options.append_to_db = 0;
|
||||
dsp_options.max_occurences = 5;
|
||||
dsp_options.append_to_db = 1;
|
||||
dsp_options.max_occurences = 1;
|
||||
|
||||
experiment = "highspeed_2024";
|
||||
dsp_options.mode = "load_run_id"; % 'simulate' & 'load_files'
|
||||
@@ -40,25 +40,25 @@ end
|
||||
|
||||
fp = QueryFilter();
|
||||
% fp.where('Runs', 'run_id','EQUALS', 2776);
|
||||
M = 4;
|
||||
M = 6;
|
||||
fp.where('Runs', 'pam_level','EQUALS', M);
|
||||
fp.where('Runs', 'bitrate','EQUALS', 390e9);%360,390
|
||||
% fp.where('Runs', 'bitrate','EQUALS', 390e9);%360,390
|
||||
% fp.where('Runs', 'symbolrate','EQUALS', 195e9);
|
||||
fp.where('Runs', 'fiber_length','EQUALS', 2);
|
||||
% fp.where('Runs', 'is_mpi','EQUALS', 0);
|
||||
fp.where('Runs', 'fiber_length','EQUALS', 10);
|
||||
fp.where('Runs', 'is_mpi','EQUALS', 0);
|
||||
% fp.where('Runs', 'interference_path_length','EQUALS', 1000);
|
||||
% fp.where('Runs', 'loop_id','GREATER_THAN', 11);
|
||||
% fp.where('Runs', 'sir','EQUALS',18);
|
||||
fp.where('Runs', 'wavelength','EQUALS', 1310);
|
||||
% fp.where('Runs', 'wavelength','EQUALS', 1310);
|
||||
fp.where('Runs', 'db_mode','EQUALS', 0);
|
||||
fp.where('Runs', 'rop_attenuation','EQUAL', 0);
|
||||
% fp.where('Runs', 'power_pd_in','GREATER_THAN', 7);
|
||||
% fp.where('Runs', 'power_pd_in','LESS_THAN', 7);
|
||||
|
||||
[dataTable,~] = db.queryDB(fp, db.getTableFieldNames('Runs'));
|
||||
|
||||
% === Set LOOPS & Initialize DataStorage ===
|
||||
dsp_options.parameters = struct();
|
||||
% dsp_options.parameters.pf_ncoeffs = [1,2];%[0,logspace(-4,0,10)];
|
||||
% dsp_options.parameters.pf_ncoeffs = [1,2];%s[0,logspace(-4,0,10)];
|
||||
|
||||
wh = DataStorage(dsp_options.parameters);
|
||||
wh.addStorage("ffe_package");
|
||||
@@ -70,10 +70,7 @@ wh.addStorage("mlmlse_package");
|
||||
|
||||
%% === RUN IT ===
|
||||
|
||||
[results,wh] = submitJobs(dataTable.run_id(:), dsp_options, "serial", 'wh', wh, 'waitbar', true);
|
||||
|
||||
|
||||
|
||||
[results,wh] = submitJobs(dataTable.run_id(:), dsp_options, "parallel", 'wh', wh, 'waitbar', true);
|
||||
|
||||
|
||||
|
||||
|
||||
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;
|
||||
fdac = 256e9;
|
||||
random_key = 0;
|
||||
M = 4;
|
||||
pams = [4];
|
||||
|
||||
if (db_precode==1)&&(db_coding_approach==0)
|
||||
cols = cbrewer2('Paired',6);
|
||||
for i = 1:length(pams)
|
||||
M = pams(i);
|
||||
if (db_precode==1)&&(db_coding_approach==0)
|
||||
|
||||
if M == 4
|
||||
pulsef=1;
|
||||
precomp_amp_max = -50;
|
||||
elseif M == 6
|
||||
pulsef=0;
|
||||
precomp_amp_max = -50;
|
||||
elseif M == 8
|
||||
pulsef=0;
|
||||
precomp_amp_max = -50;
|
||||
if M == 4
|
||||
pulsef=1;
|
||||
precomp_amp_max = -50;
|
||||
fsym = 196e9;
|
||||
elseif M == 6
|
||||
pulsef=0;
|
||||
precomp_amp_max = -50;
|
||||
fsym = 180e9;
|
||||
elseif M == 8
|
||||
pulsef=0;
|
||||
precomp_amp_max = -50;
|
||||
fsym = 160e9;
|
||||
end
|
||||
|
||||
elseif (db_precode==1)&&(db_coding_approach==1)
|
||||
|
||||
if M == 4
|
||||
pulsef=1;
|
||||
precomp_amp_max = -38;
|
||||
pulsef = 1;
|
||||
elseif M == 6
|
||||
pulsef=0;
|
||||
precomp_amp_max = -38;
|
||||
pulsef = 1;
|
||||
elseif M == 8
|
||||
pulsef=0;
|
||||
precomp_amp_max = -38;
|
||||
pulsef = 1;
|
||||
end
|
||||
|
||||
elseif (db_precode==0)&&(db_coding_approach==0)
|
||||
|
||||
if M == 4
|
||||
pulsef=1;
|
||||
precomp_amp_max = -37;
|
||||
pulsef = 1;
|
||||
fsym = 196e9;
|
||||
elseif M == 6
|
||||
pulsef=0;
|
||||
precomp_amp_max = -34;
|
||||
pulsef = 1;
|
||||
fsym = 180e9;
|
||||
elseif M == 8
|
||||
pulsef=0;
|
||||
precomp_amp_max = -34;
|
||||
pulsef = 0;
|
||||
fsym = 160e9;
|
||||
end
|
||||
end
|
||||
|
||||
elseif (db_precode==1)&&(db_coding_approach==1)
|
||||
|
||||
if M == 4
|
||||
pulsef=1;
|
||||
precomp_amp_max = -38;
|
||||
pulsef = 1;
|
||||
elseif M == 6
|
||||
pulsef=0;
|
||||
precomp_amp_max = -38;
|
||||
pulsef = 1;
|
||||
elseif M == 8
|
||||
pulsef=0;
|
||||
precomp_amp_max = -38;
|
||||
pulsef = 1;
|
||||
rcalpha = 0.05;
|
||||
Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rrc","pulselength",16,"alpha",rcalpha);
|
||||
|
||||
Pamsource = PAMsource(...
|
||||
"fsym",fsym,"M",M,"order",19,"useprbs",0,...
|
||||
"fs_out",fdac,...
|
||||
"applyclipping",0,"clipfactor",1.2,...
|
||||
"applypulseform",pulsef,"pulseformer",Pform,...
|
||||
"randkey",random_key,...
|
||||
"db_precode",db_precode,"db_encode",db_coding_approach,...
|
||||
"mrds_code",0,"mrds_blocklength",512);
|
||||
|
||||
[Digi_sig,Symbols,Bits] = Pamsource.process();
|
||||
|
||||
Digi_sig = Digi_sig.normalize("mode","rms");
|
||||
|
||||
precomp_est = ChannelFreqResp("Nacq",2048,"Navg",100,"Ncp",63,'f_ref',Digi_sig.fs);
|
||||
|
||||
% maxampdb = [-30:-3:-50,precomp_amp_max];
|
||||
maxampdb = precomp_amp_max;%sort(maxampdb);
|
||||
cols_ = cbrewer2('spectral',15);
|
||||
|
||||
for j = 1:length(maxampdb)
|
||||
|
||||
if maxampdb(j) == precomp_amp_max
|
||||
color=clr.Set1.green;
|
||||
else
|
||||
color=cols_(j,:);
|
||||
end
|
||||
|
||||
Digi_sig_pre = precomp_est.precomp(Digi_sig,'maxampdb',maxampdb(j),'loadPath',precomp_path,'fileName',precomp_fn);
|
||||
|
||||
% Digi_sig_pre = Digi_sig_pre.normalize("mode","rms");
|
||||
|
||||
Digi_sig_pre = Digi_sig_pre.resample("fs_out",fdac);
|
||||
|
||||
Digi_sig_pre= Digi_sig_pre.normalize("mode","rms");
|
||||
|
||||
Digi_sig_pre.spectrum("displayname","Strong Precomp","fignum",2223,"normalizeToNyquist",0,"normalizeTo0dB",0,"color",color,"linestyle",'-','addDCoffset',27);
|
||||
|
||||
end
|
||||
|
||||
elseif (db_precode==0)&&(db_coding_approach==0)
|
||||
Digi_sig.spectrum("displayname","No Precomp","fignum",2223,"normalizeToNyquist",0,"normalizeTo0dB",0,"color",cols(2*i,:),"linestyle",'-','addDCoffset',27);
|
||||
|
||||
if M == 4
|
||||
pulsef=1;
|
||||
precomp_amp_max = -37;
|
||||
pulsef = 1;
|
||||
elseif M == 6
|
||||
pulsef=0;
|
||||
precomp_amp_max = -34;
|
||||
pulsef = 1;
|
||||
elseif M == 8
|
||||
pulsef=0;
|
||||
precomp_amp_max = -34;
|
||||
pulsef = 0;
|
||||
end
|
||||
end
|
||||
|
||||
ylim([-25,10]);
|
||||
xlim([0,105]);
|
||||
xticks(0:20:110);
|
||||
yticks(-30:10:10);
|
||||
|
||||
rcalpha = 0.05;
|
||||
Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rrc","pulselength",16,"alpha",rcalpha);
|
||||
|
||||
Pamsource = PAMsource(...
|
||||
"fsym",fsym,"M",M,"order",19,"useprbs",0,...
|
||||
"fs_out",fdac,...
|
||||
"applyclipping",0,"clipfactor",1.2,...
|
||||
"applypulseform",pulsef,"pulseformer",Pform,...
|
||||
"randkey",random_key,...
|
||||
"db_precode",db_precode,"db_encode",db_coding_approach,...
|
||||
"mrds_code",0,"mrds_blocklength",512);
|
||||
|
||||
[Digi_sig,Symbols,Bits] = Pamsource.process();
|
||||
|
||||
Digi_sig = Digi_sig.normalize("mode","rms");
|
||||
|
||||
Digi_sig.spectrum("displayname","No Precomp","fignum",2223,"normalizeToNyquist",0,"normalizeTo0dB",0);
|
||||
|
||||
precomp_est = ChannelFreqResp("Nacq",2048,"Navg",100,"Ncp",63,'f_ref',Digi_sig.fs);
|
||||
|
||||
Digi_sig = precomp_est.precomp(Digi_sig,'maxampdb',precomp_amp_max,'loadPath',precomp_path,'fileName',precomp_fn);
|
||||
|
||||
Digi_sig = Digi_sig.normalize("mode","rms");
|
||||
|
||||
Digi_sig = Digi_sig.resample("fs_out",fdac);
|
||||
|
||||
Digi_sig= Digi_sig.normalize("mode","rms");
|
||||
|
||||
Digi_sig.spectrum("displayname","Strong Precomp","fignum",2223,"normalizeToNyquist",0,"normalizeTo0dB",0);
|
||||
|
||||
ylim([-30,3]);
|
||||
xlim([-5,100]);
|
||||
fig = gcf;
|
||||
pos = [536.3333 879 450 222];
|
||||
set(fig, 'Position', pos);
|
||||
@@ -30,7 +30,7 @@ for l = 1:numel(lambda_vals)
|
||||
for m = 1:numel(M_vals)
|
||||
|
||||
ber_ffe = wh.getStoValue('ber_ffe',v_bias_vals,awg_vpp_vals(1),precomp_amp_max_vals(1),rop_atten_vals(1),M_vals(m),lambda_vals(l));
|
||||
ber = wh.getStoValue('ber_collect',v_bias_vals,awg_vpp_vals(1),precomp_amp_max_vals(1),rop_atten_vals(1),M_vals(m),lambda_vals(l));
|
||||
ber = wh.getStoValue('ber_ffe',v_bias_vals,awg_vpp_vals(1),precomp_amp_max_vals(1),rop_atten_vals(1),M_vals(m),lambda_vals(l));
|
||||
exfo = wh.getStoValue('exfo',v_bias_vals,awg_vpp_vals(1),precomp_amp_max_vals(1),rop_atten_vals(1),M_vals(m),lambda_vals(l));
|
||||
|
||||
lb = wh.getStoValue('exfo',v_bias_vals,awg_vpp_vals(1),precomp_amp_max_vals(1),rop_atten_vals(1),M_vals(m),lambda_vals(l));
|
||||
|
||||
Reference in New Issue
Block a user