Code covered by the BSD License  

Highlights from
COLORMAP and COLORBAR utilities (Jul 2014)

image thumbnail

COLORMAP and COLORBAR utilities (Jul 2014)

by

Carlos Adrian Vargas Aguilera

 

08 Jun 2009 (Updated )

MATLAB color utilities including COLORMAP join and interpolation; freeze and fit COLORBAR, etc.

cbfreeze(varargin)
function CBH = cbfreeze(varargin)
%CBFREEZE   Freezes the colormap of a colorbar.
%
%   SYNTAX:
%           cbfreeze
%           cbfreeze off
%           cbfreeze(CMAP)          % Freezes it with this colormap!
%           cbfreeze(CMAP,'off')
%           cbfreeze(H,...)
%     CBH = cbfreeze(...);
%
%   INPUTS:
%     CMAP  - Colormap matrix or name to be used at the colorbar.
%             DEFAULT: (uses the figure one)
%     H     - Handles of colorbars to be frozen, or from figures to search
%             for them or from peer axes (see COLORBAR).
%             DEFAULT: gcf (freezes all colorbars from the current figure)
%     'off' - Unfreezes the colorbars, other options are:
%               'on'    Freezes
%               'un'    same as 'off'
%               'del'   Deletes the colorbars.
%             DEFAULT: 'on' (of course)
%
%   OUTPUTS (all optional):
%     CBH - Color bar handle(s).
%
%   DESCRIPTION:
%     MATLAB works with a unique COLORMAP by figure which is a big
%     limitation. Function FREEZECOLORS by John Iversen allows to use
%     different COLORMAPs in a single figure, but it fails freezing the
%     COLORBAR. This program handles this problem.
%
%   NOTE:
%     * Optional inputs use its DEFAULT value when not given or [].
%     * Optional outputs may or not be called.
%     * If no colorbar is found, one is created on each of the axes.
%     * But, if you need to creat it with LCOLORBAR instead of COLORBAR,
%       use:
%        >> lcolorbar(...,'Tag','Colorbar')
%     * The new frozen colorbar is an axes object and does not behaves
%       as normally colorbars when resizing the peer axes. Although, some
%       time the normal behavior is not that good.
%     * Besides, it does not have the 'Location' property anymore.
%     * But, it does acts normally: no ZOOM, no PAN, no ROTATE3D and no
%       mouse selectable.
%     * No need to say that CAXIS and COLORMAP must be defined before using
%       this function. Besides, the colorbar location. Anyway, 'off' or
%       'del' may help.
%     * The 'del' functionality may be used whether or not the colorbar(s)
%       is(are) froozen. The peer axes are resized back. Try:
%        >> colorbar, cbfreeze del
%
%   EXAMPLE:
%     surf(peaks(30))
%     colormap jet
%     cbfreeze
%     colormap gray
%     title('What...?')
%
%   SEE ALSO:
%     COLORMAP, COLORBAR, CAXIS
%     and
%     FREEZECOLORS by John Iversen
%     at http://www.mathworks.com/matlabcentral/fileexchange
%
%
%   ---
%   MFILE:   cbfreeze.m
%   VERSION: 2.1 (Jul 03, 2014) (<a href="matlab:web('http://www.mathworks.com/matlabcentral/fileexchange/authors/11258')">download</a>)
%   MATLAB:  8.2.0.701 (R2013b)
%   AUTHOR:  Carlos Adrian Vargas Aguilera (MEXICO)
%   CONTACT: nubeobscura@hotmail.com

%   REVISIONS:
%   1.0      Released. (Jun 08, 2009)
%   1.1      Fixed BUG with image handle on MATLAB R2009a. Thanks to Sergio
%            Muniz. (Sep 02, 2009)
%   2.0      Fixed several BUGs about scientific notation, thanks to Rafa
%            and Jenny from the FileExchange. Changed application name to
%            'cbfreeze' on both, the colorbar and the peer axes. New
%            optional input CMAP. (Jun 05, 2014) 
%   2.1      Fixed BUGs about reading inputs, thanks to Maxime Desbiens. 
%            (Jul 03, 2014) 

