Phase unwrapping algorithms which are CPU and GPU agnostic
Project description
xpUnwrap
Phase Unwrapping on GPU (and CPU), with Python
There are many phase unwrapping algorithms out there. Many are implemented in CUDA, C++ etc. I haven't yet found any algorithm that interfaces easily with Python via the wonderful GPU-based package CuPy. Please inform me if you know of one that is open-source.
This package aims to make GPU-based phase unwrapping in Python seamless. If you don't have a GPU, don't worry, all the code works on the CPU (albeit slower).
What does "xp" stand for?
The xp in xpUnwrap references several things:
- CuPy's agnostic code idea
where
cpis for cupy andnpis for numpy. - the "G" in GPU and "C" in CPU.
- the "Q" from QPI (Quantitative Phase Imaging) e.g., from the sister package qpretrieve.
Installation
# if you have the CUDA Toolkit version 12x use:
pip install xpunwrap[cupy-cuda12x]
# if you have the CUDA Toolkit version 13x use:
pip install xpunwrap[cupy-cuda13x]
# to install and just use on the CPU, just don't use any optional dependencies:
pip install xpunwrap
# to also use skimage's unwrap (CPU-only):
pip install xpunwrap[scikit-image]
# for faster CPU Fourier transforms via pyFFTW:
pip install xpunwrap[FFTW]
On the CPU backend, xpunwrap automatically uses pyFFTW for the Fourier
transforms in the least-squares solvers when it is installed, falling back to
NumPy otherwise. On the GPU backend, CuPy's FFT is always used.
Compatible Phase Retrieval and Numerical Refocusing GPU packages
In the same group on GitHub, we have two other packages that work seamlessy
with xpunwrap.
- Phase Retrieval that works on CPU and GPU: qpretrieve
- Numerical Refocussing that works on CPU and GPU: nrefocus
- If you are looking for a file format that can also work with the GPU, try out zarr-python
Documentation and Citations
Check out the Documentation and Examples here: https://xpunwrap.readthedocs.io/
Using xpunwrap
There are several phase unwrapping algorithms to choose from:
algo_ls_poisson: Least-squares Poisson solveralgo_ls_poisson_pg: Least-squares unwrapping with periodic gradient enforcementalgo_ls_weighted: Weighted least-squares unwrapping with border maskingalgo_skimage_unwrap: Scikit-Image's Path Following algorithm (Herraez et al.) is included for comparison. It only works on the CPU, as it is not suitable for use with GPU.
"""
Field retrieval (qpretrieve) and phase unwrapping (xpunwrap) on GPU.
"""
import matplotlib.pyplot as plt
import numpy as np
import qpretrieve
import xpunwrap
# Force GPU backend for both libraries.
qpretrieve.set_ndarray_backend("cupy")
xpunwrap.set_ndarray_backend("cupy")
xp = xpunwrap.get_ndarray_backend()
fft_interface = qpretrieve.fourier.FFTFilterCupy
edata = np.load("./data/hologram_cell.npz")
holo = qpretrieve.OffAxisHologram(edata["data"], fft_interface)
bg = qpretrieve.OffAxisHologram(edata["bg_data"], fft_interface)
holo.run_pipeline(filter_name="disk", filter_size=1 / 2, scale_to_filter=True)
bg.process_like(holo)
phase_wrapped = xp.asarray(holo.phase - bg.phase).astype(xp.float32)
# Unwrap the phase with all available algorithms
outputs = {}
for algo_name, algo in xpunwrap.algos_available().items():
outputs[algo_name] = algo(phase_wrapped)
skimage_out = outputs.get("algo_skimage_unwrap", None)
if skimage_out is not None:
outputs_no_skimage = {k: v for k, v in outputs.items() if k != "algo_skimage_unwrap"}
else:
outputs_no_skimage = outputs
# plot the wrapped and unwrapped phases
plt.style.use("dark_background")
fig, axes = plt.subplots(2, 3, figsize=(8, 6))
fig.suptitle("Field Retrieval + Phase Unwrapping (GPU)", fontsize=18)
axes = axes.flatten(order="F")
axes[0].imshow(phase_wrapped.get()[0])
axes[0].set_title("Wrapped Phase")
# With column-major flattening, bottom-right is index 5.
skimage_ax = axes[5]
# Fill remaining non-skimage algorithms first (slots 1..4).
plot_slots = [2, 3, 4]
for slot, (algo_name, arr) in zip(plot_slots, outputs_no_skimage.items()):
ax = axes[slot]
ax.imshow(arr.get()[0])
ax.set_title(f"Unwrapped\n{algo_name}")
if skimage_out is not None:
skimage_ax.imshow(skimage_out.get()[0])
skimage_ax.set_title("Unwrapped (CPU-only)\nalgo_skimage_unwrap")
else:
skimage_ax.text(0.5, 0.5, "skimage missing", ha="center", va="center")
skimage_ax.set_title("Unwrapped\nalgo_skimage_unwrap")
for ax in axes:
ax.set_axis_off()
plt.tight_layout(w_pad=4.5)
# plt.savefig("gpu_field_retr_phase_unwrapping.png")
plt.show()
Developers
Install everything you need with (for example for cuda12x)
pip install -e .[cupy-cuda12x] --group dev
Run the unit tests with pytest
pip install --group tests
pytest tests
Build docs with sphinx
pip install --group docs
cd docs
sphinx-build . _build
Check the docs locally by opening docs/_build/index.html file in your browser.
Package management with uv
If you wish to use uv to handle package management, then you need to first
install uv and then run:
For example, for the optional cupy-cuda12x
uv sync -active --all-groups --all-extras
Which should install all dev dependencies.
Other phase unwrapping packages
Here are several phase unwrapping packages that exist in Python:
- https://github.com/blakedewey/phase_unwrap (CPU)
- Scikit-image (CPU)
Use of AI
This package used Codex (mostly 5.4-Mini) to translate the source citations (see documentation website) into Python code, as well as the mathematical derivations. All code and documents were then human-verified and verified with Claude Opus, and tested against known input data.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file xpunwrap-0.0.0.tar.gz.
File metadata
- Download URL: xpunwrap-0.0.0.tar.gz
- Upload date:
- Size: 18.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
177b9e691fed9d747a6f8479de13b0cb2d1bacbc4a9328005084b2cca5a4bad8
|
|
| MD5 |
7b57f8983dfeb98e044be2d47b7d21bb
|
|
| BLAKE2b-256 |
a98ac6446c38e9bbff31aaedd12eb8c1adfb22d8ec86b6b8a9ca216d78270fcc
|
Provenance
The following attestation bundles were made for xpunwrap-0.0.0.tar.gz:
Publisher:
deploy_pypi.yml on RI-imaging/xpunwrap
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
xpunwrap-0.0.0.tar.gz -
Subject digest:
177b9e691fed9d747a6f8479de13b0cb2d1bacbc4a9328005084b2cca5a4bad8 - Sigstore transparency entry: 2035372718
- Sigstore integration time:
-
Permalink:
RI-imaging/xpunwrap@ddd17cddd4cd244c9ea1c8b1996256dcb823b014 -
Branch / Tag:
refs/tags/0.1.0 - Owner: https://github.com/RI-imaging
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
deploy_pypi.yml@ddd17cddd4cd244c9ea1c8b1996256dcb823b014 -
Trigger Event:
push
-
Statement type:
File details
Details for the file xpunwrap-0.0.0-py3-none-any.whl.
File metadata
- Download URL: xpunwrap-0.0.0-py3-none-any.whl
- Upload date:
- Size: 19.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
744c466910297396163754e561d2f26117a07dd98f78d40e22450cdf8526a4b9
|
|
| MD5 |
b06e6e5eb098e15b85592276d79cadea
|
|
| BLAKE2b-256 |
d6d2fd000330e5a455a3a67c31854dd2b2ce35c9e93c868703715ffab445b6be
|
Provenance
The following attestation bundles were made for xpunwrap-0.0.0-py3-none-any.whl:
Publisher:
deploy_pypi.yml on RI-imaging/xpunwrap
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
xpunwrap-0.0.0-py3-none-any.whl -
Subject digest:
744c466910297396163754e561d2f26117a07dd98f78d40e22450cdf8526a4b9 - Sigstore transparency entry: 2035372847
- Sigstore integration time:
-
Permalink:
RI-imaging/xpunwrap@ddd17cddd4cd244c9ea1c8b1996256dcb823b014 -
Branch / Tag:
refs/tags/0.1.0 - Owner: https://github.com/RI-imaging
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
deploy_pypi.yml@ddd17cddd4cd244c9ea1c8b1996256dcb823b014 -
Trigger Event:
push
-
Statement type: