Minimal changes

Add Theory plots for Silas Diss
This commit is contained in:
Silas Oettinghaus
2026-01-29 16:49:50 +01:00
parent 7eaa4b8791
commit 7eb3364814
8 changed files with 860 additions and 115 deletions

View File

@@ -1,10 +1,13 @@
classdef WesPalette
% WESPALETTE Wes Anderson color palettes with auto-completion
% Usage:
% cmap = WesPalette.Zissou1.rgb()
% cmap = WesPalette.Zissou1.rgb(3)
% https://github.com/karthik/wesanderson?tab=readme-ov-file
% cmap = WesPalette.Zissou1.rgb() % full palette
% cmap = WesPalette.Zissou1.rgb(3) % 3 colors (discrete default)
% cmap = WesPalette.Zissou1.rgb(12,"discrete") % any n, no interpolation
% cmap = WesPalette.Zissou1.rgb(256,"continuous") % smooth colormap (Lab interpolation)
%
% Requires:
% - colorspace.m (Pascal Getreuer) on MATLAB path for "continuous" mode
enumeration
BottleRocket1
@@ -34,21 +37,33 @@ classdef WesPalette
end
methods
function cmap = rgb(obj, n)
function cmap = rgb(obj, n, mode)
% Return palette as Nx3 RGB colormap [01]
%
% n : number of requested colors (optional)
% mode : "discrete" (default) or "continuous"
hex = obj.hex();
base_hex = obj.hex();
base_rgb = WesPalette.hex2rgb(base_hex);
rgb = hex2rgb(hex);
if nargin < 2 || isempty(n)
cmap = base_rgb;
return;
end
if nargin < 3 || isempty(mode)
mode = "discrete";
end
mode = lower(string(mode));
if nargin == 2
if n > size(rgb,1)
error('Requested %d colors, but only %d available.', ...
n, size(rgb,1))
end
cmap = rgb(1:n,:);
validateattributes(n, {'numeric'}, {'scalar','integer','positive'}, mfilename, 'n');
if mode ~= "discrete" && mode ~= "continuous"
error('mode must be "discrete" or "continuous".');
end
if mode == "discrete"
cmap = WesPalette.sample_discrete(base_rgb, n);
else
cmap = rgb;
cmap = WesPalette.interpolate_continuous_lab(base_rgb, n);
end
end
end
@@ -56,78 +71,116 @@ classdef WesPalette
methods (Access = private)
function hex = hex(obj)
% Internal HEX storage
switch obj
case WesPalette.BottleRocket1
hex = {'#A42820','#5F5647','#9B110E','#3F5151','#4E2A1E','#550307','#0C1707'};
case WesPalette.BottleRocket2
hex = {'#FAD510','#CB2314','#273046','#354823','#1E1E1E'};
case {WesPalette.Rushmore1, WesPalette.Rushmore}
hex = {'#E1BD6D','#EABE94','#0B775E','#35274A','#F2300F'};
case WesPalette.Royal1
hex = {'#899DA4','#C93312','#FAEFD1','#DC863B'};
case WesPalette.Royal2
hex = {'#9A8822','#F5CDB4','#F8AFA8','#FDDDA0','#74A089'};
case WesPalette.Zissou1
hex = {'#3B9AB2','#78B7C5','#EBCC2A','#E1AF00','#F21A00'};
case WesPalette.Zissou1Continuous
hex = {'#3A9AB2','#6FB2C1','#91BAB6','#A5C2A3','#BDC881', ...
'#DCCB4E','#E3B710','#E79805','#EC7A05','#EF5703','#F11B00'};
case WesPalette.Darjeeling1
hex = {'#FF0000','#00A08A','#F2AD00','#F98400','#5BBCD6'};
case WesPalette.Darjeeling2
hex = {'#ECCBAE','#046C9A','#D69C4E','#ABDDDE','#000000'};
case WesPalette.Chevalier1
hex = {'#446455','#FDD262','#D3DDDC','#C7B19C'};
case WesPalette.FantasticFox1
hex = {'#DD8D29','#E2D200','#46ACC8','#E58601','#B40F20'};
case WesPalette.Moonrise1
hex = {'#F3DF6C','#CEAB07','#D5D5D3','#24281A'};
case WesPalette.Moonrise2
hex = {'#798E87','#C27D38','#CCC591','#29211F'};
case WesPalette.Moonrise3
hex = {'#85D4E3','#F4B5BD','#9C964A','#CDC08C','#FAD77B'};
case WesPalette.Cavalcanti1
hex = {'#D8B70A','#02401B','#A2A475','#81A88D','#972D15'};
case WesPalette.GrandBudapest1
hex = {'#F1BB7B','#FD6467','#5B1A18','#D67236'};
case WesPalette.GrandBudapest2
hex = {'#E6A0C4','#C6CDF7','#D8A499','#7294D4'};
case WesPalette.IsleofDogs1
hex = {'#9986A5','#79402E','#CCBA72','#0F0D0E','#D9D0D3','#8D8680'};
case WesPalette.IsleofDogs2
hex = {'#EAD3BF','#AA9486','#B6854D','#39312F','#1C1718'};
case WesPalette.FrenchDispatch
hex = {'#90D4CC','#BD3027','#B0AFA2','#7FC0C6','#9D9C85'};
case WesPalette.AsteroidCity1
hex = {'#0A9F9D','#CEB175','#E54E21','#6C8645','#C18748'};
case WesPalette.AsteroidCity2
hex = {'#C52E19','#AC9765','#54D8B1','#B67C3B','#175149','#AF4E24'};
case WesPalette.AsteroidCity3
hex = {'#FBA72A','#D3D4D8','#CB7A5C','#5785C1'};
end
end
end
methods (Static, Access = private)
function rgb = hex2rgb(hex)
% hex: cellstr like {'#RRGGBB', ...}
if isstring(hex), hex = cellstr(hex); end
n = numel(hex);
rgb = zeros(n,3);
for i = 1:n
h = char(hex{i});
if startsWith(h,'#'), h = h(2:end); end
if numel(h) ~= 6
error('Invalid HEX color: %s', hex{i});
end
rgb(i,1) = hex2dec(h(1:2))/255;
rgb(i,2) = hex2dec(h(3:4))/255;
rgb(i,3) = hex2dec(h(5:6))/255;
end
end
function cmap = sample_discrete(base_rgb, n)
% No interpolation; allow any n by sampling/repeating.
k = size(base_rgb,1);
if n <= k
idx = round(linspace(1, k, n)); % spread across palette
idx = max(1, min(k, idx));
cmap = base_rgb(idx,:);
else
reps = floor(n / k);
rmd = mod(n, k);
cmap = [repmat(base_rgb, reps, 1); base_rgb(1:rmd,:)];
end
end
function cmap = interpolate_continuous_lab(base_rgb, n)
% Smooth interpolation in Lab using colorspace().
% Requires colorspace.m by Pascal Getreuer on MATLAB path.
k = size(base_rgb,1);
if k == 1
cmap = repmat(base_rgb, n, 1);
return;
end
% Convert to Lab, interpolate each channel, convert back
lab = colorspace('Lab<-RGB', base_rgb);
t_base = linspace(0, 1, k);
t_new = linspace(0, 1, n);
lab_new = zeros(n,3);
for c = 1:3
lab_new(:,c) = interp1(t_base, lab(:,c), t_new, 'linear');
end
rgb_new = colorspace('RGB<-Lab', lab_new);
% Clamp to displayable gamut
cmap = min(max(rgb_new, 0), 1);
end
end
end

View File

@@ -5,8 +5,8 @@ y2 = 1e0 ./ (1 + exp(-0.4*(x-12))); % NLPN
y3 = 1e-6 * 10.^(0.45*x); % RP on gamma
y4 = 1e-2 * 10.^(0.18*(x-8)); % RP on beta2
cmap = WesPalette.AsteroidCity1.rgb(4);
cmap = linspecer(4);
cmap = WesPalette.AsteroidCity1;
% cmap = linspecer(4);
figure1=figure(202998);clf;hold on
lw = 0.8; ms = 4;
plot(x,y1,'LineWidth',lw,'Color',cmap(1,:),'Marker','o','MarkerEdgeColor',cmap(1,:),'MarkerFaceColor',[1,1,1],'MarkerSize',ms);