Scattered stuff from Silas during Dissertation

This commit is contained in:
Silas Oettinghaus
2026-06-03 09:05:33 +02:00
parent a91da3b97c
commit 5c2e27687d
37 changed files with 1726 additions and 1338 deletions

View File

@@ -47,12 +47,12 @@ function output = dsp_scope_signal(Scpe_sig_raw, Symbols, Tx_bits, options)
use_dd_mode = 1;
use_ffe = 1;
use_dfe = 0;
use_vnle_mlse = 0;
use_dbtgt = 0;
use_dfe = 1;
use_vnle_mlse = 1;
use_dbtgt = 1;
use_dbenc = 0;
use_ml_mlse = 0;
showAnalysis = 1;
showAnalysis = 0;
decoding_mode = [];
addProcessingResultToDatabase = 0; %#ok<NASGU>
@@ -70,8 +70,8 @@ function output = dsp_scope_signal(Scpe_sig_raw, Symbols, Tx_bits, options)
pf_ = Postfilter("ncoeff", pf_ncoeffs, "useBurg", 1); %#ok<NASGU>
mlse_ = MLSE("duobinary_output", 0, 'M', M, 'trellis_states', PAMmapper(M,0).levels); %#ok<NASGU>
eq_post = FFE("epochs_tr",5,"epochs_dd",5,"len_tr",4096*2,"mu_dd",1e-4,"mu_tr",0,"order",2001,"sps",1,"decide",0,"adaption_technique","lms"); %#ok<NASGU>
eq_post = FFE("epochs_tr",5,"epochs_dd",2,"len_tr",2^13,"mu_dd",mu_dd,"mu_tr",mu_tr,"order",25,"sps",2,"decide",0, "adaption",adaption_method(adaption),"dd_mode",use_dd_mode); %#ok<NASGU>
eq_post = FFE("epochs_tr",5,"epochs_dd",5,"len_tr",4096*2,"mu_dd",1e-4,"mu_tr",0,"order",2001,"sps",1,"decide",0,"adaption_technique","lms","mu_dc",mu_dc); %#ok<NASGU>
eq_post = FFE("epochs_tr",5,"epochs_dd",2,"len_tr",2^13,"mu_dd",mu_dd,"mu_tr",mu_tr,"order",25,"sps",2,"decide",0, "adaption_technique",adaption_method(adaption),"dd_mode",use_dd_mode,"mu_dc",mu_dc); %#ok<NASGU>
mlse_db_enc = MLSE("DIR", [1,1], "duobinary_output", 0, "M", M, "trellis_states", PAMmapper(M,0).levels); %#ok<NASGU>
eq_db_enc = EQ("Ne", ffe_order_dbtgt, "Nb", dfe_order_dbtgt, "training_length", len_tr, ...
@@ -81,21 +81,22 @@ function output = dsp_scope_signal(Scpe_sig_raw, Symbols, Tx_bits, options)
Scpe_sig = preprocessSignal(Scpe_sig_raw, Symbols, fsym, ...
"mode", options.preprocess_mode, ...
"tx_pulseformer", options.tx_pulseformer, ...
"debug_plots", options.debug_plots);
Scpe_sig.spectrum("fignum",200,"normalizeTo0dB",1,"displayname",'Rx','addDCoffset',-6);
Scpe_sig.spectrum("fignum",201,"normalizeTo0dB",0,"displayname",'Rx');
"debug_plots", 0);
ylim([-30,3]);
xlim([-5,100]);
% Scpe_sig.spectrum("fignum",200,"normalizeTo0dB",1,"displayname",'Rx','addDCoffset',-6);
% ylim([-30,3]);
% xlim([-5,100]);
Scpe_sig.signal = Scpe_sig.signal(1:2*Symbols.length);
Scpe_sig.signal = real(Scpe_sig.signal);
if duob_mode ~= db_mode.db_encoded
if use_ffe
eq_dfe = EQ("Ne",ffe_order_ffe,"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_ffe = EQ("Ne",ffe_order_ffe,"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_ffe = FFE("epochs_tr",5,"epochs_dd",5,"len_tr",4096*2,"mu_dd",1e-1,"mu_tr",0.4,"order",ffe_order_ffe(1),...
"sps",2,"decide",0,"optmize_mus",0,"dd_mode",1,"adaption_technique","nlms","mu_dc",1.021e-05);
ffe_results = ffe(eq_dfe, M, Scpe_sig, Symbols, Tx_bits, ...
ffe_results = ffe(eq_ffe, M, Scpe_sig, Symbols, Tx_bits, ...
"precode_mode", duob_mode, ...
'showAnalysis', options.debug_plots, ...
"postFFE", [], ...
@@ -116,7 +117,7 @@ function output = dsp_scope_signal(Scpe_sig_raw, Symbols, Tx_bits, options)
"eth_style_symbol_mapping", 0);
dfe_results.config.equalizer_structure = "dfe";
dfe_results.metrics.print;
dfe_results.metrics.print("description",'DFE');
output.dfe_package = dfe_results;
end
@@ -144,8 +145,8 @@ function output = dsp_scope_signal(Scpe_sig_raw, Symbols, Tx_bits, options)
"eth_style_symbol_mapping", 0);
ffe_results.config.equalizer_structure = "vnle";
ffe_results.metrics.print;
mlse_results.metrics.print;
ffe_results.metrics.print("description",'VNLE');
mlse_results.metrics.print("description",'MLSE');
output.mlse_package = mlse_results;
output.vnle_package = ffe_results;
@@ -190,7 +191,7 @@ function output = dsp_scope_signal(Scpe_sig_raw, Symbols, Tx_bits, options)
"decoding_mode", decoding_mode);
end
dbt_results.metrics.print;
dbt_results.metrics.print("description",'Duob. Target');
output.dbtgt_package = dbt_results;
end
end

