📄 subsref.m
字号:
function theResult = subsref(self, theStruct)
% ncvar/subsref -- Overloaded "{}", ".", and "()" operators.
% subsref(self, theStruct) processes the subscripting
% operator () for self, an "ncvar" object referenced on
% the righthand side of an assignment, such as in
% result = self(i, j, ...), where the sole operator
% is '()'. If the syntax is result = self.theAttname
% or result = self.theAttname(...), the named attribute
% object of self is processed. If fewer than the full
% number of indices are provided, the silent ones
% default to 1, unless the last one provided is ':',
% in which case the remainder default to ':' as well.
% Indices beyond the full number needed are ignored.
% ## Only a constant stride is permitted at present.
%
% If the "quick" flag is set, faster "vanilla-flavored"
% processing is forced. Except for autoscaling, no
% special treatments are performed, such as virtual
% indexing, implicit indexing (including ":"), unsigned
% conversions, or auto-NaNing.
% Also see: ncvar/subsasgn.
% Copyright (C) 1996-7 Dr. Charles R. Denham, ZYDECO.
% All Rights Reserved.
% Disclosure without explicit written consent from the
% copyright owner does not constitute publication.
% Version of 07-Aug-1997 15:55:19.
% Updated 25-Mar-2003 11:35:17.
if nargin < 1, help(mfilename), return, end
if length(theStruct) < 1
result = self;
if nargout > 0
theResult = result;
else
disp(result)
end
return
end
% Quick processing.
% The NetCDF file must already be in "data" mode.
isQuick = quick(self) & ...
length(theStruct) == 1 & ...
isequal(theStruct.type, '()');
if isQuick
indices = theStruct.subs;
if ~iscell(indices), indices = {indices}; end
if (0) % Slow, but proper.
theNCid = ncid(self);
theVarid = varid(self);
theSize = ncsize(self); % Slow.
start = zeros(size(theSize));
count = zeros(size(theSize));
theAutoscaleflag = autoscale(self);
else % Fast, but very bad manners.
s = struct(self);
s = s.ncitem;
s = struct(s);
theNCid = s.itsNCid;
theVarid = s.itsVarid;
start = zeros(1, length(indices));
count = zeros(1, length(indices));
theAutoscaleflag = s.itIsAutoscaling;
end
for i = 1:length(indices)
k = indices{i};
start(i) = min(k) - 1;
count(i) = length(k);
end
[result, status] = ncmex('varget', theNCid, theVarid, ...
start, count, theAutoscaleflag);
if status >= 0
result = permute(result, length(size(result)):-1:1);
end
if nargout > 0
theResult = result;
else
disp(result)
end
return
end
% Composite-variable processing.
% We map the source-indices to the destination-indices
% for each composite-variable participant. The indices
% are in cells of cells, arranged in the same order as
% the variables, which themselves are in a cell.
% Can we consolidate some of this mess?
theVars = var(self); % A cell.
if ~isempty(theVars)
[theSrcsubs, theDstsubs] = subs(self); % The mappings.
for j = 1:length(theSrcsubs)
siz = size(theVars{j});
src = theSrcsubs{j};
for i = 1:length(src)
if isequal(src{i}, ':') % Convert to numbers.
src{i} = 1:siz(i);
end
end
theSrcsubs{j} = src;
end
theSize = zeros(size(theDstsubs));
for j = 1:length(theDstsubs)
dst = theDstsubs{j};
for i = 1:length(dst)
theSize(i) = max(theSize(i), max(dst{i}));
end
end
theSubs = theStruct(1).subs;
if ~iscell(theSubs), theSubs = {theSubs}; end
isColon = isequal(theSubs{end}, ':');
if isColon, s = ':'; else, s = 1; end
while length(theSubs) < length(theSize)
theSubs{end+1} = s;
end
% Note: We compute a base-1 surrogate of theSubs,
% in order to keep the pre-allocated "result" matrix
% as small as possible.
subsx = cell(size(theSubs)); % "subs" is a function.
siz = zeros(size(subsx));
for i = 1:length(theSubs)
if isequal(theSubs{i}, ':')
theSubs{i} = 1:theSize(i);
end
subsx{i} = theSubs{i} - min(theSubs{i}) + 1; % Base-1.
siz(i) = max(subsx{i});
end
result = zeros(siz); % Pre-allocate.
for j = 1:length(theVars)
% [from, to] = mapsubs(theSrcsubs{j}, theDstsubs{j}, theSubs);
[from, to] = mapsubs(theSrcsubs{j}, theDstsubs{j}, subsx);
if ~isempty(from) & ~isempty(to)
x = ncsubsref(theVars{j}, '()', from);
result(to{:}) = x;
end
end
% result = result(theSubs{:}); % Subset.
result = result(subsx{:}); % Subset.
if nargout > 0
theResult = result;
else
disp(result)
end
return
end
% Regular processing.
result = [];
if nargout > 0, theResult = result; end
s = theStruct;
theType = s(1).type;
theSubs = s(1).subs;
s(1) = [];
nccheck(self)
theAutoscaleflag = (autoscale(self) == 1);
theDatatype = datatype(self);
theTypelen = ncmex('typelen', theDatatype);
isUnsigned = unsigned(self);
theFillvalue = fillval(self);
theAutonanflag = (autonan(self) == 1) & ~isempty(theFillvalue);
if theAutoscaleflag
theScalefactor = scalefactor(self);
theAddoffset = addoffset(self);
end
switch theType
case '()' % Variable data by index: self(..., ...).
indices = theSubs;
theSize = ncsize(self);
for i = 1:length(indices)
if isa(indices{i}, 'double')
if any(diff(diff(indices{i})))
disp(' ## Indexing strides must be positive and constant.')
return
end
end
end
% Flip and permute indices before proceeding,
% since we are using virtual indexing.
theOrientation = orient(self);
if any(theOrientation < 0) | any(diff(theOrientation) ~= 1)
for i = 1:length(theOrientation)
if theOrientation(i) < 0
if isa(indices{i}, 'double') % Slide the indices.
indices{i} = fliplr(theSize(i) + 1 - indices{i});
end
end
end
indices(abs(theOrientation)) = indices;
theSize(abs(theOrientation)) = theSize;
end
if prod(theSize) > 0
start = zeros(1, length(theSize));
count = ones(1, length(theSize));
stride = ones(1, length(theSize));
for i = 1:min(length(indices), length(theSize))
k = indices{i};
if ~isstr(k) & ~strcmp(k, ':') & ~strcmp(k, '-')
start(i) = k(1)-1;
count(i) = length(k);
d = 0;
if length(k) > 1, d = diff(k); end
stride(i) = max(d(1), 1);
else
count(i) = -1;
if i == length(indices) & i < length(theSize)
j = i+1:length(theSize);
count(j) = -ones(1, length(j));
end
end
end
start(start < 0) = 0;
stride(stride < 0) = 1;
for i = 1:length(count)
if count(i) == -1
maxcount = fix((theSize(i)-start(i)+stride(i)-1) ./ stride(i));
count(i) = maxcount;
end
end
theNetCDF = parent(self);
theNetCDF = endef(theNetCDF);
count(count < 0) = 0;
if any(count == 0), error(' ## Bad count.'), end
if all(count == 1)
[result, status] = ncmex('varget1', ncid(self), varid(self), ...
start, 0);
elseif all(stride == 1)
[result, status] = ncmex('varget', ncid(self), varid(self), ...
start, count, 0);
else
imap = [];
[result, status] = ncmex('vargetg', ncid(self), varid(self), ...
start, count, stride, imap, ...
0);
end
if theAutonanflag & status >= 0
f = find(result == theFillvalue);
if any(f), result(f) = NaN; end
end
if theAutoscaleflag & status >= 0
result = result .* theScalefactor + theAddoffset;
end
if isUnsigned & prod(size(result)) > 0
result(result < 0) = 2^(8*theTypelen) + result(result < 0);
end
else
result = [];
status = 0;
end
if status >= 0 & prod(size(result)) > 0
result = permute(result, length(size(result)):-1:1);
theOrientation = orient(self);
if any(theOrientation < 0) | any(diff(theOrientation) ~= 1)
for i = 1:length(theOrientation)
if theOrientation(i) < 0
result = flipdim(result, abs(theOrientation(i)));
end
end
if length(theOrientation) < 2
theOrientation = [theOrientation 2];
end
result = permute(result, abs(theOrientation));
end
elseif status >= 0 & prod(size(result)) == 0
result = [];
else
status, prod_size_result = prod(size(result)) % ***
warning(' ## ncvar/subsref failure.')
end
case '.' % Attribute: self.theAttname(...)
theAttname = theSubs;
while length(s) > 0 % Dotted name.
switch s(1).type
case '.'
theAttname = [theAttname '.' s(1).subs];
s(1) = [];
otherwise
break
end
end
result = att(self, theAttname);
if ~isempty(result), result = subsref(result, s); end
otherwise
warning([' ## Illegal syntax: "' theType '"'])
end
if nargout > 0 % Always true.
theResult = result;
else % Is there any way to force this?
c = ncatt('C_format', self);
if ~isempty(c)
c = c(:);
s = size(result)
result = result.';
result = result(:);
step = prod(s)/s(1);
k = 1:step;
for i = 1:s(1)
fprintf(c, result(k));
fprintf('\n');
k = k + step;
end
else
disp(result)
end
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -