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