gusucode.com > 信号处理工具箱 - signal源码程序 > signal\signal\siggui\sigbrowse.m

    function varargout = sigbrowse(varargin)
%SIGBROWSE  Signal Browser.
%   This graphical tool allows you to display, measure, filter, hear
%   and analyze digital signals.
%
%   Type 'sptool' to start the Signal Processing GUI Tool and access
%   the Signal Browser.
% 
%   See also SPTOOL, FILTDES, FILTVIEW, SPECTVIEW.

%   Copyright (c) 1988-98 by The MathWorks, Inc.
% $Revision: 1.1 $

if nargin<1 
    if isempty(findobj(0,'tag','sptool'))
        disp('Type ''sptool'' to start the Signal GUI.')
    else
        disp('To use the Signal Browser, import a signal into the SPTool,')
        disp('and then click on the ''View'' button under ''Signals''.')
    end
    return
end

if ~isstr(varargin{1})
    sbinit
    
    save_shh = get(0,'showhiddenhandles');
    set(0,'showhiddenhandles','on')
    set(gcf,'visible','on')
    set(0,'showhiddenhandles',save_shh)
    drawnow
    return
end
%------------------------------------------------------------------------
switch varargin{1}
%------------------------------------------------------------------------
%sigbrowse('update',fig)
%sigbrowse('update',fig,s,ind)
%sigbrowse('update',fig,s,ind,sptoolfig)
%sigbrowse('update',fig,s,ind,sptoolfig,msg)
% Callback for when selected signals have changed
% Inputs:
%   fig - figure handle of signal browser
%   s - structure array of signals 
%   ind - index of selected signals   
%     s,ind together are optional - if omitted, they are obtained from SPTool
%   sptoolfig - figure handle of SPTool (optional)
%   msg - message as passed from SPTool
%    can be 'new', 'value', 'label', 'Fs', 'dup', 'clear'
%    The only real distinction here is between 'new' and the rest;
%      'new' means start from scratch as you cannot count on objects
%      being the same just because they are at the same index position in ind.
%      So 'new' will allocate new lines while anything else will retain any
%      lines that are at the same index location.
case 'update'
    fig = varargin{2};
    ud = get(fig,'userdata');
    
    if nargin > 2
        s = varargin{3};
        ind = varargin{4};
    else
        [s,ind] = sptool('Signals');
    end
    
    if nargin > 5
        msg = varargin{6};
    else
        msg = 'new';  % new starts from scratch
    end
    fromScratch = strcmp(msg,'new');
    
    arrayFlag = 0;
    
    for i = 1:length(s(ind))
        if isempty(s(ind(i)).lineinfo)
            % assign next available line color and style
           [s(ind(i)).lineinfo,ud.colorCount] = ...
               nextcolor(ud.colororder,ud.linestyleorder,ud.colorCount);
            s(ind(i)).lineinfo.columns = 1;
            % poke back into SPTool
            if nargin > 4
                sptool('import',s(ind(i)),0,varargin{5})
            else
                sptool('import',s(ind(i)))
            end
        end
        if strcmp(s(ind(i)).type,'array')
            arrayFlag = 1;
        end
    end

    if arrayFlag
        set(ud.hand.arraybutton,'enable','on')
    else
        set(ud.hand.arraybutton,'enable','off')
    end

    oldLines = ud.lines;
    % de-allocate any lines that are no longer visible (save in cache):
    for i=1:length(ud.lines)
        if ~any(ud.SPToolIndices(i)==ind) | fromScratch
            % a quick command line test reveals that destroying and creating
            % 100 lines is about twice as slow as setting the visible, tag, 
            % xdata, and ydata of 100 lines.
            ud.linecache.h = [ud.linecache.h; ud.lines(i).h];
            ud.linecache.ph = [ud.linecache.ph; ud.lines(i).ph];
        end
    end
 
    % reset line cache:
    set(ud.linecache.h,'visible','off','tag','','xdata',0,'ydata',0)
    if ud.prefs.tool.panner
        set(ud.linecache.ph,'visible','off','tag','','xdata',0,'ydata',0)
    end
        
    N = length(ind);
    if length(ud.lines)>N
        ud.lines(N+1:end) = [];
    end

    complex_flag = 0;
    for i=1:length(s(ind))
        if ~isreal(s(ind(i)).data)
            complex_flag = 1;
        end
    end
    cv = get(ud.hand.complexpopup,'value');
    if complex_flag
        set(ud.hand.complexpopup,'enable','on')
    else
        set(ud.hand.complexpopup,'enable','off')
    end

    for i=1:N
        if ~isempty(ud.SPToolIndices) & ~fromScratch
            j = find(ind(i)==ud.SPToolIndices);
        else
            j = [];
        end
        if isempty(j) | ~isequal(s(ind(i)),ud.sigs(j))
            %assign lines, set xdata and ydata
            [ud.lines(i).h,ud.linecache.h] = assignline(ud.linecache.h,...
                 length(s(ind(i)).lineinfo.columns),ud.mainaxes,...
                 'color',s(ind(i)).lineinfo.color,...
                 'linestyle',s(ind(i)).lineinfo.linestyle,...
                 'visible','on',...
                 'tag',s(ind(i)).label);
            % set up fields for panning:
            ud.lines(i).data = s(ind(i)).data;
            ud.lines(i).columns = s(ind(i)).lineinfo.columns;
            ud.lines(i).Fs = s(ind(i)).Fs;
            ud.lines(i).t0 = 0;  % starting time: 0 by definition
            ud.lines(i).xdata = [];  % initialize field to empty
            if ud.prefs.tool.panner
                [ud.lines(i).ph,ud.linecache.ph] = assignline(...
                           ud.linecache.ph,...
                           length(s(ind(i)).lineinfo.columns),...
                           ud.panner.panaxes,...
                           'color',s(ind(i)).lineinfo.color,...
                           'linestyle',s(ind(i)).lineinfo.linestyle,...
                           'buttondownfcn','sbswitch(''pandown'',1)',...
                           'visible','on',...
                           'tag',s(ind(i)).label);
            end
            for k=1:length(s(ind(i)).lineinfo.columns)
                xd = (0:size(s(ind(i)).data,1)-1)/s(ind(i)).Fs;
                if ~isempty(xd)
                    yd = s(ind(i)).data(:,s(ind(i)).lineinfo.columns(k));
                    yd = sbcomplexfcn(yd,cv,complex_flag);
                else
                    yd = [];
                end
                set(ud.lines(i).h(k),'xdata',xd,'ydata',yd,'visible','on');
                if ud.prefs.tool.panner
                    set(ud.lines(i).ph(k),'xdata',xd,'ydata',yd,'visible','on');
                end
                set(ud.lines(i).h(k),...
                         'buttondownfcn',['sbswitch(''pickfcn'',' ...
                            num2str(i) ',' num2str(k) ')'])
            end
        else
        % use old lines (no need to set x and ydata)
            ud.lines(i) = oldLines(j);
            for k=1:length(s(ind(i)).lineinfo.columns)
                set(ud.lines(i).h(k),...
                     'buttondownfcn',['sbswitch(''pickfcn'',' ...
                                         num2str(i) ',' num2str(k) ')'])
            end
        end
    end  % for i=1:N

    if ~fromScratch
        common = intersect(ud.SPToolIndices,ind);
    else
        common = [];
    end
    ud.SPToolIndices = ind;
    ud.sigs = s(ind);
        
    ud.focusIndex = 1;
    % save the focusline handle in the userdata struct:
    if ~isempty(ud.sigs)
        focusLineInfo = ud.sigs(ud.focusIndex).lineinfo;
        ud.focusline = ud.lines(ud.focusIndex).h(1);
    else
        ud.focusline = [];
    end
    
    sbzoomout(ud,isempty(common),0)  % saves userdata
    ud = get(fig,'userdata');
        
    sptlegend('setstring',{ud.sigs.label},{ud.lines.columns},fig)
    
    set(get(ud.mainaxes,'title'),'string',sbtitle(fig,ud.sigs,'auto',''))
    
    pickfcn('noMouse',ud.focusIndex,1,fig)
      
