function varargout = rslice(varargin)
% RSLICE:  ROMS slicing tool
%
% r = rslice('file',filename) starts rslice on a single local netcdf file.
%
% r = rslice('url',url) starts rslice on an OPeNDAP URL.
%
% r = rslice(...,'time_variable',varname) specifies the name of the variable
% that serves as time.  Usually this is just 'ocean_time'.
%
% See the doc directory for more information.
%
% See also: GUIDE, GUIDATA, GUIHANDLES
%

%
% Fields of the global data structure, sometimes called "gdata", 
% sometimes called "rslice_object", sometimes called "rslice_data".
%
%     default_depth:
%         Depth (positive downward) in meters at which to take the 
%         first horizontal slice.
%     dim_type:
%         One of these possibilities.
%             'YX':  no vertical or temporal dimension.  Like 'h'.
%             'TYX':  no vertical dimension, like 'u_bar'.
%             'TZYX':  a full four dimensional dataset, like 'temp'.
%     hslice_on_sigma:
%         A flag.  If set, then the current variable should be sliced
%         along the sigma coordinate (much faster) than the other
%         case, which is slicing along a constant depth.
%     fileResource:
%         Mostly used for java case.  If given a URL, we will try to
%         open the URL just once and then continually pass the file
%         ID into SNCTOOLS rather than continually reopening and
%         closing the file.
%     first_redraw:
%         There are a few things that are done differently if we've
%         already rendered a slice once, so we keep track of this 
%         thru a flag.  One of these things is setting the CLim 
%         property for the first rendering.
%     input_type:
%         Can be either 'file', 'directory', 'url'
%         'file' and 'directory' mean that the data is being retrieved
%         from files on the local filesystem.  'url' means that an
%         opendap server is the data source.  
%     interpolation_method:
%         Can be one of 
%             'griddata_lite':  
%                 A variation on the griddata algorithm.
%             'nearest':  
%                 Nearest neighbor
%         This controls how the slice values are interpolated from
%         the dataset.
%     load_time_series_variables_only:
%         If set, then such variables as "h", "lon_rho", etc. will not
%         be included in the list of variables to choose from.
%     max_num_timesteps:
%         The number of discrete time steps available for perusal in 
%         the current dataset.  This value is echoed in the rslice 
%         figure window.
%     max_num_usable_vars:
%         If there are so many variables in the dataset, then using
%         a drop down menu becomes a bad way to do it, and we should
%         use a dialog box instead.
%     ncfile_index:
%         A 1-based index into "ncfile_list".
%     ncfile_list:
%         A cell array.
%
%         switch ( input_type )
%         case 'directory'
%             Could be many values, possibly as many as there are files
%             within the intended directory.
%         case 'file'
%             Just one value, the full pathname of a single NetCDF 
%             file.
%         case 'url'
%             Just one value, the URL of the opendap dataset.
%         end
%
%     ncfile_start_index, ncfile_stop_index:
%         An array whose size is the same as ncfile_list, so only in
%         the case of 'directory' is it anything other than a single
%         value, which would be 0.  In the case of 'directory', then
%         each element corresponds to a netcdf file, specifically
%         where the first and last time step in that file fall into 
%         place in the aggregated time series.  For example, suppose 
%         that there are three netcdf files in the current directory.
%         File A has 5 timesteps, file B has 7 timesteps, and file C
%         has 9 timestep.  Then the values of the ncfile_start_index
%         would be [0 5 12] and the value of the ncfile_stop_index
%         would be [4 11 20].
%
%     ocean_time:
%         Vector of all time values from all netcdf input files.
%         The units are matlab datenum, however, not julian days or 
%         "seconds since yyyy-mm-dd" or whatever it was that is 
%         present in the "units" attribute of the "ocean_time" variable.
%
%     record_variable:
%         Specify this in case the unlimited record variable is not 
%         'ocean_time'.  So the default record variable is 'ocean_time'.
%         The reason why this is necessary is that it does not seem
%         to be currently possible to determine who the record variable
%         is when an OPeNDAP-enabled version of mexnc is used on URLs.
%
%     restricted_varlist:
%         If present, then this is a user-specified list of variables.
%         Sometimes there are so many roms variables that it overwhelms
%         the GUI.  This is a way to ease it a bit.
%
%     rslice_grid:
%         A structure with five subfields.  These subfields are
%       
%         coordsys:
%             Either 'geographic' (if the input files have lat_rho
%             and lon_rho) or 'xy' otherwise (x_rho and y_rho).
%         roms_grid:
%             Structure as returned by m-file "roms_get_grid.m"
%         x, y:
%             Structures with metadata about the horizontal and 
%             vertical coordinates referenced by coordsys above.
%         angle:
%             Structure with metadata about the ROMS variable "angle".
%             If the coordsys is 'xy', then this is ignored.
%     sigma_index:
%         If slicing along the sigma coordinate, this index specifies
%         the index of the sigma coordinate.  The default is 0.  It
%         can be changed to xxx by typing "s=xxx" in the depth edit
%         box.
%     timestep:
%         The current time index.
%     varinfo:
%         A structure of information about the current variable.
%     varlist:
%         Cell array of usable variables.
%     varname:
%         The name of the dataset currently being displayed in the 
%         rslice figure window.
%     velocity:
%         A structure with two fields, 'u_velocity' and 'v_velocity'.
%         Each of these fields is in turn a structure of metadata about
%         their respective velocity dataset.
%     verbose:
%         This is a flag that can be set from the command line.  If
%         set to 1, then rslice will print out a bit more information
%         during its course of operation than otherwise.  It currently
%         is not well implemented, though.
%     vslice_data:
%         A matlab structure that is only present when a vertical slice
%         has been defined.  This structure has five fields.
%             vx, vz: 
%                 Arrays that define the horizontal and vertical 
%                 directions (vertical meaning down) along the vertical
%                 slice. 
%             vdata:
%                 Data from vertical slice variable at the locations
%                 defined by vx, vz.
%             control_pt_x, control_pt_y:
%                 Control points that defined the slice.  
%     z_type:
%         Either 's_rho' or 's_w', which are names of the sigma depth
%         coordinates.  's_w' is typically one more than 's_r'.  It
%         affects how the depths are calculated.
%
% GUI Controls    
%     close_menu:
%         A menu item under "File".  This closes out the current rslice
%         object.
%     default_depth:
%         If no depth is provided, then this is the depth we assume to
%         slice at.
%     depth_edit:
%         An editable text widget that controls either the depth or the
%         sigma coordinate at which the current data set is sliced. 
%         The default is sigma coordiate, which is designated with an
%         "s=" string prepended onto the numeric value.  Getting rid
%         of the prefix makes rslice interpret the value as a depth.
%     fastforward_pushbutton:
%         A pushbutton which will start an animation by continually 
%         advancing the time step until the end is reached.
%     file_menu:
%         A drop down menu that exposes the usual File options one
%         would expect in a File menu, such as open and close.
%     hslice_figure:
%         This is the same as the rslice field.  Don't use 
%         "hslice_figure".
%     horizontal_slice_axis:
%         This is the main axis that displays during rslice operations.
%     horizontal_slice_title:
%         Lost in space?
%     horizontal_slice_title2:
%         A bad name for a title string on the main rslice window.
%     horizontal_cmax_edit:
%         An editable text widget that displays the current maximum 
%         value of the rslice window color range.  This can be changed
%         manually, or by changing variables.
%     horizontal_cmin_edit:
%         An editable text widget that displays the current minimum 
%         value of the rslice window color range.  This can be changed
%         manually, or by changing variables.
%     horizontal_cmax_text:
%         A read-only text widget that just displays "CMax".  It refers
%         to the maximum value of the color range.
%     horizontal_cmn_text:
%         A read-only text widget that just displays "CMin".  It refers
%         to the minimal value of the color range.
%     hvoc_figure:
%         A handle for the horizontal velocity overlay control window.
%     max_sigma_level:
%         Number of sigma coordinates possible in the current variable.
%         For something like 'h', this is 0.
%     new_directory:
%         A menu item under the "File" menu.  A native matlab directory
%         browser window pops up, allowing the user to navigate to 
%         another directory source of ROMS files.
%     new_menu:
%         A menu item under the "File" menu.  A native matlab file
%         browser window pops up, allowing the user to navigate to a 
%         new ROMS file.
%     new_url_menu:
%         A menu item under the "File" menu.  A crude popup appears
%         that allows the user to type in a new URL to load.  Did I
%         say that it was crude?
%     original_xlim, original_ylim:
%         These are the original XLim and YLim properties of the first
%         rendering of a dataset.  They are used for "zoom back".
%     other_menu:
%         Drop down menu that contains other miscellaneous menu items.
%         Maybe "Miscellaneous" would have been a better name.
%     output:
%         Currently this is the same as the rslice field.  Don't use
%         this.
%     rslice:
%         This is the return parameter for the rslice m-file.  Thru 
%         this handle, all of the other gui widgets and fields can
%         be accessed.
%     rewind_pushbutton:
%         A pushbutton on the main rslice figure window which will 
%         start an animation by continually advancing the time step
%         BACKWARDS by one discrete unit until the beginning is 
%         reached.
%     sigma_index:
%         An index into the sigma layer coordinate.  0 is the bottom
%         layer in roms.
%     step_back_pushbutton:
%         A pushbutton which will advance the current time BACKWARDS by
%         one discrete time step.
%     step_forward_pushbutton:
%         A pushbutton which will advance the current time by one 
%         discrete time step.
%     stop_animation_button:
%         A pushbutton whose only job is to toggle a flag.  If this
%         is done during the middle of an animation (such as the
%         time step continually advancing), then the animation
%         will be broken.
%     timestep_edit:
%         An editable text widget that displays the current time index
%         (not time value) of the ROMS dataset.  It is zero-based.
%     timestep_text:
%         A text widget that displays the value of the current time 
%         step in human readable terms.
%     variable_menu:
%         A drop down menu that exposes the list of ROMS variables that
%         the user can choose to display.
%     velocity_overlay_tag:
%         A menu item under "Other".  This initiates a popup figure
%         window that the user will control to specify how the 
%         velocity overlay arrows will look.
%     vslice_figure:
%         A handle for the vertical slice figure window.
%     vslice_menu:
%         A menu item under "Other".  This initiates a vertical slice
%         operation on the dataset being currently displayed in the
%         rslice figure window.
%     vslice_vel_figure:
%         A handle for the vertical slice velocity figure window.
%     vslice_velocity_menu:
%         A menu item under "Other".  This initiates a vertical slice
%         operation on the vertical velocity fields, regardless of
%         what the current dataset it.  If there are no velocity 
%         fields, then this menu item is grayed out.
%     zoom_back_menu:
%         A menu item under "Other".  This "unzooms" by bringing the
%         field of view back to the original state.
%     zoom_menu:
%         A menu item under "Other".  This enables the usual zooming
%         feature, which is normally turned off.
%         
%

