NC文件读写方式

一、概述:

NetCDF全称为network Common Data Format,中文译法为“网络通用数据格式”

对程序员来说,它和zip、jpeg、bmp文件格式类似,都是一种文件格式的标准。netcdf文件开始的目的是用于存储气象科学中的数据,现在已经成为许多数据采集软件的生成文件的格式。 

从数学上来说,netcdf存储的数据就是一个多自变量的单值函数。用公式来说就是f(x,y,z,…)=value, 函数的自变量x,y,z等在netcdf中叫做维(dimension) 或坐标轴(axix),函数值value在netcdf中叫做变量(Variables).而自变量和函数值在物理学上的一些性质,比如计量单位(量纲)、物理学名称等等。 在netcdf中就叫属性(Attributes).

二、netcdf文件的内容:

一个netcdf文件的结构包括以下对象: 

1、变量(Variables) 

变量对应着真实的物理数据。比如我们家里的电表,每个时刻显示的读数表示用户的到该时刻的耗电量。这个读数值就可以用netcdf里的变量来表示。它是一个以时间为自变量(或者说自变量个数为一维)的单值函数。再比如在气象学中要作出一个气压图,就是“东经xx度,北纬yy度的点的大气压值为多少帕”,这是一个二维单值函数,两维分别是经度和纬度。函数值为大气压。

从上面的例子可以看出,netcdf中的变量就是一个N维数组,数组的维数就是实际问题中的自变量个数,数组的值就是观测得到的物理值。变量(数组值)在netcdf中的存储类型有六种,ascii字符(char) ,字节(byte), 短整型(short), 整型(int), 浮点(float), 双精度(double). 显然这些类型和c中的类型一致,搞C的朋友应该很快就能明白。

2、维(dimension) 

一个维对应着函数中的某个自变量,或者说函数图象中的一个坐标轴,在线性代数中就是一个N维向量的一个分量(这也是维这个名称的由来)。在netcdf中,一个维具有一个名字和范围(或者说长度,也就是数学上所说的定义域,可以是离散的点集合或者连续的区间)。在netcdf中,维的长度基本都是有限的,最多只能有一个具有无限长度的维。

3、属性(Attribute) 

属性对变量值和维的具体物理含义的注释或者说解释。因为变量和维在netcdf中都只是无量纲的数字,要想让人们明白这些数字的具体含义,就得靠属性这个对象了。 

在netcdf中,属性由一个属性名和一个属性值(一般为字符串)组成。比如,在某个cdl文件(cdl文件的具体格式在下一节中讲述)中有这样的代码段 

temperature:units = “celsius” ; 

前面的temperature是一个已经定义好的变量(Variable),即温度,冒号后面的units就是属性名,表示物理单位,=后面的就是units这个属性的值,为“celsius” ,即摄氏度,整个一行代码的意思就是温度这个物理量的单位为celsius,很好理解。

三、CDL结构:

CDL全称为network Common data form Description Language,它是用来描述netcdf文件的结构的一种语法格式。它包括前面所说的三种netcdf对象(变量、维、属性)的具体定义。看一个具体例子(这个例子cdl文件是从netcdf教程中的2.1 节The simple xy Example摘出来的)

netcdf simple_xy {

dimensions:

x = 6 ;

y = 12 ;

variables:

int data(x, y) ;

data:

data =

0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,

12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,

24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,

36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,

48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,

60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71 ;

}

上面的代码定义了一个符合netcdf格式的结构simple_xy, 这个结构包括三个部分 

1、维的定义,以dimensions:关键字开头 

dimensions: 

x = 6 ; 

y = 12 ; 

定义了两个轴(或者说两维),名字分别为x和y,x轴的长度(准确的说是坐标点的个数)为6, y轴的长度为12。

2、变量的定义:以variables:开头 

variables: 

int data(x, y); 

定义了一个以x轴和y轴为自变量的函数data,数学公式就是f(x,y)=data; 

注意维出现的顺序是有序的,它决定data段中的具体赋值结果.

3、数据的定义,以data:开头 

data: 

data = 

0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 

12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 

24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 

36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 

48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 

60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71 ; 

这段数据用数学的函数公式f(x,y)=data可以看出:

x=0,y=0时,data = 0; 
x=0,y=1时,data = 1;
x=5,y=11是,data=71;

但是要注意的是: 

1、赋值顺序: 