%------------------------------------------------------------------------
% sigbrowse('changefocus')
%  callback of sptlegend
case 'changefocus'
    [i,j] = sptlegend('value');
    pickfcn('noMouse',i,j)
    
%------------------------------------------------------------------------
% sigbrowse('newColor',lineColor,lineStyle)
%  newColorCallback of sptlegend
%  color and linestyle of ud.focusline have already been updated
case 'newColor'
    lineColor = varargin{2};
    lineStyle = varargin{3};
    
    fig = gcf;
    ud = get(fig,'userdata');
    
    ind = ud.focusIndex;
    ud.sigs(ind).lineinfo.color = lineColor;
    ud.sigs(ind).lineinfo.linestyle = lineStyle;

    set(fig,'userdata',ud)
    
    % poke back into SPTool
    sptool('import',ud.sigs(ind))
    
    % set in case of array signals:
    set(ud.lines(ind).h,'color',lineColor,'linestyle',lineStyle)
    if ud.prefs.tool.panner
        set(ud.lines(ind).ph,'color',lineColor,'linestyle',lineStyle)
    end
    
%------------------------------------------------------------------------
% sigbrowse('array')
%  put up array signals dialog box
case 'array'
    fig = gcf;
    ud = get(fig,'userdata');
    
    % find out which signals are array signals:
    sigTypes = {ud.sigs.type};
    ind = findcstr(sigTypes,'array');
    
    [jkl,columns] = sbarray(ud.sigs(ind));
    if ~isempty(jkl)
        i = ind(jkl);
        % now set the number of columns for ud.sigs(i)
        % disp(sprintf('displaying new columns for signal %g',i))
        if ~isequal(ud.sigs(i).lineinfo.columns,columns)
            ud.sigs(i).lineinfo.columns = columns;
            xd = get(ud.lines(i).h(1),'xdata');
            ud.linecache.h = [ud.linecache.h; ud.lines(i).h];
            if ud.prefs.tool.panner
                ud.linecache.ph = [ud.linecache.ph; ud.lines(i).ph];
            end
            % reset line cache:
            set(ud.linecache.h,'visible','off','tag','','xdata',0,'ydata',0)
            if ud.prefs.tool.panner
                set(ud.linecache.ph,'visible','off','tag','','xdata',0,'ydata',0)
            end
       
            M = length(columns);
            %assign lines, set xdata and ydata
            [ud.lines(i).h,ud.linecache.h] = assignline(ud.linecache.h,...
                  M,ud.mainaxes,...
                  'color',ud.sigs(i).lineinfo.color,...
                  'linestyle',ud.sigs(i).lineinfo.linestyle,...
                  'visible','on',...
                  'tag',ud.sigs(i).label);
            % set up fields for panning:
            ud.lines(i).data = ud.sigs(i).data(:,columns);
            ud.lines(i).columns = columns;
            if ud.prefs.tool.panner
                [ud.lines(i).ph,ud.linecache.ph] = assignline(...
                       ud.linecache.ph,M,...
                       ud.panner.panaxes,...
                       'color',ud.sigs(i).lineinfo.color,...
                       'linestyle',ud.sigs(i).lineinfo.linestyle,...
                       'buttondownfcn','sbswitch(''pandown'',1)',...
                       'visible','on',...
                       'tag',ud.sigs(i).label);
            end
        
            complex_flag = ~isreal(ud.sigs(i).data);
            cv = get(ud.hand.complexpopup,'value');
           
            for k=1:M
                yd = ud.sigs(i).data(:,columns(k));
                yd = sbcomplexfcn(yd,cv,complex_flag);
                set([ud.lines(i).h(k) ud.lines(i).ph(k)],...
                           'xdata',xd,'ydata',yd);
                set(ud.lines(i).h(k),...
                     'buttondownfcn',['sbswitch(''pickfcn'',' ...
                                    num2str(i) ',' num2str(columns(k)) ')'])
            end
            
            sbzoomout(ud,0,0)  % zooms out and saves userdata 
            
            % poke back into SPTool:
            sptool('import',ud.sigs(i))
            sptlegend('setstring',{ud.sigs.label},{ud.lines.columns},fig)
            
            pickfcn('noMouse',i,1,fig)
        end
    else
        % disp('cancelled')
    end
    
    return
    
