首先先定義疊圖與拼圖。
何謂疊圖 (composite)?
這裏所謂的疊圖,是指在一張圖上,運用顏色、形狀等方式展現數個不同的場量。舉例來說,可以在一張地面天氣圖上面同時畫上地面氣壓,氣溫,風場,水氣。運用不同顏色的等值線或粗細或塗色,可以將數筆資訊濃縮在一張圖裡面。若學過GrADS,可以知道這是一個在直覺不過的動作,先畫氣壓,再畫氣溫,再畫風場,最後畫水氣,結束。要疊幾張,就同一個步驟重複幾次就可以了。但用NCL做起來可是複雜了幾分...。
何謂拼圖 (panel)?
在一面畫布 (一張PNG或一頁PDF,) 一次上呈現多張圖。舉例來說,要把春、夏、秋、冬四個季節分別的平均氣溫,同時畫在一張畫布上,以2x2的方式排列,左上為春,右上為夏,左下為秋,右下為冬。
Concept of Hold-On
在看範例前,先就概念上解釋一下作法。
是否曾用Matlab疊過圖?譬如畫兩條不同的拋物線在同一個XY座標上,概念是十分類似的。如果直接:
plot(x1,y1)
plot(x2,y2)
這樣輸入兩次 plot 指令,那麼最後只會有第二條線出現在畫面上。因為第二次的 plot 把第一次的 plot 蓋掉了!在Matlab中用 "hold" 告知電腦後面還有圖要畫,類似這樣:
plot(x1,y1) ; hold on
plot(x2,y2) ; hold off
回到NCL。
一樣用前面使用過的 air.2014.nc 來練習。若要將兩層不同高度的溫度場疊起來,如果像 Day 3 中的範例 NCL101-4.ncl 那樣直接輸入兩次
plot = gsn_csm_contour_map_ce( wks , Temp( 0, : , : ) , res )
plot = gsn_csm_contour_map_ce( wks , Temp( 1 , : , : ) , res )
兩層溫度場並不會疊在同一張圖上,而是會得到獨立分開的兩張圖。所以,要找到在NCL中類似 "hold" 的指令,請它等一下 (hold on),等你的 plot 指令全部下完後再一起畫!
Draw and Frame
NCL中,請它等一下的參數是
res@gsnDraw = False ; 先別畫!
res@gsnFrame = False ; 先別翻頁!
第一個,@gsnDraw,代表先不要畫;第二個,@gsnFrame 代表先不要翻頁。如果不特別指定,NCL預設會一直自動翻頁畫下一張圖,就像之前範例 NCL101-4.ncl 中,執行了三次的 plot 後,出來的 AirTempMap2.pdf 會有三頁,每頁一張圖。
最後再介紹兩個指令就可以開工了:
draw(plot) ; 可以畫圖了!
frame(wks) ; 可以翻頁了!
在下面的範例 NCL101-5.ncl 中,總共開了四個WorkStations,執行script後會產生四個PDF檔。由於已經事先將 @gsnDraw 和 @gsnFrame 指定為 False,所以在這個script中必須手動執行 draw 和 frame 才行。
;===== NCL101-5.ncl =====
load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/gsn_code.ncl"
load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/gsn_csm.ncl"
begin
; Work Station
wks_type = "pdf"
wks_type@wkPaperWidthF = 8.0
wks_type@wkPaperHeightF = 4.5
wks1 = gsn_open_wks(wks_type,"day4-1")
wks2 = gsn_open_wks(wks_type,"day4-2")
wks3 = gsn_open_wks(wks_type,"day4-3")
wks4 = gsn_open_wks(wks_type,"day4-4")
; Variable
ncFile = addfile("air.2014.nc","r")
Temp = ncFile->air(0,:,:,:)
; Plot resources
res = True
res@gsnMaximize = True
res@gsnPaperOrientation = "portrait"
res@gsnDraw = False
res@gsnFrame = False
; Plot on wks1
plot1 = gsn_csm_contour_map_ce(wks1,Temp( 0,:,:),res)
draw(plot1)
frame(wks1)
plot1 = gsn_csm_contour_map_ce(wks1,Temp( 5,:,:),res)
draw(plot1)
frame(wks1)
plot1 = gsn_csm_contour_map_ce(wks1,Temp(10,:,:),res)
draw(plot1)
frame(wks1)
; Plot on wks2
plot2 = gsn_csm_contour_map_ce(wks2,Temp( 0,:,:),res)
plot2 = gsn_csm_contour_map_ce(wks2,Temp( 5,:,:),res)
plot2 = gsn_csm_contour_map_ce(wks2,Temp(10,:,:),res)
draw(plot2)
frame(wks2)
; Plot on wks3
plot3 = gsn_csm_contour_map_ce(wks3,Temp( 0,:,:),res)
draw(plot3)
plot3 = gsn_csm_contour_map_ce(wks3,Temp( 5,:,:),res)
draw(plot3)
plot3 = gsn_csm_contour_map_ce(wks3,Temp(10,:,:),res)
draw(plot3)
frame(wks3)
plot4 = gsn_csm_contour_map_ce(wks4,Temp( 0,:,:),res)
frame(wks4)
plot4 = gsn_csm_contour_map_ce(wks4,Temp( 5,:,:),res)
frame(wks4)
plot4 = gsn_csm_contour_map_ce(wks4,Temp(10,:,:),res)
frame(wks4)
draw(plot4)
print("All Done.")
end
;=====
第一個PDF,是每 plot 一次,就 draw 一次,再 frame 一次。翻譯成白話文就是,每作一張圖 (plot) 就畫 (draw) 到畫布上然後翻面 (frame)。所以第一個PDF檔案理論上是跟 NCL101-4.ncl 所做出來的 AirTempMap2.pdf 相似。
而後面三個PDF檔分別測試了不同策略的 draw 和 frame 的組合。在打開下面的PDF檔案連結之前,你能先想想看每個檔案應該長什麼樣子嗎?結果和你想的一樣嗎?
解答:
day4-1.pdf
day4-2.pdf
day4-3.pdf
day4-4.pdf
Composite and Panel
範例 NCL101-6.ncl 示範如何疊圖和拼圖。跟疊圖和拼圖直接相關的指令用螢光筆畫了重點。
;===== NCL101-6.ncl =====
load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/gsn_code.ncl"
load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/gsn_csm.ncl"
begin
; Work Station
wks_type = "pdf"
wks_type@wkPaperWidthF = 8.0
wks_type@wkPaperHeightF = 4.5
wks = gsn_open_wks(wks_type,"day4_example")
; Variable
ncFile = addfile("air.2014.nc","r")
Temp = ncFile->air(0,:,:,:)
; Plot resources
res = True
res@gsnLeftString = ""
res@gsnRightString = ""
res@gsnDraw = False
res@gsnFrame = False
; Resources for contour plot
res_cn = res
res_cn@cnFillOn = False
res_cn@cnLinesOn = True
res_cn@cnInfoLabelOn = False
; Resources for shading plot
res_sd = res
res_sd@gsnMaximize = True
res_sd@gsnPaperOrientation = "portrait"
res_sd@cnFillOn = True
res_sd@cnLinesOn = False
res_sd@mpCenterLonF = 180.
res_sd@mpMinLatF = 0.
res_sd@mpMaxLatF = 80.
res_sd@mpMinLonF = 60.
res_sd@mpMaxLonF = 200.
res_sd@tiMainString = "Composite Demo"
res_sd@gsnLeftString = "Shading: T @ level 0"
res_sd@gsnRightString = "Contour: T @ level 5"
res_sd@lbOrientation = "vertical"
res_pn = True
res_pn@gsnMaximize = True
res_pn@gsnPaperOrientation = "portrait"
; composite plot
plot_sd = gsn_csm_contour_map_ce(wks,Temp(5,:,:),res_sd)
plot_cn = gsn_csm_contour(wks,Temp(0,:,:),res_cn)
overlay(plot_sd,plot_cn)
draw(plot_sd)
frame(wks)
; panel plot (3*2)
plot_pn = new(6,graphic)
plot_pn(0) = gsn_csm_contour_map_ce(wks,Temp(0,:,:),res_cn)
plot_pn(1) = gsn_csm_contour_map_ce(wks,Temp(1,:,:),res_cn)
plot_pn(2) = gsn_csm_contour_map_ce(wks,Temp(2,:,:),res_cn)
plot_pn(3) = gsn_csm_contour_map_ce(wks,Temp(3,:,:),res_cn)
plot_pn(4) = gsn_csm_contour_map_ce(wks,Temp(4,:,:),res_cn)
plot_pn(5) = gsn_csm_contour_map_ce(wks,Temp(5,:,:),res_cn)
gsn_panel(wks,plot_pn,(/2,3/),res_pn)
print("All Done.")
end
;=====
>>$ NCL101-6.ncl
執行後產生 day4_example.pdf
範例 script 說明:
<<疊圖>>
疊圖的要領就是先在 plot resources 中設定「先別畫」+「先別翻頁」
res@gsnDraw = False
res@gsnFrame = False
設定好 plot_sd 和 plot_cn 兩張要疊在一起的圖之後,告訴NCL要哪張壓在哪張上面
overlay(底圖,上面疊的那張圖)
在範例中一張是shding一張是contour,所以如果寫反把shading疊在contour上面,會把contour完全覆蓋掉;相對的,如果兩張都是contour,不管哪張在上面都可以看到疊加在一起的兩張圖。
另外要注意的是兩張含有地圖資訊 (gsn_csm_contour_map_ce) 的圖是無法疊加的,所以只有底圖可以用 gsn_csm_contour_map_ce,要疊在上面的圖都只能用 gsn_csm_contour 來畫。
最後提醒一點,如果要疊三張以上的圖也沒問題,一樣都先設定好 plot,再一次一張的蓋上去:
plot_bottom = ...
plot1 = ...
plot2 = ...
plot3 = ...
overlay( plot_bottom , plot1 )
overlay( plot_bottom , plot2 )
overlay( plot_bottom , plot3 )
draw(plot_bottom)
<<拼圖>>
說穿了,拼圖就是一個指令而已
gsn_panel( wks , plot_pn , (/2,3/) , res_pn )
函數 gsn_panel 需要的 input 就是:WorkStation,圖,排列方式,Resources。
為了方便輸入 (縮短程式碼),通常會把圖做成一個 array,像範例中的作法:
plot_pn = new( 6 , graphic )
plot_pn 就是一個可以含有6個plot的集合。new 是一個常用的函數,也常常被用來定義一個新的變數,譬如 NewTemp = new( (/nT,nZ,nY,nX/) , float ) 再次提醒一下,記得像這樣把座標順序反過來寫。
排列方式,就是一個二維的向量,指定拼圖總共有幾行幾欄。在NCL中一個陣列的標準寫法就是 ( / A , B , C , D , ... / )。
最後提醒一點,從 NCL101-4.ncl 就都有使用到的兩個設定 @gsnMaximize 和 @gsnPaperOrientation 一直還沒有解釋用途。在單張單張作圖的時候,照著先用就對了,不用管它們的用途。但在疊圖與拼圖時,需要特別注意使用的時機,才不會讓作出來的圖忽大忽小或位置不太對。這裏只講結論:
1. 對於疊圖,只有底圖要做這兩個設定。
2. 對於拼圖,只有最後一個步驟的 gsn_panel 要做這兩個設定。
待續... Day 5
沒有留言:
張貼留言