Clarify behaviour of overloads, and better error checking of _move_and_measure inputs
This commit is contained in:
parent
ba8a4ca744
commit
08046ff657
2 changed files with 47 additions and 8 deletions
|
|
@ -83,7 +83,7 @@ class RomDataTracker:
|
||||||
:param axis: The axis which is being measured. This must be 'x' or 'y'.
|
:param axis: The axis which is being measured. This must be 'x' or 'y'.
|
||||||
:param stage_movement: The movement to be performed in stage coordinates.
|
:param stage_movement: The movement to be performed in stage coordinates.
|
||||||
:param stage_position: The current stage position in stage coordinates.
|
:param stage_position: The current stage position in stage coordinates.
|
||||||
:returns: The predicted relative z displacement needed to stay in focus.
|
:return: The predicted relative z displacement needed to stay in focus.
|
||||||
"""
|
"""
|
||||||
# x or y positions
|
# x or y positions
|
||||||
lateral_positions = [i[axis] for i in self.stage_coords]
|
lateral_positions = [i[axis] for i in self.stage_coords]
|
||||||
|
|
@ -479,6 +479,11 @@ class RangeofMotionThing(lt.Thing):
|
||||||
autofocus is repeated.
|
autofocus is repeated.
|
||||||
:return: The calculated offset from cross correlation.
|
:return: The calculated offset from cross correlation.
|
||||||
"""
|
"""
|
||||||
|
if max_autofocus_repeats > 0 and abs_min_offset <= 0:
|
||||||
|
raise ValueError(
|
||||||
|
"abs_min_offset must be positive if max_autofocus_repeats > 0."
|
||||||
|
)
|
||||||
|
|
||||||
# Take image before move
|
# Take image before move
|
||||||
before_img = rom_deps.cam.grab_as_array()
|
before_img = rom_deps.cam.grab_as_array()
|
||||||
# Move and autofocus if required
|
# Move and autofocus if required
|
||||||
|
|
@ -533,22 +538,26 @@ class RangeofMotionThing(lt.Thing):
|
||||||
return {"x": offset[1], "y": offset[0]}
|
return {"x": offset[1], "y": offset[0]}
|
||||||
|
|
||||||
|
|
||||||
@overload
|
# The number of return arguments depends on if return_other is True or False
|
||||||
def _axis_from_movement_dict(movement: dict[str, float]) -> str: ...
|
# let MyPy know with overloads typed to Literal[False] and Literal[True].
|
||||||
|
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def _axis_from_movement_dict(
|
def _axis_from_movement_dict(
|
||||||
movement: dict[str, float], return_other: Literal[False]
|
movement: dict[str, float], return_other: Literal[False]
|
||||||
) -> str: ...
|
) -> str: ...
|
||||||
|
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def _axis_from_movement_dict(
|
def _axis_from_movement_dict(
|
||||||
movement: dict[str, float], return_other: Literal[True]
|
movement: dict[str, float], return_other: Literal[True]
|
||||||
) -> tuple[str, str]: ...
|
) -> tuple[str, str]: ...
|
||||||
|
|
||||||
|
|
||||||
|
# Overload the case where return_other is not specified, this is needed
|
||||||
|
# because MyPy doesn't see that return other's default is `False` and use
|
||||||
|
# the `Literal[False]` overload.
|
||||||
|
@overload
|
||||||
|
def _axis_from_movement_dict(movement: dict[str, float]) -> str: ...
|
||||||
|
|
||||||
|
|
||||||
|
# Finally The function.
|
||||||
def _axis_from_movement_dict(
|
def _axis_from_movement_dict(
|
||||||
movement: dict[str, float], return_other: bool = False
|
movement: dict[str, float], return_other: bool = False
|
||||||
) -> str | tuple[str, str]:
|
) -> str | tuple[str, str]:
|
||||||
|
|
@ -573,10 +582,12 @@ def _axis_from_movement_dict(
|
||||||
def _parasitic_motion_detected(
|
def _parasitic_motion_detected(
|
||||||
movement: dict[str, float], offset: dict[str, float]
|
movement: dict[str, float], offset: dict[str, float]
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""Compare a desired movement to measured offset and error if parasitic motion is too high.
|
"""Compare desired movement to measured offset, report if parasitic motion was detected.
|
||||||
|
|
||||||
:param movement: The movement dictionary in image coordinates.
|
:param movement: The movement dictionary in image coordinates.
|
||||||
:param offset: The offset calculated from correlation.
|
:param offset: The offset calculated from correlation.
|
||||||
|
:return: True if too much parasitic motion is detects. False if movement is as
|
||||||
|
expected.
|
||||||
"""
|
"""
|
||||||
movement_axis, other_axis = _axis_from_movement_dict(movement, return_other=True)
|
movement_axis, other_axis = _axis_from_movement_dict(movement, return_other=True)
|
||||||
parasitic_motion = abs(offset[other_axis])
|
parasitic_motion = abs(offset[other_axis])
|
||||||
|
|
|
||||||
|
|
@ -273,6 +273,34 @@ def test_move_and_measure_with_refocus(
|
||||||
assert offset == expected_return
|
assert offset == expected_return
|
||||||
|
|
||||||
|
|
||||||
|
def test_move_and_measure_with_bad_refocus_args(rom_thing, mocker):
|
||||||
|
"""Check error if abs_min_offset is not positive when using it to determine if to autofocus."""
|
||||||
|
offset_from_mock = mocker.patch.object(
|
||||||
|
rom_thing, "_offset_from", return_value={"x": 0, "y": 0}
|
||||||
|
)
|
||||||
|
|
||||||
|
# First check with abs_min_offset not set. The default should be zero.
|
||||||
|
with pytest.raises(ValueError, match="abs_min_offset must be positive"):
|
||||||
|
rom_thing._move_and_measure(
|
||||||
|
movement={"x": 10, "y": 0},
|
||||||
|
rom_deps=mock_rom_deps,
|
||||||
|
perform_autofocus=False,
|
||||||
|
max_autofocus_repeats=3,
|
||||||
|
)
|
||||||
|
# Then check with abs_min_offset negative, this might happen if the the expected
|
||||||
|
# move calculation is not made absolute.
|
||||||
|
with pytest.raises(ValueError, match="abs_min_offset must be positive"):
|
||||||
|
rom_thing._move_and_measure(
|
||||||
|
movement={"x": 10, "y": 0},
|
||||||
|
rom_deps=mock_rom_deps,
|
||||||
|
perform_autofocus=False,
|
||||||
|
max_autofocus_repeats=3,
|
||||||
|
abs_min_offset=-123.456,
|
||||||
|
)
|
||||||
|
# Should have never measured and offset. Just error straight away.
|
||||||
|
assert offset_from_mock.call_count == 0
|
||||||
|
|
||||||
|
|
||||||
def test_move_back_until_motion_detected(rom_thing, mock_rom_deps, mocker):
|
def test_move_back_until_motion_detected(rom_thing, mock_rom_deps, mocker):
|
||||||
"""Check that _move_back_until_motion_detected is making increasing negative moves.
|
"""Check that _move_back_until_motion_detected is making increasing negative moves.
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue