Skip to main content

cng-datasets

DOI

A CLI toolkit for processing large geospatial datasets into cloud-native formats on Kubernetes.

What it does: Takes source geospatial data (Shapefiles, GeoPackages, FileGDB, GeoTIFFs) and produces:

  • GeoParquet — columnar format for analytical queries (DuckDB, Polars)
  • PMTiles — vector tiles for web map visualization
  • H3 Hex Parquet — hexagonal grid indexed at configurable H3 resolution, hive-partitioned for fast spatial joins
  • Cloud-Optimized GeoTIFF — for raster data, optimized for HTTP range requests

How it works: You run a single CLI command locally. It generates Kubernetes Job YAML files that orchestrate the entire pipeline on your cluster. You never process data on your local machine — the CLI just generates the jobs.

Installation

pip install cng-datasets

Or from source:

pip install -e "."

Usage

Generate a vector processing pipeline

cng-datasets workflow \
  --dataset cpad-2024 \
  --source-url https://example.com/cpad.gdb \
  --bucket public-cpad \
  --layer CPAD_SuperUnits \
  --h3-resolution 10 \
  --parent-resolutions "9,8,0" \
  --hex-memory 32Gi \
  --max-completions 200 \
  --max-parallelism 50

This generates YAML files for a 5-step pipeline:

  1. setup-bucket — creates the S3 bucket with public-read policy
  2. convert — reads source data, reprojects to EPSG:4326, writes GeoParquet
  3. pmtiles — converts GeoParquet to PMTiles (parallel with step 4)
  4. hex — computes H3 cell assignments in parallel pods
  5. repartition — consolidates hex chunks into hive-partitioned layout

Multiple sources: Add --source-url multiple times to merge datasets:

cng-datasets workflow \
  --dataset merged-regions \
  --source-url https://example.com/region1.shp \
  --source-url https://example.com/region2.shp \
  --source-url https://example.com/region3.shp \
  --bucket my-bucket

Apply them:

kubectl apply -f <output-dir>/workflow-rbac.yaml
kubectl apply -f <output-dir>/configmap.yaml
kubectl apply -f <output-dir>/workflow.yaml

The workflow orchestrator runs steps sequentially, launching pmtiles and hex in parallel.

Generate a raster processing pipeline

cng-datasets raster-workflow \
  --dataset wetlands-cog \
  --source-url https://example.com/wetlands.tif \
  --bucket public-wetlands

Multi-layer sources

For GeoDatabase or GeoPackage files with multiple layers, run one workflow per layer. Use --layer to select each layer and --dataset with / for hierarchical S3 paths:

# Inspect layers
ogrinfo /vsicurl/https://example.com/data.gdb

# Process each layer separately
cng-datasets workflow --dataset mydata/layer-a --layer LayerA ...
cng-datasets workflow --dataset mydata/layer-b --layer LayerB ...

The / in --dataset creates nested S3 paths (e.g., mydata/layer-a.parquet) while using hyphens for k8s resource names.

CLI Reference

Command Purpose
cng-datasets workflow Generate vector processing k8s pipeline
cng-datasets raster-workflow Generate raster processing k8s pipeline
cng-datasets storage setup-bucket Create and configure an S3 bucket
cng-convert-to-parquet Convert vector data to GeoParquet
cng-datasets vector Run H3 hex tiling (used inside k8s pods)
cng-datasets raster Run raster H3 tiling (used inside k8s pods)
cng-datasets repartition Consolidate hex chunks (used inside k8s pods)
cng-datasets merge-chunks Consolidate sub-h0 raster hex chunks (used inside k8s pods)

Commands marked "used inside k8s pods" are called by the generated jobs — you don't run them directly.

cng-datasets workflow options

--dataset NAME             Dataset name for S3 paths. Use / for hierarchy (e.g., "padus/fee").
--source-url URL           Public URL to source data.
--bucket BUCKET            Target S3 bucket name.
--layer LAYER              Layer name for multi-layer sources (GDB, GPKG).
--h3-resolution N          H3 resolution for hex tiling (default: 10).
--parent-resolutions STR   Comma-separated parent resolutions (default: "9,8,0").
--hex-memory SIZE          Memory per hex pod (default: 8Gi).
--max-completions N        Number of parallel chunks, max 200 (default: auto).
--max-parallelism N        Max concurrent pods (default: 50).
--id-column COL            ID column name (auto-detected if omitted).
--output-dir DIR           Directory for generated YAML files.
--intermediate-chunk-size  Rows per unnest batch (decrease if OOM).
--row-group-size N         Rows per parquet row group (default: 100000).

cng-datasets raster-workflow options

