Code covered by the BSD License  

Highlights from
Time Series Viewer

image thumbnail
from Time Series Viewer by Scott Hirsch
Interactive tool for plotting time series.

timeseriesviewer(varargin)
function varargout = timeseriesviewer(varargin)
%% TIMESERIESVIEWER    Interactive application for exploring time series data
%
% TIMESERIESVIEWER opens the timeseriesviewer application. Detailed help is available
% from the help menu.  

% Scott Hirsch
% shirsch@mathworks.com
% Copyright 2003 - 2003 The MathWorks, Inc.


% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
    'gui_Singleton',  gui_Singleton, ...
    'gui_OpeningFcn', @timeseriesviewer_OpeningFcn, ...
    'gui_OutputFcn',  @timeseriesviewer_OutputFcn, ...
    'gui_LayoutFcn',  [] , ...
    'gui_Callback',   []);
if nargin & isstr(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT


% --- Executes just before timeseriesviewer is made visible.
function timeseriesviewer_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to timeseriesviewer (see VARARGIN)

% Choose default command line output for timeseriesviewer
handles.output = hObject;

% Handle multiple axes configurations.
% There are 4 configurations, containing between 1 and 4 axes. 
% All possible positions are laid out in guide, but we'll only use 4 of the
% axes.  Get the positions from all axes, then delete the ones we don't
% need.  We'll hide the axes we aren't currently using

% Store axes handles a bit more conveniently
ax1 = handles.Ax11;                                             %1 Axes
ax2 = [handles.Ax21 handles.Ax22];                              %2 Axes
ax3 = [handles.Ax31 handles.Ax32 handles.Ax33];                 %3 Axes
ax4 = [handles.Ax41 handles.Ax42 handles.Ax43 handles.Ax44];    %4 Axes

handles.axes = ax4;     %These are the only four we need
handles.axpos{1} = {get(ax1,'Position')};
handles.axpos{2} = get(ax2,'Position');
handles.axpos{3} = get(ax3,'Position');
handles.axpos{4} = get(ax4,'Position');

delete([ax1 ax2 ax3]);

% Initially, show only one axes
DA = 1;            %Vector from 1:number axes
set(ax4(DA),'Visible','on','Position',handles.axpos{1}{1});
set(ax4(DA+1:end),'Visible','off');

% Make the one visible axes look inactive
inactivecolor = [.7 .7 .7];
set(ax4(DA),'Color',inactivecolor,'XColor',inactivecolor,'YColor',inactivecolor);

% Configure drag and drop interface.
% Allow parameters to be dragged from parameter list to axes
% Also allow one axes to be dragged to another - replace the contents of
% the target with the source.  This is useful for moving a plot up to the
% top axes
% Finally, allow for parameters to be dragged from parameter list to
% TimeSelectPopup.  This defines these parameters as time bases, as removes
% them from the parameter list.
dd = dragndrop(handles.figure1);

set(dd,'DragHandles',[handles.listbox1 handles.axes]);
% set(dd,'DropHandles',[handles.axes handles.TimeSelectPopup]);
set(dd,'DropHandles',[handles.axes handles.AddTimeVectorsFrame]);
set(dd,'DropCallbacks',@localDropCallback);
set(dd,'DropValidDrag','all');
% set(dd,'DropValidDrag','all');

% Make only the Time Select popup valid.  Once the user adds something 
% to the TimeSelect, we'll enable visible axes, too.  This happens in
% localDropCallback.
% set(dd,'DropHandles',handles.TimeSelectPopup);
set(dd,'DropHandles',handles.AddTimeVectorsFrame);

handles.dd = dd;

% Add a context menu to the axes
% Add a context menu to each line
cmenu = uicontextmenu('Parent',handles.figure1);
set(handles.axes,'UIContextMenu',cmenu);
item1 = uimenu(cmenu, 'Label', 'Export Axes', ...        % Export Axes
    'Callback', @localExportAxes,'Tag','ExportAxes');

item2 = uimenu(cmenu, 'Label', 'Clear Axes', ...        % Clear Axes
    'Callback', @localClearAxes,'Tag','ClearAxes', ...
    'Separator','on');

% Put icons on toolbar
load zoom_icons
set(handles.ZoomButton,'CData',zoomxCData);

load datatip_icon
set(handles.DataLabelButton,'CData',cdata);

% Initialize a storage location for derived parameters
handles.derivedparameters = {};

% Initialize application data for storage of parameter names in each axes
for ii=1:length(handles.axes)
    setappdata(handles.axes(ii),'Parameters',{})
end;

% Load data from workspace
%   - populate parameter list with all 2D variables, except time
localUpdateParmlist(handles);

% Add a context menu to the parameter list
% I can't do this, because the context menu shows up whenever you drag!!
% cmenu = uicontextmenu('Parent',handles.figure1);
% set(handles.listbox1,'UIContextMenu',cmenu);
% item1 = uimenu(cmenu, 'Label', 'Clear', ...        % Clear Parameter
%     'Callback', @localClearParameter,'Tag','ClearParameter');
% item2 = uimenu(cmenu, 'Label', 'Update Parameters', ...        % Refresh Parameter List
%     'Callback', @localUpdateParmlist,'Tag','UpdateParameters');

% Initialize the TimeSelectPopup, so it knows that no data has been dragged
% to it.
firsttime = 1;
set(handles.TimeSelectPopup,'UserData',firsttime);

% Update handles structure
guidata(hObject, handles);
%UIWAIT makes timeseriesviewer wait for user response (see UIRESUME)
% uiwait(handles.figure1);

movegui(handles.figure1,'north')

% --- Outputs from this function are returned to the command line.
function varargout = timeseriesviewer_OutputFcn(hObject, eventdata, handles)
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure
varargout{1} = handles.output;


% --- Executes during object creation, after setting all properties.
function listbox1_CreateFcn(hObject, eventdata, handles)
% hObject    handle to listbox1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: listbox controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end


% --- Executes on selection change in listbox1.
function listbox1_Callback(hObject, eventdata, handles)
% hObject    handle to listbox1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: contents = get(hObject,'String') returns listbox1 contents as cell array
%        contents{get(hObject,'Value')} returns selected item from listbox1



function localDropCallback(drag,drop);
% Don't do anything if drop target is invisible (such as a hidden axes)
vis = get(drop,'Visible');
if ~strcmp(vis,'on')
    return
end;
handles = guidata(drag);        %Get handles structure

% Switch between drop target types:
% 1) Popupmenu.  Identify a parameter as a time basis.
% 2) Axes.  Drag and drop plotting

