Skip to main content

cosmic-crunch

CI License: MIT Python DOI

Download JPL GENESIS COSMIC radio-occultation ASCII data files and convert them to netCDF4.

cosmic-crunch crawls the JPL GENESIS data archive, downloads the Level-2 ASCII occultation profiles, and (optionally) converts them into self-describing netCDF4 files.

Problems this solves

Reach for this if you are trying to:

  • Bulk-download COSMIC-1 (FORMOSAT-3) GNSS radio-occultation (RO) data from the JPL GENESIS archive without hand-writing a crawler.
  • Convert COSMIC / GENESIS Level-2 ASCII occultation profiles to netCDF4 — the profile's fields (temperature, pressure, refractivity, water vapour, …) as a self-describing, xarray-friendly file.
  • Resume an interrupted bulk pull — downloads are atomic and skip files already present, so you can just re-run.
  • Download only the slice you need — filter by instrument, year, or date (year and date by regex) instead of pulling the whole archive.

Site restructure note (2020 → 2026). JPL restructured the GENESIS site: the old crawl root (/ftp/pub/genesis/glevels) is dead, so v1 of this tool silently "succeeded" while downloading nothing. v2 targets the current root https://genesis.jpl.nasa.gov/ftp/glevels/ and fails loudly — a crawl that finds nothing exits non-zero instead of pretending to succeed.

Mission status. COSMIC-1 (FORMOSAT-3, flight modules FM1–FM6, served here as cosmic1/–cosmic6/) was decommissioned in 2020, so this is a static archive — the data has stopped changing. (COSMIC-2 is a different mission on a different archive and is out of scope.) The COSMIC program's primary archive is UCAR's CDAAC; this tool crawls JPL's independent GENESIS processing of COSMIC-1, which is a separate archive with its own ASCII format.

Installation

pip install cosmic-crunch

This installs the cosmic-crunch command with two subcommands, get and convert. Python 3.10+ is required.

To hack on the package itself, install from a clone instead: pip install -e . (or pip install -e ".[test]" to run the test suite).

Usage

cosmic-crunch has a single entry point with two subcommands:

cosmic-crunch get      # crawl the GENESIS site and download ASCII files
cosmic-crunch convert  # convert downloaded ASCII files to netCDF4

cosmic-crunch get

usage: cosmic-crunch get [-h] [--base-url BASE_URL] [--logfile LOGFILE]
                         [--instrument INSTRUMENT] [--year_regex YEAR_REGEX]
                         [--date_regex DATE_REGEX] [--processes PROCESSES]
                         [--test] [--netcdf4] [--skip_empty] [--compress]
                         [--complevel COMPLEVEL]
