%'nc2struct': transform a netcdf file in a corresponding matlab structure % it reads all the global attributes and all variables, or a selected list. % The corresponding dimensions and variable attributes are then extracted %---------------------------------------------------------------------- % function [Data,var_detect,ichoice]=nc2struct(nc,varargin) % % OUTPUT: % Data: structure containing all the information of the netcdf file (or netcdf object) % with fields: % (optional) .ListGlobalAttribute: cell listing the names of the global attributes % .Att_1,Att_2... : values of the global attributes % .ListVarName: list of variable names to select (cell array of char strings {'VarName1', 'VarName2',...} ) % .VarDimName: list of dimension names for each element of .ListVarName (cell array of string cells) % .Var1, .Var2....: variables (Matlab arrays) with names listed in .ListVarName % .ListDimName=list of dimension (added information, not requested for field description) % .DimValue= vlalues of dimensions (added information, not requested for field description) % .VarDimIndex= list of dimension indices (added information, %INPUT: % nc: name of a netcdf file (char string) or netcdf object % additional arguments: % -in the absence of other arguments, all the fields are read % -a cell array, ListVarName, of char strings {'VarName1', 'VarName2',...} ) % if ListVarName=[] or {}, no variables is read (only global attributes) % if ListVarName is absent, or = '*', ALL the variables are read. % if ListVarName is a cell array with n lines, the set of variables % will be sought by order of priority in the list, while output names will be set by the first line % - the string 'ListGlobalAttribute' followed by a list of attribute names: reads only these attributes (fast reading) % %AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA % Copyright Joel Sommeria, 2008, LEGI / CNRS-UJF-INPG, sommeria@coriolis-legi.org. %AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA % This file is part of the toolbox UVMAT. % % UVMAT is free software; you can redistribute it and/or modify % it under the terms of the GNU General Public License as published by % the Free Software Foundation; either version 2 of the License, or % (at your option) any later version. % % UVMAT is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the % GNU General Public License (file UVMAT/COPYING.txt) for more details. %AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA function [Data,var_detect,ichoice]=nc2struct(nc,varargin) if isempty(varargin) varargin{1}='*'; end hhh=which('netcdf.open');% look for built-in matlab netcdf library if ~isequal(hhh,'') %default output Data=[]; var_detect=[]; ichoice=[];%default %open the netcdf file for reading if ischar(nc) if exist(nc,'file') nc=netcdf.open(nc,'NC_NOWRITE'); testfile=1; else Data.Txt=['ERROR:file ' nc ' does not exist']; return end else testfile=0; end % short reading of global attributes if isequal(varargin{1},'ListGlobalAttribute') for ilist=2:numel(varargin) try valuestr = netcdf.getAtt(nc,netcdf.getConstant('NC_GLOBAL'),varargin{ilist}); catch valuestr=[]; end eval(['Data.' varargin{ilist} '=valuestr;']) end netcdf.close(nc) return end % reading of variables, including attributes ListVarName=varargin{1}; [ndims,nvars,ngatts]=netcdf.inq(nc);%nbre of dimensions, variables, attributes % -------- read global attributes (constants)----------- att_key={};%default iatt_g=0; Data.ListGlobalAttribute={};%default for iatt=1:ngatts keystr= netcdf.inqAttName(nc,netcdf.getConstant('NC_GLOBAL'),iatt-1); indstr1=regexp(keystr,'\\');%detect '\\' indstr2=regexp(keystr,'\.');%detect '\.' if isempty(indstr1) && isempty(indstr2) valuestr = netcdf.getAtt(nc,netcdf.getConstant('NC_GLOBAL'),keystr); if ischar(valuestr) && length(valuestr)<200 iatt_g=iatt_g+1; indstr1=regexp(keystr,'\\');%detect '\\' indstr2=regexp(keystr,'\.');%detect '\.' if isempty(indstr1) && isempty(indstr2) eval(['Data.' keystr '=''' valuestr ''';']) att_key{iatt_g}=keystr; end elseif isempty(valuestr) iatt_g=iatt_g+1; eval(['Data.' keystr '=[];']) att_key{iatt_g}=keystr; elseif isnumeric(valuestr) iatt_g=iatt_g+1; eval(['Data.' keystr '=valuestr;']) att_key{iatt_g}=keystr; end end end Data.ListGlobalAttribute=att_key; % -------- read dimensions ----------- ListDimName={}; dim_value=[]; for idim=1:ndims%length(dim_read); [ListDimName{idim},dim_value(idim)] = netcdf.inqDim(nc,idim-1); end if ~isempty(ListDimName) %&& ~isempty(dim_value) % Data.DimValue=dim_value; % DimIndices=[1:ndims]; %index of the dimension in the netcdf file flag_used=zeros(1,ndims);%initialize test of used dimensions end % -------- read variables ----------- var_read={}; %default dimids={}; nbatt=[]; for ivar=1:nvars [var_read{ivar},xtype,dimids{ivar},nbatt(ivar)] = netcdf.inqVar(nc,ivar-1); end var_index=1:nvars; %default set of variable indices in the netcdf file testmulti=0; OutputList=[]; %select input variables, if requested by the input ListVarName if ~(isequal(ListVarName,'*')||isempty(ListVarName)) sizvar=size(ListVarName); testmulti=(sizvar(1)>1); var_index=zeros(1,sizvar(2));%default if testmulti OutputList=ListVarName(1,:); testend=0; for iline=1:sizvar(1) if testend break end % var_index=zeros(size(ListVarName));%default for ivar=1:sizvar(2) if ~isempty(ListVarName{iline,ivar}) for ilist=1:nvars if isequal(var_read{ilist},ListVarName{iline,ivar}) var_index(ivar)=ilist; % var_detect(ivar)=1; break end end if ivar==1 if var_index(ivar)==0 break%go to next line if the first nc variable is not found else testend=1; %this line will be read ichoice=iline-1; %selectedline number in the list of input names of variables end end end end end else %single list of input variables for ivar=1:sizvar(2) for ilist=1:nvars if isequal(var_read{ilist},ListVarName{ivar}) var_index(ivar)=ilist; var_detect(ivar)=1; break end end end end list_index=find(var_index); if ~isempty(list_index) if testmulti OutputList=OutputList(list_index); end var_index=var_index(list_index); var_detect=(var_index~=0); var_read=var_read(var_index); end end %select variable attributes and associate dimensions % var_dim_index=[]; %default Data.ListVarName={};%default VarDimIndex={};%default for ivar=1:length(var_read) if testmulti Data.ListVarName{ivar}=OutputList{ivar};%new name given by ListVarName(1,:) else Data.ListVarName{ivar}=var_read{ivar};%name of the variable end var_dim=dimids{var_index(ivar)}+1; %dimension indices used by the variable flag_used(var_dim)=ones(size(var_dim));%flag_used =1 for the indices of used dimensions VarDimIndex{ivar}=var_dim; %variable attributes if ivar==1 Data.VarAttribute={};%initialisation of the list of variable attributes end %variable attributes for iatt=1:nbatt(var_index(ivar)) attname = netcdf.inqAttName(nc,var_index(ivar)-1,iatt-1); valuestr= netcdf.getAtt(nc,var_index(ivar)-1,attname); if ischar(valuestr) eval(['Data.VarAttribute{ivar}.' attname '=''' valuestr ''';']) elseif isempty(valuestr) eval(['Data.VarAttribute{ivar}.' attname '=[];']) elseif isnumeric(valuestr) eval(['Data.VarAttribute{ivar}.' attname '=valuestr;']) end end end %select the used dimensions if ~isempty(var_read) % if isfield(Data,'ListDimName') %&& isfield(Data,'DimValue') % Data=rmfield(Data,'ListDimName'); % %Data=rmfield(Data,'DimValue'); % end % else % list_dim=1:ndims; dim_index=find(flag_used); % list_dim=list_dim(dim_index); old2new=cumsum(flag_used); ListDimName=ListDimName(dim_index); dim_value=dim_value(dim_index); end for ivar=1:length(var_read) %Data.VarDimIndex{ivar}=old2new(VarDimIndex{ivar});% ENLEVER Data.VarDimIndex ulterieurement %Data.VarDimName{ivar}=Data.ListDimName(Data.VarDimIndex{ivar}); Data.VarDimName{ivar}=ListDimName(old2new(VarDimIndex{ivar})); end Data.ListDimName=ListDimName; Data.DimValue=dim_value; Data.VarDimIndex= VarDimIndex; %variable values if ~isempty(ListVarName) for ivar=1:length(Data.ListVarName) VarName=Data.ListVarName{ivar}; indstr=regexp(VarName,'-');%detect '-' if ~isempty(indstr) VarName(indstr)=[]; end eval(['Data.' VarName '=netcdf.getVar(nc,var_index(ivar)-1);'])%read the variable data %eval(['siz=size(Data.' VarName ');']) % if numel(siz)<=2 %eval(['Data.' VarName '=Data.' VarName ''';'])%read the variable data %end end end % -------- close fle----------- if testfile==1 netcdf.close(nc) end else [Data,var_detect,ichoice]=nc2struct_toolbox(nc,varargin); end