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-reliability 0 (the calibration-free wiggle test). Raise --conncomp-reliability or use --conncomp-min-coherence when you want a more conservative low-coherence coverage mask. The legacy linear grow remains 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.3.1.tar.gz (248.4 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.3.1-cp311-abi3-win_amd64.whl (1.6 MB view details)

Uploaded CPython 3.11+Windows x86-64

whirlwind_insar-0.3.1-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.3.1-cp311-abi3-musllinux_1_2_aarch64.whl (1.7 MB view details)

Uploaded CPython 3.11+musllinux: musl 1.2+ ARM64

whirlwind_insar-0.3.1-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.3.1-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.3.1-cp311-abi3-macosx_11_0_arm64.whl (1.4 MB view details)

Uploaded CPython 3.11+macOS 11.0+ ARM64

whirlwind_insar-0.3.1-cp311-abi3-macosx_10_12_x86_64.whl (1.6 MB view details)

Uploaded CPython 3.11+macOS 10.12+ x86-64

File details

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

File metadata

  • Download URL: whirlwind_insar-0.3.1.tar.gz
  • Upload date:
  • Size: 248.4 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.3.1.tar.gz
Algorithm Hash digest
SHA256 05910cc2bfa90f0f8e397d2438e6967911b49b4725ebff73aad5ca0230123f74
MD5 2edcb273f14860afd725f3a03787b02b
BLAKE2b-256 7567c6282e2cba874d89ae51ef6a339ed3631c2976fa54d687183ef1d674f0c7

See more details on using hashes here.

Provenance

The following attestation bundles were made for whirlwind_insar-0.3.1.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.3.1-cp311-abi3-win_amd64.whl.

File metadata

File hashes

Hashes for whirlwind_insar-0.3.1-cp311-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 ab7a023b31d2e515ee67f4dfcece37f485923ae4c9265deec87da0a9a2e46e62
MD5 753800c450591f5e2066929877679e9a
BLAKE2b-256 98a408a20cfc46313fbb6395a3ef55bb2050252bd43ed50ff289744e318c1108

See more details on using hashes here.

Provenance

The following attestation bundles were made for whirlwind_insar-0.3.1-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.3.1-cp311-abi3-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for whirlwind_insar-0.3.1-cp311-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 cd98709f4d4d9c605d9c6cd54d24bbe812c29a2e22e6e7ae14ced19fc03d8418
MD5 8efa1dc145a6c3114b6175c1c92f7cc8
BLAKE2b-256 783a939ea2ee5ca0b999193ef856b708727ae6aefa923995a3321780ea4dab16

See more details on using hashes here.

Provenance

The following attestation bundles were made for whirlwind_insar-0.3.1-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.3.1-cp311-abi3-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for whirlwind_insar-0.3.1-cp311-abi3-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 794473b5a351438d133077246fc6b63b9d1fd6ed0430fd2d31f8e6802dc88701
MD5 45cb2599a889fe02fe320d7f7bee119c
BLAKE2b-256 50979547a820df57f3434e866ba97c0438c9b9210061746570fc438f9039acc2

See more details on using hashes here.

Provenance

The following attestation bundles were made for whirlwind_insar-0.3.1-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.3.1-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for whirlwind_insar-0.3.1-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 8af0fc96dbb9a55cbcfa5e50fed9d912f1877db1e8d22d5665db274abfb566ad
MD5 fd13ae5f182d68d8e8e2cd289b412293
BLAKE2b-256 ac5a8d75da068a70ecb4c4da6ed300aba1082ca1fb2c1a41738a145bea25ad11

See more details on using hashes here.

Provenance

The following attestation bundles were made for whirlwind_insar-0.3.1-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.3.1-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for whirlwind_insar-0.3.1-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 7ee5fe4590496aeef73bebf682d82a6af6ecf9b7fe623e3c75b19862e3ca4fc7
MD5 58d1d5fa5afc6b05ce3721d9927379b1
BLAKE2b-256 cc5d065b4350db3869b580edb8892cd5e041965fa68a538871bbe891ba6ed18b

See more details on using hashes here.

Provenance

The following attestation bundles were made for whirlwind_insar-0.3.1-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.3.1-cp311-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for whirlwind_insar-0.3.1-cp311-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 f98053da0d6bfdb7b7b63b08b90482e37e17ff607a25c337b99302dbb9132716
MD5 00dab1252d9a0340f2ee0001f19151c9
BLAKE2b-256 b9149811d61d32fb5c779fb082b01806dd9180ab79e4f599dea5d2de7a26f4f1

See more details on using hashes here.

Provenance

The following attestation bundles were made for whirlwind_insar-0.3.1-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.3.1-cp311-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for whirlwind_insar-0.3.1-cp311-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 1d2d882c9333e0dc10e012090b668abdbdc708b3af8ac91b0d82a76be149fe90
MD5 81131dc438f0598d53d2fca62790f852
BLAKE2b-256 9ee1126b7eaf69e1390d43f6a7fea1202d4b97a3045c058382c2a62d67d53811

See more details on using hashes here.

Provenance

The following attestation bundles were made for whirlwind_insar-0.3.1-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