首先看一個nc文件中包含哪些部分,例如一個標准的 FVCOM 輸入文件 wind.nc:
netcdf wind {
dimensions:
nele = 36858 ;
node = 18718 ;
time = UNLIMITED ; // (151 currently)
variables:
int iint(time) ;
iint:long_name = "internal mode iteration number" ;
float time(time) ;
time:long_name = "time" ;
time:units = "days since 0.0" ;
time:time_zone = "none" ;
float uwind_speed(time, nele) ;
uwind_speed:long_name = "Eastward Wind Speed" ;
uwind_speed:standard_name = "Wind Speed" ;
uwind_speed:units = "m/s" ;
uwind_speed:grid = "fvcom_grid" ;
uwind_speed:type = "data" ;
float vwind_speed(time, nele) ;
vwind_speed:long_name = "Northward Wind Speed" ;
vwind_speed:standard_name = "Wind Speed" ;
vwind_speed:units = "m/s" ;
vwind_speed:grid = "fvcom_grid" ;
vwind_speed:type = "data" ;
// global attributes:
:title = "wind.nc" ;
:institution = "School for Marine Science and Technology" ;
:source = "fvcom grid (unstructured) surface forcing" ;
:history = "FILE CREATED: Sun Jul 31 13:48:52 2011" ;
:references = "http://fvcom.smast.umassd.edu,http://codfish.smast.umassd.edu" ;
:Conventions = "CF-1.0" ;
:CoordinateSystem = "Cartesian" ;
:CoordinateProjection = "none" ;
}
nc 文件主要內容
可以看出 nc 文件包含兩個主要部分:
dimensions:各個變量維度大小variables:變量
dimensions
在上面文件中包含三個維度:nele,node,time。其中 nele,node 兩個是固定長度的,而 time 則是 UNLIMITED,代表其為任意長度。
variables
在 variables 下,每個變量形式為
float uwind_speed(time, nele)
括號包含了變量的維度,每個維度變量指定了該變量某個維度的長度。
在 netcdf 定義中數組是按行排列,因此循環是由右至左。而在matlab中,數組則是按列排列,因此儲存的數組會將各個維度順序交換,即 uwind_speed(nele, time)。
生成nc文件方法
使用 matlab 的 netcdf 工具箱生成文件時需要按照以下順序:
- 定義文件內維度與變量,包括
- 定義維度
- 定義變量
- 儲存變量
以生成一個如上的wind.nc文件為例
定義維度
首先定義文件中維度:nele, node, time。
注意 time 長度是不固定的。
%% creat new netcdf file
ncid = netcdf.create('wind.nc','CLOBBER');
% definition
ele_dim = netcdf.defDim(ncid,'nele', eleNum);
node_dim = netcdf.defDim(ncid,'node', nodeNum);
time_dim = netcdf.defDim(ncid,'time', netcdf.getConstant('NC_UNLIMITED'));
定義維度之后便可根據維度定義變量。
注意,由於 time 維度是不定長度的,因此其必須作為變量最后一個維度(元素循環由左向右)
iint_var_id = netcdf.defVar(ncid,'init','int', time_dim);
time_var_id = netcdf.defVar(ncid,'time','float', time_dim);
u_var_id = netcdf.defVar(ncid,'uwind_speed','double',[ele_dim, time_dim]);
v_var_id = netcdf.defVar(ncid,'vwind_speed','double',[ele_dim, time_dim]);
% end definition
netcdf.endDef(ncid);
netcdf.close(ncid);
定義完變量之后便可向nc文件中儲存數據了。
在這里需要注意的是,由於matlab 調用 c 語言的 NetCDF函數庫,因此在其函數中數組下標是由0開始。(詳見 help netcdf)
% write data
ncid = netcdf.open('wind.nc', 'WRITE');
netcdf.putVar(ncid, time_var_id, 0, nstep, 1, time(1:nstep));
如上述代碼中,0 為起始序號,nstep 為數據總數, 1 為儲存數據間隔,time 即使儲存在matlab中變量名。
采用相同方法將 uwind_speed 與 vwind_speed 循環儲存在文件內。
for itime = 1:nstep
...
netcdf.putVar(ncid, u_var_id, [0, itime-1], [eleNum, 1], u_interp);
...
netcdf.putVar(ncid, v_var_id, [0, itime-1], [eleNum, 1], v_interp);
fprintf('Processing: %f \n', itime/nstep);
end% for
在這里,uwind_speed 與 vwind_speed 是多維數組,因此指定其起始位置也要采用一個向量 [0, itime-1](0 代表 nele 維度起始序號;'itime-1' 則代表 time 維度起始序號)。[eleNum, 1] 為這次要儲存的數據占個維度個數,明顯我們要儲存一整個時間步的數據,所以長度分別為單元個數與時間步數 1。最后 u_interp 與 v_interp 則是變量名。
結語
最終,我們來檢查下生成的nc文件,使用 matlab 版本為 R2014b,NetCDF 版本號為4.1.3。
Source:
/Users/mac/Documents/MATLAB/temp/forZhangNa/FVCOM_wind/wind.nc
Format:
classic
Dimensions:
nele = 21284
node = 10951
time = 3 (UNLIMITED)
Variables:
init
Size: 3x1
Dimensions: time
Datatype: int32
time
Size: 3x1
Dimensions: time
Datatype: single
uwind_speed
Size: 21284x3
Dimensions: nele,time
Datatype: double
vwind_speed
Size: 21284x3
Dimensions: nele,time
Datatype: double
