adding screening diffraction image ingestion logic to aaredb and service methods
Build and Publish / test (push) Successful in 2m14s
Build and Publish / build (push) Successful in 17s
Build and Publish / Build and Deploy Docs (push) Successful in 42s

This commit is contained in:
GotthardG
2026-06-29 15:58:41 +02:00
parent bfa9bf04a9
commit 5c9635d35d
3 changed files with 72 additions and 8 deletions
+10 -6
View File
@@ -152,18 +152,22 @@ class AareWrapper:
logger.debug(f"Response status code: {response.status_code}")
@log_timing(logger, "AareDB call")
def upload_jpg(self, sample_id: int, filename: str, jpg_image):
def upload_jpg(self, sample_id: int, filename: str, jpg_image, message: Optional[str] = None):
logger.debug(f"jppg_image of type: {type(jpg_image)}")
url = f"{self.__host}/protected_router/sample_runner/{sample_id}/upload-images"
headers = {
"accept": "application/json",
"X-Shared-Password": os.getenv("AAREDB_SHARED_PASSWORD")
}
response = requests.post(url,
files={'uploaded_file': (filename + ".jpg", jpg_image, "image/jpeg")},
verify=self.__ssl_ca_cert,
cert=(self.__cert_file, self.__key_file),
headers=headers)
request_kwargs = {
"files": {'uploaded_file': (filename + ".jpg", jpg_image, "image/jpeg")},
"verify": self.__ssl_ca_cert,
"cert": (self.__cert_file, self.__key_file),
"headers": headers,
}
if message is not None:
request_kwargs["data"] = {"comment": message}
response = requests.post(url, **request_kwargs)
logger.debug(f"Response status code: {response.status_code}")
@log_timing(logger, "AareDB call")
@@ -85,6 +85,47 @@ class RotationService:
result=scan_result,
)
def _ingest_screening_diffraction(self, sample, scan_result) -> None:
"""Pull each screening wedge's diffraction image from JFJoch (with spot
finding + resolution-estimate ring drawn in) and upload it to the DB,
linked to this run's sample. One image per wedge (1/2/4 typically).
Best-effort: a missing/failed image is logged and skipped, never fatal.
"""
images = getattr(scan_result, "images", None) or []
for idx, img in enumerate(images, start=1):
image_id = getattr(img, "number", None)
if image_id is None:
continue
try:
jpg = self.ctx.deps.jfjoch.get_diffraction_image(
image_id, show_spots=True, show_res_est=True
)
except Exception:
self.logger.warning(
"Screening diffraction image %s unavailable; skipping",
image_id,
exc_info=True,
)
continue
bits = []
angle = getattr(img, "angle", None)
spots = getattr(img, "spots", None)
res = getattr(img, "res", None)
if angle is not None:
bits.append(f"{angle:.2f}°")
if spots is not None:
bits.append(f"{spots} spots")
if res is not None:
bits.append(f"{res:.2f} Å")
comment = "Screening diffraction (wedge {}{})".format(
idx, (", " + ", ".join(bits)) if bits else ""
)
filename = f"{sample.db_id}_screening_diffraction_{image_id}"
self.ctx.deps.aare.upload_jpg(
sample.db_id, filename, jpg, message=comment
)
def run(self, request: RotationScanRequest) -> CompletedRotationScan:
sample = self.ctx.sample
@@ -112,6 +153,12 @@ class RotationService:
self.ctx.settings.preview_filename,
)
# For screening runs, ingest the per-wedge diffraction images. Done
# before the COLLECTED event so they pin to the same sample event the
# run is bound to (the COLLECTING event), matching the preview above.
if request.screening and not self.ctx.deps.cfg.simulated_detector:
self._ingest_screening_diffraction(sample, result.result)
if self.ctx.services.events is not None:
self.ctx.services.events.send(sample.db_id, SampleEventType.COLLECTED)
+15 -2
View File
@@ -298,11 +298,24 @@ class JFJochWrapper:
def take_pedestal(self):
raise NotImplementedError("take_pedestal is not implemented in DAQ through the JFJoch API yet")
def get_diffraction_image(self, image_id: int, wait_between_retries_s: float = 0.1):
def get_diffraction_image(
self,
image_id: int,
wait_between_retries_s: float = 0.1,
*,
show_spots: bool = False,
show_res_est: bool = False,
show_beam_center: bool = False,
):
last_error = None
for _ in range(3):
try:
return self.__api.image_buffer_image_jpeg_get(id=image_id, show_spots=False)
return self.__api.image_buffer_image_jpeg_get(
id=image_id,
show_spots=show_spots,
show_res_est=show_res_est,
show_beam_center=show_beam_center,
)
except Exception as e:
last_error = e
time.sleep(wait_between_retries_s)