source: trunk/src/nc2struct.m @ 749

Last change on this file since 749 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
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
[693]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
[534]18%         .Txt: error message
[140]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
[8]23%INPUT:
[140]24%  nc:  name of a netcdf file (char string) or netcdf object   
25%  additional arguments:
[648]26%       -no additional arguments: all the variables of the netcdf file are read.
[140]27%       -a cell array, ListVarName, made of  char strings {'VarName1', 'VarName2',...} )
[648]28%         if ListVarName=[] or {}, no variable value is read (only global attributes and list of variables and dimensions)
[140]29%         if ListVarName is absent, or = '*', ALL the variables of the netcdf file are read.
[747]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.
[648]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   
[747]54function [Data,var_detect,ichoice,errormsg]=nc2struct(nc,varargin)
55errormsg='';%default error message
[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
[747]68    if ischar(nc)
[8]69        if exist(nc,'file')
[150]70            try
[747]71                nc=netcdf.open(nc,'NC_NOWRITE');
72                testfile=1;
[227]73            catch ME
[747]74                errormsg=['ERROR opening ' nc ': ' ME.message];
75                return
[150]76            end
[8]77        else
[747]78            errormsg=['ERROR:file ' nc ' does not exist'];
79            return
[8]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
[747]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)
[747]96        return
[8]97    end
[648]98   
99    %% time variable or dimension
100    input_index=1;
[747]101    CheckTimeVar=0;
102    TimeVarName='';
[648]103    if isequal(varargin{1},'TimeVarName')
104        TimeVarName=varargin{2};
[747]105        CheckTimeVar=1;
106        TimeIndex=varargin{3};
107        input_index=4;% list of varibles to read is at fourth argument
[648]108    elseif isequal(varargin{1},'TimeDimName')
109        TimeDimName=varargin{2};
[747]110        TimeIndex=varargin{3};
[648]111        input_index=4;
112    end
[747]113   
[140]114    %% full reading: get the nbre of dimensions, variables, global attributes
[747]115    ListVarName=varargin{input_index};
[140]116    [ndims,nvars,ngatts]=netcdf.inq(nc);%nbre of dimensions, variables, global attributes, in the netcdf file
[8]117   
[140]118    %%  -------- read all global attributes (constants)-----------
[8]119    Data.ListGlobalAttribute={};%default
[527]120    att_key=cell(1,ngatts);%default
[8]121    for iatt=1:ngatts
122        keystr= netcdf.inqAttName(nc,netcdf.getConstant('NC_GLOBAL'),iatt-1);
[227]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
[236]129            if ischar(valuestr) %& length(valuestr)<200 & double(valuestr)<=122 & double(valuestr)>=48 %usual characters
[227]130                eval(['Data.' keystr '=''' valuestr ''';'])
[8]131            elseif isnumeric(valuestr)
132                eval(['Data.' keystr '=valuestr;'])
[227]133            else
[747]134                eval(['Data.' keystr '='';'])
[8]135            end
[227]136            att_key{iatt}=keystr;
137        catch ME
138            att_key{iatt}=['attr_' num2str(iatt)];
[527]139            Data.(att_key{iatt})=[];
[8]140        end
141    end
142    Data.ListGlobalAttribute=att_key;
[747]143   
[140]144    %%  -------- read dimension names-----------
[527]145    ListDimNameNetcdf=cell(1,ndims);
146    dim_value=zeros(1,ndims);
[140]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
[8]149    end
[747]150    if ~isempty(ListDimNameNetcdf)
[140]151        flag_used=zeros(1,ndims);%initialize the flag indicating the selected dimensions in the list (0=unused)
[8]152    end
[648]153    if isequal(varargin{1},'TimeDimName')% time dimension introduced
[747]154        TimeDimIndex=find(strcmp(TimeDimName,ListDimNameNetcdf));
[648]155        if isempty(TimeDimIndex)
[747]156            errormsg=['requested time dimension ' varargin{2} ' not found'];
[648]157            return
158        end
159        if dim_value(TimeDimIndex)<varargin{3}
[747]160           errormsg=['requested time index ' num2str(varargin{3}) ' exceeds matrix dimension'];
[648]161            return
162        end
[747]163    end 
164   
[140]165    %%  -------- read names of variables -----------
[527]166    ListVarNameNetcdf=cell(1,nvars); %default
167    dimids=cell(1,nvars);
168    nbatt=zeros(1,nvars);
[140]169    for ncvar=1:nvars %loop on the variables of the netcdf file
[747]170        %get name, type, dimensions and attribute numbers of each variable
[693]171        [ListVarNameNetcdf{ncvar},xtype(ncvar),dimids{ncvar},nbatt(ncvar)] = netcdf.inqVar(nc,ncvar-1);
[747]172    end
173%     testmulti=0;
[140]174    if isequal(ListVarName,'*')||isempty(ListVarName)
[747]175        var_index=1:nvars; %all the variables are selected in the netcdf file
[140]176        Data.ListVarName=ListVarNameNetcdf;
177    else   %select input variables, if requested by the input ListVarName
[527]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
[517]182            end
183        end
[747]184        ListVarName=ListVarName(:,logical(check_keep));
[748]185        if size(ListVarName,1)>1 %multiple choice of variable ranked by order of priority
186            for iline=1:size(ListVarName,1)
[140]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
[8]190                end
191            end
[140]192            ichoice=iline-1;%selected line number in the list of input names of variables
193        else
194            iline=1;
[8]195        end
[747]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
[748]206        var_index=zeros(1,size(ListVarName,2));%default list of variable indices
[747]207        for ivar=1:size(ListVarName,2)
[140]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
[8]211            end
212        end
[747]213        var_detect=(var_index~=0);%=1 for detected variables
[140]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
[8]217    end
[747]218   
219    %% get the dimensions and attributes associated to  variables
220    var_dim=cell(size(var_index));% initiate list of dimensions for variables
[140]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
[8]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);
[227]228            attname=regexprep(attname,{'\','/','\.','-',' '},{'','','','',''});%remove  '\','.' or '-' if exists
229            if strcmp(attname(1),'_')
230                attname(1)=[];
231            end
232            try
[747]233                if isempty(valuestr)
234                    Data.VarAttribute{ivar}.(attname)=valuestr;
235                end
[227]236            catch ME
237                display(attname)
238                display(valuestr)
[747]239                display(ME.message)
[693]240                Data.VarAttribute{ivar}.(['atrr_' num2str(iatt)])='not read';
[227]241            end
[8]242        end
243    end
[648]244   
[140]245    %% select the dimensions used for the set of input variables
[747]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);
[421]249        Data.DimValue=dim_value(dim_index);
[747]250        if input_index==4% if a dimension is selected as time
251            Data.DimValue(TimeDimIndex)=numel(TimeIndex);
252        end
[8]253    end
[140]254   
255    %% get the values of the input variables
[8]256    if  ~isempty(ListVarName)
[140]257        for ivar=1:length(var_index)
[8]258            VarName=Data.ListVarName{ivar};
[747]259            VarName=regexprep(VarName,'-','_'); %suppress '-' if it exists in the netcdf variable name (leads to errors in matlab)
260%             CheckSub=0;
[648]261            if input_index==4% if a dimension is selected as time
[747]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
[648]276            end
[747]277            if xtype(var_index(ivar))==5
[693]278                Data.(VarName)=double(Data.(VarName)); %transform to double for single pecision
[648]279            end
[8]280        end
281    end
[693]282    Data.VarType=xtype(var_index);
[140]283   
284    %%  -------- close fle-----------
[8]285    if testfile==1
[747]286        netcdf.close(nc)
[8]287    end
[140]288   
[747]289    %% old netcdf library
[8]290else
291    [Data,var_detect,ichoice]=nc2struct_toolbox(nc,varargin);
292end
Note: See TracBrowser for help on using the repository browser.