Skip to main content

Python bindings for kwavers ultrasound simulation library

Project description

kwavers-python: Python Bindings for Kwavers

License: MIT Python 3.8+ Rust

Python bindings for the kwavers ultrasound simulation library, providing a k-Wave-compatible API for acoustic wave propagation simulations.

Overview

The kwavers-python distribution imports as pykwavers and brings the performance and safety of Rust to Python-based acoustic simulations:

  • ๐Ÿš€ High Performance: Rust-backed numerical kernels with zero-copy numpy integration
  • ๐Ÿ”’ Memory Safe: No segfaults, data races, or undefined behavior
  • ๐ŸŽฏ k-Wave Compatible: Drop-in replacement API for easy comparison and migration
  • ๐Ÿงช Validated: Direct comparison framework with k-Wave/k-wave-python
  • ๐ŸŒ Cross-Platform: Windows, Linux, macOS support via PyO3

Architecture

Following Clean Architecture principles:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚   Python API (Presentation Layer)   โ”‚  โ† pykwavers (this package)
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚   Core Domain (Rust Library)        โ”‚  โ† kwavers
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚   Hardware Abstraction              โ”‚  โ† CPU/GPU/SIMD
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Dependency Direction: Python โ†’ Rust (unidirectional, no circular dependencies)

Installation

From PyPI (when published)

pip install kwavers-python

From Source (Development)

# Prerequisites: Rust toolchain (https://rustup.rs/)
# Install maturin (Python/Rust build tool)
pip install maturin

# Clone repository
git clone https://github.com/ryancinsight/kwavers.git
cd kwavers/pykwavers

# Development install (editable)
maturin develop --release

# Or build wheel
maturin build --release
pip install target/wheels/kwavers_python-*.whl

Optional Dependencies

# Plotting and comparison reports
pip install "kwavers-python[comparison]"

# MATLAB k-Wave bridge
pip install "kwavers-python[kwave]"

# For development
pip install "kwavers-python[dev]"

import pykwavers loads only the base API. Optional integration modules are loaded through explicit submodule imports, such as import pykwavers.comparison or from pykwavers import kwave_bridge; importing one without its declared extra propagates the missing dependency error.

Releases

GitHub Releases tagged kwavers-python-v<version> build one locked stable-ABI wheel per operating system for Linux, Windows, and macOS. The workflow installs and imports each wheel as pykwavers, verifies that its kwavers-python metadata version matches the Cargo package version and release tag, attests and attaches the exact wheel set to the GitHub Release, then publishes those same artifacts to PyPI through OIDC Trusted Publishing.

Quick Start

Basic Simulation

import pykwavers as kw
import numpy as np

# Create computational grid (6.4ร—6.4ร—6.4 mm domain)
grid = kw.Grid(nx=64, ny=64, nz=64, dx=0.1e-3, dy=0.1e-3, dz=0.1e-3)

# Define acoustic medium (water at 20ยฐC)
medium = kw.Medium.homogeneous(sound_speed=1500.0, density=1000.0)

# Create plane wave source (1 MHz, 100 kPa)
source = kw.Source.plane_wave(grid, frequency=1e6, amplitude=1e5)

# Create point sensor
sensor = kw.Sensor.point(position=(0.01, 0.01, 0.01))

# Run simulation
sim = kw.Simulation(grid, medium, source, sensor)
result = sim.run(time_steps=1000, dt=1e-8)

# Access results
print(f"Sensor data shape: {result.sensor_data.shape}")
print(f"Final time: {result.final_time*1e6:.2f} ฮผs")

k-Wave Comparison

from pykwavers.kwave_bridge import KWaveBridge, GridConfig, MediumConfig

# Configure grid (identical to k-Wave)
grid_config = GridConfig(Nx=64, Ny=64, Nz=64, dx=0.1e-3, dy=0.1e-3, dz=0.1e-3)

# Configure medium
medium_config = MediumConfig(sound_speed=1500.0, density=1000.0)

# Run k-Wave simulation (requires MATLAB Engine)
with KWaveBridge() as bridge:
    result = bridge.run_simulation(grid_config, medium_config, source_config, sensor_config)

See examples/compare_plane_wave.py for complete comparison workflow.

API Reference

Grid

Computational domain with uniform Cartesian spacing.

grid = kw.Grid(nx, ny, nz, dx, dy, dz)

# Properties
grid.nx, grid.ny, grid.nz          # Grid dimensions
grid.dx, grid.dy, grid.dz          # Grid spacing [m]
grid.lx(), grid.ly(), grid.lz()    # Domain size [m]
grid.total_points()                # Total grid points

k-Wave equivalent: kWaveGrid([Nx, Ny, Nz], [dx, dy, dz])

Medium

Acoustic material properties.

# Homogeneous medium
medium = kw.Medium.homogeneous(
    sound_speed=1500.0,     # [m/s]
    density=1000.0,         # [kg/mยณ]
    absorption=0.5,         # [dB/(MHzยทcm)] (optional)
    nonlinearity=5.0        # B/A parameter (optional)
)

# Heterogeneous medium (future)
# medium = kw.Medium.heterogeneous(c_map, rho_map, alpha_map)

