check the ncread for new version matlab from Mathworks.
The attributes of scale factor, offset value and missing value are considered in this version.
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 |
2 comments:
Hi thanks for making this code accessible. I tried to run it using Matlab7.11 on both ubuntu 10.10 and xp spc3 platforms. I also tried it using Matlab7.10 on Windows 7 home. But in all instances I am getting the error messages related to dimensions : Could you please elaborate the last argument for this function? "mydata=GetNcVarMatlab('mask.nc','tmask','1:1,1:46,1:400,1:568');"?
All the variables in my case are one dimensional.
Thanks a lot!
here is the out put from ncdump for one of my files:
dimensions:
MSL_alt = 400 ;
variables:
float MSL_alt(MSL_alt) ;
MSL_alt:long_name = "Mean Sea Level geometric height" ;
MSL_alt:units = "km" ;
MSL_alt:missing_value = "-999" ;
MSL_alt:_FillValue = -999.f ;
MSL_alt:valid_range = -2.f, 120.f ;
float Temp(MSL_alt) ;
Temp:long_name = "temperature" ;
Temp:units = "C" ;
Temp:missing_value = "-999" ;
Temp:_FillValue = -999.f ;
Temp:valid_range = -150.f, 100.f ;
float Vp(MSL_alt) ;
Vp:long_name = "H2O vapor pressure" ;
Vp:units = "mb" ;
Vp:missing_value = "-999" ;
Vp:_FillValue = -999.f ;
Vp:valid_range = 0.f, 60.f ;
float Pres(MSL_alt) ;
Pres:long_name = "pressure level" ;
Pres:units = "mb" ;
Pres:missing_value = "-999" ;
Pres:_FillValue = -999.f ;
Pres:valid_range = 0.f, 1200.f ;
float Ref(MSL_alt) ;
Ref:long_name = "Analyzed refractivity, consistent with Temp, Vp, and Pres" ;
Ref:units = "N" ;
Ref:missing_value = "-999" ;
Ref:_FillValue = -999.f ;
Ref:valid_range = 0.f, 500.f ;
float Lat(MSL_alt) ;
Lat:long_name = "latitude, -90 to 90 north" ;
Lat:units = "deg" ;
Lat:missing_value = "-999" ;
Lat:_FillValue = -999.f ;
Lat:valid_range = -90.f, 90.f ;
float Lon(MSL_alt) ;
Lon:long_name = "longitude, -180 to 180 east" ;
Lon:units = "deg" ;
Lon:missing_value = "-999" ;
Lon:_FillValue = -999.f ;
Lon:valid_range = -180.f, 180.f ;
float Ref_obs(MSL_alt) ;
Ref_obs:long_name = "Observed refractivity, interpolated from the atmPrf file" ;
Ref_obs:units = "N" ;
Ref_obs:missing_value = "-999" ;
Ref_obs:_FillValue = -999.f ;
Ref_obs:valid_range = 0.f, 500.f ;
// global attributes:
:occ_id = 1 ;
:fiducial_id = ;
:reference_sat_id = 10 ;
:occulting_sat_id = 5 ;
:start_time = 674266226. ;
:stop_time = 674266292.460002 ;
:year = 2001 ;
:month = 5 ;
:day = 19 ;
:hour = 0 ;
:minute = 10 ;
:second = 26. ;
:lat = -82.9064833516599 ;
:lon = -22.7066976024562 ;
:fileStamp = "CHAM.2001.139.00.10.G05" ;
:center = "UCAR/CDAAC" ;
:bad = "0" ;
:errstr = ;
:Znh = -999. ;
:Znh2 = -999. ;
Hi zola, sorry for late reply. I was busy in the past few weeks.
In my case, I have a 4D variable "tmask", one time record, 46 levs, 400 in y (latitude) and 568 in x (longitude).
Make sure the dimensions in RangeStr are the same order as that you get using ncdump. If you are using netcdf.getvar() directly, it returns something with dimensions in a reverse order.
Post a Comment