Background
I have four 2D arrays: lon_centers, lat_centers, lon_bnds, and lat_bnds. bnds
means the boundary of each pixel and centers
stands for the center of pixels.
Data overview
import numpy as np
import matplotlib.pyplot as plt
lon_bnds = np.array([[-77.9645 , -77.56074 , -77.162025, -76.76827 , -76.37937 ],
[-77.88815 , -77.48613 , -77.08915 , -76.69711 , -76.30993 ],
[-77.811676, -77.41139 , -77.01614 , -76.62582 , -76.24034 ],
[-77.73638 , -77.337814, -76.944275, -76.55565 , -76.17186 ],
[-77.66197 , -77.265114, -76.87326 , -76.48632 , -76.1042 ]])
lat_bnds = np.array([[-77.34674 , -77.35804 , -77.36858 , -77.378395, -77.38752 ],
[-77.28847 , -77.299614, -77.31001 , -77.31969 , -77.328674],
[-77.23022 , -77.24122 , -77.25147 , -77.26101 , -77.26986 ],
[-77.17193 , -77.182785, -77.192894, -77.20229 , -77.211006],
[-77.11363 , -77.12434 , -77.13431 , -77.14357 , -77.15215 ]])
lon_centers = np.array([[-77.72404 , -77.323685, -76.92833 , -76.53787 ],
[-77.64892 , -77.2503 , -76.85666 , -76.46791 ],
[-77.57335 , -77.17646 , -76.78454 , -76.3975 ],
[-77.499626, -77.10444 , -76.71421 , -76.32886 ]])
lat_centers = np.array([[-77.32333 , -77.334175, -77.344284, -77.353676],
[-77.264946, -77.27564 , -77.28561 , -77.29487 ],
[-77.20665 , -77.21719 , -77.22702 , -77.23614 ],
[-77.14826 , -77.15867 , -77.16835 , -77.17734 ]])
plt.scatter(lon_bnds, lat_bnds, label='corner')
plt.scatter(lon_centers, lat_centers, marker='x', c='r', label='center')
plt.legend()
Goal
The goal is to calculate the area (m2) of each pixel, which means area
has the same shape as lon_centers
and lat_centers
.
I found this useful question for calculating the area of one geo-polygon. However, it needs inputs in order and loop of the 2D arrays.
Attempt
from pyproj import Geod
geod = Geod(ellps="WGS84")
areas = []
for x in range(lon_bnds.shape[0]-1):
for y in range(lon_bnds.shape[1]-1):
lons = lon_bnds[x:x+2, y:y+2].ravel()
lats = lat_bnds[x:x+2, y:y+2].ravel()
lons[-2], lons[-1] = lons[-1], lons[-2]
lats[-2], lats[-1] = lats[-1], lats[-2]
poly_area, poly_perimeter = geod.polygon_area_perimeter(lons, lats)
areas.append(poly_area)
areas = np.asarray(areas).reshape(lon_centers.shape)
The for loop is too slow if there're more pixels. Is it possible to speed it up?