halfway merged and pulled?!

This commit is contained in:
Silas Labor Zizou
2025-12-15 15:41:02 +01:00
parent 7d0a634b87
commit b8cecae895
145 changed files with 19835 additions and 0 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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' ...
% });

View File

@@ -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];

View File

@@ -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}',...
});

View File

@@ -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;
% =======================================================================
% (24) 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

View File

@@ -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

View File

@@ -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 ===

View File

@@ -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);

View File

@@ -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

View File

@@ -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' ...
});

View File

@@ -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

View File

@@ -0,0 +1,240 @@
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','LESS_THAN', 1312);
% 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 = '-';
%% PLOT NGMI
% Common cfg
cfg.show_precoded = 1;
cfg.group_by = {'equalizer_structure','pre_emph'};
cfg.x_axis = 'grossrate';
cfg.y_axis = 'NGMI'; % 'BER' | 'GMI' | 'AIR' | ...
cfg.y_scale = 'lin';
cfg.plot.custom_colors_scatter = [];
cfg.plot.use_cbrewer2 = false;
cfg.fec_lines = [];
cfg.agg = 'max';
cfg.figure_number = 45;
% fig = figure(cfg.figure_number);
lambda = 1310;
% PAM 4
cfg.plot.custom_colors = clr.Paired.red;
cfg.plot.custom_linetypes = {'-'};
cfg.filters = struct('is_mpi',0,'pam_level',4, ...
'equalizer_structure',equalizer_structure.vnle_db_mlse, ...
'pre_emph',0,'wavelength',lambda);
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(grossrates, ...
'NGMI', ngmi_pam4, ...
'BER', BER_VNLE);
cfg.plot.custom_colors = clr.Paired.red;
cfg.plot.custom_linetypes = {'--'};
cfg.filters = struct('is_mpi',0,'pam_level',4, ...
'equalizer_structure',equalizer_structure.vnle_db_mlse, ...
'pre_emph',0,'wavelength',1293);
cfg.show_precoded = 1;
plot_measurements_gpt(dataTable, cfg);
% PAM 6
cfg.plot.custom_colors = clr.Paired.blue;
cfg.plot.custom_linetypes = {'-'};
cfg.filters = struct('is_mpi',0,'pam_level',6, ...
'equalizer_structure',equalizer_structure.vnle_pf_mlse, ...
'pre_emph',1,'wavelength',lambda);
cfg.show_precoded = 0;
plot_measurements_gpt(dataTable, cfg);
cfg.plot.custom_colors = clr.Paired.blue;
cfg.plot.custom_linetypes = {'--'};
cfg.filters = struct('is_mpi',0,'pam_level',6, ...
'equalizer_structure',equalizer_structure.vnle_pf_mlse, ...
'pre_emph',1,'wavelength',1293);
cfg.show_precoded = 0;
plot_measurements_gpt(dataTable, cfg);
% PAM 8
cfg.plot.custom_colors = clr.Paired.green;
cfg.plot.custom_linetypes = {'-'};
cfg.filters = struct('is_mpi',0,'pam_level',8, ...
'equalizer_structure',equalizer_structure.vnle_pf_mlse, ...
'pre_emph',1,'wavelength',lambda);
cfg.show_precoded = 0;
plot_measurements_gpt(dataTable, cfg);
cfg.plot.custom_colors = clr.Paired.green;
cfg.plot.custom_linetypes = {'--'};
cfg.filters = struct('is_mpi',0,'pam_level',8, ...
'equalizer_structure',equalizer_structure.vnle_pf_mlse, ...
'pre_emph',1,'wavelength',1293);
cfg.show_precoded = 0;
plot_measurements_gpt(dataTable, cfg);
beautifyBERplot
ylim([0.87,1.01]);
% xlim([290,480]);
%% PLOT AIR
% Common cfg
cfg.show_precoded = 1;
cfg.group_by = {'equalizer_structure','pre_emph'};
cfg.x_axis = 'grossrate';
cfg.y_axis = 'AIR'; % 'BER' | 'GMI' | 'AIR' | ...
cfg.y_scale = 'lin';
cfg.plot.custom_colors_scatter = [];
cfg.plot.use_cbrewer2 = false;
cfg.fec_lines = [];
cfg.agg = 'max';
cfg.figure_number = 47;
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 = {'-'};
cfg.filters = struct('is_mpi',0,'pam_level',4, ...
'equalizer_structure',equalizer_structure.vnle_db_mlse, ...
'pre_emph',0,'wavelength',lambda);
cfg.show_precoded = 1;
plot_measurements_gpt(dataTable, cfg);
cfg.plot.custom_colors = clr.Paired.red;
cfg.plot.custom_linetypes = {'--'};
cfg.filters = struct('is_mpi',0,'pam_level',4, ...
'equalizer_structure',equalizer_structure.vnle_db_mlse, ...
'pre_emph',0,'wavelength',1293);
cfg.show_precoded = 1;
plot_measurements_gpt(dataTable, cfg);
% PAM 6
cfg.plot.custom_colors = clr.Paired.blue;
cfg.plot.custom_linetypes = {'-'};
cfg.filters = struct('is_mpi',0,'pam_level',6, ...
'equalizer_structure',equalizer_structure.vnle_pf_mlse, ...
'pre_emph',1,'wavelength',lambda);
cfg.show_precoded = 0;
plot_measurements_gpt(dataTable, cfg);
cfg.plot.custom_colors = clr.Paired.blue;
cfg.plot.custom_linetypes = {'--'};
cfg.filters = struct('is_mpi',0,'pam_level',6, ...
'equalizer_structure',equalizer_structure.vnle_pf_mlse, ...
'pre_emph',1,'wavelength',1293);
cfg.show_precoded = 0;
plot_measurements_gpt(dataTable, cfg);
% PAM 8
cfg.plot.custom_colors = clr.Paired.green;
cfg.plot.custom_linetypes = {'-'};
cfg.filters = struct('is_mpi',0,'pam_level',8, ...
'equalizer_structure',equalizer_structure.vnle_pf_mlse, ...
'pre_emph',1,'wavelength',lambda);
cfg.show_precoded = 0;
plot_measurements_gpt(dataTable, cfg);
cfg.plot.custom_colors = clr.Paired.green;
cfg.plot.custom_linetypes = {'--'};
cfg.filters = struct('is_mpi',0,'pam_level',8, ...
'equalizer_structure',equalizer_structure.vnle_pf_mlse, ...
'pre_emph',1,'wavelength',1293);
cfg.show_precoded = 0;
plot_measurements_gpt(dataTable, cfg);
ax = gca;
beautifyBERplot
ylim([275,435]);
xlim([290,480]);
%%