%------------------------------------------------------------------------
% sigbrowse('print')
%  print contents of sigbrowse (assumed in gcf)
case 'print'

%------------------------------------------------------------------------
% sigbrowse('play')
%  play signal
case 'play'
    ud = get(gcf,'userdata');
    if isempty(ud.focusIndex)
        return
    end
    setptr(gcf,'watch');
    ud.pointer = -1; 
    set(gcf,'userdata',ud)
    
    y = ud.sigs(ud.focusIndex).data(:,ud.focusColumn);
    Fs = ud.sigs(ud.focusIndex).Fs;
        
    if ~isreal(y)
    % for complex signals, play real / imag in separate channels
        y = [real(y(:)) imag(y(:))];
    end

    if Fs < 25   % sampling rate too low - use platform default
        soundStr = 'soundsc(y)';
    else
        soundStr = 'soundsc(y,Fs)';
    end
    eval(soundStr,'')  % catch errors in case of no sound capabilities

    ud.pointer = 0; 
    set(gcf,'userdata',ud)
    sbmotion(gcf)
        
%------------------------------------------------------------------------
% enable = sigbrowse('selection',action,msg,SPTfig)
%  respond to selection change in SPTool
% possible actions are
%    'view'
%  msg - either 'value', 'label', or 'Fs'
%         'value' - only the listbox value has changed
%         'label' - one of the selected objects has changed it's name
%         'Fs' - one of the selected objects's .Fs field has changed
%         'dup' - a selected object was duplicated
%         'clear' - a selected object was cleared
%  Button is enabled when there is at least one signal selected
case 'selection'
    msg = varargin{3};
    sptoolfig = varargin{4};
    [s,ind] = sptool('Signals',1,sptoolfig);
    if isempty(ind)
        enable = 'off';
    else
        enable = 'on';
    end
    fig = findobj('type','figure','tag','sigbrowse');
    if ~isempty(fig)
        ud = get(fig,'userdata');
        switch msg
        case {'new','value','dup'}
            if ~isequal(ud.sigs,s(ind))
                sigbrowse('update',fig,s,ind,sptoolfig,msg)
            end
        case 'label'
            for i=1:length(ind)
                if ~isequal(ud.sigs(i).label,s(ind(i)).label)
                    % change label of ud.sigs(i)
                    ud.sigs(i).label = s(ind(i)).label;
                    set(fig,'userdata',ud)
                    sptlegend('setstring',{ud.sigs.label},{ud.lines.columns},fig,1)
                    set(get(ud.mainaxes,'title'),'string',sbtitle(fig,ud.sigs,'auto',''))
                    break
                end
            end
        case 'Fs'
            for i=1:length(ind)
                if ~isequal(ud.sigs(i).Fs,s(ind(i)).Fs)
                    % change Fs of ud.sigs(i)
                    newFs = s(ind(i)).Fs;
                    oldFs = ud.sigs(i).Fs;
                    xd = (0:length(s(ind(i)).data)-1)/newFs;
                    ud.sigs(i).Fs = newFs;
                    ud.lines(i).Fs = newFs;
                    set(ud.lines(i).h,'xdata',xd)
                    if ud.prefs.tool.panner
                        set(ud.lines(i).ph,'xdata',xd)
                    end
                    sbzoomout(ud,0,1)
                    set(get(ud.mainaxes,'title'),'string',sbtitle(fig,ud.sigs,'auto',''))
                    break
                end
            end
        case 'clear'
            deletedStruc = sptool('changedStruc',sptoolfig);
            if ~strcmp(deletedStruc.SPTIdentifier.type,'Signal')
                % do nothing
            elseif isempty(ind)
                sigbrowse('update',fig,s,ind,sptoolfig,msg)
            else
                % first find out which one was deleted
                rmInd = length(ud.sigs);
                for i = 1:length(ind)
                    if ~strcmp(s(ind(i)).label,ud.sigs(i).label)
                        rmInd = i;
                        break  % found it
                    end
                end
                delete(ud.lines(rmInd).h)
                if ud.prefs.tool.panner
                    delete(ud.lines(rmInd).ph)
                end
                
                ud.sigs(rmInd) = [];
                ud.lines(rmInd) = [];
                
                ud.SPToolIndices = ind;
            
                set(fig,'userdata',ud)
                sptlegend('setstring',{ud.sigs.label},{ud.lines.columns},fig,1)
                
                if ud.focusIndex == rmInd
                  % shift focus to first signal
                    ud.focusIndex = 1;
                    % save the focusline handle in the userdata struct:
                    focusLineInfo = ud.sigs(ud.focusIndex).lineinfo;
                    ud.focusline = ud.lines(ud.focusIndex).h(focusLineInfo.columns(1));
                    sbzoomout(ud,0,0)  % saves userdata
                    ud = get(fig,'userdata');
                    pickfcn('noMouse',ud.focusIndex,1,fig)
                else
                    if ud.focusIndex > rmInd
                        ud.focusIndex = ud.focusIndex - 1;
                    end
                    sbzoomout(ud,0,0)  % saves userdata
                    if ud.prefs.tool.ruler
                        ruler('showlines',fig)
                    end
                    ud = get(fig,'userdata');
                end    
            
            end  % if isempty(ind)
        end  % switch msg
    end  % if ~isempty(fig)
    
    varargout{1} = enable;
    
