Skip to main content

Phase unwrapping algorithms which are CPU and GPU agnostic

Project description

XPUnwrap

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 cp is for cupy and np is 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 solver
  • algo_ls_poisson_pg: Least-squares unwrapping with periodic gradient enforcement
  • algo_ls_weighted: Weighted least-squares unwrapping with border masking
  • algo_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()

gpu_field_retr_phase_unwrapping.png

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:

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


Download files

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

Source Distribution

xpunwrap-0.0.0.tar.gz (18.0 kB view details)

Uploaded Source

Built Distribution

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

xpunwrap-0.0.0-py3-none-any.whl (19.5 kB view details)

Uploaded Python 3

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

Hashes for xpunwrap-0.0.0.tar.gz
Algorithm Hash digest
SHA256 177b9e691fed9d747a6f8479de13b0cb2d1bacbc4a9328005084b2cca5a4bad8
MD5 7b57f8983dfeb98e044be2d47b7d21bb
BLAKE2b-256 a98ac6446c38e9bbff31aaedd12eb8c1adfb22d8ec86b6b8a9ca216d78270fcc

See more details on using hashes here.

Provenance

The following attestation bundles were made for xpunwrap-0.0.0.tar.gz:

Publisher: deploy_pypi.yml on RI-imaging/xpunwrap

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

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

Hashes for xpunwrap-0.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 744c466910297396163754e561d2f26117a07dd98f78d40e22450cdf8526a4b9
MD5 b06e6e5eb098e15b85592276d79cadea
BLAKE2b-256 d6d2fd000330e5a455a3a67c31854dd2b2ce35c9e93c868703715ffab445b6be

See more details on using hashes here.

Provenance

The following attestation bundles were made for xpunwrap-0.0.0-py3-none-any.whl:

Publisher: deploy_pypi.yml on RI-imaging/xpunwrap

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