Merge branch 'dont-test-focus-change' into 'v3'
Remove focus_change_acceptable test Closes #342 See merge request openflexure/openflexure-microscope-server!249
This commit is contained in:
commit
3adc34c30b
1 changed files with 18 additions and 66 deletions
|
|
@ -66,30 +66,6 @@ def unpack_autofocus(scan_data):
|
||||||
return jpeg_heights[turning[0] : turning[1]], jpeg_sizes_mb[turning[0] : turning[1]]
|
return jpeg_heights[turning[0] : turning[1]], jpeg_sizes_mb[turning[0] : turning[1]]
|
||||||
|
|
||||||
|
|
||||||
def focus_change_acceptable(prev_pos, prev_z, new_pos, new_z, fractional_limit):
|
|
||||||
"""Return true if the change in z-position is small enough.
|
|
||||||
|
|
||||||
A large change in z-position in an indication of focus failure.
|
|
||||||
fractional_limit is the largest ratio of change in z to change in xy that's allowed
|
|
||||||
"""
|
|
||||||
|
|
||||||
prev_xy = np.asarray(prev_pos, dtype="float64")
|
|
||||||
new_xy = np.asarray(new_pos, dtype="float64")
|
|
||||||
|
|
||||||
dist = np.sqrt(np.sum(((new_xy - prev_xy) / 10**4) ** 2, dtype="float64"))
|
|
||||||
|
|
||||||
focus_change = abs(new_z - prev_z) / 10**4
|
|
||||||
if dist == 0:
|
|
||||||
print(f"Not moved between {prev_pos} and {new_pos}")
|
|
||||||
movement_ratio = 0
|
|
||||||
else:
|
|
||||||
movement_ratio = np.divide(focus_change, dist, dtype="float64")
|
|
||||||
|
|
||||||
if movement_ratio > fractional_limit:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
class NotEnoughFreeSpaceError(IOError):
|
class NotEnoughFreeSpaceError(IOError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
@ -388,7 +364,7 @@ class SmartScanThing(Thing):
|
||||||
self._stage.move_absolute(
|
self._stage.move_absolute(
|
||||||
x=next_point[0],
|
x=next_point[0],
|
||||||
y=next_point[1],
|
y=next_point[1],
|
||||||
z=z_estimate - self._scan_data["autofocus_dz"] / 2,
|
z=z_estimate,
|
||||||
)
|
)
|
||||||
|
|
||||||
return (next_point[0], next_point[1], z_estimate)
|
return (next_point[0], next_point[1], z_estimate)
|
||||||
|
|
@ -578,6 +554,11 @@ class SmartScanThing(Thing):
|
||||||
|
|
||||||
next_pos_xy, z_est = route_planner.get_next_location_and_z_estimate()
|
next_pos_xy, z_est = route_planner.get_next_location_and_z_estimate()
|
||||||
new_pos_xyz = self._move_to_next_point(next_pos_xy, z_est)
|
new_pos_xyz = self._move_to_next_point(next_pos_xy, z_est)
|
||||||
|
current_pos_xyz = (
|
||||||
|
new_pos_xyz[0],
|
||||||
|
new_pos_xyz[1],
|
||||||
|
self._stage.position["z"],
|
||||||
|
)
|
||||||
|
|
||||||
capture_image = True
|
capture_image = True
|
||||||
# If skipping background, take an image to check if it is background
|
# If skipping background, take an image to check if it is background
|
||||||
|
|
@ -596,11 +577,11 @@ class SmartScanThing(Thing):
|
||||||
|
|
||||||
focused = False
|
focused = False
|
||||||
if self._scan_data["autofocus_on"]:
|
if self._scan_data["autofocus_on"]:
|
||||||
closest_xyz = route_planner.closest_focus_site(new_pos_xyz[:2])
|
focused, focused_z = self._try_autofocus(new_pos_xyz)
|
||||||
focused = self._try_autofocus(new_pos_xyz, closest_xyz)
|
current_pos_xyz = (new_pos_xyz[0], new_pos_xyz[1], focused_z)
|
||||||
|
|
||||||
route_planner.mark_location_visited(
|
route_planner.mark_location_visited(
|
||||||
new_pos_xyz, imaged=True, focused=focused
|
current_pos_xyz, imaged=True, focused=focused
|
||||||
)
|
)
|
||||||
|
|
||||||
# wait for the previous capture to be saved, i.e. don't leave more than one image saving in the background
|
# wait for the previous capture to be saved, i.e. don't leave more than one image saving in the background
|
||||||
|
|
@ -625,18 +606,15 @@ class SmartScanThing(Thing):
|
||||||
def _try_autofocus(
|
def _try_autofocus(
|
||||||
self,
|
self,
|
||||||
this_xyz: tuple[int, int, int],
|
this_xyz: tuple[int, int, int],
|
||||||
closest_xyz: Optional[tuple[int, int, int]],
|
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""
|
"""
|
||||||
Try to perform autofocus and return boolean for if successful
|
Try to perform autofocus and return boolean for if successful
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
this_xyz is the current x,y,z position.
|
this_xyz is the current x,y,z position.
|
||||||
closest_xyz is the (x, y, z) coordinates of the closest position, this is None
|
|
||||||
if no previous images have been taken or in focus
|
|
||||||
|
|
||||||
Return True on successful autofocus.
|
Return True, focused_height on successful autofocus.
|
||||||
Return False if failed after 3 tries - the position will be the initial estimate
|
Return False, initial_height if failed after 3 tries - the position will be the initial estimate
|
||||||
"""
|
"""
|
||||||
attempts = 0
|
attempts = 0
|
||||||
max_attempts = 3
|
max_attempts = 3
|
||||||
|
|
@ -645,46 +623,20 @@ class SmartScanThing(Thing):
|
||||||
while attempts < max_attempts:
|
while attempts < max_attempts:
|
||||||
attempts += 1
|
attempts += 1
|
||||||
|
|
||||||
_, jpeg_sizes = self._autofocus.looping_autofocus(dz=dz, start="base")
|
_, jpeg_sizes = self._autofocus.looping_autofocus(dz=dz, start="centre")
|
||||||
current_height = self._stage.position["z"]
|
|
||||||
time.sleep(0.2)
|
time.sleep(0.2)
|
||||||
autofocus_sharp_enough = self._autofocus.verify_focus_sharpness(
|
autofocus_sharp_enough = self._autofocus.verify_focus_sharpness(
|
||||||
sweep_sizes=jpeg_sizes, camera=CamDep, threshold=0.92
|
sweep_sizes=jpeg_sizes, camera=CamDep, threshold=0.92
|
||||||
)
|
)
|
||||||
|
|
||||||
# Not sharp enough, go to start and try again
|
# If sharp enough, break and return success, otherwise go to start and try again
|
||||||
if not autofocus_sharp_enough:
|
if autofocus_sharp_enough:
|
||||||
z = this_xyz[2] - dz / 2 if attempts < max_attempts else this_xyz[2]
|
return True, self._stage.position["z"]
|
||||||
self._stage.move_absolute(z=z)
|
else:
|
||||||
continue
|
self._stage.move_absolute(z=this_xyz[2])
|
||||||
|
|
||||||
# No previous positions to compare against return success
|
|
||||||
if closest_xyz is None:
|
|
||||||
return True
|
|
||||||
|
|
||||||
# Check the change in z-position is acceptable
|
|
||||||
# If the z change compared to the closest focused image exceeds
|
|
||||||
# a given fraction of the xy displacement this indicates failure
|
|
||||||
success = focus_change_acceptable(
|
|
||||||
prev_pos=closest_xyz[:2],
|
|
||||||
prev_z=closest_xyz[2],
|
|
||||||
new_pos=this_xyz[:2],
|
|
||||||
new_z=current_height,
|
|
||||||
fractional_limit=0.5,
|
|
||||||
)
|
|
||||||
# No focus change acceptable return success
|
|
||||||
if success:
|
|
||||||
return True
|
|
||||||
|
|
||||||
# Shifted to far move to start and try again
|
|
||||||
z = this_xyz[2] - dz / 2 if attempts < max_attempts else this_xyz[2]
|
|
||||||
self._stage.move_absolute(z=z)
|
|
||||||
self._scan_logger.info(
|
|
||||||
"The focus has shifted further than we expect: retrying."
|
|
||||||
)
|
|
||||||
|
|
||||||
self._scan_logger.warning("Could not autofocus after 3 attempts.")
|
self._scan_logger.warning("Could not autofocus after 3 attempts.")
|
||||||
return False
|
return False, self._stage.position["z"]
|
||||||
|
|
||||||
@_scan_running
|
@_scan_running
|
||||||
def _wait_for_capture_thread(self) -> None:
|
def _wait_for_capture_thread(self) -> None:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue