ML Equalizer works now.

Not yet perfectly integrated into all the routines
This commit is contained in:
Silas Oettinghaus
2025-11-12 09:24:02 +01:00
parent 39bc8243fc
commit 0080cb2264
44 changed files with 5289 additions and 2868 deletions

View File

@@ -1,13 +1,41 @@
classdef ML_MLSE < handle classdef ML_MLSE < handle
% Implementation of plain and simple FFE. % ALGORITHM DESCRIBED IN:
% 1) Training mode (stable performance when you use NLMS) % W. Lanneer and Y. Lefevre, Machine Learning-Based Pre-Equalizers for
% 2) Decision directed mode % Maximum Likelihood Sequence Estimation in High-Speed PONs,
% % in 2023 31st European Signal Processing Conference
%LMS: mu in order of 0.0001 for acceptable convergence speed
%NLMS: mu in order of 0.01 for acceptable convergence speed % Further ML Refs:
%RLS: mu is lambda -> 0.99 -> 1 (has a strong dependency on this! use a loop to find out best values) % https://machinelearningmastery.com/cross-entropy-for-machine-learning/
% % https://docs.pytorch.org/docs/stable/generated/torch.nn.CrossEntropyLoss.html
% FFE("epochs_tr",5,"epochs_dd",2,"len_tr",2^13,"mu_dd",mu_dd,"mu_tr",mu_tr,"order",25,"sps",2,"decide",0, "adaption",adaption_method(adaption),"dd_mode",use_dd_mode);
% The central idea is to overcome the (white-) noise assumption within the previously described
% Viterbi algorithm, more precisely a closed-loop optimization is proposed that finds a suitable
% filter-set to directly compute the branch metrics c_k (s,s^' ). These can directly be used to
% carry out the conventional Viterbi algorithm. The system consists of S^L S=F linear FIR filters,
% combined with one bias coefficient respectively. These filters take the received input samples to
% compute the branch metrics estimates (c_k ) ̂(s,s^' ) according toThe central idea is to overcome
% the (white-) noise assumption within the previously described Viterbi algorithm, more precisely
% a closed-loop optimization is proposed that finds a suitable filter-set to directly compute the
% branch metrics c_k (s,s^' ). These can directly be used to carry out the conventional Viterbi
% algorithm. The system consists of S^L S=F linear FIR filters, combined with one bias coefficient
% respectively. These filters take the received input samples to compute the branch metrics
% estimates. Finally, the usual Viterbi is carried out...
% Recommended Settings and some findings:
% Requires many training epochs. According to ML people, 100,200 or
% even up to 1000 epochs are normal for ML-convergence
% The mu parameter _can_ be adaptive - using the cross entropy and when
% analyzing the isolated training it looks very promisig. However, is
% later use I found this is not as stable as a fixed learning rate.
% mu = 0.1 worked good for me
% Longer orders/ filter length are not always better. For me order=11
% was good.
% Delay factor (delta) is good when the order is also increased. With
% order = 11, a delta of =4 shows good results
properties properties
sps % usually 2 sps % usually 2
@@ -24,6 +52,8 @@ classdef ML_MLSE < handle
mu_dd %weight update in dd mode mu_dd %weight update in dd mode
epochs_dd epochs_dd
adaptive_mu
constellation constellation
L %viterbi memory length L %viterbi memory length
@@ -50,11 +80,13 @@ classdef ML_MLSE < handle
w w
% --- New: fast state lookup --- % --- New: fast state lookup ---
true_to_state_idx
state_dict % containers.Map: key(sequence)->state index state_dict % containers.Map: key(sequence)->state index
key_fmt = '%.8g_'; % key format for sequence strings key_fmt = '%.8g_'; % key format for sequence strings
nSym % |constellation| nSym % |constellation|
ber = [] ber = []
ce = ones(1,1);
end end
methods methods
@@ -72,6 +104,8 @@ classdef ML_MLSE < handle
options.mu_dd = 1e-5; options.mu_dd = 1e-5;
options.epochs_dd = 5; options.epochs_dd = 5;
options.adaptive_mu = 1;
options.delta = 0; options.delta = 0;
options.traceback_depth = 1024; options.traceback_depth = 1024;
@@ -180,11 +214,12 @@ classdef ML_MLSE < handle
X_viterbi = X_viterbi.logbookentry(lbdesc); % append to logbook X_viterbi = X_viterbi.logbookentry(lbdesc); % append to logbook
end end
function [y,y_vit] = equalize(obj,x,d,mu,epochs,N,training) function [y,y_ref] = equalize(obj,x,d,mu,epochs,N,training)
% ============================================================== % ==============================================================
% FFE + Whitening + ML-Based Branch Metric Estimation + Viterbi % FFE + Whitening + ML-Based Branch Metric Estimation + Viterbi
% ============================================================== % ==============================================================
debug = 1; debug = 1;
showPlots = 1;
% --- Input padding and preallocation % --- Input padding and preallocation
y = zeros(N,1); y = zeros(N,1);
@@ -200,7 +235,8 @@ classdef ML_MLSE < handle
v_tilde = zeros(1,obj.nFeasible); v_tilde = zeros(1,obj.nFeasible);
pred = zeros(nSymbols, obj.nStates, 'uint32'); pred = zeros(nSymbols, obj.nStates, 'uint32');
pm_sto = nan(obj.nStates, nSymbols,'like',pm); pm_sto = nan(obj.nStates, nSymbols,'like',pm);
CE_accum = 0;
%%% START IDX %%% START IDX
if training if training
@@ -210,7 +246,7 @@ classdef ML_MLSE < handle
start_sample = 1; start_sample = 1;
end_sample = start_sample + (ceil(N/obj.sps)-1)*obj.sps; end_sample = start_sample + (ceil(N/obj.sps)-1)*obj.sps;
else else
start_sample = 1; start_sample = 1;%obj.len_tr;
end_sample = N; end_sample = N;
end end
@@ -251,34 +287,72 @@ classdef ML_MLSE < handle
% ===== Gradient update (Algorithm 1) ===== % ===== Gradient update (Algorithm 1) =====
if 1 %training if 1 %training
% previous "to" becomes current "from" (shift-register) % --- allocate storage once
true_from_state_idx = true_to_state_idx; if epoch == 1 && symbol == 1
obj.true_to_state_idx = ones(ceil(N/obj.sps),1,'uint32');
% --- Build current "to" state from ABSOLUTE symbol index
if sym_idx >= obj.L
curr_seq = d(sym_idx-obj.L+1 : sym_idx); % [d_k-L+1 ... d_k]
key_to = obj.seq_key(flip(curr_seq)); % -> [d_k ... d_k-L+1]
if isKey(obj.state_dict, key_to)
true_to_state_idx = obj.state_dict(key_to);
else
% Fall back safely (should not happen with proper constellation)
true_to_state_idx = true_from_state_idx;
end
else
% Not enough history yet for a full L-symbol state
% keep previous 'to' and 'from'
true_to_state_idx = true_to_state_idx;
true_from_state_idx = true_from_state_idx;
end end
% Dirac delta over correct extended transition (from,to) % --- previous "to" becomes current "from"
if symbol > 1
true_from_state_idx = obj.true_to_state_idx(symbol-1);
else
true_from_state_idx = 1;
end
% --- compute or reuse "to" state
if epoch == 1
% only compute in first epoch
if sym_idx >= obj.L
key_to = obj.seq_key(flip(d(sym_idx-obj.L+1 : sym_idx)));
if isKey(obj.state_dict, key_to)
obj.true_to_state_idx(symbol) = obj.state_dict(key_to);
else
obj.true_to_state_idx(symbol) = true_from_state_idx;
end
else
obj.true_to_state_idx(symbol) = true_from_state_idx;
end
end
% --- reuse cached state from second epoch onward
true_to_state_idx = obj.true_to_state_idx(symbol);
% --- ensure valid (from,to)
dirac = zeros(obj.nFeasible,1); dirac = zeros(obj.nFeasible,1);
dirac(obj.valid_from_idx==true_from_state_idx & ... mask = obj.valid_from_idx==true_from_state_idx & ...
obj.valid_to_idx ==true_to_state_idx) = 1; obj.valid_to_idx ==true_to_state_idx;
if any(mask)
dirac(mask) = 1;
else
idx = find(obj.valid_from_idx==true_from_state_idx,1,'first');
dirac(idx) = 1;
obj.true_to_state_idx(symbol) = obj.valid_to_idx(idx);
end
% softmax over -v_tilde (numerically safe shift) % softmax over -v_tilde (numerically safe shift)
p = exp(-(v_tilde - max(v_tilde))); v_shift = -(v_tilde - min(v_tilde)); % shift to small positive numbers
p = p./(sum(p)+eps); v_shift = min(v_shift, 100); % clamp exponent argument ( exp(50)=3e21)
expv = exp(v_shift);
p = expv ./ (sum(expv) + eps);
% for logging only:
CE_symbol(symbol) = -log(p(dirac==1) + eps);
if sym_idx > obj.L
CE_smooth(symbol) = 0.01*CE_symbol(symbol) + 0.99*CE_smooth(symbol-1);
else
if epoch > 1
CE_smooth(symbol) = obj.ce(end); %use ce from last epoch or =1 for very first round?!
else
CE_smooth(symbol) = CE_symbol(symbol);
end
end
CE_accum = CE_symbol(symbol) + CE_accum;
% gradient term (t - p) % gradient term (t - p)
dmp = (dirac - p)'; % 1×nFeasible dmp = (dirac - p)'; % 1×nFeasible
@@ -288,10 +362,14 @@ classdef ML_MLSE < handle
% Start updates only when the ABSOLUTE symbol index has L history % Start updates only when the ABSOLUTE symbol index has L history
if sym_idx >= obj.L if sym_idx >= obj.L
if obj.adaptive_mu
mu_eff = CE_smooth(sym_idx);
mu_eff = max(min(mu_eff, 0.2), 1e-4);
else
mu_eff = mu;
end
obj.w = obj.w - mu_eff .* dL_Dw; % (Nf+1)×nFeasible
obj.w = obj.w - ones(size(dL_Dw,1),1).*mu .* dL_Dw; % (Nf+1)×nFeasible
% obj.w = obj.w - mu * dL_Dw; % (Nf+1)×nFeasible
end end
% if debug && epoch > 2 % if debug && epoch > 2
@@ -335,42 +413,69 @@ classdef ML_MLSE < handle
viterbi_path(n-1) = pred(n, viterbi_path(n)); viterbi_path(n-1) = pred(n, viterbi_path(n));
end end
y_vit = obj.first_sym(viterbi_path); y_ref = d(start_symbol:end);
y = obj.first_sym(viterbi_path); y = obj.first_sym(viterbi_path);
if debug %&& training if debug && training
sym_start = start_symbol; sym_start = start_symbol;
sym_end = start_symbol + symbol - 1; sym_end = start_symbol + symbol - 1;
ref_slice = d(sym_start : sym_end); ref_slice = d(sym_start : sym_end);
err = sum(y ~= ref_slice(1:numel(y))); err = sum(y ~= ref_slice(1:numel(y)));
ref_bits = PAMmapper(obj.S,0).demap(ref_slice); try
eq_bits = PAMmapper(obj.S,0).demap(y); ref_bits = PAMmapper(obj.S,0).demap(ref_slice);
[~, ~, ber, ~] = calc_ber(ref_bits, eq_bits, "skip_front", 10, "skip_end", 10, "returnErrorLocation", 1); eq_bits = PAMmapper(obj.S,0).demap(y);
fprintf('Epoch: %d - BER: %.1e \n',epoch, ber); [~, ~, ber, ~] = calc_ber(ref_bits, eq_bits, "skip_front", 10, "skip_end", 10, "returnErrorLocation", 1);
fprintf('Epoch: %d - BER: %.1e \n',epoch, ber);
obj.ber(epoch) = ber; obj.ber(epoch) = ber;
catch
ser = err./length(y);
fprintf('Epoch: %d - SER: %.1e \n',epoch, ser);
end
% ser = err./length(y); obj.ce(epoch) = CE_accum./symbol;
% fprintf('Epoch: %d - SER: %.1e \n',epoch, ser);
figure(10); if showPlots
subplot(2,2,1:2); figure(10);clf
heatmap(obj.w); subplot(3,2,1:2);
title('Filter') heatmap(obj.w);
title('Filter')
subplot(2,2,3);
v_tildemat = NaN(obj.nStates, obj.nStates); subplot(3,2,3);
v_tildemat(obj.valid) = v_tilde; % log-domain scores v_tildemat = NaN(obj.nStates, obj.nStates);
heatmap(v_tildemat); v_tildemat(obj.valid) = v_tilde; % log-domain scores
title('Path Metrics (v_tilde)') heatmap(v_tildemat);
title('Path Metrics (v_tilde)')
subplot(2,2,4);
scatter(1:symbol,pm_sto,1,'.') subplot(3,2,4);
% plot(1:symbol,pm_sto,'LineStyle','none') scatter(1:symbol,pm_sto,1,'.')
title('Path Metric Winners') title('Path Metric Winners')
drawnow subplot(3,2,5);hold on
scatter(1:symbol,CE_symbol,1,'.');
scatter(1:symbol,CE_smooth,1,'.')
title('Cross Entropy')
subplot(3,2,6); hold on
% Left y-axis: Cross Entropy (linear)
yyaxis left
scatter(1:length(obj.ce), obj.ce, 10, 's', 'filled')
ylabel('Cross Entropy')
% Right y-axis: BER (logarithmic)
yyaxis right
scatter(1:length(obj.ber), obj.ber, 10, 'd', 'filled')
set(gca, 'YScale', 'log')
ylabel('BER (log scale)')
xlim([1, epochs])
xlabel('Epoch')
title('Cross Entropy // BER')
grid on
drawnow
end
end end
end end
end end

View File

@@ -118,7 +118,7 @@ classdef MLSE < handle
elseif trellis_state_mode == 2 %simply use the states from the ref signal (should be a robust option) elseif trellis_state_mode == 2 %simply use the states from the ref signal (should be a robust option)
obj.trellis_states = reshape(unique(data_ref),size(obj.trellis_states)); obj.trellis_states = reshape(unique(data_ref),1,length(unique(data_ref)));
elseif trellis_state_mode == 3 %use_statistical_levels elseif trellis_state_mode == 3 %use_statistical_levels

View File

@@ -16,9 +16,9 @@ classdef Metricstruct
SNR (1,1) double {mustBeNumeric} = NaN SNR (1,1) double {mustBeNumeric} = NaN
SNR_level (:,1) double {mustBeNumeric} = [] SNR_level (:,1) double {mustBeNumeric} = []
STD (1,1) double {mustBeNumeric} = NaN STD (1,1) double {mustBeNumeric} = NaN
STD_level (:,1) double {mustBeNumeric, mustBeNonnegative} = [] STD_level (:,1) double = []
STDrx (1,1) double {mustBeNumeric} = NaN STDrx (1,1) double {mustBeNumeric} = NaN
STDrx_level (:,1) double {mustBeNumeric, mustBeNonnegative} = [] STDrx_level (:,1) double = []
EVM (1,1) double {mustBeNumeric} = NaN EVM (1,1) double {mustBeNumeric} = NaN
EVM_level (:,1) double {mustBeNumeric} = [] EVM_level (:,1) double {mustBeNumeric} = []

View File

@@ -1,251 +1,251 @@
% Script, that shows the data management routine :-) % Script, that shows the data management routine :-)
loadExistingWareHouse = 0; loadExistingWareHouse = 0;
if loadExistingWareHouse if loadExistingWareHouse
[file, path] = uigetfile(); [file, path] = uigetfile();
wh = load([path filesep file]); wh = load([path filesep file]);
wh = wh.wh; wh = wh.wh;
wh.showInfo; wh.showInfo;
else else
% 1) Define all your parameters, best practice directly constructs a % 1) Define all your parameters, best practice directly constructs a
% structure % structure
params = struct; params = struct;
params.l = [2,10]; params.l = [2,10];
params.dispersion = [0]; params.dispersion = [0];
params.sgm = [0]; params.sgm = [0];
% params.pol = ["YXYXYXYX","YXXYYXXY","YYYYYYYY"]; % params.pol = ["YXYXYXYX","YXXYYXXY","YYYYYYYY"];
params.pol = ["alternated","paired","copolarized"]; params.pol = ["alternated","paired","copolarized"];
params.p_in = [3]; params.p_in = [3];
params.p_out = [-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2]; params.p_out = [-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2];
params.pmd = [0.1]; params.pmd = [0.1];
params.gamma = [0.0023]; params.gamma = [0.0023];
params.realization = [1:20]; params.realization = [1:20];
params.numchannels = [16]; params.numchannels = [16];
params.center_wavelength = floor([getSweepWavelengths(35, 50e9, 1310)] .* 1000) ./ 1000 ; params.center_wavelength = floor([getSweepWavelengths(35, 50e9, 1310)] .* 1000) ./ 1000 ;
params.center_wavelength = [1285 1287 1290 1292 1295]; params.center_wavelength = [1285 1287 1290 1292 1295];
params.center_wavelength = 1310; params.center_wavelength = 1310;
params.channelspacing = [400e9]; params.channelspacing = [400e9];
params.random_zdw = [0]; params.random_zdw = [0];
%wh = warehouse :-) %wh = warehouse :-)
wh = DataStorage(params); wh = DataStorage(params);
wh.showInfo; wh.showInfo;
wh.addStorage("ber"); wh.addStorage("ber");
wh.addStorage("totalBer"); wh.addStorage("totalBer");
end end
%2) Simulate a bunch of data - TO BE IMPLEMENTED HERE - for now use scripts %2) Simulate a bunch of data - TO BE IMPLEMENTED HERE - for now use scripts
%from Sebastian %from Sebastian
%3) Once the simulation folder is around, specifiy path and analyze dirs %3) Once the simulation folder is around, specifiy path and analyze dirs
path = uigetdir('C:\Users\Silas\Documents\MATLAB\Raw_Cluster_Simulations'); path = uigetdir('C:\Users\Silas\Documents\MATLAB\Raw_Cluster_Simulations');
allMat = getAllFilesInFolder(path,'.mat'); allMat = getAllFilesInFolder(path,'.mat');
allErr = getAllFilesInFolder(path,'.err'); allErr = getAllFilesInFolder(path,'.err');
%allMat = dir([path filesep '*.mat']); %allMat = dir([path filesep '*.mat']);
%allErr = dir([path filesep '*.err']); %allErr = dir([path filesep '*.err']);
if numel(allMat) == 0 if numel(allMat) == 0
warning('You defined an empty folder. Could not locate any .mat file.') warning('You defined an empty folder. Could not locate any .mat file.')
else else
fprintf('%-20s', 'Err Files:'); fprintf('%-12s', num2str(numel(allErr))); fprintf('\n'); fprintf('%-20s', 'Err Files:'); fprintf('%-12s', num2str(numel(allErr))); fprintf('\n');
fprintf('%-20s', 'Mat Files:'); fprintf('%-12s', num2str(numel(allMat))); fprintf('\n'); fprintf('%-20s', 'Mat Files:'); fprintf('%-12s', num2str(numel(allMat))); fprintf('\n');
fprintf('%-20s', 'Missing Mat Files:'); fprintf('%-12s', num2str(numel(allErr)-numel(allMat))); fprintf('\n'); fprintf('%-20s', 'Missing Mat Files:'); fprintf('%-12s', num2str(numel(allErr)-numel(allMat))); fprintf('\n');
end end
%4) Now load that data %4) Now load that data
f = waitbar(0,'Please wait...'); f = waitbar(0,'Please wait...');
cnt = 0; cnt = 0;
for num = 1:numel(allMat) for num = 1:numel(allMat)
fileName = allMat(num).name; fileName = allMat(num).name;
fileFolder = allMat(num).path; fileFolder = allMat(num).path;
fileExt = allMat(num).ext; fileExt = allMat(num).ext;
% %
matFile = load([fileFolder filesep fileName fileExt]); matFile = load([fileFolder filesep fileName fileExt]);
matFile = matFile.loop_data; matFile = matFile.loop_data;
% ____________________________________ % ____________________________________
% FIND THE DATAPOINT CURRENTLY LOADED % FIND THE DATAPOINT CURRENTLY LOADED
zdw = 1310; zdw = 1310;
channelplan = "symmetric"; channelplan = "symmetric";
channelspacing = str2double(strrep(regexp(fileName,'(_chsp)+([\d]*)','match'),'_chsp','')).*1e9; channelspacing = str2double(strrep(regexp(fileName,'(_chsp)+([\d]*)','match'),'_chsp','')).*1e9;
numchannels = str2double(strrep(regexp(fileName,'(ch)+(_)+([\d]*)','match'),'ch_','')); numchannels = str2double(strrep(regexp(fileName,'(ch)+(_)+([\d]*)','match'),'ch_',''));
center_wavelength = str2double(insertAfter(strrep(regexp(fileName,'(lambda)+([\d]*)','match'),'lambda',''),4,'.')); center_wavelength = str2double(insertAfter(strrep(regexp(fileName,'(lambda)+([\d]*)','match'),'lambda',''),4,'.'));
center_wavelength = floor(center_wavelength * 1000) / 1000; center_wavelength = floor(center_wavelength * 1000) / 1000;
if center_wavelength == 2192 if center_wavelength == 2192
continue continue
end end
center_wavelength = 1310; center_wavelength = 1310;
random_zdw = str2double(strrep(regexp(fileName,'(rzwd)+([\d])','match'),'rzwd','')); random_zdw = str2double(strrep(regexp(fileName,'(rzwd)+([\d])','match'),'rzwd',''));
l = str2double(strrep(regexp(fileName,'([L])+(_)+([\d]*)','match'),'L_','')); l = str2double(strrep(regexp(fileName,'([L])+(_)+([\d]*)','match'),'L_',''));
d = str2double(strrep(regexp(fileName,'([D])+(_)+([\d]*)','match'),'D_','')); d = str2double(strrep(regexp(fileName,'([D])+(_)+([\d]*)','match'),'D_',''));
if d == 0 if d == 0
sgm = false; sgm = false;
else else
sgm = true; sgm = true;
end end
if numel(regexp(fileName,'(YYYY)','match')) > 1 if numel(regexp(fileName,'(YYYY)','match')) > 1
pol = "copolarized"; pol = "copolarized";
elseif numel(regexp(fileName,'(YXXY)','match')) > 1 elseif numel(regexp(fileName,'(YXXY)','match')) > 1
pol = "paired"; pol = "paired";
elseif numel(regexp(fileName,'(YXYX)','match')) > 1 elseif numel(regexp(fileName,'(YXYX)','match')) > 1
pol = "alternated"; pol = "alternated";
else else
pol = "copolarized"; pol = "copolarized";
end end
p_in = str2double(strrep(regexp(fileName,'(pow_)+([-,\d]{1})','match'),'pow_','')); p_in = str2double(strrep(regexp(fileName,'(pow_)+([-,\d]{1})','match'),'pow_',''));
pmd = 0.1; pmd = 0.1;
gamma = 0.0023; gamma = 0.0023;
realiz = str2double(strrep(regexp(fileName,'(r)+([-,\d]{1,3})','match'),'r','')); realiz = str2double(strrep(regexp(fileName,'(r)+([-,\d]{1,3})','match'),'r',''));
% ____________________________________ % ____________________________________
% Get the information you want from current file % Get the information you want from current file
rop=[]; rop=[];
ber = []; ber = [];
for pow = 2:12 for pow = 2:12
module_number = ''; module_number = '';
for p = 1:11 %11 because there are 11 ROP branches in model for p = 1:11 %11 because there are 11 ROP branches in model
% get ROP % get ROP
if p == 1 if p == 1
p_out = matFile.dp_optatten_para.atten; p_out = matFile.dp_optatten_para.atten;
else else
p_out = matFile.("dp_optatten__"+(p)+"_para").atten; p_out = matFile.("dp_optatten__"+(p)+"_para").atten;
end end
p_out = round(p_out-10*log10(numel(matFile.config.parameters.common.wavelengthPlan))); p_out = round(p_out-10*log10(numel(matFile.config.parameters.common.wavelengthPlan)));
for c = 1:numel(matFile.config.parameters.common.wavelengthPlan) for c = 1:numel(matFile.config.parameters.common.wavelengthPlan)
ber(c) = matFile.("prms_compare_wdm__"+(p+1)+"_out"){1,c}.ber; ber(c) = matFile.("prms_compare_wdm__"+(p+1)+"_out"){1,c}.ber;
end end
totalBer = matFile.("prms_compare_wdm__"+(p+1)+"_out"){1,end}.totalBer; totalBer = matFile.("prms_compare_wdm__"+(p+1)+"_out"){1,end}.totalBer;
if totalBer > 0.2 && channelspacing == 400e9 && pol == "alternated" if totalBer > 0.2 && channelspacing == 400e9 && pol == "alternated"
disp("stopping here"); disp("stopping here");
pause; pause;
end end
% ____________________________________ % ____________________________________
% Add value to warehouse at the correct position % Add value to warehouse at the correct position
wh.addValueToStorage(ber,'ber',l,d,sgm,pol,p_in,p_out,pmd,gamma,realiz,numchannels, center_wavelength,channelspacing,random_zdw); wh.addValueToStorage(ber,'ber',l,d,sgm,pol,p_in,p_out,pmd,gamma,realiz,numchannels, center_wavelength,channelspacing,random_zdw);
wh.getStoValue('ber',l,d,sgm,pol,p_in,p_out,pmd,gamma,realiz,numchannels, center_wavelength,channelspacing,random_zdw); wh.getStoValue('ber',l,d,sgm,pol,p_in,p_out,pmd,gamma,realiz,numchannels, center_wavelength,channelspacing,random_zdw);
wh.addValueToStorage(totalBer,'totalBer',l,d,sgm,pol,p_in,p_out,pmd,gamma,realiz,numchannels,center_wavelength,channelspacing,random_zdw); wh.addValueToStorage(totalBer,'totalBer',l,d,sgm,pol,p_in,p_out,pmd,gamma,realiz,numchannels,center_wavelength,channelspacing,random_zdw);
end end
end end
waitbar(num/numel(allMat),f,'Loading your data'); waitbar(num/numel(allMat),f,'Loading your data');
end end
close(f) close(f)
% 4) Hey! the warehouse is here and (hopefully) filled with data :-) % 4) Hey! the warehouse is here and (hopefully) filled with data :-)
% Create a save dialog % Create a save dialog
defaultDir = 'C:\Users\Silas\Documents\MATLAB\Raw_Cluster_Simulations\'; defaultDir = 'C:\Users\Silas\Documents\MATLAB\Raw_Cluster_Simulations\';
defaultExt = '*.mat'; defaultExt = '*.mat';
[filename, pathname] = uiputfile(fullfile(defaultDir, defaultExt),'', 'wh.mat'); [filename, pathname] = uiputfile(fullfile(defaultDir, defaultExt),'', 'wh.mat');
% Check if the user pressed Cancel % Check if the user pressed Cancel
if isequal(filename, 0) || isequal(pathname, 0) if isequal(filename, 0) || isequal(pathname, 0)
disp('Save operation canceled.'); disp('Save operation canceled.');
else else
% Save the variable to the selected file % Save the variable to the selected file
save(fullfile(pathname, filename), 'wh'); save(fullfile(pathname, filename), 'wh');
disp(['Variable "wh" saved to: ', fullfile(pathname, filename)]); disp(['Variable "wh" saved to: ', fullfile(pathname, filename)]);
end end
function matFileStructArray = getAllFilesInFolder(folderPath,extension) function matFileStructArray = getAllFilesInFolder(folderPath,extension)
% Get a list of all files in the current folder % Get a list of all files in the current folder
currentFolderFiles = dir(fullfile(folderPath, '*')); currentFolderFiles = dir(fullfile(folderPath, '*'));
% Exclude '.' and '..' directories % Exclude '.' and '..' directories
currentFolderFiles = currentFolderFiles(~ismember({currentFolderFiles.name}, {'.', '..'})); currentFolderFiles = currentFolderFiles(~ismember({currentFolderFiles.name}, {'.', '..'}));
% Initialize the structure array for .mat files % Initialize the structure array for .mat files
matFileStructArray = struct('path', {}, 'name', {}, 'ext', {}); matFileStructArray = struct('path', {}, 'name', {}, 'ext', {});
% Loop over each file in the current folder % Loop over each file in the current folder
for i = 1:length(currentFolderFiles) for i = 1:length(currentFolderFiles)
currentFile = currentFolderFiles(i); currentFile = currentFolderFiles(i);
% Check if the current item is a file and has a .mat extension % Check if the current item is a file and has a .mat extension
if ~currentFile.isdir && endsWith(currentFile.name, extension, 'IgnoreCase', true) if ~currentFile.isdir && endsWith(currentFile.name, extension, 'IgnoreCase', true)
% If it's a .mat file, add it to the structure array % If it's a .mat file, add it to the structure array
[matFileStructArray(end + 1).path,matFileStructArray(end+1).name, matFileStructArray(end+1).ext] = fileparts(fullfile(folderPath, currentFile.name)); [matFileStructArray(end + 1).path,matFileStructArray(end+1).name, matFileStructArray(end+1).ext] = fileparts(fullfile(folderPath, currentFile.name));
elseif currentFile.isdir elseif currentFile.isdir
% If it's a directory, recursively call the function % If it's a directory, recursively call the function
subfolderPath = fullfile(folderPath, currentFile.name); subfolderPath = fullfile(folderPath, currentFile.name);
subfolderMatFiles = getAllFilesInFolder(subfolderPath,extension); subfolderMatFiles = getAllFilesInFolder(subfolderPath,extension);
% Add .mat files from the subfolder to the structure array % Add .mat files from the subfolder to the structure array
matFileStructArray = [matFileStructArray, subfolderMatFiles]; matFileStructArray = [matFileStructArray, subfolderMatFiles];
end end
end end
end end

View File

@@ -1,250 +1,250 @@
% Script, that shows the data management routine :-) % Script, that shows the data management routine :-)
loadExistingWareHouse = 0; loadExistingWareHouse = 0;
if loadExistingWareHouse if loadExistingWareHouse
[file, path] = uigetfile(); [file, path] = uigetfile();
wh = load([path filesep file]); wh = load([path filesep file]);
wh = wh.wh; wh = wh.wh;
wh.showInfo; wh.showInfo;
else else
% 1) Define all your parameters, best practice directly constructs a % 1) Define all your parameters, best practice directly constructs a
% structure % structure
params = struct; params = struct;
params.l = [2, 10]; params.l = [2, 10];
params.dispersion = [0, 3]; params.dispersion = [0, 3];
params.sgm = [0, 1]; params.sgm = [0, 1];
% params.pol = ["YXYXYXYX","YXXYYXXY","YYYYYYYY"]; % params.pol = ["YXYXYXYX","YXXYYXXY","YYYYYYYY"];
params.pol = ["alternated","paired","copolarized"]; params.pol = ["alternated","paired","copolarized"];
params.p_in = [3]; params.p_in = [3];
params.p_out = [-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2]; params.p_out = [-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2];
params.pmd = [0.1]; params.pmd = [0.1];
params.gamma = [0.0023]; params.gamma = [0.0023];
params.realization = [1:20]; params.realization = [1:20];
params.numchannels = [1,2,4,8,16]; params.numchannels = [1,2,4,8,16];
params.center_wavelength = floor([getSweepWavelengths(35, 50e9, 1310)] .* 1000) ./ 1000 ; params.center_wavelength = floor([getSweepWavelengths(35, 50e9, 1310)] .* 1000) ./ 1000 ;
params.center_wavelength = [1285 1287 1290 1292 1295]; params.center_wavelength = [1285 1287 1290 1292 1295];
params.center_wavelength = 1310; params.center_wavelength = 1310;
params.channelspacing = [400e9]; params.channelspacing = [400e9];
params.random_zdw = [0,1]; params.random_zdw = [0,1];
%wh = warehouse :-) %wh = warehouse :-)
wh = DataStorage(params); wh = DataStorage(params);
wh.showInfo; wh.showInfo;
wh.addStorage("ber"); wh.addStorage("ber");
wh.addStorage("totalBer"); wh.addStorage("totalBer");
end end
%2) Simulate a bunch of data - TO BE IMPLEMENTED HERE - for now use scripts %2) Simulate a bunch of data - TO BE IMPLEMENTED HERE - for now use scripts
%from Sebastian %from Sebastian
%3) Once the simulation folder is around, specifiy path and analyze dirs %3) Once the simulation folder is around, specifiy path and analyze dirs
path = uigetdir('C:\Users\Silas\Documents\MATLAB\Raw_Cluster_Simulations'); path = uigetdir('C:\Users\Silas\Documents\MATLAB\Raw_Cluster_Simulations');
allMat = getAllFilesInFolder(path,'.mat'); allMat = getAllFilesInFolder(path,'.mat');
allErr = getAllFilesInFolder(path,'.err'); allErr = getAllFilesInFolder(path,'.err');
%allMat = dir([path filesep '*.mat']); %allMat = dir([path filesep '*.mat']);
%allErr = dir([path filesep '*.err']); %allErr = dir([path filesep '*.err']);
if numel(allMat) == 0 if numel(allMat) == 0
warning('You defined an empty folder. Could not locate any .mat file.') warning('You defined an empty folder. Could not locate any .mat file.')
else else
fprintf('%-20s', 'Err Files:'); fprintf('%-12s', num2str(numel(allErr))); fprintf('\n'); fprintf('%-20s', 'Err Files:'); fprintf('%-12s', num2str(numel(allErr))); fprintf('\n');
fprintf('%-20s', 'Mat Files:'); fprintf('%-12s', num2str(numel(allMat))); fprintf('\n'); fprintf('%-20s', 'Mat Files:'); fprintf('%-12s', num2str(numel(allMat))); fprintf('\n');
fprintf('%-20s', 'Missing Mat Files:'); fprintf('%-12s', num2str(numel(allErr)-numel(allMat))); fprintf('\n'); fprintf('%-20s', 'Missing Mat Files:'); fprintf('%-12s', num2str(numel(allErr)-numel(allMat))); fprintf('\n');
end end
%4) Now load that data %4) Now load that data
f = waitbar(0,'Please wait...'); f = waitbar(0,'Please wait...');
cnt = 0; cnt = 0;
for num = 1:numel(allMat) for num = 1:numel(allMat)
fileName = allMat(num).name; fileName = allMat(num).name;
fileFolder = allMat(num).path; fileFolder = allMat(num).path;
fileExt = allMat(num).ext; fileExt = allMat(num).ext;
% %
matFile = load([fileFolder filesep fileName fileExt]); matFile = load([fileFolder filesep fileName fileExt]);
matFile = matFile.loop_data; matFile = matFile.loop_data;
% ____________________________________ % ____________________________________
% FIND THE DATAPOINT CURRENTLY LOADED % FIND THE DATAPOINT CURRENTLY LOADED
zdw = 1310; zdw = 1310;
channelplan = "symmetric"; channelplan = "symmetric";
channelspacing = str2double(strrep(regexp(fileName,'(_chsp)+([\d]*)','match'),'_chsp','')).*1e9; channelspacing = str2double(strrep(regexp(fileName,'(_chsp)+([\d]*)','match'),'_chsp','')).*1e9;
numchannels = str2double(strrep(regexp(fileName,'(ch)+(_)+([\d]*)','match'),'ch_','')); numchannels = str2double(strrep(regexp(fileName,'(ch)+(_)+([\d]*)','match'),'ch_',''));
center_wavelength = str2double(insertAfter(strrep(regexp(fileName,'(lambda)+([\d]*)','match'),'lambda',''),4,'.')); center_wavelength = str2double(insertAfter(strrep(regexp(fileName,'(lambda)+([\d]*)','match'),'lambda',''),4,'.'));
center_wavelength = floor(center_wavelength * 1000) / 1000; center_wavelength = floor(center_wavelength * 1000) / 1000;
if center_wavelength == 2192 if center_wavelength == 2192
continue continue
end end
center_wavelength = 1310; center_wavelength = 1310;
random_zdw = str2double(strrep(regexp(fileName,'(rzwd)+([\d])','match'),'rzwd','')); random_zdw = str2double(strrep(regexp(fileName,'(rzwd)+([\d])','match'),'rzwd',''));
l = str2double(strrep(regexp(fileName,'([L])+(_)+([\d]*)','match'),'L_','')); l = str2double(strrep(regexp(fileName,'([L])+(_)+([\d]*)','match'),'L_',''));
d = str2double(strrep(regexp(fileName,'([D])+(_)+([\d]*)','match'),'D_','')); d = str2double(strrep(regexp(fileName,'([D])+(_)+([\d]*)','match'),'D_',''));
if d == 0 if d == 0
sgm = false; sgm = false;
else else
sgm = true; sgm = true;
end end
if numel(regexp(fileName,'(YYYY)','match')) > 1 if numel(regexp(fileName,'(YYYY)','match')) > 1
pol = "copolarized"; pol = "copolarized";
elseif numel(regexp(fileName,'(YXXY)','match')) > 1 elseif numel(regexp(fileName,'(YXXY)','match')) > 1
pol = "paired"; pol = "paired";
elseif numel(regexp(fileName,'(YXYX)','match')) > 1 elseif numel(regexp(fileName,'(YXYX)','match')) > 1
pol = "alternated"; pol = "alternated";
else else
pol = "copolarized"; pol = "copolarized";
end end
p_in = str2double(strrep(regexp(fileName,'(pow_)+([-,\d]{1})','match'),'pow_','')); p_in = str2double(strrep(regexp(fileName,'(pow_)+([-,\d]{1})','match'),'pow_',''));
pmd = 0.1; pmd = 0.1;
gamma = 0.0023; gamma = 0.0023;
realiz = str2double(strrep(regexp(fileName,'(r)+([-,\d]{1,3})','match'),'r','')); realiz = str2double(strrep(regexp(fileName,'(r)+([-,\d]{1,3})','match'),'r',''));
% ____________________________________ % ____________________________________
% Get the information you want from current file % Get the information you want from current file
rop=[]; rop=[];
ber = []; ber = [];
for pow = 2:12 for pow = 2:12
module_number = ''; module_number = '';
for p = 1:11 %11 because there are 11 ROP branches in model for p = 1:11 %11 because there are 11 ROP branches in model
% get ROP % get ROP
if p == 1 if p == 1
p_out = matFile.dp_optatten_para.atten; p_out = matFile.dp_optatten_para.atten;
else else
p_out = matFile.("dp_optatten__"+(p)+"_para").atten; p_out = matFile.("dp_optatten__"+(p)+"_para").atten;
end end
p_out = round(p_out-10*log10(numel(matFile.config.parameters.common.wavelengthPlan))); p_out = round(p_out-10*log10(numel(matFile.config.parameters.common.wavelengthPlan)));
for c = 1:numel(matFile.config.parameters.common.wavelengthPlan) for c = 1:numel(matFile.config.parameters.common.wavelengthPlan)
ber(c) = matFile.("prms_compare_wdm__"+(p+1)+"_out"){1,c}.ber; ber(c) = matFile.("prms_compare_wdm__"+(p+1)+"_out"){1,c}.ber;
end end
totalBer = matFile.("prms_compare_wdm__"+(p+1)+"_out"){1,end}.totalBer; totalBer = matFile.("prms_compare_wdm__"+(p+1)+"_out"){1,end}.totalBer;
if totalBer > 0.2 && channelspacing == 400e9 && pol == "alternated" if totalBer > 0.2 && channelspacing == 400e9 && pol == "alternated"
disp("stopping here"); disp("stopping here");
pause; pause;
end end
% ____________________________________ % ____________________________________
% Add value to warehouse at the correct position % Add value to warehouse at the correct position
wh.addValueToStorage(ber,'ber',l,d,sgm,pol,p_in,p_out,pmd,gamma,realiz,numchannels, center_wavelength,channelspacing,random_zdw); wh.addValueToStorage(ber,'ber',l,d,sgm,pol,p_in,p_out,pmd,gamma,realiz,numchannels, center_wavelength,channelspacing,random_zdw);
wh.getStoValue('ber',l,d,sgm,pol,p_in,p_out,pmd,gamma,realiz,numchannels, center_wavelength,channelspacing,random_zdw); wh.getStoValue('ber',l,d,sgm,pol,p_in,p_out,pmd,gamma,realiz,numchannels, center_wavelength,channelspacing,random_zdw);
wh.addValueToStorage(totalBer,'totalBer',l,d,sgm,pol,p_in,p_out,pmd,gamma,realiz,numchannels,center_wavelength,channelspacing,random_zdw); wh.addValueToStorage(totalBer,'totalBer',l,d,sgm,pol,p_in,p_out,pmd,gamma,realiz,numchannels,center_wavelength,channelspacing,random_zdw);
end end
end end
waitbar(num/numel(allMat),f,'Loading your data'); waitbar(num/numel(allMat),f,'Loading your data');
end end
close(f) close(f)
% 4) Hey! the warehouse is here and (hopefully) filled with data :-) % 4) Hey! the warehouse is here and (hopefully) filled with data :-)
% Create a save dialog % Create a save dialog
defaultDir = 'C:\Users\Silas\Documents\MATLAB\Raw_Cluster_Simulations\'; defaultDir = 'C:\Users\Silas\Documents\MATLAB\Raw_Cluster_Simulations\';
defaultExt = '*.mat'; defaultExt = '*.mat';
[filename, pathname] = uiputfile(fullfile(defaultDir, defaultExt),'', 'wh.mat'); [filename, pathname] = uiputfile(fullfile(defaultDir, defaultExt),'', 'wh.mat');
% Check if the user pressed Cancel % Check if the user pressed Cancel
if isequal(filename, 0) || isequal(pathname, 0) if isequal(filename, 0) || isequal(pathname, 0)
disp('Save operation canceled.'); disp('Save operation canceled.');
else else
% Save the variable to the selected file % Save the variable to the selected file
save(fullfile(pathname, filename), 'wh'); save(fullfile(pathname, filename), 'wh');
disp(['Variable "wh" saved to: ', fullfile(pathname, filename)]); disp(['Variable "wh" saved to: ', fullfile(pathname, filename)]);
end end
function matFileStructArray = getAllFilesInFolder(folderPath,extension) function matFileStructArray = getAllFilesInFolder(folderPath,extension)
% Get a list of all files in the current folder % Get a list of all files in the current folder
currentFolderFiles = dir(fullfile(folderPath, '*')); currentFolderFiles = dir(fullfile(folderPath, '*'));
% Exclude '.' and '..' directories % Exclude '.' and '..' directories
currentFolderFiles = currentFolderFiles(~ismember({currentFolderFiles.name}, {'.', '..'})); currentFolderFiles = currentFolderFiles(~ismember({currentFolderFiles.name}, {'.', '..'}));
% Initialize the structure array for .mat files % Initialize the structure array for .mat files
matFileStructArray = struct('path', {}, 'name', {}, 'ext', {}); matFileStructArray = struct('path', {}, 'name', {}, 'ext', {});
% Loop over each file in the current folder % Loop over each file in the current folder
for i = 1:length(currentFolderFiles) for i = 1:length(currentFolderFiles)
currentFile = currentFolderFiles(i); currentFile = currentFolderFiles(i);
% Check if the current item is a file and has a .mat extension % Check if the current item is a file and has a .mat extension
if ~currentFile.isdir && endsWith(currentFile.name, extension, 'IgnoreCase', true) if ~currentFile.isdir && endsWith(currentFile.name, extension, 'IgnoreCase', true)
% If it's a .mat file, add it to the structure array % If it's a .mat file, add it to the structure array
[matFileStructArray(end + 1).path,matFileStructArray(end+1).name, matFileStructArray(end+1).ext] = fileparts(fullfile(folderPath, currentFile.name)); [matFileStructArray(end + 1).path,matFileStructArray(end+1).name, matFileStructArray(end+1).ext] = fileparts(fullfile(folderPath, currentFile.name));
elseif currentFile.isdir elseif currentFile.isdir
% If it's a directory, recursively call the function % If it's a directory, recursively call the function
subfolderPath = fullfile(folderPath, currentFile.name); subfolderPath = fullfile(folderPath, currentFile.name);
subfolderMatFiles = getAllFilesInFolder(subfolderPath,extension); subfolderMatFiles = getAllFilesInFolder(subfolderPath,extension);
% Add .mat files from the subfolder to the structure array % Add .mat files from the subfolder to the structure array
matFileStructArray = [matFileStructArray, subfolderMatFiles]; matFileStructArray = [matFileStructArray, subfolderMatFiles];
end end
end end
end end

