Code covered by the BSD License  

Highlights from
choose_profile_limits

image thumbnail
from choose_profile_limits by Kevin Bartlett
Allows user to choose limits of oceanographic profile (e.g., CTD cast)

choose_profile_limits(varargin)
function [varargout] = choose_profile_limits(varargin)
%
% choose_profile_limits.m--A GUI to enable a user to choose the start and
% end of a depth profile (from a CTD cast, VMP cast, etc.).
%
% choose_profile_limits.m can be called specifying just the depth vector
% (z) as an input argument or both depth and time (x) vectors.
%
% Other options are specified as parameter/value pairs:
%    'closeAfter': if 1, then figure window will close after limits chosen
%       (default is 1);
%    'initStartIndex': an initial value of the index (default is 1);
%    'initEndIndex': an initial value of the index (default is length(z));
%    'boxWidthPct': width of smaller axes as percent of range(x) (default 5);
%    'marker': 'on' or 'off' (the default);
%    'titleStr': default is no title;
%    'xlabelStr': default is no xlabel;
%    'ylabelStr': default is 'pressure/depth';
%    'buttonStrs': default is {'Accept' 'Reject' 'Skip' 'Marker' 'Quit'}
%    'showButtons': default is [1 1 1 1 1]
%
% By default, choose_profile_limits produces a GUI with five buttons:
%   "Accept" returns the current crop limits;
%   "Reject" returns crop limits of [+Inf -Inf];
%   "Skip" returns crop limits of [NaN NaN];
%   "Marker" turns the line markers on and off;
%   "Quit" returns crop limits of [[][]] and closes figure.
%
% If you anticipate no need to distinguish between a user skipping and
% rejecting a particular cast, you can eliminate the "Skip" button by
% setting the 'showButtons' parameter to [1 1 0 1 1]. The 'buttonStrs'
% parameter may then be changed to {'Crop' 'Cancel' 'dummy' 'Marker'
% 'Quit'} (or whatever you want) to make the button labels more intuitive.
% Similarly, remove the ability to turn line markers on and off by
% eliminating the "Marker" button.
%
% H = CHOOSE_PROFILE_LIMITS(PARAMETER,VALUE,...) creates an empty
% choose_profile_limits figure window with handle H. The parameter/value
% pairs are optional.
% 
% ...CHOOSE_PROFILE_LIMITS(H,...), where H is the handle of an existing
% choose_profile_limits figure window, results in the existing figure being
% reused for the next profile. This is useful when choose_profile_limits.m
% is being called in a loop.
%
% Syntax: choose_profile_limits(<h>,<<x>,z>,<parameter1,value1,...>)
%
% e.g.,   [x,z] = choose_profile_limits('demo'); % (gets demo data)
% 
% e.g.,   [startIndex,endIndex] = choose_profile_limits(z)
% 
% e.g.,   [startIndex,endIndex] = choose_profile_limits(x,z)
%
% e.g.,   h = choose_profile_limits('buttonShow',[1 1 0 0 1],'closeAfter',0);
%         [startIndex,endIndex] = choose_profile_limits(h,x,z)
%
% e.g.,   [startIndex,endIndex] = choose_profile_limits(x,z,...
%                               'initStartIndex',32,'initEndIndex',108,...
%                               'boxWidthPct',25,'marker','on',...
%                               'titleStr','This is a title',...
%                               'xlabelStr','Samples',...
%                               'ylabelStr','Depth', ...
%                               'buttonStrs',{'Crop' 'Cancel' 'dummy' 'dummy' 'dummy'}, ...
%                               'buttonShow',[1 1 0 0 0])

% Developed in Matlab 7.0.1.24704 (R14) Service Pack 1 on GLNX86.
% Kevin Bartlett (kpb@uvic.ca), 2006-03-17 16:23
%-------------------------------------------------------------------------

% Define constants.
CROPLINESTYLE = '--';
CROPLINEWIDTH = 3;
markerStyle = 'o';
GuiScale = 1;
DeltaFontSize = 0;
FigurePosition = NaN;
axLimsBufferPct = 5; % percentage of minimum required for data.

% Handle input arguments.

