source: Roms_tools/mexcdf/netcdf_toolbox/netcdf/@ncvar/subsref.m @ 1

Last change on this file since 1 was 1, checked in by cholod, 13 years ago

import Roms_Agrif

File size: 9.7 KB
Line 
1function theResult = subsref(self, theStruct)
2
3% ncvar/subsref -- Overloaded "{}", ".", and "()" operators.
4%  subsref(self, theStruct) processes the subscripting
5%   operator () for self, an "ncvar" object referenced on
6%   the righthand side of an assignment, such as in
7%   result = self(i, j, ...), where the sole operator
8%   is '()'.  If the syntax is result = self.theAttname
9%   or result = self.theAttname(...), the named attribute
10%   object of self is processed.  If fewer than the full
11%   number of indices are provided, the silent ones
12%   default to 1, unless the last one provided is ':',
13%   in which case the remainder default to ':' as well.
14%   Indices beyond the full number needed are ignored.
15%   ## Only a constant stride is permitted at present.
16%
17%   If the "quick" flag is set, faster "vanilla-flavored"
18%   processing is forced.  Except for autoscaling, no
19%   special treatments are performed, such as virtual
20%   indexing, implicit indexing (including ":"), unsigned
21%   conversions, or auto-NaNing.
22
23% Also see: ncvar/subsasgn.
24 
25% Copyright (C) 1996-7 Dr. Charles R. Denham, ZYDECO.
26%  All Rights Reserved.
27%   Disclosure without explicit written consent from the
28%    copyright owner does not constitute publication.
29 
30% Version of 07-Aug-1997 15:55:19.
31% Updated    25-Mar-2003 11:35:17.
32
33if nargin < 1, help(mfilename), return, end
34
35if length(theStruct) < 1
36        result = self;
37        if nargout > 0
38                theResult = result;
39        else
40                disp(result)
41        end
42        return
43end
44
45% Quick processing.
46%  The NetCDF file must already be in "data" mode.
47
48isQuick = quick(self) & ...
49                        length(theStruct) == 1 & ...
50                        isequal(theStruct.type, '()');
51
52if isQuick
53        indices = theStruct.subs;
54        if ~iscell(indices), indices = {indices}; end
55        if (0)   % Slow, but proper.
56                theNCid = ncid(self);
57                theVarid = varid(self);
58                theSize = ncsize(self);   % Slow.
59                start = zeros(size(theSize));
60                count = zeros(size(theSize));
61                theAutoscaleflag = autoscale(self);
62        else   % Fast, but very bad manners.
63                s = struct(self);
64                s = s.ncitem;
65                s = struct(s);
66                theNCid = s.itsNCid;
67                theVarid = s.itsVarid;
68                start = zeros(1, length(indices));
69                count = zeros(1, length(indices));
70                theAutoscaleflag = s.itIsAutoscaling;
71        end
72        for i = 1:length(indices)
73                k = indices{i};
74                start(i) = min(k) - 1;
75                count(i) = length(k);
76        end
77        [result, status] = ncmex('varget', theNCid, theVarid, ...
78                                                                start, count, theAutoscaleflag);
79        if status >= 0
80                result = permute(result, length(size(result)):-1:1);
81        end
82        if nargout > 0
83           theResult = result;
84        else
85           disp(result)
86        end
87        return
88end
89
90% Composite-variable processing.
91%  We map the source-indices to the destination-indices
92%  for each composite-variable participant.  The indices
93%  are in cells of cells, arranged in the same order as
94%  the variables, which themselves are in a cell.
95
96%  Can we consolidate some of this mess?
97
98theVars = var(self);   % A cell.
99if ~isempty(theVars)
100        [theSrcsubs, theDstsubs] = subs(self);  % The mappings.
101        for j = 1:length(theSrcsubs)
102                siz = size(theVars{j});
103                src = theSrcsubs{j};
104                for i = 1:length(src)
105                        if isequal(src{i}, ':')   % Convert to numbers.
106                                src{i} = 1:siz(i);
107                        end
108                end
109                theSrcsubs{j} = src;
110        end
111        theSize = zeros(size(theDstsubs));
112        for j = 1:length(theDstsubs)
113                dst = theDstsubs{j};
114                for i = 1:length(dst)
115                        theSize(i) = max(theSize(i), max(dst{i}));
116                end
117        end
118        theSubs = theStruct(1).subs;
119        if ~iscell(theSubs), theSubs = {theSubs}; end
120        isColon = isequal(theSubs{end}, ':');
121        if isColon, s = ':'; else, s = 1; end
122        while length(theSubs) < length(theSize)
123                theSubs{end+1} = s;
124        end
125       
126% Note: We compute a base-1 surrogate of theSubs,
127%  in order to keep the pre-allocated "result" matrix
128%  as small as possible.
129
130        subsx = cell(size(theSubs));   % "subs" is a function.
131        siz = zeros(size(subsx));
132        for i = 1:length(theSubs)
133                if isequal(theSubs{i}, ':')
134                        theSubs{i} = 1:theSize(i);
135                end
136                subsx{i} = theSubs{i} - min(theSubs{i}) + 1;   % Base-1.
137                siz(i) = max(subsx{i});
138        end
139       
140        result = zeros(siz);   % Pre-allocate.
141       
142        for j = 1:length(theVars)
143% [from, to] = mapsubs(theSrcsubs{j}, theDstsubs{j}, theSubs);
144                [from, to] = mapsubs(theSrcsubs{j}, theDstsubs{j}, subsx);
145                if ~isempty(from) & ~isempty(to)
146                        x = ncsubsref(theVars{j}, '()', from);
147                        result(to{:}) = x;
148                end
149        end
150
151% result = result(theSubs{:});  % Subset.
152
153        result = result(subsx{:});  % Subset.
154
155        if nargout > 0
156                theResult = result;
157        else
158                disp(result)
159        end
160        return
161end
162
163% Regular processing.
164
165result = [];
166if nargout > 0, theResult = result; end
167   
168s = theStruct;
169theType = s(1).type;
170theSubs = s(1).subs;
171s(1) = [];
172
173nccheck(self)
174theDatatype = datatype(self);
175theFillvalue = fillval(self);
176if strcmp ( theDatatype, 'char' )
177        theAutonanflag = 0;
178        theAutoscaleflag = 0;
179else
180        theAutonanflag = (autonan(self) == 1) & ~isempty(theFillvalue);
181        theAutoscaleflag = (autoscale(self) == 1);
182end
183theTypelen = ncmex('typelen', theDatatype);
184isUnsigned = unsigned(self);
185if theAutoscaleflag
186        theScalefactor = scalefactor(self);
187        theAddoffset = addoffset(self);
188end
189
190switch theType
191case '()'   % Variable data by index: self(..., ...).
192        indices = theSubs;
193        theSize = ncsize(self);
194        for i = 1:length(indices)
195                if isa(indices{i}, 'double')
196                        if any(diff(diff(indices{i})))
197                                disp(' ## Indexing strides must be positive and constant.')
198                                return
199                        end
200                end
201        end
202   
203% Flip and permute indices before proceeding,
204%  since we are using virtual indexing.
205   
206        theOrientation = orient(self);
207        if any(theOrientation < 0) | any(diff(theOrientation) ~= 1)
208                for i = 1:length(theOrientation)
209                        if theOrientation(i) < 0
210                                if isa(indices{i}, 'double')   % Slide the indices.
211                                        indices{i} = fliplr(theSize(i) + 1 - indices{i});
212                                end
213                        end
214                end
215                indices(abs(theOrientation)) = indices;
216                theSize(abs(theOrientation)) = theSize;
217        end
218
219        if prod(theSize) > 0
220
221                %
222                % Singleton variables end up with an empty "theSize".  But,
223                % prod(theSize) still results in 1.  Yeah, that makes sense.
224                % This results in [] being passed into the mex file for the
225                % index.  Yeah, ***THAT*** makes sense.  It actually works for
226                % a singleton, but causes a segmentation fault otherwise.
227                % Bad state of affairs.  So we need to watch for this.
228                % The way out is to make sure that singletons get a start
229                % index of 0.
230                %
231                % JGE
232                if isempty(theSize)
233                        start = 0;
234                else
235                        start = zeros(1, length(theSize));
236                end
237
238                count = ones(1, length(theSize));
239                stride = ones(1, length(theSize));
240                for i = 1:min(length(indices), length(theSize))
241                                k = indices{i};
242                                if ~isstr(k) & ~strcmp(k, ':') & ~strcmp(k, '-')
243                                start(i) = k(1)-1;
244                                count(i) =  length(k);
245                                d = 0;
246                                if length(k) > 1, d = diff(k); end
247                                stride(i) = max(d(1), 1);
248                        else
249                                count(i) = -1;
250                                if i == length(indices) & i < length(theSize)
251                                        j = i+1:length(theSize);
252                                        count(j) = -ones(1, length(j));
253                                end
254                        end
255                end
256                start(start < 0) = 0;
257                stride(stride < 0) = 1;
258                for i = 1:length(count)
259                        if count(i) == -1
260                                maxcount = fix((theSize(i)-start(i)+stride(i)-1) ./ stride(i));
261                                count(i) = maxcount;
262                        end
263                end
264                theNetCDF = parent(self);
265                theNetCDF = endef(theNetCDF);
266                count(count < 0) = 0;
267                if any(count == 0), error(' ## Bad count.'), end
268                if all(count == 1)
269                        [result, status] = ncmex('varget1', ncid(self), varid(self), ...
270                                                                                start, 0);
271
272elseif all(stride == 1)
273
274                        [result, status] = ncmex('varget', ncid(self), varid(self), ...
275                                                                                start, count, 0);
276                else
277                        imap = [];
278                        [result, status] = ncmex('vargetg', ncid(self), varid(self), ...
279                                                                                start, count, stride, imap, ...
280                                                                                0);
281                end
282                if theAutonanflag & status >= 0
283                        f = find(result == theFillvalue);
284                        if any(f), result(f) = NaN; end
285                end
286                if theAutoscaleflag & status >= 0
287                        result = result .* theScalefactor + theAddoffset;
288                end
289                if isUnsigned & prod(size(result)) > 0
290                        result(result < 0) = 2^(8*theTypelen) + result(result < 0);
291                end
292         else
293                result = [];
294                status = 0;
295        end
296        if status >= 0 & prod(size(result)) > 0 & (ndims(result)==2) & (strcmp(class(result),'char')) & any(find(size(result)==1))
297                %
298                % If the read operation was successful
299                % and if something was actually returned
300                % and if that something has exactly two dimensions
301                % and if that something was character
302                % and if that character string is actually 1D (ndims never returns 1)
303                % then do not permute.
304                %
305                % This way 1D character arrays are loaded as column vectors.
306                %
307                % Now if you'll excuse me, after writing this code fragment, I have to go
308                % wash my hands vigorously for a few hours (get it off, get it off, get it off, unclean..)
309                ;
310
311        elseif status >= 0 & prod(size(result)) > 0
312                result = permute(result, length(size(result)):-1:1);
313                theOrientation = orient(self);
314                if any(theOrientation < 0) | any(diff(theOrientation) ~= 1)
315                        for i = 1:length(theOrientation)
316                                if theOrientation(i) < 0
317                                        result = flipdim(result, abs(theOrientation(i)));
318                                end
319                        end
320                        if length(theOrientation) < 2
321                                theOrientation = [theOrientation 2];
322                        end
323                        result = permute(result, abs(theOrientation));
324                end
325        elseif status >= 0 & prod(size(result)) == 0
326                result = [];
327        else
328                status, prod_size_result = prod(size(result))   % ***
329                warning(' ## ncvar/subsref failure.')
330        end
331case '.'   % Attribute: self.theAttname(...)
332        theAttname = theSubs;
333        while length(s) > 0   % Dotted name.
334                switch s(1).type
335                case '.'
336                        theAttname = [theAttname '.' s(1).subs];
337                        s(1) = [];
338                otherwise
339                        break
340                end
341        end
342        result = att(self, theAttname);
343        if ~isempty(result), result = subsref(result, s); end
344otherwise
345        warning([' ## Illegal syntax: "' theType '"'])
346end
347
348if nargout > 0   % Always true.
349        theResult = result;
350else   % Is there any way to force this?
351        c = ncatt('C_format', self);
352        if ~isempty(c)
353                c = c(:);
354                s = size(result)
355                result = result.';
356                result = result(:);
357                step = prod(s)/s(1);
358                k = 1:step;
359                for i = 1:s(1)
360                        fprintf(c, result(k));
361                        fprintf('\n');
362                        k = k + step;
363                end
364        else
365                disp(result)
366        end
367end
Note: See TracBrowser for help on using the repository browser.