Python | NCL风格 | EOF | 相关 | 回归

这里在linux系统上使用geocat实现NCL风格的图片绘制

geocat

Linux上安装 geocat

conda update conda
conda create -n geocat -c conda-forge geocat-viz
conda activate geocat
conda update geocat-viz
  • Dataset
- NOAA Optimum Interpolation (OI) SST V2 # 海温月平均数据
- lsmask # 掩膜数据
- 1°x1° (180latx360lon)   # 空间分辨率
- 1981-12-01 ~ 2021-07-01  # 时间覆盖范围
- https://psl.noaa.gov/data/gridded/

导入基础库

import numpy as np
import pandas as pd
import xarray as xr
import os
from datetime import datetime
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import matplotlib.pyplot as plt
import matplotlib.patheffects as PathEffects
from scipy import stats
import geocat.viz.util as gvutil
import cmaps
from geocat.comp import eofunc_eofs, eofunc_pcs
import sys
import inspect

设置数据时间、范围、EOF模态数量

# ----- Parameter setting ------
ystr = 1982
yend = 2020

latS = -30.
latN = 30.
lonW = 120.
lonE = 290

neof = 3

读取SST数据和MASK掩膜数据

# 打印当前目录
print("当前目录:", os.getcwd())
# == netcdf file name and location"
fnc = 'oisst_monthly.nc'
dmask = xr.open_dataset('lsmask.nc')
print(dmask)

ds = xr.open_dataset(fnc)
print(ds)

对于SST进行陆地掩膜 | 计算异常

# === Climatology and Anomalies
sst = ds.sst.where(dmask.mask.isel(time=0) == 1)
clm = sst.sel(time=slice(f'{ystr}-01-01',f'{yend}-12-01')).groupby('time.month').mean(dim='time')
anm = (sst.groupby('time.month') - clm)

plt.figure(dpi=200,figsize=(12,4))
plt.subplot(121)
sst[0].plot()
plt.title('With mask')
plt.subplot(122)
ds.sst[0].plot()
plt.title('Not mask')

Figure 2024-04-04 144410

计算季节平均 | 去趋势

# == seasonal mean
anmS = anm.rolling(time=3, center=True).mean('time')
anmDJF=anmS.sel(time=slice(f'{ystr}-01-01',f'{yend}-12-01',12))
print(anmDJF)


def wgt_areaave(indat, latS, latN, lonW, lonE):
  lat=indat.lat
  lon=indat.lon

  if ( ((lonW < 0) or (lonE < 0 )) and (lon.values.min() > -1) ):
     anm=indat.assign_coords(lon=( (lon + 180) % 360 - 180) )
     lon=( (lon + 180) % 360 - 180)
  else:
     anm=indat

  iplat = lat.where( (lat >= latS ) & (lat <= latN), drop=True)
  iplon = lon.where( (lon >= lonW ) & (lon <= lonE), drop=True)

#  print(iplat)
#  print(iplon)
  wgt = np.cos(np.deg2rad(lat))
  odat=anm.sel(lat=iplat,lon=iplon).weighted(wgt).mean(("lon", "lat"), skipna=True)
  return(odat)

# -- Detorending
def detrend_dim(da, dim, deg=1):
    # detrend along a single dimension
    p = da.polyfit(dim=dim, deg=deg)
    fit = xr.polyval(da[dim], p.polyfit_coefficients)
    return da - fit
    
anmDJF=detrend_dim(anmDJF,'time',1)  

这里的rolling(time=3, center=True).mean('time')可以理解为计算季节平均的过程,返回的是以1981-12-01为中心的(*、1981-12-01、1982-01-01)的平均值,1982-01-01为中心的(1981-12-01、1982-01-01、1982-02-01)的平均值,1982-02-01为中心的(1982-01-01、1982-02-01、1982-03-01)的平均值,…依次类推。

通过时间截取每12个月为一个周期的季节平均,即挑选出:1982-01-01 1983-01-01 ... 2020-01-01为中心的季节平均,作为每年的冬季平均值。

定义一个去趋势函数,函数名为detrend_dim,它的作用是沿着指定的维度对数据进行去趋势化处理。

函数的参数包括:

  • da:输入的数据数组,可以是 xarray.DataArray 类型。
  • dim:指定的维度,沿着这个维度进行去趋势化处理。
  • deg:多项式拟合的阶数,默认为1,即线性拟合。

