Changeset 1095 for trunk/src/nc2struct.m


Ignore:
Timestamp:
Mar 31, 2021, 3:32:03 PM (3 years ago)
Author:
sommeria
Message:

reading mat files added, +-fixed,OpenDAP improved

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/nc2struct.m

    r1093 r1095  
    11
    22%'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)
    34% it reads all the global attributes and all variables, or a selected list.
    45% The corresponding dimensions and variable attributes are then extracted
     
    6061    varargin{1}='*';
    6162end
    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
     65Data=[];%default
     66var_detect=[];%default
     67ichoice=[];%default
     68
     69%% open the NetCDF (or .mat) file for reading
     70if 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
    7377            try
    7478                nc=netcdf.open(nc,'NC_NOWRITE');
    75                 testfile=1;
    7679            catch ME
    7780                errormsg=['ERROR opening ' nc ': ' ME.message];
    7881                return
    7982            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
    8092        else
    81             if regexp(nc,'^http://')
    82                 nc=netcdf.open(nc,'NC_NOWRITE');
    83                 testfile=1;
    84             else
    8593            errormsg=['ERROR:file ' nc ' does not exist'];
    8694            return
    87             end
    88         end
     95        end
     96    end
     97else
     98    testfile=0;
     99end
     100
     101%% short reading option for global attributes only, if the first argument is 'ListGlobalAttribute'
     102if 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
     113end
     114
     115%% time variable or dimension
     116input_index=1;
     117CheckTimeVar=0;
     118TimeVarName='';
     119if 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
     124elseif isequal(varargin{1},'TimeDimName')
     125    TimeDimName=varargin{2};
     126    TimeIndex=varargin{3};
     127    input_index=4;
     128end
     129
     130%% full reading: get the nbre of dimensions, variables, global attributes
     131ListVarName=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)-----------
     135Data.ListGlobalAttribute={};%default
     136att_key=cell(1,ngatts);%default
     137for 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
     157end
     158Data.ListGlobalAttribute=att_key;
     159
     160%%  -------- read dimension names-----------
     161ListDimNameNetcdf=cell(1,ndims);
     162dim_value=zeros(1,ndims);
     163for 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
     165end
     166if ~isempty(ListDimNameNetcdf)
     167    flag_used=zeros(1,ndims);%initialize the flag indicating the selected dimensions in the list (0=unused)
     168end
     169if 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
     179end
     180
     181%%  -------- read names of variables -----------
     182ListVarNameNetcdf=cell(1,nvars); %default
     183dimids=cell(1,nvars);
     184nbatt=zeros(1,nvars);
     185for 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);
     188end
     189%     testmulti=0;
     190if isequal(ListVarName,'*')||isempty(ListVarName)
     191    var_index=1:nvars; %all the variables are selected in the NetCDF file
     192    Data.ListVarName=ListVarNameNetcdf;
     193else   %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
    89209    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
     233end
     234
     235%% get the dimensions and attributes associated to  variables
     236var_dim=cell(size(var_index));% initiate list of dimensions for variables
     237for 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)=[];
    135247        end
    136248        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
    145252        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
     259end
     260
     261%% select the dimensions used for the set of input variables
     262if ~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
     269end
     270
     271%% get the values of the input variables
     272if  ~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
    198285                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
    201294        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
     301end
     302Data.VarType=xtype(var_index);
     303
     304%%  -------- close fle-----------
     305if testfile==1
     306    netcdf.close(nc)
     307end
     308
Note: See TracChangeset for help on using the changeset viewer.