source: trunk/src/nc2struct.m @ 742

Last change on this file since 742 was 693, checked in by sommeria, 11 years ago

bug repaired geometry_calib/Detect grid, + corrections in get_field

File size: 13.0 KB
Line 
1%'nc2struct': transform a netcdf file in a corresponding matlab structure
2% it reads all the global attributes and all variables, or a selected list.
3% The corresponding dimensions and variable attributes are then extracted
4%----------------------------------------------------------------------
5% function [Data,var_detect,ichoice]=nc2struct(nc,varargin)
6%
7% OUTPUT:
8%  Data: structure containing all the information of the netcdf file (or netcdf object)
9%           with (optional)fields:
10%                    .ListGlobalAttribute: cell listing the names of the global attributes
11%                    .Att_1,Att_2... : values of the global attributes
12%                    .ListVarName: list of variable names to select (cell array of  char strings {'VarName1', 'VarName2',...} )
13%                    .VarDimName: list of dimension names for each element of .ListVarName (cell array of string cells)                         
14%                    .Var1, .Var2....: variables (Matlab arrays) with names listed in .ListVarName
15%                  .ListDimName=list of dimension (added information, not requested for field description)
16%                  .DimValue= vlalues of dimensions (added information, not requested for field description)
17%                  .VarType= integers giving the type of variable as coded by netcdf= 2 for char, =4 for single,=( for double
18%         .Txt: error message
19%  var_detect: vector with same length as the cell array ListVarName, = 1 for each detected variable and 0 else.
20%            var_detect=[] in the absence of input cell array
21%  ichoice: index of the selected line in the case of multiple choice
22%        (cell array of varible names with multiple lines) , =[] by default
23%INPUT:
24%  nc:  name of a netcdf file (char string) or netcdf object   
25%  additional arguments:
26%       -no additional arguments: all the variables of the netcdf file are read.
27%       -a cell array, ListVarName, made of  char strings {'VarName1', 'VarName2',...} )
28%         if ListVarName=[] or {}, no variable value is read (only global attributes and list of variables and dimensions)
29%         if ListVarName is absent, or = '*', ALL the variables of the netcdf file are read.
30%         if ListVarName is a cell array with n lines, the set of variables will be sought by order of priority
31%                  in the list, while output names will be set by the first line
32%        - the string 'ListGlobalAttribute' followed by a list of attribute  names: reads only these attributes (fast reading)
33%        - the string 'TimeVarName', a string (the variable considered as
34%        time), an integer (the selected time index), the cell of other
35%        input variables limited to the input time index (considered as the last index of arrays)
36%        - the string 'TimeDimName', a string (the dimension considered as time), an integer (the selected time index), the cell of other
37%        input variables limited to the input time index (considered as the last index of arrays)
38
39%AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
40%  Copyright Joel Sommeria, 2008, LEGI / CNRS-UJF-INPG, sommeria@coriolis-legi.org.
41%AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
42%     This file is part of the toolbox UVMAT.
43%
44%     UVMAT is free software; you can redistribute it and/or modify
45%     it under the terms of the GNU General Public License as published by
46%     the Free Software Foundation; either version 2 of the License, or
47%     (at your option) any later version.
48%
49%     UVMAT is distributed in the hope that it will be useful,
50%     but WITHOUT ANY WARRANTY; without even the implied warranty of
51%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
52%     GNU General Public License (file UVMAT/COPYING.txt) for more details.
53%AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
54   
55function [Data,var_detect,ichoice]=nc2struct(nc,varargin)
56
57if isempty(varargin)
58    varargin{1}='*';
59end
60hhh=which('netcdf.open');% look for built-in matlab netcdf library
61
62if ~isequal(hhh,'')
63    %% default output
64    Data=[];%default
65    var_detect=[];%default
66    ichoice=[];%default
67   
68    %% open the netcdf file for reading
69    if ischar(nc)
70        if exist(nc,'file')
71            try
72            nc=netcdf.open(nc,'NC_NOWRITE');
73            testfile=1;
74            catch ME
75              Data.Txt=['ERROR opening ' nc ': ' ME.message];
76              return
77            end
78        else
79           Data.Txt=['ERROR:file ' nc ' does not exist'];
80           return
81        end
82    else
83        testfile=0;
84    end
85   
86    %% short reading option for global attributes only, if the first argument is 'ListGlobalAttribute'
87    if isequal(varargin{1},'ListGlobalAttribute')
88        for ilist=2:numel(varargin)
89            valuestr=[];%default
90            try
91            valuestr = netcdf.getAtt(nc,netcdf.getConstant('NC_GLOBAL'),varargin{ilist});
92            catch ME
93            end
94            eval(['Data.' varargin{ilist} '=valuestr;'])
95        end
96        netcdf.close(nc)
97       return
98    end
99   
100    %% time variable or dimension
101    input_index=1;
102    if isequal(varargin{1},'TimeVarName')
103        TimeVarName=varargin{2};
104        TimeVarIndex=varargin{3};
105        input_index=4;
106    elseif isequal(varargin{1},'TimeDimName')
107        TimeDimName=varargin{2};
108        TimeVarIndex=varargin{3};
109        input_index=4;
110    end
111
112    %% full reading: get the nbre of dimensions, variables, global attributes
113    ListVarName=varargin{input_index};
114    [ndims,nvars,ngatts]=netcdf.inq(nc);%nbre of dimensions, variables, global attributes, in the netcdf file
115   
116    %%  -------- read all global attributes (constants)-----------
117    Data.ListGlobalAttribute={};%default
118    att_key=cell(1,ngatts);%default
119    for iatt=1:ngatts
120        keystr= netcdf.inqAttName(nc,netcdf.getConstant('NC_GLOBAL'),iatt-1);
121        valuestr = netcdf.getAtt(nc,netcdf.getConstant('NC_GLOBAL'),keystr);
122        keystr=regexprep(keystr,{'\','/','\.','-',' '},{'','','','',''});%remove  '\','.' or '-' if exists
123        if strcmp(keystr(1),'_')
124            keystr(1)=[];
125        end
126        try
127            if ischar(valuestr) %& length(valuestr)<200 & double(valuestr)<=122 & double(valuestr)>=48 %usual characters
128                eval(['Data.' keystr '=''' valuestr ''';'])
129            elseif isnumeric(valuestr)
130                eval(['Data.' keystr '=valuestr;'])
131            else
132                eval(['Data.' keystr '='';'])
133            end
134            att_key{iatt}=keystr;
135        catch ME
136            att_key{iatt}=['attr_' num2str(iatt)];
137            Data.(att_key{iatt})=[];
138        end
139    end
140    Data.ListGlobalAttribute=att_key;
141
142    %%  -------- read dimension names-----------
143    ListDimNameNetcdf=cell(1,ndims);
144    dim_value=zeros(1,ndims);
145    for idim=1:ndims %loop on the dimensions of the netcdf file
146        [ListDimNameNetcdf{idim},dim_value(idim)] = netcdf.inqDim(nc,idim-1);%get name and value of each dimension
147    end
148    if ~isempty(ListDimNameNetcdf)
149        flag_used=zeros(1,ndims);%initialize the flag indicating the selected dimensions in the list (0=unused)
150    end
151    if isequal(varargin{1},'TimeDimName')% time dimension introduced
152        TimeDimIndex=find(strcmp(varargin{2},ListDimNameNetcdf));
153        if isempty(TimeDimIndex)
154            Data.Txt=['requested time dimension ' varargin{2} ' not found'];
155            return
156        end
157        if dim_value(TimeDimIndex)<varargin{3}
158            Data.Txt=['requested time index ' num2str(varargin{3}) ' exceeds matrix dimension'];
159            return
160        end
161    end
162 
163    %%  -------- read names of variables -----------
164    ListVarNameNetcdf=cell(1,nvars); %default
165    dimids=cell(1,nvars);
166    nbatt=zeros(1,nvars);
167    for ncvar=1:nvars %loop on the variables of the netcdf file
168        %get name, type, dimensions and attribute numbers of each variable
169        [ListVarNameNetcdf{ncvar},xtype(ncvar),dimids{ncvar},nbatt(ncvar)] = netcdf.inqVar(nc,ncvar-1);
170    end 
171    testmulti=0;
172    if isequal(ListVarName,'*')||isempty(ListVarName)
173        var_index=1:nvars; %all the variables are selected in the netcdf file
174        Data.ListVarName=ListVarNameNetcdf;
175    else   %select input variables, if requested by the input ListVarName
176        ind_remove=[];
177        check_keep=ones(1,size(ListVarName,2));
178        for ivar=1:size(ListVarName,2) % check redondancy of variable names
179            if ~isempty(find(strcmp(ListVarName{1,ivar},ListVarName(1:ivar-1)), 1))
180                check_keep(ivar)=0;% the variable #ivar is already in the list
181            end
182        end
183        ListVarName=ListVarName(:,logical(check_keep));         
184        sizvar=size(ListVarName);
185        testmulti=(sizvar(1)>1);%test for multiple choice of variable ranked by order of priority
186        var_index=zeros(1,sizvar(2));%default
187        if testmulti %multiple choice of variable ranked by order of priority
188            for iline=1:sizvar(1)
189                search_index=find(strcmp(ListVarName{iline,1},ListVarNameNetcdf),1);%look for the first variable name in the list of netcdf variables
190                if ~isempty(search_index)
191                    break % go to the next line
192                end
193            end
194            ichoice=iline-1;%selected line number in the list of input names of variables
195        else
196            iline=1;
197        end
198        for ivar=1:sizvar(2)
199            search_index=find(strcmp(ListVarName{iline,ivar},ListVarNameNetcdf),1);%look for the variable name in the list of netcdf file
200            if ~isempty(search_index)
201                var_index(ivar)=search_index;%index of the netcdf list corresponding to the input list index ivar
202            end
203        end
204        var_detect=(var_index~=0);%=1 for detected variables         
205        list_index=find(var_index);% indices in the input list corresponding to a detected variable
206        var_index=var_index(list_index);% netcdf variable indices corresponding to the output list of read variable
207        Data.ListVarName=ListVarName(1,list_index);%the first line of ListVarName sets the output names of the variables
208    end
209     
210  %% get the dimensions and attributes associated to  variables
211  var_dim=cell(size(var_index));% initiate list of dimensions for variables
212    for ivar=1:length(var_index)
213        var_dim{ivar}=dimids{var_index(ivar)}+1; %netcdf dimension indices used by the variable #ivar
214        Data.VarDimName{ivar}=ListDimNameNetcdf(var_dim{ivar});
215        flag_used(var_dim{ivar})=ones(size(var_dim{ivar}));%flag_used =1 for the indices of used dimensions
216        for iatt=1:nbatt(var_index(ivar))
217            attname = netcdf.inqAttName(nc,var_index(ivar)-1,iatt-1);
218            valuestr= netcdf.getAtt(nc,var_index(ivar)-1,attname);
219            attname=regexprep(attname,{'\','/','\.','-',' '},{'','','','',''});%remove  '\','.' or '-' if exists
220            if strcmp(attname(1),'_')
221                attname(1)=[];
222            end
223            try
224             if isempty(valuestr)
225                Data.VarAttribute{ivar}.(attname)=valuestr;
226            end
227            catch ME
228                display(attname)
229                display(valuestr)
230                display(ME.message)         
231                Data.VarAttribute{ivar}.(['atrr_' num2str(iatt)])='not read';
232            end
233        end
234    end
235   
236
237    %% select the dimensions used for the set of input variables
238    if ~isempty(var_index)     
239        dim_index=find(flag_used);%list of netcdf dimensions indices corresponding to used dimensions
240        Data.ListDimName=ListDimNameNetcdf(dim_index);
241        Data.DimValue=dim_value(dim_index);
242    end
243   
244    %% get the values of the input variables
245    if  ~isempty(ListVarName)
246        for ivar=1:length(var_index)
247            VarName=Data.ListVarName{ivar};
248            VarName=regexprep(VarName,'-',''); %suppress '-' if it exists in the netcdf variable name
249            CheckSub=0;
250            if input_index==4% if a dimension is selected as time
251                if var_dim{ivar}(end)==TimeDimIndex% if the last dim of the variable is the time
252                    slice_length=prod(var_dim{ivar}(1:end-1));
253                    Data.(VarName)=double(netcdf.getVar(nc,var_index(ivar)-1,TimeIndex*slice_length,slice_length)); %read the variable data
254                    CheckSub=1;
255                end
256            end
257            if ~CheckSub
258                Data.(VarName)=netcdf.getVar(nc,var_index(ivar)-1); %read the whole variable data
259                if xtype(var_index(ivar))==5
260                Data.(VarName)=double(Data.(VarName)); %transform to double for single pecision
261                end
262            end
263        end
264    end
265    Data.VarType=xtype(var_index);
266   
267    %%  -------- close fle-----------
268    if testfile==1
269        netcdf.close(nc)
270    end
271   
272%% old netcdf library
273else
274    [Data,var_detect,ichoice]=nc2struct_toolbox(nc,varargin);
275end
Note: See TracBrowser for help on using the repository browser.