image thumbnail

datefig: figure handle class with automatically readjusting date ticks

by

 

27 Jul 2011 (Updated )

Handle class object that automatically resets date ticks after resize, zoom or pan.

datefig
classdef datefig < handle
    % DATEFIG A date figure handle class object.
    %   OBJ = DATEFIG creates a date figure object.
    %
    %   [H,OBJ,DATA] = DATEFIG.PLOT(...) creates a date figure object OBJ
    %   and plots DATA with date ticks on the x-axis.
    %   DATEFIG.PLOT(OBJ,...) creates a plot in OBJ, which must be a
    %   datefig class object.
    %
    %   DATEFIG.SCATTER(...) creates a date figure object OBJ with a
    %   scatter plot and places dateticks on the x-axis of a scatter plot.
    %   DATEFIG.SCATTER(OBJ,...) creates scatter plot in OBJ which must be
    %   a datefig class object.
    %
    %   [AX,H1,H2,OBJ,DATA] = DATEFIG.PLOTYY(X1,Y1,X2,Y2) creates a date
    %   figure object OBJ with PLOTYY and places dateticks on the x-axis of
    %   a scatter plot.
    %   DATEFIG.PLOTYY(OBJ,...) creates PLOTYY in OBJ which must be a
    %   datefig class object.
    %
    % See also DATETICK, ZOOM, PAN, PLOT/PLOT, SCATTER/SCATTER,
    %   PLOTYY/PLOTYY, FIGURE, LINKAXES
    %
    % Reference:
    % http://www.mathworks.com/help/releases/R2011a/techdoc/ref/figure_props.html#ResizeFcn

    % Mark Mikofski, SunPower Corp.
    % Version 1-0, 2011-07
    % Version 1-1, 2011-07-28
    % 1. fix error, plot was only accepting pairs of inputs, could not
    %   input string for color/shape, single argument, etc.
    % 2. add overloaded method for scatter
    % Version 1-2, 2011-07-28
    % add overloaded method for plotyy, fix error that cause uitool to
    % throw error on datetick since eventData.Axes is vector and datetick
    % only accepts scalar, fix error with reset zoom/pan only rescales one
    % of axes
    
    properties (Constant)
        version = 1.2 % version of code
    end
    properties (SetAccess = immutable)
        figureHandle = [] % figure handle
        zoomHandle = [] % zoom handle
        panHandle = [] % pan handle
    end
    methods
        function df = datefig
            df.figureHandle = figure;
            set(df.figureHandle,'ResizeFcn',@datefig.myResizeFcn)
            df.zoomHandle = zoom(df.figureHandle);
            df.panHandle = pan(df.figureHandle);
            set(df.zoomHandle,'ActionPostCallback',@datefig.myZoomPanFcn);
            set(df.panHandle,'ActionPostCallback',@datefig.myZoomPanFcn);
        end % constructor
    end
    methods (Static)
        function [h,obj,data] = plot(varargin)
            % DATEFIG.PLOT Plot in a date figure.
            %   [H,OBJ,DATA] = DATEFIG.PLOT(...) creates a date figure
            %   object OBJ and plots DATA with date ticks on the x-axis.
            %   DATEFIG.PLOT(OBJ,...) creates a plot in OBJ, which must be
            %   a datefig class object.
            if isa(varargin{1},'datefig') % checks if first argument is a DATEFIG object
                obj = varargin{1};
                figure(obj.figureHandle); % makes OBJ the current figure
                data = varargin(2:end);   % data to pass to PLOT
            else
                obj = datefig;
                data = varargin;
            end
            h = plot(data{:});
            datetick('x')
            xlabel('Time')
            grid
        end
        function [h,obj,data] = scatter(varargin)
            % DATEFIG.SCATTER Create a scatter plot in a date figure.
            %   [H,OBJ,DATA] = DATEFIG.SCATTER(...) creates a date figure
            %   object OBJ with a scatter plot and places dateticks on the
            %   x-axis of a scatter plot.
            %   DATEFIG.SCATTER(OBJ,...) creates scatter plot in OBJ which
            %   must be a datefig class object.
            if isa(varargin{1},'datefig') % checks if first argument is a DATEFIG object
                obj = varargin{1};
                figure(obj.figureHandle); % makes OBJ the current figure
                data = varargin(2:end);   % data to pass to PLOT
            else
                obj = datefig;
                data = varargin;
            end
            h = scatter(data{:});
            datetick('x')
            xlabel('Time')
            grid
        end
        function [ax,h1,h2,obj,data] = plotyy(varargin)
            % DATEFIG.PLOTYY Create a 2-axes plot in a date figure.
            %   [AX,H1,H2,OBJ,DATA] = DATEFIG.PLOTYY(X1,Y1,X2,Y2) creates a
            %   date figure object OBJ with PLOTYY and places dateticks on
            %   the x-axis of a scatter plot.
            %   DATEFIG.PLOTYY(OBJ,...) creates PLOTYY in OBJ which must be
            %   a datefig class object.
            if isa(varargin{1},'datefig') % checks if first argument is a DATEFIG object
                obj = varargin{1};
                figure(obj.figureHandle); % makes OBJ the current figure
                data = varargin(2:end);   % data to pass to PLOT
            else
                obj = datefig;
                data = varargin;
            end
            [ax,h1,h2] = plotyy(data{:});
            linkaxes(ax,'x')
            datetick(ax(1),'x','keeplimits'),datetick(ax(2),'x','keeplimits')
            xlabel('Time')
            grid
        end
        function myZoomPanFcn (figureHandle,eventData) %#ok<INUSD>
            % zoomHandle.ActionPostCallback requires figureHandle arg.
            subPlots = allchild(figureHandle);
            subPlots = subPlots(strcmp(get(subPlots,'Type'),'axes'));
            if ~isempty(subPlots)
                subPlots = subPlots(~strcmp(get(subPlots,'Tag'),'legend'));
            end
            nSubPlots = length(subPlots);
            for n = 1:nSubPlots
                datetick(subPlots(n),'x','keeplimits');
            end
            % Don't use eventData.Axes becuase:
            % 1. For zoom/pan on PLOTYY, eventData.Axes is a vector, and
            % DATETICK will fail since it does not accept vector of axes.
            % 2. For reset zoom/pan on PLOTYY, eventData.Axes only contains
            % one axes, and so not all axes will be rescaled.
        end
        function myResizeFcn(figureHandle,eventData) %#ok<INUSD>
            % figureHandle.ResizeFcn requires eventData arg.
            subPlots = allchild(figureHandle);
            subPlots = subPlots(strcmp(get(subPlots,'Type'),'axes'));
            if ~isempty(subPlots)
                subPlots = subPlots(~strcmp(get(subPlots,'Tag'),'legend'));
            end
            nSubPlots = length(subPlots);
            for n = 1:nSubPlots
                datetick(subPlots(n),'x','keeplimits');
            end
        end
    end
    
end

Contact us