664 lines
23 KiB
Matlab
664 lines
23 KiB
Matlab
%% Investigate stored std values per PAM level
|
|
% Assumes mpi_superview contains:
|
|
% run_id, pam_level, sir, interference_path_length, std_rawlevels, mean_rawlevels
|
|
% std_rawlevels / mean_rawlevels stored as JSON arrays, e.g. [0.1,0.2,0.3,0.4]
|
|
|
|
dsp_options.database_type = "mysql";
|
|
dsp_options.dataBase = "labor";
|
|
dsp_options.server = "192.168.178.192";
|
|
dsp_options.port = 3306;
|
|
dsp_options.user = "silas";
|
|
dsp_options.password = "silas";
|
|
|
|
db = DBHandler("dataBase", dsp_options.dataBase, "type", dsp_options.database_type, ...
|
|
"server", dsp_options.server, "port", dsp_options.port, ...
|
|
"user", dsp_options.user, "password", dsp_options.password);
|
|
|
|
|
|
|
|
|
|
|
|
%% Query
|
|
fp = QueryFilter();
|
|
% fp.where('Runs','run_id','GREATER_EQUAL',3153);
|
|
fp.where('Runs', 'fiber_length', 'EQUALS', 0);
|
|
fp.where('Runs', 'db_mode', 'EQUALS', '"no_db"');
|
|
fp.where('Runs', 'interference_path_length', 'NOT_EQUAL', 0);
|
|
fp.where('Runs', 'symbolrate', 'EQUALS', 112e9);
|
|
fp.where('Runs', 'pam_level','EQUALS', 4);
|
|
[dataTable,~] = db.queryDB(fp, db.getTableFieldNames('Runs'));
|
|
|
|
|
|
% Basic filtering
|
|
|
|
% Keep only rows with available level statistics
|
|
valid = hasStoredLevelStats(dataTable);
|
|
|
|
dataTable = dataTable(valid,:);
|
|
|
|
% % Optional analysis filters
|
|
% dataTable = dataTable(dataTable.sir < 25, :);
|
|
% dataTable = dataTable(dataTable.pam_level == 4, :);
|
|
|
|
nRuns = height(dataTable);
|
|
M = 8;
|
|
|
|
std_levels = nan(M,nRuns);
|
|
mean_levels = nan(M,nRuns);
|
|
var_levels = nan(M,nRuns);
|
|
std_slope = nan(nRuns,1);
|
|
var_slope = nan(nRuns,1);
|
|
var_offset = nan(nRuns,1);
|
|
gamma = nan(nRuns,1);
|
|
|
|
% Decode JSON arrays and compute variance slopes
|
|
|
|
for i = 1:nRuns
|
|
|
|
std_i = jsondecode(char(dataTable.std_rawlevels(i)));
|
|
mean_i = jsondecode(char(dataTable.mean_rawlevels(i)));
|
|
|
|
std_i = std_i(:);
|
|
mean_i = mean_i(:);
|
|
|
|
% Keep only valid entries
|
|
valid_i = isfinite(std_i) & isfinite(mean_i);
|
|
|
|
if ~sum(valid_i)
|
|
continue
|
|
end
|
|
std_i = std_i(valid_i);
|
|
mean_i = mean_i(valid_i);
|
|
|
|
% Sort by measured level mean
|
|
[mean_i, idx] = sort(mean_i, 'ascend');
|
|
std_i = std_i(idx);
|
|
|
|
var_i = std_i.^2;
|
|
|
|
% Store
|
|
std_levels(1:numel(std_i),i) = std_i;
|
|
mean_levels(1:numel(mean_i),i) = mean_i;
|
|
var_levels(1:numel(var_i),i) = var_i;
|
|
|
|
% 1) Fit variance over measured raw level mean
|
|
p_k = polyfit(mean_i, var_i, 1);
|
|
|
|
% 2) Normalized x-axis slope, better cross-PAM comparable
|
|
x_i = (mean_i - min(mean_i)) ./ (max(mean_i) - min(mean_i));
|
|
p_std = polyfit(x_i, std_i, 1);
|
|
std_slope(i) = p_std(1);
|
|
|
|
var_slope(i) = p_k(1);
|
|
var_offset(i) = p_k(2);
|
|
|
|
gamma(i) = std_i(end) / std_i(1);
|
|
end
|
|
|
|
% Add calculated values to table
|
|
dataTable.var_slope_calc = var_slope;
|
|
dataTable.std_slope_calc = std_slope;
|
|
dataTable.var_offset_calc = var_offset;
|
|
dataTable.gamma_calc = gamma;
|
|
|
|
dataTable.sir = -7 - dataTable.power_mpi_interference;
|
|
|
|
|
|
|
|
|
|
%% Plot 1: variance per level at fixed path length, grouped by PAM level
|
|
|
|
% NICHT GENUTZT
|
|
path_length_filter = -1;
|
|
idx_path = dataTable.interference_path_length > path_length_filter;
|
|
pam_levels = unique(dataTable.pam_level(idx_path));
|
|
cols = linspecer(numel(pam_levels));
|
|
figure; hold on;
|
|
sir_values_plot = dataTable.sir(idx_path & isfinite(dataTable.sir));
|
|
if isempty(sir_values_plot)
|
|
sir_limits = [0, 1];
|
|
else
|
|
sir_limits = [min(sir_values_plot), max(sir_values_plot)];
|
|
end
|
|
if diff(sir_limits) == 0
|
|
sir_limits = sir_limits + [-0.5, 0.5];
|
|
end
|
|
sir_cmap = cbrewer2('RdBu',256);%parula(256);
|
|
colormap(sir_cmap);
|
|
caxis(sir_limits);
|
|
mkr = ['+','o','*','square'];
|
|
for g = 1:numel(pam_levels)
|
|
|
|
pamLevel = pam_levels(g);
|
|
idx_g = idx_path & dataTable.pam_level == pamLevel;
|
|
|
|
mean_g = mean_levels(:,idx_g);
|
|
var_g = std_levels(:,idx_g);
|
|
run_sir_g = dataTable.sir(idx_g);
|
|
sir_g = repmat(dataTable.sir(idx_g).', M, 1);
|
|
run_id_g = repmat(dataTable.run_id(idx_g).', M, 1);
|
|
path_length_g = repmat(dataTable.interference_path_length(idx_g).', M, 1);
|
|
pam_level_g = repmat(dataTable.pam_level(idx_g).', M, 1);
|
|
|
|
% Scatter all runs
|
|
hScatter = scatter(mean_g(:), var_g(:), 5, sir_g(:), ...
|
|
'filled', ...
|
|
'MarkerFaceAlpha', 0.55, ...
|
|
'MarkerEdgeAlpha', 0.35, ...
|
|
'HandleVisibility','off');
|
|
|
|
for runIdx = 1:5:size(mean_g, 2)
|
|
if isfinite(run_sir_g(runIdx))
|
|
sirColorIdx = round(interp1(sir_limits, [1, size(sir_cmap,1)], run_sir_g(runIdx), 'linear', 'extrap'));
|
|
sirColorIdx = min(max(sirColorIdx, 1), size(sir_cmap,1));
|
|
lineColor = sir_cmap(sirColorIdx,:);
|
|
else
|
|
lineColor = [0.5, 0.5, 0.5];
|
|
end
|
|
|
|
hLine = plot(mean_g(:,runIdx), var_g(:,runIdx), ...
|
|
'LineWidth', 0.1, ...
|
|
'LineStyle', '-', ...
|
|
'Marker', 'none', ...
|
|
'HandleVisibility', 'off');
|
|
try
|
|
hLine.Color = [lineColor, 0.25];
|
|
catch
|
|
hLine.Color = lineColor;
|
|
end
|
|
end
|
|
|
|
hScatter.DataTipTemplate.DataTipRows(1).Label = 'mean level';
|
|
hScatter.DataTipTemplate.DataTipRows(2).Label = 'variance';
|
|
hScatter.DataTipTemplate.DataTipRows(3).Label = 'SIR';
|
|
hScatter.DataTipTemplate.DataTipRows(end+1) = dataTipTextRow('run id', run_id_g(:));
|
|
hScatter.DataTipTemplate.DataTipRows(end+1) = dataTipTextRow('interference length', path_length_g(:));
|
|
hScatter.DataTipTemplate.DataTipRows(end+1) = dataTipTextRow('pam_level', pam_level_g(:));
|
|
|
|
% Group mean curve
|
|
mean_level_g = mean(mean_g, 2, 'omitnan');
|
|
mean_var_g = mean(var_g, 2, 'omitnan');
|
|
|
|
plot(mean_level_g, mean_var_g, '-o', ...
|
|
'Color', [0,0,0], ...
|
|
'LineWidth', 2, ...
|
|
'MarkerFaceColor', cols(g,:), ...
|
|
'MarkerEdgeColor', cols(g,:), ...
|
|
'DisplayName', sprintf('PAM %.0f', pamLevel), 'MarkerSize', 5,'Marker','o');
|
|
end
|
|
|
|
grid on;
|
|
xlabel('Mean raw level');
|
|
ylabel('Stored level variance');
|
|
title(sprintf('Level variance at %.0f m path length, grouped by PAM level', path_length_filter));
|
|
legend('Location','best');
|
|
cb = colorbar;
|
|
ylabel(cb, 'SIR / dB');
|
|
|
|
%% Plot 1b: variance per level at fixed path length, grouped by SIR
|
|
|
|
sir_filter_max_slope = 60;
|
|
idx_path_sir = idx_path ...
|
|
& isfinite(dataTable.sir) ...
|
|
& dataTable.sir < sir_filter_max_slope;
|
|
|
|
sir_group_edges = [-inf,17.5 20, 22.5, 25, 30, 40, inf];
|
|
sir_group_labels = {'SIR < 17.5 dB','17.5 < SIR < 20 dB', '20 < SIR < 22.5 dB','22.5 < SIR < 25 dB', '25 < SIR < 30 dB', '30 < SIR < 40 dB', sprintf('40 < SIR < %.0f dB', sir_filter_max_slope)};
|
|
sir_group_cols = cbrewer2('RdBu',numel(sir_group_labels));
|
|
pam_marker_styles = {'o','square','diamond','^','v','>','<','pentagram','hexagram'};
|
|
|
|
figure; hold on;
|
|
pam_levels_plot = unique(dataTable.pam_level(idx_path_sir));
|
|
max_slope_lines = numel(sir_group_labels) * numel(pam_levels_plot);
|
|
slope_annotation_lines = cell(max_slope_lines, 1);
|
|
slope_annotation_idx = 0;
|
|
fit_line_x = cell(max_slope_lines, 1);
|
|
fit_line_y = cell(max_slope_lines, 1);
|
|
fit_line_color = cell(max_slope_lines, 1);
|
|
fit_line_label = cell(max_slope_lines, 1);
|
|
mean_point_x = cell(max_slope_lines, 1);
|
|
mean_point_y = cell(max_slope_lines, 1);
|
|
mean_point_marker = cell(max_slope_lines, 1);
|
|
fit_text_x = nan(max_slope_lines, 1);
|
|
fit_text_y = nan(max_slope_lines, 1);
|
|
fit_text_label = cell(max_slope_lines, 1);
|
|
fit_line_idx = 0;
|
|
|
|
for sirGroupIdx = numel(sir_group_labels):-1:1
|
|
idx_sir_group = idx_path_sir ...
|
|
& dataTable.sir > sir_group_edges(sirGroupIdx) ...
|
|
& dataTable.sir < sir_group_edges(sirGroupIdx+1);
|
|
|
|
if ~any(idx_sir_group)
|
|
continue
|
|
end
|
|
|
|
pam_levels_sir = unique(dataTable.pam_level(idx_sir_group));
|
|
for pamIdx = 1:numel(pam_levels_sir)
|
|
pamLevel = pam_levels_sir(pamIdx);
|
|
idx_sir_pam = idx_sir_group & dataTable.pam_level == pamLevel;
|
|
markerStyle = pam_marker_styles{mod(pamIdx-1,numel(pam_marker_styles))+1};
|
|
|
|
mean_g = mean_levels(:,idx_sir_pam);
|
|
var_g = std_levels(:,idx_sir_pam);
|
|
sir_g = repmat(dataTable.sir(idx_sir_pam).', M, 1);
|
|
run_id_g = repmat(dataTable.run_id(idx_sir_pam).', M, 1);
|
|
path_length_g = repmat(dataTable.interference_path_length(idx_sir_pam).', M, 1);
|
|
pam_level_g = repmat(dataTable.pam_level(idx_sir_pam).', M, 1);
|
|
|
|
hScatter = scatter(mean_g(:), var_g(:), 5, sir_group_cols(sirGroupIdx,:), markerStyle, ...
|
|
'filled', ...
|
|
'MarkerFaceAlpha', 0.25, ...
|
|
'MarkerEdgeAlpha', 0.20, ...
|
|
'HandleVisibility','off');
|
|
|
|
hScatter.DataTipTemplate.DataTipRows(1).Label = 'mean level';
|
|
hScatter.DataTipTemplate.DataTipRows(2).Label = 'std';
|
|
hScatter.DataTipTemplate.DataTipRows(end+1) = dataTipTextRow('SIR', sir_g(:));
|
|
hScatter.DataTipTemplate.DataTipRows(end+1) = dataTipTextRow('run id', run_id_g(:));
|
|
hScatter.DataTipTemplate.DataTipRows(end+1) = dataTipTextRow('interference length', path_length_g(:));
|
|
hScatter.DataTipTemplate.DataTipRows(end+1) = dataTipTextRow('pam_level', pam_level_g(:));
|
|
|
|
mean_level_g = mean(mean_g, 2, 'omitnan');
|
|
mean_std_g = mean(var_g, 2, 'omitnan');
|
|
valid_mean_curve = isfinite(mean_level_g) & isfinite(mean_std_g);
|
|
|
|
if nnz(valid_mean_curve) >= 2
|
|
p_mean_slope = polyfit(mean_level_g(valid_mean_curve), mean_std_g(valid_mean_curve), 1);
|
|
fit_x_g = linspace(min(mean_level_g(valid_mean_curve)), max(mean_level_g(valid_mean_curve)), 100);
|
|
fit_y_g = polyval(p_mean_slope, fit_x_g);
|
|
slope_text_g = strrep(sprintf('%.2f', p_mean_slope(1)), '.', ',');
|
|
label_x_g = fit_x_g(end);
|
|
label_y_g = fit_y_g(end);
|
|
else
|
|
fit_x_g = [];
|
|
fit_y_g = [];
|
|
slope_text_g = 'NaN';
|
|
label_x_g = NaN;
|
|
label_y_g = NaN;
|
|
end
|
|
slope_annotation_idx = slope_annotation_idx + 1;
|
|
slope_annotation_lines{slope_annotation_idx} = sprintf('%s, PAM %.0f: %s', sir_group_labels{sirGroupIdx}, pamLevel, slope_text_g);
|
|
|
|
fit_line_idx = fit_line_idx + 1;
|
|
mean_point_x{fit_line_idx} = mean_level_g;
|
|
mean_point_y{fit_line_idx} = mean_std_g;
|
|
mean_point_marker{fit_line_idx} = markerStyle;
|
|
fit_line_x{fit_line_idx} = fit_x_g;
|
|
fit_line_y{fit_line_idx} = fit_y_g;
|
|
fit_line_color{fit_line_idx} = sir_group_cols(sirGroupIdx,:);
|
|
fit_line_label{fit_line_idx} = sprintf('%s, PAM %.0f', sir_group_labels{sirGroupIdx}, pamLevel);
|
|
fit_text_x(fit_line_idx) = label_x_g;
|
|
fit_text_y(fit_line_idx) = label_y_g;
|
|
fit_text_label{fit_line_idx} = sprintf(' m=%s', slope_text_g);
|
|
end
|
|
end
|
|
|
|
for lineIdx = 1:fit_line_idx
|
|
plot(mean_point_x{lineIdx}, mean_point_y{lineIdx}, ...
|
|
'LineStyle', 'none', ...
|
|
'Color', fit_line_color{lineIdx}, ...
|
|
'Marker', 'x', ...
|
|
'MarkerFaceColor', fit_line_color{lineIdx}, ...
|
|
'MarkerEdgeColor', fit_line_color{lineIdx}, ...
|
|
'HandleVisibility', 'off', ...
|
|
'MarkerSize', 3);
|
|
|
|
plot(fit_line_x{lineIdx}, fit_line_y{lineIdx}, '-', ...
|
|
'Color', fit_line_color{lineIdx}, ...
|
|
'LineWidth', 0.8, ...
|
|
'DisplayName', fit_line_label{lineIdx});
|
|
|
|
text(fit_text_x(lineIdx), fit_text_y(lineIdx), fit_text_label{lineIdx}, ...
|
|
'Color', fit_line_color{lineIdx}, ...
|
|
'FontSize', 8, ...
|
|
'VerticalAlignment', 'middle', ...
|
|
'HorizontalAlignment', 'left', ...
|
|
'Interpreter', 'none');
|
|
end
|
|
|
|
grid on;
|
|
xlabel('Mean raw level');
|
|
ylabel('Stored level std');
|
|
title(sprintf('Mean level-std curves at %.0f m path length, grouped by SIR and PAM level', path_length_filter));
|
|
legend('Location','eastoutside');
|
|
slope_annotation_lines = slope_annotation_lines(1:slope_annotation_idx);
|
|
|
|
|
|
%% Plot 2: slope vs interference path length
|
|
|
|
figure; hold on;
|
|
valid = dataTable.interference_path_length > 0;
|
|
scatter(dataTable.interference_path_length(valid), dataTable.var_slope_calc(valid), ...
|
|
45, dataTable.sir(valid), 'filled');
|
|
|
|
grid on;
|
|
xlabel('Interference path length / m');
|
|
ylabel('Slope of level variance');
|
|
title('Level-variance slope vs. interference path length');
|
|
cb = colorbar;
|
|
ylabel(cb, 'SIR / dB');
|
|
|
|
%% Plot 3:
|
|
|
|
figure; hold on;
|
|
|
|
valid = dataTable.interference_path_length > 50;
|
|
|
|
sir_group_edges = [-inf,20, 30, inf];
|
|
for sirGroupIdx = 1:numel(sir_group_edges)-1
|
|
idx_sir_group = validSlopeSir ...
|
|
& dataTable.sir > sir_group_edges(sirGroupIdx) ...
|
|
& dataTable.sir < sir_group_edges(sirGroupIdx+1)...
|
|
& dataTable.interference_path_length > 50;
|
|
|
|
scatter(dataTable.sir(idx_sir_group), ...
|
|
dataTable.var_slope_calc(idx_sir_group), ...
|
|
8, 'filled', ...
|
|
'MarkerFaceColor', sir_group_cols(sirGroupIdx,:), ...
|
|
'MarkerEdgeColor', sir_group_cols(sirGroupIdx,:), ...
|
|
'MarkerFaceAlpha', 1, ...
|
|
'MarkerEdgeAlpha', 1, ...
|
|
'HandleVisibility','off');
|
|
end
|
|
|
|
set(gca, 'YScale', 'log');
|
|
grid on;
|
|
xlabel('SIR');
|
|
ylabel('Slope of level variance');
|
|
|
|
|
|
%% Plot 4:
|
|
|
|
sir_filter_max_slope = 60;
|
|
validSlopeSir = isfinite(dataTable.interference_path_length) ...
|
|
& isfinite(dataTable.var_slope_calc) ...
|
|
& isfinite(dataTable.sir) ...
|
|
& dataTable.sir < sir_filter_max_slope ...
|
|
& dataTable.interference_path_length > 0 ...
|
|
& dataTable.var_slope_calc > 0;
|
|
|
|
path_lengths_slope = unique(dataTable.interference_path_length(validSlopeSir));
|
|
|
|
sir_group_edges = [-inf,20, 30, inf];
|
|
sir_group_labels = {'SIR < 20 dB','20 < SIR < 30 dB', sprintf('30 < SIR < %.0f dB', sir_filter_max_slope)};
|
|
tmp_cols = cbrewer2('RdBu', numel(sir_group_labels)+4);
|
|
% remove 4 colors from the middle to avoid the bright central colors
|
|
mid = ceil(size(tmp_cols,1)/2);
|
|
rm_idx = mid + (-1:2); % two before mid and two after (2x2 removal centered)
|
|
rm_idx = max(1,min(size(tmp_cols,1),rm_idx));
|
|
tmp_cols(rm_idx,:) = [];
|
|
sir_group_cols = tmp_cols(1:numel(sir_group_labels),:);
|
|
|
|
|
|
figure(6);clf; hold on;
|
|
|
|
% Plot raw values first. Use one single-color scatter object per SIR group
|
|
% so matlab2tikz does not need unsupported RGB scatter CData.
|
|
for sirGroupIdx = 1:numel(sir_group_labels)
|
|
idx_sir_group = validSlopeSir ...
|
|
& dataTable.sir > sir_group_edges(sirGroupIdx) ...
|
|
& dataTable.sir < sir_group_edges(sirGroupIdx+1);
|
|
|
|
scatter(dataTable.interference_path_length(idx_sir_group), ...
|
|
dataTable.var_slope_calc(idx_sir_group), ...
|
|
8, 'filled', ...
|
|
'MarkerFaceColor', sir_group_cols(sirGroupIdx,:), ...
|
|
'MarkerEdgeColor', sir_group_cols(sirGroupIdx,:), ...
|
|
'MarkerFaceAlpha', 0.35, ...
|
|
'MarkerEdgeAlpha', 0.35, ...
|
|
'HandleVisibility','off');
|
|
end
|
|
|
|
% Plot grouped averages on top of the raw points.
|
|
for sirGroupIdx = 1:numel(sir_group_labels)
|
|
idx_sir_group = validSlopeSir ...
|
|
& dataTable.sir > sir_group_edges(sirGroupIdx) ...
|
|
& dataTable.sir < sir_group_edges(sirGroupIdx+1);
|
|
|
|
mean_slope = nan(numel(path_lengths_slope),1);
|
|
|
|
for g = 1:numel(path_lengths_slope)
|
|
idx_g = idx_sir_group ...
|
|
& dataTable.interference_path_length == path_lengths_slope(g);
|
|
slope_g = dataTable.var_slope_calc(idx_g);
|
|
slope_g = slope_g(isfinite(slope_g));
|
|
if numel(slope_g) >= 3
|
|
slope_g = slope_g(~isoutlier(slope_g, 'median'));
|
|
end
|
|
mean_slope(g) = mean(slope_g, 'omitnan');
|
|
end
|
|
|
|
valid_mean_slope = isfinite(mean_slope) & mean_slope > 0;
|
|
plot(path_lengths_slope(valid_mean_slope), mean_slope(valid_mean_slope), ...
|
|
'-o', ...
|
|
'Color', sir_group_cols(sirGroupIdx,:), ...
|
|
'MarkerFaceColor', sir_group_cols(sirGroupIdx,:), ...
|
|
'MarkerEdgeColor', sir_group_cols(sirGroupIdx,:), ...
|
|
'LineWidth', 1, ...
|
|
'DisplayName', sir_group_labels{sirGroupIdx});
|
|
end
|
|
|
|
xlim([10,1000])
|
|
ylim([0.006,0.1])
|
|
set(gca, 'XScale', 'log');
|
|
set(gca, 'YScale', 'log');
|
|
grid on;
|
|
xlabel('Interference path length / m');
|
|
ylabel('Mean slope of level variance');
|
|
title(sprintf('Grouped level-variance slope vs. interference path length, SIR < %.0f dB', sir_filter_max_slope));
|
|
xticks(path_lengths_slope);
|
|
xticklabels(compose('%.0f', path_lengths_slope));
|
|
legend('Location','northwest');
|
|
beautifyBERplot("setcolors",false)
|
|
% mat2tikz_improved('C:/Users/Silas/Documents/6971e0b65b380ca6d71c837f/04_Experimental_Evaluation/tikz/mpi/interference_path_len_vs_slope_logdomain.tikz');
|
|
|
|
|
|
%% Optional: slope vs SIR sanity check
|
|
|
|
figure; hold on;
|
|
sir_cmap = cbrewer2('RdBu',256);
|
|
|
|
validSlopeCategory = isfinite(dataTable.interference_path_length) ...
|
|
& isfinite(dataTable.std_slope_calc) ...
|
|
& isfinite(dataTable.sir);
|
|
path_lengths_plot = unique(dataTable.interference_path_length(validSlopeCategory));
|
|
sir_values_plot = dataTable.sir(validSlopeCategory);
|
|
if isempty(sir_values_plot)
|
|
sir_limits = [0, 1];
|
|
else
|
|
sir_limits = [min(sir_values_plot), max(sir_values_plot)];
|
|
end
|
|
if diff(sir_limits) == 0
|
|
sir_limits = sir_limits + [-0.5, 0.5];
|
|
end
|
|
colormap(sir_cmap);
|
|
caxis(sir_limits);
|
|
has_symbolrate = ismember('symbolrate', dataTable.Properties.VariableNames);
|
|
|
|
for g = 1:numel(path_lengths_plot)
|
|
idx_g = validSlopeCategory ...
|
|
& dataTable.interference_path_length == path_lengths_plot(g);
|
|
n_g = sum(idx_g);
|
|
sir_g = dataTable.sir(idx_g);
|
|
slope_g = dataTable.var_slope_calc(idx_g);
|
|
run_id_g = dataTable.run_id(idx_g);
|
|
pam_level_g = dataTable.pam_level(idx_g);
|
|
if has_symbolrate
|
|
symbolrate_g = dataTable.symbolrate(idx_g);
|
|
else
|
|
symbolrate_g = nan(n_g,1);
|
|
end
|
|
|
|
if n_g == 1 || range(sir_g) == 0
|
|
x_g = g * ones(n_g,1);
|
|
else
|
|
x_g = g + 0.9 * ((sir_g - min(sir_g)) ./ range(sir_g) - 0.5);
|
|
end
|
|
|
|
hScatter = scatter(x_g, slope_g, ...
|
|
5, sir_g, 'filled', ...
|
|
'DisplayName', sprintf('%.0f m', path_lengths_plot(g)));
|
|
hScatter.DataTipTemplate.DataTipRows(1).Label = 'interference path category';
|
|
hScatter.DataTipTemplate.DataTipRows(2).Label = 'slope';
|
|
hScatter.DataTipTemplate.DataTipRows(3).Label = 'SIR';
|
|
hScatter.DataTipTemplate.DataTipRows(end+1) = dataTipTextRow('run id', run_id_g);
|
|
hScatter.DataTipTemplate.DataTipRows(end+1) = dataTipTextRow('PAM format', pam_level_g);
|
|
hScatter.DataTipTemplate.DataTipRows(end+1) = dataTipTextRow('symbol rate', symbolrate_g);
|
|
end
|
|
|
|
grid on;
|
|
xlabel('Interference path length / m');
|
|
ylabel('Slope of level variance');
|
|
title('Level-variance slope grouped by interference path length');
|
|
xticks(1:numel(path_lengths_plot));
|
|
xticklabels(compose('%.0f', path_lengths_plot));
|
|
cb = colorbar;
|
|
ylabel(cb, 'SIR / dB');
|
|
|
|
%% Optional: 3D slope vs SIR by interference path length
|
|
|
|
figure(7);clf; hold on;
|
|
sir_cmap_3d = cbrewer2('RdBu',256);
|
|
|
|
validSlope3D = isfinite(dataTable.interference_path_length) ...
|
|
& isfinite(dataTable.var_slope_calc) ...
|
|
& isfinite(dataTable.sir);
|
|
path_lengths_3d = unique(dataTable.interference_path_length(validSlope3D));
|
|
path_categories_3d = 0:numel(path_lengths_3d)-1;
|
|
sir_values_3d = dataTable.sir(validSlope3D);
|
|
if isempty(sir_values_3d)
|
|
sir_limits_3d = [0, 1];
|
|
else
|
|
sir_limits_3d = [min(sir_values_3d), max(sir_values_3d)];
|
|
end
|
|
if diff(sir_limits_3d) == 0
|
|
sir_limits_3d = sir_limits_3d + [-0.5, 0.5];
|
|
end
|
|
colormap(gca, sir_cmap_3d);
|
|
clim(sir_limits_3d);
|
|
has_symbolrate = ismember('symbolrate', dataTable.Properties.VariableNames);
|
|
|
|
for g = 1:numel(path_lengths_3d)
|
|
idx_g = validSlope3D ...
|
|
& dataTable.interference_path_length == path_lengths_3d(g);
|
|
n_g = sum(idx_g);
|
|
sir_g = dataTable.sir(idx_g);
|
|
slope_g = dataTable.var_slope_calc(idx_g);
|
|
path_length_g = dataTable.interference_path_length(idx_g);
|
|
run_id_g = dataTable.run_id(idx_g);
|
|
pam_level_g = dataTable.pam_level(idx_g);
|
|
if has_symbolrate
|
|
symbolrate_g = dataTable.symbolrate(idx_g);
|
|
else
|
|
symbolrate_g = nan(n_g,1);
|
|
end
|
|
|
|
path_category_g = path_categories_3d(g) * ones(n_g,1);
|
|
hScatter = scatter3(path_category_g, sir_g, slope_g, ...
|
|
8, sir_g, 'filled', ...
|
|
'DisplayName', sprintf('%.0f m', path_lengths_3d(g)));
|
|
hScatter.DataTipTemplate.DataTipRows(1).Label = 'interference path category';
|
|
hScatter.DataTipTemplate.DataTipRows(2).Label = 'SIR';
|
|
hScatter.DataTipTemplate.DataTipRows(3).Label = 'slope';
|
|
hScatter.DataTipTemplate.DataTipRows(end+1) = dataTipTextRow('interference path length', path_length_g);
|
|
hScatter.DataTipTemplate.DataTipRows(end+1) = dataTipTextRow('run id', run_id_g);
|
|
hScatter.DataTipTemplate.DataTipRows(end+1) = dataTipTextRow('PAM format', pam_level_g);
|
|
hScatter.DataTipTemplate.DataTipRows(end+1) = dataTipTextRow('symbol rate', symbolrate_g);
|
|
end
|
|
|
|
set(gca, 'XScale', 'lin');
|
|
set(gca, 'YScale', 'lin');
|
|
set(gca, 'ZScale', 'log');
|
|
grid on;
|
|
box on;
|
|
xlabel('Interference path length / m');
|
|
ylabel('SIR / dB');
|
|
zlabel('Slope');
|
|
title('Level-variance slope vs. SIR by interference path length');
|
|
xticks(path_categories_3d);
|
|
xticklabels(compose('%.0f', path_lengths_3d));
|
|
view([-35 20]);
|
|
cb = colorbar;
|
|
ylabel(cb, 'SIR / dB');
|
|
|
|
|
|
%%
|
|
|
|
|
|
|
|
sir_all = -7 - dataTable.power_mpi_interference;
|
|
% for i = 1:height(dataTable)
|
|
% sigma_all(i,:) = jsondecode(char(dataTable.std_rawlevels(i)))';
|
|
% end
|
|
slope_var = dataTable.var_slope_calc;
|
|
slope_std = dataTable.std_slope_calc;
|
|
pl = dataTable.interference_path_length;
|
|
col = cbrewer2('RdBu',256);
|
|
% map path lengths to colormap indices
|
|
pl_unique = unique(pl(isfinite(pl)));
|
|
if isempty(pl_unique)
|
|
pl_idx = ones(size(pl));
|
|
else
|
|
% normalize pl to [1, size(col,1)]
|
|
pl_norm = (pl - min(pl_unique)) ./ max(1, (max(pl_unique)-min(pl_unique)));
|
|
pl_idx = round(1 + pl_norm * (size(col,1)-1));
|
|
pl_idx(~isfinite(pl_idx)) = 1;
|
|
end
|
|
|
|
figure(); hold on;
|
|
% scatter slope_var colored by path length
|
|
for i = 1:numel(sir_all)
|
|
scatter(sir_all(i), slope_var(i), 30, col(pl_idx(i),:), '.', 'MarkerEdgeColor', col(pl_idx(i),:));
|
|
end
|
|
% scatter slope_std colored by path length with different marker edge brightness
|
|
for i = 1:numel(sir_all)
|
|
scatter(sir_all(i), slope_std(i), 30, col(pl_idx(i),:), '.', 'MarkerEdgeColor', col(pl_idx(i),:));
|
|
end
|
|
cb = colorbar;
|
|
colormap(col);
|
|
caxis([min(pl_unique), max(pl_unique)]);
|
|
ylabel(cb, 'Interference path length / m');
|
|
|
|
function valid = hasStoredLevelStats(dataTable)
|
|
valid = ~cellfun(@isempty, cellstr(string(dataTable.std_rawlevels))) & ...
|
|
~cellfun(@isempty, cellstr(string(dataTable.mean_rawlevels)));
|
|
end
|
|
|
|
function [stdLevels, meanLevels] = decodeStoredLevelStats(dataTable)
|
|
nRuns = height(dataTable);
|
|
numLevels = 0;
|
|
stdCells = cell(nRuns, 1);
|
|
meanCells = cell(nRuns, 1);
|
|
|
|
for i = 1:nRuns
|
|
std_i = jsondecode(char(dataTable.std_rawlevels(i)));
|
|
mean_i = jsondecode(char(dataTable.mean_rawlevels(i)));
|
|
|
|
std_i = std_i(:);
|
|
mean_i = mean_i(:);
|
|
|
|
valid_i = isfinite(std_i) & isfinite(mean_i);
|
|
std_i = std_i(valid_i);
|
|
mean_i = mean_i(valid_i);
|
|
|
|
[mean_i, idx] = sort(mean_i, 'ascend');
|
|
std_i = std_i(idx);
|
|
|
|
stdCells{i} = std_i;
|
|
meanCells{i} = mean_i;
|
|
numLevels = max(numLevels, numel(std_i));
|
|
end
|
|
|
|
stdLevels = nan(numLevels, nRuns);
|
|
meanLevels = nan(numLevels, nRuns);
|
|
|
|
for i = 1:nRuns
|
|
std_i = stdCells{i};
|
|
mean_i = meanCells{i};
|
|
stdLevels(1:numel(std_i), i) = std_i;
|
|
meanLevels(1:numel(mean_i), i) = mean_i;
|
|
end
|
|
end
|
|
|