我想用极投影画个类似下面这样的效果图,首先底图是一个这样的,然后再有需要的地方做标记,比如斜线和渔网状的东西。
但是我怎么尝试都是得到了一个下面这样的图这样肯定有问题
我调整为画轮廓线之后变成下面这样的图,我猜想应该是经纬度-180和180无法接上的问题。
上网搜索也没有什么好的结果,但是我忽然想到可以把要标记的区域分成两部分来做,这样规避掉这个问题。注意我之前写的是-180 0 0 180,但是还是失败了,改为下面这个和理想画出来的差异不大。
mask1 = (lons > -175) & (lons < 5) &(second_image<0.1)
mask2 = (lons > 5) & (lons < 175) & (second_image<0.1)
最后的代码
import numpy as np
import matplotlib.pyplot as plt
import rasterio
from rasterio.plot import show
import cartopy.crs as ccrs
import cartopy.feature as cfeature
from cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTER
import matplotlib.ticker as mticker
import matplotlib.patches as mpatches
from pyproj import Proj, Transformer
import cmaps
import matplotlib.colors as mcolors
# 设置全局字体样式和大小
plt.rcParams['font.family'] = 'Arial'
plt.rcParams['font.size'] = 22
# GeoTIFF文件路径
first_image_path = r'C:\Users\2016_2022_01_04_rela.tif'
second_image_path = r'C:\Users\2016_2022_01_04_pvalue.tif'
# 读取第一张GeoTIFF图像
with rasterio.open(first_image_path) as src:
first_image = src.read(1)
first_image[first_image<-1] = np.nan
# first_image[first_image > 1] = np.nan
transform = src.transform
crs = src.crs
# 读取第二张GeoTIFF图像
with rasterio.open(second_image_path) as src:
second_image = src.read(1)
second_image[np.isnan(first_image)] = np.nan
pvalue_mask = second_image < 0.1
# pvalue_mask[pvalue_mask==0]=np.nan
# 获取经纬度网格
# first_image[second_image > 0.05]=np.nan
height, width = first_image.shape
cols, rows = np.meshgrid(np.arange(width), np.arange(height))
xs, ys = rasterio.transform.xy(transform, rows, cols)
xs = np.array(xs)
ys = np.array(ys)
# 转换为经纬度
proj = Proj(crs)
transformer = Transformer.from_proj(proj, Proj(proj='latlong', datum='WGS84'))
lons, lats = transformer.transform(xs, ys)
# 绘制极地投影地图
fig, ax = plt.subplots(figsize=(10, 10), subplot_kw={'projection': ccrs.NorthPolarStereo(central_longitude=-45.0)},dpi=300)
# 绘制地图
# fig, ax = plt.subplots(figsize=(10, 10), subplot_kw={'projection': ccrs.Stereographic(central_longitude=-45.0, true_scale_latitude=70.0)}, dpi=300)
ax.set_extent([-180, 180, 60, 90], ccrs.PlateCarree())
# 添加海岸线和网格线
ax.add_feature(cfeature.COASTLINE.with_scale('110m'))
gl = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=True, linewidth=1, color='gray', linestyle='--')
gl.top_labels = True
gl.right_labels = True
gl.xformatter = LONGITUDE_FORMATTER
gl.yformatter = LATITUDE_FORMATTER
gl.xlabel_style = {'size': 20, 'color': 'black', 'rotation': 0}
gl.ylabel_style = {'size': 20, 'color': 'black', 'rotation': 0}
gl.xlocator = mticker.FixedLocator(np.linspace(-180, 180, 13))
gl.ylocator = mticker.FixedLocator(np.linspace(60, 90, 4))
# # 设置颜色条参数
# levels = np.arange(-1, 1.2, 0.2) # 设置颜色条的等级
# cmap = plt.get_cmap('jet', len(levels) - 1) # 使用 'jet' 颜色映射并设置颜色数量
# norm = mcolors.BoundaryNorm(boundaries=levels, ncolors=len(levels) - 1) # 创建 BoundaryNorm 对象
# cmap =cmaps.hotcold_18lev
# 获取原始颜色映射
original_cmap = cmaps.hotcold_18lev
# 提取颜色映射中的颜色
n_colors = original_cmap.N
colors = original_cmap(np.linspace(0, 1, n_colors))
# 插入白色到颜色映射中间
white_color = np.array([1, 1, 1, 1]) # 白色
middle_index = n_colors // 2
# 插入白色
new_colors = np.insert(colors, middle_index, white_color, axis=0)
cmap = mcolors.LinearSegmentedColormap.from_list('hotcold_with_white', new_colors, N=n_colors + 1)
# cmaps.BlueDarkRed18
c1 = ax.pcolormesh(lons, lats, first_image, cmap=cmap, transform=ccrs.PlateCarree(), vmin=-1, vmax=1)# 绘制第一个图像数据
# c1 = ax.pcolormesh(lons, lats, first_image, cmap=cmap, norm=norm, transform=ccrs.PlateCarree())
pvalue_lons, pvalue_lats = lons[pvalue_mask], lats[pvalue_mask]
mask1 = (lons > -175) & (lons < 5) &(second_image<0.1)
mask2 = (lons > 5) & (lons < 175) & (second_image<0.1)
# 使用 contourf 创建填充图
contour = ax.contourf(
lons, lats, mask1,
level=[.5,1.5], # 设置级别来仅显示感兴趣的区域
colors='none', # 不用颜色填充
hatches=['','+++'], # 使用斜线填充
alpha=0,
transform=ccrs.PlateCarree()
)
contour = ax.contourf(
lons, lats, mask2,
level=[.5,1.5], # 设置级别来仅显示感兴趣的区域
colors='none', # 不用颜色填充
hatches=['','///'], # 使用斜线填充
alpha=0,
transform=ccrs.PlateCarree()
)
# 添加海岸线和网格线
# position=fig.add_axes([0.2, 0.15, 0.5, 0.045])#图标位置
font = {'family' : 'serif',
'color' : 'darkred',
'weight' : 'normal',
'size' : 16,
}
# 添加颜色条
cbar=fig.colorbar(c1,orientation='horizontal',extend='both')#设置图标,format='%.1f'
# cbar = plt.colorbar(c1, orientation='horizontal', pad=0.05, aspect=50)
cbar.set_label('Pearson correlation')
# 设置刻度
ticks = [-1, -0.5, 0, 0.5, 1]
cbar.set_ticks(ticks)
cbar.set_ticklabels([f'{tick:.1f}' for tick in ticks])
# 显示图像
plt.show()
# fig.savefig(r'C:\Users\relationshipwith_2mt.jpg', dpi=300, bbox_inches='tight')#保存