% Edit the above text to modify the response to help rslice
% Last Modified by GUIDE v2.5 11-May-2006 08:10:33
% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @rslice_OpeningFcn, ...
                   'gui_OutputFcn',  @rslice_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);



if nargin && ischar(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



return




% --- Executes just before rslice is made visible.
function rslice_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 rslice (see VARARGIN)

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

% Update handles structure
%guidata(hObject, handles);

gdata = guidata ( hObject );
gdata.output = hObject;
gdata.rslice = hObject;
guidata ( hObject, gdata );


% UIWAIT makes rslice wait for user response (see UIRESUME)
% uiwait(handles.hslice_figure);
options = rslice_defaults;

options = parse_rslice_command_line(options,varargin{:});

rslice_initialize ( hObject, options );

% -------------------------------------------------------------------------
function rslice_initialize ( hObject, options )
% RSLICE_INITIALIZE:
%
%
% gdata fields:
%     autoscale_clims:
%         If set to 1, then let matlab set the color limits for us.
%     rslice_grid:  
%         coordsys:  can be one of
%             'geographic':  datasets lon_rho, lat_rho, and angle exist
%             'xy:  datasets x_rho and y_rho exist
%
%         roms_grid:
%             As returned by call to roms_get_grid.  Useful, but this
%             doesn't give us everything we need.
%
%         x, y, angle:
%             These are structures.  If coordsys is 'geographic', then
%             x would be the structure returned from nc_getvarinfo for
%             'lon_rho'.  If coordsys is 'xy', then it is the structure
%             returned for 'x_rho'.  
%
%             If the dataset angle is not actually present in the netcdf 
%             file, then the angle field is set to the empty set.
%
%             In addition to the metadata attributes, an additional
%             field is present, 'data', which is the actual 2D 
%             array for x, y, and angle.
%
%     velocity:
%             A structure.  We have two fields
%
%             u_varinfo, v_varinfo
%  
%             These are as returned from nc_getvarinfo.
%
%     verbose:  
%         0 ==> no verbose messages
%         1 ==> verbose messages
%     input_type:
%         'file' ==>  operations are restricted to a single netcdf file
%         'directory' ==>  treat all netcdf files in said directory
%             as a single netcdf file
%     ncfile_list:
%         cell array of netcdf files (possibly just 1)
%     ncfile_index:
%         specifies the current netcdf file in "ncfile_list" being
%         operated on.
%     varname:
%         Current active variable.
%     varinfo:
%         structure of metadata pertaining to the current active
%         variable.
%     max_num_timesteps:
%         Number of timesteps in the ROMS location.  Possible contexts
%         are for all the netcdf files in a directory or just a single
%         netcdf file.
%     roms_grid:
%         As returned by call to roms_get_grid.m
%
%
% Options fields:
%    verbose:
%    location:
%    regex:
%    variable:
%        The default display variable is "h".  This option allows the
%        user to change that.
%    vslice:
%        2 column matrix.  The x coordinates 
%    

%
% CALLS:
%    roms_get_grid,
%    rslice_fix_roms_grid, rslice_io, rslice_message, 
%    rslice_set_varmenu, enable_or_disable_velocity_overlay, 
%    rslice_init_grid
% CALLED BY:
%    rslice
%

gdata = guidata ( hObject );
handles = guihandles ( hObject );

%
% set defaults.
gdata.verbose = 0;


if gdata.verbose > 0
    rslice_message ( sprintf ( '%s:  start', mfilename ) );
end



% Did the user specify an alternate unlimited variable?
if isfield ( options, 'record_variable' )
    gdata.record_variable = options.record_variable;
else
    gdata.record_variable = 'ocean_time';
end



% Did the user specify an alternate time dimension?
if isfield ( options, 'time_dimension' )
    gdata.time_dimension = options.time_dimension;
else
    gdata.time_dimension = 'ocean_time';
end




if isfield ( options, 'input_type' ) && isempty(options.input_type)
    return;
end
gdata = handleDataSource ( hObject, options, gdata );


% It's always the first file.
ncfile = gdata.ncfile_list{1};

% Store the info struct so we don't have to keep inquiring.
gdata.file_info = nc_info(ncfile);
guidata ( hObject, gdata );



gdata.rslice_grid = rslice_init_grid ( hObject );
guidata ( hObject, gdata );


%
% Start off by looking at the first file in the list (maybe there
% is only one anyway.
gdata.ncfile_index = 1;


%
% Did we specify a certain subset of variables?
% If so, this overrides the default variable.
if isfield ( options, 'restricted_varlist' )
    gdata.restricted_varlist = options.restricted_varlist;
    gdata.varname = gdata.restricted_varlist{1};
end

gdata.load_time_series_variables_only = options.load_time_series_variables_only;


%
% Set the switch for autoscaling the color limits.  Default
% is to NOT autoscale.
gdata.autoscale_clims = 0;

%
% Load information about the default variable
    if ~nc_isvar ( ncfile, gdata.varname )
        v = rslice_file_datasets ( gdata );
        gdata.varname = v{1};
    end
gdata.varinfo = rslice_init_varinfo ( gdata, ncfile, gdata.varname );


%
% If appropriate, load in u, and v varinfo for the velocity
% slicing.
velocity_ok = get ( handles.velocity_overlay_tag, 'Enable' );
if strcmp ( velocity_ok, 'on' )
    if nc_isvar ( ncfile, 'v' )
    gdata.velocity.u_varinfo = nc_getvarinfo ( ncfile, 'u' );
    gdata.velocity.v_varinfo = nc_getvarinfo ( ncfile, 'v' );
    end
  %flc% Added to plot 2D vector currents
    if nc_isvar ( ncfile, 'vbar' )
    gdata.velocity.u_varinfo = nc_getvarinfo ( ncfile, 'ubar' );
    gdata.velocity.v_varinfo = nc_getvarinfo ( ncfile, 'vbar' );
    end
end


gdata = rslice_determine_timestep_info ( gdata );



[gdata.dim_type, gdata.z_type] = rslice_classify_variable ( gdata.varinfo );


gdata.timestep = 0;

%gdata.interpolation_method = 'nearest_neighbor';
gdata.interpolation_method = 'griddata_lite';

%
% There are certain defaults used when we draw for the first time.  We have to
% flag for this.
gdata.first_redraw = 1;


%
% Set a handle for the vslice figure.
gdata.vslice_figure = vslice;
set ( gdata.vslice_figure, 'visible', 'off' );
vdata.parent = hObject;
guidata ( gdata.vslice_figure, vdata );

%
% Set a handle for the vslice velocity figure.
gdata.vslice_vel_figure = vslice_vel;
set ( gdata.vslice_vel_figure, 'visible', 'off' );
vdata.parent = hObject;
guidata ( gdata.vslice_vel_figure, vdata );

%
% Set a handle for the horizontal velocity overlay control figure
%gdata.hvoc_figure = horizontal_velocity_overlay_controls ( hObject );
gdata.hvoc_figure = hvo;
set ( gdata.hvoc_figure, 'visible', 'off' );
hvoc_data.parent = hObject;
guidata ( gdata.hvoc_figure, hvoc_data );



%
% Now set some of the handle properties
handles = guihandles ( hObject );

set ( handles.timestep_edit, 'String', '0' );  





%
% The default is to slice on sigma level
gdata.hslice_on_sigma = 1;
switch ( gdata.dim_type )
case 'TZYX'
    gdata.max_sigma_level = gdata.varinfo.Size(2);
    gdata.sigma_index = gdata.max_sigma_level - 1;
otherwise
    gdata.sigma_index = 0;
    gdata.max_sigma_level = 0;
end


gdata.default_depth = 0.5;
switch ( gdata.dim_type )
case { 'TZYX', 'ZYX' }
    theString = sprintf ( 's=%d', gdata.sigma_index );
    set ( handles.depth_edit, 'String', theString );  
otherwise
    set ( handles.depth_edit, 'String', '' );  
end




%
% Did we specify a certain number of variables?  
if isfield ( options, 'nvarcutoff' )
    gdata.max_num_usable_vars = options.nvarcutoff;
else
    gdata.max_num_usable_vars = 20;
end





%
% store the initialized values
guidata ( hObject, gdata );

%
% setup the choice of variables.
rslice_set_varmenu ( hObject );

rslice_hslice_redraw ( hObject );
gdata = guidata ( hObject );

if isfield ( options, 'vslice' )

    control_pt_x = options.vslice(:,1);
    control_pt_y = options.vslice(:,2);
    vslice_data.control_pt_x = control_pt_x;
    vslice_data.control_pt_y = control_pt_y;


    %
    % Pack the gdata.vslice_data structure appropriately.
    [spx, spy] = create_vslice_line ( control_pt_x, control_pt_y );
    vslice_data.spline_x = spx;
    vslice_data.spline_y = spy;

    [hires_x, hires_y] = create_hires_line ( spx, spy );
    vslice_data.hires_x = hires_x;
    vslice_data.hires_y = hires_y;


    %
    % save the global structure again
    gdata.vslice_data = vslice_data;
    gdata.vslice_vel_data = vslice_data;
    guidata ( hObject, gdata );

    vslice_options.retrieve_new_data = 1;
    rslice_vslice_redraw ( hObject, vslice_options );

    %
    % We need to explicitly retrieve this again.
    gdata = guidata ( hObject );

end

if isfield ( options, 'vslice_vel' )

    control_pt_x = options.vslice(:,1);
    control_pt_y = options.vslice(:,2);
    vslice_data.control_pt_x = control_pt_x;
    vslice_data.control_pt_y = control_pt_y;


    %
    % Pack the gdata.vslice_data structure appropriately.
    [spx, spy] = create_vslice_line ( control_pt_x, control_pt_y );
    vslice_data.spline_x = spx;
    vslice_data.spline_y = spy;

    [hires_x, hires_y] = create_hires_line ( spx, spy );
    vslice_data.hires_x = hires_x;
    vslice_data.hires_y = hires_y;


    %
    % save the global structure again
    gdata.vslice_data = vslice_data;
    gdata.vslice_vel_data = vslice_data;
    guidata ( hObject, gdata );

    vslice_options.retrieve_new_data = 1;
    rslice_vslice_velocity_redraw ( hObject, vslice_options );

    %
    % We need to explicitly retrieve this again.
    gdata = guidata ( hObject );

end

%
% Get the default axes extents, use this for a zoom reset since 
% zoom out seems to be broken on solaris.  Jeezuz I hate solaris.
% We hates, we hates, we HATES solaris!
gdata.original_xlim = get ( handles.horizontal_slice_axis, 'XLim' );
gdata.original_ylim = get ( handles.horizontal_slice_axis, 'YLim' );

%
% store the initialized values (again)
guidata ( hObject, gdata );



return




%--------------------------------------------------------------------------
function varinfo = rslice_init_varinfo ( rslice_obj, ncfile, varname )


varinfo = [];


% retrieve/construct a structure of metadata for the variable in question.
varinfo = nc_getvarinfo ( rslice_obj.fileResource, rslice_obj.varname );


return









%--------------------------------------------------------------------------
% RSLICE_INIT_GRID:
%
% This function populates a structure called "rslice_grid".
%
%     rslice_grid:  
%         coordsys:  can be one of
%             'geographic':  datasets lon_rho, lat_rho, and angle exist
%             'xy:  datasets x_rho and y_rho exist
%
%         roms_grid:
%             As returned by call to roms_get_grid.  Useful, but this
%             doesn't give us everything we need.
%
%         x, y, angle:
%             These are structures.  If coordsys is 'geographic', then
%             x would be the structure returned from nc_getvarinfo for
%             'lon_rho'.  If coordsys is 'xy', then it is the structure
%             returned for 'x_rho'.  
%
%             If the dataset angle is not actually present in the netcdf 
%             file, then the angle field is set to the empty set.
%
%             In addition to the metadata attributes, an additional
%             field is present, 'data', which is the actual 2D 
%             array for x, y, and angle.
%
function rslice_grid = rslice_init_grid ( hObject )

gdata = guidata(hObject);
handles = guihandles ( hObject );

% Get what grid information we can from roms_get_grid.
ncfile = gdata.ncfile_list{1};

coordsys = classify_grid_coordsys(gdata);


roms_grid = snc_roms_get_grid ( gdata, ncfile );
roms_grid = rslice_fix_roms_grid ( ncfile, roms_grid, coordsys );
rslice_grid.roms_grid = roms_grid;
rslice_grid.coordsys = coordsys;



%
% Disable vertical slicing if we don't have the proper vertical
% information.
if isfield ( rslice_grid.roms_grid, 'z_r' )
    set ( handles.vslice_menu, 'Enable', 'on' );
else
    set ( handles.vslice_menu, 'Enable', 'off' );
end


%
% get the metadata for the x, y, and angle fields.
switch ( rslice_grid.coordsys )
case 'geographic'
    rslice_grid.x = nc_getvarinfo ( ncfile, 'lon_rho' );
    rslice_grid.y = nc_getvarinfo ( ncfile, 'lat_rho' );
    if nc_isvar ( ncfile, 'angle' )
        rslice_grid.angle = nc_getvarinfo ( ncfile, 'angle' );
    else
        rslice_grid.angle = [];
    end

case 'xy'
    x = nc_getvarinfo ( ncfile, 'x_rho' );
    y = nc_getvarinfo ( ncfile, 'y_rho' );
    
    rslice_grid.x = x;
    rslice_grid.y = y;
    rslice_grid.angle = [];

case 'ij'
    x.data = roms_grid.x_rho;
    y.data = roms_grid.y_rho;
    
    rslice_grid.x = x;
    rslice_grid.y = y;
    rslice_grid.angle = [];

        otherwise
            error ( '%s:  unhandled coordinate system %s.\n', mfilename, rslice_grid.coordsys );
end



%
% Get the actual data for x, y, and the angle.
switch ( rslice_grid.coordsys )
case 'geographic'
    rslice_grid.x.data = rslice_grid.roms_grid.lon_rho;
    rslice_grid.y.data = rslice_grid.roms_grid.lat_rho;
    if isempty(rslice_grid.angle)
        rslice_grid.have_angle = 0;
        rslice_grid.angle.data = zeros(size(rslice_grid.roms_grid.lon_rho));
    else
        rslice_grid.have_angle = 1;
        rslice_grid.angle.data = rslice_grid.roms_grid.angle;
    end

case 'xy'
    rslice_grid.x.data = nc_varget ( gdata.fileResource, 'x_rho' );
    rslice_grid.y.data = nc_varget ( gdata.fileResource, 'y_rho' );
end




%--------------------------------------------------------------------------
function gdata = handleDataSource ( hObject, options, gdata );

import ucar.nc2.dods.*     % import opendap reader classes
import ucar.nc2.*

% handleDataSource : Check the input_type field to see whether we are dealing
% with a directory, a file, or a url.
if isfield ( options, 'input_type' )
    switch ( options.input_type )
    case 'file'
        if exist( options.source, 'file' )
            gdata.input_type = 'file';
            gdata.ncfile_list = { options.source };
        else
            error ( 'File %s cannot be found.\n', options.source );
        end
        gdata.varname = options.default_variable;  % default is bathymetry
        gdata.fileResource = gdata.ncfile_list{1};

    case 'directory'
        if ~exist( options.source,'dir')
            error('Supplied directory ''%s'' does not exist.\n',options.source);
        end
        if ~isfield ( options , 'regex')
            error ( 'If you give me a directory, I also need a regular expression to narrow down the list of netcdf files.\n' );
        end
        gdata.input_type = 'directory';
        gdata.ncfile_list = rnt_getfilenames ( options.source, options.regex, gdata );
        gdata.varname = options.default_variable;  % default is bathymetry
        gdata.fileResource = gdata_ncfile_list{1};

    case 'url'
        gdata.input_type = 'url';
        gdata.ncfile_list = { options.source };
        gdata.varname = options.default_variable;  % default is bathymetry
        try
            gdata.fileResource = NetcdfFile.open(gdata.ncfile_list{1});
        catch
            gdata.fileResource = DODSNetcdfFile(gdata.ncfile_list{1});
        end

    otherwise
        msg = sprintf ( '%s:  unhandled input type %s.\n', mfilename, options.input_type );
    end


    %
    % At this point we need to check that we have enough information to allow for 
    % the velocity overlay
    enable_or_disable_velocity_overlay ( hObject, gdata.ncfile_list{1} );
end




% --- Outputs from this function are returned to the command line.
function varargout = rslice_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
if isfield ( handles, 'output' )
varargout{1} = handles.output;
end

return


% --- Executes during object creation, after setting all properties.
function timestep_edit_CreateFcn(hObject, eventdata, handles)
% hObject    handle to timestep_edit (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 timestep_edit_Callback(hObject, eventdata, handles)
% hObject    handle to timestep_edit (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 timestep_edit as text
%        str2double(get(hObject,'String')) returns contents of timestep_edit as a double


    %new_timestep = str2double ( get (handles.timestep_edit, 'String' ) );
    new_timestep_string = get (handles.timestep_edit, 'String' );
    rslice_handle_new_timestep ( hObject, eventdata, handles, new_timestep_string );
    return


% --- Executes during object creation, after setting all properties.
function depth_edit_CreateFcn(hObject, eventdata, handles)
% hObject    handle to depth_edit (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 depth_edit_Callback(hObject, eventdata, handles)
% hObject    handle to depth_edit (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 depth_edit as text
%        str2double(get(hObject,'String')) returns contents of depth_edit as a double


    gdata = guidata ( hObject );

    depthString = get (handles.depth_edit, 'String' );

    %
    % Try to parse it.  Is it of the form 's=%d'?  If so, then
    % it is a sigma level.  Otherwise, it must be depth.
    [s,r] = strtok ( depthString, '=' );
    if isempty(r)

        %
        % Ok, we were told to slice on depth.  Is this even possible? 
        % Check to see if we have any depth information.
        try
            if isfield ( gdata.rslice_grid.roms_grid, 'z_r' )
                %
                % We do have depth information.  Flag this fact.
                gdata.hslice_on_sigma = 0;
            else
                depthString = sprintf ( 's=%d', gdata.max_sigma_level-1 );
                set ( handles.depth_edit, 'String', depthString );
                rslice_hslice_redraw;
                return;
            end
        catch
            depthString = sprintf ( 's=%d', gdata.max_sigma_level-1 );
            set ( handles.depth_edit, 'String', depthString );
            rslice_hslice_redraw;
            return;
        end



        new_depth = str2double ( get ( handles.depth_edit, 'String' ) );

        %
        % Set the slice method

        %
        % Check to make sure that the depth is valid.  
        if isnan ( new_depth )
    
            %
            % Ok, the user did something bad.  Set the depth back to 
            % zero.
            new_depth = 0;
    
        elseif ( new_depth < -1 )
    
            %
            % Allow for a little ssh.  Actually that's quite a bit.
            new_depth = -1;
    
        end
    
        %
        % This only changes things if the value specified by the
        % user was not a valid depth.
        gdata.depth = new_depth;
        set ( handles.depth_edit, 'String', num2str(new_depth) );
    
    
    else
        [s,r] = strtok ( r, '=' );
        sigma_level = str2double ( s );
        
        %
        % If it is out of bounds, reset it.
        if sigma_level >= gdata.max_sigma_level
            sigma_level = gdata.max_sigma_level - 1;
            depthString = sprintf ( 's=%d', sigma_level );
            set ( handles.depth_edit, 'String', depthString );
        end

        %
        % Set the slice method
        gdata.sigma_index = sigma_level;
        gdata.hslice_on_sigma = 1;

    end




    %
    % Save the global data structure.
    guidata ( gcbo, gdata );


    %
    % And finally just redraw the horizontal slice at the new depth.
    rslice_hslice_redraw;



    return






% --- Executes during object creation, after setting all properties.
function horizontal_cmin_edit_CreateFcn(hObject, eventdata, handles)
% hObject    handle to horizontal_cmin_edit (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 horizontal_cmin_edit_Callback(hObject, eventdata, handles)
% hObject    handle to horizontal_cmin_edit (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 horizontal_cmin_edit as text
%        str2double(get(hObject,'String')) returns contents of horizontal_cmin_edit as a double


    %
    % redraw the horizontal slice with a new set of color limits.
    rslice_hslice_redraw;

    gdata = guidata ( hObject );

    %
    % Is the vslice figure visible?  If so, then issue a redraw.
    vis = get ( gdata.vslice_figure, 'Visible' );
    if strcmp ( vis, 'on' )
        rslice_vslice_redraw ( hObject );
    end

    return



% --- Executes during object creation, after setting all properties.
function horizontal_cmax_edit_CreateFcn(hObject, eventdata, handles)
% hObject    handle to horizontal_cmax_edit (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 horizontal_cmax_edit_Callback(hObject, eventdata, handles)
% hObject    handle to horizontal_cmax_edit (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 horizontal_cmax_edit as text
%        str2double(get(hObject,'String')) returns contents of horizontal_cmax_edit as a double


    %
    % redraw the horizontal slice with a new set of color limits.
    rslice_hslice_redraw;

    gdata = guidata ( gcbo );

    %
    % Is the vslice figure visible?  If so, then issue a redraw.
    vis = get ( gdata.vslice_figure, 'Visible' );
    if strcmp ( vis, 'on' )
        rslice_vslice_redraw ( hObject );
    end

    return




% --------------------------------------------------------------------
function file_menu_Callback(hObject, eventdata, handles)
% hObject    handle to file_menu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


% --------------------------------------------------------------------
function new_menu_Callback(hObject, eventdata, handles)
% hObject    handle to new_menu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


    %
    % Navigate to a new netcdf file.
    [filename, pathname, filterindex] = uigetfile ( '*.nc', 'Pick a ROMS File' );
    if ( filterindex == 0 )

        %
        % Ok the user canceled.  So will we.
        return

    end


    %
    % Construct the full path to the netcdf file.
    ncfile = [pathname filesep filename];

    %
    % If the file does not exist

    options = rslice_defaults;

    %
    % Do the appropriate default overrides and proceed to initialize for use.
    options.verbose = 0;
    options.input_type = 'file';
    options.source = ncfile;
    rslice_initialize ( hObject, options );

    return




% --------------------------------------------------------------------
function close_menu_Callback(hObject, eventdata, handles)
% hObject    handle to close_menu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

    %
    % First try to delete the horizontal slice figure.
    gdata = guidata ( gcbo );
    delete ( handles.hslice_figure );

    %
    % Now try to delete the auxilliary windows.  They may or 
    % may not exist, so we have to couch this in try/catch.
    try
        delete ( gdata.vslice_vel_figure );
    end
    try
        delete ( gdata.hvoc_figure );
    end
    try
        delete ( gdata.vslice_figure );
    end
    try
        delete ( gdata.hvoc_figure );
    end

    if strcmp(gdata.input_type,'url')
        close(gdata.fileResource);
    end
    return



% --------------------------------------------------------------------
function variable_menu_Callback(hObject, eventdata, handles)
% hObject    handle to variable_menu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

    gdata = guidata ( gcbo );
    if ~isfield ( gdata, 'varlist' )
        fprintf ( 2, 'You need to load a dataset first.\n' );
        return
    end
    if ( length(gdata.varlist) > gdata.max_num_usable_vars)

        vml = rslice_varmenu_overflow_listbox;

        %
        % Store a reference to rslice so that the 
        % rslice_varmenu_overflow_listbox callbacks can 
        % interact with rslice again.
        vml_data = hObject;
        guidata ( vml, vml_data );

        listbox = findobj ( vml, 'Tag', 'varmenu_listbox' );
        set ( listbox, 'String', gdata.varlist );
    end
    return


% --------------------------------------------------------------------
function projection_menu_Callback(hObject, eventdata, handles)
% hObject    handle to projection_menu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


% --------------------------------------------------------------------
function geographic_menu_Callback(hObject, eventdata, handles)
% hObject    handle to geographic_menu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


% --------------------------------------------------------------------
function utm_menu_Callback(hObject, eventdata, handles)
% hObject    handle to utm_menu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


% --------------------------------------------------------------------
function albers_equal_area_menu_Callback(hObject, eventdata, handles)
% hObject    handle to albers_equal_area_menu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


% --------------------------------------------------------------------
function lambert_equal_area_azimuthal_Callback(hObject, eventdata, handles)
% hObject    handle to lambert_equal_area_azimuthal (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


% --------------------------------------------------------------------
function other_menu_Callback(hObject, eventdata, handles)
% hObject    handle to other_menu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


% --------------------------------------------------------------------
function velocity_overlay_menu_Callback(hObject, eventdata, handles)
% hObject    handle to velocity_overlay_menu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


    %
    % This is an old routine, can I delete it now?
    return





% --------------------------------------------------------------------
function vslice_menu_Callback(hObject, eventdata, handles)
% hObject    handle to vslice_menu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)



    %
    % Let the user define a new vslice line, retrieve the data
    % along that line, and render it!
    vslice_options.get_new_line = 1;
    vslice_options.retrieve_new_data = 1;
    rslice_vslice_redraw ( hObject, vslice_options );


    return



% --------------------------------------------------------------------
function zoom_menu_Callback(hObject, eventdata, handles)
% hObject    handle to zoom_menu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

    %
    % Just make sure that 'zoom' is turned on.
    zoom ( handles.hslice_figure, 'on' );
    return


% --------------------------------------------------------------------
function Untitled_15_Callback(hObject, eventdata, handles)
% hObject    handle to Untitled_15 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


% --------------------------------------------------------------------
function new_directory_Callback(hObject, eventdata, handles)
% hObject    handle to new_directory (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


    pathname = uigetdir ( '.', 'Pick a ROMS Directory' );


    if isempty ( pathname )
        ncfile = pwd;
    else
        ncfile = pathname
    end

    options = rslice_defaults;


    %
    % Ask the user for a regular expression that will winnow down 
    % the list of available netcdf files.
    prompt = 'Enter a regular expression for the netcdf files.  ';
    prompt = [prompt 'See the help for rslice for details on how to use this.'] ;
    the_answer = inputdlg ( prompt );
    options.regex = the_answer{1};

    %
    % appropriately override the rest of the defaults
    options.input_type = 'directory';
    options.source = ncfile;
    options.verbose = 0;

    rslice_initialize ( hObject, options );

    return


% --------------------------------------------------------------------
function new_url_menu_Callback(hObject, eventdata, handles)
% hObject    handle to new_url_menu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

    options = rslice_defaults;

    %
    % We can't use a fancy file diolog box for this.  
    prompt = 'Enter a new URL.' ;
    the_answer = inputdlg ( prompt );
    if isempty(the_answer)
        %
        % {} if the user hits cancel.  Do nothing.
        return
    end
    if isempty(the_answer{1})
        %
        % {} if the user hits OK with nothing in the box.  Do nothing.
        return
    end

    %
    % Do the appropriate default overrides.
    options.input_type = 'url';
    options.source = the_answer{1};

    rslice_initialize ( hObject, options );

    return


% --------------------------------------------------------------------
function zoom_back_menu_Callback(hObject, eventdata, handles)
% hObject    handle to zoom_back_menu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

    gdata = guidata ( hObject );

    %
    % Reset the axis limits back to the original values.
    % Have to do this because "un-zoom" seems broken on
    % solaris.
    set ( handles.horizontal_slice_axis, 'XLim', gdata.original_xlim );
    set ( handles.horizontal_slice_axis, 'YLim', gdata.original_ylim );
    return


% --------------------------------------------------------------------
function velocity_overlay_tag_Callback(hObject, eventdata, handles)
% hObject    handle to velocity_overlay_tag (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

    rslice_data = guidata ( hObject );

    %
    % Is the figure window still there?
    % If not, recreate it.
    try
        get ( rslice_data.hvoc_figure, 'Visible' );
    catch
        rslice_data.hvoc_figure = hvo;

        %
        % The hvoc figure needs to be able to access the rslice_data object.
        hvoc_data.parent = hObject;
        guidata ( rslice_data.hvoc_figure, hvoc_data );
    end



    rslice_velocity_overlay_redraw ( hObject );
    return



% --------------------------------------------------------------------
function vslice_velocity_menu_Callback(hObject, eventdata, handles)
% hObject    handle to vslice_velocity_menu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

    %
    % Let the user define a new vslice line, retrieve the data
    % on that line, and render it.
    vslice_options.get_new_line = 1;
    vslice_options.retrieve_new_data = 1;
    rslice_vslice_velocity_redraw ( hObject, vslice_options );


    return


% --- Executes on button press in rewind_pushbutton_back_pushbutton.
function rewind_pushbutton_back_pushbutton_Callback(hObject, eventdata, handles)
% hObject    handle to rewind_pushbutton_back_pushbutton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% --- Executes on button press in rewind_pushbutton_back_pushbutton.
function step_back_pushbutton_Callback(hObject, eventdata, handles)
% hObject    handle to rewind_pushbutton_back_pushbutton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

    rslice_step_back ( hObject, handles );
    return

% --- Executes on button press in rewind_pushbutton.
function rewind_pushbutton_Callback(hObject, eventdata, handles)
% hObject    handle to rewind_pushbutton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

    rslice_rewind ( hObject, handles );
    return

% --- Executes on button press in step_forward_pushbutton.
function step_forward_pushbutton_Callback(hObject, eventdata, handles)
% hObject    handle to step_forward_pushbutton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

    rslice_step_forward ( hObject, handles );
    return


% --- Executes on button press in fastforward_pushbutton.
function fastforward_pushbutton_Callback(hObject, eventdata, handles)
% hObject    handle to fastforward_pushbutton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


    rslice_fastforward ( hObject, handles );
    return


% --- Executes on button press in stop_animation_button.
function stop_animation_button_Callback(hObject, eventdata, handles)
% hObject    handle to stop_animation_button (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

    set ( handles.stop_animation_button, 'UserData', 1 );

return


% --------------------------------------------------------------------
function Print_tag_Callback(hObject, eventdata, handles)
% hObject    handle to Print_tag (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

    printdlg;


% --------------------------------------------------------------------
function Toggle_clim_autoscale_Callback(hObject, eventdata, handles)
% hObject    handle to Toggle_clim_autoscale (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

    rslice_toggle_clim_autoscale ( hObject, handles );
    return



%--------------------------------------------------------------------------
function rslice_set_varmenu( arg )
% RSLICE_SET_VARMENU:  Create the menu list of variables.
%
%
% USAGE:  rslice_set_varmenu ( gcbo );
%
% PARAMETERS:
% Input:
%     gcbo:  Optional. 
%         Should be the current callback object.  This means that you
%         should be careful about calling this from the command line.
%
% If there is no "u" and "v" variables, then unset the velocity overlay
% menu
%
% Calls:
%     rslice_message
% Called By:
%


if nargin == 1
    gcbo = arg;
end
gdata = guidata ( gcbo );

if gdata.verbose > 0
    rslice_message ( sprintf ( '%s', mfilename ) );
end

handles = guihandles ( gcbo );

%
% Get rid of all the old ones
% For some reason we need to keep the last one as an empty place
% holder.  Otherwise I can't add any at all.
ch = get ( handles.variable_menu, 'Children' );
delete ( ch(1:end-1) );


netcdf_file_info = nc_info ( gdata.fileResource );
Dataset = netcdf_file_info.Dataset;


%
% Count the number of usable datasets
num_usable_vars = 0;
num_vars = length(Dataset );

usable_dataset = [];

first_non_grid_variable = 1;
usable_dataset = cell(num_vars,1);
for j = 1:num_vars

    % Skip certain variables.
    switch ( Dataset(j).Name )
        case { 'lon_rho', 'lat_rho', 'lon_u', 'lat_u', 'lon_v', 'lat_v' }
            continue
    end

    %
    % If we specified a restricted list of variables from the 
    % command line, then we should ignore anything else.
    if isfield ( gdata, 'restricted_varlist' )
        did_not_find_it = 1;
        for k = 1:numel(gdata.restricted_varlist)
            if strcmp ( gdata.restricted_varlist{k}, Dataset(j).Name )
                did_not_find_it = 0;
            end
        end

        if did_not_find_it
            continue;
        end
    end

    
    dim_type = rslice_classify_variable ( Dataset(j) );
    switch ( dim_type )
        case { 'YX', 'ZYX' }

            % Have we excluded grid variables?
            if gdata.load_time_series_variables_only
                continue
            else

                if first_non_grid_variable
                    gdata.default_variable = Dataset(j).Name;
                    first_non_grid_variable = 0;
                end

                num_usable_vars = num_usable_vars + 1;
                usable_dataset{num_usable_vars} = Dataset(j).Name;
            end

        case { 'TZYX', 'TYX' }

            num_usable_vars = num_usable_vars + 1;
            usable_dataset{num_usable_vars} = Dataset(j).Name;

    end
end
usable_dataset(num_usable_vars+1:end) = [];

if isempty(usable_dataset)
    error ( '%s:  No usable datasets were found.\n', mfilename );
end
%
% Store the list of variables.
gdata.varlist = usable_dataset;

    
%
% If we only found a small number of usable datasets, then go ahead
% and put them into the Variable menu.
h = zeros(num_usable_vars,1);
if num_usable_vars < gdata.max_num_usable_vars
    for j = 1:num_usable_vars
    
        callback_string = sprintf ( 'rslice_set_new_variable( gcbo, ''%s'')', gdata.varlist{j} );
        h(j) = uimenu ( handles.variable_menu, ...
            'Callback', callback_string, ...
            'Enable', 'on', ...
            'Label', gdata.varlist{j}, ...
            'Tag', [gdata.varlist{j} '_var_menu'], ...
            'Visible', 'on' );

    end

end

%
% And save the variable list.
guidata ( gcbo, gdata );
return




%-------------------------------------------------------------------------
function rslice_handle_new_timestep ( hObject, eventdata, handles, new_timestep )
% RSLICE_HANDLE_NEW_TIMESTEP:  set a new timestep for rslice
%

gdata = guidata ( hObject );

if ischar(new_timestep)
    new_timestep = str2double(new_timestep);
end


%
% Check to make sure that the timestep is valid.  If not, then set it 
% to whichever extrema to which it is closest.
if isnan ( new_timestep )

    %
    % Ok, the user did something bad.  Set the timestep back to 
    % zero.
    new_timestep = 0;

elseif ( new_timestep < 0 )
    new_timestep = 0;
    gdata.timestep = 0;
elseif ( new_timestep >= gdata.max_num_timesteps )
    new_timestep = gdata.max_num_timesteps - 1;
    gdata.timestep = gdata.max_num_timesteps - 1;
else
    %
    % No fractions.
    gdata.timestep = floor(new_timestep);
end

%
% This only changes things if the value specified by the
% user was not a valid discrete timestep index.
set ( handles.timestep_edit, 'String', num2str(gdata.timestep) );

%
% If we are using a list of netcdf files, then check if we are to
% advance into another file
if strcmp ( gdata.input_type, 'directory' )
    ind = find ( (new_timestep >= gdata.ncfile_start_index) & (new_timestep <= gdata.ncfile_stop_index) );
    gdata.ncfile_index = ind;
end


guidata ( hObject, gdata );

rslice_hslice_redraw ( hObject );

%
% Is the vslice figure visible?  If so, then issue a redraw.
vis = get ( gdata.vslice_figure, 'Visible' );
if strcmp ( vis, 'on' )
    vslice_options.get_new_line = 0;
    vslice_options.retrieve_new_data = 1;
    rslice_vslice_redraw ( hObject, vslice_options );
end


%
% Is the vslice velocity figure visible?  If so, then issue a redraw.
vis = get ( gdata.vslice_vel_figure, 'Visible' );
if strcmp ( vis, 'on' )
    vslice_options.get_new_line = 0;
    vslice_options.retrieve_new_data = 1;
    rslice_vslice_velocity_redraw ( hObject, vslice_options );
end


%-------------------------------------------------------------------------
function options = rslice_defaults 
% RSLICE_DEFAULTS:  sets up default startup options
%

options.default_variable = 'h';
options.input_type = [];

%
% Load only time series variables by default.  Spatial-only variables
% can also be included by specifying '-spatial' at the command line
% startup.
options.load_time_series_variables_only = true;

options.roms_regex = [];
options.verbose = [];

return

%-------------------------------------------------------------------------
function options = parse_rslice_command_line(options,varargin)
% Parse the user-supplied command line inputs.  Store them
% in a structure called "options".
%
% Fields of options structure:
%     input_type:
%         One of four possibilities.
%           'directory' :  
%               Use a collection of NetCDF files all in the same 
%               directory.
%           'file' :
%               Use a single NetCDF file.
%           'url' :
%               Use an OpenDAP dataset.  Works the same as a file, but
%               The user MUST have an opendap-enabled mexnc available.
%     regex:
%           Regular expression to be used to par down the list of
%           files to be used when the input_type is 'directory'
%     source:
%           If the input type is 'file', then this is the file (duh)
%           the user wants to be used.
%           If the input type is 'url', then this is the url (duh)
%           the user wants to be used.
%           If the input type is 'directory', then this is the directory (duh)
%           the user wants to be used.   The directory is later scanned
%           to get a full list of files.
%     verbose:
%           0 or 1.  If 1, then additional messages may be printed out
%           from the command line window.
%     vslice:
%           An array of two columns of x and y data that the user wants
%           to use as an initial vslice line.
%         
nargs = length(varargin);
%for j = 1:length(varargin)
j = 1;
try
    while j < nargs
    
        if findstr(varargin{j},'=')
            [current_option,rest] = strtok ( varargin{j},'=' ); %#ok<NASGU>
        else
            current_option = varargin{j};
        end
    
    
        switch ( current_option ) 
        case { 'directory' }
            options.input_type = 'directory';
            options.source = varargin{j+1};
            j = j + 1;
        case { 'file' }
            options.input_type = 'file';
            options.source = varargin{j+1};
            j = j + 1;
        case { 'nvarcutoff' }
            options.nvarcutoff = varargin{j+1};
            j = j + 1;
        case { 'regexp' }
            options.regex = varargin{j+1};
            j = j + 1;
        case { 'spatial' }
            options.load_time_series_variables_only = varargin{j+1};
            j = j + 1;
        case { 'time_dimension' }
            options.time_dimension = varargin{j+1};
            j = j + 1;
        case { 'time_variable' }
            options.record_variable = varargin{j+1};
            j = j + 1;
        case 'url'
            options.input_type = 'url';
            options.source = varargin{j+1};
            j = j + 1;
        case 'variable'
            options.default_variable = varargin{j+1};
            j = j + 1;
        case 'varlist'
            if iscell(varargin{j+1})
                error ( 'varlist option must be a cell array.' );
            end
            options.restricted_varlist = varargin{j+1};
            j = j + 1;
        case { 'verbose' }
            options.verbose = varargin{j+1};
            j = j + 1;
        case 'vslice'
            if ~strcmp(class(varargin{j+1}),'double')
                error ( 'vslice option must be numeric.' );
            end
            options.vslice = varargin{j+1};
            j = j + 1;
        case 'vslice_vel'
            if ~strcmp(class(varargin{j+1}),'double')
                error ( 'vslice_vel option must be numeric.' );
            end
            options.vslice_vel = varargin{j+1};
            j = j + 1;
        otherwise
            error ( '%s:  Unhandled option %s.\n', mfilename, current_option );
        end
    
        j = j + 1;
    
    end
catch
    rslice_usage;
    rethrow(lasterror);
end


%-------------------------------------------------------------------------
function rslice_usage()
% RSLICE_USAGE:  Prints a general usage message

fprintf('RSLICE Usage:\n' );
fprintf('    RSLICE(''PropertyName'',PropertyValue,...)\n' );
fprintf('                                              \n' );
fprintf('    where the ''PropertyName'' and ''PropertyValue'' pairs can be given as\n' );
fprintf('    follows.                                                              \n' );
fprintf('                                                                           \n' );
fprintf('   ''directory'':                                                          \n' );
fprintf('        The ROMS input is a set of files in the given directory.  This     \n' );
fprintf('        property must be accompanied by ''regexp'' (see below).            \n' );
fprintf('   ''file'':                                                               \n' );
fprintf('        The PropertyValue is the path to a single local netCDF file.  This \n' );
fprintf('        is usually the only PropertyName/PropertyValue pair you need to    \n' );
fprintf('        provide.                                                           \n' );
fprintf('   ''regexp'':                                                             \n' );
fprintf('        A regular expression that describes the set of netCDF files to be  \n' );
fprintf('        used as input.  Used in conjunction with ''directory''.  This      \n' );
fprintf('        allows rslice to use just a subset of all the netCDF files that    \n' );
fprintf('        may reside in the given directory.  See also REGEXP.               \n' );
fprintf('   ''spatial'':                                                            \n' );
fprintf('        If given as 1, then non-temporal variables, such as ''lon_rho''    \n' );
fprintf('        for example, will be loaded as well.  Default is 0.  If given, the \n' );
fprintf('        PropertyValue must be numeric.                                     \n' );
fprintf('   ''time_dimension'':                                                     \n' );
fprintf('        The PropertyValue is the name of the dimension upon which the time \n' );
fprintf('        variable is defined.  The default is ''ocean_time''.               \n' );
fprintf('   ''time_variable'':                                                      \n' );
fprintf('        The PropertyValue is the name of the time variable.  The default is\n' );
fprintf('        ''ocean_time''.                                                    \n' );
fprintf('   ''url'':                                                                \n' );
fprintf('        The Roms input is an OPeNDAP URL.  In order for this to work,      \n' );
fprintf('        SNCTOOLS must be configured for OPeNDAP access.                    \n' );
fprintf('   ''variable'':                                                           \n' );
fprintf('        Specifies a default variable to be displayed when rslice first     \n' );
fprintf('        starts.                                                            \n' );
fprintf('   ''varlist'':                                                            \n' );
fprintf('        Specifies a subset of variables that rslice will use.  All others  \n' );
fprintf('        will be ignored.  The PropertyValue here must be a cell array.     \n' );
fprintf('   ''verbose'':                                                            \n' );
fprintf('        If given as 1, then a lot of debugging information will be printed.\n' );
fprintf('        The default is 0.  This PropertyValue must be numeric.             \n' );
fprintf('   ''vslice'':                                                             \n' );
fprintf('        The PropertyValue is an Nx2 array of surface coordinates to use as \n' );
fprintf('        a set of control points that defines a vertical slice line.        \n' );
fprintf('   ''vslice_vel'':                                                         \n' );
fprintf('        The PropertyValue is an Nx2 array of surface coordinates to use as \n' );
fprintf('        a set of control points that defines a vertical slice line of      \n' );
fprintf('        velocity.                                                          \n' );



%-------------------------------------------------------------------------------
function enable_or_disable_velocity_overlay ( hObject, arg )
% ENABLE_OR_DISABLE_VELOCITY_OVERLAY:
%
% There are situations where the user should not have the option of
% even trying to create a velocity overlay.
%
%     1.  There is no "u" or "v" dataset in the netcdf file.  We need
%         to actually check the netcdf file in this case.
%



handles = guihandles ( hObject );

%
% If the 2nd argument is numeric and zero, then just disable it now.
if isnumeric ( arg )
    if arg == 0
        set ( handles.velocity_overlay_tag, 'Enable', 'off' );
        set ( handles.vslice_velocity_menu, 'Enable', 'off' );
        return
    end
else
    ncfile = arg;
end



have_u = 0;
have_v = 0;

%
% Check for both U and V
if nc_isvar ( ncfile, 'u' )
    have_u = 1;
end
%original -> if nc_isvar ( ncfile, 'u' )
if nc_isvar ( ncfile, 'v' )
    have_v = 1;
end

% Check for both U and V
%flc% added to plot 2D current vector 
if nc_isvar ( ncfile, 'ubar' )
    have_u = 1;

end
if nc_isvar ( ncfile, 'vbar' )
    have_v = 1;
end


if have_u & have_v 
    set ( handles.velocity_overlay_tag, 'Enable', 'on' );
else
    set ( handles.velocity_overlay_tag, 'Enable', 'off' );
end




%-------------------------------------------------------------------------
function rdata_out = rslice_determine_timestep_info ( rdata )
% RSLICE_DETERMINE_TIMESTEP_INFO:  retrieve all the timesteps and associated metadata
%
% PARAMETERS
% Input:
%     rdata:  metadata for rslice
% Output:
%     rdata_out:  rdata plus addition fields
%         ocean_time:  
%             All time values from the dataset.  Units are matlab native datenum. 
%         max_num_timesteps:           
%             length of ocean time.  I don't think this is really 
%             needed anymore.
%         ncfile_start_index, ncfile_stop_index:
%             This is needed in the case that the input is a directory
%             of files.  Each entry corresponds to one netcdf file and
%             gives its starting and stopping index in the overall 
%             time record.

rdata_out = rdata;

%
% How many timesteps?
switch rdata.input_type
case 'directory'
    ncfile =  rdata.ncfile_list{rdata.ncfile_index};

    max_num_timesteps = 0;
    n = length(rdata.ncfile_list);
    start_index = zeros(n,1);
    stop_index = zeros(n,1);
    last_index = -1;
    ocean_time = zeros(n,1);

    time_units = nc_attget ( rdata.fileResource, rdata.record_variable, 'units' );
    for j = 1:length(rdata.ncfile_list)

        this_ocean_time = nc_varget ( rdata.fileResource, rdata.record_variable );
        num_times = length(this_ocean_time);
        max_num_timesteps = max_num_timesteps + num_times;
        start_index(j) = last_index + 1;
        stop_index(j) = start_index(j) + num_times - 1;
        last_index = stop_index(j);

        ocean_time(start_index(j)+1:stop_index(j)+1) = this_ocean_time;

    end

case { 'file', 'url' }

    if nc_isvar ( rdata.fileResource, rdata.record_variable )
        ocean_time = nc_varget ( rdata.fileResource, rdata.record_variable );
        time_units = nc_attget ( rdata.fileResource, rdata.record_variable, 'units' );
    else

	error('RSLICE:noTimeVariable', ...
		'''%s'' could not be located.  Please specify the time variable.', ...
		rdata.record_variable );

    end
    num_times = length(ocean_time);
    max_num_timesteps = num_times;
    start_index = 0;
    stop_index = num_times-1;


otherwise
    error ( 'unknown rdata.location type ''%s''.', rdata.location );
end

ocean_time = rslice_time2matd ( ocean_time, time_units );




rdata_out.max_num_timesteps = max_num_timesteps;
rdata_out.ncfile_start_index = start_index;
rdata_out.ncfile_stop_index = stop_index;
rdata_out.ocean_time = ocean_time;

return





%------------------------------------------------------------------------------
function matd = rslice_time2matd ( ocean_time, base_date )
% RSLICE_TIME2MATD:  convert netcdf times to matlab-native times
%
% PARAMETERS:
% Input:
%     ocean_time:
%         all time instances as read from the netcdf file(s)
%     base_date:
%         the units string from the netcdf file(s)
% Output:
%     matd:
%         matlab datenum equivalents of all the ocean time values.
%         This depends upon correctly parsing the units string.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% $Name: rslice-0_9_2 $
% $Id: rslice_time2matd.m,v 1.1 2005/12/30 18:17:30 jevans Exp $
% AUTHOR:  johnevans@acm.org
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%







[time_units,r] = strtok ( base_date, ' ' );
[since,some_date] = strtok ( r, ' ' );
matd = [];
if length(some_date) > 0
    [f,date_token_count] = sscanf ( some_date, '%f-%f-%f %f:%f:%f' );
    if ( date_token_count == 6 )
        matd = datenum ( f(1), f(2), f(3), f(4), f(5), f(6) );
        switch ( time_units )
        case 'days'
            matd = matd + ocean_time;
        case 'hours'
            matd = matd + ocean_time/24;
        case 'minutes'
            matd = matd + ocean_time/1440;
        case 'seconds'
            matd = matd + ocean_time/86400;
        otherwise
            msg = sprintf ( '%s:  unhandled time units %s.\n', mfilename, time_units );
            rslice_message ( msg );
        end
    else
        msg = sprintf ( '%s:  did not read 6 values from %s.\n', mfilename, some_date );
        rslice_message ( msg );

    end
else
    msg = sprintf ( '%s:  could not parse %s.\n', mfilename, base_date );
    rslice_message ( msg );
end


return;



%--------------------------------------------------------------------------
function rslice_fastforward ( hObject, handles )
% RSLICE_FASTFORWARD:  moves the timestep forward to the end.
%
% Calls: 
%     rslice_hslice_redraw, rslice_vslice_redraw, 
%     rslice_velocity_vslice_redraw
% Called by:  
%     rslice


gdata = guidata ( hObject );

old_timestep = str2double ( get (handles.timestep_edit, 'String' ) );

for j = old_timestep:(gdata.max_num_timesteps - 1)

    gdata = guidata ( hObject );

    %
    % Was the Stop button pushed?
    stop_animation = get ( handles.stop_animation_button, 'UserData' );
    if ( stop_animation )
        
        %
        % Reset it so we can hit fastforward and rewind again.
        set ( handles.stop_animation_button, 'UserData', 0 );

        break;

    end


    old_timestep = str2double ( get (handles.timestep_edit, 'String' ) );
    new_timestep = j;



    %
    % Check to make sure that the timestep is valid.  If not, then set it 
    % to whichever extrema to which it is closest.
    if isnan ( new_timestep )

        %
        % Ok, the user did something bad.  Set the timestep back to 
        % zero.
        new_timestep = old_timestep;

    elseif ( new_timestep < 0 )
        new_timestep = 0;
    elseif ( new_timestep >= gdata.max_num_timesteps )
        new_timestep = gdata.max_num_timesteps - 1;
    else
        %
        % No fractions.
        new_timestep = floor(new_timestep);
    end

    gdata.timestep = new_timestep;

    %
    % This only changes things if the value specified by the
    % user was not a valid discrete timestep index.
    set ( handles.timestep_edit, 'String', num2str(gdata.timestep) );

    %
    % If we are using a list of netcdf files, then check if we are to
    % advance into another file
    if strcmp ( gdata.input_type, 'directory' )
        ind = find ( (new_timestep >= gdata.ncfile_start_index) & (new_timestep <= gdata.ncfile_stop_index) );
        gdata.ncfile_index = ind;
    end


    guidata ( hObject, gdata );

    rslice_hslice_redraw;

    %
    % Is the vslice figure visible?  If so, then issue a redraw.
    vis = get ( gdata.vslice_figure, 'Visible' );
    if strcmp ( vis, 'on' )
        vslice_options.get_new_line = 0;
        vslice_options.retrieve_new_data = 1;
        rslice_vslice_redraw ( hObject, vslice_options );
    end


    %
    % Is the vslice velocity figure visible?  If so, then issue a redraw.
    vis = get ( gdata.vslice_vel_figure, 'Visible' );
    if strcmp ( vis, 'on' )
        vslice_options.get_new_line = 0;
        vslice_options.retrieve_new_data = 1;
        rslice_vslice_velocity_redraw ( hObject, vslice_options );
    end

    drawnow;

end

return

%-------------------------------------------------------------------------
function rslice_rewind ( hObject, handles )
% RSLICE_REWIND:  moves the timestep continuously back to zero.
%
% Calls: 
%     rslice_hslice_redraw, rslice_vslice_redraw, 
%     rslice_velocity_vslice_redraw
% Called by:  
%     rslice

old_timestep = str2double ( get (handles.timestep_edit, 'String' ) );

for j = old_timestep:-1:0
    
    gdata = guidata ( hObject );

    %
    % Was the Stop button pushed?
    stop_animation = get ( handles.stop_animation_button, 'UserData' );
    if ( stop_animation )
        
        %
        % Reset it so we can hit fastforward and rewind again.
        set ( handles.stop_animation_button, 'UserData', 0 );

        break;

    end



    old_timestep = str2double ( get (handles.timestep_edit, 'String' ) );
    new_timestep = j;

    %
    % Check to make sure that the timestep is valid.  If not, then set it 
    % to whichever extrema to which it is closest.
    if isnan ( new_timestep )

        %
        % Ok, the user did something bad.  Set the timestep back to 
        % zero.
        new_timestep = old_timestep;

    elseif ( new_timestep < 0 )
        new_timestep = 0;
    elseif ( new_timestep >= gdata.max_num_timesteps )
        new_timestep = gdata.max_num_timesteps - 1;
    else
        %
        % No fractions.
        new_timestep = floor(new_timestep);
    end

    gdata.timestep = new_timestep;



    %
    % This only changes things if the value specified by the
    % user was not a valid discrete timestep index.
    set ( handles.timestep_edit, 'String', num2str(gdata.timestep) );

    %
    % If we are using a list of netcdf files, then check if we are to
    % advance into another file
    if strcmp ( gdata.input_type, 'directory' )
        ind = find ( (new_timestep >= gdata.ncfile_start_index) & (new_timestep <= gdata.ncfile_stop_index) );
        gdata.ncfile_index = ind;
    end


    guidata ( hObject, gdata );

    rslice_hslice_redraw;

    %
    % Is the vslice figure visible?  If so, then issue a redraw.
    vis = get ( gdata.vslice_figure, 'Visible' );
    if strcmp ( vis, 'on' )
        vslice_options.get_new_line = 0;
        vslice_options.retrieve_new_data = 1;
        rslice_vslice_redraw ( hObject, vslice_options );
    end


    %
    % Is the vslice velocity figure visible?  If so, then issue a redraw.
    vis = get ( gdata.vslice_vel_figure, 'Visible' );
    if strcmp ( vis, 'on' )
        vslice_options.get_new_line = 0;
        vslice_options.retrieve_new_data = 1;
        rslice_vslice_velocity_redraw ( hObject, vslice_options );
    end

    drawnow;

end
return



%-------------------------------------------------------------------------
function rslice_step_back ( hObject, handles )
% RSLICE_STEP_BACK:  moves the timestep back one unit.
%
% Calls: 
%     rslice_hslice_redraw, rslice_vslice_redraw, 
%     rslice_velocity_vslice_redraw
% Called by:  
%     rslice

    gdata = guidata ( hObject );

    old_timestep = str2double ( get (handles.timestep_edit, 'String' ) );
    new_timestep = old_timestep - 1;



    %
    % Check to make sure that the timestep is valid.  If not, then set it 
    % to whichever extrema to which it is closest.
    if isnan ( new_timestep )

        %
        % Ok, the user did something bad.  Set the timestep back to 
        % zero.
        new_timestep = old_timestep;

    elseif ( new_timestep < 0 )
        new_timestep = 0;
        gdata.timestep = 0;
    elseif ( new_timestep >= gdata.max_num_timesteps )
        new_timestep = gdata.max_num_timesteps - 1;
        gdata.timestep = gdata.max_num_timesteps - 1;
    else
        %
        % No fractions.
        gdata.timestep = floor(new_timestep);
    end

    %
    % This only changes things if the value specified by the
    % user was not a valid discrete timestep index.
    set ( handles.timestep_edit, 'String', num2str(gdata.timestep) );

    %
    % If we are using a list of netcdf files, then check if we are to
    % advance into another file
    if strcmp ( gdata.input_type, 'directory' )
        ind = find ( (new_timestep >= gdata.ncfile_start_index) & (new_timestep <= gdata.ncfile_stop_index) );
        gdata.ncfile_index = ind;
    end


    guidata ( hObject, gdata );

    rslice_hslice_redraw;

    %
    % Is the vslice figure visible?  If so, then issue a redraw.
    vis = get ( gdata.vslice_figure, 'Visible' );
    if strcmp ( vis, 'on' )
        vslice_options.get_new_line = 0;
        vslice_options.retrieve_new_data = 1;
        rslice_vslice_redraw ( hObject, vslice_options );
    end


    %
    % Is the vslice velocity figure visible?  If so, then issue a redraw.
    vis = get ( gdata.vslice_vel_figure, 'Visible' );
    if strcmp ( vis, 'on' )
        vslice_options.get_new_line = 0;
        vslice_options.retrieve_new_data = 1;
        rslice_vslice_velocity_redraw ( hObject, vslice_options );
    end


return


%--------------------------------------------------------------------------
function rslice_step_forward ( hObject, handles )
% RSLICE_STEP_FORWARD:  moves the timestep forward one unit.
%
% Calls: 
%     rslice_hslice_redraw, rslice_vslice_redraw, 
%     rslice_velocity_vslice_redraw
% Called by:  
%     rslice

    gdata = guidata ( hObject );

    old_timestep = str2double ( get (handles.timestep_edit, 'String' ) );
    new_timestep = old_timestep + 1;



    %
    % Check to make sure that the timestep is valid.  If not, then set it 
    % to whichever extrema to which it is closest.
    if isnan ( new_timestep )

        %
        % Ok, the user did something bad.  Set the timestep back to 
        % zero.
        new_timestep = old_timestep;

    elseif ( new_timestep < 0 )
        new_timestep = 0;
        gdata.timestep = 0;
    elseif ( new_timestep >= gdata.max_num_timesteps )
        new_timestep = gdata.max_num_timesteps - 1;
        gdata.timestep = gdata.max_num_timesteps - 1;
    else
        %
        % No fractions.
        gdata.timestep = floor(new_timestep);
    end

    %
    % This only changes things if the value specified by the
    % user was not a valid discrete timestep index.
    set ( handles.timestep_edit, 'String', num2str(gdata.timestep) );

    %
    % If we are using a list of netcdf files, then check if we are to
    % advance into another file
    if strcmp ( gdata.input_type, 'directory' )
        ind = find ( (new_timestep >= gdata.ncfile_start_index) & (new_timestep <= gdata.ncfile_stop_index) );
        gdata.ncfile_index = ind;
    end


    guidata ( hObject, gdata );

    rslice_hslice_redraw;

    %
    % Is the vslice figure visible?  If so, then issue a redraw.
    vis = get ( gdata.vslice_figure, 'Visible' );
    if strcmp ( vis, 'on' )
        vslice_options.get_new_line = 0;
        vslice_options.retrieve_new_data = 1;
        rslice_vslice_redraw ( hObject, vslice_options );
    end


    %
    % Is the vslice velocity figure visible?  If so, then issue a redraw.
    vis = get ( gdata.vslice_vel_figure, 'Visible' );
    if strcmp ( vis, 'on' )
        vslice_options.get_new_line = 0;
        vslice_options.retrieve_new_data = 1;
        rslice_vslice_velocity_redraw ( hObject, vslice_options );
    end


    return


%--------------------------------------------------------------------------
function files = rnt_getfilenames(direc,rexp, gdata)
% RNT_GETFILENAMES: retrieves files in a directory matching a regular expression
%
% After retrieving matching files, they are sorted by time.  
%
% USAGE:  files = rnt_getfilenames (direc,regular_expression);
%
% PARAMETERS:
% Input:
%     direc:  
%         directory path
%     regular_expression:
%         a regular expression suitable to be used with the REGEXP 
%         function.  Make sure you are fully versed with REGEXP!
% Output:
%     files:
%         Cell array of all files (full pathnames) that matched the
%         regular expression.
%
% Example:
%     direc = '.'
%     files = rnt_getfilenames( '.','his');
%     files = rnt_getfilenames( '.','his.*_008\d\.nc');
%
%     The first case would return all the history files in the current
%     directory.  The second example would return only those files
%     enumerated '0080', '0081', '0082', ... '0089'.
%

files = [];

if ~exist ( direc, 'dir' )
    msg = sprintf ( '%s:  directory ''%s'' does not exist.\n', mfilename, direc );
    error ( msg );
end

d_struct = dir ( direc );


%
% This keeps track of how many files we matched.
match_count = 0;

%
% go thru the directory listing and try to match them up
for j = 1:length(d_struct)

    %
    % skip directories, of course
    if ( d_struct(j).isdir )
        continue
    end

    start_match = regexp ( d_struct(j).name, rexp );
    if ~isempty(start_match)
        candidate = sprintf ( '%s%s%s', direc, filesep,  d_struct(j).name );

        [ncid, status] = mexnc ( 'open', candidate, nc_noclobber_mode );
        if ( status == 0 )
            match_count = match_count + 1;
            mexnc ( 'close', ncid );
            files{match_count,1} = candidate;
        else
            msg = sprintf ( 'Could not open %s...\n', candidate );
            rslice_message ( msg );
        end
    end

end

if length(files) == 0
    return
end

%
% Now sort by time.  
for j = 1:length(files)
    t = nc_varget ( gdata.fileResource, gdata.record_variable );
    start_time(j,1) = t(1);
    end_time(j,1) = t(end);
end

[dud,sort_inds] = sort ( start_time );

files = files(sort_inds);




%---------------------------------------------------------------------------
function usable_dataset = rslice_file_datasets( gdata )


netcdf_file_info = nc_info ( gdata.fileResource );
Dataset = netcdf_file_info.Dataset;


%
% Count the number of usable datasets
num_usable_vars = 0;
num_vars = length(Dataset );

usable_dataset = [];

first_non_grid_variable = 1;
for j = 1:num_vars


    %
    % Skip certain variables.
    switch ( Dataset(j).Name )
    case { 'lon_rho', 'lat_rho', 'lon_u', 'lat_u', 'lon_v', 'lat_v' }
        continue
    end

    dim_type = rslice_classify_variable ( Dataset(j) );
    switch ( dim_type )
    case { 'YX', 'ZYX' }
        continue;

    case { 'TZYX', 'TYX' }

        num_usable_vars = num_usable_vars + 1;
        usable_dataset{num_usable_vars} = Dataset(j).Name;

    end
end

if length(usable_dataset) == 0
    error ( '%s:  No usable datasets were found.\n', mfilename );
end

return





%--------------------------------------------------------------------------
function rslice_toggle_clim_autoscale ( hObject, handles )
% RSLICE_TOGGLE_CLIM_AUTOSCALE:  flip the autoscale switch.  Default
% is off.

gdata = guidata ( hObject );

gdata.autoscale_clims = 1 - gdata.autoscale_clims;

%
% Reset the label
switch ( gdata.autoscale_clims )
case 0
    set ( gcbo, 'Label', 'Autoscale Color Limits' );
case 1
    set ( gcbo, 'Label', 'Turn Off Color Limit Autoscaling' );
end

%
% And finally, save it.
guidata ( hObject, gdata );

return



%--------------------------------------------------------------------------
function coordsys = classify_grid_coordsys(gdata)
% Classify as either 'geographic' or 'xy'
has_lat_rho = false; has_lon_rho = false; has_x_rho = false; has_y_rho = false;
for j = 1:numel(gdata.file_info.Dataset)
    if strcmp(gdata.file_info.Dataset(j).Name,'lat_rho')
        has_lat_rho = true;
    end
    if strcmp(gdata.file_info.Dataset(j).Name,'lon_rho')
        has_lon_rho = true;
    end
    if strcmp(gdata.file_info.Dataset(j).Name,'x_rho')
        has_x_rho = true;
    end
    if strcmp(gdata.file_info.Dataset(j).Name,'y_rho')
        has_y_rho = true;
    end
end
if has_lat_rho && has_lon_rho
    coordsys = 'geographic';
elseif has_x_rho && has_y_rho
    coordsys = 'xy';
else
    coordsys = 'ij';
end

return