--dataset NAME             Dataset name for S3 paths. Use / for hierarchy.
--source-url URL           Public URL to a source raster. Repeat to mosaic tiles.
--bucket BUCKET            Target S3 bucket name.
--h3-resolution N          H3 resolution for hex tiling (default: 8).
--parent-resolutions STR   Comma-separated parent resolutions (default: "0").
--hex-resampling R         mean | sum | mode | fractions | max | min (default: mean).
--nodata VALS              NoData value(s) to exclude, comma-separated.
--hex-memory SIZE          Memory per hex pod (default: 32Gi).
--hex-cpu N                CPU request/limit per hex pod (default: 4).
--hex-workers N            Worker processes per hex pod (default: one per --hex-cpu).
--hex-chunk-size N         Cells per exact_extract call (default: 100000).
--h0-subset CELLS          The h0 base cells the source overlaps (default: all 122).
--chunk-resolution N       H3 resolution of one hex pod's unit of work (default: 0, one h0).
--max-hex-memory SIZE      Pick --chunk-resolution automatically to fit this budget.
--backend BACKEND          k8s (default) | armada | auto (armada past ~200 chunks).
--max-parallelism N        Max concurrent hex pods (default: 61).
--output-dir DIR           Directory for generated YAML files.

S3 Output Layout

bucket/
├── dataset.parquet              # GeoParquet
├── dataset.pmtiles              # PMTiles
├── dataset/
│   └── hex/
│       └── h0={cell}/data_0.parquet   # H3-indexed, hive-partitioned
├── README.md
└── stac-collection.json

Docker

The CLI and all dependencies are packaged in a Docker image used by the k8s jobs:

docker pull ghcr.io/boettiger-lab/datasets:latest

Troubleshooting

OOM on hex jobs (vector): Increase --hex-memory (e.g., 32Gi → 64Gi), increase --max-completions for smaller chunks, or decrease --intermediate-chunk-size.

Raster hex pod too big even at one worker: the pod's memory tracks the largest chunk's H3-cell count, and the default chunk is a whole h0 base cell (~282M cells at res 10). Pass --chunk-resolution 1 or 2 to raster-workflow to make the unit a descendant of an h0 instead — roughly 7x fewer cells per level — or --max-hex-memory 8Gi to have it chosen for you. The generated workflow gains a merge step that restores the usual h0={cell}/data_0.parquet layout, so the published layout is unchanged. Past ~200 chunks a single indexed Job exceeds the namespace pod guideline; --backend auto routes to Armada at that point. Sub-chunked pods read only their own window of the source COG rather than localizing the whole file (--window-reads), so total transfer stays proportional to the data instead of to the number of chunks.

OOM on hex jobs (raster): Lower --hex-workers before raising --hex-memory. Peak RSS is roughly --hex-workers × --hex-chunk-size × bytes per cell, and a memory request large enough to matter (past ~128Gi) makes the pod contend for scarce large-RAM nodes, turning a retryable OOM into an unschedulable one. Both knobs are always written into the manifest as CNG_HEX_WORKERS / CNG_HEX_CHUNK_SIZE, so a tuned pod survives regeneration.

Convert fails on curved geometries (MULTISURFACE): Handled automatically — the converter linearizes curved geometry types via ogr2ogr before processing.

Monitoring:

kubectl get jobs              # Pipeline status
kubectl logs job/<name>       # Job logs
kubectl get pods | grep OOM   # Check for memory issues

Development

pip install -e ".[dev]"
pytest tests/

License

Apache 2.0

Citation

If you use cng-datasets in your work, please cite it via its Zenodo archive. The DOI badge at the top of this README resolves to the latest release; each release also has its own version-specific DOI. Citation metadata (authors, title, funding) lives in .zenodo.json and is minted automatically by Zenodo on each GitHub release.

Boettiger, C., & Buhler, C. K. cng-datasets: A cloud-native toolkit for processing large geospatial datasets on Kubernetes. Zenodo. https://zenodo.org/badge/latestdoi/921944685

Once the first release is archived on Zenodo, replace the redirect above with the concrete versioned DOI it mints.

Download files

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

Source Distribution

cng_datasets-0.5.0.tar.gz (220.9 kB view details)

Uploaded Source

Built Distribution

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

cng_datasets-0.5.0-py3-none-any.whl (144.0 kB view details)

Uploaded Python 3

File details

Details for the file cng_datasets-0.5.0.tar.gz.

File metadata

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

File hashes

Hashes for cng_datasets-0.5.0.tar.gz
Algorithm Hash digest
SHA256 c4cae1e0f61560d46e491b5484d9e27b2f66a509eb27c90dd2daad3bc89b8ed5
MD5 40df63b4b06dd603619bcefd49b2fdeb
BLAKE2b-256 a0b29ba46ff33f7cb40a9df3eb30916504d537e6c0a8c2e85e77b21b609d0b07

See more details on using hashes here.

Provenance

The following attestation bundles were made for cng_datasets-0.5.0.tar.gz:

Publisher: release.yml on boettiger-lab/datasets

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

File details

Details for the file cng_datasets-0.5.0-py3-none-any.whl.

File metadata

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

File hashes

Hashes for cng_datasets-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6ea8b1609645769de88d9eb175058122b47485eadeaa66c469bb6d86979f1368
MD5 650cd85f0343a04db2dc95c414154ff7
BLAKE2b-256 73bf5356fd98162f0312e1d7024c5001ccf1a6af3521e8f1572b3928a4b1dfc0

See more details on using hashes here.

Provenance

The following attestation bundles were made for cng_datasets-0.5.0-py3-none-any.whl:

Publisher: release.yml on boettiger-lab/datasets

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

Release history Release notifications | RSS feed

This release

0.5.0 This release

2 files

0.4.0

2 files

0.3.1

2 files

0.3.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page