View File

@@ -1,415 +1,415 @@
%automate plots %automate plots
[file, path] = uigetfile("C:\Users\Silas\Documents\MATLAB\Datensätze\Raw_Cluster_Simulations\session_februar_24\wh_mi_nacht.mat"); [file, path] = uigetfile("C:\Users\Silas\Documents\MATLAB\Datensätze\Raw_Cluster_Simulations\session_februar_24\wh_mi_nacht.mat");
wh = load([path filesep file]); wh = load([path filesep file]);
wh = wh.wh; wh = wh.wh;
% fields = fieldnames(wh.parameter); % fields = fieldnames(wh.parameter);
% for k = 1:numel(fields) % for k = 1:numel(fields)
% oldParam = wh.parameter.(fields{k}); % oldParam = wh.parameter.(fields{k});
% % copy over the properties to your new class % % copy over the properties to your new class
% wh.parameter.(fields{k}) = StorageParameter(... % wh.parameter.(fields{k}) = StorageParameter(...
% oldParam.Name, oldParam.values); % oldParam.Name, oldParam.values);
% end % end
% %
plotJob = struct(); plotJob = struct();
width = 350; width = 350;
height = 200; height = 200;
plotJob.Position = [100 100 width 100+height]; plotJob.Position = [100 100 width 100+height];
cols = cbrewer2("paired",12); cols = cbrewer2("paired",12);
plotJob.color = cols(1,:); plotJob.color = cols(1,:);
plotJob.l = 2; plotJob.l = 2;
plotJob.ch = 16; plotJob.ch = 16;
plotJob.d = 0; plotJob.d = 0;
plotJob.sgm = 0; plotJob.sgm = 0;
plotJob.pol = "copolarized"; plotJob.pol = "copolarized";
plotJob.p_in = 3; plotJob.p_in = 3;
plotJob.gamma = 0.0023; plotJob.gamma = 0.0023;
plotJob.pmd = 0.1; plotJob.pmd = 0.1;
plotJob.channelspacing = 400e9; plotJob.channelspacing = 400e9;
plotJob.randzdw = 0; plotJob.randzdw = 0;
plotJob.plot_ber_curve = 0; plotJob.plot_ber_curve = 0;
plotJob.plot_3dber_curve = 0; plotJob.plot_3dber_curve = 0;
plotJob.plot_violin = 1; plotJob.plot_violin = 1;
plotJob.plot_wavelength_sweep = 0; plotJob.plot_wavelength_sweep = 0;
plotJob.plot_wavelength_sweep_failure_rate = 0; plotJob.plot_wavelength_sweep_failure_rate = 0;
plotJob.dataStatArg = 'Lineplot with quartiles'; plotJob.dataStatArg = 'Lineplot with quartiles';
plotJob.plotTypeArg = 'Lines'; plotJob.plotTypeArg = 'Lines';
plotJob.displayname = 'a'; plotJob.displayname = 'a';
plotJob.title = 'title'; plotJob.title = 'title';
plotJob.figName = '16 Chann'; plotJob.figName = '16 Chann';
plotJob.xAxisLabel = 'ROP per Channel in dBm'; plotJob.xAxisLabel = 'ROP per Channel in dBm';
plotJob.yAxisLabel = 'BER'; plotJob.yAxisLabel = 'BER';
%% %%
% createbercurves(wh,plotJob) % createbercurves(wh,plotJob)
P = [3,6]; P = [3,6];
for i = 1:2 for i = 1:2
plotJob.p_in = P(i); plotJob.p_in = P(i);
createviolinplots(wh,plotJob); createviolinplots(wh,plotJob);
end end
% createsweepplots(wh,plotJob); % createsweepplots(wh,plotJob);
%% 1 %% 1
function createbercurves(wh,plotJob) function createbercurves(wh,plotJob)
width = 1650; width = 1650;
height = 400; height = 400;
s = 100; s = 100;
e = 100; e = 100;
cols = cbrewer2("paired",12); cols = cbrewer2("paired",12);
numRows = 2; numRows = 2;
numCols = 4; numCols = 4;
plotJob.figName = '16 Chann_200G'; plotJob.figName = '16 Chann_200G';
plotJob.channelspacing = 400e9; plotJob.channelspacing = 400e9;
plotJob.ch = 16; plotJob.ch = 16;
Len = [2,2,2,2,10,10,10,10]; Len = [2,2,2,2,10,10,10,10];
Pol = ["copolarized","alternated","paired","copolarized","copolarized","alternated","paired","copolarized"]; Pol = ["copolarized","alternated","paired","copolarized","copolarized","alternated","paired","copolarized"];
Title = ["Co Polarized","Alternating Pol. Interl.","Paired Pol. Interl.","Link Segmentation",]; Title = ["Co Polarized","Alternating Pol. Interl.","Paired Pol. Interl.","Link Segmentation",];
D = [0,0,0,3,0,0,0,3]; D = [0,0,0,3,0,0,0,3];
Sgm = [0,0,0,1,0,0,0,1]; Sgm = [0,0,0,1,0,0,0,1];
colidx = [4,8,6]; colidx = [4,8,6];
P_launch = [3,6]; P_launch = [3,6];
fig = figure('Name',plotJob.figName); fig = figure('Name',plotJob.figName);
fig.Position = plotJob.Position; fig.Position = plotJob.Position;
fig.Units = "centimeters"; fig.Units = "centimeters";
fig.Position = [0 0 18 7]; fig.Position = [0 0 18 7];
t = tiledlayout(numRows,numCols,'TileSpacing','compact','Padding','compact'); t = tiledlayout(numRows,numCols,'TileSpacing','compact','Padding','compact');
for idx = 1:(numRows * numCols) for idx = 1:(numRows * numCols)
% Create subplot % Create subplot
% sp = subplot(numRows, numCols, idx); % sp = subplot(numRows, numCols, idx);
nexttile; nexttile;
plotJob.l = Len(idx); plotJob.l = Len(idx);
plotJob.pol = Pol(idx); plotJob.pol = Pol(idx);
plotJob.d = D(idx); plotJob.d = D(idx);
plotJob.sgm = Sgm(idx); plotJob.sgm = Sgm(idx);
plotJob.randzdw = 1; plotJob.randzdw = 1;
for i = 1:length(P_launch) for i = 1:length(P_launch)
plotJob.p_in = P_launch(i); plotJob.p_in = P_launch(i);
plotJob.color = cols(colidx(i),:); plotJob.color = cols(colidx(i),:);
hold on hold on
plotCurve(wh, plotJob); plotCurve(wh, plotJob);
end end
% %
if idx ~= 1 && idx ~= 5 % For example, hide y-axis for subplot 1 if idx ~= 1 && idx ~= 5 % For example, hide y-axis for subplot 1
set(gca, 'YTickLabel',[]); % Hide y-axis ticks and labels set(gca, 'YTickLabel',[]); % Hide y-axis ticks and labels
set(gca,'YGrid','on'); set(gca,'YGrid','on');
set(gca, 'YLabel', []); set(gca, 'YLabel', []);
end end
if idx ~= 5 && idx ~= 6 && idx ~= 7 && idx ~= 8 if idx ~= 5 && idx ~= 6 && idx ~= 7 && idx ~= 8
set(gca, 'XLabel', []); set(gca, 'XLabel', []);
set(gca, 'XTickLabel', []); set(gca, 'XTickLabel', []);
end end
grid on grid on
g = gca; g = gca;
pos = g.Position; pos = g.Position;
if idx <= 4 if idx <= 4
title(Title(idx),'FontSize',8); title(Title(idx),'FontSize',8);
% a = annotation('textbox', pos-[0.0020 -0.1434 0.0947 0.3121], 'String', "FEC: 3.8e-3","LineStyle","none","FontSize",8,'LineWidth',0.1,'Interpreter','latex',"FontUnits","points",'Vert','middle','FitBoxToText','on'); % a = annotation('textbox', pos-[0.0020 -0.1434 0.0947 0.3121], 'String', "FEC: 3.8e-3","LineStyle","none","FontSize",8,'LineWidth',0.1,'Interpreter','latex',"FontUnits","points",'Vert','middle','FitBoxToText','on');
% a = annotation('textbox', pos, 'String', "2 km","LineStyle","none","FontSize",8,'LineWidth',0.1,'Interpreter','latex',"FontUnits","points",'Vert','bottom','FitBoxToText','on'); % a = annotation('textbox', pos, 'String', "2 km","LineStyle","none","FontSize",8,'LineWidth',0.1,'Interpreter','latex',"FontUnits","points",'Vert','bottom','FitBoxToText','on');
else else
% a = annotation('textbox', pos, 'String', "FEC: 3.8e-3","LineStyle","none","FontSize",8,'LineWidth',0.1,'Interpreter','latex',"FontUnits","points",'Vert','middle','FitBoxToText','on'); % a = annotation('textbox', pos, 'String', "FEC: 3.8e-3","LineStyle","none","FontSize",8,'LineWidth',0.1,'Interpreter','latex',"FontUnits","points",'Vert','middle','FitBoxToText','on');
% a = annotation('textbox', pos, 'String', "10 km","LineStyle","none","FontSize",8,'LineWidth',0.1,'Interpreter','latex',"FontUnits","points",'Vert','bottom','FitBoxToText','on'); % a = annotation('textbox', pos, 'String', "10 km","LineStyle","none","FontSize",8,'LineWidth',0.1,'Interpreter','latex',"FontUnits","points",'Vert','bottom','FitBoxToText','on');
end end
end end
% Create textbox % Create textbox
annotation(fig,'textbox',... annotation(fig,'textbox',...
[0.0696078431372547 0.246851385390432 0.0656862745098043 0.0453400503778337],... [0.0696078431372547 0.246851385390432 0.0656862745098043 0.0453400503778337],...
'String','10 km',... 'String','10 km',...
'LineStyle','none',... 'LineStyle','none',...
'Interpreter','latex',... 'Interpreter','latex',...
'FontSize',8,... 'FontSize',8,...
'FitBoxToText','off'); 'FitBoxToText','off');
% Create textbox % Create textbox
annotation(fig,'textbox',... annotation(fig,'textbox',...
[0.288235294117647 0.239294710327459 0.0656862745098043 0.0453400503778338],... [0.288235294117647 0.239294710327459 0.0656862745098043 0.0453400503778338],...
'String','10 km',... 'String','10 km',...
'LineStyle','none',... 'LineStyle','none',...
'Interpreter','latex',... 'Interpreter','latex',...
'FontSize',8,... 'FontSize',8,...
'FitBoxToText','off'); 'FitBoxToText','off');
% Create textbox % Create textbox
annotation(fig,'textbox',... annotation(fig,'textbox',...
[0.516666666666666 0.241813602015117 0.0656862745098042 0.0453400503778338],... [0.516666666666666 0.241813602015117 0.0656862745098042 0.0453400503778338],...
'String','10 km',... 'String','10 km',...
'LineStyle','none',... 'LineStyle','none',...
'Interpreter','latex',... 'Interpreter','latex',...
'FontSize',8,... 'FontSize',8,...
'FitBoxToText','off'); 'FitBoxToText','off');
% Create textbox % Create textbox
annotation(fig,'textbox',... annotation(fig,'textbox',...
[0.742156862745097 0.236775818639802 0.0656862745098042 0.0453400503778339],... [0.742156862745097 0.236775818639802 0.0656862745098042 0.0453400503778339],...
'String','10 km',... 'String','10 km',...
'LineStyle','none',... 'LineStyle','none',...
'Interpreter','latex',... 'Interpreter','latex',...
'FontSize',8,... 'FontSize',8,...
'FitBoxToText','off'); 'FitBoxToText','off');
% Create textbox % Create textbox
annotation(fig,'textbox',... annotation(fig,'textbox',...
[0.071996471804854 0.578899159967702 0.0656862745098039 0.0453400503778341],... [0.071996471804854 0.578899159967702 0.0656862745098039 0.0453400503778341],...
'String',{'2 km'},... 'String',{'2 km'},...
'LineStyle','none',... 'LineStyle','none',...
'Interpreter','latex',... 'Interpreter','latex',...
'FontSize',8,... 'FontSize',8,...
'FitBoxToText','off'); 'FitBoxToText','off');
% Create textbox % Create textbox
annotation(fig,'textbox',... annotation(fig,'textbox',...
[0.29596893566113 0.576253721089996 0.0656862745098041 0.0453400503778341],... [0.29596893566113 0.576253721089996 0.0656862745098041 0.0453400503778341],...
'String',{'2 km'},... 'String',{'2 km'},...
'LineStyle','none',... 'LineStyle','none',...
'Interpreter','latex',... 'Interpreter','latex',...
'FontSize',8,... 'FontSize',8,...
'FitBoxToText','off'); 'FitBoxToText','off');
% Create textbox % Create textbox
annotation(fig,'textbox',... annotation(fig,'textbox',...
[0.524883914268912 0.580785315705112 0.0656862745098041 0.0453400503778341],... [0.524883914268912 0.580785315705112 0.0656862745098041 0.0453400503778341],...
'String',{'2 km'},... 'String',{'2 km'},...
'LineStyle','none',... 'LineStyle','none',...
'Interpreter','latex',... 'Interpreter','latex',...
'FontSize',8,... 'FontSize',8,...
'FitBoxToText','off'); 'FitBoxToText','off');
% Create textbox % Create textbox
annotation(fig,'textbox',... annotation(fig,'textbox',...
[0.753758338909501 0.581291504465311 0.0656862745098037 0.0453400503778341],... [0.753758338909501 0.581291504465311 0.0656862745098037 0.0453400503778341],...
'String',{'2 km'},... 'String',{'2 km'},...
'LineStyle','none',... 'LineStyle','none',...
'Interpreter','latex',... 'Interpreter','latex',...
'FontSize',8,... 'FontSize',8,...
'FitBoxToText','off'); 'FitBoxToText','off');
a=sgtitle(['N=',num2str(plotJob.ch),'; $\Delta f_{\mathrm{ch}}$= ',num2str(plotJob.channelspacing*1e-9),' GHz'],'FontSIze',10); a=sgtitle(['N=',num2str(plotJob.ch),'; $\Delta f_{\mathrm{ch}}$= ',num2str(plotJob.channelspacing*1e-9),' GHz'],'FontSIze',10);
a.Interpreter = "latex"; a.Interpreter = "latex";
lgd = legend('$P_{\mathrm{in}}=0$ dBm','$P_{\mathrm{in}}=3$ dBm','$P_{\mathrm{in}}=6$ dBm','Interpreter','latex'); lgd = legend('$P_{\mathrm{in}}=0$ dBm','$P_{\mathrm{in}}=3$ dBm','$P_{\mathrm{in}}=6$ dBm','Interpreter','latex');
lgd.NumColumns = 3; lgd.NumColumns = 3;
lgd.Layout.Tile = 'south'; lgd.Layout.Tile = 'south';
copygraphics(t,'BackgroundColor','none'); copygraphics(t,'BackgroundColor','none');
end end
%% 2 %% 2
function createviolinplots(wh,plotJob) function createviolinplots(wh,plotJob)
width = 350; width = 350;
height = 200; height = 200;
s = 100; s = 100;
e = 100; e = 100;
cols = cbrewer2("paired",12); cols = cbrewer2("paired",12);
numRows = 1; numRows = 1;
numCols = 4; numCols = 4;
plotJob.ch = 16; plotJob.ch = 16;
plotJob.randzdw = 1; plotJob.randzdw = 1;
Pol = ["copolarized","copolarized","alternated","paired",]; Pol = ["copolarized","copolarized","alternated","paired",];
Title = ["Co Pol.","Link Segmentation","Paired Pol. Interl.","Alternating Pol. Interl."]; Title = ["Co Pol.","Link Segmentation","Paired Pol. Interl.","Alternating Pol. Interl."];
D = [0,3,0,0]; D = [0,3,0,0];
Sgm = [0,1,0,0]; Sgm = [0,1,0,0];
colidx = [3]; colidx = [3];
Len = [10]; Len = [10];
fig = findall(groot, 'Type', 'figure', 'Name', plotJob.figName); fig = findall(groot, 'Type', 'figure', 'Name', plotJob.figName);
if isvalid(fig) if isvalid(fig)
figure(fig) figure(fig)
% fig = get(fig); % fig = get(fig);
AxesMain = fig.CurrentAxes; AxesMain = fig.CurrentAxes;
hold on hold on
% t = tiledlayout(1,4,'TileSpacing','compact','Padding','compact'); % t = tiledlayout(1,4,'TileSpacing','compact','Padding','compact');
else else
fig = figure('name',char(plotJob.figName)); fig = figure('name',char(plotJob.figName));
AxesMain = gca; AxesMain = gca;
hold on; grid on; hold on; grid on;
% t = tiledlayout(1,4,'TileSpacing','compact','Padding','compact'); % t = tiledlayout(1,4,'TileSpacing','compact','Padding','compact');
end end
for idx = 1:(numRows * numCols) for idx = 1:(numRows * numCols)
% Create subplot % Create subplot
subplot(numRows, numCols, idx); subplot(numRows, numCols, idx);
plotJob.pol = Pol(idx); plotJob.pol = Pol(idx);
plotJob.d = D(idx); plotJob.d = D(idx);
plotJob.sgm = Sgm(idx); plotJob.sgm = Sgm(idx);
for i = 1 for i = 1
plotJob.color = cols(colidx(i),:); plotJob.color = cols(colidx(i),:);
plotJob.l = Len(i); plotJob.l = Len(i);
hold on hold on
plotViolin(wh, plotJob); plotViolin(wh, plotJob);
end end
if idx ~= 1 % For example, hide y-axis for subplot 1 if idx ~= 1 % For example, hide y-axis for subplot 1
%set(gca, 'YTickLabel',[]); % Hide y-axis ticks and labels %set(gca, 'YTickLabel',[]); % Hide y-axis ticks and labels
set(gca, 'YGrid','on'); set(gca, 'YGrid','on');
set(gca, 'YLabel', []); set(gca, 'YLabel', []);
end end
if idx <= 4 if idx <= 4
title(Title(idx)); title(Title(idx));
end end
end end
% Create textbox % Create textbox
annotation(fig,'textbox',... annotation(fig,'textbox',...
[0.300019607843137 0.816120906801009 0.108803921568628 0.0906801007556676],... [0.300019607843137 0.816120906801009 0.108803921568628 0.0906801007556676],...
'String','$P_{\mathrm{in}}=3$ dBm',... 'String','$P_{\mathrm{in}}=3$ dBm',...
'LineStyle','none',... 'LineStyle','none',...
'Interpreter','latex',... 'Interpreter','latex',...
'FontSize',8,... 'FontSize',8,...
'FitBoxToText','off'); 'FitBoxToText','off');
% Create textbox % Create textbox
annotation(fig,'textbox',... annotation(fig,'textbox',...
[0.530411764705882 0.81612090680101 0.108803921568628 0.0906801007556676],... [0.530411764705882 0.81612090680101 0.108803921568628 0.0906801007556676],...
'String','$P_{\mathrm{in}}=3$ dBm',... 'String','$P_{\mathrm{in}}=3$ dBm',...
'LineStyle','none',... 'LineStyle','none',...
'Interpreter','latex',... 'Interpreter','latex',...
'FontSize',8,... 'FontSize',8,...
'FitBoxToText','off'); 'FitBoxToText','off');
% Create textbox % Create textbox
annotation(fig,'textbox',... annotation(fig,'textbox',...
[0.755901960784313 0.816120906801011 0.108803921568628 0.0906801007556676],... [0.755901960784313 0.816120906801011 0.108803921568628 0.0906801007556676],...
'String','$P_{\mathrm{in}}=3$ dBm',... 'String','$P_{\mathrm{in}}=3$ dBm',...
'LineStyle','none',... 'LineStyle','none',...
'Interpreter','latex',... 'Interpreter','latex',...
'FontSize',8,... 'FontSize',8,...
'FitBoxToText','off'); 'FitBoxToText','off');
% Create textbox % Create textbox
annotation(fig,'textbox',... annotation(fig,'textbox',...
[0.0696274509803918 0.584382871536529 0.108803921568628 0.0906801007556676],... [0.0696274509803918 0.584382871536529 0.108803921568628 0.0906801007556676],...
'String','$P_{\mathrm{in}}=3$ dBm',... 'String','$P_{\mathrm{in}}=3$ dBm',...
'LineStyle','none',... 'LineStyle','none',...
'Interpreter','latex',... 'Interpreter','latex',...
'FontSize',8,... 'FontSize',8,...
'FitBoxToText','off'); 'FitBoxToText','off');
% lgd = legend('$P_{\mathrm{in}}=0$ dBm','$P_{\mathrm{in}}=3$ dBm','$P_{\mathrm{in}}=6$ dBm','Interpreter','latex'); % lgd = legend('$P_{\mathrm{in}}=0$ dBm','$P_{\mathrm{in}}=3$ dBm','$P_{\mathrm{in}}=6$ dBm','Interpreter','latex');
% lgd.NumColumns = 3; % lgd.NumColumns = 3;
% lgd.Layout.Tile = 'south'; % lgd.Layout.Tile = 'south';
end end
%% 3 %% 3
function createsweepplots(wh,plotJob) function createsweepplots(wh,plotJob)
width = 650; width = 650;
height = 200; height = 200;
s = 100; s = 100;
e = 100; e = 100;
plotJob.Position = [0 0 width e+height]; plotJob.Position = [0 0 width e+height];
cols = cbrewer2("paired",12); cols = cbrewer2("paired",12);
numRows = 1; numRows = 1;
numCols = 4; numCols = 4;
plotJob.channelspacing = 200e9; plotJob.channelspacing = 200e9;
plotJob.ch = 16; plotJob.ch = 16;
plotJob.randzdw = 1; plotJob.randzdw = 1;
plotJob.l = 10; plotJob.l = 10;
plotJob.p_in = 3; plotJob.p_in = 3;
Pol = ["copolarized","alternated","paired","copolarized"]; Pol = ["copolarized","alternated","paired","copolarized"];
Title = ["Co Polarized","Alternating Pol. Interl.","Paired Pol. Interl.","Link Segmentation",]; Title = ["Co Polarized","Alternating Pol. Interl.","Paired Pol. Interl.","Link Segmentation",];
D = [0,0,0,3]; D = [0,0,0,3];
Sgm = [0,0,0,1]; Sgm = [0,0,0,1];
Channelspacing = [200e9, 200e9]; Channelspacing = [200e9, 200e9];
PlotTypeArg = ["--","-"]; PlotTypeArg = ["--","-"];
colidx = [6,8,2,4]; colidx = [6,8,2,4];
Len = [2,10]; Len = [2,10];
plotJob.figName = [num2str(plotJob.ch),num2str(plotJob.channelspacing*1e-9),num2str(plotJob.p_in),'...']; plotJob.figName = [num2str(plotJob.ch),num2str(plotJob.channelspacing*1e-9),num2str(plotJob.p_in),'...'];
plotJob.figName = "10km 400ghz"; plotJob.figName = "10km 400ghz";
fig = findall(groot, 'Type', 'figure', 'Name', plotJob.figName); fig = findall(groot, 'Type', 'figure', 'Name', plotJob.figName);
if isvalid(fig) if isvalid(fig)
figure(fig) figure(fig)
fig = get(fig); fig = get(fig);
AxesMain = fig.CurrentAxes; AxesMain = fig.CurrentAxes;
hold on hold on
else else
fig = figure('name',char(plotJob.figName)); fig = figure('name',char(plotJob.figName));
AxesMain = gca; AxesMain = gca;
hold on hold on
end end
fig.Position = plotJob.Position; fig.Position = plotJob.Position;
fig.Units = "centimeters"; fig.Units = "centimeters";
fig.Position = [0 0 18 7]; fig.Position = [0 0 18 7];
for j = 1 for j = 1
plotJob.channelspacing = Channelspacing(j); plotJob.channelspacing = Channelspacing(j);
plotJob.plotTypeArg = PlotTypeArg(j); plotJob.plotTypeArg = PlotTypeArg(j);
for idx = 1:4 for idx = 1:4
plotJob.color = cols(colidx(idx),:); plotJob.color = cols(colidx(idx),:);
plotJob.pol = Pol(idx); plotJob.pol = Pol(idx);
plotJob.d = D(idx); plotJob.d = D(idx);
plotJob.sgm = Sgm(idx); plotJob.sgm = Sgm(idx);
plotJob.displayname = [char(plotJob.pol)]; plotJob.displayname = [char(plotJob.pol)];
hold on hold on
plotBerVsZdwFailureRate(wh, plotJob); plotBerVsZdwFailureRate(wh, plotJob);
end end
end end
legend('Location', 'southoutside', 'Orientation', 'horizontal'); legend('Location', 'southoutside', 'Orientation', 'horizontal');
%plot channel positions %plot channel positions
hold on hold on
chpos = calcWavelengthPlan(plotJob.ch, plotJob.channelspacing, 1310); chpos = calcWavelengthPlan(plotJob.ch, plotJob.channelspacing, 1310);
xline(chpos,'LineWidth',2,'Alpha',0.4,'HandleVisibility','off'); xline(chpos,'LineWidth',2,'Alpha',0.4,'HandleVisibility','off');
chpos = calcWavelengthPlan(plotJob.ch, plotJob.channelspacing, chpos(4)); chpos = calcWavelengthPlan(plotJob.ch, plotJob.channelspacing, chpos(4));
xline(chpos,'LineWidth',2,'LineStyle','--','Alpha',0.1,'HandleVisibility','off'); xline(chpos,'LineWidth',2,'LineStyle','--','Alpha',0.1,'HandleVisibility','off');
title(['N=',num2str(plotJob.ch),' $\Delta f_{\mathrm{ch}}$= ',num2str(plotJob.channelspacing*1e-9),' GHz'],'FontSize',10,'Interpreter','latex'); title(['N=',num2str(plotJob.ch),' $\Delta f_{\mathrm{ch}}$= ',num2str(plotJob.channelspacing*1e-9),' GHz'],'FontSize',10,'Interpreter','latex');
end end

View File

@@ -1,83 +1,83 @@
%automate plots %automate plots
[file, path] = uigetfile("C:\Users\Silas\Documents\MATLAB\Datensätze\Raw_Cluster_Simulations\"); [file, path] = uigetfile("C:\Users\Silas\Documents\MATLAB\Datensätze\Raw_Cluster_Simulations\");
wh = load([path filesep file]); wh = load([path filesep file]);
wh = wh.wh; wh = wh.wh;
plotJob = struct(); plotJob = struct();
width = 350; width = 350;
height = 200; height = 200;
plotJob.Position = [100 100 width 100+height]; plotJob.Position = [100 100 width 100+height];
cols = cbrewer2("paired",12); cols = cbrewer2("paired",12);
plotJob.color = cols(1,:); plotJob.color = cols(1,:);
plotJob.l = 1; plotJob.l = 1;
plotJob.ch = 1; plotJob.ch = 1;
plotJob.sgm = 1; plotJob.sgm = 1;
plotJob.pol = "copolarized"; plotJob.pol = "copolarized";
plotJob.p_in = 3; plotJob.p_in = 3;
plotJob.gamma = 0.0023; plotJob.gamma = 0.0023;
plotJob.pmd = 0.1; plotJob.pmd = 0.1;
plotJob.channelspacing = 400e9; plotJob.channelspacing = 400e9;
plotJob.randzdw = 0; plotJob.randzdw = 0;
plotJob.plot_ber_curve = 1; plotJob.plot_ber_curve = 1;
plotJob.plot_3dber_curve = 0; plotJob.plot_3dber_curve = 0;
plotJob.plot_violin = 0; plotJob.plot_violin = 0;
plotJob.plot_wavelength_sweep = 0; plotJob.plot_wavelength_sweep = 0;
plotJob.plot_wavelength_sweep_failure_rate = 0; plotJob.plot_wavelength_sweep_failure_rate = 0;
plotJob.dataStatArg = 'Lineplot with quartiles'; plotJob.dataStatArg = 'Lineplot with quartiles';
plotJob.plotTypeArg = 'Lines'; plotJob.plotTypeArg = 'Lines';
plotJob.displayname = 'a'; plotJob.displayname = 'a';
plotJob.title = 'title'; plotJob.title = 'title';
plotJob.figName = '1 Chann__'; plotJob.figName = '1 Chann__';
plotJob.xAxisLabel = 'ROP per Channel in dBm'; plotJob.xAxisLabel = 'ROP per Channel in dBm';
plotJob.yAxisLabel = 'BER'; plotJob.yAxisLabel = 'BER';
plotJob.d = 0; plotJob.d = 0;
xAxis = wh.parameter.p_out.values; xAxis = wh.parameter.p_out.values;
D = wh.parameter.dispersion.values; D = wh.parameter.dispersion.values;
figure() figure()
ber_ = []; ber_ = [];
for d_ = 0:39 for d_ = 0:39
if d_ == 0 if d_ == 0
plotJob.sgm = 0; plotJob.sgm = 0;
ber_(d_+1,:) = wh.getStoValue('ber',plotJob.l,d_,plotJob.sgm,string(plotJob.pol),plotJob.p_in,xAxis,plotJob.pmd,plotJob.gamma,1,plotJob.ch,1310,plotJob.channelspacing,plotJob.randzdw)'; ber_(d_+1,:) = wh.getStoValue('ber',plotJob.l,d_,plotJob.sgm,string(plotJob.pol),plotJob.p_in,xAxis,plotJob.pmd,plotJob.gamma,1,plotJob.ch,1310,plotJob.channelspacing,plotJob.randzdw)';
else else
plotJob.sgm = 1; plotJob.sgm = 1;
ber_(d_+1,:) = wh.getStoValue('ber',plotJob.l,d_,plotJob.sgm,string(plotJob.pol),plotJob.p_in,xAxis,plotJob.pmd,plotJob.gamma,1,plotJob.ch,1310,plotJob.channelspacing,plotJob.randzdw)'; ber_(d_+1,:) = wh.getStoValue('ber',plotJob.l,d_,plotJob.sgm,string(plotJob.pol),plotJob.p_in,xAxis,plotJob.pmd,plotJob.gamma,1,plotJob.ch,1310,plotJob.channelspacing,plotJob.randzdw)';
end end
hold on hold on
plot(xAxis,ber_(d_+1,:)) plot(xAxis,ber_(d_+1,:))
set(gca,'yscale','log'); set(gca,'yscale','log');
end end
yline(3.8e-3); yline(3.8e-3);
hdfec = 3.8e-3.*ones(size(xAxis)); hdfec = 3.8e-3.*ones(size(xAxis));
for i = 1:size(ber_,1) for i = 1:size(ber_,1)
ber_series = ber_(i,:); ber_series = ber_(i,:);
a = InterX([hdfec(:)';xAxis],[ber_series;xAxis]); a = InterX([hdfec(:)';xAxis],[ber_series;xAxis]);
cross(i) = a(2); cross(i) = a(2);
end end
col = cbrewer2('Paired',8); col = cbrewer2('Paired',8);
figure() figure()
plot(D,cross,'Marker','o','MarkerSize',5,'MarkerEdgeColor',[1,1,1],'MarkerFaceColor',col(2,:),'Color',col(1,:),'LineWidth',1); plot(D,cross,'Marker','o','MarkerSize',5,'MarkerEdgeColor',[1,1,1],'MarkerFaceColor',col(2,:),'Color',col(1,:),'LineWidth',1);
grid minor grid minor
xlabel('Accumulated Dispersion') xlabel('Accumulated Dispersion')
ylabel('Required ROP to reach FEC limit in dB') ylabel('Required ROP to reach FEC limit in dB')
line([D(16),D(16)],[-10,cross(16)],'linestyle','--') line([D(16),D(16)],[-10,cross(16)],'linestyle','--')
line([0,D(16)],[cross(16),cross(16)],'linestyle','--') line([0,D(16)],[cross(16),cross(16)],'linestyle','--')
line([D(29),D(29)],[-10,cross(29)],'linestyle','--') line([D(29),D(29)],[-10,cross(29)],'linestyle','--')
line([0,D(29)],[cross(29),cross(29)],'linestyle','--') line([0,D(29)],[cross(29),cross(29)],'linestyle','--')

View File

@@ -1,52 +1,52 @@
wh = load("C:\Users\Silas\Documents\MATLAB\Datensätze\Raw_Cluster_Simulations\session_dispersion_validation\wh_with_variation.mat"); wh = load("C:\Users\Silas\Documents\MATLAB\Datensätze\Raw_Cluster_Simulations\session_dispersion_validation\wh_with_variation.mat");
wh = wh.wh; wh = wh.wh;
lambda = 1295; lambda = 1295;
figure(3) figure(3)
plot(xAxis,getber(wh,lambda),'DisplayName',['w:', num2str(lambda), 'variation']); plot(xAxis,getber(wh,lambda),'DisplayName',['w:', num2str(lambda), 'variation']);
yline(3.8e-3,'HandleVisibility','off'); yline(3.8e-3,'HandleVisibility','off');
legend legend
set(gca,'yscale','log'); set(gca,'yscale','log');
grid(gca,'on'); grid(gca,'on');
grid(gca,'minor'); grid(gca,'minor');
grid minor grid minor
fontsize(gca,8,"points") fontsize(gca,8,"points")
fig.Units = "centimeters"; fig.Units = "centimeters";
fig.Position = [2 2 8.5 7]; fig.Position = [2 2 8.5 7];
set(gca,'TickLabelInterpreter','latex') set(gca,'TickLabelInterpreter','latex')
ylim([1e-5,0.5]); ylim([1e-5,0.5]);
xlim([min(xAxis),-3]); xlim([min(xAxis),-3]);
wh = load("C:\Users\Silas\Documents\MATLAB\Datensätze\Raw_Cluster_Simulations\session_dispersion_validation\wh_no_variation.mat"); wh = load("C:\Users\Silas\Documents\MATLAB\Datensätze\Raw_Cluster_Simulations\session_dispersion_validation\wh_no_variation.mat");
wh = wh.wh; wh = wh.wh;
figure(3) figure(3)
hold on hold on
plot(xAxis,getber(wh,lambda),'DisplayName',['w:', num2str(lambda), 'no variation']); plot(xAxis,getber(wh,lambda),'DisplayName',['w:', num2str(lambda), 'no variation']);
yline(3.8e-3,'HandleVisibility','off'); yline(3.8e-3,'HandleVisibility','off');
legend legend
set(gca,'yscale','log'); set(gca,'yscale','log');
grid(gca,'on'); grid(gca,'on');
grid(gca,'minor'); grid(gca,'minor');
grid minor grid minor
fontsize(gca,8,"points") fontsize(gca,8,"points")
fig.Units = "centimeters"; fig.Units = "centimeters";
fig.Position = [2 2 8.5 7]; fig.Position = [2 2 8.5 7];
set(gca,'TickLabelInterpreter','latex') set(gca,'TickLabelInterpreter','latex')
ylim([1e-5,0.5]); ylim([1e-5,0.5]);
xlim([min(xAxis),-3]); xlim([min(xAxis),-3]);
function ber = getber(wh,lambda) function ber = getber(wh,lambda)
realization = wh.parameter.realization.values(1:end); realization = wh.parameter.realization.values(1:end);
xAxis = wh.parameter.p_out.values; xAxis = wh.parameter.p_out.values;
ber = []; ber = [];
for xl = 1:numel(xAxis) for xl = 1:numel(xAxis)
p_out = xAxis(xl); p_out = xAxis(xl);
temp = wh.getStoValue('ber',10,0,0,"copolarized",3,p_out,0.1,0.0023,realization,1,lambda,400e9,1); temp = wh.getStoValue('ber',10,0,0,"copolarized",3,p_out,0.1,0.0023,realization,1,lambda,400e9,1);
ber(xl) = mean(temp,'all'); ber(xl) = mean(temp,'all');
end end
end end

View File

@@ -1,61 +1,61 @@
function generatePlots(wh,plotJob) function generatePlots(wh,plotJob)
% 0) Test for valid query: % 0) Test for valid query:
p_out = wh.parameter.p_out.values(1); p_out = wh.parameter.p_out.values(1);
realization = 9; realization = 9;
if 1 %~isempty(wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.ch,1310)) if 1 %~isempty(wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.ch,1310))
% test violin % test violin
baseName = plotJob.figName; baseName = plotJob.figName;
width = 350; width = 350;
height = 200; height = 200;
s = 100; s = 100;
e = 100; e = 100;
if plotJob.plot_ber_curve if plotJob.plot_ber_curve
plotJob.Position = [100 100 width e+height]; plotJob.Position = [100 100 width e+height];
plotJob.figName = [baseName, ' zdwvsber']; plotJob.figName = [baseName, ' zdwvsber'];
plotCurve(wh, plotJob); plotCurve(wh, plotJob);
end end
if plotJob.plot_3dber_curve if plotJob.plot_3dber_curve
plotJob.Position = [100 100 width e+height]; plotJob.Position = [100 100 width e+height];
plotJob.figName = [baseName, ' zdwvsber']; plotJob.figName = [baseName, ' zdwvsber'];
plot3dCurve(wh, plotJob); plot3dCurve(wh, plotJob);
end end
if plotJob.plot_wavelength_sweep if plotJob.plot_wavelength_sweep
plotJob.Position = [100 100 width e+height]; plotJob.Position = [100 100 width e+height];
plotJob.figName = [baseName, ' zdwvsber']; plotJob.figName = [baseName, ' zdwvsber'];
plotBerVsZDW(wh, plotJob); plotBerVsZDW(wh, plotJob);
end end
if plotJob.plot_wavelength_sweep_failure_rate if plotJob.plot_wavelength_sweep_failure_rate
plotJob.Position = [100 100 width e+height]; plotJob.Position = [100 100 width e+height];
plotJob.figName = [baseName, ' zdwvsber']; plotJob.figName = [baseName, ' zdwvsber'];
plotBerVsZdwFailureRate(wh, plotJob); plotBerVsZdwFailureRate(wh, plotJob);
end end
if plotJob.plot_violin if plotJob.plot_violin
plotJob.Position = [s+width 100 width e+height]; plotJob.Position = [s+width 100 width e+height];
plotJob.figName = [baseName, ' violin']; plotJob.figName = [baseName, ' violin'];
plotViolin(wh, plotJob); plotViolin(wh, plotJob);
end end
if 0 if 0
%2) plotHistogram %2) plotHistogram
plotJob.Position = [s+2*width 100 width e+height]; plotJob.Position = [s+2*width 100 width e+height];
plotJob.figName = [baseName, ' FEC crossing']; plotJob.figName = [baseName, ' FEC crossing'];
plotHistogram(wh,plotJob) plotHistogram(wh,plotJob)
end end
else else
warndlg('The requested Datapoint is not available... This can occur for some edgecase constellations... ') warndlg('The requested Datapoint is not available... This can occur for some edgecase constellations... ')
end end
end end

