NetCDF 共享軟件 中文

 

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 』中!

  1. NF_STRERROR(status) 
    這個指令主要在提供你除錯的錯誤訊息!其中 status 爲你程序執行錯誤時所傳回來的數字,爲整數!你能夠寫一個以下的子程序在每個檔案的結尾處,將可讓你的程序具備輸出錯誤訊息的功能! 
    ----- 
    subroutine handle_err(status) 
    integer status 
    if (status .NE. nf_noerr) then 
    print *, nf_strerror(status) 
    stop 'stopped' 
    endif 
    end 
    -----
  2. NF_INQ_LIBVERS() 
    取得你的 NetCDF 程序版本,語法爲: 
    ----- 
    print *, nf_inq_libvers() 
    -----
  3. 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 這個子程序 
    -----
  4. NF_OPEN('filename', mode, ncid) <==極重要,開啓舊檔案用 
    若是是開啓一個已存在的檔案的話,則使用 nf_open 這個指令啦!只有 mode 與 nf_create 不一樣,其主要分爲 nf_write (可擦寫), nf_nowrite (只讀文件,這是默認值), 及 nf_share三個主要模式。如下說明開啓只讀檔的方法: 
    ----- 
    status=nf_open('netcdf.ncf', nf_nowrite, ncid) 
    -----
  5. NF_REDEF(ncid) <==與 NF_OPEN 搭配使用 
    這個指令是用在當你要在一個已存在的檔案中加入新變量時使用的!使用語法爲: 
    ----- 
    status=nf_redef(ncid) 
    -----
  6. NF_INQ(ncid, ndims, nvars, ngatts, unlimdimid) 
    這個指令用在讀取一個已存在檔案的變量、層數、與說明檔數目,因此固然是與 nf_open 有關囉!基本上與讀取檔較爲相關。 
    ----- 
    status=nf_inq(ncid, ndims, nvars, ngatts, unlimdimid) 
    write(*,*), ndims, nvars, ngatts, unlimdimid 
    -----
  7. NF_ENDDEF(ncid) 
    這指令很重要,前面一章提過一個 fortran 程序可分爲:變量宣告區與數據區,而變量宣告區『必定』要關閉以後才能進行數據的輸入!因此宣告完變量以後必定要有這個指令才行: 
    ----- 
    status=nf_enddef(ncid) 
    -----
  8. NF_CLOSE(ncid) 
    這個參數可下可不下,不過在你完成了一個 NetCDF 的工做以後,最後仍是下達這個指令,以使檔案關閉! 
    ----- 
    status=nf_close(ncid) 
    -----

Top

 


 


進階三:定義 dimention 指令:

如前一章(進階二)所述,在創建或開啓了一個檔案以後,再來就是要宣告維數(dimention)啦!維數的宣告指令以下:

  1. 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) 
    -----
  2. NF_INQ_DIMID(ncid, name, dimid) 
    這個檔案主要與 nf_open 搭配,目的在取得已存在檔案的維數的 ID,這是由於在每一個維數中均有其代號(就是 ID),透過這個代號能夠將相關的檔案訊息讀入!因此在讀取一個已知檔案時,一般須要這個指令喔!以下面的程序中若與上面一個指令相配合! 
    ----- 
    status=nf_inq_dimid(ncid, 'lat', LATID) 
    -----
  3. 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) 
    -----
  4. 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,如下分別介紹之:

  1. 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) 
    -----
  2. NF_INQ_VARID(ncid, 'name', varid) 調查變量代碼 
    這個指令的做用在取得變量的 ID ,基本上與前一節(進階三)的 nf_inq_dimid 類似。在取得了變量的 ID 以後才能夠取得變量的其餘信息,因此這個指令與下一個指令一般適合在一塊兒寫的!語法爲: 
    ----- 
    status=nf_inq_varid(ncid, 'lat', LATID) 
    print *, LATID <== 能夠列出從上個指令取得的變量代碼! 
    -----
  3. 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 
    -----
  4. 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) 
    -----
  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) 
    -----
  6. 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) 
    -----
  7. 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) 
    -----
  8. 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 這三個指令較爲重要!
  9. 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 
    -----
  10. NF_GET_VAR_type(ncid, varid, type_var(x)) 
    這個指令則是『取得某一變量的所有數據』。其中 type_var(x) 是一個數組囉! 
    ----- 
    status=nf_get_var_double(ncid, RHID, rhval) 
    -----
  11. NF_GET_VARA_type(ncid, varid, start(x), count(x), type_var(x)) 
    一樣的,這個指令就是取得某一個數組區域內的變量數據啦!用法與前面 nf_put_vara_type 相同哩!
  12. NF_GET_VARS_type(ncid, varid, start(x), count(x), stride(x), type_var(x)) 
    這個也應該不用再說了吧!就是取得更小的數組的數據啦!
  13. 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)等等。底下說說主要的幾個指令吧!

  1. 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) 
    -----
  2. 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 
    -----
  3. NF_GET_ATT_type(ncid, varid, 'name', type_var(x)) 
    取得 attribute 的內容! 
    ----- 
    status=nf_get_att_double(ncid, rhid, 'balid_range', vrval) 
    -----
  4. NF_RENAME_ATT(ncid, varid, 'name', newname) 
    與 nf_rename_var 類似的用法,往前翻翻看看吧!
  5. 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 [變量名稱] [文件名]。這也是一個經常使用的參數喔!

相關文章
相關標籤/搜索