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.1.1.tar.gz (8.6 MB view details)

Uploaded Source

Built Distribution

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

xpunwrap-0.1.1-py3-none-any.whl (21.1 kB view details)

Uploaded Python 3

File details

Details for the file xpunwrap-0.1.1.tar.gz.

File metadata

  • Download URL: xpunwrap-0.1.1.tar.gz
  • Upload date:
  • Size: 8.6 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for xpunwrap-0.1.1.tar.gz
Algorithm Hash digest
SHA256 066916e87a348b2c795ed05b7ae9192b86b8fa734397ce2c596bbfcd08ada0ab
MD5 cb40d52c20be256c2bcc7f22810c6fa2
BLAKE2b-256 8853a02bf85be4a25e4f0ad1c38495707d92dda58edffebe24dc0a2399527c52

See more details on using hashes here.

Provenance

The following attestation bundles were made for xpunwrap-0.1.1.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.1.1-py3-none-any.whl.

File metadata

  • Download URL: xpunwrap-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 21.1 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.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 9e70ea6ec8749c2c52722465cd08fd240c75cb24e6dd1da375bf5de8c1830043
MD5 528209e02de5693757d3dd516c9488ef
BLAKE2b-256 3eb09749bec4d3ce780286506b581358fd1eb8e3a74bef4fc403be3cfec8ad6b

See more details on using hashes here.

Provenance

The following attestation bundles were made for xpunwrap-0.1.1-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