View File

@@ -1,248 +1,248 @@
function plotCurve(wh,plotJob) function plotCurve(wh,plotJob)
%PLOTCURVE Summary of this function goes here %PLOTCURVE Summary of this function goes here
% Detailed explanation goes here % Detailed explanation goes here
fig = findall(groot, 'Type', 'figure', 'Name', plotJob.figName); fig = findall(groot, 'Type', 'figure', 'Name', plotJob.figName);
if isvalid(fig) if isvalid(fig)
figure(fig) figure(fig)
fig = get(fig); fig = get(fig);
AxesMain = fig.CurrentAxes; AxesMain = fig.CurrentAxes;
hold on hold on
else else
fig = figure('name',char(plotJob.figName)); fig = figure('name',char(plotJob.figName));
AxesMain = gca; AxesMain = gca;
hold on hold on
end end
col = plotJob.color; col = plotJob.color;
% we want to fetch all realizations % we want to fetch all realizations
if plotJob.pmd == 0 if plotJob.pmd == 0
realization = 499; realization = 499;
% realization = 0:7; % realization = 0:7;
else else
realization = wh.parameter.realization.values(1:end); realization = wh.parameter.realization.values(1:end);
end end
realization = wh.parameter.realization.values(1:end); realization = wh.parameter.realization.values(1:end);
% get all xAxis values % get all xAxis values
xAxis = wh.parameter.p_out.values; xAxis = wh.parameter.p_out.values;
% Fetch Data from Warehouse % Fetch Data from Warehouse
for xl = 1:numel(xAxis) for xl = 1:numel(xAxis)
p_out = xAxis(xl); p_out = xAxis(xl);
if string(plotJob.dataStatArg) == "Worst" if string(plotJob.dataStatArg) == "Worst"
temp = wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.ch,1310,plotJob.channelspacing,plotJob.randzdw); temp = wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.ch,1310,plotJob.channelspacing,plotJob.randzdw);
temp = removeZeros(temp); temp = removeZeros(temp);
ber(xl) = max(temp,[],'all'); ber(xl) = max(temp,[],'all');
linew = 1.0; linew = 1.0;
markersz = 3; markersz = 3;
linestyle = '-'; linestyle = '-';
elseif string(plotJob.dataStatArg) == "AVG" elseif string(plotJob.dataStatArg) == "AVG"
temp = wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.ch,1310,plotJob.channelspacing,plotJob.randzdw); temp = wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.ch,1310,plotJob.channelspacing,plotJob.randzdw);
temp = removeZeros(temp); temp = removeZeros(temp);
ber(xl) = mean(temp,'all'); ber(xl) = mean(temp,'all');
linew = 1.0; linew = 1.0;
markersz = 3; markersz = 3;
linestyle = '-'; linestyle = '-';
elseif string(plotJob.dataStatArg) == "Best" elseif string(plotJob.dataStatArg) == "Best"
temp = wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.ch,1310,plotJob.channelspacing,plotJob.randzdw); temp = wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.ch,1310,plotJob.channelspacing,plotJob.randzdw);
temp = removeZeros(temp); temp = removeZeros(temp);
ber(xl) = min(temp,[],'all'); ber(xl) = min(temp,[],'all');
linew = 1.0; linew = 1.0;
markersz = 3; markersz = 3;
linestyle = '-'; linestyle = '-';
elseif string(plotJob.dataStatArg) == "All Channels; mean(PMD Realizations)" elseif string(plotJob.dataStatArg) == "All Channels; mean(PMD Realizations)"
temp = wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.ch,1310,plotJob.channelspacing,plotJob.randzdw); temp = wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.ch,1310,plotJob.channelspacing,plotJob.randzdw);
temp = removeZeros(temp); temp = removeZeros(temp);
ber(:,xl) = mean(temp,1,"omitnan").'; ber(:,xl) = mean(temp,1,"omitnan").';
linew = 1; linew = 1;
markersz = 3; markersz = 3;
linestyle = '--'; linestyle = '--';
elseif string(plotJob.dataStatArg) == "Lineplot with quartiles" elseif string(plotJob.dataStatArg) == "Lineplot with quartiles"
temp = wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.ch,1310,plotJob.channelspacing,plotJob.randzdw); temp = wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.ch,1310,plotJob.channelspacing,plotJob.randzdw);
temp = removeZeros(temp); temp = removeZeros(temp);
ber(xl) = mean(temp,"all","omitnan").'; ber(xl) = mean(temp,"all","omitnan").';
upperq(xl) = quantile(temp,0.9,"all"); upperq(xl) = quantile(temp,0.9,"all");
lowerq(xl) = quantile(temp,0.1,"all"); lowerq(xl) = quantile(temp,0.1,"all");
if lowerq(xl) == 0 if lowerq(xl) == 0
lowerq(xl) = lowerq(xl-1); lowerq(xl) = lowerq(xl-1);
end end
% upperq(xl) = 0.5*std(tmp,1,'all','omitnan'); % upperq(xl) = 0.5*std(tmp,1,'all','omitnan');
% lowerq(xl) = 0.5*std(tmp,1,'all','omitnan'); % lowerq(xl) = 0.5*std(tmp,1,'all','omitnan');
% upperq(xl) = max(dataNoNans); % upperq(xl) = max(dataNoNans);
% lowerq(xl) = min(dataNoNans); % lowerq(xl) = min(dataNoNans);
% upperq(xl) = mean(tmp,"all","omitnan") + 1.96 * (std(tmp,1,'all','omitnan')/sqrt(numel(tmp))); % upperq(xl) = mean(tmp,"all","omitnan") + 1.96 * (std(tmp,1,'all','omitnan')/sqrt(numel(tmp)));
% lowerq(xl) = mean(tmp,"all","omitnan") - 1.96 * (std(tmp,1,'all','omitnan')/sqrt(numel(tmp))); % lowerq(xl) = mean(tmp,"all","omitnan") - 1.96 * (std(tmp,1,'all','omitnan')/sqrt(numel(tmp)));
linew = 1; linew = 1;
markersz = 1; markersz = 1;
linestyle = '-'; linestyle = '-';
elseif string(plotJob.dataStatArg) == "All Channels ;All PMD Realizations" elseif string(plotJob.dataStatArg) == "All Channels ;All PMD Realizations"
tmp = reshape(wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.ch,1310,plotJob.channelspacing,plotJob.randzdw).',[],1); tmp = reshape(wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.ch,1310,plotJob.channelspacing,plotJob.randzdw).',[],1);
ber(1:size(tmp,1),xl) = tmp; ber(1:size(tmp,1),xl) = tmp;
linew = 0.3; linew = 0.3;
markersz = 2; markersz = 2;
linestyle = ':'; linestyle = ':';
end end
end end
xAxis = xAxis; xAxis = xAxis;
% Plot Data % Plot Data
if string(plotJob.plotTypeArg) == "Scatter" if string(plotJob.plotTypeArg) == "Scatter"
for rlz = 1:size(ber,1) for rlz = 1:size(ber,1)
if rlz < size(ber,1) if rlz < size(ber,1)
scatter(xAxis,ber(rlz,:),markersz,'MarkerEdgeColor',col,'MarkerFaceColor',col,'Parent', AxesMain(1),'HandleVisibility','off'); scatter(xAxis,ber(rlz,:),markersz,'MarkerEdgeColor',col,'MarkerFaceColor',col,'Parent', AxesMain(1),'HandleVisibility','off');
else else
scatter(xAxis,ber(rlz,:),markersz,'MarkerEdgeColor',col,'MarkerFaceColor',col,'Parent', AxesMain(1),'DisplayName',[plotJob.dataStatArg,' Ch.: ', plotJob.displayname]); scatter(xAxis,ber(rlz,:),markersz,'MarkerEdgeColor',col,'MarkerFaceColor',col,'Parent', AxesMain(1),'DisplayName',[plotJob.dataStatArg,' Ch.: ', plotJob.displayname]);
end end
end end
elseif string(plotJob.plotTypeArg) == "Lines" elseif string(plotJob.plotTypeArg) == "Lines"
% if ~anynan(ber) % if ~anynan(ber)
% [xAxis,ber] = interpCurve(xAxis, ber); % [xAxis,ber] = interpCurve(xAxis, ber);
% end % end
for rlz = 1:size(ber,1) for rlz = 1:size(ber,1)
% %
if (string(plotJob.dataStatArg) == "All Channels ;All PMD Realizations")||(string(plotJob.dataStatArg) == "All Channels; mean(PMD Realizations)") if (string(plotJob.dataStatArg) == "All Channels ;All PMD Realizations")||(string(plotJob.dataStatArg) == "All Channels; mean(PMD Realizations)")
ch = mod(rlz,plotJob.ch); ch = mod(rlz,plotJob.ch);
if ch == 0; ch = plotJob.ch; end if ch == 0; ch = plotJob.ch; end
else else
ch = plotJob.dataStatArg; ch = plotJob.dataStatArg;
end end
if rlz <= size(ber,1) if rlz <= size(ber,1)
s = plot3(xAxis,repmat(ch,1,numel(xAxis)),ber(rlz,:),linestyle,'Marker',"o",'MarkerSize',markersz,'MarkerFaceColor',plotJob.color,'LineWidth',linew,'Color',col,'Parent', AxesMain,'HandleVisibility','off'); s = plot3(xAxis,repmat(ch,1,numel(xAxis)),ber(rlz,:),linestyle,'Marker',"o",'MarkerSize',markersz,'MarkerFaceColor',plotJob.color,'LineWidth',linew,'Color',col,'Parent', AxesMain,'HandleVisibility','off');
s.DataTipTemplate.Interpreter = "latex"; s.DataTipTemplate.Interpreter = "latex";
s.DataTipTemplate.DataTipRows(1).Label = "Ch: "; s.DataTipTemplate.DataTipRows(1).Label = "Ch: ";
s.DataTipTemplate.DataTipRows(1).Value = repmat(ch,size(ber)); s.DataTipTemplate.DataTipRows(1).Value = repmat(ch,size(ber));
s.DataTipTemplate.DataTipRows(1); s.DataTipTemplate.DataTipRows(1);
s.DataTipTemplate.DataTipRows(2) = []; s.DataTipTemplate.DataTipRows(2) = [];
else else
if string(plotJob.dataStatArg) == "Lineplot with quartiles" if string(plotJob.dataStatArg) == "Lineplot with quartiles"
[hl,hp] = boundedline(xAxis,ber(rlz,:),([(ber(rlz,:)-lowerq(rlz,:));upperq(rlz,:)-ber(rlz,:)]'),'-*', 'alpha','Color',col,'transparency', 0.2); [hl,hp] = boundedline(xAxis,ber(rlz,:),([(ber(rlz,:)-lowerq(rlz,:));upperq(rlz,:)-ber(rlz,:)]'),'-*', 'alpha','Color',col,'transparency', 0.2);
hp.LineWidth = 1.2; hp.LineWidth = 1.2;
ho = outlinebounds(hl,hp); ho = outlinebounds(hl,hp);
set(ho, 'linestyle', ':', 'color', col); set(ho, 'linestyle', ':', 'color', col);
else else
s = plot(xAxis,ber(rlz,:),linestyle,'Marker',"o",'MarkerFaceColor',col,'MarkerSize',markersz,'LineWidth',linew,'Color',col,'Parent', AxesMain,'DisplayName',[plotJob.displayname]); s = plot(xAxis,ber(rlz,:),linestyle,'Marker',"o",'MarkerFaceColor',col,'MarkerSize',markersz,'LineWidth',linew,'Color',col,'Parent', AxesMain,'DisplayName',[plotJob.displayname]);
s.DataTipTemplate.Interpreter = "latex"; s.DataTipTemplate.Interpreter = "latex";
s.DataTipTemplate.DataTipRows(1).Label = "Ch: "; s.DataTipTemplate.DataTipRows(1).Label = "Ch: ";
s.DataTipTemplate.DataTipRows(1).Value = repmat(string(ch),size(ber)); s.DataTipTemplate.DataTipRows(1).Value = repmat(string(ch),size(ber));
s.DataTipTemplate.DataTipRows(1) s.DataTipTemplate.DataTipRows(1)
s.DataTipTemplate.DataTipRows(2) = []; s.DataTipTemplate.DataTipRows(2) = [];
end end
end end
end end
end end
% Draw FEC Threshold Line % Draw FEC Threshold Line
%get x data of first children: %get x data of first children:
%get all linear Values %get all linear Values
if 0 if 0
linear = wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,wh.parameter.p_out.values,0,0,499,"symmetric"); linear = wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,wh.parameter.p_out.values,0,0,499,"symmetric");
linear = mean(linear,2); linear = mean(linear,2);
lincurve = findall(AxesMain, 'Type', 'line','DisplayName','Linear Baseline'); lincurve = findall(AxesMain, 'Type', 'line','DisplayName','Linear Baseline');
% %
if isempty(lincurve) if isempty(lincurve)
xdata = AxesMain.Children(1).XData; xdata = AxesMain.Children(1).XData;
hdfec = 3.8e-3.*ones(size(xdata)); hdfec = 3.8e-3.*ones(size(xdata));
plot(xdata,linear,'-','Marker',"o",'MarkerSize',3,'LineWidth',4,'Color',[0.6400 0.6400 0.6400],'MarkerFaceColor',[0.6400 0.6400 0.6400],'Parent', AxesMain,'DisplayName','Linear Baseline'); plot(xdata,linear,'-','Marker',"o",'MarkerSize',3,'LineWidth',4,'Color',[0.6400 0.6400 0.6400],'MarkerFaceColor',[0.6400 0.6400 0.6400],'Parent', AxesMain,'DisplayName','Linear Baseline');
%h = get(gca,'Children'); %h = get(gca,'Children');
%set(gca,'Children',[h(2) h(1)]) %set(gca,'Children',[h(2) h(1)])
end end
end end
feccurve = findall(AxesMain, 'Type', 'line','DisplayName','FEC $3.8*10^{-3}$'); feccurve = findall(AxesMain, 'Type', 'line','DisplayName','FEC $3.8*10^{-3}$');
% %
if isempty(feccurve) if isempty(feccurve)
xdata = xAxis; xdata = xAxis;
hdfec = 3.8e-3.*ones(size(xdata)); hdfec = 3.8e-3.*ones(size(xdata));
for ch = 1:plotJob.ch for ch = 1:plotJob.ch
plot3(xdata,repmat(ch,1,numel(xAxis)),hdfec,':','MarkerSize',4,'Color','black','MarkerFaceColor','black','LineWidth',0.5,'Parent', AxesMain,'DisplayName','FEC $3.8*10^{-3}$','HandleVisibility','off'); plot3(xdata,repmat(ch,1,numel(xAxis)),hdfec,':','MarkerSize',4,'Color','black','MarkerFaceColor','black','LineWidth',0.5,'Parent', AxesMain,'DisplayName','FEC $3.8*10^{-3}$','HandleVisibility','off');
end end
%h = get(gca,'Children'); %h = get(gca,'Children');
%set(gca,'Children',[h(2) h(1)]) %set(gca,'Children',[h(2) h(1)])
end end
% Figure Settings % Figure Settings
%title(AxesMain,plotJob.title,"Interpreter","none"); %title(AxesMain,plotJob.title,"Interpreter","none");
xlabel(AxesMain,plotJob.xAxisLabel,"Interpreter","none"); xlabel(AxesMain,plotJob.xAxisLabel,"Interpreter","none");
ylabel(AxesMain,plotJob.yAxisLabel,"Interpreter","none"); ylabel(AxesMain,plotJob.yAxisLabel,"Interpreter","none");
set(AxesMain,'zscale','log'); set(AxesMain,'zscale','log');
grid(AxesMain,'on'); grid(AxesMain,'on');
grid(AxesMain,'minor'); grid(AxesMain,'minor');
grid minor grid minor
view(AxesMain,[42.0619302949062 23.4176470588235]); view(AxesMain,[42.0619302949062 23.4176470588235]);
%legend(AxesMain); %legend(AxesMain);
fontsize(AxesMain,8,"points") fontsize(AxesMain,8,"points")
fontname(AxesMain,"Arial") fontname(AxesMain,"Arial")
fig.Position = plotJob.Position; fig.Position = plotJob.Position;
fig.Units = "centimeters"; fig.Units = "centimeters";
fig.Position = [2 2 8.5 7]; fig.Position = [2 2 8.5 7];
set(AxesMain,'TickLabelInterpreter','none') set(AxesMain,'TickLabelInterpreter','none')
set(AxesMain.Legend,'Interpreter','none') set(AxesMain.Legend,'Interpreter','none')
% set(gcf,'Units','centimeters') % set(gcf,'Units','centimeters')
% set(gcf,'Position',[2 2 9 4.5]) % set(gcf,'Position',[2 2 9 4.5])
zlim([1e-4,0.3]); zlim([1e-4,0.3]);
xlim([min(xAxis),-3]); xlim([min(xAxis),-3]);
annotation('textbox', [0.125, 0.32, 0.1, 0.1], 'String', "FEC 3.8e-3","LineStyle","none","FontSize",8,"FontUnits","points") annotation('textbox', [0.125, 0.32, 0.1, 0.1], 'String', "FEC 3.8e-3","LineStyle","none","FontSize",8,"FontUnits","points")
hold off hold off
end end
function vec = removeZeros(vec) function vec = removeZeros(vec)
% Find rows that contain only zeros % Find rows that contain only zeros
rows_to_remove = all(vec == 0, 2); rows_to_remove = all(vec == 0, 2);
% Remove rows with only zeros % Remove rows with only zeros
vec(rows_to_remove, :) = []; vec(rows_to_remove, :) = [];
end end

View File

@@ -1,300 +1,300 @@
function plotBerVsZDW(wh,plotJob) function plotBerVsZDW(wh,plotJob)
fig = findall(groot, 'Type', 'figure', 'Name', plotJob.figName); fig = findall(groot, 'Type', 'figure', 'Name', plotJob.figName);
if isvalid(fig) if isvalid(fig)
figure(fig) figure(fig)
fig = get(fig); fig = get(fig);
AxesMain = fig.CurrentAxes; AxesMain = fig.CurrentAxes;
hold on hold on
else else
fig = figure('name',char(plotJob.figName)); fig = figure('name',char(plotJob.figName));
AxesMain = gca; AxesMain = gca;
hold on hold on
end end
col = plotJob.color; col = plotJob.color;
% we want to fetch all realizations % we want to fetch all realizations
realization = wh.parameter.realization.values(1:end); realization = wh.parameter.realization.values(1:end);
% get all xAxis values % get all xAxis values
xAxis = wh.parameter.p_out.values; xAxis = wh.parameter.p_out.values;
% get all center wavelengths % get all center wavelengths
wavelengths = wh.parameter.center_wavelength.values; wavelengths = wh.parameter.center_wavelength.values;
% totber = NaN(numel(realization),1,numel(xAxis),numel(wavelengths)); % totber = NaN(numel(realization),1,numel(xAxis),numel(wavelengths));
% ber = zeros(numel(realization),plotJob.ch,numel(xAxis),numel(wavelengths)); % ber = zeros(numel(realization),plotJob.ch,numel(xAxis),numel(wavelengths));
%get BER values for query %get BER values for query
for w = 2:numel(wavelengths) for w = 2:numel(wavelengths)
for xl = 1:numel(xAxis) for xl = 1:numel(xAxis)
c_wavelen = wavelengths(w); c_wavelen = wavelengths(w);
p_out = xAxis(xl); p_out = xAxis(xl);
% dim1 : realiz; dim2: channels, dim3: rop, dim4, c_wavelength % dim1 : realiz; dim2: channels, dim3: rop, dim4, c_wavelength
temp = removeZeros(wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.ch,c_wavelen,plotJob.channelspacing,plotJob.randzdw)); temp = removeZeros(wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.ch,c_wavelen,plotJob.channelspacing,plotJob.randzdw));
ber(1:size(temp,1),:,xl,w) = temp; ber(1:size(temp,1),:,xl,w) = temp;
end end
end end
hdfec = 3.8e-3.*ones(size(xAxis)); hdfec = 3.8e-3.*ones(size(xAxis));
zdw_ = []; zdw_ = [];
zdw_chann = []; zdw_chann = [];
zdw_tot = []; zdw_tot = [];
cf_tot = []; cf_tot = [];
cf_ = []; cf_ = [];
S = []; S = [];
Stot = []; Stot = [];
S_chann = []; S_chann = [];
cf_chann = []; cf_chann = [];
cnt = 0; cnt = 0;
%get fec thresholds %get fec thresholds
%linear = squeeze(linear); %linear = squeeze(linear);
for c_wavelen = 1:size(ber,4) for c_wavelen = 1:size(ber,4)
for realiz = 1:size(ber,1) for realiz = 1:size(ber,1)
for chann = 1:size(ber,2) for chann = 1:size(ber,2)
%finde Schnittpunkt zwischen FEC und BER Kurve %finde Schnittpunkt zwischen FEC und BER Kurve
temp_ber = squeeze(ber(realiz,chann,:,c_wavelen)).'; temp_ber = squeeze(ber(realiz,chann,:,c_wavelen)).';
if ~all(temp_ber == 0) if ~all(temp_ber == 0)
%nur wenn nicht alles nullen sind %nur wenn nicht alles nullen sind
crossing_ch = InterX([hdfec;xAxis],[temp_ber;xAxis]); crossing_ch = InterX([hdfec;xAxis],[temp_ber;xAxis]);
else else
continue continue
end end
%Req. FEC Ergebnis einsortieren %Req. FEC Ergebnis einsortieren
if ~isempty(crossing_ch) if ~isempty(crossing_ch)
if crossing_ch(2) == 0 if crossing_ch(2) == 0
print("d") print("d")
end end
S(realiz,chann,c_wavelen) = crossing_ch(2); S(realiz,chann,c_wavelen) = crossing_ch(2);
else else
S(realiz,chann,c_wavelen) = -1; S(realiz,chann,c_wavelen) = -1;
cnt = cnt +1; cnt = cnt +1;
end end
end end
end end
end end
temp_max = -inf; temp_max = -inf;
for i = 1:plotJob.ch for i = 1:plotJob.ch
hold on hold on
%S:: 1.dim: realiz; 2.dim: channel; 3.dim: center wavelength %S:: 1.dim: realiz; 2.dim: channel; 3.dim: center wavelength
%squeeze a channel: %squeeze a channel:
temp_data = squeeze(S(:,i,:)); temp_data = squeeze(S(:,i,:));
%remove realizations that have no entry (only zero) %remove realizations that have no entry (only zero)
temp_data = removeZeros(temp_data); temp_data = removeZeros(temp_data);
%replace zeros with NAN (e.g. for the wavelengths that have missing realizations) %replace zeros with NAN (e.g. for the wavelengths that have missing realizations)
temp_data(temp_data==0) = NaN; temp_data(temp_data==0) = NaN;
%plot required ROP for channel and all realizations that cross the %plot required ROP for channel and all realizations that cross the
%FEC limit %FEC limit
scatter(wavelengths,temp_data ,5,plotJob.color,'Marker','.'); scatter(wavelengths,temp_data ,5,plotJob.color,'Marker','.');
% %plot mean per channel % %plot mean per channel
% temp_mean = mean(temp_data,'omitnan'); % temp_mean = mean(temp_data,'omitnan');
% hold on % hold on
% plot(wavelengths,temp_mean,'Marker','*'); % plot(wavelengths,temp_mean,'Marker','*');
%get max overall value %get max overall value
temp_max = max(temp_max,max(temp_data)); temp_max = max(temp_max,max(temp_data));
end end
%plot mean overall %plot mean overall
mean_overall = squeeze(mean(S,2)); mean_overall = squeeze(mean(S,2));
mean_overall(mean_overall==0) = NaN; mean_overall(mean_overall==0) = NaN;
%mean_overall(mean_overall==-1) = NaN; %mean_overall(mean_overall==-1) = NaN;
mean_overall=mean(mean_overall,1,'omitnan'); mean_overall=mean(mean_overall,1,'omitnan');
plot(wavelengths,mean_overall,'Color',plotJob.color); plot(wavelengths,mean_overall,'Color',plotJob.color);
%plot max overall %plot max overall
scatter(wavelengths,temp_max ,35,plotJob.color,'Marker','v'); scatter(wavelengths,temp_max ,35,plotJob.color,'Marker','v');
%plot channel positions %plot channel positions
hold on hold on
chpos = calcWavelengthPlan(plotJob.ch, 400e9, 1310); chpos = calcWavelengthPlan(plotJob.ch, 400e9, 1310);
xline(chpos,'LineWidth',2,'Alpha',0.2); xline(chpos,'LineWidth',2,'Alpha',0.2);
chpos = calcWavelengthPlan(plotJob.ch, 400e9, chpos(4)); chpos = calcWavelengthPlan(plotJob.ch, 400e9, chpos(4));
xline(chpos,'LineWidth',2,'Alpha',0.2); xline(chpos,'LineWidth',2,'Alpha',0.2);
fig.Position = plotJob.Position; fig.Position = plotJob.Position;
ylabel('Penalty in dB'); ylabel('Penalty in dB');
xlabel('Wavelength in nm'); xlabel('Wavelength in nm');
xlim([min(wavelengths),max(wavelengths) ]); xlim([min(wavelengths),max(wavelengths) ]);
grid minor; grid minor;
set(gca, 'color', 'none'); set(gca, 'color', 'none');
legend = []; legend = [];
fontsize(AxesMain,8,"points") fontsize(AxesMain,8,"points")
fig.Position = plotJob.Position; fig.Position = plotJob.Position;
fig.Units = "centimeters"; fig.Units = "centimeters";
fig.Position = [2 2 8.5 7]; fig.Position = [2 2 8.5 7];
set(AxesMain,'TickLabelInterpreter','latex') set(AxesMain,'TickLabelInterpreter','latex')
set(AxesMain.Legend,'Interpreter','latex') set(AxesMain.Legend,'Interpreter','latex')
% %
% %
% %
% %
% %
% distinct_cf = unique(cf_chann); % distinct_cf = unique(cf_chann);
% %
% for i = 1:length(distinct_cf) % for i = 1:length(distinct_cf)
% indices = find(cf_chann==distinct_cf(i)); % indices = find(cf_chann==distinct_cf(i));
% cf(i) = distinct_cf(i); % cf(i) = distinct_cf(i);
% worst_fec_cross(i) = max(S_chann(indices)); % worst_fec_cross(i) = max(S_chann(indices));
% avg_fec_cross(i) = mean(S_chann(indices)); % avg_fec_cross(i) = mean(S_chann(indices));
% end % end
% %
% avg_fec_cross = smooth(avg_fec_cross,5); % avg_fec_cross = smooth(avg_fec_cross,5);
% %
% figure(224) % figure(224)
% hold on % hold on
% scatter(cf_,S,10.*abs(S-mean(S)).*ones(size(S)),'DisplayName',['AVG'],'MarkerEdgeColor',col,'MarkerFaceColor',col,'Marker','.'); % scatter(cf_,S,10.*abs(S-mean(S)).*ones(size(S)),'DisplayName',['AVG'],'MarkerEdgeColor',col,'MarkerFaceColor',col,'Marker','.');
% hold on % hold on
% scatter(cf(2:end),worst_fec_cross(2:end),15,'DisplayName',['Worst'],'MarkerEdgeColor',col,'MarkerFaceColor',col,'Marker','.','HandleVisibility','off'); % scatter(cf(2:end),worst_fec_cross(2:end),15,'DisplayName',['Worst'],'MarkerEdgeColor',col,'MarkerFaceColor',col,'Marker','.','HandleVisibility','off');
% plot(cf(2:end),avg_fec_cross(2:end),'DisplayName',['AVG'],'LineWidth',1,'LineStyle','-','Color',col,'Marker','none','MarkerFaceColor',col,'MarkerSize',2); % plot(cf(2:end),avg_fec_cross(2:end),'DisplayName',['AVG'],'LineWidth',1,'LineStyle','-','Color',col,'Marker','none','MarkerFaceColor',col,'MarkerSize',2);
% plot(cf(2:end),worst_fec_cross(2:end),'DisplayName',['AVG'],'LineWidth',0.5,'LineStyle','-','Color',col,'Marker','none','MarkerFaceColor',col,'MarkerSize',2); % plot(cf(2:end),worst_fec_cross(2:end),'DisplayName',['AVG'],'LineWidth',0.5,'LineStyle','-','Color',col,'Marker','none','MarkerFaceColor',col,'MarkerSize',2);
% ghzgrid = hz2nm(nm2hz(1310)+[0:1:20].*400e9); % ghzgrid = hz2nm(nm2hz(1310)+[0:1:20].*400e9);
% set(gca,'xtick',sort(ghzgrid)) % set(gca,'xtick',sort(ghzgrid))
% xlim([min(cf(cf~=0)), 1310.1]); % xlim([min(cf(cf~=0)), 1310.1]);
% %
% %
% % With matlab internal errorbar function... % % With matlab internal errorbar function...
% figure(221) % figure(221)
% %plot(cf,avg_fec_cross,'DisplayName',['AVG'],'LineWidth',1,'Color',col,'Marker','none','MarkerFaceColor',col,'MarkerSize',2); % %plot(cf,avg_fec_cross,'DisplayName',['AVG'],'LineWidth',1,'Color',col,'Marker','none','MarkerFaceColor',col,'MarkerSize',2);
% hold on % hold on
% %plot(cf_tot,min(S_chann(1:length(cf_tot),:),[],2),'DisplayName',['AVG'],'LineWidth',1,'LineStyle',':','Color',col,'Marker','^','MarkerFaceColor',col,'MarkerSize',2); % %plot(cf_tot,min(S_chann(1:length(cf_tot),:),[],2),'DisplayName',['AVG'],'LineWidth',1,'LineStyle',':','Color',col,'Marker','^','MarkerFaceColor',col,'MarkerSize',2);
% plot(cf,worst_fec_cross,'DisplayName',['AVG'],'LineWidth',2,'LineStyle','-','Color',col,'Marker','none','MarkerFaceColor',col,'MarkerSize',2); % plot(cf,worst_fec_cross,'DisplayName',['AVG'],'LineWidth',2,'LineStyle','-','Color',col,'Marker','none','MarkerFaceColor',col,'MarkerSize',2);
% ghzgrid = hz2nm(nm2hz(1310)+[0:1:20].*400e9); % ghzgrid = hz2nm(nm2hz(1310)+[0:1:20].*400e9);
% set(gca,'xtick',sort(ghzgrid)) % set(gca,'xtick',sort(ghzgrid))
% xlim([1302, 1310.1]); % xlim([1302, 1310.1]);
% xline(ghzgrid,'LineStyle',':','Color',[.7 .7 .7]); % xline(ghzgrid,'LineStyle',':','Color',[.7 .7 .7]);
%with %with
% Stot = movmean(Stot,5); % Stot = movmean(Stot,5);
% figure(222) % figure(222)
% [hl,hp] = boundedline(cf_tot,Stot,[(Stot'-min(S_chann(1:length(cf_tot),:),[],2)),(max(S_chann(1:length(cf_tot),:),[],2)-Stot')], 'alpha','Color',col,'transparency', 0.05); % [hl,hp] = boundedline(cf_tot,Stot,[(Stot'-min(S_chann(1:length(cf_tot),:),[],2)),(max(S_chann(1:length(cf_tot),:),[],2)-Stot')], 'alpha','Color',col,'transparency', 0.05);
% ho = outlinebounds(hl,hp); % ho = outlinebounds(hl,hp);
% set(ho, 'linestyle', ':', 'color', col, 'marker', '.','linewidth',0.5); % set(ho, 'linestyle', ':', 'color', col, 'marker', '.','linewidth',0.5);
% hold on % hold on
% %
% ghzgrid = hz2nm(nm2hz(1310)+[0:1:12].*400e9); % ghzgrid = hz2nm(nm2hz(1310)+[0:1:12].*400e9);
% xline(ghzgrid); % xline(ghzgrid);
%plot the total ber %plot the total ber
% %figure(22); % %figure(22);
% hold on; % hold on;
% b= movmean(Stot,3); % b= movmean(Stot,3);
% plot(AxesMain,cf_tot,b,'LineWidth',2,'DisplayName',[plotJob.dataStatArg,' Ch.: ', plotJob.displayname],'Color',col,'Marker','o'); % plot(AxesMain,cf_tot,b,'LineWidth',2,'DisplayName',[plotJob.dataStatArg,' Ch.: ', plotJob.displayname],'Color',col,'Marker','o');
% hold on % hold on
%scatter(AxesMain,zdw_,S,'Marker','+','MarkerEdgeColor',col,'MarkerFaceAlpha',0.4,'MarkerEdgeAlpha',0.4,'LineWidth',0.5,'Parent', AxesMain(1),'DisplayName',[plotJob.dataStatArg,' Ch.: ', plotJob.displayname]); %scatter(AxesMain,zdw_,S,'Marker','+','MarkerEdgeColor',col,'MarkerFaceAlpha',0.4,'MarkerEdgeAlpha',0.4,'LineWidth',0.5,'Parent', AxesMain(1),'DisplayName',[plotJob.dataStatArg,' Ch.: ', plotJob.displayname]);
%ylim(AxesMain,[-9.3 -7]); %ylim(AxesMain,[-9.3 -7]);
% for i = 1:numel(chp) % for i = 1:numel(chp)
% hold on % hold on
% xline(AxesMain,chp(i),'Color',colr(i,:),'DisplayName',['CH: ', num2str(i)],'LineWidth',1.5); % xline(AxesMain,chp(i),'Color',colr(i,:),'DisplayName',['CH: ', num2str(i)],'LineWidth',1.5);
% hold off % hold off
% end % end
% %
% a = movmean(sortrows([zdw_; S]'),10,'Endpoints','discard'); % a = movmean(sortrows([zdw_; S]'),10,'Endpoints','discard');
% %
% sorted = sortrows([zdw_; S]'); % sorted = sortrows([zdw_; S]');
% figure(2) % figure(2)
% scatter(sorted(:,1),sorted(:,2)) % scatter(sorted(:,1),sorted(:,2))
% %
% ber_sorted = sort(S); % ber_sorted = sort(S);
% mean(ber_sorted); % mean(ber_sorted);
% std(ber_sorted); % std(ber_sorted);
% z1 = []; % z1 = [];
% penalty = mean(ber_sorted):0.01:mean(ber_sorted)+2; % penalty = mean(ber_sorted):0.01:mean(ber_sorted)+2;
% for i = 1:length(penalty) % for i = 1:length(penalty)
% l = penalty(i); % l = penalty(i);
% if i == 1 % if i == 1
% z1 = [z1 sum(ber_sorted(1,:)<l ) / length(ber_sorted) ]; % z1 = [z1 sum(ber_sorted(1,:)<l ) / length(ber_sorted) ];
% else % else
% z1 = [z1 sum(ber_sorted(1,:)<l & ber_sorted(1,:)>l-0.01) / length(ber_sorted) ]; % z1 = [z1 sum(ber_sorted(1,:)<l & ber_sorted(1,:)>l-0.01) / length(ber_sorted) ];
% end % end
% %
% end % end
% %
% penalty_higherthan = 0.5; % penalty_higherthan = 0.5;
% probability = sum(z1(find(penalty>mean(ber_sorted)+penalty_higherthan))); % probability = sum(z1(find(penalty>mean(ber_sorted)+penalty_higherthan)));
% disp(['A penalty of more than 1dB has a probability of: ', num2str(probability)]); % disp(['A penalty of more than 1dB has a probability of: ', num2str(probability)]);
% % % %
% stem(AxesMain,penalty,z1,"filled",'Marker','o','MarkerSize',2,'Color',col); % stem(AxesMain,penalty,z1,"filled",'Marker','o','MarkerSize',2,'Color',col);
% %
% %
% [f1,x1]=ecdf(S(end,:)); % [f1,x1]=ecdf(S(end,:));
% %figure(23);plot(AxesMain,x1,f1,'r','LineWidth',3, 'Color',col); % %figure(23);plot(AxesMain,x1,f1,'r','LineWidth',3, 'Color',col);
% %
% %plot(AxesMain,a(:,1),a(:,2),'Color',col+1,'Parent', AxesMain(1)); % %plot(AxesMain,a(:,1),a(:,2),'Color',col+1,'Parent', AxesMain(1));
% %
% % histogram(AxesMain,S,1000,'EdgeColor','none','FaceAlpha',0.4); % % histogram(AxesMain,S,1000,'EdgeColor','none','FaceAlpha',0.4);
% %
% %
% %
% % % %
% %scatter(AxesMain,zdw_,S,'Marker','+','MarkerEdgeColor',col,'MarkerFaceAlpha',0.4,'MarkerEdgeAlpha',0.4,'LineWidth',0.5,'Parent', AxesMain(1),'DisplayName',[plotJob.dataStatArg,' Ch.: ', plotJob.displayname]); % %scatter(AxesMain,zdw_,S,'Marker','+','MarkerEdgeColor',col,'MarkerFaceAlpha',0.4,'MarkerEdgeAlpha',0.4,'LineWidth',0.5,'Parent', AxesMain(1),'DisplayName',[plotJob.dataStatArg,' Ch.: ', plotJob.displayname]);
% hold on % hold on
% %scatter(AxesMain,zdw_chann(:,1),mean(S_chann,2),'Marker','diamond','MarkerEdgeColor',col,'MarkerFaceAlpha',0.6,'LineWidth',7,'MarkerFaceColor',col,'Parent', AxesMain(1),'DisplayName',[plotJob.dataStatArg,' Ch.: ', plotJob.displayname]); % %scatter(AxesMain,zdw_chann(:,1),mean(S_chann,2),'Marker','diamond','MarkerEdgeColor',col,'MarkerFaceAlpha',0.6,'LineWidth',7,'MarkerFaceColor',col,'Parent', AxesMain(1),'DisplayName',[plotJob.dataStatArg,' Ch.: ', plotJob.displayname]);
% hold off % hold off
% % % %
% % for rlz = 1:size(S,2) % % for rlz = 1:size(S,2)
% % zdwval = zdw_(rlz); % % zdwval = zdw_(rlz);
% % feccrossing = S(rlz); % % feccrossing = S(rlz);
% % scatter(AxesMain,zdwval,feccrossing,10,'MarkerEdgeColor',col,'MarkerFaceColor',col,'Parent', AxesMain(1),'DisplayName',[plotJob.dataStatArg,' Ch.: ', plotJob.displayname]); % % scatter(AxesMain,zdwval,feccrossing,10,'MarkerEdgeColor',col,'MarkerFaceColor',col,'Parent', AxesMain(1),'DisplayName',[plotJob.dataStatArg,' Ch.: ', plotJob.displayname]);
% % end % % end
% %
% xline([1302.03471732576,1304.30061112288,1306.57440520904,1308.85614097425,1311.14586009814,1313.44360455251,1315.74941660391,1318.06333881618]); % xline([1302.03471732576,1304.30061112288,1306.57440520904,1308.85614097425,1311.14586009814,1313.44360455251,1315.74941660391,1318.06333881618]);
end end
function vec = removeZeros(vec) function vec = removeZeros(vec)
% Find rows that contain only zeros % Find rows that contain only zeros
rows_to_remove = all(vec == 0, 2); rows_to_remove = all(vec == 0, 2);
% Remove rows with only zeros % Remove rows with only zeros
vec(rows_to_remove, :) = []; vec(rows_to_remove, :) = [];
end end