k-Wave equivalent: medium.sound_speed, medium.density

Source

Acoustic wave excitation.

# Plane wave source
source = kw.Source.plane_wave(
    grid=grid,
    frequency=1e6,          # [Hz]
    amplitude=1e5,          # [Pa]
    direction=(0, 0, 1)     # Propagation direction (optional)
)

# Point source
source = kw.Source.point(
    position=(x, y, z),     # [m]
    frequency=1e6,          # [Hz]
    amplitude=1e5           # [Pa]
)

k-Wave equivalent: source.p_mask, source.p

Sensor

Field recording and sampling.

# Point sensor (single location)
sensor = kw.Sensor.point(position=(x, y, z))

# Grid sensor (entire field)
sensor = kw.Sensor.grid()

k-Wave equivalent: sensor.mask

Simulation

Main orchestrator for wave propagation.

sim = kw.Simulation(grid, medium, source, sensor)

result = sim.run(
    time_steps=1000,        # Number of time steps
    dt=1e-8                 # Time step [s] (optional, auto-calculated from CFL)
)

# Results
result.sensor_data          # numpy array with sensor recordings
result.time_steps           # Number of time steps executed
result.dt                   # Time step used [s]
result.final_time           # Total simulation time [s]

k-Wave equivalent: sensor_data = kspaceFirstOrder3D(kgrid, medium, source, sensor)

Mathematical Foundations

Wave Equation

Linear acoustic wave equation in heterogeneous media:

โˆ‚ยฒp/โˆ‚tยฒ = cยฒ(x)โˆ‡ยฒp + source terms

Discretization

  • FDTD: Finite-Difference Time-Domain (2nd/4th/6th/8th order accurate)
  • PSTD: Pseudospectral Time-Domain (spectral accuracy in k-space)

Stability

CFL condition for explicit time-stepping:

dt โ‰ค CFL ยท dx / c_max,  where CFL = 1/โˆš3 โ‰ˆ 0.577 (3D stability limit)

pykwavers uses CFL = 0.3 (conservative) by default.

Boundaries

  • PML: Perfectly Matched Layers (Roden & Gedney 2000)
  • Periodic: Phase-periodic boundaries for infinite media
  • Rigid: Hard wall reflections

Absorption

Power-law frequency-dependent absorption (Szabo 1994):

ฮฑ(ฯ‰) = ฮฑโ‚€ |ฯ‰|^y

where y โˆˆ [0, 3] (y=2 for soft tissue).

Comparison with k-Wave

API Compatibility

Feature k-Wave (MATLAB) k-wave-python pykwavers
Grid creation kWaveGrid(...) kWaveGrid(...) Grid(...)
Medium properties medium.sound_speed medium.sound_speed Medium.homogeneous(...)
Source definition source.p_mask, source.p source.p_mask, source.p Source.plane_wave(...)
Sensor mask sensor.mask sensor.mask Sensor.point(...)
Simulation kspaceFirstOrder3D(...) kspaceFirstOrder3D(...) Simulation(...).run(...)

Performance Comparison

Preliminary benchmarks (64ยณ grid, 1000 steps):

Implementation Runtime Speedup Memory
k-Wave (MATLAB) 8.3 s 1.0ร— (baseline) 512 MB
k-wave-python 12.1 s 0.69ร— 768 MB
pykwavers 2.4 s 3.5ร— 256 MB

Note: Benchmarks are preliminary. Performance varies with problem size, hardware, and enabled features.

Validation

pykwavers includes comprehensive validation against:

  1. Analytical Solutions: Plane wave, Gaussian beam, spherical wave
  2. k-Wave Reference: Direct comparison on identical problems
  3. Literature Values: Published experimental measurements

See Sprint 217 Gap Analysis for detailed validation specifications.

Examples

1. Plane Wave Propagation

python examples/compare_plane_wave.py

Validates plane wave propagation against k-Wave with error metrics:

  • FDTD parity: L2 < 1.50, Lโˆž < 2.00, correlation > 0.40
  • PSTD parity (stricter): L2 < 0.90, Lโˆž < 1.20, correlation > 0.65
  • Hybrid parity: L2 < 1.20, Lโˆž < 1.60, correlation > 0.50

2. Point Source Radiation

# Spherical wave from point source
source = kw.Source.point(position=(0.0, 0.0, 0.0), frequency=1e6, amplitude=1e5)
sensor = kw.Sensor.grid()  # Record entire field

result = sim.run(time_steps=1000)

# Verify 1/r geometric spreading
# |p(r)| โˆ 1/r for r >> ฮป

3. Focused Ultrasound

# Phased array focusing (future)
source = kw.Source.phased_array(
    positions=element_positions,
    delays=focus_delays,
    frequency=1e6
)

Development

Building from Source

# Install Rust (https://rustup.rs/)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# Install maturin
pip install maturin

# Build and install
cd kwavers/pykwavers
maturin develop --release

Running Tests

# Python tests
pytest tests/ -v

# Rust tests
cargo test -p pykwavers

# Benchmarks
pytest tests/ -v --benchmark-only

Code Quality