% ...Return demo data if requested.
if nargin == 1

    if isstr(varargin{1})

        if strcmp(lower(varargin{1}),'demo')
            z = [0 0 0 10 20 30 40 50 50 40 30 20 10 0];
            z = interp1([1:length(z)],z,linspace(1,length(z),200));
            %x = linspace(now,now+.1,length(z));
            x = linspace(1000,1100,length(z));
            varargout{1} = x;
            varargout{2} = z;
            return;
        else
            error([mfilename '.m--Unrecognised input string ''' varargin{1} '''']);
        end % if

    end % if

end % if

% If no arguments passed to function or if first argument is a parameter
% name, initialise a "hollow" version of the GUI for later calls. 
if nargin == 0
    isHollow = true;
elseif isstr(varargin{1})
    isHollow = true;
else    
    isHollow = false;
end % if

% Remove first argument from the list if it is the handle of an existing
% choose_profile_limits figure window.
args = varargin;
cplFig = [];

% ...By default, not reusing an existing figure.
doReuse = false;

if length(args) > 0
    if ishandle(args{1})
        if strcmp(get(args{1},'Tag'),'cpl_fig')

            cplFig = args{1};
            doReuse = true;

            if length(args)>1
                args = args(2:end);
            else
                args = {};
            end % if

        end % if
    end % if
end % if

% Arguments are [z] (odd number) or [x,z] (even number) or
% [z,parameter/value pairs] (odd number) or [x,z,parameter/value pairs]
% (even number). The first argument, then, is z if the number of arguments
% is odd; otherwise, the first two arguments are x and z.
isOdd = rem(length(args),2) == 1;

if isHollow
    % Making "hollow" GUI with no data.
    x = [];
    z = [];
elseif isOdd

    x = [];
    z = args{1};

    if length(args) > 1
        args = args(2:end);
    else
        args = {};
    end % if

else

    x = args{1};
    z = args{2};

    if length(args) > 2
        args = args(3:end);
    else
        args = {};
    end % if

end % if

% ...If x is not supplied by user, then create it, making x a simple index
% to the elements of z.
if isempty(x)
    x = 1:length(z);
end % if

if length(x) ~= length(z)
    error([mfilename '.m--Vectors ''x'' and ''z'' must be same length.']);
end % if

% ...Handle parameter/value pairs.
if doReuse == true
    
    % If reusing existing figure, most defaults are extracted from the
    % figure.
    cpl_properties = getappdata(cplFig,'cpl_properties');
    defaultVals.initStartIndex = 1;
    defaultVals.initEndIndex = length(z);
    defaultVals.boxWidthPct = cpl_properties.boxWidthPct;
    defaultVals.titleStr = cpl_properties.titleStr;
    defaultVals.xlabelStr = cpl_properties.xlabelStr;
    defaultVals.ylabelStr = cpl_properties.ylabelStr;
    defaultVals.marker = cpl_properties.marker;
    defaultVals.buttonStrs = cpl_properties.buttonStrs;
    defaultVals.buttonShow = cpl_properties.buttonShow;
    defaultVals.closeAfter = cpl_properties.closeAfter;
    
else
    defaultVals.initStartIndex = 1;
    defaultVals.initEndIndex = length(z);
    defaultVals.boxWidthPct = 5; % percent of total data width
    defaultVals.titleStr = '';
    defaultVals.xlabelStr = '';
    defaultVals.ylabelStr = 'pressure/depth';
    defaultVals.marker = 'off';
    defaultVals.buttonStrs = {'Accept' 'Reject' 'Skip' 'Marker' 'Quit'};
    defaultVals.buttonShow = [1 1 1 1 1];
    defaultVals.closeAfter = 1;
end % if

allowNewFields = 0;
isCaseSensitive = 0;
parValStruct = parse_args(defaultVals,args{:},allowNewFields,isCaseSensitive);
initStartIndex = parValStruct.initStartIndex;
initEndIndex = parValStruct.initEndIndex;
boxWidthPct = parValStruct.boxWidthPct;
titleStr = parValStruct.titleStr;
xlabelStr = parValStruct.xlabelStr;
ylabelStr = parValStruct.ylabelStr;
markerVal = parValStruct.marker;
buttonStrs = parValStruct.buttonStrs;
buttonShow = parValStruct.buttonShow;
closeAfter = parValStruct.closeAfter ;
marker = parValStruct.marker;

% ......Test parameter/value pairs; over-ride if necessary.
if isempty(z)
    initStartIndex = [];
    initEndIndex = [];
else

    if initStartIndex < 0
        initStartIndex = 1;
    end % if

    if initStartIndex>length(z)
        initStartIndex = 1;
    end % if

    if initEndIndex <= initStartIndex
        initEndIndex = length(z);
    end % if

    if initEndIndex>length(z)
        initEndIndex = length(z);
    end % if

end % if

if boxWidthPct <= 0 | boxWidthPct >= 100
    boxWidthPct = defaultVals.boxWidthPct;
end % if

if ~isstr(titleStr)
    titleStr = '';
end % if

if ~isstr(xlabelStr)
    xlabelStr = '';
end % if

if ~isstr(ylabelStr)
    ylabelStr = '';
end % if

% Create GUI objects if they don't already exist.
if isempty(cplFig)
    doCreateGUI = true;
else
    doCreateGUI = false;
end % if

if doCreateGUI
    cplObjs = cpl_makeguiobjects(GuiScale,DeltaFontSize,FigurePosition);
    cplFig = findobj(cplObjs,'Type','figure');
    set(findobj(cplFig,'Tag','accept_control'),'Callback','accept_control_callback');
    set(findobj(cplFig,'Tag','reject_control'),'Callback','reject_control_callback');
    set(findobj(cplFig,'Tag','skip_control'),'Callback','skip_control_callback');
    set(findobj(cplFig,'Tag','marker_control'),'Callback','marker_control_callback');
    set(findobj(cplFig,'Tag','quit_control'),'Callback','quit_control_callback');
    set(findobj(cplFig,'Tag','full_ax'),'ButtonDownFcn','full_ax_mouse_callback')
    helpMenu = uimenu('Label','Help');
    set(helpMenu,'Callback','cpl_help');
    cpl_make_lines(cplFig);

    % Customise button labels.
    accept_control = findobj(cplFig,'Tag','accept_control');
    reject_control = findobj(cplFig,'Tag','reject_control');
    skip_control = findobj(cplFig,'Tag','skip_control');
    marker_control = findobj(cplFig,'Tag','marker_control');
    quit_control = findobj(cplFig,'Tag','quit_control');

    set(accept_control,'String',buttonStrs{1});
    set(reject_control,'String',buttonStrs{2});
    set(skip_control,'String',buttonStrs{3});
    set(marker_control,'String',buttonStrs{4});
    set(quit_control,'String',buttonStrs{5});

    % Make some buttons invisible, if requested.
    buttonShowStrs = cell(length(buttonShow),1);
    [buttonShowStrs{:}] = deal('on');
    [buttonShowStrs{buttonShow==0}] = deal('off');
    set(accept_control,'visible',buttonShowStrs{1});
    set(reject_control','visible',buttonShowStrs{2});
    set(skip_control,'visible',buttonShowStrs{3});
    set(marker_control,'visible',buttonShowStrs{4});
    set(quit_control,'visible',buttonShowStrs{5});

    % Adjust the location of the buttons if any have been made invisible.
    if any(buttonShow==0)

        buttonPos = [];
        buttonPos(end+1,:) = get(accept_control,'position');
        buttonPos(end+1,:) = get(reject_control,'position');
        buttonPos(end+1,:) = get(skip_control,'position');
        buttonPos(end+1,:) = get(marker_control,'position');
        buttonPos(end+1,:) = get(quit_control,'position');
        buttonWidth = buttonPos(1,3);
        leftMost = buttonPos(1,1);
        rightMost = buttonPos(end,1)+buttonWidth;
        %buttonPanelCentre = mean([leftMost rightMost]);
        buttonPanelWidth = rightMost - leftMost;
        numButtons = length(find(buttonShow==1));
        buttonCentres = leftMost + ((1:numButtons)./(numButtons+1)) .* buttonPanelWidth;
        leftLocations = buttonCentres - buttonWidth/2;
        newButtonPos = buttonPos;
        newButtonPos(buttonShow==1,1) = leftLocations;

        set(accept_control,'position',newButtonPos(1,:));
        set(reject_control,'position',newButtonPos(2,:));
        set(skip_control,'position',newButtonPos(3,:));
        set(marker_control,'position',newButtonPos(4,:));
        set(quit_control,'position',newButtonPos(5,:));

    end % if

    set(findobj(cplFig,'Tag','full_ax'),'box','on','ydir','reverse');
    set(findobj(cplFig,'Tag','start_ax'),'box','on','ydir','reverse');
    set(findobj(cplFig,'Tag','end_ax'),'box','on','ydir','reverse');

end % if

% Initialise appdata to initial limits.
setappdata(cplFig,'profileLimits',[initStartIndex initEndIndex]);

set(get(findobj(cplFig,'Tag','full_ax'),'title'),'string',titleStr);
set(get(findobj(cplFig,'Tag','full_ax'),'xlabel'),'string',xlabelStr);
set(get(findobj(cplFig,'Tag','full_ax'),'ylabel'),'string',ylabelStr);

% ...Data lines:
if strcmp(markerVal,'on')
    markerStr = markerStyle;
else
    markerStr = 'none';
end % if

full_ax_preStartDepthLine = findobj(cplFig,'Tag','full_ax_preStartDepthLine');
full_ax_postEndDepthLine = findobj(cplFig,'Tag','full_ax_postEndDepthLine');
full_ax_selectDepthLine = findobj(cplFig,'Tag','full_ax_selectDepthLine');
start_ax_preStartDepthLine = findobj(cplFig,'Tag','start_ax_preStartDepthLine');
start_ax_postEndDepthLine = findobj(cplFig,'Tag','start_ax_postEndDepthLine');
start_ax_selectDepthLine = findobj(cplFig,'Tag','start_ax_selectDepthLine');
end_ax_preStartDepthLine = findobj(cplFig,'Tag','end_ax_preStartDepthLine');
end_ax_postEndDepthLine = findobj(cplFig,'Tag','end_ax_postEndDepthLine');
end_ax_selectDepthLine = findobj(cplFig,'Tag','end_ax_selectDepthLine');

set(full_ax_preStartDepthLine,'marker',markerStr);
set(full_ax_postEndDepthLine,'marker',markerStr);
set(full_ax_selectDepthLine, ...
    'marker',markerStr,...
    'xdata',x,...
    'ydata',z);

set(start_ax_preStartDepthLine,'marker',markerStr);
set(start_ax_postEndDepthLine,'marker',markerStr);

set(start_ax_selectDepthLine,...
    'marker',markerStr,...
    'xdata',x,...
    'ydata',z);

set(end_ax_preStartDepthLine,'marker',markerStr);
set(end_ax_postEndDepthLine,'marker',markerStr);

set(end_ax_selectDepthLine,...
    'marker',markerStr,...
    'xdata',x,...
    'ydata',z);

%set(findobj(cplFig,'Tag','full_ax_preStartDepthLine'),'UserData',markerVal);
lineProps = {markerStyle markerVal};
set(findobj(cplFig,'Tag','full_ax_preStartDepthLine'),'UserData',lineProps);

startBoxL = findobj(cplFig,'Tag','startBoxL');
startBoxR = findobj(cplFig,'Tag','startBoxR');
startBoxT = findobj(cplFig,'Tag','startBoxT');
startBoxB = findobj(cplFig,'Tag','startBoxB');

endBoxL = findobj(cplFig,'Tag','endBoxL');
endBoxR = findobj(cplFig,'Tag','endBoxR');
endBoxT = findobj(cplFig,'Tag','endBoxT');
endBoxB = findobj(cplFig,'Tag','endBoxB');

full_ax_StartLine = findobj(cplFig,'Tag','full_ax_StartLine');

if isempty(z)
    initStartX = [];
    initEndX = [];
    initZ = [];
else
    initStartX = [x(initStartIndex) x(initStartIndex)];
    initEndX = [x(initEndIndex) x(initEndIndex)];
    initZ = [NaN NaN];
end % if

set(full_ax_StartLine,'xdata',initStartX,'ydata',initZ);
full_ax_EndLine = findobj(cplFig,'Tag','full_ax_EndLine');
set(full_ax_EndLine,'xdata',initEndX,'ydata',initZ);
start_ax_StartLine = findobj(cplFig,'Tag','start_ax_StartLine');
set(start_ax_StartLine,'xdata',initStartX,'ydata',initZ);
start_ax_EndLine = findobj(cplFig,'Tag','start_ax_EndLine');
set(start_ax_EndLine,'xdata',initEndX,'ydata',initZ);

% ...Start/end lines for end axis:
end_ax_StartLine = findobj(cplFig,'Tag','end_ax_StartLine');
set(end_ax_StartLine,'xdata',initStartX,'ydata',initZ);
end_ax_EndLine = findobj(cplFig,'Tag','end_ax_EndLine');
set(end_ax_EndLine,'xdata',initEndX,'ydata',initZ);

cropLines = [full_ax_StartLine full_ax_EndLine ...
    start_ax_StartLine start_ax_EndLine ...
    end_ax_StartLine end_ax_EndLine];

set(cropLines,'linewidth',CROPLINEWIDTH,'linestyle',CROPLINESTYLE);

% ......Ignore crop lines in determining y-limits of plot.
set(cropLines,'yliminclude','off');

% Add callbacks to lines and buttons, etc.
%set(cropLines,'ButtonDownFcn','cpl_drag_crop_lines');
draglines(cropLines,'cpl_finish_crop_drag');
set([startBoxL startBoxR endBoxL endBoxR],'ButtonDownFcn','cpl_drag_box_lines');

% Store certain values in the figure for later use by other functions.
cpl_properties.boxWidthPct = boxWidthPct;
cpl_properties.axLimsBufferPct = axLimsBufferPct;
cpl_properties.x = x;
cpl_properties.z = z;
cpl_properties.startIndex = initStartIndex;
cpl_properties.endIndex = initEndIndex;
cpl_properties.titleStr = titleStr;
cpl_properties.xlabelStr = xlabelStr;
cpl_properties.ylabelStr = ylabelStr;
cpl_properties.marker = marker;
cpl_properties.buttonStrs = buttonStrs;
cpl_properties.buttonShow = buttonShow;
cpl_properties.closeAfter = closeAfter;
setappdata(cplFig,'cpl_properties',cpl_properties);

accept_control = findobj(cplFig,'Tag','accept_control');
reject_control = findobj(cplFig,'Tag','reject_control');
skip_control = findobj(cplFig,'Tag','skip_control');
marker_control = findobj(cplFig,'Tag','marker_control');
quit_control = findobj(cplFig,'Tag','quit_control');

if isHollow    
    % Disable all but the Quit button.
    set([accept_control reject_control skip_control marker_control],...
        'enable','off');
    
    % Return the figure handle.
    if nargout > 0
        varargout{1} = cplFig;
    end % if
    
    return;
    
else
    % Otherwise, enable all controls.
    set([accept_control reject_control skip_control marker_control quit_control],...
        'enable','on');
end % if

cpl_update(cplFig);

% Wait for figure window to be closed or a GUI button to be pressed.
uiwait;

if ishandle(cplFig)
    xlims = getappdata(cplFig,'profileLimits');
else
    % If figure has been closed, then xlims will be empty (xlims will also
    % be empty if Quit button was pressed).
    xlims = [];
end % if

if closeAfter == 1
    if ishandle(cplFig)
        close(cplFig);
    end % if
end % if

if nargout > 1
    if length(xlims)>1
        varargout{1} = xlims(1);
        varargout{2} = xlims(2);
    else
        varargout{1} = [];
        varargout{2} = [];
    end
end % if

%-------------------------------------------------------------------------
function [] = cpl_make_lines(cplFig)
%
% cpl_make_lines.m--Makes line objects for cpl GUI (cpl_makeguiobjects.m
% makes only axes, uicontrols, etc.).

% Syntax: cpl_make_lines(cplFig)

% Developed in Matlab 7.0.1.24704 (R14) Service Pack 1 on GLNX86.
% Kevin Bartlett (kpb@uvic.ca), 2006-03-17 16:23
%-------------------------------------------------------------------------

LEFTCOLOUR = [1 0 0];
RIGHTCOLOUR = [0 1 0];
BOXCOLOUR = .1 * [1 1 1];
PRESTARTCOLOUR = .7 * [1 1 1];
POSTENDCOLOUR = .7 * [1 1 1];
SELECTLINEWIDTH = 3;
SELECTCOLOUR = [0 0 1];

axes(findobj(cplFig,'Tag','full_ax'));
full_ax_preStartDepthLine = line(NaN,NaN,...
    'Tag','full_ax_preStartDepthLine',...
    'color',PRESTARTCOLOUR);

full_ax_postEndDepthLine = line(NaN,NaN,...
    'Tag','full_ax_postEndDepthLine',...
    'color',POSTENDCOLOUR);

full_ax_selectDepthLine = line(NaN,NaN,...
    'Tag','full_ax_selectDepthLine',...
    'color',SELECTCOLOUR,...
    'lineWidth',SELECTLINEWIDTH);

axes(findobj(cplFig,'Tag','start_ax'));
start_ax_preStartDepthLine = line(NaN,NaN,...
    'Tag','start_ax_preStartDepthLine',...
    'color',PRESTARTCOLOUR);

start_ax_postEndDepthLine = line(NaN,NaN,...
    'Tag','start_ax_postEndDepthLine',...
    'color',POSTENDCOLOUR);

start_ax_selectDepthLine = line(NaN,NaN,...
    'color',SELECTCOLOUR,...
    'lineWidth',SELECTLINEWIDTH,...
    'Tag','start_ax_selectDepthLine');

axes(findobj(cplFig,'Tag','end_ax'));
end_ax_preStartDepthLine = line(NaN,NaN,...
    'Tag','end_ax_preStartDepthLine',...
    'color',PRESTARTCOLOUR);

end_ax_postEndDepthLine = line(NaN,NaN,...
    'Tag','end_ax_postEndDepthLine',...
    'color',POSTENDCOLOUR);

end_ax_selectDepthLine = line(NaN,NaN,...
    'Tag','end_ax_selectDepthLine',...
    'color',SELECTCOLOUR,...
    'lineWidth',SELECTLINEWIDTH);

% ...Make "boxes" in full-profile axes, indicating region covered by start
% and end axes.

% ......Start box.
axes(findobj(cplFig,'Tag','full_ax'));
startBoxL = line([NaN NaN],[NaN NaN],'Tag','startBoxL');
startBoxR = line([NaN NaN],[NaN NaN],'Tag','startBoxR');
startBoxT = line([NaN NaN],[NaN NaN],'Tag','startBoxT');
startBoxB = line([NaN NaN],[NaN NaN],'Tag','startBoxB');

% ......End box.
axes(findobj(cplFig,'Tag','full_ax'));
endBoxL = line([NaN NaN],[NaN NaN],'Tag','endBoxL');
endBoxR = line([NaN NaN],[NaN NaN],'Tag','endBoxR');
endBoxT = line([NaN NaN],[NaN NaN],'Tag','endBoxT');
endBoxB = line([NaN NaN],[NaN NaN],'Tag','endBoxB');

boxLines = [startBoxL startBoxR startBoxT startBoxB ...
    endBoxL endBoxR endBoxT endBoxB];

set(boxLines,'color',BOXCOLOUR,'linestyle','--');

% ...Start/end lines for full-profile axis:
axes(findobj(cplFig,'Tag','full_ax'));
full_ax_StartLine = line([NaN NaN],[NaN NaN],'color',LEFTCOLOUR,'Tag','full_ax_StartLine');
full_ax_EndLine = line([NaN NaN],[NaN NaN],'color',RIGHTCOLOUR,'Tag','full_ax_EndLine');

% ...Start/end lines for start axis:
axes(findobj(cplFig,'Tag','start_ax'));
start_ax_StartLine = line([NaN NaN],[NaN NaN],'color',LEFTCOLOUR,'Tag','start_ax_StartLine');
start_ax_EndLine = line([NaN NaN],[NaN NaN],'color',RIGHTCOLOUR,'Tag','start_ax_EndLine');

% ...Start/end lines for end axis:
axes(findobj(cplFig,'Tag','end_ax'));
end_ax_StartLine = line([NaN NaN],[NaN NaN],'color',LEFTCOLOUR,'Tag','end_ax_StartLine');
end_ax_EndLine = line([NaN NaN],[NaN NaN],'color',RIGHTCOLOUR,'Tag','end_ax_EndLine');

Contact us at files@mathworks.com