Changeset 1095 for trunk/src/nc2struct.m
- Timestamp:
- Mar 31, 2021, 3:32:03 PM (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/nc2struct.m
r1093 r1095 1 1 2 2 %'nc2struct': transform a NetCDF file in a corresponding matlab structure 3 % or directly read the a matlab data file .mat (calling the fct mat2struct.m) 3 4 % it reads all the global attributes and all variables, or a selected list. 4 5 % The corresponding dimensions and variable attributes are then extracted … … 60 61 varargin{1}='*'; 61 62 end 62 hhh=which('netcdf.open');% look for built-in matlab NetCDF library 63 64 if ~isempty(hhh) 65 %% default output 66 Data=[];%default 67 var_detect=[];%default 68 ichoice=[];%default 69 70 %% open the NetCDF file for reading 71 if ischar(nc) 72 if exist(nc,'file') 63 64 %% default output 65 Data=[];%default 66 var_detect=[];%default 67 ichoice=[];%default 68 69 %% open the NetCDF (or .mat) file for reading 70 if ischar(nc) 71 testfile=1; 72 if exist(nc,'file') 73 if ~isempty(regexp(nc,'.mat$')) 74 Data=mat2struct(nc,varargin{1}); 75 return 76 else 73 77 try 74 78 nc=netcdf.open(nc,'NC_NOWRITE'); 75 testfile=1;76 79 catch ME 77 80 errormsg=['ERROR opening ' nc ': ' ME.message]; 78 81 return 79 82 end 83 end 84 else %case of OpenDAP files 85 if regexp(nc,'^http://') 86 try 87 nc=netcdf.open(nc,'NC_NOWRITE'); 88 catch ME 89 errormsg=['ERROR opening ' nc ': ' ME.message]; 90 return 91 end 80 92 else 81 if regexp(nc,'^http://')82 nc=netcdf.open(nc,'NC_NOWRITE');83 testfile=1;84 else85 93 errormsg=['ERROR:file ' nc ' does not exist']; 86 94 return 87 end 88 end 95 end 96 end 97 else 98 testfile=0; 99 end 100 101 %% short reading option for global attributes only, if the first argument is 'ListGlobalAttribute' 102 if isequal(varargin{1},'ListGlobalAttribute') 103 for ilist=2:numel(varargin) 104 valuestr=[];%default 105 try 106 valuestr = netcdf.getAtt(nc,netcdf.getConstant('NC_GLOBAL'),varargin{ilist}); 107 catch ME 108 end 109 eval(['Data.' varargin{ilist} '=valuestr;']) 110 end 111 netcdf.close(nc) 112 return 113 end 114 115 %% time variable or dimension 116 input_index=1; 117 CheckTimeVar=0; 118 TimeVarName=''; 119 if isequal(varargin{1},'TimeVarName') 120 TimeVarName=varargin{2}; 121 CheckTimeVar=1; 122 TimeIndex=varargin{3}; 123 input_index=4;% list of variables to read is at fourth argument 124 elseif isequal(varargin{1},'TimeDimName') 125 TimeDimName=varargin{2}; 126 TimeIndex=varargin{3}; 127 input_index=4; 128 end 129 130 %% full reading: get the nbre of dimensions, variables, global attributes 131 ListVarName=varargin{input_index}; 132 [ndims,nvars,ngatts]=netcdf.inq(nc);%nbre of dimensions, variables, global attributes, in the NetCDF file 133 134 %% -------- read all global attributes (constants)----------- 135 Data.ListGlobalAttribute={};%default 136 att_key=cell(1,ngatts);%default 137 for iatt=1:ngatts 138 keystr= netcdf.inqAttName(nc,netcdf.getConstant('NC_GLOBAL'),iatt-1); 139 valuestr = netcdf.getAtt(nc,netcdf.getConstant('NC_GLOBAL'),keystr); 140 keystr=regexprep(keystr,{'\','/','\.','-',' '},{'','','','',''});%remove '\','.' or '-' if exists 141 if strcmp(keystr(1),'_') 142 keystr(1)=[]; 143 end 144 try 145 if ischar(valuestr) %& length(valuestr)<200 & double(valuestr)<=122 & double(valuestr)>=48 %usual characters 146 eval(['Data.' keystr '=''' valuestr ''';']) 147 elseif isnumeric(valuestr) 148 eval(['Data.' keystr '=valuestr;']) 149 else 150 eval(['Data.' keystr '='';']) 151 end 152 att_key{iatt}=keystr; 153 catch ME 154 att_key{iatt}=['attr_' num2str(iatt)]; 155 Data.(att_key{iatt})=[]; 156 end 157 end 158 Data.ListGlobalAttribute=att_key; 159 160 %% -------- read dimension names----------- 161 ListDimNameNetcdf=cell(1,ndims); 162 dim_value=zeros(1,ndims); 163 for idim=1:ndims %loop on the dimensions of the NetCDF file 164 [ListDimNameNetcdf{idim},dim_value(idim)] = netcdf.inqDim(nc,idim-1);%get name and value of each dimension 165 end 166 if ~isempty(ListDimNameNetcdf) 167 flag_used=zeros(1,ndims);%initialize the flag indicating the selected dimensions in the list (0=unused) 168 end 169 if isequal(varargin{1},'TimeDimName')% time dimension introduced 170 TimeDimIndex=find(strcmp(TimeDimName,ListDimNameNetcdf)); 171 if isempty(TimeDimIndex) 172 errormsg=['requested time dimension ' varargin{2} ' not found']; 173 return 174 end 175 if dim_value(TimeDimIndex)<varargin{3} 176 errormsg=['requested time index ' num2str(varargin{3}) ' exceeds matrix dimension']; 177 return 178 end 179 end 180 181 %% -------- read names of variables ----------- 182 ListVarNameNetcdf=cell(1,nvars); %default 183 dimids=cell(1,nvars); 184 nbatt=zeros(1,nvars); 185 for ncvar=1:nvars %loop on the variables of the NetCDF file 186 %get name, type, dimensions and attribute numbers of each variable 187 [ListVarNameNetcdf{ncvar},xtype(ncvar),dimids{ncvar},nbatt(ncvar)] = netcdf.inqVar(nc,ncvar-1); 188 end 189 % testmulti=0; 190 if isequal(ListVarName,'*')||isempty(ListVarName) 191 var_index=1:nvars; %all the variables are selected in the NetCDF file 192 Data.ListVarName=ListVarNameNetcdf; 193 else %select input variables, if requested by the input ListVarName 194 check_keep=ones(1,size(ListVarName,2)); 195 for ivar=1:size(ListVarName,2) % check redondancy of variable names 196 if ~isempty(find(strcmp(ListVarName{1,ivar},ListVarName(1:ivar-1)), 1)) 197 check_keep(ivar)=0;% the variable #ivar is already in the list 198 end 199 end 200 ListVarName=ListVarName(:,logical(check_keep)); 201 if size(ListVarName,1)>1 %multiple choice of variable ranked by order of priority 202 for iline=1:size(ListVarName,1) 203 search_index=find(strcmp(ListVarName{iline,1},ListVarNameNetcdf),1);%look for the first variable name in the list of NetCDF variables 204 if ~isempty(search_index) 205 break % go to the next line 206 end 207 end 208 ichoice=iline-1;%selected line number in the list of input names of variables 89 209 else 90 testfile=0; 91 end 92 93 %% short reading option for global attributes only, if the first argument is 'ListGlobalAttribute' 94 if isequal(varargin{1},'ListGlobalAttribute') 95 for ilist=2:numel(varargin) 96 valuestr=[];%default 97 try 98 valuestr = netcdf.getAtt(nc,netcdf.getConstant('NC_GLOBAL'),varargin{ilist}); 99 catch ME 100 end 101 eval(['Data.' varargin{ilist} '=valuestr;']) 102 end 103 netcdf.close(nc) 104 return 105 end 106 107 %% time variable or dimension 108 input_index=1; 109 CheckTimeVar=0; 110 TimeVarName=''; 111 if isequal(varargin{1},'TimeVarName') 112 TimeVarName=varargin{2}; 113 CheckTimeVar=1; 114 TimeIndex=varargin{3}; 115 input_index=4;% list of variables to read is at fourth argument 116 elseif isequal(varargin{1},'TimeDimName') 117 TimeDimName=varargin{2}; 118 TimeIndex=varargin{3}; 119 input_index=4; 120 end 121 122 %% full reading: get the nbre of dimensions, variables, global attributes 123 ListVarName=varargin{input_index}; 124 [ndims,nvars,ngatts]=netcdf.inq(nc);%nbre of dimensions, variables, global attributes, in the NetCDF file 125 126 %% -------- read all global attributes (constants)----------- 127 Data.ListGlobalAttribute={};%default 128 att_key=cell(1,ngatts);%default 129 for iatt=1:ngatts 130 keystr= netcdf.inqAttName(nc,netcdf.getConstant('NC_GLOBAL'),iatt-1); 131 valuestr = netcdf.getAtt(nc,netcdf.getConstant('NC_GLOBAL'),keystr); 132 keystr=regexprep(keystr,{'\','/','\.','-',' '},{'','','','',''});%remove '\','.' or '-' if exists 133 if strcmp(keystr(1),'_') 134 keystr(1)=[]; 210 iline=1; 211 end 212 %ListVarName=ListVarName(iline,:);% select the appropriate option for input variable (lin ein the input name matrix) 213 if CheckTimeVar 214 TimeVarIndex=find(strcmp(TimeVarName,ListVarNameNetcdf),1); %look for the index of the time variable in the netcdf list 215 if isempty(TimeVarIndex) 216 errormsg='requested variable for time is missing'; 217 return 218 end 219 TimeDimIndex=dimids{TimeVarIndex}(1)+1; 220 ListVarName=[ListVarName {TimeVarName}]; 221 end 222 var_index=zeros(1,size(ListVarName,2));%default list of variable indices 223 for ivar=1:size(ListVarName,2) 224 search_index=find(strcmp(ListVarName{iline,ivar},ListVarNameNetcdf),1);%look for the variable name in the list of NetCDF file 225 if ~isempty(search_index) 226 var_index(ivar)=search_index;%index of the netcdf list corresponding to the input list index ivar 227 end 228 end 229 var_detect=(var_index~=0);%=1 for detected variables 230 list_index=find(var_index);% indices in the input list corresponding to a detected variable 231 var_index=var_index(list_index);% NetCDF variable indices corresponding to the output list of read variable 232 Data.ListVarName=ListVarName(1,list_index);%the first line of ListVarName sets the output names of the variables 233 end 234 235 %% get the dimensions and attributes associated to variables 236 var_dim=cell(size(var_index));% initiate list of dimensions for variables 237 for ivar=1:length(var_index) 238 var_dim{ivar}=dimids{var_index(ivar)}+1; %netcdf dimension indices used by the variable #ivar 239 Data.VarDimName{ivar}=ListDimNameNetcdf(var_dim{ivar}); 240 flag_used(var_dim{ivar})=ones(size(var_dim{ivar}));%flag_used =1 for the indices of used dimensions 241 for iatt=1:nbatt(var_index(ivar)) 242 attname = netcdf.inqAttName(nc,var_index(ivar)-1,iatt-1); 243 valuestr= netcdf.getAtt(nc,var_index(ivar)-1,attname); 244 attname=regexprep(attname,{'\','/','\.','-',' '},{'','','','',''});%remove '\','.' or '-' if exists 245 if strcmp(attname(1),'_') 246 attname(1)=[]; 135 247 end 136 248 try 137 if ischar(valuestr) %& length(valuestr)<200 & double(valuestr)<=122 & double(valuestr)>=48 %usual characters 138 eval(['Data.' keystr '=''' valuestr ''';']) 139 elseif isnumeric(valuestr) 140 eval(['Data.' keystr '=valuestr;']) 141 else 142 eval(['Data.' keystr '='';']) 143 end 144 att_key{iatt}=keystr; 249 if ~isempty(valuestr) 250 Data.VarAttribute{ivar}.(attname)=valuestr; 251 end 145 252 catch ME 146 att_key{iatt}=['attr_' num2str(iatt)]; 147 Data.(att_key{iatt})=[]; 148 end 149 end 150 Data.ListGlobalAttribute=att_key; 151 152 %% -------- read dimension names----------- 153 ListDimNameNetcdf=cell(1,ndims); 154 dim_value=zeros(1,ndims); 155 for idim=1:ndims %loop on the dimensions of the NetCDF file 156 [ListDimNameNetcdf{idim},dim_value(idim)] = netcdf.inqDim(nc,idim-1);%get name and value of each dimension 157 end 158 if ~isempty(ListDimNameNetcdf) 159 flag_used=zeros(1,ndims);%initialize the flag indicating the selected dimensions in the list (0=unused) 160 end 161 if isequal(varargin{1},'TimeDimName')% time dimension introduced 162 TimeDimIndex=find(strcmp(TimeDimName,ListDimNameNetcdf)); 163 if isempty(TimeDimIndex) 164 errormsg=['requested time dimension ' varargin{2} ' not found']; 165 return 166 end 167 if dim_value(TimeDimIndex)<varargin{3} 168 errormsg=['requested time index ' num2str(varargin{3}) ' exceeds matrix dimension']; 169 return 170 end 171 end 172 173 %% -------- read names of variables ----------- 174 ListVarNameNetcdf=cell(1,nvars); %default 175 dimids=cell(1,nvars); 176 nbatt=zeros(1,nvars); 177 for ncvar=1:nvars %loop on the variables of the NetCDF file 178 %get name, type, dimensions and attribute numbers of each variable 179 [ListVarNameNetcdf{ncvar},xtype(ncvar),dimids{ncvar},nbatt(ncvar)] = netcdf.inqVar(nc,ncvar-1); 180 end 181 % testmulti=0; 182 if isequal(ListVarName,'*')||isempty(ListVarName) 183 var_index=1:nvars; %all the variables are selected in the NetCDF file 184 Data.ListVarName=ListVarNameNetcdf; 185 else %select input variables, if requested by the input ListVarName 186 check_keep=ones(1,size(ListVarName,2)); 187 for ivar=1:size(ListVarName,2) % check redondancy of variable names 188 if ~isempty(find(strcmp(ListVarName{1,ivar},ListVarName(1:ivar-1)), 1)) 189 check_keep(ivar)=0;% the variable #ivar is already in the list 190 end 191 end 192 ListVarName=ListVarName(:,logical(check_keep)); 193 if size(ListVarName,1)>1 %multiple choice of variable ranked by order of priority 194 for iline=1:size(ListVarName,1) 195 search_index=find(strcmp(ListVarName{iline,1},ListVarNameNetcdf),1);%look for the first variable name in the list of NetCDF variables 196 if ~isempty(search_index) 197 break % go to the next line 253 display(attname) 254 display(valuestr) 255 display(ME.message) 256 Data.VarAttribute{ivar}.(['atrr_' num2str(iatt)])='not read'; 257 end 258 end 259 end 260 261 %% select the dimensions used for the set of input variables 262 if ~isempty(var_index) 263 dim_index=find(flag_used);%list of netcdf dimensions indices corresponding to used dimensions 264 Data.ListDimName=ListDimNameNetcdf(dim_index); 265 Data.DimValue=dim_value(dim_index); 266 if input_index==4% if a dimension is selected as time 267 Data.DimValue(TimeDimIndex)=numel(TimeIndex); 268 end 269 end 270 271 %% get the values of the input variables 272 if ~isempty(ListVarName) 273 for ivar=1:length(var_index) 274 VarName=Data.ListVarName{ivar}; 275 VarName=regexprep(VarName,'-','_'); %suppress '-' if it exists in the NetCDF variable name (leads to errors in matlab) 276 % CheckSub=0; 277 if input_index==4% if a dimension is selected as time 278 ind_vec=zeros(1,numel(var_dim{ivar}));% vector with zeros corresponding to al the dimensions of the variable VarName 279 ind_size=dim_value(var_dim{ivar});% vector giving the size (for each dimension) of the variable VarName 280 index_time=find(var_dim{ivar}==TimeDimIndex); 281 if ~isempty(index_time) 282 if ind_size(index_time)<max(TimeIndex) 283 errormsg=['requested index ' num2str(TimeIndex) ' exceeds matrix dimension']; 284 return 198 285 end 199 end 200 ichoice=iline-1;%selected line number in the list of input names of variables 286 ind_vec(index_time)=TimeIndex-1;% selected index(or indices) to read 287 ind_size(index_time)=numel(TimeIndex);%length of the selected set of time indices 288 if numel(TimeIndex)==1 && ~strcmp(VarName,TimeVarName) 289 Data.VarDimName{ivar}(index_time)=[];% for a single selected time remove the time in the list of dimensions (except for tTime itself) 290 end 291 end 292 Data.(VarName)=netcdf.getVar(nc,var_index(ivar)-1,ind_vec,ind_size); %read the variable data 293 Data.(VarName)=squeeze(Data.(VarName));%remove singeton dimension 201 294 else 202 iline=1; 203 end 204 %ListVarName=ListVarName(iline,:);% select the appropriate option for input variable (lin ein the input name matrix) 205 if CheckTimeVar 206 TimeVarIndex=find(strcmp(TimeVarName,ListVarNameNetcdf),1); %look for the index of the time variable in the netcdf list 207 if isempty(TimeVarIndex) 208 errormsg='requested variable for time is missing'; 209 return 210 end 211 TimeDimIndex=dimids{TimeVarIndex}(1)+1; 212 ListVarName=[ListVarName {TimeVarName}]; 213 end 214 var_index=zeros(1,size(ListVarName,2));%default list of variable indices 215 for ivar=1:size(ListVarName,2) 216 search_index=find(strcmp(ListVarName{iline,ivar},ListVarNameNetcdf),1);%look for the variable name in the list of NetCDF file 217 if ~isempty(search_index) 218 var_index(ivar)=search_index;%index of the netcdf list corresponding to the input list index ivar 219 end 220 end 221 var_detect=(var_index~=0);%=1 for detected variables 222 list_index=find(var_index);% indices in the input list corresponding to a detected variable 223 var_index=var_index(list_index);% NetCDF variable indices corresponding to the output list of read variable 224 Data.ListVarName=ListVarName(1,list_index);%the first line of ListVarName sets the output names of the variables 225 end 226 227 %% get the dimensions and attributes associated to variables 228 var_dim=cell(size(var_index));% initiate list of dimensions for variables 229 for ivar=1:length(var_index) 230 var_dim{ivar}=dimids{var_index(ivar)}+1; %netcdf dimension indices used by the variable #ivar 231 Data.VarDimName{ivar}=ListDimNameNetcdf(var_dim{ivar}); 232 flag_used(var_dim{ivar})=ones(size(var_dim{ivar}));%flag_used =1 for the indices of used dimensions 233 for iatt=1:nbatt(var_index(ivar)) 234 attname = netcdf.inqAttName(nc,var_index(ivar)-1,iatt-1); 235 valuestr= netcdf.getAtt(nc,var_index(ivar)-1,attname); 236 attname=regexprep(attname,{'\','/','\.','-',' '},{'','','','',''});%remove '\','.' or '-' if exists 237 if strcmp(attname(1),'_') 238 attname(1)=[]; 239 end 240 try 241 if ~isempty(valuestr) 242 Data.VarAttribute{ivar}.(attname)=valuestr; 243 end 244 catch ME 245 display(attname) 246 display(valuestr) 247 display(ME.message) 248 Data.VarAttribute{ivar}.(['atrr_' num2str(iatt)])='not read'; 249 end 250 end 251 end 252 253 %% select the dimensions used for the set of input variables 254 if ~isempty(var_index) 255 dim_index=find(flag_used);%list of netcdf dimensions indices corresponding to used dimensions 256 Data.ListDimName=ListDimNameNetcdf(dim_index); 257 Data.DimValue=dim_value(dim_index); 258 if input_index==4% if a dimension is selected as time 259 Data.DimValue(TimeDimIndex)=numel(TimeIndex); 260 end 261 end 262 263 %% get the values of the input variables 264 if ~isempty(ListVarName) 265 for ivar=1:length(var_index) 266 VarName=Data.ListVarName{ivar}; 267 VarName=regexprep(VarName,'-','_'); %suppress '-' if it exists in the NetCDF variable name (leads to errors in matlab) 268 % CheckSub=0; 269 if input_index==4% if a dimension is selected as time 270 ind_vec=zeros(1,numel(var_dim{ivar}));% vector with zeros corresponding to al the dimensions of the variable VarName 271 ind_size=dim_value(var_dim{ivar});% vector giving the size (for each dimension) of the variable VarName 272 index_time=find(var_dim{ivar}==TimeDimIndex); 273 if ~isempty(index_time) 274 if ind_size(index_time)<max(TimeIndex) 275 errormsg=['requested index ' num2str(TimeIndex) ' exceeds matrix dimension']; 276 return 277 end 278 ind_vec(index_time)=TimeIndex-1;% selected index(or indices) to read 279 ind_size(index_time)=numel(TimeIndex);%length of the selected set of time indices 280 if numel(TimeIndex)==1 && ~strcmp(VarName,TimeVarName) 281 Data.VarDimName{ivar}(index_time)=[];% for a single selected time remove the time in the list of dimensions (except for tTime itself) 282 end 283 end 284 Data.(VarName)=netcdf.getVar(nc,var_index(ivar)-1,ind_vec,ind_size); %read the variable data 285 Data.(VarName)=squeeze(Data.(VarName));%remove singeton dimension 286 else 287 Data.(VarName)=netcdf.getVar(nc,var_index(ivar)-1); %read the whole variable data 288 end 289 if xtype(var_index(ivar))==5 290 Data.(VarName)=double(Data.(VarName)); %transform to double for single pecision 291 end 292 end 293 end 294 Data.VarType=xtype(var_index); 295 296 %% -------- close fle----------- 297 if testfile==1 298 netcdf.close(nc) 299 end 300 301 %% old NetCDF library 302 else 303 [Data,var_detect,ichoice]=nc2struct_toolbox(nc,varargin); 304 end 295 Data.(VarName)=netcdf.getVar(nc,var_index(ivar)-1); %read the whole variable data 296 end 297 if xtype(var_index(ivar))==5 298 Data.(VarName)=double(Data.(VarName)); %transform to double for single pecision 299 end 300 end 301 end 302 Data.VarType=xtype(var_index); 303 304 %% -------- close fle----------- 305 if testfile==1 306 netcdf.close(nc) 307 end 308
Note: See TracChangeset
for help on using the changeset viewer.