View File

@@ -1,157 +1,157 @@
function plotBerVsZdwFailureRate(wh,plotJob) function plotBerVsZdwFailureRate(wh,plotJob)
fig = findall(groot, 'Type', 'figure', 'Name', plotJob.figName); fig = findall(groot, 'Type', 'figure', 'Name', plotJob.figName);
if isvalid(fig) if isvalid(fig)
figure(fig) figure(fig)
fig = get(fig); fig = get(fig);
AxesMain = fig.CurrentAxes; AxesMain = fig.CurrentAxes;
hold on hold on
else else
fig = figure('name',char(plotJob.figName)); fig = figure('name',char(plotJob.figName));
AxesMain = gca; AxesMain = gca;
hold on hold on
end end
col = plotJob.color; col = plotJob.color;
% we want to fetch all realizations % we want to fetch all realizations
realization = wh.parameter.realization.values(1:end); realization = wh.parameter.realization.values(1:end);
% get all xAxis values % get all xAxis values
xAxis = wh.parameter.p_out.values; xAxis = wh.parameter.p_out.values;
% get all center wavelengths % get all center wavelengths
wavelengths = wh.parameter.center_wavelength.values; wavelengths = wh.parameter.center_wavelength.values;
%wavelengths = wavelengths(2:end); %wavelengths = wavelengths(2:end);
% totber = NaN(numel(realization),1,numel(xAxis),numel(wavelengths)); % totber = NaN(numel(realization),1,numel(xAxis),numel(wavelengths));
% ber = zeros(numel(realization),plotJob.ch,numel(xAxis),numel(wavelengths)); % ber = zeros(numel(realization),plotJob.ch,numel(xAxis),numel(wavelengths));
%get BER values for query %get BER values for query
for w = 1:numel(wavelengths) for w = 1:numel(wavelengths)
for xl = 1:numel(xAxis) for xl = 1:numel(xAxis)
c_wavelen = wavelengths(w); c_wavelen = wavelengths(w);
p_out = xAxis(xl); p_out = xAxis(xl);
% dim1 : realiz; dim2: channels, dim3: rop, dim4, c_wavelength % dim1 : realiz; dim2: channels, dim3: rop, dim4, c_wavelength
temp = removeZeros(wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.ch,c_wavelen,plotJob.channelspacing,plotJob.randzdw)); temp = removeZeros(wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.ch,c_wavelen,plotJob.channelspacing,plotJob.randzdw));
ber(1:size(temp,1),:,xl,w) = temp; ber(1:size(temp,1),:,xl,w) = temp;
end end
end end
hdfec = 3.8e-3.*ones(size(xAxis)); hdfec = 3.8e-3.*ones(size(xAxis));
zdw_ = []; zdw_ = [];
zdw_chann = []; zdw_chann = [];
zdw_tot = []; zdw_tot = [];
cf_tot = []; cf_tot = [];
cf_ = []; cf_ = [];
S = []; S = [];
Stot = []; Stot = [];
S_chann = []; S_chann = [];
cf_chann = []; cf_chann = [];
cnt = 0; cnt = 0;
%get fec thresholds %get fec thresholds
%linear = squeeze(linear); %linear = squeeze(linear);
for c_wavelen = 1:size(ber,4) for c_wavelen = 1:size(ber,4)
for realiz = 1:size(ber,1) for realiz = 1:size(ber,1)
for chann = 1:size(ber,2) for chann = 1:size(ber,2)
%finde Schnittpunkt zwischen FEC und BER Kurve %finde Schnittpunkt zwischen FEC und BER Kurve
temp_ber = squeeze(ber(realiz,chann,:,c_wavelen)).'; temp_ber = squeeze(ber(realiz,chann,:,c_wavelen)).';
if ~all(temp_ber == 0) if ~all(temp_ber == 0)
%nur wenn nicht alles nullen sind %nur wenn nicht alles nullen sind
crossing_ch = InterX([hdfec;xAxis],[temp_ber;xAxis]); crossing_ch = InterX([hdfec;xAxis],[temp_ber;xAxis]);
else else
continue continue
end end
%Req. FEC Ergebnis einsortieren %Req. FEC Ergebnis einsortieren
if ~isempty(crossing_ch) if ~isempty(crossing_ch)
if crossing_ch(2) == 0 if crossing_ch(2) == 0
print("d") print("d")
end end
S(realiz,chann,c_wavelen) = crossing_ch(2); S(realiz,chann,c_wavelen) = crossing_ch(2);
else else
S(realiz,chann,c_wavelen) = -1; S(realiz,chann,c_wavelen) = -1;
cnt = cnt +1; cnt = cnt +1;
end end
end end
end end
end end
temp_max = -inf; temp_max = -inf;
sum_FEC_not_crossed=[]; sum_FEC_not_crossed=[];
sum_FEC_crossed=[]; sum_FEC_crossed=[];
threshold = plotJob.p_in - 10; threshold = plotJob.p_in - 10;
for i = 1:plotJob.ch for i = 1:plotJob.ch
hold on hold on
%S:: 1.dim: realiz; 2.dim: channel; 3.dim: center wavelength %S:: 1.dim: realiz; 2.dim: channel; 3.dim: center wavelength
%squeeze a channel: %squeeze a channel:
temp_data = squeeze(S(:,i,:)); temp_data = squeeze(S(:,i,:));
%remove realizations that have no entry (only zero) %remove realizations that have no entry (only zero)
temp_data = removeZeros(temp_data); temp_data = removeZeros(temp_data);
%replace zeros with NAN (e.g. for the wavelengths that have missing realizations) %replace zeros with NAN (e.g. for the wavelengths that have missing realizations)
temp_data(temp_data==0) = NaN; temp_data(temp_data==0) = NaN;
%for current channel %for current channel
FEC_crossed = temp_data < threshold & ~isnan(temp_data); FEC_crossed = temp_data < threshold & ~isnan(temp_data);
FEC_not_crossed = temp_data >= threshold & ~isnan(temp_data); FEC_not_crossed = temp_data >= threshold & ~isnan(temp_data);
%sum over channels for overall picture %sum over channels for overall picture
sum_FEC_not_crossed(i,:) = sum(FEC_not_crossed); sum_FEC_not_crossed(i,:) = sum(FEC_not_crossed);
sum_FEC_crossed(i,:) = sum(FEC_crossed); sum_FEC_crossed(i,:) = sum(FEC_crossed);
failure_rate_channelwise(i,:) = sum_FEC_not_crossed(i,:)./ ( sum_FEC_crossed(i,:) + sum_FEC_not_crossed(i,:)); failure_rate_channelwise(i,:) = sum_FEC_not_crossed(i,:)./ ( sum_FEC_crossed(i,:) + sum_FEC_not_crossed(i,:));
end end
failure_rate_total = sum(sum_FEC_not_crossed,1) ./ ( sum(sum_FEC_crossed,1) + sum(sum_FEC_not_crossed,1) ); failure_rate_total = sum(sum_FEC_not_crossed,1) ./ ( sum(sum_FEC_crossed,1) + sum(sum_FEC_not_crossed,1) );
% plot failure rate (nbetween 0 and 1) % plot failure rate (nbetween 0 and 1)
plot(wavelengths,failure_rate_total,'Color',plotJob.color,'LineWidth',1,'LineStyle',plotJob.plotTypeArg,'Marker','x','MarkerSize',5,'MarkerFaceColor',plotJob.color,'DisplayName',plotJob.displayname); plot(wavelengths,failure_rate_total,'Color',plotJob.color,'LineWidth',1,'LineStyle',plotJob.plotTypeArg,'Marker','x','MarkerSize',5,'MarkerFaceColor',plotJob.color,'DisplayName',plotJob.displayname);
%plot max overall %plot max overall
%scatter(wavelengths,failure_rate_channelwise ,35,plotJob.color,'Marker','.'); %scatter(wavelengths,failure_rate_channelwise ,35,plotJob.color,'Marker','.');
ylabel('Failure Rate of Link'); ylabel('Failure Rate of Link');
xlabel('Wavelength in nm'); xlabel('Wavelength in nm');
xlim([min(wavelengths),max(wavelengths) ]); xlim([min(wavelengths),max(wavelengths) ]);
ylim([0,1]); ylim([0,1]);
grid minor; grid minor;
set(gca, 'color', 'none'); set(gca, 'color', 'none');
legend = []; legend = [];
% fontsize(AxesMain,8,"points") % fontsize(AxesMain,8,"points")
fig.Position = plotJob.Position; fig.Position = plotJob.Position;
fig.Units = "centimeters"; fig.Units = "centimeters";
fig.Position = [0 0 12 5 7]; fig.Position = [0 0 12 5 7];
try try
set(AxesMain,'TickLabelInterpreter','latex') set(AxesMain,'TickLabelInterpreter','latex')
set(AxesMain.Legend,'Interpreter','latex') set(AxesMain.Legend,'Interpreter','latex')
end end
end end
function vec = removeZeros(vec) function vec = removeZeros(vec)
% Find rows that contain only zeros % Find rows that contain only zeros
rows_to_remove = all(vec == 0, 2); rows_to_remove = all(vec == 0, 2);
% Remove rows with only zeros % Remove rows with only zeros
vec(rows_to_remove, :) = []; vec(rows_to_remove, :) = [];
end end

View File

@@ -1,51 +1,51 @@
function plotChannelSpacingAna(wh,plotJob) function plotChannelSpacingAna(wh,plotJob)
xAxis = wh.parameter.p_out.values; xAxis = wh.parameter.p_out.values;
realization = wh.parameter.realization.values(1:end); realization = wh.parameter.realization.values(1:end);
channelsp = wh.parameter.channelspacing.values(1:end); channelsp = wh.parameter.channelspacing.values(1:end);
channelsp = [200 400].*1e9; channelsp = [200 400].*1e9;
for ch = 1:2 for ch = 1:2
channspacing = channelsp(ch); channspacing = channelsp(ch);
for xl = 1:numel(xAxis) for xl = 1:numel(xAxis)
p_out = xAxis(xl); p_out = xAxis(xl);
curber = wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.numchannels,channspacing); curber = wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.numchannels,channspacing);
curzdw = wh.getStoValue('zdw',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.numchannels,channspacing); curzdw = wh.getStoValue('zdw',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.numchannels,channspacing);
ber(1:size(curber,1),1:size(curber,2),xl) = curber; ber(1:size(curber,1),1:size(curber,2),xl) = curber;
zdw(1:size(curber,1),1,xl) = curzdw; zdw(1:size(curber,1),1,xl) = curzdw;
end end
ber = squeeze(mean(ber,1)); ber = squeeze(mean(ber,1));
zdw = squeeze(mean(zdw,1)); zdw = squeeze(mean(zdw,1));
hdfec = 3.8e-3.*ones(size(xAxis)); hdfec = 3.8e-3.*ones(size(xAxis));
S = []; S = [];
wavelength={}; wavelength={};
zdw_ = []; zdw_ = [];
zdw_chann = []; zdw_chann = [];
zdw_tot = []; zdw_tot = [];
S = []; S = [];
S_chann = []; S_chann = [];
wl = round([1302.03471732576,1304.30061112288,1306.57440520904,1308.85614097425,1311.14586009814,1313.44360455251,1315.74941660391,1318.06333881618],2); wl = round([1302.03471732576,1304.30061112288,1306.57440520904,1308.85614097425,1311.14586009814,1313.44360455251,1315.74941660391,1318.06333881618],2);
wl = 1:16; wl = 1:16;
wl = [1.2930 1.2953 1.2975 1.2998 1.3020 1.3043 1.3066 1.3089 1.3111 1.3134 1.3157 1.3181 1.3204 1.3227 1.3251 1.3274]; wl = [1.2930 1.2953 1.2975 1.2998 1.3020 1.3043 1.3066 1.3089 1.3111 1.3134 1.3157 1.3181 1.3204 1.3227 1.3251 1.3274];
a = InterX([hdfec(:)';xAxis],[mean(ber,1);xAxis]); a = InterX([hdfec(:)';xAxis],[mean(ber,1);xAxis]);
if ~isempty(a) if ~isempty(a)
s(ch) = a(2); s(ch) = a(2);
else else
s(ch) = NaN; s(ch) = NaN;
end end
end end
figure(2224) figure(2224)
hold on hold on
plot(channelsp,s,'LineWidth',1,'Color',plotJob.color,'Marker','o'); plot(channelsp,s,'LineWidth',1,'Color',plotJob.color,'Marker','o');

View File

@@ -1,294 +1,294 @@
function plotCurve(wh,plotJob) function plotCurve(wh,plotJob)
%PLOTCURVE Summary of this function goes here %PLOTCURVE Summary of this function goes here
% Detailed explanation goes here % Detailed explanation goes here
fig = findall(groot, 'Type', 'figure', 'Name', plotJob.figName); fig = findall(groot, 'Type', 'figure', 'Name', plotJob.figName);
if isvalid(fig) if isvalid(fig)
figure(fig) figure(fig)
% fig = get(fig); % fig = get(fig);
AxesMain = fig.CurrentAxes; AxesMain = fig.CurrentAxes;
hold on hold on
else else
fig = figure('name',char(plotJob.figName)); fig = figure('name',char(plotJob.figName));
AxesMain = gca; AxesMain = gca;
hold on hold on
end end
col = plotJob.color; col = plotJob.color;
% we want to fetch all realizations % we want to fetch all realizations
if plotJob.pmd == 0 if plotJob.pmd == 0
realization = 499; realization = 499;
% realization = 0:7; % realization = 0:7;
else else
realization = wh.parameter.realization.values(1:end); realization = wh.parameter.realization.values(1:end);
end end
realization = wh.parameter.realization.values(1:end); realization = wh.parameter.realization.values(1:end);
% get all xAxis values % get all xAxis values
xAxis = wh.parameter.p_out.values; xAxis = wh.parameter.p_out.values;
markerstyle = 'o'; markerstyle = 'o';
linestyle = '-'; linestyle = '-';
% Fetch Data from Warehouse % Fetch Data from Warehouse
for xl = 1:numel(xAxis) for xl = 1:numel(xAxis)
p_out = xAxis(xl); p_out = xAxis(xl);
if string(plotJob.dataStatArg) == "Worst" if string(plotJob.dataStatArg) == "Worst"
temp = wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.ch,1310,plotJob.channelspacing,plotJob.randzdw); temp = wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.ch,1310,plotJob.channelspacing,plotJob.randzdw);
temp = removeZeros(temp); temp = removeZeros(temp);
ber(xl) = quantile(temp,0.9,"all"); ber(xl) = quantile(temp,0.9,"all");
% ber(xl) = max(temp,[],'all'); % ber(xl) = max(temp,[],'all');
linew = 1.0; linew = 1.0;
markersz = plotJob.markersize; markersz = plotJob.markersize;
markerstyle = plotJob.markerstyle; markerstyle = plotJob.markerstyle;
linestyle = plotJob.linestyle; linestyle = plotJob.linestyle;
elseif string(plotJob.dataStatArg) == "AVG" elseif string(plotJob.dataStatArg) == "AVG"
temp = wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.ch,1310,plotJob.channelspacing,plotJob.randzdw); temp = wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.ch,1310,plotJob.channelspacing,plotJob.randzdw);
temp = removeZeros(temp); temp = removeZeros(temp);
ber(xl) = mean(temp,'all'); ber(xl) = mean(temp,'all');
linew = 1.0; linew = 1.0;
markersz = plotJob.markersize; markersz = plotJob.markersize;
markerstyle = plotJob.markerstyle; markerstyle = plotJob.markerstyle;
linestyle = plotJob.linestyle; linestyle = plotJob.linestyle;
elseif string(plotJob.dataStatArg) == "Best" elseif string(plotJob.dataStatArg) == "Best"
temp = wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.ch,1310,plotJob.channelspacing,plotJob.randzdw); temp = wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.ch,1310,plotJob.channelspacing,plotJob.randzdw);
temp = removeZeros(temp); temp = removeZeros(temp);
ber(xl) = min(temp,[],'all'); ber(xl) = min(temp,[],'all');
linew = 1.0; linew = 1.0;
markersz = plotJob.markersize; markersz = plotJob.markersize;
markerstyle = plotJob.markerstyle; markerstyle = plotJob.markerstyle;
linestyle = plotJob.linestyle; linestyle = plotJob.linestyle;
elseif string(plotJob.dataStatArg) == "All Channels; mean(PMD Realizations)" elseif string(plotJob.dataStatArg) == "All Channels; mean(PMD Realizations)"
temp = wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.ch,1310,plotJob.channelspacing,plotJob.randzdw); temp = wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.ch,1310,plotJob.channelspacing,plotJob.randzdw);
temp = removeZeros(temp); temp = removeZeros(temp);
ber(:,xl) = mean(temp,1,"omitnan").'; ber(:,xl) = mean(temp,1,"omitnan").';
linew = 1; linew = 1;
markersz = 1; markersz = 1;
markerstyle = plotJob.markerstyle; markerstyle = plotJob.markerstyle;
linestyle = plotJob.linestyle; linestyle = plotJob.linestyle;
elseif string(plotJob.dataStatArg) == "Lineplot with quartiles" elseif string(plotJob.dataStatArg) == "Lineplot with quartiles"
temp = wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.ch,1310,plotJob.channelspacing,plotJob.randzdw); temp = wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.ch,1310,plotJob.channelspacing,plotJob.randzdw);
temp = removeZeros(temp); temp = removeZeros(temp);
ber(xl) = mean(temp,"all","omitnan").'; ber(xl) = mean(temp,"all","omitnan").';
upperq(xl) = quantile(temp,0.99,"all"); upperq(xl) = quantile(temp,0.99,"all");
lowerq(xl) = quantile(temp,0.04,"all"); lowerq(xl) = quantile(temp,0.04,"all");
% upperq(xl) = 0.5*std(tmp,1,'all','omitnan'); % upperq(xl) = 0.5*std(tmp,1,'all','omitnan');
% lowerq(xl) = 0.5*std(tmp,1,'all','omitnan'); % lowerq(xl) = 0.5*std(tmp,1,'all','omitnan');
upperq(xl) = max(temp(:)); upperq(xl) = max(temp(:));
lowerq(xl) = min(temp(:)); lowerq(xl) = min(temp(:));
if lowerq(xl) == 0 if lowerq(xl) == 0
lowerq(xl) = 1e-8; lowerq(xl) = 1e-8;
end end
% upperq(xl) = mean(tmp,"all","omitnan") + 1.96 * (std(tmp,1,'all','omitnan')/sqrt(numel(tmp))); % upperq(xl) = mean(tmp,"all","omitnan") + 1.96 * (std(tmp,1,'all','omitnan')/sqrt(numel(tmp)));
% lowerq(xl) = mean(tmp,"all","omitnan") - 1.96 * (std(tmp,1,'all','omitnan')/sqrt(numel(tmp))); % lowerq(xl) = mean(tmp,"all","omitnan") - 1.96 * (std(tmp,1,'all','omitnan')/sqrt(numel(tmp)));
linew = 1; linew = 1;
markersz = 1; markersz = 1;
linestyle = '-'; linestyle = '-';
elseif string(plotJob.dataStatArg) == "All Channels ;All PMD Realizations" elseif string(plotJob.dataStatArg) == "All Channels ;All PMD Realizations"
raw_fetch = wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.ch,1310,plotJob.channelspacing,plotJob.randzdw).'; raw_fetch = wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.ch,1310,plotJob.channelspacing,plotJob.randzdw).';
tmp = reshape(raw_fetch,[],1); tmp = reshape(raw_fetch,[],1);
ber(1:size(tmp,1),xl) = tmp; ber(1:size(tmp,1),xl) = tmp;
ber_per_chann(:,:,xl) = raw_fetch; ber_per_chann(:,:,xl) = raw_fetch;
linew = 0.3; linew = 0.3;
markersz = 2; markersz = 2;
linestyle = ':'; linestyle = ':';
end end
end end
%routine to remove total outliers (here those wehere the rop curve has a mean BER greater than 0.1) %routine to remove total outliers (here those wehere the rop curve has a mean BER greater than 0.1)
% ber_per_chann_clean = NaN(size(ber_per_chann)); % ber_per_chann_clean = NaN(size(ber_per_chann));
% for ch = 1:size(ber_per_chann,1) % for ch = 1:size(ber_per_chann,1)
% bla = squeeze(ber_per_chann(ch,:,:)); % bla = squeeze(ber_per_chann(ch,:,:));
% ber_per_chann(ch,find(mean(bla,2)>0.25),:) = NaN; % ber_per_chann(ch,find(mean(bla,2)>0.25),:) = NaN;
% cleaned = rmoutliers(bla,"mean",'ThresholdFactor',2); % cleaned = rmoutliers(bla,"mean",'ThresholdFactor',2);
% %
% ber_per_chann_clean(ch,1:size(cleaned,1),1:size(cleaned,2)) = cleaned; % ber_per_chann_clean(ch,1:size(cleaned,1),1:size(cleaned,2)) = cleaned;
% %
% end % end
% %
% ber = []; % ber = [];
% for rop = 1:size(ber_per_chann,3) % for rop = 1:size(ber_per_chann,3)
% temp = squeeze(ber_per_chann_clean(:,:,rop)); % temp = squeeze(ber_per_chann_clean(:,:,rop));
% ber(rop) = mean(temp,"all","omitnan").'; % ber(rop) = mean(temp,"all","omitnan").';
% upperq(rop) = quantile(temp,0.9,"all"); % upperq(rop) = quantile(temp,0.9,"all");
% lowerq(rop) = quantile(temp,0.1,"all"); % lowerq(rop) = quantile(temp,0.1,"all");
% end % end
xAxis = xAxis; xAxis = xAxis;
% Plot Data % Plot Data
if string(plotJob.plotTypeArg) == "Scatter" if string(plotJob.plotTypeArg) == "Scatter"
for rlz = 1:size(ber,1) for rlz = 1:size(ber,1)
if rlz < size(ber,1) if rlz < size(ber,1)
scatter(xAxis,ber(rlz,:),markersz,'MarkerEdgeColor',col,'MarkerFaceColor',col,'Parent', AxesMain(1),'HandleVisibility','off'); scatter(xAxis,ber(rlz,:),markersz,'MarkerEdgeColor',col,'MarkerFaceColor',col,'Parent', AxesMain(1),'HandleVisibility','off');
else else
scatter(xAxis,ber(rlz,:),markersz,'MarkerEdgeColor',col,'MarkerFaceColor',col,'Parent', AxesMain(1),'DisplayName',[plotJob.dataStatArg,' Ch.: ', plotJob.displayname]); scatter(xAxis,ber(rlz,:),markersz,'MarkerEdgeColor',col,'MarkerFaceColor',col,'Parent', AxesMain(1),'DisplayName',[plotJob.dataStatArg,' Ch.: ', plotJob.displayname]);
end end
end end
elseif string(plotJob.plotTypeArg) == "Lines" elseif string(plotJob.plotTypeArg) == "Lines"
% if ~anynan(ber) % if ~anynan(ber)
% [xAxis,ber] = interpCurve(xAxis, ber); % [xAxis,ber] = interpCurve(xAxis, ber);
% end % end
cols = cbrewer2('RdBu',size(ber,1)); cols = cbrewer2('RdBu',size(ber,1));
for rlz = 1:size(ber,1) for rlz = 1:size(ber,1)
% %
if (string(plotJob.dataStatArg) == "All Channels ;All PMD Realizations")||(string(plotJob.dataStatArg) == "All Channels; mean(PMD Realizations)") if (string(plotJob.dataStatArg) == "All Channels ;All PMD Realizations")||(string(plotJob.dataStatArg) == "All Channels; mean(PMD Realizations)")
ch = mod(rlz,plotJob.ch); ch = mod(rlz,plotJob.ch);
if ch == 0; ch = plotJob.ch; end if ch == 0; ch = plotJob.ch; end
else else
ch = plotJob.dataStatArg; ch = plotJob.dataStatArg;
end end
if rlz < size(ber,1) if rlz < size(ber,1)
col = cols(rlz,:); col = cols(rlz,:);
s = plot(xAxis,ber(rlz,:),linestyle,'Marker',"none",'MarkerSize',markersz,'LineWidth',linew,'Color',col,'Parent', AxesMain,'HandleVisibility','off'); s = plot(xAxis,ber(rlz,:),linestyle,'Marker',"none",'MarkerSize',markersz,'LineWidth',linew,'Color',col,'Parent', AxesMain,'HandleVisibility','off');
s.DataTipTemplate.Interpreter = "latex"; s.DataTipTemplate.Interpreter = "latex";
s.DataTipTemplate.DataTipRows(1).Label = "Ch: "; s.DataTipTemplate.DataTipRows(1).Label = "Ch: ";
s.DataTipTemplate.DataTipRows(1).Value = repmat(ch,size(ber)); s.DataTipTemplate.DataTipRows(1).Value = repmat(ch,size(ber));
s.DataTipTemplate.DataTipRows(1); s.DataTipTemplate.DataTipRows(1);
s.DataTipTemplate.DataTipRows(2) = []; s.DataTipTemplate.DataTipRows(2) = [];
else else
if string(plotJob.dataStatArg) == "Lineplot with quartiles" if string(plotJob.dataStatArg) == "Lineplot with quartiles"
[hl,hp] = boundedline(xAxis,ber(rlz,:),([(ber(rlz,:)-lowerq(rlz,:));upperq(rlz,:)-ber(rlz,:)]'),'-o','alpha','Color',col,'transparency', 0.06,'linewidth',0.7); [hl,hp] = boundedline(xAxis,ber(rlz,:),([(ber(rlz,:)-lowerq(rlz,:));upperq(rlz,:)-ber(rlz,:)]'),'-o','alpha','Color',col,'transparency', 0.06,'linewidth',0.7);
hl.MarkerFaceColor = col; hl.MarkerFaceColor = col;
hl.MarkerSize = 2; hl.MarkerSize = 2;
set(hp,'HandleVisibility','off'); set(hp,'HandleVisibility','off');
%hp.LineWidth = 1.2; %hp.LineWidth = 1.2;
ho = outlinebounds(hl,hp); ho = outlinebounds(hl,hp);
set(ho, 'linestyle', ':', 'color', col,'Linewidth',0.6); set(ho, 'linestyle', ':', 'color', col,'Linewidth',0.6);
set(ho,'HandleVisibility','off'); set(ho,'HandleVisibility','off');
% errorbar(xAxis,ber(rlz,:),ber(rlz,:)-lowerq(rlz,:),upperq(rlz,:)-ber(rlz,:),'-o','Color',col,'linewidth',0.7); % errorbar(xAxis,ber(rlz,:),ber(rlz,:)-lowerq(rlz,:),upperq(rlz,:)-ber(rlz,:),'-o','Color',col,'linewidth',0.7);
else else
s = plot(xAxis,ber(rlz,:),linestyle,'Marker',markerstyle,'MarkerFaceColor',col,'MarkerSize',markersz,'LineWidth',linew,'Color',col,'Parent', AxesMain,'DisplayName',[plotJob.displayname]); s = plot(xAxis,ber(rlz,:),linestyle,'Marker',markerstyle,'MarkerFaceColor',col,'MarkerSize',markersz,'LineWidth',linew,'Color',col,'Parent', AxesMain,'DisplayName',[plotJob.displayname]);
s.DataTipTemplate.Interpreter = "latex"; s.DataTipTemplate.Interpreter = "latex";
s.DataTipTemplate.DataTipRows(1).Label = "Ch: "; s.DataTipTemplate.DataTipRows(1).Label = "Ch: ";
s.DataTipTemplate.DataTipRows(1).Value = repmat(string(ch),size(ber)); s.DataTipTemplate.DataTipRows(1).Value = repmat(string(ch),size(ber));
s.DataTipTemplate.DataTipRows(1) s.DataTipTemplate.DataTipRows(1)
s.DataTipTemplate.DataTipRows(2) = []; s.DataTipTemplate.DataTipRows(2) = [];
end end
end end
end end
end end
% Draw FEC Threshold Line % Draw FEC Threshold Line
%get x data of first children: %get x data of first children:
%get all linear Values %get all linear Values
if 0 if 0
linear = wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,wh.parameter.p_out.values,0,0,499,"symmetric"); linear = wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,wh.parameter.p_out.values,0,0,499,"symmetric");
linear = mean(linear,2); linear = mean(linear,2);
lincurve = findall(AxesMain, 'Type', 'line','DisplayName','Linear Baseline'); lincurve = findall(AxesMain, 'Type', 'line','DisplayName','Linear Baseline');
% %
if isempty(lincurve) if isempty(lincurve)
xdata = AxesMain.Children(1).XData; xdata = AxesMain.Children(1).XData;
hdfec = 3.8e-3.*ones(size(xdata)); hdfec = 3.8e-3.*ones(size(xdata));
plot(xdata,linear,'-','Marker',"o",'MarkerSize',3,'LineWidth',4,'Color',[0.6400 0.6400 0.6400],'MarkerFaceColor',[0.6400 0.6400 0.6400],'Parent', AxesMain,'DisplayName','Linear Baseline'); plot(xdata,linear,'-','Marker',"o",'MarkerSize',3,'LineWidth',4,'Color',[0.6400 0.6400 0.6400],'MarkerFaceColor',[0.6400 0.6400 0.6400],'Parent', AxesMain,'DisplayName','Linear Baseline');
%h = get(gca,'Children'); %h = get(gca,'Children');
%set(gca,'Children',[h(2) h(1)]) %set(gca,'Children',[h(2) h(1)])
end end
end end
feccurve = findall(AxesMain, 'Type', 'line','DisplayName','FEC $3.8*10^{-3}$'); feccurve = findall(AxesMain, 'Type', 'line','DisplayName','FEC $3.8*10^{-3}$');
% %
if isempty(feccurve) if isempty(feccurve)
xdata = AxesMain.Children(1).XData; xdata = AxesMain.Children(1).XData;
hdfec = 3.8e-3.*ones(size(xdata)); hdfec = 3.8e-3.*ones(size(xdata));
plot(xdata,hdfec,'--','MarkerSize',4,'Color','black','MarkerFaceColor','black','LineWidth',1,'Parent', AxesMain,'DisplayName','FEC $3.8*10^{-3}$','HandleVisibility','off'); plot(xdata,hdfec,'--','MarkerSize',4,'Color','black','MarkerFaceColor','black','LineWidth',1,'Parent', AxesMain,'DisplayName','FEC $3.8*10^{-3}$','HandleVisibility','off');
%h = get(gca,'Children'); %h = get(gca,'Children');
%set(gca,'Children',[h(2) h(1)]) %set(gca,'Children',[h(2) h(1)])
end end
% Figure Settings % Figure Settings
%title(AxesMain,plotJob.title,"Interpreter","none"); %title(AxesMain,plotJob.title,"Interpreter","none");
xlabel(AxesMain,plotJob.xAxisLabel,"Interpreter","latex"); xlabel(AxesMain,plotJob.xAxisLabel,"Interpreter","latex");
ylabel(AxesMain,plotJob.yAxisLabel,"Interpreter","latex"); ylabel(AxesMain,plotJob.yAxisLabel,"Interpreter","latex");
set(AxesMain,'yscale','log'); set(AxesMain,'yscale','log');
grid(AxesMain,'on'); grid(AxesMain,'on');
grid(AxesMain,'minor'); grid(AxesMain,'minor');
grid minor grid minor
%legend(AxesMain); %legend(AxesMain);
fontsize(AxesMain,8,"points") fontsize(AxesMain,8,"points")
% fontname(AxesMain,"Arial") % fontname(AxesMain,"Arial")
% fig.Position = plotJob.Position; % fig.Position = plotJob.Position;
% fig.Units = "centimeters"; % fig.Units = "centimeters";
% fig.Position = [2 2 8.5 7]; % fig.Position = [2 2 8.5 7];
set(AxesMain,'TickLabelInterpreter','latex') set(AxesMain,'TickLabelInterpreter','latex')
set(AxesMain.Legend,'Interpreter','latex') set(AxesMain.Legend,'Interpreter','latex')
% set(gcf,'Units','centimeters') % set(gcf,'Units','centimeters')
% set(gcf,'Position',[2 2 9 4.5]) % set(gcf,'Position',[2 2 9 4.5])
ylim([1e-5,0.3]); ylim([1e-5,0.3]);
xlim([-10,-4]); xlim([-10,-4]);
% annotation('textbox', [0.125, 0.32, 0.1, 0.1], 'String', "FEC 3.8e-3","LineStyle","none","FontSize",8,"FontUnits","points") % annotation('textbox', [0.125, 0.32, 0.1, 0.1], 'String', "FEC 3.8e-3","LineStyle","none","FontSize",8,"FontUnits","points")
hold off hold off
end end
function vec = removeZeros(vec) function vec = removeZeros(vec)
% Find rows that contain only zeros % Find rows that contain only zeros
rows_to_remove = all(vec == 0, 2); rows_to_remove = all(vec == 0, 2);
% Remove rows with only zeros % Remove rows with only zeros
vec(rows_to_remove, :) = []; vec(rows_to_remove, :) = [];
end end

View File

