Skip to content

Commit

Permalink
kymo: add landmarks argument to calibrate_to_kbp
Browse files Browse the repository at this point in the history
  • Loading branch information
rpauszek committed Feb 13, 2025
1 parent 0b7280d commit 641432b
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 6 deletions.
15 changes: 13 additions & 2 deletions lumicks/pylake/kymo.py
Original file line number Diff line number Diff line change
Expand Up @@ -998,7 +998,7 @@ def image_factory(_, channel):

return result

def calibrate_to_kbp(self, length_kbp, *, start=None, end=None, length_um=None):
def calibrate_to_kbp(self, length_kbp, *, start=None, end=None, length_um=None, landmarks=None):
"""Calibrate from microns to other units.
Parameters
Expand All @@ -1011,17 +1011,28 @@ def calibrate_to_kbp(self, length_kbp, *, start=None, end=None, length_um=None):
End point of the tether in microns. Must also supply `start`.
length_um: float | None
Length of the tether in microns. Must also supply `start`.
landmarks: list | None
List of (micron, kbp) pairs of known positions. `start` must be `None`.
"""
if self._calibration.unit == PositionUnit.kbp:
raise RuntimeError("kymo is already calibrated in base pairs.")

if start is None:
if end is not None or length_um is not None:
raise ValueError("start must be supplied")
raise ValueError("Start must be supplied with end or length_um.")
elif landmarks is not None:
if len(landmarks) < 2:
raise ValueError("At least 2 landmarks must be supplied.")
pixels = [self._calibration.to_pixels(landmark[0]) for landmark in landmarks]
kbp = [landmark[1] for landmark in landmarks]
kbp_per_pixel, intercept = np.polyfit(pixels, kbp, deg=1)
pixel_origin = -intercept / kbp_per_pixel
else:
kbp_per_pixel = length_kbp / self._num_pixels[0]
pixel_origin = 0.0
else:
if landmarks is not None:
raise ValueError("Cannot use landmarks with start.")
if (end is None) and (length_um is None):
raise ValueError("Either end or length_um must be supplied with start.")
if (end is not None) and (length_um is not None):
Expand Down
27 changes: 23 additions & 4 deletions lumicks/pylake/tests/test_imaging_confocal/test_kymo_transforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,31 @@ def test_calibrate_to_kbp(test_kymo):
kymo_bp.calibrate_to_kbp(10)


@pytest.mark.parametrize("start, end", [(None, 0.33), (0.12, None)])
def test_calibrate_to_kbp_invalid_range(test_kymo, start, end):
def test_calibrate_to_kbp_invalid(test_kymo):
with pytest.raises(
ValueError, match="Both start and end points of the tether must be supplied."
ValueError, match="Start must be supplied with end or length_um."
):
test_kymo[0].calibrate_to_kbp(1, start=start, end=end)
test_kymo[0].calibrate_to_kbp(1, start=None, end=0.33)
with pytest.raises(
ValueError, match="Start must be supplied with end or length_um."
):
test_kymo[0].calibrate_to_kbp(1, start=None, length_um=10.0)
with pytest.raises(
ValueError, match="Either end or length_um must be supplied with start."
):
test_kymo[0].calibrate_to_kbp(1, start=0.33, end=None)
with pytest.raises(
ValueError, match="Either end or length_um must be supplied with start."
):
test_kymo[0].calibrate_to_kbp(1, start=0.33, length_um=None)
with pytest.raises(
ValueError, match="Cannot use landmarks with start."
):
test_kymo[0].calibrate_to_kbp(1, start=0.33, landmarks=([1, 2], [3, 4]))
with pytest.raises(
ValueError, match="At least 2 landmarks must be supplied."
):
test_kymo[0].calibrate_to_kbp(1, landmarks=([1, 2], ))


def check_factory_forwarding(kymo1, kymo2, check_timestamps):
Expand Down

0 comments on commit 641432b

Please sign in to comment.