%------------------------------------------------------------------------
% enable = sigbrowse('action',action,selection)
%  respond to button push in SPTool
% possible actions are
%    'view'
case 'action'
    sptoolfig = gcf;
    fig = findobj('type','figure','tag','sigbrowse');
    if isempty(fig)
        sigbrowse(sptoolfig)
        fig = gcf;
    else
        figure(fig)
    end
    ud = get(fig,'userdata');
    [s,ind] = sptool('Signals',1,sptoolfig);
    if ~isequal(ud.sigs,s(ind))
        sigbrowse('update',fig,s,ind,sptoolfig,'new')
    end

%------------------------------------------------------------------------
% sigbrowse('SPTclose',action)
% Signal Browser close request function
%   This function is called when a browser window is closed.
%  action will be:  'view'
case 'SPTclose'
    fig = findobj('type','figure','tag','sigbrowse');
    if ~isempty(fig)
        ud = get(fig,'userdata');
        if ~isempty(ud.tabfig)
            delete(ud.tabfig)
        end
        delete(fig)
    end
    
%------------------------------------------------------------------------
% errstr = sigbrowse('setprefs',panelName,p)
% Set preferences for the panel with name panelName
% Inputs:
%   panelName - string; must be either 'ruler','color', or 'sigbrowse'
%              (see sptprefreg for definitions)
%   p - preference structure for this panel
case 'setprefs'
    errstr = '';
    panelName = varargin{2};
    p = varargin{3};
    switch panelName
    case 'ruler'
        rc = evalin('base',p.rulerColor,'-1');
        if rc == -1
            errstr = 'The Ruler Color you entered cannot be evaluated.';
        elseif ~iscolor(rc)
            errstr = 'The Ruler Color you entered is not a valid color.';
        end
        if isempty(errstr)
            ms = evalin('base',p.markerSize,'-1');
            if ms == -1
                errstr = 'The Marker Size you entered cannot be evaluated.';
            elseif all(size(ms)~=1) | ms<=0 
                errstr = 'The Marker Size you entered must be a real scalar.';     
            end
        end
    case 'color'
        co = evalin('base',p.colorOrder,'-1');
        if co == -1
            errstr = 'The Color Order that you entered cannot be evaluated.';
        else
            if ~iscell(co)
                co = num2cell(co,[3 2]);  % convert to cell array
            end
            for i = 1:length(co)
                if ~iscolor(co{i})
                    errstr = 'The Color Order that you entered is invalid.';
                    break
                end
            end
        end
    
        if isempty(errstr)
            lso = evalin('base',p.linestyleOrder,'-1');
            if lso == -1
                errstr = 'The Line Style Order that you entered cannot be evaluated.';
            else
                if ~iscell(lso)
                    lso = num2cell(lso,[3 2]);  % convert to cell array
                end
                for i = 1:length(lso)
                    if isempty(findcstr({'-' '--' ':' '-.'},lso{i}))
                        errstr = 'The Line Style Order that you entered is invalid.';
                        break
                    end
                end
            end
        end
        
    case 'sigbrowse'
    end
    varargout{1} = errstr;
    if ~isempty(errstr)
        return
    end
    
    fig = findobj('type','figure','tag','sigbrowse');
    if ~isempty(fig)
        ud = get(fig,'userdata');
        newprefs = ud.prefs;
        switch panelName
        case 'ruler'
            markerStr = { '+' 'o' '*' '.' 'x' ...
               'square' 'diamond' 'v' '^' '>' '<' 'pentagram' 'hexagram'}';
            newprefs.ruler.color = p.rulerColor;
            newprefs.ruler.marker = markerStr{p.rulerMarker};
            newprefs.ruler.markersize = p.markerSize;
            
            if ud.prefs.tool.ruler
                rc = evalin('base',newprefs.ruler.color);
                set(ud.ruler.lines,'color',rc);
                set(ud.ruler.markers,'color',rc,'marker',newprefs.ruler.marker,...
                   'markersize',evalin('base',newprefs.ruler.markersize))
            end
        case 'color'
            newprefs.colororder = p.colorOrder;
            newprefs.linestyleorder = p.linestyleOrder;
            ud.colororder = num2cell(evalin('base',newprefs.colororder),2);
            ud.linestyleorder = num2cell(evalin('base',newprefs.linestyleorder),2);
        case 'sigbrowse'
            newprefs.xaxis.label = p.xlabel;
            newprefs.yaxis.label = p.ylabel;
            newprefs.tool.ruler = p.rulerEnable;
            newprefs.tool.panner = p.pannerEnable;
            newprefs.tool.zoompersist = p.zoomFlag;
            set(get(ud.mainaxes,'xlabel'),'string',p.xlabel)
            set(get(ud.mainaxes,'ylabel'),'string',p.ylabel)
            
            % resize flags
            rbrowse = 0; 
            rpanner = 0;
        
            % enable / disable ruler
            if ud.prefs.tool.ruler~=newprefs.tool.ruler
                if newprefs.tool.ruler
                    % turn ruler on
                    rulerPrefs = sptool('getprefs','ruler');
                    typeStr = {'vertical','horizontal','track','slope'};
                    ud.prefs.ruler.type = typeStr{rulerPrefs.initialType};
                    set(fig,'userdata',ud)
                    ruler('init',fig)
                    ruler('showlines',fig)
                    ruler('newlimits',fig)
                    ruler('newsig',fig)
                else
                    ruler('close',fig)
                end
                ud = get(fig,'userdata');
                rbrowse = 1;
                if newprefs.tool.panner, rpanner = 1; end
            end
        
            % enable / disable panner
            if ud.prefs.tool.panner~=newprefs.tool.panner
                if newprefs.tool.panner
                    panner('init',fig)
                    ud = get(fig,'userdata');
                    for i=1:length(ud.lines)
                        ud.lines.ph = copyobj(ud.lines.h,ud.panner.panaxes);
                        set(ud.lines.ph,'buttondownfcn','sbswitch(''pandown'',1)')
                    end
                else
                    panner('close',fig)
                    ud = get(fig,'userdata');
                end
                rbrowse = 1;
            end
        
            % resize objects if necessary:
            if rbrowse, 
                sbresize(0,fig)
                if newprefs.tool.ruler
                    ruler('resizebtns',fig)
                end
             end
            if rpanner, panner('resize',0,fig), end
        end
        ud.prefs = newprefs;
        set(fig,'userdata',ud)
            
    end