函数的主要步骤包括:

  • 使用 da.polyfit() 方法进行多项式拟合,拟合得到沿着指定维度的多项式系数。
  • 使用 xr.polyval() 方法根据拟合的多项式系数计算拟合曲线。
  • 将原始数据减去拟合曲线得到去趋势化后的数据。
  • 最终函数返回去趋势化后的数据数组。

rolling()函数通过计算窗口中的数据点的平均值来代表窗口中心点的值。这与中心差分类似,因为我们在某一点附近使用了周围数据点的平均值来估计该点的值。因此,在某种程度上,你可以将滚动窗口均值视为一种离散形式的中心差分。

这里使用官网的一个例子来解释:
https://docs.xarray.dev/en/stable/generated/xarray.DataArray.rolling.html

da = xr.DataArray(
    np.linspace(0, 11, num=12),
    coords=[
        pd.date_range(
            "1999-12-15",
            periods=12,
            freq=pd.DateOffset(months=1),
        )
    ],
    dims="time",
)

da
<xarray.DataArray (time: 12)> Size: 96B
array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10., 11.])
Coordinates:
  * time     (time) datetime64[ns] 96B 1999-12-15 2000-01-15 ... 2000-11-15
  
da.rolling(time=3, center=True).mean()
<xarray.DataArray (time: 12)> Size: 96B
array([nan,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10., nan])
Coordinates:
  * time     (time) datetime64[ns] 96B 1999-12-15 2000-01-15 ... 2000-11-15

在第一个数据点处,窗口中包含了该数据点、下一个数据点和前一个数据点。而在最后一个数据点处,窗口中包含了该数据点、前一个数据点和后一个数据点。由于这些位置处的窗口无法完全包含3个数据点,因此在这些位置处的滚动窗口均值计算结果为NaN。

所以第一个点rolling后的数值为nan,第二个点的数值为(0+1+2)/3=1,依次类推。


计算nino指数 | 与冬季海温异常的相关/回归系数

eof_sstDJF-nino_corr

nino=wgt_areaave(anmDJF,-5,5,-170,-120)
ninoSD=nino/nino.std(dim='time')

# simultaneous
cor0 = xr.corr(ninoSD, anmDJF, dim="time")
reg0 = xr.cov(ninoSD,  anmDJF, dim="time")/ninoSD.var(dim='time',skipna=True).values

绘图 | Nino 指数 | 显著打点


def makefig0(cor, title, grid_space):

  cor = gvutil.xr_add_cyclic_longitudes(cor, 'lon')

  ax = fig.add_subplot(grid_space,
          projection=ccrs.Robinson(central_longitude=180))
  ax.coastlines(linewidth=0.5, alpha=0.6)
  
  gl = ax.gridlines(crs=ccrs.PlateCarree(),
                  draw_labels=True,
                  dms=False,
                  x_inline=False,
                  y_inline=False,
                  linewidth=1,
                  linestyle='dotted',
                  color="black",
                  alpha=0.3)
  gl.top_labels = False
  gl.right_labels = False
  gl.rotate_labels = False

  gvutil.add_major_minor_ticks(ax, labelsize=10)

  gvutil.add_lat_lon_ticklabels(ax)
  
  newcmp = cmaps.BlueYellowRed
  index = [5, 20,  35, 50, 65, 85, 95, 110, 125,  0, 0, 135, 150,  165, 180, 200, 210, 220, 235, 250 ]
  color_list = [newcmp[i].colors for i in index]

  color_list[9]=[ 1., 1., 1.]
  color_list[10]=[ 1., 1., 1.]

  kwargs = dict(
    vmin = -1.0,
    vmax = 1.0,
    levels = 21,
    colors=color_list,
    add_colorbar=False,  # allow for colorbar specification later
    transform=ccrs.PlateCarree(),  # ds projection
  )

  fillplot = cor.plot.contourf(ax=ax,  **kwargs)
  ax.add_feature(cfeature.LAND, facecolor='lightgray', zorder=1)
  ax.add_feature(cfeature.COASTLINE, edgecolor='gray', linewidth=0.5, zorder=1)
 
  df = 35 
  sig=xr.DataArray(data=cor.values*np.sqrt((df-2)/(1-np.square(cor.values))),
      dims=["lat","lon'"],
      coords=[cor.lat, cor.lon])
  t90=stats.t.ppf(1-0.05, df-2)
  t95=stats.t.ppf(1-0.025, df-2)
  sig.plot.contourf(ax=ax,levels = [-1*t95, -1*t90, t90, t95], colors='none', 
      hatches=['..', None, None, None, '..'], extend='both', 
      add_colorbar=False, transform=ccrs.PlateCarree())
  gvutil.set_titles_and_labels(ax,
                             lefttitle=title,
                             lefttitlefontsize=16,
                             righttitle='',
                             righttitlefontsize=16,
                             xlabel="",
                             ylabel="")

  return ax, fillplot




def make_bar_plot0(dataset, grid_space):
    years = list(dataset.time.dt.year)
    values = list(dataset.values)
    colors = ['blue' if val < 0 else 'red' for val in values]

    ax = fig.add_subplot(grid_space)

    ax.bar(years,
           values,
           color=colors,
           width=1.0,
           edgecolor='black',
           linewidth=0.5)

    gvutil.add_major_minor_ticks(ax,
                                 x_minor_per_major=5,
                                 y_minor_per_major=5,
                                 labelsize=10)

    gvutil.set_axes_limits_and_ticks(ax,
                                     xticks=np.linspace(1980, 2020, 5),
                                     xlim=[1979.5, 2020.5])
    gvutil.set_titles_and_labels(ax,
                             lefttitle='Nino3.4 index',
                             lefttitlefontsize=16,
                             righttitle='',
                             righttitlefontsize=16,
                             xlabel="Year",
                             ylabel="Standardized")
    return ax


# Show the plot

fig = plt.figure(figsize=(10, 12),dpi=200)
grid = fig.add_gridspec(ncols=1, nrows=3)
ax1, fill1 = makefig0(cor0,'SST correlation (>95%)', grid[0:2,0])

fig.colorbar(fill1,
                 ax=[ax1],
#                 ticks=np.linspace(-5, 5, 11),
                 drawedges=True,
                 orientation='horizontal',
                 shrink=0.5,
                 pad=0.05,
                 extendfrac='auto',
                 extendrect=True)

ax2 = make_bar_plot0(ninoSD, grid[2,0])

 
fig.suptitle('ENSO (DJF)', fontsize=18, y=0.9)

plt.draw()

plt.savefig(fnFIG+"nino_corr.png")

纬度加权处理

anmDJF = anmDJF.sortby("lat", ascending=True)
clat = anmDJF['lat'].astype(np.float64)
clat = np.sqrt(np.cos(np.deg2rad(clat)))
wanm = anmDJF 
wanm = anmDJF * clat
wanm.attrs = anmDJF.attrs
print(wanm)

截取太平洋中部区域

xw_anm = wanm.sel(lat=slice(latS, latN), lon=slice(lonW, lonE)).transpose('time', 'lat', 'lon')
print(xw_anm)

EOF 分析

eofs = eofunc_eofs(xw_anm.data, neofs=neof, meta=True)
pcs = eofunc_pcs(xw_anm.data, npcs=neof, meta=True)
# 对主成分进行标准化,即除以时间维度上的标准差,以确保主成分的方差为1。
pcs = pcs / pcs.std(dim='time')
pcs['time']=anmDJF['time']
pcs.attrs['varianceFraction'] = eofs.attrs['varianceFraction']
print(pcs)

evec = xr.DataArray(data=eofs, dims=('eof','lat','lon'),
    coords = {'eof': np.arange(0,neof), 'lat': xw_anm['lat'], 'lon': xw_anm['lon']} )
print(evec)

计算主成分与原始数据之间的相关系数(correlation)和回归系数(regression coefficient)

  • 计算主成分与原始数据 anmDJF 之间的相关系数,使用的函数是 xr.corr(),其中参数 dim="time" 指定了计算相关系数时沿着时间维度进行计算。

  • 使用 xr.cov() 函数计算协方差,然后除以第一个主成分的方差来得到回归系数。

如果解释变量(自变量)是一个主成分,而响应变量(因变量)是原始数据,且假设线性关系是准确的,那么回归系数可以通过计算主成分与原始数据的协方差除以主成分的方差来得到。最小二乘法的目标是最小化观测值与回归模型的残差平方和。对于简单线性回归模型,可以证明,使得残差平方和最小化的回归系数可以通过以下公式计算:

假设简单线性回归模型为:

Y = β 0 + β 1 x + ε Y=\beta_0+\beta_1x+\varepsilon Y=β0+β1x+ε
其中, Y Y Y 是响应变量, x x x 是解释变量, β 0 \beta_0 β0 β 1 \beta_1 β1 是回归系数, ε \varepsilon ε 是随机误差。
我们知道,协方差的定义是:

C o v ( x , Y ) = 1 n ∑ i = 1 n ( x i − x ˉ ) ( Y i − Y ˉ ) \mathrm{Cov}(x,Y)=\frac{1}{n}\sum_{i=1}^n(x_i-\bar{x})(Y_i-\bar{Y}) Cov(x,Y)=n1i=1n(xixˉ)(YiYˉ)
其中, x ˉ \bar{x} xˉ Y ˉ \bar{Y} Yˉ 分别是 x x x Y Y Y 的样本均值。现在,我们对 Y Y Y 给定 x x x 求期望:

E ( Y ∣ x ) = E ( β 0 + β 1 x + ε ∣ x ) = β 0 + β 1 x + E ( ε ∣ x ) E(Y|x)=E(\beta_0+\beta_1x+\varepsilon|x)=\beta_0+\beta_1x+E(\varepsilon|x) E(Yx)=E(β0+β1x+εx)=β0+β1x+E(εx)
因为 ε \varepsilon ε 是一个随机误差,所以在给定 x x x 的情况下, ε \varepsilon ε的期望为零。因此,上式可以简化为

$$

E(Y|x)=\beta_{0}+\beta_{1}x

$$
现在,我们来计算

C o v ( x , E ( Y ∣ x ) ) = 1 n ∑ i = 1 n ( x i − x ˉ ) ( E ( Y i ∣ x ) − E ( Y ˉ ∣ x ) ) Cov(x,E(Y|x))=\frac1n\sum_{i=1}^n(x_i-\bar{x})(E(Y_i|x)-E(\bar{Y}|x)) Cov(x,E(Yx))=n1i=1n(xixˉ)(E(Yix)E(Yˉx))

因为

E ( Y i ∣ x ) = β 0 + β 1 x i , E(Y_i|x)=\beta_0+\beta_1x_i, E(Yix)=β0+β1xi,

而且
E ( Y ˉ ∣ x ) = β 0 + β 1 x ˉ , E(\bar{Y}|x)=\beta_0+\beta_1\bar{x}, E(Yˉx)=β0+β1xˉ,
所以上式可以进一步简化为:
C o v ( x , E ( Y ∣ x ) ) = 1 n ∑ i = 1 n ( x i − x ˉ ) ( β 0 + β 1 x i − ( β 0 + β 1 x ˉ ) ) = 1 n ∑ i = 1 n ( x i − x ˉ ) ( β 1 x i − β 1 x ˉ ) = β 1 1 n ∑ i = 1 n ( x i − x ˉ ) 2 = β 1 V a r ( x ) \begin{aligned} &Cov(x,E(Y|x))=\frac1n\sum_{i=1}^n(x_i-\bar{x})(\beta_0+\beta_1x_i-(\beta_0+\beta_1\bar{x})) \\ &=\frac1n\sum_{i=1}^n(x_i-\bar{x})(\beta_1x_i-\beta_1\bar{x}) \\ &=\beta_1\frac1n\sum_{i=1}^n(x_i-\bar{x})^2 \\ &=\beta_1\mathrm{Var}(x) \end{aligned} Cov(x,E(Yx))=n1i=1n(xixˉ)(β0+β1xi(β0+β1xˉ))=n1i=1n(xixˉ)(β1xiβ1xˉ)=β1n1i=1n(xixˉ)2=β1Var(x)

因此,我们得到了公式 C o v ( x , E ( Y ∣ x ) ) = β 1 Cov( x, E( Y|x) ) = \beta_1 Cov(x,E(Yx))=β1Var$( x) $

cor1 = xr.corr(pcs[0,:], anmDJF, dim="time")
cor2 = xr.corr(pcs[1,:], anmDJF, dim="time")
cor3 = xr.corr(pcs[2,:], anmDJF, dim="time")
reg1 = xr.cov(pcs[0,:], anmDJF, dim="time")/pcs[0,:].var(dim='time',skipna=True).values
reg2 = xr.cov(pcs[1,:], anmDJF, dim="time")/pcs[1,:].var(dim='time',skipna=True).values
reg3 = xr.cov(pcs[2,:], anmDJF, dim="time")/pcs[2,:].var(dim='time',skipna=True).values

定义绘图函数 - 空间pattern

def makefig(dat, ieof, grid_space):
  # 通过添加子图 ax,使用 ccrs.PlateCarree 投影来绘制地图,并设置中心经度为 180 度。
  # 这样做是为了修正在 0 和 360 度经度附近未显示数据的问题。
  ax = fig.add_subplot(grid_space,
          projection=ccrs.PlateCarree(central_longitude=180))
  # 绘制海岸线
  ax.coastlines(linewidth=0.5, alpha=0.6)
  # 创建网格线,并进行相应的设置,包括绘制标签、设置线宽和样式、设置颜色和透明度等
  gl = ax.gridlines(crs=ccrs.PlateCarree(),
                  draw_labels=True,
                  dms=False,
                  x_inline=False,
                  y_inline=False,
                  linewidth=1,
                  linestyle='dotted',
                  color="black",
                  alpha=0.3)
  gl.top_labels = False
  gl.right_labels = False
  gl.rotate_labels = False
  gl.xlocator=ctk.LongitudeLocator(20)
  gl.ylocator=ctk.LatitudeLocator(5)
  # 添加主要和次要刻度线。
  gvutil.add_major_minor_ticks(ax, labelsize=10)
  
  # 添加纬度和经度的刻度标签。
  gvutil.add_lat_lon_ticklabels(ax)
  
  # 设置了填充图的颜色
  newcmp = cmaps.BlueYellowRed
  index = [5, 20,  35, 50, 65, 85, 95, 110, 125,  0, 0, 135, 150,  165, 180, 200, 210, 220, 235, 250 ]
  color_list = [newcmp[i].colors for i in index]
  #-- Change to white
  color_list[9]=[ 1., 1., 1.]
  color_list[10]=[ 1., 1., 1.]
  
  # 绘制填充图所需的参数,如最小值、最大值、颜色等
  kwargs = dict(
    vmin = -0.06,
    vmax = 0.06,
    levels = 21,
    colors=color_list,
    add_colorbar=False,  # allow for colorbar specification later
    transform=ccrs.PlateCarree(),  # ds projection
  )
  
  # 填充图,并将其保存到变量 fillplot 中
  fillplot = dat[ieof,:,:].plot.contourf(ax=ax,  **kwargs)

  # 添加陆地和海岸线等地图特征。
  ax.add_feature(cfeature.LAND, facecolor='lightgray', zorder=1)
  ax.add_feature(cfeature.COASTLINE, edgecolor='gray', linewidth=0.5, zorder=1)
  
  # 图形的标题和标签。
  gvutil.set_titles_and_labels(ax,
                             lefttitle=f'EOF{ieof+1} pattern',
                             lefttitlefontsize=12,
                             righttitle='',
                             righttitlefontsize=12,
                             maintitle='',
                             xlabel="",
                             ylabel="")

  return ax, fillplot

定义柱状图的绘图函数

该函数接受三个参数:

  • dataset:包含数据的 xarray 数据集。
  • ieof:表示要绘制的主成分(PC)的索引。
  • grid_space:指定子图在网格中的位置。
def make_bar_plot(dataset, ieof, grid_space):

  # 获取数据集中时间坐标的年份、指定主成分的数据,并将其转换为列表 
    years = list(dataset.time.dt.year)
    values = list(dataset[ieof,:].values)
  # 根据主成分的值,生成与其相对应的颜色列表 colors,如果值小于 0,则对应颜色为蓝色,否则为红色。
    colors = ['blue' if val < 0 else 'red' for val in values]

    ax = fig.add_subplot(grid_space)

    ax.bar(years,
           values,
           color=colors,
           width=1.0,
           edgecolor='black',
           linewidth=0.5)

    # 添加主要和次要刻度线,并设置刻度线的密度和标签大小
    gvutil.add_major_minor_ticks(ax,
                                 x_minor_per_major=5,
                                 y_minor_per_major=5,
                                 labelsize=10)

    # 设置坐标轴的范围和刻度值。
    gvutil.set_axes_limits_and_ticks(ax,
                                     xticks=np.linspace(1980, 2020, 5),
                                     xlim=[1979.5, 2020.5],
                                     ylim=[-3.0, 3.5])

    pct = dataset.attrs['varianceFraction'].values[ieof] * 100
    print(pct)
    # 获取主成分的方差百分比,并将其转换为字符串格式
    # 设置图形的标题和标签,包括左侧标题、右侧标题、横坐标标签和纵坐标标签。
    gvutil.set_titles_and_labels(ax,
                             lefttitle=f'PC{ieof+1} (normalized)',
                             lefttitlefontsize=12,
                             righttitle=f'{pct:.1f}%',
                             righttitlefontsize=12,
                             xlabel="Year",
                             ylabel="",
                             labelfontsize=10 )
    return ax


