From 8bc0573ab1342e4d2cfec3a9063277812332e63c Mon Sep 17 00:00:00 2001 From: jaknapper Date: Thu, 1 May 2025 16:07:05 +0100 Subject: [PATCH] Capture_array can now use "full" stream --- .../things/autofocus.py | 15 ++------ .../things/camera/__init__.py | 16 +------- .../things/capture.py | 38 ++----------------- 3 files changed, 9 insertions(+), 60 deletions(-) diff --git a/src/openflexure_microscope_server/things/autofocus.py b/src/openflexure_microscope_server/things/autofocus.py index 528195a4..7131cd0d 100644 --- a/src/openflexure_microscope_server/things/autofocus.py +++ b/src/openflexure_microscope_server/things/autofocus.py @@ -311,25 +311,16 @@ class AutofocusThing(Thing): stack_dir, f"{capture_count}.jpeg", ) - metadata = metadata_getter() if capture_method == "blob": capture.capture_jpeg(filename=jpeg_path, cam=cam) - elif capture_method == "hires_array": - # A new way to get the full array - img = capture.capture_highres_array() - _save_capture( - jpeg_path, - img, - metadata, - logger - ) - elif capture_method == "array": - # The old capture and save a "main" res image + elif capture_method == "hires_array" or capture_method == "array": + stream = 'main' if capture_method == "array" else "full" capture._capture_and_save( jpeg_path=jpeg_path, cam=cam, logger=logger, metadata_getter=metadata_getter, + stream_name=stream, ) else: raise ValueError('Capture method must be one of "array", "blob" or "hires_array"') diff --git a/src/openflexure_microscope_server/things/camera/__init__.py b/src/openflexure_microscope_server/things/camera/__init__.py index 6f84fe66..076d2efd 100644 --- a/src/openflexure_microscope_server/things/camera/__init__.py +++ b/src/openflexure_microscope_server/things/camera/__init__.py @@ -44,7 +44,7 @@ class CameraProtocol(Protocol): def capture_array( self, - stream_name: Literal["main", "lores", "raw"] = "main", + stream_name: Literal["main", "lores", "raw", "full"] = "main", ) -> NDArray: ... def capture_jpeg( @@ -77,12 +77,6 @@ class CameraProtocol(Protocol): """Acquire one image from the preview stream and return its size""" ... - def capture_highres_array( - self, - ): - ... - - class BaseCamera(Thing): """A Thing representing a camera @@ -171,16 +165,10 @@ class CameraStub(BaseCamera): @thing_action def capture_array( self, - stream_name: Literal["main", "lores", "raw"] = "main", + stream_name: Literal["main", "lores", "raw", "full"] = "main", ) -> NDArray: raise NotImplementedError("Cameras must not inherit from CameraStub") - @thing_action - def capture_highres_array( - self, - ): - raise NotImplementedError("Cameras must not inherit from CameraStub") - @thing_action def capture_jpeg( self, diff --git a/src/openflexure_microscope_server/things/capture.py b/src/openflexure_microscope_server/things/capture.py index c4ca7cae..dc5a1572 100644 --- a/src/openflexure_microscope_server/things/capture.py +++ b/src/openflexure_microscope_server/things/capture.py @@ -28,6 +28,7 @@ class CaptureThing(Thing): cam: CamDep, logger: InvocationLogger, metadata_getter: GetThingStates, + stream: str = "main", ) -> None: """Capture an image and save it to disk @@ -38,6 +39,7 @@ class CaptureThing(Thing): image, metadata = self._capture_array( cam, metadata_getter, + stream=stream, ) acquisition_time = time.time() self._save_capture(jpeg_path, image, metadata, logger) @@ -55,19 +57,14 @@ class CaptureThing(Thing): jpeg.save(filename) @thing_action - def capture_highres_array(self, cam: CamDep): - """Return a full resolution stream array""" - return cam.capture_highres_array() - - @thing_action - def _capture_array(self, cam: CamDep, metadata_getter: GetThingStates): + def _capture_array(self, cam: CamDep, metadata_getter: GetThingStates, stream: str = 'main'): """Capture an image in memory and return it with metadata CaptureError raised if the capture fails for any reason returns tuple with numpy array of image data, and dict of metadata """ try: metadata = metadata_getter() - image = cam.capture_array(stream_name="main")[..., :3] + image = cam.capture_array(stream_name=stream)[..., :3] except Exception as e: raise CaptureError("An error occurred while capturing") from e return image, metadata @@ -99,30 +96,3 @@ class CaptureThing(Thing): logger.warning(f"Failed to add metadata to {jpeg_path}") except Exception as e: raise IOError(f"An error occurred while saving {jpeg_path}") from e - -def _save_capture( - jpeg_path: str, - image: np.ndarray, - metadata: dict, - logger: InvocationLogger, -) -> None: - """Saving the captured image and metadata to disk - logger warning (via InvocationLogger) is raised if metadata is failed to be added - IOError is raised if the file cannot be saved - nothing is returned on success""" - try: - Image.fromarray(image.astype("uint8"), "RGB").save( - jpeg_path, quality=95, subsampling=0 - ) - try: - exif_dict = piexif.load(jpeg_path) - exif_dict["Exif"][piexif.ExifIFD.UserComment] = json.dumps( - metadata - ).encode("utf-8") - piexif.insert(piexif.dump(exif_dict), jpeg_path) - except: # noqa: E722 - # We need to capture any exception as there are many reasons metadata - # might not be added. We warn rather than log the error. - logger.warning(f"Failed to add metadata to {jpeg_path}") - except Exception as e: - raise IOError(f"An error occurred while saving {jpeg_path}") from e