Small updates from the SAXS beamtime #264
@@ -270,10 +270,10 @@ class ROIMappingBox(QGroupBox):
|
||||
layout.setColumnStretch(2, 1)
|
||||
|
||||
# An unknown calibration must not silently become a one-motor-unit-per-pixel scan.
|
||||
self.camera_scale_pixel_x = spinbox(value=0.0, single_step=0.1, parent=self)
|
||||
self.camera_scale_pixel_x = spinbox(value=0.0, single_step=0.1, decimals=6, parent=self)
|
||||
self.offset_cam_xray_x = spinbox(value=0.0, single_step=0.1, parent=self)
|
||||
self.direction_x = direction_combo(self)
|
||||
self.camera_scale_pixel_y = spinbox(value=0.0, single_step=0.1, parent=self)
|
||||
self.camera_scale_pixel_y = spinbox(value=0.0, single_step=0.1, decimals=6, parent=self)
|
||||
self.offset_cam_xray_y = spinbox(value=0.0, single_step=0.1, parent=self)
|
||||
self.direction_y = direction_combo(self)
|
||||
self.mapping_lock_toggle = ToggleSwitch(self, checked=False)
|
||||
|
||||
@@ -13,6 +13,7 @@ from typing import Any, Literal
|
||||
from uuid import uuid4
|
||||
|
||||
from bec_lib import bec_logger
|
||||
from bec_lib.endpoints import MessageEndpoints
|
||||
from bec_lib.messages import VariableMessage
|
||||
from bec_qthemes import material_icon
|
||||
from bec_widgets.utils.bec_widget import BECWidget
|
||||
@@ -115,6 +116,11 @@ class SAXSWidget(BECWidget, QWidget):
|
||||
self._sync_mapping_reference_to_display()
|
||||
self._refresh_crosshair_pin_if_enabled()
|
||||
|
||||
# Connect to ScanStatusUpdates
|
||||
self.bec_dispatcher.connect_slot(
|
||||
slot=self._deactivate_toggle_live_mode, topics = MessageEndpoints.scan_status()
|
||||
)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# UI construction
|
||||
# ------------------------------------------------------------------
|
||||
@@ -229,6 +235,7 @@ class SAXSWidget(BECWidget, QWidget):
|
||||
"step_size",
|
||||
"readback",
|
||||
"device_box",
|
||||
"setpoint",
|
||||
}:
|
||||
widget.hide()
|
||||
|
||||
@@ -283,8 +290,22 @@ class SAXSWidget(BECWidget, QWidget):
|
||||
self._clear_reference_crosshair_pin()
|
||||
# self.image.toggle_crosshair(False)
|
||||
|
||||
@SafeSlot(dict,dict)
|
||||
def _deactivate_toggle_live_mode(self, content, _metadata) -> None:
|
||||
status = content.get("status", "")
|
||||
if status == "open":
|
||||
enabled = False
|
||||
else:
|
||||
enabled = True
|
||||
toggle_cam_action = self.image.toolbar.components.get_action("toggle_cam")
|
||||
if toggle_cam_action is not None:
|
||||
toggle_cam_action.action.setEnabled(enabled)
|
||||
|
||||
def _toggle_camera_live_mode(self, enabled: bool) -> None:
|
||||
# If enabled, set the camera to live mode, if disabled, stop the live mode.
|
||||
dev_manager = self.bec_dispatcher.client.device_manager
|
||||
if dev_manager.scan_info.msg is not None and dev_manager.scan_info.msg.status in ["open"]:
|
||||
return # Ignore commands if scan is running
|
||||
device_name = getattr(self.image, "device", "")
|
||||
if device_name and device_name in self.dev:
|
||||
device = self.dev[device_name]
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
eiger_1_5:
|
||||
description: Eiger 1.5M in-vacuum detector
|
||||
deviceClass: csaxs_bec.devices.jungfraujoch.eiger_1_5m.Eiger1_5M
|
||||
deviceConfig:
|
||||
detector_distance: 2150
|
||||
beam_center: [860, 1219]
|
||||
onFailure: raise
|
||||
enabled: True
|
||||
readoutPriority: async
|
||||
softwareTrigger: False
|
||||
|
||||
# eiger_9:
|
||||
# description: Eiger 9M detector
|
||||
# deviceClass: csaxs_bec.devices.jungfraujoch.eiger_9m.Eiger9M
|
||||
# eiger_1_5:
|
||||
# description: Eiger 1.5M in-vacuum detector
|
||||
# deviceClass: csaxs_bec.devices.jungfraujoch.eiger_1_5m.Eiger1_5M
|
||||
# deviceConfig:
|
||||
# detector_distance: 2200
|
||||
# beam_center: [870, 1203]
|
||||
# detector_distance: 2150
|
||||
# beam_center: [860, 1219]
|
||||
# onFailure: raise
|
||||
# enabled: True
|
||||
# readoutPriority: async
|
||||
# softwareTrigger: False
|
||||
|
||||
eiger_9:
|
||||
description: Eiger 9M detector
|
||||
deviceClass: csaxs_bec.devices.jungfraujoch.eiger_9m.Eiger9M
|
||||
deviceConfig:
|
||||
detector_distance: 6975.225
|
||||
beam_center: [1149.71, 1450.89]
|
||||
onFailure: raise
|
||||
enabled: True
|
||||
readoutPriority: async
|
||||
softwareTrigger: False
|
||||
|
||||
# ids_cam:
|
||||
# description: IDS camera for live image acquisition
|
||||
# deviceClass: csaxs_bec.devices.ids_cameras.IDSCamera
|
||||
|
||||
@@ -16,11 +16,17 @@ endstation:
|
||||
detectors:
|
||||
- !include ./bl_detectors.yaml
|
||||
|
||||
xeye:
|
||||
- !include ./xeye.yaml
|
||||
|
||||
ssaxs:
|
||||
- !include ./ssaxs.yaml
|
||||
|
||||
#sastt:
|
||||
# - !include ./sastt.yaml
|
||||
|
||||
flomni:
|
||||
- !include ./ptycho_flomni.yaml
|
||||
# flomni:
|
||||
# - !include ./ptycho_flomni.yaml
|
||||
|
||||
#omny:
|
||||
# - !include ./ptycho_omny.yaml
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
samx:
|
||||
description: Owis motor stage samx
|
||||
deviceClass: ophyd_devices.devices.psi_motor.EpicsUserMotorVME
|
||||
deviceConfig:
|
||||
prefix: X12SA-ES2-ES01
|
||||
motor_resolution: 0.00125
|
||||
base_velocity: 0.0625
|
||||
velocity: 10
|
||||
backlash_distance: 0.125
|
||||
acceleration: 0.2
|
||||
user_offset_dir: 0
|
||||
deviceTags:
|
||||
- cSAXS
|
||||
- owis_samx
|
||||
onFailure: buffer
|
||||
enabled: true
|
||||
readoutPriority: baseline
|
||||
softwareTrigger: false
|
||||
|
||||
|
||||
samy:
|
||||
description: Owis motor stage samy
|
||||
deviceClass: ophyd_devices.devices.psi_motor.EpicsUserMotorVME
|
||||
deviceConfig:
|
||||
prefix: X12SA-ES2-ES02
|
||||
motor_resolution: 0.00125
|
||||
base_velocity: 0.0625
|
||||
velocity: 10
|
||||
backlash_distance: 0.125
|
||||
acceleration: 0.2
|
||||
user_offset_dir: 0
|
||||
deviceTags:
|
||||
- cSAXS
|
||||
- owis_samy
|
||||
onFailure: buffer
|
||||
enabled: true
|
||||
readoutPriority: baseline
|
||||
softwareTrigger: false
|
||||
|
||||
|
||||
micz:
|
||||
description: Owis motor stage micz
|
||||
deviceClass: ophyd_devices.devices.psi_motor.EpicsUserMotorVME
|
||||
deviceConfig:
|
||||
prefix: X12SA-ES2-ES03
|
||||
motor_resolution: 0.000125
|
||||
base_velocity: 0.00625
|
||||
velocity: 1
|
||||
backlash_distance: 0.0125
|
||||
acceleration: 0.2
|
||||
user_offset_dir: 0
|
||||
deviceTags:
|
||||
- cSAXS
|
||||
- owis_micz
|
||||
onFailure: buffer
|
||||
enabled: true
|
||||
readoutPriority: baseline
|
||||
softwareTrigger: false
|
||||
|
||||
cam_sample:
|
||||
description: Camera sample
|
||||
deviceClass: csaxs_bec.devices.ids_cameras.ids_camera.IDSCamera
|
||||
deviceConfig:
|
||||
camera_id: 5
|
||||
bits_per_pixel: 24
|
||||
num_rotation_90: 3
|
||||
transpose: false
|
||||
force_monochrome: false
|
||||
m_n_colormode: 1
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: async
|
||||
# userParameter:
|
||||
# pixel_calibration: 0.00044247787610619477 # mm/pixel (= 0.05 / 113)
|
||||
@@ -0,0 +1,56 @@
|
||||
eyex:
|
||||
description: Owis motor stage eyex
|
||||
deviceClass: ophyd_devices.devices.psi_motor.EpicsUserMotorVME
|
||||
deviceConfig:
|
||||
prefix: X12SA-ES2-ES04
|
||||
motor_resolution: 0.00125
|
||||
base_velocity: 0.0625
|
||||
velocity: 1
|
||||
backlash_distance: 0.125
|
||||
acceleration: 0.2
|
||||
user_offset_dir: 0
|
||||
deviceTags:
|
||||
- cSAXS
|
||||
- owis_eyex
|
||||
onFailure: buffer
|
||||
enabled: true
|
||||
readoutPriority: baseline
|
||||
softwareTrigger: false
|
||||
|
||||
|
||||
eyey:
|
||||
description: Owis motor stage eyey
|
||||
deviceClass: ophyd_devices.devices.psi_motor.EpicsUserMotorVME
|
||||
deviceConfig:
|
||||
prefix: X12SA-ES2-ES05
|
||||
motor_resolution: 0.00125
|
||||
base_velocity: 0.0625
|
||||
velocity: 1
|
||||
backlash_distance: 0.125
|
||||
acceleration: 0.2
|
||||
user_offset_dir: 0
|
||||
deviceTags:
|
||||
- cSAXS
|
||||
- owis_eyey
|
||||
onFailure: buffer
|
||||
enabled: true
|
||||
readoutPriority: baseline
|
||||
softwareTrigger: false
|
||||
|
||||
|
||||
cam_xeye:
|
||||
description: Camera Xray eye ID1
|
||||
deviceClass: csaxs_bec.devices.ids_cameras.ids_camera.IDSCamera
|
||||
deviceConfig:
|
||||
camera_id: 1
|
||||
bits_per_pixel: 24
|
||||
num_rotation_90: 2
|
||||
transpose: true
|
||||
force_monochrome: true
|
||||
m_n_colormode: 1
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: async
|
||||
# userParameter:
|
||||
# pixel_calibration: 0.00044247787610619477 # mm/pixel (= 0.05 / 113)
|
||||
@@ -41,6 +41,7 @@ import yaml
|
||||
from bec_lib.file_utils import get_full_path
|
||||
from bec_lib.logger import bec_logger
|
||||
from bec_server.scan_server.scans.scan_base import ScanInfo as ScanServerScanInfo
|
||||
from jfjoch_client.models.azim_int_settings import AzimIntSettings
|
||||
from jfjoch_client.models.dataset_settings import DatasetSettings
|
||||
from jfjoch_client.models.detector_settings import DetectorSettings
|
||||
from jfjoch_client.models.detector_state import DetectorState
|
||||
@@ -85,7 +86,13 @@ class Eiger(PSIDeviceBase):
|
||||
**kwargs: Additional keyword arguments.
|
||||
"""
|
||||
|
||||
USER_ACCESS = ["set_detector_distance", "set_beam_center"]
|
||||
USER_ACCESS = [
|
||||
"set_detector_distance",
|
||||
"set_beam_center",
|
||||
"print_detector_distance_and_center",
|
||||
"set_azi_settings",
|
||||
"get_azi_settings",
|
||||
]
|
||||
|
||||
file_event = Cpt(FileEventSignal, name="file_event")
|
||||
preview_image = Cpt(PreviewSignal, name="preview_image", ndim=2)
|
||||
@@ -160,6 +167,45 @@ class Eiger(PSIDeviceBase):
|
||||
"""
|
||||
self.detector_distance = distance
|
||||
|
||||
def print_detector_distance_and_center(self):
|
||||
print(f"Detector Distance : {self.detector_distance}")
|
||||
print(f"Beam cetner position (x,y) : {self.beam_center}")
|
||||
|
||||
def get_azi_settings(self):
|
||||
return self.jfj_client.api.config_azim_int_get(_request_timeout=5).model_dump()
|
||||
|
||||
def set_azi_settings(
|
||||
self,
|
||||
pol_cor: bool,
|
||||
solid_angle_corr: bool,
|
||||
high_q_recip_a: float,
|
||||
low_q_recip_a: float,
|
||||
q_spacing: float,
|
||||
azimuthal_bins: int = 16,
|
||||
force_cpu: bool = True,
|
||||
) -> None:
|
||||
"""
|
||||
Set the azimuthal integration settings.
|
||||
|
||||
Args:
|
||||
pol_cor (bool): Apply polarization correction for azimuthal integration.
|
||||
solid_angle_corr (bool): Apply solid angle correction for azimuthal integration.
|
||||
high_q_recip_a (float): High q value in reciprocal angstroms.
|
||||
low_q_recip_a (float): Low q value in reciprocal angstroms.
|
||||
q_spacing (float): Q spacing.
|
||||
azimuthal_bins (int): Number of azimuthal (phi) bins; 1 = standard 1D azimuthal integration.
|
||||
"""
|
||||
model = AzimIntSettings(
|
||||
polarization_corr=pol_cor,
|
||||
solid_angle_corr=solid_angle_corr,
|
||||
high_q_recip_a=high_q_recip_a,
|
||||
low_q_recip_a=low_q_recip_a,
|
||||
q_spacing=q_spacing,
|
||||
azimuthal_bins=azimuthal_bins,
|
||||
force_cpu=force_cpu,
|
||||
)
|
||||
self.jfj_client.api.config_azim_int_put(azim_int_settings=model, _request_timeout=5)
|
||||
|
||||
# pylint: disable=missing-function-docstring
|
||||
@property
|
||||
def beam_center(self) -> tuple[float, float]:
|
||||
@@ -273,6 +319,9 @@ class Eiger(PSIDeviceBase):
|
||||
logger.info(f"Device {self.name} on_stage called.")
|
||||
start_time = time.time()
|
||||
self.scan_parameters = fetch_scan_info(self.scan_info)
|
||||
if self.jfj_client.detector_state != DetectorState.IDLE:
|
||||
self.jfj_client.stop(request_timeout=0.5)
|
||||
self.jfj_client.wait_for_idle(timeout=5)
|
||||
|
||||
# TODO Reactivate
|
||||
try:
|
||||
@@ -323,8 +372,8 @@ class Eiger(PSIDeviceBase):
|
||||
image_time_us=int(exp_time * 1e6),
|
||||
ntrigger=self._num_triggers,
|
||||
file_prefix=path,
|
||||
beam_x_pxl=int(self._beam_center[0]),
|
||||
beam_y_pxl=int(self._beam_center[1]),
|
||||
beam_x_pxl=float(self._beam_center[0]),
|
||||
beam_y_pxl=float(self._beam_center[1]),
|
||||
detector_distance_mm=self.detector_distance,
|
||||
incident_energy_ke_v=self._incident_energy,
|
||||
)
|
||||
|
||||
@@ -398,8 +398,13 @@ def test_eiger_on_stage(eiger_1_5m):
|
||||
with (
|
||||
mock.patch.object(eiger.jfj_client, "wait_for_idle", return_value=True),
|
||||
mock.patch.object(eiger.jfj_client, "start") as mock_start,
|
||||
mock.patch.object(eiger.jfj_client, "stop") as mock_stop,
|
||||
mock.patch.object(
|
||||
eiger.jfj_client.api, "status_get", return_value=BrokerStatus(state="Idle")
|
||||
),
|
||||
):
|
||||
eiger.stage()
|
||||
mock_stop.assert_not_called()
|
||||
assert (
|
||||
eiger._full_path
|
||||
== f"{scan_msg.info['file_components'][0]}_{eiger.name}_master.{scan_msg.info['file_components'][1]}"
|
||||
|
||||
Reference in New Issue
Block a user