Skip to content

Commit

Permalink
kymotracker: enforce keyword arguments for tracking algorithms
Browse files Browse the repository at this point in the history
  • Loading branch information
rpauszek committed Mar 9, 2023
1 parent 5674bcb commit 46db289
Show file tree
Hide file tree
Showing 6 changed files with 22 additions and 18 deletions.
2 changes: 2 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

#### Breaking changes

* Optional arguments for [`lk.track_greedy()`](https://lumicks-pylake.readthedocs.io/en/latest/_api/lumicks.pylake.track_greedy.html#) and [`lk.track_lines()`](https://lumicks-pylake.readthedocs.io/en/latest/_api/lumicks.pylake.track_lines.html#) are now enforced as keyword only.
* The `vel` argument has been renamed to `velocity` for [`lk.track_greedy()`](https://lumicks-pylake.readthedocs.io/en/latest/_api/lumicks.pylake.track_greedy.html#).
* When performing particle tracking on kymographs, bias correction is now enabled by default; without this correction, kymographs with high background signal will suffer from biased localization estimates. To disable bias correction, specify `bias_correction=False` to [`lk.track_greedy()`](https://lumicks-pylake.readthedocs.io/en/latest/_api/lumicks.pylake.track_greedy.html#) and [`lk.refine_tracks_centroid()`](https://lumicks-pylake.readthedocs.io/en/latest/_api/lumicks.pylake.refine_tracks_centroid.html).
* `lk.track_lines()` now performs bias-corrected centroid refinement after tracking to improve localization accuracy. Note that the old behaviour can be recovered by passing `refine=False`.
* Changed several `asserts` to `Exceptions`.
Expand Down
8 changes: 5 additions & 3 deletions lumicks/pylake/kymotracker/kymotracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,12 @@ def _validate_track_width(track_width, bound, unit):
def track_greedy(
kymograph,
channel,
*,
track_width=None,
pixel_threshold=None,
window=8,
sigma=None,
vel=0.0,
velocity=0.0,
diffusion=0.0,
sigma_cutoff=2.0,
rect=None,
Expand Down Expand Up @@ -119,7 +120,7 @@ def track_greedy(
next frame will be linked to this one. Increasing this value will make the algorithm tend
to allow more positional variation in the tracks. If none, the algorithm will use half the
track width.
vel : float
velocity : float
Expected velocity of the traces in the image in physical units. This can be used for
non-static particles that are expected to move at a constant rate (default: 0.0).
diffusion : float
Expand Down Expand Up @@ -202,7 +203,7 @@ def track_greedy(
peaks = merge_close_peaks(peaks, half_width_pixels)

# Convert algorithm parameters to pixel units
velocity_pixels = vel * kymograph.line_time_seconds / position_scale
velocity_pixels = velocity * kymograph.line_time_seconds / position_scale
diffusion_pixels = diffusion / (position_scale**2 / kymograph.line_time_seconds)
sigma_pixels = sigma / position_scale if sigma else half_width_pixels

Expand Down Expand Up @@ -257,6 +258,7 @@ def track_lines(
channel,
line_width,
max_lines,
*,
start_threshold=0.005,
continuation_threshold=0.005,
angle_weight=10.0,
Expand Down
6 changes: 3 additions & 3 deletions lumicks/pylake/kymotracker/tests/test_algorithm_scaling.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,18 @@ def generate_gaussian_line(vel, dt, dx, sigma=0.3, area=10, samples_per_pixel=10
def test_kymotracker_positional_scaling(vel, dt, dx):
"""Integration test to make sure position and velocity parameters are correctly scaled"""
kymo = generate_gaussian_line(vel=vel, dt=dt, dx=dx)
traces = track_greedy(kymo, "red", pixel_threshold=3, track_width=1, sigma=0.01, vel=vel)
traces = track_greedy(kymo, "red", pixel_threshold=3, track_width=1, sigma=0.01, velocity=vel)
ref_seconds = np.arange(0.0, 2.0, dt)
ref_positions = 1 + vel * ref_seconds
np.testing.assert_allclose(traces[0].seconds, ref_seconds)
np.testing.assert_allclose(traces[0].position, ref_positions, rtol=1e-2)

# Check whether a wrong velocity also fails to track the line
traces = track_greedy(kymo, "red", pixel_threshold=3, track_width=1, sigma=0.01, vel=2 * vel)
traces = track_greedy(kymo, "red", pixel_threshold=3, track_width=1, sigma=0.01, velocity=2 * vel)
np.testing.assert_equal(len(traces[0].seconds), 1)
np.testing.assert_equal(len(traces[0].position), 1)

# When sigma is large, we expect the line to be strung together despite the velocity being zero
traces = track_greedy(kymo, "red", pixel_threshold=3, track_width=1, sigma=0.5 * vel * dx, vel=0)
traces = track_greedy(kymo, "red", pixel_threshold=3, track_width=1, sigma=0.5 * vel * dx, velocity=0)
np.testing.assert_allclose(traces[0].seconds, ref_seconds)
np.testing.assert_allclose(traces[0].position, ref_positions, rtol=1e-2)
10 changes: 5 additions & 5 deletions lumicks/pylake/kymotracker/tests/test_greedy_algorithm.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def test_kymotracker_subset_test_greedy(kymo_integration_test_data):
pixel_size = kymo_integration_test_data.pixelsize_um[0]
rect = [[0.0 * line_time, 15.0 * pixel_size], [30 * line_time, 30.0 * pixel_size]]

tracks = track_greedy(kymo_integration_test_data, "red", 3 * pixel_size, 4, rect=rect)
tracks = track_greedy(kymo_integration_test_data, "red", track_width=3 * pixel_size, pixel_threshold=4, rect=rect)
np.testing.assert_allclose(tracks[0].sample_from_image(1), [40] * np.ones(10))


Expand All @@ -57,7 +57,7 @@ def test_kymotracker_greedy_algorithm_integration_tests(kymo_integration_test_da
line_time = test_data.line_time_seconds
pixel_size = test_data.pixelsize_um[0]

tracks = track_greedy(test_data, "red", 3 * pixel_size, 4)
tracks = track_greedy(test_data, "red", track_width=3 * pixel_size, pixel_threshold=4)
np.testing.assert_allclose(tracks[0].coordinate_idx, [11] * np.ones(10))
np.testing.assert_allclose(tracks[1].coordinate_idx, [21] * np.ones(10))
np.testing.assert_allclose(tracks[0].position, [11 * pixel_size] * np.ones(10))
Expand All @@ -70,7 +70,7 @@ def test_kymotracker_greedy_algorithm_integration_tests(kymo_integration_test_da
np.testing.assert_allclose(tracks[1].sample_from_image(1), [40] * np.ones(10))

rect = [[0.0 * line_time, 15.0 * pixel_size], [30 * line_time, 30.0 * pixel_size]]
tracks = track_greedy(test_data, "red", 3 * pixel_size, 4, rect=rect)
tracks = track_greedy(test_data, "red", track_width=3 * pixel_size, pixel_threshold=4, rect=rect)
np.testing.assert_allclose(tracks[0].coordinate_idx, [21] * np.ones(10))
np.testing.assert_allclose(tracks[0].time_idx, np.arange(15, 25))

Expand Down Expand Up @@ -109,7 +109,7 @@ def test_default_parameters(kymo_pixel_calibrations):

# test that default values are used when `None` is supplied
default_threshold = np.percentile(kymo.get_image("red"), 98)
ref_tracks = track_greedy(kymo, "red", default_width, default_threshold)
ref_tracks = track_greedy(kymo, "red", track_width=default_width, pixel_threshold=default_threshold)

tracks = track_greedy(kymo, "red", track_width=None, pixel_threshold=default_threshold)
for ref, track in zip(ref_tracks, tracks):
Expand All @@ -125,7 +125,7 @@ def test_default_parameters(kymo_pixel_calibrations):

# We want to see that when setting the tracking parameter to something other than the
# defaults actually has an effect
ref_tracks = track_greedy(kymo, "red", None, None)
ref_tracks = track_greedy(kymo, "red", track_width=None, pixel_threshold=None)
tracks = track_greedy(
kymo, "red", track_width=None, pixel_threshold=default_threshold * 0.7
)
Expand Down
8 changes: 4 additions & 4 deletions lumicks/pylake/nb_widgets/kymotracker_widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,7 @@ def __init__(
pixel_threshold=None,
window=None,
sigma=None,
vel=None,
velocity=None,
diffusion=None,
sigma_cutoff=None,
min_length=None,
Expand Down Expand Up @@ -577,7 +577,7 @@ def __init__(
Uncertainty in the particle position. This parameter will determine whether a peak in the next frame will be
linked to this one. Increasing this value will make the algorithm tend to allow more positional variation in
the tracks. If none, the algorithm will use half the track width.
vel : float, optional
velocity : float, optional
Expected velocity of the traces in the image. This can be used for non-static particles that are expected to
move at an expected rate (default: 0.0).
diffusion : float, optional
Expand All @@ -599,7 +599,7 @@ def __init__(
Dictionary with custom ranges for selected parameter sliders. Ranges should be in the
following format: (lower bound, upper bound).
Valid options are: "window", "pixel_threshold", "track_width", "sigma", "min_length" and
"vel".
"velocity".
"""

def wrapped_track_greedy(kymo, channel, min_length, **kwargs):
Expand Down Expand Up @@ -792,7 +792,7 @@ def _get_default_parameters(kymo, channel):
r"noise, but at the cost of potentially merging tracks that are close together.",
abridged_name="Spot size",
),
"vel": KymotrackerParameter(
"velocity": KymotrackerParameter(
"Expected velocity",
"How fast does the particle move?",
"float",
Expand Down
6 changes: 3 additions & 3 deletions lumicks/pylake/nb_widgets/tests/test_kymotracker_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -363,9 +363,9 @@ def test_keyword_args(kymograph):
"gain,line_time,pixel_size,ref_values",
(
# fmt:off
(1, 2.0, 5.0, {"pixel_threshold": (97, 1, 99), "track_width": (4 * 5, 3 * 5, 15 * 5), "sigma": (2 * 5, 1 * 5, 5 * 5), "vel": (0, -5 * 5/2, 5 * 5/2)}),
(0, 2.0, 5.0, {"pixel_threshold": (1, 1, 2), "track_width": (4 * 5, 3 * 5, 15 * 5), "sigma": (2 * 5, 1 * 5, 5 * 5), "vel": (0, -5 * 5/2, 5 * 5/2)}),
(1, 4.0, 4.0, {"pixel_threshold": (97, 1, 99), "track_width": (4 * 4, 3 * 4, 15 * 4), "sigma": (2 * 4, 1 * 4, 5 * 4), "vel": (0, -5 * 4/4, 5 * 4/4)}),
(1, 2.0, 5.0, {"pixel_threshold": (97, 1, 99), "track_width": (4 * 5, 3 * 5, 15 * 5), "sigma": (2 * 5, 1 * 5, 5 * 5), "velocity": (0, -5 * 5/2, 5 * 5/2)}),
(0, 2.0, 5.0, {"pixel_threshold": (1, 1, 2), "track_width": (4 * 5, 3 * 5, 15 * 5), "sigma": (2 * 5, 1 * 5, 5 * 5), "velocity": (0, -5 * 5/2, 5 * 5/2)}),
(1, 4.0, 4.0, {"pixel_threshold": (97, 1, 99), "track_width": (4 * 4, 3 * 4, 15 * 4), "sigma": (2 * 4, 1 * 4, 5 * 4), "velocity": (0, -5 * 4/4, 5 * 4/4)}),
# fmt:on
),
)
Expand Down

0 comments on commit 46db289

Please sign in to comment.