使用Cartopy的PlateCarree投影绘制TROPOMI SO2数据时出现伪影问题
解决TROPOMI SO2数据在Cartopy PlateCarree投影下的绘图伪影问题
这种伪影的核心原因是:PlateCarree投影默认采用[-180°, 180°]的经度范围,当数据集中的点横跨-180°和180°(国际日期变更线)时,pcolormesh会错误地将最西端(接近-180°)和最东端(接近180°)的网格点直接连接,形成贯穿整个地图的伪影。而Orthographic投影是球面视角,能自然处理这种跨边界的数据,所以不会出现问题。
下面提供两种直接有效的解决方法:
方法一:转换经度范围至[0°, 360°]
将数据的经度从[-180°, 180°]转换为[0°, 360°],避开-180°/180°的边界,同时对经度排序保证数据连续性:
import xarray as xr import matplotlib.pyplot as plt import cartopy.crs as ccrs # 加载数据部分不变 xr_data = xr.open_dataset(file_name, group='PRODUCT', engine='netcdf4', decode_coords=True) xr_data = xr_data.set_coords(("latitude", "longitude")) xr_data_so2 = xr_data['sulfurdioxide_total_vertical_column'][0] xr_data_so2 = xr_data_so2 * xr_data_so2.multiplication_factor_to_convert_to_molecules_percm2 # 转换经度范围并排序 xr_data_so2['longitude'] = xr.where(xr_data_so2['longitude'] < 0, xr_data_so2['longitude'] + 360, xr_data_so2['longitude']) xr_data_so2 = xr_data_so2.sortby('longitude') # 绘图 plt.figure(figsize=(14,6)) ax = plt.axes(projection=ccrs.PlateCarree()) ax.set_extent([0, 360, -90, 90], crs=ccrs.PlateCarree()) xr_data_so2.plot.pcolormesh(ax=ax, x='longitude', y='latitude', robust=True, shading='none', cmap='jet') ax.coastlines() # 添加海岸线增强可读性 plt.show()
方法二:使用Cartopy的循环点工具
利用Cartopy内置的add_cyclic_point函数,在经度维度末尾添加与起始点一致的数据,填补-180°和180°之间的间隙:
import xarray as xr import matplotlib.pyplot as plt import cartopy.crs as ccrs from cartopy.util import add_cyclic_point # 加载数据部分不变 xr_data = xr.open_dataset(file_name, group='PRODUCT', engine='netcdf4', decode_coords=True) xr_data = xr_data.set_coords(("latitude", "longitude")) xr_data_so2 = xr_data['sulfurdioxide_total_vertical_column'][0] xr_data_so2 = xr_data_so2 * xr_data_so2.multiplication_factor_to_convert_to_molecules_percm2 # 添加循环点,处理边界问题 cyclic_data, cyclic_lon = add_cyclic_point(xr_data_so2.values, coord=xr_data_so2.longitude.values) cyclic_so2 = xr.DataArray(cyclic_data, dims=['latitude', 'longitude'], coords={'latitude': xr_data_so2.latitude, 'longitude': cyclic_lon}) # 绘图 plt.figure(figsize=(14,6)) ax = plt.axes(projection=ccrs.PlateCarree()) cyclic_so2.plot.pcolormesh(ax=ax, x='longitude', y='latitude', robust=True, shading='none', cmap='jet') ax.coastlines() plt.show()
两种方法都能有效消除伪影,你可以根据自己的需求选择:方法一更适合习惯[0°,360°]经度范围的场景,方法二则保留原[-180°,180°]的经度显示。
内容的提问来源于stack exchange,提问作者Karol Przeździecki
相关产品推荐
相关产品推荐

