Skip to main content

whirlwind

Fast Rust-backed 2D InSAR phase unwrapping with Python bindings.

Whirlwind unwraps a complex interferogram and returns both unwrapped phase and connected-component labels. The NISAR comparison shows agreement with production SNAPHU on 2pi ambiguities, with lower runtime in the tested scenes.

The package is whirlwind-insar on PyPI and GitHub; it imports as whirlwind.

Quickstart

git clone https://github.com/scottstanie/whirlwind-insar.git
cd whirlwind-insar
pip install .

Source installs require Python 3.11+ and Rust.

Usage

import whirlwind as ww

unw, conncomp = ww.unwrap(igram, corr, nlooks=10.0, mask=mask)

igram is a complex wrapped interferogram, corr is coherence/correlation in [0, 1], and mask is optional with True for valid pixels.

For noisy scenes, coarsen the solve with downsample (it unwraps a coherently-averaged copy at the given factor to pick each block's 2π cycle, then maps the cycles back onto the full-resolution phase). nlooks stays the effective looks of your input corr — the down-look scaling is handled internally, so you do not raise it yourself:

unw, conncomp = ww.unwrap(igram, corr, nlooks=10.0, mask=mask, downsample=8)

CLI

The whirlwind CLI is at feature parity with the Python unwrap: every knob the Python API exposes (downsample, the bridge post-pass, persistent-scatterer interpolate, Goldstein filtering, and the connected-component cost controls) is available as a flag. Run whirlwind --help for the full list. There are no subcommands: unwrapping is the whole CLI, so all flags go directly to whirlwind (earlier releases used a whirlwind unwrap ... subcommand, which is still accepted with a deprecation note).

Install

Pick whichever is simplest for you:

  1. Prebuilt binary (no Python or toolchain). Download the archive for your platform from the latest release, unpack it, and run the whirlwind executable. A single self-contained binary - handy for MATLAB users driving it via system('whirlwind ...').

  2. With the Python package. The wheel ships a whirlwind console script (the same Rust CLI, entered in-process):

    uvx --from whirlwind-insar whirlwind --help   # zero-install try-out
    pip install whirlwind-insar                   # puts `whirlwind` on PATH
    
  3. From source with Cargo (needs the Rust toolchain):

    cargo install --path crates/whirlwind-cli --locked
    
  4. Docker (see below).

Run

whirlwind \
    --phase wrapped_phase.tif \
    --cor coherence.tif \
    --mask valid_mask.tif \
    --nlooks 10 \
    --out unwrapped_phase.tif

--phase is the wrapped phase in radians: a float32 TIFF, or a flat binary float32 file (see below). If you start from a complex-valued GeoTIFF, extract GDAL's PHASE derived subdataset first and pass that as --phase; --ifg is for flat complex64 rasters. The phase path reconstructs a unit-magnitude interferogram, so it does not preserve amplitude. --mask is optional; nonzero means valid. When --mask is omitted the CLI uses coherence > 0 (and igram != 0 with --ifg) as the default valid mask, matching the Python API. The CLI writes a SNAPHU-faithful connected-component label map by default next to --out (foo.conncomp.tif for TIFF, foo.unw.conncomp for flat .unw); use --conncomp PATH to choose the path or --no-conncomp to skip it.

Flat-binary formats (snaphu / ROI_PAC / isce2 / GAMMA)

Headerless flat-binary rasters from the classic pipelines work directly - no GDAL conversion needed:

# snaphu-style: complex64 .int + amp/cor .cc; width ("line length") on the CLI
whirlwind --ifg pair.int --cor pair.cc --cols 1024 --nlooks 10 --out pair.unw

# ROI_PAC / Stanford: geometry read from the <file>.rsc sidecar automatically
whirlwind --ifg 20150902_20150914.int --cor 20150902_20150914.cc \
    --nlooks 10 --out 20150902_20150914.unw

# isce2 stripmapStack / topsStack: the <file>.xml sidecars provide everything
whirlwind --ifg filt_fine.int --cor filt_fine.cor --nlooks 10 \
    --out filt_fine.unw

# GAMMA: big-endian; width from a .par/.off (or --cols + --big-endian)
whirlwind --ifg pair.diff --ifg-meta pair.off \
    --cor pair.cc --cor-meta pair.off --nlooks 10 --out-format float --out pair.unw
  • --ifg is the raw flat complex64 interferogram (snaphu COMPLEX_DATA, i.e. numpy.tofile() of a complex64 array), preserving amplitude for flat classic pipelines. --phase accepts float32 wrapped phase as TIFF or flat binary (snaphu FLOAT_DATA) and reconstructs unit-magnitude complex values. Exactly one of the two is given.
  • --cor may be single-band float32 (isce2 .cor, GAMMA .cc) or the two-band line-interleaved amplitude+correlation "rmg" layout (snaphu's default, ROI_PAC .cc): the band count is detected from the file size and the correlation is read from the second channel, exactly as snaphu does. --cor-format alt-sample covers snaphu's sample-interleaved variant.
  • --cols (alias --width) is snaphu's "line length" / ROI_PAC WIDTH; the row count always comes from the file size. A <file>.rsc or <file>.xml next to each input supplies it automatically (and, for isce2, the dtype, band count, scheme, and byte order). Use --ifg-meta, --phase-meta, or --cor-meta when the sidecar is not next to that input.
  • Output is chosen by extension (override with --out-format): .tif → TIFF; .unw → two-band amp+phase rmg (snaphu's default output layout); anything else → flat float32 phase. Conncomp follows the output style by default: u16 TIFF for TIFF outputs, or one-byte-per-pixel flat for flat outputs (the snaphu/isce2 convention). Flat outputs keep the input's byte order.
  • --mask also accepts snaphu-style flat byte masks (nonzero = valid).

Connected components default to the SNAPHU-faithful ambiguity-wiggle grow (--conncomp-algorithm snaphu) with --conncomp-min-coherence auto, which labels 0 any pixel below a coherence floor of 0.32/sqrt(nlooks) (0.08 at 16 looks). Set --conncomp-min-coherence off to label every reliably unwrapped pixel, or pass a number for a fixed cutoff. The legacy linear grow is available with --conncomp-algorithm linear.

For noisy scenes, coarsen the solve with --downsample (as in the Python API); the integration-component --no-bridge-able re-leveling pass runs by default:

whirlwind --phase wrapped_phase.tif --cor coherence.tif \
    --mask valid_mask.tif --nlooks 10 --downsample 8 \
    --out unwrapped_phase.tif

The CLI is pure Rust (no GDAL), so it also runs from a container. Pull the prebuilt image (published to the GitHub Container Registry by CI), or build it locally:

docker pull ghcr.io/scottstanie/whirlwind-insar:main   # prebuilt, or:
docker build -t ghcr.io/scottstanie/whirlwind-insar .  # build locally

docker run --rm -v "$PWD:/data" ghcr.io/scottstanie/whirlwind-insar \
    --phase /data/wrapped.tif --cor /data/cor.tif --nlooks 10 \
    --out /data/unw.tif

Dolphin

Dolphin can select Whirlwind as an unwrap method:

dolphin unwrap --unwrap-options.unwrap-method whirlwind ...

See the Dolphin docs for the rest of the Dolphin workflow.

Development

uv sync
uv run maturin develop --release
uv run pytest python/tests
cargo test --workspace

More

Repository Layout

  • python/whirlwind: Python API.
  • crates/whirlwind-core: Rust algorithms.
  • crates/whirlwind-py: PyO3 bindings.
  • crates/whirlwind-cli: CLI binary.
  • docs: reference docs.
  • scripts: benchmarks and development utilities.

License

Licensed under either the BSD 3-Clause License or the Apache License, Version 2.0, at your option. See LICENSE.

Download files

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

Source Distribution

whirlwind_insar-0.4.0.tar.gz (249.3 kB view details)

Uploaded Source

Built Distributions

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

whirlwind_insar-0.4.0-cp311-abi3-win_amd64.whl (1.6 MB view details)

Uploaded CPython 3.11+Windows x86-64

whirlwind_insar-0.4.0-cp311-abi3-musllinux_1_2_x86_64.whl (2.0 MB view details)

Uploaded CPython 3.11+musllinux: musl 1.2+ x86-64

whirlwind_insar-0.4.0-cp311-abi3-musllinux_1_2_aarch64.whl (1.7 MB view details)

Uploaded CPython 3.11+musllinux: musl 1.2+ ARM64

whirlwind_insar-0.4.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.8 MB view details)

Uploaded CPython 3.11+manylinux: glibc 2.17+ x86-64

whirlwind_insar-0.4.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.5 MB view details)

Uploaded CPython 3.11+manylinux: glibc 2.17+ ARM64

whirlwind_insar-0.4.0-cp311-abi3-macosx_11_0_arm64.whl (1.4 MB view details)

Uploaded CPython 3.11+macOS 11.0+ ARM64

whirlwind_insar-0.4.0-cp311-abi3-macosx_10_12_x86_64.whl (1.7 MB view details)

Uploaded CPython 3.11+macOS 10.12+ x86-64

File details

Details for the file whirlwind_insar-0.4.0.tar.gz.

File metadata

  • Download URL: whirlwind_insar-0.4.0.tar.gz
  • Upload date:
  • Size: 249.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for whirlwind_insar-0.4.0.tar.gz
Algorithm Hash digest
SHA256 51114c43b14a2b5d3293c2ad7aa57d87192c72158973e2faf33cb6866adb1620
MD5 80a55ab3e8a7f9e081ef82aa0726fc68
BLAKE2b-256 22cd49b1a6cfd173bb58aae7da87818cf6048dd2f12f54ec6bb8a31a17b453d2

See more details on using hashes here.

Provenance

The following attestation bundles were made for whirlwind_insar-0.4.0.tar.gz:

Publisher: release.yml on scottstanie/whirlwind-insar

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

File details

Details for the file whirlwind_insar-0.4.0-cp311-abi3-win_amd64.whl.

File metadata

File hashes

Hashes for whirlwind_insar-0.4.0-cp311-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 45f65389bab0f3ff3d2af4647cd3626f1bc84b9f689a07d1bc5ca4521be0e5ec
MD5 a551bda8a99c5d69cab2a996cabc33ca
BLAKE2b-256 c453838980f222072c03d62cdc4bb2ba7408f0dcffb6d9506937ca72fea31daa

See more details on using hashes here.

Provenance

The following attestation bundles were made for whirlwind_insar-0.4.0-cp311-abi3-win_amd64.whl:

Publisher: release.yml on scottstanie/whirlwind-insar

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

File details

Details for the file whirlwind_insar-0.4.0-cp311-abi3-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for whirlwind_insar-0.4.0-cp311-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 6e293c0a79b9b1f6cd916458d389ecfc0aac06ca62da79e25e50b4498ed8c7fc
MD5 40d017bfaf146f86a2bb54b8cbca4882
BLAKE2b-256 8f29bfcfae0c798a5bd21a2b048472f96f872c8625ed320a20dd10d05b730602

See more details on using hashes here.

Provenance

The following attestation bundles were made for whirlwind_insar-0.4.0-cp311-abi3-musllinux_1_2_x86_64.whl:

Publisher: release.yml on scottstanie/whirlwind-insar

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

File details

Details for the file whirlwind_insar-0.4.0-cp311-abi3-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for whirlwind_insar-0.4.0-cp311-abi3-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 48b71d374027c658f055c45cf04d0a6d388d0ce9769dd1f188f1a300721946ac
MD5 f933c0db685424a6abb22baccb6efb0d
BLAKE2b-256 fe48a587104945b877d0dc5cc3b6b8e8e7bf056d7196714ef711ec56d80334ae

See more details on using hashes here.

Provenance

The following attestation bundles were made for whirlwind_insar-0.4.0-cp311-abi3-musllinux_1_2_aarch64.whl:

Publisher: release.yml on scottstanie/whirlwind-insar

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

File details

Details for the file whirlwind_insar-0.4.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for whirlwind_insar-0.4.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 5caaf341ef2ea69969624c0342083eff22b98ee93f9a3b48935c7ec1ed103c8b
MD5 38da1d0b2ebc7aa0413dbb8f0beb4a91
BLAKE2b-256 400023367c5c062350e91f7ffc4e26ac62cb262baa365713f9a49d5d5061d15f

See more details on using hashes here.

Provenance

The following attestation bundles were made for whirlwind_insar-0.4.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on scottstanie/whirlwind-insar

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

File details

Details for the file whirlwind_insar-0.4.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for whirlwind_insar-0.4.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 0a2102a541e1750d9321c4c400b5cf7fd33a8dd57f399876650e3de618581203
MD5 3fdbd588c7b54dca60ac25eb14d7162c
BLAKE2b-256 a4519c8286863e7e1dec1bb1e4b9ef40f6f29c790286b51d259699db6ce9d4c7

See more details on using hashes here.

Provenance

The following attestation bundles were made for whirlwind_insar-0.4.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on scottstanie/whirlwind-insar

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

File details

Details for the file whirlwind_insar-0.4.0-cp311-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for whirlwind_insar-0.4.0-cp311-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 98fc990a5c1a600aea950d51e4170a5029444f61e5b470118112e1d73cafbc4e
MD5 0119372ef30c7954df84f65987e0076c
BLAKE2b-256 1ef7348533ecb3a6582002c765d296a129244274ced78e23694fcb12899f3651

See more details on using hashes here.

Provenance

The following attestation bundles were made for whirlwind_insar-0.4.0-cp311-abi3-macosx_11_0_arm64.whl:

Publisher: release.yml on scottstanie/whirlwind-insar

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

File details

Details for the file whirlwind_insar-0.4.0-cp311-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for whirlwind_insar-0.4.0-cp311-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 174fd46387faf1954449fba9de458ce4a0ddc537729c4e0aafcbe092341db0b2
MD5 c2970eae84eeb1fc7e6a43a5eed1a2dd
BLAKE2b-256 a5a73fe48c77b3cd803abe5c87ff28d751c46f0b94630d0f53b76a7a273806d7

See more details on using hashes here.

Provenance

The following attestation bundles were made for whirlwind_insar-0.4.0-cp311-abi3-macosx_10_12_x86_64.whl:

Publisher: release.yml on scottstanie/whirlwind-insar

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