source: Roms_tools/mexcdf/snctools/nc_varget.m @ 1

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

import Roms_Agrif

File size: 12.8 KB
Line 
1function data = nc_varget(ncfile, varname, varargin )
2% NC_VARGET:  Retrieve data from a netCDF variable.
3%
4% DATA = NC_VARGET(NCFILE,VARNAME) retrieves all the data from the
5% variable VARNAME in the netCDF file NCFILE.
6%
7% DATA = NC_VARGET(NCFILE,VARNAME,START,COUNT) retrieves the contiguous
8% portion of the variable specified by the index vectors START and
9% COUNT.  Remember that SNCTOOLS indexing is zero-based, not
10% one-based.  Specifying a -1 in COUNT means to retrieve everything
11% along that dimension from the START coordinate.
12%
13% DATA = NC_VARGET(NCFILE,VARNAME,START,COUNT,STRIDE) retrieves
14% a non-contiguous portion of the dataset.  The amount of
15% skipping along each dimension is given through the STRIDE vector.
16%
17% NCFILE can also be an OPeNDAP URL if the proper java SNCTOOLS
18% backend is installed.  See the README for details.
19%
20% NC_VARGET tries to be intelligent about retrieving the data.
21% Since most general matlab operations are done in double precision,
22% retrieved numeric data will be cast to double precision, while
23% character data remains just character data. 
24%
25% Singleton dimensions are removed from the output data. 
26%
27% A '_FillValue' attribute is honored by flagging those datums as NaN.
28% A 'missing_value' attribute is honored by flagging those datums as
29% NaN.  The exception to this is for NC_CHAR variables, as mixing
30% character data and NaN doesn't really seem to work in matlab.
31%
32% If the named NetCDF variable has valid scale_factor and add_offset
33% attributes, then the data is scaled accordingly. 
34%
35% Setting the preference 'PRESERVE_FVD' to true will compel NC_VARGET
36% to preserve the fastest varying dimension.  This basically means
37% that NC_VARGET will not transpose the data.  This basically flips
38% the order of the dimension IDs from what one would see by using
39% the ncdump C utility.  You may get a substantial performance boost from
40% this.
41%
42% EXAMPLE:
43% #1.  In this case, the variable in question has rank 2, and has size
44%      500x700.  We want to retrieve starting at row 300, column 250.
45%      We want 100 contiguous rows, 200 contiguous columns.
46%
47%      vardata = nc_varget ( file, variable_name, [300 250], [100 200] );
48%
49
50%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
51%
52% $Id: nc_varget.m 2681 2009-04-28 14:55:17Z johnevans007 $
53% $LastChangedDate: 2009-04-28 10:55:17 -0400 (Tue, 28 Apr 2009) $
54% $LastChangedRevision: 2681 $
55% $LastChangedBy: johnevans007 $
56%
57%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
58
59
60
61error(nargchk(2,5,nargin,'struct'));
62error(nargoutchk(0,1,nargout,'struct'));
63
64[start, count, stride] = parse_and_validate_args(ncfile,varname,varargin{:});
65
66retrieval_method = snc_read_backend(ncfile);
67switch(retrieval_method)
68        case 'tmw'
69                data = nc_varget_tmw(ncfile,varname,start,count,stride);
70        case 'java'
71                data = nc_varget_java(ncfile,varname,start,count,stride);
72        case 'mexnc'
73                data = nc_varget_mexnc(ncfile,varname,start,count,stride);
74end
75
76return
77
78
79
80
81
82
83
84
85
86
87
88%----------------------------------------------------------------------
89function values = nc_varget_mexnc(ncfile,varname,start,count,stride)
90
91
92
93[ncid,status]=mexnc('open',ncfile,'NOWRITE');
94if status ~= 0
95    ncerr = mexnc('strerror', status);
96    error ( 'SNCTOOLS:NC_VARGET:MEXNC:OPEN', ncerr );
97end
98
99
100[varid, status]=mexnc('inq_varid',ncid,varname);
101if status ~= 0
102    ncerr = mexnc('strerror', status);
103    mexnc('close',ncid);
104    error ( 'SNCTOOLS:NC_VARGET:MEXNC:INQ_VARID', ncerr );
105end
106
107[dud,var_type,nvdims,dimids,dud,status]=mexnc('inq_var',ncid,varid);
108if status ~= 0
109    mexnc('close',ncid);
110    error ( 'SNCTOOLS:NC_VARGET:MEXNC:INQ_VAR', mexnc('strerror',status) );
111end
112
113
114% mexnc does not preserve the fastest varying dimension.  If we want this,
115% then we flip the indices.
116preserve_fvd = getpref('SNCTOOLS','PRESERVE_FVD',false);
117if preserve_fvd
118    start = fliplr(start);
119    count = fliplr(count);
120    stride = fliplr(stride);
121end
122
123
124%
125% Check that the start, count, stride parameters have appropriate lengths.
126% Otherwise we get confusing error messages later on.
127validate_index_vectors(start,count,stride,nvdims);
128
129%
130% What mexnc operation will we use?
131[funcstr_family, funcstr] = determine_funcstr ( var_type, nvdims, start, count, stride );
132
133
134the_var_size = determine_varsize_mex ( ncid, dimids, nvdims );
135
136%
137% If the user had set non-positive numbers in "count", then we replace them
138% with what we need to get the rest of the variable.
139negs = find(count<0);
140count(negs) = the_var_size(negs) - start(negs);
141
142
143
144%
145% At long last, retrieve the data.
146switch funcstr_family
147    case 'get_var'
148        [values, status] = mexnc ( funcstr, ncid, varid );
149
150    case 'get_var1'
151        [values, status] = mexnc ( funcstr, ncid, varid, 0 );
152
153    case 'get_vara'
154        [values, status] = mexnc ( funcstr, ncid, varid, start, count );
155
156
157    case 'get_vars'
158        [values, status] = mexnc ( funcstr, ncid, varid, start, count, stride );
159
160    otherwise
161        error ( 'SNCTOOLS:NC_VARGET:unhandledType', ...
162                'Unhandled function string type ''%s''\n', funcstr_family );
163       
164end
165
166if ( status ~= 0 )
167    mexnc('close',ncid);
168    ncerr = mexnc('strerror', status);
169    eid = sprintf ( 'SNCTOOLS:nc_varget:%s', funcstr );
170    error ( eid, ncerr );
171end
172
173
174
175
176%
177% If it's a 1D vector, make it a column vector. 
178% Otherwise permute the data
179% to make up for the row-major-order-vs-column-major-order issue.
180if length(the_var_size) == 1
181    values = values(:);
182else
183    % Ok it's not a 1D vector.  If we are not preserving the fastest
184    % varying dimension, we should permute the data.
185    if ~getpref('SNCTOOLS','PRESERVE_FVD',false)
186        pv = fliplr ( 1:length(the_var_size) );
187        values = permute(values,pv);
188    end
189end                                                                                   
190
191
192values = handle_fill_value_mex ( ncid, varid, var_type, values );
193values = handle_mex_missing_value ( ncid, varid, var_type, values );
194values = handle_scaling_mex ( ncid, varid, values );
195
196
197%
198% remove any singleton dimensions.
199values = squeeze ( values );
200
201
202mexnc('close',ncid);
203
204
205return
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223%--------------------------------------------------------------------------
224function [start, count, stride] = parse_and_validate_args(ncfile,varname,varargin)
225
226%
227% Set up default outputs.
228start = [];
229count = [];
230stride = [];
231
232
233switch nargin
234case 4
235    start = varargin{1};
236    count = varargin{2};
237
238case 5
239    start = varargin{1};
240    count = varargin{2};
241    stride = varargin{3};
242
243end
244
245
246
247%
248% Error checking on the inputs.
249if ~ischar(ncfile)
250    error ( 'SNCTOOLS:NC_VARGET:badInput', 'the filename must be character.' );
251end
252if ~ischar(varname)
253    error ( 'SNCTOOLS:NC_VARGET:badInput', 'the variable name must be character.' );
254end
255
256if ~isnumeric ( start )
257    error ( 'SNCTOOLS:NC_VARGET:badInput', 'the ''start'' argument must be numeric.' );
258end
259if ~isnumeric ( count )
260    error ( 'SNCTOOLS:NC_VARGET:badInput', 'the ''count'' argument must be numeric.' );
261end
262if ~isnumeric ( stride )
263    error ( 'SNCTOOLS:NC_VARGET:badInput', 'the ''stride'' argument must be numeric.' );
264end
265
266
267return
268
269
270
271
272
273
274
275
276
277%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
278%
279% DETERMINE_FUNCSTR
280%     Determines if we are to use, say, 'get_var1_text', or 'get_vars_double',
281%     or whatever.
282
283function [prefix,funcstr] = determine_funcstr ( var_type, nvdims, start, count, stride )
284
285%
286% Determine if we are retriving a single value, the whole variable, a
287% contiguous portion, or a strided portion.
288if nvdims == 0
289
290    %
291    % It is a singleton variable.
292    prefix = 'get_var1';
293
294elseif isempty(start)
295   
296    %
297    % retrieving the entire variable.
298    prefix = 'get_var';
299
300elseif ~isempty(start) && ~isempty(count) && isempty(stride)
301   
302    %
303    % retrieving a contiguous portion
304    prefix = 'get_vara';
305
306elseif ~isempty(start) && ~isempty(count) && ~isempty(stride)
307   
308    %
309    % retrieving a contiguous portion
310    prefix = 'get_vars';
311
312else
313    error ( 'SNCTOOLS:NC_VARGET:FUNCSTR', 'Could not determine funcstr prefix.' );
314end
315
316
317
318switch ( var_type )
319    case nc_char
320        funcstr = [prefix '_text'];
321
322    case { nc_double, nc_float, nc_int, nc_short, nc_byte }
323        funcstr = [prefix '_double'];
324
325    otherwise
326        error ( 'SNCTOOLS:NC_VARGET:badDatatype', ...
327                'Unhandled datatype %d.', var_type );
328
329end
330return
331
332
333
334
335
336%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
337%
338% HANDLE_MEX_FILL_VALUE
339%     If there is a fill value, then replace such values with NaN.
340%
341%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
342function values = handle_fill_value_mex ( ncid, varid, var_type, values )
343
344%
345% Handle the fill value, if any.  Change those values into NaN.
346[dud, dud, status] = mexnc('INQ_ATT', ncid, varid, '_FillValue' );
347if ( status == 0 )
348
349    switch ( var_type )
350    case nc_char
351        %
352        % For now, do nothing.  Does a fill value even make sense with char data?
353        % If it does, please tell me so.
354
355    case { nc_double, nc_float, nc_int, nc_short, nc_byte }
356        [fill_value, status] = mexnc ( 'get_att_double', ncid, varid, '_FillValue' );
357        values(values==fill_value) = NaN;
358
359    otherwise
360        mexnc('close',ncid);
361        error ( 'SNCTOOLS:nc_varget:mexnc:unhandledFillValueDatatype', ...
362                'Unhandled datatype %d.', var_type );
363    end
364
365    if ( status ~= 0 )
366        mexnc('close',ncid);
367        ncerr = mexnc ( 'strerror', status );
368        error ( 'SNCTOOLS:NC_VARGET:MEXNC:GET_ATT', ncerr );
369    end
370
371
372
373end
374
375return
376
377
378
379
380%--------------------------------------------------------------------------
381function values = handle_mex_missing_value ( ncid, varid, var_type, values )
382% HANDLE_MEX_MISSING_VALUE
383%     If there is a missing value, then replace such values with NaN.
384
385%
386% If there is a fill value attribute, then that had precedence.  Do nothing.
387[dud, dud, status] = mexnc('INQ_ATT', ncid, varid, '_FillValue' );
388if status == 0
389    return
390end
391
392%
393% Handle the missing value, if any.  Change those values into NaN.
394[dud, dud, status] = mexnc('INQ_ATT', ncid, varid, 'missing_value' );
395if ( status == 0 )
396
397    switch ( var_type )
398    case nc_char
399        %
400        % For now, do nothing.  Does a fill value even make sense with char data?
401        % If it does, please tell me so.
402
403    case { nc_double, nc_float, nc_int, nc_short, nc_byte }
404        [fill_value, status] = mexnc ( 'get_att_double', ncid, varid, 'missing_value' );
405        values(values==fill_value) = NaN;
406
407    otherwise
408        mexnc('close',ncid);
409        error ( 'SNCTOOLS:nc_varget:mexnc:unhandledDatatype', ...
410                'Unhandled datatype %d.', var_type );
411
412    end
413
414    if ( status ~= 0 )
415        mexnc('close',ncid);
416        ncerr = mexnc ( 'strerror', status );
417        error ( 'SNCTOOLS:NC_VARGET:MEXNC:GET_ATT', ncerr );
418    end
419
420
421end
422
423return
424
425
426
427
428
429
430%--------------------------------------------------------------------------
431function values = handle_scaling_mex ( ncid, varid, values )
432% HANDLE_MEX_SCALING
433%     If there is a scale factor and/or  add_offset attribute, convert the data
434%     to double precision and apply the scaling.
435
436have_scale = false;
437have_addoffset = false;
438[dud, dud, status] = mexnc('INQ_ATT', ncid, varid, 'scale_factor' );
439if ( status == 0 )
440    have_scale = true;
441end
442[dud, dud, status] = mexnc('INQ_ATT', ncid, varid, 'add_offset' );
443if ( status == 0 )
444    have_addoffset = true;
445end
446
447%
448% Return early if we don't have either one.
449if ~(have_scale || have_addoffset)
450    return;
451end
452
453scale_factor = 1.0;
454add_offset = 0.0;
455
456if have_scale
457    [scale_factor, status] = mexnc ( 'get_att_double', ncid, varid, 'scale_factor' );
458    if ( status ~= 0 )
459        mexnc('close',ncid);
460        ncerr = mexnc('strerror', status);
461        error ( 'SNCTOOLS:NC_VARGET:MEXNC:GET_ATT_DOUBLE', ncerr );
462    end
463end
464
465if have_addoffset
466    [add_offset, status] = mexnc ( 'get_att_double', ncid, varid, 'add_offset' );
467    if ( status ~= 0 )
468        mexnc('close',ncid);
469        ncerr = mexnc('strerror', status);
470        error ( 'SNCTOOLS:NC_VARGET:MEXNC:GET_ATT_DOUBLE', ncerr );
471    end
472end
473
474values = double(values) * scale_factor + add_offset;
475
476return
477
478
479
480
481
482
483
484
485%-----------------------------------------------------------------------
486function the_var_size = determine_varsize_mex ( ncid, dimids, nvdims )
487% DETERMINE_VARSIZE_MEX: Need to figure out just how big the variable is.
488%
489% VAR_SIZE = DETERMINE_VARSIZE_MEX(NCID,DIMIDS,NVDIMS);
490
491%
492% If not a singleton, we need to figure out how big the variable is.
493if nvdims == 0
494    the_var_size = 1;
495else
496    the_var_size = zeros(1,nvdims);
497    for j=1:nvdims,
498        dimid = dimids(j);
499        [dim_size,status]=mexnc('inq_dimlen', ncid, dimid);
500        if ( status ~= 0 )
501            ncerr = mexnc ( 'strerror', status );
502            mexnc('close',ncid);
503            error ( 'SNCTOOLS:NC_VARGET:MEXNC:INQ_DIM_LEN', ncerr );
504        end
505        the_var_size(j)=dim_size;
506    end
507end
508
509return
510
511
512
513
Note: See TracBrowser for help on using the repository browser.