%   DISCLAIMER:
%   cbfreeze.m is provided "as is" without warranty of any kind, under the
%   revised BSD license.

%   Copyright (c) 2009-2014 Carlos Adrian Vargas Aguilera


% INPUTS CHECK-IN
% -------------------------------------------------------------------------

% Parameters:
appName = 'cbfreeze';

% Set defaults:
OPT  = 'on';
H    = get(get(0,'CurrentFigure'),'CurrentAxes');
CMAP = [];

% Checks inputs:
assert(nargin<=3,'CAVARGAS:cbfreeze:IncorrectInputsNumber',...
    'At most 3 inputs are allowed.')
assert(nargout<=1,'CAVARGAS:cbfreeze:IncorrectOutputsNumber',...
    'Only 1 output is allowed.')

% Checks from where CBFREEZE was called:
if (nargin~=2) || (isempty(varargin{1}) || ...
        ~all(reshape(ishandle(varargin{1}),[],1)) ...
        || ~isempty(varargin{2}))
    % CBFREEZE called from Command Window or M-file:

    % Reads H in the first input: Version 2.1
    if ~isempty(varargin) && ~isempty(varargin{1}) && ...
            all(reshape(ishandle(varargin{1}),[],1)) 
        H = varargin{1};
        varargin(1) = [];
    end
    
    % Reads CMAP in the first input: Version 2.1
    if ~isempty(varargin) && ~isempty(varargin{1})
        if isnumeric(varargin{1}) && (size(varargin{1},2)==3) && ...
                (size(varargin{1},1)==numel(varargin{1})/3)
            CMAP = varargin{1};
            varargin(1) = [];
        elseif ischar(varargin{1}) && ...
                (size(varargin{1},2)==numel(varargin{1}))
            temp = figure('Visible','off');
            try
                CMAP = colormap(temp,varargin{1});
            catch
                close temp
                error('CAVARGAS:cbfreeze:IncorrectInput',...
                    'Incorrrect colormap name ''%s''.',varargin{1})
            end
            close temp
            varargin(1) = [];
        end
    end
    
    % Reads options: Version 2.1
    while ~isempty(varargin)
        if isempty(varargin{1}) || ~ischar(varargin{1}) || ...
                (numel(varargin{1})~=size(varargin{1},2))
            varargin(1) = [];
            continue
        end
        switch lower(varargin{1})
            case {'off','of','unfreeze','unfreez','unfree','unfre', ...
                    'unfr','unf','un','u'}
                OPT = 'off';
            case {'delete','delet','dele','del','de','d'}
                OPT = 'delete';
            otherwise
                OPT = 'on';
        end
    end
    
    % Gets colorbar handles or creates them:
    CBH = cbhandle(H,'force');
    
else
    
    % Check for CallBacks functionalities:
    % ------------------------------------
    
    varargin{1} = double(varargin{1});
    
    if strcmp(get(varargin{1},'BeingDelete'),'on')
        % CBFREEZE called from DeletFcn:
        
        if (ishandle(get(varargin{1},'Parent')) && ...
                ~strcmpi(get(get(varargin{1},'Parent'),'BeingDeleted'),'on'))
            % The handle input is being deleted so do the colorbar:
            OPT = 'delete';
            
            if strcmp(get(varargin{1},'Tag'),'Colorbar')
                % The frozen colorbar is being deleted:
                H = varargin{1};
            else
                % The peer axes is being deleted:
                H = ancestor(varargin{1},{'figure','uipanel'});
            end
        else
            % The figure is getting close:
            return
        end
        
    elseif ((gca==varargin{1}) && ...
            (gcf==ancestor(varargin{1},{'figure','uipanel'})))
        % CBFREEZE called from ButtonDownFcn:
        
        cbdata = getappdata(varargin{1},appName);
        if ~isempty(cbdata)
            if ishandle(cbdata.peerHandle)
                % Sets the peer axes as current (ignores mouse click-over):
                set(gcf,'CurrentAxes',cbdata.peerHandle);
                return
            end
        else
            % Clears application data:
            rmappdata(varargin{1},appName)
        end
        H = varargin{1};
    end
    
    % Gets out:
    CBH = cbhandle(H);
    
