new plots for Diss. Mostly AI gen. Few changes in actual codebase
This commit is contained in:
384
projects/Diss/400G_revisit/PLOT_EYES_400G_REVISIT.m
Normal file
384
projects/Diss/400G_revisit/PLOT_EYES_400G_REVISIT.m
Normal file
@@ -0,0 +1,384 @@
|
||||
%% 400G revisit: eye comparison for PAM-4/6/8
|
||||
% The native Signal.eye() method is used for the eye display. Optional TikZ
|
||||
% export is configured below and uses mat2tikz_improved().
|
||||
%
|
||||
% db_mode_setting:
|
||||
% 0 - no duobinary processing; use the copied FFE configuration
|
||||
% 1 - DB-targeted VNLE; the VNLE target is Duobinary().encode(Symbols)
|
||||
% 2 - DB-encoded data; equalize the stored DB-encoded Symbols with a VNLE
|
||||
|
||||
clc;
|
||||
|
||||
%% Configuration
|
||||
M_values = [4];
|
||||
selectedBitrate = 360e9;
|
||||
selectedFiberLengthKm = 10;
|
||||
selectedWavelengthNm = 1310;
|
||||
selectedRopAttenuation = 0;
|
||||
selectedIsMpi = 0;
|
||||
db_mode_setting = 2; % Set to 0, 1, or 2.
|
||||
|
||||
average_signals = 1;
|
||||
show_histograms = true;
|
||||
export_tikz = 0;
|
||||
max_occurences = 10;
|
||||
histogram_figure_base = 600;
|
||||
eye_figure_base = 500;
|
||||
psd_figure_base = 700;
|
||||
|
||||
% PSD colors follow the established DSP algorithm styles. The target is
|
||||
% black and the received waveform is grey.
|
||||
dsp_styles = defaultAlgorithmStyles();
|
||||
psd_color_target = [0, 0, 0];
|
||||
psd_color_received = [0.3500, 0.3500, 0.3500];
|
||||
psd_color_equalized = dsp_styles.color(dsp_styles.algorithm_key == "vnle", :);
|
||||
|
||||
tikz_root = 'C:\Users\Silas\Documents\6971e0b65b380ca6d71c837f\04_Experimental_Evaluation\tikz\400g';
|
||||
tikz_eye_folder = fullfile(tikz_root, 'eyes');
|
||||
tikz_histogram_folder = fullfile(tikz_root, 'histograms');
|
||||
tikz_psd_folder = fullfile(tikz_root, 'psd');
|
||||
|
||||
% The averaging/gain/normalization follows FIGURE_EYES.m.
|
||||
average_gain = 1.25;
|
||||
|
||||
% Common equalizer parameters copied from FIGURE_EYES.m.
|
||||
len_tr = 4096*2;
|
||||
training_loops = 5;
|
||||
dd_loops = 5;
|
||||
eq_K = 2;
|
||||
mu_dc = 0.005;
|
||||
mu_ffe = [0.0001, 0.0008, 0.001];
|
||||
mu_dfe = 0.0004;
|
||||
|
||||
if ~ismember(db_mode_setting, [0, 1, 2])
|
||||
error('PLOT_EYES_400G_REVISIT:InvalidDbMode', ...
|
||||
'db_mode_setting must be 0, 1, or 2.');
|
||||
end
|
||||
|
||||
if export_tikz
|
||||
if ~exist(tikz_eye_folder, 'dir')
|
||||
mkdir(tikz_eye_folder);
|
||||
end
|
||||
if ~exist(tikz_histogram_folder, 'dir')
|
||||
mkdir(tikz_histogram_folder);
|
||||
end
|
||||
if ~exist(tikz_psd_folder, 'dir')
|
||||
mkdir(tikz_psd_folder);
|
||||
end
|
||||
end
|
||||
|
||||
%% Database setup
|
||||
dsp_options = struct();
|
||||
dsp_options.storage_path = 'W:\labdata\sioe_labor\';
|
||||
dsp_options.start_occurence = 1;
|
||||
dsp_options.max_occurences = max_occurences;
|
||||
|
||||
database = DBHandler( ...
|
||||
"dataBase", "labor_highspeed", ...
|
||||
"type", "mysql", ...
|
||||
"server", "192.168.178.192", ...
|
||||
"user", "silas", ...
|
||||
"password", "silas");
|
||||
|
||||
%% DSP phase: query, synchronize, equalize, and collect all signals
|
||||
selectedRuns = [];
|
||||
eyeSignals = cell(size(M_values));
|
||||
rawSignals = cell(size(M_values));
|
||||
eyeReferences = cell(size(M_values));
|
||||
symbolRates = NaN(size(M_values));
|
||||
|
||||
for mIdx = 1:numel(M_values)
|
||||
M = M_values(mIdx);
|
||||
|
||||
fp = QueryFilter();
|
||||
fp.where('Runs', 'fiber_length', 'EQUALS', selectedFiberLengthKm);
|
||||
fp.where('Runs', 'wavelength', 'EQUALS', selectedWavelengthNm);
|
||||
fp.where('Runs', 'rop_attenuation', 'EQUALS', selectedRopAttenuation);
|
||||
fp.where('Runs', 'is_mpi', 'EQUALS', selectedIsMpi);
|
||||
fp.where('Runs', 'pam_level', 'EQUALS', M);
|
||||
fp.where('Runs', 'db_mode', 'EQUALS', db_mode_setting);
|
||||
if ~isempty(selectedBitrate)
|
||||
fp.where('Runs', 'bitrate', 'EQUALS', selectedBitrate);
|
||||
end
|
||||
|
||||
[dataTable, ~] = database.queryDB(fp, database.getTableFieldNames('Runs'));
|
||||
if isempty(dataTable)
|
||||
error('PLOT_EYES_400G_REVISIT:MissingRun', ...
|
||||
'No run found for PAM-%d with the selected filters.', M);
|
||||
end
|
||||
|
||||
dataTable = sortrows(dataTable, {'bitrate', 'run_id'});
|
||||
dataTable = dataTable(1, :);
|
||||
if isempty(selectedRuns)
|
||||
selectedRuns = dataTable;
|
||||
else
|
||||
selectedRuns = [selectedRuns; dataTable]; %#ok<AGROW>
|
||||
end
|
||||
|
||||
fsym = double(dataTable.symbolrate(1));
|
||||
symbolRates(mIdx) = fsym;
|
||||
[~, Symbols, Scpe_cell, found_sync] = ...
|
||||
loadAndSyncRunSignals(dataTable, dsp_options);
|
||||
|
||||
if ~found_sync || isempty(Scpe_cell)
|
||||
error('PLOT_EYES_400G_REVISIT:SynchronizationFailed', ...
|
||||
'Could not synchronize the selected PAM-%d run.', M);
|
||||
end
|
||||
|
||||
Scpe_sig = averageScopeSignals(Scpe_cell, average_signals, average_gain);
|
||||
Scpe_sig = preprocessSignal(Scpe_sig, Symbols, fsym);
|
||||
Scpe_sig = Scpe_sig.normalize("mode", "rms");
|
||||
|
||||
switch db_mode_setting
|
||||
case 0
|
||||
% Simply FFE, copied from FIGURE_EYES.m.
|
||||
eq_ = EQ("Ne", [50, 0, 0], ...
|
||||
"Nb", [0, 0, 0], ...
|
||||
"training_length", len_tr, ...
|
||||
"training_loops", training_loops, ...
|
||||
"dd_loops", dd_loops, ...
|
||||
"K", eq_K, ...
|
||||
"DCmu", mu_dc, ...
|
||||
"DDmu", [mu_ffe, mu_dfe], ...
|
||||
"DFEmu", 0.005, ...
|
||||
"FFEmu", 0, ...
|
||||
"plotfinal", 0, ...
|
||||
"ideal_dfe", false);
|
||||
referenceForEye = Symbols;
|
||||
|
||||
case 1
|
||||
% DB-targeted VNLE: train against the DB waveform generated
|
||||
% from the stored (precoded but not DB-encoded) symbols.
|
||||
eq_ = makeVnle(len_tr, training_loops, dd_loops, eq_K, ...
|
||||
mu_dc, mu_ffe, mu_dfe);
|
||||
referenceForEye = Duobinary().encode(Symbols, "M", M);
|
||||
|
||||
case 2
|
||||
% DB-encoded data: the stored Symbols already contain the DB
|
||||
% encoded reference waveform used by the VNLE.
|
||||
eq_ = makeVnle(len_tr, training_loops, dd_loops, eq_K, ...
|
||||
mu_dc, mu_ffe, mu_dfe);
|
||||
referenceForEye = Symbols;
|
||||
end
|
||||
|
||||
[equalized_signal, ~] = eq_.process(Scpe_sig, referenceForEye);
|
||||
eyeSignals{mIdx} = equalized_signal;
|
||||
rawSignals{mIdx} = Scpe_sig;
|
||||
eyeReferences{mIdx} = referenceForEye;
|
||||
|
||||
fprintf('PAM-%d: run %d, %.3f GBd, db_mode %d\n', ...
|
||||
M, dataTable.run_id(1), fsym*1e-9, db_mode_setting);
|
||||
end
|
||||
|
||||
|
||||
%% Plotting and export phase
|
||||
show_histograms = 1;
|
||||
showEye = 1;
|
||||
showPSD = 1;
|
||||
|
||||
for mIdx = 1:numel(M_values)
|
||||
M = M_values(mIdx);
|
||||
fsym = symbolRates(mIdx);
|
||||
rawSignal = rawSignals{mIdx};
|
||||
equalized_signal = eyeSignals{mIdx};
|
||||
referenceForEye = eyeReferences{mIdx};
|
||||
|
||||
if showPSD
|
||||
psdFigure = psd_figure_base + mIdx + db_mode_setting;
|
||||
figure(psdFigure); clf;
|
||||
|
||||
switch db_mode_setting
|
||||
case 0
|
||||
referencePsdName = sprintf('PAM-%d reference', M);
|
||||
equalizedPsdName = 'FFE output';
|
||||
psd_color_equalized = dsp_styles.color( ...
|
||||
dsp_styles.algorithm_key == "vnle", :);
|
||||
case 1
|
||||
referencePsdName = 'DB-target reference';
|
||||
equalizedPsdName = 'DB-targeted VNLE output';
|
||||
psd_color_equalized = dsp_styles.color( ...
|
||||
dsp_styles.algorithm_key == "vnle_db_mlse", :);
|
||||
case 2
|
||||
referencePsdName = 'DB-encoded reference';
|
||||
equalizedPsdName = 'DB-encoded VNLE output';
|
||||
psd_color_equalized = dsp_styles.color( ...
|
||||
dsp_styles.algorithm_key == "db_encoded", :);
|
||||
end
|
||||
|
||||
referenceForEye.spectrum( ...
|
||||
"fignum", psdFigure, ...
|
||||
"show_onesided", 1, ...
|
||||
"fft_length", 4096, ...
|
||||
"displayname", referencePsdName, ...
|
||||
"color", psd_color_target);
|
||||
rawSignal.spectrum( ...
|
||||
"fignum", psdFigure, ...
|
||||
"show_onesided", 1, ...
|
||||
"fft_length", 4096, ...
|
||||
"displayname", 'Received signal', ...
|
||||
"color", psd_color_received);
|
||||
equalized_signal.spectrum( ...
|
||||
"fignum", psdFigure, ...
|
||||
"show_onesided", 1, ...
|
||||
"fft_length", 4096, ...
|
||||
"displayname", equalizedPsdName, ...
|
||||
"color", psd_color_equalized);
|
||||
|
||||
eq_noise = equalized_signal - referenceForEye;
|
||||
showEQNoisePSD(eq_noise, ...
|
||||
"fignum", 800, ...
|
||||
"displayname", sprintf('%.0f Gbps: VNLE Noise', selectedBitrate), ...
|
||||
"colormode", "diverging");
|
||||
|
||||
% PSDs are line-only, irrespective of the marker styles used by
|
||||
% algorithm comparison plots.
|
||||
set(findall(gca, 'Type', 'Line'), 'Marker', 'none');
|
||||
|
||||
figure(psdFigure);
|
||||
title(sprintf('PSD comparison: %.0f GBd PAM-%d', fsym*1e-9, M), ...
|
||||
'Interpreter', 'none');
|
||||
legend('Location', 'best', 'Interpreter', 'none');
|
||||
grid on;
|
||||
box on;
|
||||
|
||||
if export_tikz
|
||||
baudrateLabel = sprintf('%.0fGBd', fsym*1e-9);
|
||||
psdFilename = fullfile(tikz_psd_folder, ...
|
||||
sprintf('psd_pam_%d_%s_db_mode_%d.tikz', ...
|
||||
M, baudrateLabel, db_mode_setting));
|
||||
mat2tikz_improved(psdFilename);
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if showEye
|
||||
% Use the native Signal eye implementation for the displayed eye.
|
||||
eyeFigure = eye_figure_base + mIdx+ db_mode_setting;
|
||||
equalized_signal.eye(fsym, M, ...
|
||||
"fignum", eyeFigure, ...
|
||||
"displayname", sprintf('PAM-%d, db_mode = %d', M, db_mode_setting));
|
||||
figure(eyeFigure);
|
||||
set(gcf, "Position", [100 + 430*(mIdx - 1), 100, 400, 360]);
|
||||
stripEyeAxes(gca);
|
||||
|
||||
|
||||
if export_tikz
|
||||
baudrateLabel = sprintf('%.0fGBd', fsym*1e-9);
|
||||
eyeFilename = fullfile(tikz_eye_folder, ...
|
||||
sprintf('eye_pam_%d_%s_db_mode_%d.tikz', ...
|
||||
M, baudrateLabel, db_mode_setting));
|
||||
mat2tikz_improved(eyeFilename);
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if show_histograms || export_tikz
|
||||
histogramFigure = histogram_figure_base + M + db_mode_setting;
|
||||
plotHistogram(equalized_signal, referenceForEye, ...
|
||||
M, histogramFigure, db_mode_setting, histogramLegendLabels(M));
|
||||
|
||||
if export_tikz
|
||||
figure(histogramFigure);
|
||||
histogramFilename = fullfile(tikz_histogram_folder, ...
|
||||
sprintf('histogram_pam_%d_%s_db_mode_%d.tikz', ...
|
||||
M, baudrateLabel, db_mode_setting));
|
||||
mat2tikz_improved(histogramFilename,"cleanfigure",1);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
%% Local functions
|
||||
function signalOut = averageScopeSignals(scopeCell, averageSignals, gain)
|
||||
signalOut = scopeCell{1};
|
||||
if ~averageSignals
|
||||
return
|
||||
end
|
||||
|
||||
commonLength = min(cellfun(@(s) numel(s.signal), scopeCell));
|
||||
scopeMean = zeros(commonLength, 1);
|
||||
for idx = 1:numel(scopeCell)
|
||||
scopeMean = scopeMean + scopeCell{idx}.signal(1:commonLength);
|
||||
end
|
||||
scopeMean = scopeMean ./ numel(scopeCell);
|
||||
signalOut.signal = gain .* scopeMean;
|
||||
end
|
||||
|
||||
function eq_ = makeVnle(lenTr, trainingLoops, ddLoops, eqK, muDc, muFfe, muDfe)
|
||||
eq_ = EQ("Ne", [50, 5, 5], ...
|
||||
"Nb", [0, 0, 0], ...
|
||||
"training_length", lenTr, ...
|
||||
"training_loops", trainingLoops, ...
|
||||
"dd_loops", ddLoops, ...
|
||||
"K", eqK, ...
|
||||
"DCmu", muDc, ...
|
||||
"DDmu", [muFfe, muDfe], ...
|
||||
"DFEmu", 0.005, ...
|
||||
"FFEmu", 0, ...
|
||||
"plotfinal", 0, ...
|
||||
"ideal_dfe", true);
|
||||
end
|
||||
|
||||
function plotHistogram(equalizedSignal, referenceForEye, M, figureNumber, ...
|
||||
dbModeSetting, legendLabels)
|
||||
figure(figureNumber); clf;
|
||||
if dbModeSetting ~= 0
|
||||
uncodedReference = Duobinary().decode(referenceForEye, "M", M);
|
||||
showLevelHistogram(equalizedSignal, referenceForEye, ...
|
||||
"fignum", figureNumber, ...
|
||||
"ref_symbol_uncoded", uncodedReference, ...
|
||||
"legendLabels", legendLabels);
|
||||
else
|
||||
showLevelHistogram(equalizedSignal, referenceForEye, ...
|
||||
"fignum", figureNumber, ...
|
||||
"legendLabels", legendLabels);
|
||||
end
|
||||
title(sprintf('PAM-%d histogram, db\_mode = %d', M, dbModeSetting));
|
||||
end
|
||||
|
||||
function labels = histogramLegendLabels(M)
|
||||
labels = arrayfun(@(idx) sprintf('$p(z|d=d_{%d})$', idx), ...
|
||||
1:M, 'UniformOutput', false);
|
||||
end
|
||||
|
||||
function stripEyeAxes(ax)
|
||||
title(ax, '');
|
||||
xlabel(ax, '');
|
||||
ylabel(ax, '');
|
||||
set(ax, ...
|
||||
'XTick', [], ...
|
||||
'YTick', [], ...
|
||||
'XTickLabel', [], ...
|
||||
'YTickLabel', [], ...
|
||||
'XMinorTick', 'off', ...
|
||||
'YMinorTick', 'off');
|
||||
grid(ax, 'off');
|
||||
end
|
||||
|
||||
function styles = defaultAlgorithmStyles()
|
||||
styles = table( ...
|
||||
["vnle"; ...
|
||||
"vnle_pf_mlse"; ...
|
||||
"vnle_db_mlse"; ...
|
||||
"ml_mlse"; ...
|
||||
"db_encoded"], ...
|
||||
[equalizer_structure.vnle; ...
|
||||
equalizer_structure.vnle_pf_mlse; ...
|
||||
equalizer_structure.vnle_db_mlse; ...
|
||||
equalizer_structure.ml_mlse; ...
|
||||
equalizer_structure.db_encoded], ...
|
||||
["VNLE"; ...
|
||||
"VNLE + PF + MLSE"; ...
|
||||
"VNLE DBt. + MLSE"; ...
|
||||
"ML pre-EQ + Viterbi"; ...
|
||||
"DBS + VNLE + MLSE"], ...
|
||||
["o"; "square"; "diamond"; "^"; "v"], ...
|
||||
["-"; "-"; "-"; "-"; "-"], ...
|
||||
["w"; "w"; "w"; "w"; "w"], ...
|
||||
[clr.Paired.red; ...
|
||||
clr.Paired.green; ...
|
||||
clr.Paired.blue; ...
|
||||
clr.Paired.purple; ...
|
||||
clr.Paired.orange], ...
|
||||
'VariableNames', ["algorithm_key", "eq", "name", "marker", ...
|
||||
"lineStyle", "markerFaceColor", "color"]);
|
||||
end
|
||||
Reference in New Issue
Block a user