对地静止投影的纬度/经度计算

时间:2019-09-27 06:18:47

标签: python-xarray satellite-image pyproj

我正在分析GOES-16卫星数据,需要计算每个网格坐标的基础纬度,经度,作为进一步分析的一部分。我目前正在尝试使用pyproj来执行此操作,并且遇到了超出图像预期范围的经度值,该经度值在预期范围内。

下载图像:

import boto3
import xarray as xr
s3 = boto3.client('s3')
s3.download_file('noaa-goes17', 'ABI-L1b-RadC/2019/022/21/OR_ABI-L1b-RadC-M3C02_G17_s20190222102189_e20190222104562_c20190222104588.nc', 
'test.nc')

ds = xr.open_dataset('test.nc')

转换投影:

from pyproj import Proj
p = Proj(proj='geos', h='35786023.0', lon_0='-137.0', sweep='x')

dat = ds.metpy.parse_cf('Rad')
cord_grid = np.meshgrid(dat['x'].values, dat['y'].values)
lons, lats = p(cord_grid[0], cord_grid[1], inverse=True)

此处的最小和最大lon值分别为-179.99和179.9。我只希望此图像包含介于-89.6和175.6之间的数据,如下所示。

当我检查此图像的预期地理范围时,将得到以下信息:

ds['geospatial_lat_lon_extent']


Out[61]:
<xarray.DataArray 'geospatial_lat_lon_extent' ()>
array(9.96921e+36, dtype=float32)
Coordinates:
    t        datetime64[ns] ...
    y_image  float32 ...
    x_image  float32 ...
Attributes:
    long_name:                       geospatial latitude and longitude refere...
    geospatial_westbound_longitude:  175.62358
    geospatial_northbound_latitude:  53.50006
    geospatial_eastbound_longitude:  -89.62357
    geospatial_southbound_latitude:  14.57134
    geospatial_lat_center:           29.967
    geospatial_lon_center:           -137.0
    geospatial_lat_nadir:            0.0
    geospatial_lon_nadir:            -137.0
    geospatial_lat_units:            degrees_north
    geospatial_lon_units:            degrees_east

我对地理空间数据操作还比较陌生。我在这里做什么错了?

2 个答案:

答案 0 :(得分:0)

查看您的数据,看起来它越过了antimeridian(-180/180经度)。 使用rioxarray检查数据。

常规检查可能不会发现以下内容:

import numpy as np
from pyproj import Transformer
import rioxarray

rds = rioxarray.open_rasterio("test.nc", masked=True)
<xarray.Dataset>
Dimensions:      (band: 1, x: 10000, y: 6000)
Coordinates:
  * y            (y) float64 1.583e+06 1.584e+06 ... 4.588e+06 4.589e+06
  * x            (x) float64 -2.505e+06 -2.504e+06 ... 2.504e+06 2.505e+06
  * band         (band) int64 1
    spatial_ref  int64 0
Data variables:
    Rad          (band, y, x) float64 ...
    DQF          (band, y, x) float64 ...
rds.rio.crs
CRS.from_wkt('PROJCS["unnamed",GEOGCS["unknown",DATUM["unnamed",SPHEROID["Spheroid",6378137,298.2572221]],PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]]],PROJECTION["Geostationary_Satellite"],PARAMETER["central_meridian",-137],PARAMETER["satellite_height",35786023],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["Easting",EAST],AXIS["Northing",NORTH],EXTENSION["PROJ4","+proj=geos +lon_0=-137 +h=35786023 +x_0=0 +y_0=0 +ellps=GRS80 +units=m +no_defs +sweep=x"]]')
rds.Rad.rio.transform_bounds("epsg:4326")
(-177.77133129663548,
 14.561801004390198,
 179.99792429593583,
 53.52729472471354)

但是,一旦转换了数据: (旁注,这就是为什么我使用Transformer代替Proj https://pyproj4.github.io/pyproj/stable/gotchas.html#proj-not-a-generic-latitude-longitude-to-projection-converter的原因)

transformer = Transformer.from_crs(rds.rio.crs, "epsg:4326", always_xy=True)
x_coords, y_coords = np.meshgrid(
    rds.coords[rds.rio.x_dim], rds.coords[rds.rio.y_dim]
)
lon, lat = transformer.transform(x_coords, y_coords)

您会看到拐角不在线的同一侧:

(lon[0][0], lat[0][0]), (lon[-1][-1], lat[-1][-1]), (lon[0][-1], lat[0][-1]), (lon[-1][0], lat[-1][0])```
((-161.57648657675344, 14.798043104222199),
 (-89.56850957728933, 53.5204809865526),
 (-112.4235101487757, 14.798043165552787),
 (175.56851955360526, 53.52047990993389))

由于这一点,当您使用最小值和最大值来获取界限时,这会产生误导,因为经度的最小值和最大值都位于经纬度(-180/180)的纬度/经度旁边。

lon.min(), lat.min(), lon.max(), lat.max()
(-179.99994221231273, 14.564185533235145, 179.9999815862486, 53.5204809865526)

答案 1 :(得分:0)

使用我创建的 GOES 包,您可以轻松获得 ABI 像素的经纬度。此 tutorial 中显示了许多示例。我希望你觉得它有用。