diff --git a/debye_bec/devices/mo1_bragg/mo1_bragg.py b/debye_bec/devices/mo1_bragg/mo1_bragg.py index e6172db..18e41bb 100644 --- a/debye_bec/devices/mo1_bragg/mo1_bragg.py +++ b/debye_bec/devices/mo1_bragg/mo1_bragg.py @@ -81,7 +81,7 @@ class Mo1Bragg(PSIDeviceBase, Mo1BraggPositioner): The prefix to connect to the soft IOC is X01DA-OP-MO1:BRAGG: """ - USER_ACCESS = ["set_advanced_xas_settings"] + USER_ACCESS = ["set_advanced_xas_settings", "set_xtal"] def __init__(self, name: str, prefix: str = "", scan_info: ScanInfo | None = None, **kwargs): # type: ignore """ @@ -315,13 +315,8 @@ class Mo1Bragg(PSIDeviceBase, Mo1BraggPositioner): high (float): High energy/angle value of the scan scan_time (float): Time for a half oscillation """ - move_type = self.move_type.get() - if move_type == MoveType.ENERGY: - self.scan_settings.s_scan_energy_lo.put(low) - self.scan_settings.s_scan_energy_hi.put(high) - else: - self.scan_settings.s_scan_angle_lo.put(low) - self.scan_settings.s_scan_angle_hi.put(high) + self.scan_settings.s_scan_energy_lo.put(low) + self.scan_settings.s_scan_energy_hi.put(high) self.scan_settings.s_scan_scantime.put(scan_time) def wait_for_signal(self, signal: Cpt, value: Any, timeout: float | None = None) -> None: @@ -381,18 +376,10 @@ class Mo1Bragg(PSIDeviceBase, Mo1BraggPositioner): p_kink (float): Position of kink in % e_kink (float): Energy of kink in eV """ - # TODO Add fallback solution for automatic testing, otherwise test will fail - # because no monochromator will calculate the angle - # Unsure how to implement this - - move_type = self.move_type.get() - if move_type == MoveType.ENERGY: - e_kink_deg = self.convert_angle_energy(mode="EnergyToAngle", inp=e_kink) - # Angle and Energy are inverse proportional! - high_deg = self.convert_angle_energy(mode="EnergyToAngle", inp=low) - low_deg = self.convert_angle_energy(mode="EnergyToAngle", inp=high) - else: - raise Mo1BraggError("MoveType Angle not implemented for advanced scans, use Energy") + e_kink_deg = self.convert_angle_energy(mode="EnergyToAngle", inp=e_kink) + # Angle and Energy are inverse proportional! + high_deg = self.convert_angle_energy(mode="EnergyToAngle", inp=low) + low_deg = self.convert_angle_energy(mode="EnergyToAngle", inp=high) pos, vel, dt = compute_spline( low_deg=low_deg, diff --git a/debye_bec/devices/mo1_bragg/mo1_bragg_devices.py b/debye_bec/devices/mo1_bragg/mo1_bragg_devices.py index e7b8546..fada768 100644 --- a/debye_bec/devices/mo1_bragg/mo1_bragg_devices.py +++ b/debye_bec/devices/mo1_bragg/mo1_bragg_devices.py @@ -189,13 +189,13 @@ class Mo1BraggScanControl(Device): class Mo1BraggPositioner(Device, PositionerBase): """ - Positioner implementation of the MO1 Bragg positioner. + Positioner implementation with readback energy of the MO1 Bragg positioner. The prefix to connect to the soft IOC is X01DA-OP-MO1:BRAGG: This soft IOC connects to the NI motor and its control loop. """ - USER_ACCESS = ["set_advanced_xas_settings"] + USER_ACCESS = ["set_xtal"] ####### Sub-components ######## # Namespace is cleaner and easier to maintain @@ -207,10 +207,6 @@ class Mo1BraggPositioner(Device, PositionerBase): scan_control = Cpt(Mo1BraggScanControl, "") status = Cpt(Mo1BraggStatus, "") - ############# switch between energy and angle ############# - # TODO should be removed/replaced once decision about pseudo motor is made - move_type = Cpt(MoveTypeSignal, value=MoveType.ENERGY, kind="config") - ############# Energy PVs ############# readback = Cpt( @@ -226,22 +222,6 @@ class Mo1BraggPositioner(Device, PositionerBase): high_lim = Cpt(EpicsSignalRO, suffix="hi_lim_pos_energy_RBV", kind="config", auto_monitor=True) velocity = Cpt(EpicsSignalWithRBV, suffix="move_velocity", kind="config", auto_monitor=True) - ########### Angle PVs ############# - - # TODO Pseudo motor for angle? - feedback_pos_angle = Cpt( - EpicsSignalRO, suffix="feedback_pos_angle_RBV", kind="normal", auto_monitor=True - ) - setpoint_abs_angle = Cpt( - EpicsSignalWithRBV, suffix="set_abs_pos_angle", kind="normal", auto_monitor=True - ) - low_limit_angle = Cpt( - EpicsSignalRO, suffix="lo_lim_pos_angle_RBV", kind="config", auto_monitor=True - ) - high_limit_angle = Cpt( - EpicsSignalRO, suffix="hi_lim_pos_angle_RBV", kind="config", auto_monitor=True - ) - ########## Move Command PVs ########## move_abs = Cpt(EpicsSignal, suffix="move_abs", kind="config", put_complete=True) @@ -290,9 +270,7 @@ class Mo1BraggPositioner(Device, PositionerBase): @property def limits(self) -> tuple: """Return limits of the Bragg positioner""" - if self.move_type.get() == MoveType.ENERGY: - return (self.low_lim.get(), self.high_lim.get()) - return (self.low_limit_angle.get(), self.high_limit_angle.get()) + return (self.low_lim.get(), self.high_lim.get()) @property def low_limit(self) -> float: @@ -307,16 +285,12 @@ class Mo1BraggPositioner(Device, PositionerBase): @property def egu(self) -> str: """Return the engineering units of the positioner""" - if self.move_type.get() == MoveType.ENERGY: - return "eV" - return "deg" + return "eV" @property def position(self) -> float: """Return the current position of Mo1Bragg, considering the move type""" - move_type = self.move_type.get() - move_cpt = self.readback if move_type == MoveType.ENERGY else self.feedback_pos_angle - return move_cpt.get() + return self.readback.get() # pylint: disable=arguments-differ def check_value(self, value: float) -> None: @@ -332,7 +306,7 @@ class Mo1BraggPositioner(Device, PositionerBase): raise LimitError(f"position={value} not within limits {self.limits}") def _move_and_finish( - self, target_pos: float, move_cpt: Cpt, status: DeviceStatus, update_frequency: float = 0.1 + self, target_pos: float, status: DeviceStatus, update_frequency: float = 0.1 ) -> None: """ Method to be called in the move thread to move the Bragg positioner @@ -351,7 +325,7 @@ class Mo1BraggPositioner(Device, PositionerBase): """ try: # Set the target position on IOC - move_cpt.put(target_pos) + self.setpoint.put(target_pos) self.move_abs.put(1) # Currently sleep is needed due to delay in updates on PVs, maybe time can be reduced time.sleep(0.5) @@ -367,7 +341,7 @@ class Mo1BraggPositioner(Device, PositionerBase): logger.error(f"Error in move thread of device {self.name}: {content}") status.set_exception(exc=exc) - def move(self, value: float, move_type: str | MoveType = None, **kwargs) -> DeviceStatus: + def move(self, value: float, **kwargs) -> DeviceStatus: """ Move the Bragg positioner to the specified value, allows to switch between move types angle and energy. @@ -381,16 +355,12 @@ class Mo1BraggPositioner(Device, PositionerBase): DeviceStatus : status object to track the motion """ self._stopped = False - if move_type is not None: - self.move_type.put(move_type) - move_type = self.move_type.get() - move_cpt = self.setpoint if move_type == MoveType.ENERGY else self.setpoint_abs_angle self.check_value(value) status = DeviceStatus(device=self) self._move_thread = threading.Thread( - target=self._move_and_finish, args=(value, move_cpt, status, 0.1) + target=self._move_and_finish, args=(value, status, 0.1) ) self._move_thread.start() return status diff --git a/debye_bec/scans/mono_bragg_scans.py b/debye_bec/scans/mono_bragg_scans.py index 57ed477..e1ac5b6 100644 --- a/debye_bec/scans/mono_bragg_scans.py +++ b/debye_bec/scans/mono_bragg_scans.py @@ -72,11 +72,8 @@ class XASSimpleScan(AsyncFlyScanBase): yield None def pre_scan(self): - """Pre Scan action. Ensure the motor movetype is set to energy, then check - limits for start/end energy. - #TODO Remove once the motor movetype is removed and ANGLE motion is a pseudo motor. + """Pre Scan action. """ - yield from self.stubs.send_rpc_and_wait(self.motor, "move_type.set", "energy") self._check_limits() # Ensure parent class pre_scan actions to be called.