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?


Here's something you can consider when you are doing multiple for loops onto arrays.