Skip to content

Commit f5c765f

Browse files
waltsimsclaude
andauthored
Bump version to 0.6.1, update release plan (#694)
* Bump version to 0.6.1, update release plan v0.6.1 combines: C-order migration, 29 ported examples, 47 parity tests, 3D PML fix, docs cleanup, infra removal. Renumber: old v0.6.2 (examples) merged into v0.6.1, old v0.6.3 (features) becomes v0.6.2, old v0.6.4 (axisymmetric) becomes v0.6.3. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Clean up stale Phase 2.x sections in release plan Remove old Phase 2.1/2.2/2.3 detailed sections (superseded by v0.6.x summary). Update Testing Strategy and Implementation Order to match current version numbering. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Walter Simson <waltsims@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 22c4c8e commit f5c765f

2 files changed

Lines changed: 50 additions & 229 deletions

File tree

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.6.0"
12+
__version__ = "0.6.1"
1313

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

plans/release-strategy.md

Lines changed: 49 additions & 228 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,9 @@ This release strategy brings the unified solver architecture to fruition.
1010
|---------|-----------|-------|
1111
| **0.5.0** | Finalize master/main | Stabilize current codebase |
1212
| **0.6.0** | Python Solver + Unified API + Deprecation | Python solver, `kspaceFirstOrder()` kwargs, Future warnings |
13-
| **0.6.1** | C-order Migration (Helpers) | Migrate utils/helpers from F-order to C-order, keep legacy API working |
14-
| **0.6.2** | Example Restructure & Docs Gallery | Flatten examples, jupytext notebooks, docs gallery, CuPy validation |
15-
| **0.6.3** | Tier 2 Features + Examples | Time-reversal, rect sensors, sound_speed_ref, port Tier 2 examples |
16-
| **0.6.4** | Axisymmetric Support | Axisymmetric solver in new API, port AS examples |
13+
| **0.6.1** | C-order + Examples + Docs | C-order migration, 29 examples ported, 47 parity tests, docs cleanup |
14+
| **0.6.2** | Tier 2 Features + Examples | Time-reversal, rect sensors, sound_speed_ref, port Tier 2 examples |
15+
| **0.6.3** | Axisymmetric Support | Axisymmetric solver in new API, port AS examples |
1716
| **0.7.0** | CLI (`kwp`) | Command-line interface for running simulations |
1817
| **1.0.0** | Clean Release | Remove deprecated code. Simple, readable, fast. |
1918
| **2.0.0** | Performance & Scale | nanobind CUDA, MPI, Devito, multi-GPU |
@@ -125,169 +124,57 @@ warnings.warn(
125124

126125
---
127126

128-
## Phase 2.1: v0.6.1 - C-order Migration (Helpers)
127+
## v0.6.x Point Releases
129128

130-
**Goal:** Migrate helper/utility code from Fortran-order to C-order internally, while keeping the legacy API functional. No structural API changes — Future warnings only. Fix hacky shaping/indexing throughout.
129+
### v0.6.1 — C-order + Examples + Docs (released 2026-03-29)
131130

132-
**Scope:** 55 occurrences of `order="F"` across 10 files. Migrate where possible, keep F-order only at explicit boundaries.
131+
Combined release: C-order migration, example restructure, parity tests, docs cleanup.
133132

134-
**Migrate (internal helpers — safe to convert):**
133+
**C-order migration:**
134+
- `kspace_solver.py`: F-order → C-order internally
135+
- `cpp_simulation.py`: `_fix_output_order()` for C++ backend compatibility
136+
- `kspaceFirstOrder.py`: `_reshape_sensor_to_grid()` for full-grid sensors
137+
- F-order kept at boundaries: `matlab.py`, `cpp_simulation._write_hdf5()`, legacy API
135138

136-
| File | `order="F"` count | Notes |
137-
|------|-------------------|-------|
138-
| `kwave/utils/matlab.py` | 11 | reshape, flatten, unflatten utilities |
139-
| `kwave/kgrid.py` | 8 | Grid coordinate generation |
140-
| `kwave/utils/mapgen.py` | 6 | Map generation |
141-
| `kwave/utils/conversion.py` | 2 | Unit conversion |
142-
| `kwave/utils/matrix.py` | 1 | Matrix utilities |
143-
| `kwave/solvers/kspace_solver.py` | 19 | Audit each: keep F-order only at `simulate_from_dicts` boundary. Convert internal field storage, `_expand_to_grid`, `_build_source_op`, sensor mask extraction. |
144-
| `kwave/kspaceFirstOrder.py` | 1 | Likely removable |
145-
146-
**Keep as-is (fixed boundaries):**
147-
148-
| File | `order="F"` count | Reason |
149-
|------|-------------------|--------|
150-
| `kwave/solvers/cpp_simulation.py` | 3 | C++ binary expects F-order HDF5 |
151-
| `kwave/kWaveSimulation.py` | 1 | Legacy, deleted in v1.0.0 |
152-
| `kwave/kWaveSimulation_helper/*` | 3 | Legacy, deleted in v1.0.0 |
153-
154-
**Testing:**
155-
- All existing tests must pass (no behavioral change)
156-
- Add `tests/test_memory_layout.py`: verify C/F-order input produces identical results, `simulate_from_dicts` round-trips correctly, `cpp_simulation` writes correct F-order HDF5
157-
158-
---
159-
160-
## Phase 2.2: v0.6.2 - Example Migration
161-
162-
**Goal:** Port remaining examples from legacy `kspaceFirstOrder2D/3D` to `kspaceFirstOrder()`, validated against MATLAB reference outputs.
163-
164-
### Strategy
165-
166-
Port examples one at a time using MATLAB as ground truth — not old Python results. Use the k-wave-cupy interop layer as the bridge between MATLAB and Python.
167-
168-
**Per-example workflow:**
169-
170-
1. **MATLAB reference** — Run the example in MATLAB k-Wave, save outputs to `.mat`
171-
2. **k-wave-cupy validation** — Call the Python solver from MATLAB via k-wave-cupy (`simulate_from_dicts`). Compare against MATLAB output. This catches F/C ordering and interop issues at the boundary.
172-
3. **Standalone Python port** — Port the example to `kspaceFirstOrder()`, compare against the same MATLAB `.mat` reference
173-
4. **CI fixture** — Add the MATLAB `.mat` as a reference test in `tests/integration/`
174-
175-
**Why k-wave-cupy first:** The interop layer handles F→C conversion at the boundary. Validating there first means ordering bugs are caught before they propagate to the standalone Python example. Once the k-wave-cupy version matches MATLAB, the Python port is a straightforward translation.
176-
177-
**Order of work:**
178-
1. Migrate example in k-wave-cupy repo (MATLAB calls Python solver)
179-
2. Validate against MATLAB reference output
180-
3. Port the standalone Python example in k-wave-python
181-
4. Add integration test with `.mat` fixture
182-
183-
### Examples to port
184-
185-
| Example | Blocker | Resolution |
186-
|---------|---------|------------|
187-
| `pr_2D_TR_line_sensor`, `pr_3D_TR_planar_sensor` | `TimeReversal` class uses legacy API internally | Refactor `TimeReversal` to call `kspaceFirstOrder()` |
188-
| `us_defining_transducer`, `us_beam_patterns`, `us_bmode_linear_transducer`, `us_bmode_phased_array` | `NotATransducer`-as-source pipeline untested with new API | Validate transducer pipeline end-to-end via k-wave-cupy first |
189-
| `checkpointing/checkpoint.py` | `checkpoint_file`/`checkpoint_timesteps` not exposed in new API | Add checkpoint kwargs to `kspaceFirstOrder()` |
190-
191-
---
192-
193-
## Phase 2.3: v0.6.3 - Axisymmetric Support
194-
195-
**Goal:** Add axisymmetric simulation to `kspaceFirstOrder()` and port AS examples.
196-
197-
**What axisymmetric means:** Dimensionality reduction for problems with cylindrical symmetry. A 3D symmetric problem is simulated on a 2D (r, z) half-domain; a 2D symmetric problem on a 1D half-domain. Results are mirrored around the symmetry axis to reconstruct the full field.
198-
199-
**Current state:** `kspaceFirstOrderAS.py` / `kspaceFirstOrderASC.py` are standalone entry points using the legacy `kWaveSimulation` pipeline. The new API hardcodes `axisymmetric_flag=0`.
200-
201-
**Design:** Not a separate solver — a wrapper around `kspaceFirstOrder()` that:
202-
1. Takes `axisymmetric=True` kwarg
203-
2. Reduces the grid to a half-domain (y ≥ 0 = radial direction)
204-
3. Adds radial symmetry terms: special PML at axis (no absorption at y=0), expanded grid for FFT symmetries (WSWA: 4× radial, WSWS: 2×-2), radial coordinate vectors for geometric source terms
205-
4. Runs the lower-dimensional simulation via `Simulation`
206-
5. Mirrors results around the axis for output
207-
208-
**Legacy mapping:** `kspaceFirstOrderAS``kspaceFirstOrder(..., axisymmetric=True, backend="python")`, `kspaceFirstOrderASC``kspaceFirstOrder(..., axisymmetric=True, backend="cpp")`
209-
210-
**Constraints:** Staggered grid mandatory (`use_sg=True` enforced). Viscous absorption only (`alpha_power=2` fixed).
211-
212-
**Tasks:**
213-
1. Add `axisymmetric: bool = False` kwarg to `kspaceFirstOrder()`
214-
2. Implement radial symmetry pre/post-processing in `kspaceFirstOrder()` (grid reduction, PML axis handling, result mirroring)
215-
3. Add radial terms to `Simulation` class (geometric source terms for (r, z) grid)
216-
4. Port `at_circular_piston_AS`, `at_focused_bowl_AS` using the v0.6.2 MATLAB-first workflow
217-
5. Validate against MATLAB references
218-
6. Deprecate `kspaceFirstOrderAS` / `kspaceFirstOrderASC`
219-
220-
---
221-
222-
## Phase 2.x: v0.6.x Point Releases
223-
224-
### v0.6.1 — C-order Migration
225-
226-
**Status: implemented on `c-order-migration` branch**
227-
228-
Atomic migration of all solver internals from Fortran-order to C-order. The `kspaceFirstOrder()` API is experimental pre-1.0, so output shape changes are acceptable without a deprecation cycle.
229-
230-
**Changes:**
231-
- `kspace_solver.py`: all `flatten(order="F")`/`reshape(..., order="F")``ravel()`/`reshape()`. C-order strides for bilinear interpolation.
232-
- `cpp_simulation.py`: `_fix_output_order()` transposes full-grid fields and permutes sensor time-series rows from F-indexed to C-indexed.
233-
- `kspaceFirstOrder.py`: `_reshape_sensor_to_grid()` for full-grid sensors → `(Nt, *grid_shape)` output. Aggregates → `(*grid_shape)`.
234-
- `cart2grid`, `combine_sensor_data`, `get_distributed_source_signal`: `order=` param with `FutureWarning` defaulting to `"F"`.
235-
236-
**Unchanged (by design):** `matlab.py` (F-order boundary), `mapgen.py` (geometry), `kgrid.py` (MATLAB inputs), `cpp_simulation._write_hdf5()` (C++ binary format), legacy `kspaceFirstOrder2D/3D`.
237-
238-
### v0.6.2 — Example Restructure & Docs Gallery
239-
240-
**Status: in progress (restructure-examples branch, PR #686)**
241-
242-
Flatten example directory, add jupytext notebook generation, build docs gallery.
243-
244-
**Done:**
245-
- 29 Tier 1 examples ported to `setup()/run()/__main__` pattern with `kspaceFirstOrder()`
139+
**Example restructure:**
140+
- 29 Tier 1 examples ported to `setup()/run()/__main__` pattern
246141
- Flattened `examples/ported/``examples/`, dropped `example_` prefix
247-
- Old subdirectory examples moved to `examples/legacy/`
248-
- Test file parametrized: 15 classes → table-driven (550 → 290 lines), 35 pass / 2 skip
249-
- Separate `p_thresh` / `p_final_thresh` per example (machine precision for time-series)
250-
- `jupytext.toml` + `generate-notebooks.yml` — auto-generates `.ipynb` on merge to master
142+
- Old subdirectory examples in `examples/legacy/`
251143
- `run-examples.yml` triggers on PRs touching `examples/`, excludes `legacy/`
252-
- Deleted dead `test_example.yml`
253144

254-
**Remaining for v0.6.2:**
255-
1. **Docs example gallery** — Add nbsphinx or sphinx-gallery to docs build; render generated notebooks as HTML pages with "Open in Colab" badges. Wire into `test_pages.yml`.
256-
2. **8 more parity tests** — ivp_saving_movie_files, na_optimising_performance, na_source_smoothing, pr_2D_FFT_line_sensor, pr_3D_FFT_planar_sensor, sd_directional_array_elements, sd_directivity_modelling_2D/3D
257-
3. **Investigate 3D p_final mismatch** — 2 skipped tests (likely p0 smoothing or medium mapping difference)
258-
4. **CuPy GPU validation** — Run all 29 examples on DigitalOcean GPU droplet, verify NumPy↔CuPy parity
259-
5. **Real-world validation** — Run representative simulations from published papers or user workflows to catch edge cases not covered by toy examples
145+
**Testing:**
146+
- 47 parity tests passing (machine precision), 6 skipped (missing refs)
147+
- 3D PML fix: MATLAB defaults to pml_size=10 for 3D
148+
- Table-driven parametrized test framework
260149

261-
**CI test tiers (implemented):**
262-
- **Tier 1 (every PR):** `test_native_solver.py` + old C++ API tests — no MATLAB needed, ~2s
263-
- **Tier 2 (every PR):** `test_example_parity.py` — skips gracefully when `.mat` refs absent
264-
- **Tier 3 (weekly + PR):** `run-examples.yml` — runs all examples end-to-end
265-
- **`matlab_parity` marker** registered in `pytest.ini` for selective runs
150+
**Docs & infra cleanup:**
151+
- README: Python-first framing, both backends described
152+
- Dev docs: simplified setup with `uv sync`, removed outdated sections
153+
- macOS C++ hint in executor.py (scoped to linker errors)
154+
- Deleted: Makefile, Dockerfile, run_examples.py, notebook pipeline, dead CI workflows
266155

267-
### v0.6.3New Features + Updated Examples
156+
### v0.6.2Tier 2 Features + Examples
268157

269-
**Goal:** Add solver features needed by Tier 2 examples, port those examples, update docs gallery.
158+
**Goal:** Add solver features needed by Tier 2 examples, port those examples.
270159

271160
**Features to add:**
272-
- **Time-reversal reconstruction** — needed by 9 PR examples (`pr_2D_TR_*`, `pr_3D_TR_*`)
161+
- **Time-reversal reconstruction** — needed by PR examples (`pr_2D_TR_*`, `pr_3D_TR_*`)
273162
- **Rectangular/corner sensor masks** — needed by 5 examples
274163
- **`sound_speed_ref`** — needed by `tvsp_slit_diffraction`
275164
- **Frequency-response sensor** — needed by `ivp_sensor_frequency_response`
276165
- **Directional sensor** — needed by `sd_sensor_directivity_2D`
277166

278-
**Per-feature workflow:**
279-
1. Implement feature in solver (`kspace_solver.py`)
280-
2. Port the MATLAB examples that need it
281-
3. Generate MATLAB references, add parity tests
282-
4. Update docs gallery with new examples
167+
**Also:**
168+
- CuPy GPU validation on DigitalOcean (29 examples ready)
169+
- Real-world validation (published paper simulations)
170+
- Consolidate test infrastructure (`tests/integration/` + `test_example_parity.py`)
283171

284172
**Simplification targets:**
285173
- Delete `examples/legacy/` once all examples are ported or confirmed obsolete
286-
- Consolidate `tests/integration/` and `tests/test_example_parity.py` test infrastructure
287174
- Remove unused MATLAB collector infrastructure if parity tests replace it
288175
- Audit `kWaveSimulation_helper/` — delete helpers superseded by `kspaceFirstOrder()`
289176

290-
### v0.6.4 — Axisymmetric Support
177+
### v0.6.3 — Axisymmetric Support
291178

292179
Axisymmetric = dimensionality reduction (3D→2D or 2D→1D). Not a separate solver — wrapper around `kspaceFirstOrder()` with radial symmetry terms added to the wave equation.
293180

@@ -389,96 +276,30 @@ result = kspaceFirstOrder(kgrid, medium, source, sensor,
389276

390277
## Testing Strategy
391278

392-
**Existing (keep):**
393-
- MATLAB reference tests via CI (66 MATLAB collectors → `.mat` fixtures, `scipy.io.loadmat`)
279+
**Current (v0.6.1):**
394280
- Multi-platform pytest (Windows, Ubuntu, macOS) × Python 3.10-3.13 (12-job matrix)
395-
- Integration tests in `tests/integration/` with `assert_fields_close()` (rtol=1e-10, atol=1e-12)
396-
- Weekly example runner (`run-examples.yml`, `KWAVE_FORCE_CPU=1`)
397-
398-
**v0.6.0 (done):**
399-
- `tests/test_native_solver.py` — 33 tests for Python backend
400-
- `tests/test_unified_api.py` — new kwargs API
401-
- `tests/test_compat.py``options_to_kwargs()` migration
281+
- MATLAB reference tests via CI (66 collectors → `.mat` fixtures)
282+
- `test_example_parity.py` — 47 table-driven parity tests against MATLAB refs
283+
- `test_native_solver.py` — 33 tests for Python backend
284+
- Weekly example runner (`run-examples.yml`)
285+
- `matlab_parity` marker for selective runs
402286

403-
**v0.6.1 (C-order migration):**
404-
- `tests/test_memory_layout.py` — C/F-order input produces identical results, `simulate_from_dicts` F→C→F round-trip, `cpp_simulation` writes correct F-order HDF5
405-
406-
**v0.6.2 (example migration):**
407-
- Per-example MATLAB reference integration tests — validate via k-wave-cupy interop first, then add `.mat` fixtures to `tests/integration/`
408-
- Each ported example gets a corresponding `test_<example_name>.py` with MATLAB reference comparison
287+
**v0.6.2 (Tier 2 features):**
288+
- Parity tests for time-reversal, rect sensors, etc.
289+
- CuPy GPU validation
409290

410291
**v0.6.3 (axisymmetric):**
411-
- Extend existing `test_ivp_axisymmetric_simulation.py` to use new `kspaceFirstOrder(..., axisymmetric=True)` API
412-
- New MATLAB reference tests for `at_circular_piston_AS`, `at_focused_bowl_AS`
413-
414-
**Cross-cutting:**
415-
- `tests/test_backend_parity.py` — Python vs C++ backends produce same results for shared test cases
416-
- `tests/test_Future_warnings.py` — verify FutureWarning emitted on legacy API calls
417-
418-
---
419-
420-
## Verification
421-
422-
```bash
423-
# v0.5.0 - CI passes
424-
uv run pytest tests/ -v
425-
426-
# v0.6.0 - Unified API works
427-
uv run python -c "
428-
from kwave.kspaceFirstOrder import kspaceFirstOrder
429-
from kwave.kgrid import kWaveGrid
430-
from kwave.kmedium import kWaveMedium
431-
from kwave.ksource import kSource
432-
from kwave.ksensor import kSensor
433-
import numpy as np
434-
435-
kgrid = kWaveGrid([64, 64], [0.1e-3, 0.1e-3])
436-
kgrid.makeTime(1500, 0.3, 20e-6)
437-
medium = kWaveMedium(sound_speed=1500)
438-
source = kSource()
439-
source.p0 = np.zeros((64, 64)); source.p0[32, 32] = 1
440-
sensor = kSensor()
441-
sensor.mask = np.ones((64, 64), dtype=bool)
442-
443-
result = kspaceFirstOrder(kgrid, medium, source, sensor, backend='native')
444-
print('Success:', result['p'].shape)
445-
"
446-
447-
# v0.6.0 - Future warnings
448-
uv run python -W error::FutureWarning -c "
449-
from kwave.options.simulation_options import SimulationOptions
450-
" # Should warn
451-
452-
# v1.0.0 - Full test suite
453-
uv run pytest tests/ -v
454-
```
292+
- MATLAB reference tests for `at_circular_piston_AS`, `at_focused_bowl_AS`
455293

456294
---
457295

458296
## Implementation Order
459297

460-
1. **Now:** Finalize master/main for v0.5.0
461-
2. **Next:** Python solver + `kspaceFirstOrder()` API + Future for v0.6.0
462-
3. **Then:** C-order migration of helpers/utils for v0.6.1
463-
4. **Then:** Port remaining examples to new API for v0.6.2
464-
5. **Then:** Axisymmetric support in new API for v0.6.3
465-
6. **Then:** `kwp` CLI for v0.7.0
466-
7. **Then:** Clean delete for v1.0.0
467-
8. **Post-1.0:** Devito, nanobind/MPI based on profiling and user demand
468-
469-
---
470-
471-
## Critical Files
472-
473-
| File | Action | Version |
474-
|------|--------|---------|
475-
| `kwave/solvers/kspace_solver.py` | Finalize native solver | 0.6.0 |
476-
| `kwave/solvers/native.py` | Finalize | 0.6.0 |
477-
| `kwave/solvers/kwave_adapter.py` | Finalize | 0.6.0 |
478-
| `kwave/kspaceFirstOrder.py` | Create unified entry point | 0.6.0 |
479-
| `kwave/solvers/serializer.py` | Create HDF5 writer | 0.6.0 |
480-
| `kwave/kspaceFirstOrder2D.py` | Simplify to wrapper | 0.6.0 |
481-
| `kwave/kspaceFirstOrder3D.py` | Simplify to wrapper | 0.6.0 |
482-
| `kwave/options/simulation_options.py` | Delete | 1.0.0 |
483-
| `kwave/options/simulation_execution_options.py` | Delete | 1.0.0 |
484-
| `kwave/kWaveSimulation.py` | Delete | 1.0.0 |
298+
1. ~~v0.5.0~~ ✅ Stabilize master
299+
2. ~~v0.6.0~~ ✅ Python solver + unified API + deprecations
300+
3. ~~v0.6.1~~ ✅ C-order + examples + docs cleanup
301+
4. **Next:** v0.6.2 — Tier 2 features + examples
302+
5. **Then:** v0.6.3 — Axisymmetric support
303+
6. **Then:** v0.7.0 — CLI (`kwp`)
304+
7. **Then:** v1.0.0 — Clean release (delete deprecated code)
305+
8. **Post-1.0:** Performance & scale based on profiling

0 commit comments

Comments
 (0)