Wait params in captures, multiple attempts to capture

This commit is contained in:
jaknapper 2025-05-02 17:25:43 +01:00 committed by Julian Stirling
parent de7ffb9d1e
commit a9fdd0ea3e
3 changed files with 27 additions and 12 deletions

View file

@ -8,7 +8,7 @@ See repository root for licensing information.
from __future__ import annotations
import logging
from typing import Literal, Protocol, runtime_checkable
from typing import Literal, Protocol, runtime_checkable, Optional
from labthings_fastapi.thing import Thing
from labthings_fastapi.decorators import thing_action, thing_property
@ -45,12 +45,14 @@ class CameraProtocol(Protocol):
def capture_array(
self,
stream_name: Literal["main", "lores", "raw", "full"] = "main",
wait: Optional[float] = 5,
) -> NDArray: ...
def capture_jpeg(
self,
metadata_getter: GetThingStates,
resolution: Literal["lores", "main", "full"] = "main",
wait: Optional[float] = 5,
) -> JPEGBlob:
"""Acquire one image from the camera and return as a JPEG blob"""
...
@ -166,6 +168,7 @@ class CameraStub(BaseCamera):
def capture_array(
self,
stream_name: Literal["main", "lores", "raw", "full"] = "main",
wait: Optional[float] = 5,
) -> NDArray:
raise NotImplementedError("Cameras must not inherit from CameraStub")
@ -174,6 +177,7 @@ class CameraStub(BaseCamera):
self,
metadata_getter: GetThingStates,
resolution: Literal["lores", "main", "full"] = "main",
wait: Optional[float] = 5,
) -> JPEGBlob:
"""Acquire one image from the camera and return as a JPEG blob"""
raise NotImplementedError("Cameras must not inherit from CameraStub")

View file

@ -40,6 +40,7 @@ class CaptureThing(Thing):
cam,
metadata_getter,
stream=stream_name,
logger=logger,
)
acquisition_time = time.time()
self._save_capture(jpeg_path, image, metadata, logger)
@ -51,23 +52,33 @@ class CaptureThing(Thing):
)
@thing_action
def capture_jpeg(self, filename: str, cam: CamDep):
def capture_jpeg(self, filename: str, cam: CamDep, logger: InvocationLogger):
"""Capture a JPEG (from a JPEGBlob) to disk"""
jpeg = cam.capture_jpeg(resolution="full")
jpeg.save(filename)
for capture_attempts in range(5):
try:
jpeg = cam.capture_jpeg(resolution="full", wait=5)
jpeg.save(filename)
return
except TimeoutError:
logger.warning(f'Attempt {capture_attempts+1} to capture image timed out. Do you have enough RAM?')
except Exception as e:
logger.warning(e)
raise CaptureError("An error occurred while capturing after 5 attempts")
@thing_action
def _capture_array(self, cam: CamDep, metadata_getter: GetThingStates, stream: str = 'main'):
def _capture_array(self, cam: CamDep, metadata_getter: GetThingStates, logger: InvocationLogger, 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=stream)[..., :3]
except Exception as e:
raise CaptureError("An error occurred while capturing") from e
return image, metadata
for capture_attempts in range(5):
try:
metadata = metadata_getter()
image = cam.capture_array(stream_name=stream, wait=5)[..., :3]
return image, metadata
except TimeoutError:
logger.warning(f'Attempt {capture_attempts+1} to capture image timed out. Do you have enough RAM?')
raise CaptureError("An error occurred while capturing after 5 attempts")
def _save_capture(
self,

View file

@ -694,7 +694,7 @@ class SmartScanThing(Thing):
self._autofocus.run_z_stack(
images_dir=self._ongoing_scan_images_dir,
stack_dir=site_folder,
capture_method="hires_array",
capture_method="blob",
)
# increment capure counter as thread has completed