View File

@@ -0,0 +1,112 @@
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_aug_nov_2025')]; %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 = '-';
%%
cfg.figure_number = 42;
% ---- VNLE, no pre-emph (solid red) ----
cfg.plot.custom_colors = [clr.Paired.red];
cfg.plot.custom_linetypes = {'-'};
cfg.filters = struct('is_mpi',0,'pam_level',M, ...
'equalizer_structure',equalizer_structure.vnle, ...
'pre_emph',0);
plot_measurements_gpt(dataTable, cfg);
% ---- VNLE, with pre-emph (dashed red) ----
cfg.plot.custom_colors = [clr.Paired.red];
cfg.plot.custom_linetypes = {'--'};
cfg.filters.pre_emph = 1;
plot_measurements_gpt(dataTable, cfg);
% ---- VNLE PF MLSE, no pre-emph (solid green) ----
cfg.plot.custom_colors = [clr.Paired.green];
cfg.plot.custom_linetypes = {'-'};
cfg.filters.equalizer_structure = equalizer_structure.vnle_pf_mlse;
cfg.filters.pre_emph = 0;
plot_measurements_gpt(dataTable, cfg);
% ---- VNLE PF MLSE, with pre-emph (dashed green) ----
cfg.plot.custom_colors = [clr.Paired.green];
cfg.plot.custom_linetypes = {'--'};
cfg.filters.pre_emph = 1;
plot_measurements_gpt(dataTable, cfg);
% === FEC LINES (no legend) ===
yline([2.2e-4 4.85e-3 2e-2], ...
'LineWidth',1.5,'Color',[0.4 0.4 0.4], ...
'LineStyle',':','HandleVisibility','off');
% === BEAUTIFY ===
% beautifyBERplot; % your function
%% === 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' ...
} );

