FSO analysis:
- minimal changes in several files - new Timing Rec from Magnus
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
|
||||
base = "C:\Users\Silas\Nextcloud\Cluster";
|
||||
base = "C:\Users\Silas\Nextcloud4\Cluster";
|
||||
all_files = dir(fullfile(base, "**/*.mat"));
|
||||
|
||||
schemes = ["co","pair","alt","seg"];
|
||||
@@ -13,8 +13,8 @@ T = table('Size',[0 10], ...
|
||||
rx = "^WDM_(?<date>\d{8})_(?<time>\d{6})_n(?<node>\d+)_(?<jobid>\d+)_" + ...
|
||||
"(?<L>\d+)km_(?<Nch>\d+)ch_(?<df>\d+)ghz_(?<scheme>[a-z]+)_alpha(?<alpha>\d+(?:_\d+)?)\.mat$";
|
||||
|
||||
for k = 1:numel(all_files)
|
||||
f = all_files(k);
|
||||
for i = 1:numel(all_files)
|
||||
f = all_files(i);
|
||||
folder = string(f.folder);
|
||||
file = string(f.name);
|
||||
|
||||
@@ -44,6 +44,8 @@ for k = 1:numel(all_files)
|
||||
end
|
||||
|
||||
%%
|
||||
|
||||
|
||||
idx = strcmp(T.scheme,"co") & ...
|
||||
T.alpha == 0.4 & ...
|
||||
T.date >= datetime(2026,1,9) & ...
|
||||
@@ -51,13 +53,181 @@ idx = strcmp(T.scheme,"co") & ...
|
||||
|
||||
T_sel = T(idx,:);
|
||||
|
||||
i = 2;
|
||||
res = load(fullfile(T_sel.folder(i),T_sel.file(i)),'res');
|
||||
res = res.res;
|
||||
% ---- Load all res ----
|
||||
R = cell(numel(T_sel.file),1);
|
||||
for i = 1:numel(T_sel.file)
|
||||
S = load(fullfile(T_sel.folder(i),T_sel.file(i)),'res');
|
||||
S.res = strip_config_from_res(S.res);
|
||||
R{i} = S.res;
|
||||
end
|
||||
|
||||
res_all = combine_res_list(R);
|
||||
res_all = drop_empty_realizations(res_all);
|
||||
|
||||
|
||||
%%
|
||||
|
||||
|
||||
|
||||
%%
|
||||
|
||||
|
||||
%%
|
||||
% Routine A: plot BER curves and compute crossings
|
||||
S = plot_BER_vs_ROP(res, 'fec', 3.8e-3);
|
||||
S = plot_BER_vs_ROP(res_all, 'fec', 3.8e-3);
|
||||
|
||||
%% Routine B: violin plot (independent)
|
||||
plot_FEC_violin(res, 'tech','VNLE', 'fec',3.8e-3, 'ylim',[-10 0]);
|
||||
plot_FEC_violin(res_all, 'tech','VNLE', 'fec',3.8e-3, 'ylim',[-10 0],'eval_ptr',5);
|
||||
|
||||
|
||||
%%
|
||||
|
||||
function res = strip_config_from_res(res)
|
||||
% Remove the "config" payload from every non-empty result cell
|
||||
% Works whether entries are structs-with-field or objects-with-property.
|
||||
|
||||
techs = {'ffe','dfe','vnle','mlse','dbt'};
|
||||
|
||||
for t = 1:numel(techs)
|
||||
fn = techs{t};
|
||||
if ~isfield(res, fn) || isempty(res.(fn)), continue; end
|
||||
|
||||
C = res.(fn);
|
||||
if ~iscell(C), continue; end
|
||||
|
||||
idx = find(~cellfun('isempty', C)); % fast builtin
|
||||
for k = 1:numel(idx)
|
||||
x = C{idx(k)};
|
||||
|
||||
% Case 1: struct entry with field "config"
|
||||
if isstruct(x) && isfield(x,'config')
|
||||
x = rmfield(x,'config');
|
||||
|
||||
% Case 2: object entry with property "config"
|
||||
elseif isobject(x) && isprop(x,'config')
|
||||
try
|
||||
x.config = []; % lighter than keeping Equalizerstruct JSON
|
||||
catch
|
||||
% ignore if class forbids assignment
|
||||
end
|
||||
end
|
||||
|
||||
C{idx(k)} = x;
|
||||
end
|
||||
|
||||
res.(fn) = C;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
% ===================== Local helper functions =====================
|
||||
|
||||
function res_out = combine_res_list(R)
|
||||
% Concatenate along realization dimension (dim=3) for all techniques.
|
||||
% Requires consistent sizes in dims 1,2,4 and consistent eval_dist_km.
|
||||
|
||||
fieldsTech = ["ffe","dfe","vnle","mlse","dbt"];
|
||||
|
||||
% Start with first
|
||||
res_out = R{1};
|
||||
|
||||
% --- Build common distance axis (union, stable) ---
|
||||
dist_all = res_out.eval_dist_km(:).';
|
||||
for k = 2:numel(R)
|
||||
dist_all = unique([dist_all, R{k}.eval_dist_km(:).'], 'stable');
|
||||
end
|
||||
|
||||
% --- If res_out not already on dist_all, expand it ---
|
||||
if ~isequal(res_out.eval_dist_km(:).', dist_all)
|
||||
res_out = expand_res_dist(res_out, dist_all);
|
||||
end
|
||||
|
||||
% --- For each file: expand to dist_all, then merge realizations (your logic) ---
|
||||
for k = 2:numel(R)
|
||||
R{k} = expand_res_dist(R{k}, dist_all);
|
||||
end
|
||||
|
||||
|
||||
% Concatenate technique cell arrays along dim=3 (realizations)
|
||||
for f = fieldsTech
|
||||
A = res_out.(f);
|
||||
for k = 2:numel(R)
|
||||
B = R{k}.(f);
|
||||
A = cat(3, A, B);
|
||||
end
|
||||
res_out.(f) = A;
|
||||
end
|
||||
|
||||
% Update num_realiz in settings to match concatenated dim
|
||||
dims = size(res_out.ffe); if numel(dims)<3, dims(3)=1; end
|
||||
res_out.settings.num_realiz = dims(3);
|
||||
end
|
||||
|
||||
function res = expand_res_dist(res, dist_all)
|
||||
techs = {'ffe','dfe','vnle','mlse','dbt'};
|
||||
|
||||
old = res.eval_dist_km(:).';
|
||||
new = dist_all(:).';
|
||||
[~,loc] = ismember(old, new); % mapping old -> new positions
|
||||
if any(loc==0)
|
||||
error('expand_res_dist: internal: old distances not found in union.');
|
||||
end
|
||||
|
||||
% sizes from an existing field (prefer ffe)
|
||||
Cref = res.ffe;
|
||||
sz = size(Cref); sz(end+1:4) = 1; % ensure 4 dims
|
||||
Nch=sz(1); Nrop=sz(2); Nreal=sz(3); Nnew=numel(new);
|
||||
|
||||
for t = 1:numel(techs)
|
||||
fn = techs{t};
|
||||
if ~isfield(res,fn) || isempty(res.(fn)), continue; end
|
||||
Cold = res.(fn);
|
||||
sz2 = size(Cold); sz2(end+1:4) = 1;
|
||||
|
||||
Cnew = cell(sz2(1), sz2(2), sz2(3), Nnew);
|
||||
Cnew(:,:,:,loc) = Cold; % place old distances into new axis
|
||||
res.(fn) = Cnew;
|
||||
end
|
||||
|
||||
res.eval_dist_km = new;
|
||||
end
|
||||
|
||||
|
||||
function res_out = drop_empty_realizations(res_in)
|
||||
% Removes realizations where ALL entries are empty across ALL techniques
|
||||
% (across channels, rop, distances).
|
||||
|
||||
res_out = res_in;
|
||||
fieldsTech = ["ffe","dfe","vnle","mlse","dbt"];
|
||||
|
||||
% Determine sizes from one field
|
||||
dims = size(res_in.ffe);
|
||||
if numel(dims) < 4, dims(end+1:4) = 1; end
|
||||
Nreal = dims(3);
|
||||
|
||||
% For each realization, check if there is at least one non-empty result anywhere
|
||||
keep = false(1, Nreal);
|
||||
for r = 1:Nreal
|
||||
hasAny = false;
|
||||
for f = fieldsTech
|
||||
C = res_in.(f); % cell array
|
||||
% Slice all ch,rop,dist for this realization
|
||||
slice = C(:,:,r,:); % still a cell array
|
||||
hasAny = any(~cellfun(@isempty, slice(:)));
|
||||
if hasAny, break; end
|
||||
end
|
||||
keep(r) = hasAny;
|
||||
end
|
||||
|
||||
fprintf('drop_empty_realizations: keeping %d/%d realizations (dropping %d)\n', ...
|
||||
sum(keep), Nreal, sum(~keep));
|
||||
|
||||
% Apply keep mask
|
||||
for f = fieldsTech
|
||||
res_out.(f) = res_out.(f)(:,:,keep,:);
|
||||
end
|
||||
|
||||
% Update settings
|
||||
res_out.settings.num_realiz = sum(keep);
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user