绘图 | 保存图片


fig = plt.figure(figsize=(14, 6),dpi=200)
grid = fig.add_gridspec(ncols=3, nrows=3, hspace=0.4)

ax1, fill1 = makefig(evec,0, grid[0:2,0])
ax2, fill2 = makefig(evec,1, grid[0:2,1])
ax3, fill3 = makefig(evec,2, grid[0:2,2])

fig.colorbar(fill2,
                 ax=[ax1,ax2,ax3],
                 ticks=np.linspace(-0.06, 0.06, 5),
                 drawedges=True,
                 label='Eigenvector',
                 orientation='horizontal',
                 shrink=0.3,
                 pad=0.08,
                 extendfrac='auto',
                 extendrect=True)

ax1 = make_bar_plot(pcs,0,grid[2,0])
ax2 = make_bar_plot(pcs,1,grid[2,1])
ax3 = make_bar_plot(pcs,2,grid[2,2])

 
fig.suptitle('EOF for SST (DJF)', fontsize=16, y=0.9)

plt.draw()
plt.savefig(fnFIG+".png")

展示绘图结果

eof_sstDJF


未去线性趋势结果

  • 可以对比发现,未去掉线性趋势,对于模态的影响在第三模态,其空间patter以及PC的结果存在较大差异;而前两个模态影响较小。但是这个仅仅是对于该区域来说,对于其他区域的影响仍需要进一步探究。

eof_sstDJF-without-detrend

未加权处理结果

  • 对于此区域来看,加权的结果对于分析影响较小。
    eof_sstDJF-without-weight

绘制全球范围的EOF分析

eof_sstDJF-v3-glbaol

未使用异常数据 | 全球

eof_sstDJF-without_ana

未使用异常数据 | 中太平洋

eof_sstDJF-without_ana_loc

  • 对于是否使用异常SST来看,对于主导模态结果影响较小;但是个人感觉来说更取决于你所关注的研究方向。

绘制相关系数空间分布

eof_sstDJF-corr


def makefig2(dat, ieof, grid_space):

  ax = fig.add_subplot(grid_space,
          projection=ccrs.PlateCarree(central_longitude=180))
  ax.coastlines(linewidth=0.5, alpha=0.6)
  
  gl = ax.gridlines(crs=ccrs.PlateCarree(),
                  draw_labels=True,
                  dms=False,
                  x_inline=False,
                  y_inline=False,
                  linewidth=1,
                  linestyle='dotted',
                  color="black",
                  alpha=0.3)
  gl.top_labels = False
  gl.right_labels = False
  gl.rotate_labels = False
  gvutil.add_major_minor_ticks(ax, labelsize=10)
  gvutil.add_lat_lon_ticklabels(ax)
  newcmp = cmaps.BlueYellowRed
  index = [5, 20,  35, 50, 65, 85, 95, 110, 125,  0, 0, 135, 150,  165, 180, 200, 210, 220, 235, 250 ]
  color_list = [newcmp[i].colors for i in index]
  #-- Change to white
  color_list[9]=[ 1., 1., 1.]
  color_list[10]=[ 1., 1., 1.]
  kwargs = dict(
    vmin = -1.0,
    vmax = 1.0,
    levels = 21,
    colors=color_list,
    add_colorbar=False,  # allow for colorbar specification later
    transform=ccrs.PlateCarree(),  # ds projection
  )

  fillplot = dat[:,:].plot.contourf(ax=ax,  **kwargs)

  ax.add_feature(cfeature.LAND, facecolor='lightgray', zorder=1)
  ax.add_feature(cfeature.COASTLINE, edgecolor='gray', linewidth=0.5, zorder=1)

  gvutil.set_titles_and_labels(ax,
                             lefttitle=f'EOF{ieof+1} pattern',
                             lefttitlefontsize=12,
                             righttitle='',
                             righttitlefontsize=12,
                             maintitle='',
                             xlabel="",
                             ylabel="")

  return ax, fillplot