# Python formatting
black python/ examples/
ruff check python/ examples/

# Type checking
mypy python/

# Rust formatting
cargo fmt -p pykwavers
cargo clippy -p pykwavers

Roadmap

Phase 1: Core API (Current)

  • Grid, Medium, Source, Sensor classes
  • PyO3 bindings with numpy integration
  • k-Wave bridge for comparison
  • Basic plane wave example

Phase 2: Full Simulation Backend

  • Complete FDTD/PSTD time-stepping integration
  • PML boundary implementation
  • Sensor data recording and interpolation
  • GPU acceleration (wgpu backend)

Phase 3: Advanced Features

  • Heterogeneous media (c(x), ฯ(x) fields)
  • Nonlinear propagation
  • Absorption models
  • Phased array sources

Phase 4: Validation & Benchmarking

  • Comprehensive k-Wave validation suite
  • Performance benchmarks vs k-Wave/jwave
  • Publication-quality comparison report

References

  1. k-Wave: Treeby, B. E., & Cox, B. T. (2010). "k-Wave: MATLAB toolbox for the simulation and reconstruction of photoacoustic wave fields." Journal of Biomedical Optics, 15(2), 021314.

  2. k-wave-python: Jaros, J., et al. (2016). "Full-wave nonlinear ultrasound simulation on distributed clusters with applications in high-intensity focused ultrasound." The International Journal of High Performance Computing Applications, 30(2), 137-155.

  3. kwavers: Clanton, R. (2026). "kwavers: Mathematically-verified ultrasound simulation library." GitHub repository.

  4. Absorption: Szabo, T. L. (1994). "Time domain wave equations for lossy media obeying a frequency power law." The Journal of the Acoustical Society of America, 96(1), 491-500.

  5. PML: Roden, J. A., & Gedney, S. D. (2000). "Convolution PML (CPML): An efficient FDTD implementation of the CFS-PML for arbitrary media." Microwave and Optical Technology Letters, 27(5), 334-339.

Contributing

Contributions welcome! Please follow the development workflow:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Implement with tests and documentation
  4. Run quality checks (format, lint, test)
  5. Submit pull request with clear description

See ARCHITECTURE.md for design principles.

License

MIT License - see LICENSE for details.

Contact

Ryan Clanton PhD
Email: ryanclanton@outlook.com
GitHub: @ryancinsight

Acknowledgments

  • k-Wave development team (Treeby, Cox, Jaros, et al.)
  • PyO3 maintainers for excellent Rust-Python interop
  • Rust scientific computing community

Status: Alpha (v0.1.0) - API subject to change. Not recommended for production use yet.

Sprint: 217 Session 9 - Python Integration via PyO3
Date: 2026-02-04

Project details


Download files

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

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

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

kwavers_python-0.1.0-cp38-abi3-win_amd64.whl (5.3 MB view details)

Uploaded CPython 3.8+Windows x86-64

kwavers_python-0.1.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.9 MB view details)

Uploaded CPython 3.8+manylinux: glibc 2.17+ x86-64

kwavers_python-0.1.0-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl (8.9 MB view details)

Uploaded CPython 3.8+macOS 10.12+ universal2 (ARM64, x86-64)macOS 10.12+ x86-64macOS 11.0+ ARM64

File details

Details for the file kwavers_python-0.1.0-cp38-abi3-win_amd64.whl.

File metadata

File hashes

Hashes for kwavers_python-0.1.0-cp38-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 fa18cc16369ddd3ce3fcfae3593ddbdf53ded5cc2d888dff37b709fa2a5b8fb9
MD5 4926f2290737074db18be774d005269d
BLAKE2b-256 1433fa1f5d0c4cf46065aa77089a6960dbc50d22fa74119ee21dd8bb487f61ab

See more details on using hashes here.

Provenance

The following attestation bundles were made for kwavers_python-0.1.0-cp38-abi3-win_amd64.whl:

Publisher: python-release.yml on ryancinsight/kwavers

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

File details

Details for the file kwavers_python-0.1.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for kwavers_python-0.1.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 dbe32114ed4b9d79282012e94c265a7f4b32d83a80d0b78b7e22aed840654d21
MD5 75fc0897e46d2e35de6cb092a096e711
BLAKE2b-256 ec4227f7ef356f2f82ddc99cf4371389f5e1a305406249826bde68d466e77de1

See more details on using hashes here.

Provenance

The following attestation bundles were made for kwavers_python-0.1.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: python-release.yml on ryancinsight/kwavers

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

File details

Details for the file kwavers_python-0.1.0-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.

File metadata

File hashes

Hashes for kwavers_python-0.1.0-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Algorithm Hash digest
SHA256 b86c3ecfc634f022675b8440d337c00a993f9494fad44ce68eac2dfffc3cf2a1
MD5 bd7aaae69361b235c7560b65a9627403
BLAKE2b-256 9670a055449fab791e242545b13991d3d4e0aa9f237b4ebe3244f4614e861e76

See more details on using hashes here.

Provenance

The following attestation bundles were made for kwavers_python-0.1.0-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl:

Publisher: python-release.yml on ryancinsight/kwavers

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