function [output_constituents, lon, lat] = read_otps_output ( input_otps_file )
% READ_OTPS_OUTPUT:  reads output of OTPS executable "extract_HC"
%
% The tidal constituents that are extracted can be one of
%         m2, s2, n2, k2, t2, l2, k1, o1, p1, q1, m1, j1, mf, mm, ssa, 
%         m4, and m6
%
% USAGE:  [output_constituents, lon, lat] = read_otps_output ( input_otps_file );
%
% PARAMETERS:
% Input:
%     input_otps_file:
%         ascii text file produces by "extract_HC"
%
%
% Output:
%     output_constituents:
%         array of structures.  Each structure has the following fields:
%             Name
%             Period
%             Amplitude
%             Phase
%         The structure is sorted into descending order with respect to
%         the period.
%     lon, lat:
%         Optionally, the longitude and latitude of the points at which
%         the tidal harmonics are defined.
%
% 


afid = fopen ( input_otps_file, 'r' );
if afid == -1
	msg = sprintf ( '%s:  fopen failed on %s.\n', mfilename, input_otps_file );
	error ( msg );
end

%
% Scan thru it to get the number of lines
line_count = 0;
while 1
	tline = fgetl ( afid );
	if ~ischar ( tline )
		break;
	end
	line_count = line_count + 1;
end




%
% Rewind the file.
fseek(afid,0,-1);




%
% Get past the header
% OTPS produces a header that looks something like the following.
%
%      Model:        EC
%      Elevations (m)
%      Lat     Lon       o1_amp  o1_ph   p1_amp  blah blah blah
fgetl ( afid );
fgetl ( afid );
constituents_line = fgetl ( afid );

%
% figure out what constituents we have
r = constituents_line;
count = 0;
while 1
	[t,r] = strtok ( r );
	if isempty(r)
		break
	end
	index = findstr ( t, 'amp' );
	if index
		count = count + 1;
		constituents{count} = t(1:index-2);
	end

end



num_constituents = length(constituents);

%
% Classify the tidal components.
for j = 1:num_constituents

	%
	% what is the period?
	switch ( lower(constituents{j}) )

	%
	% semi-diurnal components
	case 'm2'
		period(j) = 12.4206;
	case 's2'
		period(j) = 12.0000;
	case 'n2'
		period(j) = 12.6583;
	case 'k2'
		period(j) = 11.97;
	case 't2'
		period(j) = 12.01;
	case 'l2'
		period(j) = 12.19;

	%
	% Diurnal components
	case 'k1'
		period(j) = 23.9345;
	case 'o1'
		period(j) = 25.8193;
	case 'p1'
		period(j) = 24.07;
	case 'q1'
		period(j) = 26.87;
	case 'm1'
		period(j) = 24.86;
	case 'j1'
		period(j) = 23.10;

	%
	% Long period components
	case 'mf'
		period(j) = 327.86;
	case 'mm'
		period(j) = 661.30;
	case 'ssa'
		period(j) = 2191.43;

	case 'm4'
		period(j) = 6.21;

	case 'm6'
		period(j) = 4.14;

	otherwise
		msg = sprintf ( '%s:  unknown tidal component ''%s''\n', constituents{j} );
		error ( msg );
	end

end


%
% allocate the arrays
lat = NaN * zeros ( line_count-3, 1 );
lon = NaN * zeros ( line_count-3, 1 );
amplitude = NaN * zeros ( line_count-3, num_constituents );
phase = NaN * zeros ( line_count-3, num_constituents );

%
% Construct the sscanf format string.  There are two times the number
% of constituents floats, plus the lat and lon.
fmt = repmat ( ' %f', 1, num_constituents*2 );
constituents_fmt = ['%f %f' fmt];

line_count = 3;
while 1
	tline = fgetl ( afid );
	if ~ischar ( tline )
		break;
	end

	line_count = line_count + 1;

	if findstr( 'Site is out of model grid OR land', tline )

		%
		% If the line contains the string "Site is out of model grid OR land", then 
		% skip the constituents.  But we still fill in the lat and lon.
		[d,token_count] = sscanf ( tline, '%f %f %s' );
		if ( token_count ~= 3 )
			msg = sprintf ( '%s:  sscanf failed on line %d in input file %s.\n', mfilename, line_count, input_otps_file );
			error ( msg );
		end
		lat(line_count-3) = d(1);
		lon(line_count-3) = d(2);

	elseif findstr( 'Model:', tline )

		%
		% do nothing
		;

	elseif findstr( 'Lat limits:', tline )

		%
		% do nothing
		;

	elseif findstr( 'Lon limits:', tline )

		%
		% do nothing
		;

	elseif findstr( 'Elevations (m)', tline )

		%
		% do nothing
		;

	elseif findstr( 'Lat     Lon', tline )

		%
		% do nothing
		;

	else

		%
		% We must be over water.  Get all the constituents as well as the lat/lon
		[d,token_count] = sscanf ( tline, constituents_fmt );
		if ( token_count ~= (num_constituents*2 + 2) )
			error_fmt = '%s:  sscanf failed on line %d in input file %s, reading %d inputs instead of %d.\n'
			msg = sprintf ( error_fmt, mfilename, line_count, input_otps_file, token_count, (num_constituents*2 + 2) );
			error ( msg );
		end

		lat(line_count-3) = d(1);
		lon(line_count-3) = d(2);

		if ( d(1) == 0 ) & (d(2) == 0 ) 
			line_count
		end

		point_amplitude = d(3:2:end);
		point_phase = d(4:2:end);
		amplitude(line_count-3,:) = point_amplitude';
		phase(line_count-3,:) = point_phase';

	end

end

fclose ( afid );



%
% Load the output structure with the proper components
for j = 1:num_constituents
	output_constituents(j) = struct ( 'Name', constituents{j}, 'Amplitude', amplitude(:,j), 'Phase', phase(:,j), 'Period', period(j) );
end


%
% sort the periods into descending order, use that to sort the output into
% descending order with regards to the period.
%[dud, I] = sort ( period, 'descend' );
[dud, I] = sort ( period);% edited for a different
I=flipud(I);% version of sort
dud=flipud(dud);

output_constituents = output_constituents(I);
