% UNPACK  Part of the DODS data browser (browse.m)
%
% UNPACK  unpacks the returned arrays in the main workspace
%         and puts them into recognizable and distinct variable
%         names based on the information in the archive.m
%
%
%            Deirdre Byrne, The Island Institute, 7 April 1997
%                 dbyrne@islandinstitute.org
%

% The preceding empty line is important.
%
% $Id: unpack.m,v 1.15 2000/03/23 02:53:17 dbyrne Exp $

% $Log: unpack.m,v $
% Revision 1.15  2000/03/23 02:53:17  dbyrne
%
%
% Rewrote unpack.m from scratch.  Much shorter, better commented,
% more robust now.  In particular, it now checks for blank names,
% zero-size arguments, removes these all handily, and distinguishes
% between the potential number of plots and the returned number
% of URLs.  Plotscript.m and dispmenu.m changed accordingly to
% use num_plots instead of num_urls.  -- dbyrne 00/03/22
%
% Revision 1.14  2000/03/17 08:42:52  dbyrne
%
%
% Changed the way the display args and the listargs are determined.
% I hope it works.  The old way had a bug in that if empty names
% were returned, these were left on the list and went thru whole
% unpack sequence.  -- dbyrne 00/03/17
%
% Revision 1.13  1999/07/21 16:46:30  dbyrne
%
%
% Fixed bug in clearing variables empty in all URLs. -- dbyrne 99/07/21
%
% Revision 1.12  1999/07/19 22:38:22  dbyrne
%
%
% Fixed a bug that carried over datarange from previous datasets!  Nasty.
% dbyrne 99/07/19
%
% Revision 1.11  1999/07/19 19:02:52  dbyrne
%
%
% Dataset scroll window is now modal -- will not show other datasets once
% one is chosen.  Also, dataset name colors changed to black for unselected,
% and choice of black or light gray once selected (depending on dataset color).
%
% Fixed a bug in plotscript that was using an incorrect index into the
% data range (used in scaling images).
%
% dbyrne 99/07/19
%
% Revision 1.10  1999/05/13 03:09:54  dbyrne
%
%
% Added Acknowledge and Data_Use_Policy to archive.m.  Fixed getxxx functions
% to use dodsmsg instead of stdout for errors/info.  Made ChangeLog so that it's
% in Emacs format.  All changes for release 3.0.0 -- dbyrne 99/05/12
%
% Revision 1.17  1999/05/13 00:53:06  root
% Lots of changes for version 3.0.0 of browser.
%
% Revision 1.16  1998/11/26 07:59:35  root
% Fixed a bug in unpack that incorrectly eliminate names of
% properly returned variables.
%
% Revision 1.15  1998/10/12 21:10:27  root
% Modified to delete any variables which are empty in every URL in the request.
%
% Revision 1.14  1998/10/12 14:50:22  root
% checking for empty arguments!
%
% Revision 1.13  1998/09/13 14:59:24  root
% Fixed 'clear all Rxx_' once again.
%
% Revision 1.12  1998/09/12 15:28:41  root
% Made modifications necessary to let display menu be called numerous times.
%
% Revision 1.11  1998/09/12 11:20:17  root
% changing display menu
%
% Revision 1.10  1998/09/12 10:38:03  root
% Testing changes to input arguments for dispmenu.m
%
% Revision 1.9  1998/09/08 21:29:59  dbyrne
% Modified to unpack URLs as well as data.
%
% Revision 1.8  1998/09/08 16:04:20  dbyrne
% browse_get_variables and browse_display_choices too long for v4. Changed
% them to browse_getvariables and browse_dispchoices
%
% Revision 1.7  1998/09/04 10:02:12  dbyrne
% fixed up error messages.
%
% Revision 1.6  1998/09/04 08:41:03  dbyrne
% Fixed bug in 'addclear' call.
%
% Revision 1.5  1998/09/04 08:27:47  dbyrne
% Preparing to fix a bug in browse_data_list.
%
% Revision 1.4  1998/09/03 20:32:41  dbyrne
% CLeaning up multivariable plot items.
%
% Revision 1.3  1998/09/03 19:02:28  dbyrne
% *** empty log message ***
%
% Revision 1.2  1998/09/01 07:15:47  dbyrne
% beginning changes for output of multivariables
%
% Revision 1.1  1998/05/17 14:10:53  dbyrne
% *** empty log message ***
%
% Revision 1.1.1.1  1997/09/22 14:13:54  tom
% Imported Matlab GUI sources to CVS
%

if exist('browse_count') == 1
  if all(size(browse_count) == [1 1]) & size(browse_sizes,2) == 3
    % find out if all arguments are the same for each URL
    % why?  Because if this is the case, we will preserve
    % arguments which have a size of zero in only some of those
    % URLs because the display will still work!  In this case
    % we will remove only those arguments which are empty
    % in all of the URLs.
    %
    % If instead not all arguments are the same, we can randomly
    % delete any empty ones.

    % find the beginning of each URL -- these should always have
    % an index number of zero, (index number is index into 
    % datarange argument) because each URL starts with the
    % Acknowledgements and these have no datarange.  We also 
    % check that it is the first argument for the URL.  These
    % conditions may very well be redundant.
    browse_inx = find(browse_sizes(:,3) == 1 & browse_index == 0);
    browse_inx = [browse_inx(:); size(browse_sizes,1)+1];
    browse_num_urls = size(browse_inx,1)-1;
    browse_sameflag = 0;
    if browse_num_urls > 1
      if all(diff(browse_inx) == diff(browse_inx(1:2)))
	% each URL has same number of arguments returned
	% check if they have same names
	browse_sameflag = 1;
	for browse_j = 1:browse_inx(2)-1
	  browse_i = browse_inx(1:length(browse_inx)-1)+browse_j-1;
	  % this is a cheap shortcut to compare a lot of strings
	  if ~all(all(diff(abs(browse_names(browse_i,:))) == 0))
	    % goto "NOT SAME" routine
	    browse_num_plots = 1;
	    browse_sameflag = 0;
	    break
	  end
	end
      else
	% some URLs have an unlike number of arguments returned
	browse_sameflag = 0;
      end
    else
      browse_sameflag = 1;
      % there is only 1 URL, so checking argument consistency
      % between URLs is pointless
    end
    
    browse_empty = [];
    if browse_sameflag
      % only mark as empty arguments which are empty in ALL URLs
      for browse_j = 1:browse_inx(2)-1
	browse_i = browse_inx(1:length(browse_inx)-1)+browse_j-1;
	if all(browse_sizes(browse_i,1) == 0) | ...
	      all(browse_sizes(browse_i,2) == 0)
	  browse_empty = [browse_empty browse_i(:)'];
	end
      end
      browse_i = 1:size(browse_index,1);
      browse_j = find(~isin(browse_i,browse_empty));
      if ~isempty(browse_j)
	browse_names = browse_names(browse_j,:);
	browse_sizes = browse_sizes(browse_j,:);
	browse_index = browse_index(browse_j);
	browse_num_plots = browse_num_urls;
      end 

    else
      % mark as empty any arguments which are empty and tell the display
      % menu to only allow plotting of the first URL.
      browse_num_plots = 1;
      for browse_j = 1:size(browse_index,1)
	if any(browse_sizes(browse_j,1:2) == 0)
	  browse_empty = [browse_empty browse_j];
	end
      end
      browse_i = 1:size(browse_index,1);
      browse_j = find(~isin(browse_i,browse_empty));
      if ~isempty(browse_j)
	browse_names = browse_names(browse_j,:);
	browse_sizes = browse_sizes(browse_j,:);
	browse_index = browse_index(browse_j);
      end 
      % in this scenario, we might just have deleted
      % an entire URL.  Calculate number of URLs again.
      browse_num_urls = size(browse_inx,1)-1;
    end
    
    if browse_num_urls > 1 & browse_num_plots == 1
      dodsmsg([ 'Data from more than one URL have been returned', ...
	    ' to the workspace. However, it is only possible to ', ...
	    ' display the data from the first URL, as there appear ', ...
	    ' to be different variables for each URL.'])
    end

    browse_data_list = ''; 
    browse_dispargs = '';
    
    if isempty(browse_j)
      dodsmsg('This request generated no data')
    else
      % now recalculate location of the start of each URL
      % this is bad because it assumes acknowledgments
      % are still present -- they may been empty and thus
      % removed!  It would be better to keep track of what
      % gets wiped from the lists and recalculate browse_inx
      % based on that.
      browse_inx = find(browse_sizes(:,3) == 1 & browse_index == 0);
      browse_inx = [browse_inx(:); size(browse_sizes,1)+1];
    
      browse_listargs = '';
      browse_datarangeindex = [];
      % make a list for display menu.  Exclude Acknowledgments.
      % make a list for return message.  Add Return Count to names.
      for browse_i = 1:browse_inx(2)-1
	if ~isempty(deblank(browse_names(browse_i,:)))
	  if browse_index(browse_i) > 0 
	    browse_dispargs = str2mat(browse_dispargs, ...
		deblank(browse_names(browse_i,:)));
	    browse_datarangeindex = [browse_datarangeindex; ...
	      browse_index(browse_i)];
	  end
	  browse_listargs = str2mat(browse_listargs, ...
	      sprintf('R%i_%s', browse_count, ...
	      deblank(browse_names(browse_i,:))));
	end
      end
      if size(browse_dispargs,1) > 1
	browse_dispargs = ...
	    browse_dispargs(2:size(browse_dispargs,1),:);
      else
	browse_dispargs = '';
      end
      if size(browse_listargs,1) > 1
	browse_listargs = ...
	    browse_listargs(2:size(browse_listargs,1),:);
      else
	browse_listargs = '';
      end
      
      % now unpack all of the data.  Be sure to skip any whose
      % names are empty (a line of all blanks).
      for browse_i = 1:size(browse_index,1)
	% find which URL we are unpacking
	browse_j = min(find(browse_inx > browse_i))-1+browse_count-1;
	if isempty(deblank(browse_names(browse_i,:)))
	  if ~any(browse_sizes(browse_i,1:2) == 0)
	    browse_string = sprintf('Error! empty string in R%i_ %s', ...
		browse_j, ...
		'has data assigned to it.  These data will NOT be unpacked.');
	    dodsmsg(browse_string)
	    % we must clip the data anyway, ... ack!
	    browse_size = browse_sizes(browse_i,1)*browse_sizes(browse_i,2);
	    browse_data = browse_data(browse_size+1:length(browse_data));
	  end
	else %  ************** NAME IS NOT EMPTY. UNPACK SOMETHING INTO IT.
	  browse_string = sprintf('R%i_%s', ...
	      browse_j, deblank(browse_names(browse_i,:)));
	  % add this variable to the list of arguments in 'Clear All Rxx_ ' list
	  browse_data_list = [browse_string ' ' browse_data_list];
	  browse_string = sprintf('%s = %s;', browse_string, ...
	      [ 'reshape(browse_data(1:browse_sizes(browse_i,1)*', ...
		'browse_sizes(browse_i,2)),', ...
		'browse_sizes(browse_i,1),browse_sizes(browse_i,2))']);
	  eval(browse_string)
	  % if these are the acknowledgements, turn them back into a string
	  if strcmp(deblank(browse_names(browse_i,:)),'Acknowledge')
	    browse_string = sprintf('R%i_%s = setstr(R%i_%s);', ...
		browse_j, deblank(browse_names(browse_i,:)), ...
		browse_j, deblank(browse_names(browse_i,:)));
	    eval(browse_string)
	  end
	  % clip browse_data so we don't end up using memory
	  % for two full copies of the data
	  browse_size = browse_sizes(browse_i,1)*browse_sizes(browse_i,2);
	  browse_data = browse_data(browse_size+1:length(browse_data));
	end
      end % end of loop through browse_i
    end % end of all are empty
    
    % unpack the URLs and add them to the list of arguments in the 
    % 'Clear All Rxx_ ' list
    for browse_i = 1:browse_num_urls
      browse_data_list = [browse_data_list ' ' ...
	    sprintf('R%i_URL', browse_count+browse_i-1)];
      % unpack the URL
      browse_string = sprintf('R%i_URL = ''%s'';', browse_count+browse_i-1, ...
	  browse_urls(browse_i,:));
      eval(browse_string)
    end
    
    % update the 'Clear All Rxx_' list
    if ~isempty(browse_data_list)
      browse('addclear', browse_data_list)
    end

    % -----------------------------------------------------
    browse_string2 = sprintf('R%i_   ', ...
	browse_count:browse_count+browse_num_urls-1);
    browse_string = sprintf('\n%s%i%s\n%s%s','This request generated ',  ...
	browse_num_urls, ' separate URLs, ', ...
	'which are stored in the sets:  ', ...
	browse_string2);
    browse_string = sprintf('%s\n\n%s\n', ...
	browse_string, ...
	'Each individual argument is stored like so:');
    % check to see if any argument was empty for ALL returning URLs
    browse_string2 = '';
    for browse_j = 1:size(browse_listargs,1)
      browse_string2 = [browse_string2 ' ' ...
	    deblank(browse_listargs(browse_j,:))];
    end
    browse_string = sprintf('%s%s\n', browse_string, ...
	browse_string2);
    dodsmsg(browse_string)

    browse_dispchoices = zeros(12,1);
    set(browse_clear_button,'enable','off')
    if ~isempty(browse_dispargs)
      dispmenu('display', browse_dispargs, browse_datarangeindex, ...
	  browse_getvariables, browse_num_plots)
    % old call -- I don't think 'new' was ever used
    %dispmenu('display', browse_dispargs, browse_datarangeindex, ...
    %    browse_getvariables, browse_num_urls, 'new');

    end
  else % browse_count is empty
    dodsmsg('This request generated no URLs')
  end
else % browse_count does not exist -- this happens whenever 
  % the estimated datasize is greated than the check level,
  % so we don't want to alarm the user with a false error 
  % message here.  It could *also* happen when no data are returned
  % from a getdata request, if somehow that wasn't caught
  % internally, although I've yet to see it.
  % dodsmsg('This request generated no URLs')
end
