Files
imdd_silas/projects/Diss/400G_revisit/PLOT_BER_VS_ALGO.m
2026-07-20 10:22:11 +02:00

295 lines
9.8 KiB
Matlab

%% 400G BER over bitrate from labor_highspeed.dashboard_ungrouped_alltime
% 1) gather all BER entries for one PAM format and fiber length
% 2) derive pre-emphasis and precoding groups
% 3) plot one bitrate-vs-BER tile per equalizer structure
clear; clc;
%% 1) Gather data
selectedPamLevel = 4;
selectedFiberLengthKm = 10;
selectedWavelength =1310; % set [] to use all wavelengths
selectedRopAttenuation = []; % set [] to use all ROP attenuation values
selectedIsMpi = []; % set [] to use all entries
maxBerForPlot = 0.5;
showRawEntries = true;
showMedianLine = true;
eqStyles = defaultEqualizerStyles();
comboStyles = defaultCombinationStyles();
db = DBHandler( ...
"dataBase", "labor_highspeed", ...
"type", "mysql");
db.refresh();
fp = QueryFilter();
fp.where('Runs', 'fiber_length', 'EQUALS', selectedFiberLengthKm);
fp.where('Runs', 'pam_level', 'EQUALS', selectedPamLevel);
if ~isempty(selectedWavelength)
fp.where('Runs', 'wavelength', 'EQUALS', selectedWavelength);
end
if ~isempty(selectedRopAttenuation)
fp.where('Runs', 'rop_attenuation', 'EQUALS', selectedRopAttenuation);
end
if ~isempty(selectedIsMpi)
fp.where('Runs', 'is_mpi', 'EQUALS', selectedIsMpi);
end
selectedFields = db.getTableFieldNames('dashboard_ungrouped_alltime');
selectedFields = [selectedFields; {'Runs.precomp_amp'; 'Runs.is_mpi'}];
selectedFields = selectedFields(:);
[rawData, query] = db.queryDB(fp, selectedFields);
disp(query);
fprintf("Fetched %d 400G result rows.\n", height(rawData));
%% 2) Clean data and derive analysis groups
data = rawData;
numericFields = ["result_id", "run_id", "eq_id", "bitrate", "grossrate", ...
"symbolrate", "pam_level", "wavelength", "fiber_length", "db_mode", ...
"rop_attenuation", "precomp_amp", "is_mpi", "numBits", "numBitErr", ...
"BER", "numBitErr_precoded", "BER_precoded", "STD", "STDrx", ...
"GMI", "AIR", "NGMI", "EVM", "Alpha"];
for fieldIdx = 1:numel(numericFields)
fieldName = numericFields(fieldIdx);
if ismember(fieldName, string(data.Properties.VariableNames))
data.(char(fieldName)) = numericColumn(data.(char(fieldName)));
end
end
if ~ismember("precomp_amp", string(data.Properties.VariableNames))
warning("analyze_db:NoPrecompAmp", ...
"Runs.precomp_amp was not returned. Falling back to pre_emphasis = (db_mode == 0).");
data.pre_emphasis = data.db_mode == 0;
else
data.pre_emphasis = derivePreEmphasis(data.precomp_amp, data.db_mode);
end
plotData = buildBerMetricRows(data);
plotData = plotData(isfinite(plotData.BER_plot) & ...
plotData.BER_plot > 0 & plotData.BER_plot < maxBerForPlot, :);
if isempty(plotData)
warning("analyze_db:NoRows", ...
"No rows remain after fiber/PAM/BER filtering.");
return
end
plotData.bitrate_Gbps = plotData.bitrate .* 1e-9;
plotData.grossrate_Gbps = plotData.grossrate .* 1e-9;
fprintf("Remaining plotted BER rows: %d\n", height(plotData));
disp(groupcounts(plotData, ["equalizer_structure", "pre_emphasis", "precode"]));
bestPlotData = bestBerByBitrateAndGroup(plotData);
fprintf("Keeping %d best-BER rows across bitrate/EQ/pre-emphasis/precode groups.\n", ...
height(bestPlotData));
%% 3) Plot bitrate versus BER
availableEqStyles = eqStyles(hasEqualizerRows(bestPlotData, eqStyles), :);
if isempty(availableEqStyles)
warning("analyze_db:NoSelectedEqualizers", ...
"None of the configured equalizer styles match the queried rows.");
return
end
fig = figure(401); clf;
tiledlayout(1, height(availableEqStyles), ...
"TileSpacing", "compact", ...
"Padding", "compact");
for eqIdx = 1:height(availableEqStyles)
eqStyle = availableEqStyles(eqIdx, :);
ax = nexttile; hold(ax, "on");
eqMask = equalizerMask(bestPlotData.equalizer_structure, eqStyle.eq);
for comboIdx = 1:height(comboStyles)
comboStyle = comboStyles(comboIdx, :);
rowMask = eqMask & ...
bestPlotData.pre_emphasis == comboStyle.pre_emphasis & ...
bestPlotData.precode == comboStyle.precode;
if ~any(rowMask)
continue
end
comboData = sortrows(bestPlotData(rowMask, :), "bitrate_Gbps");
comboColor = emphasisColor(eqStyle.color, comboStyle.pre_emphasis);
label = sprintf("%s, %s", eqStyle.name, comboStyle.name);
if showRawEntries
scatter(ax, comboData.bitrate_Gbps, comboData.BER_plot, ...
5, ...
"Marker", '.', ...
"MarkerEdgeColor", comboColor, ...
"MarkerFaceColor", comboColor, ...
"MarkerEdgeAlpha", 0.25, ...
"MarkerFaceAlpha", 0.25, ...
"HandleVisibility", "off");
end
if showMedianLine
summaryTable = summarizeBerByBitrate(comboData);
plot(ax, summaryTable.bitrate_Gbps, summaryTable.median_BER_plot, ...
"LineStyle", comboStyle.lineStyle, ...
"Marker", eqStyle.marker, ...
"MarkerSize", 4, ...
"LineWidth", 1.4, ...
"Color", comboColor, ...
"MarkerFaceColor", comboStyle.markerFaceColor, ...
"MarkerEdgeColor", comboColor, ...
"DisplayName", label);
end
end
yline(ax, [2.2e-4, 4.85e-3, 2e-2], ...
"LineWidth", 1, ...
"LineStyle", "--", ...
"Color", [0.25 0.25 0.25], ...
"HandleVisibility", "off");
title(ax, sprintf("PAM-%d, %s", selectedPamLevel, eqStyle.name));
xlabel(ax, "Gross rate [Gb/s]");
ylabel(ax, "BER");
set(ax, "YScale", "log");
ylim(ax, [1e-5, maxBerForPlot]);
grid(ax, "on");
box(ax, "on");
xTicks = unique(bestPlotData.bitrate_Gbps(isfinite(bestPlotData.bitrate_Gbps)));
if ~isempty(xTicks)
xticks(ax, xTicks);
xlim(ax, [min(xTicks), max(xTicks)]);
end
legend(ax, "Location", "best", "Interpreter", "none");
if exist("beautifyBERplot", "file")
beautifyBERplot("logscale", true, "setcolors", false, ...
"setmarkers", false, "changemarkers", false);
end
end
set(fig, "Position", 1e3 .* [0.1000 0.5500 1.4113 0.3200]);
%% Local helpers
function values = numericColumn(values)
if iscell(values)
values = string(values);
end
if isstring(values) || ischar(values)
values = str2double(values);
end
values = double(values);
end
function styles = defaultEqualizerStyles()
styles = table( ...
[equalizer_structure.vnle; ...
equalizer_structure.vnle_pf_mlse; ...
equalizer_structure.vnle_db_mlse; ...
equalizer_structure.ml_mlse], ...
["VNLE"; ...
"VNLE + PF + MLSE"; ...
"VNLE DBt. + MLSE"; ...
"ML pre-EQ + Viterbi"], ...
["o"; "square"; "diamond"; "^"], ...
[clr.Paired.red; ...
clr.Paired.green; ...
clr.Paired.blue; ...
clr.Paired.purple], ...
'VariableNames', ["eq", "name", "marker", "color"]);
end
function styles = defaultCombinationStyles()
styles = table( ...
[true; true; false; false], ...
[true; false; true; false], ...
["w/ pre-emph., w/ precode"; ...
"w/ pre-emph., w/o precode"; ...
"w/o pre-emph., w/ precode"; ...
"w/o pre-emph., w/o precode"], ...
["--"; "-"; "--"; "-"], ...
["w"; "w"; "none"; "none"], ...
'VariableNames', ["pre_emphasis", "precode", "name", ...
"lineStyle", "markerFaceColor"]);
end
function preEmphasis = derivePreEmphasis(precompAmp, dbMode)
preEmphasis = false(size(dbMode));
validPrecomp = isfinite(precompAmp);
% In the 400G measurement scripts, -50 dB is the low/no-pre-emphasis
% setting, while -38/-37/-34 dB are the active pre-emphasis settings.
preEmphasis(validPrecomp) = precompAmp(validPrecomp) > -45;
missingPrecomp = ~validPrecomp;
preEmphasis(missingPrecomp) = dbMode(missingPrecomp) == 0;
end
function plotData = buildBerMetricRows(data)
baseRows = data(isfinite(data.BER), :);
baseRows.precode = false(height(baseRows), 1);
baseRows.BER_plot = baseRows.BER;
if ismember("BER_precoded", string(data.Properties.VariableNames))
precodedRows = data(isfinite(data.BER_precoded), :);
precodedRows.precode = true(height(precodedRows), 1);
precodedRows.BER_plot = precodedRows.BER_precoded;
plotData = [baseRows; precodedRows];
else
warning("analyze_db:NoPrecodedBer", ...
"BER_precoded was not returned. Plotting only precode = 0 rows.");
plotData = baseRows;
end
end
function mask = equalizerMask(equalizerColumn, eqValue)
if isa(equalizerColumn, "equalizer_structure")
mask = equalizerColumn == eqValue;
elseif isnumeric(equalizerColumn)
mask = double(equalizerColumn) == double(int32(eqValue));
else
mask = string(equalizerColumn) == string(eqValue);
end
end
function keep = hasEqualizerRows(data, eqStyles)
keep = false(height(eqStyles), 1);
for idx = 1:height(eqStyles)
keep(idx) = any(equalizerMask(data.equalizer_structure, eqStyles.eq(idx)));
end
end
function summaryTable = summarizeBerByBitrate(data)
summaryTable = groupsummary(data, "bitrate_Gbps", "median", "BER_plot");
summaryTable = sortrows(summaryTable, "bitrate_Gbps");
end
function bestData = bestBerByBitrateAndGroup(data)
groupVars = ["equalizer_structure", "pre_emphasis", "precode", "bitrate_Gbps"];
groupId = findgroups(data(:, groupVars));
keepIdx = NaN(max(groupId), 1);
for curGroup = 1:max(groupId)
rowIdx = find(groupId == curGroup);
[~, localBestIdx] = min(data.BER_plot(rowIdx));
keepIdx(curGroup) = rowIdx(localBestIdx);
end
bestData = sortrows(data(keepIdx, :), groupVars);
end
function color = emphasisColor(baseColor, preEmphasis)
if preEmphasis
color = 0.65 .* baseColor + 0.35;
else
color = baseColor;
end
end