DAQ: added screenshot service handler
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
import time
|
||||
from typing import Protocol
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
|
||||
from aare.common.models import SampleShortInfo
|
||||
from aare.daq.aaredb import AareWrapper
|
||||
from aare.daq.mlbox import MlBox
|
||||
from aare.devices.mx_lib import clean_filename
|
||||
|
||||
|
||||
class NonCriticalRunner(Protocol):
|
||||
def __call__(
|
||||
self,
|
||||
action,
|
||||
*,
|
||||
description: str,
|
||||
sample: SampleShortInfo | None = None,
|
||||
) -> object | None: ...
|
||||
|
||||
|
||||
class SampleProvider(Protocol):
|
||||
@property
|
||||
def sample(self) -> SampleShortInfo | None: ...
|
||||
|
||||
|
||||
class PGroupProvider(Protocol):
|
||||
@property
|
||||
def pgroup(self) -> str | None: ...
|
||||
|
||||
|
||||
@dataclass
|
||||
class ScreenshotService:
|
||||
mlbox: MlBox
|
||||
aare: AareWrapper
|
||||
logger: object
|
||||
run_noncritical: NonCriticalRunner
|
||||
sample_provider: SampleProvider
|
||||
pgroup_provider: PGroupProvider
|
||||
output_dir: str = "/sls/mx/applications/logs"
|
||||
photos_root: str = "/sls/mx/data"
|
||||
|
||||
def _get_inference_image(self) -> np.ndarray:
|
||||
image = self.mlbox.get_latest_image()
|
||||
if image is None:
|
||||
raise RuntimeError("No inference image available from aarelc-infer")
|
||||
return image
|
||||
|
||||
def _current_sample(self) -> SampleShortInfo | None:
|
||||
provider = self.sample_provider
|
||||
if callable(provider):
|
||||
return provider()
|
||||
return provider.sample
|
||||
|
||||
def _current_pgroup(self) -> str | None:
|
||||
provider = self.pgroup_provider
|
||||
if callable(provider):
|
||||
return provider()
|
||||
return provider.pgroup
|
||||
|
||||
def save_local(self, filename: str, settle_time_s: float = 0.2) -> None:
|
||||
time.sleep(settle_time_s)
|
||||
bgr_image = self._get_inference_image()
|
||||
self.logger.debug(f"saving screenshot {filename} from inference image")
|
||||
cv2.imwrite(f"{self.output_dir}/{filename}.jpg", bgr_image)
|
||||
|
||||
def save_to_db(self, sample_id: int, filename: str, settle_time_s: float = 0.2) -> None:
|
||||
time.sleep(settle_time_s)
|
||||
sample = self._current_sample()
|
||||
bgr_image = self._get_inference_image()
|
||||
|
||||
def _upload() -> None:
|
||||
self.aare.upload_image(sample_id, filename, bgr_image)
|
||||
|
||||
self.run_noncritical(
|
||||
_upload,
|
||||
description=f"screenshot upload '{filename}'",
|
||||
sample=sample,
|
||||
)
|
||||
|
||||
def send_to_db(
|
||||
self,
|
||||
*,
|
||||
filename: str | None = None,
|
||||
message: str | None = None,
|
||||
default_message: str,
|
||||
) -> None:
|
||||
sample = self._current_sample()
|
||||
if sample is None or sample.db_id is None or sample.db_id < 0:
|
||||
raise ValueError("No sample with a valid sample_id is mounted.")
|
||||
|
||||
sample_id = sample.db_id
|
||||
pgroup = self._current_pgroup()
|
||||
bgr_image = self._get_inference_image()
|
||||
|
||||
if filename:
|
||||
safe_filename = clean_filename(filename)
|
||||
if not pgroup:
|
||||
raise ValueError("No active pgroup set; cannot save screenshot to photos directory.")
|
||||
|
||||
photos_dir = Path(self.photos_root) / pgroup / "raw" / "photos" / str(sample_id)
|
||||
photos_dir.mkdir(parents=True, exist_ok=True)
|
||||
photo_path = photos_dir / f"{safe_filename}.jpeg"
|
||||
cv2.imwrite(str(photo_path), bgr_image)
|
||||
upload_name = safe_filename
|
||||
else:
|
||||
upload_name = f"{sample_id}_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
|
||||
|
||||
final_message = (message or "").strip() or default_message
|
||||
|
||||
def _upload() -> None:
|
||||
self.aare.upload_image(sample_id, upload_name, bgr_image, message=final_message)
|
||||
|
||||
self.run_noncritical(
|
||||
_upload,
|
||||
description=f"send screenshot '{upload_name}'",
|
||||
sample=sample,
|
||||
)
|
||||
Reference in New Issue
Block a user