Home > fvcom_prepro > get_EA_river_climatology.m

get_EA_river_climatology

PURPOSE ^

Read river temperature climatologies from the Environment Agency river

SYNOPSIS ^

function Mobj = get_EA_river_climatology(Mobj, ea, dist_thresh)

DESCRIPTION ^

 Read river temperature climatologies from the Environment Agency river
 temperature data. If no data are found within the threshold specified, a
 mean climatology from the nearest 30 sites is provided instead.

 function Mobj = get_EA_river(Mogj, ea)

 DESCRIPTION:
   Load all the river data from the river climatology netCDF file and find
   the most relevant one to the river nodes in Mobj.rivers.positions.

 INPUT:
   Mobj        : MATLAB mesh structure which must contain:
                   - Mobj.river_nodes - river node IDs.
                   - Mobj.lon, Mobj.lat - unstructured grid node
                   positions.
                   - Mobj.river_time - Modified Julian Day array of the
                   times for the river discharge data (Mobj.river_flux).
   ea          : Full path to the river climatology netCDF file.
   dist_thresh : distance threshold beyond which a river temperature
                 climatology data point is considered too far to be valid
                 (in degrees).

 OUTPUT:
   Mobj        : MATLAB structure with a new Mobj.river_temp field which
                 contains the climatology for the river nodes.

 EXAMPLE USAGE:
   Mobj = get_EA_river_climatology(Mobj, '/path/to/netcdf.nc', 0.05)

 Author(s):
   Pierre Cazenave (Plymouth Marine Laboratory)

 Revision history
   2013-11-05 First version.
   2014-07-08 Think I've fixed the issue with leap years and incorrectly
   sized output temperature arrays with multiple years.
   2014-09-02 Nope, I hadn't fixed leap years, but I might have now.
   2015-09-24 Add check for whether we actually have any rivers to
   process.

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function Mobj = get_EA_river_climatology(Mobj, ea, dist_thresh)
0002 % Read river temperature climatologies from the Environment Agency river
0003 % temperature data. If no data are found within the threshold specified, a
0004 % mean climatology from the nearest 30 sites is provided instead.
0005 %
0006 % function Mobj = get_EA_river(Mogj, ea)
0007 %
0008 % DESCRIPTION:
0009 %   Load all the river data from the river climatology netCDF file and find
0010 %   the most relevant one to the river nodes in Mobj.rivers.positions.
0011 %
0012 % INPUT:
0013 %   Mobj        : MATLAB mesh structure which must contain:
0014 %                   - Mobj.river_nodes - river node IDs.
0015 %                   - Mobj.lon, Mobj.lat - unstructured grid node
0016 %                   positions.
0017 %                   - Mobj.river_time - Modified Julian Day array of the
0018 %                   times for the river discharge data (Mobj.river_flux).
0019 %   ea          : Full path to the river climatology netCDF file.
0020 %   dist_thresh : distance threshold beyond which a river temperature
0021 %                 climatology data point is considered too far to be valid
0022 %                 (in degrees).
0023 %
0024 % OUTPUT:
0025 %   Mobj        : MATLAB structure with a new Mobj.river_temp field which
0026 %                 contains the climatology for the river nodes.
0027 %
0028 % EXAMPLE USAGE:
0029 %   Mobj = get_EA_river_climatology(Mobj, '/path/to/netcdf.nc', 0.05)
0030 %
0031 % Author(s):
0032 %   Pierre Cazenave (Plymouth Marine Laboratory)
0033 %
0034 % Revision history
0035 %   2013-11-05 First version.
0036 %   2014-07-08 Think I've fixed the issue with leap years and incorrectly
0037 %   sized output temperature arrays with multiple years.
0038 %   2014-09-02 Nope, I hadn't fixed leap years, but I might have now.
0039 %   2015-09-24 Add check for whether we actually have any rivers to
0040 %   process.
0041 
0042 subname = 'get_EA_river_climatology';
0043 
0044 global ftbverbose
0045 if ftbverbose
0046     fprintf('\nbegin : %s \n', subname)
0047 end
0048 
0049 if isempty(Mobj.river_nodes)
0050     warning('No rivers specified in the domain.')
0051     Mobj.river_temp = [];
0052 
0053     if ftbverbose
0054         fprintf('end   : %s\n', subname)
0055     end
0056     return
0057 end
0058 
0059 % Load the position (lon/lat), time, climatology and SiteType variables
0060 % only. Not really bothered about the other variables.
0061 nc = netcdf.open(ea, 'NOWRITE');
0062 varid = netcdf.inqVarID(nc, 'climatology');
0063 climatology = netcdf.getVar(nc, varid, 'single');
0064 varid = netcdf.inqVarID(nc, 'time');
0065 time = netcdf.getVar(nc, varid, 'single');
0066 varid = netcdf.inqVarID(nc, 'lon');
0067 lon = netcdf.getVar(nc, varid, 'single');
0068 varid = netcdf.inqVarID(nc, 'lat');
0069 lat = netcdf.getVar(nc, varid, 'single');
0070 varid = netcdf.inqVarID(nc, 'SiteType');
0071 SiteType = netcdf.getVar(nc, varid);
0072 netcdf.close(nc)
0073 clear varid
0074 
0075 % Remove any sites which aren't RIVER in SiteType. This is not pretty but
0076 % relatively speedy, so it'll have to do.
0077 good = [];
0078 for i = 1:size(SiteType, 2)
0079     if strcmp(strtrim(SiteType(:, i)'), 'RIVER')
0080         good = [good, i];
0081     end
0082 end
0083 
0084 % Clear out the bad sites.
0085 climatology = climatology(:, good);
0086 lon = lon(good);
0087 lat = lat(good);
0088 
0089 % Now find the nearest nodes to the river node positions.
0090 nr = length(Mobj.river_nodes);
0091 
0092 clim = nan(length(time), nr);
0093 
0094 for r = 1:nr
0095     dist = sqrt((lon - Mobj.lon(Mobj.river_nodes(r))).^2 + (lat - Mobj.lat(Mobj.river_nodes(r))).^2);
0096     [howclose, idx] = min(dist);
0097 
0098     if howclose > dist_thresh
0099         % Find the 30 closest sites and use their data instead.
0100         [~, idx] = sort(dist);
0101         clim(:, r) = median(climatology(:, idx(1:30)), 2);
0102     else
0103         % Get the relevant climatology.
0104         clim(:, r) = climatology(:, idx);
0105     end
0106 end
0107 
0108 % Since the EA climatology is only 365 days long, add the mean of
0109 % the first and last days to the end of the time series for leap
0110 % years.
0111 clim = [clim; mean([clim(1, :); clim(end, :)])];
0112 
0113 % Now we have the climatologies for the relevant river nodes, we need to
0114 % repeat it to fit the length of the Mobj.river_time array. Since the
0115 % climatology data are for a year only, we need to find the correct index
0116 % for the start and end of the Mobj.river_time array so that we don't put
0117 % January temperature in July, for example.
0118 [yyyy, mm, dd, HH, MM, SS] = mjulian2greg(Mobj.river_time);
0119 startday = (datenum(yyyy(1), mm(1), dd(1), HH(1), MM(1), SS(1)) - ...
0120     datenum(min(yyyy), 1, 1, 0, 0, 0)) + 1; % add offset of 1 for MATLAB indexing.
0121 warning('Don''t know what''s going on with this here. Check the code to find the end day for the river climatology.')
0122 
0123 years = unique(yyyy);
0124 ny = length(years);
0125 if ny == 1
0126     % Offset time series by 1 day to get a full year (365/366 days).
0127     endday = (1 + datenum(yyyy(end), mm(end), dd(end), HH(end), MM(end), SS(end)) - ...
0128         datenum(max(yyyy), 1, 1, 0, 0, 0));
0129 
0130     % Subset the river climatology for the right days.
0131     repclim = clim(startday:endday, :);
0132 else
0133     % Otherwise build up the time series using the number of unique years
0134     % we have.
0135     for y = 1:ny
0136         % Find the number of days in this year and only extract that number
0137         % from the climatology.
0138         tidx = 1:length(yyyy);
0139         tidx(yyyy ~= years(y)) = [];
0140         % Offset time series by 1 day to get a full year (365/366 days).
0141         endday = (1 + datenum(yyyy(tidx(end)), mm(tidx(end)), dd(tidx(end)), HH(tidx(end)), MM(tidx(end)), SS(tidx(end))) - ...
0142             datenum(max(yyyy(tidx)), 1, 1, 0, 0, 0));
0143 
0144         nd = sum(eomday(years(y), 1:12));
0145         if y == 1
0146             % This is the part year for the first year. Prepend the
0147             % existing array with the number of days required.
0148             repclim = clim(startday:end, :);
0149         elseif y == ny
0150             repclim = [repclim; clim(1:endday, :)];
0151         elseif y ~= 1 || y ~= ny
0152             % We're in the middle years, so just repeat add the clim array
0153             % to the end of the previous interation's.
0154             repclim = [repclim; clim];
0155         end
0156 
0157         % We sometimes need to add an extra couple of day's data to the end
0158         % of the array for this (leap) year. A recent fix to the code above
0159         % should have made this obsolete, but you never know...
0160         if nd == 366
0161             backidx = 366 - nd;
0162             repclim = [repclim; repclim(end - backidx:end, :)];
0163         end
0164     end
0165 end
0166 
0167 % Add the temperature climatology to Mobj.
0168 Mobj.river_temp = repclim;
0169 
0170 if ftbverbose
0171     fprintf('end   : %s \n', subname)
0172 end

Generated on Wed 20-Feb-2019 16:06:01 by m2html © 2005