# Show the plot
fig = plt.figure(figsize=(14, 8),dpi=200)
grid = fig.add_gridspec(ncols=3, nrows=3, hspace=0.4)
ax1, fill1 = makefig2(cor1,0, grid[0:2,0])
ax2, fill2 = makefig2(cor2,1, grid[0:2,1])
ax3, fill3 = makefig2(cor3,2, grid[0:2,2])
fig.colorbar(fill2,
                 ax=[ax1,ax2,ax3],
                 ticks=np.linspace(-1.0, 1.0, 5),
                 drawedges=True,
                 label='Correlation',
                 orientation='horizontal',
                 shrink=0.3,
                 pad=0.08,
                 extendfrac='auto',
                 extendrect=True)
fig.suptitle('EOF for SST (DJF)', fontsize=16, y=0.85)
plt.draw()
plt.savefig(fnFIG+"corr.png",bbox_inches='tight')

https://geocat-viz.readthedocs.io/en/latest/installation.html

https://geocat-viz.readthedocs.io/en/latest/examples.html

http://unidata.github.io/netcdf4-python/

https://geocat-examples.readthedocs.io/en/latest/gallery/index.html

https://climate.usu.edu/people/yoshi/pyclm101/index.html

https://docs.xarray.dev/en/stable/gallery.html

本文由mdnice多平台发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/525186.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

dubbo知识点

为什么要用 Dubbo&#xff1f; 随着服务化的进一步发展&#xff0c;服务越来越多&#xff0c;服务之间的调用和依赖关系也越来越复杂&#xff0c;诞生了面向服务的架构体系(SOA)&#xff0c;也因此衍生出了一系列相应的技术&#xff0c;如对服务提供、服务调用、连接处理、通信…

React - 你使用过高阶组件吗

难度级别:初级及以上 提问概率:55% 高阶组件并不能单纯的说它是一个函数,或是一个组件,在React中,函数也可以做为一种组件。而高阶组件就是将一个组件做为入参,被传入一个函数或者组件中,经过一定的加工处理,最终再返回一个组件的组合…

海外仓的痛点和需求都有哪些?位像素海外仓系统能解决什么问题?

在全球化贸易的时代&#xff0c;越来越多人将目光聚焦在海外仓上&#xff0c;下场想要分一杯羹。然而&#xff0c;海外仓管理过程中也存在着许多痛点和挑战。为此&#xff0c;海外仓都会使用海外仓系统来协助管理海外仓。来探讨一下海外仓的痛点、需求以及海外仓系统能够解决的…

TiDB 慢查询日志分析

导读 TiDB 中的慢查询日志是一项 关键的性能监控工具&#xff0c;其主要作用在于协助数据库管理员追踪执行时间较长的 SQL 查询语句。 通过记录那些超过设定阈值的查询&#xff0c;慢查询日志为性能优化提供了关键的线索&#xff0c;有助于发现潜在的性能瓶颈&#xff0c;优化…

XML HTTP传输 小结

what’s XML XML 指可扩展标记语言&#xff08;eXtensible Markup Language&#xff09;。 XML 被设计用来传输和存储数据&#xff0c;不用于表现和展示数据&#xff0c;HTML 则用来表现数据。 XML 是独立于软件和硬件的信息传输工具。 应该掌握的基础知识 HTMLJavaScript…

跨越网络边界:借助C++编写的下载器程序,轻松获取Amazon商品信息

背景介绍 在数字化时代&#xff0c;数据是新的石油。企业和开发者都在寻找高效的方法来收集和分析网络上的信息。亚马逊&#xff0c;作为全球最大的电子商务平台之一&#xff0c;拥有丰富的商品信息&#xff0c;这对于市场分析和竞争情报来说是一个宝贵的资源。 问题陈述 然…

相机标定——四个坐标系介绍

世界坐标系(Xw,Yw,Zw) 世界坐标系是一个用于描述和定位三维空间中物体位置的坐标系&#xff0c;通常反映真实世界下物体的位置和方向。它是一个惯性坐标系&#xff0c;被用作整个场景或系统的参考框架。在很多情况下&#xff0c;世界坐标系被认为是固定不变的&#xff0c;即它…

Windows系统配置Docker的国内镜像

1.打开docker的设置&#xff0c;点击Docker Engine 2.添加国内的镜像源&#xff0c;将下面的内容加进去 "registry-mirrors": ["https://docker.mirrors.ustc.edu.cn","https://registry.docker-cn.com","http://hub-mirror.c.163.com&quo…

电动汽车电池管理系统(BMS)

1 动力电池 目前几乎所有电动汽车都使用锂离子电池作为动力电池&#xff0c;根据极性材料的选择不同&#xff0c;动力电池可分为3种&#xff1a;镍钴锰三元电池NMC&#xff0c;镍钴铝三元电池NCA和磷酸铁锂电池LFP 1.1 NMC 镍钴锰三元电池&#xff0c;简称 NCM&#xff0c;是取…

