2025, Nov 01 01:17
Перевыборка NetCDF: перенос высот на сетку землепользования по lon/lat
Пошагово покажем, как в Python перенести топографию из NetCDF на сетку землепользования: перевыборка по lon/lat в pyresample методом ближайшего соседа.
Когда два набора данных NetCDF4 охватывают одну и ту же область, но лежат на разных сетках, прямое копирование значений из одного файла в другой не совпадёт по местоположению. Типичная ситуация: файл землепользования со своей сеткой lon/lat и файл топографии с другой сеткой lon/lat. Задача — перенести значения высоты на сетку землепользования методом ближайшего соседа по географическим координатам. Ниже — понятный путь, как сделать это на Python, не искажая модель данных.
Что идёт не так при прямой записи
Чтение массива высот из файла топографии и попытка присвоить его переменной в файле землепользования обычно завершается ошибкой или даёт неверное пространственное выравнивание. Формы массивов и координаты отличаются, поэтому такое присваивание бессмысленно, даже если файлы покрывают примерно одну и ту же область.
from netCDF4 import Dataset
import numpy as np
lu_ds = Dataset('LUindexHCLIM3.nc', mode='a')
z_ds = Dataset('topography.nc', mode='r')
lon_target = np.array(lu_ds.variables['lon'])
lat_target = np.array(lu_ds.variables['lat'])
z_src = np.array(z_ds.variables['HGT_M'])
# Плохая идея: сетки отличаются, поэтому такое присваивание некорректно
z_on_lu = lu_ds.createVariable('HGT_M', 'f4', ('y', 'x'))
z_on_lu[:] = z_src # mismatched grid/shape
lu_ds.close()
z_ds.close()
Значения высоты принадлежат другой сетке. Без сопоставления координат исходной и целевой сеток данные окажутся не на своих местах.
Почему так происходит
Массивы долготы и широты задают реальное географическое положение каждой ячейки. Переменные, ссылающиеся на разные массивы lon/lat, находятся на разных сетках, даже если их рамки перекрываются. Индексное присваивание не учитывает географическую близость. Нужна перевыборка (resampling): для каждой целевой ячейки найти ближайшую исходную координату и взять её значение.
Практическое решение: перевыборка по ближайшим lon/lat с помощью pyresample
Короткий способ перенести значения с одной регулярной или нерегулярной сетки на другую — воспользоваться pyresample. Идея проста: задать исходную область (swath) по lon/lat из топографии, задать целевую — по lon/lat из землепользования, затем выполнить перевыборку методом ближайшего соседа, получив массив формы целевой сетки.
from netCDF4 import Dataset
import numpy as np
from pyresample import geometry, kd_tree
lu_nc = Dataset('LUindexHCLIM3.nc', mode='a')
ztop_nc = Dataset('topography.nc', mode='r')
# Получаем поля из файла землепользования
landcover_main = np.array(lu_nc.variables['Main_Nature_Cover'])
lon_dest = np.array(lu_nc.variables['lon'])
lat_dest = np.array(lu_nc.variables['lat'])
# Получаем поля из файла топографии
z_vals = np.array(ztop_nc.variables['HGT_M'])
lon_src = np.array(ztop_nc.variables['lon'])
lat_src = np.array(ztop_nc.variables['lat'])
# Формируем описания источника и приёмника для pyresample
src_swath = geometry.SwathDefinition(lons=lon_src, lats=lat_src)
dst_swath = geometry.SwathDefinition(lons=lon_dest, lats=lat_dest)
# Перевыборка методом ближайшего соседа на сетку землепользования
z_on_landuse = kd_tree.resample_nearest(
src_swath,
z_vals,
dst_swath,
radius_of_influence=500000,
fill_value=None
)
# Для удобства превращаем маску в массив с NaN
z_on_landuse = z_on_landuse.filled(np.nan)
# Сохраняем перевыборенные высоты в файл землепользования
z_var = lu_nc.createVariable('HGT_M', 'f4', ('y', 'x'))
z_var[:] = z_on_landuse
lu_nc.close()
ztop_nc.close()
Так каждой ячейке целевой сетки присваивается высота ближайшей исходной координаты в заданном радиусе. При необходимости можно поэкспериментировать с другими схемами интерполяции.
Почему важно сделать это правильно
Работа напрямую с lon/lat избавляет от хрупких предположений о формах массивов. Перевыборка гарантирует, что итоговое поле ляжет точно на сетку землепользования, поэтому все последующие вычисления используют согласованные границы и положения ячеек. Это особенно важно при сочетании наборов данных, созданных разными моделями или конвейерами предобработки.
Выводы
Если две переменные NetCDF4 находятся на разных сетках, рассматривайте их как отдельные пространственные слои и сводите через перевыборку. Метод ближайшего соседа в pyresample — прямой способ перенести топографию на сетку землепользования по реальным координатам. Убедитесь, что оба набора данных охватывают одну область, выполните перевыборку по lon/lat и затем запишите результат в целевой файл. Если качество результата требует настройки, попробуйте другие варианты интерполяции в том же процессе.
Статья основана на вопросе на StackOverflow от Elsri и ответе PhoenixFire1081.