flag description
--base-url Override the crawl root. Precedence: flag > COSMIC_CRUNCH_BASE_URL env var > built-in default (https://genesis.jpl.nasa.gov/ftp/glevels).
--instrument Instrument tree to crawl (substring filter). Defaults to cosmic (matches cosmic1–cosmic6); the same archive also serves champ, gracea, gracefo1, …
--year_regex Download only years matching this regular expression.
--date_regex Download only dates matching this regular expression.
--processes Worker processes for the multiprocessing pool (default 1).
--test Download a small subset (cosmic1, 2019-01-03, 10 files) as a smoke test.
--netcdf4 Convert the downloaded ASCII files to netCDF4 afterward.
--skip_empty Skip converting files whose data arrays are all empty.
--compress Losslessly zlib-compress the netCDF4 output (off by default — see Compression).
--complevel zlib level 1–9 (default 7); applies only with --compress.

Downloads are atomic and resumable: each file is streamed to a .part temporary and renamed into place only once complete, and files already present with a matching size are skipped — so an interrupted bulk pull can simply be re-run.

A successful run resembles:

$ cosmic-crunch get --year_regex=2006 --date_regex=2006-05-02 --netcdf4 --skip_empty --processes=4
Crawling all ./cosmic<#>/postproc: 100%|████████████████████| 6/6 [00:03<00:00,  1.61it/s]
Crawling all ./cosmic<#>/.../<year>: 100%|██████████████████| 6/6 [00:03<00:00,  1.59it/s]
Crawling all ./cosmic<#>/.../<date>: 100%|██████████████████| 3/3 [00:03<00:00,  1.17s/it]
Crawling all ./cosmic<#>/.../L2/<format>: 100%|█████████████| 4/4 [00:04<00:00,  1.09s/it]
Downloading data files: 100%|███████████████████████████████| 20/20 [00:26<00:00,  1.33s/it]
Converting ASCII to netCDF4: 100%|██████████████████████████| 20/20 [00:03<00:00,  6.32it/s]

ASCII to netCDF4 conversion summary:
 - Successful conversions: 17
 - Skipped conversions:    3
 - Conversion errors:      0
 - Total number of files:  20

Downloaded files are written under ./jpl_cosmic/<year>/<date>/txt/.

cosmic-crunch convert

usage: cosmic-crunch convert [-h] [--logfile LOGFILE] [--processes PROCESSES]
                             [--skip_empty] [--compress] [--complevel COMPLEVEL]
                             path [path ...]

Convert one or more ASCII .txt.gz files — or directories of them (crawled recursively) — to netCDF4. netCDF4 files are written into a sibling nc/ directory (mirroring the txt/ layout), or beside the source file otherwise.

cosmic-crunch convert ./jpl_cosmic/2006/ --skip_empty --processes=4

Use from Python

The conversion machinery is importable as a library:

from cosmic_crunch import convert

# Convert a directory tree (or a single file) of ASCII profiles:
convert.crawl_convert(["./jpl_cosmic/2006/"], processes=4)

# Or parse one ASCII file directly into a header dict and a dict of
# pandas DataFrames (one per profile):
header, data, is_empty = convert.read_cosmic_ascii_file(
    "20060501_0632co1_g35_2p6.L2.txt.gz"
)

The netCDF4 output nests each profile in a group (see the structure below), so name the group when reading it back — a bare xarray.open_dataset(path) shows only the global attributes:

import xarray as xr

profile = xr.open_dataset(
    "20060501_0632co1_g35_2p6.L2.nc", group="COSMIC1-Profile"
)

Compression

Output is uncompressed by default. --compress turns on lossless zlib compression (--complevel sets the level, default 7); stored values round-trip bit-identically either way.

Compression is opt-in because it does not reliably shrink these files. A COSMIC profile is many small float64 variables, and HDF5's per-variable chunk + filter overhead outweighs zlib's savings on short profiles — enabling compression can nearly double a small file. It only pays off for long profiles and bulk archival (measured crossover ≈ 1000 levels). Enable it when your profiles are large, and measure on a sample before committing an archive.

netCDF4 output structure

Each ASCII file becomes one netCDF4 file. The ASCII header becomes global attributes; each DataType profile becomes a group whose variables are that profile's columns, indexed by an Index dimension:

netcdf 20060501_0632co1_g35_2p6.L2 {
  // global attributes: ProductCreationTime, ShortName, DataSetID,
  //                     PlatformShortName, Receiver, ... (the ASCII header)

  group: COSMIC1-Profile {
    dimensions:  Index = <n> ;
    variables:   Height, Lat, Lon, Refractivity, Temperature, Pressure, WV Pressure ;
  }
  group: ECMWF-Profile {
    dimensions:  Index = <n> ;
    variables:   Height, Lat, Lon, Refractivity, Temperature, Pressure, WV Pressure ;
  }
}

Missing values in the ASCII data (-9999) are stored as NaN.

Security note

v1 parsed header values with eval(), allowing arbitrary code execution from a malicious or corrupted data file. v2 uses ast.literal_eval with a raw-string fallback — header parsing can no longer execute code.

Development

pip install -e ".[test]"
python -m pytest -q        # offline test suite (never touches the network)
ruff check .

License

MIT — see LICENSE. Built by Erick Shepherd.

Metadata

Release files for cosmic-crunch 2.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cosmic-crunch 2.1.2
File Size Uploaded
cosmic_crunch-2.1.2.tar.gz 48.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for cosmic-crunch 2.1.2
File Interpreter ABI Platform
cosmic_crunch-2.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 71.2 kB

Release files / cosmic_crunch-2.1.2.tar.gz

Download URL cosmic_crunch-2.1.2.tar.gz
Size 48.4 kB
Tags Source
SHA-256 checksum
How to use checksums
a15313c2153186c0c4c00cbe84501d2b8125748718986de203cd4817ca52a94e
BLAKE2b-256 checksum
How to use checksums
f2af713ee8e6d8e1f8833735ac1376d347c8990e6217b29b786da7d256eafc43
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 22, 2026.

Transparency log

Release files / cosmic_crunch-2.1.2-py3-none-any.whl

Download URL cosmic_crunch-2.1.2-py3-none-any.whl
Size 22.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4a9afa0d87fce871378fdc7f7fbc952f9c6313ca8be0f136749f9066f091c1f9
BLAKE2b-256 checksum
How to use checksums
7894510378f7c5124e48b39f06aeffbc411ea438e8687b19f9576a9b619e8d9b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 22, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

2.1.2 This release

2 release files

2.1.1

2 release files

2.1.0

2 release files

2.0.2

2 release files

2.0.1

2 release files

2.0.0

2 release 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