More focus on Database analysis and direct DSP'ing of run_id's

This commit is contained in:
Silas Oettinghaus
2025-04-08 10:21:41 +02:00
parent 74066d0669
commit e86930335e
20 changed files with 1008 additions and 187 deletions

View File

@@ -6,10 +6,10 @@ if 1
uloops = struct;
uloops.precomp = [0,1];
uloops.db_precode = [0,1];
uloops.bitrate = [224,336,360,390,420,448].*1e9; %[300,330,360,390,420,450,480] [224,336,360,390,420,448] for MPI
uloops.bitrate = [420].*1e9; %[300,330,360,390,420,450,480] [224,336,360,390,420,448] for MPI
% uloops.laser_wavelength = [1293,1297.5,1302,1306.5,1310,1313.4,1318,1322.7,1327.4];
uloops.laser_wavelength = [1310];
uloops.M = [4,6,8];
uloops.M = [4];
uloops.link_length = [1]; % 1,2,3,5,6,8,10
wh = DataStorage(uloops);
wh.addStorage("ber");

View File

@@ -203,7 +203,7 @@ for iatt = 1:numel(dataTable.interference_attenuation)
if ~found
Raw_signal = load([basePath, char(dataTable.rx_raw_path(1))]);
Raw_signal = Raw_signal.Scpe_sig_raw;
[~,Scpe_cell,found] =Raw_signal.tsynch("reference",Symbols,"fs_ref",fsym,"debug_plots",0);
[~,Scpe_cell,found] =Raw_signal.tsynch("reference",Symbols,"fs_ref",fsym,"debug_plots",1);
end
if ~found
@@ -217,16 +217,6 @@ for iatt = 1:numel(dataTable.interference_attenuation)
end
end
%
% Raw_signal = Filter('filtdegree',4,"f_cutoff",Symbols.fs.*0.55,"fs",Raw_signal.fs,"filterType",filtertypes.gaussian,"active",true).process(Raw_signal);
%
% Scpe_cell{1}.eye(fsym,M,"displayname",'eye','fignum',227);
%
% Raw_signal.spectrum("normalizeTo0dB",0,"fignum",11,"fft_length",2^12);
% Raw_signal.move_it_spectrum("fignum",334);
% Raw_signal.move_it_spectrum("fignum",334);
fsym = Symbols.fs;
if db_precode
@@ -249,13 +239,7 @@ for iatt = 1:numel(dataTable.interference_attenuation)
Scpe_sig = Filter('filtdegree',4,"f_cutoff",Symbols.fs.*0.5,"fs",Scpe_sig.fs,"filterType",filtertypes.gaussian,"active",true).process(Scpe_sig);
Scpe_sig = Scpe_sig - mean(Scpe_sig.signal);
%
% Pform = Pulseformer("fsym",Scpe_sig.fs,"fdac",2*fsym,"pulse","rrc","pulselength",16,"alpha",rcalpha,"matched",0);
%
% Scpe_sig_matched = Pform.process(Scpe_sig);
%
% Scpe_sig.spectrum("normalizeTo0dB",0,"fignum",336,"displayname","scope ");
% Scpe_sig_matched.spectrum("normalizeTo0dB",0,"fignum",336,"displayname","matched");
%%% EQUALIZING
@@ -277,6 +261,7 @@ for iatt = 1:numel(dataTable.interference_attenuation)
vnle_dfe_package{iatt,occ} = result;
end
%%%%% VNLE + PF + MLSE %%%%
if 1
@@ -299,7 +284,6 @@ for iatt = 1:numel(dataTable.interference_attenuation)
end
%%%%% Duobinary Targeting %%%%
if 1

View File

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

View File

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

View File

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

View File

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

View File

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