我们给出的是c格式的cdl文件,因此这里的赋值顺序和c语言中的一致,也就是通常所说的“行式赋值”,而fortran语言中则是“列式赋值”,因此在fortran格式的cdl文件中,data段的数值顺序和这里正好行列互换。 

2、自变量的默认取值和坐标变量 

如果只给出维的长度,那么维的值默认从0开始,然后自动加1,到(长度-1)停止, 

很多情况下我们要自己给出每个点的坐标值,这时就需要用到netcdf里的坐标变量 

“coordinate varibles”:增加一个和只和维相关的一元函数(自变量)并给出它的取值范围。 

比如下面的cdl文件(摘自netcdf教程中的2.2 The sfc pres temp Example) 

netcdf sfc_pres_temp { 

dimensions: 

latitude = 6 ; //纬度轴 

longitude = 12 ; //经度轴 

variables: 

float latitude(latitude) ; //坐标变量,存储具体纬度 

latitude:units = “degrees_north” ; 

float longitude(longitude) ; //坐标变量,存储具体纬度 

longitude:units = “degrees_east” ; 

float pressure(latitude, longitude) ; //某个点(经度和纬度的交点)的大气压值 

pressure:units = “hPa” ; //大气压的单位为 

float temperature(latitude, longitude) ; //某个点(经度和纬度的交点)的温度值 

temperature:units = “celsius” ; //温度的单位为 

data: 

latitude = 25, 30, 35, 40, 45, 50 ; 

longitude = -125, -120, -115, -110, -105, -100, -95, -90, -85, -80, -75, -70 ; 

pressure = 

900, 906, 912, 918, 924, 930, 936, 942, 948, 954, 960, 966, 

901, 907, 913, 919, 925, 931, 937, 943, 949, 955, 961, 967, 

902, 908, 914, 920, 926, 932, 938, 944, 950, 956, 962, 968, 

903, 909, 915, 921, 927, 933, 939, 945, 951, 957, 963, 969, 

904, 910, 916, 922, 928, 934, 940, 946, 952, 958, 964, 970, 

905, 911, 917, 923, 929, 935, 941, 947, 953, 959, 965, 971 ; 

temperature = 

9, 10.5, 12, 13.5, 15, 16.5, 18, 19.5, 21, 22.5, 24, 25.5, 

9.25, 10.75, 12.25, 13.75, 15.25, 16.75, 18.25, 19.75, 21.25, 22.75, 24.25, 

25.75, 

9.5, 11, 12.5, 14, 15.5, 17, 18.5, 20, 21.5, 23, 24.5, 26, 

9.75, 11.25, 12.75, 14.25, 15.75, 17.25, 18.75, 20.25, 21.75, 23.25, 24.75, 

26.25, 

10, 11.5, 13, 14.5, 16, 17.5, 19, 20.5, 22, 23.5, 25, 26.5, 

10.25, 11.75, 13.25, 14.75, 16.25, 17.75, 19.25, 20.75, 22.25, 23.75, 

25.25

对于上面的数据,就是 

latitude = 25,longitude = -125时,pressure = 900,temperature = 9; 

latitude = 25,longitude = -120时,pressure = 906,temperature = 10.5; 

以此类推。

四、文件读写:

一次只读取一层

如果CONC是一个7维的变量,为了节省空间,如果每一次只读取一层,方法如下所示 

int[] start = { 0, 0, 0, 0, 0, 0, 0 }; /* 开始的位置*/ 

int[] count = { 1, 1, 1, 1, 1, south_northLen, west_eastLen };//每次读取的数组大小 

start[4] = l; 

CONCarraySize = south_northLen * west_eastLen; 

float[] CONC = new float[CONCarraySize];//DRYDEP和WETDEP大小是一样的 

NetCDF.nc_get_vara_float(ncid, CONCid, start, count, CONC);

一次将所有的数据均读取出来

 float[] U10 = new float[south_northLen * west_eastLen];

 float[] V10 = new float[south_northLen * west_eastLen];

 NetCDF.nc_inq_varid(ncid, "U10", out Uid);

 NetCDF.nc_inq_varid(ncid, "V10", out Vid);

 NetCDF.nc_get_var_float(ncid, Uid, U10);

 NetCDF.nc_get_var_float(ncid, Vid, V10);

目前更新到此,后期有深入了解再继续更新......

  • 12
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值