%'nc2struct': transform a NetCDF file in a corresponding matlab structure % or directly read the a matlab data file .mat (calling the fct mat2struct.m) % 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,errormsg]=nc2struct(nc,varargin) % % OUTPUT: % Data: structure containing all the information of the NetCDF file (or NetCDF object) % with (optional)fields: % .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) % .VarType= integers giving the type of variable as coded by netcdf =2 for char, =4 for single,=( for double % var_detect: vector with same length as the cell array ListVarName, = 1 for each detected variable and 0 else. % var_detect=[] in the absence of input cell array % ichoice: index of the selected line in the case of multiple choice % (cell array of varible names with multiple lines) , =[] by default % % INPUT: % nc: name of a NetCDF file (char string) or NetCDF object % additional arguments: % -no additional arguments: all the variables of the NetCDF file are read. % - empty argument []: the output field structure is limited to the names of variables, without their values % -a cell array, ListVarName, made of char strings {'VarName1', 'VarName2',...} ) % if ListVarName=[] or {}, no variable value is read (only global attributes and list of variables and dimensions) % if ListVarName is absent, or = '*', ALL the variables of the NetCDF file 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) % - the string 'TimeVarName', a string (the name of the variable considered as time), an integer or vector with integer values % representing time indices to select for each variable, the cell of other input variable names. %======================================================================= % Copyright 2008-2024, LEGI UMR 5519 / CNRS UGA G-INP, Grenoble, France % http://www.legi.grenoble-inp.fr % Joel.Sommeria - Joel.Sommeria (A) univ-grenoble-alpes.fr % % 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 (see LICENSE.txt) for more details. %======================================================================= function [Data,var_detect,ichoice,errormsg]=nc2struct(nc,varargin) errormsg='';%default error message if isempty(varargin) varargin{1}='*'; end %% default output Data=[];%default var_detect=[];%default ichoice=[];%default %% open the NetCDF (or .mat) file for reading if ischar(nc) testfile=1; if exist(nc,'file') if ~isempty(regexp(nc,'.mat$')) Data=mat2struct(nc,varargin{1}); return else try nc=netcdf.open(nc,'NC_NOWRITE'); catch ME errormsg=['ERROR opening ' nc ': ' ME.message]; return end end else %case of OpenDAP files if regexp(nc,'^http://') try nc=netcdf.open(nc,'NC_NOWRITE'); catch ME errormsg=['ERROR opening ' nc ': ' ME.message]; return end else errormsg=['ERROR:file ' nc ' does not exist']; return end end else testfile=0; end %% short reading option for global attributes only, if the first argument is 'ListGlobalAttribute' if isequal(varargin{1},'ListGlobalAttribute') for ilist=2:numel(varargin) valuestr=[];%default try valuestr = netcdf.getAtt(nc,netcdf.getConstant('NC_GLOBAL'),varargin{ilist}); catch ME end Data.(varargin{ilist})=valuestr; end netcdf.close(nc) return end %% time variable or dimension input_index=1; CheckTimeVar=0; TimeVarName=''; if isequal(varargin{1},'TimeVarName') TimeVarName=varargin{2}; CheckTimeVar=1; TimeIndex=varargin{3}; input_index=4;% list of variables to read is at fourth argument elseif isequal(varargin{1},'TimeDimName') TimeDimName=varargin{2}; TimeIndex=varargin{3}; input_index=4; end %% full reading: get the nbre of dimensions, variables, global attributes ListVarName=varargin{input_index}; [ndims,nvars,ngatts]=netcdf.inq(nc);%nbre of dimensions, variables, global attributes, in the NetCDF file %% -------- read all global attributes (constants)----------- Data.ListGlobalAttribute={};%default att_key=cell(1,ngatts);%default for iatt=1:ngatts keystr= netcdf.inqAttName(nc,netcdf.getConstant('NC_GLOBAL'),iatt-1); valuestr = netcdf.getAtt(nc,netcdf.getConstant('NC_GLOBAL'),keystr); keystr=regexprep(keystr,{'\','/','\.','-',' '},{'','','','',''});%remove '\','.' or '-' if exists if strcmp(keystr(1),'_') keystr(1)=[]; end try if ischar(valuestr) %& length(valuestr)<200 & double(valuestr)<=122 & double(valuestr)>=48 %usual characters eval(['Data.' keystr '=''' valuestr ''';']) elseif isnumeric(valuestr) eval(['Data.' keystr '=valuestr;']) else eval(['Data.' keystr '='';']) end att_key{iatt}=keystr; catch ME att_key{iatt}=['attr_' num2str(iatt)]; Data.(att_key{iatt})=[]; end end Data.ListGlobalAttribute=att_key; %% -------- read dimension names----------- ListDimNameNetcdf=cell(1,ndims); dim_value=zeros(1,ndims); for idim=1:ndims %loop on the dimensions of the NetCDF file [ListDimNameNetcdf{idim},dim_value(idim)] = netcdf.inqDim(nc,idim-1);%get name and value of each dimension end if ~isempty(ListDimNameNetcdf) flag_used=zeros(1,ndims);%initialize the flag indicating the selected dimensions in the list (0=unused) end if isequal(varargin{1},'TimeDimName')% time dimension introduced TimeDimIndex=find(strcmp(TimeDimName,ListDimNameNetcdf)); if isempty(TimeDimIndex) errormsg=['requested time dimension ' varargin{2} ' not found']; return end if dim_value(TimeDimIndex)=ivar && isfield(Data.VarAttribute{ivar},'scale_factor') Data.(VarName)=Data.VarAttribute{ivar}.scale_factor *Data.(VarName); end end end Data.VarType=xtype(var_index); %% -------- close fle----------- if testfile==1 netcdf.close(nc) end