Search, download, process, and regrid Suomi-NPP VIIRS Level-2P sea surface temperature granules from the NASA Earthdata PO.DAAC GHRSST archive.

Overview

This package targets the active PO.DAAC GHRSST NOAA STAR ACSPO product VIIRS_NPP-STAR-L2P-v2.80 (the default collection). Each Level-2P swath file contains both day and night retrievals, with the day/night state encoded in the CF l2p_flags bitmask.

Two scripts cover the workflow:

  • snpp_viirs_sst.py — search NASA Earthdata/CMR via earthaccess, download raw granules idempotently, and process them into smaller, analysis-ready NetCDF files (Kelvin→Celsius, a recommended-quality mask, and decoded day/night masks). Search, download, and processing can each be run in isolation.
  • regrid_snpp_sst.py — resample a processed or raw swath onto a regular lat/lon grid or a regional azimuthal-equidistant cartesian grid, with an optional PNG map preview. Built on common.swath_regrid (pyresample).

All outputs land under /spray/snpp by default, overridable with --out-root.

Installation & dependencies

Core dependencies: earthaccess, xarray, numpy, a NetCDF writer (netCDF4 or h5netcdf), and pyproj + pyresample for regridding. tqdm is used for progress bars when present. From the repo root:

python -m pip install -e ".[all]"       # everything, or:
python -m pip install -e ".[plot,kriging]"
  • NASA Earthdata credentials are required for downloads. earthaccess reads them from ~/.netrc:

text machine urs.earthdata.nasa.gov login <username> password <password>

  • The plot extra installs cartopy, used for the coastline/gridline map preview in regrid_snpp_sst.py --plot. Without it the plot falls back to a plain lon/lat axes. The kriging extra (pykrige) enables the kriging regrid method.

Entry points & scripts

Console script Module Purpose
odsl-snpp-sst snpp.snpp_viirs_sst:main Search, download, and process VIIRS L2P SST
odsl-snpp-regrid snpp.regrid_snpp_sst:main Regrid a processed/raw swath and optionally plot
odsl-snpp-footprints snpp.granule_footprints:main Incremental parquet of processed granules for colocate

Footprints default to /spray/snpp/footprints/snpp_granule_footprints.parquet (odsl-colocate-refresh --targets snpp). Re-running is incremental unless --rebuild is set.

Each script also runs directly (python snpp/snpp_viirs_sst.py …); a repo-root sys.path bootstrap makes the shared common package importable either way.

Usage

Search a date range and bounding box (west south east north), download, and process to /spray/snpp:

python snpp/snpp_viirs_sst.py \
    --start 2024-01-01 \
    --end 2024-01-02 \
    --bbox -98 18 -80 31

Common variations:

# Search + write manifests only (no download)
python snpp/snpp_viirs_sst.py --start 2024-01-01 --end 2024-01-02 \
    --bbox -98 18 -80 31 --manifest-only

# Download raw granules but skip processing
python snpp/snpp_viirs_sst.py --start 2024-01-01 --end 2024-01-02 --download-only

# Keep full swaths (do not subset processed files to --bbox)
python snpp/snpp_viirs_sst.py --start 2024-01-01 --end 2024-01-02 \
    --bbox -98 18 -80 31 --no-bbox-subset

# Keep every source variable; disable the quality mask; re-run overwriting
python snpp/snpp_viirs_sst.py --start 2024-01-01 --end 2024-01-01 \
    --variables all --no-quality-mask \
    --overwrite-downloads --overwrite-processed

Other flags: --collection (CMR short name, default VIIRS_NPP-STAR-L2P-v2.80), --provider (default POCLOUD), --max-granules, --quality-min, --auth-strategy.

Regrid a processed swath onto a 0.02° lat/lon grid with a map preview:

python snpp/regrid_snpp_sst.py \
    --input /spray/snpp/processed/VIIRS_NPP-STAR-L2P-v2.80/2024/01/01/example_processed.nc \
    --grid-type latlon \
    --bbox -98 18 -80 31 \
    --resolution-deg 0.02 \
    --method gaussian \
    --radius-of-influence 15000 \
    --smoothing-radius 7500 \
    --grid-file /spray/snpp/grids/gulf_002deg.nc \
    --plot

Regrid onto a regional 2 km cartesian grid centered on a point:

python snpp/regrid_snpp_sst.py \
    --input /spray/snpp/raw/VIIRS_NPP-STAR-L2P-v2.80/2024/01/01/example.nc \
    --grid-type cartesian \
    --center-lat 25 --center-lon -89 \
    --dx-m 2000 --width-m 1500000 --height-m 1100000 \
    --method linear \
    --grid-file /spray/snpp/grids/gulf_2km_aeqd.nc \
    --plot

If --grid-file exists it is loaded and grid-creation flags are ignored; otherwise the newly built grid is saved there for reuse. Regridding accepts multiple inputs or quoted wildcard patterns (use --output-dir/--plot-dir for batches, --output/--plot-output only for single files). Regrid methods: nearest, gaussian, linear, bilinear, kriging. A --day-night day/night filter and --variable (default sst_celsius) are also available.

Output layout

/spray/snpp/
├── manifests/
│   ├── VIIRS_NPP-STAR-L2P-v2.80_<start>_<end>_manifest.csv
│   └── VIIRS_NPP-STAR-L2P-v2.80_<start>_<end>_manifest.json
├── raw/
│   └── VIIRS_NPP-STAR-L2P-v2.80/YYYY/MM/DD/*.nc
├── processed/
│   └── VIIRS_NPP-STAR-L2P-v2.80/YYYY/MM/DD/*_processed.nc
├── grids/                 # saved reusable target grids (regrid)
├── regridded/             # default regrid outputs and PNG previews
└── footprints/
    └── snpp_granule_footprints.parquet

Raw files are checked against what is already on disk and skipped unless --overwrite-downloads is set; processed files are skipped unless --overwrite-processed is set.

SST processing details

Processed files retain a selected subset of source variables (or all with --variables all) and add these derived fields:

Variable Description
sst_celsius sea_surface_temperature converted from Kelvin (− 273.15) to °C
recommended_quality int8 mask where quality_level >= 5 (default --quality-min; disable with --no-quality-mask)
is_day Daytime pixel mask decoded from the l2p_flags CF bitmask
is_night Nighttime pixel mask decoded from l2p_flags (falls back to ~is_day when only a day flag is present)

Day/night masks are decoded from the flag_masks/flag_values + flag_meanings attributes of l2p_flags. When --bbox is supplied, processed files are subset to that box unless --no-bbox-subset is given. The regridder re-derives these fields on the fly for raw inputs and applies the recommended-quality and day/night masks before resampling.

Shared code

These modules were refactored to import shared helpers from the repo-root common package so the SNPP and GEOS pipelines stay in sync:

  • common.log — timestamped log() to stderr
  • common.earthdatanormalize_cmr_time, split_antimeridian_bbox, filename_from_url, date_parts, safe_token, existing_netcdf_files
  • common.flags — CF flag-decode helpers (_as_list, _normalize_flag_name)
  • common.datasetclear_encodings
  • common.cliparse_variables
  • common.swath_regrid — pyresample-based swath→grid regridding (build_latlon_grid, load_target_grid, regrid_dataarray, …)
  • common.footprints — incremental SST granule index (odsl-snpp-footprints)

Each script prepends the repo root to sys.path so it runs both as an installed console script and directly.