@@ -1,151 +1,151 @@
function plotHistogram(wh,plotJob) function plotHistogram(wh,plotJob)
fig = findall(groot, 'Type', 'figure', 'Name', plotJob.figName); fig = findall(groot, 'Type', 'figure', 'Name', plotJob.figName);
if isvalid(fig) if isvalid(fig)
figure(fig) figure(fig)
fig = get(fig); fig = get(fig);
AxesMain = fig.CurrentAxes; AxesMain = fig.CurrentAxes;
hold on hold on
else else
fig = figure('name',char(plotJob.figName)); fig = figure('name',char(plotJob.figName));
AxesMain = gca; AxesMain = gca;
hold on hold on
end end
col = plotJob.color; col = plotJob.color;
% we want to fetch all realizations % we want to fetch all realizations
realization = wh.parameter.realization.values(1:end); realization = wh.parameter.realization.values(1:end);
% get all xAxis values % get all xAxis values
xAxis = wh.parameter.p_out.values; xAxis = wh.parameter.p_out.values;
% Fetch Data from Warehouse % Fetch Data from Warehouse
for xl = 1:numel(xAxis) for xl = 1:numel(xAxis)
p_out = xAxis(xl); p_out = xAxis(xl);
if string(plotJob.dataStatArg) == "Worst" if string(plotJob.dataStatArg) == "Worst"
ber(xl) = max(wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,string(plotJob.channelplan),string(plotJob.dsp)),[],'all'); ber(xl) = max(wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,string(plotJob.channelplan),string(plotJob.dsp)),[],'all');
linew = 2.0; linew = 2.0;
markersz = 3; markersz = 3;
linestyle = '-'; linestyle = '-';
elseif string(plotJob.dataStatArg) == "AVG" elseif string(plotJob.dataStatArg) == "AVG"
ber(xl) = mean(wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,string(plotJob.channelplan),string(plotJob.dsp)),'all'); ber(xl) = mean(wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,string(plotJob.channelplan),string(plotJob.dsp)),'all');
linew = 2.0; linew = 2.0;
markersz = 3; markersz = 3;
linestyle = ':'; linestyle = ':';
elseif string(plotJob.dataStatArg) == "Best" elseif string(plotJob.dataStatArg) == "Best"
ber(xl) = min(wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,string(plotJob.channelplan),string(plotJob.dsp)),[],'all'); ber(xl) = min(wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,string(plotJob.channelplan),string(plotJob.dsp)),[],'all');
linew = 2.0; linew = 2.0;
markersz = 3; markersz = 3;
linestyle = ':'; linestyle = ':';
elseif string(plotJob.dataStatArg) == "All Channels; mean(PMD Realizations)" elseif string(plotJob.dataStatArg) == "All Channels; mean(PMD Realizations)"
tmp = wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,string(plotJob.channelplan),string(plotJob.dsp)); tmp = wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,string(plotJob.channelplan),string(plotJob.dsp));
if numel(tmp(tmp==0)) ~= 0 if numel(tmp(tmp==0)) ~= 0
disp('Removed all zero values!'); disp('Removed all zero values!');
tmp(tmp==0) = NaN; tmp(tmp==0) = NaN;
end end
ber(:,xl) = mean(tmp,1,"omitnan").'; ber(:,xl) = mean(tmp,1,"omitnan").';
linew = 0.7; linew = 0.7;
markersz = 2; markersz = 2;
linestyle = '-'; linestyle = '-';
elseif string(plotJob.dataStatArg) == "All Channels ;All PMD Realizations" elseif string(plotJob.dataStatArg) == "All Channels ;All PMD Realizations"
tmp = reshape(wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,string(plotJob.channelplan),string(plotJob.dsp)).',[],1); tmp = reshape(wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,string(plotJob.channelplan),string(plotJob.dsp)).',[],1);
ber(1:size(tmp,1),xl) = tmp; ber(1:size(tmp,1),xl) = tmp;
linew = 0.3; linew = 0.3;
markersz = 2; markersz = 2;
linestyle = ':'; linestyle = ':';
end end
end end
disp('Removed all zero values!'); disp('Removed all zero values!');
ber(ber==0) = NaN; ber(ber==0) = NaN;
if ~anynan(ber) if ~anynan(ber)
[xAxis,ber] = interpCurve(xAxis, ber); [xAxis,ber] = interpCurve(xAxis, ber);
end end
% plot FEC Crossing as histogram % plot FEC Crossing as histogram
hdfec = 3.8e-3.*ones(size(xAxis)); hdfec = 3.8e-3.*ones(size(xAxis));
S = []; S = [];
for i = 1:size(ber,1) for i = 1:size(ber,1)
a = InterX([hdfec;xAxis],[ber(i,:);xAxis]); a = InterX([hdfec;xAxis],[ber(i,:);xAxis]);
if ~isempty(a) if ~isempty(a)
S(:,i) = a; S(:,i) = a;
end end
end end
%% SUB 1 %% SUB 1
AxesMain = subplot(2,1,1); AxesMain = subplot(2,1,1);
hold on hold on
if ~isempty(S) if ~isempty(S)
histogram(S(end,:),300,'Normalization','probability','FaceColor',col,'EdgeColor',col,'Parent',AxesMain,'DisplayName',[plotJob.dataStatArg,' Ch.: ', plotJob.displayname],'FaceAlpha',0.4,'EdgeAlpha',0.4); histogram(S(end,:),300,'Normalization','probability','FaceColor',col,'EdgeColor',col,'Parent',AxesMain,'DisplayName',[plotJob.dataStatArg,' Ch.: ', plotJob.displayname],'FaceAlpha',0.4,'EdgeAlpha',0.4);
end end
xlim([-3 ,9 ]); xlim([-3 ,9 ]);
ylim([0 .10]); ylim([0 .10]);
% Figure Settings % Figure Settings
title(AxesMain,['$P_{in}:$ ',num2str(plotJob.p_in-9), 'dBm; L : ', num2str(plotJob.l),'Km'],'Interpreter','latex'); title(AxesMain,['$P_{in}:$ ',num2str(plotJob.p_in-9), 'dBm; L : ', num2str(plotJob.l),'Km'],'Interpreter','latex');
xlabel(AxesMain,plotJob.xAxisLabel,'Interpreter','latex'); xlabel(AxesMain,plotJob.xAxisLabel,'Interpreter','latex');
ylabel('PDF') ylabel('PDF')
grid(AxesMain,'on'); grid(AxesMain,'on');
grid(AxesMain,'minor'); grid(AxesMain,'minor');
%legend(AxesMain,'Interpreter','latex'); %legend(AxesMain,'Interpreter','latex');
fontsize(AxesMain,24,"pixels") fontsize(AxesMain,24,"pixels")
hold off hold off
%% SUB 2 %% SUB 2
AxesMain = subplot(2,1,2); AxesMain = subplot(2,1,2);
if ~isempty(S) if ~isempty(S)
hold on hold on
[f1,x1]=ecdf(S(end,:)); [f1,x1]=ecdf(S(end,:));
plot(x1,f1,'r','LineWidth',3, 'Color',col,'DisplayName',[plotJob.dataStatArg,' Ch.: ', plotJob.displayname]); plot(x1,f1,'r','LineWidth',3, 'Color',col,'DisplayName',[plotJob.dataStatArg,' Ch.: ', plotJob.displayname]);
end end
xlim([-3 ,9 ]); xlim([-3 ,9 ]);
ylim([0 1]); ylim([0 1]);
% Figure Settings % Figure Settings
title(AxesMain,['$P_{in}:$ ',num2str(plotJob.p_in-9), 'dBm; L : ', num2str(plotJob.l),'Km'],'Interpreter','latex'); title(AxesMain,['$P_{in}:$ ',num2str(plotJob.p_in-9), 'dBm; L : ', num2str(plotJob.l),'Km'],'Interpreter','latex');
xlabel(AxesMain,plotJob.xAxisLabel,'Interpreter','latex'); xlabel(AxesMain,plotJob.xAxisLabel,'Interpreter','latex');
ylabel('CDF') ylabel('CDF')
grid(AxesMain,'on'); grid(AxesMain,'on');
grid(AxesMain,'minor'); grid(AxesMain,'minor');
fontsize(AxesMain,24,"pixels") fontsize(AxesMain,24,"pixels")
%legend(AxesMain,'Interpreter','latex'); %legend(AxesMain,'Interpreter','latex');
fig.Position = plotJob.Position; fig.Position = plotJob.Position;
hold off hold off
end end

View File

@@ -1,206 +1,206 @@
function plotViolin(wh,plotJob) function plotViolin(wh,plotJob)
fig = findall(groot, 'Type', 'figure', 'Name', plotJob.figName); fig = findall(groot, 'Type', 'figure', 'Name', plotJob.figName);
if isvalid(fig) if isvalid(fig)
figure(fig) figure(fig)
fig = get(fig); fig = get(fig);
AxesMain = fig.CurrentAxes; AxesMain = fig.CurrentAxes;
hold on hold on
else else
fig = figure('name',char(plotJob.figName)); fig = figure('name',char(plotJob.figName));
AxesMain = gca; AxesMain = gca;
hold on hold on
end end
%% Violin %% Violin
col = plotJob.color; col = plotJob.color;
% we want to fetch all realizations % we want to fetch all realizations
if plotJob.pmd == 0 if plotJob.pmd == 0
realization = 1; realization = 1;
else else
realization = wh.parameter.realization.values(1:end); realization = wh.parameter.realization.values(1:end);
end end
%realization = 0:8; %realization = 0:8;
% get all xAxis values % get all xAxis values
xAxis = wh.parameter.p_out.values; xAxis = wh.parameter.p_out.values;
% ber = NaN(500,16,10); % ber = NaN(500,16,10);
% zdw = NaN(500,1,10); % zdw = NaN(500,1,10);
%get BER values for query %get BER values for query
for xl = 1:numel(xAxis) for xl = 1:numel(xAxis)
p_out = xAxis(xl); p_out = xAxis(xl);
curber = wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.ch,1310,plotJob.channelspacing,plotJob.randzdw); curber = wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.ch,1310,plotJob.channelspacing,plotJob.randzdw);
curber= removeZeros(curber); curber= removeZeros(curber);
ber(1:size(curber,1),1:size(curber,2),xl) = curber; ber(1:size(curber,1),1:size(curber,2),xl) = curber;
end end
% to remove outliers set the percentile range % to remove outliers set the percentile range
% a = squeeze(mean(ber,2)); % a = squeeze(mean(ber,2));
% out = isoutlier(mean(a,2),"percentiles",[0 100]); % out = isoutlier(mean(a,2),"percentiles",[0 100]);
% ber = ber(~out,:,:); % ber = ber(~out,:,:);
% disp(sum(out)); % disp(sum(out));
hdfec = 3.8e-3.*ones(size(xAxis)); hdfec = 3.8e-3.*ones(size(xAxis));
S = []; S = [];
wavelength={}; wavelength={};
S = []; S = [];
S_chann = []; S_chann = [];
wl = calcWavelengthPlan(plotJob.ch,plotJob.channelspacing,1310); wl = calcWavelengthPlan(plotJob.ch,plotJob.channelspacing,1310);
%get fec thresholds %get fec thresholds
% [C,ia,ib] =intersect(linx,xAxis); % [C,ia,ib] =intersect(linx,xAxis);
% linear = squeeze(linear); % linear = squeeze(linear);
%ber(ber==0) = NaN; %ber(ber==0) = NaN;
S_chann_no_crossing = zeros(1,plotJob.ch); S_chann_no_crossing = zeros(1,plotJob.ch);
for chann = 1:size(ber,2) for chann = 1:size(ber,2)
for realiz = 1:size(ber,1) for realiz = 1:size(ber,1)
ber_series = squeeze(ber(realiz,chann,:)).'; ber_series = squeeze(ber(realiz,chann,:)).';
if mean(ber_series) > 0.1 if mean(ber_series) > 0.1
continue continue
end end
a = InterX([hdfec(:)';xAxis],[ber_series;xAxis]); a = InterX([hdfec(:)';xAxis],[ber_series;xAxis]);
if ~isempty(a) if ~isempty(a)
S_chann(realiz,chann) = a(2); S_chann(realiz,chann) = a(2);
% if a(2) > -7 && string(plotJob.pol) == "copolarized" % if a(2) > -7 && string(plotJob.pol) == "copolarized"
% continue % continue
% end % end
S(end+1) = a(2); S(end+1) = a(2);
wavelength{end+1} = num2str(wl(chann)); wavelength{end+1} = num2str(wl(chann));
else else
S(end+1) = 0; S(end+1) = 0;
wavelength{end+1} = num2str(wl(chann)); wavelength{end+1} = num2str(wl(chann));
S_chann_no_crossing(realiz,chann) = 1; S_chann_no_crossing(realiz,chann) = 1;
S_chann(realiz,chann) = -1; S_chann(realiz,chann) = -1;
end end
end end
end end
threshold = -6; threshold = -6;
FEC_crossed = sum(S_chann < threshold & ~isnan(S_chann),1); FEC_crossed = sum(S_chann < threshold & ~isnan(S_chann),1);
FEC_not_crossed = sum(S_chann >= threshold & ~isnan(S_chann),1); FEC_not_crossed = sum(S_chann >= threshold & ~isnan(S_chann),1);
failure_rate = FEC_not_crossed ./ (FEC_crossed + FEC_not_crossed) ; failure_rate = FEC_not_crossed ./ (FEC_crossed + FEC_not_crossed) ;
S_chann(S_chann==0) = NaN; S_chann(S_chann==0) = NaN;
total_avg = mean(S_chann,"all","omitnan"); total_avg = mean(S_chann,"all","omitnan");
%figure(2024) %figure(2024)
%C = flip(cbrewer2('Spectral',8)); %C = flip(cbrewer2('Spectral',8));
if numel(S) <= numel(wl) if numel(S) <= numel(wl)
vs = scatter(1:numel(S),S,50,'o','MarkerEdgeColor','black','MarkerFaceColor',plotJob.color,'LineWidth',1,'HandleVisibility','off'); vs = scatter(1:numel(S),S,50,'o','MarkerEdgeColor','black','MarkerFaceColor',plotJob.color,'LineWidth',1,'HandleVisibility','off');
%vs = scatter(1,mean(S),50,'o','MarkerEdgeColor','black','MarkerFaceColor',plotJob.color,'LineWidth',1); %vs = scatter(1,mean(S),50,'o','MarkerEdgeColor','black','MarkerFaceColor',plotJob.color,'LineWidth',1);
else else
vs = violinplot(S,wavelength,... vs = violinplot(S,wavelength,...
'ViolinColor',plotJob.color,... 'ViolinColor',plotJob.color,...
'ViolinAlpha',0.1,... 'ViolinAlpha',0.1,...
'MarkerSize',1,... 'MarkerSize',1,...
'ShowMedian',false,... 'ShowMedian',false,...
'EdgeColor',plotJob.color,... 'EdgeColor',plotJob.color,...
'ShowWhiskers',false,... 'ShowWhiskers',false,...
'ShowData',false,... 'ShowData',false,...
'ShowBox',false,... 'ShowBox',false,...
'Bandwidth',0.051 ... 'Bandwidth',0.051 ...
); );
hold on hold on
partly_failed = boolean(ceil(failure_rate)); partly_failed = boolean(ceil(failure_rate));
avg = mean(S_chann,1,"omitnan"); avg = mean(S_chann,1,"omitnan");
notfailed = ~partly_failed .* avg; notfailed = ~partly_failed .* avg;
notfailed(notfailed==0) = NaN; notfailed(notfailed==0) = NaN;
scatter(1:size(S_chann,2),notfailed,10,'Marker','x','MarkerEdgeColor','black','MarkerFaceColor',plotJob.color,'LineWidth',0.5,'HandleVisibility','off'); scatter(1:size(S_chann,2),notfailed,10,'Marker','x','MarkerEdgeColor','black','MarkerFaceColor',plotJob.color,'LineWidth',0.5,'HandleVisibility','off');
hold on hold on
partly_failed = partly_failed.*avg; partly_failed = partly_failed.*avg;
partly_failed(partly_failed==0) = NaN; partly_failed(partly_failed==0) = NaN;
s=scatter(1:numel(failure_rate),partly_failed,10,'Marker','x','LineWidth',0.5,'HandleVisibility','off','MarkerEdgeColor','red'); s=scatter(1:numel(failure_rate),partly_failed,10,'Marker','x','LineWidth',0.5,'HandleVisibility','off','MarkerEdgeColor','red');
s.DataTipTemplate.Interpreter = "latex"; s.DataTipTemplate.Interpreter = "latex";
s.DataTipTemplate.DataTipRows(1).Label = "Fail Rate: "; s.DataTipTemplate.DataTipRows(1).Label = "Fail Rate: ";
s.DataTipTemplate.DataTipRows(1).Value = failure_rate; s.DataTipTemplate.DataTipRows(1).Value = failure_rate;
s.DataTipTemplate.DataTipRows(2) = []; s.DataTipTemplate.DataTipRows(2) = [];
hold off hold off
end end
% ax = gca; % ax = gca;
% ax.XTicks % ax.XTicks
hold on hold on
yline(total_avg,'LineWidth',1,'LineStyle','--','DisplayName','System Avg.') yline(total_avg,'LineWidth',1,'LineStyle','--','DisplayName','System Avg.')
fig.Position = plotJob.Position; fig.Position = plotJob.Position;
xticklabels(1:16); xticklabels(1:16);
ylabel('Penalty in dB'); ylabel('Penalty in dB');
xlabel('Channel Number'); xlabel('Channel Number');
ylim([-9.3,-3]); ylim([-9.3,-3]);
xlim([0,plotJob.ch+1]); xlim([0,plotJob.ch+1]);
% grid minor; % grid minor;
set(gca, 'color', 'none'); set(gca, 'color', 'none');
legend = []; legend = [];
fontsize(AxesMain,8,"points") fontsize(AxesMain,8,"points")
fig.Position = plotJob.Position; fig.Position = plotJob.Position;
fig.Units = "centimeters"; fig.Units = "centimeters";
fig.Position = [2 2 8.5 7]; fig.Position = [2 2 8.5 7];
set(AxesMain,'TickLabelInterpreter','latex') set(AxesMain,'TickLabelInterpreter','latex')
set(AxesMain.Legend,'Interpreter','latex') set(AxesMain.Legend,'Interpreter','latex')
if 0 if 0
ber_sorted = sort(S); ber_sorted = sort(S);
z1 = []; z1 = [];
penalty = mean(ber_sorted):0.01:mean(ber_sorted)+2; penalty = mean(ber_sorted):0.01:mean(ber_sorted)+2;
for i = 1:length(penalty) for i = 1:length(penalty)
l = penalty(i); l = penalty(i);
if i == 1 if i == 1
z1 = [z1 sum(ber_sorted(1,:)<l ) / length(ber_sorted) ]; z1 = [z1 sum(ber_sorted(1,:)<l ) / length(ber_sorted) ];
else else
z1 = [z1 sum(ber_sorted(1,:)<l & ber_sorted(1,:)>l-0.01) / length(ber_sorted) ]; z1 = [z1 sum(ber_sorted(1,:)<l & ber_sorted(1,:)>l-0.01) / length(ber_sorted) ];
end end
end end
penalty_higherthan = 0.5; penalty_higherthan = 0.5;
probability = sum(z1(find(penalty>mean(ber_sorted)+penalty_higherthan))); probability = sum(z1(find(penalty>mean(ber_sorted)+penalty_higherthan)));
disp(['A penalty of more than 0.5 dB has a probability of: ', num2str(probability)]); disp(['A penalty of more than 0.5 dB has a probability of: ', num2str(probability)]);
end end
end end
function vec = removeZeros(vec) function vec = removeZeros(vec)
% Find rows that contain only zeros % Find rows that contain only zeros
rows_to_remove = all(vec == 0, 2); rows_to_remove = all(vec == 0, 2);
% Remove rows with only zeros % Remove rows with only zeros
vec(rows_to_remove, :) = []; vec(rows_to_remove, :) = [];
end end

View File

@@ -1,58 +1,58 @@
%automate plots %automate plots
% [file, path] = uigetfile("C:\Users\Silas\Documents\MATLAB\Raw_Cluster_Simulations\session_januar24\wh_complete_at_1310.mat"); % [file, path] = uigetfile("C:\Users\Silas\Documents\MATLAB\Raw_Cluster_Simulations\session_januar24\wh_complete_at_1310.mat");
% wh = load([path filesep file]); % wh = load([path filesep file]);
% wh = wh.wh; % wh = wh.wh;
plotJob = struct(); plotJob = struct();
plotJob.l = 10; plotJob.l = 10;
plotJob.ch = 16; plotJob.ch = 16;
plotJob.d = 3; plotJob.d = 3;
plotJob.sgm = 1; plotJob.sgm = 1;
plotJob.pol = "copolarized"; plotJob.pol = "copolarized";
plotJob.p_in = 3; plotJob.p_in = 3;
plotJob.gamma = 0.0023; plotJob.gamma = 0.0023;
plotJob.pmd = 0.1; plotJob.pmd = 0.1;
plotJob.channelspacing = 400e9; plotJob.channelspacing = 400e9;
plotJob.randzdw = 0; plotJob.randzdw = 0;
ber_per_chann = []; ber_per_chann = [];
% get all xAxis values % get all xAxis values
xAxis = wh.parameter.p_out.values; xAxis = wh.parameter.p_out.values;
realization = wh.parameter.realization.values(1:end); realization = wh.parameter.realization.values(1:end);
% Fetch Data from Warehouse % Fetch Data from Warehouse
for xl = 1:numel(xAxis) for xl = 1:numel(xAxis)
p_out = xAxis(xl); p_out = xAxis(xl);
raw_fetch = wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.ch,1310,plotJob.channelspacing,plotJob.randzdw).'; raw_fetch = wh.getStoValue('ber',plotJob.l,plotJob.d,plotJob.sgm,string(plotJob.pol),plotJob.p_in,p_out,plotJob.pmd,plotJob.gamma,realization,plotJob.ch,1310,plotJob.channelspacing,plotJob.randzdw).';
ber_per_chann(:,:,xl) = raw_fetch; ber_per_chann(:,:,xl) = raw_fetch;
end end
%% %%
figure(2023); figure(2023);
for ch = [1,floor(plotJob.ch/2),ceil(plotJob.ch/2)+1,plotJob.ch] %1:15:size(ber_per_chann,1) for ch = [1,floor(plotJob.ch/2),ceil(plotJob.ch/2)+1,plotJob.ch] %1:15:size(ber_per_chann,1)
for p = 5%1:size(ber_per_chann,3) for p = 5%1:size(ber_per_chann,3)
% Extract data for the current row % Extract data for the current row
row_data = squeeze(ber_per_chann(ch,:,p)); row_data = squeeze(ber_per_chann(ch,:,p));
[f, xi] = ksdensity(row_data); [f, xi] = ksdensity(row_data);
% Identify the peak point % Identify the peak point
[max_density, max_index] = max(f); [max_density, max_index] = max(f);
peak_x = xi(max_index); peak_x = xi(max_index);
end end
% Create a histogram plot for the current row with a unique color % Create a histogram plot for the current row with a unique color
plot(xi, f, 'LineWidth', 2, 'DisplayName', ['Ch. ', num2str(ch)],'LineStyle','--'); plot(xi, f, 'LineWidth', 2, 'DisplayName', ['Ch. ', num2str(ch)],'LineStyle','--');
%histogram(row_data,100, 'DisplayName', ['Channel ', num2str(ch)], 'EdgeColor', 'none'); %histogram(row_data,100, 'DisplayName', ['Channel ', num2str(ch)], 'EdgeColor', 'none');
hold on; % Hold the plot for the next iteration hold on; % Hold the plot for the next iteration
text(peak_x, max_density, ['Ch ', num2str(ch)], 'VerticalAlignment', 'bottom', 'HorizontalAlignment', 'left'); text(peak_x, max_density, ['Ch ', num2str(ch)], 'VerticalAlignment', 'bottom', 'HorizontalAlignment', 'left');
end end
legend show legend show
%% %%

View File

@@ -8,6 +8,7 @@ classdef equalizer_structure < int32
% db_precoded (3) % db_precoded (3)
vnle_db_mlse (4) vnle_db_mlse (4)
db_encoded (5) db_encoded (5)
ml_mlse (6)
end end
end end

View File

@@ -13,14 +13,13 @@ arguments
end end
try try
% Initialize output structures % Initialize output structures
output.ffe_package = {}; output.ffe_package = {};
output.mlse_package = {}; output.mlse_package = {};
output.vnle_package = {}; output.vnle_package = {};
output.dbtgt_package = {}; output.dbtgt_package = {};
output.dbenc_package = {}; output.dbenc_package = {};
output.mlmlse_package = {};
if options.mode == "load_run_id" || options.append_to_db if options.mode == "load_run_id" || options.append_to_db
% Initialize database connection % Initialize database connection
@@ -98,9 +97,10 @@ try
use_ffe = 0; use_ffe = 0;
use_dfe = 0; use_dfe = 0;
use_vnle_mlse = 1; use_vnle_mlse = 0;
use_dbtgt = 0; use_dbtgt = 0;
use_dbenc = 0; use_dbenc = 0;
use_ml_mlse = 1;
addProcessingResultToDatabase = 0; addProcessingResultToDatabase = 0;
@@ -130,7 +130,7 @@ try
mlse_ = MLSE("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels); mlse_ = MLSE("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,"adaption_technique","lms"); 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,"adaption_technique","lms");
eq_post =FFE("epochs_tr",5,"epochs_dd",2,"len_tr",2^13,"mu_dd",mu_dd,"mu_tr",mu_tr,"order",25,"sps",2,"decide",0, "adaption",adaption_method(adaption),"dd_mode",use_dd_mode); eq_post = FFE("epochs_tr",5,"epochs_dd",2,"len_tr",2^13,"mu_dd",mu_dd,"mu_tr",mu_tr,"order",25,"sps",2,"decide",0, "adaption",adaption_method(adaption),"dd_mode",use_dd_mode);
% Duobinary signaling (db encoded) % Duobinary signaling (db encoded)
mlse_db_enc = MLSE("DIR", [1,1], "duobinary_output", 0, "M", M, "trellis_states", PAMmapper(M,0).levels); mlse_db_enc = MLSE("DIR", [1,1], "duobinary_output", 0, "M", M, "trellis_states", PAMmapper(M,0).levels);
eq_db_enc = EQ("Ne", ffe_order, "Nb", dfe_order, "training_length", len_tr, ... eq_db_enc = EQ("Ne", ffe_order, "Nb", dfe_order, "training_length", len_tr, ...
@@ -233,30 +233,25 @@ try
database.addProcessingResult(run_id, ffe_results.metrics, ffe_results.config); database.addProcessingResult(run_id, ffe_results.metrics, ffe_results.config);
end end
% pf_ncoeffs = 2; end
% 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); if use_ml_mlse
% % 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); %ML-based MLSE (L=2)
% mu_ml = 0.01; training_epochs = 250;
% [ffe_results, mlse_results] = vnle_postfilter_mlse(eq_, pf_, mlse_, M, Scpe_sig, Symbols, Tx_bits, ... ml_mlse_equalizer = ML_MLSE("epochs_tr",training_epochs,"epochs_dd",1, ...
% "precode_mode", duob_mode,... "len_tr",length(Scpe_sig),"mu_dd",mu_ml,"mu_tr",mu_ml,"order",11,"sps",2, ...
% 'showAnalysis', 0, ... "traceback_depth",128,"L",2,"delta",4,"adaptive_mu",0);
% "postFFE", [],...
% "eth_style_symbol_mapping", 0); [ml_mlse_results] = ml_mlse(ml_mlse_equalizer, M, Scpe_sig, Symbols, Tx_bits,"precode_mode",duob_mode);
% output.mlmlse_package{r} = ml_mlse_results;
% ffe_results.metrics.print;
% mlse_results.metrics.print; if options.append_to_db
% database.addProcessingResult(run_id, ml_mlse_results.metrics, ml_mlse_results.config);
% output.mlse_package{r} = mlse_results; end
% output.vnle_package{r} = ffe_results;
%
% if options.append_to_db
% database.addProcessingResult(run_id, mlse_results.metrics, mlse_results.config);
% database.addProcessingResult(run_id, ffe_results.metrics, ffe_results.config);
% end
end end
if use_dbtgt if use_dbtgt
@@ -292,6 +287,7 @@ try
if duob_mode == db_mode.db_encoded if duob_mode == db_mode.db_encoded
mlse_db_enc = MLSE_viterbi("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",0,"postFFE",[]); db_results = duobinary_signaling(eq_db_enc, mlse_db_enc, M, Scpe_sig, Symbols, Tx_bits, "precode_mode",duob_mode, "showAnalysis",0,"postFFE",[]);
output.dbenc_package{r} = db_results; output.dbenc_package{r} = db_results;
if options.append_to_db if options.append_to_db

View File

@@ -36,8 +36,9 @@ if ~isempty(options.postFFE)
end end
% Process through MLSE % Process through MLSE
% [mlse_signal] = mlse_.process(eq_signal); [mlse_signal] = mlse_.process(eq_signal);
[mlse_signal,~,GMI_MLSE] = mlse_.process(eq_signal,tx_symbols); % tx_symbols_ = Duobinary().decode(tx_symbols);
% [mlse_signal,~,GMI_MLSE] = mlse_.process(eq_signal,tx_symbols);
% Apply duobinary encoding and decoding % Apply duobinary encoding and decoding
mlse_signal = Duobinary().encode(mlse_signal); mlse_signal = Duobinary().encode(mlse_signal);

View File

@@ -0,0 +1,113 @@
function [ml_mlse_results] = ml_mlse(eq_, M, rx_signal, tx_symbols, tx_bits, options)
%
%
% Inputs:
% eq_ - Equalizer object
% M - Modulation order
% rx_signal - Received signal
% tx_symbols - Transmitted symbols
% tx_bits - Transmitted bits
% options - Optional parameters
%
% Outputs:
% ffe_results - Results from FFE processing
arguments
eq_
M
rx_signal
tx_symbols
tx_bits
options.precode_mode db_mode
options.eth_style_symbol_mapping = 0;
options.postFFE = [];
end
%% Process signals through equalizer
[eq_signal_hd,y_ref] = eq_.process(rx_signal,tx_symbols);
%% Calculate BER based on precoding mode
[bits, errors, ber, error_pos, errors_precoded, ber_precoded] = calculateBER(eq_signal_hd, tx_symbols, tx_bits, options.precode_mode, M, options.eth_style_symbol_mapping);
% Create FFE results structure
ml_mlse_results = struct();
try
eq_.e = [];
eq_.e2 = [];
eq_.e3 = [];
eq_.b = [];
eq_.b2 = [];
eq_.b3 = [];
end
ml_mlse_results.config = Equalizerstruct();
ml_mlse_results.config.eq = jsonencode(eq_);
ml_mlse_results.config.equalizer_structure = int32(equalizer_structure.ml_mlse);
ml_mlse_results.config.comment = 'function: ML-based MLSE';
ml_mlse_results.metrics = Metricstruct;
ml_mlse_results.metrics.result_id = NaN;
ml_mlse_results.metrics.run_id = NaN;
ml_mlse_results.metrics.eqParam_id = NaN;
ml_mlse_results.metrics.date_of_processing = datetime('now');
ml_mlse_results.metrics.BER = ber;
ml_mlse_results.metrics.numBits = bits;
ml_mlse_results.metrics.numBitErr = errors;
ml_mlse_results.metrics.BER_precoded = ber_precoded;
ml_mlse_results.metrics.numBitErr_precoded = errors_precoded;
ml_mlse_results.metrics.SNR = NaN;
ml_mlse_results.metrics.SNR_level = NaN;
ml_mlse_results.metrics.STD = NaN;
ml_mlse_results.metrics.STD_level = NaN;
ml_mlse_results.metrics.STDrx = NaN;
ml_mlse_results.metrics.STDrx_level = NaN;
ml_mlse_results.metrics.GMI = NaN;
ml_mlse_results.metrics.AIR = NaN;
ml_mlse_results.metrics.EVM = NaN;
ml_mlse_results.metrics.EVM_level = NaN;
ml_mlse_results.metrics.Alpha = NaN;
end
%% Helper Functions
function [bits, errors, ber, error_pos, errors_precoded, ber_precoded] = calculateBER(eq_signal_hd, tx_symbols, tx_bits, precode_mode, M, eth_style)
% Calculate BER based on precoding mode
mapper = PAMmapper(M, 0, "eth_style", eth_style);
switch precode_mode
case db_mode.no_db
% TX Data is not precoded
% A) Emulate diff precoding
eq_signal_hd_precoded = Duobinary().encode(eq_signal_hd, "M", M);
eq_signal_hd_precoded = Duobinary().decode(eq_signal_hd_precoded, "M", M);
tx_symbols_precoded = Duobinary().encode(tx_symbols);
tx_symbols_precoded = Duobinary().decode(tx_symbols_precoded);
tx_bits_precoded = mapper.demap(tx_symbols_precoded);
rx_bits = mapper.demap(eq_signal_hd_precoded);
[~, errors_precoded, ber_precoded, ~] = calc_ber(rx_bits.signal, tx_bits_precoded.signal, "skip_front", 30000, "skip_end", 150, "returnErrorLocation", 1);
% B) Just determine BER
rx_bits = mapper.demap(eq_signal_hd);
[bits, errors, ber, error_pos] = calc_ber(rx_bits.signal, tx_bits.signal, "skip_front", 30000, "skip_end", 150, "returnErrorLocation", 1);
case db_mode.db_precoded
% Data is precoded on TX side
% A) Decode at Rx if no DB targeting was applied
eq_signal_hd_decoded = Duobinary().encode(eq_signal_hd, "M", M);
eq_signal_hd_decoded = Duobinary().decode(eq_signal_hd_decoded, "M", M);
rx_bits_decoded = mapper.demap(eq_signal_hd_decoded);
[~, errors_precoded, ber_precoded, ~] = calc_ber(rx_bits_decoded.signal, tx_bits.signal, "skip_front", 30000, "skip_end", 150, "returnErrorLocation", 1);
% B) Omit the Coding by comparing with demapped TX symbol sequence
tx_bits_demapped = mapper.demap(tx_symbols);
rx_bits = mapper.demap(eq_signal_hd);
[bits, errors, ber, error_pos] = calc_ber(rx_bits.signal, tx_bits_demapped.signal, "skip_front", 30000, "skip_end", 150, "returnErrorLocation", 1);
end
end

View File

@@ -1,40 +0,0 @@
function [eq_, pf_, mlse_, mlse_db_, eq_post] = configureEqualizers(M, len_tr, vnle_order, dfe_order, mu_dc, mu_ffe, mu_dfe, pf_ncoeffs)
% CONFIGUREEQUALIZERS Creates and configures equalizer objects
%
% Inputs:
% M - PAM level
% len_tr - Training length
% vnle_order - Array with orders for VNLE [order1, order2, order3]
% dfe_order - Array with orders for DFE
% mu_dc - DC adaptation rate
% mu_ffe - Array with adaptation rates for FFE [mu1, mu2, mu3]
% mu_dfe - Adaptation rate for DFE
% pf_ncoeffs - Number of coefficients for postfilter
%
% Outputs:
% eq_ - Configured EQ object
% pf_ - Configured Postfilter object
% mlse_ - Configured MLSE_viterbi object
% mlse_db_ - Configured MLSE_viterbi object for duobinary
% eq_post - Configured FFE object for post-processing
% Configure main equalizer
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);
% Configure postfilter
pf_ = Postfilter("ncoeff", pf_ncoeffs, "useBurg", 1);
% Configure MLSE objects
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);
% Configure post-FFE
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);
end

View File

@@ -16,9 +16,9 @@ Scpe_sig = Scpe_sig.resample("fs_out", 2*fsym);
[Scpe_sig, ~] = Scpe_sig.tsynch("reference", Symbols, "fs_ref", fsym, "debug_plots", 0); [Scpe_sig, ~] = Scpe_sig.tsynch("reference", Symbols, "fs_ref", fsym, "debug_plots", 0);
% Apply Gaussian filter % Apply Gaussian filter
% Scpe_sig = Filter('filtdegree', 4, "f_cutoff", Symbols.fs.*0.6, ... Scpe_sig = Filter('filtdegree', 4, "f_cutoff", Symbols.fs.*0.6, ...
% "fs", Scpe_sig.fs, "filterType", filtertypes.gaussian, ... "fs", Scpe_sig.fs, "filterType", filtertypes.gaussian, ...
% "active", true).process(Scpe_sig); "active", true).process(Scpe_sig);
% Remove DC offset % Remove DC offset
Scpe_sig = Scpe_sig - mean(Scpe_sig.signal); Scpe_sig = Scpe_sig - mean(Scpe_sig.signal);

View File

@@ -209,6 +209,7 @@ wh = submit_options.wh;
wh.addValueToStorageByLinIdx(val.vnle_package, 'vnle_package', jobIndex); wh.addValueToStorageByLinIdx(val.vnle_package, 'vnle_package', jobIndex);
wh.addValueToStorageByLinIdx(val.dbtgt_package,'dbtgt_package',jobIndex); wh.addValueToStorageByLinIdx(val.dbtgt_package,'dbtgt_package',jobIndex);
wh.addValueToStorageByLinIdx(val.dbenc_package,'dbenc_package',jobIndex); wh.addValueToStorageByLinIdx(val.dbenc_package,'dbenc_package',jobIndex);
wh.addValueToStorageByLinIdx(val.mlmlse_package,'mlmlse_package',jobIndex);
end end
end end
function p = setupParallelPool(numWorkers, idleTimeout) function p = setupParallelPool(numWorkers, idleTimeout)

View File

@@ -1,43 +1,97 @@
function beautifyBERplot(options) function beautifyBERplot(options)
% BEAUTIFYBERPLOT Enhances BER-style plots for publication-quality figures.
% Supports automatic smoothing and trend-line overlay.
%
% Usage examples:
% beautifyBERplot; % default
% beautifyBERplot("polyfit",1); % add polynomial fit
% beautifyBERplot("polyfit",1,"fitmethod","pchip") % piecewise cubic fit
%
% Supported fitmethod options: 'polyfit', 'smoothingspline', 'loess', 'pchip'
arguments arguments
options.logscale = 1 options.logscale (1,1) logical = 1
options.polyfit (1,1) logical = 0
options.polyorder (1,1) double = 2
options.fitmethod (1,1) string = "polyfit" % choose fit type
end end
% BEAUTIFYBERPLOT Enhances a BER plot for publication-quality figures.
% Set line properties for all current plot lines % --- find all line objects in current axes
lines = findall(gca, 'Type', 'Line'); lines = findall(gca, 'Type', 'Line');
markers = {'o', 's', 'd', '^', 'v', '>', '<', 'p', 'h'}; % Define marker styles markers = {'o', 's', 'd', '^', 'v', '>', '<', 'p', 'h'};
num_markers = length(markers); num_markers = length(markers);
% --- style all lines consistently
for i = 1:length(lines)
lines(i).LineWidth = 1.1;
lines(i).LineStyle = '-';
if string(lines(i).Marker) == "none"
lines(i).Marker = markers{mod(i-1, num_markers) + 1};
end
lines(i).MarkerSize = 4;
lines(i).MarkerFaceColor = lines(i).Color;
end
% --- optional smoothing/fitting overlay
if options.polyfit
hold on
for i = 1:length(lines) for i = 1:length(lines)
lines(i).LineWidth = 1.3; % Thicker line width x = lines(i).XData;
lines(i).LineStyle = '-'; % Solid lines for simplicity y = lines(i).YData;
if string(lines(i).Marker) == "none" valid = isfinite(x) & isfinite(y);
lines(i).Marker = markers{mod(i-1, num_markers) + 1}; % Assign markers cyclically if sum(valid) < options.polyorder + 1
continue;
end end
lines(i).MarkerSize = 7; % Marker size
lines(i).MarkerFaceColor = lines(i).Color; % Use line color for marker face xf = linspace(min(x(valid)), max(x(valid)), 200);
lines(i).MarkerEdgeColor = 'white';
% ----- choose fitting method -----
switch lower(options.fitmethod)
case "polyfit"
p = polyfit(x(valid), y(valid), options.polyorder);
yf = polyval(p, xf);
case "smoothingspline"
try
f = fit(x(valid)', y(valid)', 'smoothingspline');
yf = feval(f, xf);
catch
yf = interp1(x(valid), y(valid), xf, 'pchip');
end
case "loess"
yf = smooth(x(valid), y(valid), 0.2, 'loess');
yf = interp1(x(valid), yf, xf, 'linear', 'extrap');
case "pchip"
yf = interp1(x(valid), y(valid), xf, 'pchip');
otherwise
warning('Unknown fitmethod "%s". Using polyfit.', options.fitmethod);
p = polyfit(x(valid), y(valid), options.polyorder);
yf = polyval(p, xf);
end
% --- lightened color for fit overlay
lightcol = lines(i).Color + 0.4 * (1 - lines(i).Color);
lightcol(lightcol > 1) = 1;
plot(xf, yf, '-', 'Color', lightcol, ...
'LineWidth', 0.7, 'Marker', 'none', ...
'HandleVisibility','off');
end end
hold off
% Change all text interpreters to LaTeX end
set(findall(gca, '-property', 'Interpreter'), 'Interpreter', 'latex');
% --- axis scaling and cosmetics
% Set figure background to white if options.logscale
set(gcf, 'Color', 'w'); set(gca, 'YScale', 'log');
end
% Set logarithmic scale for y-axis, but only if it makes sense. set(findall(gca, '-property', 'Interpreter'), 'Interpreter', 'latex');
% If this is not always desired, you could condition this on the presence of lines or data. set(gcf, 'Color', 'w');
if options.logscale set(gca, 'Box', 'on', 'LineWidth', 0.8);
set(gca, 'YScale', 'log'); grid on;
end set(gca, 'FontSize', 10, 'FontName', 'Times New Roman');
% Customize grid and box appearance
set(gca, 'Box', 'on', 'LineWidth', 0.8); % Thicker border
grid on;
% grid minor;
% Adjust font size and style for better readability
set(gca, 'FontSize', 10, 'FontName', 'Times New Roman');
end end

