CLEANUP - changes to folder structure
This commit is contained in:
@@ -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);
|
||||
@@ -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
|
||||
|
||||
@@ -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]);
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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' ...
|
||||
% });
|
||||
@@ -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];
|
||||
@@ -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}',...
|
||||
});
|
||||
@@ -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;
|
||||
|
||||
% =======================================================================
|
||||
% (2–4) 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
|
||||
@@ -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
|
||||
@@ -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 ===
|
||||
@@ -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);
|
||||
@@ -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
|
||||
@@ -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' ...
|
||||
});
|
||||
Binary file not shown.
@@ -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
|
||||
@@ -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
|
||||
@@ -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]);
|
||||
|
||||
|
||||
%%
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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' ...
|
||||
} );
|
||||
@@ -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}',...
|
||||
% });
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
@@ -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])
|
||||
@@ -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
|
||||
@@ -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')
|
||||
@@ -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
|
||||
@@ -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');
|
||||
@@ -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;
|
||||
@@ -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');
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 |
Binary file not shown.
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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.');
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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);
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
341
projects/Advanced_DSP_for_400G_IMDD_experiments/baudrate_sweep.m
Normal file
341
projects/Advanced_DSP_for_400G_IMDD_experiments/baudrate_sweep.m
Normal 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)
|
||||
@@ -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]);
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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']);
|
||||
|
||||
|
||||
@@ -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')
|
||||
@@ -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');
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user