Skip to content

Commit 580a31b

Browse files
authored
Merge pull request #678 from waltsims/docs-new-api-060
Add unified API docs and bump version to 0.6.0
2 parents a98aadd + 1026458 commit 580a31b

6 files changed

Lines changed: 181 additions & 11 deletions

File tree

docs/README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,25 @@
88
This project is a Python implementation of v1.4.0 of the [MATLAB toolbox k-Wave](http://www.k-wave.org/) as well as an
99
interface to the pre-compiled v1.3 of k-Wave simulation binaries, which support NVIDIA sm 5.0 (Maxwell) to sm 9.0a (Hopper) GPUs.
1010

11+
## What's New in v0.6.0
12+
13+
**Unified API:** A single `kspaceFirstOrder()` function replaces `kspaceFirstOrder2D` / `3D` and their options classes.
14+
Dimensionality is auto-detected from the grid. All simulation parameters are keyword arguments.
15+
16+
**Python solver:** A pure NumPy/CuPy solver runs 1D, 2D, and 3D simulations without the C++ binary.
17+
Use `device="gpu"` for GPU acceleration via CuPy.
18+
19+
```python
20+
from kwave.kspaceFirstOrder import kspaceFirstOrder
21+
22+
result = kspaceFirstOrder(kgrid, medium, source, sensor) # NumPy CPU
23+
result = kspaceFirstOrder(kgrid, medium, source, sensor, device="gpu") # CuPy GPU
24+
result = kspaceFirstOrder(kgrid, medium, source, sensor, backend="cpp") # C++ binary
25+
```
26+
27+
The legacy `kspaceFirstOrder2D` / `3D` functions still work but emit deprecation warnings.
28+
See the [Unified API guide](https://k-wave-python.readthedocs.io/en/latest/get_started/new_api.html) for migration details.
29+
1130
## Mission
1231

1332
With this project, we hope to increase the accessibility and reproducibility of [k-Wave](http://www.k-wave.org/) simulations

docs/get_started/first_simulation.rst

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -138,21 +138,28 @@ Sensors specify where we record the acoustic data:
138138
Step 5: Run the Simulation
139139
--------------------------
140140

141-
Now we combine all four components and run the simulation:
141+
Now we combine all four components and run:
142142

143143
.. code-block:: python
144144
145-
from kwave import kspaceFirstOrder2D
146-
147-
# Run the simulation
148-
sensor_data = kspaceFirstOrder2D(
149-
grid=grid,
150-
medium=medium,
151-
source=source,
152-
sensor=sensor,
153-
simulation_options={'PMLInside': False, 'PlotSim': False}
145+
from kwave.kspaceFirstOrder import kspaceFirstOrder
146+
147+
# Run with the NumPy/CuPy backend in Python
148+
sensor_data = kspaceFirstOrder(
149+
grid, medium, source, sensor,
150+
pml_inside=False,
151+
quiet=True,
154152
)
155153
154+
.. note::
155+
156+
``kspaceFirstOrder()`` is the unified entry point introduced in v0.6.0.
157+
It auto-detects dimensionality from the grid and replaces the legacy
158+
``kspaceFirstOrder2D`` / ``3D`` functions. See :doc:`/get_started/new_api`
159+
for details.
160+
161+
The legacy functions still work but emit deprecation warnings.
162+
156163
Step 6: Visualize Results
157164
-------------------------
158165

docs/get_started/new_api.rst

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
Unified API (v0.6.0)
2+
====================
3+
4+
Starting with v0.6.0, ``kspaceFirstOrder()`` is the preferred way to run
5+
simulations. It replaces the legacy ``kspaceFirstOrder2D``,
6+
``kspaceFirstOrder3D``, and their GPU variants with a single function that
7+
auto-detects dimensionality from the grid.
8+
9+
.. contents:: On this page
10+
:local:
11+
:depth: 2
12+
13+
Quick Start
14+
-----------
15+
16+
.. code-block:: python
17+
18+
from kwave.kgrid import kWaveGrid
19+
from kwave.kmedium import kWaveMedium
20+
from kwave.ksource import kSource
21+
from kwave.ksensor import kSensor
22+
from kwave.kspaceFirstOrder import kspaceFirstOrder
23+
import numpy as np
24+
25+
# Setup (works for 1D, 2D, or 3D — just change grid dimensions)
26+
kgrid = kWaveGrid([128, 128], [0.1e-3, 0.1e-3])
27+
kgrid.makeTime(1500)
28+
29+
medium = kWaveMedium(sound_speed=1500, density=1000)
30+
31+
source = kSource()
32+
source.p0 = np.zeros((128, 128))
33+
source.p0[64, 64] = 1.0
34+
35+
sensor = kSensor(mask=np.ones((128, 128), dtype=bool))
36+
37+
# Run with the NumPy/CuPy solver in Python
38+
result = kspaceFirstOrder(kgrid, medium, source, sensor)
39+
40+
print(result["p"].shape) # (16384, Nt) — time series at each sensor
41+
print(result["p_final"].shape) # (128, 128) — final pressure field
42+
43+
Backend and Device
44+
------------------
45+
46+
Two independent choices control how the simulation runs:
47+
48+
- **backend** selects the simulation engine:
49+
50+
- ``"python"`` (default) — pure Python solver using NumPy or CuPy.
51+
No external dependencies beyond NumPy.
52+
- ``"cpp"`` — serializes to HDF5 and invokes the pre-compiled C++ binary.
53+
Requires FFTW (``brew install fftw`` on macOS).
54+
55+
- **device** selects the hardware:
56+
57+
- ``"cpu"`` (default) — NumPy for ``backend="python"``, OMP binary for
58+
``backend="cpp"``.
59+
- ``"gpu"`` — CuPy for ``backend="python"`` (requires CuPy + CUDA),
60+
CUDA binary for ``backend="cpp"``.
61+
62+
.. code-block:: python
63+
64+
# NumPy on CPU (default)
65+
result = kspaceFirstOrder(kgrid, medium, source, sensor)
66+
67+
# CuPy on GPU (requires CuPy + CUDA)
68+
result = kspaceFirstOrder(kgrid, medium, source, sensor, device="gpu")
69+
70+
# C++ binary on CPU (requires FFTW)
71+
result = kspaceFirstOrder(kgrid, medium, source, sensor, backend="cpp")
72+
73+
# C++ CUDA binary on GPU
74+
result = kspaceFirstOrder(kgrid, medium, source, sensor, backend="cpp", device="gpu")
75+
76+
PML Options
77+
-----------
78+
79+
The perfectly-matched layer (PML) absorbs outgoing waves at the domain
80+
boundary. Three controls:
81+
82+
.. code-block:: python
83+
84+
# Fixed size (default: 20 grid points on all sides)
85+
result = kspaceFirstOrder(kgrid, medium, source, sensor, pml_size=20)
86+
87+
# Per-dimension sizes
88+
result = kspaceFirstOrder(kgrid, medium, source, sensor, pml_size=(10, 15))
89+
90+
# Auto-optimal size (computed from grid via FFT analysis)
91+
result = kspaceFirstOrder(kgrid, medium, source, sensor, pml_size="auto")
92+
93+
# PML inside the user domain (saves memory, but PML overlaps your grid)
94+
result = kspaceFirstOrder(kgrid, medium, source, sensor, pml_inside=True)
95+
96+
By default (``pml_inside=False``), the grid is automatically expanded so
97+
the PML sits outside your domain. Full-grid output fields (``_final``,
98+
``_max``, etc.) are cropped back to the original size.
99+
100+
Save-Only Mode (Cluster Submission)
101+
------------------------------------
102+
103+
Generate HDF5 input files for the C++ binary without running it:
104+
105+
.. code-block:: python
106+
107+
result = kspaceFirstOrder(
108+
kgrid, medium, source, sensor,
109+
backend="cpp",
110+
save_only=True,
111+
data_path="/path/to/output",
112+
)
113+
print(result["input_file"]) # path to HDF5 input
114+
print(result["output_file"]) # path where C++ will write results
115+
116+
Full Parameter Reference
117+
------------------------
118+
119+
.. autofunction:: kwave.kspaceFirstOrder.kspaceFirstOrder
120+
121+
Migrating from Legacy API
122+
--------------------------
123+
124+
The ``kwave.compat`` module provides ``options_to_kwargs()`` to convert
125+
old ``SimulationOptions`` / ``SimulationExecutionOptions`` to keyword
126+
arguments:
127+
128+
.. code-block:: python
129+
130+
from kwave.compat import options_to_kwargs
131+
from kwave.options.simulation_options import SimulationOptions
132+
from kwave.options.simulation_execution_options import SimulationExecutionOptions
133+
134+
sim_opts = SimulationOptions(smooth_p0=False, pml_inside=True)
135+
exec_opts = SimulationExecutionOptions(is_gpu_simulation=False)
136+
137+
kwargs = options_to_kwargs(simulation_options=sim_opts, execution_options=exec_opts)
138+
result = kspaceFirstOrder(kgrid, medium, source, sensor, **kwargs)
139+
140+
The legacy ``kspaceFirstOrder2D`` and ``kspaceFirstOrder3D`` functions
141+
continue to work but emit ``DeprecationWarning``.

docs/index.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ k-Wave is an open source acoustics toolbox for MATLAB and C++ developed by Bradl
1414
:hidden:
1515

1616
get_started/first_simulation
17+
get_started/new_api
1718
get_started/grid_overview
1819
get_started/medium_overview
1920
get_started/source_overview
@@ -29,6 +30,7 @@ k-Wave is an open source acoustics toolbox for MATLAB and C++ developed by Bradl
2930
kwave.kmedium
3031
kwave.ksource
3132
kwave.ksensor
33+
kwave.kspaceFirstOrder
3234
kwave.kWaveSimulation
3335
kwave.kspaceFirstOrder2D
3436
kwave.kspaceFirstOrder3D

kwave/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
# Test installation with:
1111
# python3 -m pip install -i https://test.pypi.org/simple/ --extra-index-url=https://pypi.org/simple/ k-Wave-python==0.3.0
12-
__version__ = "0.5.0rc1"
12+
__version__ = "0.6.0"
1313

1414
# Constants and Configurations
1515
URL_BASE = "https://github.com/waltsims/"

kwave/compat.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ def options_to_kwargs(simulation_options=None, execution_options=None):
3434
elif opts.pml_alpha is not None:
3535
kwargs["pml_alpha"] = opts.pml_alpha
3636

37+
kwargs["pml_inside"] = opts.pml_inside
3738
kwargs["use_sg"] = opts.use_sg
3839
kwargs["use_kspace"] = opts.use_kspace
3940
kwargs["smooth_p0"] = opts.smooth_p0

0 commit comments

Comments
 (0)