View File

@@ -20,7 +20,7 @@ fp.where('Runs', 'rop_attenuation','EQUALS', 0);
fields = db.getTableFieldNames('power_state_info'); fields = db.getTableFieldNames('power_state_info');
fields = [fields; db.getTableFieldNames('dashboard_ungrouped')]; fields = [fields; db.getTableFieldNames('dashboard_ungrouped_new')];
[dataTable,~] = db.queryDB(fp, fields); [dataTable,~] = db.queryDB(fp, fields);
eqstructures = unique(dataTable.equalizer_structure); eqstructures = unique(dataTable.equalizer_structure);

View File

@@ -41,7 +41,9 @@ plotdefs = struct( ...
'legendLocation' , 'best', ... 'legendLocation' , 'best', ...
'fecLineWidth' , 2.2, ... % thicker FEC limits 'fecLineWidth' , 2.2, ... % thicker FEC limits
'fecColor' , [0.25 0.25 0.25], ... 'fecColor' , [0.25 0.25 0.25], ...
'capSize' , 6 ... 'capSize' , 6, ...
'lineStyle_default' , '-', ...
'use_pre_emph_styling' , true ...
); );
cfg.plot = filldefaults(cfg.plot, plotdefs); cfg.plot = filldefaults(cfg.plot, plotdefs);
@@ -131,8 +133,23 @@ for gi = 1:nG
yu = yu(ord); ylo = ylo(ord); yhi = yhi(ord); yu = yu(ord); ylo = ylo(ord); yhi = yhi(ord);
% Styles % Styles
pre = logical(grpTbl.pre_emph(gi)); % Decide if we style by pre_emph
ls = tern(pre, cfg.plot.lineStyle_pre_emph_on, cfg.plot.lineStyle_pre_emph_off); canStyleByPre = cfg.plot.use_pre_emph_styling && ismember('pre_emph', T.Properties.VariableNames);
if canStyleByPre
if any(strcmp(group_by,'pre_emph'))
% pre_emph is an explicit grouping key -> take it from the group table
pre = logical(grpTbl.pre_emph(gi));
else
% pre_emph not grouped, but available in the rows -> infer from the members of this group
pre = logical(mode(T.pre_emph(G==gi)));
end
ls = tern(pre, cfg.plot.lineStyle_pre_emph_on, cfg.plot.lineStyle_pre_emph_off);
else
% no pre-emph styling use a single default style
ls = cfg.plot.lineStyle_default;
end
lbl = buildLabel(grpTbl(gi,:), group_by); lbl = buildLabel(grpTbl(gi,:), group_by);
% Main line (dark) % Main line (dark)

View File