switch get(drop,'Type')
    case 'uicontrol'    % Identify a parameter as a time basis.
        
        % Special case for first time
        %  - Enable other controls
        %  - Replace string with parameters
        firsttime = get(handles.TimeSelectPopup,'UserData');
        if firsttime
            oldtimes = {};
            firsttime = 0;
            set(handles.TimeSelectPopup,'UserData',firsttime);
            
            % Enable dropping on the axes.
%             handles.dd = set(handles.dd,'DropHandles',[handles.axes(1) handles.TimeSelectPopup]);
            handles.dd = set(handles.dd,'DropHandles',[handles.axes(1) handles.AddTimeVectorsFrame]);
            
            
        else
            % Get original time list
            val = get(handles.TimeSelectPopup,'Value');
            oldtimes = get(handles.TimeSelectPopup,'String'); 
            oldtimes = localRemoveLengthFromParms(oldtimes);
            selectedtime = oldtimes{val};
        end;
        
        % Get new time vectors from parameter list
        val = get(drag,'Value');
        parms = get(drag,'String'); 
        
        % Strip lengths off of parms
        parms = localRemoveLengthFromParms(parms);
        
        newtimes = parms(val);             %Name of parameters
        
        % Build unique intersection of the lists.
        times = unique([oldtimes;newtimes]);
        
        % Remove from parameter list
        ind = 1:length(parms);
        keepind = setdiff(ind,val);
        parms = parms(keepind);
        
        % Update parameter list
        set(handles.listbox1,'Value',1);
        parms = localAddLengthToParms(parms);
        set(handles.listbox1,'String',parms);
        
        % Update list of time vectors and Select the new time vector 
        % (first if multiple added)
        val = find(strcmp(newtimes{1},times));
        times = localAddLengthToParms(times);
        set(handles.TimeSelectPopup,'String',times);
        set(handles.TimeSelectPopup,'Value',val);
        
        % Set the axis limits to the max range of all time vectors
        tlim = localGetAxesLimits(handles);
        set(handles.axes,'XLim',tlim);
        set(handles.axes,'XTick',[tlim(1) mean(tlim) tlim(2)]);
        
    case 'axes'         % Drag and drop plotting
        % Switch between valid drag sources: 1) Parameter list. 2) another axes
        switch get(drag,'Type')
            case 'uicontrol'        % Parameter List
                val = get(drag,'Value');
                strng = get(drag,'String'); 
                parms = strng(val);             %Name of parameters
                
                % Strip lengths off of parms
                parms = localRemoveLengthFromParms(parms);
                
                set(handles.figure1,'CurrentAxes',drop);
                
                % First time only:
                % * Enable some controls
                % * Turn off text directions covering the axes
                % * Change the axes color
                if strcmp(get(handles.DirectionsText,'Visible'),'on');
                    % Enable other controls
                    list = [handles.ZoomButton handles.CursorButton handles.DataLabelButton ...
                            handles.NoAxesCombo handles.NoAxesText];
                    set(list,'Enable','on');
                    
                    set(handles.DirectionsText,'Visible','off');
                    % Give axes normal colors
                    set(handles.axes,'Color','w','XColor','k','YColor','k')
                end;
                
                % Get list of parameters already plotted
                oldparms = getappdata(drop,'Parameters');
                
                % New parameters
                newparms = setdiff(parms,oldparms);
                
                % Each parameter could have multiple columns.  Need to
                % account for all of them.
                %                 nLines = 0;
                %                 for ii=1:length(newparms)
                %                     [nr,nc] = evalin('base',['size(' newparms{ii} ')']);
                %                     if nr<nc, % Force into columns
                %                         newparms{ii} = newparms{ii}'; 
                %                         [nr,nc] = size(newparms{ii});
                %                     end 
                %                     nLines = nLines = nc;
                %                 end;
                
                % Initialize array of line handles
                lh = [];
                
                % Color picking.  This is flawed, but good enough for now.
                colors = get(0,'defaultAxesColorOrder');
                cind = length(oldparms) + 1; nc = length(colors);  %Number of colors
                    cind = rem(cind,nc);    % limit to 1..nc
                    if cind==0, cind=size(colors,1); end;
                
                % Get time basis
                time = localGetCurrentTime(handles);
                
                % Store list of parameters that are actually plotted.  Any
                % parameters that aren't the same length as the time basis
                % will be removed
                newparms_keep = {};
                keepers = 0;
                for ii=1:length(newparms)
                    data = evalin('base',newparms{ii});
                    
                    % Don't plot if this variable is not defined on
                    % the current time.  Instead, display a NO
                    % cursor
                    if length(data) ~= length(time)
                        ptr = get(handles.figure1,'Pointer');
                        set(handles.figure1,'Pointer','custom');
                        set(handles.figure1,'PointerShapeCData',no_icon,'PointerShapeHotSpot',[9 9]);
                        pause(.2)
                        set(handles.figure1,'Pointer',ptr);
                        
                        continue    % Go to next iteration
                    end;
                    
                    % Handle
                    lh = [lh line(time, data, ...
                        'Parent',drop, ...
                        'Color',colors(cind,:))];
                    
                    % Add to list of parameters we actually plotted
                    keepers = keepers+1;
                    newparms_keep{keepers,1} = newparms{ii};
                    
                    %Cycle through colors
                    cind = rem(cind+1,nc);
                    if cind==0, cind=size(colors,1); end;
                end;
                
                % Build list of all parameters plotted on this axes.
                parms = unique([oldparms;newparms_keep]);
                
                % Store tags. Skip if didn't add any parameters
                if any(lh)
                    set(lh,{'Tag'},newparms_keep);                  %Store names in lines
                end;
                %     plot(handles.timeNumVec, handles.rawdata(:,val),'Parent',drop)
                setappdata(drop,'Parameters',parms);    %Store this so that we can restore legend
                localUpdateLegend(drop);
                
                
                %If datalabels are on, update them
                if get(handles.DataLabelButton,'Value')
                    datalabel('update');
                end;
                
                % Add a context menu to each line
                cmenu = uicontextmenu('Parent',handles.figure1);
                set(lh,'UIContextMenu',cmenu);
                
                % Define the context menu items
                %Label Max and Min
                item1 = uimenu(cmenu, 'Label', 'Label Max and Min', ...
                    'Callback', @localContextMenuCallback,'Tag','MaxMin');
                
                %Label mean
                item1 = uimenu(cmenu, 'Label', 'Label Mean', ...
                    'Callback', @localContextMenuCallback,'Tag','Mean');
                
                %Plot derivative
                item1 = uimenu(cmenu, 'Label', 'Plot derivative', ...
                    'Callback', @localContextMenuCallback,'Tag','Derivative');
                
                %Find Value
                item1 = uimenu(cmenu, 'Label', 'Find value', ...
                    'Callback', @localContextMenuCallback,'Tag','FindValue');
                
                %Delete this line
                item1 = uimenu(cmenu, 'Label', 'Delete', ...
                    'Callback', @localDeleteObject,'Separator','on');
                
            case 'axes'
                % Do nothing if dropping axes on itself
                if drag==drop
                    return
                end;
                
                % Get all children of drag axes
                dragkids = get(drag,'Children');
                dragmenus = get(dragkids,'UIContextMenu');
                if ~iscell(dragmenus), dragmenus = {dragmenus};end;
                if iscell(dragkids)
                    dragkids = cell2mat(dragkids);
                end;
                
                % Get all children of drop axes
                dropkids = get(drop,'Children');
                dropmenus = get(dropkids,'UIContextMenu');
                if iscell(dropkids)
                    dropkids = cell2mat(dropkids);
                end;
                if ~iscell(dropmenus), dropmenus = {dropmenus};end;
                
                % Swap children
                hgS_drag = handle2struct(dragkids);
                hgS_drop = handle2struct(dropkids);
                
                % Delete kids
                delete(dragkids)
                delete(dropkids)
                
                % Add children to axes
                newdropkids = struct2handle(hgS_drag,drop);
                set(newdropkids,{'UIContextMenu'},dragmenus)
                
                newdragkids = struct2handle(hgS_drop,drag);
                set(newdragkids,{'UIContextMenu'},dropmenus)
                
                
                % Update parameter list of axes
                dragparms = getappdata(drag,'Parameters');
                dropparms = getappdata(drop,'Parameters');
                setappdata(drop,'Parameters',dragparms);
                parms = getappdata(drop,'Parameters');
                setappdata(drag,'Parameters',dropparms);
                
                % Update legend on drop axes
                localUpdateLegend(drop)
                localUpdateLegend(drag)
                
            end;
    end;
    
    
    
    
    % --- Executes during object creation, after setting all properties.
    function NoAxesEdit_CreateFcn(hObject, eventdata, handles)
    % hObject    handle to NoAxesEdit (see GCBO)
    % eventdata  reserved - to be defined in a future version of MATLAB
    % handles    empty - handles not created until after all CreateFcns called
    
    % Hint: edit controls usually have a white background on Windows.
    %       See ISPC and COMPUTER.
    if ispc
        set(hObject,'BackgroundColor','white');
    else
        set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
    end
    
    
    
    function NoAxesEdit_Callback(hObject, eventdata, handles)
    % hObject    handle to NoAxesEdit (see GCBO)
    % eventdata  reserved - to be defined in a future version of MATLAB
    % handles    structure with handles and user data (see GUIDATA)
    
    % Hints: get(hObject,'String') returns contents of NoAxesEdit as text
    %        str2double(get(hObject,'String')) returns contents of NoAxesEdit as a double
    
    % Adjust the number of visible axes
    
    % Error check - must be number between 1 and 4
    % --- Executes during object creation, after setting all properties.
    function NoAxesCombo_CreateFcn(hObject, eventdata, handles)
    % hObject    handle to NoAxesCombo (see GCBO)
    % eventdata  reserved - to be defined in a future version of MATLAB
    % handles    empty - handles not created until after all CreateFcns called
    
    % Hint: slider controls usually have a light gray background, change
    %       'usewhitebg' to 0 to use default.  See ISPC and COMPUTER.
    usewhitebg = 1;
    
    % Set slider to gray, edit box to white
    switch get(hObject,'style') 
        case 'slider'
            if usewhitebg
                set(hObject,'BackgroundColor',[.9 .9 .9]);
            else
                set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
            end
        case 'edit'
            set(hObject,'BackgroundColor',[1 1 1]);
    end;
    
    
    % --- Executes on slider movement.
    function NoAxesCombo_Callback(hObject, eventdata, handles)
    % hObject    handle to NoAxesCombo (see GCBO)
    % eventdata  reserved - to be defined in a future version of MATLAB
    % handles    structure with handles and user data (see GUIDATA)
    
    % Hints: get(hObject,'Value') returns position of slider
    %        get(hObject,'Min') and get(hObject,'Max') to determine range of slider
    
    %I've created my own combobox - combining an edit box and a slider.  I gave
    %them both the same handle so that they would share a callback
    
    
    sl = handles.NoAxesCombo(1);        %Slider handle
    ed = handles.NoAxesCombo(2);        %Edit handle
    
    if hObject==sl      %Slider
        NoAx = round(get(sl,'Value'));
        set(ed,'String',num2str(NoAx));
        
    else                %Edit
        NoAx = str2num(get(hObject,'String'));
        
        if isempty(NoAx)
            NoAx=1;
            set(hObject,'String','1');
        end;
        
        NoAx = round(NoAx);
        if NoAx<1
            NoAx = 1;
            set(hObject,'String','1');
        elseif NoAx>4
            NoAx = 4;
            set(hObject,'String','4');
        end;    
    end;
    
    % Set the selected number of axes visible
    ax = handles.axes;      %Handles to axes
    
    set(ax(1:NoAx),'Visible','on',{'Position'},handles.axpos{NoAx});         %First NoAx are visible
    set(ax(NoAx+1:end),'Visible','off');    %The rest (if any) are not
    
    % Show XTicks on bottom axes only
