k-Wave-python 0.6.0__tar.gz → 0.6.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. k_wave_python-0.6.2/.git +1 -0
  2. k_wave_python-0.6.2/CLAUDE.md +95 -0
  3. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/PKG-INFO +34 -42
  4. k_wave_python-0.6.2/docs/README.md +66 -0
  5. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/__init__.py +60 -7
  6. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/compat.py +4 -0
  7. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/enums.py +12 -0
  8. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/executor.py +8 -1
  9. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/kWaveSimulation_helper/create_absorption_variables.py +4 -4
  10. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/kgrid.py +1 -1
  11. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/kmedium.py +57 -44
  12. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/kspaceFirstOrder.py +112 -8
  13. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/kspaceFirstOrder2D.py +5 -0
  14. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/kspaceFirstOrder3D.py +5 -0
  15. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/solvers/cpp_simulation.py +97 -14
  16. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/solvers/kspace_solver.py +294 -114
  17. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/utils/checks.py +62 -0
  18. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/utils/conversion.py +22 -10
  19. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/utils/filters.py +22 -8
  20. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/utils/kwave_array.py +49 -26
  21. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/utils/mapgen.py +38 -35
  22. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/utils/math.py +2 -4
  23. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/utils/plot.py +2 -2
  24. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/utils/typing.py +16 -2
  25. k_wave_python-0.6.2/plans/release-strategy.md +364 -0
  26. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/pyproject.toml +17 -15
  27. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/pytest.ini +1 -0
  28. k_wave_python-0.6.2/uv.lock +2691 -0
  29. k_wave_python-0.6.0/.claude/settings.local.json +0 -45
  30. k_wave_python-0.6.0/Makefile +0 -44
  31. k_wave_python-0.6.0/docs/README.md +0 -76
  32. k_wave_python-0.6.0/htmlcov/.gitignore +0 -2
  33. k_wave_python-0.6.0/htmlcov/class_index.html +0 -733
  34. k_wave_python-0.6.0/htmlcov/coverage_html_cb_6fb7b396.js +0 -733
  35. k_wave_python-0.6.0/htmlcov/function_index.html +0 -4913
  36. k_wave_python-0.6.0/htmlcov/index.html +0 -488
  37. k_wave_python-0.6.0/htmlcov/status.json +0 -1
  38. k_wave_python-0.6.0/htmlcov/style_cb_8e611ae1.css +0 -337
  39. k_wave_python-0.6.0/htmlcov/z_008abe0f134486c2___init___py.html +0 -99
  40. k_wave_python-0.6.0/htmlcov/z_008abe0f134486c2_checks_py.html +0 -396
  41. k_wave_python-0.6.0/htmlcov/z_008abe0f134486c2_colormap_py.html +0 -192
  42. k_wave_python-0.6.0/htmlcov/z_008abe0f134486c2_conversion_py.html +0 -605
  43. k_wave_python-0.6.0/htmlcov/z_008abe0f134486c2_data_py.html +0 -307
  44. k_wave_python-0.6.0/htmlcov/z_008abe0f134486c2_dotdictionary_py.html +0 -156
  45. k_wave_python-0.6.0/htmlcov/z_008abe0f134486c2_filters_py.html +0 -700
  46. k_wave_python-0.6.0/htmlcov/z_008abe0f134486c2_interp_py.html +0 -492
  47. k_wave_python-0.6.0/htmlcov/z_008abe0f134486c2_io_py.html +0 -593
  48. k_wave_python-0.6.0/htmlcov/z_008abe0f134486c2_mapgen_py.html +0 -3212
  49. k_wave_python-0.6.0/htmlcov/z_008abe0f134486c2_math_py.html +0 -566
  50. k_wave_python-0.6.0/htmlcov/z_008abe0f134486c2_matlab_py.html +0 -264
  51. k_wave_python-0.6.0/htmlcov/z_008abe0f134486c2_matrix_py.html +0 -537
  52. k_wave_python-0.6.0/htmlcov/z_008abe0f134486c2_pml_py.html +0 -250
  53. k_wave_python-0.6.0/htmlcov/z_008abe0f134486c2_signals_py.html +0 -833
  54. k_wave_python-0.6.0/htmlcov/z_008abe0f134486c2_tictoc_py.html +0 -143
  55. k_wave_python-0.6.0/htmlcov/z_008abe0f134486c2_typing_py.html +0 -133
  56. k_wave_python-0.6.0/htmlcov/z_08ccaf6f6fd0d069___init___py.html +0 -106
  57. k_wave_python-0.6.0/htmlcov/z_08ccaf6f6fd0d069_create_absorption_variables_py.html +0 -207
  58. k_wave_python-0.6.0/htmlcov/z_08ccaf6f6fd0d069_display_simulation_params_py.html +0 -191
  59. k_wave_python-0.6.0/htmlcov/z_08ccaf6f6fd0d069_expand_grid_matrices_py.html +0 -411
  60. k_wave_python-0.6.0/htmlcov/z_08ccaf6f6fd0d069_retract_transducer_grid_size_py.html +0 -121
  61. k_wave_python-0.6.0/htmlcov/z_08ccaf6f6fd0d069_save_to_disk_func_py.html +0 -622
  62. k_wave_python-0.6.0/htmlcov/z_08ccaf6f6fd0d069_scale_source_terms_func_py.html +0 -494
  63. k_wave_python-0.6.0/htmlcov/z_08ccaf6f6fd0d069_set_sound_speed_ref_py.html +0 -190
  64. k_wave_python-0.6.0/htmlcov/z_af83d3eb1fd99cb4___init___py.html +0 -110
  65. k_wave_python-0.6.0/htmlcov/z_af83d3eb1fd99cb4_simulation_execution_options_py.html +0 -342
  66. k_wave_python-0.6.0/htmlcov/z_af83d3eb1fd99cb4_simulation_options_py.html +0 -449
  67. k_wave_python-0.6.0/htmlcov/z_c3dba8f0d3a212d1___init___py.html +0 -304
  68. k_wave_python-0.6.0/htmlcov/z_c3dba8f0d3a212d1_data_py.html +0 -220
  69. k_wave_python-0.6.0/htmlcov/z_c3dba8f0d3a212d1_enums_py.html +0 -121
  70. k_wave_python-0.6.0/htmlcov/z_c3dba8f0d3a212d1_executor_py.html +0 -242
  71. k_wave_python-0.6.0/htmlcov/z_c3dba8f0d3a212d1_kWaveSimulation_py.html +0 -1593
  72. k_wave_python-0.6.0/htmlcov/z_c3dba8f0d3a212d1_kgrid_py.html +0 -800
  73. k_wave_python-0.6.0/htmlcov/z_c3dba8f0d3a212d1_kmedium_py.html +0 -331
  74. k_wave_python-0.6.0/htmlcov/z_c3dba8f0d3a212d1_ksensor_py.html +0 -241
  75. k_wave_python-0.6.0/htmlcov/z_c3dba8f0d3a212d1_ksource_py.html +0 -481
  76. k_wave_python-0.6.0/htmlcov/z_c3dba8f0d3a212d1_kspaceFirstOrder2D_py.html +0 -547
  77. k_wave_python-0.6.0/htmlcov/z_c3dba8f0d3a212d1_ktransducer_py.html +0 -863
  78. k_wave_python-0.6.0/htmlcov/z_c3dba8f0d3a212d1_recorder_py.html +0 -242
  79. k_wave_python-0.6.0/htmlcov/z_c6e89a0ff279d0c3___init___py.html +0 -110
  80. k_wave_python-0.6.0/htmlcov/z_c6e89a0ff279d0c3_time_reversal_py.html +0 -243
  81. k_wave_python-0.6.0/plans/release-strategy.md +0 -283
  82. k_wave_python-0.6.0/run_examples.py +0 -26
  83. k_wave_python-0.6.0/uv.lock +0 -2256
  84. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/.gitignore +0 -0
  85. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/.pre-commit-config.yaml +0 -0
  86. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/.readthedocs.yaml +0 -0
  87. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/CITATION.cff +0 -0
  88. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/Dockerfile +0 -0
  89. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/LICENSE +0 -0
  90. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/data.py +0 -0
  91. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/kWaveSimulation.py +0 -0
  92. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/kWaveSimulation_helper/__init__.py +0 -0
  93. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/kWaveSimulation_helper/display_simulation_params.py +0 -0
  94. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/kWaveSimulation_helper/expand_grid_matrices.py +0 -0
  95. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/kWaveSimulation_helper/retract_transducer_grid_size.py +0 -0
  96. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/kWaveSimulation_helper/save_to_disk_func.py +0 -0
  97. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/kWaveSimulation_helper/scale_source_terms_func.py +0 -0
  98. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/kWaveSimulation_helper/set_sound_speed_ref.py +0 -0
  99. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/ksensor.py +0 -0
  100. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/ksource.py +0 -0
  101. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/kspaceFirstOrderAS.py +0 -0
  102. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/kspaceLineRecon.py +0 -0
  103. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/kspacePlaneRecon.py +0 -0
  104. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/ktransducer.py +0 -0
  105. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/options/__init__.py +0 -0
  106. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/options/simulation_execution_options.py +0 -0
  107. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/options/simulation_options.py +0 -0
  108. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/reconstruction/__init__.py +0 -0
  109. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/reconstruction/beamform.py +0 -0
  110. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/reconstruction/time_reversal.py +0 -0
  111. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/reconstruction/tools.py +0 -0
  112. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/recorder.py +0 -0
  113. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/solvers/__init__.py +0 -0
  114. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/solvers/native.py +0 -0
  115. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/solvers/validation.py +0 -0
  116. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/utils/__init__.py +0 -0
  117. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/utils/angular_spectrum.py +0 -0
  118. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/utils/angular_spectrum_cw.py +0 -0
  119. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/utils/atten_comp.py +0 -0
  120. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/utils/colormap.py +0 -0
  121. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/utils/data.py +0 -0
  122. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/utils/dotdictionary.py +0 -0
  123. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/utils/interp.py +0 -0
  124. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/utils/io.py +0 -0
  125. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/utils/matlab.py +0 -0
  126. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/utils/matrix.py +0 -0
  127. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/utils/pml.py +0 -0
  128. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/utils/sharpness_filters.py +0 -0
  129. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/utils/signals.py +0 -0
  130. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/kwave/utils/tictoc.py +0 -0
  131. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/make_docs.sh +0 -0
  132. {k_wave_python-0.6.0 → k_wave_python-0.6.2}/run_tests.sh +0 -0
