Home > fvcom_prepro > get_POLPRED_spectide.m

get_POLPRED_spectide

PURPOSE ^

Extract tidal harmonic phases and amplitudes from POLPRED ASCII files.

SYNOPSIS ^

function [Mobj] = get_POLPRED_spectide(Mobj, POLPRED)

DESCRIPTION ^

 Extract tidal harmonic phases and amplitudes from POLPRED ASCII files.

 get_POLPRED_spectide(Mobj, POLPRED)

 DESCRIPTION:
    Extract POLPRED harmonic amplitude and phases for the nearest point in
    the POLPRED grid to the open boundary nodes in Mobj.

 INPUT:
   Mobj    = MATLAB mesh object (see read_sms_mesh.m)
   POLPRED = ASCII file of the POLPRED harmonics

 OUTPUT:
    Mobj  = MATLAB mesh object with two new arrays:
       phase - Harmonic phases at each open boundary point
       amp   - Harmonic amplitudes at each open boundary point

 EXAMPLE USAGE
    Mobj = get_POLPRED_spectide(Mobj, '/path/to/POLPRED.txt')

 Author(s):  
    Pierre Cazenave (Plymouth Marine Laboratory)
 
 Revision history
    2012-11-15 First version. Based in part on tide_tools.py from the
    fvcom-py Python toolbox (https://bitbucket.org/pwcazenave/fvcom-py)
    and Ricardo Torres' searchtides.m.
   
==========================================================================

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function [Mobj] = get_POLPRED_spectide(Mobj, POLPRED)
0002 % Extract tidal harmonic phases and amplitudes from POLPRED ASCII files.
0003 %
0004 % get_POLPRED_spectide(Mobj, POLPRED)
0005 %
0006 % DESCRIPTION:
0007 %    Extract POLPRED harmonic amplitude and phases for the nearest point in
0008 %    the POLPRED grid to the open boundary nodes in Mobj.
0009 %
0010 % INPUT:
0011 %   Mobj    = MATLAB mesh object (see read_sms_mesh.m)
0012 %   POLPRED = ASCII file of the POLPRED harmonics
0013 %
0014 % OUTPUT:
0015 %    Mobj  = MATLAB mesh object with two new arrays:
0016 %       phase - Harmonic phases at each open boundary point
0017 %       amp   - Harmonic amplitudes at each open boundary point
0018 %
0019 % EXAMPLE USAGE
0020 %    Mobj = get_POLPRED_spectide(Mobj, '/path/to/POLPRED.txt')
0021 %
0022 % Author(s):
0023 %    Pierre Cazenave (Plymouth Marine Laboratory)
0024 %
0025 % Revision history
0026 %    2012-11-15 First version. Based in part on tide_tools.py from the
0027 %    fvcom-py Python toolbox (https://bitbucket.org/pwcazenave/fvcom-py)
0028 %    and Ricardo Torres' searchtides.m.
0029 %
0030 %==========================================================================
0031 
0032 subname = 'get_POLPRED_spectide';
0033 
0034 global ftbverbose;
0035 if ftbverbose
0036   fprintf('\n')
0037   fprintf(['begin : ' subname '\n'])
0038 end
0039 
0040 % Check we have spherical coordinates in Mobj (we can't extract harmonics
0041 % without them (easily)).
0042 if ~Mobj.have_lonlat
0043     error('Spherical coordinates absent from Mobj. Cannot extract harmonics from cartesian coordinates.')
0044 end
0045 
0046 % Read the POLPRED header into a struct of header names plus their values.
0047 fid = fopen(POLPRED,'rt');
0048 if(fid < 0)
0049     error(['file: ' POLPRED ' does not exist']);
0050 end
0051 
0052 if ftbverbose
0053   fprintf(['reading from: ' POLPRED '\n'])
0054   fprintf('extracting header\n')
0055 end
0056 
0057 readingHeader = true;
0058 header = struct();
0059 while readingHeader
0060     lin = fgetl(fid);
0061     if isempty(lin)
0062         % Got to the end of the header
0063         readingHeader = false;
0064     else
0065         % We have some header information. Load it into a struct.
0066         key = regexp(lin, ':', 'split');
0067         header.(strtrim(regexprep(key{1}, ' ', '_'))) = strtrim(key{2});
0068     end
0069 end
0070 
0071 % Reformat the list of harmonics into a more sensible format
0072 header.Harmonics = regexp(header.Harmonics, ' ', 'split');
0073 
0074 % Get the positions in header.Harmonics for the constituents in which we're
0075 % interested.
0076 
0077 pInd = 1:length(header.Harmonics);
0078 pIndUse = nan(length(Mobj.Components), 2);
0079 for i=1:length(Mobj.Components)
0080     pPos = pInd(strcmp(Mobj.Components{i}, header.Harmonics));
0081     if isempty(pPos)
0082         warning('Supplied constituent (%s) is not present in the POLPRED data', Mobj.Components{i}) %#ok<WNTAG>
0083     else
0084         % Make index start at zero so the multiplication works, but
0085         % compensate for that once the offset has been applied. Also add
0086         % offset for the 2 columns (amplitude and phase).
0087         pIndUse(i, :) = (repmat((pPos - 1 ) * 6, 1, 2) + 1) + (0:1);
0088     end
0089 end
0090 % Add three to offset by the lat, lon and flag columns
0091 pIndUse = pIndUse + 3;
0092 
0093 % Now we're at the data. Load it all into a massive array.
0094 if ftbverbose
0095   fprintf('extracting data\n')
0096 end
0097 
0098 readingData = true;
0099 i = 0;
0100 % Preallocate data to something big and then cut back afterwards (if
0101 % necessary). Get the number of columns from the header and multiply by 6
0102 % (amplitude and phases for z, u and v). Add three for the lat, lon and
0103 % flag columns). The rows is the number of data lines in my files for the
0104 % northwest European shelf domain.
0105 nCols = 3 + (str2double(header.Number_of_harmonics) * 6);
0106 data = nan(358797, nCols);
0107 if ftbverbose
0108     tic
0109 end
0110 while readingData
0111     lin = fgetl(fid);
0112     if lin ~= -1 % EOF is -1
0113         i = i + 1;
0114         if ftbverbose
0115             if mod(i, 10000) == 0
0116                 fprintf('line %i\n', i)
0117             end
0118         end
0119         % str2double doesn't work without a couple of calls to regexp,
0120         % which makes it ~20x slower than str2num on its own. The regexp
0121         % approach is still here if you don't believe me.
0122         data(i, :) = str2num(strtrim(lin)); %#ok<ST2NM>
0123 %         data(i, :) = str2double(regexp(regexprep(strtrim(lin), '\s+', ' '), ' ', 'split'));
0124     else
0125         if ftbverbose
0126             fprintf('end of file at line %i\n', i)
0127         end
0128         readingData = false;
0129     end
0130 end
0131 if ftbverbose
0132     toc
0133 end
0134 
0135 fclose(fid);
0136 
0137 % Clear out any additional NaNs in data from preallocation.
0138 data = reshape(data(~isnan(data)), i, nCols);
0139 
0140 % Now we have the data, identify the indices of data which correspond to
0141 % the nearest point to each open boundary point. This approach may not be
0142 % the best: it might instead be better to simply read in the positions and
0143 % create an index which we use to extract the harmonics of interest.
0144 % However, we've got this far so might as well carry on.
0145 
0146 % Get the open boundary node IDs with which to extract their locations
0147 tmpObcNodes = Mobj.obc_nodes';
0148 ObcNodes = tmpObcNodes(tmpObcNodes~=0)';
0149 obc_lon = Mobj.lon(ObcNodes);
0150 obc_lat = Mobj.lat(ObcNodes);
0151 
0152 % For each position, find the nearest POLPRED value. Use the
0153 % find_nearest_pt.m logic to get the nearest point (we can't use the
0154 % function here because the values for which we're searching aren't in
0155 % Mobj).
0156 distance = nan(size(obc_lon));
0157 point = nan(size(distance));
0158 % Omit the NaNs in the indices from POLPRED when calculating the output
0159 % array size.
0160 amp = nan(length(obc_lon), length(pIndUse(~isnan(pIndUse(:, 1)), 1)));
0161 phase = nan(size(amp));
0162 for i=1:length(obc_lon)
0163     radvec = sqrt((obc_lon(i)-data(:,2)).^2 + (obc_lat(i)-data(:,1)).^2);
0164     [distance(i), point(i)] = min(radvec);
0165     % Get the amplitude and phase for each constituent (in order of
0166     % Mobj.Components). Check for and omit NaNs here (for missing tidal
0167     % constituents in the supplied list and what's given in POLPRED).
0168     amp(i, :) = data(point(i), pIndUse(~isnan(pIndUse(:, 1)), 1));
0169     phase(i, :) = data(point(i), pIndUse(~isnan(pIndUse(:, 1)), 2));
0170 end
0171 
0172 % Check for and warn about NaNs (-999.9 in POLPRED data).
0173 if sum(amp(:)==-999.9) > 0
0174     warning('NaN values (-999.9 in POLPRED terms) in the amplitude data. Are your boundaries on land?') %#ok<WNTAG>
0175 end
0176 if sum(phase(:)==-999.9) > 0
0177     warning('NaN values (-999.9 in POLPRED terms) in the phase data. Are your boundaries on land?') %#ok<WNTAG>
0178 end
0179 
0180 Mobj.amp = amp;
0181 Mobj.phase = phase;
0182 
0183 % Plot the open boundary positions and the closest POLPRED point.
0184 % figure(1000)
0185 % plot(obc_lon, obc_lat, 'o')
0186 % hold on
0187 % plot(data(point,2), data(point,1), 'rx')
0188

Generated on Mon 04-Feb-2013 14:22:28 by m2html © 2005