NetCDF 共享软件 转载git
在 Models-3 模式中,使用的数据存取接口称为 I/O API,其实就是 NetCDF 文件格式。而因为咱们须要了解 Models-3 输出档案的数据状况,所以对于 NetCDF 的档案结构与变量型态须要有比较完整的了解。因此在底下的翻译数据中,须要知道的在基础篇的『简介』『前言』『NetCDF档案的主要组成成分』『NetCDF的数据格式』等部分须要比较详细的参详参详,另外,在工具篇里面有两个重要工具程序(ncgen与ncdump)也须要看一下的!至于进阶篇主要是针对程序发展者的介绍,有须要再看吧,并且这一部分我翻译的不是很好,虽然我本身看得懂,可是建议您直接看原文会比较容易进入情况喔!你也能够到这里来看一下原文说明喔!数据库
基础篇小程序
进阶篇(有须要再看,建议直接看原文)windows
工具篇数组
其余相关话题喔数据结构
简介:工具
NetCDF(network Common Data Format)最先是由美国国家科学委员会资助之计划--Unidata --所发展,其用意是在Unidata计划中不一样的应用项目下,提供一种能够通用的数据存取方式,数据的形状包括单点的观测值、时间序列、规则排列的网格、以及人造卫星或雷达之图像文件案。其自行说明表头的理念是参照NASA Goddart国家太空数据中心在1987年所发表的论文。网站
NetCDF 可简单的视为一种存取接口,任何使用 NetCDF 存取格式的档案就可称为 NetCDF 档案;至于 NetCDF 这套软件的功能,在于提供C、Fortran、C++、Perl、或其余语言I/O的连接库,以让程序发展者能够读写数据文件,其自己具备说明的能力、而且能够跨越平台和机器的限制。每个NetCDF档案能够含括多维度的、具备名称的变量,包括长短的整数、单倍与双倍精度的实数、字符等,且每个变量都有其自我介绍的数据,包括量度的单位、全名及意义等文字说明,在此摘要性的档头以后,才是真正的数据自己。
为什么 NetCDF 适合于科技技术方面的使用呢?这是由于这个接口是一种多维的数据分布系统,因此由这个接口所产生的档案,具备多维的数据格式,当你须要其中的某一笔数据时,程序将不会从第一笔数据读到你所须要的数据处,而是由 NetCDF 软件直接存取那一个数据!如此一来将会大量的下降模式运算时数据存取的时间。例如对于支持 NetCDF 格式的绘图软件来讲,只要有此格式的数据文件便可针对任一变数的任一维度或多维度(包括时间)变化进行绘图,并且不论这个变量的数据是存在档案中的那个地方,都可直接读取该值而不用循序读取在它前面数据后再读取该值,如此可大大减小绘图所需的时间。
另外,在三维空气质量模式仿真中,须要读入的排放源数据库及空气质量模式,并不是仅读取一次,模式是一直持续的在读取与计算。例如你模拟一个七天的事件,总共 168 个小时,那第一个小时读入数据后,程序便开始运算,等算完了,模式会再由数据文件读入第二小时的数据,以此类推,OK!那你知道通常传统档案如何读档吗?假设共有10000笔数据,而你要的是200-300及9800-9900这两段数据,则程序须要由第一笔数据读到第9900笔资料后,舍弃没必要要的 9700 笔数据后,才可获得你的 200 笔数据。那你晓得 NetCDF 的优势了吗?没错,如上面所述, NetCDF 只须要直接读取 200 笔数据就能够了,对,他能够直接到数据所在的那一个单元格去将数据取出!但也就是由于这样, NetCDF 所须要的空间是很大的,由于他多了不少的变量宣告项目,与其具备既定的单元格式所致!
Anyway,简单的说, NetCDF 是一套软件,也是一种存取接口,这种接口的优势在于『其数据具备说明的文件头』,因此数据不会被误用;而其存取方式为『直接至该笔数据读取』,所以能够省去不少没必要要的读取时间;另外,这种档案是一种能够『跨平台操做』读取的格式,所以,不论你是以何种操做系统制做 NetCDF 档案,在其余平台之下,仍是可使用这样的数据文件的!
Top
前言:
NetCDF 为 Network Common Data Form 的缩写,为一甚为有用的科技数据处理接口,其数据取出输入的方法与传统的由档头读至该笔使用 data 处不一样,故其接口较新,且须要使用特殊的程序读写,如下将主要介绍以 Fortran 程序语言建置 NetCDF 的方法,尤为当中 NetCDF 的文件格式最为重要!请详细看一下。这是由于 Models-3 主要就是使用 NetCDF 的文件格式,因此你能够不知道 NetCDF 如何建置,可是必定要晓得如何将 NetCDF 内的数据读出来看!
开宗明义的说, NetCDF 主要设计的目的,即在于增进储存、读取以及方便多维(array is an n-dimensional)数据的存取的一种档案『接口』。目前 NetCDF 已经开发至至关多的操做平台(Unix, WindowsNT等等,Linux也有支援)。至于 NetCDF 的档案结构将在后续的章节说明之。
说到最重要的执行效能(performance),如前所述,因为传统的档案读取方式实在太慢了,而且,对于多变量的档案(例如一个排放源数据文件中,将包含了 PM、VOC、SOx、NOx及其余林林总总的污染物变量)其读取方式很容易出错。这是由于在传统的档案中,每一笔数据都必需要在『特定的』相关位置,不可随意变更,不然在另外一个操做界面或者用户在使用时,将彻底看不懂这个档案里头数据的意义!而且可能形成程序的误判!而在 NetCDF 当中,因为其存取接口是使用 direct (直接)至该相关位置存取,而且每一笔数据都有对应的 ID,因此 PM 的数据绝对不会被程序看成 SOx 浓度使用!即便另外一个使用者创建的排放量 NetCDF 格式的档案中 PM 所放置的与原先的并不相同,那也彻底不会影响程序的读取数据!所以, NetCDF 不但能够增进数据的访问时间,亦且也能够帮助用户了解资料内容,而且也不易有错误数据发生。不过,如果当你的档案中仅有单一物种数据,那因为 NetCDF 是一笔一笔去读数据,而传统读文件的连续读取会比较快速!所以对于较为简单的档案, NetCDF 执行效能反而是不如传统的读档方式的,这点请必定要搞清楚!
其实在 MM5 的文件格式中,也是与 NetCDF 具备相同的功能,亦即每一笔数据都有对应的 ID以及该变量的简短说明(包括该变量的单位),因此对于数据的保存是颇有用的。另外,因为 NetCDF 能够跨平台操做,所以你在 Unix 创建的档案,拿到 windows NT 仍然是可使用的哩!很棒对不对!
说了这样多,可是 NetCDF 仍然是有缺点的。
- 因为 NetCDF 档案须要宣告变量,每一种变量都有其特定的单元格,而变数仅有六种,8-,8-,16-,32-,32-,64-bit(这一部分将在变数格式中说明),因此你的 NetCDF 档案一般要比传统的档案来的大。例如你的变数为 11-bit 的实数,但实数仅有 32-及64-bit 的变量,所以你的变量便需宣告为 32-bit 的变量,因此档案在无形之中就会变大啦!
- 因为 NetCDF 启始设计的环境并很差,(多是在 MS-DOS 的 FAT 表下设计的)因此对于每个档案的数据均只能到达 2GB 的限制,亦便是当你的档案数据太大,大到超过 2GB 则 NetCDF 就会显示错误啦!这也是下一阶段 NetCDF 发展团队努力想要克服的障碍!
Top
NetCDF 档案的主要组成:
任何一个 NetCDF 的档案均含有下列几个部分:
- dimensions:多维数据结构,例如 latitude, longitude, layers, and time
- variables:各类变数,例如 temperature, RH, latitude, longitude
- attributes:辅助记忆的说明文件头
- data:主要的资料部分。
咱们可使用下面这一个档案来作说明:在下表中,蓝色的字为鸟哥附加的说明,不包括在档案中!
netcdf example_1 { // example of CDL notation for a netCDF dataset 这一行只是 Title 的说明,告诉你这是一个 NetCDF 档案, 接在 // 以后的是说明的资料 dimensions: // dimension names and lengths are declared first lat = 5, lon = 10, level = 4, time = unlimited; 宣告数组的地方,上面宣布共有5个纬度(lat)、10个经度、四层、及时间等多维数组 要注意的地方是,time 为 unlimited 也就是说,关于时间的数组可一直增长下去! variables: // variable types, names, shapes, attributes float temp(time,level,lat,lon); temp:long_name = "temperature"; temp:units = "celsius"; float rh(time,lat,lon); rh:long_name = "relative humidity"; rh:valid_range = 0.0, 1.0; // min and max int lat(lat), lon(lon), level(level); lat:units = "degrees_north"; lon:units = "degrees_east"; level:units = "millibars"; short time(time); time:units = "hours since 1996-1-1"; // global attributes :source = "Fictional Model Output"; 宣告变量的地方,其中要注意的是: float、int 及 short 是变量的型态, float 为小数点、int 为整数,这一部分会在后面详细说明。 至于变量名称则有 temp, rh, lat, lon, level, time等,而且定义 temp 为时间、层、经纬度的函数, rh 为时间、经纬度的函数等等 另外,在每一个变量之下均有 long_name 及 units 的说明,这就是此一变量的说明文件头啦! 至于 //global attributes 指的是这个档案的主要参数喔!(例如网格数、原点坐标、这个档案的创建时间等等) data: // optional data assignments level = 1000, 850, 700, 500; lat = 20, 30, 40, 50, 60; lon = -160,-140,-118,-96,-84,-52,-45,-35,-25,-15; time = 12; rh =.5,.2,.4,.2,.3,.2,.4,.5,.6,.7, .1,.3,.1,.1,.1,.1,.5,.7,.8,.8, .1,.2,.2,.2,.2,.5,.7,.8,.9,.9, .1,.2,.3,.3,.3,.3,.7,.8,.9,.9, 0,.1,.2,.4,.4,.4,.4,.7,.9,.9; } 这是最后的部分,就是实体数据的存放处啦。level 共有四层,分别为1000,850,700与500, 如下的 lat 与 lon 均相赞成思! 至于 rh 则有 50 个数据,因为 rh 是(时间、经纬度)函数,因此在经纬度共分红50格(5x10) 而时间只有一个(12小时)的状况下,所以 rh 就有 50x1 =50 笔资料啦! |
请注意,上表是以 ASCII 码的型态来表示 NetCDF 的格式,实际的 NetCDF 格式并不是如此,必须藉由 NetCDF 软件的转换程序才能将上面的数据转成 NetCDF 格式文件!不过因为上面的 ASCII 码档案能够经由 NetCDF 的工具软件直接转换成 NetCDF 档案,因此与上面的档案具备相同格式的 files 就被称为 Network Common Data Form Language (CDL) 档案啦!
在安装 NetCDF 的那一节中,咱们提到了 setup NetCDF 最终会产生两个有用的工具程序,分别是 ncgen 及 ncdump 两个程序。其中, ncgen 能够将上面这一种 CDL 档案 (其实就是 ASCII 码档案) 直接转成 NetCDF 格式的档案,因此若是你不懂如何以 Fortran 写程序来转换 NetCDF 文件,则能够利用文书编辑软件写出上面这一种 CDL 档案后,在 Unix 平台下,直接将档案转换!另外,若是你只是要看看 NetCDF 档案的内容,则可使用 ncdump 来看档案!这两个档案很经常使用,尤为是 ncdump 更是经常使用的不得了!至于使用方法,会在后面再提到!
另外,要注意的是,因为 NetCDF 数据文件中共分为 variable 及 attributes 两种, attributes 可能会被包含在 variable 中,可是 attributes 不可能含有 variable ,且 attributes 没有比较有用的变量型态,所以在 user menual 中做者强烈建议科技数据使用 variables 的型态!
Top
NetCDF 的数据(Data)格式:
在前一节有提到 NetCDF 的主要内容,而其内容中最重要的部分大概就属 variable 的型态啦! NetCDF 的变量型态主要有六种,分别以下:
char |
8-bit characters intended for representing text. |
28 大小的字符 |
byte |
8-bit signed or unsigned integers. |
28大小的整数 |
short |
16-bit signed integers. |
216大小的短形整数 |
int |
32-bit signed integers. |
232大小的长形整数 |
float or real |
32-bit IEEE floating-point. |
232大小的浮点数 单精倍数 |
double |
64-bit IEEE floating-point. |
264大小的倍精倍数 |
上面是主要的 NetCDF 数据变量,并且每一种变量均有既定的单元格式,例如 char 变数中,就仅有 28 个字符的储存空间! int 就只能储存整数型态的数据等等,所以变量的宣告与你本来数据的型态相关性就很重大!这是由于若是你的变量型态定义错误的话,可能会形成你的数据的『准确度』彻底不对!而且程序也不会显示错误!这很严重。假设你的原始数据称为 external data 而经由 NetCDF 转换后储存在 NetCDF 档案的数据称为 internal data,若你的 external data 为 0.13245,可是你对这个数据宣告的变量型态为 byte 时,则程序会将 0.13245 存成 『0』 !小数点后的资料彻底不见了!!而且此一情况在程序执行中并不会产生 error message(由于实际上数据并无错误,有误的只是数据的准确度而已)。此外,若是你的数据为 1025 而你的变量宣告为 byte ,哈哈!那你的 data 将彻底不许确啦!所以你要针对你的数据去进行变量的宣告。固然,若是你惧怕变量宣告错误形成你的数据准确度的问题的话,这里提供一个建议,那就是将你全部的数值数据均宣告为储存空间最大的 double 这一个变量型态,那你的数据必定不会错!可是相对的,这样一来你的 NetCDF 档案就会无形之中增大不少,你能够想象的到,将 1 以 1.0000000000.......(n个0)型态储存,那样的空间必定是占去很大啦。
Top
进阶一:以Fortran程序创建NetCDF档案:
说穿了,使用 Fortran 程序语言要来写 NetCDF 的文件系统的话,是必定要使用到 NetCDF 的数据库(Library)的,他的 Library 不是很好懂,基本上,咱们也不是很须要了解啦(若是你只是要会跑 Models-3 而已的话),就连原做者也说即便你不懂 NetCDF 的 Library 也不要紧,由于还有 ncgen 这种小工具可让你直接将档案写入 NetCDF 当中。因此这一节以及底下连续的几个小节,都不是很须要努力的看,不过在讲到 ncdump 的使用方法那一节就要好好的看看啰!
咱们可使用 Fortran 写程序来创建、读取与增长变量于 NetCDF 档案,创建的方法共分为四种,分别为:创建新档案、读取已知变量的旧档案、读取未知变量的旧档案及增长变量进入档案中等四种。本节主要仅在说明须要的变量名称,详细的使用方法将在后面继续说明之。
如下以表稍微解释所须要的变量名称(在 Fortran 语言中的使用喔)
创建新档案须要的变量 |
NF_CREATE ! create netCDF dataset: enter define mode ... NF_DEF_DIM ! define dimensions: from name and length ... NF_DEF_VAR ! define variables: from name, type, dims ... NF_PUT_ATT ! assign attribute values ... NF_ENDDEF ! end definitions: leave define mode ... NF_PUT_VAR ! provide values for variable ... NF_CLOSE ! close: save new netCDF dataset |
读取已知变量的旧档案 |
NF_OPEN ! open existing netCDF dataset ... NF_INQ_DIMID ! get dimension IDs ... NF_INQ_VARID ! get variable IDs ... NF_GET_ATT ! get attribute values ... NF_GET_VAR ! get values of variables ... NF_CLOSE ! close netCDF dataset |
读取未知变量的旧档案 |
NF_OPEN ! open existing netCDF dataset ... NF_INQ ! find out what is in it ... NF_INQ_DIM ! get dimension names, lengths ... NF_INQ_VAR ! get variable names, types, shapes ... NF_INQ_ATTNAME ! get attribute names ... NF_INQ_ATT ! get attribute values ... NF_GET_ATT ! get attribute values ... NF_GET_VAR ! get values of variables ... NF_CLOSE ! close netCDF dataset |
增长变量于旧档案中 |
NF_OPEN ! open existing netCDF dataset ... NF_REDEF ! put it into define mode ... NF_DEF_DIM ! define additional dimensions (if any) ... NF_DEF_VAR ! define additional variables (if any) ... NF_PUT_ATT ! define other attributes (if any) ... NF_ENDDEF ! check definitions, leave define mode ... NF_PUT_VAR ! provide new variable values ... NF_CLOSE ! close netCDF dataset |
基本上你能够将每一种方法都区分为两个部分,一个是定义区(define)另外一个是数据写入区(data writing)。如上表的『创建新檔』中,先以 NF_CREATE 创建一个档案后,以 NF_DEF_DIM, NF_DEF_VAR, NF_PUT_ATT 宣告数组、变量及放置相关的说明后,再以 NF_ENDDEF 关闭定义区,请注意,必定要『先在定义区宣告一些变量后,并关闭定义区,才能够往下输入数据!』。在完成了变量定义以后,以 NF_PUT_VAR 一笔一笔创建数据的输入,待数据所有输入完毕后,方以 NF_CLOSE 关闭这一个程序!原则上,创建档案的步骤就是这样啰。那详细的执行流程会在后面再加以介绍。
在完成了程序的编写以后,最重要的固然就是编译与连结档案啰(compile and link)!在 Models-3 的 scripts 中常会看到相关的 NetCDF 的连接指令,因此这里你能够稍微看一下,以了解为什么 Models-3 的程序要这样写!
目的:在一个档名为 myprogram.f 的 Fortran 档案中,须要将 include 档案包含进这个程序;
语法: f77 -c -I/usr/local/include myprogram.f
说明:上面的语法中, -c -I 为 fortran 的 flags,-c 表示只要编译不要作成执行档,因此执行上面这一行以后,你会产生一个名为 myprogram.o 的档案;至于 /usr/local/include 则是你的 NetCDF 的所在目录下的档案(若是您是用鸟哥教你的安装方法安装的话)!以后则是要将刚刚的编译码作成执行档啦!一般你能够利用下面这两种写法来完成:
语法一:f77 -o myprogram myprogram.o -L/usr/local/lib -lnetcdf
语法二:f77 -o myprogram myprogram.o -l/usr/local/lib/libnetcdf
那就能够获得一个名为 myprogram 的执行档啰!这两种方法均可以将 NetCDF 的 Library 用在你的程序中,而 语法一 是较常于 Models-3 的程序中看到的一种方法!
Top
进阶二:新建、开启、变量宣告与结束档案的 Fortran 程序:
如同前一节(进阶一)提到的开启档案与宣告变量的方法,这一节主要将介绍档案开启与变量宣告的指令与其参数。另外,因为使用的是 NetCDF 的参数,因此在每一个 Fortran 程序以前均须要加入 『 include 'netcdf.inc'』这一行字。其中 netcdf.inc 这个档案是你在安装完了 NetCDF 后所产生的档案,放置在『 /usr/local/include 』中!
- NF_STRERROR(status)
这个指令主要在提供你除错的错误讯息!其中 status 为你程序执行错误时所传回来的数字,为整数!你能够写一个以下的子程序在每个档案的结尾处,将可让你的程序具备输出错误讯息的功能!
-----
subroutine handle_err(status)
integer status
if (status .NE. nf_noerr) then
print *, nf_strerror(status)
stop 'stopped'
endif
end
-----
- NF_INQ_LIBVERS()
取得你的 NetCDF 程序版本,语法为:
-----
print *, nf_inq_libvers()
-----
- NF_CREATE('filename', mode, ncid) <==极重要,新增长档案用
若你要创建一个名为 netcdf.ncf 的 NetCDF 档案,则你须要定义这个档案的开启号码(ncid 为整数),与其写入的方式(mode,分为 nf_clobber, nf_noclobber, nf_share)。要注意的是,ncid 虽然只是个整数,不过这个数字是由程序自动判断给的,因此不能够设定为固定!必须为变量型态!通常而言,你能够这样写:
-----
integer status, ncid
status=nf_create('netcdf.ncf', nf_clobber, ncid)
if (status .NE. nf_noerr) call handle_err(status) <==这里说明有错误就执行 handle_err 这个子程序
-----
- NF_OPEN('filename', mode, ncid) <==极重要,开启旧档案用
若是是开启一个已存在的档案的话,则使用 nf_open 这个指令啦!只有 mode 与 nf_create 不一样,其主要分为 nf_write (可擦写), nf_nowrite (只读文件,这是默认值), 及 nf_share三个主要模式。如下说明开启只读档的方法:
-----
status=nf_open('netcdf.ncf', nf_nowrite, ncid)
-----
- NF_REDEF(ncid) <==与 NF_OPEN 搭配使用
这个指令是用在当你要在一个已存在的档案中加入新变量时使用的!使用语法为:
-----
status=nf_redef(ncid)
-----
- NF_INQ(ncid, ndims, nvars, ngatts, unlimdimid)
这个指令用在读取一个已存在档案的变量、层数、与说明档数目,因此固然是与 nf_open 有关啰!基本上与读取档较为相关。
-----
status=nf_inq(ncid, ndims, nvars, ngatts, unlimdimid)
write(*,*), ndims, nvars, ngatts, unlimdimid
-----
- NF_ENDDEF(ncid)
这指令很重要,前面一章提过一个 fortran 程序可分为:变量宣告区与数据区,而变量宣告区『必定』要关闭以后才能进行数据的输入!因此宣告完变量以后必定要有这个指令才行:
-----
status=nf_enddef(ncid)
-----
- NF_CLOSE(ncid)
这个参数可下可不下,不过在你完成了一个 NetCDF 的工做以后,最后仍是下达这个指令,以使档案关闭!
-----
status=nf_close(ncid)
-----
Top
进阶三:定义 dimention 指令:
如前一章(进阶二)所述,在创建或开启了一个档案以后,再来就是要宣告维数(dimention)啦!维数的宣告指令以下:
- NF_DEF_DIM(ncid, name, len, dimid) <==与 nf_create 搭配
这个指令主要目的为:在开启的号码为 ncid 的档案中,增长一个名为 name 的维数,其个数为 len 个,并传回来 ID 为 dimid,注意,这里的 dimid 也必须是变量喔!若是在第一号档案中增长一个 lat 的维数,个数18个,并增长一个 rec 维数,个数可无限增长,则分别可写成:
-----
status=nf_def_dim(ncid, 'lat', 18, latid)
status=nf_def_dim(ncid, 'rec', nf_unlimited, recid)
-----
- NF_INQ_DIMID(ncid, name, dimid)
这个档案主要与 nf_open 搭配,目的在取得已存在档案的维数的 ID,这是由于在每一个维数中均有其代号(就是 ID),透过这个代号能够将相关的档案讯息读入!因此在读取一个已知档案时,一般须要这个指令喔!以下面的程序中若与上面一个指令相配合!
-----
status=nf_inq_dimid(ncid, 'lat', LATID)
-----
- NF_INQ_DIM(ncid, dimid, name, len)
这个程序必定是与 nf_inq_dimid 配合使用的,由 nf_inq_dimid 取得维数的代号以后,以这个指令将此维数(dimention)的讯息取得之。与上面的程序相配合,由下面的指令能够发现 name='lat', len=18。
-----
status=nf_inq_dim(ncid, LATID, name, len)
-----
- NF_RENAME_DIM(ncid, dimid, name)
这是一个能够改变维数名称的指令,与上面的程序相配合的话,则能够将 lat 改为 latitude 的维数名称:
-----
status=nf_rename_dim(ncid, LATID, 'latitude')
-----
Top
进阶四:创建与取得变量数据:
在宣告完了维数以后,固然就是变量的宣告与写入啰!基本上变量的定义用 nf_def_xxx, 而变量的调查使用 nf_inq_xxx, 变量的写入使用 nf_put_xxx, 而变量的读取则使用 nf_get_xxx,如下分别介绍之:
- NF_DEF_VAR(ncid, name, xtype, nvdims, vdims, varid) 宣告变量
这个指令在定义变量,上式中,name 为变量名称,xtype为变量的型态,还记得六种型态吧?分别是:nf_byte, nf_char, nf_short, nf_int, nf_float, nf_double 等六种。nvdims则是这个变量的内变量为多少,vdims则是变量的函数相对应的维数ID,varid则是这个变数的代码啦!假设咱们要记录一个相对湿度的变量,其根据经纬度及时间(三个内变量),因此 vdims 就必须与 经度、纬度、时间的ID相同啦!且其变量代码设为 VARID ,则能够写成:
-----
status=nf_creat('netcdf.ncf, nf_noclobber, ncid)
status=nf_def_dim(ncid, 'lat', 5, LATID)
status=nf_def_dim(ncid, 'lon', 10, LONID)
status=nf_def_dim(ncid, 'time', nf_unlimited, TIMEID)
integer RHDIMS(3)
RHDIMS(1) = LONID
RHDIMS(2) = LATID
RHDIMS(3) = TIMEID
status=nf_def_var(ncid, 'rh', nf_double, 3, RHDIMS, RHID)
-----
- NF_INQ_VARID(ncid, 'name', varid) 调查变量代码
这个指令的做用在取得变量的 ID ,基本上与前一节(进阶三)的 nf_inq_dimid 类似。在取得了变量的 ID 以后才能够取得变量的其余信息,因此这个指令与下一个指令一般适合在一块儿写的!语法为:
-----
status=nf_inq_varid(ncid, 'lat', LATID)
print *, LATID <== 能够列出从上个指令取得的变量代码!
-----
- NF_INQ_VAR(ncid, varid, 'name', xtype, ndims, dimids, natts)
根据 ncid 与 varid (前一个指令获得的)两个数据,即可取得 xtype, ndims, dimids, natts 的信息!语法为:
-----
status=nf_inq_var(ncid, LATID, latname, lattype, nlat, latdims, latnatts)
write(*,*), latname, lattype, nlat, latdims, latnatts
-----
- NF_PUT_VAR1_type(ncid, varid, index(x), type_val) 写入变数
这个指令在将你的『一笔数据』『读入』数据储存区啰!是很重要的一个指令!其中,type 为六种数据型态的名称,分别为『TEXT, INT1, INT2, INT, REAL, DOUBLE』六种。至于 index 则是一个数组,指出变量要存的地方,下面的指令更重要喔!能够去看看!在这个指令的语法:若咱们要记录三个相对湿度进入档案中,且三个相对湿度都是 0.5 ,则:
-----
integet RHINDX(3)
data RHINDX /4, 3, 2/
statuse=nf_put_var1_double(ncid, RHID, RHINDX, 0.5)
-----
- NF_PUT_VAR_type(ncid, varid, type_var(x))
这个指令比刚刚的更常使用在一个新创建的档案中,由于他是将『全部的数据数组均写入档案中』的一个指令!type 的型态与上个指令相同。假设咱们要写入一个三维数组函数(相对湿度),你能够这样写:
-----
double rhvar(ilon, ilat, itime)
do 10 ilon=1, lons
do 10 ilat=1, lats
do 10 itime=1, times
rhvar(ilon, ilat, itime)=0.5
10 continue
status=nf_put_var_double(ncid, RHID, rhvar)
-----
- NF_PUT_VARA_type(ncid, varid, start(x), count(x), type_var(x))
这个指令在于写入一部分数据进入一个 array 中。注意!这个 array 的维数要与已存在的档案相同,你能够与下一个指令相配合着看!这个指令比较经常使用在新增长或取代一部分数据于一个已存在的档案中。其中,start(x)指开始写入的位置,count(x)则是写入的个数!与上一个指令的范例相配合,咱们能够发现 rhvar 为一个三维的数组,因此 start 与 count 都须要输入三个变量启始与个数值。若由第1个写起,共写了 lons, lats, times 个,则:
-----
integer start(3), count(3)
data start /1, 1, 1/
data count /lons, lats, times/
status=nf_put_vara_double(ncid, RHID, start, count, rhvar)
-----
- NF_PUT_VARS_type(ncid, varid, start(x), count(x), stride(x), type_var(x))
配合上一个指令,这个指令仅写入一个比原来的数组(array)还要小的数组中,更经常使用于取代一个已存在的档案中的数据。例如上一个指令的范例中 rhvar 为三维变量,咱们要改变其中两个维数,则能够写成:
-----
integer start(2), count(2), stride(2)
statuse=nf_put_vars_real(ncid, RHID, start, count, stride, rh)
-----
- NF_PUT_VARM_type(ncid, varid, start(x), count(x), staride(x), imap(x), type_var(x))
这个指令我看不太懂,由于 map 的定义我并不明了之故!不过,基本上储存变量的方法以 nf_put_var, nf_put_vara, nf_put_var1 这三个指令较为重要!
- NF_GET_VAR1_type(ncid, varid, index(x), type_var)
这个指令在取得某变量的『一笔数据』,例如 rhval 这个三维数据中,咱们要取得 rhval(4,3,2) 这个变量值,你能够这样写:
-----
integet rhidx(3)
data rhidx /4, 3, 2/
statuse=nf_get_var1_double(ncid, RHID, rhidx, rhval)
print *, rhval
-----
- NF_GET_VAR_type(ncid, varid, type_var(x))
这个指令则是『取得某一变量的所有数据』。其中 type_var(x) 是一个数组啰!
-----
status=nf_get_var_double(ncid, RHID, rhval)
-----
- NF_GET_VARA_type(ncid, varid, start(x), count(x), type_var(x))
一样的,这个指令就是取得某一个数组区域内的变量数据啦!用法与前面 nf_put_vara_type 相同哩!
- NF_GET_VARS_type(ncid, varid, start(x), count(x), stride(x), type_var(x))
这个也应该不用再说了吧!就是取得更小的数组的数据啦!
- NF_RENAME_VAR(ncid, varid, 'newname')
这个指令在更改一个变量的名称,须要与 nf_redef, nf_inq_varid 配合写入,以下所示:
-----
status=open('netcdf.ncf', nf_write, ncid)
status=nf_redef(ncid)
status=nf_inq_varid(ncid, 'rh', RHID)
status=nf_rename_var(ncid, RHID, 'rel_hum')
status=nf_enddef_dim(ncid)
-----
Top
进阶五:创建与取得说明数据:
在前面的进阶一至进阶四中你已经创建好了一个 NetCDF 的档案了,可是你这个档案内容的属性尚未很详细的被定义下来,这个说明部分就是所谓的 attributes 部分。为什么要加入这一部分呢?这是由于咱们在前面的时候就已经提到了, NetCDF 能够有很详细的文件属性说明,以免档案的内容被误判!基本上 Models-3 里面的输出档,都有很详细的说明档头,另外,针对每个变量亦均加入了适当的说明,例如单位(moles/s)、长名(long name)等等。底下说说主要的几个指令吧!
- NF_PUT_ATT_type(ncid, varid, 'name', xtype, len, type_var(x))
一样的,与(进阶四)中提到的相同, xtype 共分为六种型态:nf_byte, nf_char, nf_short, nf_int, nf_float, nf_double 等六种。而 type_var(x) 是一个数组喔!例如咱们要对 rh 进行变量说明,说明的内容为 『valid_range』,而咱们给他的合理区间在 (0.0D0 ~ 100.0D0)则:
-----
double rhrange(2)
data rhrange /0.0D0, 100.0D0/
status=nf_put_att_double(ncid, RHID, 'valid_range', nf_double, 2, rhrange)
-----
- NF_INQ_ATT(ncid, varid, 'name', xtype, len)
调查 attributes 的档头说明,一般与 nf_inq_varid 配合使用。
-----
status=nf_inq_varid(1, 'rh', rhid)
status=nf_inq_att(ncid, rhid, name, xtype, len)
write(*,*), name, xtype, len
-----
- NF_GET_ATT_type(ncid, varid, 'name', type_var(x))
取得 attribute 的内容!
-----
status=nf_get_att_double(ncid, rhid, 'balid_range', vrval)
-----
- NF_RENAME_ATT(ncid, varid, 'name', newname)
与 nf_rename_var 类似的用法,往前翻翻看看吧!
- NF_DEL_ATT(ncid, varid, 'name')
就是砍到不要的 attribute 咯,方法以下:
-----
status=nf_del_att(ncid, rhid, 'valid_range')
-----
Top
进阶六:程序范例:
基本上,如同一开始说到的,进阶这一部分的资料在 for fortran 的 NetCDF 手册中有蛮详细的说明,因此若是你有任何关于程序的写做问题真的直接就去找原文啦!不过原文手册中虽然有对于每个指令进行详尽的解释,可是并无一个完整的 fortran 程序,所以鸟哥我本人就写了几个小程序来玩玩啦,若是你有兴趣的话,能够下载来执行看看啰。(注:写完了这个程序后,让小弟对于 NetCDF 档案的制做过程有更清楚了理解。)
范例一:创建一个三维的档案,里头有两个变量,分别为 PM10 与 PM2_5,其中,PM10 为 50 ,PM2.5 为 30,且说明内容 PM 浓度为 ug/m3。按这里下载吧!
Top
有用的工具:
NetCDF 的单元格式:
NetCDF 在储存的时候大体上分为两个区域,如同前面在讲到 CDL 档案的时候提到的样子。分为:
- 档头(header):主要用来记录变量名称、个数与型态;dimention名称、个数与型态;以及相关的说明内容。因为这一部份内容并无用到实际数据储存的空间,因此使用的空间并不会多出来!
- 资料区(data):这一部分就是实际数据记录的地方啦!因为这一部分的空间有涉及你当初设定的变量型态,假如你的数据为整数,可是你记录的单元格式为倍精倍数,则这个区域的储存空间无形之中会变的很大!
基本上就仅分为这两个部分!因此你在看档案的时候,看前面就知道后面数据的型态!
ncgen:
这个小程序主要是用来将 CDL 档案转成 NetCDF 档案的工做!假设你已经写了一个 CDL 档案,名称为 netcdf.cdl ,你想将此档案转成 NetCDF 档,则只要下达:
# ncgen -o netcdf.ncf netcdf.cdl
就能够了,语法为: ncgen -o [output filename] [input filename]。
并且 ncgen 亦提供一个不错的选项,亦即将你的 netcdf.cdl 档案转成一个 fortran 程序,则你只要将此 程序 编译并执行后,则能够将 netcdf.cdl 转成 NetCDF 档案!
# ncgen -f netcdf.cdl > netcdf.f
上式中 netcdf.f 为 fortran 程序文件。不过用此语法须要注意,由于此一语法仅适合比较小的 CDL 档案!
ncdump:
另一个最有经常使用到的程序称为 ncdump ,主要的目的在于将 NetCDF 档案数据读成 ASCII 码的数据!因为 NetCDF 储存区分为两段,一个为档头、一个为数据区,若你只想读取数据区的变量使用状况,则能够下达:
# ncdump -h netcdf.ncf
则屏幕上将出现 netcdf.ncf 这个档案的文件头数据。而若是你想要将全部的档案都输出成为 ASCII 码数据,则直接下达:
# ncdump netcdf.ncf | more
便可,在上式中, "| more"这个指令做用是将 netcdf.ncf 这个档案以一个画面一个画面的方式展现之意。而若是你想要将画面的资料存成一个 CDL 档案,能够下达:
# ncdump netcdf.ncf > netcdf.cdl
则程序将直接把 netcdf.ncf 档案转存成一个 netcdf.cdl 的 ASCII 码格式的档案!如此则你将看的到里头的资料啰!
不过使用的时候要当心,由于一个 Models-3 输出档经常是几百 MB 的大小,若是你将 NetCDF 的数据直接存成 ASCII 码的档案,将耗费不少时间与空间!所以上,除非是你在除错或者是档案很小,不然不是很必要将档案转存成 ASCII 格式的档案!
而若你只想察看 netcdf.ncf 档案里面一个名为 'TEMP' 的变量的话,你能够下达:
# ncdump -v TEMP netcdf.ncf
语法为:ncdump -v [变量名称] [文件名]。这也是一个经常使用的参数喔!