Code covered by the BSD License  

Highlights from
Valcolor

image thumbnail

Valcolor

by

 

Apply color CLR to colormap entry pertaining to value VAL. Either scaled or indexed figure.

valcolor(varargin)
function varargout = valcolor(varargin)
%VALCOLOR - Change colormap entry for specified value to a chosen color
%  valcolor(VAL,CLR)
%  Updates current figure's colormap so values VAL get color CLR.
%  This includes values mapped to the same color as VAL. 
%  CLR is either a vector between 0-1, e.g. [.4 .2 .9] or 
%  a standard MATLAB color string shorthand, e.g. 'r'.
%  Based on Clim and CDataMapping value of current axes and image.
%  
%  valcolor(H,VAL,CLR) uses figure handle H instead of current.
%
%  cmap = valcolor(...)
%  Returns modified cmap based on figure's colormap.
%  Does not apply it to figure. Apply with colormap().
%
%  cmap = valcolor(VAL,CLR,oldmap,clims)
%  Outputs colored cmap based on input map and clims. 
%  May supply data instead of clims, gets [min max] to create clims.
%  If clims = false, assumes indexed colormap.
%
%
%  --- Notes:
%  Does nothing with RGB images. Made for real 2D intensity matrices, but
%  also handles indexed images. See the CDataMapping image property.
%
%  Other values will be affected if they are mapped to the same color as
%  VAL. To affect *only* VAL there are some options (not included):
%  1 Convert to indexed type such that VAL has a unique index.
%  2 Manipulate the affected data values near VAL.
%  3 Increase the colormap size. Feasibility depends on data.
%  4 Change VAL value to e.g. NaN/inf, then change CLims so other data 
%  uses 99% of the colormap. Make the last color your custom color.
%
%  Currently only takes 1  value-color pair for input. For mapping a range 
%  of values to specific colors, see customcolormap (FEX#36501).
%
%  ~~~~Jurgen


if nargout
    out = true;
else
    out = false;
end

% --- Parse VAL, H, CLR, oldmap, clims, data
[VAL H CLR clims oldmap] = parse_args(varargin);


% --- convert shorthand to [R G B]
if ischar(CLR)
    CLR = convert_to_rgb(CLR);
else
    assert(iscolor(CLR),...
    'input value CLR isn''t a color!')
end

% if indexed:
if clims == false
    cmap = oldmap;
    cmap(VAL,:) = CLR;
    finish
    return
end

% --- find entry to make cmap
idx              = findclr(VAL,oldmap,clims);
cmap             = oldmap;
cmap(idx,:)      = CLR;
finish

function finish
    if out
        varargout{1} = cmap;
    else
        colormap(get(H,'CurrentAxes'),cmap)
    end
end  %Nested

end


function idx = findclr(VAL,oldmap,clims)
% Assumes CLim range gets linearly quantized when mapping
a = linspace(clims(1),clims(2),size(oldmap,1)+1);
if any(a == VAL)
   idx = find(a == VAL);
else
   idx = sum(a<VAL);
end
end

function CLR = convert_to_rgb(CLR)
    switch CLR
        case 'r'
            CLR = [1 0 0];
        case 'c'
            CLR = [0 1 1];            
        case 'y'
            CLR = [1 1 0];            
        case 'm'
            CLR = [1 0 1];            
        case 'g'
            CLR = [0 1 0];            
        case 'b'
            CLR = [0 0 1];            
        case 'k'
            CLR = [0 0 0];            
        case 'w'
            CLR = [1 1 1];            
        otherwise
            error(['Unknown color shorthand: ' CLR]);
    end    
end

function c = iscolor(CLR)
if all(CLR<=1) && all(CLR>=0) && (length(CLR)==3) && (numel(CLR)==3)
    c = true;
else
    c = false;
end
end    
        
function [VAL H CLR clims oldmap] = parse_args(args)
nargin = length(args);

if nargin == 3 
        H   = args{1};
        VAL = args{2};
        CLR = args{3};
        assert(ishandle(H) && (H ~= 0) && strcmp(get(H,'Type'),'figure')...
            ,'Wrong handle for H or wrong syntax');
elseif nargin == 4 %custom input
    VAL = args{1};
    CLR = args{2};
    H = [];
    oldmap = args{3};
    clims  = args{4};
    if clims ~= false %intensity
        clims  = [min(clims(:)) max(clims(:))];
        check_clims(VAL,clims);
    else %indexed
        VAL = min(size(oldmap,1),VAL);
        VAL = max(1,VAL);
        VAL = round(VAL);
    end
    return
else
    H   = gcf;
    VAL = args{1};
    CLR = args{2};
end

% For figure based mapping, get oldmap and clims.
% Base mapping on current axes(clim) and image(cdatamapping)
[dum dum dum flag]  = getimage(H);
assert(flag ~= 4,'Can not apply colormaps to RGB images');
    
oldmap = get(H,'Colormap');
ax     = get(H,'CurrentAxes');
clims  = get(ax,'CLim');
    
if ~isempty(findobj(ax,'CDataMapping','direct','-depth',1))
    clims = false; %identifier for indexed types      
    VAL = min(size(oldmap,1),VAL);
    VAL = max(1,VAL);
    VAL = round(VAL);
    warning('Image is indexed');
else
    check_clims(VAL,clims);
end

end

function check_clims(VAL,clims)
%Final clim checks
assert(clims(1)~=clims(2),'Wrong clim values, can not be equal');
try 
assert(clims(1) <= (VAL+eps) && clims(2) >= (VAL-eps))
catch
    display(clims);
    disp(['Failing boundary (zero fails): ' num2str([(clims(1) <= eps(1)) (clims(2) >= eps(1))])]);
    disp(' ');
    error('parseargs:limitcheck',...
['  CLim Check: No explicit VAL value in colormap range!\n'...
'  i.e. values are / were being clipped--if they exist at all.\n'...
'  Change CLim property vector to contain VAL (see caxis)']);
end
end    
    

Contact us