wip changes from the beamline
This commit is contained in:
@@ -156,7 +156,7 @@ class flomniGuiTools:
|
||||
)
|
||||
self.progressbar.set_value([progress, subtomo_progress, 0])
|
||||
if self.text_box is not None:
|
||||
text = f"Progress report:\n Tomo type: ....................... {self.progress['tomo_type']}\n Projection: ...................... {self.progress['projection']:.0f}\n Total projections expected ....... {self.progress['total_projections']}\n Angle: ........................... {self.progress['angle']}\n Current subtomo: ................. {self.progress['subtomo']}\n Current projection within subtomo: {self.progress['subtomo_projection']}\n Total projections per subtomo: ... {self.progress['subtomo_total_projections']}"
|
||||
text = f"Progress report:\n Tomo type: ....................... {self.progress['tomo_type']}\n Projection: ...................... {self.progress['projection']:.0f}\n Total projections expected ....... {self.progress['total_projections']}\n Angle: ........................... {self.progress['angle']}\n Current subtomo: ................. {self.progress['subtomo']}\n Current projection within subtomo: {self.progress['subtomo_projection']}\n Total projections per subtomo: ... {self.progress['subtomo_total_projections']}"
|
||||
self.text_box.set_plain_text(text)
|
||||
|
||||
|
||||
|
||||
@@ -365,6 +365,18 @@ rtz:
|
||||
readOnly: false
|
||||
readoutPriority: on_request
|
||||
|
||||
rt_flyer:
|
||||
description: flomni rt flyer
|
||||
deviceClass: csaxs_bec.devices.omny.rt.rt_flomni_ophyd.RtFlomniFlyer
|
||||
deviceConfig:
|
||||
host: mpc2844.psi.ch
|
||||
port: 2222
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: async
|
||||
|
||||
|
||||
############################################################
|
||||
####################### Cameras ############################
|
||||
############################################################
|
||||
|
||||
@@ -10,7 +10,7 @@ from ophyd import Component as Cpt
|
||||
from ophyd import Device, DeviceStatus, PositionerBase, Signal
|
||||
from ophyd.status import wait as status_wait
|
||||
from ophyd.utils import LimitError
|
||||
from ophyd_devices.utils.bec_signals import AsyncSignal
|
||||
from ophyd_devices.utils.bec_signals import AsyncMultiSignal, ProgressSignal
|
||||
from ophyd_devices.utils.controller import Controller, threadlocked
|
||||
from ophyd_devices.utils.socket import SocketIO, raise_if_disconnected
|
||||
from prettytable import PrettyTable
|
||||
@@ -741,7 +741,26 @@ class RtFlomniMotor(Device, PositionerBase):
|
||||
|
||||
class RtFlomniFlyer(Device):
|
||||
USER_ACCESS = ["controller"]
|
||||
data = Cpt(AsyncSignal, "data", ndim=1, async_update={"type": "add", "max_shape": [None]})
|
||||
data = Cpt(
|
||||
AsyncMultiSignal,
|
||||
name="data",
|
||||
signals=[
|
||||
"target_x",
|
||||
"average_x_st_fzp",
|
||||
"stdev_x_st_fzp",
|
||||
"target_y",
|
||||
"average_y_st_fzp",
|
||||
"stdev_y_st_fzp",
|
||||
"average_rotz",
|
||||
"stdev_rotz",
|
||||
"average_stdeviations_x_st_fzp",
|
||||
"average_stdeviations_y_st_fzp",
|
||||
],
|
||||
ndim=0,
|
||||
max_size=10000,
|
||||
async_update={"type": "add", "max_shape": [None]},
|
||||
)
|
||||
progress = Cpt(ProgressSignal, name="progress")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@@ -765,15 +784,11 @@ class RtFlomniFlyer(Device):
|
||||
read_attrs=read_attrs,
|
||||
configuration_attrs=configuration_attrs,
|
||||
parent=parent,
|
||||
host=host,
|
||||
port=port,
|
||||
socket_cls=socket_cls,
|
||||
device_manager=device_manager,
|
||||
**kwargs,
|
||||
)
|
||||
self.shutdown_event = threading.Event()
|
||||
self.controller = RtFlomniController(
|
||||
socket_cls=socket_cls, socket_host=host, socket_port=port
|
||||
socket_cls=socket_cls, socket_host=host, socket_port=port, device_manager=device_manager
|
||||
)
|
||||
self.average_stdeviations_x_st_fzp = 0
|
||||
self.average_stdeviations_y_st_fzp = 0
|
||||
@@ -805,11 +820,20 @@ class RtFlomniFlyer(Device):
|
||||
)
|
||||
if current_position_in_scan > 5:
|
||||
while current_position_in_scan > read_counter + 1:
|
||||
return_table = (self.socket_put_and_receive(f"r{read_counter}")).split(",")
|
||||
return_table = (
|
||||
self.controller.socket_put_and_receive(f"r{read_counter}")
|
||||
).split(",")
|
||||
logger.info(f"Read {read_counter} out of {number_of_positions_planned}")
|
||||
read_counter = read_counter + 1
|
||||
signals = self._get_signals_from_table(return_table)
|
||||
self.data.set(signals)
|
||||
self.progress.put(
|
||||
value=read_counter,
|
||||
max_value=number_of_positions_planned,
|
||||
done=(number_of_positions_planned == read_counter),
|
||||
)
|
||||
logger.info(f"Updating progress: {read_counter} / {number_of_positions_planned}")
|
||||
|
||||
|
||||
if self.shutdown_event.wait(0.05):
|
||||
logger.info("Shutdown event set, stopping readout.")
|
||||
@@ -819,57 +843,65 @@ class RtFlomniFlyer(Device):
|
||||
|
||||
# read the last samples even though scan is finished already
|
||||
while number_of_positions_planned > read_counter and not self.shutdown_event.is_set():
|
||||
return_table = (self.socket_put_and_receive(f"r{read_counter}")).split(",")
|
||||
return_table = (self.controller.socket_put_and_receive(f"r{read_counter}")).split(",")
|
||||
logger.info(f"Read {read_counter} out of {number_of_positions_planned}")
|
||||
read_counter = read_counter + 1
|
||||
|
||||
signals = self._get_signals_from_table(return_table)
|
||||
logger.info(f"Setting data: {signals}")
|
||||
self.data.set(signals)
|
||||
self.progress.put(
|
||||
value=read_counter,
|
||||
max_value=number_of_positions_planned,
|
||||
done=(number_of_positions_planned == read_counter),
|
||||
)
|
||||
logger.info(f"Updating progress: {read_counter} / {number_of_positions_planned}")
|
||||
|
||||
|
||||
# NOTE: No need to set the status to failed if the shutdown_event is set.
|
||||
# The stop() method will take care of that.
|
||||
status.set_finished()
|
||||
|
||||
logger.info(
|
||||
"Flomni statistics: Average of all standard deviations: x"
|
||||
f" {self.average_stdeviations_x_st_fzp/read_counter*1000:.1f}, y"
|
||||
f" {self.average_stdeviations_y_st_fzp/read_counter*1000:.1f}"
|
||||
)
|
||||
if read_counter != 0:
|
||||
logger.info(
|
||||
"Flomni statistics: Average of all standard deviations: x"
|
||||
f" {self.average_stdeviations_x_st_fzp/read_counter*1000:.1f}, y"
|
||||
f" {self.average_stdeviations_y_st_fzp/read_counter*1000:.1f}"
|
||||
)
|
||||
|
||||
|
||||
def _get_signals_from_table(self, return_table) -> dict:
|
||||
self.average_stdeviations_x_st_fzp += float(return_table[4])
|
||||
self.average_stdeviations_y_st_fzp += float(return_table[7])
|
||||
signals = {
|
||||
"target_x": {"value": float(return_table[2])},
|
||||
"average_x_st_fzp": {"value": float(return_table[3])},
|
||||
"stdev_x_st_fzp": {"value": float(return_table[4])},
|
||||
"target_y": {"value": float(return_table[5])},
|
||||
"average_y_st_fzp": {"value": float(return_table[6])},
|
||||
"stdev_y_st_fzp": {"value": float(return_table[7])},
|
||||
"average_rotz": {"value": float(return_table[8])},
|
||||
"stdev_rotz": {"value": float(return_table[9])},
|
||||
"average_stdeviations_x_st_fzp": {
|
||||
f"{self.name}_data_target_x": {"value": float(return_table[2])},
|
||||
f"{self.name}_data_average_x_st_fzp": {"value": float(return_table[3])},
|
||||
f"{self.name}_data_stdev_x_st_fzp": {"value": float(return_table[4])},
|
||||
f"{self.name}_data_target_y": {"value": float(return_table[5])},
|
||||
f"{self.name}_data_average_y_st_fzp": {"value": float(return_table[6])},
|
||||
f"{self.name}_data_stdev_y_st_fzp": {"value": float(return_table[7])},
|
||||
f"{self.name}_data_average_rotz": {"value": float(return_table[8])},
|
||||
f"{self.name}_data_stdev_rotz": {"value": float(return_table[9])},
|
||||
f"{self.name}_data_average_stdeviations_x_st_fzp": {
|
||||
"value": self.average_stdeviations_x_st_fzp / (int(return_table[0]) + 1)
|
||||
},
|
||||
"average_stdeviations_y_st_fzp": {
|
||||
f"{self.name}_data_average_stdeviations_y_st_fzp": {
|
||||
"value": self.average_stdeviations_y_st_fzp / (int(return_table[0]) + 1)
|
||||
},
|
||||
}
|
||||
return signals
|
||||
|
||||
def start_readout(self, status: DeviceStatus):
|
||||
logger.info("Starting readout thread.")
|
||||
readout = threading.Thread(target=self.read_positions_from_sampler, args=(status,))
|
||||
readout.start()
|
||||
|
||||
def kickoff(self):
|
||||
def kickoff(self) -> DeviceStatus:
|
||||
self.shutdown_event.clear()
|
||||
while not self._min_scan_buffer_reached and not self.shutdown_event.wait(0.001):
|
||||
while not self.controller._min_scan_buffer_reached and not self.shutdown_event.wait(0.001):
|
||||
...
|
||||
self.start_scan()
|
||||
self.controller.start_scan()
|
||||
self.shutdown_event.wait(0.1)
|
||||
|
||||
def complete(self) -> DeviceStatus:
|
||||
"""Wait until the flyer is done."""
|
||||
status = DeviceStatus(self)
|
||||
self.start_readout(status)
|
||||
return status
|
||||
|
||||
@@ -26,12 +26,12 @@ import numpy as np
|
||||
from bec_lib import bec_logger, messages
|
||||
from bec_lib.endpoints import MessageEndpoints
|
||||
from bec_server.scan_server.errors import ScanAbortion
|
||||
from bec_server.scan_server.scans import SyncFlyScanBase
|
||||
from bec_server.scan_server.scans import AsyncFlyScanBase
|
||||
|
||||
logger = bec_logger.logger
|
||||
|
||||
|
||||
class FlomniFermatScan(SyncFlyScanBase):
|
||||
class FlomniFermatScan(AsyncFlyScanBase):
|
||||
scan_name = "flomni_fermat_scan"
|
||||
scan_type = "fly"
|
||||
required_kwargs = ["fovx", "fovy", "exp_time", "step", "angle"]
|
||||
@@ -97,6 +97,7 @@ class FlomniFermatScan(SyncFlyScanBase):
|
||||
logger.warning("The zshift is smaller than -100 um. It will be limited to -100 um.")
|
||||
self.zshift = -100
|
||||
self.flomni_rotation_status = None
|
||||
self.flyer_num_pos = 0
|
||||
|
||||
def initialize(self):
|
||||
self.scan_motors = []
|
||||
@@ -107,10 +108,6 @@ class FlomniFermatScan(SyncFlyScanBase):
|
||||
self.positions, corridor_size=self.optim_trajectory_corridor
|
||||
)
|
||||
|
||||
@property
|
||||
def monitor_sync(self):
|
||||
return "rt_flomni"
|
||||
|
||||
def reverse_trajectory(self):
|
||||
"""
|
||||
Reverse the trajectory. Every other scan should be reversed to
|
||||
@@ -135,13 +132,13 @@ class FlomniFermatScan(SyncFlyScanBase):
|
||||
if flip_axes:
|
||||
self.positions = np.flipud(self.positions)
|
||||
|
||||
self.num_pos = len(self.positions)
|
||||
self.flyer_num_pos = len(self.positions)
|
||||
self._check_min_positions()
|
||||
|
||||
def _check_min_positions(self):
|
||||
if self.num_pos < 20:
|
||||
if self.flyer_num_pos < 20:
|
||||
raise ScanAbortion(
|
||||
f"The number of positions must exceed 20. Currently: {self.num_pos}."
|
||||
f"The number of positions must exceed 20. Currently: {self.flyer_num_pos}."
|
||||
)
|
||||
|
||||
def _prepare_setup(self):
|
||||
@@ -150,6 +147,8 @@ class FlomniFermatScan(SyncFlyScanBase):
|
||||
|
||||
yield from self.stubs.send_rpc_and_wait("rty", "set", self.positions[0][1])
|
||||
|
||||
yield from self.stubs.scan_report_instruction({"device_progress": ["rt_flyer"]})
|
||||
|
||||
def _prepare_setup_part2(self):
|
||||
if self.flomni_rotation_status:
|
||||
self.flomni_rotation_status.wait()
|
||||
@@ -280,12 +279,13 @@ class FlomniFermatScan(SyncFlyScanBase):
|
||||
return np.array(positions)
|
||||
|
||||
def scan_core(self):
|
||||
yield from self.stubs.kickoff(device="rt_flyer")
|
||||
status = yield from self.stubs.complete(device="rt_flyer", wait=False)
|
||||
status = yield from self.stubs.kickoff(device="rt_flyer", wait=False)
|
||||
while not status.done:
|
||||
yield from self.stubs.read(group="monitored")
|
||||
yield from self.stubs.read(group="monitored", point_id=self.point_id)
|
||||
time.sleep(1)
|
||||
self.point_id += 1
|
||||
logger.debug("reading monitors")
|
||||
self.num_pos = self.point_id
|
||||
|
||||
def move_to_start(self):
|
||||
"""return to the start position"""
|
||||
|
||||
Reference in New Issue
Block a user