end

% -------------------------------------------------------------------------
% MAIN
% -------------------------------------------------------------------------

% Keeps current figure:
cfh = get(0,'CurrentFigure');

% Works on every colorbar:
for icb = 1:length(CBH)
    
    % Colorbar handle:
    cbh = double(CBH(icb));
    
    % This application data:
    cbdata = getappdata(cbh,appName);
    
    % Gets peer axes handle:
    if ~isempty(cbdata)
        peer = cbdata.peerHandle;
        if ~ishandle(peer)
            rmappdata(cbh,appName)
            continue
        end
    else
        % No matters, get them below:
        peer = [];
    end
    
    % Choose functionality:
    switch OPT
        
        case 'delete'
            % Deletes:
            if ~isempty(peer)
                % Returns axes to previous size:
                oldunits = get(peer,'Units');
                set(peer,'Units','Normalized');
                set(peer,'Position',cbdata.peerPosition)
                set(peer,'Units',oldunits)
                set(peer,'DeleteFcn','')
                if isappdata(peer,appName)
                    rmappdata(peer,appName)
                end
            end
            if strcmp(get(cbh,'BeingDelete'),'off')
                delete(cbh)
            end
            
        case 'off'
            % Unfrozes:
            if ~isempty(peer)
                delete(cbh);
                set(peer,'DeleteFcn','')
                if isappdata(peer,appName)
                    rmappdata(peer,appName)
                end
                oldunits = get(peer,'Units');
                set(peer,'Units','Normalized')
                set(peer,'Position',cbdata.peerPosition)
                set(peer,'Units',oldunits)
                CBH(icb) = colorbar(...
                    'Peer'    ,peer,...
                    'Location',cbdata.cbLocation);
            end
            
        case 'on'
            % Freezes:

            % Gets colorbar axes properties:
            cbprops = get(cbh);
            
            % Current axes on colorbar figure:
            fig = ancestor(cbh,{'figure','uipanel'});
            cah = get(fig,'CurrentAxes');
            
            % Gets colorbar image handle. Fixed BUG, Sep 2009
            himage = findobj(cbh,'Type','image');
            
            % Gets image data and transforms them to RGB:
            CData = get(himage,'CData');
            if size(CData,3)~=1
                % It's already frozen:
                continue
            end
            
            % Gets image tag:
            imageTag = get(himage,'Tag');
            
            % Deletes previous colorbar preserving peer axes position:
            if isempty(peer)
                peer = cbhandle(cbh,'peer');
            end
            oldunits = get(peer,'Units');
            set(peer,'Units','Normalized')
            position = get(peer,'Position');
            delete(cbh)
            oldposition = get(peer,'Position');
            
            % Seves axes position
            cbdata.peerPosition = oldposition;
            set(peer,'Position',position)
            set(peer,'Units',oldunits)
            
            % Generates a new colorbar axes:
            % NOTE: this is needed because each time COLORMAP or CAXIS
            %       is used, MATLAB generates a new COLORBAR! This
            %       eliminates that behaviour and is the central point
            %       on this function.
            cbh = axes(...
                'Parent'  ,cbprops.Parent,...
                'Units'   ,'Normalized',...
                'Position',cbprops.Position...
                );
            
            % Saves location for future calls:
            cbdata.cbLocation = cbprops.Location;
            
            % Move ticks because IMAGE draws centered pixels:
            XLim = cbprops.XLim;
            YLim = cbprops.YLim;
            if     isempty(cbprops.XTick)
                % Vertical:
                X = XLim(1) + diff(XLim)/2;
                Y = YLim    + diff(YLim)/(2*length(CData))*[+1 -1];
            else % isempty(YTick)
                % Horizontal:
                Y = YLim(1) + diff(YLim)/2;
                X = XLim    + diff(XLim)/(2*length(CData))*[+1 -1];
            end
            
            % Gets colormap:
            if isempty(CMAP)
                cmap = colormap(fig);
            else
                cmap = CMAP;
            end
            
            % Draws a new RGB image:
            image(X,Y,ind2rgb(CData,cmap),...
                'Parent'            ,cbh,...
                'HitTest'           ,'off',...
                'Interruptible'     ,'off',...
                'SelectionHighlight','off',...
                'Tag'               ,imageTag)
            
            % Moves all '...Mode' properties at the end of the structure,
            % so they won't become 'manual':
            % Bug found by Rafa at the FEx. Thanks!, which also solves the
            % bug found by Jenny at the FEx too. Version 2.0
            cbfields = fieldnames(cbprops);
            indmode  = strfind(cbfields,'Mode');
            temp     = repmat({'' []},length(indmode),1);
            cont     = 0;
            for k = 1:length(indmode)
                % Removes the '...Mode' properties:
                if ~isempty(indmode{k})
                    cont = cont+1;
                    temp{cont,1} = cbfields{k};
                    temp{cont,2} = getfield(cbprops,cbfields{k});
                    cbprops = rmfield(cbprops,cbfields{k});
                end
            end
            for k=1:cont
                % Now adds them at the end:
                cbprops = setfield(cbprops,temp{k,1},temp{k,2});
            end
            
            % Removes special COLORBARs properties:
            cbprops = rmfield(cbprops,{...
                'CurrentPoint','TightInset','BeingDeleted','Type',...       % read-only
                'Title','XLabel','YLabel','ZLabel','Parent','Children',...  % handles
                'UIContextMenu','Location',...                              % colorbars
                'ButtonDownFcn','DeleteFcn',...                             % callbacks
                'CameraPosition','CameraTarget','CameraUpVector', ...
                'CameraViewAngle',...
                'PlotBoxAspectRatio','DataAspectRatio','Position',...
                'XLim','YLim','ZLim'});
            
            % And now, set new axes properties almost equal to the unfrozen
            % colorbar:
            set(cbh,cbprops)
            
            % CallBack features:
            set(cbh,...
                'ActivePositionProperty','position',...
                'ButtonDownFcn'         ,@cbfreeze,...  % mhh...
                'DeleteFcn'             ,@cbfreeze)     % again
            set(peer,'DeleteFcn'        ,@cbfreeze)     % and again!
            
            % Do not zoom or pan or rotate:
            %if isAllowAxesZoom(fig,cbh)
            setAllowAxesZoom  (    zoom(fig),cbh,false)
            %end
            %if isAllowAxesPan(fig,cbh)
            setAllowAxesPan   (     pan(fig),cbh,false)
            %end
            %if isAllowAxesRotate(fig,cbh)
            setAllowAxesRotate(rotate3d(fig),cbh,false)
            %end
            
            % Updates data:
            CBH(icb) = cbh;
            
            % Saves data for future undo:
            cbdata.peerHandle = peer;
            cbdata.cbHandle   = cbh;
            setappdata(cbh ,appName,cbdata);
            setappdata(peer,appName,cbdata);
            
            % Returns current axes:
            if ishandle(cah)
                set(fig,'CurrentAxes',cah)
            end
            
    end % switch functionality
    
end  % MAIN loop

% Resets the current figure
if ishandle(cfh)
    set(0,'CurrentFigure',cfh)
end

% OUTPUTS CHECK-OUT
% -------------------------------------------------------------------------

% Output?:
if ~nargout
    clear CBH
else
    CBH(~ishandle(CBH)) = [];
end

end

% [EOF] CBFREEZE.M by Carlos A. Vargas A.

Contact us