@@ -0,0 +1 @@
1
+ gitdir: /Users/Walter/git/k-wave-python/.git/worktrees/kwave-v0.6.2
@@ -0,0 +1,95 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## What is k-wave-python?
6
+
7
+ Python implementation of the [k-Wave](http://www.k-wave.org/) acoustics toolbox for time-domain acoustic and ultrasound simulations. Two backends: a pure Python/NumPy/CuPy solver and C++ binaries (OMP/CUDA).
8
+
9
+ ## Commands
10
+
11
+ ```bash
12
+ # Setup
13
+ uv sync --extra dev --extra test
14
+ uv run pre-commit install
15
+
16
+ # Run tests
17
+ uv run pytest # all tests
18
+ uv run pytest tests/test_kgrid.py # single file
19
+ uv run pytest tests/test_kgrid.py::test_name # single test
20
+ uv run pytest -m integration # MATLAB-reference tests only
21
+
22
+ # Lint/format
23
+ uv run ruff check . --fix
24
+ uv run ruff format .
25
+ uv run pre-commit run --all-files
26
+
27
+ # Run an example
28
+ uv run examples/ivp_homogeneous_medium.py
29
+
30
+ # Build
31
+ uv build
32
+ ```
33
+
34
+ Always use `uv run` (not `uv run python`) for pytest, examples, and scripts.
35
+
36
+ ## Code Style
37
+
38
+ - Line length: 140 (configured in `pyproject.toml` under `[tool.ruff]`)
39
+ - Pre-commit hooks: ruff (lint + format), codespell, nb-clean
40
+ - Ruff ignores F821 (nested function refs) and F722 (jaxtyping annotations)
41
+ - Type annotations use `beartype` + `jaxtyping`
42
+
43
+ ## Architecture
44
+
45
+ ### Entry point
46
+
47
+ `kwave/kspaceFirstOrder.py` — `kspaceFirstOrder()` is the unified API. It accepts `kgrid`, `medium`, `source`, `sensor` and dispatches to the appropriate backend.
48
+
49
+ ```
50
+ kspaceFirstOrder(kgrid, medium, source, sensor, backend="python"|"cpp", device="cpu"|"gpu")
51
+ ```
52
+
53
+ ### Two backends
54
+
55
+ - **Python backend** (`kwave/solvers/kspace_solver.py`): `Simulation` class implementing k-space pseudospectral method in NumPy/CuPy. Supports 1D/2D/3D. Uses CuPy for GPU when `device="gpu"`.
56
+ - **C++ backend** (`kwave/solvers/cpp_simulation.py` + `kwave/executor.py`): Serializes to HDF5, invokes compiled C++ binary, reads results back. `save_only=True` writes HDF5 without running (for cluster jobs).
57
+
58
+ ### Core data classes
59
+
60
+ - `kWaveGrid` (`kwave/kgrid.py`) — domain discretization, spacing, time array
61
+ - `kWaveMedium` (`kwave/kmedium.py`) — sound speed, density, absorption, nonlinearity
62
+ - `kSource` (`kwave/ksource.py`) — pressure/velocity sources with masks and signals
63
+ - `kSensor` (`kwave/ksensor.py`) — sensor mask and recording configuration
64
+
65
+ ### Legacy path
66
+
67
+ `kspaceFirstOrder2D()` / `kspaceFirstOrder3D()` in their respective files route through `kWaveSimulation` (`kwave/kWaveSimulation.py`) — a large legacy dataclass used by the C++ backend path. New code should use `kspaceFirstOrder()` directly.
68
+
69
+ ### PML handling
70
+
71
+ When `pml_inside=False` (default), `kspaceFirstOrder()` expands the grid by `2*pml_size` before simulation and strips PML from full-grid output fields afterward. `pml_size="auto"` selects optimal sizes via `get_optimal_pml_size()`.
72
+
73
+ ### Key utilities
74
+
75
+ - `kwave/utils/pml.py` — PML sizing (`get_pml()`, `get_optimal_pml_size()`)
76
+ - `kwave/utils/mapgen.py` — geometry generators (`make_disc`, `make_ball`, `make_cart_circle`, etc.)
77
+ - `kwave/utils/signals.py` — signal generation (tone bursts, filtering)
78
+ - `kwave/utils/filters.py` — spatial smoothing, Gaussian filters
79
+ - `kwave/utils/io.py` — HDF5 read/write
80
+ - `kwave/utils/conversion.py` — unit conversion, `cart2grid`
81
+
82
+ ## Testing
83
+
84
+ - Tests in `tests/`, configured via `[tool.pytest.ini_options]` in `pyproject.toml`
85
+ - Integration tests (`@pytest.mark.integration`) compare against MATLAB reference data
86
+ - Test fixtures in `tests/integration/conftest.py`: `load_matlab_ref` (fixture), `assert_fields_close` (helper function for field comparison)
87
+ - MATLAB reference data for `@pytest.mark.integration` tests lives in `tests/matlab_test_data_collectors/python_testers/collectedValues/` (hardcoded in `conftest.py`)
88
+ - `test_example_parity.py` (MATLAB-parity tests) reads `KWAVE_MATLAB_REF_DIR` (defaults to `~/git/k-wave-cupy/tests` if unset)
89
+
90
+ ## Naming Conventions
91
+
92
+ - `backend="python"` or `"cpp"` (not "native")
93
+ - `device="cpu"` or `"gpu"` (not `use_gpu` bool)
94
+ - `quiet=True` to suppress output; `debug=True` for detailed output
95
+ - `pml_size="auto"` for automatic PML sizing (not a separate boolean)
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: k-Wave-python
3
- Version: 0.6.0
3
+ Version: 0.6.2
4
4
  Summary: Acoustics toolbox for time domain acoustic and ultrasound simulations in complex and tissue-realistic media.
5
5
  Project-URL: Homepage, http://www.k-wave.org/
6
6
  Project-URL: Documentation, https://waltersimson.com/k-wave-python/
7
7
  Project-URL: Repository, https://github.com/waltsims/k-wave-python
8
8
  Project-URL: Bug-tracker, https://github.com/waltsims/k-wave-python/issues
9
- Author-email: Farid Yagubbayli <farid.yagubbayli@tum.de>, Walter Simson <walter.simson@tum.de>
10
- Maintainer-email: Walter Simson <walter.simson@tum.de>, Farid Yagubbayli <farid.yagubbayli@tum.de>, David Sinden <david.sinden@mevis.fraunhofer.de>
9
+ Author-email: Farid Yagubbayli <farid.yagubbayli@tum.de>, Walter Simson <walter.a.simson@gmail.com>
10
+ Maintainer-email: Walter Simson <walter.a.simson@gmail.com>, Farid Yagubbayli <farid.yagubbayli@tum.de>, David Sinden <david.sinden@mevis.fraunhofer.de>
11
11
  License: GNU LESSER GENERAL PUBLIC LICENSE
12
12
  Version 3, 29 June 2007
13
13
 
@@ -179,30 +179,32 @@ Classifier: Operating System :: OS Independent
179
179
  Classifier: Programming Language :: Python :: 3
180
180
  Requires-Python: >=3.10
181
181
  Requires-Dist: beartype==0.22.9
182
- Requires-Dist: deepdiff==8.6.1
182
+ Requires-Dist: deepdiff==9.0.0
183
183
  Requires-Dist: deprecated>=1.2.14
184
- Requires-Dist: h5py==3.15.1
185
- Requires-Dist: jaxtyping==0.3.2
186
- Requires-Dist: matplotlib==3.10.7
184
+ Requires-Dist: h5py==3.16.0
185
+ Requires-Dist: jaxtyping==0.3.7
186
+ Requires-Dist: matplotlib==3.10.9
187
187
  Requires-Dist: numpy<2.3.0,>=1.22.2
188
188
  Requires-Dist: opencv-python==4.13.0.92
189
189
  Requires-Dist: scipy==1.15.3
190
+ Requires-Dist: tqdm>=4.60
190
191
  Provides-Extra: dev
191
- Requires-Dist: pre-commit==4.5.1; extra == 'dev'
192
+ Requires-Dist: pre-commit==4.6.0; extra == 'dev'
192
193
  Provides-Extra: docs
193
- Requires-Dist: furo==2024.8.6; extra == 'docs'
194
+ Requires-Dist: furo==2025.12.19; extra == 'docs'
194
195
  Requires-Dist: sphinx-copybutton==0.5.2; extra == 'docs'
195
196
  Requires-Dist: sphinx-mdinclude==0.6.2; extra == 'docs'
196
- Requires-Dist: sphinx-tabs==3.4.7; extra == 'docs'
197
- Requires-Dist: sphinx-toolbox==3.8.0; extra == 'docs'
197
+ Requires-Dist: sphinx-tabs==3.4.5; extra == 'docs'
198
+ Requires-Dist: sphinx-toolbox==4.1.2; extra == 'docs'
199
+ Requires-Dist: sphinx<9; extra == 'docs'
198
200
  Provides-Extra: example
199
- Requires-Dist: gdown==5.2.0; extra == 'example'
201
+ Requires-Dist: gdown==6.0.0; extra == 'example'
200
202
  Provides-Extra: test
201
- Requires-Dist: coverage==7.10.6; extra == 'test'
203
+ Requires-Dist: coverage==7.14.0; extra == 'test'
202
204
  Requires-Dist: phantominator; extra == 'test'
203
205
  Requires-Dist: pytest; extra == 'test'
204
206
  Requires-Dist: pytest-xdist; extra == 'test'
205
- Requires-Dist: requests==2.32.5; extra == 'test'
207
+ Requires-Dist: requests==2.34.0; extra == 'test'
206
208
  Requires-Dist: testfixtures==8.3.0; extra == 'test'
207
209
  Description-Content-Type: text/markdown
208
210
 
@@ -211,52 +213,42 @@ Description-Content-Type: text/markdown
211
213
  [![Support](https://img.shields.io/discord/1234942672418897960?style=flat&logo=discord)](https://discord.gg/your-invite-code)
212
214
  [![Documentation Status](https://readthedocs.org/projects/k-wave-python/badge/?version=latest)](https://k-wave-python.readthedocs.io/en/latest/?badge=latest)
213
215
  [![codecov](https://codecov.io/gh/waltsims/k-wave-python/graph/badge.svg?token=6ofwtPiDNG)](https://codecov.io/gh/waltsims/k-wave-python)
214
- [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/waltsims/k-wave-python/master)
215
216
 
216
- 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
217
- 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.
218
-
219
- **New in v0.6.0:** Unified `kspaceFirstOrder()` API with a pure NumPy/CuPy solver. See the [API guide](https://k-wave-python.readthedocs.io/en/latest/get_started/new_api.html).
217
+ A Python implementation of [k-Wave](http://www.k-wave.org/) an acoustics toolbox for time-domain simulation of acoustic wave fields. Includes a pure NumPy/CuPy solver (`backend="python"`) and an interface to the pre-compiled k-Wave C++ binaries (`backend="cpp"`) with NVIDIA GPU support (sm 5.0–9.0a).
220
218
 
221
219
  ## Mission
222
220
 
223
- With this project, we hope to increase the accessibility and reproducibility of [k-Wave](http://www.k-wave.org/) simulations
224
- for medical imaging, algorithmic prototyping, and testing. Many tools and methods of [k-Wave](http://www.k-wave.org/) can
225
- be found here, but this project has and will continue to diverge from the original [k-Wave](http://www.k-wave.org/) APIs
226
- to leverage pythonic practices.
221
+ Increase the accessibility and reproducibility of [k-Wave](http://www.k-wave.org/) simulations for medical imaging, algorithmic prototyping, and testing.
227
222
 
228
223
  ## Getting started
229
224
 
230
225
  ![](_static/example_bmode.png)
231
226
 
232
- A large [collection of examples](../examples/) exists to get started with k-wave-python. All examples can be run in Google Colab notebooks with a few clicks. One can begin with e.g. the [B-mode reconstruction example notebook](https://colab.research.google.com/github/waltsims/k-wave-python/blob/HEAD/examples/us_bmode_linear_transducer/us_bmode_linear_transducer.ipynb).
227
+ A [collection of examples](../examples/) covers common simulation scenarios. Run any example locally:
228
+
229
+ ```bash
230
+ uv run examples/ivp_homogeneous_medium.py
231
+ ```
233
232
 
234
- This example file steps through the process of:
235
- 1. Generating a simulation medium
236
- 2. Configuring a transducer
237
- 3. Running the simulation
238
- 4. Reconstructing the simulation
233
+ No GPU required all examples run on CPU with NumPy.
239
234
 
240
235
  ## Installation
241
236
 
242
- To install the most recent build of k-Wave-python from PyPI, run:
237
+ Using [uv](https://docs.astral.sh/uv/) (recommended):
238
+
239
+ ```bash
240
+ uv add k-wave-python
241
+ ```
242
+
243
+ Or with pip:
243
244
 
244
245
  ```bash
245
246
  pip install k-wave-python
246
247
  ```
247
- > **Note for MacOS:**
248
- >
249
- > k-wave-python offers initial support for MacOS, but you will need to install the following dependencies using the [brew package manager](https://docs.brew.sh/Installation) along with the Python package:
250
- > ```bash
251
- > brew install fftw hdf5 zlib libomp
252
- > ```
253
- After installing the Python package, the required binaries will be downloaded and installed the first time you run a
254
- simulation.
255
248
 
256
249
  ## Development
257
250
 
258
- If you're enjoying k-Wave-python and want to contribute, development instructions can be
259
- found [here](https://k-wave-python.readthedocs.io/en/latest/development/development_environment.html).
251
+ Development instructions can be found [here](https://k-wave-python.readthedocs.io/en/latest/development/development_environment.html).
260
252
 
261
253
  ## Related Projects
262
254
 
@@ -273,7 +265,7 @@ The documentation for k-wave-python can be found [here](https://k-wave-python.re
273
265
  ## Citation
274
266
  ```bibtex
275
267
  @software{k-Wave-Python,
276
- author = {Yagubbbayli, Farid and Sinden, David and Simson, Walter},
268
+ author = {Yagubbayli, Farid and Sinden, David and Simson, Walter},
277
269
  license = {GPL-3.0},
278
270
  title = {{k-Wave-Python}},
279
271
  url = {https://github.com/waltsims/k-wave-python}
@@ -281,4 +273,4 @@ url = {https://github.com/waltsims/k-wave-python}
281
273
  ```
282
274
  ## Contact
283
275
 
284
- e-mail [wsimson@stanford.edu](mailto:wsimson@stanford.edu).
276
+ e-mail [walter.a.simson@gmail.com](mailto:walter.a.simson@gmail.com).
@@ -0,0 +1,66 @@
1
+ # k-wave-python
2
+
3
+ [![Support](https://img.shields.io/discord/1234942672418897960?style=flat&logo=discord)](https://discord.gg/your-invite-code)
4
+ [![Documentation Status](https://readthedocs.org/projects/k-wave-python/badge/?version=latest)](https://k-wave-python.readthedocs.io/en/latest/?badge=latest)
5
+ [![codecov](https://codecov.io/gh/waltsims/k-wave-python/graph/badge.svg?token=6ofwtPiDNG)](https://codecov.io/gh/waltsims/k-wave-python)
6
+
7
+ A Python implementation of [k-Wave](http://www.k-wave.org/) — an acoustics toolbox for time-domain simulation of acoustic wave fields. Includes a pure NumPy/CuPy solver (`backend="python"`) and an interface to the pre-compiled k-Wave C++ binaries (`backend="cpp"`) with NVIDIA GPU support (sm 5.0–9.0a).
8
+
9
+ ## Mission
10
+
11
+ Increase the accessibility and reproducibility of [k-Wave](http://www.k-wave.org/) simulations for medical imaging, algorithmic prototyping, and testing.
12
+
13
+ ## Getting started
14
+
15
+ ![](_static/example_bmode.png)
16
+
17
+ A [collection of examples](../examples/) covers common simulation scenarios. Run any example locally:
18
+
19
+ ```bash
20
+ uv run examples/ivp_homogeneous_medium.py
21
+ ```
22
+
23
+ No GPU required — all examples run on CPU with NumPy.
24
+
25
+ ## Installation
26
+
27
+ Using [uv](https://docs.astral.sh/uv/) (recommended):
28
+
29
+ ```bash
30
+ uv add k-wave-python
31
+ ```
32
+
33
+ Or with pip:
34
+
35
+ ```bash
36
+ pip install k-wave-python
37
+ ```
38
+
39
+ ## Development
40
+
41
+ Development instructions can be found [here](https://k-wave-python.readthedocs.io/en/latest/development/development_environment.html).
42
+
43
+ ## Related Projects
44
+
45
+ 1. [k-Wave](https://github.com/ucl-bug/k-wave): A MATLAB toolbox for the time-domain simulation of acoustic wave fields.
46
+ 2. [j-wave](https://github.com/ucl-bug/jwave): Differentiable acoustic simulations in JAX.
47
+ 3. [ADSeismic.jl](https://github.com/kailaix/ADSeismic.jl): a finite difference acoustic simulator with support for AD
48
+ and JIT compilation in Julia.
49
+ 4. [stride](https://github.com/trustimaging/stride): a general optimisation framework for medical ultrasound tomography.
50
+
51
+ ## Documentation
52
+
53
+ The documentation for k-wave-python can be found [here](https://k-wave-python.readthedocs.io/en/latest/).
54
+
55
+ ## Citation
56
+ ```bibtex
57
+ @software{k-Wave-Python,
58
+ author = {Yagubbayli, Farid and Sinden, David and Simson, Walter},
59
+ license = {GPL-3.0},
60
+ title = {{k-Wave-Python}},
61
+ url = {https://github.com/waltsims/k-wave-python}
62
+ }
63
+ ```
64
+ ## Contact
65
+
66
+ e-mail [walter.a.simson@gmail.com](mailto:walter.a.simson@gmail.com).
@@ -3,23 +3,45 @@ import json
3
3
  import logging
4
4
  import os
5
5
  import platform
6
+ import stat
7
+ import warnings
6
8
  from pathlib import Path
7
9
  from typing import List
8
10
  from urllib.request import urlretrieve
9
11
 
10
12
  # Test installation with:
11
13
  # 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"
14
+ __version__ = "0.6.2"
13
15
 
14
16
  # Constants and Configurations
15
17
  URL_BASE = "https://github.com/waltsims/"
16
- BINARY_VERSION = "v1.3.0"
17
- PREFIX = f"{URL_BASE}kspaceFirstOrder-{{}}-{{}}/releases/download/{BINARY_VERSION}/"
18
+ BINARY_VERSION = "v1.4.1"
19
+ # Pin both Windows binaries to v1.3.0. v1.4.x windows builds switched compiler /
20
+ # OpenMP / FFT / CUDA runtime stacks and neither v1.4.x release ships its runtime
21
+ # DLLs (cufft, cudart, vcomp, vcruntime140_1, fftw3f, etc.). v1.3.0 binaries are
22
+ # self-contained with their Intel-era DLL bundle (listed in WINDOWS_DLLS below,
23
+ # downloaded with the OMP request and used by both .exe files since they share
24
+ # kwave/bin/windows/). OMP DLL bundling is fixed in kspacefirstorder-unified#14
25
+ # (awaiting validation); CUDA DLL bundling is tracked in kspacefirstorder-unified#17.
26
+ WINDOWS_OMP_VERSION = "v1.3.0"
27
+ WINDOWS_CUDA_VERSION = "v1.3.0"
18
28
  PLATFORM = platform.system().lower()
19
29
 
20
30
  if PLATFORM not in ["linux", "windows", "darwin"]:
21
31
  raise NotImplementedError(f"k-wave-python is currently unsupported on this operating system: {PLATFORM}.")
22
32
 
33
+ # darwin C++ binary is arm64-only; universal2 coverage tracked for v0.6.5
34
+ DARWIN_BINARY_ARCH = "arm64"
35
+ _darwin_unsupported = PLATFORM == "darwin" and platform.machine() != DARWIN_BINARY_ARCH
36
+ if _darwin_unsupported:
37
+ warnings.warn(
38
+ f"k-wave-python's macOS C++ binary is {DARWIN_BINARY_ARCH}-only. "
39
+ f"Detected {platform.machine()} — the C++ backend (backend='cpp') will not run on this machine. "
40
+ "Use backend='python' instead. Universal2 (Intel + Apple Silicon) coverage is tracked for v0.6.5.",
41
+ RuntimeWarning,
42
+ stacklevel=2,
43
+ )
44
+
23
45
  # TODO: install directly in to /bin/ directory system directory is no longer needed
24
46
  # TODO: deprecate in 0.5.0
25
47
  BINARY_PATH = Path(__file__).parent / "bin" / PLATFORM
@@ -44,21 +66,24 @@ ARCHITECTURES = ["omp", "cuda"]
44
66
 
45
67
 
46
68
  def get_windows_release_urls(architecture: str) -> list:
69
+ version = WINDOWS_OMP_VERSION if architecture == "omp" else WINDOWS_CUDA_VERSION
47
70
  specific_filenames = [EXECUTABLE_PREFIX + architecture + ".exe"]
48
71
  if architecture == "omp":
49
72
  specific_filenames += WINDOWS_DLLS
50
- release_urls = [PREFIX.format(architecture.upper(), PLATFORM.lower()) + filename for filename in specific_filenames]
51
- return release_urls
73
+ base = f"{URL_BASE}kspaceFirstOrder-{architecture.upper()}-{PLATFORM.lower()}/releases/download/{version}/"
74
+ return [base + filename for filename in specific_filenames]
52
75
 
53
76
 
54
77
  URL_DICT = {
55
78
  "linux": {
56
- "cuda": [URL_BASE + f"kspaceFirstOrder-CUDA-{PLATFORM}/releases/download/v1.3.1/{EXECUTABLE_PREFIX}CUDA"],
79
+ "cuda": [URL_BASE + f"kspaceFirstOrder-CUDA-{PLATFORM}/releases/download/{BINARY_VERSION}/{EXECUTABLE_PREFIX}CUDA"],
57
80
  "omp": [URL_BASE + f"kspaceFirstOrder-OMP-{PLATFORM}/releases/download/{BINARY_VERSION}/{EXECUTABLE_PREFIX}OMP"],
58
81
  },
59
82
  "darwin": {
60
83
  "cuda": [],
61
- "omp": [URL_BASE + f"k-wave-omp-{PLATFORM}/releases/download/v0.3.0rc3/{EXECUTABLE_PREFIX}OMP"],
84
+ "omp": (
85
+ [] if _darwin_unsupported else [URL_BASE + f"k-wave-omp-{PLATFORM}/releases/download/{BINARY_VERSION}/{EXECUTABLE_PREFIX}OMP"]
86
+ ),
62
87
  },
63
88
  "windows": {architecture: get_windows_release_urls(architecture) for architecture in ARCHITECTURES},
64
89
  }
@@ -77,6 +102,31 @@ def _hash_file(filepath: str) -> str:
77
102
  return md5.hexdigest()
78
103
 
79
104
 
105
+ def _ensure_executable(binary_filepath) -> None:
106
+ # Self-heal the executable bit on Linux/macOS. urlretrieve creates files
107
+ # at 0644, and prior versions of this package didn't fix that up, so users
108
+ # upgrading with a cached non-executable binary on disk would otherwise
109
+ # stay stuck (the cache check below returns True and skips re-download).
110
+ # Any OS-level failure here (broken symlink, read-only FS, wrong ownership,
111
+ # TOCTOU race) is degraded to a warning so it never aborts `import kwave`.
112
+ if PLATFORM == "windows":
113
+ return
114
+ try:
115
+ current_mode = os.stat(binary_filepath).st_mode
116
+ desired_mode = current_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
117
+ if current_mode == desired_mode:
118
+ return
119
+ os.chmod(binary_filepath, desired_mode)
120
+ except OSError: # pragma: no cover - defensive; degrades to warning, never fatal
121
+ # Don't abort import. The user can chmod +x manually or reinstall
122
+ # into a writable location.
123
+ logging.warning(
124
+ "kwave: cannot set executable bit on %s — backend='cpp' may fail with "
125
+ "Permission denied. Run `chmod +x` manually or reinstall.",
126
+ binary_filepath,
127
+ )
128
+
129
+
80
130
  def _is_binary_present(binary_name: str, binary_type: str) -> bool:
81
131
  binary_filepath = BINARY_PATH / binary_name
82
132
  binary_file_exists = os.path.exists(binary_filepath)
@@ -106,6 +156,8 @@ def _is_binary_present(binary_name: str, binary_type: str) -> bool:
106
156
  if existing_metadata["url"] not in latest_urls:
107
157
  return False
108
158
 
159
+ _ensure_executable(binary_filepath)
160
+
109
161
  # No need to check `version` field for now
110
162
  # because we version is already present in the URL
111
163
  return True
@@ -176,6 +228,7 @@ def download_binaries(system_os: str, bin_type: str):
176
228
  try:
177
229
  binary_filepath = os.path.join(BINARY_PATH, filename)
178
230
  urlretrieve(url, binary_filepath)
231
+ _ensure_executable(binary_filepath)
179
232
  _record_binary_metadata(binary_version=binary_version, binary_filepath=binary_filepath, binary_url=url, filename=filename)
180
233
 
181
234
  except TimeoutError:
@@ -70,5 +70,9 @@ def options_to_kwargs(simulation_options=None, execution_options=None):
70
70
  kwargs["num_threads"] = opts.num_threads
71
71
  if opts.device_num is not None:
72
72
  kwargs["device_num"] = opts.device_num
73
+ # Read _binary_path directly: the property auto-resolves to a default,
74
+ # so it can't distinguish a user-set path from one.
75
+ if opts._binary_path is not None:
76
+ kwargs["binary_path"] = opts._binary_path
73
77
 
74
78
  return kwargs
@@ -1,5 +1,17 @@
1
1
  from enum import Enum
2
2
 
3
+
4
+ class AlphaMode(str, Enum):
5
+ """Controls which absorption/dispersion terms are included in the equation of state."""
6
+
7
+ NO_ABSORPTION = "no_absorption"
8
+ NO_DISPERSION = "no_dispersion"
9
+ STOKES = "stokes"
10
+
11
+ def __str__(self):
12
+ return self.value
13
+
14
+
3
15
  ################################################################
4
16
  # literals that link the discrete cosine and sine transform types with
5
17
  # their type definitions in the functions dtt1D, dtt2D, and dtt3D
@@ -52,9 +52,16 @@ class Executor:
52
52
  raise subprocess.CalledProcessError(proc.returncode, command, stdout, stderr)
53
53
 
54
54
  except subprocess.CalledProcessError as e:
55
- # This ensures stdout is printed regardless of show_sim_logs value if an error occurs
56
55
  print(e.stdout)
57
56
  print(e.stderr, file=sys.stderr)
57
+ if sys.platform == "darwin" and e.stderr and any(s in e.stderr for s in ("Library not loaded", "image not found", "dyld")):
58
+ print(
59
+ "\nMissing macOS libraries for the C++ backend.\n"
60
+ "Install them with:\n\n"
61
+ " brew install fftw hdf5 zlib libomp\n\n"
62
+ "Alternatively, use backend='python' which requires no extra dependencies.",
63
+ file=sys.stderr,
64
+ )
58
65
  raise
59
66
 
60
67
  sensor_data = self.parse_executable_output(output_filename)
@@ -12,19 +12,19 @@ def create_absorption_variables(kgrid: kWaveGrid, medium: kWaveMedium, equation_
12
12
  # define the lossy derivative operators and proportionality coefficients
13
13
  """
14
14
  Selects and returns absorption and dispersion operators and coefficients for the given medium based on the equation of state.
15
-
15
+
16
16
  Parameters:
17
17
  kgrid (kWaveGrid): Grid object providing wavenumber array via `kgrid.k`.
18
18
  medium (kWaveMedium): Medium properties used to compute absorption/dispersion coefficients.
19
19
  equation_of_state (str): One of `"absorbing"`, `"stokes"`, or `"lossless"` determining which variables to produce.
20
-
20
+
21
21
  Returns:
22
22
  tuple: (nabla1, nabla2, tau, eta)
23
23
  - nabla1: First-order absorption operator or `None` when not applicable.
24
24
  - nabla2: Dispersion operator or `None` when not applicable.
25
25
  - tau: Absorbing coefficient or `None` when not applicable.
26
26
  - eta: Dispersive coefficient or `None` when not applicable.
27
-
27
+
28
28
  Behavior:
29
29
  - "absorbing": returns (nabla1, nabla2, tau, eta) computed for an absorbing medium.
30
30
  - "stokes": returns (None, None, tau, None) where `tau` is the Stokes absorbing coefficient.
@@ -127,4 +127,4 @@ def apply_alpha_filter(medium, nabla1, nabla2):
127
127
  # shift the parameters back
128
128
  nabla1 = np.fft.ifftshift(nabla1)
129
129
  nabla2 = np.fft.ifftshift(nabla2)
130
- return nabla1, nabla2
130
+ return nabla1, nabla2
@@ -108,7 +108,7 @@ class kWaveGrid(object):
108
108
  @t_array.setter
109
109
  def t_array(self, t_array):
110
110
  # check for 'auto' input
111
- if t_array == "auto":
111
+ if isinstance(t_array, str) and t_array == "auto":
112
112
  # set values to auto
113
113
  self.Nt = "auto"
114
114
  self.dt = "auto"