Use backlash compensation in smart scan and autofocus
This commit is contained in:
parent
c12814f0eb
commit
0527990282
4 changed files with 21 additions and 13 deletions
|
|
@ -22,7 +22,7 @@ import labthings_fastapi as lt
|
||||||
from labthings_fastapi.types.numpy import NDArray
|
from labthings_fastapi.types.numpy import NDArray
|
||||||
|
|
||||||
from .camera import BaseCamera, CaptureParams
|
from .camera import BaseCamera, CaptureParams
|
||||||
from .stage import BaseStage
|
from .stage import BacklashCompensation, BaseStage
|
||||||
|
|
||||||
LOGGER = logging.getLogger(__name__)
|
LOGGER = logging.getLogger(__name__)
|
||||||
MIN_TEST_IMAGE_COUNT = 3
|
MIN_TEST_IMAGE_COUNT = 3
|
||||||
|
|
@ -458,14 +458,17 @@ class AutofocusThing(lt.Thing):
|
||||||
up to 10 times.
|
up to 10 times.
|
||||||
"""
|
"""
|
||||||
attempt = 0
|
attempt = 0
|
||||||
backlash = 200
|
|
||||||
|
|
||||||
with JPEGSharpnessMonitor(self._stage, self._cam) as sharpness_monitor:
|
with JPEGSharpnessMonitor(self._stage, self._cam) as sharpness_monitor:
|
||||||
while attempt < 10:
|
while attempt < 10:
|
||||||
attempt += 1
|
attempt += 1
|
||||||
if start == "centre":
|
if start == "centre":
|
||||||
self._stage.move_relative(x=0, y=0, z=-int(backlash + dz / 2))
|
self._stage.move_relative(
|
||||||
self._stage.move_relative(x=0, y=0, z=backlash)
|
x=0,
|
||||||
|
y=0,
|
||||||
|
z=-int(dz / 2),
|
||||||
|
backlash_compensation=BacklashCompensation.Z_ONLY,
|
||||||
|
)
|
||||||
|
|
||||||
# Always start centrally for future runs
|
# Always start centrally for future runs
|
||||||
start = "centre"
|
start = "centre"
|
||||||
|
|
@ -480,8 +483,10 @@ class AutofocusThing(lt.Thing):
|
||||||
target_max = np.max(heights) - dz / 5
|
target_max = np.max(heights) - dz / 5
|
||||||
|
|
||||||
# move to the peak
|
# move to the peak
|
||||||
self._stage.move_absolute(z=peak_height - backlash)
|
self._stage.move_absolute(
|
||||||
self._stage.move_absolute(z=peak_height)
|
z=peak_height,
|
||||||
|
backlash_compensation=BacklashCompensation.Z_ONLY,
|
||||||
|
)
|
||||||
|
|
||||||
if target_min < peak_height < target_max:
|
if target_min < peak_height < target_max:
|
||||||
# If it is within the target range then return
|
# If it is within the target range then return
|
||||||
|
|
@ -622,12 +627,10 @@ class AutofocusThing(lt.Thing):
|
||||||
# Better to start too low and take too many images than too high and need to refocus
|
# Better to start too low and take too many images than too high and need to refocus
|
||||||
self._stage.move_relative(
|
self._stage.move_relative(
|
||||||
z=-int(
|
z=-int(
|
||||||
stack_parameters.steps_undershoot
|
stack_parameters.steps_undershoot + stack_parameters.stack_z_range / 2
|
||||||
+ stack_parameters.backlash_correction
|
),
|
||||||
+ stack_parameters.stack_z_range / 2
|
backlash_compensation=BacklashCompensation.Z_ONLY,
|
||||||
)
|
|
||||||
)
|
)
|
||||||
self._stage.move_relative(z=stack_parameters.backlash_correction)
|
|
||||||
|
|
||||||
captures: list[CaptureInfo] = []
|
captures: list[CaptureInfo] = []
|
||||||
# Always check for focus using the the last `min_images_to_test` in the
|
# Always check for focus using the the last `min_images_to_test` in the
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ from openflexure_microscope_server.utilities import coerce_thing_selector
|
||||||
# Things
|
# Things
|
||||||
from .camera import BaseCamera
|
from .camera import BaseCamera
|
||||||
from .scan_workflows import ScanWorkflow
|
from .scan_workflows import ScanWorkflow
|
||||||
from .stage import BaseStage
|
from .stage import BacklashCompensation, BaseStage
|
||||||
|
|
||||||
T = TypeVar("T")
|
T = TypeVar("T")
|
||||||
P = ParamSpec("P")
|
P = ParamSpec("P")
|
||||||
|
|
@ -311,6 +311,7 @@ class SmartScanThing(lt.Thing):
|
||||||
x=next_point[0],
|
x=next_point[0],
|
||||||
y=next_point[1],
|
y=next_point[1],
|
||||||
z=z_estimate,
|
z=z_estimate,
|
||||||
|
backlash_compensation=BacklashCompensation.XY_ONLY,
|
||||||
)
|
)
|
||||||
|
|
||||||
return (next_point[0], next_point[1], z_estimate)
|
return (next_point[0], next_point[1], z_estimate)
|
||||||
|
|
|
||||||
|
|
@ -142,7 +142,9 @@ class BaseStage(lt.Thing):
|
||||||
"""Current position of the stage."""
|
"""Current position of the stage."""
|
||||||
return self._apply_axis_direction(self._hardware_position)
|
return self._apply_axis_direction(self._hardware_position)
|
||||||
|
|
||||||
backlash_steps: dict[str, int] = lt.setting(default={"x": 200, "y": 200, "z": 200})
|
backlash_steps: dict[str, int] = lt.setting(
|
||||||
|
default={"x": 200, "y": 200, "z": 200}, readonly=True
|
||||||
|
)
|
||||||
"""The number of steps to elimate backlash. The sign sets the direction.
|
"""The number of steps to elimate backlash. The sign sets the direction.
|
||||||
|
|
||||||
A positive number sets the direction of the second move in a backlash correction.
|
A positive number sets the direction of the second move in a backlash correction.
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,8 @@ def test_looping_autofocus(start_z, max_loc, centre, attempts_expected, passes,
|
||||||
|
|
||||||
def adjust_pos(**kwargs: int) -> None:
|
def adjust_pos(**kwargs: int) -> None:
|
||||||
"""Move relative should update position. So make a side effect for the mock."""
|
"""Move relative should update position. So make a side effect for the mock."""
|
||||||
|
# Remove backlash compensation from the dict if it exists.
|
||||||
|
kwargs.pop("backlash_compensation", None)
|
||||||
for axis, value in kwargs.items():
|
for axis, value in kwargs.items():
|
||||||
autofocus_thing._stage.position[axis] += value
|
autofocus_thing._stage.position[axis] += value
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue