source: trunk/src/nc2struct.m @ 660

Last change on this file since 660 was 648, checked in by sommeria, 11 years ago

get_field updated, several bugs corrected,open_uvmat suppressd

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