⚠️ Important Note
This project is actively under development. While the core functionality is production-ready and thoroughly tested, some advanced features are still being refined.
Physics-informed deep learning for InSAR phase unwrapping.
Why this exists · How it works · Install · Quickstart · Notebooks · Architecture · Citation
pyunwrap-insar unwraps Interferometric Synthetic Aperture Radar (InSAR) phase — the
core measurement behind satellite-based ground-deformation monitoring — using a
physics-informed U-Net that predicts an integer ambiguity map, not the
unwrapped phase itself. The rewrapping identity is enforced by construction,
so the model is structurally incapable of producing an output that
contradicts the observed wrapped phase; it can only be wrong about how many
2π cycles were missed, never about the physics of wrapping.
Why this exists
Every classical phase-unwrapping algorithm — branch-cut methods, minimum-cost
flow (the approach behind SNAPHU, the field's long-standing reference tool),
Goldstein's algorithm — rests on one assumption: that the true phase gradient
between adjacent pixels never exceeds π radians (the Nyquist/Itoh
condition). Two situations break that assumption in practice:
- Low coherence. Vegetation, water, and temporal decorrelation add near-random phase noise. Once the local gradient becomes unreliable, branch-cut and MCF methods don't just get that one pixel wrong — they propagate the error across the connected region downstream of it.
- Steep deformation gradients. Earthquakes, volcanic inflation, and
mining subsidence can produce genuine phase gradients that exceed
πradians per pixel near the source. No amount of algorithmic cleverness recovers this from the wrapped phase alone without an external prior — which is exactly the gap a learned model can fill.
pyunwrap targets both regimes directly, and does so without inheriting the
most common failure mode of naive deep-learning approaches to this problem:
regressing the unwrapped phase directly gives a network no reason to respect
wrap(prediction) == observed_phase. Predicting the integer ambiguity
instead makes that identity a mathematical guarantee, not a hope.
How it works
AmbiguityNet outputs a continuous ambiguity prediction, rounds it via a
straight-through estimator, and reconstructs phase directly:
φ̂ = ψ + 2π · round(k̂), k̂ ∈ ℤ
| Approach | Failure mode |
|---|---|
Regress φ directly |
Nothing constrains wrap(prediction) == ψ; the network can output any real value |
Predict k (this package) |
wrap(ψ + 2π·round(k̂)) == ψ holds by construction — the network only has to get the integer cycle count right |
That single design decision shapes everything downstream: training uses a
physics-informed loss with a component that's provably near-zero regardless
of prediction quality (documented explicitly, not hidden — see
pyunwrap/models/losses.py); tiled inference
merges the integer ambiguity map across overlapping patches, never the
phase itself, because averaging phase directly across a tile boundary can
silently produce a value that satisfies no physical interferogram.
Key features
Synthetic data engine (pyunwrap.synthetic)
— Gaussian subsidence bowls, a from-scratch Okada (1985) rectangular fault
dislocation model, a Mogi (1958) volcanic point source, DEM-driven
topographic phase, Kolmogorov-spectrum atmospheric turbulence, orbital
ramps, coherence-dependent decorrelation noise, and a pseudo-real strategy
that rewraps real L-band (ALOS-2) unwrapped phase into simulated C-band data
to help bridge the sim-to-real gap.
AmbiguityNet (pyunwrap.models)
— a ResNet-34-encoder U-Net with a dual head: the integer ambiguity map via
a straight-through-estimator rounding layer, and an auxiliary residue-
probability map for uncertainty. Trained with a four-component
physics-informed loss (ambiguity regression, re-wrap consistency,
coherence-weighted smoothness, ambiguity-map residue penalty).
Curriculum training (pyunwrap.training)
— a three-stage curriculum (high-coherence/low-gradient → moderate →
full difficulty), optional SNAPHU pseudo-ground-truth fine-tuning on real
data, AdamW with warmup/cosine annealing, and TensorBoard logging.
Production inference (pyunwrap.inference)
— tiled processing of arbitrarily large interferograms with edge-aware,
residue-probability-weighted smart merging of the ambiguity map, Monte
Carlo Dropout uncertainty, and an ONNX Runtime → OpenVINO backend fallback
chain for deployment without a PyTorch dependency.
Scientific analytics (pyunwrap.analytics)
— Goldstein-style residue detection and clustering, Nyquist
gradient-violation mapping, error-distribution statistics, Grad-CAM and
Integrated-Gradients explainability, and uncertainty-calibration
reliability diagrams.
Visualization & reporting (pyunwrap.visualization)
— interactive Plotly 3D phase surfaces and heatmaps, a folium
swipe-comparison map, and a self-contained, Jinja2-templated HTML report
tying every stage together.
Architecture
InSARSyntheticGenerator ──┐ real GeoTIFFs
│ (wrapped, coherence, amplitude)
▼ │
tiling + normalization ▼
│ tiled inference
▼ via PhaseUnwrapper
InSARTileDataset │
│ │
▼ ▼
Trainer.fit() ──── AmbiguityNet ──── smart ambiguity-map
(curriculum, (this is the merging (never
physics loss) same model) the phase)
│
▼
unwrapped phase +
analytics + report
See docs/architecture.md for the full
module-by-module reference and a longer explanation of the physics
invariant every stage is built around.
Installation
git clone https://github.com/yourusername/pyunwrap.git
cd pyunwrap
pip install -e .
Optional extras, installed as needed:
| Extra | Adds | Use case |
|---|---|---|
dev |
pytest, pytest-cov, black, ruff, mypy |
Development, testing, linting |
maps |
folium, leafmap |
Interactive map visualization |
deploy |
openvino, onnx, onnxconverter-common, onnxscript |
ONNX export, OpenVINO inference |
notebooks |
jupyter, ipykernel |
Running the example notebooks |
pip install -e ".[dev,maps,deploy,notebooks]" # everything
Quickstart
from pyunwrap.synthetic.generator import InSARSyntheticGenerator
from pyunwrap.models.ambiguity_net import AmbiguityNet
from pyunwrap.inference.unwrapper import PhaseUnwrapper
# Generate a synthetic training sample (Mogi volcanic source deformation).
gen = InSARSyntheticGenerator(size=256, seed=42)
sample = gen.generate_sample(deformation_type="mogi")
# Run tiled inference on a real interferogram with a trained model.
model = AmbiguityNet(pretrained=False, k_max=10.0) # or load your own checkpoint
unwrapper = PhaseUnwrapper(model=model, device="cuda")
result = unwrapper.unwrap(
wrapped_phase_path="data/wrapped_phase.tif",
coherence_path="data/coherence.tif",
amplitude_path="data/amplitude.tif",
tile_size=512, overlap=64,
generate_report=True,
)
result.save_geotiff("unwrapped_output.tif")
Training a model end to end:
pyunwrap-train \
--train-hdf5 train_tiles.h5 --val-hdf5 val_tiles.h5 \
--epochs 60 --warmup-epochs 5 \
--finetune-hdf5 snaphu_pseudo_gt.h5 --finetune-start-epoch 55 \
--out-dir runs/pyunwrap_v1
Notebooks
Two notebooks in notebooks/ walk through the package
hands-on, checked in pre-executed with real outputs so they're readable
without running anything:
01_training_pipeline.ipynb— the complete training chain: synthetic data, tiling,AmbiguityNet+Trainer, training curves, and predicted-vs-ground-truth comparison.02_full_pipeline.ipynb— the complete end-to-end chain: a deformation-model gallery, tiling and augmentation visualized, a full curriculum training run with every loss component plotted, tiled inference on real GeoTIFFs, residue/Nyquist/error analytics, Grad-CAM and Integrated-Gradients explainability, 3D and interactive-map visualization, ONNX deployment with a numerical PyTorch-vs-ONNX agreement check, and the final HTML report.
pip install -e ".[dev,maps,notebooks]"
jupyter notebook notebooks/
Testing
pytest -m "not slow" # fast unit + integration tests
pytest # full suite, including the end-to-end
# synthetic → train → infer → report test
pytest --cov=pyunwrap --cov-report=term-missing
The suite includes known-answer physics tests (e.g. residue detection is
checked against a hand-constructed phase vortex with an exact, known
topological charge — not just "runs without crashing") and a tile-merging
regression test that asserts tiled-and-merged inference is numerically
identical to a whole-image pass, directly targeting the class of bug where
tile boundaries silently corrupt the output. See
CONTRIBUTING.md for the full breakdown and development
setup.
Project status
Early-stage and actively developed. The pipeline — synthetic data
generation, training, tiled inference, analytics, and reporting — is
implemented and tested end to end, but no pretrained weights ship yet;
from_pretrained() downloads from a Zenodo record you supply, and the
example notebooks train small demo models from scratch rather than loading
a benchmarked checkpoint. Monte Carlo Dropout uncertainty is currently a
no-op (AmbiguityNet has no nn.Dropout layers yet, only BatchNorm) —
tracked as a known gap, not hidden. APIs may change between minor versions
until 1.0. See CHANGELOG.md for what's landed so far.
Relationship to the wider EO stack
pyunwrap works standalone, but is designed to eventually sit downstream of
pygeofetch (interferogram acquisition/formation) and alongside
ps-gnn (persistent scatterer identification) in a broader open-source
InSAR processing stack.
Citation
If pyunwrap is useful in your research, please cite it:
@software{pyunwrap2026,
title = {pyunwrap: Physics-Informed Deep Learning for InSAR Phase Unwrapping},
author = {{pyunwrap contributors}},
year = {2026},
url = {https://doi.org/10.5281/zenodo.22209219},
note = {Version 0.1.1}
}
References
- Goldstein, R. M., Zebker, H. A., & Werner, C. L. (1988). Satellite radar interferometry: Two-dimensional phase unwrapping. Radio Science, 23(4).
- Itoh, K. (1982). Analysis of the phase unwrapping algorithm. Applied Optics, 21(14).
- Chen, C. W., & Zebker, H. A. (2001). Two-dimensional phase unwrapping with use of statistical models for cost functions in nonlinear optimization (SNAPHU). JOSA A, 18(2).
- Okada, Y. (1985). Surface deformation due to shear and tensile faults in a half-space. Bulletin of the Seismological Society of America, 75(4).
- Mogi, K. (1958). Relations between the eruptions of various volcanoes and the deformations of the ground surfaces around them. Bulletin of the Earthquake Research Institute, 36.
Contributing
Contributions are welcome — bug reports, documentation, new deformation
models, or core improvements. See CONTRIBUTING.md for
development setup, test/lint conventions, and the design principles worth
knowing before touching the physics-critical modules.
License
Metadata
Release files for pyunwrap-insar 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| pyunwrap_insar-0.1.1.tar.gz | 90.4 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pyunwrap_insar-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 171.7 kB
Release files / pyunwrap_insar-0.1.1.tar.gz
| Download URL | pyunwrap_insar-0.1.1.tar.gz |
|---|---|
| Size | 90.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6ae0a4d38926f1605aa87df4bf8e71717fbdd4a38b69ba161494ec741b4d18f9
|
|
BLAKE2b-256 checksum How to use checksums |
2abcee79bd087a806e6f13aa90406138ef25b31b4653fa223f044caf05ca7f0f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.6
|
Release files / pyunwrap_insar-0.1.1-py3-none-any.whl
| Download URL | pyunwrap_insar-0.1.1-py3-none-any.whl |
|---|---|
| Size | 81.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e9fc7683362e902f16bb51676702500d674d15e2028795812cb8f28ee7e9d810
|
|
BLAKE2b-256 checksum How to use checksums |
6e5a65db31380f0b919b8ae8ccc75a36e6961e02a049b7ac9d982cc242ed752c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.6
|
Security for pyunwrap-insar 0.1.1
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.