@@ -1,6 +1,6 @@
% === SETTINGS === % === SETTINGS ===
dsp_options.append_to_db = 1; dsp_options.append_to_db = 1;
dsp_options.max_occurences = 15; dsp_options.max_occurences = 2;
experiment = "highspeed_2024"; experiment = "highspeed_2024";
dsp_options.mode = "load_run_id"; % 'simulate' & 'load_files' dsp_options.mode = "load_run_id"; % 'simulate' & 'load_files'
@@ -42,16 +42,16 @@ fp = QueryFilter();
% fp.where('Runs', 'run_id','EQUALS', 987); % fp.where('Runs', 'run_id','EQUALS', 987);
M = 4; M = 4;
fp.where('Runs', 'pam_level','EQUALS', M); fp.where('Runs', 'pam_level','EQUALS', M);
fp.where('Runs', 'bitrate','EQUALS', 420e9);%360,390 fp.where('Runs', 'bitrate','EQUALS', 300e9);%360,390
% fp.where('Runs', 'symbolrate','EQUALS', 162e9); % fp.where('Runs', 'symbolrate','EQUALS', 195e9);
fp.where('Runs', 'fiber_length','EQUALS', 2); % fp.where('Runs', 'fiber_length','EQUALS', 1);
fp.where('Runs', 'is_mpi','EQUALS', 0); fp.where('Runs', 'is_mpi','EQUALS', 0);
% fp.where('Runs', 'interference_path_length','EQUALS', 1000); % fp.where('Runs', 'interference_path_length','EQUALS', 1000);
% fp.where('Runs', 'loop_id','GREATER_THAN', 11); % fp.where('Runs', 'loop_id','GREATER_THAN', 11);
% fp.where('Runs', 'sir','EQUALS',18); % fp.where('Runs', 'sir','EQUALS',18);
fp.where('Runs', 'wavelength','EQUAL', 1310); fp.where('Runs', 'wavelength','EQUAL', 1310);
fp.where('Runs', 'db_mode','EQUALS', 0); fp.where('Runs', 'db_mode','EQUALS', 1);
fp.where('Runs', 'rop_attenuation','EQUAL', 0); % fp.where('Runs', 'rop_attenuation','EQUAL', 0);
% fp.where('Runs', 'power_pd_in','GREATER_THAN', 7); % fp.where('Runs', 'power_pd_in','GREATER_THAN', 7);
[dataTable,~] = db.queryDB(fp, db.getTableFieldNames('Runs')); [dataTable,~] = db.queryDB(fp, db.getTableFieldNames('Runs'));
@@ -66,15 +66,41 @@ wh.addStorage("mlse_package");
wh.addStorage("vnle_package"); wh.addStorage("vnle_package");
wh.addStorage("dbtgt_package"); wh.addStorage("dbtgt_package");
wh.addStorage("dbenc_package"); wh.addStorage("dbenc_package");
wh.addStorage("mlmlse_package");
% === RUN IT === %% === RUN IT ===
[results,wh] = submitJobs(dataTable.run_id(:), dsp_options, "serial", 'wh', wh, 'waitbar', true); [results,wh] = submitJobs(dataTable.run_id(:), dsp_options, "serial", 'wh', wh, 'waitbar', true);
%%
results_db = results(dataTable.db_mode==1); results_db = results(dataTable.db_mode==1);
results_nodb = results(dataTable.db_mode==0); results_nodb = results(dataTable.db_mode==0);
for i = 1:numel(results_db) %BER for ML based MLSE
for i = 1:length(results_db)
ber_m = cellfun(@(c) c.metrics.BER_precoded, results_db{1,i}.mlmlse_package);
[BER_MLMLSE_pre_emph(i), ~] = min(ber_m);
ber_m = cellfun(@(c) c.metrics.BER_precoded, results_nodb{1,i}.mlmlse_package);
[BER_MLMLSE(i), ~] = min(ber_m);
ber_m = cellfun(@(c) c.metrics.BER_precoded, results_nodb{1,i}.mlmlse_package);
[BER_MLMLSE(i), ~] = min(ber_m);
baudrate(i) = dataTable.symbolrate(i);
rop_db(i) = dataTable.power_rop((2*i)-1);
end
figure(11);hold on
plot(sort(rop_db),sort(BER_MLMLSE_pre_emph))
plot(sort(rop_db),sort(BER_MLMLSE))
beautifyBERplot
%%
results_db = results(dataTable.db_mode==1);
results_nodb = results(dataTable.db_mode==0);
for i = 1:numel(results_nodb)
% VNLE (from results_nodb) % VNLE (from results_nodb)
gmi_v = cellfun(@(c) c.metrics.GMI, results_nodb{1,i}.vnle_package); gmi_v = cellfun(@(c) c.metrics.GMI, results_nodb{1,i}.vnle_package);
@@ -89,9 +115,9 @@ for i = 1:numel(results_db)
idx_air_max_vnle(i) = find(air_v == max(air_v), 1); idx_air_max_vnle(i) = find(air_v == max(air_v), 1);
% MLSE (from results_db) % MLSE (from results_db)
gmi_m = cellfun(@(c) c.metrics.GMI, results_nodb{1,i}.mlse_package); gmi_m = cellfun(@(c) c.metrics.GMI, results_db{1,i}.mlse_package);
ber_m = cellfun(@(c) c.metrics.BER, results_nodb{1,i}.mlse_package); ber_m = cellfun(@(c) c.metrics.BER, results_nodb{1,i}.mlse_package);
air_m = cellfun(@(c) c.metrics.AIR, results_nodb{1,i}.mlse_package); air_m = cellfun(@(c) c.metrics.AIR, results_db{1,i}.mlse_package);
[BER_MLSE(i), idx_ber] = min(ber_m); [BER_MLSE(i), idx_ber] = min(ber_m);
GMI_MLSE(i) = gmi_m(idx_ber); GMI_MLSE(i) = gmi_m(idx_ber);
AIR_MLSE(i) = air_m(idx_ber); AIR_MLSE(i) = air_m(idx_ber);
@@ -111,11 +137,22 @@ for i = 1:numel(results_db)
idx_gmi_min_db(i) = find(gmi_db == min(gmi_db), 1); idx_gmi_min_db(i) = find(gmi_db == min(gmi_db), 1);
idx_air_max_db(i) = find(air_db == max(air_db), 1); idx_air_max_db(i) = find(air_db == max(air_db), 1);
%BER for ML based MLSE
ber_m = cellfun(@(c) c.metrics.BER, results_nodb{1,i}.mlmlse_package);
[BER_MLMLSE(i), idx_ber] = min(ber_m);
ber_m = cellfun(@(c) c.metrics.BER_precoded, results_db{1,i}.mlmlse_package);
[BER_MLMLSE_PREC(i), idx_ber] = min(ber_m);
% metadata % metadata
bitrate(i) = dataTable.bitrate(i); bitrate(i) = dataTable.bitrate(i);
baudrate(i) = dataTable.symbolrate(i); baudrate(i) = dataTable.symbolrate(i);
rop_atten(i) = dataTable.rop_attenuation(2*i);
rop_pre(i) = dataTable.power_rop((2*i)-1);
rop(i) = dataTable.power_rop((2*i));
end end
%%
STYLE_BASE = 2; % adjust this single number to scale markers & lines STYLE_BASE = 2; % adjust this single number to scale markers & lines
MARKER_SIZE = STYLE_BASE; % marker size (MATLAB MarkerSize) MARKER_SIZE = STYLE_BASE; % marker size (MATLAB MarkerSize)
LINE_WIDTH = max(2, STYLE_BASE/3); % line width (keeps lines reasonable when STYLE_BASE large) LINE_WIDTH = max(2, STYLE_BASE/3); % line width (keeps lines reasonable when STYLE_BASE large)
@@ -128,6 +165,7 @@ cm.VNLE = cols(1 + d, :);
cm.MLSE = cols(2 + d, :); cm.MLSE = cols(2 + d, :);
cm.DB_precode = cols(3 + d, :); cm.DB_precode = cols(3 + d, :);
cm.DB = cols(4 + d, :); % duobinary cm.DB = cols(4 + d, :); % duobinary
cm.ML_MLSE = cols(6 + d, :);
% prepare x values in GBd % prepare x values in GBd
xGHz = baudrate .* 1e-9; xGHz = baudrate .* 1e-9;
@@ -139,7 +177,7 @@ mk.VNLE = {'Marker','o','MarkerFaceColor',cm.VNLE,'MarkerEdgeColor',cm.VNLE,'
mk.MLSE = {'Marker','*','MarkerFaceColor',cm.MLSE,'MarkerEdgeColor',cm.MLSE,'MarkerSize',MARKER_SIZE}; mk.MLSE = {'Marker','*','MarkerFaceColor',cm.MLSE,'MarkerEdgeColor',cm.MLSE,'MarkerSize',MARKER_SIZE};
mk.DB_precode = {'Marker','^','MarkerFaceColor',cm.DB_precode,'MarkerEdgeColor',cm.DB_precode,'MarkerSize',MARKER_SIZE}; mk.DB_precode = {'Marker','^','MarkerFaceColor',cm.DB_precode,'MarkerEdgeColor',cm.DB_precode,'MarkerSize',MARKER_SIZE};
mk.DB = {'Marker','d','MarkerFaceColor',cm.DB,'MarkerEdgeColor',cm.DB,'MarkerSize',MARKER_SIZE}; mk.DB = {'Marker','d','MarkerFaceColor',cm.DB,'MarkerEdgeColor',cm.DB,'MarkerSize',MARKER_SIZE};
mk.ML_MLSE = {'Marker','^','MarkerFaceColor',cm.ML_MLSE,'MarkerEdgeColor',cm.ML_MLSE,'MarkerSize',MARKER_SIZE};
% ---------------- FIGURE : BER ---------------- % ---------------- FIGURE : BER ----------------
figure(112+M); clf; hold on; figure(112+M); clf; hold on;
@@ -149,20 +187,100 @@ plot(xGHz, BER_VNLE, ...
plot(xGHz, BER_MLSE, ... plot(xGHz, BER_MLSE, ...
'DisplayName','MLSE', ... 'DisplayName','MLSE', ...
mk.MLSE{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.MLSE); mk.MLSE{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.MLSE);
plot(xGHz, BER_DB, ...
'DisplayName','DB tgt.', ...
mk.DB{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.DB);
plot(xGHz, BER_DB_PREC, ... plot(xGHz, BER_DB_PREC, ...
'DisplayName','Diff. Precode + DB tgt.', ... 'DisplayName','Diff. Precode + DB tgt.', ...
mk.DB{:}, 'LineStyle',':','LineWidth',LINE_WIDTH,'Color',cm.DB); mk.DB{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.DB);
plot(xGHz, BER_MLMLSE_PREC, ...
'DisplayName','ML-based MLSE (L=2)', ...
mk.ML_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(4.85e-3,'LineWidth',1,'HandleVisibility','off');
yline(2.2e-4,'LineWidth',1,'HandleVisibility','off'); yline(2.2e-4,'LineWidth',1,'HandleVisibility','off');
xlabel('Baudrate in GBd'); xlabel('Baudrate in GBd');
ylabel('BER'); ylabel('BER');
set(gca, 'yscale', 'log'); set(gca, 'yscale', 'log');
set(gca, 'XTick', xticks_vals(1:2:end), 'XTickLabel', xtick_labels(1:2:end)); set(gca, 'XTick', xticks_vals(1:end), 'XTickLabel', xtick_labels(1:end));
grid on; grid on;
legend('Location','best'); legend('Location','best');
beautifyBERplot
%%
%%
STYLE_BASE = 2; % adjust this single number to scale markers & lines
MARKER_SIZE = STYLE_BASE; % marker size (MATLAB MarkerSize)
LINE_WIDTH = max(2, STYLE_BASE/3); % line width (keeps lines reasonable when STYLE_BASE large)
% --- color map / method -> color assignment (keeps colors consistent) ---
cols = cbrewer2('Paired',8);
cols = linspecer(6);
d = 0;
cm.VNLE = cols(1 + d, :);
cm.MLSE = cols(2 + d, :);
cm.DB_precode = cols(3 + d, :);
cm.DB = cols(4 + d, :); % duobinary
cm.ML_MLSE = cols(6 + d, :);
% prepare x values in GBd
xdbm = flip(sort(rop));
xticks_vals = xdbm;
xtick_labels = arrayfun(@(v) sprintf('%d', round(v)), xticks_vals, 'UniformOutput', false);
% common marker settings (filled, same face+edge color)
mk.VNLE = {'Marker','o','MarkerFaceColor',cm.VNLE,'MarkerEdgeColor',cm.VNLE,'MarkerSize',MARKER_SIZE};
mk.MLSE = {'Marker','*','MarkerFaceColor',cm.MLSE,'MarkerEdgeColor',cm.MLSE,'MarkerSize',MARKER_SIZE};
mk.DB_precode = {'Marker','^','MarkerFaceColor',cm.DB_precode,'MarkerEdgeColor',cm.DB_precode,'MarkerSize',MARKER_SIZE};
mk.DB = {'Marker','d','MarkerFaceColor',cm.DB,'MarkerEdgeColor',cm.DB,'MarkerSize',MARKER_SIZE};
mk.ML_MLSE = {'Marker','^','MarkerFaceColor',cm.ML_MLSE,'MarkerEdgeColor',cm.ML_MLSE,'MarkerSize',MARKER_SIZE};
% ---------------- FIGURE : BER ----------------
figure(112+M); clf; hold on;
plot(flip(sort(rop)), sort(BER_VNLE), ...
'DisplayName','VNLE', ...
mk.VNLE{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.VNLE);
plot(flip(sort(rop)), sort(BER_MLSE), ...
'DisplayName','MLSE', ...
mk.MLSE{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.MLSE);
plot(flip(sort(rop)), sort(BER_MLSE), ...
'DisplayName','MLSE', ...
mk.MLSE{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.MLSE);
plot(flip(sort(rop_pre)), sort(BER_DB_PREC), ...
'DisplayName','Diff. Precode + DB tgt.', ...
mk.DB{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.DB);
plot(flip(sort(rop_pre)), sort(BER_MLMLSE_PREC), ...
'DisplayName','ML-based MLSE Diff. Prec. (L=2)', ...
mk.ML_MLSE{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.ML_MLSE);
plot(flip(sort(rop_pre)), sort(BER_MLMLSE), ...
'DisplayName','ML-based MLSE (L=2)', ...
mk.ML_MLSE{:}, 'LineStyle',':','LineWidth',LINE_WIDTH,'Color',cm.DB_precode);
yline(2e-2,'LineWidth',1,'HandleVisibility','off');
yline(4.85e-3,'LineWidth',1,'HandleVisibility','off');
yline(2.2e-4,'LineWidth',1,'HandleVisibility','off');
xlabel('ROP in dBm');
ylabel('BER');
set(gca, 'yscale', 'log');
% set(gca, 'XTick', xticks_vals(1:end), 'XTickLabel', xtick_labels(1:end));
grid on;
legend('Location','best');
beautifyBERplot
%%
% ---------------- FIGURE 15 : GMI ---------------- % ---------------- FIGURE 15 : GMI ----------------

View File

@@ -6,31 +6,32 @@ M = 4;
fp = QueryFilter(); fp = QueryFilter();
% fp.where('Runs', 'run_id','EQUALS', 987); % fp.where('Runs', 'run_id','EQUALS', 987);
% fp.where('Runs', 'pam_level','EQUALS', M); % fp.where('Runs', 'pam_level','EQUALS', M);
% fp.where('Runs', 'symbolrate','EQUALS', 150e9); % fp.where('Runs', 'symbolrate','EQUALS', 165e9); %150, 165, 180, 195, 210, 225, 240
% fp.where('Runs', 'fiber_length','EQUALS', 10); % fp.where('Runs', 'fiber_length','EQUALS', 10);
fp.where('Runs', 'is_mpi','EQUALS', 0); % 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', 'interference_path_length','EQUALS', 1000);
% fp.where('Runs', 'loop_id','GREATER_THAN', 11); % fp.where('Runs', 'loop_id','GREATER_THAN', 11);
% fp.where('Runs', 'sir','EQUALS',18); % fp.where('Runs', 'sir','EQUALS',18);
% fp.where('Runs', 'wavelength','EQUALS', 1310); % fp.where('Runs', 'wavelength','EQUALS', 1310);
fp.where('Runs', 'db_mode','EQUALS', 1); % 0 == high preemphasis // 1 == low preemphasis fp.where('Runs', 'db_mode','EQUALS', 2); % 0 == high preemphasis // 1 == low preemphasis
fp.where('Runs', 'rop_attenuation','EQUALS', 0); % fp.where('Runs', 'rop_attenuation','EQUALS', 0);
fields = db.getTableFieldNames('power_state_info'); fields = db.getTableFieldNames('power_state_info');
fields = [fields; db.getTableFieldNames('dashboard_ungrouped_new')]; fields = [fields; db.getTableFieldNames('dashboard_ungrouped_new')];
[dataTable,~] = db.queryDB(fp, fields); [dataTable,~] = db.queryDB(fp, fields);
%% %%
cfg = struct; cfg = struct;
cfg.x_axis = 'wavelength'; % 'symbolrate' | 'baudrate' | 'bitrate' | 'wavelength' cfg.x_axis = 'symbolrate'; % 'symbolrate' | 'bitrate' | 'wavelength'
cfg.y_axis = 'power_mzm'; % 'BER' | 'GMI' | 'AIR' | ... cfg.y_axis = 'BER'; % 'BER' | 'GMI' | 'AIR' | ...
cfg.group_by = {}; cfg.group_by = {'wavelength'};
cfg.filters = struct('is_mpi',0,'pam_level',M,'equalizer_structure',[equalizer_structure.vnle,equalizer_structure.ffe,equalizer_structure.vnle_pf_mlse,equalizer_structure.vnle_db_mlse,equalizer_structure.dfe]); cfg.filters = struct('is_mpi',0,'pam_level',M,'equalizer_structure',[equalizer_structure.vnle_db_mlse]);%,equalizer_structure.ffe,equalizer_structure.vnle_pf_mlse,equalizer_structure.vnle_db_mlse,equalizer_structure.dfe]);
cfg.y_scale = 'auto'; % auto -> log for BER*, linear otherwise cfg.y_scale = 'auto'; % auto -> log for BER*, linear otherwise
cfg.outlier = 'mad'; % simple, robust; 'none' or 'pctl' also available cfg.outlier = 'mad'; % simple, robust; 'none' or 'pctl' also available
cfg.show_raw = true; cfg.show_raw = true;
cfg.show_spread = 'none'; % 'none' or 'iqr' cfg.show_spread = 'iqr'; % 'none' or 'iqr'
cfg.agg = 'mean'; % or 'median' cfg.agg = 'mean'; % or 'median'
cfg.show_precoded = 0; cfg.show_precoded = 0;
cfg.fec_lines = [2.2e-4 4.85e-3 2e-2]; % optional cfg.fec_lines = [2.2e-4 4.85e-3 2e-2]; % optional
@@ -45,5 +46,4 @@ cfg.plot.scatterAlpha = 0.35;
cfg.plot.legendLocation = 'best'; cfg.plot.legendLocation = 'best';
cfg.plot.fecLineWidth = 2.4; % thicker FEC limits cfg.plot.fecLineWidth = 2.4; % thicker FEC limits
plot_measurements_gpt(dataTable, cfg); plot_measurements_gpt(dataTable, cfg);

View File

@@ -0,0 +1,164 @@
%% analyze_filter_length.m
clear; clc;
M = 4;
randkey = 1;
% --- Parameter sweep
order_range = 2:3:11; % FFE order
delta_range = 0:2:4; % delta
SNR_dB = 20;
% --- Prepare bit sequence
order_bits = 19;
s = RandStream('twister','Seed',randkey);
for i = 1:log2(M)
N = 2^(order_bits-1);
bitpattern(:,i) = randi(s,[0 1], N, 1);
end
Bits = Informationsignal(bitpattern);
Symbols = PAMmapper(M,0).map(Bits);
Symbols.fs = 200e9;
% --- Channel (minimal ISI + AWGN)
h = [0.3 0.9 0.3]; h = h/norm(h);
symbols_filt = Symbols.filter(h,1);
symbols_noi = symbols_filt;
symbols_noi.signal = awgn(symbols_filt.signal,SNR_dB,'measured');
% --- Generate all parameter pairs
[O,D] = ndgrid(order_range, delta_range);
pairs = [O(:), D(:)];
training_len = 100;
ber_vec = nan(size(pairs,1),1); % initialize with NaN
ber_training = nan(size(pairs,1),training_len);
ce_vec = nan(size(pairs,1),1);
ce_training = nan(size(pairs,1),training_len);
% --- Parallel loop over parameter pairs
parfor k = 1:size(pairs,1)
order_k = pairs(k,1);
delta_k = pairs(k,2);
% Skip invalid combinations (delay cannot exceed filter length)
if abs(delta_k) >= order_k
fprintf('Skip: order=%d, delta=%d (invalid)\n', order_k, delta_k);
continue;
end
try
ml = ML_MLSE("epochs_tr",training_len,"epochs_dd",1,"len_tr",2^15, ...
"mu_dd",0.1,"mu_tr",0.1,"order",order_k,"sps",1, ...
"traceback_depth",128,"L",3,"delta",delta_k,"adaptive_mu",0);
[y_ml,y_ref] = ml.process(symbols_noi,Symbols);
ref_bits = PAMmapper(M,0).demap(y_ref);
eq_bits = PAMmapper(M,0).demap(y_ml);
ber_training(k,:) = ml.ber;
ce_training(k,:) = ml.ce;
[~,~,ber_vec(k)] = calc_ber(eq_bits.signal, ref_bits.signal, ...
"skip_front",10,"skip_end",10);
L = min(length(ml.ce),30);
ce_vec(k) = mean(ml.ce(end-L+1:end));
fprintf('order=%d, delta=%d BER=%.2e, CE=%.3f\n', ...
order_k, delta_k, ber_vec(k), ce_vec(k));
catch ME
fprintf('Error at order=%d, delta=%d: %s\n', ...
order_k, delta_k, ME.message);
ber_vec(k) = NaN;
ce_vec(k) = NaN;
end
end
% --- reshape to 2D matrices
ber_mat = reshape(ber_vec, numel(order_range), numel(delta_range));
ce_mat = reshape(ce_vec, numel(order_range), numel(delta_range));
%% --- Plot BER
figure; hold on
cols = cbrewer2('Set1',10);
for i = 1:numel(delta_range)
plot(order_range,ber_mat(:,i),'DisplayName',sprintf('delta: %d',delta_range(i)),'Color',cols(i,:))
end
beautifyBERplot
ylabel('BER'); xlabel('Filter Order [N]');
title('BER vs. Filter order');
ylim([1e-4, 0.1]);
yline(3.8e-3,'HandleVisibility','off');
yline(2.2e-4,'HandleVisibility','off');
%% --- Plot Cross-Entropy
figure; hold on
for i = 1:numel(delta_range)
plot(order_range,ce_mat(:,i),'DisplayName',sprintf('delta: %d',delta_range(i)))
end
% beautifyBERplot
ylabel('BER'); xlabel('Filter Order [N]');
title('BER vs. Filter order');
%% --- Training Curves: BER and CE per combination
figure('Name','Training Convergence'); hold on
cols = cbrewer2('Set1', 10); % one color per delta
[O, D] = ndgrid(order_range, delta_range);
for i = 1:size(ber_training,1)
ord = O(i);
del = D(i);
if ord <= del
continue;
end
% --- show only order 2 and 10
if ord == 2
lnst = '-';
elseif ord == 5
lnst = ':';
elseif ord == 8
lnst = '--';
elseif ord == 11
lnst = '-.';
end
b = ber_training(i,:);
plot_label = sprintf('order=%d, delta=%d', ord, del);
plot(1:length(b), b, 'Color', cols(del+1, :), ...
'DisplayName', plot_label,'LineStyle',lnst);
end
set(gca,'YScale','log');
xlabel('Epoch');
ylabel('BER');
title('Training Convergence (BER)');
legend('show');
grid on;
%% --- Cross-Entropy curves
figure('Name','Cross-Entropy'); hold on
cols = cbrewer2('Set1',size(ce_training,1));
for i = 1:size(ce_training,1)
[O, D] = ndgrid(order_range, delta_range);
plot_label = sprintf('order=%d, delta=%d', O(i), D(i));
c = ce_training(i,:);
c(~isfinite(c) | c==0) = NaN;
if all(isnan(c)), continue; end
plot(1:length(c), c, 'Color', cols(D(i)+1,:), ...
'DisplayName', plot_label);
end
set(gca,'YScale','log');
xlabel('Epoch');
ylabel('Cross-Entropy');
title('Training Convergence (CE)');
legend('show');
grid on;

View File

@@ -0,0 +1,113 @@
M = 4;
order = 19;
randkey = 1;
bitpattern = [];
s = RandStream('twister','Seed',randkey);
for i = 1:log2(M)
N = 2^(order-1); %length of prbs
bitpattern(:,i) = randi(s,[0 1], N, 1);
end
if M == 6
bitpattern = reshape(bitpattern',[],1);
bitpattern = bitpattern(1:end-mod(length(bitpattern),5));
end
Bits = Informationsignal(bitpattern);
Symbols = PAMmapper(M,0).map(Bits);
Symbols.fs = 200e9;
Bits_ = PAMmapper(M, 0, "eth_style", 0).demap(Symbols);
% --- Channel: minimal ISI response + AWGN ---
h = [0.3 0.9 0.3]; % impulse response (normalized later if desired)
h = h / norm(h); % optional normalization for unit energy
symbols_filt = Symbols.filter(h,1);
%% SHOW Loss during training
mu = logspace(-3,-0.8,12);
ber_ml_mlse = zeros(size(mu));
ber_training = [];
ce_training = [];
parfor i = 1:numel(mu)
symbols_noi = symbols_filt;
SNR_dB = 20;
symbols_noi.signal = awgn(symbols_filt.signal, SNR_dB, 'measured'); % AWGN with given SNR
ml_mlse_equalizer = ML_MLSE("epochs_tr",200,"epochs_dd",1,"len_tr",2^15,...
"mu_dd",mu(i),"mu_tr",mu(i),"order",5,"sps",1,...
"traceback_depth",128,"L",3,"delta",0,'adaptive_mu',0);
[y_ml_mlse,y_ref] = ml_mlse_equalizer.process(symbols_noi,Symbols);
ref_bits = PAMmapper(M, 0, "eth_style", 0).demap(y_ref);
ml_mlse_bits = PAMmapper(M, 0, "eth_style", 0).demap(y_ml_mlse);
[~, errors, ber_ml_mlse(i), errpos] = calc_ber(ml_mlse_bits.signal, ref_bits.signal, "skip_front", 10, "skip_end", 10, "returnErrorLocation", 1);
fprintf('ML MLSE BER: %.2e \n',ber_ml_mlse(i));
ber_training(i,:) = ml_mlse_equalizer.ber;
ce_training(i,:) = ml_mlse_equalizer.ce;
end
%%
symbols_noi = symbols_filt;
SNR_dB = 20;
symbols_noi.signal = awgn(symbols_filt.signal, SNR_dB, 'measured'); % AWGN with given SNR
ml_mlse_equalizer_adap = ML_MLSE("epochs_tr",200,"epochs_dd",1,"len_tr",2^16,...
"mu_dd",1,"mu_tr",1,"order",5,"sps",1,...
"traceback_depth",128,"L",3,"delta",0,"adaptive_mu",1);
[y_ml_mlse,y_ref] = ml_mlse_equalizer_adap.process(symbols_noi,Symbols);
ref_bits = PAMmapper(M, 0, "eth_style", 0).demap(y_ref);
ml_mlse_bits = PAMmapper(M, 0, "eth_style", 0).demap(y_ml_mlse);
[~, errors, ber_ml_mlse_, errpos] = calc_ber(ml_mlse_bits.signal, ref_bits.signal, "skip_front", 10, "skip_end", 10, "returnErrorLocation", 1);
fprintf('ML MLSE BER: %.2e \n',ber_ml_mlse_);
%%
figure();hold on
plot(mu,ber_ml_mlse,'DisplayName','ML-based MLSE');
beautifyBERplot;
xlim([mu(1), mu(end)]);
xlabel('mu');
ylabel('BER');
title('PAM-4; M=3; AWGN Channel');
ylim([1e-5 0.1]);
%%
figure()
hold on;
cols = cbrewer2('Spectral',12);
for i = 1:12
plot(1:200,ber_training(i,:),'DisplayName', sprintf('mu=%.3f ',mu(i)),'Color',cols(i,:));
end
set(gca,'YScale','log');
xlabel('Epoch');
ylabel('BER');
title('PAM-4; L=3; SNR=20; AWGN Channel');
plot(1:200,ml_mlse_equalizer_adap.ber,'DisplayName','Adaptive mu');
%%
figure()
hold on;
cols = cbrewer2('Spectral',12);
for i = 1:12
plot(1:200,ce_training(i,:),'DisplayName', sprintf('mu=%.3f ',mu(i)),'Color',cols(i,:));
end
set(gca,'YScale','log');
xlabel('Epoch');
ylabel('Cross-Entropy');
title('PAM-4; L=3; SNR=20; AWGN Channel');
plot(1:200,ml_mlse_equalizer_adap.ce,'DisplayName','Adaptive mu');
%% SUPER LONG EPOCHS

View File

@@ -0,0 +1,162 @@
dsp_options.storage_path = 'Z:\2024\sioe_labor\';
dsp_options.max_occurences = 1;
database = DBHandler("dataBase", 'labor_highspeed', "type", 'mysql' );
run_id = 2776;
dataTable = queryRunid(run_id, database);
fsym = dataTable.symbolrate;
M = double(dataTable.pam_level);
duob_mode = db_mode(strrep(dataTable.db_mode,'"',''));
% if database.checkIfRunExists('Results','run_id',run_id)
% disp(['Already got at least one reulst for run id: ',num2str(run_id),' '])
% return
% end
% 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",1,"displayname",'Rx')
%%
ffe_order = [50, 5, 5];
mu_ffe = [0.0001, 0.0008, 0.001];
mu_dfe = 0.0004;
eq_ = EQ("Ne",ffe_order,"Nb",[0,0,0],"training_length",2^14,"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);
mlse_ = MLSE("DIR",[1,1],"duobinary_output",0,"M",M,"trellis_states",PAMmapper(M,0).levels,'scale_mode',2,'trellis_exclusion',0,'trellis_state_mode',3);
%Duobinary Targeting
db_ref_sequence = Duobinary().encode(Symbols);
db_ref_constellation = unique(db_ref_sequence.signal);
[eq_signal, eq_noise] = eq_.process(Scpe_sig,db_ref_sequence);
%%
if 0
[mlse_sig_sd,LLR,GMI_MLSE] = mlse_.process(eq_signal,Symbols);
else
% Ml MLSE
ml_mlse_equalizer = ML_MLSE("epochs_tr",20,"epochs_dd",1,"len_tr",length(eq_signal),...
"mu_dd",0.01,"mu_tr",0.01,"order",11,"sps",2,...
"traceback_depth",128,"L",1,"delta",4,'adaptive_mu',0);
[mlse_sig_sd,ref_sig] = ml_mlse_equalizer.process(Scpe_sig,db_ref_sequence);
end
%%
mlse_sig_sd_decoded = Duobinary().decode(mlse_sig_sd,"M",M);
ref_sig_decoded = Duobinary().decode(db_ref_sequence,"M",M);
mlse_sig_bits = PAMmapper(M,0,"eth_style",0).demap(mlse_sig_sd_decoded);
ref_sig_bits = PAMmapper(M,0,"eth_style",0).demap(ref_sig_decoded);
err = sum(ref_sig_decoded.signal ~= mlse_sig_sd_decoded.signal);
[bits_db,errors_db,ber_db,a] = calc_ber(mlse_sig_bits.signal,ref_sig_bits.signal,"skip_front",0,"skip_end",0,"returnErrorLocation",1);
%%
switch duob_mode
case db_mode.no_db
% TX Data is not precoded:
% A) Emulate diff precoding
mlse_sig_hd_precoded = Duobinary().encode(mlse_sig_hd,"M",M);
mlse_sig_hd_precoded = Duobinary().decode(mlse_sig_hd_precoded,"M",M);
tx_symbols_precoded = Duobinary().encode(Symbols);
tx_symbols_precoded = Duobinary().decode(tx_symbols_precoded);
tx_bits_precoded = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(tx_symbols_precoded);
rx_bits_mlse = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(mlse_sig_hd_precoded);
[~,errors_db_diff_precoded,ber_db_diff_precoded,~] = calc_ber(rx_bits_mlse.signal,tx_bits_precoded.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
%B) Just determine BER
rx_bits_mlse = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(mlse_sig_hd);
[bits_mlse,errors_mlse,ber_db,~] = calc_ber(rx_bits_mlse.signal,Tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
case db_mode.db_precoded
% Daten SIND TATSÄCHLICH precoded auf TX Seite:
% A) Decode at Rx if no DB targeting was applied (we are in VNLE or MLSE EQ structure here!
mlse_sig_hd_decoded = Duobinary().encode(mlse_sig_hd,"M",M);
mlse_sig_hd_decoded = Duobinary().decode(mlse_sig_hd_decoded,"M",M);
rx_bits_mlse_decoded = PAMmapper(M,0,"eth_style",0).demap(mlse_sig_hd_decoded);
[~,errors_db_diff_precoded,ber_db_diff_precoded,a] = calc_ber(rx_bits_mlse_decoded.signal,Tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
burst_db_precoded = count_error_bursts(a, 40);
% B) Omit the Coding by comparing with demapped TX symbol sequence
Tx_bits_ = PAMmapper(M,0,"eth_style",0).demap(Symbols);
rx_bits_mlse = PAMmapper(M,0,"eth_style",0).demap(mlse_sig_hd);
[bits_db,errors_db,ber_db,a] = calc_ber(rx_bits_mlse.signal,Tx_bits_.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
burst_db = count_error_bursts(a, 40);
cols = linspecer(8);
figure();hold on;
stem(1:40,burst_db,'LineWidth',1,'Color',cols(4,:),'Marker','_','DisplayName','w/o diff. precoder');
stem(1:40,burst_db_precoded,'LineWidth',1,'Color',cols(3,:),'Marker','.','LineStyle','-','DisplayName','w diff. precoder');
xlabel('Bit Error Burst Length')
ylabel('Occurence')
set(gca, 'yscale', 'log');
end
%% SHOW Loss during training
mu = logspace(-3,-0.8,12);
ber_ml_mlse = zeros(size(mu));
ber_training = [];
ce_training = [];
parfor i = 1:numel(mu)
ml_mlse_equalizer = ML_MLSE("epochs_tr",200,"epochs_dd",1,"len_tr",length(Scpe_sig),...
"mu_dd",mu(i),"mu_tr",mu(i),"order",11,"sps",2,...
"traceback_depth",128,"L",2,"delta",4,'adaptive_mu',0);
[y_ml_mlse,y_ref] = ml_mlse_equalizer.process(Scpe_sig,Symbols);
ref_bits = PAMmapper(M, 0, "eth_style", 0).demap(y_ref);
ml_mlse_bits = PAMmapper(M, 0, "eth_style", 0).demap(y_ml_mlse);
[~, errors, ber_ml_mlse(i), errpos] = calc_ber(ml_mlse_bits.signal, ref_bits.signal, "skip_front", 10, "skip_end", 10, "returnErrorLocation", 1);
fprintf('ML MLSE BER: %.2e \n',ber_ml_mlse(i));
ber_training(i,:) = ml_mlse_equalizer.ber;
ce_training(i,:) = ml_mlse_equalizer.ce;
end
%%
figure();hold on
plot(mu,ber_ml_mlse,'DisplayName','ML-based MLSE');
beautifyBERplot;
xlim([mu(1), mu(end)]);
xlabel('mu');
ylabel('BER');
title('PAM-4; M=3; AWGN Channel');
ylim([1e-5 0.1]);
%%
figure()
hold on;
cols = cbrewer2('Spectral',12);
for i = 1:12
plot(1:200,ber_training(i,:),'DisplayName', sprintf('mu=%.3f ',mu(i)),'Color',cols(i,:));
end
set(gca,'YScale','log');
xlabel('Epoch');
ylabel('BER');
title('PAM-4; L=3; SNR=20; AWGN Channel');
plot(1:200,ml_mlse_equalizer_adap.ber,'DisplayName','Adaptive mu');

View File

@@ -0,0 +1,13 @@
function rop_fec = interp_fec_cross(rops, ber, fec_thr)
if all(~isfinite(ber))
rop_fec = NaN; return;
end
idx = find(ber < fec_thr, 1, 'first');
if isempty(idx) || idx == 1
rop_fec = NaN; return; % no crossing
end
% linear interpolation between the two nearest points
x1 = rops(idx-1); x2 = rops(idx);
y1 = ber(idx-1); y2 = ber(idx);
rop_fec = interp1([y1 y2], [x1 x2], fec_thr, 'linear', NaN);
end

Binary file not shown.

View File

@@ -0,0 +1,555 @@
classdef bcjr_pam < handle
%MLSE calculates the most probable sequence for an input signal with given/ known channel impulse response of any length
properties(Access=public)
M %PAM-M
DIR
trellis_states
duobinary_output
end
methods (Access=public)
function obj = bcjr_pam(options)
%NAME Construct an instance of this class
% Detailed explanation goes here
arguments
options.M double = 4;
options.DIR double = [1];
options.trellis_states double = [-3 -1 1 3];
options.duobinary_output logical = false;
end
%
fn = fieldnames(options);
for n = 1:numel(fn)
try
obj.(fn{n}) = options.(fn{n});
end
end
end
function [VITERBI_ESTIMATION_SYMBOLS,LLR_exact,GMI] = process(obj,data_in,data_ref,tx_bits,bit_mapping)
debug = 0;
% States should match the target states of the prev. EQ (EQ's job was to reduce the error between signal and the target)
trellis_state_mode = 2;
% 0 = use provided states (MUST provide the correct states);
% 1 = normalize to = 1 rms;
% 2 = use target symbols;
% 3 = use statistical levels
% 3 analyzes avg of rx signal levels - can help with nonlinear impairments
trellis_exclusion = 1; % PAM-6 only (only if data is NOT precoded!)
% Additional scaling between states, expected output (noiseless_received) and the noisy, filtered input signal
scale_mode = 2; % scale_mode:
% 0 = no scaling,
% 1 = use RMS to scale MODEL,
% 2 = use MMSE/time-corr to scale MODEL, -> This best to get the GMI right -> sometimes the LLP's are not centered around zero...
% 3 = use RMS to scale DATA,
% 4 = use MMSE/time-corr to scale DATA
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%% PREPARATIONS %%%%%%%%
% remove unnecessary zeros at start of impulse response to keep
% number of trellis states minimal
DIR_nonzero = find(obj.DIR ~= 0);
if DIR_nonzero(1) > 1
obj.DIR(1:DIR_nonzero(1)-1) = [];
end
if isscalar(obj.DIR)
obj.DIR = [0 obj.DIR];
end
% impulse respnse to remove from signal
obj.DIR = flip(obj.DIR); %i.e. -0.2676 -0.0478 1.0000
% Trellis States
obj.trellis_states = reshape(obj.trellis_states,1,[]);
if trellis_state_mode == 1 % Normalize the Trellis states to =1 RMS
obj.trellis_states = obj.trellis_states ./ rms(obj.trellis_states);
elseif trellis_state_mode == 2 %simply use the states from the ref signal (should be a robust option)
obj.trellis_states = reshape(unique(data_ref),size(obj.trellis_states));
elseif trellis_state_mode == 3 %use_statistical_levels
%%%% Separate the equalized signal into the respective levels based on the actually transmitted level
constellation = unique(data_ref);
% find actual levels from rx signal
symbols_for_lvl = NaN(numel(constellation),length(data_ref));
for l = 1:numel(constellation)
level_amplitude = constellation(l);
symbols_for_lvl(l,data_ref==level_amplitude) = data_in(data_ref==level_amplitude);
end
%replace the trellis states
avg_levels = mean(symbols_for_lvl,2,'omitnan');
obj.trellis_states = sort(avg_levels)';
%also replace the whole ref signal (PAM-M) levels
[~, idx] = ismember(data_ref, unique(data_ref));
data_ref = avg_levels(idx);
end
% seems to be the only way to use combvec for a flexible amount
% of vectors. 'combs' contains all trellis states
pre_comb_mat = repmat(obj.trellis_states,length(obj.DIR)-1,1);
pre_comb_cell = mat2cell(pre_comb_mat,ones(1,size(pre_comb_mat,1)),size(pre_comb_mat,2));
combs = fliplr(combvec(pre_comb_cell{:}).');
first_sym = combs(:,1); % das ist das älteste/ trailing Symbol aus der sequenz
last_sym = combs(:,end); %hiermit wird entschieden/ das ist das cursor symbol am ende der sequenz
nStates = length(last_sym);
% % Calculate all possible input symbols for the desired impulse
% % response. Row number is the index of the previous state,
% % column number is the index of the next state
% % noise free received == branch metrics
% assumes: last_sym = combs(:,end); % already defined earlier
levels = sort(unique(obj.trellis_states(:)).');
edges = [levels(1) levels(end)]; % edge levels (0 and 5 in PAM6)
noise_free_received = inf(nStates,nStates); % rows: to, cols: from
edge_edge_mask = false(nStates,nStates); % rows: to, cols: from
for from = 1:nStates
for to = 1:nStates
% valid transition if shift-register overlap holds
if all(combs(to,2:end) == combs(from,1:end-1))
% noiseless sample for the 'to' state reached from 'from'
noise_free_received(to,from) = ...
dot(combs(to,:), obj.DIR(end:-1:2)) + last_sym(from)*obj.DIR(1);
% mark edgeedge candidate (to be excluded only on evenodd steps)
edge_edge_mask(to,from) = ...
(last_sym(from)==edges(1) || last_sym(from)==edges(2)) && ...
(last_sym(to) ==edges(1) || last_sym(to) ==edges(2));
end
end
end
h = flip(obj.DIR(:)).';
data_in = data_in(:);
y_ideal = conv(data_ref(:), h, "same");
switch scale_mode
case 0
g = 1; b = 0;
case 1 % RMS: scale model to data
g = rms(data_in)/rms(y_ideal); b = mean(data_in) - g*mean(y_ideal);
case 2 % MMSE/time-corr: scale states to data
[c,lags] = xcorr(data_in(:), y_ideal, 64);
[~,ix] = max(abs(c));
lag = lags(ix);
y_ideal = circshift(y_ideal, lag);
mu_y = mean(data_in(:));
mu_i = mean(y_ideal);
y_c = data_in(:)-mu_y;
yi_c = y_ideal-mu_i;
g = (yi_c'*y_c)/(yi_c'*yi_c);
b = mu_y - g*mu_i;
case 3 % RMS flipped: scale data to model
gd = rms(y_ideal)/rms(data_in); bd = mean(y_ideal) - gd*mean(data_in);
data_in = gd*data_in + bd;
g = 1; b = 0;
case 4 % MMSE/time-corr flipped: scale data to states
[c,lags] = xcorr(data_in(:), y_ideal(:), 64);
[~,ix] = max(abs(c));
lag = lags(ix);
y_ideal = circshift(y_ideal(:), lag);
mu_y = mean(data_in(:));
mu_i = mean(y_ideal);
y_c = data_in(:) - mu_y; % data_in centered
yi_c = y_ideal - mu_i; % ideal centered
g = (y_c' * yi_c) / (y_c' * y_c);
b = mu_i - g * mu_y;
data_in = g * data_in(:) + b;
g = 1; b = 0;
end
% apply (g,b) to states/ expected values
noise_free_received = g*noise_free_received + b;
last_sym = g*last_sym + b;
% calculate noise power
sigma2 = mean(abs(data_in - (g*y_ideal + b)).^2); %noise = mean(abs((RX Signal - IDEAL Signal)))^2
inv2s2 = 1/(2*sigma2);
if debug
figure(100); clf; hold on
obj.showLevelScatter_(data_in, data_ref);
yline(noise_free_received(:), 'DisplayName','Transition States','Color','red','HandleVisibility','off');
yline(obj.trellis_states(:), 'DisplayName','Transition States','Color','green','LineWidth',2,'HandleVisibility','off')
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%% FORWARD PASS (VITERBI -Alpha's) %%%%%
% Initialize the output vector
pm = zeros(nStates,nStates);
bm_fw = zeros(nStates,nStates,length(data_in));
% first start is evaluated without ISI/ wihout the full Impulse response
% so simply use the constellation here
bm = -(data_in(1) - last_sym).^2 * inv2s2;
pm = pm + bm;
[alpha(:,1),pm_survivor_fw_idx(:,1)] = max(pm,[],2);
pm = repmat(alpha(:,1).',nStates,1);
bm_fw(:,:,1) = pm;
% Forward Recursion (FSM Computation)
for n = 2:length(data_in)
bm = -(data_in(n) - noise_free_received).^2 * inv2s2;
% exclude edge to edge transitions only for even->odd steps && PAM-6
if mod(n,2) == 0 && obj.M == 6 && trellis_exclusion
bm(edge_edge_mask) = -Inf;
end
pm = pm + bm;
[alpha(:,n),pm_survivor_fw_idx(:,n)] = max(pm,[],2); % choose lowest path metric as new state (get min distance for all state transitions towards a new state)
pm = repmat(alpha(:,n).',nStates,1); % update pm (chosen state to 2nd dimension -> FROM state)
bm_fw(:,:,n) = bm;
end
% we can now get the best path as min
viterbi_path = NaN(1,length(data_in));
% find ideal trellis path by going through the trellis backwards
[~,viterbi_path(length(data_in))] = max(alpha(:,length(data_in)));
for n = length(data_in):-1:2
viterbi_path(n-1) = pm_survivor_fw_idx(viterbi_path(n),n);
end
if debug
alpha_ = alpha - min(alpha) + eps;
figure();hold on;
n = 10;
scatter(1:n,obj.trellis_states(repmat([1:numel(obj.trellis_states)]',1,n)),abs(alpha_(:,end-n+1:end)),'Marker','o','LineWidth',1);
scatter(1:n,obj.trellis_states(viterbi_path(end-n+1:end)),500,'Marker','x','LineWidth',1,'MarkerEdgeColor','green');
% scatter(1:n,data_ref(end-n+1:end),500,'Marker','x','LineWidth',1,'MarkerEdgeColor','red');
yticks(obj.trellis_states);
ylim([min(obj.trellis_states)-1 max(obj.trellis_states)+1]);
end
VITERBI_ESTIMATION_SYMBOLS(1:length(data_in)) = first_sym(viterbi_path);
VITERBI_ESTIMATION_SYMBOLS = reshape(VITERBI_ESTIMATION_SYMBOLS,size(data_in));
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%% BACKWARD (Beta's) %%%%%
% Initialize the output vector
pm = zeros(nStates,nStates);
beta = zeros(nStates,length(data_in));
pm_survivor_bw_idx = zeros(nStates,length(data_in));
bm_bw = zeros(nStates,nStates,length(data_in));
% starting with the state that has the lowest sum path
% metric, follow the stored information about the
% predecessor
for h = length(data_in)-1:-1:1
bm = -(data_in(h+1) - noise_free_received).^2 * inv2s2;
% exclude edge to edge transitions for even->odd steps && PAM-6
if mod(h+1, 2) == 0 && obj.M == 6 && trellis_exclusion
bm(edge_edge_mask) = -Inf;
end
pm = pm + bm.';
[beta(:,h),pm_survivor_bw_idx(:,h)] = max(pm,[],2); % choose lowest path metric as new state
pm = repmat(beta(:,h).',nStates,1); % update pm (chosen state to 2nd dimension -> FROM state)
bm_bw(:,:,h) = bm;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%% FORWARD (Combine Alpha and Beta to yield LLP's) %%%%%
%calc the log probabilities (llp's)
for k = 1:length(data_in)
if k == 1
alpha_ = repmat(alpha(:,k)',[nStates,1])';
beta_ = beta(:,k);
LLP(:,k) = max(alpha_ + beta_,[],2);
else
alpha_ = repmat(alpha(:,k-1)',[nStates,1])';
gamma_ = bm_fw(:,:,k)';
beta_ = beta(:,k);
LLP(:,k) = max(alpha_ + gamma_,[],1) + beta_';
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%% Calc LLR's %%%%%
% These are interchangeable...
nml_LLP = LLP - max(LLP); %subtract highest value for better numerical stability, LLP's are not always close to zero
expLLP = exp(nml_LLP);
state_prob = expLLP ./ sum(expLLP); % sums to one (or numerically close to one)
% compute symbolposteriors from LLP in the logdomain:
amax = max(LLP,[],1);
logZ = amax + log(sum(exp(LLP - amax), 1));
logPstate = LLP - logZ; % still in logdomain
state_prob = exp(logPstate); % exact, sums to 1
if obj.M == 6
num_bits = 5;
% all possible transitions (for now 36, including the "edges"
% of the QAM 32 constellation)
states = [-5 -3 -1 1 3 5];
pam6transitions = combvec(states,states)'; % pam6transitions =
% [-5 -5;
% -3 -5;
% -1 -5; ...
[~, idx_sym_1] = ismember(pam6transitions(:,1), states);
[~, idx_sym_2] = ismember(pam6transitions(:,2), states);
pam6ind = [idx_sym_1, idx_sym_2];
numPairs = floor(size(LLP,2)/2);
LLR_exact = zeros(numPairs,5);
LLR_maxlogmap = zeros(numPairs,5);
for k = 1:numPairs
symbol1 = 2*k-1;
symbol2 = 2*k;
LLP1 = LLP(:,symbol1);
LLP2 = LLP(:,symbol2);
prob1 = state_prob(:,symbol1);
prob2 = state_prob(:,symbol2);
% All 36 Combinations: M = LLP Symbol 1 + LLP Symbol 2
Mij = LLP1(pam6ind(:,1)) + LLP2(pam6ind(:,2));
pij = prob1(pam6ind(:,1)) .* prob2(pam6ind(:,2));
% for each of the 5 bits sum exact-probs or max-log
for b = 1:num_bits
idx_sym_1 = bit_mapping(:,b)==1;
idx_bit_1 = bit_mapping(:,b)==0;
% exact LLR from probabilities
P1 = sum(pij(idx_sym_1)); %prob that bit == 1
P0 = sum(pij(idx_bit_1));
LLR_exact(k,b) = log(P1./P0); %ratio by multiplication
% max-log:
LLR_maxlogmap(k,b) = max( Mij(idx_sym_1) ) - max( Mij(idx_bit_1) ); % ratio by subtraction
end
end
% GMI calc includes the Tx-bitstream
tx_bits_pam6_reshaped = reshape(tx_bits',5,[])'; % N x 5
MI = zeros(1, num_bits);
for k = 1:num_bits
idx_bit_1 = (tx_bits_pam6_reshaped(:,k) == 0); %wo sind die 1en
idx_sym_1 = (tx_bits_pam6_reshaped(:,k) == 1); %wo sind die 0en
%LLR's for all actually transmitted ones or zeros
llr0 = LLR_exact(idx_bit_1,k);
llr1 = LLR_exact(idx_sym_1,k);
% Calculate mutual information for bit position k
I0 = mean(log2(1 + exp(llr0))); % exp(--LLR) = exp(positive) > 1
I1 = mean(log2(1 + exp(-llr1))); % exp(-+LLR) = exp(negative) < 1
MI(k) = 1 - 0.5 * (I0 + I1);
end
GMI = sum(MI); % Total mutual information per symbol
GMI = GMI/2; % GMI per single symbol not per two symbols
else
% Number of symbols and bits per symbol
num_bits = log2(length(obj.trellis_states)); % 2 bits per symbol
% bit_mapping = PAMmapper(length(obj.trellis_states),0,"eth_style",0).showBitMapping;
% Initialize LLR storage
LLR_maxlogmap = zeros(length(data_in),num_bits);
LLR_exact = zeros(length(data_in),num_bits);
% Compute bit-wise LLRs
for bit_idx = 1:num_bits
% Find indices where bit is 0 and where it is 1
idx_bit_0 = bit_mapping(:,bit_idx) == 0;
idx_bit_1 = bit_mapping(:,bit_idx) == 1;
% Sum over log-probabilities
% Max-Log approximation uses the single max LLP value
% instead of sum over all LLP's
LLR_maxlogmap(:,bit_idx) = max(LLP(idx_bit_1,:), [], 1) - max(LLP(idx_bit_0,:), [], 1);
% Sum probabilities over states for which the bit is 1 and 0, respectively.
P0 = sum(state_prob(idx_bit_0, :),1);
P1 = sum(state_prob(idx_bit_1, :),1);
LLR_exact(:,bit_idx) = log(P1./P0); % N x num_bits
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%% CALC NGMI %%%%%
MI = zeros(1, num_bits);
for k = 1:num_bits
idx_bit_0 = (tx_bits(:,k) == 0); %wo sind die 1en
idx_bit_1 = (tx_bits(:,k) == 1); %wo sind die 0en
%LLR's for all actually transmitted ones or zeros
llr0 = LLR_exact(idx_bit_0,k);
llr1 = LLR_exact(idx_bit_1,k);
% mutual information for bit position k
I0 = mean(log2(1 + exp(llr0))); % exp(--LLR) = exp(positive) > 1
I1 = mean(log2(1 + exp(-llr1))); % exp(-+LLR) = exp(negative) < 1
MI(k) = 1 - 0.5 * (I0 + I1); % assumes equally distributed ones and zeros
end
GMI = sum(MI); % Total bitwise mutual information
end
if debug
%%% DEBUG PLOT LIKELIHOOD RATIOS %%%
figure(115);clf
subplot(2,1,1)
for bit = 1:num_bits
hold on;
histogram(LLR_exact(:,bit),1000,"DisplayName",sprintf('Actual LLR of Bit Pos %d',bit),'LineStyle','none','FaceAlpha',0.4);
end
legend
subplot(2,1,2)
for bit = 1:num_bits
hold on;
histogram(LLR_maxlogmap(:,bit),1000,"DisplayName",sprintf('Max Log LLR of Bit Pos %d',bit),'LineStyle','none','FaceAlpha',0.4);
end
legend
if obj.M == 6
pairs = reshape(VITERBI_ESTIMATION_SYMBOLS,2,[]).';
levels = sort(unique(VITERBI_ESTIMATION_SYMBOLS));
isedge = ismember(pairs, [levels(1) levels(end)]);
isforbidden = sum(isedge,2)==2;
fprintf('Found %d forbidden transitions (even -> odd ; edge -> edge).\n', nnz(isforbidden));
end
end
end
function [symbols_for_lvl,avg_for_lvl] = showLevelScatter_(~,eq_signal,ref_symbols)
figure()
rx_symbols = eq_signal; %./ rms(eq_signal);
correct_symbols = ref_symbols;
% col = cbrewer2('Paired',numel(unique(correct_symbols))*2);
col = ...
[0.6510 0.8078 0.8902; ...
0.1216 0.4706 0.7059; ...
0.6980 0.8745 0.5412; ...
0.2000 0.6275 0.1725; ...
0.9843 0.6039 0.6000; ...
0.8902 0.1020 0.1098; ...
0.9922 0.7490 0.4353; ...
1.0000 0.4980 0; ...
0.7922 0.6980 0.8392; ...
0.4157 0.2392 0.6039; ...
1.0000 1.0000 0.6000; ...
0.6941 0.3490 0.1569; ...
0.6510 0.8078 0.8902; ...
0.1216 0.4706 0.7059; ...
0.6980 0.8745 0.5412; ...
0.2000 0.6275 0.1725];
ccnt = -1;
levels = unique(correct_symbols);
symbols_for_lvl = NaN(numel(levels),length(correct_symbols));
start = 1;
ende = length(correct_symbols);
for l = 1:numel(levels)
ccnt = ccnt+2;
level_amplitude = levels(l);
symbols_for_lvl(l,correct_symbols==level_amplitude) = rx_symbols(correct_symbols==level_amplitude);
std_lvl(l) = std(symbols_for_lvl(l,:),'omitnan');
xax = 1:length(correct_symbols);
scatter(xax(start:ende),symbols_for_lvl(l,start:ende),10,'.','MarkerFaceAlpha',0.5,'MarkerEdgeAlpha',0.5,'MarkerEdgeColor',col(ccnt,:));
hold on;
end
std_lvl = round(std_lvl,2);
ccnt = 0;
avg_for_lvl = NaN(numel(levels),length(correct_symbols));
% Add the windowed/ smoothed curves
for l = 1:numel(levels)
ccnt = ccnt+2;
level_amplitude = levels(l);
L = 500;
movmean = 1/L .* movsum(rx_symbols(correct_symbols==level_amplitude),[L/2,L/2], 'Endpoints', 'fill');
avg_for_lvl(l,correct_symbols==level_amplitude) = movmean;
nanx = isnan(avg_for_lvl(l,:));
t = 1:numel(avg_for_lvl(l,:));
avg_for_lvl(l,nanx) = interp1(t(~nanx), avg_for_lvl(l,~nanx), t(nanx));
plot(xax(start:ende),avg_for_lvl(l,start:ende),'Color',col(ccnt,:));
hold on
end
% yline(levels);
xlabel('Samples');
ylabel('Amplitude');
ylim([-3 3]);
end
end
end

View File

@@ -0,0 +1,193 @@
if 0
% A) RUN FULL LOOP
M_format = [2,4,6,8];
snr = 10:25;
else
% B) RUN FOR DEBUG AND TEST
M_format = 4;
snr = 20;
end
for m = 1:length(M_format)
% --- Parameters ---
M = M_format(m); % PAM order (e.g., 2,4,8)
Nsym = 1e5; % number of symbols
h = [1, 0.5, 0.2]; % Impulse response to remove
b = log2(M);
if M == 6 b = 5; end
rng(1);
bits_tx = logical(randi([0 1], Nsym, b, 'uint8'));
tx_symbols = pammap(bits_tx,M);
if M == 6
states = unique(tx_symbols);
pam6transitions = combvec(states',states')'; % pam6transitions =
bitmapping = pamdemap(reshape(pam6transitions',1,[])',M);
else
bitmapping = pamdemap(unique(tx_symbols),M);
end
scaling = sqrt(sum(unique(tx_symbols).^2)/numel(unique(tx_symbols)));
tx_symbols = tx_symbols ./ scaling;
% apply impulse response to signal
y_filt = filter(h, 1, tx_symbols);
for s = 1:length(snr)
% apply noise
y = awgn(y_filt,snr(s),"measured",1);
% apply ml-MLSE
adaptive_mu = 0;
mu_lms = 0.15;
ml_mlse_equalizer = ml_mlse_pam("epochs_tr",50,"epochs_dd",1,"len_tr",length(y)/2,...
"mu_dd",mu_lms,"mu_tr",mu_lms,"order",11,"sps",1,...
"L",2,"delta",4,"adaptive_mu",adaptive_mu);
[ml_mlse_estimate,~] = ml_mlse_equalizer.process(y,tx_symbols);
rx_symbols = ml_mlse_estimate .* scaling;
bits_rx = pamdemap(rx_symbols,M);
BER_ml(m,s) = nnz(bits_tx ~= bits_rx) / numel(bits_tx);
fprintf('BER = %.2e \n', BER_ml(m,s));
% apply bcjr
BCJR = bcjr_pam("DIR",h,"duobinary_output",0,"M",M,"trellis_states",unique(tx_symbols));
[viterbi_estimate,LLR,GMI(m,s)] = BCJR.process(y,tx_symbols,bits_tx,bitmapping);
% decode LLR's
bits_LLR = LLR > 0;
% demap viterbi symbols sequence
rx_symbols = viterbi_estimate .* scaling;
bits_rx = pamdemap(rx_symbols,M);
% BER calc
BER_vit(m,s) = nnz(bits_tx ~= bits_LLR) / numel(bits_tx);
fprintf('BER LLR = %.2e \n', BER_vit(m,s));
BER_llr(m,s) = nnz(bits_tx ~= bits_rx) / numel(bits_tx);
fprintf('BER = %.2e \n', BER_llr(m,s));
end
end
%%
figure();hold on
for m = 1:length(M_format)
p=plot(snr,BER_llr(m,:),'DisplayName',sprintf('Viterbi: PAM %d',M_format(m)));
plot(snr,BER_ml(m,:),'DisplayName',sprintf('ML-Based: PAM %d',M_format(m)),'LineStyle',':','Color',p.Color);
end
ylabel('BER');
xlabel('SNR')
title('BER vs. SNR');
set(gca, 'XScale', 'linear', ...
'YScale', 'log', ...
'TickLabelInterpreter', 'latex', ...
'FontSize', 11);
%%
figure();hold on
for m = 1:length(M_format)
plot(snr,GMI(m,:),'DisplayName',sprintf('GMI PAM %d',M_format(m)))
end
ylabel('GMI');
xlabel('SNR')
title('GMI vs. SNR');
set(gca, 'XScale', 'linear', ...
'YScale', 'linear', ...
'TickLabelInterpreter', 'latex', ...
'FontSize', 11);
function symbols = pammap(bits,M)
bits = logical(bits);
if M == 2
symbols = bits;
elseif M == 4
symbols= 2*bits(:,1) + (bits(:,1)==bits(:,2));
symbols=2*symbols-3;
elseif M == 6
m = 1;
if size(bits,2)>size(bits,1)
bits = bits'; %vector aufrecht stellen
end
bits = reshape(bits',1,[])';
thres = [-3 5;-1 5;-3 -5;-1 -5;-5 3;-5 1;-5 -3;-5 -1;-1 3;-1 1;-1 -3;-1 -1;-3 3;-3 1;-3 -3;-3 -1;3 5;1 5;3 -5;1 -5;5 3;5 1;5 -3;5 -1;1 3;1 1;1 -3;1 -1;3 3;3 1;3 -3;3 -1];
% LUT based mapping
for k = 1:5:fix(length(bits)/5)*5
symbols(m:m+1,1) = thres(bin2dec(int2str(bits(k:k+4)'))+1,:);
m = m+2;
end
elseif M == 8
x1 = bits(:,1);
x2 = (bits(:,1)==bits(:,3));
x3 = x2~=bits(:,2);
symbols = 4*x1 + 2*x2 + x3;
symbols=2*symbols-7;
end
end
function bits = pamdemap(symbols,M)
if M == 2
thres=0;
elseif M == 4
thres=[-2,0,2];
elseif M == 6
thres = [-3 5;-1 5;-3 -5;-1 -5;-5 3;-5 1;-5 -3;-5 -1;-1 3;-1 1;-1 -3;-1 -1;-3 3;-3 1;-3 -3;-3 -1;3 5;1 5;3 -5;1 -5;5 3;5 1;5 -3;5 -1;1 3;1 1;1 -3;1 -1;3 3;3 1;3 -3;3 -1];
elseif M == 8
thres=-6:2:6;
end
if M ~= 6
symbols = symbols';
a = squeeze(repmat(real(symbols),[1 1 length(thres)])); %Eingangssignal in 3 spalten
b = squeeze(repmat(reshape(thres(:).',[1 1 length(thres)]),[1 length(symbols) 1])); %Threshold in 3 Spalten
comp_real = a > b; %check for each symbol/ sampling if it exeeds the obj.thresholdseshold 1, 2 or 3
comp_real=repmat(real(symbols),[1 1 length(thres)]) > repmat(reshape(thres(:).',[1 1 length(thres)]),[1 length(symbols) 1]);
s1=size(comp_real,1);
s2=size(comp_real,2);
end
if M == 2
data_out=abs(comp_real(:,:,1));
elseif M == 4
data_out=[comp_real(:,:,2); ones(s1,s2) - comp_real(:,:,1) + comp_real(:,:,3)];
elseif M == 6
if size(symbols,2) > 1
symbols = symbols.';
end
if length(symbols)/2 ~= round(length(symbols)/2)
symbols = [symbols;0];
end
m = 1;
for n = 1:2:length(symbols)
dist = sqrt((symbols(n)-thres(:,1)).^2+(symbols(n+1)-thres(:,2)).^2);
[~,dd_idx] = min(dist);
% dec_out(n:n+1) = LUT(dd_idx,:);
data_out(m:m+4) = bitget(dd_idx-1,5:-1:1);
m = m+5;
end
data_out = reshape(data_out',5,[]);
elseif M == 8
data_out=[comp_real(:,:,4);
comp_real(:,:,1)-comp_real(:,:,3)+comp_real(:,:,5)-comp_real(:,:,7);
1-comp_real(:,:,2)+comp_real(:,:,6)];
end
bits = data_out';
end

View File

@@ -0,0 +1,473 @@
classdef ml_mlse_pam < handle
% ALGORITHM DESCRIBED IN:
% W. Lanneer and Y. Lefevre, Machine Learning-Based Pre-Equalizers for
% Maximum Likelihood Sequence Estimation in High-Speed PONs,
% in 2023 31st European Signal Processing Conference
% Further ML Refs:
% https://machinelearningmastery.com/cross-entropy-for-machine-learning/
% https://docs.pytorch.org/docs/stable/generated/torch.nn.CrossEntropyLoss.html
% The central idea is to overcome the (white-) noise assumption within the previously described
% Viterbi algorithm, more precisely a closed-loop optimization is proposed that finds a suitable
% filter-set to directly compute the branch metrics c_k (s,s^' ). These can directly be used to
% carry out the conventional Viterbi algorithm. The system consists of S^L S=F linear FIR filters,
% combined with one bias coefficient respectively. These filters take the received input samples to
% compute the branch metrics estimates (c_k ) ̂(s,s^' ) according toThe central idea is to overcome
% the (white-) noise assumption within the previously described Viterbi algorithm, more precisely
% a closed-loop optimization is proposed that finds a suitable filter-set to directly compute the
% branch metrics c_k (s,s^' ). These can directly be used to carry out the conventional Viterbi
% algorithm. The system consists of S^L S=F linear FIR filters, combined with one bias coefficient
% respectively. These filters take the received input samples to compute the branch metrics
% estimates. Finally, the usual Viterbi is carried out...
% Recommended Settings and some findings:
% Requires many training epochs. According to ML people, 100,200 or
% even up to 1000 epochs are normal for ML-convergence
% The mu parameter _can_ be adaptive - using the cross entropy and when
% analyzing the isolated training it looks very promisig. However, is
% later use I found this is not as stable as a fixed learning rate.
% mu = 0.1 worked good for me
% Longer orders/ filter length are not always better. For me order=11
% was good.
% Delay factor (delta) is good when the order is also increased. With
% order = 11, a delta of =4 shows good results
properties
sps % usually 2
order
e
e_tr
error
len_tr
mu_tr
epochs_tr
% dd_mode -> not implemented here!
mu_dd %weight update in dd mode
epochs_dd
adaptive_mu
constellation
L %viterbi memory length
alpha
DIR
DIR_flip
trellis_states
traceback_depth
S
Nf
delta
nStates
nFeasible
combs
first_sym
last_sym
valid
valid_to_idx
valid_from_idx
w
nbiasTerms
true_to_state_idx
state_dict % containers.Map: key(sequence)->state index
key_fmt = '%.8g_'; % key format for sequence strings
nSym % |constellation|
ber = []
ce = ones(1,1);
end
methods
function obj = ml_mlse_pam(options)
arguments(Input)
options.sps = 2;
options.order = 15;
options.len_tr = 4096;
options.mu_tr = 0;
options.epochs_tr = 5;
% options.dd_mode = 1;
options.mu_dd = 1e-5;
options.epochs_dd = 5;
options.adaptive_mu = 1;
options.delta = 0;
options.traceback_depth = 1024;
options.L = 1
end
fn = fieldnames(options);
for n = 1:numel(fn)
obj.(fn{n}) = options.(fn{n});
end
obj.e = zeros(obj.order,1);
obj.error = 0;
end
function [x_viterbi,x_ref] = process(obj, X, D)
% actual processing of the signal (steps 1. - 3.)
% 1 normalize RMS
X = X./rms(X);
% Use sorted constellation for deterministic mapping
obj.constellation = sort(unique(D),'ascend');
obj.nSym = numel(obj.constellation);
if length(X)/length(D) ~= obj.sps
warning('Signal length does not fit to reference!');
end
% ==============================================================
% INITIALIZATION
% ==============================================================
% --- Parameters
obj.S = numel(obj.constellation); % Num of Symbols
obj.Nf = obj.order*obj.sps; % filter length (auto adapt for n-SPS...)
obj.nStates = obj.S^obj.L; % S^L states
obj.nFeasible = obj.nStates*obj.S; % S^(L+1) feasible states
% --- Trellis mapping
obj.trellis_states = reshape(obj.constellation,1,[]); % make row vector
pre_comb_mat = repmat(obj.trellis_states, obj.L, 1);
pre_comb_cell = mat2cell(pre_comb_mat, ones(1,obj.L), size(pre_comb_mat,2));
obj.combs = fliplr(combvec(pre_comb_cell{:}).'); % rows: states, columns: [x_k, x_{k-1}, ...]
obj.first_sym = obj.combs(:,1);
obj.last_sym = obj.combs(:,end);
obj.nStates = size(obj.combs,1);
% --- Valid transitions; adapted from the old Viterbi in
% Move-It where the "noise free received" states are calculated
% using the same loop and clause
obj.valid = false(obj.nStates);
for from = 1:obj.nStates
for to = 1:obj.nStates
if all(obj.combs(to,2:end) == obj.combs(from,1:end-1))
obj.valid(to,from) = true;
end
end
end
[obj.valid_to_idx, obj.valid_from_idx] = find(obj.valid);
% Allocate vectors and weights
% !! IF SHAPE FIT, then we already have smth there an we want
% to start with the existing filter-set (saves comp. time/ or to test fixed filter on new data)
obj.nbiasTerms = 1;
if isempty(obj.w) || any(size(obj.w) ~= [obj.Nf+obj.nbiasTerms,obj.nFeasible])
obj.w = zeros(obj.Nf+obj.nbiasTerms,obj.nFeasible); % filter weights per transition + bias tap
% obj.w = randn(obj.Nf+obj.nbiasTerms,obj.nFeasible);
end
% This is a weird workaround - but it works and is much faster
% than findig the state indices every time:
% Precompute dictionary for fast state lookup (sequence -> state)
keys = cell(obj.nStates,1);
for i = 1:obj.nStates
keys{i} = obj.seq_key(obj.combs(i,:)); % combs row is already [x_k, x_{k-1}, ...]
end
obj.state_dict = containers.Map(keys, 1:obj.nStates);
% ==============================================================
% TRAINING
% ==============================================================
n = obj.len_tr;
training = 1;
obj.equalize(X, D,obj.mu_tr,obj.epochs_tr,n,training);
obj.e_tr = obj.e;
% ==============================================================
% Testing; Fixed Mode
% ==============================================================
n = length(X);
training = 0;
obj.mu_dd = obj.mu_tr; %For now no DD mode is implemented...
[x_viterbi,x_ref]=obj.equalize(X, D,obj.mu_dd,obj.epochs_dd,n,training);
end
function [y,y_ref] = equalize(obj,x,d,mu,epochs,N,training)
% ==============================================================
% ML-Based Branch Metric Estimation + Viterbi
% ==============================================================
debug = 1;
showPlots = 1;
nSymbols = ceil(N/obj.sps);
for epoch = 1:epochs
% state metrics (log-domain costs): keep as column [nStatesx1]
pm = zeros(obj.nStates,1);
v_tilde = zeros(1,obj.nFeasible);
pred = zeros(nSymbols, obj.nStates);
pm_sto = nan(obj.nStates, nSymbols);
CE_accum = 0;
% START IDX can be randomized during training, but this
% requires some testing - it is not better, maybe a
% solutiuon is to use the same window for 10-20 epochs
% and then switch to another window
% for now: simply use the first parts of the signal for
% training and also for testing... not "the
randomize_training_window = 0;
if randomize_training_window && training
max_start = length(x) - ( (ceil(N/obj.sps)-1)*obj.sps + 1 );
max_start = max(1, max_start); % safety
start_sample = randi([1, max_start], 1); %rnd training; not really good
else
start_sample = 1;
end
end_sample = start_sample + (ceil(N/obj.sps)-1)*obj.sps;
start_symbol = 1 + floor((start_sample - 1)/obj.sps); % ABSOLUTE symbol index
symbol = 0;
for sample = start_sample:obj.sps:end_sample
symbol = symbol + 1;
k = symbol;
sym_idx = start_symbol + (symbol - 1);
% input signal window y_k; delayed by delta
i1 = sample - obj.Nf + 1 + obj.delta;
i2 = sample + obj.delta;
buf = x(max(1,i1):min(length(x),i2));
padL = max(0,1 - i1);
padR = max(0,i2 - length(x));
yk = [zeros(padL,1); buf(:); zeros(padR,1)]; % Nfx1
yk = [yk;ones( obj.nbiasTerms,1)];
% Apply Filter; Predict branch metrics for all feasible transitions: c_hat
% Formula (8)
c_hat = (yk.' * obj.w); % [1xnFeasible]
c_hat = c_hat.'; % [nFeasiblex1]
% Extended path metrics: v_tilde = pm(from) + c_hat
v_tilde = pm(obj.valid_from_idx) + c_hat; % [nFeasiblex1]
% ===== Cross Entropy Loss Update =====
if 1 %training
% --- allocate storage once
if epoch == 1 && symbol == 1
obj.true_to_state_idx = ones(ceil(N/obj.sps),1,'uint32');
end
% --- previous "to" becomes current "from"
if symbol > 1
true_from_state_idx = obj.true_to_state_idx(symbol-1);
else
true_from_state_idx = 1;
end
% --- compute or reuse "to" state
if epoch == 1
% only compute in first epoch
if sym_idx >= obj.L
key_to = obj.seq_key(flip(d(sym_idx-obj.L+1 : sym_idx)));
if isKey(obj.state_dict, key_to)
obj.true_to_state_idx(symbol) = obj.state_dict(key_to);
else
obj.true_to_state_idx(symbol) = true_from_state_idx;
end
else
obj.true_to_state_idx(symbol) = true_from_state_idx;
end
end
% --- ensure valid (from,to)
dirac = zeros(obj.nFeasible,1);
mask = obj.valid_from_idx==true_from_state_idx & ...
obj.valid_to_idx == obj.true_to_state_idx(symbol);
if any(mask)
dirac(mask) = 1;
else
idx = find(obj.valid_from_idx==true_from_state_idx,1,'first');
dirac(idx) = 1;
obj.true_to_state_idx(symbol) = obj.valid_to_idx(idx);
end
% softmax over -v_tilde (numerically safe shift)
v_shift = -(v_tilde - min(v_tilde)); % shift to small positive numbers
v_shift = min(v_shift, 100); % clamp exponent argument to avoid extreme numbers/ overflow (exp(50)=5e21)
expv = exp(v_shift);
p = expv ./ (sum(expv) + eps);
% Cross entropy
CE_symbol(symbol) = -log(p(dirac==1) + eps);
if sym_idx > obj.L
CE_smooth(symbol) = 0.01*CE_symbol(symbol) + 0.99*CE_smooth(symbol-1);
else
if epoch > 1
CE_smooth(symbol) = obj.ce(end); %stitch together ce from last epoch? or =1 for very first round?!
else
CE_smooth(symbol) = CE_symbol(symbol);
end
end
CE_accum = CE_symbol(symbol) + CE_accum;
% Formula (10)
% gradient term (t - p)
dmp = (dirac - p)'; % 1xnFeasible
% Formula (10)
dL_Dw = (yk) .* dmp;
% Start updates only when the symbol index has L history
if sym_idx >= obj.L
if obj.adaptive_mu
mu_eff = CE_smooth(sym_idx);
mu_eff = max(min(mu_eff, 0.2), 1e-4);
else
mu_eff = mu;
end
% see Algorithm 1 in paper
obj.w = obj.w - mu_eff .* dL_Dw; % (Nf+1)xnFeasible
end
% if debug && epoch > 2
% figure(100);
% subplot(4,1,1);
% heatmap(p');
% title('Probs')
% subplot(4,1,2);
% heatmap(dmp);
% title('Update')
% subplot(4,1,3);
% heatmap(dL_Dw);
% title('Update')
% subplot(4,1,4);
% heatmap(bj.w);
% title('Update')
%
% end
end
% Compare-Select
v_tilde_mat = inf(obj.nStates, obj.nStates);
v_tilde_mat(obj.valid) = v_tilde; %reshapes to usual (from x to) matrix
[pm_next, pred(k,:)] = min(v_tilde_mat, [], 2); %here, calc min for each column
% re-center, otherwise it will overflow
pm_next = pm_next - min(pm_next);
pm = pm_next;
pm_sto(:,symbol) = pm;
end
% Traceback
[~, s_end] = min(pm);
viterbi_path = zeros(symbol,1);
viterbi_path(symbol) = s_end;
for n = symbol:-1:2
viterbi_path(n-1) = pred(n, viterbi_path(n));
end
% cut here to have the same indices when shuffling/
% starting the start_symbol indx != 1
y_ref = d(start_symbol:end);
y = obj.first_sym(viterbi_path);
% Debug and Plots
if debug && training
sym_start = start_symbol;
sym_end = start_symbol + symbol - 1;
ref_slice = d(sym_start : sym_end);
err = sum(y ~= ref_slice(1:numel(y)));
try %works with demapper, not provided in Deliverable
ref_bits = PAMmapper(obj.S,0).demap(ref_slice);
eq_bits = PAMmapper(obj.S,0).demap(y);
[~, ~, ber, ~] = calc_ber(ref_bits, eq_bits, "skip_front", 10, "skip_end", 10, "returnErrorLocation", 1);
fprintf('Epoch: %d - BER: %.1e \n',epoch, ber);
obj.ber(epoch) = ber;
berlabel = 'BER';
catch %fallback ser
ser = err./length(y);
fprintf('Epoch: %d - SER: %.1e \n',epoch, ser);
obj.ber(epoch) = ser;
berlabel = 'BER';
end
obj.ce(epoch) = CE_accum./symbol;
if showPlots
figure(10);clf
subplot(3,2,1:2);
heatmap(obj.w);
title('Filter')
subplot(3,2,3);
v_tildemat = NaN(obj.nStates, obj.nStates);
v_tildemat(obj.valid) = v_tilde; % log-domain scores
heatmap(v_tildemat);
title('Extended Path Metrics v-tilde')
subplot(3,2,4);
scatter(1:symbol,pm_sto,1,'.')
title('Path Metric Winners v')
subplot(3,2,5);hold on
scatter(1:symbol,CE_symbol,1,'.');
scatter(1:symbol,CE_smooth,1,'.')
title('Cross Entropy')
ylabel('Cross Entropy')
xlabel('Symbols')
subplot(3,2,6); hold on
% Left y-axis: Cross Entropy
yyaxis left
scatter(1:length(obj.ce), obj.ce, 10, 's', 'filled')
ylabel('Cross Entropy')
% Right y-axis: BER
yyaxis right
scatter(1:length(obj.ber), obj.ber, 10, 'd', 'filled')
set(gca, 'YScale', 'log')
ylabel(berlabel)
xlim([1, epochs])
xlabel('Epoch')
title('Cross Entropy // BER')
grid on
drawnow
end
end
end
end
end
methods (Access=private)
function k = seq_key(obj, seq)
% Build a stable key string for a sequence row vector in the *same order as combs rows* ([x_k, x_{k-1}, ...])
% Use rounding via sprintf to avoid floating-point issues.
% seq must be a row vector.
k = sprintf(obj.key_fmt, seq);
end
end
end

View File

@@ -5,14 +5,14 @@ ber_dbtgt = [];
ber_ml = []; ber_ml = [];
mlse = 1; mlse = 1;
dbtgt = 1; dbtgt = 0;
duob_mode = db_mode.no_db;
baudrates = [136:8:224].*1e9; baudrates = [136:8:224].*1e9;
parfor i = 1:length(baudrates) for i = 1:length(baudrates)
rop = -8; rop = -8;
M = 4; M = 4;
[Rx_sig_2sps_v1, Symbols_v1, Tx_bits_v1] = standard_link_model("M",M,"fsym",baudrates(i),"rop",rop,"laser_linewidth",1300,"link_length_m",0,"random_key",1,"apply_pulsef",0); [Rx_sig_2sps_v1, Symbols_v1, Tx_bits_v1] = standard_link_model("M",M,"fsym",baudrates(i),"rop",rop,"laser_linewidth",1310,"link_length_m",0,"random_key",1,"apply_pulsef",1);
% [Rx_sig_2sps_v2, Symbols_v2, Tx_bits_v2] = standard_link_model("M",M,"fsym",200e9,"rop",rop,"laser_linewidth",1300,"link_length_m",0,"random_key",2); % [Rx_sig_2sps_v2, Symbols_v2, Tx_bits_v2] = standard_link_model("M",M,"fsym",200e9,"rop",rop,"laser_linewidth",1300,"link_length_m",0,"random_key",2);
% [Rx_sig_2sps_v3, Symbols_v3, Tx_bits_v3] = standard_link_model("M",M,"fsym",200e9,"rop",rop,"laser_linewidth",1300,"link_length_m",0,"random_key",3); % [Rx_sig_2sps_v3, Symbols_v3, Tx_bits_v3] = standard_link_model("M",M,"fsym",200e9,"rop",rop,"laser_linewidth",1300,"link_length_m",0,"random_key",3);
@@ -25,6 +25,7 @@ parfor i = 1:length(baudrates)
eq_ = EQ("Ne",ffe_order,"Nb",[0,0,0],"training_length",2^13,"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); eq_ = EQ("Ne",ffe_order,"Nb",[0,0,0],"training_length",2^13,"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);
pf_ = Postfilter("ncoeff",pf_ncoeffs,"useBurg",1); pf_ = Postfilter("ncoeff",pf_ncoeffs,"useBurg",1);
mlse_ = MLSE("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels,'scale_mode',2,'trellis_exclusion',0,'trellis_state_mode',2,'debug',0,'DIR',pf_.coefficients); mlse_ = MLSE("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels,'scale_mode',2,'trellis_exclusion',0,'trellis_state_mode',2,'debug',0,'DIR',pf_.coefficients);
[ffe_results, mlse_results] = vnle_postfilter_mlse(eq_, pf_, mlse_, M, Rx_sig_2sps_v1, Symbols_v1, Tx_bits_v1, ... [ffe_results, mlse_results] = vnle_postfilter_mlse(eq_, pf_, mlse_, M, Rx_sig_2sps_v1, Symbols_v1, Tx_bits_v1, ...
"precode_mode", duob_mode,... "precode_mode", duob_mode,...
'showAnalysis', 0, ... 'showAnalysis', 0, ...
@@ -33,6 +34,9 @@ parfor i = 1:length(baudrates)
ber_ffe(i) = ffe_results.metrics.BER; ber_ffe(i) = ffe_results.metrics.BER;
ber_mlse(i) = mlse_results.metrics.BER; ber_mlse(i) = mlse_results.metrics.BER;
fprintf('BER FFE: %.2e \n',ber_ffe(i));
fprintf('BER MLSE: %.2e \n',ber_mlse(i));
end end
@@ -69,11 +73,14 @@ parfor i = 1:length(baudrates)
%% RUN ML-Based MLSE %% RUN ML-Based MLSE
mu_lms = 0.15; mu_lms = 0.15;
ml_mlse_equalizer = ML_MLSE("epochs_tr",30,"epochs_dd",1,"len_tr",2^15,... ml_mlse_equalizer = ML_MLSE("epochs_tr",50,"epochs_dd",1,"len_tr",2^16,...
"mu_dd",mu_lms,"mu_tr",mu_lms,"order",5,"sps",1,... "mu_dd",mu_lms,"mu_tr",mu_lms,"order",4,"sps",2,...
"traceback_depth",128,"L",3,"delta",0); "traceback_depth",128,"L",2,"delta",0);
[y_ml_mlse,~] = ml_mlse_equalizer.process(y_white,Symbols_v1); ml_mlse_equalizer.mu_tr = 0.005;
ml_mlse_equalizer.epochs_tr = 2;
ml_mlse_equalizer.epochs_dd = 1;
[y_ml_mlse,~] = ml_mlse_equalizer.process(Rx_sig_2sps_v1,Symbols_v1);
ml_mlse_bits = PAMmapper(M, 0, "eth_style", 0).demap(y_ml_mlse); ml_mlse_bits = PAMmapper(M, 0, "eth_style", 0).demap(y_ml_mlse);
[~, errors, ber_ml(i), errpos] = calc_ber(ml_mlse_bits.signal, Tx_bits_v1.signal, "skip_front", 10, "skip_end", 10, "returnErrorLocation", 1); [~, errors, ber_ml(i), errpos] = calc_ber(ml_mlse_bits.signal, Tx_bits_v1.signal, "skip_front", 10, "skip_end", 10, "returnErrorLocation", 1);
fprintf('ML MLSE BER: %.2e \n',ber_ml(i)); fprintf('ML MLSE BER: %.2e \n',ber_ml(i));

View File

@@ -0,0 +1,30 @@
%% read_wpd_csv.m
% Minimal importer for WebPlotDigitizer multi-curve CSV
filename = 'wpd_datasets.csv'; % <-- set your file path here
T = readtable(filename);
% Read header row manually
fid = fopen(filename);
hdr1 = strsplit(strrep(fgetl(fid), '"', ''), ','); % curve names
hdr2 = strsplit(strrep(fgetl(fid), '"', ''), ','); % X/Y header row
fclose(fid);
% Extract unique curve names
names = hdr1(~cellfun('isempty',hdr1));
% Create struct for each curve
mii = struct();
for i = 1:numel(names)
base = matlab.lang.makeValidName(strrep(names{i},' ','_'));
xi = 2*(i-1)+1; % X column
yi = xi+1; % Y column
mii.(base).X = T{:,xi};
mii.(base).Y = T{:,yi};
% also create workspace variable "name_wpd"
assignin('base',[base '_wpd'], mii.(base));
end
disp('Imported datasets:');
disp(fieldnames(mii));

View File

@@ -1,95 +1,139 @@
clear; clc;
ber_ffe = []; M = 4;
ber_mlse = []; randkey = 1;
ber_dbtgt = []; duob_mode = db_mode.no_db;
ber_ml = [];
mlse = 1; mlse = 1;
dbtgt = 1; dbtgt = 1;
rops = linspace(-15,-5,12); baudrates = 180e9:2e9:220e9; % outer loop
parfor i = 1:length(rops) rops = linspace(-10,0,12); % inner sweep
FEC_thr = 3.8e-3; % BER target
rop = rops(i);
M = 4; % --- allocate results
[Rx_sig_2sps_v1, Symbols_v1, Tx_bits_v1] = standard_link_model("M",M,"fsym",224e9,"rop",rop,"laser_linewidth",1300,"link_length_m",0,"random_key",1); reqROP_FFE = nan(size(baudrates));
% [Rx_sig_2sps_v2, Symbols_v2, Tx_bits_v2] = standard_link_model("M",M,"fsym",200e9,"rop",rop,"laser_linewidth",1300,"link_length_m",0,"random_key",2); reqROP_MLSE = nan(size(baudrates));
% [Rx_sig_2sps_v3, Symbols_v3, Tx_bits_v3] = standard_link_model("M",M,"fsym",200e9,"rop",rop,"laser_linewidth",1300,"link_length_m",0,"random_key",3); reqROP_DBTGT = nan(size(baudrates));
reqROP_ML_MLSE2 = nan(size(baudrates));
%% FFE + MLSE reqROP_ML_MLSE3 = nan(size(baudrates));
if mlse
pf_ncoeffs = 1; %% ====================== OUTER LOOP ======================
ffe_order = [50, 0, 0]; for b = 1:numel(baudrates)
mu_ffe = [0.0001, 0.0008, 0.001]; baudrate = baudrates(b);
mu_dfe = 0.0004; fprintf('\n=== %.0f GBd ===\n', baudrate/1e9);
eq_ = EQ("Ne",ffe_order,"Nb",[0,0,0],"training_length",2^13,"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);
pf_ = Postfilter("ncoeff",pf_ncoeffs,"useBurg",1); ber_ffe = nan(size(rops));
mlse_ = MLSE("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels,'scale_mode',2,'trellis_exclusion',0,'trellis_state_mode',2,'debug',0,'DIR',pf_.coefficients); ber_mlse = nan(size(rops));
[ffe_results, mlse_results] = vnle_postfilter_mlse(eq_, pf_, mlse_, M, Rx_sig_2sps_v1, Symbols_v1, Tx_bits_v1, ... ber_dbtgt = nan(size(rops));
"precode_mode", duob_mode,... ber_ml2 = nan(size(rops));
'showAnalysis', 0, ... ber_ml3 = nan(size(rops));
"postFFE", [],...
"eth_style_symbol_mapping", 0); %% -------- inner ROP loop --------
for i = 1:length(rops)
ber_ffe(i) = ffe_results.metrics.BER; rop = rops(i);
ber_mlse(i) = mlse_results.metrics.BER;
end [Rx_sig_2sps_v1, Symbols_v1, Tx_bits_v1] = standard_link_model( ...
"M",M,"fsym",baudrate,"rop",rop,"laser_linewidth",1310, ...
"link_length_m",0,"random_key",1);
%% FFE DB tgt. + MLSE
if dbtgt
mlse_db_ = MLSE("DIR",[1,1],"duobinary_output",0,"M",M,"trellis_states",PAMmapper(M,0).levels,'scale_mode',2,'trellis_exclusion',0,'trellis_state_mode',3);
ffe_order = [50, 0, 0];
mu_ffe = [0.0001, 0.0008, 0.001];
mu_dfe = 0.0004;
eq_ = EQ("Ne",ffe_order,"Nb",[0,0,0],"training_length",2^13,"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, Rx_sig_2sps_v1, Symbols_v1, Tx_bits_v1, ...
"precode_mode", duob_mode, ...
'showAnalysis', 0,...
"postFFE", []);
ber_dbtgt(i) = dbt_results.metrics.BER;
end
%% RUN ML-Based MLSE
mu_lms = 0.15;
ml_mlse_equalizer = ML_MLSE("epochs_tr",30,"epochs_dd",1,"len_tr",2^14,...
"mu_dd",mu_lms,"mu_tr",mu_lms,"order",4,"sps",2,...
"traceback_depth",128,"L",2,"delta",0);
[y_ml_mlse,~] = ml_mlse_equalizer.process(Rx_sig_2sps_v1,Symbols_v1); %% FFE + MLSE
ml_mlse_bits = PAMmapper(M, 0, "eth_style", 0).demap(y_ml_mlse); if mlse
[~, errors, ber_ml(i), errpos] = calc_ber(ml_mlse_bits.signal, Tx_bits_v1.signal, "skip_front", 10, "skip_end", 10, "returnErrorLocation", 1); pf_ncoeffs = 1;
fprintf('ML MLSE BER: %.2e \n',ber_ml(i)); ffe_order = [50, 0, 0];
mu_ffe = [0.0001, 0.0008, 0.001];
% figure(11);hold on mu_dfe = 0.0004;
% plot(1:numel(ml_mlse_equalizer.ber),ml_mlse_equalizer.ber); eq_ = EQ("Ne",ffe_order,"Nb",[0,0,0],"training_length",2^13, ...
% beautifyBERplot; "training_loops",5,"dd_loops",5,"K",2,"DCmu",0.005, ...
% xlim([1,numel(ml_mlse_equalizer.ber)]) "DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0, ...
"plotfinal",0,"ideal_dfe",1);
pf_ = Postfilter("ncoeff",pf_ncoeffs,"useBurg",1);
mlse_ = MLSE("duobinary_output",0,'M',M, ...
'trellis_states',PAMmapper(M,0).levels,'scale_mode',2, ...
'trellis_exclusion',0,'trellis_state_mode',2,'debug',0, ...
'DIR',pf_.coefficients);
[ffe_results, mlse_results] = vnle_postfilter_mlse(eq_, pf_, mlse_, M, ...
Rx_sig_2sps_v1, Symbols_v1, Tx_bits_v1, ...
"precode_mode", duob_mode,'showAnalysis', 0, "postFFE", [], ...
"eth_style_symbol_mapping", 0);
ber_ffe(i) = ffe_results.metrics.BER;
ber_mlse(i) = mlse_results.metrics.BER;
end
%% FFE + duobinary target MLSE
if dbtgt
mlse_db_ = MLSE("DIR",[1,1],"duobinary_output",0,"M",M, ...
"trellis_states",PAMmapper(M,0).levels,'scale_mode',2, ...
'trellis_exclusion',0,'trellis_state_mode',3);
ffe_order = [50, 0, 0];
mu_ffe = [0.0001, 0.0008, 0.001];
mu_dfe = 0.0004;
eq_ = EQ("Ne",ffe_order,"Nb",[0,0,0],"training_length",2^13, ...
"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, Rx_sig_2sps_v1, ...
Symbols_v1, Tx_bits_v1, "precode_mode", duob_mode, ...
'showAnalysis', 0, "postFFE", []);
ber_dbtgt(i) = dbt_results.metrics.BER;
end
%% ML-based MLSE (L=2)
mu_ml = 0.1; training_epochs = 100;
ml_mlse_equalizer = ML_MLSE("epochs_tr",training_epochs,"epochs_dd",1, ...
"len_tr",2^16,"mu_dd",mu_ml,"mu_tr",mu_ml,"order",11,"sps",2, ...
"traceback_depth",128,"L",2,"delta",4,"adaptive_mu",0);
[y_ml_mlse,y_ref] = ml_mlse_equalizer.process(Rx_sig_2sps_v1,Symbols_v1);
ref_bits = PAMmapper(M,0).demap(y_ref);
ml_bits = PAMmapper(M,0).demap(y_ml_mlse);
[~,~,ber_ml2(i)] = calc_ber(ml_bits.signal, ref_bits.signal, ...
"skip_front",10,"skip_end",10);
%% ML-based MLSE (L=3)
ml_mlse_equalizer = ML_MLSE("epochs_tr",training_epochs,"epochs_dd",1, ...
"len_tr",2^16,"mu_dd",mu_ml,"mu_tr",mu_ml,"order",11,"sps",2, ...
"traceback_depth",128,"L",3,"delta",4,"adaptive_mu",0);
[y_ml_mlse,y_ref] = ml_mlse_equalizer.process(Rx_sig_2sps_v1,Symbols_v1);
ref_bits = PAMmapper(M,0).demap(y_ref);
ml_bits = PAMmapper(M,0).demap(y_ml_mlse);
[~,~,ber_ml3(i)] = calc_ber(ml_bits.signal, ref_bits.signal, ...
"skip_front",10,"skip_end",10);
end % ROP loop
%% --- find required ROP (FEC crossing)
reqROP_FFE(b) = interp_fec_cross(rops, ber_ffe, FEC_thr);
reqROP_MLSE(b) = interp_fec_cross(rops, ber_mlse, FEC_thr);
reqROP_DBTGT(b) = interp_fec_cross(rops, ber_dbtgt, FEC_thr);
reqROP_ML_MLSE2(b) = interp_fec_cross(rops, ber_ml2, FEC_thr);
reqROP_ML_MLSE3(b) = interp_fec_cross(rops, ber_ml3, FEC_thr);
% --- diagnostic
fprintf('Baud %.0f GBd: FFE %.1f, MLSE %.1f, DB %.1f, ML2 %.1f, ML3 %.1f\n', ...
baudrate/1e9, reqROP_FFE(b), reqROP_MLSE(b), reqROP_DBTGT(b), ...
reqROP_ML_MLSE2(b), reqROP_ML_MLSE3(b));
end end
%% %% ====================== PLOT REQUIRED ROP ======================
cols = cbrewer2('Set1',8);
figure(3); hold on; colFFE = cols(1,:);
if mlse colMLSE = cols(2,:);
plot(rops,ber_ffe,'DisplayName','FFE'); colDBTGT = cols(4,:);
plot(rops,ber_mlse,'DisplayName','MLSE'); colML_MLSE = cols(3,:);
end
if dbtgt
plot(rops,ber_dbtgt,'DisplayName','DB tgt');
end
plot(rops,ber_ml,'DisplayName','ML-MLSE');
beautifyBERplot;
legend
figure(); hold on
plot(baudrates/1e9, reqROP_FFE, '-o','Color',colFFE, 'DisplayName','FFE');
plot(baudrates/1e9, reqROP_MLSE, '-s','Color',colMLSE, 'DisplayName','FFE+PF+MLSE');
plot(baudrates/1e9, reqROP_DBTGT, '--^','Color',colDBTGT, 'DisplayName','DB tgt. MLSE');
plot(baudrates/1e9, reqROP_ML_MLSE2, '-v','Color',colML_MLSE, 'DisplayName','ML-based MLSE (L=2)');
plot(baudrates/1e9, reqROP_ML_MLSE3, '-d','Color',colML_MLSE*0.8,'DisplayName','ML-based MLSE (L=3)');
xlabel('Baud rate [GBd]');
ylabel('Required ROP [dBm]');
title('ROP required for FEC threshold');
grid on; legend('Location','northwest');
beautifyBERplot("logscale",0,"polyfit",1,"polyorder",4,"fitmethod",'polyfit');

View File

@@ -0,0 +1,140 @@
clear; clc;
M = 4;
randkey = 1;
duob_mode = db_mode.no_db;
mlse = 1;
dbtgt = 1;
link_lengths = 0:1:8; % [m] --- outer loop
rops = linspace(-10, 0, 12); % [dBm] --- inner sweep
FEC_thr = 3.8e-3; % BER target
baudrate = 200e9;
% --- allocate results
reqROP_FFE = nan(size(link_lengths));
reqROP_MLSE = nan(size(link_lengths));
reqROP_DBTGT = nan(size(link_lengths));
reqROP_ML_MLSE2 = nan(size(link_lengths));
reqROP_ML_MLSE3 = nan(size(link_lengths));
%% ====================== OUTER LOOP ======================
for L = 1:numel(link_lengths)
link_length_m = link_lengths(L);
fprintf('\n=== %.0f m fiber length ===\n', link_length_m);
ber_ffe = nan(size(rops));
ber_mlse = nan(size(rops));
ber_dbtgt = nan(size(rops));
ber_ml2 = nan(size(rops));
ber_ml3 = nan(size(rops));
%% -------- inner ROP loop --------
parfor i = 1:length(rops)
rop = rops(i);
[Rx_sig_2sps_v1, Symbols_v1, Tx_bits_v1] = standard_link_model( ...
"M",M,"fsym",baudrate,"rop",rop,"laser_wavelength",1290, ...
"link_length_km",link_length_m,"random_key",1);
Rx_sig_2sps_v1.spectrum("displayname",'Rx Sig','normalizeTo0dB',1);
%% FFE + MLSE
if mlse
pf_ncoeffs = 1;
ffe_order = [50, 0, 0];
mu_ffe = [0.0001, 0.0008, 0.001];
mu_dfe = 0.0004;
eq_ = EQ("Ne",ffe_order,"Nb",[0,0,0],"training_length",2^13, ...
"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);
pf_ = Postfilter("ncoeff",pf_ncoeffs,"useBurg",1);
mlse_ = MLSE("duobinary_output",0,'M',M, ...
'trellis_states',PAMmapper(M,0).levels,'scale_mode',2, ...
'trellis_exclusion',0,'trellis_state_mode',2,'debug',0, ...
'DIR',pf_.coefficients);
[ffe_results, mlse_results] = vnle_postfilter_mlse(eq_, pf_, mlse_, M, ...
Rx_sig_2sps_v1, Symbols_v1, Tx_bits_v1, ...
"precode_mode", duob_mode,'showAnalysis', 0, "postFFE", [], ...
"eth_style_symbol_mapping", 0);
ber_ffe(i) = ffe_results.metrics.BER;
ber_mlse(i) = mlse_results.metrics.BER;
end
%% FFE + duobinary target MLSE
if dbtgt
mlse_db_ = MLSE("DIR",[1,1],"duobinary_output",0,"M",M, ...
"trellis_states",PAMmapper(M,0).levels,'scale_mode',2, ...
'trellis_exclusion',0,'trellis_state_mode',3);
ffe_order = [50, 0, 0];
mu_ffe = [0.0001, 0.0008, 0.001];
mu_dfe = 0.0004;
eq_ = EQ("Ne",ffe_order,"Nb",[0,0,0],"training_length",2^13, ...
"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, Rx_sig_2sps_v1, ...
Symbols_v1, Tx_bits_v1, "precode_mode", duob_mode, ...
'showAnalysis', 0, "postFFE", []);
ber_dbtgt(i) = dbt_results.metrics.BER;
end
%% ML-based MLSE (L=2)
mu_ml = 0.1; training_epochs = 100;
ml_mlse_equalizer = ML_MLSE("epochs_tr",training_epochs,"epochs_dd",1, ...
"len_tr",2^16,"mu_dd",mu_ml,"mu_tr",mu_ml,"order",11,"sps",2, ...
"traceback_depth",128,"L",2,"delta",4,"adaptive_mu",0);
[y_ml_mlse,y_ref] = ml_mlse_equalizer.process(Rx_sig_2sps_v1,Symbols_v1);
ref_bits = PAMmapper(M,0).demap(y_ref);
ml_bits = PAMmapper(M,0).demap(y_ml_mlse);
[~,~,ber_ml2(i)] = calc_ber(ml_bits.signal, ref_bits.signal, ...
"skip_front",10,"skip_end",10);
%% ML-based MLSE (L=3)
ml_mlse_equalizer = ML_MLSE("epochs_tr",training_epochs,"epochs_dd",1, ...
"len_tr",2^16,"mu_dd",mu_ml,"mu_tr",mu_ml,"order",11,"sps",2, ...
"traceback_depth",128,"L",3,"delta",4,"adaptive_mu",0);
[y_ml_mlse,y_ref] = ml_mlse_equalizer.process(Rx_sig_2sps_v1,Symbols_v1);
ref_bits = PAMmapper(M,0).demap(y_ref);
ml_bits = PAMmapper(M,0).demap(y_ml_mlse);
[~,~,ber_ml3(i)] = calc_ber(ml_bits.signal, ref_bits.signal, ...
"skip_front",10,"skip_end",10);
end % ROP loop
%% --- find required ROP (FEC crossing)
reqROP_FFE(L) = interp_fec_cross(rops, ber_ffe, FEC_thr);
reqROP_MLSE(L) = interp_fec_cross(rops, ber_mlse, FEC_thr);
reqROP_DBTGT(L) = interp_fec_cross(rops, ber_dbtgt, FEC_thr);
reqROP_ML_MLSE2(L) = interp_fec_cross(rops, ber_ml2, FEC_thr);
reqROP_ML_MLSE3(L) = interp_fec_cross(rops, ber_ml3, FEC_thr);
fprintf('Length %.0f m: FFE %.1f, MLSE %.1f, DB %.1f, ML2 %.1f, ML3 %.1f\n', ...
link_length_m, reqROP_FFE(L), reqROP_MLSE(L), reqROP_DBTGT(L), ...
reqROP_ML_MLSE2(L), reqROP_ML_MLSE3(L));
end
%% ====================== PLOT REQUIRED ROP ======================
cols = cbrewer2('Set1',8);
colFFE = cols(1,:);
colMLSE = cols(2,:);
colDBTGT = cols(4,:);
colML_MLSE = cols(3,:);
figure(); hold on
plot(link_lengths, reqROP_FFE, '-o','Color',colFFE, 'DisplayName','FFE');
plot(link_lengths, reqROP_MLSE, '-s','Color',colMLSE, 'DisplayName','FFE+PF+MLSE');
plot(link_lengths, reqROP_DBTGT, '--^','Color',colDBTGT, 'DisplayName','DB tgt. MLSE');
plot(link_lengths, reqROP_ML_MLSE2, '-v','Color',colML_MLSE, 'DisplayName','ML-based MLSE (L=2)');
plot(link_lengths, reqROP_ML_MLSE3, '-d','Color',colML_MLSE*0.8,'DisplayName','ML-based MLSE (L=3)');
xlabel('Link length [km]');
ylabel('Required ROP [dBm]');
title(sprintf('Required ROP the reach FEC threshold (3.8e-3); %.0f GBd PAM-%d', baudrate.*1e-9, M));
legend('Location','northwest');
grid on;
beautifyBERplot("logscale",0,"polyfit",1,"polyorder",3,"fitmethod",'smoothingspline');

View File

@@ -22,7 +22,7 @@ function [Rx_sig_2sps,Symbols,Tx_bits] = standard_link_model(options)
options.laser_linewidth (1,1) double = 1e6 options.laser_linewidth (1,1) double = 1e6
% --- Channel parameters --- % --- Channel parameters ---
options.link_length_m (1,1) double = 0 options.link_length_km (1,1) double = 0
options.rop (1,:) double = -5 options.rop (1,:) double = -5
options.fsym (1,:) double = (212:16:256)*1e9 options.fsym (1,:) double = (212:16:256)*1e9
options.doub_mode (1,1) db_mode = db_mode.no_db options.doub_mode (1,1) db_mode = db_mode.no_db
@@ -57,7 +57,7 @@ function [Rx_sig_2sps,Symbols,Tx_bits] = standard_link_model(options)
"randomkey",options.random_key+1).process(El_sig); "randomkey",options.random_key+1).process(El_sig);
% --- Fiber --- % --- Fiber ---
Opt_sig = Fiber("fsimu",Opt_sig.fs,"fiber_length",options.link_length_m, ... Opt_sig = Fiber("fsimu",Opt_sig.fs,"fiber_length",options.link_length_km, ...
"alpha",0.3,"D",0,"lambda0",1310,"gamma",0,"Dslope",0.07).process(Opt_sig); "alpha",0.3,"D",0,"lambda0",1310,"gamma",0,"Dslope",0.07).process(Opt_sig);
% --- Amplifier (ROP set) --- % --- Amplifier (ROP set) ---
@@ -90,6 +90,10 @@ function [Rx_sig_2sps,Symbols,Tx_bits] = standard_link_model(options)
[~,Scpe_cell,~,found_sync] = Scpe_sig_2sps.tsynch( ... [~,Scpe_cell,~,found_sync] = Scpe_sig_2sps.tsynch( ...
"reference",Symbols,"fs_ref",options.fsym,"debug_plots",0); "reference",Symbols,"fs_ref",options.fsym,"debug_plots",0);
Rx_sig_2sps = Scpe_cell{1}.normalize("mode","rms"); try
Rx_sig_2sps = Scpe_cell{1}.normalize("mode","rms");
catch
Rx_sig_2sps = Scpe_sig_2sps.normalize("mode","rms");
end
end end

View File

@@ -0,0 +1,157 @@
M = 4;
order = 18;
randkey = 1;
bitpattern = [];
s = RandStream('twister','Seed',randkey);
for i = 1:log2(M)
N = 2^(order-1); %length of prbs
bitpattern(:,i) = randi(s,[0 1], N, 1);
end
if M == 6
bitpattern = reshape(bitpattern',[],1);
bitpattern = bitpattern(1:end-mod(length(bitpattern),5));
end
Bits = Informationsignal(bitpattern);
Symbols = PAMmapper(M,0).map(Bits);
Symbols.fs = 200e9;
Bits_ = PAMmapper(M, 0, "eth_style", 0).demap(Symbols);
% --- Channel: minimal ISI response + AWGN ---
h = [0.3 0.9 0.3,0.1]; % impulse response (normalized later if desired)
h = h / norm(h); % optional normalization for unit energy
symbols_filt = Symbols.filter(h,1);
%% SHOW FIG 3 in Paper: "ML Base Pre-Eq"
SNR_dB = [20:1:25];
SNR_db = linspace(12,25,12);
ber_ffe = zeros(size(SNR_dB));
ber_mlse_l5 = zeros(size(SNR_dB));
ber_nwf_mlse_l2 = zeros(size(SNR_dB));
ber_ml_mlse_l2 = zeros(size(SNR_dB));
ber_ml_mlse_l3 = zeros(size(SNR_dB));
ber_ml_mlse_l4 = zeros(size(SNR_dB));
epochs_training = 100;
for i = 1:numel(SNR_dB)
symbols_noi = symbols_filt;
symbols_noi.signal = awgn(symbols_filt.signal, SNR_dB(i), 'measured'); % AWGN with given SNR
% Sequence Est L=5
mlse_ = MLSE("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels,'scale_mode',0,'trellis_exclusion',0,'trellis_state_mode',2,'debug',0,'DIR',h);
mlse_.DIR = h;
[y_mlse] = mlse_.process(symbols_noi,Symbols);
mlse_bits = PAMmapper(M, 0, "eth_style", 0).demap(y_mlse);
[~, ~, ber_mlse_l5(i), ~] = calc_ber(mlse_bits.signal, Bits.signal, "skip_front", 10, "skip_end", 10, "returnErrorLocation", 1);
fprintf('MLSE L5: %.2e \n',ber_mlse_l5(i));
% 2nd Approach
mu_lms = 0.0005;
pf_ncoeffs = 1;
eq_ = FFE("epochs_tr",5,"epochs_dd",5,"len_tr",2^13,"mu_dd",mu_lms,"mu_tr",mu_lms,"order",16,"sps",1,"dd_mode",1,"adaption_technique","lms");
pf_ = Postfilter("ncoeff",pf_ncoeffs,"useBurg",1);
% FFE
[y_ffe, ffe_noise] = eq_.process(symbols_noi, Symbols);
Eq_bits = PAMmapper(M, 0, "eth_style", 0).demap(y_ffe);
[~, ~, ber_ffe(i), ~] = calc_ber(Eq_bits.signal, Bits.signal, "skip_front", 0, "skip_end", 0, "returnErrorLocation", 1);
fprintf('FFE: %.2e \n',ber_ffe(i));
% Postfilter
[y_white,~] = pf_.process(y_ffe, ffe_noise);
% Sequence Est
mlse_ = MLSE("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels,'scale_mode',0,'trellis_exclusion',0,'trellis_state_mode',2,'debug',0,'DIR',pf_.coefficients);
[y_mlse] = mlse_.process(y_white,Symbols);
mlse_bits = PAMmapper(M, 0, "eth_style", 0).demap(y_mlse);
[~, errors, ber_nwf_mlse_l2(i), errpos] = calc_ber(mlse_bits.signal, Bits.signal, "skip_front", 10, "skip_end", 10, "returnErrorLocation", 1);
fprintf('MLSE: %.2e \n',ber_nwf_mlse_l2(i));
% ML-base MLSE L=2
adaptive_mu = 0;
mu_lms = 0.15;
ml_mlse_equalizer = ML_MLSE("epochs_tr",epochs_training,"epochs_dd",1,"len_tr",2^15,...
"mu_dd",mu_lms,"mu_tr",mu_lms,"order",11,"sps",1,...
"traceback_depth",128,"L",2,"delta",4,"adaptive_mu",adaptive_mu);
[y_ml_mlse,~] = ml_mlse_equalizer.process(symbols_noi,Symbols);
ml_mlse_bits = PAMmapper(M, 0, "eth_style", 0).demap(y_ml_mlse);
[~, errors, ber_ml_mlse_l2(i), errpos] = calc_ber(ml_mlse_bits.signal, Bits.signal, "skip_front", 10, "skip_end", 10, "returnErrorLocation", 1);
fprintf('ML MLSE BER: %.2e \n',ber_ml_mlse_l2(i));
% ML-base MLSE L=3
mu_lms = 0.15;
ml_mlse_equalizer = ML_MLSE("epochs_tr",epochs_training,"epochs_dd",1,"len_tr",2^16,...
"mu_dd",mu_lms,"mu_tr",mu_lms,"order",11,"sps",1,...
"traceback_depth",128,"L",3,"delta",4,"adaptive_mu",adaptive_mu);
[y_ml_mlse,~] = ml_mlse_equalizer.process(symbols_noi,Symbols);
ml_mlse_bits = PAMmapper(M, 0, "eth_style", 0).demap(y_ml_mlse);
[~, errors, ber_ml_mlse_l3(i), errpos] = calc_ber(ml_mlse_bits.signal, Bits.signal, "skip_front", 10, "skip_end", 10, "returnErrorLocation", 1);
fprintf('ML MLSE BER: %.2e \n',ber_ml_mlse_l3(i));
% % ML-base MLSE L=5
% mu_lms = 0.15;
% ml_mlse_equalizer = ML_MLSE("epochs_tr",epochs_training,"epochs_dd",1,"len_tr",2^15,...
% "mu_dd",mu_lms,"mu_tr",mu_lms,"order",11,"sps",1,...
% "traceback_depth",128,"L",5,"delta",4);
% [y_ml_mlse,~] = ml_mlse_equalizer.process(symbols_noi,Symbols);
% ml_mlse_bits = PAMmapper(M, 0, "eth_style", 0).demap(y_ml_mlse);
% [~, errors, ber_ml_mlse_l5(i), errpos] = calc_ber(ml_mlse_bits.signal, Bits.signal, "skip_front", 10, "skip_end", 10, "returnErrorLocation", 1);
% fprintf('ML MLSE BER: %.2e \n',ber_ml_mlse_l5(i));
end
%%
figure(); hold on;
% --- define scheme colors (consistent palette)
cols = cbrewer2('SET1',8);
colFFE = cols(1,:); % blue
colMLSE = cols(2,:); % orange
colML_MLSE = cols(3,:); % green
colNWF_MLSE = cols(4,:); % purple
% --- local simulation results
plot(SNR_dB, ber_ffe, '-o', 'Color', colFFE, 'DisplayName','FFE (N=16)');
if M==2, plot(FFE_wpd.X, FFE_wpd.Y, ':', 'LineWidth',1.5, 'Color', colFFE, 'DisplayName','Paper FFE'); end
plot(SNR_dB, ber_mlse_l5, '-s', 'Color', colMLSE, 'DisplayName','MLSE (L=5)');
if M==2, plot(MLSE_wpd.X, MLSE_wpd.Y, ':', 'LineWidth',1.5, 'Color', colMLSE, 'DisplayName','Paper MLSE L=5'); end
plot(SNR_dB, ber_nwf_mlse_l2,'--^','Color', colNWF_MLSE, 'DisplayName','FFE+PF+MLSE (L=2)');
plot(SNR_dB, ber_ml_mlse_l2, '-v', 'Color', colML_MLSE, 'DisplayName','ML-based MLSE (L=2)');
if M==2, plot(ML_MLSE_L_2_wpd.X,ML_MLSE_L_2_wpd.Y,':', 'LineWidth',1.5, 'Color', colML_MLSE, 'DisplayName','Paper ML-based MLSE L=2'); end
plot(SNR_dB, ber_ml_mlse_l3, '-d', 'Color', colML_MLSE, 'DisplayName','ML-based MLSE (L=3)');
if M==2, plot(SNR_dB, ber_ml_mlse_l5, '-p', 'Color', colML_MLSE, 'DisplayName','ML-based MLSE (L=5)'); end
if M==2, plot(ML_MLSE_L_5_wpd.X,ML_MLSE_L_5_wpd.Y,':', 'LineWidth',1.5, 'Color', colML_MLSE, 'DisplayName','Paper ML-based MLSE L=5'); end
% --- imported WebPlotDigitizer data (dotted)
yline(3.8e-3,'HandleVisibility','off');
yline(2.2e-4,'HandleVisibility','off');
% --- formatting
beautifyBERplot;
xlim([SNR_dB(1), SNR_dB(end)]);
ylim([1e-5 0.1]);
xlabel('Input SNR [dB]');
ylabel('Bit Error Rate (BER)');
title('PAM-4; M=4; AWGN Channel');
legend('Location','southwest');
grid on;