Wait params in captures, multiple attempts to capture
This commit is contained in:
parent
de7ffb9d1e
commit
a9fdd0ea3e
3 changed files with 27 additions and 12 deletions
|
|
@ -8,7 +8,7 @@ See repository root for licensing information.
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
import logging
|
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.thing import Thing
|
||||||
from labthings_fastapi.decorators import thing_action, thing_property
|
from labthings_fastapi.decorators import thing_action, thing_property
|
||||||
|
|
@ -45,12 +45,14 @@ class CameraProtocol(Protocol):
|
||||||
def capture_array(
|
def capture_array(
|
||||||
self,
|
self,
|
||||||
stream_name: Literal["main", "lores", "raw", "full"] = "main",
|
stream_name: Literal["main", "lores", "raw", "full"] = "main",
|
||||||
|
wait: Optional[float] = 5,
|
||||||
) -> NDArray: ...
|
) -> NDArray: ...
|
||||||
|
|
||||||
def capture_jpeg(
|
def capture_jpeg(
|
||||||
self,
|
self,
|
||||||
metadata_getter: GetThingStates,
|
metadata_getter: GetThingStates,
|
||||||
resolution: Literal["lores", "main", "full"] = "main",
|
resolution: Literal["lores", "main", "full"] = "main",
|
||||||
|
wait: Optional[float] = 5,
|
||||||
) -> JPEGBlob:
|
) -> JPEGBlob:
|
||||||
"""Acquire one image from the camera and return as a JPEG blob"""
|
"""Acquire one image from the camera and return as a JPEG blob"""
|
||||||
...
|
...
|
||||||
|
|
@ -166,6 +168,7 @@ class CameraStub(BaseCamera):
|
||||||
def capture_array(
|
def capture_array(
|
||||||
self,
|
self,
|
||||||
stream_name: Literal["main", "lores", "raw", "full"] = "main",
|
stream_name: Literal["main", "lores", "raw", "full"] = "main",
|
||||||
|
wait: Optional[float] = 5,
|
||||||
) -> NDArray:
|
) -> NDArray:
|
||||||
raise NotImplementedError("Cameras must not inherit from CameraStub")
|
raise NotImplementedError("Cameras must not inherit from CameraStub")
|
||||||
|
|
||||||
|
|
@ -174,6 +177,7 @@ class CameraStub(BaseCamera):
|
||||||
self,
|
self,
|
||||||
metadata_getter: GetThingStates,
|
metadata_getter: GetThingStates,
|
||||||
resolution: Literal["lores", "main", "full"] = "main",
|
resolution: Literal["lores", "main", "full"] = "main",
|
||||||
|
wait: Optional[float] = 5,
|
||||||
) -> JPEGBlob:
|
) -> JPEGBlob:
|
||||||
"""Acquire one image from the camera and return as a JPEG blob"""
|
"""Acquire one image from the camera and return as a JPEG blob"""
|
||||||
raise NotImplementedError("Cameras must not inherit from CameraStub")
|
raise NotImplementedError("Cameras must not inherit from CameraStub")
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ class CaptureThing(Thing):
|
||||||
cam,
|
cam,
|
||||||
metadata_getter,
|
metadata_getter,
|
||||||
stream=stream_name,
|
stream=stream_name,
|
||||||
|
logger=logger,
|
||||||
)
|
)
|
||||||
acquisition_time = time.time()
|
acquisition_time = time.time()
|
||||||
self._save_capture(jpeg_path, image, metadata, logger)
|
self._save_capture(jpeg_path, image, metadata, logger)
|
||||||
|
|
@ -51,23 +52,33 @@ class CaptureThing(Thing):
|
||||||
)
|
)
|
||||||
|
|
||||||
@thing_action
|
@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"""
|
"""Capture a JPEG (from a JPEGBlob) to disk"""
|
||||||
jpeg = cam.capture_jpeg(resolution="full")
|
for capture_attempts in range(5):
|
||||||
jpeg.save(filename)
|
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
|
@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
|
"""Capture an image in memory and return it with metadata
|
||||||
CaptureError raised if the capture fails for any reason
|
CaptureError raised if the capture fails for any reason
|
||||||
returns tuple with numpy array of image data, and dict of metadata
|
returns tuple with numpy array of image data, and dict of metadata
|
||||||
"""
|
"""
|
||||||
try:
|
for capture_attempts in range(5):
|
||||||
metadata = metadata_getter()
|
try:
|
||||||
image = cam.capture_array(stream_name=stream)[..., :3]
|
metadata = metadata_getter()
|
||||||
except Exception as e:
|
image = cam.capture_array(stream_name=stream, wait=5)[..., :3]
|
||||||
raise CaptureError("An error occurred while capturing") from e
|
return image, metadata
|
||||||
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(
|
def _save_capture(
|
||||||
self,
|
self,
|
||||||
|
|
|
||||||
|
|
@ -694,7 +694,7 @@ class SmartScanThing(Thing):
|
||||||
self._autofocus.run_z_stack(
|
self._autofocus.run_z_stack(
|
||||||
images_dir=self._ongoing_scan_images_dir,
|
images_dir=self._ongoing_scan_images_dir,
|
||||||
stack_dir=site_folder,
|
stack_dir=site_folder,
|
||||||
capture_method="hires_array",
|
capture_method="blob",
|
||||||
)
|
)
|
||||||
|
|
||||||
# increment capure counter as thread has completed
|
# increment capure counter as thread has completed
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue