More focus on Database analysis and direct DSP'ing of run_id's
This commit is contained in:
@@ -689,10 +689,17 @@ classdef Signal
|
|||||||
|
|
||||||
%estimate start pos of signal
|
%estimate start pos of signal
|
||||||
maxpeaknum = floor(length(a)/length(b));
|
maxpeaknum = floor(length(a)/length(b));
|
||||||
[pks,pkpos,w,p] = findpeaks(abs(co./max(co)),'MinPeakDistance',length(b)/2,'MinPeakHeight',0.2,'NPeaks',maxpeaknum,'SortStr','descend');
|
try
|
||||||
|
[pks,pkpos,w,p] = findpeaks(abs(co./max(co)),'MinPeakDistance',length(b)/2,'MinPeakHeight',0.2,'NPeaks',maxpeaknum,'SortStr','descend');
|
||||||
|
catch
|
||||||
|
warning(['Error in findpeaks, ususally the seuqnece is too short. Max peak num: ', num2str(maxpeaknum)]);
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
if mean(w) > 10 || mean(p) > 10
|
if mean(w) > 10 || mean(p) > 10
|
||||||
return
|
return
|
||||||
|
else
|
||||||
|
sequenceFound = 1;
|
||||||
end
|
end
|
||||||
|
|
||||||
if options.debug_plots
|
if options.debug_plots
|
||||||
@@ -700,6 +707,8 @@ classdef Signal
|
|||||||
findpeaks(abs(co./max(co)),'MinPeakDistance',length(b)/2,'MinPeakHeight',0.2,'NPeaks',maxpeaknum,'SortStr','descend')
|
findpeaks(abs(co./max(co)),'MinPeakDistance',length(b)/2,'MinPeakHeight',0.2,'NPeaks',maxpeaknum,'SortStr','descend')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
shifts = lags(pkpos);
|
shifts = lags(pkpos);
|
||||||
|
|
||||||
shifts = shifts(shifts>=0);
|
shifts = shifts(shifts>=0);
|
||||||
@@ -752,6 +761,12 @@ classdef Signal
|
|||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
%%
|
%%
|
||||||
function obj = filter(obj,a,b)
|
function obj = filter(obj,a,b)
|
||||||
|
|
||||||
|
|||||||
@@ -677,8 +677,6 @@ classdef DBHandler < handle
|
|||||||
delete(fig);
|
delete(fig);
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function filterParams = promptFilterParameters(obj)
|
function filterParams = promptFilterParameters(obj)
|
||||||
% promptFilterParameters Prompts the user to enter filter parameters using a
|
% promptFilterParameters Prompts the user to enter filter parameters using a
|
||||||
% custom scrollable UI with dropdowns.
|
% custom scrollable UI with dropdowns.
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ classdef equalizer_structure < int32
|
|||||||
vnle (1)
|
vnle (1)
|
||||||
vnle_pf_mlse (2)
|
vnle_pf_mlse (2)
|
||||||
% db_precoded (3)
|
% db_precoded (3)
|
||||||
% db_encoded (4)
|
|
||||||
vnle_db_mlse (3)
|
vnle_db_mlse (3)
|
||||||
|
db_encoded (4)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -1,18 +1,96 @@
|
|||||||
function [eq_package] = duobinary_signaling(eq_, mlse_,M ,rx_signal, tx_symbols, tx_bits)
|
function [eq_package] = duobinary_signaling(eq_, mlse_,M ,rx_signal, tx_symbols, tx_bits,options)
|
||||||
%Duobinary Signaling
|
%Duobinary Signaling
|
||||||
|
arguments
|
||||||
|
eq_
|
||||||
|
mlse_
|
||||||
|
M
|
||||||
|
rx_signal
|
||||||
|
tx_symbols
|
||||||
|
tx_bits
|
||||||
|
options.postFFE = [];
|
||||||
|
end
|
||||||
|
|
||||||
[eq_signal, eq_noise] = eq_.process(rx_signal,tx_symbols);
|
|
||||||
|
|
||||||
eq_signal = mlse_.process(eq_signal);
|
[eq_signal, eq_noise] = eq_.process(rx_signal,tx_symbols);
|
||||||
|
|
||||||
eq_signal = Duobinary().encode(eq_signal);
|
if ~isempty(options.postFFE)
|
||||||
eq_signal = Duobinary().decode(eq_signal);
|
[eq_signal,eq_noise] = options.postFFE.process(eq_signal,tx_symbols);
|
||||||
|
end
|
||||||
|
|
||||||
% M = numel(unique(eq_signal.signal));
|
|
||||||
rx_bits = PAMmapper(M,0).demap(eq_signal);
|
|
||||||
|
|
||||||
[~,numErrors,ber,~] = calc_ber(rx_bits.signal,tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
eq_signal = mlse_.process(eq_signal);
|
||||||
|
|
||||||
eq_package.ber = ber;
|
eq_signal = Duobinary().encode(eq_signal);
|
||||||
|
eq_signal = Duobinary().decode(eq_signal);
|
||||||
|
|
||||||
|
% M = numel(unique(eq_signal.signal));
|
||||||
|
rx_bits = PAMmapper(M,0).demap(eq_signal);
|
||||||
|
|
||||||
|
[bits_db,errors_db,ber_db,~] = calc_ber(rx_bits.signal,tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||||
|
|
||||||
|
eq_package.ber = ber_db;
|
||||||
|
|
||||||
|
resultsDBsignaling = struct( ...
|
||||||
|
'result_id', NaN, ... %
|
||||||
|
'run_id', NaN, ... % Beispielhafte Run-ID
|
||||||
|
'eqParam_id', NaN, ... % Beispielhafter Fremdschlüssel zur EqualizerParameters-Tabelle
|
||||||
|
'date_of_processing', datetime('now'), ... % Aktuelles Datum und Uhrzeit
|
||||||
|
'numBits', bits_db, ... % Beispiel: 1.000.000 Bits
|
||||||
|
'numBitErr', errors_db, ... % Beispiel: 120 Bitfehler
|
||||||
|
'BER_precoded', [], ... % BER = 120 / 1.000.000
|
||||||
|
'numBitErr_precoded', [], ... % Beispiel: 120 Bitfehler
|
||||||
|
'BER', ber_db, ... % BER = 120 / 1.000.000
|
||||||
|
'SNR', [], ... % Beispielhafte SNR
|
||||||
|
'SNR_level', jsonencode([]), ... % SNR-Level als JSON-codiertes Array
|
||||||
|
'GMI', [], ... % Beispielhafter GMI-Wert
|
||||||
|
'AIR', [], ... % Beispielhafter AIR-Wert
|
||||||
|
'EVM', [], ... % Beispielhafte EVM
|
||||||
|
'EVM_level', jsonencode([]), ... % EVM-Level als JSON-codiertes Array
|
||||||
|
'Alpha', [] ... % Beispielhafter Alpha-Wert
|
||||||
|
);
|
||||||
|
|
||||||
|
if ~isempty(options.postFFE)
|
||||||
|
npostFFE = options.postFFE.order;
|
||||||
|
else
|
||||||
|
npostFFE = 0;
|
||||||
|
end
|
||||||
|
|
||||||
|
equalizerConfigDBsignaling = struct( ...
|
||||||
|
'eq_id', NaN, ... % Auto-Inkrement, wird in der DB gesetzt
|
||||||
|
'equalizer_structure', int32(equalizer_structure.db_encoded), ... % Beispiel: 1 (z.B. für vnle)
|
||||||
|
'M', M, ... % Ordnung der PAM-Konstellation
|
||||||
|
'target_constellation', jsonencode(round(unique(tx_symbols.signal),5)), ... % Beispielhafter Target-String
|
||||||
|
'db_target', 1, ... % 0 oder 1
|
||||||
|
'diff_precode', 1, ... % 0 oder 1
|
||||||
|
'postFFE', ~isempty(options.postFFE), ... % Beispielwert
|
||||||
|
'NpostFFE', npostFFE, ... % Beispielwert
|
||||||
|
'Ne1', eq_.Ne(1), ... % Feedforward Koeffizienten 1. Ordnung
|
||||||
|
'Ne2', eq_.Ne(2), ... % Feedforward Koeffizienten 2. Ordnung
|
||||||
|
'Ne3', eq_.Ne(3), ... % Feedforward Koeffizienten 3. Ordnung
|
||||||
|
'Nb1', eq_.Nb(1), ... % Decision Feedback Koeffizienten 1. Ordnung
|
||||||
|
'Nb2', eq_.Nb(2), ... % Decision Feedback Koeffizienten 2. Ordnung
|
||||||
|
'Nb3', eq_.Nb(3), ... % Decision Feedback Koeffizienten 3. Ordnung
|
||||||
|
'K', eq_.K, ... % Samples pro Symbol
|
||||||
|
'DCmu', eq_.DCmu, ... % Anpassungsrate für DC-Tap
|
||||||
|
'ideal_dfe', eq_.ideal_dfe, ... % Flag für ideal DFE (0 oder 1)
|
||||||
|
'training_length', eq_.training_length, ... % Anzahl Trainingssymbole
|
||||||
|
'training_loops', eq_.training_loops, ... % Anzahl Trainingsdurchläufe
|
||||||
|
'TRmu1', eq_.FFEmu, ... % mu für DD-Modus (1. Ordnung)
|
||||||
|
'TRmu2', eq_.FFEmu, ... % mu für DD-Modus (2. Ordnung)
|
||||||
|
'TRmu3', eq_.FFEmu, ... % mu für DD-Modus (3. Ordnung)
|
||||||
|
'TRmuDFE', eq_.DFEmu, ... % mu für DFE-Modus im DD
|
||||||
|
'dd_loops', 5, ... % Anzahl Durchläufe im DD-Modus
|
||||||
|
'DDmu1', eq_.DDmu(1), ... % mu für DD-Modus (1. Ordnung)
|
||||||
|
'DDmu2', eq_.DDmu(2), ... % mu für DD-Modus (2. Ordnung)
|
||||||
|
'DDmu3', eq_.DDmu(3), ... % mu für DD-Modus (3. Ordnung)
|
||||||
|
'DDmuDFE', eq_.DDmu(4), ... % mu für DFE-Modus im DD
|
||||||
|
'MLSE_mode', 'viterbi', ... % Beispiel: MLSE-Modus als String
|
||||||
|
'MLSE_trellis_states', jsonencode(mlse_.trellis_states), ... % Trellis-States, z.B. als JSON-String oder kommasepariert
|
||||||
|
'comment', 'function: duobinary_target.m', ... % Zusätzliche Kommentare
|
||||||
|
'config_hash', NaN ...
|
||||||
|
);
|
||||||
|
|
||||||
|
eq_package.resultsDBsignaling = resultsDBsignaling;
|
||||||
|
eq_package.equalizerConfigDBsignaling = equalizerConfigDBsignaling;
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -30,35 +30,42 @@ mlse_sig_hd = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).quanti
|
|||||||
% precoding to mitigate error propagation, most prominently used in
|
% precoding to mitigate error propagation, most prominently used in
|
||||||
% combination with duobinary signaling to avoid catastrophic error
|
% combination with duobinary signaling to avoid catastrophic error
|
||||||
% behavior (see J.W.M. Bergmans, Digital Baseband Transmission and Recording -> partial response signaling)
|
% behavior (see J.W.M. Bergmans, Digital Baseband Transmission and Recording -> partial response signaling)
|
||||||
|
|
||||||
% takes:
|
|
||||||
% -> eq_signal_hd: hard decision signal after eq
|
|
||||||
% -> tx_symbols: that where used as reference for eq
|
|
||||||
|
|
||||||
switch options.precode_mode
|
switch options.precode_mode
|
||||||
case db_mode.db_emulate
|
|
||||||
|
|
||||||
mlse_sig_hd = Duobinary().encode(mlse_sig_hd,"M",M);
|
case db_mode.no_db
|
||||||
mlse_sig_hd = Duobinary().decode(mlse_sig_hd,"M",M);
|
% 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(tx_symbols);
|
tx_symbols_precoded = Duobinary().encode(tx_symbols);
|
||||||
tx_symbols_precoded = Duobinary().decode(tx_symbols_precoded);
|
tx_symbols_precoded = Duobinary().decode(tx_symbols_precoded);
|
||||||
|
|
||||||
tx_bits = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(tx_symbols_precoded);
|
tx_bits_precoded = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(tx_symbols_precoded);
|
||||||
|
|
||||||
case db_mode.db_discard
|
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);
|
||||||
|
|
||||||
% normal dsp for precoded sequence == discard/omit/ignore precode
|
%B) Just determine BER
|
||||||
tx_bits = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(tx_symbols);
|
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_encoded
|
|
||||||
|
|
||||||
% normal DB encoded data (only for 10KM)
|
|
||||||
|
|
||||||
case db_mode.db_precoded
|
case db_mode.db_precoded
|
||||||
|
|
||||||
mlse_sig_hd = Duobinary().encode(mlse_sig_hd,"M",M);
|
% Daten SIND TATSÄCHLICH precoded auf TX Seite:
|
||||||
mlse_sig_hd = Duobinary().decode(mlse_sig_hd,"M",M);
|
|
||||||
|
% 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",options.eth_style_symbol_mapping).demap(mlse_sig_hd_decoded);
|
||||||
|
[~,errors_db_diff_precoded,ber_db_diff_precoded,~] = calc_ber(rx_bits_mlse_decoded.signal,tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||||
|
|
||||||
|
% B) Omit the Coding by comparing with demapped TX symbol sequence
|
||||||
|
|
||||||
|
tx_bits = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(tx_symbols);
|
||||||
|
rx_bits_mlse = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(mlse_sig_hd);
|
||||||
|
[bits_db,errors_db,ber_db,~] = calc_ber(rx_bits_mlse.signal,tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -75,6 +82,8 @@ resultsDBtgt = struct( ...
|
|||||||
'date_of_processing', datetime('now'), ... % Aktuelles Datum und Uhrzeit
|
'date_of_processing', datetime('now'), ... % Aktuelles Datum und Uhrzeit
|
||||||
'numBits', bits_db, ... % Beispiel: 1.000.000 Bits
|
'numBits', bits_db, ... % Beispiel: 1.000.000 Bits
|
||||||
'numBitErr', errors_db, ... % Beispiel: 120 Bitfehler
|
'numBitErr', errors_db, ... % Beispiel: 120 Bitfehler
|
||||||
|
'BER_precoded', ber_db_diff_precoded, ... % BER = 120 / 1.000.000
|
||||||
|
'numBitErr_precoded', errors_db_diff_precoded, ... % Beispiel: 120 Bitfehler
|
||||||
'BER', ber_db, ... % BER = 120 / 1.000.000
|
'BER', ber_db, ... % BER = 120 / 1.000.000
|
||||||
'SNR', [], ... % Beispielhafte SNR
|
'SNR', [], ... % Beispielhafte SNR
|
||||||
'SNR_level', jsonencode([]), ... % SNR-Level als JSON-codiertes Array
|
'SNR_level', jsonencode([]), ... % SNR-Level als JSON-codiertes Array
|
||||||
|
|||||||
@@ -15,104 +15,114 @@ arguments
|
|||||||
options.database = [];
|
options.database = [];
|
||||||
end
|
end
|
||||||
|
|
||||||
%FFE or VNLE
|
%FFE or VNLE
|
||||||
[eq_signal_sd,eq_noise] = eq_.process(rx_signal,tx_symbols);
|
[eq_signal_sd,eq_noise] = eq_.process(rx_signal,tx_symbols);
|
||||||
|
|
||||||
if ~isempty(options.postFFE)
|
if ~isempty(options.postFFE)
|
||||||
[eq_signal_sd,eq_noise] = options.postFFE.process(eq_signal_sd,tx_symbols);
|
[eq_signal_sd,eq_noise] = options.postFFE.process(eq_signal_sd,tx_symbols);
|
||||||
end
|
end
|
||||||
|
|
||||||
eq_signal_hd = PAMmapper(M,0).quantize(eq_signal_sd);
|
eq_signal_hd = PAMmapper(M,0).quantize(eq_signal_sd);
|
||||||
|
|
||||||
mlse_sig_sd = pf_.process(eq_signal_sd,eq_noise);
|
mlse_sig_sd = pf_.process(eq_signal_sd,eq_noise);
|
||||||
|
|
||||||
mlse_.DIR = pf_.coefficients;
|
mlse_.DIR = pf_.coefficients;
|
||||||
% [mlse_sig_hd,mlse_sig_sd] = mlse_.process(mlse_sig_sd,tx_symbols);
|
% [mlse_sig_hd,mlse_sig_sd] = mlse_.process(mlse_sig_sd,tx_symbols);
|
||||||
mlse_sig_sd = mlse_.process(mlse_sig_sd);
|
mlse_sig_sd = mlse_.process(mlse_sig_sd);
|
||||||
|
|
||||||
mlse_sig_hd = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).quantize(mlse_sig_sd);
|
mlse_sig_hd = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).quantize(mlse_sig_sd);
|
||||||
|
|
||||||
% precoding to mitigate error propagation, most prominently used in
|
% precoding to mitigate error propagation, most prominently used in
|
||||||
% combination with duobinary signaling to avoid catastrophic error
|
% combination with duobinary signaling to avoid catastrophic error
|
||||||
% behavior (see J.W.M. Bergmans, Digital Baseband Transmission and Recording -> partial response signaling)
|
% behavior (see J.W.M. Bergmans, Digital Baseband Transmission and Recording -> partial response signaling)
|
||||||
|
|
||||||
% takes:
|
switch options.precode_mode
|
||||||
% -> M
|
|
||||||
% -> eq_signal_hd: hard decision signal after eq
|
|
||||||
% -> tx_symbols: that where used as reference for eq
|
|
||||||
|
|
||||||
switch options.precode_mode
|
case db_mode.no_db
|
||||||
case db_mode.db_emulate
|
% TX Data is not precoded:
|
||||||
% re
|
|
||||||
eq_signal_hd = Duobinary().encode(eq_signal_hd,"M",M);
|
|
||||||
eq_signal_hd = Duobinary().decode(eq_signal_hd,"M",M);
|
|
||||||
|
|
||||||
mlse_sig_hd = Duobinary().encode(mlse_sig_hd,"M",M);
|
% A) Emulate diff precoding
|
||||||
mlse_sig_hd = Duobinary().decode(mlse_sig_hd,"M",M);
|
eq_signal_hd_precoded = Duobinary().encode(eq_signal_hd,"M",M);
|
||||||
|
eq_signal_hd_precoded = Duobinary().decode(eq_signal_hd_precoded,"M",M);
|
||||||
|
|
||||||
|
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(tx_symbols);
|
tx_symbols_precoded = Duobinary().encode(tx_symbols);
|
||||||
tx_symbols_precoded = Duobinary().decode(tx_symbols_precoded);
|
tx_symbols_precoded = Duobinary().decode(tx_symbols_precoded);
|
||||||
|
|
||||||
tx_bits = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(tx_symbols_precoded);
|
tx_bits_precoded = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(tx_symbols_precoded);
|
||||||
|
|
||||||
case db_mode.db_discard
|
rx_bits_vnle = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(eq_signal_hd_precoded);
|
||||||
|
[~,errors_vnle_diff_precoded,ber_vnle_diff_precoded,~] = calc_ber(rx_bits_vnle.signal,tx_bits_precoded.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||||
|
|
||||||
|
rx_bits_mlse = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(mlse_sig_hd_precoded);
|
||||||
|
[~,errors_mlse_diff_precoded,ber_mlse_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_vnle = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(eq_signal_hd);
|
||||||
|
[bits_vnle,errors_vnle,ber_vnle,~] = calc_ber(rx_bits_vnle.signal,tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||||
|
|
||||||
|
rx_bits_mlse = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(mlse_sig_hd);
|
||||||
|
[bits_mlse,errors_mlse,ber_mlse,~] = 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!
|
||||||
|
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_vnle_decoded = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(eq_signal_hd_decoded);
|
||||||
|
[~,errors_vnle_diff_precoded,ber_vnle_diff_precoded,~] = calc_ber(rx_bits_vnle_decoded.signal,tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||||
|
|
||||||
|
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",options.eth_style_symbol_mapping).demap(mlse_sig_hd_decoded);
|
||||||
|
[~,errors_mlse_diff_precoded,ber_mlse_diff_precoded,~] = calc_ber(rx_bits_mlse_decoded.signal,tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||||
|
|
||||||
|
% B) Omit the Coding by comparing with demapped TX symbol sequence
|
||||||
|
|
||||||
% normal dsp for precoded sequence == discard/omit/ignore precode
|
|
||||||
tx_bits = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(tx_symbols);
|
tx_bits = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(tx_symbols);
|
||||||
|
rx_bits_vnle = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(eq_signal_hd);
|
||||||
|
[bits_vnle,errors_vnle,ber_vnle,~] = calc_ber(rx_bits_vnle.signal,tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||||
|
|
||||||
case db_mode.db_encoded
|
rx_bits_mlse = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(mlse_sig_hd);
|
||||||
|
[bits_mlse,errors_mlse,ber_mlse,~] = calc_ber(rx_bits_mlse.signal,tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||||
|
|
||||||
% normal DB encoded data (only for 10KM)
|
end
|
||||||
|
|
||||||
case db_mode.db_precoded
|
% METRICS OF VNLE SD Signal:
|
||||||
|
[snr_vnle,snr_vnle_lvl] = calc_snr(tx_symbols.signal,eq_noise.signal);
|
||||||
|
[gmi_vnle] = calc_air(eq_signal_sd,tx_symbols,"skip_front",10000,"skip_end",10000);
|
||||||
|
air_vnle = tx_symbols.fs .* floor(log2(double(M))*10)/10 .* gmi_vnle ./ log2(double(M));
|
||||||
|
[evm_vnle_total,evm_vnle_lvl] = calc_evm(eq_signal_sd,tx_symbols);
|
||||||
|
|
||||||
eq_signal_hd = Duobinary().encode(eq_signal_hd,"M",M);
|
% METRICS OF MLSE (HD-VITERBI)
|
||||||
eq_signal_hd = Duobinary().decode(eq_signal_hd,"M",M);
|
pf_.ncoeff = 1;
|
||||||
|
pf_.process(eq_signal_sd,eq_noise);
|
||||||
|
alpha = pf_.coefficients(2);
|
||||||
|
|
||||||
mlse_sig_hd = Duobinary().encode(mlse_sig_hd,"M",M);
|
eq_package.ber_mlse = ber_mlse;
|
||||||
mlse_sig_hd = Duobinary().decode(mlse_sig_hd,"M",M);
|
eq_package.ber_vnle = ber_vnle;
|
||||||
|
eq_package.evm_vnle_total = evm_vnle_total;
|
||||||
|
eq_package.evm_vnle_lvl = evm_vnle_lvl;
|
||||||
|
eq_package.gmi = gmi_vnle;
|
||||||
|
|
||||||
end
|
eq_package.eq = eq_;
|
||||||
|
eq_package.pf = pf_;
|
||||||
|
eq_package.mlse = mlse_;
|
||||||
|
|
||||||
% METRICS OF VNLE %
|
resultsVNLE = struct( ...
|
||||||
rx_bits_vnle = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(eq_signal_hd);
|
|
||||||
[bits_vnle,errors_vnle,ber_vnle,errorIndice_vnle] = calc_ber(rx_bits_vnle.signal,tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
|
||||||
[snr_vnle,snr_vnle_lvl] = calc_snr(tx_symbols.signal,eq_noise.signal);
|
|
||||||
|
|
||||||
% correct TUM implementation of AIR
|
|
||||||
[gmi_vnle] = calc_air(eq_signal_sd,tx_symbols,"skip_front",10000,"skip_end",10000);
|
|
||||||
gmi_vnle = min(max(abs(gmi_vnle),0.1),0); %set to zero if no convergence of gmi below 0.1 to avoid negative or any other "dumb" value
|
|
||||||
air_vnle = tx_symbols.fs .* floor(log2(8)*10)/10 .* gmi_vnle;
|
|
||||||
|
|
||||||
[evm_vnle_total,evm_vnle_lvl] = calc_evm(eq_signal_sd,tx_symbols);
|
|
||||||
|
|
||||||
% METRICS OF MLSE (HD-VITERBI)
|
|
||||||
rx_bits_mlse = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(mlse_sig_hd);
|
|
||||||
[bits_mlse,errors_mlse,ber_mlse,errorIndice_mlse]= calc_ber(rx_bits_mlse.signal,tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
|
||||||
|
|
||||||
pf_.ncoeff = 1;
|
|
||||||
pf_.process(eq_signal_sd,eq_noise);
|
|
||||||
alpha = pf_.coefficients(2);
|
|
||||||
|
|
||||||
|
|
||||||
eq_package.ber_mlse = ber_mlse;
|
|
||||||
eq_package.ber_vnle = ber_vnle;
|
|
||||||
eq_package.evm_vnle_total = evm_vnle_total;
|
|
||||||
eq_package.evm_vnle_lvl = evm_vnle_lvl;
|
|
||||||
eq_package.gmi = gmi_vnle;
|
|
||||||
|
|
||||||
eq_package.eq = eq_;
|
|
||||||
eq_package.pf = pf_;
|
|
||||||
eq_package.mlse = mlse_;
|
|
||||||
|
|
||||||
resultsVNLE = struct( ...
|
|
||||||
'result_id', NaN, ... %
|
'result_id', NaN, ... %
|
||||||
'run_id', NaN, ... % Beispielhafte Run-ID
|
'run_id', NaN, ... % Beispielhafte Run-ID
|
||||||
'eqParam_id', NaN, ... % Beispielhafter Fremdschlüssel zur EqualizerParameters-Tabelle
|
'eqParam_id', NaN, ... % Beispielhafter Fremdschlüssel zur EqualizerParameters-Tabelle
|
||||||
'date_of_processing', datetime('now'), ... % Aktuelles Datum und Uhrzeit
|
'date_of_processing', datetime('now'), ... % Aktuelles Datum und Uhrzeit
|
||||||
|
'BER', ber_vnle, ... % BER = 120 / 1.000.000
|
||||||
'numBits', bits_vnle, ... % Beispiel: 1.000.000 Bits
|
'numBits', bits_vnle, ... % Beispiel: 1.000.000 Bits
|
||||||
'numBitErr', errors_vnle, ... % Beispiel: 120 Bitfehler
|
'numBitErr', errors_vnle, ... % Beispiel: 120 Bitfehler
|
||||||
'BER', ber_vnle, ... % BER = 120 / 1.000.000
|
'BER_precoded', ber_vnle_diff_precoded, ... % BER = 120 / 1.000.000
|
||||||
|
'numBitErr_precoded', errors_vnle_diff_precoded, ... % Beispiel: 120 Bitfehler
|
||||||
'SNR', snr_vnle, ... % Beispielhafte SNR
|
'SNR', snr_vnle, ... % Beispielhafte SNR
|
||||||
'SNR_level', jsonencode(snr_vnle_lvl), ... % SNR-Level als JSON-codiertes Array
|
'SNR_level', jsonencode(snr_vnle_lvl), ... % SNR-Level als JSON-codiertes Array
|
||||||
'GMI', gmi_vnle, ... % Beispielhafter GMI-Wert
|
'GMI', gmi_vnle, ... % Beispielhafter GMI-Wert
|
||||||
@@ -120,15 +130,15 @@ end
|
|||||||
'EVM', evm_vnle_total, ... % Beispielhafte EVM
|
'EVM', evm_vnle_total, ... % Beispielhafte EVM
|
||||||
'EVM_level', jsonencode(evm_vnle_lvl), ... % EVM-Level als JSON-codiertes Array
|
'EVM_level', jsonencode(evm_vnle_lvl), ... % EVM-Level als JSON-codiertes Array
|
||||||
'Alpha', [] ... % Beispielhafter Alpha-Wert
|
'Alpha', [] ... % Beispielhafter Alpha-Wert
|
||||||
);
|
);
|
||||||
|
|
||||||
if ~isempty(options.postFFE)
|
if ~isempty(options.postFFE)
|
||||||
npostFFE = options.postFFE.order;
|
npostFFE = options.postFFE.order;
|
||||||
else
|
else
|
||||||
npostFFE = 0;
|
npostFFE = 0;
|
||||||
end
|
end
|
||||||
|
|
||||||
equalizerConfigVNLE = struct( ...
|
equalizerConfigVNLE = struct( ...
|
||||||
'eq_id', NaN, ... % Auto-Inkrement, wird in der DB gesetzt
|
'eq_id', NaN, ... % Auto-Inkrement, wird in der DB gesetzt
|
||||||
'equalizer_structure', int32(equalizer_structure.vnle), ... % Beispiel: 1 (z.B. für vnle)
|
'equalizer_structure', int32(equalizer_structure.vnle), ... % Beispiel: 1 (z.B. für vnle)
|
||||||
'M', M, ... % Ordnung der PAM-Konstellation
|
'M', M, ... % Ordnung der PAM-Konstellation
|
||||||
@@ -159,17 +169,19 @@ end
|
|||||||
'DDmuDFE', eq_.DDmu(4), ... % mu für DFE-Modus im DD
|
'DDmuDFE', eq_.DDmu(4), ... % mu für DFE-Modus im DD
|
||||||
'comment', 'function: vnle_postfilter_mlse', ... % Zusätzliche Kommentare
|
'comment', 'function: vnle_postfilter_mlse', ... % Zusätzliche Kommentare
|
||||||
'config_hash', NaN ...
|
'config_hash', NaN ...
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
resultsMLSE = struct( ...
|
resultsMLSE = struct( ...
|
||||||
'result_id', NaN, ... %
|
'result_id', NaN, ... %
|
||||||
'run_id', NaN, ... % Beispielhafte Run-ID
|
'run_id', NaN, ... % Beispielhafte Run-ID
|
||||||
'eqParam_id', NaN, ... % Beispielhafter Fremdschlüssel zur EqualizerParameters-Tabelle
|
'eqParam_id', NaN, ... % Beispielhafter Fremdschlüssel zur EqualizerParameters-Tabelle
|
||||||
'date_of_processing', datetime('now'), ... % Aktuelles Datum und Uhrzeit
|
'date_of_processing', datetime('now'), ... % Aktuelles Datum und Uhrzeit
|
||||||
|
'BER', ber_mlse, ... % BER = 120 / 1.000.000
|
||||||
'numBits', bits_mlse, ... % Beispiel: 1.000.000 Bits
|
'numBits', bits_mlse, ... % Beispiel: 1.000.000 Bits
|
||||||
'numBitErr', errors_mlse, ... % Beispiel: 120 Bitfehler
|
'numBitErr', errors_mlse, ... % Beispiel: 120 Bitfehler
|
||||||
'BER', ber_mlse, ... % BER = 120 / 1.000.000
|
'BER_precoded', ber_mlse_diff_precoded, ... % BER = 120 / 1.000.000
|
||||||
|
'numBitErr_precoded', errors_mlse_diff_precoded, ... % Beispiel: 120 Bitfehler
|
||||||
'SNR', [], ... % Beispielhafte SNR
|
'SNR', [], ... % Beispielhafte SNR
|
||||||
'SNR_level', jsonencode([]), ... % SNR-Level als JSON-codiertes Array
|
'SNR_level', jsonencode([]), ... % SNR-Level als JSON-codiertes Array
|
||||||
'GMI', [], ... % Beispielhafter GMI-Wert
|
'GMI', [], ... % Beispielhafter GMI-Wert
|
||||||
@@ -178,11 +190,10 @@ end
|
|||||||
'EVM_level', jsonencode([]), ... % EVM-Level als JSON-codiertes Array
|
'EVM_level', jsonencode([]), ... % EVM-Level als JSON-codiertes Array
|
||||||
'Alpha', alpha, ... % Beispielhafter Alpha-Wert
|
'Alpha', alpha, ... % Beispielhafter Alpha-Wert
|
||||||
'MLSE_dir', jsonencode([mlse_.DIR])...
|
'MLSE_dir', jsonencode([mlse_.DIR])...
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
equalizerConfigMLSE = struct( ...
|
||||||
equalizerConfigMLSE = struct( ...
|
|
||||||
'eq_id', NaN, ... % Auto-Inkrement, wird in der DB gesetzt
|
'eq_id', NaN, ... % Auto-Inkrement, wird in der DB gesetzt
|
||||||
'equalizer_structure', int32(equalizer_structure.vnle_pf_mlse), ... % Beispiel: 1 (z.B. für vnle)
|
'equalizer_structure', int32(equalizer_structure.vnle_pf_mlse), ... % Beispiel: 1 (z.B. für vnle)
|
||||||
'M', M, ... % Ordnung der PAM-Konstellation
|
'M', M, ... % Ordnung der PAM-Konstellation
|
||||||
@@ -215,42 +226,42 @@ end
|
|||||||
'MLSE_trellis_states', jsonencode(mlse_.trellis_states), ... % Trellis-States, z.B. als JSON-String oder kommasepariert
|
'MLSE_trellis_states', jsonencode(mlse_.trellis_states), ... % Trellis-States, z.B. als JSON-String oder kommasepariert
|
||||||
'comment', 'function: vnle_postfilter_mlse', ... % Zusätzliche Kommentare
|
'comment', 'function: vnle_postfilter_mlse', ... % Zusätzliche Kommentare
|
||||||
'config_hash', NaN ...
|
'config_hash', NaN ...
|
||||||
);
|
);
|
||||||
eq_package.resultsVNLE = resultsVNLE;
|
eq_package.resultsVNLE = resultsVNLE;
|
||||||
eq_package.resultsMLSE = resultsMLSE;
|
eq_package.resultsMLSE = resultsMLSE;
|
||||||
eq_package.equalizerConfigVNLE = equalizerConfigVNLE;
|
eq_package.equalizerConfigVNLE = equalizerConfigVNLE;
|
||||||
eq_package.equalizerConfigMLSE = equalizerConfigMLSE;
|
eq_package.equalizerConfigMLSE = equalizerConfigMLSE;
|
||||||
|
|
||||||
% eq_package.vnle_out = eq_signal_sd;
|
% eq_package.vnle_out = eq_signal_sd;
|
||||||
if options.showAnalysis
|
if options.showAnalysis
|
||||||
|
|
||||||
% fprintf(['VNLE EVM lvl: ',repmat('%.3f ',1,numel(evm_lvl)),' \n'],evm_lvl);
|
% fprintf(['VNLE EVM lvl: ',repmat('%.3f ',1,numel(evm_lvl)),' \n'],evm_lvl);
|
||||||
|
|
||||||
fprintf('VNLE BER: %.2e \n',ber_vnle);
|
fprintf('VNLE BER: %.2e \n',ber_vnle);
|
||||||
|
|
||||||
fprintf('MLSE BER: %.2e \n',ber_mlse);
|
fprintf('MLSE BER: %.2e \n',ber_mlse);
|
||||||
|
|
||||||
showEQNoisePSD(eq_noise,"fignum",336,"displayname",'Residual Noise after VNLE','postfilter_taps',pf_.coefficients);
|
showEQNoisePSD(eq_noise,"fignum",336,"displayname",'Residual Noise after VNLE','postfilter_taps',pf_.coefficients);
|
||||||
|
|
||||||
|
|
||||||
rx_signal.spectrum("normalizeTo0dB",1,"fignum",337,"displayname",'Rx Signal');
|
rx_signal.spectrum("normalizeTo0dB",1,"fignum",337,"displayname",'Rx Signal');
|
||||||
|
|
||||||
tx_symbols.spectrum("normalizeTo0dB",1,"fignum",337,'displayname','Tx Signal');
|
tx_symbols.spectrum("normalizeTo0dB",1,"fignum",337,'displayname','Tx Signal');
|
||||||
|
|
||||||
showLevelHistogram(eq_signal_sd,tx_symbols)
|
showLevelHistogram(eq_signal_sd,tx_symbols)
|
||||||
% showLevelHistogram(mlse_sig_sd,tx_symbols)
|
% showLevelHistogram(mlse_sig_sd,tx_symbols)
|
||||||
|
|
||||||
showEQcoefficients('n1',eq_.e,'n2',eq_.e2,'n3',eq_.e3,"displayname",'Coefficients');
|
showEQcoefficients('n1',eq_.e,'n2',eq_.e2,'n3',eq_.e3,"displayname",'Coefficients');
|
||||||
|
|
||||||
showEQNoiseSNR(tx_symbols,eq_noise,"displayname",'vnle snr','fignum',101);
|
showEQNoiseSNR(tx_symbols,eq_noise,"displayname",'vnle snr','fignum',101);
|
||||||
|
|
||||||
%%% EQ SNR Spectrum %230
|
%%% EQ SNR Spectrum %230
|
||||||
%snr
|
%snr
|
||||||
|
|
||||||
|
|
||||||
% showErrorBurstCount(eq_signal_sd,tx_symbols)
|
% showErrorBurstCount(eq_signal_sd,tx_symbols)
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
62
Functions/Theory/modifiedGodardTimingRecovery.m
Normal file
62
Functions/Theory/modifiedGodardTimingRecovery.m
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
function tau_error = modifiedGodardTimingRecovery(rx, N, eta, beta)
|
||||||
|
% modifiedGodardTimingRecovery
|
||||||
|
%
|
||||||
|
% This function estimates the symbol timing error using the modified Godard
|
||||||
|
% approach in the frequency domain as described in:
|
||||||
|
%
|
||||||
|
% "Modified Godard Timing Recovery for Non-Integer Oversampling Receivers"
|
||||||
|
% Appl. Sci. 2017, 7, 655. :contentReference[oaicite:0]{index=0}​:contentReference[oaicite:1]{index=1}
|
||||||
|
%
|
||||||
|
% Inputs:
|
||||||
|
% rx - Received time-domain signal (vector)
|
||||||
|
% N - FFT size (should be an even integer)
|
||||||
|
% eta - Effective oversampling factor used for timing recovery (eta > 1)
|
||||||
|
% beta - Roll-off related parameter (0 < beta <= 1)
|
||||||
|
%
|
||||||
|
% Output:
|
||||||
|
% tau_error - Estimated timing error (in sample units)
|
||||||
|
%
|
||||||
|
% Implementation Notes:
|
||||||
|
% 1. The function computes an N-point FFT of the first N samples of rx.
|
||||||
|
% 2. It then determines an offset (Delta) defined as:
|
||||||
|
% offset = round((1 - 1/eta) * N)
|
||||||
|
% 3. To avoid index overflow, the summation is taken over indices k from 1 to
|
||||||
|
% floor(N/2) - offset.
|
||||||
|
% 4. The timing error is estimated as:
|
||||||
|
% tau_error = ( (1+beta)/(2*eta*N - 1) * sum(phase difference) ) / (2*pi)
|
||||||
|
% where the phase difference is (angle(R(k)) - angle(R(k+offset)))
|
||||||
|
%
|
||||||
|
% Make sure that the input signal rx contains at least N samples.
|
||||||
|
|
||||||
|
% Check input length
|
||||||
|
if length(rx) < N
|
||||||
|
error('Input signal length must be at least N.');
|
||||||
|
end
|
||||||
|
|
||||||
|
% Compute the N-point FFT of the first N samples of rx
|
||||||
|
R = fft(rx(1:N), N);
|
||||||
|
|
||||||
|
% Determine the offset based on the oversampling factor (eta)
|
||||||
|
offset = round((1 - 1/eta) * N);
|
||||||
|
|
||||||
|
% Define the summation range to avoid index overflow
|
||||||
|
k_min = 1;
|
||||||
|
k_max = floor(N/2) - offset;
|
||||||
|
if k_max < k_min
|
||||||
|
error('Chosen parameters result in an empty summation range. Adjust N, eta, or beta.');
|
||||||
|
end
|
||||||
|
|
||||||
|
% Compute the sum of phase differences over the selected frequency bins
|
||||||
|
phase_diff_sum = 0;
|
||||||
|
for k = k_min:k_max
|
||||||
|
phase_k = angle(R(k));
|
||||||
|
phase_k_offset = angle(R(k + offset));
|
||||||
|
phase_diff_sum = phase_diff_sum + (phase_k - phase_k_offset);
|
||||||
|
end
|
||||||
|
|
||||||
|
% Normalization factor as per the modified Godard algorithm
|
||||||
|
norm_factor = (1 + beta) / (2 * eta * N - 1);
|
||||||
|
|
||||||
|
% Estimate the timing error in sample units
|
||||||
|
tau_error = (norm_factor * phase_diff_sum) / (2 * pi);
|
||||||
|
end
|
||||||
@@ -6,10 +6,10 @@ if 1
|
|||||||
uloops = struct;
|
uloops = struct;
|
||||||
uloops.precomp = [0,1];
|
uloops.precomp = [0,1];
|
||||||
uloops.db_precode = [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 = [1293,1297.5,1302,1306.5,1310,1313.4,1318,1322.7,1327.4];
|
||||||
uloops.laser_wavelength = [1310];
|
uloops.laser_wavelength = [1310];
|
||||||
uloops.M = [4,6,8];
|
uloops.M = [4];
|
||||||
uloops.link_length = [1]; % 1,2,3,5,6,8,10
|
uloops.link_length = [1]; % 1,2,3,5,6,8,10
|
||||||
wh = DataStorage(uloops);
|
wh = DataStorage(uloops);
|
||||||
wh.addStorage("ber");
|
wh.addStorage("ber");
|
||||||
|
|||||||
@@ -203,7 +203,7 @@ for iatt = 1:numel(dataTable.interference_attenuation)
|
|||||||
if ~found
|
if ~found
|
||||||
Raw_signal = load([basePath, char(dataTable.rx_raw_path(1))]);
|
Raw_signal = load([basePath, char(dataTable.rx_raw_path(1))]);
|
||||||
Raw_signal = Raw_signal.Scpe_sig_raw;
|
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
|
end
|
||||||
|
|
||||||
if ~found
|
if ~found
|
||||||
@@ -217,16 +217,6 @@ for iatt = 1:numel(dataTable.interference_attenuation)
|
|||||||
end
|
end
|
||||||
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;
|
fsym = Symbols.fs;
|
||||||
|
|
||||||
if db_precode
|
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 = 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 = 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
|
%%% EQUALIZING
|
||||||
|
|
||||||
@@ -277,6 +261,7 @@ for iatt = 1:numel(dataTable.interference_attenuation)
|
|||||||
vnle_dfe_package{iatt,occ} = result;
|
vnle_dfe_package{iatt,occ} = result;
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
%%%%% VNLE + PF + MLSE %%%%
|
%%%%% VNLE + PF + MLSE %%%%
|
||||||
if 1
|
if 1
|
||||||
|
|
||||||
@@ -299,7 +284,6 @@ for iatt = 1:numel(dataTable.interference_attenuation)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
%%%%% Duobinary Targeting %%%%
|
%%%%% Duobinary Targeting %%%%
|
||||||
if 1
|
if 1
|
||||||
|
|
||||||
|
|||||||
@@ -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');
|
||||||
194
projects/HighSpeedExperiment_2024/auswertung MPI/dsp_run_id.m
Normal file
194
projects/HighSpeedExperiment_2024/auswertung MPI/dsp_run_id.m
Normal 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
|
||||||
@@ -5,47 +5,67 @@ database = DBHandler("pathToDB",[basePath,'silas_labor.db']);
|
|||||||
|
|
||||||
filterParams = database.tables;
|
filterParams = database.tables;
|
||||||
filterParams.Configurations = struct( ...
|
filterParams.Configurations = struct( ...
|
||||||
'bitrate', 336e9, ...
|
'bitrate', [], ... %[224,336,360,390,420,448]
|
||||||
'db_mode', 0, ...
|
'db_mode', int32(db_mode.no_db), ...
|
||||||
'fiber_length', 1, ...
|
'fiber_length', 1, ...
|
||||||
'interference_attenuation', [], ...
|
'interference_attenuation', [], ...
|
||||||
'interference_path_length', [], ...
|
'interference_path_length', [], ...
|
||||||
'is_mpi', 1, ...
|
'is_mpi', 1, ...
|
||||||
'pam_level', 4, ...
|
'pam_level', 4, ...
|
||||||
'rop_attenuation', 0 ...
|
'rop_attenuation', 0, ...
|
||||||
|
'wavelength', 1310 ...
|
||||||
);
|
);
|
||||||
|
|
||||||
filterParams.EqualizerParameters.diff_precode = int32(db_mode.no_db);
|
% filterParams.EqualizerParameters.diff_precode = int32(db_mode.no_db);
|
||||||
filterParams.EqualizerParameters.equalizer_structure = int32(equalizer_structure.vnle);
|
filterParams.EqualizerParameters.equalizer_structure = int32(equalizer_structure.vnle);
|
||||||
|
% filterParams.EqualizerParameters.DCmu = 0.005;
|
||||||
|
|
||||||
selectedFields = {'Configurations.run_id' 'Runs.rx_raw_path' 'Configurations.bitrate' 'Configurations.symbolrate' 'Configurations.pam_level' 'Configurations.db_mode' 'Configurations.rop_attenuation' 'Configurations.is_mpi' 'Configurations.interference_attenuation' 'EqualizerParameters.equalizer_structure' 'EqualizerParameters.diff_precode' 'EqualizerParameters.eq_id' 'Measurements.power_pd_in' 'Measurements.power_mpi_interference' 'Measurements.power_mpi_signal' 'Results.BER' 'Results.SNR' 'Results.GMI' 'Results.Alpha'};
|
selectedFields = {'Configurations.run_id' '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);
|
[dataTable,sql_query] = database.queryDB(filterParams, selectedFields);
|
||||||
|
|
||||||
fixedVars = {'run_id','eq_id','bitrate'};
|
fixedVars = {'run_id','eq_id','bitrate'};
|
||||||
resultTable = groupIt(fixedVars,dataTable);
|
dataTableGrpd = groupIt(fixedVars,dataTable);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
% Create a new figure
|
% Create a new figure
|
||||||
figure(1);
|
figure(3);
|
||||||
hold on
|
hold on
|
||||||
unique_rates = unique(resultTable.bitrate);
|
unique_rates = unique(dataTable.bitrate);
|
||||||
|
cols = linspecer(8);
|
||||||
for i = 1:numel(unique_rates)
|
for i = 1:numel(unique_rates)
|
||||||
|
|
||||||
% Plot BER vs. interference_attenuation
|
% 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
|
end
|
||||||
|
|
||||||
% Label the axes and add a title
|
% Label the axes and add a title
|
||||||
xlabel('Interference Attenuation');
|
xlabel('SIR in dB');
|
||||||
ylabel('BER');
|
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
|
% Enable grid for better readability
|
||||||
grid on;
|
grid on;
|
||||||
|
|
||||||
beautifyBERplot;
|
beautifyBERplot;
|
||||||
|
ylim([1e-4 0.5]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -70,7 +90,7 @@ function resultTable = groupIt(fixedVars,dataTable)
|
|||||||
colData = dataTable.(varNames{j});
|
colData = dataTable.(varNames{j});
|
||||||
if isnumeric(colData)
|
if isnumeric(colData)
|
||||||
% For numeric data, compute the mean.
|
% For numeric data, compute the mean.
|
||||||
aggData{i, j} = mean(colData(idx));
|
aggData{i, j} = min(colData(idx));
|
||||||
else
|
else
|
||||||
% For non-numeric data, take the first entry.
|
% For non-numeric data, take the first entry.
|
||||||
if iscell(colData)
|
if iscell(colData)
|
||||||
@@ -89,3 +109,42 @@ function resultTable = groupIt(fixedVars,dataTable)
|
|||||||
resultTable.nRows = groupCount;
|
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
|
||||||
|
|||||||
186
projects/HighSpeedExperiment_2024/db_auswertung/rate_vs_ber.m
Normal file
186
projects/HighSpeedExperiment_2024/db_auswertung/rate_vs_ber.m
Normal 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
|
||||||
@@ -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
|
||||||
BIN
projects/Messung_Zürich/AIR_simp_new.fig
Normal file
BIN
projects/Messung_Zürich/AIR_simp_new.fig
Normal file
Binary file not shown.
BIN
projects/Messung_Zürich/BER_ief.fig
Normal file
BIN
projects/Messung_Zürich/BER_ief.fig
Normal file
Binary file not shown.
BIN
projects/Messung_Zürich/BER_simp_new.fig
Normal file
BIN
projects/Messung_Zürich/BER_simp_new.fig
Normal file
Binary file not shown.
BIN
projects/Messung_Zürich/NDR_simp_new.fig
Normal file
BIN
projects/Messung_Zürich/NDR_simp_new.fig
Normal file
Binary file not shown.
BIN
projects/Messung_Zürich/NGMI_ief.fig
Normal file
BIN
projects/Messung_Zürich/NGMI_ief.fig
Normal file
Binary file not shown.
BIN
projects/Messung_Zürich/NGMI_simp_new.fig
Normal file
BIN
projects/Messung_Zürich/NGMI_simp_new.fig
Normal file
Binary file not shown.
Reference in New Issue
Block a user