%% 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