Skip to content

Commit 6d5e80c

Browse files
waltsimsclaude
andcommitted
Add tests for _f_to_c_source_reorder covering all branches
Tests: 1D noop, 2D/3D multi-source reordering, single-source noop, uniform broadcast noop, missing mask, scalar mask, velocity sources. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent df6cfb9 commit 6d5e80c

1 file changed

Lines changed: 96 additions & 0 deletions

File tree

tests/test_c_order.py

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from kwave.ksensor import kSensor
1111
from kwave.ksource import kSource
1212
from kwave.kspaceFirstOrder import reshape_to_grid
13+
from kwave.solvers.kspace_solver import _f_to_c_source_reorder
1314

1415
# ---------------------------------------------------------------------------
1516
# _fix_output_order (CppSimulation)
@@ -141,6 +142,101 @@ def test_passthrough_higher_dim(self):
141142
assert out.shape == (2, 3, 4, 5)
142143

143144

145+
# ---------------------------------------------------------------------------
146+
# _f_to_c_source_reorder (MATLAB interop)
147+
# ---------------------------------------------------------------------------
148+
149+
150+
class TestFToCSourceReorder:
151+
def test_1d_noop(self):
152+
"""1D grids have no F/C ordering difference — source unchanged."""
153+
source = {"p_mask": np.array([0, 1, 0, 1, 0, 0, 0, 0], dtype=bool), "p": np.array([[10, 11], [20, 21]])}
154+
out = _f_to_c_source_reorder(source, (8,))
155+
np.testing.assert_array_equal(out["p"], np.array([[10, 11], [20, 21]]))
156+
157+
def test_pressure_multi_source_2d(self):
158+
"""Multi-row pressure source rows are reordered from F-flat to C-flat."""
159+
grid_shape = (3, 4)
160+
mask = np.zeros(grid_shape, dtype=bool)
161+
mask[0, 0] = True # F-idx 0, C-idx 0
162+
mask[1, 0] = True # F-idx 1, C-idx 4
163+
mask[0, 1] = True # F-idx 3, C-idx 1
164+
165+
# Signal rows in F-flat order: row0→(0,0), row1→(1,0), row2→(0,1)
166+
p_signal = np.array([[100, 101], [200, 201], [300, 301]])
167+
source = {"p_mask": mask, "p": p_signal.copy()}
168+
out = _f_to_c_source_reorder(source, grid_shape)
169+
170+
# C-flat order: (0,0)=idx0, (0,1)=idx1, (1,0)=idx4
171+
# So C-flat rows should be: (0,0), (0,1), (1,0) = F-rows 0, 2, 1
172+
np.testing.assert_array_equal(out["p"][0], [100, 101]) # (0,0)
173+
np.testing.assert_array_equal(out["p"][1], [300, 301]) # (0,1)
174+
np.testing.assert_array_equal(out["p"][2], [200, 201]) # (1,0)
175+
176+
def test_velocity_multi_source_2d(self):
177+
"""Multi-row velocity source rows are reordered."""
178+
grid_shape = (3, 4)
179+
mask = np.zeros(grid_shape, dtype=bool)
180+
mask[0, 0] = True
181+
mask[2, 1] = True # F-idx 5, C-idx 6
182+
183+
ux = np.array([[10, 11], [20, 21]])
184+
source = {"u_mask": mask, "ux": ux.copy(), "uy": None}
185+
out = _f_to_c_source_reorder(source, grid_shape)
186+
# With only 2 points, check that reorder happened (or is identity if indices align)
187+
assert out["ux"].shape == (2, 2)
188+
189+
def test_single_source_noop(self):
190+
"""Single-source (n_src=1) is not reordered."""
191+
grid_shape = (4, 4)
192+
mask = np.zeros(grid_shape, dtype=bool)
193+
mask[2, 3] = True
194+
p_signal = np.array([[5, 6, 7]])
195+
source = {"p_mask": mask, "p": p_signal.copy()}
196+
out = _f_to_c_source_reorder(source, grid_shape)
197+
np.testing.assert_array_equal(out["p"], p_signal)
198+
199+
def test_uniform_source_noop(self):
200+
"""Uniform source (1 row broadcast to all) is not reordered."""
201+
grid_shape = (4, 4)
202+
mask = np.zeros(grid_shape, dtype=bool)
203+
mask[0, 0] = True
204+
mask[1, 1] = True
205+
mask[2, 2] = True
206+
# 1 row, broadcast — n_rows != n_src
207+
p_signal = np.array([[1, 2, 3]])
208+
source = {"p_mask": mask, "p": p_signal.copy()}
209+
out = _f_to_c_source_reorder(source, grid_shape)
210+
np.testing.assert_array_equal(out["p"], p_signal)
211+
212+
def test_no_mask_noop(self):
213+
"""Missing mask key is silently skipped."""
214+
source = {"p": np.array([[1, 2]])}
215+
out = _f_to_c_source_reorder(source, (4, 4))
216+
np.testing.assert_array_equal(out["p"], np.array([[1, 2]]))
217+
218+
def test_scalar_mask_noop(self):
219+
"""Scalar mask (size 1) is skipped."""
220+
source = {"p_mask": np.array([True]), "p": np.array([[1, 2]])}
221+
out = _f_to_c_source_reorder(source, (4, 4))
222+
np.testing.assert_array_equal(out["p"], np.array([[1, 2]]))
223+
224+
def test_3d_grid(self):
225+
"""Works with 3D grids."""
226+
grid_shape = (2, 3, 4)
227+
mask = np.zeros(grid_shape, dtype=bool)
228+
mask[0, 0, 0] = True # F-idx 0, C-idx 0
229+
mask[1, 0, 0] = True # F-idx 1, C-idx 12
230+
mask[0, 1, 0] = True # F-idx 2, C-idx 4
231+
p_signal = np.array([[10, 11], [20, 21], [30, 31]])
232+
source = {"p_mask": mask, "p": p_signal.copy()}
233+
out = _f_to_c_source_reorder(source, grid_shape)
234+
# C-flat: (0,0,0)=0, (0,1,0)=4, (1,0,0)=12 → F-rows 0, 2, 1
235+
np.testing.assert_array_equal(out["p"][0], [10, 11])
236+
np.testing.assert_array_equal(out["p"][1], [30, 31])
237+
np.testing.assert_array_equal(out["p"][2], [20, 21])
238+
239+
144240
# ---------------------------------------------------------------------------
145241
# FutureWarning tests
146242
# ---------------------------------------------------------------------------

0 commit comments

Comments
 (0)