Skip to main content

Losslessly rewrite netCDF4/HDF5 files with different compression settings.

Project description

CI status MIT License Python 3.10-3.13

Reincarnate legacy scientific data as modern netCDF4.

ncarnate reads netCDF3, netCDF4/HDF5, and HDF4/HDF-EOS2 files and writes recompressed, CF-annotated netCDF4. It does two jobs:

  • Recompress netCDF/HDF5 files — change the compression level, shuffle filter, or storage layout without changing a single stored value.

  • Convert HDF4 and HDF-EOS2 granules (AMSR-E, MODIS, and kin) to netCDF4, reconstructing the CF coordinates that modern tools (xarray, QGIS, Panoply) need: grid projections become CF grid mappings with 1-D x/y and 2-D lat/lon coordinates, swath geolocation is attached as CF coordinates, and dimension-mapped (e.g. 5 km → 1 km) geolocation is interpolated through ECEF space.

The fidelity contract

Converting or recompressing a file changes storage, never science data:

  • Every variable’s stored values are preserved bit-identically — packed integers stay packed; scale_factor/add_offset/ _FillValue are carried across as declarations, never applied.

  • Every dimension (including unlimited-ness), attribute (including its type), and group survives. HDF-EOS2 StructMetadata is preserved verbatim; names netCDF cannot hold are sanitized with the original recorded in a companion attribute.

  • Geolocation reconstruction is strictly additive: the original information always rides along, so the conversion never becomes the only copy of the truth.

  • Every output is verified against the source value-for-value before it replaces anything. A source file is never destroyed by a failed run, and HDF4 sources are never replaced at all.

  • Unsupported constructs (user-defined netCDF types, unverified GCTP projections, exotic swath layouts) fail loud with a named error rather than guessing — a wrong coordinate is worse than a refused conversion. --no-geolocation converts the raw payload anyway.

The details, the guarantee boundary, and how the test suite pins each clause live in docs/fidelity-notes.md.

Installation

pip install ncarnate

On Linux (x86_64) and macOS (arm64), every dependency — including pyhdf — installs as a self-contained binary wheel with no system libraries required (the pyhdf wheels there bundle the HDF4 C library). On platforms without a repaired pyhdf wheel (e.g. Linux aarch64), building from sdist requires the system HDF4 library first (Debian/Ubuntu: apt install libhdf4-dev).

Windows: the netCDF/HDF5 recompression path works from PyPI wheels out of the box, but the HDF4/HDF-EOS2 conversion path does notpyhdf’s Windows wheel ships no HDF4 runtime, so import pyhdf fails with a DLL-load error. For HDF4 support on Windows, install pyhdf from conda-forge first (conda install -c conda-forge pyhdf), which provides a properly linked build with the HDF4 runtime, then pip install ncarnate into that same environment — or use WSL and follow the Linux instructions.

Command line usage

# Recompress a netCDF4 file in place (verified before replacement).
ncarnate observations.nc --complevel 9

# Keep the original; write observations_recompressed.nc beside it.
ncarnate --no-overwrite observations.nc

# Convert an HDF-EOS2 granule -> granule.nc with CF geolocation.
ncarnate AMSR_E_L3_SeaIce12km_B02_20020619.hdf

# Convert the raw SDS payload only (unsupported-projection escape hatch).
ncarnate --no-geolocation granule.hdf

# Recurse over a directory tree.
ncarnate -r /data/archive

Exit codes: 0 success, 1 one or more files failed, 2 bad input paths or arguments.

Library usage

from ncarnate import recompress

# Lossless recompression; returns the output path.
recompress("observations.nc", complevel=9)

# HDF-EOS2 conversion; the .hdf source is never replaced.
recompress("granule.hdf", dst="granule.nc")

Example

The AMSR-E daily 12.5 km sea-ice granule this project grew up around:

File

Input

Output

netCDF4 recompression (--complevel 9)

42.6 MB

19.9 MB

HDF-EOS2 → netCDF4 (+ reconstructed lat/lon)

60.2 MB

35.5 MB

Both outputs re-read bit-identically to their sources; the conversion additionally carries CF polar_stereographic grid mappings and coordinates for both hemispheric grids. The northern grid’s reconstructed latitudes/longitudes agree with The HDF Group’s independent conversion of the same granule to within 10-5 degrees (about a metre), the tolerance the test suite enforces.

Supported inputs

  • netCDF4 / HDF5 and netCDF3 — recompressed via the netCDF4 library.

  • HDF4 / HDF-EOS2 — read via the pyhdf SD API. GRID structures with GCTP polar-stereographic, geographic, and Lambert-azimuthal (EASE-Grid) projections; SWATH structures with direct or dimension-mapped geolocation. Output is always netCDF4 — HDF4 is never written.

Development

pip install -e ".[test]"
ruff check .
pytest

The test suite runs entirely offline against small committed fixtures trimmed from real granules (provenance sidecars included); cross-checks against the raw multi-MB granules self-skip where the local granule store is absent.

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ncarnate-2.0.0.tar.gz (456.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ncarnate-2.0.0-py3-none-any.whl (36.1 kB view details)

Uploaded Python 3

File details

Details for the file ncarnate-2.0.0.tar.gz.

File metadata

  • Download URL: ncarnate-2.0.0.tar.gz
  • Upload date:
  • Size: 456.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for ncarnate-2.0.0.tar.gz
Algorithm Hash digest
SHA256 5d97943f26a7e8899301e16c79c9ae7571f5840abf7723ca7bd53a71fe32fbde
MD5 7a918a5dd4cfdca3b3a4f256ab9551fe
BLAKE2b-256 57e8b61070831c859f77e58bf1d71008a8d66fca1803b529cbb8a50e08e1363d

See more details on using hashes here.

Provenance

The following attestation bundles were made for ncarnate-2.0.0.tar.gz:

Publisher: publish.yml on ErickShepherd/ncarnate

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ncarnate-2.0.0-py3-none-any.whl.

File metadata

  • Download URL: ncarnate-2.0.0-py3-none-any.whl
  • Upload date:
  • Size: 36.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for ncarnate-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2acb9bfdbeb824b5119620f018b5c27f3931e0cc0a339da150c99cef3cab3172
MD5 f81940b2ee632569ce80613afdd20f93
BLAKE2b-256 7fc2b77c1f9caf6411af9de8a6570f9014abdcd6b646b74616fa2af2bc90d6e7

See more details on using hashes here.

Provenance

The following attestation bundles were made for ncarnate-2.0.0-py3-none-any.whl:

Publisher: publish.yml on ErickShepherd/ncarnate

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page