%     set(ax(1:NoAx-1),'XTick',[]);
    localZoomCallback(handles.figure1);
    
    % Set the children of only the visible axes to be visible
    showkids = get(ax(1:NoAx),'Children');
    if iscell(showkids)
        showkids = cell2mat(showkids);
    end;
    hidekids = get(ax(NoAx+1:end),'Children');
    if iscell(hidekids)
        hidekids = cell2mat(hidekids);
    end;
    
    set(showkids,'visible','on');
    set(hidekids,'visible','off');
    
    % Reset the legends
    for ii=1:4
        legend(ax(ii),'off');
    end;
    
    for ii=1:NoAx
        if isappdata(ax(ii),'Parameters');
            parms = getappdata(ax(ii),'Parameters');
            if ~isempty(parms)
                legend(ax(ii),parms)
            end;
        end;
    end;
    
    % Reset the dragndrop targets to just the visible axes.  This will also
    % update the positions.
%     handles.dd = set(handles.dd,'DropHandles',[ax(1:NoAx) handles.TimeSelectPopup]);
    handles.dd = set(handles.dd,'DropHandles',[ax(1:NoAx) handles.AddTimeVectorsFrame]);
    
    guidata(handles.figure1,handles);
    % Set the positions
    
    % 
    % %Some fun and games to get a decent array of handles to children of each
    % %axes
    % ax1kids = get(ax1,'Children');
    % ax1kids = ax1kids';
    % ax2kids = get(ax2,'Children');ax2kids = cell2mat(ax2kids)';
    % ax3kids = get(ax3,'Children');ax3kids = cell2mat(ax3kids)';
    % ax4kids = get(ax4,'Children');ax4kids = cell2mat(ax4kids)';
    % 
    % %Delete all legends.  Add a new one when axes become visible
    % delete(findobj(handles.figure1,'Type','Axes','Tag','legend'));
    % 
    % if isempty(ax1kids)
    %     ax1kids = [];
    % end;
    % if isempty(ax2kids)
    %     ax2kids = [];
    % end;
    % if isempty(ax3kids)
    %     ax3kids = [];
    % end;
    % if isempty(ax4kids)
    %     ax4kids = [];
    % end;
    % 
    % 
    % switch NoAx
    %     case 1
    %         set([ax1 ax1kids],'Visible','on');
    %         set([ax2 ax3 ax4 ax2kids ax3kids ax4kids],'Visible','off');
    %         %         legend([ax2 ax3 ax4],'hide');
    %         %         legend(ax1,'show')
    %         legend(ax1,getappdata(ax1,'Parameters'))
    %     case 2
    %         set([ax2 ax2kids],'Visible','on');
    %         set([ax1 ax3 ax4 ax1kids ax3kids ax4kids],'Visible','off');
    %         %         legend([ax1 ax3 ax4],'hide');
    %         %         legend(ax2,'show')
    %         for ii=1:2
    %             if isappdata(ax2(ii),'Parameters');
    %                 legend(ax2(ii),getappdata(ax2(ii),'Parameters'))
    %             end;
    %         end;
    %     case 3
    %         set([ax3 ax3kids],'Visible','on');
    %         set([ax1 ax2 ax4 ax1kids ax2kids ax4kids],'Visible','off');
    %         %         legend([ax1 ax2 ax4],'hide');
    %         %         legend(ax3,'show')
    %         for ii=1:3
    %             if isappdata(ax3(ii),'Parameters');
    %                 legend(ax3(ii),getappdata(ax3(ii),'Parameters'))
    %             end;
    %         end;
    %     case 4
    %         set([ax4 ax4kids],'Visible','on');
    %         set([ax1 ax2 ax3 ax1kids ax2kids ax3kids],'Visible','off');
    % %         legend([ax1 ax2 ax3],'hide');
    % %         legend(ax4,'show')
    %         for ii=1:4
    %             if isappdata(ax4(ii),'Parameters');
    %                 legend(ax4(ii),getappdata(ax4(ii),'Parameters'))
    %             end;
    %         end;
    % end;
    % 
    %         
    
    
    
    
    % --- Executes on button press in ZoomButton.
    function ZoomButton_Callback(hObject, eventdata, handles)
    % hObject    handle to ZoomButton (see GCBO)
    % eventdata  reserved - to be defined in a future version of MATLAB
    % handles    structure with handles and user data (see GUIDATA)
    
    val = get(hObject,'Value');
    if val
        %Turn off datalabels
        set(handles.DataLabelButton,'Value',0);
        datalabel off
        
        %Turn off cursors
        set(handles.CursorButton,'Value',0)
        eventlabel off
        
        %Turn on zoom
        linkedzoom(handles.axes,'onx',{@localZoomCallback,handles.figure1});
        
        % Reset legends - they get hidden by linkedzoom
        for ii=1:4
            localUpdateLegend(handles.axes(ii));
        end;
        
        
    else
        % Turn off zoom
        linkedzoom off
        
        % Reset axis limits
        localTurnOffZoom(handles);
        
    end;
    
    
    
    % --- Executes on button press in DataLabelButton.
    function DataLabelButton_Callback(hObject, eventdata, handles)
    % hObject    handle to DataLabelButton (see GCBO)
    % eventdata  reserved - to be defined in a future version of MATLAB
    % handles    structure with handles and user data (see GUIDATA)
    
    val = get(hObject,'Value');
    if val
        %Turn off zoom
        set(handles.ZoomButton,'Value',0);
        linkedzoom off
        
        % Reset axis limits
        localTurnOffZoom(handles);
                
        %Turn off event labels
        set(handles.CursorButton,'Value',0)
        eventlabel off
        
        %Turn on datalabels
        datalabel on
        
    else
        datalabel off
    end;
    
    
    
    % --- Executes on button press in CursorButton.
    function CursorButton_Callback(hObject, eventdata, handles)
    % hObject    handle to CursorButton (see GCBO)
    % eventdata  reserved - to be defined in a future version of MATLAB
    % handles    structure with handles and user data (see GUIDATA)
    
    % Hint: get(hObject,'Value') returns toggle state of CursorButton
    
    val = get(hObject,'Value');
    if val
        %Turn off datalabels
        set(handles.DataLabelButton,'Value',0);
        datalabel off
        
        % Reset axis limits
        localTurnOffZoom(handles);
                
        %Turn off zoom
        set(handles.ZoomButton,'Value',0)
        linkedzoom off
        
        %Turn on cursors
        eventlabel
        
    else
        eventlabel off
    end;
    
    function localContextMenuCallback(hObject,eventdata);
    % Callback function for ContextMenu on lines
    fn = get(hObject,'Tag');
    handles = guidata(hObject);
    
    hLine = gco;        %Selected line
    xd = get(hLine,'XData');
    yd = get(hLine,'YData');
    parm = get(hLine,'Tag');
    hAx = get(hLine,'Parent');   %Axes handle
    
    switch fn
        case 'MaxMin'   %Compute and display max and min values
            % Label Max and Min of selected parameter
            % Compute max&min
            [ymax,maxind] = max(yd);
            [ymin,minind] = min(yd);
            
            xmax = xd(maxind);
            xmin = xd(minind);
            
            %Add text
            th(1) = text(xmax,ymax,{parm;['x_{max} = ' num2str(xmax)];['y_{max} = ' num2str(ymax)]});
            th(2) = text(xmin,ymin,{parm;['x_{min} = ' num2str(xmin)];['y_{min} = ' num2str(ymin)]});
            set(th(1),'VerticalAlignment','top');
            set(th(2),'VerticalAlignment','bottom');
            
            %Add marker, too
            lh(1) = line(xmax,ymax,'Color','k','Marker','o','MarkerFaceColor',get(hLine,'Color'),'MarkerSize',4);
            lh(2) = line(xmin,ymin,'Color','k','Marker','o','MarkerFaceColor',get(hLine,'Color'),'MarkerSize',4);
            
            setappdata(th(1),'h',lh(1));
            setappdata(th(2),'h',lh(2));
            setappdata(lh(1),'h',th(1));
            setappdata(lh(2),'h',th(2));
            
            %Right click marker or text to delete
            cmenu = uicontextmenu('Parent',handles.figure1);
            set([lh th],'UIContextMenu',cmenu);
            
            % Define the context menu items
            item1 = uimenu(cmenu, 'Label', 'Delete', ...
                'Callback', 'h=getappdata(gco,''h'');delete(h);delete(gco)');
            set(th,'BackgroundColor',localLighten(get(hLine,'Color')),'FontSize',8);
            set(th,'ButtonDownFcn','dragtext(gco)');
            
        case 'Mean'     %Compute and display mean value
            % Label Mean value of selected parameter
            
            % Compute mean
            ymn = mean(yd);
            
            
            % Add text.  Place it just to the right of the axis.
            xl = xlim(get(hLine,'Parent'));
            x = xl(2) - .05*diff(xl);
            th = text(x,ymn,{[parm ': mean = ' num2str(ymn)]});
            set(th,'VerticalAlignment','middle');
            
            % Add a line along the mean, too
            hMeanLine = line(xd,ymn*ones(1,length(xd)), ...
                'Color',localLighten(get(hLine,'Color')), ...
                'LineStyle', '-.');
            
            setappdata(th,'h',hMeanLine);
            setappdata(hMeanLine,'h',th);        
            
            %Right click text to delete
            cmenu = uicontextmenu('Parent',handles.figure1);
            set([th hMeanLine],'UIContextMenu',cmenu);
            
            % Define the context menu items
            item1 = uimenu(cmenu, 'Label', 'Delete', ...
                'Callback', 'h=getappdata(gco,''h'');delete(h);delete(gco)');
            set(th,'BackgroundColor',localLighten(get(hLine,'Color')),'FontSize',8);
            set(th,'ButtonDownFcn','dragtext(gco)');
            
        case 'Derivative'       %Plot the normalized derivative
            d = diff(yd);
            
            ymin = min(yd);     %We'll normalize to the original data
            ymax = max(yd);
            yl = [ymin ymax];
            
            dmn = min(d);
            dmx = max(d);
            
            dn = yl(1) + (d-dmn)*(diff(yl)/(dmx-dmn));   %Normalized to same scale as y
            dt = mean(diff(xd));        %Approximate dt
            dtime = xd(1:end-1)+.5*dt;  %Approximate time
            % Compute color for new line - same color, but lighter!
            color = get(hLine,'Color');
            color = localLighten(color);
            
            lh = line(dtime, dn,'Color',color);
            %         lh = patch([dtime NaN],[dn NaN],'k', ...
            %             'FaceColor','n', ...
            %             'EdgeColor',get(hLine,'Color'), ...
            %             'EdgeAlpha',.3);
            %         %Use patch instead of line, so that we can make it faint
            set(lh,'Tag',['d' parm]);
            
            %Right click line to delete
            cmenu = uicontextmenu('Parent',handles.figure1);
            set(lh,'UIContextMenu',cmenu);
            
            % Define the context menu items
            item1 = uimenu(cmenu, 'Label', 'Delete', ...
                'Callback', @localDeleteObject);
            
            % Update legend
            parms = getappdata(hAx,'Parameters');    %Store this so that we can restore legend        
            parms{end+1} = ['d' parm];
            setappdata(hAx,'Parameters',parms);
            legend(hAx,parms)
            
        case 'FindValue'        %Find a specified value
            % Create a simple dialog
            h = localCreateFindValueGUI([],[],'init',parm,handles);
            waitfor(h,'Tag');       %We change the tag when clicking apply button
            
            % Get updated handles structure
            handles = guidata(hObject);
            
            %Overlay conditional on plot
            values = handles.data.(parm).conditional.values;
            time   = handles.data.(parm).conditional.time;
            
            % Check if anything was found
            if all(isnan(values))
                msgbox('No values found','','modal');
                return
            end;
            
            % If only a few values, plot a marker
            if length(values)<=15 
                Marker = '*';
            else
                Marker = 'none';
            end;
            
            % Use same color as existing line, just a little thicker
            c = get(hLine,'Color');
            lh = line(time, values, ...
                'Parent',hAx, ...
                'Color',c, ...
                'LineWidth',3, ...
                'Marker',Marker, ...
                'Tag',handles.data.(parm).conditional.equation);
            
            parms = getappdata(hAx,'Parameters');
            parms{end+1} = handles.data.(parm).conditional.equation;
            
            setappdata(hAx,'Parameters',parms);
            
            % Add a context menu to delete
            cmenu = uicontextmenu('Parent',handles.figure1);
            set(lh,'UIContextMenu',cmenu);
            
            % Define the context menu items
            item1 = uimenu(cmenu, 'Label', 'Delete', ...
                'Callback', @localDeleteObject);
            
            % Update the legend.
            localUpdateLegend(hAx)
            
            
            
    end;
    
    
    
    
    
    % --------------------------------------------------------------------
    function Untitled_1_Callback(hObject, eventdata, handles)
    % hObject    handle to Untitled_1 (see GCBO)
    % eventdata  reserved - to be defined in a future version of MATLAB
    % handles    structure with handles and user data (see GUIDATA)
    
    % Unused callback for File menu (top level)
    % Do not delete
    
    function localZoomCallback(hFigure);
    % Callback for zoom action. 
    % Keep ticks at first, center, last
    % This is called by linkedzoom after each zoom update.
    
    % Get handles
    handles = guidata(hFigure); 
    
    % Get the axis limits
    noax = str2num(get(handles.NoAxesCombo(2),'String'));
    ax = handles.axes(noax);
    tlim = xlim(ax);
    
    % Set the ticks on last axes, hide on others
    NoAx = str2num(get(handles.NoAxesCombo(2),'String'));
    set(handles.axes(NoAx),'XTick',[tlim(1) mean(tlim([1 end])) tlim(end)]);
    set(handles.axes(1:NoAx-1),'XTick',[]);
    
    function localExportAxes(hObject,eventdata);
    % Callback for axes context menu item to export the axes (to a new
    % figure)
    
    % Clone the current axes
    hgS = handle2struct(gco);
    
    figure;
    ax = axes;
    struct2handle(hgS,ax);
    
    function localClearAxes(hObject,eventdata);
    % handle 2 input cases.
    switch get(hObject,'type')
        case 'axes'         % Internal call to clear axes
            h = hObject;  
        case 'uimenu'       % Context menu select clear
            h = gco;
    end;    
    
    % Callback for axes context menu item to clear the axes
    kids = get(h,'Children');     % Handle to children
    fig = get(h,'Parent');        % Figure handle
    
    if ~isempty(kids)               % Don't bother if there's nothing to delete
        localDeleteObject(kids,[],1);   % Third argument says delete all kids
    end;
    
    
    %     for ii=1:length(kids)
    %         set(fig,'CurrentObject',kids(ii));  % Make this child current (necessary for localDeleteObject)
    %         localDeleteObject(kids(ii),[]);
    %     end;
    
    function localDeleteObject(hObject,eventdata,deleteall);
    % Callback for context menu item to delete an object
    % Third input argument is an option for internal calls which tells
    % localDeleteObject that it is deleting all of the objects on an axes.
    % This provides speed benefits.  deleteall = 1 (true) or 0 (false).
    % You must still pass the handles to all objects you want to delete
    
    if nargin<3             % Default
        deleteall = 0;  
    end;
    
    % handle 2 input cases.
    switch get(hObject(1),'type')
        case 'uimenu'       % Context menu select clear
            h = gco;        % The selected line
        otherwise 
            h = hObject;  
    end;    
    
    % Delete an object and update the legend
    hAx = get(h(1),'Parent');       %Axes handle
    %     hAx = get(gco,'Parent');       %Axes handle
    handles = guidata(hObject(1));  % All handles
    parms = getappdata(hAx,'Parameters');    %Store this so that we can restore legend
    
    if deleteall
        % Remove parameters from list
        parmsnew = {};
        setappdata(hAx,'Parameters',parmsnew);
        
        % Delete objects
        delete(h)
        
        % Update legend
        localUpdateLegend(hAx)
        return
    end;
    
    
    
    %Remove from appdata
    thisparm = get(h,'Tag');
    %     thisparm = get(gco,'Tag');
    ind = strmatch(thisparm,parms);
    
    parmsnew = cell(length(parms)-1,1);
    for ii=1:length(parms)
        if ii<ind
            parmsnew{ii} = parms{ii};
        elseif ii>ind
            parmsnew{ii-1} = parms{ii};
        end;
    end;
    
    setappdata(hAx,'Parameters',parmsnew);
    
    % Delete line
    delete(h)
    %     delete(gco)
    h = flipud(findobj(hAx,'Type','Line'));
    % Update legend
    % if length(parmsnew)>0
    localUpdateLegend(hAx)
    % end;
    
    function hFigureFV = localCreateFindValueGUI(hObject,eventdata,action,parm,mainhandles);
    
    switch action
        case 'init' %Initialize
            hFigureFV = figure('Position',[300 300 150 80], ...
                'MenuBar','none','NumberTitle','off','Name','Find Values', ...
                'Visible','off','HandleVisibility','Callback');%, ...
            %            'CloseRequestFcn',{@localCreateFindValueGUI,'close',[],mainhandles});
            %             'WindowStyle','modal');
            
            movegui(hFigureFV,'center');
            set(hFigureFV,'Visible','on');
            
            hParm = uicontrol(hFigureFV, ...            % Parameter text string
                'Position',[10 50 40 17], ...
                'Style','text', ...
                'String',parm, ...
                'BackgroundColor',get(0,'defaultFigureColor'), ...
                'Tag','Parm');
            hOperator = uicontrol(hFigureFV, ...        % Operator menu
                'Position',[55 50 40 20], ...
                'Style','Popupmenu', ...
                'String',{'==';'<';'>';'<=';'>='}, ...
                'BackgroundColor','white', ...
                'Tag','Operator');        
            hValue = uicontrol(hFigureFV, ...           % Value edit box
                'Position',[100 50 40 20], ...
                'Style','Edit', ...
                'String','', ...
                'BackgroundColor','white', ...
                'Tag','Value');   
            hApply = uicontrol(hFigureFV, ...           % Apply button
                'Position',[25 10 40 20], ...
                'Style','Pushbutton', ...
                'String','Apply', ...
                'Callback',{@localCreateFindValueGUI,'apply',[],mainhandles});   
            hClose = uicontrol(hFigureFV, ...           % Close button
                'Position',[85 10 40 20], ...
                'Style','Pushbutton', ...
                'String','Close', ...
                'Callback',{@localCreateFindValueGUI,'close',[],mainhandles});   
            
            handles = guihandles(hFigureFV);
            guidata(hFigureFV,handles)
            
            
            
        case 'apply'
            handles= guidata(hObject);
            
            parm = get(handles.Parm,'String');
            str = get(handles.Operator,'String');
            opind = get(handles.Operator,'Value');
            operator = str{opind};
            
            value = str2num(get(handles.Value,'String'));
            
            t = mainhandles.data.(parm).time;
            v = mainhandles.data.(parm).values;
            
            a = feval(operator,v,value);
            
            %Time and Value for which the condition is met.
            tfind = t;  tfind(~a) = NaN;
            vfind = v;  vfind(~a) = NaN;
            
            mainhandles.data.(parm).conditional.time = tfind;
            mainhandles.data.(parm).conditional.values = vfind;
            mainhandles.data.(parm).conditional.equation = [parm ' ' operator ' ' num2str(value)];
            
            % Update guidata for main application
            guidata(mainhandles.figure1,mainhandles);
            
            % Change the tag.  This indicates to the caller that something has
            % happened (it ends a waitfor condition)
            set(get(handles.Parm,'Parent'),'Tag',num2str(rand));
            
            
        case 'close'
            %         localCreateFindValueGUI(hObject,eventdata,'apply');
            delete(get(hObject,'Parent'));
            
    end;
    
    function localUpdateLegend(hAx)
    % Update the legend on axes hAx
    % Use the parameter list as the legend strings
    
    parms = getappdata(hAx,'Parameters');
    if ~isempty(parms)
        hLeg = legend(hAx,parms);
    else
        legend(hAx,'off');      %Turn off if plot is empty
    end;    
    
    
    
    % --- Executes during object creation, after setting all properties.
    function DerivedParametersListBox_CreateFcn(hObject, eventdata, handles)
    % hObject    handle to DerivedParametersListBox (see GCBO)
    % eventdata  reserved - to be defined in a future version of MATLAB
    % handles    empty - handles not created until after all CreateFcns called
    
    % Hint: listbox controls usually have a white background on Windows.
    %       See ISPC and COMPUTER.
    if ispc
        set(hObject,'BackgroundColor','white');
    else
        set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
    end
    
    
    % --- Executes on selection change in DerivedParametersListBox.
    function DerivedParametersListBox_Callback(hObject, eventdata, handles)
    % hObject    handle to DerivedParametersListBox (see GCBO)
    % eventdata  reserved - to be defined in a future version of MATLAB
    % handles    structure with handles and user data (see GUIDATA)
    
    % Hints: contents = get(hObject,'String') returns DerivedParametersListBox contents as cell array
    %        contents{get(hObject,'Value')} returns selected item from DerivedParametersListBox
    
    
    % --- Executes on button press in CreateDerivedButton.
    function CreateDerivedButton_Callback(hObject, eventdata, handles)
    % hObject    handle to CreateDerivedButton (see GCBO)
    % eventdata  reserved - to be defined in a future version of MATLAB
    % handles    structure with handles and user data (see GUIDATA)
    
    % Open a generic edit box to let user type in equation
    
    eqn  = inputdlg('Enter equation, using names from parameter list (ALL CAPS)', ...
        'Create Derived Parameter');
    if isempty(eqn), return, end;
    eqn = eqn{1};       %Break out of cell
    
    % To just evaluate eqn, we need to define individual variables for each parameter.
    % The problem is that each parameter is on a unique time basis.  To get
    % around this, we have stored a field interpvalues in each parameter.  This
    % field contains the data interpolated to a common time basis.  This is
    % done by readsparsecsv.
    parmlist = fieldnames(handles.data);
    
    for ii=1:length(parmlist);
        name = parmlist{ii};
        assignhere(name,handles.data.(name).interpvalues);
    end;
    
    answer = eval(eqn);
    
    % Store results in a cell array within handles
    derivedparameters = handles.derivedparameters;
    new.equation = eqn;
    new.values = answer;
    % Don't need to store time - use handles.commontime
    
    % Add to derived parameter list
    str = get(handles.DerivedParametersListBox,'String');
    str{end+1} = eqn;
    set(handles.DerivedParametersListBox,'String',str);
    
    % Update handles structure
    if isempty(derivedparameters)   %First time only
        handles.derivedparameters = {new};
    else
        handles.derivedparameters = {derivedparameters; new};
    end;
    
    % Alternate approach:
    % Just add derived parameters to bottom of regular parameter list.  One
    % problem, though - the parameter display is not a valid MATLAB variable
    % (or field name).
    
    guidata(hObject, handles);
    
    
    
    
    
    
    function localParameterContextMenuCallback(hObject,eventdata);
    % Callback function for ContextMenu on lines
    fn = get(hObject,'Tag');
    handles = guidata(hObject);
    
    % Get selected parameters
    vals = get(gco,'Value');
    parmlist = get(gco,'String');
    parms = parmlist(vals);
    
    hLine = gco;        %Selected line
    xd = get(hLine,'XData');
    yd = get(hLine,'YData');
    parm = get(hLine,'Tag');
    hAx = get(hLine,'Parent');   %Axes handle
    
    % switch fn
    
    
    % --------------------------------------------------------------------
    function Untitled_2_Callback(hObject, eventdata, handles)
    % hObject    handle to Untitled_2 (see GCBO)
    % eventdata  reserved - to be defined in a future version of MATLAB
    % handles    structure with handles and user data (see GUIDATA)
    
    
    function color = localLighten(color)
    % Create a lighter version of a color
    chsv = rgb2hsv(color);
    chsv(2) = .25;     %Reduce luminescence value
    color = hsv2rgb(chsv);
        
    % --------------------------------------------------------------------
    % --------------------------------------------------------------------
    function HelpMain_Callback(hObject, eventdata, handles)
    % hObject    handle to HelpMain (see GCBO)
    % eventdata  reserved - to be defined in a future version of MATLAB
    % handles    structure with handles and user data (see GUIDATA)
    
    
    % --------------------------------------------------------------------
    function HelpMenu_Callback(hObject, eventdata, handles)
    % hObject    handle to HelpMenu (see GCBO)
    % eventdata  reserved - to be defined in a future version of MATLAB
    % handles    structure with handles and user data (see GUIDATA)
    
    thisdir = which(mfilename);
    thisdir = fileparts(thisdir);
    web([thisdir filesep 'private' filesep 'timeseriesviewer_help.html'])
    
    
    % --- Executes during object creation, after setting all properties.
    function TimeSelectPopup_CreateFcn(hObject, eventdata, handles)
    % hObject    handle to TimeSelectPopup (see GCBO)
    % eventdata  reserved - to be defined in a future version of MATLAB
    % handles    empty - handles not created until after all CreateFcns called
    
    % Hint: popupmenu controls usually have a white background on Windows.
    %       See ISPC and COMPUTER.
    if ispc
        set(hObject,'BackgroundColor','white');
    else
        set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
    end
    
    
    % --- Executes on selection change in TimeSelectPopup.
    function TimeSelectPopup_Callback(hObject, eventdata, handles)
    % Update the axes limits to reflect new time
    
    % time = localGetCurrentTime(handles);
    % set(handles.axes,'XLim',[time(1) time(end)]);
    % set(handles.axes,'XTick',[time(1) mean(time([1 end])) time(end)]);
    
    
    function localUpdateParmlist(varargin)
    if nargin==1
        handles = varargin{1};
    else
        handles = guidata(varargin{1});
    end;
    
    % Updates the listbox to match the current workspace
    vars = evalin('base','who');
    
    % Find candidate variables
    series = localFindSeries;
    
    if isempty(series)      % No valid candidates.  Demo mode
        disp('You have no valid time series in your workspace.  Running in demo mode');
        time1 = 0:.001:1;
        parm1a = sin(4*pi*time1);
        parm1b = rand(size(time1));
        time2 = 0:.035:1.25;
        parm2a = cos(pi*time2);
        parm2b = rand(size(time2));
        
        assignin('base','time1',time1);
        assignin('base','time2',time2);
        assignin('base','parm1a',parm1a);
        assignin('base','parm1b',parm1b);
        assignin('base','parm2a',parm2a);
        assignin('base','parm2b',parm2b);
        
        series = localFindSeries;
    end;
    
    
    % Exclude defined time parameters
    times = get(handles.TimeSelectPopup,'String');
    keepers = ~ismember(series,times);
    series = series(keepers);
    
    
    set(handles.listbox1,'String',series)
    
    
    function series = localFindSeries
    % Find potential series (eligible variables for this application)
    
    vars = evalin('base','whos');
    
    % Keep only 2D numeric real arrays with one singleton dimension (row or
    % column vectors; no matrices)
    series={};
    nkeep = 0;
    foundmatrices = 0;
    for ii=1:length(vars)
        
        % Must be numeric
        if isnumeric(evalin('base',[vars(ii).name]))
            if prod(vars(ii).size)>1    % Not a scalar. Keep going
                % If there is no singleton dimension, make a note and move
                % on.
                if ( vars(ii).size(1)~=1 & vars(ii).size(2)~=1)
                    foundmatrices = 1;
                else
                    nkeep = nkeep + 1;
                    %                     series{nkeep} = vars(ii).name;
                    series{nkeep,1} = [vars(ii).name '  (' num2str(max(vars(ii).size)) ')'];
                end;
            end;
        end;
    end;
    
    if foundmatrices
        warndlg([upper(mfilename) ' only supports row and column vectors. ' ...
                'Please split matrices into multiple variables.']);
    end;
    
    
    % --- Executes on button press in UpdateParametersButton.
    function UpdateParametersButton_Callback(hObject, eventdata, handles)
    % hObject    handle to UpdateParametersButton (see GCBO)
    % eventdata  reserved - to be defined in a future version of MATLAB
    % handles    structure with handles and user data (see GUIDATA)
    localUpdateParmlist(handles)
    
    
    function time = localGetCurrentTime(handles);
    % Return vector of currently selected time
    timeslist = get(handles.TimeSelectPopup,'String');
    timeslist = localRemoveLengthFromParms(timeslist);
    timesind = get(handles.TimeSelectPopup,'Value');
    timestr = timeslist{timesind};
    time = evalin('base',timestr);
    
    function P = no_icon;
    % Create icon for mouse pointer indicating target isn't valid
    P=[ 2     2     2     2     2     2     2     2     2     2     2     2     2     2     2     2
        2     2     2     2     2     2     2     2     2     2     2     2     2     2     2     2
        2     2     2     2     2     2     2     2     2     2     2     2     2     2     2     2
        2     2     2     2     2     2     2     1     1     2     2     2     1     2     2     2
        2     2     2     2     2     1     1     2     2     1     1     1     2     2     2     2
        2     2     2     2     1     2     2     2     2     2     1     1     2     2     2     2
        2     2     2     2     1     2     2     2     2     1     2     1     2     2     2     2
        2     2     2     1     2     2     2     2     1     2     2     2     1     2     2     2
        2     2     2     1     2     2     2     1     2     2     2     2     1     2     2     2
        2     2     2     2     1     2     1     2     2     2     2     1     2     2     2     2
        2     2     2     2     1     1     2     2     2     2     2     1     2     2     2     2
        2     2     2     2     1     1     1     2     2     1     1     2     2     2     2     2
        2     2     2     1     2     2     2     1     1     2     2     2     2     2     2     2
        2     2     2     2     2     2     2     2     2     2     2     2     2     2     2     2
        2     2     2     2     2     2     2     2     2     2     2     2     2     2     2     2
        2     2     2     2     2     2     2     2     2     2     2     2     2     2     2     2];
    
    function tlim = localGetAxesLimits(handles);
    % Compute x axis limits
    timeslist = get(handles.TimeSelectPopup,'String');
    timeslist = localRemoveLengthFromParms(timeslist);
    tmin = inf;
    tmax = -inf;
    for ii=1:length(timeslist)
        time = evalin('base',timeslist{ii});
        if min(time) < tmin
            tmin = min(time);
        end;
        if max(time) > tmax
            tmax = max(time);
        end;
    end;
    
    tlim = [tmin tmax];
    
    function parms = localRemoveLengthFromParms(parms);
    % Remove the lengths from the parameter strings.
    for ii=1:length(parms);
        % Find the first blank.
        blank = strfind(parms{ii},' ');
        parms{ii} = parms{ii}(1:blank(1)-1);
    end;
    
    function parms = localAddLengthToParms(parms);
    % Remove the lengths from the parameter strings.
    for ii=1:length(parms);
        L = evalin('base',['length(' parms{ii} ');']);
        parms{ii} = [parms{ii} '  (' num2str(L) ')'];
    end;
    
%     function localClearParameter(hObject,event);
%     % Clear a parameter from the workspace
%     val = get(gco,'Value');
%     parms = get(gco,'String'); 
%     
%     % Strip lengths off of parms
%     parms = localRemoveLengthFromParms(parms);
%     
%     % Clear the parameter
%     evalin('base',['clear ' parms{val}]);
%     
%     % Update the Parameter List
%     localUpdateParmlist(guidata(hObject));
function localTurnOffZoom(handles)
tlim = localGetAxesLimits(handles);
set(handles.axes,'XLim',tlim);

% Set the ticks on last axes, hide on others
NoAx = str2num(get(handles.NoAxesCombo(2),'String'));
set(handles.axes(NoAx),'XTick',[tlim(1) mean(tlim) tlim(2)]);
set(handles.axes(1:NoAx-1),'XTick',[]);

Contact us at files@mathworks.com