DAQ: Include JFJoch, first try
Build and Publish / build (push) Successful in 22s

This commit is contained in:
2025-06-16 12:22:54 +02:00
parent 63fc40af7f
commit 5fdd3a3327
4 changed files with 211 additions and 96 deletions
+35 -26
View File
@@ -1,3 +1,4 @@
import copy
import time
from math import ceil
from typing import List, Tuple
@@ -6,7 +7,13 @@ import cv2
import numpy as np
import redis
from aaredaq import workflows
from aaredaq.autofocus import calculate_focus_measure
from aaredaq.config import BeamlineConfig, ABR_POS_MOUNT
from aaredaq.config import BeamlineStateEnum
from aaredaq.devices import BeamlineDevices
from aaredaq.mlbox import MlBox
from aaredaqlib.beamline import MXBeamline
from aaredaqlib.coordinate import Coordinate, SmargonCoordinate
from aaredaqlib.diffraction_geometry import DiffractionGeometry
from aaredaqlib.models import (
@@ -17,13 +24,7 @@ from aaredaqlib.models import (
from aaredaqlib.raster_grid import RasterGridRequest, CompletedRasterGrid
from aaredaqlib.rotation_scan import RotationScanRequest
from aaredaqlib.sample_geometry import SampleGeometryModel
from aaredaq import workflows
from aaredaqlib.beamline import MXBeamline
from aaredaq.config import BeamlineConfig, ABR_POS_MOUNT
from aaredaq.config import BeamlineStateEnum
from aaredaq.devices import BeamlineDevices
from aaredaq.mlbox import MlBox
from mxlibs3.jfjoch import JFJochWrapper
class TransformationInvalidException(Exception):
@@ -45,6 +46,7 @@ class AareDAQ:
self.__cfg = cfg
self.__devs = BeamlineDevices(bl)
self.__mlbox = MlBox()
self.__jfjoch = JFJochWrapper(bl)
@property
def state(self) -> BeamlineStateEnum:
@@ -239,9 +241,10 @@ class AareDAQ:
def list_loaded_pucks(self) -> List[PuckLoadedInfo]:
return self.__devs.tell.get_detected_pucks()
def __raster(self, r: RasterGridRequest):
def __raster(self, r: RasterGridRequest) -> CompletedRasterGrid:
max_time = r.exp_time_s * r.n_y * r.n_x + 60
self.__set_state(BeamlineStateEnum.DataCollection)
self.__jfjoch.measure_raster(r, self.diffraction_geometry, self.sample)
self.__devs.aerotech.move(r.omega_deg, wait=True, speed=360.0)
save_smargon_position = self.__devs.smargon.readback
self.__devs.smargon.target = r.smargon
@@ -251,15 +254,17 @@ class AareDAQ:
self.__devs.aerotech.wait_scan_done(max_time)
self.__devs.aerotech.reset()
self.__devs.smargon.target = save_smargon_position
result = self.__jfjoch.wait_till_done(5)
return CompletedRasterGrid(request=copy.deepcopy(r), result=result)
def measure_raster(self, r: RasterGridRequest) -> CompletedRasterGrid:
max_time = r.exp_time_s * r.n_y * r.n_x + 60
self.__cfg.try_set_busy(timeout=ceil(max_time + 360))
try:
self.__raster(r)
result = self.__raster(r)
self.__set_state(BeamlineStateEnum.SampleAlignment)
self.__cfg.state_busy = False
return CompletedRasterGrid(request=r)
return result
except Exception as e:
self.__cfg.state_busy = False
raise e
@@ -271,6 +276,8 @@ class AareDAQ:
self.__devs.smargon.target = request.start
self.__devs.smargon.wait()
self.__jfjoch.measure_rotation(request, self.diffraction_geometry, self.sample)
if request.screening:
self.__devs.aerotech.measure_screening(request.start_omega_deg,
request.wedge_omega_deg,
@@ -278,26 +285,27 @@ class AareDAQ:
request.incr_omega_deg,
request.steps)
self.__devs.aerotech.wait_scan_done(request.exp_time_s * request.steps + 60)
return
else:
total_omega = request.incr_omega_deg * request.steps
total_time = request.exp_time_s * request.steps
total_omega = request.incr_omega_deg * request.steps
total_time = request.exp_time_s * request.steps
self.__devs.aerotech.measure_standard(
request.start_omega_deg, total_omega, total_time
)
self.__devs.aerotech.measure_standard(
request.start_omega_deg, total_omega, total_time
)
if request.start is not None and request.end is not None:
smargon_time_step = request.time_sec / float(request.steps)
pos_step = (request.end.sh_mm - request.start.sh_mm) * (1.0 / float(request.steps))
if request.start is not None and request.end is not None:
smargon_time_step = request.time_sec / float(request.steps)
pos_step = (request.end.sh_mm - request.start.sh_mm) * (1.0 / float(request.steps))
for i in range(request.steps):
self.__devs.smargon.target = SmargonCoordinate(
sh_mm=request.start.sh_mm + pos_step * i
)
time.sleep(smargon_time_step)
for i in range(request.steps):
self.__devs.smargon.target = SmargonCoordinate(
sh_mm=request.start.sh_mm + pos_step * i
)
time.sleep(smargon_time_step)
self.__devs.aerotech.wait_scan_done(request.total_time_sec + 60)
self.__devs.aerotech.wait_scan_done(request.total_time_sec + 60)
self.__jfjoch.wait_till_done(5)
self.__devs.aerotech.reset()
def measure_rotation(self, request: RotationScanRequest):
@@ -722,10 +730,11 @@ class AareDAQ:
@property
def diffraction_geometry(self) -> DiffractionGeometry:
det_cfg = self.__jfjoch.detector()
return DiffractionGeometry(
energy_keV=self.__devs.energy_kev,
dtz_mm=self.__devs.dtz.value,
detector_size_pxl=(1553,1630),
detector_size_pxl=(det_cfg.width, det_cfg.height),
pixel_size_mm=0.150, #PILATUS 4
beam_center_pxl=self.__cfg.beam_center
)
-13
View File
@@ -1,13 +0,0 @@
from aaredaqlib.beamline import MXBeamline
from jfjoch_client.api.default_api import DefaultApi
from jfjoch_client.configuration import Configuration
class JfjochWrapper:
def __init__(
self,
bl: MXBeamline,
host: str = "https://sls-gpu-001:8080",
):
config = Configuration(host=host)
self.__client = DefaultApi(config)
+109
View File
@@ -0,0 +1,109 @@
import math
import jfjoch_client
from aaredaqlib.beamline import MXBeamline
from aaredaqlib.diffraction_geometry import DiffractionGeometry
from aaredaqlib.models import SampleShortInfo
from aaredaqlib.raster_grid import RasterGridRequest
from aaredaqlib.rotation_scan import RotationScanRequest
class JFJochWrapper:
def __init__(self, bl: MXBeamline):
match bl:
case MXBeamline.X06DA:
self.__url = "http://sls-gpu-001:8080"
case MXBeamline.SIMULATED:
self.__url = "http://localhost:8080"
case _:
raise Exception("unknown beamline")
self.__client = jfjoch_client.ApiClient(jfjoch_client.Configuration(host=self.__url))
self.__api = jfjoch_client.DefaultApi(self.__client)
def initialize(self):
self.__api.initialize_post()
def is_idle(self) -> bool:
status = self.__api.status_get()
return status.state == 'Idle'
def measure_rotation(self,
r: RotationScanRequest,
d: DiffractionGeometry,
s: SampleShortInfo | None) -> None:
if s is None:
pgroup = "p16371"
sample = None
else:
pgroup = s.user
sample = s.sample_name
goniometer_settings = jfjoch_client.RotationAxis(
step=r.incr_omega_deg,
start=r.start_omega_deg,
name="omega",
vector= [0,1,0]
)
dataset_settings = jfjoch_client.DatasetSettings(
beam_x_pxl=d.beam_center_pxl[0],
beam_y_pxl=d.beam_center_pxl[1],
ntrigger= 1,
images_per_trigger=r.steps,
detector_distance_mm=d.dtz_mm,
file_prefix=f"{pgroup}/raw/{r.file_prefix}",
incident_energy_keV=d.energy_keV,
goniometer=goniometer_settings,
sample_name=sample,
image_time_us=round(r.exp_time_s * 1e6),
experiment_group=pgroup
)
self.__api.start_post(dataset_settings=dataset_settings)
def measure_raster(self,
r: RasterGridRequest,
d: DiffractionGeometry,
s: SampleShortInfo | None):
if s is None:
pgroup = "p16371"
sample = None
else:
pgroup = s.user
sample = s.sample_name
grid_settings = jfjoch_client.GridScan(
n_fast= r.n_x,
snake=True,
step_x_um=r.grid_size_mm.x * 1000.0,
step_y_um=r.grid_size_mm.y * 1000.0,
vertical=False
)
dataset_settings = jfjoch_client.DatasetSettings(
beam_x_pxl=d.beam_center_pxl[0],
beam_y_pxl=d.beam_center_pxl[1],
ntrigger= r.n_y,
images_per_trigger=r.n_x,
detector_distance_mm=d.dtz_mm,
file_prefix=f"{pgroup}/raw/{r.file_prefix}",
incident_energy_keV=d.energy_keV,
grid_scan=grid_settings,
sample_name=sample,
image_time_us=round(r.exp_time_s * 1e6),
experiment_group=pgroup
)
self.__api.start_post(dataset_settings=dataset_settings)
def wait_till_done(self, timeout : int | float) -> jfjoch_client.models.ScanResult:
self.__api.wait_till_done_post_with_http_info(timeout=math.ceil(timeout))
return self.__api.result_scan_get()
def detector(self) -> jfjoch_client.models.DetectorListElement:
l = self.__api.config_select_detector_get()
if len(l.detectors) == 0:
raise Exception("no detectors configured")
return l.detectors[l.current_id]