View File

@@ -14,6 +14,7 @@ function [db_results] = duobinary_target(eq_, mlse_,M, rx_signal, tx_symbols, tx
options.decoding_mode db_decoder = db_decoder.sequencedetection;
end
%Duobinary Targeting
db_ref_sequence = Duobinary().encode(tx_symbols);
@@ -172,14 +173,15 @@ function [db_results] = duobinary_target(eq_, mlse_,M, rx_signal, tx_symbols, tx
rx_signal.spectrum("normalizeTo0dB",1,"fignum",250,"displayname","Rx Spectrum");
Duobinary().encode(tx_symbols).spectrum("normalizeTo0dB",1,"fignum",10,"displayname","DB encoded reference");
Duobinary().encode(tx_symbols).spectrum("normalizeTo0dB",1,"fignum",250,"displayname","DB encoded reference");
showEQNoisePSD(eq_noise,"fignum",250,"displayname",'Duobinary Target Noise after Equalization');
fprintf('DB tgt BER: %.2e \n',ber_db);
figure(341); clf;
showLevelHistogram(eq_signal, db_ref_sequence, "fignum", 341);
tx_symbols_uncoded = Duobinary().decode(db_ref_sequence);
showLevelHistogram(eq_signal, db_ref_sequence, "fignum", 341,"ref_symbol_uncoded",tx_symbols_uncoded);
end

View File

@@ -171,6 +171,8 @@ function displayAnalysis(eq_noise, eq_signal_sd, rx_signal, eq_, tx_symbols, M,
showEQNoisePSD(eq_noise, "fignum", 103, "displayname", 'Residual Noise after FFE');
% showEQcoefficients('n1', eq_.e, "displayname", 'Coefficients', 'fignum', 104);
% Figure 2: Post-FFE coefficients (if available)
if ~isempty(postFFE)
showEQcoefficients('n1', postFFE.e, "displayname", 'Coefficients', 'fignum', 104);
@@ -179,7 +181,6 @@ function displayAnalysis(eq_noise, eq_signal_sd, rx_signal, eq_, tx_symbols, M,
try
figure(339);hold on
showEQfilter(eq_.e, eq_signal_sd.fs.*2,"displayname",'training','fignum',339);
% showEQfilter(eq_.e, eq_signal_sd.fs.*2,"displayname",'dec. directed','fignum',339);
legend on
end

View File

@@ -48,6 +48,8 @@ eq_signal_hd = PAMmapper(M, 0).quantize(eq_signal_sd);
[mlse_sig_sd,whitened_noise] = pf_.process(eq_signal_sd, eq_noise);
[tx_symbols_pr,~] = pf_.process(tx_symbols, eq_noise);
if 0 %tx_symbols.fs > 190e9
if pf_.ncoeff == 1
if pf_.coefficients(2) < 0
@@ -283,7 +285,7 @@ if ~isempty(postFFE)
showEQcoefficients('n1', postFFE.e, "displayname", 'Coefficients', 'fignum', 341);
end
% showEQcoefficients('n1', eq_.e1,'n2', eq_.e2,'n3', eq_.e3, "displayname", 'Coefficients', 'fignum', 339);
showEQcoefficients('n1', eq_.e,'n2', eq_.e2,'n3', eq_.e3, "displayname", 'Coefficients', 'fignum', 339);
showEQfilter(eq_.e, eq_signal_sd.fs.*2);
figure(340); clf;

View File

@@ -4,6 +4,12 @@ arguments
ref_symbols
options.fignum (1,1) double = NaN % Default to NaN if not provided
options.displayname (1,:) char = '' % Default to an empty string if not provided
options.color = [];
options.clear = true;
options.rasterize = false;
options.raster_resolution (1,1) double = 1000;
options.raster_markersize (1,1) double = 1;
options.raster_clim = [];
end
plot_shit = 1;
@@ -22,7 +28,9 @@ if plot_shit
fig = figure; % Create a new figure and get its handle
else
fig = figure(options.fignum); % Use the specified figure number
clf;
if options.clear
clf;
end
end
end
@@ -31,6 +39,8 @@ rx_symbols = eq_signal; %./ rms(eq_signal);
correct_symbols = ref_symbols;
col = cbrewer2('Paired',numel(unique(correct_symbols))*3);
useDefaultColormap = isempty(options.color);
scatterColor = options.color;
ccnt = -1;
levels = unique(correct_symbols);
@@ -66,20 +76,146 @@ D = sqrt(D_even.^2 + D_odd.^2);
[X,Y] = meshgrid(levels, levels);
[X_,Y_] = meshgrid(statistical_mean, statistical_mean);
plot_xlim = [floor(min(X_(:)))-1, ceil(max(X_(:)))+1];
plot_ylim = [floor(min(Y_(:)))-1, ceil(max(Y_(:)))+1];
hold on;
scatter(rx_even,rx_odd,5*ones(1,length(D)),D,'.','DisplayName',['Even/Odd PAM-',num2str(M)],'MarkerEdgeColor',col(2,:));
% colormap(gca,flip(cbrewer2('Spectral',100)))
colormap(gca,'hsv');
scatter(X_(:), Y_(:), 2, 'x', 'LineWidth', 10, 'MarkerEdgeColor', col(6,:),'DisplayName','Statistical Rx Levels');
scatter(X(:), Y(:), 2, 'x', 'LineWidth', 10, 'MarkerEdgeColor', col(4,:),'DisplayName','Tx Levels');
xlim([floor(min(X_(:)))-1, ceil(max(X_(:)))+1]);
ylim([floor(min(Y_(:)))-1, ceil(max(Y_(:)))+1]);
if isempty(options.displayname)
displayName = ['Even/Odd PAM-',num2str(M)];
else
displayName = options.displayname;
end
if useDefaultColormap
cols = flip(cbrewer2('RdYlBu',100));
cols=(cbrewer2("RdYlBu",4096));
% cols(45:55,:) = [];
colormap(gca,cols);
if isempty(options.raster_clim)
cLim = [0 max(D).*0.45];
else
cLim = options.raster_clim;
end
if cLim(2) <= cLim(1)
cLim(2) = cLim(1) + eps;
end
clim(cLim);
% colormap(gca,'hsv');
if options.rasterize
nBins = options.raster_resolution;
xEdges = linspace(plot_xlim(1),plot_xlim(2),nBins+1);
yEdges = linspace(plot_ylim(1),plot_ylim(2),nBins+1);
xBin = discretize(rx_even,xEdges);
yBin = discretize(rx_odd,yEdges);
valid = ~isnan(xBin) & ~isnan(yBin) & isfinite(D);
yticks((levels(1:end-1) + levels(2:end)) / 2);
xticks((levels(1:end-1) + levels(2:end)) / 2);
countImg = accumarray([yBin(valid), xBin(valid)],1,[nBins nBins],@sum,0);
dImg = accumarray([yBin(valid), xBin(valid)],D(valid),[nBins nBins],@mean,NaN);
countImgRaw = countImg;
markerRadius = max(0, round((options.raster_markersize - 1) / 2));
if markerRadius > 0
kernel = ones(2*markerRadius+1);
countImg = conv2(countImg,kernel,'same');
weightedD = dImg;
weightedD(~isfinite(weightedD)) = 0;
weightedD = conv2(weightedD .* countImgRaw,kernel,'same');
dWeight = conv2(isfinite(dImg) .* countImgRaw,kernel,'same');
dImg = weightedD ./ dWeight;
end
colorIdx = round((dImg-cLim(1)) ./ diff(cLim) * (size(cols,1)-1)) + 1;
colorIdx = min(max(colorIdx,1),size(cols,1));
density = log1p(countImg);
if max(density(:)) > 0
density = density ./ max(density(:));
end
rgbImg = ones(nBins,nBins,3);
for rgbIdx = 1:3
colorPlane = reshape(cols(colorIdx,rgbIdx),nBins,nBins);
colorPlane(~isfinite(dImg)) = 1;
rgbImg(:,:,rgbIdx) = (1-density) + density .* colorPlane;
end
hImg = image(linspace(plot_xlim(1),plot_xlim(2),nBins), ...
linspace(plot_ylim(1),plot_ylim(2),nBins), ...
rgbImg);
hImg.HandleVisibility = 'off';
set(gca,'YDir','normal');
uistack(hImg,'bottom');
plot(nan,nan,'.','DisplayName',displayName,'MarkerEdgeColor',col(2,:));
else
sz = ones(1,length(D)).*1;
scatter(rx_even,rx_odd,sz,D,'.','DisplayName',displayName);
end
rxLevelColor = col(6,:);
else
if options.rasterize
nBins = options.raster_resolution;
xEdges = linspace(plot_xlim(1),plot_xlim(2),nBins+1);
yEdges = linspace(plot_ylim(1),plot_ylim(2),nBins+1);
xBin = discretize(rx_even,xEdges);
yBin = discretize(rx_odd,yEdges);
valid = ~isnan(xBin) & ~isnan(yBin);
countImg = accumarray([yBin(valid), xBin(valid)],1,[nBins nBins],@sum,0);
markerRadius = max(0, round((options.raster_markersize - 1) / 2));
if markerRadius > 0
kernel = ones(2*markerRadius+1);
countImg = conv2(countImg,kernel,'same');
end
density = log1p(countImg);
if max(density(:)) > 0
density = density ./ max(density(:));
end
rgbImg = ones(nBins,nBins,3);
for rgbIdx = 1:3
rgbImg(:,:,rgbIdx) = (1-density) + density .* scatterColor(rgbIdx);
end
hImg = image(linspace(plot_xlim(1),plot_xlim(2),nBins), ...
linspace(plot_ylim(1),plot_ylim(2),nBins), ...
rgbImg);
hImg.HandleVisibility = 'off';
set(gca,'YDir','normal');
uistack(hImg,'bottom');
plot(nan,nan,'.','DisplayName',displayName,'MarkerEdgeColor',scatterColor);
else
scatter(rx_even,rx_odd,5*ones(1,length(D)),'.','DisplayName',displayName,'MarkerEdgeColor',scatterColor);
end
rxLevelColor = scatterColor;
end
scatter(X_(:), Y_(:), 2, 'x', 'LineWidth', 10, 'MarkerEdgeColor', rxLevelColor,'DisplayName',[displayName, ' Rx Levels']);
scatter(X(:), Y(:), 2, 'x', 'LineWidth', 10, 'MarkerEdgeColor', col(4,:),'DisplayName','Tx Levels');
xlim(plot_xlim);
ylim(plot_ylim);
decisionBoundaries = (levels(1:end-1) + levels(2:end)) / 2;
ax = gca;
xticks(levels);
yticks(levels);
xticklabels(compose('%g',levels));
yticklabels(compose('%g',levels));
try
ax.XAxis.MinorTickValues = decisionBoundaries;
ax.YAxis.MinorTickValues = decisionBoundaries;
end
ax.XMinorTick = 'on';
ax.YMinorTick = 'on';
ax.XMinorGrid = 'on';
ax.YMinorGrid = 'on';
ax.GridLineStyle = '--';
ax.MinorGridLineStyle = ':';
ax.GridColor = [0.65 0.65 0.65];
ax.MinorGridColor = [0.35 0.35 0.35];
ax.GridAlpha = 0.35;
ax.MinorGridAlpha = 0.45;
legend
xlabel('even symbols');
ylabel('odd symbols');
axis equal; grid on;
axis equal;
grid on;
grid minor;
ax.Layer = 'top';
end

View File

@@ -4,7 +4,7 @@ arguments
options.postfilter_taps = NaN
options.fignum (1,1) double = NaN % Default to NaN if not provided
options.displayname (1,:) char = '' % Default to an empty string if not provided
options.color = [0.2157 0.4941 0.7216];
options.color = [];
end
% Determine the figure number to use or create a new figure
@@ -16,12 +16,14 @@ end
hold on
ax = gca;
% N = numel(ax.Children);
N = sum(arrayfun(@(x) strcmp(x.LineStyle, '-'), ax.Children));
cmap = linspecer(8);
options.color = cmap(mod(N, size(cmap, 1)) + 1, :);
if isempty(options.color)
N = sum(arrayfun(@(x) strcmp(x.LineStyle, '-'), ax.Children));
cmap = linspecer(8);
options.color = cmap(mod(N, size(cmap, 1)) + 1, :);
end
% Ensure the figure is ready before calling spectrum
eq_noise.spectrum("displayname", options.displayname, "fignum", fig.Number, "normalizeTo0dB", 1,"color",options.color);
eq_noise.spectrum("displayname", options.displayname, "fignum", fig.Number, "normalizeTo0dB", 0,"color",options.color);
if ~isnan(options.postfilter_taps)
% Hold on to the figure for further plotting

View File

@@ -6,7 +6,8 @@ arguments
options.fs_rx
options.fignum (1,1) double = NaN % Default to NaN if not provided
options.displayname (1,:) char = '' % Default to an empty string if not provided
options.color = [0.2157 0.4941 0.7216];
options.color = [];
options.linestyle = '-';
end
% Determine the figure number to use or create a new figure
@@ -30,42 +31,52 @@ end
ax = gca;
% N = numel(ax.Children);
N = sum(arrayfun(@(x) strcmp(x.LineStyle, '-'), ax.Children));
cmap = linspecer(8);
options.color = cmap(mod(N, size(cmap, 1)) + 1, :);
% Ensure the figure is ready before calling spectrum
title('SNR of received Signal')
if isempty(options.color)
N = sum(arrayfun(@(x) strcmp(x.LineStyle, '-'), ax.Children));
cmap = linspecer(8);
options.color = cmap(mod(N, size(cmap, 1)) + 1, :);
end
fft_length = 2^(nextpow2(length(eq_signal))-7);
[s_lin,w] = pwelch(eq_signal,hanning(fft_length),fft_length/2,fft_length,options.fs_tx,"centered","psd","mean");
[n_lin,w] = pwelch(noise_signal,hanning(fft_length),fft_length/2,fft_length,options.fs_rx,"centered","psd","mean");
[n_lin,w_noise] = pwelch(noise_signal,hanning(fft_length),fft_length/2,fft_length,options.fs_rx,"centered","psd","mean");
if numel(w_noise) ~= numel(w) || any(abs(w_noise - w) > max(options.fs_tx,options.fs_rx)*eps)
n_lin = interp1(w_noise,n_lin,w,"linear",NaN);
end
w = w.*1e-9;
snr_dbm = 10*log10(s_lin./n_lin);
snr_lin = s_lin./n_lin;
snr_lin = movmean(snr_lin,10);
snr_dbm = 10*log10(snr_lin);
% figure(231)
hold on
plot(w,snr_dbm,'DisplayName','SNR','LineWidth',0.5,'Color',options.color);
yline(mean(snr_dbm),'HandleVisibility','off','Color',options.color);
if isempty(options.displayname)
options.displayname = 'SNR';
end
plot(w,snr_dbm,'DisplayName',options.displayname,'LineWidth',1,'Color',options.color,'LineStyle',options.linestyle);
% yline(mean(snr_dbm),'HandleVisibility','off','Color',options.color,'LineStyle','--','LineWidth',1);
xlabel("Frequency in GHz");
edgetick = 2^(nextpow2(options.fs_tx*1e-9));
ticks = -edgetick:16:edgetick;
xticks(ticks);
[~,b]=min(abs((-edgetick:16:edgetick)-max(w)));
xlim([-ticks(b+1) ticks(b+1)]);
ylabel("SNR (dB)");
xlim([min(w) max(w)]);
max_snr = ceil(max(snr_dbm)/10)*10;
min_snr = floor(min(snr_dbm)/10)*10;
ylim([min_snr,max_snr]);
yticks(-200:10:100);
y_min = min(snr_dbm(:));
y_max = max(snr_dbm(:));
y_range = y_max - y_min;
if y_range == 0
y_range = 10;
end
y_margin = 0.05 * y_range;
ylim([y_min - y_margin, y_max + y_margin]);
try
yticks(round(linspace(y_min, y_max, min(10, max(4, ceil(y_range/10))))));
end
grid on; grid minor;
legend('Interpreter','none');
title('Noise of soft decision signal (not MLSE)');
grid on;
if isempty(get(gca, 'Legend'))
legend('Interpreter','none');
end
end

View File

@@ -6,6 +6,7 @@ arguments
fs
options.fignum (1,1) double = NaN % Default to NaN if not provided
options.displayname (1,:) char = '' % Default to an empty string if not provided
options.color = [];
end
% Assuming that obj.e contains the final FFE filter coefficients.
@@ -34,20 +35,24 @@ end
end
% Magnitude response (in dB)
subplot(2,1,1);
% subplot(2,1,1);
hold on
plot(f.*1e-9, H_db,'DisplayName',options.displayname);
if isempty(options.color)
plot(f.*1e-9, H_db,'DisplayName',options.displayname,'LineWidth',1);
else
plot(f.*1e-9, H_db,'DisplayName',options.displayname,'Color',options.color,'LineWidth',1);
end
title('(Inverted) Magnitude Response of FFE Filter');
xlabel('Frequency (GHz)');
ylabel('Magnitude (dB)');
grid on;
% Phase response
subplot(2,1,2);
plot(f.*1e-9, unwrap(angle(H)),'DisplayName',options.displayname);
title('Phase Response of FFE Filter');
xlabel('Frequency (GHz)');
ylabel('Phase');
grid on;
% % Phase response
% subplot(2,1,2);
% plot(f.*1e-9, unwrap(angle(H)),'DisplayName',options.displayname);
% title('Phase Response of FFE Filter');
% xlabel('Frequency (GHz)');
% ylabel('Phase');
% grid on;
end

View File

@@ -4,6 +4,8 @@ arguments
ref_symbols
options.fignum (1,1) double = NaN % Default to NaN if not provided
options.displayname (1,:) char = '' % Default to an empty string if not provided
options.ref_symbol_uncoded = []
options.nbins (1,1) double = 1000
end
if isa(eq_signal,'Signal')
@@ -12,6 +14,20 @@ end
if isa(ref_symbols,'Signal')
ref_symbols = ref_symbols.signal;
end
if isa(options.ref_symbol_uncoded,'Signal')
options.ref_symbol_uncoded = options.ref_symbol_uncoded.signal;
end
eq_signal = eq_signal(:);
ref_symbols = ref_symbols(:);
ref_symbol_uncoded = options.ref_symbol_uncoded(:);
assert(numel(eq_signal) == numel(ref_symbols), ...
'showLevelHistogram:LengthMismatch', ...
'eq_signal and ref_symbols must have the same number of samples.');
assert(isempty(ref_symbol_uncoded) || numel(ref_symbol_uncoded) == numel(eq_signal), ...
'showLevelHistogram:LengthMismatch', ...
'options.ref_symbol_uncoded must have the same number of samples as eq_signal.');
% Determine the figure number to use or create a new figure
if isnan(options.fignum)
@@ -22,31 +38,70 @@ end
eq_signal = max(min(eq_signal,3),-3);
%%% Separate Classes
constellation = unique(ref_symbols);
received_sd = NaN(numel(constellation),length(ref_symbols));
lvlcol = cbrewer2('Paired',numel(constellation)*2);
lvlcol = lvlcol(2:2:end,:);
lvlcol = linspecer(numel(constellation));
% lvlcol = cbrewer2('Set1',numel(constellation));
for lvl = 1:numel(constellation)
%Separate the equalized signal into the
%respective levels based on the actually
%transmitted level!
received_sd(lvl,ref_symbols==constellation(lvl)) = eq_signal(ref_symbols==constellation(lvl));
end
% scaling = PAMmapper(numel(constellation),0).get_scaling;
%%% FFE histogram
%%% histogram
clf
for lvl = 1:numel(constellation)
intermediate = received_sd(lvl,:);
cnt(lvl) = round(numel(intermediate(~isnan(intermediate)))./length(eq_signal),3).*100;
hold on
warning off
histogram(received_sd(lvl,:),1000,"EdgeAlpha",0,'DisplayName',['Lvl ',num2str(lvl),' ; ',num2str(cnt(lvl)),' '],'FaceColor',lvlcol(lvl,:),'Normalization','pdf');
warning on
if isempty(ref_symbol_uncoded)
% Normal mode: split the received signal by the actually
% transmitted reference level.
constellation = unique(ref_symbols);
received_sd = NaN(numel(constellation),numel(ref_symbols));
lvlcol = linspecer(numel(constellation));
for lvl = 1:numel(constellation)
class_mask = ref_symbols == constellation(lvl);
received_sd(lvl,class_mask) = eq_signal(class_mask);
end
for lvl = 1:numel(constellation)
intermediate = received_sd(lvl,:);
cnt(lvl) = round(numel(intermediate(~isnan(intermediate)))./numel(eq_signal),3).*100;
hold on
warning off
histogram(received_sd(lvl,:),options.nbins, ...
"EdgeAlpha",0, ...
"DisplayName",['Lvl ',num2str(lvl),' ; ',num2str(cnt(lvl)),' '], ...
"FaceColor",lvlcol(lvl,:), ...
"Normalization","pdf");
warning on
end
else
% Plot p(y | x_n): y is the noisy observation and x_n is the
% uncoded PAM class. For duobinary this naturally gives multi-modal
% PDFs because one x_n class can map to multiple DB amplitudes. Each
% DB lobe is drawn separately so the DB-level structure stays visible.
db_constellation = unique(ref_symbols);
classes = unique(ref_symbol_uncoded);
lvlcol = linspecer(numel(classes));
for db_lvl = 1:numel(db_constellation)
db_mask = ref_symbols == db_constellation(db_lvl);
mapped_class = mode(ref_symbol_uncoded(db_mask));
[~,class_idx] = min(abs(classes - mapped_class));
cnt = round(nnz(ref_symbol_uncoded == mapped_class)./numel(eq_signal),3).*100;
if db_lvl == findFirstMappedDbLevel(ref_symbols,ref_symbol_uncoded,db_constellation,mapped_class)
display_name = ['p(y|x_',num2str(class_idx),') ; ',num2str(cnt),' '];
display_name = ['p(y|x_',num2str(class_idx),')'];
handle_visibility = "on";
else
display_name = ['p(y|x_',num2str(class_idx),') ; ',num2str(cnt),' '];
display_name = ['p(y|x_',num2str(class_idx),')'];
handle_visibility = "off";
end
weighted_lobe = NaN(size(eq_signal));
weighted_lobe(db_mask) = eq_signal(db_mask);
hold on
warning off
histogram(weighted_lobe,options.nbins, ...
"EdgeAlpha",0, ...
"DisplayName",display_name, ...
"FaceColor",lvlcol(class_idx,:), ...
"HandleVisibility",handle_visibility, ...
"Normalization","pdf");
warning on
end
end
xlim([-3 3]);
legend
@@ -58,3 +113,15 @@ end
end
function first_db_lvl = findFirstMappedDbLevel(ref_symbols,ref_symbol_uncoded,db_constellation,mapped_class)
first_db_lvl = NaN;
for db_lvl = 1:numel(db_constellation)
db_mask = ref_symbols == db_constellation(db_lvl);
if mode(ref_symbol_uncoded(db_mask)) == mapped_class
first_db_lvl = db_lvl;
return
end
end
end

View File

@@ -0,0 +1,35 @@
function showMarkovDiagram(sequence,M)
if isa(sequence,'Signal')
sequence = sequence.signal;
end
sequence = sequence(2+mod(1,length(sequence)):end); %filtered sequences often have one "old" sample at idx=1
x = sequence;
levels = sort(unique(x)).'; % or provide known 1x6 level values
[~,ix] = min(abs(x - levels),[],2);
x = levels(ix);
K = numel(levels);
% map to state indices 1..K
[tf, idx] = ismember(x, levels);
idx = idx(:);
from = idx(1:end-1);
to = idx(2:end);
from = idx(1:2:end);
to = idx(2:2:end);
% counts C(from,to)
C = accumarray([from,to], 1, [K K], @sum, 0);
% row-stochastic transition matrix P(to|from)
rowSums = sum(C,2);
P = C ./ max(rowSums,1);
mc = dtmc(P, 'StateNames', string(levels.*PAMmapper(M,0).get_scaling));
figure('Name','Markov Graph (dtmc)');
gp = graphplot(mc, 'ColorEdges',true, 'LabelEdges',true);
end

View File

@@ -0,0 +1,40 @@
function showTransitionProbabilities(sequence)
if isa(sequence,'Signal')
sequence = sequence.signal;
end
sequence = sequence(2+mod(1,length(sequence)):end); %filtered sequences often have one "old" sample at idx=1
x = sequence;
levels = sort(unique(x)).'; % or provide known 1x6 level values
[~,ix] = min(abs(x - levels),[],2);
x = levels(ix);
K = numel(levels);
% map to state indices 1..K
[tf, idx] = ismember(x, levels);
idx = idx(:);
% from = idx(1:end-1);
% to = idx(2:end);
from = idx(1:2:end);
to = idx(2:2:end);
% counts C(from,to)
C = accumarray([from,to], 1, [K K], @sum, 0);
% row-stochastic transition matrix P(to|from)
rowSums = sum(C,2);
P = C ./ max(rowSums,1);
%% 1) HEATMAP (which transitions are more probable?)
figure('Name','Transition Probabilities (to | from)');
h = heatmap(levels, levels, P, 'Colormap', parula, 'ColorbarVisible','on');
colormap(gca,[[1,1,1];flip(cbrewer2('Spectral',100))]);clim([0,ceil(max(P(:))*10)/10]);
h.XLabel = 'From state (level)';
h.YLabel = 'To state (level)';
h.Title = 'P(to | from)';
end

View File

@@ -1,6 +1,6 @@
% Define the precomp path
precomp_path = "C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\precomp";
precomp_path = "W:\labdata\sioe_labor\precomp";
precomp_path = "C:\Users\Silas\Documents\MATLAB\imdd_simulation\projects\ECOC_2025_MPI";
% Step 1: Find all valid files (assume .mat files for ChannelFreqResp)
fileList = dir(fullfile(precomp_path, '*.mat'));
fileNames = {fileList.name};

View File

@@ -1,9 +1,12 @@
function mat2tikz_improved(filename)
function mat2tikz_improved(filename,options)
arguments
% Default to the path in your example if no argument is provided
filename (1,1) string = 'C:\Users\Silas\Documents\Dissertation\00_Examples\tikz\textfig.tikz';
options.cleanfigure = false;
end
if options.cleanfigure
cleanfigure;
end
cleanfigure;
matlab2tikz(char(filename), ...
'width', '\fwidth', ...
'height', '\fheight', ...