From 3ef4b99e3a4477e9c63a19ef2ff38cbe109b7295 Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Fri, 30 Aug 2024 05:15:42 +0200 Subject: [PATCH] Add tests for native engine --- .github/workflows/build.yml | 20 +++++++- src/python/pffdtd/analysis/room_modes.py | 37 +++++++++----- src/python/test/test_sim3d.py | 62 ++++++++++++++++++------ 3 files changed, 92 insertions(+), 27 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1ab4683..22510d8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,6 +29,7 @@ jobs: cmake_prefix_path: "/opt/intel/oneapi/tbb/latest" cmake_flags: "" cxx_flags: "-march=x86-64-v2" + python_version: "3.12" - name: macOS-X64 os: macos-13 @@ -36,6 +37,7 @@ jobs: cmake_prefix_path: "" cmake_flags: '-D OpenMP_ROOT=`brew list libomp | grep libomp.a | sed -E "s/\/lib\/.*//"`' cxx_flags: "-march=x86-64-v2" + python_version: "3.12" - name: macOS-ARM64 os: macos-14 @@ -43,6 +45,7 @@ jobs: cmake_prefix_path: "" cmake_flags: '-D OpenMP_ROOT=`brew list libomp | grep libomp.a | sed -E "s/\/lib\/.*//"`' cxx_flags: "" + python_version: "3.12" # - name: Windows # os: windows-latest @@ -56,6 +59,10 @@ jobs: with: lfs: true + - uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python_version }} + - name: Install dependencies (Linux) if: runner.os == 'Linux' run: | @@ -105,5 +112,14 @@ jobs: - name: CMake build run: cmake --build build - # - name: CTest - # run: ctest --test-dir build -C Release --output-on-failure -j 1 + - name: Build and install (Python) + run: pip3 install --verbose .[test] + + - name: Test (Python) + run: pytest --cov=pffdtd --cov-branch + + - name: Upload coverage report + uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.CODECOV_TOKEN }} + fail_ci_if_error: true diff --git a/src/python/pffdtd/analysis/room_modes.py b/src/python/pffdtd/analysis/room_modes.py index 29ee912..d19d548 100644 --- a/src/python/pffdtd/analysis/room_modes.py +++ b/src/python/pffdtd/analysis/room_modes.py @@ -92,17 +92,7 @@ def frequency_spacing_index(modes): return psi / (num-1) -@click.command(name="room-modes", help="Plot room modes.") -@click.argument('filename', nargs=-1, type=click.Path(exists=True)) -@click.option('--data_dir', type=click.Path(exists=True)) -@click.option('--fmin', default=1.0, type=float) -@click.option('--fmax', default=200.0, type=float) -@click.option('--width', default=2.0, type=float) -@click.option('--length', default=3.0, type=float) -@click.option('--height', default=4.0, type=float) -@click.option('--num_modes', default=10, type=int) -@click.option('--plot/--no-plot', default=True) -def main( +def detect_room_modes( filename, data_dir, fmin, @@ -195,3 +185,28 @@ def main( plt.show() return calculated_mode_freqs, measured_mode_freqs + + +@click.command(name="room-modes", help="Plot room modes.") +@click.argument('filename', nargs=-1, type=click.Path(exists=True)) +@click.option('--data_dir', type=click.Path(exists=True)) +@click.option('--fmin', default=1.0, type=float) +@click.option('--fmax', default=200.0, type=float) +@click.option('--width', default=2.0, type=float) +@click.option('--length', default=3.0, type=float) +@click.option('--height', default=4.0, type=float) +@click.option('--num_modes', default=10, type=int) +@click.option('--plot/--no-plot', default=True) +def main( + filename, + data_dir, + fmin, + fmax, + width, + length, + height, + num_modes, + plot, +): + detect_room_modes(filename, data_dir, fmin, fmax, width, + length, height, num_modes, plot) diff --git a/src/python/test/test_sim3d.py b/src/python/test/test_sim3d.py index a9889eb..dcb1b89 100644 --- a/src/python/test/test_sim3d.py +++ b/src/python/test/test_sim3d.py @@ -1,11 +1,14 @@ +from contextlib import chdir import json +import pathlib +import subprocess import pytest import numpy as np import scipy.io.wavfile as wavfile from pffdtd.analysis.room_modes import find_nearest -from pffdtd.analysis.room_modes import main as room_modes +from pffdtd.analysis.room_modes import detect_room_modes from pffdtd.materials.adm_funcs import write_freq_ind_mat_from_Yn, convert_Sabs_to_Yn from pffdtd.sim2d.fdtd import point_on_circle from pffdtd.sim3d.room_builder import RoomBuilder @@ -15,7 +18,37 @@ from pffdtd.localization.tdoa import locate_sound_source -def test_sim3d_locate_sound_source(tmp_path): +ENGINE_EXE = pathlib.Path("./build/src/cpp/main_3d/pffdtd_3d").absolute() + + +def _run_engine(sim_dir, engine): + if engine == "python": + eng = EnginePython3D(sim_dir) + eng.run_all(1) + eng.save_outputs() + else: + assert engine == "native" + assert ENGINE_EXE.exists() + + with chdir(sim_dir): + result = subprocess.run( + args=[str(ENGINE_EXE)], + capture_output=True, + text=True, + check=True, + ) + assert result.returncode == 0 + + +def _skip_if_native_engine_unavailable(engine): + if engine == "native" and not ENGINE_EXE.exists(): + pytest.skip("Native engine not available") + + +@pytest.mark.parametrize("engine", ["python", "native"]) +def test_sim3d_locate_sound_source(tmp_path, engine): + _skip_if_native_engine_unavailable(engine) + fmin = 20 fmax = 1000 ppw = 10.5 @@ -69,9 +102,7 @@ def test_sim3d_locate_sound_source(tmp_path): save_folder=sim_dir, ) - eng = EnginePython3D(sim_dir) - eng.run_all(1) - eng.save_outputs() + _run_engine(sim_dir=sim_dir, engine=engine) process_outputs( data_dir=sim_dir, @@ -112,7 +143,10 @@ def test_sim3d_locate_sound_source(tmp_path): assert np.linalg.norm(actual-estimated) <= 0.1 -def test_sim3d_infinite_baffle(tmp_path): +@pytest.mark.parametrize("engine", ["python", "native"]) +def test_sim3d_infinite_baffle(tmp_path, engine): + _skip_if_native_engine_unavailable(engine) + fmin = 20 fmax = 1000 ppw = 10.5 @@ -184,9 +218,7 @@ def test_sim3d_infinite_baffle(tmp_path): bmin=[0, 0, 0], ) - eng = EnginePython3D(sim_dir) - eng.run_all(1) - eng.save_outputs() + _run_engine(sim_dir=sim_dir, engine=engine) process_outputs( data_dir=sim_dir, @@ -214,6 +246,7 @@ def test_sim3d_infinite_baffle(tmp_path): assert error_3 < -12.0 +@pytest.mark.parametrize("engine", ["python", "native"]) @pytest.mark.parametrize( "size,fmax,ppw,fcc,dx_scale,tolerance", [ @@ -221,7 +254,9 @@ def test_sim3d_infinite_baffle(tmp_path): ((3.0, 1.0, 2.0), 800, 7.7, True, 3, 6), ] ) -def test_sim3d_detect_room_modes(tmp_path, size, fmax, ppw, fcc, dx_scale, tolerance): +def test_sim3d_detect_room_modes(tmp_path, engine, size, fmax, ppw, fcc, dx_scale, tolerance): + _skip_if_native_engine_unavailable(engine) + L = size[0] W = size[1] H = size[2] @@ -258,9 +293,7 @@ def test_sim3d_detect_room_modes(tmp_path, size, fmax, ppw, fcc, dx_scale, toler save_folder=sim_dir, ) - eng = EnginePython3D(sim_dir) - eng.run_all(1) - eng.save_outputs() + _run_engine(sim_dir=sim_dir, engine=engine) process_outputs( data_dir=sim_dir, @@ -276,7 +309,8 @@ def test_sim3d_detect_room_modes(tmp_path, size, fmax, ppw, fcc, dx_scale, toler plot=False, ) - actual, measured = room_modes( + actual, measured = detect_room_modes( + filename=None, data_dir=sim_dir, fmin=fmin, fmax=fmax,