Monday, January 3, 2011

[UPDATED] read netcdf file using native matlab functions

check the ncread for new version matlab from Mathworks. 
 
The attributes of scale factor, offset value and missing value are considered in this version.

function ncvardata=GetNcVarMatlab(ncfile,ncvar,RangeStr)
% to read a variable from the netcdf file using native matlab netcdf-functions
% Usage: vardata=GetNcVarMatlab(nc-filename,nc-varname,Dimension-Range)
% e.g.,
%        mydata=GetNcVarMatlab('mask.nc','tmask','1:1,1:46,1:400,1:568');
%                      RangeStr here is similar to the output of ncdump
% note: by default, variable will be converted into the class of double,
%                      and the missing value will be converted into nan.
% copyright @ http://scriptdemo.blogspot.com


IsDebug=0;
IsMissingNaN=1; % convert missing values into NaN
if ~exist(ncfile,'file')
   error([ncfile,' can not been found']);
   return
end

ncfid=netcdf.open(ncfile,'NC_NOWRITE');
% get dimension length
[numdims, numvars, numglobalatts, unlimdimID] = netcdf.inq(ncfid);
for NDim=1:numdims
   [dimname{NDim}, dimlen(NDim)] = netcdf.inqDim(ncfid,NDim-1);
end

%var infor
varid=netcdf.inqVarID(ncfid,ncvar);
[varname,varxtype,vardimids,NumAtts]=netcdf.inqVar(ncfid,varid);
numdims=length(vardimids); % some variables may have less dimensions

%check scale_factor & off_set
IsRescale=0; IsMissing=0;
myScale=1; myOffSet=0.0;
for numA=1:NumAtts
    tmpattname=netcdf.inqAttName(ncfid,varid,numA-1);
    switch lower(tmpattname)
       case {'scale_factor','scalefactor'}
            IsRescale=1;
            myscale=netcdf.getAtt(ncfid,varid,tmpattname);
       case {'add_offset','off_set','offset'}
            IsRescale=1;
            myoffset=netcdf.getAtt(ncfid,varid,tmpattname);
       case {'missing_value','missingvalue','missing'}
            IsMissing=1;
            mymissing=netcdf.getAtt(ncfid,varid,tmpattname);
       otherwise
            % do nothing
    end
end
if IsRescale==1
   if (myscale==1 & myoffset==0)
      IsRescale=0;
   end
else
   if ~exist('myscale','var') myscale=1; end
   if ~exist('myoffset','var') myoffset=0; end
end

if ~exist('RangeStr','var')
   RangeStr=':';
   for nd=2:numdims
       RangeStr=[RangeStr,',:'];
   end
end

IndC=strfind(RangeStr,',');% index of commas
if length(IndC)~=numdims-1
   disp(['Input dimension range is not correct, should be: ',num2str(numdims),'-d']);
   return
end

startstr=''; countstr=''; stridestr='';
for nn=1:length(IndC)+1
    if nn==1
       tmpstr=RangeStr(1:IndC(1)-1);
    elseif nn<numdims
       tmpstr=RangeStr(IndC(nn-1)+1:IndC(nn)-1);
    else
       tmpstr=RangeStr(IndC(nn-1)+1:end);
    end

    [tmpstart,tmpcount,tmpstride]=GetIndFromStr(tmpstr,':',dimlen(vardimids(numdims-nn+1)+1));
    if nn==1
        startstr=[num2str(tmpstart),'],'];
        countstr=[num2str(tmpcount),'],'];
        stridestr=[num2str(tmpstride),']'];
    elseif nn==numdims
        startstr=[',[',num2str(tmpstart),',',startstr];
        countstr=['[',num2str(tmpcount),',',countstr];
        stridestr=['[',num2str(tmpstride),',',stridestr];
    else
        startstr=[num2str(tmpstart),',',startstr];
        countstr=[num2str(tmpcount),',',countstr];
        stridestr=[num2str(tmpstride),',',stridestr];
    end
end

if IsDebug
   disp(['ncvardata=netcdf.getVar(ncfid,varid',startstr,countstr,stridestr,');']);
end
eval(['ncvardata=netcdf.getVar(ncfid,varid',startstr,countstr,stridestr,');']);
netcdf.close(ncfid);
ncvardata=permute(ncvardata,length(size(ncvardata)):-1:1);

if IsRescale==1
   %convert all data type into double
   if ~strcmp(class(ncvardata),'double')
      ncvardata=double(ncvardata);
   end
   if IsMissing
      if IsMissingNaN==1; % convert missing values into NaN
         ncvardata(ncvardata==mymissing)=nan;
         ncvardata=ncvardata*double(myscale)+double(myoffset);
      else
         disp(['missing value for ',ncvar,' is ',num2str(mymissing)]);
         %IndValid=find(ncvardata~=mymissing); length(IndValid)
         %ncvardata(IndValid)=ncvardata(IndValid)*double(myscale)+double(myoffset);
         ncvardata(ncvardata~=mymissing)=ncvardata(ncvardata~=mymissing)*double(myscale)+double(myoffset);
      end
   else
      ncvardata=ncvardata*double(myscale)+double(myoffset);
   end
else
  ncvardata=double(ncvardata);
end

function [numstart,numcount,numstride]=GetIndFromStr(tmpstr,ctag,Ndim)
% Read the numbers from the special string
IsDebug=0;
IndC=strfind(tmpstr,ctag);
if isempty(IndC)
   numstart=str2double(tmpstr)-1;
   numcount=1;
   numstride=1;
else
  switch length(IndC)
      case {1}
          switch IndC
            case {1} % : and :num
                if strcmp(tmpstr,':')
                   numstart=0; numcount=Ndim; numstride=1;
                else
                   if strcmp(tmpstr(2:end),'end')
                    numstart=0; numcount=Ndim; numstride=1;
                   else
                    numstart=0; numcount=str2double(tmpstr(2:end))-1; numstride=1;
                   end
                end
            case {length(tmpstr)}
                if strcmp(tmpstr,':')
                   numstart=0; numcount=Ndim; numstride=1;
                   return
                else
                   numstart=str2double(tmpstr(1:IndC-1))-1;
                   numcount=Ndim-numstart;
                   numstride=1;
                end
            otherwise
               numstart=str2double(tmpstr(1:IndC-1))-1;
               if strcmp(tmpstr(IndC+1:end),'end')
                  numend=Ndim;
               else
                  numend=str2double(tmpstr(IndC+1:end));
               end
               numcount=numend-numstart;
               numstride=1;
          end
      case {2}
          % num0:stride:num1
          if IndC(1)==1
             numstart=0;
          else
             numstart=str2double(tmpstr(1:IndC(1)-1))-1;
          end
          if IndC(2)==IndC(1)+1
             numstride=1;
          else
             numstride=str2double(tmpstr(IndC(1)+1:IndC(2)-1));
          end
          if IndC(2)==length(tmpstr)
                 numend=Ndim-1;
          else
            if strcmp(tmpstr(IndC(2)+1:end),'end')
               numend=Ndim-1;
            else
               numend=str2double(tmpstr(IndC(2)+1:end))-1;
            end
          end
          numcount=floor((numend-numstart)/numstride)+1;
          numend=numstart+(numcount-1)*(numStride);
      otherwise
          error('Not defined range type')
  end
end
if IsDebug
   disp(['tmpstr=',tmpstr])
   disp(['start:',num2str(numstart), ' stride:',num2str(numstride),' count:',num2str(numcount)])
end

Wednesday, December 22, 2010

num2strcell

function mystrcel=num2strcell(mynum,GFmat)
% to convert a numeric array into a string cell
% usage:
%           mystrcel=num2strcell(YouNumArray,Digit.Format);
%  e.g.,  mystrcel=num2strcell(0.1:0.1:0.5,'%3.2f');
%  copyright by http://scriptdemo.blogspot.com

[nrow,ncol]=size(mynum);
for nj=1:nrow
      for ni=1:ncol
            mystrcel{nj,ni}=num2str(mynum(nj,ni),GFmat);
      end
end

read netcdf file using native matlab functions

UPDATED VERSION:  Here

function ncvardata=GetNcVarMatlab(ncfile,ncvar,RangeStr)
% to read data from the netcdf file using native matlab netcdf-functions
% Usage: vardata=GetNcVarMatlab(nc-filename,nc-varname,Dimension-Range)
% e.g.,
% mydata=GetNcVarMatlab('mask.nc','tmask','1:1,1:46,1:400,1:568');
% RangeStr here is similar to the output of ncdump
% copyright by http://scriptdemo.blogspot.com

IsDebug=0;
if ~exist(ncfile,'file')
   error([ncfile,' can not been found']);
   return
end

ncfid=netcdf.open(ncfile,'NC_NOWRITE');
% get dimension length
[numdims, numvars, numglobalatts, unlimdimID] = netcdf.inq(ncfid);
for NDim=1:numdims
      [dimname{NDim}, dimlen(NDim)] = netcdf.inqDim(ncfid,NDim-1);
end

%var infor
varid=netcdf.inqVarID(ncfid,ncvar);
[varname,varxtype,vardimids,varnumatts]=netcdf.inqVar(ncfid,varid);
numdims=length(vardimids); % some variables may have less dimensions

if ~exist('RangeStr','var')
   RangeStr=':';
   for nd=2:numdims
         RangeStr=[RangeStr,',:'];
   end
end

IndC=strfind(RangeStr,',');% index of commas
if length(IndC)~=numdims-1
   disp(['Input dimension range is not correct, should be: ',num2str(numdims),'-d']);
   return
end

startstr=''; countstr=''; stridestr='';
for nn=1:length(IndC)+1
      if nn==1
         tmpstr=RangeStr(1:IndC(1)-1);
      elseif nn<numdims
         tmpstr=RangeStr(IndC(nn-1)+1:IndC(nn)-1);
      else
         tmpstr=RangeStr(IndC(nn-1)+1:end);
      end

      [tmpstart,tmpcount,tmpstride]=GetIndFromStr(tmpstr,':',dimlen(vardimids(numdims-nn+1)+1));
     if nn==1
        startstr=[num2str(tmpstart),'],'];
        countstr=[num2str(tmpcount),'],'];
        stridestr=[num2str(tmpstride),']'];
     elseif nn==numdims
        startstr=[',[',num2str(tmpstart),',',startstr];
        countstr=['[',num2str(tmpcount),',',countstr];
        stridestr=['[',num2str(tmpstride),',',stridestr];
     else
        startstr=[num2str(tmpstart),',',startstr];
        countstr=[num2str(tmpcount),',',countstr];
        stridestr=[num2str(tmpstride),',',stridestr];
     end
end

if IsDebug
   disp(['ncvardata=netcdf.getVar(ncfid,varid',startstr,countstr,stridestr,');']);
end
eval(['ncvardata=netcdf.getVar(ncfid,varid',startstr,countstr,stridestr,');']);
netcdf.close(ncfid);
ncvardata=permute(ncvardata,length(size(ncvardata)):-1:1);

function [numstart,numcount,numstride]=GetIndFromStr(tmpstr,ctag,Ndim)
% Read the numbers from the special string
IsDebug=0;
IndC=strfind(tmpstr,ctag);
if isempty(IndC)
   numstart=str2double(tmpstr)-1;
   numcount=1;
   numstride=1;
else
  switch length(IndC)
    case {1}
        switch IndC
            case {1} % : and :num
                if strcmp(tmpstr,':')
                   numstart=0; numcount=Ndim; numstride=1;
                else
                   if strcmp(tmpstr(2:end),'end')
                      numstart=0; numcount=Ndim; numstride=1;
                   else
                      numstart=0; numcount=str2double(tmpstr(2:end))-1; numstride=1;
                   end
                end
            case {length(tmpstr)}
                if strcmp(tmpstr,':')
                    numstart=0; numcount=Ndim; numstride=1;
                    return
                else
                    numstart=str2double(tmpstr(1:IndC-1))-1;
                    numcount=Ndim-numstart;
                    numstride=1;
                end
           otherwise
                numstart=str2double(tmpstr(1:IndC-1))-1;
                if strcmp(tmpstr(IndC+1:end),'end')
                    numend=Ndim;
                else
                    numend=str2double(tmpstr(IndC+1:end));
                end
                numcount=numend-numstart;
                numstride=1;
            end
   case {2}
      % num0:stride:num1
      if IndC(1)==1
         numstart=0;
      else
         numstart=str2double(tmpstr(1:IndC(1)-1))-1;
      end
      if IndC(2)==IndC(1)+1
         numstride=1;
      else
         numstride=str2double(tmpstr(IndC(1)+1:IndC(2)-1));
      end
      if IndC(2)==length(tmpstr)
             numend=Ndim;
      else
         if strcmp(tmpstr(IndC(2)+1:end),'end')
            numend=Ndim;
         else
            numend=str2double(tmpstr(IndC(2)+1:end));
         end
      end
      numcount=numend-numstart;
   otherwise
       error('Not defined range type')
   end
end
if IsDebug
   disp(['tmpstr=',tmpstr])
   disp(['start:',num2str(numstart), ' stride:',num2str(numstride),' count:',num2str(numcount)])
end

ShowCalendar