Add new functions
This commit is contained in:
150
Functions/EQ_visuals/analyzeEQperformance.m
Normal file
150
Functions/EQ_visuals/analyzeEQperformance.m
Normal file
@@ -0,0 +1,150 @@
|
||||
function analyzeEQperformance(ref_bits,ref_symbols,rx_signal,eq_signal,eq_decisions,fsym,M,options)
|
||||
arguments
|
||||
ref_bits
|
||||
ref_symbols
|
||||
rx_signal
|
||||
eq_signal
|
||||
eq_decisions
|
||||
fsym
|
||||
M
|
||||
options.postfilterclass
|
||||
options.eqclass
|
||||
options.mlseclass
|
||||
options.db_precoded
|
||||
options.displayname
|
||||
end
|
||||
|
||||
% toolkit to visualize stuff related to DSP of IM/DD
|
||||
%%% Preps
|
||||
if isempty(eq_decisions)
|
||||
eq_decisions = PAMmapper(M,0).quantize(eq_signal);
|
||||
end
|
||||
|
||||
%%% Demap eqlzd signal to determine BER
|
||||
if options.db_precoded
|
||||
eq_hd = PAMmapper(M,0).quantize(eq_signal);
|
||||
eq_hd = Duobinary().encode(eq_hd);
|
||||
eq_hd = Duobinary().decode(eq_hd,"M",M);
|
||||
rx_bits = PAMmapper(M,0).demap(eq_hd);
|
||||
else
|
||||
rx_bits = PAMmapper(M,0).demap(eq_signal);
|
||||
end
|
||||
|
||||
[~,numerr,ber_sd,errpos] = calc_ber(rx_bits.signal,ref_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||
% fprintf('SD BER: %.2e \n',ber_sd);
|
||||
|
||||
%%% Demap provided decisions to determine BER
|
||||
rx_bits = PAMmapper(M,0).demap(eq_decisions);
|
||||
[~,numerr,ber_mlse,errpos] = calc_ber(rx_bits.signal,ref_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||
% fprintf('MLSE BER: %.2e \n',ber_mlse);
|
||||
|
||||
|
||||
|
||||
%%% Noise prior to DSP (is thius accurate with resampling?)
|
||||
rx_resampled = rx_signal.normalize("mode","rms").resample("fs_out",fsym);
|
||||
rx_noise = rx_resampled-ref_symbols;
|
||||
|
||||
%%% Noise after to soft-decision DSP
|
||||
eq_noise = eq_signal-ref_symbols;
|
||||
|
||||
|
||||
col = cbrewer2('paired',12);
|
||||
lines = numel(findall(figure(200), 'Type', 'Line'))+1;
|
||||
darkcoloridx = max(mod(2*lines,12),2);
|
||||
lightcoloridx = max(mod(2*lines-1,12),1);
|
||||
|
||||
%%% Separate Classes
|
||||
constellation = unique(ref_symbols.signal);
|
||||
received_sd = NaN(numel(constellation),length(ref_symbols));
|
||||
received_hd = NaN(numel(constellation),length(ref_symbols));
|
||||
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.signal==constellation(lvl)) = eq_signal.signal(ref_symbols.signal==constellation(lvl));
|
||||
received_hd(lvl,ref_symbols.signal==constellation(lvl)) = eq_decisions.signal(ref_symbols.signal==constellation(lvl));
|
||||
end
|
||||
|
||||
%%% bursts
|
||||
% Find differences between consecutive elements
|
||||
diff_indices = diff(errpos);
|
||||
|
||||
% Identify the start of new sequences (when the difference is not 1)
|
||||
sequence_starts = [1, find(diff_indices ~= 1) + 1]; % Include the first index
|
||||
sequence_ends = [sequence_starts(2:end) - 1, length(errpos)]; % Calculate end indices
|
||||
|
||||
% Initialize burst count and print bursts longer than 10
|
||||
burst_len = 1:10;
|
||||
burst_count = zeros(length(burst_len),1);
|
||||
for t = 1:numel(burst_len)
|
||||
for i = 1:length(sequence_starts)
|
||||
% Extract current sequence
|
||||
current_burst = errpos(sequence_starts(i):sequence_ends(i));
|
||||
% Check if the sequence length matches criterion
|
||||
if length(current_burst) == burst_len(t)
|
||||
burst_count(t) = burst_count(t) + 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
burst_symbols = burst_count .* burst_len';
|
||||
burst_rate = burst_symbols ;%./ length(rx_signal);
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
%%% Rx Spectrum %200
|
||||
rx_signal.spectrum("displayname",sprintf('Rx %d GBd PAM%d',fsym.*1e-9,M),'fignum',200,'normalizeTo0dB',1,'color',col(darkcoloridx,:));
|
||||
xline([-fsym/2,fsym/2].*1e-9,'Color',col(mod(lines,12)+2,:),'HandleVisibility','off');
|
||||
ylim([-20,3]);
|
||||
%%% EQ Spectrum
|
||||
%
|
||||
|
||||
%%% EQ Time Series %210
|
||||
showEQTimeSignal(eq_signal,ref_symbols)
|
||||
|
||||
|
||||
%%% EQ Noise Spectrum + inverted Postfilter %220
|
||||
showEQNoisePSD(eq_noise,options.postfilterclass.burg_coeff,"fignum",220,"color",col(darkcoloridx,:));
|
||||
|
||||
%%% EQ SNR Spectrum %230
|
||||
fft_length = 2^13;
|
||||
[s_lin,w] = pwelch(eq_signal.signal,hanning(fft_length),fft_length/2,fft_length,eq_signal.fs,"centered","psd","mean");
|
||||
[n_lin,w] = pwelch(eq_noise.signal,hanning(fft_length),fft_length/2,fft_length,eq_noise.fs,"centered","psd","mean");
|
||||
w = w.*1e-9;
|
||||
snr_dbm = 10*log10(s_lin./n_lin);
|
||||
|
||||
figure(230)
|
||||
hold on
|
||||
plot(w,snr_dbm,'DisplayName','SNR after EQ','LineWidth',1,'Color',col(darkcoloridx,:));
|
||||
xlabel("Frequency in GHz");
|
||||
edgetick = 2^(nextpow2(eq_signal.fs*1e-9));
|
||||
xticks(-edgetick:16:edgetick);
|
||||
xlim([-128 128]);
|
||||
ylim([-20,35]);
|
||||
grid minor
|
||||
yticks(-200:10:100);
|
||||
grid on; grid minor;
|
||||
legend('Interpreter','none');
|
||||
title('Noise of soft decision signal (not MLSE)');
|
||||
|
||||
%%% FFE histogram %240
|
||||
showLevelHistogram(eq_signal,ref_symbols)
|
||||
|
||||
%%% Confusion Matrix
|
||||
showLevelConfusionMatrix(eq_decisions,ref_symbols,"fignum",250)
|
||||
|
||||
|
||||
%%% Burst Count
|
||||
figure(260)
|
||||
hold on
|
||||
plot(burst_len,burst_rate,'Marker','x','Color',col(darkcoloridx,:),"displayname",sprintf('Rx %d GBd PAM%d; %s',fsym.*1e-9,M,options.displayname));
|
||||
xlabel('length of error burst');
|
||||
ylabel('occurences')
|
||||
grid on
|
||||
set(gca, 'YScale', 'log');
|
||||
|
||||
|
||||
autoArrangeFigures
|
||||
|
||||
end
|
||||
44
Functions/EQ_visuals/showEQNoisePSD.m
Normal file
44
Functions/EQ_visuals/showEQNoisePSD.m
Normal file
@@ -0,0 +1,44 @@
|
||||
function showEQNoisePSD(eq_noise, options)
|
||||
arguments
|
||||
eq_noise
|
||||
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];
|
||||
end
|
||||
|
||||
% Determine the figure number to use or create a new figure
|
||||
if isnan(options.fignum)
|
||||
fig = figure; % Create a new figure and get its handle
|
||||
else
|
||||
fig = figure(options.fignum); % Use the specified figure number
|
||||
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, :);
|
||||
|
||||
% Ensure the figure is ready before calling spectrum
|
||||
eq_noise.spectrum("displayname", options.displayname, "fignum", fig.Number, "normalizeTo0dB", 1,"color",options.color);
|
||||
title('Noise of soft decision signal (not MLSE)')
|
||||
|
||||
if ~isnan(options.postfilter_taps)
|
||||
% Hold on to the figure for further plotting
|
||||
hold on;
|
||||
|
||||
% Compute the frequency response of the postfilter
|
||||
[h, w] = freqz(1, options.postfilter_taps, length(eq_noise), "whole", eq_noise.fs);
|
||||
h = h / max(abs(h)); % Normalize the filter response
|
||||
|
||||
% Adjust frequency axis to center at 0
|
||||
w_ = (w - eq_noise.fs / 2);
|
||||
|
||||
% Plot the inverted postfilter response
|
||||
plot(w_ * 1e-9, 20 * log10(fftshift(abs(h))), 'DisplayName', ['Burg Coeffs: ', num2str(round(options.postfilter_taps, 2)), ' '], 'LineWidth', 1,'Color',options.color,'LineStyle','--');
|
||||
|
||||
% Ensure a legend is displayed
|
||||
legend('show');
|
||||
end
|
||||
end
|
||||
70
Functions/EQ_visuals/showEQNoiseSNR.m
Normal file
70
Functions/EQ_visuals/showEQNoiseSNR.m
Normal file
@@ -0,0 +1,70 @@
|
||||
function showEQNoiseSNR(tx_signal, rx_signal, options)
|
||||
arguments
|
||||
tx_signal
|
||||
rx_signal
|
||||
options.fs_tx
|
||||
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];
|
||||
end
|
||||
|
||||
% Determine the figure number to use or create a new figure
|
||||
if isnan(options.fignum)
|
||||
fig = figure; % Create a new figure and get its handle
|
||||
else
|
||||
fig = figure(options.fignum); % Use the specified figure number
|
||||
end
|
||||
|
||||
if isa(tx_signal,'Signal')
|
||||
options.fs_tx = tx_signal.fs;
|
||||
tx_signal = tx_signal.signal;
|
||||
end
|
||||
if isa(rx_signal,'Signal')
|
||||
options.fs_rx = rx_signal.fs;
|
||||
rx_signal = rx_signal.signal;
|
||||
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, :);
|
||||
|
||||
% Ensure the figure is ready before calling spectrum
|
||||
title('SNR of received Signal')
|
||||
|
||||
fft_length = 2^(nextpow2(length(tx_signal))-7);
|
||||
|
||||
[s_lin,w] = pwelch(tx_signal,hanning(fft_length),fft_length/2,fft_length,options.fs_tx,"centered","psd","mean");
|
||||
[n_lin,w] = pwelch(rx_signal,hanning(fft_length),fft_length/2,fft_length,options.fs_rx,"centered","psd","mean");
|
||||
|
||||
w = w.*1e-9;
|
||||
snr_dbm = 10*log10(s_lin./n_lin);
|
||||
|
||||
% figure(231)
|
||||
hold on
|
||||
plot(w,snr_dbm,'DisplayName','SNR','LineWidth',0.5,'Color',options.color);
|
||||
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)]);
|
||||
|
||||
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);
|
||||
|
||||
grid on; grid minor;
|
||||
legend('Interpreter','none');
|
||||
title('Noise of soft decision signal (not MLSE)');
|
||||
|
||||
|
||||
end
|
||||
54
Functions/EQ_visuals/showEQTimeSignal.m
Normal file
54
Functions/EQ_visuals/showEQTimeSignal.m
Normal file
@@ -0,0 +1,54 @@
|
||||
function showEQTimeSignal(eq_signal,ref_symbols,options)
|
||||
|
||||
arguments
|
||||
eq_signal
|
||||
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 = [0.2157 0.4941 0.7216];
|
||||
end
|
||||
% Determine the figure number to use or create a new figure
|
||||
if isnan(options.fignum)
|
||||
fig = figure; % Create a new figure and get its handle
|
||||
else
|
||||
fig = figure(options.fignum); % Use the specified figure number
|
||||
end
|
||||
|
||||
|
||||
M = numel(unique(ref_symbols.signal));
|
||||
lvlcol = cbrewer2('Set1',M);
|
||||
col = cbrewer2('paired',2);
|
||||
|
||||
eq_decisions = PAMmapper(M,0).quantize(eq_signal);
|
||||
rx_bits = PAMmapper(M,0).demap(eq_signal);
|
||||
ref_bits = PAMmapper(M,0).demap(ref_symbols);
|
||||
|
||||
%%% Separate Classes
|
||||
constellation = unique(ref_symbols.signal);
|
||||
received_sd = NaN(numel(constellation),length(ref_symbols));
|
||||
received_hd = NaN(numel(constellation),length(ref_symbols));
|
||||
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.signal==constellation(lvl)) = eq_signal.signal(ref_symbols.signal==constellation(lvl));
|
||||
received_hd(lvl,ref_symbols.signal==constellation(lvl)) = eq_decisions.signal(ref_symbols.signal==constellation(lvl));
|
||||
end
|
||||
|
||||
[~,numerr,ber_sd,errpos] = calc_ber(rx_bits.signal,ref_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||
|
||||
%%% EQ Time Series %210
|
||||
eq_signal.plot("fignum",fig.Number,"displayname",'Equalized Signal','color',col(1,:),'clear',1);
|
||||
hold on
|
||||
|
||||
try
|
||||
yline(PAMmapper(M,0).get_demodulation_thresholds,'HandleVisibility','off','LineStyle','--');
|
||||
|
||||
for c = 1:M
|
||||
scatter(errpos./eq_signal.fs,received_sd(c,errpos),1,'x','MarkerEdgeColor',lvlcol(c,:),'LineWidth',2,'DisplayName',sprintf('Tx Lvl: %d',c));
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
58
Functions/EQ_visuals/showEQcoefficients.m
Normal file
58
Functions/EQ_visuals/showEQcoefficients.m
Normal file
@@ -0,0 +1,58 @@
|
||||
function showEQcoefficients(n1, n2, n3, options)
|
||||
% Show filter coefficients as stem plot
|
||||
% n1, n2, and n3 in different subplots
|
||||
% Scale all y-axis to -1 and 1
|
||||
|
||||
arguments
|
||||
n1
|
||||
n2
|
||||
n3
|
||||
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.clf = 0; % Clear figure before plotting new
|
||||
end
|
||||
|
||||
% Determine the figure number to use or create a new figure
|
||||
if isnan(options.fignum)
|
||||
fig = figure; % Create a new figure and get its handle
|
||||
else
|
||||
fig = figure(options.fignum); % Use the specified figure number
|
||||
end
|
||||
|
||||
if options.clf
|
||||
clf(fig); % Clear the figure if requested
|
||||
end
|
||||
|
||||
hold on
|
||||
ax = gca;
|
||||
N = numel(ax.Children);
|
||||
|
||||
% Set up a colormap for consistent coloring
|
||||
cmap = linspecer(8);
|
||||
options.color = cmap(mod(N, size(cmap, 1)) + 1, :);
|
||||
|
||||
% Create subplots for n1, n2, n3
|
||||
for i = 1:3
|
||||
subplot(3, 1, i);
|
||||
switch i
|
||||
case 1
|
||||
stem(n1, 'Color', options.color, 'LineWidth', 1,'Marker','.','MarkerSize',10);
|
||||
title(sprintf('1st order Filter Coefficients: %d',numel(n1)));
|
||||
case 2
|
||||
stem(n2, 'Color', options.color, 'LineWidth', 1,'Marker','.','MarkerSize',10);
|
||||
title(sprintf('2nd order Filter Coefficients: %d',numel(n2)));
|
||||
case 3
|
||||
stem(n3, 'Color', options.color, 'LineWidth', 1,'Marker','.','MarkerSize',10);
|
||||
title(sprintf('3rd order Filter Coefficients: %d',numel(n3)));
|
||||
end
|
||||
ylim([-1, 1]); % Scale y-axis to -1 and 1
|
||||
grid on;
|
||||
grid minor
|
||||
xlabel('Coefficient Index');
|
||||
ylabel('Amplitude');
|
||||
end
|
||||
|
||||
% Ensure the layout is tight for better visibility
|
||||
sgtitle('Filter Coefficients'); % Overall title
|
||||
end
|
||||
47
Functions/EQ_visuals/showErrorBurstCount.m
Normal file
47
Functions/EQ_visuals/showErrorBurstCount.m
Normal file
@@ -0,0 +1,47 @@
|
||||
function showErrorBurstCount(eq_signal,ref_symbols,options)
|
||||
arguments
|
||||
eq_signal
|
||||
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
|
||||
end
|
||||
|
||||
% Determine the figure number to use or create a new figure
|
||||
if isnan(options.fignum)
|
||||
fig = figure; % Create a new figure and get its handle
|
||||
else
|
||||
fig = figure(options.fignum); % Use the specified figure number
|
||||
end
|
||||
|
||||
if numel(unique(eq_signal.signal)) > 20
|
||||
M = numel(unique(ref_symbols.signal));
|
||||
eq_signal = PAMmapper(M,0).quantize(eq_signal);
|
||||
end
|
||||
|
||||
diff_indices = eq_signal.signal == ref_symbols.signal;
|
||||
|
||||
|
||||
% Identify the start of new sequences (when the difference is not 1)
|
||||
sequence_starts = [1, find(diff_indices ~= 1) + 1]; % Include the first index
|
||||
sequence_ends = [sequence_starts(2:end) - 1, length(errpos)]; % Calculate end indices
|
||||
|
||||
% Initialize burst count and print bursts longer than 10
|
||||
burst_len = 1:10;
|
||||
burst_count = zeros(length(burst_len),1);
|
||||
for t = 1:numel(burst_len)
|
||||
for i = 1:length(sequence_starts)
|
||||
% Extract current sequence
|
||||
current_burst = errpos(sequence_starts(i):sequence_ends(i));
|
||||
% Check if the sequence length matches criterion
|
||||
if length(current_burst) == burst_len(t)
|
||||
burst_count(t) = burst_count(t) + 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
burst_symbols = burst_count .* burst_len';
|
||||
burst_rate = burst_symbols ;%./ length(rx_signal);
|
||||
|
||||
|
||||
|
||||
end
|
||||
27
Functions/EQ_visuals/showLevelConfusionMatrix.m
Normal file
27
Functions/EQ_visuals/showLevelConfusionMatrix.m
Normal file
@@ -0,0 +1,27 @@
|
||||
function showLevelConfusionMatrix(decided_symbols,ref_symbols,options)
|
||||
arguments
|
||||
decided_symbols
|
||||
ref_symbols
|
||||
options.M = 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
|
||||
end
|
||||
|
||||
% Determine the figure number to use or create a new figure
|
||||
if isnan(options.fignum)
|
||||
fig = figure; % Create a new figure and get its handle
|
||||
else
|
||||
fig = figure(options.fignum); % Use the specified figure number
|
||||
end
|
||||
|
||||
if length(unique(decided_symbols.signal))>20
|
||||
assert(~isnan(options.M),'Provide either decided symbol sequence or modulation order M (PAM-4 -> M=4)');
|
||||
decided_symbols = PAMmapper(options.M,0).quantize(decided_symbols);
|
||||
end
|
||||
|
||||
%%% Confusion Matrix
|
||||
cm = confusionchart(ref_symbols.signal,decided_symbols.signal,'RowSummary','row-normalized','ColumnSummary','column-normalized','Title','Confusion Matrix','XLabel','Decisions','YLabel','Transmitted');
|
||||
|
||||
|
||||
end
|
||||
|
||||
50
Functions/EQ_visuals/showLevelHistogram.m
Normal file
50
Functions/EQ_visuals/showLevelHistogram.m
Normal file
@@ -0,0 +1,50 @@
|
||||
function showLevelHistogram(eq_signal,ref_symbols,options)
|
||||
arguments
|
||||
eq_signal
|
||||
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
|
||||
end
|
||||
|
||||
if isa(eq_signal,'Signal')
|
||||
eq_signal = eq_signal.signal;
|
||||
end
|
||||
if isa(ref_symbols,'Signal')
|
||||
ref_symbols = ref_symbols.signal;
|
||||
end
|
||||
|
||||
% Determine the figure number to use or create a new figure
|
||||
if isnan(options.fignum)
|
||||
fig = figure; % Create a new figure and get its handle
|
||||
else
|
||||
fig = figure(options.fignum); % Use the specified figure number
|
||||
end
|
||||
|
||||
%%% Separate Classes
|
||||
constellation = unique(ref_symbols);
|
||||
received_sd = NaN(numel(constellation),length(ref_symbols));
|
||||
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
|
||||
|
||||
|
||||
|
||||
%%% FFE 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
|
||||
histogram(received_sd(lvl,:),1000,"EdgeAlpha",0,'DisplayName',['Lvl ',num2str(lvl),' | ',num2str(cnt(lvl)),' %'],'FaceColor',lvlcol(lvl,:),'Normalization','pdf');
|
||||
end
|
||||
legend
|
||||
grid on
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user