View File

@@ -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}',...
% });

View File

@@ -0,0 +1,111 @@
dsp_options.storage_path = 'Z:\2024\sioe_labor\';
dsp_options.max_occurences = 1;
database = DBHandler("dataBase", 'labor_highspeed', "type", 'mysql' );
rate = 390e9;
%% 1 - PAM 4 with preemphasis
fp = QueryFilter();
M = 4;
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', 0);
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);
% 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);
if rate == 390e9
Scpe_sig.spectrum("fignum",200,"normalizeTo0dB",1,"displayname",'Rx','addDCoffset',-5.8);
elseif rate == 300e9
Scpe_sig.spectrum("fignum",200,"normalizeTo0dB",1,"displayname",'Rx','addDCoffset',-4.7);
end
ylim([-30,3]);
xlim([-5,100]);
Scpe_sig.spectrum("fignum",201,"normalizeTo0dB",0,"displayname",'Rx');
%% 1 - PAM 4 without preemphasis
fp = QueryFilter();
M = 4;
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', 1);
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);
% 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.spectrum("fignum",200,"normalizeTo0dB",1,"displayname",'Rx','addDCoffset',0);
ylim([-30,3]);
xlim([-5,100]);
Scpe_sig.spectrum("fignum",201,"normalizeTo0dB",0,"displayname",'Rx');
if 1
%% show freuqncy response of filter
measure = 1;
freqresp = ChannelFreqResp("Nacq",1024,"Navg",64,"Ncp",70,"f_ref",256e9);
%
Digi_sig = freqresp.buildOFDM();
% Digi_sig.spectrum("fignum",1112,"displayname",['maxamp:',num2str(maxamp)]);
Digi_sig = Filter('filtdegree',3,"f_cutoff",70e9,"fs",256e9,"filterType",filtertypes.butterworth,"active",true).process(Digi_sig);
Digi_sig = Filter('filtdegree',3,"f_cutoff",70e9,"fs",256e9,"filterType",filtertypes.bessel_inp,"active",true).process(Digi_sig);
freqresp.estimate(Digi_sig,"fileName",'','save',false);
freqresp.plot()
a = gca;
a.YTick = [-30,-20,-10,0];
%% system frex
precomp_filename ='lab_high_speed';
precomp_path = "C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\precomp";
freqresp = ChannelFreqResp("Nacq",1024,"Navg",64,"Ncp",63,'f_ref',92e9);
freqresp.load('loadPath', precomp_path, 'fileName', precomp_filename);
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

View File

@@ -0,0 +1,222 @@
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_gpt(dataTable, cfg);
% [h, M] = plot_measurements_gpt(dataTable, cfg);
%
% For values only, without plotting, call:
% [M, cfg] = analyze_measurements_gpt(dataTable, cfg);
if nargin < 2, cfg = struct; end
% --- 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', ...
'paired_dark_first' , true, ...
'lineWidth' , 1.8, ...
'errWidth' , 1.0, ...
'scatterSize' , 14, ...
'scatterAlpha' , 0.35, ...
'marker' , 'o', ...
'marker_precoded' , 's', ...
'legendLocation' , 'best', ...
'fecLineWidth' , 2.2, ...
'fecColor' , [0.25 0.25 0.25], ...
'capSize' , 6, ...
'lineStyle_default' , '-', ...
'custom_colors' , [], ...
'custom_colors_scatter' , [] ...
);
if ~isfield(cfg,'plot') || isempty(cfg.plot)
cfg.plot = struct;
end
cfg.plot = filldefaults(cfg.plot, plotdefs);
%% ---- Colors ----
[cols_line, cols_scatter] = buildGroupColors(nG, cfg.plot);
%% ---- Axes / Figure handling ----
if isfield(cfg,'ax') && ~isempty(cfg.ax) && isgraphics(cfg.ax,'axes')
ax = cfg.ax;
set(gcf,'CurrentAxes',ax);
else
if isfield(cfg,'figure_number') && ~isempty(cfg.figure_number)
figure(cfg.figure_number);
else
figure;
end
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
g = M.group{gi};
xu = g.x;
yu = g.y;
ylo = g.y_lo;
yhi = g.y_hi;
% --- Linestyle selection ---
ls = cfg.plot.lineStyle_default;
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
colL = cols_line(gi,:);
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
if any(isfinite(ylo)) && any(isfinite(yhi))
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 scatter
if cfg.show_raw
% reuse stored raw data (no extra filtering)
xi = g.x_raw;
yi = g.y_raw;
colS = cols_scatter(gi,:);
scatter(ax, xi, yi, cfg.plot.scatterSize, colS, 'filled', ...
'MarkerFaceAlpha', cfg.plot.scatterAlpha, ...
'MarkerEdgeAlpha', cfg.plot.scatterAlpha, ...
'HandleVisibility','off');
end
% 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(ax, M.y_axis, 'Interpreter','none');
xlabel(ax, M.x_label, 'Interpreter','none');
set(ax, 'YScale', cfg.y_scale, 'FontSize', 11);
% 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(M.y_axis,"BER",'IgnoreCase',true)
for v = cfg.fec_lines
yline(ax, v, '--', 'Color', cfg.plot.fecColor, ...
'LineWidth', cfg.plot.fecLineWidth, 'HandleVisibility','off');
end
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 =====
%% ===================== 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));
end
end
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, :);
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
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
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

