183 lines
5.6 KiB
Matlab
183 lines
5.6 KiB
Matlab
function beautifyBERplot(options)
|
|
% BEAUTIFYBERPLOT Publication-style beautification for BER / NSD plots.
|
|
% Style aligned to manual plotting script (lw=0.8, ms=4, white markers).
|
|
%
|
|
% Usage examples:
|
|
% beautifyBERplot
|
|
% beautifyBERplot("polyfit",true,"polyorder",1)
|
|
% beautifyBERplot("polyfit",true,"fitmethod","pchip")
|
|
% beautifyBERplot("changemarkers",true)
|
|
|
|
arguments
|
|
options.logscale (1,1) logical = 1
|
|
options.setmarkers (1,1) logical = 1
|
|
options.changemarkers (1,1) logical = 0
|
|
options.setcolors (1,1) logical = 1
|
|
options.polyfit (1,1) logical = 0
|
|
options.polyorder (1,1) double = 2
|
|
options.fitmethod (1,1) string = "polyfit"
|
|
end
|
|
|
|
ax = gca;
|
|
|
|
% ---------------------------------------------------------
|
|
% Extract real data objects from ax.Children
|
|
% ---------------------------------------------------------
|
|
children = ax.Children;
|
|
isLine = arrayfun(@(h) isa(h,'matlab.graphics.chart.primitive.Line'), children);
|
|
isScatter = arrayfun(@(h) isa(h,'matlab.graphics.chart.primitive.Scatter'), children);
|
|
|
|
% Remove helper lines (e.g. yline, fit overlays)
|
|
isConstantLine = arrayfun(@(h) isprop(h,'Tag') && strcmp(h.Tag,'ConstantLine'), children);
|
|
|
|
dataObjects = children((isLine | isScatter) & ~isConstantLine);
|
|
n = numel(dataObjects);
|
|
|
|
% ---------------------------------------------------------
|
|
% Fixed color palette (deterministic across figures)
|
|
% ---------------------------------------------------------
|
|
if n > 0
|
|
try
|
|
cmap = linspecer(n);
|
|
catch
|
|
cmap = linespecer_fallback(n);
|
|
end
|
|
end
|
|
|
|
% Simple marker set that exports cleanly with common MATLAB-to-TikZ workflows.
|
|
markers = {'o','square','diamond','^','v','>','<','pentagram'};
|
|
lw = 1;
|
|
ms = 5;
|
|
applyMarkers = options.setmarkers || options.changemarkers;
|
|
|
|
% ---------------------------------------------------------
|
|
% Apply line/scatter + marker styling
|
|
% ---------------------------------------------------------
|
|
for i = 1:n
|
|
dataObj = dataObjects(n-i+1); % preserve plotting order
|
|
|
|
if isa(dataObj,'matlab.graphics.chart.primitive.Line')
|
|
dataObj.LineWidth = lw;
|
|
|
|
if options.setcolors
|
|
dataObj.Color = cmap(i,:);
|
|
end
|
|
|
|
if applyMarkers
|
|
if options.changemarkers || strcmp(dataObj.Marker,'none')
|
|
dataObj.Marker = markers{mod(i-1,numel(markers))+1};
|
|
end
|
|
dataObj.MarkerSize = ms;
|
|
if options.setcolors
|
|
dataObj.MarkerEdgeColor = cmap(i,:);
|
|
end
|
|
dataObj.MarkerFaceColor = [1 1 1];
|
|
end
|
|
elseif isa(dataObj,'matlab.graphics.chart.primitive.Scatter')
|
|
if options.setcolors
|
|
dataObj.CData = cmap(i,:);
|
|
dataObj.MarkerEdgeColor = cmap(i,:);
|
|
markerFaceColor = dataObj.MarkerFaceColor;
|
|
hasNoFace = ischar(markerFaceColor) && strcmp(markerFaceColor,'none');
|
|
if ~hasNoFace
|
|
dataObj.MarkerFaceColor = cmap(i,:);
|
|
end
|
|
end
|
|
|
|
if applyMarkers
|
|
if options.changemarkers || strcmp(dataObj.Marker,'none')
|
|
dataObj.Marker = markers{mod(i-1,numel(markers))+1};
|
|
end
|
|
dataObj.SizeData = ms;
|
|
end
|
|
end
|
|
end
|
|
|
|
% ---------------------------------------------------------
|
|
% Optional smoothing / fitting overlay
|
|
% ---------------------------------------------------------
|
|
if options.polyfit && n > 0
|
|
hold on
|
|
for i = 1:n
|
|
dataObj = dataObjects(n-i+1);
|
|
x = dataObj.XData(:);
|
|
y = dataObj.YData(:);
|
|
valid = isfinite(x) & isfinite(y);
|
|
|
|
if sum(valid) < options.polyorder+1
|
|
continue
|
|
end
|
|
|
|
xf = linspace(min(x(valid)),max(x(valid)),200);
|
|
|
|
switch lower(options.fitmethod)
|
|
case "polyfit"
|
|
p = polyfit(x(valid),y(valid),options.polyorder);
|
|
yf = polyval(p,xf);
|
|
|
|
case "smoothingspline"
|
|
try
|
|
f = fit(x(valid),y(valid),'smoothingspline');
|
|
yf = feval(f,xf);
|
|
catch
|
|
yf = interp1(x(valid),y(valid),xf,'pchip');
|
|
end
|
|
|
|
case "loess"
|
|
ys = smooth(x(valid),y(valid),0.2,'loess');
|
|
yf = interp1(x(valid),ys,xf,'linear','extrap');
|
|
|
|
case "pchip"
|
|
yf = interp1(x(valid),y(valid),xf,'pchip');
|
|
|
|
otherwise
|
|
p = polyfit(x(valid),y(valid),options.polyorder);
|
|
yf = polyval(p,xf);
|
|
end
|
|
|
|
if isa(dataObj,'matlab.graphics.chart.primitive.Line')
|
|
basecol = dataObj.Color;
|
|
else
|
|
basecol = dataObj.CData(1,:);
|
|
if numel(basecol) ~= 3
|
|
basecol = cmap(i,:);
|
|
end
|
|
end
|
|
lightcol = basecol + 0.4*(1-basecol);
|
|
lightcol(lightcol>1)=1;
|
|
|
|
plot(xf,yf,'-','Color',lightcol,...
|
|
'LineWidth',0.7,'Marker','none',...
|
|
'HandleVisibility','off');
|
|
end
|
|
hold off
|
|
end
|
|
|
|
% ---------------------------------------------------------
|
|
% Axes formatting (matches first script)
|
|
% ---------------------------------------------------------
|
|
if options.logscale
|
|
set(ax,'YScale','log')
|
|
end
|
|
|
|
grid(ax,'on')
|
|
set(ax,'GridLineStyle','--',...
|
|
'GridLineWidth',0.5,...
|
|
'MinorGridLineWidth',0.5)
|
|
|
|
set(ax,'FontSize',12,...
|
|
'Box','on',...
|
|
'LineWidth',0.8)
|
|
|
|
set(findall(ax,'-property','Interpreter'),'Interpreter','latex')
|
|
set(gcf,'Color','w')
|
|
|
|
end
|
|
|
|
% ---------------------------------------------------------
|
|
% Fallback palette (only used if linspecer is missing)
|
|
% ---------------------------------------------------------
|
|
function cmap = linespecer_fallback(n)
|
|
cmap = lines(n);
|
|
end
|