%------------------------------------------------------------------------
% sigbrowse('help')
% Callback of help button in toolbar
case 'help'
    fig = gcf;
    ud = get(fig,'userdata');
    if ud.pointer ~= 2   % if not in help mode
        % enter help mode
        saveEnableControls = [ ud.hand.arraybutton 
                               ud.hand.complexpopup 
                               ud.legend.legendpopup 
                               ud.legend.legendbutton];
        ax = [ud.mainaxes ud.toolbar.toolbar];
        if ud.prefs.tool.ruler
            ax = [ax ud.ruler.hand.ruleraxes];
        end
        if ud.prefs.tool.panner
            ax = [ax ud.panner.panaxes];
        end
        
        titleStr = 'Signal Browser Help';
        helpFcn = 'sbhelpstr';
        spthelp('enter',fig,saveEnableControls,ax,titleStr,helpFcn)
    else
        spthelp('exit')
    end
    
%------------------------------------------------------------------------
% default
otherwise
    if isstr(varargin{1})
        disp(sprintf('Sigbrowse: action ''%s'' not recognized',varargin{1}))
    else
        disp(sprintf('Sigbrowse: takes no arguments',varargin{1}))
    end
end


function sbzoomout(ud,xflag,rulerFlag)
% reset limits of mainaxes, and set Full View limits (ud.limits field)
% Inputs:
%   ud - userdata struct
%   xflag - 1 ==> zoom out in x
%           0 ==> keep xlimits the same
%   rulerFlag (optional) - 1 ==> update rulers (default)
%                          0 ==> don't update rulers
% CAUTION: Sets figure userdata !!!!!

    if nargin < 3
        rulerFlag = 1;
    end
    
    fig = get(ud.mainaxes,'parent');
    
    % turn off rulers for limits calculation:
    if ud.prefs.tool.ruler
        h = [ud.ruler.lines(:); ud.ruler.markers(:)];
        set(h,'visible','off')
    end
        
    % zoom out
    set(ud.mainaxes,'ylimmode','auto')
    if isempty(ud.sigs)
        xlim = get(ud.mainaxes,'xlim');
        ylim = get(ud.mainaxes,'ylim');
    elseif xflag   % FULL VIEW
        x2 = 0;
        for i=1:length(ud.sigs)
            x2 = max(x2,(size(ud.sigs(i).data,1)-1)/ud.sigs(i).Fs);
        end
        if x2 <= 0
            x2 = max(1./[ud.sigs.Fs]);
        end
        xlim = [0 x2];
        ud.limits.xlim = xlim;
        set(ud.mainaxes,'xlim',xlim)
        ylim = get(ud.mainaxes,'ylim');
        ud.limits.ylim = ylim;
    else   % only zoom out Y, but update ud.limits to FULL VIEW
        xlim = get(ud.mainaxes,'xlim');
        x2 = 0;
        for i=1:length(ud.sigs)
            x2 = max(x2,(size(ud.sigs(i).data,1)-1)/ud.sigs(i).Fs);
        end
        if x2 <= 0
            x2 = max(1./[ud.sigs.Fs]);
        end
        ud.limits.xlim = [0 x2];
        set(ud.mainaxes,'xlim',ud.limits.xlim)
        ud.limits.ylim = get(ud.mainaxes,'ylim');
        set(ud.mainaxes,'xlim',xlim)
        ylim = get(ud.mainaxes,'ylim');
    end
    xlim = inbounds(xlim,ud.limits.xlim);
    set(ud.mainaxes,'xlim',xlim,'ylim',ylim)

    set(fig,'userdata',ud)
    
    if ud.prefs.tool.panner
        set(ud.panner.panaxes,'xlim',ud.limits.xlim,'ylim',ud.limits.ylim)
        panner('update',fig)
    end

    if ud.prefs.tool.ruler & rulerFlag
        ruler('showlines',fig)
        ruler('newlimits',fig)
        ruler('newsig',fig)
    end

function data = sbcomplexfcn(data,cv,cf)
%SBCOMPLEXFCN Signal Browser complex number conversion function.
%   Inputs:
%      data - matrix to be converted
%      cv - complex value (1=real,2=imag,3=mag,4=angle)
%      cf - complex flag (0 = no, 1 = yes)
%   Outputs:
%      data - converted input data

    if cf
        switch cv
        case 1    % real
            data = real(data);
        case 2    % imaginary
            data = imag(data);
        case 3    % magnitude
            data = abs(data);
        case 4    % angle
            data = angle(data);
        end
    end