CLEANUP - changes to folder structure

This commit is contained in:
Silas Oettinghaus
2026-03-25 10:57:48 +01:00
parent 0c5ad28f0a
commit 0ae846d3c3
351 changed files with 405 additions and 1294 deletions

View File

@@ -0,0 +1,111 @@
database_type = 'mysql';
dataBase = 'labor_highspeed';%'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\silas_labor_newdsp_newstructure.db';
db = DBHandler("dataBase", [dataBase], "type", database_type);
fp = QueryFilter();
% fp.where('Runs', 'run_id','EQUALS', 987);
M = 6;
fp.where('Runs', 'pam_level','EQUALS', M);
baudrate = 162e9;
fp.where('Runs', 'symbolrate','EQUALS', baudrate);
% fp.where('Runs', 'fiber_length','EQUALS', 2);
fp.where('Runs', 'is_mpi','EQUALS', 0);
% fp.where('Runs', 'interference_path_length','EQUALS', 1000);
% fp.where('Runs', 'loop_id','GREATER_THAN', 11);
% fp.where('Runs', 'sir','EQUALS',18);
% fp.where('Runs', 'wavelength','EQUALS', 1310);
fp.where('Runs', 'db_mode','EQUALS', 1); % 0 == high preemphasis // 1 == low preemphasis
fp.where('Runs', 'rop_attenuation','EQUALS', 0);
fields = db.getTableFieldNames('power_state_info');
fields = [fields; db.getTableFieldNames('dashboard_ungrouped_new')];
[dataTable,~] = db.queryDB(fp, fields);
eqstructures = unique(dataTable.equalizer_structure);
fiber_len = unique(dataTable.fiber_length);
cnt = 1;
f=figure();
clf
hold on
markers = {'o', 's', 'd', '^', 'v', '>', '<', 'p', 'h'}; % Define marker styles
for fl = 1:numel(fiber_len)
fl_filtered = dataTable(dataTable.fiber_length == fiber_len(fl),:);
for eqs = [equalizer_structure.vnle_pf_mlse]
eq_choice = equalizer_structure(eqs);
if sum(eqstructures == eq_choice)~=1
disp(eq_choice)
continue
end
eq_filtered = fl_filtered(fl_filtered.equalizer_structure == eq_choice,:);
dispersion_sorted = sortrows(eq_filtered, {'accumulated_dispersion'}, 'ascend');
% dispersion_sorted = dispersion_sorted(dispersion_sorted.wavelength <= 1320,:);
% dispersion_sorted = dispersion_sorted(dispersion_sorted.BER < 0.02,:);
% pull out your vectors
accumulated_dispersion = dispersion_sorted.accumulated_dispersion;
ber = dispersion_sorted.BER;
% ber = dispersion_sorted.BER_precoded;
run_ids = dispersion_sorted.run_id; % <-- this is what we want in the datatip
len = dispersion_sorted.fiber_length;
lambda = dispersion_sorted.wavelength;
cols = cbrewer2('Set1',8);
% cols = flip(cbrewer2('RdYlGn',14));
cols = linspecer(8);
ber_wavelen_grouped = groupsummary( ...
dispersion_sorted, ... % input table
"wavelength", ... % grouping variable
"min", ... % which summary statistic
"BER_precoded");
dname = sprintf('%s; %d km',eq_choice, fiber_len(fl));
h1 = plot(ber_wavelen_grouped.wavelength, ber_wavelen_grouped.min_BER_precoded,'LineWidth', 2, 'MarkerSize', 5,'Marker',markers(cnt),'LineStyle','-','Color',cols(cnt,:),'MarkerEdgeColor','auto','MarkerFaceColor','white','DisplayName',dname);
plotallscatters=0;
if plotallscatters
% plot the two curves and capture their Line handles
dname = sprintf('%s; %d km',eq_choice, fiber_len(fl));
h1 = plot(lambda, ber,'LineWidth', 1.5, 'MarkerSize', 5,'Marker','o','LineStyle','none','Color',cols(cnt,:),'MarkerFaceColor',cols(cnt,:),'DisplayName',dname);
% Add run_id as a datatip row
% For each line, tell the datatip template where to find the run_id:
h1.DataTipTemplate.DataTipRows(end+1) = ...
dataTipTextRow('run\_id', run_ids);
h1.DataTipTemplate.DataTipRows(end+1) = ...
dataTipTextRow('len', len);
h1.DataTipTemplate.DataTipRows(end+1) = ...
dataTipTextRow('lambda', lambda);
end
xticks(sort(unique(lambda)));
xticklabels(sort(unique(lambda)));
grid on;
% Labels, scales, legend, etc.
xlabel('Wavelength in nm','FontSize',12);
ylabel('BER','FontSize',12);
tit = sprintf('%d GBd PAM-%d',baudrate.*1e-9, M);
title(tit,'FontSize',14,'FontWeight','bold');
set(gca, 'XScale','linear','YScale','log','FontSize',11);
legend
xlim([min(lambda)-2, max(lambda)+2]);
ylim([1e-4, 0.2]);
cnt = cnt+1;
end
end
yline([4.85e-3, 2e-2],'--','LineWidth',1,'HandleVisibility','off');
posH = get(f, 'Position'); % [left, bottom, width, height]
newPos = [posH(1), posH(2), 750, 300];
set(f, 'Position', newPos);

View File

@@ -0,0 +1,284 @@
database_type = 'mysql';
dataBase = 'labor_highspeed';%'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\silas_labor_newdsp_newstructure.db';
db = DBHandler("dataBase", [dataBase], "type", database_type);
fp = QueryFilter();
% fp.where('Runs', 'run_id','EQUALS', 987);
M = 6;
fp.where('Runs', 'pam_level','EQUALS', M);
% fp.where('Runs', 'bitrate','LESS_THAN', 310e9);
fp.where('Runs', 'fiber_length','EQUALS', 2);
fp.where('Runs', 'is_mpi','EQUALS', 0);
% fp.where('Runs', 'interference_path_length','EQUALS', 1000);
% fp.where('Runs', 'loop_id','GREATER_THAN', 11);
% fp.where('Runs', 'sir','EQUALS',18);
fp.where('Runs', 'wavelength','EQUALS', 1310);
% fp.where('Runs', 'db_mode','EQUALS', 0);
fp.where('Runs', 'rop_attenuation','EQUALS', 0);
fields = db.getTableFieldNames('power_state_info');
fields = [fields; db.getTableFieldNames('dashboard_ungrouped_aug_nov_2025')];
[dataTable,~] = db.queryDB(fp, fields);
eqstructures = unique(dataTable.equalizer_structure);
% Create the figure
showFiltered = true;
showPrecoded = false;
show_bitrate = true;
figure(5);
hold on
for eqs = [equalizer_structure.vnle]
% figure('Name',string([char(eqs),'']));
% hold on
for pre_emph = [0,1]
dbmode_filtered = dataTable(dataTable.db_mode == ~pre_emph,:);
eq_choice = equalizer_structure(eqs);
if sum(eqstructures == eq_choice)~=1
disp(eq_choice)
continue
end
eq_filtered = dbmode_filtered(dbmode_filtered.equalizer_structure == eq_choice,:);
% ===== NEW: compute averages + per-row keep masks (robust filtering) =====
[Tav, keepMask, keepMaskP] = avgBerBySymbolrate(eq_filtered); % <= NEW
% x-values (bitrate) for raw points (same mapping as your lines)
M = unique(eq_filtered.pam_level); % (assumes single PAM per curve)
if show_bitrate
x_raw = eq_filtered.symbolrate.*1e-9 .* floor(log2(M)*10)/10;
else
x_raw = eq_filtered.symbolrate.*1e-9;
end
% ===== NEW: scatter kept raw BER points (hidden from legend) =====
cols = cbrewer2('Paired',12);
thisColor = cols((2*eqs)+1+pre_emph,:);
scatter(x_raw(keepMask), ... % kept points
eq_filtered.BER(keepMask), ...
14, thisColor, 'filled', ...
'MarkerFaceAlpha', 0.35, ...
'MarkerEdgeAlpha', 0.35, ...
'HandleVisibility','off');
if showPrecoded
scatter(x_raw(keepMaskP), ... % kept precoded points
eq_filtered.BER_precoded(keepMaskP), ...
14, thisColor, 'filled', ...
'Marker', 'square', ...
'MarkerFaceAlpha', 0.35, ...
'MarkerEdgeAlpha', 0.35, ...
'HandleVisibility','off');
end
% ===== NEW: optionally show filtered-out points in red =====
if showFiltered
bad = ~keepMask;
if any(bad)
scatter(x_raw(bad), eq_filtered.BER(bad), ...
18, 'r', 'x', 'LineWidth', 1.2, ...
'HandleVisibility','off');
end
badp = ~keepMaskP;
if any(badp)
scatter(x_raw(badp), eq_filtered.BER_precoded(badp), ...
18, 'r', '+', 'LineWidth', 1.2, ...
'HandleVisibility','off');
end
end
% Keep your sorting and one-per-symbolrate behavior (using Tav)
symbolrate_sorted = sortrows(Tav,{'symbolrate','avg_BER_calc'}, 'ascend');
[~, ia] = unique(symbolrate_sorted.symbolrate, 'first');
symbolrate_sorted = symbolrate_sorted(ia, :);
if show_bitrate
% Bitrate for the averaged curves (unchanged)
xraw = symbolrate_sorted.symbolrate.*1e-9 .* floor(log2(M)*10)/10;
else
xraw = symbolrate_sorted.symbolrate.*1e-9;
end
% Use the MATLAB-averaged BERs
ber = symbolrate_sorted.avg_BER_calc;
ber_precoded = symbolrate_sorted.avg_BER_precoded_calc;
dname = strrep([char(eq_choice)],'_',' ');
if pre_emph
dname = [dname,' with pre-emph.'];
else
dname = [dname,' w/o pre-emph.'];
end
plot(xraw, ber, ...
'LineWidth', 1.5, 'MarkerSize', 5, ...
'Marker','o','LineStyle','-', ...
'Color',thisColor,'MarkerEdgeColor',thisColor,'MarkerFaceColor',[1,1,1], ...
'DisplayName', dname);
if showPrecoded
plot(xraw, ber_precoded, ...
'LineWidth', 1.5, 'MarkerSize', 5, ...
'Marker','square','LineStyle',':', ...
'Color',thisColor,'MarkerEdgeColor',thisColor,'MarkerFaceColor',[1,1,1], ...
'DisplayName', [dname,'; pre-coded']);
end
grid on;
if show_bitrate
xlabel('Net bitrate [GBps]', 'FontSize', 12);
else
xlabel('Symbol rate [GBd]', 'FontSize', 12);
end
ylabel('BER', 'FontSize', 12);
title('BER vs. Baud Rate','FontSize', 14, 'FontWeight', 'bold');
set(gca, 'XScale', 'linear', ...
'YScale', 'log', ...
'TickLabelInterpreter', 'latex', ...
'FontSize', 11);
xticks(xraw);
if show_bitrate
% xticks(200:25:500);
% xlim([350 500]);
xlim([min(xraw), max(xraw)]);
else
xlim([min(xraw), max(xraw)]);
end
ylim([1e-4, 0.5]);
end
yline([2.2e-4, 4.85e-3, 2e-2],'LineWidth',1,'LineStyle','--','HandleVisibility','off');
end
function [Tav, keepAll, keepAllP] = avgBerBySymbolrate(T, ZT, MIN_G)
% Minimal robust averaging of BER per symbolrate (+ masks for kept points).
% Usage: [Tav, keepAll, keepAllP] = avgBerBySymbolrate(T, ZT, MIN_G)
% Defaults: ZT=3 (MAD z-thresh in log10), MIN_G=2 (min points to filter)
if nargin < 2, ZT = 5; end
if nargin < 5, MIN_G = 0; end
hasP = ismember('BER_precoded', T.Properties.VariableNames);
hasNB = ismember('numBits', T.Properties.VariableNames);
[G,~,idx] = unique(T.symbolrate);
nG = numel(G);
avgBER = nan(nG,1);
avgBERp = nan(nG,1);
keepAll = false(height(T),1);
keepAllP = false(height(T),1);
for gi = 1:nG
r = idx==gi;
x = T.BER(r);
nb = hasNB * T.numBits(r) + ~hasNB; % if missing, nb==1 (scalar expansion ok)
[avgBER(gi), keepAll(r)] = rmeanBer(x, nb, ZT, MIN_G);
if hasP
xp = T.BER_precoded(r);
[avgBERp(gi), keepAllP(r)] = rmeanBer(xp, nb, ZT, MIN_G);
end
end
Tav = table(G, avgBER, avgBERp, ...
'VariableNames', {'symbolrate','avg_BER_calc','avg_BER_precoded_calc'});
end
function [mu, keep] = rmeanBer(x, nb, ZT, MIN_G, onlyHighOutliers, minKeepThreshold)
% Robust arithmetic mean of BER with log-domain MAD filtering (returns keep mask)
%
% Params:
% x : BER values
% nb : numBits (for floor)
% ZT : MAD z-threshold
% MIN_G : min group size before filtering
% onlyHighOutliers : (bool) if true, only discard values above mean
% minKeepThreshold : values below this BER are always kept
%
% Returns:
% mu : robust mean
% keep : logical mask of kept samples
if nargin < 5, onlyHighOutliers = false; end
if nargin < 6, minKeepThreshold = 0; end
x(~isfinite(x)) = NaN;
if ~isscalar(nb), nb(~isfinite(nb)) = NaN; end
if isscalar(nb) && ~isfinite(nb), nb = 1; end
floorVal = realmin;
if ~isscalar(nb) || (isscalar(nb) && isfinite(nb) && nb~=1)
fv = 0.5 ./ max(nb, eps); % rule-of-three style floor
if isscalar(fv), floorVal = fv; else, floorVal = fv; end
end
xAdj = x;
bad = ~isfinite(xAdj) | xAdj <= 0;
if isscalar(floorVal)
xAdj(bad) = floorVal;
else
xAdj(bad) = floorVal(bad);
end
valid = isfinite(xAdj) & xAdj > 0;
keep = false(size(xAdj));
if nnz(valid)==0
mu = NaN; return
end
if nnz(valid) < MIN_G
mu = mean(xAdj(valid),'omitnan'); keep(valid)=true; return
end
lx = log10(xAdj(valid));
med = median(lx,'omitnan');
mad = median(abs(lx-med),'omitnan');
if mad<=0 || ~isfinite(mad)
keep(valid) = true;
mu = mean(xAdj(valid),'omitnan');
return
end
sigma = 1.4826*mad;
ksel = abs(lx-med) <= ZT*sigma;
% convert to linear indices
vIdx = find(valid);
% === Extension A: only drop high outliers ===
if onlyHighOutliers
logMean = mean(lx,'omitnan');
highIdx = lx > logMean;
ksel = ksel | ~highIdx; % always keep values below/equal to mean
end
% === Extension B: always keep values below minKeepThreshold ===
belowThr = xAdj(valid) < minKeepThreshold;
ksel = ksel | belowThr;
keep(vIdx(ksel)) = true;
if any(keep)
mu = mean(xAdj(keep),'omitnan');
else
mu = mean(xAdj(valid),'omitnan');
keep(valid) = true;
end
end

View File

@@ -0,0 +1,117 @@
database_type = 'mysql';
dataBase = 'labor_highspeed';%'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\silas_labor_newdsp_newstructure.db';
db = DBHandler("dataBase", [dataBase], "type", database_type);
fp = QueryFilter();
% fp.where('Runs', 'run_id','EQUALS', 987);
M = 8;
fp.where('Runs', 'pam_level','EQUALS', M);
% fp.where('Runs', 'bitrate','LESS_THAN', 310e9);
fp.where('Runs', 'fiber_length','EQUALS', 2);
fp.where('Runs', 'is_mpi','EQUALS', 0);
% fp.where('Runs', 'interference_path_length','EQUALS', 1000);
% fp.where('Runs', 'loop_id','GREATER_THAN', 11);
% fp.where('Runs', 'sir','EQUALS',18);
fp.where('Runs', 'wavelength','EQUALS', 1310);
% fp.where('Runs', 'db_mode','EQUALS', 1);
fp.where('Runs', 'rop_attenuation','EQUALS', 0);
[dataTable,~] = db.queryDB(fp, db.getTableFieldNames('dashboard_ungrouped_after_nov_2025'));
eqstructures = unique(dataTable.equalizer_structure);
% Create the figure
f=figure(4);
hold on
eqs = [equalizer_structure.vnle, equalizer_structure.vnle_pf_mlse , equalizer_structure.vnle_db_mlse];
cols = [0.4660 0.6740 0.1880 ; 0.9290 0.6940 0.1250 ; 0 0.4470 0.7410; 0.4940 0.1840 0.5560]; %VNLE; PF ; DFE ; DB tgt
eq_choice = equalizer_structure.vnle;
pre_emph = 1;
dbmode_filtered = dataTable(dataTable.db_mode == ~pre_emph,:);
eq_filtered = dbmode_filtered(dbmode_filtered.equalizer_structure == eq_choice,:);
symbolrate_sorted = sortrows(eq_filtered,{'symbolrate','min_BER_precoded'}, 'ascend');
[~, ia] = unique(symbolrate_sorted.symbolrate, 'first');
symbolrate_sorted = symbolrate_sorted(ia, :);
symbolrate = symbolrate_sorted.symbolrate.*1e-9; % in baud
bitrate = symbolrate * floor(log2(M)*10)/10;
ber = symbolrate_sorted.min_BER; % BER
ber_precoded = symbolrate_sorted.min_BER_precoded; % BER
plot(bitrate, ber, 'LineWidth', 1.5, 'MarkerSize', 5,'Marker','v','LineStyle',':','Color',cols(1,:),'MarkerEdgeColor',cols(1,:),'MarkerFaceColor',cols(1,:),'DisplayName',['Tx pre-emphasis + VNLE']);
eq_choice = equalizer_structure.vnle_pf_mlse;
pre_emph = 0;
dbmode_filtered = dataTable(dataTable.db_mode == ~pre_emph,:);
eq_filtered = dbmode_filtered(dbmode_filtered.equalizer_structure == eq_choice,:);
symbolrate_sorted = sortrows(eq_filtered,{'symbolrate','min_BER_precoded'}, 'ascend');
[~, ia] = unique(symbolrate_sorted.symbolrate, 'first');
symbolrate_sorted = symbolrate_sorted(ia, :);
symbolrate = symbolrate_sorted.symbolrate.*1e-9; % in baud
bitrate = symbolrate * floor(log2(M)*10)/10;
ber = symbolrate_sorted.min_BER; % BER
ber_precoded = symbolrate_sorted.min_BER_precoded; % BER
plot(bitrate, ber, 'LineWidth', 1.5, 'MarkerSize', 5,'Marker','diamond','LineStyle',':','Color',cols(2,:),'MarkerEdgeColor',cols(2,:),'MarkerFaceColor',cols(2,:),'DisplayName',['VNLE+2-tap post-filter+MLSE']);
% eq_choice = equalizer_structure.dfe;
% pre_emph = 1;
% dbmode_filtered = dataTable(dataTable.db_mode == ~pre_emph,:);
% eq_filtered = dbmode_filtered(dbmode_filtered.equalizer_structure == eq_choice,:);
% symbolrate_sorted = sortrows(eq_filtered,{'symbolrate','min_BER_precoded'}, 'ascend');
% [~, ia] = unique(symbolrate_sorted.symbolrate, 'first');
% symbolrate_sorted = symbolrate_sorted(ia, :);
% symbolrate = symbolrate_sorted.symbolrate.*1e-9; % in baud
% bitrate = symbolrate * floor(log2(M)*10)/10;
% ber = symbolrate_sorted.min_BER; % BER
% ber_precoded = symbolrate_sorted.min_BER_precoded; % BER
% plot(bitrate, ber, 'LineWidth', 1.5, 'MarkerSize', 5,'Marker','o','LineStyle','-','Color',cols(3,:),'MarkerEdgeColor',cols(3,:),'MarkerFaceColor',cols(3,:),'DisplayName',[char(eq_choice)]);
eq_choice = equalizer_structure.vnle_db_mlse;
pre_emph = 0;
dbmode_filtered = dataTable(dataTable.db_mode == ~pre_emph,:);
eq_filtered = dbmode_filtered(dbmode_filtered.equalizer_structure == eq_choice,:);
symbolrate_sorted = sortrows(eq_filtered,{'symbolrate','min_BER_precoded'}, 'ascend');
[~, ia] = unique(symbolrate_sorted.symbolrate, 'first');
symbolrate_sorted = symbolrate_sorted(ia, :);
symbolrate = symbolrate_sorted.symbolrate.*1e-9; % in baud
bitrate = symbolrate * floor(log2(M)*10)/10;
ber = symbolrate_sorted.min_BER; % BER
ber_precoded = symbolrate_sorted.min_BER_precoded; % BER
plot(bitrate, ber_precoded, 'LineWidth', 1.5, 'MarkerSize', 5,'Marker','square','LineStyle',':','Color',cols(4,:),'MarkerEdgeColor',cols(4,:),'MarkerFaceColor',cols(4,:),'DisplayName',['DB precoding + DB tgt. + MLSE']);
% Axis labels and title with Arial font
xlabel('Gross bitrate [Gb/s]', 'FontSize', 12, 'FontName', 'Arial', 'Interpreter', 'none');
ylabel('BER', 'FontSize', 12, 'FontName', 'Arial', 'Interpreter', 'none');
title('', 'FontSize', 14, 'FontWeight', 'bold', 'FontName', 'Arial', 'Interpreter', 'none');
% Improve tick formatting
set(gca, 'XScale', 'linear', ...
'YScale', 'log', ...
'TickLabelInterpreter', 'none', ...
'FontSize', 11, ...
'FontName', 'Arial');
% Legend with Arial font
% legend('FontName', 'Arial', 'Interpreter', 'none','Location','best');
xticks(bitrate);
% Optional: tighten axis limits
xlim([min(bitrate), max(bitrate)]);
ylim([5e-4, 0.05]);
yline([3.8e-3], 'LineWidth', 2, 'LineStyle', '--', ...
'HandleVisibility', 'off', 'LabelHorizontalAlignment', 'left');
posH = get(f, 'Position'); % [left, bottom, width, height]
newPos = [posH(1), posH(2), 350, 200];
set(f, 'Position', newPos);
annotation(f,'textbox',...
[0.398095238095238 0.273381294964029 0.491428571428572 0.140287769784173],...
'String',{'PAM-8; 2 km; 1293 nm'},...
'LineWidth',0.5,...
'FitBoxToText','off',...
'BackgroundColor',[1 1 1]);

View File

@@ -0,0 +1,146 @@
%% ============================================================
% SETTINGS
% ============================================================
database_type = 'mysql';
db = DBHandler("dataBase", "labor_highspeed", "type", database_type);
fiberL = 1; % km
wlen = 1310; % nm
bit = 300e9; % example (adjust if needed)
max_pd = 7; % ROP limit (same as before)
PAM_list = [4 6 8]; % formats to compare
% Colors for PAM formats
colors = {clr.Paired.red, clr.Paired.green, clr.Paired.blue};
% Best DSP selection:
bestDSP = struct;
bestDSP = struct;
bestDSP.P4 = equalizer_structure.vnle_db_mlse; % PAM-4
bestDSP.P6 = equalizer_structure.vnle; % PAM-6
bestDSP.P8 = equalizer_structure.vnle; % PAM-8
%% ============================================================
% LOOP over PAM formats extract data
% ============================================================
results = struct;
for pi = 1:numel(PAM_list)
M = PAM_list(pi);
eq = bestDSP.(sprintf('P%d', M));
% ---- DB FILTER ----
fp = QueryFilter();
fp.where('Runs','pam_level','EQUALS',M);
fp.where('Runs','fiber_length','EQUALS',fiberL);
fp.where('Runs','wavelength','EQUALS',wlen);
fp.where('Runs','bitrate','EQUALS',bit);
fp.where('Runs','power_pd_in','LESS_THAN',max_pd);
fields = [
db.getTableFieldNames('power_state_info');
db.getTableFieldNames('dashboard_ungrouped_alltime')
];
[T,~] = db.queryDB(fp, fields);
% ---- DSP OPTIONS ----
pre_emph = decide_preemph(M, eq);
precoded = decide_precoded(M, eq);
cfg = struct;
cfg.x_axis = 'power_mzm';
cfg.y_axis = 'BER';
cfg.agg = 'min';
cfg.outlier = 'none';
cfg.show_raw = false;
cfg.filters = struct( ...
'pam_level', M, ...
'fiber_length', fiberL, ...
'wavelength', wlen, ...
'bitrate', bit, ...
'is_mpi', 0, ...
'equalizer_structure', eq, ...
'pre_emph', pre_emph);
A = analyze_measurements_gpt(T, cfg);
results(pi).M = M;
results(pi).x = A.group{1}.x;
results(pi).color = colors{pi};
if precoded
results(pi).ber = A.group{1}.y_precoded;
else
results(pi).ber = A.group{1}.y;
end
end
%% ============================================================
% PLOT all PAM formats in one ROP plot
% ============================================================
fig = figure(91); hold on;
lw = 2.2; ms = 7;
for pi = 1:numel(results)
plot(results(pi).x, results(pi).ber, ...
'-o', ...
'LineWidth', lw, ...
'MarkerSize', ms, ...
'MarkerFaceColor', results(pi).color, ...
'Color', results(pi).color, ...
'DisplayName', sprintf('PAM-%d', results(pi).M));
end
set(gca,'YScale','log');
grid minor;
xlabel('ROP / Power (MZM) [dBm]');
ylabel('BER');
ylim([1e-4 2e-1]);
legend('Location','best');
title(sprintf('BER vs ROP Best DSP (4,6,8) at %.0f GBd, λ=%d nm, %.0f km', ...
bit*1e-9, wlen, fiberL));
beautifyBERplot();
set(fig,'Position',1e3*[0.35 0.45 1.0 0.45]);
%% ============================================================
% DECISION LOGIC (INLINE FUNCTIONS)
% ============================================================
function pe = decide_preemph(M, eq)
% PRE-EMPH RULES:
switch M
case 4
if eq == equalizer_structure.vnle
pe = 1; % PAM4: VNLE pre-emph on
else
pe = 0; % PAM4: all others off
end
case {6,8}
pe = 1; % PAM6/8: all pre-emph on
otherwise
pe = 0;
end
end
function flag = decide_precoded(M, eq)
% PRE-CODE RULES:
if eq == equalizer_structure.vnle_db_mlse
flag = 1; % Always for DB-target
elseif eq == equalizer_structure.ml_mlse && M == 4
flag = 1; % PAM4: ML-based precoded
else
flag = 0;
end
end

View File

@@ -0,0 +1,272 @@
%% ============================================================
% LOAD DATA FOR PAM = 4,6,8
% ============================================================
database_type = 'mysql';
db = DBHandler("dataBase", "labor_highspeed", "type", database_type);
pam_levels = [4, 6, 8]; % three tiles
bitrate_set = 360e9;
fiberL = 2;
fields = [
db.getTableFieldNames('power_state_info');
db.getTableFieldNames('dashboard_ungrouped_alltime')
];
%% ============================================================
% DEFINE DSP SCHEMES
% ============================================================
curves = struct;
curves(1).name = 'VNLE';
curves(1).eq = equalizer_structure.vnle;
curves(1).color = clr.Paired.red;
curves(2).name = 'PF + MLSE';
curves(2).eq = equalizer_structure.vnle_pf_mlse;
curves(2).color = clr.Paired.green;
curves(3).name = 'DB-target + MLSE';
curves(3).eq = equalizer_structure.vnle_db_mlse;
curves(3).color = clr.Paired.blue;
curves(4).name = 'ML-based MLSE';
curves(4).eq = equalizer_structure.ml_mlse;
curves(4).color = clr.Paired.purple;
%% ============================================================
% ANALYSIS NO PLOTTING
% results(p, k) p: PAM index, k: DSP index
% ============================================================
results = struct;
for p = 1:length(pam_levels)
M = pam_levels(p);
% --- Load DB rows for this PAM ---
fp = QueryFilter();
fp.where('Runs','pam_level','EQUALS', M);
fp.where('Runs','fiber_length','EQUALS', fiberL);
fp.where('Runs','bitrate','EQUALS', bitrate_set);
fp.where('Runs','is_mpi','EQUALS', 0);
[dataTable, ~] = db.queryDB(fp, fields);
for k = 1:numel(curves)
%% =====================================================
% DECIDE PRE-EMPHASIS AND PRECoded BER
% ======================================================
pre_emph = decide_preemph(M, curves(k).eq);
use_precoded = decide_precoded(M, curves(k).eq);
%% ---- base config ----
cfg = struct;
cfg.x_axis = 'wavelength';
cfg.y_axis = 'BER';
cfg.agg = 'min';
cfg.outlier = 'none';
% cfg.group_by = {'wavelength'};
cfg.show_raw = false;
cfg.filters = struct( ...
'pam_level', M, ...
'is_mpi', 0, ...
'bitrate', bitrate_set, ...
'fiber_length', fiberL, ...
'equalizer_structure', curves(k).eq, ...
'pre_emph', pre_emph);
%% ---- Run analysis ----
A = analyze_measurements_gpt(dataTable, cfg);
results(p,k).wavelength = A.group{1}.x;
%% ---- store BER variant ----
if use_precoded
results(p,k).ber = A.group{1}.y_precoded;
else
results(p,k).ber = A.group{1}.y;
end
end
end
%% ============================================================
% PLOT 1×3 (PAM-4, PAM-6, PAM-8)
% ============================================================
fig = figure(9112); clf;
tiledlayout(1,3,'TileSpacing','compact','Padding','compact');
lw = 1.8;
ms = 6;
for p = 1:length(pam_levels)
nexttile; hold on;
for k = 1:numel(curves)
plot(results(p,k).wavelength, results(p,k).ber, ...
'-o', ...
'Color', curves(k).color, ...
'MarkerFaceColor', curves(k).color, ...
'MarkerSize', ms, ...
'LineWidth', lw, ...
'DisplayName', curves(k).name);
end
set(gca,'YScale','log');
grid on;
if p == 1
ylabel('BER');
else
ylabel('');
end
xlabel('wavelength');
ylim([4e-4, 0.1]);
beautifyBERplot();
yline([2.2e-4 4.85e-3 2e-2], ...
'LineWidth',1.1, 'Color',[0.2 0.2 0.2], ...
'LineStyle',':','HandleVisibility','off');
if p == 1
x1 = 1290;
x2 = 1297;
x3 = 1300;
x4 = 1323;
x5 = 1325;
x6 = 1330;
elseif p == 2
x1 = 1290;
x2 = 1295;
x3 = 1300;
x4 = 1323.5;
x5 = 1325;
x6 = 1330;
elseif p == 3
x1 = 1290;
x2 = 1292;
x3 = 1298;
x4 = 1323;
x5 = 1327.5;
x6 = 1330;
end
% --- Get current y-limits ---
yl = ylim;
% --- LEFT AREA BELOW KP4 FEC ---
patch([x1 x2 x2 x1], [yl(1) yl(1) yl(2) yl(2)], ...
clr.Set1.red, ... % RGB = red
'FaceAlpha', 0.1, ... % transparency 0.1
'EdgeColor', 'none'); % no border
% --- RIGHT AREA BELOW KP4 FEC ---
patch([x2 x3 x3 x2], [yl(1) yl(1) yl(2) yl(2)], ...
clr.Set1.blue, ... % RGB = red
'FaceAlpha', 0.10, ... % transparency 0.1
'EdgeColor', 'none'); % no border
% --- LEFT AREA BELOW O-FEC ---
patch([x4 x5 x5 x4], [yl(1) yl(1) yl(2) yl(2)], ...
clr.Set1.blue, ... % RGB = red
'FaceAlpha', 0.10, ... % transparency 0.1
'EdgeColor', 'none'); % no border
% --- RIGHT AREA BELOW O-FEC ---
patch([x5 x6 x6 x5], [yl(1) yl(1) yl(2) yl(2)], ...
clr.Set1.red, ... % RGB = red
'FaceAlpha', 0.10, ... % transparency 0.1
'EdgeColor', 'none'); % no border
uistack(findobj(gca,'Type','patch'),'bottom'); % send the patch behind curves
% ax = gca;
% axpos = ax.Position; % [x y w h] normalized
% xl = xlim;
% yl = ylim;
%
% % Convert axis coords normalized figure coords
% toNorm = @(x,y) [ ...
% axpos(1) + (x - xl(1)) / (xl(2)-xl(1)) * axpos(3), ...
% axpos(2) + (y - yl(1)) / (yl(2)-yl(1)) * axpos(4) ...
% ];
%
% % Choose vertical placement (10% above bottom of axis)
% y_arrow = yl(1) * (yl(2)/yl(1))^0.10; % works with log-scale axes
%
% % === Arrow 1: x3 <-> x4 ======================================
% p1 = toNorm(x3, y_arrow);
% p2 = toNorm(x4, y_arrow);
%
% annotation('doublearrow', ...
% [p1(1) p2(1)], [p1(2) p2(2)], ...
% 'Color', [0 0 0], 'LineWidth', 1.4);
%
% % === Arrow 2: x2 <-> x5 ======================================
% p3 = toNorm(x2, y_arrow);
% p4 = toNorm(x5, y_arrow);
%
% annotation('doublearrow', ...
% [p3(1) p4(1)], [p3(2) p4(2)], ...
% 'Color', [0 0 0], 'LineWidth', 1.4);
end
% pos = 1e3.*[2.7770 1.2017 1.4000 0.3200];
% set(fig, 'Position', pos);
%% === EXPORT ===
% outfile = 'C:\Users\Silas\Documents\latex\JLT_400G copy\media\matlab2tikz\wavelength_analysis.tikz';
% matlab2tikz(outfile, ...
% 'width','\fwidth', ...
% 'height','\fheight', ...
% 'showInfo',false, ...
% 'extraAxisOptions',{ ...
% 'legend style={font=\footnotesize}', ...
% 'legend columns=1' ...
% });
%% ============================================================
% DECISION LOGIC (INLINE FUNCTIONS)
% ============================================================
function pe = decide_preemph(M, eq)
% PRE-EMPH RULES:
switch M
case 4
if eq == equalizer_structure.vnle
pe = 1; % PAM4: VNLE pre-emph on
else
pe = 0; % PAM4: all others off
end
case {6,8}
pe = 1; % PAM6/8: all pre-emph on
otherwise
pe = 0;
end
end
function flag = decide_precoded(M, eq)
% PRE-CODE RULES:
if eq == equalizer_structure.vnle_db_mlse
flag = 1; % Always for DB-target
elseif eq == equalizer_structure.ml_mlse && M == 4
flag = 1; % PAM4: ML-based precoded
else
flag = 0;
end
end

View File

@@ -0,0 +1,132 @@
database_type = 'mysql';
dataBase = 'labor_highspeed';
db = DBHandler("dataBase", dataBase, "type", database_type);
%% FILTER QUERY
fp = QueryFilter();
fp.where('Runs', 'fiber_length','EQUALS', 2);
fp.where('Runs', 'wavelength','EQUALS', 1310);
fp.where('Runs', 'rop_attenuation','EQUALS', 0);
fields = db.getTableFieldNames('power_state_info');
fields = [fields; db.getTableFieldNames('dashboard_ungrouped_alltime')];
[dataTable,~] = db.queryDB(fp, fields);
%% ---- CONFIG ----
cfg = struct;
cfg.x_axis = 'grossrate';
cfg.y_axis = 'BER';
cfg.y_scale = 'log';
cfg.outlier = 'mad';
cfg.show_raw = false;
cfg.show_spread = 'none';
cfg.agg = 'min';
cfg.show_precoded = 1;
cfg.fec_lines = [];
cfg.plot = struct;
cfg.plot.use_cbrewer2 = false;
cfg.plot.lineWidth = 2.0;
cfg.plot.errWidth = 1.2;
cfg.plot.scatterAlpha = 0.35;
cfg.plot.legendLocation = 'best';
cfg.plot.fecLineWidth = 2.4;
cfg.plot.custom_colors_scatter = []; % disabled
%% ---- DSP DEFINITIONS ----
DSP(1).name = 'VNLE';
DSP(1).eq = equalizer_structure.vnle;
DSP(1).color = clr.Paired.red;
DSP(1).lightcolor = clr.Paired.lightred;
DSP(2).name = 'VNLE PF MLSE';
DSP(2).eq = equalizer_structure.vnle_pf_mlse;
DSP(2).color = clr.Paired.green;
DSP(2).lightcolor = clr.Paired.lightgreen;
DSP(3).name = 'VNLE DB MLSE';
DSP(3).eq = equalizer_structure.vnle_db_mlse;
DSP(3).color = clr.Paired.blue;
DSP(3).lightcolor = clr.Paired.lightblue;
DSP(4).name = 'ML MLSE';
DSP(4).eq = equalizer_structure.ml_mlse;
DSP(4).color = clr.Paired.purple;
DSP(4).lightcolor = clr.Paired.lightpurple;
%% ---- GRID CONFIG ----
rows = 3; % PAM 4,6,8
cols = 4; % DSP schemes
pam = [4 6 8];
cfg.figure_number = 46;
fig = figure(cfg.figure_number); clf;
t = tiledlayout(rows, cols, ...
'TileSpacing','compact', ...
'Padding','compact');
cfg.group_by = {'equalizer_structure','pre_emph'};
cfg.plot.use_cbrewer2 = false;
%% ==== MAIN PLOT LOOP =====
for r = 1:rows
Mlev = pam(r);
for c = 1:cols
ax = nexttile(t, (r-1)*cols + c);
cfg.ax = ax;
% ---- PRE-EMPH = 1 ----
cfg.filters = struct('is_mpi',0,'pam_level',Mlev, ...
'equalizer_structure',DSP(c).eq, ...
'pre_emph',1);
cfg.plot.custom_colors = DSP(c).lightcolor;
cfg.plot.custom_linetypes = {'-'};
[~, M1] = plot_measurements_gpt(dataTable, cfg);
% ---- PRE-EMPH = 0 ----
cfg.filters.pre_emph = 0;
cfg.plot.custom_colors = DSP(c).color;
cfg.plot.custom_linetypes = {'-'};
[~, M0] = plot_measurements_gpt(dataTable, cfg);
% Axis limits
if Mlev == 4
ylim([1e-5 0.3]);
elseif Mlev == 6
ylim([6e-4 0.1]);
elseif Mlev == 8
ylim([9e-4 0.1]);
end
% ---- FEC lines ----
yline([2.2e-4 4.85e-3 2e-2], ...
'LineWidth',1.1, 'Color',[0.2 0.2 0.2], ...
'LineStyle',':','HandleVisibility','off');
beautifyBERplot;
% ---- Remove redundant labels ----
if c > 1, ax.YLabel = []; end
if r < rows, ax.XLabel = []; end
grid(ax,'on'); box(ax,'on');
end
end
%% ---- FIXED FIGURE SIZE ----
pos = 1e3.*[0.1070 0.5497 1.4113 0.6847];
set(fig, 'Position', pos);
% %% === EXPORT ===
% outfile = 'C:\Users\Silas\Documents\latex\JLT_400G copy\media\matlab2tikz\compare_pre_emphasis.tikz';
% matlab2tikz(outfile, ...
% 'width','\fwidth', ...
% 'height','\fheight', ...
% 'showInfo',false, ...
% 'extraAxisOptions',{ ...
% 'legend style={font=\footnotesize}', ...
% 'legend columns=1' ...
% });

View File

@@ -0,0 +1,279 @@
dsp_options.storage_path = 'Z:\2024\sioe_labor\';
dsp_options.max_occurences = 1;
database = DBHandler("dataBase", 'labor_highspeed', "type", 'mysql' );
cols = cbrewer2('BuPu',25);
cols = [cols(end-10:2:end,:)];
cols = cbrewer2('Set1',6);
fignum = 200;
fig=figure(fignum);clf;
dbmode = 0;
% 1 - PAM 4 with preemphasis
fp = QueryFilter();
M = 8;
rate = [360e9];
fp.where('Runs', 'pam_level','EQUALS', M);
fp.where('Runs', 'bitrate','EQUALS', rate);%360,390
fp.where('Runs', 'fiber_length','EQUALS', 2);
fp.where('Runs', 'wavelength','EQUALS', 1310);
fp.where('Runs', 'db_mode','EQUALS', dbmode);
fp.where('Runs', 'rop_attenuation','EQUAL', 0);
[dataTable,~] = database.queryDB(fp, database.getTableFieldNames('Runs'));
dataTable = queryRunid(dataTable.run_id, database);
fsym = dataTable.symbolrate;
M = double(dataTable.pam_level);
duob_mode = db_mode(strrep(dataTable.db_mode,'"',''));
% Load and Sync signal data from DB
[Tx_bits, Symbols, Scpe_cell, ~] = loadAndSyncSignalDataFromDb(dataTable, dsp_options);
Scpe_sig_syncd = Scpe_cell{1};
Scpe_sig_syncd.eye(fsym,M,"fignum",rate.*1e-9*M+1,"displayname",' Eye of Signal');
%%%%%% SNR CHEAT - Avges the measured signal occurences found after correlation in "tsynch" %%%%%%
average_signals = 1;
if average_signals
Scpe_sig_avg = Scpe_sig_syncd;
scope_mean = zeros(size(Scpe_cell{1}.signal));
for n=1:numel(Scpe_cell)
scope_mean = scope_mean + Scpe_cell{n}.signal;
end
scope_mean = scope_mean ./ n;
Scpe_sig_avg.signal = scope_mean;
Scpe_sig_avg.spectrum("displayname","Scope PSD","fignum",20,"normalizeTo0dB",1);
Scpe_sig_avg.plot("displayname","Scope raw signal","fignum",27,"clear",1);
Scpe_sig_avg = Scpe_sig_avg.*1.25;
Scpe_sig_avg.eye(fsym,M,"fignum",rate.*1e-9*M,"displayname",' Eye of AVG Signal');
end
% Preprocess signal
Scpe_sig = preprocessSignal(Scpe_sig_avg, Symbols, fsym);
Scpe_sig.eye(fsym,M,"fignum",M*10);
%% === EXPORT TO TIKZ ===
% outfile = ['C:\Users\Silas\Documents\latex\JLT_400G_submission\media\matlab2tikz\eye_pam_',num2str(M),'-2.tikz'];
% % outfile = ['C:\Users\Silas\Documents\latex\JLT_400G copy\media\matlab2tikz\vnle_optimization.tikz'];
% matlab2tikz(outfile, ...
% 'width','\fwidth', ...
% 'height','\fheight', ...
% 'showInfo',false, ...
% 'extraAxisOptions',{ ...
% 'legend style={font=\footnotesize}', ...
% 'legend columns=1' ...
% } );
%%
if duob_mode == db_mode.no_db && M == 6 %only for PAM-6 and no duobinary precoding, otherwise leads to false sequence estimation
trellexlusion = 1;
else
trellexlusion = 0;
end
mlse_db_ = MLSE("DIR",[1,1],"duobinary_output",0,"M",M,"trellis_states",PAMmapper(M,0).levels,'scale_mode',2,'trellis_exclusion',trellexlusion,'trellis_state_mode',3);
len_tr = 4096*2;
ffe_order = [50, 5, 5];
dfe_order = [0, 0, 0];
pf_ncoeffs = 1;
mu_ffe = [0.0001, 0.0008, 0.001];
mu_dfe = 0.0004;
mu_dc = 0.005;
dc_buffer_len = 1;
mu_tr = 0;
mu_dd = 0.05;
adaption= 1;
use_dd_mode = 1;
ffe_order = [50, 5, 5];
eq_ = EQ("Ne",ffe_order,"Nb",dfe_order,"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
dbt_results = duobinary_target(eq_, mlse_db_, M, Scpe_sig, Symbols, Tx_bits, ...
"precode_mode", duob_mode, ...
'showAnalysis', 1,...
"postFFE", []);
%% === FINAL FIGURE SIZE ===
% Existing figure numbers
figEye = 249;
figConst = 341;
% Find axes in the source figures
srcAxEye = findobj(figEye, 'Type', 'axes');
srcAxConst = findobj(figConst, 'Type', 'axes');
% Create new combined figure
figCombined = figure;
t = tiledlayout(figCombined, 1, 2);
t.TileSpacing = 'compact';
t.Padding = 'compact';
% ------------------------------------------------------------
% LEFT TILE: EYE DIAGRAM
% ------------------------------------------------------------
ax1 = nexttile(t, 1);
hold(ax1, 'on')
% Copy children (images, lines, patches, hist objects, etc.)
copyobj(srcAxEye.Children, ax1);
% Copy labels and title
ax1.XLabel.String = srcAxEye.XLabel.String;
ax1.YLabel.String = srcAxEye.YLabel.String;
ax1.Title.String = srcAxEye.Title.String;
% Copy axis limits
ax1.XLim = srcAxEye.XLim;
ax1.YLim = srcAxEye.YLim;
ax1.YDir = srcAxEye.YDir;
% Copy ticks + labels EXACTLY (including remapped/scaled ones)
ax1.XTick = srcAxEye.XTick;
ax1.XTickLabel = srcAxEye.XTickLabel;
ax1.YTick = srcAxEye.YTick;
ax1.YTickLabel = srcAxEye.YTickLabel;
% Copy colormap + clim (important for density eye)
colormap(ax1, colormap(srcAxEye.Parent));
ax1.CLim = srcAxEye.CLim;
% Copy any style props that matter
ax1.TickDir = srcAxEye.TickDir;
ax1.TickLength = srcAxEye.TickLength;
ax1.FontSize = srcAxEye.FontSize;
ax1.Box = srcAxEye.Box;
grid(ax1,'on');
% ------------------------------------------------------------
% RIGHT TILE: CONSTELLATION HISTOGRAM
% ------------------------------------------------------------
ax2 = nexttile(t, 2);
hold(ax2, 'on')
copyobj(srcAxConst.Children, ax2);
% Copy labels and title
ax2.XLabel.String = srcAxConst.XLabel.String;
ax2.YLabel.String = srcAxConst.YLabel.String;
ax2.Title.String = srcAxConst.Title.String;
% The histogram uses the same y-axis as the eye
% Extract mapping from eye
rawTicks = ax1.YTick;
rawLabelsCell = ax1.YTickLabel;
trueVoltages = str2double(rawLabelsCell);
% Apply true voltages to the histogram axis
ax2.XTick = flip(trueVoltages);
ax2.XTickLabel = flip(rawLabelsCell);
% Set histogram y-limits to match the actual voltages
ax2.XLim = [min(trueVoltages) max(trueVoltages)];
% Ensure eye diagram prints the same (we *do not* touch ax1.YLim)
ax1.XTickLabel = rawLabelsCell;
% Copy colormap (your histogram uses same palette)
colormap(ax2, colormap(srcAxConst.Parent));
% Style properties
ax2.TickDir = srcAxConst.TickDir;
ax2.TickLength = srcAxConst.TickLength;
ax2.FontSize = srcAxConst.FontSize;
ax2.Box = srcAxConst.Box;
grid(ax2,'on');
% ============================================================
% remove right y-axis completely
% ============================================================
ax2.XAxis.Visible = 'off'; % hides ticks + labels + axis line
% BUT we still keep the YTick positions internally for alignment:
% ax2.YTick = <values already set earlier> ;
% ============================================================
% minimize distance between the two plots
% ============================================================
t.TileSpacing = 'none'; % no space between tiles
t.Padding = 'none'; % no outer padding
% Also reduce internal padding for each axis
ax1.Position(3) = ax1.Position(3) + 0.02; % widen eye a bit
ax2.Position(1) = ax2.Position(1) - 0.02; % pull histogram closer
% Keep left axis grid visible
ax2.YGrid = 'off';
%
% =====================================================================
% FINAL POLISHING: unified visual style
% =======================================================================
% --- unified font size ---
FS = 12;
set([ax1 ax2], 'FontSize', FS);
% --- unified axis line width (outline stroke thickness) ---
LW = 1.0;
set([ax1 ax2], 'LineWidth', LW);
% --- unified tick length ---
TL = [.015 .015];
set([ax1 ax2], 'TickLength', TL);
% --- unified grid style ---
set([ax1 ax2], 'XGrid', 'on', 'YGrid', 'on');
set([ax1 ax2], 'GridLineStyle', '--');
set([ax1 ax2], 'GridAlpha', 0.2);
% --- remove right y-axis ticks and labels ---
ax2.YAxis.Visible = 'off';
% --- copy colormap + CLim from the eye to histogram (synchronize look) ---
colormap(ax1, colormap(srcAxEye.Parent));
colormap(ax2, colormap(srcAxEye.Parent));
ax2.CLim = ax1.CLim;
% --- minimal spacing between tiles ---
t.TileSpacing = 'none';
t.Padding = 'none';
% --- pull the panels together (touching boundary effect) ---
pos1 = ax1.Position;
pos2 = ax2.Position;
% Shift histogram left until the outlines touch
pos2(1) = pos1(1) + pos1(3) - 0.002; % 0.002 = fine overlap control
ax2.Position = pos2;
% Expand histogram slightly, remove white band
pos2 = ax2.Position;
pos2(3) = pos2(3) + 0.01;
ax2.Position = pos2;
% Ensure the left plot stays correct after the move
ax1.Position = pos1;
% --- enforce same visible outline ---
% For ax2, create a fake left spine (since YAxis is hidden)
ax2.Box = 'on'; % keep outline but no ticks on the right
ax1.Box = 'on';
ax2.View = [90 -90];

View File

@@ -0,0 +1,221 @@
%% ============================================================
% GRID: NGMI, AIR, HD-NetRate, SD-NetRate (1 × 4)
% ============================================================
db = DBHandler("dataBase","labor_highspeed","type","mysql");
%% --- Base DB Filters (shared across all curves)
fp = QueryFilter();
fp.where('Runs','fiber_length','EQUALS', 2);
fp.where('Runs','wavelength','EQUALS', 1310);
fp.where('Runs','rop_attenuation','EQUALS', 0);
fp.where('Runs','is_mpi','EQUALS', 0);
fields = db.getTableFieldNames('dashboard_ungrouped_alltime');
[dataTable,~] = db.queryDB(fp, fields);
%% === Curve Definitions =======================================
curves = struct;
% PAM-8 VNLE PF MLSE no_emph = 1 RED
curves(1).pam = 8;
curves(1).eq = equalizer_structure.vnle_pf_mlse;
curves(1).pre = 0;
curves(1).color = clr.Paired.red;
curves(1).mkr = 'o';
% PAM-6 VNLE PF MLSE no_emph = 1 BLUE
curves(2).pam = 6;
curves(2).eq = equalizer_structure.vnle_pf_mlse;
curves(2).pre = 1;
curves(2).color = clr.Paired.blue;
curves(2).mkr = 'square';
% PAM-4 VNLE DB MLSE pre_emph = 0 GREEN
curves(3).pam = 4;
curves(3).eq = equalizer_structure.vnle_db_mlse;
curves(3).pre = 0;
curves(3).color = clr.Paired.green;
curves(3).mkr = 'diamond';
%% === Prepare Analysis Config ==================================
base = struct;
base.group_by = {'equalizer_structure','pre_emph'};
base.x_axis = 'symbolrate';
base.outlier = 'none';
base.show_raw = false;
base.filters = struct; % will be filled per curve
%% === Precompute All Curves ====================================
results = struct;
for k = 1:numel(curves)
% --- BER ---
cfg = base;
cfg.y_axis = 'BER';
cfg.agg = 'min';
cfg.filters = struct('pam_level', curves(k).pam, ...
'equalizer_structure', curves(k).eq, ...
'pre_emph', curves(k).pre);
A = analyze_measurements_gpt(dataTable, cfg);
cfg.x_axis = 'grossrate';
B = analyze_measurements_gpt(dataTable, cfg);
results(k).baudr = A.group{1}.x;
results(k).gross = B.group{1}.x;
if curves(k).pam == 4
results(k).ber = A.group{1}.y_precoded;
else
results(k).ber = A.group{1}.y;
end
% --- NGMI ---
cfg.y_axis = 'NGMI';
cfg.agg = 'max';
A = analyze_measurements_gpt(dataTable, cfg);
results(k).ngmi = A.group{1}.y;
% --- AIR ---
cfg.y_axis = 'AIR';
cfg.agg = 'max';
A = analyze_measurements_gpt(dataTable, cfg);
results(k).air = A.group{1}.y;
results(k).air = results(k).ngmi .* results(k).gross;
% --- Net Rates ---
tp = TransmissionPerformance;
results(k).ndr = tp.calculateNetRate(results(k).gross, ...
'NGMI', results(k).ngmi, ...
'BER', results(k).ber);
end
%% ============================================================
% FIGURE: 1 × 4 GRID
% ============================================================
fig = figure(71); clf;
t = tiledlayout(1,4, 'TileSpacing','compact', 'Padding','compact');
lw = 1.0;
% === NGMI vs Grossrate ===
ax = nexttile(t,1);
hold on;
for k = 1:3
plot(results(k).baudr, results(k).ngmi, ...
'LineWidth', lw, ...
'Color', curves(k).color, ...
'MarkerSize', 1, ...
'MarkerFaceColor', curves(k).color,...
'Marker',curves(k).mkr);
end
ylabel('NGMI');
xlabel('Baud rate [GBd]');
xlim([100 210]);
xticks(100:15:225);
ylim([0.9, 1]);
grid minor; box on;
beautifyBERplot("logscale",0,"setmarkers",0);
% === AIR vs Grossrate ===
ax = nexttile(t,2);
hold on;
for k = 1:3
plot(results(k).baudr, results(k).air, ...
'-', 'LineWidth', lw, ...
'Color', curves(k).color, ...
'MarkerSize', 2, ...
'MarkerFaceColor', curves(k).color,'Marker',curves(k).mkr);
end
ylabel('AIR [Gb/s]');
xlabel('Baud rate [GBd]');
ylim([280 430]);
yticks(280:30:440)
xlim([100 210]);
xticks(100:15:225);
grid minor; box on;
beautifyBERplot("logscale",0,"setmarkers",0);
yline(400,'LineStyle','--');
% === SD-FEC Net Rate ===
ax = nexttile(t,3);
hold on;
for k = 1:3
plot(results(k).baudr, results(k).ndr.SDHD.NetRate, ...
'LineWidth', lw, ...
'Color', curves(k).color, ...
'MarkerSize', 2, ...
'MarkerFaceColor', curves(k).color,...
'Marker',curves(k).mkr);
end
ylabel('NDR [Gb/s]');
xlabel('Baud rate [GBd]');
ylim([280 430]);
yticks(280:30:440)
xlim([100 210]);
xticks(100:15:225);
grid minor; box on;
beautifyBERplot("logscale",0,"setmarkers",0);
yline(400,'LineStyle','--');
% === HD-FEC Net Rate ===
ax = nexttile(t,4);
hold on;
for k = 1:3
% plot(results(k).baudr, results(k).ndr.STAIR.NetRate, ...
% '-', 'LineWidth', lw, ...
% 'Color', curves(k).color, ...
% 'MarkerSize', 4,'Marker','+', ...
% 'MarkerFaceColor', curves(k).color);
plot(results(k).baudr, results(k).ndr.O_FEC.NetRate, ...
':', 'LineWidth', lw, ...
'Color', curves(k).color, ...
'MarkerSize', 2,...
'MarkerFaceColor', curves(k).color,...
'Marker',curves(k).mkr);
plot(results(k).baudr, results(k).ndr.KP4_hamming.NetRate, ...
'--', 'LineWidth', lw, ...
'Color', curves(k).color, ...
'MarkerSize', 2,'Marker','diamond', ...
'MarkerFaceColor', curves(k).color,...
'Marker',curves(k).mkr);
end
yline(400,'LineStyle','--');
ylabel('');
xlabel('Baud rate [GBd]');
ylim([280 430]);
yticks(280:30:440)
xlim([100 210]);
xticks(100:15:225);
grid minor; box on;
beautifyBERplot("logscale",0,"setmarkers",0);
% === FINAL FIGURE SIZE ===
pos = 1e3.*[0.7950 1.1150 1.4113 0.1900];
set(fig, 'Position', pos);
% % % %% === EXPORT ===
outfile = 'C:\Users\Silas\Documents\latex\JLT_400G copy\media\matlab2tikz\compare_ndr_v3.tikz';
matlab2tikz(outfile, ...
'width','\fwidth', ...
'height','\fheight', ...
'showInfo',false, ...
'extraAxisOptions',{ ...
'legend style={font=\footnotesize}', ...
'legend columns=1' ...
'every axis/.append style={font=\scriptsize}',...
'minor grid style={line width=0.2pt, solid, color=black!10}',...
'grid style={line width=0.4pt, solid, color=black!20}',...
'grid style={dashed}',...
});

View File

@@ -0,0 +1,180 @@
%% ============================================================
% GRID (1 × 4):
% 1) NGMI overview (PAM4+PAM6+PAM8 superimposed)
% 2) PAM-4 tile (AIR + SD-NDR + HD-NDR)
% 3) PAM-6 tile
% 4) PAM-8 tile
% ============================================================
db = DBHandler("dataBase","labor_highspeed","type","mysql");
%% --- Base DB Filters (shared across all curves)
fp = QueryFilter();
fp.where('Runs','fiber_length','EQUALS', 2);
fp.where('Runs','wavelength','EQUALS', 1310);
fp.where('Runs','rop_attenuation','EQUALS', 0);
fp.where('Runs','is_mpi','EQUALS', 0);
fields = db.getTableFieldNames('dashboard_ungrouped_alltime');
[dataTable,~] = db.queryDB(fp, fields);
%% === CURVE DEFINITIONS =================================================
curves = struct;
curves(1).pam = 8;
curves(1).eq = equalizer_structure.vnle_pf_mlse;
curves(1).pre = 0;
curves(1).color = clr.Paired.red;
curves(2).pam = 6;
curves(2).eq = equalizer_structure.vnle_pf_mlse;
curves(2).pre = 1;
curves(2).color = clr.Paired.blue;
curves(3).pam = 4;
curves(3).eq = equalizer_structure.vnle_db_mlse;
curves(3).pre = 0;
curves(3).color = clr.Paired.green;
% === ANALYSIS ENGINE (extract BER/NGMI/AIR/netrates) ===================
base = struct;
base.group_by = {'equalizer_structure','pre_emph'};
base.x_axis = 'grossrate';
base.outlier = 'none';
base.show_raw = false;
results = struct;
for k = 1:numel(curves)
% ========== BER ==========
cfg = base;
cfg.y_axis = 'BER';
cfg.agg = 'min';
cfg.filters = struct('pam_level', curves(k).pam, ...
'equalizer_structure', curves(k).eq, ...
'pre_emph', curves(k).pre);
A = analyze_measurements_gpt(dataTable, cfg);
results(k).gross = A.group{1}.x;
if curves(k).pam == 4
results(k).ber = A.group{1}.y_precoded;
else
results(k).ber = A.group{1}.y;
end
% ========== NGMI ==========
cfg.y_axis = 'NGMI'; cfg.agg = 'max';
A = analyze_measurements_gpt(dataTable, cfg);
results(k).ngmi = A.group{1}.y;
% ========== AIR ==========
cfg.y_axis = 'AIR'; cfg.agg = 'max';
A = analyze_measurements_gpt(dataTable, cfg);
results(k).air = A.group{1}.y;
% ========== NET RATES ==========
tp = TransmissionPerformance;
results(k).ndr = tp.calculateNetRate(results(k).gross, ...
'NGMI', results(k).ngmi, ...
'BER', results(k).ber);
end
% ============================================================
% FIGURE
% ============================================================
fig = figure(3);
t = tiledlayout(1,4,'TileSpacing','compact','Padding','compact');
lw = 1.7;
% =======================================================================
% (1) NGMI OVERVIEW TILE (all 3 curves)
% =======================================================================
ax = nexttile(t,1); hold on;
for k = 1:3
plot(results(k).gross, results(k).ngmi, ...
'-o', 'Color', curves(k).color, ...
'LineWidth',lw,'MarkerSize',5, ...
'MarkerFaceColor',curves(k).color);
end
ylabel('NGMI');
xlabel('Grossrate [Gb/s]');
ylim([0.9 1]); % your chosen limits
xlim([300 480]);
xticks(300:30:480)
grid minor; box on;
beautifyBERplot;
% =======================================================================
% (24) PAM-SPECIFIC TILES: AIR, SD-NDR, HD-NDR
% =======================================================================
pam_order = [4 6 8]; % left right
for ti = 1:3
pam_target = pam_order(ti);
ax = nexttile(t, 1+ti); hold on;
% find matching curve
for k = 1:3
if curves(k).pam ~= pam_target, continue; end
col = curves(k).color;
% AIR
plot(results(k).gross, results(k).air, ...
'-','Color',col,'LineWidth',lw,'Marker','*', ...
'MarkerSize',5,'MarkerFaceColor',col,'DisplayName','AIR');
% SD-based net rate
plot(results(k).gross, results(k).ndr.SDHD.NetRate, ...
'--','Color',col,'LineWidth',lw,'Marker','v', ...
'MarkerSize',5,'MarkerFaceColor',col,'DisplayName','SD+HD');
% HD-based net rate
plot(results(k).gross, results(k).ndr.STAIR.NetRate, ...
':','Color',col,'LineWidth',lw,'Marker','x', ...
'MarkerSize',5,'MarkerFaceColor',col,'DisplayName','HD-FEC (Staircase)');
% HD-based net rate
plot(results(k).gross, results(k).ndr.O_FEC.NetRate, ...
'LineStyle','-.','Color',col,'LineWidth',lw,'Marker','+', ...
'MarkerSize',5,'MarkerFaceColor',col,'DisplayName','O-FEC');
% HD-based net rate
plot(results(k).gross, results(k).ndr.KP4_hamming.NetRate, ...
'LineStyle','-','Color',col,'LineWidth',lw,'Marker','x', ...
'MarkerSize',5,'MarkerFaceColor',col,'DisplayName','KP4+Hamming');
end
ylabel('NDR [Gb/s]');
xlabel('Grossrate [Gb/s]');
ylim([300 440]); % your chosen limits
yticks(300:20:480)
xlim([300 480]);
xticks(300:30:480)
grid minor; box on;
beautifyBERplot;
yline(400,'HandleVisibility','off');
end
% === FIX FIGURE SIZE FOR TIKZ ==========================================
if 0
pos = 1e3.*[0.3643 0.9943 1.4113 0.2120];
set(fig,'Position',pos);
% outfile = 'C:\Users\Silas\Documents\latex\JLT_400G copy\media\matlab2tikz\compare_ndr.tikz';
% matlab2tikz(outfile, ...
% 'width','\fwidth', ...
% 'height','\fheight', ...
% 'showInfo',false, ...
% 'extraAxisOptions',{ ...
% 'legend style={font=\footnotesize}', ...
% 'legend columns=1' ...
% });
end

View File

@@ -0,0 +1,153 @@
%% ============================================================
% LOAD DATA (PAM-4, sweep over ROP)
% ============================================================
database_type = 'mysql';
db = DBHandler("dataBase", "labor_highspeed", "type", database_type);
pam_level = 4;
fiberL = 1; % 1 km
wlen = 1310;
baudrate = 360e9;
fp = QueryFilter();
fp.where('Runs','pam_level','EQUALS', pam_level);
fp.where('Runs','fiber_length','EQUALS', fiberL);
fp.where('Runs','wavelength','EQUALS', wlen);
fp.where('Runs','bitrate','EQUALS', baudrate);
fp.where('Runs','power_pd_in','LESS_THAN', 7);
fields = [
db.getTableFieldNames('power_state_info');
db.getTableFieldNames('dashboard_ungrouped_alltime')
];
[dataTable,~] = db.queryDB(fp, fields);
%% ============================================================
% DSP SCHEMES (Best combinations only)
% ============================================================
curves = struct;
curves(1).name = 'VNLE';
curves(1).eq = equalizer_structure.vnle;
curves(1).color = clr.Paired.red;
curves(2).name = 'PF + MLSE';
curves(2).eq = equalizer_structure.vnle_pf_mlse;
curves(2).color = clr.Paired.green;
curves(3).name = 'DB-target + MLSE';
curves(3).eq = equalizer_structure.vnle_db_mlse;
curves(3).color = clr.Paired.blue;
curves(4).name = 'ML-based MLSE';
curves(4).eq = equalizer_structure.ml_mlse;
curves(4).color = clr.Paired.purple;
%% ============================================================
% ANALYSIS ENGINE (No plotting)
% ============================================================
results = struct;
for k = 1:numel(curves)
pre_emph = decide_preemph(pam_level,curves(k).eq);
precoded = decide_precoded(pam_level,curves(k).eq);
cfg = struct;
cfg.x_axis = 'power_mzm'; % ROP axis
cfg.y_axis = 'BER';
cfg.agg = 'min';
cfg.outlier = 'none';
cfg.show_raw = false;
cfg.filters = struct( ...
'pam_level', pam_level, ...
'fiber_length', fiberL, ...
'wavelength', wlen, ...
'bitrate', baudrate, ...
'is_mpi', 0, ...
'equalizer_structure', curves(k).eq, ...
'pre_emph', pre_emph);
A = analyze_measurements_gpt(dataTable, cfg);
results(k).x = A.group{1}.x;
if precoded
results(k).ber = A.group{1}.y_precoded;
else
results(k).ber = A.group{1}.y;
end
end
%% ============================================================
% PLOT BER vs ROP (Single Axis)
% ============================================================
fig = figure(); clf; hold on;
lw = 2.0;
ms = 7;
for k = 1:numel(curves)
plot(results(k).x, results(k).ber, ...
'-o', ...
'Color', curves(k).color, ...
'MarkerFaceColor', curves(k).color, ...
'MarkerSize', ms, ...
'LineWidth', lw, ...
'DisplayName', curves(k).name);
end
set(gca,'YScale','log');
grid on;
xlabel('ROP / Power (MZM) [dBm]');
ylabel('BER');
ylim([1e-4 2e-1]);
title(sprintf('BER vs ROP PAM-%d, %.0f km, %.0f GBd, %.0f nm', ...
pam_level, fiberL, baudrate*1e-9, wlen));
legend('Location','best');
beautifyBERplot();
pos = 1e3.*[0.2 0.6 1.3 0.4];
set(fig, 'Position', pos);
%% ============================================================
% DECISION LOGIC (INLINE FUNCTIONS)
% ============================================================
function pe = decide_preemph(M, eq)
% PRE-EMPH RULES:
switch M
case 4
if eq == equalizer_structure.vnle
pe = 1; % PAM4: VNLE pre-emph on
else
pe = 0; % PAM4: all others off
end
case {6,8}
pe = 1; % PAM6/8: all pre-emph on
otherwise
pe = 0;
end
end
function flag = decide_precoded(M, eq)
% PRE-CODE RULES:
if eq == equalizer_structure.vnle_db_mlse
flag = 1; % Always for DB-target
elseif eq == equalizer_structure.ml_mlse && M == 4
flag = 1; % PAM4: ML-based precoded
else
flag = 0;
end
end

View File

@@ -0,0 +1,185 @@
dsp_options.storage_path = 'Z:\2024\sioe_labor\';
dsp_options.max_occurences = 1;
database = DBHandler("dataBase", 'labor_highspeed', "type", 'mysql' );
rates = [420e9];
cols = cbrewer2('BuPu',25);
cols = [cols(end-10:2:end,:)];
cols = cbrewer2('Set1',6);
fignum = 200;
fig=figure(fignum);clf;
for dbmode = 1%length(rates)
if 0
rcalpha = 0.05;
fsym = rates/2;
pulsef = 1;
Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rrc","pulselength",16,"alpha",rcalpha);
Pamsource = PAMsource(...
"fsym",fsym,"M",4,"order",18,"useprbs",0,...
"fs_out",fdac,...
"applyclipping",0,"clipfactor",1.2,...
"applypulseform",pulsef,"pulseformer",Pform,...
"randkey",20,...
"db_precode",dbmode,"db_encode",0,...
"mrds_code",0,"mrds_blocklength",512);
[Digi_sig,Symbols,Bits] = Pamsource.process();
Digi_sig = Digi_sig.normalize("mode","rms");
%%% 1) PLOT FULL RESPONSE SIGNAL
Digi_sig.spectrum("displayname","Full Response","fignum",fignum+dbmode,"normalizeToNyquist",0,"normalizeTo0dB",0,"color",[0.2,0.2,0.2],"linestyle",'-','addDCoffset',0,'normalizeToDC',1);
%%% 2) PLOT PREEMPH. TX SIGNAL
if dbmode == 0
maxamp = -37;
precomp_est = ChannelFreqResp("Nacq",2048,"Navg",100,"Ncp",63,'f_ref',Digi_sig.fs);
precomp_path = "C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\precomp";
precomp_fn = "lab_high_speed";
Digi_sig_pre = precomp_est.precomp(Digi_sig,'maxampdb',maxamp,'loadPath',precomp_path,'fileName',precomp_fn);
Digi_sig_pre = Digi_sig_pre.resample("fs_out",fdac);
Digi_sig_pre= Digi_sig_pre.normalize("mode","rms");
Digi_sig_pre.spectrum("displayname","Strong Precomp","fignum",fignum+dbmode,"normalizeToNyquist",0,"normalizeTo0dB",0,"color",[0,0,0],"linestyle",'-.','addDCoffset',0,'normalizeToDC',1);
end
end
% 1 - PAM 4 with preemphasis
fp = QueryFilter();
M = 4;
fp.where('Runs', 'pam_level','EQUALS', M);
fp.where('Runs', 'bitrate','EQUALS', rates);%360,390
fp.where('Runs', 'fiber_length','EQUALS', 2);
fp.where('Runs', 'wavelength','EQUALS', 1310); %1327.4
fp.where('Runs', 'db_mode','EQUALS', dbmode);
fp.where('Runs', 'rop_attenuation','EQUAL', 0);
[dataTable,~] = database.queryDB(fp, database.getTableFieldNames('Runs'));
dataTable = queryRunid(dataTable.run_id, database);
fsym = dataTable.symbolrate;
M = double(dataTable.pam_level);
% Load and Sync signal data from DB
[Tx_bits, Symbols, Scpe_cell, ~] = loadAndSyncSignalDataFromDb(dataTable, dsp_options);
% Preprocess signal
Scpe_sig = preprocessSignal(Scpe_cell{1}, Symbols, fsym);
Scpe_sig = Scpe_cell{1};
%%% 3) PLOT DB Tgt. SIGNAL
if 1
DB_Symbols = Duobinary().encode(Symbols);
DB_Symbols.spectrum("fignum",fignum+dbmode,"normalizeTo0dB",1,"displayname",'DB-Response','addDCoffset',0,'color',clr.Set1.blue,'normalizeToNyquist',0,'linestyle','--');
end
%%% 4) Plot RX Signal
Scpe_sig.spectrum("fignum",fignum+dbmode,"normalizeTo0dB",1,"displayname",'Rx','addDCoffset',1,'color',[0,0,0],'normalizeToNyquist',0,'linestyle',':');
Scpe_sig.eye(fsym,M,"fignum",47,"displayname",' Eye of AVG Signal');
% xline(Symbols.fs/2.*1e-9,'Color',cols(r,:),'HandleVisibility','off');
average_signals = 1;
if average_signals
Scpe_sig_avg = Scpe_sig;
scope_mean = zeros(size(Scpe_cell{1}.signal));
for n=1:numel(Scpe_cell)
scope_mean = scope_mean + Scpe_cell{n}.signal;
end
scope_mean = scope_mean ./ n;
Scpe_sig_avg.signal = scope_mean;
figure(20);hold on
Symbols.spectrum("fignum",20,"normalizeTo0dB",1,"displayname",'Full Response','addDCoffset',0,'color',clr.Set1.red,'normalizeToNyquist',0,'linestyle','--');
DB_Symbols.spectrum("fignum",20,"normalizeTo0dB",1,"displayname",'DB-Response','addDCoffset',0,'color',clr.Set1.blue,'normalizeToNyquist',0,'linestyle','--');
Scpe_sig_avg.spectrum("displayname","Scope PSD","fignum",20,"normalizeTo0dB",1,"addDCoffset",5);
Scpe_sig_avg.plot("displayname","Scope raw signal","fignum",27,"clear",1);
Scpe_sig_avg.eye(fsym,M,"fignum",48,"displayname",' Eye of AVG Signal');
end
fig = figure(fignum+dbmode);
if dbmode == 0
ylim([-22,12]);
else
ylim([-22,2]);
end
xlim([0,105]);
xticks(-100:20:100);
yticks(-20:10:10);
beautifyBERplot("logscale",0,"setmarkers",0)
pos = [100.3333 991.6667 358.0000 192.6667];
set(fig, 'Position', pos);
%%%%%%%%%%%%
drawnow;
% Do EQ and find alpha's
len_tr = 4096*2;
ffe_order = [50, 5, 5];
dfe_order = [0, 0, 0];
pf_ncoeffs = 1;
mu_ffe = [0.0001, 0.0008, 0.001];
mu_dfe = 0.0004;
mu_dc = 0.005;
%%% FULL RESP TARGET
eq_ = EQ("Ne",ffe_order,"Nb",dfe_order,"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",0);
pf_1 = Postfilter("ncoeff",1,"useBurg",1);
[eq_signal_sd, eq_noise] = eq_.process(Scpe_sig, Symbols);
% eq_noise.signal = eq_noise.signal - mean(eq_noise.signal);
% eq_noise = eq_noise.normalize("mode","rms");
[mlse_sig_sd,whitened_noise] = pf_1.process(eq_signal_sd, eq_noise);
fig = figure(fignum+dbmode+10); hold on
[h, w] = freqz(1, pf_1.coefficients, length(eq_noise), "whole", eq_noise.fs);
h = h / max(abs(h)); % Normalize the filter response
w_ = (w - eq_noise.fs / 2);
%%% DB TARGET
db_ref_sequence = Duobinary().encode(Symbols);
eq_ = EQ("Ne",ffe_order,"Nb",dfe_order,"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",0);
[eq_signal, db_noise] = eq_.process(Scpe_sig,db_ref_sequence);
% db_noise.signal = db_noise.signal - mean(db_noise.signal);
% db_noise = db_noise.normalize("mode","rms");
%%% 1-3) Plot EQ Noise EEN
figure(fignum+dbmode+10)
eq_noise.spectrum("displayname", 'Noise', "fignum", fignum+dbmode+10, "normalizeTo0dB", 0,"color",clr.Set1.green,"normalizeToDC",0,"addDCoffset",0);
if dbmode == 1
offset = 27.7;
else
offset = 29.8;
end
plot(w_ * 1e-9, 20 * log10(fftshift(abs(h)))-offset, 'DisplayName', ['Burg Coeffs: ', num2str(round(pf_1.coefficients, 2)), ' '], 'LineWidth', 1,'Color',clr.Set1.green,'LineStyle','--');
db_noise.spectrum("displayname", 'DBt. Noise', "fignum", fignum+dbmode+10, "normalizeTo0dB", 0,"color",clr.Set1.blue,"normalizeToDC",0,"addDCoffset",0);
ylim([-54,-25]);
xlim([0,105]);
xticks(0:20:110);
yticks(-50:10:10);
beautifyBERplot("logscale",0,"setmarkers",0)
pos = [100.3333 991.6667 358.0000 192.6667];
set(fig, 'Position', pos);
end
% === FINAL FIGURE SIZE ===

View File

@@ -0,0 +1,124 @@
%% ============================================================
% LOAD DATA
% ============================================================
database_type = 'mysql';
db = DBHandler("dataBase", "labor_highspeed", "type", database_type);
M = 4; % PAM level for this analysis
fp = QueryFilter();
fp.where('Runs', 'pam_level', 'EQUALS', M);
fp.where('Runs', 'fiber_length', 'EQUALS', 10);
fp.where('Runs', 'bitrate', 'EQUALS', 360e9);
fp.where('Runs', 'is_mpi', 'EQUALS', 0);
fields = [
db.getTableFieldNames('power_state_info');
db.getTableFieldNames('dashboard_ungrouped_alltime')
];
[dataTable, ~] = db.queryDB(fp, fields);
%% ============================================================
% COMMON CONFIGURATION FOR ALL SUBPLOTS
% ============================================================
%% ============================================================
% DEFINE DSP ALGORITHMS FOR THE 4 SUBPLOTS
% ============================================================
curves = struct;
curves(1).name = 'VNLE';
curves(1).eq = equalizer_structure.vnle;
curves(1).pre = 0;
curves(1).color = clr.Paired.red;
curves(2).name = 'PF + MLSE';
curves(2).eq = equalizer_structure.vnle_pf_mlse;
curves(2).pre = 0;
curves(2).color = clr.Paired.green;
curves(3).name = 'DB-target + MLSE';
curves(3).eq = equalizer_structure.vnle_db_mlse;
curves(3).pre = 0;
curves(3).color = clr.Paired.blue;
curves(4).name = 'ML-based MLSE';
curves(4).eq = equalizer_structure.ml_mlse;
if M == 4
curves(4).pre = 0;
else
curves(4).pre = 1;
end
curves(4).color = clr.Paired.purple;
%% ============================================================
% ANALYSIS ENGINE NO PLOTTING
% ============================================================
results = struct;
for k = 1:numel(curves)
%% ---- BASE CONFIG ----
cfg = struct;
cfg.x_axis = 'wavelength';
cfg.y_axis = 'BER';
cfg.agg = 'min';
cfg.outlier = 'none';
% cfg.group_by = {'wavelength'};
cfg.show_raw = false;
cfg.filters = struct( ...
'pam_level', M, ...
'is_mpi', 0, ...
'bitrate', 360e9, ...
'fiber_length', 10, ...
'equalizer_structure', curves(k).eq, ...
'pre_emph', curves(k).pre);
%% ---- GET BER ----
cfg.y_axis = 'BER';
A = analyze_measurements_gpt(dataTable, cfg);
results(k).wavelength = A.group{1}.x;
if curves(k).eq == equalizer_structure.vnle_db_mlse || ...
curves(k).eq == equalizer_structure.ml_mlse
% DB and ML-based need precoded BER
results(k).ber = A.group{1}.y_precoded;
else
results(k).ber = A.group{1}.y;
end
end
%% ============================================================
% 1×4 TILED BER-vs-WAVELENGTH FIGURE
% ============================================================
fig=figure(901);
tiledlayout(1,4,'TileSpacing','compact','Padding','compact');
lw = 1.8; % line width
ms = 6; % marker size
for k = 1:numel(curves)
nexttile; hold on;
plot(results(k).wavelength, results(k).ber, ...
'-o', ...
'Color', curves(k).color, ...
'MarkerFaceColor', curves(k).color, ...
'MarkerSize', ms, ...
'LineWidth', lw);
set(gca,'YScale','log');
grid on;
xlabel('wavelength');
ylabel('BER');
title(curves(k).name);
ylim([1e-4, 0.1])
beautifyBERplot();
end
pos = 1e3.*[0.1070 0.5497 1.4113 0.3253];
set(fig, 'Position', pos);

View File

@@ -0,0 +1,160 @@
%% ============================================================
% PARAMETERS
% ============================================================
database_type = 'mysql';
db = DBHandler("dataBase", "labor_highspeed", "type", database_type);
pam_level = 4; % FIXED for this figure
baudrates = [300e9 330e9 360e9 390e9];
fiberL = 10;
fields = [
db.getTableFieldNames('power_state_info');
db.getTableFieldNames('dashboard_ungrouped_alltime')
];
%% ============================================================
% DEFINE DSP SCHEMES
% ============================================================
curves = struct;
curves(1).name = 'VNLE';
curves(1).eq = equalizer_structure.vnle;
curves(1).color = clr.Paired.red;
curves(2).name = 'PF + MLSE';
curves(2).eq = equalizer_structure.vnle_pf_mlse;
curves(2).color = clr.Paired.green;
curves(3).name = 'DB-target + MLSE';
curves(3).eq = equalizer_structure.vnle_db_mlse;
curves(3).color = clr.Paired.blue;
curves(4).name = 'ML-based MLSE';
curves(4).eq = equalizer_structure.ml_mlse;
curves(4).color = clr.Paired.purple;
%% ============================================================
% ANALYSIS results(b, k): b = baudrate index, k = DSP scheme index
% ============================================================
results = struct;
for b = 1:length(baudrates)
Rb = baudrates(b);
% --- query matching runs ---
fp = QueryFilter();
fp.where('Runs','pam_level','EQUALS', pam_level);
fp.where('Runs','fiber_length','EQUALS', fiberL);
fp.where('Runs','bitrate','EQUALS', Rb);
fp.where('Runs','is_mpi','EQUALS', 0);
[dataTable, ~] = db.queryDB(fp, fields);
for k = 1:numel(curves)
%% ---- DECIDE PRE-EMPH & PRECoded RULES for PAM-4 ----
pre_emph = decide_preemph(pam_level, curves(k).eq);
use_precoded = decide_precoded(pam_level, curves(k).eq);
%% ---- SETUP ANALYSIS CONFIG ----
cfg = struct;
cfg.x_axis = 'wavelength';
cfg.y_axis = 'BER';
cfg.agg = 'min';
cfg.outlier = 'none';
% cfg.group_by = {'wavelength'};
cfg.show_raw = false;
cfg.filters = struct( ...
'pam_level', pam_level, ...
'is_mpi', 0, ...
'bitrate', Rb, ...
'fiber_length', fiberL, ...
'equalizer_structure', curves(k).eq, ...
'pre_emph', pre_emph);
%% ---- RUN ANALYSIS ----
A = analyze_measurements_gpt(dataTable, cfg);
results(b,k).wavelength = A.group{1}.x;
if use_precoded
results(b,k).ber = A.group{1}.y_precoded;
else
results(b,k).ber = A.group{1}.y;
end
end
end
%% ============================================================
% PLOT 1×4 (one tile per baudrate)
% ============================================================
fig = figure(); clf;
tiledlayout(1,4,'TileSpacing','compact','Padding','compact');
lw = 1.8;
ms = 6;
for b = 1:length(baudrates)
nexttile; hold on;
for k = 1:numel(curves)
plot(results(b,k).wavelength, results(b,k).ber, ...
'-o', ...
'Color', curves(k).color, ...
'MarkerFaceColor', curves(k).color, ...
'MarkerSize', ms, ...
'LineWidth', lw, ...
'DisplayName', curves(k).name);
end
set(gca,'YScale','log');
grid on;
xlabel('Wavelength [nm]');
ylabel('BER');
ylim([1e-4 0.1]);
title(sprintf('PAM-%d @ %.0f GBd',pam_level, baudrates(b)/1e9));
legend('Location','best');
beautifyBERplot();
end
% Optional figure size
pos = 1e3.*[0.1 0.55 1.4 0.32];
set(fig, 'Position', pos);
%% ============================================================
% DECISION LOGIC (INLINE FUNCTIONS)
% ============================================================
function pe = decide_preemph(M, eq)
% PRE-EMPH RULES:
switch M
case 4
if eq == equalizer_structure.vnle
pe = 1; % PAM4: VNLE pre-emph on
else
pe = 0; % PAM4: all others off
end
case {6,8}
pe = 1; % PAM6/8: all pre-emph on
otherwise
pe = 0;
end
end
function flag = decide_precoded(M, eq)
% PRE-CODE RULES:
if eq == equalizer_structure.vnle_db_mlse
flag = 1; % Always for DB-target
elseif eq == equalizer_structure.ml_mlse && M == 4
flag = 1; % PAM4: ML-based precoded
else
flag = 0;
end
end

View File

@@ -0,0 +1,144 @@
tablename = 'C:\Users\Silas\Documents\latex\JLT_400G_submission\HighSpeedExperiments_oneandonly_csv.csv';
% Returns a Table
data = readtable(tablename,"Delimiter",';','DecimalSeparator',',');
%% ============================================================
% PLOT
% ============================================================
%% 1. DATA EXTRACTION & SETUP
%% 1. DATA EXTRACTION & SETUP
raw_M = data.M;
raw_baud = data.BaudRate;
raw_net = data.NetRate;
raw_codes = string(data.ZoteroCode);
raw_names = string(data.Name);
raw_band = string(data.Band);
% Filter Valid Data
target_M = [2, 4, 6, 8];
validIdx = ismember(raw_M, target_M) & ~isnan(raw_baud) & ~isnan(raw_net);
Mvals = raw_M(validIdx);
baud = raw_baud(validIdx);
netrate = raw_net(validIdx);
codes = raw_codes(validIdx);
names = raw_names(validIdx);
bands = raw_band(validIdx);
pam_list = target_M;
colors = flip(cbrewer2('SET1',4));
%% 2. PLOT (For Visual Check only)
figure; hold on;
ms = 20;
lw = 0.5;
for k = 1:length(pam_list)
M = pam_list(k);
idxPam = (Mvals == M);
x = baud(idxPam);
y = netrate(idxPam);
b = bands(idxPam);
n = names(idxPam);
col = colors(k,:);
firstLegend = true;
for i = 1:sum(idxPam)
% Marker Logic
ms = 20;
if strcmpi(b(i), 'O')
marker = 'o';
elseif strcmpi(b(i), 'C')
marker = 'd';
else
marker = 's';
end
if strcmpi(n(i), 'THIS WORK')
marker = 'pentagram';
ms = 100;
end
% Plot Scatter
if firstLegend
scatter(x(i), y(i), ms, 'Marker', marker, ...
'MarkerEdgeColor', col, 'MarkerFaceColor', col, ...
'DisplayName', sprintf('PAM-%d', M));
firstLegend = false;
else
scatter(x(i), y(i), ms, 'Marker', marker, ...
'MarkerEdgeColor', col, 'MarkerFaceColor', col, ...
'HandleVisibility','off');
end
end
% Fit lines
if length(x) >= 3
[p, S, mu] = polyfit(x, y, 2);
xfit = linspace(min(x), max(x), 200);
yfit = polyval(p, xfit, S, mu);
plot(xfit, yfit, '-', 'LineWidth', lw, 'Color', col, 'HandleVisibility', 'off');
end
end
grid on; box on;
xlabel('Baud rate [GBd]');
ylabel('Net rate [Gb/s]');
% title('Check Command Window for TikZ Code');
% legend('Location','northwest');
%% 3. GENERATE TIKZ ANNOTATION CODE
% This prints the manual \draw commands to the console
%% GENERATE TIKZ ANNOTATION CODE
% This prints the manual \draw commands to the console
%% GENERATE TIKZ ANNOTATION CODE (Colored Borders + Tiny Font)
%% GENERATE TIKZ ANNOTATION CODE (No Arrow, Close Text)
fprintf('\n\n%% ===========================================================\n');
fprintf('%% COPY THE FOLLOWING LINES INTO YOUR .TEX FILE \n');
fprintf('%% (Paste them just before \\end{axis})\n');
fprintf('%% ===========================================================\n\n');
for i = 1:length(baud)
bx = baud(i);
by = netrate(i);
key = codes(i);
M_val = Mvals(i);
% --- PLACEMENT LOGIC ---
if M_val == 8
% PAM-8: Place Top-Left
% 'south east' anchor means the text's bottom-right corner touches the coordinate
% shift moves it slightly up and left to clear the marker
anchorStr = 'south east';
shiftStr = 'shift={(-3pt, 3pt)}';
else
% Others: Place Bottom-Right
% 'north west' anchor means the text's top-left corner touches the coordinate
% shift moves it slightly down and right
anchorStr = 'north west';
shiftStr = 'shift={(3pt, -3pt)}';
end
% --- PRINT COMMAND ---
% Uses \node directly at the coordinate (axis cs:...)
fprintf('\\node[anchor=%s, %s, font=\\tiny, fill=white, inner sep=1pt] at (axis cs:%.2f, %.2f) {\\cite{%s}};\n', ...
anchorStr, shiftStr, bx, by, key);
end
fprintf('\n')
%% === EXPORT ===
outfile = 'C:\Users\Silas\Documents\latex\JLT_400G_submission\media\matlab2tikz\highspeedresults_test.tikz';
matlab2tikz(outfile, ...
'width','\fwidth', ...
'height','\fheight', ...
'showInfo',false, ...
'extraAxisOptions',{ ...
'legend style={font=\footnotesize}', ...
'legend columns=1' ...
});

View File

@@ -0,0 +1,334 @@
function [M, cfg] = analyze_measurements_gpt(T, cfg)
% ANALYZE_MEASUREMENTS_GPT
% Filter, compute X/Y, group and aggregate measurements from table T.
% No plotting here.
%
% Usage:
% [M, cfg] = analyze_measurements_gpt(dataTable, cfg);
%
% Typical result (single group):
% M.x -> aggregated x-values (e.g., grossrate)
% M.y -> aggregated y-values (e.g., BER or NGMI)
% M.y_precoded -> aggregated precoded BER (if available)
%
% For multiple groups:
% M.group(g).x, M.group(g).y, M.group(g).label, ...
%% ---- Defaults (non-plot) ----
if nargin < 2, cfg = struct; end
defaults = struct( ...
'x_axis' , 'symbolrate', ...
'y_axis' , 'BER', ...
'y_scale' , 'auto', ...
'group_by' , {{'equalizer_structure','pre_emph'}}, ...
'filters' , struct, ...
'agg' , 'mean', ...
'outlier' , 'auto', ...
'mad_z' , 4, ...
'pct_limits' , [2.5 97.5], ...
'min_pts_x' , 3, ...
'show_raw' , true, ...
'show_precoded', [], ...
'show_spread' , 'none', ...
'fec_lines' , [], ...
'plot' , struct() ... % plot settings handled in plot function
);
cfg = filldefaults(cfg, defaults);
%% ---- Derived/prep columns ----
if ~ismember('pre_emph', T.Properties.VariableNames)
if ~ismember('db_mode', T.Properties.VariableNames)
error('Missing column "db_mode" for pre_emph derivation.');
end
T.pre_emph = T.db_mode == 0;
end
if ~ismember(cfg.y_axis, T.Properties.VariableNames)
error('y_axis "%s" not found in table.', cfg.y_axis);
end
isBER = startsWith(cfg.y_axis, "BER", 'IgnoreCase', true);
M.isBER = isBER;
if strcmpi(cfg.y_scale,'auto')
cfg.y_scale = tern(isBER, 'log', 'linear');
end
if strcmpi(cfg.outlier,'auto')
cfg.outlier = tern(isBER, 'mad', 'none');
end
if isempty(cfg.show_precoded)
cfg.show_precoded = isBER && ismember('BER_precoded', T.Properties.VariableNames);
end
%% ---- Filters & core X/Y extraction ----
T = applyFilters(T, cfg.filters);
[x_raw, x_label] = computeX(T, cfg.x_axis);
y_raw = T.(cfg.y_axis);
validXY = isfinite(x_raw) & isfinite(y_raw);
T = T(validXY, :);
x_raw = x_raw(validXY);
y_raw = y_raw(validXY);
% Degiga if needed
if mean(abs(y_raw)) > 1e8
y_raw = y_raw .* 1e-9;
end
if cfg.show_precoded && ismember('BER_precoded', T.Properties.VariableNames)
y_raw_p = T.BER_precoded(validXY);
else
y_raw_p = [];
end
%% ---- Grouping ----
group_by = cfg.group_by;
if ~all(ismember(group_by, T.Properties.VariableNames))
error('Some group_by columns are missing in table.');
end
[G, grpTbl] = findgroups(T(:, group_by));
nG = max(G);
%% ---- Aggregation per group ----
M = struct;
M.cfg = cfg;
M.x_label = x_label;
M.y_axis = cfg.y_axis;
M.x_axis = cfg.x_axis;
M.nGroups = nG;
% raw (filtered) data
M.raw = struct;
M.raw.x = x_raw;
M.raw.y = y_raw;
M.raw.y_precoded = y_raw_p;
M.raw.T = T;
M.group = cell(nG,1);
useLog = strcmpi(cfg.y_scale,'log');
for gi = 1:nG
idx = (G == gi);
Ti = T(idx,:);
xi = x_raw(idx);
yi = y_raw(idx);
[xu, ~, iu] = unique(xi);
yu = nan(size(xu));
ylo = nan(size(xu));
yhi = nan(size(xu));
for k = 1:numel(xu)
bin = (iu==k);
yy = yi(bin);
yy = yy(isfinite(yy));
if isempty(yy), continue; end
km = outlierMask(yy, cfg, useLog);
if nnz(km) < cfg.min_pts_x, km = true(size(yy)); end
yy = yy(km);
switch lower(cfg.agg)
case 'median'
yu(k) = median(yy,'omitnan');
case 'mean'
yu(k) = mean(yy,'omitnan');
case 'min'
yu(k) = min(yy);
case 'max'
yu(k) = max(yy);
otherwise
error('Unknown agg mode "%s".', cfg.agg);
end
if strcmpi(cfg.show_spread,'iqr')
q = prctile(yy,[25 75]);
ylo(k) = max(yu(k)-q(1), eps);
yhi(k) = max(q(2)-yu(k), eps);
elseif strcmpi(cfg.show_spread,'minmax')
ylo(k) = min(yy);
yhi(k) = max(yy);
end
end
% sort by x
[xu, ord] = sort(xu);
yu = yu(ord);
ylo = ylo(ord);
yhi = yhi(ord);
g = struct;
g.label = buildLabel(grpTbl(gi,:), group_by);
g.idx = find(G==gi);
g.T = Ti;
g.x_raw = xi;
g.y_raw = yi;
g.x = xu;
g.y = yu;
g.y_lo = ylo;
g.y_hi = yhi;
g.y_precoded = [];
g.y_precoded_lo = [];
g.y_precoded_hi = [];
% Precoded aggregation (if requested & available)
if cfg.show_precoded && ~isempty(y_raw_p) && strcmpi(cfg.y_axis,'BER')
ypi = y_raw_p(idx);
ypu = nan(size(xu));
for k = 1:numel(xu)
bin = (iu==k);
yy = ypi(bin);
yy = yy(isfinite(yy));
if isempty(yy), continue; end
km = outlierMask(yy, cfg, true);
if nnz(km) < cfg.min_pts_x, km = true(size(yy)); end
yy = yy(km);
switch lower(cfg.agg)
case 'median'
ypu(k) = median(yy,'omitnan');
case 'mean'
ypu(k) = mean(yy,'omitnan');
case 'min'
ypu(k) = min(yy);
case 'max'
ypu(k) = max(yy);
end
end
g.y_precoded = ypu(ord);
end
M.group{gi} = g;
end
% Convenience flatten for single-group case
if nG == 1
g = M.group{1};
M.x = g.x;
M.y = g.y;
M.y_precoded = g.y_precoded;
end
end % ===== main =====
%% ===================== Helpers =====================
function cfg = filldefaults(cfg, defs)
fn = fieldnames(defs);
for i = 1:numel(fn)
f = fn{i};
if ~isfield(cfg, f) || isempty(cfg.(f))
cfg.(f) = defs.(f);
elseif isstruct(defs.(f)) && isstruct(cfg.(f))
cfg.(f) = filldefaults(cfg.(f), defs.(f)); % recursive
end
end
end
function out = tern(cond, a, b)
if cond
out = a;
else
out = b;
end
end
function T2 = applyFilters(T, filters)
if isempty(filters), T2 = T; return; end
keep = true(height(T),1);
fns = fieldnames(filters);
for i = 1:numel(fns)
name = fns{i};
if ~ismember(name, T.Properties.VariableNames)
warning('Filter column "%s" not found. Ignored.', name);
continue
end
val = filters.(name);
col = T.(name);
if isa(val,'function_handle')
m = val(col);
if ~islogical(m) || ~isequal(size(m), size(col))
error('Filter for %s must return logical mask of same size.', name);
end
keep = keep & m;
else
keep = keep & ismember(col, val);
end
end
T2 = T(keep,:);
end
function [x, label] = computeX(T, whichX)
switch lower(whichX)
case {'symbolrate','baudrate'}
x = T.symbolrate * 1e-9;
label = 'Symbol rate [GBd]';
case 'bitrate'
if ~ismember('pam_level', T.Properties.VariableNames)
error('bitrate requires "pam_level" column.');
end
bits = floor(log2(double(T.pam_level))*10)/10;
x = (T.symbolrate .* bits) * 1e-9;
label = 'Grossrate [Gb/s]';
case 'grossrate'
x = T.grossrate * 1e-9;
label = 'Grossrate [Gb/s]';
otherwise
if ~ismember(whichX, T.Properties.VariableNames)
error('x_axis "%s" not found in table.', whichX);
end
x = T.(whichX);
label = whichX;
end
x = double(x(:));
end
function keep = outlierMask(y, cfg, useLog)
if isempty(y), keep = false(size(y)); return; end
y = y(:);
switch lower(cfg.outlier)
case 'none'
keep = true(size(y)); return
case 'mad'
z = tern(useLog, log10(y), y);
med = median(z,'omitnan');
madv = median(abs(z-med),'omitnan');
if ~(isfinite(madv) && madv>0)
keep = true(size(y)); return
end
sigma = 1.4826*madv;
zz = tern(useLog, log10(y), y);
keep = abs(zz - med) <= cfg.mad_z*sigma;
case 'pctl'
pr = prctile(y, cfg.pct_limits);
keep = (y >= pr(1)) & (y <= pr(2));
otherwise
error('Unknown outlier mode "%s".', cfg.outlier);
end
end
function s = buildLabel(grpRow, group_by)
parts = strings(1, numel(group_by));
for i = 1:numel(group_by)
key = group_by{i};
val = grpRow.(key);
if iscell(val), val = val{1}; end
if islogical(val), val = tern(val,'w/','w/o'); end
if key == "equalizer_structure"
key = '';
val = upper(val);
val = strrep(val,'_',' ');
end
if key == "pre_emph"
val = [val, ' pre-emph.'];
key = '';
end
parts(i) = sprintf('%s %s', key, string(val));
end
s = strjoin(parts, ', ');
end

View File

@@ -0,0 +1,127 @@
%% Main Script: Compare Bibliographies
% This script loads two .bbl files, parses them into tables, and compares
% them to find missing citations and duplicates.
clc; clear; close all;
% --- STEP 0: Create Dummy Files for Demonstration ---
% (You can remove this step if you have actual files on disk)
file1 = 'C:\Users\Silas\Documents\latex\JLT_400G_submission\Advanced_DSP_for_400G_IMDD.bbl'; % The file based on your input
file2 = 'C:\Users\Silas\Documents\latex\JLT_400G_submission\Advanced_DSP_for_400G_IMDD_v1.bbl'; % A modified version to show differences
% --- STEP 1: Load and Parse Files ---
fprintf('Loading files...\n');
try
tab1 = parse_bbl_file(file1);
tab2 = parse_bbl_file(file2);
catch ME
error('Error loading files: %s', ME.message);
end
fprintf('File 1 (%s): %d citations found.\n', file1, height(tab1));
fprintf('File 2 (%s): %d citations found.\n', file2, height(tab2));
disp('------------------------------------------------------------');
% --- STEP 2: Check for Duplicates within files ---
check_duplicates(tab1, file1);
check_duplicates(tab2, file2);
disp('------------------------------------------------------------');
% --- STEP 3: Compare Files (Set Differences) ---
% Find keys in A that are NOT in B
[~, idx1] = setdiff(tab1.Key, tab2.Key);
missing_in_B = tab1(idx1, :);
% Find keys in B that are NOT in A
[~, idx2] = setdiff(tab2.Key, tab1.Key);
missing_in_A = tab2(idx2, :);
% --- STEP 4: Display Comparison Results ---
if isempty(missing_in_B)
fprintf('All citations from %s are present in %s.\n', file1, file2);
else
fprintf('Citations in %s but MISSING in %s (%d):\n', file1, file2, height(missing_in_B));
disp(missing_in_B.Key);
end
fprintf('\n');
if isempty(missing_in_A)
fprintf('All citations from %s are present in %s.\n', file2, file1);
else
fprintf('Citations in %s but MISSING in %s (%d):\n', file2, file1, height(missing_in_A));
disp(missing_in_A.Key);
end
%% ---------------------------------------------------------
% HELPER FUNCTIONS
% ---------------------------------------------------------
function check_duplicates(T, filename)
% Checks if the 'Key' column has non-unique entries
[uKeys, ~, idx] = unique(T.Key);
counts = accumarray(idx, 1);
dup_indices = find(counts > 1);
if isempty(dup_indices)
fprintf('No duplicates found in %s.\n', filename);
else
fprintf('** WARNING: Duplicates found in %s! **\n', filename);
for i = 1:length(dup_indices)
key_idx = dup_indices(i);
fprintf(' Key "%s" appears %d times.\n', uKeys{key_idx}, counts(key_idx));
end
end
end
function bibTable = parse_bbl_file(filename)
% PARSE_BBL_FILE Loads a .bbl file and extracts citations using Regex.
%
% bibTable = PARSE_BBL_FILE(filename) returns a table with columns:
% - Key: The citation key (e.g., 'dambrosiaAug2025Progress')
% - RawContent: The full text of the citation entry
% - Line: Approximate line number where it starts
% 1. Read the file content
if ~isfile(filename)
error('File "%s" not found.', filename);
end
str = fileread(filename);
% 2. Define Regex Structure
% Explanation:
% \\bibitem\{ -> Match literal "\bibitem{"
% (?<Key>[^}]+) -> Capture Group 'Key': match anything except '}'
% \} -> Match literal "}"
% \s* -> Match optional whitespace
% (?<Content>.*?) -> Capture Group 'Content': match any character lazily...
% (?=(\\bibitem|\\end\{thebibliography\})) -> ...until looking ahead sees "\bibitem" or end of env.
% Note: 'dotexceptnewline' is usually default, but we need dot to match newlines
% for multi-line citations. We handle this using the '(?s)' flag or explicit loop.
% Here we use standard pattern matching.
pattern = '\\bibitem\{(?<Key>[^}]+)\}\s*(?<Content>.*?)(?=(\\bibitem|\\end\{thebibliography\}))';
% 3. Execute Regex
% 'warnings' turned off for empty matches if file is malformed
[matches] = regexp(str, pattern, 'names');
% 4. Convert to Table
if isempty(matches)
warning('No citations found in %s using standard regex.', filename);
bibTable = table({}, {}, 'VariableNames', {'Key', 'RawContent'});
return;
end
% Clean up content (remove leading/trailing spaces/newlines)
keys = {matches.Key}';
content = {matches.Content}';
content = strtrim(content);
bibTable = table(keys, content, 'VariableNames', {'Key', 'RawContent'});
end

View File

@@ -0,0 +1,240 @@
database_type = 'mysql';
dataBase = 'labor_highspeed';
db = DBHandler("dataBase", [dataBase], "type", database_type);
% M = 4;
fp = QueryFilter();
% fp.where('Runs', 'pam_level','EQUALS', M);
fp.where('Runs', 'fiber_length','EQUALS', 2);
fp.where('Runs', 'wavelength','LESS_THAN', 1312);
% fp.where('Runs', 'db_mode','EQUALS', 1); % 0 == high preemphasis // 1 == low preemphasis
fp.where('Runs', 'rop_attenuation','EQUALS', 0);
fields = db.getTableFieldNames('power_state_info');
fields = [fields; db.getTableFieldNames('dashboard_ungrouped_alltime')]; %dashboard_ungrouped_after_nov_2025 dashboard_ungrouped_aug_nov_2025
[dataTable,~] = db.queryDB(fp, fields);
%%
cfg = struct;
cfg.x_axis = 'grossrate'; % 'symbol rate' | 'bitrate' | 'wavelength' grossrate
cfg.y_axis = 'BER'; % 'BER' | 'GMI' | 'AIR' | ...
cfg.y_scale = 'auto'; % auto -> log for BER*, linear otherwise
cfg.outlier = 'mad'; % simple, robust; 'none' or 'pctl' also available
cfg.show_raw = false;
cfg.show_spread = 'none'; % 'none' or 'iqr' or minmax
cfg.agg = 'min'; % or 'median'
cfg.show_precoded = 0;
% cfg.fec_lines = [2.2e-4 4.85e-3 2e-2]; % optional
cfg.fec_lines = [];
cfg.plot.custom_colors = [
clr.Paired.red;
clr.Paired.blue;
clr.Paired.green;
clr.Paired.orange;
clr.Paired.purple
];
cfg.plot.custom_colors_scatter = [
clr.Paired.lightred;
clr.Paired.lightblue;
clr.Paired.lightgreen;
clr.Paired.lightorange;
clr.Paired.lightpurple
];
% New styling knobs
cfg.plot.use_cbrewer2 = true;
cfg.plot.colormap = 'Paired';
cfg.plot.paired_dark_first = false; % dark for lines, light for scatter
cfg.plot.lineWidth = 2.0;
cfg.plot.errWidth = 1.2;
cfg.plot.scatterAlpha = 0.35;
cfg.plot.legendLocation = 'best';
cfg.plot.fecLineWidth = 2.4; % thicker FEC limits
cfg.plot.lineStyle_pre_emph_on = '-';
cfg.plot.lineStyle_pre_emph_off = '-';
%% PLOT NGMI
% Common cfg
cfg.show_precoded = 1;
cfg.group_by = {'equalizer_structure','pre_emph'};
cfg.x_axis = 'grossrate';
cfg.y_axis = 'NGMI'; % 'BER' | 'GMI' | 'AIR' | ...
cfg.y_scale = 'lin';
cfg.plot.custom_colors_scatter = [];
cfg.plot.use_cbrewer2 = false;
cfg.fec_lines = [];
cfg.agg = 'max';
cfg.figure_number = 45;
% fig = figure(cfg.figure_number);
lambda = 1310;
% PAM 4
cfg.plot.custom_colors = clr.Paired.red;
cfg.plot.custom_linetypes = {'-'};
cfg.filters = struct('is_mpi',0,'pam_level',4, ...
'equalizer_structure',equalizer_structure.vnle_db_mlse, ...
'pre_emph',0,'wavelength',lambda);
cfg.show_precoded = 1;
a = plot_measurements_gpt(dataTable, cfg);
ngmi_pam4 = a.lines(1).YData;
grossrates = a.lines(1).XData;
tp = TransmissionPerformance;
netrates_vnle = tp.calculateNetRate(grossrates, ...
'NGMI', ngmi_pam4, ...
'BER', BER_VNLE);
cfg.plot.custom_colors = clr.Paired.red;
cfg.plot.custom_linetypes = {'--'};
cfg.filters = struct('is_mpi',0,'pam_level',4, ...
'equalizer_structure',equalizer_structure.vnle_db_mlse, ...
'pre_emph',0,'wavelength',1293);
cfg.show_precoded = 1;
plot_measurements_gpt(dataTable, cfg);
% PAM 6
cfg.plot.custom_colors = clr.Paired.blue;
cfg.plot.custom_linetypes = {'-'};
cfg.filters = struct('is_mpi',0,'pam_level',6, ...
'equalizer_structure',equalizer_structure.vnle_pf_mlse, ...
'pre_emph',1,'wavelength',lambda);
cfg.show_precoded = 0;
plot_measurements_gpt(dataTable, cfg);
cfg.plot.custom_colors = clr.Paired.blue;
cfg.plot.custom_linetypes = {'--'};
cfg.filters = struct('is_mpi',0,'pam_level',6, ...
'equalizer_structure',equalizer_structure.vnle_pf_mlse, ...
'pre_emph',1,'wavelength',1293);
cfg.show_precoded = 0;
plot_measurements_gpt(dataTable, cfg);
% PAM 8
cfg.plot.custom_colors = clr.Paired.green;
cfg.plot.custom_linetypes = {'-'};
cfg.filters = struct('is_mpi',0,'pam_level',8, ...
'equalizer_structure',equalizer_structure.vnle_pf_mlse, ...
'pre_emph',1,'wavelength',lambda);
cfg.show_precoded = 0;
plot_measurements_gpt(dataTable, cfg);
cfg.plot.custom_colors = clr.Paired.green;
cfg.plot.custom_linetypes = {'--'};
cfg.filters = struct('is_mpi',0,'pam_level',8, ...
'equalizer_structure',equalizer_structure.vnle_pf_mlse, ...
'pre_emph',1,'wavelength',1293);
cfg.show_precoded = 0;
plot_measurements_gpt(dataTable, cfg);
beautifyBERplot
ylim([0.87,1.01]);
% xlim([290,480]);
%% PLOT AIR
% Common cfg
cfg.show_precoded = 1;
cfg.group_by = {'equalizer_structure','pre_emph'};
cfg.x_axis = 'grossrate';
cfg.y_axis = 'AIR'; % 'BER' | 'GMI' | 'AIR' | ...
cfg.y_scale = 'lin';
cfg.plot.custom_colors_scatter = [];
cfg.plot.use_cbrewer2 = false;
cfg.fec_lines = [];
cfg.agg = 'max';
cfg.figure_number = 47;
lambda = 1310;
% cfg = struct;
cfg.filters = struct('is_mpi',0,'pam_level',4, ...
'equalizer_structure',equalizer_structure.vnle_db_mlse, ...
'pre_emph',0,'wavelength',lambda);
cfg.x_axis = 'grossrate';
cfg.y_axis = 'NGMI'; % or 'NGMI', etc.
cfg.show_precoded = 1;
[M, cfg] = analyze_measurements_gpt(dataTable, cfg);
grossrates = M.x; % aggregated X
ber = M.y; % aggregated Y (BER or NGMI)
ber_prec = M.y_precoded; % precoded BER (if available)
[h, M] = plot_measurements_gpt(dataTable, cfg);
% PAM 4
cfg.plot.custom_colors = clr.Paired.red;
cfg.plot.custom_linetypes = {'-'};
cfg.filters = struct('is_mpi',0,'pam_level',4, ...
'equalizer_structure',equalizer_structure.vnle_db_mlse, ...
'pre_emph',0,'wavelength',lambda);
cfg.show_precoded = 1;
plot_measurements_gpt(dataTable, cfg);
cfg.plot.custom_colors = clr.Paired.red;
cfg.plot.custom_linetypes = {'--'};
cfg.filters = struct('is_mpi',0,'pam_level',4, ...
'equalizer_structure',equalizer_structure.vnle_db_mlse, ...
'pre_emph',0,'wavelength',1293);
cfg.show_precoded = 1;
plot_measurements_gpt(dataTable, cfg);
% PAM 6
cfg.plot.custom_colors = clr.Paired.blue;
cfg.plot.custom_linetypes = {'-'};
cfg.filters = struct('is_mpi',0,'pam_level',6, ...
'equalizer_structure',equalizer_structure.vnle_pf_mlse, ...
'pre_emph',1,'wavelength',lambda);
cfg.show_precoded = 0;
plot_measurements_gpt(dataTable, cfg);
cfg.plot.custom_colors = clr.Paired.blue;
cfg.plot.custom_linetypes = {'--'};
cfg.filters = struct('is_mpi',0,'pam_level',6, ...
'equalizer_structure',equalizer_structure.vnle_pf_mlse, ...
'pre_emph',1,'wavelength',1293);
cfg.show_precoded = 0;
plot_measurements_gpt(dataTable, cfg);
% PAM 8
cfg.plot.custom_colors = clr.Paired.green;
cfg.plot.custom_linetypes = {'-'};
cfg.filters = struct('is_mpi',0,'pam_level',8, ...
'equalizer_structure',equalizer_structure.vnle_pf_mlse, ...
'pre_emph',1,'wavelength',lambda);
cfg.show_precoded = 0;
plot_measurements_gpt(dataTable, cfg);
cfg.plot.custom_colors = clr.Paired.green;
cfg.plot.custom_linetypes = {'--'};
cfg.filters = struct('is_mpi',0,'pam_level',8, ...
'equalizer_structure',equalizer_structure.vnle_pf_mlse, ...
'pre_emph',1,'wavelength',1293);
cfg.show_precoded = 0;
plot_measurements_gpt(dataTable, cfg);
ax = gca;
beautifyBERplot
ylim([275,435]);
xlim([290,480]);
%%

View File

@@ -0,0 +1,112 @@
database_type = 'mysql';
dataBase = 'labor_highspeed';
db = DBHandler("dataBase", [dataBase], "type", database_type);
M = 4;
fp = QueryFilter();
fp.where('Runs', 'pam_level','EQUALS', M);
fp.where('Runs', 'fiber_length','EQUALS', 2);
fp.where('Runs', 'wavelength','EQUALS', 1310);
% fp.where('Runs', 'db_mode','EQUALS', 1); % 0 == high preemphasis // 1 == low preemphasis
fp.where('Runs', 'rop_attenuation','EQUALS', 0);
fields = db.getTableFieldNames('power_state_info');
fields = [fields; db.getTableFieldNames('dashboard_ungrouped_aug_nov_2025')]; %dashboard_ungrouped_after_nov_2025 dashboard_ungrouped_aug_nov_2025
[dataTable,~] = db.queryDB(fp, fields);
%%
cfg = struct;
cfg.x_axis = 'grossrate'; % 'symbol rate' | 'bitrate' | 'wavelength' grossrate
cfg.y_axis = 'BER'; % 'BER' | 'GMI' | 'AIR' | ...
cfg.y_scale = 'auto'; % auto -> log for BER*, linear otherwise
cfg.outlier = 'mad'; % simple, robust; 'none' or 'pctl' also available
cfg.show_raw = false;
cfg.show_spread = 'none'; % 'none' or 'iqr' or minmax
cfg.agg = 'min'; % or 'median'
cfg.show_precoded = 0;
% cfg.fec_lines = [2.2e-4 4.85e-3 2e-2]; % optional
cfg.fec_lines = [];
cfg.plot.custom_colors = [
clr.Paired.red;
clr.Paired.blue;
clr.Paired.green;
clr.Paired.orange;
clr.Paired.purple
];
cfg.plot.custom_colors_scatter = [
clr.Paired.lightred;
clr.Paired.lightblue;
clr.Paired.lightgreen;
clr.Paired.lightorange;
clr.Paired.lightpurple
];
% New styling knobs
cfg.plot.use_cbrewer2 = true;
cfg.plot.colormap = 'Paired';
cfg.plot.paired_dark_first = false; % dark for lines, light for scatter
cfg.plot.lineWidth = 2.0;
cfg.plot.errWidth = 1.2;
cfg.plot.scatterAlpha = 0.35;
cfg.plot.legendLocation = 'best';
cfg.plot.fecLineWidth = 2.4; % thicker FEC limits
cfg.plot.lineStyle_pre_emph_on = '-';
cfg.plot.lineStyle_pre_emph_off = '-';
%%
cfg.figure_number = 42;
% ---- VNLE, no pre-emph (solid red) ----
cfg.plot.custom_colors = [clr.Paired.red];
cfg.plot.custom_linetypes = {'-'};
cfg.filters = struct('is_mpi',0,'pam_level',M, ...
'equalizer_structure',equalizer_structure.vnle, ...
'pre_emph',0);
plot_measurements_gpt(dataTable, cfg);
% ---- VNLE, with pre-emph (dashed red) ----
cfg.plot.custom_colors = [clr.Paired.red];
cfg.plot.custom_linetypes = {'--'};
cfg.filters.pre_emph = 1;
plot_measurements_gpt(dataTable, cfg);
% ---- VNLE PF MLSE, no pre-emph (solid green) ----
cfg.plot.custom_colors = [clr.Paired.green];
cfg.plot.custom_linetypes = {'-'};
cfg.filters.equalizer_structure = equalizer_structure.vnle_pf_mlse;
cfg.filters.pre_emph = 0;
plot_measurements_gpt(dataTable, cfg);
% ---- VNLE PF MLSE, with pre-emph (dashed green) ----
cfg.plot.custom_colors = [clr.Paired.green];
cfg.plot.custom_linetypes = {'--'};
cfg.filters.pre_emph = 1;
plot_measurements_gpt(dataTable, cfg);
% === FEC LINES (no legend) ===
yline([2.2e-4 4.85e-3 2e-2], ...
'LineWidth',1.5,'Color',[0.4 0.4 0.4], ...
'LineStyle',':','HandleVisibility','off');
% === BEAUTIFY ===
% beautifyBERplot; % your function
%% === EXPORT TO TIKZ ===
outfile = 'C:\Users\Silas\Documents\latex\JLT_400G copy\media\matlab2tikz\compare_pre_emphasis.tikz';
matlab2tikz(outfile, ...
'width','\fwidth', ...
'height','\fheight', ...
'showInfo',false, ...
'extraAxisOptions',{ ...
'legend style={font=\footnotesize}', ...
'legend columns=1' ...
} );

View File

@@ -0,0 +1,92 @@
% ============================================================
% MINIMAL EXAMPLE: Query Analyze Plot Extract X/Y data
% ============================================================
%% === Load from database ===
db = DBHandler("dataBase","labor_highspeed","type","mysql");
fp = QueryFilter();
fp.where('Runs','fiber_length','EQUALS',2);
% fp.where('Runs','pam_level','EQUALS',6); % PAM-4
% fp.where('Runs','db_mode','EQUALS',0); % w/o pre-emph
fields = db.getTableFieldNames('dashboard_ungrouped_alltime');
[dataTable,~] = db.queryDB(fp, fields);
%% === Define config ===
for m = [4,6,8]
cfg = struct;
cfg.x_axis = 'symbolrate';
cfg.y_axis = 'Alpha';
cfg.group_by = {'equalizer_structure','pre_emph'};
cfg.filters = struct('is_mpi',0,'pam_level',m, ...
'equalizer_structure',equalizer_structure.vnle_pf_mlse, ...
'pre_emph',0);
cfg.agg = 'max';
cfg.outlier = 'mad';
cfg.show_raw = false;
cfg.show_precoded = 0;
% Plot cosmetics (minimal)
cfg.plot = struct;
cfg.plot.custom_colors = linspecer(8);
cfg.plot.custom_linetypes = {'-'};
cfg.plot.lineWidth = 2;
% ============================================================
% === ANALYSIS ONLY (no plotting) =============================
% ============================================================
A = analyze_measurements_gpt(dataTable, cfg);
% Now you have:
% A.raw.x = raw x-values
% A.raw.y = raw BER values
% A.group{1}.x = unique sorted x-values
% A.group{1}.y = aggregated BER for each x
x_values = A.group{1}.x;
y_values = A.group{1}.y;
% ============================================================
% === PLOT ====================================================
% ============================================================
figure(10);hold on
cfg.ax = gca; % optional: plot into existing axes
plot(x_values,y_values,...
'LineWidth', 2, ...
'Color', clr.Set1.red, ...
'MarkerSize', 5, ...
'MarkerFaceColor', clr.Set1.red,...
'Marker','o');
% [h, ~] = plot_measurements_gpt(dataTable, cfg);
title('Minimal VNLE BER Example')
xlabel('Grossrate [Gb/s]')
ylabel('BER')
xticks(100:30:220)
xlim([100,220]);
ylim([0,1]);
end
% outfile = 'C:\Users\Silas\Documents\latex\JLT_400G copy\media\matlab2tikz\alphas.tikz';
% matlab2tikz(outfile, ...
% 'width','\fwidth', ...
% 'height','\fheight', ...
% 'showInfo',false, ...
% 'extraAxisOptions',{ ...
% 'legend style={font=\footnotesize}', ...
% 'legend columns=1' ...
% 'every axis/.append style={font=\scriptsize}',...
% 'minor grid style={line width=0.2pt, solid, color=black!10}',...
% 'grid style={line width=0.4pt, solid, color=black!20}',...
% 'grid style={dashed}',...
% });

View File

@@ -0,0 +1,111 @@
dsp_options.storage_path = 'Z:\2024\sioe_labor\';
dsp_options.max_occurences = 1;
database = DBHandler("dataBase", 'labor_highspeed', "type", 'mysql' );
rate = 390e9;
%% 1 - PAM 4 with preemphasis
fp = QueryFilter();
M = 4;
fp.where('Runs', 'pam_level','EQUALS', M);
fp.where('Runs', 'bitrate','EQUALS', rate);%360,390
fp.where('Runs', 'fiber_length','EQUALS', 2);
fp.where('Runs', 'wavelength','EQUALS', 1310);
fp.where('Runs', 'db_mode','EQUALS', 0);
fp.where('Runs', 'rop_attenuation','EQUAL', 0);
[dataTable,~] = db.queryDB(fp, database.getTableFieldNames('Runs'));
dataTable = queryRunid(dataTable.run_id, database);
fsym = dataTable.symbolrate;
M = double(dataTable.pam_level);
% Load and Sync signal data from DB
[Tx_bits, Symbols, Scpe_cell, ~] = loadAndSyncSignalDataFromDb(dataTable, dsp_options);
% Preprocess signal
Scpe_sig = preprocessSignal(Scpe_cell{1}, Symbols, fsym);
if rate == 390e9
Scpe_sig.spectrum("fignum",200,"normalizeTo0dB",1,"displayname",'Rx','addDCoffset',-5.8);
elseif rate == 300e9
Scpe_sig.spectrum("fignum",200,"normalizeTo0dB",1,"displayname",'Rx','addDCoffset',-4.7);
end
ylim([-30,3]);
xlim([-5,100]);
Scpe_sig.spectrum("fignum",201,"normalizeTo0dB",0,"displayname",'Rx');
%% 1 - PAM 4 without preemphasis
fp = QueryFilter();
M = 4;
fp.where('Runs', 'pam_level','EQUALS', M);
fp.where('Runs', 'bitrate','EQUALS', rate);%360,390
fp.where('Runs', 'fiber_length','EQUALS', 2);
fp.where('Runs', 'wavelength','EQUALS', 1310);
fp.where('Runs', 'db_mode','EQUALS', 1);
fp.where('Runs', 'rop_attenuation','EQUAL', 0);
[dataTable,~] = db.queryDB(fp, database.getTableFieldNames('Runs'));
dataTable = queryRunid(dataTable.run_id, database);
fsym = dataTable.symbolrate;
M = double(dataTable.pam_level);
% Load and Sync signal data from DB
[Tx_bits, Symbols, Scpe_cell, ~] = loadAndSyncSignalDataFromDb(dataTable, dsp_options);
% Preprocess signal
Scpe_sig = preprocessSignal(Scpe_cell{1}, Symbols, fsym);
Scpe_sig.spectrum("fignum",200,"normalizeTo0dB",1,"displayname",'Rx','addDCoffset',0);
ylim([-30,3]);
xlim([-5,100]);
Scpe_sig.spectrum("fignum",201,"normalizeTo0dB",0,"displayname",'Rx');
if 1
%% show freuqncy response of filter
measure = 1;
freqresp = ChannelFreqResp("Nacq",1024,"Navg",64,"Ncp",70,"f_ref",256e9);
%
Digi_sig = freqresp.buildOFDM();
% Digi_sig.spectrum("fignum",1112,"displayname",['maxamp:',num2str(maxamp)]);
Digi_sig = Filter('filtdegree',3,"f_cutoff",70e9,"fs",256e9,"filterType",filtertypes.butterworth,"active",true).process(Digi_sig);
Digi_sig = Filter('filtdegree',3,"f_cutoff",70e9,"fs",256e9,"filterType",filtertypes.bessel_inp,"active",true).process(Digi_sig);
freqresp.estimate(Digi_sig,"fileName",'','save',false);
freqresp.plot()
a = gca;
a.YTick = [-30,-20,-10,0];
%% system frex
precomp_filename ='lab_high_speed';
precomp_path = "C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\precomp";
freqresp = ChannelFreqResp("Nacq",1024,"Navg",64,"Ncp",63,'f_ref',92e9);
freqresp.load('loadPath', precomp_path, 'fileName', precomp_filename);
fprintf('Plotting: %s\n', precomp_filename);
freqresp.plot();
outfile = 'C:\Users\Silas\Documents\latex\JLT_400G copy\media\matlab2tikz\spectrum_2.tikz';
matlab2tikz(outfile, ...
'width','\fwidth', ...
'height','\fheight', ...
'showInfo',false, ...
'extraAxisOptions',{ ...
'legend style={font=\footnotesize}', ...
'legend columns=1' ...
});
end

View File

@@ -0,0 +1,222 @@
function [h, M, cfg] = plot_measurements_gpt(T, cfg)
% PLOT_MEASUREMENTS_GPT
% Plot measurements, using analyze_measurements_gpt for data handling.
%
% Usage:
% h = plot_measurements_gpt(dataTable, cfg);
% [h, M] = plot_measurements_gpt(dataTable, cfg);
%
% For values only, without plotting, call:
% [M, cfg] = analyze_measurements_gpt(dataTable, cfg);
if nargin < 2, cfg = struct; end
% --- First: run analysis (filtering, grouping, aggregation) ---
[M, cfg] = analyze_measurements_gpt(T, cfg);
nG = M.nGroups;
%% ---- Plot defaults ----
plotdefs = struct( ...
'use_cbrewer2' , true, ...
'colormap' , 'Paired', ...
'paired_dark_first' , true, ...
'lineWidth' , 1.8, ...
'errWidth' , 1.0, ...
'scatterSize' , 14, ...
'scatterAlpha' , 0.35, ...
'marker' , 'o', ...
'marker_precoded' , 's', ...
'legendLocation' , 'best', ...
'fecLineWidth' , 2.2, ...
'fecColor' , [0.25 0.25 0.25], ...
'capSize' , 6, ...
'lineStyle_default' , '-', ...
'custom_colors' , [], ...
'custom_colors_scatter' , [] ...
);
if ~isfield(cfg,'plot') || isempty(cfg.plot)
cfg.plot = struct;
end
cfg.plot = filldefaults(cfg.plot, plotdefs);
%% ---- Colors ----
[cols_line, cols_scatter] = buildGroupColors(nG, cfg.plot);
%% ---- Axes / Figure handling ----
if isfield(cfg,'ax') && ~isempty(cfg.ax) && isgraphics(cfg.ax,'axes')
ax = cfg.ax;
set(gcf,'CurrentAxes',ax);
else
if isfield(cfg,'figure_number') && ~isempty(cfg.figure_number)
figure(cfg.figure_number);
else
figure;
end
ax = gca;
end
hold(ax,'on');
grid(ax,'on');
h.lines = gobjects(nG,1);
h.err = gobjects(nG,1);
h.scat = gobjects(nG,1);
h.lines_p = gobjects(nG,1);
%% ---- Plot each group ----
for gi = 1:nG
g = M.group{gi};
xu = g.x;
yu = g.y;
ylo = g.y_lo;
yhi = g.y_hi;
% --- Linestyle selection ---
ls = cfg.plot.lineStyle_default;
if isfield(cfg.plot,'custom_linetypes') && ~isempty(cfg.plot.custom_linetypes)
L = cfg.plot.custom_linetypes;
ls = L{ mod(gi-1, numel(L)) + 1 };
end
colL = cols_line(gi,:);
lbl = g.label;
% Main line
h.lines(gi) = plot(ax, xu, yu, ...
'LineWidth', cfg.plot.lineWidth, ...
'Marker', cfg.plot.marker, 'MarkerSize', 3, ...
'Color', colL, 'LineStyle', ls, ...
'DisplayName', char(lbl));
% Spread
if any(isfinite(ylo)) && any(isfinite(yhi))
h.err(gi) = errorbar(ax, xu, yu, ylo, yhi, 'LineStyle','none', ...
'Color', colL, 'CapSize', cfg.plot.capSize, 'HandleVisibility','off');
h.err(gi).LineWidth = cfg.plot.errWidth;
end
% Raw scatter
if cfg.show_raw
% reuse stored raw data (no extra filtering)
xi = g.x_raw;
yi = g.y_raw;
colS = cols_scatter(gi,:);
scatter(ax, xi, yi, cfg.plot.scatterSize, colS, 'filled', ...
'MarkerFaceAlpha', cfg.plot.scatterAlpha, ...
'MarkerEdgeAlpha', cfg.plot.scatterAlpha, ...
'HandleVisibility','off');
end
% Precoded overlay
if cfg.show_precoded && ~isempty(g.y_precoded) && strcmpi(M.y_axis,'BER')
ypu = g.y_precoded;
h.lines_p(gi) = plot(ax, xu, ypu, ...
'LineWidth', max(1.2, cfg.plot.lineWidth-0.2), ...
'Marker', cfg.plot.marker_precoded, 'MarkerSize', 3, ...
'Color', colL, 'LineStyle', ':', ...
'DisplayName', [char(lbl) ' (precoded)']);
end
end
%% ---- Axes / Labels / FEC ----
ylabel(ax, M.y_axis, 'Interpreter','none');
xlabel(ax, M.x_label, 'Interpreter','none');
set(ax, 'YScale', cfg.y_scale, 'FontSize', 11);
% X ticks/limits using all group x-values
allX = cellfun(@(g) g.x(:), M.group, 'UniformOutput', false);
allX = unique(vertcat(allX{:}));
if ~isempty(allX)
xticks(ax, allX);
xticklabels(cellstr(num2str(round(allX,1), '%.4f')))
xlim(ax, [min(allX), max(allX)]);
end
if startsWith(M.y_axis,"BER",'IgnoreCase',true)
for v = cfg.fec_lines
yline(ax, v, '--', 'Color', cfg.plot.fecColor, ...
'LineWidth', cfg.plot.fecLineWidth, 'HandleVisibility','off');
end
ylim(ax, [1e-5, 0.5]);
yticks(ax, [1e-5, 1e-4, 1e-3, 1e-2, 1e-1]);
end
% legend(ax, 'Location', cfg.plot.legendLocation); % if you want legends
box(ax,'on');
end % ===== main =====
%% ===================== Helpers =====================
function cfg = filldefaults(cfg, defs)
fn = fieldnames(defs);
for i = 1:numel(fn)
f = fn{i};
if ~isfield(cfg, f) || isempty(cfg.(f))
cfg.(f) = defs.(f);
elseif isstruct(defs.(f)) && isstruct(cfg.(f))
cfg.(f) = filldefaults(cfg.(f), defs.(f));
end
end
end
function [cols_line, cols_scatter] = buildGroupColors(nG, plotcfg)
% 1) User-provided custom colors
if isfield(plotcfg,'custom_colors') && ~isempty(plotcfg.custom_colors)
C = plotcfg.custom_colors;
if size(C,1) < nG
error('custom_colors must have at least nG=%d rows.', nG);
end
cols_line = C(1:nG, :);
if isfield(plotcfg,'custom_colors_scatter') && ~isempty(plotcfg.custom_colors_scatter)
Cs = plotcfg.custom_colors_scatter;
if size(Cs,1) < nG
error('custom_colors_scatter must have at least nG=%d rows.', nG);
end
cols_scatter = Cs(1:nG, :);
else
cols_scatter = zeros(nG,3);
for i = 1:nG
cols_scatter(i,:) = lightenColor(cols_line(i,:), 0.40);
end
end
return;
end
% 2) Standard behavior
useBrewer = plotcfg.use_cbrewer2 && exist('cbrewer2','file')==2;
if useBrewer
N = max(2*nG, 12);
C = cbrewer2(plotcfg.colormap, N);
cols_line = zeros(nG,3);
cols_scatter = zeros(nG,3);
for i = 1:nG
if plotcfg.paired_dark_first
dark = C(2*i-1, :);
light = C(2*i, :);
else
light = C(2*i-1, :);
dark = C(2*i, :);
end
cols_line(i,:) = dark;
cols_scatter(i,:) = light;
end
else
C = lines(max(nG,7));
cols_line = C(1:nG,:);
cols_scatter = zeros(nG,3);
for i = 1:nG
cols_scatter(i,:) = lightenColor(cols_line(i,:), 0.50);
end
end
end
function c2 = lightenColor(c, fracTowardWhite)
c = c(:).';
c2 = (1-fracTowardWhite)*c + fracTowardWhite*1;
end

View File

@@ -0,0 +1,436 @@
function h = plot_measurements_gpt_old(T, cfg)
% Versatile plotting from your DB table (with cbrewer2 'Paired' palette).
%
% Usage:
% h = plot_measurements_flex(dataTable, cfg)
%% ---- Defaults
if nargin < 2, cfg = struct; end
defaults = struct( ...
'x_axis' , 'symbolrate', ...
'y_axis' , 'BER', ...
'y_scale' , 'auto', ...
'group_by' , {{'equalizer_structure','pre_emph'}}, ...
'filters' , struct, ...
'agg' , 'mean', ...
'outlier' , 'auto', ...
'mad_z' , 4, ...
'pct_limits' , [2.5 97.5], ...
'min_pts_x' , 3, ...
'show_raw' , true, ...
'show_precoded', [], ...
'show_spread' , 'none', ...
'fec_lines' , [], ...
'plot', struct() ...
);
cfg = filldefaults(cfg, defaults);
% ---- Plot defaults (new)
plotdefs = struct( ...
'use_cbrewer2' , true, ...
'colormap' , 'Paired', ... % ColorBrewer 'Paired'
'paired_dark_first' , true, ... % dark for lines, light for scatter
'lineWidth' , 1.8, ...
'errWidth' , 1.0, ...
'scatterSize' , 14, ...
'scatterAlpha' , 0.35, ...
'marker' , 'o', ...
'marker_precoded' , 's', ...
'lineStyle_pre_emph_on' , '--', ...
'lineStyle_pre_emph_off', '-', ...
'legendLocation' , 'best', ...
'fecLineWidth' , 2.2, ... % thicker FEC limits
'fecColor' , [0.25 0.25 0.25], ...
'capSize' , 6, ...
'lineStyle_default' , '-', ...
'use_pre_emph_styling' , true ...
);
cfg.plot = filldefaults(cfg.plot, plotdefs);
%% ---- Derived/prep columns
if ~ismember('pre_emph', T.Properties.VariableNames)
if ~ismember('db_mode', T.Properties.VariableNames)
error('Missing column "db_mode" for pre_emph derivation.');
end
T.pre_emph = T.db_mode == 0;
end
if ~ismember(cfg.y_axis, T.Properties.VariableNames)
error('y_axis "%s" not found in table.', cfg.y_axis);
end
isBER = startsWith(cfg.y_axis, "BER", 'IgnoreCase', true);
if strcmpi(cfg.y_scale,'auto'), cfg.y_scale = tern(isBER, 'log', 'linear'); end
if strcmpi(cfg.outlier,'auto'), cfg.outlier = tern(isBER, 'mad', 'none'); end
if isempty(cfg.show_precoded)
cfg.show_precoded = isBER && ismember('BER_precoded', T.Properties.VariableNames);
end
%% ---- Filters
T = applyFilters(T, cfg.filters);
[x_raw, x_label] = computeX(T, cfg.x_axis);
y_raw = T.(cfg.y_axis);
validXY = isfinite(x_raw) & isfinite(y_raw);
T = T(validXY, :);
x_raw = x_raw(validXY);
y_raw = y_raw(validXY);
if mean(abs(y_raw)) > 1e8
%giga values
y_raw = y_raw.*1e-9;
end
if cfg.show_precoded && ismember('BER_precoded', T.Properties.VariableNames)
y_raw_p = T.BER_precoded(validXY);
else
y_raw_p = [];
end
%% ---- Grouping
group_by = cfg.group_by;
if ~all(ismember(group_by, T.Properties.VariableNames))
error('Some group_by columns are missing in table.');
end
[G, grpTbl] = findgroups(T(:, group_by));
nG = max(G);
% ==== Colors (cbrewer2 'Paired' with dark/ light pairs) ====
[cols_line, cols_scatter] = buildGroupColors(nG, cfg.plot);
%% ---- Axes / Figure handling (new unified logic)
% Priority:
% 1) cfg.ax use existing axes (subplots/tiles)
% 2) cfg.figure_number select/create figure
% 3) fallback: create new figure
if isfield(cfg,'ax') && ~isempty(cfg.ax) && isgraphics(cfg.ax,'axes')
ax = cfg.ax; % use caller-provided axes
set(gcf,'CurrentAxes',ax);
else
if isfield(cfg,'figure_number') && ~isempty(cfg.figure_number)
figure(cfg.figure_number);
else
figure;
end
ax = gca; % active axes
end
hold(ax,'on');
grid(ax,'on');
h.lines = gobjects(nG,1);
h.err = gobjects(nG,1);
h.scat = gobjects(nG,1);
h.lines_p = gobjects(nG,1);
for gi = 1:nG
idx = (G==gi);
Ti = T(idx,:);
xi = x_raw(idx);
yi = y_raw(idx);
% Aggregate per unique x
[xu, ia, iu] = unique(xi);
yu = nan(size(xu));
ylo = nan(size(xu));
yhi = nan(size(xu));
for k = 1:numel(xu)
bin = (iu==k);
yy = yi(bin);
yy = yy(isfinite(yy));
if isempty(yy), continue; end
km = outlierMask(yy, cfg, strcmpi(cfg.y_scale,'log'));
if nnz(km) < cfg.min_pts_x, km = true(size(yy)); end
yy = yy(km);
if strcmpi(cfg.agg,'median'), yu(k)=median(yy,'omitnan'); elseif strcmpi(cfg.agg,'mean'), yu(k)=mean(yy,'omitnan'); elseif strcmpi(cfg.agg,'min'), yu(k)=min(yy); elseif strcmpi(cfg.agg,'max'), yu(k)=max(yy); end
if strcmpi(cfg.show_spread,'iqr')
q = prctile(yy,[25 75]);
ylo(k) = max(yu(k)-q(1), eps);
yhi(k) = max(q(2)-yu(k), eps);
elseif strcmpi(cfg.show_spread,'minmax')
ylo(k) = min(yy);
yhi(k) = max(yy);
end
end
% sort
[xu, ord] = sort(xu);
yu = yu(ord);
ylo = ylo(ord);
yhi = yhi(ord);
% Styles
% Decide if we style by pre_emph
% --- LINE TYPE SELECTION (no pre-emphasis logic) ---
ls = cfg.plot.lineStyle_default;
% User-defined override (cycled)
if isfield(cfg.plot,'custom_linetypes') && ~isempty(cfg.plot.custom_linetypes)
L = cfg.plot.custom_linetypes;
ls = L{ mod(gi-1, numel(L)) + 1 };
end
lbl = buildLabel(grpTbl(gi,:), group_by);
% Main line (dark)
colL = cols_line(gi,:);
h.lines(gi) = plot(xu, yu, ...
'LineWidth', cfg.plot.lineWidth, ...
'Marker', cfg.plot.marker, 'MarkerSize', 3, ...
'Color', colL, 'LineStyle', ls, ...
'DisplayName', char(lbl));
% Spread (IQR) in line color
if any(isfinite(ylo)) && any(isfinite(yhi))
h.err(gi) = errorbar(xu, yu, ylo, yhi, 'LineStyle','none', ...
'Color', colL, 'CapSize', cfg.plot.capSize, 'HandleVisibility','off');
h.err(gi).LineWidth = cfg.plot.errWidth;
end
% Raw kept scatter (light)
if cfg.show_raw
keep_all = false(size(yi));
for k = 1:numel(xu)
bin = (iu==k);
yy = yi(bin);
km = outlierMask(yy, cfg, strcmpi(cfg.y_scale,'log'));
if nnz(km) < cfg.min_pts_x, km = true(size(yy)); end
keep_all(bin) = km;
end
colS = cols_scatter(gi,:);
scatter(xi(keep_all), yi(keep_all), cfg.plot.scatterSize, colS, 'filled', ...
'MarkerFaceAlpha', cfg.plot.scatterAlpha, 'MarkerEdgeAlpha', cfg.plot.scatterAlpha, ...
'HandleVisibility','off');
end
% Precoded overlay (dotted, squares), in line color
if cfg.show_precoded && ~isempty(y_raw_p) && strcmpi(cfg.y_axis,'BER')
ypi = y_raw_p(idx);
ypu = nan(size(xu));
for k = 1:numel(xu)
bin = (iu==k);
yy = ypi(bin);
yy = yy(isfinite(yy));
if isempty(yy), continue; end
km = outlierMask(yy, cfg, true);
if nnz(km) < cfg.min_pts_x, km = true(size(yy)); end
yy = yy(km);
if strcmpi(cfg.agg,'median'), ypu(k)=median(yy,'omitnan'); elseif strcmpi(cfg.agg,'mean'), ypu(k)=mean(yy,'omitnan'); elseif strcmpi(cfg.agg,'min'), ypu(k)=min(yy); elseif strcmpi(cfg.agg,'max'), ypu(k)=max(yy); end
end
h.lines_p(gi) = plot(xu, ypu, ...
'LineWidth', max(1.2, cfg.plot.lineWidth-0.2), ...
'Marker', cfg.plot.marker_precoded, 'MarkerSize', 3, ...
'Color', colL, 'LineStyle', ':', ...
'DisplayName', [char(lbl) ' (precoded)']);
end
end
%% ---- Axes / Labels / FEC
ylabel(cfg.y_axis, 'Interpreter','none');
xlabel(x_label, 'Interpreter','none');
set(gca, 'YScale', cfg.y_scale, 'FontSize', 11);
% legend('Location', cfg.plot.legendLocation); box on;
xticks(floor(xu));
xlim([min(xu), max(xu)])
if startsWith(cfg.y_axis,"BER",'IgnoreCase',true)
for v = cfg.fec_lines
yline(v, '--', 'Color', cfg.plot.fecColor, ...
'LineWidth', cfg.plot.fecLineWidth, 'HandleVisibility','off');
end
ylim([1e-5, 0.5]);
yticks([1e-5, 1e-4, 1e-3, 1e-2, 1e-1]);
end
end % ===== main =====
%% ===================== Helpers =====================
function cfg = filldefaults(cfg, defs)
fn = fieldnames(defs);
for i = 1:numel(fn)
f = fn{i};
if ~isfield(cfg, f) || isempty(cfg.(f))
cfg.(f) = defs.(f);
elseif isstruct(defs.(f)) && isstruct(cfg.(f))
cfg.(f) = filldefaults(cfg.(f), defs.(f)); % recursive for structs
end
end
end
function out = tern(cond, a, b)
if cond
out = a;
else
out = b;
end
end
function T2 = applyFilters(T, filters)
if isempty(filters), T2 = T; return; end
keep = true(height(T),1);
fns = fieldnames(filters);
for i = 1:numel(fns)
name = fns{i};
if ~ismember(name, T.Properties.VariableNames)
warning('Filter column "%s" not found. Ignored.', name); %#ok<*WNTAG>
continue
end
val = filters.(name);
col = T.(name);
if isa(val,'function_handle')
m = val(col);
if ~islogical(m) || ~isequal(size(m), size(col))
error('Filter for %s must return logical mask of same size.', name);
end
keep = keep & m;
else
keep = keep & ismember(col, val);
end
end
T2 = T(keep,:);
end
function [x, label] = computeX(T, whichX)
switch lower(whichX)
case {'symbolrate','baudrate'}
x = T.symbolrate * 1e-9;
label = 'Symbol rate [GBd]';
case 'bitrate'
if ~ismember('pam_level', T.Properties.VariableNames)
error('bitrate requires "pam_level" column.');
end
bits = floor(log2(double(T.pam_level))*10)/10;
x = (T.symbolrate .* bits) * 1e-9;
label = 'Grossrate [Gb/s]';
case 'grossrate'
x = (T.grossrate) * 1e-9;
label = 'Grossrate [Gb/s]';
otherwise
if ~ismember(whichX, T.Properties.VariableNames)
error('x_axis "%s" not found in table.', whichX);
end
x = T.(whichX);
label = whichX;
end
x = double(x(:));
end
function keep = outlierMask(y, cfg, useLog)
if isempty(y), keep = false(size(y)); return; end
y = y(:);
switch lower(cfg.outlier)
case 'none'
keep = true(size(y)); return
case 'mad'
z = tern(useLog, log10(y), y);
med = median(z,'omitnan');
madv = median(abs(z-med),'omitnan');
if ~(isfinite(madv) && madv>0)
keep = true(size(y)); return
end
sigma = 1.4826*madv;
zz = tern(useLog, log10(y), y);
keep = abs(zz - med) <= cfg.mad_z*sigma;
case 'pctl'
pr = prctile(y, cfg.pct_limits);
keep = (y >= pr(1)) & (y <= pr(2));
otherwise
error('Unknown outlier mode "%s".', cfg.outlier);
end
end
function s = buildLabel(grpRow, group_by)
parts = strings(1, numel(group_by));
for i = 1:numel(group_by)
key = group_by{i};
val = grpRow.(key);
if iscell(val), val = val{1}; end
if islogical(val), val = tern(val,'w/','w/o'); end
if key == "equalizer_structure"
key = '';
val = upper(val);
val = strrep(val,'_',' ');
end
if key == "pre_emph"
% key = strrep(key,'_','-');
val = [val, ' pre-emph.'];
key = '';
end
parts(i) = sprintf('%s %s', key, string(val));
end
s = strjoin(parts, ', ');
end
function [cols_line, cols_scatter] = buildGroupColors(nG, plotcfg)
% --- 1) User-provided custom colors -------------------------------
if isfield(plotcfg,'custom_colors') && ~isempty(plotcfg.custom_colors)
C = plotcfg.custom_colors;
if size(C,1) < nG
error('custom_colors must have at least nG=%d rows.', nG);
end
cols_line = C(1:nG, :);
% Scatter colors: either user-provided or lightened
if isfield(plotcfg,'custom_colors_scatter') && ~isempty(plotcfg.custom_colors_scatter)
Cs = plotcfg.custom_colors_scatter;
if size(Cs,1) < nG
error('custom_colors_scatter must have at least nG=%d rows.', nG);
end
cols_scatter = Cs(1:nG, :);
else
% auto-lighten scatter colors
cols_scatter = zeros(nG,3);
for i = 1:nG
cols_scatter(i,:) = lightenColor(cols_line(i,:), 0.40);
end
end
return;
end
% --- 2) Standard behavior (using cbrewer2 or fallback) ------------
useBrewer = plotcfg.use_cbrewer2 && exist('cbrewer2','file')==2;
if useBrewer
N = max(2*nG, 12);
C = cbrewer2(plotcfg.colormap, N);
cols_line = zeros(nG,3);
cols_scatter = zeros(nG,3);
for i = 1:nG
if plotcfg.paired_dark_first
dark = C(2*i-1, :);
light = C(2*i, :);
else
light = C(2*i-1, :);
dark = C(2*i, :);
end
cols_line(i,:) = dark;
cols_scatter(i,:) = light;
end
else
C = lines(max(nG,7));
cols_line = C(1:nG,:);
cols_scatter = zeros(nG,3);
for i = 1:nG
cols_scatter(i,:) = lightenColor(cols_line(i,:), 0.50);
end
end
end
function c2 = lightenColor(c, fracTowardWhite)
c = c(:).';
c2 = (1-fracTowardWhite)*c + fracTowardWhite*1;
end

View File

@@ -0,0 +1,38 @@
X-Werte;PAM-2;PAM-4;PAM-6;PAM-8;PAM-12
224;204;;;;
205,5;193,4;;;;
205,1;189,7;;;;
192;168;;;;
240;;427,4;;;
225;;420,5;;;
210;;336;;;
184;;332;;;
192;;320;;;
176;;306,0869565;;;
190;;304;;;
168;;294;;;
156,2;;287,1;;;
160,8;;286,9;;;
170;;272;;;
132;;250,9505703;;;
112;;209,3457944;;;
172;;337;;;
216;;;474,6;;
147,2;;;329,9;;
132;;;319,7891753;;
143,1;;;318;;
160;;;377;;
225;;;;562,5;
200;;;;510;
160;;;;438;
180;;;;432;
180;;;;432;
144;;;;384;
143,7;;;;363,4;
144;;;;360;
136;;;;353,859497;
136;;;;342,7995295;
128;;;;329,0488432;
129,7;;;;311,2;
160;;;;413;
160;;;;;481,2
1 X-Werte PAM-2 PAM-4 PAM-6 PAM-8 PAM-12
2 224 204
3 205,5 193,4
4 205,1 189,7
5 192 168
6 240 427,4
7 225 420,5
8 210 336
9 184 332
10 192 320
11 176 306,0869565
12 190 304
13 168 294
14 156,2 287,1
15 160,8 286,9
16 170 272
17 132 250,9505703
18 112 209,3457944
19 172 337
20 216 474,6
21 147,2 329,9
22 132 319,7891753
23 143,1 318
24 160 377
25 225 562,5
26 200 510
27 160 438
28 180 432
29 180 432
30 144 384
31 143,7 363,4
32 144 360
33 136 353,859497
34 136 342,7995295
35 128 329,0488432
36 129,7 311,2
37 160 413
38 160 481,2

View File

@@ -0,0 +1,76 @@
database_type = 'mysql';
dataBase = 'labor_highspeed';%'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\silas_labor_newdsp_newstructure.db';
db = DBHandler("dataBase", [dataBase], "type", database_type);
M = 8;
fp = QueryFilter();
% fp.where('Runs', 'run_id','EQUALS', 987);
fp.where('Runs', 'pam_level','EQUALS', M);
% fp.where('Runs', 'symbolrate','EQUALS', 165e9); %150, 165, 180, 195, 210, 225, 240
fp.where('Runs', 'fiber_length','EQUALS', 2);
% fp.where('Runs', 'is_mpi','EQUALS', 0);
% fp.where('Runs', 'power_pd_in','GREATER_THAN', 7);
% fp.where('Runs', 'interference_path_length','EQUALS', 1000);
% fp.where('Runs', 'loop_id','GREATER_THAN', 11);
% fp.where('Runs', 'sir','EQUALS',18);
fp.where('Runs', 'wavelength','EQUALS', 1310);
% fp.where('Runs', 'db_mode','EQUALS', 1); % 0 == high preemphasis // 1 == low preemphasis
% fp.where('Runs', 'rop_attenuation','EQUALS', 0);
fields = db.getTableFieldNames('power_state_info');
fields = [fields; db.getTableFieldNames('dashboard_ungrouped_alltime')]; %dashboard_ungrouped_after_nov_2025 dashboard_ungrouped_aug_nov_2025
[dataTable,~] = db.queryDB(fp, fields);
%%
cfg = struct;
cfg.x_axis = 'grossrate'; % 'symbol rate' | 'bitrate' | 'wavelength' grossrate
cfg.y_axis = 'BER'; % 'BER' | 'GMI' | 'AIR' | ...
cfg.group_by = {'equalizer_structure','pre_emph'};
cfg.filters = struct('is_mpi',0,'pam_level',M,'equalizer_structure',[equalizer_structure.ml_mlse]);%,equalizer_structure.vnle_pf_mlse,equalizer_structure.vnle]);
cfg.y_scale = 'auto'; % auto -> log for BER*, linear otherwise
cfg.outlier = 'mad'; % simple, robust; 'none' or 'pctl' also available
cfg.show_raw = false;
cfg.show_spread = 'none'; % 'none' or 'iqr' or minmax
cfg.agg = 'min'; % or 'median'
cfg.show_precoded = 0;
cfg.fec_lines = [2.2e-4 4.85e-3 2e-2]; % optional
cfg.figure_number = 42;
cfg.plot.custom_colors = [
clr.Paired.red;
clr.Paired.blue;
clr.Paired.green;
clr.Paired.orange;
clr.Paired.purple
];
cfg.plot.custom_colors_scatter = [
clr.Paired.lightred;
clr.Paired.lightblue;
clr.Paired.lightgreen;
clr.Paired.lightorange;
clr.Paired.lightpurple
];
% New styling knobs
cfg.plot.use_cbrewer2 = true;
cfg.plot.colormap = 'Paired';
cfg.plot.paired_dark_first = false; % dark for lines, light for scatter
cfg.plot.lineWidth = 2.0;
cfg.plot.errWidth = 1.2;
cfg.plot.scatterAlpha = 0.35;
cfg.plot.legendLocation = 'best';
cfg.plot.fecLineWidth = 2.4; % thicker FEC limits
plot_measurements_gpt(dataTable, cfg);
% beautifyBERplot()
%% FIG PRE EMPHASIS

View File

@@ -0,0 +1,87 @@
database_type = 'mysql';
dataBase = 'labor_highspeed';%'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\silas_labor_newdsp_newstructure.db';
db = DBHandler("dataBase", [dataBase], "type", database_type);
M = 8;
fp = QueryFilter();
% fp.where('Runs', 'run_id','EQUALS', 987);
fp.where('Runs', 'pam_level','EQUALS', M);
% fp.where('Runs', 'symbolrate','EQUALS', 165e9);
fp.where('Runs', 'fiber_length','EQUALS', 2);
fp.where('Runs', 'is_mpi','EQUALS', 0);
% fp.where('Runs', 'interference_path_length','EQUALS', 1000);
% fp.where('Runs', 'loop_id','GREATER_THAN', 11);
% fp.where('Runs', 'sir','EQUALS',18);
fp.where('Runs', 'wavelength','EQUALS', 1310);
% fp.where('Runs', 'db_mode','EQUALS', 1); % 0 == high preemphasis // 1 == low preemphasis
fp.where('Runs', 'rop_attenuation','EQUALS', 0);
fields = db.getTableFieldNames('power_state_info');
fields = [fields; db.getTableFieldNames('dashboard_ungrouped_new')];
[dataTable,~] = db.queryDB(fp, fields);
eqstructures = unique(dataTable.equalizer_structure);
% Create the figure
figure(18);
hold on
for pre_emph = [0,1]
dbmode_filtered = dataTable(dataTable.db_mode == ~pre_emph,:);
for eqs = [equalizer_structure.vnle]
eq_choice = equalizer_structure(eqs);
if sum(eqstructures == eq_choice)~=1
disp(eq_choice)
continue
end
eq_filtered = dbmode_filtered(dbmode_filtered.equalizer_structure == eq_choice,:);
if eqs ==equalizer_structure.vnle_pf_mlse
eq_filtered = eq_filtered(eq_filtered.DIR == "1",:);
end
symbolrate_sorted = sortrows(eq_filtered,{'symbolrate'}, 'ascend');
% Example data (replace these with your real vectors)
symbolrate = symbolrate_sorted.symbolrate.*1e-9; % in baud
bitrate = symbolrate * 2;
gmi = symbolrate_sorted.GMI; % BER
snr = symbolrate_sorted.SNR; % BER
cols = cbrewer2('Paired',12);
dname = [char(eq_choice)];
dname = strrep(dname,'_','+');
if pre_emph
dname = [dname,'; w/ pre-emph.'];
else
dname = [dname,'; w/o pre-emph.'];
end
plot(symbolrate, snr, 'LineWidth', 1.5, 'MarkerSize', 5,'Marker','o','LineStyle','-','Color',cols((2*eqs)+1+pre_emph,:),'MarkerEdgeColor',cols((2*eqs)+1+pre_emph,:),'MarkerFaceColor',[1,1,1],'DisplayName',[dname]);
grid on;
% Axis labels and title
xlabel('Bit Rate Gbps', 'FontSize', 12);
ylabel('GMI', 'FontSize', 12);
title('GMI vs. Bit Rate', 'FontSize', 14, 'FontWeight', 'bold');
% Improve tick formatting
set(gca, 'XScale', 'linear', ...
'YScale', 'linear', ...
'TickLabelInterpreter', 'none', ...
'FontSize', 11);
legend
xticks(symbolrate);
% Optional: tighten axis limits
xlim([min(symbolrate), max(symbolrate)]);
% ylim([log2(M)-1, log2(M)]);
end
end

View File

@@ -0,0 +1,96 @@
database_type = 'mysql';
dataBase = 'labor_highspeed';%'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\silas_labor_newdsp_newstructure.db';
db = DBHandler("dataBase", [dataBase], "type", database_type);
fp = QueryFilter();
fp.where('power_state_info', 'pam_level','EQUALS', 4);
fp.where('power_state_info', 'db_mode','EQUALS', 1);
% fp.where('power_state_info', 'fiber_length','EQUALS', 1);
fp.where('power_state_info', 'is_mpi','EQUALS', 0);
fields = db.getTableFieldNames('power_state_info');
% [dataTable,~] = db.queryDB(fp, fields);
fiber_len = unique(dataTable.fiber_length);
cnt = 0;
y_variable = 'power_mzm';
x_variable = "wavelength";
f = figure(3);
clf
hold on
for fl = 1:numel(fiber_len)
fl_filtered = dataTable(dataTable.fiber_length == fiber_len(fl),:);
[~, ia] = unique(fl_filtered.run_id, 'first');
fl_filtered = fl_filtered(ia, :);
fl_filtered_ = groupsummary( ...
fl_filtered, ... % input table
x_variable, ... % grouping variable
"mean", ... % which summary statistic
y_variable); % which column to average
wavelength_sorted = sortrows(fl_filtered, {'wavelength'}, 'ascend');
% pull out your vectors
lambda = wavelength_sorted.wavelength;
power_laser = wavelength_sorted.power_laser;
power_mzm = wavelength_sorted.power_mzm;
power_rop = wavelength_sorted.power_rop;
power_pd = wavelength_sorted.power_pd_in;
voa = wavelength_sorted.voa_atten;
len = wavelength_sorted.fiber_length;
run_ids = wavelength_sorted.run_id; % <-- this is what we want in the datatip
cols = linspecer(8);
% plot the two curves and capture their Line handles
% h1 = plot(lambda, power_laser,'LineWidth', 0.5, 'MarkerSize', 4,'Marker','o','LineStyle','none','Color',cols(fl,:),'MarkerFaceColor',cols(fl,:),'DisplayName','Laser Output');
% % Add run_id as a datatip row
% % For each line, tell the datatip template where to find the run_id:
% h1.DataTipTemplate.DataTipRows(end+1) = ...
% dataTipTextRow('run\_id', run_ids);
% h1.DataTipTemplate.DataTipRows(end+1) = ...
% dataTipTextRow('len', run_ids);
% h1.DataTipTemplate.DataTipRows(end+1) = ...
% dataTipTextRow('voaatten', voa);
%
dname = sprintf('%s; %d km',y_variable, fiber_len(fl));
h2 = plot(fl_filtered_.(x_variable), fl_filtered_.(['mean_',y_variable]), 'LineWidth', 1, 'MarkerSize', 4,'Marker','o','LineStyle','-','Color',cols(fl,:),'MarkerFaceColor',cols(fl,:),'DisplayName',dname);
h2.DataTipTemplate.DataTipRows(end+1) = ...
dataTipTextRow('run\_id', run_ids);
h2.DataTipTemplate.DataTipRows(end+1) = ...
dataTipTextRow('len', len);
h2.DataTipTemplate.DataTipRows(end+1) = ...
dataTipTextRow('voaatten', voa);
grid on;
xticks(sort(unique(lambda)));
xticklabels(sort(unique(lambda)));
% Labels, scales, legend, etc.
xlabel('Wavelength in nm','FontSize',12);
ylabel('Power in dB','FontSize',12);
title('Power ','FontSize',14,'FontWeight','bold');
set(gca, 'XScale','linear','YScale','linear','FontSize',11);
legend
xlim([min(lambda)-2, max(lambda)+2]);
ylim([floor(min(fl_filtered_.(['mean_',y_variable])))-1 12]);
ylim([-12 12]);
cnt = cnt+1;
yline(8,'HandleVisibility','off');
end
yline([4.85e-3, 2e-2],'--','LineWidth',1,'HandleVisibility','off');
posH = get(f, 'Position'); % [left, bottom, width, height]
newPos = [posH(1), posH(2), 750, 300];
set(f, 'Position', newPos);

View File

@@ -0,0 +1,380 @@
% === SETTINGS ===
dsp_options.append_to_db = 0;
dsp_options.max_occurences = 1;
experiment = "highspeed_2024";
dsp_options.mode = "load_run_id"; % 'simulate' & 'load_files'
dsp_options.load_file_path = struct();
if dsp_options.mode == "load_run_id"
if experiment == "highspeed_2024"
dsp_options.database_type = "mysql";
dsp_options.dataBase = 'labor_highspeed';%'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\silas_labor_newdsp_newstructure.db';
dsp_options.storage_path = 'Z:\2024\sioe_labor\';
db = DBHandler("dataBase", [dsp_options.dataBase],...
"type", dsp_options.database_type,"server","134.245.243.254","user","silas","password","silas");
elseif experiment == "mpi_ecoc_2025"
dsp_options.database_type = 'mysql';
dsp_options.dataBase = 'labor';
dsp_options.storage_path = 'Z:\2025\ECOC Silas\ecoc_2025\';
db = DBHandler("dataBase", [dsp_options.dataBase], "type", dsp_options.database_type);
end
elseif dsp_options.mode == "load_files"
dsp_options.load_file_path.tx_bits_path = "Z:\2025\ECOC Silas\ecoc_2025\mpi_opti_1000m_pam2 4 6 8\20250417_091513_PAM_4_R_112_bits.mat"';
dsp_options.load_file_path.tx_symbols_path = "Z:\2025\ECOC Silas\ecoc_2025\mpi_opti_1000m_pam2 4 6 8\20250417_091513_PAM_4_R_112_symbols.mat"';
dsp_options.load_file_path.rx_raw_path = "Z:\2025\ECOC Silas\ecoc_2025\mpi_opti_1000m_pam2 4 6 8\20250417_091525_PAM_4_R_112_rec01_rx_signal_raw.mat"';
elseif dsp_options.mode == "simulate"
error('Not yet implemented')
end
% === Get Run ID's ===
fp = QueryFilter();
% fp.where('Runs', 'run_id','EQUALS', 2776);
M = 6;
fp.where('Runs', 'pam_level','EQUALS', M);
fp.where('Runs', 'bitrate','EQUALS', 360e9);%360,390
% fp.where('Runs', 'symbolrate','EQUALS', 195e9);
fp.where('Runs', 'fiber_length','EQUALS', 2);
fp.where('Runs', 'is_mpi','EQUALS', 0);
% fp.where('Runs', 'interference_path_length','EQUALS', 1000);
% fp.where('Runs', 'loop_id','GREATER_THAN', 11);
% fp.where('Runs', 'sir','EQUALS',18);
fp.where('Runs', 'wavelength','EQUALS', 1310);
fp.where('Runs', 'db_mode','EQUALS', 0);
fp.where('Runs', 'rop_attenuation','EQUAL', 0);
% fp.where('Runs', 'power_pd_in','LESS_THAN', 7);
[dataTable,~] = db.queryDB(fp, db.getTableFieldNames('Runs'));
% === Set LOOPS & Initialize DataStorage ===
dsp_options.parameters = struct();
% dsp_options.parameters.pf_ncoeffs = [1,2];%s[0,logspace(-4,0,10)];
wh = DataStorage(dsp_options.parameters);
wh.addStorage("ffe_package");
wh.addStorage("mlse_package");
wh.addStorage("vnle_package");
wh.addStorage("dbtgt_package");
wh.addStorage("dbenc_package");
wh.addStorage("mlmlse_package");
%% === RUN IT ===
[results,wh] = submitJobs(dataTable.run_id(:), dsp_options, "serial", 'wh', wh, 'waitbar', true);
%% =========================================================================
% LOAD METADATA
% =========================================================================
[dataTable, ~] = db.queryDB(fp, db.getTableFieldNames('Runs'));
results = results(:).'; % ensure row vector
N = numel(results);
% =========================================================================
% PREALLOCATE METRIC ARRAYS
% =========================================================================
BER_VNLE = nan(1,N);
BER_MLSE = nan(1,N);
BER_DB = nan(1,N);
BER_DB_PREC = nan(1,N);
BER_MLMLSE = nan(1,N);
BER_MLMLSE_PREC = nan(1,N);
% =========================================================================
% EXTRACT METRICS (ONE LOOP, ROBUST)
% =========================================================================
for i = 1:N
r = results{i};
% ---- VNLE (no-DB mode) ----
if isfield(r, 'vnle_package') && ~isempty(r.vnle_package)
pkg = r.vnle_package;
BER_VNLE(i) = min(cellfun(@(c) c.metrics.BER, pkg));
end
% ---- Classical MLSE (DB mode) ----
if isfield(r, 'mlse_package') && ~isempty(r.mlse_package)
pkg = r.mlse_package;
BER_MLSE(i) = min(cellfun(@(c) c.metrics.BER, pkg));
BER_MLSE_PREC(i) = min(cellfun(@(c) c.metrics.BER_precoded, pkg));
end
% ---- DB Target (DB mode) ----
if isfield(r, 'dbtgt_package') && ~isempty(r.dbtgt_package)
pkg = r.dbtgt_package;
BER_DB(i) = min(cellfun(@(c) c.metrics.BER, pkg));
BER_DB_PREC(i) = min(cellfun(@(c) c.metrics.BER_precoded, pkg));
end
% ---- ML-based MLSE (both modes) ----
if isfield(r, 'mlmlse_package') && ~isempty(r.mlmlse_package)
pkg = r.mlmlse_package;
% raw BER
BER_MLMLSE(i) = min(cellfun(@(c) c.metrics.BER, pkg));
% precoded BER
if isfield(pkg{1}.metrics, 'BER_precoded')
BER_MLMLSE_PREC(i) = min(cellfun(@(c) c.metrics.BER_precoded, pkg));
end
end
end
%% =========================================================================
% METADATA (ALWAYS INDEX-ALIGNED WITH RESULTS)
% =========================================================================
bitrate = dataTable.bitrate(:).';
baudrate = dataTable.symbolrate(:).';
rop_atten = dataTable.rop_attenuation(2:2:end).';
rop_pre = dataTable.power_rop(1:2:end).';
rop = dataTable.power_rop(2:2:end).';
% =========================================================================
% PLOT STYLE
% =========================================================================
STYLE_BASE = 2;
MARKER_SIZE = STYLE_BASE;
LINE_WIDTH = max(2, STYLE_BASE/3);
cols = cbrewer2('Paired', 8);
cm.VNLE = cols(1,:);
cm.MLSE = cols(2,:);
cm.DB_PREC = cols(3,:);
cm.DB = cols(4,:);
cm.ML_MLSE = cols(6,:);
mk = @(col,shape) {'Marker',shape,'MarkerFaceColor',col,'MarkerEdgeColor',col,'MarkerSize',MARKER_SIZE};
% =========================================================================
% FIGURE 1: BER vs BAUDRATE
% =========================================================================
figure(112+M); clf; hold on;
xGHz = baudrate * 1e-9;
plot(xGHz, BER_VNLE, 'DisplayName','VNLE', 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.VNLE);
plot(xGHz, BER_MLSE, 'DisplayName','MLSE', 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.MLSE);
% plot(xGHz, BER_MLSE_PREC, 'DisplayName','MLSE', 'LineStyle',':','LineWidth',LINE_WIDTH,'Color',cm.MLSE);
plot(xGHz, BER_DB_PREC, 'DisplayName','Diff. Precode + DB', 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.DB_PREC);
plot(xGHz, BER_MLMLSE_PREC, 'DisplayName','ML-based MLSE', 'LineStyle',':','LineWidth',LINE_WIDTH,'Color',cm.ML_MLSE);
yline(2e-2,'LineWidth',1,'HandleVisibility','off');
yline(4.85e-3,'LineWidth',1,'HandleVisibility','off');
yline(2.2e-4,'LineWidth',1,'HandleVisibility','off');
xlabel('Baudrate in GBd');
ylabel('BER');
set(gca, 'YScale', 'log'); grid on; legend('Location','best');
% beautifyBERplot;
%% ---------------- FIGURE 15 : GMI ----------------
figure(113+M); clf; hold on;
plot(xGHz, GMI_VNLE, ...
'DisplayName','VNLE', ...
mk.VNLE{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.VNLE);
plot(xGHz, GMI_MLSE, ...
'DisplayName','MLSE', ...
mk.MLSE{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.MLSE);
plot(xGHz, GMI_DB, ...
'DisplayName','DB tgt.', ...
mk.DB{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.DB);
ylim([log2(M)-1, log2(M)]);
xlabel('Baudrate in GBd');
ylabel('GMI');
set(gca, 'XTick', xticks_vals(1:2:end), 'XTickLabel', xtick_labels(1:2:end));
grid on;
legend('Location','best');
% ---------------- FIGURE 15 : AIR ----------------
m = floor(log2(M)*10)/10;
figure(114+M); clf; hold on;
plot(xGHz, GMI_VNLE.*xGHz, ...
'DisplayName','AIR VNLE', ...
mk.VNLE{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.VNLE);
% duobinary has only one GMI curve (DB output)
plot(xGHz, GMI_MLSE.*xGHz, ...
'DisplayName','AIR MLSE', ...
mk.MLSE{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.MLSE);
% MLSE symbol-wise (if present)
plot(xGHz, GMI_DB.*xGHz, ...
'DisplayName','AIR DB tgt.', ...
mk.DB{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.DB);
% ylim([log2(M)-1, log2(M)]);
xlabel('Baudrate in GBd');
ylabel('AIR in Gbps');
set(gca, 'XTick', xticks_vals(1:2:end), 'XTickLabel', xtick_labels(1:2:end));
grid on;
legend('Location','best');
% ---------------- FIGURE 15 : Information Rates ----------------
tp = TransmissionPerformance;
m = floor(log2(M)*10)/10;
figure(213+M); clf; hold on;
netrates_vnle = tp.calculateNetRate(baudrate.* m, ...
'NGMI', GMI_VNLE./m, ...
'BER', BER_VNLE);
%
% plot(xGHz, GMI_VNLE.*xGHz, ...
% 'DisplayName','GMI*R VNLE', ...
% mk.VNLE{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.VNLE);
%
% plot(xGHz, netrates_vnle.SDHD.NetRate.*1e-9, ...
% 'DisplayName','SD+HD VNLE', ...
% mk.VNLE{:}, 'LineStyle',':','LineWidth',LINE_WIDTH,'Color',cm.VNLE);
% plot(xGHz, netrates_vnle.HD.NetRate.*1e-9, ...
% 'DisplayName','Staircase VNLE', ...
% mk.VNLE{:}, 'LineStyle','-.','LineWidth',LINE_WIDTH,'Color',cm.VNLE);
%
%
% %
% % MLSE symbol-wise (if present)
% plot(xGHz, GMI_MLSE.*xGHz, ...
% 'DisplayName','GMI*R MLSE', ...
% mk.MLSE{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.MLSE);
%
% netrates_mlse = tp.calculateNetRate(baudrate.* m, ...
% 'NGMI', GMI_MLSE./m, ...
% 'BER', BER_MLSE);
% plot(xGHz, netrates_mlse.SDHD.NetRate.*1e-9, ...
% 'DisplayName','SD+HD MLSE', ...
% mk.MLSE{:}, 'LineStyle',':','LineWidth',LINE_WIDTH,'Color',cm.MLSE);
% plot(xGHz, netrates_mlse.HD.NetRate.*1e-9, ...
% 'DisplayName','Staircase MLSE', ...
% mk.MLSE{:}, 'LineStyle','-.','LineWidth',LINE_WIDTH,'Color',cm.MLSE);
% duobinary has only one GMI curve (DB output)
figure(1111); clf; hold on;
plot(xGHz, GMI_DB.*xGHz, ...
'DisplayName','GMI*R DB tgt.', ...
mk.DB{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.DB);
netrates_db = tp.calculateNetRate(baudrate.* m, ...
'NGMI', GMI_DB./m, ...
'BER', BER_DB_PREC);
plot(xGHz, netrates_db.SDHD.NetRate.*1e-9, ...
'DisplayName','SD+HD DB', ...
mk.DB{:}, 'LineStyle',':','LineWidth',LINE_WIDTH,'Color',cm.DB);
plot(xGHz, netrates_db.STAIR.NetRate.*1e-9, ...
'DisplayName','Staircase DB', ...
mk.DB_precode{:}, 'LineStyle','-.','LineWidth',LINE_WIDTH,'Color',cm.DB_precode);
plot(xGHz, netrates_db.O_FEC.NetRate.*1e-9, ...
'DisplayName','O-FEC DB', ...
mk.DB_precode{:}, 'LineStyle','--','LineWidth',LINE_WIDTH,'Color',cm.DB_precode);
plot(xGHz, netrates_db.KP4_hamming.NetRate.*1e-9, ...
'DisplayName','KP4 Hamming DB', ...
mk.DB_precode{:}, 'LineStyle',':','LineWidth',LINE_WIDTH,'Color',cm.DB_precode);
% ylim([log2(M)-1, log2(M)]);
xlabel('Baudrate in GBd');
ylabel('AIR in Gbps');
set(gca, 'XTick', xticks_vals(1:2:end), 'XTickLabel', xtick_labels(1:2:end));
grid on;
legend('Location','best');
% xlim([1, 256])
figure(2222); clf; hold on;
plot(xGHz, GMI_MLSE.*xGHz, ...
'DisplayName','GMI*R DB tgt.', ...
mk.MLSE{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.MLSE);
netrates_mlse = tp.calculateNetRate(baudrate.* m, ...
'NGMI', GMI_MLSE./m, ...
'BER', BER_MLSE);
plot(xGHz, netrates_mlse.SDHD.NetRate.*1e-9, ...
'DisplayName','SD+HD DB', ...
mk.MLSE{:}, 'LineStyle',':','LineWidth',LINE_WIDTH,'Color',cm.MLSE);
plot(xGHz, netrates_mlse.STAIR.NetRate.*1e-9, ...
'DisplayName','Staircase DB', ...
mk.VNLE{:}, 'LineStyle','-.','LineWidth',LINE_WIDTH,'Color',cm.VNLE);
plot(xGHz, netrates_mlse.O_FEC.NetRate.*1e-9, ...
'DisplayName','O-FEC DB', ...
mk.VNLE{:}, 'LineStyle','--','LineWidth',LINE_WIDTH,'Color',cm.VNLE);
plot(xGHz, netrates_mlse.KP4_hamming.NetRate.*1e-9, ...
'DisplayName','KP4 Hamming DB', ...
mk.VNLE{:}, 'LineStyle',':','LineWidth',LINE_WIDTH,'Color',cm.VNLE);
% ylim([log2(M)-1, log2(M)]);
xlabel('Baudrate in GBd');
ylabel('AIR in Gbps');
set(gca, 'XTick', xticks_vals(1:2:end), 'XTickLabel', xtick_labels(1:2:end));
grid on;
legend('Location','best');
% xlim([1, 256])
figure(3333); clf; hold on;
plot(xGHz, GMI_VNLE.*xGHz, ...
'DisplayName','GMI*R DB tgt.', ...
mk.MLSE{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.MLSE);
netrates_vnle = tp.calculateNetRate(baudrate.* m, ...
'NGMI', GMI_VNLE./m, ...
'BER', BER_VNLE);
plot(xGHz, netrates_vnle.SDHD.NetRate.*1e-9, ...
'DisplayName','SD+HD DB', ...
mk.MLSE{:}, 'LineStyle',':','LineWidth',LINE_WIDTH,'Color',cm.MLSE);
plot(xGHz, netrates_vnle.STAIR.NetRate.*1e-9, ...
'DisplayName','Staircase DB', ...
mk.VNLE{:}, 'LineStyle','-.','LineWidth',LINE_WIDTH,'Color',cm.VNLE);
plot(xGHz, netrates_vnle.O_FEC.NetRate.*1e-9, ...
'DisplayName','O-FEC DB', ...
mk.VNLE{:}, 'LineStyle','--','LineWidth',LINE_WIDTH,'Color',cm.VNLE);
plot(xGHz, netrates_vnle.KP4_hamming.NetRate.*1e-9, ...
'DisplayName','KP4 Hamming DB', ...
mk.VNLE{:}, 'LineStyle',':','LineWidth',LINE_WIDTH,'Color',cm.VNLE);
% ylim([log2(M)-1, log2(M)]);
xlabel('Baudrate in GBd');
ylabel('AIR in Gbps');
set(gca, 'XTick', xticks_vals(1:2:end), 'XTickLabel', xtick_labels(1:2:end));
grid on;
legend('Location','best');
% xlim([1, 256])

View File

@@ -0,0 +1,236 @@
precomp_mode = 0;
precomp_path = "C:\Users\Silas\Documents\MATLAB\imdd_simulation\projects\HighSpeedExperiment_2024\Auswertung_JLT";
precomp_fn = "precomp_simulated.mat";
% TX
M = 4;
fsym = 72e9;
f_nyquist = fsym/2;
apply_pulsef = 1;
fdac = 256e9;
fadc = 256e9;
% fdac = 2*fsym;
% fadc = 2*fsym;
random_key = 1;
duob_mode = db_mode.no_db;
tx_bwl = 0.8.*f_nyquist;
rx_bwl = 0.8.*f_nyquist;
rcalpha = 0.05;
kover = 16;
vbias_rel = 0.5;
u_pi = 2.9;
vbias = -vbias_rel*u_pi;
laser_wavelength = 1293;
laser_linewidth = 0;
% Channel
link_length = 60000;
% RX
rop = -8;
% EQ
eq_mode = equalizer_structure.vnle_pf_mlse;
ffe_order=[50,0,0];
vnle_order=[50,5,5];
dfe_order = [0 0 0];
len_tr = 4096*2;
mu_ffe = [0.0004 0.0004 0.0004];
mu_dfe = 0.0004;
mu_dc = 0.00;
dfe_ = sum(dfe_order)>0;
Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rc","pulselength",16,"alpha",rcalpha);
[Digi_sig,Symbols,Tx_bits] = PAMsource(...
"fsym",fsym,"M",M,"order",18,"useprbs",0,...
"fs_out",fdac,...
"applyclipping",0,"clipfactor",1.5,...
"applypulseform",apply_pulsef,"pulseformer",Pform,...
"randkey",random_key,...
"duobinary_mode",duob_mode).process();
if precomp_mode == 1 % measure channel
precomp_est = ChannelFreqResp("Nacq",1024,"Navg",64,"Ncp",63,'f_ref',fdac);
Digi_sig = precomp_est.buildOFDM();
elseif precomp_mode == 2 % apply precomp
precomp_est = ChannelFreqResp("Nacq",1024,"Navg",64,"Ncp",63,'f_ref',Digi_sig.fs);
Digi_sig = precomp_est.precomp(Digi_sig,'maxampdb',-50,'loadPath',precomp_path,'fileName',precomp_fn);
end
% Symbols.spectrum("displayname",'Tx Symbols','fignum',10,'normalizeTo0dB',1);
Digi_sig.eye(fsym,M,"fignum",1234567);
%%%%% AWG
%El_sig = M8199B("kover",kover).process(Digi_sig);
El_sig = AWG("fdac",fdac,"f_cutoff",fsym,"lpf_active",0,"kover",kover,"bit_resolution",12,"upsampling_method","samplehold","precomp_sinc_rolloff",1).process(Digi_sig);
% El_sig.spectrum("displayname",'Digi Spectrum','fignum',100,'normalizeTo0dB',0);
% El_sig = El_sig.setPower(0,"dBm");
El_sig.spectrum("displayname",'Tx Signal','fignum',10,'normalizeTo0dB',0);
%%%%% Low-pass el. components %%%%%%
El_sig = Filter('filtdegree',4,"f_cutoff",tx_bwl,"fs",fdac*kover,"filterType",filtertypes.gaussian,"active",true).process(El_sig);
% El_sig.spectrum("displayname",'Digi Spectrum','fignum',100,'normalizeTo0dB',1);
%%%%% Electrical Driver Amplifier %%%%%%
El_sig = Amplifier("amp_mode","ideal_no_noise","gain_mode","gain","amplification_db",3).process(El_sig);
El_sig = El_sig.normalize("mode","oneone");
%%%%% MODULATE E/O CONVERSION %%%%%%
[Opt_sig] = EML("mode",eml_mode.im_cosinus,"power",3,"fsimu",El_sig.fs,"lambda",laser_wavelength,"bias",vbias,"u_pi",u_pi,"linewidth",laser_linewidth,"randomkey",random_key+1).process(El_sig);
Opt_sig = Fiber("fsimu",Opt_sig.fs,"fiber_length",link_length/1000,"alpha",0.3,"D",0,"lambda0",1310,"gamma",0,"Dslope",0.07).process(Opt_sig);
%%%%%% ROP %%%%%%
Rx_sig = Amplifier("amp_mode","ideal_no_noise","gain_mode","output_power","amplification_db",rop).process(Opt_sig);
%%%%%% PD Square Law %%%%%%
Rx_sig = Photodiode("fsimu",fdac*kover,"dark_current",2e-08,"responsivity",1,"temperature",20,"nep",1.8e-11).process(Rx_sig);
%%%%%% Low-pass RX (PD, El. Connectors and Scope %%%%%%
Rx_sig = Filter('filtdegree',4,"f_cutoff",rx_bwl,"fs",fdac*kover,"filterType",filtertypes.bessel_inp,"active",true).process(Rx_sig);
% %%%%%% Low-pass Scope %%%%%%
Lp_scpe = Filter('filtdegree',4,"f_cutoff",35e9,"fs",fadc,"filterType",filtertypes.butterworth,"active",true);
% Rx_sig.spectrum("displayname",'Analog Rx Spectrum','fignum',100,'normalizeTo0dB',1);
%%%%%% Scope %%%%%%
Scpe_sig = Scope("fsimu",fdac*kover,"fadc",fadc,...
"delay",0,"fixed_delay",0,"filtertype",filtertypes.butterworth,...
"samplingdelay",0,"rand_samplingdelay",0,"freq_offset",0,"samp_jitter",0,...
"adcresolution",8,"quantbuffer",0.1,'block_dc',1,'lpf_active',1,'H_lpf',Lp_scpe).process(Rx_sig);
Scpe_sig.spectrum("displayname",'Rx Signal','fignum',10,'normalizeTo0dB',1);
Scpe_sig.eye(fsym,M,"fignum",1973763)
%%%%% Precompensation Routine %%%%%%
if precomp_mode == 1
Scpe_sig_resampled = Scpe_sig.resample("fs_in",fadc,"fs_out",2*fsym);
precomp_est.estimate(Scpe_sig_resampled,"save",false,"savePath",precomp_path,"fileName",precomp_fn);
precomp_est.plot();
precomp_est.save();
end
% Preprocess signal
Scpe_sig = preprocessSignal(Scpe_sig, Symbols, fsym);
Scpe_sig.signal = Scpe_sig.signal(1:2*Symbols.length);
use_ffe = 0;
use_dfe = 0;
use_vnle_mlse = 1;
use_dbtgt = 1;
use_dbenc = 1;
if duob_mode ~= db_mode.db_encoded
if use_ffe
ffe_order = [50, 0, 0];
eq_dfe = EQ("Ne",ffe_order,"Nb",[0,0,0],"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",0);
ffe_results = ffe(eq_dfe,M,Scpe_sig,Symbols,Tx_bits,...
"precode_mode",duob_mode,...
'showAnalysis',1,...
"postFFE",[],...
"eth_style_symbol_mapping",0);
disp('FFE:')
ffe_results.metrics.print;
end
if use_dfe
ffe_order = [50, 5, 5];
eq_dfe = EQ("Ne",ffe_order,"Nb",[2,0,0],"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",0);
dfe_results = ffe(eq_dfe,M,Scpe_sig,Symbols,Tx_bits,...
"precode_mode",duob_mode,...
'showAnalysis',0,...
"postFFE",[],...
"eth_style_symbol_mapping",0);
disp('DFE:')
dfe_results.metrics.print;
end
if use_vnle_mlse
if 0
pf_ncoeffs = 1;
eq_ = EQ("Ne",ffe_order,"Nb",dfe_order,"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
pf_ = Postfilter("ncoeff",pf_ncoeffs,"useBurg",1);
% mlse_ = MLSE_viterbi("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels);
mlse_ = MLSE("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels);
[ffe_results, mlse_results] = vnle_postfilter_mlse(eq_, pf_, mlse_, M, Scpe_sig, Symbols, Tx_bits, ...
"precode_mode", duob_mode,...
'showAnalysis', 1, ...
"postFFE", [],...
"eth_style_symbol_mapping", 0);
disp('VNLE:')
ffe_results.metrics.print;
disp('MLSE:')
mlse_results.metrics.print;
end
pf_ncoeffs = 2;
eq_ = EQ("Ne",ffe_order,"Nb",dfe_order,"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
pf_ = Postfilter("ncoeff",pf_ncoeffs,"useBurg",1);
% mlse_ = MLSE_viterbi("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels);
mlse_ = MLSE("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels);
[ffe_results, mlse_results] = vnle_postfilter_mlse(eq_, pf_, mlse_, M, Scpe_sig, Symbols, Tx_bits, ...
"precode_mode", duob_mode,...
'showAnalysis', 1, ...
"postFFE", [],...
"eth_style_symbol_mapping", 0);
disp('VNLE:')
ffe_results.metrics.print;
disp('MLSE:')
mlse_results.metrics.print;
end
if use_dbtgt
eq_ = EQ("Ne",ffe_order,"Nb",dfe_order,"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
mlse_db_ = MLSE("DIR",[1,1],"duobinary_output",0,"M",M,"trellis_states",PAMmapper(M,0).levels);
dbt_results = duobinary_target(eq_, mlse_db_, M, Scpe_sig, Symbols, Tx_bits, ...
"precode_mode", duob_mode, ...
'showAnalysis',1 ,...
"postFFE", []);
disp('DB:')
dbt_results.metrics.print;
end
end
if duob_mode == db_mode.db_encoded
eq_db_enc = EQ("Ne", ffe_order, "Nb", dfe_order, "training_length", len_tr, ...
"training_loops", 5, "dd_loops", 5, "K", 2, "DCmu", mu_dc, ...
"DDmu", [mu_ffe mu_dfe], "DFEmu", 0.005, "FFEmu", 0, "plotfinal", 0, "ideal_dfe", 1);
mlse_db_enc = MLSE("DIR", [1,1], "duobinary_output", 0, "M", M, "trellis_states", PAMmapper(M,0).levels);
db_results = duobinary_signaling(eq_db_enc, mlse_db_enc, M, Scpe_sig, Symbols, Tx_bits, "precode_mode",duob_mode, "showAnalysis",1,"postFFE",[]);
db_results.metrics.print;
end

View File

@@ -0,0 +1,162 @@
dsp_options.storage_path = 'Z:\2024\sioe_labor\';
dsp_options.max_occurences = 1;
db = DBHandler("dataBase", 'labor_highspeed', "type", 'mysql','server','134.245.243.254','password','silas','user','silas');
% fp = QueryFilter();
%
% fp.where('Runs','fiber_length','EQUALS', 2);
% fp.where('Runs','wavelength','EQUALS', 1310);
% fp.where('Runs','bitrate','EQUALS', 300e9);
% fp.where('Runs','pam_level','EQUALS', 4);
% fp.where('Runs','rop_attenuation','EQUALS', 0);
% fp.where('Runs','is_mpi','EQUALS', 0);
% fp.where('Runs', 'db_mode','EQUALS', 0);
% % fields = db.getTableFieldNames('Runs');
% % [dataTable,~] = db.queryDB(fp, fields);
%
run_ids = [ 993 1205 1413 1623 1833 2043 2253 2628 2836 2958 3000 3042 3323 5098 5225 5267 5309];
for id = run_ids
fp = QueryFilter();
fp.where('Runs', 'run_id','EQUALS', id);
fields = db.getTableFieldNames('power_state_info');
fields = [fields; db.getTableFieldNames('Runs')];
fields = [fields; db.getTableFieldNames('dashboard_ungrouped_alltime')]; %dashboard_ungrouped_after_nov_2025 dashboard_ungrouped_aug_nov_2025
fields = unique(fields);
[dataTable,~] = db.queryDB(fp, fields);
fsym = dataTable(1,:).symbolrate;
M = double(dataTable(1,:).pam_level);
duob_mode = db_mode(strrep(dataTable(1,:).db_mode,'"',''));
% Load and Sync signal data from DB
[Tx_bits, Symbols, Scpe_cell, ~] = loadAndSyncSignalDataFromDb(dataTable(1,:), dsp_options);
% Preprocess signal
Scpe_sig = preprocessSignal(Scpe_cell{1}, Symbols, fsym);
% Show spectrum
Scpe_sig.spectrum("fignum",1,"displayname",'Rx')
meta = struct();
meta.varnames = dataTable.Properties.VariableNames;
for k = 1:numel(meta.varnames)
v = meta.varnames{k};
col = dataTable.(v);
if isnumeric(col) || islogical(col)
meta.(v) = col;
elseif isstring(col)
meta.(v) = cellstr(col);
elseif iscellstr(col)
meta.(v) = col;
else
error("Unsupported table column type: %s", class(col))
end
end
exp_data.metadata = meta;
exp_data = struct();
exp_data.metadata = dataTable;
exp_data.tx_bits = Tx_bits.signal;
exp_data.tx_signal = Symbols.signal;
exp_data.rx_signal_2sps = Scpe_sig.signal;
fname = dataTable(1,:).rx_raw_path;
[~, filename, ext] = fileparts(fname);
filename = strrep(filename,"_raw_signal","");
filename = filename + ext;
savepath = fullfile('F:\2024\sioe_labor\export_skuehl\',filename);
save(savepath,'exp_data','-v7.3');
end
%% simple FFE
mu_ffe = [0.0001, 0.0008, 0.001];
mu_dfe = 0.0004;
ffe_order = [50, 0, 0];
eq_dfe = EQ("Ne",ffe_order,"Nb",[0,0,0],"training_length",4096,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.005,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",0);
ffe_results = ffe(eq_dfe,M,Scpe_sig,Symbols,Tx_bits,...
"precode_mode",duob_mode,...
'showAnalysis',0,...
"postFFE",[],...
"eth_style_symbol_mapping",0);
ffe_results.metrics.print("description",'FFE');
ffe_results.config.equalizer_structure = "ffe";
%% a) VNLE // b) concatenated VNLE + MLSE
pf_ncoeffs = 1;
ffe_order = [50, 5, 5];
dfe_order = [0,0,0];
eq_ = EQ("Ne",ffe_order,"Nb",dfe_order,"training_length",4096,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.005,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",0);
pf_ = Postfilter("ncoeff",pf_ncoeffs,"useBurg",1);
if duob_mode == db_mode.no_db && M == 6 %only for PAM-6 and no duobinary precoding, otherwise leads to false sequence estimation
trellexlusion = 1;
else
trellexlusion = 0;
end
%state_mode 3 -> stat lvl; state_mode 2 -> use target lvls
%scale_mode 2 -> mmse adaption
mlse_ = MLSE("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels,'scale_mode',2,'trellis_exclusion',trellexlusion,'trellis_state_mode',2);
[vnle_results, mlse_results] = vnle_postfilter_mlse(eq_, pf_, mlse_, M, Scpe_sig, Symbols, Tx_bits, ...
"precode_mode", duob_mode,...
'showAnalysis', 0, ...
"postFFE", [],...
"eth_style_symbol_mapping", 0);
vnle_results.metrics.print("description",'VNLE');
mlse_results.metrics.print("description",'VNLE + PF + MLSE');
%% Duobinary Equalization
if duob_mode == db_mode.no_db && M == 6 %only for PAM-6 and no duobinary precoding, otherwise leads to false sequence estimation
trellexlusion = 1;
else
trellexlusion = 0;
end
mlse_db_ = MLSE("DIR",[1,1],"duobinary_output",0,"M",M,"trellis_states",PAMmapper(M,0).levels,'scale_mode',2,'trellis_exclusion',trellexlusion,'trellis_state_mode',3);
ffe_order = [50, 5, 5];
dfe_order = [0,0,0];
eq_ = EQ("Ne",ffe_order,"Nb",dfe_order,"training_length",4096,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.005,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
dbt_results = duobinary_target(eq_, mlse_db_, M, Scpe_sig, Symbols, Tx_bits, ...
"precode_mode", duob_mode, ...
'showAnalysis', 0,...
"postFFE", []);
dbt_results.metrics.print("description",'Duobinary EQ');
%% Ml based Viterbi
%ML-based MLSE (L=2)
mu_ml = 0.01; training_epochs = 100;
ml_mlse_equalizer = ML_MLSE("epochs_tr",training_epochs,"epochs_dd",1, ...
"len_tr",length(Scpe_sig),"mu_dd",mu_ml,"mu_tr",mu_ml,"order",11,"sps",2, ...
"traceback_depth",128,"L",1,"delta",4,"adaptive_mu",0);
[ml_mlse_results] = ml_mlse(ml_mlse_equalizer, M, Scpe_sig, Symbols, Tx_bits,"precode_mode",duob_mode);
ml_mlse_results.metrics.print("description",'ML pre Eq. + Viterbi')

View File

@@ -0,0 +1,84 @@
% cleanup measurement data
% remove fots from files
% merge measurments into database
if 1
folderPath = "/Volumes/NT-Labor/2024/sioe/High Speed Messungen Oktober/mpi_measurement";
% Get list of all files in the folder and subfolders
fileList = dir(fullfile(folderPath, '**', '*'));
% Loop through each file
big_wh_list = {};
small_wh_list = {};
for i = 1:length(fileList)
fileName = fileList(i).name;
iswh = strfind(fileName, 'wh');
if ~isempty(iswh)
wh = load(fullfile(fileList(i).folder, fileName));
wh = wh.obj;
if isa(wh,'DataStorage')
if prod(wh.dim) > 2
big_wh_list{end+1} = wh;
else
small_wh_list{end+1} = wh;
end
end
end
end
end
%%% merge MPI structs by copying the values %%%
params.M = [4,6,8];
params.bitrate = [224,336,448].*1e9;
params.duobinary = [0,1];
params.interference_atten = [0 3 6 9 12 15 18 21 24 27 30 45];
wh_new=DataStorage(params);
for w = 1:numel(big_wh_list)
wh = big_wh_list{w};
for m = wh.parameter.M.values
for br = wh.parameter.bitrate.values
for db = wh.parameter.duobinary.values
for iatten = wh.parameter.interference_atten.values
storage_names = fieldnames(wh.sto);
for i = 1:length(storage_names)
%get two things:
%1) current data storage name
cur_storage = storage_names{i};
%2) the value saved at this storage and dimension
value = wh.getStoValue(cur_storage,m,br,db,iatten);
% check if storage name already exists, if not
% .addStorgae(...)
if ~isfield(wh_new.sto,cur_storage)
wh_new.addStorage(cur_storage);
end
if isempty(wh_new.getStoValue(cur_storage,m,br,db,iatten))
% Finally, add the value to the repsective storage
wh_new.addValueToStorage(value,cur_storage,m,br,db,iatten);
else
warning('double vaue?')
end
end
end
end
end
end
end

View File

@@ -0,0 +1,92 @@
% basePath = 'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\';
% db = DBHandler("pathToDB",[basePath,'silas_labor.db']);
if 1
uloops = struct;
uloops.precomp = [0,1];
uloops.db_precode = [0,1];
uloops.bitrate = [420].*1e9; %[300,330,360,390,420,450,480] [224,336,360,390,420,448] for MPI
% uloops.laser_wavelength = [1293,1297.5,1302,1306.5,1310,1313.4,1318,1322.7,1327.4];
uloops.laser_wavelength = [1310];
uloops.M = [4];
uloops.link_length = [1]; % 1,2,3,5,6,8,10
wh = DataStorage(uloops);
wh.addStorage("ber");
% wh = submit_simulations(wh,"parallel",0,"simulation_mode",0);
wh = submit_handle(@dsp_mpi,wh,"parallel",1);
end
a = wh_mpi_112gbd.getStoValue('ber',uloops.precomp, uloops.db_precode, uloops.bitrate(1) , uloops.laser_wavelength, uloops.M, uloops.link_length);
%VNLE standalone
try
ber_vnle = cellfun(@(x) x.vnle_dfe_package{1,1}.ber_vnle, a);
end
%MLSE
try
ber_values_mlse = cellfun(@(s) cellfun(@(pkg) pkg.ber_mlse, s.vnle_pf_package, 'UniformOutput', false), a, 'UniformOutput', false);
ber_values_mlse = cell2mat(ber_values_mlse{1});
end
%DB
try
ber_values_db = cellfun(@(s) cellfun(@(pkg) pkg.ber, s.dbtgt_package, 'UniformOutput', false), a, 'UniformOutput', false);
ber_values_db = cell2mat(ber_values_db{1});
end
xax = [0
3
6
9
12
15
18
21
24
27
30
45];
cols = cbrewer2('Set1',8);
% Compute min, max, and mean for PAM 4 MLSE
min_mlse = min(ber_values_mlse, [], 2);
max_mlse = max(ber_values_mlse, [], 2);
mean_mlse = mean(ber_values_mlse, 2);
err_lower_mlse = mean_mlse - min_mlse;
err_upper_mlse = max_mlse - mean_mlse;
err_mlse = [err_lower_mlse, err_upper_mlse];
% Compute min, max, and mean for PAM 4 DB tgt.
min_db = min(ber_values_db, [], 2);
max_db = max(ber_values_db, [], 2);
mean_db = mean(ber_values_db, 2);
err_lower_db = mean_db - min_db;
err_upper_db = max_db - mean_db;
err_db = [err_lower_db, err_upper_db];
figure(1)
hold on
title('MPI');
% Plot the MLSE curve with bounded error using boundedline
[hl_mlse, hp_mlse] = boundedline(xax, mean_mlse, err_mlse,'Color', cols(1,:));
plot(xax,ber_values_mlse,'DisplayName','PAM 4 MLSE','Color',cols(1,:),'LineStyle','-','HandleVisibility','on','Marker','none','LineWidth',0.2);
% Plot the DB tgt. curve with bounded error using boundedline
[hl_db, hp_db] = boundedline(xax, mean_db, err_db, 'Color', cols(2,:));
plot(xax,ber_values_db,'DisplayName','PAM 4 MLSE','Color',cols(2,:),'LineStyle','-','HandleVisibility','on','Marker','none','LineWidth',0.2);
% Format the plot
xticks(xax);
set(gca, 'YScale', 'log');
ylim([5e-5 0.4]);
xlim([min(xax) max(xax)]);
yline([4.85e-3, 2e-2], 'HandleVisibility', 'off');
legend
% beautifyBERplot()
xlabel('Interference Attenuation');
ylabel('BER');

View File

@@ -0,0 +1,333 @@
function [output] = dsp_mpi(varargin)
simulation_mode = 0;
%%% Change folder
curFolder = pwd;
funcFolder=fileparts(mfilename('fullpath'));
if ~isempty(funcFolder)
cd(funcFolder);
end
%%% Run parameters
% TX
M = 4;
fsym = 180e9;
apply_pulsef = 1;
fdac = 256e9;
fadc = 256e9;
random_key = 1;
interference_attenuation = 0;
is_mpi = 1;
precomp = 0;
db_precode = 0;
db_encode = 0;
rcalpha = 0.05;
kover = 16;
vbias_rel = 0.5;
u_pi = 2.9;
vbias = -vbias_rel*u_pi;
laser_wavelength = 1293;
laser_linewidth = 0;
tx_bw_nyquist = 0.8;
% Channel
link_length = 1;
% RX
rop = -5;
rx_bw_nyquist = 0.8;
vnle_order1 = 50;
vnle_order2 = 5;
vnle_order3 = 5;
vnle_order=[vnle_order1,vnle_order2,vnle_order3];
dfe_order = [0 0 0];
pf_ncoeffs = 1;
alpha = 0;
len_tr = 4096*2;
mu_ffe1 = 0.0001;
mu_ffe2 = 0.0008;
mu_ffe3 = 0.001;
mu_dc = 0.005;
mu_dc = 0;
mu_ffe = [mu_ffe1 mu_ffe3 mu_ffe3];
mu_dfe = 0.0004;
dfe_ = sum(dfe_order)>0;
doub_mode = db_mode.no_db;
%%% change specific parameter if given in varargin
% Parse optional input arguments
if ~isempty(varargin)
var_s = varargin{1};
if isstruct(var_s)
fields = fieldnames(var_s);
for i = 1:numel(fields)
if isnumeric(fields{i})
eval([fields{i}, ' = ', num2str( var_s.(fields{i}) ), ';']);
fprintf("%s <-- %.2f \n", fields{i}, var_s.(fields{i}));
else
eval([fields{i}, ' = ', 'var_s.(fields{',num2str(i),'})' , ';']);
end
end
else
error('Optional variables should be passed as a struct.');
end
end
if doub_mode ~= db_mode.db_encoded
if precomp == 0 && db_precode == 1
doub_mode = db_mode.db_precoded;
db_precode = 1; % preceded data (in my measurement set, this corresponds to low precomp too!)
discard_precode = 0; %
emulate_precode = 0;
legendentry = 'low precomp; precoded';
disp('low precomp; precoded')
elseif precomp == 1 && db_precode == 1
doub_mode = db_mode.db_emulate;
db_precode = 0; % preceded data (in my measurement set, this corresponds to low precomp too!)
discard_precode = 0; %
emulate_precode = 1;
legendentry = 'high precomp; precoded';
disp('high precomp; precoded')
elseif precomp == 0 && db_precode == 0
doub_mode = db_mode.db_discard;
db_precode = 1; % preceded data (in my measurement set, this corresponds to low precomp too!)
discard_precode = 1; %
emulate_precode = 0;
legendentry = 'no precomp; not precoded';
disp('no precomp; not precoded')
elseif precomp == 1 && db_precode == 0
doub_mode = db_mode.no_db;
db_precode = 0; % preceded data (in my measurement set, this corresponds to low precomp too!)
discard_precode = 0; %
emulate_precode = 0;
legendentry = 'high precomp; not precoded';
disp('high precomp; not precoded')
end
else
end
fsym_ = floor( bitrate*1e-9./log2(M) ).*1e9;
if fsym_ ~= fsym
fsym = fsym_;
% fprintf('Adapted symbolrate to %d GBd, to match provided bitrate of %d GBit/s using PAM %d \n',fsym.*1e-9,bitrate.*1e-9, M);
end
f_nyquist = fsym/2;
basePath = 'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\';
database = DBHandler("pathToDB",[basePath,'silas_labor.db']);
useGui = 0;
% db = DBHandler("pathToDB",[basePath,'silas_labor.db']);
filterParams = database.tables;
% filterParams.Runs.run_id = 2958; % no db
% filterParams.Runs.run_id = 2937; % no db
filterParams.Configurations = struct( ...
'bitrate', bitrate, ...
'db_mode', db_precode+db_encode, ...
'fiber_length', link_length, ...
'interference_attenuation', [], ...
'interference_path_length', [], ...
'is_mpi', is_mpi, ...
'pam_level', M, ...
'precomp_amp', [], ...
'rop_attenuation', 0, ...
'symbolrate', [], ...
'v_awg', [], ...
'v_bias', [], ...
'wavelength', laser_wavelength ...
);
selectedFields = {'Runs.run_id','Runs.tx_bits_path', 'Runs.tx_symbols_path', 'Runs.rx_sync_path','Runs.rx_raw_path',...
'Configurations.db_mode','Configurations.pam_level','Configurations.bitrate','Configurations.symbolrate','Configurations.fiber_length','Configurations.wavelength','Configurations.precomp_amp','Measurements.power_rop','Configurations.v_bias',...
'Configurations.interference_attenuation'};
[dataTable,sql_query] = database.queryDB(filterParams, selectedFields);
[~, uniqueIdx] = unique(dataTable.run_id); % Get unique run_id indices
dataTable = dataTable(uniqueIdx,:); % Extract unique configurations for each run_id
fprintf('Found %d entries for requested Configuration. IDs are: %s \n \n',size(dataTable,1),jsonencode(dataTable.run_id(1:min(size(dataTable,1),100))));
output = struct();
vnle_pf_package = {};
vnle_dfe_package = {};
dbtgt_package = {};
disp(num2str(bitrate))
for iatt = 1:numel(dataTable.interference_attenuation)
current_run_id = dataTable.run_id(iatt);
Tx_bits = load([basePath, char(dataTable.tx_bits_path(iatt))]);
Tx_bits = Tx_bits.Bits;
Symbols_mapped = PAMmapper(M,0).map(Tx_bits);
Symbols_mapped.fs = fsym;
Symbols = load([basePath, char(dataTable.tx_symbols_path(iatt))]);
Symbols = Symbols.Symbols;
Scpe_load = load([basePath, char(dataTable.rx_sync_path(iatt))]);
Scpe_cell = Scpe_load.S;
[~,~,found]=Scpe_cell{2}.tsynch("reference",Symbols,"fs_ref",fsym,"debug_plots",1);
if ~found
Raw_signal = load([basePath, char(dataTable.rx_raw_path(1))]);
Raw_signal = Raw_signal.Scpe_sig_raw;
[~,Scpe_cell,found] =Raw_signal.tsynch("reference",Symbols,"fs_ref",fsym,"debug_plots",1);
end
if ~found
if length(Symbols_mapped.signal) == sum(Symbols_mapped.signal == Symbols.signal)
warning('Could not synchronize the received signal with the stored symbols!')
else
[~,Scpe_cell,found] =Raw_signal.tsynch("reference",Symbols_mapped,"fs_ref",fsym,"debug_plots",0);
end
if ~found
warning('Could not synchronize the received signal with the stored symbols!')
end
end
fsym = Symbols.fs;
if db_precode
Symbols_precoded = Symbols;
end
proc_occ = min(15,length(Scpe_cell));
for occ = 1:proc_occ
Scpe_sig = Scpe_cell{occ};
%%%%%% Sample to 2x fsym %%%%%%
Scpe_sig = Scpe_sig.resample("fs_out",2*fsym);
%%%%%% Sync Rx signal with reference %%%%%%
[Scpe_sig,~] = Scpe_sig.tsynch("reference",Symbols,"fs_ref",fsym,"debug_plots",0);
Scpe_sig = Filter('filtdegree',4,"f_cutoff",Symbols.fs.*0.5,"fs",Scpe_sig.fs,"filterType",filtertypes.gaussian,"active",true).process(Scpe_sig);
Scpe_sig = Scpe_sig - mean(Scpe_sig.signal);
%%% EQUALIZING
% eq_mlse = FFE_DCremoval("epochs_tr",5,"epochs_dd",5,"len_tr",len_tr,"mu_dd",mu_ffe(1),"mu_tr",0,"order",ffe_order(1),"sps",2,"decide",0,"dc_buffer_len",1,"mu_dc",0.05);
% eq_mlse = FFE("epochs_tr",5,"epochs_dd",5,"len_tr",len_tr,"mu_dd",mu_ffe(1),"mu_tr",0,"order",ffe_order(1),"sps",2,"decide",0);
% eq_mlse = FFE_DCremoval("epochs_tr",5,"epochs_dd",5,"len_tr",len_tr,"mu_dd",mu_ffe(1),"mu_tr",0,"order",ffe_order(1),"sps",2,"decide",0,"dc_buffer_len",512,"mu_dc",0.05);
mu_ffe = [mu_ffe1 mu_ffe2 mu_ffe3];
vnle_order=[vnle_order1,vnle_order2,vnle_order3];
% %%%%% VNLE + DFE %%%%
if 0
eq_vnle_dfe = EQ("Ne",vnle_order,"Nb",[0,0,0],"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",0);
eq_2 = FFE("epochs_tr",5,"epochs_dd",5,"len_tr",4096*2,"mu_dd",1e-4,"mu_tr",0,"order",2001,"sps",1,"decide",0);
[result] = vnle(eq_vnle_dfe,M,Scpe_sig,Symbols,Tx_bits,"precode_mode",doub_mode,"showAnalysis",1,"postFFE",[]);
vnle_dfe_package{iatt,occ} = result;
end
%%%%% VNLE + PF + MLSE %%%%
if 1
try
% len_tr = length(Symbols)-1000;
eq_vnle_ = EQ("Ne",vnle_order,"Nb",dfe_order,"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
% eq_vnle_ = VNLE("epochs_tr",5,"epochs_dd",5,"len_tr",4096*2,"mu_dd",[0.0004 0.0005 0.0006],"mu_tr",0,"order",vnle_order,"sps",2,"decide",0);
pf_ = Postfilter("ncoeff",pf_ncoeffs,"useBurg",1);
mlse_ = MLSE_viterbi("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels);
eq_2 = FFE("epochs_tr",5,"epochs_dd",5,"len_tr",4096*2,"mu_dd",1e-4,"mu_tr",0,"order",2001,"sps",1,"decide",0);
[result] = vnle_postfilter_mlse(eq_vnle_,pf_,mlse_,M,Scpe_sig,Symbols,Tx_bits,"precode_mode",doub_mode,'showAnalysis',0,"postFFE",[]);
vnle_pf_package{iatt,occ} = result;
database.addProcessingResult(current_run_id,result.resultsMLSE, result.equalizerConfigMLSE);
database.addProcessingResult(current_run_id,result.resultsVNLE, result.equalizerConfigVNLE);
catch
warning(['VNLE+MLSE fail: run id: ', num2str(current_run_id)],' occ:', num2str(occ), ' iatten: ',num2str(iatt))
end
end
%%%%% Duobinary Targeting %%%%
if 1
try
mlse_db = MLSE_viterbi("DIR",[1,1],"duobinary_output",0,"M",M,"trellis_states",PAMmapper(M,0).levels);
eq_db = EQ("Ne",vnle_order,"Nb",dfe_order,"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
eq_2 = FFE("epochs_tr",5,"epochs_dd",5,"len_tr",4096*2,"mu_dd",1e-4,"mu_tr",0,"order",2001,"sps",1,"decide",0);
[result] = duobinary_target(eq_db, mlse_db, M, Scpe_sig, Symbols, Tx_bits, "precode_mode", doub_mode,'showAnalysis',0,"postFFE",[]);
dbtgt_package{iatt,occ} = result;
database.addProcessingResult(current_run_id,result.resultsDBtgt, result.equalizerConfigDBtgt);
catch
warning(['VNLE DB+MLSE fail: run id: ', num2str(current_run_id)],' occ:', num2str(occ), ' iatten: ',num2str(iatt))
end
end
%%%%%% %db signaling => db encoded %%%%%
if 0
mlse_db_enc = MLSE_viterbi("DIR",[1,1],"duobinary_output",0,"M",M,"trellis_states",PAMmapper(M,0).levels);
eq_db_enc = EQ("Ne",vnle_order,"Nb",dfe_order,"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
[result] = duobinary_signaling(eq_db_enc, mlse_db_enc,M, Scpe_sig ,Symbols, Tx_bits);
dbenc_package{iatt,occ} = result;
end
% autoArrangeFigures;
disp('- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ')
fprintf('\n')
end
if ~isempty(curFolder)
cd(curFolder);
end
end
output.dataTable = dataTable;
output.vnle_dfe_package = vnle_dfe_package;
output.vnle_pf_package = vnle_pf_package;
output.dbtgt_package = dbtgt_package;

View File

@@ -0,0 +1,62 @@
% 1) Find RUN ID's
basePath = 'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\';
% database = DBHandler("pathToDB",[basePath,'silas_labor.db']);
database = DBHandler("type",'mysql');
filterParams = database.tables;
filterParams.Configurations = struct( ...
'bitrate', 112e9, ... %[224,336,360,390,420,448]
'db_mode', [], ...
'fiber_length', [], ...
'interference_attenuation',[], ...
'interference_path_length',300, ...
'is_mpi', 1, ...
'pam_level', 4 ...
);
selectedFields = {'Runs.run_id',...
'Configurations.db_mode','Configurations.pam_level','Configurations.bitrate','Configurations.symbolrate','Configurations.fiber_length','Configurations.wavelength',...
'Configurations.precomp_amp','Measurements.power_rop','Measurements.power_pd_in','Configurations.v_bias','Configurations.is_mpi',...
'Configurations.interference_attenuation','Configurations.rop_attenuation'};
[dataTable,sql_query] = database.queryDB(filterParams, selectedFields);
% only the rows without BER so far
% dataTable = dataTable(dataTable.BER == 0,:);
dataTable = dataTable((dataTable.fiber_length ~= 1),:);
% Ensure a parallel pool is running
pool = gcp('nocreate');
if isempty(pool)
pool = parpool;
% stop all forgotten or unfetched jobs from queue
elseif ~isempty(pool.FevalQueue.QueuedFutures) || ~isempty(pool.FevalQueue.RunningFutures)
oldq = length(pool.FevalQueue.QueuedFutures) + length(pool.FevalQueue.RunningFutures);
pool.FevalQueue.cancelAll
fprintf('Canceled %d unfetched jobs from old queue.', oldq);
end
% Number of tasks to submit (one per run_id)
nTasks = height(dataTable);
futures = parallel.FevalFuture.empty();
% Submit each DSP run as a parallel task using parfeval
for i = 1:nTasks
% Extract the run_id (other parameters could be passed if needed)
runID = dataTable.run_id(i);
% Submit the function call to dsp_run_id (assuming it returns no output, hence 0 outputs)
futures(i) = parfeval(pool, @dsp_run_id, 0, runID, "max_occurences", 15, "append_to_db", 1);
end
% Set up a waitbar to monitor progress
h = waitbar(0, 'Processing DSP runs...');
while ~all(strcmp({futures.State}, 'finished'))
finishedCount = sum(strcmp({futures.State}, 'finished'));
waitbar(finishedCount / nTasks, h);
pause(0.1);
end
delete(h);
fprintf('All DSP runs processed.\n');

View File

@@ -0,0 +1,194 @@
function [output] = dsp_run_id(run_id,options)
arguments
run_id
options.append_to_db = 0;
options.max_occurences = 4;
options.parameters = struct();
end
basePath = 'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\';
database = DBHandler("pathToDB",[basePath,'silas_labor.db']);
filterParams = database.tables;
filterParams.Configurations = struct('run_id', run_id);
selectedFields = {'Runs.run_id','Runs.tx_bits_path', 'Runs.tx_symbols_path', 'Runs.rx_sync_path','Runs.rx_raw_path',...
'Configurations.db_mode','Configurations.pam_level','Configurations.bitrate','Configurations.symbolrate','Configurations.fiber_length','Configurations.wavelength','Configurations.precomp_amp','Measurements.power_rop','Configurations.v_bias',...
'Configurations.interference_attenuation'};
[dataTable,sql_query] = database.queryDB(filterParams, selectedFields);
[~, uniqueIdx] = unique(dataTable.run_id); % Get unique run_id indices
dataTable = dataTable(uniqueIdx,:); % Extract unique configurations for each run_id
fsym = dataTable.symbolrate;
M = double(dataTable.pam_level);
duob_mode = db_mode(dataTable.db_mode);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
len_tr = 4096*2;
vnle_order1 = 50;
vnle_order2 = 5;
vnle_order3 = 5;
dfe_order = [0 0 0];
pf_ncoeffs = 1;
mu_ffe1 = 0.0001;
mu_ffe2 = 0.0008;
mu_ffe3 = 0.001;
mu_dfe = 0.0004;
mu_dc = 0.00;
mu_ffe = [mu_ffe1 mu_ffe2 mu_ffe3];
vnle_order=[vnle_order1,vnle_order2,vnle_order3];
% Overwrite default parameters if given in options.parameters
paramStruct = options.parameters;
if ~isempty(paramStruct)
paramNames = fieldnames(paramStruct);
for i = 1:numel(paramNames)
thisName = paramNames{i};
thisValue = paramStruct.(thisName);
eval([thisName ' = thisValue;']);
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
eq_ = EQ("Ne",vnle_order,"Nb",dfe_order,"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
pf_ = Postfilter("ncoeff",pf_ncoeffs,"useBurg",1);
mlse_ = MLSE_viterbi("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels);
mlse_db_ = MLSE_viterbi("DIR",[1,1],"duobinary_output",0,"M",M,"trellis_states",PAMmapper(M,0).levels);
eq_post = FFE("epochs_tr",5,"epochs_dd",5,"len_tr",4096*2,"mu_dd",1e-4,"mu_tr",0,"order",2001,"sps",1,"decide",0);
output = struct();
vnle_pf_package = {};
vnle_dfe_package = {};
dbtgt_package = {};
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Tx_bits = load([basePath, char(dataTable.tx_bits_path)]);
Tx_bits = Tx_bits.Bits;
Symbols_mapped = PAMmapper(M,0).map(Tx_bits);
Symbols_mapped.fs = dataTable.symbolrate;
Symbols = load([basePath, char(dataTable.tx_symbols_path)]);
Symbols = Symbols.Symbols;
Scpe_load = load([basePath, char(dataTable.rx_sync_path)]);
Scpe_cell = Scpe_load.S;
[~,~,found]=Scpe_cell{2}.tsynch("reference",Symbols,"fs_ref",dataTable.symbolrate,"debug_plots",0);
if ~found
Raw_signal = load([basePath, char(dataTable.rx_raw_path(1))]);
Raw_signal = Raw_signal.Scpe_sig_raw;
[~,Scpe_cell,found] =Raw_signal.tsynch("reference",Symbols,"fs_ref",dataTable.symbolrate,"debug_plots",0);
end
if ~found
if length(Symbols_mapped.signal) == sum(Symbols_mapped.signal == Symbols.signal)
warning('Could not synchronize the received signal with the stored symbols!')
else
[~,Scpe_cell,found] =Raw_signal.tsynch("reference",Symbols_mapped,"fs_ref",dataTable.symbolrate,"debug_plots",0);
end
if ~found
warning('Could not synchronize the received signal with the stored symbols!')
end
end
proc_occ = min(options.max_occurences,length(Scpe_cell));
for occ = 1:proc_occ
Scpe_sig = Scpe_cell{occ};
%%%%%% Sample to 2x fsym %%%%%%
Scpe_sig = Scpe_sig.resample("fs_out",2*fsym);
%%%%%% Sync Rx signal with reference %%%%%%
[Scpe_sig,~] = Scpe_sig.tsynch("reference",Symbols,"fs_ref",fsym,"debug_plots",0);
Scpe_sig = Filter('filtdegree',4,"f_cutoff",Symbols.fs.*0.5,"fs",Scpe_sig.fs,"filterType",filtertypes.gaussian,"active",true).process(Scpe_sig);
Scpe_sig = Scpe_sig - mean(Scpe_sig.signal);
% Scpe_sig.plot("displayname",'Scope Signal','fignum',11);
% Scpe_sig.spectrum("displayname",'Raw Signal','fignum',20);
if duob_mode ~= db_mode.db_encoded
% %%%%% VNLE + DFE %%%%
if 0
eq_vnle_dfe = EQ("Ne",vnle_order,"Nb",[0,0,0],"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.001,"FFEmu",0,"plotfinal",0,"ideal_dfe",0);
eq_post = FFE("epochs_tr",5,"epochs_dd",5,"len_tr",4096*2,"mu_dd",1e-4,"mu_tr",0,"order",2001,"sps",1,"decide",0);
[result] = vnle(eq_vnle_dfe,M,Scpe_sig,Symbols,Tx_bits,"precode_mode",duob_mode,"showAnalysis",1,"postFFE",[]);
vnle_dfe_package{occ} = result;
end
%%%%% VNLE + PF + MLSE %%%%
if 1
[result] = vnle_postfilter_mlse(eq_,pf_,mlse_,M,Scpe_sig,Symbols,Tx_bits,"precode_mode",duob_mode,'showAnalysis',0,"postFFE",[],"eth_style_symbol_mapping",0);
vnle_pf_package{occ} = result;
if options.append_to_db
database.addProcessingResult(run_id,result.resultsMLSE, result.equalizerConfigMLSE);
database.addProcessingResult(run_id,result.resultsVNLE, result.equalizerConfigVNLE);
end
end
%%%%% Duobinary Targeting %%%%
if 1
[result] = duobinary_target(eq_, mlse_db_, M, Scpe_sig, Symbols, Tx_bits, "precode_mode", duob_mode,'showAnalysis',0,"postFFE",[]);
dbtgt_package{occ} = result;
if options.append_to_db
database.addProcessingResult(run_id, result.resultsDBtgt, result.equalizerConfigDBtgt);
end
end
fprintf("BER VNLE: %.2e | %.2e; BER MLSE: %.2e | %.2e; BER DB tgt: %.2e | %.2e \n",vnle_pf_package{occ}.resultsVNLE.BER,vnle_pf_package{occ}.resultsVNLE.BER_precoded ,vnle_pf_package{occ}.resultsMLSE.BER,vnle_pf_package{occ}.resultsMLSE.BER_precoded,dbtgt_package{occ}.resultsDBtgt.BER,dbtgt_package{occ}.resultsDBtgt.BER_precoded)
% fprintf("BER VNLE: %.2e | %.2e; BER MLSE: %.2e | %.2e \n",vnle_pf_package{occ}.resultsVNLE.BER,vnle_pf_package{occ}.resultsVNLE.BER_precoded ,vnle_pf_package{occ}.resultsMLSE.BER,vnle_pf_package{occ}.resultsMLSE.BER_precoded);
else
%%%%%% %db signaling => db encoded %%%%%
if 1
mlse_db_enc = MLSE_viterbi("DIR",[1,1],"duobinary_output",0,"M",M,"trellis_states",PAMmapper(M,0).levels);
eq_db_enc = EQ("Ne",vnle_order,"Nb",dfe_order,"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
[result] = duobinary_signaling(eq_db_enc, mlse_db_enc,M, Scpe_sig ,Symbols, Tx_bits);
dbenc_package{occ} = result;
if options.append_to_db
database.addProcessingResult(run_id, result.resultsDBsignaling, result.equalizerConfigDBsignaling);
end
end
fprintf("BER DB: %.2e \n",dbenc_package{occ}.resultsDBsignaling.BER);
end
% autoArrangeFigures;
disp('- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ')
fprintf('\n')
end
output.dataTable = dataTable;
output.vnle_dfe_package = vnle_dfe_package;
output.vnle_pf_package = vnle_pf_package;
output.dbtgt_package = dbtgt_package;
end

View File

@@ -0,0 +1,151 @@
basePath = 'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\';
database = DBHandler("pathToDB",[basePath,'silas_labor_plain.db'],"type",'sqlite');
filterParams = database.tables;
filterParams.Configurations = struct( ...
'bitrate', [], ... %[224,336,360,390,420,448]
'db_mode', [], ...
'fiber_length', 1, ...
'interference_attenuation', [], ...
'interference_path_length', [], ...
'is_mpi', 0, ...
'pam_level', 4, ...
'rop_attenuation', 0, ...
'wavelength', 1310 ...
);
% filterParams.EqualizerParameters.diff_precode = int32(db_mode.no_db);
% filterParams.EqualizerParameters.equalizer_structure = int32(equalizer_structure.vnle);
% filterParams.EqualizerParameters.DCmu = 0.005;
selectedFields = {'Configurations.run_id' 'Runs.rx_raw_path' 'Configurations.bitrate' 'Configurations.symbolrate' 'Configurations.pam_level' 'Configurations.db_mode' 'Configurations.rop_attenuation' 'Configurations.is_mpi' 'Configurations.interference_attenuation' 'EqualizerParameters.equalizer_structure' 'EqualizerParameters.diff_precode' 'EqualizerParameters.eq_id' 'Measurements.power_pd_in' 'Measurements.power_mpi_interference' 'Measurements.power_mpi_signal' 'Results.BER' 'Results.SNR' 'Results.GMI' 'Results.Alpha'};
% selectedFields = {'Configurations.run_id'};
[dataTable,sql_query] = database.queryDB(filterParams, selectedFields);
fixedVars = {'run_id','eq_id','bitrate'};
dataTableGrpd = groupIt(fixedVars,dataTable);
% Create a new figure
figure(3);
hold on
unique_rates = unique(dataTable.bitrate);
cols = linspecer(8);
for i = 1:numel(unique_rates)
% Plot BER vs. interference_attenuation
% plot(dataTableGrpd.power_mpi_signal(dataTableGrpd.bitrate==unique_rates(i),:)-dataTableGrpd.power_mpi_interference(dataTableGrpd.bitrate==unique_rates(i),:), dataTableGrpd.BER(dataTableGrpd.bitrate==unique_rates(i),:), '-', 'LineWidth', 0.5,'Color',cols(i,:));
if filterParams.Configurations.is_mpi
sir = dataTable.power_mpi_signal(dataTable.bitrate==unique_rates(i),:)-dataTable.power_mpi_interference(dataTable.bitrate==unique_rates(i),:);
ber = dataTable.BER(dataTable.bitrate==unique_rates(i),:);
sc=scatter(dataTable.power_mpi_signal(dataTable.bitrate==unique_rates(i),:)-dataTable.power_mpi_interference(dataTable.bitrate==unique_rates(i),:), dataTable.BER(dataTable.bitrate==unique_rates(i),:), 'LineWidth', 0.5,'Marker','.','MarkerEdgeColor',cols(i+1,:));
pair_one = {'Run ID', dataTable.run_id(dataTable.bitrate==unique_rates(i),:)};
pair_two = {'Rate', dataTable.bitrate(dataTable.bitrate==unique_rates(i),:)};
addDatatips(sc, pair_one, pair_two);
else
sc=scatter(62*ones(size( dataTableGrpd.BER(dataTableGrpd.bitrate==unique_rates(i),:))), dataTableGrpd.BER(dataTableGrpd.bitrate==unique_rates(i),:), 'LineWidth', 0.5,'Marker','o','MarkerEdgeColor',cols(i,:),'MarkerFaceColor',cols(i,:));
pair_one = {'Run ID', dataTableGrpd.run_id(dataTableGrpd.bitrate==unique_rates(i),:)};
pair_two = {'Rate', dataTableGrpd.bitrate(dataTableGrpd.bitrate==unique_rates(i),:)};
addDatatips(sc, pair_one, pair_two);
end
end
% Label the axes and add a title
xlabel('SIR in dB');
ylabel('BER');
title('BER vs. Signal to Interference Ratio');
yline(3.8e-3,'LineWidth',1,'LineStyle','--','HandleVisibility','off');
% Enable grid for better readability
grid on;
beautifyBERplot;
ylim([1e-4 0.5]);
function resultTable = groupIt(fixedVars,dataTable)
% Group by run_id and eq_id (adjust grouping keys as needed)
[G, groupKeys] = findgroups(dataTable(:, fixedVars));
% Preallocate a cell array for aggregated data.
varNames = dataTable.Properties.VariableNames;
nVars = numel(varNames);
aggData = cell(height(groupKeys), nVars);
groupCount = zeros(height(groupKeys), 1); % To store the size of each group
% Loop over each group.
for i = 1:height(groupKeys)
idx = (G == i); % Logical index for group i
groupCount(i) = sum(idx); % Count number of rows in this group
% For each variable in the table:
for j = 1:nVars
colData = dataTable.(varNames{j});
if isnumeric(colData)
% For numeric data, compute the mean.
aggData{i, j} = min(colData(idx));
else
% For non-numeric data, take the first entry.
if iscell(colData)
aggData{i, j} = colData{find(idx, 1)};
else
aggData{i, j} = colData(find(idx, 1));
end
end
end
end
% Convert the aggregated cell array into a table.
resultTable = cell2table(aggData, 'VariableNames', varNames);
% Append the group count as a new column.
resultTable.nRows = groupCount;
end
function addDatatips(sc, varargin)
% addDatatips Adds custom data tip rows to a scatter plot.
%
% addDatatips(sc, pair1, pair2, ...) adds one or more custom rows to the
% data tip display of the scatter plot identified by sc.
%
% Each pair should be provided as a 1x2 cell array: {label, value}.
% The value can be a scalar or a vector. If a vector is provided, its length
% must match the number of scatter plot points.
%
% Example:
% sc = scatter(x, y, 'LineWidth', 1.5, 'Marker', 'o');
% pair_one = {'Attenuation', attenuationVector};
% addDatatips(sc, pair_one);
numPoints = numel(sc.XData);
for k = 1:length(varargin)
pair = varargin{k};
if ~iscell(pair) || numel(pair) ~= 2
error('Each pair must be a 1x2 cell array: {label, value}.');
end
label = pair{1};
value = pair{2};
% If value is a vector, ensure its length is either 1 or equal to the number of scatter points.
if isvector(value) && numel(value) ~= 1 && numel(value) ~= numPoints
error('The vector for "%s" must be a scalar or have %d elements matching the scatter data points.', label, numPoints);
end
% Create a new data tip row using the provided label and vector.
newRow = dataTipTextRow(label, value);
sc.DataTipTemplate.DataTipRows(end+1) = newRow;
end
end

View File

@@ -0,0 +1,68 @@
% basePath = 'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\';
% db = DBHandler("pathToDB",[basePath,'silas_labor.db']);
if 0
uloops = struct;
uloops.precomp = [0];
uloops.db_precode = [0];
uloops.bitrate = [330,390,450].*1e9; %[300,330,360,390,420,450,480]
uloops.laser_wavelength = [1310];
uloops.M = [4];
uloops.link_length = [2]; % 1,2,3,5,6,8,10
%uloops.alpha = [0:0.1:1];
wh = DataStorage(uloops);
wh.addStorage("ber");
wh = submit_simulations(wh,"parallel",1,"simulation_mode",0);
end
col = cbrewer2('spectral',6);%
col=linspecer(5);
cnt = 1;
for br = uloops.bitrate
a = wh_burg.getStoValue('ber',uloops.precomp, uloops.db_precode, br , uloops.laser_wavelength, uloops.M, uloops.link_length);
ber_mlse = cellfun(@(x) x.vnle_pf_package{1,1}.ber_mlse, a);
alpha = cellfun(@(x) x.vnle_pf_package{1,1}.pf.coefficients, a,'UniformOutput', false);
figure(23)
hold on
scatter(alpha{1}(2),ber_mlse,100,'MarkerEdgeColor',col(cnt,:),'Marker','x','LineWidth',2,'HandleVisibility','off');
cnt = cnt+1;
end
cnt = 1;
alpha = [];
for br = uloops.bitrate
a = wh_alphas.getStoValue('ber',uloops.precomp, uloops.db_precode, br , uloops.laser_wavelength, uloops.M, uloops.link_length, [0:0.1:1]);
ber_mlse = cellfun(@(x) x.vnle_pf_package{1,1}.ber_mlse, a);
x_ax = [0:0.1:1];
figure(23)
hold on
% title(sprintf('%d km | %d nm | PAM %d',uloops.link_length,wavelength,uloops.M));
plot(x_ax,ber_mlse,'DisplayName',sprintf(' %d GBps PAM 4',br.*1e-9),'LineStyle','-','HandleVisibility','on','Color',col(cnt,:));
xticks(x_ax);
set(gca, 'YScale', 'log');
ylim([1e-5 0.4]);
xlim([min(x_ax), max(x_ax) ]);
yline([3.8e-3, 2e-2],'HandleVisibility','off');
legend
beautifyBERplot();
xlabel('Channel $\alpha$');
ylabel('BER');
cnt = cnt+1;
end

View File

@@ -0,0 +1,57 @@
% basePath = 'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\';
% db = DBHandler("pathToDB",[basePath,'silas_labor.db']);
if 0
uloops = struct;
uloops.precomp = [0];
uloops.db_precode = [0];
uloops.bitrate = [390].*1e9; %[300,330,360,390,420,450,480]
uloops.laser_wavelength = [1310];
uloops.M = [4];
uloops.link_length = [2]; % 1,2,3,5,6,8,10
uloops.vnle_order1 = [5,10:10:100];
uloops.vnle_order2 = [0];
uloops.vnle_order3 = [0];
wh = DataStorage(uloops);
wh.addStorage("ber");
wh = submit_simulations(wh,"parallel",1,"simulation_mode",0);
end
col = cbrewer2('spectral',6);%
col=linspecer(5);
cnt = 1;
for n3 = uloops.vnle_order3
a = wh.getStoValue('ber',uloops.precomp, uloops.db_precode, uloops.bitrate , uloops.laser_wavelength, uloops.M, uloops.link_length,...
uloops.vnle_order1,...
uloops.vnle_order2,...
n3);
ber_vnle = cellfun(@(x) x.vnle_pf_package{1,1}.ber_vnle, a);
ber_mlse = cellfun(@(x) x.vnle_pf_package{1,1}.ber_mlse, a);
ber_db = cellfun(@(x) x.dbtgt_package{1,1}.ber, a);
log_bers = log10(ber_vnle + 1e-12);
figure(20)
hold on
title(sprintf('%d km | %d nm | PAM %d',uloops.link_length,wavelength,uloops.M));
% plot(uloops.vnle_order1,ber_vnle,'DisplayName',sprintf('Tx precomp. + VNLE'),'LineStyle','-','HandleVisibility','on','Color',col(cnt,:));
plot(uloops.vnle_order1,ber_mlse,'DisplayName',sprintf('VNLE + Postfilter + ;MLSE'),'LineStyle','-','HandleVisibility','on','Color',col(cnt,:));
plot(uloops.vnle_order1,ber_db,'DisplayName',sprintf('DB tgt. VNLE + MLSE'),'LineStyle','-','HandleVisibility','on','Color',col(cnt+2,:));
xticks(uloops.vnle_order1([1:1:end]));
set(gca, 'YScale', 'log');
ylim([5e-5 0.4]);
xlim([min(uloops.vnle_order1), max(uloops.vnle_order1) ]);
yline([3.8e-3, 2e-2],'HandleVisibility','off');
legend
beautifyBERplot();
xlabel('Number of 1st order coeff.');
ylabel('BER');
cnt = cnt+1;
end

View File

@@ -0,0 +1,50 @@
if 0
uloops = struct;
uloops.precomp = [0];
uloops.db_precode = [0,1];
uloops.bitrate = [420].*1e9; %[300,330,360,390,420,450,480]
% uloops.laser_wavelength = [1293,1297.5,1302,1306.5,1310,1313.4,1318,1322.7,1327.4];
uloops.laser_wavelength = [1293, 1302,1310,1318,1327.4];
uloops.M = [4,6,8];
uloops.link_length = [5]; % 1,2,3,5,6,8,10
wh = DataStorage(uloops);
wh.addStorage("ber");
wh = submit_simulations(wh,"parallel",1,"simulation_mode",0);
end
col = cbrewer2('Set2',6);%
col=linspecer(5);
cnt = 1;
m = 8;
% a = wh.getStoValue('ber',1, 0, uloops.bitrate , uloops.laser_wavelength, m, uloops.link_length);
% ber_vnle = cellfun(@(x) x.vnle_pf_package{1,1}.ber_vnle, a);
a = wh.getStoValue('ber',0, 0, uloops.bitrate , uloops.laser_wavelength, m, uloops.link_length);
ber_mlse = cellfun(@(x) x.vnle_pf_package{1,1}.ber_mlse, a);
a = wh.getStoValue('ber',0, 1, uloops.bitrate , uloops.laser_wavelength, m, uloops.link_length);
ber_db = cellfun(@(x) x.dbtgt_package{1,1}.ber, a);
x_ax = uloops.laser_wavelength;
figure(21)
hold on
% title(sprintf('%d km | %d GBd | PAM %d',uloops.link_length,uloops.bitrate/log2(m).*1e-9,m));
% plot(x_ax,ber_vnle,'DisplayName',sprintf('Tx precomp. + VNLE'),'LineStyle','-','HandleVisibility','on','Color',col(cnt+1,:));
plot(x_ax,ber_mlse,'DisplayName',sprintf('VNLE + Postfilter + MLSE'),'LineStyle','-','HandleVisibility','on','Color',colorsets.DeepRed.RGB);
% plot(x_ax,ber_db,'DisplayName',sprintf('DB tgt. VNLE + MLSE'),'LineStyle','-','HandleVisibility','on','Color',col(cnt,:));
xticks(x_ax([1:1:end]));
set(gca, 'YScale', 'log');
ylim([5e-5 0.4]);
xlim([min(x_ax)-3, max(x_ax)+3 ]);
yline([3.8e-3, 2e-2],'HandleVisibility','off');
legend
beautifyBERplot();
xlabel('Number of 1st order coeff.');
ylabel('BER');
cnt = cnt+1;

View File

@@ -0,0 +1,70 @@
% basePath = 'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\';
% db = DBHandler("pathToDB",[basePath,'silas_labor.db']);
if 0
uloops = struct;
uloops.precomp = [0];
uloops.db_precode = [0];
uloops.bitrate = [300,330,360,390,420,450,480].*1e9; %[300,330,360,390,420,450,480]
uloops.laser_wavelength = [1310];
uloops.M = [4];
uloops.link_length = [2]; % 1,2,3,5,6,8,10
uloops.vnle_order1 = [50];
uloops.vnle_order2 = [7];
uloops.vnle_order3 = [7];
uloops.pf_ncoeffs = [1,2,3];
wh = DataStorage(uloops);
wh.addStorage("ber");
wh = submit_simulations(wh,"parallel",1,"simulation_mode",0);
end
col = cbrewer2('spectral',6);%
col=linspecer(5);
cnt = 1;
alpha = [];
for n = uloops.pf_ncoeffs
a = wh.getStoValue('ber',uloops.precomp, uloops.db_precode, uloops.bitrate , uloops.laser_wavelength, uloops.M, uloops.link_length,...
uloops.vnle_order1,...
uloops.vnle_order2,...
uloops.vnle_order3,...
n);
ber_vnle = cellfun(@(x) x.vnle_pf_package{1,1}.ber_vnle, a);
ber_mlse = cellfun(@(x) x.vnle_pf_package{1,1}.ber_mlse, a);
% PF = cellfun(@(x) x.vnle_pf_package{1,1}.pf.coefficients, a,'UniformOutput',false);
%
% showTransferFunction(PF{3}.coefficients,"fignum",12,"color",clr.Set1.red,"DisplayName",['360 GBd']);
%
% showTransferFunction(PF{4}.coefficients,"fignum",12,"color",clr.Set1.blue,"DisplayName",['390 GBd']);
%
% showTransferFunction(PF{5}.coefficients,"fignum",12,'color',clr.Set1.green,"DisplayName",['420 GBd']);
% ber_db = cellfun(@(x) x.dbtgt_package{1,1}.ber, a);
x_ax = uloops.bitrate.*1e-9;
figure(23)
hold on
title(sprintf('%d km | %d nm | PAM %d',uloops.link_length,wavelength,uloops.M));
if n==1
plot(x_ax,ber_vnle,'DisplayName',sprintf('Tx precomp. + VNLE'),'LineStyle','-','HandleVisibility','on','Color',col(cnt+4,:));
end
plot(x_ax,ber_mlse,'DisplayName',sprintf('VNLE + Postfilter + ;MLSE'),'LineStyle','-','HandleVisibility','on','Color',col(cnt,:));
% plot(x_ax,ber_db,'DisplayName',sprintf('DB tgt. VNLE + MLSE'),'LineStyle','-','HandleVisibility','on','Color',col(cnt+2,:));
xticks(x_ax([1:1:end]));
set(gca, 'YScale', 'log');
ylim([1e-5 0.4]);
xlim([min(x_ax(2:end)), max(x_ax) ]);
yline([3.8e-3, 2e-2],'HandleVisibility','off');
legend
beautifyBERplot();
xlabel('Gross Bitrate in Gbps');
ylabel('BER');
cnt = cnt+1;
end

View File

@@ -0,0 +1,150 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 1365 313" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;">
<g transform="matrix(1,0,0,1,-350.052,-234.682)">
<g id="g40994" transform="matrix(3.14734,0,0,3.14734,-400.995,-235.585)">
<path id="rect40684" d="M277.516,207.069C277.516,206.587 277.125,206.197 276.643,206.197L240.002,206.197C239.52,206.197 239.129,206.587 239.129,207.069L239.129,243.711C239.129,244.192 239.52,244.583 240.002,244.583L276.643,244.583C277.125,244.583 277.516,244.192 277.516,243.711L277.516,207.069Z" style="fill:none;stroke:black;stroke-width:1px;"/>
<g id="g40700" transform="matrix(1,0,0,1,53.6992,6.29287)">
<path id="path40686" d="M211.915,223.139L198.35,223.139L201.742,217.266L205.133,211.392L208.524,217.266L211.915,223.139Z" style="fill:none;fill-rule:nonzero;stroke:black;stroke-width:1px;"/>
<path id="path40688" d="M205.133,223.139L205.133,230.555" style="fill:none;fill-rule:nonzero;stroke:black;stroke-width:1px;"/>
<path id="path40690" d="M205.133,211.392L205.133,205.096" style="fill:none;fill-rule:nonzero;stroke:black;stroke-width:1px;"/>
<path id="path40694" d="M198.143,211.392L212.123,211.392" style="fill:none;fill-rule:nonzero;stroke:black;stroke-width:1px;"/>
</g>
<g id="path40702" transform="matrix(0.317729,-0,-0,0.317729,238.629,149.417)">
<path d="M82.941,200.888L86.409,190.917L76.351,194.125C79.689,194.169 82.984,197.55 82.941,200.888Z" style="fill:rgb(255,0,0);fill-rule:nonzero;"/>
<path d="M80.998,196.189C77.477,199.62 73.535,203.461 73.535,203.461" style="fill:none;fill-rule:nonzero;stroke:rgb(255,0,0);stroke-width:3.15px;"/>
</g>
<g id="path40702-1" transform="matrix(0.317729,-0,-0,0.317729,238.629,149.417)">
<path d="M102.022,200.888L105.49,190.917L95.433,194.125C98.771,194.169 102.066,197.55 102.022,200.888Z" style="fill:rgb(255,0,0);fill-rule:nonzero;"/>
<path d="M100.08,196.189C96.559,199.62 92.617,203.461 92.617,203.461" style="fill:none;fill-rule:nonzero;stroke:rgb(255,0,0);stroke-width:3.15px;"/>
</g>
</g>
<g id="g40994-4" transform="matrix(3.07687,0,0,3.07687,-308.034,-474.106)">
<g id="g41806">
<path id="path41709" d="M272.852,307.633L280.529,307.633L288.207,302.14L295.884,302.141L303.561,307.633L311.239,307.633" style="fill:none;fill-rule:nonzero;stroke:rgb(2,0,0);stroke-width:1px;"/>
<path id="path41709-4" d="M272.852,307.633L280.529,307.633L288.207,313.126L295.884,313.126L303.561,307.633L311.239,307.633" style="fill:none;fill-rule:nonzero;stroke:rgb(2,0,0);stroke-width:1px;"/>
</g>
<path id="rect40684-3" d="M311.239,289.332C311.239,288.84 310.839,288.44 310.346,288.44L273.745,288.44C273.252,288.44 272.852,288.84 272.852,289.332L272.852,325.934C272.852,326.427 273.252,326.827 273.745,326.827L310.346,326.827C310.839,326.827 311.239,326.427 311.239,325.934L311.239,289.332Z" style="fill:none;stroke:rgb(2,0,0);stroke-width:1px;"/>
</g>
<g transform="matrix(1,0,0,1,462.763,-27.6418)">
<g id="g42228" transform="matrix(3.07687,0,0,3.07687,-770.796,-623.629)">
<path id="rect40684-3-5" d="M311.239,289.332C311.239,288.84 310.839,288.44 310.346,288.44L273.745,288.44C273.252,288.44 272.852,288.84 272.852,289.332L272.852,325.934C272.852,326.427 273.252,326.827 273.745,326.827L310.346,326.827C310.839,326.827 311.239,326.427 311.239,325.934L311.239,289.332Z" style="fill:none;stroke:rgb(2,0,0);stroke-width:1px;"/>
</g>
<g transform="matrix(0.916758,0,0,0.916758,-209.942,-134.558)">
<g transform="matrix(36.36,0,0,36.36,410.943,511.232)">
</g>
<text x="325.44px" y="511.232px" style="font-family:'ArialMT', 'Arial';font-size:36.36px;">A<tspan x="348.342px 382.661px " y="511.232px 511.232px ">WG</tspan></text>
</g>
</g>
<g id="use14586" transform="matrix(4.16667,0,0,4.16667,538.992,319.037)">
<g id="path38721" transform="matrix(1.27892,-0.000404508,-0.000404508,1,-27.2331,0.0394952)">
<path d="M71.975,37.134L122.852,37.061" style="fill:none;fill-rule:nonzero;stroke:rgb(255,0,0);stroke-width:0.73px;"/>
</g>
<circle id="circle38723" cx="90.574" cy="26.615" r="10.503" style="fill:none;stroke:rgb(255,0,0);stroke-width:0.73px;"/>
<circle id="circle38725" cx="96.619" cy="26.638" r="10.503" style="fill:none;stroke:rgb(255,0,0);stroke-width:0.73px;"/>
<circle id="circle38727" cx="102.664" cy="26.594" r="10.503" style="fill:none;stroke:rgb(255,0,0);stroke-width:0.73px;"/>
</g>
<g transform="matrix(1,0,0,1,-180.978,231.592)">
<g transform="matrix(1.12196,0,0,1.12196,-146.494,-56.6939)">
<circle cx="974.409" cy="265.748" r="29.528" style="fill:white;stroke:rgb(255,0,0);stroke-width:2.67px;stroke-miterlimit:1.5;"/>
</g>
<g transform="matrix(1.16567,-0.0445706,-0.0445706,1.1674,-141.533,6.43198)">
<g transform="matrix(0.859131,0.032801,0.032801,0.857855,577.71,19.194)">
<path d="M441.614,202.956L452.737,201.256L451.254,212.411L441.614,202.956Z" style="fill:rgb(255,0,0);"/>
<path d="M382.592,272.779C382.592,272.779 431.613,222.795 447.694,206.398" style="fill:none;stroke:rgb(255,0,0);stroke-width:3px;stroke-miterlimit:1.5;"/>
</g>
</g>
<g transform="matrix(1,0,0,1,-20.5026,130.73)">
<text x="933.238px" y="184.877px" style="font-family:'ArialMT', 'Arial';font-size:33.333px;">P</text>
<g transform="matrix(20.8333,0,0,20.8333,1016.86,184.877)">
</g>
<text x="955.471px" y="184.877px" style="font-family:'ArialMT', 'Arial';font-size:20.833px;">launch</text>
</g>
</g>
<g transform="matrix(1,0,0,1,350.518,231.592)">
<g transform="matrix(1.12196,0,0,1.12196,-146.494,-56.6939)">
<circle cx="974.409" cy="265.748" r="29.528" style="fill:white;stroke:rgb(255,0,0);stroke-width:2.67px;stroke-miterlimit:1.5;"/>
</g>
<g transform="matrix(1.16567,-0.0445706,-0.0445706,1.1674,-141.533,6.43198)">
<g transform="matrix(0.859131,0.032801,0.032801,0.857855,121.085,1.76038)">
<path d="M973.11,202.956L984.233,201.256L982.75,212.411L973.11,202.956Z" style="fill:rgb(255,0,0);"/>
<path d="M914.089,272.779C914.089,272.779 963.109,222.795 979.19,206.398" style="fill:none;stroke:rgb(255,0,0);stroke-width:3px;stroke-miterlimit:1.5;"/>
</g>
</g>
<g transform="matrix(1,0,0,1,-20.5026,130.73)">
<text x="937.937px" y="184.877px" style="font-family:'ArialMT', 'Arial';font-size:33.333px;">PD</text>
<g transform="matrix(20.8333,0,0,20.8333,1000.46,184.877)">
</g>
<text x="984.242px" y="184.877px" style="font-family:'ArialMT', 'Arial';font-size:20.833px;">in</text>
</g>
</g>
<g transform="matrix(1.04523e-16,1.70851,-1.55299,9.48961e-17,2134.48,-837.195)">
<path d="M767.327,630.707L794.304,673.144L740.349,673.144L767.327,630.707Z" style="fill:none;stroke:rgb(255,20,3);stroke-width:1.84px;stroke-miterlimit:1.5;"/>
</g>
<g id="g409941" serif:id="g40994" transform="matrix(3.07687,0,0,3.07687,681.554,-221.053)">
<path id="rect406841" serif:id="rect40684" d="M277.516,207.089C277.516,206.596 277.116,206.197 276.623,206.197L240.022,206.197C239.529,206.197 239.129,206.596 239.129,207.089L239.129,243.691C239.129,244.183 239.529,244.583 240.022,244.583L276.623,244.583C277.116,244.583 277.516,244.183 277.516,243.691L277.516,207.089Z" style="fill:none;stroke:black;stroke-width:1px;"/>
<g id="g407001" serif:id="g40700" transform="matrix(1,0,0,1,53.6992,6.29287)">
<path id="path406861" serif:id="path40686" d="M211.915,223.139L198.35,223.139L201.742,217.266L205.133,211.392L208.524,217.266L211.915,223.139Z" style="fill:none;fill-rule:nonzero;stroke:black;stroke-width:1px;"/>
<path id="path406881" serif:id="path40688" d="M205.133,223.139L205.133,230.555" style="fill:none;fill-rule:nonzero;stroke:black;stroke-width:1px;"/>
<path id="path406901" serif:id="path40690" d="M205.133,211.392L205.133,205.096" style="fill:none;fill-rule:nonzero;stroke:black;stroke-width:1px;"/>
<path id="path406941" serif:id="path40694" d="M198.143,211.392L212.123,211.392" style="fill:none;fill-rule:nonzero;stroke:black;stroke-width:1px;"/>
</g>
<g id="path407021" serif:id="path40702" transform="matrix(0.325006,-0,-0,0.325006,-107.74,148.117)">
<path d="M1147.45,199.771L1137.62,202.907L1141.01,193.159C1140.97,196.423 1144.19,199.728 1147.45,199.771Z" style="fill:rgb(255,0,0);fill-rule:nonzero;"/>
<path d="M1150.21,190.644C1150.21,190.644 1146.35,194.399 1142.91,197.753" style="fill:none;fill-rule:nonzero;stroke:rgb(255,0,0);stroke-width:3.08px;"/>
</g>
<g id="path40702-11" serif:id="path40702-1" transform="matrix(0.325006,-0,-0,0.325006,-107.74,148.117)">
<path d="M1166.11,199.771L1156.28,202.907L1159.67,193.159C1159.62,196.423 1162.84,199.728 1166.11,199.771Z" style="fill:rgb(255,0,0);fill-rule:nonzero;"/>
<path d="M1168.86,190.644C1168.86,190.644 1165.01,194.399 1161.56,197.753" style="fill:none;fill-rule:nonzero;stroke:rgb(255,0,0);stroke-width:3.08px;"/>
</g>
</g>
<g transform="matrix(1,0,0,1,1525.75,150.876)">
<g id="g422281" serif:id="g42228" transform="matrix(3.07687,0,0,3.07687,-770.796,-623.629)">
<path id="rect40684-3-51" serif:id="rect40684-3-5" d="M311.239,289.332C311.239,288.84 310.839,288.44 310.346,288.44L273.745,288.44C273.252,288.44 272.852,288.84 272.852,289.332L272.852,325.934C272.852,326.427 273.252,326.827 273.745,326.827L310.346,326.827C310.839,326.827 311.239,326.427 311.239,325.934L311.239,289.332Z" style="fill:none;stroke:rgb(2,0,0);stroke-width:1px;"/>
</g>
<g transform="matrix(0.916758,0,0,0.916758,-209.942,-134.558)">
<g transform="matrix(36.36,0,0,36.36,405.909,511.232)">
</g>
<text x="330.473px" y="511.232px" style="font-family:'ArialMT', 'Arial';font-size:36.36px;">R<tspan x="356.074px " y="511.232px ">T</tspan>O</text>
</g>
</g>
<g transform="matrix(1.26861,0.00113446,0.00113446,1,277.224,235.237)">
<g transform="matrix(0.788264,-0.000894252,-0.000894252,0.999996,57.4082,-0.620229)">
<path d="M368.303,230.541L376.948,237.082L368.248,243.55L368.303,230.541Z" style="fill:rgb(255,0,0);"/>
<path d="M304.499,236.776C304.499,236.776 351.883,236.976 370.01,237.053" style="fill:none;stroke:rgb(255,0,0);stroke-width:2.89px;stroke-miterlimit:1.5;"/>
</g>
</g>
<g transform="matrix(0.934186,-0.000277962,-0.000277962,0.999999,198.405,236.65)">
<g transform="matrix(1.07045,0.000297545,0.000297545,1,162.33,-1.92253)">
<path d="M170.653,231.452L179.298,237.993L170.598,244.461L170.653,231.452Z" style="fill:rgb(255,0,0);"/>
<path d="M125.948,237.768C125.948,237.768 157.916,237.903 172.36,237.964" style="fill:none;stroke:rgb(255,0,0);stroke-width:2.89px;stroke-miterlimit:1.5;"/>
</g>
</g>
<g transform="matrix(1.73353,0.00309801,0.00309801,1.00001,639.025,236.856)">
<g transform="matrix(0.57686,-0.0017871,-0.0017871,0.999992,-166.693,-1.6572)">
<path d="M895.303,232.857L903.948,239.399L895.248,245.866L895.303,232.857Z" style="fill:rgb(255,0,0);"/>
<path d="M804.948,238.98C804.948,238.98 874.5,239.274 897.01,239.369" style="fill:none;stroke:rgb(255,0,0);stroke-width:2.89px;stroke-miterlimit:1.5;"/>
</g>
</g>
<g transform="matrix(1.45403,0.00191757,0.00191757,1.00001,901.662,237.501)">
<g transform="matrix(0.687744,-0.00131879,-0.00131879,0.999994,-379.363,-2.09148)">
<path d="M1058.63,233.083L1067.27,239.624L1058.57,246.092L1058.63,233.083Z" style="fill:rgb(255,0,0);"/>
<path d="M984.233,239.274C984.233,239.274 1040.38,239.511 1060.33,239.595" style="fill:none;stroke:rgb(255,0,0);stroke-width:2.89px;stroke-miterlimit:1.5;"/>
</g>
</g>
<g transform="matrix(0.00422338,0.959693,-0.999991,0.00405319,825.177,70.1581)">
<path d="M297.222,235.883L354.331,236.124" style="fill:none;"/>
<g transform="matrix(0.00422338,-0.999991,1.04198,0.00440072,169.424,475.845)">
<path d="M248.693,165.557L240.499,176.482L232.306,165.557L248.693,165.557Z"/>
<path d="M240.499,121.674L240.499,167.742" style="fill:none;stroke:black;stroke-width:3.64px;stroke-miterlimit:1.5;"/>
</g>
</g>
<g transform="matrix(0.959693,-0.00422338,0.00405319,0.999991,1250.8,239.181)">
<path d="M297.222,235.883L354.331,236.124" style="fill:none;"/>
<g transform="matrix(1.04198,0.00440072,-0.00422338,0.999991,-938.545,-8.46312)">
<path d="M1230.83,230.931L1241.76,239.125L1230.83,247.318L1230.83,230.931Z"/>
<path d="M1186.95,239.125L1233.02,239.125" style="fill:none;stroke:black;stroke-width:3.64px;stroke-miterlimit:1.5;"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e8eaed"><path d="M480-120q-151 0-255.5-46.5T120-280v-400q0-66 105.5-113T480-840q149 0 254.5 47T840-680v400q0 67-104.5 113.5T480-120Zm0-479q89 0 179-25.5T760-679q-11-29-100.5-55T480-760q-91 0-178.5 25.5T200-679q14 30 101.5 55T480-599Zm0 199q42 0 81-4t74.5-11.5q35.5-7.5 67-18.5t57.5-25v-120q-26 14-57.5 25t-67 18.5Q600-528 561-524t-81 4q-42 0-82-4t-75.5-11.5Q287-543 256-554t-56-25v120q25 14 56 25t66.5 18.5Q358-408 398-404t82 4Zm0 200q46 0 93.5-7t87.5-18.5q40-11.5 67-26t32-29.5v-98q-26 14-57.5 25t-67 18.5Q600-328 561-324t-81 4q-42 0-82-4t-75.5-11.5Q287-343 256-354t-56-25v99q5 15 31.5 29t66.5 25.5q40 11.5 88 18.5t94 7Z"/></svg>

After

Width:  |  Height:  |  Size: 729 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e8eaed"><path d="m105-399-65-47 200-320 120 140 160-260 120 180 135-214 65 47-198 314-119-179-152 247-121-141-145 233Zm475 159q42 0 71-29t29-71q0-42-29-71t-71-29q-42 0-71 29t-29 71q0 42 29 71t71 29ZM784-80 676-188q-21 14-45.5 21t-50.5 7q-75 0-127.5-52.5T400-340q0-75 52.5-127.5T580-520q75 0 127.5 52.5T760-340q0 26-7 50.5T732-244l108 108-56 56Z"/></svg>

After

Width:  |  Height:  |  Size: 452 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e8eaed"><path d="M440-120v-480H120v-160q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H440Zm80-80h240v-160H520v160Zm0-240h240v-160H520v160ZM200-680h560v-80H200v80ZM120-80v-80h102q-48-23-77.5-68T115-330q0-79 55.5-134.5T305-520v80q-45 0-77.5 32T195-330q0 39 24 69t61 38v-97h80v240H120Z"/></svg>

After

Width:  |  Height:  |  Size: 421 B

View File

@@ -0,0 +1,137 @@
basePath = 'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\';
useGui = 0;
pamlvls = [4, 6, 8];
wlengths = [1310];
db = DBHandler("pathToDB", [basePath, 'silas_labor.db']);
for w = 1:numel(wlengths)
for p = 1:numel(pamlvls)
% Load data from database
joinedData = loadDataFromDB(db, pamlvls(p), wlengths(w), useGui);
% Plot filtered data
figure(pamlvls(p));
hold on;
plotFilteredData(joinedData, wlengths(w));
% Continue with the rest of your plot settings
finalizePlot();
end
end
% Custom function to load data from database
function joinedData = loadDataFromDB(db, pamlvl, wlength, useGui)
if useGui
filterParams = db.promptFilterParameters();
selectedFields = db.promptSelectFields();
else
filterParams = db.tables;
filterParams.Configurations = struct( ...
'bitrate', [], 'db_mode', [], 'fiber_length', 1, ...
'interference_attenuation', [], 'interference_path_length', [], ...
'is_mpi', 0, 'pam_level', pamlvl, 'precomp_amp', [], ...
'rop_attenuation', 0, 'symbolrate', [], 'v_awg', [], 'v_bias', [], ...
'wavelength', wlength ...
);
selectedFields = {'Runs.run_id', 'BERs.ber_id', 'Equalizer.eq_id', 'Equalizer.eq_type', 'BERs.ber', 'BERs.occurrence', ...
'Configurations.db_mode', 'Configurations.pam_level', 'Configurations.bitrate', 'Configurations.symbolrate', ...
'Configurations.fiber_length', 'Configurations.wavelength', 'Configurations.precomp_amp', ...
'Measurements.power_rop', 'Measurements.power_laser', 'Measurements.power_pd_in'};
end
% Get data table from DB
[dataTable, ~] = db.queryDB(filterParams, selectedFields);
% Extract unique rows for each run_id
uniqueConfigFields = {'run_id', 'pam_level', 'bitrate', 'symbolrate', 'fiber_length', 'wavelength', 'precomp_amp', 'db_mode'};
[~, uniqueIdx] = unique(dataTable.run_id);
configDetails = dataTable(uniqueIdx, uniqueConfigFields);
% Calculate the mean BER for each combination of 'run_id' and 'eq_type'
groupedData = groupsummary(dataTable, {'run_id', 'eq_type'}, {'mean', 'min', @(x) meanExcludingOutliers(x)}, {'ber', 'power_rop', 'power_pd_in'});
% Join groupedData with configDetails on the run_id field
joinedData = join(groupedData, configDetails, 'Keys', 'run_id');
end
% Custom function to plot filtered data
function plotFilteredData(joinedData, wlength)
filterFields = {'eq_type'};
cols = linspecer(8);
lst = ["-", ":", "--"];
% Loop over each field you want to filter by
for f = 1:numel(filterFields)
currentField = filterFields{f};
uniqueValues = unique(joinedData.(currentField));
for i = 1:numel(uniqueValues)
currentValue = uniqueValues(i);
% Filter joinedData for the current value
if isnumeric(currentValue)
filteredData = joinedData(joinedData.(currentField) == currentValue, :);
else
filteredData = joinedData(strcmp(joinedData.(currentField), currentValue), :);
end
% Group and average BERs of several run ids => repeated measurements in lab!
groupVars = {'bitrate'};
groupedDataWithMeans = groupsummary(filteredData, groupVars, {'mean', 'min'}, {'mean_ber', 'min_ber', 'fun1_ber', 'mean_power_rop', 'mean_power_pd_in'});
[~, uniqueIdx] = unique(filteredData.bitrate);
constantFields = filteredData(uniqueIdx, {'bitrate', 'GroupCount', 'pam_level', 'symbolrate', 'fiber_length', 'wavelength', 'precomp_amp', 'db_mode'});
groupedRunIDs = varfun(@(x) {unique(x)}, filteredData, 'GroupingVariables', groupVars, 'InputVariables', 'run_id');
groupedRunIDs.Properties.VariableNames(end) = {'GroupedRunIDs'};
groupedDataWithMeans = join(groupedDataWithMeans, constantFields, 'Keys', 'bitrate');
groupedDataWithMeans = join(groupedDataWithMeans, groupedRunIDs, 'Keys', 'bitrate');
filteredData = groupedDataWithMeans;
% Plotting
a = plot(filteredData.bitrate .* 1e-9, filteredData.mean_fun1_ber, ...
'Color', cols(i, :), 'MarkerSize', 4, 'LineWidth', 1, 'LineStyle', lst(mod(wlength - 1, numel(lst)) + 1), ...
'Marker', 'o', 'MarkerFaceColor', 'auto', 'MarkerEdgeColor', cols(i, :), ...
'DisplayName', [char(currentValue), '; ', num2str(wlength), ' nm']);
a.DataTipTemplate.DataTipRows(1).Label = 'Bitrate';
a.DataTipTemplate.DataTipRows(1).Format = ['%.1f', ' Gbit/s'];
a.DataTipTemplate.DataTipRows(2).Label = 'BER';
a.DataTipTemplate.DataTipRows(2).Format = '%.1e';
a.DataTipTemplate.DataTipRows(3).Label = 'P_{out}';
a.DataTipTemplate.DataTipRows(3).Value = filteredData.mean_mean_power_rop;
a.DataTipTemplate.DataTipRows(3).Format = ['%.2f', ' dBm'];
a.DataTipTemplate.DataTipRows(4).Label = 'Baudr';
a.DataTipTemplate.DataTipRows(4).Value = filteredData.bitrate .* 1e-9;
a.DataTipTemplate.DataTipRows(4).Format = ['%.1f', ' GBd'];
a.DataTipTemplate.DataTipRows(5).Label = 'Run ID';
a.DataTipTemplate.DataTipRows(5).Value = filteredData.GroupedRunIDs;
a.DataTipTemplate.FontSize = 9;
a.DataTipTemplate.FontName = 'arial';
end
end
end
% Custom function to finalize the plot settings
function finalizePlot()
yline(2e-2, 'DisplayName', '20% O-FEC', 'LineStyle', '--', 'HandleVisibility', 'off');
yline(3.8e-3, 'DisplayName', 'HD-FEC', 'LineStyle', '--', 'HandleVisibility', 'off');
xlabel('Bit Rate in GBps');
ylabel('Bit Error Rate (BER)');
xlim([300, 480]);
set(gca, 'yscale', 'log');
set(gca, 'Box', 'on');
grid on;
grid minor;
legend('Interpreter', 'none');
end
% Custom function using rmoutliers to calculate mean after removing outliers
function meanWithoutOutliers = meanExcludingOutliers(x)
[xWithoutOutliers,outlierpos] = rmoutliers(x);
if isempty(xWithoutOutliers)
meanWithoutOutliers = NaN;
else
meanWithoutOutliers = mean(xWithoutOutliers);
end
end

View File

@@ -0,0 +1,89 @@
if 0
uloops = struct;
uloops.precomp = [0,1];
uloops.db_precode = [0,1];
uloops.bitrate = [300,330,360,390,420,450,480].*1e9; %[300,330,360,390,420,450,480]
uloops.laser_wavelength = [1293,1302,1310,1318,1327.4];
uloops.M = [4,6,8];
uloops.link_length = [2]; % 1,2,3,5,6,8,10
wh = DataStorage(uloops);
wh.addStorage("ber");
wh = submit_simulations(wh,"parallel",1,"simulation_mode",0);
save('wh_2km',"wh");
end
for wavelength = wh.parameter.laser_wavelength.values
cols = linspecer(6);%cbrewer2('Set2',10);
figcnt = 0;
figWidth = 21; % Full-width for IEEE double-column papers (~7 inches)
figHeight = 6; % Adjust height as needed (~3.5 inches)
figure('Units','centimeters','Position', [1 1 figWidth figHeight],'PaperUnits','centimeters','PaperPosition', [0 0 figWidth figHeight])
tiledlayout(1,3, 'Padding', 'compact', 'TileSpacing', 'compact');
for m = uloops.M
figcnt = figcnt+1;
% subplot(1,3,figcnt)
nexttile
hold on
title(sprintf('%d km | %d nm | PAM %d',uloops.link_length,wavelength,m));
precomp = 1;
db_precode = 0;
a = wh.getStoValue('ber',precomp, db_precode, uloops.bitrate , wavelength, m, uloops.link_length);
ber_vnle = cellfun(@(x) x.vnle_pf_package{1,1}.ber_vnle, a);
ber_vnle_cell = cellfun(@(s) cellfun(@(p) p.ber_vnle, s.vnle_pf_package, 'UniformOutput', true), a, 'UniformOutput', false);
ber_vnle_best = cellfun(@(c) min(c), ber_vnle_cell);
plot(uloops.bitrate.*1e-9,ber_vnle_best,'DisplayName',sprintf('Tx precomp + VNLE'),'Color',cols(3,:),'LineStyle','-','HandleVisibility','on');
xticks(uloops.bitrate.*1e-9);
xlim([min(uloops.bitrate.*1e-9) max(uloops.bitrate.*1e-9)]);
precomp = 0; %0
db_precode = 1;
a = wh.getStoValue('ber',precomp, db_precode, uloops.bitrate , wavelength, m, uloops.link_length);
% ber_db = cellfun(@(x) x.dbtgt_package{1,1}.ber, a);
ber_db_cell = cellfun(@(s) cellfun(@(p) p.ber, s.dbtgt_package, 'UniformOutput', true), a, 'UniformOutput', false);
ber_db_best = cellfun(@(c) min(c), ber_db_cell);
plot(uloops.bitrate.*1e-9,ber_db_best,'DisplayName',sprintf('DB tgt. + MLSE',uloops.link_length,uloops.M),'Color',cols(1,:),'LineStyle','-','HandleVisibility','on');
xticks(uloops.bitrate.*1e-9);
xlim([min(uloops.bitrate.*1e-9) max(uloops.bitrate.*1e-9)]);
precomp = 0; %0
db_precode = 0; %1
a = wh.getStoValue('ber',precomp, db_precode, uloops.bitrate , wavelength, m, uloops.link_length);
% ber_mlse = cellfun(@(x) x.vnle_pf_package{1,1}.ber_mlse, a);
ber_mlse_cell = cellfun(@(s) cellfun(@(p) p.ber_mlse, s.vnle_pf_package, 'UniformOutput', true), a, 'UniformOutput', false);
ber_mlse_best = cellfun(@(c) min(c), ber_mlse_cell);
plot(uloops.bitrate.*1e-9,ber_mlse_best,'DisplayName',sprintf('VNLE + 1 tap post-filter + MLSE',uloops.link_length,uloops.M),'Color',cols(4,:),'LineStyle','-','HandleVisibility','on');
xticks(uloops.bitrate.*1e-9);
xlim([min(uloops.bitrate.*1e-9) max(uloops.bitrate.*1e-9)]);
set(gca, 'YScale', 'log');
ylim([8e-5 0.3]);
yline([4.8e-3, 2e-2],'HandleVisibility','off','LineWidth',1,'LineStyle','--','Color',[0.1 0.1 0.1]);
% legend
beautifyBERplot()
xlabel('Bit Rate in Gbps');
ylabel('BER');
if m ==4
text(310,6.8e-3,"4.8e-3","FontSize",10,"Interpreter","latex")
text(310,3e-2,"2e-2","FontSize",10,"Interpreter","latex")
end
% text(0.5,1,sprintf('%d km %d nm PAM %d',uloops.link_length,wavelength,m),...
% 'Units', 'normalized',"FontSize",10,"Interpreter","latex","BackgroundColor",[1 1 1],"EdgeColor",[0 0 0],'HorizontalAlignment','center','VerticalAlignment','top')
end
lgd = legend;
% Place the legend underneath the tiled layout
lgd.NumColumns = 3;
lgd.Layout.Tile = 'south';
end

View File

@@ -0,0 +1,170 @@
basePath = 'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\';
useGui = 0;
pamlvls = [4,6,8];
wlengths = [1302];
figoffset = 0;
figure(30)
tiledlayout(1, 3, 'TileSpacing', 'compact', 'Padding', 'compact');
for p = 1:numel(pamlvls)
nexttile;
for w = 1:numel(wlengths)
sgtitle(['Lambda: ',num2str(wlengths),' nm'])
hold on
pamlvl = pamlvls(p);
wlength = wlengths(w);
db = DBHandler("pathToDB",[basePath,'silas_labor.db']);
if useGui
filterParams = db.promptFilterParameters();
selectedFields = db.promptSelectFields();
else
filterParams = db.tables;
filterParams.Configurations = struct( ...
'bitrate', [], ...
'db_mode', [], ...
'fiber_length', 10, ...
'interference_attenuation', [], ...
'interference_path_length', [], ...
'is_mpi', 0, ...
'pam_level', pamlvl, ...
'precomp_amp', [], ...
'rop_attenuation', 0, ...
'symbolrate', [], ...
'v_awg', [], ...
'v_bias', [], ...
'wavelength', wlength ...
);
selectedFields = {'Runs.run_id','BERs.ber_id','Equalizer.eq_id','Equalizer.eq_type','BERs.ber','BERs.occurrence',...
'Configurations.db_mode','Configurations.pam_level','Configurations.bitrate','Configurations.symbolrate','Configurations.fiber_length','Configurations.wavelength','Configurations.precomp_amp',...
'Measurements.power_rop','Measurements.power_laser','Measurements.power_pd_in'};
end
% Get data table from DB
[dataTable,~] = db.queryDB(filterParams, selectedFields);
% Grouping variables: 'bitrate' and 'eq_type'
groupVars = {'bitrate', 'eq_type'};
% Calculate mean BER for each combination of 'bitrate' and 'eq_type'
groupedData = groupsummary(dataTable, groupVars, {'mean', 'min', @(x) meanExcludingOutliers(x)}, {'ber', 'power_rop','power_pd_in'});
% Collect the run_id values for each group
groupedRunIDs = varfun(@(x) {unique(x)}, dataTable, 'GroupingVariables', groupVars, 'InputVariables', 'run_id');
groupedRunIDs.Properties.VariableNames(end) = {'GroupedRunIDs'};
% Join the grouped data with the grouped run_id list
avgdBerTable = join(groupedData, groupedRunIDs, 'Keys', groupVars);
% Define the fields that you want to use for filtering
filterFields = {'eq_type'};
% Loop over each field you want to filter by
for f = 1:numel(filterFields)
currentField = filterFields{f};
% Determine unique values for the current field
uniqueValues = unique(avgdBerTable.(currentField));
% Loop over each unique value for the current field
for i = 1:numel(uniqueValues)
currentValue = uniqueValues(i);
% Filter joinedData for the current value
if isnumeric(currentValue)
filteredData = avgdBerTable(avgdBerTable.(currentField) == currentValue, :);
else
filteredData = avgdBerTable(strcmp(avgdBerTable.(currentField), currentValue), :);
end
cols = linspecer(8);
lst = ["-",":","--"];
a=plot(filteredData.bitrate.*1e-9,filteredData.min_ber,...
'Color',cols(i,:),'MarkerSize',4,'LineWidth',1,'LineStyle',lst(w),...
'Marker','o','MarkerFaceColor','auto','MarkerEdgeColor',cols(i,:),...
'DisplayName',[char(currentValue),'; ',num2str(wlength),' nm' ]);
a.DataTipTemplate.DataTipRows(1).Label = 'Bitrate';
a.DataTipTemplate.DataTipRows(1).Format = ['%.1f',' Gbit/s'];
a.DataTipTemplate.DataTipRows(2).Label = 'BER';
a.DataTipTemplate.DataTipRows(2).Format ='%.1e';
a.DataTipTemplate.DataTipRows(3).Label = 'P_{out}';
a.DataTipTemplate.DataTipRows(3).Value = filteredData.mean_power_rop;
a.DataTipTemplate.DataTipRows(3).Format = ['%.2f',' dBm'];
a.DataTipTemplate.DataTipRows(4).Label = 'Run ID';
a.DataTipTemplate.DataTipRows(4).Value = filteredData.GroupedRunIDs;
a.DataTipTemplate.DataTipRows(4).Format = ['%d',' '];
a.DataTipTemplate.FontSize = 9;
a.DataTipTemplate.FontName = 'arial';
%
% a=scatter(filteredData.bitrate.*1e-9,filteredData.min_ber,5,'Marker','diamond',...
% 'Color',cols(i,:),'LineWidth',1,...
% 'MarkerFaceColor','auto','MarkerEdgeColor',cols(i,:),...
% 'DisplayName',currentValue);
%
% a.DataTipTemplate.DataTipRows(1).Label = 'Bitrate';
% a.DataTipTemplate.DataTipRows(1).Format = ['%.1f',' Gbit/s'];
%
% a.DataTipTemplate.DataTipRows(2).Label = 'BER';
% a.DataTipTemplate.DataTipRows(2).Format ='%.1e';
%
% a.DataTipTemplate.DataTipRows(3).Label = 'P_{out}';
% a.DataTipTemplate.DataTipRows(3).Value = filteredData.mean_power_rop;
% a.DataTipTemplate.DataTipRows(3).Format = ['%.2f',' dBm'];
%
% a.DataTipTemplate.DataTipRows(4).Label = 'Run ID';
% a.DataTipTemplate.DataTipRows(4).Value = filteredData.GroupedRunIDs;
% a.DataTipTemplate.DataTipRows(4).Format = ['%d',' '];
%
%
% a.DataTipTemplate.FontSize = 9;
% a.DataTipTemplate.FontName = 'arial';
end
end
% Continue with the rest of your plot settings
title(sprintf('%d km | %d nm | PAM %d',unique(filterParams.Configurations.fiber_length),wlength,pamlvl));
yline(2e-2, 'DisplayName', '20% O-FEC', 'LineStyle', '--', 'HandleVisibility', 'off','LineWidth',1);
yline(3.8e-3, 'DisplayName', 'HD-FEC', 'LineStyle', '--', 'HandleVisibility', 'off','LineWidth',1);
xlabel('Bit Rate in Gbps');
ylabel('Bit Error Rate');
xlim([300, 480])
ylim([8e-4,0.5])
set(gca, 'yscale', 'log');
set(gca, 'Box', 'on');
grid on;
grid minor;
end
end
legend('Interpreter', 'none');
set(gcf, 'Units', 'pixels', 'Position', 1.0e+03 * [0.2483 0.7303 1.2093 0.3980]);
% Custom function using rmoutliers to calculate mean after removing outliers
function meanWithoutOutliers = meanExcludingOutliers(x)
% Remove outliers using rmoutliers with default method (based on median)
xWithoutOutliers = rmoutliers(x);
% Calculate the mean of the non-outliers
if isempty(xWithoutOutliers)
% Handle the case where all values are outliers
meanWithoutOutliers = NaN;
else
meanWithoutOutliers = mean(xWithoutOutliers);
end
end

View File

@@ -0,0 +1,192 @@
basePath = 'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\';
useGui = 0;
pamlvls = [6];
wlengths = [1293,1302,1310];%db.distinctValues.Configurations.wavelength
figoffset = 20;
figure(21)
tiledlayout(1, 3, 'TileSpacing', 'compact', 'Padding', 'compact');
for w = 1:numel(wlengths)
nexttile;
for p = 1:numel(pamlvls)
pamlvl = pamlvls(p);
wlength = wlengths(w);
db = DBHandler("pathToDB",[basePath,'silas_labor.db']);
if useGui
filterParams = db.promptFilterParameters();
selectedFields = db.promptSelectFields();
else
filterParams = db.tables;
filterParams.Configurations = struct( ...
'bitrate', 420e9, ...
'db_mode', [], ...
'fiber_length', [], ...
'interference_attenuation', [], ...
'interference_path_length', [], ...
'is_mpi', 0, ...
'pam_level', pamlvl, ...
'precomp_amp', [], ...
'rop_attenuation', 0, ...
'symbolrate', [], ...
'v_awg', [], ...
'v_bias', [], ...
'wavelength', wlength ...
);
% filterParams.Equalizer.eq_type = equalizer_structure.vnle;
selectedFields = {'Runs.run_id','BERs.ber_id','Equalizer.eq_id','Equalizer.eq_type','BERs.ber','BERs.occurrence',...
'Configurations.db_mode','Configurations.pam_level','Configurations.bitrate','Configurations.symbolrate','Configurations.fiber_length','Configurations.wavelength','Configurations.precomp_amp',...
'Measurements.power_rop','Measurements.power_laser','Measurements.power_pd_in'};
end
sgtitle(['Rate: ',num2str(filterParams.Configurations.bitrate),' Gbit/s'])
% Get data table from DB
[dataTable,~] = db.queryDB(filterParams, selectedFields);
% Extract unique rows from dataTable for each run_id with relevant configuration details
uniqueConfigFields = {'run_id', 'pam_level', 'bitrate','symbolrate', 'fiber_length', 'wavelength', 'precomp_amp', 'db_mode'};
[~, uniqueIdx] = unique(dataTable.run_id); % Get unique run_id indices
configDetails = dataTable(uniqueIdx, uniqueConfigFields); % Extract unique configurations for each run_id
% Calculate the mean BER for each combination of 'run_id' and 'eq_type'
groupedData = groupsummary(dataTable, {'run_id', 'eq_type'}, {'mean','min'}, {'ber', 'power_rop','power_pd_in'});
groupedData = groupsummary(dataTable, {'run_id', 'eq_type'}, {'mean', 'min', @(x) meanExcludingOutliers(x)}, {'ber', 'power_rop','power_pd_in'});
% Join groupedData with configDetails on the run_id field
joinedData = join(groupedData, configDetails, 'Keys', 'run_id');
% Define the fields that you want to use for filtering
filterFields = {'eq_type'};
% Create a cell array to store filtered data tables for each filter field
filteredDataByField = struct();
hold on
% Loop over each field you want to filter by
for f = 1:numel(filterFields)
currentField = filterFields{f};
% Determine unique values for the current field
uniqueValues = unique(joinedData.(currentField));
% Create a struct entry for the current field
filteredDataByField.(currentField) = cell(numel(uniqueValues), 1);
% Loop over each unique value for the current field
for i = 1:numel(uniqueValues)
currentValue = uniqueValues(i);
% Filter joinedData for the current value
if isnumeric(currentValue)
filteredData = joinedData(joinedData.(currentField) == currentValue, :);
else
filteredData = joinedData(strcmp(joinedData.(currentField), currentValue), :);
end
%%% workaround to average the BERs of several runs (ie in 1km case or trials)
%%% Workaround to average the BERs of several runs (e.g., in 1 km case or trials)
% Grouping variable(s)
groupVars = {'fiber_length'};
% Use groupsummary to calculate the mean and min of relevant fields
groupedDataWithMeans = groupsummary(filteredData, groupVars, {'mean', 'min'}, {'mean_ber', 'min_ber', 'fun1_ber', 'mean_power_rop', 'mean_power_pd_in'});
% Extract representative values for constant fields
[~, uniqueIdx] = unique(filteredData.(groupVars{1})); % Get the first occurrence of each bitrate value
constantFields = filteredData(uniqueIdx, {'bitrate', 'GroupCount', 'pam_level', 'symbolrate', 'fiber_length', 'wavelength', 'precomp_amp', 'db_mode'});
% Keep track of which run_id values were grouped
groupedRunIDs = varfun(@(x) {unique(x)}, filteredData, 'GroupingVariables', groupVars, 'InputVariables', 'run_id');
groupedRunIDs.Properties.VariableNames(end) = {'GroupedRunIDs'};
% Join the grouped data with the constant fields
groupedDataWithMeans = join(groupedDataWithMeans, constantFields, 'Keys', groupVars);
% Join the grouped data with the grouped run_id list
groupedDataWithMeans = join(groupedDataWithMeans, groupedRunIDs, 'Keys', groupVars);
% Update filteredData to include the grouped information
filteredData = groupedDataWithMeans;
%%% end of workaround
cols = linspecer(8);
% a=plot(filteredData.bitrate.*1e-9,filteredData.mean_mean_ber,...
% 'Color',cols(i,:),'MarkerSize',4,'LineWidth',1,'LineStyle',':',...
% 'Marker','o','MarkerFaceColor','auto','MarkerEdgeColor',cols(i,:),...
% 'DisplayName',currentValue);
lst = ["-",":","--"];
a=plot(filteredData.(groupVars{1}),filteredData.mean_fun1_ber,...
'Color',cols(i,:),'MarkerSize',4,'LineWidth',1,'LineStyle',lst(1),...
'Marker','o','MarkerFaceColor','auto','MarkerEdgeColor',cols(i,:),...
'DisplayName',[char(currentValue),'; ',num2str(wlength),' nm' ]);
%
% scatter(filteredData.symbolrate.*1e-9,filteredData.min_min_ber,5,'Marker','_',...
% 'Color',cols(i,:),'LineWidth',1,...
% 'MarkerFaceColor',cols(i,:),'MarkerEdgeColor','black',...
% 'DisplayName',currentValue);
a.DataTipTemplate.DataTipRows(1).Label = groupVars{1};
a.DataTipTemplate.DataTipRows(1).Format = ['%.1f',''];
a.DataTipTemplate.DataTipRows(2).Label = 'BER';
a.DataTipTemplate.DataTipRows(2).Format ='%.1e';
a.DataTipTemplate.DataTipRows(3).Label = 'P_{out}';
a.DataTipTemplate.DataTipRows(3).Value = filteredData.mean_mean_power_rop;
a.DataTipTemplate.DataTipRows(3).Format = ['%.2f',' dBm'];
a.DataTipTemplate.DataTipRows(4).Label = 'Baudr';
a.DataTipTemplate.DataTipRows(4).Value = filteredData.bitrate .*1e-9;
a.DataTipTemplate.DataTipRows(4).Format = ['%.1f',' GBd'];
a.DataTipTemplate.DataTipRows(5).Label = 'Run ID';
a.DataTipTemplate.DataTipRows(5).Value = filteredData.GroupedRunIDs;
a.DataTipTemplate.DataTipRows(5).Format = ['%f',' GBd'];
a.DataTipTemplate.FontSize = 9;
a.DataTipTemplate.FontName = 'arial';
end
end
% Continue with the rest of your plot settings
title(sprintf('Lambda: %f',wlength));
yline(2e-2, 'DisplayName', '20% O-FEC', 'LineStyle', '--', 'HandleVisibility', 'off');
yline(3.8e-3, 'DisplayName', 'HD-FEC', 'LineStyle', '--', 'HandleVisibility', 'off');
xlabel(groupVars{1},'Interpreter','none');
ylabel('Bit Error Rate (BER)');
%xlim([300, 480])
ylim([8e-4,0.5])
set(gca, 'yscale', 'log');
set(gca, 'Box', 'on');
grid on;
grid minor;
legend('Interpreter', 'none');
end
end
% Custom function using rmoutliers to calculate mean after removing outliers
function meanWithoutOutliers = meanExcludingOutliers(x)
% Remove outliers using rmoutliers with default method (based on median)
xWithoutOutliers = rmoutliers(x);
% Calculate the mean of the non-outliers
if isempty(xWithoutOutliers)
% Handle the case where all values are outliers
meanWithoutOutliers = NaN;
else
meanWithoutOutliers = mean(xWithoutOutliers);
end
end

View File

@@ -0,0 +1,554 @@
% Connect to SQLite database
pathToDB = 'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\silas_labor.db'; % Update the path as needed
db = DBHandler("pathToDB",pathToDB);
% main file path
sioe_labor_path = 'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor';
% Get list of all folders (including subfolders) within sioe_labor_path
folderList = dir(fullfile(sioe_labor_path, '**', '*'));
% Filter to include only directories and exclude '.' and '..'
folderNames = {folderList([folderList.isdir]).name};
folderPaths = {folderList([folderList.isdir]).folder}; % Get the full paths
folderPaths = folderPaths(~ismember(folderNames, {'.', '..'}));
folderNames = folderNames(~ismember(folderNames, {'.', '..'}));
% Combine folder names with paths
fullFolderPaths = flip(fullfile(folderPaths, folderNames));
% process only MPI?
only_mpi=0;
if only_mpi
fullFolderPaths = fullFolderPaths(contains(fullFolderPaths,"mpi"));
end
% Shorten folder paths to display only the folder name after the last filesep
displayFolderPaths = cellfun(@(x) x(find(x == filesep, 1, 'last') + 1 : end), fullFolderPaths, 'UniformOutput', false);
% Create checkbox settings for each folder path
numFolders = numel(fullFolderPaths);
checkboxSettings = cell(1, 2 * numFolders);
for i = 1:numFolders
checkboxSettings{2*i-1} = {displayFolderPaths{i}; sprintf('Folder_%d', i)};
checkboxSettings{2*i} = true; % Set false for unchecked by default
end
% Create settings dialog using settingsdlg
[settings, button] = settingsdlg( ...
'Description', 'Select Folders to Process:', ...
'title', 'Folder Selection', ...
checkboxSettings{:});
% Check if the user pressed OK
if strcmp(button, 'OK')
% Get all the field names from settings
allFields = fieldnames(settings);
% Determine which folders were selected
selectedFoldersIdx = cellfun(@(x) settings.(x), allFields);
% Get the list of selected folders
selectedFolders = fullFolderPaths(selectedFoldersIdx==1);
% Display the selected folders
fprintf('Selected Folders to Process:\n');
disp(selectedFolders);
else
fprintf('No folders selected.\n');
end
relativeFolderPaths = strrep(selectedFolders, sioe_labor_path, '');
disp(['Start to process ',num2str(numel(relativeFolderPaths)), ' folder in the directory']);
for f = 1:numel(selectedFolders)
folder = selectedFolders{n};
relfolder = relativeFolderPaths{f};
% Get list of all files in the specified folder and subfolders
fileList = dir(folder);
if isempty(fileList(~[fileList.isdir]))
continue
end
matches = regexp(folder, '\d+km', 'match');
% Check if a match was found
if ~isempty(matches)
length_from_foldername_km = matches{1}; % Extract the first match
length_from_foldername_km = strrep(length_from_foldername_km,'km','');
disp(['The length is: ', length_from_foldername_km]);
else
disp('No length information found in the folder name.');
end
% Loop through each file and rename if necessary
for i = 1:length(fileList)
oldName = fileList(i).name;
% Use regex to find and remove any prefix before the date string
newName = regexprep(oldName, '^[^\d]*(\d{8}_\d{6}.*)', '$1');
% Insert an underscore before "PAM" if missing
newName = regexprep(newName, '(\d{8}_\d{6})(PAM)', '$1_PAM');
% Rename the file only if a change was made
if ~strcmp(oldName, newName)
movefile(fullfile(fileList(i).folder, oldName), fullfile(fileList(i).folder, newName));
fprintf('Renamed: %s -> %s\n', oldName, newName);
end
end
% Get new list of all files in the specified folder and subfolders, we
% renamed files so we need to get the new filenames here to work on :-)
fileList = dir(folder);
% Initialize lists to store DataStorage objects based on size
big_wh_list = {}; % For large DataStorage objects
big_wh_filename = {}; % Corresponding filenames for large objects
small_wh_list = {}; % For small DataStorage objects
small_wh_filename = {}; % Corresponding filenames for small objects
% Loop through each file and categorize based on the presence of 'wh' in the filename
for i = 1:length(fileList)
fileName = fileList(i).name;
if contains(fileName, 'wh')
% Load DataStorage object from file
wh = load(fullfile(fileList(i).folder, fileName));
wh = wh.obj;
% Classify as big or small based on dimensions
if isa(wh, 'DataStorage')
if prod(wh.dim) > 2
big_wh_list{end+1} = wh;
big_wh_filename{end+1} = fileName;
else
small_wh_list{end+1} = wh;
small_wh_filename{end+1} = fileName;
end
end
end
end
% Aggregate unique parameters across all large DataStorage objects
params_merge = struct;
for c = 1:numel(big_wh_list)
fnames = fieldnames(big_wh_list{c}.parameter);
for fn = 1:numel(fnames)
% Initialize field if not already present
if ~isfield(params_merge, fnames{fn})
params_merge.(fnames{fn}) = [];
end
% Merge unique parameter values into params_merge
a = big_wh_list{c}.parameter.(fnames{fn}).values;
b = params_merge.(fnames{fn});
vals_to_add = setdiff(a, b); % New values in a that aren't in b
b = sort([b, vals_to_add]); % Combine and sort values
params_merge.(fnames{fn}) = b;
end
end
% Process each large DataStorage object
for w = 1:numel(big_wh_list)
wh = big_wh_list{w};
% Extract date and time for filename generation
datebody = regexp(big_wh_filename{w}, '^\d{8}_\d{6}', 'match', 'once');
% Get the total number of linear indices
totalIndices = wh.getLastLinIndice;
% Initialize the waitbar
h = waitbar(0, 'Processing DataStorage...');
% Loop over each linear index in DataStorage
for i = 1:wh.getLastLinIndice
% Update the waitbar with the current progress
waitbar(i / totalIndices, h, sprintf('Folder: %s...\n %d of %d', string(strrep(strrep(relfolder, '\', '/'),'_',' ')), i, totalIndices));
% Initialize record struct for each entry and flag for non-empty data
measurementStruct = struct();
recordIsFilled = false;
% Loop over each storage within DataStorage and gather data
storage_names = fieldnames(wh.sto);
for s = 1:length(storage_names)
% Retrieve physical values, parameter names, and stored value
[configStruct, stored_value] = wh.getPhysAndValueByLinIndex(storage_names{s}, i);
measurementStruct.(storage_names{s}) = stored_value;
if ~isempty(stored_value)
recordIsFilled = true; % Mark as filled if value is present
end
end
[configStruct.precomp_amp_max,configStruct.v_bias_for_pam] = getBias(configStruct.duobinary,configStruct.M);
isMPI = isfield(measurementStruct,'i_power');
% Process record if it contains *any* data
if recordIsFilled
if ~isMPI
% Generate filenames with conditionally formatted parameters
% Format the L parameter value (show decimal only if non-zero)
if configStruct.lambda == floor(configStruct.lambda)
L_str = sprintf('%.0f',configStruct.lambda); % No decimal part
else
L_str = sprintf('%.1f', configStruct.lambda); % Include one decimal place
end
% Synthesize filename base with placeholders for storage types
fbody_tx = sprintf('%s_PAM_%d_L_%s_R_%d_DB_%d_ROP_%d', datebody, ...
configStruct.M, L_str, configStruct.bitrate, configStruct.duobinary, 0);
fbody_tx = strrep(fbody_tx, '.', '_'); % Replace decimal point with underscore
if configStruct.rop_atten == round(configStruct.rop_atten)
fbody_rx = sprintf('%s_PAM_%d_L_%s_R_%d_DB_%d_ROP_%d', datebody, ...
configStruct.M, L_str, configStruct.bitrate, configStruct.duobinary, configStruct.rop_atten);
else
fbody_rx = sprintf('%s_PAM_%d_L_%s_R_%d_DB_%d_ROP_%.1f', datebody, ...
configStruct.M, L_str, configStruct.bitrate, configStruct.duobinary, configStruct.rop_atten);
end
fbody_rx = strrep(fbody_rx, '.', '_');
elseif isMPI
fbody_tx = sprintf('%s_PAM_%d_R_%d_DB_%d_I_atten_%d', datebody, ...
configStruct.M, configStruct.bitrate, configStruct.duobinary, 0);
fbody_tx = strrep(fbody_tx, '.', '_'); % Replace decimal point with underscore
if configStruct.interference_atten == round(configStruct.interference_atten)
fbody_rx = sprintf('%s_PAM_%d_R_%d_DB_%d_I_atten_%d', datebody, ...
configStruct.M, configStruct.bitrate, configStruct.duobinary, configStruct.interference_atten);
else
fbody_rx = sprintf('%s_PAM_%d_R_%d_DB_%d_I_atten_%.1f', datebody, ...
configStruct.M, configStruct.bitrate, configStruct.duobinary, configStruct.interference_atten);
end
fbody_rx = strrep(fbody_rx, '.', '_'); % Replace decimal point with underscore
end
% Check existence of different file types (bits, symbols, raw signal, rx signal)
% BIT SEQUENCE
fn_bits = [filesep, fbody_tx, '_bits.mat'];
fp_bits = fullfile([folder, fn_bits]);
if exist(fp_bits, "file") == 2
fn_bits_rel = [relfolder, fn_bits];
else
warning(['Bits not found at: ', fn_bits]);
end
% SYMBOL SEQUENCE
fn_symbols = [filesep, fbody_tx, '_symbols.mat'];
fp_symbols = fullfile([folder, fn_symbols]);
if exist(fp_symbols, "file") == 2
fn_symbols_rel = [relfolder, fn_symbols];
else
warning(['Symbols not found at: ', fn_symbols]);
end
% RAW RX SIGNAL
fn_rxraw = [filesep, fbody_rx, '_raw_signal.mat'];
fp_rxraw = fullfile([folder, fn_rxraw]);
missing_raw_flag = 1; % Initialize as missing
if exist(fp_rxraw, "file") == 2
fn_rxraw_rel = [relfolder, fn_rxraw];
missing_raw_flag = 0;
end
% SYNCHRONIZED RX SIGNAL
fn_rxtsynch = [filesep, fbody_rx, '_rx_signal.mat'];
fp_rxtsynch = fullfile([folder, fn_rxtsynch]);
fn_rxtsynch_rel = [];
if exist(fp_rxtsynch, "file") == 2
fn_rxtsynch_rel = [relfolder, fn_rxtsynch];
matObj = matfile([folder, fn_rxtsynch]);
% If RX signal actually contains raw signal, handle as necessary
if isprop(matObj, 'Scpe_sig_raw')
sig_rx = load([folder, fn_rxtsynch]);
if missing_raw_flag
% Save as raw signal if original raw signal is missing
Scpe_sig_raw = sig_rx.Scpe_sig_raw;
save([folder, fn_rxraw], "Scpe_sig_raw");
delete([folder, fn_rxtsynch]);
else
% Check if raw and rx signal files are identical, then delete duplicate
sig_raw = load([folder, fn_rxraw]);
if isequal(sig_raw, sig_rx)
delete([folder, fn_rxtsynch]);
end
end
end
elseif exist(fp_rxtsynch, "file") == 0
disp(['RX Signal not found at: ', fn_rxtsynch,' generate and save new one using symbols and raw signal']);
Scpe_sig_raw = load(fp_rxraw);
Scpe_sig_raw = Scpe_sig_raw.Scpe_sig_raw;
Symbols = load(fp_symbols);
Symbols = Symbols.Symbols;
%%%%%% Sample to 2x fsym %%%%%%
Scpe_sig_resampled = Scpe_sig_raw.resample("fs_in",Scpe_sig_raw.fs,"fs_out",2*Symbols.fs);
%%%%%% Sync Rx signal with reference (S is a cell array with all occurences) %%%%%%
[Scpe_sig_syncd,S,isFlipped] = Scpe_sig_resampled.tsynch("reference",Symbols,"fs_ref",Symbols.fs);
%%%%% Plot and Save Routines: SAVE RECEIVED SIGNALS %%%%%%%%%%%%%%%%%%%%%%%%%
save(fp_rxtsynch,"S");
if exist(fp_rxtsynch, "file") == 0
warndlg('Something still wromg... No rx file here but we just generated it from raw signal');
end
fn_rxtsynch_rel = [relfolder, fn_rxtsynch];
elseif missing_raw_flag
warndlg('No RAW or RX signal found! This is bad!');
% look at measurementStruct and configStruct
end
else
disp('Record not filled?')
% look at measurementStruct and configStruct
end
% Call the duplicate check function
if ~isempty(fn_rxtsynch_rel)
exists = db.checkIfRunExists('Runs', 'rx_sync_path', fn_rxtsynch_rel);
end
if ~exists
% Table 1: Append to Runs
newRun = db.tables.Runs; % Get the existing table structure (an empty table)
newRun = struct(...
'run_id', NaN, ... % Auto-increment, leave empty
'date_of_run', datetime(datebody, 'InputFormat', 'yyyyMMdd_HHmmss'), ...
'tx_bits_path', fn_bits_rel, ...
'tx_symbols_path', fn_symbols_rel, ...
'rx_sync_path', fn_rxtsynch_rel, ...
'rx_raw_path', fn_rxraw_rel, ...
'filename', fbody_rx ...
);
% Append the new row to the Runs table and get the generated run ID
run_id = db.appendToTable('Runs', newRun);
if isMPI
assert(configStruct.interference_atten==measurementStruct.voa.value(4),'MPI attuation differs between voa state and desired config from simulation loop.');
interference_attenuation = configStruct.interference_atten;
interference_path_length = 2;
power_mpi_interference = measurementStruct.voa.power_state(4);
power_mpi_signal = measurementStruct.voa.power_state(3);
rop_attenuation = 0;
wavelength = 1310;
fiber_length = 1;
else
interference_attenuation = NaN;
interference_path_length = NaN;
power_mpi_interference = NaN;
power_mpi_signal = NaN;
rop_attenuation = configStruct.rop_atten;
wavelength = configStruct.lambda;
fiber_length = str2double(length_from_foldername_km);
end
% Table 2: Append to Configurations
newConfig = db.tables.Configurations; % Get the existing table structure (an empty table)
newConfig = struct(...
'configuration_id', NaN, ... % Auto-increment, leave empty
'run_id', run_id, ... % Foreign key from Runs
'unique_elab_id', "20241028-dea635ef776cd18270922ba0e52c65831ff7699f", ... % Set unique_elab_id as needed
'bitrate', configStruct.bitrate, ...
'symbolrate', floor(configStruct.bitrate * 1e-9 / log2(configStruct.M)) * 1e9, ... % Calculate symbolrate if available
'pam_level', configStruct.M, ...
'db_mode', configStruct.duobinary, ... % Assuming db_mode corresponds to duobinary mode
'v_bias', configStruct.v_bias_for_pam, ...
'v_awg', 2.7, ...
'precomp_amp', configStruct.precomp_amp_max, ...
'rop_attenuation', rop_attenuation, ...
'wavelength', wavelength, ...
'fiber_length', fiber_length, ...
'is_mpi', isMPI, ... % Set false for no MPI, change as needed
'interference_path_length', interference_path_length, ... % Set NaN if not applicable
'interference_attenuation', interference_attenuation ... % Set NaN if not applicable
);
% Append the new row to the Configurations table
db.appendToTable('Configurations', newConfig);
% Table 3: Append to Measurements
newMeas = db.tables.Measurements; % Get the existing table structure (an empty table)
newMeas = struct(...
'measurement_id', NaN, ... % Auto-increment, leave empty
'run_id', run_id, ... % Foreign key from Runs
'power_laser', measurementStruct.exfo.cur_power, ...
'power_rop', measurementStruct.rop, ...
'power_pd_in', measurementStruct.pd_in, ...
'power_mpi_interference', power_mpi_interference, ...
'power_mpi_signal', power_mpi_signal, ...
'voa_class', measurementStruct.voa, ...
'pdfa_class', measurementStruct.pdfa, ...
'laser_class', measurementStruct.exfo ...
);
% Append the new row to the Measurements table
db.appendToTable('Measurements', newMeas);
% % Table 4: Append to Bers
% [ber, structure, settings] = getBers(configStruct,measurementStruct);
% for t = 1:numel(ber)
%
% if iscell(ber(t))
% ber_ = ber(t);
% ber_ = ber_{1};
% else
% ber_ = ber(t);
% end
%
% if ber_~=-1
%
% newBer = struct(...
% 'ber_id', NaN,...
% 'run_id', run_id,...
% 'processing_structure', structure(t),...
% 'processing_settings', settings(t),...
% 'ber', jsonencode(ber_)...
% );
%
% db.appendToTable('BERs', newBer);
%
% end
%
% end
end
end
end
end
function [ber, structure, settings] = getBers(configStruct,measurementStruct)
if configStruct.duobinary == 0
structure(1) = "vnle";
settings(1) = EQ("Ne",[50,7,7],"Nb",[0,0,0],"training_length",4096*2,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.0,"DDmu",[0.0004 0.0004 0.0004 0.0004 ],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
ber(1) = measurementStruct.ber_vnle;
structure(2) = "vnle -> remove DC from error ""Noi{s}.signal = Noi{s}.signal - mean(Noi{s}.signal);"" -> burg(error) -> pf -> mlse";
settings(2) = EQ("Ne",[50,7,7],"Nb",[0,0,0],"training_length",4096*2,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.0,"DDmu",[0.0004 0.0004 0.0004 0.0004 ],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
ber(2) = measurementStruct.ber_vnle_mlse;
elseif configStruct.duobinary == 1
structure(1) = "tx: duobinary precode; rx: db target -> mlse -> modulo";
settings(1) = EQ("Ne",[50,7,7],"Nb",[0,0,0],"training_length",4096*2,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.0,"DDmu",[0.0004 0.0004 0.0004 0.0004 ],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
ber(1) = measurementStruct.ber_db;
elseif configStruct.duobinary == 2
structure(1) = "tx: duobinary precode -> encode; rx: db target -> mlse as decoder -> modulo";
settings(1) = EQ("Ne",[50,7,7],"Nb",[0,0,0],"training_length",4096*2,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.0,"DDmu",[0.0004 0.0004 0.0004 0.0004 ],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
ber(1) = measurementStruct.ber_db;
end
end
function [precomp_amp_max,v_bias_for_pam] = getBias(db,M)
if db == 1
ffe_only = 0;
postfilter_approach = 0;
db_channel_approach = 1;
db_coding_approach = 0;
db_precode = db_coding_approach || db_channel_approach;
if M == 4
pulsef=1;
precomp_amp_max = -50;
v_bias_for_pam = 2.3;
pulsef = 1;
elseif M == 6
pulsef=0;
precomp_amp_max = -50;
v_bias_for_pam = 2.3;
pulsef = 1;
elseif M == 8
pulsef=0;
precomp_amp_max = -50;
v_bias_for_pam=2.6;
pulsef = 0;
end
elseif db == 2
ffe_only = 0;
postfilter_approach = 0;
db_channel_approach = 0;
db_coding_approach = 1;
db_precode = db_coding_approach || db_channel_approach;
if M == 4
pulsef=1;
precomp_amp_max = -38;
v_bias_for_pam = 2.8;
pulsef = 1;
elseif M == 6
pulsef=0;
precomp_amp_max = -38;
v_bias_for_pam = 2.8;
pulsef = 1;
elseif M == 8
pulsef=0;
precomp_amp_max = -38;
v_bias_for_pam = 2.8;
pulsef = 1;
end
elseif db == 0
ffe_only = 0;
postfilter_approach = 1;
db_channel_approach = 0;
db_coding_approach = 0;
db_precode = db_coding_approach || db_channel_approach;
if M == 4
pulsef=1;
precomp_amp_max = -37;
v_bias_for_pam = 2.3;
pulsef = 1;
elseif M == 6
pulsef=0;
precomp_amp_max = -34;
v_bias_for_pam = 2.3;
pulsef = 1;
elseif M == 8
pulsef=0;
precomp_amp_max = -34;
v_bias_for_pam=2.6;
pulsef = 0;
end
end
end

View File

@@ -0,0 +1,28 @@
function checkDB(db_path)
db = DBHandler("pathToDB",db_path);
num_runs = db.fetch('SELECT COUNT(*) AS total_runs FROM Runs');
num_configs = db.fetch('SELECT COUNT(*) AS total_configurations FROM Configurations');
num_meas = db.fetch('SELECT COUNT(*) AS total_measurements FROM Measurements');
assert((num_runs{1,1}==num_configs{1,1})&&(num_configs{1,1}==num_meas{1,1}),'Different num of entries per table')
% should not be possible, but check if anyconfig or meas is without
% parent Run entry
unmatchedConfigs = db.fetch('SELECT COUNT(*) AS unmatched_configs FROM Configurations WHERE run_id NOT IN (SELECT run_id FROM Runs)');
unmatchedMeasurements = db.fetch('SELECT COUNT(*) AS unmatched_measurements FROM Measurements WHERE run_id NOT IN (SELECT run_id FROM Runs)');
if unmatchedConfigs{1,1}~=0 || unmatchedMeasurements{1,1}~=0
fprintf('Unmatched Configurations: %d\n', unmatchedConfigs{1,1});
fprintf('Unmatched Measurements: %d\n', unmatchedMeasurements{1,1});
end
%Check for any duplicate paths
db.fetch("SELECT rx_raw_path, COUNT(*) AS occurrences FROM Runs GROUP BY rx_raw_path HAVING COUNT(*) > 1");
db.fetch("SELECT rx_sync_path, COUNT(*) AS occurrences FROM Runs GROUP BY rx_sync_path HAVING COUNT(*) > 1");
db.fetch("SELECT filename, COUNT(*) AS occurrences FROM Runs GROUP BY filename HAVING COUNT(*) > 1");
end

View File

@@ -0,0 +1,42 @@
% Load the Runs table from the database
db = DBHandler("pathToDB", 'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\silas_labor.db');
runsTable = db.queryDB(db.tables, {'Runs.run_id', 'Runs.tx_bits_path', 'Runs.tx_symbols_path', 'Runs.rx_sync_path', 'Runs.rx_raw_path', 'Runs.filename'});
% Initialize an array to store the result of existence check
fileExistenceResults = false(height(runsTable), 4); % 4 columns for the paths: tx_bits, tx_symbols, rx_sync, rx_raw
% Main file path
sioe_labor_path = 'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor';
% Loop through all rows in the table and check paths
for i = 1:height(runsTable)
fileExistenceResults(i, 1) = exist([sioe_labor_path, runsTable.tx_bits_path{i}], 'file') == 2;
fileExistenceResults(i, 2) = exist([sioe_labor_path, runsTable.tx_symbols_path{i}], 'file') == 2;
fileExistenceResults(i, 3) = exist([sioe_labor_path, runsTable.rx_sync_path{i}], 'file') == 2;
fileExistenceResults(i, 4) = exist([sioe_labor_path, runsTable.rx_raw_path{i}], 'file') == 2;
end
% Identify corrupted run_ids (where any path does not exist)
corruptedRunIds = runsTable.run_id(~all(fileExistenceResults, 2));
% Delete entries in all tables related to corrupted run_ids
for i = 1:numel(corruptedRunIds)
run_id = corruptedRunIds(i);
% Delete from BERs table
db.executeSQL(sprintf('DELETE FROM BERs WHERE run_id = %d;', run_id));
% Delete from Equalizer table (if applicable)
db.executeSQL(sprintf('DELETE FROM Equalizer WHERE eq_id IN (SELECT eq_id FROM BERs WHERE run_id = %d);', run_id));
% Delete from Measurements table
db.executeSQL(sprintf('DELETE FROM Measurements WHERE run_id = %d;', run_id));
% Delete from Configurations table
db.executeSQL(sprintf('DELETE FROM Configurations WHERE run_id = %d;', run_id));
% Delete from Runs table
db.executeSQL(sprintf('DELETE FROM Runs WHERE run_id = %d;', run_id));
end
%
% disp('Entries for corrupted run_ids have been removed from the database.');

View File

@@ -0,0 +1,52 @@
function createConfigMenu(DBHandler)
% Create the main figure window
fig = uifigure('Name', 'Configuration Query', 'Position', [100, 100, 400, 300]);
% Retrieve tables and table names using the DBHandler class
dbTables = DBHandler.getTables();
tableNames = DBHandler.getTableNames();
% Assume that the DBHandler class provides methods to get the unique
% configuration options (e.g., PAM levels, bitrates, etc.)
uniqueBitrates = unique([dbTables.bitrate]);
uniquePAMLevels = unique([dbTables.pam_level]);
uniqueWavelengths = unique([dbTables.wavelength]);
uniqueDBModes = unique([dbTables.db_mode]);
% Create dropdown menus for each configuration
lblBitrate = uilabel(fig, 'Text', 'Bitrate:', 'Position', [50, 240, 100, 20]);
dropdownBitrate = uidropdown(fig, 'Items', string(uniqueBitrates), 'Position', [150, 240, 200, 20]);
lblPAM = uilabel(fig, 'Text', 'PAM Level:', 'Position', [50, 200, 100, 20]);
dropdownPAM = uidropdown(fig, 'Items', string(uniquePAMLevels), 'Position', [150, 200, 200, 20]);
lblWavelength = uilabel(fig, 'Text', 'Wavelength:', 'Position', [50, 160, 100, 20]);
dropdownWavelength = uidropdown(fig, 'Items', string(uniqueWavelengths), 'Position', [150, 160, 200, 20]);
lblDBMode = uilabel(fig, 'Text', 'DB Mode:', 'Position', [50, 120, 100, 20]);
dropdownDBMode = uidropdown(fig, 'Items', string(uniqueDBModes), 'Position', [150, 120, 200, 20]);
% Create a button to query the configuration
btnQuery = uibutton(fig, 'Text', 'Query Configuration', 'Position', [150, 80, 200, 30], ...
'ButtonPushedFcn', @(btn, event) queryConfiguration(DBHandler, ...
dropdownBitrate.Value, ...
dropdownPAM.Value, ...
dropdownWavelength.Value, ...
dropdownDBMode.Value));
% Function to handle querying the configuration
function queryConfiguration(DBHandler, bitrate, pamLevel, wavelength, dbMode)
% Convert dropdown values to numeric if necessary
bitrate = str2double(bitrate);
pamLevel = str2double(pamLevel);
wavelength = str2double(wavelength);
dbMode = str2double(dbMode);
% Query the DBHandler class with the specified configuration
results = DBHandler.query(bitrate, pamLevel, wavelength, dbMode);
% Display the results in the command window (or update the GUI)
disp('Query Results:');
disp(results);
end
end

View File

@@ -0,0 +1,32 @@
function [berTable, foundBerFlag] = getBerForRunId(db, run_id)
% getBerForRunId Queries the BER data for the specified run_id.
% Inputs:
% db - The database handler object.
% run_id - The run ID for which to get the BER data.
% Outputs:
% berData - A table containing BER results for the given run ID.
% Set up filter parameters to query the BER data for the specific run_id
filterParams = db.tables;
filterParams.Runs.run_id = run_id; % Filter by specific run_id
% Define the fields to be retrieved from the database
selectedFields = {'Runs.run_id', 'BERs.ber_id', 'Equalizer.eq_id', 'Equalizer.eq_type', ...
'BERs.ber', 'BERs.occurrence', 'Configurations.db_mode', ...
'Configurations.pam_level', 'Configurations.bitrate', 'Configurations.symbolrate', ...
'Configurations.fiber_length', 'Configurations.wavelength', ...
'Configurations.precomp_amp', 'Measurements.power_rop', 'Measurements.power_laser', ...
'Measurements.power_pd_in'};
% Query the database for the specified run_id
[berTable, ~] = db.queryDB(filterParams, selectedFields);
if ~isnumeric(berTable.ber)
foundBerFlag = ~isnan(str2num(berTable.ber));
else
foundBerFlag = 1;
end
% Display information about the found BER entries
% fprintf('Found %d BER entries for run_id %d.\n', size(berTable, 1), run_id);
end

View File

@@ -0,0 +1,122 @@
precomp_path = "C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\precomp";
precomp_fn = "lab_high_speed";
precomp_mode = 2; %0=do nothing ; 1= measure; 2=precomp active
db_precode = 0;
db_coding_approach = 0;
fsym = 160e9;
fdac = 256e9;
random_key = 0;
pams = [4];
cols = cbrewer2('Paired',6);
for i = 1:length(pams)
M = pams(i);
if (db_precode==1)&&(db_coding_approach==0)
if M == 4
pulsef=1;
precomp_amp_max = -50;
fsym = 196e9;
elseif M == 6
pulsef=0;
precomp_amp_max = -50;
fsym = 180e9;
elseif M == 8
pulsef=0;
precomp_amp_max = -50;
fsym = 160e9;
end
elseif (db_precode==1)&&(db_coding_approach==1)
if M == 4
pulsef=1;
precomp_amp_max = -38;
pulsef = 1;
elseif M == 6
pulsef=0;
precomp_amp_max = -38;
pulsef = 1;
elseif M == 8
pulsef=0;
precomp_amp_max = -38;
pulsef = 1;
end
elseif (db_precode==0)&&(db_coding_approach==0)
if M == 4
pulsef=1;
precomp_amp_max = -37;
pulsef = 1;
fsym = 196e9;
elseif M == 6
pulsef=0;
precomp_amp_max = -34;
pulsef = 1;
fsym = 180e9;
elseif M == 8
pulsef=0;
precomp_amp_max = -34;
pulsef = 0;
fsym = 160e9;
end
end
rcalpha = 0.05;
Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rrc","pulselength",16,"alpha",rcalpha);
Pamsource = PAMsource(...
"fsym",fsym,"M",M,"order",19,"useprbs",0,...
"fs_out",fdac,...
"applyclipping",0,"clipfactor",1.2,...
"applypulseform",pulsef,"pulseformer",Pform,...
"randkey",random_key,...
"db_precode",db_precode,"db_encode",db_coding_approach,...
"mrds_code",0,"mrds_blocklength",512);
[Digi_sig,Symbols,Bits] = Pamsource.process();
Digi_sig = Digi_sig.normalize("mode","rms");
precomp_est = ChannelFreqResp("Nacq",2048,"Navg",100,"Ncp",63,'f_ref',Digi_sig.fs);
% maxampdb = [-30:-3:-50,precomp_amp_max];
maxampdb = precomp_amp_max;%sort(maxampdb);
cols_ = cbrewer2('spectral',15);
for j = 1:length(maxampdb)
if maxampdb(j) == precomp_amp_max
color=clr.Set1.green;
else
color=cols_(j,:);
end
Digi_sig_pre = precomp_est.precomp(Digi_sig,'maxampdb',maxampdb(j),'loadPath',precomp_path,'fileName',precomp_fn);
% Digi_sig_pre = Digi_sig_pre.normalize("mode","rms");
Digi_sig_pre = Digi_sig_pre.resample("fs_out",fdac);
Digi_sig_pre= Digi_sig_pre.normalize("mode","rms");
Digi_sig_pre.spectrum("displayname","Strong Precomp","fignum",2223,"normalizeToNyquist",0,"normalizeTo0dB",0,"color",color,"linestyle",'-','addDCoffset',27);
end
Digi_sig.spectrum("displayname","No Precomp","fignum",2223,"normalizeToNyquist",0,"normalizeTo0dB",0,"color",cols(2*i,:),"linestyle",'-','addDCoffset',27);
end
ylim([-25,10]);
xlim([0,105]);
xticks(0:20:110);
yticks(-30:10:10);
fig = gcf;
pos = [536.3333 879 450 222];
set(fig, 'Position', pos);

View File

@@ -0,0 +1,165 @@
tic
basePath = 'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\';
useGui = 0;
db = DBHandler("pathToDB",[basePath,'silas_labor.db']);
toc
if useGui
filterParams = db.promptFilterParameters();
selectedFields = db.promptSelectFields();
else
filterParams = db.tables;
filterParams.Configurations = struct( ...
'bitrate', 300e9, ...
'db_mode', 0, ...
'fiber_length', 1, ...
'interference_attenuation', [], ...
'interference_path_length', [], ...
'is_mpi', 0, ...
'pam_level', 4, ...
'precomp_amp', [], ...
'rop_attenuation', [], ...
'symbolrate', [], ...
'v_awg', [], ...
'v_bias', [], ...
'wavelength', 1310 ...
);
% filterParams.Runs.run_id = 3303;
%filterParams.Equalizer.eq_id = equalizer_structure.vnle;
selectedFields = {'Runs.run_id','Runs.tx_bits_path', 'Runs.tx_symbols_path', 'Runs.rx_sync_path','Runs.rx_raw_path',...
'Configurations.db_mode','Configurations.pam_level','Configurations.bitrate','Configurations.fiber_length','Configurations.wavelength','Configurations.precomp_amp','BERs.ber'};
end
toc
[dataTable,sql_query] = db.queryDB(filterParams, selectedFields);
[~, uniqueIdx] = unique(dataTable.run_id); % Get unique run_id indices
dataTable = dataTable(uniqueIdx,:); % Extract unique configurations for each run_id
fprintf('Found %d entries for requested Configuration. IDs are: %s \n \n',size(dataTable,1),jsonencode(dataTable.run_id(1:min(size(dataTable,1),100))));
toc
fprintf('Processing: %d%%', 0);
%2) Process Measurement Config
for i = 1:size(dataTable,1)
fprintf('\b\b\b\b%4d', i); % Backspace 3 characters, then overwrite
[~, foundBerFlag] = getBerForRunId(db, dataTable.run_id(i));
if foundBerFlag
continue
end
fprintf('\n%s T: %f CURRENT ID: %d == %d KM == %s PAM %d == %d Gbit/s == %d nm %s \n \n', repmat('=', 1, 10), toc/60, dataTable.run_id(i), dataTable.fiber_length(i) ,db_mode(dataTable.db_mode(i)), dataTable.pam_level(i) ,dataTable.bitrate(i).*1e-9,dataTable.wavelength(i), repmat('=', 1, 10)); % Print a blank line, then a thick line of 80 '=' characters, then another blank line
% FROM NOW ON, ONE Run_id IS CHOSEN AND WILL BE DSP'd
tx_bits = load([basePath, char(dataTable.tx_bits_path(i))]);
tx_bits = tx_bits.Bits;
tx_symbols = load([basePath, char(dataTable.tx_symbols_path(i))]);
tx_symbols = tx_symbols.Symbols;
rx_sync = load([basePath, char(dataTable.rx_sync_path(i))]);
rx_sync = rx_sync.S;
%rx_raw = load([basePath, char(result.rx_raw_path(i))]);
ffe_order=[50,0,0];
vnle_order=[50,7,7];
dfe_order = [0 0 0];
len_tr = 4096*2;
mu_ffe = [0.0004 0.0004 0.0004];
mu_dfe = 0.0004;
mu_dc = 0.05;
dfe_ = sum(dfe_order)>0;
%Loop through sliced oscilloscope measurement
parfor o = 1:numel(rx_sync)
rx_sig = rx_sync{o};
M = dataTable.pam_level(i);
switch dataTable.db_mode(i)
case db_mode.no_db
%FFE
eq_ffe(o) = EQ("Ne",ffe_order,"Nb",dfe_order,"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.05,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
[eq_sig,eq_noise,ber_ffe(o),totalErrors] = vnle( eq_ffe(o),M,rx_sig,tx_symbols, tx_bits);
%VNLE
eq_vnle(o) = EQ("Ne",vnle_order,"Nb",dfe_order,"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.05,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
[eq_sig,eq_noise,ber_vnle(o),totalErrors] = vnle(eq_vnle(o),M,rx_sig,tx_symbols, tx_bits);
%VNLE + PF + MLSE
eq_mlse(o) = EQ("Ne",vnle_order,"Nb",dfe_order,"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.05,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
pf_(o) = Postfilter("ncoeff",2);
mlse_(o) = MLSE("DIR",[0,0],"duobinary_output",0,"M",[],"trellis_states",[]);
[eq_sig,eq_noise,ber_mlse(o),totalErrors] = vnle_postfilter_mlse(eq_mlse(o) , pf_(o), mlse_(o),M, rx_sig,tx_symbols, tx_bits);
case db_mode.db_precoded
%EQ targets DB => less precompensation; pre-coded
M = dataTable.pam_level(i);
mlse_db_pre(o) = MLSE("DIR",[1,1],"duobinary_output",1,"M",M,"trellis_states",PAMmapper(M,0).levels);
eq_db_pre(o) = EQ("Ne",vnle_order,"Nb",dfe_order,"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.05,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
[eq_sig,eq_noise,ber_db_pre(o),totalErrors] = duobinary_target(eq_db_pre(o), mlse_db_pre(o),M, rx_sig, tx_symbols, tx_bits);
%->append BER to DB
case db_mode.db_encoded
%db signaling => db encoded
M = dataTable.pam_level(i);
mlse_db_enc(o) = MLSE("DIR",[1,1],"duobinary_output",1,"M",M,"trellis_states",PAMmapper(M,0).levels);
eq_db_enc(o) = EQ("Ne",vnle_order,"Nb",dfe_order,"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.05,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
[eq_sig,eq_noise,ber_db_enc(o),totalErrors] = duobinary_signaling(eq_db_enc(o), mlse_db_enc(o),M, rx_sig, tx_symbols, tx_bits);
%->append BER to DB
end
end
for o = 1:numel(rx_sync)
switch dataTable.db_mode(i)
case db_mode.no_db
%FFE
eq_type = equalizer_structure.ffe;
db.addBEREntry(ber_ffe(o), o, dataTable.run_id(i), eq_ffe(o), dfe_, [], [], eq_type, ffe_order, dfe_order, len_tr, mu_ffe, mu_dfe, mu_dc, "FFE");
showCurrentMeasurement('EQ', string(eq_type), 'BER',ber_ffe(o), 'Mode', string(db_mode(dataTable.db_mode(i))), 'Len', dataTable.fiber_length(i) ,'PAM' , dataTable.pam_level(i) , 'GBit/s' ,dataTable.bitrate(i).*1e-9, 'Lambda' ,dataTable.wavelength(i) );
%VNLE
eq_type = equalizer_structure.vnle;
db.addBEREntry(ber_vnle(o), o, dataTable.run_id(i), eq_vnle(o), dfe_, [], [], eq_type, vnle_order, dfe_order, len_tr, mu_ffe, mu_dfe, mu_dc, "VNLE");
showCurrentMeasurement('EQ', string(eq_type), 'BER',ber_vnle(o), 'Mode', string(db_mode(dataTable.db_mode(i))), 'Len', dataTable.fiber_length(i) ,'PAM' , dataTable.pam_level(i) , 'GBit/s' ,dataTable.bitrate(i).*1e-9, 'Lambda' ,dataTable.wavelength(i) );
%MLSE
eq_type = equalizer_structure.vnle_pf_mlse;
db.addBEREntry(ber_mlse(o), o, dataTable.run_id(i), eq_mlse(o), dfe_, mlse_(o), pf_(o), eq_type, vnle_order, dfe_order, len_tr, mu_ffe, mu_dfe, mu_dc, "VNLE;PF;MLSE");
showCurrentMeasurement('EQ', string(eq_type), 'BER',ber_mlse(o), 'Mode', string(db_mode(dataTable.db_mode(i))), 'Len', dataTable.fiber_length(i) ,'PAM' , dataTable.pam_level(i) , 'GBit/s' ,dataTable.bitrate(i).*1e-9, 'Lambda' ,dataTable.wavelength(i) );
case db_mode.db_precoded
%db_precoded
eq_type = equalizer_structure.db_precoded;
db.addBEREntry(ber_db_pre(o), o, dataTable.run_id(i), eq_db_pre(o), dfe_, mlse_db_pre(o), [], eq_type, vnle_order, dfe_order, len_tr, mu_ffe, mu_dfe, mu_dc, "DB Precode;DB Target;MLSE DB Decode;Modulo");
showCurrentMeasurement('EQ', string(eq_type), 'BER',ber_db_pre(o), 'Mode', string(db_mode(dataTable.db_mode(i))), 'Len', dataTable.fiber_length(i) ,'PAM' , dataTable.pam_level(i) , 'GBit/s' ,dataTable.bitrate(i).*1e-9, 'Lambda' ,dataTable.wavelength(i) );
case db_mode.db_encoded
%db_encoded
eq_type = equalizer_structure.db_encoded;
db.addBEREntry(ber_db_enc(o), o, dataTable.run_id(i), eq_db_enc(o), dfe_, mlse_db_enc(o), [], eq_type, vnle_order, dfe_order, len_tr, mu_ffe, mu_dfe, mu_dc, "DB Precode;DB Encode;DB Target;MLSE DB Decode;Modulo");
showCurrentMeasurement('EQ', string(eq_type), 'BER',ber_db_enc(o), 'Mode', string(db_mode(dataTable.db_mode(i))), 'Len', dataTable.fiber_length(i) ,'PAM' , dataTable.pam_level(i) , 'GBit/s' ,dataTable.bitrate(i).*1e-9, 'Lambda' ,dataTable.wavelength(i) );
end
end
end
fprintf('\n%s SIMULATION COMPLETE AFTER %f MINUTES %s \n \n', repmat('=', 1, 35), toc/60 ,repmat('=', 1, 35)); % Print a blank line, then a thick line of 80 '=' characters, then another blank line

View File

@@ -0,0 +1,131 @@
filename = "F:\2024\sioe\High Speed Messungen Oktober\baudrate_sweep_b2b\PAMX_b2b_baudrate20241024_210648_wh_final.mat";
a = load(filename);
wh = a.obj;
wh.showInfo;
fsym_vals = wh.parameter.fsym.values;
rop_atten_vals = wh.parameter.rop_atten.values;
M_vals = wh.parameter.M.values;
if 1
%%% (A) PLOT ROP CURVES OF ALL THREE MODULATION FORMATS NEXT TO EACH OTHER %%%
figure(300)
clf
hold on
ber_ffe=[];
ber_mlse=[];
rop=[];
v_bias=[];
cols = [cbrewer2('Set1',9);cbrewer2('Set2',8)];
for fsym_iter = 1:numel(fsym_vals)
for modulation_iter = 1:numel(M_vals)
ber_ffe(:,modulation_iter,fsym_iter) = wh.getStoValue('ber_ffe',fsym_vals(fsym_iter),rop_atten_vals,M_vals(modulation_iter));
ber_mlse(:,modulation_iter,fsym_iter) = wh.getStoValue('ber_mlse',fsym_vals(fsym_iter),rop_atten_vals,M_vals(modulation_iter));
rop(:,modulation_iter,fsym_iter) = wh.getStoValue('rop',fsym_vals(fsym_iter),rop_atten_vals,M_vals(modulation_iter));
v_bias(:,modulation_iter,fsym_iter) = wh.getStoValue('v_bias',fsym_vals(fsym_iter),rop_atten_vals,M_vals(modulation_iter));
subplot(1,3,modulation_iter)
title(['PAM ',num2str(M_vals(modulation_iter))]);
hold on
a = plot(rop(:,modulation_iter,fsym_iter),ber_ffe(:,modulation_iter,fsym_iter),...
'Color',cols(fsym_iter,:),'MarkerSize',2,'LineWidth',1,...
'Marker','o','MarkerFaceColor',cols(fsym_iter,:),'MarkerEdgeColor','black',...
'DisplayName',[num2str(fsym_vals(fsym_iter).*1e-9),'GBd']);
a.DataTipTemplate.DataTipRows(1).Label = 'P_{out}';
a.DataTipTemplate.DataTipRows(2).Label = 'BER';
a.DataTipTemplate.DataTipRows(2).Format =['%.1e'];
a.DataTipTemplate.DataTipRows(3).Label = 'Baudr';
a.DataTipTemplate.DataTipRows(3).Value = repmat(fsym_vals(fsym_iter).*1e-9,size(rop(:,modulation_iter,fsym_iter)));
a.DataTipTemplate.DataTipRows(3).Format = ['%d',' GBd'];
a.DataTipTemplate.DataTipRows(4).Label = 'Bitr';
a.DataTipTemplate.DataTipRows(4).Value = repmat(fsym_vals(fsym_iter).*1e-9.*log2(M_vals(modulation_iter)),size(rop(:,modulation_iter,fsym_iter)));
a.DataTipTemplate.DataTipRows(4).Format = ['%d',' Gbps'];
a.DataTipTemplate.FontSize = 9;
a.DataTipTemplate.FontName = 'arial';
% Continue with the rest of your plot settings
yline(3.8e-3, 'DisplayName', 'HD-FEC', 'LineStyle', '--', 'HandleVisibility', 'off');
xlabel('Measured MZM Output Power (dBm)');
ylabel('Bit Error Rate (BER)');
set(gca, 'yscale', 'log');
set(gca, 'Box', 'on');
grid on;
grid minor;
legend('Interpreter', 'none');
end
end
end
%%% (B) PLOT BEST ROP OF EACH MOD FORMAT OVER BAUDRATE %%%
if 1
figure(211)
clf
hold on
cols = [cbrewer2('Set1',9);cbrewer2('Set2',8)];
ber_ffe=[];
ber_mlse=[];
rop=[];
v_bias=[];
for modulation_iter = 1:numel(M_vals)
ber_ffe(:,modulation_iter) = wh.getStoValue('ber_ffe',fsym_vals,rop_atten_vals(1),M_vals(modulation_iter));
ber_mlse(:,modulation_iter) = wh.getStoValue('ber_mlse',fsym_vals,rop_atten_vals(1),M_vals(modulation_iter));
rop(:,modulation_iter) = wh.getStoValue('rop',fsym_vals,rop_atten_vals(1),M_vals(modulation_iter));
v_bias(:,modulation_iter) = wh.getStoValue('v_bias',fsym_vals,rop_atten_vals(1),M_vals(modulation_iter));
a=plot(fsym_vals.*1e-9.*log2(M_vals(modulation_iter)),ber_ffe(:,modulation_iter),...
'Color',cols(modulation_iter,:),'MarkerSize',2,'LineWidth',1,...
'Marker','o','MarkerFaceColor',cols(modulation_iter,:),'MarkerEdgeColor','black',...
'DisplayName',['PAM ',num2str(M_vals(modulation_iter))]);
a.DataTipTemplate.DataTipRows(1).Label = 'Bitr';
a.DataTipTemplate.DataTipRows(1).Format = ['%.1f',' Gbps'];
a.DataTipTemplate.DataTipRows(2).Label = 'BER';
a.DataTipTemplate.DataTipRows(2).Format ='%.1e';
a.DataTipTemplate.DataTipRows(3).Label = 'P_{out}';
a.DataTipTemplate.DataTipRows(3).Value = rop(:,modulation_iter);
a.DataTipTemplate.DataTipRows(3).Format = ['%.2f',' dBm'];
a.DataTipTemplate.DataTipRows(4).Label = 'Baudr';
a.DataTipTemplate.DataTipRows(4).Value = fsym_vals.*1e-9;
a.DataTipTemplate.DataTipRows(4).Format = ['%.1f',' GBd'];
a.DataTipTemplate.FontSize = 9;
a.DataTipTemplate.FontName = 'arial';
% Continue with the rest of your plot settings
title('Opt B2B')
yline(3.8e-3, 'DisplayName', 'HD-FEC', 'LineStyle', '--', 'HandleVisibility', 'off');
xlabel('Bit Rate in GBps');
ylabel('Bit Error Rate (BER)');
set(gca, 'yscale', 'log');
set(gca, 'Box', 'on');
grid on;
grid minor;
legend('Interpreter', 'none');
end
end

View File

@@ -0,0 +1,341 @@
folderpath = 'C:\Users\sioe\Documents\High_Speed_Measurement_2024\baudrate_sweep_b2b\';
experiment_name = 'PAMX_b2b_baudrate';
currentTime = datetime('now', 'Format', 'yyyyMMdd_HHmmss');
timeStr = char(currentTime);
experiment_name = [experiment_name, timeStr];
ffe_only = 0;
postfilter_approach = 1;
db_channel_approach = 0;
db_coding_approach = 0;
db_precode = 0;%db_coding_approach || db_channel_approach;
%%% SIR Sweep for MPI Experiment %%%
params = struct;
params.fsym = [100:6:200].*1e9; %2.67; % PAM6=2.3V %PAM8=2.68V
params.rop_atten = 0:0.5:7;
params.M = [8,6,4];
wh = DataStorage(params);
wh.addStorage("ber_ffe");
wh.addStorage("ber_mlse");
wh.addStorage("ber_db");
wh.addStorage("pd_in");
wh.addStorage("rop");
wh.addStorage("M");
wh.addStorage("signals");
wh.addStorage("v_bias");
wh.addStorage("awg_vpp");
wh.addStorage("precomp_amp_max")
precomp_path = "C:\Users\sioe\Documents\High_Speed_Measurement_2024\precomp\";
precomp_fn = "lab_high_speed";
precomp_mode = 2; %0=do nothing ; 1= measure; 2=precomp active
precomp_amp_max = 5;
awg_vpp = 2.7;
random_key = 2;
pd_in_set = 7;
looptotal = prod(wh.dim);
disp(['Start Measurement of ',num2str(looptotal),' loops...'])
iterationTimes = zeros(looptotal, 1); % Preallocate for speed
if ~exist('hWaitbar', 'var') || ~isvalid(hWaitbar)
hWaitbar = waitbar(0, sprintf('Starting %d measurements',looptotal), 'Name', 'Processing Progress');
else
waitbar(0, hWaitbar, sprintf('Starting %d measurements',looptotal));
end
loopcnt = 0;
estimatedTimeRemaining = 0;
estimatedTotalTime = 0;
for M = wh.parameter.M.values
%%%%% 1) SET Voltages for each modulation format once %%%%%%
if M == 4
v_bias = 2.1;
elseif M == 6
v_bias = 2.3;
elseif M == 8
v_bias = 2.67;
end
dcs = DC_supply("active",[1,0],"voltage",[v_bias, 0]);
dcs.set("voltage",[v_bias, 0]);
%%%%% SET Voltages %%%%%%
if M ~= 8
pause(30*60); %wait 30 minutes for stable bias
end
for fsym = wh.parameter.fsym.values
%%%% 2) PREARE THE TX SIGNAL ONCE FOR EACH FSYM RATE %%%%
%%%%% Construct AWG and Scope Modules %%%%%%
fdac = 256e9;
fadc = 256e9;
SCP = ScopeKeysight("model","UXR1104B",'autoscale',1,"fadc","GSa_256","channel",[0,1,0,0],"recordLen",4000000,"removeDC",1);
AWG = AwgKeysight("model","M8199B","fdac",fdac,"scaletodac",[1,1],"skews",[0,0],"voltages",[0,awg_vpp]);
A2S = Awg2Scope(AWG,SCP,[0,2,0,0],"waitUntilClick",0); %
%%%%% Symbol Generation %%%%%%
Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rrc","pulselength",16,"rrcalpha",0.05);
[Digi_sig,Symbols,Bits] = PAMsource(...
"fsym",fsym,"M",M,"order",19,"useprbs",1,...
"fs_out",fdac,...
"applyclipping",0,"clipfactor",1.7,...
"applypulseform",0,"pulseformer",Pform,...
"randkey",random_key,...
"db_precode",db_precode,"db_encode",db_coding_approach,...
"mrds_code",0,"mrds_blocklength",512).process();
%%%%% Precompensation Routine %%%%%%
precomp_est = ChannelFreqResp("Nacq",1024,"Navg",64,"Ncp",63,'f_ref',Digi_sig.fs);
Digi_sig = precomp_est.precomp(Digi_sig,'maxampdb',precomp_amp_max,'loadPath',precomp_path,'fileName',precomp_fn);
%%%%% Resample to DAC rate %%%%%%
Digi_sig = Digi_sig.resample("fs_out",AWG.fdac);
%%%%% Plot and Save Routine 1 %%%%%%%%%%%%%%%%%%%%%%%%%
%Digi_sig.spectrum("displayname","Normal Tx","fignum",10);
loop_name = ['PAM_',num2str(M),'_fsym_',num2str(fsym.*1e-9)];
save([folderpath,experiment_name,loop_name,'_bits'],"Bits");
save([folderpath,experiment_name,loop_name,'_symbols'],"Symbols");
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
for rop_atten = wh.parameter.rop_atten.values
%%%%% Loop Preps
iterationStartTime = tic;
loopcnt = loopcnt+1;
%%%%% SET Attenuator %%%%%%
voa = OptAtten("active",[1,2,1,1],"value",[rop_atten,pd_in_set,0,0],"wavelength",[1310,1310,1310,1310]);
voa.set('active',[1,2,1,1],'value',[rop_atten,pd_in_set,0,0]);
%%% HERE SHOULD BE THE DATA PREPARATION WHICH IS NOW IN BETWEEN
%%% THE LOOPS :-) %%%
%%%%% AWG --> Scope %%%%%%
[~,Scpe_sig_raw,~,D] = A2S.process("signal2",Digi_sig,"waitUntilClick",0);
%%%%%% Sample to 2x fsym %%%%%%
Scpe_sig_resampled = Scpe_sig_raw.resample("fs_in",fadc,"fs_out",2*fsym);
voa.readvals();
rop = voa.power_state(1);
pd_in = voa.power_state(2);
% disp(['ROP: ',num2str(rop),' dBm || PD in: ',num2str(pd_in), ' dBm']);
%%%%%% Sync Rx signal with reference (S is a cell array with all occurences) %%%%%%
[Scpe_sig_syncd,S,isFlipped] = Scpe_sig_resampled.tsynch("reference",Symbols,"fs_ref",fsym);
%%%%% Plot and Save Routines: SAVE RECEIVED SIGNALS %%%%%%%%%%%%%%%%%%%%%%%%%
loop_name = ['PAM_',num2str(M),'_fsym_',num2str(fsym.*1e-9),'_rop_',num2str(rop_atten)];
loop_name = strrep(loop_name,'.','_');
save([folderpath,experiment_name,loop_name,'_rx_signal'],"S");
%%%%% EQUALIZE %%%%%%
Eq = FFE("epochs_tr",5,"epochs_dd",5,"len_tr",4096*2,"mu_dd",1e-4,"mu_tr",0,"order",50,"sps",2,"decide",0);
% Eq = VNLE("epochs_tr",5,"epochs_dd",5,"len_tr",4096*2,"mu_dd",[0.0004 0.0005 0.0006],"mu_tr",0,"order",[50,7,7],"sps",2,"decide",1);
Eq = EQ("Ne",[50,7,7],"Nb",[0,0,0],"training_length",4096*2,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.05,"DDmu",[0.0004 0.0004 0.0004 0.0004 ],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
% set to minus one not zero not avoid confusion if BER is acutally zero
ber_ffe = -1;
ber_mlse = -1;
ber_db = -1;
if ffe_only %%%%%%%%%%%%%%%%%%%%%%%%%%%
[EQ_sig] = Eq.process(Scpe_sig_syncd,Symbols);
% EQ_sig.plot("fignum",50,"displayname",'After EQ');
Rx_bits = PAMmapper(M,0).demap(EQ_sig);
[~,errors_bm,ber_ffe,errors] = calc_ber(Rx_bits.signal,Bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
disp(['FFE: ',sprintf('%.1E',ber_ffe),'| ROP: ',num2str(rop),' dB | PD_in: ',num2str(pd_in),' dBm']);
if 0
EQ_sig.plot("fignum",50,"displayname",'After EQ','clear',1);
figure(56);
clf
title(sprintf('PAM %d ; BER: %1.2e',M, ber_ffe));
constellation = unique(Symbols.signal);
received = NaN(numel(constellation),length(Symbols));
for lvl = 1:numel(constellation)
%Separate the equalized signal into the
%respective levels based on the actually
%transmitted level!
received(lvl,Symbols.signal==constellation(lvl)) = EQ_sig.signal(Symbols.signal==constellation(lvl));
intermediate = received(lvl,:);
cnt(lvl) = numel(intermediate(~isnan(intermediate)));
hold on
histogram(received(lvl,:),1000,"EdgeAlpha",0,'DisplayName',['Lvl ',num2str(lvl),' | ',num2str(cnt(lvl)),' entries']);
end
legend
end
elseif postfilter_approach %%%%%%%%%%%%%%%%%%%%%%%%%%%
[EQ_sig] = Eq.process(Scpe_sig_syncd,Symbols);
% EQ_sig.plot("fignum",50,"displayname",'After EQ','clear',1);
Noi = EQ_sig-Symbols;
Rx_bits = PAMmapper(M,0).demap(EQ_sig);
[~,num_errors,ber_ffe,pos_errors] = calc_ber(Rx_bits.signal,Bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
nc = 2;
burg_coeff = arburg(Noi.signal,nc);
EQ_sig = EQ_sig.filter(burg_coeff,1);
if 0
Noi.spectrum('displayname','Noise PSD','fignum',123)
[h,w] = freqz(1,burg_coeff,length(Noi),"whole",Noi.fs);
h = h/max(abs(h));
hold on
w_ = (w - Noi.fs/2);
plot(w_.*1e-9,20*log10(fftshift(h)),'DisplayName',['', num2str(nc), ' coefficients for burg alg.']);
end
EQ_sig = MLSE("DIR",burg_coeff,"duobinary_output",0,"M",M,"trellis_states",PAMmapper(M,0).levels).process(EQ_sig);
Rx_bits = PAMmapper(M,0).demap(EQ_sig);
[~,num_errors,ber_mlse,pos_errors] = calc_ber(Rx_bits.signal,Bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
disp(['FFE: ',sprintf('%.1E',ber_ffe),' -> PF -> MLSE: ',sprintf('%.1E',ber_mlse),' dB | PD_in: ',num2str(pd_in),' dBm']);
elseif db_channel_approach %%%%%%%%%%%%%%%%%%%%%%%%%%%
if db_precode
[EQ_sig, Noi] = Eq.process(Scpe_sig_syncd,Duobinary().encode(Symbols));
EQ_sig.plot("fignum",50,"displayname",'After EQ','clear',1);
EQ_sig = MLSE("DIR",[1,1],"duobinary_output",1,"M",M,"trellis_states",PAMmapper(M,0).levels).process(EQ_sig);
EQ_sig = Duobinary().decode(EQ_sig);
Rx_bits = PAMmapper(M,0).demap(EQ_sig);
[~,num_errors,ber_db,pos_errors] = calc_ber(Rx_bits.signal,Bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
disp([' DB Precode -> Channel -> FFE -> Decode/ Mod ',sprintf('%.1E',ber_db),' | PD_in: ',num2str(pd_in),' dBm']);
else
% Toms approach für precode emulation
[EQ_sig, Noi] = Eq.process(Scpe_sig_syncd,Duobinary().encode(Symbols));
EQ_sig.spectrum("displayname","Signal Spectrum after Postfilter","fignum",1234,"normalizeToNyquist",0);
EQ_sig = MLSE("DIR",[1,1],"duobinary_output",1,"M",M,"trellis_states",PAMmapper(M,0).levels).process(EQ_sig);
% 2: Entschiedene Symbole codieren
%EQ_sig = Duobinary().encode(EQ_sig);
% 3. Entschiedene und codierte Symbole dekodieren
EQ_sig = Duobinary().decode(EQ_sig);
% 4. Demap EQ'd symbols
Rx_bits = PAMmapper(M,0).demap(EQ_sig);
Symbols_db = Duobinary().precode(Symbols);
Bits_ = PAMmapper(M,0).demap(Symbols_db);
[~,num_errors,ber_db,pos_errors] = calc_ber(Rx_bits.signal,Bits_.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
disp([' DB Precode -> Channel -> FFE -> Decode/ Mod ',sprintf('%.1E',ber_db),' | PD_in: ',num2str(pd_in),' dBm']);
end
elseif db_coding_approach %%%%%%%%%%%%%%%%%%%%%%%%%%%
[EQ_sig, Noi] = Eq.process(Scpe_sig_syncd,Symbols);
EQ_sig = MLSE("DIR",[1,1],"duobinary_output",1,"M",M,"trellis_states",PAMmapper(M,0).levels).process(EQ_sig);
EQ_sig = Duobinary().decode(EQ_sig);
Rx_bits = PAMmapper(M,0).demap(EQ_sig);
[~,errors_bm,ber_db,errors] = calc_ber(Rx_bits.signal,Bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
EQ_sig.plot("fignum",50,"displayname",'After EQ');
disp([' DB Precode -> DB Code -> Channel -> FFE -> Decode/ Mod ',sprintf('%.1E',ber_db),' | PD_in: ',num2str(pd_in),' dBm']);
end
%%%%% Store measurement into measurement "warehouse" %%%%%%
wh.addValueToStorage(ber_ffe,'ber_ffe',fsym,rop_atten,M);
wh.addValueToStorage(ber_mlse,'ber_mlse',fsym,rop_atten,M);
wh.addValueToStorage(ber_db,'ber_db',fsym,rop_atten,M);
wh.addValueToStorage(rop,'rop',fsym,rop_atten,M);
wh.addValueToStorage(pd_in,'pd_in',fsym,rop_atten,M);
% wh.addValueToStorage(Rx_bits,'signals',fsym,awg_vpp,precomp_amp_max,rop_atten);
wh.addValueToStorage(M,'M',fsym,rop_atten,M);
wh.addValueToStorage(v_bias,"v_bias",fsym,rop_atten,M);
wh.addValueToStorage(awg_vpp,"awg_vpp",fsym,rop_atten,M);
wh.addValueToStorage(precomp_amp_max,"precomp_amp_max",fsym,rop_atten,M);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%% Plot stuff into Table (feel free to add own values in -> 'name',value <- notation. Must be closed when table is changed)%%%%%%%%%%%%%%%%%%%%%%
showCurrentMeasurement('FFE', ber_ffe,'MLSE',ber_mlse, 'Fsym',fsym.*1e-9, 'ROP', rop, 'PD in', pd_in, 'PAM',M, 'Vbias', v_bias, 'AWG Vpp', awg_vpp, 'Precomp MaxAmp',precomp_amp_max);
%%%%% Arrange Figures %%%%%%%%%%%%%%%%%%%%%%
% autoArrangeFigures(3,3,2);
iterationTimes(loopcnt) = toc(iterationStartTime);
averageTimePerIteration = mean(iterationTimes(1:loopcnt));
estimatedTotalTime = averageTimePerIteration * looptotal;
estimatedTimeRemaining = estimatedTotalTime - sum(iterationTimes(1:loopcnt));
progressFraction = loopcnt / looptotal;
waitbar(progressFraction, hWaitbar, ...
sprintf('Loop: %d of %d \n Runtime: %.1f min | %.1f sec per Loop |Time to go: %.1f min ', ...
loopcnt, looptotal, sum(iterationTimes(1:loopcnt))/60, averageTimePerIteration, estimatedTimeRemaining/60 ));
wh.save([folderpath,experiment_name,'_wh']);
if rop_atten == 0
figure(10)
hold on
col = linspecer(8);
scatter(fsym.*1e-9,ber_ffe,30,'o','MarkerEdgeColor',col(M,:),'LineWidth',2);
xlim([wh.parameter.fsym.values(1) wh.parameter.fsym.values(end)].*1e-9);
yline(3.8e-3, 'DisplayName', 'HD-FEC', 'LineStyle', '--', 'HandleVisibility', 'off');
xlabel('Received Optical Power (dBm)');
ylabel('Bit Error Rate (BER)');
title('Bit Error Rate vs. ROP');
set(gca, 'yscale', 'log');
set(gca, 'Box', 'on');
grid on;
grid minor;
legend('Interpreter', 'none');
end
end
end
end
close(hWaitbar);
wh.save([folderpath,experiment_name,'_wh_final']);
autoArrangeFigures(3,3,2)

View File

@@ -0,0 +1,165 @@
filename = "Z:\2024\sioe\High Speed Messungen Oktober\bias_5km\PAMX_5km_20241025_204334_wh.mat";
a = load(filename);
wh = a.obj;
v_bias_vals = wh.parameter.vbias.values;
awg_vpp_vals = wh.parameter.awg_vpp.values;
precomp_amp_max_vals = wh.parameter.precomp_amp_max.values;
rop_atten_vals = wh.parameter.rop_atten.values;
lambda_vals = wh.parameter.lambda.values;
M_vals = wh.parameter.M.values;
fsym_vals = [168e9, 144e9, 120e9];
ber_ffe = [];
ber_mlse = [];
rop_measured = [];
pd_in_measured = [];
rop_measured = [];
cnt = 0;
figure(252)
clf
hold on
cols = cbrewer2('Set1',3);
for l = 1:numel(lambda_vals)
figure()
for m = 1:numel(M_vals)
ber_ffe = wh.getStoValue('ber_ffe',v_bias_vals,awg_vpp_vals(1),precomp_amp_max_vals(1),rop_atten_vals(1),M_vals(m),lambda_vals(l));
ber = wh.getStoValue('ber_ffe',v_bias_vals,awg_vpp_vals(1),precomp_amp_max_vals(1),rop_atten_vals(1),M_vals(m),lambda_vals(l));
exfo = wh.getStoValue('exfo',v_bias_vals,awg_vpp_vals(1),precomp_amp_max_vals(1),rop_atten_vals(1),M_vals(m),lambda_vals(l));
lb = wh.getStoValue('exfo',v_bias_vals,awg_vpp_vals(1),precomp_amp_max_vals(1),rop_atten_vals(1),M_vals(m),lambda_vals(l));
for e = 1:numel(exfo)
laser_pow(e) = exfo{e}.cur_power;
end
rop_measured = wh.getStoValue('rop',v_bias_vals,awg_vpp_vals(1),precomp_amp_max_vals(1),rop_atten_vals(1),M_vals(m),lambda_vals(l));
pd_in_measured(l,m,:) = wh.getStoValue('pd_in',v_bias_vals,awg_vpp_vals(1),precomp_amp_max_vals(1),rop_atten_vals(1),M_vals(m),lambda_vals(l));
rx_logbook = wh.getStoValue('rx_logbook',v_bias_vals(1),awg_vpp_vals(1),precomp_amp_max_vals(1),rop_atten_vals(1),M_vals(1),lambda_vals(1));
hold on
a = scatter(v_bias_vals,min(ber,[],2),40,'LineWidth',2,'Marker','.','DisplayName',['PAM ',num2str(M_vals(m))],'MarkerEdgeColor',cols(m,:));
title([num2str(lambda_vals(l)),'nm'])
a.DataTipTemplate.DataTipRows(1).Label = 'Vbias';
a.DataTipTemplate.DataTipRows(2).Label = 'BER';
a.DataTipTemplate.DataTipRows(2).Format ='%.1e';
a.DataTipTemplate.DataTipRows(3).Label = 'P_{out}';
a.DataTipTemplate.DataTipRows(3).Value = rop_measured;
a.DataTipTemplate.DataTipRows(3).Format = ['auto'];
a.DataTipTemplate.DataTipRows(4).Label = 'Baudr';
a.DataTipTemplate.DataTipRows(4).Value = repmat(fsym_vals(m).*1e-9,size(ber_ffe));
a.DataTipTemplate.DataTipRows(4).Format = ['%d',' GBd'];
a.DataTipTemplate.DataTipRows(5).Label = 'L_{out}';
a.DataTipTemplate.DataTipRows(5).Value = laser_pow;
a.DataTipTemplate.DataTipRows(5).Format = ['auto'];
% Polynomial fit (e.g., second-order polynomial)
[woutliers,n] = rmoutliers( min(ber,[],2) );
p = polyfit( v_bias_vals(~n), log10(woutliers), 3); % Adjust order as needed
BER_fit = polyval(p, v_bias_vals);
% Plot the fitted curve
plot(v_bias_vals, 10.^(BER_fit), '-r', 'LineWidth', 1.5,'Color',cols(m,:),'HandleVisibility','off');
% Continue with the rest of your plot settings
yline(3.8e-3, 'DisplayName', 'HD-FEC', 'LineStyle', '--', 'HandleVisibility', 'off');
xlabel('Bias Voltage');
ylabel('Bit Error Rate (BER)');
sgtitle('Bit Error Rate vs. ROP');
set(gca, 'yscale', 'log');
set(gca, 'Box', 'on');
grid on;
grid minor;
legend('Interpreter', 'none');
ylim([1e-3,0.5]);
xlim([-16, -2]);
ylim([1e-3,0.5]);
xlim([min(v_bias_vals) max(v_bias_vals)]);
end
end
%%
filename = "Z:\2024\sioe\High Speed Messungen Oktober\bias_testing_and_b2b\PAM4_b2b_bias_sweep_20241023_191202_wh_BB_BIAS_FINAL.mat";
a = load(filename);
wh = a.obj;
v_bias_vals = wh.parameter.vbias.values;
awg_vpp_vals = wh.parameter.awg_vpp.values;
precomp_amp_max_vals = wh.parameter.precomp_amp_max.values;
rop_atten_vals = wh.parameter.rop_atten.values;
M_vals = wh.parameter.M.values;
ber_ffe = [];
ber_mlse = [];
rop_measured = [];
pd_in_measured = [];
figure(2024)
for i = 1:3
ber_ffe(i,:) = wh.getStoValue('ber_ffe',v_bias_vals,awg_vpp_vals(1),precomp_amp_max_vals(1),rop_atten_vals(1),M_vals(i));
rop_measured(i,:) = wh.getStoValue('rop',v_bias_vals,awg_vpp_vals(1),precomp_amp_max_vals(1),rop_atten_vals(1),M_vals(i));
[bestber,bestindex] = min(ber_ffe(i,:),[],'all');
[awg_pos,v_bias_pos]=ind2sub(size(ber_ffe(i,:)),bestindex);
bestawgvpp=awg_vpp_vals(awg_pos);
bestvbias=v_bias_vals(v_bias_pos);
disp(['Best Vpp: ',num2str(bestvbias),' V; Best Vpp AWG: ',num2str(bestawgvpp),' V' ]);
% Polynomial fit (e.g., second-order polynomial)
[woutliers,n] = rmoutliers( ber_ffe(i,:) );
p = polyfit( v_bias_vals(~n), log10(woutliers), 8); % Adjust order as needed
BER_fit = polyval(p, v_bias_vals);
% Plot the fitted curve
plot(v_bias_vals, 10.^(BER_fit), '-r', 'LineWidth', 1.5,'Color',cols(i,:),'HandleVisibility','off');
hold on
a = scatter(v_bias_vals,ber_ffe(i,:),'Marker','+','DisplayName',['PAM ',num2str(wh.parameter.M.values(i))],'MarkerEdgeColor',cols(i,:));
a.DataTipTemplate.DataTipRows(1).Label = 'Vbias';
a.DataTipTemplate.DataTipRows(2).Label = 'BER';
a.DataTipTemplate.DataTipRows(2).Format ='%.1e';
a.DataTipTemplate.DataTipRows(3).Label = 'P_{out}';
a.DataTipTemplate.DataTipRows(3).Value = rop_measured(i,:);
a.DataTipTemplate.DataTipRows(3).Format = 'auto';
end
% Continue with the rest of your plot settings
yline(3.8e-3, 'DisplayName', 'HD-FEC', 'LineStyle', '--', 'HandleVisibility', 'off');
xlabel('Bias Voltage');
ylabel('Bit Error Rate (BER)');
title('Bit Error Rate vs. ROP | MI->DO | B2B');
set(gca, 'yscale', 'log');
set(gca, 'Box', 'on');
grid on;
grid minor;
legend('Interpreter', 'none');
ylim([1e-4,0.5]);
xlim([1.6 3.2]);

View File

@@ -0,0 +1,547 @@
folderpath = 'C:\Users\sioe\Documents\High_Speed_Measurement_2024\bias_5km\';
experiment_name = 'PAMX_5km_';
currentTime = datetime('now', 'Format', 'yyyyMMdd_HHmmss');
timeStr = char(currentTime);
experiment_name = [experiment_name, timeStr];
ffe_only = 0;
postfilter_approach = 0;
db_channel_approach = 1;
db_coding_approach = 0;
db_precode = db_coding_approach || db_channel_approach;
%%% SIR Sweep for MPI Experiment %%%
params = struct;
% params.vbias = [1.7:0.02:3.2]; % PAM6=2.3V %PAM8=2.68V
% params.awg_vpp = [2.7];
% params.precomp_amp_max = [5];
% params.rop_atten = [0];
% params.M = [4,6,8];
% params.lambda = [1293,1310,1327.4]; %calcWavelengthPlan(16, 400e9 , 1310);
params.vbias = [2.3]; %PAM4=2.3 V PAM6=2.3V %PAM8=2.6V
params.awg_vpp = [2.7];
params.precomp_amp_max = [-50];
params.rop_atten = [0];
params.M = [4];
params.lambda = [1310]; %calcWavelengthPlan(16, 400e9 , 1310);
params.rcalpha = [0.05];
wh = DataStorage(params);
wh.addStorage("ber_collect");
wh.addStorage("ber_ffe");
wh.addStorage("ber_mlse");
wh.addStorage("ber_db");
wh.addStorage("pd_in");
wh.addStorage("rop");
wh.addStorage("m");
wh.addStorage("rx_logbook");
wh.addStorage("dcs");
wh.addStorage("pdfa");
wh.addStorage("exfo");
precomp_path = "C:\Users\sioe\Documents\High_Speed_Measurement_2024\precomp\";
precomp_fn = "lab_high_speed";
precomp_mode = 2; %0=do nothing ; 1= measure; 2=precomp active
precomp_amp_max = -34;
random_key = 2;
pd_in_set = 8;
looptotal = prod(wh.dim);
disp(['Start Measurement of ',num2str(looptotal),' loops...'])
iterationTimes = zeros(looptotal, 1); % Preallocate for speed
if ~exist('hWaitbar', 'var') || ~isvalid(hWaitbar)
hWaitbar = waitbar(0, sprintf('Starting %d measurements',looptotal), 'Name', 'Processing Progress');
else
waitbar(0, hWaitbar, sprintf('Starting %d measurements',looptotal));
end
loopcnt = 0;
estimatedTimeRemaining = 0;
estimatedTotalTime = 0;
for rcalpha = wh.parameter.rcalpha.values
for lambda = wh.parameter.lambda.values
exfo = Exfo_laser("serialport_number",'COM8','mainframe_channel',1,'safety_mode',0);
pdfa = Thor_PDFA("safety_mode",0);
exfo.getLaserInfo;
if ~(exfo.cur_wavelength == lambda)
% 1)
pdfa.disablePDFA;
% 2)
exfo.setWavelength(lambda);
% 3)
pdfa.enablePDFA();
% 4)
pdfa.setPumpLevel(100);
end
% 5) SET to first vbias and wait 30 minutes
v_bias_first = wh.parameter.vbias.values(1);
dcs = DC_supply("active",[1,0],"voltage",[v_bias_first, 0]);
dcs.set("voltage",[v_bias_first, 0]);
dcs.readVals();
% pause(30*60); %wait 30 minutes for stable bias
for v_bias = wh.parameter.vbias.values
for rop_atten = wh.parameter.rop_atten.values
for precomp_amp_max = wh.parameter.precomp_amp_max.values
for M = wh.parameter.M.values
for awg_vpp = wh.parameter.awg_vpp.values
iterationStartTime = tic;
loopcnt = loopcnt+1;
if M == 4
fsym = 220e9;
pulsef = 0;
elseif M == 6
fsym = 180e9;
pulsef = 0;
elseif M == 8
fsym = 160e9;
pulsef = 0;
end
%%%%% Loop Preps
%fsym = round(targetrate/log2(M));
loop_name = ['_fsym_',num2str(fsym)];
%%%%% SET Voltages %%%%%%
dcs = DC_supply("active",[1,0],"voltage",[v_bias, 0]);
dcs.set("voltage",[v_bias, 0]);
%%%%% SET Attenuator %%%%%%
voa = OptAtten("active",[1,2,1,1],"value",[rop_atten,pd_in_set,0,0],"wavelength",[1310,1310,1310,1310],"speed",[1000,100,1000,1000]);
voa.set('active',[1,2,1,1],'value',[rop_atten,pd_in_set,0,0]);
% voa.readvals();
%%%%% Construct AWG and Scope Modules %%%%%%
fdac = 256e9;
fadc = 256e9;
SCP = ScopeKeysight("model","UXR1104B",'autoscale',1,"fadc","GSa_256","channel",[0,1,0,0],"recordLen",3000000,"removeDC",1);
AWG = AwgKeysight("model","M8199B","fdac",fdac,"scaletodac",[1,1],"skews",[0,0],"voltages",[0,awg_vpp]);
A2S = Awg2Scope(AWG,SCP,[0,2,0,0],"waitUntilClick",0); %
%%%%% Symbol Generation %%%%%%
Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rrc","pulselength",16,"rrcalpha",rcalpha);
[Digi_sig,Symbols,Bits] = PAMsource(...
"fsym",fsym,"M",M,"order",19,"useprbs",1,...
"fs_out",fdac,...
"applyclipping",0,"clipfactor",1.5,...
"applypulseform",pulsef,"pulseformer",Pform,...
"randkey",random_key,...
"db_precode",db_precode,"db_encode",db_coding_approach,...
"mrds_code",0,"mrds_blocklength",512).process();
Digi_sig.spectrum("displayname","Normal Tx","fignum",10,"normalizeToNyquist",0,"normalizeTo0dB",0);
%%%%% Precompensation Routine %%%%%%
if precomp_mode == 1 % measure channel
precomp_est = ChannelFreqResp("Nacq",1024,"Navg",64,"Ncp",63,'f_ref',fdac);
Digi_sig = precomp_est.buildOFDM();
elseif precomp_mode == 2 % apply precomp
precomp_est = ChannelFreqResp("Nacq",1024,"Navg",64,"Ncp",63,'f_ref',Digi_sig.fs);
Digi_sig = precomp_est.precomp(Digi_sig,'maxampdb',precomp_amp_max,'loadPath',precomp_path,'fileName',precomp_fn);
end
%%%%% Resample to DAC rate %%%%%%
Digi_sig = Digi_sig.resample("fs_out",AWG.fdac);
%%%%% Plot and Save Routine 1 %%%%%%%%%%%%%%%%%%%%%%%%%
Digi_sig.spectrum("displayname","Normal Tx","fignum",14,"normalizeToNyquist",0,"normalizeTo0dB",0);
% save([folderpath,[experiment_name,'_bits'],loop_name],"Bits");
% save([folderpath,[experiment_name,'_symbols'],loop_name],"Symbols");
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%% AWG --> Scope %%%%%%
[~,Scpe_sig_raw,~,D] = A2S.process("signal2",Digi_sig,"waitUntilClick",0);
Scpe_sig_raw.spectrum("displayname","Scope PSD","fignum",20,"normalizeTo0dB",1);
Scpe_sig_raw.plot("displayname","Scope raw signal","fignum",29,"clear",1);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%% Sample to 2x fsym %%%%%%
Scpe_sig_resampled = Scpe_sig_raw.resample("fs_in",fadc,"fs_out",2*fsym);
%%%%% Precompensation Routine %%%%%%
if precomp_mode == 1
precomp_est.estimate(Scpe_sig_resampled,"save",true,"savePath",precomp_path,"fileName",precomp_fn);
precomp_est.plot();
end
voa.readvals();
rop = voa.power_state(1);
pd_in = voa.power_state(2);
disp(['ROP: ',num2str(rop),' dBm || PD in: ',num2str(pd_in), ' dBm']);
%%%%%% Sync Rx signal with reference (S is a cell array with all occurences) %%%%%%
[Scpe_sig_syncd,S,isFlipped] = Scpe_sig_resampled.tsynch("reference",Symbols,"fs_ref",fsym);
%%%%%% SNR CHEAT - Avges the measured signal occurences found after correlation in "tsynch" %%%%%%
average_signals = 0;
if average_signals
Scpe_sig_avg = Scpe_sig_syncd;
scope_mean = zeros(size(S{1}.signal));
for n=1:numel(S)
scope_mean = scope_mean + S{n}.signal;
end
scope_mean = scope_mean ./ n;
Scpe_sig_avg.signal = scope_mean;
Scpe_sig_avg.spectrum("displayname","Scope PSD","fignum",20,"normalizeTo0dB",1);
Scpe_sig_avg.plot("displayname","Scope raw signal","fignum",27,"clear",1);
Scpe_sig_avg.eye(fsym,M,"fignum",41,"displayname",' Eye of AVG Signal');
end
% Optfilter = Filter('filtdegree',6,"f_cutoff",100e9,"fs",Scpe_sig_avg.fs,"filterType",filtertypes.gaussian,"active",true);
% Scpe_sig_syncd = Optfilter.process(Scpe_sig_syncd);
% Scpe_sig_syncd.spectrum("displayname","Scope PSD","fignum",20,"normalizeTo0dB",1);
%%%%% Plot and Save Routines: SAVE RECEIVED SIGNALS %%%%%%%%%%%%%%%%%%%%%%%%%
% save([folderpath,experiment_name,'_rx_signal',loop_name],"S");
Scpe_sig_syncd.eye(fsym,M,"fignum",40,"displayname",' after Scope');
%%%%% EQUALIZE %%%%%%
Eq = FFE("epochs_tr",5,"epochs_dd",5,"len_tr",4096*2,"mu_dd",1e-4,"mu_tr",0,"order",50,"sps",2,"decide",0);
% Eq = VNLE("epochs_tr",5,"epochs_dd",5,"len_tr",4096*2,"mu_dd",[0.0004 0.0005 0.0006],"mu_tr",0,"order",[50,7,7],"sps",2,"decide",1);
Eq = EQ("Ne",[50,7,7],"Nb",[0,0,0],"training_length",4096*2,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.05,"DDmu",[0.0004 0.0004 0.0004 0.0004 ],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
% set to minus one not zero not avoid confusion if BER is acutally zero
ber_ffe = -1;
ber_mlse = -1;
ber_db = -1;
if ffe_only %%%%%%%%%%%%%%%%%%%%%%%%%%%
ber = [];
parfor i = 1:numel(S)
[EQ_sig] = Eq.process(S{i},Symbols);
% EQ_sig.plot("fignum",50,"displayname",'After EQ');
Rx_bits = PAMmapper(M,0).demap(EQ_sig);
[~,errors_bm,ber(i),errors] = calc_ber(Rx_bits.signal,Bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
% disp(['FFE: ',sprintf('%.1E',ber(i)),'| ROP: ',num2str(rop),' dB | PD_in: ',num2str(pd_in),' dBm']);
end
disp(['FFE EQ: BEST BER: ',sprintf('%.1E',min(ber)),' AVG BER: ',sprintf('%.1E',mean(ber)),' WORST:',sprintf('%.1E',max(ber)),'. Out of ',num2str(numel(ber))]);
try
ber_ffe = mean(rmoutliers(ber));
catch
ber_ffe = min(ber);
end
if 0
EQ_sig.plot("fignum",50,"displayname",'After EQ','clear',1);
figure(56);
clf
title(sprintf('PAM %d ; BER: %1.2e',M, ber_ffe));
constellation = unique(Symbols.signal);
received = NaN(numel(constellation),length(Symbols));
for lvl = 1:numel(constellation)
%Separate the equalized signal into the
%respective levels based on the actually
%transmitted level!
received(lvl,Symbols.signal==constellation(lvl)) = EQ_sig.signal(Symbols.signal==constellation(lvl));
intermediate = received(lvl,:);
cnt(lvl) = numel(intermediate(~isnan(intermediate)));
hold on
histogram(received(lvl,:),1000,"EdgeAlpha",0,'DisplayName',['Lvl ',num2str(lvl),' | ',num2str(cnt(lvl)),' entries']);
end
legend
end
elseif postfilter_approach %%%%%%%%%%%%%%%%%%%%%%%%%%%
ber_vnle = [];
ber_vnle_mlse = [];
ber_ffe_mlse =[];
ber_ffe = [];
parfor s = 1:numel(S)
if 1
%FFE LINEAR
Eq = EQ("Ne",[50,0,0],"Nb",[0,0,0],"training_length",4096*2,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.05,"DDmu",[0.0004 0.0004 0.0004 0.0004 ],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
Scpe_sig_syncd = S{s};
[EQ_ffe] = Eq.process(Scpe_sig_syncd,Symbols);
Noi = EQ_ffe-Symbols;
Rx_bits = PAMmapper(M,0).demap(EQ_ffe);
[~,num_errors,ber_ffe(s),pos_errors] = calc_ber(Rx_bits.signal,Bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
end
if 1
%FFE + MLSE
nc = 2;
burg_coeff = arburg(Noi.signal,nc);
EQ_ffe = EQ_ffe.filter(burg_coeff,1);
EQ_mlse = MLSE("DIR",burg_coeff,"duobinary_output",0,"M",M,"trellis_states",PAMmapper(M,0).levels).process(EQ_ffe);
Rx_bits = PAMmapper(M,0).demap(EQ_mlse);
[~,num_errors,ber_ffe_mlse(s),pos_errors] = calc_ber(Rx_bits.signal,Bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
end
%VNLE
Eq = EQ("Ne",[50,7,7],"Nb",[0,0,0],"training_length",4096*2,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.05,"DDmu",[0.0004 0.0004 0.0004 0.0004 ],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
Scpe_sig_syncd = S{s};
[EQ_vnle] = Eq.process(Scpe_sig_syncd,Symbols);
Noi = EQ_vnle-Symbols;
Rx_bits = PAMmapper(M,0).demap(EQ_vnle);
[~,num_errors,ber_vnle(s),pos_errors] = calc_ber(Rx_bits.signal,Bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
%VNLE + MLSE
if 0
nc = 2;
burg_coeff = arburg(Noi.signal,nc);
EQ_mlse = EQ_vnle.filter(burg_coeff,1);
EQ_mlse = MLSE("DIR",burg_coeff,"duobinary_output",0,"M",M,"trellis_states",PAMmapper(M,0).levels).process(EQ_mlse);
Rx_bits = PAMmapper(M,0).demap(EQ_mlse);
[~,num_errors,ber_vnle_mlse(s),pos_errors] = calc_ber(Rx_bits.signal,Bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
end
end
disp(['FFE EQ: BEST BER: ',sprintf('%.1E',min(ber_ffe)),' AVG BER: ',sprintf('%.1E',mean(ber_ffe)),' WORST:',sprintf('%.1E',max(ber_ffe)),'. Out of ',num2str(numel(ber_ffe))]);
disp(['FFE + MLSE EQ: BEST BER: ',sprintf('%.1E',min(ber_ffe_mlse)),' AVG BER: ',sprintf('%.1E',mean(ber_ffe_mlse)),' WORST:',sprintf('%.1E',max(ber_ffe_mlse)),'. Out of ',num2str(numel(ber_ffe_mlse))]);
disp(['VNLE EQ: BEST BER: ',sprintf('%.1E',min(ber_vnle)),' AVG BER: ',sprintf('%.1E',mean(ber_vnle)),' WORST:',sprintf('%.1E',max(ber_vnle)),'. Out of ',num2str(numel(ber_vnle))]);
% disp(['VNLE+MLSE EQ: BEST BER: ',sprintf('%.1E',min(ber_vnle_mlse)),' AVG BER: ',sprintf('%.1E',mean(ber_vnle_mlse)),' WORST:',sprintf('%.1E',max(ber_vnle_mlse)),'. Out of ',num2str(numel(ber_ffe))]);
if 0
window = 100;
Noi_ = Noi;
Noi.signal = Noi.signal - movmean(Noi.signal,[floor(window/2),ceil(window/2)]);
EQ_vnle.spectrum('displayname','EQ out PSD','fignum',123);
Noi.spectrum('displayname','Noise PSD','fignum',123);
nc = 1;
burg_coeff = arburg(Noi.signal,nc);
[h,w] = freqz(1,burg_coeff,length(Noi),"whole",Noi.fs);
h = h/max(abs(h));
hold on
w_ = (w - Noi.fs/2);
plot(w_.*1e-9,20*log10(fftshift(h)),'DisplayName',['', num2str(nc), ' coefficients for burg alg.']);
end
if 0
figure(57);
clf
title(sprintf('PAM %d ; BER: %1.2e',M, ber_ffe));
constellation = unique(Symbols.signal);
received = NaN(numel(constellation),length(Symbols));
for lvl = 1:numel(constellation)
%Separate the equalized signal into the
%respective levels based on the actually
%transmitted level!
received(lvl,Symbols.signal==constellation(lvl)) = EQ_vnle.signal(Symbols.signal==constellation(lvl));
intermediate = received(lvl,:);
cnt(lvl) = numel(intermediate(~isnan(intermediate)));
hold on
histogram(received(lvl,:),1000,"EdgeAlpha",0,'DisplayName',['Lvl ',num2str(lvl),' | ',num2str(cnt(lvl)),' entries']);
end
legend
end
% disp(['FFE: ',sprintf('%.1E',ber_ffe),' -> PF -> MLSE: ',sprintf('%.1E',ber_mlse),' dB | PD_in: ',num2str(pd_in),' dBm']);
elseif db_channel_approach %%%%%%%%%%%%%%%%%%%%%%%%%%%
parfor s = 1:numel(S)
Scpe_sig_syncd = S{s};
[EQ_sig, Noi] = Eq.process(Scpe_sig_syncd,Duobinary().encode(Symbols));
% EQ_sig.plot("fignum",50,"displayname",'After EQ','clear',1);
EQ_sig = MLSE("DIR",[1,1],"duobinary_output",1,"M",M,"trellis_states",PAMmapper(M,0).levels).process(EQ_sig);
EQ_sig = Duobinary().decode(EQ_sig);
Rx_bits = PAMmapper(M,0).demap(EQ_sig);
[~,num_errors,ber_db(s),pos_errors] = calc_ber(Rx_bits.signal,Bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
%disp([' DB Precode -> Channel -> FFE -> Decode/ Mod ',sprintf('%.1E',ber_db(s)),' | PD_in: ',num2str(pd_in),' dBm']);
end
disp(['DB EQ: BEST BER: ',sprintf('%.1E',min(ber_db)),' AVG BER: ',sprintf('%.1E',mean(ber_db)),' WORST:',sprintf('%.1E',max(ber_db)),'. Out of',num2str(numel(ber_db))]);
ber = min(ber_db);
elseif db_coding_approach %%%%%%%%%%%%%%%%%%%%%%%%%%%
[EQ_sig, Noi] = Eq.process(Scpe_sig_syncd,Symbols);
EQ_sig = MLSE("DIR",[1,1],"duobinary_output",1,"M",M,"trellis_states",PAMmapper(M,0).levels).process(EQ_sig);
EQ_sig = Duobinary().decode(EQ_sig);
Rx_bits = PAMmapper(M,0).demap(EQ_sig);
[~,errors_bm,ber_db,errors] = calc_ber(Rx_bits.signal,Bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
EQ_sig.plot("fignum",50,"displayname",'After EQ');
disp([' DB Precode -> DB Code -> Channel -> FFE -> Decode/ Mod ',sprintf('%.1E',ber_db),' | PD_in: ',num2str(pd_in),' dBm']);
end
%%%%% Store measurement into measurement "warehouse" %%%%%%
wh.addValueToStorage(ber,'ber_collect',v_bias,awg_vpp,precomp_amp_max,rop_atten,M,lambda,rcalpha);
wh.addValueToStorage(ber_ffe,'ber_ffe',v_bias,awg_vpp,precomp_amp_max,rop_atten,M,lambda,rcalpha);
wh.addValueToStorage(ber_mlse,'ber_mlse',v_bias,awg_vpp,precomp_amp_max,rop_atten,M,lambda,rcalpha);
wh.addValueToStorage(ber_db,'ber_db',v_bias,awg_vpp,precomp_amp_max,rop_atten,M,lambda,rcalpha);
wh.addValueToStorage(rop,'rop',v_bias,awg_vpp,precomp_amp_max,rop_atten,M,lambda,rcalpha);
wh.addValueToStorage(pd_in,'pd_in',v_bias,awg_vpp,precomp_amp_max,rop_atten,M,lambda,rcalpha);
% Rx_bits.logbook.SignalCopy = [];
% wh.addValueToStorage(Rx_bits,'rx_logbook',v_bias,awg_vpp,precomp_amp_max,rop_atten,M,lambda,rcalpha);
wh.addValueToStorage(M,'m',v_bias,awg_vpp,precomp_amp_max,rop_atten,M,lambda,rcalpha);
wh.addValueToStorage(dcs,'dcs',v_bias,awg_vpp,precomp_amp_max,rop_atten,M,lambda,rcalpha);
wh.addValueToStorage(pdfa,'pdfa',v_bias,awg_vpp,precomp_amp_max,rop_atten,M,lambda,rcalpha);
wh.addValueToStorage(exfo,'exfo',v_bias,awg_vpp,precomp_amp_max,rop_atten,M,lambda,rcalpha);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%% Plot stuff into Table (feel free to add own values in -> 'name',value <- notation. Must be closed when table is changed)%%%%%%%%%%%%%%%%%%%%%%
% showCurrentMeasurement('BER', min(ber_vnle),'BER',mean(ber_vnle),'Alpha',rcalpha, 'Fsym',fsym.*1e-9, 'ROP', rop,'pulsef',pulsef,'rrcalpha',rrcalpha, 'PAM',M, 'Vbias', v_bias, 'AWG Vpp', awg_vpp, 'Precomp MaxAmp',precomp_amp_max);
%%%%% Arrange Figures %%%%%%%%%%%%%%%%%%%%%%
autoArrangeFigures(3,3,2);
iterationTimes(loopcnt) = toc(iterationStartTime);
averageTimePerIteration = mean(iterationTimes(1:loopcnt));
estimatedTotalTime = averageTimePerIteration * looptotal;
estimatedTimeRemaining = estimatedTotalTime - sum(iterationTimes(1:loopcnt));
progressFraction = loopcnt / looptotal;
waitbar(progressFraction, hWaitbar, ...
sprintf('Loop: %d of %d \n Runtime: %.1f min | %.1f sec per Loop |Time to go: %.1f min ', ...
loopcnt, looptotal, sum(iterationTimes(1:loopcnt))/60, averageTimePerIteration, estimatedTimeRemaining/60 ));
wh.save([folderpath,experiment_name,'_wh']);
end
end
end
end
end
end
end
close(hWaitbar);
wh.save([folderpath,experiment_name,'_wh']);
% autoArrangeFigures(3,3,2)
%%% LAMBDA PLOT
if 0
lambda_vals = wh.parameter.lambda.values;
ber_ffe = wh.getStoValue('ber_ffe',v_bias,awg_vpp,precomp_amp_max,rop_atten,M,lambda_vals);
ber_mlse = wh.getStoValue('ber_mlse',v_bias,awg_vpp,precomp_amp_max,rop_atten,M,lambda_vals);
rop_measured = wh.getStoValue('rop',v_bias,awg_vpp,precomp_amp_max,rop_atten,M,lambda_vals);
pd_in_measured = wh.getStoValue('pd_in',v_bias,awg_vpp,precomp_amp_max,rop_atten,M,lambda_vals);
figure(240);
hold on
legendname = ['5 km Fsym:',num2str(fsym.*1e-9),' GBd | PAM',num2str(M),' | PD: ',num2str(pd_in_set),'| Vbias: ', num2str(v_bias),'V | '];
ffeLine = plot(lambda_vals, ber_ffe, "LineWidth", 0.5, "LineStyle", "-", "Marker", ".", "MarkerSize", 15, "DisplayName", [legendname,' + VNLE']);
% Continue with the rest of your plot settings
yline(3.8e-3, 'DisplayName', 'HD-FEC', 'LineStyle', '--', 'HandleVisibility', 'off');
xlabel('Wavelength in nm');
ylabel('Bit Error Rate (BER)');
title('Bit Error Rate vs. ROP');
set(gca, 'yscale', 'log');
set(gca, 'Box', 'on');
grid on;
grid minor;
legend('Interpreter', 'none');
end
%%% ROP PLOT
if 0
rop_vals = wh.parameter.rop_atten.values;
ber_ffe = wh.getStoValue('ber_ffe',v_bias,awg_vpp,precomp_amp_max,rop_vals,M);
ber_mlse = wh.getStoValue('ber_mlse',v_bias,awg_vpp,precomp_amp_max,rop_vals,M);
rop_measured = wh.getStoValue('rop',v_bias,awg_vpp,precomp_amp_max,rop_vals,M);
pd_in_measured = wh.getStoValue('pd_in',v_bias,awg_vpp,precomp_amp_max,rop_vals,M);
legendname = ['Thormax: ',num2str(fsym.*1e-9),' GBd | PAM',num2str(M),' | PD: ',num2str(pd_in_set),'| Vbias: ', num2str(v_bias),'V | '];
figure(230);
hold on; % Retain the plot so new points can be added without complete redraw
% Plot the data and get the line handle
ffeLine = plot(rop_measured, ber_ffe, "LineWidth", 0.5, "LineStyle", "-", "Marker", ".", "MarkerSize", 15, "DisplayName", [legendname,' + FFE']);
mlseLine = plot(rop_measured, ber_mlse, "LineWidth", 0.5, "LineStyle", "-", "Marker", ".", "MarkerSize", 15, "DisplayName", [legendname,' +MLSE']);
% Store pd_in_measured in the ZData property
ffeLine.ZData = pd_in_measured;
% Customize the data tips
% Set labels for existing data tip rows
ffeLine.DataTipTemplate.DataTipRows(1).Label = 'ROP';
ffeLine.DataTipTemplate.DataTipRows(2).Label = 'FFE';
ffeLine.DataTipTemplate.DataTipRows(2).Format = '%.2e'; % Format BER as "3e-4"
% Add a new data tip row for PDin
pdinRow = dataTipTextRow('PDin', 'ZData');
ffeLine.DataTipTemplate.DataTipRows(3) = pdinRow;
% Store pd_in_measured in the ZData property
mlseLine.ZData = pd_in_measured;
% Customize the data tips
% Set labels for existing data tip rows
mlseLine.DataTipTemplate.DataTipRows(1).Label = 'ROP';
mlseLine.DataTipTemplate.DataTipRows(2).Label = 'MLSE';
mlseLine.DataTipTemplate.DataTipRows(2).Format = '%.2e'; % Format BER as "3e-4"
% Add a new data tip row for PDin
pdinRow = dataTipTextRow('PDin', 'ZData');
mlseLine.DataTipTemplate.DataTipRows(3) = pdinRow;
% Continue with the rest of your plot settings
yline(3.8e-3, 'DisplayName', 'HD-FEC', 'LineStyle', '--', 'HandleVisibility', 'off');
xlabel('Received Optical Power (dBm)');
ylabel('Bit Error Rate (BER)');
title('Bit Error Rate vs. ROP');
set(gca, 'yscale', 'log');
set(gca, 'Box', 'on');
grid on;
grid minor;
legend('Interpreter', 'none');
end

View File

@@ -0,0 +1,186 @@
basePath = 'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\';
database = DBHandler("dataBase",[basePath,'silas_labor.db'],"type",'sqlite');
filterParams = database.tables;
filterParams.Configurations = struct( ...
'bitrate', [390e9], ... %[224,336,360,390,420,448]
'db_mode', 1, ...
'fiber_length', 1, ...
'interference_attenuation', [], ...
'interference_path_length', [], ...
'is_mpi', 0, ...
'pam_level', 4, ...
'rop_attenuation', 0, ...
'wavelength', 1310 ...
);
% filterParams.EqualizerParameters.diff_precode = int32(db_mode.db_encoded);
% filterParams.EqualizerParameters.equalizer_structure = int32(equalizer_structure.vnle);
% filterParams.EqualizerParameters.DCmu = 0.00;
selectedFields = {'Configurations.run_id' 'Runs.rx_raw_path' 'Configurations.bitrate' 'Configurations.symbolrate' 'Configurations.pam_level'...
'Configurations.db_mode' 'Configurations.rop_attenuation' 'Configurations.is_mpi' 'Configurations.interference_attenuation' ...
'EqualizerParameters.equalizer_structure' 'EqualizerParameters.diff_precode' 'EqualizerParameters.eq_id' 'EqualizerParameters.DCmu' 'Measurements.power_pd_in' ...
'Measurements.power_mpi_interference' 'Measurements.power_mpi_signal' 'Results.BER' 'Results.BER_precoded' 'Results.SNR' 'Results.GMI' 'Results.Alpha' 'Results.date_of_processing'};
[dataTable,sql_query] = database.queryDB(filterParams, selectedFields);
fixedVars = {'eq_id','bitrate'};
dataTableGrpd = groupIt(fixedVars,dataTable);
plotRealizations = 0;
% Create a new figure
figure();
hold on
unique_eq = unique(dataTable.eq_id);
cols = linspecer(8);
for i = 1:numel(unique_eq)
idx = find(dataTableGrpd.eq_id == unique_eq(i), 1, 'first');
equalizer_ = equalizer_structure(dataTableGrpd.equalizer_structure(idx));
loop_filt = dataTableGrpd.eq_id==unique_eq(i);
% Plot LINE: BER vs. interference_attenuation
switch equalizer_
case equalizer_structure.vnle
bers = dataTableGrpd.BER(loop_filt,:);
case equalizer_structure.vnle_pf_mlse
bers = dataTableGrpd.BER(loop_filt,:);
case equalizer_structure.vnle_db_mlse
bers = dataTableGrpd.BER_precoded(loop_filt,:);
case equalizer_structure.db_encoded
bers = dataTableGrpd.BER(loop_filt,:);
end
name = sprintf('%s',equalizer_);
p = plot(dataTableGrpd.bitrate(loop_filt,:).*1e-9, bers, '-', 'LineWidth', 0.5,'Color',cols(i,:),'DisplayName',name);
pair_one = {'Run ID', dataTableGrpd.run_id(loop_filt,:)};
pair_two = {'Rate', dataTableGrpd.bitrate(loop_filt,:)};
addDatatips(p, pair_one, pair_two);
xticks(unique(dataTableGrpd.bitrate(loop_filt,:).*1e-9));
% Plot SCATTERS: BER vs. interference_attenuation
loop_filt = dataTable.eq_id==unique_eq(i);
if plotRealizations
switch equalizer_
case equalizer_structure.vnle
bers = dataTable.BER(loop_filt,:);
case equalizer_structure.vnle_pf_mlse
bers = dataTable.BER(loop_filt,:);
case equalizer_structure.vnle_db_mlse
bers = dataTable.BER_precoded(loop_filt,:);
case equalizer_structure.db_encoded
bers = dataTable.BER(loop_filt,:);
end
sc = scatter(dataTable.bitrate(loop_filt,:).*1e-9, bers, 'LineWidth', 0.5,'Marker','*','MarkerEdgeColor',cols(i,:),'HandleVisibility','off');
pair_one = {'Run ID', dataTable.run_id(loop_filt,:)};
pair_two = {'Rate', dataTable.bitrate(loop_filt,:)};
addDatatips(sc, pair_one, pair_two);
xticks(unique(dataTable.bitrate(loop_filt,:).*1e-9));
end
end
% Label the axes and add a title
xlabel('Bitrate in Gbps');
ylabel('BER');
title('Line Rate vs. BER');
yline(3.8e-3,'LineWidth',1,'LineStyle','--','HandleVisibility','off');
% Enable grid for better readability
grid on;
beautifyBERplot;
ylim([1e-4 0.5]);
function resultTable = groupIt(fixedVars,dataTable)
% Group by run_id and eq_id (adjust grouping keys as needed)
[G, groupKeys] = findgroups(dataTable(:, fixedVars));
% Preallocate a cell array for aggregated data.
varNames = dataTable.Properties.VariableNames;
nVars = numel(varNames);
aggData = cell(height(groupKeys), nVars);
groupCount = zeros(height(groupKeys), 1); % To store the size of each group
% Loop over each group.
for i = 1:height(groupKeys)
idx = (G == i); % Logical index for group i
groupCount(i) = sum(idx); % Count number of rows in this group
% For each variable in the table:
for j = 1:nVars
colData = dataTable.(varNames{j});
if isnumeric(colData)
% For numeric data, compute the mean.
aggData{i, j} = min(colData(idx));
else
% For non-numeric data, take the first entry.
if iscell(colData)
aggData{i, j} = colData{find(idx, 1)};
else
aggData{i, j} = colData(find(idx, 1));
end
end
end
end
% Convert the aggregated cell array into a table.
resultTable = cell2table(aggData, 'VariableNames', varNames);
% Append the group count as a new column.
resultTable.nRows = groupCount;
end
function addDatatips(sc, varargin)
% addDatatips Adds custom data tip rows to a scatter plot.
%
% addDatatips(sc, pair1, pair2, ...) adds one or more custom rows to the
% data tip display of the scatter plot identified by sc.
%
% Each pair should be provided as a 1x2 cell array: {label, value}.
% The value can be a scalar or a vector. If a vector is provided, its length
% must match the number of scatter plot points.
%
% Example:
% sc = scatter(x, y, 'LineWidth', 1.5, 'Marker', 'o');
% pair_one = {'Attenuation', attenuationVector};
% addDatatips(sc, pair_one);
numPoints = numel(sc.XData);
for k = 1:length(varargin)
pair = varargin{k};
if ~iscell(pair) || numel(pair) ~= 2
error('Each pair must be a 1x2 cell array: {label, value}.');
end
label = pair{1};
value = pair{2};
% If value is a vector, ensure its length is either 1 or equal to the number of scatter points.
if isvector(value) && numel(value) ~= 1 && numel(value) ~= numPoints
error('The vector for "%s" must be a scalar or have %d elements matching the scatter data points.', label, numPoints);
end
% Create a new data tip row using the provided label and vector.
newRow = dataTipTextRow(label, value);
sc.DataTipTemplate.DataTipRows(end+1) = newRow;
end
end

View File

@@ -0,0 +1,164 @@
basePath = 'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\';
database = DBHandler("pathToDB",[basePath,'silas_labor.db'],"type",'sqlite');
filterParams = database.tables;
filterParams.Configurations = struct( ...
'bitrate', 420e9, ... %[224,336,360,390,420,448]
'db_mode', int32(db_mode.no_db), ...
'fiber_length', 10, ...
'interference_attenuation', [], ...
'interference_path_length', [], ...
'is_mpi', 0, ...
'pam_level', 4, ...
'rop_attenuation', 0, ...
'wavelength', 1310 ...
);
% filterParams.EqualizerParameters.diff_precode = int32(db_mode.db_encoded);
% filterParams.EqualizerParameters.equalizer_structure = int32(equalizer_structure.vnle);
filterParams.EqualizerParameters.DCmu = 0.00;
selectedFields = {'Configurations.run_id' 'Runs.rx_raw_path' 'Configurations.bitrate' 'Configurations.symbolrate' 'Configurations.pam_level'...
'Configurations.db_mode' 'Configurations.rop_attenuation' 'Configurations.is_mpi' 'Configurations.interference_attenuation' ...
'EqualizerParameters.equalizer_structure' 'EqualizerParameters.diff_precode' 'EqualizerParameters.eq_id' 'Measurements.power_pd_in' ...
'Measurements.power_mpi_interference' 'Measurements.power_mpi_signal' 'Results.BER' 'Results.BER_precoded' 'Results.SNR' 'Results.GMI' 'Results.Alpha' 'Results.date_of_processing'};
[dataTable,sql_query] = database.queryDB(filterParams, selectedFields);
fixedVars = {'eq_id','bitrate'};
dataTableGrpd = groupIt(fixedVars,dataTable);
plotRealizations = 1;
% Create a new figure
figure();
hold on
unique_eq = unique(dataTable.eq_id);
cols = linspecer(8);
for i = 1:numel(unique_eq)
idx = find(dataTableGrpd.eq_id == unique_eq(i), 1, 'first');
equalizer_ = equalizer_structure(dataTableGrpd.equalizer_structure(idx));
% Plot SCATTERS: timestamp vs. interference_attenuation
loop_filt = dataTable.eq_id==unique_eq(i);
if plotRealizations
switch equalizer_
case equalizer_structure.vnle
bers = dataTable.BER(loop_filt,:);
case equalizer_structure.vnle_pf_mlse
bers = dataTable.BER(loop_filt,:);
case equalizer_structure.vnle_db_mlse
bers = dataTable.BER_precoded(loop_filt,:);
case equalizer_structure.db_encoded
bers = dataTable.BER(loop_filt,:);
end
date_of_proc = datetime(dataTable.date_of_processing(loop_filt,:));
sc = scatter(date_of_proc, bers, 'LineWidth', 0.5,'Marker','*','MarkerEdgeColor',cols(i,:),'HandleVisibility','off');
pair_one = {'Run ID', dataTable.run_id(loop_filt,:)};
pair_two = {'Rate', dataTable.bitrate(loop_filt,:)};
addDatatips(sc, pair_one, pair_two);
xticks(date_of_proc);
end
end
% Label the axes and add a title
xlabel('Time of Processing');
ylabel('BER');
title('Line Rate vs. BER');
yline(3.8e-3,'LineWidth',1,'LineStyle','--','HandleVisibility','off');
% Enable grid for better readability
grid on;
beautifyBERplot;
ylim([1e-4 0.5]);
function resultTable = groupIt(fixedVars,dataTable)
% Group by run_id and eq_id (adjust grouping keys as needed)
[G, groupKeys] = findgroups(dataTable(:, fixedVars));
% Preallocate a cell array for aggregated data.
varNames = dataTable.Properties.VariableNames;
nVars = numel(varNames);
aggData = cell(height(groupKeys), nVars);
groupCount = zeros(height(groupKeys), 1); % To store the size of each group
% Loop over each group.
for i = 1:height(groupKeys)
idx = (G == i); % Logical index for group i
groupCount(i) = sum(idx); % Count number of rows in this group
% For each variable in the table:
for j = 1:nVars
colData = dataTable.(varNames{j});
if isnumeric(colData)
% For numeric data, compute the mean.
aggData{i, j} = min(colData(idx));
else
% For non-numeric data, take the first entry.
if iscell(colData)
aggData{i, j} = colData{find(idx, 1)};
else
aggData{i, j} = colData(find(idx, 1));
end
end
end
end
% Convert the aggregated cell array into a table.
resultTable = cell2table(aggData, 'VariableNames', varNames);
% Append the group count as a new column.
resultTable.nRows = groupCount;
end
function addDatatips(sc, varargin)
% addDatatips Adds custom data tip rows to a scatter plot.
%
% addDatatips(sc, pair1, pair2, ...) adds one or more custom rows to the
% data tip display of the scatter plot identified by sc.
%
% Each pair should be provided as a 1x2 cell array: {label, value}.
% The value can be a scalar or a vector. If a vector is provided, its length
% must match the number of scatter plot points.
%
% Example:
% sc = scatter(x, y, 'LineWidth', 1.5, 'Marker', 'o');
% pair_one = {'Attenuation', attenuationVector};
% addDatatips(sc, pair_one);
numPoints = numel(sc.XData);
for k = 1:length(varargin)
pair = varargin{k};
if ~iscell(pair) || numel(pair) ~= 2
error('Each pair must be a 1x2 cell array: {label, value}.');
end
label = pair{1};
value = pair{2};
% If value is a vector, ensure its length is either 1 or equal to the number of scatter points.
if isvector(value) && numel(value) ~= 1 && numel(value) ~= numPoints
error('The vector for "%s" must be a scalar or have %d elements matching the scatter data points.', label, numPoints);
end
% Create a new data tip row using the provided label and vector.
newRow = dataTipTextRow(label, value);
sc.DataTipTemplate.DataTipRows(end+1) = newRow;
end
end

View File

@@ -0,0 +1,85 @@
wh = load('C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\highspeed_oct_2024\10km_bitrate_complete\20241030_170224_wh.mat');
wh = wh.obj;
M_vals = wh.parameter.M.values;
M_choose = M_vals(1);
lambda_vals = wh.parameter.lambda.values;
bitrate_vals = wh.parameter.bitrate.values;
duobinary_vals = wh.parameter.duobinary.values;
rop_atten_vals = wh.parameter.rop_atten.values;
figure(18)
tiledlayout(3, 3, 'TileSpacing', 'compact', 'Padding', 'compact');
%CHANGE PAM FORMAT HERE (use 4,6,8)
for M_choose = [8]
sgtitle(['PAM',num2str(M_choose)])
for l = 1:numel(lambda_vals)
ber_vnle = [];
ber_vnle_mlse= [];
ber_db= [];
ber_db_enc= [];
for b = 1:numel(bitrate_vals)
cel = wh.getStoValue('ber_vnle',M_choose(1),lambda_vals(l),bitrate_vals(b),duobinary_vals(1),rop_atten_vals(1));
ber_vnle(b)=min(cel{1});
cel = wh.getStoValue('ber_vnle_mlse',M_choose(1),lambda_vals(l),bitrate_vals(b),duobinary_vals(1),rop_atten_vals(1));
ber_vnle_mlse(b)=min(cel{1});
cel = wh.getStoValue('ber_db',M_choose(1),lambda_vals(l),bitrate_vals(b),duobinary_vals(2),rop_atten_vals(1));
ber_db(b)=min(cel{1});
cel = wh.getStoValue('ber_db',M_choose(1),lambda_vals(l),bitrate_vals(b),duobinary_vals(3),rop_atten_vals(1));
ber_db_enc(b)=min(cel{1});
dcs_ = wh.getStoValue('dcs',M_choose(1),lambda_vals(l),bitrate_vals(b),duobinary_vals(2),rop_atten_vals(1));
end
cols = linspecer(4);
%subplot(3,3,l)
nexttile;
if M_choose == 4
lst = '-';
mkr = 'o';
hv = 'on';
elseif M_choose == 6
lst = '-';
mkr = 'x';
hv = 'on';
elseif M_choose == 8
lst = '-';
mkr = 'diamond';
hv = 'on';
end
fsym_vals = floor( bitrate_vals*1e-9./log2(M_choose) );
hold on
plot(bitrate_vals*1e-9,ber_db,'Color',cols(1,:),'Marker',mkr,'MarkerFaceColor','auto','DisplayName','DB pre','LineStyle',lst,'HandleVisibility',hv,'LineWidth',1);
plot(bitrate_vals*1e-9,ber_db_enc,'Color',cols(2,:)','Marker',mkr,'MarkerFaceColor','auto','DisplayName','DB enc','LineStyle',lst,'HandleVisibility',hv,'LineWidth',1);
plot(bitrate_vals*1e-9,ber_vnle,'Color',cols(3,:),'Marker',mkr,'MarkerFaceColor','auto','DisplayName','VNLE','LineStyle',lst,'HandleVisibility',hv,'LineWidth',1);
plot(bitrate_vals*1e-9,ber_vnle_mlse,'Color',cols(4,:),'Marker',mkr,'MarkerFaceColor','auto','DisplayName','VNLE+PF+MLSE','LineStyle',lst,'HandleVisibility',hv,'LineWidth',1);
% Continue with the rest of your plot settings
yline(3.8e-3, 'DisplayName', 'HD-FEC', 'LineStyle', '--', 'HandleVisibility', 'off');
yline(2e-2, 'DisplayName', '20%', 'LineStyle', '--','LineWidth',1, 'HandleVisibility', 'off');
%xlabel('Bitrate');
ylabel('BER');
title([num2str(lambda_vals(l)),' nm']);
set(gca, 'yscale', 'log');
set(gca, 'Box', 'on');
grid on;
grid minor;
% legend('Interpreter', 'none','Location','southwest','Visible','off','HandleVisibility','off');
ylim([8e-4,1e-1]);
xlim([bitrate_vals(1)*1e-9,bitrate_vals(end)*1e-9])
end
end

View File

@@ -0,0 +1,538 @@
folderpath = 'C:\Users\sioe\Documents\High_Speed_Measurement_2024\10km_bitrate_complete\';
experiment_name = '';
currentTime = datetime('now', 'Format', 'yyyyMMdd_HHmmss');
timeStr = char(currentTime);
experiment_name = [experiment_name, timeStr];
if 1
%%% BITRATE Sweep for MPI Experiment %%%
awg_vpp = 2.7;
pd_in_set = 8;
random_key = 0;
params = struct;
params.M = [8];
params.lambda = [1293, 1297.5, 1302, 1306.5, 1310, 1313.4, 1318, 1322.7, 1327.4]; %calcWavelengthPlan(16, 400e9 , 1310);
params.bitrate = [270,300,330,360,390,400,410,420,430,440,450,460,470,480].*1e9;
params.duobinary = [0,1,2];
params.rop_atten = [0];
end
if 0
%%% ROP SWEEP
awg_vpp = 2.7;
pd_in_set = 6;
random_key = 0;
params = struct;
params.M = [8,6,4];
params.lambda = [1310]; %calcWavelengthPlan(16, 400e9 , 1310);
params.bitrate = [300:30:480].*1e9;
params.duobinary = [1,0];
params.rop_atten = [0:1.5:7.5];
end
wh = DataStorage(params);
wh.addStorage("ber_ffe");
wh.addStorage("ber_ffe_mlse");
wh.addStorage("ber_vnle");
wh.addStorage("ber_vnle_mlse");
wh.addStorage("ber_db");
wh.addStorage("FFE");
wh.addStorage("VNLE");
wh.addStorage("pd_in");
wh.addStorage("rop");
wh.addStorage("m");
wh.addStorage("dcs");
wh.addStorage("pdfa");
wh.addStorage("exfo");
wh.addStorage("voa");
wh.addStorage("filename");
precomp_path = "C:\Users\sioe\Documents\High_Speed_Measurement_2024\precomp\";
precomp_fn = "lab_high_speed";
precomp_mode = 2; %0=do nothing ; 1= measure; 2=precomp active
looptotal = prod(wh.dim);
disp(['Start Measurement of ',num2str(looptotal),' loops...'])
iterationTimes = zeros(looptotal, 1); % Preallocate for speed
if ~exist('hWaitbar', 'var') || ~isvalid(hWaitbar)
hWaitbar = waitbar(0, sprintf('Starting %d measurements',looptotal), 'Name', 'Processing Progress');
else
waitbar(0, hWaitbar, sprintf('Starting %d measurements',looptotal));
end
loopcnt = 0;
estimatedTimeRemaining = 0;
estimatedTotalTime = 0;
for M = wh.parameter.M.values
dcs = DC_supply("active",[1,0],"voltage",[2.3, 0]);
for db = wh.parameter.duobinary.values
if db == 1
ffe_only = 0;
postfilter_approach = 0;
db_channel_approach = 1;
db_coding_approach = 0;
db_precode = db_coding_approach || db_channel_approach;
if M == 4
pulsef=1;
precomp_amp_max = -50;
v_bias_for_pam = 2.3;
dcs.set("voltage",[v_bias_for_pam, 0]);
pulsef = 1;
elseif M == 6
pulsef=0;
precomp_amp_max = -50;
v_bias_for_pam = 2.3;
dcs.set("voltage",[v_bias_for_pam, 0]);
pulsef = 1;
elseif M == 8
pulsef=0;
precomp_amp_max = -50;
v_bias_for_pam=2.6;
dcs.set("voltage",[v_bias_for_pam, 0]);
pause(7*60); %wait 30 minutes for stable bias
pulsef = 0;
end
elseif db == 2
ffe_only = 0;
postfilter_approach = 0;
db_channel_approach = 0;
db_coding_approach = 1;
db_precode = db_coding_approach || db_channel_approach;
if M == 4
pulsef=1;
precomp_amp_max = -38;
v_bias_for_pam = 2.8;
dcs.set("voltage",[v_bias_for_pam, 0]);
pulsef = 1;
elseif M == 6
pulsef=0;
precomp_amp_max = -38;
v_bias_for_pam = 2.8;
dcs.set("voltage",[v_bias_for_pam, 0]);
pulsef = 1;
elseif M == 8
pulsef=0;
precomp_amp_max = -38;
v_bias_for_pam = 2.8;
dcs.set("voltage",[v_bias_for_pam, 0]);
pulsef = 1;
end
elseif db == 0
ffe_only = 0;
postfilter_approach = 1;
db_channel_approach = 0;
db_coding_approach = 0;
db_precode = db_coding_approach || db_channel_approach;
if M == 4
pulsef=1;
precomp_amp_max = -37;
v_bias_for_pam = 2.3;
dcs.set("voltage",[v_bias_for_pam, 0]);
pulsef = 1;
elseif M == 6
pulsef=0;
precomp_amp_max = -34;
v_bias_for_pam = 2.3;
dcs.set("voltage",[v_bias_for_pam, 0]);
pulsef = 1;
elseif M == 8
pulsef=0;
precomp_amp_max = -34;
v_bias_for_pam=2.6;
dcs.set("voltage",[v_bias_for_pam, 0]);
pause(7*60); %wait 30 minutes for stable bias
pulsef = 0;
end
end
for lambda = wh.parameter.lambda.values
exfo = Exfo_laser("serialport_number",'COM8','mainframe_channel',1,'safety_mode',0);
pdfa = Thor_PDFA("safety_mode",0);
exfo.getLaserInfo;
if ~(exfo.cur_wavelength == lambda)
% 1)
pdfa.disablePDFA;
% 2)
exfo.setWavelength(lambda);
% 3)
pdfa.enablePDFA();
% 4)
pdfa.setPumpLevel(86);
end
for bitrate = wh.parameter.bitrate.values
fsym = floor( bitrate*1e-9./log2(M) ).*1e9;
%%%%% Construct AWG and Scope Modules %%%%%%
fdac = 256e9;
fadc = 256e9;
SCP = ScopeKeysight("model","UXR1104B",'autoscale',1,"fadc","GSa_256","channel",[0,1,0,0],"recordLen",4000000,"removeDC",1);
AWG = AwgKeysight("model","M8199B","fdac",fdac,"scaletodac",[1,1],"skews",[0,0],"voltages",[0,awg_vpp]);
A2S = Awg2Scope(AWG,SCP,[0,2,0,0],"waitUntilClick",0); %
%%%%% Symbol Generation %%%%%%
rcalpha = 0.05;
Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rrc","pulselength",16,"rrcalpha",rcalpha);
Pamsource = PAMsource(...
"fsym",fsym,"M",M,"order",19,"useprbs",1,...
"fs_out",fdac,...
"applyclipping",0,"clipfactor",1.2,...
"applypulseform",pulsef,"pulseformer",Pform,...
"randkey",random_key,...
"db_precode",db_precode,"db_encode",db_coding_approach,...
"mrds_code",0,"mrds_blocklength",512);
[Digi_sig,Symbols,Bits] = Pamsource.process();
% Digi_sig.plot("displayname","Digi_sig clipped","fignum",21,"clear",1);
%%%%% Precompensation Routine %%%%%%
if precomp_mode == 1 % measure channel
precomp_est = ChannelFreqResp("Nacq",2048,"Navg",100,"Ncp",63,'f_ref',fdac);
Digi_sig = precomp_est.buildOFDM();
elseif precomp_mode == 2 % apply precomp
precomp_est = ChannelFreqResp("Nacq",2048,"Navg",100,"Ncp",63,'f_ref',Digi_sig.fs);
Digi_sig = precomp_est.precomp(Digi_sig,'maxampdb',precomp_amp_max,'loadPath',precomp_path,'fileName',precomp_fn);
end
%%%%% Resample to DAC rate %%%%%%
Digi_sig = Digi_sig.resample("fs_out",AWG.fdac);
% Digi_sig.spectrum("displayname","TX After precomp","fignum",222,"normalizeToNyquist",0,"normalizeTo0dB",1);
if 0 %negative performance...
% X: design FIR filter for sinc precomp
% https://www.dsprelated.com/showarticle/1191.php
ntaps = 13;
npts = 32;
% least-squares FIR design
fmax = AWG.fdac*0.5;
ff = linspace(0,fmax,npts);
hsinc = sin(pi*ff/AWG.fdac)./(pi*ff/AWG.fdac + eps); % transfer function of sample and hold DAC
hsinc(1) = 1;
h_goal= 1./hsinc; % goal function
f = 2.*ff./AWG.fdac; %vector between 0 and 1, where 1 is nyquist is fsamp/2
b = firls(ntaps-1,f,h_goal);
Digi_sig.signal = conv(Digi_sig.signal,b,"same");
end
% Digi_sig.spectrum("displayname","TX After SINC precomp","fignum",222,"normalizeToNyquist",0,"normalizeTo0dB",1);
for rop_atten = wh.parameter.rop_atten.values
%%%%% Loop Preps
iterationStartTime = tic;
loopcnt = loopcnt+1;
loop_name = ['_PAM_',num2str(M),'_L_',num2str(lambda),'_R_',num2str(bitrate),'_DB_',num2str(db),'_ROP_',num2str(rop_atten)];
loop_name = strrep(loop_name,'.','_');
%%%%% READ Voltages %%%%%%
dcs.readVals();
%%%%% SET Attenuator %%%%%%
voa = OptAtten("active",[1,2,1,1],"value",[rop_atten,pd_in_set,0,0],"wavelength",[1310,1310,1310,1310],"speed",[1000,100,1000,1000]);
voa.set('active',[1,2,1,1],'value',[rop_atten,pd_in_set,0,0]);
voa.readvals();
%%%% SIGNAL USUALLY HERE, NOW ABOVE ROP_ATTEN %%%
%%%%% Plot and Save Routine 1 - same for all rops, thus save only once %%%%%%%%%%%%%%%%%%%%%%%%%
if rop_atten == 0
save([folderpath,experiment_name,loop_name,'_bits'],"Bits");
save([folderpath,experiment_name,loop_name,'_symbols'],"Symbols");
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%% AWG --> Scope %%%%%%
[~,Scpe_sig_raw,~,D] = A2S.process("signal2",Digi_sig,"waitUntilClick",0);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
save([folderpath,experiment_name,loop_name,'_raw_signal'],"Scpe_sig_raw");
% Scpe_sig_raw = Filter('filtdegree',5,"f_cutoff",0.55.*fsym,"fs",fadc,"filterType",filtertypes.gaussian,"active",true).process(Scpe_sig_raw);
%
Scpe_sig_raw.plot("displayname","Scope raw signal","fignum",20,"clear",1);
% Scpe_sig_raw.spectrum("displayname","Scope PSD","fignum",30,"normalizeTo0dB",1);
% Scpe_sig_raw.eye(fsym,M,"displayname",'eye','fignum',200);
%%%%%% Sample to 2x fsym %%%%%%
Scpe_sig_resampled = Scpe_sig_raw.resample("fs_in",fadc,"fs_out",2*fsym);
%%%%% Precompensation Routine %%%%%%
if precomp_mode == 1
precomp_est.estimate(Scpe_sig_resampled,"save",true,"savePath",precomp_path,"fileName",precomp_fn);
precomp_est.plot();
end
voa.readvals();
rop = voa.power_state(1);
pd_in = voa.power_state(2);
%%%%%% Sync Rx signal with reference (S is a cell array with all occurences) %%%%%%
[Scpe_sig_syncd,S,isFlipped] = Scpe_sig_resampled.tsynch("reference",Symbols,"fs_ref",fsym);
%%%%% Plot and Save Routines: SAVE RECEIVED SIGNALS %%%%%%%%%%%%%%%%%%%%%%%%%
save([folderpath,experiment_name,loop_name,'_rx_signal'],"S");
%%%%% EQUALIZE %%%%%%
% set to minus one not zero not avoid confusion if BER is acutally zero
ber_vnle = [-1];
ber_vnle_mlse = [-1];
ber_ffe_mlse =[-1];
ber_ffe = [-1];
ber_db = [-1];
ffe = EQ("Ne",[50,0,0],"Nb",[0,0,0],"training_length",4096*2,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.05,"DDmu",[0.0004 0.0004 0.0004 0.0004 ],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
vnle = EQ("Ne",[50,7,7],"Nb",[0,0,0],"training_length",4096*2,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.05,"DDmu",[0.0004 0.0004 0.0004 0.0004 ],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
if postfilter_approach %%%%%%%%%%%%%%%%%%%%%%%%%%%
if 1
eq_values = min(numel(S),8);
Noi = cell(eq_values,1);
EQ_vnle= cell(eq_values,1);
EQ_ffe= cell(eq_values,1);
parfor s = 1:eq_values
if 1
%VNLE
vnle = EQ("Ne",[50,7,7],"Nb",[0,0,0],"training_length",4096*2,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.0,"DDmu",[0.0004 0.0004 0.0004 0.0004 ],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
Scpe_sig_syncd = S{s};
[EQ_vnle{s}] = vnle.process(Scpe_sig_syncd,Symbols);
Noi{s} = EQ_vnle{s}-Symbols;
Rx_bits = PAMmapper(M,0).demap(EQ_vnle{s});
[~,~,ber_vnle(s),~] = calc_ber(Rx_bits.signal,Bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
end
%VNLE + MLSE
if 1
Noi{s}.signal = Noi{s}.signal - mean(Noi{s}.signal);
nc = 2;
burg_coeff = arburg(Noi{s}.signal,nc);
EQ_mlse = EQ_vnle{s}.filter(burg_coeff,1);
EQ_mlse = MLSE("DIR",burg_coeff,"duobinary_output",0,"M",M,"trellis_states",PAMmapper(M,0).levels).process(EQ_mlse);
Rx_bits = PAMmapper(M,0).demap(EQ_mlse);
[~,~,ber_vnle_mlse(s),~] = calc_ber(Rx_bits.signal,Bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
end
end
if 0
[~,s]=min(ber_vnle_mlse);
nc = 2;
burg_coeff = arburg(Noi{s}.signal,nc);
Noi{s}.spectrum('displayname','Noise PSD','fignum',123);
[h,w] = freqz(1,burg_coeff,length(Noi{s}),"whole",Noi{s}.fs);
h = h/max(abs(h));
hold on
w_ = (w - Noi{s}.fs/2);
plot(w_.*1e-9,20*log10(fftshift(h)),'DisplayName',['', num2str(nc), ' coefficients for burg alg.']);
end
if 0
figure(55);
clf
title(sprintf('PAM %d ; BER: %1.2e',M, ber_vnle_mlse(s) ));
constellation = unique(Symbols.signal);
received = NaN(numel(constellation),length(Symbols));
for lvl = 1:numel(constellation)
%Separate the equalized signal into the
%respective levels based on the actually
%transmitted level!
received(lvl,Symbols.signal==constellation(lvl)) = EQ_vnle{s}.signal(Symbols.signal==constellation(lvl));
intermediate = received(lvl,:);
cnt(lvl) = numel(intermediate(~isnan(intermediate)));
hold on
histogram(received(lvl,:),1000,"EdgeAlpha",0,'DisplayName',['Lvl ',num2str(lvl),' | ',num2str(cnt(lvl)),' entries']);
end
legend
end
% disp(['FFE EQ: BEST BER: ',sprintf('%.1E',min(ber_ffe)),' AVG BER: ',sprintf('%.1E',mean(ber_ffe)),' WORST:',sprintf('%.1E',max(ber_ffe)),'. Out of ',num2str(numel(ber_ffe))]);
% disp(['FFE + MLSE EQ: BEST BER: ',sprintf('%.1E',min(ber_ffe_mlse)),' AVG BER: ',sprintf('%.1E',mean(ber_ffe_mlse)),' WORST:',sprintf('%.1E',max(ber_ffe_mlse)),'. Out of ',num2str(numel(ber_ffe_mlse))]);
disp(['VNLE EQ: BEST BER: ',sprintf('%.1E',min(ber_vnle)),' AVG BER: ',sprintf('%.1E',mean(ber_vnle)),' WORST:',sprintf('%.1E',max(ber_vnle)),'. Out of ',num2str(numel(ber_vnle))]);
% disp(['VNLE+MLSE EQ: BEST BER: ',sprintf('%.1E',min(ber_vnle_mlse)),' AVG BER: ',sprintf('%.1E',mean(ber_vnle_mlse)),' WORST:',sprintf('%.1E',max(ber_vnle_mlse)),'. Out of ',num2str(numel(ber_vnle_mlse))]);
end
elseif db_channel_approach %%%%%%%%%%%%%%%%%%%%%%%%%%%
ffe = EQ("Ne",[50,0,0],"Nb",[0,0,0],"training_length",4096*2,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.05,"DDmu",[0.0004 0.0004 0.0004 0.0004 ],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
ffe = EQ("Ne",[50,7,7],"Nb",[0,0,0],"training_length",4096*2,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.0,"DDmu",[0.0004 0.0004 0.0004 0.0004 ],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
if 1
eq_values = min(numel(S),8);
Noi = cell(eq_values,1);
EQ_sig = cell(eq_values,1);
parfor s = 1:eq_values
Scpe_sig_syncd = S{s};
[EQ_sig{s}, Noi{s}] = ffe.process(Scpe_sig_syncd,Duobinary().encode(Symbols));
EQ_sig{s}.signal = EQ_sig{s}.signal-mean(EQ_sig{s}.signal);
EQ_sig_mlse = MLSE("DIR",[1,1],"duobinary_output",1,"M",M,"trellis_states",PAMmapper(M,0).levels).process(EQ_sig{s});
EQ_sig_mlse = Duobinary().decode(EQ_sig_mlse);
Rx_bits = PAMmapper(M,0).demap(EQ_sig_mlse);
[~,num_errors,ber_db(s),pos_errors] = calc_ber(Rx_bits.signal,Bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
end
if 0
[~,s]=min(ber_vnle_mlse);
Noi{s}.spectrum('displayname',['Noise; SIR:',sprintf('%.2f',sir)],'fignum',40,'normalizeTo0dB',1);
Duobinary().encode(Symbols).spectrum('displayname',['DB coded symbols; SIR:',sprintf('%.2f',sir)],'fignum',40,'normalizeTo0dB',1);
EQ_sig{s}.spectrum('displayname',['EQ; SIR:',sprintf('%.2f',sir)],'fignum',40,'normalizeTo0dB',1);
EQ_sig{s}.signal = EQ_sig{1}.signal-mean(EQ_sig{s}.signal);
end
disp(['DB EQ: BEST BER: ',sprintf('%.1E',min(ber_db)),' AVG BER: ',sprintf('%.1E',mean(ber_db)),' WORST:',sprintf('%.1E',max(ber_db)),'. Out of',num2str(numel(ber_db))]);
else
% disp('Disabled MLSE for DB in all cases, due to time in measurement loop')
end
elseif db_coding_approach
ffe = EQ("Ne",[50,7,7],"Nb",[0,0,0],"training_length",4096*2,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.0,"DDmu",[0.0004 0.0004 0.0004 0.0004 ],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
if 1
eq_values = min(numel(S),8);
Noi = cell(eq_values,1);
EQ_sig = cell(eq_values,1);
EQ_sig_mlse = cell(eq_values,1);
parfor s = 1:eq_values
[EQ_sig{s}, Noi{s}] = ffe.process(S{s},Symbols);
EQ_sig_mlse{s} = MLSE("DIR",[1,1],"duobinary_output",1,"M",M,"trellis_states",PAMmapper(M,0).levels).process(EQ_sig{s});
EQ_sig_mlse{s} = Duobinary().decode(EQ_sig_mlse{s});
Rx_bits = PAMmapper(M,0).demap(EQ_sig_mlse{s});
[~,num_errors,ber_db(s),pos_errors] = calc_ber(Rx_bits.signal,Bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
end
disp(['DB EQ: BEST BER: ',sprintf('%.1E',min(ber_db)),' AVG BER: ',sprintf('%.1E',mean(ber_db)),' WORST:',sprintf('%.1E',max(ber_db)),'. Out of',num2str(numel(ber_db))]);
if 1
[~,s]=min(ber_db);
Noi{s}.spectrum('displayname',['Noise '],'fignum',50,'normalizeTo0dB',1);
EQ_sig{s}.spectrum('displayname',['EQLZD '],'fignum',50,'normalizeTo0dB',1);
Symbols.spectrum('displayname',['Symbols '],'fignum',222,'normalizeTo0dB',1);
end
if 1
figure(51);
clf
title(sprintf('DB coded PAM after EQ ; BER: %1.2e',M, ber_db(s) ));
constellation = unique(Symbols.signal);
received = NaN(numel(constellation),length(Symbols));
for lvl = 1:numel(constellation)
%Separate the equalized signal into the
%respective levels based on the actually
%transmitted level!
received(lvl,Symbols.signal==constellation(lvl)) = EQ_sig{s}.signal(Symbols.signal==constellation(lvl));
intermediate = received(lvl,:);
cnt(lvl) = numel(intermediate(~isnan(intermediate)));
hold on
histogram(received(lvl,:),1000,"EdgeAlpha",0,'DisplayName',['Lvl ',num2str(lvl),' | ',num2str(cnt(lvl)),' entries']);
end
legend
end
end
end
% showCurrentMeasurement('Vbias', v_bias_for_pam,'MIN BER', min(ber_db),'MEAN BER',mean(ber_db),'MAX BER',max(ber_db), 'Fsym',fsym.*1e-9, 'ROP', rop, 'Precomp MaxAmp',precomp_amp_max);
%%%%% Store measurement into measurement "warehouse" %%%%%%
wh.addValueToStorage({ber_ffe},'ber_ffe',M,lambda,bitrate,db,rop_atten);
wh.addValueToStorage({ber_ffe_mlse},'ber_ffe_mlse',M,lambda,bitrate,db,rop_atten);
wh.addValueToStorage({ber_vnle},'ber_vnle',M,lambda,bitrate,db,rop_atten);
wh.addValueToStorage({ber_vnle_mlse},'ber_vnle_mlse',M,lambda,bitrate,db,rop_atten);
wh.addValueToStorage({ber_db},'ber_db',M,lambda,bitrate,db,rop_atten);
wh.addValueToStorage(rop,'rop',M,lambda,bitrate,db,rop_atten);
wh.addValueToStorage(pd_in,'pd_in',M,lambda,bitrate,db,rop_atten);
wh.addValueToStorage(M,'m',M,lambda,bitrate,db,rop_atten);
wh.addValueToStorage(dcs,'dcs',M,lambda,bitrate,db,rop_atten);
wh.addValueToStorage(pdfa,'pdfa',M,lambda,bitrate,db,rop_atten);
wh.addValueToStorage(exfo,'exfo',M,lambda,bitrate,db,rop_atten);
wh.addValueToStorage(voa,'voa',M,lambda,bitrate,db,rop_atten);
wh.addValueToStorage(ffe,'FFE',M,lambda,bitrate,db,rop_atten);
wh.addValueToStorage(vnle,'VNLE',M,lambda,bitrate,db,rop_atten);
wh.addValueToStorage(string([experiment_name,loop_name]),'filename',M,lambda,bitrate,db,rop_atten);
iterationTimes(loopcnt) = toc(iterationStartTime);
averageTimePerIteration = mean(iterationTimes(1:loopcnt));
estimatedTotalTime = averageTimePerIteration * looptotal;
estimatedTimeRemaining = estimatedTotalTime - sum(iterationTimes(1:loopcnt));
progressFraction = loopcnt / looptotal;
waitbar(progressFraction, hWaitbar, ...
sprintf('Loop: %d of %d \n Runtime: %.1f min | %.1f sec per Loop |Time to go: %.1f min ', ...
loopcnt, looptotal, sum(iterationTimes(1:loopcnt))/60, averageTimePerIteration, estimatedTimeRemaining/60 ));
wh.save([folderpath,experiment_name,'_wh']);
end
end
end
end
end
close(hWaitbar);
wh.save([folderpath,experiment_name,'_wh']);

View File

@@ -0,0 +1,503 @@
folderpath = 'C:\Users\sioe\Documents\High_Speed_Measurement_2024\MPI_duobinary_encoded\';
experiment_name = '';
currentTime = datetime('now', 'Format', 'yyyyMMdd_HHmmss');
timeStr = char(currentTime);
experiment_name = [experiment_name, timeStr];
%%% BITRATE Sweep for MPI Experiment %%%
awg_vpp = 2.7;
rop_atten = 0; %VOA 1 -> %nicht angeschlossen
pd_in_set = 8; %VOA 2 -> PD in
%VOA 3 -> Signal path
%VOA 4 -> Interference path
random_key = 0;
params = struct;
params.M = [4];
params.bitrate = [336,360,390,420,448].*1e9;%[90:60:480].*1e9;%[300:30:480].*1e9;
params.duobinary = [2];
params.interference_atten = [0:1:20,45];
wh = DataStorage(params);
wh.addStorage("ber_ffe");
wh.addStorage("ber_ffe_mlse");
wh.addStorage("ber_vnle");
wh.addStorage("ber_vnle_mlse");
wh.addStorage("ber_db");
wh.addStorage("FFE");
wh.addStorage("VNLE");
wh.addStorage("pd_in");
wh.addStorage("rop");
wh.addStorage("s_power");
wh.addStorage("i_power");
wh.addStorage("sir");
wh.addStorage("filename");
wh.addStorage("m");
wh.addStorage("dcs");
wh.addStorage("pdfa");
wh.addStorage("exfo");
wh.addStorage("voa");
precomp_path = "C:\Users\sioe\Documents\High_Speed_Measurement_2024\precomp\";
precomp_fn = "lab_high_speed";
precomp_mode = 2; %0=do nothing ; 1= measure; 2=precomp active
looptotal = prod(wh.dim);
disp(['Start Measurement of ',num2str(looptotal),' loops...'])
iterationTimes = zeros(looptotal, 1); % Preallocate for speed
if ~exist('hWaitbar', 'var') || ~isvalid(hWaitbar)
hWaitbar = waitbar(0, sprintf('Starting %d measurements',looptotal), 'Name', 'Processing Progress');
else
waitbar(0, hWaitbar, sprintf('Starting %d measurements',looptotal));
end
loopcnt = 0;
estimatedTimeRemaining = 0;
estimatedTotalTime = 0;
for M = wh.parameter.M.values
for bitrate = wh.parameter.bitrate.values
fsym = floor( bitrate*1e-9./log2(M) ).*1e9;
for db = wh.parameter.duobinary.values
dcs = DC_supply("active",[1,0],"voltage",[2.3, 0]);
if db == 1
ffe_only = 0;
postfilter_approach = 0;
db_channel_approach = 1;
db_coding_approach = 0;
db_precode = db_coding_approach || db_channel_approach;
if M == 4
pulsef=1;
precomp_amp_max = -50;
v_bias_for_pam = 2.3;
dcs.set("voltage",[v_bias_for_pam, 0]);
pulsef = 1;
elseif M == 6
pulsef=0;
precomp_amp_max = -50;
v_bias_for_pam = 2.3;
dcs.set("voltage",[v_bias_for_pam, 0]);
pulsef = 1;
elseif M == 8
pulsef=0;
precomp_amp_max = -50;
v_bias_for_pam=2.6;
dcs.set("voltage",[v_bias_for_pam, 0]);
pause(7*60); %wait 30 minutes for stable bias
pulsef = 0;
end
elseif db == 2
ffe_only = 0;
postfilter_approach = 0;
db_channel_approach = 0;
db_coding_approach = 1;
db_precode = db_coding_approach || db_channel_approach;
if M == 4
pulsef=1;
precomp_amp_max = -38;
v_bias_for_pam = 2.8;
dcs.set("voltage",[v_bias_for_pam, 0]);
pulsef = 1;
elseif M == 6
pulsef=0;
precomp_amp_max = -38;
v_bias_for_pam = 2.8;
dcs.set("voltage",[v_bias_for_pam, 0]);
pulsef = 1;
elseif M == 8
pulsef=0;
precomp_amp_max = -38;
v_bias_for_pam = 2.8;
dcs.set("voltage",[v_bias_for_pam, 0]);
pulsef = 1;
end
elseif db == 0
ffe_only = 0;
postfilter_approach = 1;
db_channel_approach = 0;
db_coding_approach = 0;
db_precode = db_coding_approach || db_channel_approach;
if M == 4
pulsef=1;
precomp_amp_max = -37;
v_bias_for_pam = 2.3;
dcs.set("voltage",[v_bias_for_pam, 0]);
pulsef = 1;
elseif M == 6
pulsef=0;
precomp_amp_max = -34;
v_bias_for_pam = 2.3;
dcs.set("voltage",[v_bias_for_pam, 0]);
pulsef = 1;
elseif M == 8
pulsef=0;
precomp_amp_max = -34;
v_bias_for_pam=2.6;
dcs.set("voltage",[v_bias_for_pam, 0]);
pause(7*60); %wait 30 minutes for stable bias
pulsef = 0;
end
end
%%%%% Construct AWG and Scope Modules %%%%%%
fdac = 256e9;
fadc = 256e9;
%%%%% Symbol Generation %%%%%%
rcalpha = 0.05;
Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rrc","pulselength",16,"rrcalpha",rcalpha);
Pamsource = PAMsource(...
"fsym",fsym,"M",M,"order",19,"useprbs",1,...
"fs_out",fdac,...
"applyclipping",0,"clipfactor",1.5,...
"applypulseform",pulsef,"pulseformer",Pform,...
"randkey",random_key,...
"db_precode",db_precode,"db_encode",db_coding_approach,...
"mrds_code",0,"mrds_blocklength",512);
[Digi_sig,Symbols,Bits] = Pamsource.process();
%%%%% Precompensation Routine %%%%%%
if precomp_mode == 1 % measure channel
precomp_est = ChannelFreqResp("Nacq",1024,"Navg",64,"Ncp",63,'f_ref',fdac);
Digi_sig = precomp_est.buildOFDM();
elseif precomp_mode == 2 % apply precomp
precomp_est = ChannelFreqResp("Nacq",1024,"Navg",64,"Ncp",63,'f_ref',Digi_sig.fs);
Digi_sig = precomp_est.precomp(Digi_sig,'maxampdb',precomp_amp_max,'loadPath',precomp_path,'fileName',precomp_fn);
end
%%%%% Resample to DAC rate %%%%%%
Digi_sig = Digi_sig.resample("fs_out",fdac);
% Digi_sig = Filter('filtdegree',5,"f_cutoff",0.75*fsym,"fs",fadc,"filterType",filtertypes.gaussian,"active",true).process(Digi_sig);
% Digi_sig.spectrum("displayname","TX After precomp","fignum",10,"normalizeToNyquist",0,"normalizeTo0dB",0);
% holdAndShowValue;
scopeAutoScale = 1;
for interference_atten = wh.parameter.interference_atten.values
SCP = ScopeKeysight("model","UXR1104B",'autoscale',scopeAutoScale,"fadc","GSa_256","channel",[0,1,0,0],"recordLen",6000000,"removeDC",1);
AWG = AwgKeysight("model","M8199B","fdac",fdac,"scaletodac",[1,1],"skews",[0,0],"voltages",[0,awg_vpp]);
A2S = Awg2Scope(AWG,SCP,[0,2,0,0],"waitUntilClick",1); %
% scopeAutoScale = 0; %until is set to 1 in next db change and then bitrate
%%%%% Loop Preps
iterationStartTime = tic;
loopcnt = loopcnt+1;
loop_name = ['_PAM_',num2str(M),'_R_',num2str(bitrate),'_DB_',num2str(db),'_I_atten_',num2str(interference_atten)];
loop_name = strrep(loop_name,'.','_');
%%%%% READ Voltages %%%%%%
dcs.readVals();
%%%%% SET Attenuator %%%%%%
voa = OptAtten("active",[1,2,1,1],"value",[rop_atten,pd_in_set,0,interference_atten],"wavelength",[1310,1310,1310,1310],"speed",[1000,100,1000,1000]);
voa.set('active',[1,2,1,1],'value',[rop_atten,pd_in_set,0,interference_atten]);
%%%% SIGNAL USUALLY HERE, NOW ABOVE ROP_ATTEN %%%
%%%%% Plot and Save Routine 1 - same for all rops, thus save only once %%%%%%%%%%%%%%%%%%%%%%%%%
if interference_atten == 0
save([folderpath,experiment_name,loop_name,'_bits'],"Bits");
save([folderpath,experiment_name,loop_name,'_symbols'],"Symbols");
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%% AWG --> Scope %%%%%%
[~,Scpe_sig_raw,~,D] = A2S.process("signal2",Digi_sig,"waitUntilClick",0);
save([folderpath,experiment_name,loop_name,'_raw_signal'],"Scpe_sig_raw");
voa.readvals();
rop = voa.power_state(1);
pd_in = voa.power_state(2);
i_power = voa.power_state(4);
s_power = voa.power_state(3);
sir = s_power-i_power;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Scpe_sig_raw.spectrum("displayname","Scope PSD before filter","fignum",30,"normalizeTo0dB",1);
% Scpe_sig_raw = Filter('filtdegree',5,"f_cutoff",0.65.*fsym,"fs",fadc,"filterType",filtertypes.gaussian,"active",true).process(Scpe_sig_raw);
% Scpe_sig_raw.spectrum("displayname","Scope PSD after filter","fignum",30,"normalizeTo0dB",1);
%%%%%% Sample to 2x fsym %%%%%%
Scpe_sig_resampled = Scpe_sig_raw.resample("fs_in",fadc,"fs_out",2*fsym);
Scpe_sig_raw.plot("displayname",['SIR: ',sprintf('%.2f',sir),' dB'],"fignum",20,"clear",1);
% disp(['PDin: ',sprintf('%.2f',pd_in),' dB | S: ',sprintf('%.2f',s_power),' dB | I: ',sprintf('%.2f',i_power),' dB | -> SIR: ',sprintf('%.2f',sir),' dB']);
%%%%%% Sync Rx signal with reference (S is a cell array with all occurences) %%%%%%
[Scpe_sig_syncd,S,isFlipped] = Scpe_sig_resampled.tsynch("reference",Symbols,"fs_ref",fsym);
%%%%% Plot and Save Routines: SAVE RECEIVED SIGNALS %%%%%%%%%%%%%%%%%%%%%%%%%
save([folderpath,experiment_name,loop_name,'_rx_signal'],"S");
%%%%% EQUALIZE %%%%%%
% set to minus one not zero not avoid confusion if BER is acutally zero
ber_vnle = [-1];
ber_vnle_mlse = [-1];
ber_ffe_mlse =[-1];
ber_ffe = [-1];
ber_db = [-1];
ffe = EQ("Ne",[50,0,0],"Nb",[0,0,0],"training_length",4096*2,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.05,"DDmu",[0.0004 0.0004 0.0004 0.0004 ],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
vnle = EQ("Ne",[50,7,7],"Nb",[0,0,0],"training_length",4096*2,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.05,"DDmu",[0.0004 0.0004 0.0004 0.0004 ],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
if postfilter_approach %%%%%%%%%%%%%%%%%%%%%%%%%%%
if 1
eq_values = min(numel(S),8);
Noi = cell(eq_values,1);
EQ_vnle= cell(eq_values,1);
EQ_ffe= cell(eq_values,1);
parfor s = 1:eq_values
if 1
%VNLE
vnle = EQ("Ne",[50,7,7],"Nb",[0,0,0],"training_length",4096*2,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.0,"DDmu",[0.0004 0.0004 0.0004 0.0004 ],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
Scpe_sig_syncd = S{s};
[EQ_vnle{s}] = vnle.process(Scpe_sig_syncd,Symbols);
Noi{s} = EQ_vnle{s}-Symbols;
Rx_bits = PAMmapper(M,0).demap(EQ_vnle{s});
[~,~,ber_vnle(s),~] = calc_ber(Rx_bits.signal,Bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
end
%VNLE + MLSE
if 1
Noi{s}.signal = Noi{s}.signal - mean(Noi{s}.signal);
nc = 2;
burg_coeff = arburg(Noi{s}.signal,nc);
EQ_mlse = EQ_vnle{s}.filter(burg_coeff,1);
EQ_mlse = MLSE("DIR",burg_coeff,"duobinary_output",0,"M",M,"trellis_states",PAMmapper(M,0).levels).process(EQ_mlse);
Rx_bits = PAMmapper(M,0).demap(EQ_mlse);
[~,~,ber_vnle_mlse(s),~] = calc_ber(Rx_bits.signal,Bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
end
end
if 1
[~,s]=min(ber_vnle_mlse);
nc = 2;
burg_coeff = arburg(Noi{s}.signal,nc);
Noi{s}.spectrum('displayname','Noise PSD','fignum',123);
[h,w] = freqz(1,burg_coeff,length(Noi{s}),"whole",Noi{s}.fs);
h = h/max(abs(h));
hold on
w_ = (w - Noi{s}.fs/2);
plot(w_.*1e-9,20*log10(fftshift(h)),'DisplayName',['', num2str(nc), ' coefficients for burg alg.']);
end
if 1
figure(55);
clf
title(sprintf('PAM %d ; BER: %1.2e',M, ber_vnle_mlse(s) ));
constellation = unique(Symbols.signal);
received = NaN(numel(constellation),length(Symbols));
for lvl = 1:numel(constellation)
%Separate the equalized signal into the
%respective levels based on the actually
%transmitted level!
received(lvl,Symbols.signal==constellation(lvl)) = EQ_vnle{s}.signal(Symbols.signal==constellation(lvl));
intermediate = received(lvl,:);
cnt(lvl) = numel(intermediate(~isnan(intermediate)));
hold on
histogram(received(lvl,:),1000,"EdgeAlpha",0,'DisplayName',['Lvl ',num2str(lvl),' | ',num2str(cnt(lvl)),' entries']);
end
legend
end
% disp(['FFE EQ: BEST BER: ',sprintf('%.1E',min(ber_ffe)),' AVG BER: ',sprintf('%.1E',mean(ber_ffe)),' WORST:',sprintf('%.1E',max(ber_ffe)),'. Out of ',num2str(numel(ber_ffe))]);
% disp(['FFE + MLSE EQ: BEST BER: ',sprintf('%.1E',min(ber_ffe_mlse)),' AVG BER: ',sprintf('%.1E',mean(ber_ffe_mlse)),' WORST:',sprintf('%.1E',max(ber_ffe_mlse)),'. Out of ',num2str(numel(ber_ffe_mlse))]);
disp(['VNLE EQ: BEST BER: ',sprintf('%.1E',min(ber_vnle)),' AVG BER: ',sprintf('%.1E',mean(ber_vnle)),' WORST:',sprintf('%.1E',max(ber_vnle)),'. Out of ',num2str(numel(ber_vnle))]);
% disp(['VNLE+MLSE EQ: BEST BER: ',sprintf('%.1E',min(ber_vnle_mlse)),' AVG BER: ',sprintf('%.1E',mean(ber_vnle_mlse)),' WORST:',sprintf('%.1E',max(ber_vnle_mlse)),'. Out of ',num2str(numel(ber_vnle_mlse))]);
end
elseif db_channel_approach %%%%%%%%%%%%%%%%%%%%%%%%%%%
ffe = EQ("Ne",[50,0,0],"Nb",[0,0,0],"training_length",4096*2,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.05,"DDmu",[0.0004 0.0004 0.0004 0.0004 ],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
ffe = EQ("Ne",[50,7,7],"Nb",[0,0,0],"training_length",4096*2,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.0,"DDmu",[0.0004 0.0004 0.0004 0.0004 ],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
if 0
eq_values = min(numel(S),8);
Noi = cell(eq_values,1);
EQ_sig = cell(eq_values,1);
parfor s = 1:eq_values
Scpe_sig_syncd = S{s};
[EQ_sig{s}, Noi{s}] = ffe.process(Scpe_sig_syncd,Duobinary().encode(Symbols));
EQ_sig{s}.signal = EQ_sig{s}.signal-mean(EQ_sig{s}.signal);
EQ_sig_mlse = MLSE("DIR",[1,1],"duobinary_output",1,"M",M,"trellis_states",PAMmapper(M,0).levels).process(EQ_sig{s});
EQ_sig_mlse = Duobinary().decode(EQ_sig_mlse);
Rx_bits = PAMmapper(M,0).demap(EQ_sig_mlse);
[~,num_errors,ber_db(s),pos_errors] = calc_ber(Rx_bits.signal,Bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
end
if 1
[~,s]=min(ber_vnle_mlse);
Noi{s}.spectrum('displayname',['Noise; SIR:',sprintf('%.2f',sir)],'fignum',40,'normalizeTo0dB',1);
Duobinary().encode(Symbols).spectrum('displayname',['DB coded symbols; SIR:',sprintf('%.2f',sir)],'fignum',40,'normalizeTo0dB',1);
EQ_sig{s}.spectrum('displayname',['EQ; SIR:',sprintf('%.2f',sir)],'fignum',40,'normalizeTo0dB',1);
EQ_sig{s}.signal = EQ_sig{1}.signal-mean(EQ_sig{s}.signal);
end
disp(['DB EQ: BEST BER: ',sprintf('%.1E',min(ber_db)),' AVG BER: ',sprintf('%.1E',mean(ber_db)),' WORST:',sprintf('%.1E',max(ber_db)),'. Out of',num2str(numel(ber_db))]);
else
% disp('Disabled MLSE for DB in all cases, due to time in measurement loop')
end
elseif db_coding_approach
ffe = EQ("Ne",[50,7,7],"Nb",[0,0,0],"training_length",4096*2,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.0,"DDmu",[0.0004 0.0004 0.0004 0.0004 ],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
if 1
eq_values = min(numel(S),8);
Noi = cell(eq_values,1);
EQ_sig = cell(eq_values,1);
EQ_sig_mlse = cell(eq_values,1);
parfor s = 1:eq_values
[EQ_sig{s}, Noi{s}] = ffe.process(S{s},Symbols);
EQ_sig_mlse{s} = MLSE("DIR",[1,1],"duobinary_output",1,"M",M,"trellis_states",PAMmapper(M,0).levels).process(EQ_sig{s});
EQ_sig_mlse{s} = Duobinary().decode(EQ_sig_mlse{s});
Rx_bits = PAMmapper(M,0).demap(EQ_sig_mlse{s});
[~,num_errors,ber_db(s),pos_errors] = calc_ber(Rx_bits.signal,Bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
end
disp(['DB EQ: BEST BER: ',sprintf('%.1E',min(ber_db)),' AVG BER: ',sprintf('%.1E',mean(ber_db)),' WORST:',sprintf('%.1E',max(ber_db)),'. Out of',num2str(numel(ber_db))]);
if 1
[~,s]=min(ber_db);
Noi{s}.spectrum('displayname',['Noise '],'fignum',50,'normalizeTo0dB',1);
EQ_sig{s}.spectrum('displayname',['EQLZD '],'fignum',50,'normalizeTo0dB',1);
Symbols.spectrum('displayname',['Symbols '],'fignum',50,'normalizeTo0dB',1);
nc = 5;
burg_coeff = arburg(Noi{s}.signal,nc);
[h,w] = freqz(1,burg_coeff,length(Noi{s}),"whole",Noi{s}.fs);
h = h/max(abs(h));
hold on
w_ = (w - Noi{s}.fs/2);
plot(w_.*1e-9,20*log10(fftshift(h)),'DisplayName',['', num2str(nc), ' coefficients for burg alg.']);
end
if 1
figure(51);
clf
title(sprintf('DB coded PAM after EQ ; BER: %1.2e',M, ber_db(s) ));
constellation = unique(Symbols.signal);
received = NaN(numel(constellation),length(Symbols));
for lvl = 1:numel(constellation)
%Separate the equalized signal into the
%respective levels based on the actually
%transmitted level!
received(lvl,Symbols.signal==constellation(lvl)) = EQ_sig{s}.signal(Symbols.signal==constellation(lvl));
intermediate = received(lvl,:);
cnt(lvl) = numel(intermediate(~isnan(intermediate)));
hold on
histogram(received(lvl,:),1000,"EdgeAlpha",0,'DisplayName',['Lvl ',num2str(lvl),' | ',num2str(cnt(lvl)),' entries']);
end
legend
end
end
end
showCurrentMeasurement('Att.',interference_atten,'SIR',sir,'MIN BER', min(ber_db),'MEAN BER',mean(ber_db),'MAX BER',max(ber_db), 'Fsym',fsym.*1e-9, 'ROP', rop, 'Precomp MaxAmp',precomp_amp_max);
%%%%% Store measurement into measurement "warehouse" %%%%%%
wh.addValueToStorage({ber_ffe},'ber_ffe',M,bitrate,db,interference_atten);
wh.addValueToStorage({ber_ffe_mlse},'ber_ffe_mlse',M,bitrate,db,interference_atten);
wh.addValueToStorage({ber_vnle},'ber_vnle',M,bitrate,db,interference_atten);
wh.addValueToStorage({ber_vnle_mlse},'ber_vnle_mlse',M,bitrate,db,interference_atten);
wh.addValueToStorage({ber_db},'ber_db',M,bitrate,db,interference_atten);
wh.addValueToStorage(rop,'rop',M,bitrate,db,interference_atten);
wh.addValueToStorage(pd_in,'pd_in',M,bitrate,db,interference_atten);
wh.addValueToStorage(s_power,'s_power',M,bitrate,db,interference_atten);
wh.addValueToStorage(i_power,'i_power',M,bitrate,db,interference_atten);
wh.addValueToStorage(sir,'sir',M,bitrate,db,interference_atten);
wh.addValueToStorage(string([experiment_name,loop_name]),'filename',M,bitrate,db,interference_atten);
wh.addValueToStorage(M,'m',M,bitrate,db,interference_atten);
wh.addValueToStorage(dcs,'dcs',M,bitrate,db,interference_atten);
exfo = Exfo_laser("serialport_number",'COM8','mainframe_channel',1,'safety_mode',0);
exfo.getLaserInfo;
wh.addValueToStorage(exfo,'exfo',M,bitrate,db,interference_atten);
wh.addValueToStorage(voa,'voa',M,bitrate,db,interference_atten);
wh.addValueToStorage(ffe,'FFE',M,bitrate,db,interference_atten);
wh.addValueToStorage(vnle,'VNLE',M,bitrate,db,interference_atten);
iterationTimes(loopcnt) = toc(iterationStartTime);
averageTimePerIteration = mean(iterationTimes(1:loopcnt));
estimatedTotalTime = averageTimePerIteration * looptotal;
estimatedTimeRemaining = estimatedTotalTime - sum(iterationTimes(1:loopcnt));
progressFraction = loopcnt / looptotal;
waitbar(progressFraction, hWaitbar, ...
sprintf('Loop: %d of %d \n Runtime: %.1f min | %.1f sec per Loop |Time to go: %.1f min ', ...
loopcnt, looptotal, sum(iterationTimes(1:loopcnt))/60, averageTimePerIteration, estimatedTimeRemaining/60 ));
wh.save([folderpath,experiment_name,'_wh']);
end
end
end
end
close(hWaitbar);
wh.save([folderpath,experiment_name,'_wh']);
disp('Measurement complete')

View File

@@ -0,0 +1,97 @@
% Set your folder path here
folderPath = 'C:\Users\sioe\Documents\High_Speed_Measurement_2024\mpi_measurement\';
fileTimeStmp = 'testen20241028_163511';
fileBody = [fileTimeStmp,'_PAM_4_R_336000000000_DB_1_I_atten_'];
fileBits = [folderPath,fileBody,'0_bits'];
fileSymbols = [folderPath,fileBody,'0_symbols'];
fileWareHouse = [folderPath,fileTimeStmp,'_wh'];
Bits = load(fileBits,"Bits");Bits = Bits.Bits;
Symbols = load(fileSymbols);Symbols = Symbols.Symbols;
wh = load(fileWareHouse);wh = wh.obj;
M = wh.parameter.M.values(1);
cnt = 1;
for i_atten = 24%flip([0:3:30,45])
fileRx = [folderPath,fileBody,num2str(i_atten),'_rx_signal'];
S = load(fileRx);S = S.S;
Scpe_sig_raw = load([folderPath,fileBody,num2str(i_atten),'_raw_signal']);
Scpe_sig_raw = Scpe_sig_raw.Scpe_sig_raw;
Scpe_sig_raw.spectrum("displayname",'Raw signal','fignum',80,'normalizeTo0dB',1);
eq_values = min(numel(S),8);
Noi = cell(eq_values,1);
EQ_vnle= cell(eq_values,1);
EQ_ffe= cell(eq_values,1);
%ffe = EQ("Ne",[50,0,0],"Nb",[0,0,0],"training_length",4096*2,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.05,"DDmu",[0.0004 0.0004 0.0004 0.0004 ],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
vnle = EQ("Ne",[50,0,0],"Nb",[0,0,0],"training_length",4096*2,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.0,"DDmu",[0.0004 0.0004 0.0004 0.0004 ],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
parfor s = 1:eq_values
if 1
%VNLE
Scpe_sig_syncd = S{s};
[EQ_vnle{s}] = vnle.process(Scpe_sig_syncd,Symbols);
Noi{s} = EQ_vnle{s}-Symbols;
Rx_bits = PAMmapper(M,0).demap(EQ_vnle{s});
[~,~,ber_vnle(s),~] = calc_ber(Rx_bits.signal,Bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
end
%VNLE + MLSE
if 1
Noi{s}.signal = Noi{s}.signal - mean(Noi{s}.signal);
nc = 2;
burg_coeff = arburg(Noi{s}.signal,nc);
EQ_mlse = EQ_vnle{s}.filter(burg_coeff,1);
EQ_mlse = MLSE("DIR",burg_coeff,"duobinary_output",0,"M",M,"trellis_states",PAMmapper(M,0).levels).process(EQ_mlse);
Rx_bits = PAMmapper(M,0).demap(EQ_mlse);
[~,~,ber_vnle_mlse(s),~] = calc_ber(Rx_bits.signal,Bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
end
end
if 1
[~,s]=min(ber_vnle_mlse);
nc = 2;
burg_coeff = arburg(Noi{s}.signal,nc);
Noi{s}.spectrum('displayname','Noise PSD','fignum',123);
[h,w] = freqz(1,burg_coeff,length(Noi{s}),"whole",Noi{s}.fs);
h = h/max(abs(h));
hold on
w_ = (w - Noi{s}.fs/2);
plot(w_.*1e-9,20*log10(fftshift(h)),'DisplayName',['', num2str(nc), ' coefficients for burg alg.']);
end
disp(['VNLE EQ: BEST BER: ',sprintf('%.1E',min(ber_vnle)),' AVG BER: ',sprintf('%.1E',mean(ber_vnle)),' WORST:',sprintf('%.1E',max(ber_vnle)),'. Out of ',num2str(numel(ber_vnle))]);
disp(['VNLE+MLSE EQ: BEST BER: ',sprintf('%.1E',min(ber_vnle_mlse)),' AVG BER: ',sprintf('%.1E',mean(ber_vnle_mlse)),' WORST:',sprintf('%.1E',max(ber_vnle_mlse)),'. Out of ',num2str(numel(ber_vnle_mlse))]);
vnle_result(cnt) = min(ber_vnle);
mlse_result(cnt) = min(ber_vnle_mlse);
cnt=cnt+1;
end
i_atten = flip([0:3:30,45]);
figure(90)
plot(i_atten,mlse_result);
% Continue with the rest of your plot settings
title('MPI')
yline(3.8e-3, 'DisplayName', 'HD-FEC', 'LineStyle', '--', 'HandleVisibility', 'off');
xlabel('Bit Rate in GBps');
ylabel('Attenuation of I Branch');
set(gca, 'yscale', 'log');
set(gca, 'Box', 'on');
grid on;
grid minor;
legend('Interpreter', 'none');

View File

@@ -0,0 +1,87 @@
wh = load('C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\highspeed_oct_2024\10km_bitrate_complete\20241030_170224_wh.mat');
wh = wh.obj;
M_vals = wh.parameter.M.values;
M_choose = M_vals(1);
lambda_vals = wh.parameter.lambda.values;
bitrate_vals = wh.parameter.bitrate.values;
duobinary_vals = wh.parameter.duobinary.values;
rop_atten_vals = wh.parameter.rop_atten.values;
figure(11)
l = 6;
for m = 1:numel(M_vals)
sgtitle(['Lambda: ',num2str(lambda_vals(l)),' nm'])
%for l = 1:numel(lambda_vals)
ber_vnle = [];
ber_vnle_mlse= [];
ber_db= [];
ber_db_enc= [];
for b = 1:numel(bitrate_vals)
M_choose = M_vals(m);
cel = wh.getStoValue('ber_vnle',M_choose(1),lambda_vals(l),bitrate_vals(b),duobinary_vals(1),rop_atten_vals(1));
ber_vnle(b)=min(cel{1});
cel = wh.getStoValue('ber_vnle_mlse',M_choose(1),lambda_vals(l),bitrate_vals(b),duobinary_vals(1),rop_atten_vals(1));
ber_vnle_mlse(b)=min(cel{1});
cel = wh.getStoValue('ber_db',M_choose(1),lambda_vals(l),bitrate_vals(b),duobinary_vals(2),rop_atten_vals(1));
ber_db(b)=min(cel{1});
cel = wh.getStoValue('ber_db',M_choose(1),lambda_vals(l),bitrate_vals(b),duobinary_vals(3),rop_atten_vals(1));
ber_db_enc(b)=min(cel{1});
dcs_ = wh.getStoValue('dcs',M_choose(1),lambda_vals(l),bitrate_vals(b),duobinary_vals(2),rop_atten_vals(1));
end
cols = linspecer(4);
subplot(1,3,m)
if M_choose == 4
lst = '-';
mkr = 'o';
hv = 'on';
elseif M_choose == 6
lst = '-';
mkr = 'x';
hv = 'on';
elseif M_choose == 8
lst = '-';
mkr = 'diamond';
hv = 'on';
end
fsym_vals = floor( bitrate_vals*1e-9./log2(M_choose) );
hold on
plot(bitrate_vals*1e-9,ber_db,'Color',cols(1,:),'Marker',mkr,'MarkerFaceColor','auto','DisplayName','DB pre','LineStyle',lst,'HandleVisibility',hv,'LineWidth',1);
plot(bitrate_vals*1e-9,ber_db_enc,'Color',cols(2,:)','Marker',mkr,'MarkerFaceColor','auto','DisplayName','DB enc','LineStyle',lst,'HandleVisibility',hv,'LineWidth',1);
plot(bitrate_vals*1e-9,ber_vnle,'Color',cols(3,:),'Marker',mkr,'MarkerFaceColor','auto','DisplayName','VNLE','LineStyle',lst,'HandleVisibility',hv,'LineWidth',1);
plot(bitrate_vals*1e-9,ber_vnle_mlse,'Color',cols(4,:),'Marker',mkr,'MarkerFaceColor','auto','DisplayName','VNLE+PF+MLSE','LineStyle',lst,'HandleVisibility',hv,'LineWidth',1);
% Continue with the rest of your plot settings
yline(3.8e-3, 'DisplayName', 'HD-FEC', 'LineStyle', '--', 'HandleVisibility', 'off');
yline(2e-2, 'DisplayName', '20%', 'LineStyle', '--','LineWidth',1, 'HandleVisibility', 'off');
xlabel('Bitrate');
ylabel('Bit Error Rate (BER)');
title(['PAM ',num2str(M_choose),' ']);
set(gca, 'yscale', 'log');
set(gca, 'Box', 'on');
grid on;
grid minor;
legend('Interpreter', 'none','Location','southwest');
ylim([1e-4,1e-1]);
xlim([bitrate_vals(1)*1e-9,bitrate_vals(end)*1e-9])
%end
end