start with 400G analysis work
This commit is contained in:
294
projects/Diss/400G_revisit/PLOT_BER_VS_ALGO.m
Normal file
294
projects/Diss/400G_revisit/PLOT_BER_VS_ALGO.m
Normal file
@@ -0,0 +1,294 @@
|
||||
%% 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
|
||||
Reference in New Issue
Block a user