计算旋转坐标空间中的numpy数组的区域统计量

时间:2019-03-22 20:07:14

标签: python numpy raster affinetransform rasterio

BLUF:

我在使用rasterstats包通过旋转数组计算区域统计信息时遇到了麻烦。我猜问题出在我的仿射矩阵上,但我不确定。下面是仿射变换矩阵和输出:

| 951.79, 0.45, 2999993.57|
| 0.00,-996.15,-1985797.84|
| 0.00, 0.00, 1.00|

enter image description here

背景

我正在为地下水流模型创建文件,需要使用来自波多黎各农业用水管理Web门户的一些.csv数据来计算每个模型网格的区域统计信息。这些数据可在每天的时间步长上获取大量参数(例如ET,tmax,tmin,precip等)。这些文件未进行地理参考,但是可以使用辅助文件来指定每个像元的lon / lat,然后可以使用pyproj进行投影:

import pandas as pd
import numpy as np
import pyproj

url_base = 'http://academic.uprm.edu/hdc/GOES-PRWEB_RESULTS'

# Load some data
f = '/'.join([url_base, 'actual_ET', 'actual_ET20090101.csv'])
array = pd.read_csv(f, header=None).values

# Read longitude values
f = '/'.join([url_base, 'NON_TRANSIENT_PARAMETERS', 'LONGITUDE.csv'])
lon = pd.read_csv(f, header=None).values

# Read latitude values
f = '/'.join([url_base, 'NON_TRANSIENT_PARAMETERS', 'LATITUDE.csv'])
lat = np.flipud(pd.read_csv(f, header=None).values)

# Project to x/y coordinates (North America Albers Equal Area Conic)
aea = pyproj.Proj('+init=ESRI:102008')
x, y = aea(lon, lat)

在我可以计算区域统计数据之前,我需要创建将行/列坐标与投影的x / y坐标相关联的仿射变换。我指定了6个参数以使用仿射库创建Affine对象:

import math
from affine import Affine

length_of_degree_longitude_at_lat_mean = 105754.71  # 18.25 degrees via http://www.csgnetwork.com/degreelenllavcalc.html
length_of_degree_latitude_at_lat_mean = 110683.25   # 18.25 degrees via http://www.csgnetwork.com/degreelenllavcalc.html

# Find the upper left x, y
xul, yul = aea(lon[0][0], lat[0][0])
xll, yll = aea(lon[-1][0], lat[-1][0])
xur, yur = aea(lon[0][-1], lat[0][-1])
xlr, ylr = aea(lon[-1][-1], lat[-1][-1])

# Compute pixel width
a = abs(lon[0][1] - lon[0][0]) * length_of_degree_longitude_at_lat_mean

# Row rotation
adj = abs(xlr - xll)
opp = abs(ylr - yll)
b = math.atan(opp/adj)

# x-coordinate of the upper left corner
c = xul - a / 2

# Compute pixel height
e = -abs(lat[1][0] - lat[0][0]) * length_of_degree_latitude_at_lat_mean

# Column rotation
d = 0

# y-coordinate of the upper left corner
f = yul - e / 2

affine = Affine(a, b, c, d, e, f)

其中:

  • a =像素的宽度
  • b =行旋转(通常为零)
  • c =左上像素左上角的x坐标
  • d =列旋转(通常为零)
  • e =像素的高度(通常为负)
  • f =左上像素左上角的y坐标

(来自https://www.perrygeo.com/python-affine-transforms.html

所得的仿射矩阵看起来很合理,我尝试将行和列的旋转传递为弧度和度,结果几乎没有变化。链接到网格特征:grid_2km.geojson

import rasterstats
import matplotlib.pyplot as plt

grid_f = 'grid_2km.geojson'
gdf = gpd.read_file(grid_f)

zs = rasterstats.zonal_stats(gdf, 
                             array, 
                             affine=affine,
                             stats=['mean'])

df = pd.DataFrame(zs).fillna(value=np.nan)

fig = plt.figure(figsize=(14, 6))

ax = fig.add_subplot(131, aspect='equal')
ax.pcolormesh(x, y, np.zeros_like(array))
ax.pcolormesh(x, y, array)
ax.set_title('Projected Data')

ax = fig.add_subplot(132, aspect='equal')
gdf.plot(ax=ax)
ax.set_title('Projected Shapefile')

ax = fig.add_subplot(133, aspect='equal')
ax.imshow(df['mean'].values.reshape((gdf.row.max(), gdf.col.max())))
ax.set_title('Zonal Statistics Output')

plt.tight_layout()
plt.show()

enter image description here

此外,使用仿射对象转换的x和y值对与使用pyproj从本地lon,lat值派生的x,y值对之间存在差异:

rr = np.array([np.ones(x.shape[1], dtype=np.int) * i for i in range(x.shape[0])])
cc = np.array([np.arange(x.shape[1]) for i in range(x.shape[0])])
x1, y1 = affine * (cc, rr)

fig = plt.figure(figsize=(14, 6))

ax = fig.add_subplot(111, aspect='equal')
ax.scatter(x, y, s=.2)
ax.scatter(x1, y1, s=.2)

plt.show()

enter image description here

0 个答案:

没有答案