You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将经纬度坐标对设置为GOES卫星xarray数据集主索引

GOES卫星xarray数据集经纬度坐标保留方案

问题说明

处理自带x/y扫描角坐标的GOES卫星数据时,常规流程为数据转DataFrame后,再转为xarray DataArray开展运算。现有经纬度计算逻辑仅将经纬度作为非索引附加坐标绑定到数据集,这类随两个维度变化的2D成对坐标无法直接设置为数据集索引,导致拆分出DataArray时经纬度信息不会被保留,系统仍默认以原始x/y作为维度坐标。
原有经纬度计算实现如下:

def calc_latlon(ds):
    
    x = ds.x
    y = ds.y
    goes_imager_projection = ds.goes_imager_projection
    
    x,y = np.meshgrid(x,y)
    
    r_eq = goes_imager_projection.attrs["semi_major_axis"]
    r_pol = goes_imager_projection.attrs["semi_minor_axis"]
    l_0 = goes_imager_projection.attrs["longitude_of_projection_origin"] * (np.pi/180)
    h_sat = goes_imager_projection.attrs["perspective_point_height"]
    H = r_eq + h_sat
    
    a = np.sin(x)**2 + (np.cos(x)**2 * (np.cos(y)**2 + (r_eq**2 / r_pol**2) * np.sin(y)**2))
    b = -2 * H * np.cos(x) * np.cos(y)
    c = H**2 - r_eq**2
    
    r_s = (-b - np.sqrt(b**2 - 4*a*c))/(2*a)
    
    s_x = r_s * np.cos(x) * np.cos(y)
    s_y = -r_s * np.sin(x)
    s_z = r_s * np.cos(x) * np.sin(y)
    
    lat = np.arctan((r_eq**2 / r_pol**2) * (s_z / np.sqrt((H-s_x)**2 +s_y**2))) * (180/np.pi)
    lon = (l_0 - np.arctan(s_y / (H-s_x))) * (180/np.pi)
    
    ds = ds.assign_coords({
        "lat":(["y","x"],lat),
        "lon":(["y","x"],lon)
    })
    ds.lat.attrs["units"] = "degrees_north"
    ds.lon.attrs["units"] = "degrees_east"
    return ds

当前数据集元数据显示x/y仍为参考坐标系维度,经纬度仅为附加坐标;拆解为DataArray后系统仍以x/y作为坐标系,未使用已计算的经纬度坐标。此前尝试修改经纬度输出格式、拆分坐标对设置数据集索引、直接通过坐标对设置索引三种思路,均未实现预期效果。

实现方法

xarray的维度索引坐标必须为1D结构,且与对应维度严格一一映射,计算得到的2D经纬度网格本身不符合维度索引的要求,因此直接设置索引的操作无法生效。根据使用场景可选择以下两种可落地的方案:

方案1:保留原始x/y维度,标记经纬度为CF规范地理坐标(推荐,无插值误差)

不需要修改原始维度结构,仅需在绑定经纬度坐标时补全CF公约要求的元数据,即可让xarray及所有支持CF规范的工具(cartopy、rioxarray、NetCDF客户端等)自动识别经纬度为地理参考坐标,拆分DataArray、经纬度切片等操作都不会丢失坐标信息。修改后的计算函数如下:

import numpy as np

def calc_latlon(ds):
    x = ds.x
    y = ds.y
    goes_proj = ds.goes_imager_projection
    x_mesh, y_mesh = np.meshgrid(x, y)

    # 提取GOES投影参数
    r_eq = goes_proj.attrs["semi_major_axis"]
    r_pol = goes_proj.attrs["semi_minor_axis"]
    lon_origin = goes_proj.attrs["longitude_of_projection_origin"] * (np.pi/180)
    h_sat = goes_proj.attrs["perspective_point_height"]
    H = r_eq + h_sat

    # 静止卫星投影几何计算
    a = np.sin(x_mesh)**2 + (np.cos(x_mesh)**2 * (np.cos(y_mesh)**2 + (r_eq**2 / r_pol**2) * np.sin(y_mesh)**2))
    b = -2 * H * np.cos(x_mesh) * np.cos(y_mesh)
    c = H**2 - r_eq**2
    r_s = (-b - np.sqrt(b**2 - 4*a*c))/(2*a)

    s_x = r_s * np.cos(x_mesh) * np.cos(y_mesh)
    s_y = -r_s * np.sin(x_mesh)
    s_z = r_s * np.cos(x_mesh) * np.sin(y_mesh)

    lat = np.arctan((r_eq**2 / r_pol**2) * (s_z / np.sqrt((H-s_x)**2 + s_y**2))) * (180/np.pi)
    lon = (lon_origin - np.arctan(s_y / (H - s_x))) * (180/np.pi)

    # 绑定坐标并补全CF规范元数据
    ds = ds.assign_coords(
        lat=(["y", "x"], lat, {
            "units": "degrees_north",
            "standard_name": "latitude",
            "axis": "Y"
        }),
        lon=(["y", "x"], lon, {
            "units": "degrees_east",
            "standard_name": "longitude",
            "axis": "X"
        })
    )
    return ds

处理完成后可直接通过ds.sel(lat=slice(..., ...), lon=slice(..., ...))按经纬度范围切片,提取的DataArray会自动携带经纬度坐标信息。

方案2:重采样到规则经纬度网格,将经纬度替换为1D维度索引

如果需要将经纬度转为可直接作为索引的1D维度(例如与其他规则经纬度网格数据集做匹配运算),可在计算得到经纬度后,通过插值生成规则网格,再重置维度:

# 先通过方案1的函数得到带经纬度坐标的数据集
ds = calc_latlon(ds)

# 按需求定义目标规则经纬度网格的分辨率和范围
target_lon = np.arange(np.floor(ds.lon.min().values), np.ceil(ds.lon.max().values), 0.02)
target_lat = np.arange(np.floor(ds.lat.min().values), np.ceil(ds.lat.max().values), 0.02)

# 插值到规则经纬度网格
ds_regular = ds.interp(lon=target_lon, lat=target_lat).reset_coords(["x", "y"], drop=True)

重采样后的数据集以lat、lon为1D维度索引,拆分出的DataArray默认使用经纬度作为坐标系。

注意事项

  • 不要强行将2D经纬度网格设置为维度索引,该操作不符合xarray的底层坐标规则,也是此前尝试的三种方案无法生效的核心原因
  • 方案1为GOES等静止卫星数据的通用处理方式,不会引入插值误差,也不会丢失原始投影信息,绝大多数场景优先选择该方案
  • 补全CF元数据后存储为NetCDF文件,所有常规GIS、遥感软件可直接识别数据的地理参考,无需额外配置投影参数

内容的提问来源于stack exchange,提问作者markd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 16:28:03