diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e283337a..a76fd9e7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,3 +21,7 @@ jobs: - name: Run tests run: | make coverage + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v4.0.1 + with: + token: ${{ secrets.CODECOV_TOKEN }} diff --git a/peakipy/cli/main.py b/peakipy/cli/main.py index 46186429..3a636632 100644 --- a/peakipy/cli/main.py +++ b/peakipy/cli/main.py @@ -441,28 +441,6 @@ def select_specified_planes(plane, peakipy_data): return plane_numbers, peakipy_data -def select_specified_planes(plane, peakipy_data): - plane_numbers = np.arange(peakipy_data.data.shape[peakipy_data.dims[0]]) - # only fit specified planes - if plane: - inds = [i for i in plane] - data_inds = [ - (i in inds) for i in range(peakipy_data.data.shape[peakipy_data.dims[0]]) - ] - plane_numbers = np.arange(peakipy_data.data.shape[peakipy_data.dims[0]])[ - data_inds - ] - peakipy_data.data = peakipy_data.data[data_inds] - print( - "[yellow]Using only planes {plane} data now has the following shape[/yellow]", - peakipy_data.data.shape, - ) - if peakipy_data.data.shape[peakipy_data.dims[0]] == 0: - print("[red]You have excluded all the data![/red]", peakipy_data.data.shape) - exit() - return plane_numbers, peakipy_data - - def exclude_specified_planes(exclude_plane, peakipy_data): plane_numbers = np.arange(peakipy_data.data.shape[peakipy_data.dims[0]]) # do not fit these planes @@ -566,6 +544,10 @@ def unpack_xy_bounds(xy_bounds, peakipy_data): xy_bounds = list(xy_bounds) xy_bounds[0] = xy_bounds[0] * peakipy_data.pt_per_ppm_f2 xy_bounds[1] = xy_bounds[1] * peakipy_data.pt_per_ppm_f1 + case _: + raise TypeError( + "xy_bounds should be a tuple (, )" + ) return xy_bounds diff --git a/test/test_main.py b/test/test_main.py index 6e3bb4ce..cf0f144e 100644 --- a/test/test_main.py +++ b/test/test_main.py @@ -9,8 +9,12 @@ from peakipy.cli.main import ( get_vclist, check_for_include_column_and_add_if_missing, + check_data_shape_is_consistent_with_dims, select_specified_planes, exclude_specified_planes, + remove_excluded_peaks, + warn_if_trying_to_fit_large_clusters, + unpack_xy_bounds, validate_plane_selection, validate_sample_count, unpack_plotting_colors, @@ -32,6 +36,8 @@ class PeakipyData: df: pd.DataFrame = field(default_factory=lambda: pd.DataFrame()) data: np.array = field(default_factory=lambda: np.zeros((4, 10, 20))) dims: list = field(default_factory=lambda: [0, 1, 2]) + pt_per_ppm_f2 = 10 + pt_per_ppm_f1 = 20 def test_get_vclist(actual_vclist): @@ -47,6 +53,13 @@ def test_get_vclist_none(): assert args == expected_args +def test_get_vclist_error(): + vclist = "vclist" + args = {} + with pytest.raises(Exception): + get_vclist(vclist, args) + + def test_check_for_include_column(): peakipy_data = PeakipyData(pd.DataFrame()) peakipy_data = check_for_include_column_and_add_if_missing(peakipy_data) @@ -68,6 +81,14 @@ def test_select_specified_planes_2(): assert peakipy_data.data.shape == (2, 10, 20) +def test_select_specified_planes_all_planes_excluded(capsys): + plane = [10] + with pytest.raises(SystemExit): + select_specified_planes(plane, PeakipyData()) + captured = capsys.readouterr() + assert "" in captured.err + + def test_exclude_specified_planes(): plane = None expected_plane_numbers = np.arange(4) @@ -83,6 +104,66 @@ def test_exclude_specified_planes_2(): assert peakipy_data.data.shape == (2, 10, 20) +def test_exclude_specified_planes_all_planes_excluded(capsys): + plane = [0, 1, 2, 3] + with pytest.raises(SystemExit): + exclude_specified_planes(plane, PeakipyData()) + captured = capsys.readouterr() + assert "" in captured.err + + +def test_remove_excluded_peaks(): + actual_dict = dict( + include=["yes", "yes", "no"], + peak=[1, 2, 3], + INDEX=[0, 1, 2], + ASS=["one", "two", "three"], + X_PPM=[1, 2, 3], + Y_PPM=[1, 2, 3], + CLUSTID=[1, 2, 3], + MEMCNT=[1, 1, 1], + ) + expected_dict = {k: v[:-1] for k, v in actual_dict.items()} + actual_df = pd.DataFrame(actual_dict) + expected_df = pd.DataFrame(expected_dict) + peakipy_data = PeakipyData(df=actual_df) + pd.testing.assert_frame_equal(remove_excluded_peaks(peakipy_data).df, expected_df) + + +def test_warn_if_trying_to_fit_large_clusters(): + max_cluster_size = 7 + df = pd.DataFrame(dict(MEMCNT=[1, 6], CLUSTID=[0, 1])) + peakipy_data = PeakipyData(df=df) + assert ( + warn_if_trying_to_fit_large_clusters(max_cluster_size, peakipy_data) + == max_cluster_size + ) + + +def test_warn_if_trying_to_fit_large_clusters_none(): + max_cluster_size = None + df = pd.DataFrame(dict(MEMCNT=[1, 12], CLUSTID=[0, 1])) + peakipy_data = PeakipyData(df=df) + assert warn_if_trying_to_fit_large_clusters(max_cluster_size, peakipy_data) == 12 + + +def test_unpack_xy_bounds_case_00(): + xy_bounds = (0, 0) + result = unpack_xy_bounds(xy_bounds, PeakipyData()) + assert result == None + + +def test_unpack_xy_bounds_case_xy(): + xy_bounds = (1, 2) + result = unpack_xy_bounds(xy_bounds, PeakipyData()) + assert result == [10, 40] + + +def test_unpack_xy_bounds_invalid_input(): + with pytest.raises(TypeError): + unpack_xy_bounds(None, PeakipyData()) + + class MockPseudo3D: def __init__(self, n_planes): self.n_planes = n_planes @@ -195,3 +276,9 @@ def test_invalid_clusters(): fits = pd.DataFrame({"clustid": [1, 2, 3]}) with pytest.raises(SystemExit): get_fit_data_for_selected_peak_clusters(fits, [4, 5, 6]) + + +def test_check_data_shape_is_consistent_with_dims(): + peakipy_data = PeakipyData(data=np.zeros((4, 10))) + with pytest.raises(SystemExit): + check_data_shape_is_consistent_with_dims(peakipy_data)