source: trunk/src/nc2struct.m @ 748

Last change on this file since 748 was 748, checked in by sommeria, 10 years ago

update for 3D plots, panel Coordiantes introduces, while coordiantes now called Axes

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