From ecbdd8a5bff4ebb06f1b82de2d97e8dd3ca4f111 Mon Sep 17 00:00:00 2001 From: Joe Knapper Date: Wed, 1 Dec 2021 13:09:32 +0000 Subject: [PATCH 1/3] Added measure_settling_time function to autofocus --- .../api/default_extensions/autofocus.py | 53 ++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/openflexure_microscope/api/default_extensions/autofocus.py b/openflexure_microscope/api/default_extensions/autofocus.py index 5f736121..c8918517 100644 --- a/openflexure_microscope/api/default_extensions/autofocus.py +++ b/openflexure_microscope/api/default_extensions/autofocus.py @@ -45,6 +45,31 @@ class JPEGSharpnessMonitor: self.camera.stream.stop_tracking() self.camera.stream.reset_tracking() + def hold(self, delay: int = 5): + self.camera.stream.start_tracking() + self.stage_times.append(time.time()) + self.stage_positions.append(self.stage.position) + + time.sleep(delay) + + self.camera.stream.stop_tracking() + self.stage_times.append(time.time()) + self.stage_positions.append(self.stage.position) + + # Retrieve frame data + for frame in self.camera.stream.frames: + # Make timestamp absolute Unix time + self.jpeg_times.append(frame.time) + self.jpeg_sizes.append(frame.size) + # Clear frame data for this move from the stream + self.camera.stream.reset_tracking() + + # Index of the data for this movement + data_index: int = len(self.stage_positions) - 2 + # Final z position after move + final_z_position: int = self.stage_positions[-1][2] + return data_index, final_z_position + def focus_rel(self, dz: int, backlash: bool = False, **kwargs) -> Tuple[int, int]: # Store the start time and position self.camera.stream.start_tracking() @@ -496,6 +521,32 @@ class AutofocusExtension(BaseExtension): # Return all focus data return m.data_dict() + @extension_action( + args={ + "dz": fields.Int( + missing=500, + example=500, + description="Total Z range to move down, then up (in stage steps)", + ), + "delay": fields.Int( + missing=5, + example=5, + description="How long to measure sharpness for after the move", + ) + } + ) + def measure_settling_time(self, microscope: Optional[Microscope] = None, delay: int = 2, dz: int = 400) -> Dict[str, np.ndarray]: + """Make a Z move down then up, then monitor sharpness. + This is useful so we can see how long we need to wait for the sharpness value to converge""" + if not microscope: + microscope = find_microscope_with_real_stage() + with microscope.lock(timeout=1), microscope.camera.lock, microscope.stage.lock: + with monitor_sharpness(microscope) as m: + m.focus_rel(-dz) + m.focus_rel(dz) + m.hold(delay) + return m.data_dict() + @extension_action( args={ "dz": fields.Int( @@ -516,7 +567,7 @@ class AutofocusExtension(BaseExtension): missing=25, minimum=0, description="Distance to undershoot, before correction move.", - ), + ) } ) def fast_up_down_up_autofocus( From 2d494b41d91326ebd495c54b4b39b5930dc489ff Mon Sep 17 00:00:00 2001 From: Joe Knapper Date: Tue, 11 Jan 2022 15:46:15 +0000 Subject: [PATCH 2/3] Added docstring for measure_settling_time and hold --- openflexure_microscope/api/default_extensions/autofocus.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openflexure_microscope/api/default_extensions/autofocus.py b/openflexure_microscope/api/default_extensions/autofocus.py index c8918517..46879f04 100644 --- a/openflexure_microscope/api/default_extensions/autofocus.py +++ b/openflexure_microscope/api/default_extensions/autofocus.py @@ -46,6 +46,8 @@ class JPEGSharpnessMonitor: self.camera.stream.reset_tracking() def hold(self, delay: int = 5): + """Run time.sleep for delay seconds, + while monitoring the JPEG frame size of the stream""" self.camera.stream.start_tracking() self.stage_times.append(time.time()) self.stage_positions.append(self.stage.position) @@ -536,7 +538,7 @@ class AutofocusExtension(BaseExtension): } ) def measure_settling_time(self, microscope: Optional[Microscope] = None, delay: int = 2, dz: int = 400) -> Dict[str, np.ndarray]: - """Make a Z move down then up, then monitor sharpness. + """Make a Z move down then up by dz, then pause for delay while monitoring sharpness. This is useful so we can see how long we need to wait for the sharpness value to converge""" if not microscope: microscope = find_microscope_with_real_stage() From 23bf3410f3c2089e3c506951b96afdf83cc44932 Mon Sep 17 00:00:00 2001 From: Richard Bowman Date: Thu, 13 Jan 2022 14:47:38 +0000 Subject: [PATCH 3/3] Code formatting fixes from black --- .../api/default_extensions/autofocus.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/openflexure_microscope/api/default_extensions/autofocus.py b/openflexure_microscope/api/default_extensions/autofocus.py index 46879f04..04d98d3b 100644 --- a/openflexure_microscope/api/default_extensions/autofocus.py +++ b/openflexure_microscope/api/default_extensions/autofocus.py @@ -534,10 +534,12 @@ class AutofocusExtension(BaseExtension): missing=5, example=5, description="How long to measure sharpness for after the move", - ) + ), } ) - def measure_settling_time(self, microscope: Optional[Microscope] = None, delay: int = 2, dz: int = 400) -> Dict[str, np.ndarray]: + def measure_settling_time( + self, microscope: Optional[Microscope] = None, delay: int = 2, dz: int = 400 + ) -> Dict[str, np.ndarray]: """Make a Z move down then up by dz, then pause for delay while monitoring sharpness. This is useful so we can see how long we need to wait for the sharpness value to converge""" if not microscope: @@ -569,7 +571,7 @@ class AutofocusExtension(BaseExtension): missing=25, minimum=0, description="Distance to undershoot, before correction move.", - ) + ), } ) def fast_up_down_up_autofocus(