More docstrings and comments. Removed json dump to openflexure folder.
This commit is contained in:
parent
4cde2d5cd1
commit
024c74f67b
1 changed files with 43 additions and 15 deletions
|
|
@ -9,12 +9,12 @@ of increasing pixel sizes in the opposite direction until motion is detected. Th
|
|||
position is taken as the true final position.
|
||||
|
||||
Throughout the test, parasitic motion(motion in the axis not being measured)
|
||||
is tracked and an error is raised if it exceeds a reasonable amount.
|
||||
is tracked and an error is raised if it exceeds a minimum amount. Currently
|
||||
this is 10% of the expected motion is the measured axis.
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
import cv2
|
||||
import json
|
||||
from typing import Literal
|
||||
from PIL import Image
|
||||
import time
|
||||
|
|
@ -54,11 +54,15 @@ def _generate_move_dicts(
|
|||
return {
|
||||
"x": (fov_perc / 100) * stream_resolution[0] * factor * direction,
|
||||
"y": (fov_perc / 100) * stream_resolution[1] * factor * direction,
|
||||
}
|
||||
} # factor used for creating minimum offsets.
|
||||
|
||||
|
||||
def _predict_z(
|
||||
positions: list, axis: Literal["x", "y"], relative_move: float, stage: StageDep, csm: CSMDep
|
||||
positions: list,
|
||||
axis: Literal["x", "y"],
|
||||
relative_move: float,
|
||||
stage: StageDep,
|
||||
csm: CSMDep,
|
||||
) -> float:
|
||||
"""Predict the next z position for a move using previous positions.
|
||||
|
||||
|
|
@ -67,6 +71,8 @@ def _predict_z(
|
|||
:params axis: The axis in which the stage is moving. This must be 'x' or 'y'.
|
||||
:params relative_move: The move which the function is trying to predict z for.
|
||||
Here, this is inputted with units of pixels.
|
||||
:param stage: A direct_thing_client dependency for the the microscope stage.
|
||||
:param csm: A direct_thing_client dependency for camera stage mapping.
|
||||
:return: A number of pixels the stage needs to move in z.
|
||||
"""
|
||||
pixel_step = {
|
||||
|
|
@ -74,7 +80,7 @@ def _predict_z(
|
|||
"y": 1 / csm.image_to_stage_displacement_matrix[1][0],
|
||||
}
|
||||
|
||||
lateral_positions = [i[axis] for i in positions]
|
||||
lateral_positions = [i[axis] for i in positions] # x or y positions
|
||||
z_positions = [i["z"] for i in positions]
|
||||
parameters, _ = curve_fit(quadratic, lateral_positions, z_positions)
|
||||
z_dest = quadratic(
|
||||
|
|
@ -101,6 +107,9 @@ def _move_and_measure(
|
|||
:params data: The object used to track stage coordinates, correlation and delta.
|
||||
:params image1: An image taken before moving to be correlated with image2.
|
||||
:params autofocus_proc: If true, looping.autofocus will be used after the stage moves.
|
||||
:param csm: A direct_thing_client dependency for camera stage mapping.
|
||||
:param autofocus: A direct_thing_client dependency for autofocus.
|
||||
:param camera: A raw_thing_client depeendency for the camera.
|
||||
:return: All required data for the next move. This includes the updated delta value and offset.
|
||||
Also returns what wrong_axis is i.e. if the direction is 'x', wrong_axis = 'y'.
|
||||
"""
|
||||
|
|
@ -144,6 +153,10 @@ def _acquire_z_predict_points(
|
|||
:param direction: The direction the stage moves.
|
||||
:params axis: The axis which is being measured. This must be 'x' or 'y'.
|
||||
:params data: The object used to track stage coordinates, correlation and delta.
|
||||
:param csm: A direct_thing_client dependency for camera stage mapping.
|
||||
:param camera: A raw_thing_client depeendency for the camera.
|
||||
:param stage: A raw_thing_client depeendency for the microscope stage.
|
||||
:param autofocus: A direct_thing_client dependency for autofocus.
|
||||
:return: Stage_coords and cor_lat_steps are lists of data tracked throughout the test.
|
||||
Delta is updated and tracked after each move.
|
||||
"""
|
||||
|
|
@ -154,7 +167,7 @@ def _acquire_z_predict_points(
|
|||
for _loop in range(5):
|
||||
image1 = cv2.resize(
|
||||
np.array(Image.open(cam.grab_jpeg().open())), dsize=(0, 0), fx=1, fy=1
|
||||
)
|
||||
) # Captures image with option to resize
|
||||
offset, wrong_axis = _move_and_measure(
|
||||
step_size=_generate_move_dicts(medium_step, stream_resolution, direction),
|
||||
axis=axis,
|
||||
|
|
@ -196,13 +209,17 @@ def _check_stage_operation(
|
|||
:params data: The object used to track stage coordinates, correlation and delta.
|
||||
:params minimum_offset_small: A dictionary containing the minimum values for
|
||||
a successful correlation.
|
||||
:param csm: A direct_thing_client dependency for camera stage mapping.
|
||||
:param camera: A raw_thing_client depeendency for the camera.
|
||||
:param stage: A raw_thing_client depeendency for the microscope stage.
|
||||
:param autofocus: A direct_thing_client dependency for autofocus.
|
||||
:return: Stage_coords and cor_lat_steps are lists of data tracked throughout the test.
|
||||
Delta is updated and tracked after each move.
|
||||
"""
|
||||
failure_count = 0
|
||||
wrong_axis_max_small = _generate_move_dicts(
|
||||
small_step, stream_resolution, direction, factor=0.1
|
||||
)
|
||||
) # Dictionary with maximum allowed parasitic motion
|
||||
|
||||
for _loop in range(3):
|
||||
image1 = cv2.resize(
|
||||
|
|
@ -220,6 +237,7 @@ def _check_stage_operation(
|
|||
)
|
||||
logger.info(f"Offset measured as {data.delta[axis]}")
|
||||
|
||||
# If correlation is too small, refocuses and capture new image 3 times.
|
||||
while (
|
||||
np.abs(data.delta[axis]) < np.abs(minimum_offset_small[axis])
|
||||
and failure_count < 3
|
||||
|
|
@ -272,6 +290,9 @@ def _motion_detection(
|
|||
:params axis: The axis in which the stage is moving. This must be 'x' or 'y'.
|
||||
:params direction: The direction in which the stage was moving
|
||||
previous to motion detection being used.
|
||||
:param csm: A direct_thing_client dependency for camera stage mapping.
|
||||
:param stage: A raw_thing_client depeendency for the microscope stage.
|
||||
:param camera: A raw_thing_client depeendency for the camera.
|
||||
:return: The stage coordinates where motion was detected.
|
||||
"""
|
||||
displacements = [
|
||||
|
|
@ -285,7 +306,7 @@ def _motion_detection(
|
|||
128,
|
||||
256,
|
||||
512,
|
||||
] # Array of increasing step sizes
|
||||
] # Array of increasing pixel sizes
|
||||
motion_minimum = 20 # minimum number of pixels for motion to be detected
|
||||
|
||||
this_motion_step = {"x": 0, "y": 0}
|
||||
|
|
@ -353,10 +374,14 @@ class RangeofMotionThing(lt.Thing):
|
|||
csm: CSMDep,
|
||||
logger: lt.deps.InvocationLogger,
|
||||
axis: Literal["x", "y"],
|
||||
direction: Literal[1,-1],
|
||||
direction: Literal[1, -1],
|
||||
) -> dict:
|
||||
"""Measure the range of motion in a single axis and direction.
|
||||
|
||||
:param stage: A raw_thing_client depeendency for the microscope stage.
|
||||
:param cam: A raw_thing_client depeendency for the camera.
|
||||
:param csm: A raw_thing_client depeendency for camera stage mapping.
|
||||
:param logger: A raw_thing_client depeendency for the logger.
|
||||
:params axis: The axis which is being measured. This must be 'x' or 'y'.
|
||||
:params direction: The direction which is being measured. This must be 1 or -1.
|
||||
:return: Results dictionary containing stage positions,
|
||||
|
|
@ -366,11 +391,10 @@ class RangeofMotionThing(lt.Thing):
|
|||
|
||||
starting_position = list(stage.position.values())
|
||||
|
||||
rom_data = RomDataTracker()
|
||||
rom_data = RomDataTracker() # initialise data tracking object
|
||||
axis_results = {}
|
||||
|
||||
try:
|
||||
|
||||
logger.info(
|
||||
f"Beginning the {axis}-axis in the {'positive' if direction == 1 else 'negative'} direction"
|
||||
)
|
||||
|
|
@ -482,6 +506,11 @@ class RangeofMotionThing(lt.Thing):
|
|||
):
|
||||
"""Measures the range of motion of the stage across the x and y axes.
|
||||
|
||||
:param autofocus: A raw_thing_client dependency for autofocus.
|
||||
:param stage: A raw_thing_client depeendency for the microscope stage.
|
||||
:param cam: A raw_thing_client depeendency for the camera.
|
||||
:param csm: A raw_thing_client depeendency for camera stage mapping.
|
||||
:param logger: A raw_thing_client depeendency for the logger.
|
||||
:return: Results dictionary separated into keys of each axis and direction.
|
||||
"""
|
||||
logger.info(
|
||||
|
|
@ -491,6 +520,7 @@ class RangeofMotionThing(lt.Thing):
|
|||
start_time = time.time()
|
||||
rom_results = {}
|
||||
|
||||
# Loop through all axes and directions.
|
||||
for axis_dir in [["x", 1], ["x", -1], ["y", 1], ["y", -1]]:
|
||||
axis_dir_results = self.rom_axis(
|
||||
autofocus,
|
||||
|
|
@ -501,6 +531,7 @@ class RangeofMotionThing(lt.Thing):
|
|||
axis=axis_dir[0],
|
||||
direction=axis_dir[1],
|
||||
)
|
||||
# Save results from single axis and direction
|
||||
rom_results[f"{axis_dir}"] = axis_dir_results
|
||||
|
||||
end_time = time.time()
|
||||
|
|
@ -515,7 +546,7 @@ class RangeofMotionThing(lt.Thing):
|
|||
- rom_results["['y', -1]"]["final_position"]["y"]
|
||||
)
|
||||
step_range = [x_range, y_range]
|
||||
logger.info(f"Range of motion is {x_range} X {y_range}")
|
||||
logger.info(f"Range of motion is {x_range} X {y_range} steps")
|
||||
|
||||
rom_results["Time"] = total_time
|
||||
rom_results["CSM Matrix"] = csm.image_to_stage_displacement_matrix
|
||||
|
|
@ -523,9 +554,6 @@ class RangeofMotionThing(lt.Thing):
|
|||
|
||||
self.last_calibration = DenumpifyingDict(rom_results).model_dump()
|
||||
|
||||
with open("/var/openflexure/ROM_Test_Results.json", "w") as file_object:
|
||||
json.dump(rom_results, file_object, indent=3)
|
||||
|
||||
return rom_results
|
||||
|
||||
last_calibration = lt.ThingSetting(initial_value=None, model=dict, readonly=True)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue