はじめに
論文の図はここ最近はずっとmatplotlibやcartopyで描いているけれど、描き方をよく忘れる。調べ直すのは思いの外面倒。忘れないようにこの記事に使える方法を残しておく。
matplotlib
フォント設定
論文ではフォントの指定があることが多く、ほとんどの場合Arialにしておけば問題ないので、コードの初めの方に以下のように設定しておく。
plt.rcParams['font.family']='Arial'
共通Y軸の設定
一つのグラフにX軸を2つ追加したい場合には以下のようにする。Y軸を2つ追加したい場合にはtwinxを使う。
ax11=ax[1,1].twiny()
ax11.plot(std1,lev1,color='black',ls='dashed')
ax11.plot(std2,lev1,color='red',ls='dashed')
ax11.set_xlim([0,2.5])
カラーマップパッケージ
以下の"colormaps"という名前のパッケージをimportすればNCL以外の色んなカラーパレットが使えるようになる。名前がややこしいので検索してもヒットしづらい。
使い方は以下のとおり。内部ではカテゴリー分けがあるものの、使用時にはカテゴリー指定はしない。
import colormaps as cmaps
# set colormap
color1=cmaps.BlueWhiteOrangeRed
gridspec
図中にパネルが多くなってくるとsubplotsではしんどく、gridspecが必要になる。ただしgridspecの使い方は様々で、あの設定はどうすればよかったけ・・となることが多い。よく使う使い方についてここにメモしておく。
パネルの初期作成
パネルを複数生成するのにはgridspecを使えばいいけど、どうやって呼び出すんだっけ・・とよく忘れる。以下では3行4列のパネルを生成している。figはplt.figureで呼び出し、axはnp.emptyで初期化して配列として呼び出している。
import numpy as np
from matplotlib import gridspec
fig = plt.figure(figsize=(14,12))
gs = gridspec.GridSpec(3,4,width_ratios=[2,0.5,2,0.5])
ax = np.empty((3,4),dtype=object)
for r in range(3):
for c in range(4):
ax[r,c]=fig.add_subplot(gs[r,c])
subplotsを使った以下のような呼び出し方もある。ただしこれは簡易的な描き方で、細かく設定するならgridspecの方がいいかもしれない。
fig,ax=plt.subplots(3,2,figsize=(12,12),
gridspec_kw={'wspace': 0.15, 'hspace': 0.3})
cartopy
気象や気候モデルの出力を可視化するのは以前はbasaemapだったけど開発が止まったので、cartopyが現在の標準ツールだと思う。
投影法・基本設定
以下はよく使う基本設定。経度180度を中心に持ってきて、陸は塗りつぶし。coastlinesで海岸線を描いている。
# set figure
fig=plt.figure(figsize=(10,6))
# set projection
proj=ccrs.PlateCarree(central_longitude=180)
# set axis projection
ax=plt.axes(projection=proj)
ax.coastlines()
ax.add_feature(cfeature.LAND,facecolor='lightgray')
gridspecを使うときの軸の設定は以下のようにする。
for j in range(3):
for i in range(4):
ax[j,i]=fig.add_subplot(gs[j,i],projection=proj)
領域限定描写
set_extentで領域を限定して描写できる。投影法については先の軸の設定で終了しているので、以降の描写ではcrs=ccrs.PlateCarree()を記述して対応する。
for j in range(3):
for i in range(4):
ax[j,i].set_extent((90,240,-30,60),crs=ccrs.PlateCarree())
ax[j,i].coastlines()
コンター
以下ではコンターで分布を塗りつぶしている。投影法のためにtransform=ccrs.PlateCarree()を記述する。
levels = np.arange(-1, 1.1, 0.2)
cf = ax.contourf(lon, lat, acc2[6,:,:],
levels=levels,transform=ccrs.PlateCarree(),cmap='RdBu_r')
plt.colorbar(cf, orientation='horizontal',
pad=0.05, ticks=levels, label='ACC')
緯度経度ラベルの表示
コンターの前後で緯度経度のグリッドラインを追加。top, rightのラベルは省略。
gl = ax.gridlines(crs=ccrs.PlateCarree(),draw_labels=True,
linewidth=0.5,color='gray',alpha=0.5,linestyle='--')
gl.top_labels = False
gl.right_labels = False
gridspecを使う場合には以下のようにしていた。crs=ccrs.PlateCarree()を忘れないこと。transformは使えない。ticksの線が出ないので定義したくなるが、使うと緯度経度のラベルが狂ってしまうのでオススメしない。
gl=np.empty((3,4),dtype=object)
for j in range(3):
for i in range(4):
gl[j,i] = ax[j,i].gridlines(crs=ccrs.PlateCarree(),
draw_labels=True,linewidth=0.5,color='gray',
alpha=0.5,linestyle='--')
gl[j,i].top_labels = False
gl[j,i].right_labels = False
if j<=1: gl[j,i].bottom_labels = False
if i>=1: gl[j,i].left_labels = False
緯度経度のラベル間隔が狭すぎるときには以下で間引いて表示する。
import matplotlib.ticker as mticker
gl[j,i].xlocator = mticker.MultipleLocator(60)
gl[j,i].ylocator = mticker.MultipleLocator(20)
ハッチング
msk=var1>var0などで論理型配列を作り、コンター上にハッチングする。1 or NaNの配列を作るとハッチングしやすいかもしれない。
def plotvar(ax,var1,var0,msk):
lon=var1['lon']
lat=var1['lat']
clevs=np.linspace(-0.8,0.8,9)
cf=ax.contourf( lon,lat,var1,clevs,cmap=cmaps.cet_d_bwr,
transform=ccrs.PlateCarree(),
extend='both')
#ax.add_feature(cfeature.LAND,facecolor='lightgray')#,zorder=3)
#ax.contourf(lon,lat,msk.astype(float),levels=[0.5,1.5],colors='none',
# hatches=['..'],zorder=2,transform=ccrs.PlateCarree())
tr=0.4
msk2=np.where(msk,1,np.nan)
ax.contourf(lon,lat,msk2,colors='gray',alpha=tr,transform=ccrs.PlateCarree())
return cf