nc_varget.m 4.61 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
function vardata = nc_varget(ncfile , varname , varargin )
%
% version of nc_varget for mexec to replace snctools version
% the aim is to replace snctools nc_ calls with faster versions that make
% simple native matlab netcdf calls.
%
% rather than changing every mexec program, the snctools library can be
% replaced with this library
%
% varargin can be
% start, count, stride
% start begins at zero, so if start = [2 3] it will retrieve data from
% row 3, column 4;
% if start is defined and count is empty, the data are retrieved from
% the point denoted by the start offset, to the end of each row and column.
%
% When I tried it, the -1 notation for count in the snctools version did
% not work as intended.
%
% This version handles _FillValue but not missing values or scaling or
% offset.
%
% The old snctools description was
%
% % DATA = NC_VARGET(NCFILE,VARNAME) retrieves all the data from the
% % variable VARNAME in the netCDF file NCFILE.
% %
% % DATA = NC_VARGET(NCFILE,VARNAME,START,COUNT) retrieves the contiguous
% % portion of the variable specified by the index vectors START and
% % COUNT.  Remember that SNCTOOLS indexing is zero-based, not
% % one-based.  Specifying a -1 in COUNT means to retrieve everything
% % along that dimension from the START coordinate.
% %
% % DATA = NC_VARGET(NCFILE,VARNAME,START,COUNT,STRIDE) retrieves
% % a non-contiguous portion of the dataset.  The amount of
% % skipping along each dimension is given through the STRIDE vector.
% %
% % NCFILE can also be an OPeNDAP URL if the proper java SNCTOOLS
% % backend is installed.  See the README for details.
% %
% % NC_VARGET tries to be intelligent about retrieving the data.
% % Since most general matlab operations are done in double precision,
% % retrieved numeric data will be cast to double precision, while
% % character data remains just character data.  %
%
%
% bak jc191 6 Feb 2020
%

args = varargin(:);
start = [];
count = [];
stride = [];
switch length(args)
    case 1
        start = args{1};
    case 2
        start = args{1};
        count = args{2};
    case 3
        start = args{1};
        count = args{2};
        stride = args{3};
    otherwise
end

ncid = netcdf.open(ncfile,'NOWRITE');

varid = netcdf.inqVarID(ncid,varname);


% is there is start but no count, then calculate count to retrieve from
% start to the end of each dimension

[varname,xtype,dimids,natts] = netcdf.inqVar(ncid, varid);

if isempty(count) & ~isempty(start)
    
    % we seem to need to flip the dimids to get the same effect as the snctools
    % nc_addvar
    
    dimids = fliplr(dimids);
    
    ndimsv = length(dimids);
    clear dimsize
    for kd = 1:ndimsv
        [dimname, dimlength] = netcdf.inqDim(ncid, dimids(kd));
        dimsize(kd) = dimlength;
    end
    
    count = dimsize(:)'-start;
    
end

% the snctools version seems to retrieve every element if there is start but no count.
%
% I couldn't see anywhere where mexec calls nc_varget with start but no
% count, so the above difference should not matter.

start = fliplr(start);
count = fliplr(count);
stride = fliplr(stride);

if isempty(start)
    vardata = netcdf.getVar(ncid, varid );
elseif isempty(count)
    fprintf(2,'\n%s\n','Warning, nc_varget has been called with start but no count');
    fprintf(2,'%s\n','The bahaviour of this version is different than the behaviour of the snctools version');
    fprintf(2,'%s\n\n','Suggest the code be rewritten to state exactly what ''count'' should be');
    error('error in nc_varget');
    % if you reinstate the line of code below you will get precisely one data
    % value, at location given by 'start'
    vardata = netcdf.getVar(ncid, varid, start );
elseif isempty(stride)
    vardata = netcdf.getVar(ncid, varid, start, count );
else
    vardata = netcdf.getVar(ncid, varid, start, count, stride);
end



if length(dimids) == 1
    vardata = vardata(:);  % techsas files have one dimension which is time; snctools nc_varget makes this a column vector
else
    vardata = vardata'; % this is necessary to mimic the action of the old nc_varget;
    %     the above line will only work on 2-D vars, ie 1xN, Mx1, MxN.
    %     mexec is not presently set up to handle more than 2-D vars.
    %     mexec files have at least three dimension parameters: n_unity, nrows1, ncols1.
    %     mexec variables are always 2-D. MxN 1xN or Mx1.
end

% now handle _FillValue

switch ( xtype )
    case { 6 } % 6 is double
        try
            fillvalue = netcdf.getAtt(ncid, varid, '_FillValue');
            vardata(vardata == fillvalue) = NaN;
        catch
            % If there is no fillvalue defined, take no action
        end
    otherwise
        
end


netcdf.close(ncid);

return