Формат NetCDF: климат + океаны + gridded geo — экспорт OSM-аналитики в .nc
NetCDF (Network Common Data Form) — это self-describing бинарный формат для многомерных научных массивов, созданный в 1989 году в Unidata Program Center (UCAR, Boulder, Colorado). Изначальная цель — machine-independent обмен atmospheric и oceanographic данными между Cray, VAX, Sun и микрокомпьютерами эпохи: один файл везде читается одинаково, без endianness-сюрпризов. За 36 лет NetCDF превратился в де-факто стандарт climate science (CMIP6, ERA5, NCEP reanalysis), satellite remote sensing (MODIS, MERRA-2, Sentinel atmospheric products) и gridded океанографии (ROMS, HYCOM). На osm2cdr.ru netcdf_exporter.py берёт OSM-аналитику (POI density, building density, road density per cell) и упаковывает её в .nc4 файл с CF-Conventions атрибутами — lat/lon/time оси, units, standard_name. Получается готовый к импорту в xarray / CDO / Panoply gridded cube для urban research.

История: от Unidata 1989 до NetCDF-4 на HDF5
История NetCDF начинается в 1988 году в Unidata Program Center — подразделении UCAR (University Corporation for Atmospheric Research) в Боулдере, Колорадо. Glenn Davis, Russ Rew и Steve Emmerson работали над проблемой: атмосферные модели генерировали output на Cray supercomputer (big-endian), а анализ делался на Sun workstation (little-endian) и VAX (mixed). Каждая лаборатория писала свой парсер для своего формата, обмен данными между университетами был мучительным.
В 1989 году вышла первая публичная версия NetCDF-1 — заимствование архитектуры из NASA CDF (Common Data Format), но с упором на machine-independent representation: XDR (eXternal Data Representation) для всех числовых типов, self-describing метаданные внутри файла (dimensions, variables, attributes), C-библиотека open-source под либеральной лицензией. К 1997 году вышел NetCDF-3 (Classic format) — стабильная версия, которая используется до сих пор: limit 2 ГБ на файл (32-bit offsets), один root-level namespace, простая структура без groups. Чуть позже добавился 64bit-Offset variant для файлов > 2 ГБ.
В 2006 году Unidata совместно с HDF Group начали работу над NetCDF-4 — переработкой backend'а на HDF5. Релиз состоялся в 2008-м. NetCDF-4 файл — это HDF5 файл с дополнительной convention: специальные атрибуты _NCProperties, _Netcdf4Dimid, ограничение на использование некоторых HDF5 features. Это дало unlimited file size, groups (иерархическая структура внутри файла), compound types (record-like структуры), variable-length types (vlen, ragged arrays), chunking и compression (gzip/szip/zstd), parallel I/O через MPI.
Параллельно с эволюцией формата развивалась convention над ним: CF-Conventions (Climate and Forecast Metadata Convention) — стандарт для атрибутов в климатических/океанографических/atmospheric NetCDF файлах. Первая версия CF-1.0 вышла в 2003 году, текущая CF-1.11 (2024) — это десятки страниц правил: какие атрибуты обязательны (units, standard_name, long_name), как описывать axes (axis="T" для time, axis="X" для longitude), как указывать CRS (grid_mapping_name), как декларировать time как "days since 1970-01-01". CMIP6, ERA5, все NASA atmospheric products, ECMWF reanalysis — все строго CF-compliant. Это то, что делает NetCDF не просто форматом, а целой экосистемой interoperability.
Внутри файла: dimensions + variables + attributes + CF
NetCDF data model — три фундаментальных абстракции:
Dimensions. Именованные оси с размером. Типичный climate cube — time × level × lat × lon. Размер каждой dimension фиксирован при создании (исключение — UNLIMITED dimension, обычно time, для append'а новых timesteps). Например: time=365, level=37, lat=720, lon=1440 для дневного ERA5 на 0.25°.
Variables. Многомерные массивы поверх dimensions. У каждой variable — name (temperature, pressure), dtype (float32, int16, double), список dimensions в порядке (temperature(time, level, lat, lon)), и атрибуты. Variables бывают data variables (собственно данные) и coordinate variables (значения по оси — например lat имеет dimension lat и содержит [-89.875, -89.625, ..., 89.875]).
Attributes. Key-value метаданные, прикреплённые либо к variable, либо global (file-level). Это где живёт CF-conventions:
global attributes:
Conventions = "CF-1.11"
title = "OSM POI density grid, Berlin, 2026"
institution = "osm2cdr.ru"
source = "OpenStreetMap via osm2pgsql + PostGIS aggregation"
history = "2026-05-13: created from OSM extract"
variables:
float lat(lat)
units = "degrees_north"
standard_name = "latitude"
axis = "Y"
float lon(lon)
units = "degrees_east"
standard_name = "longitude"
axis = "X"
int time(time)
units = "days since 2020-01-01"
standard_name = "time"
axis = "T"
calendar = "gregorian"
float poi_density(time, lat, lon)
units = "count km-2"
long_name = "OpenStreetMap POI density per square kilometer"
_FillValue = -9999.0
grid_mapping = "crs"
char crs
grid_mapping_name = "latitude_longitude"
longitude_of_prime_meridian = 0.0
semi_major_axis = 6378137.0
inverse_flattening = 298.257223563
Этого набора достаточно, чтобы любой CF-aware tool (xarray, CDO, NCO, Panoply, IDV, QGIS) понял, что poi_density — это [time × lat × lon] grid в WGS84, units = count per km², time decoded в datetime objects. Дальше — slicing, plotting, regridding, climate operators работают «из коробки».

NetCDF-3 vs NetCDF-4: classic binary vs HDF5
Главное практическое деление — версия формата. Они несовместимы на бинарном уровне, хотя API похожи.
NetCDF-3 (Classic / 64bit-Offset). Original binary format, разработанный с нуля Unidata. Простая структура: header в начале файла (XDR-encoded dimensions, variables, attributes), затем data в последовательных блоках. Преимущества — максимальная совместимость (читается чем угодно, включая Fortran 77 legacy tools, MATLAB R2008, древние IDL), малый header overhead, простой parser. Недостатки — limit 2 ГБ (Classic) или ~16 ЭБ через 64bit-Offset, нет compression, нет chunking, нет groups, нет parallel I/O.
NetCDF-4. HDF5 file с NetCDF semantic layer поверх. Получает все HDF5 features: unlimited size, chunking + compression (gzip default, szip / zstd опционально), hierarchical groups (как директории внутри файла), compound types, parallel I/O через MPI. Расширение .nc4 или просто .nc. Файл валиден как HDF5 — h5py его открывает. Недостатки — больший overhead (~few KB header), не читается NetCDF-3-only tools, медленнее на маленьких файлах.
В современном workflow (2026) — NetCDF-4 по умолчанию. Climate community давно мигрировала: CMIP6, ERA5, MODIS Level-3, MERRA-2 — все NetCDF-4. NetCDF-3 остаётся для backward compatibility и для очень простых datasets, где compression overhead не оправдан. Наш netcdf_exporter.py пишет NetCDF-4 с zlib compression level=4 (balanced).
Экосистема: ncdump, NCO, CDO, xarray, Panoply
NetCDF — это не только формат, но и зрелая экосистема инструментов, накопленных за 36 лет.
ncdump / ncgen. Стандартные CLI utilities из Unidata. ncdump -h file.nc показывает header (dimensions, variables, attributes) в текстовом CDL формате. ncdump file.nc — полный dump данных. ncgen — обратное: текстовый CDL → бинарный .nc. Используется для быстрой инспекции и для генерации тестовых файлов.
NCO (NetCDF Operators). Charlie Zender (UC Irvine), бесплатный, BSD-like. Набор CLI инструментов: ncks (NetCDF Kitchen Sink — extract / subset / convert), ncrcat (concatenate along record dimension), ncea (ensemble average), ncwa (weighted average), ncap2 (arithmetic с expression language). Незаменим для batch processing миллионов файлов в climate workflows: ncks -v temperature -d time,0,30 input.nc output.nc — извлечь первые 30 timesteps только температуры.
CDO (Climate Data Operators). Max Planck Institute for Meteorology, бесплатный, GPLv2. Конкурент NCO с фокусом на climate analysis: cdo remapbil,r360x180 input.nc output.nc — bilinear regrid на 1°×1° grid; cdo yearmean input.nc output.nc — годовое среднее; cdo selname,temperature input.nc output.nc — выборка переменной. 600+ операторов, chainable через pipe.
xarray (Python). Современный Python interface для multidimensional labeled arrays, естественный wrapper над NetCDF-4. xr.open_dataset('era5.nc') → Dataset со всеми variables, coords, attrs. Slicing по labels: ds.sel(time='2024-01-15', lat=slice(50, 60)). Lazy loading через Dask для terabyte-scale data. Сегодняшний де-факто стандарт в climate Python stack.
Panoply (NASA GISS). Бесплатный Java GUI viewer для NetCDF / HDF / GRIB. Plot 2D slices, animations через time dimension, color maps, contours. Незаменим для quick-look — открыл файл, увидел что внутри, проверил units. Работает на Windows / macOS / Linux.
NCL (NCAR Command Language). Высокоуровневый интерпретируемый язык от NCAR для climate analysis с native NetCDF support. Постепенно вытесняется Python+xarray, но огромное legacy code base в climate community.
netcdf4-python. Низкоуровневый Python binding над libnetcdf C library. Используется внутри xarray, но доступен и напрямую для тонкого контроля над compression, chunking, parallel writes.
MATLAB, IDL, R. Все имеют native NetCDF readers. MATLAB ncread('file.nc', 'temperature'), R ncdf4::nc_open(), IDL NCDF_OPEN(). Legacy, но всё ещё используется в academia.
GDAL. Поддерживает NetCDF как raster driver (для 2D georeferenced subsets). gdal_translate -of GTiff NETCDF:"file.nc":temperature output.tif — извлечь one time-slice как GeoTIFF. Не для full N-D workflows, а для интеграции с classical GIS.
OPeNDAP. Не библиотека, а протокол — позволяет читать NetCDF файлы с remote server по URL без download. THREDDS Data Server, ERDDAP — стандартные backend'ы. xr.open_dataset('https://thredds.../era5.nc') работает прозрачно как локальный файл, скачивая только нужные срезы.
NetCDF vs HDF5 vs Zarr: где какой использовать
Три формата для multidimensional scientific arrays — каждый занимает свою нишу.
NetCDF. Domain-specific (climate, ocean, atmosphere, gridded geo). Зрелая CF-conventions экосистема, специализированные tools (CDO, NCO, NCL), все datasets от метеоагентств публикуются именно так. Best fit, если работаете с climate models, satellite atmospheric products, oceanographic reanalysis, или нужна interoperability с CMIP6 / ERA5 / NCEP экосистемами. Single-file, desktop-era storage model.
HDF5. Generic hierarchical container. Любая структура — groups + datasets + arbitrary attributes. NetCDF-4 — это formal subset of HDF5 с CF semantics. HDF5 используется широко в machine learning (старые модели сохранялись в .h5), bioimaging (Imaris, BigDataViewer), NASA EOS data (MODIS L1/L2). Если нужна максимальная гибкость структуры и нет нужды в CF semantics — HDF5. Если данные климатические — NetCDF с CF.
Zarr. Cloud-native heir HDF5 / NetCDF. Каждый chunk — отдельный S3 object, parallel read/write без global lock. NumPy-compatible API. CF-conventions поверх Zarr (xarray engine='zarr') работают идентично NetCDF. Best fit для cloud workflows на S3/GCS, parallel writes из Dask cluster, terabyte/petabyte datasets. Минус — directory tree, не single file (есть ZipStore workaround), нет mature CLI tooling уровня CDO/NCO.
Практическое правило: данные генерируются раз и читаются часто, single laptop / HPC node, нужны CDO/NCO операции → NetCDF. Данные обновляются параллельно из множества writers, хостинг в облаке, нужен HTTP range streaming → Zarr. Generic non-geo научные данные с произвольной иерархией → HDF5.
NetCDF vs Zarr: один формат, разные storage models
Стоит особо проговорить: на data model level NetCDF-4 и Zarr почти идентичны. Те же dimensions, те же variables, те же CF-conventions поверх. xarray переключается между ними одной строкой:
ds.to_netcdf('output.nc') # NetCDF-4 (HDF5) — single file
ds.to_zarr('output.zarr') # Zarr — directory of chunks
Разница — storage model. NetCDF-4 — monolithic HDF5 file: один файл, глобальный B-tree index, чтение через POSIX file API. Идеально для locally-mounted disk, плохо для S3 (range reads дорогие, нет parallel writes — file lock). Zarr — chunks как separate S3 objects, JSON metadata, parallel writes тривиальны (каждый chunk — независимый PUT).
Pangeo project в начале 2020-х фактически клонировал NetCDF semantics в Zarr именно для cloud migration: те же CF-conventions, тот же xarray API, но теперь работает на S3 без боли. CMIP6 публикует данные в обоих форматах параллельно. Для archive download — NetCDF; для in-cloud analysis — Zarr копия.
В osm2cdr мы экспортируем оба: netcdf_exporter.py пишет NetCDF-4 для классических climate / GIS workflows, zarr_exporter.py (beta) — Zarr для cloud-native экспериментов. Семантика результата одинакова — отличается только storage layout.
Кейсы использования
Climate model output. CMIP6 (Coupled Model Intercomparison Project) — глобальный benchmark для климатических моделей. ~100 моделей, ~30 ПБ выходных данных, всё в NetCDF-4 / Zarr с CF-conventions. Учёный через xarray + Dask открывает petabyte-scale ensemble, делает .sel(experiment='ssp585', time=slice('2050', '2100')) — пользователь получает projection потепления к концу века по нескольким моделям сразу.
Atmospheric reanalysis. ERA5 от ECMWF — лучший global atmospheric reanalysis (1940 — present, hourly, 0.25° grid). 5 ПБ данных в NetCDF-4 на Copernicus Climate Data Store. NCEP/NCAR Reanalysis, MERRA-2 (NASA), JRA-55 (Japan) — все аналогично. Это базовые данные для климатических исследований, прогноза погоды, renewable energy resource assessment.
Satellite remote sensing. MODIS Level-3 products (Terra/Aqua, 2000—present): aerosol optical depth, vegetation indices, sea surface temperature — все в NetCDF-4 / HDF-EOS5. Sentinel-3 OLCI/SLSTR atmospheric products, ICESat-2 ATL06/ATL08, Aura OMI ozone — NetCDF-4 ubiquitous. NASA Earthdata Cloud / ESA Copernicus — точки входа.
Oceanography. ROMS (Regional Ocean Modeling System), HYCOM (HYbrid Coordinate Ocean Model), NEMO — все генерируют NetCDF output. Argo float profiles, GLORYS reanalysis, OISST — стандарт NetCDF с CF. Океанологи живут в xarray / CDO / Panoply.
Hydrology. USGS National Water Model output, GLDAS (Global Land Data Assimilation System) — gridded soil moisture, runoff, evapotranspiration в NetCDF-4. NWS forecast products через NOMADS / THREDDS.
Urban gridded analytics (наш случай). Допустим, исследователь хочет проанализировать как менялась POI density / building density по Москве за последние 5 лет, по сезонам, в сравнении с air quality reanalysis. Естественная структура — time × variable × lat × lon cube. Через osm2cdr netcdf_exporter.py мы агрегируем OSM данные через PostGIS в grid cells, упаковываем в NetCDF-4 с CF-conventions. Результат напрямую открывается в xarray, легко join'ится с ERA5 air quality через xr.merge() — получается готовый dataset для urban climate paper.

Сильные и слабые стороны
Сильные. Self-describing — файл несёт собственные метаданные, не нужны external sidecars. Machine-independent — single binary файл читается на любой архитектуре с момента создания (1989 NetCDF-1 файл откроется сегодня unchanged). Огромная экосистема (ncdump, NCO, CDO, xarray, Panoply, NCL, GDAL) накопленная за 36 лет. CF-Conventions де-факто стандарт для climate metadata — units, axes, time encoding, CRS унифицированы. Используется буквально во всех крупных climate / atmospheric / ocean datasets (CMIP6, ERA5, MODIS, MERRA-2). Open spec (Unidata), open library (libnetcdf, BSD-like). NetCDF-4 даёт chunking + compression + parallel I/O через MPI для HPC workflows. OPeNDAP protocol позволяет работать с remote файлами без download.
Слабые. Desktop-era storage model — single binary file плохо подходит для cloud (S3 range reads дорогие, parallel writes требуют file locking). Cloud-native заменитель — Zarr. Не human-readable (бинарный) — для inspection нужен ncdump -h. NetCDF-4 требует HDF5 dependency — установка libhdf5 в headless Docker иногда нетривиальна. Не оптимизирован для tabular data (POI list) — для этого GeoParquet / SQL. CF-Conventions сложный (10+ страниц правил), легко забыть требуемый атрибут — тогда tools warn'ят. Для editing — нужно переписывать чанки целиком (особенно NetCDF-3). Limit ~2 ГБ в NetCDF-3 Classic, обходится через 64bit-Offset или NetCDF-4.
FAQ
Чем NetCDF отличается от HDF5? NetCDF-4 — это HDF5 файл с дополнительными ограничениями и conventions: специальные атрибуты (_NCProperties), запрет некоторых HDF5 features (например, hard links между datasets), CF-conventions для climate metadata. Любой NetCDF-4 файл — валидный HDF5 файл (h5py его откроет), но не наоборот: произвольный HDF5 может не подчиняться NetCDF semantics. NetCDF-3 — полностью отдельный формат, не имеет ничего общего с HDF5. Подробнее в нашей статье про HDF5.
NetCDF-3 или NetCDF-4 — какой выбрать? В 2026 году — NetCDF-4 по умолчанию. Compression уменьшает размер в 3–5 раз для типичных climate data, unlimited file size снимает 2 ГБ limit, groups дают логическую структуру. NetCDF-3 имеет смысл только если требуется совместимость с очень старыми tools (Fortran 77 legacy, древний MATLAB). Наш netcdf_exporter.py пишет NetCDF-4 с zlib level=4.
Что такое CF-Conventions и обязательны ли они? CF (Climate and Forecast Metadata Convention) — стандарт атрибутов NetCDF файлов для climate / forecast / earth system data. Указывает обязательные атрибуты variables (units, standard_name, long_name), как кодировать time ("days since 1970-01-01"), как описывать CRS (grid_mapping), как обозначать axes (axis="T"). Технически — не обязательны (файл без CF тоже валидный NetCDF), но без них xarray / CDO / Panoply не смогут автоматически распознать оси и сделать proper plotting. Все professional datasets — CF-compliant. Наш экспортёр пишет CF-1.11.
Как открыть .nc файл без программирования? Panoply (NASA GISS, бесплатный Java GUI) — лучший выбор для quick-look: открыл, посмотрел dimensions / variables, нарисовал 2D map. Альтернативы — IDV (NCAR), ncBrowse, или сама QGIS через GDAL NetCDF driver (Layer → Add Raster Layer → файл .nc → выбрать subdataset). Для command-line быстрой инспекции — ncdump -h file.nc.
Как NetCDF справляется с time? Time в NetCDF хранится как numeric value + units string в формате "<unit> since <reference>": например "days since 1850-01-01 00:00:00" или "hours since 2024-01-01". Дополнительный атрибут calendar указывает календарь (gregorian, noleap, 360_day для climate models). При чтении через xarray / netCDF4-python time автоматически decodes в datetime objects. Это позволяет хранить time-series от 1850 до 2300 без single Unix timestamp limit'а.
Может ли NetCDF хранить vector data (точки, линии, полигоны)? Технически — да, через CF-Conventions Discrete Sampling Geometries (DSG) extension: timeSeries, profile, trajectory features описываются через специальную instance dimension + coordinate variables. Используется для измерений с buoys, weather stations, ship tracks. Но для типичных GIS vector layers (POI, buildings, roads) NetCDF — неестественный выбор. Берите GeoJSON, Shapefile, GeoParquet, GeoArrow. NetCDF — для rasterized / gridded data.
Pipeline в OSM2CDR
Наш netcdf_exporter.py — четырёхступенчатый pipeline для превращения OSM-области в CF-compliant gridded cube:
Шаг 1: PostGIS aggregation. Берём bbox от пользователя, разбиваем на сетку (default 100×100 cells, configurable). Для каждой cell через PostGIS считаем aggregations: COUNT POI per category, SUM building footprint area, SUM road length, density per km². SQL запрос — параметризованный, использует ST_Within с spatial index по grid cells.
Шаг 2: Stack in numpy array. Результаты aggregation складываем в 3D numpy array [variable × lat × lon] (или 4D [time × variable × lat × lon] если запрошены multiple snapshots — для future temporal feature). Lat/lon axes — actual coordinates центров cells в WGS84.
Шаг 3: Wrap in xarray Dataset. Создаём xr.Dataset с coordinates (lat, lon, опционально time) и data variables (poi_density, building_density, road_density, etc). Прикрепляем CF-conventions атрибуты: standard_name, units, long_name для каждой variable; axis, standard_name для coordinates; grid_mapping для CRS (WGS84 latitude_longitude); global attrs (Conventions="CF-1.11", title, institution="osm2cdr.ru", source, history).
Шаг 4: Write NetCDF-4. Через ds.to_netcdf('output.nc4', format='NETCDF4', engine='netcdf4', encoding={var: {'zlib': True, 'complevel': 4} for var in ds.data_vars}). Получается ~1–5 МБ файл для типичного city-bbox grid 100×100×4 variables, готовый к импорту в любой CF-aware tool.
Validate output:
ncdump -h output.nc4 | head -30
# Должен показать Conventions = "CF-1.11", корректные axes, units
cdo info output.nc4
# CDO распознает grid и variables
python -c "import xarray; ds = xarray.open_dataset('output.nc4'); print(ds)"
# xarray decode time, attaches coords, shows Dataset structure
Заключение
NetCDF — лучший выбор если ваша работа лежит в climate science, atmospheric / oceanographic research, satellite remote sensing, или gridded environmental data. 36 лет зрелой экосистемы (ncdump, NCO, CDO, xarray, Panoply), CF-conventions де-факто стандарт, все major climate datasets публикуются именно так (CMIP6, ERA5, MODIS, MERRA-2). Для cloud-native scaling — Zarr c такой же semantics. Для generic hierarchical scientific data — HDF5 без CF overhead. Для типичной OSM-карты (vector POI/roads/buildings) — NetCDF overkill, берите GeoJSON или Shapefile.
На osm2cdr.ru netcdf_exporter.py агрегирует OSM-features в gridded cube с CF-1.11 атрибутами — это естественный мост между OpenStreetMap и climate research экосистемой. Если делаете urban climate paper, нужен POI density grid для join'а с ERA5 air quality — наш NetCDF экспорт работает прямо в xarray.
Попробовать экспорт в NetCDF из OSM-области — /formats/netcdf/.
Связанные материалы
- HDF5 — иерархический формат для научных данных
- Zarr — облачный chunked-формат для N-мерных массивов
- GeoTIFF — формат растровых геоданных с 1995 года
- GeoArrow — columnar геопространственный формат
Источники
- Unidata NetCDF documentation — docs.unidata.ucar.edu/netcdf-c/current/
- CF Metadata Conventions — cfconventions.org
- NCO (NetCDF Operators) — nco.sourceforge.net
- CDO (Climate Data Operators) — code.mpimet.mpg.de/projects/cdo
- Panoply (NASA GISS) — giss.nasa.gov/tools/panoply
- xarray documentation — docs.xarray.dev
- ERA5 reanalysis (Copernicus) — cds.climate.copernicus.eu
- CMIP6 datasets — esgf-node.llnl.gov/projects/cmip6