Skip to content

Commit

Permalink
improve basic_interpolated_peak_picker.py testing
Browse files Browse the repository at this point in the history
  • Loading branch information
leoschwarz committed May 30, 2024
1 parent aad8f49 commit ca511a6
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 5 deletions.
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ testing = [
"coverage>=7.4.3",
"hypothesis>=6.99.11",
"mypy>=1.9.0",
"pytype>=2023.12.18"
"pytype>=2023.12.18",
"logot"
]
dev = [
"bokeh>=3.3.2",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def _interpolate_max_mz_and_intensity(
# Fit a cubic spline
spline = scipy.interpolate.CubicSpline(interp_mz, interp_int)
roots = spline.derivative().roots()
if len(roots) == 0:
if np.isnan(roots).any():
loguru.logger.warning(
f"Error: {len(roots)} roots found for local maximum at index {local_max_index}; "
f"{interp_mz=}, {interp_int=}, {roots=}"
Expand All @@ -89,3 +89,7 @@ def _find_local_maxima_indices(self, mz_arr: NDArray[float], int_arr: NDArray[fl
),
)
return local_maxima_indices


# TODO the interpolation could be much faster, if it were implemented in numba for our specific case of 3 points,
# since in general the scipy library will do everything much moe general than is actually required.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
from unittest.mock import patch, MagicMock

import numpy as np
from logot import Logot, logged
from logot.loguru import LoguruCapturer

from depiction.spectrum.peak_picking import BasicPeakPicker, BasicInterpolatedPeakPicker

Expand All @@ -23,11 +25,46 @@ def basic_interpolated_peak_picker(self) -> BasicInterpolatedPeakPicker:
peak_filtering=self.mock_peak_filtering,
)

def test_interpolate_max_mz_and_intensity_when_success(self) -> None:
pass
def test_interpolate_max_mz_and_intensity_when_success_and_exact(self) -> None:
"""In this very simple case, interpolation should return the same value as the intensity on both sides is
symmetric."""
local_max_index = 2
mz_arr = np.array([1., 2, 3, 4, 5])
int_arr = np.array([0., 0, 10, 0, 0])

interpolated_mz, interpolated_int = self.basic_interpolated_peak_picker._interpolate_max_mz_and_intensity(
local_max_index, mz_arr, int_arr
)

self.assertAlmostEqual(3, interpolated_mz)
self.assertAlmostEqual(10, interpolated_int)

def test_interpolate_max_mz_and_intensity_when_success_and_not_exact(self) -> None:
local_max_index = 2
mz_arr = np.array([1., 2, 3, 4, 5])
int_arr = np.array([0., 0, 10, 5, 0])

interpolated_mz, interpolated_int = self.basic_interpolated_peak_picker._interpolate_max_mz_and_intensity(
local_max_index, mz_arr, int_arr
)

self.assertAlmostEqual(3.16667, interpolated_mz, places=5)
self.assertAlmostEqual(10.20833, interpolated_int, places=5)

def test_interpolate_max_mz_and_intensity_when_failure(self) -> None:
pass
local_max_index = 2
mz_arr = np.array([1., 2, 3, 4, 5])
int_arr = np.array([0., 10, 10, 10, 0])

with Logot().capturing(capturer=LoguruCapturer) as logot:
interpolated_mz, interpolated_int = self.basic_interpolated_peak_picker._interpolate_max_mz_and_intensity(
local_max_index, mz_arr, int_arr
)
self.assertIsNone(interpolated_mz)
self.assertIsNone(interpolated_int)
logot.assert_logged(logged.warning("Error: %d roots found for local maximum at index 2; %s"))

# TODO test interpolate when there are 2 roots because of numerical issues, 3 is apparently also possible

@patch.object(BasicPeakPicker, "get_min_distance_indices")
def test_find_local_maxima_indices(self, mock_get_min_distance_indices) -> None:
Expand Down

0 comments on commit ca511a6

Please sign in to comment.