CAMS EAC4 → EOPF HEALPix Converter#
Converts CAMS EAC4 aerosol reanalysis (regular 0.75°) to EOPF-compliant HEALPix zarr (level 6, ~100 km).
Pipeline: download NetCDF via ADS REST API → resample to HEALPix → write zarr → inject STAC
Resampling (method=, default "psf"): PSFResampler tuned for the regular grid (threshold=0.01 → 0 NaN, lam=5.0 → no Gibbs ringing / 0 negative AOD), with a final clip(0, None). Pass method="nn" for the nearest-neighbour binning alternative (exact, faster). Both give 0 NaN / 0 negative and correlate > 0.98.
import logging
from pathlib import Path
from healpix_convert.converters.cams import CAMSConverter
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")
Configuration#
DATE = "2025-01-01"
TIME = "00:00"
LOCAL_DIR = Path(".")
OUTPUT = LOCAL_DIR / f"S00__ADF_CAMSA_{DATE.replace('-','')}.zarr"
converter = CAMSConverter(
date=DATE,
time=TIME,
local_dir=LOCAL_DIR,
method="psf", # default; use "nn" for nearest-neighbour binning
)
Step 1 — Prepare (download)#
result = converter.prepare(output_path=str(OUTPUT))
print(f"Chunks: {result.n_chunks} | Timesteps: {result.n_times}")
Step 2 — Convert (all spatial chunks)#
for i in range(result.n_chunks):
converter.convert_group(i)
if (i + 1) % 20 == 0:
print(f" {i+1}/{result.n_chunks}")
Step 3 — Consolidate#
converter.consolidate()
print(f"Done: {OUTPUT}")
Validation#
import healpy as hp
import matplotlib.pyplot as plt
import xarray as xr
ds = xr.open_zarr(str(OUTPUT), consolidated=True)
print(ds)
data = ds["aod550"].isel(time=0).values
hp.mollview(
hp.reorder(data, n2r=True),
flip="geo",
nest=False,
cmap="viridis",
min=0,
max=1.5,
unit="AOD",
title="CAMS AOD550 — HEALPix level 6",
)
plt.show()