View File

@@ -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

View File

@@ -0,0 +1,38 @@
X-Werte;PAM-2;PAM-4;PAM-6;PAM-8;PAM-12
224;204;;;;
205,5;193,4;;;;
205,1;189,7;;;;
192;168;;;;
240;;427,4;;;
225;;420,5;;;
210;;336;;;
184;;332;;;
192;;320;;;
176;;306,0869565;;;
190;;304;;;
168;;294;;;
156,2;;287,1;;;
160,8;;286,9;;;
170;;272;;;
132;;250,9505703;;;
112;;209,3457944;;;
172;;337;;;
216;;;474,6;;
147,2;;;329,9;;
132;;;319,7891753;;
143,1;;;318;;
160;;;377;;
225;;;;562,5;
200;;;;510;
160;;;;438;
180;;;;432;
180;;;;432;
144;;;;384;
143,7;;;;363,4;
144;;;;360;
136;;;;353,859497;
136;;;;342,7995295;
128;;;;329,0488432;
129,7;;;;311,2;
160;;;;413;
160;;;;;481,2
1 X-Werte PAM-2 PAM-4 PAM-6 PAM-8 PAM-12
2 224 204
3 205,5 193,4
4 205,1 189,7
5 192 168
6 240 427,4
7 225 420,5
8 210 336
9 184 332
10 192 320
11 176 306,0869565
12 190 304
13 168 294
14 156,2 287,1
15 160,8 286,9
16 170 272
17 132 250,9505703
18 112 209,3457944
19 172 337
20 216 474,6
21 147,2 329,9
22 132 319,7891753
23 143,1 318
24 160 377
25 225 562,5
26 200 510
27 160 438
28 180 432
29 180 432
30 144 384
31 143,7 363,4
32 144 360
33 136 353,859497
34 136 342,7995295
35 128 329,0488432
36 129,7 311,2
37 160 413
38 160 481,2

View File

@@ -0,0 +1,76 @@
database_type = 'mysql';
dataBase = 'labor_highspeed';%'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\silas_labor_newdsp_newstructure.db';
db = DBHandler("dataBase", [dataBase], "type", database_type);
M = 8;
fp = QueryFilter();
% fp.where('Runs', 'run_id','EQUALS', 987);
fp.where('Runs', 'pam_level','EQUALS', M);
% fp.where('Runs', 'symbolrate','EQUALS', 165e9); %150, 165, 180, 195, 210, 225, 240
fp.where('Runs', 'fiber_length','EQUALS', 2);
% fp.where('Runs', 'is_mpi','EQUALS', 0);
% fp.where('Runs', 'power_pd_in','GREATER_THAN', 7);
% 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', '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.group_by = {'equalizer_structure','pre_emph'};
cfg.filters = struct('is_mpi',0,'pam_level',M,'equalizer_structure',[equalizer_structure.ml_mlse]);%,equalizer_structure.vnle_pf_mlse,equalizer_structure.vnle]);
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.figure_number = 42;
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
plot_measurements_gpt(dataTable, cfg);
% beautifyBERplot()
%% FIG PRE EMPHASIS