基于wsl的Ubuntu20.04上安装桌面环境

在子系统Ubuntu20.04上安装桌面环境 1. 更换软件源 由于Ubuntu默认的软件源在国外&#xff0c;有时候后可能会造成下载软件卡顿&#xff0c;这里我们更换为国内的阿里云源&#xff0c;其他国内源亦可。 双击打开Ubuntu20.04 LTS图标&#xff0c;在命令行中输入 # 备份原来的软…

LeetCode-74. 搜索二维矩阵【数组 二分查找 矩阵】

LeetCode-74. 搜索二维矩阵【数组 二分查找 矩阵】 题目描述&#xff1a;解题思路一&#xff1a;先二分查找行&#xff0c;再二分查找列。解题思路二&#xff1a;暴力遍历&#xff0c;也能过。解题思路三&#xff1a;用python的in。 题目描述&#xff1a; 给你一个满足下述两条…

HarmonyOS NEXT应用开发之Tab组件实现增删Tab标签

介绍 本示例介绍使用了Tab组件实现自定义增删Tab页签的功能。该场景多用于浏览器等场景。 效果图预览 使用说明&#xff1a; 点击新增按钮&#xff0c;新增Tab页面。点击删除按钮&#xff0c;删除Tab页面。 实现思路 设置Tab组件的barHeight为0&#xff0c;隐藏组件自带的…

实践笔记-03 docker buildx 使用

docker buildx 使用 1.启用docker buildx2.启用 binfmt_misc3.从默认的构建器切换到多平台构建器3.1创建buildkitd.toml文件&#xff08;私有仓库是http没有证书的情况下&#xff0c;需要配置&#xff09;3.2创建构建器并使用新创建的构建器 4.构建多架构镜像并推送至harbor仓库…

5分钟学会Rust语言如何操作JSON

JSON(JavaScript Object Notation)在Web开发中被广泛应用于数据交换。作为一种数据格式&#xff0c;JSON相较于XML来说&#xff0c;更易于阅读和写入&#xff0c;且数据解析性能强。Rust作为一门系统级编程语言&#xff0c;其与JSON的交互操作密切。本文将详细地描述在Rust中如…

vscode 安装vim插件配置ctrl + c/v功能

搜索Vim插件 插件介绍部分有提示操作 首先安装该插件&#xff0c;然后按照下述步骤设置ctrl相关的快捷键&#xff0c;以便于脱离im快捷键而愉快的敲代码。 1.在“设置”搜索框内搜索vim.handleKeys&#xff0c;选择 Edit in settings.json 2. 设置ctrl-c,ctrl-v等快捷键置为fa…

VSCODE目录树缩进调整

VSCode默认的缩进太小了&#xff0c;简直看不出来&#xff0c;很容易弄混目录。在设置里修改就行了。 修改后效果&#xff1a;

面试算法-151-矩阵置零

题目 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,1,1],[1,0,1],[1,1,1]] 输出&#xff1a;[[1,0,1],[0,0,0],[1,0,1]] 解 class Solutio…

医疗设备安全简史

作者&#xff1a;AJ Burns、M. Eric Johnson和Peter Honeyman 随着软件驱动设备的植入&#xff0c;给人体带来了独特的隐私和安全威胁。 介绍&#xff1a; 现代医疗设备的功能继续从根本上改变急性病症的治疗以及慢性长期疾病的管理。随着这些技术的发展&#xff0c;这些设备…

python语言程序设计完结

概述&#xff1a; 程序设计是计算机可编程的体现 程序设计&#xff0c;亦称编程&#xff0c;是深度应用计算机的主要手段 程序设计已经成为当今社会需求量最大的职业技能之一 程序设计语言是一种用于交互&#xff08;交流&#xff09;的人造语言 程序设计语言&#xff0c;亦称…

顺序表——功能实现

✨✨欢迎&#x1f44d;&#x1f44d;点赞☕️☕️收藏✍✍评论 个人主页&#xff1a;秋邱博客 所属栏目&#xff1a;C语言 &#xff08;感谢您的光临&#xff0c;您的光临蓬荜生辉&#xff09; 目录 1.0 前言 2.0 线性表 2.1 顺序表 2.2 顺序表的分类 2.3 顺序表功能的实现…