Skip to content

Commit

Permalink
HG2 default size
Browse files Browse the repository at this point in the history
* default size to suit HG2.
* improve error messages.
* include PRESET_COLORMAP
* remove CUBEHELIX_FIND
  • Loading branch information
DrosteEffect committed Feb 28, 2022
1 parent db6878a commit 25c2488
Show file tree
Hide file tree
Showing 5 changed files with 224 additions and 283 deletions.
82 changes: 51 additions & 31 deletions cubehelix.m
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
function [map,lo,hi,prm] = cubehelix(N,start,rots,satn,gamma,irange,domain)
% Generate an RGB colormap of Dave Green's CubeHelix colorscheme. With range and domain control.
%
% (c) 2013-2020 Stephen Cobeldick
% (c) 2013-2022 Stephen Cobeldick
%
% Returns a colormap with colors defined by Dave Green's CubeHelix colorscheme.
% The colormap nodes are selected along a tapered helix in the RGB color cube,
Expand Down Expand Up @@ -65,47 +65,48 @@
%
%% Input and Output Arguments %%
%
%%% Inputs (*=default):
%%% Inputs (**=default):
% N = NumericScalar, an integer to specify the colormap length.
% = *[], same length as the current figure's colormap (see COLORMAP).
% start = NumericScalar, *+0.5, the helix's start color (modulus 3): R=1, G=2, B=3.
% rots = NumericScalar, *-1.5, the number of R->G->B rotations over the scheme length.
% satn = NumericScalar, *1, controls how saturated the colors are.
% gamma = NumericScalar, *1, change the gamma to emphasize low or high intensity values.
% irange = NumericVector, *[0,1], range of brightness levels of the scheme's endnodes. Size 1x2.
% domain = NumericVector, *[0,1], domain of the CubeHelix calculation (endnode positions). Size 1x2.
% = []**, same length as the current figure's colormap (see COLORMAP).
% start = NumericScalar, +0.5**, the helix's start color (modulus 3): R=1, G=2, B=3.
% rots = NumericScalar, -1.5**, the number of R->G->B rotations over the scheme length.
% satn = NumericScalar, 1.0**, controls how saturated the colors are.
% gamma = NumericScalar, 1.0**, change the gamma to emphasize low or high intensity values.
% irange = NumericVector, [0,1]**, range of brightness levels of the scheme's endnodes.
% domain = NumericVector, [0,1]**, domain of the CubeHelix calculation (endnode positions).
%
%%% Outputs:
% map = NumericMatrix, a colormap of RGB values between 0 and 1. Size Nx3
% lo = LogicalMatrix, true where <map> values<0 were clipped to 0. Size Nx3
% hi = LogicalMatrix, true where <map> values>1 were clipped to 1. Size Nx3
%
% See also BREWERMAP LBMAP PARULA LINES RGBPLOT COLORMAP COLORBAR AXES SET CONTOURF
% See also CUBEHELIX_VIEW PRESET_COLORMAP BREWERMAP MAXDISTCOLOR LBMAP
% PARULA LINES RGBPLOT COLORMAP COLORBAR PLOT PLOT3 AXES SET CONTOURF

%% Input Wrangling %%
%
err = 'First input must be a real positive scalar numeric or [].';
err = 'First input <N> must be a real scalar numeric or [].';
if nargin==0 || (isnumeric(N)&&isequal(N,[]))
% Default is the same as MATLAB colormaps:
N = size(get(gcf,'colormap'),1);
% Default N is the same as MATLAB colormaps:
N = cmDefaultN();
else
assert(isnumeric(N)&&isscalar(N),...
'SC:cubehelix:NotScalarNumeric',err)
'SC:cubehelix:N:NotNumericScalar', err)
assert(isreal(N)&&isfinite(N)&&fix(N)==N&&N>=0,...
'SC:cubehelix:NotRealPositive',err)
'SC:cubehelix:N:NotRealWhole', err)
N = double(N);
end
%
iss = @(x)isnumeric(x)&&isreal(x)&&isscalar(x)&&isfinite(x);
isn = @(x,n)isnumeric(x)&&isreal(x)&&numel(x)==n&&all(isfinite(x(:)));
%
% Parameters:
% Start, rotations, saturation, and gamma parameters:
if nargin<2
% Default parameter values.
start = +0.5;
rots = -1.5;
satn = 1;
gamma = 1;
satn = +1.0;
gamma = +1.0;
elseif nargin<5
% Parameters are in a vector.
if nargin>2
Expand All @@ -115,8 +116,8 @@
domain = satn;
end
assert(isn(start,4)&&isvector(start),...
'SC:cubehelix:NotVectorParameters',...
'Second input can be a 1x4 real numeric of parameter values.')
'SC:cubehelix:start:NotVectorParameters',...
'Second input <start> can be a 1x4 real numeric of parameter values.')
start = double(start);
gamma = start(4);
satn = start(3);
Expand All @@ -125,10 +126,10 @@
else
% Parameters as individual scalar values.
rsn = 'Input <%s> must be a real scalar numeric.';
assert(iss(start), 'SC:cubehelix:NotScalarNumeric_start', rsn,'start')
assert(iss(rots), 'SC:cubehelix:NotScalarNumeric_rots', rsn,'rots')
assert(iss(satn), 'SC:cubehelix:NotScalarNumeric_satn', rsn,'satn')
assert(iss(gamma), 'SC:cubehelix:NotScalarNumeric_gamma', rsn,'gamma')
assert(iss(start), 'SC:cubehelix:start:NotNumericScalar', rsn,'start')
assert(iss(rots), 'SC:cubehelix:rots:NotNumericScalar', rsn,'rots')
assert(iss(satn), 'SC:cubehelix:satn:NotNumericScalar', rsn,'satn')
assert(iss(gamma), 'SC:cubehelix:gamma:NotNumericScalar', rsn,'gamma')
start = double(start);
rots = double(rots);
satn = double(satn);
Expand All @@ -139,7 +140,8 @@
if any(nargin==[0,1,2,5])
irange = [0,1];
else
assert(isn(irange,2),'SC:cubehelix:NotVector_irange',...
assert(isn(irange,2),...
'SC:cubehelix:irange:NotNumericVector',...
'Input <irange> must be a 1x2 real numeric.')
irange = double(irange);
end
Expand All @@ -148,15 +150,16 @@
if any(nargin==[0,1,2,3,5,6])
domain = [0,1];
else
assert(isn(domain,2),'SC:cubehelix:NotVector_domain',...
assert(isn(domain,2),...
'SC:cubehelix:domain:NotNumericVector',...
'Input <domain> must be a 1x2 real numeric.')
domain = double(domain);
end
%
prm = [start;rots;satn;gamma;irange(:);domain(:)];
map = nan(N,3);
%
if N==0
map = ones(0,3);
lo = false(0,3);
hi = false(0,3);
return
Expand All @@ -176,18 +179,35 @@
cof = [-0.14861,1.78277;-0.29227,-0.90649;1.97294,0];
%
vec = sign(N)*(1:abs(N)) - min(0,N-1);
for m = abs(N):-1:1
n = vec(m);
map(m,:) = tmp(n) + amp(n) * (cof*csm(:,n));
for ii = 1:abs(N)
jj = vec(ii);
map(ii,:) = tmp(jj) + amp(jj)*(cof*csm(:,jj));
end
%
lo = map<0;
hi = map>1;
%
map = max(0,min(1,map));
%
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%cubehelix
% Copyright (c) 2013-2020 Stephen Cobeldick
function N = cmDefaultN()
% Get the colormap size from the current figure or default colormap.
try
F = get(groot,'CurrentFigure');
catch %#ok<CTCH> pre HG2
N = size(get(gcf,'colormap'),1);
return
end
if isempty(F)
N = size(get(groot,'DefaultFigureColormap'),1);
else
N = size(F.Colormap,1);
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%cmDefaultN
%
% Copyright (c) 2013-2022 Stephen Cobeldick
%
% Licensed under the Apache License, Version 2.0 (the "License");
% you may not use this file except in compliance with the License.
Expand Down
41 changes: 41 additions & 0 deletions cubehelix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
CUBEHELIX Function
==================

CUBEHELIX is the only colormap-generator you will ever need for MATLAB: CUBEHELIX generates colormaps for published or distributed documents as they are very attractive in full color and yet are suitable for grayscale conversion.

CUBEHELIX creates different colormaps using just a few parameters. The standard algorithm offer very attractive colorschemes for online and electronic documents (e.g. PDF), and yet when printed in grayscale they keep exactly the sequence information of the original data. CUBEHELIX function also includes two extra controls over the range and domain of the colormap values, giving a practically unlimited number of colormaps with many different styles: maximally distinct, multi or single hue, and may be suitable for grayscale printing or even simple grayscale.

### Algorithm ###

CUBEHELIX colorschemes consist of nodes along a tapered helix in the RGB color cube, with a continuous increase in perceived intensity (e.g. black->white). Thus the scheme defines attractive colormaps with a huge choice of hue, saturation and brightness, and yet printing a figure (or image) in Black-and-White (e.g. postscript) results in a monotonically increasing grayscale that retains the brightness order of the original colormap. The sequence information of the colormap is retained even in grayscale, which means an attractive colored image can be printed in grayscale and still be informative to the end-user.

The CUBEHELIX algorithm is defined here: http://astron-soc.in/bulletin/11June/289392011.pdf

For more information and examples: http://www.mrao.cam.ac.uk/~dag/CUBEHELIX/

### Examples ###

% New colors for the COLORMAP example:
S = load('spine');
image(S.X)
colormap(cubehelix) % default parameters

% New colors for the SURF example:
[X,Y,Z] = peaks(30);
surfc(X,Y,Z)
colormap(cubehelix([],0.5,-1.5,1,1,[0.29,0.92]))
axis([-3,3,-3,3,-10,5])

### Bonus Function ###

CUBEHELIX_VIEW creates an interactive figure that allows selection of the colorscheme, and that contains two colorbars showing colors of the colormap and the grayscale equivalent.

R2014b or later: CUBEHELIX_VIEW can also update other axes' or figures' colormaps in real time, for example:

S = load('spine');
image(S.X)
cubehelix_view(gca)

### Notes ###

* The original specification (the links above) misnamed the saturation option as "hue". In the CUBEHELIX function the saturation option is named "satn".
Loading

0 comments on commit 25c2488

Please sign in to comment.