Final MPI Calculations here

This commit is contained in:
Silas Oettinghaus
2026-07-14 11:50:22 +02:00
parent f421348e5b
commit 8c4edf2490
8 changed files with 1003 additions and 12 deletions

View File

@@ -0,0 +1,254 @@
%% BER over SIR from MpiReductionResults
% 1) gather data from the database
% 2) clean data and remove per-curve outliers
% 3) plot BER over SIR grouped by algorithm
clear; clc;
%% 1) Gather data
studyName = "pam4_112_greater_3153";
pathLengthToPlot = 0;
selectedBlockUpdate = 1; % set [] to pool all block_update values
selectedPamLevels = []; % set [] to use all PAM levels in the query result
selectedAlgorithms = []; % set [] to use all algorithms in the query result
useBoundedLines = true;
usePolyfit = true;
polyfitOrderMax = 4;
maxBerForPlot = 0.1;
db = DBHandler( ...
"dataBase", "labor", ...
"type", "mysql", ...
"server", "192.168.178.192", ...
"user", "silas", ...
"password", "silas");
db.refresh();
fp = QueryFilter();
fp.where('Runs', 'interference_path_length', 'EQUALS', pathLengthToPlot);
fp.where('Runs', 'fiber_length', 'EQUALS', 0);
fp.where('Runs', 'db_mode', 'EQUALS', '"no_db"');
fp.where('MpiReductionResults', 'study_name', 'EQUALS', char(studyName));
if ~isempty(selectedBlockUpdate)
fp.where('MpiReductionResults', 'block_update', 'EQUALS', selectedBlockUpdate);
end
selectedFields = { ...
'Runs.run_id', ...
'Runs.sir', ...
'Runs.pam_level', ...
'Runs.symbolrate', ...
'Runs.interference_path_length', ...
'Runs.power_mpi_interference', ...
'MpiReductionResults.occurrence_idx', ...
'MpiReductionResults.storage_name', ...
'MpiReductionResults.algorithm', ...
'MpiReductionResults.algorithm_variant', ...
'MpiReductionResults.eq_class', ...
'MpiReductionResults.block_update', ...
'MpiReductionResults.BER', ...
'MpiReductionResults.BER_precoded', ...
'MpiReductionResults.SNR', ...
'MpiReductionResults.GMI', ...
'MpiReductionResults.AIR'};
selectedFields = selectedFields(:);
[rawData, query] = db.queryDB(fp, selectedFields);
disp(query);
fprintf("Fetched %d MPI reduction rows.\n", height(rawData));
%% 2) Clean data
data = rawData;
numericFields = ["run_id", "sir", "pam_level", "symbolrate", ...
"interference_path_length", "occurrence_idx", "block_update", ...
"power_mpi_interference", "BER", "BER_precoded", "SNR", "GMI", "AIR"];
for fieldIdx = 1:numel(numericFields)
fieldName = numericFields(fieldIdx);
if ismember(fieldName, string(data.Properties.VariableNames))
data.(char(fieldName)) = numericColumn(data.(char(fieldName)));
end
end
stringFields = ["storage_name", "algorithm", "algorithm_variant", "eq_class"];
for fieldIdx = 1:numel(stringFields)
fieldName = stringFields(fieldIdx);
if ismember(fieldName, string(data.Properties.VariableNames))
data.(char(fieldName)) = stringColumn(data.(char(fieldName)));
end
end
data = data(isfinite(data.BER) & data.BER > 0 & data.BER < maxBerForPlot, :);
data.sir_exact = -7 - data.power_mpi_interference;
if isempty(data)
warning("PLOT_mpi_reduction_db_ber_vs_sir:NoRows", ...
"No rows remain after initial BER/path/study/block filtering.");
return
end
if isempty(selectedPamLevels)
selectedPamLevels = unique(data.pam_level(isfinite(data.pam_level))).';
else
data = data(ismember(data.pam_level, selectedPamLevels), :);
end
if isempty(selectedAlgorithms)
selectedAlgorithms = unique(data.algorithm, "stable").';
else
selectedAlgorithms = string(selectedAlgorithms);
data = data(ismember(data.algorithm, selectedAlgorithms), :);
end
if isempty(data)
warning("PLOT_mpi_reduction_db_ber_vs_sir:NoSelectedRows", ...
"No rows remain after selectedPamLevels/selectedAlgorithms filtering.");
return
end
data.clean_keep = true(height(data), 1);
[groupId, groupPam, groupAlgorithm, groupSir] = findgroups(data.pam_level, data.algorithm, data.sir);
for groupIdx = 1:max(groupId)
rowMask = groupId == groupIdx;
berValues = data.BER(rowMask);
if nnz(rowMask) > 3
data.clean_keep(rowMask) = ~isoutlier(berValues);
end
end
cleanData = data(data.clean_keep, :);
summaryTable = groupsummary(cleanData, ["pam_level", "algorithm", "sir"], ...
{"mean", "min", "max"}, "BER");
sirExactTable = groupsummary(cleanData, ["pam_level", "algorithm", "sir"], ...
"median", "sir_exact");
summaryTable.sir_exact = sirExactTable.median_sir_exact;
summaryTable = sortrows(summaryTable, ["pam_level", "algorithm", "sir"]);
fprintf("Cleaned to %d rows across %d PAM/algorithm/SIR groups.\n", ...
height(cleanData), height(summaryTable));
disp(groupcounts(cleanData, ["pam_level", "algorithm"]));
%% 3) Plot data
if exist("linspecer", "file")
algColors = linspecer(numel(selectedAlgorithms));
else
algColors = lines(numel(selectedAlgorithms));
end
figure(); clf;
tiledlayout(numel(selectedPamLevels), 1, "TileSpacing", "compact");
for pamIdx = 1:numel(selectedPamLevels)
pamLevel = selectedPamLevels(pamIdx);
nexttile; hold on;
for algIdx = 1:numel(selectedAlgorithms)
algorithmName = selectedAlgorithms(algIdx);
algColor = algColors(algIdx, :);
rawMask = cleanData.pam_level == pamLevel & cleanData.algorithm == algorithmName;
curveMask = summaryTable.pam_level == pamLevel & summaryTable.algorithm == algorithmName;
if ~any(curveMask)
continue
end
scatter(cleanData.sir_exact(rawMask), cleanData.BER(rawMask), ...
30, ...
"Marker", ".", ...
"MarkerEdgeColor", algColor, ...
"HandleVisibility", "off");
sirValues = summaryTable.sir_exact(curveMask).';
meanBer = summaryTable.mean_BER(curveMask).';
minBer = summaryTable.min_BER(curveMask).';
maxBer = summaryTable.max_BER(curveMask).';
valid = isfinite(sirValues) & isfinite(meanBer) & meanBer > 0;
if useBoundedLines && exist("boundedline", "file") && any(valid)
yLower = max(meanBer - minBer, 0);
yUpper = max(maxBer - meanBer, 0);
yBounds = [yLower(:), yUpper(:)];
[hl, hp] = boundedline(sirValues(valid).', meanBer(valid).', yBounds(valid, :), ...
'alpha', 'transparency', 0.08, ...
'cmap', algColor, ...
'nan', 'fill', ...
'orientation', 'vert');
set(hl, "LineStyle", "none", "Marker", "none", "HandleVisibility", "off");
set(hp, "LineStyle", "none", "HandleVisibility", "off");
end
plot(sirValues(valid), meanBer(valid), ...
"LineStyle", "none", ...
"Marker", "o", ...
"MarkerSize", 5, ...
"LineWidth", 1.2, ...
"Color", algColor, ...
"MarkerFaceColor", algColor, ...
"DisplayName", char(algorithmName));
if usePolyfit
fitMask = valid & meanBer > 0;
if nnz(fitMask) >= 2
fitOrder = min(polyfitOrderMax, nnz(fitMask) - 1);
fitCoeff = polyfit(sirValues(fitMask), log10(meanBer(fitMask)), fitOrder);
xFit = linspace(min(sirValues(fitMask)), max(sirValues(fitMask)), 300);
yFit = 10 .^ polyval(fitCoeff, xFit);
plot(xFit, yFit, ...
"LineStyle", "--", ...
"LineWidth", 1.1, ...
"Color", algColor, ...
"HandleVisibility", "off");
end
end
end
yline(2.2e-4, "LineWidth", 1, "LineStyle", "--", "HandleVisibility", "off");
yline(3.8e-3, "LineWidth", 1, "LineStyle", "--", "HandleVisibility", "off");
yline(2e-2, "LineWidth", 1, "LineStyle", "--", "HandleVisibility", "off");
title(sprintf("PAM %.0f, path %.0f m, block update %s", ...
pamLevel, pathLengthToPlot, blockUpdateLabel(selectedBlockUpdate)));
xlabel("SIR (dB)");
ylabel("BER");
set(gca, "YScale", "log");
ylim([9e-5, maxBerForPlot]);
grid on;
box on;
legend("Location", "best", "Interpreter", "none");
end
if exist("beautifyBERplot", "file")
beautifyBERplot("logscale", true, "setcolors", false, "setmarkers", false);
end
%% 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 values = stringColumn(values)
if iscell(values)
values = string(values);
elseif ischar(values)
values = string(values);
end
values = strip(string(values));
end
function label = blockUpdateLabel(selectedBlockUpdate)
if isempty(selectedBlockUpdate)
label = "pooled";
else
label = string(selectedBlockUpdate);
end
end